[
  {
    "path": ".allstar/binary_artifacts.yaml",
    "content": "# Ignore reason: Packed extension for demo purposes.\nignorePaths:\n  - _archive/mv2/api/permissions/extension-questions.crx\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n---\n\n⚠️ If you have general Chrome Extensions questions, consider posting to the [Chromium Extensions Group](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-extensions) or [Stack Overflow](https://stackoverflow.com/questions/tagged/google-chrome-extension).\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior, or file the issue is found in:\n\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Notes**\nAnything additional here. 🌈\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n  - package-ecosystem: \"npm\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n"
  },
  {
    "path": ".github/workflows/lint.yml",
    "content": "name: CI\non: [push, pull_request]\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v4\n    - name: Install modules\n      run: npm ci\n    - name: Run ESLint\n      run: npm run lint \n"
  },
  {
    "path": ".github/workflows/sample-list-generator.yml",
    "content": "name: Sample List Generator\non:\n  push:\n    branches:\n      - main\n\ndefaults:\n  run:\n    working-directory: ./.repo/sample-list-generator\n\njobs:\n  generate:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 18\n\n      - name: Install dependencies\n        run: npm install\n\n      - name: Generate sample list\n        run: npm run start\n\n      - name: Upload to artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: extension-samples.json\n          path: ./.repo/sample-list-generator/extension-samples.json\n          if-no-files-found: error\n"
  },
  {
    "path": ".gitignore",
    "content": "*~\n*.DS_store\nnode_modules\n# Temporary directory for debugging extension samples\n_debug\n_metadata\ndist\n**/*.swp \n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "npx lint-staged\n"
  },
  {
    "path": ".prettierignore",
    "content": "_archive\nthird-party\nnode_modules\ndist\n"
  },
  {
    "path": ".prettierrc.json",
    "content": "{\n  \"printWidth\": 80,\n  \"tabWidth\": 2,\n  \"semi\": true,\n  \"singleQuote\": true,\n  \"trailingComma\": \"none\",\n  \"bracketSpacing\": true,\n  \"arrowParens\": \"always\"\n}\n"
  },
  {
    "path": ".repo/migrate-samples.js",
    "content": "// Copyright 2020 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview Intended to be run as a script on the old samples page, to\n * extract a list of samples and render as a Markdown table.\n */\n\nvar sampleHeadings = Array.from(document.querySelectorAll('main h2'));\n\nvar samples = sampleHeadings2.map((heading) => {\n  const title = heading.textContent;\n\n  const link = heading.querySelector('a');\n  const href = link.href;\n\n  const expectedHrefPrefix = 'https://developer.chrome.com/extensions/examples/'\n  let id = '';\n  if (href.startsWith(expectedHrefPrefix)) {\n    id = href.substr(expectedHrefPrefix.length).replace(/\\.zip$/, '');\n  } else {\n    console.warn('bad href', href);\n  }\n\n  let notes = '';\n\n  // probably a TEXT node\n  let curr = heading;\n  for (;;) {\n    curr = curr.nextSibling;\n    if (!(curr instanceof Text)) {\n      break;\n    }\n    notes += curr.textContent;\n  }\n\n  notes = notes.trim();\n  notes = notes.replace(/\\s+/g, ' ');\n\n  // curr probably points to Calls: now\n\n  const callNodes = Array.from(curr.querySelectorAll('ul li code'));\n  const calls = callNodes.map((node) => node.textContent);\n\n  return {title, id, notes, calls};\n});\n\nvar formatCallsList = (calls) => {\n  const parts = calls.map((call) => `<li>${call}</li>`);\n  return `<ul>${parts.join('')}</ul>`;\n};\n\nvar formatRow = (sample) => {\n  return `[${sample.title}](${sample.id})<br />${sample.notes} | ${formatCallsList(sample.calls)}`;\n};\n\nvar formatTable = (all) => {\n  return `Sample | Calls\\n--- | ---\\n${all.map(formatRow).join('\\n')}`;\n};"
  },
  {
    "path": ".repo/sample-list-generator/.gitignore",
    "content": "extension-samples.json\n"
  },
  {
    "path": ".repo/sample-list-generator/README.md",
    "content": "# Sample List Generator\n\n## Overview\n\nIt's a script that generates `./extension-samples.json` with the list of all the samples available. Currently, this JSON will be provided to [developer.chrome.com](https://developer.chrome.com) for generating a list page containing all the samples. This allows developers to quickly find the sample they want to reference.\n\n## How to use\n\n### Install dependencies\n\n```bash\nnpm install\n```\n\n### Run prefetch script (optional)\n\nThe prefetch script will generate a list of all the available extension apis on [developer.chrome.com](https://developer.chrome.com/docs/extensions/reference) and save it to `./extension-apis.json`.\n\nThe file `./extension-apis.json` will be committed so you don't need to run this script unless you want to update the list.\n\n```bash\nnpm run prepare-chrome-types\n```\n\n### Run the generator\n\n```bash\nnpm start\n```\n\n### Run the tests\n\n```bash\nnpm test\n```\n\n## Types\n\n```ts\ntype ApiTypeResult = 'event' | 'method' | 'property' | 'type' | 'unknown';\n\ninterface ApiItem {\n  type: ApiTypeResult;\n  namespace: string;\n  propertyName: string;\n}\n\ninterface SampleItem {\n  type: 'API_SAMPLE' | 'FUNCTIONAL_SAMPLE';\n  name: string;\n  title: string;\n  description: string;\n  repo_link: string;\n  apis: ApiItem[];\n  permissions: string[];\n}\n\n// the type of extension-samples.json file is SampleItem[]\n```\n\n## Example\n\nHere is an example of the generated `extension-samples.json` file:\n\n```json\n[\n  {\n    \"type\": \"API_SAMPLE\",\n    \"name\": \"alarms\",\n    \"title\": \"Alarms API Demo\",\n    \"description\": \"\",\n    \"repo_link\": \"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/api-samples/alarms\",\n    \"permissions\": [\"alarms\"],\n    \"apis\": [\n      {\n        \"type\": \"event\",\n        \"namespace\": \"runtime\",\n        \"propertyName\": \"onInstalled\"\n      },\n      {\n        \"type\": \"event\",\n        \"namespace\": \"action\",\n        \"propertyName\": \"onClicked\"\n      },\n      {\n        \"type\": \"event\",\n        \"namespace\": \"alarms\",\n        \"propertyName\": \"onAlarm\"\n      },\n      {\n        \"type\": \"type\",\n        \"namespace\": \"runtime\",\n        \"propertyName\": \"OnInstalledReason\"\n      },\n      {\n        \"type\": \"method\",\n        \"namespace\": \"alarms\",\n        \"propertyName\": \"create\"\n      },\n      {\n        \"type\": \"method\",\n        \"namespace\": \"tabs\",\n        \"propertyName\": \"create\"\n      },\n      {\n        \"type\": \"method\",\n        \"namespace\": \"alarms\",\n        \"propertyName\": \"clear\"\n      },\n      {\n        \"type\": \"method\",\n        \"namespace\": \"alarms\",\n        \"propertyName\": \"clearAll\"\n      },\n      {\n        \"type\": \"method\",\n        \"namespace\": \"alarms\",\n        \"propertyName\": \"getAll\"\n      }\n    ]\n  },\n  {\n    \"type\": \"FUNCTIONAL_SAMPLE\",\n    \"name\": \"tutorial.getting-started\",\n    \"title\": \"Getting Started Example\",\n    \"description\": \"Build an Extension!\",\n    \"repo_link\": \"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/functional-samples/tutorial.getting-started\",\n    \"permissions\": [\"storage\", \"activeTab\", \"scripting\"],\n    \"apis\": [\n      {\n        \"type\": \"event\",\n        \"namespace\": \"runtime\",\n        \"propertyName\": \"onInstalled\"\n      },\n      {\n        \"type\": \"property\",\n        \"namespace\": \"storage\",\n        \"propertyName\": \"sync\"\n      },\n      {\n        \"type\": \"method\",\n        \"namespace\": \"tabs\",\n        \"propertyName\": \"query\"\n      },\n      {\n        \"type\": \"method\",\n        \"namespace\": \"scripting\",\n        \"propertyName\": \"executeScript\"\n      }\n    ]\n  }\n]\n```\n"
  },
  {
    "path": ".repo/sample-list-generator/extension-apis.json",
    "content": "{\n  \"_comment\": \"This file is autogenerated by running `npm run prepare-chrome-types`, do not edit.\",\n  \"accessibilityFeatures\": {\n    \"properties\": [\n      \"animationPolicy\",\n      \"autoclick\",\n      \"caretHighlight\",\n      \"cursorColor\",\n      \"cursorHighlight\",\n      \"dictation\",\n      \"dockedMagnifier\",\n      \"focusHighlight\",\n      \"highContrast\",\n      \"largeCursor\",\n      \"screenMagnifier\",\n      \"selectToSpeak\",\n      \"spokenFeedback\",\n      \"stickyKeys\",\n      \"switchAccess\",\n      \"virtualKeyboard\"\n    ],\n    \"methods\": [],\n    \"types\": [],\n    \"events\": []\n  },\n  \"action\": {\n    \"properties\": [],\n    \"methods\": [\n      \"disable\",\n      \"enable\",\n      \"getBadgeBackgroundColor\",\n      \"getBadgeText\",\n      \"getBadgeTextColor\",\n      \"getPopup\",\n      \"getTitle\",\n      \"getUserSettings\",\n      \"isEnabled\",\n      \"openPopup\",\n      \"setBadgeBackgroundColor\",\n      \"setBadgeText\",\n      \"setBadgeTextColor\",\n      \"setIcon\",\n      \"setPopup\",\n      \"setTitle\"\n    ],\n    \"types\": [\n      \"OpenPopupOptions\",\n      \"TabDetails\",\n      \"UserSettings\",\n      \"UserSettingsChange\"\n    ],\n    \"events\": [\"onClicked\", \"onUserSettingsChanged\"]\n  },\n  \"alarms\": {\n    \"properties\": [],\n    \"methods\": [\"clear\", \"clearAll\", \"create\", \"get\", \"getAll\"],\n    \"types\": [\"Alarm\", \"AlarmCreateInfo\"],\n    \"events\": [\"onAlarm\"]\n  },\n  \"app.runtime\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\"EmbedRequest\", \"LaunchData\", \"LaunchItem\", \"LaunchSource\"],\n    \"events\": [\"onEmbedRequested\", \"onLaunched\", \"onRestarted\"]\n  },\n  \"app.window\": {\n    \"properties\": [],\n    \"methods\": [\n      \"canSetVisibleOnAllWorkspaces\",\n      \"create\",\n      \"current\",\n      \"get\",\n      \"getAll\"\n    ],\n    \"types\": [\n      \"AppWindow\",\n      \"Bounds\",\n      \"BoundsSpecification\",\n      \"ContentBounds\",\n      \"CreateWindowOptions\",\n      \"FrameOptions\",\n      \"State\",\n      \"WindowType\"\n    ],\n    \"events\": [\n      \"onBoundsChanged\",\n      \"onClosed\",\n      \"onFullscreened\",\n      \"onMaximized\",\n      \"onMinimized\",\n      \"onRestored\"\n    ]\n  },\n  \"app\": {\n    \"properties\": [],\n    \"methods\": [\"getDetails\", \"getIsInstalled\", \"installState\", \"runningState\"],\n    \"types\": [\"DOMWindow\", \"Details\", \"InstallState\", \"RunningState\"],\n    \"events\": []\n  },\n  \"appviewTag\": {\n    \"properties\": [],\n    \"methods\": [\"connect\"],\n    \"types\": [\"EmbedRequest\"],\n    \"events\": []\n  },\n  \"audio\": {\n    \"properties\": [],\n    \"methods\": [\n      \"getDevices\",\n      \"getMute\",\n      \"setActiveDevices\",\n      \"setMute\",\n      \"setProperties\"\n    ],\n    \"types\": [\n      \"AudioDeviceInfo\",\n      \"DeviceFilter\",\n      \"DeviceIdLists\",\n      \"DeviceProperties\",\n      \"LevelChangedEvent\",\n      \"MuteChangedEvent\",\n      \"DeviceType\",\n      \"StreamType\"\n    ],\n    \"events\": [\"onDeviceListChanged\", \"onLevelChanged\", \"onMuteChanged\"]\n  },\n  \"bluetooth\": {\n    \"properties\": [],\n    \"methods\": [\n      \"getAdapterState\",\n      \"getDevice\",\n      \"getDevices\",\n      \"startDiscovery\",\n      \"stopDiscovery\"\n    ],\n    \"types\": [\n      \"AdapterState\",\n      \"BluetoothFilter\",\n      \"Device\",\n      \"DeviceType\",\n      \"FilterType\",\n      \"Transport\",\n      \"VendorIdSource\"\n    ],\n    \"events\": [\n      \"onAdapterStateChanged\",\n      \"onDeviceAdded\",\n      \"onDeviceChanged\",\n      \"onDeviceRemoved\"\n    ]\n  },\n  \"bluetoothLowEnergy\": {\n    \"properties\": [],\n    \"methods\": [\n      \"connect\",\n      \"createCharacteristic\",\n      \"createDescriptor\",\n      \"createService\",\n      \"disconnect\",\n      \"getCharacteristic\",\n      \"getCharacteristics\",\n      \"getDescriptor\",\n      \"getDescriptors\",\n      \"getIncludedServices\",\n      \"getService\",\n      \"getServices\",\n      \"notifyCharacteristicValueChanged\",\n      \"readCharacteristicValue\",\n      \"readDescriptorValue\",\n      \"registerAdvertisement\",\n      \"registerService\",\n      \"removeService\",\n      \"resetAdvertising\",\n      \"sendRequestResponse\",\n      \"setAdvertisingInterval\",\n      \"startCharacteristicNotifications\",\n      \"stopCharacteristicNotifications\",\n      \"unregisterAdvertisement\",\n      \"unregisterService\",\n      \"writeCharacteristicValue\",\n      \"writeDescriptorValue\"\n    ],\n    \"types\": [\n      \"Advertisement\",\n      \"Characteristic\",\n      \"ConnectProperties\",\n      \"Descriptor\",\n      \"Device\",\n      \"ManufacturerData\",\n      \"Notification\",\n      \"NotificationProperties\",\n      \"Request\",\n      \"Response\",\n      \"Service\",\n      \"ServiceData\",\n      \"AdvertisementType\",\n      \"CharacteristicProperty\",\n      \"DescriptorPermission\"\n    ],\n    \"events\": [\n      \"onCharacteristicReadRequest\",\n      \"onCharacteristicValueChanged\",\n      \"onCharacteristicWriteRequest\",\n      \"onDescriptorReadRequest\",\n      \"onDescriptorValueChanged\",\n      \"onDescriptorWriteRequest\",\n      \"onServiceAdded\",\n      \"onServiceChanged\",\n      \"onServiceRemoved\"\n    ]\n  },\n  \"bluetoothSocket\": {\n    \"properties\": [],\n    \"methods\": [\n      \"close\",\n      \"connect\",\n      \"create\",\n      \"disconnect\",\n      \"getInfo\",\n      \"getSockets\",\n      \"listenUsingL2cap\",\n      \"listenUsingRfcomm\",\n      \"send\",\n      \"setPaused\",\n      \"update\"\n    ],\n    \"types\": [\n      \"AcceptErrorInfo\",\n      \"AcceptInfo\",\n      \"CreateInfo\",\n      \"ListenOptions\",\n      \"ReceiveErrorInfo\",\n      \"ReceiveInfo\",\n      \"SocketInfo\",\n      \"SocketProperties\",\n      \"AcceptError\",\n      \"ReceiveError\"\n    ],\n    \"events\": [\"onAccept\", \"onAcceptError\", \"onReceive\", \"onReceiveError\"]\n  },\n  \"bookmarks\": {\n    \"properties\": [\n      \"MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE\",\n      \"MAX_WRITE_OPERATIONS_PER_HOUR\"\n    ],\n    \"methods\": [\n      \"create\",\n      \"get\",\n      \"getChildren\",\n      \"getRecent\",\n      \"getSubTree\",\n      \"getTree\",\n      \"move\",\n      \"remove\",\n      \"removeTree\",\n      \"search\",\n      \"update\"\n    ],\n    \"types\": [\n      \"BookmarkTreeNode\",\n      \"CreateDetails\",\n      \"BookmarkTreeNodeUnmodifiable\",\n      \"FolderType\"\n    ],\n    \"events\": [\n      \"onChanged\",\n      \"onChildrenReordered\",\n      \"onCreated\",\n      \"onImportBegan\",\n      \"onImportEnded\",\n      \"onMoved\",\n      \"onRemoved\"\n    ]\n  },\n  \"browser\": {\n    \"properties\": [],\n    \"methods\": [\"openTab\"],\n    \"types\": [\"OpenTabOptions\"],\n    \"events\": []\n  },\n  \"browserAction\": {\n    \"properties\": [],\n    \"methods\": [\n      \"disable\",\n      \"enable\",\n      \"getBadgeBackgroundColor\",\n      \"getBadgeText\",\n      \"getPopup\",\n      \"getTitle\",\n      \"setBadgeBackgroundColor\",\n      \"setBadgeText\",\n      \"setIcon\",\n      \"setPopup\",\n      \"setTitle\"\n    ],\n    \"types\": [\"TabDetails\", \"ColorArray\", \"ImageDataType\"],\n    \"events\": [\"onClicked\"]\n  },\n  \"browsingData\": {\n    \"properties\": [],\n    \"methods\": [\n      \"remove\",\n      \"removeAppcache\",\n      \"removeCache\",\n      \"removeCacheStorage\",\n      \"removeCookies\",\n      \"removeDownloads\",\n      \"removeFileSystems\",\n      \"removeFormData\",\n      \"removeHistory\",\n      \"removeIndexedDB\",\n      \"removeLocalStorage\",\n      \"removePasswords\",\n      \"removePluginData\",\n      \"removeServiceWorkers\",\n      \"removeWebSQL\",\n      \"settings\"\n    ],\n    \"types\": [\"DataTypeSet\", \"RemovalOptions\"],\n    \"events\": []\n  },\n  \"certificateProvider\": {\n    \"properties\": [],\n    \"methods\": [\n      \"reportSignature\",\n      \"requestPin\",\n      \"setCertificates\",\n      \"stopPinRequest\"\n    ],\n    \"types\": [\n      \"CertificateInfo\",\n      \"CertificatesUpdateRequest\",\n      \"ClientCertificateInfo\",\n      \"PinResponseDetails\",\n      \"ReportSignatureDetails\",\n      \"RequestPinDetails\",\n      \"SetCertificatesDetails\",\n      \"SignRequest\",\n      \"SignatureRequest\",\n      \"StopPinRequestDetails\",\n      \"Algorithm\",\n      \"Error\",\n      \"Hash\",\n      \"PinRequestErrorType\",\n      \"PinRequestType\"\n    ],\n    \"events\": [\n      \"onCertificatesRequested\",\n      \"onCertificatesUpdateRequested\",\n      \"onSignDigestRequested\",\n      \"onSignatureRequested\"\n    ]\n  },\n  \"chrome_url_overrides\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\"UrlOverrideInfo\"],\n    \"events\": []\n  },\n  \"clipboard\": {\n    \"properties\": [],\n    \"methods\": [\"setImageData\"],\n    \"types\": [\"AdditionalDataItem\", \"DataItemType\", \"ImageType\"],\n    \"events\": [\"onClipboardDataChanged\"]\n  },\n  \"commands\": {\n    \"properties\": [],\n    \"methods\": [\"getAll\"],\n    \"types\": [\"Command\"],\n    \"events\": [\"onCommand\"]\n  },\n  \"contentScripts\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\"ContentScript\"],\n    \"events\": []\n  },\n  \"contentSettings\": {\n    \"properties\": [\n      \"autoVerify\",\n      \"automaticDownloads\",\n      \"camera\",\n      \"clipboard\",\n      \"cookies\",\n      \"fullscreen\",\n      \"images\",\n      \"javascript\",\n      \"location\",\n      \"microphone\",\n      \"mouselock\",\n      \"notifications\",\n      \"plugins\",\n      \"popups\",\n      \"unsandboxedPlugins\"\n    ],\n    \"methods\": [],\n    \"types\": [\n      \"ContentSetting\",\n      \"ResourceIdentifier\",\n      \"AutoVerifyContentSetting\",\n      \"CameraContentSetting\",\n      \"ClipboardContentSetting\",\n      \"CookiesContentSetting\",\n      \"FullscreenContentSetting\",\n      \"ImagesContentSetting\",\n      \"JavascriptContentSetting\",\n      \"LocationContentSetting\",\n      \"MicrophoneContentSetting\",\n      \"MouselockContentSetting\",\n      \"MultipleAutomaticDownloadsContentSetting\",\n      \"NotificationsContentSetting\",\n      \"PluginsContentSetting\",\n      \"PopupsContentSetting\",\n      \"PpapiBrokerContentSetting\",\n      \"Scope\"\n    ],\n    \"events\": []\n  },\n  \"contextMenus\": {\n    \"properties\": [\"ACTION_MENU_TOP_LEVEL_LIMIT\"],\n    \"methods\": [\"create\", \"remove\", \"removeAll\", \"update\"],\n    \"types\": [\"CreateProperties\", \"OnClickData\", \"ContextType\", \"ItemType\"],\n    \"events\": [\"onClicked\"]\n  },\n  \"cookies\": {\n    \"properties\": [],\n    \"methods\": [\n      \"get\",\n      \"getAll\",\n      \"getAllCookieStores\",\n      \"getPartitionKey\",\n      \"remove\",\n      \"set\"\n    ],\n    \"types\": [\n      \"Cookie\",\n      \"CookieDetails\",\n      \"CookiePartitionKey\",\n      \"CookieStore\",\n      \"FrameDetails\",\n      \"OnChangedCause\",\n      \"SameSiteStatus\"\n    ],\n    \"events\": [\"onChanged\"]\n  },\n  \"crossOriginIsolation\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\"ResponseHeader\"],\n    \"events\": []\n  },\n  \"debugger\": {\n    \"properties\": [],\n    \"methods\": [\"attach\", \"detach\", \"getTargets\", \"sendCommand\"],\n    \"types\": [\n      \"Debuggee\",\n      \"DebuggerSession\",\n      \"TargetInfo\",\n      \"DetachReason\",\n      \"TargetInfoType\"\n    ],\n    \"events\": [\"onDetach\", \"onEvent\"]\n  },\n  \"declarativeContent\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\n      \"PageStateMatcher\",\n      \"RequestContentScript\",\n      \"SetIcon\",\n      \"ShowAction\",\n      \"ShowPageAction\",\n      \"ImageDataType\"\n    ],\n    \"events\": [\"onPageChanged\"]\n  },\n  \"declarativeNetRequest\": {\n    \"properties\": [\n      \"DYNAMIC_RULESET_ID\",\n      \"GETMATCHEDRULES_QUOTA_INTERVAL\",\n      \"GUARANTEED_MINIMUM_STATIC_RULES\",\n      \"MAX_GETMATCHEDRULES_CALLS_PER_INTERVAL\",\n      \"MAX_NUMBER_OF_DYNAMIC_RULES\",\n      \"MAX_NUMBER_OF_ENABLED_STATIC_RULESETS\",\n      \"MAX_NUMBER_OF_REGEX_RULES\",\n      \"MAX_NUMBER_OF_SESSION_RULES\",\n      \"MAX_NUMBER_OF_STATIC_RULESETS\",\n      \"MAX_NUMBER_OF_UNSAFE_DYNAMIC_RULES\",\n      \"MAX_NUMBER_OF_UNSAFE_SESSION_RULES\",\n      \"SESSION_RULESET_ID\"\n    ],\n    \"methods\": [\n      \"getAvailableStaticRuleCount\",\n      \"getDisabledRuleIds\",\n      \"getDynamicRules\",\n      \"getEnabledRulesets\",\n      \"getMatchedRules\",\n      \"getSessionRules\",\n      \"isRegexSupported\",\n      \"setExtensionActionOptions\",\n      \"testMatchOutcome\",\n      \"updateDynamicRules\",\n      \"updateEnabledRulesets\",\n      \"updateSessionRules\",\n      \"updateStaticRules\"\n    ],\n    \"types\": [\n      \"ExtensionActionOptions\",\n      \"GetDisabledRuleIdsOptions\",\n      \"GetRulesFilter\",\n      \"HeaderInfo\",\n      \"IsRegexSupportedResult\",\n      \"MatchedRule\",\n      \"MatchedRuleInfo\",\n      \"MatchedRuleInfoDebug\",\n      \"MatchedRulesFilter\",\n      \"ModifyHeaderInfo\",\n      \"QueryKeyValue\",\n      \"QueryTransform\",\n      \"Redirect\",\n      \"RegexOptions\",\n      \"RequestDetails\",\n      \"Rule\",\n      \"RuleAction\",\n      \"RuleCondition\",\n      \"RulesMatchedDetails\",\n      \"Ruleset\",\n      \"TabActionCountUpdate\",\n      \"TestMatchOutcomeResult\",\n      \"TestMatchRequestDetails\",\n      \"URLTransform\",\n      \"UpdateRuleOptions\",\n      \"UpdateRulesetOptions\",\n      \"UpdateStaticRulesOptions\",\n      \"DomainType\",\n      \"HeaderOperation\",\n      \"RequestMethod\",\n      \"ResourceType\",\n      \"RuleActionType\",\n      \"UnsupportedRegexReason\"\n    ],\n    \"events\": [\"onRuleMatchedDebug\"]\n  },\n  \"declarativeWebRequest\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\n      \"AddRequestCookie\",\n      \"AddResponseCookie\",\n      \"AddResponseHeader\",\n      \"CancelRequest\",\n      \"EditRequestCookie\",\n      \"EditResponseCookie\",\n      \"IgnoreRules\",\n      \"RedirectByRegEx\",\n      \"RedirectRequest\",\n      \"RedirectToEmptyDocument\",\n      \"RedirectToTransparentImage\",\n      \"RemoveRequestCookie\",\n      \"RemoveRequestHeader\",\n      \"RemoveResponseCookie\",\n      \"RemoveResponseHeader\",\n      \"RequestMatcher\",\n      \"SendMessageToExtension\",\n      \"SetRequestHeader\",\n      \"FilterResponseCookie\",\n      \"HeaderFilter\",\n      \"RequestCookie\",\n      \"ResponseCookie\",\n      \"Stage\"\n    ],\n    \"events\": [\"onMessage\", \"onRequest\"]\n  },\n  \"desktopCapture\": {\n    \"properties\": [],\n    \"methods\": [\"cancelChooseDesktopMedia\", \"chooseDesktopMedia\"],\n    \"types\": [\n      \"DesktopCaptureSourceType\",\n      \"SelfCapturePreferenceEnum\",\n      \"SystemAudioPreferenceEnum\"\n    ],\n    \"events\": []\n  },\n  \"devtools.inspectedWindow\": {\n    \"properties\": [\"tabId\"],\n    \"methods\": [\"eval\", \"getResources\", \"reload\"],\n    \"types\": [\"Resource\"],\n    \"events\": [\"onResourceAdded\", \"onResourceContentCommitted\"]\n  },\n  \"devtools.network\": {\n    \"properties\": [],\n    \"methods\": [\"getHAR\"],\n    \"types\": [\"Request\"],\n    \"events\": [\"onNavigated\", \"onRequestFinished\"]\n  },\n  \"devtools.panels\": {\n    \"properties\": [\"elements\", \"sources\", \"themeName\"],\n    \"methods\": [\"create\", \"openResource\", \"setOpenResourceHandler\"],\n    \"types\": [\n      \"Button\",\n      \"ElementsPanel\",\n      \"ExtensionPanel\",\n      \"ExtensionSidebarPane\",\n      \"SourcesPanel\"\n    ],\n    \"events\": []\n  },\n  \"devtools.performance\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [],\n    \"events\": [\"onProfilingStarted\", \"onProfilingStopped\"]\n  },\n  \"devtools.recorder\": {\n    \"properties\": [],\n    \"methods\": [\"createView\", \"registerRecorderExtensionPlugin\"],\n    \"types\": [\"RecorderExtensionPlugin\", \"RecorderView\"],\n    \"events\": []\n  },\n  \"diagnostics\": {\n    \"properties\": [],\n    \"methods\": [\"sendPacket\"],\n    \"types\": [\"SendPacketOptions\", \"SendPacketResult\"],\n    \"events\": []\n  },\n  \"dns\": {\n    \"properties\": [],\n    \"methods\": [\"resolve\"],\n    \"types\": [\"ResolveCallbackResolveInfo\"],\n    \"events\": []\n  },\n  \"documentScan\": {\n    \"properties\": [],\n    \"methods\": [\n      \"cancelScan\",\n      \"closeScanner\",\n      \"getOptionGroups\",\n      \"getScannerList\",\n      \"openScanner\",\n      \"readScanData\",\n      \"scan\",\n      \"setOptions\",\n      \"startScan\"\n    ],\n    \"types\": [\n      \"CancelScanResponse\",\n      \"CloseScannerResponse\",\n      \"DeviceFilter\",\n      \"GetOptionGroupsResponse\",\n      \"GetScannerListResponse\",\n      \"OpenScannerResponse\",\n      \"OptionConstraint\",\n      \"OptionGroup\",\n      \"OptionSetting\",\n      \"ReadScanDataResponse\",\n      \"ScanOptions\",\n      \"ScanResults\",\n      \"ScannerInfo\",\n      \"ScannerOption\",\n      \"SetOptionResult\",\n      \"SetOptionsResponse\",\n      \"StartScanOptions\",\n      \"StartScanResponse\",\n      \"Configurability\",\n      \"ConnectionType\",\n      \"ConstraintType\",\n      \"OperationResult\",\n      \"OptionType\",\n      \"OptionUnit\"\n    ],\n    \"events\": []\n  },\n  \"dom\": {\n    \"properties\": [],\n    \"methods\": [\"openOrClosedShadowRoot\"],\n    \"types\": [],\n    \"events\": []\n  },\n  \"downloads\": {\n    \"properties\": [],\n    \"methods\": [\n      \"acceptDanger\",\n      \"cancel\",\n      \"download\",\n      \"erase\",\n      \"getFileIcon\",\n      \"open\",\n      \"pause\",\n      \"removeFile\",\n      \"resume\",\n      \"search\",\n      \"setShelfEnabled\",\n      \"setUiOptions\",\n      \"show\",\n      \"showDefaultFolder\"\n    ],\n    \"types\": [\n      \"BooleanDelta\",\n      \"DoubleDelta\",\n      \"DownloadDelta\",\n      \"DownloadItem\",\n      \"DownloadOptions\",\n      \"DownloadQuery\",\n      \"FilenameSuggestion\",\n      \"GetFileIconOptions\",\n      \"HeaderNameValuePair\",\n      \"StringDelta\",\n      \"UiOptions\",\n      \"DangerType\",\n      \"FilenameConflictAction\",\n      \"HttpMethod\",\n      \"InterruptReason\",\n      \"State\"\n    ],\n    \"events\": [\"onChanged\", \"onCreated\", \"onDeterminingFilename\", \"onErased\"]\n  },\n  \"enterprise.deviceAttributes\": {\n    \"properties\": [],\n    \"methods\": [\n      \"getDeviceAnnotatedLocation\",\n      \"getDeviceAssetId\",\n      \"getDeviceHostname\",\n      \"getDeviceSerialNumber\",\n      \"getDirectoryDeviceId\"\n    ],\n    \"types\": [],\n    \"events\": []\n  },\n  \"enterprise.hardwarePlatform\": {\n    \"properties\": [],\n    \"methods\": [\"getHardwarePlatformInfo\"],\n    \"types\": [\"HardwarePlatformInfo\"],\n    \"events\": []\n  },\n  \"enterprise.kioskInput\": {\n    \"properties\": [],\n    \"methods\": [\"setCurrentInputMethod\"],\n    \"types\": [\"SetCurrentInputMethodOptions\"],\n    \"events\": []\n  },\n  \"enterprise.networkingAttributes\": {\n    \"properties\": [],\n    \"methods\": [\"getNetworkDetails\"],\n    \"types\": [\"NetworkDetails\"],\n    \"events\": []\n  },\n  \"enterprise.platformKeys\": {\n    \"properties\": [],\n    \"methods\": [\n      \"challengeKey\",\n      \"challengeMachineKey\",\n      \"challengeUserKey\",\n      \"getCertificates\",\n      \"getTokens\",\n      \"importCertificate\",\n      \"removeCertificate\"\n    ],\n    \"types\": [\n      \"ChallengeKeyOptions\",\n      \"RegisterKeyOptions\",\n      \"Token\",\n      \"Algorithm\",\n      \"Scope\"\n    ],\n    \"events\": []\n  },\n  \"events\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\"Event\", \"Rule\", \"UrlFilter\"],\n    \"events\": []\n  },\n  \"extension\": {\n    \"properties\": [\"inIncognitoContext\", \"lastError\"],\n    \"methods\": [\n      \"getBackgroundPage\",\n      \"getExtensionTabs\",\n      \"getURL\",\n      \"getViews\",\n      \"isAllowedFileSchemeAccess\",\n      \"isAllowedIncognitoAccess\",\n      \"sendRequest\",\n      \"setUpdateUrlData\"\n    ],\n    \"types\": [\"ViewType\"],\n    \"events\": [\"onRequest\", \"onRequestExternal\"]\n  },\n  \"extensionTypes\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\n      \"DeleteInjectionDetails\",\n      \"ImageDetails\",\n      \"InjectDetails\",\n      \"CSSOrigin\",\n      \"DocumentLifecycle\",\n      \"ExecutionWorld\",\n      \"FrameType\",\n      \"ImageFormat\",\n      \"RunAt\"\n    ],\n    \"events\": []\n  },\n  \"extensionsManifestTypes\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\n      \"ContentCapabilities\",\n      \"ExternallyConnectable\",\n      \"OptionsUI\",\n      \"UsbPrinters\",\n      \"bluetooth\",\n      \"sockets\",\n      \"KioskSecondaryApps\",\n      \"SocketHostPatterns\",\n      \"automation\"\n    ],\n    \"events\": []\n  },\n  \"fileBrowserHandler\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\"FileHandlerExecuteEventDetails\"],\n    \"events\": [\"onExecute\"]\n  },\n  \"fileHandlers\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\"FileHandler\", \"Icon\"],\n    \"events\": []\n  },\n  \"fileSystem\": {\n    \"properties\": [],\n    \"methods\": [\n      \"chooseEntry\",\n      \"getDisplayPath\",\n      \"getVolumeList\",\n      \"getWritableEntry\",\n      \"isRestorable\",\n      \"isWritableEntry\",\n      \"requestFileSystem\",\n      \"restoreEntry\",\n      \"retainEntry\"\n    ],\n    \"types\": [\n      \"AcceptOption\",\n      \"ChooseEntryOptions\",\n      \"RequestFileSystemOptions\",\n      \"Volume\",\n      \"VolumeListChangedEvent\",\n      \"ChooseEntryType\"\n    ],\n    \"events\": [\"onVolumeListChanged\"]\n  },\n  \"fileSystemProvider\": {\n    \"properties\": [],\n    \"methods\": [\"get\", \"getAll\", \"mount\", \"notify\", \"unmount\"],\n    \"types\": [\n      \"AbortRequestedOptions\",\n      \"Action\",\n      \"AddWatcherRequestedOptions\",\n      \"Change\",\n      \"CloseFileRequestedOptions\",\n      \"CloudFileInfo\",\n      \"CloudIdentifier\",\n      \"ConfigureRequestedOptions\",\n      \"CopyEntryRequestedOptions\",\n      \"CreateDirectoryRequestedOptions\",\n      \"CreateFileRequestedOptions\",\n      \"DeleteEntryRequestedOptions\",\n      \"EntryMetadata\",\n      \"ExecuteActionRequestedOptions\",\n      \"FileSystemInfo\",\n      \"GetActionsRequestedOptions\",\n      \"GetMetadataRequestedOptions\",\n      \"MountOptions\",\n      \"MoveEntryRequestedOptions\",\n      \"NotifyOptions\",\n      \"OpenFileRequestedOptions\",\n      \"OpenedFile\",\n      \"ReadDirectoryRequestedOptions\",\n      \"ReadFileRequestedOptions\",\n      \"RemoveWatcherRequestedOptions\",\n      \"TruncateRequestedOptions\",\n      \"UnmountOptions\",\n      \"UnmountRequestedOptions\",\n      \"Watcher\",\n      \"WriteFileRequestedOptions\",\n      \"ChangeType\",\n      \"CommonActionId\",\n      \"OpenFileMode\",\n      \"ProviderError\"\n    ],\n    \"events\": [\n      \"onAbortRequested\",\n      \"onAddWatcherRequested\",\n      \"onCloseFileRequested\",\n      \"onConfigureRequested\",\n      \"onCopyEntryRequested\",\n      \"onCreateDirectoryRequested\",\n      \"onCreateFileRequested\",\n      \"onDeleteEntryRequested\",\n      \"onExecuteActionRequested\",\n      \"onGetActionsRequested\",\n      \"onGetMetadataRequested\",\n      \"onMountRequested\",\n      \"onMoveEntryRequested\",\n      \"onOpenFileRequested\",\n      \"onReadDirectoryRequested\",\n      \"onReadFileRequested\",\n      \"onRemoveWatcherRequested\",\n      \"onTruncateRequested\",\n      \"onUnmountRequested\",\n      \"onWriteFileRequested\"\n    ]\n  },\n  \"fontSettings\": {\n    \"properties\": [],\n    \"methods\": [\n      \"clearDefaultFixedFontSize\",\n      \"clearDefaultFontSize\",\n      \"clearFont\",\n      \"clearMinimumFontSize\",\n      \"getDefaultFixedFontSize\",\n      \"getDefaultFontSize\",\n      \"getFont\",\n      \"getFontList\",\n      \"getMinimumFontSize\",\n      \"setDefaultFixedFontSize\",\n      \"setDefaultFontSize\",\n      \"setFont\",\n      \"setMinimumFontSize\"\n    ],\n    \"types\": [\"FontName\", \"GenericFamily\", \"LevelOfControl\", \"ScriptCode\"],\n    \"events\": [\n      \"onDefaultFixedFontSizeChanged\",\n      \"onDefaultFontSizeChanged\",\n      \"onFontChanged\",\n      \"onMinimumFontSizeChanged\"\n    ]\n  },\n  \"gcm\": {\n    \"properties\": [\"MAX_MESSAGE_SIZE\"],\n    \"methods\": [\"register\", \"send\", \"unregister\"],\n    \"types\": [],\n    \"events\": [\"onMessage\", \"onMessagesDeleted\", \"onSendError\"]\n  },\n  \"hid\": {\n    \"properties\": [],\n    \"methods\": [\n      \"connect\",\n      \"disconnect\",\n      \"getDevices\",\n      \"receive\",\n      \"receiveFeatureReport\",\n      \"send\",\n      \"sendFeatureReport\"\n    ],\n    \"types\": [\n      \"DeviceFilter\",\n      \"GetDevicesOptions\",\n      \"HidCollectionInfo\",\n      \"HidConnectInfo\",\n      \"HidDeviceInfo\"\n    ],\n    \"events\": [\"onDeviceAdded\", \"onDeviceRemoved\"]\n  },\n  \"history\": {\n    \"properties\": [],\n    \"methods\": [\n      \"addUrl\",\n      \"deleteAll\",\n      \"deleteRange\",\n      \"deleteUrl\",\n      \"getVisits\",\n      \"search\"\n    ],\n    \"types\": [\"HistoryItem\", \"UrlDetails\", \"VisitItem\", \"TransitionType\"],\n    \"events\": [\"onVisitRemoved\", \"onVisited\"]\n  },\n  \"i18n\": {\n    \"properties\": [],\n    \"methods\": [\n      \"detectLanguage\",\n      \"getAcceptLanguages\",\n      \"getMessage\",\n      \"getUILanguage\"\n    ],\n    \"types\": [\"LanguageCode\"],\n    \"events\": []\n  },\n  \"identity\": {\n    \"properties\": [],\n    \"methods\": [\n      \"clearAllCachedAuthTokens\",\n      \"getAccounts\",\n      \"getAuthToken\",\n      \"getProfileUserInfo\",\n      \"getRedirectURL\",\n      \"launchWebAuthFlow\",\n      \"removeCachedAuthToken\"\n    ],\n    \"types\": [\n      \"AccountInfo\",\n      \"GetAuthTokenResult\",\n      \"InvalidTokenDetails\",\n      \"ProfileDetails\",\n      \"ProfileUserInfo\",\n      \"TokenDetails\",\n      \"WebAuthFlowDetails\",\n      \"AccountStatus\"\n    ],\n    \"events\": [\"onSignInChanged\"]\n  },\n  \"idle\": {\n    \"properties\": [],\n    \"methods\": [\"getAutoLockDelay\", \"queryState\", \"setDetectionInterval\"],\n    \"types\": [\"IdleState\"],\n    \"events\": [\"onStateChanged\"]\n  },\n  \"incognito\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\"IncognitoMode\"],\n    \"events\": []\n  },\n  \"input.ime\": {\n    \"properties\": [],\n    \"methods\": [\n      \"clearComposition\",\n      \"commitText\",\n      \"deleteSurroundingText\",\n      \"hideInputView\",\n      \"keyEventHandled\",\n      \"sendKeyEvents\",\n      \"setAssistiveWindowButtonHighlighted\",\n      \"setAssistiveWindowProperties\",\n      \"setCandidateWindowProperties\",\n      \"setCandidates\",\n      \"setComposition\",\n      \"setCursorPosition\",\n      \"setMenuItems\",\n      \"updateMenuItems\"\n    ],\n    \"types\": [\n      \"AssistiveWindowProperties\",\n      \"InputContext\",\n      \"KeyboardEvent\",\n      \"MenuItem\",\n      \"MenuParameters\",\n      \"AssistiveWindowButton\",\n      \"AssistiveWindowType\",\n      \"AutoCapitalizeType\",\n      \"InputContextType\",\n      \"KeyboardEventType\",\n      \"MenuItemStyle\",\n      \"MouseButton\",\n      \"ScreenType\",\n      \"UnderlineStyle\",\n      \"WindowPosition\"\n    ],\n    \"events\": [\n      \"onActivate\",\n      \"onAssistiveWindowButtonClicked\",\n      \"onBlur\",\n      \"onCandidateClicked\",\n      \"onDeactivated\",\n      \"onFocus\",\n      \"onInputContextUpdate\",\n      \"onKeyEvent\",\n      \"onMenuItemActivated\",\n      \"onReset\",\n      \"onSurroundingTextChanged\"\n    ]\n  },\n  \"instanceID\": {\n    \"properties\": [],\n    \"methods\": [\n      \"deleteID\",\n      \"deleteToken\",\n      \"getCreationTime\",\n      \"getID\",\n      \"getToken\"\n    ],\n    \"types\": [],\n    \"events\": [\"onTokenRefresh\"]\n  },\n  \"loginState\": {\n    \"properties\": [],\n    \"methods\": [\"getProfileType\", \"getSessionState\"],\n    \"types\": [\"ProfileType\", \"SessionState\"],\n    \"events\": [\"onSessionStateChanged\"]\n  },\n  \"management\": {\n    \"properties\": [],\n    \"methods\": [\n      \"createAppShortcut\",\n      \"generateAppForLink\",\n      \"get\",\n      \"getAll\",\n      \"getPermissionWarningsById\",\n      \"getPermissionWarningsByManifest\",\n      \"getSelf\",\n      \"installReplacementWebApp\",\n      \"launchApp\",\n      \"setEnabled\",\n      \"setLaunchType\",\n      \"uninstall\",\n      \"uninstallSelf\"\n    ],\n    \"types\": [\n      \"ExtensionInfo\",\n      \"IconInfo\",\n      \"UninstallOptions\",\n      \"ExtensionDisabledReason\",\n      \"ExtensionInstallType\",\n      \"ExtensionType\",\n      \"LaunchType\"\n    ],\n    \"events\": [\"onDisabled\", \"onEnabled\", \"onInstalled\", \"onUninstalled\"]\n  },\n  \"manifestTypes\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\n      \"ChromeSettingsOverrides\",\n      \"FileSystemProviderCapabilities\",\n      \"FileSystemProviderSource\"\n    ],\n    \"events\": []\n  },\n  \"mdns\": {\n    \"properties\": [\"MAX_SERVICE_INSTANCES_PER_EVENT\"],\n    \"methods\": [\"forceDiscovery\"],\n    \"types\": [\"MDnsService\"],\n    \"events\": [\"onServiceList\"]\n  },\n  \"mediaGalleries\": {\n    \"properties\": [],\n    \"methods\": [\n      \"addGalleryWatch\",\n      \"addUserSelectedFolder\",\n      \"getMediaFileSystemMetadata\",\n      \"getMediaFileSystems\",\n      \"getMetadata\",\n      \"removeGalleryWatch\"\n    ],\n    \"types\": [\n      \"AddGalleryWatchResult\",\n      \"GalleryChangeDetails\",\n      \"MediaFileSystemMetadata\",\n      \"MediaFileSystemsDetails\",\n      \"MediaMetadata\",\n      \"MediaMetadataOptions\",\n      \"StreamInfo\",\n      \"GalleryChangeType\",\n      \"GetMediaFileSystemsInteractivity\",\n      \"GetMetadataType\"\n    ],\n    \"events\": [\"onGalleryChanged\"]\n  },\n  \"networking.onc\": {\n    \"properties\": [],\n    \"methods\": [\n      \"createNetwork\",\n      \"disableNetworkType\",\n      \"enableNetworkType\",\n      \"forgetNetwork\",\n      \"getCaptivePortalStatus\",\n      \"getDeviceStates\",\n      \"getGlobalPolicy\",\n      \"getManagedProperties\",\n      \"getNetworks\",\n      \"getProperties\",\n      \"getState\",\n      \"requestNetworkScan\",\n      \"setProperties\",\n      \"startConnect\",\n      \"startDisconnect\"\n    ],\n    \"types\": [\n      \"CellularProperties\",\n      \"CellularProviderProperties\",\n      \"CellularStateProperties\",\n      \"CertificatePattern\",\n      \"DeviceStateProperties\",\n      \"EAPProperties\",\n      \"EthernetProperties\",\n      \"EthernetStateProperties\",\n      \"FoundNetworkProperties\",\n      \"GlobalPolicy\",\n      \"IPConfigProperties\",\n      \"IssuerSubjectPattern\",\n      \"ManagedBoolean\",\n      \"ManagedCellularProperties\",\n      \"ManagedDOMString\",\n      \"ManagedDOMStringList\",\n      \"ManagedEthernetProperties\",\n      \"ManagedIPConfigProperties\",\n      \"ManagedIPConfigType\",\n      \"ManagedLong\",\n      \"ManagedManualProxySettings\",\n      \"ManagedProperties\",\n      \"ManagedProxyLocation\",\n      \"ManagedProxySettings\",\n      \"ManagedProxySettingsType\",\n      \"ManagedThirdPartyVPNProperties\",\n      \"ManagedVPNProperties\",\n      \"ManagedWiFiProperties\",\n      \"ManualProxySettings\",\n      \"NetworkConfigProperties\",\n      \"NetworkFilter\",\n      \"NetworkProperties\",\n      \"NetworkStateProperties\",\n      \"PaymentPortal\",\n      \"ProxyLocation\",\n      \"ProxySettings\",\n      \"SIMLockStatus\",\n      \"ThirdPartyVPNProperties\",\n      \"VPNProperties\",\n      \"VPNStateProperties\",\n      \"WiFiProperties\",\n      \"WiFiStateProperties\",\n      \"WiMAXProperties\",\n      \"ActivationStateType\",\n      \"CaptivePortalStatus\",\n      \"ClientCertificateType\",\n      \"ConnectionStateType\",\n      \"DeviceStateType\",\n      \"IPConfigType\",\n      \"NetworkType\",\n      \"ProxySettingsType\"\n    ],\n    \"events\": [\n      \"onDeviceStateListChanged\",\n      \"onNetworkListChanged\",\n      \"onNetworksChanged\",\n      \"onPortalDetectionCompleted\"\n    ]\n  },\n  \"notifications\": {\n    \"properties\": [],\n    \"methods\": [\"clear\", \"create\", \"getAll\", \"getPermissionLevel\", \"update\"],\n    \"types\": [\n      \"NotificationBitmap\",\n      \"NotificationButton\",\n      \"NotificationItem\",\n      \"NotificationOptions\",\n      \"PermissionLevel\",\n      \"TemplateType\"\n    ],\n    \"events\": [\n      \"onButtonClicked\",\n      \"onClicked\",\n      \"onClosed\",\n      \"onPermissionLevelChanged\",\n      \"onShowSettings\"\n    ]\n  },\n  \"oauth2\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\"OAuth2Info\"],\n    \"events\": []\n  },\n  \"offscreen\": {\n    \"properties\": [],\n    \"methods\": [\"closeDocument\", \"createDocument\"],\n    \"types\": [\"CreateParameters\", \"Reason\"],\n    \"events\": []\n  },\n  \"omnibox\": {\n    \"properties\": [],\n    \"methods\": [\"setDefaultSuggestion\"],\n    \"types\": [\n      \"DefaultSuggestResult\",\n      \"SuggestResult\",\n      \"DescriptionStyleType\",\n      \"OnInputEnteredDisposition\"\n    ],\n    \"events\": [\n      \"onDeleteSuggestion\",\n      \"onInputCancelled\",\n      \"onInputChanged\",\n      \"onInputEntered\",\n      \"onInputStarted\"\n    ]\n  },\n  \"pageAction\": {\n    \"properties\": [],\n    \"methods\": [\n      \"getPopup\",\n      \"getTitle\",\n      \"hide\",\n      \"setIcon\",\n      \"setPopup\",\n      \"setTitle\",\n      \"show\"\n    ],\n    \"types\": [\"TabDetails\", \"ImageDataType\"],\n    \"events\": [\"onClicked\"]\n  },\n  \"pageCapture\": {\n    \"properties\": [],\n    \"methods\": [\"saveAsMHTML\"],\n    \"types\": [],\n    \"events\": []\n  },\n  \"permissions\": {\n    \"properties\": [],\n    \"methods\": [\n      \"addHostAccessRequest\",\n      \"contains\",\n      \"getAll\",\n      \"remove\",\n      \"removeHostAccessRequest\",\n      \"request\"\n    ],\n    \"types\": [\"Permissions\"],\n    \"events\": [\"onAdded\", \"onRemoved\"]\n  },\n  \"platformKeys\": {\n    \"properties\": [],\n    \"methods\": [\n      \"getKeyPair\",\n      \"getKeyPairBySpki\",\n      \"selectClientCertificates\",\n      \"subtleCrypto\",\n      \"verifyTLSServerCertificate\"\n    ],\n    \"types\": [\n      \"ClientCertificateRequest\",\n      \"Match\",\n      \"SelectDetails\",\n      \"VerificationDetails\",\n      \"VerificationResult\",\n      \"ClientCertificateType\"\n    ],\n    \"events\": []\n  },\n  \"power\": {\n    \"properties\": [],\n    \"methods\": [\"releaseKeepAwake\", \"reportActivity\", \"requestKeepAwake\"],\n    \"types\": [\"Level\"],\n    \"events\": []\n  },\n  \"printerProvider\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\"PrintJob\", \"PrinterInfo\", \"PrintError\"],\n    \"events\": [\n      \"onGetCapabilityRequested\",\n      \"onGetPrintersRequested\",\n      \"onGetUsbPrinterInfoRequested\",\n      \"onPrintRequested\"\n    ]\n  },\n  \"printing\": {\n    \"properties\": [\n      \"MAX_GET_PRINTER_INFO_CALLS_PER_MINUTE\",\n      \"MAX_SUBMIT_JOB_CALLS_PER_MINUTE\"\n    ],\n    \"methods\": [\n      \"cancelJob\",\n      \"getJobStatus\",\n      \"getPrinterInfo\",\n      \"getPrinters\",\n      \"submitJob\"\n    ],\n    \"types\": [\n      \"GetPrinterInfoResponse\",\n      \"Printer\",\n      \"SubmitJobRequest\",\n      \"SubmitJobResponse\",\n      \"JobStatus\",\n      \"PrinterSource\",\n      \"PrinterStatus\",\n      \"SubmitJobStatus\"\n    ],\n    \"events\": [\"onJobStatusChanged\"]\n  },\n  \"printingMetrics\": {\n    \"properties\": [],\n    \"methods\": [\"getPrintJobs\"],\n    \"types\": [\n      \"MediaSize\",\n      \"PrintJobInfo\",\n      \"PrintSettings\",\n      \"Printer\",\n      \"ColorMode\",\n      \"DuplexMode\",\n      \"PrintJobSource\",\n      \"PrintJobStatus\",\n      \"PrinterSource\"\n    ],\n    \"events\": [\"onPrintJobFinished\"]\n  },\n  \"privacy\": {\n    \"properties\": [\"network\", \"services\", \"websites\"],\n    \"methods\": [],\n    \"types\": [\"IPHandlingPolicy\"],\n    \"events\": []\n  },\n  \"processes\": {\n    \"properties\": [],\n    \"methods\": [\"getProcessIdForTab\", \"getProcessInfo\", \"terminate\"],\n    \"types\": [\"Cache\", \"Process\", \"TaskInfo\", \"ProcessType\"],\n    \"events\": [\n      \"onCreated\",\n      \"onExited\",\n      \"onUnresponsive\",\n      \"onUpdated\",\n      \"onUpdatedWithMemory\"\n    ]\n  },\n  \"proxy\": {\n    \"properties\": [\"settings\"],\n    \"methods\": [],\n    \"types\": [\n      \"PacScript\",\n      \"ProxyConfig\",\n      \"ProxyRules\",\n      \"ProxyServer\",\n      \"Mode\",\n      \"Scheme\"\n    ],\n    \"events\": [\"onProxyError\"]\n  },\n  \"readingList\": {\n    \"properties\": [],\n    \"methods\": [\"addEntry\", \"query\", \"removeEntry\", \"updateEntry\"],\n    \"types\": [\n      \"AddEntryOptions\",\n      \"QueryInfo\",\n      \"ReadingListEntry\",\n      \"RemoveOptions\",\n      \"UpdateEntryOptions\"\n    ],\n    \"events\": [\"onEntryAdded\", \"onEntryRemoved\", \"onEntryUpdated\"]\n  },\n  \"runtime\": {\n    \"properties\": [\"id\", \"lastError\"],\n    \"methods\": [\n      \"connect\",\n      \"connectNative\",\n      \"getBackgroundPage\",\n      \"getContexts\",\n      \"getManifest\",\n      \"getPackageDirectoryEntry\",\n      \"getPlatformInfo\",\n      \"getURL\",\n      \"openOptionsPage\",\n      \"reload\",\n      \"requestUpdateCheck\",\n      \"restart\",\n      \"restartAfterDelay\",\n      \"sendMessage\",\n      \"sendNativeMessage\",\n      \"setUninstallURL\"\n    ],\n    \"types\": [\n      \"ContextFilter\",\n      \"ExtensionContext\",\n      \"MessageSender\",\n      \"PlatformInfo\",\n      \"Port\",\n      \"ContextType\",\n      \"OnInstalledReason\",\n      \"OnRestartRequiredReason\",\n      \"PlatformArch\",\n      \"PlatformNaclArch\",\n      \"PlatformOs\",\n      \"RequestUpdateCheckStatus\"\n    ],\n    \"events\": [\n      \"onBrowserUpdateAvailable\",\n      \"onConnect\",\n      \"onConnectExternal\",\n      \"onConnectNative\",\n      \"onInstalled\",\n      \"onMessage\",\n      \"onMessageExternal\",\n      \"onRestartRequired\",\n      \"onStartup\",\n      \"onSuspend\",\n      \"onSuspendCanceled\",\n      \"onUpdateAvailable\",\n      \"onUserScriptConnect\",\n      \"onUserScriptMessage\"\n    ]\n  },\n  \"scripting\": {\n    \"properties\": [],\n    \"methods\": [\n      \"executeScript\",\n      \"getRegisteredContentScripts\",\n      \"insertCSS\",\n      \"registerContentScripts\",\n      \"removeCSS\",\n      \"unregisterContentScripts\",\n      \"updateContentScripts\"\n    ],\n    \"types\": [\n      \"CSSInjection\",\n      \"ContentScriptFilter\",\n      \"InjectionResult\",\n      \"InjectionTarget\",\n      \"RegisteredContentScript\",\n      \"ScriptInjection\",\n      \"ExecutionWorld\",\n      \"StyleOrigin\"\n    ],\n    \"events\": []\n  },\n  \"search\": {\n    \"properties\": [],\n    \"methods\": [\"query\"],\n    \"types\": [\"QueryInfo\", \"Disposition\"],\n    \"events\": []\n  },\n  \"serial\": {\n    \"properties\": [],\n    \"methods\": [\n      \"clearBreak\",\n      \"connect\",\n      \"disconnect\",\n      \"flush\",\n      \"getConnections\",\n      \"getControlSignals\",\n      \"getDevices\",\n      \"getInfo\",\n      \"send\",\n      \"setBreak\",\n      \"setControlSignals\",\n      \"setPaused\",\n      \"update\"\n    ],\n    \"types\": [\n      \"ConnectionInfo\",\n      \"ConnectionOptions\",\n      \"DeviceControlSignals\",\n      \"DeviceInfo\",\n      \"HostControlSignals\",\n      \"ReceiveErrorInfo\",\n      \"ReceiveInfo\",\n      \"SendInfo\",\n      \"DataBits\",\n      \"ParityBit\",\n      \"ReceiveError\",\n      \"SendError\",\n      \"StopBits\"\n    ],\n    \"events\": [\"onReceive\", \"onReceiveError\"]\n  },\n  \"sessions\": {\n    \"properties\": [\"MAX_SESSION_RESULTS\"],\n    \"methods\": [\"getDevices\", \"getRecentlyClosed\", \"restore\"],\n    \"types\": [\"Device\", \"Filter\", \"Session\"],\n    \"events\": [\"onChanged\"]\n  },\n  \"sharedModule\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\"Export\", \"Import\"],\n    \"events\": []\n  },\n  \"sidePanel\": {\n    \"properties\": [],\n    \"methods\": [\n      \"getOptions\",\n      \"getPanelBehavior\",\n      \"open\",\n      \"setOptions\",\n      \"setPanelBehavior\"\n    ],\n    \"types\": [\n      \"GetPanelOptions\",\n      \"OpenOptions\",\n      \"PanelBehavior\",\n      \"PanelOptions\",\n      \"SidePanel\"\n    ],\n    \"events\": []\n  },\n  \"socket\": {\n    \"properties\": [],\n    \"methods\": [\n      \"accept\",\n      \"bind\",\n      \"connect\",\n      \"create\",\n      \"destroy\",\n      \"disconnect\",\n      \"getInfo\",\n      \"getJoinedGroups\",\n      \"getNetworkList\",\n      \"joinGroup\",\n      \"leaveGroup\",\n      \"listen\",\n      \"read\",\n      \"recvFrom\",\n      \"secure\",\n      \"sendTo\",\n      \"setKeepAlive\",\n      \"setMulticastLoopbackMode\",\n      \"setMulticastTimeToLive\",\n      \"setNoDelay\",\n      \"write\"\n    ],\n    \"types\": [\n      \"AcceptInfo\",\n      \"CreateInfo\",\n      \"CreateOptions\",\n      \"NetworkInterface\",\n      \"ReadInfo\",\n      \"RecvFromInfo\",\n      \"SecureOptions\",\n      \"SocketInfo\",\n      \"TLSVersionConstraints\",\n      \"WriteInfo\",\n      \"SocketType\"\n    ],\n    \"events\": []\n  },\n  \"sockets.tcp\": {\n    \"properties\": [],\n    \"methods\": [\n      \"close\",\n      \"connect\",\n      \"create\",\n      \"disconnect\",\n      \"getInfo\",\n      \"getSockets\",\n      \"secure\",\n      \"send\",\n      \"setKeepAlive\",\n      \"setNoDelay\",\n      \"setPaused\",\n      \"update\"\n    ],\n    \"types\": [\n      \"CreateInfo\",\n      \"ReceiveErrorInfo\",\n      \"ReceiveInfo\",\n      \"SecureOptions\",\n      \"SendInfo\",\n      \"SocketInfo\",\n      \"SocketProperties\",\n      \"TLSVersionConstraints\",\n      \"DnsQueryType\"\n    ],\n    \"events\": [\"onReceive\", \"onReceiveError\"]\n  },\n  \"sockets.tcpServer\": {\n    \"properties\": [],\n    \"methods\": [\n      \"close\",\n      \"create\",\n      \"disconnect\",\n      \"getInfo\",\n      \"getSockets\",\n      \"listen\",\n      \"setPaused\",\n      \"update\"\n    ],\n    \"types\": [\n      \"AcceptErrorInfo\",\n      \"AcceptInfo\",\n      \"CreateInfo\",\n      \"SocketInfo\",\n      \"SocketProperties\"\n    ],\n    \"events\": [\"onAccept\", \"onAcceptError\"]\n  },\n  \"sockets.udp\": {\n    \"properties\": [],\n    \"methods\": [\n      \"bind\",\n      \"close\",\n      \"create\",\n      \"getInfo\",\n      \"getJoinedGroups\",\n      \"getSockets\",\n      \"joinGroup\",\n      \"leaveGroup\",\n      \"send\",\n      \"setBroadcast\",\n      \"setMulticastLoopbackMode\",\n      \"setMulticastTimeToLive\",\n      \"setPaused\",\n      \"update\"\n    ],\n    \"types\": [\n      \"CreateInfo\",\n      \"ReceiveErrorInfo\",\n      \"ReceiveInfo\",\n      \"SendInfo\",\n      \"SocketInfo\",\n      \"SocketProperties\",\n      \"DnsQueryType\"\n    ],\n    \"events\": [\"onReceive\", \"onReceiveError\"]\n  },\n  \"storage\": {\n    \"properties\": [\"local\", \"managed\", \"session\", \"sync\"],\n    \"methods\": [],\n    \"types\": [\"StorageArea\", \"StorageChange\", \"AccessLevel\"],\n    \"events\": [\"onChanged\"]\n  },\n  \"syncFileSystem\": {\n    \"properties\": [],\n    \"methods\": [\n      \"getConflictResolutionPolicy\",\n      \"getFileStatus\",\n      \"getFileStatuses\",\n      \"getServiceStatus\",\n      \"getUsageAndQuota\",\n      \"requestFileSystem\",\n      \"setConflictResolutionPolicy\"\n    ],\n    \"types\": [\n      \"FileInfo\",\n      \"FileStatusInfo\",\n      \"ServiceInfo\",\n      \"StorageInfo\",\n      \"ConflictResolutionPolicy\",\n      \"FileStatus\",\n      \"ServiceStatus\",\n      \"SyncAction\",\n      \"SyncDirection\"\n    ],\n    \"events\": [\"onFileStatusChanged\", \"onServiceStatusChanged\"]\n  },\n  \"system.cpu\": {\n    \"properties\": [],\n    \"methods\": [\"getInfo\"],\n    \"types\": [\"CpuInfo\", \"CpuTime\", \"ProcessorInfo\"],\n    \"events\": []\n  },\n  \"system.display\": {\n    \"properties\": [],\n    \"methods\": [\n      \"clearTouchCalibration\",\n      \"completeCustomTouchCalibration\",\n      \"enableUnifiedDesktop\",\n      \"getDisplayLayout\",\n      \"getInfo\",\n      \"overscanCalibrationAdjust\",\n      \"overscanCalibrationComplete\",\n      \"overscanCalibrationReset\",\n      \"overscanCalibrationStart\",\n      \"setDisplayLayout\",\n      \"setDisplayProperties\",\n      \"setMirrorMode\",\n      \"showNativeTouchCalibration\",\n      \"startCustomTouchCalibration\"\n    ],\n    \"types\": [\n      \"Bounds\",\n      \"DisplayLayout\",\n      \"DisplayMode\",\n      \"DisplayProperties\",\n      \"DisplayUnitInfo\",\n      \"Edid\",\n      \"GetInfoFlags\",\n      \"Insets\",\n      \"MirrorModeInfo\",\n      \"Point\",\n      \"TouchCalibrationPair\",\n      \"TouchCalibrationPairQuad\",\n      \"ActiveState\",\n      \"LayoutPosition\",\n      \"MirrorMode\"\n    ],\n    \"events\": [\"onDisplayChanged\"]\n  },\n  \"system.memory\": {\n    \"properties\": [],\n    \"methods\": [\"getInfo\"],\n    \"types\": [\"MemoryInfo\"],\n    \"events\": []\n  },\n  \"system.network\": {\n    \"properties\": [],\n    \"methods\": [\"getNetworkInterfaces\"],\n    \"types\": [\"NetworkInterface\"],\n    \"events\": []\n  },\n  \"system.storage\": {\n    \"properties\": [],\n    \"methods\": [\"ejectDevice\", \"getAvailableCapacity\", \"getInfo\"],\n    \"types\": [\n      \"StorageAvailableCapacityInfo\",\n      \"StorageUnitInfo\",\n      \"EjectDeviceResultCode\",\n      \"StorageUnitType\"\n    ],\n    \"events\": [\"onAttached\", \"onDetached\"]\n  },\n  \"systemLog\": {\n    \"properties\": [],\n    \"methods\": [\"add\"],\n    \"types\": [\"MessageOptions\"],\n    \"events\": []\n  },\n  \"tabCapture\": {\n    \"properties\": [],\n    \"methods\": [\"capture\", \"getCapturedTabs\", \"getMediaStreamId\"],\n    \"types\": [\n      \"CaptureInfo\",\n      \"CaptureOptions\",\n      \"GetMediaStreamOptions\",\n      \"MediaStreamConstraint\",\n      \"TabCaptureState\"\n    ],\n    \"events\": [\"onStatusChanged\"]\n  },\n  \"tabGroups\": {\n    \"properties\": [\"TAB_GROUP_ID_NONE\"],\n    \"methods\": [\"get\", \"move\", \"query\", \"update\"],\n    \"types\": [\"TabGroup\", \"Color\"],\n    \"events\": [\"onCreated\", \"onMoved\", \"onRemoved\", \"onUpdated\"]\n  },\n  \"tabs\": {\n    \"properties\": [\n      \"MAX_CAPTURE_VISIBLE_TAB_CALLS_PER_SECOND\",\n      \"TAB_ID_NONE\",\n      \"TAB_INDEX_NONE\"\n    ],\n    \"methods\": [\n      \"captureVisibleTab\",\n      \"connect\",\n      \"create\",\n      \"detectLanguage\",\n      \"discard\",\n      \"duplicate\",\n      \"executeScript\",\n      \"get\",\n      \"getAllInWindow\",\n      \"getCurrent\",\n      \"getSelected\",\n      \"getZoom\",\n      \"getZoomSettings\",\n      \"goBack\",\n      \"goForward\",\n      \"group\",\n      \"highlight\",\n      \"insertCSS\",\n      \"move\",\n      \"query\",\n      \"reload\",\n      \"remove\",\n      \"removeCSS\",\n      \"sendMessage\",\n      \"sendRequest\",\n      \"setZoom\",\n      \"setZoomSettings\",\n      \"ungroup\",\n      \"update\"\n    ],\n    \"types\": [\n      \"MutedInfo\",\n      \"Tab\",\n      \"ZoomSettings\",\n      \"MutedInfoReason\",\n      \"TabStatus\",\n      \"WindowType\",\n      \"ZoomSettingsMode\",\n      \"ZoomSettingsScope\"\n    ],\n    \"events\": [\n      \"onActivated\",\n      \"onActiveChanged\",\n      \"onAttached\",\n      \"onCreated\",\n      \"onDetached\",\n      \"onHighlightChanged\",\n      \"onHighlighted\",\n      \"onMoved\",\n      \"onRemoved\",\n      \"onReplaced\",\n      \"onSelectionChanged\",\n      \"onUpdated\",\n      \"onZoomChange\"\n    ]\n  },\n  \"topSites\": {\n    \"properties\": [],\n    \"methods\": [\"get\"],\n    \"types\": [\"MostVisitedURL\"],\n    \"events\": []\n  },\n  \"tts\": {\n    \"properties\": [],\n    \"methods\": [\"getVoices\", \"isSpeaking\", \"pause\", \"resume\", \"speak\", \"stop\"],\n    \"types\": [\"TtsEvent\", \"TtsOptions\", \"TtsVoice\", \"EventType\", \"VoiceGender\"],\n    \"events\": [\"onVoicesChanged\"]\n  },\n  \"ttsEngine\": {\n    \"properties\": [],\n    \"methods\": [\"updateLanguage\", \"updateVoices\"],\n    \"types\": [\n      \"AudioBuffer\",\n      \"AudioStreamOptions\",\n      \"LanguageStatus\",\n      \"LanguageUninstallOptions\",\n      \"SpeakOptions\",\n      \"TtsClient\",\n      \"LanguageInstallStatus\",\n      \"TtsClientSource\",\n      \"VoiceGender\"\n    ],\n    \"events\": [\n      \"onInstallLanguageRequest\",\n      \"onLanguageStatusRequest\",\n      \"onPause\",\n      \"onResume\",\n      \"onSpeak\",\n      \"onSpeakWithAudioStream\",\n      \"onStop\",\n      \"onUninstallLanguageRequest\"\n    ]\n  },\n  \"types\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\"ChromeSetting\", \"ChromeSettingScope\", \"LevelOfControl\"],\n    \"events\": []\n  },\n  \"usb\": {\n    \"properties\": [],\n    \"methods\": [\n      \"bulkTransfer\",\n      \"claimInterface\",\n      \"closeDevice\",\n      \"controlTransfer\",\n      \"findDevices\",\n      \"getConfiguration\",\n      \"getConfigurations\",\n      \"getDevices\",\n      \"getUserSelectedDevices\",\n      \"interruptTransfer\",\n      \"isochronousTransfer\",\n      \"listInterfaces\",\n      \"openDevice\",\n      \"releaseInterface\",\n      \"requestAccess\",\n      \"resetDevice\",\n      \"setConfiguration\",\n      \"setInterfaceAlternateSetting\"\n    ],\n    \"types\": [\n      \"ConfigDescriptor\",\n      \"ConnectionHandle\",\n      \"ControlTransferInfo\",\n      \"Device\",\n      \"DeviceFilter\",\n      \"DevicePromptOptions\",\n      \"EndpointDescriptor\",\n      \"EnumerateDevicesAndRequestAccessOptions\",\n      \"EnumerateDevicesOptions\",\n      \"GenericTransferInfo\",\n      \"InterfaceDescriptor\",\n      \"IsochronousTransferInfo\",\n      \"TransferResultInfo\",\n      \"Direction\",\n      \"Recipient\",\n      \"RequestType\",\n      \"SynchronizationType\",\n      \"TransferType\",\n      \"UsageType\"\n    ],\n    \"events\": [\"onDeviceAdded\", \"onDeviceRemoved\"]\n  },\n  \"userScripts\": {\n    \"properties\": [],\n    \"methods\": [\n      \"configureWorld\",\n      \"execute\",\n      \"getScripts\",\n      \"getWorldConfigurations\",\n      \"register\",\n      \"resetWorldConfiguration\",\n      \"unregister\",\n      \"update\"\n    ],\n    \"types\": [\n      \"InjectionResult\",\n      \"InjectionTarget\",\n      \"RegisteredUserScript\",\n      \"ScriptSource\",\n      \"UserScriptFilter\",\n      \"UserScriptInjection\",\n      \"WorldProperties\",\n      \"ExecutionWorld\"\n    ],\n    \"events\": []\n  },\n  \"virtualKeyboard\": {\n    \"properties\": [],\n    \"methods\": [\"restrictFeatures\"],\n    \"types\": [\"FeatureRestrictions\"],\n    \"events\": []\n  },\n  \"vpnProvider\": {\n    \"properties\": [],\n    \"methods\": [\n      \"createConfig\",\n      \"destroyConfig\",\n      \"notifyConnectionStateChanged\",\n      \"sendPacket\",\n      \"setParameters\"\n    ],\n    \"types\": [\"Parameters\", \"PlatformMessage\", \"UIEvent\", \"VpnConnectionState\"],\n    \"events\": [\n      \"onConfigCreated\",\n      \"onConfigRemoved\",\n      \"onPacketReceived\",\n      \"onPlatformMessage\",\n      \"onUIEvent\"\n    ]\n  },\n  \"wallpaper\": {\n    \"properties\": [],\n    \"methods\": [\"setWallpaper\"],\n    \"types\": [\"WallpaperLayout\"],\n    \"events\": []\n  },\n  \"webAccessibleResources\": {\n    \"properties\": [],\n    \"methods\": [],\n    \"types\": [\"WebAccessibleResource\"],\n    \"events\": []\n  },\n  \"webAuthenticationProxy\": {\n    \"properties\": [],\n    \"methods\": [\n      \"attach\",\n      \"completeCreateRequest\",\n      \"completeGetRequest\",\n      \"completeIsUvpaaRequest\",\n      \"detach\"\n    ],\n    \"types\": [\n      \"CreateRequest\",\n      \"CreateResponseDetails\",\n      \"DOMExceptionDetails\",\n      \"GetRequest\",\n      \"GetResponseDetails\",\n      \"IsUvpaaRequest\",\n      \"IsUvpaaResponseDetails\"\n    ],\n    \"events\": [\n      \"onCreateRequest\",\n      \"onGetRequest\",\n      \"onIsUvpaaRequest\",\n      \"onRemoteSessionStateChange\",\n      \"onRequestCanceled\"\n    ]\n  },\n  \"webNavigation\": {\n    \"properties\": [],\n    \"methods\": [\"getAllFrames\", \"getFrame\"],\n    \"types\": [\"TransitionQualifier\", \"TransitionType\"],\n    \"events\": [\n      \"onBeforeNavigate\",\n      \"onCommitted\",\n      \"onCompleted\",\n      \"onCreatedNavigationTarget\",\n      \"onDOMContentLoaded\",\n      \"onErrorOccurred\",\n      \"onHistoryStateUpdated\",\n      \"onReferenceFragmentUpdated\",\n      \"onTabReplaced\"\n    ]\n  },\n  \"webRequest\": {\n    \"properties\": [\"MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES\"],\n    \"methods\": [\"handlerBehaviorChanged\"],\n    \"types\": [\n      \"BlockingResponse\",\n      \"RequestFilter\",\n      \"UploadData\",\n      \"FormDataItem\",\n      \"HttpHeaders\",\n      \"IgnoredActionType\",\n      \"OnAuthRequiredOptions\",\n      \"OnBeforeRedirectOptions\",\n      \"OnBeforeRequestOptions\",\n      \"OnBeforeSendHeadersOptions\",\n      \"OnCompletedOptions\",\n      \"OnErrorOccurredOptions\",\n      \"OnHeadersReceivedOptions\",\n      \"OnResponseStartedOptions\",\n      \"OnSendHeadersOptions\",\n      \"ResourceType\"\n    ],\n    \"events\": [\n      \"onActionIgnored\",\n      \"onAuthRequired\",\n      \"onBeforeRedirect\",\n      \"onBeforeRequest\",\n      \"onBeforeSendHeaders\",\n      \"onCompleted\",\n      \"onErrorOccurred\",\n      \"onHeadersReceived\",\n      \"onResponseStarted\",\n      \"onSendHeaders\"\n    ]\n  },\n  \"webviewTag\": {\n    \"properties\": [\"contentWindow\", \"contextMenus\", \"request\"],\n    \"methods\": [\n      \"addContentScripts\",\n      \"back\",\n      \"canGoBack\",\n      \"canGoForward\",\n      \"captureVisibleRegion\",\n      \"clearData\",\n      \"executeScript\",\n      \"find\",\n      \"forward\",\n      \"getAudioState\",\n      \"getProcessId\",\n      \"getUserAgent\",\n      \"getZoom\",\n      \"getZoomMode\",\n      \"go\",\n      \"insertCSS\",\n      \"isAudioMuted\",\n      \"isSpatialNavigationEnabled\",\n      \"isUserAgentOverridden\",\n      \"loadDataWithBaseUrl\",\n      \"print\",\n      \"reload\",\n      \"removeContentScripts\",\n      \"setAudioMuted\",\n      \"setSpatialNavigationEnabled\",\n      \"setUserAgentOverride\",\n      \"setZoom\",\n      \"setZoomMode\",\n      \"stop\",\n      \"stopFinding\",\n      \"terminate\"\n    ],\n    \"types\": [\n      \"ClearDataOptions\",\n      \"ClearDataTypeSet\",\n      \"ContentScriptDetails\",\n      \"ContentWindow\",\n      \"ContextMenuCreateProperties\",\n      \"ContextMenuUpdateProperties\",\n      \"ContextMenus\",\n      \"DialogController\",\n      \"DownloadPermissionRequest\",\n      \"FileSystemPermissionRequest\",\n      \"FindCallbackResults\",\n      \"FindOptions\",\n      \"FullscreenPermissionRequest\",\n      \"GeolocationPermissionRequest\",\n      \"HidPermissionRequest\",\n      \"InjectDetails\",\n      \"InjectionItems\",\n      \"LoadPluginPermissionRequest\",\n      \"MediaPermissionRequest\",\n      \"NewWindow\",\n      \"PointerLockPermissionRequest\",\n      \"SelectionRect\",\n      \"WebRequestEventInterface\",\n      \"ContextType\",\n      \"ZoomMode\"\n    ],\n    \"events\": [\n      \"close\",\n      \"consolemessage\",\n      \"contentload\",\n      \"dialog\",\n      \"exit\",\n      \"findupdate\",\n      \"loadabort\",\n      \"loadcommit\",\n      \"loadredirect\",\n      \"loadstart\",\n      \"loadstop\",\n      \"newwindow\",\n      \"permissionrequest\",\n      \"responsive\",\n      \"sizechanged\",\n      \"unresponsive\",\n      \"zoomchange\"\n    ]\n  },\n  \"windows\": {\n    \"properties\": [\"WINDOW_ID_CURRENT\", \"WINDOW_ID_NONE\"],\n    \"methods\": [\n      \"create\",\n      \"get\",\n      \"getAll\",\n      \"getCurrent\",\n      \"getLastFocused\",\n      \"remove\",\n      \"update\"\n    ],\n    \"types\": [\n      \"QueryOptions\",\n      \"Window\",\n      \"CreateType\",\n      \"WindowState\",\n      \"WindowType\"\n    ],\n    \"events\": [\"onBoundsChanged\", \"onCreated\", \"onFocusChanged\", \"onRemoved\"]\n  }\n}\n"
  },
  {
    "path": ".repo/sample-list-generator/package.json",
    "content": "{\n  \"name\": \"sample-list-generator\",\n  \"version\": \"1.0.0\",\n  \"scripts\": {\n    \"start\": \"ts-node src/index.ts\",\n    \"prepare-chrome-types\": \"ts-node src/prepare-chrome-types.ts\",\n    \"test\": \"mocha --require ts-node/register test/**/*.test.ts\"\n  },\n  \"devDependencies\": {\n    \"@types/babel__core\": \"7.20.1\",\n    \"@types/mocha\": \"10.0.1\",\n    \"@types/node-fetch\": \"2.6.4\",\n    \"@types/sinon\": \"10.0.15\",\n    \"mocha\": \"10.2.0\",\n    \"sinon\": \"15.2.0\",\n    \"ts-node\": \"10.9.1\",\n    \"typescript\": \"5.1.3\"\n  },\n  \"dependencies\": {\n    \"@babel/core\": \"7.22.5\",\n    \"node-fetch\": \"2.6.11\",\n    \"typedoc\": \"0.24.8\"\n  }\n}\n"
  },
  {
    "path": ".repo/sample-list-generator/src/constants.ts",
    "content": "export type FolderTypes = \"API_SAMPLE\" | \"FUNCTIONAL_SAMPLE\";\n\n// Define all available folders for samples\nexport const AVAILABLE_FOLDERS: { path: string, type: FolderTypes }[] = [\n  {\n    path: 'api-samples',\n    type: 'API_SAMPLE'\n  },\n  {\n    path: 'functional-samples',\n    type: 'FUNCTIONAL_SAMPLE'\n  }\n];\n\nexport const REPO_BASE_URL =\n  'https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/';\n"
  },
  {
    "path": ".repo/sample-list-generator/src/index.ts",
    "content": "import path from 'path';\nimport fs from 'fs/promises';\nimport { getAllSamples } from './libs/sample-collector';\n\nconst start = async () => {\n  const samples = await getAllSamples();\n\n  // write to extension-samples.json\n  await fs.writeFile(\n    path.join(__dirname, '../extension-samples.json'),\n    JSON.stringify(samples, null, 2)\n  );\n};\n\nstart();\n"
  },
  {
    "path": ".repo/sample-list-generator/src/libs/api-detector.ts",
    "content": "import {\n  ApiItem,\n  ApiItemWithType,\n  ApiTypeResult,\n  ExtensionApiMap\n} from '../types';\nimport * as babel from '@babel/core';\nimport { isIdentifier } from '@babel/types';\nimport fs from 'fs/promises';\nimport { getAllJsFiles } from '../utils/filesystem';\nimport { loadExtensionApis } from './api-loader';\n\nlet EXTENSION_API_MAP: ExtensionApiMap = loadExtensionApis();\n\n/**\n * Gets the type of an api call.\n * @param namespace - The namespace of the api call.\n * @param propertyName - The property name of the api call.\n * @returns The type of the api call.\n * @example\n * getApiType('tabs', 'query')\n * // returns 'method'\n */\nexport const getApiType = (\n  namespace: string,\n  propertyName: string\n): ApiTypeResult => {\n  namespace = namespace.replace(/_/g, '.');\n\n  const apiTypes = EXTENSION_API_MAP[namespace];\n  if (apiTypes) {\n    if (apiTypes.methods.includes(propertyName)) {\n      return 'method';\n    }\n    if (apiTypes.events.includes(propertyName)) {\n      return 'event';\n    }\n    if (apiTypes.properties.includes(propertyName)) {\n      return 'property';\n    }\n    if (apiTypes.types.includes(propertyName)) {\n      return 'type';\n    }\n  }\n  return 'unknown';\n};\n\n/**\n * Gets all the api calls in a sample.\n * @param sampleFolderPath - The path to the sample folder.\n * @returns A promise that resolves to an array of apis the sample uses.\n */\nexport const getApiListForSample = async (\n  sampleFolderPath: string\n): Promise<ApiItemWithType[]> => {\n  // get all js files in the folder\n  const jsFiles = await getAllJsFiles(sampleFolderPath);\n\n  const calls: ApiItemWithType[] = [];\n\n  await Promise.all(\n    jsFiles.map(async (file) => {\n      const callsFromFile = await extractApiCalls((await fs.readFile(file)).toString('utf-8'));\n      calls.push(...callsFromFile);\n    })\n  );\n\n  return uniqueItems(calls);\n};\n\n/**\n * Gets the complete API call for the member expression.\n * @param path - The path to the MemberExpression node.\n * @returns The full member expression.\n * @example\n * getFullMemberExpression(path.node)\n * // returns ['chrome', 'tabs', 'query']\n */\nexport function getFullMemberExpression(\n  path: babel.NodePath<babel.types.MemberExpression>\n): string[] {\n  const result: string[] = [];\n\n  // Include the chrome. or browser. identifier\n  if (isIdentifier(path.node.object)) {\n    result.push(path.node.object.name);\n  } else {\n    // We don't support expressions\n    return result;\n  }\n\n  while (path) {\n    if (isIdentifier(path.node.property)) {\n      result.push(path.node.property.name);\n    } else {\n      // We don't support expressions\n      break;\n    }\n\n    const parentPath = path.parentPath;\n\n    if (!parentPath || !parentPath.isMemberExpression()) {\n      break;\n    } else {\n      path = parentPath;\n    }\n  }\n\n  return result;\n}\n\n/**\n * Gets the namespace and property name of an api call.\n * @param parts - The parts of the api call.\n * @returns The namespace and property name of the api call.\n * @example\n * getApiItem(['chrome', 'tabs', 'query'])\n * // returns { namespace: 'tabs', propertyName: 'query' }\n * getApiItem(['chrome', 'devtools', 'inspectedWindow', 'eval'])\n * // returns { namespace: 'devtools.inspectedWindow', propertyName: 'eval' }\n */\nexport function getApiItem(parts: string[]): ApiItem {\n  let namespace = '';\n  let propertyName = '';\n\n  // For some apis like `chrome.devtools.inspectedWindow.eval`,\n  // the namespace is actually `devtools.inspectedWindow`.\n  // So we need to check if the first two parts combined is a valid namespace.\n  if (EXTENSION_API_MAP[`${parts[0]}.${parts[1]}`]) {\n    namespace = `${parts[0]}.${parts[1]}`;\n    propertyName = parts[2];\n  } else {\n    namespace = parts[0];\n    propertyName = parts[1];\n  }\n\n  return { namespace, propertyName };\n}\n\n/**\n * Filters an array of ApiItemWithType to remove duplicates.\n * @param array - The array of ApiItemWithType to filter.\n */\nfunction uniqueItems(array: ApiItemWithType[]) {\n  const tmp = new Set<string>();\n  return array.filter((item) => {\n    const fullApiString = `${item.namespace}.${item.propertyName}`;\n    return !tmp.has(fullApiString) && tmp.add(fullApiString);\n  });\n}\n\n/**\n * Extracts all chrome and browser api calls from a file.\n * @param script - The script string to extract api calls from.\n * @returns A promise that resolves to an array of ApiItemWithType.\n * @example\n * extractApiCalls('chrome.tabs.query({})')\n * // returns [{ type: 'method', namespace: 'tabs', propertyName: 'query' }]\n */\nexport const extractApiCalls = (script: string): Promise<ApiItemWithType[]> => {\n  return new Promise((resolve, reject) => {\n    const calls: ApiItemWithType[] = [];\n\n    babel.parse(\n      script,\n      { ast: true, compact: false },\n      (err, result) => {\n        if (err || !result) {\n          reject(err);\n          return;\n        }\n\n        babel.traverse(result, {\n          MemberExpression(path) {\n            const parts = getFullMemberExpression(path);\n\n            // not a chrome or browser api\n            if (!['chrome', 'browser'].includes(parts.shift() || '')) {\n              return;\n            }\n\n            const { namespace, propertyName } = getApiItem(parts);\n            let type = getApiType(namespace, propertyName);\n\n            // api not found\n            if (type === 'unknown') {\n              console.warn('api not found', namespace, propertyName);\n              return;\n            }\n            calls.push({ type, namespace, propertyName });\n          }\n        });\n\n        resolve(calls);\n      }\n    );\n  });\n};\n"
  },
  {
    "path": ".repo/sample-list-generator/src/libs/api-loader.ts",
    "content": "import path from 'path';\nimport fs from 'fs';\nimport type { ExtensionApiMap } from '../types';\nimport { isFileExistsSync } from '../utils/filesystem';\n\nexport const loadExtensionApis = (): ExtensionApiMap => {\n  const filePath = path.join(__dirname, '../../extension-apis.json');\n\n  // check if extension-apis.json exists\n  if (!isFileExistsSync(filePath)) {\n    console.error(\n      'extension-apis.json does not exist. Please run \"npm run prepare-chrome-types\" first.'\n    );\n    process.exit(1);\n  }\n\n  let data = fs.readFileSync(filePath, 'utf8');\n  const apiMap = JSON.parse(data);\n\n  // Due to the specific implementation of this API, we need to manually add it\n  // to the list of APIs recognised by the sample list generator.\n  apiMap['aiOriginTrial.languageModel'] = {\n    properties: [],\n    methods: ['create', 'capabilities', 'params', 'availability'],\n    types: [],\n    events: []\n  };\n\n  return apiMap;\n};\n"
  },
  {
    "path": ".repo/sample-list-generator/src/libs/sample-collector.ts",
    "content": "import path from 'path';\nimport fs from 'fs/promises';\nimport { AVAILABLE_FOLDERS, REPO_BASE_URL } from '../constants';\nimport { getApiListForSample } from './api-detector';\nimport type { AvailableFolderItem, SampleItem } from '../types';\nimport { getBasePath, isDirectory, isFileExists } from '../utils/filesystem';\nimport { getManifest } from '../utils/manifest';\n\nexport const getAllSamples = async () => {\n  let samples: SampleItem[] = [];\n\n  // loop through all available folders\n  // e.g. api-samples, functional-samples\n  for (let samplesFolder of AVAILABLE_FOLDERS) {\n    const currentSamples = await getSamples(\n      samplesFolder.path,\n      samplesFolder.type\n    );\n    samples.push(...currentSamples);\n  }\n\n  return samples;\n};\n\nconst getSamples = async (\n  currentRootFolderPath: string,\n  sampleType: AvailableFolderItem['type']\n): Promise<SampleItem[]> => {\n  const samples: SampleItem[] = [];\n  const basePath = getBasePath();\n\n  // get all contents in the folder\n  const contents = await fs.readdir(path.join(basePath, currentRootFolderPath));\n\n  for (let content of contents) {\n    const currentPath = path.join(basePath, currentRootFolderPath, content);\n\n    // if content is not a folder, skip\n    if (!(await isDirectory(currentPath))) {\n      continue;\n    }\n\n    const manifestPath = path.join(currentPath, 'manifest.json');\n    // check if manifest.json exists\n    const manifestExists = await isFileExists(manifestPath);\n    if (manifestExists) {\n      // get manifest metadata\n      const manifestData = await getManifest(manifestPath);\n\n      // add to samples\n      samples.push({\n        type: sampleType,\n        name: content,\n        repo_link: new URL(\n          `${REPO_BASE_URL}${currentPath.replace(basePath, '')}`\n        ).toString(),\n        apis: await getApiListForSample(currentPath),\n        title: manifestData.name || content,\n        description: manifestData.description || '',\n        permissions: manifestData.permissions || []\n      });\n    } else {\n      // if manifest.json does not exist, loop through all folders in current folder\n      const currentSamples = await getSamples(\n        path.join(currentRootFolderPath, content),\n        sampleType\n      );\n      samples.push(...currentSamples);\n    }\n  }\n  return samples;\n};\n"
  },
  {
    "path": ".repo/sample-list-generator/src/prepare-chrome-types.ts",
    "content": "import fetch from 'node-fetch';\nimport path from 'path';\nimport fs from 'fs/promises';\nimport { ExtensionApiMap } from './types';\nimport { ReflectionKind } from 'typedoc';\n\n// Bucket used to store processed types data\nconst STORAGE_BUCKET = process.env.STORAGE_BUCKET;\n\n// Fetch the latest version of the chrome types from storage\nconst fetchChromeTypes = async (): Promise<Record<string, any>> => {\n  if (!STORAGE_BUCKET) {\n    throw new Error('The STORAGE_BUCKET environment variable must be set.');\n  }\n\n  console.log('Fetching chrome types...');\n\n  const response = await fetch(\n    `https://storage.googleapis.com/download/storage/v1/b/${STORAGE_BUCKET}/o/chrome-types.json?alt=media`\n  );\n  const chromeTypes = await response.json();\n  return chromeTypes;\n};\n\nconst run = async () => {\n  const result: ExtensionApiMap = {};\n\n  const chromeTypes = await fetchChromeTypes();\n\n  for (const [chromeApiKey, chromeApiDetails] of Object.entries(chromeTypes)) {\n    const apiDetails: ExtensionApiMap[string] = {\n      properties: [],\n      methods: [],\n      types: [],\n      events: []\n    };\n\n    for (let property of chromeApiDetails._type.properties) {\n      const name = property.name as string;\n\n      // check property type\n      let propertyType = 'types';\n      if (property.kind & ReflectionKind.VariableOrProperty) {\n        propertyType = 'properties';\n      }\n      if (\n        property.type?.type === 'reference' &&\n        ['CustomChromeEvent', 'events.Event', 'Event'].includes(\n          property.type.name\n        )\n      ) {\n        propertyType = 'events';\n      }\n      if (property.signatures) {\n        propertyType = 'methods';\n      }\n\n      apiDetails[propertyType].push(name);\n    }\n\n    result[chromeApiKey] = apiDetails;\n  }\n\n  console.log('Writing to file...');\n  await fs.writeFile(\n    path.join(__dirname, '../extension-apis.json'),\n    JSON.stringify(\n      {\n        _comment:\n          'This file is autogenerated by running `npm run prepare-chrome-types`, do not edit.',\n        ...result\n      },\n      null,\n      2\n    )\n  );\n  console.log('Done!');\n};\n\nrun();\n"
  },
  {
    "path": ".repo/sample-list-generator/src/types.ts",
    "content": "import type { FolderTypes } from './constants';\n\nexport interface ApiItem {\n  namespace: string;\n  propertyName: string;\n}\n\nexport interface ApiItemWithType extends ApiItem {\n  type: ApiTypeResult;\n}\n\nexport interface ManifestData {\n  [key: string]: string;\n  name: string;\n  description: string;\n  permissions: string[];\n}\n\nexport interface LocaleData {\n  [key: string]: {\n    message: string;\n    description: string;\n  };\n}\n\nexport type SampleItem = {\n  type: FolderTypes;\n  name: string;\n  repo_link: string;\n  apis: ApiItem[];\n  title: string;\n  description: string;\n  permissions: string[];\n};\n\nexport interface AvailableFolderItem {\n  path: string;\n  type: FolderTypes;\n}\n\nexport type ApiTypeResult =\n  | 'event'\n  | 'method'\n  | 'property'\n  | 'type'\n  | 'unknown';\n\nexport type ExtensionApiMap = Record<string, Record<string, string[]>>\n"
  },
  {
    "path": ".repo/sample-list-generator/src/utils/filesystem.ts",
    "content": "import fs from 'fs/promises';\nimport { accessSync } from 'fs';\nimport path from 'path';\n\nexport const getAllFiles = async (dir: string): Promise<string[]> => {\n  const result: string[] = [];\n\n  for (const file of await fs.readdir(dir)) {\n    const filePath = path.join(dir, file);\n    const stats = await fs.stat(filePath);\n\n    if (stats.isFile()) {\n      result.push(filePath);\n    } else if (stats.isDirectory()) {\n      if (file === \"node_modules\") continue;\n      result.push(...(await getAllFiles(filePath)));\n    }\n  }\n\n  return result;\n};\n\nexport const getAllJsFiles = async (dir: string): Promise<string[]> => {\n  const allFiles = await getAllFiles(dir);\n  return allFiles.filter((file) =>\n    file.endsWith('.js')\n  );\n}\n\nexport const isDirectory = async (path: string): Promise<boolean> => {\n  return (await fs.stat(path)).isDirectory()\n}\n\nexport const isFileExists = async (filePath: string): Promise<boolean> => {\n  try {\n    await fs.access(filePath);\n    return true;\n  } catch {\n    return false;\n  }\n};\n\nexport const isFileExistsSync = (filePath: string): boolean => {\n  try {\n    accessSync(filePath);\n    return true;\n  } catch {\n    return false;\n  }\n};\n\nexport const getBasePath = (): string => {\n  return path.join(__dirname, '../../../../');\n};\n"
  },
  {
    "path": ".repo/sample-list-generator/src/utils/manifest.ts",
    "content": "import fs from 'fs/promises';\nimport { dirname } from 'path';\nimport { ManifestData, LocaleData } from '../types';\nconst localeRegex = /__MSG_([^_]*)__/\n\nfunction usesLocaleFiles(obj: object): boolean {\n  // recursively check if any value in a supplied object\n  // is a string that starts with __MSG_. If found, it \n  // means that the extension uses locale files.\n  return Object.values(obj).some((value) => {\n    if (Object.prototype.toString.call(value) === '[object Object]') {\n      return usesLocaleFiles(value);\n    }\n    return typeof value === 'string' && value.startsWith('__MSG_')\n  });\n}\n\nexport const getManifest = async (\n  manifestPath: string\n): Promise<ManifestData> => {\n  const manifest = await fs.readFile(manifestPath, 'utf8');\n  const parsedManifest = JSON.parse(manifest);\n\n  if (usesLocaleFiles(parsedManifest)) {\n    const directory = dirname(manifestPath);\n    const localeFile: string = await fs.readFile(`${directory}/_locales/en/messages.json`, 'utf8')\n    const localeData: LocaleData = JSON.parse(localeFile);\n\n    for (const [key, value] of Object.entries(parsedManifest)) {\n      if (typeof value === 'string' && value.startsWith('__MSG_')) {\n        const localeKey: string | undefined = value.match(localeRegex)?.[1];\n\n        if (localeKey) {\n          const localeKeyData = localeData[localeKey]\n          const localeMessage: string = localeKeyData?.message;\n\n          parsedManifest[key] = localeMessage;\n        }\n      }\n    }\n  }\n\n  return parsedManifest;\n};\n"
  },
  {
    "path": ".repo/sample-list-generator/test/api-detector/api-detector.test.ts",
    "content": "import { describe, it, beforeEach } from 'mocha';\nimport assert from 'assert';\nimport sinon from 'sinon';\nimport {\n  getApiType,\n  extractApiCalls,\n  getApiItem\n} from '../../src/libs/api-detector';\n\ndescribe('API Detector', function () {\n  beforeEach(function () {\n    sinon.reset();\n  });\n\n  describe('extractApiCalls()', function () {\n    it('should return correct api list for sample file (normal)', async function () {\n      const file = `\n        let a = 1;\n        let b = chrome.action.getBadgeText();\n        let c = chrome.action.setBadgeText(a);\n\n        chrome.action.onClicked.addListener(function (tab) {\n          console.log('clicked');\n        });\n\n        alert(chrome.contextMenus.ACTION_MENU_TOP_LEVEL_LIMIT)\n      `;\n      const result = await extractApiCalls(file);\n      assert.deepEqual(result, [\n        {\n          namespace: 'action',\n          propertyName: 'getBadgeText',\n          type: 'method'\n        },\n        {\n          namespace: 'action',\n          propertyName: 'setBadgeText',\n          type: 'method'\n        },\n        {\n          namespace: 'action',\n          propertyName: 'onClicked',\n          type: 'event'\n        },\n        {\n          namespace: 'contextMenus',\n          propertyName: 'ACTION_MENU_TOP_LEVEL_LIMIT',\n          type: 'property'\n        }\n      ]);\n    });\n\n    it('should return correct api list for sample file (storage)', async function () {\n      const file = `\n        let b = await chrome.storage.local.get();\n        let c = await chrome.storage.sync.get();\n        let d = await chrome.storage.managed.get();\n        let e = await chrome.storage.session.get();\n        let f = await chrome.storage.onChanged.addListener();\n      `;\n      const result = await extractApiCalls(file);\n      assert.deepEqual(result, [\n        {\n          namespace: 'storage',\n          propertyName: 'local',\n          type: 'property'\n        },\n        {\n          namespace: 'storage',\n          propertyName: 'sync',\n          type: 'property'\n        },\n        {\n          namespace: 'storage',\n          propertyName: 'managed',\n          type: 'property'\n        },\n        {\n          namespace: 'storage',\n          propertyName: 'session',\n          type: 'property'\n        },\n        {\n          namespace: 'storage',\n          propertyName: 'onChanged',\n          type: 'event'\n        }\n      ]);\n    });\n\n    it('should return correct api list for sample file (async)', async function () {\n      const file = `\n        let a = 1;\n        let b = await chrome.action.getBadgeText();\n        await chrome.action.setBadgeText(a);\n      `;\n      const result = await extractApiCalls(file);\n      assert.deepEqual(result, [\n        {\n          namespace: 'action',\n          propertyName: 'getBadgeText',\n          type: 'method'\n        },\n        {\n          namespace: 'action',\n          propertyName: 'setBadgeText',\n          type: 'method'\n        }\n      ]);\n    });\n\n    it('should return correct api list for sample file (special case)', async function () {\n      const file = `\n        let a = 1;\n        let b = await chrome.system.cpu.getInfo();\n        chrome.devtools.network.onRequestFinished.addListener(\n          function(request) {\n            if (request.response.bodySize > 40*1024) {\n              chrome.devtools.inspectedWindow.eval(\n                  'console.log(\"Large image: \" + unescape(\"' +\n                  escape(request.request.url) + '\"))');\n            }\n          }\n        );\n      `;\n\n      const result = await extractApiCalls(file);\n      assert.deepEqual(result, [\n        {\n          namespace: 'system.cpu',\n          propertyName: 'getInfo',\n          type: 'method'\n        },\n        {\n          namespace: 'devtools.network',\n          propertyName: 'onRequestFinished',\n          type: 'event'\n        },\n        {\n          namespace: 'devtools.inspectedWindow',\n          propertyName: 'eval',\n          type: 'method'\n        }\n      ]);\n    });\n  });\n\n  describe('getApiType()', function () {\n    it('should return correct type of api in normal case', function () {\n      let apiType = getApiType('action', 'getBadgeText');\n      assert.equal(apiType, 'method');\n    });\n\n    it('should return correct type of api in special case', function () {\n      let apiType = getApiType('devtools.network', 'onNavigated');\n      assert.equal(apiType, 'event');\n    });\n\n    it('should return unknown when api not found', function () {\n      let apiType = getApiType('action', '123');\n      assert.equal(apiType, 'unknown');\n    });\n  });\n\n  describe('getApiItem()', function () {\n    it('should return correct api item', function () {\n      let apiItem = getApiItem(['action', 'getBadgeText']);\n      assert.deepEqual(apiItem, {\n        namespace: 'action',\n        propertyName: 'getBadgeText'\n      });\n    });\n\n    it('should return correct api item (storage)', function () {\n      let apiItem = getApiItem(['storage', 'sync', 'get']);\n      assert.deepEqual(apiItem, {\n        namespace: 'storage',\n        propertyName: 'sync'\n      });\n\n      apiItem = getApiItem(['storage', 'sync', 'onChanged']);\n      assert.deepEqual(apiItem, {\n        namespace: 'storage',\n        propertyName: 'sync'\n      });\n\n      apiItem = getApiItem(['storage', 'onChanged']);\n      assert.deepEqual(apiItem, {\n        namespace: 'storage',\n        propertyName: 'onChanged'\n      });\n    });\n\n    it('should return correct api item (special case)', function () {\n      let apiItem = getApiItem([\n        'devtools',\n        'network',\n        'onRequestFinished',\n        'addListener'\n      ]);\n      assert.deepEqual(apiItem, {\n        namespace: 'devtools.network',\n        propertyName: 'onRequestFinished'\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# How to Contribute\n\nWe'd love to accept your patches and contributions to this project.\n\n## Before you begin\n\n### Sign our Contributor License Agreement\n\nContributions to this project must be accompanied by a\n[Contributor License Agreement](https://cla.developers.google.com/about) (CLA).\nYou (or your employer) retain the copyright to your contribution; this simply\ngives us permission to use and redistribute your contributions as part of the\nproject.\n\nIf you or your current employer have already signed the Google CLA (even if it\nwas for a different project), you probably don't need to do it again.\n\nVisit <https://cla.developers.google.com/> to see your current agreements or to\nsign a new one.\n\n### Review our Community Guidelines\n\nThis project follows [Google's Open Source Community\nGuidelines](https://opensource.google/conduct/).\n\n## Contribution process\n\n### Create an issue first\n\nBefore adding a new sample, [create an issue first](https://github.com/GoogleChrome/chrome-extensions-samples/issues/new).\nDescribe why this sample is needed and how you plan to implement it. Only once\nyou've got the approval from one of the maintainers start working on a PR. Non\ntrivial PRs without an approved issue will be rejected.\n\n### Code Reviews\n\nAll submissions, including submissions by project members, require review. We\nuse GitHub pull requests for this purpose. Consult\n[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more\ninformation on using pull requests.\n\n### Setting up your Environment\n\nIf you want to contribute to this repository, you need to first [create your own fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo).\nAfter forking chrome-extensions-samples to your own Github account, run the\nfollowing steps to get started:\n\n```sh\n# clone your fork to your local machine\ngit clone https://github.com/your-fork/chrome-extensions-samples.git\n\ncd chrome-extensions-samples\n\n# install dependencies\nnpm install\n```\n\n### Writing a README\n\nAll new code samples or samples updated from Manifest V2 should include a\nREADME file. Please copy the [provided template](./README-template.md) into\nyour sample's folder and follow the instructions therein.\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README-template.md",
    "content": "_To create a README for your sample_\n\n1. _Copy this file to your sample folder._\n1. _Enter the requested information below._\n1. _Delete these instructions._\n\n_For API samples use the name of the API. For example, a sample about the `chrome.declarativeNetRequest` would simply be called \"chrome.declarativeNetRequest\". (Do not use special formatting in headings.) For functional samples, the title should be what the sample demonstrates_\n\n# Title\n\n_Describe what the sample demonstrates. If this is an API sample, link to the API._\n\nThis sample demonstrates ...\n\n## Overview\n\n_Describe how the sample demonstrates the API or use case and briefly describe how to use it._\n\n## Implementation Notes\n\n_Add any information that doesn't fit elsewhere in the README._\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. _Add the rest of the instructions here_\n"
  },
  {
    "path": "README.md",
    "content": "# Chrome Extensions samples\n\nOfficial samples for Chrome Extensions and the Chrome Apps platform. (Chrome Apps are deprecated. Learn more [on the Chromium blog](https://blog.chromium.org/2020/08/changes-to-chrome-app-support-timeline.html)).\n\nFor more information on extensions, see [Chrome Developers](https://developer.chrome.com).\n\n## Explore samples\n\nThe directory structure is as follows:\n\n- [api-samples/](api-samples/) - extensions focused on a single API package\n- [functional-samples/](functional-samples/) - full featured extensions spanning multiple API packages\n- [\\_archive/apps/](_archive/apps/) - deprecated Chrome Apps platform (not listed below)\n- [\\_archive/mv2/](_archive/mv2/) - resources for manifest version 2\n\nYou can also use the [Samples](https://developer.chrome.com/docs/extensions/samples/) page to discover extensions by type, permissions, and extension API.\n\n## Installation\n\nTo experiment with these samples, please clone this repo and use 'Load Unpacked Extension'.\nRead more on [Development Basics](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n\n## Contributing\n\nPlease see [the CONTRIBUTING file](/CONTRIBUTING.md) for information on contributing to the `chrome-extensions-samples` project.\n\n## License\n\n`chrome-extensions-samples` are authored by Google and are licensed under the [Apache License, Version 2.0](/LICENSE).\n"
  },
  {
    "path": "_archive/apps/README.md",
    "content": "# Chrome Apps samples\n\nOfficial samples for deprecated Chrome Apps platform. If you want to learn about the platform, you can:\n\n1. look at the source code of the samples below. Most samples have a \"Try it now\" button that allows you to install and play with it.\n2. read the [official docs](http://developer.chrome.com/apps)\n\nIf you have questions, [search](http://stackoverflow.com/questions/tagged/google-chrome-app) or [ask at StackOverflow](http://stackoverflow.com/questions/ask?tags=google-chrome-app) (observe the google-chrome-app tag) or join the [Chromium Apps](https://groups.google.com/a/chromium.org/forum/?fromgroups#!forum/chromium-apps) Google group.\n\n\n# Samples\n\n<!-- sample_table_autogen_start THIS TABLE IS AUTOGENERATED! PLEASE, DON'T EDIT IT DIRECTLY! -->\n\nSample | API or feature | Link\n--- | --- |:---:\n<a name=\"_sample_analytics\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/analytics\">analytics</a> | <a href=\"#_feature_storage\">storage</a><br> <a href=\"#mobile-support\">ios</a><br> <a href=\"#mobile-support\">android</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/anfhlhgdnbpnglngmblhkdifdbcepjce\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_appengine-channelapi_app\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/appengine-channelapi/app\">appengine-channelapi/app</a> | <a href=\"#_feature_webview\">webview</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/alieplnmdkoekpkepkfgickpmhhabfkl\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_appsquare\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/appsquare\">appsquare</a> | <a href=\"#_feature_geolocation\">geolocation</a><br> <a href=\"#_feature_identity\">identity</a><br> <a href=\"#_feature_storage\">storage</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/loimmcmmgnhkbppokdpfhlccebcpicld\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_appview_embedded-app\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/appview/embedded-app\">appview/embedded-app</a> | <a href=\"#_feature_getUserMedia\">getUserMedia</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/mighjnlldblaiimoaidiggecdkobklfe\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_appview_host-app\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/appview/host-app\">appview/host-app</a> | <a href=\"#_feature_appview\">appview</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/gkmjlnhjcdognmniiadfdhdlgdocngda\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_blink1\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/blink1\">blink1</a> | <a href=\"#_feature_hid\">hid</a><br> <a href=\"#_feature_usb\">usb</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/kcpjgiicabigbjejdjnkflkdkjknkdch\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_bluetooth-samples_battery-service-demo\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/bluetooth-samples/battery-service-demo\">bluetooth-samples/battery-service-demo</a> | <a href=\"#_feature_bluetooth\">bluetooth</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/kllncpgahapecnfkhefffabcemaknamh\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_bluetooth-samples_device-info-demo\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/bluetooth-samples/device-info-demo\">bluetooth-samples/device-info-demo</a> | <a href=\"#_feature_bluetooth\">bluetooth</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/dblimghcclaakknbpajckcamddhjaaai\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_bluetooth-samples_heart-rate-sensor\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/bluetooth-samples/heart-rate-sensor\">bluetooth-samples/heart-rate-sensor</a> | <a href=\"#_feature_bluetooth\">bluetooth</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/nmlcgjldnboapnjdmllfcdenlljfjanm\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_calculator\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/calculator\">calculator</a> | <a href=\"#_feature_clipboard\">clipboard</a><br> <a href=\"#mobile-support\">ios</a><br> <a href=\"#mobile-support\">android</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/pelimflkpjiicnajdjcmekpioacmahkh\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_camera-capture\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/camera-capture\">camera-capture</a> | <a href=\"#_feature_getUserMedia\">getUserMedia</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ilefapmpngkdnnllcnlcjffipbolhklf\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_clock\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/clock\">clock</a> | <a href=\"#_feature_framelessWindows\">framelessWindows</a><br> <a href=\"#_feature_geolocation\">geolocation</a><br> <a href=\"#_feature_richNotifications\">richNotifications</a><br> <a href=\"#_feature_storage\">storage</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/lhfiglpmnendbchimlikaeachppfonmm\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_context-menu\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/context-menu\">context-menu</a> | <a href=\"#_feature_contextMenu\">contextMenu</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/biknlgbccocnocjfclpedecpgopjokik\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_dart\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/dart\">dart</a> | <a href=\"#_feature_dart\">dart</a><br> <a href=\"#mobile-support\">ios</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/pcbbhbaibaphjlbaoahmahgmncbdkeli\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_desktop-capture\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/desktop-capture\">desktop-capture</a> | <a href=\"#_feature_desktopCapture\">desktopCapture</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/mhkidniocjdaiddjckopkigjmjbadfji\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_dialog-element\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/dialog-element\">dialog-element</a> |   | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/mikhnkopoddcomlgmcjgfnaccjhibiec\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_diff\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/diff\">diff</a> | <a href=\"#_feature_clipboard\">clipboard</a><br> <a href=\"#_feature_fileSystem\">fileSystem</a><br> <a href=\"#_feature_storage\">storage</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/neifiophhpiohjlhiohlhlekkfokcepk\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_filesystem-access\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/filesystem-access\">filesystem-access</a> | <a href=\"#_feature_fileSystem\">fileSystem</a><br> <a href=\"#_feature_storage\">storage</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ehbhjpchdgepkgjhfkhpkjdbnljedllm\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_frameless-window\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/frameless-window\">frameless-window</a> | <a href=\"#_feature_framelessWindows\">framelessWindows</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hjjdaddngnaofnfjpajdcbdmkegiakec\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_gcm-notifications\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/gcm-notifications\">gcm-notifications</a> | <a href=\"#_feature_gcm\">gcm</a><br> <a href=\"#_feature_richNotifications\">richNotifications</a><br> <a href=\"#_feature_storage\">storage</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/gpededflkpcoehfjpdecdkoiagajloin\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_gdrive\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/gdrive\">gdrive</a> | <a href=\"#_feature_framelessWindows\">framelessWindows</a><br> <a href=\"#_feature_identity\">identity</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/jpabeekbjicamajjcfejnochhmlbpgjh\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_github-auth\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/github-auth\">github-auth</a> | <a href=\"#_feature_identity\">identity</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/laolmfhjaobpboigjfbclcphckmjodlp\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_hello-world\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/hello-world\">hello-world</a> |  <a href=\"#mobile-support\">ios</a><br> <a href=\"#mobile-support\">android</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/nmfpplkdkcbhediajmbhljkafnlahcda\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_hello-world-sync\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/hello-world-sync\">hello-world-sync</a> | <a href=\"#_feature_storage\">storage</a><br> <a href=\"#mobile-support\">ios</a><br> <a href=\"#mobile-support\">android</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ajjcafkkflbcealbcfjajolnkogffgcb\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_hid\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/hid\">hid</a> | <a href=\"#_feature_hid\">hid</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ohndmecdhlgohpibepbboddcoecomnpc\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_identity\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/identity\">identity</a> | <a href=\"#_feature_identity\">identity</a><br> <a href=\"#mobile-support\">android</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/oficlfehfenioickohognhdhmmcpceil\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_image-edit\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/image-edit\">image-edit</a> | <a href=\"#_feature_fileSystem\">fileSystem</a><br> <a href=\"#_feature_storage\">storage</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/foibnkkcggahkmckladbmgkajodpcjfh\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_instagram-auth\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/instagram-auth\">instagram-auth</a> | <a href=\"#_feature_identity\">identity</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/baaenjnmlaejajnalldcecpdafeggelb\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_io2012-presentation\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/io2012-presentation\">io2012-presentation</a> | <a href=\"#_feature_framelessWindows\">framelessWindows</a><br> <a href=\"#_feature_getUserMedia\">getUserMedia</a><br> <a href=\"#_feature_serial\">serial</a><br> <a href=\"#_feature_storage\">storage</a><br> <a href=\"#_feature_webview\">webview</a><br>  | -\n<a name=\"_sample_io2012-presentation_helloworld\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/io2012-presentation/helloworld\">io2012-presentation/helloworld</a> |   | -\n<a name=\"_sample_io2012-presentation_servo\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/io2012-presentation/servo\">io2012-presentation/servo</a> | <a href=\"#_feature_getUserMedia\">getUserMedia</a><br> <a href=\"#_feature_serial\">serial</a><br>  | -\n<a name=\"_sample_ioio\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/ioio\">ioio</a> | <a href=\"#_feature_bluetooth\">bluetooth</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hknlnnbpihcamokfeggmahjgldbcpkof\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_keyboard-handler\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/keyboard-handler\">keyboard-handler</a> |   | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/pcbbaldjljokfnnkphllabnpolciapjc\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_managed-in-app-payments\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/managed-in-app-payments\">managed-in-app-payments</a> | <a href=\"#_feature_in-app-payments\">in-app-payments</a><br>  | -\n<a name=\"_sample_manga-cam\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/manga-cam\">manga-cam</a> | <a href=\"#_feature_framelessWindows\">framelessWindows</a><br> <a href=\"#_feature_getUserMedia\">getUserMedia</a><br> <a href=\"#_feature_syncFileSystem\">syncFileSystem</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/cnehcenehakkickcnoiaemcpjpaigmbb\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_mdns-browser\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/mdns-browser\">mdns-browser</a> | <a href=\"#_feature_framelessWindows\">framelessWindows</a><br> <a href=\"#_feature_sockets\">sockets</a><br> <a href=\"#_feature_systemInfo\">systemInfo</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/kipighjpklofchgbdgclfaoccdlghidp\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_media-gallery\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/media-gallery\">media-gallery</a> | <a href=\"#_feature_mediaGallery\">mediaGallery</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/lidepfgfmameopopgagobnpndcnfgbnk\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_messaging_app1\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/messaging/app1\">messaging/app1</a> | <a href=\"#_feature_messaging\">messaging</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/mcfaknmahgbmjlbondlciokappnnjbnf\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_messaging_app2\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/messaging/app2\">messaging/app2</a> | <a href=\"#_feature_messaging\">messaging</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hdligeegpimhdjepakblhneiekccbhol\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_messaging_extension\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/messaging/extension\">messaging/extension</a> | <a href=\"#_feature_messaging\">messaging</a><br> <a href=\"#_feature_richNotifications\">richNotifications</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ihhkahhkmiddbnfhlglocakcdfbgddkj\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_mini-code-edit\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/mini-code-edit\">mini-code-edit</a> | <a href=\"#_feature_commands\">commands</a><br> <a href=\"#_feature_contextMenu\">contextMenu</a><br> <a href=\"#_feature_fileSystem\">fileSystem</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/inbjbbebnhailhhkfaaokegkfjlmgabb\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_multicast\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/multicast\">multicast</a> | <a href=\"#_feature_framelessWindows\">framelessWindows</a><br> <a href=\"#_feature_messaging\">messaging</a><br> <a href=\"#_feature_sockets\">sockets</a><br> <a href=\"#_feature_storage\">storage</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/bnheobjndkaipbloffigkiddhcbblihl\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_one-time-payment\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/one-time-payment\">one-time-payment</a> | <a href=\"#_feature_identity\">identity</a><br> <a href=\"#_feature_storage\">storage</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ebcgmmcbgnpoclkoibogeiokfdmjbbob\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_optional-permissions\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/optional-permissions\">optional-permissions</a> | <a href=\"#_feature_optionalPermissions\">optionalPermissions</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ggkojffeaocnfigijnfbnliopcilipgg\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_parrot-ar-drone\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/parrot-ar-drone\">parrot-ar-drone</a> | <a href=\"#_feature_old_sockets\">old_sockets</a><br> <a href=\"#_feature_sockets\">sockets</a><br> <a href=\"#mobile-support\">android</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/lhdfniaagbjbipjmgfbnlbcmlbcgklkh\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_platform-title\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/platform-title\">platform-title</a> | <a href=\"#_feature_framelessWindows\">framelessWindows</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/gdpimhplfcmbiakglpomcdcchbmgfiaj\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_printing\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/printing\">printing</a> | <a href=\"#_feature_print\">print</a><br> <a href=\"#_feature_storage\">storage</a><br> <a href=\"#_feature_systemInfo\">systemInfo</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/eahldfpkmibbaajaoeifhjeehfgdagdm\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_restarted-demo\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/restarted-demo\">restarted-demo</a> | <a href=\"#_feature_storage\">storage</a><br> <a href=\"#mobile-support\">ios</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ljngdccbopfaompkjfhepllagnijbdne\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_rich-notifications\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/rich-notifications\">rich-notifications</a> | <a href=\"#_feature_richNotifications\">richNotifications</a><br> <a href=\"#mobile-support\">android</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/cndmbddaappldijonoekcdfdlhemhejm\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_sandbox\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/sandbox\">sandbox</a> | <a href=\"#_feature_sandbox\">sandbox</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ipchbpppeafbpnmnjbkljpfhkkiaeikd\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_sandboxed-content\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/sandboxed-content\">sandboxed-content</a> | <a href=\"#_feature_sandbox\">sandbox</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/gaaeficfcmngmogaejhikdnkdijlpgec\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_serial-control-signals\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/serial-control-signals\">serial-control-signals</a> | <a href=\"#_feature_serial\">serial</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/gmlopmidlcfikepbnklkochchhehjpak\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_serial_adkjs_app\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/serial/adkjs/app\">serial/adkjs/app</a> | <a href=\"#_feature_serial\">serial</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ieoiddehfkbacdideciijbdjfjegmpjo\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_serial_espruino\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/serial/espruino\">serial/espruino</a> | <a href=\"#_feature_serial\">serial</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ghbnaccmkndoembcopnaklidmocbdkfp\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_serial_ledtoggle\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/serial/ledtoggle\">serial/ledtoggle</a> | <a href=\"#_feature_serial\">serial</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/bdiclhdalonemjdeeaglackjgdboboem\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_servo\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/servo\">servo</a> | <a href=\"#_feature_getUserMedia\">getUserMedia</a><br> <a href=\"#_feature_serial\">serial</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/lhedgapiolhajjkgokaplenafmdppmak\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_storage\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/storage\">storage</a> |   | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/bpncolcpekidijienghhkibflikohggn\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_syncfs-editor\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/syncfs-editor\">syncfs-editor</a> | <a href=\"#_feature_syncFileSystem\">syncFileSystem</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ccphiekjjhfnhbmpcbmkmjjhbfhlijkc\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_systemInfo\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/systemInfo\">systemInfo</a> | <a href=\"#_feature_systemInfo\">systemInfo</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/lfkebofdngpbnooppdhiibpdpepgjoch\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_tasks\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/tasks\">tasks</a> | <a href=\"#_feature_identity\">identity</a><br> <a href=\"#mobile-support\">android</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/tasks-sample-using-gapi/licakmgdnppmfjlkgijcbnobnkoaegko\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_tcpserver\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/tcpserver\">tcpserver</a> | <a href=\"#_feature_sockets\">sockets</a><br> <a href=\"#_feature_systemInfo\">systemInfo</a><br> <a href=\"#_feature_webview\">webview</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ahlcocbkjpjkobcdpjcobmibmpbeecpg\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_telnet\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/telnet\">telnet</a> | <a href=\"#_feature_sockets\">sockets</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ebckmolcafdmfjbkmamhoacnmmkiohpe\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_text-editor\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/text-editor\">text-editor</a> | <a href=\"#_feature_clipboard\">clipboard</a><br> <a href=\"#_feature_fileSystem\">fileSystem</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/jkgbibkjioaefdopcdbhjehefhajgadh\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_todomvc\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/todomvc\">todomvc</a> | <a href=\"#_feature_alarms\">alarms</a><br> <a href=\"#_feature_fileSystem\">fileSystem</a><br> <a href=\"#_feature_richNotifications\">richNotifications</a><br> <a href=\"#_feature_storage\">storage</a><br> <a href=\"#_feature_syncFileSystem\">syncFileSystem</a><br> <a href=\"#mobile-support\">android</a><br> | -\n<a name=\"_sample_tts\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/tts\">tts</a> | <a href=\"#_feature_tts\">tts</a><br>  | -\n<a name=\"_sample_udp\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/udp\">udp</a> | <a href=\"#_feature_sockets\">sockets</a><br> <a href=\"#mobile-support\">ios</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/okhdmjejphblookgnkabaoaalhcoobec\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_url-handler\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/url-handler\">url-handler</a> | <a href=\"#_feature_storage\">storage</a><br> <a href=\"#_feature_webview\">webview</a><br>  | -\n<a name=\"_sample_usb-label-printer\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/usb-label-printer\">usb-label-printer</a> | <a href=\"#_feature_fileSystem\">fileSystem</a><br> <a href=\"#_feature_getUserMedia\">getUserMedia</a><br> <a href=\"#_feature_optionalPermissions\">optionalPermissions</a><br> <a href=\"#_feature_usb\">usb</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/fgnncpfphbgfchijmoopegkdhihegfla\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_usb_device-info\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/usb/device-info\">usb/device-info</a> | <a href=\"#_feature_usb\">usb</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/igkmggljimacfdfalpeelenjeicmfnll\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_usb_knob\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/usb/knob\">usb/knob</a> | <a href=\"#_feature_optionalPermissions\">optionalPermissions</a><br> <a href=\"#_feature_usb\">usb</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/npiachjbcianljljdlckbnkilpnddnfn\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_weather\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/weather\">weather</a> | <a href=\"#_feature_geolocation\">geolocation</a><br> <a href=\"#_feature_storage\">storage</a><br> <a href=\"#mobile-support\">ios</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hfgmgghdkhgcklddhfefhdhcpkpmikhi\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_web-store\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/web-store\">web-store</a> | <a href=\"#_feature_fileSystem\">fileSystem</a><br> <a href=\"#_feature_identity\">identity</a><br> <a href=\"#_feature_storage\">storage</a><br> <a href=\"#_feature_webstore\">webstore</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ndgidogppopohjpghapeojgoehfmflab\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_webgl-pointer-lock\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webgl-pointer-lock\">webgl-pointer-lock</a> | <a href=\"#_feature_framelessWindows\">framelessWindows</a><br> <a href=\"#_feature_pointerLock\">pointerLock</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/pjfconokbhkicolnaaphhfhjpcgnnfpj\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_webserver\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webserver\">webserver</a> | <a href=\"#_feature_sockets\">sockets</a><br> <a href=\"#_feature_systemInfo\">systemInfo</a><br> <a href=\"#mobile-support\">android</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hflhcpmgeolmjlbmdicgkjedjmkoocbe\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_websocket-server\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/websocket-server\">websocket-server</a> | <a href=\"#_feature_sockets\">sockets</a><br> <a href=\"#mobile-support\">ios</a><br> | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/pkbpddppnkjmlbgliipgmhjeialadokj\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_webview-samples_browser\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webview-samples/browser\">webview-samples/browser</a> | <a href=\"#_feature_webview\">webview</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/edggnmnajhcbhlnpjnogkjpghaikidaa\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_webview-samples_declarative-web-request\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webview-samples/declarative-web-request\">webview-samples/declarative-web-request</a> | <a href=\"#_feature_storage\">storage</a><br> <a href=\"#_feature_webview\">webview</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hhflblflkeainajnkamabjibdbfnbilb\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_webview-samples_insert-css\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webview-samples/insert-css\">webview-samples/insert-css</a> | <a href=\"#_feature_storage\">storage</a><br> <a href=\"#_feature_webview\">webview</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/dnedmnfnnbpgnedogbljhiacgmkbklfj\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_webview-samples_local-resources\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webview-samples/local-resources\">webview-samples/local-resources</a> | <a href=\"#_feature_webview\">webview</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/nfeplfjagjlljomimjealpedhjgamkle\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_webview-samples_multi-tab-browser\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webview-samples/multi-tab-browser\">webview-samples/multi-tab-browser</a> | <a href=\"#_feature_contextMenu\">contextMenu</a><br> <a href=\"#_feature_webview\">webview</a><br>  | -\n<a name=\"_sample_webview-samples_new-window\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webview-samples/new-window\">webview-samples/new-window</a> | <a href=\"#_feature_webview\">webview</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/kpgjodoohleggakakpaadgjeedfgeafi\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_webview-samples_new-window-user-agent\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webview-samples/new-window-user-agent\">webview-samples/new-window-user-agent</a> | <a href=\"#_feature_contextMenu\">contextMenu</a><br> <a href=\"#_feature_webview\">webview</a><br>  | -\n<a name=\"_sample_webview-samples_shared-script\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webview-samples/shared-script\">webview-samples/shared-script</a> | <a href=\"#_feature_webview\">webview</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/cbdacningpambfjjejgfebeagmhpdcko\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_webview-samples_user-agent\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webview-samples/user-agent\">webview-samples/user-agent</a> | <a href=\"#_feature_webview\">webview</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/fbkdeonndngdbojbccanjnpnlpdmgchc\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_webview-samples_webview\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webview-samples/webview\">webview-samples/webview</a> | <a href=\"#_feature_geolocation\">geolocation</a><br> <a href=\"#_feature_getUserMedia\">getUserMedia</a><br> <a href=\"#_feature_pointerLock\">pointerLock</a><br> <a href=\"#_feature_webview\">webview</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hnanccpkhjhkkgiipckodmdldeomdohj\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_window-options\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/window-options\">window-options</a> | <a href=\"#_feature_fullscreen\">fullscreen</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/cfcgoifcnpnadlhhoolkemkjkhoajfmk\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_window-state\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/window-state\">window-state</a> | <a href=\"#_feature_fullscreen\">fullscreen</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hcbhfbnaaancmblfhdknlnojpafjohbi\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<a name=\"_sample_windows\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/windows\">windows</a> | <a href=\"#_feature_framelessWindows\">framelessWindows</a><br>  | <a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ldenchfohdfgggloeimambnckhjpedgc\"><img alt=\"Try it now\" src=\"https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton_small.png\" title=\"Click here to install this sample from the Chrome Web Store\"></img></a>\n<!-- sample_table_autogen_end THIS TABLE IS AUTOGENERATED! PLEASE, DON'T EDIT IT DIRECTLY! -->\n\n\n\n# Samples by features\n\n<!-- feature_table_autogen_start THIS TABLE IS AUTOGENERATED! PLEASE, DON'T EDIT IT DIRECTLY! -->\nAPI or feature | Samples\n--- | ---\n<a name=\"_feature_alarms\"></a>alarms | <a href=\"#_sample_todomvc\">todomvc</a> \n<a name=\"_feature_appview\"></a>appview | <a href=\"#_sample_appview_host-app\">appview_host-app</a> \n<a name=\"_feature_bluetooth\"></a>bluetooth | <a href=\"#_sample_bluetooth-samples_battery-service-demo\">bluetooth-samples_battery-service-demo</a> <a href=\"#_sample_bluetooth-samples_device-info-demo\">bluetooth-samples_device-info-demo</a> <a href=\"#_sample_bluetooth-samples_heart-rate-sensor\">bluetooth-samples_heart-rate-sensor</a> <a href=\"#_sample_ioio\">ioio</a> \n<a name=\"_feature_clipboard\"></a>clipboard | <a href=\"#_sample_calculator\">calculator</a> <a href=\"#_sample_diff\">diff</a> <a href=\"#_sample_text-editor\">text-editor</a> \n<a name=\"_feature_commands\"></a>commands | <a href=\"#_sample_mini-code-edit\">mini-code-edit</a> \n<a name=\"_feature_contextMenu\"></a>contextMenu | <a href=\"#_sample_context-menu\">context-menu</a> <a href=\"#_sample_mini-code-edit\">mini-code-edit</a> <a href=\"#_sample_webview-samples_multi-tab-browser\">webview-samples_multi-tab-browser</a> <a href=\"#_sample_webview-samples_new-window-user-agent\">webview-samples_new-window-user-agent</a> \n<a name=\"_feature_dart\"></a>dart | <a href=\"#_sample_dart\">dart</a> \n<a name=\"_feature_desktopCapture\"></a>desktopCapture | <a href=\"#_sample_desktop-capture\">desktop-capture</a> \n<a name=\"_feature_fileSystem\"></a>fileSystem | <a href=\"#_sample_diff\">diff</a> <a href=\"#_sample_filesystem-access\">filesystem-access</a> <a href=\"#_sample_image-edit\">image-edit</a> <a href=\"#_sample_mini-code-edit\">mini-code-edit</a> <a href=\"#_sample_text-editor\">text-editor</a> <a href=\"#_sample_todomvc\">todomvc</a> <a href=\"#_sample_usb-label-printer\">usb-label-printer</a> <a href=\"#_sample_web-store\">web-store</a> \n<a name=\"_feature_framelessWindows\"></a>framelessWindows | <a href=\"#_sample_clock\">clock</a> <a href=\"#_sample_frameless-window\">frameless-window</a> <a href=\"#_sample_gdrive\">gdrive</a> <a href=\"#_sample_io2012-presentation\">io2012-presentation</a> <a href=\"#_sample_manga-cam\">manga-cam</a> <a href=\"#_sample_mdns-browser\">mdns-browser</a> <a href=\"#_sample_multicast\">multicast</a> <a href=\"#_sample_platform-title\">platform-title</a> <a href=\"#_sample_webgl-pointer-lock\">webgl-pointer-lock</a> <a href=\"#_sample_windows\">windows</a> \n<a name=\"_feature_fullscreen\"></a>fullscreen | <a href=\"#_sample_window-options\">window-options</a> <a href=\"#_sample_window-state\">window-state</a> \n<a name=\"_feature_gcm\"></a>gcm | <a href=\"#_sample_gcm-notifications\">gcm-notifications</a> \n<a name=\"_feature_geolocation\"></a>geolocation | <a href=\"#_sample_appsquare\">appsquare</a> <a href=\"#_sample_clock\">clock</a> <a href=\"#_sample_weather\">weather</a> <a href=\"#_sample_webview-samples_webview\">webview-samples_webview</a> \n<a name=\"_feature_getUserMedia\"></a>getUserMedia | <a href=\"#_sample_appview_embedded-app\">appview_embedded-app</a> <a href=\"#_sample_camera-capture\">camera-capture</a> <a href=\"#_sample_io2012-presentation\">io2012-presentation</a> <a href=\"#_sample_io2012-presentation_servo\">io2012-presentation_servo</a> <a href=\"#_sample_manga-cam\">manga-cam</a> <a href=\"#_sample_servo\">servo</a> <a href=\"#_sample_usb-label-printer\">usb-label-printer</a> <a href=\"#_sample_webview-samples_webview\">webview-samples_webview</a> \n<a name=\"_feature_hid\"></a>hid | <a href=\"#_sample_blink1\">blink1</a> <a href=\"#_sample_hid\">hid</a> \n<a name=\"_feature_identity\"></a>identity | <a href=\"#_sample_appsquare\">appsquare</a> <a href=\"#_sample_gdrive\">gdrive</a> <a href=\"#_sample_github-auth\">github-auth</a> <a href=\"#_sample_identity\">identity</a> <a href=\"#_sample_instagram-auth\">instagram-auth</a> <a href=\"#_sample_one-time-payment\">one-time-payment</a> <a href=\"#_sample_tasks\">tasks</a> <a href=\"#_sample_web-store\">web-store</a> \n<a name=\"_feature_in-app-payments\"></a>in-app-payments | <a href=\"#_sample_managed-in-app-payments\">managed-in-app-payments</a> \n<a name=\"_feature_mediaGallery\"></a>mediaGallery | <a href=\"#_sample_media-gallery\">media-gallery</a> \n<a name=\"_feature_messaging\"></a>messaging | <a href=\"#_sample_messaging_app1\">messaging_app1</a> <a href=\"#_sample_messaging_app2\">messaging_app2</a> <a href=\"#_sample_messaging_extension\">messaging_extension</a> <a href=\"#_sample_multicast\">multicast</a> \n<a name=\"_feature_old_sockets\"></a>old_sockets | <a href=\"#_sample_parrot-ar-drone\">parrot-ar-drone</a> \n<a name=\"_feature_optionalPermissions\"></a>optionalPermissions | <a href=\"#_sample_optional-permissions\">optional-permissions</a> <a href=\"#_sample_usb-label-printer\">usb-label-printer</a> <a href=\"#_sample_usb_knob\">usb_knob</a> \n<a name=\"_feature_pointerLock\"></a>pointerLock | <a href=\"#_sample_webgl-pointer-lock\">webgl-pointer-lock</a> <a href=\"#_sample_webview-samples_webview\">webview-samples_webview</a> \n<a name=\"_feature_print\"></a>print | <a href=\"#_sample_printing\">printing</a> \n<a name=\"_feature_richNotifications\"></a>richNotifications | <a href=\"#_sample_clock\">clock</a> <a href=\"#_sample_gcm-notifications\">gcm-notifications</a> <a href=\"#_sample_messaging_extension\">messaging_extension</a> <a href=\"#_sample_rich-notifications\">rich-notifications</a> <a href=\"#_sample_todomvc\">todomvc</a> \n<a name=\"_feature_sandbox\"></a>sandbox | <a href=\"#_sample_sandbox\">sandbox</a> <a href=\"#_sample_sandboxed-content\">sandboxed-content</a> \n<a name=\"_feature_serial\"></a>serial | <a href=\"#_sample_io2012-presentation\">io2012-presentation</a> <a href=\"#_sample_io2012-presentation_servo\">io2012-presentation_servo</a> <a href=\"#_sample_serial-control-signals\">serial-control-signals</a> <a href=\"#_sample_serial_adkjs_app\">serial_adkjs_app</a> <a href=\"#_sample_serial_espruino\">serial_espruino</a> <a href=\"#_sample_serial_ledtoggle\">serial_ledtoggle</a> <a href=\"#_sample_servo\">servo</a> \n<a name=\"_feature_sockets\"></a>sockets | <a href=\"#_sample_mdns-browser\">mdns-browser</a> <a href=\"#_sample_multicast\">multicast</a> <a href=\"#_sample_parrot-ar-drone\">parrot-ar-drone</a> <a href=\"#_sample_tcpserver\">tcpserver</a> <a href=\"#_sample_telnet\">telnet</a> <a href=\"#_sample_udp\">udp</a> <a href=\"#_sample_webserver\">webserver</a> <a href=\"#_sample_websocket-server\">websocket-server</a> \n<a name=\"_feature_storage\"></a>storage | <a href=\"#_sample_analytics\">analytics</a> <a href=\"#_sample_appsquare\">appsquare</a> <a href=\"#_sample_clock\">clock</a> <a href=\"#_sample_diff\">diff</a> <a href=\"#_sample_filesystem-access\">filesystem-access</a> <a href=\"#_sample_gcm-notifications\">gcm-notifications</a> <a href=\"#_sample_hello-world-sync\">hello-world-sync</a> <a href=\"#_sample_image-edit\">image-edit</a> <a href=\"#_sample_io2012-presentation\">io2012-presentation</a> <a href=\"#_sample_multicast\">multicast</a> <a href=\"#_sample_one-time-payment\">one-time-payment</a> <a href=\"#_sample_printing\">printing</a> <a href=\"#_sample_restarted-demo\">restarted-demo</a> <a href=\"#_sample_todomvc\">todomvc</a> <a href=\"#_sample_url-handler\">url-handler</a> <a href=\"#_sample_weather\">weather</a> <a href=\"#_sample_web-store\">web-store</a> <a href=\"#_sample_webview-samples_declarative-web-request\">webview-samples_declarative-web-request</a> <a href=\"#_sample_webview-samples_insert-css\">webview-samples_insert-css</a> \n<a name=\"_feature_syncFileSystem\"></a>syncFileSystem | <a href=\"#_sample_manga-cam\">manga-cam</a> <a href=\"#_sample_syncfs-editor\">syncfs-editor</a> <a href=\"#_sample_todomvc\">todomvc</a> \n<a name=\"_feature_systemInfo\"></a>systemInfo | <a href=\"#_sample_mdns-browser\">mdns-browser</a> <a href=\"#_sample_printing\">printing</a> <a href=\"#_sample_systemInfo\">systemInfo</a> <a href=\"#_sample_tcpserver\">tcpserver</a> <a href=\"#_sample_webserver\">webserver</a> \n<a name=\"_feature_tts\"></a>tts | <a href=\"#_sample_tts\">tts</a> \n<a name=\"_feature_usb\"></a>usb | <a href=\"#_sample_blink1\">blink1</a> <a href=\"#_sample_usb-label-printer\">usb-label-printer</a> <a href=\"#_sample_usb_device-info\">usb_device-info</a> <a href=\"#_sample_usb_knob\">usb_knob</a> \n<a name=\"_feature_webstore\"></a>webstore | <a href=\"#_sample_web-store\">web-store</a> \n<a name=\"_feature_webview\"></a>webview | <a href=\"#_sample_appengine-channelapi_app\">appengine-channelapi_app</a> <a href=\"#_sample_io2012-presentation\">io2012-presentation</a> <a href=\"#_sample_tcpserver\">tcpserver</a> <a href=\"#_sample_url-handler\">url-handler</a> <a href=\"#_sample_webview-samples_browser\">webview-samples_browser</a> <a href=\"#_sample_webview-samples_declarative-web-request\">webview-samples_declarative-web-request</a> <a href=\"#_sample_webview-samples_insert-css\">webview-samples_insert-css</a> <a href=\"#_sample_webview-samples_local-resources\">webview-samples_local-resources</a> <a href=\"#_sample_webview-samples_multi-tab-browser\">webview-samples_multi-tab-browser</a> <a href=\"#_sample_webview-samples_new-window\">webview-samples_new-window</a> <a href=\"#_sample_webview-samples_new-window-user-agent\">webview-samples_new-window-user-agent</a> <a href=\"#_sample_webview-samples_shared-script\">webview-samples_shared-script</a> <a href=\"#_sample_webview-samples_user-agent\">webview-samples_user-agent</a> <a href=\"#_sample_webview-samples_webview\">webview-samples_webview</a> \n<!-- feature_table_autogen_end THIS TABLE IS AUTOGENERATED! PLEASE, DON'T EDIT IT DIRECTLY! -->\n\n# Mobile support\n\nYou can generate native mobile versions of the samples below using the procedure\ndescribed <a\nhref=\"https://github.com/MobileChromeApps/mobile-chrome-apps/blob/master/README.md\">here</a>.\n\n<!-- mobile_table_autogen_start THIS TABLE IS AUTOGENERATED! PLEASE, DON'T EDIT IT DIRECTLY! -->\n<table>\n<tr><th width=\"16%\">Sample</th><th width=\"42%\">Android support</th><th width=\"42%\">iOS support</th></tr>\n<tr><td><a name=\"_mobile_analytics\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/analytics\">analytics</a></td><td>Supported.</td><td>Supported.</td></tr>\n<tr><td><a name=\"_mobile_calculator\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/calculator\">calculator</a></td><td>Supported. Visual issues caused by fixed-size layout</td><td>Supported. Visual issues caused by fixed-size layout</td></tr>\n<tr><td><a name=\"_mobile_dart\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/dart\">dart</a></td><td></td><td>Supported. Visual issues caused by fixed-size layout</td></tr>\n<tr><td><a name=\"_mobile_hello-world\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/hello-world\">hello-world</a></td><td>Supported.</td><td>Supported.</td></tr>\n<tr><td><a name=\"_mobile_hello-world-sync\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/hello-world-sync\">hello-world-sync</a></td><td>Supported. sync storage doesn't actually sync - works local</td><td>Supported. sync storage doesn't actually sync - works local</td></tr>\n<tr><td><a name=\"_mobile_identity\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/identity\">identity</a></td><td>Supported. You need to add an Android OAuth app in the Cloud API console of the OAuth project. The app's SHA1 can be the debug one (see more <a href=\"https://developers.google.com/console/help/new/#installedapplications\">here</a>), and the package name is org.chromium.identity.MyApp. If you don't add the Android OAuth app and tries to use the OAuth client-id from the Chrome app, you will get a generic message GoogleAuthException</td><td></td></tr>\n<tr><td><a name=\"_mobile_parrot-ar-drone\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/parrot-ar-drone\">parrot-ar-drone</a></td><td>Supported. Communication to the Drone works, but the UI requires a connected gamepad.</td><td></td></tr>\n<tr><td><a name=\"_mobile_restarted-demo\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/restarted-demo\">restarted-demo</a></td><td></td><td>Supported. Restart must be done via Safari remote debugging.</td></tr>\n<tr><td><a name=\"_mobile_rich-notifications\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/rich-notifications\">rich-notifications</a></td><td>Supported.</td><td></td></tr>\n<tr><td><a name=\"_mobile_tasks\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/tasks\">tasks</a></td><td>Supported.</td><td></td></tr>\n<tr><td><a name=\"_mobile_todomvc\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/todomvc\">todomvc</a></td><td>Supported.</td><td></td></tr>\n<tr><td><a name=\"_mobile_udp\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/udp\">udp</a></td><td></td><td>Supported.</td></tr>\n<tr><td><a name=\"_mobile_weather\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/weather\">weather</a></td><td></td><td>Supported.</td></tr>\n<tr><td><a name=\"_mobile_webserver\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webserver\">webserver</a></td><td>Supported. Directory picking doesn't work on some versions of Android</td><td></td></tr>\n<tr><td><a name=\"_mobile_websocket-server\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/websocket-server\">websocket-server</a></td><td></td><td>Supported.</td></tr>\n</table>\n<!-- mobile_table_autogen_end THIS TABLE IS AUTOGENERATED! PLEASE, DON'T EDIT IT DIRECTLY! -->\n\n# Libraries and tools\n\n* [Google APIs client library for Chrome Apps](https://github.com/GoogleChrome/chrome-extensions-samples/blob/main/_archive/apps/libraries/gapi-chrome-apps-lib)\n* [Google Analytics for Chrome Apps and Extensions](https://github.com/GoogleChrome/chrome-platform-analytics)\n"
  },
  {
    "path": "_archive/apps/libraries/gapi-chrome-apps-lib/LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "_archive/apps/libraries/gapi-chrome-apps-lib/README.md",
    "content": "# Google API javascript client library loader for Chrome Packaged Apps\n\nProvides the Google API javascript client 'gapi' as\nappropriate for hosted websites, or if in a Chrome packaged\napp implement a minimal set of functionality that is Content\nSecurity Policy compliant and uses the chrome identity api.\n\n## Status\n\nThis library is likely not suitable for use without additional modifications.\n\n## Usage\n\nTo be expanded upon, but essentially:\n- Add 'identity' permission to manifest.\n- Reference this script instead of the apis.google.com online version.\n- Call gapi methods as usual.\n\n## Examples:\n\n* [Tasks app using GAPI](https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/tasks)\n\n## Resources\n\n* [JavaScript Client Library Reference](https://developers.google.com/api-client-library/javascript/reference/referencedocs)\n\n"
  },
  {
    "path": "_archive/apps/libraries/gapi-chrome-apps-lib/gapi-chrome-apps.js",
    "content": "/**\n * Copyright 2013 Google Inc. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n/**\n * gapi-chrome-apps version 0.001\n *\n * Provides the Google API javascript client 'gapi' as\n * appropriate for hosted websites, or if in a Chrome packaged\n * app implement a minimal set of functionality that is Content\n * Security Policy compliant and uses the chrome identity api.\n *\n * https://github.com/GoogleChrome/chrome-app-samples/tree/master/gapi-chrome-apps-lib\n *\n */\n\"use strict\";\n\n(function () {\n  if (typeof gapi !== 'undefined')\n    throw new Error('gapi already defined.');\n  if (typeof gapiIsLoaded !== 'function')\n    throw new Error('gapiIsLoaded callback function must be defined prior to ' +\n                    'loading gapi-chrome-apps.js');\n\n  // If not running in a chrome packaged app, load web gapi:\n  if (!(chrome && chrome.app && chrome.app.runtime)) {\n    // Load web gapi.\n    var script = document.createElement('script');\n    script.src = 'https://apis.google.com/js/client.js?onload=gapiIsLoaded';\n    document.documentElement.appendChild(script);\n    return;\n  }\n\n  window.gapi = {};\n  window.gapi.auth = {};\n  window.gapi.client = {};\n\n  var access_token = undefined;\n\n  gapi.auth.authorize = function (params, callback) {\n    if (typeof callback !== 'function')\n      throw new Error('callback required');\n\n    var details = {};\n    details.interactive = params.immediate === false || false;\n    if (params.accountHint) {\n      // Specifying this prevents the account chooser from appearing on Android.\n      details.accountHint = params.accountHint;\n    }\n    console.assert(!params.response_type || params.response_type == 'token');\n\n    var callbackWrapper = function (getAuthTokenCallbackParam) {\n      access_token = getAuthTokenCallbackParam;\n      // TODO: error conditions?\n      if (typeof access_token !== 'undefined')\n        callback({ access_token: access_token});\n      else\n        callback();\n    }\n\n    chrome.identity.getAuthToken(details, callbackWrapper);\n  };\n\n\n  gapi.client.request = function (args) {\n    if (typeof args !== 'object')\n      throw new Error('args required');\n    if (typeof args.callback !== 'function')\n      throw new Error('callback required');\n    if (typeof args.path !== 'string')\n      throw new Error('path required');\n\n    if (args.root && args.root === 'string') {\n      var path = args.root + args.path;\n    } else {\n      var path = 'https://www.googleapis.com' + args.path;\n    }\n\n    if (typeof args.params === 'object') {\n      var deliminator = '?';\n      for (var i in args.params) {\n        path += deliminator + encodeURIComponent(i) + \"=\"\n          + encodeURIComponent(args.params[i]);\n        deliminator = '&';\n      }\n    }\n\n    var xhr = new XMLHttpRequest();\n    xhr.open(args.method || 'GET', path);\n    xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);\n    if (typeof args.body !== 'undefined') {\n      xhr.setRequestHeader('content-type', 'application/json');\n      xhr.send(JSON.stringify(args.body));\n    } else {\n      xhr.send();\n    }\n\n    xhr.onerror = function () {\n      // TODO, error handling.\n      debugger;\n    };\n\n    xhr.onload = function() {\n      var rawResponseObject = {\n        // TODO: body, headers.\n        gapiRequest: {\n          data: {\n            status: this.status,\n            statusText: this.statusText\n          }\n        }\n      };\n\n      var rawResp = JSON.stringify(rawResponseObject);\n      if (this.response) {\n        var jsonResp = JSON.parse(this.response);\n        args.callback(jsonResp, rawResp);\n      } else {\n        args.callback(null, rawResp);\n      }\n    };\n  };\n\n  // Call client handler when gapi is ready.\n  setTimeout(function () { gapiIsLoaded(); }, 0);\n})();\n"
  },
  {
    "path": "_archive/apps/samples/analytics/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/anfhlhgdnbpnglngmblhkdifdbcepjce\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Analytics\n\nThis example demonstrates how to include support for Google Analytics in your\npackaged application. It uses the\n[chrome-platform-analytics](https://github.com/GoogleChrome/chrome-platform-analytics) library,\nwhich allows tracking app views or any arbitrary event to Google Analytics.\nSee more at the [project wiki](https://github.com/GoogleChrome/chrome-platform-analytics/wiki)\n\n*Please note: You will need to modify main.js to include real Google Analytics credentials.*\n\n## Resources\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n* [chrome-platform-analytics](https://github.com/GoogleChrome/chrome-platform-analytics/wiki)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/analytics/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/analytics/background.js",
    "content": "// Copyright 2013 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('main.html', {\"id\": \"analyticsWinID\"}, function() {});\n});\n"
  },
  {
    "path": "_archive/apps/samples/analytics/google-analytics-bundle.js",
    "content": "(function() { var g,aa=aa||{},h=this,ba=function(){},ca=function(a){var b=typeof a;if(\"object\"==b)if(a){if(a instanceof Array)return\"array\";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if(\"[object Window]\"==c)return\"object\";if(\"[object Array]\"==c||\"number\"==typeof a.length&&\"undefined\"!=typeof a.splice&&\"undefined\"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable(\"splice\"))return\"array\";if(\"[object Function]\"==c||\"undefined\"!=typeof a.call&&\"undefined\"!=typeof a.propertyIsEnumerable&&\n!a.propertyIsEnumerable(\"call\"))return\"function\"}else return\"null\";else if(\"function\"==b&&\"undefined\"==typeof a.call)return\"object\";return b},m=function(a){return\"array\"==ca(a)},da=function(a){var b=ca(a);return\"array\"==b||\"object\"==b&&\"number\"==typeof a.length},n=function(a){return\"string\"==typeof a},ea=function(a){return\"number\"==typeof a},p=function(a){return\"function\"==ca(a)},q=function(a){var b=typeof a;return\"object\"==b&&null!=a||\"function\"==b},fa=function(a,b,c){return a.call.apply(a.bind,\narguments)},ga=function(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}return function(){return a.apply(b,arguments)}},r=function(a,b,c){r=Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf(\"native code\")?fa:ga;return r.apply(null,arguments)},ha=function(a,b){var c=Array.prototype.slice.call(arguments,1);return function(){var b=\nc.slice();b.push.apply(b,arguments);return a.apply(this,b)}},s=Date.now||function(){return+new Date},t=function(a,b){var c=a.split(\".\"),d=h;c[0]in d||!d.execScript||d.execScript(\"var \"+c[0]);for(var e;c.length&&(e=c.shift());)c.length||void 0===b?d=d[e]?d[e]:d[e]={}:d[e]=b},u=function(a,b){function c(){}c.prototype=b.prototype;a.L=b.prototype;a.prototype=new c;a.Pc=function(a,c,f){return b.prototype[c].apply(a,Array.prototype.slice.call(arguments,2))}};\nFunction.prototype.bind=Function.prototype.bind||function(a,b){if(1<arguments.length){var c=Array.prototype.slice.call(arguments,1);c.unshift(this,a);return r.apply(null,c)}return r(this,a)};var v=function(a){if(Error.captureStackTrace)Error.captureStackTrace(this,v);else{var b=Error().stack;b&&(this.stack=b)}a&&(this.message=String(a))};u(v,Error);v.prototype.name=\"CustomError\";var ia=function(a,b){return a<b?-1:a>b?1:0};var w=Array.prototype,ja=w.indexOf?function(a,b,c){return w.indexOf.call(a,b,c)}:function(a,b,c){c=null==c?0:0>c?Math.max(0,a.length+c):c;if(n(a))return n(b)&&1==b.length?a.indexOf(b,c):-1;for(;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1},ka=w.forEach?function(a,b,c){w.forEach.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=n(a)?a.split(\"\"):a,f=0;f<d;f++)f in e&&b.call(c,e[f],f,a)},la=w.some?function(a,b,c){return w.some.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=n(a)?a.split(\"\"):\na,f=0;f<d;f++)if(f in e&&b.call(c,e[f],f,a))return!0;return!1},ma=w.every?function(a,b,c){return w.every.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=n(a)?a.split(\"\"):a,f=0;f<d;f++)if(f in e&&!b.call(c,e[f],f,a))return!1;return!0},oa=function(a){var b;t:{b=na;for(var c=a.length,d=n(a)?a.split(\"\"):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a)){b=e;break t}b=-1}return 0>b?null:n(a)?a.charAt(b):a[b]},pa=function(a,b){var c=ja(a,b),d;(d=0<=c)&&w.splice.call(a,c,1);return d},qa=function(a){return w.concat.apply(w,\narguments)},ra=function(a,b,c){return 2>=arguments.length?w.slice.call(a,b):w.slice.call(a,b,c)};var sa=\"StopIteration\"in h?h.StopIteration:Error(\"StopIteration\"),ta=function(){};ta.prototype.next=function(){throw sa;};ta.prototype.vc=function(){return this};var ua=function(a,b,c){for(var d in a)b.call(c,a[d],d,a)},va=function(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b},wa=function(a){var b=[],c=0,d;for(d in a)b[c++]=d;return b},xa=function(a,b){var c;t:{for(c in a)if(b.call(void 0,a[c],c,a))break t;c=void 0}return c&&a[c]},ya=\"constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf\".split(\" \"),za=function(a,b){for(var c,d,e=1;e<arguments.length;e++){d=arguments[e];for(c in d)a[c]=d[c];for(var f=0;f<ya.length;f++)c=\nya[f],Object.prototype.hasOwnProperty.call(d,c)&&(a[c]=d[c])}};var x=function(a,b){this.p={};this.b=[];this.oa=this.h=0;var c=arguments.length;if(1<c){if(c%2)throw Error(\"Uneven number of arguments\");for(var d=0;d<c;d+=2)this.set(arguments[d],arguments[d+1])}else a&&this.ia(a)};x.prototype.t=function(){Aa(this);for(var a=[],b=0;b<this.b.length;b++)a.push(this.p[this.b[b]]);return a};x.prototype.F=function(){Aa(this);return this.b.concat()};x.prototype.Q=function(a){return y(this.p,a)};\nx.prototype.remove=function(a){return y(this.p,a)?(delete this.p[a],this.h--,this.oa++,this.b.length>2*this.h&&Aa(this),!0):!1};var Aa=function(a){if(a.h!=a.b.length){for(var b=0,c=0;b<a.b.length;){var d=a.b[b];y(a.p,d)&&(a.b[c++]=d);b++}a.b.length=c}if(a.h!=a.b.length){for(var e={},c=b=0;b<a.b.length;)d=a.b[b],y(e,d)||(a.b[c++]=d,e[d]=1),b++;a.b.length=c}};g=x.prototype;g.get=function(a,b){return y(this.p,a)?this.p[a]:b};\ng.set=function(a,b){y(this.p,a)||(this.h++,this.b.push(a),this.oa++);this.p[a]=b};g.ia=function(a){var b;a instanceof x?(b=a.F(),a=a.t()):(b=wa(a),a=va(a));for(var c=0;c<b.length;c++)this.set(b[c],a[c])};g.forEach=function(a,b){for(var c=this.F(),d=0;d<c.length;d++){var e=c[d],f=this.get(e);a.call(b,f,e,this)}};g.clone=function(){return new x(this)};g.Jb=function(){Aa(this);for(var a={},b=0;b<this.b.length;b++){var c=this.b[b];a[c]=this.p[c]}return a};\ng.vc=function(a){Aa(this);var b=0,c=this.b,d=this.p,e=this.oa,f=this,k=new ta;k.next=function(){for(;;){if(e!=f.oa)throw Error(\"The map has changed since the iterator was created\");if(b>=c.length)throw sa;var k=c[b++];return a?k:d[k]}};return k};var y=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};var Ba,Ca,Da={id:\"hitType\",name:\"t\",valueType:\"text\",maxLength:void 0,defaultValue:void 0},Ea={id:\"sessionControl\",name:\"sc\",valueType:\"text\",maxLength:void 0,defaultValue:void 0},Fa={id:\"description\",name:\"cd\",valueType:\"text\",maxLength:2048,defaultValue:void 0},Ga={id:\"eventCategory\",name:\"ec\",valueType:\"text\",maxLength:150,defaultValue:void 0},Ha={id:\"eventAction\",name:\"ea\",valueType:\"text\",maxLength:500,defaultValue:void 0},Ia={id:\"eventLabel\",name:\"el\",valueType:\"text\",maxLength:500,defaultValue:void 0},\nJa={id:\"eventValue\",name:\"ev\",valueType:\"integer\",maxLength:void 0,defaultValue:void 0},Ka={pd:Da,Qc:{id:\"anonymizeIp\",name:\"aip\",valueType:\"boolean\",maxLength:void 0,defaultValue:void 0},Ad:{id:\"queueTime\",name:\"qt\",valueType:\"integer\",maxLength:void 0,defaultValue:void 0},Wc:{id:\"cacheBuster\",name:\"z\",valueType:\"text\",maxLength:void 0,defaultValue:void 0},Gd:Ea,Wd:{id:\"userId\",name:\"uid\",valueType:\"text\",maxLength:void 0,defaultValue:void 0},xd:{id:\"nonInteraction\",name:\"ni\",valueType:\"boolean\",\nmaxLength:void 0,defaultValue:void 0},fd:Fa,Pd:{id:\"title\",name:\"dt\",valueType:\"text\",maxLength:1500,defaultValue:void 0},Sc:{id:\"appId\",name:\"aid\",valueType:\"text\",maxLength:150,defaultValue:void 0},Tc:{id:\"appInstallerId\",name:\"aiid\",valueType:\"text\",maxLength:150,defaultValue:void 0},jd:Ga,hd:Ha,kd:Ia,ld:Ja,Id:{id:\"socialNetwork\",name:\"sn\",valueType:\"text\",maxLength:50,defaultValue:void 0},Hd:{id:\"socialAction\",name:\"sa\",valueType:\"text\",maxLength:50,defaultValue:void 0},Jd:{id:\"socialTarget\",\nname:\"st\",valueType:\"text\",maxLength:2048,defaultValue:void 0},Sd:{id:\"transactionId\",name:\"ti\",valueType:\"text\",maxLength:500,defaultValue:void 0},Rd:{id:\"transactionAffiliation\",name:\"ta\",valueType:\"text\",maxLength:500,defaultValue:void 0},Td:{id:\"transactionRevenue\",name:\"tr\",valueType:\"currency\",maxLength:void 0,defaultValue:void 0},Ud:{id:\"transactionShipping\",name:\"ts\",valueType:\"currency\",maxLength:void 0,defaultValue:void 0},Vd:{id:\"transactionTax\",name:\"tt\",valueType:\"currency\",maxLength:void 0,\ndefaultValue:void 0},dd:{id:\"currencyCode\",name:\"cu\",valueType:\"text\",maxLength:10,defaultValue:void 0},td:{id:\"itemPrice\",name:\"ip\",valueType:\"currency\",maxLength:void 0,defaultValue:void 0},ud:{id:\"itemQuantity\",name:\"iq\",valueType:\"integer\",maxLength:void 0,defaultValue:void 0},rd:{id:\"itemCode\",name:\"ic\",valueType:\"text\",maxLength:500,defaultValue:void 0},sd:{id:\"itemName\",name:\"in\",valueType:\"text\",maxLength:500,defaultValue:void 0},qd:{id:\"itemCategory\",name:\"iv\",valueType:\"text\",maxLength:500,\ndefaultValue:void 0},bd:{id:\"campaignSource\",name:\"cs\",valueType:\"text\",maxLength:100,defaultValue:void 0},$c:{id:\"campaignMedium\",name:\"cm\",valueType:\"text\",maxLength:50,defaultValue:void 0},ad:{id:\"campaignName\",name:\"cn\",valueType:\"text\",maxLength:100,defaultValue:void 0},Zc:{id:\"campaignKeyword\",name:\"ck\",valueType:\"text\",maxLength:500,defaultValue:void 0},Xc:{id:\"campaignContent\",name:\"cc\",valueType:\"text\",maxLength:500,defaultValue:void 0},Yc:{id:\"campaignId\",name:\"ci\",valueType:\"text\",maxLength:100,\ndefaultValue:void 0},od:{id:\"gclid\",name:\"gclid\",valueType:\"text\",maxLength:void 0,defaultValue:void 0},ed:{id:\"dclid\",name:\"dclid\",valueType:\"text\",maxLength:void 0,defaultValue:void 0},zd:{id:\"pageLoadTime\",name:\"plt\",valueType:\"integer\",maxLength:void 0,defaultValue:void 0},gd:{id:\"dnsTime\",name:\"dns\",valueType:\"integer\",maxLength:void 0,defaultValue:void 0},Kd:{id:\"tcpConnectTime\",name:\"tcp\",valueType:\"integer\",maxLength:void 0,defaultValue:void 0},Fd:{id:\"serverResponseTime\",name:\"srt\",valueType:\"integer\",\nmaxLength:void 0,defaultValue:void 0},yd:{id:\"pageDownloadTime\",name:\"pdt\",valueType:\"integer\",maxLength:void 0,defaultValue:void 0},Bd:{id:\"redirectResponseTime\",name:\"rrt\",valueType:\"integer\",maxLength:void 0,defaultValue:void 0},Ld:{id:\"timingCategory\",name:\"utc\",valueType:\"text\",maxLength:150,defaultValue:void 0},Od:{id:\"timingVar\",name:\"utv\",valueType:\"text\",maxLength:500,defaultValue:void 0},Nd:{id:\"timingValue\",name:\"utt\",valueType:\"integer\",maxLength:void 0,defaultValue:void 0},Md:{id:\"timingLabel\",\nname:\"utl\",valueType:\"text\",maxLength:500,defaultValue:void 0},md:{id:\"exDescription\",name:\"exd\",valueType:\"text\",maxLength:150,defaultValue:void 0},nd:{id:\"exFatal\",name:\"exf\",valueType:\"boolean\",maxLength:void 0,defaultValue:\"1\"}},La=function(a){if(1>a||200<a)throw Error(\"Expected dimension index range 1-200, but was : \"+a);return{id:\"dimension\"+a,name:\"cd\"+a,valueType:\"text\",maxLength:150,defaultValue:void 0}},Ma=function(a){if(1>a||200<a)throw Error(\"Expected metric index range 1-200, but was : \"+\na);return{id:\"metric\"+a,name:\"cm\"+a,valueType:\"integer\",maxLength:void 0,defaultValue:void 0}};var Na=function(a){if(1>a)return\"0\";if(3>a)return\"1-2\";a=Math.floor(Math.log(a-1)/Math.log(2));return Math.pow(2,a)+1+\"-\"+Math.pow(2,a+1)},Oa=function(a,b){for(var c=0,d=a.length-1,e=0;c<=d;){var f=Math.floor((c+d)/2),e=a[f];if(b<=e){d=0==f?0:a[f-1];if(b>d)return(d+1).toString()+\"-\"+e.toString();d=f-1}else if(b>e){if(f>=a.length-1)return(a[a.length-1]+1).toString()+\"+\";c=f+1}}return\"<= 0\"};var z=function(){this.ab=[]},Pa=function(){return new z};g=z.prototype;g.when=function(a){this.ab.push(a);return this};g.zb=function(a){var b=arguments;this.when(function(a){return 0<=ja(b,a.Gb())});return this};g.Oc=function(a,b){var c=ra(arguments,1);this.when(function(b){b=b.T().get(a);return 0<=ja(c,b)});return this};g.xb=function(a,b){if(q(this.e))throw Error(\"Filter has already been set.\");this.e=q(b)?r(a,b):a;return this};\ng.Ca=function(){if(0==this.ab.length)throw Error(\"Must specify at least one predicate using #when or a helper method.\");if(!q(this.e))throw Error(\"Must specify a delegate filter using #applyFilter.\");return r(function(a){ma(this.ab,function(b){return b(a)})&&this.e(a)},this)};var A=function(){this.Ab=!1;this.Bb=\"\";this.qb=!1;this.za=null};A.prototype.wc=function(a){this.Ab=!0;this.Bb=a||\" - \";return this};A.prototype.Nc=function(){this.qb=!0;return this};A.prototype.Ec=function(){return Qa(this,Na)};A.prototype.Fc=function(a){return Qa(this,ha(Oa,a))};\nvar Qa=function(a,b){if(null!=a.za)throw Error(\"LabelerBuilder: Only one labeling strategy may be used.\");a.za=r(function(a){var d=a.T().get(Ja),e=a.T().get(Ia);ea(d)&&(d=b(d),null!=e&&this.Ab&&(d=e+this.Bb+d),a.T().set(Ia,d))},a);return a};A.prototype.Ca=function(){if(null==this.za)throw Error(\"LabelerBuilder: a labeling strategy must be specified prior to calling build().\");return Pa().zb(\"event\").xb(r(function(a){this.za(a);this.qb&&a.T().remove(Ja)},this)).Ca()};var Ra=function(a,b){var c=Array.prototype.slice.call(arguments),d=c.shift();if(\"undefined\"==typeof d)throw Error(\"[goog.string.format] Template required\");return d.replace(/%([0\\-\\ \\+]*)(\\d+)?(\\.(\\d+))?([%sfdiu])/g,function(a,b,d,l,N,J,U,V){if(\"%\"==J)return\"%\";var Db=c.shift();if(\"undefined\"==typeof Db)throw Error(\"[goog.string.format] Not enough arguments\");arguments[0]=Db;return B[J].apply(null,arguments)})},B={s:function(a,b,c){return isNaN(c)||\"\"==c||a.length>=c?a:a=-1<b.indexOf(\"-\",0)?a+Array(c-\na.length+1).join(\" \"):Array(c-a.length+1).join(\" \")+a},f:function(a,b,c,d,e){d=a.toString();isNaN(e)||\"\"==e||(d=a.toFixed(e));var f;f=0>a?\"-\":0<=b.indexOf(\"+\")?\"+\":0<=b.indexOf(\" \")?\" \":\"\";0<=a&&(d=f+d);if(isNaN(c)||d.length>=c)return d;d=isNaN(e)?Math.abs(a).toString():Math.abs(a).toFixed(e);a=c-d.length-f.length;return d=0<=b.indexOf(\"-\",0)?f+d+Array(a+1).join(\" \"):f+Array(a+1).join(0<=b.indexOf(\"0\",0)?\"0\":\" \")+d},d:function(a,b,c,d,e,f,k,l){return B.f(parseInt(a,10),b,c,d,0,f,k,l)}};B.i=B.d;\nB.u=B.d;var Sa=function(a){if(\"function\"==typeof a.t)return a.t();if(n(a))return a.split(\"\");if(da(a)){for(var b=[],c=a.length,d=0;d<c;d++)b.push(a[d]);return b}return va(a)},Ta=function(a,b){if(\"function\"==typeof a.forEach)a.forEach(b,void 0);else if(da(a)||n(a))ka(a,b,void 0);else{var c;if(\"function\"==typeof a.F)c=a.F();else if(\"function\"!=typeof a.t)if(da(a)||n(a)){c=[];for(var d=a.length,e=0;e<d;e++)c.push(e)}else c=wa(a);else c=void 0;for(var d=Sa(a),e=d.length,f=0;f<e;f++)b.call(void 0,d[f],c&&c[f],\na)}};var C=function(a){this.B=new x;for(var b=arguments,c=0;c<b.length;c+=2)this.set(b[c],b[c+1])};C.prototype.set=function(a,b){this.B.set(a.name,{key:a,value:b})};C.prototype.remove=function(a){this.B.remove(a.name)};C.prototype.get=function(a){a=this.B.get(a.name,null);return null===a?null:a.value};C.prototype.ia=function(a){this.B.ia(a.B)};var Ua=function(a,b){ka(a.B.t(),function(a){b(a.key,a.value)})};C.prototype.Jb=function(){var a={};Ua(this,function(b,c){a[b.id]=c});return a};\nC.prototype.clone=function(){var a=new C;a.B=this.B.clone();return a};C.prototype.toString=function(){var a={};Ua(this,function(b,c){a[b.id]=c});return JSON.stringify(a)};var D=function(a){this.e=a};g=D.prototype;g.xc=function(a){var b=new D(r(this.P,this));b.I=Ga;b.N=a;return b};g.action=function(a){var b=new D(r(this.P,this));b.I=Ha;b.N=a;return b};g.label=function(a){var b=new D(r(this.P,this));b.I=Ia;b.N=a;return b};g.value=function(a){var b=new D(r(this.P,this));b.I=Ja;b.N=a;return b};g.yc=function(a,b){var c=new D(r(this.P,this));c.I=La(a);c.N=b;return c};g.Dc=function(a,b){var c=new D(r(this.P,this));c.I=Ma(a);c.N=b;return c};\ng.send=function(a){var b=new C;this.P(b);return a.send(\"event\",b)};g.P=function(a){null!=this.I&&null!=this.N&&!a.B.Q(this.I.name)&&a.set(this.I,this.N);q(this.e)&&this.e(a)};var Va=new D(ba);var E=function(){this.Y=this.Y;this.Da=this.Da};E.prototype.Y=!1;E.prototype.xa=function(){this.Y||(this.Y=!0,this.l())};E.prototype.l=function(){if(this.Da)for(;this.Da.length;)this.Da.shift()()};var F=function(a,b){this.type=a;this.currentTarget=this.target=b;this.defaultPrevented=this.U=!1;this.kb=!0};F.prototype.l=function(){};F.prototype.xa=function(){};F.prototype.preventDefault=function(){this.defaultPrevented=!0;this.kb=!1};var Wa=function(a){Wa[\" \"](a);return a};Wa[\" \"]=ba;var G;t:{var Xa=h.navigator;if(Xa){var Ya=Xa.userAgent;if(Ya){G=Ya;break t}}G=\"\"}var H=function(a){return-1!=G.indexOf(a)};var Za=H(\"Opera\")||H(\"OPR\"),I=H(\"Trident\")||H(\"MSIE\"),K=H(\"Gecko\")&&-1==G.toLowerCase().indexOf(\"webkit\")&&!(H(\"Trident\")||H(\"MSIE\")),L=-1!=G.toLowerCase().indexOf(\"webkit\"),$a=function(){var a=h.document;return a?a.documentMode:void 0},ab=function(){var a=\"\",b;if(Za&&h.opera)return a=h.opera.version,p(a)?a():a;K?b=/rv\\:([^\\);]+)(\\)|;)/:I?b=/\\b(?:MSIE|rv)[: ]([^\\);]+)(\\)|;)/:L&&(b=/WebKit\\/(\\S+)/);b&&(a=(a=b.exec(G))?a[1]:\"\");return I&&(b=$a(),b>parseFloat(a))?String(b):a}(),bb={},M=function(a){var b;\nif(!(b=bb[a])){b=0;for(var c=String(ab).replace(/^[\\s\\xa0]+|[\\s\\xa0]+$/g,\"\").split(\".\"),d=String(a).replace(/^[\\s\\xa0]+|[\\s\\xa0]+$/g,\"\").split(\".\"),e=Math.max(c.length,d.length),f=0;0==b&&f<e;f++){var k=c[f]||\"\",l=d[f]||\"\",N=RegExp(\"(\\\\d*)(\\\\D*)\",\"g\"),J=RegExp(\"(\\\\d*)(\\\\D*)\",\"g\");do{var U=N.exec(k)||[\"\",\"\",\"\"],V=J.exec(l)||[\"\",\"\",\"\"];if(0==U[0].length&&0==V[0].length)break;b=ia(0==U[1].length?0:parseInt(U[1],10),0==V[1].length?0:parseInt(V[1],10))||ia(0==U[2].length,0==V[2].length)||ia(U[2],V[2])}while(0==\nb)}b=bb[a]=0<=b}return b},cb=h.document,db=cb&&I?$a()||(\"CSS1Compat\"==cb.compatMode?parseInt(ab,10):5):void 0;var eb=!I||I&&9<=db,fb=I&&!M(\"9\"),gb=!L||M(\"528\"),hb=K&&M(\"1.9b\")||I&&M(\"8\")||Za&&M(\"9.5\")||L&&M(\"528\"),ib=K&&!M(\"8\")||I&&!M(\"9\");var O=function(a,b){F.call(this,a?a.type:\"\");this.relatedTarget=this.currentTarget=this.target=null;this.charCode=this.keyCode=this.button=this.screenY=this.screenX=this.clientY=this.clientX=this.offsetY=this.offsetX=0;this.metaKey=this.shiftKey=this.altKey=this.ctrlKey=!1;this.Db=this.state=null;if(a){var c=this.type=a.type;this.target=a.target||a.srcElement;this.currentTarget=b;var d=a.relatedTarget;if(d){if(K){var e;t:{try{Wa(d.nodeName);e=!0;break t}catch(f){}e=!1}e||(d=null)}}else\"mouseover\"==\nc?d=a.fromElement:\"mouseout\"==c&&(d=a.toElement);this.relatedTarget=d;this.offsetX=L||void 0!==a.offsetX?a.offsetX:a.layerX;this.offsetY=L||void 0!==a.offsetY?a.offsetY:a.layerY;this.clientX=void 0!==a.clientX?a.clientX:a.pageX;this.clientY=void 0!==a.clientY?a.clientY:a.pageY;this.screenX=a.screenX||0;this.screenY=a.screenY||0;this.button=a.button;this.keyCode=a.keyCode||0;this.charCode=a.charCode||(\"keypress\"==c?a.keyCode:0);this.ctrlKey=a.ctrlKey;this.altKey=a.altKey;this.shiftKey=a.shiftKey;this.metaKey=\na.metaKey;this.state=a.state;this.Db=a;a.defaultPrevented&&this.preventDefault()}};u(O,F);O.prototype.preventDefault=function(){O.L.preventDefault.call(this);var a=this.Db;if(a.preventDefault)a.preventDefault();else if(a.returnValue=!1,fb)try{if(a.ctrlKey||112<=a.keyCode&&123>=a.keyCode)a.keyCode=-1}catch(b){}};O.prototype.l=function(){};var jb=\"closure_listenable_\"+(1E6*Math.random()|0),kb=function(a){return!(!a||!a[jb])},lb=0;var mb=function(a,b,c,d,e){this.O=a;this.proxy=null;this.src=b;this.type=c;this.pa=!!d;this.sa=e;this.key=++lb;this.removed=this.qa=!1},nb=function(a){a.removed=!0;a.O=null;a.proxy=null;a.src=null;a.sa=null};var P=function(a){this.src=a;this.j={};this.Z=0};P.prototype.add=function(a,b,c,d,e){var f=a.toString();a=this.j[f];a||(a=this.j[f]=[],this.Z++);var k=ob(a,b,d,e);-1<k?(b=a[k],c||(b.qa=!1)):(b=new mb(b,this.src,f,!!d,e),b.qa=c,a.push(b));return b};P.prototype.remove=function(a,b,c,d){a=a.toString();if(!(a in this.j))return!1;var e=this.j[a];b=ob(e,b,c,d);return-1<b?(nb(e[b]),w.splice.call(e,b,1),0==e.length&&(delete this.j[a],this.Z--),!0):!1};\nvar pb=function(a,b){var c=b.type;if(!(c in a.j))return!1;var d=pa(a.j[c],b);d&&(nb(b),0==a.j[c].length&&(delete a.j[c],a.Z--));return d};P.prototype.removeAll=function(a){a=a&&a.toString();var b=0,c;for(c in this.j)if(!a||c==a){for(var d=this.j[c],e=0;e<d.length;e++)++b,nb(d[e]);delete this.j[c];this.Z--}return b};P.prototype.X=function(a,b,c,d){a=this.j[a.toString()];var e=-1;a&&(e=ob(a,b,c,d));return-1<e?a[e]:null};\nvar ob=function(a,b,c,d){for(var e=0;e<a.length;++e){var f=a[e];if(!f.removed&&f.O==b&&f.pa==!!c&&f.sa==d)return e}return-1};var qb=\"closure_lm_\"+(1E6*Math.random()|0),rb={},sb=0,tb=function(a,b,c,d,e){if(m(b)){for(var f=0;f<b.length;f++)tb(a,b[f],c,d,e);return null}c=ub(c);return kb(a)?a.listen(b,c,d,e):vb(a,b,c,!1,d,e)},vb=function(a,b,c,d,e,f){if(!b)throw Error(\"Invalid event type\");var k=!!e,l=wb(a);l||(a[qb]=l=new P(a));c=l.add(b,c,d,e,f);if(c.proxy)return c;d=xb();c.proxy=d;d.src=a;d.O=c;a.addEventListener?a.addEventListener(b.toString(),d,k):a.attachEvent(yb(b.toString()),d);sb++;return c},xb=function(){var a=zb,\nb=eb?function(c){return a.call(b.src,b.O,c)}:function(c){c=a.call(b.src,b.O,c);if(!c)return c};return b},Ab=function(a,b,c,d,e){if(m(b)){for(var f=0;f<b.length;f++)Ab(a,b[f],c,d,e);return null}c=ub(c);return kb(a)?a.bb(b,c,d,e):vb(a,b,c,!0,d,e)},Bb=function(a,b,c,d,e){if(m(b))for(var f=0;f<b.length;f++)Bb(a,b[f],c,d,e);else c=ub(c),kb(a)?a.Va(b,c,d,e):a&&(a=wb(a))&&(b=a.X(b,c,!!d,e))&&Cb(b)},Cb=function(a){if(ea(a)||!a||a.removed)return!1;var b=a.src;if(kb(b))return pb(b.A,a);var c=a.type,d=a.proxy;\nb.removeEventListener?b.removeEventListener(c,d,a.pa):b.detachEvent&&b.detachEvent(yb(c),d);sb--;(c=wb(b))?(pb(c,a),0==c.Z&&(c.src=null,b[qb]=null)):nb(a);return!0},yb=function(a){return a in rb?rb[a]:rb[a]=\"on\"+a},Fb=function(a,b,c,d){var e=1;if(a=wb(a))if(b=a.j[b.toString()])for(b=b.concat(),a=0;a<b.length;a++){var f=b[a];f&&f.pa==c&&!f.removed&&(e&=!1!==Eb(f,d))}return Boolean(e)},Eb=function(a,b){var c=a.O,d=a.sa||a.src;a.qa&&Cb(a);return c.call(d,b)},zb=function(a,b){if(a.removed)return!0;if(!eb){var c;\nif(!(c=b))t:{c=[\"window\",\"event\"];for(var d=h,e;e=c.shift();)if(null!=d[e])d=d[e];else{c=null;break t}c=d}e=c;c=new O(e,this);d=!0;if(!(0>e.keyCode||void 0!=e.returnValue)){t:{var f=!1;if(0==e.keyCode)try{e.keyCode=-1;break t}catch(k){f=!0}if(f||void 0==e.returnValue)e.returnValue=!0}e=[];for(f=c.currentTarget;f;f=f.parentNode)e.push(f);for(var f=a.type,l=e.length-1;!c.U&&0<=l;l--)c.currentTarget=e[l],d&=Fb(e[l],f,!0,c);for(l=0;!c.U&&l<e.length;l++)c.currentTarget=e[l],d&=Fb(e[l],f,!1,c)}return d}return Eb(a,\nnew O(b,this))},wb=function(a){a=a[qb];return a instanceof P?a:null},Gb=\"__closure_events_fn_\"+(1E9*Math.random()>>>0),ub=function(a){if(p(a))return a;a[Gb]||(a[Gb]=function(b){return a.handleEvent(b)});return a[Gb]};var Q=function(){E.call(this);this.A=new P(this);this.kc=this;this.Qa=null};u(Q,E);Q.prototype[jb]=!0;g=Q.prototype;g.addEventListener=function(a,b,c,d){tb(this,a,b,c,d)};g.removeEventListener=function(a,b,c,d){Bb(this,a,b,c,d)};\ng.dispatchEvent=function(a){var b,c=this.Qa;if(c){b=[];for(var d=1;c;c=c.Qa)b.push(c),++d}c=this.kc;d=a.type||a;if(n(a))a=new F(a,c);else if(a instanceof F)a.target=a.target||c;else{var e=a;a=new F(d,c);za(a,e)}var e=!0,f;if(b)for(var k=b.length-1;!a.U&&0<=k;k--)f=a.currentTarget=b[k],e=Hb(f,d,!0,a)&&e;a.U||(f=a.currentTarget=c,e=Hb(f,d,!0,a)&&e,a.U||(e=Hb(f,d,!1,a)&&e));if(b)for(k=0;!a.U&&k<b.length;k++)f=a.currentTarget=b[k],e=Hb(f,d,!1,a)&&e;return e};\ng.l=function(){Q.L.l.call(this);this.A&&this.A.removeAll(void 0);this.Qa=null};g.listen=function(a,b,c,d){return this.A.add(String(a),b,!1,c,d)};g.bb=function(a,b,c,d){return this.A.add(String(a),b,!0,c,d)};g.Va=function(a,b,c,d){return this.A.remove(String(a),b,c,d)};var Hb=function(a,b,c,d){b=a.A.j[String(b)];if(!b)return!0;b=b.concat();for(var e=!0,f=0;f<b.length;++f){var k=b[f];if(k&&!k.removed&&k.pa==c){var l=k.O,N=k.sa||k.src;k.qa&&pb(a.A,k);e=!1!==l.call(N,d)&&e}}return e&&0!=d.kb};\nQ.prototype.X=function(a,b,c,d){return this.A.X(String(a),b,c,d)};var Ib=function(a){h.setTimeout(function(){throw a;},0)},Jb,Kb=function(){var a=h.MessageChannel;\"undefined\"===typeof a&&\"undefined\"!==typeof window&&window.postMessage&&window.addEventListener&&(a=function(){var a=document.createElement(\"iframe\");a.style.display=\"none\";a.src=\"\";document.documentElement.appendChild(a);var b=a.contentWindow,a=b.document;a.open();a.write(\"\");a.close();var c=\"callImmediate\"+Math.random(),d=\"file:\"==b.location.protocol?\"*\":b.location.protocol+\"//\"+b.location.host,a=r(function(a){if(a.origin==\nd||a.data==c)this.port1.onmessage()},this);b.addEventListener(\"message\",a,!1);this.port1={};this.port2={postMessage:function(){b.postMessage(c,d)}}});if(\"undefined\"!==typeof a&&!H(\"Trident\")&&!H(\"MSIE\")){var b=new a,c={},d=c;b.port1.onmessage=function(){c=c.next;var a=c.Fb;c.Fb=null;a()};return function(a){d.next={Fb:a};d=d.next;b.port2.postMessage(0)}}return\"undefined\"!==typeof document&&\"onreadystatechange\"in document.createElement(\"script\")?function(a){var b=document.createElement(\"script\");b.onreadystatechange=\nfunction(){b.onreadystatechange=null;b.parentNode.removeChild(b);b=null;a();a=null};document.documentElement.appendChild(b)}:function(a){h.setTimeout(a,0)}};var Qb=function(a,b){Lb||Mb();Nb||(Lb(),Nb=!0);Ob.push(new Pb(a,b))},Lb,Mb=function(){if(h.Promise&&h.Promise.resolve){var a=h.Promise.resolve();Lb=function(){a.then(Rb)}}else Lb=function(){var a=Rb;!p(h.setImmediate)||h.Window&&h.Window.prototype.setImmediate==h.setImmediate?(Jb||(Jb=Kb()),Jb(a)):h.setImmediate(a)}},Nb=!1,Ob=[],Rb=function(){for(;Ob.length;){var a=Ob;Ob=[];for(var b=0;b<a.length;b++){var c=a[b];try{c.zc.call(c.scope)}catch(d){Ib(d)}}}Nb=!1},Pb=function(a,b){this.zc=a;this.scope=\nb};var Sb=function(a){a.prototype.then=a.prototype.then;a.prototype.$goog_Thenable=!0},Tb=function(a){if(!a)return!1;try{return!!a.$goog_Thenable}catch(b){return!1}};var R=function(a,b){this.m=0;this.v=void 0;this.n=this.o=null;this.ua=this.La=!1;try{var c=this;a.call(b,function(a){Ub(c,2,a)},function(a){Ub(c,3,a)})}catch(d){Ub(this,3,d)}};R.prototype.then=function(a,b,c){return Vb(this,p(a)?a:null,p(b)?b:null,c)};Sb(R);R.prototype.cancel=function(a){0==this.m&&Qb(function(){var b=new Wb(a);Xb(this,b)},this)};\nvar Xb=function(a,b){if(0==a.m)if(a.o){var c=a.o;if(c.n){for(var d=0,e=-1,f=0,k;k=c.n[f];f++)if(k=k.wa)if(d++,k==a&&(e=f),0<=e&&1<d)break;0<=e&&(0==c.m&&1==d?Xb(c,b):(d=c.n.splice(e,1)[0],Yb(c),d.Ma(b)))}}else Ub(a,3,b)},$b=function(a,b){a.n&&a.n.length||2!=a.m&&3!=a.m||Zb(a);a.n||(a.n=[]);a.n.push(b)},Vb=function(a,b,c,d){var e={wa:null,jb:null,Ma:null};e.wa=new R(function(a,k){e.jb=b?function(c){try{var e=b.call(d,c);a(e)}catch(J){k(J)}}:a;e.Ma=c?function(b){try{var e=c.call(d,b);void 0===e&&b instanceof\nWb?k(b):a(e)}catch(J){k(J)}}:k});e.wa.o=a;$b(a,e);return e.wa};R.prototype.vb=function(a){this.m=0;Ub(this,2,a)};R.prototype.wb=function(a){this.m=0;Ub(this,3,a)};\nvar Ub=function(a,b,c){if(0==a.m){if(a==c)b=3,c=new TypeError(\"Promise cannot resolve to itself\");else{if(Tb(c)){a.m=1;c.then(a.vb,a.wb,a);return}if(q(c))try{var d=c.then;if(p(d)){ac(a,c,d);return}}catch(e){b=3,c=e}}a.v=c;a.m=b;Zb(a);3!=b||c instanceof Wb||bc(a,c)}},ac=function(a,b,c){a.m=1;var d=!1,e=function(b){d||(d=!0,a.vb(b))},f=function(b){d||(d=!0,a.wb(b))};try{c.call(b,e,f)}catch(k){f(k)}},Zb=function(a){a.La||(a.La=!0,Qb(a.uc,a))};\nR.prototype.uc=function(){for(;this.n&&this.n.length;){var a=this.n;this.n=[];for(var b=0;b<a.length;b++){var c=a[b],d=this.v;2==this.m?c.jb(d):(Yb(this),c.Ma(d))}}this.La=!1};var Yb=function(a){for(;a&&a.ua;a=a.o)a.ua=!1},bc=function(a,b){a.ua=!0;Qb(function(){a.ua&&cc.call(null,b)})},cc=Ib,Wb=function(a){v.call(this,a)};u(Wb,v);Wb.prototype.name=\"cancel\";/*\n Portions of this code are from MochiKit, received by\n The Closure Authors under the MIT license. All other code is Copyright\n 2005-2009 The Closure Authors. All Rights Reserved.\n*/\nvar S=function(a,b){this.ja=[];this.hb=a;this.gb=b||null;this.W=this.C=!1;this.v=void 0;this.Ka=this.Lb=this.Ja=!1;this.ka=0;this.o=null;this.Ia=0};S.prototype.cancel=function(a){if(this.C)this.v instanceof S&&this.v.cancel();else{if(this.o){var b=this.o;delete this.o;a?b.cancel(a):(b.Ia--,0>=b.Ia&&b.cancel())}this.hb?this.hb.call(this.gb,this):this.Ka=!0;this.C||this.w(new dc)}};S.prototype.ib=function(a,b){this.Ja=!1;ec(this,a,b)};\nvar ec=function(a,b,c){a.C=!0;a.v=c;a.W=!b;fc(a)},hc=function(a){if(a.C){if(!a.Ka)throw new gc;a.Ka=!1}};S.prototype.G=function(a){hc(this);ec(this,!0,a)};S.prototype.w=function(a){hc(this);ec(this,!1,a)};S.prototype.J=function(a,b){return ic(this,a,null,b)};var ic=function(a,b,c,d){a.ja.push([b,c,d]);a.C&&fc(a);return a};S.prototype.then=function(a,b,c){var d,e,f=new R(function(a,b){d=a;e=b});ic(this,d,function(a){a instanceof dc?f.cancel():e(a)});return f.then(a,b,c)};Sb(S);\nvar jc=function(a){var b=new S;ic(a,b.G,b.w,b);return b},kc=function(a){return la(a.ja,function(a){return p(a[1])})},fc=function(a){if(a.ka&&a.C&&kc(a)){var b=a.ka,c=lc[b];c&&(h.clearTimeout(c.ma),delete lc[b]);a.ka=0}a.o&&(a.o.Ia--,delete a.o);for(var b=a.v,d=c=!1;a.ja.length&&!a.Ja;){var e=a.ja.shift(),f=e[0],k=e[1],e=e[2];if(f=a.W?k:f)try{var l=f.call(e||a.gb,b);void 0!==l&&(a.W=a.W&&(l==b||l instanceof Error),a.v=b=l);Tb(b)&&(d=!0,a.Ja=!0)}catch(N){b=N,a.W=!0,kc(a)||(c=!0)}}a.v=b;d&&(l=r(a.ib,\na,!0),d=r(a.ib,a,!1),b instanceof S?(ic(b,l,d),b.Lb=!0):b.then(l,d));c&&(b=new mc(b),lc[b.ma]=b,a.ka=b.ma)},nc=function(a){var b=new S;b.G(a);return b},pc=function(){var a=oc,b=new S;b.w(a);return b},gc=function(){v.call(this)};u(gc,v);gc.prototype.message=\"Deferred has already fired\";gc.prototype.name=\"AlreadyCalledError\";var dc=function(){v.call(this)};u(dc,v);dc.prototype.message=\"Deferred was canceled\";dc.prototype.name=\"CanceledError\";\nvar mc=function(a){this.ma=h.setTimeout(r(this.pc,this),0);this.ga=a};mc.prototype.pc=function(){delete lc[this.ma];throw this.ga;};var lc={};var qc=function(a){this.$a=[];this.e=a};qc.prototype.S=function(a){if(!p(a))throw Error(\"Invalid filter. Must be a function.\");this.$a.push(a)};qc.prototype.send=function(a,b){for(var c=new T(a,b),d=0;d<this.$a.length&&(this.$a[d](c),!c.Za);d++);return c.Za?nc():this.e.send(a,b)};var T=function(a,b){this.rc=a;this.qc=b;this.Za=!1};T.prototype.Gb=function(){return this.rc};T.prototype.T=function(){return this.qc};T.prototype.cancel=function(){this.Za=!0};var rc=function(a,b){this.width=a;this.height=b};rc.prototype.clone=function(){return new rc(this.width,this.height)};rc.prototype.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};!K&&!I||I&&I&&9<=db||K&&M(\"1.9.1\");I&&M(\"9\");var sc={id:\"apiVersion\",name:\"v\",valueType:\"text\",maxLength:void 0,defaultValue:void 0},tc={id:\"appName\",name:\"an\",valueType:\"text\",maxLength:100,defaultValue:void 0},uc={id:\"appVersion\",name:\"av\",valueType:\"text\",maxLength:100,defaultValue:void 0},vc={id:\"clientId\",name:\"cid\",valueType:\"text\",maxLength:void 0,defaultValue:void 0},wc={id:\"language\",name:\"ul\",valueType:\"text\",maxLength:20,defaultValue:void 0},xc={id:\"libVersion\",name:\"_v\",valueType:\"text\",maxLength:void 0,defaultValue:void 0},yc={id:\"sampleRateOverride\",\nname:\"usro\",valueType:\"integer\",maxLength:void 0,defaultValue:void 0},zc={id:\"screenColors\",name:\"sd\",valueType:\"text\",maxLength:20,defaultValue:void 0},Ac={id:\"screenResolution\",name:\"sr\",valueType:\"text\",maxLength:20,defaultValue:void 0},Bc={id:\"trackingId\",name:\"tid\",valueType:\"text\",maxLength:void 0,defaultValue:void 0},Cc={id:\"viewportSize\",name:\"vp\",valueType:\"text\",maxLength:20,defaultValue:void 0},Dc={Rc:sc,Uc:tc,Vc:uc,cd:vc,vd:wc,wd:xc,Cd:yc,Dd:zc,Ed:Ac,Qd:Bc,Xd:Cc},Fc=function(a){if(!n(a))return a;\nvar b=Ec(a,Ka);if(q(b))return b;b=Ec(a,Dc);if(q(b))return b;b=/^dimension(\\d+)$/.exec(a);if(null!==b)return La(parseInt(b[1],10));b=/^metric(\\d+)$/.exec(a);if(null!==b)return Ma(parseInt(b[1],10));throw Error(a+\" is not a valid parameter name.\");},Ec=function(a,b){var c=xa(b,function(b){return b.id==a&&\"metric\"!=a&&\"dimension\"!=a});return q(c)?c:null};var W=function(a,b){this.Zb=b;this.q=b.Sa();this.sb=new C;this.Ya=!1};g=W.prototype;g.set=function(a,b){var c=Fc(a);this.sb.set(c,b)};g.S=function(a){this.Zb.S(a)};g.send=function(a,b){if(a instanceof D)return a.send(this);var c=this.sb.clone();b instanceof C?c.ia(b):q(b)&&ua(b,function(a,b){null!=a&&c.set(Fc(b),a)},this);this.Ya&&(this.Ya=!1,c.set(Ea,\"start\"));return this.q.send(a,c)};g.Gc=function(a){var b={description:a};this.set(Fa,a);return this.send(\"appview\",b)};\ng.Hc=function(a,b,c,d){return this.send(\"event\",{eventCategory:a,eventAction:b,eventLabel:c,eventValue:d})};g.Jc=function(a,b,c){return this.send(\"social\",{socialNetwork:a,socialAction:b,socialTarget:c})};g.Ic=function(a,b){return this.send(\"exception\",{exDescription:a,exFatal:b})};g.Cb=function(a,b,c,d,e){return this.send(\"timing\",{timingCategory:a,timingVar:b,timingLabel:d,timingValue:c,sampleRateOverride:e})};g.Ac=function(){this.Ya=!0};g.Mc=function(a,b,c,d){return new Gc(this,a,b,c,d)};\nvar Gc=function(a,b,c,d,e){this.yb=a;this.bc=b;this.ec=c;this.cc=d;this.V=e;this.dc=s()};Gc.prototype.send=function(){var a=this.yb.Cb(this.bc,this.ec,s()-this.dc,this.cc,this.V);this.yb=null;return a};var Hc=function(a,b,c,d,e){this.ic=a;this.fc=b;this.gc=c;this.k=d;this.hc=e};\nHc.prototype.Cc=function(a){var b=new W(0,this.hc.create());b.set(xc,this.ic);b.set(sc,1);b.set(tc,this.fc);b.set(uc,this.gc);b.set(Bc,a);a=window.navigator.language;b.set(wc,a);a=screen.colorDepth+\"-bit\";b.set(zc,a);a=[screen.width,screen.height].join(\"x\");b.set(Ac,a);a=window.document;a=\"CSS1Compat\"==a.compatMode?a.documentElement:a.body;a=new rc(a.clientWidth,a.clientHeight);a=[a.width,a.height].join(\"x\");b.set(Cc,a);return b};Hc.prototype.Bc=function(){return jc(this.k.ha)};var Ic=function(a){this.sc=a};Ic.prototype.send=function(a,b){this.sc.push({Ub:a,Vb:b});return nc()};var Jc=function(a,b,c){this.k=a;this.ra=[];this.M={enabled:new Ic(this.ra),disabled:c};this.q=this.M.enabled;ic(jc(this.k.ha),ha(this.Pb,b),this.Ob,this)};Jc.prototype.Pb=function(a){this.M.enabled=a();Kc(this);ka(this.ra,function(a){this.send(a.Ub,a.Vb)},this);this.ra=null;Lc(this.k,r(this.Xb,this))};Jc.prototype.Ob=function(){this.q=this.M.enabled=this.M.disabled;this.ra=null};Jc.prototype.send=function(a,b){return this.q.send(a,b)};var Kc=function(a){a.q=a.k.va()?a.M.enabled:a.M.disabled};\nJc.prototype.Xb=function(a){switch(a){case \"analytics.tracking-permitted\":Kc(this)}};var Mc=function(a,b,c,d,e,f){S.call(this,e,f);this.Na=a;this.Oa=[];this.lb=!!b;this.Nb=!!c;this.Mb=!!d;for(b=this.mb=0;b<a.length;b++)ic(a[b],r(this.rb,this,b,!0),r(this.rb,this,b,!1));0!=a.length||this.lb||this.G(this.Oa)};u(Mc,S);Mc.prototype.rb=function(a,b,c){this.mb++;this.Oa[a]=[b,c];this.C||(this.lb&&b?this.G([a,c]):this.Nb&&!b?this.w(c):this.mb==this.Na.length&&this.G(this.Oa));this.Mb&&!b&&(c=null);return c};Mc.prototype.w=function(a){Mc.L.w.call(this,a);for(a=0;a<this.Na.length;a++)this.Na[a].cancel()};\nvar Nc=function(a){return(new Mc(a,!1,!0)).J(function(a){for(var c=[],d=0;d<a.length;d++)c[d]=a[d][1];return c})};var X=function(a){this.H=a;this.V=100;this.nb=[];this.Pa=this.la=null;this.ha=Oc(this);this.ha.J(function(){tb(this.H,\"a\",r(this.Rb,this))},this)},Oc=function(a){return Pc(a).J(function(){return this},a)},Pc=function(a){return Nc([Qc(a),Rc(a)])};X.prototype.Rb=function(){var a=this.la,b=this.va();Pc(this).J(function(){if(a!=this.la)throw Error(\"User ID changed unexpectedly!\");b!=this.va()&&Sc(this)},this)};var Lc=function(a,b){a.nb.push(b)};\nX.prototype.Lc=function(a){this.H.set(\"analytics.tracking-permitted\",a).J(function(){this.Pa=a},this)};X.prototype.va=function(){var a;if(a=this.Pa)a=h._gaUserPrefs,a=!(a&&a.ioo&&a.ioo());return a};\nvar Qc=function(a){return a.H.get(\"analytics.tracking-permitted\").J(function(a){this.Pa=void 0!==a?a:!0},a)},Rc=function(a){return a.H.get(\"analytics.user-id\").J(function(a){if(!a){a=\"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".split(\"\");for(var c=0,d=a.length;c<d;c++)switch(a[c]){case \"x\":a[c]=Math.floor(16*Math.random()).toString(16);break;case \"y\":a[c]=(Math.floor(4*Math.random())+8).toString(16)}a=a.join(\"\");this.H.set(\"analytics.user-id\",a)}this.la=a},a)};X.prototype.Kc=function(a){this.V=a};\nvar Sc=function(a){ka(a.nb,function(a){a(\"analytics.tracking-permitted\")})};var Tc=function(a){Q.call(this);this.Wa=a;this.H=chrome.storage.local;chrome.storage.onChanged.addListener(r(this.nc,this))};u(Tc,Q);Tc.prototype.nc=function(a){Uc(this,a)&&this.dispatchEvent(\"a\")};var Uc=function(a,b){return la(wa(b),function(a){return 0==a.lastIndexOf(this.Wa,0)},a)};Tc.prototype.get=function(a){var b=new S,c=this.Wa+\".\"+a;this.H.get(c,function(a){var e=chrome.runtime.lastError;e?b.w(e):b.G(a[c])});return b};\nTc.prototype.set=function(a,b){var c=new S,d={};d[this.Wa+\".\"+a]=b;this.H.set(d,function(){var a=chrome.runtime.lastError;a?c.w(a):c.G()});return c};var Y=function(){};Y.Yb=function(){return Y.Ib?Y.Ib:Y.Ib=new Y};Y.prototype.send=function(){return nc()};var Vc=function(a,b){this.Xa=[];var c=r(function(){this.Aa=new qc(b.Sa());ka(this.Xa,function(a){this.Aa.S(a)},this);this.Xa=null;return this.Aa},this);this.q=new Jc(a,c,Y.Yb())};Vc.prototype.Sa=function(){return this.q};Vc.prototype.S=function(a){this.Aa?this.Aa.S(a):this.Xa.push(a)};var Wc=function(a,b){this.k=a;this.mc=b};Wc.prototype.create=function(){return new Vc(this.k,this.mc)};var Xc=function(a,b){Q.call(this);this.ya=a||1;this.R=b||h;this.Ra=r(this.lc,this);this.Ta=s()};u(Xc,Q);g=Xc.prototype;g.enabled=!1;g.g=null;g.lc=function(){if(this.enabled){var a=s()-this.Ta;0<a&&a<.8*this.ya?this.g=this.R.setTimeout(this.Ra,this.ya-a):(this.g&&(this.R.clearTimeout(this.g),this.g=null),this.dispatchEvent(\"tick\"),this.enabled&&(this.g=this.R.setTimeout(this.Ra,this.ya),this.Ta=s()))}};g.start=function(){this.enabled=!0;this.g||(this.g=this.R.setTimeout(this.Ra,this.ya),this.Ta=s())};\ng.stop=function(){this.enabled=!1;this.g&&(this.R.clearTimeout(this.g),this.g=null)};g.l=function(){Xc.L.l.call(this);this.stop();delete this.R};var Yc=function(a,b,c){if(p(a))c&&(a=r(a,c));else if(a&&\"function\"==typeof a.handleEvent)a=r(a.handleEvent,a);else throw Error(\"Invalid listener argument\");return 2147483647<b?-1:h.setTimeout(a,b||0)};var Z=function(a){E.call(this);this.Ua=a;this.b={}};u(Z,E);var Zc=[];Z.prototype.listen=function(a,b,c,d){m(b)||(b&&(Zc[0]=b.toString()),b=Zc);for(var e=0;e<b.length;e++){var f=tb(a,b[e],c||this.handleEvent,d||!1,this.Ua||this);if(!f)break;this.b[f.key]=f}return this};Z.prototype.bb=function(a,b,c,d){return $c(this,a,b,c,d)};var $c=function(a,b,c,d,e,f){if(m(c))for(var k=0;k<c.length;k++)$c(a,b,c[k],d,e,f);else{b=Ab(b,c,d||a.handleEvent,e,f||a.Ua||a);if(!b)return a;a.b[b.key]=b}return a};\nZ.prototype.Va=function(a,b,c,d,e){if(m(b))for(var f=0;f<b.length;f++)this.Va(a,b[f],c,d,e);else c=c||this.handleEvent,e=e||this.Ua||this,c=ub(c),d=!!d,b=kb(a)?a.X(b,c,d,e):a?(a=wb(a))?a.X(b,c,d,e):null:null,b&&(Cb(b),delete this.b[b.key]);return this};Z.prototype.removeAll=function(){ua(this.b,Cb);this.b={}};Z.prototype.l=function(){Z.L.l.call(this);this.removeAll()};Z.prototype.handleEvent=function(){throw Error(\"EventHandler.handleEvent not implemented\");};var ad=function(){Q.call(this);this.ta=new Z(this);gb&&(hb?this.ta.listen(ib?document.body:window,[\"online\",\"offline\"],this.tb):(this.ub=gb?navigator.onLine:!0,this.g=new Xc(250),this.ta.listen(this.g,\"tick\",this.ac),this.g.start()))};u(ad,Q);ad.prototype.ac=function(){var a=gb?navigator.onLine:!0;a!=this.ub&&(this.ub=a,this.tb())};ad.prototype.tb=function(){this.dispatchEvent((gb?navigator.onLine:1)?\"online\":\"offline\")};\nad.prototype.l=function(){ad.L.l.call(this);this.ta.xa();this.ta=null;this.g&&(this.g.xa(),this.g=null)};var bd=function(a,b){this.k=a;this.e=b};bd.prototype.send=function(a,b){b.set(vc,this.k.la);return this.e.send(a,b)};var cd=function(a){this.e=a};cd.prototype.send=function(a,b){dd(b);ed(b);return this.e.send(a,b)};var dd=function(a){Ua(a,function(b,c){void 0!==b.maxLength&&\"text\"==b.valueType&&0<b.maxLength&&c.length>b.maxLength&&a.set(b,c.substring(0,b.maxLength))})},ed=function(a){Ua(a,function(b,c){void 0!==b.defaultValue&&c==b.defaultValue&&a.remove(b)})};var oc={status:\"device-offline\",Ba:void 0},fd={status:\"rate-limited\",Ba:void 0},gd={status:\"sampled-out\",Ba:void 0},hd={status:\"sent\",Ba:void 0};var id=function(a,b){this.Wb=a;this.e=b};id.prototype.send=function(a,b){var c;c=this.Wb;var d=c.pb(),e=Math.floor((d-c.ob)*c.Sb);0<e&&(c.$=Math.min(c.$+e,c.Tb),c.ob=d);1>c.$?c=!1:(c.$-=1,c=!0);return c||\"item\"==a||\"transaction\"==a?this.e.send(a,b):nc(fd)};var jd=function(){this.$=60;this.Tb=500;this.Sb=5E-4;this.pb=function(){return(new Date).getTime()};this.ob=this.pb()};var kd=function(a,b){this.k=a;this.e=b};kd.prototype.send=function(a,b){var c=b.get(vc),c=parseInt(c.split(\"-\")[1],16),d;\"timing\"!=a?d=this.k.V:((d=b.get(yc))&&b.remove(yc),d||(d=this.k.V));return c<655.36*d?this.e.send(a,b):nc(gd)};var ld=/^(?:([^:/?#.]+):)?(?:\\/\\/(?:([^/?#]*)@)?([^/#?]*?)(?::([0-9]+))?(?=[/#?]|$))?([^?#]+)?(?:\\?([^#]*))?(?:#(.*))?$/,md=L,nd=function(a,b){if(md){md=!1;var c=h.location;if(c){var d=c.href;if(d&&(d=(d=nd(3,d))?decodeURI(d):d)&&d!=c.hostname)throw md=!0,Error();}}return b.match(ld)[a]||null};var od=function(){};od.prototype.Eb=null;var qd=function(a){var b;(b=a.Eb)||(b={},pd(a)&&(b[0]=!0,b[1]=!0),b=a.Eb=b);return b};var rd,sd=function(){};u(sd,od);var td=function(a){return(a=pd(a))?new ActiveXObject(a):new XMLHttpRequest},pd=function(a){if(!a.Hb&&\"undefined\"==typeof XMLHttpRequest&&\"undefined\"!=typeof ActiveXObject){for(var b=[\"MSXML2.XMLHTTP.6.0\",\"MSXML2.XMLHTTP.3.0\",\"MSXML2.XMLHTTP\",\"Microsoft.XMLHTTP\"],c=0;c<b.length;c++){var d=b[c];try{return new ActiveXObject(d),a.Hb=d}catch(e){}}throw Error(\"Could not create ActiveXObject. ActiveX might be disabled, or MSXML might not be installed\");}return a.Hb};rd=new sd;var $=function(a){Q.call(this);this.headers=new x;this.fa=a||null;this.D=!1;this.ca=this.a=null;this.ba=this.Fa=\"\";this.K=this.Ea=this.aa=this.Ha=!1;this.ea=0;this.da=null;this.cb=\"\";this.Ga=this.Kb=!1};u($,Q);var ud=/^https?$/i,vd=[\"POST\",\"PUT\"],wd=[],xd=function(a,b,c){var d=new $;wd.push(d);b&&d.listen(\"complete\",b);d.bb(\"ready\",d.tc);d.send(a,\"POST\",c,void 0)};$.prototype.tc=function(){this.xa();pa(wd,this)};\n$.prototype.send=function(a,b,c,d){if(this.a)throw Error(\"[goog.net.XhrIo] Object is active with another request=\"+this.Fa+\"; newUri=\"+a);b=b?b.toUpperCase():\"GET\";this.Fa=a;this.ba=\"\";this.Ha=!1;this.D=!0;this.a=this.fa?td(this.fa):td(rd);this.ca=this.fa?qd(this.fa):qd(rd);this.a.onreadystatechange=r(this.eb,this);try{this.Ea=!0,this.a.open(b,String(a),!0),this.Ea=!1}catch(e){this.ga(5,e);return}a=c||\"\";var f=this.headers.clone();d&&Ta(d,function(a,b){f.set(b,a)});d=oa(f.F());c=h.FormData&&a instanceof\nh.FormData;!(0<=ja(vd,b))||d||c||f.set(\"Content-Type\",\"application/x-www-form-urlencoded;charset=utf-8\");f.forEach(function(a,b){this.a.setRequestHeader(b,a)},this);this.cb&&(this.a.responseType=this.cb);\"withCredentials\"in this.a&&(this.a.withCredentials=this.Kb);try{yd(this),0<this.ea&&((this.Ga=zd(this.a))?(this.a.timeout=this.ea,this.a.ontimeout=r(this.fb,this)):this.da=Yc(this.fb,this.ea,this)),this.aa=!0,this.a.send(a),this.aa=!1}catch(k){this.ga(5,k)}};\nvar zd=function(a){return I&&M(9)&&ea(a.timeout)&&void 0!==a.ontimeout},na=function(a){return\"content-type\"==a.toLowerCase()};$.prototype.fb=function(){\"undefined\"!=typeof aa&&this.a&&(this.ba=\"Timed out after \"+this.ea+\"ms, aborting\",this.dispatchEvent(\"timeout\"),this.abort(8))};$.prototype.ga=function(a,b){this.D=!1;this.a&&(this.K=!0,this.a.abort(),this.K=!1);this.ba=b;Ad(this);Bd(this)};var Ad=function(a){a.Ha||(a.Ha=!0,a.dispatchEvent(\"complete\"),a.dispatchEvent(\"error\"))};\n$.prototype.abort=function(){this.a&&this.D&&(this.D=!1,this.K=!0,this.a.abort(),this.K=!1,this.dispatchEvent(\"complete\"),this.dispatchEvent(\"abort\"),Bd(this))};$.prototype.l=function(){this.a&&(this.D&&(this.D=!1,this.K=!0,this.a.abort(),this.K=!1),Bd(this,!0));$.L.l.call(this)};$.prototype.eb=function(){this.Y||(this.Ea||this.aa||this.K?Cd(this):this.jc())};$.prototype.jc=function(){Cd(this)};\nvar Cd=function(a){if(a.D&&\"undefined\"!=typeof aa&&(!a.ca[1]||4!=Dd(a)||2!=Ed(a)))if(a.aa&&4==Dd(a))Yc(a.eb,0,a);else if(a.dispatchEvent(\"readystatechange\"),4==Dd(a)){a.D=!1;try{var b=Ed(a),c,d;t:switch(b){case 200:case 201:case 202:case 204:case 206:case 304:case 1223:d=!0;break t;default:d=!1}if(!(c=d)){var e;if(e=0===b){var f=nd(1,String(a.Fa));if(!f&&self.location)var k=self.location.protocol,f=k.substr(0,k.length-1);e=!ud.test(f?f.toLowerCase():\"\")}c=e}if(c)a.dispatchEvent(\"complete\"),a.dispatchEvent(\"success\");\nelse{var l;try{l=2<Dd(a)?a.a.statusText:\"\"}catch(N){l=\"\"}a.ba=l+\" [\"+Ed(a)+\"]\";Ad(a)}}finally{Bd(a)}}},Bd=function(a,b){if(a.a){yd(a);var c=a.a,d=a.ca[0]?ba:null;a.a=null;a.ca=null;b||a.dispatchEvent(\"ready\");try{c.onreadystatechange=d}catch(e){}}},yd=function(a){a.a&&a.Ga&&(a.a.ontimeout=null);ea(a.da)&&(h.clearTimeout(a.da),a.da=null)},Dd=function(a){return a.a?a.a.readyState:0},Ed=function(a){try{return 2<Dd(a)?a.a.status:-1}catch(b){return-1}};var Fd=function(a,b,c){this.r=a||null;this.oc=!!c},Hd=function(a){if(!a.c&&(a.c=new x,a.h=0,a.r))for(var b=a.r.split(\"&\"),c=0;c<b.length;c++){var d=b[c].indexOf(\"=\"),e=null,f=null;0<=d?(e=b[c].substring(0,d),f=b[c].substring(d+1)):e=b[c];e=decodeURIComponent(e.replace(/\\+/g,\" \"));e=Gd(a,e);a.add(e,f?decodeURIComponent(f.replace(/\\+/g,\" \")):\"\")}};g=Fd.prototype;g.c=null;g.h=null;g.add=function(a,b){Hd(this);this.r=null;a=Gd(this,a);var c=this.c.get(a);c||this.c.set(a,c=[]);c.push(b);this.h++;return this};\ng.remove=function(a){Hd(this);a=Gd(this,a);return this.c.Q(a)?(this.r=null,this.h-=this.c.get(a).length,this.c.remove(a)):!1};g.Q=function(a){Hd(this);a=Gd(this,a);return this.c.Q(a)};g.F=function(){Hd(this);for(var a=this.c.t(),b=this.c.F(),c=[],d=0;d<b.length;d++)for(var e=a[d],f=0;f<e.length;f++)c.push(b[d]);return c};g.t=function(a){Hd(this);var b=[];if(n(a))this.Q(a)&&(b=qa(b,this.c.get(Gd(this,a))));else{a=this.c.t();for(var c=0;c<a.length;c++)b=qa(b,a[c])}return b};\ng.set=function(a,b){Hd(this);this.r=null;a=Gd(this,a);this.Q(a)&&(this.h-=this.c.get(a).length);this.c.set(a,[b]);this.h++;return this};g.get=function(a,b){var c=a?this.t(a):[];return 0<c.length?String(c[0]):b};g.toString=function(){if(this.r)return this.r;if(!this.c)return\"\";for(var a=[],b=this.c.F(),c=0;c<b.length;c++)for(var d=b[c],e=encodeURIComponent(String(d)),d=this.t(d),f=0;f<d.length;f++){var k=e;\"\"!==d[f]&&(k+=\"=\"+encodeURIComponent(String(d[f])));a.push(k)}return this.r=a.join(\"&\")};\ng.clone=function(){var a=new Fd;a.r=this.r;this.c&&(a.c=this.c.clone(),a.h=this.h);return a};var Gd=function(a,b){var c=String(b);a.oc&&(c=c.toLowerCase());return c};var Id=function(a,b){this.$b=a;this.na=b};Id.prototype.send=function(a,b){if(gb&&!navigator.onLine)return pc();var c=new S,d=Jd(a,b);d.length>this.na?c.w({status:\"payload-too-big\",Ba:Ra(\"Encoded hit length == %s, but should be <= %s.\",d.length,this.na)}):xd(this.$b,function(){c.G(hd)},d);return c};var Jd=function(a,b){var c=new Fd;c.add(Da.name,a);Ua(b,function(a,b){c.add(a.name,b.toString())});return c.toString()};var Kd=function(a,b,c){this.k=a;this.Qb=b;this.na=c};Kd.prototype.Sa=function(){if(!this.q){var a=this.k;if(!jc(a.ha).C)throw Error(\"Cannot construct shared channel prior to settings being ready.\");new ad;var b=new cd(new Id(this.Qb,this.na)),c=new jd;this.q=new bd(a,new kd(a,new id(c,b)))}return this.q};var Ld=new x,Md=function(){if(!Ba){var a=new Tc(\"google-analytics\");Ba=new X(a)}return Ba};t(\"goog.async.Deferred\",S);t(\"goog.async.Deferred.prototype.addCallback\",S.prototype.J);t(\"goog.events.EventTarget\",Q);t(\"goog.events.EventTarget.prototype.listen\",Q.prototype.listen);t(\"analytics.getService\",function(a){var b=Ld.get(a,null);if(null===b){var b=chrome.runtime.getManifest().version,c=Md();if(!Ca){var d=Md();Ca=new Wc(d,new Kd(d,\"https://www.google-analytics.com/collect\",8192))}b=new Hc(\"ca1.5.2\",a,b,c,Ca);Ld.set(a,b)}return b});t(\"analytics.internal.GoogleAnalyticsService\",Hc);\nt(\"analytics.internal.GoogleAnalyticsService.prototype.getTracker\",Hc.prototype.Cc);t(\"analytics.internal.GoogleAnalyticsService.prototype.getConfig\",Hc.prototype.Bc);t(\"analytics.internal.ServiceSettings\",X);t(\"analytics.internal.ServiceSettings.prototype.setTrackingPermitted\",X.prototype.Lc);t(\"analytics.internal.ServiceSettings.prototype.isTrackingPermitted\",X.prototype.va);t(\"analytics.internal.ServiceSettings.prototype.setSampleRate\",X.prototype.Kc);t(\"analytics.internal.ServiceTracker\",W);\nt(\"analytics.internal.ServiceTracker.prototype.send\",W.prototype.send);t(\"analytics.internal.ServiceTracker.prototype.sendAppView\",W.prototype.Gc);t(\"analytics.internal.ServiceTracker.prototype.sendEvent\",W.prototype.Hc);t(\"analytics.internal.ServiceTracker.prototype.sendSocial\",W.prototype.Jc);t(\"analytics.internal.ServiceTracker.prototype.sendException\",W.prototype.Ic);t(\"analytics.internal.ServiceTracker.prototype.sendTiming\",W.prototype.Cb);\nt(\"analytics.internal.ServiceTracker.prototype.startTiming\",W.prototype.Mc);t(\"analytics.internal.ServiceTracker.Timing\",Gc);t(\"analytics.internal.ServiceTracker.Timing.prototype.send\",Gc.prototype.send);t(\"analytics.internal.ServiceTracker.prototype.forceSessionStart\",W.prototype.Ac);t(\"analytics.internal.ServiceTracker.prototype.addFilter\",W.prototype.S);t(\"analytics.internal.FilterChannel.Hit\",T);t(\"analytics.internal.FilterChannel.Hit.prototype.getHitType\",T.prototype.Gb);\nt(\"analytics.internal.FilterChannel.Hit.prototype.getParameters\",T.prototype.T);t(\"analytics.internal.FilterChannel.Hit.prototype.cancel\",T.prototype.cancel);t(\"analytics.ParameterMap\",C);t(\"analytics.ParameterMap.Entry\",C.Entry);t(\"analytics.ParameterMap.prototype.set\",C.prototype.set);t(\"analytics.ParameterMap.prototype.get\",C.prototype.get);t(\"analytics.ParameterMap.prototype.remove\",C.prototype.remove);t(\"analytics.ParameterMap.prototype.toObject\",C.prototype.Jb);\nt(\"analytics.HitTypes.APPVIEW\",\"appview\");t(\"analytics.HitTypes.EVENT\",\"event\");t(\"analytics.HitTypes.SOCIAL\",\"social\");t(\"analytics.HitTypes.TRANSACTION\",\"transaction\");t(\"analytics.HitTypes.ITEM\",\"item\");t(\"analytics.HitTypes.TIMING\",\"timing\");t(\"analytics.HitTypes.EXCEPTION\",\"exception\");ua(Ka,function(a){var b=a.id.replace(/[A-Z]/,\"_$&\").toUpperCase();t(\"analytics.Parameters.\"+b,a)});t(\"analytics.filters.EventLabelerBuilder\",A);\nt(\"analytics.filters.EventLabelerBuilder.prototype.appendToExistingLabel\",A.prototype.wc);t(\"analytics.filters.EventLabelerBuilder.prototype.stripValue\",A.prototype.Nc);t(\"analytics.filters.EventLabelerBuilder.prototype.powersOfTwo\",A.prototype.Ec);t(\"analytics.filters.EventLabelerBuilder.prototype.rangeBounds\",A.prototype.Fc);t(\"analytics.filters.EventLabelerBuilder.prototype.build\",A.prototype.Ca);t(\"analytics.filters.FilterBuilder\",z);t(\"analytics.filters.FilterBuilder.builder\",Pa);\nt(\"analytics.filters.FilterBuilder.prototype.when\",z.prototype.when);t(\"analytics.filters.FilterBuilder.prototype.whenHitType\",z.prototype.zb);t(\"analytics.filters.FilterBuilder.prototype.whenValue\",z.prototype.Oc);t(\"analytics.filters.FilterBuilder.prototype.applyFilter\",z.prototype.xb);t(\"analytics.filters.FilterBuilder.prototype.build\",z.prototype.Ca);t(\"analytics.EventBuilder\",D);t(\"analytics.EventBuilder.builder\",function(){return Va});t(\"analytics.EventBuilder.prototype.category\",D.prototype.xc);\nt(\"analytics.EventBuilder.prototype.action\",D.prototype.action);t(\"analytics.EventBuilder.prototype.label\",D.prototype.label);t(\"analytics.EventBuilder.prototype.value\",D.prototype.value);t(\"analytics.EventBuilder.prototype.dimension\",D.prototype.yc);t(\"analytics.EventBuilder.prototype.metric\",D.prototype.Dc);t(\"analytics.EventBuilder.prototype.send\",D.prototype.send); })()\n"
  },
  {
    "path": "_archive/apps/samples/analytics/main.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Analytics sample app</title>\n  </head>\n  <body>\n    <div>\n      <button id=\"chocolate\">Chocolate</button>\n      <button id=\"vanilla\">Vanilla</button>\n\n      <div id=out></div>\n    </div>\n    <div id=\"settings\">\n      <h1>Settings</h1>\n      <div id=\"settings-loading\">\n        Loading settings...\n      </div>\n      <div id=\"settings-loaded\" hidden>\n        <label>\n          <input id=\"analytics\" type=\"checkbox\" />\n          Send anonymous usage data.\n        </label>\n      </div>\n    </div>\n    <script src=\"google-analytics-bundle.js\"></script>\n    <script src=\"main.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/analytics/main.js",
    "content": "// Copyright 2013 Google Inc. All Rights Reserved.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nvar service, tracker, out;\n\nfunction initAnalyticsConfig(config) {\n  document.getElementById('settings-loading').hidden = true;\n  document.getElementById('settings-loaded').hidden = false;\n\n  var checkbox = document.getElementById('analytics');\n  checkbox.checked = config.isTrackingPermitted();\n  checkbox.onchange = function() {\n    config.setTrackingPermitted(checkbox.checked);\n  };\n}\n\nfunction startApp() {\n  // Initialize the Analytics service object with the name of your app.\n  service = analytics.getService('ice_cream_app');\n  service.getConfig().addCallback(initAnalyticsConfig);\n\n  // Get a Tracker using your Google Analytics app Tracking ID.\n  tracker = service.getTracker('UA-XXXXX-X');\n\n  // Record an \"appView\" each time the user launches your app or goes to a new\n  // screen within the app.\n  tracker.sendAppView('MainView');\n\n  var button1 = document.getElementById('chocolate');\n  var button2 = document.getElementById('vanilla');\n  out = document.getElementById('out');\n  [button1, button2].forEach(addButtonListener);\n}\n\nfunction addButtonListener(button) {\n  button.addEventListener('click', function() {\n    tracker.sendEvent('Flavor', 'Choose', button.id);\n    out.textContent = 'You chose: ' + button.textContent;\n  });\n}\n\nwindow.onload = startApp;\n"
  },
  {
    "path": "_archive/apps/samples/analytics/manifest.json",
    "content": "{\n  \"name\": \"Analytics Sample App\",\n  \"description\": \"An example app using Google Analytics without the Closure library\",\n  \"version\": \"1.2.5\",\n  \"manifest_version\": 2,\n  \"icons\": {\"128\": \"icon_128.png\"},\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [\n    \"https://www.google-analytics.com/*\",\n    \"storage\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/analytics/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"analytics\",\n  \"files_with_snippets\": [ ],\n  \"android\": {\"works\": true},\n  \"ios\": {\"works\": true}\n}\n"
  },
  {
    "path": "_archive/apps/samples/appengine-channelapi/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/alieplnmdkoekpkepkfgickpmhhabfkl\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n\n# AppEngine Channel API example\n\nThis is an example of how to use the AppEngine's Channel API in a Chrome Packaged App. Since the Channel API is not directly compatible with the CSP restrictions in a packaged app, this sample uses a WebView and a \"proxy\" object that communicates with the Webview using async postMessage.\n\nThis code is an adaptation of the [Tic Tac Toe game](https://code.google.com/p/channel-tac-toe/) used by the AppEngine team to demonstrate the Channel API. The main modifications from the original game are:\n\n- index.html is not rendered as a template in the server, it is embedded in the app. All responses from the server are JSON messages;\n- the server doesn't use the appengine's user library, since that would require another authentication step. Instead, the server attributes a random UUID to the first user and another to the second. This user ID is returned to the client that uses it in the following calls. It is not secure, but simple enough for this sample. In a real application, this method would allow an eaversdropper to capture the GET request and replay with different commands;\n- all the interations with the channel API are abstracted in the ChannelAPI object defined by channel_in_a_webview.js. This object communicates with the webview page (channel_in_a_webview.html), served to the webview from the appengine server.\n\nTo run:\n\n- go to the `appengine` folder and type `dev_appserver.py .`\n- install the Chrome Packaged App in the `app` folder\n- run the Chrome packaged app twice and copy the game ID from one screen to the other\n- play\n\n* [Appengine Channel API](https://developers.google.com/appengine/docs/python/channel)\n* [Webview](https://developer.chrome.com/apps/tags/webview)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/appengine_channelapi/app/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/appengine-channelapi/app/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/alieplnmdkoekpkepkfgickpmhhabfkl\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n"
  },
  {
    "path": "_archive/apps/samples/appengine-channelapi/app/channel_in_a_webview.js",
    "content": "(function (exports) {\n\n  function ChannelInAWebview(rootUrl) {\n    this.webview = document.createElement('webview');\n    this.webview.src = rootUrl+'/static/channel_in_a_webview.html';\n    this.webview.style.width='0px';\n    this.webview.style.height='0px';\n    this.webview.style.display='none';\n    this.webview.style.width='10px';\n    this.webview.style.height='10px';\n    this.webview.style.display='block';\n    this.webview.style.border='1px solid red';\n    document.body.appendChild(this.webview);\n\n    this.onOpened = this.onMessage = null;\n\n    window.addEventListener('message', function(e) {\n      // sanity check for origin\n      if ( this.webview.src.indexOf(e.origin)!=0 ) {\n        console.error(\"Invalid origin of message, ignoring\");\n        return;\n      }\n      // onOpened event\n      if ( this.onOpened && e.data && 'onOpened' in e.data ) {\n        this.onOpened();\n      }\n      // onMessage event\n      if ( this.onMessage && e.data && 'onMessage' in e.data ) {\n        this.onMessage.call(this, e.data['onMessage']);\n      }\n    }.bind(this));\n  }\n\n\n  ChannelInAWebview.prototype._sendMessageToWebview = function(data) {\n    this.webview.contentWindow.postMessage(data, this.webview.src);\n  }\n\n  ChannelInAWebview.prototype.openChannel = function(token) {\n    this._sendMessageToWebview({'openChannel': token});\n  }\n\n  exports.ChannelInAWebview = ChannelInAWebview;\n\n})(window);\n"
  },
  {
    "path": "_archive/apps/samples/appengine-channelapi/app/game.js",
    "content": "\nROOT = 'http:/localhost:8080';\n\nwindow.addEventListener('DOMContentLoaded', init);\n\nfunction init() {\n  var xhr = new XMLHttpRequest();\n  xhr.open('GET', ROOT);\n  xhr.onload = function(e) {\n    game(JSON.parse(e.target.responseText));\n  };\n  xhr.send();\n}\n\n\nfunction game(data) {\n\n  // event listeners:\n  document.querySelector('#go').addEventListener('click', function() {\n    var xhr = new XMLHttpRequest();\n    xhr.open('GET', ROOT+'/?g='+document.querySelector('#another_game_key').value);\n    xhr.onload = function(e) {\n      initialize(JSON.parse(e.target.responseText));\n    };\n    xhr.send();\n  });\n\n  var handleMouseOver = function(e) { highlightSquare(parseInt(e.target.id)) };\n  var handleOnClick = function(e) { moveInSquare(parseInt(e.target.id)) };\n  var i;\n  for (i = 0; i < 9; i++) {\n    var square = document.getElementById(i);\n    square.onmouseover = handleMouseOver;\n    square.onclick = handleOnClick;\n  }\n\n\n  var state = {\n  };\n\n  updateGame = function() {\n    for (i = 0; i < 9; i++) {\n      var square = document.getElementById(i);\n      square.innerHTML = state.board[i];\n      if (state.winner != '' && state.winningBoard != '') {\n        if (state.winningBoard[i] == state.board[i]) {\n          if (state.winner == state.me) {\n            square.style.background = \"green\";\n          } else {\n            square.style.background = \"red\";\n          }\n        } else {\n          square.style.background = \"white\";\n        }\n      }\n    }\n    \n    var display = {\n      'other-player': 'none',\n      'your-move': 'none',\n      'their-move': 'none',\n      'you-won': 'none',\n      'you-lost': 'none',\n      'board': 'block'\n    }; \n\n    if (!state.userO || state.userO == '') {\n      display['other-player'] = 'block';\n      display['board'] = 'none';\n    } else if (state.winner == state.me) {\n      display['you-won'] = 'block';\n    } else if (state.winner != '') {\n      display['you-lost'] = 'block';\n    } else if (isMyMove()) {\n      display['your-move'] = 'block';\n    } else {\n      display['their-move'] = 'block';\n    }\n    \n    for (var label in display) {\n      document.getElementById(label).style.display = display[label];\n    }\n  };\n  \n  isMyMove = function() {\n    return (state.winner == \"\") && \n        (state.moveX == (state.userX == state.me));\n  }\n\n  myPiece = function() {\n    return state.userX == state.me ? 'X' : 'O';\n  }\n\n  sendMessage = function(path, opt_param) {\n    path = ROOT + path + '?g=' + state.game_key;\n    if (state.me) {\n      path += '&u=' + state.me;\n    }\n    if (opt_param) {\n      path += '&' + opt_param;\n    }\n    var xhr = new XMLHttpRequest();\n    xhr.open('POST', path, true);\n    xhr.send();\n  };\n\n  moveInSquare = function(id) {\n    if (isMyMove() && state.board[id] == ' ') {\n      sendMessage('/move', 'i=' + id);\n    }\n  }\n\n  highlightSquare = function(id) {\n    if (state.winner != \"\") {\n      return;\n    }\n    for (i = 0; i < 9; i++) {\n      if (i == id  && isMyMove()) {\n        if (state.board[i] = ' ') {\n          color = 'lightBlue';\n        } else {\n          color = 'lightGrey';\n        }\n      } else {\n        color = 'white';\n      }\n\n      document.getElementById(i).style['background'] = color;\n    }\n  }\n  \n  onOpened = function() {\n    sendMessage('/opened');\n  };\n  \n  onMessage = function(m) {\n    var newState = JSON.parse(m.data);\n    state.board = newState.board || state.board;\n    state.userX = newState.userX || state.userX;\n    state.userO = newState.userO || state.userO;\n    state.moveX = newState.moveX;\n    state.winner = newState.winner || \"\";\n    state.winningBoard = newState.winningBoard || \"\";\n    updateGame();\n  }\n  \n  initialize = function(data) {\n    state = {\n      game_key: data.game_key,\n      me: data.me\n    }\n    var gamelinks = document.querySelectorAll('.gamelink');\n    for (var i=0; i<gamelinks.length; i++) {\n      gamelinks[i].textContent=data.game_key;\n    }\n    channelAPI.openChannel(data.token);\n    onMessage({data: data.initial_message});\n  }      \n\n  var channelAPI = new ChannelInAWebview( ROOT );\n  channelAPI.onOpened = onOpened;\n  channelAPI.onMessage = onMessage;\n\n  setTimeout( function() {initialize(data)}, 100 );\n\n\n}\n"
  },
  {
    "path": "_archive/apps/samples/appengine-channelapi/app/index.css",
    "content": "        body {\n          font-family: 'Helvetica';\n        }\n\n        #board {\n          width:152px; \n          height: 152px;\n          margin: 20px auto;\n        }\n        \n        #display-area {\n          text-align: center;\n        }\n        \n        #this-game {\n          font-size: 9pt;\n        }\n        \n        #winner {\n        }\n        \n        table {\n          border-collapse: collapse;\n        }\n        \n        td {\n          width: 50px;\n          height: 50px;\n          font-family: \"Helvetica\";\n          font-size: 16pt;\n          text-align: center;\n          vertical-align: middle;\n          margin:0px;\n          padding: 0px;\n        }\n        \n        div.cell {\n          float: left;\n          width: 50px;\n          height: 50px;\n          border: none;\n          margin: 0px;\n          padding: 0px;\n        }\n        \n        div.mark {\n          position: absolute;\n          top: 15px;          \n        }\n        \n        div.l {\n          border-right: 1pt solid black;\n        }\n        \n        div.c {\n        }\n        \n        div.r {\n          border-left: 1pt solid black;\n        }\n        \n        div.t {\n          border-bottom: 1pt solid black;\n        }\n        \n        div.m {\n        }\n        \n        div.b {\n          border-top: 1pt solid black;\n        }\n"
  },
  {
    "path": "_archive/apps/samples/appengine-channelapi/app/index.html",
    "content": "<html>\n  <head>\n      <link rel=\"stylesheet\" href=\"index.css\">\n  </head>\n  <body>\n    <script type='text/javascript' src=\"channel_in_a_webview.js\"></script>\n    <script type='text/javascript' src=\"game.js\"></script>\n    <div id='display-area'>\n      <h2>Channel-based Tic Tac Toe</h2>\n      <div id='other-player' style='display:none'>\n        Waiting for another player to join.<br>\n        Send them this game ID to play:<br>\n        <div id='game-link' style=\"-webkit-user-select: initial;\" class=\"gamelink\"></div>\n        or enter a game ID another player sent you:\n        <input type=\"text\" id=\"another_game_key\"></input>\n        <button id=\"go\">go</button>\n      </div>\n      <div id='your-move' style='display:none'>\n        Your move! Click a square to place your piece.\n      </div>\n      <div id='their-move' style='display:none'>\n        Waiting for other player to move...\n      </div>\n      <div id='you-won'>\n        You won this game!\n      </div>\n      <div id='you-lost'>\n        You lost this game.\n      </div>\n      <div id='board'>\n        <div class='t l cell'><table><tr><td id='0'></td></tr></td></table></div>\n        <div class='t c cell'><table><tr><td id='1'></td></tr></td></table></div>\n        <div class='t r cell'><table><tr><td id='2'></td></tr></td></table></div>\n        <div class='m l cell'><table><tr><td id='3'></td></tr></td></table></div>\n        <div class='m c cell'><table><tr><td id='4'></td></tr></td></table></div>\n        <div class='m r cell'><table><tr><td id='5'></td></tr></td></table></div>\n        <div class='b l cell'><table><tr><td id='6'></td></tr></td></table></div>\n        <div class='b c cell'><table><tr><td id='7'></td></tr></td></table></div>\n        <div class='b r cell'><table><tr><td id='8'></td></tr></td></table></div>\n      </div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/appengine-channelapi/app/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n  \tid: \"appEngineSampleID\",\n    innerBounds: {\n      width: 500,\n      height: 300\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/appengine-channelapi/app/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Appengine Channel API Sample\",\n  \"version\": \"2\",\n  \"minimum_chrome_version\": \"27\",\n  \"permissions\": [\"webview\", \"http://localhost:8080/*\"],\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/appengine-channelapi/appengine/app.yaml",
    "content": "application: moishetest\r\nversion: 1\r\nruntime: python\r\napi_version: 1\r\n\r\nhandlers:\r\n- url: /static\r\n  static_dir: static\r\n\r\n- url: /.*\r\n  script: chatactoe.py\r\n\r\ninbound_services:\r\n- channel_presence\r\n"
  },
  {
    "path": "_archive/apps/samples/appengine-channelapi/appengine/chatactoe.py",
    "content": "#!/usr/bin/python2.4\n#\n# Copyright 2010 Google Inc. All Rights Reserved.\n\n# pylint: disable-msg=C6310\n\n\"\"\"Channel Tic Tac Toe\n\nThis module demonstrates the App Engine Channel API by implementing a\nsimple tic-tac-toe game.\n\"\"\"\n\nimport datetime\nimport logging\nimport os\nimport random\nimport re\nimport uuid\nimport sys\nfrom django.utils import simplejson\nfrom google.appengine.api import channel\nfrom google.appengine.ext import db\nfrom google.appengine.ext import webapp\nfrom google.appengine.ext.webapp import template\nfrom google.appengine.ext.webapp.util import run_wsgi_app\n\n\nclass Game(db.Model):\n  \"\"\"All the data we store for a game\"\"\"\n  userX = db.StringProperty()\n  userO = db.StringProperty()\n  board = db.StringProperty()\n  moveX = db.BooleanProperty()\n  winner = db.StringProperty()\n  winning_board = db.StringProperty()\n  \n\nclass Wins():\n  x_win_patterns = ['XXX......',\n                    '...XXX...',\n                    '......XXX',\n                    'X..X..X..',\n                    '.X..X..X.',\n                    '..X..X..X',\n                    'X...X...X',\n                    '..X.X.X..']\n\n  o_win_patterns = map(lambda s: s.replace('X','O'), x_win_patterns)\n  \n  x_wins = map(lambda s: re.compile(s), x_win_patterns)\n  o_wins = map(lambda s: re.compile(s), o_win_patterns)\n\n\nclass GameUpdater():\n  game = None\n\n  def __init__(self, game):\n    self.game = game\n\n  def get_game_message(self):\n    gameUpdate = {\n      'board': self.game.board,\n      'userX': self.game.userX,\n      'userO': '' if not self.game.userO else self.game.userO,\n      'moveX': self.game.moveX,\n      'winner': self.game.winner,\n      'winningBoard': self.game.winning_board\n    }\n    return simplejson.dumps(gameUpdate)\n\n  def send_update(self):\n    message = self.get_game_message()\n    channel.send_message(self.game.userX + self.game.key().id_or_name(), message)\n    if self.game.userO:\n      channel.send_message(self.game.userO + self.game.key().id_or_name(), message)\n\n  def check_win(self):\n    if self.game.moveX:\n      # O just moved, check for O wins\n      wins = Wins().o_wins\n      potential_winner = self.game.userO\n    else:\n      # X just moved, check for X wins\n      wins = Wins().x_wins\n      potential_winner = self.game.userX\n      \n    for win in wins:\n      if win.match(self.game.board):\n        self.game.winner = potential_winner\n        self.game.winning_board = win.pattern\n        return\n\n  def make_move(self, position, user):\n    if position >= 0 and user == self.game.userX or user == self.game.userO:\n      if self.game.moveX == (user == self.game.userX):\n        boardList = list(self.game.board)\n        if (boardList[position] == ' '):\n          boardList[position] = 'X' if self.game.moveX else 'O'\n          self.game.board = \"\".join(boardList)\n          self.game.moveX = not self.game.moveX\n          self.check_win()\n          self.game.put()\n          self.send_update()\n          return\n\n\nclass GameFromRequest():\n  game = None;\n  user = None;\n\n  def __init__(self, request):\n    self.user = request.get('u')\n    game_key = request.get('g')\n    if game_key:\n      self.game = Game.get_by_key_name(game_key)\n\n  def get_game_data(self):\n    return ( self.game, self.user )\n\n\nclass MovePage(webapp.RequestHandler):\n  def post(self):\n    (game, user) = GameFromRequest(self.request).get_game_data()\n    if game and user:\n      id = int(self.request.get('i'))\n      GameUpdater(game).make_move(id, user)\n\n\nclass OpenedPage(webapp.RequestHandler):\n  def post(self):\n    (game, user) = GameFromRequest(self.request).get_game_data()\n    GameUpdater(game).send_update()\n\n\nclass MainPage(webapp.RequestHandler):\n  \"\"\"The main UI page, renders the 'index.html' template.\"\"\"\n\n  def get(self):\n    \"\"\"Renders the main page. When this page is shown, we create a new\n    channel to push asynchronous updates to the client.\"\"\"\n    game_key = self.request.get('g')\n    game = None\n    user = None\n    if game_key:\n      game = Game.get_by_key_name(game_key)\n      if game: \n        user = game.userO\n        if not user:\n          user = uuid.uuid4().hex\n          game.userO = user\n          game.put()\n\n    if not game:\n      game_key = uuid.uuid4().hex\n      user = uuid.uuid4().hex\n      game = Game(key_name = game_key,\n                  moveX = True,\n                  userX = user,\n                  complete = False,\n                  board = '         ')\n      game.put()\n\n\n    game_link = 'http://localhost:8080/?g=' + game_key\n\n    if game:\n      token = channel.create_channel(user + game_key)\n      values = {'token': token,\n                'me': user,\n                'game_key': game_key,\n                'game_link': game_link,\n                'initial_message': GameUpdater(game).get_game_message()\n               }\n      self.response.out.write(simplejson.dumps(values))\n    else:\n      self.response.out.write(simplejson.dumps({'error': 'No such game'}))\n\n\napplication = webapp.WSGIApplication([\n    ('/', MainPage),\n    ('/opened', OpenedPage),\n    ('/move', MovePage)], debug=True)\n\n\ndef main():\n  run_wsgi_app(application)\n\nif __name__ == \"__main__\":\n  main()\n"
  },
  {
    "path": "_archive/apps/samples/appengine-channelapi/appengine/static/channel_in_a_webview.html",
    "content": "<html>\n<!-- This file goes into your web application folder, and is accessed through a webview -->\n  <head>\n      <script src='/_ah/channel/jsapi'></script>\n  </head>\n  <body>\n    <script type='text/javascript'>\n\nvar appWindow, appOrigin;\n\nfunction onWindowMessageReceived(e) {\n  // sanity check for origin\n  if ( e.origin.indexOf('chrome-extension://')!=0 ) {\n    console.error(\"Invalid origin of message, ignoring\");\n    return;\n  }\n  if (!appWindow || !appOrigin) {\n    appWindow = e.source;\n    appOrigin = e.origin;\n  }\n  if ( e.data && 'openChannel' in e.data ) {\n    openChannel(e.data['openChannel']);\n  }\n}\n\nwindow.addEventListener('message', onWindowMessageReceived);\n\nfunction doSendWindowMessage(m) {\n  if (appWindow && appOrigin) {\n    appWindow.postMessage(m, appOrigin)\n  } else {\n    console.log(\"ERROR: don't have container app info - no initial message received\");\n  }\n}\n\n\nfunction openChannel(token) {\n  var channel = new goog.appengine.Channel(token);\n  var onopen = function(m) { doSendWindowMessage({'onOpened': m}); };\n  var onmessage = function (m) { doSendWindowMessage({'onMessage': m}); };\n  var handler = {\n    'onopen': onopen,\n    'onmessage': onmessage,\n    'onerror': function() {},\n    'onclose': function() {}\n  };\n  var socket = channel.open(handler);\n  socket.onopen = onopen;\n  socket.onmessage = onmessage;\n}\n\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/appsquare/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/loimmcmmgnhkbppokdpfhlccebcpicld\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# AppSquare\n\nThis is a basic Foursquare client implemented as a packaged app.\n\nIt just displays recent checkins of the logged in user's friends. To log into Foursquare, it uses the [identity API](http://developer.chrome.com/apps/identity.html) (specfically, the `launchWebAuthFlow` method). Once it gets the OAuth token, it uses the [storage API](http://developer.chrome.com/apps/storage) to persist it. It also uses the [W3C Geolocation API](http://www.w3.org/TR/geolocation-API/) to pass in the current location to the Foursquare API.\n\nWhen running it unpacked, it will normally have a different ID (the unpacked\nextension ID is a hash of the path on disk). However, this will result in the\nauth API not working, since the redirect URL will be different. To force the\nunpacked app to have the same ID, add this key and value to `manifest.json`:\n\n    \"key\": \"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDnyZBBnfu+qNi1x5C0YKIob4ACrA84HdMArTGobttMHIxM2Z6aLshFmoKZa/pbyQS6D5yNywr4KM/llWiY2aV2puIflUxRT8SjjPehswCvm6eWQM+r3mB755m48x+diDl8URJsX4AJ3pQHnKWEvitZcuBh0GTfsLzKU/BfHEaH7QIDAQAB\"\n(this is a base 64 encoded version of the app's public key)\n\nThe key *must* be removed before uploading it to the store.\n\n## Resources\n\n* [Identity](https://developer.chrome.com/docs/apps/app_identity/)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/appsquare/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/appsquare/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('main.html', {\n  \tid: \"appSquareID\",\n    innerBounds: {\n      width: 300,\n      height: 600\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/appsquare/foursquare.js",
    "content": "var foursquare = {};\n\n(function(api) {\n  // See \"Pure AJAX application\" from\n  // https://developer.foursquare.com/overview/auth\n  var ACCESS_TOKEN_PREFIX = '#access_token=';\n\n  var storage = chrome.storage.local;\n  var ACCESS_TOKEN_STORAGE_KEY = 'foursquare-access-token';\n\n  var getAccessToken = function(callback) {\n    storage.get(ACCESS_TOKEN_STORAGE_KEY, function(items) {\n      callback(items[ACCESS_TOKEN_STORAGE_KEY]);\n    });\n  }\n\n  var setAccessToken = function(accessToken, callback) {\n    var items = {};\n    items[ACCESS_TOKEN_STORAGE_KEY] = accessToken;\n    storage.set(items, callback);\n  }\n\n  var clearAccessToken = function(callback) {\n    storage.remove(ACCESS_TOKEN_STORAGE_KEY, callback);\n  }\n\n  // Tokens state is not exposed via the API\n  api.isSignedIn = function(callback) {\n    getAccessToken(function(accessToken) {\n      callback(!!accessToken);\n    });\n  };\n  api.signIn = function(appId, clientId, successCallback, errorCallback) {\n    var redirectUrl = chrome.identity.getRedirectURL();\n    var authUrl = 'https://foursquare.com/oauth2/authorize?' +\n        'client_id=' + clientId + '&' +\n        'response_type=token&' +\n        'redirect_uri=' + encodeURIComponent(redirectUrl);\n    chrome.identity.launchWebAuthFlow(\n        {url: authUrl, interactive: true},\n        function(responseUrl) {\n        if (chrome.runtime.lastError) {\n          errorCallback(chrome.runtime.lastError.message);\n          return;\n        }\n\n        var accessTokenStart = responseUrl.indexOf(ACCESS_TOKEN_PREFIX);\n\n        if (!accessTokenStart) {\n          errorCallback('Unexpected responseUrl: ' + responseUrl);\n          return;\n        }\n\n        var accessToken = responseUrl.substring(\n            accessTokenStart + ACCESS_TOKEN_PREFIX.length);\n\n        setAccessToken(accessToken, successCallback);\n      });\n  };\n  api.signOut = function(callback) {\n    clearAccessToken(callback);\n  };\n\n  var apiMethod = function(\n      path, postData, params, successCallback, errorCallback) {\n    getAccessToken(function(accessToken) {\n      var xhr = new XMLHttpRequest();\n      // TODO(mihaip): use xhr.responseType = 'json' once it's supported.\n      xhr.onload = function() {\n        successCallback(JSON.parse(xhr.responseText).response);\n      }\n      xhr.onerror = function() {\n        errorCallback(xhr.status, xhr.statusText, JSON.parse(xhr.responseText));\n      }\n\n      var encodedParams = [];\n      for (var paramName in params) {\n        encodedParams.push(encodeURIComponent(paramName) + '=' +\n            encodeURIComponent(params[paramName]));\n      }\n      xhr.open(\n        'GET',\n        'https://api.foursquare.com/v2/' + path + '?oauth_token=' +\n            encodeURIComponent(accessToken) + '&' + encodedParams.join('&'),\n        true);\n      xhr.send(null);\n    });\n  }\n\n  api.getRecentCheckins = apiMethod.bind(api, 'checkins/recent', undefined);\n})(foursquare);\n"
  },
  {
    "path": "_archive/apps/samples/appsquare/loader.js",
    "content": "function ImageLoader(url) {\n  this.url_ = url;\n}\n\nImageLoader.prototype.loadInto = function(imageNode) {\n  var xhr = new XMLHttpRequest();\n  xhr.responseType = 'blob';\n  xhr.onload = function() {\n    // TODO(mihaip): cache the response into a local filesystem.\n    imageNode.src = window.webkitURL.createObjectURL(xhr.response);\n  }\n  xhr.open('GET', this.url_, true);\n  xhr.send();\n};\n"
  },
  {
    "path": "_archive/apps/samples/appsquare/main.html",
    "content": "<html>\n  <head>\n    <title>Foursquare Client</title>\n    <style>\n      body {\n        background: #fff;\n        font-family: Helvetica;\n        font-size: 12px;\n        padding: 0;\n        margin: 0;\n        overflow: hidden;\n      }\n\n      .container {\n        width: 100%;\n        height: 100%;\n        position: absolute;\n        top: 0;\n        opacity: 0;\n        -webkit-transition: opacity .2s;\n      }\n\n      .signed-in #signed-in,\n      .signed-out #signed-out {\n        opacity: 1;\n      }\n\n      .signed-in #signed-out,\n      .signed-out #signed-in {\n        display: none;\n      }\n\n      .header {\n        background: #eee;\n        border-bottom: solid 1px #ccc;\n        height: 23px;\n        padding: 3px;\n      }\n\n      .scrollable {\n        width: 300px;\n        height: -webkit-calc(100% - 30px);\n        overflow: auto;\n      }\n\n      #checkins {\n        list-style-type: none;\n        padding: 0;\n        margin: 0;\n      }\n\n      .checkin {\n        padding: 2px;\n        border-bottom: solid 1px #ccc;\n        overflow: hidden;\n        position: relative;\n      }\n\n      .checkin h3 {\n        margin: 0;\n        font-size: 14px;\n        line-height: 20px;\n        height: 20px;\n        white-space: nowrap;\n        overflow: hidden;\n        text-overflow: ellipsis;\n      }\n\n      .checkin .photo {\n        width: 40px;\n        height: 40px;\n        padding: 3px;\n        float: left;\n      }\n\n      .checkin .mayor-overlay {\n        position: absolute;\n        top: 0;\n        left: 0;\n        width: 18px;\n        height: 17px;\n      }\n\n      .checkin .location {\n        color: #999;\n        height: 14px;\n        overflow: hidden;\n      }\n\n      .checkin .timestamp {\n        color: #999;\n        font-size: 10px;\n        height: 12px;\n        overflow: hidden;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"signed-in\" class=\"container\">\n      <div class=\"header\">\n        <button id=\"sign-out-button\">Sign out</button>\n      </div>\n\n      <div class=\"scrollable\">\n        <ol id=\"checkins\"></ol>\n      </div>\n    </div>\n\n    <div id=\"signed-out\" class=\"container\">\n      <div class=\"header\">\n        <button id=\"sign-in-button\">Sign in with Foursquare</button>\n      </div>\n    </div>\n\n    <script src=\"loader.js\"></script>\n    <script src=\"foursquare.js\"></script>\n    <script src=\"main.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/appsquare/main.js",
    "content": "function initUi() {\n  foursquare.isSignedIn(function(isSignedIn) {\n    if (isSignedIn) {\n      document.body.classList.add('signed-in');\n      document.body.classList.remove('signed-out');\n      fetchCheckins();\n    } else {\n      document.body.classList.add('signed-out');\n      document.body.classList.remove('signed-in');\n    }\n  });\n};\n\ndocument.getElementById('sign-in-button').onclick = function() {\n  foursquare.signIn(\n      location.hostname, // the app's ID\n      'JP3SRNV00FA1P11W0PHONEUDRQJVSCNODBTCGBKSOPSXIVMX', // Foursquare API client ID\n      initUi,\n      function(error) {\n        console.log('Sign-in error: ' + error);\n      });\n};\n\ndocument.getElementById('sign-out-button').onclick = function() {\n  foursquare.signOut(initUi);\n};\n\nfunction fetchCheckins() {\n  function fetchCheckinsWithLocation(opt_location) {\n    var params = {\n      'limit': 40\n    };\n\n    if (opt_location) {\n      params['ll'] = opt_location;\n    }\n\n    foursquare.getRecentCheckins(\n        params,\n        function(responseJson) {\n          renderCheckins(responseJson.recent);\n        },\n        function(status, statusText, responseJson) {\n          console.log('Error status: ' + status + ' (' + statusText + ')\\n' +\n              JSON.stringify(responseJson));\n        });\n  }\n\n  navigator.geolocation.getCurrentPosition(\n      function(position) {\n        fetchCheckinsWithLocation(\n            position.coords.latitude + ',' + position.coords.longitude);\n      },\n      function(error) {\n        console.log('Geolocation error: ' + error.message);\n        fetchCheckinsWithLocation();\n      });\n};\n\nfunction renderCheckins(checkins) {\n  var checkinsNode = document.getElementById('checkins');\n  checkinsNode.innerHTML = '';\n  checkins.forEach(function(checkin) {\n    var user = checkin.user;\n    var venue = checkin.venue;\n\n    var checkinNode = document.createElement('li');\n    checkinNode.className = 'checkin';\n    if (checkin.isMayor) {\n      var mayorOverlayNode = document.createElement('img');\n      mayorOverlayNode.className = 'mayor-overlay';\n      mayorOverlayNode.src = 'crown-overlay.png';\n      checkinNode.appendChild(mayorOverlayNode);\n    }\n\n    var displayName = user.firstName;\n    if (displayName && user.lastName) {\n      displayName += ' ' + user.lastName.substring(0, 1) + '.';\n    } else if (user.lastName) {\n      displayName = user.lastName;\n    } else {\n      displayName = '<Anonymous>';\n    }\n    var displayVenueName = venue.name || '<Unknown>';\n\n    var photoNode = document.createElement('img');\n    photoNode.className = 'photo';\n    var photoLoader = new ImageLoader(checkin.user.photo);\n    photoLoader.loadInto(photoNode);\n    checkinNode.appendChild(photoNode);\n\n    var headerNode = document.createElement('h3');\n    headerNode.innerText = displayName + ' @ ' + displayVenueName;\n    checkinNode.appendChild(headerNode);\n\n    var locationNode = document.createElement('div');\n    locationNode.className = 'location';\n    var displayVenueLocation;\n    var venueLocation = venue.location;\n    if (venueLocation.country == 'United States') {\n      displayVenueLocation = venueLocation.city + ', ' + venueLocation.state;\n    } else {\n      displayVenueLocation = venueLocation.city + ', ' + venueLocation.country;\n    }\n    if (venueLocation.distance && venueLocation.distance < 100000) {\n      displayVenueLocation += ' (';\n      if (venueLocation.distance < 1000) {\n        displayVenueLocation += venueLocation.distance + ' m';\n      } else {\n        displayVenueLocation += Math.round(venueLocation.distance/1000) + ' km';\n      }\n      displayVenueLocation += ' away)';\n    }\n    locationNode.innerText = displayVenueLocation;\n    checkinNode.appendChild(locationNode);\n\n    var timestampNode = document.createElement('div');\n    timestampNode.className = 'timestamp';\n    var displayTimestamp = new Date(checkin.createdAt * 1000).toLocaleDateString();\n    var timeDelta = Date.now()/1000 - checkin.createdAt;\n    if (timeDelta < 60) {\n      displayTimestamp = 'just now';\n    } else if (timeDelta < 3600) {\n      displayTimestamp = Math.round(timeDelta/60) + ' mins ago';\n    } else if (timeDelta < 24 * 3600) {\n      displayTimestamp = Math.round(timeDelta/3600) + ' hours ago';\n    } else if (timeDelta < 7 * 24 * 3600) {\n      displayTimestamp = Math.round(timeDelta/(24 * 3600)) + ' days ago';\n    }\n    timestampNode.innerText = displayTimestamp;\n    checkinNode.appendChild(timestampNode);\n\n    checkinsNode.appendChild(checkinNode);\n  });\n}\n\nonload = initUi;\n"
  },
  {
    "path": "_archive/apps/samples/appsquare/manifest.json",
    "content": "{\n  \"name\": \"Sample of Foursquare integration\",\n  \"version\": \"7.1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"33\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"icons\": {\n    \"16\": \"icon16.png\",\n    \"48\": \"icon48.png\",\n    \"128\": \"icon128.png\"\n  },\n  \"permissions\": [\n    \"identity\",\n    \"geolocation\",\n    \"storage\",\n\n    \"https://api.foursquare.com/\",\n    \"https://*.4sqi.net/\",\n    \"https://foursquare.com/\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/appview/README.md",
    "content": "# Appview\n\nThese samples show how to use the `<appview>` tag to embed other Chrome Apps\nwithin your Chrome App.\n\nAdd `host-app` and `embedded-app` and embed the `embedded-app` inside\n`host-app`.\n\n## Resources\n\n* [Appview](https://developer.chrome.com/apps/tags/appview)\n* [Runtime](http://developer.chrome.com/apps/app_runtime)\n* [Window](http://developer.chrome.com/apps/app_window)\n* [videoCapture](https://developer.chrome.com/apps/declare_permissions)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/appview/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/appview/embedded-app/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/mighjnlldblaiimoaidiggecdkobklfe\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n"
  },
  {
    "path": "_archive/apps/samples/appview/embedded-app/camera.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <style>\n    body {\n      margin: 0 auto;\n    }\n    video {\n      height: 100%;\n      width: 100%;\n    }\n  </style>\n</head>\n<body>\n  <script src=\"camera.js\"></script>\n  <video autoplay></video>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/appview/embedded-app/camera.js",
    "content": "navigator.webkitGetUserMedia({ video: true }, function(stream) {\n  document.querySelector('video').src = URL.createObjectURL(stream);\n}, function(error) { console.log(error) });\n"
  },
  {
    "path": "_archive/apps/samples/appview/embedded-app/default.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <style>\n    body {\n      background-color: #4CAF50;\n      color: white;\n      margin: 16px;\n    }\n  </style>\n</head>\n<body>\n  <h1>Yeah! I'm succesfully embedded!</h1>\n  <h2>How about sending some data now? Let's try!</h2>\n  <h2><pre>{\"message\": \"camera\"}</pre></h2>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/appview/embedded-app/main.js",
    "content": "chrome.app.runtime.onEmbedRequested.addListener(function(request) {\n  if (!request.data.message) {\n    request.allow('default.html');\n  } else if (request.data.message == 'camera') {\n    request.allow('camera.html');\n  } else {\n    request.deny();\n  }\n});\n"
  },
  {
    "path": "_archive/apps/samples/appview/embedded-app/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Sample Appview Embedded\",\n  \"description\": \"This sample shows how to allow your app to be embedded into another app\",\n  \"version\": \"2\",\n  \"minimum_chrome_version\": \"43\",\n  \"permissions\": [\"videoCapture\"],\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/appview/host-app/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/gkmjlnhjcdognmniiadfdhdlgdocngda\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n"
  },
  {
    "path": "_archive/apps/samples/appview/host-app/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <style>\n    html, body {\n      height: 100%;\n    }\n    body {\n      margin: 0 auto;\n    }\n    #log {\n      background-color: #F1F1F1;\n      font-family: monospace;\n      height: 32px;\n      margin-top: 4px;\n      overflow-y: scroll;\n      padding: 10px 0 2px 6px;\n    }\n    form {\n      height: 60px;\n      padding: 8px;\n    }\n    appview {\n      height: calc(100% - 92px);\n      margin: 8px;\n      outline: 1px dashed #999;\n      position: absolute;\n      width: calc(100% - 16px);\n    }\n    .success {\n      outline: none;\n    }\n  </style>\n</head>\n<body>\n    <form>\n      <input id=\"embedAppId\" size=\"32\" type=\"text\" placeholder=\"App ID\"></input>\n      <input id=\"embedAppData\" type=\"text\" placeholder=\"JSON Data\"></input>\n      <button id=\"sendButton\">Embed</button>\n      <div id=\"log\"></div>\n    </form>\n    <div id=\"container\">\n      <appview></appview>\n    </div>\n    <script src=\"index.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/appview/host-app/index.js",
    "content": "var container = document.querySelector('#container');\nvar logField = document.querySelector('#log');\nvar form = document.querySelector('form');\nvar embedAppId = document.querySelector('#embedAppId');\nvar embedAppData = document.querySelector('#embedAppData');\n\nform.addEventListener('submit', function(event) {\n  event.preventDefault();\n\n  var appview = document.createElement('appview');\n  container.textContent = '';\n  container.appendChild(appview);\n\n  try {\n    var data = JSON.parse(embedAppData.value || '{}');\n  } catch(e) {\n    appendLog('&#9888; Syntax error has occured when parsing JSON App Data.');\n    return;\n  }\n\n  appendLog('Attempting to embed app ' + embedAppId.value + '...');\n  appview.connect(embedAppId.value, data, function(result) {\n    if (result) {\n      appendLog('Embedding request has succedded.');\n    } else {\n      appendLog('Embedding request has failed.');\n    }\n    appview.classList.toggle('success', result);\n  });\n  \n});\n\nfunction appendLog(message) {\n  logField.innerHTML += new Date().toLocaleTimeString() + ': ' + message + '<br/>';\n  logField.scrollTop = logField.scrollHeight;\n}\n"
  },
  {
    "path": "_archive/apps/samples/appview/host-app/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n    id: \"host\",\n    innerBounds: {\n      width: 800,\n      height: 600,\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/appview/host-app/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Sample Appview Host\",\n  \"description\": \"This sample shows how to request another app to be embedded.\",\n  \"version\": \"2\",\n  \"minimum_chrome_version\": \"43\",\n  \"permissions\": [\"appview\"],\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/blink1/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/kcpjgiicabigbjejdjnkflkdkjknkdch\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Blink(1)\n\nThis sample demos the `chrome.hid` API by controlling a [ThingM blink(1) mk2](http://blink1mk2.thingm.com/) RGB LED light via USB HID Feature Reports.\n\n## APIs\n\n* [HID](https://developer.chrome.com/apps/hid)\n* [Runtime](https://developer.chrome.com/apps/app_runtime)\n* [Window](https://developer.chrome.com/apps/app_window)\n\n## Running this app on Linux\n\nOn Linux a udev rule must be added to allow Chrome to open the blink(1) device. Copy the file [`udev/61-blink1.rules`](https://raw.githubusercontent.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/samples/blink1/udev/61-blink1.rules) to `/etc/udev/rules.d`. It contains the following rule which allows anyone in the `plugdev` group read/write access the `hidraw` node for this device. See [USB Caveats](https://developer.chrome.com/apps/app_usb#caveats) for more details.\n\n    # Make the blink(1) accessible to plugdev via hidraw.\n    SUBSYSTEM==\"hidraw\", SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"27b8\", ATTRS{idProduct}==\"01ed\", MODE=\"0660\", GROUP=\"plugdev\"\n\n## Screenshot\n![screenshot](/_archive/apps/samples/blink1/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/blink1/blink1.js",
    "content": "function Blink1(deviceId) {\n  this.deviceId = deviceId;\n  this.connection = null;\n};\n\nBlink1.VENDOR_ID = 0x27B8;\nBlink1.PRODUCT_ID = 0x01ED;\n\nBlink1.prototype.connect = function(cb) {\n  chrome.hid.connect(this.deviceId, function(connectionInfo) {\n    if (chrome.runtime.lastError) {\n      console.warn(\"Unable to connect device: \" +\n                   chrome.runtime.lastError.message);\n      cb(false);\n      return;\n    }\n\n    this.connection = connectionInfo.connectionId;\n    cb(true);\n  }.bind(this));\n};\n\nBlink1.prototype.disconnect = function(cb) {\n  chrome.hid.disconnect(this.connection, function() {\n    if (chrome.runtime.lastError) {\n      console.warn(\"Unable to disconnect device: \" +\n                   chrome.runtime.lastError.message);\n      cb(false);\n      return;\n    }\n\n    cb(true);\n  }.bind(this));\n};\n\n// The following functions send commands to the blink(1). The command protocol\n// operates over feature reports and is documented here:\n//\n// https://github.com/todbot/blink1/blob/master/docs/blink1-hid-commands.md\n//\n// blink(1) HID feature reports are 8 bytes, though only the first 7 bytes\n// appear to ever be read by the firmware. 8 bytes must be sent because some\n// platforms require it (Windows). The documentation refers to sending the\n// report ID as the first byte of the buffer, this is a detail of the HID\n// transport layer and the firmware's HID library and is not reflected in the\n// buffers sent here. This confusion is probably why the firmware only uses the\n// first 7 bytes of the report.\n//\n// Be careful not to send multiple commands simultaneously as each command\n// overwrites the buffer returned by a GET_REPORT(Feature) request and so the\n// command result may be lost or misattributed.\n//\n// TODO(reillyeon): Add transparent request queueing to prevent this.\n\nBlink1.prototype.fadeRgb = function(r, g, b, fade_ms, led) {\n  var fade_time = fade_ms / 10;\n  var th = (fade_time & 0xff00) >> 8;\n  var tl = fade_time & 0x00ff;\n  var data = new Uint8Array(8);\n  data[0] = 'c'.charCodeAt(0);\n  data[1] = r;\n  data[2] = g;\n  data[3] = b;\n  data[4] = th;\n  data[5] = tl;\n  data[6] = led;\n  chrome.hid.sendFeatureReport(this.connection, 1, data.buffer, function() {\n    if (chrome.runtime.lastError) {\n      console.warn(\"Unable to send fade command: \" +\n                   chrome.runtime.lastError.message);\n    }\n  });\n};\n\nBlink1.prototype.getRgb = function(led, cb) {\n  var data = new Uint8Array(8);\n  data[0] = 'r'.charCodeAt(0);\n  data[6] = led;\n  chrome.hid.sendFeatureReport(this.connection, 1, data.buffer, function() {\n    if (chrome.runtime.lastError) {\n      console.warn(\"Unable to send get command: \" +\n                   chrome.runtime.lastError.message);\n      cb(undefined, undefined, undefined);\n      return;\n    }\n\n    chrome.hid.receiveFeatureReport(this.connection, 1, function(buffer) {\n      if (chrome.runtime.lastError) {\n        console.warn(\"Unable to read get response: \" +\n                     chrome.runtime.lastError.message);\n        cb(undefined, undefined, undefined);\n        return;\n      }\n\n      var data = new Uint8Array(buffer);\n      cb(data[2], data[3], data[4]);\n    });\n  }.bind(this));\n};\n\nBlink1.prototype.getVersion = function(cb) {\n  var data = new Uint8Array(8);\n  data[0] = 'v'.charCodeAt(0);\n  chrome.hid.sendFeatureReport(this.connection, 1, data.buffer, function() {\n    if (chrome.runtime.lastError) {\n      console.warn(\"Unable to send version command: \" +\n                   chrome.runtime.lastError.message);\n      cb(undefined);\n      return;\n    }\n\n    chrome.hid.receiveFeatureReport(this.connection, 1, function(buffer) {\n      if (chrome.runtime.lastError) {\n        console.warn(\"Unable to read version response: \" +\n                     chrome.runtime.lastError.message);\n        cb(undefined);\n        return;\n      }\n\n      var data = new Uint8Array(buffer);\n      cb(String.fromCharCode(data[3]) + \".\" + String.fromCharCode(data[4]));\n    });\n  }.bind(this));\n};\n"
  },
  {
    "path": "_archive/apps/samples/blink1/color-picker.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <link rel=\"stylesheet\" href=\"style.css\">\n    <script src=\"blink1.js\"></script>\n    <script src=\"color-picker.js\"></script>\n  </head>\n  <body>\n    <select id=\"picker\" disabled>\n      <option id=\"empty\" selected>No devices found.</option>\n    </select>\n    <input type=\"range\" min=\"0\" max=\"255\" value=\"0\" id=\"r\" disabled />\n    <input type=\"range\" min=\"0\" max=\"255\" value=\"0\" id=\"g\" disabled />\n    <input type=\"range\" min=\"0\" max=\"255\" value=\"0\" id=\"b\" disabled />\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/blink1/color-picker.js",
    "content": "(function() {\n  var ui = {\n    picker: null,\n    r: null,\n    g: null,\n    b: null\n  };\n\n  var bg = undefined;\n\n  function initializeWindow() {\n    for (var k in ui) {\n      var id = k.replace(/([A-Z])/, '-$1').toLowerCase();\n      var element = document.getElementById(id);\n      if (!element) {\n        throw \"Missing UI element: \" + k;\n      }\n      ui[k] = element;\n    }\n    setGradients();\n    ui.picker.addEventListener('change', onSelectionChanged);\n    ui.r.addEventListener('input', onColorChanged);\n    ui.g.addEventListener('input', onColorChanged);\n    ui.b.addEventListener('input', onColorChanged);\n\n    chrome.hid.getDevices({}, onDevicesEnumerated);\n    if (chrome.hid.onDeviceAdded) {\n      chrome.hid.onDeviceAdded.addListener(onDeviceAdded);\n    }\n    if (chrome.hid.onDeviceRemoved) {\n      chrome.hid.onDeviceRemoved.addListener(onDeviceRemoved);\n    }\n  };\n\n  function enableControls(enabled) {\n    ui.r.disabled = !enabled;\n    ui.g.disabled = !enabled;\n    ui.b.disabled = !enabled;\n  };\n\n  function onDevicesEnumerated(devices) {\n    if (chrome.runtime.lastError) {\n      console.error(\"Unable to enumerate devices: \" +\n                    chrome.runtime.lastError.message);\n      return;\n    }\n\n    for (var device of devices) {\n      onDeviceAdded(device);\n    }\n  }\n\n  function onDeviceAdded(device) {\n    if (device.vendorId != Blink1.VENDOR_ID ||\n        device.productId != Blink1.PRODUCT_ID) {\n      return;\n    }\n\n    var blink1 = new Blink1(device.deviceId);\n    blink1.connect(function (success) {\n      if (success) {\n        blink1.getVersion(function (version) {\n          if (version) {\n            blink1.version = version;\n            addNewDevice(blink1);\n          }\n        });\n      }\n    });\n  }\n\n  function onDeviceRemoved(deviceId) {\n    var option = ui.picker.options.namedItem('device-' + deviceId);\n    if (!option) {\n      return;\n    }\n\n    if (option.selected) {\n      bg.blink1.disconnect(function() {});\n      bg.blink1 = undefined;\n      enableControls(false);\n      if (option.previousSibling) {\n        option.previousSibling.selected = true;\n      }\n      if (option.nextSibling) {\n        option.nextSibling.selected = true;\n      }\n    }\n    ui.picker.remove(option.index);\n    if (ui.picker.options.length == 0) {\n      var empty = document.createElement('option');\n      empty.text = 'No devices found.';\n      empty.id = 'empty';\n      empty.selected = true;\n      ui.picker.add(empty);\n      ui.picker.disabled = true;\n    } else {\n      switchToDevice(ui.picker.selectedIndex);\n    }\n  }\n\n  function addNewDevice(blink1) {\n    var firstDevice = ui.picker.options[0].id == 'empty';\n    var option = document.createElement('option');\n    option.text = blink1.deviceId + ' (version ' + blink1.version + ')';\n    option.id = 'device-' + blink1.deviceId;\n    ui.picker.add(option);\n    ui.picker.disabled = false;\n    if (firstDevice) {\n      ui.picker.remove(0);\n      option.selected = true;\n      setActiveDevice(blink1);\n    } else {\n      blink1.disconnect(function () {});\n    }\n  }\n\n  function setActiveDevice(blink1) {\n    bg.blink1 = blink1;\n    bg.blink1.getRgb(0, function(r, g, b) {\n      ui.r.value = r || 0;\n      ui.g.value = g || 0;\n      ui.b.value = b || 0;\n      setGradients();\n    });\n    enableControls(true);\n  }\n\n  function switchToDevice(optionIndex) {\n    var deviceId =\n        parseInt(ui.picker.options[optionIndex].id.substring(7));\n    var blink1 = new Blink1(deviceId);\n    blink1.connect(function (success) {\n      if (success) {\n        setActiveDevice(blink1);\n      }\n    });\n  }\n\n  function onSelectionChanged() {\n    bg.blink1.disconnect(function() {});\n    bg.blink1 = undefined;\n    enableControls(false);\n    switchToDevice(ui.picker.selectedIndex);\n  }\n\n  function onColorChanged() {\n    setGradients();\n    bg.blink1.fadeRgb(ui.r.value, ui.g.value, ui.b.value, 250, 0);\n  }\n\n  function setGradients() {\n    var r = ui.r.value, g = ui.g.value, b = ui.b.value;\n    ui.r.style.background =\n       'linear-gradient(to right, rgb(0, ' + g + ', ' + b + '), ' +\n                                 'rgb(255, ' + g + ', ' + b + '))';\n    ui.g.style.background =\n       'linear-gradient(to right, rgb(' + r + ', 0, ' + b + '), ' +\n                                 'rgb(' + r + ', 255, ' + b + '))';\n    ui.b.style.background =\n       'linear-gradient(to right, rgb(' + r + ', ' + g + ', 0), ' +\n                                 'rgb(' + r + ', ' + g + ', 255))';\n  }\n\n  window.addEventListener('load', function() {\n    // Once the background page has been loaded, it will not unload until this\n    // window is closed.\n    chrome.runtime.getBackgroundPage(function(backgroundPage) {\n      bg = backgroundPage;\n      initializeWindow();\n    });\n  });\n}());\n"
  },
  {
    "path": "_archive/apps/samples/blink1/main.js",
    "content": "var blink1 = undefined;\n\nfunction onAppWindowClosed() {\n  if (blink1) {\n    blink1.disconnect();\n  }\n  window.close();\n}\n\nfunction onAppWindowCreated(appWindow) {\n  appWindow.onClosed.addListener(onAppWindowClosed);\n}\n\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create(\n      \"color-picker.html\", {\n        id: \"blink1\",\n        innerBounds: { width: 160, height: 115 },\n        resizable: false\n      }, onAppWindowCreated);\n});\n"
  },
  {
    "path": "_archive/apps/samples/blink1/manifest.json",
    "content": "{\n  \"name\": \"blink(1)\",\n  \"manifest_version\": 2,\n  \"version\": \"0.3\",\n  \"minimum_chrome_version\": \"39.0.2140.0\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [ \"main.js\" ]\n    }\n  },\n  \"icons\": {\n    \"128\": \"128.png\"\n  },\n  \"permissions\": [\n    \"hid\",\n    {\n      \"usbDevices\": [\n        { \"vendorId\": 10168, \"productId\": 493 }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/blink1/style.css",
    "content": "select {\n  margin: 2px;\n  width: 140px;\n}\n\ninput[type=range] {\n  outline: none;\n  -webkit-appearance: none;\n  width: 140px;\n}\n\ninput[type=range]::-webkit-slider-runnable-track {\n  transition: opacity .4s ease-in;\n}\n\ninput[type=range]:disabled::-webkit-slider-runnable-track {\n  opacity: 0;\n}\n"
  },
  {
    "path": "_archive/apps/samples/blink1/udev/61-blink1.rules",
    "content": "# Make the blink(1) accessible to plugdev via hidraw.\nSUBSYSTEM==\"hidraw\", SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"27b8\", ATTRS{idProduct}==\"01ed\", MODE=\"0660\", GROUP=\"plugdev\"\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/battery-service-demo/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/kllncpgahapecnfkhefffabcemaknamh\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\nBluetooth Low-Energy Battery Service Demo\n=========================================\n\nThis sample demonstrates how an app can read the battery level of a Bluetooth\nLow Energy peripheral using the chrome.bluetoothLowEnergy API to communicate\nwith the Generic Attribute Profile (GATT) based Battery Service.\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/bluetooth-samples/battery-service-demo/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/battery-service-demo/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('main.html', {\n    'innerBounds': {\n      'width': 620,\n      'height': 274,\n      'minWidth': 620,\n      'minHeight': 274,\n      'left': 100,\n      'top': 100\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/battery-service-demo/main.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>Bluetooth LE Battery Service Demo</title>\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n  <script src=\"ui.js\"></script>\n  <script src=\"main.js\"></script>\n</head>\n<body>\n  <div id=\"header\">\n    <img src=\"bluetooth.png\" alt=\"bluetooth icon\">\n    <h1>Bluetooth LE Battery Service</h1>\n    <div id=\"adapter-status\">\n      <ul>\n        <li><span id=\"adapter-name\"></span></li>\n        <li><span id=\"adapter-address\"></span></li>\n      </ul>\n    </div>\n    <hr>\n    <div id=\"device-selection-div\">\n      Select device with Battery Service:\n      <select id=\"device-selector\">\n        <option id=\"placeholder\" value=\"\" disabled selected>\n          No connected devices\n        </option>\n      </select>\n      <button type=\"button\" id=\"discovery-toggle-button\">\n        start discovery\n      </button>\n    </div>\n  </div>\n  <div id=\"no-devices-error\">\n    No device with \"Battery Service\" selected.\n  </div>\n  <div id=\"info-div\">\n    <div class=\"battery\">\n      <div id=\"battery-level-box\" class=\"level\"></div>\n      <div id=\"battery-level\">-</div>\n    </div>\n    <div class=\"battery-tip\"></div>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/battery-service-demo/main.js",
    "content": "var main = (function() {\n  // GATT Battery Service UUIDs\n  var BATTERY_SERVICE_UUID  = '0000180f-0000-1000-8000-00805f9b34fb';\n  var BATTERY_LEVEL_UUID    = '00002a19-0000-1000-8000-00805f9b34fb';\n\n  function BatteryLevelDemo() {\n    // A mapping from device addresses to device names for found devices that\n    // expose a Battery service.\n    this.deviceMap_ = {};\n\n    // The currently selected service and its characteristic.\n    this.service_ = null;\n    this.batteryLevelChrc_ = null;\n    this.discovering_ = false;\n  }\n\n  /**\n   * Sets up the UI for the given service by retrieving its characteristic and\n   * setting up notifications.\n   */\n  BatteryLevelDemo.prototype.selectService = function(service) {\n    // Hide or show the appropriate elements based on whether or not\n    // |serviceId| is undefined.\n    UI.getInstance().resetState(!service);\n\n    if (this.service_ && (!service || this.service_.deviceAddress !== service.deviceAddress)) {\n      chrome.bluetoothLowEnergy.disconnect(this.service_.deviceAddress);\n    }\n\n    this.service_ = service;\n\n    // Disable notifications from the currently selected Battery Level\n    // characteristic.\n    if (this.batteryLevelChrc_) {\n      chrome.bluetoothLowEnergy.stopCharacteristicNotifications(\n          this.batteryLevelChrc_.instanceId);\n    }\n\n    this.batteryLevelChrc_ = null;\n    this.updateBatteryLevelValue();  // Initialize to unknown\n\n    if (!service) {\n      console.log('No service selected.');\n      return;\n    }\n\n    console.log('GATT service selected: ' + service.instanceId);\n\n    // Get the characteristics of the selected service.\n    var self = this;\n    chrome.bluetoothLowEnergy.getCharacteristics(service.instanceId,\n                                                 function(chrcs) {\n      if (chrome.runtime.lastError) {\n        console.log(chrome.runtime.lastError.message);\n        return;\n      }\n\n      // Make sure that the same service is still selected.\n      if (self.service_ && service.instanceId != self.service_.instanceId) {\n        return;\n      }\n\n      if (chrcs.length == 0) {\n        console.log('Service has no characteristics: ' + service.instanceId);\n        return;\n      }\n\n      chrcs.forEach(function(chrc) {\n        // This service should have only one characteristic.\n        if (chrc.uuid != BATTERY_LEVEL_UUID) {\n          console.log('Found unexpected characteristic: ' + chrc.instanceId +\n                      ' with UUID: ' + chrc.uuid);\n          return;\n        }\n\n        console.log('Setting Battery Level characteristic: ' + chrc.instanceId);\n        self.batteryLevelChrc_ = chrc;\n\n        // Enable notifications from the characteristic.\n        chrome.bluetoothLowEnergy.startCharacteristicNotifications(\n            chrc.instanceId,\n            function() {\n          if (chrome.runtime.lastError &&\n              chrome.runtime.lastError.message != 'Already notifying') {\n            console.log('Failed to enable Battery Level notifications: ' +\n                        chrome.runtime.lastError.message);\n            return;\n          }\n\n          console.log('Battery Level notifications enabled! Sending request to ' +\n                      'read current battery level.');\n\n          // Read the value of the characteristic once and store it. The Battery\n          // Level characteristic must support both reads and notifications, so\n          // we will track the value via both.\n          chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId,\n                                                            function(readChrc) {\n            if (chrome.runtime.lastError) {\n              console.log(chrome.runtime.lastError.message);\n              return;\n            }\n\n            // Make sure that the same characteristic is still selected.\n            if (readChrc.instanceId != self.batteryLevelChrc_.instanceId) {\n              return;\n            }\n\n            // No need the update the value here, as a successful read will trigger\n            // the onCharacteristicValueChanged event. We will perform the update in\n            // the listener instead.\n            console.log('Request to read battery level complete.');\n          });\n        });\n      });\n    });\n  };\n\n  BatteryLevelDemo.prototype.updateBatteryLevelValue = function() {\n    if (!this.batteryLevelChrc_) {\n      console.log('No Battery Level Characteristic selected');\n      UI.getInstance().setBatteryLevel(null);\n      return;\n    }\n\n    // Value field might be undefined if the read request failed or no\n    // notification has been received yet.\n    if (!this.batteryLevelChrc_.value) {\n      console.log('No Battery Level value received yet');\n      return;\n    }\n\n    var valueBytes = new Uint8Array(this.batteryLevelChrc_.value);\n\n    // The value should contain a single byte.\n    if (valueBytes.length != 1) {\n      console.log('Invalid Battery Level value length: ' + valueBytes.length);\n      return;\n    }\n\n    var batteryLevel = valueBytes[0];\n    UI.getInstance().setBatteryLevel(batteryLevel);\n  };\n\n  BatteryLevelDemo.prototype.updateDiscoveryToggleState = function(discovering) {\n    if (this.discovering_ !== discovering) {\n      this.discovering_ = discovering;\n      UI.getInstance().setDiscoveryToggleState(this.discovering_);\n    }\n  };\n\n  BatteryLevelDemo.prototype.init = function() {\n    // Set up the UI to look like no device was initially selected.\n    this.selectService(null);\n\n    // Store the |this| to be used by API callbacks below.\n    var self = this;\n\n    // Request information about the local Bluetooth adapter to be displayed in\n    // the UI.\n    var updateAdapterState = function(adapterState) {\n      UI.getInstance().setAdapterState(adapterState.address, adapterState.name);\n      self.updateDiscoveryToggleState(adapterState.discovering);\n    };\n\n    chrome.bluetooth.getAdapterState(function(adapterState) {\n      if (chrome.runtime.lastError) {\n        console.log(chrome.runtime.lastError.message);\n      }\n      self.updateDiscoveryToggleState(adapterState.discovering);\n      updateAdapterState(adapterState);\n    });\n\n    chrome.bluetooth.onAdapterStateChanged.addListener(updateAdapterState);\n\n    // Helper functions used below.\n    var isKnownDevice = function(deviceAddress) {\n      return self.deviceMap_.hasOwnProperty(deviceAddress);\n    };\n\n    var storeDevice = function(deviceAddress, device) {\n      var resetUI = false;\n      if (device == null) {\n        delete self.deviceMap_[deviceAddress];\n        resetUI = true;\n      } else {\n        self.deviceMap_[deviceAddress] =\n            (device.name ? device.name : deviceAddress);\n      }\n\n      // Update the selector UI with the new device list.\n      UI.getInstance().updateDeviceSelector(self.deviceMap_, resetUI);\n    };\n\n    // Initialize the device map.\n    chrome.bluetooth.getDevices(function(devices) {\n      if (chrome.runtime.lastError) {\n        console.log(chrome.runtime.lastError.message);\n      }\n\n      if (devices) {\n        devices.forEach(function(device) {\n          // See if the device exposes a Battery service.\n          chrome.bluetoothLowEnergy.getServices(device.address,\n                                                function(services) {\n            if (chrome.runtime.lastError) {\n              console.log(chrome.runtime.lastError.message);\n              return;\n            }\n\n            if (!services) {\n              return;\n            }\n\n            var found = false;\n            for (var i = 0; i < services.length; i++) {\n              if (services[i].uuid == BATTERY_SERVICE_UUID) {\n                console.log('Found Battery service!');\n                found = true;\n                break;\n              }\n            }\n\n            if (!found) {\n              return;\n            }\n\n            console.log('Found device with Battery service: ' +\n                        device.address);\n            storeDevice(device.address, device);\n          });\n        });\n      }\n    });\n\n    // Set up discovery toggle button handler\n    UI.getInstance().setDiscoveryToggleHandler(function() {\n      var discoveryHandler = function() {\n        if (chrome.runtime.lastError) {\n          console.log('Failed to ' + (self.discovering_ ? 'stop' : 'start') + ' discovery ' +\n                      chrome.runtime.lastError.message);\n        }\n      };\n      if (self.discovering_) {\n        chrome.bluetooth.stopDiscovery(discoveryHandler);\n      } else {\n        chrome.bluetooth.startDiscovery(discoveryHandler);\n      }\n    });\n\n    // Set up the device selector.\n    UI.getInstance().setDeviceSelectionHandler(function(selectedValue) {\n      // If |selectedValue| is empty, unselect everything.\n      if (!selectedValue) {\n        self.selectService(null);\n        return;\n      }\n\n      chrome.bluetoothLowEnergy.connect(selectedValue, function () {\n        if (chrome.runtime.lastError) {\n          console.log('Failed to connect to Battery device \"' + selectedValue +\n                      '\" ' + chrome.runtime.lastError.message);\n          return;\n        }\n        console.log('Connected to Battery device: ' + selectedValue);\n      });\n\n      // Request all GATT services of the selected device to see if it still has\n      // a Battery service and pick the first one to display.\n      chrome.bluetoothLowEnergy.getServices(selectedValue, function(services) {\n        if (chrome.runtime.lastError) {\n          console.log(chrome.runtime.lastError.message);\n          self.selectService(undefined);\n          return;\n        }\n\n        var foundService = null;\n        for (var i = 0; i < services.length; i++) {\n          if (services[i].uuid == BATTERY_SERVICE_UUID) {\n            foundService = services[i];\n            break;\n          }\n        }\n\n        self.selectService(foundService);\n      });\n    });\n\n    // Track devices that get added and removed. If they have the battery service\n    // UUID in their advertisement data, then it will be available in the\n    // |uuids| field of the device.\n    chrome.bluetooth.onDeviceAdded.addListener(function (device) {\n      if (!device.uuids || device.uuids.indexOf(BATTERY_SERVICE_UUID) < 0) {\n        return;\n      }\n\n      if (self.deviceMap_.hasOwnProperty(device.address)) {\n        return;\n      }\n\n      console.log('Found device with Battery service: ' + device.address);\n\n      self.deviceMap_[device.address] =\n          (device.name ? device.name : device.address);\n      UI.getInstance().updateDeviceSelector(self.deviceMap_);\n    });\n\n    // Track devices as they are removed.\n    chrome.bluetooth.onDeviceRemoved.addListener(function (device) {\n      if (!self.deviceMap_.hasOwnProperty(device.address)) {\n        return;\n      }\n\n      console.log('Battery device removed: ' + device.address);\n      delete self.deviceMap_[device.address];\n      if (self.service_ && self.service_.deviceAddress == device.address) {\n        chrome.bluetoothLowEnergy.disconnect(device.address);\n        self.selectService(undefined);\n        UI.getInstance().triggerDeviceSelection();\n      }\n      UI.getInstance().updateDeviceSelector(self.deviceMap_);\n    });\n\n    // Track GATT services as they are added.\n    chrome.bluetoothLowEnergy.onServiceAdded.addListener(function(service) {\n      // Ignore, if the service is not a Battery service.\n      if (service.uuid != BATTERY_SERVICE_UUID) {\n        return;\n      }\n\n      // If this came from the currently selected device and no service is\n      // currently selected, select this service.\n      if (UI.getInstance().getSelectedDeviceAddress() == service.deviceAddress\n          && !self.service_) {\n        self.selectService(service);\n      }\n\n      // Add the device of the service to the device map and update the UI.\n      console.log('New Battery service added: ' + service.instanceId);\n      if (isKnownDevice(service.deviceAddress)) {\n        return;\n      }\n\n      // Looks like it's a brand new device. Get information about the device so\n      // that we can display the device name in the drop-down menu.\n      chrome.bluetooth.getDevice(service.deviceAddress, function(device) {\n        if (chrome.runtime.lastError) {\n          console.log(chrome.runtime.lastError.message);\n          return;\n        }\n\n        storeDevice(device.address, device);\n      });\n    });\n\n    // Track GATT services as they are removed.\n    chrome.bluetoothLowEnergy.onServiceRemoved.addListener(function(service) {\n      // Ignore, if the service is not a Battery service.\n      if (service.uuid != BATTERY_SERVICE_UUID) {\n        return;\n      }\n\n      // See if this is the currently selected service. If so, unselect it.\n      console.log('Battery service removed: ' + service.instanceId);\n      var selectedRemoved = false;\n      if (self.service_ && self.service_.instanceId == service.instanceId) {\n        console.log('The selected service disappeared!');\n        self.selectService(null);\n        selectedRemoved = true;\n      }\n\n      // Remove the associated device from the map only if it has no other Battery\n      // services exposed (this will usually be the case)\n      if (!isKnownDevice(service.deviceAddress)) {\n        return;\n      }\n\n      chrome.bluetooth.getDevice(service.deviceAddress, function(device) {\n        if (chrome.runtime.lastError) {\n          console.log(chrome.runtime.lastError.message);\n          return;\n        }\n\n        chrome.bluetoothLowEnergy.getServices(device.address,\n                                              function(services) {\n          if (chrome.runtime.lastError) {\n            // Error obtaining services. Remove the device from the map.\n            console.log(chrome.runtime.lastError.message);\n            storeDevice(device.address, null);\n            return;\n          }\n\n          var found = false;\n          for (var i = 0; i < services.length; i++) {\n            if (services[i].uuid == BATTERY_SERVICE_UUID) {\n              found = true;\n              break;\n            }\n          }\n\n          if (found) {\n            return;\n          }\n\n          console.log('Removing device: ' + device.address);\n          storeDevice(device.address, null);\n        });\n      });\n    });\n\n    // Track GATT services as they change.\n    chrome.bluetoothLowEnergy.onServiceChanged.addListener(function(service) {\n      // This only matters if the selected service changed.\n      if (!self.service_ || service.instanceId != self.service_.instanceId) {\n        return;\n      }\n\n      console.log('The selected service has changed');\n\n      // Reselect the service to force an updated.\n      self.selectService(service);\n    });\n\n    // Track GATT characteristic value changes. This event will be triggered after\n    // successful characteristic value reads and received notifications and\n    // indications.\n    chrome.bluetoothLowEnergy.onCharacteristicValueChanged.addListener(\n        function(chrc) {\n      if (self.batteryLevelChrc_ &&\n          chrc.instanceId == self.batteryLevelChrc_.instanceId) {\n        console.log('Battery Level value changed');\n        self.batteryLevelChrc_ = chrc;\n        self.updateBatteryLevelValue();\n        return;\n      }\n    });\n  };\n\n  return {\n    BatteryLevelDemo: BatteryLevelDemo\n  };\n\n})();\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  var demo = new main.BatteryLevelDemo();\n  demo.init();\n});\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/battery-service-demo/manifest.json",
    "content": "{\n  \"name\": \"Battery Service Demo\",\n  \"description\": \"Battery Service Demo using chrome.bluetoothLowEnergy\",\n  \"version\": \"0.1\",\n  \"minimum_chrome_version\": \"37\",\n  \"icons\": {\n    \"16\": \"bluetooth.png\",\n    \"48\": \"bluetooth.png\",\n    \"128\": \"bluetooth.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"bluetooth\": {\n    \"low_energy\": true,\n    \"uuids\": [\"180f\"]\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/battery-service-demo/style.css",
    "content": "body {\n  margin: 0;\n  overflow: hidden;\n  height: 274px;\n}\n\n#header {\n  padding: 10px 15px 5px 15px;\n  background: #fafafa;\n  box-shadow: 0 0 5px #858585;\n}\n\n#header img {\n  width: 50px;\n}\n\n#header h1 {\n  font-family: 'DejaVu Sans Light', Verdana, sans-serif;\n  font-weight: normal;\n  vertical-align: top;\n  display: inline-block;\n  margin: 8px;\n}\n\n#adapter-status {\n  float: right;\n  margin-top: 2px;\n}\n\n#adapter-address {\n  font-weight: bold;\n}\n\nul {\n  padding-left: 0;\n  margin: inherit;\n}\n\nul li {\n  list-style-type: none;\n}\n\n#device-selection-div {\n  margin-top: 5px;\n}\n\n#device-selector {\n  background: transparent;\n  border: 1px solid #aaa;\n  color: #454545;\n  font-style: italic;\n}\n\n#discovery-toggle-button {\n  background: transparent;\n  border: 1px solid #aaa;\n  color: #454545;\n  font-style: italic;\n}\n\nhr {\n  border: 0;\n  height: 0;\n  border-top: 1px solid rgba(0,0,0,0.12);\n  border-bottom: 1px solid rgba(255,255,255,0.3);\n}\n\n#no-devices-error {\n  font-size: 10pt;\n  text-align: center;\n  padding-top: 60px;\n}\n\n#info-div {\n  position: relative;\n  margin: auto;\n  width: 185px;\n  height: 80px;\n  top: 15%;\n}\n\n.battery {\n  z-index: -1;\n  position: relative;\n  width: 97%;\n  height: 100%;\n  border: 7px solid black;\n  box-sizing: border-box;\n}\n\n.battery .level {\n  position: absolute;\n  height: 100%;\n}\n\n.battery .level.high {\n  background-color: green;\n}\n\n.battery .level.medium {\n  background-color: orange;\n}\n\n.battery .level.low {\n  background-color: red;\n}\n\n.battery-tip {\n  position: absolute;\n  left: 97%;\n  background-color: black;\n  width: 3%;\n  height: 30%;\n  top: 35%;\n}\n\n#battery-level {\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  text-align: center;\n  color: black;\n  font-size: 3em;\n  padding-top: 3%\n}\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/battery-service-demo/ui.js",
    "content": "var UI = (function() {\n\n  // Common functions used for tweaking UI elements.\n  function UI() {\n  }\n\n  // Global instance.\n  var instance;\n\n  UI.prototype.resetState = function(noDevices) {\n    document.getElementById('no-devices-error').hidden = !noDevices;\n    document.getElementById('info-div').hidden = noDevices;\n    this.clearAllFields();\n  };\n\n  UI.prototype.clearAllFields = function() {\n    this.setBatteryLevel(null);\n  };\n\n  UI.prototype.setBatteryLevel = function(level) {\n    var levelField = document.getElementById('battery-level');\n    var value = (level == null) ? '-' : level + ' %';\n\n    levelField.innerHTML = '';\n    levelField.appendChild(document.createTextNode(value));\n\n    var batteryBox = document.getElementById('battery-level-box');\n\n    if (level == null) {\n      batteryBox.style.width = '0%';\n      return;\n    }\n\n    var levelClass;\n\n    if (level > 65) {\n      levelClass = 'high';\n    } else if (level > 30) {\n      levelClass = 'medium';\n    } else {\n      levelClass = 'low';\n    }\n\n    batteryBox.className = 'level ' + levelClass;\n    batteryBox.style.width = level + '%';\n  };\n\n  UI.prototype.setDiscoveryToggleState = function(isDiscoverying) {\n    var discoveryToggleButton = document.getElementById('discovery-toggle-button');\n    if (isDiscoverying) {\n      discoveryToggleButton.innerHTML = 'stop discovery';\n    } else {\n      discoveryToggleButton.innerHTML = 'start discovery';\n    }\n  };\n\n  UI.prototype.setDiscoveryToggleHandler = function(handler) {\n    var discoveryToggleButton = document.getElementById('discovery-toggle-button');\n    discoveryToggleButton.onclick = handler;\n  };\n\n  UI.prototype.setDeviceSelectionHandler = function(handler) {\n    var deviceSelector =  document.getElementById('device-selector');\n    deviceSelector.onchange = function() {\n      handler(deviceSelector[deviceSelector.selectedIndex].value);\n    };\n  };\n\n  UI.prototype.triggerDeviceSelection = function() {\n    var deviceSelector = document.getElementById('device-selector');\n    if (deviceSelector.onchange)\n      deviceSelector.onchange();\n  };\n\n  UI.prototype.getSelectedDeviceAddress = function() {\n    var deviceSelector = document.getElementById('device-selector');\n    return deviceSelector[deviceSelector.selectedIndex].value;\n  };\n\n  UI.prototype.updateDeviceSelector = function(deviceMap, reset) {\n    var deviceSelector = document.getElementById('device-selector');\n    var placeHolder = document.getElementById('placeholder');\n    var addresses = Object.keys(deviceMap);\n\n    reset = (reset !== undefined) ? reset : false;\n\n    deviceSelector.innerHTML = '';\n    placeHolder.innerHTML = '';\n    deviceSelector.appendChild(placeHolder);\n\n    // Clear the drop-down menu.\n    if (addresses.length == 0) {\n      console.log('No connected devices found');\n      placeHolder.appendChild(document.createTextNode('No connected devices'));\n      return;\n    }\n\n    // Hide the placeholder and populate\n    placeHolder.appendChild(document.createTextNode('Connected devices found'));\n\n    for (var i = 0; i < addresses.length; i++) {\n      var address = addresses[i];\n      var deviceOption = document.createElement('option');\n      deviceOption.setAttribute('value', address);\n      deviceOption.appendChild(document.createTextNode(\n          deviceMap[address]));\n      deviceSelector.appendChild(deviceOption);\n    }\n\n    if (reset)\n      deviceSelector.selectedIndex = 0;\n  };\n\n  UI.prototype.setAdapterState = function(address, name) {\n    var addressField = document.getElementById('adapter-address');\n    var nameField = document.getElementById('adapter-name');\n\n    var setAdapterField = function (field, value) {\n      field.innerHTML = '';\n      field.appendChild(document.createTextNode(value));\n    };\n\n    setAdapterField(addressField, address ? address : 'unknown');\n    setAdapterField(nameField, name ? name : 'Local Adapter');\n  };\n\n  return {\n    getInstance: function() {\n      if (!instance) {\n        instance = new UI();\n      }\n\n      return instance;\n    }\n  };\n\n})();\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/device-info-demo/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/dblimghcclaakknbpajckcamddhjaaai\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\nBluetooth Low-Energy Device Information Service Demo\n====================================================\n\nThis sample demonstrates how an app can communicate with the GATT based Device\nInformation Service on a Bluetooth Low Energy peripheral using the\nchrome.bluetoothLowEnergy API.\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/bluetooth-samples/device-info-demo/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/device-info-demo/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('main.html', {\n    'innerBounds': {\n      'width': 635,\n      'height': 370,\n      'minWidth': 635,\n      'minHeight': 370,\n      'left': 100,\n      'top': 100\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/device-info-demo/main.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>Bluetooth LE Device Information Service Demo</title>\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n  <script src=\"ui.js\"></script>\n  <script src=\"main.js\"></script>\n</head>\n<body>\n  <div id=\"header\">\n    <img src=\"bluetooth.png\" alt=\"bluetooth icon\">\n    <h1>BLE Device Information Service</h1>\n    <div id=\"adapter-status\">\n      <ul>\n        <li><span id=\"adapter-name\"></span></li>\n        <li><span id=\"adapter-address\"></span></li>\n      </ul>\n    </div>\n    <hr>\n    <div id=\"device-selection-div\">\n      Select device with Device Information Service:\n      <select id=\"device-selector\">\n        <option id=\"placeholder\" value=\"\" disabled selected>\n          No connected devices\n        </option>\n      </select>\n      <button type=\"button\" id=\"discovery-toggle-button\">\n        start discovery\n      </button>\n    </div>\n  </div>\n  <div id=\"no-devices-error\">\n    No device with \"Device Information Service\" selected.\n  </div>\n  <div id=\"info-div\">\n    <div class=\"device-info-field\">\n      Manufacturer Name: <span id=\"manufacturer-name-string\">-</span>\n    </div>\n    <div class=\"device-info-field\">\n      Serial Number: <span id=\"serial-number-string\">-</span>\n    </div>\n    <div class=\"device-info-field\">\n      Hardware Revision: <span id=\"hardware-revision-string\">-</span>\n    </div>\n    <div class=\"device-info-field\">\n      Firmware Revision: <span id=\"firmware-revision-string\">-</span>\n    </div>\n    <div class=\"device-info-field\">\n      Software Revision: <span id=\"software-revision-string\">-</span>\n    </div>\n    <div class=\"device-info-field\">\n      Vendor ID Source: <span id=\"vendor-id-source\">-</span>\n    </div>\n    <div class=\"device-info-field\">\n      Vendor ID: <span id=\"vendor-id\">-</span>\n    </div>\n    <div class=\"device-info-field\">\n      Product ID: <span id=\"product-id\">-</span>\n    </div>\n    <div class=\"device-info-field\">\n      Product Version: <span id=\"product-version\">-</span>\n    </div>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/device-info-demo/main.js",
    "content": "var main = (function() {\n  // GATT Device Information Service UUIDs\n  var DEVICE_INFO_SERVICE_UUID      = '0000180a-0000-1000-8000-00805f9b34fb';\n  var MANUFACTURER_NAME_STRING_UUID = '00002a29-0000-1000-8000-00805f9b34fb';\n  var SERIAL_NUMBER_STRING_UUID     = '00002a25-0000-1000-8000-00805f9b34fb';\n  var HARDWARE_REVISION_STRING_UUID = '00002a27-0000-1000-8000-00805f9b34fb';\n  var FIRMWARE_REVISION_STRING_UUID = '00002a26-0000-1000-8000-00805f9b34fb';\n  var SOFTWARE_REVISION_STRING_UUID = '00002a28-0000-1000-8000-00805f9b34fb';\n  var PNP_ID_UUID                   = '00002a50-0000-1000-8000-00805f9b34fb';\n\n  function DeviceInfoDemo() {\n    // A mapping from device addresses to device names for found devices that\n    // expose a Battery service.\n    this.deviceMap_ = {};\n\n    // The currently selected service and its characteristics.\n    this.service_ = null;\n    this.chrcMap_ = {};\n    this.discovering_ = false;\n  }\n\n  /**\n   * Sets up the UI for the given service.\n   */\n  DeviceInfoDemo.prototype.selectService = function(service) {\n    // Hide or show the appropriate elements based on whether or not\n    // |serviceId| is undefined.\n    UI.getInstance().resetState(!service);\n\n    if (this.service_ && (!service || this.service_.deviceAddress !== service.deviceAddress)) {\n      chrome.bluetoothLowEnergy.disconnect(this.service_.deviceAddress);\n    }\n\n    this.service_ = service;\n    this.chrcMap_ = {};\n\n    if (!service) {\n      console.log('No service selected.');\n      return;\n    }\n\n    console.log('GATT service selected: ' + service.instanceId);\n\n    // Get the characteristics of the selected service.\n    var self = this;\n    chrome.bluetoothLowEnergy.getCharacteristics(service.instanceId,\n                                                 function (chrcs) {\n      if (chrome.runtime.lastError) {\n        console.log(chrome.runtime.lastError.message);\n        return;\n      }\n\n      // Make sure that the same service is still selected.\n      if (self.service_ && service.instanceId != self.service_.instanceId) {\n        return;\n      }\n\n      if (chrcs.length == 0) {\n        console.log('Service has no characteristics: ' + service.instanceId);\n        return;\n      }\n\n      chrcs.forEach(function (chrc) {\n        var fieldId;\n        var valueDisplayFunction = UI.getInstance().setStringValue;\n\n        if (chrc.uuid == MANUFACTURER_NAME_STRING_UUID) {\n          console.log('Setting Manufacturer Name String Characteristic: ' +\n                      chrc.instanceId);\n          fieldId = 'manufacturer-name-string';\n        } else if (chrc.uuid == SERIAL_NUMBER_STRING_UUID) {\n          console.log('Setting Serial Number String Characteristic: ' +\n                      chrc.instanceId);\n          fieldId = 'serial-number-string';\n        } else if (chrc.uuid == HARDWARE_REVISION_STRING_UUID) {\n          console.log('Setting Hardware Revision String Characteristic: ' +\n                      chrc.instanceId);\n          fieldId = 'hardware-revision-string';\n        } else if (chrc.uuid == FIRMWARE_REVISION_STRING_UUID) {\n          console.log('Setting Firmware Revision String Characteristic: ' +\n                      chrc.instanceId);\n          fieldId = 'firmware-revision-string';\n        } else if (chrc.uuid == SOFTWARE_REVISION_STRING_UUID) {\n          console.log('Setting Software Revision String Characteristic: ' +\n                      chrc.instanceId);\n          fieldId = 'software-revision-string';\n        } else if (chrc.uuid == PNP_ID_UUID) {\n          console.log('Setting PnP ID Characteristic: ' + chrc.instanceId);\n          fieldId = 'pnp-id';\n          valueDisplayFunction = UI.getInstance().setPnpIdValue;\n        }\n\n        if (fieldId === undefined) {\n          console.log('Ignoring characteristic \"' + chrc.instanceId +\n                      '\" with UUID ' + chrc.uuid);\n          return;\n        }\n\n        self.chrcMap_[fieldId] = chrc;\n\n        // Read the value of the characteristic and store it.\n        chrome.bluetoothLowEnergy.readCharacteristicValue(chrc.instanceId,\n                                                          function (readChrc) {\n          if (chrome.runtime.lastError) {\n            console.log(chrome.runtime.lastError.message);\n            return;\n          }\n\n          // Make sure that the same characteristic is still selected.\n          if (!self.chrcMap_.hasOwnProperty(fieldId) ||\n              self.chrcMap_[fieldId].instanceId != readChrc.instanceId)\n            return;\n\n          self.chrcMap_[fieldId] = readChrc;\n          valueDisplayFunction(fieldId, readChrc.value);\n        });\n      });\n    });\n  };\n\n  DeviceInfoDemo.prototype.updateDiscoveryToggleState = function(discovering) {\n    if (this.discovering_ !== discovering) {\n      this.discovering_ = discovering;\n      UI.getInstance().setDiscoveryToggleState(this.discovering_);\n    }\n  };\n\n  DeviceInfoDemo.prototype.init = function() {\n    // Set up the UI to look like no device was initially selected.\n    this.selectService(null);\n\n    // Store the |this| to be used by API callbacks below.\n    var self = this;\n\n    // Request information about the local Bluetooth adapter to be displayed in\n    // the UI.\n    var updateAdapterState = function(adapterState) {\n      UI.getInstance().setAdapterState(adapterState.address, adapterState.name);\n      self.updateDiscoveryToggleState(adapterState.discovering);\n    };\n\n    chrome.bluetooth.getAdapterState(function (adapterState) {\n      if (chrome.runtime.lastError)\n        console.log(chrome.runtime.lastError.message);\n\n      self.updateDiscoveryToggleState(adapterState.discovering);\n      updateAdapterState(adapterState);\n    });\n\n    chrome.bluetooth.onAdapterStateChanged.addListener(updateAdapterState);\n\n    // Helper functions used below.\n    var isKnownDevice = function(deviceAddress) {\n      return self.deviceMap_.hasOwnProperty(deviceAddress);\n    };\n\n    var storeDevice = function(deviceAddress, device) {\n      var resetUI = false;\n      if (device == null) {\n        delete self.deviceMap_[deviceAddress];\n        resetUI = true;\n      } else {\n        self.deviceMap_[deviceAddress] =\n            (device.name ? device.name : deviceAddress);\n      }\n\n      // Update the selector UI with the new device list.\n      UI.getInstance().updateDeviceSelector(self.deviceMap_, resetUI);\n    };\n\n    // Initialize the device map.\n    chrome.bluetooth.getDevices(function (devices) {\n      if (chrome.runtime.lastError) {\n        console.log(chrome.runtime.lastError.message);\n      }\n\n      if (devices) {\n        devices.forEach(function (device) {\n          // See if the device exposes a Device Information service.\n          chrome.bluetoothLowEnergy.getServices(device.address,\n                                                function (services) {\n            if (chrome.runtime.lastError) {\n              console.log(chrome.runtime.lastError.message);\n              return;\n            }\n\n            if (!services)\n              return;\n\n            var found = false;\n            services.forEach(function (service) {\n              if (service.uuid == DEVICE_INFO_SERVICE_UUID) {\n                console.log('Found Device Information service!');\n                found = true;\n              }\n            });\n\n            if (!found)\n              return;\n\n            console.log('Found device with Device Information service: ' +\n                        device.address);\n            storeDevice(device.address, device);\n          });\n        });\n      }\n    });\n\n    // Set up discovery toggle button handler\n    UI.getInstance().setDiscoveryToggleHandler(function() {\n      var discoveryHandler = function() {\n        if (chrome.runtime.lastError) {\n          console.log('Failed to ' + (self.discovering_ ? 'stop' : 'start') + ' discovery ' +\n                      chrome.runtime.lastError.message);\n        }\n      };\n      if (self.discovering_) {\n        chrome.bluetooth.stopDiscovery(discoveryHandler);\n      } else {\n        chrome.bluetooth.startDiscovery(discoveryHandler);\n      }\n    });\n\n    // Set up the device selector.\n    UI.getInstance().setDeviceSelectionHandler(function(selectedValue) {\n      // If |selectedValue| is empty, unselect everything.\n      if (!selectedValue) {\n        self.selectService(null);\n        return;\n      }\n\n      chrome.bluetoothLowEnergy.connect(selectedValue, function () {\n        if (chrome.runtime.lastError) {\n          console.log('Failed to connect to Battery device \"' + selectedValue +\n                      '\" ' + chrome.runtime.lastError.message);\n          return;\n        }\n        console.log('Connected to Battery device: ' + selectedValue);\n      });\n\n      // Request all GATT services of the selected device to see if it still has\n      // a Device Information service and pick the first one to display.\n      chrome.bluetoothLowEnergy.getServices(selectedValue, function (services) {\n        if (chrome.runtime.lastError) {\n          console.log(chrome.runtime.lastError.message);\n          self.selectService(null);\n          return;\n        }\n\n        var foundService = null;\n        services.forEach(function (service) {\n          if (service.uuid == DEVICE_INFO_SERVICE_UUID)\n            foundService = service;\n        });\n\n        self.selectService(foundService);\n      });\n    });\n\n    // Track devices that get added and removed. If they have the device info\n    // service UUID in their advertisement data, then it will be available in\n    // the |uuids| field of the device.\n    chrome.bluetooth.onDeviceAdded.addListener(function (device) {\n      if (!device.uuids || device.uuids.indexOf(DEVICE_INFO_SERVICE_UUID) < 0) {\n        return;\n      }\n\n      if (self.deviceMap_.hasOwnProperty(device.address)) {\n        return;\n      }\n\n      console.log('Found device with Device Info service: ' + device.address);\n\n      self.deviceMap_[device.address] =\n          (device.name ? device.name : device.address);\n      UI.getInstance().updateDeviceSelector(self.deviceMap_);\n    });\n\n    // Track devices as they are removed.\n    chrome.bluetooth.onDeviceRemoved.addListener(function (device) {\n      if (!self.deviceMap_.hasOwnProperty(device.address)) {\n        return;\n      }\n\n      console.log('Device Info device removed: ' + device.address);\n      delete self.deviceMap_[device.address];\n      if (self.service_ && self.service_.deviceAddress == device.address) {\n        chrome.bluetoothLowEnergy.disconnect(device.address);\n        self.selectService(undefined);\n        UI.getInstance().triggerDeviceSelection();\n      }\n      UI.getInstance().updateDeviceSelector(self.deviceMap_);\n    });\n\n    // Track GATT services as they are added.\n    chrome.bluetoothLowEnergy.onServiceAdded.addListener(function (service) {\n      // Ignore, if the service is not a Device Information service.\n      if (service.uuid != DEVICE_INFO_SERVICE_UUID)\n        return;\n\n      // If this came from the currently selected device and no service is\n      // currently selected, select this service.\n      if (UI.getInstance().getSelectedDeviceAddress() == service.deviceAddress\n          && !self.service_) {\n        self.selectService(service);\n      }\n\n      // Add the device of the service to the device map and update the UI.\n      console.log('New Device Information service added: ' + service.instanceId);\n      if (isKnownDevice(service.deviceAddress))\n        return;\n\n      // Looks like it's a brand new device. Get information about the device so\n      // that we can display the device name in the drop-down menu.\n      chrome.bluetooth.getDevice(service.deviceAddress, function (device) {\n        if (chrome.runtime.lastError) {\n          console.log(chrome.runtime.lastError.message);\n          return;\n        }\n\n        storeDevice(device.address, device);\n      });\n    });\n\n    // Track GATT services as they are removed.\n    chrome.bluetoothLowEnergy.onServiceRemoved.addListener(function (service) {\n      // Ignore, if the service is not a Device Information service.\n      if (service.uuid != DEVICE_INFO_SERVICE_UUID)\n        return;\n\n      // See if this is the currently selected service. If so, unselect it.\n      console.log('Device Information service removed: ' + service.instanceId);\n      var selectedRemoved = false;\n      if (self.service_ && self.service_.instanceId == service.instanceId) {\n        console.log('The selected service disappeared!');\n        self.selectService(null);\n        selectedRemoved = true;\n      }\n\n      // Remove the associated device from the map only if it has no other Device\n      // Information services exposed (this will usually be the case)\n      if (!isKnownDevice(service.deviceAddress)) {\n        return;\n      }\n\n      chrome.bluetooth.getDevice(service.deviceAddress, function (device) {\n        if (chrome.runtime.lastError) {\n          console.log(chrome.runtime.lastError.message);\n          return;\n        }\n\n        chrome.bluetoothLowEnergy.getServices(device.address,\n                                              function (services) {\n          if (chrome.runtime.lastError) {\n            // Error obtaining services. Remove the device from the map.\n            console.log(chrome.runtime.lastError.message);\n            storeDevice(device.address, null);\n            return;\n          }\n\n          var found = false;\n          for (var i = 0; i < services.length; i++) {\n            if (services[i].uuid == DEVICE_INFO_SERVICE_UUID) {\n              found = true;\n              break;\n            }\n          }\n\n          if (found) {\n            return;\n          }\n\n          console.log('Removing device: ' + device.address);\n          storeDevice(device.address, null);\n        });\n      });\n    });\n\n    // Track GATT services as they change.\n    chrome.bluetoothLowEnergy.onServiceChanged.addListener(function (service) {\n      // This only matters if the selected service changed.\n      if (!self.service_ || service.instanceId != self.service_.instanceId) {\n        return;\n      }\n      console.log('The selected service has changed');\n\n      // Reselect the service to force an updated.\n      self.selectService(service);\n    });\n  };\n\n  return {\n    DeviceInfoDemo: DeviceInfoDemo\n  };\n})();\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  var demo = new main.DeviceInfoDemo();\n  demo.init();\n});\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/device-info-demo/manifest.json",
    "content": "{\n  \"name\": \"Device Information Service Demo\",\n  \"description\": \"Device Information Demo using chrome.bluetoothLowEnergy\",\n  \"version\": \"0.3\",\n  \"minimum_chrome_version\": \"37\",\n  \"icons\": {\n    \"16\": \"bluetooth.png\",\n    \"48\": \"bluetooth.png\",\n    \"128\": \"bluetooth.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"bluetooth\": {\n    \"low_energy\": true,\n    \"uuids\": [\"180a\"]\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/device-info-demo/style.css",
    "content": "body {\n  margin: 0;\n  overflow: hidden;\n}\n\n#header {\n  padding: 10px 15px 5px 15px;\n  background: #fafafa;\n  box-shadow: 0 0 5px #858585;\n}\n\n#header img {\n  width: 50px;\n}\n\n#header h1 {\n  font-family: 'DejaVu Sans Light', Verdana, sans-serif;\n  font-weight: normal;\n  vertical-align: top;\n  display: inline-block;\n  margin: 8px;\n  white-space: nowrap;\n  overflow: hidden;\n}\n\n#adapter-status {\n  float: right;\n  margin-top: 2px;\n}\n\n#adapter-address {\n  font-weight: bold;\n}\n\nul {\n  padding-left: 0;\n  margin: inherit;\n}\n\nul li {\n  list-style-type: none;\n}\n\n#device-selection-div {\n  margin-top: 5px;\n}\n\n#device-selector {\n  background: transparent;\n  border: 1px solid #aaa;\n  color: #454545;\n  font-style: italic;\n}\n\n#discovery-toggle-button {\n  background: transparent;\n  border: 1px solid #aaa;\n  color: #454545;\n  font-style: italic;\n}\n\nhr {\n  border: 0;\n  height: 0;\n  border-top: 1px solid rgba(0,0,0,0.12);\n  border-bottom: 1px solid rgba(255,255,255,0.3);\n}\n\n#no-devices-error {\n  font-size: 10pt;\n  text-align: center;\n  padding-top: 15%;\n}\n\n#info-div {\n  height: 245px;\n  box-sizing: border-box;\n  margin: 10px;\n  padding: 10px;\n  box-shadow: 0 0 4px rgba(0, 0, 0, 0.65);\n  overflow-y: scroll;\n  overflow-x: hidden;\n  word-break: break-all;\n  color: #333;\n}\n\n.device-info-field {\n  margin-bottom: 6px;\n  font-weight: bold;\n}\n\ndiv.device-info-field span {\n  font-style: italic;\n  font-weight: normal;\n}\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/device-info-demo/ui.js",
    "content": "var UI = (function() {\n\n  // Common functions used for tweaking UI elements.\n  function UI() {\n  }\n\n  // Global instance.\n  var instance;\n\n  UI.prototype.resetState = function(noDevices) {\n    document.getElementById('no-devices-error').hidden = !noDevices;\n    document.getElementById('info-div').hidden = noDevices;\n    this.clearAllFields();\n  };\n\n  UI.prototype.clearAllFields = function() {\n    setFieldValue('manufacturer-name-string', null);\n    setFieldValue('serial-number-string', null);\n    setFieldValue('hardware-revision-string', null);\n    setFieldValue('firmware-revision-string', null);\n    setFieldValue('software-revision-string', null);\n    setFieldValue('vendor-id-source', null);\n    setFieldValue('vendor-id', null);\n    setFieldValue('product-id', null);\n    setFieldValue('product-version', null);\n  };\n\n  UI.prototype.setStringValue = function(id, buffer) {\n    if (!buffer) {\n      setFieldValue(id, null);\n      return;\n    }\n\n    var valueString = String.fromCharCode.apply(null, new Uint8Array(buffer));\n    setFieldValue(id, valueString);\n  };\n\n  UI.prototype.setPnpIdValue = function(id, buffer) {\n    var vendorIdSource = null;\n    var vendorId = null;\n    var productId = null;\n    var productVersion = null;\n\n    var setPnpValues = function() {\n      setFieldValue('vendor-id-source', vendorIdSource);\n      setFieldValue('vendor-id', vendorId);\n      setFieldValue('product-id', productId);\n      setFieldValue('product-version', productVersion);\n    };\n\n    if (!buffer) {\n      setPnpValues();\n      return;\n    }\n\n    var valueBytes = new Uint8Array(buffer);\n    if (valueBytes.length != 7) {\n      setPnpValues();\n      return;\n    }\n\n    var vendorIdSource = valueBytes[0];\n    var vendorId = valueBytes[1] | valueBytes[2] << 8;\n    var productId = valueBytes[3] | valueBytes[4] << 8;\n    var productVersion = valueBytes[5] | valueBytes[6] << 8;\n\n    setPnpValues();\n  };\n\n  UI.prototype.setDiscoveryToggleState = function(isDiscoverying) {\n    var discoveryToggleButton = document.getElementById('discovery-toggle-button');\n    if (isDiscoverying) {\n      discoveryToggleButton.innerHTML = 'stop discovery';\n    } else {\n      discoveryToggleButton.innerHTML = 'start discovery';\n    }\n  };\n\n  UI.prototype.setDiscoveryToggleHandler = function(handler) {\n    var discoveryToggleButton = document.getElementById('discovery-toggle-button');\n    discoveryToggleButton.onclick = handler;\n  };\n\n  UI.prototype.setDeviceSelectionHandler = function(handler) {\n    var deviceSelector =  document.getElementById('device-selector');\n    deviceSelector.onchange = function() {\n      handler(deviceSelector[deviceSelector.selectedIndex].value);\n    };\n  };\n\n  UI.prototype.triggerDeviceSelection = function() {\n    var deviceSelector = document.getElementById('device-selector');\n    if (deviceSelector.onchange)\n      deviceSelector.onchange();\n  };\n\n  UI.prototype.getSelectedDeviceAddress = function() {\n    var deviceSelector = document.getElementById('device-selector');\n    return deviceSelector[deviceSelector.selectedIndex].value;\n  };\n\n  UI.prototype.updateDeviceSelector = function(deviceMap, reset) {\n    var deviceSelector = document.getElementById('device-selector');\n    var placeHolder = document.getElementById('placeholder');\n    var addresses = Object.keys(deviceMap);\n\n    reset = (reset !== undefined) ? reset : false;\n\n    deviceSelector.innerHTML = '';\n    placeHolder.innerHTML = '';\n    deviceSelector.appendChild(placeHolder);\n\n    // Clear the drop-down menu.\n    if (addresses.length == 0) {\n      console.log('No connected devices found');\n      placeHolder.appendChild(document.createTextNode('No connected devices'));\n      return;\n    }\n\n    // Hide the placeholder and populate\n    placeHolder.appendChild(document.createTextNode('Connected devices found'));\n\n    for (var i = 0; i < addresses.length; i++) {\n      var address = addresses[i];\n      var deviceOption = document.createElement('option');\n      deviceOption.setAttribute('value', address);\n      deviceOption.appendChild(document.createTextNode(\n          deviceMap[address]));\n      deviceSelector.appendChild(deviceOption);\n    }\n\n    if (reset)\n      deviceSelector.selectedIndex = 0;\n  };\n\n  UI.prototype.setAdapterState = function(address, name) {\n    var addressField = document.getElementById('adapter-address');\n    var nameField = document.getElementById('adapter-name');\n\n    var setAdapterField = function (field, value) {\n      field.innerHTML = '';\n      field.appendChild(document.createTextNode(value));\n    };\n\n    setAdapterField(addressField, address ? address : 'unknown');\n    setAdapterField(nameField, name ? name : 'Local Adapter');\n  };\n\n  // private methods:\n\n  function setFieldValue(id, value) {\n    var div = document.getElementById(id);\n    div.innerHTML = '';\n    div.appendChild(\n        document.createTextNode((value == null) ? '-' : value));\n  }\n\n  return {\n    getInstance: function() {\n      if (!instance) {\n        instance = new UI();\n      }\n\n      return instance;\n    }\n  };\n})();\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/heart-rate-sensor/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/nmlcgjldnboapnjdmllfcdenlljfjanm\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\nLow-Energy Heart Rate Sensor\n============================\n\nThis sample demonstrates using the chrome.bluetoothLowEnergy API to communicate\nwith the Generic Attribute Profile (GATT) based Heart Rate Service on a\nBluetooth Low Energy heart rate sensor.\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/bluetooth-samples/heart-rate-sensor/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/heart-rate-sensor/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('main.html', {\n    'innerBounds': {\n      'width': 620,\n      'height': 274,\n      'minWidth': 620,\n      'minHeight': 274,\n      'left': 100,\n      'top': 100\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/heart-rate-sensor/main.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>Bluetooth LE Heart Rate Monitor</title>\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n  <script src=\"ui.js\"></script>\n  <script src=\"main.js\"></script>\n</head>\n<body>\n  <div id=\"header\">\n    <img src=\"hr_sensor_icon128.png\" alt=\"bluetooth heart icon\">\n    <h1>Bluetooth LE Heart Rate Monitor</h1>\n    <div id=\"adapter-status\">\n      <ul>\n        <li><span id=\"adapter-name\"></span></li>\n        <li><span id=\"adapter-address\"></span></li>\n      </ul>\n    </div>\n    <hr>\n    <div id=\"device-selection-div\">\n      Select Heart Rate Monitor:\n      <select id=\"device-selector\">\n        <option id=\"placeholder\" value=\"\" disabled selected>\n          No HR devices\n        </option>\n      </select>\n      <button type=\"button\" id=\"discovery-toggle-button\">\n        start discovery\n      </button>\n    </div>\n  </div>\n  <div id=\"no-devices-error\">\n    No Heart Rate device selected\n  </div>\n  <div id=\"info-div\">\n    <div id=\"heart-rate-bpm\">\n      <span id=\"heart-rate-measurement\">-</span>\n      <div id=\"heart\">\n        <img src=\"heart.png\" alt=\"heart icon\" class=\"blink-animation\">\n      </div>\n    </div>\n    <div id=\"heart-rate-fields\">\n      <div class=\"heart-rate-field\">\n        Sensor Contact Status: <span id=\"sensor-contact-status\">-</span>\n      </div>\n      <div class=\"heart-rate-field\">\n        Energy Expanded: <span id=\"energy-expanded\">-</span> kJ\n      </div>\n      <div class=\"heart-rate-field\">\n        RR-Interval: <span id=\"rr-interval\">-</span> s\n      </div>\n      <div class=\"heart-rate-field\">\n        Body Sensor Location: <span id=\"body-sensor-location\">-</span>\n      </div>\n      <button id=\"heart-rate-control-point\">Reset Energy Expanded</button>\n    </div>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/heart-rate-sensor/main.js",
    "content": "var main = (function() {\n  // GATT Heart Rate Service UUIDs\n  var HEART_RATE_SERVICE_UUID       = '0000180d-0000-1000-8000-00805f9b34fb';\n  var HEART_RATE_MEASUREMENT_UUID   = '00002a37-0000-1000-8000-00805f9b34fb';\n  var BODY_SENSOR_LOCATION_UUID     = '00002a38-0000-1000-8000-00805f9b34fb';\n  var HEART_RATE_CONTROL_POINT_UUID = '00002a39-0000-1000-8000-00805f9b34fb';\n\n  function HeartRateSensor() {\n    // A mapping from device addresses to device names for found devices that\n    // expose a Heart Rate service.\n    this.deviceMap_ = {};\n\n    // The currenty selected service and its characteristics.\n    this.service_ = null;\n    this.measurementChrc_ = null;\n    this.energyExpandedChrc_ = null;\n    this.bodySensorLocChrc_ = null;\n    this.controlPointChrc_ = null;\n    this.discovering_ = false;\n  }\n\n  /**\n   * Sets up the UI for the given service by retrieving the initial values of\n   * all relevant characteristics and performing other necessary set up.\n   */\n  HeartRateSensor.prototype.selectService = function(service) {\n    // Hide or show the appropriate elements based on whether or not\n    // |serviceId| is undefined.\n    UI.getInstance().resetState(!service);\n\n    if (this.service_ && (!service || this.service_.deviceAddress !== service.deviceAddress)) {\n      chrome.bluetoothLowEnergy.disconnect(this.service_.deviceAddress);\n    }\n\n    this.service_ = service;\n\n    // Disable notifications from the currently selected Heart Rate Measurement\n    // characteristic\n    if (this.measurementChrc_) {\n      chrome.bluetoothLowEnergy.stopCharacteristicNotifications(\n          this.measurementChrc_.instanceId);\n    }\n\n    this.measurementChrc_ = null;\n    this.bodySensorLocChrc_ = null;\n    this.controlPointChrc_ = null;\n    this.energyExpandedChrc_ = null;\n    if (!service) {\n      console.log('No service selected.');\n      return;\n    }\n\n    console.log('GATT service selected: ' + service.instanceId);\n\n    // Get the characteristics of the selected service.\n    var self = this;\n    chrome.bluetoothLowEnergy.getCharacteristics(service.instanceId,\n                                                 function (chrcs) {\n      if (chrome.runtime.lastError) {\n        console.log(chrome.runtime.lastError.message);\n        return;\n      }\n\n      // Make sure that the same service is still selected.\n      if (service.instanceId != self.service_.instanceId) {\n        return;\n      }\n\n      if (chrcs.length == 0) {\n        console.log('Service has no characteristics: ' + service.instanceId);\n        return;\n      }\n\n      chrcs.forEach(function (chrc) {\n        if (chrc.uuid == HEART_RATE_MEASUREMENT_UUID) {\n          console.log('Setting Heart Rate Measurement Characteristic: ' +\n                      chrc.instanceId);\n          self.measurementChrc_ = chrc;\n          self.updateHeartRateMeasurementValue();\n\n          // Enable notifications from the characteristic.\n          chrome.bluetoothLowEnergy.startCharacteristicNotifications(\n              chrc.instanceId,\n              function () {\n            if (chrome.runtime.lastError) {\n              console.log(\n                  'Failed to enable Heart Rate Measurement notifications: ' +\n                   chrome.runtime.lastError.message);\n              return;\n            }\n\n            console.log('Heart Rate Measurement notifications enabled!');\n          });\n          return;\n        }\n\n        if (chrc.uuid == BODY_SENSOR_LOCATION_UUID) {\n          console.log('Setting Body Sensor Location Characteristic: ' +\n                      chrc.instanceId);\n          self.bodySensorLocChrc_ = chrc;\n\n          // Read the value of the characteristic once and store it.\n          chrome.bluetoothLowEnergy.readCharacteristicValue(\n              chrc.instanceId,\n              function (readChrc) {\n            if (chrome.runtime.lastError) {\n              console.log(chrome.runtime.lastError.message);\n              return;\n            }\n\n            // Make sure that the same characteristic is still selected.\n            if (readChrc.instanceId != self.bodySensorLocChrc_.instanceId) {\n              return;\n            }\n\n            self.bodySensorLocChrc_ = readChrc;\n            self.updateBodySensorLocationValue();\n          });\n\n          return;\n        }\n\n        if (chrc.uuid == HEART_RATE_CONTROL_POINT_UUID) {\n          console.log('Setting Heart Rate Control Point Characteristic: ' +\n                      chrc.instanceId);\n          self.controlPointChrc_ = chrc;\n          UI.getInstance().setResetButtonEnabled(true);\n          return;\n        }\n      });\n    });\n  };\n\n  HeartRateSensor.prototype.updateHeartRateMeasurementValue = function() {\n    if (!this.measurementChrc_) {\n      console.log('No Heart Rate Measurement Characteristic selected');\n      return;\n    }\n\n    // The Heart Rate Measurement Characteristic does not allow 'read'\n    // operations and its value can only be obtained via notifications, so the\n    // |value| field might be undefined here.\n    if (!this.measurementChrc_.value) {\n      console.log('No Heart Rate Measurement value received yet');\n      return;\n    }\n\n    var valueBytes = new Uint8Array(this.measurementChrc_.value);\n    if (valueBytes.length < 2) {\n      console.log('Invalid Heart Rate Measurement value');\n      return;\n    }\n\n    // The first byte is the flags field.\n    var flags = valueBytes[0];\n\n    // The least significant bit is the Heart Rate Value format. If 0, the heart\n    // rate measurement is expressed in the next byte of the value. If 1, it is\n    // a 16 bit value expressed in the next two bytes of the value.\n    var hrFormat = flags & 0x01;\n\n    // The next two bits is the Sensor Contact Status.\n    var sensorContactStatus = (flags >> 1) & 0x03;\n\n    // The next bit is the Energy Expanded Status. If 1, the Energy Expanded\n    // field is present in the characteristic value.\n    var eeStatus = (flags >> 3) & 0x01;\n\n    // The next bit is the RR-Interval bit. If 1, RR-Interval values are\n    // present.\n    var rrBit = (flags >> 4) & 0x01;\n\n    var heartRateMeasurement;\n    var energyExpanded;\n    var rrInterval;\n    var minLength = hrFormat == 1 ? 3 : 2;\n    if (valueBytes.length < minLength) {\n      console.log('Invalid Heart Rate Measurement value');\n      return;\n    }\n\n    if (hrFormat == 0) {\n      console.log('8-bit Heart Rate format');\n      heartRateMeasurement = valueBytes[1];\n    } else {\n      console.log('16-bit Heart Rate format');\n      heartRateMeasurement = valueBytes[1] | (valueBytes[2] << 8);\n    }\n\n    var nextByte = minLength;\n    if (eeStatus == 1) {\n      if (valueBytes.length < nextByte + 2) {\n        console.log('Invalid value for \"Energy Expanded\"');\n        return;\n      }\n\n      console.log('Energy Expanded field present');\n      energyExpanded = valueBytes[nextByte] | (valueBytes[nextByte + 1] << 8);\n      nextByte += 2;\n    }\n\n    if (rrBit == 1) {\n      if (valueBytes.length < nextByte + 2) {\n        console.log('Invalid value for \"RR-Interval\"');\n        return;\n      }\n\n      console.log('RR-Interval field present');\n\n      // Note: According to the specification, there can be several RR-Interval\n      // values in a characteristic value, however we're just picking the first\n      // one here for demo purposes.\n      rrInterval = valueBytes[nextByte] | (valueBytes[nextByte + 1] << 8);\n    }\n\n    UI.getInstance().setHeartRateMeasurement(heartRateMeasurement);\n    UI.getInstance().setSensorContactStatus((function() {\n      switch (sensorContactStatus) {\n      case 0:\n      case 1:\n        return 'not supported';\n      case 2:\n        return 'contact not detected';\n      case 3:\n        return 'contact detected';\n      default:\n        return;\n      }\n    })());\n\n    if (energyExpanded !== undefined) {\n        this.energyExpandedChrc_ = energyExpanded;\n    }\n\n    UI.getInstance().setEnergyExpanded(this.energyExpandedChrc_);\n    UI.getInstance().setRRInterval(rrInterval);\n  };\n\n  HeartRateSensor.prototype.updateBodySensorLocationValue = function() {\n    if (!this.bodySensorLocChrc_) {\n      console.log('No Body Sensor Location Characteristic selected');\n      return;\n    }\n\n    // Since this function is called after a read request, the value should be\n    // present if the read was successful but it may be undefined if the read\n    // failed, so check here.\n    if (!this.bodySensorLocChrc_.value) {\n      console.log('No Body Sensor Location has been read');\n      return;\n    }\n\n    var valueBytes = new Uint8Array(this.bodySensorLocChrc_.value);\n    if (valueBytes.length != 1) {\n      console.log('Invalid Body Sensor Location value');\n      return;\n    }\n\n    var bodySensorLocation = (function () {\n      switch (valueBytes[0]) {\n      case 0:\n        return 'Other';\n      case 1:\n        return 'Chest';\n      case 2:\n        return 'Wrist';\n      case 3:\n        return 'Finger';\n      case 4:\n        return 'Hand';\n      case 5:\n        return 'Ear Lobe';\n      case 6:\n        return 'Foot';\n      default:\n        return;\n      }\n    })();\n\n    UI.getInstance().setBodySensorLocation(bodySensorLocation);\n  };\n\n  HeartRateSensor.prototype.resetEnergyExpanded = function() {\n    if (!this.controlPointChrc_) {\n      console.log('No Heart Rate Control Point characteristic selected');\n      return;\n    }\n\n    var writeValue = new ArrayBuffer(1);\n    var writeBytes = new Uint8Array(writeValue);\n    writeBytes[0] = 1;  // '1' indicates a 'reset' command.\n\n    chrome.bluetoothLowEnergy.writeCharacteristicValue(\n        this.controlPointChrc_.instanceId,\n        writeValue,\n        function () {\n      if (chrome.runtime.lastError) {\n        console.log(chrome.runtime.lastError.message);\n        return;\n      }\n\n      console.log('Heart Rate Control Point Characteristic written!');\n    });\n  };\n\n  HeartRateSensor.prototype.updateDiscoveryToggleState = function(discovering) {\n    if (this.discovering_ !== discovering) {\n      this.discovering_ = discovering;\n      UI.getInstance().setDiscoveryToggleState(this.discovering_);\n    }\n  };\n\n  HeartRateSensor.prototype.init = function() {\n    // Set up the UI to look like no device was initially selected.\n    this.selectService(undefined);\n\n    var self = this;\n    // Request information about the local Bluetooth adapter to be displayed in\n    // the UI.\n    var updateAdapterState = function(adapterState) {\n      UI.getInstance().setAdapterState(adapterState.address, adapterState.name);\n      self.updateDiscoveryToggleState(adapterState.discovering);\n    };\n\n    chrome.bluetooth.getAdapterState(function (adapterState) {\n      if (chrome.runtime.lastError) {\n        console.log(chrome.runtime.lastError.message);\n      }\n\n      self.updateDiscoveryToggleState(adapterState.discovering);\n      updateAdapterState(adapterState);\n    });\n\n    chrome.bluetooth.onAdapterStateChanged.addListener(updateAdapterState);\n\n    // Initialize the device map.\n    chrome.bluetooth.getDevices(function (devices) {\n      if (chrome.runtime.lastError) {\n        console.log(chrome.runtime.lastError.message);\n      }\n\n      if (devices) {\n        devices.forEach(function (device) {\n          if (device.uuids &&\n              device.uuids.indexOf(HEART_RATE_SERVICE_UUID) > -1) {\n            if (!self.deviceMap_.hasOwnProperty(device.address)) {\n              self.deviceMap_[device.address] =\n                  (device.name ? device.name : device.address);\n              UI.getInstance().updateDeviceSelector(self.deviceMap_);\n            }\n            return;\n          }\n\n          // See if the device exposes a Heart Rate service.\n          chrome.bluetoothLowEnergy.getServices(device.address,\n                                                function (services) {\n            if (chrome.runtime.lastError) {\n              console.log(chrome.runtime.lastError.message);\n              return;\n            }\n\n            if (!services) {\n              return;\n            }\n\n            var found = false;\n            services.forEach(function (service) {\n              if (service.uuid == HEART_RATE_SERVICE_UUID) {\n                console.log('Found Heart Rate service!');\n                found = true;\n              }\n            });\n\n            if (!found) {\n              return;\n            }\n\n            if (!self.deviceMap_.hasOwnProperty(device.address)) {\n              console.log('Found device with Heart Rate service: ' +\n                          device.address);\n              self.deviceMap_[device.address] =\n                  (device.name ? device.name : device.address);\n              UI.getInstance().updateDeviceSelector(self.deviceMap_);\n            }\n          });\n        });\n      }\n    });\n\n    // Set up discovery toggle button handler\n    UI.getInstance().setDiscoveryToggleHandler(function() {\n      var discoveryHandler = function() {\n        if (chrome.runtime.lastError) {\n          console.log('Failed to ' + (self.discovering_ ? 'stop' : 'start') + ' discovery ' +\n                      chrome.runtime.lastError.message);\n        }\n      };\n      if (self.discovering_) {\n        chrome.bluetooth.stopDiscovery(discoveryHandler);\n      } else {\n        chrome.bluetooth.startDiscovery(discoveryHandler);\n      }\n    });\n\n    // Set up the device selector.\n    UI.getInstance().setDeviceSelectionHandler(function (selectedValue) {\n      // If |selectedValue| is empty, unselect everything.\n      if (!selectedValue) {\n        self.selectService(undefined);\n        return;\n      }\n\n      chrome.bluetoothLowEnergy.connect(selectedValue, function () {\n        if (chrome.runtime.lastError) {\n          console.log('Failed to connect to HR device \"' + selectedValue +\n                      '\" ' + chrome.runtime.lastError.message);\n          return;\n        }\n        console.log('Connected to HR device: ' + selectedValue);\n      });\n\n      // Request all GATT services of the selected device to see if it still has\n      // a Heart Rate service and pick the first Heart Rate service to display.\n      chrome.bluetoothLowEnergy.getServices(selectedValue, function (services) {\n        if (chrome.runtime.lastError) {\n          console.log(chrome.runtime.lastError.message);\n          self.selectService(undefined);\n          return;\n        }\n\n        var foundService = undefined;\n        services.forEach(function (service) {\n          if (service.uuid == HEART_RATE_SERVICE_UUID) {\n            foundService = service;\n          }\n        });\n\n        self.selectService(foundService);\n      });\n    });\n\n    // Set up the \"Reset Energy Expanded\" button action.\n    UI.getInstance().setResetEnergyExpandedHandler(function() {\n      self.resetEnergyExpanded();\n    });\n\n    // Track devices that get added and removed. If they have the heart rate\n    // UUID in their advertisement data, then it will be available in the\n    // |uuids| field of the device.\n    chrome.bluetooth.onDeviceAdded.addListener(function (device) {\n      if (!device.uuids || device.uuids.indexOf(HEART_RATE_SERVICE_UUID) < 0) {\n        return;\n      }\n\n      if (self.deviceMap_.hasOwnProperty(device.address)) {\n        return;\n      }\n\n      console.log('Found device with HR service: ' + device.address);\n\n      self.deviceMap_[device.address] =\n          (device.name ? device.name : device.address);\n      UI.getInstance().updateDeviceSelector(self.deviceMap_);\n    });\n\n    // Track devices as they are removed.\n    chrome.bluetooth.onDeviceRemoved.addListener(function (device) {\n      if (!self.deviceMap_.hasOwnProperty(device.address)) {\n        return;\n      }\n\n      console.log('HR device removed: ' + device.address);\n      delete self.deviceMap_[device.address];\n      if (self.service_ && self.service_.deviceAddress == device.address) {\n        chrome.bluetoothLowEnergy.disconnect(device.address);\n        self.selectService(undefined);\n        UI.getInstance().triggerDeviceSelection();\n      }\n      UI.getInstance().updateDeviceSelector(self.deviceMap_);\n    });\n\n    // Track GATT services as they are added.\n    chrome.bluetoothLowEnergy.onServiceAdded.addListener(function (service) {\n      // Ignore, if the service is not a Heart Rate service.\n      if (service.uuid != HEART_RATE_SERVICE_UUID) {\n        return;\n      }\n\n      // If this came from the currently selected device and no service is\n      // currently selected, select this service.\n      if (UI.getInstance().getSelectedDeviceAddress() == service.deviceAddress\n          && !self.service_) {\n        self.selectService(service);\n      }\n\n      // Add the device of the service to the device map and update the UI.\n      console.log('New Heart Rate service added: ' + service.instanceId);\n      if (self.deviceMap_.hasOwnProperty(service.deviceAddress)) {\n        return;\n      }\n\n      // Looks like it's a brand new device. Get information about the device so\n      // that we can display the device name in the drop-down menu.\n      chrome.bluetooth.getDevice(service.deviceAddress, function (device) {\n        if (chrome.runtime.lastError) {\n          console.log(chrome.runtime.lastError.message);\n          return;\n        }\n\n        self.deviceMap_[device.address] =\n            (device.name ? device.name : device.address);\n        UI.getInstance().updateDeviceSelector(self.deviceMap_);\n      });\n    });\n\n    // Track GATT services as they are removed.\n    chrome.bluetoothLowEnergy.onServiceRemoved.addListener(function (service) {\n      // Ignore, if the service is not a Heart Rate service.\n      if (service.uuid != HEART_RATE_SERVICE_UUID) {\n        return;\n      }\n\n      // See if this is the currently selected service. If so, unselect it.\n      console.log('Heart Rate service removed: ' + service.instanceId);\n      var selectedRemoved = false;\n      if (self.service_ && self.service_.instanceId == service.instanceId) {\n        console.log('The selected service disappeared!');\n        self.selectService(undefined);\n        selectedRemoved = true;\n        UI.getInstance().updateDeviceSelector(self.deviceMap_,\n                                              true /* reset */);\n      }\n\n      // Remove the associated device from the map only if it no longer lists\n      // the Heart Rate UUID.\n      if (!self.deviceMap_.hasOwnProperty(service.deviceAddress)) {\n        return;\n      }\n\n      chrome.bluetooth.getDevice(service.deviceAddress, function (device) {\n        if (chrome.runtime.lastError) {\n          console.log(chrome.runtime.lastError.message);\n          return;\n        }\n\n        if (!device.uuids || device.uuids.indexOf(HEART_RATE_SERVICE_UUID) < 0) {\n          console.log('Removing device: ' + device.address);\n          delete self.deviceMap_[device.address];\n          UI.getInstance().updateDeviceSelector(self.deviceMap_);\n        }\n\n        if (selectedRemoved) {\n          UI.getInstance().triggerDeviceSelection();\n        }\n      });\n    });\n\n    // Track GATT services as they change.\n    chrome.bluetoothLowEnergy.onServiceChanged.addListener(function (service) {\n      // This only matters if the selected service changed.\n      if (!self.service_ ||\n          service.instanceId != self.service_.instanceId) {\n        return;\n      }\n\n      console.log('The selected service has changed');\n\n      // Reselect the service to force an updated.\n      self.selectService(service);\n    });\n\n    // Track GATT characteristic value changes. This event will be triggered\n    // after successful characteristic value reads and received notifications\n    // and indications.\n    chrome.bluetoothLowEnergy.onCharacteristicValueChanged.addListener(\n        function (chrc) {\n      if (self.measurementChrc_ &&\n          chrc.instanceId == self.measurementChrc_.instanceId) {\n        console.log('Heart Rate Measurement value changed');\n        self.measurementChrc_ = chrc;\n        self.updateHeartRateMeasurementValue();\n        return;\n      }\n    });\n  };\n\n  return {\n    HeartRateSensor: HeartRateSensor\n  };\n\n})();\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  var sensor = new main.HeartRateSensor();\n  sensor.init();\n});\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/heart-rate-sensor/manifest.json",
    "content": "{\n  \"name\": \"Heart Rate Service Demo\",\n  \"description\": \"Heart Rate Monitor Demo using chrome.bluetoothLowEnergy\",\n  \"version\": \"0.1\",\n  \"minimum_chrome_version\": \"37\",\n  \"icons\": {\n    \"16\": \"hr_sensor_icon16.png\",\n    \"48\": \"hr_sensor_icon48.png\",\n    \"128\": \"hr_sensor_icon128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"bluetooth\": {\n    \"low_energy\": true,\n    \"uuids\": [\"180d\"]\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/heart-rate-sensor/style.css",
    "content": "body {\n  margin: 0;\n  overflow: hidden;\n}\n\n#header {\n  padding: 10px 15px 5px 15px;\n  background: #fafafa;\n  box-shadow: 0 0 5px #858585;\n  margin-bottom: 20px;\n}\n\n#header img {\n  width: 50px;\n}\n\n#header h1 {\n  font-family: 'DejaVu Sans Light', Verdana, sans-serif;\n  font-weight: normal;\n  vertical-align: top;\n  display: inline-block;\n  margin: 8px;\n}\n\n#adapter-status {\n  float: right;\n  margin-top: 2px;\n}\n\n#adapter-address {\n  font-weight: bold;\n}\n\nul {\n  padding-left: 0;\n  margin: inherit;\n}\n\nul li {\n  list-style-type: none;\n}\n\n#device-selection-div {\n  margin-top: 5px;\n}\n\n#device-selector {\n  background: transparent;\n  border: 1px solid #aaa;\n  color: #454545;\n  font-style: italic;\n}\n\n#discovery-toggle-button {\n  background: transparent;\n  border: 1px solid #aaa;\n  color: #454545;\n  font-style: italic;\n}\n\nhr {\n  border: 0;\n  height: 0;\n  border-top: 1px solid rgba(0,0,0,0.12);\n  border-bottom: 1px solid rgba(255,255,255,0.3);\n}\n\n#no-devices-error {\n  font-size: 10pt;\n  text-align: center;\n  padding-top: 7%;\n}\n\n#heart-rate-bpm {\n  float: left;\n  height: 136px;\n  line-height: 136px;\n  width: 50%;\n  text-align: center;\n  font-size: 35px;\n  color: #ff0000;\n}\n\n#heart {\n  position: relative;\n  display: inline-block;\n  width: 40px;\n  height: 40px;\n  top: 5%;\n  left: -10px;\n}\n\n#heart img {\n  position: absolute;\n  width: 50%;\n  height: 50%;\n  top: 25%;\n  left: 25%;\n}\n\n.blink-animation {\n  -webkit-animation: blink 1s linear infinite;\n}\n\n@-webkit-keyframes \"blink\" {\n  0% { opacity: 1; }\n  33% { opacity: 1; }\n  66% { opacity: 0; }\n  100% { opacity: 0; }\n}\n\n#heart-rate-fields {\n  float: right;\n  width: 48%;\n  margin-right: 2%;\n  box-sizing: border-box;\n  padding: 10px;\n  box-shadow: 0 0 4px rgba(0, 0, 0, 0.65);\n}\n\n.heart-rate-field {\n  margin-bottom: 5px;\n}\n\ndiv.heart-rate-field span {\n  font-style: italic;\n  color: #333;\n}\n"
  },
  {
    "path": "_archive/apps/samples/bluetooth-samples/heart-rate-sensor/ui.js",
    "content": "var UI = (function() {\n\n  // Common functions used for tweaking UI elements.\n  function UI() {\n  }\n\n  // Global instance.\n  var instance;\n\n  UI.prototype.resetState = function(noDevices) {\n    document.getElementById('no-devices-error').hidden = !noDevices;\n    document.getElementById('info-div').hidden = noDevices;\n    this.clearAllFields();\n  };\n\n  UI.prototype.clearAllFields = function() {\n    this.setHeartRateMeasurement(null);\n    this.setSensorContactStatus(null);\n    this.setEnergyExpanded(null);\n    this.setRRInterval(null);\n    this.setBodySensorLocation(null);\n    this.setResetButtonEnabled(false);\n  };\n\n  UI.prototype.setHeartRateMeasurement = function(value) {\n    setFieldValue('heart-rate-measurement', value);\n  };\n\n  UI.prototype.setSensorContactStatus = function(value) {\n    setFieldValue('sensor-contact-status', value);\n  };\n\n  UI.prototype.setEnergyExpanded = function(value) {\n    setFieldValue('energy-expanded', value);\n  };\n\n  UI.prototype.setRRInterval = function(value) {\n    setFieldValue('rr-interval', value);\n  };\n\n  UI.prototype.setBodySensorLocation = function(value) {\n    setFieldValue('body-sensor-location', value);\n  };\n\n  UI.prototype.setResetButtonEnabled = function(enabled) {\n    document.getElementById('heart-rate-control-point').disabled = !enabled;\n  };\n\n  UI.prototype.setResetEnergyExpandedHandler = function(handler) {\n    document.getElementById('heart-rate-control-point').onclick = handler;\n  };\n\n  UI.prototype.setDiscoveryToggleState = function(isDiscoverying) {\n    var discoveryToggleButton = document.getElementById('discovery-toggle-button');\n    if (isDiscoverying) {\n      discoveryToggleButton.innerHTML = 'stop discovery';\n    } else {\n      discoveryToggleButton.innerHTML = 'start discovery';\n    }\n  };\n\n  UI.prototype.setDiscoveryToggleHandler = function(handler) {\n    var discoveryToggleButton = document.getElementById('discovery-toggle-button');\n    discoveryToggleButton.onclick = handler;\n  };\n\n  UI.prototype.setDeviceSelectionHandler = function(handler) {\n    var deviceSelector =  document.getElementById('device-selector');\n    deviceSelector.onchange = function() {\n      handler(deviceSelector[deviceSelector.selectedIndex].value);\n    };\n  };\n\n  UI.prototype.triggerDeviceSelection = function() {\n    var deviceSelector = document.getElementById('device-selector');\n    if (deviceSelector.onchange)\n      deviceSelector.onchange();\n  };\n\n  UI.prototype.getSelectedDeviceAddress = function() {\n    var deviceSelector = document.getElementById('device-selector');\n    return deviceSelector[deviceSelector.selectedIndex].value;\n  };\n\n  UI.prototype.updateDeviceSelector = function(deviceMap, reset) {\n    var deviceSelector = document.getElementById('device-selector');\n    var placeHolder = document.getElementById('placeholder');\n    var addresses = Object.keys(deviceMap);\n\n    reset = (reset !== undefined) ? reset : false;\n\n    deviceSelector.innerHTML = '';\n    placeHolder.innerHTML = '';\n    deviceSelector.appendChild(placeHolder);\n\n    // Clear the drop-down menu.\n    if (addresses.length == 0) {\n      console.log('No heart rate devices found');\n      placeHolder.appendChild(document.createTextNode('No HR devices found'));\n      return;\n    }\n\n    // Hide the placeholder and populate\n    placeHolder.appendChild(document.createTextNode('HR devices found'));\n\n    for (var i = 0; i < addresses.length; i++) {\n      var address = addresses[i];\n      var deviceOption = document.createElement('option');\n      deviceOption.setAttribute('value', address);\n      deviceOption.appendChild(document.createTextNode(\n          deviceMap[address]));\n      deviceSelector.appendChild(deviceOption);\n    }\n\n    if (reset)\n      deviceSelector.selectedIndex = 0;\n  };\n\n  UI.prototype.setAdapterState = function(address, name) {\n    var addressField = document.getElementById('adapter-address');\n    var nameField = document.getElementById('adapter-name');\n\n    var setAdapterField = function (field, value) {\n      field.innerHTML = '';\n      field.appendChild(document.createTextNode(value));\n    };\n\n    setAdapterField(addressField, address ? address : 'unknown');\n    setAdapterField(nameField, name ? name : 'Local Adapter');\n  };\n\n  // private methods:\n\n  function setFieldValue(id, value) {\n    var div = document.getElementById(id);\n    div.innerHTML = '';\n    div.appendChild(\n        document.createTextNode((value == null) ? '-' : value));\n  }\n\n  return {\n    getInstance: function() {\n      if (!instance) {\n        instance = new UI();\n      }\n\n      return instance;\n    }\n  };\n\n})();\n"
  },
  {
    "path": "_archive/apps/samples/calculator/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/pelimflkpjiicnajdjcmekpioacmahkh\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Calculator\n\nA sample application that provides a simple calculator. Supports basic operations\nsuch as addition, multiplication, subtraction and division.\n\nThis sample also incorporates an MVC-style structure and requires jQuery for\nDOM manipulation.\n\n## APIs\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/calculator/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/calculator/calculator.html",
    "content": "<html>\n\t<head>\n\t\t<title>Calculator</title>\n\t\t<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />\n\t\t<script src=\"jquery/jquery.min.js\"></script>\n\t\t<script src=\"controller.js\"></script>\n\t\t<script src=\"model.js\"></script>\n\t\t<script src=\"view.js\"></script>\n\t</head>\n\n\t<body>\n\t\t<div class=\"edge-top\"></div>\n\t\t<div class=\"edge\"></div>\n\t\t<div id=\"calc\">\n      <div id=\"display\" class=\"calc-display\">\n      </div>\n      <div id=\"buttons\" class=\"button-row\">\n        <div class=\"button-column\" style=\"flex-basis: 300%\">\n          <div class=\"button-row\">\n            <div class=\"calc-button AC\">AC</div>\n            <div class=\"calc-button plus-minus\">+/-</div>\n            <div class=\"calc-button div big\">&divide;</div>\n          </div>\n          <div class=\"button-row\">\n            <div class=\"calc-button seven\">7</div>\n            <div class=\"calc-button eight\">8</div>\n            <div class=\"calc-button nine\">9</div>\n          </div>\n          <div class=\"button-row\">\n            <div class=\"calc-button four\">4</div>\n            <div class=\"calc-button five\">5</div>\n            <div class=\"calc-button six\">6</div>\n          </div>\n          <div class=\"button-row\">\n            <div class=\"calc-button one\">1</div>\n            <div class=\"calc-button two\">2</div>\n            <div class=\"calc-button three\">3</div>\n          </div>\n          <div class=\"button-row\">\n            <div class=\"calc-button zero\">0</div>\n            <div class=\"calc-button point big\">.</div>\n          </div>\n        </div>\n        <div class=\"button-column\">\n          <div class=\"calc-button mult big\">&times;</div>\n          <div class=\"calc-button minus big\">&#150;</div>\n          <div class=\"calc-button plus big\">+</div>\n          <div class=\"calc-button equals big\">=</div>\n        </div>  \n      </div>\n    </div>\n\t</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/calculator/controller.js",
    "content": "$(document).ready(function () {\n  new View(new Calculator());\n});\n"
  },
  {
    "path": "_archive/apps/samples/calculator/main.js",
    "content": "/**\n * Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\n\n/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('calculator.html', {\n    id: \"calcWinID\",\n    innerBounds: {\n      width: 244,\n      height: 380,\n      minWidth: 244,\n      minHeight: 380\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/calculator/manifest.json",
    "content": "{\n  \"name\": \"Calculator\",\n  \"description\": \"A simple calculator.\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"23\",\n  \"version\": \"1.2\",\n  \"offline_enabled\": true,\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\" : [\n    \"clipboardWrite\"\n  ],\n  \"icons\": {\n    \"16\": \"assets/icon-128x128.png\",\n    \"128\": \"assets/icon-128x128.png\"\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/calculator/model.js",
    "content": "function Calculator() {\n  this.operatorNeedsReset = true;\n  this.operandNeedsReset = true;\n  this.accumulatorNeedsReset = true;\n  this.decimal = -1;\n  this.ResetRegisters();\n}\n\nCalculator.prototype.DoOperation = function() {\n  switch (this.operator) {\n    case '+':\n      this.accumulator += this.operand;\n      break;\n    case '-':\n      this.accumulator -= this.operand;\n      break;\n    case '/':\n      this.accumulator /= this.operand;\n      break;\n    case '*':\n      this.accumulator *= this.operand;\n      break;\n    default:\n      this.accumulator = this.operand;\n    break;\n  }\n  return this.accumulator;\n}\n\nCalculator.prototype.SendAccumulatorByUDP = function() {\n  var calcResult = this.accumulator;\n}\n\nCalculator.prototype.ResetRegisters = function() {\n  if (this.operatorNeedsReset) {\n    this.operatorNeedsReset = false;\n    this.operator = null;\n  }\n  if (this.operandNeedsReset) {\n    this.operandNeedsReset = false;\n    this.operand = 0;\n    this.decimal = -1;\n  }\n  if (this.accumulatorNeedsReset) {\n    this.accumulatorNeedsReset = false;\n    this.accumulator = 0;\n  }\n}\n\nCalculator.prototype.HandleButtonClick = function(buttonValue) {\n  var result;\n\n  switch (buttonValue) {\n    case '+':\n    case '-':\n    case '/':\n    case '*':\n      this.decimal = -1;\n      if (this.operatorNeedsReset) {\n        this.operatorNeedsReset = false;\n        this.operator = null;\n        this.operand = this.accumulator;\n      }\n      this.operandNeedsReset = true;\n      result = this.DoOperation();\n      this.operator = buttonValue;\n      break;\n    case '=':\n      this.decimal = -1;\n      this.operandNeedsReset = true;\n      this.operatorNeedsReset = true;\n      this.DoOperation();\n      this.SendAccumulatorByUDP();\n      break;\n    case 'AC':\n      this.decimal = -1;\n      this.accumulatorNeedsReset = true;\n      this.operandNeedsReset = true;\n      this.operatorNeedsReset = true;\n      this.ResetRegisters();\n      break;\n    case '.':\n      if (this.decimal < 0)\n        this.decimal = 0;\n      this.operand = parseFloat(this.operand);\n      result = this.operand;\n      break;\n    case '+ / -':\n      this.operand *= -1;\n      break;\n    case 'back':\n      this.accumulatorNeedsReset = false;\n      this.ResetRegisters();\n      if (this.operand == 0) {\n        this.operator = 'back';\n        this.operatorNeedsReset = true;\n      }\n      else {\n        var operandStr = this.operand + '';\n        operandStr = operandStr.slice(0, operandStr.length - 1);\n        if (operandStr == '') this.operand = 0;\n        else this.operand = parseFloat(operandStr);\n      }\n      break;\n    default:\n      this.ResetRegisters();\n      if (this.decimal >= 0) {\n        this.decimal += 1;\n        this.operand += ( Math.pow(10, -1 * this.decimal)\n                          * parseInt(buttonValue));\n      } else {\n        this.operand *= 10;\n        this.operand += parseInt(buttonValue);\n      }\n      result = this.operand;\n      break;\n  }\n\n  if (result == null) {\n    result = this.accumulator;\n  }\n\n  var rstr_len = (result + '').length;\n  if ((result >= 0 && rstr_len > 8) ||\n      (result < 0 && rstr_len > 9)) {\n    result = 'Overflow';\n  }\n  return [this.operator, this.operand, this.accumulator];\n}\n"
  },
  {
    "path": "_archive/apps/samples/calculator/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"calculator\",\n  \"files_with_snippets\": [ ],\n  \"android\": {\"works\": true, \"comments\": \"Visual issues caused by fixed-size layout\"},\n  \"ios\": {\"works\": true, \"comments\": \"Visual issues caused by fixed-size layout\"}\n}\n"
  },
  {
    "path": "_archive/apps/samples/calculator/style.css",
    "content": "html {\n  margin: 0;\n  padding: 0;\n  width: 100%;\n  height: 100%;\n  overflow: hidden;\n}\n\nbody {\n  margin: 0px;\n  padding: 0px;\n  width: 100%;\n  height: 100%;\n  font: bold 16px 'Open Sans', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;\n  font-weight: 700;\n}\n\n::-webkit-scrollbar {\n  display: none;\n}\n\n::-webkit-scrollbar-thumb {\n  display: none;\n}\n\n#calc {\n  background-color: #fff;\n  border: 0;\n  margin: 0;\n  padding: 0px;\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n}\n\n#calc #display,\n#calc #display:focus {\n  flex: 1 1 100%;\n  border: none;\n  letter-spacing: 1px;\n  line-height: 20px;\n  margin: 0px;\n  min-width: 204px;\n  overflow: scroll;\n  padding: 20px;\n  width: calc( 100% - 40px );\n}\n\n.edge-top {\n  height: 5px;\n  width: 100%;\n  z-index: 99;\n  position: absolute;\n  background: #fff;\n}\n\n.edge {\n  background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,\n                                         rgba(255,255,255,0) 100%);\n  height: 20px;\n  position: absolute;\n  top: 5px;\n  width: 100%;\n  z-index: 99;\n}\n\n.equation {\n  width: 100%;\n  position: relative;\n  clear: both;\n  height: 22px;\n}\n\n.equation .operator {\n  color: #2c2c2c;\n  width: 15px;\n  float: right;\n  padding-right: 5px;\n  height: 22px;\n  line-height: 16px;\n  padding-top: 3px;\n  padding-bottom: 3px;\n}\n\n.equation .operand {\n  color: #2c2c2c;\n  float: right;\n  max-width: 80px;\n  text-align: right;\n  overflow: hidden;\n  height: 16px;\n  line-height: 16px;\n  padding-top: 3px;\n  padding-bottom: 3px;\n}\n\n.equation .accumulator {\n  color: #888;\n  float: left;\n  font-size: 13px;\n  width: 85px;\n  max-width: 80px;\n  text-align: left;\n  overflow: hidden;\n  height: 13px;\n  line-height: 13px;\n  padding-top: 6px;\n  padding-bottom: 3px;\n}\n\n#display .hr {\n  width: 100%;\n  height: 0px;\n  border-top: 1px solid #d9d9d9;\n  position: relative;\n}\n\n#calc #buttons {\n  flex: 1 1 100%;\n  height: 244px;\n  width: 100%;\n  min-height: 225px;\n  min-width: 244px;\n}\n\n.button-row {\n  display: flex;\n  flex-direction: row;\n  flex-wrap: nowrap;\n  flex: 1 1 100%;\n}\n\n.button-column {\n  display: flex;\n  flex-direction: column;\n  flex-wrap: nowrap;\n  flex: 1 1 100%;\n}\n\n.calc-button {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  font-size: 16px;\n  cursor: pointer;\n  text-align: center;\n  color: rgb(202, 202, 202);\n  background: linear-gradient(#4B4B4B, #424242);\n  box-shadow: inset 1px 1px 0 #636363, inset -1px -1px 0 #141414;\n  text-shadow: 1px 1px #222;\n  flex: 1 1 100%;\n}\n.calc-button:active, .calc-button.active {\n  background: linear-gradient(#424242, #4B4B4B);\n  box-shadow: inset 1px 1px 0 #141414, inset -1px -1px 0 #636363;\n}\n\n.calc-button.big {\n  font-size: 24px;\n}\n\n.calc-button.AC {\n}\n\n.calc-button.plus-minus {\n}\n\n.calc-button.div {\n}\n\n.calc-button.mult {\n}\n.calc-button.plus {\n}\n.calc-button.minus {\n}\n.calc-button.one {\n}\n.calc-button.two {\n}\n.calc-button.three {\n}\n.calc-button.four {\n}\n.calc-button.five {\n}\n.calc-button.six {\n}\n.calc-button.seven {\n}\n.calc-button.eight {\n}\n.calc-button.nine {\n}\n.calc-button.equals {\n  flex: 2 1 200%;\n  background: linear-gradient(#6BA0FF, #2C76F8);\n  box-shadow: inset 1px 1px 0 #84ACF5, inset -1px -1px 0 #175EDA;\n}\n.calc-button.equals:active, .calc-button.equals.active {\n  background: linear-gradient(#2C76F8, #6BA0FF);\n  box-shadow: inset 1px 1px 0 #175EDA, inset -1px -1px 0 #84ACF5;\n}\n.calc-button.zero {\n}\n.calc-button.point {\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/calculator/tests/calculator_test.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n    <title>Calculator Chrome App</title>\n    <script type=\"text/javascript\" src=\"../jquery/jquery.min.js\"></script>\n    <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/git/qunit.js\"></script>\n    <script type=\"text/javascript\" src=\"../view.js\"></script>\n    <script type=\"text/javascript\" src=\"../model.js\"></script>\n    <script type=\"text/javascript\" src=\"../controller.js\"></script>\n    <script type=\"text/javascript\" src=\"calculator_test.js\"></script>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"http://code.jquery.com/qunit/git/qunit.css\">\n  </head>\n\n  <body>\n    <h1 id=\"qunit-header\">Calculator Tests</h1>\n    <h2 id=\"qunit-banner\"></h2>\n    <div id=\"qunit-testrunner-toolbar\"></div>\n    <h2 id=\"qunit-userAgent\"></h2>\n    <ol id=\"qunit-tests\"></ol>\n\n    <div id=\"qunit-fixture\">\n      <div id=\"calc\">\n        <div class=\"edge-top\"></div>\n        <div class=\"edge\"></div>\n        <div id=\"display\" class=\"calc-display\"></div>\n        <div id=\"buttons\"></div>\n      </div>\n    </div>\n\n</body>\n</html>\n\n\n\n\n"
  },
  {
    "path": "_archive/apps/samples/calculator/tests/calculator_test.js",
    "content": "$(document).ready(function() {\n\n  module(\"Initialize and Reset Registers\");\n\n    test(\"Basic Initialization\", function() {\n      var calculator = new Calculator();\n      ok(!calculator.operatorNeedsReset);\n      equal(calculator.operator, null);\n      equal(calculator.decimal, -1);\n      ok(!calculator.operandNeedsReset);\n      ok(!calculator.accumulatorNeedsReset);\n      equal(calculator.operand, 0);\n      equal(calculator.accumulator, 0);\n    });\n\n    test(\"Reset Operator\", function() {\n      var calculator = new Calculator();\n      calculator.operator = '+';\n      calculator.operatorNeedsReset = true;\n      calculator.ResetRegisters();\n      ok(!calculator.operatorNeedsReset);\n      equal(calculator.operator, null);\n    });\n\n    test(\"Reset Operand\", function() {\n      var calculator = new Calculator();\n      calculator.operand = 50;\n      calculator.decimal = -5;\n      calculator.operandNeedsReset = true;\n      calculator.ResetRegisters();\n      ok(!calculator.operatorNeedsReset);\n      equal(calculator.operator, null);\n      equal(calculator.decimal, -1);\n    });\n\n    test(\"Reset Accumulator\", function() {\n      var calculator = new Calculator();\n      calculator.accumulator = 50;\n      calculator.accumulatorNeedsReset = true;\n      calculator.ResetRegisters();\n      ok(!calculator.accumulatorNeedsReset);\n      equal(calculator.accumulator, 0);\n    });\n\n  module(\"Do Operations\");\n\n    test(\"Plus\", function() {\n      var calculator = new Calculator();\n      calculator.operator = '+';\n      equal(calculator.accumulator, 0);\n\n      calculator.operand = 5;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 5);\n\n      calculator.operand = -3;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 2);\n\n      calculator.operand = -2;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 0);\n\n      calculator.operand = -1;\n      calculator.DoOperation();\n      equal(calculator.accumulator, -1);\n\n      calculator.operand = 3;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 2);\n\n      calculator.operand = 0;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 2);\n    });\n\n    test(\"Minus\", function() {\n      var calculator = new Calculator();\n      calculator.operator = '-';\n      equal(calculator.accumulator, 0);\n\n      calculator.operand = 5;\n      calculator.DoOperation();\n      equal(calculator.accumulator, -5);\n\n      calculator.operand = -3;\n      calculator.DoOperation();\n      equal(calculator.accumulator, -2);\n\n      calculator.operand = -2;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 0);\n\n      calculator.operand = -1;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 1);\n\n      calculator.operand = 3;\n      calculator.DoOperation();\n      equal(calculator.accumulator, -2);\n\n      calculator.operand = 0;\n      calculator.DoOperation();\n      equal(calculator.accumulator, -2);\n    });\n\n    test(\"Multiplication\", function() {\n      var calculator = new Calculator();\n      calculator.operator = '*';\n      equal(calculator.accumulator, 0);\n\n      calculator.operand = 5;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 0);\n\n      calculator.accumulator = 1;\n      equal(calculator.accumulator, 1);\n\n      calculator.operand = 5;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 5);\n\n      calculator.operand = -2;\n      calculator.DoOperation();\n      equal(calculator.accumulator, -10);\n\n      calculator.operand = 1.5;\n      calculator.DoOperation();\n      equal(calculator.accumulator, -15);\n\n      calculator.operand = -1;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 15);\n\n      calculator.operand = 0;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 0);\n    });\n\n    test(\"Division\", function() {\n      var calculator = new Calculator();\n      calculator.operator = '/';\n      equal(calculator.accumulator, 0);\n\n      calculator.operand = 5;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 0);\n\n      calculator.accumulator = 1;\n      equal(calculator.accumulator, 1);\n\n      calculator.operand = 5;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 0.2);\n\n      calculator.operand = -2;\n      calculator.DoOperation();\n      equal(calculator.accumulator, -0.1);\n\n      calculator.operand = 0.1;\n      calculator.DoOperation();\n      equal(calculator.accumulator, -1);\n\n      calculator.operand = -1;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 1);\n\n      calculator.operand = 0;\n      calculator.DoOperation();\n      equal(calculator.accumulator, 'Infinity');\n    });\n\n\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/calculator/view.js",
    "content": "var operators = ['+', '-', '/', '*'];\n\nvar values = { 'one'   : 1,\n               'two'   : 2,\n               'three' : 3,\n               'four'  : 4,\n               'five'  : 5,\n               'six'   : 6,\n               'seven' : 7,\n               'eight' : 8,\n               'nine'  : 9,\n               'zero'  : 0,\n               'plus'  : '+',\n               'minus' : '-',\n               'div'   : '/',\n               'mult'  : '*',\n               'equals': '=',\n               'point' : '.',\n               'AC'    : 'AC',\n               'plus-minus' : '+ / -'\n              };\n\nvar keyboard = { 49 : 1,\n                 50 : 2,\n                 51 : 3,\n                 52 : 4,\n                 53 : 5,\n                 54 : 6,\n                 55 : 7,\n                 56 : 8,\n                 57 : 9,\n                 48 : 0,\n                 187 : '=',\n                 13 : '=',\n                 190 : '.',\n                 189 : '-',\n                 191 : '/',\n                 65 : 'AC',  // a\n                 67 : 'AC',  // c\n                 8 : 'back',\n                 97 : 1,  // numberpad\n                 98 : 2,\n                 99 : 3,\n                 100 : 4,\n                 101 : 5,\n                 102 : 6,\n                 103 : 7,\n                 104 : 8,\n                 105 : 9,\n                 96 : 0,\n                 110 : '.',\n                 109 : '-',\n                 111 : '/',\n                 107 : '+',\n                 106 : '*'\n              };\nvar shiftKeyboard = { 187 : '+',\n                      56 : '*'\n                    };\n\nvar shift = false;\n\nfunction View(calcModel) {\n  this.calcElement = $('#calc');\n  this.buttonsElement = $('#buttons');\n  this.displayElement = $('#display');\n  this.lastDisplayElement = null;\n  this.BuildWidgets();\n  var calc = this;\n\n  Array.prototype.forEach.call(document.querySelectorAll('.calc-button'),\n    function(button) {\n      var handler = function(e) {\n        e.preventDefault();\n        var clicked = values[e.target.classList[1]];\n        var result = calcModel.HandleButtonClick(clicked);\n        calc.buttonClicked(clicked, result);\n      };\n      button.addEventListener('touchstart', handler);\n      button.addEventListener('click', handler);\n      button.addEventListener('touchstart', function(e) {\n        e.target.classList.add('active');\n      });\n      button.addEventListener('touchend', function(e) {\n        e.target.classList.remove('active');\n      });\n    });\n\n  window.addEventListener(\"copy\", function(e) {\n    var result = calcModel.accumulator;\n    e.preventDefault();\n    e.clipboardData.setData(\"text/plain\",result);\n  });\n\n  $(document).keydown(function(event) {\n    if (event.ctrlKey && event.keyCode == 67) {\n      return;\n    }\n    var clicked = null;\n    if (event.which == 16)\n      shift = true;\n    else if (shift && event.which in shiftKeyboard)\n      clicked = shiftKeyboard[event.which];\n    else if (!shift && event.which in keyboard)\n      clicked = keyboard[event.which];\n    if (clicked != null) {\n      var result = calcModel.HandleButtonClick(clicked);\n      calc.buttonClicked(clicked, result);\n    }\n  });\n\n  $(document).keyup(function(event) {\n    if (event.which == 16)\n      shift = false;\n  });\n}\n\nfunction displayNumber(number) {\n  var digits = (number + '').length;\n  if ((number >= 0 && digits > 8) || (number < 0 && digits > 9)) {\n    if (number % 1 != 0) {\n      number = parseFloat((number + '').slice(0, 8));\n      if (number % 1 != 0) return number;\n    }\n    var pow = (number + '').length - 1;\n    var extra_length = (pow + '').length + 2;\n    number = number * Math.pow(10, -1*pow);\n    number = (number + '').slice(0, 8 - extra_length) + 'e' + pow;\n  }\n  return number;\n}\n\nView.prototype.buttonClicked = function(clicked, result) {\n  var operator = result[0];\n  var operand = displayNumber(result[1]);\n  var accumulator = displayNumber(result[2]);\n  if (clicked == 'AC') {\n    this.displayElement.text('');\n    this.AddDisplayEquation('', 0, '');\n  }\n  else if (clicked == 'back' && operator == 'back') {\n    this.UpdateDisplayEquation('', '', '');\n  }\n  else if (operators.indexOf(clicked) != -1) {\n    if (this.lastDisplayElement)\n      this.UpdateTotal(accumulator);\n    operand = '';\n    accumulator = '';\n    this.AddDisplayEquation(operator, operand, accumulator);\n  }\n  else if (clicked == '=') {\n    this.displayElement.append('<div class=\"hr\"></div>');\n    this.AddDisplayEquation('', accumulator, accumulator);\n    this.lastDisplayElement = null;\n  }\n  else if (clicked == '+ / -') {\n    this.UpdateDisplayEquation(operator, operand, '');\n  }\n  else if (this.lastDisplayElement) {\n    accumulator = '';\n    this.UpdateDisplayEquation(operator, operand, accumulator);\n  }\n  else {\n    accumulator = '';\n    operator = '';\n    this.AddDisplayEquation(operator, operand, accumulator);\n  }\n}\n\nView.prototype.BuildWidgets = function() {\n  // this.AddButtons(this.calcElement);\n  this.AddDisplayEquation('', 0, '');\n}\n\nView.prototype.UpdateTotal = function(accumulator) {\n  $(this.lastDisplayElement).children('.accumulator').text(accumulator);\n}\n\nView.prototype.AddDisplayEquation = function(operator, operand, accumulator) {\n  this.displayElement.append(\n      '<div class=\"equation\">'\n      + '<div class=\"operand\">' + operand + '</div>'\n      + '<div class=\"operator\">' + operator + '</div>'\n      + '<div class=\"accumulator\">' + accumulator + '</div'\n      + '</div>');\n  this.lastDisplayElement = $('.equation').last();\n  this.displayElement.scrollTop(this.displayElement[0].scrollHeight);\n}\n\nView.prototype.UpdateDisplayEquation = function(operator, operand, accumulator) {\n  $(this.lastDisplayElement).children('.operator').text(operator);\n  $(this.lastDisplayElement).children('.operand').text(operand);\n  $(this.lastDisplayElement).children('.accumulator').text(accumulator);\n  this.displayElement.scrollTop(this.displayElement[0].scrollHeight);\n}\n"
  },
  {
    "path": "_archive/apps/samples/camera-capture/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ilefapmpngkdnnllcnlcjffipbolhklf\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Camera Capture\n\nShows how to grab a camera feed using getUserMedia. Requires\nthe `videoCapture` permissions to be set in the manifest file.\n\n## APIs\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n* [videoCapture](https://developer.chrome.com/apps/declare_permissions)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/camera-capture/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/camera-capture/app.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Eric Bidelman (ericbidelman@chromium.org)\n*/\n\n/**\n * Grabs the camera feed from the browser, requesting\n * video from the selected device. Requires the permissions\n * for videoCapture to be set in the manifest.\n *\n * @see http://developer.chrome.com/apps/manifest#permissions\n */\n\nvar curStream = null; // keep track of current stream\n\nfunction getCamera() {\n  var cameraSrcId = document.querySelector('select').value;\n\n  // constraints allow us to select a specific video source \n  var constraints = {\n    video: {\n      optional: [{\n        sourceId: cameraSrcId\n      }]\n    },\n    audio:false\n  }\n\n  navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia\n\n  navigator.getUserMedia(constraints, function(stream) {\n    var videoElm = document.querySelector('video');\n    videoElm.src = URL.createObjectURL(stream);\n\n    stream.onended = function() {\n      updateButtonState();\n    }\n\n    videoElm.onplay = function() {\n      if(curStream !== null) {\n        // stop previous stream\n        curStream.stop();\n      }\n\n      curStream = stream;\n      updateButtonState();  \n    }\n  }, function(e) {\n    curStream = null;\n    console.error(e);\n  });\n}\n\n/**\n * Click handler to init the camera grab\n */\ndocument.querySelector('button').addEventListener('click', function(e) {\n  // camera is active, stop stream\n  if(curStream && curStream.active) {\n    curStream.stop();\n    document.querySelector('video').src = \"\";\n  }\n  else {\n    getCamera();\n  }\n\n});\n\n/**\n * Change stream source according to dropdown selection\n */\ndocument.querySelector('select').addEventListener('change',function() {\n  if(curStream && curStream.active) {\n    getCamera();\n  }\n});\n\n/**\n * Updates button state according to Camera stream status\n */\n\nfunction updateButtonState() {\n  var btn = document.querySelector('button');\n  btn.disabled = false;\n\n  if((!curStream) || (!curStream.active)) {\n    btn.innerHTML = \"Enable Camera\";\n  }\n  else {\n    btn.innerHTML = \"Disable Camera\"; \n  }\n}\n\n/**\n * Populate camera sources drop down\n */\n\ngetVideoSources(function(cameras){\n  var ddl = document.querySelector('select');\n  if(cameras.length == 1) {\n    // if only 1 camera is found drop down can be disabled\n    ddl.disabled = true;\n  }\n\n  cameras.forEach(function(camera){\n    var opt = document.createElement('option');\n    opt.value = camera.id;\n    opt.appendChild(document.createTextNode(camera.label));\n\n    ddl.appendChild(opt);\n  });   \n}); \n\n/**\n * This retrieves video sources and passes them to callback parameter\n */\n\nfunction getVideoSources(callback) {\n  var videoSources = [];\n  callback = callback || function(){};\n\n  MediaStreamTrack.getSources(function(sources){\n    sources.forEach(function(source,index){\n      if(source.kind === 'video') {\n        // we only need to enlist video sources\n        videoSources.push({\n          id: source.id,\n          label: source.label || 'Camera '+(videoSources.length+1)\n        });  \n      }\n    });\n\n    callback(videoSources);\n  });\n}\n"
  },
  {
    "path": "_archive/apps/samples/camera-capture/background.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n  \tid: \"camCaptureID\",\n    innerBounds: {\n      width: 700,\n      height: 600\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/camera-capture/index.html",
    "content": "<html>\n<head>\n<style>\n  body {\n    background: white;\n    display: -webkit-flex;\n    -webkit-justify-content: center;\n    -webkit-align-items: center;\n    -webkit-flex-direction: column;\n  }\n  video {\n    width: 640px;\n    height: 480px;\n    background: white;\n  }\n\n  button,select {\n    display: inline-block;\n    background: -webkit-linear-gradient(#F9F9F9 40%, #E3E3E3 70%);\n    background: linear-gradient(#F9F9F9 40%, #E3E3E3 70%);\n    border: 1px solid #999;\n    -webkit-border-radius: 3px;\n    border-radius: 3px;\n    padding: 5px 8px;\n    outline: none;\n    white-space: nowrap;\n    -webkit-user-select: none;\n    user-select: none;\n    cursor: pointer;\n    text-shadow: 1px 1px #fff;\n    font-weight: 700;\n    font-size: 10pt;\n    margin:0px 5px;\n    max-width:200px;\n  }\n  button:hover,\n  button.active {\n    border-color: black;\n  }\n  button:active,\n  button.active {\n    background: -webkit-linear-gradient(#E3E3E3 40%, #F9F9F9 70%);\n    background: linear-gradient(#E3E3E3 40%, #F9F9F9 70%);\n  }\n\n  video {\n    object-fit: none;\n    border: 1px solid #e2e2e2;\n    box-shadow: 0 1px 1px rgba(0,0,0,0.2);\n  }\n</style>\n</head>\n<body>\n  <video autoplay poster=\"camera.png\"></video>\n  <p>\n    <button>Enable Camera</button>\n    <select></select>\n  </p>\n<script src=\"app.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/camera-capture/manifest.json",
    "content": "{\n  \"name\": \"Camera Capture Sample\",\n  \"version\": \"2.2\",\n  \"manifest_version\": 2,\n  \"icons\": {\n    \"16\": \"camera.png\",\n    \"128\": \"camera.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [\n    \"videoCapture\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/clock/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/lhfiglpmnendbchimlikaeachppfonmm\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Clock\n\nA widget-like application that provides a world clock, an alarm, a timer and a stopwatch.\n\n## APIs\n\n* [Sync Storage API](http://developer.chrome.com/apps/storage)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/clock/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/clock/alarm.js",
    "content": "Alarm = function(id, name, hour, minute, on) {\n\tthis.id = id;\n\tthis.name = name;\n\tthis.hour = hour;\n\tthis.minute = minute;\n\tthis.on = on;\n\tthis.displayed = false;\n\n\tthis.alarm_time = new Date();\n\tthis.alarm_time.setHours(hour);\n\tthis.alarm_time.setMinutes(minute);\n}\n\n//Alarm inherits from Clock\nAlarm.prototype = new Clock(this.id, 0);\n\n//Method to initialize the alarm\nAlarm.prototype.create = function() {\n\tthis.canvas = $('.alarm .' + this.id + ' .clock')[0];\n\tthis.canvas.height = this.config.container.height;\n\tthis.canvas.width = this.config.container.width;\n\n\tthis.context = this.canvas.getContext(\"2d\");\n\n\tthis.startTick();\n}\n\n//Method to update the alarm\nAlarm.prototype.update = function(name, hour, minute) {\n\tthis.name = name;\n\tthis.hour = hour;\n\tthis.minute = minute;\n\tthis.drawClock(this.hour, this.minute, 0);\n \tthis.displayTime(this.hour, this.minute, false);\n}\n\n//Method to draw the number\nAlarm.prototype.drawText = function(hour, minute, second) {\n\tfor (var i = 0; i < 12; i++) {\n\t\tthis.context.save();\n\t\tthis.context.translate(this.config.container.width/2, this.config.container.height/2);\n\t\tthis.context.rotate(Math.PI * (2.0 * (i/12) - 0.5));\n\t\tthis.context.translate(this.config.face.radius - 24, 0);\n\t\tthis.context.rotate((Math.PI * (2.0 * (i/12) - 0.5) * -1));\n\n\t\tvar alpha = this.config.unit.major.alpha;\n\n\t\tif (i === 0)\n\t\t\tvar textValue = 12;\n\t\telse\n\t\t\tvar textValue = i;\n\n\t\tthis.context.globalAlpha = alpha;\n\n\t\tthis.context.fillStyle = this.config.unit.major.color;\n\t\tthis.context.shadowOffsetX = 1;\n\t\tthis.context.shadowOffsetY = 1;\n\t\tthis.context.shadowColor = \"rgba(0, 0, 0, 0.8)\";\n\t\tthis.context.font = \"500 13px 'Open Sans'\";\n\t\tthis.context.textBaseline = 'middle';\n\t\tthis.context.textAlign = \"center\";\n\n\t\tthis.context.fillText(textValue, 0, 0);\n\t\tthis.context.restore();\n\t}\n}\n\n//Method to fire each second and redraw the clock\nAlarm.prototype.tick = function() {\n \tthis.drawClock(this.hour, this.minute, 0);\n \tthis.displayTime(this.hour, this.minute, false);\n \tvar now = new Date();\n \tif (this.on && now.getHours() == this.hour && now.getMinutes() == this.minute && !this.displayed) {\n \t\tnew Notification(name, {\n \t\t\ticon: 'img/alarm.png'\t\n \t\t});\n \t\t\n \t\tthis.displayed = true;\n \t} else {\n \t\tthis.displayed = false;\n \t}\n}\n\nAlarm.prototype.toggleState = function() {\n\tthis.on = !this.on;\n\treturn this.on;\n}\n"
  },
  {
    "path": "_archive/apps/samples/clock/clock.js",
    "content": "Clock = function(id, offset) {\n\n\tthis.config = {\n\t\tcontainer: {height: 240, width: 240},\n\t\tface: {color: '#424240', alpha: 1, radius: 120},\n\t\thourHand: {color: '#4d90fe', alpha: 1, length: 70, width: 4},\n\t\tminuteHand: {color: '#4d90fe', alpha: 1, length: 90, width: 4},\n\t\tunit: {\n\t\t\tmajor: {color: '#f5f5f5', alpha: 0.4, length: 8, width: 6},\n\t\t\tmid: {color: '#f5f5f5', alpha: 0.4, length: 8, width: 4},\n\t\t\tminor: {color: '#f5f5f5', alpha: 0.4, length: 8, width: 2}\n\t\t}\n\t};\n\tthis.tickId;\n\tthis.offset = offset;\n\tthis.id = id;\n}\n\n//Method to initialize the clock\nClock.prototype.create = function(ctx) {\n\n\tif (ctx) {\n\t\tthis.context = ctx;\n\t}\n\telse {\n\t\tthis.canvas = $('.world .' + this.id + ' .clock')[0];\n\t\tthis.canvas.height = this.config.container.height;\n\t\tthis.canvas.width = this.config.container.width;\n\t\tthis.context = this.canvas.getContext(\"2d\");\n\t}\n\n\tthis.startTick();\n}\n\n//Methods to draw the clock\nClock.prototype.drawClock = function (hour, minute, second) {\n\tthis.context.clearRect(0, 0, this.config.container.width, this.config.container.height);\n\n\tthis.drawface();\n\tthis.drawUnits();\n\tthis.innerShadow();\n\tthis.drawText(hour, minute, second);\n\tthis.drawHands(hour, minute, second);\n}\n\n//Method to draw the clocks face\nClock.prototype.drawface = function () {\n\tthis.context.save();\n\n\tthis.context.shadowOffsetX = 0;\n\tthis.context.shadowOffsetY = 1;\n\tthis.context.shadowBlur = 1;\n\tthis.context.shadowColor = \"rgba(255, 255, 255, 1)\";\n\n\tthis.context.beginPath();\n\tthis.context.arc(this.config.container.width/2, this.config.container.height/2, this.config.face.radius, 0, Math.PI*2, false);\n\tthis.context.closePath();\n\tthis.context.fillStyle = this.config.face.color;\n\tthis.context.fill();\n\tthis.context.restore();\n}\n\n//Method to draw an inner shadow on the clock face\nClock.prototype.innerShadow = function() {\n\tthis.context.save();\n\n\tthis.context.strokeStyle = \"rgba(0, 0, 0, 0.3)\";\n\tthis.context.shadowOffsetX = 0;\n\tthis.context.shadowOffsetY = 1;\n\tthis.context.shadowBlur = 1;\n\tthis.context.shadowColor = \"rgba(0, 0, 0, 0.3)\";\n\n\tthis.context.beginPath();\n\tthis.context.arc(this.config.container.width/2, this.config.container.height/2, this.config.face.radius, Math.PI, 0);\n\tthis.context.stroke();\n\tthis.context.restore();\n}\n\n\n//Method to draw the hands\nClock.prototype.drawHands = function(hour, minute, second) {\n\tthis.context.save();\n\n\tthis.context.translate(this.config.container.width/2, this.config.container.height/2);\n\tthis.context.rotate(Math.PI * (2.0 * (((hour%12)*5 + minute/12.0)/60) - 0.5));\n\tthis.context.globalAlpha = this.config.hourHand.alpha;\n\tthis.context.strokeStyle = this.config.hourHand.color;\n\tthis.context.lineWidth = this.config.hourHand.width;\n\tthis.context.lineCap = \"round\";\n\tthis.context.shadowOffsetX = 0;\n\tthis.context.shadowOffsetY = 4;\n\tthis.context.shadowBlur = 2;\n\tthis.context.shadowColor = \"rgba(0, 0, 0, 0.2)\";\n\n\tthis.context.beginPath();\n\tthis.context.moveTo(-8, 0);\n\tthis.context.lineTo(this.config.hourHand.length - 5, 0);\n\tthis.context.closePath();\n\n\tthis.context.stroke();\n\n\tthis.context.restore();\n\n\n\tthis.context.save();\n\n\tthis.context.translate(this.config.container.width/2,this.config.container.height/2);\n\tthis.context.rotate(Math.PI * (2.0 * ((minute + (second/60.0))/60) - 0.5));\n\tthis.context.globalAlpha = this.config.minuteHand.alpha;\n\tthis.context.strokeStyle = this.config.minuteHand.color;\n\tthis.context.lineWidth = this.config.minuteHand.width;\n\tthis.context.lineCap = \"round\";\n\tthis.context.shadowOffsetX = 0;\n\tthis.context.shadowOffsetY = 4;\n\tthis.context.shadowBlur = 2;\n\tthis.context.shadowColor = \"rgba(0, 0, 0, 0.2)\";\n\n\tthis.context.beginPath();\n\tthis.context.moveTo(-8, 0);\n\tthis.context.lineTo(this.config.minuteHand.length - 5, 0);\n\tthis.context.closePath();\n\n\tthis.context.stroke();\n\n\tthis.context.restore();\n\n\tthis.context.save();\n\tthis.context.beginPath();\n\tthis.context.arc(this.config.container.width/2, this.config.container.height/2, 4, 0, Math.PI*2, false);\n\tthis.context.closePath();\n\tthis.context.fillStyle = this.config.minuteHand.color;\n\tthis.context.fill();\n\tthis.context.restore();\n\n\tthis.context.save();\n\tthis.context.beginPath();\n\tthis.context.arc(this.config.container.width/2, this.config.container.height/2, 1, 0, Math.PI*2, false);\n\tthis.context.closePath();\n\tthis.context.fillStyle = this.config.unit.major.color;\n\tthis.context.fill();\n\tthis.context.restore();\n}\n\n//Method to draw the number\nClock.prototype.drawText = function(hour, minute, second) {\n\tfor (var i = 0; i < 12; i++) {\n\t\tthis.context.save();\n\t\tthis.context.translate(this.config.container.width/2, this.config.container.height/2);\n\t\tthis.context.rotate(Math.PI * (2.0 * (i/12) - 0.5));\n\t\tthis.context.translate(this.config.face.radius - 24, 0);\n\t\tthis.context.rotate((Math.PI * (2.0 * (i/12) - 0.5) * -1));\n\n\t\tvar alpha = this.config.unit.major.alpha;\n\n\t\tif (i === 0) j = 11;\n\t\telse j = i - 1;\n\t\tvar textValue = '';\n\t\tif ((hour % 12) === i) {\n\t\t\talpha += (1-this.config.unit.major.alpha);\n\t\t\tif (i === 0) textValue = 12;\n\t\t\telse textValue = i;\n\t\t}\n\n\t\tthis.context.globalAlpha = alpha;\n\n\t\tthis.context.fillStyle = this.config.unit.major.color;\n\t\tthis.context.shadowOffsetX = 1;\n\t\tthis.context.shadowOffsetY = 1;\n\t\tthis.context.shadowColor = \"rgba(0, 0, 0, 0.8)\";\n\t\tthis.context.font = \"500 13px 'Open Sans'\";\n\t\tthis.context.textBaseline = 'middle';\n\t\tthis.context.textAlign = \"center\";\n\n\t\tthis.context.fillText(textValue, 0, 0);\n\t\tthis.context.restore();\n\t}\n}\n\n//Method to draw the units\nClock.prototype.drawUnits = function() {\n\tfor (var i = 0; i < 60; i++) {\n\t\tthis.context.save();\n\t\tthis.context.translate(this.config.container.width/2, this.config.container.height/2);\n\t\tthis.context.rotate(Math.PI * (2.0 * (i/60) - 0.5));\n\t\tthis.context.globalAlpha = this.config.unit.major.alpha;\n\t\tthis.context.strokeStyle = this.config.unit.major.color;\n\n\t\tif (i  % 5 === 0) {\n\t\t\tif (i % 15 === 0) {\n\t\t\t\tthis.context.lineWidth = this.config.unit.major.width;\n\t\t\t\tvar length = this.config.unit.major.length;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.context.lineWidth = this.config.unit.mid.width;\n\t\t\t\tvar length = this.config.unit.mid.length;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthis.context.lineWidth = this.config.unit.minor.width;\n\t\t\tvar length = this.config.unit.minor.length;\n\t\t}\n\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(this.config.face.radius - length, 0);\n\t\tthis.context.lineTo(this.config.face.radius, 0);\n\t\tthis.context.closePath();\n\t\tthis.context.stroke();\n\t\tthis.context.restore();\n\t}\n}\n\nClock.prototype.displayTime = function(hours, minutes, displayDay) {\n \tvar day = ' &bull; Today';\n  var noon = ' AM';\n\n  if (minutes < 0) {\n  \tminutes += 60;\n  \thours -= 1;\n  } else if (minutes > 59) {\n  \tminutes -= 60;\n  \thours += 1;\n  }\n  if (minutes < 10) minutes = '0' + minutes;\n\n  if (hours < 0) {\n  \tday = ' &bull; Yesterday';\n  \thours += 24;\n  } else if (hours >= 24) {\n  \tday = ' &bull; Tomorrow';\n  \thours -= 24;\n  }\n\n  if (hours >= 12) noon = ' PM';\n  if (hours > 12) hours -= 12;\n  if (hours == 0) hours = 12;\n\n  var time = hours + ':' + minutes + noon;\n\n  $('.' + this.id + ' .time').html(time);\n  if (displayDay) $('.' + this.id + ' .day').html(day);\n}\n\n//Method to fire each second and redraw the clock\nClock.prototype.tick = function() {\n\tvar str_offset = (this.offset + '').split('.');\n\tvar hours_offset = parseInt(str_offset[0]);\n\tvar minutes_offset = 0;\n\tif (str_offset.length > 1) minutes_offset = parseInt(str_offset[1]);\n\n  var now = new Date();\n  var hours = now.getHours() + hours_offset;\n  var minutes = now.getMinutes() + minutes_offset;\n  var seconds = now.getSeconds();\n\n \tthis.drawClock(hours, minutes, seconds);\n\n \tthis.displayTime(hours, minutes, true);\n}\n\nClock.prototype.startTick = function() {\n\tvar inst = this;\n\tthis.tickId = setInterval(function() { inst.tick(); }, 1000);\n}\n\nClock.prototype.stopTick = function() {\n\tclearInterval(tickId);\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "_archive/apps/samples/clock/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<title>World Clock</title>\n\n\t\t<link href=\"style.css\" rel=\"stylesheet\" type=\"text/css\">\n\n    <script type=\"text/javascript\" src=\"lib/jquery-1.7.2.min.js\"></script>\n \t\t<script type=\"text/javascript\" src=\"lib/tipTipv13/jquery.tipTip.minified.js\"></script>\n\n    <script src=\"clock.js\" type=\"text/javascript\"></script>\n    <script src=\"alarm.js\" type=\"text/javascript\"></script>\n    <script src=\"timer.js\" type=\"text/javascript\"></script>\n    <script src=\"stopwatch.js\" type=\"text/javascript\"></script>\n    <script src=\"script.js\" type=\"text/javascript\"></script>\n\t</head>\n\n\t<body>\n\t\t<div class=\"close\"></div>\n\n\t\t<div id='container'>\n\t\t\t<div class=\"world selected\">\n\t\t\t\t<div class=\"new hidden\">\n\t\t\t\t\t<canvas class=\"clock\"></canvas>\n\t\t\t\t\t<div class=\"new-input\">\n\t\t\t\t\t\t<input type=\"text\" id=\"new-city\" /><br>\n\t\t\t\t\t\t<div class=\"error-message hidden\"></div>\n\t\t\t\t\t\t<div class=\"button add\">Add</div>\n\t\t\t\t\t\t<div class=\"button cancel\">Cancel</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"alarm hidden\">\n\t\t\t\t<div class=\"new hidden\">\n\t\t\t\t\t<canvas class=\"clock\"></canvas>\n\t\t\t\t\t<div class=\"new-input\">\n\t\t\t\t\t\t<input type=\"text\" id=\"new-alarm-name\" /><br>\n\t\t\t\t\t\t<input type=\"text\" id=\"new-alarm-hour\" maxlength=\"2\" />\n\t\t\t\t\t\t<input type=\"text\" id=\"new-alarm-minute\" maxlength=\"2\" />\n\t\t\t\t\t\t<input type=\"text\" id=\"new-alarm-noon\" maxlength=\"2\" /><br>\n\t\t\t\t\t\t<div class=\"button add\">Add</div>\n\t\t\t\t\t\t<div class=\"button cancel\">Cancel</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"timer hidden\">\n\t\t\t\t<div class=\"timer-clock\">\n\t\t\t\t\t<canvas class=\"clock\"></canvas>\n\t\t\t\t\t<input type=\"text\" id=\"timer-minute\" maxlength=\"2\" />\n\t\t\t\t\t<input type=\"text\" id=\"timer-second\" maxlength=\"2\" />\n\t\t\t\t\t<br>\n\t\t\t\t\t<div class=\"button start disabled\">START</div>\n\t\t\t\t\t<div class=\"button stop hidden\">STOP</div>\n\t\t\t\t\t<div class=\"button reset\">RESET</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"stopwatch hidden\">\n\t\t\t\t<div class=\"stopwatch-clock\">\n\t\t\t\t\t<canvas class=\"clock\"></canvas>\n\t\t\t\t\t<div class=\"button start\">START</div>\n\t\t\t\t\t<div class=\"button stop hidden\">STOP</div>\n\t\t\t\t\t<div class=\"button reset\">RESET</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t\t<div id='menu'>\n\t\t\t<div class='menu-item world selected' title=\"WORLD\"></div>\n\t\t\t<div class='menu-item new-world button'>ADD</div>\n\t\t\t<div class='menu-item alarm' title=\"ALARM\"></div>\n\t\t\t<div class='menu-item new-alarm button hidden'>ADD</div>\n\t\t\t<div class='menu-item timer' title=\"TIMER\"></div>\n\t\t\t<div class='menu-item stopwatch' title=\"STOPWATCH\"></div>\n\t\t</div>\n\t</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/clock/lib/tipTipv13/jquery.tipTip.js",
    "content": " /*\n * TipTip\n * Copyright 2010 Drew Wilson\n * www.drewwilson.com\n * code.drewwilson.com/entry/tiptip-jquery-plugin\n *\n * Version 1.3   -   Updated: Mar. 23, 2010\n *\n * This Plug-In will create a custom tooltip to replace the default\n * browser tooltip. It is extremely lightweight and very smart in\n * that it detects the edges of the browser window and will make sure\n * the tooltip stays within the current window size. As a result the\n * tooltip will adjust itself to be displayed above, below, to the left \n * or to the right depending on what is necessary to stay within the\n * browser window. It is completely customizable as well via CSS.\n *\n * This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:\n *   http://www.opensource.org/licenses/mit-license.php\n *   http://www.gnu.org/licenses/gpl.html\n */\n\n(function($){\n\t$.fn.tipTip = function(options) {\n\t\tvar defaults = { \n\t\t\tactivation: \"hover\",\n\t\t\tkeepAlive: false,\n\t\t\tmaxWidth: \"200px\",\n\t\t\tedgeOffset: 3,\n\t\t\tdefaultPosition: \"bottom\",\n\t\t\tdelay: 400,\n\t\t\tfadeIn: 200,\n\t\t\tfadeOut: 200,\n\t\t\tattribute: \"title\",\n\t\t\tcontent: false, // HTML or String to fill TipTIp with\n\t\t  \tenter: function(){},\n\t\t  \texit: function(){}\n\t  \t};\n\t \tvar opts = $.extend(defaults, options);\n\t \t\n\t \t// Setup tip tip elements and render them to the DOM\n\t \tif($(\"#tiptip_holder\").length <= 0){\n\t \t\tvar tiptip_holder = $('<div id=\"tiptip_holder\" style=\"max-width:'+ opts.maxWidth +';\"></div>');\n\t\t\tvar tiptip_content = $('<div id=\"tiptip_content\"></div>');\n\t\t\tvar tiptip_arrow = $('<div id=\"tiptip_arrow\"></div>');\n\t\t\t$(\"body\").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id=\"tiptip_arrow_inner\"></div>')));\n\t\t} else {\n\t\t\tvar tiptip_holder = $(\"#tiptip_holder\");\n\t\t\tvar tiptip_content = $(\"#tiptip_content\");\n\t\t\tvar tiptip_arrow = $(\"#tiptip_arrow\");\n\t\t}\n\t\t\n\t\treturn this.each(function(){\n\t\t\tvar org_elem = $(this);\n\t\t\tif(opts.content){\n\t\t\t\tvar org_title = opts.content;\n\t\t\t} else {\n\t\t\t\tvar org_title = org_elem.attr(opts.attribute);\n\t\t\t}\n\t\t\tif(org_title != \"\"){\n\t\t\t\tif(!opts.content){\n\t\t\t\t\torg_elem.removeAttr(opts.attribute); //remove original Attribute\n\t\t\t\t}\n\t\t\t\tvar timeout = false;\n\t\t\t\t\n\t\t\t\tif(opts.activation == \"hover\"){\n\t\t\t\t\torg_elem.hover(function(){\n\t\t\t\t\t\tactive_tiptip();\n\t\t\t\t\t}, function(){\n\t\t\t\t\t\tif(!opts.keepAlive){\n\t\t\t\t\t\t\tdeactive_tiptip();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tif(opts.keepAlive){\n\t\t\t\t\t\ttiptip_holder.hover(function(){}, function(){\n\t\t\t\t\t\t\tdeactive_tiptip();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else if(opts.activation == \"focus\"){\n\t\t\t\t\torg_elem.focus(function(){\n\t\t\t\t\t\tactive_tiptip();\n\t\t\t\t\t}).blur(function(){\n\t\t\t\t\t\tdeactive_tiptip();\n\t\t\t\t\t});\n\t\t\t\t} else if(opts.activation == \"click\"){\n\t\t\t\t\torg_elem.click(function(){\n\t\t\t\t\t\tactive_tiptip();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}).hover(function(){},function(){\n\t\t\t\t\t\tif(!opts.keepAlive){\n\t\t\t\t\t\t\tdeactive_tiptip();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tif(opts.keepAlive){\n\t\t\t\t\t\ttiptip_holder.hover(function(){}, function(){\n\t\t\t\t\t\t\tdeactive_tiptip();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\n\t\t\t\tfunction active_tiptip(){\n\t\t\t\t\topts.enter.call(this);\n\t\t\t\t\ttiptip_content.html(org_title);\n\t\t\t\t\ttiptip_holder.hide().removeAttr(\"class\").css(\"margin\",\"0\");\n\t\t\t\t\ttiptip_arrow.removeAttr(\"style\");\n\t\t\t\t\t\n\t\t\t\t\tvar top = parseInt(org_elem.offset()['top']);\n\t\t\t\t\tvar left = parseInt(org_elem.offset()['left']);\n\t\t\t\t\tvar org_width = parseInt(org_elem.outerWidth());\n\t\t\t\t\tvar org_height = parseInt(org_elem.outerHeight());\n\t\t\t\t\tvar tip_w = tiptip_holder.outerWidth();\n\t\t\t\t\tvar tip_h = tiptip_holder.outerHeight();\n\t\t\t\t\tvar w_compare = Math.round((org_width - tip_w) / 2);\n\t\t\t\t\tvar h_compare = Math.round((org_height - tip_h) / 2);\n\t\t\t\t\tvar marg_left = Math.round(left + w_compare);\n\t\t\t\t\tvar marg_top = Math.round(top + org_height + opts.edgeOffset);\n\t\t\t\t\tvar t_class = \"\";\n\t\t\t\t\tvar arrow_top = \"\";\n\t\t\t\t\tvar arrow_left = Math.round(tip_w - 12) / 2;\n\n                    if(opts.defaultPosition == \"bottom\"){\n                    \tt_class = \"_bottom\";\n                   \t} else if(opts.defaultPosition == \"top\"){ \n                   \t\tt_class = \"_top\";\n                   \t} else if(opts.defaultPosition == \"left\"){\n                   \t\tt_class = \"_left\";\n                   \t} else if(opts.defaultPosition == \"right\"){\n                   \t\tt_class = \"_right\";\n                   \t}\n\t\t\t\t\t\n\t\t\t\t\tvar right_compare = (w_compare + left) < parseInt($(window).scrollLeft());\n\t\t\t\t\tvar left_compare = (tip_w + left) > parseInt($(window).width());\n\t\t\t\t\t\n\t\t\t\t\tif((right_compare && w_compare < 0) || (t_class == \"_right\" && !left_compare) || (t_class == \"_left\" && left < (tip_w + opts.edgeOffset + 5))){\n\t\t\t\t\t\tt_class = \"_right\";\n\t\t\t\t\t\tarrow_top = Math.round(tip_h - 13) / 2;\n\t\t\t\t\t\tarrow_left = -12;\n\t\t\t\t\t\tmarg_left = Math.round(left + org_width + opts.edgeOffset);\n\t\t\t\t\t\tmarg_top = Math.round(top + h_compare);\n\t\t\t\t\t} else if((left_compare && w_compare < 0) || (t_class == \"_left\" && !right_compare)){\n\t\t\t\t\t\tt_class = \"_left\";\n\t\t\t\t\t\tarrow_top = Math.round(tip_h - 13) / 2;\n\t\t\t\t\t\tarrow_left =  Math.round(tip_w);\n\t\t\t\t\t\tmarg_left = Math.round(left - (tip_w + opts.edgeOffset + 5));\n\t\t\t\t\t\tmarg_top = Math.round(top + h_compare);\n\t\t\t\t\t}\n\n\t\t\t\t\tvar top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop());\n\t\t\t\t\tvar bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0;\n\t\t\t\t\t\n\t\t\t\t\tif(top_compare || (t_class == \"_bottom\" && top_compare) || (t_class == \"_top\" && !bottom_compare)){\n\t\t\t\t\t\tif(t_class == \"_top\" || t_class == \"_bottom\"){\n\t\t\t\t\t\t\tt_class = \"_top\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt_class = t_class+\"_top\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tarrow_top = tip_h;\n\t\t\t\t\t\tmarg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset));\n\t\t\t\t\t} else if(bottom_compare | (t_class == \"_top\" && bottom_compare) || (t_class == \"_bottom\" && !top_compare)){\n\t\t\t\t\t\tif(t_class == \"_top\" || t_class == \"_bottom\"){\n\t\t\t\t\t\t\tt_class = \"_bottom\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt_class = t_class+\"_bottom\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tarrow_top = -12;\t\t\t\t\t\t\n\t\t\t\t\t\tmarg_top = Math.round(top + org_height + opts.edgeOffset);\n\t\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\tif(t_class == \"_right_top\" || t_class == \"_left_top\"){\n\t\t\t\t\t\tmarg_top = marg_top + 5;\n\t\t\t\t\t} else if(t_class == \"_right_bottom\" || t_class == \"_left_bottom\"){\t\t\n\t\t\t\t\t\tmarg_top = marg_top - 5;\n\t\t\t\t\t}\n\t\t\t\t\tif(t_class == \"_left_top\" || t_class == \"_left_bottom\"){\t\n\t\t\t\t\t\tmarg_left = marg_left + 5;\n\t\t\t\t\t}\n\t\t\t\t\ttiptip_arrow.css({\"margin-left\": arrow_left+\"px\", \"margin-top\": arrow_top+\"px\"});\n\t\t\t\t\ttiptip_holder.css({\"margin-left\": marg_left+\"px\", \"margin-top\": marg_top+\"px\"}).attr(\"class\",\"tip\"+t_class);\n\t\t\t\t\t\n\t\t\t\t\tif (timeout){ clearTimeout(timeout); }\n\t\t\t\t\ttimeout = setTimeout(function(){ tiptip_holder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay);\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tfunction deactive_tiptip(){\n\t\t\t\t\topts.exit.call(this);\n\t\t\t\t\tif (timeout){ clearTimeout(timeout); }\n\t\t\t\t\ttiptip_holder.fadeOut(opts.fadeOut);\n\t\t\t\t}\n\t\t\t}\t\t\t\t\n\t\t});\n\t}\n})(jQuery);  \t"
  },
  {
    "path": "_archive/apps/samples/clock/lib/tipTipv13/jquery.tipTip.minified.js",
    "content": " /*\n * TipTip\n * Copyright 2010 Drew Wilson\n * www.drewwilson.com\n * code.drewwilson.com/entry/tiptip-jquery-plugin\n *\n * Version 1.3   -   Updated: Mar. 23, 2010\n *\n * This Plug-In will create a custom tooltip to replace the default\n * browser tooltip. It is extremely lightweight and very smart in\n * that it detects the edges of the browser window and will make sure\n * the tooltip stays within the current window size. As a result the\n * tooltip will adjust itself to be displayed above, below, to the left \n * or to the right depending on what is necessary to stay within the\n * browser window. It is completely customizable as well via CSS.\n *\n * This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:\n *   http://www.opensource.org/licenses/mit-license.php\n *   http://www.gnu.org/licenses/gpl.html\n */\n(function($){$.fn.tipTip=function(options){var defaults={activation:\"hover\",keepAlive:false,maxWidth:\"200px\",edgeOffset:3,defaultPosition:\"bottom\",delay:400,fadeIn:200,fadeOut:200,attribute:\"title\",content:false,enter:function(){},exit:function(){}};var opts=$.extend(defaults,options);if($(\"#tiptip_holder\").length<=0){var tiptip_holder=$('<div id=\"tiptip_holder\" style=\"max-width:'+opts.maxWidth+';\"></div>');var tiptip_content=$('<div id=\"tiptip_content\"></div>');var tiptip_arrow=$('<div id=\"tiptip_arrow\"></div>');$(\"body\").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id=\"tiptip_arrow_inner\"></div>')))}else{var tiptip_holder=$(\"#tiptip_holder\");var tiptip_content=$(\"#tiptip_content\");var tiptip_arrow=$(\"#tiptip_arrow\")}return this.each(function(){var org_elem=$(this);if(opts.content){var org_title=opts.content}else{var org_title=org_elem.attr(opts.attribute)}if(org_title!=\"\"){if(!opts.content){org_elem.removeAttr(opts.attribute)}var timeout=false;if(opts.activation==\"hover\"){org_elem.hover(function(){active_tiptip()},function(){if(!opts.keepAlive){deactive_tiptip()}});if(opts.keepAlive){tiptip_holder.hover(function(){},function(){deactive_tiptip()})}}else if(opts.activation==\"focus\"){org_elem.focus(function(){active_tiptip()}).blur(function(){deactive_tiptip()})}else if(opts.activation==\"click\"){org_elem.click(function(){active_tiptip();return false}).hover(function(){},function(){if(!opts.keepAlive){deactive_tiptip()}});if(opts.keepAlive){tiptip_holder.hover(function(){},function(){deactive_tiptip()})}}function active_tiptip(){opts.enter.call(this);tiptip_content.html(org_title);tiptip_holder.hide().removeAttr(\"class\").css(\"margin\",\"0\");tiptip_arrow.removeAttr(\"style\");var top=parseInt(org_elem.offset()['top']);var left=parseInt(org_elem.offset()['left']);var org_width=parseInt(org_elem.outerWidth());var org_height=parseInt(org_elem.outerHeight());var tip_w=tiptip_holder.outerWidth();var tip_h=tiptip_holder.outerHeight();var w_compare=Math.round((org_width-tip_w)/2);var h_compare=Math.round((org_height-tip_h)/2);var marg_left=Math.round(left+w_compare);var marg_top=Math.round(top+org_height+opts.edgeOffset);var t_class=\"\";var arrow_top=\"\";var arrow_left=Math.round(tip_w-12)/2;if(opts.defaultPosition==\"bottom\"){t_class=\"_bottom\"}else if(opts.defaultPosition==\"top\"){t_class=\"_top\"}else if(opts.defaultPosition==\"left\"){t_class=\"_left\"}else if(opts.defaultPosition==\"right\"){t_class=\"_right\"}var right_compare=(w_compare+left)<parseInt($(window).scrollLeft());var left_compare=(tip_w+left)>parseInt($(window).width());if((right_compare&&w_compare<0)||(t_class==\"_right\"&&!left_compare)||(t_class==\"_left\"&&left<(tip_w+opts.edgeOffset+5))){t_class=\"_right\";arrow_top=Math.round(tip_h-13)/2;arrow_left=-12;marg_left=Math.round(left+org_width+opts.edgeOffset);marg_top=Math.round(top+h_compare)}else if((left_compare&&w_compare<0)||(t_class==\"_left\"&&!right_compare)){t_class=\"_left\";arrow_top=Math.round(tip_h-13)/2;arrow_left=Math.round(tip_w);marg_left=Math.round(left-(tip_w+opts.edgeOffset+5));marg_top=Math.round(top+h_compare)}var top_compare=(top+org_height+opts.edgeOffset+tip_h+8)>parseInt($(window).height()+$(window).scrollTop());var bottom_compare=((top+org_height)-(opts.edgeOffset+tip_h+8))<0;if(top_compare||(t_class==\"_bottom\"&&top_compare)||(t_class==\"_top\"&&!bottom_compare)){if(t_class==\"_top\"||t_class==\"_bottom\"){t_class=\"_top\"}else{t_class=t_class+\"_top\"}arrow_top=tip_h;marg_top=Math.round(top-(tip_h+5+opts.edgeOffset))}else if(bottom_compare|(t_class==\"_top\"&&bottom_compare)||(t_class==\"_bottom\"&&!top_compare)){if(t_class==\"_top\"||t_class==\"_bottom\"){t_class=\"_bottom\"}else{t_class=t_class+\"_bottom\"}arrow_top=-12;marg_top=Math.round(top+org_height+opts.edgeOffset)}if(t_class==\"_right_top\"||t_class==\"_left_top\"){marg_top=marg_top+5}else if(t_class==\"_right_bottom\"||t_class==\"_left_bottom\"){marg_top=marg_top-5}if(t_class==\"_left_top\"||t_class==\"_left_bottom\"){marg_left=marg_left+5}tiptip_arrow.css({\"margin-left\":arrow_left+\"px\",\"margin-top\":arrow_top+\"px\"});tiptip_holder.css({\"margin-left\":marg_left+\"px\",\"margin-top\":marg_top+\"px\"}).attr(\"class\",\"tip\"+t_class);if(timeout){clearTimeout(timeout)}timeout=setTimeout(function(){tiptip_holder.stop(true,true).fadeIn(opts.fadeIn)},opts.delay)}function deactive_tiptip(){opts.exit.call(this);if(timeout){clearTimeout(timeout)}tiptip_holder.fadeOut(opts.fadeOut)}}})}})(jQuery);"
  },
  {
    "path": "_archive/apps/samples/clock/lib/tipTipv13/tipTip.css",
    "content": "/* TipTip CSS - Version 1.2 */\n\n#tiptip_holder {\n\tdisplay: none;\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tz-index: 99999;\n}\n\n#tiptip_holder.tip_top {\n\tpadding-bottom: 5px;\n}\n\n#tiptip_holder.tip_bottom {\n\tpadding-top: 5px;\n}\n\n#tiptip_holder.tip_right {\n\tpadding-left: 5px;\n}\n\n#tiptip_holder.tip_left {\n\tpadding-right: 5px;\n}\n\n#tiptip_content {\n\tfont-size: 11px;\n\tcolor: #fff;\n\ttext-shadow: 0 0 2px #000;\n\tpadding: 4px 8px;\n\tborder: 1px solid rgba(255,255,255,0.25);\n\tbackground-color: rgb(25,25,25);\n\tbackground-color: rgba(25,25,25,0.92);\n\tbackground-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(transparent), to(#000));\n\tborder-radius: 3px;\n\t-webkit-border-radius: 3px;\n\t-moz-border-radius: 3px;\n\tbox-shadow: 0 0 3px #555;\n\t-webkit-box-shadow: 0 0 3px #555;\n\t-moz-box-shadow: 0 0 3px #555;\n}\n\n#tiptip_arrow, #tiptip_arrow_inner {\n\tposition: absolute;\n\tborder-color: transparent;\n\tborder-style: solid;\n\tborder-width: 6px;\n\theight: 0;\n\twidth: 0;\n}\n\n#tiptip_holder.tip_top #tiptip_arrow {\n\tborder-top-color: #fff;\n\tborder-top-color: rgba(255,255,255,0.35);\n}\n\n#tiptip_holder.tip_bottom #tiptip_arrow {\n\tborder-bottom-color: #fff;\n\tborder-bottom-color: rgba(255,255,255,0.35);\n}\n\n#tiptip_holder.tip_right #tiptip_arrow {\n\tborder-right-color: #fff;\n\tborder-right-color: rgba(255,255,255,0.35);\n}\n\n#tiptip_holder.tip_left #tiptip_arrow {\n\tborder-left-color: #fff;\n\tborder-left-color: rgba(255,255,255,0.35);\n}\n\n#tiptip_holder.tip_top #tiptip_arrow_inner {\n\tmargin-top: -7px;\n\tmargin-left: -6px;\n\tborder-top-color: rgb(25,25,25);\n\tborder-top-color: rgba(25,25,25,0.92);\n}\n\n#tiptip_holder.tip_bottom #tiptip_arrow_inner {\n\tmargin-top: -5px;\n\tmargin-left: -6px;\n\tborder-bottom-color: rgb(25,25,25);\n\tborder-bottom-color: rgba(25,25,25,0.92);\n}\n\n#tiptip_holder.tip_right #tiptip_arrow_inner {\n\tmargin-top: -6px;\n\tmargin-left: -5px;\n\tborder-right-color: rgb(25,25,25);\n\tborder-right-color: rgba(25,25,25,0.92);\n}\n\n#tiptip_holder.tip_left #tiptip_arrow_inner {\n\tmargin-top: -6px;\n\tmargin-left: -7px;\n\tborder-left-color: rgb(25,25,25);\n\tborder-left-color: rgba(25,25,25,0.92);\n}\n\n/* Webkit Hacks  */\n@media screen and (-webkit-min-device-pixel-ratio:0) {\t\n\t#tiptip_content {\n\t\tpadding: 4px 8px 5px 8px;\n\t\tbackground-color: rgba(45,45,45,0.88);\n\t}\n\t#tiptip_holder.tip_bottom #tiptip_arrow_inner { \n\t\tborder-bottom-color: rgba(45,45,45,0.88);\n\t}\n\t#tiptip_holder.tip_top #tiptip_arrow_inner { \n\t\tborder-top-color: rgba(20,20,20,0.92);\n\t}\n}"
  },
  {
    "path": "_archive/apps/samples/clock/main.js",
    "content": "/**\n * Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\n\n/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\n chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n  \tid: \"clockWinID\",\n    innerBounds: {\n      height: 550,\n      width: 800,\n      top: 100\n    },\n    frame: 'none'\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/clock/manifest.json",
    "content": "{\n\t\"name\": \"World Clock\",\n\t\"version\": \"0.1.6\",\n\t\"manifest_version\": 2,\n\t\"minimum_chrome_version\": \"23\",\n\t\"description\": \"A world clock application.\",\n\t\"icons\": {\n\t\t\"16\": \"assets/icon.png\",\n\t\t\"128\": \"assets/icon.png\"\n\t},\n\t\"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n\t\"offline_enabled\": true,\n\t\"permissions\": [\"geolocation\",\n\t\t\t\t\t\t\t\t\t\"storage\",\n\t\t\t\t\t\t\t\t\t\"notifications\",\n\t\t\t\t\t\t\t\t\t\"<all_urls>\"\n\t\t\t\t\t\t\t\t ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/clock/script.js",
    "content": "var local;\nvar local_class;\nvar clocks = {};\nvar alarms = {};\nvar alarm_clocks = {};\n\nvar base_url = 'http://api.worldweatheronline.com/free/v1/tz.ashx?key=vfc3k7q22tjedr2rxse7xzke&format=json&q=';\n\nvar view = 'world';\n\nvar stopwatch;\nvar timer;\n\n$(document).ready(function() {\n\n\t$('.close').click(function() {\n\t\twindow.close();\n\t});\n\n\t$('.menu-item.world').tipTip({ edgeOffset: -5, defaultPosition: 'top' });\n\t$('.menu-item.alarm').tipTip({ edgeOffset: -5, defaultPosition: 'top' });\n\t$('.menu-item.timer').tipTip({ edgeOffset: -5, defaultPosition: 'top' });\n\t$('.menu-item.stopwatch').tipTip({ edgeOffset: -5, defaultPosition: 'top' });\n\n\tsetInterval(function() {\n\t\tif (view == 'world' && !navigator.onLine)\n\t\t\t$('.menu-item.new-world').addClass('hidden');\n\t\telse if (view == 'world')\n\t\t\t$('.menu-item.new-world').removeClass('hidden');\n\t})\n\n\t$('.menu-item.world').click(function() {\n\t\t$('.menu-item.button').addClass('hidden');\n\t\t$('#container > div').addClass('hidden');\n\t\t$('#container .world').removeClass('hidden');\n\t\t$('.menu-item').removeClass('selected');\n\t\t$('.menu-item.world').addClass('selected');\n\t\tview = 'world';\n\t\tif (sizeOf(clocks) == 0)\n\t\t\t$('.menu-item.new-world').click();\n\t\t$('.new-world').removeClass('hidden');\n\t});\n\n\t$('.menu-item.alarm').click(function() {\n\t\t$('.menu-item.button').addClass('hidden');\n\t\t$('#container > div').addClass('hidden');\n\t\t$('#container .alarm').removeClass('hidden');\n\t\t$('.menu-item').removeClass('selected');\n\t\t$('.menu-item.alarm').addClass('selected');\n\t\tview = 'alarm';\n\t\tif (sizeOf(alarms) == 0)\n\t\t\t$('.menu-item.new-alarm').click();\n\t\t$('.new-alarm').removeClass('hidden');\n\t});\n\n\t$('.menu-item.timer').click(function() {\n\t\t$('.menu-item.button').addClass('hidden');\n\t\t$('#container > div').addClass('hidden');\n\t\t$('#container .timer').removeClass('hidden');\n\t\t$('.menu-item').removeClass('selected');\n\t\t$('.menu-item.timer').addClass('selected');\n\t\tview = 'timer';\n\t});\n\n\t$('.menu-item.stopwatch').click(function() {\n\t\t$('.menu-item.button').addClass('hidden');\n\t\t$('#container > div').addClass('hidden');\n\t\t$('#container .stopwatch').removeClass('hidden');\n\t\t$('.menu-item').removeClass('selected');\n\t\t$('.menu-item.stopwatch').addClass('selected');\n\t\tview = 'stopwatch';\n\t});\n\n\t$('.menu-item.new-world').click(function() {\n\t\topenNewClock();\n\t});\n\n\t$('.menu-item.new-alarm').click(function() {\n\t\topenNewAlarm();\n\t});\n\n\t$('.world .new .add').click(function() {\n\t\taddWorldClock();\n\t});\n\n\t$('.alarm .new .add').click(function() {\n\t\taddAlarmClock();\n\t});\n\n\t$('#new-city').keyup(function(event) {\n\t\tif (event.which == 13) $('.world .new .add').click();\n\t});\n\n\t$('.world .new .cancel').click(function() {\n\t\t$('.world .new #new-city').val('');\n\t\t$('.world .new #new-city').removeClass('form-error');\n\t\t$('.new .error-message').addClass('hidden');\n\t\t$('.new .error-message').html('');\n\t\t$('.world .new').addClass('hidden');\n\t\tresize();\n\t});\n\n\t$('.alarm .new .cancel').click(function() {\n\t\t$('.alarm .new #new-alarm-name').val('');\n\t\t$('#new-alarm-hour').val('');\n\t\t$('#new-alarm-minute').val('');\n\t\t$('#new-alarm-noon').val('');\n\t\t$('.alarm .new').addClass('hidden');\n\t\tresize();\n\t});\n\n\t$('.alarm .edit .cancel').live('click', function() {\n\t\tvar id = $(this).parent().attr('class').split(' ')[0];\n\t\t$('.edit.' + id).addClass('hidden');\n\t\t$('.info.' + id).removeClass('hidden');\n\t\t$(this).parent().parent().removeClass('editing');\n\t});\n\n\t$('.alarm .edit .save').live('click', function() {\n\t\tvar id = $(this).parent().attr('class').split(' ')[0];\n\t\teditAlarmClock(id);\n\t\t$('.edit.' + id).addClass('hidden');\n\t\t$('.info.' + id).removeClass('hidden');\n\t\t$(this).parent().parent().removeClass('editing');\n\t});\n\n\tcreateDefaultText('00', $('#timer-minute'));\n\tcreateDefaultText('00', $('#timer-second'));\n\n\t$('#timer-minute').keyup(function() {\n\t\tif ($('#timer-minute').val() != '00') {\n\t\t\t$('.timer .button.start').removeClass('disabled');\n\t\t}\n\t});\n\t$('#timer-second').keyup(function() {\n\t\tif ($('#timer-second').val() != '00') {\n\t\t\t$('.timer .button.start').removeClass('disabled');\n\t\t}\n\t});\n\n\t$('.timer .button.start').click(function() {\n\t\tif (!$(this).hasClass('disabled')) {\n\t\t\tvar minute = parseInt($('#timer-minute').val()) % 60;\n\t\t\tvar second = parseInt($('#timer-second').val()) % 60;\n\t\t\tif (isNaN(minute)) {\n\t\t\t\tminute = 0;\n\t\t\t\t$('#timer-minute').val('00');\n\t\t\t} if (isNaN(second)) {\n\t\t\t\tsecond = 0;\n\t\t\t\t$('#timer-second').val('00');\n\t\t\t}\n\t\t\ttimer.setWatch(minute, second);\n\t\t\ttimer.startTiming();\n\t\t\t$('.timer #timer-minute').addClass('disabled');\n\t\t\t$('.timer #timer-second').addClass('disabled');\n\t\t\t$('.timer .button.start').addClass('hidden');\n\t\t\t$('.timer .button.stop').removeClass('disabled');\n\t\t\t$('.timer .button.stop').removeClass('hidden');\n\t\t\t$('.timer .button.reset').removeClass('disabled');\n\t\t}\n\t});\n\n\t$('.timer .button.stop').click(function() {\n\t\ttimer.stopTiming();\n\t\t$('.timer .button.start').removeClass('hidden');\n\t\t$('.timer .button.stop').addClass('hidden');\n\t});\n\n\t$('.timer .button.reset').click(function() {\n\t\t$('.timer .button.start').removeClass('hidden');\n\t\t$('.timer .button.stop').addClass('hidden');\n\t\t$('.timer .button.start').addClass('disabled');\n\t\t$('.timer .button.reset').addClass('disabled');\n\t\ttimer.resetWatch();\n\t\t$('.timer #timer-minute').val('00');\n\t\t$('.timer #timer-second').val('00');\n\t\t$('.timer #timer-minute').removeClass('disabled');\n\t\t$('.timer #timer-second').removeClass('disabled');\n\t});\n\n\t$('.stopwatch .button.start').click(function() {\n\t\tstopwatch.startTiming();\n\t\t$('.stopwatch .button.start').addClass('hidden');\n\t\t$('.stopwatch .button.stop').removeClass('hidden');\n\t});\n\n\t$('.stopwatch .button.stop').click(function() {\n\t\tstopwatch.stopTiming();\n\t\t$('.stopwatch .button.start').removeClass('hidden');\n\t\t$('.stopwatch .button.stop').addClass('hidden');\n\t});\n\n\t$('.stopwatch .button.reset').click(function() {\n\t\tstopwatch.resetWatch();\n\t\t$('.stopwatch .button.start').removeClass('hidden');\n\t\t$('.stopwatch .button.stop').addClass('hidden');\n\t});\n\n\t$('.delete').live('click', function() {\n\t\tvar class_name = $(this).parent().attr('class').split(' ')[1];\n\t\t$('.' + class_name).remove();\n\t\tif (view == 'alarm') {\n\t\t\tvar num = parseInt(class_name.slice(1));\n\t\t\tvar cur_num = sizeOf(alarms);\n\t\t\tif (cur_num === 1) {\n\t\t\t\tdelete alarms[class_name];\n\t\t\t\tdelete alarm_clocks[class_name];\n\t\t\t}\n\t\t\telse {\n\t\t\t\twhile (cur_num > num) {\n\t\t\t\t\tvar id = 'a' + cur_num;\n\t\t\t\t\tvar alarm = alarms[id];\n\t\t\t\t\tvar alarm_clock = alarm_clocks[id];\n\t\t\t\t\tdelete alarms[id];\n\t\t\t\t\tdelete alarm_clocks[id];\n\t\t\t\t\tcur_num -= 1;\n\t\t\t\t\talarms['a' + cur_num] = alarm;\n\t\t\t\t\talarm_clocks['a' + cur_num] = alarm_clock;\n\t\t\t\t\t$('.' + id).removeClass(id).addClass('a' + cur_num);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdelete clocks[class_name];\n\t\tchrome.storage.sync.set({ 'clocks': clocks, 'alarms': alarms });\n\t\tif (sizeOf(clocks) == 0)\n\t\t\t$('.menu-item.new-world').click();\n\t\tif (sizeOf(alarms) == 0)\n\t\t\t$('.menu-item.new-alarm').click();\n\n\t\tresize();\n\t});\n\n\t$('.info').live('click', function() {\n\t\t$(this).parent().addClass('editing');\n\t\tvar id = $(this).attr('class').split(' ')[0];\n\t\tvar hour = parseInt(alarms[id]['hour']);\n\t\tvar minute = parseInt(alarms[id]['minute']);\n\t\tvar noon = 'AM';\n\t\tif (hour == 12) {\n\t\t\tnoon = 'PM';\n\t\t}\n\t\tif (hour > 12) {\n\t\t\tnoon = 'PM';\n\t\t\thour -= 12;\n\t\t}\n\t\tif (hour == 0) {\n\t\t\thour = 12;\n\t\t}\n\t\tif (hour < 10) {\n\t\t\thour = '0' + hour;\n\t\t}\n\t\tif (minute < 10) {\n\t\t\tminute = '0' + minute;\n\t\t}\n\t\t$('.' + id + ' .edit-alarm-name').val(alarms[id]['name']);\n\t\t$('.' + id + ' .edit-alarm-hour').val(hour);\n\t\t$('.' + id + ' .edit-alarm-minute').val(minute);\n\t\t$('.' + id + ' .edit-alarm-noon').val(noon);\n\t\t$(this).addClass('hidden');\n\t\t$('.' + id + '.edit').removeClass('hidden');\n\t});\n\n\t$(window).resize(function() {\n\t\tresize();\n\t});\n\n\tsetup();\n\n});\n\nfunction createDefaultText(default_text, $input) {\n\t$input.css('color', '#666');\n\t$input.val(default_text);\n\t$input.focus(function() {\n\t\tvar actual_text = $input.val();\n\t\tif (actual_text == default_text) {\n\t\t\t$input.val('');\n\t\t\t$input.css('color', '#333');\n\t\t}\n\t});\n\t$input.blur(function() {\n\t\tvar actual_text = $input.val();\n\t\tif (!actual_text) {\n\t\t\t$input.val(default_text);\n\t\t\t$input.css('color', '#666');\n\t\t}\n\t});\n}\n\nfunction openNewClock() {\n\t$('.world .new').removeClass('hidden');\n\t$('#new-city').focus();\n\tresize();\n}\n\nfunction openNewAlarm() {\n\tvar default_text = 'Alarm ' + (sizeOf(alarms) + 1);\n\tvar $input = $('#new-alarm-name');\n\tcreateDefaultText(default_text, $input);\n\tcreateDefaultText('00', $('#new-alarm-hour'));\n\tcreateDefaultText('00', $('#new-alarm-minute'));\n\tcreateDefaultText('AM', $('#new-alarm-noon'));\n\t$('.alarm .new').removeClass('hidden');\n\tresize();\n}\n\nfunction setup() {\n\tchrome.storage.sync.get(function(items) {\n\t\tfor (var clock_class in items['clocks']) {\n\t\t\tclocks[clock_class] = items['clocks'][clock_class];\n\t\t}\n\t\tfor (var alarm_class in items['alarms']) {\n\t\t\talarms[alarm_class] = items['alarms'][alarm_class];\n\t\t}\n\t\tlocal = items['local'];\n\n\t\tnavigator.geolocation.getCurrentPosition(getCurrentPosSuccessFunction,\n    \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \t getCurrentPosErrorFunction);\n\t});\n}\n\nfunction setupClocks() {\n\tvar clock = new Clock('new', 0);\n\tclock.create();\n\tvar found_local = false;\n\tfor (var city_class in clocks) {\n\t\tif (city_class == local_class) found_local = true;\n\t\taddClock(city_class);\n\t}\n\tif (local_class && !found_local) addClock(local_class);\n\tif (sizeOf(clocks) == 0) {\n\t\t$('.menu-item.new-world').click();\n\t}\n}\n\nfunction setupAlarms() {\n\tvar alarm = new Alarm('new', 'new', 0, 0, 0);\n\talarm.create();\n\tfor (var id in alarms) {\n\t\taddAlarm(id);\n\t}\n\tif (sizeOf(alarms) == 0)\n\t\t$('.menu-item.new-alarm').click();\n}\n\nfunction setupTimer() {\n\ttimer = new Timer();\n\ttimer.create();\n}\n\nfunction setupStopwatch() {\n\tstopwatch = new Stopwatch();\n\tstopwatch.create();\n}\n\nfunction getCurrentPosSuccessFunction(position) {\n  var lat = position.coords.latitude;\n  var lng = position.coords.longitude;\n  var url = encodeURI(base_url + lat + ',' + lng);\n\t$.get(url,\n\t\tfunction(data) {\n\t\t\tif (!data['data']['error']) {\n\t\t\t\tlocal = parseInt(data['data']['time_zone'][0]['utcOffset']);\n\t\t\t\tchrome.storage.sync.set({ 'local' : local });\n\t\t\t}\n\t\t},\n\t\t'json'\n\t);\n\tsetupClocks();\n\tsetupAlarms();\n\tsetupTimer();\n\tsetupStopwatch();\n}\n\nfunction getCurrentPosErrorFunction(error) {\n  console.log(\"Geocoder failed\");\n  local = -new Date().getTimezoneOffset()/60;\n  setupClocks();\n  setupAlarms();\n  setupTimer();\n\tsetupStopwatch();\n}\n\n// Function adds a canvas element and initializes a new clock for that canvas\nfunction addClock(city_class) {\n\tvar city = clocks[city_class][0];\n\tvar offset = clocks[city_class][1] - local;\n\t$('#container .world .new').before('<div class=\"city-clock ' + city_class + '\"></div>');\n\t$('.' + city_class).append('<div class=\"delete\"></div>');\n\t$('.' + city_class).append('<canvas class=\"clock\"></canvas>');\n\t$('.' + city_class).append('<div class=\"city\">' + city + '</div>');\n\t$('.' + city_class).append('<div class=\"time\"></div>');\n\t$('.' + city_class).append('<div class=\"day\"></div>');\n\tvar clock = new Clock(city_class, offset);\n\tclock.create();\n\tresize();\n}\n\n// Function adds a canvas element and initializes a new alarm for that canvas\nfunction addAlarm(id) {\n\tvar alarm = alarms[id];\n\tvar edit = '<div class=\"' + id + ' edit hidden\">\\\n\t\t\t\t\t\t\t\t<input type=\"text\" class=\"edit-alarm-name\" /><br>\\\n\t\t\t\t\t\t\t\t<input type=\"text\" class=\"edit-alarm-hour\" maxlength=\"2\" />\\\n\t\t\t\t\t\t\t\t<input type=\"text\" class=\"edit-alarm-minute\" maxlength=\"2\" />\\\n\t\t\t\t\t\t\t\t<input type=\"text\" class=\"edit-alarm-noon\" maxlength=\"2\" /><br>\\\n\t\t\t\t\t\t\t\t<div class=\"button save\">Save</div>\\\n\t\t\t\t\t\t\t\t<div class=\"button cancel\">Cancel</div>\\\n\t\t\t\t\t\t\t</div>';\n\tvar info = '<div class=\"' + id + ' info\">\\\n\t\t\t\t\t\t\t\t<div class=\"name\">' + alarm['name'] + '</div>\\\n\t\t\t\t\t\t\t\t<div class=\"time\"></div>\\\n\t\t\t\t\t\t\t</div>'\n\t$('#container .alarm .new').before('<div class=\"alarm-clock ' + id + '\"></div>');\n\t$('.alarm-clock.' + id).append('<div class=\"delete\"></div>');\n\t$('.alarm-clock.' + id).append('<canvas class=\"clock\"></canvas>');\n\t$('.alarm-clock.' + id).append(info);\n\t$('.alarm-clock.' + id).append(edit);\n\tvar alarm_clock = new Alarm(id,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\talarm['name'],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\talarm['hour'],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\talarm['minute'],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\talarm['on']);\n\talarm_clock.create();\n\talarm_clocks[id] = alarm_clock;\n\tresize();\n}\n\nfunction addWorldClock() {\n\tvar city = $('.world .new #new-city').val();\n\tif (city.split(' ').join('-') in clocks) {\n\t\t$('.world .new .button.cancel').click();\n\t}\n\telse {\n\t\tvar url = encodeURI(base_url + city);\n\t\t$.get(url,\n\t\t\tfunction(data) {\n\t\t\t\tif (data['data']['error']) {\n\t\t\t\t\tvar city = $('.world .new #new-city').val();\n\t\t\t\t\t$('.world .new #new-city').addClass('form-error');\n\t\t\t\t\t$('.new .error-message').html('Could not find the time for ' + city + '.<br>');\n\t\t\t\t\t$('.new .error-message').removeClass('hidden');\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tvar city = data['data']['request'][0]['query'].split(', ')[0];\n\t\t\t\t\tvar city_class = city.split(' ').join('-');\n\t\t\t\t\tvar time_zone = parseInt(data['data']['time_zone'][0]['utcOffset']);\n\t\t\t\t\tclocks[city_class] = [city, time_zone];\n\t\t\t\t\tchrome.storage.sync.set({ 'clocks' : clocks });\n\t\t\t\t\taddClock(city_class);\n\t\t\t\t\t$('.world .new #new-city').val('');\n\t\t\t\t\t$('.new .error-message').html('');\n\t\t\t\t\t$('.world .new').addClass('hidden');\n\t\t\t\t}\n\t\t\t},\n\t\t\t'json'\n\t\t);\n\t}\n}\n\nfunction addAlarmClock() {\n\tvar name = $('#new-alarm-name').val();\n\tvar hour = parseInt($('#new-alarm-hour').val());\n\tvar minute = parseInt($('#new-alarm-minute').val());\n\tif (isNaN(hour)) {\n\t\thour = 12;\n\t} if (isNaN(minute)) {\n\t\tminute = 0;\n\t}\n\tvar noon = $('#new-alarm-noon').val();\n\tif (noon.toLowerCase() == 'pm' && hour != 12) hour += 12;\n\telse if (noon.toLowerCase() == 'am' && hour == 12) hour -= 12;\n\tvar id = 'a' + (sizeOf(alarms) + 1);\n\talarm = { 'name' : name, 'hour' : hour, 'minute' : minute, 'on' : true };\n\talarms[id] = alarm;\n\tchrome.storage.sync.set({ 'alarms' : alarms });\n\t$('#new-alarm-name').val('');\n\t$('#new-alarm-hour').val('');\n\t$('#new-alarm-minute').val('');\n\t$('#new-alarm-noon').val('');\n\taddAlarm(id);\n\t$('.alarm .new').addClass('hidden');\n}\n\nfunction editAlarmClock(id) {\n\tvar name = $('.edit.' + id + ' .edit-alarm-name').val();\n\tconsole.log(name);\n\tvar hour = parseInt($('.edit.' + id + ' .edit-alarm-hour').val());\n\tvar minute = parseInt($('.edit.' + id + ' .edit-alarm-minute').val());\n\tif (isNaN(hour)) {\n\t\thour = alarms[id]['hour'];\n\t} if (isNaN(minute)) {\n\t\tminute = alarms[id]['minute'];\n\t}\n\tvar noon = $('.edit.' + id + ' .edit-alarm-noon').val();\n\tif (noon.toLowerCase() == 'pm' && hour != 12) hour += 12;\n\telse if (noon.toLowerCase() == 'am' && hour == 12) hour -= 12;\n\talarm = { 'name' : name, 'hour' : hour, 'minute' : minute, 'on' : alarms[id]['on'] };\n\talarms[id] = alarm;\n\talarm_clock = alarm_clocks[id];\n\tconsole.log(hour);\n\tconsole.log(minute);\n\talarm_clock.update(name, hour, minute);\n\tchrome.storage.sync.set({ 'alarms' : alarms });\n\t$('.' + id + '.info .name').text(name);\n}\n\nfunction resize() {\n\tvar clock_width = 330.0;\n\tvar clocks_size = sizeOf(clocks);\n\tif (!$('.world .new').hasClass('hidden'))\n\t\tclocks_size += 1;\n\tvar lines = Math.ceil(clock_width * clocks_size / window.innerWidth);\n\tvar height = 350 * lines;\n\tif (window.innerHeight > height + 100) {\n\t\t$('.world').css({ 'top' : '50%', 'margin-top' : '-' + height/2 + 'px' });\n\t} else {\n\t\t$('.world').css({ 'top' : '0px', 'margin-top' : '0px' });\n\t}\n\n\tvar alarm_width = 300.0;\n\tvar alarms_size = sizeOf(alarms);\n\tif (!$('.alarm .new').hasClass('hidden'))\n\t\talarms_size += 1;\n\tvar lines = Math.ceil(alarm_width * alarms_size / window.innerWidth);\n\tvar height = 385 * lines;\n\tif (window.innerHeight > height) {\n\t\t$('.alarm').css({ 'top' : '50%', 'margin-top' : '-' + height/2 + 'px' });\n\t} else {\n\t\t$('.alarm').css({ 'top' : '0px', 'margin-top' : '0px' });\n\t}\n}\n\nfunction sizeOf(dictionary) {\n\tvar count = 0;\n\tfor (var key in dictionary) {\n\t\tif (dictionary.hasOwnProperty(key)) count++;\n\t}\n\treturn count;\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/clock/stopwatch.js",
    "content": "Stopwatch = function() {\n\tthis.config = {\n\t\tcontainer: {height: 250, width: 250},\n\t\tface: {color: '#424240', alpha: 1, radius: 120},\n\t\thourHand: {color: '#4d90fe', alpha: 1, length: 35, width: 3},\n\t\tminuteHand: {color: '#4d90fe', alpha: 1, length: 90, width: 2},\n\t\tunit: {\n\t\t\tmajor: {color: '#f5f5f5', alpha: 0.4, length: 12, width: 2},\n\t\t\tmid: {color: '#f5f5f5', alpha: 0.4, length: 12, width: 1},\n\t\t\tminor: {color: '#f5f5f5', alpha: 0.4, length: 8, width: 1}\n\t\t},\n\t\tminute: {\n\t\t\tface: {color: '#424240', alpha: 1, radius: 35},\n\t\t\thand: {color: '#4d90fe', alpha: 1, length: 20, width: 2},\n\t\t\tunit: {\n\t\t\t\tmajor: {color: '#f5f5f5', alpha: 0.4, length: 5, width: 2},\n\t\t\t\tmid: {color: '#f5f5f5', alpha: 0.4, length: 5, width: 1},\n\t\t\t\tminor: {color: '#f5f5f5', alpha: 0.4, length: 2, width: 1}\n\t\t\t}\n\t\t}\n\t};\n\n\tthis.timing = false;\n\tthis.time_passed = new Date(0);\n}\n\n//Stopwatch inherits from Clock\nStopwatch.prototype = new Clock(this.id, 0);\n\n//Method to initialize the stopwatch\nStopwatch.prototype.create = function() {\n\tthis.canvas = $('.stopwatch .clock')[0];\n\tthis.canvas.height = this.config.container.height;\n\tthis.canvas.width = this.config.container.width;\n\n\tthis.context = this.canvas.getContext(\"2d\");\n\n\tthis.drawClock(0, 0, 0, 0);\n\n\tthis.startTick();\n}\n\n//Methods to draw the stopwatch\nStopwatch.prototype.drawClock = function (hour, minute, second, millisecond) {\n\tthis.context.clearRect(0, 0, this.config.container.width, this.config.container.height);\n\n\tthis.drawface();\n\tthis.drawUnits();\n\tthis.innerShadow();\n\tthis.drawText(hour, minute, second);\n\tthis.drawTime(minute, second, millisecond);\n\tthis.drawHands(hour, minute, second, millisecond);\n}\n\n//Method to draw the hands (minutes and seconds are switched... TODO: fix that)\nStopwatch.prototype.drawHands = function(hour, second, minute, millisecond) {\n\tthis.context.save();\n\n\tthis.context.translate(this.config.container.width/2,this.config.container.height/2);\n\tthis.context.rotate(Math.PI * (2.0 * ((minute + (millisecond/1000.0))/60) - 0.5));\n\tthis.context.globalAlpha = this.config.minuteHand.alpha;\n\tthis.context.strokeStyle = this.config.minuteHand.color;\n\tthis.context.lineWidth = this.config.minuteHand.width;\n\tthis.context.lineCap = \"round\";\n\tthis.context.shadowOffsetX = 0;\n\tthis.context.shadowOffsetY = 4;\n\tthis.context.shadowBlur = 2;\n\tthis.context.shadowColor = \"rgba(0, 0, 0, 0.2)\";\n\n\tthis.context.beginPath();\n\tthis.context.moveTo(0, 0);\n\tthis.context.lineTo(this.config.minuteHand.length - 5, 0);\n\tthis.context.closePath();\n\n\tthis.context.stroke();\n\n\tthis.context.restore();\n\n\tthis.context.save();\n\tthis.context.beginPath();\n\tthis.context.arc(this.config.container.width/2, this.config.container.height/2, 4, 0, Math.PI*2, false);\n\tthis.context.closePath();\n\tthis.context.fillStyle = this.config.minuteHand.color;\n\tthis.context.fill();\n\tthis.context.restore();\n\n\tthis.context.save();\n\tthis.context.beginPath();\n\tthis.context.arc(this.config.container.width/2, this.config.container.height/2, 1, 0, Math.PI*2, false);\n\tthis.context.closePath();\n\tthis.context.fillStyle = this.config.unit.major.color;\n\tthis.context.fill();\n\tthis.context.restore();\n\n\tthis.context.save();\n\n\tthis.context.translate(this.config.container.width/2,this.config.container.height/3.5);\n\tthis.context.rotate(Math.PI * (2.0 * ((second + (minute / 60.0)) / 60) - 0.5));\n\tthis.context.globalAlpha = this.config.minute.hand.alpha;\n\tthis.context.strokeStyle = this.config.minute.hand.color;\n\tthis.context.lineWidth = this.config.minute.hand.width;\n\tthis.context.lineCap = \"round\";\n\tthis.context.shadowOffsetX = 0;\n\tthis.context.shadowOffsetY = 4;\n\tthis.context.shadowBlur = 2;\n\tthis.context.shadowColor = \"rgba(0, 0, 0, 0.2)\";\n\n\tthis.context.beginPath();\n\tthis.context.moveTo(0, 0);\n\tthis.context.lineTo(this.config.minute.hand.length - 5, 0);\n\tthis.context.closePath();\n\n\tthis.context.stroke();\n\n\tthis.context.restore();\n\n\tthis.context.save();\n\tthis.context.beginPath();\n\tthis.context.arc(this.config.container.width/2, this.config.container.height/3.5, 4, 0, Math.PI*2, false);\n\tthis.context.closePath();\n\tthis.context.fillStyle = this.config.minute.hand.color;\n\tthis.context.fill();\n\tthis.context.restore();\n\n\tthis.context.save();\n\tthis.context.beginPath();\n\tthis.context.arc(this.config.container.width/2, this.config.container.height/3.5, 1, 0, Math.PI*2, false);\n\tthis.context.closePath();\n\tthis.context.fillStyle = this.config.minute.unit.major.color;\n\tthis.context.fill();\n\tthis.context.restore();\n}\n\n//Method to draw the number\nStopwatch.prototype.drawText = function(hour, minute, second, millisecond) {\n\t//Numbers for main face\n\tfor (var i = 0; i < 12; i++) {\n\t\tthis.context.save();\n\t\tthis.context.translate(this.config.container.width/2, this.config.container.height/2);\n\t\tthis.context.rotate(Math.PI * (2.0 * (i/12) - 0.5));\n\t\tthis.context.translate(this.config.face.radius - 22, 0);\n\t\tthis.context.rotate((Math.PI * (2.0 * (i/12) - 0.5) * -1));\n\n\t\tvar alpha = this.config.unit.major.alpha;\n\n\t\tthis.context.globalAlpha = alpha;\n\n\t\tthis.context.fillStyle = this.config.unit.major.color;\n\t\tthis.context.shadowOffsetX = 1;\n\t\tthis.context.shadowOffsetY = 1;\n\t\tthis.context.shadowColor = \"rgba(0, 0, 0, 0.8)\";\n\t\tthis.context.font = \"600 11px 'Open Sans'\";\n\t\tthis.context.textBaseline = 'middle';\n\t\tthis.context.textAlign = \"center\";\n\n\t\tvar textValue;\n\n\t\tif (i === 0) {\n\t\t\ttextValue = 60;\n\t\t}\n\t\telse {\n\t\t\ttextValue = i * 5;\n\t\t}\n\n\t\tthis.context.fillText(textValue, 0, 0);\n\t\tthis.context.restore();\n\t}\n\n\t//Numbers for minutes face\n\tfor (var i = 0; i < 12; i++) {\n\t\tthis.context.save();\n\t\tthis.context.translate(this.config.container.width/2, this.config.container.height/3.5);\n\t\tthis.context.rotate(Math.PI * (2.0 * (i/12) - 0.5));\n\t\tthis.context.translate(this.config.minute.face.radius - 13, 0);\n\t\tthis.context.rotate((Math.PI * (2.0 * (i/12) - 0.5) * -1));\n\n\t\tvar alpha = this.config.minute.unit.major.alpha;\n\n\t\tthis.context.globalAlpha = alpha;\n\n\t\tthis.context.fillStyle = this.config.minute.unit.major.color;\n\t\tthis.context.shadowOffsetX = 1;\n\t\tthis.context.shadowOffsetY = 1;\n\t\tthis.context.shadowColor = \"rgba(0, 0, 0, 0.8)\";\n\t\tthis.context.font = \"600 10px 'Open Sans'\";\n\t\tthis.context.textBaseline = 'middle';\n\t\tthis.context.textAlign = \"center\";\n\n\t\tvar textValue = '';\n\t\tif (i === 0) {\n\t\t\ttextValue = 60;\n\t\t}\n\t\telse if (i % 2 === 0) {\n\t\t\ttextValue = i * 5;\n\t\t}\n\n\t\tthis.context.fillText(textValue, 0, 0);\n\t\tthis.context.restore();\n\t}\n}\n\n//Method to draw the units\nStopwatch.prototype.drawUnits = function() {\n\t//Draw units for main face\n\tfor (var i = 0; i < 60 * 5; i++) {\n\t\tthis.context.save();\n\t\tthis.context.translate(this.config.container.width/2, this.config.container.height/2);\n\t\tthis.context.rotate(Math.PI * (2.0 * (i/(60*5)) - 0.5));\n\t\tthis.context.globalAlpha = this.config.unit.major.alpha;\n\t\tthis.context.strokeStyle = this.config.unit.major.color;\n\n\t\tif (i % 5 === 0) {\n\t\t\tif (i % 25 === 0) {\n\t\t\t\tthis.context.lineWidth = this.config.unit.major.width;\n\t\t\t\tvar length = this.config.unit.major.length;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.context.lineWidth = this.config.unit.mid.width;\n\t\t\t\tvar length = this.config.unit.mid.length;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthis.context.lineWidth = this.config.unit.minor.width;\n\t\t\tvar length = this.config.unit.minor.length;\n\t\t}\n\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(this.config.face.radius - length, 0);\n\t\tthis.context.lineTo(this.config.face.radius, 0);\n\t\tthis.context.closePath();\n\t\tthis.context.stroke();\n\t\tthis.context.restore();\n\t}\n\n\t//Draw units for minutes face\n\tfor (var i = 0; i < 60; i++) {\n\t\tthis.context.save();\n\t\tthis.context.translate(this.config.container.width/2, this.config.container.height/3.5);\n\t\tthis.context.rotate(Math.PI * (2.0 * (i / 60) - 0.5));\n\t\tthis.context.globalAlpha = this.config.minute.unit.major.alpha;\n\t\tthis.context.strokeStyle = this.config.minute.unit.major.color;\n\n\t\tif (i % 5 === 0) {\n\t\t\tif (i % 15 === 0) {\n\t\t\t\tthis.context.lineWidth = this.config.minute.unit.major.width;\n\t\t\t\tvar length = this.config.minute.unit.major.length;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthis.context.lineWidth = this.config.minute.unit.mid.width;\n\t\t\t\tvar length = this.config.minute.unit.mid.length;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthis.context.lineWidth = this.config.minute.unit.minor.width;\n\t\t\tvar length = this.config.minute.unit.minor.length;\n\t\t}\n\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(this.config.minute.face.radius - length, 0);\n\t\tthis.context.lineTo(this.config.minute.face.radius, 0);\n\t\tthis.context.closePath();\n\t\tthis.context.stroke();\n\t\tthis.context.restore();\n\t}\n}\n\nStopwatch.prototype.drawTime = function(minute, second, millisecond) {\n\tthis.context.save();\n\n\tthis.context.translate(this.config.container.width/2, this.config.container.height/1.3);\n\n\tvar alpha = this.config.unit.major.alpha;\n\n\tthis.context.globalAlpha = alpha;\n\n\tthis.context.fillStyle = this.config.unit.major.color;\n\tthis.context.shadowOffsetX = 1;\n\tthis.context.shadowOffsetY = 1;\n\tthis.context.shadowColor = \"rgba(0, 0, 0, 0.8)\";\n\tthis.context.font = \"600 14px 'Open Sans'\";\n\tthis.context.textBaseline = 'middle';\n\tthis.context.textAlign = \"center\";\n\n\tif (minute < 10) minute = '0' + minute;\n\tif (second < 10) second = '0' + second;\n\tmillisecond = parseInt(millisecond / 100);\n\n\tvar textValue = minute + ':' + second + ':' + millisecond;\n\n\tthis.context.fillText(textValue, 0, 0);\n\tthis.context.restore();\n}\n\nStopwatch.prototype.startTiming = function() {\n\tthis.timing = true;\n}\n\nStopwatch.prototype.stopTiming = function() {\n\tthis.timing = false;\n}\n\nStopwatch.prototype.resetWatch = function() {\n\tthis.timing = false;\n\tthis.time_passed = new Date(0)\n\tthis.drawClock(0, 0, 0, 0);\n}\n\n//Method to fire ten times each second and redraw the clock\nStopwatch.prototype.tick = function() {\n\tif (this.timing) {\n\t\tthis.time_passed.setTime(this.time_passed.getTime() + 100);\n\t\tvar minute = this.time_passed.getMinutes();\n\t\tvar second = this.time_passed.getSeconds();\n\t\tvar millisecond = this.time_passed.getMilliseconds();\n\t\tthis.drawClock(0, minute, second, millisecond);\n\t}\n}\n\nStopwatch.prototype.startTick = function() {\n\tvar inst = this;\n\tthis.tickId = setInterval(function() { inst.tick(); }, 100);\n}\n"
  },
  {
    "path": "_archive/apps/samples/clock/style.css",
    "content": "html {\n  position: fixed;\n  width: 100%;\n  height: 100%;\n  -webkit-app-region: drag;\n}\n\ninput, button, .menu-item, .button, .close {\n  -webkit-app-region: no-drag;\n}\n\nbody {\n  background: #f5f5f5;\n  color: #222;\n  font-family: \"Open Sans\", \"Helvetica Neue\", \"Helvetica\", \"Arial\", sans-serif;\n  font-size: 13px;\n  line-height: 18px;\n  margin: 0px;\n  text-align: left;\n}\n\n.button {\n  background-color: #f5f5f5;\n  background-image: linear-gradient(top, #f5f5f5, #f1f1f1);\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f1f1f1);\n  border: 1px solid rgba(0, 0, 0, 0.1);\n  border-radius: 2px;\n  -webkit-border-radius: 2px;\n  color: #444;\n  cursor: default;\n  display: inline-block;\n  font-size: 11px;\n  font-weight: bold;\n  height: 27px;\n  line-height: 27px;\n  margin-left: 2px;\n  margin-right: 2px;\n  margin-top: 8px;\n  min-width: 40px;\n  padding: 0 8px;\n  text-align: center;\n  transition: all 0.218s;\n  -webkit-transition: all 0.218s;\n  white-space: nowrap;\n}\n\n.button:hover {\n  background-color: #f8f8f8;\n  background-image: -webkit-linear-gradient(top, #f8f8f8, #f1f1f1);\n  background-image: linear-gradient(top, #f8f8f8, #f1f1f1);\n  border: 1px solid #c6c6Cc;\n  box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);\n  -webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);\n  color: #222;\n  transition: all 0.0s;\n  -webkit-transition: all 0.0s;\n}\n\n.button:active {\n  background-color: #f6f6f6;\n  background-image: -webkit-linear-gradient(top, #f6f6f6, #f1f1f1);\n  background-image: linear-gradient(top, #f6f6f6, #f1f1f1);\n  border: 1px solid #c6c6c6;\n  box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);\n  -webkit-box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);\n  color: #333;\n}\n\ninput[type=text] {\n  background-color: #fff;\n  border: 1px solid #d9d9d9;\n  border-top: 1px solid #c0c0c0;\n  box-sizing: border-box;\n  -webkit-box-sizing: border-box;\n  border-radius: 1 px;\n  -webkit-border-radius: 1px;\n  color: #333;\n  display: inline-block;\n  height: 29px;\n  line-height: 27px;\n  margin-top: 8px;\n  padding-left: 8px;\n  vertical-align: top;\n}\n\ninput[type=text]:hover {\n  border: 1px solid #b9b9b9;\n  border-top: 1px solid #a0a0a0;\n  box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);\n  -webkit-box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);\n}\n\ninput[type=text]:focus {\n  border: 1px solid #4d90fe;\n  box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.3);\n  outline: none;\n}\n\ninput[type=text].form-error{\n  border: 1px solid #dd4b39;\n}\n\n.error-message {\n  color: #dd4b39;\n  padding: 0px;\n}\n\n.close {\n\tbackground: url('img/x.png') center no-repeat;\n\tbackground-size: 20px 20px;\n\theight: 20px;\n\twidth: 20px;\n\tmargin: 5px;\n\tfloat: right;\n\topacity: 0.7;\n\tz-index: 50;\n}\n\n.close:hover {\n\topacity: 1;\n}\n\n#container {\n\ttext-align: center;\n}\n\n#container .world,\n#container .alarm,\n#container .timer,\n#container .stopwatch {\n\ttop: 20px;\n\tbottom: 100px;\n\tposition: absolute;\n\ttext-align: center;\n\twidth: 100%;\n\toverflow: auto;\n}\n\n#container .timer,\n#container .stopwatch {\n\tmargin-top: -165px;\n\ttop: 50%;\n}\n\n#container .world .city-clock,\n#container .world .new,\n#container .alarm .alarm-clock,\n#container .alarm .new,\n#container .timer .timer-clock,\n#container .stopwatch .stopwatch-clock {\n\tdisplay: inline-block;\n\tposition: static;\n\ttext-align: center;\n\tvertical-align: middle;\n\tmargin: 40px;\n\tmargin-top: 0px;\n\tmargin-bottom: 30px;\n}\n\n#container .world .new {\n\tmargin-bottom: -12px;\n}\n\n#container .alarm .new {\n\tmargin-bottom: -74px;\n}\n\n#container .alarm .editing {\n\tmargin-bottom: -38px;\n}\n\n.world .city-clock .clock,\n.word .new .clock,\n.alarm .alarm-clock .clock,\n.alarm .new .clock {\n\tdisplay: block;\n\theight: 240px;\n\tposition: relative;\n\twidth: 240px;\n\tmargin-right: -25px;\n\tmargin-bottom: 30px;\n}\n\n.timer .clock,\n.stopwatch .clock {\n\tdisplay: block;\n\tposition: static;\n}\n\n.world .new .new-input,\n.alarm .new .new-input {\n\ttext-align: center;\n\tposition: static;\n}\n\n#container .world .new.hidden,\n#container .alarm .new.hidden {\n\tdisplay: none;\n}\n\n.world .city-clock .city,\n.alarm .alarm-clock .name {\n\tdisplay: block;\n\tfont-weight: bold;\n\tfont-size: 18px;\n\tmargin-bottom: 5px;\n}\n\n.world .city-clock .time,\n.world .city-clock .day,\n.alarm .alarm-clock .time {\n\tdisplay: inline-block;\n\tfont-size: 14px;\n\tpadding: 1px;\n}\n\n.alarm .new #new-alarm-hour,\n.alarm .new #new-alarm-minute,\n.alarm .new #new-alarm-noon,\n.alarm .edit .edit-alarm-hour,\n.alarm .edit .edit-alarm-minute,\n.alarm .edit .edit-alarm-noon {\n\tdisplay: inline-block;\n\tmargin-right: -2px;\n\tmargin-left: -2px;\n\twidth: 43px;\n\theight: 29px;\n\tline-height: 27px;\n\tpadding-right: 13px;\n}\n\n.alarm .info {\n\tposition: relative;\n\tz-index: 10;\n}\n\n.delete {\n\tbackground: url('img/x.png') center no-repeat;\n\tbackground-size: 15px 15px;\n\tfloat: right;\n\theight: 15px;\n\topacity: 0;\n\tpadding: 10px;\n\tposition: relative;\n\twidth: 15px;\n\tz-index: 10;\n}\n\n.city-clock:hover .delete,\n.alarm-clock:hover .delete {\n\topacity: 0.7;\n}\n\n.delete:hover {\n\topacity: 1;\n}\n\n.timer-clock .button,\n.stopwatch-clock .button {\n\tfont-weight: normal;\n\tletter-spacing: 1px;\n\tmargin-top: 30px;\n\tbackground: #424240;\n\tcolor: #ccc;\n\tmin-width: 50px;\n\tmargin-right: 20px;\n}\n\n.timer-clock .button.reset,\n.timer-clock .button.set,\n.stopwatch-clock .button.reset {\n\tmargin-right: 0px;\n}\n\n.timer-clock .button:hover,\n.stopwatch-clock .button:hover,\n.menu-item.button:hover {\n\tbackground: #424240;\n\tborder: 1px solid rgba(0, 0, 0, 0.1);\n}\n\n.timer-clock .button:active,\n.stopwatch-clock .button:active,\n.menu-item.button:active {\n\tbackground: #3e3e3c;\n\tborder: 1px solid rgba(0, 0, 0, 0.3);\n}\n\n.timer .button.disabled {\n\topacity: 0.5;\n}\n\n.timer-clock #timer-minute,\n.timer-clock #timer-second {\n\tdisplay: inline-block;\n\theight: 26px;\n\tline-height: 24px;\n\tmargin-right: -3px;\n\tmargin-top: 20px;\n\tmargin-bottom: -10px;\n\twidth: 35px;\n\topacity: 1;\n}\n\n.timer-clock #timer-minute.disabled,\n.timer-clock #timer-second.disabled {\n\topacity: 0;\n}\n\n#menu {\n\tposition: absolute;\n\ttext-align: center;\n\tbottom: 25px;\n\twidth: 100%;\n}\n\n.menu-item {\n\tdisplay: inline-block;\n\theight: 24px;\n\tmargin: 10px;\n\tmargin-bottom: 25px;\n\twidth: 24px;\n}\n\n.menu-item.world {\n\tbackground: url('img/world.png') center no-repeat;\n\tbackground-size: 24px 24px;\n}\n\n#menu .alarm {\n\tbackground: url('img/alarm.png') center no-repeat;\n\tbackground-size: 24px 24px;\n}\n\n#menu .timer {\n\tbackground: url('img/timer.png') center no-repeat;\n\tbackground-size: 24px 24px;\n}\n\n#menu .stopwatch {\n\tbackground: url('img/stopwatch.png') center no-repeat;\n\tbackground-size: 24px 24px;\n}\n\n.menu-item.button {\n\tposition: static;\n\tfont-weight: 600;\n\tfont-size: 11px;\n\tletter-spacing: 1px;\n\tmargin: 0px;\n\tmargin-left: -48px;\n\tbackground: #424240;\n\tcolor: #f5f5f5;\n\twidth: 16px;\n\theight: 20px;\n\tpadding-left: 2px;\n\tpadding-right: 2px;\n\tline-height: 18px;\n}\n\n.menu-item.world:hover {\n\tbackground: url('img/world_hover.png') center no-repeat;\n\tbackground-size: 24px 24px;\n}\n\n#menu .alarm:hover {\n\tbackground: url('img/alarm_hover.png') center no-repeat;\n\tbackground-size: 24px 24px;\n}\n\n#menu .timer:hover {\n\tbackground: url('img/timer_hover.png') center no-repeat;\n\tbackground-size: 24px 24px;\n}\n\n#menu .stopwatch:hover {\n\tbackground: url('img/stopwatch_hover.png') center no-repeat;\n\tbackground-size: 24px 24px;\n}\n\n.menu-item.world.selected {\n\tbackground: url('img/world_selected.png') center no-repeat;\n\tbackground-size: 24px 24px;\n}\n\n#menu .alarm.selected {\n\tbackground: url('img/alarm_selected.png') center no-repeat;\n\tbackground-size: 24px 24px;\n}\n\n#menu .timer.selected {\n\tbackground: url('img/timer_selected.png') center no-repeat;\n\tbackground-size: 24px 24px;\n}\n\n#menu .stopwatch.selected {\n\tbackground: url('img/stopwatch_selected.png') center no-repeat;\n\tbackground-size: 24px 24px;\n}\n\n\n\n.hidden {\n\tdisplay: none;\n}\n\n#tiptip_holder {\n\tdisplay: none;\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tz-index: 99999;\n}\n\n#tiptip_holder.tip_top {\n\tpadding-bottom: 5px;\n}\n\n#tiptip_holder.tip_bottom {\n\tpadding-top: 5px;\n}\n\n#tiptip_holder.tip_right {\n\tpadding-left: 5px;\n}\n\n#tiptip_holder.tip_left {\n\tpadding-right: 5px;\n}\n\n#tiptip_content {\n\tfont-size: 10px;\n\tfont-weight: 600;\n\tcolor: #999;\n}\n\n#tiptip_arrow,\n#tiptip_arrow_inner {\n\tdisplay: none;\n}\n\n#tiptip_holder.tip_top #tiptip_arrow {\n\tdisplay: none;\n}\n\n#tiptip_holder.tip_bottom #tiptip_arrow {\n\tdisplay: none;\n}\n\n#tiptip_holder.tip_right #tiptip_arrow {\n\tdisplay: none;\n}\n\n#tiptip_holder.tip_left #tiptip_arrow {\n\tdisplay: none;\n}\n\n#tiptip_holder.tip_top #tiptip_arrow_inner {\n\tdisplay: none;\n}\n\n#tiptip_holder.tip_bottom #tiptip_arrow_inner {\n\tdisplay: none;\n}\n\n#tiptip_holder.tip_right #tiptip_arrow_inner {\n\tdisplay: none;\n}\n\n#tiptip_holder.tip_left #tiptip_arrow_inner {\n\tdisplay: none;\n}\n"
  },
  {
    "path": "_archive/apps/samples/clock/tests/clock_test.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n    <title>World Clock Chrome App</title>\n    <script type=\"text/javascript\" src=\"lib/right.js\"></script>\n    <script type=\"text/javascript\" src=\"../lib/jquery-1.7.2.min.js\"></script>\n    <script type=\"text/javascript\" src=\"../lib/tipTipv13/jquery.tipTip.minified.js\"></script>\n    <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/git/qunit.js\"></script>\n    <script type=\"text/javascript\" src=\"../clock.js\"></script>\n    <script type=\"text/javascript\" src=\"../alarm.js\"></script>\n    <script type=\"text/javascript\" src=\"../timer.js\"></script>\n    <script type=\"text/javascript\" src=\"../stopwatch.js\"></script>\n    <script type=\"text/javascript\" src=\"../script.js\"></script>\n    <script type=\"text/javascript\" src=\"clock_test.js\"></script>\n\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"http://code.jquery.com/qunit/git/qunit.css\">\n  </head>\n\n  <body>\n    <h1 id=\"qunit-header\">World Clock Tests</h1>\n    <h2 id=\"qunit-banner\"></h2>\n    <div id=\"qunit-testrunner-toolbar\"></div>\n    <h2 id=\"qunit-userAgent\"></h2>\n    <ol id=\"qunit-tests\"></ol>\n\n    <div id=\"qunit-fixture\">\n      <div class=\"world\"><div class=\"clock-id\"><div class=\"clock\"></div></div></div>\n    </div>\n\n</body>\n</html>\n\n\n\n\n"
  },
  {
    "path": "_archive/apps/samples/clock/tests/clock_test.js",
    "content": "chrome = {};\nchrome.storage = {};\nchrome.storage.sync = {};\nstorage_get_called = false;\nstorage_set_called = false;\n\nchrome.storage.sync.get = function() {\n  storage_get_called = true;\n}\n\nchrome.storage.sync.set = function(items) {\n  storage_set_called = true;\n  storage_items = items;\n}\n\nvar Context = new Class({\n  initialize: function($canvasElem) {\n    this._ctx = $canvasElem._.getContext('2d');\n\n    this._calls = []; // names/args of recorded calls\n\n    this._initMethods();\n  },\n  _initMethods: function() {\n    // define methods to test here\n    // no way to introspect so we have to do some extra work :(\n    var methods = {\n      fill: function() {\n        this._ctx.fill();\n      },\n      lineTo: function(x, y) {\n        this._ctx.lineTo(x, y);\n      },\n      moveTo: function(x, y) {\n        this._ctx.moveTo(x, y);\n      },\n      stroke: function() {\n        this._ctx.stroke();\n      }\n      // and so on\n    };\n\n    // attach methods to the class itself\n    var scope = this;\n    var addMethod = function(name, method) {\n      scope[methodName] = function() {\n        scope.record(name, arguments);\n        method.apply(scope, arguments);\n      };\n    }\n\n    for(var methodName in methods) {\n      var method = methods[methodName];\n      addMethod(methodName, method);\n    }\n  },\n  assign: function(k, v) {\n    this._ctx[k] = v;\n  },\n  record: function(methodName, args) {\n    this._calls.push({name: methodName, args: args});\n  },\n  getCalls: function() {\n    return this._calls;\n  }\n  // TODO: expand API as needed\n});\n\n\n$(document).ready(function() {\n\n  module(\"Initialization\");\n\n    test(\"Get Chrome Storage\", function() {\n      expect(1);\n      ok(storage_get_called);\n    });\n\n  module(\"Clock\");\n\n\n});\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "_archive/apps/samples/clock/tests/lib/prototype.js",
    "content": "/*  Prototype JavaScript framework, version 1.7.1\n *  (c) 2005-2010 Sam Stephenson\n *\n *  Prototype is freely distributable under the terms of an MIT-style license.\n *  For details, see the Prototype web site: http://www.prototypejs.org/\n *\n *--------------------------------------------------------------------------*/\n\nvar Prototype = {\n\n  Version: '1.7.1',\n\n  Browser: (function(){\n    var ua = navigator.userAgent;\n    var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';\n    return {\n      IE:             !!window.attachEvent && !isOpera,\n      Opera:          isOpera,\n      WebKit:         ua.indexOf('AppleWebKit/') > -1,\n      Gecko:          ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,\n      MobileSafari:   /Apple.*Mobile/.test(ua)\n    }\n  })(),\n\n  BrowserFeatures: {\n    XPath: !!document.evaluate,\n\n    SelectorsAPI: !!document.querySelector,\n\n    ElementExtensions: (function() {\n      var constructor = window.Element || window.HTMLElement;\n      return !!(constructor && constructor.prototype);\n    })(),\n    SpecificElementExtensions: (function() {\n      if (typeof window.HTMLDivElement !== 'undefined')\n        return true;\n\n      var div = document.createElement('div'),\n          form = document.createElement('form'),\n          isSupported = false;\n\n      if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {\n        isSupported = true;\n      }\n\n      div = form = null;\n\n      return isSupported;\n    })()\n  },\n\n  ScriptFragment: '<script[^>]*>([\\\\S\\\\s]*?)<\\/script\\\\s*>',\n  JSONFilter: /^\\/\\*-secure-([\\s\\S]*)\\*\\/\\s*$/,\n\n  emptyFunction: function() { },\n\n  K: function(x) { return x }\n};\n\nif (Prototype.Browser.MobileSafari)\n  Prototype.BrowserFeatures.SpecificElementExtensions = false;\n/* Based on Alex Arnell's inheritance implementation. */\n\nvar Class = (function() {\n\n  var IS_DONTENUM_BUGGY = (function(){\n    for (var p in { toString: 1 }) {\n      if (p === 'toString') return false;\n    }\n    return true;\n  })();\n\n  function subclass() {};\n  function create() {\n    var parent = null, properties = $A(arguments);\n    if (Object.isFunction(properties[0]))\n      parent = properties.shift();\n\n    function klass() {\n      this.initialize.apply(this, arguments);\n    }\n\n    Object.extend(klass, Class.Methods);\n    klass.superclass = parent;\n    klass.subclasses = [];\n\n    if (parent) {\n      subclass.prototype = parent.prototype;\n      klass.prototype = new subclass;\n      parent.subclasses.push(klass);\n    }\n\n    for (var i = 0, length = properties.length; i < length; i++)\n      klass.addMethods(properties[i]);\n\n    if (!klass.prototype.initialize)\n      klass.prototype.initialize = Prototype.emptyFunction;\n\n    klass.prototype.constructor = klass;\n    return klass;\n  }\n\n  function addMethods(source) {\n    var ancestor   = this.superclass && this.superclass.prototype,\n        properties = Object.keys(source);\n\n    if (IS_DONTENUM_BUGGY) {\n      if (source.toString != Object.prototype.toString)\n        properties.push(\"toString\");\n      if (source.valueOf != Object.prototype.valueOf)\n        properties.push(\"valueOf\");\n    }\n\n    for (var i = 0, length = properties.length; i < length; i++) {\n      var property = properties[i], value = source[property];\n      if (ancestor && Object.isFunction(value) &&\n          value.argumentNames()[0] == \"$super\") {\n        var method = value;\n        value = (function(m) {\n          return function() { return ancestor[m].apply(this, arguments); };\n        })(property).wrap(method);\n\n        value.valueOf = (function(method) {\n          return function() { return method.valueOf.call(method); };\n        })(method);\n\n        value.toString = (function(method) {\n          return function() { return method.toString.call(method); };\n        })(method);\n      }\n      this.prototype[property] = value;\n    }\n\n    return this;\n  }\n\n  return {\n    create: create,\n    Methods: {\n      addMethods: addMethods\n    }\n  };\n})();\n(function() {\n\n  var _toString = Object.prototype.toString,\n      _hasOwnProperty = Object.prototype.hasOwnProperty,\n      NULL_TYPE = 'Null',\n      UNDEFINED_TYPE = 'Undefined',\n      BOOLEAN_TYPE = 'Boolean',\n      NUMBER_TYPE = 'Number',\n      STRING_TYPE = 'String',\n      OBJECT_TYPE = 'Object',\n      FUNCTION_CLASS = '[object Function]',\n      BOOLEAN_CLASS = '[object Boolean]',\n      NUMBER_CLASS = '[object Number]',\n      STRING_CLASS = '[object String]',\n      ARRAY_CLASS = '[object Array]',\n      DATE_CLASS = '[object Date]',\n      NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&\n        typeof JSON.stringify === 'function' &&\n        JSON.stringify(0) === '0' &&\n        typeof JSON.stringify(Prototype.K) === 'undefined';\n\n\n\n  var DONT_ENUMS = ['toString', 'toLocaleString', 'valueOf',\n   'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'constructor'];\n\n  var IS_DONTENUM_BUGGY = (function(){\n    for (var p in { toString: 1 }) {\n      if (p === 'toString') return false;\n    }\n    return true;\n  })();\n\n  function Type(o) {\n    switch(o) {\n      case null: return NULL_TYPE;\n      case (void 0): return UNDEFINED_TYPE;\n    }\n    var type = typeof o;\n    switch(type) {\n      case 'boolean': return BOOLEAN_TYPE;\n      case 'number':  return NUMBER_TYPE;\n      case 'string':  return STRING_TYPE;\n    }\n    return OBJECT_TYPE;\n  }\n\n  function extend(destination, source) {\n    for (var property in source)\n      destination[property] = source[property];\n    return destination;\n  }\n\n  function inspect(object) {\n    try {\n      if (isUndefined(object)) return 'undefined';\n      if (object === null) return 'null';\n      return object.inspect ? object.inspect() : String(object);\n    } catch (e) {\n      if (e instanceof RangeError) return '...';\n      throw e;\n    }\n  }\n\n  function toJSON(value) {\n    return Str('', { '': value }, []);\n  }\n\n  function Str(key, holder, stack) {\n    var value = holder[key];\n    if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') {\n      value = value.toJSON(key);\n    }\n\n    var _class = _toString.call(value);\n\n    switch (_class) {\n      case NUMBER_CLASS:\n      case BOOLEAN_CLASS:\n      case STRING_CLASS:\n        value = value.valueOf();\n    }\n\n    switch (value) {\n      case null: return 'null';\n      case true: return 'true';\n      case false: return 'false';\n    }\n\n    var type = typeof value;\n    switch (type) {\n      case 'string':\n        return value.inspect(true);\n      case 'number':\n        return isFinite(value) ? String(value) : 'null';\n      case 'object':\n\n        for (var i = 0, length = stack.length; i < length; i++) {\n          if (stack[i] === value) {\n            throw new TypeError(\"Cyclic reference to '\" + value + \"' in object\");\n          }\n        }\n        stack.push(value);\n\n        var partial = [];\n        if (_class === ARRAY_CLASS) {\n          for (var i = 0, length = value.length; i < length; i++) {\n            var str = Str(i, value, stack);\n            partial.push(typeof str === 'undefined' ? 'null' : str);\n          }\n          partial = '[' + partial.join(',') + ']';\n        } else {\n          var keys = Object.keys(value);\n          for (var i = 0, length = keys.length; i < length; i++) {\n            var key = keys[i], str = Str(key, value, stack);\n            if (typeof str !== \"undefined\") {\n               partial.push(key.inspect(true)+ ':' + str);\n             }\n          }\n          partial = '{' + partial.join(',') + '}';\n        }\n        stack.pop();\n        return partial;\n    }\n  }\n\n  function stringify(object) {\n    return JSON.stringify(object);\n  }\n\n  function toQueryString(object) {\n    return $H(object).toQueryString();\n  }\n\n  function toHTML(object) {\n    return object && object.toHTML ? object.toHTML() : String.interpret(object);\n  }\n\n  function keys(object) {\n    if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }\n    var results = [];\n    for (var property in object) {\n      if (_hasOwnProperty.call(object, property))\n        results.push(property);\n    }\n\n    if (IS_DONTENUM_BUGGY) {\n      for (var i = 0; property = DONT_ENUMS[i]; i++) {\n        if (_hasOwnProperty.call(object, property))\n          results.push(property);\n      }\n    }\n\n    return results;\n  }\n\n  function values(object) {\n    var results = [];\n    for (var property in object)\n      results.push(object[property]);\n    return results;\n  }\n\n  function clone(object) {\n    return extend({ }, object);\n  }\n\n  function isElement(object) {\n    return !!(object && object.nodeType == 1);\n  }\n\n  function isArray(object) {\n    return _toString.call(object) === ARRAY_CLASS;\n  }\n\n  var hasNativeIsArray = (typeof Array.isArray == 'function')\n    && Array.isArray([]) && !Array.isArray({});\n\n  if (hasNativeIsArray) {\n    isArray = Array.isArray;\n  }\n\n  function isHash(object) {\n    return object instanceof Hash;\n  }\n\n  function isFunction(object) {\n    return _toString.call(object) === FUNCTION_CLASS;\n  }\n\n  function isString(object) {\n    return _toString.call(object) === STRING_CLASS;\n  }\n\n  function isNumber(object) {\n    return _toString.call(object) === NUMBER_CLASS;\n  }\n\n  function isDate(object) {\n    return _toString.call(object) === DATE_CLASS;\n  }\n\n  function isUndefined(object) {\n    return typeof object === \"undefined\";\n  }\n\n  extend(Object, {\n    extend:        extend,\n    inspect:       inspect,\n    toJSON:        NATIVE_JSON_STRINGIFY_SUPPORT ? stringify : toJSON,\n    toQueryString: toQueryString,\n    toHTML:        toHTML,\n    keys:          Object.keys || keys,\n    values:        values,\n    clone:         clone,\n    isElement:     isElement,\n    isArray:       isArray,\n    isHash:        isHash,\n    isFunction:    isFunction,\n    isString:      isString,\n    isNumber:      isNumber,\n    isDate:        isDate,\n    isUndefined:   isUndefined\n  });\n})();\nObject.extend(Function.prototype, (function() {\n  var slice = Array.prototype.slice;\n\n  function update(array, args) {\n    var arrayLength = array.length, length = args.length;\n    while (length--) array[arrayLength + length] = args[length];\n    return array;\n  }\n\n  function merge(array, args) {\n    array = slice.call(array, 0);\n    return update(array, args);\n  }\n\n  function argumentNames() {\n    var names = this.toString().match(/^[\\s\\(]*function[^(]*\\(([^)]*)\\)/)[1]\n      .replace(/\\/\\/.*?[\\r\\n]|\\/\\*(?:.|[\\r\\n])*?\\*\\//g, '')\n      .replace(/\\s+/g, '').split(',');\n    return names.length == 1 && !names[0] ? [] : names;\n  }\n\n\n  function bind(context) {\n    if (arguments.length < 2 && Object.isUndefined(arguments[0]))\n      return this;\n\n    if (!Object.isFunction(this))\n      throw new TypeError(\"The object is not callable.\");\n\n    var nop = function() {};\n    var __method = this, args = slice.call(arguments, 1);\n\n    var bound = function() {\n      var a = merge(args, arguments), c = context;\n      var c = this instanceof bound ? this : context;\n      return __method.apply(c, a);\n    };\n\n    nop.prototype   = this.prototype;\n    bound.prototype = new nop();\n\n    return bound;\n  }\n\n  function bindAsEventListener(context) {\n    var __method = this, args = slice.call(arguments, 1);\n    return function(event) {\n      var a = update([event || window.event], args);\n      return __method.apply(context, a);\n    }\n  }\n\n  function curry() {\n    if (!arguments.length) return this;\n    var __method = this, args = slice.call(arguments, 0);\n    return function() {\n      var a = merge(args, arguments);\n      return __method.apply(this, a);\n    }\n  }\n\n  function delay(timeout) {\n    var __method = this, args = slice.call(arguments, 1);\n    timeout = timeout * 1000;\n    return window.setTimeout(function() {\n      return __method.apply(__method, args);\n    }, timeout);\n  }\n\n  function defer() {\n    var args = update([0.01], arguments);\n    return this.delay.apply(this, args);\n  }\n\n  function wrap(wrapper) {\n    var __method = this;\n    return function() {\n      var a = update([__method.bind(this)], arguments);\n      return wrapper.apply(this, a);\n    }\n  }\n\n  function methodize() {\n    if (this._methodized) return this._methodized;\n    var __method = this;\n    return this._methodized = function() {\n      var a = update([this], arguments);\n      return __method.apply(null, a);\n    };\n  }\n\n  var extensions = {\n    argumentNames:       argumentNames,\n    bindAsEventListener: bindAsEventListener,\n    curry:               curry,\n    delay:               delay,\n    defer:               defer,\n    wrap:                wrap,\n    methodize:           methodize\n  };\n\n  if (!Function.prototype.bind)\n    extensions.bind = bind;\n\n  return extensions;\n})());\n\n\n\n(function(proto) {\n\n\n  function toISOString() {\n    return this.getUTCFullYear() + '-' +\n      (this.getUTCMonth() + 1).toPaddedString(2) + '-' +\n      this.getUTCDate().toPaddedString(2) + 'T' +\n      this.getUTCHours().toPaddedString(2) + ':' +\n      this.getUTCMinutes().toPaddedString(2) + ':' +\n      this.getUTCSeconds().toPaddedString(2) + 'Z';\n  }\n\n\n  function toJSON() {\n    return this.toISOString();\n  }\n\n  if (!proto.toISOString) proto.toISOString = toISOString;\n  if (!proto.toJSON) proto.toJSON = toJSON;\n\n})(Date.prototype);\n\n\nRegExp.prototype.match = RegExp.prototype.test;\n\nRegExp.escape = function(str) {\n  return String(str).replace(/([.*+?^=!:${}()|[\\]\\/\\\\])/g, '\\\\$1');\n};\nvar PeriodicalExecuter = Class.create({\n  initialize: function(callback, frequency) {\n    this.callback = callback;\n    this.frequency = frequency;\n    this.currentlyExecuting = false;\n\n    this.registerCallback();\n  },\n\n  registerCallback: function() {\n    this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);\n  },\n\n  execute: function() {\n    this.callback(this);\n  },\n\n  stop: function() {\n    if (!this.timer) return;\n    clearInterval(this.timer);\n    this.timer = null;\n  },\n\n  onTimerEvent: function() {\n    if (!this.currentlyExecuting) {\n      try {\n        this.currentlyExecuting = true;\n        this.execute();\n        this.currentlyExecuting = false;\n      } catch(e) {\n        this.currentlyExecuting = false;\n        throw e;\n      }\n    }\n  }\n});\nObject.extend(String, {\n  interpret: function(value) {\n    return value == null ? '' : String(value);\n  },\n  specialChar: {\n    '\\b': '\\\\b',\n    '\\t': '\\\\t',\n    '\\n': '\\\\n',\n    '\\f': '\\\\f',\n    '\\r': '\\\\r',\n    '\\\\': '\\\\\\\\'\n  }\n});\n\nObject.extend(String.prototype, (function() {\n  var NATIVE_JSON_PARSE_SUPPORT = window.JSON &&\n    typeof JSON.parse === 'function' &&\n    JSON.parse('{\"test\": true}').test;\n\n  function prepareReplacement(replacement) {\n    if (Object.isFunction(replacement)) return replacement;\n    var template = new Template(replacement);\n    return function(match) { return template.evaluate(match) };\n  }\n\n  function gsub(pattern, replacement) {\n    var result = '', source = this, match;\n    replacement = prepareReplacement(replacement);\n\n    if (Object.isString(pattern))\n      pattern = RegExp.escape(pattern);\n\n    if (!(pattern.length || pattern.source)) {\n      replacement = replacement('');\n      return replacement + source.split('').join(replacement) + replacement;\n    }\n\n    while (source.length > 0) {\n      if (match = source.match(pattern)) {\n        result += source.slice(0, match.index);\n        result += String.interpret(replacement(match));\n        source  = source.slice(match.index + match[0].length);\n      } else {\n        result += source, source = '';\n      }\n    }\n    return result;\n  }\n\n  function sub(pattern, replacement, count) {\n    replacement = prepareReplacement(replacement);\n    count = Object.isUndefined(count) ? 1 : count;\n\n    return this.gsub(pattern, function(match) {\n      if (--count < 0) return match[0];\n      return replacement(match);\n    });\n  }\n\n  function scan(pattern, iterator) {\n    this.gsub(pattern, iterator);\n    return String(this);\n  }\n\n  function truncate(length, truncation) {\n    length = length || 30;\n    truncation = Object.isUndefined(truncation) ? '...' : truncation;\n    return this.length > length ?\n      this.slice(0, length - truncation.length) + truncation : String(this);\n  }\n\n  function strip() {\n    return this.replace(/^\\s+/, '').replace(/\\s+$/, '');\n  }\n\n  function stripTags() {\n    return this.replace(/<\\w+(\\s+(\"[^\"]*\"|'[^']*'|[^>])+)?>|<\\/\\w+>/gi, '');\n  }\n\n  function stripScripts() {\n    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');\n  }\n\n  function extractScripts() {\n    var matchAll = new RegExp(Prototype.ScriptFragment, 'img'),\n        matchOne = new RegExp(Prototype.ScriptFragment, 'im');\n    return (this.match(matchAll) || []).map(function(scriptTag) {\n      return (scriptTag.match(matchOne) || ['', ''])[1];\n    });\n  }\n\n  function evalScripts() {\n    return this.extractScripts().map(function(script) { return eval(script); });\n  }\n\n  function escapeHTML() {\n    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n  }\n\n  function unescapeHTML() {\n    return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');\n  }\n\n\n  function toQueryParams(separator) {\n    var match = this.strip().match(/([^?#]*)(#.*)?$/);\n    if (!match) return { };\n\n    return match[1].split(separator || '&').inject({ }, function(hash, pair) {\n      if ((pair = pair.split('='))[0]) {\n        var key = decodeURIComponent(pair.shift()),\n            value = pair.length > 1 ? pair.join('=') : pair[0];\n\n        if (value != undefined) value = decodeURIComponent(value);\n\n        if (key in hash) {\n          if (!Object.isArray(hash[key])) hash[key] = [hash[key]];\n          hash[key].push(value);\n        }\n        else hash[key] = value;\n      }\n      return hash;\n    });\n  }\n\n  function toArray() {\n    return this.split('');\n  }\n\n  function succ() {\n    return this.slice(0, this.length - 1) +\n      String.fromCharCode(this.charCodeAt(this.length - 1) + 1);\n  }\n\n  function times(count) {\n    return count < 1 ? '' : new Array(count + 1).join(this);\n  }\n\n  function camelize() {\n    return this.replace(/-+(.)?/g, function(match, chr) {\n      return chr ? chr.toUpperCase() : '';\n    });\n  }\n\n  function capitalize() {\n    return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();\n  }\n\n  function underscore() {\n    return this.replace(/::/g, '/')\n               .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')\n               .replace(/([a-z\\d])([A-Z])/g, '$1_$2')\n               .replace(/-/g, '_')\n               .toLowerCase();\n  }\n\n  function dasherize() {\n    return this.replace(/_/g, '-');\n  }\n\n  function inspect(useDoubleQuotes) {\n    var escapedString = this.replace(/[\\x00-\\x1f\\\\]/g, function(character) {\n      if (character in String.specialChar) {\n        return String.specialChar[character];\n      }\n      return '\\\\u00' + character.charCodeAt().toPaddedString(2, 16);\n    });\n    if (useDoubleQuotes) return '\"' + escapedString.replace(/\"/g, '\\\\\"') + '\"';\n    return \"'\" + escapedString.replace(/'/g, '\\\\\\'') + \"'\";\n  }\n\n  function unfilterJSON(filter) {\n    return this.replace(filter || Prototype.JSONFilter, '$1');\n  }\n\n  function isJSON() {\n    var str = this;\n    if (str.blank()) return false;\n    str = str.replace(/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');\n    str = str.replace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g, ']');\n    str = str.replace(/(?:^|:|,)(?:\\s*\\[)+/g, '');\n    return (/^[\\],:{}\\s]*$/).test(str);\n  }\n\n  function evalJSON(sanitize) {\n    var json = this.unfilterJSON(),\n        cx = /[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g;\n    if (cx.test(json)) {\n      json = json.replace(cx, function (a) {\n        return '\\\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\n      });\n    }\n    try {\n      if (!sanitize || json.isJSON()) return eval('(' + json + ')');\n    } catch (e) { }\n    throw new SyntaxError('Badly formed JSON string: ' + this.inspect());\n  }\n\n  function parseJSON() {\n    var json = this.unfilterJSON();\n    return JSON.parse(json);\n  }\n\n  function include(pattern) {\n    return this.indexOf(pattern) > -1;\n  }\n\n  function startsWith(pattern) {\n    return this.lastIndexOf(pattern, 0) === 0;\n  }\n\n  function endsWith(pattern) {\n    var d = this.length - pattern.length;\n    return d >= 0 && this.indexOf(pattern, d) === d;\n  }\n\n  function empty() {\n    return this == '';\n  }\n\n  function blank() {\n    return /^\\s*$/.test(this);\n  }\n\n  function interpolate(object, pattern) {\n    return new Template(this, pattern).evaluate(object);\n  }\n\n  return {\n    gsub:           gsub,\n    sub:            sub,\n    scan:           scan,\n    truncate:       truncate,\n    strip:          String.prototype.trim || strip,\n    stripTags:      stripTags,\n    stripScripts:   stripScripts,\n    extractScripts: extractScripts,\n    evalScripts:    evalScripts,\n    escapeHTML:     escapeHTML,\n    unescapeHTML:   unescapeHTML,\n    toQueryParams:  toQueryParams,\n    parseQuery:     toQueryParams,\n    toArray:        toArray,\n    succ:           succ,\n    times:          times,\n    camelize:       camelize,\n    capitalize:     capitalize,\n    underscore:     underscore,\n    dasherize:      dasherize,\n    inspect:        inspect,\n    unfilterJSON:   unfilterJSON,\n    isJSON:         isJSON,\n    evalJSON:       NATIVE_JSON_PARSE_SUPPORT ? parseJSON : evalJSON,\n    include:        include,\n    startsWith:     startsWith,\n    endsWith:       endsWith,\n    empty:          empty,\n    blank:          blank,\n    interpolate:    interpolate\n  };\n})());\n\nvar Template = Class.create({\n  initialize: function(template, pattern) {\n    this.template = template.toString();\n    this.pattern = pattern || Template.Pattern;\n  },\n\n  evaluate: function(object) {\n    if (object && Object.isFunction(object.toTemplateReplacements))\n      object = object.toTemplateReplacements();\n\n    return this.template.gsub(this.pattern, function(match) {\n      if (object == null) return (match[1] + '');\n\n      var before = match[1] || '';\n      if (before == '\\\\') return match[2];\n\n      var ctx = object, expr = match[3],\n          pattern = /^([^.[]+|\\[((?:.*?[^\\\\])?)\\])(\\.|\\[|$)/;\n\n      match = pattern.exec(expr);\n      if (match == null) return before;\n\n      while (match != null) {\n        var comp = match[1].startsWith('[') ? match[2].replace(/\\\\\\\\]/g, ']') : match[1];\n        ctx = ctx[comp];\n        if (null == ctx || '' == match[3]) break;\n        expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);\n        match = pattern.exec(expr);\n      }\n\n      return before + String.interpret(ctx);\n    });\n  }\n});\nTemplate.Pattern = /(^|.|\\r|\\n)(#\\{(.*?)\\})/;\n\nvar $break = { };\n\nvar Enumerable = (function() {\n  function each(iterator, context) {\n    try {\n      this._each(iterator, context);\n    } catch (e) {\n      if (e != $break) throw e;\n    }\n    return this;\n  }\n\n  function eachSlice(number, iterator, context) {\n    var index = -number, slices = [], array = this.toArray();\n    if (number < 1) return array;\n    while ((index += number) < array.length)\n      slices.push(array.slice(index, index+number));\n    return slices.collect(iterator, context);\n  }\n\n  function all(iterator, context) {\n    iterator = iterator || Prototype.K;\n    var result = true;\n    this.each(function(value, index) {\n      result = result && !!iterator.call(context, value, index, this);\n      if (!result) throw $break;\n    }, this);\n    return result;\n  }\n\n  function any(iterator, context) {\n    iterator = iterator || Prototype.K;\n    var result = false;\n    this.each(function(value, index) {\n      if (result = !!iterator.call(context, value, index, this))\n        throw $break;\n    }, this);\n    return result;\n  }\n\n  function collect(iterator, context) {\n    iterator = iterator || Prototype.K;\n    var results = [];\n    this.each(function(value, index) {\n      results.push(iterator.call(context, value, index, this));\n    }, this);\n    return results;\n  }\n\n  function detect(iterator, context) {\n    var result;\n    this.each(function(value, index) {\n      if (iterator.call(context, value, index, this)) {\n        result = value;\n        throw $break;\n      }\n    }, this);\n    return result;\n  }\n\n  function findAll(iterator, context) {\n    var results = [];\n    this.each(function(value, index) {\n      if (iterator.call(context, value, index, this))\n        results.push(value);\n    }, this);\n    return results;\n  }\n\n  function grep(filter, iterator, context) {\n    iterator = iterator || Prototype.K;\n    var results = [];\n\n    if (Object.isString(filter))\n      filter = new RegExp(RegExp.escape(filter));\n\n    this.each(function(value, index) {\n      if (filter.match(value))\n        results.push(iterator.call(context, value, index, this));\n    }, this);\n    return results;\n  }\n\n  function include(object) {\n    if (Object.isFunction(this.indexOf))\n      if (this.indexOf(object) != -1) return true;\n\n    var found = false;\n    this.each(function(value) {\n      if (value == object) {\n        found = true;\n        throw $break;\n      }\n    });\n    return found;\n  }\n\n  function inGroupsOf(number, fillWith) {\n    fillWith = Object.isUndefined(fillWith) ? null : fillWith;\n    return this.eachSlice(number, function(slice) {\n      while(slice.length < number) slice.push(fillWith);\n      return slice;\n    });\n  }\n\n  function inject(memo, iterator, context) {\n    this.each(function(value, index) {\n      memo = iterator.call(context, memo, value, index, this);\n    }, this);\n    return memo;\n  }\n\n  function invoke(method) {\n    var args = $A(arguments).slice(1);\n    return this.map(function(value) {\n      return value[method].apply(value, args);\n    });\n  }\n\n  function max(iterator, context) {\n    iterator = iterator || Prototype.K;\n    var result;\n    this.each(function(value, index) {\n      value = iterator.call(context, value, index, this);\n      if (result == null || value >= result)\n        result = value;\n    }, this);\n    return result;\n  }\n\n  function min(iterator, context) {\n    iterator = iterator || Prototype.K;\n    var result;\n    this.each(function(value, index) {\n      value = iterator.call(context, value, index, this);\n      if (result == null || value < result)\n        result = value;\n    }, this);\n    return result;\n  }\n\n  function partition(iterator, context) {\n    iterator = iterator || Prototype.K;\n    var trues = [], falses = [];\n    this.each(function(value, index) {\n      (iterator.call(context, value, index, this) ?\n        trues : falses).push(value);\n    }, this);\n    return [trues, falses];\n  }\n\n  function pluck(property) {\n    var results = [];\n    this.each(function(value) {\n      results.push(value[property]);\n    });\n    return results;\n  }\n\n  function reject(iterator, context) {\n    var results = [];\n    this.each(function(value, index) {\n      if (!iterator.call(context, value, index, this))\n        results.push(value);\n    }, this);\n    return results;\n  }\n\n  function sortBy(iterator, context) {\n    return this.map(function(value, index) {\n      return {\n        value: value,\n        criteria: iterator.call(context, value, index, this)\n      };\n    }, this).sort(function(left, right) {\n      var a = left.criteria, b = right.criteria;\n      return a < b ? -1 : a > b ? 1 : 0;\n    }).pluck('value');\n  }\n\n  function toArray() {\n    return this.map();\n  }\n\n  function zip() {\n    var iterator = Prototype.K, args = $A(arguments);\n    if (Object.isFunction(args.last()))\n      iterator = args.pop();\n\n    var collections = [this].concat(args).map($A);\n    return this.map(function(value, index) {\n      return iterator(collections.pluck(index));\n    });\n  }\n\n  function size() {\n    return this.toArray().length;\n  }\n\n  function inspect() {\n    return '#<Enumerable:' + this.toArray().inspect() + '>';\n  }\n\n\n\n\n\n\n\n\n\n  return {\n    each:       each,\n    eachSlice:  eachSlice,\n    all:        all,\n    every:      all,\n    any:        any,\n    some:       any,\n    collect:    collect,\n    map:        collect,\n    detect:     detect,\n    findAll:    findAll,\n    select:     findAll,\n    filter:     findAll,\n    grep:       grep,\n    include:    include,\n    member:     include,\n    inGroupsOf: inGroupsOf,\n    inject:     inject,\n    invoke:     invoke,\n    max:        max,\n    min:        min,\n    partition:  partition,\n    pluck:      pluck,\n    reject:     reject,\n    sortBy:     sortBy,\n    toArray:    toArray,\n    entries:    toArray,\n    zip:        zip,\n    size:       size,\n    inspect:    inspect,\n    find:       detect\n  };\n})();\n\nfunction $A(iterable) {\n  if (!iterable) return [];\n  if ('toArray' in Object(iterable)) return iterable.toArray();\n  var length = iterable.length || 0, results = new Array(length);\n  while (length--) results[length] = iterable[length];\n  return results;\n}\n\n\nfunction $w(string) {\n  if (!Object.isString(string)) return [];\n  string = string.strip();\n  return string ? string.split(/\\s+/) : [];\n}\n\nArray.from = $A;\n\n\n(function() {\n  var arrayProto = Array.prototype,\n      slice = arrayProto.slice,\n      _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available\n\n  function each(iterator, context) {\n    for (var i = 0, length = this.length >>> 0; i < length; i++) {\n      if (i in this) iterator.call(context, this[i], i, this);\n    }\n  }\n  if (!_each) _each = each;\n\n  function clear() {\n    this.length = 0;\n    return this;\n  }\n\n  function first() {\n    return this[0];\n  }\n\n  function last() {\n    return this[this.length - 1];\n  }\n\n  function compact() {\n    return this.select(function(value) {\n      return value != null;\n    });\n  }\n\n  function flatten() {\n    return this.inject([], function(array, value) {\n      if (Object.isArray(value))\n        return array.concat(value.flatten());\n      array.push(value);\n      return array;\n    });\n  }\n\n  function without() {\n    var values = slice.call(arguments, 0);\n    return this.select(function(value) {\n      return !values.include(value);\n    });\n  }\n\n  function reverse(inline) {\n    return (inline === false ? this.toArray() : this)._reverse();\n  }\n\n  function uniq(sorted) {\n    return this.inject([], function(array, value, index) {\n      if (0 == index || (sorted ? array.last() != value : !array.include(value)))\n        array.push(value);\n      return array;\n    });\n  }\n\n  function intersect(array) {\n    return this.uniq().findAll(function(item) {\n      return array.indexOf(item) !== -1;\n    });\n  }\n\n\n  function clone() {\n    return slice.call(this, 0);\n  }\n\n  function size() {\n    return this.length;\n  }\n\n  function inspect() {\n    return '[' + this.map(Object.inspect).join(', ') + ']';\n  }\n\n  function indexOf(item, i) {\n    if (this == null) throw new TypeError();\n\n    var array = Object(this), length = array.length >>> 0;\n    if (length === 0) return -1;\n\n    i = Number(i);\n    if (isNaN(i)) {\n      i = 0;\n    } else if (i !== 0 && isFinite(i)) {\n      i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));\n    }\n\n    if (i > length) return -1;\n\n    var k = i >= 0 ? i : Math.max(length - Math.abs(i), 0);\n    for (; k < length; k++)\n      if (k in array && array[k] === item) return k;\n    return -1;\n  }\n\n\n  function lastIndexOf(item, i) {\n    if (this == null) throw new TypeError();\n\n    var array = Object(this), length = array.length >>> 0;\n    if (length === 0) return -1;\n\n    if (!Object.isUndefined(i)) {\n      i = Number(i);\n      if (isNaN(i)) {\n        i = 0;\n      } else if (i !== 0 && isFinite(i)) {\n        i = (i > 0 ? 1 : -1) * Math.floor(Math.abs(i));\n      }\n    } else {\n      i = length;\n    }\n\n    var k = i >= 0 ? Math.min(i, length - 1) :\n     length - Math.abs(i);\n\n    for (; k >= 0; k--)\n      if (k in array && array[k] === item) return k;\n    return -1;\n  }\n\n  function concat(_) {\n    var array = [], items = slice.call(arguments, 0), item, n = 0;\n    items.unshift(this);\n    for (var i = 0, length = items.length; i < length; i++) {\n      item = items[i];\n      if (Object.isArray(item) && !('callee' in item)) {\n        for (var j = 0, arrayLength = item.length; j < arrayLength; j++) {\n          if (j in item) array[n] = item[j];\n          n++;\n        }\n      } else {\n        array[n++] = item;\n      }\n    }\n    array.length = n;\n    return array;\n  }\n\n\n  function wrapNative(method) {\n    return function() {\n      if (arguments.length === 0) {\n        return method.call(this, Prototype.K);\n      } else if (arguments[0] === undefined) {\n        var args = slice.call(arguments, 1);\n        args.unshift(Prototype.K);\n        return method.apply(this, args);\n      } else {\n        return method.apply(this, arguments);\n      }\n    };\n  }\n\n\n  function map(iterator) {\n    if (this == null) throw new TypeError();\n    iterator = iterator || Prototype.K;\n\n    var object = Object(this);\n    var results = [], context = arguments[1], n = 0;\n\n    for (var i = 0, length = object.length >>> 0; i < length; i++) {\n      if (i in object) {\n        results[n] = iterator.call(context, object[i], i, object);\n      }\n      n++;\n    }\n    results.length = n;\n    return results;\n  }\n\n  if (arrayProto.map) {\n    map = wrapNative(Array.prototype.map);\n  }\n\n  function filter(iterator) {\n    if (this == null || !Object.isFunction(iterator))\n      throw new TypeError();\n\n    var object = Object(this);\n    var results = [], context = arguments[1], value;\n\n    for (var i = 0, length = object.length >>> 0; i < length; i++) {\n      if (i in object) {\n        value = object[i];\n        if (iterator.call(context, value, i, object)) {\n          results.push(value);\n        }\n      }\n    }\n    return results;\n  }\n\n  if (arrayProto.filter) {\n    filter = Array.prototype.filter;\n  }\n\n  function some(iterator) {\n    if (this == null) throw new TypeError();\n    iterator = iterator || Prototype.K;\n    var context = arguments[1];\n\n    var object = Object(this);\n    for (var i = 0, length = object.length >>> 0; i < length; i++) {\n      if (i in object && iterator.call(context, object[i], i, object)) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  if (arrayProto.some) {\n    var some = wrapNative(Array.prototype.some);\n  }\n\n\n  function every(iterator) {\n    if (this == null) throw new TypeError();\n    iterator = iterator || Prototype.K;\n    var context = arguments[1];\n\n    var object = Object(this);\n    for (var i = 0, length = object.length >>> 0; i < length; i++) {\n      if (i in object && !iterator.call(context, object[i], i, object)) {\n        return false;\n      }\n    }\n\n    return true;\n  }\n\n  if (arrayProto.every) {\n    var every = wrapNative(Array.prototype.every);\n  }\n\n  var _reduce = arrayProto.reduce;\n  function inject(memo, iterator) {\n    iterator = iterator || Prototype.K;\n    var context = arguments[2];\n    return _reduce.call(this, iterator.bind(context), memo);\n  }\n\n  if (!arrayProto.reduce) {\n    var inject = Enumerable.inject;\n  }\n\n  Object.extend(arrayProto, Enumerable);\n\n  if (!arrayProto._reverse)\n    arrayProto._reverse = arrayProto.reverse;\n\n  Object.extend(arrayProto, {\n    _each:     _each,\n\n    map:       map,\n    collect:   map,\n    select:    filter,\n    filter:    filter,\n    findAll:   filter,\n    some:      some,\n    any:       some,\n    every:     every,\n    all:       every,\n    inject:    inject,\n\n    clear:     clear,\n    first:     first,\n    last:      last,\n    compact:   compact,\n    flatten:   flatten,\n    without:   without,\n    reverse:   reverse,\n    uniq:      uniq,\n    intersect: intersect,\n    clone:     clone,\n    toArray:   clone,\n    size:      size,\n    inspect:   inspect\n  });\n\n  var CONCAT_ARGUMENTS_BUGGY = (function() {\n    return [].concat(arguments)[0][0] !== 1;\n  })(1,2);\n\n  if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;\n\n  if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;\n  if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;\n})();\nfunction $H(object) {\n  return new Hash(object);\n};\n\nvar Hash = Class.create(Enumerable, (function() {\n  function initialize(object) {\n    this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);\n  }\n\n\n  function _each(iterator, context) {\n    for (var key in this._object) {\n      var value = this._object[key], pair = [key, value];\n      pair.key = key;\n      pair.value = value;\n      iterator.call(context, pair);\n    }\n  }\n\n  function set(key, value) {\n    return this._object[key] = value;\n  }\n\n  function get(key) {\n    if (this._object[key] !== Object.prototype[key])\n      return this._object[key];\n  }\n\n  function unset(key) {\n    var value = this._object[key];\n    delete this._object[key];\n    return value;\n  }\n\n  function toObject() {\n    return Object.clone(this._object);\n  }\n\n\n\n  function keys() {\n    return this.pluck('key');\n  }\n\n  function values() {\n    return this.pluck('value');\n  }\n\n  function index(value) {\n    var match = this.detect(function(pair) {\n      return pair.value === value;\n    });\n    return match && match.key;\n  }\n\n  function merge(object) {\n    return this.clone().update(object);\n  }\n\n  function update(object) {\n    return new Hash(object).inject(this, function(result, pair) {\n      result.set(pair.key, pair.value);\n      return result;\n    });\n  }\n\n  function toQueryPair(key, value) {\n    if (Object.isUndefined(value)) return key;\n\n    var value = String.interpret(value);\n\n    value = value.gsub(/(\\r)?\\n/, '\\r\\n');\n    value = encodeURIComponent(value);\n    value = value.gsub(/%20/, '+');\n    return key + '=' + value;\n  }\n\n  function toQueryString() {\n    return this.inject([], function(results, pair) {\n      var key = encodeURIComponent(pair.key), values = pair.value;\n\n      if (values && typeof values == 'object') {\n        if (Object.isArray(values)) {\n          var queryValues = [];\n          for (var i = 0, len = values.length, value; i < len; i++) {\n            value = values[i];\n            queryValues.push(toQueryPair(key, value));\n          }\n          return results.concat(queryValues);\n        }\n      } else results.push(toQueryPair(key, values));\n      return results;\n    }).join('&');\n  }\n\n  function inspect() {\n    return '#<Hash:{' + this.map(function(pair) {\n      return pair.map(Object.inspect).join(': ');\n    }).join(', ') + '}>';\n  }\n\n  function clone() {\n    return new Hash(this);\n  }\n\n  return {\n    initialize:             initialize,\n    _each:                  _each,\n    set:                    set,\n    get:                    get,\n    unset:                  unset,\n    toObject:               toObject,\n    toTemplateReplacements: toObject,\n    keys:                   keys,\n    values:                 values,\n    index:                  index,\n    merge:                  merge,\n    update:                 update,\n    toQueryString:          toQueryString,\n    inspect:                inspect,\n    toJSON:                 toObject,\n    clone:                  clone\n  };\n})());\n\nHash.from = $H;\nObject.extend(Number.prototype, (function() {\n  function toColorPart() {\n    return this.toPaddedString(2, 16);\n  }\n\n  function succ() {\n    return this + 1;\n  }\n\n  function times(iterator, context) {\n    $R(0, this, true).each(iterator, context);\n    return this;\n  }\n\n  function toPaddedString(length, radix) {\n    var string = this.toString(radix || 10);\n    return '0'.times(length - string.length) + string;\n  }\n\n  function abs() {\n    return Math.abs(this);\n  }\n\n  function round() {\n    return Math.round(this);\n  }\n\n  function ceil() {\n    return Math.ceil(this);\n  }\n\n  function floor() {\n    return Math.floor(this);\n  }\n\n  return {\n    toColorPart:    toColorPart,\n    succ:           succ,\n    times:          times,\n    toPaddedString: toPaddedString,\n    abs:            abs,\n    round:          round,\n    ceil:           ceil,\n    floor:          floor\n  };\n})());\n\nfunction $R(start, end, exclusive) {\n  return new ObjectRange(start, end, exclusive);\n}\n\nvar ObjectRange = Class.create(Enumerable, (function() {\n  function initialize(start, end, exclusive) {\n    this.start = start;\n    this.end = end;\n    this.exclusive = exclusive;\n  }\n\n  function _each(iterator, context) {\n    var value = this.start;\n    while (this.include(value)) {\n      iterator.call(context, value);\n      value = value.succ();\n    }\n  }\n\n  function include(value) {\n    if (value < this.start)\n      return false;\n    if (this.exclusive)\n      return value < this.end;\n    return value <= this.end;\n  }\n\n  return {\n    initialize: initialize,\n    _each:      _each,\n    include:    include\n  };\n})());\n\n\n\nvar Abstract = { };\n\n\nvar Try = {\n  these: function() {\n    var returnValue;\n\n    for (var i = 0, length = arguments.length; i < length; i++) {\n      var lambda = arguments[i];\n      try {\n        returnValue = lambda();\n        break;\n      } catch (e) { }\n    }\n\n    return returnValue;\n  }\n};\n\nvar Ajax = {\n  getTransport: function() {\n    return Try.these(\n      function() {return new XMLHttpRequest()},\n      function() {return new ActiveXObject('Msxml2.XMLHTTP')},\n      function() {return new ActiveXObject('Microsoft.XMLHTTP')}\n    ) || false;\n  },\n\n  activeRequestCount: 0\n};\n\nAjax.Responders = {\n  responders: [],\n\n  _each: function(iterator, context) {\n    this.responders._each(iterator, context);\n  },\n\n  register: function(responder) {\n    if (!this.include(responder))\n      this.responders.push(responder);\n  },\n\n  unregister: function(responder) {\n    this.responders = this.responders.without(responder);\n  },\n\n  dispatch: function(callback, request, transport, json) {\n    this.each(function(responder) {\n      if (Object.isFunction(responder[callback])) {\n        try {\n          responder[callback].apply(responder, [request, transport, json]);\n        } catch (e) { }\n      }\n    });\n  }\n};\n\nObject.extend(Ajax.Responders, Enumerable);\n\nAjax.Responders.register({\n  onCreate:   function() { Ajax.activeRequestCount++ },\n  onComplete: function() { Ajax.activeRequestCount-- }\n});\nAjax.Base = Class.create({\n  initialize: function(options) {\n    this.options = {\n      method:       'post',\n      asynchronous: true,\n      contentType:  'application/x-www-form-urlencoded',\n      encoding:     'UTF-8',\n      parameters:   '',\n      evalJSON:     true,\n      evalJS:       true\n    };\n    Object.extend(this.options, options || { });\n\n    this.options.method = this.options.method.toLowerCase();\n\n    if (Object.isHash(this.options.parameters))\n      this.options.parameters = this.options.parameters.toObject();\n  }\n});\nAjax.Request = Class.create(Ajax.Base, {\n  _complete: false,\n\n  initialize: function($super, url, options) {\n    $super(options);\n    this.transport = Ajax.getTransport();\n    this.request(url);\n  },\n\n  request: function(url) {\n    this.url = url;\n    this.method = this.options.method;\n    var params = Object.isString(this.options.parameters) ?\n          this.options.parameters :\n          Object.toQueryString(this.options.parameters);\n\n    if (!['get', 'post'].include(this.method)) {\n      params += (params ? '&' : '') + \"_method=\" + this.method;\n      this.method = 'post';\n    }\n\n    if (params && this.method === 'get') {\n      this.url += (this.url.include('?') ? '&' : '?') + params;\n    }\n\n    this.parameters = params.toQueryParams();\n\n    try {\n      var response = new Ajax.Response(this);\n      if (this.options.onCreate) this.options.onCreate(response);\n      Ajax.Responders.dispatch('onCreate', this, response);\n\n      this.transport.open(this.method.toUpperCase(), this.url,\n        this.options.asynchronous);\n\n      if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);\n\n      this.transport.onreadystatechange = this.onStateChange.bind(this);\n      this.setRequestHeaders();\n\n      this.body = this.method == 'post' ? (this.options.postBody || params) : null;\n      this.transport.send(this.body);\n\n      /* Force Firefox to handle ready state 4 for synchronous requests */\n      if (!this.options.asynchronous && this.transport.overrideMimeType)\n        this.onStateChange();\n\n    }\n    catch (e) {\n      this.dispatchException(e);\n    }\n  },\n\n  onStateChange: function() {\n    var readyState = this.transport.readyState;\n    if (readyState > 1 && !((readyState == 4) && this._complete))\n      this.respondToReadyState(this.transport.readyState);\n  },\n\n  setRequestHeaders: function() {\n    var headers = {\n      'X-Requested-With': 'XMLHttpRequest',\n      'X-Prototype-Version': Prototype.Version,\n      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'\n    };\n\n    if (this.method == 'post') {\n      headers['Content-type'] = this.options.contentType +\n        (this.options.encoding ? '; charset=' + this.options.encoding : '');\n\n      /* Force \"Connection: close\" for older Mozilla browsers to work\n       * around a bug where XMLHttpRequest sends an incorrect\n       * Content-length header. See Mozilla Bugzilla #246651.\n       */\n      if (this.transport.overrideMimeType &&\n          (navigator.userAgent.match(/Gecko\\/(\\d{4})/) || [0,2005])[1] < 2005)\n            headers['Connection'] = 'close';\n    }\n\n    if (typeof this.options.requestHeaders == 'object') {\n      var extras = this.options.requestHeaders;\n\n      if (Object.isFunction(extras.push))\n        for (var i = 0, length = extras.length; i < length; i += 2)\n          headers[extras[i]] = extras[i+1];\n      else\n        $H(extras).each(function(pair) { headers[pair.key] = pair.value });\n    }\n\n    for (var name in headers)\n      this.transport.setRequestHeader(name, headers[name]);\n  },\n\n  success: function() {\n    var status = this.getStatus();\n    return !status || (status >= 200 && status < 300) || status == 304;\n  },\n\n  getStatus: function() {\n    try {\n      if (this.transport.status === 1223) return 204;\n      return this.transport.status || 0;\n    } catch (e) { return 0 }\n  },\n\n  respondToReadyState: function(readyState) {\n    var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);\n\n    if (state == 'Complete') {\n      try {\n        this._complete = true;\n        (this.options['on' + response.status]\n         || this.options['on' + (this.success() ? 'Success' : 'Failure')]\n         || Prototype.emptyFunction)(response, response.headerJSON);\n      } catch (e) {\n        this.dispatchException(e);\n      }\n\n      var contentType = response.getHeader('Content-type');\n      if (this.options.evalJS == 'force'\n          || (this.options.evalJS && this.isSameOrigin() && contentType\n          && contentType.match(/^\\s*(text|application)\\/(x-)?(java|ecma)script(;.*)?\\s*$/i)))\n        this.evalResponse();\n    }\n\n    try {\n      (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);\n      Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);\n    } catch (e) {\n      this.dispatchException(e);\n    }\n\n    if (state == 'Complete') {\n      this.transport.onreadystatechange = Prototype.emptyFunction;\n    }\n  },\n\n  isSameOrigin: function() {\n    var m = this.url.match(/^\\s*https?:\\/\\/[^\\/]*/);\n    return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({\n      protocol: location.protocol,\n      domain: document.domain,\n      port: location.port ? ':' + location.port : ''\n    }));\n  },\n\n  getHeader: function(name) {\n    try {\n      return this.transport.getResponseHeader(name) || null;\n    } catch (e) { return null; }\n  },\n\n  evalResponse: function() {\n    try {\n      return eval((this.transport.responseText || '').unfilterJSON());\n    } catch (e) {\n      this.dispatchException(e);\n    }\n  },\n\n  dispatchException: function(exception) {\n    (this.options.onException || Prototype.emptyFunction)(this, exception);\n    Ajax.Responders.dispatch('onException', this, exception);\n  }\n});\n\nAjax.Request.Events =\n  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];\n\n\n\n\n\n\n\n\nAjax.Response = Class.create({\n  initialize: function(request){\n    this.request = request;\n    var transport  = this.transport  = request.transport,\n        readyState = this.readyState = transport.readyState;\n\n    if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {\n      this.status       = this.getStatus();\n      this.statusText   = this.getStatusText();\n      this.responseText = String.interpret(transport.responseText);\n      this.headerJSON   = this._getHeaderJSON();\n    }\n\n    if (readyState == 4) {\n      var xml = transport.responseXML;\n      this.responseXML  = Object.isUndefined(xml) ? null : xml;\n      this.responseJSON = this._getResponseJSON();\n    }\n  },\n\n  status:      0,\n\n  statusText: '',\n\n  getStatus: Ajax.Request.prototype.getStatus,\n\n  getStatusText: function() {\n    try {\n      return this.transport.statusText || '';\n    } catch (e) { return '' }\n  },\n\n  getHeader: Ajax.Request.prototype.getHeader,\n\n  getAllHeaders: function() {\n    try {\n      return this.getAllResponseHeaders();\n    } catch (e) { return null }\n  },\n\n  getResponseHeader: function(name) {\n    return this.transport.getResponseHeader(name);\n  },\n\n  getAllResponseHeaders: function() {\n    return this.transport.getAllResponseHeaders();\n  },\n\n  _getHeaderJSON: function() {\n    var json = this.getHeader('X-JSON');\n    if (!json) return null;\n\n    try {\n      json = decodeURIComponent(escape(json));\n    } catch(e) {\n    }\n\n    try {\n      return json.evalJSON(this.request.options.sanitizeJSON ||\n        !this.request.isSameOrigin());\n    } catch (e) {\n      this.request.dispatchException(e);\n    }\n  },\n\n  _getResponseJSON: function() {\n    var options = this.request.options;\n    if (!options.evalJSON || (options.evalJSON != 'force' &&\n      !(this.getHeader('Content-type') || '').include('application/json')) ||\n        this.responseText.blank())\n          return null;\n    try {\n      return this.responseText.evalJSON(options.sanitizeJSON ||\n        !this.request.isSameOrigin());\n    } catch (e) {\n      this.request.dispatchException(e);\n    }\n  }\n});\n\nAjax.Updater = Class.create(Ajax.Request, {\n  initialize: function($super, container, url, options) {\n    this.container = {\n      success: (container.success || container),\n      failure: (container.failure || (container.success ? null : container))\n    };\n\n    options = Object.clone(options);\n    var onComplete = options.onComplete;\n    options.onComplete = (function(response, json) {\n      this.updateContent(response.responseText);\n      if (Object.isFunction(onComplete)) onComplete(response, json);\n    }).bind(this);\n\n    $super(url, options);\n  },\n\n  updateContent: function(responseText) {\n    var receiver = this.container[this.success() ? 'success' : 'failure'],\n        options = this.options;\n\n    if (!options.evalScripts) responseText = responseText.stripScripts();\n\n    if (receiver = $(receiver)) {\n      if (options.insertion) {\n        if (Object.isString(options.insertion)) {\n          var insertion = { }; insertion[options.insertion] = responseText;\n          receiver.insert(insertion);\n        }\n        else options.insertion(receiver, responseText);\n      }\n      else receiver.update(responseText);\n    }\n  }\n});\n\nAjax.PeriodicalUpdater = Class.create(Ajax.Base, {\n  initialize: function($super, container, url, options) {\n    $super(options);\n    this.onComplete = this.options.onComplete;\n\n    this.frequency = (this.options.frequency || 2);\n    this.decay = (this.options.decay || 1);\n\n    this.updater = { };\n    this.container = container;\n    this.url = url;\n\n    this.start();\n  },\n\n  start: function() {\n    this.options.onComplete = this.updateComplete.bind(this);\n    this.onTimerEvent();\n  },\n\n  stop: function() {\n    this.updater.options.onComplete = undefined;\n    clearTimeout(this.timer);\n    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);\n  },\n\n  updateComplete: function(response) {\n    if (this.options.decay) {\n      this.decay = (response.responseText == this.lastText ?\n        this.decay * this.options.decay : 1);\n\n      this.lastText = response.responseText;\n    }\n    this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);\n  },\n\n  onTimerEvent: function() {\n    this.updater = new Ajax.Updater(this.container, this.url, this.options);\n  }\n});\n\n(function(GLOBAL) {\n\n  var UNDEFINED;\n  var SLICE = Array.prototype.slice;\n\n  var DIV = document.createElement('div');\n\n\n  function $(element) {\n    if (arguments.length > 1) {\n      for (var i = 0, elements = [], length = arguments.length; i < length; i++)\n        elements.push($(arguments[i]));\n      return elements;\n    }\n\n    if (Object.isString(element))\n      element = document.getElementById(element);\n    return Element.extend(element);\n  }\n\n  GLOBAL.$ = $;\n\n\n  if (!GLOBAL.Node) GLOBAL.Node = {};\n\n  if (!GLOBAL.Node.ELEMENT_NODE) {\n    Object.extend(GLOBAL.Node, {\n      ELEMENT_NODE:                1,\n      ATTRIBUTE_NODE:              2,\n      TEXT_NODE:                   3,\n      CDATA_SECTION_NODE:          4,\n      ENTITY_REFERENCE_NODE:       5,\n      ENTITY_NODE:                 6,\n      PROCESSING_INSTRUCTION_NODE: 7,\n      COMMENT_NODE:                8,\n      DOCUMENT_NODE:               9,\n      DOCUMENT_TYPE_NODE:         10,\n      DOCUMENT_FRAGMENT_NODE:     11,\n      NOTATION_NODE:              12\n    });\n  }\n\n  var ELEMENT_CACHE = {};\n\n  function shouldUseCreationCache(tagName, attributes) {\n    if (tagName === 'select') return false;\n    if ('type' in attributes) return false;\n    return true;\n  }\n\n  var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){\n    try {\n      var el = document.createElement('<input name=\"x\">');\n      return el.tagName.toLowerCase() === 'input' && el.name === 'x';\n    }\n    catch(err) {\n      return false;\n    }\n  })();\n\n\n  var oldElement = GLOBAL.Element;\n  function Element(tagName, attributes) {\n    attributes = attributes || {};\n    tagName = tagName.toLowerCase();\n\n    if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {\n      tagName = '<' + tagName + ' name=\"' + attributes.name + '\">';\n      delete attributes.name;\n      return Element.writeAttribute(document.createElement(tagName), attributes);\n    }\n\n    if (!ELEMENT_CACHE[tagName])\n      ELEMENT_CACHE[tagName] = Element.extend(document.createElement(tagName));\n\n    var node = shouldUseCreationCache(tagName, attributes) ?\n     ELEMENT_CACHE[tagName].cloneNode(false) : document.createElement(tagName);\n\n    return Element.writeAttribute(node, attributes);\n  }\n\n  GLOBAL.Element = Element;\n\n  Object.extend(GLOBAL.Element, oldElement || {});\n  if (oldElement) GLOBAL.Element.prototype = oldElement.prototype;\n\n  Element.Methods = { ByTag: {}, Simulated: {} };\n\n  var methods = {};\n\n  var INSPECT_ATTRIBUTES = { id: 'id', className: 'class' };\n  function inspect(element) {\n    element = $(element);\n    var result = '<' + element.tagName.toLowerCase();\n\n    var attribute, value;\n    for (var property in INSPECT_ATTRIBUTES) {\n      attribute = INSPECT_ATTRIBUTES[property];\n      value = (element[property] || '').toString();\n      if (value) result += ' ' + attribute + '=' + value.inspect(true);\n    }\n\n    return result + '>';\n  }\n\n  methods.inspect = inspect;\n\n\n  function visible(element) {\n    return $(element).style.display !== 'none';\n  }\n\n  function toggle(element, bool) {\n    element = $(element);\n    if (Object.isUndefined(bool))\n      bool = !Element.visible(element);\n    Element[bool ? 'show' : 'hide'](element);\n\n    return element;\n  }\n\n  function hide(element) {\n    element = $(element);\n    element.style.display = 'none';\n    return element;\n  }\n\n  function show(element) {\n    element = $(element);\n    element.style.display = '';\n    return element;\n  }\n\n\n  Object.extend(methods, {\n    visible: visible,\n    toggle:  toggle,\n    hide:    hide,\n    show:    show\n  });\n\n\n  function remove(element) {\n    element = $(element);\n    element.parentNode.removeChild(element);\n    return element;\n  }\n\n  var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){\n    var el = document.createElement(\"select\"),\n        isBuggy = true;\n    el.innerHTML = \"<option value=\\\"test\\\">test</option>\";\n    if (el.options && el.options[0]) {\n      isBuggy = el.options[0].nodeName.toUpperCase() !== \"OPTION\";\n    }\n    el = null;\n    return isBuggy;\n  })();\n\n  var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){\n    try {\n      var el = document.createElement(\"table\");\n      if (el && el.tBodies) {\n        el.innerHTML = \"<tbody><tr><td>test</td></tr></tbody>\";\n        var isBuggy = typeof el.tBodies[0] == \"undefined\";\n        el = null;\n        return isBuggy;\n      }\n    } catch (e) {\n      return true;\n    }\n  })();\n\n  var LINK_ELEMENT_INNERHTML_BUGGY = (function() {\n    try {\n      var el = document.createElement('div');\n      el.innerHTML = \"<link />\";\n      var isBuggy = (el.childNodes.length === 0);\n      el = null;\n      return isBuggy;\n    } catch(e) {\n      return true;\n    }\n  })();\n\n  var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||\n   TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;\n\n  var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {\n    var s = document.createElement(\"script\"),\n        isBuggy = false;\n    try {\n      s.appendChild(document.createTextNode(\"\"));\n      isBuggy = !s.firstChild ||\n        s.firstChild && s.firstChild.nodeType !== 3;\n    } catch (e) {\n      isBuggy = true;\n    }\n    s = null;\n    return isBuggy;\n  })();\n\n  function update(element, content) {\n    element = $(element);\n\n    var descendants = element.getElementsByTagName('*'),\n     i = descendants.length;\n    while (i--) purgeElement(descendants[i]);\n\n    if (content && content.toElement)\n      content = content.toElement();\n\n    if (Object.isElement(content))\n      return element.update().insert(content);\n\n\n    content = Object.toHTML(content);\n    var tagName = element.tagName.toUpperCase();\n\n    if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) {\n      element.text = content;\n      return element;\n    }\n\n    if (ANY_INNERHTML_BUGGY) {\n      if (tagName in INSERTION_TRANSLATIONS.tags) {\n        while (element.firstChild)\n          element.removeChild(element.firstChild);\n\n        var nodes = getContentFromAnonymousElement(tagName, content.stripScripts());\n        for (var i = 0, node; node = nodes[i]; i++)\n          element.appendChild(node);\n\n      } else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {\n        while (element.firstChild)\n          element.removeChild(element.firstChild);\n\n        var nodes = getContentFromAnonymousElement(tagName,\n         content.stripScripts(), true);\n\n        for (var i = 0, node; node = nodes[i]; i++)\n          element.appendChild(node);\n      } else {\n        element.innerHTML = content.stripScripts();\n      }\n    } else {\n      element.innerHTML = content.stripScripts();\n    }\n\n    content.evalScripts.bind(content).defer();\n    return element;\n  }\n\n  function replace(element, content) {\n    element = $(element);\n\n    if (content && content.toElement) {\n      content = content.toElement();\n    } else if (!Object.isElement(content)) {\n      content = Object.toHTML(content);\n      var range = element.ownerDocument.createRange();\n      range.selectNode(element);\n      content.evalScripts.bind(content).defer();\n      content = range.createContextualFragment(content.stripScripts());\n    }\n\n    element.parentNode.replaceChild(content, element);\n    return element;\n  }\n\n  var INSERTION_TRANSLATIONS = {\n    before: function(element, node) {\n      element.parentNode.insertBefore(node, element);\n    },\n    top: function(element, node) {\n      element.insertBefore(node, element.firstChild);\n    },\n    bottom: function(element, node) {\n      element.appendChild(node);\n    },\n    after: function(element, node) {\n      element.parentNode.insertBefore(node, element.nextSibling);\n    },\n\n    tags: {\n      TABLE:  ['<table>',                '</table>',                   1],\n      TBODY:  ['<table><tbody>',         '</tbody></table>',           2],\n      TR:     ['<table><tbody><tr>',     '</tr></tbody></table>',      3],\n      TD:     ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],\n      SELECT: ['<select>',               '</select>',                  1]\n    }\n  };\n\n  var tags = INSERTION_TRANSLATIONS.tags;\n\n  Object.extend(tags, {\n    THEAD: tags.TBODY,\n    TFOOT: tags.TBODY,\n    TH:    tags.TD\n  });\n\n  function replace_IE(element, content) {\n    element = $(element);\n    if (content && content.toElement)\n      content = content.toElement();\n    if (Object.isElement(content)) {\n      element.parentNode.replaceChild(content, element);\n      return element;\n    }\n\n    content = Object.toHTML(content);\n    var parent = element.parentNode, tagName = parent.tagName.toUpperCase();\n\n    if (tagName in INSERTION_TRANSLATIONS.tags) {\n      var nextSibling = Element.next(element);\n      var fragments = getContentFromAnonymousElement(\n       tagName, content.stripScripts());\n\n      parent.removeChild(element);\n\n      var iterator;\n      if (nextSibling)\n        iterator = function(node) { parent.insertBefore(node, nextSibling) };\n      else\n        iterator = function(node) { parent.appendChild(node); }\n\n      fragments.each(iterator);\n    } else {\n      element.outerHTML = content.stripScripts();\n    }\n\n    content.evalScripts.bind(content).defer();\n    return element;\n  }\n\n  if ('outerHTML' in document.documentElement)\n    replace = replace_IE;\n\n  function isContent(content) {\n    if (Object.isUndefined(content) || content === null) return false;\n\n    if (Object.isString(content) || Object.isNumber(content)) return true;\n    if (Object.isElement(content)) return true;\n    if (content.toElement || content.toHTML) return true;\n\n    return false;\n  }\n\n  function insertContentAt(element, content, position) {\n    position   = position.toLowerCase();\n    var method = INSERTION_TRANSLATIONS[position];\n\n    if (content && content.toElement) content = content.toElement();\n    if (Object.isElement(content)) {\n      method(element, content);\n      return element;\n    }\n\n    content = Object.toHTML(content);\n    var tagName = ((position === 'before' || position === 'after') ?\n     element.parentNode : element).tagName.toUpperCase();\n\n    var childNodes = getContentFromAnonymousElement(tagName, content.stripScripts());\n\n    if (position === 'top' || position === 'after') childNodes.reverse();\n\n    for (var i = 0, node; node = childNodes[i]; i++)\n      method(element, node);\n\n    content.evalScripts.bind(content).defer();\n  }\n\n  function insert(element, insertions) {\n    element = $(element);\n\n    if (isContent(insertions))\n      insertions = { bottom: insertions };\n\n    for (var position in insertions)\n      insertContentAt(element, insertions[position], position);\n\n    return element;\n  }\n\n  function wrap(element, wrapper, attributes) {\n    element = $(element);\n\n    if (Object.isElement(wrapper)) {\n      $(wrapper).writeAttribute(attributes || {});\n    } else if (Object.isString(wrapper)) {\n      wrapper = new Element(wrapper, attributes);\n    } else {\n      wrapper = new Element('div', wrapper);\n    }\n\n    if (element.parentNode)\n      element.parentNode.replaceChild(wrapper, element);\n\n    wrapper.appendChild(element);\n\n    return wrapper;\n  }\n\n  function cleanWhitespace(element) {\n    element = $(element);\n    var node = element.firstChild;\n\n    while (node) {\n      var nextNode = node.nextSibling;\n      if (node.nodeType === Node.TEXT_NODE && !/\\S/.test(node.nodeValue))\n        element.removeChild(node);\n      node = nextNode;\n    }\n    return element;\n  }\n\n  function empty(element) {\n    return $(element).innerHTML.blank();\n  }\n\n  function getContentFromAnonymousElement(tagName, html, force) {\n    var t = INSERTION_TRANSLATIONS.tags[tagName], div = DIV;\n\n    var workaround = !!t;\n    if (!workaround && force) {\n      workaround = true;\n      t = ['', '', 0];\n    }\n\n    if (workaround) {\n      div.innerHTML = '&#160;' + t[0] + html + t[1];\n      div.removeChild(div.firstChild);\n      for (var i = t[2]; i--; )\n        div = div.firstChild;\n    } else {\n      div.innerHTML = html;\n    }\n\n    return $A(div.childNodes);\n  }\n\n  function clone(element, deep) {\n    if (!(element = $(element))) return;\n    var clone = element.cloneNode(deep);\n    if (!HAS_UNIQUE_ID_PROPERTY) {\n      clone._prototypeUID = UNDEFINED;\n      if (deep) {\n        var descendants = Element.select(clone, '*'),\n         i = descendants.length;\n        while (i--)\n          descendants[i]._prototypeUID = UNDEFINED;\n      }\n    }\n    return Element.extend(clone);\n  }\n\n  function purgeElement(element) {\n    var uid = getUniqueElementID(element);\n    if (uid) {\n      Element.stopObserving(element);\n      if (!HAS_UNIQUE_ID_PROPERTY)\n        element._prototypeUID = UNDEFINED;\n      delete Element.Storage[uid];\n    }\n  }\n\n  function purgeCollection(elements) {\n    var i = elements.length;\n    while (i--)\n      purgeElement(elements[i]);\n  }\n\n  function purgeCollection_IE(elements) {\n    var i = elements.length, element, uid;\n    while (i--) {\n      element = elements[i];\n      uid = getUniqueElementID(element);\n      delete Element.Storage[uid];\n      delete Event.cache[uid];\n    }\n  }\n\n  if (HAS_UNIQUE_ID_PROPERTY) {\n    purgeCollection = purgeCollection_IE;\n  }\n\n\n  function purge(element) {\n    if (!(element = $(element))) return;\n    purgeElement(element);\n\n    var descendants = element.getElementsByTagName('*'),\n     i = descendants.length;\n\n    while (i--) purgeElement(descendants[i]);\n\n    return null;\n  }\n\n  Object.extend(methods, {\n    remove:  remove,\n    update:  update,\n    replace: replace,\n    insert:  insert,\n    wrap:    wrap,\n    cleanWhitespace: cleanWhitespace,\n    empty:   empty,\n    clone:   clone,\n    purge:   purge\n  });\n\n\n\n  function recursivelyCollect(element, property, maximumLength) {\n    element = $(element);\n    maximumLength = maximumLength || -1;\n    var elements = [];\n\n    while (element = element[property]) {\n      if (element.nodeType === Node.ELEMENT_NODE)\n        elements.push(Element.extend(element));\n\n      if (elements.length === maximumLength) break;\n    }\n\n    return elements;\n  }\n\n\n  function ancestors(element) {\n    return recursivelyCollect(element, 'parentNode');\n  }\n\n  function descendants(element) {\n    return Element.select(element, '*');\n  }\n\n  function firstDescendant(element) {\n    element = $(element).firstChild;\n    while (element && element.nodeType !== Node.ELEMENT_NODE)\n      element = element.nextSibling;\n\n    return $(element);\n  }\n\n  function immediateDescendants(element) {\n    var results = [], child = $(element).firstChild;\n\n    while (child) {\n      if (child.nodeType === Node.ELEMENT_NODE)\n        results.push(Element.extend(child));\n\n      child = child.nextSibling;\n    }\n\n    return results;\n  }\n\n  function previousSiblings(element) {\n    return recursivelyCollect(element, 'previousSibling');\n  }\n\n  function nextSiblings(element) {\n    return recursivelyCollect(element, 'nextSibling');\n  }\n\n  function siblings(element) {\n    element = $(element);\n    var previous = previousSiblings(element),\n     next = nextSiblings(element);\n    return previous.reverse().concat(next);\n  }\n\n  function match(element, selector) {\n    element = $(element);\n\n    if (Object.isString(selector))\n      return Prototype.Selector.match(element, selector);\n\n    return selector.match(element);\n  }\n\n\n  function _recursivelyFind(element, property, expression, index) {\n    element = $(element), expression = expression || 0, index = index || 0;\n    if (Object.isNumber(expression)) {\n      index = expression, expression = null;\n    }\n\n    while (element = element[property]) {\n      if (element.nodeType !== 1) continue;\n      if (expression && !Prototype.Selector.match(element, expression))\n        continue;\n      if (--index >= 0) continue;\n\n      return Element.extend(element);\n    }\n  }\n\n\n  function up(element, expression, index) {\n    element = $(element);\n\n    if (arguments.length === 1) return $(element.parentNode);\n    return _recursivelyFind(element, 'parentNode', expression, index);\n  }\n\n  function down(element, expression, index) {\n    element = $(element), expression = expression || 0, index = index || 0;\n\n    if (Object.isNumber(expression))\n      index = expression, expression = '*';\n\n    var node = Prototype.Selector.select(expression, element)[index];\n    return Element.extend(node);\n  }\n\n  function previous(element, expression, index) {\n    return _recursivelyFind(element, 'previousSibling', expression, index);\n  }\n\n  function next(element, expression, index) {\n    return _recursivelyFind(element, 'nextSibling', expression, index);\n  }\n\n  function select(element) {\n    element = $(element);\n    var expressions = SLICE.call(arguments, 1).join(', ');\n    return Prototype.Selector.select(expressions, element);\n  }\n\n  function adjacent(element) {\n    element = $(element);\n    var expressions = SLICE.call(arguments, 1).join(', ');\n    var siblings = Element.siblings(element), results = [];\n    for (var i = 0, sibling; sibling = siblings[i]; i++) {\n      if (Prototype.Selector.match(sibling, expressions))\n        results.push(sibling);\n    }\n\n    return results;\n  }\n\n  function descendantOf_DOM(element, ancestor) {\n    element = $(element), ancestor = $(ancestor);\n    while (element = element.parentNode)\n      if (element === ancestor) return true;\n    return false;\n  }\n\n  function descendantOf_contains(element, ancestor) {\n    element = $(element), ancestor = $(ancestor);\n    if (!ancestor.contains) return descendantOf_DOM(element, ancestor);\n    return ancestor.contains(element) && ancestor !== element;\n  }\n\n  function descendantOf_compareDocumentPosition(element, ancestor) {\n    element = $(element), ancestor = $(ancestor);\n    return (element.compareDocumentPosition(ancestor) & 8) === 8;\n  }\n\n  var descendantOf;\n  if (DIV.compareDocumentPosition) {\n    descendantOf = descendantOf_compareDocumentPosition;\n  } else if (DIV.contains) {\n    descendantOf = descendantOf_contains;\n  } else {\n    descendantOf = descendantOf_DOM;\n  }\n\n\n  Object.extend(methods, {\n    recursivelyCollect:   recursivelyCollect,\n    ancestors:            ancestors,\n    descendants:          descendants,\n    firstDescendant:      firstDescendant,\n    immediateDescendants: immediateDescendants,\n    previousSiblings:     previousSiblings,\n    nextSiblings:         nextSiblings,\n    siblings:             siblings,\n    match:                match,\n    up:                   up,\n    down:                 down,\n    previous:             previous,\n    next:                 next,\n    select:               select,\n    adjacent:             adjacent,\n    descendantOf:         descendantOf,\n\n    getElementsBySelector: select,\n\n    childElements:         immediateDescendants\n  });\n\n\n  var idCounter = 1;\n  function identify(element) {\n    element = $(element);\n    var id = Element.readAttribute(element, 'id');\n    if (id) return id;\n\n    do { id = 'anonymous_element_' + idCounter++ } while ($(id));\n\n    Element.writeAttribute(element, 'id', id);\n    return id;\n  }\n\n\n  function readAttribute(element, name) {\n    return $(element).getAttribute(name);\n  }\n\n  function readAttribute_IE(element, name) {\n    element = $(element);\n\n    var table = ATTRIBUTE_TRANSLATIONS.read;\n    if (table.values[name])\n      return table.values[name](element, name);\n\n    if (table.names[name]) name = table.names[name];\n\n    if (name.include(':')) {\n      if (!element.attributes || !element.attributes[name]) return null;\n      return element.attributes[name].value;\n    }\n\n    return element.getAttribute(name);\n  }\n\n  function readAttribute_Opera(element, name) {\n    if (name === 'title') return element.title;\n    return element.getAttribute(name);\n  }\n\n  var PROBLEMATIC_ATTRIBUTE_READING = (function() {\n    DIV.setAttribute('onclick', Prototype.emptyFunction);\n    var value = DIV.getAttribute('onclick');\n    var isFunction = (typeof value === 'function');\n    DIV.removeAttribute('onclick');\n    return isFunction;\n  })();\n\n  if (PROBLEMATIC_ATTRIBUTE_READING) {\n    readAttribute = readAttribute_IE;\n  } else if (Prototype.Browser.Opera) {\n    readAttribute = readAttribute_Opera;\n  }\n\n\n  function writeAttribute(element, name, value) {\n    element = $(element);\n    var attributes = {}, table = ATTRIBUTE_TRANSLATIONS.write;\n\n    if (typeof name === 'object') {\n      attributes = name;\n    } else {\n      attributes[name] = Object.isUndefined(value) ? true : value;\n    }\n\n    for (var attr in attributes) {\n      name = table.names[attr] || attr;\n      value = attributes[attr];\n      if (table.values[attr])\n        name = table.values[attr](element, value);\n      if (value === false || value === null)\n        element.removeAttribute(name);\n      else if (value === true)\n        element.setAttribute(name, name);\n      else element.setAttribute(name, value);\n    }\n\n    return element;\n  }\n\n  function hasAttribute(element, attribute) {\n    attribute = ATTRIBUTE_TRANSLATIONS.has[attribute] || attribute;\n    var node = $(element).getAttributeNode(attribute);\n    return !!(node && node.specified);\n  }\n\n  GLOBAL.Element.Methods.Simulated.hasAttribute = hasAttribute;\n\n  function classNames(element) {\n    return new Element.ClassNames(element);\n  }\n\n  var regExpCache = {};\n  function getRegExpForClassName(className) {\n    if (regExpCache[className]) return regExpCache[className];\n\n    var re = new RegExp(\"(^|\\\\s+)\" + className + \"(\\\\s+|$)\");\n    regExpCache[className] = re;\n    return re;\n  }\n\n  function hasClassName(element, className) {\n    if (!(element = $(element))) return;\n\n    var elementClassName = element.className;\n\n    if (elementClassName.length === 0) return false;\n    if (elementClassName === className) return true;\n\n    return getRegExpForClassName(className).test(elementClassName);\n  }\n\n  function addClassName(element, className) {\n    if (!(element = $(element))) return;\n\n    if (!hasClassName(element, className))\n      element.className += (element.className ? ' ' : '') + className;\n\n    return element;\n  }\n\n  function removeClassName(element, className) {\n    if (!(element = $(element))) return;\n\n    element.className = element.className.replace(\n     getRegExpForClassName(className), ' ').strip();\n\n    return element;\n  }\n\n  function toggleClassName(element, className, bool) {\n    if (!(element = $(element))) return;\n\n    if (Object.isUndefined(bool))\n      bool = !hasClassName(element, className);\n\n    var method = Element[bool ? 'addClassName' : 'removeClassName'];\n    return method(element, className);\n  }\n\n  var ATTRIBUTE_TRANSLATIONS = {};\n\n  var classProp = 'className', forProp = 'for';\n\n  DIV.setAttribute(classProp, 'x');\n  if (DIV.className !== 'x') {\n    DIV.setAttribute('class', 'x');\n    if (DIV.className === 'x')\n      classProp = 'class';\n  }\n\n  var LABEL = document.createElement('label');\n  LABEL.setAttribute(forProp, 'x');\n  if (LABEL.htmlFor !== 'x') {\n    LABEL.setAttribute('htmlFor', 'x');\n    if (LABEL.htmlFor === 'x')\n      forProp = 'htmlFor';\n  }\n  LABEL = null;\n\n  function _getAttr(element, attribute) {\n    return element.getAttribute(attribute);\n  }\n\n  function _getAttr2(element, attribute) {\n    return element.getAttribute(attribute, 2);\n  }\n\n  function _getAttrNode(element, attribute) {\n    var node = element.getAttributeNode(attribute);\n    return node ? node.value : '';\n  }\n\n  function _getFlag(element, attribute) {\n    return $(element).hasAttribute(attribute) ? attribute : null;\n  }\n\n  DIV.onclick = Prototype.emptyFunction;\n  var onclickValue = DIV.getAttribute('onclick');\n\n  var _getEv;\n\n  if (String(onclickValue).indexOf('{') > -1) {\n    _getEv = function(element, attribute) {\n      var value = element.getAttribute(attribute);\n      if (!value) return null;\n      value = value.toString();\n      value = value.split('{')[1];\n      value = value.split('}')[0];\n      return value.strip();\n    };\n  }\n  else if (onclickValue === '') {\n    _getEv = function(element, attribute) {\n      var value = element.getAttribute(attribute);\n      if (!value) return null;\n      return value.strip();\n    };\n  }\n\n  ATTRIBUTE_TRANSLATIONS.read = {\n    names: {\n      'class':     classProp,\n      'className': classProp,\n      'for':       forProp,\n      'htmlFor':   forProp\n    },\n\n    values: {\n      style: function(element) {\n        return element.style.cssText.toLowerCase();\n      },\n      title: function(element) {\n        return element.title;\n      }\n    }\n  };\n\n  ATTRIBUTE_TRANSLATIONS.write = {\n    names: {\n      className:   'class',\n      htmlFor:     'for',\n      cellpadding: 'cellPadding',\n      cellspacing: 'cellSpacing'\n    },\n\n    values: {\n      checked: function(element, value) {\n        element.checked = !!value;\n      },\n\n      style: function(element, value) {\n        element.style.cssText = value ? value : '';\n      }\n    }\n  };\n\n  ATTRIBUTE_TRANSLATIONS.has = { names: {} };\n\n  Object.extend(ATTRIBUTE_TRANSLATIONS.write.names,\n   ATTRIBUTE_TRANSLATIONS.read.names);\n\n  var CAMEL_CASED_ATTRIBUTE_NAMES = $w('colSpan rowSpan vAlign dateTime ' +\n   'accessKey tabIndex encType maxLength readOnly longDesc frameBorder');\n\n  for (var i = 0, attr; attr = CAMEL_CASED_ATTRIBUTE_NAMES[i]; i++) {\n    ATTRIBUTE_TRANSLATIONS.write.names[attr.toLowerCase()] = attr;\n    ATTRIBUTE_TRANSLATIONS.has.names[attr.toLowerCase()]   = attr;\n  }\n\n  Object.extend(ATTRIBUTE_TRANSLATIONS.read.values, {\n    href:        _getAttr2,\n    src:         _getAttr2,\n    type:        _getAttr,\n    action:      _getAttrNode,\n    disabled:    _getFlag,\n    checked:     _getFlag,\n    readonly:    _getFlag,\n    multiple:    _getFlag,\n    onload:      _getEv,\n    onunload:    _getEv,\n    onclick:     _getEv,\n    ondblclick:  _getEv,\n    onmousedown: _getEv,\n    onmouseup:   _getEv,\n    onmouseover: _getEv,\n    onmousemove: _getEv,\n    onmouseout:  _getEv,\n    onfocus:     _getEv,\n    onblur:      _getEv,\n    onkeypress:  _getEv,\n    onkeydown:   _getEv,\n    onkeyup:     _getEv,\n    onsubmit:    _getEv,\n    onreset:     _getEv,\n    onselect:    _getEv,\n    onchange:    _getEv\n  });\n\n\n  Object.extend(methods, {\n    identify:        identify,\n    readAttribute:   readAttribute,\n    writeAttribute:  writeAttribute,\n    classNames:      classNames,\n    hasClassName:    hasClassName,\n    addClassName:    addClassName,\n    removeClassName: removeClassName,\n    toggleClassName: toggleClassName\n  });\n\n\n  function normalizeStyleName(style) {\n    if (style === 'float' || style === 'styleFloat')\n      return 'cssFloat';\n    return style.camelize();\n  }\n\n  function normalizeStyleName_IE(style) {\n    if (style === 'float' || style === 'cssFloat')\n      return 'styleFloat';\n    return style.camelize();\n  }\n\n  function setStyle(element, styles) {\n    element = $(element);\n    var elementStyle = element.style, match;\n\n    if (Object.isString(styles)) {\n      elementStyle.cssText += ';' + styles;\n      if (styles.include('opacity')) {\n        var opacity = styles.match(/opacity:\\s*(\\d?\\.?\\d*)/)[1];\n        Element.setOpacity(element, opacity);\n      }\n      return element;\n    }\n\n    for (var property in styles) {\n      if (property === 'opacity') {\n        Element.setOpacity(element, styles[property]);\n      } else {\n        var value = styles[property];\n        if (property === 'float' || property === 'cssFloat') {\n          property = Object.isUndefined(elementStyle.styleFloat) ?\n           'cssFloat' : 'styleFloat';\n        }\n        elementStyle[property] = value;\n      }\n    }\n\n    return element;\n  }\n\n\n  function getStyle(element, style) {\n    element = $(element);\n    style = normalizeStyleName(style);\n\n    var value = element.style[style];\n    if (!value || value === 'auto') {\n      var css = document.defaultView.getComputedStyle(element, null);\n      value = css ? css[style] : null;\n    }\n\n    if (style === 'opacity') return value ? parseFloat(value) : 1.0;\n    return value === 'auto' ? null : value;\n  }\n\n  function getStyle_Opera(element, style) {\n    switch (style) {\n      case 'height': case 'width':\n        if (!Element.visible(element)) return null;\n\n        var dim = parseInt(getStyle(element, style), 10);\n\n        if (dim !== element['offset' + style.capitalize()])\n          return dim + 'px';\n\n        return Element.measure(element, style);\n\n      default: return getStyle(element, style);\n    }\n  }\n\n  function getStyle_IE(element, style) {\n    element = $(element);\n    style = normalizeStyleName_IE(style);\n\n    var value = element.style[style];\n    if (!value && element.currentStyle) {\n      value = element.currentStyle[style];\n    }\n\n    if (style === 'opacity' && !STANDARD_CSS_OPACITY_SUPPORTED)\n      return getOpacity_IE(element);\n\n    if (value === 'auto') {\n      if ((style === 'width' || style === 'height') && Element.visible(element))\n        return Element.measure(element, style) + 'px';\n      return null;\n    }\n\n    return value;\n  }\n\n  function stripAlphaFromFilter_IE(filter) {\n    return (filter || '').replace(/alpha\\([^\\)]*\\)/gi, '');\n  }\n\n  function hasLayout_IE(element) {\n    if (!element.currentStyle.hasLayout)\n      element.style.zoom = 1;\n    return element;\n  }\n\n  var STANDARD_CSS_OPACITY_SUPPORTED = (function() {\n    DIV.style.cssText = \"opacity:.55\";\n    return /^0.55/.test(DIV.style.opacity);\n  })();\n\n  function setOpacity(element, value) {\n    element = $(element);\n    if (value == 1 || value === '') value = '';\n    else if (value < 0.00001) value = 0;\n    element.style.opacity = value;\n    return element;\n  }\n\n  function setOpacity_IE(element, value) {\n    if (STANDARD_CSS_OPACITY_SUPPORTED)\n      return setOpacity(element, value);\n\n    element = hasLayout_IE($(element));\n    var filter = Element.getStyle(element, 'filter'),\n     style = element.style;\n\n    if (value == 1 || value === '') {\n      filter = stripAlphaFromFilter_IE(filter);\n      if (filter) style.filter = filter;\n      else style.removeAttribute('filter');\n      return element;\n    }\n\n    if (value < 0.00001) value = 0;\n\n    style.filter = stripAlphaFromFilter_IE(filter) +\n     'alpha(opacity=' + (value * 100) + ')';\n\n    return element;\n  }\n\n\n  function getOpacity(element) {\n    return Element.getStyle(element, 'opacity');\n  }\n\n  function getOpacity_IE(element) {\n    if (STANDARD_CSS_OPACITY_SUPPORTED)\n      return getOpacity(element);\n\n    var filter = Element.getStyle(element, 'filter');\n    if (filter.length === 0) return 1.0;\n    var match = (filter || '').match(/alpha\\(opacity=(.*)\\)/);\n    if (match[1]) return parseFloat(match[1]) / 100;\n    return 1.0;\n  }\n\n\n  Object.extend(methods, {\n    setStyle:   setStyle,\n    getStyle:   getStyle,\n    setOpacity: setOpacity,\n    getOpacity: getOpacity\n  });\n\n  if ('styleFloat' in DIV.style) {\n    methods.getStyle = getStyle_IE;\n    methods.setOpacity = setOpacity_IE;\n    methods.getOpacity = getOpacity_IE;\n  }\n\n  var UID = 0;\n\n  GLOBAL.Element.Storage = { UID: 1 };\n\n  function getUniqueElementID(element) {\n    if (element === window) return 0;\n\n    if (typeof element._prototypeUID === 'undefined')\n      element._prototypeUID = Element.Storage.UID++;\n    return element._prototypeUID;\n  }\n\n  function getUniqueElementID_IE(element) {\n    if (element === window) return 0;\n    if (element == document) return 1;\n    return element.uniqueID;\n  }\n\n  var HAS_UNIQUE_ID_PROPERTY = ('uniqueID' in DIV);\n  if (HAS_UNIQUE_ID_PROPERTY)\n    getUniqueElementID = getUniqueElementID_IE;\n\n  function getStorage(element) {\n    if (!(element = $(element))) return;\n\n    var uid = getUniqueElementID(element);\n\n    if (!Element.Storage[uid])\n      Element.Storage[uid] = $H();\n\n    return Element.Storage[uid];\n  }\n\n  function store(element, key, value) {\n    if (!(element = $(element))) return;\n    var storage = getStorage(element);\n    if (arguments.length === 2) {\n      storage.update(key);\n    } else {\n      storage.set(key, value);\n    }\n    return element;\n  }\n\n  function retrieve(element, key, defaultValue) {\n    if (!(element = $(element))) return;\n    var storage = getStorage(element), value = storage.get(key);\n\n    if (Object.isUndefined(value)) {\n      storage.set(key, defaultValue);\n      value = defaultValue;\n    }\n\n    return value;\n  }\n\n\n  Object.extend(methods, {\n    getStorage: getStorage,\n    store:      store,\n    retrieve:   retrieve\n  });\n\n\n  var Methods = {}, ByTag = Element.Methods.ByTag,\n   F = Prototype.BrowserFeatures;\n\n  if (!F.ElementExtensions && ('__proto__' in DIV)) {\n    GLOBAL.HTMLElement = {};\n    GLOBAL.HTMLElement.prototype = DIV['__proto__'];\n    F.ElementExtensions = true;\n  }\n\n  function checkElementPrototypeDeficiency(tagName) {\n    if (typeof window.Element === 'undefined') return false;\n    var proto = window.Element.prototype;\n    if (proto) {\n      var id = '_' + (Math.random() + '').slice(2),\n       el = document.createElement(tagName);\n      proto[id] = 'x';\n      var isBuggy = (el[id] !== 'x');\n      delete proto[id];\n      el = null;\n      return isBuggy;\n    }\n\n    return false;\n  }\n\n  var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY =\n   checkElementPrototypeDeficiency('object');\n\n  function extendElementWith(element, methods) {\n    for (var property in methods) {\n      var value = methods[property];\n      if (Object.isFunction(value) && !(property in element))\n        element[property] = value.methodize();\n    }\n  }\n\n  var EXTENDED = {};\n  function elementIsExtended(element) {\n    var uid = getUniqueElementID(element);\n    return (uid in EXTENDED);\n  }\n\n  function extend(element) {\n    if (!element || elementIsExtended(element)) return element;\n    if (element.nodeType !== Node.ELEMENT_NODE || element == window)\n      return element;\n\n    var methods = Object.clone(Methods),\n     tagName = element.tagName.toUpperCase();\n\n    if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);\n\n    extendElementWith(element, methods);\n    EXTENDED[getUniqueElementID(element)] = true;\n    return element;\n  }\n\n  function extend_IE8(element) {\n    if (!element || elementIsExtended(element)) return element;\n\n    var t = element.tagName;\n    if (t && (/^(?:object|applet|embed)$/i.test(t))) {\n      extendElementWith(element, Element.Methods);\n      extendElementWith(element, Element.Methods.Simulated);\n      extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);\n    }\n\n    return element;\n  }\n\n  if (F.SpecificElementExtensions) {\n    extend = HTMLOBJECTELEMENT_PROTOTYPE_BUGGY ? extend_IE8 : Prototype.K;\n  }\n\n  function addMethodsToTagName(tagName, methods) {\n    tagName = tagName.toUpperCase();\n    if (!ByTag[tagName]) ByTag[tagName] = {};\n    Object.extend(ByTag[tagName], methods);\n  }\n\n  function mergeMethods(destination, methods, onlyIfAbsent) {\n    if (Object.isUndefined(onlyIfAbsent)) onlyIfAbsent = false;\n    for (var property in methods) {\n      var value = methods[property];\n      if (!Object.isFunction(value)) continue;\n      if (!onlyIfAbsent || !(property in destination))\n        destination[property] = value.methodize();\n    }\n  }\n\n  function findDOMClass(tagName) {\n    var klass;\n    var trans = {\n      \"OPTGROUP\": \"OptGroup\", \"TEXTAREA\": \"TextArea\", \"P\": \"Paragraph\",\n      \"FIELDSET\": \"FieldSet\", \"UL\": \"UList\", \"OL\": \"OList\", \"DL\": \"DList\",\n      \"DIR\": \"Directory\", \"H1\": \"Heading\", \"H2\": \"Heading\", \"H3\": \"Heading\",\n      \"H4\": \"Heading\", \"H5\": \"Heading\", \"H6\": \"Heading\", \"Q\": \"Quote\",\n      \"INS\": \"Mod\", \"DEL\": \"Mod\", \"A\": \"Anchor\", \"IMG\": \"Image\", \"CAPTION\":\n      \"TableCaption\", \"COL\": \"TableCol\", \"COLGROUP\": \"TableCol\", \"THEAD\":\n      \"TableSection\", \"TFOOT\": \"TableSection\", \"TBODY\": \"TableSection\", \"TR\":\n      \"TableRow\", \"TH\": \"TableCell\", \"TD\": \"TableCell\", \"FRAMESET\":\n      \"FrameSet\", \"IFRAME\": \"IFrame\"\n    };\n    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';\n    if (window[klass]) return window[klass];\n    klass = 'HTML' + tagName + 'Element';\n    if (window[klass]) return window[klass];\n    klass = 'HTML' + tagName.capitalize() + 'Element';\n    if (window[klass]) return window[klass];\n\n    var element = document.createElement(tagName),\n     proto = element['__proto__'] || element.constructor.prototype;\n\n    element = null;\n    return proto;\n  }\n\n  function addMethods(methods) {\n    if (arguments.length === 0) addFormMethods();\n\n    if (arguments.length === 2) {\n      var tagName = methods;\n      methods = arguments[1];\n    }\n\n    if (!tagName) {\n      Object.extend(Element.Methods, methods || {});\n    } else {\n      if (Object.isArray(tagName)) {\n        for (var i = 0, tag; tag = tagName[i]; i++)\n          addMethodsToTagName(tag, methods);\n      } else {\n        addMethodsToTagName(tagName, methods);\n      }\n    }\n\n    var ELEMENT_PROTOTYPE = window.HTMLElement ? HTMLElement.prototype :\n     Element.prototype;\n\n    if (F.ElementExtensions) {\n      mergeMethods(ELEMENT_PROTOTYPE, Element.Methods);\n      mergeMethods(ELEMENT_PROTOTYPE, Element.Methods.Simulated, true);\n    }\n\n    if (F.SpecificElementExtensions) {\n      for (var tag in Element.Methods.ByTag) {\n        var klass = findDOMClass(tag);\n        if (Object.isUndefined(klass)) continue;\n        mergeMethods(klass.prototype, ByTag[tag]);\n      }\n    }\n\n    Object.extend(Element, Element.Methods);\n    Object.extend(Element, Element.Methods.Simulated);\n    delete Element.ByTag;\n    delete Element.Simulated;\n\n    Element.extend.refresh();\n\n    ELEMENT_CACHE = {};\n  }\n\n  Object.extend(GLOBAL.Element, {\n    extend:     extend,\n    addMethods: addMethods\n  });\n\n  if (extend === Prototype.K) {\n    GLOBAL.Element.extend.refresh = Prototype.emptyFunction;\n  } else {\n    GLOBAL.Element.extend.refresh = function() {\n      if (Prototype.BrowserFeatures.ElementExtensions) return;\n      Object.extend(Methods, Element.Methods);\n      Object.extend(Methods, Element.Methods.Simulated);\n\n      EXTENDED = {};\n    };\n  }\n\n  function addFormMethods() {\n    Object.extend(Form, Form.Methods);\n    Object.extend(Form.Element, Form.Element.Methods);\n    Object.extend(Element.Methods.ByTag, {\n      \"FORM\":     Object.clone(Form.Methods),\n      \"INPUT\":    Object.clone(Form.Element.Methods),\n      \"SELECT\":   Object.clone(Form.Element.Methods),\n      \"TEXTAREA\": Object.clone(Form.Element.Methods),\n      \"BUTTON\":   Object.clone(Form.Element.Methods)\n    });\n  }\n\n  Element.addMethods(methods);\n\n})(this);\n(function() {\n\n  function toDecimal(pctString) {\n    var match = pctString.match(/^(\\d+)%?$/i);\n    if (!match) return null;\n    return (Number(match[1]) / 100);\n  }\n\n  function getRawStyle(element, style) {\n    element = $(element);\n\n    var value = element.style[style];\n    if (!value || value === 'auto') {\n      var css = document.defaultView.getComputedStyle(element, null);\n      value = css ? css[style] : null;\n    }\n\n    if (style === 'opacity') return value ? parseFloat(value) : 1.0;\n    return value === 'auto' ? null : value;\n  }\n\n  function getRawStyle_IE(element, style) {\n    var value = element.style[style];\n    if (!value && element.currentStyle) {\n      value = element.currentStyle[style];\n    }\n    return value;\n  }\n\n  function getContentWidth(element, context) {\n    var boxWidth = element.offsetWidth;\n\n    var bl = getPixelValue(element, 'borderLeftWidth',  context) || 0;\n    var br = getPixelValue(element, 'borderRightWidth', context) || 0;\n    var pl = getPixelValue(element, 'paddingLeft',      context) || 0;\n    var pr = getPixelValue(element, 'paddingRight',     context) || 0;\n\n    return boxWidth - bl - br - pl - pr;\n  }\n\n  if ('currentStyle' in document.documentElement) {\n    getRawStyle = getRawStyle_IE;\n  }\n\n\n  function getPixelValue(value, property, context) {\n    var element = null;\n    if (Object.isElement(value)) {\n      element = value;\n      value = getRawStyle(element, property);\n    }\n\n    if (value === null || Object.isUndefined(value)) {\n      return null;\n    }\n\n    if ((/^(?:-)?\\d+(\\.\\d+)?(px)?$/i).test(value)) {\n      return window.parseFloat(value);\n    }\n\n    var isPercentage = value.include('%'), isViewport = (context === document.viewport);\n\n    if (/\\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {\n      var style = element.style.left, rStyle = element.runtimeStyle.left;\n      element.runtimeStyle.left = element.currentStyle.left;\n      element.style.left = value || 0;\n      value = element.style.pixelLeft;\n      element.style.left = style;\n      element.runtimeStyle.left = rStyle;\n\n      return value;\n    }\n\n    if (element && isPercentage) {\n      context = context || element.parentNode;\n      var decimal = toDecimal(value), whole = null;\n\n      var isHorizontal = property.include('left') || property.include('right') ||\n       property.include('width');\n\n      var isVertical   = property.include('top') || property.include('bottom') ||\n        property.include('height');\n\n      if (context === document.viewport) {\n        if (isHorizontal) {\n          whole = document.viewport.getWidth();\n        } else if (isVertical) {\n          whole = document.viewport.getHeight();\n        }\n      } else {\n        if (isHorizontal) {\n          whole = $(context).measure('width');\n        } else if (isVertical) {\n          whole = $(context).measure('height');\n        }\n      }\n\n      return (whole === null) ? 0 : whole * decimal;\n    }\n\n    return 0;\n  }\n\n  function toCSSPixels(number) {\n    if (Object.isString(number) && number.endsWith('px'))\n      return number;\n    return number + 'px';\n  }\n\n  function isDisplayed(element) {\n    while (element && element.parentNode) {\n      var display = element.getStyle('display');\n      if (display === 'none') {\n        return false;\n      }\n      element = $(element.parentNode);\n    }\n    return true;\n  }\n\n  var hasLayout = Prototype.K;\n  if ('currentStyle' in document.documentElement) {\n    hasLayout = function(element) {\n      if (!element.currentStyle.hasLayout) {\n        element.style.zoom = 1;\n      }\n      return element;\n    };\n  }\n\n  function cssNameFor(key) {\n    if (key.include('border')) key = key + '-width';\n    return key.camelize();\n  }\n\n  Element.Layout = Class.create(Hash, {\n    initialize: function($super, element, preCompute) {\n      $super();\n      this.element = $(element);\n\n      Element.Layout.PROPERTIES.each( function(property) {\n        this._set(property, null);\n      }, this);\n\n      if (preCompute) {\n        this._preComputing = true;\n        this._begin();\n        Element.Layout.PROPERTIES.each( this._compute, this );\n        this._end();\n        this._preComputing = false;\n      }\n    },\n\n    _set: function(property, value) {\n      return Hash.prototype.set.call(this, property, value);\n    },\n\n    set: function(property, value) {\n      throw \"Properties of Element.Layout are read-only.\";\n    },\n\n    get: function($super, property) {\n      var value = $super(property);\n      return value === null ? this._compute(property) : value;\n    },\n\n    _begin: function() {\n      if (this._isPrepared()) return;\n\n      var element = this.element;\n      if (isDisplayed(element)) {\n        this._setPrepared(true);\n        return;\n      }\n\n\n      var originalStyles = {\n        position:   element.style.position   || '',\n        width:      element.style.width      || '',\n        visibility: element.style.visibility || '',\n        display:    element.style.display    || ''\n      };\n\n      element.store('prototype_original_styles', originalStyles);\n\n      var position = getRawStyle(element, 'position'), width = element.offsetWidth;\n\n      if (width === 0 || width === null) {\n        element.style.display = 'block';\n        width = element.offsetWidth;\n      }\n\n      var context = (position === 'fixed') ? document.viewport :\n       element.parentNode;\n\n      var tempStyles = {\n        visibility: 'hidden',\n        display:    'block'\n      };\n\n      if (position !== 'fixed') tempStyles.position = 'absolute';\n\n      element.setStyle(tempStyles);\n\n      var positionedWidth = element.offsetWidth, newWidth;\n      if (width && (positionedWidth === width)) {\n        newWidth = getContentWidth(element, context);\n      } else if (position === 'absolute' || position === 'fixed') {\n        newWidth = getContentWidth(element, context);\n      } else {\n        var parent = element.parentNode, pLayout = $(parent).getLayout();\n\n        newWidth = pLayout.get('width') -\n         this.get('margin-left') -\n         this.get('border-left') -\n         this.get('padding-left') -\n         this.get('padding-right') -\n         this.get('border-right') -\n         this.get('margin-right');\n      }\n\n      element.setStyle({ width: newWidth + 'px' });\n\n      this._setPrepared(true);\n    },\n\n    _end: function() {\n      var element = this.element;\n      var originalStyles = element.retrieve('prototype_original_styles');\n      element.store('prototype_original_styles', null);\n      element.setStyle(originalStyles);\n      this._setPrepared(false);\n    },\n\n    _compute: function(property) {\n      var COMPUTATIONS = Element.Layout.COMPUTATIONS;\n      if (!(property in COMPUTATIONS)) {\n        throw \"Property not found.\";\n      }\n\n      return this._set(property, COMPUTATIONS[property].call(this, this.element));\n    },\n\n    _isPrepared: function() {\n      return this.element.retrieve('prototype_element_layout_prepared', false);\n    },\n\n    _setPrepared: function(bool) {\n      return this.element.store('prototype_element_layout_prepared', bool);\n    },\n\n    toObject: function() {\n      var args = $A(arguments);\n      var keys = (args.length === 0) ? Element.Layout.PROPERTIES :\n       args.join(' ').split(' ');\n      var obj = {};\n      keys.each( function(key) {\n        if (!Element.Layout.PROPERTIES.include(key)) return;\n        var value = this.get(key);\n        if (value != null) obj[key] = value;\n      }, this);\n      return obj;\n    },\n\n    toHash: function() {\n      var obj = this.toObject.apply(this, arguments);\n      return new Hash(obj);\n    },\n\n    toCSS: function() {\n      var args = $A(arguments);\n      var keys = (args.length === 0) ? Element.Layout.PROPERTIES :\n       args.join(' ').split(' ');\n      var css = {};\n\n      keys.each( function(key) {\n        if (!Element.Layout.PROPERTIES.include(key)) return;\n        if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return;\n\n        var value = this.get(key);\n        if (value != null) css[cssNameFor(key)] = value + 'px';\n      }, this);\n      return css;\n    },\n\n    inspect: function() {\n      return \"#<Element.Layout>\";\n    }\n  });\n\n  Object.extend(Element.Layout, {\n    PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'),\n\n    COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'),\n\n    COMPUTATIONS: {\n      'height': function(element) {\n        if (!this._preComputing) this._begin();\n\n        var bHeight = this.get('border-box-height');\n        if (bHeight <= 0) {\n          if (!this._preComputing) this._end();\n          return 0;\n        }\n\n        var bTop = this.get('border-top'),\n         bBottom = this.get('border-bottom');\n\n        var pTop = this.get('padding-top'),\n         pBottom = this.get('padding-bottom');\n\n        if (!this._preComputing) this._end();\n\n        return bHeight - bTop - bBottom - pTop - pBottom;\n      },\n\n      'width': function(element) {\n        if (!this._preComputing) this._begin();\n\n        var bWidth = this.get('border-box-width');\n        if (bWidth <= 0) {\n          if (!this._preComputing) this._end();\n          return 0;\n        }\n\n        var bLeft = this.get('border-left'),\n         bRight = this.get('border-right');\n\n        var pLeft = this.get('padding-left'),\n         pRight = this.get('padding-right');\n\n        if (!this._preComputing) this._end();\n        return bWidth - bLeft - bRight - pLeft - pRight;\n      },\n\n      'padding-box-height': function(element) {\n        var height = this.get('height'),\n         pTop = this.get('padding-top'),\n         pBottom = this.get('padding-bottom');\n\n        return height + pTop + pBottom;\n      },\n\n      'padding-box-width': function(element) {\n        var width = this.get('width'),\n         pLeft = this.get('padding-left'),\n         pRight = this.get('padding-right');\n\n        return width + pLeft + pRight;\n      },\n\n      'border-box-height': function(element) {\n        if (!this._preComputing) this._begin();\n        var height = element.offsetHeight;\n        if (!this._preComputing) this._end();\n        return height;\n      },\n\n      'border-box-width': function(element) {\n        if (!this._preComputing) this._begin();\n        var width = element.offsetWidth;\n        if (!this._preComputing) this._end();\n        return width;\n      },\n\n      'margin-box-height': function(element) {\n        var bHeight = this.get('border-box-height'),\n         mTop = this.get('margin-top'),\n         mBottom = this.get('margin-bottom');\n\n        if (bHeight <= 0) return 0;\n\n        return bHeight + mTop + mBottom;\n      },\n\n      'margin-box-width': function(element) {\n        var bWidth = this.get('border-box-width'),\n         mLeft = this.get('margin-left'),\n         mRight = this.get('margin-right');\n\n        if (bWidth <= 0) return 0;\n\n        return bWidth + mLeft + mRight;\n      },\n\n      'top': function(element) {\n        var offset = element.positionedOffset();\n        return offset.top;\n      },\n\n      'bottom': function(element) {\n        var offset = element.positionedOffset(),\n         parent = element.getOffsetParent(),\n         pHeight = parent.measure('height');\n\n        var mHeight = this.get('border-box-height');\n\n        return pHeight - mHeight - offset.top;\n      },\n\n      'left': function(element) {\n        var offset = element.positionedOffset();\n        return offset.left;\n      },\n\n      'right': function(element) {\n        var offset = element.positionedOffset(),\n         parent = element.getOffsetParent(),\n         pWidth = parent.measure('width');\n\n        var mWidth = this.get('border-box-width');\n\n        return pWidth - mWidth - offset.left;\n      },\n\n      'padding-top': function(element) {\n        return getPixelValue(element, 'paddingTop');\n      },\n\n      'padding-bottom': function(element) {\n        return getPixelValue(element, 'paddingBottom');\n      },\n\n      'padding-left': function(element) {\n        return getPixelValue(element, 'paddingLeft');\n      },\n\n      'padding-right': function(element) {\n        return getPixelValue(element, 'paddingRight');\n      },\n\n      'border-top': function(element) {\n        return getPixelValue(element, 'borderTopWidth');\n      },\n\n      'border-bottom': function(element) {\n        return getPixelValue(element, 'borderBottomWidth');\n      },\n\n      'border-left': function(element) {\n        return getPixelValue(element, 'borderLeftWidth');\n      },\n\n      'border-right': function(element) {\n        return getPixelValue(element, 'borderRightWidth');\n      },\n\n      'margin-top': function(element) {\n        return getPixelValue(element, 'marginTop');\n      },\n\n      'margin-bottom': function(element) {\n        return getPixelValue(element, 'marginBottom');\n      },\n\n      'margin-left': function(element) {\n        return getPixelValue(element, 'marginLeft');\n      },\n\n      'margin-right': function(element) {\n        return getPixelValue(element, 'marginRight');\n      }\n    }\n  });\n\n  if ('getBoundingClientRect' in document.documentElement) {\n    Object.extend(Element.Layout.COMPUTATIONS, {\n      'right': function(element) {\n        var parent = hasLayout(element.getOffsetParent());\n        var rect = element.getBoundingClientRect(),\n         pRect = parent.getBoundingClientRect();\n\n        return (pRect.right - rect.right).round();\n      },\n\n      'bottom': function(element) {\n        var parent = hasLayout(element.getOffsetParent());\n        var rect = element.getBoundingClientRect(),\n         pRect = parent.getBoundingClientRect();\n\n        return (pRect.bottom - rect.bottom).round();\n      }\n    });\n  }\n\n  Element.Offset = Class.create({\n    initialize: function(left, top) {\n      this.left = left.round();\n      this.top  = top.round();\n\n      this[0] = this.left;\n      this[1] = this.top;\n    },\n\n    relativeTo: function(offset) {\n      return new Element.Offset(\n        this.left - offset.left,\n        this.top  - offset.top\n      );\n    },\n\n    inspect: function() {\n      return \"#<Element.Offset left: #{left} top: #{top}>\".interpolate(this);\n    },\n\n    toString: function() {\n      return \"[#{left}, #{top}]\".interpolate(this);\n    },\n\n    toArray: function() {\n      return [this.left, this.top];\n    }\n  });\n\n  function getLayout(element, preCompute) {\n    return new Element.Layout(element, preCompute);\n  }\n\n  function measure(element, property) {\n    return $(element).getLayout().get(property);\n  }\n\n  function getHeight(element) {\n    return Element.getDimensions(element).height;\n  }\n\n  function getWidth(element) {\n    return Element.getDimensions(element).width;\n  }\n\n  function getDimensions(element) {\n    element = $(element);\n    var display = Element.getStyle(element, 'display');\n\n    if (display && display !== 'none') {\n      return { width: element.offsetWidth, height: element.offsetHeight };\n    }\n\n    var style = element.style;\n    var originalStyles = {\n      visibility: style.visibility,\n      position:   style.position,\n      display:    style.display\n    };\n\n    var newStyles = {\n      visibility: 'hidden',\n      display:    'block'\n    };\n\n    if (originalStyles.position !== 'fixed')\n      newStyles.position = 'absolute';\n\n    Element.setStyle(element, newStyles);\n\n    var dimensions = {\n      width:  element.offsetWidth,\n      height: element.offsetHeight\n    };\n\n    Element.setStyle(element, originalStyles);\n\n    return dimensions;\n  }\n\n  function getOffsetParent(element) {\n    element = $(element);\n\n    if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))\n      return $(document.body);\n\n    var isInline = (Element.getStyle(element, 'display') === 'inline');\n    if (!isInline && element.offsetParent) return $(element.offsetParent);\n\n    while ((element = element.parentNode) && element !== document.body) {\n      if (Element.getStyle(element, 'position') !== 'static') {\n        return isHtml(element) ? $(document.body) : $(element);\n      }\n    }\n\n    return $(document.body);\n  }\n\n\n  function cumulativeOffset(element) {\n    element = $(element);\n    var valueT = 0, valueL = 0;\n    if (element.parentNode) {\n      do {\n        valueT += element.offsetTop  || 0;\n        valueL += element.offsetLeft || 0;\n        element = element.offsetParent;\n      } while (element);\n    }\n    return new Element.Offset(valueL, valueT);\n  }\n\n  function positionedOffset(element) {\n    element = $(element);\n\n    var layout = element.getLayout();\n\n    var valueT = 0, valueL = 0;\n    do {\n      valueT += element.offsetTop  || 0;\n      valueL += element.offsetLeft || 0;\n      element = element.offsetParent;\n      if (element) {\n        if (isBody(element)) break;\n        var p = Element.getStyle(element, 'position');\n        if (p !== 'static') break;\n      }\n    } while (element);\n\n    valueL -= layout.get('margin-top');\n    valueT -= layout.get('margin-left');\n\n    return new Element.Offset(valueL, valueT);\n  }\n\n  function cumulativeScrollOffset(element) {\n    var valueT = 0, valueL = 0;\n    do {\n      valueT += element.scrollTop  || 0;\n      valueL += element.scrollLeft || 0;\n      element = element.parentNode;\n    } while (element);\n    return new Element.Offset(valueL, valueT);\n  }\n\n  function viewportOffset(forElement) {\n    var valueT = 0, valueL = 0, docBody = document.body;\n\n    var element = $(forElement);\n    do {\n      valueT += element.offsetTop  || 0;\n      valueL += element.offsetLeft || 0;\n      if (element.offsetParent == docBody &&\n        Element.getStyle(element, 'position') == 'absolute') break;\n    } while (element = element.offsetParent);\n\n    element = forElement;\n    do {\n      if (element != docBody) {\n        valueT -= element.scrollTop  || 0;\n        valueL -= element.scrollLeft || 0;\n      }\n    } while (element = element.parentNode);\n    return new Element.Offset(valueL, valueT);\n  }\n\n  function absolutize(element) {\n    element = $(element);\n\n    if (Element.getStyle(element, 'position') === 'absolute') {\n      return element;\n    }\n\n    var offsetParent = getOffsetParent(element);\n    var eOffset = element.viewportOffset(),\n     pOffset = offsetParent.viewportOffset();\n\n    var offset = eOffset.relativeTo(pOffset);\n    var layout = element.getLayout();\n\n    element.store('prototype_absolutize_original_styles', {\n      left:   element.getStyle('left'),\n      top:    element.getStyle('top'),\n      width:  element.getStyle('width'),\n      height: element.getStyle('height')\n    });\n\n    element.setStyle({\n      position: 'absolute',\n      top:    offset.top + 'px',\n      left:   offset.left + 'px',\n      width:  layout.get('width') + 'px',\n      height: layout.get('height') + 'px'\n    });\n\n    return element;\n  }\n\n  function relativize(element) {\n    element = $(element);\n    if (Element.getStyle(element, 'position') === 'relative') {\n      return element;\n    }\n\n    var originalStyles =\n     element.retrieve('prototype_absolutize_original_styles');\n\n    if (originalStyles) element.setStyle(originalStyles);\n    return element;\n  }\n\n\n  function scrollTo(element) {\n    element = $(element);\n    var pos = Element.cumulativeOffset(element);\n    window.scrollTo(pos.left, pos.top);\n    return element;\n  }\n\n\n  function makePositioned(element) {\n    element = $(element);\n    var position = Element.getStyle(element, 'position'), styles = {};\n    if (position === 'static' || !position) {\n      styles.position = 'relative';\n      if (Prototype.Browser.Opera) {\n        styles.top  = 0;\n        styles.left = 0;\n      }\n      Element.setStyle(element, styles);\n      Element.store(element, 'prototype_made_positioned', true);\n    }\n    return element;\n  }\n\n  function undoPositioned(element) {\n    element = $(element);\n    var storage = Element.getStorage(element),\n     madePositioned = storage.get('prototype_made_positioned');\n\n    if (madePositioned) {\n      storage.unset('prototype_made_positioned');\n      Element.setStyle(element, {\n        position: '',\n        top:      '',\n        bottom:   '',\n        left:     '',\n        right:    ''\n      });\n    }\n    return element;\n  }\n\n  function makeClipping(element) {\n    element = $(element);\n\n    var storage = Element.getStorage(element),\n     madeClipping = storage.get('prototype_made_clipping');\n\n    if (Object.isUndefined(madeClipping)) {\n      var overflow = Element.getStyle(element, 'overflow');\n      storage.set('prototype_made_clipping', overflow);\n      if (overflow !== 'hidden')\n        element.style.overflow = 'hidden';\n    }\n\n    return element;\n  }\n\n  function undoClipping(element) {\n    element = $(element);\n    var storage = Element.getStorage(element),\n     overflow = storage.get('prototype_made_clipping');\n\n    if (!Object.isUndefined(overflow)) {\n      storage.unset('prototype_made_clipping');\n      element.style.overflow = overflow || '';\n    }\n\n    return element;\n  }\n\n  function clonePosition(element, source, options) {\n    options = Object.extend({\n      setLeft:    true,\n      setTop:     true,\n      setWidth:   true,\n      setHeight:  true,\n      offsetTop:  0,\n      offsetLeft: 0\n    }, options || {});\n\n    source  = $(source);\n    element = $(element);\n    var p, delta, layout, styles = {};\n\n    if (options.setLeft || options.setTop) {\n      p = Element.viewportOffset(source);\n      delta = [0, 0];\n      if (Element.getStyle(element, 'position') === 'absolute') {\n        var parent = Element.getOffsetParent(element);\n        if (parent !== document.body) delta = Element.viewportOffset(parent);\n      }\n    }\n\n    if (options.setWidth || options.setHeight) {\n      layout = Element.getLayout(source);\n    }\n\n    if (options.setLeft)\n      styles.left = (p[0] - delta[0] + options.offsetLeft) + 'px';\n    if (options.setTop)\n      styles.top  = (p[1] - delta[1] + options.offsetTop)  + 'px';\n\n    if (options.setWidth)\n      styles.width  = layout.get('border-box-width')  + 'px';\n    if (options.setHeight)\n      styles.height = layout.get('border-box-height') + 'px';\n\n    return Element.setStyle(element, styles);\n  }\n\n\n  if (Prototype.Browser.IE) {\n    getOffsetParent = getOffsetParent.wrap(\n      function(proceed, element) {\n        element = $(element);\n\n        if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))\n          return $(document.body);\n\n        var position = element.getStyle('position');\n        if (position !== 'static') return proceed(element);\n\n        element.setStyle({ position: 'relative' });\n        var value = proceed(element);\n        element.setStyle({ position: position });\n        return value;\n      }\n    );\n\n    positionedOffset = positionedOffset.wrap(function(proceed, element) {\n      element = $(element);\n      if (!element.parentNode) return new Element.Offset(0, 0);\n      var position = element.getStyle('position');\n      if (position !== 'static') return proceed(element);\n\n      var offsetParent = element.getOffsetParent();\n      if (offsetParent && offsetParent.getStyle('position') === 'fixed')\n        hasLayout(offsetParent);\n\n      element.setStyle({ position: 'relative' });\n      var value = proceed(element);\n      element.setStyle({ position: position });\n      return value;\n    });\n  } else if (Prototype.Browser.Webkit) {\n    cumulativeOffset = function(element) {\n      element = $(element);\n      var valueT = 0, valueL = 0;\n      do {\n        valueT += element.offsetTop  || 0;\n        valueL += element.offsetLeft || 0;\n        if (element.offsetParent == document.body) {\n          if (Element.getStyle(element, 'position') == 'absolute') break;\n        }\n\n        element = element.offsetParent;\n      } while (element);\n\n      return new Element.Offset(valueL, valueT);\n    };\n  }\n\n\n  Element.addMethods({\n    getLayout:              getLayout,\n    measure:                measure,\n    getWidth:               getWidth,\n    getHeight:              getHeight,\n    getDimensions:          getDimensions,\n    getOffsetParent:        getOffsetParent,\n    cumulativeOffset:       cumulativeOffset,\n    positionedOffset:       positionedOffset,\n    cumulativeScrollOffset: cumulativeScrollOffset,\n    viewportOffset:         viewportOffset,\n    absolutize:             absolutize,\n    relativize:             relativize,\n    scrollTo:               scrollTo,\n    makePositioned:         makePositioned,\n    undoPositioned:         undoPositioned,\n    makeClipping:           makeClipping,\n    undoClipping:           undoClipping,\n    clonePosition:          clonePosition\n  });\n\n  function isBody(element) {\n    return element.nodeName.toUpperCase() === 'BODY';\n  }\n\n  function isHtml(element) {\n    return element.nodeName.toUpperCase() === 'HTML';\n  }\n\n  function isDocument(element) {\n    return element.nodeType === Node.DOCUMENT_NODE;\n  }\n\n  function isDetached(element) {\n    return element !== document.body &&\n     !Element.descendantOf(element, document.body);\n  }\n\n  if ('getBoundingClientRect' in document.documentElement) {\n    Element.addMethods({\n      viewportOffset: function(element) {\n        element = $(element);\n        if (isDetached(element)) return new Element.Offset(0, 0);\n\n        var rect = element.getBoundingClientRect(),\n         docEl = document.documentElement;\n        return new Element.Offset(rect.left - docEl.clientLeft,\n         rect.top - docEl.clientTop);\n      }\n    });\n  }\n\n\n})();\n\n(function() {\n\n  var IS_OLD_OPERA = Prototype.Browser.Opera &&\n   (window.parseFloat(window.opera.version()) < 9.5);\n  var ROOT = null;\n  function getRootElement() {\n    if (ROOT) return ROOT;\n    ROOT = IS_OLD_OPERA ? document.body : document.documentElement;\n    return ROOT;\n  }\n\n  function getDimensions() {\n    return { width: this.getWidth(), height: this.getHeight() };\n  }\n\n  function getWidth() {\n    return getRootElement().clientWidth;\n  }\n\n  function getHeight() {\n    return getRootElement().clientHeight;\n  }\n\n  function getScrollOffsets() {\n    var x = window.pageXOffset || document.documentElement.scrollLeft ||\n     document.body.scrollLeft;\n    var y = window.pageYOffset || document.documentElement.scrollTop ||\n     document.body.scrollTop;\n\n    return new Element.Offset(x, y);\n  }\n\n  document.viewport = {\n    getDimensions:    getDimensions,\n    getWidth:         getWidth,\n    getHeight:        getHeight,\n    getScrollOffsets: getScrollOffsets\n  };\n\n})();\nwindow.$$ = function() {\n  var expression = $A(arguments).join(', ');\n  return Prototype.Selector.select(expression, document);\n};\n\nPrototype.Selector = (function() {\n\n  function select() {\n    throw new Error('Method \"Prototype.Selector.select\" must be defined.');\n  }\n\n  function match() {\n    throw new Error('Method \"Prototype.Selector.match\" must be defined.');\n  }\n\n  function find(elements, expression, index) {\n    index = index || 0;\n    var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i;\n\n    for (i = 0; i < length; i++) {\n      if (match(elements[i], expression) && index == matchIndex++) {\n        return Element.extend(elements[i]);\n      }\n    }\n  }\n\n  function extendElements(elements) {\n    for (var i = 0, length = elements.length; i < length; i++) {\n      Element.extend(elements[i]);\n    }\n    return elements;\n  }\n\n\n  var K = Prototype.K;\n\n  return {\n    select: select,\n    match: match,\n    find: find,\n    extendElements: (Element.extend === K) ? K : extendElements,\n    extendElement: Element.extend\n  };\n})();\n/*!\n * Sizzle CSS Selector Engine\n *  Copyright 2011, The Dojo Foundation\n *  Released under the MIT, BSD, and GPL Licenses.\n *  More information: http://sizzlejs.com/\n */\n(function(){\n\nvar chunker = /((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,\n\tdone = 0,\n\ttoString = Object.prototype.toString,\n\thasDuplicate = false,\n\tbaseHasDuplicate = true,\n\trBackslash = /\\\\/g,\n\trNonWord = /\\W/;\n\n[0, 0].sort(function() {\n\tbaseHasDuplicate = false;\n\treturn 0;\n});\n\nvar Sizzle = function( selector, context, results, seed ) {\n\tresults = results || [];\n\tcontext = context || document;\n\n\tvar origContext = context;\n\n\tif ( context.nodeType !== 1 && context.nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tvar m, set, checkSet, extra, ret, cur, pop, i,\n\t\tprune = true,\n\t\tcontextXML = Sizzle.isXML( context ),\n\t\tparts = [],\n\t\tsoFar = selector;\n\n\tdo {\n\t\tchunker.exec( \"\" );\n\t\tm = chunker.exec( soFar );\n\n\t\tif ( m ) {\n\t\t\tsoFar = m[3];\n\n\t\t\tparts.push( m[1] );\n\n\t\t\tif ( m[2] ) {\n\t\t\t\textra = m[3];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} while ( m );\n\n\tif ( parts.length > 1 && origPOS.exec( selector ) ) {\n\n\t\tif ( parts.length === 2 && Expr.relative[ parts[0] ] ) {\n\t\t\tset = posProcess( parts[0] + parts[1], context );\n\n\t\t} else {\n\t\t\tset = Expr.relative[ parts[0] ] ?\n\t\t\t\t[ context ] :\n\t\t\t\tSizzle( parts.shift(), context );\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tselector = parts.shift();\n\n\t\t\t\tif ( Expr.relative[ selector ] ) {\n\t\t\t\t\tselector += parts.shift();\n\t\t\t\t}\n\n\t\t\t\tset = posProcess( selector, set );\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tif ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&\n\t\t\t\tExpr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {\n\n\t\t\tret = Sizzle.find( parts.shift(), context, contextXML );\n\t\t\tcontext = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set )[0] :\n\t\t\t\tret.set[0];\n\t\t}\n\n\t\tif ( context ) {\n\t\t\tret = seed ?\n\t\t\t\t{ expr: parts.pop(), set: makeArray(seed) } :\n\t\t\t\tSizzle.find( parts.pop(), parts.length === 1 && (parts[0] === \"~\" || parts[0] === \"+\") && context.parentNode ? context.parentNode : context, contextXML );\n\n\t\t\tset = ret.expr ?\n\t\t\t\tSizzle.filter( ret.expr, ret.set ) :\n\t\t\t\tret.set;\n\n\t\t\tif ( parts.length > 0 ) {\n\t\t\t\tcheckSet = makeArray( set );\n\n\t\t\t} else {\n\t\t\t\tprune = false;\n\t\t\t}\n\n\t\t\twhile ( parts.length ) {\n\t\t\t\tcur = parts.pop();\n\t\t\t\tpop = cur;\n\n\t\t\t\tif ( !Expr.relative[ cur ] ) {\n\t\t\t\t\tcur = \"\";\n\t\t\t\t} else {\n\t\t\t\t\tpop = parts.pop();\n\t\t\t\t}\n\n\t\t\t\tif ( pop == null ) {\n\t\t\t\t\tpop = context;\n\t\t\t\t}\n\n\t\t\t\tExpr.relative[ cur ]( checkSet, pop, contextXML );\n\t\t\t}\n\n\t\t} else {\n\t\t\tcheckSet = parts = [];\n\t\t}\n\t}\n\n\tif ( !checkSet ) {\n\t\tcheckSet = set;\n\t}\n\n\tif ( !checkSet ) {\n\t\tSizzle.error( cur || selector );\n\t}\n\n\tif ( toString.call(checkSet) === \"[object Array]\" ) {\n\t\tif ( !prune ) {\n\t\t\tresults.push.apply( results, checkSet );\n\n\t\t} else if ( context && context.nodeType === 1 ) {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\t\t\tfor ( i = 0; checkSet[i] != null; i++ ) {\n\t\t\t\tif ( checkSet[i] && checkSet[i].nodeType === 1 ) {\n\t\t\t\t\tresults.push( set[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tmakeArray( checkSet, results );\n\t}\n\n\tif ( extra ) {\n\t\tSizzle( extra, origContext, results, seed );\n\t\tSizzle.uniqueSort( results );\n\t}\n\n\treturn results;\n};\n\nSizzle.uniqueSort = function( results ) {\n\tif ( sortOrder ) {\n\t\thasDuplicate = baseHasDuplicate;\n\t\tresults.sort( sortOrder );\n\n\t\tif ( hasDuplicate ) {\n\t\t\tfor ( var i = 1; i < results.length; i++ ) {\n\t\t\t\tif ( results[i] === results[ i - 1 ] ) {\n\t\t\t\t\tresults.splice( i--, 1 );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn results;\n};\n\nSizzle.matches = function( expr, set ) {\n\treturn Sizzle( expr, null, null, set );\n};\n\nSizzle.matchesSelector = function( node, expr ) {\n\treturn Sizzle( expr, null, null, [node] ).length > 0;\n};\n\nSizzle.find = function( expr, context, isXML ) {\n\tvar set;\n\n\tif ( !expr ) {\n\t\treturn [];\n\t}\n\n\tfor ( var i = 0, l = Expr.order.length; i < l; i++ ) {\n\t\tvar match,\n\t\t\ttype = Expr.order[i];\n\n\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) ) {\n\t\t\tvar left = match[1];\n\t\t\tmatch.splice( 1, 1 );\n\n\t\t\tif ( left.substr( left.length - 1 ) !== \"\\\\\" ) {\n\t\t\t\tmatch[1] = (match[1] || \"\").replace( rBackslash, \"\" );\n\t\t\t\tset = Expr.find[ type ]( match, context, isXML );\n\n\t\t\t\tif ( set != null ) {\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( !set ) {\n\t\tset = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( \"*\" ) :\n\t\t\t[];\n\t}\n\n\treturn { set: set, expr: expr };\n};\n\nSizzle.filter = function( expr, set, inplace, not ) {\n\tvar match, anyFound,\n\t\told = expr,\n\t\tresult = [],\n\t\tcurLoop = set,\n\t\tisXMLFilter = set && set[0] && Sizzle.isXML( set[0] );\n\n\twhile ( expr && set.length ) {\n\t\tfor ( var type in Expr.filter ) {\n\t\t\tif ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {\n\t\t\t\tvar found, item,\n\t\t\t\t\tfilter = Expr.filter[ type ],\n\t\t\t\t\tleft = match[1];\n\n\t\t\t\tanyFound = false;\n\n\t\t\t\tmatch.splice(1,1);\n\n\t\t\t\tif ( left.substr( left.length - 1 ) === \"\\\\\" ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif ( curLoop === result ) {\n\t\t\t\t\tresult = [];\n\t\t\t\t}\n\n\t\t\t\tif ( Expr.preFilter[ type ] ) {\n\t\t\t\t\tmatch = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );\n\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\tanyFound = found = true;\n\n\t\t\t\t\t} else if ( match === true ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tfor ( var i = 0; (item = curLoop[i]) != null; i++ ) {\n\t\t\t\t\t\tif ( item ) {\n\t\t\t\t\t\t\tfound = filter( item, match, i, curLoop );\n\t\t\t\t\t\t\tvar pass = not ^ !!found;\n\n\t\t\t\t\t\t\tif ( inplace && found != null ) {\n\t\t\t\t\t\t\t\tif ( pass ) {\n\t\t\t\t\t\t\t\t\tanyFound = true;\n\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} else if ( pass ) {\n\t\t\t\t\t\t\t\tresult.push( item );\n\t\t\t\t\t\t\t\tanyFound = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( found !== undefined ) {\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tcurLoop = result;\n\t\t\t\t\t}\n\n\t\t\t\t\texpr = expr.replace( Expr.match[ type ], \"\" );\n\n\t\t\t\t\tif ( !anyFound ) {\n\t\t\t\t\t\treturn [];\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( expr === old ) {\n\t\t\tif ( anyFound == null ) {\n\t\t\t\tSizzle.error( expr );\n\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\told = expr;\n\t}\n\n\treturn curLoop;\n};\n\nSizzle.error = function( msg ) {\n\tthrow \"Syntax error, unrecognized expression: \" + msg;\n};\n\nvar Expr = Sizzle.selectors = {\n\torder: [ \"ID\", \"NAME\", \"TAG\" ],\n\n\tmatch: {\n\t\tID: /#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tCLASS: /\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,\n\t\tNAME: /\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,\n\t\tATTR: /\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,\n\t\tTAG: /^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,\n\t\tCHILD: /:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,\n\t\tPOS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,\n\t\tPSEUDO: /:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/\n\t},\n\n\tleftMatch: {},\n\n\tattrMap: {\n\t\t\"class\": \"className\",\n\t\t\"for\": \"htmlFor\"\n\t},\n\n\tattrHandle: {\n\t\thref: function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\" );\n\t\t},\n\t\ttype: function( elem ) {\n\t\t\treturn elem.getAttribute( \"type\" );\n\t\t}\n\t},\n\n\trelative: {\n\t\t\"+\": function(checkSet, part){\n\t\t\tvar isPartStr = typeof part === \"string\",\n\t\t\t\tisTag = isPartStr && !rNonWord.test( part ),\n\t\t\t\tisPartStrNotTag = isPartStr && !isTag;\n\n\t\t\tif ( isTag ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t}\n\n\t\t\tfor ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {\n\t\t\t\tif ( (elem = checkSet[i]) ) {\n\t\t\t\t\twhile ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}\n\n\t\t\t\t\tcheckSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?\n\t\t\t\t\t\telem || false :\n\t\t\t\t\t\telem === part;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( isPartStrNotTag ) {\n\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t}\n\t\t},\n\n\t\t\">\": function( checkSet, part ) {\n\t\t\tvar elem,\n\t\t\t\tisPartStr = typeof part === \"string\",\n\t\t\t\ti = 0,\n\t\t\t\tl = checkSet.length;\n\n\t\t\tif ( isPartStr && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tvar parent = elem.parentNode;\n\t\t\t\t\t\tcheckSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\telem = checkSet[i];\n\n\t\t\t\t\tif ( elem ) {\n\t\t\t\t\t\tcheckSet[i] = isPartStr ?\n\t\t\t\t\t\t\telem.parentNode :\n\t\t\t\t\t\t\telem.parentNode === part;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( isPartStr ) {\n\t\t\t\t\tSizzle.filter( part, checkSet, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t\"\": function(checkSet, part, isXML){\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"parentNode\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t},\n\n\t\t\"~\": function( checkSet, part, isXML ) {\n\t\t\tvar nodeCheck,\n\t\t\t\tdoneName = done++,\n\t\t\t\tcheckFn = dirCheck;\n\n\t\t\tif ( typeof part === \"string\" && !rNonWord.test( part ) ) {\n\t\t\t\tpart = part.toLowerCase();\n\t\t\t\tnodeCheck = part;\n\t\t\t\tcheckFn = dirNodeCheck;\n\t\t\t}\n\n\t\t\tcheckFn( \"previousSibling\", part, doneName, checkSet, nodeCheck, isXML );\n\t\t}\n\t},\n\n\tfind: {\n\t\tID: function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t},\n\n\t\tNAME: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByName !== \"undefined\" ) {\n\t\t\t\tvar ret = [],\n\t\t\t\t\tresults = context.getElementsByName( match[1] );\n\n\t\t\t\tfor ( var i = 0, l = results.length; i < l; i++ ) {\n\t\t\t\t\tif ( results[i].getAttribute(\"name\") === match[1] ) {\n\t\t\t\t\t\tret.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ret.length === 0 ? null : ret;\n\t\t\t}\n\t\t},\n\n\t\tTAG: function( match, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( match[1] );\n\t\t\t}\n\t\t}\n\t},\n\tpreFilter: {\n\t\tCLASS: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tmatch = \" \" + match[1].replace( rBackslash, \"\" ) + \" \";\n\n\t\t\tif ( isXML ) {\n\t\t\t\treturn match;\n\t\t\t}\n\n\t\t\tfor ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {\n\t\t\t\tif ( elem ) {\n\t\t\t\t\tif ( not ^ (elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(match) >= 0) ) {\n\t\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\t\tresult.push( elem );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( inplace ) {\n\t\t\t\t\t\tcurLoop[i] = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\tID: function( match ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" );\n\t\t},\n\n\t\tTAG: function( match, curLoop ) {\n\t\t\treturn match[1].replace( rBackslash, \"\" ).toLowerCase();\n\t\t},\n\n\t\tCHILD: function( match ) {\n\t\t\tif ( match[1] === \"nth\" ) {\n\t\t\t\tif ( !match[2] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\tmatch[2] = match[2].replace(/^\\+|\\s*/g, '');\n\n\t\t\t\tvar test = /(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(\n\t\t\t\t\tmatch[2] === \"even\" && \"2n\" || match[2] === \"odd\" && \"2n+1\" ||\n\t\t\t\t\t!/\\D/.test( match[2] ) && \"0n+\" + match[2] || match[2]);\n\n\t\t\t\tmatch[2] = (test[1] + (test[2] || 1)) - 0;\n\t\t\t\tmatch[3] = test[3] - 0;\n\t\t\t}\n\t\t\telse if ( match[2] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\tmatch[0] = done++;\n\n\t\t\treturn match;\n\t\t},\n\n\t\tATTR: function( match, curLoop, inplace, result, not, isXML ) {\n\t\t\tvar name = match[1] = match[1].replace( rBackslash, \"\" );\n\n\t\t\tif ( !isXML && Expr.attrMap[name] ) {\n\t\t\t\tmatch[1] = Expr.attrMap[name];\n\t\t\t}\n\n\t\t\tmatch[4] = ( match[4] || match[5] || \"\" ).replace( rBackslash, \"\" );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[4] = \" \" + match[4] + \" \";\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPSEUDO: function( match, curLoop, inplace, result, not ) {\n\t\t\tif ( match[1] === \"not\" ) {\n\t\t\t\tif ( ( chunker.exec(match[3]) || \"\" ).length > 1 || /^\\w/.test(match[3]) ) {\n\t\t\t\t\tmatch[3] = Sizzle(match[3], null, null, curLoop);\n\n\t\t\t\t} else {\n\t\t\t\t\tvar ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);\n\n\t\t\t\t\tif ( !inplace ) {\n\t\t\t\t\t\tresult.push.apply( result, ret );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\tPOS: function( match ) {\n\t\t\tmatch.unshift( true );\n\n\t\t\treturn match;\n\t\t}\n\t},\n\n\tfilters: {\n\t\tenabled: function( elem ) {\n\t\t\treturn elem.disabled === false && elem.type !== \"hidden\";\n\t\t},\n\n\t\tdisabled: function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\tchecked: function( elem ) {\n\t\t\treturn elem.checked === true;\n\t\t},\n\n\t\tselected: function( elem ) {\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\tparent: function( elem ) {\n\t\t\treturn !!elem.firstChild;\n\t\t},\n\n\t\tempty: function( elem ) {\n\t\t\treturn !elem.firstChild;\n\t\t},\n\n\t\thas: function( elem, i, match ) {\n\t\t\treturn !!Sizzle( match[3], elem ).length;\n\t\t},\n\n\t\theader: function( elem ) {\n\t\t\treturn (/h\\d/i).test( elem.nodeName );\n\t\t},\n\n\t\ttext: function( elem ) {\n\t\t\tvar attr = elem.getAttribute( \"type\" ), type = elem.type;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"text\" === type && ( attr === type || attr === null );\n\t\t},\n\n\t\tradio: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"radio\" === elem.type;\n\t\t},\n\n\t\tcheckbox: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"checkbox\" === elem.type;\n\t\t},\n\n\t\tfile: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"file\" === elem.type;\n\t\t},\n\n\t\tpassword: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"password\" === elem.type;\n\t\t},\n\n\t\tsubmit: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"submit\" === elem.type;\n\t\t},\n\n\t\timage: function( elem ) {\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" && \"image\" === elem.type;\n\t\t},\n\n\t\treset: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn (name === \"input\" || name === \"button\") && \"reset\" === elem.type;\n\t\t},\n\n\t\tbutton: function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && \"button\" === elem.type || name === \"button\";\n\t\t},\n\n\t\tinput: function( elem ) {\n\t\t\treturn (/input|select|textarea|button/i).test( elem.nodeName );\n\t\t},\n\n\t\tfocus: function( elem ) {\n\t\t\treturn elem === elem.ownerDocument.activeElement;\n\t\t}\n\t},\n\tsetFilters: {\n\t\tfirst: function( elem, i ) {\n\t\t\treturn i === 0;\n\t\t},\n\n\t\tlast: function( elem, i, match, array ) {\n\t\t\treturn i === array.length - 1;\n\t\t},\n\n\t\teven: function( elem, i ) {\n\t\t\treturn i % 2 === 0;\n\t\t},\n\n\t\todd: function( elem, i ) {\n\t\t\treturn i % 2 === 1;\n\t\t},\n\n\t\tlt: function( elem, i, match ) {\n\t\t\treturn i < match[3] - 0;\n\t\t},\n\n\t\tgt: function( elem, i, match ) {\n\t\t\treturn i > match[3] - 0;\n\t\t},\n\n\t\tnth: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t},\n\n\t\teq: function( elem, i, match ) {\n\t\t\treturn match[3] - 0 === i;\n\t\t}\n\t},\n\tfilter: {\n\t\tPSEUDO: function( elem, match, i, array ) {\n\t\t\tvar name = match[1],\n\t\t\t\tfilter = Expr.filters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\n\t\t\t} else if ( name === \"contains\" ) {\n\t\t\t\treturn (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || \"\").indexOf(match[3]) >= 0;\n\n\t\t\t} else if ( name === \"not\" ) {\n\t\t\t\tvar not = match[3];\n\n\t\t\t\tfor ( var j = 0, l = not.length; j < l; j++ ) {\n\t\t\t\t\tif ( not[j] === elem ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\n\t\t\t} else {\n\t\t\t\tSizzle.error( name );\n\t\t\t}\n\t\t},\n\n\t\tCHILD: function( elem, match ) {\n\t\t\tvar type = match[1],\n\t\t\t\tnode = elem;\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"only\":\n\t\t\t\tcase \"first\":\n\t\t\t\t\twhile ( (node = node.previousSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( type === \"first\" ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tnode = elem;\n\n\t\t\t\tcase \"last\":\n\t\t\t\t\twhile ( (node = node.nextSibling) )\t {\n\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true;\n\n\t\t\t\tcase \"nth\":\n\t\t\t\t\tvar first = match[2],\n\t\t\t\t\t\tlast = match[3];\n\n\t\t\t\t\tif ( first === 1 && last === 0 ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar doneName = match[0],\n\t\t\t\t\t\tparent = elem.parentNode;\n\n\t\t\t\t\tif ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {\n\t\t\t\t\t\tvar count = 0;\n\n\t\t\t\t\t\tfor ( node = parent.firstChild; node; node = node.nextSibling ) {\n\t\t\t\t\t\t\tif ( node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\tnode.nodeIndex = ++count;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent.sizcache = doneName;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar diff = elem.nodeIndex - last;\n\n\t\t\t\t\tif ( first === 0 ) {\n\t\t\t\t\t\treturn diff === 0;\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tID: function( elem, match ) {\n\t\t\treturn elem.nodeType === 1 && elem.getAttribute(\"id\") === match;\n\t\t},\n\n\t\tTAG: function( elem, match ) {\n\t\t\treturn (match === \"*\" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;\n\t\t},\n\n\t\tCLASS: function( elem, match ) {\n\t\t\treturn (\" \" + (elem.className || elem.getAttribute(\"class\")) + \" \")\n\t\t\t\t.indexOf( match ) > -1;\n\t\t},\n\n\t\tATTR: function( elem, match ) {\n\t\t\tvar name = match[1],\n\t\t\t\tresult = Expr.attrHandle[ name ] ?\n\t\t\t\t\tExpr.attrHandle[ name ]( elem ) :\n\t\t\t\t\telem[ name ] != null ?\n\t\t\t\t\t\telem[ name ] :\n\t\t\t\t\t\telem.getAttribute( name ),\n\t\t\t\tvalue = result + \"\",\n\t\t\t\ttype = match[2],\n\t\t\t\tcheck = match[4];\n\n\t\t\treturn result == null ?\n\t\t\t\ttype === \"!=\" :\n\t\t\t\ttype === \"=\" ?\n\t\t\t\tvalue === check :\n\t\t\t\ttype === \"*=\" ?\n\t\t\t\tvalue.indexOf(check) >= 0 :\n\t\t\t\ttype === \"~=\" ?\n\t\t\t\t(\" \" + value + \" \").indexOf(check) >= 0 :\n\t\t\t\t!check ?\n\t\t\t\tvalue && result !== false :\n\t\t\t\ttype === \"!=\" ?\n\t\t\t\tvalue !== check :\n\t\t\t\ttype === \"^=\" ?\n\t\t\t\tvalue.indexOf(check) === 0 :\n\t\t\t\ttype === \"$=\" ?\n\t\t\t\tvalue.substr(value.length - check.length) === check :\n\t\t\t\ttype === \"|=\" ?\n\t\t\t\tvalue === check || value.substr(0, check.length + 1) === check + \"-\" :\n\t\t\t\tfalse;\n\t\t},\n\n\t\tPOS: function( elem, match, i, array ) {\n\t\t\tvar name = match[2],\n\t\t\t\tfilter = Expr.setFilters[ name ];\n\n\t\t\tif ( filter ) {\n\t\t\t\treturn filter( elem, i, match, array );\n\t\t\t}\n\t\t}\n\t}\n};\n\nvar origPOS = Expr.match.POS,\n\tfescape = function(all, num){\n\t\treturn \"\\\\\" + (num - 0 + 1);\n\t};\n\nfor ( var type in Expr.match ) {\n\tExpr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\\[]*\\])(?![^\\(]*\\))/.source) );\n\tExpr.leftMatch[ type ] = new RegExp( /(^(?:.|\\r|\\n)*?)/.source + Expr.match[ type ].source.replace(/\\\\(\\d+)/g, fescape) );\n}\n\nvar makeArray = function( array, results ) {\n\tarray = Array.prototype.slice.call( array, 0 );\n\n\tif ( results ) {\n\t\tresults.push.apply( results, array );\n\t\treturn results;\n\t}\n\n\treturn array;\n};\n\ntry {\n\tArray.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;\n\n} catch( e ) {\n\tmakeArray = function( array, results ) {\n\t\tvar i = 0,\n\t\t\tret = results || [];\n\n\t\tif ( toString.call(array) === \"[object Array]\" ) {\n\t\t\tArray.prototype.push.apply( ret, array );\n\n\t\t} else {\n\t\t\tif ( typeof array.length === \"number\" ) {\n\t\t\t\tfor ( var l = array.length; i < l; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tfor ( ; array[i]; i++ ) {\n\t\t\t\t\tret.push( array[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n}\n\nvar sortOrder, siblingCheck;\n\nif ( document.documentElement.compareDocumentPosition ) {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {\n\t\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition(b) & 4 ? -1 : 1;\n\t};\n\n} else {\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t} else if ( a.sourceIndex && b.sourceIndex ) {\n\t\t\treturn a.sourceIndex - b.sourceIndex;\n\t\t}\n\n\t\tvar al, bl,\n\t\t\tap = [],\n\t\t\tbp = [],\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tcur = aup;\n\n\t\tif ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\n\t\t} else if ( !aup ) {\n\t\t\treturn -1;\n\n\t\t} else if ( !bup ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\twhile ( cur ) {\n\t\t\tap.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tcur = bup;\n\n\t\twhile ( cur ) {\n\t\t\tbp.unshift( cur );\n\t\t\tcur = cur.parentNode;\n\t\t}\n\n\t\tal = ap.length;\n\t\tbl = bp.length;\n\n\t\tfor ( var i = 0; i < al && i < bl; i++ ) {\n\t\t\tif ( ap[i] !== bp[i] ) {\n\t\t\t\treturn siblingCheck( ap[i], bp[i] );\n\t\t\t}\n\t\t}\n\n\t\treturn i === al ?\n\t\t\tsiblingCheck( a, bp[i], -1 ) :\n\t\t\tsiblingCheck( ap[i], b, 1 );\n\t};\n\n\tsiblingCheck = function( a, b, ret ) {\n\t\tif ( a === b ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tvar cur = a.nextSibling;\n\n\t\twhile ( cur ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\n\t\t\tcur = cur.nextSibling;\n\t\t}\n\n\t\treturn 1;\n\t};\n}\n\nSizzle.getText = function( elems ) {\n\tvar ret = \"\", elem;\n\n\tfor ( var i = 0; elems[i]; i++ ) {\n\t\telem = elems[i];\n\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\tret += elem.nodeValue;\n\n\t\t} else if ( elem.nodeType !== 8 ) {\n\t\t\tret += Sizzle.getText( elem.childNodes );\n\t\t}\n\t}\n\n\treturn ret;\n};\n\n(function(){\n\tvar form = document.createElement(\"div\"),\n\t\tid = \"script\" + (new Date()).getTime(),\n\t\troot = document.documentElement;\n\n\tform.innerHTML = \"<a name='\" + id + \"'/>\";\n\n\troot.insertBefore( form, root.firstChild );\n\n\tif ( document.getElementById( id ) ) {\n\t\tExpr.find.ID = function( match, context, isXML ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && !isXML ) {\n\t\t\t\tvar m = context.getElementById(match[1]);\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === match[1] || typeof m.getAttributeNode !== \"undefined\" && m.getAttributeNode(\"id\").nodeValue === match[1] ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\n\t\tExpr.filter.ID = function( elem, match ) {\n\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\n\t\t\treturn elem.nodeType === 1 && node && node.nodeValue === match;\n\t\t};\n\t}\n\n\troot.removeChild( form );\n\n\troot = form = null;\n})();\n\n(function(){\n\n\tvar div = document.createElement(\"div\");\n\tdiv.appendChild( document.createComment(\"\") );\n\n\tif ( div.getElementsByTagName(\"*\").length > 0 ) {\n\t\tExpr.find.TAG = function( match, context ) {\n\t\t\tvar results = context.getElementsByTagName( match[1] );\n\n\t\t\tif ( match[1] === \"*\" ) {\n\t\t\t\tvar tmp = [];\n\n\t\t\t\tfor ( var i = 0; results[i]; i++ ) {\n\t\t\t\t\tif ( results[i].nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( results[i] );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresults = tmp;\n\t\t\t}\n\n\t\t\treturn results;\n\t\t};\n\t}\n\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\n\tif ( div.firstChild && typeof div.firstChild.getAttribute !== \"undefined\" &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") !== \"#\" ) {\n\n\t\tExpr.attrHandle.href = function( elem ) {\n\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t};\n\t}\n\n\tdiv = null;\n})();\n\nif ( document.querySelectorAll ) {\n\t(function(){\n\t\tvar oldSizzle = Sizzle,\n\t\t\tdiv = document.createElement(\"div\"),\n\t\t\tid = \"__sizzle__\";\n\n\t\tdiv.innerHTML = \"<p class='TEST'></p>\";\n\n\t\tif ( div.querySelectorAll && div.querySelectorAll(\".TEST\").length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tSizzle = function( query, context, extra, seed ) {\n\t\t\tcontext = context || document;\n\n\t\t\tif ( !seed && !Sizzle.isXML(context) ) {\n\t\t\t\tvar match = /^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec( query );\n\n\t\t\t\tif ( match && (context.nodeType === 1 || context.nodeType === 9) ) {\n\t\t\t\t\tif ( match[1] ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByTagName( query ), extra );\n\n\t\t\t\t\t} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {\n\t\t\t\t\t\treturn makeArray( context.getElementsByClassName( match[2] ), extra );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( context.nodeType === 9 ) {\n\t\t\t\t\tif ( query === \"body\" && context.body ) {\n\t\t\t\t\t\treturn makeArray( [ context.body ], extra );\n\n\t\t\t\t\t} else if ( match && match[3] ) {\n\t\t\t\t\t\tvar elem = context.getElementById( match[3] );\n\n\t\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t\tif ( elem.id === match[3] ) {\n\t\t\t\t\t\t\t\treturn makeArray( [ elem ], extra );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn makeArray( [], extra );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn makeArray( context.querySelectorAll(query), extra );\n\t\t\t\t\t} catch(qsaError) {}\n\n\t\t\t\t} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\t\tvar oldContext = context,\n\t\t\t\t\t\told = context.getAttribute( \"id\" ),\n\t\t\t\t\t\tnid = old || id,\n\t\t\t\t\t\thasParent = context.parentNode,\n\t\t\t\t\t\trelativeHierarchySelector = /^\\s*[+~]/.test( query );\n\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnid = nid.replace( /'/g, \"\\\\$&\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( relativeHierarchySelector && hasParent ) {\n\t\t\t\t\t\tcontext = context.parentNode;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !relativeHierarchySelector || hasParent ) {\n\t\t\t\t\t\t\treturn makeArray( context.querySelectorAll( \"[id='\" + nid + \"'] \" + query ), extra );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} catch(pseudoError) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\t\toldContext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn oldSizzle(query, context, extra, seed);\n\t\t};\n\n\t\tfor ( var prop in oldSizzle ) {\n\t\t\tSizzle[ prop ] = oldSizzle[ prop ];\n\t\t}\n\n\t\tdiv = null;\n\t})();\n}\n\n(function(){\n\tvar html = document.documentElement,\n\t\tmatches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;\n\n\tif ( matches ) {\n\t\tvar disconnectedMatch = !matches.call( document.createElement( \"div\" ), \"div\" ),\n\t\t\tpseudoWorks = false;\n\n\t\ttry {\n\t\t\tmatches.call( document.documentElement, \"[test!='']:sizzle\" );\n\n\t\t} catch( pseudoError ) {\n\t\t\tpseudoWorks = true;\n\t\t}\n\n\t\tSizzle.matchesSelector = function( node, expr ) {\n\t\t\texpr = expr.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g, \"='$1']\");\n\n\t\t\tif ( !Sizzle.isXML( node ) ) {\n\t\t\t\ttry {\n\t\t\t\t\tif ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {\n\t\t\t\t\t\tvar ret = matches.call( node, expr );\n\n\t\t\t\t\t\tif ( ret || !disconnectedMatch ||\n\t\t\t\t\t\t\t\tnode.document && node.document.nodeType !== 11 ) {\n\t\t\t\t\t\t\treturn ret;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\treturn Sizzle(expr, null, null, [node]).length > 0;\n\t\t};\n\t}\n})();\n\n(function(){\n\tvar div = document.createElement(\"div\");\n\n\tdiv.innerHTML = \"<div class='test e'></div><div class='test'></div>\";\n\n\tif ( !div.getElementsByClassName || div.getElementsByClassName(\"e\").length === 0 ) {\n\t\treturn;\n\t}\n\n\tdiv.lastChild.className = \"e\";\n\n\tif ( div.getElementsByClassName(\"e\").length === 1 ) {\n\t\treturn;\n\t}\n\n\tExpr.order.splice(1, 0, \"CLASS\");\n\tExpr.find.CLASS = function( match, context, isXML ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && !isXML ) {\n\t\t\treturn context.getElementsByClassName(match[1]);\n\t\t}\n\t};\n\n\tdiv = null;\n})();\n\nfunction dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem.sizcache === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 && !isXML ){\n\t\t\t\t\telem.sizcache = doneName;\n\t\t\t\t\telem.sizset = i;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeName.toLowerCase() === cur ) {\n\t\t\t\t\tmatch = elem;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nfunction dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {\n\tfor ( var i = 0, l = checkSet.length; i < l; i++ ) {\n\t\tvar elem = checkSet[i];\n\n\t\tif ( elem ) {\n\t\t\tvar match = false;\n\n\t\t\telem = elem[dir];\n\n\t\t\twhile ( elem ) {\n\t\t\t\tif ( elem.sizcache === doneName ) {\n\t\t\t\t\tmatch = checkSet[elem.sizset];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\tif ( !isXML ) {\n\t\t\t\t\t\telem.sizcache = doneName;\n\t\t\t\t\t\telem.sizset = i;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( typeof cur !== \"string\" ) {\n\t\t\t\t\t\tif ( elem === cur ) {\n\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {\n\t\t\t\t\t\tmatch = elem;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telem = elem[dir];\n\t\t\t}\n\n\t\t\tcheckSet[i] = match;\n\t\t}\n\t}\n}\n\nif ( document.documentElement.contains ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn a !== b && (a.contains ? a.contains(b) : true);\n\t};\n\n} else if ( document.documentElement.compareDocumentPosition ) {\n\tSizzle.contains = function( a, b ) {\n\t\treturn !!(a.compareDocumentPosition(b) & 16);\n\t};\n\n} else {\n\tSizzle.contains = function() {\n\t\treturn false;\n\t};\n}\n\nSizzle.isXML = function( elem ) {\n\tvar documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;\n\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\nvar posProcess = function( selector, context ) {\n\tvar match,\n\t\ttmpSet = [],\n\t\tlater = \"\",\n\t\troot = context.nodeType ? [context] : context;\n\n\twhile ( (match = Expr.match.PSEUDO.exec( selector )) ) {\n\t\tlater += match[0];\n\t\tselector = selector.replace( Expr.match.PSEUDO, \"\" );\n\t}\n\n\tselector = Expr.relative[selector] ? selector + \"*\" : selector;\n\n\tfor ( var i = 0, l = root.length; i < l; i++ ) {\n\t\tSizzle( selector, root[i], tmpSet );\n\t}\n\n\treturn Sizzle.filter( later, tmpSet );\n};\n\n\nwindow.Sizzle = Sizzle;\n\n})();\n\nPrototype._original_property = window.Sizzle;\n\n;(function(engine) {\n  var extendElements = Prototype.Selector.extendElements;\n\n  function select(selector, scope) {\n    return extendElements(engine(selector, scope || document));\n  }\n\n  function match(element, selector) {\n    return engine.matches(selector, [element]).length == 1;\n  }\n\n  Prototype.Selector.engine = engine;\n  Prototype.Selector.select = select;\n  Prototype.Selector.match = match;\n})(Sizzle);\n\nwindow.Sizzle = Prototype._original_property;\ndelete Prototype._original_property;\n\nvar Form = {\n  reset: function(form) {\n    form = $(form);\n    form.reset();\n    return form;\n  },\n\n  serializeElements: function(elements, options) {\n    if (typeof options != 'object') options = { hash: !!options };\n    else if (Object.isUndefined(options.hash)) options.hash = true;\n    var key, value, submitted = false, submit = options.submit, accumulator, initial;\n\n    if (options.hash) {\n      initial = {};\n      accumulator = function(result, key, value) {\n        if (key in result) {\n          if (!Object.isArray(result[key])) result[key] = [result[key]];\n          result[key].push(value);\n        } else result[key] = value;\n        return result;\n      };\n    } else {\n      initial = '';\n      accumulator = function(result, key, value) {\n        value = value.gsub(/(\\r)?\\n/, '\\r\\n');\n        value = encodeURIComponent(value);\n        value = value.gsub(/%20/, '+');\n        return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;\n      }\n    }\n\n    return elements.inject(initial, function(result, element) {\n      if (!element.disabled && element.name) {\n        key = element.name; value = $(element).getValue();\n        if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&\n            submit !== false && (!submit || key == submit) && (submitted = true)))) {\n          result = accumulator(result, key, value);\n        }\n      }\n      return result;\n    });\n  }\n};\n\nForm.Methods = {\n  serialize: function(form, options) {\n    return Form.serializeElements(Form.getElements(form), options);\n  },\n\n\n  getElements: function(form) {\n    var elements = $(form).getElementsByTagName('*');\n    var element, results = [], serializers = Form.Element.Serializers;\n\n    for (var i = 0; element = elements[i]; i++) {\n      if (serializers[element.tagName.toLowerCase()])\n        results.push(Element.extend(element));\n    }\n    return results;\n  },\n\n  getInputs: function(form, typeName, name) {\n    form = $(form);\n    var inputs = form.getElementsByTagName('input');\n\n    if (!typeName && !name) return $A(inputs).map(Element.extend);\n\n    for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {\n      var input = inputs[i];\n      if ((typeName && input.type != typeName) || (name && input.name != name))\n        continue;\n      matchingInputs.push(Element.extend(input));\n    }\n\n    return matchingInputs;\n  },\n\n  disable: function(form) {\n    form = $(form);\n    Form.getElements(form).invoke('disable');\n    return form;\n  },\n\n  enable: function(form) {\n    form = $(form);\n    Form.getElements(form).invoke('enable');\n    return form;\n  },\n\n  findFirstElement: function(form) {\n    var elements = $(form).getElements().findAll(function(element) {\n      return 'hidden' != element.type && !element.disabled;\n    });\n    var firstByIndex = elements.findAll(function(element) {\n      return element.hasAttribute('tabIndex') && element.tabIndex >= 0;\n    }).sortBy(function(element) { return element.tabIndex }).first();\n\n    return firstByIndex ? firstByIndex : elements.find(function(element) {\n      return /^(?:input|select|textarea)$/i.test(element.tagName);\n    });\n  },\n\n  focusFirstElement: function(form) {\n    form = $(form);\n    var element = form.findFirstElement();\n    if (element) element.activate();\n    return form;\n  },\n\n  request: function(form, options) {\n    form = $(form), options = Object.clone(options || { });\n\n    var params = options.parameters, action = form.readAttribute('action') || '';\n    if (action.blank()) action = window.location.href;\n    options.parameters = form.serialize(true);\n\n    if (params) {\n      if (Object.isString(params)) params = params.toQueryParams();\n      Object.extend(options.parameters, params);\n    }\n\n    if (form.hasAttribute('method') && !options.method)\n      options.method = form.method;\n\n    return new Ajax.Request(action, options);\n  }\n};\n\n/*--------------------------------------------------------------------------*/\n\n\nForm.Element = {\n  focus: function(element) {\n    $(element).focus();\n    return element;\n  },\n\n  select: function(element) {\n    $(element).select();\n    return element;\n  }\n};\n\nForm.Element.Methods = {\n\n  serialize: function(element) {\n    element = $(element);\n    if (!element.disabled && element.name) {\n      var value = element.getValue();\n      if (value != undefined) {\n        var pair = { };\n        pair[element.name] = value;\n        return Object.toQueryString(pair);\n      }\n    }\n    return '';\n  },\n\n  getValue: function(element) {\n    element = $(element);\n    var method = element.tagName.toLowerCase();\n    return Form.Element.Serializers[method](element);\n  },\n\n  setValue: function(element, value) {\n    element = $(element);\n    var method = element.tagName.toLowerCase();\n    Form.Element.Serializers[method](element, value);\n    return element;\n  },\n\n  clear: function(element) {\n    $(element).value = '';\n    return element;\n  },\n\n  present: function(element) {\n    return $(element).value != '';\n  },\n\n  activate: function(element) {\n    element = $(element);\n    try {\n      element.focus();\n      if (element.select && (element.tagName.toLowerCase() != 'input' ||\n          !(/^(?:button|reset|submit)$/i.test(element.type))))\n        element.select();\n    } catch (e) { }\n    return element;\n  },\n\n  disable: function(element) {\n    element = $(element);\n    element.disabled = true;\n    return element;\n  },\n\n  enable: function(element) {\n    element = $(element);\n    element.disabled = false;\n    return element;\n  }\n};\n\n/*--------------------------------------------------------------------------*/\n\nvar Field = Form.Element;\n\nvar $F = Form.Element.Methods.getValue;\n\n/*--------------------------------------------------------------------------*/\n\nForm.Element.Serializers = (function() {\n  function input(element, value) {\n    switch (element.type.toLowerCase()) {\n      case 'checkbox':\n      case 'radio':\n        return inputSelector(element, value);\n      default:\n        return valueSelector(element, value);\n    }\n  }\n\n  function inputSelector(element, value) {\n    if (Object.isUndefined(value))\n      return element.checked ? element.value : null;\n    else element.checked = !!value;\n  }\n\n  function valueSelector(element, value) {\n    if (Object.isUndefined(value)) return element.value;\n    else element.value = value;\n  }\n\n  function select(element, value) {\n    if (Object.isUndefined(value))\n      return (element.type === 'select-one' ? selectOne : selectMany)(element);\n\n    var opt, currentValue, single = !Object.isArray(value);\n    for (var i = 0, length = element.length; i < length; i++) {\n      opt = element.options[i];\n      currentValue = this.optionValue(opt);\n      if (single) {\n        if (currentValue == value) {\n          opt.selected = true;\n          return;\n        }\n      }\n      else opt.selected = value.include(currentValue);\n    }\n  }\n\n  function selectOne(element) {\n    var index = element.selectedIndex;\n    return index >= 0 ? optionValue(element.options[index]) : null;\n  }\n\n  function selectMany(element) {\n    var values, length = element.length;\n    if (!length) return null;\n\n    for (var i = 0, values = []; i < length; i++) {\n      var opt = element.options[i];\n      if (opt.selected) values.push(optionValue(opt));\n    }\n    return values;\n  }\n\n  function optionValue(opt) {\n    return Element.hasAttribute(opt, 'value') ? opt.value : opt.text;\n  }\n\n  return {\n    input:         input,\n    inputSelector: inputSelector,\n    textarea:      valueSelector,\n    select:        select,\n    selectOne:     selectOne,\n    selectMany:    selectMany,\n    optionValue:   optionValue,\n    button:        valueSelector\n  };\n})();\n\n/*--------------------------------------------------------------------------*/\n\n\nAbstract.TimedObserver = Class.create(PeriodicalExecuter, {\n  initialize: function($super, element, frequency, callback) {\n    $super(callback, frequency);\n    this.element   = $(element);\n    this.lastValue = this.getValue();\n  },\n\n  execute: function() {\n    var value = this.getValue();\n    if (Object.isString(this.lastValue) && Object.isString(value) ?\n        this.lastValue != value : String(this.lastValue) != String(value)) {\n      this.callback(this.element, value);\n      this.lastValue = value;\n    }\n  }\n});\n\nForm.Element.Observer = Class.create(Abstract.TimedObserver, {\n  getValue: function() {\n    return Form.Element.getValue(this.element);\n  }\n});\n\nForm.Observer = Class.create(Abstract.TimedObserver, {\n  getValue: function() {\n    return Form.serialize(this.element);\n  }\n});\n\n/*--------------------------------------------------------------------------*/\n\nAbstract.EventObserver = Class.create({\n  initialize: function(element, callback) {\n    this.element  = $(element);\n    this.callback = callback;\n\n    this.lastValue = this.getValue();\n    if (this.element.tagName.toLowerCase() == 'form')\n      this.registerFormCallbacks();\n    else\n      this.registerCallback(this.element);\n  },\n\n  onElementEvent: function() {\n    var value = this.getValue();\n    if (this.lastValue != value) {\n      this.callback(this.element, value);\n      this.lastValue = value;\n    }\n  },\n\n  registerFormCallbacks: function() {\n    Form.getElements(this.element).each(this.registerCallback, this);\n  },\n\n  registerCallback: function(element) {\n    if (element.type) {\n      switch (element.type.toLowerCase()) {\n        case 'checkbox':\n        case 'radio':\n          Event.observe(element, 'click', this.onElementEvent.bind(this));\n          break;\n        default:\n          Event.observe(element, 'change', this.onElementEvent.bind(this));\n          break;\n      }\n    }\n  }\n});\n\nForm.Element.EventObserver = Class.create(Abstract.EventObserver, {\n  getValue: function() {\n    return Form.Element.getValue(this.element);\n  }\n});\n\nForm.EventObserver = Class.create(Abstract.EventObserver, {\n  getValue: function() {\n    return Form.serialize(this.element);\n  }\n});\n(function(GLOBAL) {\n  var DIV = document.createElement('div');\n  var docEl = document.documentElement;\n  var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl\n   && 'onmouseleave' in docEl;\n\n  var Event = {\n    KEY_BACKSPACE: 8,\n    KEY_TAB:       9,\n    KEY_RETURN:   13,\n    KEY_ESC:      27,\n    KEY_LEFT:     37,\n    KEY_UP:       38,\n    KEY_RIGHT:    39,\n    KEY_DOWN:     40,\n    KEY_DELETE:   46,\n    KEY_HOME:     36,\n    KEY_END:      35,\n    KEY_PAGEUP:   33,\n    KEY_PAGEDOWN: 34,\n    KEY_INSERT:   45\n  };\n\n\n  var isIELegacyEvent = function(event) { return false; };\n\n  if (window.attachEvent) {\n    if (window.addEventListener) {\n      isIELegacyEvent = function(event) {\n        return !(event instanceof window.Event);\n      };\n    } else {\n      isIELegacyEvent = function(event) { return true; };\n    }\n  }\n\n  var _isButton;\n\n  function _isButtonForDOMEvents(event, code) {\n    return event.which ? (event.which === code + 1) : (event.button === code);\n  }\n\n  var legacyButtonMap = { 0: 1, 1: 4, 2: 2 };\n  function _isButtonForLegacyEvents(event, code) {\n    return event.button === legacyButtonMap[code];\n  }\n\n  function _isButtonForWebKit(event, code) {\n    switch (code) {\n      case 0: return event.which == 1 && !event.metaKey;\n      case 1: return event.which == 2 || (event.which == 1 && event.metaKey);\n      case 2: return event.which == 3;\n      default: return false;\n    }\n  }\n\n  if (window.attachEvent) {\n    if (!window.addEventListener) {\n      _isButton = _isButtonForLegacyEvents;\n    } else {\n      _isButton = function(event, code) {\n        return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) :\n         _isButtonForDOMEvents(event, code);\n      }\n    }\n  } else if (Prototype.Browser.WebKit) {\n    _isButton = _isButtonForWebKit;\n  } else {\n    _isButton = _isButtonForDOMEvents;\n  }\n\n  function isLeftClick(event)   { return _isButton(event, 0) }\n\n  function isMiddleClick(event) { return _isButton(event, 1) }\n\n  function isRightClick(event)  { return _isButton(event, 2) }\n\n  function element(event) {\n    return Element.extend(_element(event));\n  }\n\n  function _element(event) {\n    event = Event.extend(event);\n\n    var node = event.target, type = event.type,\n     currentTarget = event.currentTarget;\n\n    if (currentTarget && currentTarget.tagName) {\n      if (type === 'load' || type === 'error' ||\n        (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'\n          && currentTarget.type === 'radio'))\n            node = currentTarget;\n    }\n\n    if (node.nodeType == Node.TEXT_NODE)\n      node = node.parentNode;\n\n    return Element.extend(node);\n  }\n\n  function findElement(event, expression) {\n    var element = _element(event), match = Prototype.Selector.match;\n    if (!expression) return Element.extend(element);\n    while (element) {\n      if (Object.isElement(element) && match(element, expression))\n        return Element.extend(element);\n      element = element.parentNode;\n    }\n  }\n\n  function pointer(event) {\n    return { x: pointerX(event), y: pointerY(event) };\n  }\n\n  function pointerX(event) {\n    var docElement = document.documentElement,\n     body = document.body || { scrollLeft: 0 };\n\n    return event.pageX || (event.clientX +\n      (docElement.scrollLeft || body.scrollLeft) -\n      (docElement.clientLeft || 0));\n  }\n\n  function pointerY(event) {\n    var docElement = document.documentElement,\n     body = document.body || { scrollTop: 0 };\n\n    return  event.pageY || (event.clientY +\n       (docElement.scrollTop || body.scrollTop) -\n       (docElement.clientTop || 0));\n  }\n\n\n  function stop(event) {\n    Event.extend(event);\n    event.preventDefault();\n    event.stopPropagation();\n\n    event.stopped = true;\n  }\n\n\n  Event.Methods = {\n    isLeftClick:   isLeftClick,\n    isMiddleClick: isMiddleClick,\n    isRightClick:  isRightClick,\n\n    element:     element,\n    findElement: findElement,\n\n    pointer:  pointer,\n    pointerX: pointerX,\n    pointerY: pointerY,\n\n    stop: stop\n  };\n\n  var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {\n    m[name] = Event.Methods[name].methodize();\n    return m;\n  });\n\n  if (window.attachEvent) {\n    function _relatedTarget(event) {\n      var element;\n      switch (event.type) {\n        case 'mouseover':\n        case 'mouseenter':\n          element = event.fromElement;\n          break;\n        case 'mouseout':\n        case 'mouseleave':\n          element = event.toElement;\n          break;\n        default:\n          return null;\n      }\n      return Element.extend(element);\n    }\n\n    var additionalMethods = {\n      stopPropagation: function() { this.cancelBubble = true },\n      preventDefault:  function() { this.returnValue = false },\n      inspect: function() { return '[object Event]' }\n    };\n\n    Event.extend = function(event, element) {\n      if (!event) return false;\n\n      if (!isIELegacyEvent(event)) return event;\n\n      if (event._extendedByPrototype) return event;\n      event._extendedByPrototype = Prototype.emptyFunction;\n\n      var pointer = Event.pointer(event);\n\n      Object.extend(event, {\n        target: event.srcElement || element,\n        relatedTarget: _relatedTarget(event),\n        pageX:  pointer.x,\n        pageY:  pointer.y\n      });\n\n      Object.extend(event, methods);\n      Object.extend(event, additionalMethods);\n\n      return event;\n    };\n  } else {\n    Event.extend = Prototype.K;\n  }\n\n  if (window.addEventListener) {\n    Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;\n    Object.extend(Event.prototype, methods);\n  }\n\n  var EVENT_TRANSLATIONS = {\n    mouseenter: 'mouseover',\n    mouseleave: 'mouseout'\n  };\n\n  function getDOMEventName(eventName) {\n    return EVENT_TRANSLATIONS[eventName] || eventName;\n  }\n\n  if (MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED)\n    getDOMEventName = Prototype.K;\n\n  function getUniqueElementID(element) {\n    if (element === window) return 0;\n\n    if (typeof element._prototypeUID === 'undefined')\n      element._prototypeUID = Element.Storage.UID++;\n    return element._prototypeUID;\n  }\n\n  function getUniqueElementID_IE(element) {\n    if (element === window) return 0;\n    if (element == document) return 1;\n    return element.uniqueID;\n  }\n\n  if ('uniqueID' in DIV)\n    getUniqueElementID = getUniqueElementID_IE;\n\n  function isCustomEvent(eventName) {\n    return eventName.include(':');\n  }\n\n  Event._isCustomEvent = isCustomEvent;\n\n  function getRegistryForElement(element, uid) {\n    var CACHE = GLOBAL.Event.cache;\n    if (Object.isUndefined(uid))\n      uid = getUniqueElementID(element);\n    if (!CACHE[uid]) CACHE[uid] = { element: element };\n    return CACHE[uid];\n  }\n\n  function destroyRegistryForElement(element, uid) {\n    if (Object.isUndefined(uid))\n      uid = getUniqueElementID(element);\n    delete GLOBAL.Event.cache[uid];\n  }\n\n\n  function register(element, eventName, handler) {\n    var registry = getRegistryForElement(element);\n    if (!registry[eventName]) registry[eventName] = [];\n    var entries = registry[eventName];\n\n    var i = entries.length;\n    while (i--)\n      if (entries[i].handler === handler) return null;\n\n    var uid = getUniqueElementID(element);\n    var responder = GLOBAL.Event._createResponder(uid, eventName, handler);\n    var entry = {\n      responder: responder,\n      handler:   handler\n    };\n\n    entries.push(entry);\n    return entry;\n  }\n\n  function unregister(element, eventName, handler) {\n    var registry = getRegistryForElement(element);\n    var entries = registry[eventName];\n    if (!entries) return;\n\n    var i = entries.length, entry;\n    while (i--) {\n      if (entries[i].handler === handler) {\n        entry = entries[i];\n        break;\n      }\n    }\n\n    if (!entry) return;\n\n    var index = entries.indexOf(entry);\n    entries.splice(index, 1);\n\n    return entry;\n  }\n\n\n  function observe(element, eventName, handler) {\n    element = $(element);\n    var entry = register(element, eventName, handler);\n\n    if (entry === null) return element;\n\n    var responder = entry.responder;\n    if (isCustomEvent(eventName))\n      observeCustomEvent(element, eventName, responder);\n    else\n      observeStandardEvent(element, eventName, responder);\n\n    return element;\n  }\n\n  function observeStandardEvent(element, eventName, responder) {\n    var actualEventName = getDOMEventName(eventName);\n    if (element.addEventListener) {\n      element.addEventListener(actualEventName, responder, false);\n    } else {\n      element.attachEvent('on' + actualEventName, responder);\n    }\n  }\n\n  function observeCustomEvent(element, eventName, responder) {\n    if (element.addEventListener) {\n      element.addEventListener('dataavailable', responder, false);\n    } else {\n      element.attachEvent('ondataavailable', responder);\n      element.attachEvent('onlosecapture',   responder);\n    }\n  }\n\n  function stopObserving(element, eventName, handler) {\n    element = $(element);\n    var handlerGiven = !Object.isUndefined(handler),\n     eventNameGiven = !Object.isUndefined(eventName);\n\n    if (!eventNameGiven && !handlerGiven) {\n      stopObservingElement(element);\n      return element;\n    }\n\n    if (!handlerGiven) {\n      stopObservingEventName(element, eventName);\n      return element;\n    }\n\n    var entry = unregister(element, eventName, handler);\n\n    if (!entry) return element;\n    removeEvent(element, eventName, entry.responder);\n    return element;\n  }\n\n  function stopObservingStandardEvent(element, eventName, responder) {\n    var actualEventName = getDOMEventName(eventName);\n    if (element.removeEventListener) {\n      element.removeEventListener(actualEventName, responder, false);\n    } else {\n      element.detachEvent('on' + actualEventName, responder);\n    }\n  }\n\n  function stopObservingCustomEvent(element, eventName, responder) {\n    if (element.removeEventListener) {\n      element.removeEventListener('dataavailable', responder, false);\n    } else {\n      element.detachEvent('ondataavailable', responder);\n      element.detachEvent('onlosecapture',   responder);\n    }\n  }\n\n\n\n  function stopObservingElement(element) {\n    var uid = getUniqueElementID(element),\n     registry = getRegistryForElement(element, uid);\n\n    destroyRegistryForElement(element, uid);\n\n    var entries, i;\n    for (var eventName in registry) {\n      if (eventName === 'element') continue;\n\n      entries = registry[eventName];\n      i = entries.length;\n      while (i--)\n        removeEvent(element, eventName, entries[i].responder);\n    }\n  }\n\n  function stopObservingEventName(element, eventName) {\n    var registry = getRegistryForElement(element);\n    var entries = registry[eventName];\n    if (!entries) return;\n    delete registry[eventName];\n\n    var i = entries.length;\n    while (i--)\n      removeEvent(element, eventName, entries[i].responder);\n  }\n\n\n  function removeEvent(element, eventName, handler) {\n    if (isCustomEvent(eventName))\n      stopObservingCustomEvent(element, eventName, handler);\n    else\n      stopObservingStandardEvent(element, eventName, handler);\n  }\n\n\n\n  function getFireTarget(element) {\n    if (element !== document) return element;\n    if (document.createEvent && !element.dispatchEvent)\n      return document.documentElement;\n    return element;\n  }\n\n  function fire(element, eventName, memo, bubble) {\n    element = getFireTarget($(element));\n    if (Object.isUndefined(bubble)) bubble = true;\n    memo = memo || {};\n\n    var event = fireEvent(element, eventName, memo, bubble);\n    return Event.extend(event);\n  }\n\n  function fireEvent_DOM(element, eventName, memo, bubble) {\n    var event = document.createEvent('HTMLEvents');\n    event.initEvent('dataavailable', bubble, true);\n\n    event.eventName = eventName;\n    event.memo = memo;\n\n    element.dispatchEvent(event);\n    return event;\n  }\n\n  function fireEvent_IE(element, eventName, memo, bubble) {\n    var event = document.createEventObject();\n    event.eventType = bubble ? 'ondataavailable' : 'onlosecapture';\n\n    event.eventName = eventName;\n    event.memo = memo;\n\n    element.fireEvent(event.eventType, event);\n    return event;\n  }\n\n  var fireEvent = document.createEvent ? fireEvent_DOM : fireEvent_IE;\n\n\n\n  Event.Handler = Class.create({\n    initialize: function(element, eventName, selector, callback) {\n      this.element   = $(element);\n      this.eventName = eventName;\n      this.selector  = selector;\n      this.callback  = callback;\n      this.handler   = this.handleEvent.bind(this);\n    },\n\n\n    start: function() {\n      Event.observe(this.element, this.eventName, this.handler);\n      return this;\n    },\n\n    stop: function() {\n      Event.stopObserving(this.element, this.eventName, this.handler);\n      return this;\n    },\n\n    handleEvent: function(event) {\n      var element = Event.findElement(event, this.selector);\n      if (element) this.callback.call(this.element, event, element);\n    }\n  });\n\n  function on(element, eventName, selector, callback) {\n    element = $(element);\n    if (Object.isFunction(selector) && Object.isUndefined(callback)) {\n      callback = selector, selector = null;\n    }\n\n    return new Event.Handler(element, eventName, selector, callback).start();\n  }\n\n  Object.extend(Event, Event.Methods);\n\n  Object.extend(Event, {\n    fire:          fire,\n    observe:       observe,\n    stopObserving: stopObserving,\n    on:            on\n  });\n\n  Element.addMethods({\n    fire:          fire,\n\n    observe:       observe,\n\n    stopObserving: stopObserving,\n\n    on:            on\n  });\n\n  Object.extend(document, {\n    fire:          fire.methodize(),\n\n    observe:       observe.methodize(),\n\n    stopObserving: stopObserving.methodize(),\n\n    on:            on.methodize(),\n\n    loaded:        false\n  });\n\n  if (GLOBAL.Event) Object.extend(window.Event, Event);\n  else GLOBAL.Event = Event;\n\n  GLOBAL.Event.cache = {};\n\n  function destroyCache_IE() {\n    GLOBAL.Event.cache = null;\n  }\n\n  if (window.attachEvent)\n    window.attachEvent('onunload', destroyCache_IE);\n\n  DIV = null;\n  docEl = null;\n})(this);\n\n(function(GLOBAL) {\n  /* Code for creating leak-free event responders is based on work by\n   John-David Dalton. */\n\n  var docEl = document.documentElement;\n  var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl\n    && 'onmouseleave' in docEl;\n\n  function isSimulatedMouseEnterLeaveEvent(eventName) {\n    return !MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&\n     (eventName === 'mouseenter' || eventName === 'mouseleave');\n  }\n\n  function createResponder(uid, eventName, handler) {\n    if (Event._isCustomEvent(eventName))\n      return createResponderForCustomEvent(uid, eventName, handler);\n    if (isSimulatedMouseEnterLeaveEvent(eventName))\n      return createMouseEnterLeaveResponder(uid, eventName, handler);\n\n    return function(event) {\n      var cacheEntry = Event.cache[uid];\n      var element = cacheEntry.element;\n\n      Event.extend(event, element);\n      handler.call(element, event);\n    };\n  }\n\n  function createResponderForCustomEvent(uid, eventName, handler) {\n    return function(event) {\n      var cacheEntry = Event.cache[uid], element = cacheEntry.element;\n\n      if (Object.isUndefined(event.eventName))\n        return false;\n\n      if (event.eventName !== eventName)\n        return false;\n\n      Event.extend(event, element);\n      handler.call(element, event);\n    };\n  }\n\n  function createMouseEnterLeaveResponder(uid, eventName, handler) {\n    return function(event) {\n      var cacheEntry = Event.cache[uid], element = cacheEntry.element;\n\n      Event.extend(event, element);\n      var parent = event.relatedTarget;\n\n      while (parent && parent !== element) {\n        try { parent = parent.parentNode; }\n        catch(e) { parent = element; }\n      }\n\n      if (parent === element) return;\n      handler.call(element, event);\n    }\n  }\n\n  GLOBAL.Event._createResponder = createResponder;\n  docEl = null;\n})(this);\n\n(function(GLOBAL) {\n  /* Support for the DOMContentLoaded event is based on work by Dan Webb,\n     Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */\n\n  var TIMER;\n\n  function fireContentLoadedEvent() {\n    if (document.loaded) return;\n    if (TIMER) window.clearTimeout(TIMER);\n    document.loaded = true;\n    document.fire('dom:loaded');\n  }\n\n  function checkReadyState() {\n    if (document.readyState === 'complete') {\n      document.detachEvent('onreadystatechange', checkReadyState);\n      fireContentLoadedEvent();\n    }\n  }\n\n  function pollDoScroll() {\n    try {\n      document.documentElement.doScroll('left');\n    } catch (e) {\n      TIMER = pollDoScroll.defer();\n      return;\n    }\n\n    fireContentLoadedEvent();\n  }\n\n  if (document.addEventListener) {\n    document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);\n  } else {\n    document.attachEvent('onreadystatechange', checkReadyState);\n    if (window == top) TIMER = pollDoScroll.defer();\n  }\n\n  Event.observe(window, 'load', fireContentLoadedEvent);\n})(this);\n\n\nElement.addMethods();\n/*------------------------------- DEPRECATED -------------------------------*/\n\nHash.toQueryString = Object.toQueryString;\n\nvar Toggle = { display: Element.toggle };\n\nElement.Methods.childOf = Element.Methods.descendantOf;\n\nvar Insertion = {\n  Before: function(element, content) {\n    return Element.insert(element, {before:content});\n  },\n\n  Top: function(element, content) {\n    return Element.insert(element, {top:content});\n  },\n\n  Bottom: function(element, content) {\n    return Element.insert(element, {bottom:content});\n  },\n\n  After: function(element, content) {\n    return Element.insert(element, {after:content});\n  }\n};\n\nvar $continue = new Error('\"throw $continue\" is deprecated, use \"return\" instead');\n\nvar Position = {\n  includeScrollOffsets: false,\n\n  prepare: function() {\n    this.deltaX =  window.pageXOffset\n                || document.documentElement.scrollLeft\n                || document.body.scrollLeft\n                || 0;\n    this.deltaY =  window.pageYOffset\n                || document.documentElement.scrollTop\n                || document.body.scrollTop\n                || 0;\n  },\n\n  within: function(element, x, y) {\n    if (this.includeScrollOffsets)\n      return this.withinIncludingScrolloffsets(element, x, y);\n    this.xcomp = x;\n    this.ycomp = y;\n    this.offset = Element.cumulativeOffset(element);\n\n    return (y >= this.offset[1] &&\n            y <  this.offset[1] + element.offsetHeight &&\n            x >= this.offset[0] &&\n            x <  this.offset[0] + element.offsetWidth);\n  },\n\n  withinIncludingScrolloffsets: function(element, x, y) {\n    var offsetcache = Element.cumulativeScrollOffset(element);\n\n    this.xcomp = x + offsetcache[0] - this.deltaX;\n    this.ycomp = y + offsetcache[1] - this.deltaY;\n    this.offset = Element.cumulativeOffset(element);\n\n    return (this.ycomp >= this.offset[1] &&\n            this.ycomp <  this.offset[1] + element.offsetHeight &&\n            this.xcomp >= this.offset[0] &&\n            this.xcomp <  this.offset[0] + element.offsetWidth);\n  },\n\n  overlap: function(mode, element) {\n    if (!mode) return 0;\n    if (mode == 'vertical')\n      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /\n        element.offsetHeight;\n    if (mode == 'horizontal')\n      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /\n        element.offsetWidth;\n  },\n\n\n  cumulativeOffset: Element.Methods.cumulativeOffset,\n\n  positionedOffset: Element.Methods.positionedOffset,\n\n  absolutize: function(element) {\n    Position.prepare();\n    return Element.absolutize(element);\n  },\n\n  relativize: function(element) {\n    Position.prepare();\n    return Element.relativize(element);\n  },\n\n  realOffset: Element.Methods.cumulativeScrollOffset,\n\n  offsetParent: Element.Methods.getOffsetParent,\n\n  page: Element.Methods.viewportOffset,\n\n  clone: function(source, target, options) {\n    options = options || { };\n    return Element.clonePosition(target, source, options);\n  }\n};\n\n/*--------------------------------------------------------------------------*/\n\nif (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){\n  function iter(name) {\n    return name.blank() ? null : \"[contains(concat(' ', @class, ' '), ' \" + name + \" ')]\";\n  }\n\n  instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?\n  function(element, className) {\n    className = className.toString().strip();\n    var cond = /\\s/.test(className) ? $w(className).map(iter).join('') : iter(className);\n    return cond ? document._getElementsByXPath('.//*' + cond, element) : [];\n  } : function(element, className) {\n    className = className.toString().strip();\n    var elements = [], classNames = (/\\s/.test(className) ? $w(className) : null);\n    if (!classNames && !className) return elements;\n\n    var nodes = $(element).getElementsByTagName('*');\n    className = ' ' + className + ' ';\n\n    for (var i = 0, child, cn; child = nodes[i]; i++) {\n      if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||\n          (classNames && classNames.all(function(name) {\n            return !name.toString().blank() && cn.include(' ' + name + ' ');\n          }))))\n        elements.push(Element.extend(child));\n    }\n    return elements;\n  };\n\n  return function(className, parentElement) {\n    return $(parentElement || document.body).getElementsByClassName(className);\n  };\n}(Element.Methods);\n\n/*--------------------------------------------------------------------------*/\n\nElement.ClassNames = Class.create();\nElement.ClassNames.prototype = {\n  initialize: function(element) {\n    this.element = $(element);\n  },\n\n  _each: function(iterator, context) {\n    this.element.className.split(/\\s+/).select(function(name) {\n      return name.length > 0;\n    })._each(iterator, context);\n  },\n\n  set: function(className) {\n    this.element.className = className;\n  },\n\n  add: function(classNameToAdd) {\n    if (this.include(classNameToAdd)) return;\n    this.set($A(this).concat(classNameToAdd).join(' '));\n  },\n\n  remove: function(classNameToRemove) {\n    if (!this.include(classNameToRemove)) return;\n    this.set($A(this).without(classNameToRemove).join(' '));\n  },\n\n  toString: function() {\n    return $A(this).join(' ');\n  }\n};\n\nObject.extend(Element.ClassNames.prototype, Enumerable);\n\n/*--------------------------------------------------------------------------*/\n\n(function() {\n  window.Selector = Class.create({\n    initialize: function(expression) {\n      this.expression = expression.strip();\n    },\n\n    findElements: function(rootElement) {\n      return Prototype.Selector.select(this.expression, rootElement);\n    },\n\n    match: function(element) {\n      return Prototype.Selector.match(element, this.expression);\n    },\n\n    toString: function() {\n      return this.expression;\n    },\n\n    inspect: function() {\n      return \"#<Selector: \" + this.expression + \">\";\n    }\n  });\n\n  Object.extend(Selector, {\n    matchElements: function(elements, expression) {\n      var match = Prototype.Selector.match,\n          results = [];\n\n      for (var i = 0, length = elements.length; i < length; i++) {\n        var element = elements[i];\n        if (match(element, expression)) {\n          results.push(Element.extend(element));\n        }\n      }\n      return results;\n    },\n\n    findElement: function(elements, expression, index) {\n      index = index || 0;\n      var matchIndex = 0, element;\n      for (var i = 0, length = elements.length; i < length; i++) {\n        element = elements[i];\n        if (Prototype.Selector.match(element, expression) && index === matchIndex++) {\n          return Element.extend(element);\n        }\n      }\n    },\n\n    findChildElements: function(element, expressions) {\n      var selector = expressions.toArray().join(', ');\n      return Prototype.Selector.select(selector, element || document);\n    }\n  });\n})();"
  },
  {
    "path": "_archive/apps/samples/clock/tests/lib/right.js",
    "content": "/**\n * RightJS v2.3.1 - http://rightjs.org\n * Released under the terms of MIT license\n *\n * Copyright (C) 2008-2012 Nikolay Nemshilov\n */\nvar RightJS=function(a,b,c,d,e,f,g,h,i){function cL(a,b,c,d){var e={},f=a.marginLeft.toFloat()||0,g=a.marginTop.toFloat()||0,h=c===\"right\",i=c===\"bottom\",j=c===\"top\"||i;d===\"out\"?(e[j?\"height\":\"width\"]=\"0px\",h?e.marginLeft=f+b.x+\"px\":i&&(e.marginTop=g+b.y+\"px\")):(j?(e.height=b.y+\"px\",a.height=\"0px\"):(e.width=b.x+\"px\",a.width=\"0px\"),h?(e.marginLeft=f+\"px\",a.marginLeft=f+b.x+\"px\"):i&&(e.marginTop=g+\"px\",a.marginTop=g+b.y+\"px\"));return e}function cK(a,b,c){var d=a.clone().setStyle(\"position:absolute;z-index:-1;visibility:hidden\").setWidth(a.size().x).setStyle(b),e;a.parent()&&a.insert(d,\"before\"),e=cJ(d,c),d.remove();return e}function cJ(a,b){var c=0,d=b.length,e=a.computedStyles(),f={},g;for(;c<d;c++)g=b[c],g in e&&(f[g]=\"\"+e[g],g===\"opacity\"&&(f[g]=f[g].replace(\",\",\".\")));return f}function cI(a,b,c){var d;for(d in c)(d==\"width\"||d==\"height\")&&b[d]==\"auto\"&&(b[d]=a._[\"offset\"+d.capitalize()]+\"px\");bu&&c.filter&&!b.filter&&(b.filter=\"alpha(opacity=100)\"),cG(a,b,c);for(d in c){if(c[d]!==b[d]&&/color/i.test(d)){bq&&(c[d]=c[d].replace(/\"/g,\"\"),b[d]=b[d].replace(/\"/g,\"\")),cF(c[d])||(c[d]=c[d].toRgb()),cF(b[d])||(b[d]=b[d].toRgb());if(!c[d]||!b[d])c[d]=b[d]=\"\"}/\\d/.test(c[d])&&!/\\d/.test(b[d])&&(b[d]=c[d].replace(/[\\d\\.\\-]+/g,\"0\"));if(c[d]===b[d]||!/\\d/.test(b[d])||!/\\d/.test(c[d]))delete c[d],delete b[d]}}function cH(a){var b={},c=/[\\d\\.\\-]+/g,d,e,f,g;for(e in a){d=a[e].match(c),f=d.map(\"toFloat\"),f.t=a[e].split(c),f.r=f.t[0]===\"rgb(\",f.t.length==1&&f.t.unshift(\"\");for(g=0;g<f.length;g++)f.t.splice(g*2+1,0,f[g]);b[e]=f}return b}function cG(a,b,c){for(var d=0;d<4;d++){var e=\"border\"+cC[d]+\"Style\",f=\"border\"+cC[d]+\"Width\",g=\"border\"+cC[d]+\"Color\";if(e in b&&b[e]!=c[e]){var h=a._.style;b[e]==\"none\"&&(h[f]=\"0px\"),h[e]=c[e],cF(b[g])&&(h[g]=a.getStyle(\"Color\"))}}}function cF(a){return a===\"transparent\"||a===\"rgba(0, 0, 0, 0)\"}function cE(a){var b=[],c=[\"Style\",\"Color\",\"Width\"],d,e,f;for(d in a)if(d.startsWith(\"border\"))for(e=0;e<3;e++)for(f=0;f<4;f++)b.push(\"border\"+cC[f]+c[e]);else d===\"margin\"||d===\"padding\"?cD(b,d,cC):d.startsWith(\"background\")?cD(b,\"background\",[\"Color\",\"Position\",\"PositionX\",\"PositionY\"]):d===\"opacity\"&&bu?b.push(\"filter\"):b.push(d);return b}function cD(a,b,c){for(var d=0;d<c.length;d++)a.push(b+c[d])}function cB(a){function g(){for(var a in f)e[a]=f[a]}var b=this.options,d=this.element,e=d._.style,f=c.only(d.computedStyles(),cx,cy,cz);this.onFinish(g).onCancel(function(){e[cx]=\"none\",setTimeout(g,1)}),e[cx]=\"all\",e[cy]=(cg.Durations[b.duration]||b.duration)+\"ms\",e[cz]=cA[b.transition]||b.transition,setTimeout(function(){d.setStyle(a)},0)}function cu(a,b,c){var d=J(c).compact(),e=A(d.last())?d.pop():{},f=new(cg[b.capitalize()])(a,e);f.start.apply(f,d);return a}function ct(a,b){function q(a){var b=a,c=0,d;while(c<5){d=n(b)-a;if(h.abs(d)<.001)break;b=b-d/p(b),c++}return b}function p(a){return d+a*(2*e+a*3*f)+.001}function o(a){return a*(g+a*(i+a*j))}function n(a){return a*(d+a*(e+a*f))}a=cr[a]||cA[a]||a,a=a.match(/([\\d\\.]+)[\\s,]+([\\d\\.]+)[\\s,]+([\\d\\.]+)[\\s,]+([\\d\\.]+)/),a=[0,a[1]-0,a[2]-0,a[3]-0,a[4]-0];var c=a.join(\",\")+\",\"+b,d,e,f,g,i,j,k,l,m;if(!(c in cs)){d=3*a[1],e=3*(a[3]-a[1])-d,f=1-d-e,g=3*a[2],i=3*(a[4]-a[2])-g,j=1-g-i,cs[c]=k=[],m=0,l=1/b;while(m<1.0001)k.push(o(q(m))),m+=l}return cs[c]}function cq(a){a._timer&&clearInterval(a._timer)}function cp(a){var b=a.options,c=cg.Durations[b.duration]||b.duration,d=h.ceil(c/1e3*b.fps),e=ct(b.transition,d),f=h.round(1e3/b.fps),g=0;a._timer=setInterval(function(){g===d?a.finish():(a.render(e[g]),g++)},f)}function co(a){var b=I(a._);(ci[b]||[]).each(\"cancel\"),(ch[b]||[]).splice(0)}function cn(a){var b=a.ch,c=b.shift();if(c=b[0])c[1].$ch=!0,c[1].start.apply(c[1],c[0])}function cm(a){var b=a.cr;b&&b.splice(b.indexOf(a),1)}function cl(a){a.cr&&a.cr.push(a)}function ck(a,b){var c=a.ch,d=a.options.queue;if(!c||a.$ch)return a.$ch=!1;d&&c.push([b,a]);return d&&c[0][1]!==a}function cj(a){var b=I((a.element||{})._||{});a.ch=ch[b]=ch[b]||[],a.cr=ci[b]=ci[b]||[]}function cf(a,b){a.stop(),this.send(b)}function cc(a,b){var d=a[0],e,f,g=cb(a),h=!c.keys(g).length;return(b.$listeners||[]).filter(function(a){return a.dr&&a.n===d&&(h||function(){for(var b in g)if(a.dr===b)for(e=0,f=g[b];e<f.length;e++)if(!f[e].length||f[e][0]===a.dc)return!0;return!1}())})}function cb(a){var b=J(a),c=b[1]||{},d={},e;y(c)?(d[c]=b.slice(2),B(d[c][0])&&(d[c]=d[c][0].map(N))):d=c;for(e in d)d[e]=N(d[e]),d[e]=B(d[e][0])?d[e]:[d[e]];return d}function ca(a,b,c){var d=J(b),e=d.shift();return function(b){var c=b.find(a);return c===i?c:typeof e===\"string\"?c[e].apply(c,d):e.apply(c,[b].concat(d))}}function b_(){bX&&(bX=!1,br?(b.attachEvent(\"onmouseover\",bZ),a.attachEvent(\"blur\",b$)):(b.addEventListener(\"mouseover\",bZ,!1),a.addEventListener(\"blur\",b$,!1)))}function b$(a){bW.each(function(b,c){b&&q[c]&&bY(a,q[c]._,c,!1)})}function bZ(a){var b=a.target||a.srcElement,c=a.relatedTarget||a.fromElement,d=b,e=!1,f=[],g,h;while(d.nodeType===1)g=I(d),bW[g]===i&&bY(a,d,g,bW[g]=!0),d===c&&(e=!0),f.push(d),d=d.parentNode;if(c&&!e)while(c!==null&&c.nodeType===1&&f.indexOf(c)===-1)g=I(c),bW[g]!==i&&bY(a,c,g,bW[g]=i),c=c.parentNode}function bY(a,b,c,d){var e=new bE(a);e.type=d===!0?\"mouseenter\":\"mouseleave\",e.bubbles=!1,e.stopped=!0,e.target=bA(b),e.find=function(a){return F(a,!0).indexOf(this.target._)===-1?i:this.target},e.target.fire(e),bC.fire(e)}function bV(a){var b=new bE(a),c=b.target,d=c.parent&&c.parent();b.type=a.type===\"focusin\"||a.type===\"focus\"?\"focus\":\"blur\",d&&d.fire(b)}function bS(a){a=H(a),bF=bF.concat(a),bm(bG.prototype,a),bm(bB.prototype,a)}function bR(a,b){b=b.camelize();if(b===\"opacity\")return bu?(/opacity=(\\d+)/i.exec(a.filter||\"\")||[\"\",\"100\"])[1].toInt()/100+\"\":a[b].replace(\",\",\".\");b===\"float\"&&(b=br?\"styleFloat\":\"cssFloat\");var c=a[b];bq&&/color/i.test(b)&&c&&(c=c.replace(/\"/g,\"\"));return c}function bQ(a,b){if(typeof b===\"string\"){var c=a.tagName,d=bP,e=c in bN?bN[c]:[\"\",\"\",1],f=e[2];d.innerHTML=e[0]+\"<\"+c+\">\"+b+\"</\"+c+\">\"+e[1];while(f--!==0)d=d.firstChild;b=d.childNodes;while(b.length!==0)bO.appendChild(b[0])}else for(var g=0,h=b.length,i;g<h;g++)i=b[b.length===h?g:0],bO.appendChild(i instanceof bG?i._:i);return bO}function bL(a,b,c){var d=a._,e=[],f=0,g=!c;while(d=d[b])d.nodeType===1&&(g||bA(d).match(c))&&(e[f++]=bA(d));return e}function bK(a,b,c){if(typeof b===\"string\"){a._=bJ(b,c);if(c!==i)for(var d in c)switch(d){case\"id\":a._.id=c[d];break;case\"html\":a._.innerHTML=c[d];break;case\"class\":a._.className=c[d];break;case\"on\":a.on(c[d]);break;default:a.set(d,c[d])}}else a._=b}function bA(a){if(a!=null){var b=r in a?q[a[r]]:i;if(b!==i)return b;if(a.nodeType===1)return new bG(a);if(a.nodeType===9)return new bB(a);if(a.window==a)return new bD(a);if(C(a.target)||C(a.srcElement))return new bE(a)}return a}function bz(a,b){typeof a===\"string\"&&(a=s({type:a},b),this.stopped=a.bubbles===!1,A(b)&&s(this,b)),this._=a,this.type=a.type,this.which=a.which,this.keyCode=a.keyCode,this.target=bA(a.target!=null&&\"nodeType\"in a.target&&a.target.nodeType===3?a.target.parentNode:a.target),this.currentTarget=bA(a.currentTarget),this.relatedTarget=bA(a.relatedTarget),this.pageX=a.pageX,this.pageY=a.pageY;if(bt&&\"srcElement\"in a){this.which=a.button===2?3:a.button===4?2:1,this.target=bA(a.srcElement)||b,this.relatedTarget=this.target._===a.fromElement?bA(a.toElement):this.target,this.currentTarget=b;var c=this.target.win().scrolls();this.pageX=a.clientX+c.x,this.pageY=a.clientY+c.y}}function by(a,b){bK(this,a,b);var c=this,d=c._,e=bw.Cast(d),f=r in d?d[r]:d[r]=p++;e!==i&&(c=new e(d,b),\"$listeners\"in this&&(c.$listeners=this.$listeners)),q[f]=c;return c}function bx(){return function(a,b){bi(this),this.initialize.apply(this,arguments);var c=this._,d=r in c?c[r]:c[r]=(c.nodeType===1?1:-1)*p++;q[d]=this}}function bo(a,b,c,d){if(A(b))for(var e in b)a.stopObserving(e,b[e]);else y(b)||(c=b,b=null),y(c)&&(c=a[c]),a.$listeners=(a.$listeners||[]).filter(function(a){var e=b&&c?a.e!==b||a.f!==c:b?a.e!==b:a.f!==c;e||d(a);return e})}function bn(a,b,c){var d=n.call(b,2),e=b[0],f=b[1],g=!1;if(y(e))switch(typeof f){case\"string\":g=f,f=f in a?a[f]:function(){};case\"function\":(\"$listeners\"in a?a.$listeners:a.$listeners=[]).push(c({e:e,f:f,a:d,r:g||!1,t:a}));break;default:if(B(f))for(var h=0;h<f.length;h++)a.on.apply(a,[e].concat(N(f[h])).concat(d))}else{d=n.call(b,1);for(g in e)a.on.apply(a,[g].concat(N(e[g])).concat(d))}}function bi(a){\"prebind\"in a&&B(a.prebind)&&a.prebind.each(function(b){a[b]=a[b].bind(a)})}function bh(a,b){var c=b.toUpperCase(),d=a.constructor,e=[a,d].concat(d.ancestors||[]),f=0;for(l=e.length;f<l;f++){if(c in e[f])return e[f][c];if(b in e[f])return e[f][b]}return null}function bg(a,b,c){(b[be[c?0:2]]||b[be[c?1:3]]||function(){}).call(b,a)}function bf(a,b){return c.without.apply(c,[a].concat(be.concat(b?H(\"prototype parent ancestors\"):[\"constructor\"])))}function bb(a,b){return a>b?1:a<b?-1:0}function ba(a){return!!a}function _(a,b,c){try{return a.apply(b,Z(c,b))}catch(d){if(!(d instanceof $))throw d}return i}function $(){}function Z(a,b){var c=a[0],d=n.call(a,1),e=b,f;typeof c===\"string\"?(f=c,b.length!==0&&typeof b[0][f]===\"function\"?c=function(a){return a[f].apply(a,d)}:c=function(a){return a[f]}):e=d[0];return[c,e]}function O(a,b){var c=[],d,e,f;for(d in a){e=a[d],b&&(d=b+\"[\"+d+\"]\");if(typeof e===\"object\"){if(B(e)){d.endsWith(\"[]\")||(d+=\"[]\");for(f=0;f<e.length;f++)c.push([d,e[f]])}else if(e){e=O(e,d);for(f=0;f<e.length;f++)c.push(e[f])}}else c.push([d,e])}return c}function N(a){return B(a)?a:[a]}function K(a){return s(a,{Methods:{},include:function(){for(var b=0,c=arguments.length;b<c;b++)A(arguments[b])&&(s(a.prototype,arguments[b]),s(a.Methods,arguments[b]))}})}var j=function(a){return a};j.version=\"2.3.1\",j.modules=[\"core\",\"dom\",\"form\",\"events\",\"xhr\",\"fx\",\"cookie\"];var k=d.prototype,m=c.prototype.toString,n=k.slice,o=b.documentElement,p=1,q=[],r=\"uniqueNumber\",s=j.$ext=function(a,b,c){var d=b||{},e;for(e in d)if(!c||!(e in a))a[e]=d[e];return a},t=j.$eval=function(b){b&&(\"execScript\"in a?bC.win()._.execScript(b):G(\"script\",{text:b}).insertTo(o))},u=j.$break=function(){throw new $},v=j.$alias=function(a,b){for(var c in b)a[c]=a[b[c]];return a},w=j.defined=function(a){return typeof a!==\"undefined\"},x=j.isFunction=function(a){return typeof a===\"function\"},y=j.isString=function(a){return typeof a===\"string\"},z=j.isNumber=function(a){return typeof a===\"number\"&&!isNaN(a)},A=j.isHash=function(a){return m.call(a)===\"[object Object]\"},B=j.isArray=function(a){return m.call(a)===\"[object Array]\"},C=j.isElement=function(a){return a!=null&&a.nodeType===1},D=j.isNode=function(a){return a!=null&&a.nodeType!=null},E=j.$=function(a){if(a instanceof bw)return a;typeof a===\"string\"&&(a=b.getElementById(a));return bA(a)},F=j.$$=function(a,b){return bC.find(a,b)},G=j.$E=function(a,b){return new bG(a,b)},H=j.$w=function(a){return a.trim().split(/\\s+/)},I=j.$uid=function(a){return r in a?a[r]:a[r]=p++},J=j.$A=function(a){return n.call(a,0)};k.map||(J=j.$A=function(a){try{return n.call(a,0)}catch(b){for(var c=[],d=0,e=a.length;d<e;d++)c[d]=a[d];return c}}),A(o)&&(A=j.isHash=function(a){return m.call(a)===\"[object Object]\"&&a!=null&&a.hasOwnProperty!=null});for(var L=0,M=\"Array Function Number String Date RegExp\".split(\" \");L<M.length;L++)j[M[L]]=K((new f(\"return \"+M[L]))());j.Object=c,j.Math=h,s(c,{keys:function(a){var b=[],c;for(c in a)b.push(c);return b},values:function(a){var b=[],c;for(c in a)b.push(a[c]);return b},each:function(a,b,c){for(var d in a)b.call(c,d,a[d]);return a},empty:function(a){for(var b in a)return!1;return!0},clone:function(a){return c.merge(a)},without:function(){var a=J(arguments),b=a.shift(),c={},d;for(d in b)a.include(d)||(c[d]=b[d]);return c},only:function(){var a=J(arguments),b=a.shift(),c={},d=0,e=a.length;for(;d<e;d++)a[d]in b&&(c[a[d]]=b[a[d]]);return c},merge:function(){var a={},b=0,d=arguments,e=d.length,f;for(;b<e;b++)if(A(d[b]))for(f in d[b])a[f]=A(d[b][f])&&!(d[b][f]instanceof bc)?c.merge(f in a?a[f]:{},d[b][f]):d[b][f];return a},toQueryString:function(a){var b=O(a),c=0,d=[];for(;c<b.length;c++)d.push(encodeURIComponent(b[c][0])+\"=\"+encodeURIComponent(\"\"+b[c][1]));return d.join(\"&\")}},!0);var P=h.random;h.random=function(a,b){if(arguments.length===0)return P();arguments.length===1&&(b=a,a=0);return~~(P()*(b-a+1)+~~a)};var Q=k.sort,R=k.forEach||function(a,b){for(var c=0,d=this.length;c<d;c++)a.call(b,this[c],c,this)},S=k.filter||function(a,b){for(var c=[],d=0,e=0,f=this.length;e<f;e++)a.call(b,this[e],e,this)&&(c[d++]=this[e]);return c},T=function(a,b){for(var c=[],d=0,e=0,f=this.length;e<f;e++)a.call(b,this[e],e,this)||(c[d++]=this[e]);return c},U=k.map||function(a,b){for(var c=[],d=0,e=this.length;d<e;d++)c[d]=a.call(b,this[d],d,this);return c},V=k.some||function(a,b){for(var c=0,d=this.length;c<d;c++)if(a.call(b,this[c],c,this))return!0;return!1},W=k.every||function(a,b){for(var c=0,d=this.length;c<d;c++)if(!a.call(b,this[c],c,this))return!1;return!0},X=function(a,b){for(var c=0,d=this.length;c<d;c++)if(a.call(b,this[c],c,this))return this[c];return i},Y=function(a,b){for(var c=this.length-1;c>-1;c--)if(a.call(b,this[c],c,this))return this[c];return i};d.include({indexOf:k.indexOf||function(a,b){for(var c=b<0?h.max(0,this.length+b):b||0,d=this.length;c<d;c++)if(this[c]===a)return c;return-1},lastIndexOf:k.lastIndexOf||function(a){for(var b=this.length-1;b>-1;b--)if(this[b]===a)return b;return-1},first:function(){return arguments.length?_(X,this,arguments):this[0]},last:function(){return arguments.length?_(Y,this,arguments):this[this.length-1]},random:function(){return this.length===0?i:this[h.random(this.length-1)]},size:function(){return this.length},clean:function(){this.length=0;return this},empty:function(){return this.length===0},clone:function(){return this.slice(0)},each:function(){_(R,this,arguments);return this},forEach:R,map:function(){return _(U,this,arguments)},filter:function(){return _(S,this,arguments)},reject:function(){return _(T,this,arguments)},some:function(a){return _(V,this,a?arguments:[ba])},every:function(a){return _(W,this,a?arguments:[ba])},walk:function(){this.map.apply(this,arguments).forEach(function(a,b){this[b]=a},this);return this},merge:function(){for(var a=this.clone(),b,c=0;c<arguments.length;c++){b=N(arguments[c]);for(var d=0;d<b.length;d++)a.indexOf(b[d])==-1&&a.push(b[d])}return a},flatten:function(){var a=[];this.forEach(function(b){B(b)?a=a.concat(b.flatten()):a.push(b)});return a},compact:function(){return this.without(null,i)},uniq:function(){return[].merge(this)},includes:function(){for(var a=0;a<arguments.length;a++)if(this.indexOf(arguments[a])===-1)return!1;return!0},without:function(){var a=n.call(arguments);return this.filter(function(b){return a.indexOf(b)===-1})},shuffle:function(){var a=this.clone(),b,c,d=a.length;for(;d>0;b=h.random(d-1),c=a[--d],a[d]=a[b],a[b]=c){}return a},sort:function(a){return Q.apply(this,a||!z(this[0])?arguments:[bb])},sortBy:function(){var a=Z(arguments,this);return this.sort(function(b,c){return bb(a[0].call(a[1],b),a[0].call(a[1],c))})},min:function(){return h.min.apply(h,this)},max:function(){return h.max.apply(h,this)},sum:function(){for(var a=0,b=0,c=this.length;b<c;a+=this[b++]){}return a}}),k.include=k.includes,e.include({empty:function(){return this==\"\"},blank:function(){return this==!1},trim:e.prototype.trim||function(){var a=this.replace(/^\\s\\s*/,\"\"),b=a.length;while(/\\s/.test(a.charAt(--b))){}return a.slice(0,b+1)},stripTags:function(){return this.replace(/<\\/?[^>]+>/ig,\"\")},stripScripts:function(a){var b=\"\",c=this.replace(/<script[^>]*>([\\s\\S]*?)<\\/script>/img,function(a,c){b+=c+\"\\n\";return\"\"});a===!0?t(b):x(a)&&a(b,c);return c},extractScripts:function(){var a=\"\";this.stripScripts(function(b){a=b});return a},evalScripts:function(){this.stripScripts(!0);return this},camelize:function(){return this.replace(/(\\-|_)+(.)?/g,function(a,b,c){return c?c.toUpperCase():\"\"})},underscored:function(){return this.replace(/([a-z\\d])([A-Z]+)/g,\"$1_$2\").replace(/\\-/g,\"_\").toLowerCase()},capitalize:function(){return this.charAt(0).toUpperCase()+this.substring(1).toLowerCase()},dasherize:function(){return this.underscored().replace(/_/g,\"-\")},includes:function(a){return this.indexOf(a)!=-1},startsWith:function(a,b){return(b!==!0?this.indexOf(a):this.toLowerCase().indexOf(a.toLowerCase()))===0},endsWith:function(a,b){return this.length-(b!==!0?this.lastIndexOf(a):this.toLowerCase().lastIndexOf(a.toLowerCase()))===a.length},toInt:function(a){return parseInt(this,a===i?10:a)},toFloat:function(a){return parseFloat(a===!0?this:this.replace(\",\",\".\").replace(/(\\d)-(\\d)/,\"$1.$2\"))}}),e.prototype.include=e.prototype.includes,f.include({bind:function(){var a=J(arguments),b=a.shift(),c=this;return function(){return c.apply(b,a.length!==0||arguments.length!==0?a.concat(J(arguments)):a)}},bindAsEventListener:function(){var a=J(arguments),b=a.shift(),c=this;return function(d){return c.apply(b,[d].concat(a).concat(J(arguments)))}},curry:function(){return this.bind.apply(this,[this].concat(J(arguments)))},rcurry:function(){var a=J(arguments),b=this;return function(){return b.apply(b,J(arguments).concat(a))}},delay:function(){var a=J(arguments),b=a.shift(),c=new g(setTimeout(this.bind.apply(this,[this].concat(a)),b));c.cancel=function(){clearTimeout(this)};return c},periodical:function(){var a=J(arguments),b=a.shift(),c=new g(setInterval(this.bind.apply(this,[this].concat(a)),b));c.stop=function(){clearInterval(this)};return c},chain:function(){var a=J(arguments),b=a.shift(),c=this;return function(){var d=c.apply(c,arguments);b.apply(b,a);return d}}}),g.include({times:function(a,b){for(var c=0;c<this;c++)a.call(b,c);return this},upto:function(a,b,c){for(var d=this+0;d<=a;d++)b.call(c,d);return this},downto:function(a,b,c){for(var d=this+0;d>=a;d--)b.call(c,d);return this},to:function(a,b,c){var d=this+0,e=a,f=[],g=d;b=b||function(a){return a};if(e>d)for(;g<=e;g++)f.push(b.call(c,g));else for(;g>=e;g--)f.push(b.call(c,g));return f},abs:function(){return h.abs(this)},round:function(a){return a?parseFloat(this.toFixed(a)):h.round(this)},ceil:function(){return h.ceil(this)},floor:function(){return h.floor(this)},min:function(a){return this<a?a:this+0},max:function(a){return this>a?a:this+0}}),RegExp.escape=function(a){return(\"\"+a).replace(/([.*+?\\^=!:${}()|\\[\\]\\/\\\\])/g,\"\\\\$1\")},a.JSON||(a.JSON=function(){function g(a){return(a<10?\"0\":\"\")+a}function d(a){return a.replace(c,function(a){return b[a]||\"\\\\u\"+(\"0000\"+a.charCodeAt(0).toString(16)).slice(-4)})}var a=/[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,b={\"\\b\":\"\\\\b\",\"\\t\":\"\\\\t\",\"\\n\":\"\\\\n\",\"\\f\":\"\\\\f\",\"\\r\":\"\\\\r\",'\"':'\\\\\"',\"\\\\\":\"\\\\\\\\\"},c=/[\\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g;return{stringify:function(a){switch(typeof a){case\"boolean\":return e(a);case\"number\":return e(a+0);case\"string\":return'\"'+d(a)+'\"';case\"object\":if(a===null)return\"null\";if(B(a))return\"[\"+J(a).map(JSON.stringify).join(\",\")+\"]\";if(m.call(a)===\"[object Date]\")return'\"'+a.getUTCFullYear()+\"-\"+g(a.getUTCMonth()+1)+\"-\"+g(a.getUTCDate())+\"T\"+g(a.getUTCHours())+\":\"+g(a.getUTCMinutes())+\":\"+g(a.getUTCSeconds())+\".\"+g(a.getMilliseconds())+'Z\"';var b=[],c;for(c in a)b.push('\"'+c+'\":'+JSON.stringify(a[c]));return\"{\"+b.join(\",\")+\"}\"}},parse:function(b){if(y(b)&&b){b=b.replace(a,function(a){return\"\\\\u\"+(\"0000\"+a.charCodeAt(0).toString(16)).slice(-4)});if(/^[\\],:{}\\s]*$/.test(b.replace(/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,\"@\").replace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,\"]\").replace(/(?:^|:|,)(?:\\s*\\[)+/g,\"\")))return(new f(\"return \"+b))()}throw\"JSON parse error: \"+b}}}());var bc=j.Class=function(){var a=J(arguments).slice(0,2),b=a.pop()||{},c=a.pop(),d=arguments[2],e=function(){};!a.length&&!A(b)&&(c=b,b={}),!d&&c&&(c===bw||c.ancestors.include(bw))&&(d=bx()),d=s(d||function(){bi(this);return\"initialize\"in this?this.initialize.apply(this,arguments):this},bd),c=c||bc,e.prototype=c.prototype,d.prototype=new e,d.parent=c,d.prototype.constructor=d,d.ancestors=[];while(c)d.ancestors.push(c),c=c.parent;[\"extend\",\"include\"].each(function(a){a in b&&d[a].apply(d,N(b[a]))});return d.include(b)},bd={extend:function(){J(arguments).filter(A).each(function(a){s(this,bf(a,!0)),bg(this,a,!0)},this);return this},include:function(){var a=[this].concat(this.ancestors);J(arguments).filter(A).each(function(b){c.each(bf(b,!1),function(b,c){for(var d,e=0,f=a.length;e<f;e++)if(b in a[e].prototype){d=a[e].prototype[b];break}this.prototype[b]=x(c)&&x(d)?function(){this.$super=d;return c.apply(this,arguments)}:c},this),bg(this,b,!1)},this);return this}},be=H(\"selfExtended self_extended selfIncluded self_included extend include\");s(bc,bd),bc.prototype.$super=i;var bj=j.Options={setOptions:function(a){var b=this.options=s(s({},c.clone(bh(this,\"Options\"))),a),d,e;if(x(this.on))for(e in b)if(d=e.match(/on([A-Z][A-Za-z]+)/))this.on(d[1].toLowerCase(),b[e]),delete b[e];return this},cutOptions:function(a){var b=J(a);this.setOptions(A(b.last())?b.pop():{});return b}},bk=j.Observer=new bc({include:bj,initialize:function(a){this.setOptions(a),bm(this,bh(this,\"Events\"));return this},on:function(){bn(this,arguments,function(a){return a});return this},observes:function(a,b){y(a)||(b=a,a=null),y(b)&&(b=b in this?this[b]:null);return(this.$listeners||[]).some(function(c){return a&&b?c.e===a&&c.f===b:a?c.e===a:c.f===b})},stopObserving:function(a,b){bo(this,a,b,function(){});return this},listeners:function(a){return(this.$listeners||[]).filter(function(b){return!a||b.e===a}).map(function(a){return a.f}).uniq()},fire:function(){var a=J(arguments),b=a.shift();(this.$listeners||[]).each(function(c){c.e===b&&c.f.apply(this,c.a.concat(a))},this);return this}}),bl=bk.create=function(a,b){s(a,c.without(bk.prototype,\"initialize\",\"setOptions\"),!0);return bm(a,b||bh(a,\"Events\"))},bm=bk.createShortcuts=function(a,b){(b||[]).each(function(b){var c=\"on\"+b.replace(/(^|_|:)([a-z])/g,function(a,b,c){return c.toUpperCase()});c in a||(a[c]=function(){return this.on.apply(this,[b].concat(J(arguments)))})});return a},bp=navigator.userAgent,bq=\"opera\"in a,br=\"attachEvent\"in a&&!bq,bs=j.Browser={IE:br,Opera:bq,WebKit:bp.include(\"AppleWebKit/\"),Gecko:bp.include(\"Gecko\")&&!bp.include(\"KHTML\"),MobileSafari:/Apple.*Mobile.*Safari/.test(bp),Konqueror:bp.include(\"Konqueror\"),OLD:!b.querySelector,IE8L:!1},bt=!1,bu=!(\"opacity\"in o.style)&&\"filter\"in o.style;try{b.createElement(\"<input/>\"),bs.OLD=bs.IE8L=bt=!0}catch(bv){}var bw=j.Wrapper=new bc({_:i,initialize:function(a){this._=a}});bw.Cache=q,bw.Cast=function(a){return a.tagName in bH?bH[a.tagName]:i};var bB=j.Document=new bc(bw,{win:function(){return bA(this._.defaultView||this._.parentWindow)}}),bC=bA(b),bD=j.Window=new bc(bw,{win:function(){return this},size:function(){var a=this._,b=a.document.documentElement;return a.innerWidth?{x:a.innerWidth,y:a.innerHeight}:{x:b.clientWidth,y:b.clientHeight}},scrolls:function(){var a=this._,b=a.document,c=b.body,d=b.documentElement;return a.pageXOffset||a.pageYOffset?{x:a.pageXOffset,y:a.pageYOffset}:c&&(c.scrollLeft||c.scrollTop)?{x:c.scrollLeft,y:c.scrollTop}:{x:d.scrollLeft,y:d.scrollTop}},scrollTo:function(a,b,c){var d=a,e=b,f=z(a)?null:E(a);f instanceof bG&&(a=f.position()),A(a)&&(e=a.y,d=a.x),A(c=c||b)&&j.Fx?(new cg.Scroll(this,c)).start({x:d,y:e}):this._.scrollTo(d,e);return this}}),bE=j.Event=new bc(bw,{type:null,which:null,keyCode:null,target:null,currentTarget:null,relatedTarget:null,pageX:null,pageY:null,initialize:bz,stopPropagation:function(){this._.stopPropagation?this._.stopPropagation():this._.cancelBubble=!0,this.stopped=!0;return this},preventDefault:function(){this._.preventDefault?this._.preventDefault():this._.returnValue=!1;return this},stop:function(){return this.stopPropagation().preventDefault()},position:function(){return{x:this.pageX,y:this.pageY}},offset:function(){if(this.target instanceof bG){var a=this.target.position();return{x:this.pageX-a.x,y:this.pageY-a.y}}return null},find:function(a){if(this.target instanceof bw&&this.currentTarget instanceof bw){var b=this.target._,c=this.currentTarget.find(a,!0);while(b){if(c.indexOf(b)!==-1)return bA(b);b=b.parentNode}}return i}},bz),bF=[],bG=j.Element=new bc(bw,{initialize:function(a,b){bK(this,a,b)}},by),bH=bG.Wrappers={},bI={},bJ=function(a,c){return(a in bI?bI[a]:bI[a]=b.createElement(a)).cloneNode(!1)};bt&&(bJ=function(a,c){c!==i&&(a===\"input\"||a===\"button\")&&(a=\"<\"+a+' name=\"'+c.name+'\" type=\"'+c.type+'\"'+(c.checked?\" checked\":\"\")+\" />\",delete c.name,delete c.type);return b.createElement(a)}),bG.include({parent:function(a){var b=this._.parentNode,c=b&&b.nodeType;return a?this.parents(a)[0]:c===1||c===9?bA(b):null},parents:function(a){return bL(this,\"parentNode\",a)},children:function(a){return this.find(a).filter(function(a){return a._.parentNode===this._},this)},siblings:function(a){return this.prevSiblings(a).reverse().concat(this.nextSiblings(a))},nextSiblings:function(a){return bL(this,\"nextSibling\",a)},prevSiblings:function(a){return bL(this,\"previousSibling\",a)},next:function(a){return!a&&this._.nextElementSibling!==i?bA(this._.nextElementSibling):this.nextSiblings(a)[0]},prev:function(a){return!a&&this._.previousElementSibling!==i?bA(this._.previousElementSibling):this.prevSiblings(a)[0]},remove:function(){var a=this._,b=a.parentNode;b&&b.removeChild(a);return this},insert:function(a,b){var c=null,d=this._;b=b===i?\"bottom\":b,typeof a!==\"object\"?c=a=\"\"+a:a instanceof bG&&(a=a._),bM[b](d,a.nodeType===i?bQ(b===\"bottom\"||b===\"top\"?d:d.parentNode,a):a),c!==null&&c.evalScripts();return this},insertTo:function(a,b){E(a).insert(this,b);return this},append:function(a){return this.insert(y(a)?J(arguments).join(\"\"):arguments)},update:function(a){if(typeof a!==\"object\"){a=\"\"+a;try{this._.innerHTML=a}catch(b){return this.clean().insert(a)}a.evalScripts();return this}return this.clean().insert(a)},html:function(a){return a===i?this._.innerHTML:this.update(a)},text:function(a){return a===i?this._.textContent===i?this._.innerText:this._.textContent:this.update(this.doc()._.createTextNode(a))},replace:function(a){return this.insert(a,\"instead\")},wrap:function(a){var b=this._,c=b.parentNode;c&&(a=E(a)._,c.replaceChild(a,b),a.appendChild(b));return this},clean:function(){while(this._.firstChild)this._.removeChild(this._.firstChild);return this},empty:function(){return this.html().blank()},clone:function(){return new bG(this._.cloneNode(!0))},index:function(){var a=this._,b=a.parentNode.firstChild,c=0;while(b!==a)b.nodeType===1&&c++,b=b.nextSibling;return c}});var bM={bottom:function(a,b){a.appendChild(b)},top:function(a,b){a.firstChild!==null?a.insertBefore(b,a.firstChild):a.appendChild(b)},after:function(a,b){var c=a.parentNode,d=a.nextSibling;d!==null?c.insertBefore(b,d):c.appendChild(b)},before:function(a,b){a.parentNode.insertBefore(b,a)},instead:function(a,b){a.parentNode.replaceChild(b,a)}},bN={TBODY:[\"<TABLE>\",\"</TABLE>\",2],TR:[\"<TABLE><TBODY>\",\"</TBODY></TABLE>\",3],TD:[\"<TABLE><TBODY><TR>\",\"</TR></TBODY></TABLE>\",4],COL:[\"<TABLE><COLGROUP>\",\"</COLGROUP><TBODY></TBODY></TABLE>\",2],LEGEND:[\"<FIELDSET>\",\"</FIELDSET>\",2],AREA:[\"<map>\",\"</map>\",2],OPTION:[\"<SELECT>\",\"</SELECT>\",2]};v(bN,{OPTGROUP:\"OPTION\",THEAD:\"TBODY\",TFOOT:\"TBODY\",TH:\"TD\"});var bO=b.createDocumentFragment(),bP=b.createElement(\"DIV\");bG.include({setStyle:function(a,b){var c,d,e={},f=this._.style;b!==i?(e[a]=b,a=e):y(a)&&(a.split(\";\").each(function(a){var b=a.split(\":\").map(\"trim\");b[0]&&b[1]&&(e[b[0]]=b[1])}),a=e);for(c in a)d=c.indexOf(\"-\")<0?c:c.camelize(),bu&&c===\"opacity\"?f.filter=\"alpha(opacity=\"+a[c]*100+\")\":c===\"float\"&&(d=br?\"styleFloat\":\"cssFloat\"),f[d]=a[c];return this},getStyle:function(a){return bR(this._.style,a)||bR(this.computedStyles(),a)},computedStyles:o.currentStyle?function(){return this._.currentStyle||{}}:o.runtimeStyle?function(){return this._.runtimeStyle||{}}:function(){return this._.ownerDocument.defaultView.getComputedStyle(this._,null)},hasClass:function(a){return(\" \"+this._.className+\" \").indexOf(\" \"+a+\" \")!=-1},setClass:function(a){this._.className=a;return this},getClass:function(){return this._.className},addClass:function(a){var b=\" \"+this._.className+\" \";b.indexOf(\" \"+a+\" \")==-1&&(this._.className+=(b===\"  \"?\"\":\" \")+a);return this},removeClass:function(a){this._.className=(\" \"+this._.className+\" \").replace(\" \"+a+\" \",\" \").trim();return this},toggleClass:function(a){return this[this.hasClass(a)?\"removeClass\":\"addClass\"](a)},radioClass:function(a){this.siblings().each(\"removeClass\",a);return this.addClass(a)}}),bG.include({set:function(a,b){if(typeof a===\"string\"){var c={};c[a]=b,a=c}var d,e=this._;for(d in a)d===\"style\"?this.setStyle(a[d]):(d in e||e.setAttribute(d,\"\"+a[d]),d.substr(0,5)!==\"data-\"&&(e[d]=a[d]));return this},get:function(a){var b=this._,c=b[a]||b.getAttribute(a);return c===\"\"?null:c},has:function(a){return this.get(a)!==null},erase:function(a){this._.removeAttribute(a);return this},hidden:function(){return this.getStyle(\"display\")===\"none\"},visible:function(){return!this.hidden()},hide:function(a,b){this.visible()&&(this._d=this.getStyle(\"display\"),this._.style.display=\"none\");return this},show:function(){if(this.hidden()){var a=this._,b=this._d,c;if(!b||b===\"none\")c=G(a.tagName).insertTo(o),b=c.getStyle(\"display\"),c.remove();b===\"none\"&&(b=\"block\"),a.style.display=b}return this},toggle:function(){return this[this.visible()?\"hide\":\"show\"]()},radio:function(a,b){this.siblings().each(\"hide\",a,b);return this.show()},data:function(a,b){var c,d,e,f,g,h;if(A(a))for(c in a)b=this.data(c,a[c]);else if(b===i){a=\"data-\"+(\"\"+a).dasherize();for(d={},e=!1,f=this._.attributes,h=0;h<f.length;h++){b=f[h].value;try{b=JSON.parse(b)}catch(j){}if(f[h].name===a){d=b,e=!0;break}f[h].name.indexOf(a)===0&&(d[f[h].name.substring(a.length+1).camelize()]=b,e=!0)}b=e?d:null}else{a=\"data-\"+(\"\"+a).dasherize(),A(b)||(b={\"\":b});for(c in b)g=c.blank()?a:a+\"-\"+c.dasherize(),b[c]===null?this._.removeAttribute(g):this._.setAttribute(g,y(b[c])?b[c]:JSON.stringify(b[c]));b=this}return b}}),bG.include({doc:function(){return bA(this._.ownerDocument)},win:function(){return this.doc().win()},size:function(){return{x:this._.offsetWidth,y:this._.offsetHeight}},position:function(){var a=this._.getBoundingClientRect(),b=this.doc()._.documentElement,c=this.win().scrolls();return{x:a.left+c.x-b.clientLeft,y:a.top+c.y-b.clientTop}},scrolls:function(){return{x:this._.scrollLeft,y:this._.scrollTop}},dimensions:function(){var a=this.size(),b=this.scrolls(),c=this.position();return{top:c.y,left:c.x,width:a.x,height:a.y,scrollLeft:b.x,scrollTop:b.y}},overlaps:function(a){var b=this.position(),c=this.size();return a.x>b.x&&a.x<b.x+c.x&&a.y>b.y&&a.y<b.y+c.y},setWidth:function(a){var b=this._.style;b.width=a+\"px\",b.width=2*a-this._.offsetWidth+\"px\";return this},setHeight:function(a){var b=this._.style;b.height=a+\"px\",b.height=2*a-this._.offsetHeight+\"px\";return this},resize:function(a,b){A(a)&&(b=a.y,a=a.x);return this.setWidth(a).setHeight(b)},moveTo:function(a,b){A(a)&&(b=a.y,a=a.x);return this.setStyle({left:a+\"px\",top:b+\"px\"})},scrollTo:function(a,b){A(a)&&(b=a.y,a=a.x),this._.scrollLeft=a,this._.scrollTop=b;return this},scrollThere:function(a){this.win().scrollTo(this,a);return this}}),[bG,bB,bD].each(\"include\",s(bl({}),{on:function(){bn(this,arguments,function(a){a.e===\"mouseenter\"||a.e===\"mouseleave\"?(b_(),a.n=a.e,a.w=function(){}):(a.e===\"contextmenu\"&&bs.Konqueror?a.n=\"rightclick\":a.e===\"mousewheel\"&&bs.Gecko?a.n=\"DOMMouseScroll\":a.n=a.e,a.w=function(b){b=new bE(b,a.t),a.f.apply(a.t,(a.r?[]:[b]).concat(a.a))===!1&&b.stop()},bt?a.t._.attachEvent(\"on\"+a.n,a.w):a.t._.addEventListener(a.n,a.w,!1));return a});return this},stopObserving:function(a,b){bo(this,a,b,function(a){bt?a.t._.detachEvent(\"on\"+a.n,a.w):a.t._.removeEventListener(a.n,a.w,!1)});return this},fire:function(a,b){var c=this.parent&&this.parent();a instanceof bE||(a=new bE(a,s({target:this._},b))),a.currentTarget=this,(this.$listeners||[]).each(function(b){b.e===a.type&&b.f.apply(this,(b.r?[]:[a]).concat(b.a))===!1&&a.stop()},this),c&&c.fire&&!a.stopped&&c.fire(a);return this},stopEvent:function(){return!1}})),bm(bD.prototype,H(\"blur focus scroll resize load\")),bS(\"click rightclick contextmenu mousedown mouseup mouseover mouseout mousemove keypress keydown keyup\"),[bG,bB].each(\"include\",{first:function(a){return bA(a===i&&this._.firstElementChild!==i?this._.firstElementChild:this._.querySelector(a||\"*\"))},find:function(a,b){var c=this._.querySelectorAll(a||\"*\"),d,e=0,f=c.length;if(b===!0)d=J(c);else for(d=[];e<f;e++)d[e]=bA(c[e]);return d},match:function(a){var c=this._,d=c,e,f=!1;while(d.parentNode!==null&&d.parentNode.nodeType!==11)d=d.parentNode;c===d&&(d=b.createElement(\"div\"),d.appendChild(c),f=!0),e=bA(d).find(a,!0).indexOf(c)!==-1,f&&d.removeChild(c);return e}}),bB.include({on:function(a){if(a===\"ready\"&&!this._iR){var b=this._,c=this.fire.bind(this,\"ready\");\"readyState\"in b?function(){[\"loaded\",\"complete\"].include(b.readyState)?c():arguments.callee.delay(50)}():b.addEventListener(\"DOMContentLoaded\",c,!1),this._iR=!0}return this.$super.apply(this,arguments)}}),bm(bB.prototype,[\"ready\"]);var bT=j.Form=bH.FORM=new bc(bG,{initialize:function(a){var b=a||{},d=\"remote\"in b,e=b;A(b)&&!C(b)&&(e=\"form\",b=c.without(b,\"remote\")),this.$super(e,b),d&&this.remotize()},elements:function(){return this.find(\"input,button,select,textarea\")},inputs:function(){return this.elements().filter(function(a){return![\"submit\",\"button\",\"reset\",\"image\",null].include(a._.type)})},input:function(a){var b=this._[a];\"tagName\"in b?b=bA(b):b=J(b).map(bA);return b},focus:function(){var a=this.inputs().first(function(a){return a._.type!==\"hidden\"});a&&a.focus();return this},blur:function(){this.elements().each(\"blur\");return this},disable:function(){this.elements().each(\"disable\");return this},enable:function(){this.elements().each(\"enable\");return this},values:function(){var a={};this.inputs().each(function(b){var c=b._,d=a,e,f=c.name.match(/[^\\[]+/g);if(!c.disabled&&c.name&&(c.type!==\"checkbox\"&&c.type!==\"radio\"||c.checked)){while(f.length>1)e=f.shift(),e.endsWith(\"]\")&&(e=e.substr(0,e.length-1)),d[e]||(d[e]=f[0]===\"]\"?[]:{}),d=d[e];e=f.shift(),e.endsWith(\"]\")&&(e=e.substr(0,e.length-1)),e===\"\"?d.push(b.value()):d[e]=b.value()}});return a},serialize:function(){return c.toQueryString(this.values())},submit:function(){this._.submit();return this},reset:function(){this._.reset();return this}});bS(\"submit reset focus blur disable enable change\");var bU=j.Input=bH.INPUT=bH.BUTTON=bH.SELECT=bH.TEXTAREA=bH.OPTGROUP=new bc(bG,{initialize:function(a,b){if(!a||A(a)&&!C(a))b=a||{},/textarea|select/.test(b.type||\"\")?(a=b.type,delete b.type):a=\"input\";this.$super(a,b)},form:function(){return bA(this._.form)},insert:function(a,b){this.$super(a,b),this.find(\"option\").each(function(a){a._.selected=!!a.get(\"selected\")});return this},update:function(a){return this.clean().insert(a)},getValue:function(){return this._.type==\"select-multiple\"?this.find(\"option\").map(function(a){return a._.selected?a._.value:null}).compact():this._.value},setValue:function(a){this._.type==\"select-multiple\"?(a=N(a).map(e),this.find(\"option\").each(function(b){b._.selected=a.include(b._.value)})):this._.value=a;return this},value:function(a){return this[a===i?\"getValue\":\"setValue\"](a)},focus:function(){this._.focus(),this.focused=!0,br&&this.fire(\"focus\",{bubbles:!1});return this},blur:function(){this._.blur(),this.focused=!1,br&&this.fire(\"blur\",{bubbles:!1});return this},select:function(){this._.select();return this.focus()},disable:function(){this._.disabled=!0;return this.fire(\"disable\")},enable:function(){this._.disabled=!1;return this.fire(\"enable\")},disabled:function(a){return a===i?this._.disabled:this[a?\"disable\":\"enable\"]()},checked:function(a){a===i?a=this._.checked:(this._.checked=a,a=this);return a}});bt?(b.attachEvent(\"onfocusin\",bV),b.attachEvent(\"onfocusout\",bV)):(b.addEventListener(\"focus\",bV,!0),b.addEventListener(\"blur\",bV,!0));var bW=[],bX=!0;bS(\"mouseenter mouseleave\"),[bG,bB].each(\"include\",{delegate:function(a){var b=cb(arguments),c,d,e,f;for(c in b)for(d=0,f=b[c];d<f.length;d++)this.on(a,ca(c,f[d],this)),s(this.$listeners.last(),{dr:c,dc:f[d][0]});return this},undelegate:function(a){cc(arguments,this).each(function(a){this.stopObserving(a.n,a.f)},this);return this},delegates:function(){return!!cc(arguments,this).length}}),c.each({on:\"delegate\",stopObserving:\"undelegate\",observes:\"delegates\"},function(a,b){e.prototype[a]=function(){var a=J(arguments),c;a.splice(1,0,\"\"+this),c=bC[b].apply(bC,a);return c===bC?this:c}});var cd=e.prototype.on;e.prototype.on=function(a){if(A(a))for(var b in a)cd.apply(this,[b].concat([a[b]]));else cd.apply(this,arguments);return this},bF.each(function(a){e.prototype[\"on\"+a.capitalize()]=function(){return this.on.apply(this,[a].concat(J(arguments)))}}),H(\"Element Input Form\").each(function(a){c.each(a in j?j[a].prototype:{},function(a,b){x(b)&&!(a in e.prototype)&&(e.prototype[a]=function(){var b=F(this,!0),c=0,d=b.length,e=!0,f,g;for(;c<d;c++){f=bA(b[c]),g=f[a].apply(f,arguments);if(e){if(g!==f)return g;e=!1}}return null})})});var ce=j.Xhr=new bc(bk,{extend:{EVENTS:H(\"success failure complete request cancel create\"),Options:{headers:{\"X-Requested-With\":\"XMLHttpRequest\",Accept:\"text/javascript,text/html,application/xml,text/xml,*/*\"},method:\"post\",encoding:\"utf-8\",async:!0,evalScripts:!1,evalResponse:!1,evalJS:!0,evalJSON:!0,secureJSON:!0,urlEncoded:!0,spinner:null,spinnerFx:\"fade\",params:null,iframed:!1,jsonp:!1},load:function(a,b){return(new this(a,s({method:\"get\"},b))).send()}},initialize:function(a,b){this.initCallbacks(),this.url=a,s(this.$super(b),this.options),this.params!=ce.Options.params&&(this.params=this.prepareData(ce.Options.params,this.params)),ce.Options.spinner&&E(this.spinner)===E(ce.Options.spinner)&&(this.spinner=null)},setHeader:function(a,b){this.headers[a]=b;return this},getHeader:function(a){var b;try{b=this.xhr.getResponseHeader(a)}catch(c){}return b},successful:function(){return this.status>=200&&this.status<300},send:function(a){var b={},c=this.url,d=this.method.toLowerCase(),e=this.headers,f,g;if(d==\"put\"||d==\"delete\")b._method=d,d=\"post\";var h=this.prepareData(this.params,this.prepareParams(a),b);this.urlEncoded&&d==\"post\"&&!e[\"Content-type\"]&&this.setHeader(\"Content-type\",\"application/x-www-form-urlencoded;charset=\"+this.encoding),d==\"get\"&&(h&&(c+=(c.include(\"?\")?\"&\":\"?\")+h),h=null),g=this.xhr=this.createXhr(),this.fire(\"create\"),g.open(d,c,this.async),g.onreadystatechange=this.stateChanged.bind(this);for(f in e)g.setRequestHeader(f,e[f]);g.send(h),this.fire(\"request\"),this.async||this.stateChanged();return this},update:function(a,b){return this.onSuccess(function(b){a.update(b.text)}).send(b)},cancel:function(){var a=this.xhr;if(!a||a.canceled)return this;a.abort(),a.onreadystatechange=function(){},a.canceled=!0;return this.fire(\"cancel\")},fire:function(a){return this.$super(a,this,this.xhr)},createXhr:function(){return this.jsonp?new ce.JSONP(this):this.form&&this.form.first(\"input[type=file]\")?new ce.IFramed(this.form):\"ActiveXObject\"in a?new ActiveXObject(\"MSXML2.XMLHTTP\"):new XMLHttpRequest},prepareParams:function(a){return a},prepareData:function(){return J(arguments).map(function(a){y(a)||(a=c.toQueryString(a));return a.blank()?null:a}).compact().join(\"&\")},stateChanged:function(){var a=this.xhr;if(a.readyState==4&&!a.canceled){try{this.status=a.status}catch(b){this.status=0}this.text=this.responseText=a.responseText,this.xml=this.responseXML=a.responseXML,this.fire(\"complete\").fire(this.successful()?\"success\":\"failure\")}},tryScripts:function(a){var b=this.getHeader(\"Content-type\"),c=this.getHeader(\"X-JSON\");c&&(this.json=this.responseJSON=this.headerJSON=JSON.parse(c)),this.evalResponse||this.evalJS&&/(ecma|java)script/i.test(b)?t(this.text):/json/.test(b)&&this.evalJSON?this.json=this.responseJSON=JSON.parse(this.text):this.evalScripts&&this.text.evalScripts()},initCallbacks:function(){this.on({create:\"showSpinner\",complete:\"hideSpinner\",cancel:\"hideSpinner\"}),this.on(\"complete\",\"tryScripts\"),ce.EVENTS.each(function(a){this.on(a,function(){ce.fire(a,this,this.xhr)})},this)},showSpinner:function(){ce.showSpinner.call(this,this)},hideSpinner:function(){ce.hideSpinner.call(this,this)}});s(bl(ce),{counter:0,showSpinner:function(a){ce.trySpinner(a,\"show\")},hideSpinner:function(a){ce.trySpinner(a,\"hide\")},trySpinner:function(a,b){var c=a||ce.Options,d=E(c.spinner);d&&d[b](c.spinnerFx,{duration:100})},countIn:function(){ce.counter++,ce.showSpinner()},countOut:function(){ce.counter--,ce.counter<1&&ce.hideSpinner()}}).on({create:\"countIn\",complete:\"countOut\",cancel:\"countOut\"}),bT.include({send:function(a){a=a||{},a.method=a.method||this._.method||\"post\",this.xhr=(new ce(this._.action||b.location.href,s({spinner:this.first(\".spinner\")},a))).onComplete(this.enable.bind(this)).onCancel(this.enable.bind(this)).send(this),this.disable.bind(this).delay(1);return this},cancelXhr:function(){this.xhr instanceof ce&&this.xhr.cancel();return this},remotize:function(a){this.remote||(this.on(\"submit\",cf,a),this.remote=!0);return this},unremotize:function(){this.stopObserving(\"submit\",cf),this.remote=!1;return this}}),ce.include({prepareParams:function(a){a&&a instanceof bT&&(this.form=a,a=a.values());return a}}),bG.include({load:function(a,b){(new ce(a,s({method:\"get\"},b))).update(this);return this}}),ce.Dummy={open:function(){},setRequestHeader:function(){},onreadystatechange:function(){}},ce.IFramed=new bc({include:ce.Dummy,initialize:function(a){this.form=a,this.id=\"xhr_\"+(new Date).getTime(),this.form.doc().first(\"body\").append('<i><iframe name=\"'+this.id+'\" id=\"'+this.id+'\" width=\"0\" height=\"0\" frameborder=\"0\" src=\"about:blank\"></iframe></i>',\"after\"),E(this.id).on(\"load\",this.onLoad.bind(this))},send:function(){this.form.set(\"target\",this.id).submit()},onLoad:function(){this.status=200,this.readyState=4,this.form.set(\"target\",\"\");try{this.responseText=a[this.id].document.documentElement.innerHTML}catch(b){}this.onreadystatechange()},abort:function(){E(this.id).set(\"src\",\"about:blank\")}}),ce.JSONP=new bc({include:ce.Dummy,prefix:\"jsonp\",initialize:function(a){this.xhr=a,this.name=this.prefix+(new Date).getTime(),this.param=(y(a.jsonp)?a.jsonp:\"callback\")+\"=\"+this.name,this.script=G(\"script\",{charset:a.encoding,async:a.async})},open:function(a,b,c){this.url=b,this.method=a},send:function(b){a[this.name]=this.finish.bind(this),this.script.set(\"src\",this.url+(this.url.include(\"?\")?\"&\":\"?\")+this.param+\"&\"+b).insertTo(F(\"script\").last(),\"after\")},finish:function(a){this.status=200,this.readyState=4,this.xhr.json=this.xhr.responseJSON=a,this.onreadystatechange()},abort:function(){a[this.name]=function(){}}});var cg=j.Fx=new bc(bk,{extend:{EVENTS:H(\"start finish cancel\"),Durations:{\"short\":200,normal:400,\"long\":800},Options:{fps:bt?40:60,duration:\"normal\",transition:\"default\",queue:!0,engine:\"css\"}},initialize:function(a,b){this.$super(b),this.element=E(a),cj(this)},start:function(){if(ck(this,arguments))return this;cl(this),this.prepare.apply(this,arguments),cp(this);return this.fire(\"start\",this)},finish:function(){cq(this),cm(this),this.fire(\"finish\"),cn(this);return this},cancel:function(){cq(this),cm(this);return this.fire(\"cancel\")},prepare:function(){},render:function(){}}),ch=[],ci=[],cr={\"default\":\"(.25,.1,.25,1)\",linear:\"(0,0,1,1)\",\"ease-in\":\"(.42,0,1,1)\",\"ease-out\":\"(0,0,.58,1)\",\"ease-in-out\":\"(.42,0,.58,1)\",\"ease-out-in\":\"(0,.42,1,.58)\"},cs={};e.COLORS={maroon:\"#800000\",red:\"#ff0000\",orange:\"#ffA500\",yellow:\"#ffff00\",olive:\"#808000\",purple:\"#800080\",fuchsia:\"#ff00ff\",white:\"#ffffff\",lime:\"#00ff00\",green:\"#008000\",navy:\"#000080\",blue:\"#0000ff\",aqua:\"#00ffff\",teal:\"#008080\",black:\"#000000\",silver:\"#c0c0c0\",gray:\"#808080\",brown:\"#a52a2a\"},e.include({toHex:function(){var a=/^#(\\w)(\\w)(\\w)$/.exec(this);a?a=\"#\"+a[1]+a[1]+a[2]+a[2]+a[3]+a[3]:(a=/^rgb\\((\\d+),\\s*(\\d+),\\s*(\\d+)\\)$/.exec(this))?a=\"#\"+a.slice(1).map(function(a){a=(a-0).toString(16);return a.length==1?\"0\"+a:a}).join(\"\"):a=e.COLORS[this]||this;return a},toRgb:function(a){var b=/#([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})/i.exec(this.toHex()||\"\");b&&(b=b.slice(1).map(\"toInt\",16),b=a?b:\"rgb(\"+b+\")\");return b}}),bG.include({stop:function(){co(this);return this},hide:function(a,b){return a&&this.visible()?cu(this,a,[\"out\",b]):this.$super()},show:function(a,b){return a&&!this.visible()?cu(this,a,[\"in\",b]):this.$super()},toggle:function(a,b){return a?cu(this,a,[\"toggle\",b]):this.$super()},remove:function(a,b){return a&&this.visible()?cu(this,a,[\"out\",s(b||{},{onFinish:this.$super.bind(this)})]):this.$super()},morph:function(a,b){return cu(this,\"morph\",[a,b||{}])},highlight:function(){return cu(this,\"highlight\",arguments)},fade:function(){return cu(this,\"fade\",arguments)},slide:function(){return cu(this,\"slide\",arguments)},scroll:function(a,b){return cu(this,\"scroll\",[a,b||{}])},scrollTo:function(a,b){return A(b)?this.scroll(a,b):this.$super.apply(this,arguments)}});var cv=[\"WebkitT\",\"OT\",\"MozT\",\"MsT\",\"t\"].first(function(a){return a+\"ransition\"in o.style}),cw=cv+\"ransition\",cx=cw+\"Property\",cy=cw+\"Duration\",cz=cw+\"TimingFunction\",cA={Sin:\"cubic-bezier(.3,0,.6,1)\",Cos:\"cubic-bezier(0,.3,.6,0)\",Log:\"cubic-bezier(0,.6,.3,.8)\",Exp:\"cubic-bezier(.6,0,.8,.3)\",Lin:\"cubic-bezier(0,0,1,1)\"};cg.Options.engine=cv===i||bq?\"javascript\":\"native\",cg.Morph=new bc(cg,{prepare:function(a){if(this.options.engine===\"native\"&&cv!==i)this.render=this.transition=function(){},cB.call(this,a);else{var b=cE(a),c=cJ(this.element,b),d=cK(this.element,a,b);cI(this.element,c,d),this.before=cH(c),this.after=cH(d)}},render:function(a){var b,c,d,e=this.element._.style,f,g,i;for(f in this.after){b=this.before[f],c=this.after[f];for(g=0,i=c.length;g<i;g++)d=b[g]+(c[g]-b[g])*a,c.r&&(d=h.round(d)),c.t[g*2+1]=d;e[f]=c.t.join(\"\")}}});var cC=H(\"Top Left Right Bottom\");cg.Highlight=new bc(cg.Morph,{extend:{Options:c.merge(cg.Options,{color:\"#FF8\",transition:\"Exp\"})},prepare:function(a,b){var c=this.element,d=c._.style,e=\"backgroundColor\",f=b||c.getStyle(e);cF(f)&&(this.onFinish(function(){d[e]=\"transparent\"}),f=[c].concat(c.parents()).map(\"getStyle\",e).reject(cF).compact().first()||\"#FFF\"),d[e]=a||this.options.color;return this.$super({backgroundColor:f})}}),cg.Twin=new bc(cg.Morph,{finish:function(){this.how===\"out\"&&bG.prototype.hide.call(this.element);return this.$super()},setHow:function(a){this.how=a||\"toggle\",this.how===\"toggle\"&&(this.how=this.element.visible()?\"out\":\"in\")}}),cg.Slide=new bc(cg.Twin,{extend:{Options:c.merge(cg.Options,{direction:\"top\"})},prepare:function(a){function f(){for(var a in e)d[a]=e[a]}this.setHow(a);var b=bG.prototype.show.call(this.element),d=b._.style,e=c.only(d,\"overflow\",\"width\",\"height\",\"marginTop\",\"marginLeft\");this.onFinish(f).onCancel(f),d.overflow=\"hidden\";return this.$super(cL(d,b.size(),this.options.direction,this.how))}}),cg.Fade=new bc(cg.Twin,{prepare:function(a){this.setHow(a),this.how===\"in\"&&bG.prototype.show.call(this.element.setStyle({opacity:0}));return this.$super({opacity:this.how===\"in\"?1:0})}}),cg.Attr=new bc(cg,{prepare:function(a){this.before={},this.after=a;var b,c=this.element._;for(b in a)this.before[b]=c[b]},render:function(a){var b,c=this.element._,d=this.before;for(b in d)c[b]=d[b]+(this.after[b]-d[b])*a}}),cg.Scroll=new bc(cg.Attr,{initialize:function(a,b){a=E(a),this.$super(a instanceof bD?a._.document[bs.WebKit?\"body\":\"documentElement\"]:a,b)},prepare:function(a){var b={};\"x\"in a&&(b.scrollLeft=a.x),\"y\"in a&&(b.scrollTop=a.y),this.$super(b)}});var cM=j.Cookie=new bc({include:bj,extend:{set:function(a,b,c){return(new this(a,c)).set(b)},get:function(a,b){return(new this(a,b)).get()},remove:function(a,b){return(new this(a,b)).remove()},enabled:function(){b.cookie=\"__t=1\";return b.cookie.indexOf(\"__t=1\")!=-1},Options:{secure:!1,document:b}},initialize:function(a,b){this.name=a,this.setOptions(b)},set:function(a){y(a)||(a=JSON.stringify(a));var b=encodeURIComponent(a),c=this.options;c.domain&&(b+=\"; domain=\"+c.domain),c.path&&(b+=\"; path=\"+c.path);if(c.duration){var d=new Date;d.setTime(d.getTime()+c.duration*24*60*60*1e3),b+=\"; expires=\"+d.toGMTString()}c.secure&&(b+=\"; secure\"),c.document.cookie=this.name+\"=\"+b;return this},get:function(){var a=this.options.document.cookie.match(\"(?:^|;)\\\\s*\"+RegExp.escape(this.name)+\"=([^;]*)\");if(a){a=decodeURIComponent(a[1]);try{a=JSON.parse(a)}catch(b){}}return a||null},remove:function(){this.options.duration=-1;return this.set(\"\")}});s(a,c.without(j,\"version\",\"modules\"));return j}(window,document,Object,Array,String,Function,Number,Math);RightJS.Browser.OLD&&function(a){var b=a.createElement(\"script\"),c=a.getElementsByTagName(\"script\"),d=c[c.length-1];b.src=d.src.replace(/(^|\\/)(right)([^\\/]+)$/,\"$1$2-olds$3\"),d.parentNode.appendChild(b)}(document)"
  },
  {
    "path": "_archive/apps/samples/clock/timer.js",
    "content": "Timer = function() {\n\tthis.config = {\n\t\tcontainer: {height: 250, width: 250},\n\t\tface: {color: '#424240', alpha: 1, radius: 120},\n\t\thourHand: {color: '#4d90fe', alpha: 1, length: 35, width: 3},\n\t\tminuteHand: {color: '#4d90fe', alpha: 1, length: 90, width: 2},\n\t\tunit: {\n\t\t\tmajor: {color: '#f5f5f5', alpha: 0.4, length: 12, width: 2},\n\t\t\tmid: {color: '#f5f5f5', alpha: 0.4, length: 12, width: 1},\n\t\t\tminor: {color: '#f5f5f5', alpha: 0.4, length: 8, width: 1}\n\t\t},\n\t};\n\tthis.countdown = new Date(0);\n\tthis.timing = false;\n\tthis.minutes = 0;\n\tthis.seconds = 0;\n\n}\n\n//Timer inherits from Clock\nTimer.prototype = new Clock(this.id, 0);\n\n//Method to initialize the Timer\nTimer.prototype.create = function() {\n\tthis.canvas = $('.timer .clock')[0];\n\tthis.canvas.height = this.config.container.height;\n\tthis.canvas.width = this.config.container.width;\n\n\tthis.context = this.canvas.getContext(\"2d\");\n\n\tthis.drawClock(0, 0, 0, 0);\n\n\tthis.startTick();\n}\n\n//Methods to draw the timer\nTimer.prototype.drawClock = function (hour, minute, second, millisecond) {\n\tthis.context.clearRect(0, 0, this.config.container.width, this.config.container.height);\n\n\tthis.drawface();\n\tthis.drawUnits();\n\tthis.innerShadow();\n\tthis.drawText(hour, minute, second);\n\tthis.drawTime(minute, second, millisecond);\n\tthis.drawHands(hour, minute, second, millisecond);\n}\n\n//Method to draw the hands\nTimer.prototype.drawHands = function(hour, minute, second, millisecond) {\n\tthis.context.save();\n\n\tthis.context.translate(this.config.container.width/2,this.config.container.height/2);\n\tthis.context.rotate(Math.PI * (2.0 * ((minute + (second/60.0))/60) - 0.5));\n\tthis.context.globalAlpha = this.config.minuteHand.alpha;\n\tthis.context.strokeStyle = this.config.minuteHand.color;\n\tthis.context.lineWidth = this.config.minuteHand.width;\n\tthis.context.lineCap = \"round\";\n\tthis.context.shadowOffsetX = 0;\n\tthis.context.shadowOffsetY = 4;\n\tthis.context.shadowBlur = 2;\n\tthis.context.shadowColor = \"rgba(0, 0, 0, 0.2)\";\n\n\tthis.context.beginPath();\n\tthis.context.moveTo(0, 0);\n\tthis.context.lineTo(this.config.minuteHand.length - 5, 0);\n\tthis.context.closePath();\n\n\tthis.context.stroke();\n\n\tthis.context.restore();\n\n\tthis.context.save();\n\tthis.context.beginPath();\n\tthis.context.arc(this.config.container.width/2, this.config.container.height/2, 4, 0, Math.PI*2, false);\n\tthis.context.closePath();\n\tthis.context.fillStyle = this.config.minuteHand.color;\n\tthis.context.fill();\n\tthis.context.restore();\n\n\tthis.context.save();\n\tthis.context.beginPath();\n\tthis.context.arc(this.config.container.width/2, this.config.container.height/2, 1, 0, Math.PI*2, false);\n\tthis.context.closePath();\n\tthis.context.fillStyle = this.config.unit.major.color;\n\tthis.context.fill();\n\tthis.context.restore();\n}\n\n//Method to draw the number\nTimer.prototype.drawText = function(hour, minute, second, millisecond) {\n\t//Numbers for main face\n\tfor (var i = 0; i < 12; i++) {\n\t\tthis.context.save();\n\t\tthis.context.translate(this.config.container.width/2, this.config.container.height/2);\n\t\tthis.context.rotate(Math.PI * (2.0 * (i/12) - 0.5));\n\t\tthis.context.translate(this.config.face.radius - 22, 0);\n\t\tthis.context.rotate((Math.PI * (2.0 * (i/12) - 0.5) * -1));\n\n\t\tvar alpha = this.config.unit.major.alpha;\n\n\t\tthis.context.globalAlpha = alpha;\n\n\t\tthis.context.fillStyle = this.config.unit.major.color;\n\t\tthis.context.shadowOffsetX = 1;\n\t\tthis.context.shadowOffsetY = 1;\n\t\tthis.context.shadowColor = \"rgba(0, 0, 0, 0.8)\";\n\t\tthis.context.font = \"600 11px 'Open Sans'\";\n\t\tthis.context.textBaseline = 'middle';\n\t\tthis.context.textAlign = \"center\";\n\n\t\tvar textValue;\n\n\t\tif (i === 0) {\n\t\t\ttextValue = 60;\n\t\t}\n\t\telse {\n\t\t\ttextValue = i * 5;\n\t\t}\n\n\t\tthis.context.fillText(textValue, 0, 0);\n\t\tthis.context.restore();\n\t}\n}\n\n//Method to draw the units\nTimer.prototype.drawUnits = function() {\n\t//Draw units for main face\n\tfor (var i = 0; i < 60; i++) {\n\t\tthis.context.save();\n\t\tthis.context.translate(this.config.container.width/2, this.config.container.height/2);\n\t\tthis.context.rotate(Math.PI * (2.0 * (i/60) - 0.5));\n\t\tthis.context.globalAlpha = this.config.unit.major.alpha;\n\t\tthis.context.strokeStyle = this.config.unit.major.color;\n\n\t\tif (i % 5 === 0) {\n\t\t\tthis.context.lineWidth = this.config.unit.major.width;\n\t\t\tvar length = this.config.unit.major.length;\n\t\t}\n\t\telse {\n\t\t\tthis.context.lineWidth = this.config.unit.minor.width;\n\t\t\tvar length = this.config.unit.minor.length;\n\t\t}\n\n\t\tthis.context.beginPath();\n\t\tthis.context.moveTo(this.config.face.radius - length, 0);\n\t\tthis.context.lineTo(this.config.face.radius, 0);\n\t\tthis.context.closePath();\n\t\tthis.context.stroke();\n\t\tthis.context.restore();\n\t}\n}\n\nTimer.prototype.drawTime = function(minute, second, millisecond) {\n\tthis.context.save();\n\n\tthis.context.translate(this.config.container.width/2, this.config.container.height/1.3);\n\n\tvar alpha = this.config.unit.major.alpha;\n\n\tthis.context.globalAlpha = alpha;\n\n\tthis.context.fillStyle = this.config.unit.major.color;\n\tthis.context.shadowOffsetX = 1;\n\tthis.context.shadowOffsetY = 1;\n\tthis.context.shadowColor = \"rgba(0, 0, 0, 0.8)\";\n\tthis.context.font = \"600 14px 'Open Sans'\";\n\tthis.context.textBaseline = 'middle';\n\tthis.context.textAlign = \"center\";\n\n\tif (minute < 10) minute = '0' + minute;\n\tif (second < 10) second = '0' + second;\n\n\tvar textValue = minute + ':' + second;\n\n\tthis.context.fillText(textValue, 0, 0);\n\tthis.context.restore();\n}\n\nTimer.prototype.startTiming = function() {\n\tthis.timing = true;\n}\n\nTimer.prototype.stopTiming = function() {\n\tthis.timing = false;\n}\n\nTimer.prototype.resetWatch = function() {\n\tthis.timing = false;\n\tthis.countdown = new Date(0)\n\tthis.drawClock(0, 0, 0, 0);\n}\n\nTimer.prototype.setWatch = function(minute, second) {\n\tthis.minute = minute;\n\tthis.second = second;\n\tthis.countdown = new Date(0, 0, 0, 0, this.minute, this.second);\n\tthis.drawClock(0, this.minute, this.second, 0);\n}\n\n//Method to fire ten times each second and redraw the clock\nTimer.prototype.tick = function() {\n\tif (this.timing) {\n\t\tvar minute = this.countdown.getMinutes();\n\t\tvar second = this.countdown.getSeconds();\n\t\tvar millisecond = this.countdown.getMilliseconds();\n\t\tthis.drawClock(0, minute, second, millisecond);\n\t\tif (minute == 0 && second == 0) {\n\t\t\tthis.timing = false;\n\t\t\t$('.timer .button.stop').addClass('disabled');\n\t\t\tnew Notification('World Clock Timer', { icon: 'img/timer.png' });\n\t\t} else {\n\t\t\tthis.countdown.setTime(this.countdown.getTime() - 100);\n\t\t}\n\t}\n}\n\nTimer.prototype.startTick = function() {\n\tvar inst = this;\n\tthis.tickId = setInterval(function() { inst.tick(); }, 100);\n}\n"
  },
  {
    "path": "_archive/apps/samples/context-menu/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/biknlgbccocnocjfclpedecpgopjokik\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Context menus\n\nSample that shows how to use the [context menu API](http://developer.chrome.com/apps/contextMenus) in an app to manage various application context menus, such as menus that only apply to particular windows, menus that apply to selections, and context menus that work on the app launcher.\n\n## APIs\n\n* [Context menu API](http://developer.chrome.com/apps/contextMenus)\n* [Runtime](http://developer.chrome.com/apps/app_runtime)\n* [Window](http://developer.chrome.com/apps/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/context-menu/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/context-menu/a.html",
    "content": "<html>\n  <head>\n    <script src=\"a.js\"></script>\n    <title>Window A</title>\n  </head>\n  <body>\n    <h1>Window A</h1>\n    <p>Right click to see the context menu.</p>\n    <p style=\"-webkit-user-select: text\">Select this text and then right-click</p>\n    <p>Log:</p>\n    <pre id=\"log\"></pre>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/context-menu/a.js",
    "content": "function log(message) {\n  document.getElementById('log').textContent += message + '\\n';\n}\n\nchrome.contextMenus.onClicked.addListener(function(info) {\n  if (!document.hasFocus()) {\n    log('Ignoring context menu click that happened in another window');\n    return;\n  }\n\n  log('Item selected in A: ' + info.menuItemId);\n});\n\nwindow.addEventListener(\"load\", function(e){\n  log('Window A is loaded');\n});\n\n"
  },
  {
    "path": "_archive/apps/samples/context-menu/b.html",
    "content": "<html>\n  <head>\n    <script src=\"b.js\"></script>\n    <title>Window B</title>\n  </head>\n  <body>\n    <h1>Window B</h1>\n    <p>Right click to see the context menu.</p>\n    <p>Log:</p>\n    <pre id=\"log\"></pre>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/context-menu/b.js",
    "content": "function log(message) {\n  document.getElementById('log').textContent += message + '\\n';\n}\n\nchrome.contextMenus.onClicked.addListener(function(info) {\n  if (!document.hasFocus()) {\n    log('Ignoring context menu click that happened in another window');\n    return;\n  }\n\n  log('Item selected in B: ' + info.menuItemId);\n});\n\nwindow.addEventListener(\"load\", function(e){\n  log('Window B is loaded');\n});\n"
  },
  {
    "path": "_archive/apps/samples/context-menu/main.js",
    "content": "// Holds the data structure for all the context menus used in the app\nvar CONTEXT_MENU_CONTENTS = {\n  forWindows : [\n    'foo',\n    'bar',\n    'baz'\n  ],\n  forSelection: [\n    'Selection context menu'\n  ],\n  forLauncher : [\n    'Launch Window \"A\"',\n    'Launch Window \"B\"'\n  ]\n}\n\nfunction setUpContextMenus() {\n  CONTEXT_MENU_CONTENTS.forWindows.forEach(function(commandId) {\n    chrome.contextMenus.create({\n      title: 'A: ' + commandId,\n      type: 'radio',\n      id: 'A' + commandId,\n      documentUrlPatterns: [ \"chrome-extension://*/a.html\"],\n      contexts: ['all']\n    });\n  });\n\n  CONTEXT_MENU_CONTENTS.forWindows.forEach(function(commandId) {\n    chrome.contextMenus.create({\n      title: 'B: ' + commandId,\n      type: 'checkbox',\n      id: 'B' + commandId,\n      documentUrlPatterns: [ \"chrome-extension://*/b.html\"],\n      contexts: ['all']\n    });\n  });\n\n  CONTEXT_MENU_CONTENTS.forSelection.forEach(function(commandId) {\n    chrome.contextMenus.create({\n      type: \"separator\",\n      id: 'sep1',\n      contexts: ['selection']\n    });\n    chrome.contextMenus.create( {\n      title: commandId + ' \"%s\"',\n      id: commandId,\n      contexts: ['selection']\n    });\n  });\n\n  CONTEXT_MENU_CONTENTS.forLauncher.forEach(function(commandId, index) {\n    chrome.contextMenus.create({\n      title: commandId,\n      id: 'launcher' + index,\n      contexts: ['launcher']\n    });\n  });\n}\n\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('a.html', {id: 'a', outerBounds:{top: 0, left: 0, width: 300, height: 300}});\n  chrome.app.window.create('b.html', {id: 'b', outerBounds:{top: 0, left: 310, width: 300, height: 300}});\n});\n\nchrome.runtime.onInstalled.addListener(function() {\n  // When the app gets installed, set up the context menus\n  setUpContextMenus();\n});\n\nchrome.contextMenus.onClicked.addListener(function(itemData) {\n  if (itemData.menuItemId == \"launcher0\")\n    chrome.app.window.create('a.html', {id: 'a', outerBounds:{top: 0, left: 0, width: 300, height: 300}});\n  if (itemData.menuItemId == \"launcher1\")\n    chrome.app.window.create('b.html', {id: 'b', outerBounds:{top: 0, left: 310, width: 300, height: 300}});\n});\n"
  },
  {
    "path": "_archive/apps/samples/context-menu/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Context Menu Sample\",\n  \"version\": \"4\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\"contextMenus\"]\n}\n"
  },
  {
    "path": "_archive/apps/samples/dart/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/pcbbhbaibaphjlbaoahmahgmncbdkeli\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Using DART in a Chrome Packaged App\n\nA simple Dart sample transformed into a Chrome packaged app. Please, use Dart version equal or greater than\n   0.1.2.0_15284_chrome-bot (Fri Nov 23 05:26:52 2012)\nif you want to recompile dart to JS. See the correct, CSP compatible, command-line parameter in the compile.sh script.\n\n## APIs\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/dart/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/dart/clock.html",
    "content": "<!DOCTYPE html>\n\n<!-- Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file\n     for details. All rights reserved. Use of this source code is governed by a\n     BSD-style license that can be found in the LICENSE file. -->\n\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Clock Demo</title>\n    <link rel=\"stylesheet\" href=\"css/clock.css\">\n  </head>\n  <body>\n    <h1>Clock</h1>\n\n    <p>An html5 clock using absolutely positioned elements.</p>\n\n    <div id=\"canvas-content\"></div>\n\n    <footer>\n      <p id=\"summary\"> </p>\n      <p id=\"notes\"> </p>\n    </footer>\n\n    <script type=\"application/dart\" src=\"dart/clock.dart\"></script>\n\n    <!-- dart.js detects whether the app is opened in Dartium or Chrome and\n         rewites the .dart includes appropriately. Use a derivative of the copy\n         in packages/browser/dart.js, as that does not yet handle the CSP\n         compliant \"precompiled\" version. It must come after any dart scripts.\n         -->\n    <script src=\"js/browser_dart_csp_safe.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/dart/compile.sh",
    "content": "#!/bin/bash\n\npub get\ndart2js -odart/clock.dart.js dart/clock.dart\n"
  },
  {
    "path": "_archive/apps/samples/dart/css/clock.css",
    "content": "/* Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file */\n/* for details. All rights reserved. Use of this source code is governed by a */\n/* BSD-style license that can be found in the LICENSE file. */\n\nbody {\n  background-color: #F8F8F8;\n  font-family: 'Open Sans', sans-serif;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 1.2em;\n  margin: 15px;\n}\n\np {\n  color: #333;\n}\n\n#canvas-content {\n  width: 100%;\n  height: 400px;\n  position: relative;\n  border: 1px solid #ccc;\n  background-color: #fff;\n}\n\n#summary {\n  float: left;\n}\n\n#notes {\n  float: right;\n  width: 120px;\n  text-align: right;\n}\n\n.error {\n  font-style: italic;\n  color: red;\n}\n\n#container2 {\n  width: 100px;\n  height: 100px;\n  position: relative;\n  margin: auto;\n}\n\n#target {\n  width: 100%;\n  height: 100%;\n  position: absolute;\n}\n\n#target figure {\n  display: block;\n  position: absolute;\n  width: 150px;\n  height: 80px;\n  border: 1px solid #333;\n  font-size: 36px;\n  color: #222;\n  background: #3291d8;\n  text-align: center;\n  line-height: 2em;\n}\n"
  },
  {
    "path": "_archive/apps/samples/dart/dart/balls.dart",
    "content": "// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file\n// for details. All rights reserved. Use of this source code is governed by a\n// BSD-style license that can be found in the LICENSE file.\n\npart of clock;\n\nint get clientWidth => window.innerWidth;\n\nint get clientHeight => window.innerHeight;\n\nclass Balls {\n  static const double RADIUS2 = Ball.RADIUS * Ball.RADIUS;\n\n  static const int LT_GRAY_BALL_INDEX = 0;\n  static const int GREEN_BALL_INDEX = 1;\n  static const int BLUE_BALL_INDEX = 2;\n\n  static const int DK_GRAY_BALL_INDEX = 4;\n  static const int RED_BALL_INDEX = 5;\n  static const int MD_GRAY_BALL_INDEX = 6;\n\n  static const List<String> PNGS = const [\n      \"images/ball-d9d9d9.png\", \"images/ball-009a49.png\",\n      \"images/ball-13acfa.png\", \"images/ball-265897.png\",\n      \"images/ball-b6b4b5.png\", \"images/ball-c0000b.png\",\n      \"images/ball-c9c9c9.png\"\n  ];\n\n  DivElement root;\n  num lastTime;\n  List<Ball> balls;\n\n  Balls() :\n      lastTime = new DateTime.now().millisecondsSinceEpoch,\n      balls = new List<Ball>() {\n    root = new DivElement();\n    document.body.nodes.add(root);\n    makeAbsolute(root);\n    setElementSize(root, 0.0, 0.0, 0.0, 0.0);\n  }\n\n  void tick(num now) {\n    showFps(1000.0 / (now - lastTime + 0.01));\n\n    double delta = min((now - lastTime) / 1000.0, 0.1);\n    lastTime = now;\n\n    // incrementally move each ball, removing balls that are offscreen\n    balls.removeWhere((ball) => ball.tick(delta));\n    collideBalls(delta);\n  }\n\n  void collideBalls(double delta) {\n    balls.forEach((b0) {\n      balls.forEach((b1) {\n        // See if the two balls are intersecting.\n        double dx = (b0.x - b1.x).abs();\n        double dy = (b0.y - b1.y).abs();\n        double d2 = dx * dx + dy * dy;\n\n        if (d2 < RADIUS2) {\n          // Make sure they're actually on a collision path\n          // (not intersecting while moving apart).\n          // This keeps balls that end up intersecting from getting stuck\n          // without all the complexity of keeping them strictly separated.\n          if (newDistanceSquared(delta, b0, b1) > d2) {\n            return;\n          }\n\n          // They've collided. Normalize the collision vector.\n          double d = sqrt(d2);\n\n          if (d == 0) {\n            // TODO: move balls apart.\n\n            return;\n          }\n\n          dx /= d;\n          dy /= d;\n\n          // Calculate the impact velocity and speed along the collision vector.\n          double impactx = b0.vx - b1.vx;\n          double impacty = b0.vy - b1.vy;\n          double impactSpeed = impactx * dx + impacty * dy;\n\n          // Bump.\n          b0.vx -= dx * impactSpeed;\n          b0.vy -= dy * impactSpeed;\n          b1.vx += dx * impactSpeed;\n          b1.vy += dy * impactSpeed;\n        }\n      });\n    });\n  }\n\n  double newDistanceSquared(double delta, Ball b0, Ball b1) {\n    double nb0x = b0.x + b0.vx * delta;\n    double nb0y = b0.y + b0.vy * delta;\n    double nb1x = b1.x + b1.vx * delta;\n    double nb1y = b1.y + b1.vy * delta;\n    double ndx = (nb0x - nb1x).abs();\n    double ndy = (nb0y - nb1y).abs();\n    double nd2 = ndx * ndx + ndy * ndy;\n    return nd2;\n  }\n\n  void add(double x, double y, int color) {\n    balls.add(new Ball(root, x, y, color));\n  }\n}\n\nclass Ball {\n  static const double GRAVITY = 400.0;\n  static const double RESTITUTION = 0.8;\n  static const double MIN_VELOCITY = 100.0;\n  static const double INIT_VELOCITY = 800.0;\n  static const double RADIUS = 14.0;\n\n  static Random random;\n\n  static double randomVelocity() {\n    if (random == null) {\n      random = new Random();\n    }\n\n    return (random.nextDouble() - 0.5) * INIT_VELOCITY;\n  }\n\n  Element root;\n  ImageElement elem;\n  double x, y;\n  double vx, vy;\n  double ax, ay;\n  double age;\n\n  Ball(this.root, this.x, this.y, int color) {\n    elem = new ImageElement(src: Balls.PNGS[color]);\n    makeAbsolute(elem);\n    setElementPosition(elem, x, y);\n    root.nodes.add(elem);\n\n    ax = 0.0;\n    ay = GRAVITY;\n\n    vx = randomVelocity();\n    vy = randomVelocity();\n  }\n\n  // return true => remove me\n  bool tick(double delta) {\n    // Update velocity and position.\n    vx += ax * delta;\n    vy += ay * delta;\n\n    x += vx * delta;\n    y += vy * delta;\n\n    // Handle falling off the edge.\n    if ((x < RADIUS) || (x > clientWidth)) {\n      elem.remove();\n      return true;\n    }\n\n    // Handle ground collisions.\n    if (y > clientHeight) {\n      y = clientHeight.toDouble();\n      vy *= -RESTITUTION;\n    }\n\n    // Position the element.\n    setElementPosition(elem, x - RADIUS, y - RADIUS);\n\n    return false;\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/dart/dart/clock.dart",
    "content": "// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file\n// for details. All rights reserved. Use of this source code is governed by a\n// BSD-style license that can be found in the LICENSE file.\n\nlibrary clock;\n\nimport 'dart:async';\nimport 'dart:html';\nimport 'dart:math';\n\npart 'balls.dart';\npart 'numbers.dart';\n\nvoid main() {\n  new CountDownClock();\n}\n\ndouble fpsAverage;\n\n/**\n * Display the animation's FPS in a div.\n */\nvoid showFps(num fps) {\n  if (fpsAverage == null) {\n    fpsAverage = fps;\n  } else {\n    fpsAverage = fps * 0.05 + fpsAverage * 0.95;\n\n    query(\"#notes\").text = \"${fpsAverage.round().toInt()} fps\";\n  }\n}\n\nclass CountDownClock {\n  static const int NUMBER_SPACING = 19;\n  static const double BALL_WIDTH = 19.0;\n  static const double BALL_HEIGHT = 19.0;\n\n  List<ClockNumber> hours = new List<ClockNumber>(2);\n  List<ClockNumber> minutes = new List<ClockNumber>(2);\n  List<ClockNumber> seconds = new List<ClockNumber>(2);\n  int displayedHour = -1;\n  int displayedMinute = -1;\n  int displayedSecond = -1;\n  Balls balls = new Balls();\n\n  CountDownClock() {\n    var parent = query(\"#canvas-content\");\n\n    createNumbers(parent, parent.clientWidth, parent.clientHeight);\n\n    updateTime(new DateTime.now());\n\n    window.requestAnimationFrame(tick);\n  }\n\n  void tick(num time) {\n    updateTime(new DateTime.now());\n    balls.tick(time);\n    window.requestAnimationFrame(tick);\n  }\n\n  void updateTime(DateTime now) {\n    if (now.hour != displayedHour) {\n      setDigits(pad2(now.hour), hours);\n      displayedHour = now.hour;\n    }\n\n    if (now.minute != displayedMinute) {\n      setDigits(pad2(now.minute), minutes);\n      displayedMinute = now.minute;\n    }\n\n    if (now.second != displayedSecond) {\n      setDigits(pad2(now.second), seconds);\n      displayedSecond = now.second;\n    }\n  }\n\n  void setDigits(String digits, List<ClockNumber> numbers) {\n    for (int i = 0; i < numbers.length; ++i) {\n      int digit = digits.codeUnitAt(i) - '0'.codeUnitAt(0);\n      numbers[i].setPixels(ClockNumbers.PIXELS[digit]);\n    }\n  }\n\n  String pad3(int number) {\n    if (number < 10) {\n      return \"00${number}\";\n    }\n    if (number < 100) {\n      return \"0${number}\";\n    }\n    return \"${number}\";\n  }\n\n  String pad2(int number) {\n    if (number < 10) {\n      return \"0${number}\";\n    }\n    return \"${number}\";\n  }\n\n  void createNumbers(Element parent, num width, num height) {\n    DivElement root = new DivElement();\n    makeRelative(root);\n    root.style.textAlign = 'center';\n    query(\"#canvas-content\").nodes.add(root);\n\n    double hSize = (BALL_WIDTH * ClockNumber.WIDTH + NUMBER_SPACING) * 6\n        + (BALL_WIDTH + NUMBER_SPACING) * 2;\n    hSize -= NUMBER_SPACING;\n\n    double vSize = BALL_HEIGHT * ClockNumber.HEIGHT;\n\n    double x = (width - hSize) / 2;\n    double y = (height - vSize) / 3;\n\n    for (int i = 0; i < hours.length; ++i) {\n      hours[i] = new ClockNumber(this, x, Balls.BLUE_BALL_INDEX);\n      root.nodes.add(hours[i].root);\n      setElementPosition(hours[i].root, x, y);\n      x += BALL_WIDTH * ClockNumber.WIDTH + NUMBER_SPACING;\n    }\n\n    root.nodes.add(new Colon(x, y).root);\n    x += BALL_WIDTH + NUMBER_SPACING;\n\n    for (int i = 0; i < minutes.length; ++i) {\n      minutes[i] = new ClockNumber(this, x, Balls.RED_BALL_INDEX);\n      root.nodes.add(minutes[i].root);\n      setElementPosition(minutes[i].root, x, y);\n      x += BALL_WIDTH * ClockNumber.WIDTH + NUMBER_SPACING;\n    }\n\n    root.nodes.add(new Colon(x, y).root);\n    x += BALL_WIDTH + NUMBER_SPACING;\n\n    for (int i = 0; i < seconds.length; ++i) {\n      seconds[i] = new ClockNumber(this, x, Balls.GREEN_BALL_INDEX);\n      root.nodes.add(seconds[i].root);\n      setElementPosition(seconds[i].root, x, y);\n      x += BALL_WIDTH * ClockNumber.WIDTH + NUMBER_SPACING;\n    }\n  }\n}\n\nvoid makeAbsolute(Element elem) {\n  elem.style.position = 'absolute';\n}\n\nvoid makeRelative(Element elem) {\n  elem.style.position = 'relative';\n}\n\nvoid setElementPosition(Element elem, double x, double y) {\n  elem.style.left = \"${x}px\";\n  elem.style.top = \"${y}px\";\n}\n\nvoid setElementSize(Element elem, double l, double t, double r, double b) {\n  setElementPosition(elem, l, t);\n  elem.style.right = \"${r}px\";\n  elem.style.bottom = \"${b}px\";\n}\n"
  },
  {
    "path": "_archive/apps/samples/dart/dart/clock.dart.precompiled.js",
    "content": "// Generated by dart2js, the Dart to JavaScript compiler version: 1.1.1.\n// The code supports the following hooks:\n// dartPrint(message)   - if this function is defined it is called\n//                        instead of the Dart [print] method.\n// dartMainRunner(main) - if this function is defined, the Dart [main]\n//                        method will not be invoked directly.\n//                        Instead, a closure that will invoke [main] is\n//                        passed to [dartMainRunner].\n(function($) {\nfunction dart() {}var A = new dart;\ndelete A.x;\nvar B = new dart;\ndelete B.x;\nvar C = new dart;\ndelete C.x;\nvar D = new dart;\ndelete D.x;\nvar E = new dart;\ndelete E.x;\nvar F = new dart;\ndelete F.x;\nvar G = new dart;\ndelete G.x;\nvar H = new dart;\ndelete H.x;\nvar J = new dart;\ndelete J.x;\nvar K = new dart;\ndelete K.x;\nvar L = new dart;\ndelete L.x;\nvar M = new dart;\ndelete M.x;\nvar N = new dart;\ndelete N.x;\nvar O = new dart;\ndelete O.x;\nvar P = new dart;\ndelete P.x;\nvar Q = new dart;\ndelete Q.x;\nvar R = new dart;\ndelete R.x;\nvar S = new dart;\ndelete S.x;\nvar T = new dart;\ndelete T.x;\nvar U = new dart;\ndelete U.x;\nvar V = new dart;\ndelete V.x;\nvar W = new dart;\ndelete W.x;\nvar X = new dart;\ndelete X.x;\nvar Y = new dart;\ndelete Y.x;\nvar Z = new dart;\ndelete Z.x;\nfunction Isolate() {}\ninit();\n\n$ = Isolate.$isolateProperties;\nvar $$ = {};\n\n// Native classes\n(function (reflectionData) {\n  \"use strict\";\n  function map(x){x={x:x};delete x.x;return x}\n    function processStatics(descriptor) {\n      for (var property in descriptor) {\n        if (!hasOwnProperty.call(descriptor, property)) continue;\n        if (property === \"\") continue;\n        var element = descriptor[property];\n        var firstChar = property.substring(0, 1);\n        var previousProperty;\n        if (firstChar === \"+\") {\n          mangledGlobalNames[previousProperty] = property.substring(1);\n          if (descriptor[property] == 1) descriptor[previousProperty].$reflectable = 1;\n          if (element && element.length) init.typeInformation[previousProperty] = element;\n        } else if (firstChar === \"@\") {\n          property = property.substring(1);\n          $[property][\"@\"] = element;\n        } else if (firstChar === \"*\") {\n          globalObject[previousProperty].$defaultValues = element;\n          var optionalMethods = descriptor.$methodsWithOptionalArguments;\n          if (!optionalMethods) {\n            descriptor.$methodsWithOptionalArguments = optionalMethods = {}\n          }\n          optionalMethods[property] = previousProperty;\n        } else if (typeof element === \"function\") {\n          globalObject[previousProperty = property] = element;\n          functions.push(property);\n          init.globalFunctions[property] = element;\n        } else if (element.constructor === Array) {\n          addStubs(globalObject, element, property, true, descriptor, functions);\n        } else {\n          previousProperty = property;\n          var newDesc = {};\n          var previousProp;\n          for (var prop in element) {\n            if (!hasOwnProperty.call(element, prop)) continue;\n            firstChar = prop.substring(0, 1);\n            if (prop === \"static\") {\n              processStatics(init.statics[property] = element[prop]);\n            } else if (firstChar === \"+\") {\n              mangledNames[previousProp] = prop.substring(1);\n              if (element[prop] == 1) element[previousProp].$reflectable = 1;\n            } else if (firstChar === \"@\" && prop !== \"@\") {\n              newDesc[prop.substring(1)][\"@\"] = element[prop];\n            } else if (firstChar === \"*\") {\n              newDesc[previousProp].$defaultValues = element[prop];\n              var optionalMethods = newDesc.$methodsWithOptionalArguments;\n              if (!optionalMethods) {\n                newDesc.$methodsWithOptionalArguments = optionalMethods={}\n              }\n              optionalMethods[prop] = previousProp;\n            } else {\n              var elem = element[prop];\n              if (prop && elem != null && elem.constructor === Array && prop !== \"<>\") {\n                addStubs(newDesc, elem, prop, false, element, []);\n              } else {\n                newDesc[previousProp = prop] = elem;\n              }\n            }\n          }\n          $$[property] = [globalObject, newDesc];\n          classes.push(property);\n        }\n      }\n    }\n  function addStubs(descriptor, array, name, isStatic, originalDescriptor, functions) {\n    var f, funcs = [originalDescriptor[name] = descriptor[name] = f = (function() {\n  var result = array[0];\n  if (result != null && typeof result != \"function\") {\n    throw new Error(\n        name + \": expected value of type 'function' at index \" + (0) +\n        \" but got \" + (typeof result));\n  }\n  return result;\n})()];\n    f.$stubName = name;\n    functions.push(name);\n    for (var index = 0; index < array.length; index += 2) {\n      f = array[index + 1];\n      if (typeof f != \"function\") break;\n      f.$stubName = (function() {\n  var result = array[index + 2];\n  if (result != null && typeof result != \"string\") {\n    throw new Error(\n        name + \": expected value of type 'string' at index \" + (index + 2) +\n        \" but got \" + (typeof result));\n  }\n  return result;\n})();\n      funcs.push(f);\n      if (f.$stubName) {\n        originalDescriptor[f.$stubName] = descriptor[f.$stubName] = f;\n        functions.push(f.$stubName);\n      }\n    }\n    for (var i = 0; i < funcs.length; index++, i++) {\n      funcs[i].$callName = (function() {\n  var result = array[index + 1];\n  if (result != null && typeof result != \"string\") {\n    throw new Error(\n        name + \": expected value of type 'string' at index \" + (index + 1) +\n        \" but got \" + (typeof result));\n  }\n  return result;\n})();\n    }\n    var getterStubName = (function() {\n  var result = array[++index];\n  if (result != null && typeof result != \"string\") {\n    throw new Error(\n        name + \": expected value of type 'string' at index \" + (++index) +\n        \" but got \" + (typeof result));\n  }\n  return result;\n})();\n    array = array.slice(++index);\n    var requiredParameterInfo = (function() {\n  var result = array[0];\n  if (result != null && (typeof result != \"number\" || (result|0) !== result)) {\n    throw new Error(\n        name + \": expected value of type 'int' at index \" + (0) +\n        \" but got \" + (typeof result));\n  }\n  return result;\n})();\n    var requiredParameterCount = requiredParameterInfo >> 1;\n    var isAccessor = (requiredParameterInfo & 1) === 1;\n    var isSetter = requiredParameterInfo === 3;\n    var isGetter = requiredParameterInfo === 1;\n    var optionalParameterInfo = (function() {\n  var result = array[1];\n  if (result != null && (typeof result != \"number\" || (result|0) !== result)) {\n    throw new Error(\n        name + \": expected value of type 'int' at index \" + (1) +\n        \" but got \" + (typeof result));\n  }\n  return result;\n})();\n    var optionalParameterCount = optionalParameterInfo >> 1;\n    var optionalParametersAreNamed = (optionalParameterInfo & 1) === 1;\n    var isIntercepted = requiredParameterCount + optionalParameterCount != funcs[0].length;\n    var functionTypeIndex = (function() {\n  var result = array[2];\n  if (result != null && (typeof result != \"number\" || (result|0) !== result) && typeof result != \"function\") {\n    throw new Error(\n        name + \": expected value of type 'function or int' at index \" + (2) +\n        \" but got \" + (typeof result));\n  }\n  return result;\n})();\n    var isReflectable = array.length > requiredParameterCount + optionalParameterCount + 3;\n    if (getterStubName) {\n      f = tearOff(funcs, array, isStatic, name, isIntercepted);\n      if (isStatic) init.globalFunctions[name] = f;\n      originalDescriptor[getterStubName] = descriptor[getterStubName] = f;\n      funcs.push(f);\n      if (getterStubName) functions.push(getterStubName);\n      f.$stubName = getterStubName;\n      f.$callName = null;\n    }\n    if (isReflectable) {\n      for (var i = 0; i < funcs.length; i++) {\n        funcs[i].$reflectable = 1;\n        funcs[i].$reflectionInfo = array;\n      }\n    }\n    if (isReflectable) {\n      var unmangledNameIndex = optionalParameterCount * 2 + requiredParameterCount + 3;\n      var unmangledName = (function() {\n  var result = array[unmangledNameIndex];\n  if (result != null && typeof result != \"string\") {\n    throw new Error(\n        name + \": expected value of type 'string' at index \" + (unmangledNameIndex) +\n        \" but got \" + (typeof result));\n  }\n  return result;\n})();\n      var reflectionName = unmangledName + \":\" + requiredParameterCount + \":\" + optionalParameterCount;\n      if (isGetter) {\n        reflectionName = unmangledName;\n      } else if (isSetter) {\n        reflectionName = unmangledName + \"=\";\n      }\n      if (isStatic) {\n        init.mangledGlobalNames[name] = reflectionName;\n      } else {\n        init.mangledNames[name] = reflectionName;\n      }\n      funcs[0].$reflectionName = reflectionName;\n      funcs[0].$metadataIndex = unmangledNameIndex + 1;\n      if (optionalParameterCount) descriptor[unmangledName + \"*\"] = funcs[0];\n    }\n  }\n  function tearOffGetterNoCsp(funcs, reflectionInfo, name, isIntercepted) {\n    return isIntercepted\n        ? new Function(\"funcs\", \"reflectionInfo\", \"name\", \"H\", \"c\",\n            \"return function tearOff_\" + name + (functionCounter++)+ \"(x) {\" +\n              \"if (c === null) c = H.closureFromTearOff(\" +\n                  \"this, funcs, reflectionInfo, false, [x], name);\" +\n              \"return new c(this, funcs[0], x, name);\" +\n            \"}\")(funcs, reflectionInfo, name, H, null)\n        : new Function(\"funcs\", \"reflectionInfo\", \"name\", \"H\", \"c\",\n            \"return function tearOff_\" + name + (functionCounter++)+ \"() {\" +\n              \"if (c === null) c = H.closureFromTearOff(\" +\n                  \"this, funcs, reflectionInfo, false, [], name);\" +\n              \"return new c(this, funcs[0], null, name);\" +\n            \"}\")(funcs, reflectionInfo, name, H, null)\n  }\n  function tearOffGetterCsp(funcs, reflectionInfo, name, isIntercepted) {\n    var cache = null;\n    return isIntercepted\n        ? function(x) {\n            if (cache === null) cache = H.closureFromTearOff(this, funcs, reflectionInfo, false, [x], name);\n            return new cache(this, funcs[0], x, name)\n          }\n        : function() {\n            if (cache === null) cache = H.closureFromTearOff(this, funcs, reflectionInfo, false, [], name);\n            return new cache(this, funcs[0], null, name)\n          }\n  }\n  function tearOff(funcs, reflectionInfo, isStatic, name, isIntercepted) {\n    var cache;\n    return isStatic\n        ? function() {\n            if (cache === void 0) cache = H.closureFromTearOff(this, funcs, reflectionInfo, true, [], name).prototype;\n            return cache;\n          }\n        : tearOffGetter(funcs, reflectionInfo, name, isIntercepted);\n  }\n  var functionCounter = 0;\n  var tearOffGetter = (typeof dart_precompiled == \"function\")\n      ? tearOffGetterCsp : tearOffGetterNoCsp;\n  if (!init.libraries) init.libraries = [];\n  if (!init.mangledNames) init.mangledNames = map();\n  if (!init.mangledGlobalNames) init.mangledGlobalNames = map();\n  if (!init.statics) init.statics = map();\n  if (!init.typeInformation) init.typeInformation = map();\n  if (!init.globalFunctions) init.globalFunctions = map();\n  var libraries = init.libraries;\n  var mangledNames = init.mangledNames;\n  var mangledGlobalNames = init.mangledGlobalNames;\n  var hasOwnProperty = Object.prototype.hasOwnProperty;\n  var length = reflectionData.length;\n  for (var i = 0; i < length; i++) {\n    var data = reflectionData[i];\n    var name = data[0];\n    var uri = data[1];\n    var metadata = data[2];\n    var globalObject = data[3];\n    var descriptor = data[4];\n    var isRoot = !!data[5];\n    var fields = descriptor && descriptor[\"\"];\n    var classes = [];\n    var functions = [];\n    processStatics(descriptor);\n    libraries.push([name, uri, classes, functions, metadata, fields, isRoot,\n                    globalObject]);\n  }\n})\n([\n[\"_foreign_helper\", \"dart:_foreign_helper\", , H, {\n  \"\": \"\",\n  JS_CONST: {\n    \"\": \"Object;code\"\n  }\n}],\n[\"_interceptors\", \"dart:_interceptors\", , J, {\n  \"\": \"\",\n  getInterceptor: function(object) {\n    return void 0;\n  },\n  makeDispatchRecord: function(interceptor, proto, extension, indexability) {\n    return {i: interceptor, p: proto, e: extension, x: indexability};\n  },\n  getNativeInterceptor: function(object) {\n    var record, proto, objectProto, interceptor;\n    record = object[init.dispatchPropertyName];\n    if (record == null)\n      if ($.initNativeDispatchFlag == null) {\n        H.initNativeDispatch();\n        record = object[init.dispatchPropertyName];\n      }\n    if (record != null) {\n      proto = record.p;\n      if (false === proto)\n        return record.i;\n      if (true === proto)\n        return object;\n      objectProto = Object.getPrototypeOf(object);\n      if (proto === objectProto)\n        return record.i;\n      if (record.e === objectProto)\n        throw H.wrapException(P.UnimplementedError$(\"Return interceptor for \" + H.S(proto(object, record))));\n    }\n    interceptor = H.lookupAndCacheInterceptor(object);\n    if (interceptor == null)\n      return C.UnknownJavaScriptObject_methods;\n    return interceptor;\n  },\n  Interceptor: {\n    \"\": \"Object;\",\n    $eq: function(receiver, other) {\n      return receiver === other;\n    },\n    get$hashCode: function(receiver) {\n      return H.Primitives_objectHashCode(receiver);\n    },\n    toString$0: function(receiver) {\n      return H.Primitives_objectToString(receiver);\n    },\n    \"%\": \"DOMError|FileError|MediaError|MediaKeyError|Navigator|NavigatorUserMediaError|PositionError|SQLError|SVGAnimatedLength|SVGAnimatedLengthList|SVGAnimatedNumber|SVGAnimatedNumberList\"\n  },\n  JSBool: {\n    \"\": \"bool/Interceptor;\",\n    toString$0: function(receiver) {\n      return String(receiver);\n    },\n    get$hashCode: function(receiver) {\n      return receiver ? 519018 : 218159;\n    },\n    $isbool: true\n  },\n  JSNull: {\n    \"\": \"Interceptor;\",\n    $eq: function(receiver, other) {\n      return null == other;\n    },\n    toString$0: function(receiver) {\n      return \"null\";\n    },\n    get$hashCode: function(receiver) {\n      return 0;\n    }\n  },\n  JavaScriptObject: {\n    \"\": \"Interceptor;\",\n    get$hashCode: function(_) {\n      return 0;\n    }\n  },\n  PlainJavaScriptObject: {\n    \"\": \"JavaScriptObject;\"\n  },\n  UnknownJavaScriptObject: {\n    \"\": \"JavaScriptObject;\"\n  },\n  JSArray: {\n    \"\": \"List/Interceptor;\",\n    forEach$1: function(receiver, f) {\n      return H.IterableMixinWorkaround_forEach(receiver, f);\n    },\n    elementAt$1: function(receiver, index) {\n      if (index < 0 || index >= receiver.length)\n        return H.ioore(receiver, index);\n      return receiver[index];\n    },\n    toString$0: function(receiver) {\n      return H.IterableMixinWorkaround_toStringIterable(receiver, \"[\", \"]\");\n    },\n    get$iterator: function(receiver) {\n      return new H.ListIterator(receiver, receiver.length, 0, null);\n    },\n    get$hashCode: function(receiver) {\n      return H.Primitives_objectHashCode(receiver);\n    },\n    get$length: function(receiver) {\n      return receiver.length;\n    },\n    set$length: function(receiver, newLength) {\n      if (newLength < 0)\n        throw H.wrapException(P.RangeError$value(newLength));\n      if (!!receiver.fixed$length)\n        H.throwExpression(P.UnsupportedError$(\"set length\"));\n      receiver.length = newLength;\n    },\n    $index: function(receiver, index) {\n      if (typeof index !== \"number\" || Math.floor(index) !== index)\n        throw H.wrapException(new P.ArgumentError(index));\n      if (index >= receiver.length || index < 0)\n        throw H.wrapException(P.RangeError$value(index));\n      return receiver[index];\n    },\n    $indexSet: function(receiver, index, value) {\n      if (!!receiver.immutable$list)\n        H.throwExpression(P.UnsupportedError$(\"indexed set\"));\n      if (typeof index !== \"number\" || Math.floor(index) !== index)\n        throw H.wrapException(new P.ArgumentError(index));\n      if (index >= receiver.length || index < 0)\n        throw H.wrapException(P.RangeError$value(index));\n      receiver[index] = value;\n    },\n    $isList: true,\n    $asList: null,\n    $isList: true,\n    static: {JSArray_JSArray$fixed: function($length, $E) {\n        var t1;\n        if (typeof $length !== \"number\" || Math.floor($length) !== $length || $length < 0)\n          throw H.wrapException(P.ArgumentError$(\"Length must be a non-negative integer: \" + H.S($length)));\n        t1 = H.setRuntimeTypeInfo(new Array($length), [$E]);\n        t1.fixed$length = init;\n        return t1;\n      }}\n  },\n  JSNumber: {\n    \"\": \"num/Interceptor;\",\n    remainder$1: function(receiver, b) {\n      return receiver % b;\n    },\n    toInt$0: function(receiver) {\n      var t1;\n      if (receiver >= -2147483648 && receiver <= 2147483647)\n        return receiver | 0;\n      if (isFinite(receiver)) {\n        t1 = receiver < 0 ? Math.ceil(receiver) : Math.floor(receiver);\n        return t1 + 0;\n      }\n      throw H.wrapException(P.UnsupportedError$('' + receiver));\n    },\n    roundToDouble$0: function(receiver) {\n      if (receiver < 0)\n        return -Math.round(-receiver);\n      else\n        return Math.round(receiver);\n    },\n    toString$0: function(receiver) {\n      if (receiver === 0 && 1 / receiver < 0)\n        return \"-0.0\";\n      else\n        return \"\" + receiver;\n    },\n    get$hashCode: function(receiver) {\n      return receiver & 0x1FFFFFFF;\n    },\n    $add: function(receiver, other) {\n      return receiver + other;\n    },\n    $sub: function(receiver, other) {\n      if (typeof other !== \"number\")\n        throw H.wrapException(new P.ArgumentError(other));\n      return receiver - other;\n    },\n    _tdivFast$1: function(receiver, other) {\n      return (receiver | 0) === receiver ? receiver / other | 0 : this.toInt$0(receiver / other);\n    },\n    _shrOtherPositive$1: function(receiver, other) {\n      var t1;\n      if (receiver > 0)\n        t1 = other > 31 ? 0 : receiver >>> other;\n      else {\n        t1 = other > 31 ? 31 : other;\n        t1 = receiver >> t1 >>> 0;\n      }\n      return t1;\n    },\n    $lt: function(receiver, other) {\n      if (typeof other !== \"number\")\n        throw H.wrapException(P.ArgumentError$(other));\n      return receiver < other;\n    },\n    $ge: function(receiver, other) {\n      if (typeof other !== \"number\")\n        throw H.wrapException(P.ArgumentError$(other));\n      return receiver >= other;\n    },\n    $isnum: true,\n    static: {\"\": \"JSNumber__MIN_INT32,JSNumber__MAX_INT32\"}\n  },\n  JSInt: {\n    \"\": \"int/JSNumber;\",\n    $isdouble: true,\n    $isnum: true,\n    $isint: true\n  },\n  JSDouble: {\n    \"\": \"double/JSNumber;\",\n    $isdouble: true,\n    $isnum: true\n  },\n  JSString: {\n    \"\": \"String/Interceptor;\",\n    codeUnitAt$1: function(receiver, index) {\n      if (index < 0)\n        throw H.wrapException(P.RangeError$value(index));\n      if (index >= receiver.length)\n        throw H.wrapException(P.RangeError$value(index));\n      return receiver.charCodeAt(index);\n    },\n    $add: function(receiver, other) {\n      if (typeof other !== \"string\")\n        throw H.wrapException(new P.ArgumentError(other));\n      return receiver + other;\n    },\n    substring$2: function(receiver, startIndex, endIndex) {\n      if (endIndex == null)\n        endIndex = receiver.length;\n      if (typeof endIndex !== \"number\" || Math.floor(endIndex) !== endIndex)\n        H.throwExpression(P.ArgumentError$(endIndex));\n      if (startIndex < 0)\n        throw H.wrapException(P.RangeError$value(startIndex));\n      if (typeof endIndex !== \"number\")\n        return H.iae(endIndex);\n      if (startIndex > endIndex)\n        throw H.wrapException(P.RangeError$value(startIndex));\n      if (endIndex > receiver.length)\n        throw H.wrapException(P.RangeError$value(endIndex));\n      return receiver.substring(startIndex, endIndex);\n    },\n    substring$1: function($receiver, startIndex) {\n      return this.substring$2($receiver, startIndex, null);\n    },\n    get$isEmpty: function(receiver) {\n      return receiver.length === 0;\n    },\n    toString$0: function(receiver) {\n      return receiver;\n    },\n    get$hashCode: function(receiver) {\n      var t1, hash, i;\n      for (t1 = receiver.length, hash = 0, i = 0; i < t1; ++i) {\n        hash = 536870911 & hash + receiver.charCodeAt(i);\n        hash = 536870911 & hash + ((524287 & hash) << 10 >>> 0);\n        hash ^= hash >> 6;\n      }\n      hash = 536870911 & hash + ((67108863 & hash) << 3 >>> 0);\n      hash ^= hash >> 11;\n      return 536870911 & hash + ((16383 & hash) << 15 >>> 0);\n    },\n    get$length: function(receiver) {\n      return receiver.length;\n    },\n    $index: function(receiver, index) {\n      if (typeof index !== \"number\" || Math.floor(index) !== index)\n        throw H.wrapException(new P.ArgumentError(index));\n      if (index >= receiver.length || index < 0)\n        throw H.wrapException(P.RangeError$value(index));\n      return receiver[index];\n    },\n    $isString: true\n  }\n}],\n[\"_isolate_helper\", \"dart:_isolate_helper\", , H, {\n  \"\": \"\",\n  _callInIsolate: function(isolate, $function) {\n    var result = isolate.eval$1($function);\n    init.globalState.topEventLoop.run$0();\n    return result;\n  },\n  startRootIsolate: function(entry) {\n    var t1, t2, rootContext;\n    t1 = new H._Manager(0, 0, 1, null, null, null, null, null, null, null, null, null, entry);\n    t1._Manager$1(entry);\n    init.globalState = t1;\n    if (init.globalState.isWorker === true)\n      return;\n    t1 = init.globalState;\n    t2 = t1.nextIsolateId;\n    t1.nextIsolateId = t2 + 1;\n    rootContext = new H._IsolateContext(t2, P.LinkedHashMap_LinkedHashMap(null, null, null, J.JSInt, H.RawReceivePortImpl), P.LinkedHashSet_LinkedHashSet(null, null, null, J.JSInt), new Isolate());\n    init.globalState.rootContext = rootContext;\n    init.globalState.currentContext = rootContext;\n    t1 = H.getDynamicRuntimeType();\n    t2 = H.buildFunctionType(t1, [t1])._isTest$1(entry);\n    if (t2)\n      rootContext.eval$1(new H.startRootIsolate_closure(entry));\n    else {\n      t1 = H.buildFunctionType(t1, [t1, t1])._isTest$1(entry);\n      if (t1)\n        rootContext.eval$1(new H.startRootIsolate_closure0(entry));\n      else\n        rootContext.eval$1(entry);\n    }\n    init.globalState.topEventLoop.run$0();\n  },\n  IsolateNatives_computeThisScript: function() {\n    var currentScript = init.currentScript;\n    if (currentScript != null)\n      return String(currentScript.src);\n    if (typeof version == \"function\" && typeof os == \"object\" && \"system\" in os)\n      return H.IsolateNatives_computeThisScriptD8();\n    if (typeof version == \"function\" && typeof system == \"function\")\n      return thisFilename();\n    return;\n  },\n  IsolateNatives_computeThisScriptD8: function() {\n    var stack, matches;\n    stack = new Error().stack;\n    if (stack == null) {\n      stack = (function() {try { throw new Error() } catch(e) { return e.stack }})();\n      if (stack == null)\n        throw H.wrapException(P.UnsupportedError$(\"No stack trace\"));\n    }\n    matches = stack.match(new RegExp(\"^ *at [^(]*\\\\((.*):[0-9]*:[0-9]*\\\\)$\", \"m\"));\n    if (matches != null)\n      return matches[1];\n    matches = stack.match(new RegExp(\"^[^@]*@(.*):[0-9]*$\", \"m\"));\n    if (matches != null)\n      return matches[1];\n    throw H.wrapException(P.UnsupportedError$(\"Cannot extract URI from \\\"\" + stack + \"\\\"\"));\n  },\n  IsolateNatives__processWorkerMessage: function(sender, e) {\n    var msg, t1, functionName, entryPoint, args, message, isSpawnUri, replyTo, t2, context, uri, t3, t4, t5, worker, t6, workerId;\n    msg = H._deserializeMessage(e.data);\n    t1 = J.getInterceptor$asx(msg);\n    switch (t1.$index(msg, \"command\")) {\n      case \"start\":\n        init.globalState.currentManagerId = t1.$index(msg, \"id\");\n        functionName = t1.$index(msg, \"functionName\");\n        entryPoint = functionName == null ? init.globalState.entry : init.globalFunctions[functionName]();\n        args = t1.$index(msg, \"args\");\n        message = H._deserializeMessage(t1.$index(msg, \"msg\"));\n        isSpawnUri = t1.$index(msg, \"isSpawnUri\");\n        replyTo = H._deserializeMessage(t1.$index(msg, \"replyTo\"));\n        t1 = init.globalState;\n        t2 = t1.nextIsolateId;\n        t1.nextIsolateId = t2 + 1;\n        context = new H._IsolateContext(t2, P.LinkedHashMap_LinkedHashMap(null, null, null, J.JSInt, H.RawReceivePortImpl), P.LinkedHashSet_LinkedHashSet(null, null, null, J.JSInt), new Isolate());\n        init.globalState.topEventLoop.events._add$1(new H._IsolateEvent(context, new H.IsolateNatives__processWorkerMessage_closure(entryPoint, args, message, isSpawnUri, replyTo), \"worker-start\"));\n        init.globalState.currentContext = context;\n        init.globalState.topEventLoop.run$0();\n        break;\n      case \"spawn-worker\":\n        t2 = t1.$index(msg, \"functionName\");\n        uri = t1.$index(msg, \"uri\");\n        t3 = t1.$index(msg, \"args\");\n        t4 = t1.$index(msg, \"msg\");\n        t5 = t1.$index(msg, \"isSpawnUri\");\n        t1 = t1.$index(msg, \"replyPort\");\n        if (uri == null)\n          uri = $.get$IsolateNatives_thisScript();\n        worker = new Worker(uri);\n        worker.onmessage = function(e) { H.IsolateNatives__processWorkerMessage(worker, e); };\n        t6 = init.globalState;\n        workerId = t6.nextManagerId;\n        t6.nextManagerId = workerId + 1;\n        t6 = $.get$IsolateNatives_workerIds();\n        t6.$indexSet(t6, worker, workerId);\n        t6 = init.globalState.managers;\n        t6.$indexSet(t6, workerId, worker);\n        worker.postMessage(H._serializeMessage(H.fillLiteralMap([\"command\", \"start\", \"id\", workerId, \"replyTo\", H._serializeMessage(t1), \"args\", t3, \"msg\", H._serializeMessage(t4), \"isSpawnUri\", t5, \"functionName\", t2], P.LinkedHashMap_LinkedHashMap(null, null, null, null, null))));\n        break;\n      case \"message\":\n        if (t1.$index(msg, \"port\") != null)\n          t1.$index(msg, \"port\").send$1(t1.$index(msg, \"msg\"));\n        init.globalState.topEventLoop.run$0();\n        break;\n      case \"close\":\n        t1 = init.globalState.managers;\n        t2 = $.get$IsolateNatives_workerIds();\n        t1.remove$1(t1, t2.$index(t2, sender));\n        sender.terminate();\n        init.globalState.topEventLoop.run$0();\n        break;\n      case \"log\":\n        H.IsolateNatives__log(t1.$index(msg, \"msg\"));\n        break;\n      case \"print\":\n        if (init.globalState.isWorker === true) {\n          t1 = init.globalState.mainManager;\n          t2 = H._serializeMessage(H.fillLiteralMap([\"command\", \"print\", \"msg\", msg], P.LinkedHashMap_LinkedHashMap(null, null, null, null, null)));\n          t1.toString;\n          self.postMessage(t2);\n        } else\n          P.print(t1.$index(msg, \"msg\"));\n        break;\n      case \"error\":\n        throw H.wrapException(t1.$index(msg, \"msg\"));\n      default:\n    }\n  },\n  IsolateNatives__log: function(msg) {\n    var trace, t1, t2, exception;\n    if (init.globalState.isWorker === true) {\n      t1 = init.globalState.mainManager;\n      t2 = H._serializeMessage(H.fillLiteralMap([\"command\", \"log\", \"msg\", msg], P.LinkedHashMap_LinkedHashMap(null, null, null, null, null)));\n      t1.toString;\n      self.postMessage(t2);\n    } else\n      try {\n        $.get$globalThis().console.log(msg);\n      } catch (exception) {\n        H.unwrapException(exception);\n        trace = new H._StackTrace(exception, null);\n        throw H.wrapException(P.Exception_Exception(trace));\n      }\n\n  },\n  _serializeMessage: function(message) {\n    var t1;\n    if (init.globalState.supportsWorkers === true) {\n      t1 = new H._JsSerializer(0, new H._MessageTraverserVisitedMap());\n      t1._visited = new H._JsVisitedMap(null);\n      return t1.traverse$1(message);\n    } else {\n      t1 = new H._JsCopier(new H._MessageTraverserVisitedMap());\n      t1._visited = new H._JsVisitedMap(null);\n      return t1.traverse$1(message);\n    }\n  },\n  _deserializeMessage: function(message) {\n    if (init.globalState.supportsWorkers === true)\n      return new H._JsDeserializer(null).deserialize$1(message);\n    else\n      return message;\n  },\n  _MessageTraverser_isPrimitive: function(x) {\n    return x == null || typeof x === \"string\" || typeof x === \"number\" || typeof x === \"boolean\";\n  },\n  _Deserializer_isPrimitive: function(x) {\n    return x == null || typeof x === \"string\" || typeof x === \"number\" || typeof x === \"boolean\";\n  },\n  startRootIsolate_closure: {\n    \"\": \"Closure:8;entry_0\",\n    call$0: function() {\n      this.entry_0.call$1([]);\n    }\n  },\n  startRootIsolate_closure0: {\n    \"\": \"Closure:8;entry_1\",\n    call$0: function() {\n      this.entry_1.call$2([], null);\n    }\n  },\n  _Manager: {\n    \"\": \"Object;nextIsolateId,currentManagerId,nextManagerId,currentContext,rootContext,topEventLoop,fromCommandLine,isWorker,supportsWorkers,isolates,mainManager,managers,entry\",\n    _Manager$1: function(entry) {\n      var t1, t2, t3, $function;\n      t1 = $.get$globalWindow() == null;\n      t2 = $.get$globalWorker();\n      t3 = t1 && $.get$globalPostMessageDefined() === true;\n      this.isWorker = t3;\n      if (!t3)\n        t2 = t2 != null && $.get$IsolateNatives_thisScript() != null;\n      else\n        t2 = true;\n      this.supportsWorkers = t2;\n      this.fromCommandLine = t1 && !t3;\n      t2 = H._IsolateEvent;\n      t3 = H.setRuntimeTypeInfo(new P.ListQueue(null, 0, 0, 0), [t2]);\n      t3.ListQueue$1(null, t2);\n      this.topEventLoop = new H._EventLoop(t3, 0);\n      this.isolates = P.LinkedHashMap_LinkedHashMap(null, null, null, J.JSInt, H._IsolateContext);\n      this.managers = P.LinkedHashMap_LinkedHashMap(null, null, null, J.JSInt, null);\n      if (this.isWorker === true) {\n        t1 = new H._MainManagerStub();\n        this.mainManager = t1;\n        $function = function (e) { H.IsolateNatives__processWorkerMessage(t1, e); };\n        $.get$globalThis().onmessage = $function;\n        $.get$globalThis().dartPrint = function (object) {};\n      }\n    }\n  },\n  _IsolateContext: {\n    \"\": \"Object;id,ports,weakPorts,isolateStatics<\",\n    eval$1: function(code) {\n      var old, result;\n      old = init.globalState.currentContext;\n      init.globalState.currentContext = this;\n      $ = this.isolateStatics;\n      result = null;\n      try {\n        result = code.call$0();\n      } finally {\n        init.globalState.currentContext = old;\n        if (old != null)\n          $ = old.get$isolateStatics();\n      }\n      return result;\n    },\n    lookup$1: function(portId) {\n      var t1 = this.ports;\n      return t1.$index(t1, portId);\n    },\n    register$2: function(_, portId, port) {\n      var t1 = this.ports;\n      if (t1.containsKey$1(portId))\n        throw H.wrapException(P.Exception_Exception(\"Registry: ports must be registered only once.\"));\n      t1.$indexSet(t1, portId, port);\n      this._updateGlobalState$0();\n    },\n    _updateGlobalState$0: function() {\n      var t1, t2;\n      t1 = this.id;\n      if (this.ports._collection$_length - this.weakPorts._collection$_length > 0) {\n        t2 = init.globalState.isolates;\n        t2.$indexSet(t2, t1, this);\n      } else {\n        t2 = init.globalState.isolates;\n        t2.remove$1(t2, t1);\n      }\n    }\n  },\n  _EventLoop: {\n    \"\": \"Object;events,activeTimerCount\",\n    dequeue$0: function() {\n      var t1 = this.events;\n      if (t1._head === t1._tail)\n        return;\n      return t1.removeFirst$0();\n    },\n    runIteration$0: function() {\n      var $event, t1, t2;\n      $event = this.dequeue$0();\n      if ($event == null) {\n        if (init.globalState.rootContext != null && init.globalState.isolates.containsKey$1(init.globalState.rootContext.id) && init.globalState.fromCommandLine === true && init.globalState.rootContext.ports._collection$_length === 0)\n          H.throwExpression(P.Exception_Exception(\"Program exited with open ReceivePorts.\"));\n        t1 = init.globalState;\n        if (t1.isWorker === true && t1.isolates._collection$_length === 0 && t1.topEventLoop.activeTimerCount === 0) {\n          t1 = t1.mainManager;\n          t2 = H._serializeMessage(H.fillLiteralMap([\"command\", \"close\"], P.LinkedHashMap_LinkedHashMap(null, null, null, null, null)));\n          t1.toString;\n          self.postMessage(t2);\n        }\n        return false;\n      }\n      $event.process$0();\n      return true;\n    },\n    _runHelper$0: function() {\n      if ($.get$globalWindow() != null)\n        new H._EventLoop__runHelper_next(this).call$0();\n      else\n        for (; this.runIteration$0();)\n          ;\n    },\n    run$0: function() {\n      var e, trace, exception, t1, t2;\n      if (init.globalState.isWorker !== true)\n        this._runHelper$0();\n      else\n        try {\n          this._runHelper$0();\n        } catch (exception) {\n          t1 = H.unwrapException(exception);\n          e = t1;\n          trace = new H._StackTrace(exception, null);\n          t1 = init.globalState.mainManager;\n          t2 = H._serializeMessage(H.fillLiteralMap([\"command\", \"error\", \"msg\", H.S(e) + \"\\n\" + H.S(trace)], P.LinkedHashMap_LinkedHashMap(null, null, null, null, null)));\n          t1.toString;\n          self.postMessage(t2);\n        }\n\n    }\n  },\n  _EventLoop__runHelper_next: {\n    \"\": \"Closure:0;this_0\",\n    call$0: function() {\n      if (!this.this_0.runIteration$0())\n        return;\n      P.Timer_Timer(C.Duration_0, this);\n    }\n  },\n  _IsolateEvent: {\n    \"\": \"Object;isolate,fn,message\",\n    process$0: function() {\n      this.isolate.eval$1(this.fn);\n    }\n  },\n  _MainManagerStub: {\n    \"\": \"Object;\"\n  },\n  IsolateNatives__processWorkerMessage_closure: {\n    \"\": \"Closure:8;entryPoint_0,args_1,message_2,isSpawnUri_3,replyTo_4\",\n    call$0: function() {\n      var t1, t2, t3, t4, t5, t6, t7;\n      t1 = this.entryPoint_0;\n      t2 = this.args_1;\n      t3 = this.message_2;\n      t4 = init.globalState.currentContext.id;\n      $.Primitives_mirrorFunctionCacheName = $.Primitives_mirrorFunctionCacheName + (\"_\" + t4);\n      $.Primitives_mirrorInvokeCacheName = $.Primitives_mirrorInvokeCacheName + (\"_\" + t4);\n      t4 = $.RawReceivePortImpl__nextFreeId;\n      $.RawReceivePortImpl__nextFreeId = t4 + 1;\n      t5 = new H.RawReceivePortImpl(t4, null, false);\n      t6 = init.globalState.currentContext;\n      t7 = t6.weakPorts;\n      t7.add$1(t7, t4);\n      t6.register$2(t6, t4, t5);\n      t4 = new H.ReceivePortImpl(t5, null);\n      t4.ReceivePortImpl$fromRawReceivePort$1(t5);\n      $.controlPort = t4;\n      this.replyTo_4.send$1([\"spawned\", new H._NativeJsSendPort(t5, init.globalState.currentContext.id)]);\n      if (this.isSpawnUri_3 !== true)\n        t1.call$1(t3);\n      else {\n        t4 = H.getDynamicRuntimeType();\n        t5 = H.buildFunctionType(t4, [t4, t4])._isTest$1(t1);\n        if (t5)\n          t1.call$2(t2, t3);\n        else {\n          t3 = H.buildFunctionType(t4, [t4])._isTest$1(t1);\n          if (t3)\n            t1.call$1(t2);\n          else\n            t1.call$0();\n        }\n      }\n    }\n  },\n  _BaseSendPort: {\n    \"\": \"Object;\",\n    $isSendPort: true\n  },\n  _NativeJsSendPort: {\n    \"\": \"_BaseSendPort;_receivePort,_isolateId\",\n    send$1: function(message) {\n      var t1, t2, t3, isolate, shouldSerialize;\n      t1 = {};\n      t2 = init.globalState.isolates;\n      t3 = this._isolateId;\n      isolate = t2.$index(t2, t3);\n      if (isolate == null)\n        return;\n      if (this._receivePort.get$_isClosed())\n        return;\n      shouldSerialize = init.globalState.currentContext != null && init.globalState.currentContext.id !== t3;\n      t1.msg_0 = message;\n      if (shouldSerialize)\n        t1.msg_0 = H._serializeMessage(message);\n      t2 = init.globalState.topEventLoop;\n      t3 = \"receive \" + H.S(message);\n      t2.events._add$1(new H._IsolateEvent(isolate, new H._NativeJsSendPort_send_closure(t1, this, shouldSerialize), t3));\n    },\n    $eq: function(_, other) {\n      var t1;\n      if (other == null)\n        return false;\n      t1 = J.getInterceptor(other);\n      return typeof other === \"object\" && other !== null && !!t1.$is_NativeJsSendPort && J.$eq(this._receivePort, other._receivePort);\n    },\n    get$hashCode: function(_) {\n      return this._receivePort.get$_id();\n    },\n    $is_NativeJsSendPort: true,\n    $isSendPort: true\n  },\n  _NativeJsSendPort_send_closure: {\n    \"\": \"Closure:8;box_0,this_1,shouldSerialize_2\",\n    call$0: function() {\n      var t1, t2;\n      t1 = this.this_1._receivePort;\n      if (!t1.get$_isClosed()) {\n        if (this.shouldSerialize_2) {\n          t2 = this.box_0;\n          t2.msg_0 = H._deserializeMessage(t2.msg_0);\n        }\n        t1.__isolate_helper$_add$1(this.box_0.msg_0);\n      }\n    }\n  },\n  _WorkerSendPort: {\n    \"\": \"_BaseSendPort;_workerId,_receivePortId,_isolateId\",\n    send$1: function(message) {\n      var workerMessage, t1, manager;\n      workerMessage = H._serializeMessage(H.fillLiteralMap([\"command\", \"message\", \"port\", this, \"msg\", message], P.LinkedHashMap_LinkedHashMap(null, null, null, null, null)));\n      if (init.globalState.isWorker === true) {\n        init.globalState.mainManager.toString;\n        self.postMessage(workerMessage);\n      } else {\n        t1 = init.globalState.managers;\n        manager = t1.$index(t1, this._workerId);\n        if (manager != null)\n          manager.postMessage(workerMessage);\n      }\n    },\n    $eq: function(_, other) {\n      var t1;\n      if (other == null)\n        return false;\n      t1 = J.getInterceptor(other);\n      return typeof other === \"object\" && other !== null && !!t1.$is_WorkerSendPort && J.$eq(this._workerId, other._workerId) && J.$eq(this._isolateId, other._isolateId) && J.$eq(this._receivePortId, other._receivePortId);\n    },\n    get$hashCode: function(_) {\n      var t1, t2, t3;\n      t1 = this._workerId;\n      if (typeof t1 !== \"number\")\n        return t1.$shl();\n      t2 = this._isolateId;\n      if (typeof t2 !== \"number\")\n        return t2.$shl();\n      t3 = this._receivePortId;\n      if (typeof t3 !== \"number\")\n        return H.iae(t3);\n      return (t1 << 16 ^ t2 << 8 ^ t3) >>> 0;\n    },\n    $is_WorkerSendPort: true,\n    $isSendPort: true\n  },\n  RawReceivePortImpl: {\n    \"\": \"Object;_id<,_handler,_isClosed<\",\n    _handler$1: function(arg0) {\n      return this._handler.call$1(arg0);\n    },\n    close$0: function(_) {\n      var t1, t2;\n      if (this._isClosed)\n        return;\n      this._isClosed = true;\n      this._handler = null;\n      t1 = init.globalState.currentContext;\n      t2 = t1.ports;\n      t2.remove$1(t2, this._id);\n      t1._updateGlobalState$0();\n    },\n    __isolate_helper$_add$1: function(dataEvent) {\n      if (this._isClosed)\n        return;\n      this._handler$1(dataEvent);\n    },\n    static: {\"\": \"RawReceivePortImpl__nextFreeId\"}\n  },\n  ReceivePortImpl: {\n    \"\": \"Stream;_rawPort,_controller\",\n    listen$4$cancelOnError$onDone$onError: function(onData, cancelOnError, onDone, onError) {\n      var t1 = this._controller;\n      t1.toString;\n      return H.setRuntimeTypeInfo(new P._ControllerStream(t1), [null]).listen$4$cancelOnError$onDone$onError(onData, cancelOnError, onDone, onError);\n    },\n    close$0: [function(_) {\n      var t1 = this._rawPort;\n      t1.close$0(t1);\n      t1 = this._controller;\n      t1.close$0(t1);\n    }, \"call$0\", \"get$close\", 0, 0, 0],\n    ReceivePortImpl$fromRawReceivePort$1: function(_rawPort) {\n      var t1 = P.StreamController_StreamController(this.get$close(this), null, null, null, true, null);\n      this._controller = t1;\n      this._rawPort._handler = t1.get$add(t1);\n    }\n  },\n  _JsSerializer: {\n    \"\": \"_Serializer;_nextFreeRefId,_visited\",\n    visitSendPort$1: function(x) {\n      if (!!x.$is_NativeJsSendPort)\n        return [\"sendport\", init.globalState.currentManagerId, x._isolateId, x._receivePort.get$_id()];\n      if (!!x.$is_WorkerSendPort)\n        return [\"sendport\", x._workerId, x._isolateId, x._receivePortId];\n      throw H.wrapException(\"Illegal underlying port \" + H.S(x));\n    }\n  },\n  _JsCopier: {\n    \"\": \"_Copier;_visited\",\n    visitSendPort$1: function(x) {\n      if (!!x.$is_NativeJsSendPort)\n        return new H._NativeJsSendPort(x._receivePort, x._isolateId);\n      if (!!x.$is_WorkerSendPort)\n        return new H._WorkerSendPort(x._workerId, x._receivePortId, x._isolateId);\n      throw H.wrapException(\"Illegal underlying port \" + H.S(x));\n    }\n  },\n  _JsDeserializer: {\n    \"\": \"_Deserializer;_deserialized\",\n    deserializeSendPort$1: function(list) {\n      var t1, managerId, isolateId, receivePortId, isolate, receivePort;\n      t1 = J.getInterceptor$asx(list);\n      managerId = t1.$index(list, 1);\n      isolateId = t1.$index(list, 2);\n      receivePortId = t1.$index(list, 3);\n      if (J.$eq(managerId, init.globalState.currentManagerId)) {\n        t1 = init.globalState.isolates;\n        isolate = t1.$index(t1, isolateId);\n        if (isolate == null)\n          return;\n        receivePort = isolate.lookup$1(receivePortId);\n        if (receivePort == null)\n          return;\n        return new H._NativeJsSendPort(receivePort, isolateId);\n      } else\n        return new H._WorkerSendPort(managerId, receivePortId, isolateId);\n    }\n  },\n  _JsVisitedMap: {\n    \"\": \"Object;tagged\",\n    $index: function(_, object) {\n      return object.__MessageTraverser__attached_info__;\n    },\n    $indexSet: function(_, object, info) {\n      this.tagged.push(object);\n      object.__MessageTraverser__attached_info__ = info;\n    },\n    reset$0: function(_) {\n      this.tagged = [];\n    },\n    cleanup$0: function() {\n      var $length, i, t1;\n      for ($length = this.tagged.length, i = 0; i < $length; ++i) {\n        t1 = this.tagged;\n        if (i >= t1.length)\n          return H.ioore(t1, i);\n        t1[i].__MessageTraverser__attached_info__ = null;\n      }\n      this.tagged = null;\n    }\n  },\n  _MessageTraverserVisitedMap: {\n    \"\": \"Object;\",\n    $index: function(_, object) {\n      return;\n    },\n    $indexSet: function(_, object, info) {\n    },\n    reset$0: function(_) {\n    },\n    cleanup$0: function() {\n      return;\n    }\n  },\n  _MessageTraverser: {\n    \"\": \"Object;\",\n    traverse$1: function(x) {\n      var result, t1;\n      if (H._MessageTraverser_isPrimitive(x))\n        return this.visitPrimitive$1(x);\n      t1 = this._visited;\n      t1.reset$0(t1);\n      result = null;\n      try {\n        result = this._dispatch$1(x);\n      } finally {\n        this._visited.cleanup$0();\n      }\n      return result;\n    },\n    _dispatch$1: function(x) {\n      var t1;\n      if (x == null || typeof x === \"string\" || typeof x === \"number\" || typeof x === \"boolean\")\n        return this.visitPrimitive$1(x);\n      t1 = J.getInterceptor(x);\n      if (typeof x === \"object\" && x !== null && (x.constructor === Array || !!t1.$isList))\n        return this.visitList$1(x);\n      if (typeof x === \"object\" && x !== null && !!t1.$isMap)\n        return this.visitMap$1(x);\n      if (typeof x === \"object\" && x !== null && !!t1.$isSendPort)\n        return this.visitSendPort$1(x);\n      return this.visitObject$1(x);\n    },\n    visitObject$1: function(x) {\n      throw H.wrapException(\"Message serialization: Illegal value \" + H.S(x) + \" passed\");\n    }\n  },\n  _Copier: {\n    \"\": \"_MessageTraverser;\",\n    visitPrimitive$1: function(x) {\n      return x;\n    },\n    visitList$1: function(list) {\n      var t1, copy, len, t2, i;\n      t1 = this._visited;\n      copy = t1.$index(t1, list);\n      if (copy != null)\n        return copy;\n      t1 = J.getInterceptor$asx(list);\n      len = t1.get$length(list);\n      copy = Array(len);\n      copy.fixed$length = init;\n      t2 = this._visited;\n      t2.$indexSet(t2, list, copy);\n      for (i = 0; i < len; ++i)\n        copy[i] = this._dispatch$1(t1.$index(list, i));\n      return copy;\n    },\n    visitMap$1: function(map) {\n      var t1, t2, copy;\n      t1 = {};\n      t2 = this._visited;\n      copy = t2.$index(t2, map);\n      t1.copy_0 = copy;\n      if (copy != null)\n        return copy;\n      copy = P.LinkedHashMap_LinkedHashMap(null, null, null, null, null);\n      t1.copy_0 = copy;\n      t2 = this._visited;\n      t2.$indexSet(t2, map, copy);\n      map.forEach$1(map, new H._Copier_visitMap_closure(t1, this));\n      return t1.copy_0;\n    },\n    visitSendPort$1: function(x) {\n      return H.throwExpression(P.UnimplementedError$(null));\n    }\n  },\n  _Copier_visitMap_closure: {\n    \"\": \"Closure:9;box_0,this_1\",\n    call$2: function(key, val) {\n      var t1 = this.this_1;\n      J.$indexSet$ax(this.box_0.copy_0, t1._dispatch$1(key), t1._dispatch$1(val));\n    }\n  },\n  _Serializer: {\n    \"\": \"_MessageTraverser;\",\n    visitPrimitive$1: function(x) {\n      return x;\n    },\n    visitList$1: function(list) {\n      var t1, copyId, id;\n      t1 = this._visited;\n      copyId = t1.$index(t1, list);\n      if (copyId != null)\n        return [\"ref\", copyId];\n      id = this._nextFreeRefId;\n      this._nextFreeRefId = id + 1;\n      t1 = this._visited;\n      t1.$indexSet(t1, list, id);\n      return [\"list\", id, this._serializeList$1(list)];\n    },\n    visitMap$1: function(map) {\n      var t1, copyId, id, keys;\n      t1 = this._visited;\n      copyId = t1.$index(t1, map);\n      if (copyId != null)\n        return [\"ref\", copyId];\n      id = this._nextFreeRefId;\n      this._nextFreeRefId = id + 1;\n      t1 = this._visited;\n      t1.$indexSet(t1, map, id);\n      t1 = map.get$keys();\n      keys = this._serializeList$1(P.List_List$from(t1, true, H.getRuntimeTypeArgument(t1, \"IterableBase\", 0)));\n      t1 = map.get$values(map);\n      return [\"map\", id, keys, this._serializeList$1(P.List_List$from(t1, true, H.getRuntimeTypeArgument(t1, \"IterableBase\", 0)))];\n    },\n    _serializeList$1: function(list) {\n      var t1, len, result, i, t2;\n      t1 = J.getInterceptor$asx(list);\n      len = t1.get$length(list);\n      result = [];\n      C.JSArray_methods.set$length(result, len);\n      for (i = 0; i < len; ++i) {\n        t2 = this._dispatch$1(t1.$index(list, i));\n        if (i >= result.length)\n          return H.ioore(result, i);\n        result[i] = t2;\n      }\n      return result;\n    },\n    visitSendPort$1: function(x) {\n      return H.throwExpression(P.UnimplementedError$(null));\n    }\n  },\n  _Deserializer: {\n    \"\": \"Object;\",\n    deserialize$1: function(x) {\n      if (H._Deserializer_isPrimitive(x))\n        return x;\n      this._deserialized = P.HashMap_HashMap(null, null, null, null, null);\n      return this._deserializeHelper$1(x);\n    },\n    _deserializeHelper$1: function(x) {\n      var t1, id;\n      if (x == null || typeof x === \"string\" || typeof x === \"number\" || typeof x === \"boolean\")\n        return x;\n      t1 = J.getInterceptor$asx(x);\n      switch (t1.$index(x, 0)) {\n        case \"ref\":\n          id = t1.$index(x, 1);\n          t1 = this._deserialized;\n          return t1.$index(t1, id);\n        case \"list\":\n          return this._deserializeList$1(x);\n        case \"map\":\n          return this._deserializeMap$1(x);\n        case \"sendport\":\n          return this.deserializeSendPort$1(x);\n        default:\n          return this.deserializeObject$1(x);\n      }\n    },\n    _deserializeList$1: function(x) {\n      var t1, id, dartList, len, i;\n      t1 = J.getInterceptor$asx(x);\n      id = t1.$index(x, 1);\n      dartList = t1.$index(x, 2);\n      t1 = this._deserialized;\n      t1.$indexSet(t1, id, dartList);\n      t1 = J.getInterceptor$asx(dartList);\n      len = t1.get$length(dartList);\n      if (typeof len !== \"number\")\n        return H.iae(len);\n      i = 0;\n      for (; i < len; ++i)\n        t1.$indexSet(dartList, i, this._deserializeHelper$1(t1.$index(dartList, i)));\n      return dartList;\n    },\n    _deserializeMap$1: function(x) {\n      var result, t1, id, t2, keys, values, len, i;\n      result = P.LinkedHashMap_LinkedHashMap(null, null, null, null, null);\n      t1 = J.getInterceptor$asx(x);\n      id = t1.$index(x, 1);\n      t2 = this._deserialized;\n      t2.$indexSet(t2, id, result);\n      keys = t1.$index(x, 2);\n      values = t1.$index(x, 3);\n      t1 = J.getInterceptor$asx(keys);\n      len = t1.get$length(keys);\n      if (typeof len !== \"number\")\n        return H.iae(len);\n      t2 = J.getInterceptor$asx(values);\n      i = 0;\n      for (; i < len; ++i)\n        result.$indexSet(result, this._deserializeHelper$1(t1.$index(keys, i)), this._deserializeHelper$1(t2.$index(values, i)));\n      return result;\n    },\n    deserializeObject$1: function(x) {\n      throw H.wrapException(\"Unexpected serialized object\");\n    }\n  },\n  TimerImpl: {\n    \"\": \"Object;_once,_inEventLoop,_handle\",\n    TimerImpl$2: function(milliseconds, callback) {\n      var t1, t2;\n      if (milliseconds === 0)\n        t1 = $.get$globalThis().setTimeout == null || init.globalState.isWorker === true;\n      else\n        t1 = false;\n      if (t1) {\n        this._handle = 1;\n        t1 = init.globalState.topEventLoop;\n        t2 = init.globalState.currentContext;\n        t1.events._add$1(new H._IsolateEvent(t2, new H.TimerImpl_internalCallback(this, callback), \"timer\"));\n        this._inEventLoop = true;\n      } else {\n        t1 = $.get$globalThis();\n        if (t1.setTimeout != null) {\n          t2 = init.globalState.topEventLoop;\n          t2.activeTimerCount = t2.activeTimerCount + 1;\n          this._handle = t1.setTimeout(H.convertDartClosureToJS(new H.TimerImpl_internalCallback0(this, callback), 0), milliseconds);\n        } else\n          throw H.wrapException(P.UnsupportedError$(\"Timer greater than 0.\"));\n      }\n    },\n    static: {TimerImpl$: function(milliseconds, callback) {\n        var t1 = new H.TimerImpl(true, false, null);\n        t1.TimerImpl$2(milliseconds, callback);\n        return t1;\n      }}\n  },\n  TimerImpl_internalCallback: {\n    \"\": \"Closure:0;this_0,callback_1\",\n    call$0: function() {\n      this.this_0._handle = null;\n      this.callback_1.call$0();\n    }\n  },\n  TimerImpl_internalCallback0: {\n    \"\": \"Closure:0;this_2,callback_3\",\n    call$0: function() {\n      this.this_2._handle = null;\n      var t1 = init.globalState.topEventLoop;\n      t1.activeTimerCount = t1.activeTimerCount - 1;\n      this.callback_3.call$0();\n    }\n  }\n}],\n[\"_js_helper\", \"dart:_js_helper\", , H, {\n  \"\": \"\",\n  isJsIndexable: function(object, record) {\n    var result, t1;\n    if (record != null) {\n      result = record.x;\n      if (result != null)\n        return result;\n    }\n    t1 = J.getInterceptor(object);\n    return typeof object === \"object\" && object !== null && !!t1.$isJavaScriptIndexingBehavior;\n  },\n  S: function(value) {\n    var res;\n    if (typeof value === \"string\")\n      return value;\n    if (typeof value === \"number\") {\n      if (value !== 0)\n        return \"\" + value;\n    } else if (true === value)\n      return \"true\";\n    else if (false === value)\n      return \"false\";\n    else if (value == null)\n      return \"null\";\n    res = J.toString$0(value);\n    if (typeof res !== \"string\")\n      throw H.wrapException(P.ArgumentError$(value));\n    return res;\n  },\n  Primitives_objectHashCode: function(object) {\n    var hash = object.$identityHash;\n    if (hash == null) {\n      hash = Math.random() * 0x3fffffff | 0;\n      object.$identityHash = hash;\n    }\n    return hash;\n  },\n  Primitives_objectTypeName: function(object) {\n    var $name, decompiled;\n    $name = C.JS_CONST_IX5(J.getInterceptor(object));\n    if ($name === \"Object\") {\n      decompiled = String(object.constructor).match(/^\\s*function\\s*(\\S*)\\s*\\(/)[1];\n      if (typeof decompiled === \"string\")\n        $name = decompiled;\n    }\n    if (J.getInterceptor$s($name).codeUnitAt$1($name, 0) === 36)\n      $name = C.JSString_methods.substring$1($name, 1);\n    return $name + H.joinArguments(H.getRuntimeTypeInfo(object), 0, null);\n  },\n  Primitives_objectToString: function(object) {\n    return \"Instance of '\" + H.Primitives_objectTypeName(object) + \"'\";\n  },\n  Primitives__fromCharCodeApply: function(array) {\n    var end, t1, result, i, subarray, t2;\n    end = array.length;\n    for (t1 = end <= 500, result = \"\", i = 0; i < end; i += 500) {\n      if (t1)\n        subarray = array;\n      else {\n        t2 = i + 500;\n        t2 = t2 < end ? t2 : end;\n        subarray = array.slice(i, t2);\n      }\n      result += String.fromCharCode.apply(null, subarray);\n    }\n    return result;\n  },\n  Primitives_stringFromCodePoints: function(codePoints) {\n    var a, t1, i;\n    a = [];\n    a.$builtinTypeInfo = [J.JSInt];\n    for (t1 = new H.ListIterator(codePoints, codePoints.length, 0, null); t1.moveNext$0();) {\n      i = t1._dev$_current;\n      if (typeof i !== \"number\" || Math.floor(i) !== i)\n        throw H.wrapException(P.ArgumentError$(i));\n      if (i <= 65535)\n        a.push(i);\n      else if (i <= 1114111) {\n        a.push(55296 + (C.JSInt_methods._shrOtherPositive$1(i - 65536, 10) & 1023));\n        a.push(56320 + (i & 1023));\n      } else\n        throw H.wrapException(P.ArgumentError$(i));\n    }\n    return H.Primitives__fromCharCodeApply(a);\n  },\n  Primitives_stringFromCharCodes: function(charCodes) {\n    var t1, i;\n    for (t1 = new H.ListIterator(charCodes, charCodes.length, 0, null); t1.moveNext$0();) {\n      i = t1._dev$_current;\n      if (typeof i !== \"number\" || Math.floor(i) !== i)\n        throw H.wrapException(P.ArgumentError$(i));\n      if (i < 0)\n        throw H.wrapException(P.ArgumentError$(i));\n      if (i > 65535)\n        return H.Primitives_stringFromCodePoints(charCodes);\n    }\n    return H.Primitives__fromCharCodeApply(charCodes);\n  },\n  Primitives_lazyAsJsDate: function(receiver) {\n    if (receiver.date === void 0)\n      receiver.date = new Date(receiver.millisecondsSinceEpoch);\n    return receiver.date;\n  },\n  Primitives_getHours: function(receiver) {\n    return receiver.isUtc ? H.Primitives_lazyAsJsDate(receiver).getUTCHours() + 0 : H.Primitives_lazyAsJsDate(receiver).getHours() + 0;\n  },\n  Primitives_getMinutes: function(receiver) {\n    return receiver.isUtc ? H.Primitives_lazyAsJsDate(receiver).getUTCMinutes() + 0 : H.Primitives_lazyAsJsDate(receiver).getMinutes() + 0;\n  },\n  Primitives_getSeconds: function(receiver) {\n    return receiver.isUtc ? H.Primitives_lazyAsJsDate(receiver).getUTCSeconds() + 0 : H.Primitives_lazyAsJsDate(receiver).getSeconds() + 0;\n  },\n  Primitives_getProperty: function(object, key) {\n    if (object == null || typeof object === \"boolean\" || typeof object === \"number\" || typeof object === \"string\")\n      throw H.wrapException(new P.ArgumentError(object));\n    return object[key];\n  },\n  Primitives_setProperty: function(object, key, value) {\n    if (object == null || typeof object === \"boolean\" || typeof object === \"number\" || typeof object === \"string\")\n      throw H.wrapException(new P.ArgumentError(object));\n    object[key] = value;\n  },\n  iae: function(argument) {\n    throw H.wrapException(P.ArgumentError$(argument));\n  },\n  ioore: function(receiver, index) {\n    if (receiver == null)\n      J.get$length$asx(receiver);\n    if (typeof index !== \"number\" || Math.floor(index) !== index)\n      H.iae(index);\n    throw H.wrapException(P.RangeError$value(index));\n  },\n  wrapException: function(ex) {\n    var wrapper;\n    if (ex == null)\n      ex = new P.NullThrownError();\n    wrapper = new Error();\n    wrapper.dartException = ex;\n    if (\"defineProperty\" in Object) {\n      Object.defineProperty(wrapper, \"message\", { get: H.toStringWrapper });\n      wrapper.name = \"\";\n    } else\n      wrapper.toString = H.toStringWrapper;\n    return wrapper;\n  },\n  toStringWrapper: function() {\n    return J.toString$0(this.dartException);\n  },\n  throwExpression: function(ex) {\n    var wrapper;\n    if (ex == null)\n      ex = new P.NullThrownError();\n    wrapper = new Error();\n    wrapper.dartException = ex;\n    if (\"defineProperty\" in Object) {\n      Object.defineProperty(wrapper, \"message\", { get: H.toStringWrapper });\n      wrapper.name = \"\";\n    } else\n      wrapper.toString = H.toStringWrapper;\n    throw wrapper;\n  },\n  unwrapException: function(ex) {\n    var t1, message, number, ieErrorCode, t2, t3, t4, nullLiteralCall, t5, t6, t7, t8, t9, match;\n    t1 = new H.unwrapException_saveStackTrace(ex);\n    if (ex == null)\n      return;\n    if (typeof ex !== \"object\")\n      return ex;\n    if (\"dartException\" in ex)\n      return t1.call$1(ex.dartException);\n    else if (!(\"message\" in ex))\n      return ex;\n    message = ex.message;\n    if (\"number\" in ex && typeof ex.number == \"number\") {\n      number = ex.number;\n      ieErrorCode = number & 65535;\n      if ((C.JSInt_methods._shrOtherPositive$1(number, 16) & 8191) === 10)\n        switch (ieErrorCode) {\n          case 438:\n            return t1.call$1(H.JsNoSuchMethodError$(H.S(message) + \" (Error \" + ieErrorCode + \")\", null));\n          case 445:\n          case 5007:\n            t2 = H.S(message) + \" (Error \" + ieErrorCode + \")\";\n            return t1.call$1(new H.NullError(t2, null));\n          default:\n        }\n    }\n    if (ex instanceof TypeError) {\n      t2 = $.get$TypeErrorDecoder_noSuchMethodPattern();\n      t3 = $.get$TypeErrorDecoder_notClosurePattern();\n      t4 = $.get$TypeErrorDecoder_nullCallPattern();\n      nullLiteralCall = $.get$TypeErrorDecoder_nullLiteralCallPattern();\n      t5 = $.get$TypeErrorDecoder_undefinedCallPattern();\n      t6 = $.get$TypeErrorDecoder_undefinedLiteralCallPattern();\n      t7 = $.get$TypeErrorDecoder_nullPropertyPattern();\n      $.get$TypeErrorDecoder_nullLiteralPropertyPattern();\n      t8 = $.get$TypeErrorDecoder_undefinedPropertyPattern();\n      t9 = $.get$TypeErrorDecoder_undefinedLiteralPropertyPattern();\n      match = t2.matchTypeError$1(message);\n      if (match != null)\n        return t1.call$1(H.JsNoSuchMethodError$(message, match));\n      else {\n        match = t3.matchTypeError$1(message);\n        if (match != null) {\n          match.method = \"call\";\n          return t1.call$1(H.JsNoSuchMethodError$(message, match));\n        } else {\n          match = t4.matchTypeError$1(message);\n          if (match == null) {\n            match = nullLiteralCall.matchTypeError$1(message);\n            if (match == null) {\n              match = t5.matchTypeError$1(message);\n              if (match == null) {\n                match = t6.matchTypeError$1(message);\n                if (match == null) {\n                  match = t7.matchTypeError$1(message);\n                  if (match == null) {\n                    match = nullLiteralCall.matchTypeError$1(message);\n                    if (match == null) {\n                      match = t8.matchTypeError$1(message);\n                      if (match == null) {\n                        match = t9.matchTypeError$1(message);\n                        t2 = match != null;\n                      } else\n                        t2 = true;\n                    } else\n                      t2 = true;\n                  } else\n                    t2 = true;\n                } else\n                  t2 = true;\n              } else\n                t2 = true;\n            } else\n              t2 = true;\n          } else\n            t2 = true;\n          if (t2) {\n            t2 = match == null ? null : match.method;\n            return t1.call$1(new H.NullError(message, t2));\n          }\n        }\n      }\n      t2 = typeof message === \"string\" ? message : \"\";\n      return t1.call$1(new H.UnknownJsTypeError(t2));\n    }\n    if (ex instanceof RangeError) {\n      if (typeof message === \"string\" && message.indexOf(\"call stack\") !== -1)\n        return new P.StackOverflowError();\n      return t1.call$1(new P.ArgumentError(null));\n    }\n    if (typeof InternalError == \"function\" && ex instanceof InternalError)\n      if (typeof message === \"string\" && message === \"too much recursion\")\n        return new P.StackOverflowError();\n    return ex;\n  },\n  objectHashCode: function(object) {\n    if (object == null || typeof object != 'object')\n      return J.get$hashCode$(object);\n    else\n      return H.Primitives_objectHashCode(object);\n  },\n  fillLiteralMap: function(keyValuePairs, result) {\n    var $length, index, index0, index1;\n    $length = keyValuePairs.length;\n    for (index = 0; index < $length; index = index1) {\n      index0 = index + 1;\n      index1 = index0 + 1;\n      result.$indexSet(result, keyValuePairs[index], keyValuePairs[index0]);\n    }\n    return result;\n  },\n  invokeClosure: function(closure, isolate, numberOfArguments, arg1, arg2, arg3, arg4) {\n    var t1 = J.getInterceptor(numberOfArguments);\n    if (t1.$eq(numberOfArguments, 0))\n      return H._callInIsolate(isolate, new H.invokeClosure_closure(closure));\n    else if (t1.$eq(numberOfArguments, 1))\n      return H._callInIsolate(isolate, new H.invokeClosure_closure0(closure, arg1));\n    else if (t1.$eq(numberOfArguments, 2))\n      return H._callInIsolate(isolate, new H.invokeClosure_closure1(closure, arg1, arg2));\n    else if (t1.$eq(numberOfArguments, 3))\n      return H._callInIsolate(isolate, new H.invokeClosure_closure2(closure, arg1, arg2, arg3));\n    else if (t1.$eq(numberOfArguments, 4))\n      return H._callInIsolate(isolate, new H.invokeClosure_closure3(closure, arg1, arg2, arg3, arg4));\n    else\n      throw H.wrapException(P.Exception_Exception(\"Unsupported number of arguments for wrapped closure\"));\n  },\n  convertDartClosureToJS: function(closure, arity) {\n    var $function;\n    if (closure == null)\n      return;\n    $function = closure.$identity;\n    if (!!$function)\n      return $function;\n    $function = (function(closure, arity, context, invoke) {  return function(a1, a2, a3, a4) {     return invoke(closure, context, arity, a1, a2, a3, a4);  };})(closure,arity,init.globalState.currentContext,H.invokeClosure);\n    closure.$identity = $function;\n    return $function;\n  },\n  Closure_fromTearOff: function(receiver, functions, reflectionInfo, isStatic, jsArguments, propertyName) {\n    var $function, callName, functionType, $prototype, $constructor, t1, isIntercepted, trampoline, signatureFunction, getReceiver, i, stub, stubCallName, t2;\n    $function = functions[0];\n    $function.$stubName;\n    callName = $function.$callName;\n    $function.$reflectionInfo = reflectionInfo;\n    functionType = H.ReflectionInfo_ReflectionInfo($function).functionType;\n    $prototype = isStatic ? Object.create(new H.TearOffClosure().constructor.prototype) : Object.create(new H.BoundClosure(null, null, null, null).constructor.prototype);\n    $prototype.$initialize = $prototype.constructor;\n    if (isStatic)\n      $constructor = function(){this.$initialize()};\n    else if (typeof dart_precompiled == \"function\") {\n      t1 = function(a,b,c,d) {this.$initialize(a,b,c,d)};\n      $constructor = t1;\n    } else {\n      t1 = $.Closure_functionCounter;\n      $.Closure_functionCounter = J.$add$ns(t1, 1);\n      t1 = new Function(\"a\", \"b\", \"c\", \"d\", \"this.$initialize(a,b,c,d);\" + t1);\n      $constructor = t1;\n    }\n    $prototype.constructor = $constructor;\n    $constructor.prototype = $prototype;\n    t1 = !isStatic;\n    if (t1) {\n      isIntercepted = jsArguments.length == 1 && true;\n      trampoline = H.Closure_forwardCallTo($function, isIntercepted);\n    } else {\n      $prototype.$name = propertyName;\n      trampoline = $function;\n      isIntercepted = false;\n    }\n    if (typeof functionType == \"number\")\n      signatureFunction = (function(s){return function(){return init.metadata[s]}})(functionType);\n    else if (t1 && typeof functionType == \"function\") {\n      getReceiver = isIntercepted ? H.BoundClosure_receiverOf : H.BoundClosure_selfOf;\n      signatureFunction = function(f,r){return function(){return f.apply({$receiver:r(this)},arguments)}}(functionType,getReceiver);\n    } else\n      throw H.wrapException(\"Error in reflectionInfo.\");\n    $prototype.$signature = signatureFunction;\n    $prototype[callName] = trampoline;\n    for (t1 = functions.length, i = 1; i < t1; ++i) {\n      stub = functions[i];\n      stubCallName = stub.$callName;\n      if (stubCallName != null) {\n        t2 = isStatic ? stub : H.Closure_forwardCallTo(stub, isIntercepted);\n        $prototype[stubCallName] = t2;\n      }\n    }\n    $prototype[\"call*\"] = $function;\n    return $constructor;\n  },\n  Closure_cspForwardCall: function(arity, $function) {\n    var getSelf = H.BoundClosure_selfOf;\n    switch (arity) {\n      case 0:\n        return function(F,S){return function(){return F.call(S(this))}}($function,getSelf);\n      case 1:\n        return function(F,S){return function(a){return F.call(S(this),a)}}($function,getSelf);\n      case 2:\n        return function(F,S){return function(a,b){return F.call(S(this),a,b)}}($function,getSelf);\n      case 3:\n        return function(F,S){return function(a,b,c){return F.call(S(this),a,b,c)}}($function,getSelf);\n      case 4:\n        return function(F,S){return function(a,b,c,d){return F.call(S(this),a,b,c,d)}}($function,getSelf);\n      case 5:\n        return function(F,S){return function(a,b,c,d,e){return F.call(S(this),a,b,c,d,e)}}($function,getSelf);\n      default:\n        return function(f,s){return function(){return f.apply(s(this),arguments)}}($function,getSelf);\n    }\n  },\n  Closure_forwardCallTo: function($function, isIntercepted) {\n    var arity, t1, t2, $arguments;\n    if (isIntercepted)\n      return H.Closure_forwardInterceptedCallTo($function);\n    arity = $function.length;\n    if (typeof dart_precompiled == \"function\")\n      return H.Closure_cspForwardCall(arity, $function);\n    else if (arity === 0) {\n      t1 = $.BoundClosure_selfFieldNameCache;\n      if (t1 == null) {\n        t1 = H.BoundClosure_computeFieldNamed(\"self\");\n        $.BoundClosure_selfFieldNameCache = t1;\n      }\n      t1 = \"return function(){return F.call(this.\" + H.S(t1) + \");\";\n      t2 = $.Closure_functionCounter;\n      $.Closure_functionCounter = J.$add$ns(t2, 1);\n      return new Function(\"F\", t1 + H.S(t2) + \"}\")($function);\n    } else if (1 <= arity && arity < 27) {\n      $arguments = \"abcdefghijklmnopqrstuvwxyz\".split(\"\").splice(0, arity).join(\",\");\n      t1 = \"return function(\" + $arguments + \"){return F.call(this.\";\n      t2 = $.BoundClosure_selfFieldNameCache;\n      if (t2 == null) {\n        t2 = H.BoundClosure_computeFieldNamed(\"self\");\n        $.BoundClosure_selfFieldNameCache = t2;\n      }\n      t2 = t1 + H.S(t2) + \",\" + $arguments + \");\";\n      t1 = $.Closure_functionCounter;\n      $.Closure_functionCounter = J.$add$ns(t1, 1);\n      return new Function(\"F\", t2 + H.S(t1) + \"}\")($function);\n    } else\n      return H.Closure_cspForwardCall(arity, $function);\n  },\n  Closure_cspForwardInterceptedCall: function(arity, $name, $function) {\n    var getSelf, getReceiver;\n    getSelf = H.BoundClosure_selfOf;\n    getReceiver = H.BoundClosure_receiverOf;\n    switch (arity) {\n      case 0:\n        throw H.wrapException(H.RuntimeError$(\"Intercepted function with no arguments.\"));\n      case 1:\n        return function(n,s,r){return function(){return s(this)[n](r(this))}}($name,getSelf,getReceiver);\n      case 2:\n        return function(n,s,r){return function(a){return s(this)[n](r(this),a)}}($name,getSelf,getReceiver);\n      case 3:\n        return function(n,s,r){return function(a,b){return s(this)[n](r(this),a,b)}}($name,getSelf,getReceiver);\n      case 4:\n        return function(n,s,r){return function(a,b,c){return s(this)[n](r(this),a,b,c)}}($name,getSelf,getReceiver);\n      case 5:\n        return function(n,s,r){return function(a,b,c,d){return s(this)[n](r(this),a,b,c,d)}}($name,getSelf,getReceiver);\n      case 6:\n        return function(n,s,r){return function(a,b,c,d,e){return s(this)[n](r(this),a,b,c,d,e)}}($name,getSelf,getReceiver);\n      default:\n        return function(f,s,r,a){return function(){a=[r(this)];Array.prototype.push.apply(a,arguments);return f.apply(s(this),a)}}($function,getSelf,getReceiver);\n    }\n  },\n  Closure_forwardInterceptedCallTo: function($function) {\n    var stubName, arity, t1, t2, $arguments;\n    stubName = $function.$stubName;\n    arity = $function.length;\n    if (typeof dart_precompiled == \"function\")\n      return H.Closure_cspForwardInterceptedCall(arity, stubName, $function);\n    else if (arity === 1) {\n      t1 = \"return this.\" + H.S(H.BoundClosure_selfFieldName()) + \".\" + stubName + \"(this.\" + H.S(H.BoundClosure_receiverFieldName()) + \");\";\n      t2 = $.Closure_functionCounter;\n      $.Closure_functionCounter = J.$add$ns(t2, 1);\n      return new Function(t1 + H.S(t2));\n    } else if (1 < arity && arity < 28) {\n      $arguments = \"abcdefghijklmnopqrstuvwxyz\".split(\"\").splice(0, arity - 1).join(\",\");\n      t1 = \"return function(\" + $arguments + \"){return this.\" + H.S(H.BoundClosure_selfFieldName()) + \".\" + stubName + \"(this.\" + H.S(H.BoundClosure_receiverFieldName()) + \",\" + $arguments + \");\";\n      t2 = $.Closure_functionCounter;\n      $.Closure_functionCounter = J.$add$ns(t2, 1);\n      return new Function(t1 + H.S(t2) + \"}\")();\n    } else\n      return H.Closure_cspForwardInterceptedCall(arity, stubName, $function);\n  },\n  closureFromTearOff: function(receiver, functions, reflectionInfo, isStatic, jsArguments, $name) {\n    functions.fixed$length = init;\n    reflectionInfo.fixed$length = init;\n    return H.Closure_fromTearOff(receiver, functions, reflectionInfo, !!isStatic, jsArguments, $name);\n  },\n  throwCyclicInit: function(staticName) {\n    throw H.wrapException(P.CyclicInitializationError$(\"Cyclic initialization for static \" + H.S(staticName)));\n  },\n  buildFunctionType: function(returnType, parameterTypes, optionalParameterTypes) {\n    return new H.RuntimeFunctionType(returnType, parameterTypes, optionalParameterTypes, null);\n  },\n  getDynamicRuntimeType: function() {\n    return C.C_DynamicRuntimeType;\n  },\n  createRuntimeType: function($name) {\n    return new H.TypeImpl($name, null);\n  },\n  setRuntimeTypeInfo: function(target, typeInfo) {\n    if (target != null)\n      target.$builtinTypeInfo = typeInfo;\n    return target;\n  },\n  getRuntimeTypeInfo: function(target) {\n    if (target == null)\n      return;\n    return target.$builtinTypeInfo;\n  },\n  getRuntimeTypeArguments: function(target, substitutionName) {\n    return H.substitute(target[\"$as\" + H.S(substitutionName)], H.getRuntimeTypeInfo(target));\n  },\n  getRuntimeTypeArgument: function(target, substitutionName, index) {\n    var $arguments = H.getRuntimeTypeArguments(target, substitutionName);\n    return $arguments == null ? null : $arguments[index];\n  },\n  getTypeArgumentByIndex: function(target, index) {\n    var rti = H.getRuntimeTypeInfo(target);\n    return rti == null ? null : rti[index];\n  },\n  runtimeTypeToString: function(type, onTypeVariable) {\n    if (type == null)\n      return \"dynamic\";\n    else if (typeof type === \"object\" && type !== null && type.constructor === Array)\n      return type[0].builtin$cls + H.joinArguments(type, 1, onTypeVariable);\n    else if (typeof type == \"function\")\n      return type.builtin$cls;\n    else if (typeof type === \"number\" && Math.floor(type) === type)\n      return C.JSInt_methods.toString$0(type);\n    else\n      return;\n  },\n  joinArguments: function(types, startIndex, onTypeVariable) {\n    var buffer, index, firstArgument, allDynamic, argument, str;\n    if (types == null)\n      return \"\";\n    buffer = P.StringBuffer$(\"\");\n    for (index = startIndex, firstArgument = true, allDynamic = true; index < types.length; ++index) {\n      if (firstArgument)\n        firstArgument = false;\n      else\n        buffer._contents = buffer._contents + \", \";\n      argument = types[index];\n      if (argument != null)\n        allDynamic = false;\n      str = H.runtimeTypeToString(argument, onTypeVariable);\n      str = typeof str === \"string\" ? str : H.S(str);\n      buffer._contents = buffer._contents + str;\n    }\n    return allDynamic ? \"\" : \"<\" + H.S(buffer) + \">\";\n  },\n  substitute: function(substitution, $arguments) {\n    if (typeof substitution === \"object\" && substitution !== null && substitution.constructor === Array)\n      $arguments = substitution;\n    else if (typeof substitution == \"function\") {\n      substitution = H.invokeOn(substitution, null, $arguments);\n      if (typeof substitution === \"object\" && substitution !== null && substitution.constructor === Array)\n        $arguments = substitution;\n      else if (typeof substitution == \"function\")\n        $arguments = H.invokeOn(substitution, null, $arguments);\n    }\n    return $arguments;\n  },\n  areSubtypes: function(s, t) {\n    var len, i;\n    if (s == null || t == null)\n      return true;\n    len = s.length;\n    for (i = 0; i < len; ++i)\n      if (!H.isSubtype(s[i], t[i]))\n        return false;\n    return true;\n  },\n  computeSignature: function(signature, context, contextName) {\n    return H.invokeOn(signature, context, H.getRuntimeTypeArguments(context, contextName));\n  },\n  isSubtype: function(s, t) {\n    var targetSignatureFunction, t1, typeOfS, t2, typeOfT, $name, substitution;\n    if (s === t)\n      return true;\n    if (s == null || t == null)\n      return true;\n    if (\"func\" in t) {\n      if (!(\"func\" in s)) {\n        if (\"$is_\" + H.S(t.func) in s)\n          return true;\n        targetSignatureFunction = s.$signature;\n        if (targetSignatureFunction == null)\n          return false;\n        s = targetSignatureFunction.apply(s, null);\n      }\n      return H.isFunctionSubtype(s, t);\n    }\n    if (t.builtin$cls === \"Function\" && \"func\" in s)\n      return true;\n    t1 = typeof s === \"object\" && s !== null && s.constructor === Array;\n    typeOfS = t1 ? s[0] : s;\n    t2 = typeof t === \"object\" && t !== null && t.constructor === Array;\n    typeOfT = t2 ? t[0] : t;\n    $name = H.runtimeTypeToString(typeOfT, null);\n    if (typeOfT !== typeOfS) {\n      if (!(\"$is\" + H.S($name) in typeOfS))\n        return false;\n      substitution = typeOfS[\"$as\" + H.S(H.runtimeTypeToString(typeOfT, null))];\n    } else\n      substitution = null;\n    if (!t1 && substitution == null || !t2)\n      return true;\n    t1 = t1 ? s.slice(1) : null;\n    t2 = t2 ? t.slice(1) : null;\n    return H.areSubtypes(H.substitute(substitution, t1), t2);\n  },\n  areAssignable: function(s, t, allowShorter) {\n    var sLength, tLength, i, t1, t2;\n    if (t == null && s == null)\n      return true;\n    if (t == null)\n      return allowShorter;\n    if (s == null)\n      return false;\n    sLength = s.length;\n    tLength = t.length;\n    if (allowShorter) {\n      if (sLength < tLength)\n        return false;\n    } else if (sLength !== tLength)\n      return false;\n    for (i = 0; i < tLength; ++i) {\n      t1 = s[i];\n      t2 = t[i];\n      if (!(H.isSubtype(t1, t2) || H.isSubtype(t2, t1)))\n        return false;\n    }\n    return true;\n  },\n  areAssignableMaps: function(s, t) {\n    var t1, names, i, $name, tType, sType;\n    if (t == null)\n      return true;\n    if (s == null)\n      return false;\n    t1 = Object.getOwnPropertyNames(t);\n    t1.fixed$length = init;\n    names = t1;\n    for (t1 = names.length, i = 0; i < t1; ++i) {\n      $name = names[i];\n      if (!Object.hasOwnProperty.call(s, $name))\n        return false;\n      tType = t[$name];\n      sType = s[$name];\n      if (!(H.isSubtype(tType, sType) || H.isSubtype(sType, tType)))\n        return false;\n    }\n    return true;\n  },\n  isFunctionSubtype: function(s, t) {\n    var sReturnType, tReturnType, sParameterTypes, tParameterTypes, sOptionalParameterTypes, tOptionalParameterTypes, sParametersLen, tParametersLen, sOptionalParametersLen, tOptionalParametersLen, pos, t1, t2, tPos, sPos;\n    if (!(\"func\" in s))\n      return false;\n    if (\"void\" in s) {\n      if (!(\"void\" in t) && \"ret\" in t)\n        return false;\n    } else if (!(\"void\" in t)) {\n      sReturnType = s.ret;\n      tReturnType = t.ret;\n      if (!(H.isSubtype(sReturnType, tReturnType) || H.isSubtype(tReturnType, sReturnType)))\n        return false;\n    }\n    sParameterTypes = s.args;\n    tParameterTypes = t.args;\n    sOptionalParameterTypes = s.opt;\n    tOptionalParameterTypes = t.opt;\n    sParametersLen = sParameterTypes != null ? sParameterTypes.length : 0;\n    tParametersLen = tParameterTypes != null ? tParameterTypes.length : 0;\n    sOptionalParametersLen = sOptionalParameterTypes != null ? sOptionalParameterTypes.length : 0;\n    tOptionalParametersLen = tOptionalParameterTypes != null ? tOptionalParameterTypes.length : 0;\n    if (sParametersLen > tParametersLen)\n      return false;\n    if (sParametersLen + sOptionalParametersLen < tParametersLen + tOptionalParametersLen)\n      return false;\n    if (sParametersLen === tParametersLen) {\n      if (!H.areAssignable(sParameterTypes, tParameterTypes, false))\n        return false;\n      if (!H.areAssignable(sOptionalParameterTypes, tOptionalParameterTypes, true))\n        return false;\n    } else {\n      for (pos = 0; pos < sParametersLen; ++pos) {\n        t1 = sParameterTypes[pos];\n        t2 = tParameterTypes[pos];\n        if (!(H.isSubtype(t1, t2) || H.isSubtype(t2, t1)))\n          return false;\n      }\n      for (tPos = pos, sPos = 0; tPos < tParametersLen; ++sPos, ++tPos) {\n        t1 = sOptionalParameterTypes[sPos];\n        t2 = tParameterTypes[tPos];\n        if (!(H.isSubtype(t1, t2) || H.isSubtype(t2, t1)))\n          return false;\n      }\n      for (tPos = 0; tPos < tOptionalParametersLen; ++sPos, ++tPos) {\n        t1 = sOptionalParameterTypes[sPos];\n        t2 = tOptionalParameterTypes[tPos];\n        if (!(H.isSubtype(t1, t2) || H.isSubtype(t2, t1)))\n          return false;\n      }\n    }\n    return H.areAssignableMaps(s.named, t.named);\n  },\n  invokeOn: function($function, receiver, $arguments) {\n    return $function.apply(receiver, $arguments);\n  },\n  toStringForNativeObject: function(obj) {\n    var t1 = $.getTagFunction;\n    return \"Instance of \" + (t1 == null ? \"<Unknown>\" : t1.call$1(obj));\n  },\n  hashCodeForNativeObject: function(object) {\n    return H.Primitives_objectHashCode(object);\n  },\n  defineProperty: function(obj, property, value) {\n    Object.defineProperty(obj, property, {value: value, enumerable: false, writable: true, configurable: true});\n  },\n  lookupAndCacheInterceptor: function(obj) {\n    var tag, record, interceptor, interceptorClass, mark, t1;\n    tag = $.getTagFunction.call$1(obj);\n    record = $.dispatchRecordsForInstanceTags[tag];\n    if (record != null) {\n      Object.defineProperty(obj, init.dispatchPropertyName, {value: record, enumerable: false, writable: true, configurable: true});\n      return record.i;\n    }\n    interceptor = $.interceptorsForUncacheableTags[tag];\n    if (interceptor != null)\n      return interceptor;\n    interceptorClass = init.interceptorsByTag[tag];\n    if (interceptorClass == null) {\n      tag = $.alternateTagFunction.call$2(obj, tag);\n      if (tag != null) {\n        record = $.dispatchRecordsForInstanceTags[tag];\n        if (record != null) {\n          Object.defineProperty(obj, init.dispatchPropertyName, {value: record, enumerable: false, writable: true, configurable: true});\n          return record.i;\n        }\n        interceptor = $.interceptorsForUncacheableTags[tag];\n        if (interceptor != null)\n          return interceptor;\n        interceptorClass = init.interceptorsByTag[tag];\n      }\n    }\n    if (interceptorClass == null)\n      return;\n    interceptor = interceptorClass.prototype;\n    mark = tag[0];\n    if (mark === \"!\") {\n      record = H.makeLeafDispatchRecord(interceptor);\n      $.dispatchRecordsForInstanceTags[tag] = record;\n      Object.defineProperty(obj, init.dispatchPropertyName, {value: record, enumerable: false, writable: true, configurable: true});\n      return record.i;\n    }\n    if (mark === \"~\") {\n      $.interceptorsForUncacheableTags[tag] = interceptor;\n      return interceptor;\n    }\n    if (mark === \"-\") {\n      t1 = H.makeLeafDispatchRecord(interceptor);\n      Object.defineProperty(Object.getPrototypeOf(obj), init.dispatchPropertyName, {value: t1, enumerable: false, writable: true, configurable: true});\n      return t1.i;\n    }\n    if (mark === \"+\")\n      return H.patchInteriorProto(obj, interceptor);\n    if (mark === \"*\")\n      throw H.wrapException(P.UnimplementedError$(tag));\n    if (init.leafTags[tag] === true) {\n      t1 = H.makeLeafDispatchRecord(interceptor);\n      Object.defineProperty(Object.getPrototypeOf(obj), init.dispatchPropertyName, {value: t1, enumerable: false, writable: true, configurable: true});\n      return t1.i;\n    } else\n      return H.patchInteriorProto(obj, interceptor);\n  },\n  patchInteriorProto: function(obj, interceptor) {\n    var proto, record;\n    proto = Object.getPrototypeOf(obj);\n    record = J.makeDispatchRecord(interceptor, proto, null, null);\n    Object.defineProperty(proto, init.dispatchPropertyName, {value: record, enumerable: false, writable: true, configurable: true});\n    return interceptor;\n  },\n  makeLeafDispatchRecord: function(interceptor) {\n    return J.makeDispatchRecord(interceptor, false, null, !!interceptor.$isJavaScriptIndexingBehavior);\n  },\n  makeDefaultDispatchRecord: function(tag, interceptorClass, proto) {\n    var interceptor = interceptorClass.prototype;\n    if (init.leafTags[tag] === true)\n      return J.makeDispatchRecord(interceptor, false, null, !!interceptor.$isJavaScriptIndexingBehavior);\n    else\n      return J.makeDispatchRecord(interceptor, proto, null, null);\n  },\n  initNativeDispatch: function() {\n    if (true === $.initNativeDispatchFlag)\n      return;\n    $.initNativeDispatchFlag = true;\n    H.initNativeDispatchContinue();\n  },\n  initNativeDispatchContinue: function() {\n    var map, tags, i, tag, proto, record, interceptorClass;\n    $.dispatchRecordsForInstanceTags = Object.create(null);\n    $.interceptorsForUncacheableTags = Object.create(null);\n    H.initHooks();\n    map = init.interceptorsByTag;\n    tags = Object.getOwnPropertyNames(map);\n    if (typeof window != \"undefined\") {\n      window;\n      for (i = 0; i < tags.length; ++i) {\n        tag = tags[i];\n        proto = $.prototypeForTagFunction.call$1(tag);\n        if (proto != null) {\n          record = H.makeDefaultDispatchRecord(tag, map[tag], proto);\n          if (record != null)\n            Object.defineProperty(proto, init.dispatchPropertyName, {value: record, enumerable: false, writable: true, configurable: true});\n        }\n      }\n    }\n    for (i = 0; i < tags.length; ++i) {\n      tag = tags[i];\n      if (/^[A-Za-z_]/.test(tag)) {\n        interceptorClass = map[tag];\n        map[\"!\" + tag] = interceptorClass;\n        map[\"~\" + tag] = interceptorClass;\n        map[\"-\" + tag] = interceptorClass;\n        map[\"+\" + tag] = interceptorClass;\n        map[\"*\" + tag] = interceptorClass;\n      }\n    }\n  },\n  initHooks: function() {\n    var hooks, transformers, i, transformer, getTag, getUnknownTag, prototypeForTag;\n    hooks = C.JS_CONST_aQP();\n    hooks = H.applyHooksTransformer(C.JS_CONST_0, H.applyHooksTransformer(C.JS_CONST_rr7, H.applyHooksTransformer(C.JS_CONST_Fs4, H.applyHooksTransformer(C.JS_CONST_Fs4, H.applyHooksTransformer(C.JS_CONST_gkc, H.applyHooksTransformer(C.JS_CONST_U4w, H.applyHooksTransformer(C.JS_CONST_QJm(C.JS_CONST_IX5), hooks)))))));\n    if (typeof dartNativeDispatchHooksTransformer != \"undefined\") {\n      transformers = dartNativeDispatchHooksTransformer;\n      if (typeof transformers == \"function\")\n        transformers = [transformers];\n      if (transformers.constructor == Array)\n        for (i = 0; i < transformers.length; ++i) {\n          transformer = transformers[i];\n          if (typeof transformer == \"function\")\n            hooks = transformer(hooks) || hooks;\n        }\n    }\n    getTag = hooks.getTag;\n    getUnknownTag = hooks.getUnknownTag;\n    prototypeForTag = hooks.prototypeForTag;\n    $.getTagFunction = new H.initHooks_closure(getTag);\n    $.alternateTagFunction = new H.initHooks_closure0(getUnknownTag);\n    $.prototypeForTagFunction = new H.initHooks_closure1(prototypeForTag);\n  },\n  applyHooksTransformer: function(transformer, hooks) {\n    return transformer(hooks) || hooks;\n  },\n  ReflectionInfo: {\n    \"\": \"Object;jsFunction,data,isAccessor,requiredParameterCount,optionalParameterCount,areOptionalParametersNamed,functionType\",\n    static: {\"\": \"ReflectionInfo_REQUIRED_PARAMETERS_INFO,ReflectionInfo_OPTIONAL_PARAMETERS_INFO,ReflectionInfo_FUNCTION_TYPE_INDEX,ReflectionInfo_FIRST_DEFAULT_ARGUMENT\", ReflectionInfo_ReflectionInfo: function(jsFunction) {\n        var data, requiredParametersInfo, requiredParameterCount, optionalParametersInfo;\n        data = jsFunction.$reflectionInfo;\n        if (data == null)\n          return;\n        data.fixed$length = init;\n        data = data;\n        requiredParametersInfo = data[0];\n        requiredParameterCount = requiredParametersInfo >> 1;\n        optionalParametersInfo = data[1];\n        return new H.ReflectionInfo(jsFunction, data, (requiredParametersInfo & 1) === 1, requiredParameterCount, optionalParametersInfo >> 1, (optionalParametersInfo & 1) === 1, data[2]);\n      }}\n  },\n  TypeErrorDecoder: {\n    \"\": \"Object;_pattern,_arguments,_argumentsExpr,_expr,_method,_receiver<\",\n    matchTypeError$1: function(message) {\n      var match, result, t1;\n      match = new RegExp(this._pattern).exec(message);\n      if (match == null)\n        return;\n      result = {};\n      t1 = this._arguments;\n      if (t1 !== -1)\n        result.arguments = match[t1 + 1];\n      t1 = this._argumentsExpr;\n      if (t1 !== -1)\n        result.argumentsExpr = match[t1 + 1];\n      t1 = this._expr;\n      if (t1 !== -1)\n        result.expr = match[t1 + 1];\n      t1 = this._method;\n      if (t1 !== -1)\n        result.method = match[t1 + 1];\n      t1 = this._receiver;\n      if (t1 !== -1)\n        result.receiver = match[t1 + 1];\n      return result;\n    },\n    static: {\"\": \"TypeErrorDecoder_noSuchMethodPattern,TypeErrorDecoder_notClosurePattern,TypeErrorDecoder_nullCallPattern,TypeErrorDecoder_nullLiteralCallPattern,TypeErrorDecoder_undefinedCallPattern,TypeErrorDecoder_undefinedLiteralCallPattern,TypeErrorDecoder_nullPropertyPattern,TypeErrorDecoder_nullLiteralPropertyPattern,TypeErrorDecoder_undefinedPropertyPattern,TypeErrorDecoder_undefinedLiteralPropertyPattern\", TypeErrorDecoder_extractPattern: function(message) {\n        var match, $arguments, argumentsExpr, expr, method, receiver;\n        message = message.replace(String({}), '$receiver$').replace(new RegExp(\"[[\\\\]{}()*+?.\\\\\\\\^$|]\", 'g'), '\\\\$&');\n        match = message.match(/\\\\\\$[a-zA-Z]+\\\\\\$/g);\n        if (match == null)\n          match = [];\n        $arguments = match.indexOf(\"\\\\$arguments\\\\$\");\n        argumentsExpr = match.indexOf(\"\\\\$argumentsExpr\\\\$\");\n        expr = match.indexOf(\"\\\\$expr\\\\$\");\n        method = match.indexOf(\"\\\\$method\\\\$\");\n        receiver = match.indexOf(\"\\\\$receiver\\\\$\");\n        return new H.TypeErrorDecoder(message.replace('\\\\$arguments\\\\$', '((?:x|[^x])*)').replace('\\\\$argumentsExpr\\\\$', '((?:x|[^x])*)').replace('\\\\$expr\\\\$', '((?:x|[^x])*)').replace('\\\\$method\\\\$', '((?:x|[^x])*)').replace('\\\\$receiver\\\\$', '((?:x|[^x])*)'), $arguments, argumentsExpr, expr, method, receiver);\n      }, TypeErrorDecoder_provokeCallErrorOn: function(expression) {\n        return function($expr$) {\n  var $argumentsExpr$ = '$arguments$'\n  try {\n    $expr$.$method$($argumentsExpr$);\n  } catch (e) {\n    return e.message;\n  }\n}(expression);\n      }, TypeErrorDecoder_provokePropertyErrorOn: function(expression) {\n        return function($expr$) {\n  try {\n    $expr$.$method$;\n  } catch (e) {\n    return e.message;\n  }\n}(expression);\n      }}\n  },\n  NullError: {\n    \"\": \"Error;_message,_method\",\n    toString$0: function(_) {\n      var t1 = this._method;\n      if (t1 == null)\n        return \"NullError: \" + H.S(this._message);\n      return \"NullError: Cannot call \\\"\" + H.S(t1) + \"\\\" on null\";\n    },\n    $isError: true\n  },\n  JsNoSuchMethodError: {\n    \"\": \"Error;_message,_method,_receiver<\",\n    toString$0: function(_) {\n      var t1, t2;\n      t1 = this._method;\n      if (t1 == null)\n        return \"NoSuchMethodError: \" + H.S(this._message);\n      t2 = this._receiver;\n      if (t2 == null)\n        return \"NoSuchMethodError: Cannot call \\\"\" + t1 + \"\\\" (\" + H.S(this._message) + \")\";\n      return \"NoSuchMethodError: Cannot call \\\"\" + t1 + \"\\\" on \\\"\" + t2 + \"\\\" (\" + H.S(this._message) + \")\";\n    },\n    $isError: true,\n    static: {JsNoSuchMethodError$: function(_message, match) {\n        var t1, t2;\n        t1 = match == null;\n        t2 = t1 ? null : match.method;\n        t1 = t1 ? null : match.receiver;\n        return new H.JsNoSuchMethodError(_message, t2, t1);\n      }}\n  },\n  UnknownJsTypeError: {\n    \"\": \"Error;_message\",\n    toString$0: function(_) {\n      var t1 = this._message;\n      return C.JSString_methods.get$isEmpty(t1) ? \"Error\" : \"Error: \" + t1;\n    }\n  },\n  unwrapException_saveStackTrace: {\n    \"\": \"Closure:10;ex_0\",\n    call$1: function(error) {\n      var t1 = J.getInterceptor(error);\n      if (typeof error === \"object\" && error !== null && !!t1.$isError)\n        if (error.$thrownJsError == null)\n          error.$thrownJsError = this.ex_0;\n      return error;\n    }\n  },\n  _StackTrace: {\n    \"\": \"Object;_exception,_trace\",\n    toString$0: function(_) {\n      var t1, trace;\n      t1 = this._trace;\n      if (t1 != null)\n        return t1;\n      t1 = this._exception;\n      trace = typeof t1 === \"object\" ? t1.stack : null;\n      t1 = trace == null ? \"\" : trace;\n      this._trace = t1;\n      return t1;\n    }\n  },\n  invokeClosure_closure: {\n    \"\": \"Closure:8;closure_0\",\n    call$0: function() {\n      return this.closure_0.call$0();\n    }\n  },\n  invokeClosure_closure0: {\n    \"\": \"Closure:8;closure_1,arg1_2\",\n    call$0: function() {\n      return this.closure_1.call$1(this.arg1_2);\n    }\n  },\n  invokeClosure_closure1: {\n    \"\": \"Closure:8;closure_3,arg1_4,arg2_5\",\n    call$0: function() {\n      return this.closure_3.call$2(this.arg1_4, this.arg2_5);\n    }\n  },\n  invokeClosure_closure2: {\n    \"\": \"Closure:8;closure_6,arg1_7,arg2_8,arg3_9\",\n    call$0: function() {\n      return this.closure_6.call$3(this.arg1_7, this.arg2_8, this.arg3_9);\n    }\n  },\n  invokeClosure_closure3: {\n    \"\": \"Closure:8;closure_10,arg1_11,arg2_12,arg3_13,arg4_14\",\n    call$0: function() {\n      return this.closure_10.call$4(this.arg1_11, this.arg2_12, this.arg3_13, this.arg4_14);\n    }\n  },\n  Closure: {\n    \"\": \"Object;\",\n    toString$0: function(_) {\n      return \"Closure\";\n    }\n  },\n  TearOffClosure: {\n    \"\": \"Closure;\"\n  },\n  BoundClosure: {\n    \"\": \"TearOffClosure;_self<,_target,_receiver<,__js_helper$_name\",\n    $eq: function(_, other) {\n      var t1;\n      if (other == null)\n        return false;\n      if (this === other)\n        return true;\n      t1 = J.getInterceptor(other);\n      if (typeof other !== \"object\" || other === null || !t1.$isBoundClosure)\n        return false;\n      return this._self === other._self && this._target === other._target && this._receiver === other._receiver;\n    },\n    get$hashCode: function(_) {\n      var t1, receiverHashCode;\n      t1 = this._receiver;\n      if (t1 == null)\n        receiverHashCode = H.Primitives_objectHashCode(this._self);\n      else\n        receiverHashCode = typeof t1 !== \"object\" ? J.get$hashCode$(t1) : H.Primitives_objectHashCode(t1);\n      return (receiverHashCode ^ H.Primitives_objectHashCode(this._target)) >>> 0;\n    },\n    $isBoundClosure: true,\n    static: {\"\": \"BoundClosure_selfFieldNameCache,BoundClosure_receiverFieldNameCache\", BoundClosure_selfOf: function(closure) {\n        return closure.get$_self();\n      }, BoundClosure_receiverOf: function(closure) {\n        return closure.get$_receiver();\n      }, BoundClosure_selfFieldName: function() {\n        var t1 = $.BoundClosure_selfFieldNameCache;\n        if (t1 == null) {\n          t1 = H.BoundClosure_computeFieldNamed(\"self\");\n          $.BoundClosure_selfFieldNameCache = t1;\n        }\n        return t1;\n      }, BoundClosure_receiverFieldName: function() {\n        var t1 = $.BoundClosure_receiverFieldNameCache;\n        if (t1 == null) {\n          t1 = H.BoundClosure_computeFieldNamed(\"receiver\");\n          $.BoundClosure_receiverFieldNameCache = t1;\n        }\n        return t1;\n      }, BoundClosure_computeFieldNamed: function(fieldName) {\n        var template, t1, names, i, $name;\n        template = new H.BoundClosure(\"self\", \"target\", \"receiver\", \"name\");\n        t1 = Object.getOwnPropertyNames(template);\n        t1.fixed$length = init;\n        names = t1;\n        for (t1 = names.length, i = 0; i < t1; ++i) {\n          $name = names[i];\n          if (template[$name] === fieldName)\n            return $name;\n        }\n      }}\n  },\n  RuntimeError: {\n    \"\": \"Error;message\",\n    toString$0: function(_) {\n      return \"RuntimeError: \" + H.S(this.message);\n    },\n    static: {RuntimeError$: function(message) {\n        return new H.RuntimeError(message);\n      }}\n  },\n  RuntimeType: {\n    \"\": \"Object;\"\n  },\n  RuntimeFunctionType: {\n    \"\": \"RuntimeType;returnType,parameterTypes,optionalParameterTypes,namedParameters\",\n    _isTest$1: function(expression) {\n      var functionTypeObject = this._extractFunctionTypeObjectFrom$1(expression);\n      return functionTypeObject == null ? false : H.isFunctionSubtype(functionTypeObject, this.toRti$0());\n    },\n    _extractFunctionTypeObjectFrom$1: function(o) {\n      var interceptor = J.getInterceptor(o);\n      return \"$signature\" in interceptor ? interceptor.$signature() : null;\n    },\n    toRti$0: function() {\n      var result, t1, t2, namedRti, keys, i, $name;\n      result = { \"func\": \"dynafunc\" };\n      t1 = this.returnType;\n      t2 = J.getInterceptor(t1);\n      if (typeof t1 === \"object\" && t1 !== null && !!t2.$isVoidRuntimeType)\n        result.void = true;\n      else if (typeof t1 !== \"object\" || t1 === null || !t2.$isDynamicRuntimeType)\n        result.ret = t1.toRti$0();\n      t1 = this.parameterTypes;\n      if (t1 != null && t1.length !== 0)\n        result.args = H.RuntimeFunctionType_listToRti(t1);\n      t1 = this.optionalParameterTypes;\n      if (t1 != null && t1.length !== 0)\n        result.opt = H.RuntimeFunctionType_listToRti(t1);\n      t1 = this.namedParameters;\n      if (t1 != null) {\n        namedRti = {};\n        keys = H.extractKeys(t1);\n        for (t2 = keys.length, i = 0; i < t2; ++i) {\n          $name = keys[i];\n          namedRti[$name] = t1[$name].toRti$0();\n        }\n        result.named = namedRti;\n      }\n      return result;\n    },\n    toString$0: function(_) {\n      var t1, t2, result, needsComma, i, type, keys, $name;\n      t1 = this.parameterTypes;\n      if (t1 != null)\n        for (t2 = t1.length, result = \"(\", needsComma = false, i = 0; i < t2; ++i, needsComma = true) {\n          type = t1[i];\n          if (needsComma)\n            result += \", \";\n          result += H.S(type);\n        }\n      else {\n        result = \"(\";\n        needsComma = false;\n      }\n      t1 = this.optionalParameterTypes;\n      if (t1 != null && t1.length !== 0) {\n        result = (needsComma ? result + \", \" : result) + \"[\";\n        for (t2 = t1.length, needsComma = false, i = 0; i < t2; ++i, needsComma = true) {\n          type = t1[i];\n          if (needsComma)\n            result += \", \";\n          result += H.S(type);\n        }\n        result += \"]\";\n      } else {\n        t1 = this.namedParameters;\n        if (t1 != null) {\n          result = (needsComma ? result + \", \" : result) + \"{\";\n          keys = H.extractKeys(t1);\n          for (t2 = keys.length, needsComma = false, i = 0; i < t2; ++i, needsComma = true) {\n            $name = keys[i];\n            if (needsComma)\n              result += \", \";\n            result += H.S(t1[$name].toRti$0()) + \" \" + $name;\n          }\n          result += \"}\";\n        }\n      }\n      return result + (\") -> \" + H.S(this.returnType));\n    },\n    static: {\"\": \"RuntimeFunctionType_inAssert\", RuntimeFunctionType_listToRti: function(list) {\n        var result, t1, i;\n        list = list;\n        result = [];\n        for (t1 = list.length, i = 0; i < t1; ++i)\n          result.push(list[i].toRti$0());\n        return result;\n      }}\n  },\n  DynamicRuntimeType: {\n    \"\": \"RuntimeType;\",\n    toString$0: function(_) {\n      return \"dynamic\";\n    },\n    toRti$0: function() {\n      return;\n    },\n    $isDynamicRuntimeType: true\n  },\n  TypeImpl: {\n    \"\": \"Object;_typeName,_unmangledName\",\n    toString$0: function(_) {\n      var t1, unmangledName, unmangledName0;\n      t1 = this._unmangledName;\n      if (t1 != null)\n        return t1;\n      unmangledName = this._typeName;\n      unmangledName0 = init.mangledGlobalNames[unmangledName];\n      unmangledName = unmangledName0 == null ? unmangledName : unmangledName0;\n      this._unmangledName = unmangledName;\n      return unmangledName;\n    },\n    get$hashCode: function(_) {\n      return J.get$hashCode$(this._typeName);\n    },\n    $eq: function(_, other) {\n      var t1;\n      if (other == null)\n        return false;\n      t1 = J.getInterceptor(other);\n      return typeof other === \"object\" && other !== null && !!t1.$isTypeImpl && J.$eq(this._typeName, other._typeName);\n    },\n    $isTypeImpl: true\n  },\n  initHooks_closure: {\n    \"\": \"Closure:10;getTag_0\",\n    call$1: function(o) {\n      return this.getTag_0(o);\n    }\n  },\n  initHooks_closure0: {\n    \"\": \"Closure:11;getUnknownTag_1\",\n    call$2: function(o, tag) {\n      return this.getUnknownTag_1(o, tag);\n    }\n  },\n  initHooks_closure1: {\n    \"\": \"Closure:12;prototypeForTag_2\",\n    call$1: function(tag) {\n      return this.prototypeForTag_2(tag);\n    }\n  }\n}],\n[\"clock\", \"clock.dart\", , Q, {\n  \"\": \"\",\n  main: [function() {\n    var t1, t2, t3, t4;\n    t1 = H.setRuntimeTypeInfo(Array(2), [Q.ClockNumber]);\n    t2 = H.setRuntimeTypeInfo(Array(2), [Q.ClockNumber]);\n    t3 = H.setRuntimeTypeInfo(Array(2), [Q.ClockNumber]);\n    t4 = new Q.Balls(null, P.DateTime$_now().millisecondsSinceEpoch, H.setRuntimeTypeInfo([], [Q.Ball]));\n    t4.Balls$0();\n    new Q.CountDownClock(t1, t2, t3, -1, -1, -1, t4).CountDownClock$0();\n  }, \"call$0\", \"main$closure\", 0, 0, 0],\n  setElementPosition: function(elem, x, y) {\n    J.set$left$x(elem.style, H.S(x) + \"px\");\n    J.set$top$x(elem.style, H.S(y) + \"px\");\n  },\n  Balls: {\n    \"\": \"Object;root,lastTime,balls\",\n    tick$1: function(now) {\n      var t1, t2, t3, delta;\n      t1 = J.getInterceptor$n(now);\n      t2 = J.$add$ns(t1.$sub(now, this.lastTime), 0.01);\n      if (typeof t2 !== \"number\")\n        return H.iae(t2);\n      t2 = 1000 / t2;\n      t3 = $.fpsAverage;\n      if (t3 == null)\n        $.fpsAverage = t2;\n      else {\n        if (typeof t3 !== \"number\")\n          return t3.$mul();\n        $.fpsAverage = t2 * 0.05 + t3 * 0.95;\n        document.querySelector(\"#notes\").textContent = \"\" + C.JSInt_methods.toInt$0(C.JSNumber_methods.toInt$0(J.roundToDouble$0$n($.fpsAverage))) + \" fps\";\n      }\n      t1 = t1.$sub(now, this.lastTime);\n      if (typeof t1 !== \"number\")\n        return t1.$div();\n      delta = P.min(t1 / 1000, 0.1);\n      this.lastTime = now;\n      H.IterableMixinWorkaround_removeWhereList(this.balls, new Q.Balls_tick_closure(delta));\n      this.collideBalls$1(delta);\n    },\n    collideBalls$1: function(delta) {\n      H.IterableMixinWorkaround_forEach(this.balls, new Q.Balls_collideBalls_closure(this, delta));\n    },\n    Balls$0: function() {\n      var t1 = document.createElement(\"div\", null);\n      this.root = t1;\n      document.body.appendChild(t1);\n      J.set$position$x(this.root.style, \"absolute\");\n      t1 = this.root;\n      Q.setElementPosition(t1, 0, 0);\n      J.set$right$x(t1.style, \"0px\");\n      J.set$bottom$x(t1.style, \"0px\");\n    },\n    static: {\"\": \"Balls_RADIUS2,Balls_LT_GRAY_BALL_INDEX,Balls_GREEN_BALL_INDEX,Balls_BLUE_BALL_INDEX,Balls_DK_GRAY_BALL_INDEX,Balls_RED_BALL_INDEX,Balls_MD_GRAY_BALL_INDEX,Balls_PNGS\"}\n  },\n  Balls_tick_closure: {\n    \"\": \"Closure:10;delta_0\",\n    call$1: function(ball) {\n      return ball.tick$1(this.delta_0);\n    }\n  },\n  Balls_collideBalls_closure: {\n    \"\": \"Closure:10;this_0,delta_1\",\n    call$1: function(b0) {\n      var t1 = this.this_0;\n      H.IterableMixinWorkaround_forEach(t1.balls, new Q.Balls_collideBalls__closure(t1, this.delta_1, b0));\n    }\n  },\n  Balls_collideBalls__closure: {\n    \"\": \"Closure:10;this_2,delta_3,b0_4\",\n    call$1: function(b1) {\n      var t1, t2, t3, t4, t5, dx, dy, d2, t6, t7, t8, t9, t10, ndx, ndy, d, impactSpeed;\n      t1 = this.b0_4;\n      t2 = J.getInterceptor$x(t1);\n      t3 = t2.get$x(t1);\n      t4 = J.getInterceptor$x(b1);\n      t5 = t4.get$x(b1);\n      if (typeof t3 !== \"number\")\n        return t3.$sub();\n      if (typeof t5 !== \"number\")\n        return H.iae(t5);\n      dx = Math.abs(t3 - t5);\n      t5 = t2.get$y(t1);\n      t3 = t4.get$y(b1);\n      if (typeof t5 !== \"number\")\n        return t5.$sub();\n      if (typeof t3 !== \"number\")\n        return H.iae(t3);\n      dy = Math.abs(t5 - t3);\n      d2 = dx * dx + dy * dy;\n      if (d2 < 196) {\n        t3 = this.delta_3;\n        t2 = t2.get$x(t1);\n        t5 = t1.get$vx();\n        if (typeof t2 !== \"number\")\n          return t2.$add();\n        t6 = t1.y;\n        t7 = t1.vy;\n        if (typeof t6 !== \"number\")\n          return t6.$add();\n        t4 = t4.get$x(b1);\n        t8 = b1.get$vx();\n        if (typeof t4 !== \"number\")\n          return t4.$add();\n        t9 = b1.y;\n        t10 = b1.vy;\n        if (typeof t9 !== \"number\")\n          return t9.$add();\n        ndx = Math.abs(t2 + t5 * t3 - (t4 + t8 * t3));\n        ndy = Math.abs(t6 + t7 * t3 - (t9 + t10 * t3));\n        if (ndx * ndx + ndy * ndy > d2)\n          return;\n        d = Math.sqrt(d2);\n        if (d === 0)\n          return;\n        dx /= d;\n        dy /= d;\n        t2 = t1.get$vx();\n        impactSpeed = (t2 - b1.vx) * dx + (t1.vy - b1.vy) * dy;\n        t3 = dx * impactSpeed;\n        t1.vx = t2 - t3;\n        t2 = dy * impactSpeed;\n        t1.vy = t1.vy - t2;\n        b1.vx = b1.vx + t3;\n        b1.vy = b1.vy + t2;\n      }\n    }\n  },\n  Ball: {\n    \"\": \"Object;root,elem,x>,y>,vx<,vy,ax,ay,age\",\n    tick$1: function(delta) {\n      var t1, t2, t3, t4;\n      t1 = this.vx + this.ax * delta;\n      this.vx = t1;\n      t2 = this.vy + this.ay * delta;\n      this.vy = t2;\n      t3 = this.x;\n      if (typeof t3 !== \"number\")\n        return t3.$add();\n      t1 = t3 + t1 * delta;\n      this.x = t1;\n      t3 = this.y;\n      if (typeof t3 !== \"number\")\n        return t3.$add();\n      t3 += t2 * delta;\n      this.y = t3;\n      if (!(t1 < 14)) {\n        t4 = window.innerWidth;\n        if (typeof t4 !== \"number\")\n          return H.iae(t4);\n        t4 = t1 > t4;\n      } else\n        t4 = true;\n      if (t4) {\n        t1 = this.elem;\n        t2 = t1.parentNode;\n        if (t2 != null)\n          t2.removeChild(t1);\n        return true;\n      }\n      t4 = window.innerHeight;\n      if (typeof t4 !== \"number\")\n        return H.iae(t4);\n      if (t3 > t4) {\n        t3 = window.innerHeight;\n        t3.toString;\n        this.y = t3;\n        this.vy = t2 * -0.8;\n        t2 = t3;\n      } else\n        t2 = t3;\n      t3 = this.elem;\n      if (typeof t2 !== \"number\")\n        return t2.$sub();\n      Q.setElementPosition(t3, t1 - 14, t2 - 14);\n      return false;\n    },\n    Ball$4: function(root, x, y, color) {\n      var t1;\n      if (color >= 7)\n        return H.ioore(C.List_8eb, color);\n      t1 = W.ImageElement_ImageElement(null, C.List_8eb[color], null);\n      this.elem = t1;\n      J.set$position$x(t1.style, \"absolute\");\n      Q.setElementPosition(this.elem, this.x, this.y);\n      this.root.appendChild(this.elem);\n      this.ax = 0;\n      this.ay = 400;\n      this.vx = Q.Ball_randomVelocity();\n      this.vy = Q.Ball_randomVelocity();\n    },\n    static: {\"\": \"Ball_GRAVITY,Ball_RESTITUTION,Ball_MIN_VELOCITY,Ball_INIT_VELOCITY,Ball_RADIUS,Ball_random\", Ball_randomVelocity: function() {\n        var t1 = $.Ball_random;\n        if (t1 == null) {\n          $.Ball_random = C.C__JSRandom;\n          t1 = C.C__JSRandom;\n        }\n        return (t1.nextDouble$0() - 0.5) * 800;\n      }}\n  },\n  CountDownClock: {\n    \"\": \"Object;hours,minutes,seconds,displayedHour,displayedMinute,displayedSecond,balls\",\n    tick$1: [function(time) {\n      var t1, t2;\n      this.updateTime$1(P.DateTime$_now());\n      this.balls.tick$1(time);\n      t1 = window;\n      t2 = this.get$tick();\n      C.Window_methods._ensureRequestAnimationFrame$0(t1);\n      C.Window_methods._requestAnimationFrame$1(t1, W._wrapZone(t2));\n    }, \"call$1\", \"get$tick\", 2, 0, 13],\n    updateTime$1: function(now) {\n      if (H.Primitives_getHours(now) !== this.displayedHour) {\n        this.setDigits$2(this.pad2$1(H.Primitives_getHours(now)), this.hours);\n        this.displayedHour = H.Primitives_getHours(now);\n      }\n      if (H.Primitives_getMinutes(now) !== this.displayedMinute) {\n        this.setDigits$2(this.pad2$1(H.Primitives_getMinutes(now)), this.minutes);\n        this.displayedMinute = H.Primitives_getMinutes(now);\n      }\n      if (H.Primitives_getSeconds(now) !== this.displayedSecond) {\n        this.setDigits$2(this.pad2$1(H.Primitives_getSeconds(now)), this.seconds);\n        this.displayedSecond = H.Primitives_getSeconds(now);\n      }\n    },\n    setDigits$2: function(digits, numbers) {\n      var t1, i, t2, digit;\n      for (t1 = digits.length, i = 0; i < 2; ++i) {\n        if (i >= t1)\n          H.throwExpression(P.RangeError$value(i));\n        t2 = digits.charCodeAt(i);\n        digit = t2 - \"0\".charCodeAt(0);\n        t2 = numbers[i];\n        if (digit < 0 || digit >= 10)\n          return H.ioore(C.List_e3I, digit);\n        t2.setPixels$1(C.List_e3I[digit]);\n      }\n    },\n    pad2$1: function(number) {\n      if (number < 10)\n        return \"0\" + number;\n      return \"\" + number;\n    },\n    createNumbers$3: function($parent, width, height) {\n      var root, x, y, t1, i, t2;\n      root = document.createElement(\"div\", null);\n      J.set$position$x(root.style, \"relative\");\n      J.set$textAlign$x(root.style, \"center\");\n      document.querySelector(\"#canvas-content\").appendChild(root);\n      if (typeof width !== \"number\")\n        return width.$sub();\n      x = (width - 627) / 2;\n      if (typeof height !== \"number\")\n        return height.$sub();\n      y = (height - 133) / 3;\n      for (t1 = this.hours, i = 0; i < 2; ++i) {\n        t2 = Q.ClockNumber$(this, x, 2);\n        t1[i] = t2;\n        root.appendChild(t2.root);\n        t2 = t1[i].root;\n        J.set$left$x(t2.style, \"\" + x + \"px\");\n        J.set$top$x(t2.style, \"\" + y + \"px\");\n        x += 95;\n      }\n      root.appendChild(Q.Colon$(x, y).root);\n      x += 38;\n      for (t1 = this.minutes, i = 0; i < 2; ++i) {\n        t2 = Q.ClockNumber$(this, x, 5);\n        t1[i] = t2;\n        root.appendChild(t2.root);\n        t2 = t1[i].root;\n        J.set$left$x(t2.style, \"\" + x + \"px\");\n        J.set$top$x(t2.style, \"\" + y + \"px\");\n        x += 95;\n      }\n      root.appendChild(Q.Colon$(x, y).root);\n      x += 38;\n      for (t1 = this.seconds, i = 0; i < 2; ++i) {\n        t2 = Q.ClockNumber$(this, x, 1);\n        t1[i] = t2;\n        root.appendChild(t2.root);\n        t2 = t1[i].root;\n        J.set$left$x(t2.style, \"\" + x + \"px\");\n        J.set$top$x(t2.style, \"\" + y + \"px\");\n        x += 95;\n      }\n    },\n    CountDownClock$0: function() {\n      var $parent, t1, t2;\n      $parent = document.querySelector(\"#canvas-content\");\n      this.createNumbers$3($parent, $parent.clientWidth, $parent.clientHeight);\n      this.updateTime$1(P.DateTime$_now());\n      t1 = window;\n      t2 = this.get$tick();\n      C.Window_methods._ensureRequestAnimationFrame$0(t1);\n      C.Window_methods._requestAnimationFrame$1(t1, W._wrapZone(t2));\n    },\n    static: {\"\": \"CountDownClock_NUMBER_SPACING,CountDownClock_BALL_WIDTH,CountDownClock_BALL_HEIGHT\"}\n  },\n  ClockNumber: {\n    \"\": \"Object;app,root,imgs,pixels,ballColor\",\n    setPixels$1: function(px) {\n      var t1, y, x, img, t2;\n      for (t1 = this.ballColor, y = 0; y < 7; ++y)\n        for (x = 0; x < 4; ++x) {\n          img = this.imgs[y][x];\n          t2 = this.pixels;\n          if (t2 != null)\n            if (t2[y][x] !== 0 && px[y][x] === 0)\n              P.scheduleMicrotask(new Q.ClockNumber_setPixels_closure(this, img));\n          if (px[y][x] !== 0) {\n            if (t1 >= 7)\n              return H.ioore(C.List_8eb, t1);\n            t2 = C.List_8eb[t1];\n          } else\n            t2 = \"images/ball-c9c9c9.png\";\n          J.set$src$x(img, t2);\n        }\n      this.pixels = px;\n    },\n    ClockNumber$3: function(app, pos, ballColor) {\n      var t1, y, t2, x;\n      this.imgs = H.setRuntimeTypeInfo(Array(7), [[J.JSArray, W.ImageElement]]);\n      t1 = document.createElement(\"div\", null);\n      this.root = t1;\n      J.set$position$x(t1.style, \"absolute\");\n      Q.setElementPosition(this.root, pos, 0);\n      for (y = 0; y < 7; ++y) {\n        t1 = this.imgs;\n        t2 = Array(4);\n        t2.$builtinTypeInfo = [W.ImageElement];\n        t1[y] = t2;\n      }\n      for (y = 0; y < 7; ++y)\n        for (t1 = y * 19, x = 0; x < 4; ++x) {\n          this.imgs[y][x] = W.ImageElement_ImageElement(null, null, null);\n          t2 = this.root;\n          t2.toString;\n          t2.appendChild(this.imgs[y][x]);\n          J.set$position$x(this.imgs[y][x].style, \"absolute\");\n          t2 = this.imgs[y][x];\n          J.set$left$x(t2.style, \"\" + x * 19 + \"px\");\n          J.set$top$x(t2.style, \"\" + t1 + \"px\");\n        }\n    },\n    static: {\"\": \"ClockNumber_WIDTH,ClockNumber_HEIGHT\", ClockNumber$: function(app, pos, ballColor) {\n        var t1 = new Q.ClockNumber(app, null, null, null, ballColor);\n        t1.ClockNumber$3(app, pos, ballColor);\n        return t1;\n      }}\n  },\n  ClockNumber_setPixels_closure: {\n    \"\": \"Closure:8;this_0,img_1\",\n    call$0: function() {\n      var r, t1, absx, absy, t2, t3, t4;\n      r = this.img_1.getBoundingClientRect();\n      t1 = J.getInterceptor$x(r);\n      absx = t1.get$left(r);\n      absy = t1.get$top(r);\n      t1 = this.this_0;\n      t2 = t1.app.balls;\n      t3 = t2.root;\n      t4 = new Q.Ball(t3, null, absx, absy, null, null, null, null, null);\n      t4.Ball$4(t3, absx, absy, t1.ballColor);\n      t2.balls.push(t4);\n    }\n  },\n  Colon: {\n    \"\": \"Object;root\",\n    Colon$2: function(xpos, ypos) {\n      var t1, dot;\n      t1 = document.createElement(\"div\", null);\n      this.root = t1;\n      J.set$position$x(t1.style, \"absolute\");\n      Q.setElementPosition(this.root, xpos, ypos);\n      dot = W.ImageElement_ImageElement(null, \"images/ball-b6b4b5.png\", null);\n      this.root.appendChild(dot);\n      J.set$position$x(dot.style, \"absolute\");\n      Q.setElementPosition(dot, 0, 38);\n      dot = W.ImageElement_ImageElement(null, \"images/ball-b6b4b5.png\", null);\n      this.root.appendChild(dot);\n      J.set$position$x(dot.style, \"absolute\");\n      Q.setElementPosition(dot, 0, 76);\n    },\n    static: {Colon$: function(xpos, ypos) {\n        var t1 = new Q.Colon(null);\n        t1.Colon$2(xpos, ypos);\n        return t1;\n      }}\n  }\n},\n1],\n[\"dart._collection.dev\", \"dart:_collection-dev\", , H, {\n  \"\": \"\",\n  IterableMixinWorkaround_forEach: function(iterable, f) {\n    var t1;\n    for (t1 = new H.ListIterator(iterable, iterable.length, 0, null); t1.moveNext$0();)\n      f.call$1(t1._dev$_current);\n  },\n  IterableMixinWorkaround_removeWhereList: function(list, test) {\n    var retained, $length, t1, i, element;\n    retained = [];\n    $length = list.length;\n    for (t1 = $length, i = 0; i < $length; ++i) {\n      if (i >= t1)\n        return H.ioore(list, i);\n      element = list[i];\n      if (test.call$1(element) !== true)\n        retained.push(element);\n      t1 = list.length;\n      if ($length !== t1)\n        throw H.wrapException(P.ConcurrentModificationError$(list));\n    }\n    t1 = retained.length;\n    if (t1 === $length)\n      return;\n    C.JSArray_methods.set$length(list, t1);\n    for (i = 0; i < retained.length; ++i)\n      C.JSArray_methods.$indexSet(list, i, retained[i]);\n  },\n  IterableMixinWorkaround_toStringIterable: function(iterable, leftDelimiter, rightDelimiter) {\n    var result, i, t1;\n    for (i = 0; t1 = $.get$IterableMixinWorkaround__toStringList(), i < t1.length; ++i)\n      if (t1[i] === iterable)\n        return H.S(leftDelimiter) + \"...\" + H.S(rightDelimiter);\n    result = P.StringBuffer$(\"\");\n    try {\n      $.get$IterableMixinWorkaround__toStringList().push(iterable);\n      result.write$1(leftDelimiter);\n      result.writeAll$2(iterable, \", \");\n      result.write$1(rightDelimiter);\n    } finally {\n      t1 = $.get$IterableMixinWorkaround__toStringList();\n      if (0 >= t1.length)\n        return H.ioore(t1, 0);\n      t1.pop();\n    }\n    return result.get$_contents();\n  },\n  IterableMixinWorkaround_setRangeList: function(list, start, end, from, skipCount) {\n    var $length;\n    if (start < 0 || start > list.length)\n      H.throwExpression(P.RangeError$range(start, 0, list.length));\n    if (end < start || end > list.length)\n      H.throwExpression(P.RangeError$range(end, start, list.length));\n    $length = end - start;\n    if ($length === 0)\n      return;\n    if (skipCount + $length > from.length)\n      throw H.wrapException(P.StateError$(\"Not enough elements\"));\n    H.Lists_copy(from, skipCount, list, start, $length);\n  },\n  Lists_copy: function(src, srcStart, dst, dstStart, count) {\n    var i, j, t1, t2;\n    if (srcStart < dstStart)\n      for (i = srcStart + count - 1, j = dstStart + count - 1, t1 = src.length; i >= srcStart; --i, --j) {\n        if (i >= t1)\n          return H.ioore(src, i);\n        C.JSArray_methods.$indexSet(dst, j, src[i]);\n      }\n    else\n      for (t1 = srcStart + count, t2 = src.length, j = dstStart, i = srcStart; i < t1; ++i, ++j) {\n        if (i >= t2)\n          return H.ioore(src, i);\n        C.JSArray_methods.$indexSet(dst, j, src[i]);\n      }\n  },\n  Symbol_getName: function(symbol) {\n    return symbol.get$_name();\n  },\n  ListIterator: {\n    \"\": \"Object;_iterable,_dev$_length,_index,_dev$_current\",\n    get$current: function() {\n      return this._dev$_current;\n    },\n    moveNext$0: function() {\n      var t1, t2, $length, t3;\n      t1 = this._iterable;\n      t2 = J.getInterceptor$asx(t1);\n      $length = t2.get$length(t1);\n      if (this._dev$_length !== $length)\n        throw H.wrapException(P.ConcurrentModificationError$(t1));\n      t3 = this._index;\n      if (t3 >= $length) {\n        this._dev$_current = null;\n        return false;\n      }\n      this._dev$_current = t2.elementAt$1(t1, t3);\n      this._index = this._index + 1;\n      return true;\n    }\n  },\n  MappedIterable: {\n    \"\": \"IterableBase;_iterable,_f\",\n    get$iterator: function(_) {\n      var t1 = this._iterable;\n      t1 = new H.MappedIterator(null, t1.get$iterator(t1), this._f);\n      t1.$builtinTypeInfo = this.$builtinTypeInfo;\n      return t1;\n    },\n    get$length: function(_) {\n      var t1 = this._iterable;\n      return t1.get$length(t1);\n    },\n    $asIterableBase: function($S, $T) {\n      return [$T];\n    },\n    static: {MappedIterable_MappedIterable: function(iterable, $function, $S, $T) {\n        return H.setRuntimeTypeInfo(new H.EfficientLengthMappedIterable(iterable, $function), [$S, $T]);\n      }}\n  },\n  EfficientLengthMappedIterable: {\n    \"\": \"MappedIterable;_iterable,_f\",\n    $asMappedIterable: null\n  },\n  MappedIterator: {\n    \"\": \"Iterator;_dev$_current,_iterator,_f\",\n    _f$1: function(arg0) {\n      return this._f.call$1(arg0);\n    },\n    moveNext$0: function() {\n      var t1 = this._iterator;\n      if (t1.moveNext$0()) {\n        this._dev$_current = this._f$1(t1.get$current());\n        return true;\n      }\n      this._dev$_current = null;\n      return false;\n    },\n    get$current: function() {\n      return this._dev$_current;\n    },\n    $asIterator: function($S, $T) {\n      return [$T];\n    }\n  },\n  FixedLengthListMixin: {\n    \"\": \"Object;\"\n  }\n}],\n[\"dart._js_names\", \"dart:_js_names\", , H, {\n  \"\": \"\",\n  extractKeys: function(victim) {\n    var t1 = H.setRuntimeTypeInfo((function(victim, hasOwnProperty) {\n  var result = [];\n  for (var key in victim) {\n    if (hasOwnProperty.call(victim, key)) result.push(key);\n  }\n  return result;\n})(victim, Object.prototype.hasOwnProperty), [null]);\n    t1.fixed$length = init;\n    return t1;\n  }\n}],\n[\"dart.async\", \"dart:async\", , P, {\n  \"\": \"\",\n  _invokeErrorHandler: function(errorHandler, error, stackTrace) {\n    var t1 = H.getDynamicRuntimeType();\n    t1 = H.buildFunctionType(t1, [t1, t1])._isTest$1(errorHandler);\n    if (t1)\n      return errorHandler.call$2(error, stackTrace);\n    else\n      return errorHandler.call$1(error);\n  },\n  _registerErrorHandler: function(errorHandler, zone) {\n    var t1 = H.getDynamicRuntimeType();\n    t1 = H.buildFunctionType(t1, [t1, t1])._isTest$1(errorHandler);\n    zone.toString;\n    if (t1)\n      return errorHandler;\n    else\n      return errorHandler;\n  },\n  _asyncRunCallback: [function() {\n    var callback, t1, exception, milliseconds;\n    for (; t1 = $.get$_asyncCallbacks(), t1._head !== t1._tail;) {\n      callback = t1.removeFirst$0();\n      try {\n        callback.call$0();\n      } catch (exception) {\n        H.unwrapException(exception);\n        milliseconds = C.JSInt_methods._tdivFast$1(C.Duration_0._duration, 1000);\n        H.TimerImpl$(milliseconds < 0 ? 0 : milliseconds, P._asyncRunCallback$closure());\n        throw exception;\n      }\n\n    }\n    $._callbacksAreEnqueued = false;\n  }, \"call$0\", \"_asyncRunCallback$closure\", 0, 0, 0],\n  _scheduleAsyncCallback: function(callback) {\n    $.get$_asyncCallbacks()._add$1(callback);\n    if (!$._callbacksAreEnqueued) {\n      P._createTimer(C.Duration_0, P._asyncRunCallback$closure());\n      $._callbacksAreEnqueued = true;\n    }\n  },\n  scheduleMicrotask: function(callback) {\n    var t1, f, milliseconds;\n    t1 = $.Zone__current;\n    if (t1 === C.C__RootZone) {\n      t1.toString;\n      f = C.C__RootZone !== t1 ? t1.bindCallback$1(callback) : callback;\n      $.get$_asyncCallbacks()._add$1(f);\n      if (!$._callbacksAreEnqueued) {\n        milliseconds = C.JSInt_methods._tdivFast$1(C.Duration_0._duration, 1000);\n        H.TimerImpl$(milliseconds < 0 ? 0 : milliseconds, P._asyncRunCallback$closure());\n        $._callbacksAreEnqueued = true;\n      }\n      return;\n    }\n    f = t1.bindCallback$2$runGuarded(callback, true);\n    if (C.C__RootZone !== t1)\n      f = t1.bindCallback$1(f);\n    $.get$_asyncCallbacks()._add$1(f);\n    if (!$._callbacksAreEnqueued) {\n      milliseconds = C.JSInt_methods._tdivFast$1(C.Duration_0._duration, 1000);\n      H.TimerImpl$(milliseconds < 0 ? 0 : milliseconds, P._asyncRunCallback$closure());\n      $._callbacksAreEnqueued = true;\n    }\n  },\n  StreamController_StreamController: function(onCancel, onListen, onPause, onResume, sync, $T) {\n    return sync ? H.setRuntimeTypeInfo(new P._SyncStreamController(onListen, onPause, onResume, onCancel, null, 0, null), [$T]) : H.setRuntimeTypeInfo(new P._AsyncStreamController(onListen, onPause, onResume, onCancel, null, 0, null), [$T]);\n  },\n  _runGuarded: function(notificationHandler) {\n    var result, e, s, t1, t2, exception;\n    if (notificationHandler == null)\n      return;\n    try {\n      result = notificationHandler.call$0();\n      t1 = result;\n      t2 = J.getInterceptor(t1);\n      if (typeof t1 === \"object\" && t1 !== null && !!t2.$isFuture)\n        return result;\n      return;\n    } catch (exception) {\n      t1 = H.unwrapException(exception);\n      e = t1;\n      s = new H._StackTrace(exception, null);\n      t1 = $.Zone__current;\n      t1.toString;\n      P._rootHandleUncaughtError(t1, null, t1, e, s);\n    }\n\n  },\n  _nullDataHandler: [function(value) {\n  }, \"call$1\", \"_nullDataHandler$closure\", 2, 0, 1],\n  _nullErrorHandler: [function(error, stackTrace) {\n    var t1 = $.Zone__current;\n    t1.toString;\n    P._rootHandleUncaughtError(t1, null, t1, error, stackTrace);\n  }, function(error) {\n    return P._nullErrorHandler(error, null);\n  }, null, \"call$2\", \"call$1\", \"_nullErrorHandler$closure\", 2, 2, 2, 3],\n  _nullDoneHandler: [function() {\n    return;\n  }, \"call$0\", \"_nullDoneHandler$closure\", 0, 0, 0],\n  _runUserCode: function(userCode, onSuccess, onError) {\n    var e, s, exception, t1;\n    try {\n      onSuccess.call$1(userCode.call$0());\n    } catch (exception) {\n      t1 = H.unwrapException(exception);\n      e = t1;\n      s = new H._StackTrace(exception, null);\n      onError.call$2(e, s);\n    }\n\n  },\n  _cancelAndError: function(subscription, future, error, stackTrace) {\n    var cancelFuture, t1;\n    cancelFuture = subscription.cancel$0();\n    t1 = J.getInterceptor(cancelFuture);\n    if (typeof cancelFuture === \"object\" && cancelFuture !== null && !!t1.$isFuture)\n      cancelFuture.whenComplete$1(new P._cancelAndError_closure(future, error, stackTrace));\n    else\n      future._completeError$2(error, stackTrace);\n  },\n  _cancelAndErrorClosure: function(subscription, future) {\n    return new P._cancelAndErrorClosure_closure(subscription, future);\n  },\n  Timer_Timer: function(duration, callback) {\n    var t1 = $.Zone__current;\n    if (t1 === C.C__RootZone) {\n      t1.toString;\n      return P._rootCreateTimer(t1, null, t1, duration, callback);\n    }\n    return P._rootCreateTimer(t1, null, t1, duration, t1.bindCallback$2$runGuarded(callback, true));\n  },\n  _createTimer: function(duration, callback) {\n    var milliseconds = C.JSInt_methods._tdivFast$1(duration._duration, 1000);\n    return H.TimerImpl$(milliseconds < 0 ? 0 : milliseconds, callback);\n  },\n  _rootHandleUncaughtError: function($self, $parent, zone, error, stackTrace) {\n    P._rootRun($self, null, $self, new P._rootHandleUncaughtError_closure(error, stackTrace));\n  },\n  _rootRun: function($self, $parent, zone, f) {\n    var old, t1, t2;\n    t1 = $.Zone__current;\n    t2 = zone;\n    if (t1 == null ? t2 == null : t1 === t2)\n      return f.call$0();\n    old = t1;\n    try {\n      $.Zone__current = zone;\n      t1 = f.call$0();\n      return t1;\n    } finally {\n      $.Zone__current = old;\n    }\n  },\n  _rootRunUnary: function($self, $parent, zone, f, arg) {\n    var old, t1, t2;\n    t1 = $.Zone__current;\n    t2 = zone;\n    if (t1 == null ? t2 == null : t1 === t2)\n      return f.call$1(arg);\n    old = t1;\n    try {\n      $.Zone__current = zone;\n      t1 = f.call$1(arg);\n      return t1;\n    } finally {\n      $.Zone__current = old;\n    }\n  },\n  _rootScheduleMicrotask: function($self, $parent, zone, f) {\n    P._scheduleAsyncCallback(C.C__RootZone !== zone ? zone.bindCallback$1(f) : f);\n  },\n  _rootCreateTimer: function($self, $parent, zone, duration, callback) {\n    return P._createTimer(duration, C.C__RootZone !== zone ? zone.bindCallback$1(callback) : callback);\n  },\n  _AsyncError: {\n    \"\": \"Object;error>,stackTrace<\",\n    $isError: true\n  },\n  Future: {\n    \"\": \"Object;\",\n    $isFuture: true\n  },\n  _Future: {\n    \"\": \"Object;_state,_zone<,_resultOrListeners,_nextListener<,_onValueCallback,_errorTestCallback,_onErrorCallback,_whenCompleteActionCallback\",\n    get$_isComplete: function() {\n      return this._state >= 4;\n    },\n    get$_hasError: function() {\n      return this._state === 8;\n    },\n    set$_isChained: function(value) {\n      if (value)\n        this._state = 2;\n      else\n        this._state = 0;\n    },\n    get$_onValue: function() {\n      return this._state === 2 ? null : this._onValueCallback;\n    },\n    _onValue$1: function(arg0) {\n      return this.get$_onValue().call$1(arg0);\n    },\n    get$_whenCompleteAction: function() {\n      return this._state === 2 ? null : this._whenCompleteActionCallback;\n    },\n    _whenCompleteAction$0: function() {\n      return this.get$_whenCompleteAction().call$0();\n    },\n    then$2$onError: function(f, onError) {\n      var t1, result;\n      t1 = $.Zone__current;\n      t1.toString;\n      result = H.setRuntimeTypeInfo(new P._Future(0, t1, null, null, f, null, P._registerErrorHandler(onError, t1), null), [null]);\n      this._addListener$1(result);\n      return result;\n    },\n    whenComplete$1: function(action) {\n      var t1, result;\n      t1 = $.Zone__current;\n      t1.toString;\n      result = new P._Future(0, t1, null, null, null, null, null, action);\n      result.$builtinTypeInfo = this.$builtinTypeInfo;\n      this._addListener$1(result);\n      return result;\n    },\n    get$_async$_value: function() {\n      return this._resultOrListeners;\n    },\n    get$_error: function() {\n      return this._resultOrListeners;\n    },\n    _setValue$1: function(value) {\n      this._state = 4;\n      this._resultOrListeners = value;\n    },\n    _setError$2: function(error, stackTrace) {\n      this._state = 8;\n      this._resultOrListeners = new P._AsyncError(error, stackTrace);\n    },\n    _addListener$1: function(listener) {\n      var t1;\n      if (this._state >= 4) {\n        t1 = this._zone;\n        t1.toString;\n        P._rootScheduleMicrotask(t1, null, t1, new P._Future__addListener_closure(this, listener));\n      } else {\n        listener._nextListener = this._resultOrListeners;\n        this._resultOrListeners = listener;\n      }\n    },\n    _removeListeners$0: function() {\n      var current, prev, next;\n      current = this._resultOrListeners;\n      this._resultOrListeners = null;\n      for (prev = null; current != null; prev = current, current = next) {\n        next = current.get$_nextListener();\n        current._nextListener = prev;\n      }\n      return prev;\n    },\n    _complete$1: function(value) {\n      var t1, listeners;\n      t1 = J.getInterceptor(value);\n      if (typeof value === \"object\" && value !== null && !!t1.$isFuture) {\n        P._Future__chainFutures(value, this);\n        return;\n      }\n      listeners = this._removeListeners$0();\n      this._setValue$1(value);\n      P._Future__propagateToListeners(this, listeners);\n    },\n    _completeError$2: [function(error, stackTrace) {\n      var listeners = this._removeListeners$0();\n      this._setError$2(error, stackTrace);\n      P._Future__propagateToListeners(this, listeners);\n    }, function(error) {\n      return this._completeError$2(error, null);\n    }, \"_completeError$1\", \"call$2\", \"call$1\", \"get$_completeError\", 2, 2, 2, 3],\n    _asyncComplete$1: function(value) {\n      var t1;\n      if (this._state !== 0)\n        H.throwExpression(new P.StateError(\"Future already completed\"));\n      this._state = 1;\n      t1 = this._zone;\n      t1.toString;\n      P._rootScheduleMicrotask(t1, null, t1, new P._Future__asyncComplete_closure(this, value));\n    },\n    $is_Future: true,\n    $isFuture: true,\n    static: {\"\": \"_Future__INCOMPLETE,_Future__PENDING_COMPLETE,_Future__CHAINED,_Future__VALUE,_Future__ERROR\", _Future$: function($T) {\n        return H.setRuntimeTypeInfo(new P._Future(0, $.Zone__current, null, null, null, null, null, null), [$T]);\n      }, _Future__chainFutures: function(source, target) {\n        var t1;\n        target._state = 2;\n        t1 = J.getInterceptor(source);\n        if (typeof source === \"object\" && source !== null && !!t1.$is_Future)\n          if (source._state >= 4)\n            P._Future__propagateToListeners(source, target);\n          else\n            source._addListener$1(target);\n        else\n          source.then$2$onError(new P._Future__chainFutures_closure(target), new P._Future__chainFutures_closure0(target));\n      }, _Future__propagateMultipleListeners: function(source, listeners) {\n        var listeners0;\n        do {\n          listeners0 = listeners.get$_nextListener();\n          listeners._nextListener = null;\n          P._Future__propagateToListeners(source, listeners);\n          if (listeners0 != null) {\n            listeners = listeners0;\n            continue;\n          } else\n            break;\n        } while (true);\n      }, _Future__propagateToListeners: function(source, listeners) {\n        var t1, t2, t3, hasError, asyncError, t4, t5, chainSource, listeners0;\n        t1 = {};\n        t1.source_4 = source;\n        for (t2 = source; true;) {\n          t3 = {};\n          if (!t2.get$_isComplete())\n            return;\n          hasError = t1.source_4.get$_hasError();\n          if (hasError && listeners == null) {\n            t2 = t1.source_4;\n            asyncError = t2.get$_error();\n            t2 = t2._zone;\n            t3 = J.get$error$x(asyncError);\n            t4 = asyncError.get$stackTrace();\n            t2.toString;\n            P._rootHandleUncaughtError(t2, null, t2, t3, t4);\n            return;\n          }\n          if (listeners == null)\n            return;\n          if (listeners._nextListener != null) {\n            P._Future__propagateMultipleListeners(t1.source_4, listeners);\n            return;\n          }\n          if (hasError) {\n            t2 = t1.source_4.get$_zone();\n            t4 = listeners._zone;\n            t2.toString;\n            t4.toString;\n            t2 = t4 == null ? t2 != null : t4 !== t2;\n          } else\n            t2 = false;\n          if (t2) {\n            t2 = t1.source_4;\n            asyncError = t2.get$_error();\n            t2 = t2._zone;\n            t3 = J.get$error$x(asyncError);\n            t4 = asyncError.get$stackTrace();\n            t2.toString;\n            P._rootHandleUncaughtError(t2, null, t2, t3, t4);\n            return;\n          }\n          t2 = $.Zone__current;\n          t4 = listeners._zone;\n          if (t2 == null ? t4 != null : t2 !== t4) {\n            t4.toString;\n            P._rootRun(t4, null, t4, new P._Future__propagateToListeners_closure(t1, listeners));\n            return;\n          }\n          t3.listenerHasValue_1 = null;\n          t3.listenerValueOrError_2 = null;\n          t3.isPropagationAborted_3 = false;\n          t4.toString;\n          P._rootRun(t4, null, t4, new P._Future__propagateToListeners_closure0(t1, t3, hasError, listeners));\n          if (t3.isPropagationAborted_3)\n            return;\n          t2 = t3.listenerHasValue_1 === true;\n          if (t2) {\n            t4 = t3.listenerValueOrError_2;\n            t5 = J.getInterceptor(t4);\n            t5 = typeof t4 === \"object\" && t4 !== null && !!t5.$isFuture;\n            t4 = t5;\n          } else\n            t4 = false;\n          if (t4) {\n            chainSource = t3.listenerValueOrError_2;\n            t2 = J.getInterceptor(chainSource);\n            if (typeof chainSource === \"object\" && chainSource !== null && !!t2.$is_Future && chainSource._state >= 4) {\n              listeners._state = 2;\n              t1.source_4 = chainSource;\n              t2 = chainSource;\n              continue;\n            }\n            P._Future__chainFutures(chainSource, listeners);\n            return;\n          }\n          if (t2) {\n            listeners0 = listeners._removeListeners$0();\n            t2 = t3.listenerValueOrError_2;\n            listeners._state = 4;\n            listeners._resultOrListeners = t2;\n          } else {\n            listeners0 = listeners._removeListeners$0();\n            asyncError = t3.listenerValueOrError_2;\n            t2 = J.get$error$x(asyncError);\n            t3 = asyncError.get$stackTrace();\n            listeners._state = 8;\n            listeners._resultOrListeners = new P._AsyncError(t2, t3);\n          }\n          t1.source_4 = listeners;\n          t2 = listeners;\n          listeners = listeners0;\n        }\n      }}\n  },\n  _Future__addListener_closure: {\n    \"\": \"Closure:8;this_0,listener_1\",\n    call$0: function() {\n      P._Future__propagateToListeners(this.this_0, this.listener_1);\n    }\n  },\n  _Future__chainFutures_closure: {\n    \"\": \"Closure:10;target_0\",\n    call$1: function(value) {\n      this.target_0._complete$1(value);\n    }\n  },\n  _Future__chainFutures_closure0: {\n    \"\": \"Closure:14;target_1\",\n    call$2: function(error, stackTrace) {\n      this.target_1._completeError$2(error, stackTrace);\n    },\n    call$1: function(error) {\n      return this.call$2(error, null);\n    }\n  },\n  _Future__asyncComplete_closure: {\n    \"\": \"Closure:8;this_0,value_1\",\n    call$0: function() {\n      this.this_0._complete$1(this.value_1);\n    }\n  },\n  _Future__propagateToListeners_closure: {\n    \"\": \"Closure:8;box_2,listener_3\",\n    call$0: function() {\n      P._Future__propagateToListeners(this.box_2.source_4, this.listener_3);\n    }\n  },\n  _Future__propagateToListeners_closure0: {\n    \"\": \"Closure:8;box_2,box_1,hasError_4,listener_5\",\n    call$0: function() {\n      var t1, value, asyncError, test, matchesTest, errorCallback, e, s, t2, t3, t4, t5, completeResult, exception;\n      t1 = {};\n      try {\n        t2 = this.box_2;\n        if (!this.hasError_4) {\n          value = t2.source_4.get$_async$_value();\n          t3 = this.listener_5;\n          t4 = t3._state === 2 ? null : t3._onValueCallback;\n          t5 = this.box_1;\n          if (t4 != null) {\n            t5.listenerValueOrError_2 = t3._onValue$1(value);\n            t5.listenerHasValue_1 = true;\n          } else {\n            t5.listenerValueOrError_2 = value;\n            t5.listenerHasValue_1 = true;\n          }\n          t4 = t5;\n        } else {\n          asyncError = t2.source_4.get$_error();\n          t3 = this.listener_5;\n          test = t3._state === 2 ? null : t3._errorTestCallback;\n          matchesTest = true;\n          if (test != null)\n            matchesTest = test.call$1(J.get$error$x(asyncError));\n          if (matchesTest === true)\n            t4 = (t3._state === 2 ? null : t3._onErrorCallback) != null;\n          else\n            t4 = false;\n          if (t4) {\n            errorCallback = t3._state === 2 ? null : t3._onErrorCallback;\n            t4 = this.box_1;\n            t4.listenerValueOrError_2 = P._invokeErrorHandler(errorCallback, J.get$error$x(asyncError), asyncError.get$stackTrace());\n            t4.listenerHasValue_1 = true;\n          } else {\n            t4 = this.box_1;\n            t4.listenerValueOrError_2 = asyncError;\n            t4.listenerHasValue_1 = false;\n          }\n        }\n        if ((t3._state === 2 ? null : t3._whenCompleteActionCallback) != null) {\n          completeResult = t3._whenCompleteAction$0();\n          t1.completeResult_0 = completeResult;\n          t5 = J.getInterceptor(completeResult);\n          if (typeof completeResult === \"object\" && completeResult !== null && !!t5.$isFuture) {\n            t3.set$_isChained(true);\n            t1.completeResult_0.then$2$onError(new P._Future__propagateToListeners__closure(t2, t3), new P._Future__propagateToListeners__closure0(t1, t3));\n            t4.isPropagationAborted_3 = true;\n          }\n        }\n      } catch (exception) {\n        t1 = H.unwrapException(exception);\n        e = t1;\n        s = new H._StackTrace(exception, null);\n        if (this.hasError_4) {\n          t1 = J.get$error$x(this.box_2.source_4.get$_error());\n          t2 = e;\n          t2 = t1 == null ? t2 == null : t1 === t2;\n          t1 = t2;\n        } else\n          t1 = false;\n        t2 = this.box_1;\n        if (t1)\n          t2.listenerValueOrError_2 = this.box_2.source_4.get$_error();\n        else\n          t2.listenerValueOrError_2 = new P._AsyncError(e, s);\n        t2.listenerHasValue_1 = false;\n      }\n\n    }\n  },\n  _Future__propagateToListeners__closure: {\n    \"\": \"Closure:10;box_2,listener_6\",\n    call$1: function(ignored) {\n      P._Future__propagateToListeners(this.box_2.source_4, this.listener_6);\n    }\n  },\n  _Future__propagateToListeners__closure0: {\n    \"\": \"Closure:14;box_0,listener_7\",\n    call$2: function(error, stackTrace) {\n      var t1, t2, t3, completeResult;\n      t1 = this.box_0;\n      t2 = t1.completeResult_0;\n      t3 = J.getInterceptor(t2);\n      if (typeof t2 !== \"object\" || t2 === null || !t3.$is_Future) {\n        completeResult = P._Future$(null);\n        t1.completeResult_0 = completeResult;\n        completeResult._setError$2(error, stackTrace);\n      }\n      P._Future__propagateToListeners(t1.completeResult_0, this.listener_7);\n    },\n    call$1: function(error) {\n      return this.call$2(error, null);\n    }\n  },\n  Stream: {\n    \"\": \"Object;\",\n    forEach$1: function(_, action) {\n      var t1, future;\n      t1 = {};\n      future = P._Future$(null);\n      t1.subscription_0 = null;\n      t1.subscription_0 = this.listen$4$cancelOnError$onDone$onError(new P.Stream_forEach_closure(t1, this, action, future), true, new P.Stream_forEach_closure0(future), future.get$_completeError());\n      return future;\n    },\n    get$length: function(_) {\n      var t1, future;\n      t1 = {};\n      future = P._Future$(J.JSInt);\n      t1.count_0 = 0;\n      this.listen$4$cancelOnError$onDone$onError(new P.Stream_length_closure(t1), true, new P.Stream_length_closure0(t1, future), future.get$_completeError());\n      return future;\n    }\n  },\n  Stream_forEach_closure: {\n    \"\": \"Closure;box_0,this_1,action_2,future_3\",\n    call$1: function(element) {\n      P._runUserCode(new P.Stream_forEach__closure(this.action_2, element), new P.Stream_forEach__closure0(), P._cancelAndErrorClosure(this.box_0.subscription_0, this.future_3));\n    },\n    $signature: function() {\n      return H.computeSignature(function(T) {\n        return {func: \"dynamic__T\", args: [T]};\n      }, this.this_1, \"Stream\");\n    }\n  },\n  Stream_forEach__closure: {\n    \"\": \"Closure:8;action_4,element_5\",\n    call$0: function() {\n      return this.action_4.call$1(this.element_5);\n    }\n  },\n  Stream_forEach__closure0: {\n    \"\": \"Closure:10;\",\n    call$1: function(_) {\n    }\n  },\n  Stream_forEach_closure0: {\n    \"\": \"Closure:8;future_6\",\n    call$0: function() {\n      this.future_6._complete$1(null);\n    }\n  },\n  Stream_length_closure: {\n    \"\": \"Closure:10;box_0\",\n    call$1: function(_) {\n      var t1 = this.box_0;\n      t1.count_0 = t1.count_0 + 1;\n    }\n  },\n  Stream_length_closure0: {\n    \"\": \"Closure:8;box_0,future_1\",\n    call$0: function() {\n      this.future_1._complete$1(this.box_0.count_0);\n    }\n  },\n  StreamSubscription: {\n    \"\": \"Object;\"\n  },\n  _StreamController: {\n    \"\": \"Object;\",\n    get$_pendingEvents: function() {\n      if ((this._state & 8) === 0)\n        return this._varData;\n      return this._varData.get$varData();\n    },\n    _ensurePendingEvents$0: function() {\n      if ((this._state & 8) === 0) {\n        var t1 = this._varData;\n        if (t1 == null) {\n          t1 = new P._StreamImplEvents(null, null, 0);\n          this._varData = t1;\n        }\n        return t1;\n      }\n      t1 = this._varData.get$varData();\n      return t1;\n    },\n    get$_subscription: function() {\n      if ((this._state & 8) !== 0)\n        return this._varData.get$varData();\n      return this._varData;\n    },\n    _badEventState$0: function() {\n      if ((this._state & 4) !== 0)\n        return new P.StateError(\"Cannot add event after closing\");\n      return new P.StateError(\"Cannot add event while adding a stream\");\n    },\n    add$1: [function(_, value) {\n      var t1 = this._state;\n      if (t1 >= 4)\n        throw H.wrapException(this._badEventState$0());\n      if ((t1 & 1) !== 0)\n        this._sendData$1(value);\n      else if ((t1 & 3) === 0) {\n        t1 = this._ensurePendingEvents$0();\n        t1.add$1(t1, new P._DelayedData(value, null));\n      }\n    }, \"call$1\", \"get$add\", 2, 0, function() {\n      return H.computeSignature(function(T) {\n        return {func: \"void__T\", void: true, args: [T]};\n      }, this.$receiver, \"_StreamController\");\n    }],\n    close$0: function(_) {\n      var t1, t2;\n      t1 = this._state;\n      if ((t1 & 4) !== 0)\n        return this._doneFuture;\n      if (t1 >= 4)\n        throw H.wrapException(this._badEventState$0());\n      t1 |= 4;\n      this._state = t1;\n      if (this._doneFuture == null) {\n        t2 = P._Future$(null);\n        this._doneFuture = t2;\n        if ((t1 & 2) !== 0)\n          t2._complete$1(null);\n      }\n      t1 = this._state;\n      if ((t1 & 1) !== 0)\n        this._sendDone$0();\n      else if ((t1 & 3) === 0) {\n        t1 = this._ensurePendingEvents$0();\n        t1.add$1(t1, C.C__DelayedDone);\n      }\n      return this._doneFuture;\n    },\n    _subscribe$1: function(cancelOnError) {\n      var t1, t2, subscription, pendingEvents, addState;\n      if ((this._state & 3) !== 0)\n        throw H.wrapException(new P.StateError(\"Stream has already been listened to.\"));\n      t1 = $.Zone__current;\n      t2 = cancelOnError ? 1 : 0;\n      subscription = H.setRuntimeTypeInfo(new P._ControllerSubscription(this, null, null, null, t1, t2, null, null), [null]);\n      pendingEvents = this.get$_pendingEvents();\n      t2 = this._state | 1;\n      this._state = t2;\n      if ((t2 & 8) !== 0) {\n        addState = this._varData;\n        addState.set$varData(subscription);\n        addState.resume$0();\n      } else\n        this._varData = subscription;\n      subscription._setPendingEvents$1(pendingEvents);\n      subscription._guardCallback$1(new P._StreamController__subscribe_closure(this));\n      return subscription;\n    },\n    _recordCancel$1: function(subscription) {\n      var t1, future;\n      if ((this._state & 8) !== 0)\n        this._varData.cancel$0();\n      this._varData = null;\n      this._state = this._state & 4294967286 | 2;\n      t1 = new P._StreamController__recordCancel_complete(this);\n      future = P._runGuarded(this.get$_onCancel());\n      if (future != null)\n        future = future.whenComplete$1(t1);\n      else\n        t1.call$0();\n      return future;\n    }\n  },\n  _StreamController__subscribe_closure: {\n    \"\": \"Closure:8;this_0\",\n    call$0: function() {\n      P._runGuarded(this.this_0.get$_onListen());\n    }\n  },\n  _StreamController__recordCancel_complete: {\n    \"\": \"Closure:0;this_0\",\n    call$0: function() {\n      var t1 = this.this_0._doneFuture;\n      if (t1 != null && t1._state === 0)\n        t1._asyncComplete$1(null);\n    }\n  },\n  _SyncStreamControllerDispatch: {\n    \"\": \"Object;\",\n    _sendData$1: function(data) {\n      this.get$_subscription()._async$_add$1(data);\n    },\n    _sendDone$0: function() {\n      this.get$_subscription()._close$0();\n    }\n  },\n  _AsyncStreamControllerDispatch: {\n    \"\": \"Object;\",\n    _sendData$1: function(data) {\n      this.get$_subscription()._addPending$1(new P._DelayedData(data, null));\n    },\n    _sendDone$0: function() {\n      this.get$_subscription()._addPending$1(C.C__DelayedDone);\n    }\n  },\n  _AsyncStreamController: {\n    \"\": \"_StreamController__AsyncStreamControllerDispatch;_onListen<,_onPause<,_onResume<,_onCancel<,_varData,_state,_doneFuture\",\n    $as_StreamController__AsyncStreamControllerDispatch: null\n  },\n  _StreamController__AsyncStreamControllerDispatch: {\n    \"\": \"_StreamController+_AsyncStreamControllerDispatch;\",\n    $as_StreamController: null\n  },\n  _SyncStreamController: {\n    \"\": \"_StreamController__SyncStreamControllerDispatch;_onListen<,_onPause<,_onResume<,_onCancel<,_varData,_state,_doneFuture\",\n    $as_StreamController__SyncStreamControllerDispatch: null\n  },\n  _StreamController__SyncStreamControllerDispatch: {\n    \"\": \"_StreamController+_SyncStreamControllerDispatch;\",\n    $as_StreamController: null\n  },\n  _ControllerStream: {\n    \"\": \"_StreamImpl;_async$_controller\",\n    _createSubscription$1: function(cancelOnError) {\n      return this._async$_controller._subscribe$1(cancelOnError);\n    },\n    get$hashCode: function(_) {\n      return (H.Primitives_objectHashCode(this._async$_controller) ^ 892482866) >>> 0;\n    },\n    $eq: function(_, other) {\n      var t1;\n      if (other == null)\n        return false;\n      if (this === other)\n        return true;\n      t1 = J.getInterceptor(other);\n      if (typeof other !== \"object\" || other === null || !t1.$is_ControllerStream)\n        return false;\n      return other._async$_controller === this._async$_controller;\n    },\n    $is_ControllerStream: true,\n    $as_StreamImpl: null\n  },\n  _ControllerSubscription: {\n    \"\": \"_BufferingStreamSubscription;_async$_controller,_onData,_onError,_onDone,_zone,_state,_cancelFuture,_pending\",\n    _onCancel$0: function() {\n      return this._async$_controller._recordCancel$1(this);\n    },\n    _onPause$0: [function() {\n      var t1, addState;\n      t1 = this._async$_controller;\n      if ((t1._state & 8) !== 0) {\n        addState = t1._varData;\n        addState.pause$0(addState);\n      }\n      P._runGuarded(t1.get$_onPause());\n    }, \"call$0\", \"get$_onPause\", 0, 0, 0],\n    _onResume$0: [function() {\n      var t1 = this._async$_controller;\n      if ((t1._state & 8) !== 0)\n        t1._varData.resume$0();\n      P._runGuarded(t1.get$_onResume());\n    }, \"call$0\", \"get$_onResume\", 0, 0, 0],\n    $as_BufferingStreamSubscription: null\n  },\n  _EventSink: {\n    \"\": \"Object;\"\n  },\n  _BufferingStreamSubscription: {\n    \"\": \"Object;_onData,_onError,_onDone,_zone<,_state,_cancelFuture,_pending\",\n    _setPendingEvents$1: function(pendingEvents) {\n      if (pendingEvents == null)\n        return;\n      this._pending = pendingEvents;\n      if (!pendingEvents.get$isEmpty(pendingEvents)) {\n        this._state = (this._state | 64) >>> 0;\n        pendingEvents.schedule$1(this);\n      }\n    },\n    onData$1: function(handleData) {\n      this._zone.toString;\n      this._onData = handleData;\n    },\n    onError$1: function(_, handleError) {\n      this._onError = P._registerErrorHandler(handleError, this._zone);\n    },\n    onDone$1: function(handleDone) {\n      this._zone.toString;\n      this._onDone = handleDone;\n    },\n    pause$1: function(_, resumeSignal) {\n      var t1 = this._state;\n      if ((t1 & 8) !== 0)\n        return;\n      this._state = (t1 + 128 | 4) >>> 0;\n      if (t1 < 128 && this._pending != null)\n        this._pending.cancelSchedule$0();\n      if ((t1 & 4) === 0 && (this._state & 32) === 0)\n        this._guardCallback$1(this.get$_onPause());\n    },\n    pause$0: function($receiver) {\n      return this.pause$1($receiver, null);\n    },\n    resume$0: function() {\n      var t1, t2;\n      t1 = this._state;\n      if ((t1 & 8) !== 0)\n        return;\n      if (t1 >= 128) {\n        t1 -= 128;\n        this._state = t1;\n        if (t1 < 128) {\n          if ((t1 & 64) !== 0) {\n            t2 = this._pending;\n            t2 = !t2.get$isEmpty(t2);\n          } else\n            t2 = false;\n          if (t2)\n            this._pending.schedule$1(this);\n          else {\n            t1 = (t1 & 4294967291) >>> 0;\n            this._state = t1;\n            if ((t1 & 32) === 0)\n              this._guardCallback$1(this.get$_onResume());\n          }\n        }\n      }\n    },\n    cancel$0: function() {\n      var t1 = (this._state & 4294967279) >>> 0;\n      this._state = t1;\n      if ((t1 & 8) !== 0)\n        return this._cancelFuture;\n      this._cancel$0();\n      return this._cancelFuture;\n    },\n    _cancel$0: function() {\n      var t1 = (this._state | 8) >>> 0;\n      this._state = t1;\n      if ((t1 & 64) !== 0)\n        this._pending.cancelSchedule$0();\n      if ((this._state & 32) === 0)\n        this._pending = null;\n      this._cancelFuture = this._onCancel$0();\n    },\n    _async$_add$1: function(data) {\n      var t1 = this._state;\n      if ((t1 & 8) !== 0)\n        return;\n      if (t1 < 32)\n        this._sendData$1(data);\n      else\n        this._addPending$1(new P._DelayedData(data, null));\n    },\n    _close$0: function() {\n      var t1 = this._state;\n      if ((t1 & 8) !== 0)\n        return;\n      t1 = (t1 | 2) >>> 0;\n      this._state = t1;\n      if (t1 < 32)\n        this._sendDone$0();\n      else\n        this._addPending$1(C.C__DelayedDone);\n    },\n    _onPause$0: [function() {\n    }, \"call$0\", \"get$_onPause\", 0, 0, 0],\n    _onResume$0: [function() {\n    }, \"call$0\", \"get$_onResume\", 0, 0, 0],\n    _onCancel$0: function() {\n    },\n    _addPending$1: function($event) {\n      var pending, t1;\n      pending = this._pending;\n      if (pending == null) {\n        pending = new P._StreamImplEvents(null, null, 0);\n        this._pending = pending;\n      }\n      pending.add$1(pending, $event);\n      t1 = this._state;\n      if ((t1 & 64) === 0) {\n        t1 = (t1 | 64) >>> 0;\n        this._state = t1;\n        if (t1 < 128)\n          this._pending.schedule$1(this);\n      }\n    },\n    _sendData$1: function(data) {\n      var t1 = this._state;\n      this._state = (t1 | 32) >>> 0;\n      this._zone.runUnaryGuarded$2(this._onData, data);\n      this._state = (this._state & 4294967263) >>> 0;\n      this._checkState$1((t1 & 4) !== 0);\n    },\n    _sendDone$0: function() {\n      var t1, t2, t3;\n      t1 = new P._BufferingStreamSubscription__sendDone_sendDone(this);\n      this._cancel$0();\n      this._state = (this._state | 16) >>> 0;\n      t2 = this._cancelFuture;\n      t3 = J.getInterceptor(t2);\n      if (typeof t2 === \"object\" && t2 !== null && !!t3.$isFuture)\n        t2.whenComplete$1(t1);\n      else\n        t1.call$0();\n    },\n    _guardCallback$1: function(callback) {\n      var t1 = this._state;\n      this._state = (t1 | 32) >>> 0;\n      callback.call$0();\n      this._state = (this._state & 4294967263) >>> 0;\n      this._checkState$1((t1 & 4) !== 0);\n    },\n    _checkState$1: function(wasInputPaused) {\n      var t1, t2, isInputPaused;\n      t1 = this._state;\n      if ((t1 & 64) !== 0) {\n        t2 = this._pending;\n        t2 = t2.get$isEmpty(t2);\n      } else\n        t2 = false;\n      if (t2) {\n        t1 = (t1 & 4294967231) >>> 0;\n        this._state = t1;\n        if ((t1 & 4) !== 0)\n          if (t1 < 128) {\n            t2 = this._pending;\n            t2 = t2 == null || t2.get$isEmpty(t2);\n          } else\n            t2 = false;\n        else\n          t2 = false;\n        if (t2) {\n          t1 = (t1 & 4294967291) >>> 0;\n          this._state = t1;\n        }\n      }\n      for (; true; wasInputPaused = isInputPaused) {\n        if ((t1 & 8) !== 0) {\n          this._pending = null;\n          return;\n        }\n        isInputPaused = (t1 & 4) !== 0;\n        if (wasInputPaused === isInputPaused)\n          break;\n        this._state = (t1 ^ 32) >>> 0;\n        if (isInputPaused)\n          this._onPause$0();\n        else\n          this._onResume$0();\n        t1 = (this._state & 4294967263) >>> 0;\n        this._state = t1;\n      }\n      if ((t1 & 64) !== 0 && t1 < 128)\n        this._pending.schedule$1(this);\n    },\n    static: {\"\": \"_BufferingStreamSubscription__STATE_CANCEL_ON_ERROR,_BufferingStreamSubscription__STATE_CLOSED,_BufferingStreamSubscription__STATE_INPUT_PAUSED,_BufferingStreamSubscription__STATE_CANCELED,_BufferingStreamSubscription__STATE_WAIT_FOR_CANCEL,_BufferingStreamSubscription__STATE_IN_CALLBACK,_BufferingStreamSubscription__STATE_HAS_PENDING,_BufferingStreamSubscription__STATE_PAUSE_COUNT,_BufferingStreamSubscription__STATE_PAUSE_COUNT_SHIFT\"}\n  },\n  _BufferingStreamSubscription__sendDone_sendDone: {\n    \"\": \"Closure:0;this_0\",\n    call$0: function() {\n      var t1, t2;\n      t1 = this.this_0;\n      t2 = t1._state;\n      if ((t2 & 16) === 0)\n        return;\n      t1._state = (t2 | 42) >>> 0;\n      t1._zone.runGuarded$1(t1._onDone);\n      t1._state = (t1._state & 4294967263) >>> 0;\n    }\n  },\n  _StreamImpl: {\n    \"\": \"Stream;\",\n    listen$4$cancelOnError$onDone$onError: function(onData, cancelOnError, onDone, onError) {\n      var subscription = this._createSubscription$1(true === cancelOnError);\n      subscription.onData$1(onData);\n      subscription.onError$1(subscription, onError);\n      subscription.onDone$1(onDone);\n      return subscription;\n    },\n    _createSubscription$1: function(cancelOnError) {\n      var t1, t2;\n      t1 = $.Zone__current;\n      t2 = cancelOnError ? 1 : 0;\n      return new P._BufferingStreamSubscription(null, null, null, t1, t2, null, null);\n    },\n    $asStream: null\n  },\n  _DelayedEvent: {\n    \"\": \"Object;next@\"\n  },\n  _DelayedData: {\n    \"\": \"_DelayedEvent;value,next\",\n    perform$1: function(dispatch) {\n      dispatch._sendData$1(this.value);\n    }\n  },\n  _DelayedDone: {\n    \"\": \"Object;\",\n    perform$1: function(dispatch) {\n      dispatch._sendDone$0();\n    },\n    get$next: function() {\n      return;\n    },\n    set$next: function(_) {\n      throw H.wrapException(P.StateError$(\"No events after a done.\"));\n    }\n  },\n  _PendingEvents: {\n    \"\": \"Object;\",\n    schedule$1: function(dispatch) {\n      var t1 = this._state;\n      if (t1 === 1)\n        return;\n      if (t1 >= 1) {\n        this._state = 1;\n        return;\n      }\n      P.scheduleMicrotask(new P._PendingEvents_schedule_closure(this, dispatch));\n      this._state = 1;\n    },\n    cancelSchedule$0: function() {\n      if (this._state === 1)\n        this._state = 3;\n    }\n  },\n  _PendingEvents_schedule_closure: {\n    \"\": \"Closure:8;this_0,dispatch_1\",\n    call$0: function() {\n      var t1, oldState;\n      t1 = this.this_0;\n      oldState = t1._state;\n      t1._state = 0;\n      if (oldState === 3)\n        return;\n      t1.handleNext$1(this.dispatch_1);\n    }\n  },\n  _StreamImplEvents: {\n    \"\": \"_PendingEvents;firstPendingEvent,lastPendingEvent,_state\",\n    get$isEmpty: function(_) {\n      return this.lastPendingEvent == null;\n    },\n    add$1: function(_, $event) {\n      var t1 = this.lastPendingEvent;\n      if (t1 == null) {\n        this.lastPendingEvent = $event;\n        this.firstPendingEvent = $event;\n      } else {\n        t1.set$next($event);\n        this.lastPendingEvent = $event;\n      }\n    },\n    handleNext$1: function(dispatch) {\n      var $event, t1;\n      $event = this.firstPendingEvent;\n      t1 = $event.get$next();\n      this.firstPendingEvent = t1;\n      if (t1 == null)\n        this.lastPendingEvent = null;\n      $event.perform$1(dispatch);\n    }\n  },\n  _cancelAndError_closure: {\n    \"\": \"Closure:8;future_0,error_1,stackTrace_2\",\n    call$0: function() {\n      return this.future_0._completeError$2(this.error_1, this.stackTrace_2);\n    }\n  },\n  _cancelAndErrorClosure_closure: {\n    \"\": \"Closure:15;subscription_0,future_1\",\n    call$2: function(error, stackTrace) {\n      return P._cancelAndError(this.subscription_0, this.future_1, error, stackTrace);\n    }\n  },\n  _BaseZone: {\n    \"\": \"Object;\",\n    runGuarded$1: function(f) {\n      var e, s, t1, exception;\n      try {\n        t1 = this.run$1(f);\n        return t1;\n      } catch (exception) {\n        t1 = H.unwrapException(exception);\n        e = t1;\n        s = new H._StackTrace(exception, null);\n        return this.handleUncaughtError$2(e, s);\n      }\n\n    },\n    runUnaryGuarded$2: function(f, arg) {\n      var e, s, t1, exception;\n      try {\n        t1 = this.runUnary$2(f, arg);\n        return t1;\n      } catch (exception) {\n        t1 = H.unwrapException(exception);\n        e = t1;\n        s = new H._StackTrace(exception, null);\n        return this.handleUncaughtError$2(e, s);\n      }\n\n    },\n    bindCallback$2$runGuarded: function(f, runGuarded) {\n      var registered = this.registerCallback$1(f);\n      if (runGuarded)\n        return new P._BaseZone_bindCallback_closure(this, registered);\n      else\n        return new P._BaseZone_bindCallback_closure0(this, registered);\n    },\n    bindCallback$1: function(f) {\n      return this.bindCallback$2$runGuarded(f, true);\n    },\n    bindUnaryCallback$2$runGuarded: function(f, runGuarded) {\n      var registered = this.registerUnaryCallback$1(f);\n      if (runGuarded)\n        return new P._BaseZone_bindUnaryCallback_closure(this, registered);\n      else\n        return new P._BaseZone_bindUnaryCallback_closure0(this, registered);\n    }\n  },\n  _BaseZone_bindCallback_closure: {\n    \"\": \"Closure:8;this_0,registered_1\",\n    call$0: function() {\n      return this.this_0.runGuarded$1(this.registered_1);\n    }\n  },\n  _BaseZone_bindCallback_closure0: {\n    \"\": \"Closure:8;this_2,registered_3\",\n    call$0: function() {\n      return this.this_2.run$1(this.registered_3);\n    }\n  },\n  _BaseZone_bindUnaryCallback_closure: {\n    \"\": \"Closure:10;this_0,registered_1\",\n    call$1: function(arg) {\n      return this.this_0.runUnaryGuarded$2(this.registered_1, arg);\n    }\n  },\n  _BaseZone_bindUnaryCallback_closure0: {\n    \"\": \"Closure:10;this_2,registered_3\",\n    call$1: function(arg) {\n      return this.this_2.runUnary$2(this.registered_3, arg);\n    }\n  },\n  _rootHandleUncaughtError_closure: {\n    \"\": \"Closure:8;error_0,stackTrace_1\",\n    call$0: function() {\n      P._scheduleAsyncCallback(new P._rootHandleUncaughtError__closure(this.error_0, this.stackTrace_1));\n    }\n  },\n  _rootHandleUncaughtError__closure: {\n    \"\": \"Closure:8;error_2,stackTrace_3\",\n    call$0: function() {\n      var t1, trace, t2;\n      t1 = this.error_2;\n      P.print(\"Uncaught Error: \" + H.S(t1));\n      trace = this.stackTrace_3;\n      if (trace == null) {\n        t2 = J.getInterceptor(t1);\n        t2 = typeof t1 === \"object\" && t1 !== null && !!t2.$isError;\n      } else\n        t2 = false;\n      if (t2)\n        trace = t1.get$stackTrace();\n      if (trace != null)\n        P.print(\"Stack Trace: \\n\" + H.S(trace) + \"\\n\");\n      throw H.wrapException(t1);\n    }\n  },\n  _RootZone: {\n    \"\": \"_BaseZone;\",\n    $index: function(_, key) {\n      return;\n    },\n    handleUncaughtError$2: function(error, stackTrace) {\n      return P._rootHandleUncaughtError(this, null, this, error, stackTrace);\n    },\n    run$1: function(f) {\n      return P._rootRun(this, null, this, f);\n    },\n    runUnary$2: function(f, arg) {\n      return P._rootRunUnary(this, null, this, f, arg);\n    },\n    registerCallback$1: function(f) {\n      return f;\n    },\n    registerUnaryCallback$1: function(f) {\n      return f;\n    }\n  }\n}],\n[\"dart.collection\", \"dart:collection\", , P, {\n  \"\": \"\",\n  _HashSet__newHashTable: function() {\n    var table = Object.create(null);\n    table[\"<non-identifier-key>\"] = table;\n    delete table[\"<non-identifier-key>\"];\n    return table;\n  },\n  _defaultEquals: [function(a, b) {\n    return J.$eq(a, b);\n  }, \"call$2\", \"_defaultEquals$closure\", 4, 0, 4],\n  _defaultHashCode: [function(a) {\n    return J.get$hashCode$(a);\n  }, \"call$1\", \"_defaultHashCode$closure\", 2, 0, 5],\n  HashMap_HashMap: function(equals, hashCode, isValidKey, $K, $V) {\n    return H.setRuntimeTypeInfo(new P._HashMap(0, null, null, null, null), [$K, $V]);\n  },\n  HashSet_HashSet$identity: function($E) {\n    return H.setRuntimeTypeInfo(new P._IdentityHashSet(0, null, null, null, null), [$E]);\n  },\n  _iterableToString: function(iterable) {\n    var parts, t1;\n    t1 = $.get$_toStringVisiting();\n    if (t1.contains$1(t1, iterable))\n      return \"(...)\";\n    t1 = $.get$_toStringVisiting();\n    t1.add$1(t1, iterable);\n    parts = [];\n    try {\n      P._iterablePartsToStrings(iterable, parts);\n    } finally {\n      t1 = $.get$_toStringVisiting();\n      t1.remove$1(t1, iterable);\n    }\n    t1 = P.StringBuffer$(\"(\");\n    t1.writeAll$2(parts, \", \");\n    t1.write$1(\")\");\n    return t1._contents;\n  },\n  _iterablePartsToStrings: function(iterable, parts) {\n    var it, $length, count, next, ultimateString, penultimateString, penultimate, ultimate, ultimate0, elision;\n    it = iterable.get$iterator(iterable);\n    $length = 0;\n    count = 0;\n    while (true) {\n      if (!($length < 80 || count < 3))\n        break;\n      if (!it.moveNext$0())\n        return;\n      next = H.S(it.get$current());\n      parts.push(next);\n      $length += next.length + 2;\n      ++count;\n    }\n    if (!it.moveNext$0()) {\n      if (count <= 5)\n        return;\n      if (0 >= parts.length)\n        return H.ioore(parts, 0);\n      ultimateString = parts.pop();\n      if (0 >= parts.length)\n        return H.ioore(parts, 0);\n      penultimateString = parts.pop();\n    } else {\n      penultimate = it.get$current();\n      ++count;\n      if (!it.moveNext$0()) {\n        if (count <= 4) {\n          parts.push(H.S(penultimate));\n          return;\n        }\n        ultimateString = H.S(penultimate);\n        if (0 >= parts.length)\n          return H.ioore(parts, 0);\n        penultimateString = parts.pop();\n        $length += ultimateString.length + 2;\n      } else {\n        ultimate = it.get$current();\n        ++count;\n        for (; it.moveNext$0(); penultimate = ultimate, ultimate = ultimate0) {\n          ultimate0 = it.get$current();\n          ++count;\n          if (count > 100) {\n            while (true) {\n              if (!($length > 75 && count > 3))\n                break;\n              if (0 >= parts.length)\n                return H.ioore(parts, 0);\n              $length -= parts.pop().length + 2;\n              --count;\n            }\n            parts.push(\"...\");\n            return;\n          }\n        }\n        penultimateString = H.S(penultimate);\n        ultimateString = H.S(ultimate);\n        $length += ultimateString.length + penultimateString.length + 4;\n      }\n    }\n    if (count > parts.length + 2) {\n      $length += 5;\n      elision = \"...\";\n    } else\n      elision = null;\n    while (true) {\n      if (!($length > 80 && parts.length > 3))\n        break;\n      if (0 >= parts.length)\n        return H.ioore(parts, 0);\n      $length -= parts.pop().length + 2;\n      if (elision == null) {\n        $length += 5;\n        elision = \"...\";\n      }\n    }\n    if (elision != null)\n      parts.push(elision);\n    parts.push(penultimateString);\n    parts.push(ultimateString);\n  },\n  LinkedHashMap_LinkedHashMap: function(equals, hashCode, isValidKey, $K, $V) {\n    return H.setRuntimeTypeInfo(new P._LinkedHashMap(0, null, null, null, null, null, 0), [$K, $V]);\n  },\n  LinkedHashSet_LinkedHashSet: function(equals, hashCode, isValidKey, $E) {\n    return H.setRuntimeTypeInfo(new P._LinkedHashSet(0, null, null, null, null, null, 0), [$E]);\n  },\n  Maps_mapToString: function(m) {\n    var t1, result, i, t2;\n    t1 = {};\n    for (i = 0; t2 = $.get$Maps__toStringList(), i < t2.length; ++i)\n      if (t2[i] === m)\n        return \"{...}\";\n    result = P.StringBuffer$(\"\");\n    try {\n      $.get$Maps__toStringList().push(m);\n      result.write$1(\"{\");\n      t1.first_0 = true;\n      J.forEach$1$ax(m, new P.Maps_mapToString_closure(t1, result));\n      result.write$1(\"}\");\n    } finally {\n      t1 = $.get$Maps__toStringList();\n      if (0 >= t1.length)\n        return H.ioore(t1, 0);\n      t1.pop();\n    }\n    return result.get$_contents();\n  },\n  _HashMap: {\n    \"\": \"Object;_collection$_length,_strings,_nums,_rest,_keys\",\n    get$length: function(_) {\n      return this._collection$_length;\n    },\n    get$keys: function() {\n      return H.setRuntimeTypeInfo(new P.HashMapKeyIterable(this), [H.getTypeArgumentByIndex(this, 0)]);\n    },\n    get$values: function(_) {\n      return H.MappedIterable_MappedIterable(H.setRuntimeTypeInfo(new P.HashMapKeyIterable(this), [H.getTypeArgumentByIndex(this, 0)]), new P._HashMap_values_closure(this), H.getTypeArgumentByIndex(this, 0), H.getTypeArgumentByIndex(this, 1));\n    },\n    $index: function(_, key) {\n      var strings, t1, entry, nums, rest, bucket, index;\n      if (typeof key === \"string\" && key !== \"__proto__\") {\n        strings = this._strings;\n        if (strings == null)\n          t1 = null;\n        else {\n          entry = strings[key];\n          t1 = entry === strings ? null : entry;\n        }\n        return t1;\n      } else if (typeof key === \"number\" && (key & 0x3ffffff) === key) {\n        nums = this._nums;\n        if (nums == null)\n          t1 = null;\n        else {\n          entry = nums[key];\n          t1 = entry === nums ? null : entry;\n        }\n        return t1;\n      } else {\n        rest = this._rest;\n        if (rest == null)\n          return;\n        bucket = rest[this._computeHashCode$1(key)];\n        index = this._findBucketIndex$2(bucket, key);\n        return index < 0 ? null : bucket[index + 1];\n      }\n    },\n    $indexSet: function(_, key, value) {\n      var strings, nums, rest, hash, bucket, index;\n      if (typeof key === \"string\" && key !== \"__proto__\") {\n        strings = this._strings;\n        if (strings == null) {\n          strings = P._HashMap__newHashTable();\n          this._strings = strings;\n        }\n        this._addHashTableEntry$3(strings, key, value);\n      } else if (typeof key === \"number\" && (key & 0x3ffffff) === key) {\n        nums = this._nums;\n        if (nums == null) {\n          nums = P._HashMap__newHashTable();\n          this._nums = nums;\n        }\n        this._addHashTableEntry$3(nums, key, value);\n      } else {\n        rest = this._rest;\n        if (rest == null) {\n          rest = P._HashMap__newHashTable();\n          this._rest = rest;\n        }\n        hash = this._computeHashCode$1(key);\n        bucket = rest[hash];\n        if (bucket == null) {\n          P._HashMap__setTableEntry(rest, hash, [key, value]);\n          this._collection$_length = this._collection$_length + 1;\n          this._keys = null;\n        } else {\n          index = this._findBucketIndex$2(bucket, key);\n          if (index >= 0)\n            bucket[index + 1] = value;\n          else {\n            bucket.push(key, value);\n            this._collection$_length = this._collection$_length + 1;\n            this._keys = null;\n          }\n        }\n      }\n    },\n    forEach$1: function(_, action) {\n      var keys, $length, i, key;\n      keys = this._computeKeys$0();\n      for ($length = keys.length, i = 0; i < $length; ++i) {\n        key = keys[i];\n        action.call$2(key, this.$index(this, key));\n        if (keys !== this._keys)\n          throw H.wrapException(P.ConcurrentModificationError$(this));\n      }\n    },\n    _computeKeys$0: function() {\n      var t1, result, strings, names, entries, index, i, nums, rest, bucket, $length, i0;\n      t1 = this._keys;\n      if (t1 != null)\n        return t1;\n      result = Array(this._collection$_length);\n      result.fixed$length = init;\n      strings = this._strings;\n      if (strings != null) {\n        names = Object.getOwnPropertyNames(strings);\n        entries = names.length;\n        for (index = 0, i = 0; i < entries; ++i) {\n          result[index] = names[i];\n          ++index;\n        }\n      } else\n        index = 0;\n      nums = this._nums;\n      if (nums != null) {\n        names = Object.getOwnPropertyNames(nums);\n        entries = names.length;\n        for (i = 0; i < entries; ++i) {\n          result[index] = +names[i];\n          ++index;\n        }\n      }\n      rest = this._rest;\n      if (rest != null) {\n        names = Object.getOwnPropertyNames(rest);\n        entries = names.length;\n        for (i = 0; i < entries; ++i) {\n          bucket = rest[names[i]];\n          $length = bucket.length;\n          for (i0 = 0; i0 < $length; i0 += 2) {\n            result[index] = bucket[i0];\n            ++index;\n          }\n        }\n      }\n      this._keys = result;\n      return result;\n    },\n    _addHashTableEntry$3: function(table, key, value) {\n      if (table[key] == null) {\n        this._collection$_length = this._collection$_length + 1;\n        this._keys = null;\n      }\n      P._HashMap__setTableEntry(table, key, value);\n    },\n    _computeHashCode$1: function(key) {\n      return J.get$hashCode$(key) & 0x3ffffff;\n    },\n    _findBucketIndex$2: function(bucket, key) {\n      var $length, i;\n      if (bucket == null)\n        return -1;\n      $length = bucket.length;\n      for (i = 0; i < $length; i += 2)\n        if (J.$eq(bucket[i], key))\n          return i;\n      return -1;\n    },\n    $isMap: true,\n    static: {_HashMap__setTableEntry: function(table, key, value) {\n        if (value == null)\n          table[key] = table;\n        else\n          table[key] = value;\n      }, _HashMap__newHashTable: function() {\n        var table = Object.create(null);\n        P._HashMap__setTableEntry(table, \"<non-identifier-key>\", table);\n        delete table[\"<non-identifier-key>\"];\n        return table;\n      }}\n  },\n  _HashMap_values_closure: {\n    \"\": \"Closure:10;this_0\",\n    call$1: function(each) {\n      var t1 = this.this_0;\n      return t1.$index(t1, each);\n    }\n  },\n  HashMapKeyIterable: {\n    \"\": \"IterableBase;_map\",\n    get$length: function(_) {\n      return this._map._collection$_length;\n    },\n    get$iterator: function(_) {\n      var t1 = this._map;\n      return new P.HashMapKeyIterator(t1, t1._computeKeys$0(), 0, null);\n    },\n    forEach$1: function(_, f) {\n      var t1, keys, $length, i;\n      t1 = this._map;\n      keys = t1._computeKeys$0();\n      for ($length = keys.length, i = 0; i < $length; ++i) {\n        f.call$1(keys[i]);\n        if (keys !== t1._keys)\n          throw H.wrapException(P.ConcurrentModificationError$(t1));\n      }\n    },\n    $asIterableBase: null\n  },\n  HashMapKeyIterator: {\n    \"\": \"Object;_map,_keys,_offset,_collection$_current\",\n    get$current: function() {\n      return this._collection$_current;\n    },\n    moveNext$0: function() {\n      var keys, offset, t1;\n      keys = this._keys;\n      offset = this._offset;\n      t1 = this._map;\n      if (keys !== t1._keys)\n        throw H.wrapException(P.ConcurrentModificationError$(t1));\n      else if (offset >= keys.length) {\n        this._collection$_current = null;\n        return false;\n      } else {\n        this._collection$_current = keys[offset];\n        this._offset = offset + 1;\n        return true;\n      }\n    }\n  },\n  _LinkedHashMap: {\n    \"\": \"Object;_collection$_length,_strings,_nums,_rest,_first,_last,_modifications\",\n    get$length: function(_) {\n      return this._collection$_length;\n    },\n    get$keys: function() {\n      return H.setRuntimeTypeInfo(new P.LinkedHashMapKeyIterable(this), [H.getTypeArgumentByIndex(this, 0)]);\n    },\n    get$values: function(_) {\n      return H.MappedIterable_MappedIterable(H.setRuntimeTypeInfo(new P.LinkedHashMapKeyIterable(this), [H.getTypeArgumentByIndex(this, 0)]), new P._LinkedHashMap_values_closure(this), H.getTypeArgumentByIndex(this, 0), H.getTypeArgumentByIndex(this, 1));\n    },\n    containsKey$1: function(key) {\n      var nums, rest;\n      if ((key & 0x3ffffff) === key) {\n        nums = this._nums;\n        if (nums == null)\n          return false;\n        return nums[key] != null;\n      } else {\n        rest = this._rest;\n        if (rest == null)\n          return false;\n        return this._findBucketIndex$2(rest[this._computeHashCode$1(key)], key) >= 0;\n      }\n    },\n    $index: function(_, key) {\n      var strings, cell, nums, rest, bucket, index;\n      if (typeof key === \"string\" && key !== \"__proto__\") {\n        strings = this._strings;\n        if (strings == null)\n          return;\n        cell = strings[key];\n        return cell == null ? null : cell.get$_value();\n      } else if (typeof key === \"number\" && (key & 0x3ffffff) === key) {\n        nums = this._nums;\n        if (nums == null)\n          return;\n        cell = nums[key];\n        return cell == null ? null : cell.get$_value();\n      } else {\n        rest = this._rest;\n        if (rest == null)\n          return;\n        bucket = rest[this._computeHashCode$1(key)];\n        index = this._findBucketIndex$2(bucket, key);\n        if (index < 0)\n          return;\n        return bucket[index].get$_value();\n      }\n    },\n    $indexSet: function(_, key, value) {\n      var strings, nums, rest, hash, bucket, index;\n      if (typeof key === \"string\" && key !== \"__proto__\") {\n        strings = this._strings;\n        if (strings == null) {\n          strings = P._LinkedHashMap__newHashTable();\n          this._strings = strings;\n        }\n        this._addHashTableEntry$3(strings, key, value);\n      } else if (typeof key === \"number\" && (key & 0x3ffffff) === key) {\n        nums = this._nums;\n        if (nums == null) {\n          nums = P._LinkedHashMap__newHashTable();\n          this._nums = nums;\n        }\n        this._addHashTableEntry$3(nums, key, value);\n      } else {\n        rest = this._rest;\n        if (rest == null) {\n          rest = P._LinkedHashMap__newHashTable();\n          this._rest = rest;\n        }\n        hash = this._computeHashCode$1(key);\n        bucket = rest[hash];\n        if (bucket == null)\n          rest[hash] = [this._newLinkedCell$2(key, value)];\n        else {\n          index = this._findBucketIndex$2(bucket, key);\n          if (index >= 0)\n            bucket[index].set$_value(value);\n          else\n            bucket.push(this._newLinkedCell$2(key, value));\n        }\n      }\n    },\n    remove$1: function(_, key) {\n      var rest, bucket, index, cell;\n      if (typeof key === \"string\" && key !== \"__proto__\")\n        return this._removeHashTableEntry$2(this._strings, key);\n      else if (typeof key === \"number\" && (key & 0x3ffffff) === key)\n        return this._removeHashTableEntry$2(this._nums, key);\n      else {\n        rest = this._rest;\n        if (rest == null)\n          return;\n        bucket = rest[this._computeHashCode$1(key)];\n        index = this._findBucketIndex$2(bucket, key);\n        if (index < 0)\n          return;\n        cell = bucket.splice(index, 1)[0];\n        this._unlinkCell$1(cell);\n        return cell.get$_value();\n      }\n    },\n    forEach$1: function(_, action) {\n      var cell, modifications;\n      cell = this._first;\n      modifications = this._modifications;\n      for (; cell != null;) {\n        action.call$2(cell.get$_key(), cell._value);\n        if (modifications !== this._modifications)\n          throw H.wrapException(P.ConcurrentModificationError$(this));\n        cell = cell._next;\n      }\n    },\n    _addHashTableEntry$3: function(table, key, value) {\n      var cell = table[key];\n      if (cell == null)\n        table[key] = this._newLinkedCell$2(key, value);\n      else\n        cell.set$_value(value);\n    },\n    _removeHashTableEntry$2: function(table, key) {\n      var cell;\n      if (table == null)\n        return;\n      cell = table[key];\n      if (cell == null)\n        return;\n      this._unlinkCell$1(cell);\n      delete table[key];\n      return cell.get$_value();\n    },\n    _newLinkedCell$2: function(key, value) {\n      var cell, last;\n      cell = new P.LinkedHashMapCell(key, value, null, null);\n      if (this._first == null) {\n        this._last = cell;\n        this._first = cell;\n      } else {\n        last = this._last;\n        cell._previous = last;\n        last.set$_next(cell);\n        this._last = cell;\n      }\n      this._collection$_length = this._collection$_length + 1;\n      this._modifications = this._modifications + 1 & 67108863;\n      return cell;\n    },\n    _unlinkCell$1: function(cell) {\n      var previous, next;\n      previous = cell.get$_previous();\n      next = cell.get$_next();\n      if (previous == null)\n        this._first = next;\n      else\n        previous.set$_next(next);\n      if (next == null)\n        this._last = previous;\n      else\n        next.set$_previous(previous);\n      this._collection$_length = this._collection$_length - 1;\n      this._modifications = this._modifications + 1 & 67108863;\n    },\n    _computeHashCode$1: function(key) {\n      return J.get$hashCode$(key) & 0x3ffffff;\n    },\n    _findBucketIndex$2: function(bucket, key) {\n      var $length, i;\n      if (bucket == null)\n        return -1;\n      $length = bucket.length;\n      for (i = 0; i < $length; ++i)\n        if (J.$eq(bucket[i].get$_key(), key))\n          return i;\n      return -1;\n    },\n    toString$0: function(_) {\n      return P.Maps_mapToString(this);\n    },\n    $isMap: true,\n    static: {_LinkedHashMap__newHashTable: function() {\n        var table = Object.create(null);\n        table[\"<non-identifier-key>\"] = table;\n        delete table[\"<non-identifier-key>\"];\n        return table;\n      }}\n  },\n  _LinkedHashMap_values_closure: {\n    \"\": \"Closure:10;this_0\",\n    call$1: function(each) {\n      var t1 = this.this_0;\n      return t1.$index(t1, each);\n    }\n  },\n  LinkedHashMapCell: {\n    \"\": \"Object;_key<,_value@,_next@,_previous@\"\n  },\n  LinkedHashMapKeyIterable: {\n    \"\": \"IterableBase;_map\",\n    get$length: function(_) {\n      return this._map._collection$_length;\n    },\n    get$iterator: function(_) {\n      var t1, t2;\n      t1 = this._map;\n      t2 = new P.LinkedHashMapKeyIterator(t1, t1._modifications, null, null);\n      t2._cell = t1._first;\n      return t2;\n    },\n    forEach$1: function(_, f) {\n      var t1, cell, modifications;\n      t1 = this._map;\n      cell = t1._first;\n      modifications = t1._modifications;\n      for (; cell != null;) {\n        f.call$1(cell.get$_key());\n        if (modifications !== t1._modifications)\n          throw H.wrapException(P.ConcurrentModificationError$(t1));\n        cell = cell._next;\n      }\n    },\n    $asIterableBase: null\n  },\n  LinkedHashMapKeyIterator: {\n    \"\": \"Object;_map,_modifications,_cell,_collection$_current\",\n    get$current: function() {\n      return this._collection$_current;\n    },\n    moveNext$0: function() {\n      var t1 = this._map;\n      if (this._modifications !== t1._modifications)\n        throw H.wrapException(P.ConcurrentModificationError$(t1));\n      else {\n        t1 = this._cell;\n        if (t1 == null) {\n          this._collection$_current = null;\n          return false;\n        } else {\n          this._collection$_current = t1.get$_key();\n          this._cell = t1._next;\n          return true;\n        }\n      }\n    }\n  },\n  _HashSet: {\n    \"\": \"_HashSetBase;\",\n    get$iterator: function(_) {\n      return new P.HashSetIterator(this, this._computeElements$0(), 0, null);\n    },\n    get$length: function(_) {\n      return this._collection$_length;\n    },\n    contains$1: function(_, object) {\n      var strings, nums, rest;\n      if (typeof object === \"string\" && object !== \"__proto__\") {\n        strings = this._strings;\n        return strings == null ? false : strings[object] != null;\n      } else if (typeof object === \"number\" && (object & 0x3ffffff) === object) {\n        nums = this._nums;\n        return nums == null ? false : nums[object] != null;\n      } else {\n        rest = this._rest;\n        if (rest == null)\n          return false;\n        return this._findBucketIndex$2(rest[this._computeHashCode$1(object)], object) >= 0;\n      }\n    },\n    lookup$1: function(object) {\n      var t1, rest, bucket, index;\n      if (!(typeof object === \"string\" && object !== \"__proto__\"))\n        t1 = typeof object === \"number\" && (object & 0x3ffffff) === object;\n      else\n        t1 = true;\n      if (t1)\n        return this.contains$1(this, object) ? object : null;\n      rest = this._rest;\n      if (rest == null)\n        return;\n      bucket = rest[this._computeHashCode$1(object)];\n      index = this._findBucketIndex$2(bucket, object);\n      if (index < 0)\n        return;\n      return J.$index$asx(bucket, index);\n    },\n    add$1: function(_, element) {\n      var rest, hash, bucket;\n      rest = this._rest;\n      if (rest == null) {\n        rest = P._HashSet__newHashTable();\n        this._rest = rest;\n      }\n      hash = this._computeHashCode$1(element);\n      bucket = rest[hash];\n      if (bucket == null)\n        rest[hash] = [element];\n      else {\n        if (this._findBucketIndex$2(bucket, element) >= 0)\n          return false;\n        bucket.push(element);\n      }\n      this._collection$_length = this._collection$_length + 1;\n      this._elements = null;\n      return true;\n    },\n    remove$1: function(_, object) {\n      var rest, bucket, index;\n      if (typeof object === \"string\" && object !== \"__proto__\")\n        return this._removeHashTableEntry$2(this._strings, object);\n      else if (typeof object === \"number\" && (object & 0x3ffffff) === object)\n        return this._removeHashTableEntry$2(this._nums, object);\n      else {\n        rest = this._rest;\n        if (rest == null)\n          return false;\n        bucket = rest[this._computeHashCode$1(object)];\n        index = this._findBucketIndex$2(bucket, object);\n        if (index < 0)\n          return false;\n        this._collection$_length = this._collection$_length - 1;\n        this._elements = null;\n        bucket.splice(index, 1);\n        return true;\n      }\n    },\n    _computeElements$0: function() {\n      var t1, result, strings, names, entries, index, i, nums, rest, bucket, $length, i0;\n      t1 = this._elements;\n      if (t1 != null)\n        return t1;\n      result = Array(this._collection$_length);\n      result.fixed$length = init;\n      strings = this._strings;\n      if (strings != null) {\n        names = Object.getOwnPropertyNames(strings);\n        entries = names.length;\n        for (index = 0, i = 0; i < entries; ++i) {\n          result[index] = names[i];\n          ++index;\n        }\n      } else\n        index = 0;\n      nums = this._nums;\n      if (nums != null) {\n        names = Object.getOwnPropertyNames(nums);\n        entries = names.length;\n        for (i = 0; i < entries; ++i) {\n          result[index] = +names[i];\n          ++index;\n        }\n      }\n      rest = this._rest;\n      if (rest != null) {\n        names = Object.getOwnPropertyNames(rest);\n        entries = names.length;\n        for (i = 0; i < entries; ++i) {\n          bucket = rest[names[i]];\n          $length = bucket.length;\n          for (i0 = 0; i0 < $length; ++i0) {\n            result[index] = bucket[i0];\n            ++index;\n          }\n        }\n      }\n      this._elements = result;\n      return result;\n    },\n    _removeHashTableEntry$2: function(table, element) {\n      if (table != null && table[element] != null) {\n        delete table[element];\n        this._collection$_length = this._collection$_length - 1;\n        this._elements = null;\n        return true;\n      } else\n        return false;\n    },\n    _computeHashCode$1: function(element) {\n      return J.get$hashCode$(element) & 0x3ffffff;\n    },\n    _findBucketIndex$2: function(bucket, element) {\n      var $length, i;\n      if (bucket == null)\n        return -1;\n      $length = bucket.length;\n      for (i = 0; i < $length; ++i)\n        if (J.$eq(bucket[i], element))\n          return i;\n      return -1;\n    },\n    $as_HashSetBase: null\n  },\n  _IdentityHashSet: {\n    \"\": \"_HashSet;_collection$_length,_strings,_nums,_rest,_elements\",\n    _computeHashCode$1: function(key) {\n      return H.objectHashCode(key) & 0x3ffffff;\n    },\n    _findBucketIndex$2: function(bucket, element) {\n      var $length, i, t1;\n      if (bucket == null)\n        return -1;\n      $length = bucket.length;\n      for (i = 0; i < $length; ++i) {\n        t1 = bucket[i];\n        if (t1 == null ? element == null : t1 === element)\n          return i;\n      }\n      return -1;\n    },\n    $as_HashSet: null\n  },\n  HashSetIterator: {\n    \"\": \"Object;_set,_elements,_offset,_collection$_current\",\n    get$current: function() {\n      return this._collection$_current;\n    },\n    moveNext$0: function() {\n      var elements, offset, t1;\n      elements = this._elements;\n      offset = this._offset;\n      t1 = this._set;\n      if (elements !== t1._elements)\n        throw H.wrapException(P.ConcurrentModificationError$(t1));\n      else if (offset >= elements.length) {\n        this._collection$_current = null;\n        return false;\n      } else {\n        this._collection$_current = elements[offset];\n        this._offset = offset + 1;\n        return true;\n      }\n    }\n  },\n  _LinkedHashSet: {\n    \"\": \"_HashSetBase;_collection$_length,_strings,_nums,_rest,_first,_last,_modifications\",\n    get$iterator: function(_) {\n      var t1 = new P.LinkedHashSetIterator(this, this._modifications, null, null);\n      t1._cell = this._first;\n      return t1;\n    },\n    get$length: function(_) {\n      return this._collection$_length;\n    },\n    contains$1: function(_, object) {\n      var strings, nums, rest;\n      if (typeof object === \"string\" && object !== \"__proto__\") {\n        strings = this._strings;\n        if (strings == null)\n          return false;\n        return strings[object] != null;\n      } else if (typeof object === \"number\" && (object & 0x3ffffff) === object) {\n        nums = this._nums;\n        if (nums == null)\n          return false;\n        return nums[object] != null;\n      } else {\n        rest = this._rest;\n        if (rest == null)\n          return false;\n        return this._findBucketIndex$2(rest[this._computeHashCode$1(object)], object) >= 0;\n      }\n    },\n    lookup$1: function(object) {\n      var t1, rest, bucket, index;\n      if (!(typeof object === \"string\" && object !== \"__proto__\"))\n        t1 = typeof object === \"number\" && (object & 0x3ffffff) === object;\n      else\n        t1 = true;\n      if (t1)\n        return this.contains$1(this, object) ? object : null;\n      else {\n        rest = this._rest;\n        if (rest == null)\n          return;\n        bucket = rest[this._computeHashCode$1(object)];\n        index = this._findBucketIndex$2(bucket, object);\n        if (index < 0)\n          return;\n        return J.$index$asx(bucket, index).get$_element();\n      }\n    },\n    forEach$1: function(_, action) {\n      var cell, modifications;\n      cell = this._first;\n      modifications = this._modifications;\n      for (; cell != null;) {\n        action.call$1(cell.get$_element());\n        if (modifications !== this._modifications)\n          throw H.wrapException(P.ConcurrentModificationError$(this));\n        cell = cell._next;\n      }\n    },\n    add$1: function(_, element) {\n      var nums, rest, hash, bucket;\n      if ((element & 0x3ffffff) === element) {\n        nums = this._nums;\n        if (nums == null) {\n          nums = P._LinkedHashSet__newHashTable();\n          this._nums = nums;\n        }\n        return this._addHashTableEntry$2(nums, element);\n      } else {\n        rest = this._rest;\n        if (rest == null) {\n          rest = P._LinkedHashSet__newHashTable();\n          this._rest = rest;\n        }\n        hash = this._computeHashCode$1(element);\n        bucket = rest[hash];\n        if (bucket == null)\n          rest[hash] = [this._newLinkedCell$1(element)];\n        else {\n          if (this._findBucketIndex$2(bucket, element) >= 0)\n            return false;\n          bucket.push(this._newLinkedCell$1(element));\n        }\n        return true;\n      }\n    },\n    _addHashTableEntry$2: function(table, element) {\n      if (table[element] != null)\n        return false;\n      table[element] = this._newLinkedCell$1(element);\n      return true;\n    },\n    _newLinkedCell$1: function(element) {\n      var cell, last;\n      cell = new P.LinkedHashSetCell(element, null, null);\n      if (this._first == null) {\n        this._last = cell;\n        this._first = cell;\n      } else {\n        last = this._last;\n        cell._previous = last;\n        last.set$_next(cell);\n        this._last = cell;\n      }\n      this._collection$_length = this._collection$_length + 1;\n      this._modifications = this._modifications + 1 & 67108863;\n      return cell;\n    },\n    _computeHashCode$1: function(element) {\n      return J.get$hashCode$(element) & 0x3ffffff;\n    },\n    _findBucketIndex$2: function(bucket, element) {\n      var $length, i;\n      if (bucket == null)\n        return -1;\n      $length = bucket.length;\n      for (i = 0; i < $length; ++i)\n        if (bucket[i].get$_element() === element)\n          return i;\n      return -1;\n    },\n    $as_HashSetBase: null,\n    static: {_LinkedHashSet__newHashTable: function() {\n        var table = Object.create(null);\n        table[\"<non-identifier-key>\"] = table;\n        delete table[\"<non-identifier-key>\"];\n        return table;\n      }}\n  },\n  LinkedHashSetCell: {\n    \"\": \"Object;_element<,_next@,_previous@\"\n  },\n  LinkedHashSetIterator: {\n    \"\": \"Object;_set,_modifications,_cell,_collection$_current\",\n    get$current: function() {\n      return this._collection$_current;\n    },\n    moveNext$0: function() {\n      var t1 = this._set;\n      if (this._modifications !== t1._modifications)\n        throw H.wrapException(P.ConcurrentModificationError$(t1));\n      else {\n        t1 = this._cell;\n        if (t1 == null) {\n          this._collection$_current = null;\n          return false;\n        } else {\n          this._collection$_current = t1.get$_element();\n          this._cell = t1._next;\n          return true;\n        }\n      }\n    }\n  },\n  _HashSetBase: {\n    \"\": \"IterableBase;\",\n    toString$0: function(_) {\n      return H.IterableMixinWorkaround_toStringIterable(this, \"{\", \"}\");\n    },\n    $asIterableBase: null\n  },\n  IterableBase: {\n    \"\": \"Object;\",\n    forEach$1: function(_, f) {\n      var t1;\n      for (t1 = this.get$iterator(this); t1.moveNext$0();)\n        f.call$1(t1.get$current());\n    },\n    get$length: function(_) {\n      var it, count;\n      it = this.get$iterator(this);\n      for (count = 0; it.moveNext$0();)\n        ++count;\n      return count;\n    },\n    elementAt$1: function(_, index) {\n      var t1, remaining, element;\n      if (index < 0)\n        throw H.wrapException(P.RangeError$value(index));\n      for (t1 = this.get$iterator(this), remaining = index; t1.moveNext$0();) {\n        element = t1.get$current();\n        if (remaining === 0)\n          return element;\n        --remaining;\n      }\n      throw H.wrapException(P.RangeError$value(index));\n    },\n    toString$0: function(_) {\n      return P._iterableToString(this);\n    }\n  },\n  ListMixin: {\n    \"\": \"Object;\",\n    get$iterator: function(receiver) {\n      return new H.ListIterator(receiver, this.get$length(receiver), 0, null);\n    },\n    elementAt$1: function(receiver, index) {\n      return this.$index(receiver, index);\n    },\n    forEach$1: function(receiver, action) {\n      var $length, i;\n      $length = this.get$length(receiver);\n      for (i = 0; i < $length; ++i) {\n        action.call$1(this.$index(receiver, i));\n        if ($length !== this.get$length(receiver))\n          throw H.wrapException(P.ConcurrentModificationError$(receiver));\n      }\n    },\n    toString$0: function(receiver) {\n      var result, t1;\n      t1 = $.get$_toStringVisiting();\n      if (t1.contains$1(t1, receiver))\n        return \"[...]\";\n      result = P.StringBuffer$(\"\");\n      try {\n        t1 = $.get$_toStringVisiting();\n        t1.add$1(t1, receiver);\n        result.write$1(\"[\");\n        result.writeAll$2(receiver, \", \");\n        result.write$1(\"]\");\n      } finally {\n        t1 = $.get$_toStringVisiting();\n        t1.remove$1(t1, receiver);\n      }\n      return result.get$_contents();\n    },\n    $isList: true,\n    $asList: null\n  },\n  Maps_mapToString_closure: {\n    \"\": \"Closure:9;box_0,result_1\",\n    call$2: function(k, v) {\n      var t1 = this.box_0;\n      if (!t1.first_0)\n        this.result_1.write$1(\", \");\n      t1.first_0 = false;\n      t1 = this.result_1;\n      t1.write$1(k);\n      t1.write$1(\": \");\n      t1.write$1(v);\n    }\n  },\n  ListQueue: {\n    \"\": \"IterableBase;_table,_head,_tail,_modificationCount\",\n    get$iterator: function(_) {\n      return new P._ListQueueIterator(this, this._tail, this._modificationCount, this._head, null);\n    },\n    forEach$1: function(_, action) {\n      var modificationCount, i, t1;\n      modificationCount = this._modificationCount;\n      for (i = this._head; i !== this._tail; i = (i + 1 & this._table.length - 1) >>> 0) {\n        t1 = this._table;\n        if (i < 0 || i >= t1.length)\n          return H.ioore(t1, i);\n        action.call$1(t1[i]);\n        if (modificationCount !== this._modificationCount)\n          H.throwExpression(P.ConcurrentModificationError$(this));\n      }\n    },\n    get$length: function(_) {\n      return (this._tail - this._head & this._table.length - 1) >>> 0;\n    },\n    toString$0: function(_) {\n      return H.IterableMixinWorkaround_toStringIterable(this, \"{\", \"}\");\n    },\n    removeFirst$0: function() {\n      var t1, t2, t3, result;\n      t1 = this._head;\n      if (t1 === this._tail)\n        throw H.wrapException(P.StateError$(\"No elements\"));\n      this._modificationCount = this._modificationCount + 1;\n      t2 = this._table;\n      t3 = t2.length;\n      if (t1 >= t3)\n        return H.ioore(t2, t1);\n      result = t2[t1];\n      this._head = (t1 + 1 & t3 - 1) >>> 0;\n      return result;\n    },\n    _add$1: function(element) {\n      var t1, t2, t3, newTable, split;\n      t1 = this._table;\n      t2 = this._tail;\n      t3 = t1.length;\n      if (t2 >= t3)\n        return H.ioore(t1, t2);\n      t1[t2] = element;\n      t2 = (t2 + 1 & t3 - 1) >>> 0;\n      this._tail = t2;\n      if (this._head === t2) {\n        t1 = Array(t3 * 2);\n        t1.fixed$length = init;\n        newTable = H.setRuntimeTypeInfo(t1, [H.getTypeArgumentByIndex(this, 0)]);\n        t1 = this._table;\n        t2 = this._head;\n        split = t1.length - t2;\n        H.IterableMixinWorkaround_setRangeList(newTable, 0, split, t1, t2);\n        t1 = this._head;\n        t2 = this._table;\n        H.IterableMixinWorkaround_setRangeList(newTable, split, split + t1, t2, 0);\n        this._head = 0;\n        this._tail = this._table.length;\n        this._table = newTable;\n      }\n      this._modificationCount = this._modificationCount + 1;\n    },\n    ListQueue$1: function(initialCapacity, $E) {\n      var t1 = Array(8);\n      t1.fixed$length = init;\n      this._table = H.setRuntimeTypeInfo(t1, [$E]);\n    },\n    $asIterableBase: null,\n    static: {\"\": \"ListQueue__INITIAL_CAPACITY\"}\n  },\n  _ListQueueIterator: {\n    \"\": \"Object;_queue,_end,_modificationCount,_collection$_position,_collection$_current\",\n    get$current: function() {\n      return this._collection$_current;\n    },\n    moveNext$0: function() {\n      var t1, t2, t3;\n      t1 = this._queue;\n      if (this._modificationCount !== t1._modificationCount)\n        H.throwExpression(P.ConcurrentModificationError$(t1));\n      t2 = this._collection$_position;\n      if (t2 === this._end) {\n        this._collection$_current = null;\n        return false;\n      }\n      t1 = t1._table;\n      t3 = t1.length;\n      if (t2 >= t3)\n        return H.ioore(t1, t2);\n      this._collection$_current = t1[t2];\n      this._collection$_position = (t2 + 1 & t3 - 1) >>> 0;\n      return true;\n    }\n  }\n}],\n[\"dart.core\", \"dart:core\", , P, {\n  \"\": \"\",\n  _symbolToString: function(symbol) {\n    return H.Symbol_getName(symbol);\n  },\n  Error_safeToString: function(object) {\n    var buffer, t1, i, t2, codeUnit, charCodes;\n    if (typeof object === \"number\" || typeof object === \"boolean\" || null == object)\n      return J.toString$0(object);\n    if (typeof object === \"string\") {\n      buffer = new P.StringBuffer(\"\");\n      buffer._contents = \"\\\"\";\n      for (t1 = object.length, i = 0, t2 = \"\\\"\"; i < t1; ++i) {\n        codeUnit = C.JSString_methods.codeUnitAt$1(object, i);\n        if (codeUnit <= 31)\n          if (codeUnit === 10) {\n            t2 = buffer._contents + \"\\\\n\";\n            buffer._contents = t2;\n          } else if (codeUnit === 13) {\n            t2 = buffer._contents + \"\\\\r\";\n            buffer._contents = t2;\n          } else if (codeUnit === 9) {\n            t2 = buffer._contents + \"\\\\t\";\n            buffer._contents = t2;\n          } else {\n            t2 = buffer._contents + \"\\\\x\";\n            buffer._contents = t2;\n            if (codeUnit < 16)\n              buffer._contents = t2 + \"0\";\n            else {\n              buffer._contents = t2 + \"1\";\n              codeUnit -= 16;\n            }\n            t2 = codeUnit < 10 ? 48 + codeUnit : 87 + codeUnit;\n            charCodes = P.List_List$filled(1, t2, J.JSInt);\n            t2 = H.Primitives_stringFromCharCodes(charCodes);\n            t2 = buffer._contents + t2;\n            buffer._contents = t2;\n          }\n        else if (codeUnit === 92) {\n          t2 = buffer._contents + \"\\\\\\\\\";\n          buffer._contents = t2;\n        } else if (codeUnit === 34) {\n          t2 = buffer._contents + \"\\\\\\\"\";\n          buffer._contents = t2;\n        } else {\n          charCodes = P.List_List$filled(1, codeUnit, J.JSInt);\n          t2 = H.Primitives_stringFromCharCodes(charCodes);\n          t2 = buffer._contents + t2;\n          buffer._contents = t2;\n        }\n      }\n      t1 = t2 + \"\\\"\";\n      buffer._contents = t1;\n      return t1;\n    }\n    return \"Instance of '\" + H.Primitives_objectTypeName(object) + \"'\";\n  },\n  Exception_Exception: function(message) {\n    return new P._ExceptionImplementation(message);\n  },\n  identical: [function(a, b) {\n    return a == null ? b == null : a === b;\n  }, \"call$2\", \"identical$closure\", 4, 0, 6],\n  identityHashCode: [function(object) {\n    return H.objectHashCode(object);\n  }, \"call$1\", \"identityHashCode$closure\", 2, 0, 7],\n  List_List$filled: function($length, fill, $E) {\n    var result, t1, i;\n    result = J.JSArray_JSArray$fixed($length, $E);\n    if ($length !== 0 && true)\n      for (t1 = result.length, i = 0; i < t1; ++i)\n        result[i] = fill;\n    return result;\n  },\n  List_List$from: function(other, growable, $E) {\n    var list, t1, $length, fixedList, t2, i, t3;\n    list = H.setRuntimeTypeInfo([], [$E]);\n    for (t1 = J.get$iterator$ax(other); t1.moveNext$0();)\n      list.push(t1.get$current());\n    if (growable)\n      return list;\n    $length = list.length;\n    t1 = Array($length);\n    t1.fixed$length = init;\n    fixedList = H.setRuntimeTypeInfo(t1, [$E]);\n    for (t1 = list.length, t2 = fixedList.length, i = 0; i < $length; ++i) {\n      if (i >= t1)\n        return H.ioore(list, i);\n      t3 = list[i];\n      if (i >= t2)\n        return H.ioore(fixedList, i);\n      fixedList[i] = t3;\n    }\n    return fixedList;\n  },\n  print: function(object) {\n    var line = H.S(object);\n    H.printString(line);\n  },\n  NoSuchMethodError_toString_closure: {\n    \"\": \"Closure:16;box_0\",\n    call$2: function(key, value) {\n      var t1 = this.box_0;\n      if (t1.i_1 > 0)\n        t1.sb_0.write$1(\", \");\n      t1.sb_0.write$1(P._symbolToString(key));\n    }\n  },\n  DateTime: {\n    \"\": \"Object;millisecondsSinceEpoch,isUtc\",\n    $eq: function(_, other) {\n      var t1;\n      if (other == null)\n        return false;\n      t1 = J.getInterceptor(other);\n      if (typeof other !== \"object\" || other === null || !t1.$isDateTime)\n        return false;\n      return this.millisecondsSinceEpoch === other.millisecondsSinceEpoch && this.isUtc === other.isUtc;\n    },\n    get$hashCode: function(_) {\n      return this.millisecondsSinceEpoch;\n    },\n    toString$0: function(_) {\n      var t1, t2, t3, y, m, d, h, min, sec, ms;\n      t1 = new P.DateTime_toString_twoDigits();\n      t2 = this.isUtc;\n      t3 = t2 ? H.Primitives_lazyAsJsDate(this).getUTCFullYear() + 0 : H.Primitives_lazyAsJsDate(this).getFullYear() + 0;\n      y = new P.DateTime_toString_fourDigits().call$1(t3);\n      m = t1.call$1(t2 ? H.Primitives_lazyAsJsDate(this).getUTCMonth() + 1 : H.Primitives_lazyAsJsDate(this).getMonth() + 1);\n      d = t1.call$1(t2 ? H.Primitives_lazyAsJsDate(this).getUTCDate() + 0 : H.Primitives_lazyAsJsDate(this).getDate() + 0);\n      h = t1.call$1(H.Primitives_getHours(this));\n      min = t1.call$1(H.Primitives_getMinutes(this));\n      sec = t1.call$1(H.Primitives_getSeconds(this));\n      t1 = t2 ? H.Primitives_lazyAsJsDate(this).getUTCMilliseconds() + 0 : H.Primitives_lazyAsJsDate(this).getMilliseconds() + 0;\n      ms = new P.DateTime_toString_threeDigits().call$1(t1);\n      if (t2)\n        return H.S(y) + \"-\" + H.S(m) + \"-\" + H.S(d) + \" \" + H.S(h) + \":\" + H.S(min) + \":\" + H.S(sec) + \".\" + H.S(ms) + \"Z\";\n      else\n        return H.S(y) + \"-\" + H.S(m) + \"-\" + H.S(d) + \" \" + H.S(h) + \":\" + H.S(min) + \":\" + H.S(sec) + \".\" + H.S(ms);\n    },\n    DateTime$_now$0: function() {\n      H.Primitives_lazyAsJsDate(this);\n    },\n    $isDateTime: true,\n    static: {\"\": \"DateTime_MONDAY,DateTime_TUESDAY,DateTime_WEDNESDAY,DateTime_THURSDAY,DateTime_FRIDAY,DateTime_SATURDAY,DateTime_SUNDAY,DateTime_DAYS_PER_WEEK,DateTime_JANUARY,DateTime_FEBRUARY,DateTime_MARCH,DateTime_APRIL,DateTime_MAY,DateTime_JUNE,DateTime_JULY,DateTime_AUGUST,DateTime_SEPTEMBER,DateTime_OCTOBER,DateTime_NOVEMBER,DateTime_DECEMBER,DateTime_MONTHS_PER_YEAR,DateTime__MAX_MILLISECONDS_SINCE_EPOCH\", DateTime$_now: function() {\n        var t1 = new P.DateTime(Date.now(), false);\n        t1.DateTime$_now$0();\n        return t1;\n      }}\n  },\n  DateTime_toString_fourDigits: {\n    \"\": \"Closure:17;\",\n    call$1: function(n) {\n      var absN, sign;\n      absN = Math.abs(n);\n      sign = n < 0 ? \"-\" : \"\";\n      if (absN >= 1000)\n        return \"\" + n;\n      if (absN >= 100)\n        return sign + \"0\" + H.S(absN);\n      if (absN >= 10)\n        return sign + \"00\" + H.S(absN);\n      return sign + \"000\" + H.S(absN);\n    }\n  },\n  DateTime_toString_threeDigits: {\n    \"\": \"Closure:17;\",\n    call$1: function(n) {\n      if (n >= 100)\n        return \"\" + n;\n      if (n >= 10)\n        return \"0\" + n;\n      return \"00\" + n;\n    }\n  },\n  DateTime_toString_twoDigits: {\n    \"\": \"Closure:17;\",\n    call$1: function(n) {\n      if (n >= 10)\n        return \"\" + n;\n      return \"0\" + n;\n    }\n  },\n  Duration: {\n    \"\": \"Object;_duration<\",\n    $add: function(_, other) {\n      return P.Duration$(0, 0, C.JSInt_methods.$add(this._duration, other.get$_duration()), 0, 0, 0);\n    },\n    $sub: function(_, other) {\n      return P.Duration$(0, 0, this._duration - other.get$_duration(), 0, 0, 0);\n    },\n    $lt: function(_, other) {\n      return C.JSInt_methods.$lt(this._duration, other.get$_duration());\n    },\n    $ge: function(_, other) {\n      return C.JSInt_methods.$ge(this._duration, other.get$_duration());\n    },\n    $eq: function(_, other) {\n      var t1;\n      if (other == null)\n        return false;\n      t1 = J.getInterceptor(other);\n      if (typeof other !== \"object\" || other === null || !t1.$isDuration)\n        return false;\n      return this._duration === other._duration;\n    },\n    get$hashCode: function(_) {\n      return this._duration & 0x1FFFFFFF;\n    },\n    toString$0: function(_) {\n      var t1, t2, twoDigitMinutes, twoDigitSeconds, sixDigitUs;\n      t1 = new P.Duration_toString_twoDigits();\n      t2 = this._duration;\n      if (t2 < 0)\n        return \"-\" + H.S(P.Duration$(0, 0, -t2, 0, 0, 0));\n      twoDigitMinutes = t1.call$1(C.JSInt_methods.remainder$1(C.JSInt_methods._tdivFast$1(t2, 60000000), 60));\n      twoDigitSeconds = t1.call$1(C.JSInt_methods.remainder$1(C.JSInt_methods._tdivFast$1(t2, 1000000), 60));\n      sixDigitUs = new P.Duration_toString_sixDigits().call$1(C.JSInt_methods.remainder$1(t2, 1000000));\n      return \"\" + C.JSInt_methods._tdivFast$1(t2, 3600000000) + \":\" + H.S(twoDigitMinutes) + \":\" + H.S(twoDigitSeconds) + \".\" + H.S(sixDigitUs);\n    },\n    $isDuration: true,\n    static: {\"\": \"Duration_MICROSECONDS_PER_MILLISECOND,Duration_MILLISECONDS_PER_SECOND,Duration_SECONDS_PER_MINUTE,Duration_MINUTES_PER_HOUR,Duration_HOURS_PER_DAY,Duration_MICROSECONDS_PER_SECOND,Duration_MICROSECONDS_PER_MINUTE,Duration_MICROSECONDS_PER_HOUR,Duration_MICROSECONDS_PER_DAY,Duration_MILLISECONDS_PER_MINUTE,Duration_MILLISECONDS_PER_HOUR,Duration_MILLISECONDS_PER_DAY,Duration_SECONDS_PER_HOUR,Duration_SECONDS_PER_DAY,Duration_MINUTES_PER_DAY,Duration_ZERO\", Duration$: function(days, hours, microseconds, milliseconds, minutes, seconds) {\n        return new P.Duration(days * 86400000000 + hours * 3600000000 + minutes * 60000000 + seconds * 1000000 + milliseconds * 1000 + microseconds);\n      }}\n  },\n  Duration_toString_sixDigits: {\n    \"\": \"Closure:17;\",\n    call$1: function(n) {\n      if (n >= 100000)\n        return \"\" + n;\n      if (n >= 10000)\n        return \"0\" + n;\n      if (n >= 1000)\n        return \"00\" + n;\n      if (n >= 100)\n        return \"000\" + n;\n      if (n > 10)\n        return \"0000\" + n;\n      return \"00000\" + n;\n    }\n  },\n  Duration_toString_twoDigits: {\n    \"\": \"Closure:17;\",\n    call$1: function(n) {\n      if (n >= 10)\n        return \"\" + n;\n      return \"0\" + n;\n    }\n  },\n  Error: {\n    \"\": \"Object;\",\n    get$stackTrace: function() {\n      return new H._StackTrace(this.$thrownJsError, null);\n    },\n    $isError: true\n  },\n  NullThrownError: {\n    \"\": \"Error;\",\n    toString$0: function(_) {\n      return \"Throw of null.\";\n    }\n  },\n  ArgumentError: {\n    \"\": \"Error;message\",\n    toString$0: function(_) {\n      var t1 = this.message;\n      if (t1 != null)\n        return \"Illegal argument(s): \" + H.S(t1);\n      return \"Illegal argument(s)\";\n    },\n    static: {ArgumentError$: function(message) {\n        return new P.ArgumentError(message);\n      }}\n  },\n  RangeError: {\n    \"\": \"ArgumentError;message\",\n    toString$0: function(_) {\n      return \"RangeError: \" + H.S(this.message);\n    },\n    static: {RangeError$value: function(value) {\n        return new P.RangeError(\"value \" + H.S(value));\n      }, RangeError$range: function(value, start, end) {\n        return new P.RangeError(\"value \" + H.S(value) + \" not in range \" + start + \"..\" + H.S(end));\n      }}\n  },\n  UnsupportedError: {\n    \"\": \"Error;message\",\n    toString$0: function(_) {\n      return \"Unsupported operation: \" + this.message;\n    },\n    static: {UnsupportedError$: function(message) {\n        return new P.UnsupportedError(message);\n      }}\n  },\n  UnimplementedError: {\n    \"\": \"Error;message\",\n    toString$0: function(_) {\n      var t1 = this.message;\n      return t1 != null ? \"UnimplementedError: \" + H.S(t1) : \"UnimplementedError\";\n    },\n    $isError: true,\n    static: {UnimplementedError$: function(message) {\n        return new P.UnimplementedError(message);\n      }}\n  },\n  StateError: {\n    \"\": \"Error;message\",\n    toString$0: function(_) {\n      return \"Bad state: \" + this.message;\n    },\n    static: {StateError$: function(message) {\n        return new P.StateError(message);\n      }}\n  },\n  ConcurrentModificationError: {\n    \"\": \"Error;modifiedObject\",\n    toString$0: function(_) {\n      var t1 = this.modifiedObject;\n      if (t1 == null)\n        return \"Concurrent modification during iteration.\";\n      return \"Concurrent modification during iteration: \" + H.S(P.Error_safeToString(t1)) + \".\";\n    },\n    static: {ConcurrentModificationError$: function(modifiedObject) {\n        return new P.ConcurrentModificationError(modifiedObject);\n      }}\n  },\n  StackOverflowError: {\n    \"\": \"Object;\",\n    toString$0: function(_) {\n      return \"Stack Overflow\";\n    },\n    get$stackTrace: function() {\n      return;\n    },\n    $isError: true\n  },\n  CyclicInitializationError: {\n    \"\": \"Error;variableName\",\n    toString$0: function(_) {\n      return \"Reading static variable '\" + this.variableName + \"' during its initialization\";\n    },\n    static: {CyclicInitializationError$: function(variableName) {\n        return new P.CyclicInitializationError(variableName);\n      }}\n  },\n  _ExceptionImplementation: {\n    \"\": \"Object;message\",\n    toString$0: function(_) {\n      var t1 = this.message;\n      if (t1 == null)\n        return \"Exception\";\n      return \"Exception: \" + H.S(t1);\n    }\n  },\n  Expando: {\n    \"\": \"Object;name\",\n    toString$0: function(_) {\n      return \"Expando:\" + H.S(this.name);\n    },\n    $index: function(_, object) {\n      var values = H.Primitives_getProperty(object, \"expando$values\");\n      return values == null ? null : H.Primitives_getProperty(values, this._getKey$0());\n    },\n    $indexSet: function(_, object, value) {\n      var values = H.Primitives_getProperty(object, \"expando$values\");\n      if (values == null) {\n        values = new P.Object();\n        H.Primitives_setProperty(object, \"expando$values\", values);\n      }\n      H.Primitives_setProperty(values, this._getKey$0(), value);\n    },\n    _getKey$0: function() {\n      var key, t1;\n      key = H.Primitives_getProperty(this, \"expando$key\");\n      if (key == null) {\n        t1 = $.Expando__keyCount;\n        $.Expando__keyCount = t1 + 1;\n        key = \"expando$key$\" + t1;\n        H.Primitives_setProperty(this, \"expando$key\", key);\n      }\n      return key;\n    },\n    static: {\"\": \"Expando__KEY_PROPERTY_NAME,Expando__EXPANDO_PROPERTY_NAME,Expando__keyCount\"}\n  },\n  Iterator: {\n    \"\": \"Object;\"\n  },\n  Null: {\n    \"\": \"Object;\",\n    toString$0: function(_) {\n      return \"null\";\n    }\n  },\n  Object: {\n    \"\": \";\",\n    $eq: function(_, other) {\n      return this === other;\n    },\n    get$hashCode: function(_) {\n      return H.Primitives_objectHashCode(this);\n    },\n    toString$0: function(_) {\n      return H.Primitives_objectToString(this);\n    }\n  },\n  StackTrace: {\n    \"\": \"Object;\"\n  },\n  StringBuffer: {\n    \"\": \"Object;_contents<\",\n    get$length: function(_) {\n      return this._contents.length;\n    },\n    write$1: function(obj) {\n      var str = typeof obj === \"string\" ? obj : H.S(obj);\n      this._contents = this._contents + str;\n    },\n    writeAll$2: function(objects, separator) {\n      var iterator, str;\n      iterator = J.get$iterator$ax(objects);\n      if (!iterator.moveNext$0())\n        return;\n      if (separator.length === 0)\n        do {\n          str = iterator.get$current();\n          str = typeof str === \"string\" ? str : H.S(str);\n          this._contents = this._contents + str;\n        } while (iterator.moveNext$0());\n      else {\n        this.write$1(iterator.get$current());\n        for (; iterator.moveNext$0();) {\n          this._contents = this._contents + separator;\n          str = iterator.get$current();\n          str = typeof str === \"string\" ? str : H.S(str);\n          this._contents = this._contents + str;\n        }\n      }\n    },\n    toString$0: function(_) {\n      return this._contents;\n    },\n    StringBuffer$1: function($content) {\n      this._contents = $content;\n    },\n    static: {StringBuffer$: function($content) {\n        var t1 = new P.StringBuffer(\"\");\n        t1.StringBuffer$1($content);\n        return t1;\n      }}\n  },\n  Symbol: {\n    \"\": \"Object;\"\n  }\n}],\n[\"dart.dom.html\", \"dart:html\", , W, {\n  \"\": \"\",\n  ImageElement_ImageElement: function(height, src, width) {\n    var e = document.createElement(\"img\", null);\n    if (src != null)\n      J.set$src$x(e, src);\n    return e;\n  },\n  _JenkinsSmiHash_combine: function(hash, value) {\n    hash = 536870911 & hash + value;\n    hash = 536870911 & hash + ((524287 & hash) << 10 >>> 0);\n    return hash ^ hash >>> 6;\n  },\n  _wrapZone: function(callback) {\n    var t1 = $.Zone__current;\n    if (t1 === C.C__RootZone)\n      return callback;\n    return t1.bindUnaryCallback$2$runGuarded(callback, true);\n  },\n  HtmlElement: {\n    \"\": \"Element;\",\n    \"%\": \"HTMLAppletElement|HTMLAreaElement|HTMLBRElement|HTMLBaseElement|HTMLBaseFontElement|HTMLBodyElement|HTMLButtonElement|HTMLCanvasElement|HTMLContentElement|HTMLDListElement|HTMLDataListElement|HTMLDetailsElement|HTMLDialogElement|HTMLDirectoryElement|HTMLDivElement|HTMLFieldSetElement|HTMLFontElement|HTMLFrameElement|HTMLFrameSetElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLKeygenElement|HTMLLIElement|HTMLLabelElement|HTMLLegendElement|HTMLLinkElement|HTMLMapElement|HTMLMarqueeElement|HTMLMenuElement|HTMLMetaElement|HTMLMeterElement|HTMLModElement|HTMLOListElement|HTMLObjectElement|HTMLOptGroupElement|HTMLOptionElement|HTMLOutputElement|HTMLParagraphElement|HTMLParamElement|HTMLPreElement|HTMLProgressElement|HTMLQuoteElement|HTMLShadowElement|HTMLSpanElement|HTMLStyleElement|HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement|HTMLTableRowElement|HTMLTableSectionElement|HTMLTemplateElement|HTMLTextAreaElement|HTMLTitleElement|HTMLUListElement|HTMLUnknownElement;HTMLElement\"\n  },\n  AnchorElement: {\n    \"\": \"HtmlElement;\",\n    toString$0: function(receiver) {\n      return receiver.toString();\n    },\n    \"%\": \"HTMLAnchorElement\"\n  },\n  CharacterData: {\n    \"\": \"Node;length=\",\n    \"%\": \"CDATASection|CharacterData|Comment|ProcessingInstruction|Text\"\n  },\n  CssStyleDeclaration: {\n    \"\": \"Interceptor_CssStyleDeclarationBase;length=\",\n    setProperty$3: function(receiver, propertyName, value, priority) {\n      var exception;\n      try {\n        if (priority == null)\n          priority = \"\";\n        receiver.setProperty(propertyName, value, priority);\n        if (!!receiver.setAttribute)\n          receiver.setAttribute(propertyName, value);\n      } catch (exception) {\n        H.unwrapException(exception);\n      }\n\n    },\n    \"%\": \"CSS2Properties|CSSStyleDeclaration|MSStyleCSSProperties\"\n  },\n  DomException: {\n    \"\": \"Interceptor;\",\n    toString$0: function(receiver) {\n      return receiver.toString();\n    },\n    \"%\": \"DOMException\"\n  },\n  Element: {\n    \"\": \"Node;\",\n    toString$0: function(receiver) {\n      return receiver.localName;\n    },\n    \"%\": \";Element\"\n  },\n  EmbedElement: {\n    \"\": \"HtmlElement;src}\",\n    \"%\": \"HTMLEmbedElement\"\n  },\n  ErrorEvent: {\n    \"\": \"Event;error=\",\n    \"%\": \"ErrorEvent\"\n  },\n  Event: {\n    \"\": \"Interceptor;\",\n    \"%\": \"AudioProcessingEvent|AutocompleteErrorEvent|BeforeLoadEvent|BeforeUnloadEvent|CSSFontFaceLoadEvent|CloseEvent|CompositionEvent|CustomEvent|DeviceMotionEvent|DeviceOrientationEvent|DragEvent|FocusEvent|HashChangeEvent|IDBVersionChangeEvent|KeyboardEvent|MIDIConnectionEvent|MIDIMessageEvent|MSPointerEvent|MediaKeyEvent|MediaKeyMessageEvent|MediaKeyNeededEvent|MediaStreamEvent|MediaStreamTrackEvent|MessageEvent|MouseEvent|MouseScrollEvent|MouseWheelEvent|MutationEvent|OfflineAudioCompletionEvent|OverflowEvent|PageTransitionEvent|PointerEvent|PopStateEvent|ProgressEvent|RTCDTMFToneChangeEvent|RTCDataChannelEvent|RTCIceCandidateEvent|ResourceProgressEvent|SVGZoomEvent|SecurityPolicyViolationEvent|SpeechInputEvent|SpeechRecognitionEvent|SpeechSynthesisEvent|StorageEvent|TextEvent|TouchEvent|TrackEvent|TransitionEvent|UIEvent|WebGLContextEvent|WebKitAnimationEvent|WebKitTransitionEvent|WheelEvent|XMLHttpRequestProgressEvent;Event\"\n  },\n  EventTarget: {\n    \"\": \"Interceptor;\",\n    \"%\": \"MediaStream;EventTarget\"\n  },\n  FormElement: {\n    \"\": \"HtmlElement;length=\",\n    \"%\": \"HTMLFormElement\"\n  },\n  IFrameElement: {\n    \"\": \"HtmlElement;src}\",\n    \"%\": \"HTMLIFrameElement\"\n  },\n  ImageElement: {\n    \"\": \"HtmlElement;src}\",\n    \"%\": \"HTMLImageElement\"\n  },\n  InputElement: {\n    \"\": \"HtmlElement;src}\",\n    \"%\": \"HTMLInputElement\"\n  },\n  MediaElement: {\n    \"\": \"HtmlElement;error=,src}\",\n    \"%\": \"HTMLAudioElement|HTMLMediaElement|HTMLVideoElement\"\n  },\n  Node: {\n    \"\": \"EventTarget;\",\n    toString$0: function(receiver) {\n      var t1 = receiver.nodeValue;\n      return t1 == null ? J.Interceptor.prototype.toString$0.call(this, receiver) : t1;\n    },\n    \"%\": \"Attr|Document|DocumentFragment|DocumentType|Entity|HTMLDocument|Notation|SVGDocument|ShadowRoot;Node\"\n  },\n  NodeList: {\n    \"\": \"Interceptor_ListMixin_ImmutableListMixin;\",\n    get$length: function(receiver) {\n      return receiver.length;\n    },\n    $index: function(receiver, index) {\n      var t1 = receiver.length;\n      if (index >>> 0 !== index || index >= t1)\n        throw H.wrapException(P.RangeError$range(index, 0, t1));\n      return receiver[index];\n    },\n    $indexSet: function(receiver, index, value) {\n      throw H.wrapException(P.UnsupportedError$(\"Cannot assign element of immutable List.\"));\n    },\n    elementAt$1: function(receiver, index) {\n      if (index < 0 || index >= receiver.length)\n        return H.ioore(receiver, index);\n      return receiver[index];\n    },\n    $isList: true,\n    $asList: function() {\n      return [W.Node];\n    },\n    $isJavaScriptIndexingBehavior: true,\n    \"%\": \"NodeList|RadioNodeList\"\n  },\n  ScriptElement: {\n    \"\": \"HtmlElement;src}\",\n    \"%\": \"HTMLScriptElement\"\n  },\n  SelectElement: {\n    \"\": \"HtmlElement;length=\",\n    \"%\": \"HTMLSelectElement\"\n  },\n  SourceElement: {\n    \"\": \"HtmlElement;src}\",\n    \"%\": \"HTMLSourceElement\"\n  },\n  SpeechRecognitionError: {\n    \"\": \"Event;error=\",\n    \"%\": \"SpeechRecognitionError\"\n  },\n  TrackElement: {\n    \"\": \"HtmlElement;src}\",\n    \"%\": \"HTMLTrackElement\"\n  },\n  Window: {\n    \"\": \"EventTarget;\",\n    _requestAnimationFrame$1: function(receiver, callback) {\n      return receiver.requestAnimationFrame(H.convertDartClosureToJS(callback, 1));\n    },\n    _ensureRequestAnimationFrame$0: function(receiver) {\n      if (!!(receiver.requestAnimationFrame && receiver.cancelAnimationFrame))\n        return;\n        (function($this) {\n   var vendors = ['ms', 'moz', 'webkit', 'o'];\n   for (var i = 0; i < vendors.length && !$this.requestAnimationFrame; ++i) {\n     $this.requestAnimationFrame = $this[vendors[i] + 'RequestAnimationFrame'];\n     $this.cancelAnimationFrame =\n         $this[vendors[i]+'CancelAnimationFrame'] ||\n         $this[vendors[i]+'CancelRequestAnimationFrame'];\n   }\n   if ($this.requestAnimationFrame && $this.cancelAnimationFrame) return;\n   $this.requestAnimationFrame = function(callback) {\n      return window.setTimeout(function() {\n        callback(Date.now());\n      }, 16 /* 16ms ~= 60fps */);\n   };\n   $this.cancelAnimationFrame = function(id) { clearTimeout(id); }\n  })(receiver);\n    },\n    toString$0: function(receiver) {\n      return receiver.toString();\n    },\n    \"%\": \"DOMWindow|Window\"\n  },\n  _ClientRect: {\n    \"\": \"Interceptor;height=,left=,top=,width=\",\n    toString$0: function(receiver) {\n      return \"Rectangle (\" + H.S(receiver.left) + \", \" + H.S(receiver.top) + \") \" + H.S(receiver.width) + \" x \" + H.S(receiver.height);\n    },\n    $eq: function(receiver, other) {\n      var t1, t2, t3;\n      if (other == null)\n        return false;\n      t1 = J.getInterceptor$x(other);\n      if (typeof other !== \"object\" || other === null || !t1.$isRectangle)\n        return false;\n      t2 = receiver.left;\n      t3 = t1.get$left(other);\n      if (t2 == null ? t3 == null : t2 === t3) {\n        t2 = receiver.top;\n        t3 = t1.get$top(other);\n        if (t2 == null ? t3 == null : t2 === t3) {\n          t2 = receiver.width;\n          t3 = t1.get$width(other);\n          if (t2 == null ? t3 == null : t2 === t3) {\n            t2 = receiver.height;\n            t1 = t1.get$height(other);\n            t1 = t2 == null ? t1 == null : t2 === t1;\n          } else\n            t1 = false;\n        } else\n          t1 = false;\n      } else\n        t1 = false;\n      return t1;\n    },\n    get$hashCode: function(receiver) {\n      var t1, t2, t3, t4, hash;\n      t1 = J.get$hashCode$(receiver.left);\n      t2 = J.get$hashCode$(receiver.top);\n      t3 = J.get$hashCode$(receiver.width);\n      t4 = J.get$hashCode$(receiver.height);\n      t4 = W._JenkinsSmiHash_combine(W._JenkinsSmiHash_combine(W._JenkinsSmiHash_combine(W._JenkinsSmiHash_combine(0, t1), t2), t3), t4);\n      hash = 536870911 & t4 + ((67108863 & t4) << 3 >>> 0);\n      hash ^= hash >>> 11;\n      return 536870911 & hash + ((16383 & hash) << 15 >>> 0);\n    },\n    $isRectangle: true,\n    $asRectangle: function() {\n      return [null];\n    },\n    \"%\": \"ClientRect|DOMRect\"\n  },\n  Interceptor_CssStyleDeclarationBase: {\n    \"\": \"Interceptor+CssStyleDeclarationBase;\"\n  },\n  CssStyleDeclarationBase: {\n    \"\": \"Object;\",\n    set$bottom: function(receiver, value) {\n      this.setProperty$3(receiver, \"bottom\", value, \"\");\n    },\n    set$left: function(receiver, value) {\n      this.setProperty$3(receiver, \"left\", value, \"\");\n    },\n    set$position: function(receiver, value) {\n      this.setProperty$3(receiver, \"position\", value, \"\");\n    },\n    set$right: function(receiver, value) {\n      this.setProperty$3(receiver, \"right\", value, \"\");\n    },\n    set$textAlign: function(receiver, value) {\n      this.setProperty$3(receiver, \"text-align\", value, \"\");\n    },\n    set$top: function(receiver, value) {\n      this.setProperty$3(receiver, \"top\", value, \"\");\n    }\n  },\n  Interceptor_ListMixin: {\n    \"\": \"Interceptor+ListMixin;\",\n    $isList: true,\n    $asList: function() {\n      return [W.Node];\n    }\n  },\n  Interceptor_ListMixin_ImmutableListMixin: {\n    \"\": \"Interceptor_ListMixin+ImmutableListMixin;\",\n    $isList: true,\n    $asList: function() {\n      return [W.Node];\n    }\n  },\n  ImmutableListMixin: {\n    \"\": \"Object;\",\n    get$iterator: function(receiver) {\n      return new W.FixedSizeListIterator(receiver, this.get$length(receiver), -1, null);\n    },\n    $isList: true,\n    $asList: null\n  },\n  FixedSizeListIterator: {\n    \"\": \"Object;_array,_length,_position,_current\",\n    moveNext$0: function() {\n      var nextPosition, t1;\n      nextPosition = this._position + 1;\n      t1 = this._length;\n      if (nextPosition < t1) {\n        this._current = J.$index$asx(this._array, nextPosition);\n        this._position = nextPosition;\n        return true;\n      }\n      this._current = null;\n      this._position = t1;\n      return false;\n    },\n    get$current: function() {\n      return this._current;\n    }\n  }\n}],\n[\"dart.dom.svg\", \"dart:svg\", , P, {\n  \"\": \"\",\n  FEBlendElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFEBlendElement\"\n  },\n  FEColorMatrixElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFEColorMatrixElement\"\n  },\n  FEComponentTransferElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFEComponentTransferElement\"\n  },\n  FECompositeElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFECompositeElement\"\n  },\n  FEConvolveMatrixElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFEConvolveMatrixElement\"\n  },\n  FEDiffuseLightingElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFEDiffuseLightingElement\"\n  },\n  FEDisplacementMapElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFEDisplacementMapElement\"\n  },\n  FEFloodElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFEFloodElement\"\n  },\n  FEGaussianBlurElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFEGaussianBlurElement\"\n  },\n  FEImageElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFEImageElement\"\n  },\n  FEMergeElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFEMergeElement\"\n  },\n  FEMorphologyElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFEMorphologyElement\"\n  },\n  FEOffsetElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFEOffsetElement\"\n  },\n  FEPointLightElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFEPointLightElement\"\n  },\n  FESpecularLightingElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFESpecularLightingElement\"\n  },\n  FESpotLightElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFESpotLightElement\"\n  },\n  FETileElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFETileElement\"\n  },\n  FETurbulenceElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFETurbulenceElement\"\n  },\n  FilterElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGFilterElement\"\n  },\n  ForeignObjectElement: {\n    \"\": \"GraphicsElement;x=,y=\",\n    \"%\": \"SVGForeignObjectElement\"\n  },\n  GraphicsElement: {\n    \"\": \"SvgElement;\",\n    \"%\": \"SVGAElement|SVGCircleElement|SVGClipPathElement|SVGDefsElement|SVGEllipseElement|SVGGElement|SVGLineElement|SVGPathElement|SVGPolygonElement|SVGPolylineElement|SVGSwitchElement;SVGGraphicsElement\"\n  },\n  ImageElement0: {\n    \"\": \"GraphicsElement;x=,y=\",\n    \"%\": \"SVGImageElement\"\n  },\n  MaskElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGMaskElement\"\n  },\n  PatternElement: {\n    \"\": \"SvgElement;x=,y=\",\n    \"%\": \"SVGPatternElement\"\n  },\n  RectElement: {\n    \"\": \"GraphicsElement;x=,y=\",\n    \"%\": \"SVGRectElement\"\n  },\n  SvgElement: {\n    \"\": \"Element;\",\n    \"%\": \"SVGAltGlyphDefElement|SVGAltGlyphItemElement|SVGAnimateColorElement|SVGAnimateElement|SVGAnimateMotionElement|SVGAnimateTransformElement|SVGAnimationElement|SVGComponentTransferFunctionElement|SVGCursorElement|SVGDescElement|SVGFEDistantLightElement|SVGFEDropShadowElement|SVGFEFuncAElement|SVGFEFuncBElement|SVGFEFuncGElement|SVGFEFuncRElement|SVGFEMergeNodeElement|SVGFontElement|SVGFontFaceElement|SVGFontFaceFormatElement|SVGFontFaceNameElement|SVGFontFaceSrcElement|SVGFontFaceUriElement|SVGGlyphElement|SVGGlyphRefElement|SVGGradientElement|SVGHKernElement|SVGLinearGradientElement|SVGMPathElement|SVGMarkerElement|SVGMetadataElement|SVGMissingGlyphElement|SVGRadialGradientElement|SVGScriptElement|SVGSetElement|SVGStopElement|SVGStyleElement|SVGSymbolElement|SVGTitleElement|SVGVKernElement|SVGViewElement;SVGElement\"\n  },\n  SvgSvgElement: {\n    \"\": \"GraphicsElement;x=,y=\",\n    \"%\": \"SVGSVGElement\"\n  },\n  TextContentElement: {\n    \"\": \"GraphicsElement;\",\n    \"%\": \"SVGTextPathElement;SVGTextContentElement\"\n  },\n  TextPositioningElement: {\n    \"\": \"TextContentElement;x=,y=\",\n    \"%\": \"SVGAltGlyphElement|SVGTSpanElement|SVGTextElement|SVGTextPositioningElement\"\n  },\n  UseElement: {\n    \"\": \"GraphicsElement;x=,y=\",\n    \"%\": \"SVGUseElement\"\n  }\n}],\n[\"dart.math\", \"dart:math\", , P, {\n  \"\": \"\",\n  _JenkinsSmiHash_combine0: function(hash, value) {\n    hash = 536870911 & C.JSInt_methods.$add(hash, value);\n    hash = 536870911 & hash + ((524287 & hash) << 10 >>> 0);\n    return hash ^ hash >>> 6;\n  },\n  min: function(a, b) {\n    var t1;\n    if (a > b)\n      return b;\n    if (a < b)\n      return a;\n    if (typeof a === \"number\")\n      if (a === 0)\n        return (a + b) * a * b;\n    if (a === 0)\n      t1 = b === 0 ? 1 / b < 0 : b < 0;\n    else\n      t1 = false;\n    if (t1 || isNaN(b))\n      return b;\n    return a;\n  },\n  _JSRandom: {\n    \"\": \"Object;\",\n    nextDouble$0: function() {\n      return Math.random();\n    }\n  }\n}],\n[\"dart.typed_data\", \"dart:typed_data\", , P, {\n  \"\": \"\",\n  TypedData: {\n    \"\": \"Interceptor;\",\n    _invalidIndex$2: function(receiver, index, $length) {\n      var t1 = J.getInterceptor$n(index);\n      if (t1.$lt(index, 0) || t1.$ge(index, $length))\n        throw H.wrapException(P.RangeError$range(index, 0, $length));\n      else\n        throw H.wrapException(P.ArgumentError$(\"Invalid list index \" + H.S(index)));\n    },\n    \"%\": \";ArrayBufferView;_NativeTypedArray|_NativeTypedArray_ListMixin|_NativeTypedArray_ListMixin_FixedLengthListMixin|_NativeTypedArrayOfInt\"\n  },\n  Uint8List: {\n    \"\": \"_NativeTypedArrayOfInt;\",\n    get$length: function(receiver) {\n      return receiver.length;\n    },\n    $index: function(receiver, index) {\n      var t1, t2;\n      t1 = receiver.length;\n      if (!(index >>> 0 != index)) {\n        if (typeof index !== \"number\")\n          return index.$ge();\n        t2 = index >= t1;\n      } else\n        t2 = true;\n      if (t2)\n        this._invalidIndex$2(receiver, index, t1);\n      return receiver[index];\n    },\n    $indexSet: function(receiver, index, value) {\n      var t1 = receiver.length;\n      if (index >>> 0 != index || J.$ge$n(index, t1))\n        this._invalidIndex$2(receiver, index, t1);\n      receiver[index] = value;\n    },\n    \"%\": \";Uint8Array\"\n  },\n  _NativeTypedArray: {\n    \"\": \"TypedData;\",\n    get$length: function(receiver) {\n      return receiver.length;\n    },\n    $isJavaScriptIndexingBehavior: true\n  },\n  _NativeTypedArrayOfInt: {\n    \"\": \"_NativeTypedArray_ListMixin_FixedLengthListMixin;\",\n    $isList: true,\n    $asList: function() {\n      return [J.JSInt];\n    }\n  },\n  _NativeTypedArray_ListMixin: {\n    \"\": \"_NativeTypedArray+ListMixin;\",\n    $isList: true,\n    $asList: function() {\n      return [J.JSInt];\n    }\n  },\n  _NativeTypedArray_ListMixin_FixedLengthListMixin: {\n    \"\": \"_NativeTypedArray_ListMixin+FixedLengthListMixin;\"\n  }\n}],\n[\"dart2js._js_primitives\", \"dart:_js_primitives\", , H, {\n  \"\": \"\",\n  printString: function(string) {\n    if (typeof dartPrint == \"function\") {\n      dartPrint(string);\n      return;\n    }\n    if (typeof console == \"object\" && typeof console.log == \"function\") {\n      console.log(string);\n      return;\n    }\n    if (typeof window == \"object\")\n      return;\n    if (typeof print == \"function\") {\n      print(string);\n      return;\n    }\n    throw \"Unable to print message: \" + String(string);\n  }\n}],\n]);\nIsolate.$finishClasses($$, $, null);\n$$ = null;\n\n// Runtime type support\nW.Node.$isNode = true;\nW.Node.$isObject = true;\nJ.JSInt.$isint = true;\nJ.JSInt.$isnum = true;\nJ.JSInt.$isObject = true;\nJ.JSNumber.$isnum = true;\nJ.JSNumber.$isObject = true;\nJ.JSString.$isString = true;\nJ.JSString.$isObject = true;\nP.Duration.$isDuration = true;\nP.Duration.$isObject = true;\nQ.ClockNumber.$isObject = true;\nQ.Ball.$isObject = true;\nJ.JSArray.$isObject = true;\nW.ImageElement.$isNode = true;\nW.ImageElement.$isObject = true;\nH.RawReceivePortImpl.$isObject = true;\nH._IsolateEvent.$isObject = true;\nH._IsolateContext.$isObject = true;\nP.Symbol.$isSymbol = true;\nP.Symbol.$isObject = true;\nP.StackTrace.$isStackTrace = true;\nP.StackTrace.$isObject = true;\nP.Object.$isObject = true;\nJ.JSBool.$isbool = true;\nJ.JSBool.$isObject = true;\nP._EventSink.$is_EventSink = true;\nP._EventSink.$isObject = true;\nP.Future.$isFuture = true;\nP.Future.$isObject = true;\nJ.JSDouble.$isdouble = true;\nJ.JSDouble.$isnum = true;\nJ.JSDouble.$isObject = true;\nP._DelayedEvent.$is_DelayedEvent = true;\nP._DelayedEvent.$isObject = true;\nP.DateTime.$isDateTime = true;\nP.DateTime.$isObject = true;\nP.StreamSubscription.$isStreamSubscription = true;\nP.StreamSubscription.$isObject = true;\n$.$signature_args2 = {func: \"args2\", args: [null, null]};\n$.$signature_args1 = {func: \"args1\", args: [null]};\n// getInterceptor methods\nJ.getInterceptor = function(receiver) {\n  if (typeof receiver == \"number\") {\n    if (Math.floor(receiver) == receiver)\n      return J.JSInt.prototype;\n    return J.JSDouble.prototype;\n  }\n  if (typeof receiver == \"string\")\n    return J.JSString.prototype;\n  if (receiver == null)\n    return J.JSNull.prototype;\n  if (typeof receiver == \"boolean\")\n    return J.JSBool.prototype;\n  if (receiver.constructor == Array)\n    return J.JSArray.prototype;\n  if (typeof receiver != \"object\")\n    return receiver;\n  if (receiver instanceof P.Object)\n    return receiver;\n  return J.getNativeInterceptor(receiver);\n};\nJ.getInterceptor$asx = function(receiver) {\n  if (typeof receiver == \"string\")\n    return J.JSString.prototype;\n  if (receiver == null)\n    return receiver;\n  if (receiver.constructor == Array)\n    return J.JSArray.prototype;\n  if (typeof receiver != \"object\")\n    return receiver;\n  if (receiver instanceof P.Object)\n    return receiver;\n  return J.getNativeInterceptor(receiver);\n};\nJ.getInterceptor$ax = function(receiver) {\n  if (receiver == null)\n    return receiver;\n  if (receiver.constructor == Array)\n    return J.JSArray.prototype;\n  if (typeof receiver != \"object\")\n    return receiver;\n  if (receiver instanceof P.Object)\n    return receiver;\n  return J.getNativeInterceptor(receiver);\n};\nJ.getInterceptor$n = function(receiver) {\n  if (typeof receiver == \"number\")\n    return J.JSNumber.prototype;\n  if (receiver == null)\n    return receiver;\n  if (!(receiver instanceof P.Object))\n    return J.UnknownJavaScriptObject.prototype;\n  return receiver;\n};\nJ.getInterceptor$ns = function(receiver) {\n  if (typeof receiver == \"number\")\n    return J.JSNumber.prototype;\n  if (typeof receiver == \"string\")\n    return J.JSString.prototype;\n  if (receiver == null)\n    return receiver;\n  if (!(receiver instanceof P.Object))\n    return J.UnknownJavaScriptObject.prototype;\n  return receiver;\n};\nJ.getInterceptor$s = function(receiver) {\n  if (typeof receiver == \"string\")\n    return J.JSString.prototype;\n  if (receiver == null)\n    return receiver;\n  if (!(receiver instanceof P.Object))\n    return J.UnknownJavaScriptObject.prototype;\n  return receiver;\n};\nJ.getInterceptor$x = function(receiver) {\n  if (receiver == null)\n    return receiver;\n  if (typeof receiver != \"object\")\n    return receiver;\n  if (receiver instanceof P.Object)\n    return receiver;\n  return J.getNativeInterceptor(receiver);\n};\nJ.$add$ns = function(receiver, a0) {\n  if (typeof receiver == \"number\" && typeof a0 == \"number\")\n    return receiver + a0;\n  return J.getInterceptor$ns(receiver).$add(receiver, a0);\n};\nJ.$eq = function(receiver, a0) {\n  if (receiver == null)\n    return a0 == null;\n  if (typeof receiver != \"object\")\n    return a0 != null && receiver === a0;\n  return J.getInterceptor(receiver).$eq(receiver, a0);\n};\nJ.$ge$n = function(receiver, a0) {\n  if (typeof receiver == \"number\" && typeof a0 == \"number\")\n    return receiver >= a0;\n  return J.getInterceptor$n(receiver).$ge(receiver, a0);\n};\nJ.$index$asx = function(receiver, a0) {\n  if (receiver.constructor == Array || typeof receiver == \"string\" || H.isJsIndexable(receiver, receiver[init.dispatchPropertyName]))\n    if (a0 >>> 0 === a0 && a0 < receiver.length)\n      return receiver[a0];\n  return J.getInterceptor$asx(receiver).$index(receiver, a0);\n};\nJ.$indexSet$ax = function(receiver, a0, a1) {\n  if ((receiver.constructor == Array || H.isJsIndexable(receiver, receiver[init.dispatchPropertyName])) && !receiver.immutable$list && a0 >>> 0 === a0 && a0 < receiver.length)\n    return receiver[a0] = a1;\n  return J.getInterceptor$ax(receiver).$indexSet(receiver, a0, a1);\n};\nJ.forEach$1$ax = function(receiver, a0) {\n  return J.getInterceptor$ax(receiver).forEach$1(receiver, a0);\n};\nJ.get$error$x = function(receiver) {\n  return J.getInterceptor$x(receiver).get$error(receiver);\n};\nJ.get$hashCode$ = function(receiver) {\n  return J.getInterceptor(receiver).get$hashCode(receiver);\n};\nJ.get$iterator$ax = function(receiver) {\n  return J.getInterceptor$ax(receiver).get$iterator(receiver);\n};\nJ.get$length$asx = function(receiver) {\n  return J.getInterceptor$asx(receiver).get$length(receiver);\n};\nJ.roundToDouble$0$n = function(receiver) {\n  return J.getInterceptor$n(receiver).roundToDouble$0(receiver);\n};\nJ.set$bottom$x = function(receiver, value) {\n  return J.getInterceptor$x(receiver).set$bottom(receiver, value);\n};\nJ.set$left$x = function(receiver, value) {\n  return J.getInterceptor$x(receiver).set$left(receiver, value);\n};\nJ.set$position$x = function(receiver, value) {\n  return J.getInterceptor$x(receiver).set$position(receiver, value);\n};\nJ.set$right$x = function(receiver, value) {\n  return J.getInterceptor$x(receiver).set$right(receiver, value);\n};\nJ.set$src$x = function(receiver, value) {\n  return J.getInterceptor$x(receiver).set$src(receiver, value);\n};\nJ.set$textAlign$x = function(receiver, value) {\n  return J.getInterceptor$x(receiver).set$textAlign(receiver, value);\n};\nJ.set$top$x = function(receiver, value) {\n  return J.getInterceptor$x(receiver).set$top(receiver, value);\n};\nJ.toString$0 = function(receiver) {\n  return J.getInterceptor(receiver).toString$0(receiver);\n};\nC.C_DynamicRuntimeType = new H.DynamicRuntimeType();\nC.C__DelayedDone = new P._DelayedDone();\nC.C__JSRandom = new P._JSRandom();\nC.C__RootZone = new P._RootZone();\nC.Duration_0 = new P.Duration(0);\nC.JSArray_methods = J.JSArray.prototype;\nC.JSInt_methods = J.JSInt.prototype;\nC.JSNumber_methods = J.JSNumber.prototype;\nC.JSString_methods = J.JSString.prototype;\nC.JS_CONST_0 = function(hooks) {\n  if (typeof dartExperimentalFixupGetTag != \"function\") return hooks;\n  hooks.getTag = dartExperimentalFixupGetTag(hooks.getTag);\n};\nC.JS_CONST_Fs4 = function(hooks) { return hooks; }\n;\nC.JS_CONST_IX5 = function getTagFallback(o) {\n  var constructor = o.constructor;\n  if (typeof constructor == \"function\") {\n    var name = constructor.name;\n    if (typeof name == \"string\"\n        && name !== \"\"\n        && name !== \"Object\"\n        && name !== \"Function.prototype\") {\n      return name;\n    }\n  }\n  var s = Object.prototype.toString.call(o);\n  return s.substring(8, s.length - 1);\n};\nC.JS_CONST_QJm = function(getTagFallback) {\n  return function(hooks) {\n    if (typeof navigator != \"object\") return hooks;\n    var ua = navigator.userAgent;\n    if (ua.indexOf(\"DumpRenderTree\") >= 0) return hooks;\n    if (ua.indexOf(\"Chrome\") >= 0) {\n      function confirm(p) {\n        return typeof window == \"object\" && window[p] && window[p].name == p;\n      }\n      if (confirm(\"Window\") && confirm(\"HTMLElement\")) return hooks;\n    }\n    hooks.getTag = getTagFallback;\n  };\n};\nC.JS_CONST_U4w = function(hooks) {\n  var userAgent = typeof navigator == \"object\" ? navigator.userAgent : \"\";\n  if (userAgent.indexOf(\"Firefox\") == -1) return hooks;\n  var getTag = hooks.getTag;\n  var quickMap = {\n    \"BeforeUnloadEvent\": \"Event\",\n    \"DataTransfer\": \"Clipboard\",\n    \"GeoGeolocation\": \"Geolocation\",\n    \"WorkerMessageEvent\": \"MessageEvent\",\n    \"XMLDocument\": \"!Document\"};\n  function getTagFirefox(o) {\n    var tag = getTag(o);\n    return quickMap[tag] || tag;\n  }\n  hooks.getTag = getTagFirefox;\n};\nC.JS_CONST_aQP = function() {\n  function typeNameInChrome(o) {\n    var name = o.constructor.name;\n    if (name) return name;\n    var s = Object.prototype.toString.call(o);\n    return s.substring(8, s.length - 1);\n  }\n  function getUnknownTag(object, tag) {\n    if (/^HTML[A-Z].*Element$/.test(tag)) {\n      var name = Object.prototype.toString.call(object);\n      if (name == \"[object Object]\") return null;\n      return \"HTMLElement\";\n    }\n  }\n  function getUnknownTagGenericBrowser(object, tag) {\n    if (object instanceof HTMLElement) return \"HTMLElement\";\n    return getUnknownTag(object, tag);\n  }\n  function prototypeForTag(tag) {\n    if (typeof window == \"undefined\") return null;\n    if (typeof window[tag] == \"undefined\") return null;\n    var constructor = window[tag];\n    if (typeof constructor != \"function\") return null;\n    return constructor.prototype;\n  }\n  function discriminator(tag) { return null; }\n  var isBrowser = typeof navigator == \"object\";\n  return {\n    getTag: typeNameInChrome,\n    getUnknownTag: isBrowser ? getUnknownTagGenericBrowser : getUnknownTag,\n    prototypeForTag: prototypeForTag,\n    discriminator: discriminator };\n};\nC.JS_CONST_gkc = function(hooks) {\n  var userAgent = typeof navigator == \"object\" ? navigator.userAgent : \"\";\n  if (userAgent.indexOf(\"Trident/\") == -1) return hooks;\n  var getTag = hooks.getTag;\n  var quickMap = {\n    \"BeforeUnloadEvent\": \"Event\",\n    \"DataTransfer\": \"Clipboard\",\n    \"HTMLDDElement\": \"HTMLElement\",\n    \"HTMLDTElement\": \"HTMLElement\",\n    \"HTMLPhraseElement\": \"HTMLElement\",\n    \"Position\": \"Geoposition\"\n  };\n  function getTagIE(o) {\n    var tag = getTag(o);\n    var newTag = quickMap[tag];\n    if (newTag) return newTag;\n    if (tag == \"Object\") {\n      if (window.DataView && (o instanceof window.DataView)) return \"DataView\";\n    }\n    return tag;\n  }\n  function prototypeForTagIE(tag) {\n    var constructor = window[tag];\n    if (constructor == null) return null;\n    return constructor.prototype;\n  }\n  hooks.getTag = getTagIE;\n  hooks.prototypeForTag = prototypeForTagIE;\n};\nC.JS_CONST_rr7 = function(hooks) {\n  var getTag = hooks.getTag;\n  var prototypeForTag = hooks.prototypeForTag;\n  function getTagFixed(o) {\n    var tag = getTag(o);\n    if (tag == \"Document\") {\n      if (!!o.xmlVersion) return \"!Document\";\n      return \"!HTMLDocument\";\n    }\n    return tag;\n  }\n  function prototypeForTagFixed(tag) {\n    if (tag == \"Document\") return null;\n    return prototypeForTag(tag);\n  }\n  hooks.getTag = getTagFixed;\n  hooks.prototypeForTag = prototypeForTagFixed;\n};\nIsolate.makeConstantList = function(list) {\n  list.immutable$list = init;\n  list.fixed$length = init;\n  return list;\n};\nC.List_8eb = Isolate.makeConstantList([\"images/ball-d9d9d9.png\", \"images/ball-009a49.png\", \"images/ball-13acfa.png\", \"images/ball-265897.png\", \"images/ball-b6b4b5.png\", \"images/ball-c0000b.png\", \"images/ball-c9c9c9.png\"]);\nC.List_1_1_1_1 = Isolate.makeConstantList([1, 1, 1, 1]);\nC.List_1_0_0_1 = Isolate.makeConstantList([1, 0, 0, 1]);\nC.List_Xdq = Isolate.makeConstantList([C.List_1_1_1_1, C.List_1_0_0_1, C.List_1_0_0_1, C.List_1_0_0_1, C.List_1_0_0_1, C.List_1_0_0_1, C.List_1_1_1_1]);\nC.List_0_0_0_1 = Isolate.makeConstantList([0, 0, 0, 1]);\nC.List_Xdq0 = Isolate.makeConstantList([C.List_0_0_0_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_0_0_0_1]);\nC.List_1_0_0_0 = Isolate.makeConstantList([1, 0, 0, 0]);\nC.List_Xdq1 = Isolate.makeConstantList([C.List_1_1_1_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_1_1_1_1, C.List_1_0_0_0, C.List_1_0_0_0, C.List_1_1_1_1]);\nC.List_Xdq2 = Isolate.makeConstantList([C.List_1_1_1_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_1_1_1_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_1_1_1_1]);\nC.List_Xdq3 = Isolate.makeConstantList([C.List_1_0_0_1, C.List_1_0_0_1, C.List_1_0_0_1, C.List_1_1_1_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_0_0_0_1]);\nC.List_Xdq4 = Isolate.makeConstantList([C.List_1_1_1_1, C.List_1_0_0_0, C.List_1_0_0_0, C.List_1_1_1_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_1_1_1_1]);\nC.List_Xdq5 = Isolate.makeConstantList([C.List_1_1_1_1, C.List_1_0_0_0, C.List_1_0_0_0, C.List_1_1_1_1, C.List_1_0_0_1, C.List_1_0_0_1, C.List_1_1_1_1]);\nC.List_Xdq6 = Isolate.makeConstantList([C.List_1_1_1_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_0_0_0_1]);\nC.List_Xdq7 = Isolate.makeConstantList([C.List_1_1_1_1, C.List_1_0_0_1, C.List_1_0_0_1, C.List_1_1_1_1, C.List_1_0_0_1, C.List_1_0_0_1, C.List_1_1_1_1]);\nC.List_Xdq8 = Isolate.makeConstantList([C.List_1_1_1_1, C.List_1_0_0_1, C.List_1_0_0_1, C.List_1_1_1_1, C.List_0_0_0_1, C.List_0_0_0_1, C.List_1_1_1_1]);\nC.List_e3I = Isolate.makeConstantList([C.List_Xdq, C.List_Xdq0, C.List_Xdq1, C.List_Xdq2, C.List_Xdq3, C.List_Xdq4, C.List_Xdq5, C.List_Xdq6, C.List_Xdq7, C.List_Xdq8]);\nC.Type_6Vn = H.createRuntimeType('_NativeTypedArray');\nC.Type_Hp8 = H.createRuntimeType('_NativeTypedArrayOfInt');\nC.UnknownJavaScriptObject_methods = J.UnknownJavaScriptObject.prototype;\nC.Window_methods = W.Window.prototype;\n$.controlPort = null;\n$.RawReceivePortImpl__nextFreeId = 1;\n$.Primitives_mirrorFunctionCacheName = \"$cachedFunction\";\n$.Primitives_mirrorInvokeCacheName = \"$cachedInvocation\";\n$.Closure_functionCounter = 0;\n$.BoundClosure_selfFieldNameCache = null;\n$.BoundClosure_receiverFieldNameCache = null;\n$.RuntimeFunctionType_inAssert = false;\n$.getTagFunction = null;\n$.alternateTagFunction = null;\n$.prototypeForTagFunction = null;\n$.dispatchRecordsForInstanceTags = null;\n$.interceptorsForUncacheableTags = null;\n$.initNativeDispatchFlag = null;\n$.Ball_random = null;\n$.fpsAverage = null;\n$.printToZone = null;\n$._callbacksAreEnqueued = false;\n$.Zone__current = C.C__RootZone;\n$.Expando__keyCount = 0;\n$.Device__isOpera = null;\n$.Device__isWebKit = null;\nIsolate.$lazy($, \"globalThis\", \"globalThis\", \"get$globalThis\", function() {\n  return function() { return this; }();\n});\nIsolate.$lazy($, \"globalWindow\", \"globalWindow\", \"get$globalWindow\", function() {\n  return $.get$globalThis().window;\n});\nIsolate.$lazy($, \"globalWorker\", \"globalWorker\", \"get$globalWorker\", function() {\n  return $.get$globalThis().Worker;\n});\nIsolate.$lazy($, \"globalPostMessageDefined\", \"globalPostMessageDefined\", \"get$globalPostMessageDefined\", function() {\n  return $.get$globalThis().postMessage !== void 0;\n});\nIsolate.$lazy($, \"thisScript\", \"IsolateNatives_thisScript\", \"get$IsolateNatives_thisScript\", function() {\n  return H.IsolateNatives_computeThisScript();\n});\nIsolate.$lazy($, \"workerIds\", \"IsolateNatives_workerIds\", \"get$IsolateNatives_workerIds\", function() {\n  return new P.Expando(null);\n});\nIsolate.$lazy($, \"noSuchMethodPattern\", \"TypeErrorDecoder_noSuchMethodPattern\", \"get$TypeErrorDecoder_noSuchMethodPattern\", function() {\n  return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokeCallErrorOn({ toString: function() { return \"$receiver$\"; } }));\n});\nIsolate.$lazy($, \"notClosurePattern\", \"TypeErrorDecoder_notClosurePattern\", \"get$TypeErrorDecoder_notClosurePattern\", function() {\n  return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokeCallErrorOn({ $method$: null, toString: function() { return \"$receiver$\"; } }));\n});\nIsolate.$lazy($, \"nullCallPattern\", \"TypeErrorDecoder_nullCallPattern\", \"get$TypeErrorDecoder_nullCallPattern\", function() {\n  return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokeCallErrorOn(null));\n});\nIsolate.$lazy($, \"nullLiteralCallPattern\", \"TypeErrorDecoder_nullLiteralCallPattern\", \"get$TypeErrorDecoder_nullLiteralCallPattern\", function() {\n  return H.TypeErrorDecoder_extractPattern(function() {\n  var $argumentsExpr$ = '$arguments$'\n  try {\n    null.$method$($argumentsExpr$);\n  } catch (e) {\n    return e.message;\n  }\n}());\n});\nIsolate.$lazy($, \"undefinedCallPattern\", \"TypeErrorDecoder_undefinedCallPattern\", \"get$TypeErrorDecoder_undefinedCallPattern\", function() {\n  return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokeCallErrorOn(void 0));\n});\nIsolate.$lazy($, \"undefinedLiteralCallPattern\", \"TypeErrorDecoder_undefinedLiteralCallPattern\", \"get$TypeErrorDecoder_undefinedLiteralCallPattern\", function() {\n  return H.TypeErrorDecoder_extractPattern(function() {\n  var $argumentsExpr$ = '$arguments$'\n  try {\n    (void 0).$method$($argumentsExpr$);\n  } catch (e) {\n    return e.message;\n  }\n}());\n});\nIsolate.$lazy($, \"nullPropertyPattern\", \"TypeErrorDecoder_nullPropertyPattern\", \"get$TypeErrorDecoder_nullPropertyPattern\", function() {\n  return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokePropertyErrorOn(null));\n});\nIsolate.$lazy($, \"nullLiteralPropertyPattern\", \"TypeErrorDecoder_nullLiteralPropertyPattern\", \"get$TypeErrorDecoder_nullLiteralPropertyPattern\", function() {\n  return H.TypeErrorDecoder_extractPattern(function() {\n  try {\n    null.$method$;\n  } catch (e) {\n    return e.message;\n  }\n}());\n});\nIsolate.$lazy($, \"undefinedPropertyPattern\", \"TypeErrorDecoder_undefinedPropertyPattern\", \"get$TypeErrorDecoder_undefinedPropertyPattern\", function() {\n  return H.TypeErrorDecoder_extractPattern(H.TypeErrorDecoder_provokePropertyErrorOn(void 0));\n});\nIsolate.$lazy($, \"undefinedLiteralPropertyPattern\", \"TypeErrorDecoder_undefinedLiteralPropertyPattern\", \"get$TypeErrorDecoder_undefinedLiteralPropertyPattern\", function() {\n  return H.TypeErrorDecoder_extractPattern(function() {\n  try {\n    (void 0).$method$;\n  } catch (e) {\n    return e.message;\n  }\n}());\n});\nIsolate.$lazy($, \"_toStringList\", \"IterableMixinWorkaround__toStringList\", \"get$IterableMixinWorkaround__toStringList\", function() {\n  return [];\n});\nIsolate.$lazy($, \"_asyncCallbacks\", \"_asyncCallbacks\", \"get$_asyncCallbacks\", function() {\n  var t1, t2;\n  t1 = {func: \"void_\", void: true};\n  t2 = H.setRuntimeTypeInfo(new P.ListQueue(null, 0, 0, 0), [t1]);\n  t2.ListQueue$1(null, t1);\n  return t2;\n});\nIsolate.$lazy($, \"_toStringVisiting\", \"_toStringVisiting\", \"get$_toStringVisiting\", function() {\n  return P.HashSet_HashSet$identity(null);\n});\nIsolate.$lazy($, \"_toStringList\", \"Maps__toStringList\", \"get$Maps__toStringList\", function() {\n  return [];\n});\n// Native classes\n\ninit.functionAliases = {};\n;\ninit.metadata = [{func: \"void_\", void: true},\n{func: \"void__dynamic\", void: true, args: [null]},\n{func: \"void__dynamic__StackTrace\", void: true, args: [null], opt: [P.StackTrace]},\n,\n{func: \"bool__dynamic_dynamic\", ret: J.JSBool, args: [null, null]},\n{func: \"int__dynamic\", ret: J.JSInt, args: [null]},\n{func: \"bool__Object_Object\", ret: J.JSBool, args: [P.Object, P.Object]},\n{func: \"int__Object\", ret: J.JSInt, args: [P.Object]},\n{func: \"args0\"},\n{func: \"args2\", args: [null, null]},\n{func: \"args1\", args: [null]},\n{func: \"dynamic__dynamic_String\", args: [null, J.JSString]},\n{func: \"dynamic__String\", args: [J.JSString]},\n{func: \"void__num\", void: true, args: [J.JSNumber]},\n{func: \"dynamic__dynamic__dynamic\", args: [null], opt: [null]},\n{func: \"dynamic__dynamic_StackTrace\", args: [null, P.StackTrace]},\n{func: \"dynamic__Symbol_dynamic\", args: [P.Symbol, null]},\n{func: \"String__int\", ret: J.JSString, args: [J.JSInt]},\n];\n$ = null;\nIsolate = Isolate.$finishIsolateConstructor(Isolate);\n$ = new Isolate();\nfunction convertToFastObject(properties) {\n  function MyClass() {};\n  MyClass.prototype = properties;\n  new MyClass();\n  return properties;\n}\nA = convertToFastObject(A);\nB = convertToFastObject(B);\nC = convertToFastObject(C);\nD = convertToFastObject(D);\nE = convertToFastObject(E);\nF = convertToFastObject(F);\nG = convertToFastObject(G);\nH = convertToFastObject(H);\nJ = convertToFastObject(J);\nK = convertToFastObject(K);\nL = convertToFastObject(L);\nM = convertToFastObject(M);\nN = convertToFastObject(N);\nO = convertToFastObject(O);\nP = convertToFastObject(P);\nQ = convertToFastObject(Q);\nR = convertToFastObject(R);\nS = convertToFastObject(S);\nT = convertToFastObject(T);\nU = convertToFastObject(U);\nV = convertToFastObject(V);\nW = convertToFastObject(W);\nX = convertToFastObject(X);\nY = convertToFastObject(Y);\nZ = convertToFastObject(Z);\n!function() {\n  var objectProto = Object.prototype;\n  for (var i = 0;; i++) {\n    var property = \"___dart_dispatch_record_ZxYxX_0_\";\n    if (i > 0)\n      property = rootProperty + \"_\" + i;\n    if (!(property in objectProto))\n      return init.dispatchPropertyName = property;\n  }\n}();\n// BEGIN invoke [main].\n;(function (callback) {\n  if (typeof document === \"undefined\") {\n    callback(null);\n    return;\n  }\n  if (document.currentScript) {\n    callback(document.currentScript);\n    return;\n  }\n\n  var scripts = document.scripts;\n  function onLoad(event) {\n    for (var i = 0; i < scripts.length; ++i) {\n      scripts[i].removeEventListener(\"load\", onLoad, false);\n    }\n    callback(event.target);\n  }\n  for (var i = 0; i < scripts.length; ++i) {\n    scripts[i].addEventListener(\"load\", onLoad, false);\n  }\n})(function(currentScript) {\n  init.currentScript = currentScript;\n\n  if (typeof dartMainRunner === \"function\") {\n    dartMainRunner(function() { H.startRootIsolate(Q.main$closure()); });\n  } else {\n    H.startRootIsolate(Q.main$closure());\n  }\n});\n// END invoke [main].\nfunction init() {\n  Isolate.$isolateProperties = {};\n  function generateAccessor(fieldDescriptor, accessors, cls) {\n    var fieldInformation = fieldDescriptor.split(\"-\");\n    var field = fieldInformation[0];\n    var len = field.length;\n    var code = field.charCodeAt(len - 1);\n    var reflectable;\n    if (fieldInformation.length > 1)\n      reflectable = true;\n    else\n      reflectable = false;\n    code = code >= 60 && code <= 64 ? code - 59 : code >= 123 && code <= 126 ? code - 117 : code >= 37 && code <= 43 ? code - 27 : 0;\n    if (code) {\n      var getterCode = code & 3;\n      var setterCode = code >> 2;\n      var accessorName = field = field.substring(0, len - 1);\n      var divider = field.indexOf(\":\");\n      if (divider > 0) {\n        accessorName = field.substring(0, divider);\n        field = field.substring(divider + 1);\n      }\n      if (getterCode) {\n        var args = getterCode & 2 ? \"receiver\" : \"\";\n        var receiver = getterCode & 1 ? \"this\" : \"receiver\";\n        var body = \"return \" + receiver + \".\" + field;\n        var property = cls + \".prototype.get$\" + accessorName + \"=\";\n        var fn = \"function(\" + args + \"){\" + body + \"}\";\n        if (reflectable)\n          accessors.push(property + \"$reflectable(\" + fn + \");\\n\");\n        else\n          accessors.push(property + fn + \";\\n\");\n      }\n      if (setterCode) {\n        var args = setterCode & 2 ? \"receiver, value\" : \"value\";\n        var receiver = setterCode & 1 ? \"this\" : \"receiver\";\n        var body = receiver + \".\" + field + \" = value\";\n        var property = cls + \".prototype.set$\" + accessorName + \"=\";\n        var fn = \"function(\" + args + \"){\" + body + \"}\";\n        if (reflectable)\n          accessors.push(property + \"$reflectable(\" + fn + \");\\n\");\n        else\n          accessors.push(property + fn + \";\\n\");\n      }\n    }\n    return field;\n  }\n  Isolate.$isolateProperties.$generateAccessor = generateAccessor;\n  function defineClass(name, cls, fields) {\n    var accessors = [];\n    var str = \"function \" + cls + \"(\";\n    var body = \"\";\n    for (var i = 0; i < fields.length; i++) {\n      if (i != 0)\n        str += \", \";\n      var field = generateAccessor(fields[i], accessors, cls);\n      var parameter = \"parameter_\" + field;\n      str += parameter;\n      body += \"this.\" + field + \" = \" + parameter + \";\\n\";\n    }\n    str += \") {\\n\" + body + \"}\\n\";\n    str += cls + \".builtin$cls=\\\"\" + name + \"\\\";\\n\";\n    str += \"$desc=$collectedClasses.\" + cls + \";\\n\";\n    str += \"if($desc instanceof Array) $desc = $desc[1];\\n\";\n    str += cls + \".prototype = $desc;\\n\";\n    if (typeof defineClass.name != \"string\") {\n      str += cls + \".name=\\\"\" + cls + \"\\\";\\n\";\n    }\n    str += accessors.join(\"\");\n    return str;\n  }\n  var inheritFrom = function() {\n    function tmp() {\n    }\n    var hasOwnProperty = Object.prototype.hasOwnProperty;\n    return function(constructor, superConstructor) {\n      tmp.prototype = superConstructor.prototype;\n      var object = new tmp();\n      var properties = constructor.prototype;\n      for (var member in properties)\n        if (hasOwnProperty.call(properties, member))\n          object[member] = properties[member];\n      object.constructor = constructor;\n      constructor.prototype = object;\n      return object;\n    };\n  }();\n  Isolate.$finishClasses = function(collectedClasses, isolateProperties, existingIsolateProperties) {\n    var pendingClasses = {};\n    if (!init.allClasses)\n      init.allClasses = {};\n    var allClasses = init.allClasses;\n    var hasOwnProperty = Object.prototype.hasOwnProperty;\n    if (typeof dart_precompiled == \"function\") {\n      var constructors = dart_precompiled(collectedClasses);\n    } else {\n      var combinedConstructorFunction = \"function $reflectable(fn){fn.$reflectable=1;return fn};\\n\" + \"var $desc;\\n\";\n      var constructorsList = [];\n    }\n    for (var cls in collectedClasses) {\n      if (hasOwnProperty.call(collectedClasses, cls)) {\n        var desc = collectedClasses[cls];\n        if (desc instanceof Array)\n          desc = desc[1];\n        var classData = desc[\"\"], supr, name = cls, fields = classData;\n        if (typeof classData == \"string\") {\n          var split = classData.split(\"/\");\n          if (split.length == 2) {\n            name = split[0];\n            fields = split[1];\n          }\n        }\n        var s = fields.split(\";\");\n        fields = s[1] == \"\" ? [] : s[1].split(\",\");\n        supr = s[0];\n        split = supr.split(\":\");\n        if (split.length == 2) {\n          supr = split[0];\n          var functionSignature = split[1];\n          if (functionSignature)\n            desc.$signature = function(s) {\n              return function() {\n                return init.metadata[s];\n              };\n            }(functionSignature);\n        }\n        if (supr && supr.indexOf(\"+\") > 0) {\n          s = supr.split(\"+\");\n          supr = s[0];\n          var mixin = collectedClasses[s[1]];\n          if (mixin instanceof Array)\n            mixin = mixin[1];\n          for (var d in mixin) {\n            if (hasOwnProperty.call(mixin, d) && !hasOwnProperty.call(desc, d))\n              desc[d] = mixin[d];\n          }\n        }\n        if (typeof dart_precompiled != \"function\") {\n          combinedConstructorFunction += defineClass(name, cls, fields);\n          constructorsList.push(cls);\n        }\n        if (supr)\n          pendingClasses[cls] = supr;\n      }\n    }\n    if (typeof dart_precompiled != \"function\") {\n      combinedConstructorFunction += \"return [\\n  \" + constructorsList.join(\",\\n  \") + \"\\n]\";\n      var constructors = new Function(\"$collectedClasses\", combinedConstructorFunction)(collectedClasses);\n      combinedConstructorFunction = null;\n    }\n    for (var i = 0; i < constructors.length; i++) {\n      var constructor = constructors[i];\n      var cls = constructor.name;\n      var desc = collectedClasses[cls];\n      var globalObject = isolateProperties;\n      if (desc instanceof Array) {\n        globalObject = desc[0] || isolateProperties;\n        desc = desc[1];\n      }\n      allClasses[cls] = constructor;\n      globalObject[cls] = constructor;\n    }\n    constructors = null;\n    var finishedClasses = {};\n    init.interceptorsByTag = Object.create(null);\n    init.leafTags = {};\n    function finishClass(cls) {\n      var hasOwnProperty = Object.prototype.hasOwnProperty;\n      if (hasOwnProperty.call(finishedClasses, cls))\n        return;\n      finishedClasses[cls] = true;\n      var superclass = pendingClasses[cls];\n      if (!superclass || typeof superclass != \"string\")\n        return;\n      finishClass(superclass);\n      var constructor = allClasses[cls];\n      var superConstructor = allClasses[superclass];\n      if (!superConstructor)\n        superConstructor = existingIsolateProperties[superclass];\n      var prototype = inheritFrom(constructor, superConstructor);\n      if (hasOwnProperty.call(prototype, \"%\")) {\n        var nativeSpec = prototype[\"%\"].split(\";\");\n        if (nativeSpec[0]) {\n          var tags = nativeSpec[0].split(\"|\");\n          for (var i = 0; i < tags.length; i++) {\n            init.interceptorsByTag[tags[i]] = constructor;\n            init.leafTags[tags[i]] = true;\n          }\n        }\n        if (nativeSpec[1]) {\n          tags = nativeSpec[1].split(\"|\");\n          if (nativeSpec[2]) {\n            var subclasses = nativeSpec[2].split(\"|\");\n            for (var i = 0; i < subclasses.length; i++) {\n              var subclass = allClasses[subclasses[i]];\n              subclass.$nativeSuperclassTag = tags[0];\n            }\n          }\n          for (i = 0; i < tags.length; i++) {\n            init.interceptorsByTag[tags[i]] = constructor;\n            init.leafTags[tags[i]] = false;\n          }\n        }\n      }\n    }\n    for (var cls in pendingClasses)\n      finishClass(cls);\n  };\n  Isolate.$lazy = function(prototype, staticName, fieldName, getterName, lazyValue) {\n    var sentinelUndefined = {};\n    var sentinelInProgress = {};\n    prototype[fieldName] = sentinelUndefined;\n    prototype[getterName] = function() {\n      var result = $[fieldName];\n      try {\n        if (result === sentinelUndefined) {\n          $[fieldName] = sentinelInProgress;\n          try {\n            result = $[fieldName] = lazyValue();\n          } finally {\n            if (result === sentinelUndefined) {\n              if ($[fieldName] === sentinelInProgress) {\n                $[fieldName] = null;\n              }\n            }\n          }\n        } else {\n          if (result === sentinelInProgress)\n            H.throwCyclicInit(staticName);\n        }\n        return result;\n      } finally {\n        $[getterName] = function() {\n          return this[fieldName];\n        };\n      }\n    };\n  };\n  Isolate.$finishIsolateConstructor = function(oldIsolate) {\n    var isolateProperties = oldIsolate.$isolateProperties;\n    function Isolate() {\n      var hasOwnProperty = Object.prototype.hasOwnProperty;\n      for (var staticName in isolateProperties)\n        if (hasOwnProperty.call(isolateProperties, staticName))\n          this[staticName] = isolateProperties[staticName];\n      function ForceEfficientMap() {\n      }\n      ForceEfficientMap.prototype = this;\n      new ForceEfficientMap();\n    }\n    Isolate.prototype = oldIsolate.prototype;\n    Isolate.prototype.constructor = Isolate;\n    Isolate.$isolateProperties = isolateProperties;\n    Isolate.$finishClasses = oldIsolate.$finishClasses;\n    Isolate.makeConstantList = oldIsolate.makeConstantList;\n    return Isolate;\n  };\n}\n})()\nfunction dart_precompiled($collectedClasses) {\n  var $desc;\n  function HtmlElement() {\n  }\n  HtmlElement.builtin$cls = \"HtmlElement\";\n  if (!\"name\" in HtmlElement)\n    HtmlElement.name = \"HtmlElement\";\n  $desc = $collectedClasses.HtmlElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  HtmlElement.prototype = $desc;\n  function AnchorElement() {\n  }\n  AnchorElement.builtin$cls = \"AnchorElement\";\n  if (!\"name\" in AnchorElement)\n    AnchorElement.name = \"AnchorElement\";\n  $desc = $collectedClasses.AnchorElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AnchorElement.prototype = $desc;\n  function AnimationEvent() {\n  }\n  AnimationEvent.builtin$cls = \"AnimationEvent\";\n  if (!\"name\" in AnimationEvent)\n    AnimationEvent.name = \"AnimationEvent\";\n  $desc = $collectedClasses.AnimationEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AnimationEvent.prototype = $desc;\n  function AreaElement() {\n  }\n  AreaElement.builtin$cls = \"AreaElement\";\n  if (!\"name\" in AreaElement)\n    AreaElement.name = \"AreaElement\";\n  $desc = $collectedClasses.AreaElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AreaElement.prototype = $desc;\n  function AudioElement() {\n  }\n  AudioElement.builtin$cls = \"AudioElement\";\n  if (!\"name\" in AudioElement)\n    AudioElement.name = \"AudioElement\";\n  $desc = $collectedClasses.AudioElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AudioElement.prototype = $desc;\n  function AutocompleteErrorEvent() {\n  }\n  AutocompleteErrorEvent.builtin$cls = \"AutocompleteErrorEvent\";\n  if (!\"name\" in AutocompleteErrorEvent)\n    AutocompleteErrorEvent.name = \"AutocompleteErrorEvent\";\n  $desc = $collectedClasses.AutocompleteErrorEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AutocompleteErrorEvent.prototype = $desc;\n  function BRElement() {\n  }\n  BRElement.builtin$cls = \"BRElement\";\n  if (!\"name\" in BRElement)\n    BRElement.name = \"BRElement\";\n  $desc = $collectedClasses.BRElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  BRElement.prototype = $desc;\n  function BaseElement() {\n  }\n  BaseElement.builtin$cls = \"BaseElement\";\n  if (!\"name\" in BaseElement)\n    BaseElement.name = \"BaseElement\";\n  $desc = $collectedClasses.BaseElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  BaseElement.prototype = $desc;\n  function BeforeLoadEvent() {\n  }\n  BeforeLoadEvent.builtin$cls = \"BeforeLoadEvent\";\n  if (!\"name\" in BeforeLoadEvent)\n    BeforeLoadEvent.name = \"BeforeLoadEvent\";\n  $desc = $collectedClasses.BeforeLoadEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  BeforeLoadEvent.prototype = $desc;\n  function BeforeUnloadEvent() {\n  }\n  BeforeUnloadEvent.builtin$cls = \"BeforeUnloadEvent\";\n  if (!\"name\" in BeforeUnloadEvent)\n    BeforeUnloadEvent.name = \"BeforeUnloadEvent\";\n  $desc = $collectedClasses.BeforeUnloadEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  BeforeUnloadEvent.prototype = $desc;\n  function BodyElement() {\n  }\n  BodyElement.builtin$cls = \"BodyElement\";\n  if (!\"name\" in BodyElement)\n    BodyElement.name = \"BodyElement\";\n  $desc = $collectedClasses.BodyElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  BodyElement.prototype = $desc;\n  function ButtonElement() {\n  }\n  ButtonElement.builtin$cls = \"ButtonElement\";\n  if (!\"name\" in ButtonElement)\n    ButtonElement.name = \"ButtonElement\";\n  $desc = $collectedClasses.ButtonElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ButtonElement.prototype = $desc;\n  function CDataSection() {\n  }\n  CDataSection.builtin$cls = \"CDataSection\";\n  if (!\"name\" in CDataSection)\n    CDataSection.name = \"CDataSection\";\n  $desc = $collectedClasses.CDataSection;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  CDataSection.prototype = $desc;\n  function CanvasElement() {\n  }\n  CanvasElement.builtin$cls = \"CanvasElement\";\n  if (!\"name\" in CanvasElement)\n    CanvasElement.name = \"CanvasElement\";\n  $desc = $collectedClasses.CanvasElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  CanvasElement.prototype = $desc;\n  function CharacterData() {\n  }\n  CharacterData.builtin$cls = \"CharacterData\";\n  if (!\"name\" in CharacterData)\n    CharacterData.name = \"CharacterData\";\n  $desc = $collectedClasses.CharacterData;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  CharacterData.prototype = $desc;\n  CharacterData.prototype.get$length = function(receiver) {\n    return receiver.length;\n  };\n  function CloseEvent() {\n  }\n  CloseEvent.builtin$cls = \"CloseEvent\";\n  if (!\"name\" in CloseEvent)\n    CloseEvent.name = \"CloseEvent\";\n  $desc = $collectedClasses.CloseEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  CloseEvent.prototype = $desc;\n  function Comment() {\n  }\n  Comment.builtin$cls = \"Comment\";\n  if (!\"name\" in Comment)\n    Comment.name = \"Comment\";\n  $desc = $collectedClasses.Comment;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Comment.prototype = $desc;\n  function CompositionEvent() {\n  }\n  CompositionEvent.builtin$cls = \"CompositionEvent\";\n  if (!\"name\" in CompositionEvent)\n    CompositionEvent.name = \"CompositionEvent\";\n  $desc = $collectedClasses.CompositionEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  CompositionEvent.prototype = $desc;\n  function ContentElement() {\n  }\n  ContentElement.builtin$cls = \"ContentElement\";\n  if (!\"name\" in ContentElement)\n    ContentElement.name = \"ContentElement\";\n  $desc = $collectedClasses.ContentElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ContentElement.prototype = $desc;\n  function CssFontFaceLoadEvent() {\n  }\n  CssFontFaceLoadEvent.builtin$cls = \"CssFontFaceLoadEvent\";\n  if (!\"name\" in CssFontFaceLoadEvent)\n    CssFontFaceLoadEvent.name = \"CssFontFaceLoadEvent\";\n  $desc = $collectedClasses.CssFontFaceLoadEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  CssFontFaceLoadEvent.prototype = $desc;\n  function CssStyleDeclaration() {\n  }\n  CssStyleDeclaration.builtin$cls = \"CssStyleDeclaration\";\n  if (!\"name\" in CssStyleDeclaration)\n    CssStyleDeclaration.name = \"CssStyleDeclaration\";\n  $desc = $collectedClasses.CssStyleDeclaration;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  CssStyleDeclaration.prototype = $desc;\n  CssStyleDeclaration.prototype.get$length = function(receiver) {\n    return receiver.length;\n  };\n  function CustomEvent() {\n  }\n  CustomEvent.builtin$cls = \"CustomEvent\";\n  if (!\"name\" in CustomEvent)\n    CustomEvent.name = \"CustomEvent\";\n  $desc = $collectedClasses.CustomEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  CustomEvent.prototype = $desc;\n  function DListElement() {\n  }\n  DListElement.builtin$cls = \"DListElement\";\n  if (!\"name\" in DListElement)\n    DListElement.name = \"DListElement\";\n  $desc = $collectedClasses.DListElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DListElement.prototype = $desc;\n  function DataListElement() {\n  }\n  DataListElement.builtin$cls = \"DataListElement\";\n  if (!\"name\" in DataListElement)\n    DataListElement.name = \"DataListElement\";\n  $desc = $collectedClasses.DataListElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DataListElement.prototype = $desc;\n  function DetailsElement() {\n  }\n  DetailsElement.builtin$cls = \"DetailsElement\";\n  if (!\"name\" in DetailsElement)\n    DetailsElement.name = \"DetailsElement\";\n  $desc = $collectedClasses.DetailsElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DetailsElement.prototype = $desc;\n  function DeviceMotionEvent() {\n  }\n  DeviceMotionEvent.builtin$cls = \"DeviceMotionEvent\";\n  if (!\"name\" in DeviceMotionEvent)\n    DeviceMotionEvent.name = \"DeviceMotionEvent\";\n  $desc = $collectedClasses.DeviceMotionEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DeviceMotionEvent.prototype = $desc;\n  function DeviceOrientationEvent() {\n  }\n  DeviceOrientationEvent.builtin$cls = \"DeviceOrientationEvent\";\n  if (!\"name\" in DeviceOrientationEvent)\n    DeviceOrientationEvent.name = \"DeviceOrientationEvent\";\n  $desc = $collectedClasses.DeviceOrientationEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DeviceOrientationEvent.prototype = $desc;\n  function DialogElement() {\n  }\n  DialogElement.builtin$cls = \"DialogElement\";\n  if (!\"name\" in DialogElement)\n    DialogElement.name = \"DialogElement\";\n  $desc = $collectedClasses.DialogElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DialogElement.prototype = $desc;\n  function DivElement() {\n  }\n  DivElement.builtin$cls = \"DivElement\";\n  if (!\"name\" in DivElement)\n    DivElement.name = \"DivElement\";\n  $desc = $collectedClasses.DivElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DivElement.prototype = $desc;\n  function Document() {\n  }\n  Document.builtin$cls = \"Document\";\n  if (!\"name\" in Document)\n    Document.name = \"Document\";\n  $desc = $collectedClasses.Document;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Document.prototype = $desc;\n  function DocumentFragment() {\n  }\n  DocumentFragment.builtin$cls = \"DocumentFragment\";\n  if (!\"name\" in DocumentFragment)\n    DocumentFragment.name = \"DocumentFragment\";\n  $desc = $collectedClasses.DocumentFragment;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DocumentFragment.prototype = $desc;\n  function DocumentType() {\n  }\n  DocumentType.builtin$cls = \"DocumentType\";\n  if (!\"name\" in DocumentType)\n    DocumentType.name = \"DocumentType\";\n  $desc = $collectedClasses.DocumentType;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DocumentType.prototype = $desc;\n  function DomError() {\n  }\n  DomError.builtin$cls = \"DomError\";\n  if (!\"name\" in DomError)\n    DomError.name = \"DomError\";\n  $desc = $collectedClasses.DomError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DomError.prototype = $desc;\n  function DomException() {\n  }\n  DomException.builtin$cls = \"DomException\";\n  if (!\"name\" in DomException)\n    DomException.name = \"DomException\";\n  $desc = $collectedClasses.DomException;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DomException.prototype = $desc;\n  function Element() {\n  }\n  Element.builtin$cls = \"Element\";\n  if (!\"name\" in Element)\n    Element.name = \"Element\";\n  $desc = $collectedClasses.Element;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Element.prototype = $desc;\n  function EmbedElement() {\n  }\n  EmbedElement.builtin$cls = \"EmbedElement\";\n  if (!\"name\" in EmbedElement)\n    EmbedElement.name = \"EmbedElement\";\n  $desc = $collectedClasses.EmbedElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  EmbedElement.prototype = $desc;\n  EmbedElement.prototype.set$src = function(receiver, v) {\n    return receiver.src = v;\n  };\n  function ErrorEvent() {\n  }\n  ErrorEvent.builtin$cls = \"ErrorEvent\";\n  if (!\"name\" in ErrorEvent)\n    ErrorEvent.name = \"ErrorEvent\";\n  $desc = $collectedClasses.ErrorEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ErrorEvent.prototype = $desc;\n  ErrorEvent.prototype.get$error = function(receiver) {\n    return receiver.error;\n  };\n  function Event() {\n  }\n  Event.builtin$cls = \"Event\";\n  if (!\"name\" in Event)\n    Event.name = \"Event\";\n  $desc = $collectedClasses.Event;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Event.prototype = $desc;\n  function EventTarget() {\n  }\n  EventTarget.builtin$cls = \"EventTarget\";\n  if (!\"name\" in EventTarget)\n    EventTarget.name = \"EventTarget\";\n  $desc = $collectedClasses.EventTarget;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  EventTarget.prototype = $desc;\n  function FieldSetElement() {\n  }\n  FieldSetElement.builtin$cls = \"FieldSetElement\";\n  if (!\"name\" in FieldSetElement)\n    FieldSetElement.name = \"FieldSetElement\";\n  $desc = $collectedClasses.FieldSetElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FieldSetElement.prototype = $desc;\n  function FileError() {\n  }\n  FileError.builtin$cls = \"FileError\";\n  if (!\"name\" in FileError)\n    FileError.name = \"FileError\";\n  $desc = $collectedClasses.FileError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FileError.prototype = $desc;\n  function FocusEvent() {\n  }\n  FocusEvent.builtin$cls = \"FocusEvent\";\n  if (!\"name\" in FocusEvent)\n    FocusEvent.name = \"FocusEvent\";\n  $desc = $collectedClasses.FocusEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FocusEvent.prototype = $desc;\n  function FormElement() {\n  }\n  FormElement.builtin$cls = \"FormElement\";\n  if (!\"name\" in FormElement)\n    FormElement.name = \"FormElement\";\n  $desc = $collectedClasses.FormElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FormElement.prototype = $desc;\n  FormElement.prototype.get$length = function(receiver) {\n    return receiver.length;\n  };\n  function HRElement() {\n  }\n  HRElement.builtin$cls = \"HRElement\";\n  if (!\"name\" in HRElement)\n    HRElement.name = \"HRElement\";\n  $desc = $collectedClasses.HRElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  HRElement.prototype = $desc;\n  function HashChangeEvent() {\n  }\n  HashChangeEvent.builtin$cls = \"HashChangeEvent\";\n  if (!\"name\" in HashChangeEvent)\n    HashChangeEvent.name = \"HashChangeEvent\";\n  $desc = $collectedClasses.HashChangeEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  HashChangeEvent.prototype = $desc;\n  function HeadElement() {\n  }\n  HeadElement.builtin$cls = \"HeadElement\";\n  if (!\"name\" in HeadElement)\n    HeadElement.name = \"HeadElement\";\n  $desc = $collectedClasses.HeadElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  HeadElement.prototype = $desc;\n  function HeadingElement() {\n  }\n  HeadingElement.builtin$cls = \"HeadingElement\";\n  if (!\"name\" in HeadingElement)\n    HeadingElement.name = \"HeadingElement\";\n  $desc = $collectedClasses.HeadingElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  HeadingElement.prototype = $desc;\n  function HtmlDocument() {\n  }\n  HtmlDocument.builtin$cls = \"HtmlDocument\";\n  if (!\"name\" in HtmlDocument)\n    HtmlDocument.name = \"HtmlDocument\";\n  $desc = $collectedClasses.HtmlDocument;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  HtmlDocument.prototype = $desc;\n  function HtmlHtmlElement() {\n  }\n  HtmlHtmlElement.builtin$cls = \"HtmlHtmlElement\";\n  if (!\"name\" in HtmlHtmlElement)\n    HtmlHtmlElement.name = \"HtmlHtmlElement\";\n  $desc = $collectedClasses.HtmlHtmlElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  HtmlHtmlElement.prototype = $desc;\n  function IFrameElement() {\n  }\n  IFrameElement.builtin$cls = \"IFrameElement\";\n  if (!\"name\" in IFrameElement)\n    IFrameElement.name = \"IFrameElement\";\n  $desc = $collectedClasses.IFrameElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  IFrameElement.prototype = $desc;\n  IFrameElement.prototype.set$src = function(receiver, v) {\n    return receiver.src = v;\n  };\n  function ImageElement() {\n  }\n  ImageElement.builtin$cls = \"ImageElement\";\n  if (!\"name\" in ImageElement)\n    ImageElement.name = \"ImageElement\";\n  $desc = $collectedClasses.ImageElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ImageElement.prototype = $desc;\n  ImageElement.prototype.set$src = function(receiver, v) {\n    return receiver.src = v;\n  };\n  function InputElement() {\n  }\n  InputElement.builtin$cls = \"InputElement\";\n  if (!\"name\" in InputElement)\n    InputElement.name = \"InputElement\";\n  $desc = $collectedClasses.InputElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  InputElement.prototype = $desc;\n  InputElement.prototype.set$src = function(receiver, v) {\n    return receiver.src = v;\n  };\n  function KeyboardEvent() {\n  }\n  KeyboardEvent.builtin$cls = \"KeyboardEvent\";\n  if (!\"name\" in KeyboardEvent)\n    KeyboardEvent.name = \"KeyboardEvent\";\n  $desc = $collectedClasses.KeyboardEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  KeyboardEvent.prototype = $desc;\n  function KeygenElement() {\n  }\n  KeygenElement.builtin$cls = \"KeygenElement\";\n  if (!\"name\" in KeygenElement)\n    KeygenElement.name = \"KeygenElement\";\n  $desc = $collectedClasses.KeygenElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  KeygenElement.prototype = $desc;\n  function LIElement() {\n  }\n  LIElement.builtin$cls = \"LIElement\";\n  if (!\"name\" in LIElement)\n    LIElement.name = \"LIElement\";\n  $desc = $collectedClasses.LIElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  LIElement.prototype = $desc;\n  function LabelElement() {\n  }\n  LabelElement.builtin$cls = \"LabelElement\";\n  if (!\"name\" in LabelElement)\n    LabelElement.name = \"LabelElement\";\n  $desc = $collectedClasses.LabelElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  LabelElement.prototype = $desc;\n  function LegendElement() {\n  }\n  LegendElement.builtin$cls = \"LegendElement\";\n  if (!\"name\" in LegendElement)\n    LegendElement.name = \"LegendElement\";\n  $desc = $collectedClasses.LegendElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  LegendElement.prototype = $desc;\n  function LinkElement() {\n  }\n  LinkElement.builtin$cls = \"LinkElement\";\n  if (!\"name\" in LinkElement)\n    LinkElement.name = \"LinkElement\";\n  $desc = $collectedClasses.LinkElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  LinkElement.prototype = $desc;\n  function MapElement() {\n  }\n  MapElement.builtin$cls = \"MapElement\";\n  if (!\"name\" in MapElement)\n    MapElement.name = \"MapElement\";\n  $desc = $collectedClasses.MapElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MapElement.prototype = $desc;\n  function MediaElement() {\n  }\n  MediaElement.builtin$cls = \"MediaElement\";\n  if (!\"name\" in MediaElement)\n    MediaElement.name = \"MediaElement\";\n  $desc = $collectedClasses.MediaElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MediaElement.prototype = $desc;\n  MediaElement.prototype.get$error = function(receiver) {\n    return receiver.error;\n  };\n  MediaElement.prototype.set$src = function(receiver, v) {\n    return receiver.src = v;\n  };\n  function MediaError() {\n  }\n  MediaError.builtin$cls = \"MediaError\";\n  if (!\"name\" in MediaError)\n    MediaError.name = \"MediaError\";\n  $desc = $collectedClasses.MediaError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MediaError.prototype = $desc;\n  function MediaKeyError() {\n  }\n  MediaKeyError.builtin$cls = \"MediaKeyError\";\n  if (!\"name\" in MediaKeyError)\n    MediaKeyError.name = \"MediaKeyError\";\n  $desc = $collectedClasses.MediaKeyError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MediaKeyError.prototype = $desc;\n  function MediaKeyEvent() {\n  }\n  MediaKeyEvent.builtin$cls = \"MediaKeyEvent\";\n  if (!\"name\" in MediaKeyEvent)\n    MediaKeyEvent.name = \"MediaKeyEvent\";\n  $desc = $collectedClasses.MediaKeyEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MediaKeyEvent.prototype = $desc;\n  function MediaKeyMessageEvent() {\n  }\n  MediaKeyMessageEvent.builtin$cls = \"MediaKeyMessageEvent\";\n  if (!\"name\" in MediaKeyMessageEvent)\n    MediaKeyMessageEvent.name = \"MediaKeyMessageEvent\";\n  $desc = $collectedClasses.MediaKeyMessageEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MediaKeyMessageEvent.prototype = $desc;\n  function MediaKeyNeededEvent() {\n  }\n  MediaKeyNeededEvent.builtin$cls = \"MediaKeyNeededEvent\";\n  if (!\"name\" in MediaKeyNeededEvent)\n    MediaKeyNeededEvent.name = \"MediaKeyNeededEvent\";\n  $desc = $collectedClasses.MediaKeyNeededEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MediaKeyNeededEvent.prototype = $desc;\n  function MediaStream() {\n  }\n  MediaStream.builtin$cls = \"MediaStream\";\n  if (!\"name\" in MediaStream)\n    MediaStream.name = \"MediaStream\";\n  $desc = $collectedClasses.MediaStream;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MediaStream.prototype = $desc;\n  function MediaStreamEvent() {\n  }\n  MediaStreamEvent.builtin$cls = \"MediaStreamEvent\";\n  if (!\"name\" in MediaStreamEvent)\n    MediaStreamEvent.name = \"MediaStreamEvent\";\n  $desc = $collectedClasses.MediaStreamEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MediaStreamEvent.prototype = $desc;\n  function MediaStreamTrackEvent() {\n  }\n  MediaStreamTrackEvent.builtin$cls = \"MediaStreamTrackEvent\";\n  if (!\"name\" in MediaStreamTrackEvent)\n    MediaStreamTrackEvent.name = \"MediaStreamTrackEvent\";\n  $desc = $collectedClasses.MediaStreamTrackEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MediaStreamTrackEvent.prototype = $desc;\n  function MenuElement() {\n  }\n  MenuElement.builtin$cls = \"MenuElement\";\n  if (!\"name\" in MenuElement)\n    MenuElement.name = \"MenuElement\";\n  $desc = $collectedClasses.MenuElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MenuElement.prototype = $desc;\n  function MessageEvent() {\n  }\n  MessageEvent.builtin$cls = \"MessageEvent\";\n  if (!\"name\" in MessageEvent)\n    MessageEvent.name = \"MessageEvent\";\n  $desc = $collectedClasses.MessageEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MessageEvent.prototype = $desc;\n  function MetaElement() {\n  }\n  MetaElement.builtin$cls = \"MetaElement\";\n  if (!\"name\" in MetaElement)\n    MetaElement.name = \"MetaElement\";\n  $desc = $collectedClasses.MetaElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MetaElement.prototype = $desc;\n  function MeterElement() {\n  }\n  MeterElement.builtin$cls = \"MeterElement\";\n  if (!\"name\" in MeterElement)\n    MeterElement.name = \"MeterElement\";\n  $desc = $collectedClasses.MeterElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MeterElement.prototype = $desc;\n  function MidiConnectionEvent() {\n  }\n  MidiConnectionEvent.builtin$cls = \"MidiConnectionEvent\";\n  if (!\"name\" in MidiConnectionEvent)\n    MidiConnectionEvent.name = \"MidiConnectionEvent\";\n  $desc = $collectedClasses.MidiConnectionEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MidiConnectionEvent.prototype = $desc;\n  function MidiMessageEvent() {\n  }\n  MidiMessageEvent.builtin$cls = \"MidiMessageEvent\";\n  if (!\"name\" in MidiMessageEvent)\n    MidiMessageEvent.name = \"MidiMessageEvent\";\n  $desc = $collectedClasses.MidiMessageEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MidiMessageEvent.prototype = $desc;\n  function ModElement() {\n  }\n  ModElement.builtin$cls = \"ModElement\";\n  if (!\"name\" in ModElement)\n    ModElement.name = \"ModElement\";\n  $desc = $collectedClasses.ModElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ModElement.prototype = $desc;\n  function MouseEvent() {\n  }\n  MouseEvent.builtin$cls = \"MouseEvent\";\n  if (!\"name\" in MouseEvent)\n    MouseEvent.name = \"MouseEvent\";\n  $desc = $collectedClasses.MouseEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MouseEvent.prototype = $desc;\n  function Navigator() {\n  }\n  Navigator.builtin$cls = \"Navigator\";\n  if (!\"name\" in Navigator)\n    Navigator.name = \"Navigator\";\n  $desc = $collectedClasses.Navigator;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Navigator.prototype = $desc;\n  function NavigatorUserMediaError() {\n  }\n  NavigatorUserMediaError.builtin$cls = \"NavigatorUserMediaError\";\n  if (!\"name\" in NavigatorUserMediaError)\n    NavigatorUserMediaError.name = \"NavigatorUserMediaError\";\n  $desc = $collectedClasses.NavigatorUserMediaError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  NavigatorUserMediaError.prototype = $desc;\n  function Node() {\n  }\n  Node.builtin$cls = \"Node\";\n  if (!\"name\" in Node)\n    Node.name = \"Node\";\n  $desc = $collectedClasses.Node;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Node.prototype = $desc;\n  function NodeList() {\n  }\n  NodeList.builtin$cls = \"NodeList\";\n  if (!\"name\" in NodeList)\n    NodeList.name = \"NodeList\";\n  $desc = $collectedClasses.NodeList;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  NodeList.prototype = $desc;\n  function OListElement() {\n  }\n  OListElement.builtin$cls = \"OListElement\";\n  if (!\"name\" in OListElement)\n    OListElement.name = \"OListElement\";\n  $desc = $collectedClasses.OListElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  OListElement.prototype = $desc;\n  function ObjectElement() {\n  }\n  ObjectElement.builtin$cls = \"ObjectElement\";\n  if (!\"name\" in ObjectElement)\n    ObjectElement.name = \"ObjectElement\";\n  $desc = $collectedClasses.ObjectElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ObjectElement.prototype = $desc;\n  function OptGroupElement() {\n  }\n  OptGroupElement.builtin$cls = \"OptGroupElement\";\n  if (!\"name\" in OptGroupElement)\n    OptGroupElement.name = \"OptGroupElement\";\n  $desc = $collectedClasses.OptGroupElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  OptGroupElement.prototype = $desc;\n  function OptionElement() {\n  }\n  OptionElement.builtin$cls = \"OptionElement\";\n  if (!\"name\" in OptionElement)\n    OptionElement.name = \"OptionElement\";\n  $desc = $collectedClasses.OptionElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  OptionElement.prototype = $desc;\n  function OutputElement() {\n  }\n  OutputElement.builtin$cls = \"OutputElement\";\n  if (!\"name\" in OutputElement)\n    OutputElement.name = \"OutputElement\";\n  $desc = $collectedClasses.OutputElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  OutputElement.prototype = $desc;\n  function OverflowEvent() {\n  }\n  OverflowEvent.builtin$cls = \"OverflowEvent\";\n  if (!\"name\" in OverflowEvent)\n    OverflowEvent.name = \"OverflowEvent\";\n  $desc = $collectedClasses.OverflowEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  OverflowEvent.prototype = $desc;\n  function PageTransitionEvent() {\n  }\n  PageTransitionEvent.builtin$cls = \"PageTransitionEvent\";\n  if (!\"name\" in PageTransitionEvent)\n    PageTransitionEvent.name = \"PageTransitionEvent\";\n  $desc = $collectedClasses.PageTransitionEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  PageTransitionEvent.prototype = $desc;\n  function ParagraphElement() {\n  }\n  ParagraphElement.builtin$cls = \"ParagraphElement\";\n  if (!\"name\" in ParagraphElement)\n    ParagraphElement.name = \"ParagraphElement\";\n  $desc = $collectedClasses.ParagraphElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ParagraphElement.prototype = $desc;\n  function ParamElement() {\n  }\n  ParamElement.builtin$cls = \"ParamElement\";\n  if (!\"name\" in ParamElement)\n    ParamElement.name = \"ParamElement\";\n  $desc = $collectedClasses.ParamElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ParamElement.prototype = $desc;\n  function PopStateEvent() {\n  }\n  PopStateEvent.builtin$cls = \"PopStateEvent\";\n  if (!\"name\" in PopStateEvent)\n    PopStateEvent.name = \"PopStateEvent\";\n  $desc = $collectedClasses.PopStateEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  PopStateEvent.prototype = $desc;\n  function PositionError() {\n  }\n  PositionError.builtin$cls = \"PositionError\";\n  if (!\"name\" in PositionError)\n    PositionError.name = \"PositionError\";\n  $desc = $collectedClasses.PositionError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  PositionError.prototype = $desc;\n  function PreElement() {\n  }\n  PreElement.builtin$cls = \"PreElement\";\n  if (!\"name\" in PreElement)\n    PreElement.name = \"PreElement\";\n  $desc = $collectedClasses.PreElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  PreElement.prototype = $desc;\n  function ProcessingInstruction() {\n  }\n  ProcessingInstruction.builtin$cls = \"ProcessingInstruction\";\n  if (!\"name\" in ProcessingInstruction)\n    ProcessingInstruction.name = \"ProcessingInstruction\";\n  $desc = $collectedClasses.ProcessingInstruction;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ProcessingInstruction.prototype = $desc;\n  function ProgressElement() {\n  }\n  ProgressElement.builtin$cls = \"ProgressElement\";\n  if (!\"name\" in ProgressElement)\n    ProgressElement.name = \"ProgressElement\";\n  $desc = $collectedClasses.ProgressElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ProgressElement.prototype = $desc;\n  function ProgressEvent() {\n  }\n  ProgressEvent.builtin$cls = \"ProgressEvent\";\n  if (!\"name\" in ProgressEvent)\n    ProgressEvent.name = \"ProgressEvent\";\n  $desc = $collectedClasses.ProgressEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ProgressEvent.prototype = $desc;\n  function QuoteElement() {\n  }\n  QuoteElement.builtin$cls = \"QuoteElement\";\n  if (!\"name\" in QuoteElement)\n    QuoteElement.name = \"QuoteElement\";\n  $desc = $collectedClasses.QuoteElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  QuoteElement.prototype = $desc;\n  function ResourceProgressEvent() {\n  }\n  ResourceProgressEvent.builtin$cls = \"ResourceProgressEvent\";\n  if (!\"name\" in ResourceProgressEvent)\n    ResourceProgressEvent.name = \"ResourceProgressEvent\";\n  $desc = $collectedClasses.ResourceProgressEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ResourceProgressEvent.prototype = $desc;\n  function RtcDataChannelEvent() {\n  }\n  RtcDataChannelEvent.builtin$cls = \"RtcDataChannelEvent\";\n  if (!\"name\" in RtcDataChannelEvent)\n    RtcDataChannelEvent.name = \"RtcDataChannelEvent\";\n  $desc = $collectedClasses.RtcDataChannelEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  RtcDataChannelEvent.prototype = $desc;\n  function RtcDtmfToneChangeEvent() {\n  }\n  RtcDtmfToneChangeEvent.builtin$cls = \"RtcDtmfToneChangeEvent\";\n  if (!\"name\" in RtcDtmfToneChangeEvent)\n    RtcDtmfToneChangeEvent.name = \"RtcDtmfToneChangeEvent\";\n  $desc = $collectedClasses.RtcDtmfToneChangeEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  RtcDtmfToneChangeEvent.prototype = $desc;\n  function RtcIceCandidateEvent() {\n  }\n  RtcIceCandidateEvent.builtin$cls = \"RtcIceCandidateEvent\";\n  if (!\"name\" in RtcIceCandidateEvent)\n    RtcIceCandidateEvent.name = \"RtcIceCandidateEvent\";\n  $desc = $collectedClasses.RtcIceCandidateEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  RtcIceCandidateEvent.prototype = $desc;\n  function ScriptElement() {\n  }\n  ScriptElement.builtin$cls = \"ScriptElement\";\n  if (!\"name\" in ScriptElement)\n    ScriptElement.name = \"ScriptElement\";\n  $desc = $collectedClasses.ScriptElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ScriptElement.prototype = $desc;\n  ScriptElement.prototype.set$src = function(receiver, v) {\n    return receiver.src = v;\n  };\n  function SecurityPolicyViolationEvent() {\n  }\n  SecurityPolicyViolationEvent.builtin$cls = \"SecurityPolicyViolationEvent\";\n  if (!\"name\" in SecurityPolicyViolationEvent)\n    SecurityPolicyViolationEvent.name = \"SecurityPolicyViolationEvent\";\n  $desc = $collectedClasses.SecurityPolicyViolationEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SecurityPolicyViolationEvent.prototype = $desc;\n  function SelectElement() {\n  }\n  SelectElement.builtin$cls = \"SelectElement\";\n  if (!\"name\" in SelectElement)\n    SelectElement.name = \"SelectElement\";\n  $desc = $collectedClasses.SelectElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SelectElement.prototype = $desc;\n  SelectElement.prototype.get$length = function(receiver) {\n    return receiver.length;\n  };\n  function ShadowElement() {\n  }\n  ShadowElement.builtin$cls = \"ShadowElement\";\n  if (!\"name\" in ShadowElement)\n    ShadowElement.name = \"ShadowElement\";\n  $desc = $collectedClasses.ShadowElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ShadowElement.prototype = $desc;\n  function ShadowRoot() {\n  }\n  ShadowRoot.builtin$cls = \"ShadowRoot\";\n  if (!\"name\" in ShadowRoot)\n    ShadowRoot.name = \"ShadowRoot\";\n  $desc = $collectedClasses.ShadowRoot;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ShadowRoot.prototype = $desc;\n  function SourceElement() {\n  }\n  SourceElement.builtin$cls = \"SourceElement\";\n  if (!\"name\" in SourceElement)\n    SourceElement.name = \"SourceElement\";\n  $desc = $collectedClasses.SourceElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SourceElement.prototype = $desc;\n  SourceElement.prototype.set$src = function(receiver, v) {\n    return receiver.src = v;\n  };\n  function SpanElement() {\n  }\n  SpanElement.builtin$cls = \"SpanElement\";\n  if (!\"name\" in SpanElement)\n    SpanElement.name = \"SpanElement\";\n  $desc = $collectedClasses.SpanElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SpanElement.prototype = $desc;\n  function SpeechInputEvent() {\n  }\n  SpeechInputEvent.builtin$cls = \"SpeechInputEvent\";\n  if (!\"name\" in SpeechInputEvent)\n    SpeechInputEvent.name = \"SpeechInputEvent\";\n  $desc = $collectedClasses.SpeechInputEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SpeechInputEvent.prototype = $desc;\n  function SpeechRecognitionError() {\n  }\n  SpeechRecognitionError.builtin$cls = \"SpeechRecognitionError\";\n  if (!\"name\" in SpeechRecognitionError)\n    SpeechRecognitionError.name = \"SpeechRecognitionError\";\n  $desc = $collectedClasses.SpeechRecognitionError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SpeechRecognitionError.prototype = $desc;\n  SpeechRecognitionError.prototype.get$error = function(receiver) {\n    return receiver.error;\n  };\n  function SpeechRecognitionEvent() {\n  }\n  SpeechRecognitionEvent.builtin$cls = \"SpeechRecognitionEvent\";\n  if (!\"name\" in SpeechRecognitionEvent)\n    SpeechRecognitionEvent.name = \"SpeechRecognitionEvent\";\n  $desc = $collectedClasses.SpeechRecognitionEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SpeechRecognitionEvent.prototype = $desc;\n  function SpeechSynthesisEvent() {\n  }\n  SpeechSynthesisEvent.builtin$cls = \"SpeechSynthesisEvent\";\n  if (!\"name\" in SpeechSynthesisEvent)\n    SpeechSynthesisEvent.name = \"SpeechSynthesisEvent\";\n  $desc = $collectedClasses.SpeechSynthesisEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SpeechSynthesisEvent.prototype = $desc;\n  function StorageEvent() {\n  }\n  StorageEvent.builtin$cls = \"StorageEvent\";\n  if (!\"name\" in StorageEvent)\n    StorageEvent.name = \"StorageEvent\";\n  $desc = $collectedClasses.StorageEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  StorageEvent.prototype = $desc;\n  function StyleElement() {\n  }\n  StyleElement.builtin$cls = \"StyleElement\";\n  if (!\"name\" in StyleElement)\n    StyleElement.name = \"StyleElement\";\n  $desc = $collectedClasses.StyleElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  StyleElement.prototype = $desc;\n  function TableCaptionElement() {\n  }\n  TableCaptionElement.builtin$cls = \"TableCaptionElement\";\n  if (!\"name\" in TableCaptionElement)\n    TableCaptionElement.name = \"TableCaptionElement\";\n  $desc = $collectedClasses.TableCaptionElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TableCaptionElement.prototype = $desc;\n  function TableCellElement() {\n  }\n  TableCellElement.builtin$cls = \"TableCellElement\";\n  if (!\"name\" in TableCellElement)\n    TableCellElement.name = \"TableCellElement\";\n  $desc = $collectedClasses.TableCellElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TableCellElement.prototype = $desc;\n  function TableColElement() {\n  }\n  TableColElement.builtin$cls = \"TableColElement\";\n  if (!\"name\" in TableColElement)\n    TableColElement.name = \"TableColElement\";\n  $desc = $collectedClasses.TableColElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TableColElement.prototype = $desc;\n  function TableElement() {\n  }\n  TableElement.builtin$cls = \"TableElement\";\n  if (!\"name\" in TableElement)\n    TableElement.name = \"TableElement\";\n  $desc = $collectedClasses.TableElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TableElement.prototype = $desc;\n  function TableRowElement() {\n  }\n  TableRowElement.builtin$cls = \"TableRowElement\";\n  if (!\"name\" in TableRowElement)\n    TableRowElement.name = \"TableRowElement\";\n  $desc = $collectedClasses.TableRowElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TableRowElement.prototype = $desc;\n  function TableSectionElement() {\n  }\n  TableSectionElement.builtin$cls = \"TableSectionElement\";\n  if (!\"name\" in TableSectionElement)\n    TableSectionElement.name = \"TableSectionElement\";\n  $desc = $collectedClasses.TableSectionElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TableSectionElement.prototype = $desc;\n  function TemplateElement() {\n  }\n  TemplateElement.builtin$cls = \"TemplateElement\";\n  if (!\"name\" in TemplateElement)\n    TemplateElement.name = \"TemplateElement\";\n  $desc = $collectedClasses.TemplateElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TemplateElement.prototype = $desc;\n  function Text() {\n  }\n  Text.builtin$cls = \"Text\";\n  if (!\"name\" in Text)\n    Text.name = \"Text\";\n  $desc = $collectedClasses.Text;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Text.prototype = $desc;\n  function TextAreaElement() {\n  }\n  TextAreaElement.builtin$cls = \"TextAreaElement\";\n  if (!\"name\" in TextAreaElement)\n    TextAreaElement.name = \"TextAreaElement\";\n  $desc = $collectedClasses.TextAreaElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TextAreaElement.prototype = $desc;\n  function TextEvent() {\n  }\n  TextEvent.builtin$cls = \"TextEvent\";\n  if (!\"name\" in TextEvent)\n    TextEvent.name = \"TextEvent\";\n  $desc = $collectedClasses.TextEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TextEvent.prototype = $desc;\n  function TitleElement() {\n  }\n  TitleElement.builtin$cls = \"TitleElement\";\n  if (!\"name\" in TitleElement)\n    TitleElement.name = \"TitleElement\";\n  $desc = $collectedClasses.TitleElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TitleElement.prototype = $desc;\n  function TouchEvent() {\n  }\n  TouchEvent.builtin$cls = \"TouchEvent\";\n  if (!\"name\" in TouchEvent)\n    TouchEvent.name = \"TouchEvent\";\n  $desc = $collectedClasses.TouchEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TouchEvent.prototype = $desc;\n  function TrackElement() {\n  }\n  TrackElement.builtin$cls = \"TrackElement\";\n  if (!\"name\" in TrackElement)\n    TrackElement.name = \"TrackElement\";\n  $desc = $collectedClasses.TrackElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TrackElement.prototype = $desc;\n  TrackElement.prototype.set$src = function(receiver, v) {\n    return receiver.src = v;\n  };\n  function TrackEvent() {\n  }\n  TrackEvent.builtin$cls = \"TrackEvent\";\n  if (!\"name\" in TrackEvent)\n    TrackEvent.name = \"TrackEvent\";\n  $desc = $collectedClasses.TrackEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TrackEvent.prototype = $desc;\n  function TransitionEvent() {\n  }\n  TransitionEvent.builtin$cls = \"TransitionEvent\";\n  if (!\"name\" in TransitionEvent)\n    TransitionEvent.name = \"TransitionEvent\";\n  $desc = $collectedClasses.TransitionEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TransitionEvent.prototype = $desc;\n  function UIEvent() {\n  }\n  UIEvent.builtin$cls = \"UIEvent\";\n  if (!\"name\" in UIEvent)\n    UIEvent.name = \"UIEvent\";\n  $desc = $collectedClasses.UIEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  UIEvent.prototype = $desc;\n  function UListElement() {\n  }\n  UListElement.builtin$cls = \"UListElement\";\n  if (!\"name\" in UListElement)\n    UListElement.name = \"UListElement\";\n  $desc = $collectedClasses.UListElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  UListElement.prototype = $desc;\n  function UnknownElement() {\n  }\n  UnknownElement.builtin$cls = \"UnknownElement\";\n  if (!\"name\" in UnknownElement)\n    UnknownElement.name = \"UnknownElement\";\n  $desc = $collectedClasses.UnknownElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  UnknownElement.prototype = $desc;\n  function VideoElement() {\n  }\n  VideoElement.builtin$cls = \"VideoElement\";\n  if (!\"name\" in VideoElement)\n    VideoElement.name = \"VideoElement\";\n  $desc = $collectedClasses.VideoElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  VideoElement.prototype = $desc;\n  function WheelEvent() {\n  }\n  WheelEvent.builtin$cls = \"WheelEvent\";\n  if (!\"name\" in WheelEvent)\n    WheelEvent.name = \"WheelEvent\";\n  $desc = $collectedClasses.WheelEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  WheelEvent.prototype = $desc;\n  function Window() {\n  }\n  Window.builtin$cls = \"Window\";\n  if (!\"name\" in Window)\n    Window.name = \"Window\";\n  $desc = $collectedClasses.Window;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Window.prototype = $desc;\n  function _Attr() {\n  }\n  _Attr.builtin$cls = \"_Attr\";\n  if (!\"name\" in _Attr)\n    _Attr.name = \"_Attr\";\n  $desc = $collectedClasses._Attr;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Attr.prototype = $desc;\n  function _ClientRect() {\n  }\n  _ClientRect.builtin$cls = \"_ClientRect\";\n  if (!\"name\" in _ClientRect)\n    _ClientRect.name = \"_ClientRect\";\n  $desc = $collectedClasses._ClientRect;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _ClientRect.prototype = $desc;\n  _ClientRect.prototype.get$height = function(receiver) {\n    return receiver.height;\n  };\n  _ClientRect.prototype.get$left = function(receiver) {\n    return receiver.left;\n  };\n  _ClientRect.prototype.get$top = function(receiver) {\n    return receiver.top;\n  };\n  _ClientRect.prototype.get$width = function(receiver) {\n    return receiver.width;\n  };\n  function _Entity() {\n  }\n  _Entity.builtin$cls = \"_Entity\";\n  if (!\"name\" in _Entity)\n    _Entity.name = \"_Entity\";\n  $desc = $collectedClasses._Entity;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Entity.prototype = $desc;\n  function _HTMLAppletElement() {\n  }\n  _HTMLAppletElement.builtin$cls = \"_HTMLAppletElement\";\n  if (!\"name\" in _HTMLAppletElement)\n    _HTMLAppletElement.name = \"_HTMLAppletElement\";\n  $desc = $collectedClasses._HTMLAppletElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _HTMLAppletElement.prototype = $desc;\n  function _HTMLBaseFontElement() {\n  }\n  _HTMLBaseFontElement.builtin$cls = \"_HTMLBaseFontElement\";\n  if (!\"name\" in _HTMLBaseFontElement)\n    _HTMLBaseFontElement.name = \"_HTMLBaseFontElement\";\n  $desc = $collectedClasses._HTMLBaseFontElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _HTMLBaseFontElement.prototype = $desc;\n  function _HTMLDirectoryElement() {\n  }\n  _HTMLDirectoryElement.builtin$cls = \"_HTMLDirectoryElement\";\n  if (!\"name\" in _HTMLDirectoryElement)\n    _HTMLDirectoryElement.name = \"_HTMLDirectoryElement\";\n  $desc = $collectedClasses._HTMLDirectoryElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _HTMLDirectoryElement.prototype = $desc;\n  function _HTMLFontElement() {\n  }\n  _HTMLFontElement.builtin$cls = \"_HTMLFontElement\";\n  if (!\"name\" in _HTMLFontElement)\n    _HTMLFontElement.name = \"_HTMLFontElement\";\n  $desc = $collectedClasses._HTMLFontElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _HTMLFontElement.prototype = $desc;\n  function _HTMLFrameElement() {\n  }\n  _HTMLFrameElement.builtin$cls = \"_HTMLFrameElement\";\n  if (!\"name\" in _HTMLFrameElement)\n    _HTMLFrameElement.name = \"_HTMLFrameElement\";\n  $desc = $collectedClasses._HTMLFrameElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _HTMLFrameElement.prototype = $desc;\n  function _HTMLFrameSetElement() {\n  }\n  _HTMLFrameSetElement.builtin$cls = \"_HTMLFrameSetElement\";\n  if (!\"name\" in _HTMLFrameSetElement)\n    _HTMLFrameSetElement.name = \"_HTMLFrameSetElement\";\n  $desc = $collectedClasses._HTMLFrameSetElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _HTMLFrameSetElement.prototype = $desc;\n  function _HTMLMarqueeElement() {\n  }\n  _HTMLMarqueeElement.builtin$cls = \"_HTMLMarqueeElement\";\n  if (!\"name\" in _HTMLMarqueeElement)\n    _HTMLMarqueeElement.name = \"_HTMLMarqueeElement\";\n  $desc = $collectedClasses._HTMLMarqueeElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _HTMLMarqueeElement.prototype = $desc;\n  function _MutationEvent() {\n  }\n  _MutationEvent.builtin$cls = \"_MutationEvent\";\n  if (!\"name\" in _MutationEvent)\n    _MutationEvent.name = \"_MutationEvent\";\n  $desc = $collectedClasses._MutationEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _MutationEvent.prototype = $desc;\n  function _Notation() {\n  }\n  _Notation.builtin$cls = \"_Notation\";\n  if (!\"name\" in _Notation)\n    _Notation.name = \"_Notation\";\n  $desc = $collectedClasses._Notation;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Notation.prototype = $desc;\n  function _XMLHttpRequestProgressEvent() {\n  }\n  _XMLHttpRequestProgressEvent.builtin$cls = \"_XMLHttpRequestProgressEvent\";\n  if (!\"name\" in _XMLHttpRequestProgressEvent)\n    _XMLHttpRequestProgressEvent.name = \"_XMLHttpRequestProgressEvent\";\n  $desc = $collectedClasses._XMLHttpRequestProgressEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _XMLHttpRequestProgressEvent.prototype = $desc;\n  function VersionChangeEvent() {\n  }\n  VersionChangeEvent.builtin$cls = \"VersionChangeEvent\";\n  if (!\"name\" in VersionChangeEvent)\n    VersionChangeEvent.name = \"VersionChangeEvent\";\n  $desc = $collectedClasses.VersionChangeEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  VersionChangeEvent.prototype = $desc;\n  function AElement() {\n  }\n  AElement.builtin$cls = \"AElement\";\n  if (!\"name\" in AElement)\n    AElement.name = \"AElement\";\n  $desc = $collectedClasses.AElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AElement.prototype = $desc;\n  function AltGlyphElement() {\n  }\n  AltGlyphElement.builtin$cls = \"AltGlyphElement\";\n  if (!\"name\" in AltGlyphElement)\n    AltGlyphElement.name = \"AltGlyphElement\";\n  $desc = $collectedClasses.AltGlyphElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AltGlyphElement.prototype = $desc;\n  function AnimateElement() {\n  }\n  AnimateElement.builtin$cls = \"AnimateElement\";\n  if (!\"name\" in AnimateElement)\n    AnimateElement.name = \"AnimateElement\";\n  $desc = $collectedClasses.AnimateElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AnimateElement.prototype = $desc;\n  function AnimateMotionElement() {\n  }\n  AnimateMotionElement.builtin$cls = \"AnimateMotionElement\";\n  if (!\"name\" in AnimateMotionElement)\n    AnimateMotionElement.name = \"AnimateMotionElement\";\n  $desc = $collectedClasses.AnimateMotionElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AnimateMotionElement.prototype = $desc;\n  function AnimateTransformElement() {\n  }\n  AnimateTransformElement.builtin$cls = \"AnimateTransformElement\";\n  if (!\"name\" in AnimateTransformElement)\n    AnimateTransformElement.name = \"AnimateTransformElement\";\n  $desc = $collectedClasses.AnimateTransformElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AnimateTransformElement.prototype = $desc;\n  function AnimatedLength() {\n  }\n  AnimatedLength.builtin$cls = \"AnimatedLength\";\n  if (!\"name\" in AnimatedLength)\n    AnimatedLength.name = \"AnimatedLength\";\n  $desc = $collectedClasses.AnimatedLength;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AnimatedLength.prototype = $desc;\n  function AnimatedLengthList() {\n  }\n  AnimatedLengthList.builtin$cls = \"AnimatedLengthList\";\n  if (!\"name\" in AnimatedLengthList)\n    AnimatedLengthList.name = \"AnimatedLengthList\";\n  $desc = $collectedClasses.AnimatedLengthList;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AnimatedLengthList.prototype = $desc;\n  function AnimatedNumber() {\n  }\n  AnimatedNumber.builtin$cls = \"AnimatedNumber\";\n  if (!\"name\" in AnimatedNumber)\n    AnimatedNumber.name = \"AnimatedNumber\";\n  $desc = $collectedClasses.AnimatedNumber;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AnimatedNumber.prototype = $desc;\n  function AnimatedNumberList() {\n  }\n  AnimatedNumberList.builtin$cls = \"AnimatedNumberList\";\n  if (!\"name\" in AnimatedNumberList)\n    AnimatedNumberList.name = \"AnimatedNumberList\";\n  $desc = $collectedClasses.AnimatedNumberList;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AnimatedNumberList.prototype = $desc;\n  function AnimationElement() {\n  }\n  AnimationElement.builtin$cls = \"AnimationElement\";\n  if (!\"name\" in AnimationElement)\n    AnimationElement.name = \"AnimationElement\";\n  $desc = $collectedClasses.AnimationElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AnimationElement.prototype = $desc;\n  function CircleElement() {\n  }\n  CircleElement.builtin$cls = \"CircleElement\";\n  if (!\"name\" in CircleElement)\n    CircleElement.name = \"CircleElement\";\n  $desc = $collectedClasses.CircleElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  CircleElement.prototype = $desc;\n  function ClipPathElement() {\n  }\n  ClipPathElement.builtin$cls = \"ClipPathElement\";\n  if (!\"name\" in ClipPathElement)\n    ClipPathElement.name = \"ClipPathElement\";\n  $desc = $collectedClasses.ClipPathElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ClipPathElement.prototype = $desc;\n  function DefsElement() {\n  }\n  DefsElement.builtin$cls = \"DefsElement\";\n  if (!\"name\" in DefsElement)\n    DefsElement.name = \"DefsElement\";\n  $desc = $collectedClasses.DefsElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DefsElement.prototype = $desc;\n  function DescElement() {\n  }\n  DescElement.builtin$cls = \"DescElement\";\n  if (!\"name\" in DescElement)\n    DescElement.name = \"DescElement\";\n  $desc = $collectedClasses.DescElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DescElement.prototype = $desc;\n  function EllipseElement() {\n  }\n  EllipseElement.builtin$cls = \"EllipseElement\";\n  if (!\"name\" in EllipseElement)\n    EllipseElement.name = \"EllipseElement\";\n  $desc = $collectedClasses.EllipseElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  EllipseElement.prototype = $desc;\n  function FEBlendElement() {\n  }\n  FEBlendElement.builtin$cls = \"FEBlendElement\";\n  if (!\"name\" in FEBlendElement)\n    FEBlendElement.name = \"FEBlendElement\";\n  $desc = $collectedClasses.FEBlendElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEBlendElement.prototype = $desc;\n  FEBlendElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FEBlendElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FEColorMatrixElement() {\n  }\n  FEColorMatrixElement.builtin$cls = \"FEColorMatrixElement\";\n  if (!\"name\" in FEColorMatrixElement)\n    FEColorMatrixElement.name = \"FEColorMatrixElement\";\n  $desc = $collectedClasses.FEColorMatrixElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEColorMatrixElement.prototype = $desc;\n  FEColorMatrixElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FEColorMatrixElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FEComponentTransferElement() {\n  }\n  FEComponentTransferElement.builtin$cls = \"FEComponentTransferElement\";\n  if (!\"name\" in FEComponentTransferElement)\n    FEComponentTransferElement.name = \"FEComponentTransferElement\";\n  $desc = $collectedClasses.FEComponentTransferElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEComponentTransferElement.prototype = $desc;\n  FEComponentTransferElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FEComponentTransferElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FECompositeElement() {\n  }\n  FECompositeElement.builtin$cls = \"FECompositeElement\";\n  if (!\"name\" in FECompositeElement)\n    FECompositeElement.name = \"FECompositeElement\";\n  $desc = $collectedClasses.FECompositeElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FECompositeElement.prototype = $desc;\n  FECompositeElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FECompositeElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FEConvolveMatrixElement() {\n  }\n  FEConvolveMatrixElement.builtin$cls = \"FEConvolveMatrixElement\";\n  if (!\"name\" in FEConvolveMatrixElement)\n    FEConvolveMatrixElement.name = \"FEConvolveMatrixElement\";\n  $desc = $collectedClasses.FEConvolveMatrixElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEConvolveMatrixElement.prototype = $desc;\n  FEConvolveMatrixElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FEConvolveMatrixElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FEDiffuseLightingElement() {\n  }\n  FEDiffuseLightingElement.builtin$cls = \"FEDiffuseLightingElement\";\n  if (!\"name\" in FEDiffuseLightingElement)\n    FEDiffuseLightingElement.name = \"FEDiffuseLightingElement\";\n  $desc = $collectedClasses.FEDiffuseLightingElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEDiffuseLightingElement.prototype = $desc;\n  FEDiffuseLightingElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FEDiffuseLightingElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FEDisplacementMapElement() {\n  }\n  FEDisplacementMapElement.builtin$cls = \"FEDisplacementMapElement\";\n  if (!\"name\" in FEDisplacementMapElement)\n    FEDisplacementMapElement.name = \"FEDisplacementMapElement\";\n  $desc = $collectedClasses.FEDisplacementMapElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEDisplacementMapElement.prototype = $desc;\n  FEDisplacementMapElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FEDisplacementMapElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FEDistantLightElement() {\n  }\n  FEDistantLightElement.builtin$cls = \"FEDistantLightElement\";\n  if (!\"name\" in FEDistantLightElement)\n    FEDistantLightElement.name = \"FEDistantLightElement\";\n  $desc = $collectedClasses.FEDistantLightElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEDistantLightElement.prototype = $desc;\n  function FEFloodElement() {\n  }\n  FEFloodElement.builtin$cls = \"FEFloodElement\";\n  if (!\"name\" in FEFloodElement)\n    FEFloodElement.name = \"FEFloodElement\";\n  $desc = $collectedClasses.FEFloodElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEFloodElement.prototype = $desc;\n  FEFloodElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FEFloodElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FEFuncAElement() {\n  }\n  FEFuncAElement.builtin$cls = \"FEFuncAElement\";\n  if (!\"name\" in FEFuncAElement)\n    FEFuncAElement.name = \"FEFuncAElement\";\n  $desc = $collectedClasses.FEFuncAElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEFuncAElement.prototype = $desc;\n  function FEFuncBElement() {\n  }\n  FEFuncBElement.builtin$cls = \"FEFuncBElement\";\n  if (!\"name\" in FEFuncBElement)\n    FEFuncBElement.name = \"FEFuncBElement\";\n  $desc = $collectedClasses.FEFuncBElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEFuncBElement.prototype = $desc;\n  function FEFuncGElement() {\n  }\n  FEFuncGElement.builtin$cls = \"FEFuncGElement\";\n  if (!\"name\" in FEFuncGElement)\n    FEFuncGElement.name = \"FEFuncGElement\";\n  $desc = $collectedClasses.FEFuncGElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEFuncGElement.prototype = $desc;\n  function FEFuncRElement() {\n  }\n  FEFuncRElement.builtin$cls = \"FEFuncRElement\";\n  if (!\"name\" in FEFuncRElement)\n    FEFuncRElement.name = \"FEFuncRElement\";\n  $desc = $collectedClasses.FEFuncRElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEFuncRElement.prototype = $desc;\n  function FEGaussianBlurElement() {\n  }\n  FEGaussianBlurElement.builtin$cls = \"FEGaussianBlurElement\";\n  if (!\"name\" in FEGaussianBlurElement)\n    FEGaussianBlurElement.name = \"FEGaussianBlurElement\";\n  $desc = $collectedClasses.FEGaussianBlurElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEGaussianBlurElement.prototype = $desc;\n  FEGaussianBlurElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FEGaussianBlurElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FEImageElement() {\n  }\n  FEImageElement.builtin$cls = \"FEImageElement\";\n  if (!\"name\" in FEImageElement)\n    FEImageElement.name = \"FEImageElement\";\n  $desc = $collectedClasses.FEImageElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEImageElement.prototype = $desc;\n  FEImageElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FEImageElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FEMergeElement() {\n  }\n  FEMergeElement.builtin$cls = \"FEMergeElement\";\n  if (!\"name\" in FEMergeElement)\n    FEMergeElement.name = \"FEMergeElement\";\n  $desc = $collectedClasses.FEMergeElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEMergeElement.prototype = $desc;\n  FEMergeElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FEMergeElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FEMergeNodeElement() {\n  }\n  FEMergeNodeElement.builtin$cls = \"FEMergeNodeElement\";\n  if (!\"name\" in FEMergeNodeElement)\n    FEMergeNodeElement.name = \"FEMergeNodeElement\";\n  $desc = $collectedClasses.FEMergeNodeElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEMergeNodeElement.prototype = $desc;\n  function FEMorphologyElement() {\n  }\n  FEMorphologyElement.builtin$cls = \"FEMorphologyElement\";\n  if (!\"name\" in FEMorphologyElement)\n    FEMorphologyElement.name = \"FEMorphologyElement\";\n  $desc = $collectedClasses.FEMorphologyElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEMorphologyElement.prototype = $desc;\n  FEMorphologyElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FEMorphologyElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FEOffsetElement() {\n  }\n  FEOffsetElement.builtin$cls = \"FEOffsetElement\";\n  if (!\"name\" in FEOffsetElement)\n    FEOffsetElement.name = \"FEOffsetElement\";\n  $desc = $collectedClasses.FEOffsetElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEOffsetElement.prototype = $desc;\n  FEOffsetElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FEOffsetElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FEPointLightElement() {\n  }\n  FEPointLightElement.builtin$cls = \"FEPointLightElement\";\n  if (!\"name\" in FEPointLightElement)\n    FEPointLightElement.name = \"FEPointLightElement\";\n  $desc = $collectedClasses.FEPointLightElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FEPointLightElement.prototype = $desc;\n  FEPointLightElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FEPointLightElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FESpecularLightingElement() {\n  }\n  FESpecularLightingElement.builtin$cls = \"FESpecularLightingElement\";\n  if (!\"name\" in FESpecularLightingElement)\n    FESpecularLightingElement.name = \"FESpecularLightingElement\";\n  $desc = $collectedClasses.FESpecularLightingElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FESpecularLightingElement.prototype = $desc;\n  FESpecularLightingElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FESpecularLightingElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FESpotLightElement() {\n  }\n  FESpotLightElement.builtin$cls = \"FESpotLightElement\";\n  if (!\"name\" in FESpotLightElement)\n    FESpotLightElement.name = \"FESpotLightElement\";\n  $desc = $collectedClasses.FESpotLightElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FESpotLightElement.prototype = $desc;\n  FESpotLightElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FESpotLightElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FETileElement() {\n  }\n  FETileElement.builtin$cls = \"FETileElement\";\n  if (!\"name\" in FETileElement)\n    FETileElement.name = \"FETileElement\";\n  $desc = $collectedClasses.FETileElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FETileElement.prototype = $desc;\n  FETileElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FETileElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FETurbulenceElement() {\n  }\n  FETurbulenceElement.builtin$cls = \"FETurbulenceElement\";\n  if (!\"name\" in FETurbulenceElement)\n    FETurbulenceElement.name = \"FETurbulenceElement\";\n  $desc = $collectedClasses.FETurbulenceElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FETurbulenceElement.prototype = $desc;\n  FETurbulenceElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FETurbulenceElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function FilterElement() {\n  }\n  FilterElement.builtin$cls = \"FilterElement\";\n  if (!\"name\" in FilterElement)\n    FilterElement.name = \"FilterElement\";\n  $desc = $collectedClasses.FilterElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FilterElement.prototype = $desc;\n  FilterElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  FilterElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function ForeignObjectElement() {\n  }\n  ForeignObjectElement.builtin$cls = \"ForeignObjectElement\";\n  if (!\"name\" in ForeignObjectElement)\n    ForeignObjectElement.name = \"ForeignObjectElement\";\n  $desc = $collectedClasses.ForeignObjectElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ForeignObjectElement.prototype = $desc;\n  ForeignObjectElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  ForeignObjectElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function GElement() {\n  }\n  GElement.builtin$cls = \"GElement\";\n  if (!\"name\" in GElement)\n    GElement.name = \"GElement\";\n  $desc = $collectedClasses.GElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  GElement.prototype = $desc;\n  function GraphicsElement() {\n  }\n  GraphicsElement.builtin$cls = \"GraphicsElement\";\n  if (!\"name\" in GraphicsElement)\n    GraphicsElement.name = \"GraphicsElement\";\n  $desc = $collectedClasses.GraphicsElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  GraphicsElement.prototype = $desc;\n  function ImageElement0() {\n  }\n  ImageElement0.builtin$cls = \"ImageElement0\";\n  if (!\"name\" in ImageElement0)\n    ImageElement0.name = \"ImageElement0\";\n  $desc = $collectedClasses.ImageElement0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ImageElement0.prototype = $desc;\n  ImageElement0.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  ImageElement0.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function LineElement() {\n  }\n  LineElement.builtin$cls = \"LineElement\";\n  if (!\"name\" in LineElement)\n    LineElement.name = \"LineElement\";\n  $desc = $collectedClasses.LineElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  LineElement.prototype = $desc;\n  function LinearGradientElement() {\n  }\n  LinearGradientElement.builtin$cls = \"LinearGradientElement\";\n  if (!\"name\" in LinearGradientElement)\n    LinearGradientElement.name = \"LinearGradientElement\";\n  $desc = $collectedClasses.LinearGradientElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  LinearGradientElement.prototype = $desc;\n  function MarkerElement() {\n  }\n  MarkerElement.builtin$cls = \"MarkerElement\";\n  if (!\"name\" in MarkerElement)\n    MarkerElement.name = \"MarkerElement\";\n  $desc = $collectedClasses.MarkerElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MarkerElement.prototype = $desc;\n  function MaskElement() {\n  }\n  MaskElement.builtin$cls = \"MaskElement\";\n  if (!\"name\" in MaskElement)\n    MaskElement.name = \"MaskElement\";\n  $desc = $collectedClasses.MaskElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MaskElement.prototype = $desc;\n  MaskElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  MaskElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function MetadataElement() {\n  }\n  MetadataElement.builtin$cls = \"MetadataElement\";\n  if (!\"name\" in MetadataElement)\n    MetadataElement.name = \"MetadataElement\";\n  $desc = $collectedClasses.MetadataElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MetadataElement.prototype = $desc;\n  function PathElement() {\n  }\n  PathElement.builtin$cls = \"PathElement\";\n  if (!\"name\" in PathElement)\n    PathElement.name = \"PathElement\";\n  $desc = $collectedClasses.PathElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  PathElement.prototype = $desc;\n  function PatternElement() {\n  }\n  PatternElement.builtin$cls = \"PatternElement\";\n  if (!\"name\" in PatternElement)\n    PatternElement.name = \"PatternElement\";\n  $desc = $collectedClasses.PatternElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  PatternElement.prototype = $desc;\n  PatternElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  PatternElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function PolygonElement() {\n  }\n  PolygonElement.builtin$cls = \"PolygonElement\";\n  if (!\"name\" in PolygonElement)\n    PolygonElement.name = \"PolygonElement\";\n  $desc = $collectedClasses.PolygonElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  PolygonElement.prototype = $desc;\n  function PolylineElement() {\n  }\n  PolylineElement.builtin$cls = \"PolylineElement\";\n  if (!\"name\" in PolylineElement)\n    PolylineElement.name = \"PolylineElement\";\n  $desc = $collectedClasses.PolylineElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  PolylineElement.prototype = $desc;\n  function RadialGradientElement() {\n  }\n  RadialGradientElement.builtin$cls = \"RadialGradientElement\";\n  if (!\"name\" in RadialGradientElement)\n    RadialGradientElement.name = \"RadialGradientElement\";\n  $desc = $collectedClasses.RadialGradientElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  RadialGradientElement.prototype = $desc;\n  function RectElement() {\n  }\n  RectElement.builtin$cls = \"RectElement\";\n  if (!\"name\" in RectElement)\n    RectElement.name = \"RectElement\";\n  $desc = $collectedClasses.RectElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  RectElement.prototype = $desc;\n  RectElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  RectElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function ScriptElement0() {\n  }\n  ScriptElement0.builtin$cls = \"ScriptElement0\";\n  if (!\"name\" in ScriptElement0)\n    ScriptElement0.name = \"ScriptElement0\";\n  $desc = $collectedClasses.ScriptElement0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ScriptElement0.prototype = $desc;\n  function SetElement() {\n  }\n  SetElement.builtin$cls = \"SetElement\";\n  if (!\"name\" in SetElement)\n    SetElement.name = \"SetElement\";\n  $desc = $collectedClasses.SetElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SetElement.prototype = $desc;\n  function StopElement() {\n  }\n  StopElement.builtin$cls = \"StopElement\";\n  if (!\"name\" in StopElement)\n    StopElement.name = \"StopElement\";\n  $desc = $collectedClasses.StopElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  StopElement.prototype = $desc;\n  function StyleElement0() {\n  }\n  StyleElement0.builtin$cls = \"StyleElement0\";\n  if (!\"name\" in StyleElement0)\n    StyleElement0.name = \"StyleElement0\";\n  $desc = $collectedClasses.StyleElement0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  StyleElement0.prototype = $desc;\n  function SvgDocument() {\n  }\n  SvgDocument.builtin$cls = \"SvgDocument\";\n  if (!\"name\" in SvgDocument)\n    SvgDocument.name = \"SvgDocument\";\n  $desc = $collectedClasses.SvgDocument;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SvgDocument.prototype = $desc;\n  function SvgElement() {\n  }\n  SvgElement.builtin$cls = \"SvgElement\";\n  if (!\"name\" in SvgElement)\n    SvgElement.name = \"SvgElement\";\n  $desc = $collectedClasses.SvgElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SvgElement.prototype = $desc;\n  function SvgSvgElement() {\n  }\n  SvgSvgElement.builtin$cls = \"SvgSvgElement\";\n  if (!\"name\" in SvgSvgElement)\n    SvgSvgElement.name = \"SvgSvgElement\";\n  $desc = $collectedClasses.SvgSvgElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SvgSvgElement.prototype = $desc;\n  SvgSvgElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  SvgSvgElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function SwitchElement() {\n  }\n  SwitchElement.builtin$cls = \"SwitchElement\";\n  if (!\"name\" in SwitchElement)\n    SwitchElement.name = \"SwitchElement\";\n  $desc = $collectedClasses.SwitchElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SwitchElement.prototype = $desc;\n  function SymbolElement() {\n  }\n  SymbolElement.builtin$cls = \"SymbolElement\";\n  if (!\"name\" in SymbolElement)\n    SymbolElement.name = \"SymbolElement\";\n  $desc = $collectedClasses.SymbolElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SymbolElement.prototype = $desc;\n  function TSpanElement() {\n  }\n  TSpanElement.builtin$cls = \"TSpanElement\";\n  if (!\"name\" in TSpanElement)\n    TSpanElement.name = \"TSpanElement\";\n  $desc = $collectedClasses.TSpanElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TSpanElement.prototype = $desc;\n  function TextContentElement() {\n  }\n  TextContentElement.builtin$cls = \"TextContentElement\";\n  if (!\"name\" in TextContentElement)\n    TextContentElement.name = \"TextContentElement\";\n  $desc = $collectedClasses.TextContentElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TextContentElement.prototype = $desc;\n  function TextElement() {\n  }\n  TextElement.builtin$cls = \"TextElement\";\n  if (!\"name\" in TextElement)\n    TextElement.name = \"TextElement\";\n  $desc = $collectedClasses.TextElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TextElement.prototype = $desc;\n  function TextPathElement() {\n  }\n  TextPathElement.builtin$cls = \"TextPathElement\";\n  if (!\"name\" in TextPathElement)\n    TextPathElement.name = \"TextPathElement\";\n  $desc = $collectedClasses.TextPathElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TextPathElement.prototype = $desc;\n  function TextPositioningElement() {\n  }\n  TextPositioningElement.builtin$cls = \"TextPositioningElement\";\n  if (!\"name\" in TextPositioningElement)\n    TextPositioningElement.name = \"TextPositioningElement\";\n  $desc = $collectedClasses.TextPositioningElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TextPositioningElement.prototype = $desc;\n  TextPositioningElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  TextPositioningElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function TitleElement0() {\n  }\n  TitleElement0.builtin$cls = \"TitleElement0\";\n  if (!\"name\" in TitleElement0)\n    TitleElement0.name = \"TitleElement0\";\n  $desc = $collectedClasses.TitleElement0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TitleElement0.prototype = $desc;\n  function UseElement() {\n  }\n  UseElement.builtin$cls = \"UseElement\";\n  if (!\"name\" in UseElement)\n    UseElement.name = \"UseElement\";\n  $desc = $collectedClasses.UseElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  UseElement.prototype = $desc;\n  UseElement.prototype.get$x = function(receiver) {\n    return receiver.x;\n  };\n  UseElement.prototype.get$y = function(receiver) {\n    return receiver.y;\n  };\n  function ViewElement() {\n  }\n  ViewElement.builtin$cls = \"ViewElement\";\n  if (!\"name\" in ViewElement)\n    ViewElement.name = \"ViewElement\";\n  $desc = $collectedClasses.ViewElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ViewElement.prototype = $desc;\n  function ZoomEvent() {\n  }\n  ZoomEvent.builtin$cls = \"ZoomEvent\";\n  if (!\"name\" in ZoomEvent)\n    ZoomEvent.name = \"ZoomEvent\";\n  $desc = $collectedClasses.ZoomEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ZoomEvent.prototype = $desc;\n  function _GradientElement() {\n  }\n  _GradientElement.builtin$cls = \"_GradientElement\";\n  if (!\"name\" in _GradientElement)\n    _GradientElement.name = \"_GradientElement\";\n  $desc = $collectedClasses._GradientElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _GradientElement.prototype = $desc;\n  function _SVGAltGlyphDefElement() {\n  }\n  _SVGAltGlyphDefElement.builtin$cls = \"_SVGAltGlyphDefElement\";\n  if (!\"name\" in _SVGAltGlyphDefElement)\n    _SVGAltGlyphDefElement.name = \"_SVGAltGlyphDefElement\";\n  $desc = $collectedClasses._SVGAltGlyphDefElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGAltGlyphDefElement.prototype = $desc;\n  function _SVGAltGlyphItemElement() {\n  }\n  _SVGAltGlyphItemElement.builtin$cls = \"_SVGAltGlyphItemElement\";\n  if (!\"name\" in _SVGAltGlyphItemElement)\n    _SVGAltGlyphItemElement.name = \"_SVGAltGlyphItemElement\";\n  $desc = $collectedClasses._SVGAltGlyphItemElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGAltGlyphItemElement.prototype = $desc;\n  function _SVGAnimateColorElement() {\n  }\n  _SVGAnimateColorElement.builtin$cls = \"_SVGAnimateColorElement\";\n  if (!\"name\" in _SVGAnimateColorElement)\n    _SVGAnimateColorElement.name = \"_SVGAnimateColorElement\";\n  $desc = $collectedClasses._SVGAnimateColorElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGAnimateColorElement.prototype = $desc;\n  function _SVGComponentTransferFunctionElement() {\n  }\n  _SVGComponentTransferFunctionElement.builtin$cls = \"_SVGComponentTransferFunctionElement\";\n  if (!\"name\" in _SVGComponentTransferFunctionElement)\n    _SVGComponentTransferFunctionElement.name = \"_SVGComponentTransferFunctionElement\";\n  $desc = $collectedClasses._SVGComponentTransferFunctionElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGComponentTransferFunctionElement.prototype = $desc;\n  function _SVGCursorElement() {\n  }\n  _SVGCursorElement.builtin$cls = \"_SVGCursorElement\";\n  if (!\"name\" in _SVGCursorElement)\n    _SVGCursorElement.name = \"_SVGCursorElement\";\n  $desc = $collectedClasses._SVGCursorElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGCursorElement.prototype = $desc;\n  function _SVGFEDropShadowElement() {\n  }\n  _SVGFEDropShadowElement.builtin$cls = \"_SVGFEDropShadowElement\";\n  if (!\"name\" in _SVGFEDropShadowElement)\n    _SVGFEDropShadowElement.name = \"_SVGFEDropShadowElement\";\n  $desc = $collectedClasses._SVGFEDropShadowElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGFEDropShadowElement.prototype = $desc;\n  function _SVGFontElement() {\n  }\n  _SVGFontElement.builtin$cls = \"_SVGFontElement\";\n  if (!\"name\" in _SVGFontElement)\n    _SVGFontElement.name = \"_SVGFontElement\";\n  $desc = $collectedClasses._SVGFontElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGFontElement.prototype = $desc;\n  function _SVGFontFaceElement() {\n  }\n  _SVGFontFaceElement.builtin$cls = \"_SVGFontFaceElement\";\n  if (!\"name\" in _SVGFontFaceElement)\n    _SVGFontFaceElement.name = \"_SVGFontFaceElement\";\n  $desc = $collectedClasses._SVGFontFaceElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGFontFaceElement.prototype = $desc;\n  function _SVGFontFaceFormatElement() {\n  }\n  _SVGFontFaceFormatElement.builtin$cls = \"_SVGFontFaceFormatElement\";\n  if (!\"name\" in _SVGFontFaceFormatElement)\n    _SVGFontFaceFormatElement.name = \"_SVGFontFaceFormatElement\";\n  $desc = $collectedClasses._SVGFontFaceFormatElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGFontFaceFormatElement.prototype = $desc;\n  function _SVGFontFaceNameElement() {\n  }\n  _SVGFontFaceNameElement.builtin$cls = \"_SVGFontFaceNameElement\";\n  if (!\"name\" in _SVGFontFaceNameElement)\n    _SVGFontFaceNameElement.name = \"_SVGFontFaceNameElement\";\n  $desc = $collectedClasses._SVGFontFaceNameElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGFontFaceNameElement.prototype = $desc;\n  function _SVGFontFaceSrcElement() {\n  }\n  _SVGFontFaceSrcElement.builtin$cls = \"_SVGFontFaceSrcElement\";\n  if (!\"name\" in _SVGFontFaceSrcElement)\n    _SVGFontFaceSrcElement.name = \"_SVGFontFaceSrcElement\";\n  $desc = $collectedClasses._SVGFontFaceSrcElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGFontFaceSrcElement.prototype = $desc;\n  function _SVGFontFaceUriElement() {\n  }\n  _SVGFontFaceUriElement.builtin$cls = \"_SVGFontFaceUriElement\";\n  if (!\"name\" in _SVGFontFaceUriElement)\n    _SVGFontFaceUriElement.name = \"_SVGFontFaceUriElement\";\n  $desc = $collectedClasses._SVGFontFaceUriElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGFontFaceUriElement.prototype = $desc;\n  function _SVGGlyphElement() {\n  }\n  _SVGGlyphElement.builtin$cls = \"_SVGGlyphElement\";\n  if (!\"name\" in _SVGGlyphElement)\n    _SVGGlyphElement.name = \"_SVGGlyphElement\";\n  $desc = $collectedClasses._SVGGlyphElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGGlyphElement.prototype = $desc;\n  function _SVGGlyphRefElement() {\n  }\n  _SVGGlyphRefElement.builtin$cls = \"_SVGGlyphRefElement\";\n  if (!\"name\" in _SVGGlyphRefElement)\n    _SVGGlyphRefElement.name = \"_SVGGlyphRefElement\";\n  $desc = $collectedClasses._SVGGlyphRefElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGGlyphRefElement.prototype = $desc;\n  function _SVGHKernElement() {\n  }\n  _SVGHKernElement.builtin$cls = \"_SVGHKernElement\";\n  if (!\"name\" in _SVGHKernElement)\n    _SVGHKernElement.name = \"_SVGHKernElement\";\n  $desc = $collectedClasses._SVGHKernElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGHKernElement.prototype = $desc;\n  function _SVGMPathElement() {\n  }\n  _SVGMPathElement.builtin$cls = \"_SVGMPathElement\";\n  if (!\"name\" in _SVGMPathElement)\n    _SVGMPathElement.name = \"_SVGMPathElement\";\n  $desc = $collectedClasses._SVGMPathElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGMPathElement.prototype = $desc;\n  function _SVGMissingGlyphElement() {\n  }\n  _SVGMissingGlyphElement.builtin$cls = \"_SVGMissingGlyphElement\";\n  if (!\"name\" in _SVGMissingGlyphElement)\n    _SVGMissingGlyphElement.name = \"_SVGMissingGlyphElement\";\n  $desc = $collectedClasses._SVGMissingGlyphElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGMissingGlyphElement.prototype = $desc;\n  function _SVGVKernElement() {\n  }\n  _SVGVKernElement.builtin$cls = \"_SVGVKernElement\";\n  if (!\"name\" in _SVGVKernElement)\n    _SVGVKernElement.name = \"_SVGVKernElement\";\n  $desc = $collectedClasses._SVGVKernElement;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SVGVKernElement.prototype = $desc;\n  function AudioProcessingEvent() {\n  }\n  AudioProcessingEvent.builtin$cls = \"AudioProcessingEvent\";\n  if (!\"name\" in AudioProcessingEvent)\n    AudioProcessingEvent.name = \"AudioProcessingEvent\";\n  $desc = $collectedClasses.AudioProcessingEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  AudioProcessingEvent.prototype = $desc;\n  function OfflineAudioCompletionEvent() {\n  }\n  OfflineAudioCompletionEvent.builtin$cls = \"OfflineAudioCompletionEvent\";\n  if (!\"name\" in OfflineAudioCompletionEvent)\n    OfflineAudioCompletionEvent.name = \"OfflineAudioCompletionEvent\";\n  $desc = $collectedClasses.OfflineAudioCompletionEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  OfflineAudioCompletionEvent.prototype = $desc;\n  function ContextEvent() {\n  }\n  ContextEvent.builtin$cls = \"ContextEvent\";\n  if (!\"name\" in ContextEvent)\n    ContextEvent.name = \"ContextEvent\";\n  $desc = $collectedClasses.ContextEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ContextEvent.prototype = $desc;\n  function SqlError() {\n  }\n  SqlError.builtin$cls = \"SqlError\";\n  if (!\"name\" in SqlError)\n    SqlError.name = \"SqlError\";\n  $desc = $collectedClasses.SqlError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  SqlError.prototype = $desc;\n  function TypedData() {\n  }\n  TypedData.builtin$cls = \"TypedData\";\n  if (!\"name\" in TypedData)\n    TypedData.name = \"TypedData\";\n  $desc = $collectedClasses.TypedData;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TypedData.prototype = $desc;\n  function Uint8List() {\n  }\n  Uint8List.builtin$cls = \"Uint8List\";\n  if (!\"name\" in Uint8List)\n    Uint8List.name = \"Uint8List\";\n  $desc = $collectedClasses.Uint8List;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Uint8List.prototype = $desc;\n  function JS_CONST(code) {\n    this.code = code;\n  }\n  JS_CONST.builtin$cls = \"JS_CONST\";\n  if (!\"name\" in JS_CONST)\n    JS_CONST.name = \"JS_CONST\";\n  $desc = $collectedClasses.JS_CONST;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  JS_CONST.prototype = $desc;\n  function Interceptor() {\n  }\n  Interceptor.builtin$cls = \"Interceptor\";\n  if (!\"name\" in Interceptor)\n    Interceptor.name = \"Interceptor\";\n  $desc = $collectedClasses.Interceptor;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Interceptor.prototype = $desc;\n  function JSBool() {\n  }\n  JSBool.builtin$cls = \"bool\";\n  if (!\"name\" in JSBool)\n    JSBool.name = \"JSBool\";\n  $desc = $collectedClasses.JSBool;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  JSBool.prototype = $desc;\n  function JSNull() {\n  }\n  JSNull.builtin$cls = \"JSNull\";\n  if (!\"name\" in JSNull)\n    JSNull.name = \"JSNull\";\n  $desc = $collectedClasses.JSNull;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  JSNull.prototype = $desc;\n  function JavaScriptObject() {\n  }\n  JavaScriptObject.builtin$cls = \"JavaScriptObject\";\n  if (!\"name\" in JavaScriptObject)\n    JavaScriptObject.name = \"JavaScriptObject\";\n  $desc = $collectedClasses.JavaScriptObject;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  JavaScriptObject.prototype = $desc;\n  function PlainJavaScriptObject() {\n  }\n  PlainJavaScriptObject.builtin$cls = \"PlainJavaScriptObject\";\n  if (!\"name\" in PlainJavaScriptObject)\n    PlainJavaScriptObject.name = \"PlainJavaScriptObject\";\n  $desc = $collectedClasses.PlainJavaScriptObject;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  PlainJavaScriptObject.prototype = $desc;\n  function UnknownJavaScriptObject() {\n  }\n  UnknownJavaScriptObject.builtin$cls = \"UnknownJavaScriptObject\";\n  if (!\"name\" in UnknownJavaScriptObject)\n    UnknownJavaScriptObject.name = \"UnknownJavaScriptObject\";\n  $desc = $collectedClasses.UnknownJavaScriptObject;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  UnknownJavaScriptObject.prototype = $desc;\n  function JSArray() {\n  }\n  JSArray.builtin$cls = \"List\";\n  if (!\"name\" in JSArray)\n    JSArray.name = \"JSArray\";\n  $desc = $collectedClasses.JSArray;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  JSArray.prototype = $desc;\n  function JSNumber() {\n  }\n  JSNumber.builtin$cls = \"num\";\n  if (!\"name\" in JSNumber)\n    JSNumber.name = \"JSNumber\";\n  $desc = $collectedClasses.JSNumber;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  JSNumber.prototype = $desc;\n  function JSInt() {\n  }\n  JSInt.builtin$cls = \"int\";\n  if (!\"name\" in JSInt)\n    JSInt.name = \"JSInt\";\n  $desc = $collectedClasses.JSInt;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  JSInt.prototype = $desc;\n  function JSDouble() {\n  }\n  JSDouble.builtin$cls = \"double\";\n  if (!\"name\" in JSDouble)\n    JSDouble.name = \"JSDouble\";\n  $desc = $collectedClasses.JSDouble;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  JSDouble.prototype = $desc;\n  function JSString() {\n  }\n  JSString.builtin$cls = \"String\";\n  if (!\"name\" in JSString)\n    JSString.name = \"JSString\";\n  $desc = $collectedClasses.JSString;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  JSString.prototype = $desc;\n  function startRootIsolate_closure(entry_0) {\n    this.entry_0 = entry_0;\n  }\n  startRootIsolate_closure.builtin$cls = \"startRootIsolate_closure\";\n  if (!\"name\" in startRootIsolate_closure)\n    startRootIsolate_closure.name = \"startRootIsolate_closure\";\n  $desc = $collectedClasses.startRootIsolate_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  startRootIsolate_closure.prototype = $desc;\n  function startRootIsolate_closure0(entry_1) {\n    this.entry_1 = entry_1;\n  }\n  startRootIsolate_closure0.builtin$cls = \"startRootIsolate_closure0\";\n  if (!\"name\" in startRootIsolate_closure0)\n    startRootIsolate_closure0.name = \"startRootIsolate_closure0\";\n  $desc = $collectedClasses.startRootIsolate_closure0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  startRootIsolate_closure0.prototype = $desc;\n  function _Manager(nextIsolateId, currentManagerId, nextManagerId, currentContext, rootContext, topEventLoop, fromCommandLine, isWorker, supportsWorkers, isolates, mainManager, managers, entry) {\n    this.nextIsolateId = nextIsolateId;\n    this.currentManagerId = currentManagerId;\n    this.nextManagerId = nextManagerId;\n    this.currentContext = currentContext;\n    this.rootContext = rootContext;\n    this.topEventLoop = topEventLoop;\n    this.fromCommandLine = fromCommandLine;\n    this.isWorker = isWorker;\n    this.supportsWorkers = supportsWorkers;\n    this.isolates = isolates;\n    this.mainManager = mainManager;\n    this.managers = managers;\n    this.entry = entry;\n  }\n  _Manager.builtin$cls = \"_Manager\";\n  if (!\"name\" in _Manager)\n    _Manager.name = \"_Manager\";\n  $desc = $collectedClasses._Manager;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Manager.prototype = $desc;\n  function _IsolateContext(id, ports, weakPorts, isolateStatics) {\n    this.id = id;\n    this.ports = ports;\n    this.weakPorts = weakPorts;\n    this.isolateStatics = isolateStatics;\n  }\n  _IsolateContext.builtin$cls = \"_IsolateContext\";\n  if (!\"name\" in _IsolateContext)\n    _IsolateContext.name = \"_IsolateContext\";\n  $desc = $collectedClasses._IsolateContext;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _IsolateContext.prototype = $desc;\n  _IsolateContext.prototype.get$isolateStatics = function() {\n    return this.isolateStatics;\n  };\n  function _EventLoop(events, activeTimerCount) {\n    this.events = events;\n    this.activeTimerCount = activeTimerCount;\n  }\n  _EventLoop.builtin$cls = \"_EventLoop\";\n  if (!\"name\" in _EventLoop)\n    _EventLoop.name = \"_EventLoop\";\n  $desc = $collectedClasses._EventLoop;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _EventLoop.prototype = $desc;\n  function _EventLoop__runHelper_next(this_0) {\n    this.this_0 = this_0;\n  }\n  _EventLoop__runHelper_next.builtin$cls = \"_EventLoop__runHelper_next\";\n  if (!\"name\" in _EventLoop__runHelper_next)\n    _EventLoop__runHelper_next.name = \"_EventLoop__runHelper_next\";\n  $desc = $collectedClasses._EventLoop__runHelper_next;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _EventLoop__runHelper_next.prototype = $desc;\n  function _IsolateEvent(isolate, fn, message) {\n    this.isolate = isolate;\n    this.fn = fn;\n    this.message = message;\n  }\n  _IsolateEvent.builtin$cls = \"_IsolateEvent\";\n  if (!\"name\" in _IsolateEvent)\n    _IsolateEvent.name = \"_IsolateEvent\";\n  $desc = $collectedClasses._IsolateEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _IsolateEvent.prototype = $desc;\n  function _MainManagerStub() {\n  }\n  _MainManagerStub.builtin$cls = \"_MainManagerStub\";\n  if (!\"name\" in _MainManagerStub)\n    _MainManagerStub.name = \"_MainManagerStub\";\n  $desc = $collectedClasses._MainManagerStub;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _MainManagerStub.prototype = $desc;\n  function IsolateNatives__processWorkerMessage_closure(entryPoint_0, args_1, message_2, isSpawnUri_3, replyTo_4) {\n    this.entryPoint_0 = entryPoint_0;\n    this.args_1 = args_1;\n    this.message_2 = message_2;\n    this.isSpawnUri_3 = isSpawnUri_3;\n    this.replyTo_4 = replyTo_4;\n  }\n  IsolateNatives__processWorkerMessage_closure.builtin$cls = \"IsolateNatives__processWorkerMessage_closure\";\n  if (!\"name\" in IsolateNatives__processWorkerMessage_closure)\n    IsolateNatives__processWorkerMessage_closure.name = \"IsolateNatives__processWorkerMessage_closure\";\n  $desc = $collectedClasses.IsolateNatives__processWorkerMessage_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  IsolateNatives__processWorkerMessage_closure.prototype = $desc;\n  function _BaseSendPort() {\n  }\n  _BaseSendPort.builtin$cls = \"_BaseSendPort\";\n  if (!\"name\" in _BaseSendPort)\n    _BaseSendPort.name = \"_BaseSendPort\";\n  $desc = $collectedClasses._BaseSendPort;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _BaseSendPort.prototype = $desc;\n  function _NativeJsSendPort(_receivePort, _isolateId) {\n    this._receivePort = _receivePort;\n    this._isolateId = _isolateId;\n  }\n  _NativeJsSendPort.builtin$cls = \"_NativeJsSendPort\";\n  if (!\"name\" in _NativeJsSendPort)\n    _NativeJsSendPort.name = \"_NativeJsSendPort\";\n  $desc = $collectedClasses._NativeJsSendPort;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _NativeJsSendPort.prototype = $desc;\n  function _NativeJsSendPort_send_closure(box_0, this_1, shouldSerialize_2) {\n    this.box_0 = box_0;\n    this.this_1 = this_1;\n    this.shouldSerialize_2 = shouldSerialize_2;\n  }\n  _NativeJsSendPort_send_closure.builtin$cls = \"_NativeJsSendPort_send_closure\";\n  if (!\"name\" in _NativeJsSendPort_send_closure)\n    _NativeJsSendPort_send_closure.name = \"_NativeJsSendPort_send_closure\";\n  $desc = $collectedClasses._NativeJsSendPort_send_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _NativeJsSendPort_send_closure.prototype = $desc;\n  function _WorkerSendPort(_workerId, _receivePortId, _isolateId) {\n    this._workerId = _workerId;\n    this._receivePortId = _receivePortId;\n    this._isolateId = _isolateId;\n  }\n  _WorkerSendPort.builtin$cls = \"_WorkerSendPort\";\n  if (!\"name\" in _WorkerSendPort)\n    _WorkerSendPort.name = \"_WorkerSendPort\";\n  $desc = $collectedClasses._WorkerSendPort;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _WorkerSendPort.prototype = $desc;\n  function RawReceivePortImpl(_id, _handler, _isClosed) {\n    this._id = _id;\n    this._handler = _handler;\n    this._isClosed = _isClosed;\n  }\n  RawReceivePortImpl.builtin$cls = \"RawReceivePortImpl\";\n  if (!\"name\" in RawReceivePortImpl)\n    RawReceivePortImpl.name = \"RawReceivePortImpl\";\n  $desc = $collectedClasses.RawReceivePortImpl;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  RawReceivePortImpl.prototype = $desc;\n  RawReceivePortImpl.prototype.get$_id = function() {\n    return this._id;\n  };\n  RawReceivePortImpl.prototype.get$_isClosed = function() {\n    return this._isClosed;\n  };\n  function ReceivePortImpl(_rawPort, _controller) {\n    this._rawPort = _rawPort;\n    this._controller = _controller;\n  }\n  ReceivePortImpl.builtin$cls = \"ReceivePortImpl\";\n  if (!\"name\" in ReceivePortImpl)\n    ReceivePortImpl.name = \"ReceivePortImpl\";\n  $desc = $collectedClasses.ReceivePortImpl;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ReceivePortImpl.prototype = $desc;\n  function _JsSerializer(_nextFreeRefId, _visited) {\n    this._nextFreeRefId = _nextFreeRefId;\n    this._visited = _visited;\n  }\n  _JsSerializer.builtin$cls = \"_JsSerializer\";\n  if (!\"name\" in _JsSerializer)\n    _JsSerializer.name = \"_JsSerializer\";\n  $desc = $collectedClasses._JsSerializer;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _JsSerializer.prototype = $desc;\n  function _JsCopier(_visited) {\n    this._visited = _visited;\n  }\n  _JsCopier.builtin$cls = \"_JsCopier\";\n  if (!\"name\" in _JsCopier)\n    _JsCopier.name = \"_JsCopier\";\n  $desc = $collectedClasses._JsCopier;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _JsCopier.prototype = $desc;\n  function _JsDeserializer(_deserialized) {\n    this._deserialized = _deserialized;\n  }\n  _JsDeserializer.builtin$cls = \"_JsDeserializer\";\n  if (!\"name\" in _JsDeserializer)\n    _JsDeserializer.name = \"_JsDeserializer\";\n  $desc = $collectedClasses._JsDeserializer;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _JsDeserializer.prototype = $desc;\n  function _JsVisitedMap(tagged) {\n    this.tagged = tagged;\n  }\n  _JsVisitedMap.builtin$cls = \"_JsVisitedMap\";\n  if (!\"name\" in _JsVisitedMap)\n    _JsVisitedMap.name = \"_JsVisitedMap\";\n  $desc = $collectedClasses._JsVisitedMap;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _JsVisitedMap.prototype = $desc;\n  function _MessageTraverserVisitedMap() {\n  }\n  _MessageTraverserVisitedMap.builtin$cls = \"_MessageTraverserVisitedMap\";\n  if (!\"name\" in _MessageTraverserVisitedMap)\n    _MessageTraverserVisitedMap.name = \"_MessageTraverserVisitedMap\";\n  $desc = $collectedClasses._MessageTraverserVisitedMap;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _MessageTraverserVisitedMap.prototype = $desc;\n  function _MessageTraverser() {\n  }\n  _MessageTraverser.builtin$cls = \"_MessageTraverser\";\n  if (!\"name\" in _MessageTraverser)\n    _MessageTraverser.name = \"_MessageTraverser\";\n  $desc = $collectedClasses._MessageTraverser;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _MessageTraverser.prototype = $desc;\n  function _Copier() {\n  }\n  _Copier.builtin$cls = \"_Copier\";\n  if (!\"name\" in _Copier)\n    _Copier.name = \"_Copier\";\n  $desc = $collectedClasses._Copier;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Copier.prototype = $desc;\n  function _Copier_visitMap_closure(box_0, this_1) {\n    this.box_0 = box_0;\n    this.this_1 = this_1;\n  }\n  _Copier_visitMap_closure.builtin$cls = \"_Copier_visitMap_closure\";\n  if (!\"name\" in _Copier_visitMap_closure)\n    _Copier_visitMap_closure.name = \"_Copier_visitMap_closure\";\n  $desc = $collectedClasses._Copier_visitMap_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Copier_visitMap_closure.prototype = $desc;\n  function _Serializer() {\n  }\n  _Serializer.builtin$cls = \"_Serializer\";\n  if (!\"name\" in _Serializer)\n    _Serializer.name = \"_Serializer\";\n  $desc = $collectedClasses._Serializer;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Serializer.prototype = $desc;\n  function _Deserializer() {\n  }\n  _Deserializer.builtin$cls = \"_Deserializer\";\n  if (!\"name\" in _Deserializer)\n    _Deserializer.name = \"_Deserializer\";\n  $desc = $collectedClasses._Deserializer;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Deserializer.prototype = $desc;\n  function TimerImpl(_once, _inEventLoop, _handle) {\n    this._once = _once;\n    this._inEventLoop = _inEventLoop;\n    this._handle = _handle;\n  }\n  TimerImpl.builtin$cls = \"TimerImpl\";\n  if (!\"name\" in TimerImpl)\n    TimerImpl.name = \"TimerImpl\";\n  $desc = $collectedClasses.TimerImpl;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TimerImpl.prototype = $desc;\n  function TimerImpl_internalCallback(this_0, callback_1) {\n    this.this_0 = this_0;\n    this.callback_1 = callback_1;\n  }\n  TimerImpl_internalCallback.builtin$cls = \"TimerImpl_internalCallback\";\n  if (!\"name\" in TimerImpl_internalCallback)\n    TimerImpl_internalCallback.name = \"TimerImpl_internalCallback\";\n  $desc = $collectedClasses.TimerImpl_internalCallback;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TimerImpl_internalCallback.prototype = $desc;\n  function TimerImpl_internalCallback0(this_2, callback_3) {\n    this.this_2 = this_2;\n    this.callback_3 = callback_3;\n  }\n  TimerImpl_internalCallback0.builtin$cls = \"TimerImpl_internalCallback0\";\n  if (!\"name\" in TimerImpl_internalCallback0)\n    TimerImpl_internalCallback0.name = \"TimerImpl_internalCallback0\";\n  $desc = $collectedClasses.TimerImpl_internalCallback0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TimerImpl_internalCallback0.prototype = $desc;\n  function ReflectionInfo(jsFunction, data, isAccessor, requiredParameterCount, optionalParameterCount, areOptionalParametersNamed, functionType) {\n    this.jsFunction = jsFunction;\n    this.data = data;\n    this.isAccessor = isAccessor;\n    this.requiredParameterCount = requiredParameterCount;\n    this.optionalParameterCount = optionalParameterCount;\n    this.areOptionalParametersNamed = areOptionalParametersNamed;\n    this.functionType = functionType;\n  }\n  ReflectionInfo.builtin$cls = \"ReflectionInfo\";\n  if (!\"name\" in ReflectionInfo)\n    ReflectionInfo.name = \"ReflectionInfo\";\n  $desc = $collectedClasses.ReflectionInfo;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ReflectionInfo.prototype = $desc;\n  function TypeErrorDecoder(_pattern, _arguments, _argumentsExpr, _expr, _method, _receiver) {\n    this._pattern = _pattern;\n    this._arguments = _arguments;\n    this._argumentsExpr = _argumentsExpr;\n    this._expr = _expr;\n    this._method = _method;\n    this._receiver = _receiver;\n  }\n  TypeErrorDecoder.builtin$cls = \"TypeErrorDecoder\";\n  if (!\"name\" in TypeErrorDecoder)\n    TypeErrorDecoder.name = \"TypeErrorDecoder\";\n  $desc = $collectedClasses.TypeErrorDecoder;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TypeErrorDecoder.prototype = $desc;\n  TypeErrorDecoder.prototype.get$_receiver = function() {\n    return this._receiver;\n  };\n  function NullError(_message, _method) {\n    this._message = _message;\n    this._method = _method;\n  }\n  NullError.builtin$cls = \"NullError\";\n  if (!\"name\" in NullError)\n    NullError.name = \"NullError\";\n  $desc = $collectedClasses.NullError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  NullError.prototype = $desc;\n  function JsNoSuchMethodError(_message, _method, _receiver) {\n    this._message = _message;\n    this._method = _method;\n    this._receiver = _receiver;\n  }\n  JsNoSuchMethodError.builtin$cls = \"JsNoSuchMethodError\";\n  if (!\"name\" in JsNoSuchMethodError)\n    JsNoSuchMethodError.name = \"JsNoSuchMethodError\";\n  $desc = $collectedClasses.JsNoSuchMethodError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  JsNoSuchMethodError.prototype = $desc;\n  JsNoSuchMethodError.prototype.get$_receiver = function() {\n    return this._receiver;\n  };\n  function UnknownJsTypeError(_message) {\n    this._message = _message;\n  }\n  UnknownJsTypeError.builtin$cls = \"UnknownJsTypeError\";\n  if (!\"name\" in UnknownJsTypeError)\n    UnknownJsTypeError.name = \"UnknownJsTypeError\";\n  $desc = $collectedClasses.UnknownJsTypeError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  UnknownJsTypeError.prototype = $desc;\n  function unwrapException_saveStackTrace(ex_0) {\n    this.ex_0 = ex_0;\n  }\n  unwrapException_saveStackTrace.builtin$cls = \"unwrapException_saveStackTrace\";\n  if (!\"name\" in unwrapException_saveStackTrace)\n    unwrapException_saveStackTrace.name = \"unwrapException_saveStackTrace\";\n  $desc = $collectedClasses.unwrapException_saveStackTrace;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  unwrapException_saveStackTrace.prototype = $desc;\n  function _StackTrace(_exception, _trace) {\n    this._exception = _exception;\n    this._trace = _trace;\n  }\n  _StackTrace.builtin$cls = \"_StackTrace\";\n  if (!\"name\" in _StackTrace)\n    _StackTrace.name = \"_StackTrace\";\n  $desc = $collectedClasses._StackTrace;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _StackTrace.prototype = $desc;\n  function invokeClosure_closure(closure_0) {\n    this.closure_0 = closure_0;\n  }\n  invokeClosure_closure.builtin$cls = \"invokeClosure_closure\";\n  if (!\"name\" in invokeClosure_closure)\n    invokeClosure_closure.name = \"invokeClosure_closure\";\n  $desc = $collectedClasses.invokeClosure_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  invokeClosure_closure.prototype = $desc;\n  function invokeClosure_closure0(closure_1, arg1_2) {\n    this.closure_1 = closure_1;\n    this.arg1_2 = arg1_2;\n  }\n  invokeClosure_closure0.builtin$cls = \"invokeClosure_closure0\";\n  if (!\"name\" in invokeClosure_closure0)\n    invokeClosure_closure0.name = \"invokeClosure_closure0\";\n  $desc = $collectedClasses.invokeClosure_closure0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  invokeClosure_closure0.prototype = $desc;\n  function invokeClosure_closure1(closure_3, arg1_4, arg2_5) {\n    this.closure_3 = closure_3;\n    this.arg1_4 = arg1_4;\n    this.arg2_5 = arg2_5;\n  }\n  invokeClosure_closure1.builtin$cls = \"invokeClosure_closure1\";\n  if (!\"name\" in invokeClosure_closure1)\n    invokeClosure_closure1.name = \"invokeClosure_closure1\";\n  $desc = $collectedClasses.invokeClosure_closure1;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  invokeClosure_closure1.prototype = $desc;\n  function invokeClosure_closure2(closure_6, arg1_7, arg2_8, arg3_9) {\n    this.closure_6 = closure_6;\n    this.arg1_7 = arg1_7;\n    this.arg2_8 = arg2_8;\n    this.arg3_9 = arg3_9;\n  }\n  invokeClosure_closure2.builtin$cls = \"invokeClosure_closure2\";\n  if (!\"name\" in invokeClosure_closure2)\n    invokeClosure_closure2.name = \"invokeClosure_closure2\";\n  $desc = $collectedClasses.invokeClosure_closure2;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  invokeClosure_closure2.prototype = $desc;\n  function invokeClosure_closure3(closure_10, arg1_11, arg2_12, arg3_13, arg4_14) {\n    this.closure_10 = closure_10;\n    this.arg1_11 = arg1_11;\n    this.arg2_12 = arg2_12;\n    this.arg3_13 = arg3_13;\n    this.arg4_14 = arg4_14;\n  }\n  invokeClosure_closure3.builtin$cls = \"invokeClosure_closure3\";\n  if (!\"name\" in invokeClosure_closure3)\n    invokeClosure_closure3.name = \"invokeClosure_closure3\";\n  $desc = $collectedClasses.invokeClosure_closure3;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  invokeClosure_closure3.prototype = $desc;\n  function Closure() {\n  }\n  Closure.builtin$cls = \"Closure\";\n  if (!\"name\" in Closure)\n    Closure.name = \"Closure\";\n  $desc = $collectedClasses.Closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Closure.prototype = $desc;\n  function TearOffClosure() {\n  }\n  TearOffClosure.builtin$cls = \"TearOffClosure\";\n  if (!\"name\" in TearOffClosure)\n    TearOffClosure.name = \"TearOffClosure\";\n  $desc = $collectedClasses.TearOffClosure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TearOffClosure.prototype = $desc;\n  function BoundClosure(_self, _target, _receiver, __js_helper$_name) {\n    this._self = _self;\n    this._target = _target;\n    this._receiver = _receiver;\n    this.__js_helper$_name = __js_helper$_name;\n  }\n  BoundClosure.builtin$cls = \"BoundClosure\";\n  if (!\"name\" in BoundClosure)\n    BoundClosure.name = \"BoundClosure\";\n  $desc = $collectedClasses.BoundClosure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  BoundClosure.prototype = $desc;\n  BoundClosure.prototype.get$_self = function() {\n    return this._self;\n  };\n  BoundClosure.prototype.get$_receiver = function() {\n    return this._receiver;\n  };\n  function RuntimeError(message) {\n    this.message = message;\n  }\n  RuntimeError.builtin$cls = \"RuntimeError\";\n  if (!\"name\" in RuntimeError)\n    RuntimeError.name = \"RuntimeError\";\n  $desc = $collectedClasses.RuntimeError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  RuntimeError.prototype = $desc;\n  function RuntimeType() {\n  }\n  RuntimeType.builtin$cls = \"RuntimeType\";\n  if (!\"name\" in RuntimeType)\n    RuntimeType.name = \"RuntimeType\";\n  $desc = $collectedClasses.RuntimeType;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  RuntimeType.prototype = $desc;\n  function RuntimeFunctionType(returnType, parameterTypes, optionalParameterTypes, namedParameters) {\n    this.returnType = returnType;\n    this.parameterTypes = parameterTypes;\n    this.optionalParameterTypes = optionalParameterTypes;\n    this.namedParameters = namedParameters;\n  }\n  RuntimeFunctionType.builtin$cls = \"RuntimeFunctionType\";\n  if (!\"name\" in RuntimeFunctionType)\n    RuntimeFunctionType.name = \"RuntimeFunctionType\";\n  $desc = $collectedClasses.RuntimeFunctionType;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  RuntimeFunctionType.prototype = $desc;\n  function DynamicRuntimeType() {\n  }\n  DynamicRuntimeType.builtin$cls = \"DynamicRuntimeType\";\n  if (!\"name\" in DynamicRuntimeType)\n    DynamicRuntimeType.name = \"DynamicRuntimeType\";\n  $desc = $collectedClasses.DynamicRuntimeType;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DynamicRuntimeType.prototype = $desc;\n  function TypeImpl(_typeName, _unmangledName) {\n    this._typeName = _typeName;\n    this._unmangledName = _unmangledName;\n  }\n  TypeImpl.builtin$cls = \"TypeImpl\";\n  if (!\"name\" in TypeImpl)\n    TypeImpl.name = \"TypeImpl\";\n  $desc = $collectedClasses.TypeImpl;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  TypeImpl.prototype = $desc;\n  function initHooks_closure(getTag_0) {\n    this.getTag_0 = getTag_0;\n  }\n  initHooks_closure.builtin$cls = \"initHooks_closure\";\n  if (!\"name\" in initHooks_closure)\n    initHooks_closure.name = \"initHooks_closure\";\n  $desc = $collectedClasses.initHooks_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  initHooks_closure.prototype = $desc;\n  function initHooks_closure0(getUnknownTag_1) {\n    this.getUnknownTag_1 = getUnknownTag_1;\n  }\n  initHooks_closure0.builtin$cls = \"initHooks_closure0\";\n  if (!\"name\" in initHooks_closure0)\n    initHooks_closure0.name = \"initHooks_closure0\";\n  $desc = $collectedClasses.initHooks_closure0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  initHooks_closure0.prototype = $desc;\n  function initHooks_closure1(prototypeForTag_2) {\n    this.prototypeForTag_2 = prototypeForTag_2;\n  }\n  initHooks_closure1.builtin$cls = \"initHooks_closure1\";\n  if (!\"name\" in initHooks_closure1)\n    initHooks_closure1.name = \"initHooks_closure1\";\n  $desc = $collectedClasses.initHooks_closure1;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  initHooks_closure1.prototype = $desc;\n  function Balls(root, lastTime, balls) {\n    this.root = root;\n    this.lastTime = lastTime;\n    this.balls = balls;\n  }\n  Balls.builtin$cls = \"Balls\";\n  if (!\"name\" in Balls)\n    Balls.name = \"Balls\";\n  $desc = $collectedClasses.Balls;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Balls.prototype = $desc;\n  function Balls_tick_closure(delta_0) {\n    this.delta_0 = delta_0;\n  }\n  Balls_tick_closure.builtin$cls = \"Balls_tick_closure\";\n  if (!\"name\" in Balls_tick_closure)\n    Balls_tick_closure.name = \"Balls_tick_closure\";\n  $desc = $collectedClasses.Balls_tick_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Balls_tick_closure.prototype = $desc;\n  function Balls_collideBalls_closure(this_0, delta_1) {\n    this.this_0 = this_0;\n    this.delta_1 = delta_1;\n  }\n  Balls_collideBalls_closure.builtin$cls = \"Balls_collideBalls_closure\";\n  if (!\"name\" in Balls_collideBalls_closure)\n    Balls_collideBalls_closure.name = \"Balls_collideBalls_closure\";\n  $desc = $collectedClasses.Balls_collideBalls_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Balls_collideBalls_closure.prototype = $desc;\n  function Balls_collideBalls__closure(this_2, delta_3, b0_4) {\n    this.this_2 = this_2;\n    this.delta_3 = delta_3;\n    this.b0_4 = b0_4;\n  }\n  Balls_collideBalls__closure.builtin$cls = \"Balls_collideBalls__closure\";\n  if (!\"name\" in Balls_collideBalls__closure)\n    Balls_collideBalls__closure.name = \"Balls_collideBalls__closure\";\n  $desc = $collectedClasses.Balls_collideBalls__closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Balls_collideBalls__closure.prototype = $desc;\n  function Ball(root, elem, x, y, vx, vy, ax, ay, age) {\n    this.root = root;\n    this.elem = elem;\n    this.x = x;\n    this.y = y;\n    this.vx = vx;\n    this.vy = vy;\n    this.ax = ax;\n    this.ay = ay;\n    this.age = age;\n  }\n  Ball.builtin$cls = \"Ball\";\n  if (!\"name\" in Ball)\n    Ball.name = \"Ball\";\n  $desc = $collectedClasses.Ball;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Ball.prototype = $desc;\n  Ball.prototype.get$x = function(receiver) {\n    return this.x;\n  };\n  Ball.prototype.get$y = function(receiver) {\n    return this.y;\n  };\n  Ball.prototype.get$vx = function() {\n    return this.vx;\n  };\n  function CountDownClock(hours, minutes, seconds, displayedHour, displayedMinute, displayedSecond, balls) {\n    this.hours = hours;\n    this.minutes = minutes;\n    this.seconds = seconds;\n    this.displayedHour = displayedHour;\n    this.displayedMinute = displayedMinute;\n    this.displayedSecond = displayedSecond;\n    this.balls = balls;\n  }\n  CountDownClock.builtin$cls = \"CountDownClock\";\n  if (!\"name\" in CountDownClock)\n    CountDownClock.name = \"CountDownClock\";\n  $desc = $collectedClasses.CountDownClock;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  CountDownClock.prototype = $desc;\n  function ClockNumber(app, root, imgs, pixels, ballColor) {\n    this.app = app;\n    this.root = root;\n    this.imgs = imgs;\n    this.pixels = pixels;\n    this.ballColor = ballColor;\n  }\n  ClockNumber.builtin$cls = \"ClockNumber\";\n  if (!\"name\" in ClockNumber)\n    ClockNumber.name = \"ClockNumber\";\n  $desc = $collectedClasses.ClockNumber;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ClockNumber.prototype = $desc;\n  function ClockNumber_setPixels_closure(this_0, img_1) {\n    this.this_0 = this_0;\n    this.img_1 = img_1;\n  }\n  ClockNumber_setPixels_closure.builtin$cls = \"ClockNumber_setPixels_closure\";\n  if (!\"name\" in ClockNumber_setPixels_closure)\n    ClockNumber_setPixels_closure.name = \"ClockNumber_setPixels_closure\";\n  $desc = $collectedClasses.ClockNumber_setPixels_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ClockNumber_setPixels_closure.prototype = $desc;\n  function Colon(root) {\n    this.root = root;\n  }\n  Colon.builtin$cls = \"Colon\";\n  if (!\"name\" in Colon)\n    Colon.name = \"Colon\";\n  $desc = $collectedClasses.Colon;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Colon.prototype = $desc;\n  function ListIterator(_iterable, _dev$_length, _index, _dev$_current) {\n    this._iterable = _iterable;\n    this._dev$_length = _dev$_length;\n    this._index = _index;\n    this._dev$_current = _dev$_current;\n  }\n  ListIterator.builtin$cls = \"ListIterator\";\n  if (!\"name\" in ListIterator)\n    ListIterator.name = \"ListIterator\";\n  $desc = $collectedClasses.ListIterator;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ListIterator.prototype = $desc;\n  function MappedIterable(_iterable, _f) {\n    this._iterable = _iterable;\n    this._f = _f;\n  }\n  MappedIterable.builtin$cls = \"MappedIterable\";\n  if (!\"name\" in MappedIterable)\n    MappedIterable.name = \"MappedIterable\";\n  $desc = $collectedClasses.MappedIterable;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MappedIterable.prototype = $desc;\n  function EfficientLengthMappedIterable(_iterable, _f) {\n    this._iterable = _iterable;\n    this._f = _f;\n  }\n  EfficientLengthMappedIterable.builtin$cls = \"EfficientLengthMappedIterable\";\n  if (!\"name\" in EfficientLengthMappedIterable)\n    EfficientLengthMappedIterable.name = \"EfficientLengthMappedIterable\";\n  $desc = $collectedClasses.EfficientLengthMappedIterable;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  EfficientLengthMappedIterable.prototype = $desc;\n  function MappedIterator(_dev$_current, _iterator, _f) {\n    this._dev$_current = _dev$_current;\n    this._iterator = _iterator;\n    this._f = _f;\n  }\n  MappedIterator.builtin$cls = \"MappedIterator\";\n  if (!\"name\" in MappedIterator)\n    MappedIterator.name = \"MappedIterator\";\n  $desc = $collectedClasses.MappedIterator;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  MappedIterator.prototype = $desc;\n  function FixedLengthListMixin() {\n  }\n  FixedLengthListMixin.builtin$cls = \"FixedLengthListMixin\";\n  if (!\"name\" in FixedLengthListMixin)\n    FixedLengthListMixin.name = \"FixedLengthListMixin\";\n  $desc = $collectedClasses.FixedLengthListMixin;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FixedLengthListMixin.prototype = $desc;\n  function _AsyncError(error, stackTrace) {\n    this.error = error;\n    this.stackTrace = stackTrace;\n  }\n  _AsyncError.builtin$cls = \"_AsyncError\";\n  if (!\"name\" in _AsyncError)\n    _AsyncError.name = \"_AsyncError\";\n  $desc = $collectedClasses._AsyncError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _AsyncError.prototype = $desc;\n  _AsyncError.prototype.get$error = function(receiver) {\n    return this.error;\n  };\n  _AsyncError.prototype.get$stackTrace = function() {\n    return this.stackTrace;\n  };\n  function Future() {\n  }\n  Future.builtin$cls = \"Future\";\n  if (!\"name\" in Future)\n    Future.name = \"Future\";\n  $desc = $collectedClasses.Future;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Future.prototype = $desc;\n  function _Future(_state, _zone, _resultOrListeners, _nextListener, _onValueCallback, _errorTestCallback, _onErrorCallback, _whenCompleteActionCallback) {\n    this._state = _state;\n    this._zone = _zone;\n    this._resultOrListeners = _resultOrListeners;\n    this._nextListener = _nextListener;\n    this._onValueCallback = _onValueCallback;\n    this._errorTestCallback = _errorTestCallback;\n    this._onErrorCallback = _onErrorCallback;\n    this._whenCompleteActionCallback = _whenCompleteActionCallback;\n  }\n  _Future.builtin$cls = \"_Future\";\n  if (!\"name\" in _Future)\n    _Future.name = \"_Future\";\n  $desc = $collectedClasses._Future;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Future.prototype = $desc;\n  _Future.prototype.get$_zone = function() {\n    return this._zone;\n  };\n  _Future.prototype.get$_nextListener = function() {\n    return this._nextListener;\n  };\n  function _Future__addListener_closure(this_0, listener_1) {\n    this.this_0 = this_0;\n    this.listener_1 = listener_1;\n  }\n  _Future__addListener_closure.builtin$cls = \"_Future__addListener_closure\";\n  if (!\"name\" in _Future__addListener_closure)\n    _Future__addListener_closure.name = \"_Future__addListener_closure\";\n  $desc = $collectedClasses._Future__addListener_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Future__addListener_closure.prototype = $desc;\n  function _Future__chainFutures_closure(target_0) {\n    this.target_0 = target_0;\n  }\n  _Future__chainFutures_closure.builtin$cls = \"_Future__chainFutures_closure\";\n  if (!\"name\" in _Future__chainFutures_closure)\n    _Future__chainFutures_closure.name = \"_Future__chainFutures_closure\";\n  $desc = $collectedClasses._Future__chainFutures_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Future__chainFutures_closure.prototype = $desc;\n  function _Future__chainFutures_closure0(target_1) {\n    this.target_1 = target_1;\n  }\n  _Future__chainFutures_closure0.builtin$cls = \"_Future__chainFutures_closure0\";\n  if (!\"name\" in _Future__chainFutures_closure0)\n    _Future__chainFutures_closure0.name = \"_Future__chainFutures_closure0\";\n  $desc = $collectedClasses._Future__chainFutures_closure0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Future__chainFutures_closure0.prototype = $desc;\n  function _Future__asyncComplete_closure(this_0, value_1) {\n    this.this_0 = this_0;\n    this.value_1 = value_1;\n  }\n  _Future__asyncComplete_closure.builtin$cls = \"_Future__asyncComplete_closure\";\n  if (!\"name\" in _Future__asyncComplete_closure)\n    _Future__asyncComplete_closure.name = \"_Future__asyncComplete_closure\";\n  $desc = $collectedClasses._Future__asyncComplete_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Future__asyncComplete_closure.prototype = $desc;\n  function _Future__propagateToListeners_closure(box_2, listener_3) {\n    this.box_2 = box_2;\n    this.listener_3 = listener_3;\n  }\n  _Future__propagateToListeners_closure.builtin$cls = \"_Future__propagateToListeners_closure\";\n  if (!\"name\" in _Future__propagateToListeners_closure)\n    _Future__propagateToListeners_closure.name = \"_Future__propagateToListeners_closure\";\n  $desc = $collectedClasses._Future__propagateToListeners_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Future__propagateToListeners_closure.prototype = $desc;\n  function _Future__propagateToListeners_closure0(box_2, box_1, hasError_4, listener_5) {\n    this.box_2 = box_2;\n    this.box_1 = box_1;\n    this.hasError_4 = hasError_4;\n    this.listener_5 = listener_5;\n  }\n  _Future__propagateToListeners_closure0.builtin$cls = \"_Future__propagateToListeners_closure0\";\n  if (!\"name\" in _Future__propagateToListeners_closure0)\n    _Future__propagateToListeners_closure0.name = \"_Future__propagateToListeners_closure0\";\n  $desc = $collectedClasses._Future__propagateToListeners_closure0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Future__propagateToListeners_closure0.prototype = $desc;\n  function _Future__propagateToListeners__closure(box_2, listener_6) {\n    this.box_2 = box_2;\n    this.listener_6 = listener_6;\n  }\n  _Future__propagateToListeners__closure.builtin$cls = \"_Future__propagateToListeners__closure\";\n  if (!\"name\" in _Future__propagateToListeners__closure)\n    _Future__propagateToListeners__closure.name = \"_Future__propagateToListeners__closure\";\n  $desc = $collectedClasses._Future__propagateToListeners__closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Future__propagateToListeners__closure.prototype = $desc;\n  function _Future__propagateToListeners__closure0(box_0, listener_7) {\n    this.box_0 = box_0;\n    this.listener_7 = listener_7;\n  }\n  _Future__propagateToListeners__closure0.builtin$cls = \"_Future__propagateToListeners__closure0\";\n  if (!\"name\" in _Future__propagateToListeners__closure0)\n    _Future__propagateToListeners__closure0.name = \"_Future__propagateToListeners__closure0\";\n  $desc = $collectedClasses._Future__propagateToListeners__closure0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _Future__propagateToListeners__closure0.prototype = $desc;\n  function Stream() {\n  }\n  Stream.builtin$cls = \"Stream\";\n  if (!\"name\" in Stream)\n    Stream.name = \"Stream\";\n  $desc = $collectedClasses.Stream;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Stream.prototype = $desc;\n  function Stream_forEach_closure(box_0, this_1, action_2, future_3) {\n    this.box_0 = box_0;\n    this.this_1 = this_1;\n    this.action_2 = action_2;\n    this.future_3 = future_3;\n  }\n  Stream_forEach_closure.builtin$cls = \"Stream_forEach_closure\";\n  if (!\"name\" in Stream_forEach_closure)\n    Stream_forEach_closure.name = \"Stream_forEach_closure\";\n  $desc = $collectedClasses.Stream_forEach_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Stream_forEach_closure.prototype = $desc;\n  function Stream_forEach__closure(action_4, element_5) {\n    this.action_4 = action_4;\n    this.element_5 = element_5;\n  }\n  Stream_forEach__closure.builtin$cls = \"Stream_forEach__closure\";\n  if (!\"name\" in Stream_forEach__closure)\n    Stream_forEach__closure.name = \"Stream_forEach__closure\";\n  $desc = $collectedClasses.Stream_forEach__closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Stream_forEach__closure.prototype = $desc;\n  function Stream_forEach__closure0() {\n  }\n  Stream_forEach__closure0.builtin$cls = \"Stream_forEach__closure0\";\n  if (!\"name\" in Stream_forEach__closure0)\n    Stream_forEach__closure0.name = \"Stream_forEach__closure0\";\n  $desc = $collectedClasses.Stream_forEach__closure0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Stream_forEach__closure0.prototype = $desc;\n  function Stream_forEach_closure0(future_6) {\n    this.future_6 = future_6;\n  }\n  Stream_forEach_closure0.builtin$cls = \"Stream_forEach_closure0\";\n  if (!\"name\" in Stream_forEach_closure0)\n    Stream_forEach_closure0.name = \"Stream_forEach_closure0\";\n  $desc = $collectedClasses.Stream_forEach_closure0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Stream_forEach_closure0.prototype = $desc;\n  function Stream_length_closure(box_0) {\n    this.box_0 = box_0;\n  }\n  Stream_length_closure.builtin$cls = \"Stream_length_closure\";\n  if (!\"name\" in Stream_length_closure)\n    Stream_length_closure.name = \"Stream_length_closure\";\n  $desc = $collectedClasses.Stream_length_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Stream_length_closure.prototype = $desc;\n  function Stream_length_closure0(box_0, future_1) {\n    this.box_0 = box_0;\n    this.future_1 = future_1;\n  }\n  Stream_length_closure0.builtin$cls = \"Stream_length_closure0\";\n  if (!\"name\" in Stream_length_closure0)\n    Stream_length_closure0.name = \"Stream_length_closure0\";\n  $desc = $collectedClasses.Stream_length_closure0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Stream_length_closure0.prototype = $desc;\n  function StreamSubscription() {\n  }\n  StreamSubscription.builtin$cls = \"StreamSubscription\";\n  if (!\"name\" in StreamSubscription)\n    StreamSubscription.name = \"StreamSubscription\";\n  $desc = $collectedClasses.StreamSubscription;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  StreamSubscription.prototype = $desc;\n  function _StreamController() {\n  }\n  _StreamController.builtin$cls = \"_StreamController\";\n  if (!\"name\" in _StreamController)\n    _StreamController.name = \"_StreamController\";\n  $desc = $collectedClasses._StreamController;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _StreamController.prototype = $desc;\n  function _StreamController__subscribe_closure(this_0) {\n    this.this_0 = this_0;\n  }\n  _StreamController__subscribe_closure.builtin$cls = \"_StreamController__subscribe_closure\";\n  if (!\"name\" in _StreamController__subscribe_closure)\n    _StreamController__subscribe_closure.name = \"_StreamController__subscribe_closure\";\n  $desc = $collectedClasses._StreamController__subscribe_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _StreamController__subscribe_closure.prototype = $desc;\n  function _StreamController__recordCancel_complete(this_0) {\n    this.this_0 = this_0;\n  }\n  _StreamController__recordCancel_complete.builtin$cls = \"_StreamController__recordCancel_complete\";\n  if (!\"name\" in _StreamController__recordCancel_complete)\n    _StreamController__recordCancel_complete.name = \"_StreamController__recordCancel_complete\";\n  $desc = $collectedClasses._StreamController__recordCancel_complete;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _StreamController__recordCancel_complete.prototype = $desc;\n  function _SyncStreamControllerDispatch() {\n  }\n  _SyncStreamControllerDispatch.builtin$cls = \"_SyncStreamControllerDispatch\";\n  if (!\"name\" in _SyncStreamControllerDispatch)\n    _SyncStreamControllerDispatch.name = \"_SyncStreamControllerDispatch\";\n  $desc = $collectedClasses._SyncStreamControllerDispatch;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SyncStreamControllerDispatch.prototype = $desc;\n  function _AsyncStreamControllerDispatch() {\n  }\n  _AsyncStreamControllerDispatch.builtin$cls = \"_AsyncStreamControllerDispatch\";\n  if (!\"name\" in _AsyncStreamControllerDispatch)\n    _AsyncStreamControllerDispatch.name = \"_AsyncStreamControllerDispatch\";\n  $desc = $collectedClasses._AsyncStreamControllerDispatch;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _AsyncStreamControllerDispatch.prototype = $desc;\n  function _AsyncStreamController(_onListen, _onPause, _onResume, _onCancel, _varData, _state, _doneFuture) {\n    this._onListen = _onListen;\n    this._onPause = _onPause;\n    this._onResume = _onResume;\n    this._onCancel = _onCancel;\n    this._varData = _varData;\n    this._state = _state;\n    this._doneFuture = _doneFuture;\n  }\n  _AsyncStreamController.builtin$cls = \"_AsyncStreamController\";\n  if (!\"name\" in _AsyncStreamController)\n    _AsyncStreamController.name = \"_AsyncStreamController\";\n  $desc = $collectedClasses._AsyncStreamController;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _AsyncStreamController.prototype = $desc;\n  _AsyncStreamController.prototype.get$_onListen = function() {\n    return this._onListen;\n  };\n  _AsyncStreamController.prototype.get$_onPause = function() {\n    return this._onPause;\n  };\n  _AsyncStreamController.prototype.get$_onResume = function() {\n    return this._onResume;\n  };\n  _AsyncStreamController.prototype.get$_onCancel = function() {\n    return this._onCancel;\n  };\n  function _StreamController__AsyncStreamControllerDispatch() {\n  }\n  _StreamController__AsyncStreamControllerDispatch.builtin$cls = \"_StreamController__AsyncStreamControllerDispatch\";\n  if (!\"name\" in _StreamController__AsyncStreamControllerDispatch)\n    _StreamController__AsyncStreamControllerDispatch.name = \"_StreamController__AsyncStreamControllerDispatch\";\n  $desc = $collectedClasses._StreamController__AsyncStreamControllerDispatch;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _StreamController__AsyncStreamControllerDispatch.prototype = $desc;\n  function _SyncStreamController(_onListen, _onPause, _onResume, _onCancel, _varData, _state, _doneFuture) {\n    this._onListen = _onListen;\n    this._onPause = _onPause;\n    this._onResume = _onResume;\n    this._onCancel = _onCancel;\n    this._varData = _varData;\n    this._state = _state;\n    this._doneFuture = _doneFuture;\n  }\n  _SyncStreamController.builtin$cls = \"_SyncStreamController\";\n  if (!\"name\" in _SyncStreamController)\n    _SyncStreamController.name = \"_SyncStreamController\";\n  $desc = $collectedClasses._SyncStreamController;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _SyncStreamController.prototype = $desc;\n  _SyncStreamController.prototype.get$_onListen = function() {\n    return this._onListen;\n  };\n  _SyncStreamController.prototype.get$_onPause = function() {\n    return this._onPause;\n  };\n  _SyncStreamController.prototype.get$_onResume = function() {\n    return this._onResume;\n  };\n  _SyncStreamController.prototype.get$_onCancel = function() {\n    return this._onCancel;\n  };\n  function _StreamController__SyncStreamControllerDispatch() {\n  }\n  _StreamController__SyncStreamControllerDispatch.builtin$cls = \"_StreamController__SyncStreamControllerDispatch\";\n  if (!\"name\" in _StreamController__SyncStreamControllerDispatch)\n    _StreamController__SyncStreamControllerDispatch.name = \"_StreamController__SyncStreamControllerDispatch\";\n  $desc = $collectedClasses._StreamController__SyncStreamControllerDispatch;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _StreamController__SyncStreamControllerDispatch.prototype = $desc;\n  function _ControllerStream(_async$_controller) {\n    this._async$_controller = _async$_controller;\n  }\n  _ControllerStream.builtin$cls = \"_ControllerStream\";\n  if (!\"name\" in _ControllerStream)\n    _ControllerStream.name = \"_ControllerStream\";\n  $desc = $collectedClasses._ControllerStream;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _ControllerStream.prototype = $desc;\n  function _ControllerSubscription(_async$_controller, _onData, _onError, _onDone, _zone, _state, _cancelFuture, _pending) {\n    this._async$_controller = _async$_controller;\n    this._onData = _onData;\n    this._onError = _onError;\n    this._onDone = _onDone;\n    this._zone = _zone;\n    this._state = _state;\n    this._cancelFuture = _cancelFuture;\n    this._pending = _pending;\n  }\n  _ControllerSubscription.builtin$cls = \"_ControllerSubscription\";\n  if (!\"name\" in _ControllerSubscription)\n    _ControllerSubscription.name = \"_ControllerSubscription\";\n  $desc = $collectedClasses._ControllerSubscription;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _ControllerSubscription.prototype = $desc;\n  function _EventSink() {\n  }\n  _EventSink.builtin$cls = \"_EventSink\";\n  if (!\"name\" in _EventSink)\n    _EventSink.name = \"_EventSink\";\n  $desc = $collectedClasses._EventSink;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _EventSink.prototype = $desc;\n  function _BufferingStreamSubscription(_onData, _onError, _onDone, _zone, _state, _cancelFuture, _pending) {\n    this._onData = _onData;\n    this._onError = _onError;\n    this._onDone = _onDone;\n    this._zone = _zone;\n    this._state = _state;\n    this._cancelFuture = _cancelFuture;\n    this._pending = _pending;\n  }\n  _BufferingStreamSubscription.builtin$cls = \"_BufferingStreamSubscription\";\n  if (!\"name\" in _BufferingStreamSubscription)\n    _BufferingStreamSubscription.name = \"_BufferingStreamSubscription\";\n  $desc = $collectedClasses._BufferingStreamSubscription;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _BufferingStreamSubscription.prototype = $desc;\n  _BufferingStreamSubscription.prototype.get$_zone = function() {\n    return this._zone;\n  };\n  function _BufferingStreamSubscription__sendDone_sendDone(this_0) {\n    this.this_0 = this_0;\n  }\n  _BufferingStreamSubscription__sendDone_sendDone.builtin$cls = \"_BufferingStreamSubscription__sendDone_sendDone\";\n  if (!\"name\" in _BufferingStreamSubscription__sendDone_sendDone)\n    _BufferingStreamSubscription__sendDone_sendDone.name = \"_BufferingStreamSubscription__sendDone_sendDone\";\n  $desc = $collectedClasses._BufferingStreamSubscription__sendDone_sendDone;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _BufferingStreamSubscription__sendDone_sendDone.prototype = $desc;\n  function _StreamImpl() {\n  }\n  _StreamImpl.builtin$cls = \"_StreamImpl\";\n  if (!\"name\" in _StreamImpl)\n    _StreamImpl.name = \"_StreamImpl\";\n  $desc = $collectedClasses._StreamImpl;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _StreamImpl.prototype = $desc;\n  function _DelayedEvent(next) {\n    this.next = next;\n  }\n  _DelayedEvent.builtin$cls = \"_DelayedEvent\";\n  if (!\"name\" in _DelayedEvent)\n    _DelayedEvent.name = \"_DelayedEvent\";\n  $desc = $collectedClasses._DelayedEvent;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _DelayedEvent.prototype = $desc;\n  _DelayedEvent.prototype.get$next = function() {\n    return this.next;\n  };\n  _DelayedEvent.prototype.set$next = function(v) {\n    return this.next = v;\n  };\n  function _DelayedData(value, next) {\n    this.value = value;\n    this.next = next;\n  }\n  _DelayedData.builtin$cls = \"_DelayedData\";\n  if (!\"name\" in _DelayedData)\n    _DelayedData.name = \"_DelayedData\";\n  $desc = $collectedClasses._DelayedData;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _DelayedData.prototype = $desc;\n  function _DelayedDone() {\n  }\n  _DelayedDone.builtin$cls = \"_DelayedDone\";\n  if (!\"name\" in _DelayedDone)\n    _DelayedDone.name = \"_DelayedDone\";\n  $desc = $collectedClasses._DelayedDone;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _DelayedDone.prototype = $desc;\n  function _PendingEvents() {\n  }\n  _PendingEvents.builtin$cls = \"_PendingEvents\";\n  if (!\"name\" in _PendingEvents)\n    _PendingEvents.name = \"_PendingEvents\";\n  $desc = $collectedClasses._PendingEvents;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _PendingEvents.prototype = $desc;\n  function _PendingEvents_schedule_closure(this_0, dispatch_1) {\n    this.this_0 = this_0;\n    this.dispatch_1 = dispatch_1;\n  }\n  _PendingEvents_schedule_closure.builtin$cls = \"_PendingEvents_schedule_closure\";\n  if (!\"name\" in _PendingEvents_schedule_closure)\n    _PendingEvents_schedule_closure.name = \"_PendingEvents_schedule_closure\";\n  $desc = $collectedClasses._PendingEvents_schedule_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _PendingEvents_schedule_closure.prototype = $desc;\n  function _StreamImplEvents(firstPendingEvent, lastPendingEvent, _state) {\n    this.firstPendingEvent = firstPendingEvent;\n    this.lastPendingEvent = lastPendingEvent;\n    this._state = _state;\n  }\n  _StreamImplEvents.builtin$cls = \"_StreamImplEvents\";\n  if (!\"name\" in _StreamImplEvents)\n    _StreamImplEvents.name = \"_StreamImplEvents\";\n  $desc = $collectedClasses._StreamImplEvents;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _StreamImplEvents.prototype = $desc;\n  function _cancelAndError_closure(future_0, error_1, stackTrace_2) {\n    this.future_0 = future_0;\n    this.error_1 = error_1;\n    this.stackTrace_2 = stackTrace_2;\n  }\n  _cancelAndError_closure.builtin$cls = \"_cancelAndError_closure\";\n  if (!\"name\" in _cancelAndError_closure)\n    _cancelAndError_closure.name = \"_cancelAndError_closure\";\n  $desc = $collectedClasses._cancelAndError_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _cancelAndError_closure.prototype = $desc;\n  function _cancelAndErrorClosure_closure(subscription_0, future_1) {\n    this.subscription_0 = subscription_0;\n    this.future_1 = future_1;\n  }\n  _cancelAndErrorClosure_closure.builtin$cls = \"_cancelAndErrorClosure_closure\";\n  if (!\"name\" in _cancelAndErrorClosure_closure)\n    _cancelAndErrorClosure_closure.name = \"_cancelAndErrorClosure_closure\";\n  $desc = $collectedClasses._cancelAndErrorClosure_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _cancelAndErrorClosure_closure.prototype = $desc;\n  function _BaseZone() {\n  }\n  _BaseZone.builtin$cls = \"_BaseZone\";\n  if (!\"name\" in _BaseZone)\n    _BaseZone.name = \"_BaseZone\";\n  $desc = $collectedClasses._BaseZone;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _BaseZone.prototype = $desc;\n  function _BaseZone_bindCallback_closure(this_0, registered_1) {\n    this.this_0 = this_0;\n    this.registered_1 = registered_1;\n  }\n  _BaseZone_bindCallback_closure.builtin$cls = \"_BaseZone_bindCallback_closure\";\n  if (!\"name\" in _BaseZone_bindCallback_closure)\n    _BaseZone_bindCallback_closure.name = \"_BaseZone_bindCallback_closure\";\n  $desc = $collectedClasses._BaseZone_bindCallback_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _BaseZone_bindCallback_closure.prototype = $desc;\n  function _BaseZone_bindCallback_closure0(this_2, registered_3) {\n    this.this_2 = this_2;\n    this.registered_3 = registered_3;\n  }\n  _BaseZone_bindCallback_closure0.builtin$cls = \"_BaseZone_bindCallback_closure0\";\n  if (!\"name\" in _BaseZone_bindCallback_closure0)\n    _BaseZone_bindCallback_closure0.name = \"_BaseZone_bindCallback_closure0\";\n  $desc = $collectedClasses._BaseZone_bindCallback_closure0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _BaseZone_bindCallback_closure0.prototype = $desc;\n  function _BaseZone_bindUnaryCallback_closure(this_0, registered_1) {\n    this.this_0 = this_0;\n    this.registered_1 = registered_1;\n  }\n  _BaseZone_bindUnaryCallback_closure.builtin$cls = \"_BaseZone_bindUnaryCallback_closure\";\n  if (!\"name\" in _BaseZone_bindUnaryCallback_closure)\n    _BaseZone_bindUnaryCallback_closure.name = \"_BaseZone_bindUnaryCallback_closure\";\n  $desc = $collectedClasses._BaseZone_bindUnaryCallback_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _BaseZone_bindUnaryCallback_closure.prototype = $desc;\n  function _BaseZone_bindUnaryCallback_closure0(this_2, registered_3) {\n    this.this_2 = this_2;\n    this.registered_3 = registered_3;\n  }\n  _BaseZone_bindUnaryCallback_closure0.builtin$cls = \"_BaseZone_bindUnaryCallback_closure0\";\n  if (!\"name\" in _BaseZone_bindUnaryCallback_closure0)\n    _BaseZone_bindUnaryCallback_closure0.name = \"_BaseZone_bindUnaryCallback_closure0\";\n  $desc = $collectedClasses._BaseZone_bindUnaryCallback_closure0;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _BaseZone_bindUnaryCallback_closure0.prototype = $desc;\n  function _rootHandleUncaughtError_closure(error_0, stackTrace_1) {\n    this.error_0 = error_0;\n    this.stackTrace_1 = stackTrace_1;\n  }\n  _rootHandleUncaughtError_closure.builtin$cls = \"_rootHandleUncaughtError_closure\";\n  if (!\"name\" in _rootHandleUncaughtError_closure)\n    _rootHandleUncaughtError_closure.name = \"_rootHandleUncaughtError_closure\";\n  $desc = $collectedClasses._rootHandleUncaughtError_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _rootHandleUncaughtError_closure.prototype = $desc;\n  function _rootHandleUncaughtError__closure(error_2, stackTrace_3) {\n    this.error_2 = error_2;\n    this.stackTrace_3 = stackTrace_3;\n  }\n  _rootHandleUncaughtError__closure.builtin$cls = \"_rootHandleUncaughtError__closure\";\n  if (!\"name\" in _rootHandleUncaughtError__closure)\n    _rootHandleUncaughtError__closure.name = \"_rootHandleUncaughtError__closure\";\n  $desc = $collectedClasses._rootHandleUncaughtError__closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _rootHandleUncaughtError__closure.prototype = $desc;\n  function _RootZone() {\n  }\n  _RootZone.builtin$cls = \"_RootZone\";\n  if (!\"name\" in _RootZone)\n    _RootZone.name = \"_RootZone\";\n  $desc = $collectedClasses._RootZone;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _RootZone.prototype = $desc;\n  function _HashMap(_collection$_length, _strings, _nums, _rest, _keys) {\n    this._collection$_length = _collection$_length;\n    this._strings = _strings;\n    this._nums = _nums;\n    this._rest = _rest;\n    this._keys = _keys;\n  }\n  _HashMap.builtin$cls = \"_HashMap\";\n  if (!\"name\" in _HashMap)\n    _HashMap.name = \"_HashMap\";\n  $desc = $collectedClasses._HashMap;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _HashMap.prototype = $desc;\n  function _HashMap_values_closure(this_0) {\n    this.this_0 = this_0;\n  }\n  _HashMap_values_closure.builtin$cls = \"_HashMap_values_closure\";\n  if (!\"name\" in _HashMap_values_closure)\n    _HashMap_values_closure.name = \"_HashMap_values_closure\";\n  $desc = $collectedClasses._HashMap_values_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _HashMap_values_closure.prototype = $desc;\n  function HashMapKeyIterable(_map) {\n    this._map = _map;\n  }\n  HashMapKeyIterable.builtin$cls = \"HashMapKeyIterable\";\n  if (!\"name\" in HashMapKeyIterable)\n    HashMapKeyIterable.name = \"HashMapKeyIterable\";\n  $desc = $collectedClasses.HashMapKeyIterable;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  HashMapKeyIterable.prototype = $desc;\n  function HashMapKeyIterator(_map, _keys, _offset, _collection$_current) {\n    this._map = _map;\n    this._keys = _keys;\n    this._offset = _offset;\n    this._collection$_current = _collection$_current;\n  }\n  HashMapKeyIterator.builtin$cls = \"HashMapKeyIterator\";\n  if (!\"name\" in HashMapKeyIterator)\n    HashMapKeyIterator.name = \"HashMapKeyIterator\";\n  $desc = $collectedClasses.HashMapKeyIterator;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  HashMapKeyIterator.prototype = $desc;\n  function _LinkedHashMap(_collection$_length, _strings, _nums, _rest, _first, _last, _modifications) {\n    this._collection$_length = _collection$_length;\n    this._strings = _strings;\n    this._nums = _nums;\n    this._rest = _rest;\n    this._first = _first;\n    this._last = _last;\n    this._modifications = _modifications;\n  }\n  _LinkedHashMap.builtin$cls = \"_LinkedHashMap\";\n  if (!\"name\" in _LinkedHashMap)\n    _LinkedHashMap.name = \"_LinkedHashMap\";\n  $desc = $collectedClasses._LinkedHashMap;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _LinkedHashMap.prototype = $desc;\n  function _LinkedHashMap_values_closure(this_0) {\n    this.this_0 = this_0;\n  }\n  _LinkedHashMap_values_closure.builtin$cls = \"_LinkedHashMap_values_closure\";\n  if (!\"name\" in _LinkedHashMap_values_closure)\n    _LinkedHashMap_values_closure.name = \"_LinkedHashMap_values_closure\";\n  $desc = $collectedClasses._LinkedHashMap_values_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _LinkedHashMap_values_closure.prototype = $desc;\n  function LinkedHashMapCell(_key, _value, _next, _previous) {\n    this._key = _key;\n    this._value = _value;\n    this._next = _next;\n    this._previous = _previous;\n  }\n  LinkedHashMapCell.builtin$cls = \"LinkedHashMapCell\";\n  if (!\"name\" in LinkedHashMapCell)\n    LinkedHashMapCell.name = \"LinkedHashMapCell\";\n  $desc = $collectedClasses.LinkedHashMapCell;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  LinkedHashMapCell.prototype = $desc;\n  LinkedHashMapCell.prototype.get$_key = function() {\n    return this._key;\n  };\n  LinkedHashMapCell.prototype.get$_value = function() {\n    return this._value;\n  };\n  LinkedHashMapCell.prototype.set$_value = function(v) {\n    return this._value = v;\n  };\n  LinkedHashMapCell.prototype.get$_next = function() {\n    return this._next;\n  };\n  LinkedHashMapCell.prototype.set$_next = function(v) {\n    return this._next = v;\n  };\n  LinkedHashMapCell.prototype.get$_previous = function() {\n    return this._previous;\n  };\n  LinkedHashMapCell.prototype.set$_previous = function(v) {\n    return this._previous = v;\n  };\n  function LinkedHashMapKeyIterable(_map) {\n    this._map = _map;\n  }\n  LinkedHashMapKeyIterable.builtin$cls = \"LinkedHashMapKeyIterable\";\n  if (!\"name\" in LinkedHashMapKeyIterable)\n    LinkedHashMapKeyIterable.name = \"LinkedHashMapKeyIterable\";\n  $desc = $collectedClasses.LinkedHashMapKeyIterable;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  LinkedHashMapKeyIterable.prototype = $desc;\n  function LinkedHashMapKeyIterator(_map, _modifications, _cell, _collection$_current) {\n    this._map = _map;\n    this._modifications = _modifications;\n    this._cell = _cell;\n    this._collection$_current = _collection$_current;\n  }\n  LinkedHashMapKeyIterator.builtin$cls = \"LinkedHashMapKeyIterator\";\n  if (!\"name\" in LinkedHashMapKeyIterator)\n    LinkedHashMapKeyIterator.name = \"LinkedHashMapKeyIterator\";\n  $desc = $collectedClasses.LinkedHashMapKeyIterator;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  LinkedHashMapKeyIterator.prototype = $desc;\n  function _HashSet() {\n  }\n  _HashSet.builtin$cls = \"_HashSet\";\n  if (!\"name\" in _HashSet)\n    _HashSet.name = \"_HashSet\";\n  $desc = $collectedClasses._HashSet;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _HashSet.prototype = $desc;\n  function _IdentityHashSet(_collection$_length, _strings, _nums, _rest, _elements) {\n    this._collection$_length = _collection$_length;\n    this._strings = _strings;\n    this._nums = _nums;\n    this._rest = _rest;\n    this._elements = _elements;\n  }\n  _IdentityHashSet.builtin$cls = \"_IdentityHashSet\";\n  if (!\"name\" in _IdentityHashSet)\n    _IdentityHashSet.name = \"_IdentityHashSet\";\n  $desc = $collectedClasses._IdentityHashSet;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _IdentityHashSet.prototype = $desc;\n  function HashSetIterator(_set, _elements, _offset, _collection$_current) {\n    this._set = _set;\n    this._elements = _elements;\n    this._offset = _offset;\n    this._collection$_current = _collection$_current;\n  }\n  HashSetIterator.builtin$cls = \"HashSetIterator\";\n  if (!\"name\" in HashSetIterator)\n    HashSetIterator.name = \"HashSetIterator\";\n  $desc = $collectedClasses.HashSetIterator;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  HashSetIterator.prototype = $desc;\n  function _LinkedHashSet(_collection$_length, _strings, _nums, _rest, _first, _last, _modifications) {\n    this._collection$_length = _collection$_length;\n    this._strings = _strings;\n    this._nums = _nums;\n    this._rest = _rest;\n    this._first = _first;\n    this._last = _last;\n    this._modifications = _modifications;\n  }\n  _LinkedHashSet.builtin$cls = \"_LinkedHashSet\";\n  if (!\"name\" in _LinkedHashSet)\n    _LinkedHashSet.name = \"_LinkedHashSet\";\n  $desc = $collectedClasses._LinkedHashSet;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _LinkedHashSet.prototype = $desc;\n  function LinkedHashSetCell(_element, _next, _previous) {\n    this._element = _element;\n    this._next = _next;\n    this._previous = _previous;\n  }\n  LinkedHashSetCell.builtin$cls = \"LinkedHashSetCell\";\n  if (!\"name\" in LinkedHashSetCell)\n    LinkedHashSetCell.name = \"LinkedHashSetCell\";\n  $desc = $collectedClasses.LinkedHashSetCell;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  LinkedHashSetCell.prototype = $desc;\n  LinkedHashSetCell.prototype.get$_element = function() {\n    return this._element;\n  };\n  LinkedHashSetCell.prototype.get$_next = function() {\n    return this._next;\n  };\n  LinkedHashSetCell.prototype.set$_next = function(v) {\n    return this._next = v;\n  };\n  LinkedHashSetCell.prototype.get$_previous = function() {\n    return this._previous;\n  };\n  LinkedHashSetCell.prototype.set$_previous = function(v) {\n    return this._previous = v;\n  };\n  function LinkedHashSetIterator(_set, _modifications, _cell, _collection$_current) {\n    this._set = _set;\n    this._modifications = _modifications;\n    this._cell = _cell;\n    this._collection$_current = _collection$_current;\n  }\n  LinkedHashSetIterator.builtin$cls = \"LinkedHashSetIterator\";\n  if (!\"name\" in LinkedHashSetIterator)\n    LinkedHashSetIterator.name = \"LinkedHashSetIterator\";\n  $desc = $collectedClasses.LinkedHashSetIterator;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  LinkedHashSetIterator.prototype = $desc;\n  function _HashSetBase() {\n  }\n  _HashSetBase.builtin$cls = \"_HashSetBase\";\n  if (!\"name\" in _HashSetBase)\n    _HashSetBase.name = \"_HashSetBase\";\n  $desc = $collectedClasses._HashSetBase;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _HashSetBase.prototype = $desc;\n  function IterableBase() {\n  }\n  IterableBase.builtin$cls = \"IterableBase\";\n  if (!\"name\" in IterableBase)\n    IterableBase.name = \"IterableBase\";\n  $desc = $collectedClasses.IterableBase;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  IterableBase.prototype = $desc;\n  function ListMixin() {\n  }\n  ListMixin.builtin$cls = \"ListMixin\";\n  if (!\"name\" in ListMixin)\n    ListMixin.name = \"ListMixin\";\n  $desc = $collectedClasses.ListMixin;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ListMixin.prototype = $desc;\n  function Maps_mapToString_closure(box_0, result_1) {\n    this.box_0 = box_0;\n    this.result_1 = result_1;\n  }\n  Maps_mapToString_closure.builtin$cls = \"Maps_mapToString_closure\";\n  if (!\"name\" in Maps_mapToString_closure)\n    Maps_mapToString_closure.name = \"Maps_mapToString_closure\";\n  $desc = $collectedClasses.Maps_mapToString_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Maps_mapToString_closure.prototype = $desc;\n  function ListQueue(_table, _head, _tail, _modificationCount) {\n    this._table = _table;\n    this._head = _head;\n    this._tail = _tail;\n    this._modificationCount = _modificationCount;\n  }\n  ListQueue.builtin$cls = \"ListQueue\";\n  if (!\"name\" in ListQueue)\n    ListQueue.name = \"ListQueue\";\n  $desc = $collectedClasses.ListQueue;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ListQueue.prototype = $desc;\n  function _ListQueueIterator(_queue, _end, _modificationCount, _collection$_position, _collection$_current) {\n    this._queue = _queue;\n    this._end = _end;\n    this._modificationCount = _modificationCount;\n    this._collection$_position = _collection$_position;\n    this._collection$_current = _collection$_current;\n  }\n  _ListQueueIterator.builtin$cls = \"_ListQueueIterator\";\n  if (!\"name\" in _ListQueueIterator)\n    _ListQueueIterator.name = \"_ListQueueIterator\";\n  $desc = $collectedClasses._ListQueueIterator;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _ListQueueIterator.prototype = $desc;\n  function NoSuchMethodError_toString_closure(box_0) {\n    this.box_0 = box_0;\n  }\n  NoSuchMethodError_toString_closure.builtin$cls = \"NoSuchMethodError_toString_closure\";\n  if (!\"name\" in NoSuchMethodError_toString_closure)\n    NoSuchMethodError_toString_closure.name = \"NoSuchMethodError_toString_closure\";\n  $desc = $collectedClasses.NoSuchMethodError_toString_closure;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  NoSuchMethodError_toString_closure.prototype = $desc;\n  function DateTime(millisecondsSinceEpoch, isUtc) {\n    this.millisecondsSinceEpoch = millisecondsSinceEpoch;\n    this.isUtc = isUtc;\n  }\n  DateTime.builtin$cls = \"DateTime\";\n  if (!\"name\" in DateTime)\n    DateTime.name = \"DateTime\";\n  $desc = $collectedClasses.DateTime;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DateTime.prototype = $desc;\n  function DateTime_toString_fourDigits() {\n  }\n  DateTime_toString_fourDigits.builtin$cls = \"DateTime_toString_fourDigits\";\n  if (!\"name\" in DateTime_toString_fourDigits)\n    DateTime_toString_fourDigits.name = \"DateTime_toString_fourDigits\";\n  $desc = $collectedClasses.DateTime_toString_fourDigits;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DateTime_toString_fourDigits.prototype = $desc;\n  function DateTime_toString_threeDigits() {\n  }\n  DateTime_toString_threeDigits.builtin$cls = \"DateTime_toString_threeDigits\";\n  if (!\"name\" in DateTime_toString_threeDigits)\n    DateTime_toString_threeDigits.name = \"DateTime_toString_threeDigits\";\n  $desc = $collectedClasses.DateTime_toString_threeDigits;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DateTime_toString_threeDigits.prototype = $desc;\n  function DateTime_toString_twoDigits() {\n  }\n  DateTime_toString_twoDigits.builtin$cls = \"DateTime_toString_twoDigits\";\n  if (!\"name\" in DateTime_toString_twoDigits)\n    DateTime_toString_twoDigits.name = \"DateTime_toString_twoDigits\";\n  $desc = $collectedClasses.DateTime_toString_twoDigits;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  DateTime_toString_twoDigits.prototype = $desc;\n  function Duration(_duration) {\n    this._duration = _duration;\n  }\n  Duration.builtin$cls = \"Duration\";\n  if (!\"name\" in Duration)\n    Duration.name = \"Duration\";\n  $desc = $collectedClasses.Duration;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Duration.prototype = $desc;\n  Duration.prototype.get$_duration = function() {\n    return this._duration;\n  };\n  function Duration_toString_sixDigits() {\n  }\n  Duration_toString_sixDigits.builtin$cls = \"Duration_toString_sixDigits\";\n  if (!\"name\" in Duration_toString_sixDigits)\n    Duration_toString_sixDigits.name = \"Duration_toString_sixDigits\";\n  $desc = $collectedClasses.Duration_toString_sixDigits;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Duration_toString_sixDigits.prototype = $desc;\n  function Duration_toString_twoDigits() {\n  }\n  Duration_toString_twoDigits.builtin$cls = \"Duration_toString_twoDigits\";\n  if (!\"name\" in Duration_toString_twoDigits)\n    Duration_toString_twoDigits.name = \"Duration_toString_twoDigits\";\n  $desc = $collectedClasses.Duration_toString_twoDigits;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Duration_toString_twoDigits.prototype = $desc;\n  function Error() {\n  }\n  Error.builtin$cls = \"Error\";\n  if (!\"name\" in Error)\n    Error.name = \"Error\";\n  $desc = $collectedClasses.Error;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Error.prototype = $desc;\n  function NullThrownError() {\n  }\n  NullThrownError.builtin$cls = \"NullThrownError\";\n  if (!\"name\" in NullThrownError)\n    NullThrownError.name = \"NullThrownError\";\n  $desc = $collectedClasses.NullThrownError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  NullThrownError.prototype = $desc;\n  function ArgumentError(message) {\n    this.message = message;\n  }\n  ArgumentError.builtin$cls = \"ArgumentError\";\n  if (!\"name\" in ArgumentError)\n    ArgumentError.name = \"ArgumentError\";\n  $desc = $collectedClasses.ArgumentError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ArgumentError.prototype = $desc;\n  function RangeError(message) {\n    this.message = message;\n  }\n  RangeError.builtin$cls = \"RangeError\";\n  if (!\"name\" in RangeError)\n    RangeError.name = \"RangeError\";\n  $desc = $collectedClasses.RangeError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  RangeError.prototype = $desc;\n  function UnsupportedError(message) {\n    this.message = message;\n  }\n  UnsupportedError.builtin$cls = \"UnsupportedError\";\n  if (!\"name\" in UnsupportedError)\n    UnsupportedError.name = \"UnsupportedError\";\n  $desc = $collectedClasses.UnsupportedError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  UnsupportedError.prototype = $desc;\n  function UnimplementedError(message) {\n    this.message = message;\n  }\n  UnimplementedError.builtin$cls = \"UnimplementedError\";\n  if (!\"name\" in UnimplementedError)\n    UnimplementedError.name = \"UnimplementedError\";\n  $desc = $collectedClasses.UnimplementedError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  UnimplementedError.prototype = $desc;\n  function StateError(message) {\n    this.message = message;\n  }\n  StateError.builtin$cls = \"StateError\";\n  if (!\"name\" in StateError)\n    StateError.name = \"StateError\";\n  $desc = $collectedClasses.StateError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  StateError.prototype = $desc;\n  function ConcurrentModificationError(modifiedObject) {\n    this.modifiedObject = modifiedObject;\n  }\n  ConcurrentModificationError.builtin$cls = \"ConcurrentModificationError\";\n  if (!\"name\" in ConcurrentModificationError)\n    ConcurrentModificationError.name = \"ConcurrentModificationError\";\n  $desc = $collectedClasses.ConcurrentModificationError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ConcurrentModificationError.prototype = $desc;\n  function StackOverflowError() {\n  }\n  StackOverflowError.builtin$cls = \"StackOverflowError\";\n  if (!\"name\" in StackOverflowError)\n    StackOverflowError.name = \"StackOverflowError\";\n  $desc = $collectedClasses.StackOverflowError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  StackOverflowError.prototype = $desc;\n  function CyclicInitializationError(variableName) {\n    this.variableName = variableName;\n  }\n  CyclicInitializationError.builtin$cls = \"CyclicInitializationError\";\n  if (!\"name\" in CyclicInitializationError)\n    CyclicInitializationError.name = \"CyclicInitializationError\";\n  $desc = $collectedClasses.CyclicInitializationError;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  CyclicInitializationError.prototype = $desc;\n  function _ExceptionImplementation(message) {\n    this.message = message;\n  }\n  _ExceptionImplementation.builtin$cls = \"_ExceptionImplementation\";\n  if (!\"name\" in _ExceptionImplementation)\n    _ExceptionImplementation.name = \"_ExceptionImplementation\";\n  $desc = $collectedClasses._ExceptionImplementation;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _ExceptionImplementation.prototype = $desc;\n  function Expando(name) {\n    this.name = name;\n  }\n  Expando.builtin$cls = \"Expando\";\n  if (!\"name\" in Expando)\n    Expando.name = \"Expando\";\n  $desc = $collectedClasses.Expando;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Expando.prototype = $desc;\n  function Iterator() {\n  }\n  Iterator.builtin$cls = \"Iterator\";\n  if (!\"name\" in Iterator)\n    Iterator.name = \"Iterator\";\n  $desc = $collectedClasses.Iterator;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Iterator.prototype = $desc;\n  function Null() {\n  }\n  Null.builtin$cls = \"Null\";\n  if (!\"name\" in Null)\n    Null.name = \"Null\";\n  $desc = $collectedClasses.Null;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Null.prototype = $desc;\n  function Object() {\n  }\n  Object.builtin$cls = \"Object\";\n  if (!\"name\" in Object)\n    Object.name = \"Object\";\n  $desc = $collectedClasses.Object;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Object.prototype = $desc;\n  function StackTrace() {\n  }\n  StackTrace.builtin$cls = \"StackTrace\";\n  if (!\"name\" in StackTrace)\n    StackTrace.name = \"StackTrace\";\n  $desc = $collectedClasses.StackTrace;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  StackTrace.prototype = $desc;\n  function StringBuffer(_contents) {\n    this._contents = _contents;\n  }\n  StringBuffer.builtin$cls = \"StringBuffer\";\n  if (!\"name\" in StringBuffer)\n    StringBuffer.name = \"StringBuffer\";\n  $desc = $collectedClasses.StringBuffer;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  StringBuffer.prototype = $desc;\n  StringBuffer.prototype.get$_contents = function() {\n    return this._contents;\n  };\n  function Symbol() {\n  }\n  Symbol.builtin$cls = \"Symbol\";\n  if (!\"name\" in Symbol)\n    Symbol.name = \"Symbol\";\n  $desc = $collectedClasses.Symbol;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Symbol.prototype = $desc;\n  function Interceptor_CssStyleDeclarationBase() {\n  }\n  Interceptor_CssStyleDeclarationBase.builtin$cls = \"Interceptor_CssStyleDeclarationBase\";\n  if (!\"name\" in Interceptor_CssStyleDeclarationBase)\n    Interceptor_CssStyleDeclarationBase.name = \"Interceptor_CssStyleDeclarationBase\";\n  $desc = $collectedClasses.Interceptor_CssStyleDeclarationBase;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Interceptor_CssStyleDeclarationBase.prototype = $desc;\n  function CssStyleDeclarationBase() {\n  }\n  CssStyleDeclarationBase.builtin$cls = \"CssStyleDeclarationBase\";\n  if (!\"name\" in CssStyleDeclarationBase)\n    CssStyleDeclarationBase.name = \"CssStyleDeclarationBase\";\n  $desc = $collectedClasses.CssStyleDeclarationBase;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  CssStyleDeclarationBase.prototype = $desc;\n  function Interceptor_ListMixin() {\n  }\n  Interceptor_ListMixin.builtin$cls = \"Interceptor_ListMixin\";\n  if (!\"name\" in Interceptor_ListMixin)\n    Interceptor_ListMixin.name = \"Interceptor_ListMixin\";\n  $desc = $collectedClasses.Interceptor_ListMixin;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Interceptor_ListMixin.prototype = $desc;\n  function Interceptor_ListMixin_ImmutableListMixin() {\n  }\n  Interceptor_ListMixin_ImmutableListMixin.builtin$cls = \"Interceptor_ListMixin_ImmutableListMixin\";\n  if (!\"name\" in Interceptor_ListMixin_ImmutableListMixin)\n    Interceptor_ListMixin_ImmutableListMixin.name = \"Interceptor_ListMixin_ImmutableListMixin\";\n  $desc = $collectedClasses.Interceptor_ListMixin_ImmutableListMixin;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  Interceptor_ListMixin_ImmutableListMixin.prototype = $desc;\n  function ImmutableListMixin() {\n  }\n  ImmutableListMixin.builtin$cls = \"ImmutableListMixin\";\n  if (!\"name\" in ImmutableListMixin)\n    ImmutableListMixin.name = \"ImmutableListMixin\";\n  $desc = $collectedClasses.ImmutableListMixin;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  ImmutableListMixin.prototype = $desc;\n  function FixedSizeListIterator(_array, _length, _position, _current) {\n    this._array = _array;\n    this._length = _length;\n    this._position = _position;\n    this._current = _current;\n  }\n  FixedSizeListIterator.builtin$cls = \"FixedSizeListIterator\";\n  if (!\"name\" in FixedSizeListIterator)\n    FixedSizeListIterator.name = \"FixedSizeListIterator\";\n  $desc = $collectedClasses.FixedSizeListIterator;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  FixedSizeListIterator.prototype = $desc;\n  function _JSRandom() {\n  }\n  _JSRandom.builtin$cls = \"_JSRandom\";\n  if (!\"name\" in _JSRandom)\n    _JSRandom.name = \"_JSRandom\";\n  $desc = $collectedClasses._JSRandom;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _JSRandom.prototype = $desc;\n  function _NativeTypedArray() {\n  }\n  _NativeTypedArray.builtin$cls = \"_NativeTypedArray\";\n  if (!\"name\" in _NativeTypedArray)\n    _NativeTypedArray.name = \"_NativeTypedArray\";\n  $desc = $collectedClasses._NativeTypedArray;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _NativeTypedArray.prototype = $desc;\n  function _NativeTypedArrayOfInt() {\n  }\n  _NativeTypedArrayOfInt.builtin$cls = \"_NativeTypedArrayOfInt\";\n  if (!\"name\" in _NativeTypedArrayOfInt)\n    _NativeTypedArrayOfInt.name = \"_NativeTypedArrayOfInt\";\n  $desc = $collectedClasses._NativeTypedArrayOfInt;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _NativeTypedArrayOfInt.prototype = $desc;\n  function _NativeTypedArray_ListMixin() {\n  }\n  _NativeTypedArray_ListMixin.builtin$cls = \"_NativeTypedArray_ListMixin\";\n  if (!\"name\" in _NativeTypedArray_ListMixin)\n    _NativeTypedArray_ListMixin.name = \"_NativeTypedArray_ListMixin\";\n  $desc = $collectedClasses._NativeTypedArray_ListMixin;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _NativeTypedArray_ListMixin.prototype = $desc;\n  function _NativeTypedArray_ListMixin_FixedLengthListMixin() {\n  }\n  _NativeTypedArray_ListMixin_FixedLengthListMixin.builtin$cls = \"_NativeTypedArray_ListMixin_FixedLengthListMixin\";\n  if (!\"name\" in _NativeTypedArray_ListMixin_FixedLengthListMixin)\n    _NativeTypedArray_ListMixin_FixedLengthListMixin.name = \"_NativeTypedArray_ListMixin_FixedLengthListMixin\";\n  $desc = $collectedClasses._NativeTypedArray_ListMixin_FixedLengthListMixin;\n  if ($desc instanceof Array)\n    $desc = $desc[1];\n  _NativeTypedArray_ListMixin_FixedLengthListMixin.prototype = $desc;\n  return [HtmlElement, AnchorElement, AnimationEvent, AreaElement, AudioElement, AutocompleteErrorEvent, BRElement, BaseElement, BeforeLoadEvent, BeforeUnloadEvent, BodyElement, ButtonElement, CDataSection, CanvasElement, CharacterData, CloseEvent, Comment, CompositionEvent, ContentElement, CssFontFaceLoadEvent, CssStyleDeclaration, CustomEvent, DListElement, DataListElement, DetailsElement, DeviceMotionEvent, DeviceOrientationEvent, DialogElement, DivElement, Document, DocumentFragment, DocumentType, DomError, DomException, Element, EmbedElement, ErrorEvent, Event, EventTarget, FieldSetElement, FileError, FocusEvent, FormElement, HRElement, HashChangeEvent, HeadElement, HeadingElement, HtmlDocument, HtmlHtmlElement, IFrameElement, ImageElement, InputElement, KeyboardEvent, KeygenElement, LIElement, LabelElement, LegendElement, LinkElement, MapElement, MediaElement, MediaError, MediaKeyError, MediaKeyEvent, MediaKeyMessageEvent, MediaKeyNeededEvent, MediaStream, MediaStreamEvent, MediaStreamTrackEvent, MenuElement, MessageEvent, MetaElement, MeterElement, MidiConnectionEvent, MidiMessageEvent, ModElement, MouseEvent, Navigator, NavigatorUserMediaError, Node, NodeList, OListElement, ObjectElement, OptGroupElement, OptionElement, OutputElement, OverflowEvent, PageTransitionEvent, ParagraphElement, ParamElement, PopStateEvent, PositionError, PreElement, ProcessingInstruction, ProgressElement, ProgressEvent, QuoteElement, ResourceProgressEvent, RtcDataChannelEvent, RtcDtmfToneChangeEvent, RtcIceCandidateEvent, ScriptElement, SecurityPolicyViolationEvent, SelectElement, ShadowElement, ShadowRoot, SourceElement, SpanElement, SpeechInputEvent, SpeechRecognitionError, SpeechRecognitionEvent, SpeechSynthesisEvent, StorageEvent, StyleElement, TableCaptionElement, TableCellElement, TableColElement, TableElement, TableRowElement, TableSectionElement, TemplateElement, Text, TextAreaElement, TextEvent, TitleElement, TouchEvent, TrackElement, TrackEvent, TransitionEvent, UIEvent, UListElement, UnknownElement, VideoElement, WheelEvent, Window, _Attr, _ClientRect, _Entity, _HTMLAppletElement, _HTMLBaseFontElement, _HTMLDirectoryElement, _HTMLFontElement, _HTMLFrameElement, _HTMLFrameSetElement, _HTMLMarqueeElement, _MutationEvent, _Notation, _XMLHttpRequestProgressEvent, VersionChangeEvent, AElement, AltGlyphElement, AnimateElement, AnimateMotionElement, AnimateTransformElement, AnimatedLength, AnimatedLengthList, AnimatedNumber, AnimatedNumberList, AnimationElement, CircleElement, ClipPathElement, DefsElement, DescElement, EllipseElement, FEBlendElement, FEColorMatrixElement, FEComponentTransferElement, FECompositeElement, FEConvolveMatrixElement, FEDiffuseLightingElement, FEDisplacementMapElement, FEDistantLightElement, FEFloodElement, FEFuncAElement, FEFuncBElement, FEFuncGElement, FEFuncRElement, FEGaussianBlurElement, FEImageElement, FEMergeElement, FEMergeNodeElement, FEMorphologyElement, FEOffsetElement, FEPointLightElement, FESpecularLightingElement, FESpotLightElement, FETileElement, FETurbulenceElement, FilterElement, ForeignObjectElement, GElement, GraphicsElement, ImageElement0, LineElement, LinearGradientElement, MarkerElement, MaskElement, MetadataElement, PathElement, PatternElement, PolygonElement, PolylineElement, RadialGradientElement, RectElement, ScriptElement0, SetElement, StopElement, StyleElement0, SvgDocument, SvgElement, SvgSvgElement, SwitchElement, SymbolElement, TSpanElement, TextContentElement, TextElement, TextPathElement, TextPositioningElement, TitleElement0, UseElement, ViewElement, ZoomEvent, _GradientElement, _SVGAltGlyphDefElement, _SVGAltGlyphItemElement, _SVGAnimateColorElement, _SVGComponentTransferFunctionElement, _SVGCursorElement, _SVGFEDropShadowElement, _SVGFontElement, _SVGFontFaceElement, _SVGFontFaceFormatElement, _SVGFontFaceNameElement, _SVGFontFaceSrcElement, _SVGFontFaceUriElement, _SVGGlyphElement, _SVGGlyphRefElement, _SVGHKernElement, _SVGMPathElement, _SVGMissingGlyphElement, _SVGVKernElement, AudioProcessingEvent, OfflineAudioCompletionEvent, ContextEvent, SqlError, TypedData, Uint8List, JS_CONST, Interceptor, JSBool, JSNull, JavaScriptObject, PlainJavaScriptObject, UnknownJavaScriptObject, JSArray, JSNumber, JSInt, JSDouble, JSString, startRootIsolate_closure, startRootIsolate_closure0, _Manager, _IsolateContext, _EventLoop, _EventLoop__runHelper_next, _IsolateEvent, _MainManagerStub, IsolateNatives__processWorkerMessage_closure, _BaseSendPort, _NativeJsSendPort, _NativeJsSendPort_send_closure, _WorkerSendPort, RawReceivePortImpl, ReceivePortImpl, _JsSerializer, _JsCopier, _JsDeserializer, _JsVisitedMap, _MessageTraverserVisitedMap, _MessageTraverser, _Copier, _Copier_visitMap_closure, _Serializer, _Deserializer, TimerImpl, TimerImpl_internalCallback, TimerImpl_internalCallback0, ReflectionInfo, TypeErrorDecoder, NullError, JsNoSuchMethodError, UnknownJsTypeError, unwrapException_saveStackTrace, _StackTrace, invokeClosure_closure, invokeClosure_closure0, invokeClosure_closure1, invokeClosure_closure2, invokeClosure_closure3, Closure, TearOffClosure, BoundClosure, RuntimeError, RuntimeType, RuntimeFunctionType, DynamicRuntimeType, TypeImpl, initHooks_closure, initHooks_closure0, initHooks_closure1, Balls, Balls_tick_closure, Balls_collideBalls_closure, Balls_collideBalls__closure, Ball, CountDownClock, ClockNumber, ClockNumber_setPixels_closure, Colon, ListIterator, MappedIterable, EfficientLengthMappedIterable, MappedIterator, FixedLengthListMixin, _AsyncError, Future, _Future, _Future__addListener_closure, _Future__chainFutures_closure, _Future__chainFutures_closure0, _Future__asyncComplete_closure, _Future__propagateToListeners_closure, _Future__propagateToListeners_closure0, _Future__propagateToListeners__closure, _Future__propagateToListeners__closure0, Stream, Stream_forEach_closure, Stream_forEach__closure, Stream_forEach__closure0, Stream_forEach_closure0, Stream_length_closure, Stream_length_closure0, StreamSubscription, _StreamController, _StreamController__subscribe_closure, _StreamController__recordCancel_complete, _SyncStreamControllerDispatch, _AsyncStreamControllerDispatch, _AsyncStreamController, _StreamController__AsyncStreamControllerDispatch, _SyncStreamController, _StreamController__SyncStreamControllerDispatch, _ControllerStream, _ControllerSubscription, _EventSink, _BufferingStreamSubscription, _BufferingStreamSubscription__sendDone_sendDone, _StreamImpl, _DelayedEvent, _DelayedData, _DelayedDone, _PendingEvents, _PendingEvents_schedule_closure, _StreamImplEvents, _cancelAndError_closure, _cancelAndErrorClosure_closure, _BaseZone, _BaseZone_bindCallback_closure, _BaseZone_bindCallback_closure0, _BaseZone_bindUnaryCallback_closure, _BaseZone_bindUnaryCallback_closure0, _rootHandleUncaughtError_closure, _rootHandleUncaughtError__closure, _RootZone, _HashMap, _HashMap_values_closure, HashMapKeyIterable, HashMapKeyIterator, _LinkedHashMap, _LinkedHashMap_values_closure, LinkedHashMapCell, LinkedHashMapKeyIterable, LinkedHashMapKeyIterator, _HashSet, _IdentityHashSet, HashSetIterator, _LinkedHashSet, LinkedHashSetCell, LinkedHashSetIterator, _HashSetBase, IterableBase, ListMixin, Maps_mapToString_closure, ListQueue, _ListQueueIterator, NoSuchMethodError_toString_closure, DateTime, DateTime_toString_fourDigits, DateTime_toString_threeDigits, DateTime_toString_twoDigits, Duration, Duration_toString_sixDigits, Duration_toString_twoDigits, Error, NullThrownError, ArgumentError, RangeError, UnsupportedError, UnimplementedError, StateError, ConcurrentModificationError, StackOverflowError, CyclicInitializationError, _ExceptionImplementation, Expando, Iterator, Null, Object, StackTrace, StringBuffer, Symbol, Interceptor_CssStyleDeclarationBase, CssStyleDeclarationBase, Interceptor_ListMixin, Interceptor_ListMixin_ImmutableListMixin, ImmutableListMixin, FixedSizeListIterator, _JSRandom, _NativeTypedArray, _NativeTypedArrayOfInt, _NativeTypedArray_ListMixin, _NativeTypedArray_ListMixin_FixedLengthListMixin];\n}\n"
  },
  {
    "path": "_archive/apps/samples/dart/dart/numbers.dart",
    "content": "// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file\n// for details. All rights reserved. Use of this source code is governed by a\n// BSD-style license that can be found in the LICENSE file.\n\npart of clock;\n\nclass ClockNumber {\n  static const int WIDTH = 4;\n  static const int HEIGHT = 7;\n\n  CountDownClock app;\n  Element root;\n  List<List<ImageElement>> imgs;\n  List<List<int>> pixels;\n  int ballColor;\n\n  ClockNumber(this.app, double pos, this.ballColor) {\n    imgs = new List<List<ImageElement>>(HEIGHT);\n\n    root = new DivElement();\n    makeAbsolute(root);\n    setElementPosition(root, pos, 0.0);\n\n    for (int y = 0; y < HEIGHT; ++y) {\n      imgs[y] = new List<ImageElement>(WIDTH);\n    }\n\n    for (int y = 0; y < HEIGHT; ++y) {\n      for (int x = 0; x < WIDTH; ++x) {\n        imgs[y][x] = new ImageElement();\n        root.nodes.add(imgs[y][x]);\n        makeAbsolute(imgs[y][x]);\n        setElementPosition(imgs[y][x],\n            x * CountDownClock.BALL_WIDTH, y * CountDownClock.BALL_HEIGHT);\n      }\n    }\n  }\n\n  void setPixels(List<List<int>> px) {\n    for (int y = 0; y < HEIGHT; ++y) {\n      for (int x = 0; x < WIDTH; ++x) {\n        ImageElement img = imgs[y][x];\n\n        if (pixels != null) {\n          if ((pixels[y][x] != 0) && (px[y][x] == 0)) {\n            scheduleMicrotask(() {\n              var r = img.getBoundingClientRect();\n              double absx = r.left;\n              double absy = r.top;\n\n              app.balls.add(absx, absy, ballColor);\n            });\n          }\n        }\n\n        img.src = px[y][x] != 0 ? Balls.PNGS[ballColor] : Balls.PNGS[6];\n      }\n    }\n\n    pixels = px;\n  }\n}\n\nclass Colon {\n  Element root;\n\n  Colon(double xpos, double ypos) {\n    root = new DivElement();\n    makeAbsolute(root);\n    setElementPosition(root, xpos, ypos);\n\n    ImageElement dot = new ImageElement(src: Balls.PNGS[Balls.DK_GRAY_BALL_INDEX]);\n    root.nodes.add(dot);\n    makeAbsolute(dot);\n    setElementPosition(dot, 0.0, 2.0 * CountDownClock.BALL_HEIGHT);\n\n    dot = new ImageElement(src: Balls.PNGS[Balls.DK_GRAY_BALL_INDEX]);\n    root.nodes.add(dot);\n    makeAbsolute(dot);\n    setElementPosition(dot, 0.0, 4.0 * CountDownClock.BALL_HEIGHT);\n  }\n}\n\nclass ClockNumbers {\n  static const PIXELS = const [\n     const [\n       const[ 1, 1, 1, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 1, 1, 1 ]\n    ], const [\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ]\n    ], const [\n       const[ 1, 1, 1, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 1, 1, 1, 1 ],\n       const[ 1, 0, 0, 0 ],\n       const[ 1, 0, 0, 0 ],\n       const[ 1, 1, 1, 1 ]\n    ], const [\n       const[ 1, 1, 1, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 1, 1, 1, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 1, 1, 1, 1 ]\n    ], const [\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 1, 1, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ]\n    ], const [\n       const[ 1, 1, 1, 1 ],\n       const[ 1, 0, 0, 0 ],\n       const[ 1, 0, 0, 0 ],\n       const[ 1, 1, 1, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 1, 1, 1, 1 ]\n    ], const [\n       const[ 1, 1, 1, 1 ],\n       const[ 1, 0, 0, 0 ],\n       const[ 1, 0, 0, 0 ],\n       const[ 1, 1, 1, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 1, 1, 1 ]\n    ], const [\n       const[ 1, 1, 1, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ]\n    ], const [\n       const[ 1, 1, 1, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 1, 1, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 1, 1, 1 ]\n    ], const [\n       const[ 1, 1, 1, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 0, 0, 1 ],\n       const[ 1, 1, 1, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 0, 0, 0, 1 ],\n       const[ 1, 1, 1, 1 ]\n    ]\n  ];\n}\n"
  },
  {
    "path": "_archive/apps/samples/dart/js/browser_dart_csp_safe.js",
    "content": "// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file\n// for details. All rights reserved. Use of this source code is governed by a\n// BSD-style license that can be found in the LICENSE file.\n\n(function() {\n// Bootstrap support for Dart scripts on the page as this script.\nif (navigator.userAgent.indexOf('(Dart)') === -1) {\n  // TODO:\n  // - Support in-browser compilation.\n  // - Handle inline Dart scripts.\n\n  // Use \"precompiled\" version, which is CSP safe. Required for packaged apps.\n  var jsSuffix = '.dart.precompiled.js';\n\n  // Fall back to compiled JS. Run through all the scripts and\n  // replace them if they have a type that indicate that they source\n  // in Dart code (type=\"application/dart\").\n  var scripts = document.getElementsByTagName(\"script\");\n  var length = scripts.length;\n\n  for (var i = 0; i < length; ++i) {\n    if (scripts[i].type == \"application/dart\") {\n      // Remap foo.dart to foo.dart.js.\n      if (scripts[i].src && scripts[i].src != '') {\n        var script = document.createElement('script');\n        script.src = scripts[i].src.replace(/\\.dart(?=\\?|$)/, jsSuffix);\n        var parent = scripts[i].parentNode;\n        // TODO(vsm): Find a solution for issue 8455 that works with more\n        // than one script.\n        document.currentScript = script;\n        parent.replaceChild(script, scripts[i]);\n      }\n    }\n  }\n}\n})();\n"
  },
  {
    "path": "_archive/apps/samples/dart/js/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('clock.html',\n    {id: 'clock', innerBounds: {width: 800, height: 550}});\n});\n"
  },
  {
    "path": "_archive/apps/samples/dart/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Hello Dart! Sample\",\n  \"version\": \"2\",\n  \"minimum_chrome_version\": \"23\",\n  \"icons\": {\"128\": \"images/dart_icon.png\"},\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"js/main.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/dart/pubspec.yaml",
    "content": "name: dart-clock-packaged-app-sample\n\ndependencies:\n  browser: any\n"
  },
  {
    "path": "_archive/apps/samples/dart/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"dart\",\n  \"files_with_snippets\": [ ],\n  \"ios\": {\"works\": true, \"comments\": \"Visual issues caused by fixed-size layout\"}\n}\n"
  },
  {
    "path": "_archive/apps/samples/desktop-capture/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/mhkidniocjdaiddjckopkigjmjbadfji\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Desktop Capture\n\nShows how to grab a desktop capture feed using getUserMedia. Requires\nthe appropriate permissions (`desktopCapture`) to be set in the manifest file.\n\n## APIs\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n* [desktopCapture](https://developer.chrome.com/apps/desktopCapture)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/desktop-capture/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/desktop-capture/app.js",
    "content": "/*\nCopyright 2014 Intel Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Dongseong Hwang (dongseong.hwang@intel.com)\n*/\n\n/**\n * Grabs the desktop capture feed from the browser, requesting\n * desktop capture. Requires the permissions\n * for desktop capture to be set in the manifest.\n *\n * @see https://developer.chrome.com/apps/desktopCapture\n */\nvar desktop_sharing = false;\nvar local_stream = null;\nfunction toggle() {\n    if (!desktop_sharing) {\n        chrome.desktopCapture.chooseDesktopMedia([\"screen\", \"window\"], onAccessApproved);\n    } else {\n        desktop_sharing = false;\n\n        if (local_stream)\n            local_stream.stop();\n        local_stream = null;\n\n        document.querySelector('button').innerHTML = \"Enable Capture\";\n        console.log('Desktop sharing stopped...');\n    }\n}\n\nfunction onAccessApproved(desktop_id) {\n    if (!desktop_id) {\n        console.log('Desktop Capture access rejected.');\n        return;\n    }\n    desktop_sharing = true;\n    document.querySelector('button').innerHTML = \"Disable Capture\";\n    console.log(\"Desktop sharing started.. desktop_id:\" + desktop_id);\n\n    navigator.webkitGetUserMedia({\n        audio: false,\n        video: {\n            mandatory: {\n                chromeMediaSource: 'desktop',\n                chromeMediaSourceId: desktop_id,\n                minWidth: 1280,\n                maxWidth: 1280,\n                minHeight: 720,\n                maxHeight: 720\n            }\n        }\n    }, gotStream, getUserMediaError);\n\n    function gotStream(stream) {\n        local_stream = stream;\n        document.querySelector('video').src = URL.createObjectURL(stream);\n        stream.onended = function() {\n            if (desktop_sharing) {\n                toggle();\n            }\n        };\n    }\n\n    function getUserMediaError(e) {\n      console.log('getUserMediaError: ' + JSON.stringify(e, null, '---'));\n    }\n}\n\n/**\n * Click handler to init the desktop capture grab\n */\ndocument.querySelector('button').addEventListener('click', function(e) {\n    toggle();\n});\n"
  },
  {
    "path": "_archive/apps/samples/desktop-capture/background.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n    id: \"desktopCaptureID\",\n    innerBounds: {\n      width: 700,\n      height: 600\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/desktop-capture/index.html",
    "content": "<html>\n<head>\n<style>\n  body {\n    background: white;\n    display: -webkit-flex;\n    -webkit-justify-content: center;\n    -webkit-align-items: center;\n    -webkit-flex-direction: column;\n  }\n  video {\n    width: 640px;\n    height: 480px;\n    background: rgba(0,0,0,0.25);\n  }\n  button {\n    display: inline-block;\n    background: -webkit-linear-gradient(#F9F9F9 40%, #E3E3E3 70%);\n    background: linear-gradient(#F9F9F9 40%, #E3E3E3 70%);\n    border: 1px solid #999;\n    -webkit-border-radius: 3px;\n    border-radius: 3px;\n    padding: 5px 8px;\n    outline: none;\n    white-space: nowrap;\n    -webkit-user-select: none;\n    user-select: none;\n    cursor: pointer;\n    text-shadow: 1px 1px #fff;\n    font-weight: 700;\n    font-size: 10pt;\n  }\n  button:hover,\n  button.active {\n    border-color: black;\n  }\n  button:active,\n  button.active {\n    background: -webkit-linear-gradient(#E3E3E3 40%, #F9F9F9 70%);\n    background: linear-gradient(#E3E3E3 40%, #F9F9F9 70%);\n  }\n\n  video {\n    background: white url(desktop.png) center no-repeat;\n    border: 1px solid #e2e2e2;\n    box-shadow: 0 1px 1px rgba(0,0,0,0.2);\n  }\n</style>\n</head>\n<body>\n  <video autoplay></video>\n  <p><button>Enable Capture</button></p>\n<script src=\"app.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/desktop-capture/manifest.json",
    "content": "{\n  \"name\": \"Desktop Capture Sample\",\n  \"version\": \"2\",\n  \"manifest_version\": 2,\n  \"icons\": {\n    \"16\": \"desktop.png\",\n    \"128\": \"desktop.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [\n    \"desktopCapture\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/dialog-element/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/mikhnkopoddcomlgmcjgfnaccjhibiec\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Dialog Element\n\nThe WHATWG defines a new element called `<dialog>` that can be used to define modal and modeless dialogs within an HTML page. This example shows how to use this new element.\n\nNOTE: This sample requires M31 or later in Chrome, and if necessary you might have to enable experimental web features in the chrome://flags page.\n\n```javascript\nvar dialog = document.querySelector('#dialog1');\ndocument.querySelector('#show').addEventListener(\"click\", function(evt) {\n  dialog.showModal();\n});\ndocument.querySelector('#close').addEventListener(\"click\", function(evt) {\n  dialog.close(\"thanks!\");\n});\n\ndialog.addEventListener(\"close\", function(evt) {\n  document.querySelector('#result').textContent = \"You closed the dialog with: \" + dialog.returnValue;\n});\n\n// called when the user Cancels the dialog, for example by hitting the ESC key\ndialog.addEventListener(\"cancel\", function(evt) {\n  dialog.close(\"canceled\");\n});\n```\n\n## Resources\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/dialog-element/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/dialog-element/dialog.js",
    "content": "window.addEventListener(\"load\", function(e) {\n\tvar dialog = document.querySelector('#dialog1');\n\tdocument.querySelector('#show').addEventListener(\"click\", function(evt) {\n\t  dialog.showModal();\n\t});\n\tdocument.querySelector('#close').addEventListener(\"click\", function(evt) {\n\t  dialog.close(\"thanks!\");\n\t});\n\n\tdialog.addEventListener(\"close\", function(evt) {\n\t\tdocument.querySelector('#result').textContent = \"You closed the dialog with: \" + dialog.returnValue;\n\t});\n\n\t// called when the user Cancels the dialog, for example by hitting the ESC key\n\tdialog.addEventListener(\"cancel\", function(evt) {\n\t\tdialog.close(\"canceled\");\n\t});\n});\n"
  },
  {
    "path": "_archive/apps/samples/dialog-element/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <title>Hello World</title>\n    <link rel=\"stylesheet\" href=\"styles.css\"/>\n    <script src=\"dialog.js\"></script>\n</head>\n<body>\n\t<!-- The dialog element can be enabled in Chrome 31 and higher using a setting in chrome://flags.\n\t\tLook for the \"Enable experimental Web Platform features\" flag and make sure it is enabled -->\n\t<dialog id=\"dialog1\">\n\t\t<h1>Dialog Title</h1>\n\t\t<div>\n\t\t\t<p>This is the dialog content</p>\n\t\t\t<button id=\"close\">Close</button>\n\t\t</div>\n\t</dialog>\n\t<h1>Dialog Element Example</h1>\n\n\t<p>Demonstrates how to use the &lt;dialog&gt; element in a Chrome App to implement in-app dialogs</p>\n\t<button id=\"show\">Open Modal Dialog</button>    \n\t<p id=\"result\"></p>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/dialog-element/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  // Center window on screen.\n  var screenWidth = screen.availWidth;\n  var screenHeight = screen.availHeight;\n  var width = 600;\n  var height = 400;\n\n  chrome.app.window.create('index.html', {\n    id: \"window1\",\n    outerBounds: {\n      width: width,\n      height: height,\n      left: Math.round((screenWidth-width)/2),\n      top: Math.round((screenHeight-height)/2)\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/dialog-element/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Dialog Element Example\",\n  \"version\": \"2\",\n  \"minimum_chrome_version\": \"31\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/dialog-element/styles.css",
    "content": "dialog {\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  border-radius: 6px;\n  box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  padding: 0;\n}\ndialog::backdrop {\n  position: fixed;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  background-color: rgba(0, 0, 0, 0.7);\n}\n\ndialog h1 {\n\tbackground-color: #eee;\n\tfont-size: 14pt;\n\ttext-align: center;\n\tfont-weight: bold;\n\tmargin: 0;\n\tpadding: 4pt;\n\tborder-bottom: 1px solid black;\n}\n\ndialog div {\n\tpadding: 10pt;\n}\n\np {\n\tfont-size: 14pt;\n}\n"
  },
  {
    "path": "_archive/apps/samples/diff/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/neifiophhpiohjlhiohlhlekkfokcepk\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Diff\n\nA non-trivial application to diff two files choosen by the user. This app shows how you can open for reading and for writing files in the user's computer, as long as the file was explicitly selected by the user. It uses the Filesystem API, which is an extension of the HTML5 Filesystem API.\n\n## Try it: [Diff Tool Sample](https://chrome.google.com/webstore/detail/diff-tool/knammbkafbpckgibgjilgpcnpacmecme)\n\n## APIs\n\n* [Local Storage API](http://developer.chrome.com/apps/storage) to save history of selected files\n* [Filesystem API](http://developer.chrome.com/apps/app_storage.html) to allow the user to pick arbitrary files from the disk and save them back.\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/diff/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/diff/css/editor.css",
    "content": ".ace_editor {\n    position: absolute;\n    overflow: hidden;\n    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Droid Sans Mono', 'Consolas', monospace;\n    font-size: 12px;\n}\n\n.ace_scroller {\n    position: absolute;\n    overflow-x: scroll;\n    overflow-y: hidden;\n}\n\n.ace_content {\n    position: absolute;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    cursor: text;\n}\n\n.ace_composition {\n    position: absolute;\n    background: #555;\n    color: #DDD;\n    z-index: 4;\n}\n\n.ace_gutter {\n    position: absolute;\n    overflow : hidden;\n    height: 100%;\n    width: auto;\n    cursor: default;\n    z-index: 1000;\n}\n\n.ace_gutter.horscroll {\n    box-shadow: 0px 0px 20px rgba(0,0,0,0.4);\n}\n\n.ace_gutter-cell {\n    padding-left: 19px;\n    padding-right: 6px;\n}\n\n.ace_gutter-cell.ace_error {\n    background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%F5or%F5%87%88%F5nr%F4ns%EBmq%F5z%7F%DDJT%DEKS%DFOW%F1Yc%F2ah%CE(7%CE)8%D18E%DD%40M%F2KZ%EBU%60%F4%60m%DCir%C8%16(%C8%19*%CE%255%F1%3FR%F1%3FS%E6%AB%B5%CA%5DI%CEn%5E%F7%A2%9A%C9G%3E%E0a%5B%F7%89%85%F5yy%F6%82%80%ED%82%80%FF%BF%BF%E3%C4%C4%FF%FF%FF%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%25%00%2C%00%00%00%00%10%00%10%00%00%06p%C0%92pH%2C%1A%8F%C8%D2H%93%E1d4%23%E4%88%D3%09mB%1DN%B48%F5%90%40%60%92G%5B%94%20%3E%22%D2%87%24%FA%20%24%C5%06A%00%20%B1%07%02B%A38%89X.v%17%82%11%13q%10%0Fi%24%0F%8B%10%7BD%12%0Ei%09%92%09%0EpD%18%15%24%0A%9Ci%05%0C%18F%18%0B%07%04%01%04%06%A0H%18%12%0D%14%0D%12%A1I%B3%B4%B5IA%00%3B\");\n    background-repeat: no-repeat;\n    background-position: 2px center;\n}\n\n.ace_gutter-cell.ace_warning {\n    background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%FF%DBr%FF%DE%81%FF%E2%8D%FF%E2%8F%FF%E4%96%FF%E3%97%FF%E5%9D%FF%E6%9E%FF%EE%C1%FF%C8Z%FF%CDk%FF%D0s%FF%D4%81%FF%D5%82%FF%D5%83%FF%DC%97%FF%DE%9D%FF%E7%B8%FF%CCl%7BQ%13%80U%15%82W%16%81U%16%89%5B%18%87%5B%18%8C%5E%1A%94d%1D%C5%83-%C9%87%2F%C6%84.%C6%85.%CD%8B2%C9%871%CB%8A3%CD%8B5%DC%98%3F%DF%9BB%E0%9CC%E1%A5U%CB%871%CF%8B5%D1%8D6%DB%97%40%DF%9AB%DD%99B%E3%B0p%E7%CC%AE%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%2F%00%2C%00%00%00%00%10%00%10%00%00%06a%C0%97pH%2C%1A%8FH%A1%ABTr%25%87%2B%04%82%F4%7C%B9X%91%08%CB%99%1C!%26%13%84*iJ9(%15G%CA%84%14%01%1A%97%0C%03%80%3A%9A%3E%81%84%3E%11%08%B1%8B%20%02%12%0F%18%1A%0F%0A%03'F%1C%04%0B%10%16%18%10%0B%05%1CF%1D-%06%07%9A%9A-%1EG%1B%A0%A1%A0U%A4%A5%A6BA%00%3B\");\n    background-repeat: no-repeat;\n    background-position: 2px center;\n}\n\n.ace_gutter-cell.ace_info {\n    background-image: url(\"data:image/gif;base64,R0lGODlhEAAQAMQAAAAAAEFBQVJSUl5eXmRkZGtra39/f4WFhYmJiZGRkaampry8vMPDw8zMzNXV1dzc3OTk5Orq6vDw8P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABQALAAAAAAQABAAAAUuICWOZGmeaBml5XGwFCQSBGyXRSAwtqQIiRuiwIM5BoYVbEFIyGCQoeJGrVptIQA7\");\n    background-repeat: no-repeat;\n    background-position: 2px center;\n}\n\n.ace_editor .ace_sb {\n    position: absolute;\n    overflow-x: hidden;\n    overflow-y: scroll;\n    right: 0;\n}\n\n.ace_editor .ace_sb div {\n    position: absolute;\n    width: 1px;\n    left: 0;\n}\n\n.ace_editor .ace_print_margin_layer {\n    z-index: 0;\n    position: absolute;\n    overflow: hidden;\n    margin: 0;\n    left: 0;\n    height: 100%;\n    width: 100%;\n}\n\n.ace_editor .ace_print_margin {\n    position: absolute;\n    height: 100%;\n}\n\n.ace_editor textarea {\n    position: fixed;\n    z-index: 0;\n    width: 10px;\n    height: 30px;\n    opacity: 0;\n    background: transparent;\n    appearance: none;\n    -moz-appearance: none;\n    border: none;\n    resize: none;\n    outline: none;\n    overflow: hidden;\n}\n\n.ace_layer {\n    z-index: 1;\n    position: absolute;\n    overflow: hidden;\n    white-space: nowrap;\n    height: 100%;\n    width: 100%;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    /* setting pointer-events: auto; on node under the mouse, which changes\n        during scroll, will break mouse wheel scrolling in Safari */\n    pointer-events: none;\n}\n\n.ace_gutter .ace_layer {\n    position: relative;\n    min-width: 40px;\n    text-align: right;\n    pointer-events: auto;\n}\n\n.ace_text-layer {\n    color: black;\n}\n\n.ace_cjk {\n    display: inline-block;\n    text-align: center;\n}\n\n.ace_cursor-layer {\n    z-index: 4;\n}\n\n.ace_cursor {\n    z-index: 4;\n    position: absolute;\n}\n\n.ace_cursor.ace_hidden {\n    opacity: 0.2;\n}\n\n.ace_editor.multiselect .ace_cursor {\n    border-left-width: 1px;\n}\n\n.ace_line {\n    white-space: nowrap;\n}\n\n.ace_marker-layer .ace_step {\n    position: absolute;\n    z-index: 3;\n}\n\n.ace_marker-layer .ace_selection {\n    position: absolute;\n    z-index: 5;\n}\n\n.ace_marker-layer .ace_bracket {\n    position: absolute;\n    z-index: 6;\n}\n\n.ace_marker-layer .ace_active_line {\n    position: absolute;\n    z-index: 2;\n}\n\n.ace_gutter .ace_gutter_active_line{\n    background-color : #dcdcdc;\n}\n\n.ace_marker-layer .ace_selected_word {\n    position: absolute;\n    z-index: 4;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n}\n\n.ace_line .ace_fold {\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n\n    display: inline-block;\n    height: 11px;\n    margin-top: -2px;\n    vertical-align: middle;\n\n    background-image:\n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),\n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%3AIDAT8%11c%FC%FF%FF%7F%18%03%1A%60%01%F2%3F%A0%891%80%04%FF%11-%F8%17%9BJ%E2%05%B1ZD%81v%26t%E7%80%F8%A3%82h%A12%1A%20%A3%01%02%0F%01%BA%25%06%00%19%C0%0D%AEF%D5%3ES%00%00%00%00IEND%AEB%60%82\");\n    background-repeat: no-repeat, repeat-x;\n    background-position: center center, top left;\n    color: transparent;\n\n    border: 1px solid black;\n    -moz-border-radius: 2px;\n    -webkit-border-radius: 2px;\n    border-radius: 2px;\n\n    cursor: pointer;\n    pointer-events: auto;\n}\n\n.ace_dark .ace_fold {\n}\n\n.ace_fold:hover{\n    background-image:\n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),\n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%003IDAT8%11c%FC%FF%FF%7F%3E%03%1A%60%01%F2%3F%A3%891%80%04%FFQ%26%F8w%C0%B43%A1%DB%0C%E2%8F%0A%A2%85%CAh%80%8C%06%08%3C%04%E8%96%18%00%A3S%0D%CD%CF%D8%C1%9D%00%00%00%00IEND%AEB%60%82\");\n    background-repeat: no-repeat, repeat-x;\n    background-position: center center, top left;\n}\n\n.ace_dragging .ace_content {\n    cursor: move;\n}\n\n.ace_folding-enabled > .ace_gutter-cell {\n    padding-right: 13px;\n}\n\n.ace_fold-widget {\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n\n    margin: 0 -12px 1px 1px;\n    display: inline-block;\n    height: 14px;\n    width: 11px;\n    vertical-align: text-bottom;\n\n    background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAe%8A%B1%0D%000%0C%C2%F2%2CK%96%BC%D0%8F9%81%88H%E9%D0%0E%96%C0%10%92%3E%02%80%5E%82%E4%A9*-%EEsw%C8%CC%11%EE%96w%D8%DC%E9*Eh%0C%151(%00%00%00%00IEND%AEB%60%82\");\n    background-repeat: no-repeat;\n    background-position: center 5px;\n\n    border-radius: 3px;\n}\n\n.ace_fold-widget.end {\n    background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAm%C7%C1%09%000%08C%D1%8C%ECE%C8E(%8E%EC%02)%1EZJ%F1%C1'%04%07I%E1%E5%EE%CAL%F5%A2%99%99%22%E2%D6%1FU%B5%FE0%D9x%A7%26Wz5%0E%D5%00%00%00%00IEND%AEB%60%82\");\n}\n\n.ace_fold-widget.closed {\n    background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%03%00%00%00%06%08%06%00%00%00%06%E5%24%0C%00%00%009IDATx%DA5%CA%C1%09%000%08%03%C0%AC*(%3E%04%C1%0D%BA%B1%23%A4Uh%E0%20%81%C0%CC%F8%82%81%AA%A2%AArGfr%88%08%11%11%1C%DD%7D%E0%EE%5B%F6%F6%CB%B8%05Q%2F%E9tai%D9%00%00%00%00IEND%AEB%60%82\");\n}\n\n.ace_fold-widget:hover {\n    border: 1px solid rgba(0, 0, 0, 0.3);\n    background-color: rgba(255, 255, 255, 0.2);\n    -moz-box-shadow:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n    -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n    -webkit-box-shadow:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n    -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n    box-shadow:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n    background-position: center 4px;\n}\n\n.ace_fold-widget:active {\n    border: 1px solid rgba(0, 0, 0, 0.4);\n    background-color: rgba(0, 0, 0, 0.05);\n    -moz-box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n    -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n    -webkit-box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n    -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n    box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n}\n\n.ace_fold-widget.invalid {\n    background-color: #FFB4B4;\n    border-color: #DE5555;\n}\n"
  },
  {
    "path": "_archive/apps/samples/diff/css/style.css",
    "content": "/**\n * Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\nbody {\n  background: #fff;\n  color: #222;\n  font-family: Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  line-height: 18px;\n  margin: 10px;\n  min-width: 1230px;\n}\n\n.title {\n  color: #dd4b39;\n  font-size: 20px;\n  margin-bottom: 1em;\n}\n\n.button {\n  background-color: #f5f5f5;\n  background-image: linear-gradient(top, #f5f5f5, #f1f1f1);\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f1f1f1);\n  border: 1px solid rgba(0, 0, 0, 0.1);\n  border-radius: 2px;\n  -webkit-border-radius: 2px;\n  color: #444;\n  cursor: default;\n  display: inline-block;\n  font-size: 11px;\n  font-weight: bold;\n  height: 27px;\n  line-height: 27px;\n  margin-right: 16px;\n  min-width: 54px;\n  padding: 0 8px;\n  text-align: center;\n  transition: all 0.218s;\n  -webkit-transition: all 0.218s;\n  white-space: nowrap;\n}\n\n.button:hover {\n  background-color: #f8f8f8;\n  background-image: -webkit-linear-gradient(top, #f8f8f8, #f1f1f1);\n  background-image: linear-gradient(top, #f8f8f8, #f1f1f1);\n  border: 1px solid #c6c6Cc;\n  box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);\n  -webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);\n  color: #222;\n  transition: all 0.0s;\n  -webkit-transition: all 0.0s;\n}\n\n.button:active {\n  background-color: #f6f6f6;\n  background-image: -webkit-linear-gradient(top, #f6f6f6, #f1f1f1);\n  background-image: linear-gradient(top, #f6f6f6, #f1f1f1);\n  border: 1px solid #c6c6c6;\n  box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);\n  -webkit-box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);\n  color: #333;\n}\n\n.button.blue {\n  background-color: #4d90fe;\n  background-image: -webkit-linear-gradient(top, #4d90fe, #4787ed);\n  background-image: linear-gradient(top, #4d90fe, #4787ed);\n  border: 1px solid #3079ed;\n  color: #fff;\n}\n\n.menubutton {\n  position: relative;\n  margin-top: 4px;\n}\n\n.menubutton .label {\n  display: inline-block;\n  font-size: 14px;\n  font-weight: normal;\n  margin-left: 5px;\n  overflow: hidden;\n  width: 310px;\n  text-align: left;\n}\n\n.menubutton .indicator {\n  background: url('../img/triangle-down.png') center no-repeat;\n  float: right;\n  height: 11px;\n  margin-left: 7px;\n  margin-top: -20px;\n  opacity: 0.7;\n  transform: none;\n  -webkit-transform: none;\n  width: 7px;\n}\n\n.menubutton:hover .indicator {\n  border-left-color: #999;\n  opacity: 1;\n}\n\n.menubutton .menulist {\n  background: #fff;\n  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);\n  filter: alpha(opacity=00);\n  height: 0;\n  left: -9999px;\n  margin-top: 0px;\n  opacity: 0;\n  outline: 1px solid rgba(0, 0, 0, 0.2);\n  padding: 0px;\n  position: absolute;\n  text-align: left;\n  transition: 0;\n  white-space: nowrap;\n  width: 100%;\n  z-index: 99;\n}\n\n.menubutton .menulist.shown {\n  filter: alpha(opacity=100);\n  height: auto;\n  left: 0;\n  opacity: 1.0;\n  transition: 0;\n  -webkit-transition: 0;\n}\n\n.menubutton .menulist.scroll.shown {\n  max-height: 174px;\n  overflow: auto;\n}\n\n.menulist .menulistitem {\n  color: #333;\n  cursor: default;\n  display: block;\n  font-size: 13px;\n  font-weight: normal;\n  margin: 0px;\n  margin-bottom: 4px;\n  overflow: hidden;\n  padding: 2px 40px 2px 12px;\n  position: relative;\n}\n\n.menulist .menulistitem:hover,\n.menulist .menulistitem.selected {\n  background-color: #f1f1f1;\n  color: #222;\n  transition: background 0s;\n  -webkit-transition: background 0s;\n}\n\n.menulist .menulistitem .delete {\n  background: url('../img/x.png') center no-repeat;\n  background-size: auto 15px;\n  cursor: default;\n  filter: alpha(opacity=70);\n  height: 10px;\n  opacity: 0.7;\n  position: absolute;\n  right: 5px;\n  top: 10px;\n  width: 10px;\n}\n\n.menulist .menulistitem .delete:hover {\n  opacity: 1;\n}\n\ninput[type=text] {\n  background-color: #fff;\n  border: 1px solid #d9d9d9;\n  border-top: 1px solid #c0c0c0;\n  box-sizing: border-box;\n  -webkit-box-sizing: border-box;\n  border-radius: 1 px;\n  -webkit-border-radius: 1px;\n  color: #333;\n  display: inline-block;\n  height: 29px;\n  line-height: 27px;\n  padding-left: 8px;\n  vertical-align: top;\n}\n\ninput[type=text]:hover {\n  border: 1px solid #b9b9b9;\n  border-top: 1px solid #a0a0a0;\n  box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);\n  -webkit-box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);\n}\n\ninput[type=text]:focus {\n  border: 1px solid #4d90fe;\n  box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.3);\n  outline: none;\n}\n\n#modal-shield {\n  background: #fff;\n  bottom: 0;\n  filter: alpha(opacity=75);\n  left: 0;\n  opacity: 0.75;\n  position: fixed;\n  right: 0;\n  top: 0;\n  transition: all 0.218s;\n  -webkit-transition: all 0.218s;\n  z-index: 99;\n}\n\n.modal-dialog {\n  background: white;\n  border: 1px solid #ccc;\n  box-shadow: 0 4px 16px rgba(0,0,0,0.2);\n  -webkit-box-shadow: 0 4px 16px rgba(0,0,0,0.2);\n  height: auto;\n  left: 50%;\n  margin-left: -256px;\n  opacity: 0.0;\n  outline: 1px solid rgba(0,0,0,0.2);\n  overflow: hidden;\n  padding: 30px 42px;\n  position: fixed;\n  right: auto;\n  top: 72px;\n  transform: scale(1.05);\n  -webkit-transform: scale(1.05);\n  transition: all 0.218s;\n  -webkit-transition: all 0.218s;\n  width: 512px;\n  z-index: 100;\n}\n\n.modal-dialog.visible {\n  opacity: 1.0;\n  transform: scale(1.0);\n  -webkit-transform: scale(1.0);\n}\n\n.modal-dialog h1 {\n  color: #222;\n  font-family: inherit;\n  font-size: 16px;\n  font-style: inherit;\n  font-weight: normal;\n  line-height: 24px;\n  margin: 0;\n  margin-bottom: 1em;\n  padding: 0;\n  vertical-align: baseline;\n}\n\n.modal-dialog .close-button {\n  background: url('../img/x.png') center no-repeat;\n  cursor: default;\n  filter: alpha(opacity=70);\n  height: 44px;\n  opacity: 0.7;\n  position: absolute;\n  right: 0;\n  top: 0;\n  width: 44px;\n}\n\n.modal-dialog .close-button:hover {\n  filter: alpha(opacity=100);\n  opacity: 1;\n}\n\n.prompt label {\n  display: block;\n  margin-bottom: 16px;\n}\n\n.prompt input[type=text] {\n  width: 100%;\n}\n\ninput[type=text].form-error{\n  border: 1px solid #dd4b39;\n}\n\n.error-message{\n  color: #dd4b39;\n  padding: 0px;\n}\n\n.offline {\n  margin-bottom: 10px;\n  margin-top: -5px;\n}\n\n.offline div.text {\n  color: #999;\n  font-size: 14px;\n  margin-left: 24px;\n  margin-top: -18px;\n  position: absolute;\n}\n\n.offline .loader {\n  background-color: #999;\n  border-color: #999;\n  border-radius: 50%;\n  -webkit-border-radius: 50%;\n  display: block;\n  height: 19px;\n  position: relative;\n  width: 19px;\n}\n\n.offline .loader .bolt {\n  background: url('../img/offline_lightning.png') center no-repeat;\n  height: 14px;\n  left: 50%;\n  margin-left: -4px;\n  margin-top: -7px;\n  position: absolute;\n  top: 50%;\n  transition: opacity 0.218s linear 0.44s;\n  -webkit-transition: opacity 0.218s linear 0.44s;\n  width: 8px;\n}\n\n.tooltip {\n  background: #2d2d2d;\n  box-shadow: 1px 2px 4px rgba(0,0,0,0.2);\n  -webkit-box-shadow: 0px 1px 4px rgba(0,0,0,0.2);\n  box-sizing: border-box;\n  -webkit-box-sizing: border-box;\n  color: #FFF;\n  display: block;\n  font-size: 11px;\n  font-weight: bold;\n  height: 29px;\n  line-height: 29px;\n  outline: 1px solid rgba(255,255,255,0.5);\n  padding: 0 10px;\n  position: absolute;\n  text-align: center;\n  transition: opacity 0.13s;\n  -webkit-transition: opacity 0.13s;\n  white-space: nowrap;\n  z-index: 2000;\n}\n\n.tooltip.visible {\n  opacity: 1.0;\n}\n\n.tooltip .pointer {\n  border-left: 5px solid transparent;\n  border-bottom: 5px solid #2d2d2d;\n  border-right: 5px solid transparent;\n  border-top: transparent;\n  display: block;\n  font-size: 0px;\n  height: 0;\n  left: 24px;\n  line-height: 0px;\n  margin: 0 0 0 -5px;\n  outline: none;\n  position: absolute;\n  top: -5px;\n  width: 0;\n}\n\n::-webkit-scrollbar {\n  width: 10px;\n  height: 10px;\n  border: 1px solid #eee;\n}\n\n::-webkit-scrollbar-thumb {\n  background: #ddd;\n  border: 1px solid #d5d5d5;\n}\n\n#left-side {\n  float: left;\n  height: 100%;\n  margin-right: 5px;\n  min-height: 768px;\n  position: relative;\n  width: 44px;\n}\n\n#left-side .button.new-diff {\n  cursor: pointer;\n  float: left;\n  height: 30px;\n  margin: 4px;\n  min-height: 30px;\n  min-width: 36px;\n  padding: 0px;\n  width: 36px;\n}\n\n#left-side .button.new-diff img {\n  height: 24px;\n  margin-top: 3px;\n  width: 24px;\n}\n\n#left-side .tooltip.new-diff {\n  top: 42px;\n}\n\n#left-side #prev-chunk {\n  background: url('../img/arrow-up.jpg') center no-repeat;\n  background-size: auto 20px;\n  cursor: pointer;\n  height: 30px;\n  left: 13px;\n  position: absolute;\n  top: 75px;\n  width: 20px;\n}\n\n#left-side .tooltip.prev-chunk {\n  left: 0px;\n  top: 110px;\n}\n\n#left-side .tooltip.prev-chunk .pointer {\n  left: 23px;\n}\n\n#left-side #next-chunk {\n  background: url('../img/arrow-down.jpg') center no-repeat;\n  background-size: auto 20px;\n  cursor: pointer;\n  height: 30px;\n  left: 13px;\n  position: absolute;\n  top: 105px;\n  width: 20px;\n}\n\n#left-side .tooltip.next-chunk {\n  left: 0px;\n  top: 135px;\n}\n\n#left-side .tooltip.next-chunk .pointer {\n  left: 23px;\n}\n\n#left-side #expand-all,\n#left-side #collapse-all {\n  cursor: pointer;\n  height: 20px;\n  position: absolute;\n  top: 45px;\n  width: 20px;\n}\n\n#left-side #expand-all {\n  background: url('../img/plus_all.png') center no-repeat;\n  left: 2px;\n}\n\n#left-side .tooltip.expand-all {\n  top: 73px;\n  left: 0px;\n}\n\n#left-side .tooltip.expand-all .pointer {\n  left: 15px;\n}\n\n#left-side #collapse-all {\n  background: url('../img/minus_all.png') center no-repeat;\n  left: 21px;\n}\n\n#left-side .tooltip.collapse-all {\n  top: 73px;\n  left: 18px;\n}\n\n#left-side .tooltip.collapse-all .pointer {\n  left: 15px;\n}\n\n#left-side #expand-all.disabled,\n#left-side #collapse-all.disabled,\n#left-side #prev-chunk.disabled,\n#left-side #next-chunk.disabled {\n  cursor: default;\n  opacity: 0.25;\n}\n\n#arrow-container,\n#check-container {\n  border-bottom: 2px solid #666;\n  border-top: 2px solid #666;\n  float: left;\n  height: 705px;\n  margin-top: 43px;\n  overflow: auto;\n  position: relative;\n  width: 30px;\n}\n\n#arrow-container::-webkit-scrollbar,\n#check-container::-webkit-scrollbar {\n  display: none;\n}\n\n#arrow-container .arrow {\n  background: url('../img/arrow-right.png') center no-repeat;\n  background-size: auto 85px;\n  height: 16px;\n  opacity: 0;\n}\n\n#check-container .check {\n  background: url('../img/arrow-left.png') center no-repeat;\n  background-size: auto 85px;\n  height: 20px;\n  margin-bottom: -4px;\n  opacity: 0;\n}\n\n#arrow-container .undo,\n#check-container .undo,\n#arrow-container  .holder,\n#check-container  .holder {\n  background: url('../img/undo.svg') right no-repeat;\n  height: 16px;\n  opacity: 0;\n}\n\n#arrow-container .visible,\n#check-container .visible {\n  cursor: pointer;\n  opacity: 1;\n}\n\n#arrow-container.arrow-edit,\n#check-container.check-edit {\n  opacity: 0;\n}\n\n#file0-container,\n#file1-container {\n  float: left;\n  min-height: 755px;\n  position: relative;\n  width: 45%;\n}\n\n#file0-container {\n  min-width: 555px;\n}\n\n#file1-container {\n  min-width: 530px;\n}\n\ndiv.file-name {\n  float: left;\n  font-size: 16px;\n  padding-top: 15px;\n}\n\nspan.file-name-info {\n  color: #777;\n  font-size: 11px;\n}\n\n.file-diff,\n#editor {\n  background: #fff;\n  border: 2px solid #666;\n  color: #666;\n  float: left;\n  font-family: mono, courier, monospace;\n  font-size: 10px;\n  height: 705px;\n  line-height: 16px;\n  margin-bottom: 10px;\n  margin-top: 10px;\n  overflow: auto;\n  top: 35px;\n  white-space: nowrap;\n  width: 100%;\n}\n\n#file0-container .file-diff::-webkit-scrollbar {\n  display: none;\n}\n\n#file0-container .file-diff {\n  border-right: 1px solid #999;\n}\n\n#file1-container .file-diff {\n  border-left: 1px solid #999;\n}\n\ndiv.button.edit,\ndiv.button.save {\n  float: right;\n  height: 20px;\n  margin-left: 16px;\n  margin-right: 0px;\n  margin-top: 10px;\n  min-height: 20px;\n  min-width: 20px;\n}\n\n.tooltip.save {\n  right: 0px;\n  top: 39px;\n}\n\n.tooltip.save .pointer {\n  left: 43px;\n}\n\n.tooltip.edit {\n  right: 55px;\n  top: 39px;\n}\n\ndiv.button.done {\n  float: right;\n  margin-right: 0px;\n  margin-top: 4px;\n  min-width: 20px;\n}\n\n.edit img,\n.save img {\n  height: 16px;\n  margin: 2px;\n  width: 16px;\n}\n\n.file-diff > div {\n  float: left;\n  min-height: 16px;\n  min-width: 100%;\n  position: relative;\n  white-space: nowrap;\n}\n\n.file-diff div.collapsed-num {\n  background: #ddf;\n  color: #000;\n  font-family: Helvetica, Arial, sans-serif;\n  text-align: center;\n}\n\n.file-diff div .expand {\n  background-color: #fff;\n  border-right: 1px solid #999;\n  float: left;\n  height: 48px;\n  margin-left: -1px;\n  margin-top: -16px;\n  padding-left: 3px;\n  position: absolute;\n  width: 21px;\n}\n\n.file-diff div.selected-chunk .expand {\n  width: 20px;\n}\n\n.file-diff div .expand.plus {\n  background: url('../img/plus.png') center no-repeat;\n  cursor: pointer;\n  z-index: 10;\n}\n\n.file-diff div .expand.minus {\n  background: url('../img/minus.png') center no-repeat;\n  cursor: pointer;\n  z-index: 10;\n}\n\n.file-diff div.blank {\n  background: #eee;\n}\n\n#file1-container .file-diff div.ins,\n#file1-container .file-diff div.del {\n  background: #dfd;\n}\n\n#file0-container .file-diff div.del,\n#file0-container .file-diff div.ins {\n  background: #fee;\n}\n\n.file-diff div.blank.del,\n.file-diff div.blank.ins {\n  display: none;\n}\n\n.file-diff div.selected-chunk {\n  border-left: 1px solid #000;\n  border-right: 1px solid #000;\n  color: #000;\n}\n\n.file-diff div.selected-chunk.first {\n  border-top: 1px solid #000;\n  box-shadow: 0 -4px 4px -3px #666;\n}\n\n.file-diff div.selected-chunk.last {\n  border-bottom: 1px solid #000;\n  box-shadow: 0 4px 4px -3px #666;\n}\n\n.file-diff div div.lineNum {\n  border-right: 1px solid #999;\n  float: left;\n  overflow: hidden;\n  text-align: center;\n  width: 35px;\n}\n\n#file0-container .file-diff div div.lineNum {\n  position: absolute;\n  left: 26px;\n}\n\n#file0-container .file-diff div div.text {\n  position: absolute;\n  left: 68px;\n}\n\n#file1-container .file-diff div div.text {\n  position: absolute;\n  left: 42px;\n}\n\n.file-diff div span {\n  float: left;\n  position: relative;\n}\n\n.file-diff div span.ins {\n  background: #9f9;\n}\n\n.file-diff div span.del {\n  background: #faa;\n}\n\n#file0-container .file-diff div span.ins {\n  display: none;\n}\n\n#file1-container .file-diff div span.del {\n  display: none;\n}\n\n#file0-container .file-diff div.fix,\n#file1-container .file-diff div.fix,\n#file0-container .file-diff div.correct,\n#file1-container .file-diff div.correct {\n  background: none;\n}\n\n#file0-container .file-diff div.fix span.del {\n  background: none;\n}\n\n#file1-container .file-diff div.fix span.ins {\n  display: none;\n}\n\n#file1-container .file-diff div.fix span.del {\n  display: block;\n  background: none;\n}\n\n#file0-container .file-diff div.correct span.ins {\n  display: block;\n  background: none;\n}\n\n#file0-container .file-diff div.correct span.del {\n  display: none;\n}\n\n.file-diff div.correct span {\n  background: none;\n}\n\n#num-diffs {\n  float: right;\n  margin-right: 12px;\n  margin-top: 15px;\n}\n\n.modal-dialog.new-diff .choose-file {\n  float: left;\n  margin-bottom: 16px;\n}\n\n.modal-dialog.new-diff label {\n  float: left;\n  margin-right: 16px;\n  margin-top: 5px;\n}\n\n.modal-dialog.new-diff input {\n  float: left;\n  margin-bottom: 16px;\n  width: 320px;\n}\n\n.error-message {\n  float: left;\n  margin-bottom: 8px;\n  margin-top: -14px;\n  opacity: 0;\n}\n\n.error-message.visible {\n  opacity: 1;\n}\n\n.modal-dialog.new-diff .loading {\n  margin-left: 16px;\n  position: relative;\n}\n\n.modal-dialog.new-diff .loading .loader {\n  float: left;\n  margin: 4px;\n}\n\n.hidden {\n  display: none;\n}\n\n.modal-dialog.new-diff .url.hidden {\n  display: none;\n}\n\nbr.clear {\n  clear: both;\n}\n\nbr.clear-right {\n  clear: right;\n}\n"
  },
  {
    "path": "_archive/apps/samples/diff/js/background.js",
    "content": "/**\n * Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\nfunction onLaunched(launchData) {\n  chrome.app.window.create('main.html', {\n  \tid: \"diffWinID\",\n    innerBounds: {\n      width: 1270,\n      height: 800\n    }\n  });\n}\n\nchrome.app.runtime.onLaunched.addListener(onLaunched);\n"
  },
  {
    "path": "_archive/apps/samples/diff/js/diff.js",
    "content": "/**\n * Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\nvar dmp = new diff_match_patch();\ndmp.Diff_Timeout = 1;\nvar clicked;\nvar selectedChunk = 0;\nvar totalChunks;\nvar totalCollapsible = 0;\nvar numCollapsed;\n\n$(document).ready(function() {\n\n  var buttons = [ '#new-diff',\n                  '#save',\n                  '#edit',\n                  '#expand-all',\n                  '#collapse-all',\n                  '#next-chunk',\n                  '#prev-chunk'\n                ];\n\n  for (var i = 0; i < buttons.length; i++) {\n    $(buttons[i]).hover(\n      function() {\n        var button = $(this).attr('id');\n        $('.tooltip.' + button).removeClass('hidden');\n      },\n      function() {\n        var button = $(this).attr('id');\n        $('.tooltip.' + button).addClass('hidden');\n      }\n    );\n  }\n\n  // Check for connection every 5 seconds\n  setInterval(function() {\n    if (navigator.onLine) {\n      $('.offline').addClass('hidden');\n      $('.url').removeClass('hidden');\n    } else {\n      $('.offline').removeClass('hidden');\n      $('.url').addClass('hidden');\n    }\n  }, 500);\n\n  $('.file-diff > div').click(function() {\n    console.log(this);\n    selectChunk(this);\n  });\n\n  for (i = 0; i < 2; i++) {\n    $('.file-diff.' + i).scroll(function() {\n      var i = $(this).attr('class').split(' ')[1];\n      $('.file-diff.' + ((parseInt(i) + 1) % 2)).scrollTop(\n          $('.file-diff.' + i).scrollTop());\n      $('#arrow-container').scrollTop($('.file-diff.' + i).scrollTop());\n      $('#check-container').scrollTop($('.file-diff.' + i).scrollTop());\n    });\n  }\n\n  $('#arrow-container').scroll(function() {\n    $('.file-diff').scrollTop($('#arrow-container').scrollTop());\n    $('#check-container').scrollTop($('#arrow-container').scrollTop());\n  });\n\n  $('#check-container').scroll(function() {\n    $('.file-diff').scrollTop($('#check-container').scrollTop());\n    $('#arrow-container').scrollTop($('#check-container').scrollTop());\n  });\n\n  $('#collapse-all').click(function () {\n    collapseAllMatches();\n  });\n\n  $('#expand-all').click(function () {\n    expandAllMatches();\n  });\n\n  $('#prev-chunk').click(function() {\n    selectPrevChunk();\n  });\n\n  $('#next-chunk').click(function() {\n    selectNextChunk();\n  });\n\n  $(document).keyup(function(event) {\n    var target = event.target || event.srcElement;\n    var targetName = target.tagName.toLowerCase();\n    if (!disableShortcuts()) {\n      keyboardShortcut(event);\n    }\n  });\n});\n\nfunction keyboardShortcut(event) {\n  if (event.which == 74)\n    selectNextChunk();\n  else if (event.which == 75)\n    selectPrevChunk();\n  else if ((event.which == 76) \n            && (selectedChunk > 0) && (selectedChunk <= totalChunks))\n    moveChunk('chunk-' + selectedChunk);\n  else if ((event.which == 82) \n            && (selectedChunk > 0) && (selectedChunk <= totalChunks))\n    checkRight('chunk-' + selectedChunk);\n  else if (event.which == 69)\n    expandAllMatches();\n  else if (event.which == 67)\n    collapseAllMatches();\n}\n\n\nfunction disableShortcuts () {\n  return ( !$('#modal-shield').hasClass('hidden') \n           || $('.button.edit').hasClass('hidden')\n         )\n}\n\nfunction getText(fileNum) {\n  var lines = $('.file-diff.' + fileNum + ' div').children('.text');\n  var text = '';\n  for (var i = 0; i < lines.length; i++) {\n    if (!isBlankLine($(lines[i]).parent(), null)\n        && !$(lines[i]).hasClass('hidden')) {\n      var line = $(lines[i]).children();\n      for (var j = 0; j < line.length; j++) {\n        if ($(lines[i]).hasClass('merged')) {\n          if (fileNum == 1 && !$(line[j]).hasClass('ins'))\n            text += $(line[j]).html();\n          if (fileNum == 0 && !$(line[j]).hasClass('del'))\n            text += $(line[j]).html();\n        } else {\n          if (fileNum == 0 && !$(line[j]).hasClass('ins'))\n            text += $(line[j]).html();\n          if (fileNum == 1 && !$(line[j]).hasClass('del'))\n            text += $(line[j]).html();\n        }\n      }\n      text += '\\n';\n    }\n  }\n  text = escapeHtml(text);\n  return text;\n}\n\nfunction escapeHtml(text) {\n  var text = text.replace(/&amp;/g, '&')\n                 .replace(/&lt;/g, '<')\n                 .replace(/&gt;/g, '>')\n                 .replace(/&nbsp;/g, ' ');\n  return text;\n}\n\nfunction ajaxErrorMessage(xhr) {\n  message = 'Please enter a valid URL';\n  switch (xhr.status) {\n    case 401:\n      message = 'You do not have permission to view that URL';\n      break;\n    case 403:\n      message = 'You do not have permission to view that URL';\n      break;\n    case 404:\n      message = 'The URL you entered could not be found';\n      break;\n    case 500:\n      message = 'There was a server error';\n      break;\n  }\n  return message;\n}\n\nfunction getChunk(line) {\n  return $(line).attr('class').replace('del ', '')\n                              .replace('ins ', '')\n                              .replace('blank ', '')\n                              .replace('first ', '')\n                              .replace('chunk ', '')\n                              .replace('fix ', '')\n                              .replace('correct ', '')\n                              .split(' ')[1];\n}\n\nfunction getRealLine(line) {\n  var classes =  $(line).attr('class');\n  classes = classes.replace('del ', '')\n                   .replace('ins ', '')\n                   .replace('blank ', '')\n                   .replace('first ', '')\n                   .replace('fix ', '')\n                   .replace('correct ', '')\n                   .replace('chunk ', '');\n  var realLine = classes.split(' ')[0];\n  return realLine;\n}\n\nfunction computeDiff(file1, file2) {\n  var d = dmp.diff_main(file1, file2);\n  dmp.diff_cleanupSemantic(d);\n  var ds = createHtmlLines(d);\n  if (texts[0] != '')\n    $('.file-diff.0').html(ds[0]);\n  if (texts[1] != '')\n    $('.file-diff.1').html(ds[1]);\n  setLineTypes();\n  setLineNums();\n  if (texts[0] != '' && texts[1] != '') {\n    setNumDiffs(true);\n    setArrowsAndChecks();\n    createCollapsibleMatches();\n    $('.button.save').removeClass('hidden');\n    $('.button.edit').removeClass('hidden');\n    $('#collapse-all').removeClass('hidden');\n    $('#expand-all').removeClass('hidden');\n  }\n}\n\nfunction patchToFile2(file1, patchText) {\n  var patches = dmp.patch_fromText(patchText);\n  var patchData = dmp.patch_apply(patches, file1);\n  return patchData[0];\n}\n\nfunction createHtmlLines(diffs) {\n  var pattern_amp = /&/g;\n  var pattern_lt = /</g;\n  var pattern_gt = />/g;\n  var pattern_para = /\\n/g;\n  var pattern_cr = /\\r/g;\n  var pattern_space = / /g;\n  var pattern_para_sign = /<span class=\"hidden\">&para;<\\/span>/g;\n  var line1 = 1;\n  var line2 = 1;\n  var html1 = '<div>';\n  var html2 = '<div>';\n\n  for (var x = 0; x < diffs.length; x++) {\n    var op = diffs[x][0];    // Operation (insert, delete, equal)\n    var data = diffs[x][1];  // Text of change.\n    var text = data.replace(pattern_amp, '&amp;')\n                   .replace(pattern_lt, '&lt;')\n                   .replace(pattern_gt, '&gt;')\n                   .replace(pattern_para, '&para;<br>')\n                   .replace(pattern_cr, '&para;<br>')\n                   .replace(pattern_space, '&nbsp;')\n                   .replace(pattern_para_sign, '&para;<br>');\n    text = text.split('<br>');\n    for (var i = 0; i < text.length; i++) {\n      if (text[i] != \"\") {\n        switch (op) {\n          case DIFF_INSERT:\n            var len = text[i].length;\n            if (len > 5 && text[i].slice(len - 6, len) == '&para;')\n              line2 += 1;\n            txt2 = '<span class=\"ins\">' + text[i] + '</span>';\n            html2 += txt2;\n            html1 += txt2;\n            break;\n          case DIFF_DELETE:\n            var len = text[i].length;\n            if (len > 5 && text[i].slice(len - 6, len) == '&para;')\n              line1 += 1;\n            txt1 = '<span class=\"del\">' + text[i] + '</span>';\n            html1 += txt1;\n            html2 += txt1;\n            break;\n          case DIFF_EQUAL:\n            while (line1 > line2) {\n              line2 += 1;\n              html2 += '</div><div>';\n            } while (line2 > line1) {\n              line1 += 1;\n              html1 += '</div><div>';\n            }\n            txt = '<span>' + text[i] + '</span>';\n            html1 += txt;\n            html2 += txt;\n            break;\n        }\n      }\n    }\n  }\n  while (line1 > line2) {\n    html2 += '</div><div>';\n    line2 += 1;\n  } while (line2 > line1) {\n    html1 += '</div><div>';\n    line1 += 1;\n  }\n  html1 = html1.replace(/&para;/g,\n                        '</div><span class=\"hidden\">&para;</span><div>')\n            + '</div>';\n  html2 = html2.replace(/&para;/g,\n                        '</div><span class=\"hidden\">&para;</span><div>')\n            + '</div>';\n  return [html1, html2];\n}\n\nfunction setLineTypes() {\n  $('#file0-container .file-diff > div').each(function () {\n    var spans = $(this).children();\n    var displayed = [];\n    for (var i = 0; i < spans.length; i++) {\n      if (!$(spans[i]).hasClass('ins'))\n        displayed.push(spans[i])\n    }\n    if (displayed.length == 0) {\n      $(this).addClass('blank');\n      $(this).prepend('<div class=\"expand\"></div>');\n    }\n    $(this).has('.del').addClass('del');\n    $(this).has('.ins').addClass('ins');\n  });\n  $('#file1-container .file-diff > div').each(function () {\n    var spans = $(this).children();\n    var displayed = [];\n    for (var i = 0; i < spans.length; i++) {\n      if (!$(spans[i]).hasClass('del'))\n        displayed.push(spans[i])\n    }\n    if (displayed.length == 0) {\n      $(this).addClass('blank');\n    }\n    $(this).has('.del').addClass('del');\n    $(this).has('.ins').addClass('ins');\n  });\n\n  $('.file-diff > div').remove('.blank.ins');\n  $('.file-diff > div').remove('.blank.del');\n\n  $('.file-diff > div').last().remove('.blank');\n}\n\nfunction isBlankLine(lineDiv, realLineNum) {\n  if ($(lineDiv).attr('class') && !realLineNum) {\n    var realLine = getRealLine(lineDiv);\n  } else {\n    var realLine = 'realLine-' + realLineNum;\n  }\n  return ( $(lineDiv).hasClass('blank')\n           && !$(lineDiv).hasClass('fix') \n           && !$(lineDiv).hasClass('correct')\n         )\n         || ( $(lineDiv).hasClass('fix')\n              && ($('#file0-container .' + realLine).hasClass('blank'))\n            )\n         || ( $(lineDiv).hasClass('correct')\n              && ($('#file1-container .' + realLine).hasClass('blank'))\n            )\n         || $(lineDiv).hasClass('collapsed-num');\n}\n\nfunction setLineNums() {\n  files = [0, 1];\n  for (var i = 0; i < files.length; i++) {\n    var lineNum = 1;\n    var realLineNum = 1;\n    $('.file-diff.' + files[i] + ' > div').each(function() {\n      if (!isBlankLine(this, realLineNum)) {\n        $(this).html('<div class=\"text orig\">' + $(this).html() + '</div>');\n        $(this).prepend('<div class=\"lineNum\">' + lineNum + '</div>');\n        if ($(this).parent().hasClass('0'))\n          $(this).prepend('<div class=\"expand\"></div>');\n        lineNum += 1;\n      }\n      $(this).addClass('realLine-' + realLineNum);\n      realLineNum += 1;\n    });\n  }\n}\n\nfunction resetLineNums() {\n  var files = [0, 1];\n  $('.file-diff > div > div.lineNum').remove();\n  for (var i = 0; i < files.length; i++) {\n    var lineNum = 1;\n    var realLineNum = 1;\n    $('.file-diff.' + files[i] + ' > div').each(function() {\n      if (!isBlankLine(this, realLineNum)) {\n        $(this).prepend('<div class=\"lineNum\">' + lineNum + '</div>');\n        lineNum += 1;\n      }\n      realLineNum += 1;\n    });\n  }\n}\n\nfunction setArrowsAndChecks() {\n  var numChunks = 0;\n  var arrow = '<div class=\"arrow\"></div>';\n  var check = '<div class=\"check\"></div>';\n  var cont = 0;\n  $('#arrow-container').html('');\n  $('#check-container').html('');\n  var lines = $('.file-diff.0').children('div');\n  for (var j =  0; j < lines.length; j++) {\n    var $line = $(lines[j]);\n    if ( $line.hasClass('ins')\n         || $line.hasClass('del')\n         || $line.hasClass('blank')\n       ) {\n      if (cont == 0) numChunks += 1;\n      cont += 1;\n    }\n    else if (cont > 0) {\n      insertArrowAndCheck(cont, numChunks);\n      cont = 0;\n      $('#arrow-container').append(arrow);\n      $('#check-container').append(check);\n    }\n    else {\n      $('#arrow-container').append(arrow);\n      $('#check-container').append(check);\n    }\n  }\n  if (cont > 0) insertArrowAndCheck(cont, numChunks);\n  setArrowClicks();\n  setCheckClicks();\n}\n\nfunction insertArrowAndCheck(cont, numChunks) {\n  var mid = (cont / 2) | 0;\n  var arrow = '<div class=\"arrow\"></div>';\n  var check = '<div class=\"check\"></div>';\n  for (var k = 0; k < mid; k++) {\n    $('#arrow-container').append(arrow);\n    $('#check-container').append(check);\n  }\n  $('#arrow-container').append('<div class=\"holder hidden '\n                               + 'chunk-' + numChunks + '\"></div>');\n  $('#check-container').append('<div class=\"holder hidden '\n                               + 'chunk-' + numChunks + '\"></div>');\n  $('#arrow-container').append('<div class=\"arrow visible '\n                               + 'chunk-' + numChunks + '\"></div>');\n  $('#arrow-container').append('<div class=\"undo visible hidden '\n                               + 'chunk-' + numChunks + '\"></div>');\n  $('#check-container').append('<div class=\"check visible '\n                               + 'chunk-' + numChunks + '\"></div>');\n  $('#check-container').append('<div class=\"undo visible hidden '\n                               + 'chunk-' + numChunks + '\"></div>');\n  for (var k = mid + 1; k < cont; k++) {\n    $('#arrow-container').append(arrow);\n    $('#check-container').append(check);\n  }\n}\n\nfunction setNumDiffs(set) {\n  var diffChunks = numDiffChunks(set);\n  if (diffChunks == 1)\n    $('#num-diffs').html(diffChunks + ' conflict');\n  else\n    $('#num-diffs').html(diffChunks + ' conflicts');\n}\n\nfunction numDiffChunks(set) {\n  var files = [0, 1];\n  var numChunks = [0, 0];\n  for (var i = 0; i < files.length; i++) {\n    var cont = 0;\n    var lines = $('.file-diff.' + files[i]).children('div');\n    for (var j =  0; j < lines.length; j++) {\n      var $line = $(lines[j]);\n      if (( $line.hasClass('ins') ||\n            $line.hasClass('del') ||\n            $line.hasClass('blank')\n          ) && !$line.hasClass('fix')\n            && !$line.hasClass('correct')) {\n        if (cont == 0) {\n          numChunks[files[i]] += 1;\n          $line.addClass('first');\n        }\n        cont += 1;\n        if (set) {\n          $line.addClass('chunk');\n          $line.addClass('chunk-' + numChunks[files[i]]);\n\t      }\n      } else if (cont > 0) {\n        cont = 0;\n        $(lines[j-1]).addClass('last');\n      }\n    }\n    if (cont > 0) $(lines[lines.length - 1]).addClass('last');\n  }\n  totalChunks = Math.max(numChunks[0], numChunks[1]);\n  if (selectedChunk == 0)\n    selectChunk(0);\n  return totalChunks;\n}\n\nfunction selectChunk(chunkNum) {\n  $('#next-chunk').removeClass('disabled');\n  $('#prev-chunk').removeClass('disabled');\n  if (chunkNum > totalChunks)\n    $('#next-chunk').addClass('disabled');\n  if (chunkNum < 1)\n    $('#prev-chunk').addClass('disabled')\n  if ((chunkNum >= 0) && (chunkNum <= totalChunks + 1)) {\n    selectedChunk = chunkNum;\n    $('.file-diff div').removeClass('selected-chunk');\n    $('.chunk-' + chunkNum).addClass('selected-chunk');\n    if ((chunkNum == 0) || (chunkNum == 1))\n      $('.file-diff').scrollTop(0);\n    else if (chunkNum == totalChunks + 1)\n      $('.file-diff').scrollTop($('.file-diff').scrollHeight);\n    else\n      $('.file-diff').scrollTop($('.file-diff').scrollTop()\n                                + $('.chunk-' + chunkNum).position().top - 80);\n  }\n}\n\nfunction selectNextChunk() {\n  var chunkNum = selectedChunk + 1;\n  while ( chunkNum <= totalChunks  \n          && ( $('.chunk-' + chunkNum).hasClass('fix')\n               || $('.chunk-' + chunkNum).hasClass('correct')\n             )\n        )\n    chunkNum += 1;\n  selectChunk(chunkNum);\n}\n\nfunction selectPrevChunk() {\n  var chunkNum = selectedChunk - 1;\n  while ( chunkNum > 0  \n          && ( $('.chunk-' + chunkNum).hasClass('fix')\n               || $('.chunk-' + chunkNum).hasClass('correct')\n             )\n        )\n    chunkNum -= 1;\n  selectChunk(chunkNum);\n}\n\nfunction setArrowClicks() {\n  $('#arrow-container div.arrow.visible').click(function () {\n    var chunkNum = $(this).attr('class').replace('arrow ', '')\n                                        .replace('visible ', '')\n                                        .split(' ')[0];\n    moveChunk(chunkNum);\n  });\n\n  $('#arrow-container div.undo.visible').click(function () {\n    var chunkNum = $(this).attr('class').replace('undo ', '')\n                                        .replace('visible ', '')\n                                        .split(' ')[0];\n    undoMoveChunk(chunkNum);\n  });\n}\n\nfunction setCheckClicks() {\n  $('#check-container div.check.visible').click(function () {\n    var chunkNum = $(this).attr('class').replace('check ', '')\n                                        .replace('visible ', '')\n                                        .split(' ')[0];\n    checkRight(chunkNum);\n  });\n\n  $('#check-container div.undo.visible').click(function () {\n    var chunkNum = $(this).attr('class').replace('undo ', '')\n                                        .replace('visible ', '')\n                                        .split(' ')[0];\n    undoCheckRight(chunkNum);\n  });\n}\n\nfunction createCollapsibleMatches() {\n  var lines1 = $('.file-diff.0').children('div');\n  var lines2 = $('.file-diff.1').children('div');\n  var arrows = $('#arrow-container').children('div.arrow');\n  var checks = $('#check-container').children('div.check');\n  var numContMatches = 0;\n  for (var i = 0; i < lines1.length; i++) {\n    if ( !$(lines1[i]).hasClass('ins') &&\n         !$(lines1[i]).hasClass('del') &&\n         !$(lines1[i]).hasClass('blank')\n       ) {\n      numContMatches += 1;\n    } else {\n      collapse(lines1, lines2, arrows, checks, numContMatches, i)\n      numContMatches = 0;\n    }\n  }\n  collapse(lines1, lines2, arrows, checks, numContMatches, lines1.length);\n\n  $('.collapsed-num > .plus').click(function () {\n    var collapsedNumClass = $(this).attr('class').split(' ')[0];\n    var $collapsedNum = $('div.' + collapsedNumClass);\n    expandSection($collapsedNum);\n  });\n\n  $('.minus').click(function() {\n    var collapsedNumClass = $(this).parent().attr('class').split(' ')[2];\n    var $collapsedNum = $('div.' + collapsedNumClass);\n    collapseSection($collapsedNum);\n  });\n  numCollapsed = totalCollapsible;\n  if (numCollapsed > 0)\n    $('#expand-all').removeClass('disabled');\n}\n\nfunction collapse(lines1, lines2, arrows, checks, numContMatches, i) {\n  totalCollapsible += 1;\n  if (numContMatches > 10) {\n    var firstCol = i - numContMatches + 5;\n    var lastCol = i - 5;\n    var numCol = lastCol - firstCol;\n    var firstLine = firstCol + '-line';\n    for (var l = firstCol; l < lastCol; l++) {\n      $(lines1[l]).addClass('hidden collapsible ' + firstLine);\n      $(lines2[l]).addClass('hidden collapsible ' + firstLine);\n      $(arrows[l]).addClass('hidden collapsible ' + firstLine);\n      $(checks[l]).addClass('hidden collapsible ' + firstLine);\n    }\n    $(lines1[firstCol]).before('<div class=\"collapsed-num ' + firstLine + '\">'\n                               + '<div class=\"' + firstLine + ' expand plus\"></div>'\n                               + numCol + ' lines collapsed' + '</div>');\n    $(lines2[firstCol]).before('<div class=\"collapsed-num ' + firstLine + '\">'\n                               + numCol + ' lines collapsed' + '</div>');\n    $(arrows[firstCol]).before('<div class=\"arrow collapsed-num '\n                               + firstLine + '\"></div>');\n    $(checks[firstCol]).before('<div class=\"check collapsed-num '\n                               + firstLine + '\"></div>');\n    $(lines1[firstCol]).children(':first').addClass('minus');\n  }\n}\n\nfunction moveChunk(chunkNum) {\n  var lines1 = $('.file-diff.0').children('div.' + chunkNum);\n  var lines2 = $('.file-diff.1').children('div.' + chunkNum);\n  for (var i = 0; i < lines1.length; i++) {\n    var realLineNum = getRealLine(lines1[i]);\n    var text = '';\n    if ($('.file-diff.0 .' + realLineNum).children('.text.orig').length > 0)\n      text = $('.file-diff.0 .' + realLineNum + ' > div.text').html();\n    var div = '<div class=\"merged text\">' + text + '</div>';\n    $('.file-diff.1 > .' + realLineNum + ' > .text.orig').addClass('hidden');\n    $('.file-diff.1 > .' + realLineNum).append(div);\n    $('.file-diff.0 > .' + realLineNum).addClass('fix');\n    $('.file-diff.1 > .' + realLineNum).addClass('fix');\n  }\n  $('#arrow-container .arrow.' + chunkNum).addClass('hidden');\n  $('#check-container .check.' + chunkNum).addClass('hidden');\n  $('#arrow-container .undo.' + chunkNum).removeClass('hidden');\n  $('#check-container .holder.' + chunkNum).removeClass('hidden');\n  resetLineNums();\n  var numChunks = totalChunks - 1;\n  if (numChunks == 1)\n    $('#num-diffs').html(numChunks + ' conflict');\n  else\n    $('#num-diffs').html(numChunks + ' conflicts');\n  var text = getText(1);\n  saveFile(text, 'file1.txt');\n  var num = parseInt(chunkNum.slice(6));\n  if (selectedChunk == num)\n    selectNextChunk();\n}\n\nfunction undoMoveChunk(chunkNum) {\n  var lines1 = $('.file-diff.0').children('div.' + chunkNum);\n  var lines2 = $('.file-diff.1').children('div.' + chunkNum);\n  for (var i = 0; i < lines1.length; i++) {\n    var lineNum = getRealLine(lines1[i]);\n    $('.file-diff.1 > .' + lineNum + ' > .text.orig').removeClass('hidden');\n    $('.file-diff.1 > .' + lineNum + ' > .merged').remove();\n    $('.file-diff.0 > .' + lineNum).removeClass('fix');\n    $('.file-diff.1 > .' + lineNum).removeClass('fix');\n  }\n  $('#arrow-container .arrow.' + chunkNum).removeClass('hidden');\n  $('#check-container .check.' + chunkNum).removeClass('hidden');\n  $('#arrow-container .undo.' + chunkNum).addClass('hidden');\n  $('#check-container .holder.' + chunkNum).addClass('hidden');\n  $('#arrow-container .holder.' + chunkNum).addClass('hidden');\n  resetLineNums();\n  var numChunks = totalChunks + 1;\n  if (numChunks == 1)\n    $('#num-diffs').html(numChunks + ' conflict');\n  else\n    $('#num-diffs').html(numChunks + ' conflicts');\n  var text = getText(1);\n  saveFile(text, 'file1.txt');\n  var num = parseInt(chunkNum.slice(6));\n  selectChunk(num);\n}\n\nfunction checkRight(chunkNum) {\n  var lines1 = $('.file-diff.0').children('div.' + chunkNum);\n  var lines2 = $('.file-diff.1').children('div.' + chunkNum);\n  for (var i = 0; i < lines1.length; i++) {\n    var realLineNum = getRealLine(lines1[i]);\n    var text = '';\n    if ($('.file-diff.1 .' + realLineNum).children('.text.orig').length > 0)\n      text = $('.file-diff.1 .' + realLineNum + ' > div.text').html();\n    var div = '<div class=\"merged text\">' + text + '</div>';\n    $('.file-diff.0 > .' + realLineNum + ' > .text.orig').addClass('hidden');\n    $('.file-diff.0 > .' + realLineNum).append(div);\n    $('.file-diff.0 > .' + realLineNum).addClass('correct');\n    $('.file-diff.1 > .' + realLineNum).addClass('correct');\n  }\n  $('#arrow-container .arrow.' + chunkNum).addClass('hidden');\n  $('#check-container .check.' + chunkNum).addClass('hidden');\n  $('#check-container .undo.' + chunkNum).removeClass('hidden');\n  $('#arrow-container .holder.' + chunkNum).removeClass('hidden');\n  resetLineNums();\n  var numChunks = totalChunks - 1;\n  if (numChunks == 1)\n    $('#num-diffs').html(numChunks + ' conflict');\n  else\n    $('#num-diffs').html(numChunks + ' conflicts');\n  var text = getText(0);\n  saveFile(text, 'file0.txt');\n  var num = parseInt(chunkNum.slice(6));\n  if (selectedChunk == num)\n    selectNextChunk();\n}\n\nfunction undoCheckRight(chunkNum) {\n  var lines1 = $('.file-diff.0').children('div.' + chunkNum);\n  var lines2 = $('.file-diff.1').children('div.' + chunkNum);\n  for (var i = 0; i < lines1.length; i++) {\n    var lineNum = getRealLine(lines1[i]);\n    $('.file-diff.0 > .' + lineNum + ' > .text.orig').removeClass('hidden');\n    $('.file-diff.0 > .' + lineNum + ' > .merged').remove();\n    $('.file-diff.0 > .' + lineNum).removeClass('correct');\n    $('.file-diff.1 > .' + lineNum).removeClass('correct');\n  }\n  $('#arrow-container .arrow.' + chunkNum).removeClass('hidden');\n  $('#check-container .check.' + chunkNum).removeClass('hidden');\n  $('#check-container .undo.' + chunkNum).addClass('hidden');\n  $('#check-container .holder.' + chunkNum).addClass('hidden');\n  $('#arrow-container .holder.' + chunkNum).addClass('hidden');\n  resetLineNums();\n  var numChunks = totalChunks + 1;\n  if (numChunks == 1)\n    $('#num-diffs').html(numChunks + ' conflict');\n  else\n    $('#num-diffs').html(numChunks + ' conflicts');\n  var text = getText(0);\n  saveFile(text, 'file0.txt');\n  var num = parseInt(chunkNum.slice(6));\n  selectChunk(num);\n}\n\nfunction expandAllMatches() {\n  numCollapsed = 0;\n  $('div.collapsible').removeClass('hidden');\n  $('div.collapsed-num').addClass('hidden');\n  $('#expand-all').addClass('disabled');\n  $('#collapse-all').removeClass('disabled');\n}\n\nfunction collapseAllMatches() {\n  numCollapsed = totalCollapsible;\n  $('div.collapsible').addClass('hidden');\n  $('div.collapsed-num').removeClass('hidden');\n  $('.plus').removeClass('hidden');\n  $('#expand-all').removeClass('disabled');\n  $('#collapse-all').addClass('disabled');\n}\n\nfunction expandSection($collapsedNum) {\n  numCollapsed -= 1;\n  var classes = $collapsedNum.attr('class');\n  var c = classes.replace('collapsed-num ', '').split(' ')[0];\n  $collapsedNum.addClass('hidden');\n  $('div.collapsible.' + c).removeClass('hidden');\n  $('#collapse-all').removeClass('disabled');\n  if (numCollapsed == 0)\n    $('#expand-all').addClass('disabled');\n}\n\nfunction collapseSection($collapsedNum) {\n  numCollapsed += 1;\n  var classes = $collapsedNum.attr('class');\n  var c = classes.replace('collapsible ', '')\n                 .replace('collapsed-num ', '')\n                 .split(' ')[0];\n  $collapsedNum.removeClass('hidden');\n  $('div.collapsible.' + c).addClass('hidden');\n  $('#expand-all').removeClass('disabled');\n  if (numCollapsed == totalCollapsible)\n    $('#collapse-all').addClass('disabled');\n}\n"
  },
  {
    "path": "_archive/apps/samples/diff/js/filesystem.js",
    "content": "/**\n * Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\nvar FILE_SIZE = 1024 * 1024;\nvar displayNames = [null, null];\nvar paths = {};\nvar fileEntries = [null, null];\nvar texts = [null, null];\nvar urlNum = null;\nvar badURL = false;\n\nvar fileHistory = {};\n\n$(document).ready(function() {\n\n  readFileName('name0.txt', 0);\n  readFileName('name1.txt', 1);\n\n  $('#left-side .button.new-diff').click(function() {\n    $('#modal-shield').removeClass('hidden');\n    $('.modal-dialog.new-diff').removeClass('hidden').addClass('visible');\n  });\n\n  $('.close-button').click(function() {\n    $('.modal-dialog').addClass('hidden').removeClass('visible');\n    $('#modal-shield').addClass('hidden');\n    $('.enter-url input').val('');\n    $('.error-message').removeClass('visible');\n    $('.url').removeClass('form-error');\n    $('input.url').val('');\n  });\n\n  $('.button.cancel').click(function() {\n    $('.close-button').click();\n  });\n\n  $('.modal-dialog.new-diff .button.submit').click(function() {\n    submitDiffs();\n  });\n\n  $('.modal-dialog.new-diff .choose-file.0').click(function() {\n    selectFile(0);\n  });\n  $('.modal-dialog.new-diff .choose-file.1').click(function () {\n    selectFile(1);\n  });\n\n  $('.edit').click(function() {\n    var text1 = getText(1);\n    $('#arrow-container').addClass('arrow-edit');\n    $('#check-container').addClass('check-edit');\n    $('.file-diff.1').addClass('hidden');\n    $('textarea.diff-text').val(text1);\n    $('.diff-text#editor').removeClass('hidden');\n    $('.edit').addClass('hidden');\n    $('.save').addClass('hidden');\n    $('#num-diffs').addClass('hidden');\n    $('.done').removeClass('hidden');\n  });\n\n  $('.done').click(function() {\n    texts[1] = $('textarea.diff-text').val();\n    saveFile(texts[1], 'file1.txt');\n    computeDiff(texts[0], texts[1]);\n    $('#arrow-container').removeClass('arrow-edit');\n    $('#check-container').removeClass('check-edit');\n    $('.file-diff.1').removeClass('hidden');\n    $('textarea.diff-text').addClass('hidden');\n    $('.edit').removeClass('hidden');\n    $('#num-diffs').removeClass('hidden');\n    $('.done').addClass('hidden');\n    $('.save').removeClass('hidden');\n  });\n\n  $('.save').click(function() {\n    saveFileAs();\n  });\n\n  $('input.url').blur(function() {\n    urlNum = $(this).attr('class').split(' ')[1];\n    selectURL();\n  });\n\n  $('.menubutton').click(function(event) {\n    if (!$(this).hasClass('menulist')) {\n      event.preventDefault();\n      event.stopPropagation();\n      $(this).children('ul.menulist').addClass('shown');\n    }\n  });\n\n  $(document).click(function() {\n    $('ul.menulist').removeClass('shown');\n  });\n\n  $.ajaxSetup({\n    error: function(xhr) {\n      badURL = true;\n      message = ajaxErrorMessage(xhr);\n      $('.error-message.' + urlNum).text(message);\n      $('.error-message.' + urlNum).addClass('visible');\n      $('input.url.' + urlNum).addClass('form-error');\n    }\n  });\n\n});\n\nfunction registerMenulistitemClicks() {\n  $('li.menulistitem').click(function() {\n    if ($(this).hasClass('choose-new-file')) {\n      var fileNum = parseInt($(this).parent().attr('class').split(' ')[1]);\n      selectFile(fileNum, true);\n    }\n    else if (!$(this).hasClass('selected')) {\n      var fileNum = parseInt($(this).parent().attr('class').split(' ')[1]);\n      var fileName = $(this).children('.file-name').text();\n      $(this).parent().children('li.menulistitem').removeClass('selected');\n      $(this).addClass('selected');\n      displayNames[fileNum] = fileName;\n      texts[fileNum] = fileHistory[paths[fileName]];\n      setFileName(fileNum);\n      saveFile(texts[fileNum], 'file' + fileNum + '.txt');\n      saveFile(paths[displayNames[fileNum]], 'name' + fileNum + '.txt');\n      computeDiff(texts[0], texts[1]);\n    }\n    $('.menulist').removeClass('shown');\n  });\n\n  $('li.menulistitem .delete').click(function() {\n    var name = $(this).parent().children('.file-name').text();\n    var path = paths[name];\n    delete fileHistory[path];\n    chrome.storage.local.set({'fileHistory': fileHistory});\n    $('li.menulistitem').each(function() {\n      if ($(this).children('.file-name').text() == name)\n        $(this).remove();\n    })\n  });\n}\n\nfunction selectURL() {\n  $('.error-message.' + urlNum).removeClass('visible');\n  $('.url.' + urlNum).removeClass('form-error');\n  var url = $('.modal-dialog.new-diff input.url.' + urlNum).val();\n  if (url != '') {\n    if (!(url.slice(0, 4) == 'http'))\n      url = 'http://' + url;\n    $.get(url,\n      function(text) {\n        var urlSecs = url.split('/');\n        displayNames[urlNum] = urlSecs[urlSecs.length-1];\n        paths[displayNames[urlNum]] = url;\n        badURL = false;\n        texts[urlNum] = text;\n        rememberFile(fileNum);\n        var name = 'file' + urlNum + '.txt';\n        saveFile(text, name);\n        saveFile(paths[displayNames[urlNum]], 'name' + urlNum + '.txt');\n      },\n      'html'\n    );\n  } else {\n    badURL = false;\n  }\n}\n\nfunction selectFile(fileNum, chooseNew) {\n  chrome.fileSystem.chooseEntry({'type': 'openFile'}, function(fileEntry) {\n    fileEntries[fileNum] = fileEntry;\n    chrome.fileSystem.getDisplayPath(fileEntry, function(path) {\n      var pathList = path.split('/');\n      var l = pathList.length - 1;\n      displayNames[fileNum] = pathList[l];\n      paths[displayNames[fileNum]] = path;\n      $('.modal-dialog.new-diff .file-name.' + fileNum).text(displayNames[fileNum]);\n      fileEntries[fileNum].file(function(file) {\n        var reader = new FileReader();\n        reader.onloadend = function(e) {\n          $('.error-message.' + fileNum).removeClass('visible');\n          $('.url.' + fileNum).removeClass('form-error');\n          $('input.url.' + fileNum).val('');\n          texts[fileNum] = this.result;\n          rememberFile(fileNum);\n          var name = 'file' + fileNum + '.txt';\n          saveFile(texts[fileNum], name);\n          saveFile(paths[displayNames[fileNum]], 'name' + fileNum + '.txt');\n          if (chooseNew)\n            chooseNewFile(fileNum);\n        };\n        reader.readAsText(file);\n      }, errorHandler);\n    });\n  });\n}\n\nfunction getExtension(fileName) {\n  var parts = fileName.split('.');\n  return parts[parts.length - 1];\n}\n\nfunction isPatch(fileName) {\n  return getExtension(fileName).toLowerCase() == 'patch';\n}\n\nfunction addToMenulistDisplayed(listNum, displayNum, selected) {\n  var name = displayNames[displayNum];\n  var path = paths[displayNames[displayNum]].split('/').slice(-5, -2).join('/');\n  $('ul.menulist.' + listNum).append(\n      '<li class=\"menulistitem ' + selected + '\">'\n      + '<span class=\"file-name\">' + name + '</span>'\n      + '<span class=\"file-name-info\"> - ' + path + '</span>'\n      + '<span class=\"delete\"></span></li>');\n}\n\nfunction addToMenulist(path) {\n  var pathSecs = path.split('/');\n  var name = pathSecs[pathSecs.length - 1];\n  var displayPath = pathSecs.slice(-5, -2).join('/');\n  paths[name] = path;\n  for (var listNum = 0; listNum < 2; listNum++) {\n    $('ul.menulist.' + listNum).append(\n        '<li class=\"menulistitem\">'\n        + '<span class=\"file-name\">' + name + '</span>'\n        + '<span class=\"file-name-info\"> - ' + displayPath + '</span>'\n        + '<span class=\"delete\"></span></li>');\n  }\n}\n\nfunction setFileName(fileNum) {\n  var name = displayNames[fileNum];\n  var path = paths[displayNames[fileNum]].split('/').slice(-5, -2).join('/');\n  $('#file' + fileNum + '-container .label.file-name').html(\n      '<span class=\"file-name\">' + name + '</span>'\n      + '<span class=\"file-name-info\"> - ' + path + '</span>');\n}\n\nfunction createDropdown() {\n  $('ul.menulist').html('<li class=\"menulistitem choose-new-file\">Choose File</li>');\n  for (path in fileHistory) {\n    if (path == paths[displayNames[0]]) {\n      addToMenulistDisplayed(0, 0, 'selected');\n      addToMenulistDisplayed(0, 1, '');\n    }\n    else if (path == paths[displayNames[1]]) {\n      addToMenulistDisplayed(1, 0, '');\n      addToMenulistDisplayed(1, 1, 'selected');\n    }\n    else {\n      addToMenulist(path);\n    }\n  }\n  registerMenulistitemClicks();\n}\n\nfunction rememberFile(fileNum) {\n  fileHistory[paths[displayNames[fileNum]]] = texts[fileNum];\n  chrome.storage.local.set({'fileHistory': fileHistory});\n  $('ul.menulist.' + fileNum + ' .menulistitem').removeClass('selected');\n  addToMenulistDisplayed(fileNum, fileNum, 'selected');\n  addToMenulistDisplayed(((fileNum + 1) % 2), fileNum, '');\n  registerMenulistitemClicks();\n}\n\nfunction selectRememberedFile(fileNum, fileName) {\n  texts[fileNum] = fileHistory[paths[fileName]];\n  displayNames[fileNum] = fileName;\n  submitDiffs();\n}\n\nfunction submitDiffs() {\n  if (texts[0] && texts[1] && !badURL) {\n    setFileName(0);\n    setFileName(1);\n    if (isPatch(displayNames[1])) {\n      texts[1] = patchToFile2(texts[0], texts[1]);\n      rememberFile(1);\n      saveFile(texts[1], 'file1.txt');\n    }\n    computeDiff(texts[0], texts[1]);\n    $('.modal-dialog.new-diff .close-button').click();\n    $('.button.edit').removeClass('hidden');\n    $('.button.save').removeClass('hidden');\n  }\n  if (!texts[0]) {\n    $('.error-message.0').text('Please select a file or URL.');\n    $('.error-message.0').addClass('visible');\n  }\n  if (!texts[1]) {\n    $('.error-message.1').text('Please select a file or URL.');\n    $('.error-message.1').addClass('visible');\n  }\n}\n\nfunction chooseNewFile(fileNum) {\n  setFileName(fileNum);\n  if (texts[0] && texts[1]) {\n    if ((fileNum == 1) && isPatch(displayNames[1])) {\n      texts[1] = patchToFile2(texts[0], texts[1]);\n      rememberFile(1);\n      saveFile(texts[1], 'file1.txt');\n    }\n    computeDiff(texts[0], texts[1]);\n  }\n  else\n    $('.file-diff.' + fileNum).text(texts[fileNum]);\n  if (fileNum == 1) {\n    $('.button.edit').removeClass('hidden');\n    $('.button.save').removeClass('hidden');\n  }\n}\n\nfunction saveFile(content, fileName) {\n  window.webkitRequestFileSystem(\n    window.PERSISTENT,\n    FILE_SIZE,\n    function(fs) {\n      fs.root.getFile(fileName, {create: true}, function(fileEntry) {\n        save(fileEntry, content);\n      }, errorHandler);\n    },errorHandler);\n}\n\nfunction saveFileAs() {\n  chrome.fileSystem.chooseEntry({'type': 'saveFile'}, function(fileEntry) {\n    save(fileEntry, getText(1));\n  });\n}\n\nfunction save(fileEntry, content) {\n  fileEntry.createWriter(function(fileWriter) {\n    fileWriter.onwriteend = function(e) {\n      fileWriter.onwriteend = null;\n      fileWriter.truncate(content.length);\n    };\n    fileWriter.onerror = function(e) {\n      console.log('Write failed: ' + e.toString());\n    };\n    var blob = new Blob([content], {'type': 'text/plain'});\n    fileWriter.write(blob);\n  }, errorHandler);\n}\n\nfunction readFile(fileName, fileNum) {\n  window.webkitRequestFileSystem(\n    window.PERSISTENT,\n    FILE_SIZE,\n    function(fs) {\n      fs.root.getFile(fileName, {}, function(fileEntry) {\n        fileEntry.file(function(file) {\n          var reader = new FileReader();\n          reader.onloadend = function(e) {\n            texts[fileNum] = this.result;\n            if (texts[0] && texts[1]) {\n              chrome.storage.local.get(function(items) {\n                for (key in items['fileHistory'])\n                  fileHistory[key] = items['fileHistory'][key];\n                createDropdown();\n                computeDiff(texts[0], texts[1]);\n              });\n            }\n          };\n          reader.readAsText(file);\n        }, errorHandler);\n      }, errorHandler);\n    }, errorHandler);\n}\n\nfunction readFileName(fileName, fileNum) {\n  window.webkitRequestFileSystem(\n    window.PERSISTENT,\n    FILE_SIZE,\n    function(fs) {\n      fs.root.getFile(fileName, {}, function(fileEntry) {\n        fileEntry.file(function(file) {\n          var reader = new FileReader();\n          reader.onloadend = function(e) {\n            path = this.result;\n            var pathList = path.split('/');\n            var l = pathList.length - 1;\n            displayNames[fileNum] = pathList[l];\n            paths[displayNames[fileNum]] = path;\n            setFileName(fileNum);\n            readFile('file' + fileNum + '.txt', fileNum);\n          };\n          reader.readAsText(file);\n        }, errorHandler);\n      }, errorHandler);\n    }, errorHandler);\n}\n\nfunction errorHandler(e) {\n  switch (e.code) {\n    case FileError.QUOTA_EXCEEDED_ERR:\n      msg = 'QUOTA_EXCEEDED_ERR';\n      break;\n    case FileError.NOT_FOUND_ERR:\n      msg = 'NOT_FOUND_ERR';\n      break;\n    case FileError.SECURITY_ERR:\n      msg = 'SECURITY_ERR';\n      break;\n    case FileError.INVALID_MODIFICATION_ERR:\n      msg = 'INVALID_MODIFICATION_ERR';\n      break;\n    case FileError.INVALID_STATE_ERR:\n      msg = 'INVALID_STATE_ERR';\n      break;\n    default:\n      msg = 'Unknown Error';\n      break;\n  };\n  console.log('Error: ' + msg);\n}\n\n/*\nfunction handleDragOver(event) {\n  event.stopPropagation();\n  event.preventDefault();\n  event.dataTransfer.dropEffect = 'copy';\n}\n\nfunction handleDrop(event) {\n  event.stopPropagation();\n  event.preventDefault();\n  var file = event.dataTransfer.files[0];\n  var fileName = escape(file.name);\n  var fileNum;\n  if ($(this).hasClass('1'))\n    fileNum = 0;\n  else\n    fileNum = 1;\n  setTextFromFile(file, fileName, $(this), fileNum);\n}\n*/\n"
  },
  {
    "path": "_archive/apps/samples/diff/lib/diff_match_patch.js",
    "content": "(function(){function diff_match_patch(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=0.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=0.5;this.Patch_Margin=4;this.Match_MaxBits=32}\ndiff_match_patch.prototype.diff_main=function(a,b,c,d){\"undefined\"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error(\"Null input. (diff_main)\");if(a==b)return a?[[0,a]]:[];\"undefined\"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b),c=a.substring(0,f),a=a.substring(f),b=b.substring(f),f=this.diff_commonSuffix(a,b),g=a.substring(a.length-f),a=a.substring(0,a.length-f),b=b.substring(0,b.length-f),a=this.diff_compute_(a,\nb,e,d);c&&a.unshift([0,c]);g&&a.push([0,g]);this.diff_cleanupMerge(a);return a};\ndiff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[[1,b]];if(!b)return[[-1,a]];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);if(-1!=g)return c=[[1,e.substring(0,g)],[0,f],[1,e.substring(g+f.length)]],a.length>b.length&&(c[0][0]=c[2][0]=-1),c;if(1==f.length)return[[-1,a],[1,b]];return(e=this.diff_halfMatch_(a,b))?(f=e[0],a=e[1],g=e[2],b=e[3],e=e[4],f=this.diff_main(f,g,c,d),c=this.diff_main(a,b,c,d),f.concat([[0,e]],c)):c&&100<a.length&&100<b.length?this.diff_lineMode_(a,\nb,d):this.diff_bisect_(a,b,d)};\ndiff_match_patch.prototype.diff_lineMode_=function(a,b,c){var d=this.diff_linesToChars_(a,b),a=d.chars1,b=d.chars2,d=d.lineArray,a=this.diff_main(a,b,!1,c);this.diff_charsToLines_(a,d);this.diff_cleanupSemantic(a);a.push([0,\"\"]);for(var e=d=b=0,f=\"\",g=\"\";b<a.length;){switch(a[b][0]){case 1:e++;g+=a[b][1];break;case -1:d++;f+=a[b][1];break;case 0:if(1<=d&&1<=e){a.splice(b-d-e,d+e);b=b-d-e;d=this.diff_main(f,g,!1,c);for(e=d.length-1;0<=e;e--)a.splice(b,0,d[e]);b+=d.length}d=e=0;g=f=\"\"}b++}a.pop();return a};\ndiff_match_patch.prototype.diff_bisect_=function(a,b,c){for(var d=a.length,e=b.length,f=Math.ceil((d+e)/2),g=f,h=2*f,j=Array(h),i=Array(h),k=0;k<h;k++)j[k]=-1,i[k]=-1;j[g+1]=0;i[g+1]=0;for(var k=d-e,p=0!=k%2,q=0,s=0,o=0,v=0,u=0;u<f&&!((new Date).getTime()>c);u++){for(var n=-u+q;n<=u-s;n+=2){var l=g+n,m;m=n==-u||n!=u&&j[l-1]<j[l+1]?j[l+1]:j[l-1]+1;for(var r=m-n;m<d&&r<e&&a.charAt(m)==b.charAt(r);)m++,r++;j[l]=m;if(m>d)s+=2;else if(r>e)q+=2;else if(p&&(l=g+k-n,0<=l&&l<h&&-1!=i[l])){var t=d-i[l];if(m>=\nt)return this.diff_bisectSplit_(a,b,m,r,c)}}for(n=-u+o;n<=u-v;n+=2){l=g+n;t=n==-u||n!=u&&i[l-1]<i[l+1]?i[l+1]:i[l-1]+1;for(m=t-n;t<d&&m<e&&a.charAt(d-t-1)==b.charAt(e-m-1);)t++,m++;i[l]=t;if(t>d)v+=2;else if(m>e)o+=2;else if(!p&&(l=g+k-n,0<=l&&l<h&&-1!=j[l]&&(m=j[l],r=g+m-l,t=d-t,m>=t)))return this.diff_bisectSplit_(a,b,m,r,c)}}return[[-1,a],[1,b]]};\ndiff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d),a=a.substring(c),b=b.substring(d),f=this.diff_main(f,g,!1,e),e=this.diff_main(a,b,!1,e);return f.concat(e)};\ndiff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b=\"\",c=0,f=-1,g=d.length;f<a.length-1;){f=a.indexOf(\"\\n\",c);-1==f&&(f=a.length-1);var q=a.substring(c,f+1),c=f+1;(e.hasOwnProperty?e.hasOwnProperty(q):void 0!==e[q])?b+=String.fromCharCode(e[q]):(b+=String.fromCharCode(g),e[q]=g,d[g++]=q)}return b}var d=[],e={};d[0]=\"\";var f=c(a),g=c(b);return{chars1:f,chars2:g,lineArray:d}};\ndiff_match_patch.prototype.diff_charsToLines_=function(a,b){for(var c=0;c<a.length;c++){for(var d=a[c][1],e=[],f=0;f<d.length;f++)e[f]=b[d.charCodeAt(f)];a[c][1]=e.join(\"\")}};diff_match_patch.prototype.diff_commonPrefix=function(a,b){if(!a||!b||a.charAt(0)!=b.charAt(0))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(f,e)==b.substring(f,e)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};\ndiff_match_patch.prototype.diff_commonSuffix=function(a,b){if(!a||!b||a.charAt(a.length-1)!=b.charAt(b.length-1))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(a.length-e,a.length-f)==b.substring(b.length-e,b.length-f)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};\ndiff_match_patch.prototype.diff_commonOverlap_=function(a,b){var c=a.length,d=b.length;if(0==c||0==d)return 0;c>d?a=a.substring(c-d):c<d&&(b=b.substring(0,c));c=Math.min(c,d);if(a==b)return c;for(var d=0,e=1;;){var f=a.substring(c-e),f=b.indexOf(f);if(-1==f)return d;e+=f;if(0==f||a.substring(c-e)==b.substring(0,e))d=e,e++}};\ndiff_match_patch.prototype.diff_halfMatch_=function(a,b){function c(a,b,c){for(var d=a.substring(c,c+Math.floor(a.length/4)),e=-1,g=\"\",h,j,n,l;-1!=(e=b.indexOf(d,e+1));){var m=f.diff_commonPrefix(a.substring(c),b.substring(e)),r=f.diff_commonSuffix(a.substring(0,c),b.substring(0,e));g.length<r+m&&(g=b.substring(e-r,e)+b.substring(e,e+m),h=a.substring(0,c-r),j=a.substring(c+m),n=b.substring(0,e-r),l=b.substring(e+m))}return 2*g.length>=a.length?[h,j,n,l,g]:null}if(0>=this.Diff_Timeout)return null;\nvar d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.length<d.length)return null;var f=this,g=c(d,e,Math.ceil(d.length/4)),d=c(d,e,Math.ceil(d.length/2)),h;if(!g&&!d)return null;h=d?g?g[4].length>d[4].length?g:d:d:g;var j;a.length>b.length?(g=h[0],d=h[1],e=h[2],j=h[3]):(e=h[0],j=h[1],g=h[2],d=h[3]);h=h[4];return[g,d,e,j,h]};\ndiff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,j=0,i=0;f<a.length;)0==a[f][0]?(c[d++]=f,g=j,h=i,i=j=0,e=a[f][1]):(1==a[f][0]?j+=a[f][1].length:i+=a[f][1].length,e&&e.length<=Math.max(g,h)&&e.length<=Math.max(j,i)&&(a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,d--,f=0<d?c[d-1]:-1,i=j=h=g=0,e=null,b=!0)),f++;b&&this.diff_cleanupMerge(a);this.diff_cleanupSemanticLossless(a);for(f=1;f<a.length;){if(-1==a[f-1][0]&&1==a[f][0]){b=a[f-1][1];c=a[f][1];\nd=this.diff_commonOverlap_(b,c);e=this.diff_commonOverlap_(c,b);if(d>=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,[0,c.substring(0,d)]),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,[0,b.substring(0,e)]),a[f-1][0]=1,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=-1,a[f+1][1]=b.substring(e),f++;f++}f++}};\ndiff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_),c=g&&c.match(diff_match_patch.linebreakRegex_),d=h&&d.match(diff_match_patch.linebreakRegex_),i=c&&a.match(diff_match_patch.blanklineEndRegex_),j=d&&b.match(diff_match_patch.blanklineStartRegex_);\nreturn i||j?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c<a.length-1;){if(0==a[c-1][0]&&0==a[c+1][0]){var d=a[c-1][1],e=a[c][1],f=a[c+1][1],g=this.diff_commonSuffix(d,e);if(g)var h=e.substring(e.length-g),d=d.substring(0,d.length-g),e=h+e.substring(0,e.length-g),f=h+f;for(var g=d,h=e,j=f,i=b(d,e)+b(e,f);e.charAt(0)===f.charAt(0);){var d=d+e.charAt(0),e=e.substring(1)+f.charAt(0),f=f.substring(1),k=b(d,e)+b(e,f);k>=i&&(i=k,g=d,h=e,j=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-1,1),c--),a[c][1]=\nh,j?a[c+1][1]=j:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\\s/;diff_match_patch.linebreakRegex_=/[\\r\\n]/;diff_match_patch.blanklineEndRegex_=/\\n\\r?\\n$/;diff_match_patch.blanklineStartRegex_=/^\\r?\\n\\r?\\n/;\ndiff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,j=!1,i=!1;f<a.length;){if(0==a[f][0])a[f][1].length<this.Diff_EditCost&&(j||i)?(c[d++]=f,g=j,h=i,e=a[f][1]):(d=0,e=null),j=i=!1;else if(-1==a[f][0]?i=!0:j=!0,e&&(g&&h&&j&&i||e.length<this.Diff_EditCost/2&&3==g+h+j+i))a.splice(c[d-1],0,[-1,e]),a[c[d-1]+1][0]=1,d--,e=null,g&&h?(j=i=!0,d=0):(d--,f=0<d?c[d-1]:-1,j=i=!1),b=!0;f++}b&&this.diff_cleanupMerge(a)};\ndiff_match_patch.prototype.diff_cleanupMerge=function(a){a.push([0,\"\"]);for(var b=0,c=0,d=0,e=\"\",f=\"\",g;b<a.length;)switch(a[b][0]){case 1:d++;f+=a[b][1];b++;break;case -1:c++;e+=a[b][1];b++;break;case 0:1<c+d?(0!==c&&0!==d&&(g=this.diff_commonPrefix(f,e),0!==g&&(0<b-c-d&&0==a[b-c-d-1][0]?a[b-c-d-1][1]+=f.substring(0,g):(a.splice(0,0,[0,f.substring(0,g)]),b++),f=f.substring(g),e=e.substring(g)),g=this.diff_commonSuffix(f,e),0!==g&&(a[b][1]=f.substring(f.length-g)+a[b][1],f=f.substring(0,f.length-\ng),e=e.substring(0,e.length-g))),0===c?a.splice(b-d,c+d,[1,f]):0===d?a.splice(b-c,c+d,[-1,e]):a.splice(b-c-d,c+d,[-1,e],[1,f]),b=b-c-d+(c?1:0)+(d?1:0)+1):0!==b&&0==a[b-1][0]?(a[b-1][1]+=a[b][1],a.splice(b,1)):b++,c=d=0,f=e=\"\"}\"\"===a[a.length-1][1]&&a.pop();c=!1;for(b=1;b<a.length-1;)0==a[b-1][0]&&0==a[b+1][0]&&(a[b][1].substring(a[b][1].length-a[b-1][1].length)==a[b-1][1]?(a[b][1]=a[b-1][1]+a[b][1].substring(0,a[b][1].length-a[b-1][1].length),a[b+1][1]=a[b-1][1]+a[b+1][1],a.splice(b-1,1),c=!0):a[b][1].substring(0,\na[b+1][1].length)==a[b+1][1]&&(a[b-1][1]+=a[b+1][1],a[b][1]=a[b][1].substring(a[b+1][1].length)+a[b+1][1],a.splice(b+1,1),c=!0)),b++;c&&this.diff_cleanupMerge(a)};diff_match_patch.prototype.diff_xIndex=function(a,b){var c=0,d=0,e=0,f=0,g;for(g=0;g<a.length;g++){1!==a[g][0]&&(c+=a[g][1].length);-1!==a[g][0]&&(d+=a[g][1].length);if(c>b)break;e=c;f=d}return a.length!=g&&-1===a[g][0]?f:f+(b-e)};\ndiff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=/</g,e=/>/g,f=/\\n/g,g=0;g<a.length;g++){var h=a[g][0],j=a[g][1],j=j.replace(c,\"&amp;\").replace(d,\"&lt;\").replace(e,\"&gt;\").replace(f,\"&para;<br>\");switch(h){case 1:b[g]='<ins style=\"background:#e6ffe6;\">'+j+\"</ins>\";break;case -1:b[g]='<del style=\"background:#ffe6e6;\">'+j+\"</del>\";break;case 0:b[g]=\"<span>\"+j+\"</span>\"}}return b.join(\"\")};\ndiff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;c<a.length;c++)1!==a[c][0]&&(b[c]=a[c][1]);return b.join(\"\")};diff_match_patch.prototype.diff_text2=function(a){for(var b=[],c=0;c<a.length;c++)-1!==a[c][0]&&(b[c]=a[c][1]);return b.join(\"\")};diff_match_patch.prototype.diff_levenshtein=function(a){for(var b=0,c=0,d=0,e=0;e<a.length;e++){var f=a[e][0],g=a[e][1];switch(f){case 1:c+=g.length;break;case -1:d+=g.length;break;case 0:b+=Math.max(c,d),d=c=0}}return b+=Math.max(c,d)};\ndiff_match_patch.prototype.diff_toDelta=function(a){for(var b=[],c=0;c<a.length;c++)switch(a[c][0]){case 1:b[c]=\"+\"+encodeURI(a[c][1]);break;case -1:b[c]=\"-\"+a[c][1].length;break;case 0:b[c]=\"=\"+a[c][1].length}return b.join(\"\\t\").replace(/%20/g,\" \")};\ndiff_match_patch.prototype.diff_fromDelta=function(a,b){for(var c=[],d=0,e=0,f=b.split(/\\t/g),g=0;g<f.length;g++){var h=f[g].substring(1);switch(f[g].charAt(0)){case \"+\":try{c[d++]=[1,decodeURI(h)]}catch(j){throw Error(\"Illegal escape in diff_fromDelta: \"+h);}break;case \"-\":case \"=\":var i=parseInt(h,10);if(isNaN(i)||0>i)throw Error(\"Invalid number in diff_fromDelta: \"+h);h=a.substring(e,e+=i);\"=\"==f[g].charAt(0)?c[d++]=[0,h]:c[d++]=[-1,h];break;default:if(f[g])throw Error(\"Invalid diff operation in diff_fromDelta: \"+\nf[g]);}}if(e!=a.length)throw Error(\"Delta length (\"+e+\") does not equal source text length (\"+a.length+\").\");return c};diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error(\"Null input. (match_main)\");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};\ndiff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return!f.Match_Distance?g?1:e:e+g/f.Match_Distance}if(b.length>this.Match_MaxBits)throw Error(\"Pattern too long for this browser.\");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));for(var j=1<<b.length-1,h=-1,i,k,p=b.length+a.length,q,s=0;s<b.length;s++){i=0;for(k=p;i<k;)d(s,c+\nk)<=g?i=k:p=k,k=Math.floor((p-i)/2+i);p=k;i=Math.max(1,c-k+1);var o=Math.min(c+k,a.length)+b.length;k=Array(o+2);for(k[o+1]=(1<<s)-1;o>=i;o--){var v=e[a.charAt(o-1)];k[o]=0===s?(k[o+1]<<1|1)&v:(k[o+1]<<1|1)&v|(q[o+1]|q[o])<<1|1|q[o+1];if(k[o]&j&&(v=d(s,o-1),v<=g))if(g=v,h=o-1,h>c)i=Math.max(1,2*c-h);else break}if(d(s+1,c)>g)break;q=k}return h};\ndiff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c<a.length;c++)b[a.charAt(c)]=0;for(c=0;c<a.length;c++)b[a.charAt(c)]|=1<<a.length-c-1;return b};\ndiff_match_patch.prototype.patch_addContext_=function(a,b){if(0!=b.length){for(var c=b.substring(a.start2,a.start2+a.length1),d=0;b.indexOf(c)!=b.lastIndexOf(c)&&c.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)d+=this.Patch_Margin,c=b.substring(a.start2-d,a.start2+a.length1+d);d+=this.Patch_Margin;(c=b.substring(a.start2-d,a.start2))&&a.diffs.unshift([0,c]);(d=b.substring(a.start2+a.length1,a.start2+a.length1+d))&&a.diffs.push([0,d]);a.start1-=c.length;a.start2-=c.length;a.length1+=\nc.length+d.length;a.length2+=c.length+d.length}};\ndiff_match_patch.prototype.patch_make=function(a,b,c){var d;if(\"string\"==typeof a&&\"string\"==typeof b&&\"undefined\"==typeof c)d=a,b=this.diff_main(d,b,!0),2<b.length&&(this.diff_cleanupSemantic(b),this.diff_cleanupEfficiency(b));else if(a&&\"object\"==typeof a&&\"undefined\"==typeof b&&\"undefined\"==typeof c)b=a,d=this.diff_text1(b);else if(\"string\"==typeof a&&b&&\"object\"==typeof b&&\"undefined\"==typeof c)d=a;else if(\"string\"==typeof a&&\"string\"==typeof b&&c&&\"object\"==typeof c)d=a,b=c;else throw Error(\"Unknown call format to patch_make.\");\nif(0===b.length)return[];for(var c=[],a=new diff_match_patch.patch_obj,e=0,f=0,g=0,h=d,j=0;j<b.length;j++){var i=b[j][0],k=b[j][1];if(!e&&0!==i)a.start1=f,a.start2=g;switch(i){case 1:a.diffs[e++]=b[j];a.length2+=k.length;d=d.substring(0,g)+k+d.substring(g);break;case -1:a.length1+=k.length;a.diffs[e++]=b[j];d=d.substring(0,g)+d.substring(g+k.length);break;case 0:k.length<=2*this.Patch_Margin&&e&&b.length!=j+1?(a.diffs[e++]=b[j],a.length1+=k.length,a.length2+=k.length):k.length>=2*this.Patch_Margin&&\ne&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}1!==i&&(f+=k.length);-1!==i&&(g+=k.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new diff_match_patch.patch_obj;e.diffs=[];for(var f=0;f<d.diffs.length;f++)e.diffs[f]=d.diffs[f].slice();e.start1=d.start1;e.start2=d.start2;e.length1=d.length1;e.length2=d.length2;b[c]=e}return b};\ndiff_match_patch.prototype.patch_apply=function(a,b){if(0==a.length)return[b,[]];var a=this.patch_deepCopy(a),c=this.patch_addPadding(a),b=c+b+c;this.patch_splitMax(a);for(var d=0,e=[],f=0;f<a.length;f++){var g=a[f].start2+d,h=this.diff_text1(a[f].diffs),j,i=-1;if(h.length>this.Match_MaxBits){if(j=this.match_main(b,h.substring(0,this.Match_MaxBits),g),-1!=j&&(i=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==i||j>=i))j=-1}else j=this.match_main(b,h,g);\nif(-1==j)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=j-g,g=-1==i?b.substring(j,j+h.length):b.substring(j,i+this.Match_MaxBits),h==g)b=b.substring(0,j)+this.diff_text2(a[f].diffs)+b.substring(j+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);for(var h=0,k,i=0;i<a[f].diffs.length;i++){var p=a[f].diffs[i];0!==p[0]&&(k=this.diff_xIndex(g,h));1===p[0]?b=b.substring(0,\nj+k)+p[1]+b.substring(j+k):-1===p[0]&&(b=b.substring(0,j+k)+b.substring(j+this.diff_xIndex(g,h+p[1].length)));-1!==p[0]&&(h+=p[1].length)}}}b=b.substring(c.length,b.length-c.length);return[b,e]};\ndiff_match_patch.prototype.patch_addPadding=function(a){for(var b=this.Patch_Margin,c=\"\",d=1;d<=b;d++)c+=String.fromCharCode(d);for(d=0;d<a.length;d++)a[d].start1+=b,a[d].start2+=b;var d=a[0],e=d.diffs;if(0==e.length||0!=e[0][0])e.unshift([0,c]),d.start1-=b,d.start2-=b,d.length1+=b,d.length2+=b;else if(b>e[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;0==e.length||0!=e[e.length-1][0]?(e.push([0,\nc]),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};\ndiff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c<a.length;c++)if(!(a[c].length1<=b)){var d=a[c];a.splice(c--,1);for(var e=d.start1,f=d.start2,g=\"\";0!==d.diffs.length;){var h=new diff_match_patch.patch_obj,j=!0;h.start1=e-g.length;h.start2=f-g.length;if(\"\"!==g)h.length1=h.length2=g.length,h.diffs.push([0,g]);for(;0!==d.diffs.length&&h.length1<b-this.Patch_Margin;){var g=d.diffs[0][0],i=d.diffs[0][1];1===g?(h.length2+=i.length,f+=i.length,h.diffs.push(d.diffs.shift()),\nj=!1):-1===g&&1==h.diffs.length&&0==h.diffs[0][0]&&i.length>2*b?(h.length1+=i.length,e+=i.length,j=!1,h.diffs.push([g,i]),d.diffs.shift()):(i=i.substring(0,b-h.length1-this.Patch_Margin),h.length1+=i.length,e+=i.length,0===g?(h.length2+=i.length,f+=i.length):j=!1,h.diffs.push([g,i]),i==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(i.length))}g=this.diff_text2(h.diffs);g=g.substring(g.length-this.Patch_Margin);i=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);\"\"!==i&&\n(h.length1+=i.length,h.length2+=i.length,0!==h.diffs.length&&0===h.diffs[h.diffs.length-1][0]?h.diffs[h.diffs.length-1][1]+=i:h.diffs.push([0,i]));j||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c];return b.join(\"\")};\ndiff_match_patch.prototype.patch_fromText=function(a){var b=[];if(!a)return b;for(var a=a.split(\"\\n\"),c=0,d=/^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$/;c<a.length;){var e=a[c].match(d);if(!e)throw Error(\"Invalid patch string: \"+a[c]);var f=new diff_match_patch.patch_obj;b.push(f);f.start1=parseInt(e[1],10);\"\"===e[2]?(f.start1--,f.length1=1):\"0\"==e[2]?f.length1=0:(f.start1--,f.length1=parseInt(e[2],10));f.start2=parseInt(e[3],10);\"\"===e[4]?(f.start2--,f.length2=1):\"0\"==e[4]?f.length2=0:(f.start2--,f.length2=\nparseInt(e[4],10));for(c++;c<a.length;){e=a[c].charAt(0);try{var g=decodeURI(a[c].substring(1))}catch(h){throw Error(\"Illegal escape in patch_fromText: \"+g);}if(\"-\"==e)f.diffs.push([-1,g]);else if(\"+\"==e)f.diffs.push([1,g]);else if(\" \"==e)f.diffs.push([0,g]);else if(\"@\"==e)break;else if(\"\"!==e)throw Error('Invalid patch mode \"'+e+'\" in: '+g);c++}}return b};diff_match_patch.patch_obj=function(){this.diffs=[];this.start2=this.start1=null;this.length2=this.length1=0};\ndiff_match_patch.patch_obj.prototype.toString=function(){var a,b;a=0===this.length1?this.start1+\",0\":1==this.length1?this.start1+1:this.start1+1+\",\"+this.length1;b=0===this.length2?this.start2+\",0\":1==this.length2?this.start2+1:this.start2+1+\",\"+this.length2;a=[\"@@ -\"+a+\" +\"+b+\" @@\\n\"];var c;for(b=0;b<this.diffs.length;b++){switch(this.diffs[b][0]){case 1:c=\"+\";break;case -1:c=\"-\";break;case 0:c=\" \"}a[b+1]=c+encodeURI(this.diffs[b][1])+\"\\n\"}return a.join(\"\").replace(/%20/g,\" \")};\nthis.diff_match_patch=diff_match_patch;this.DIFF_DELETE=-1;this.DIFF_INSERT=1;this.DIFF_EQUAL=0;})()\n"
  },
  {
    "path": "_archive/apps/samples/diff/lib/diff_match_patch_test.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<!--\n  Test Harness for diff_match_patch.js and diff_match_patch_uncompressed.js\n\n  Copyright 2006 Google Inc.\n  http://code.google.com/p/google-diff-match-patch/\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n-->\n\n<html>\n  <head>\n    <script type=\"text/javascript\">\n      // Depending on the URL argument, test the compressed or uncompressed version.\n      var compressed = (document.location.search == '?compressed');\n      if (compressed) {\n        document.write('<TITLE>Test harness for diff_match_patch.js</TITLE>');\n        document.write('<scr'+'ipt type=\"text/javascript\" src=\"diff_match_patch.js\"></scr'+'ipt>');\n      } else {\n        document.write('<TITLE>Test harness for diff_match_patch_uncompressed.js</TITLE>');\n        document.write('<scr'+'ipt type=\"text/javascript\" src=\"diff_match_patch_uncompressed.js\"></scr'+'ipt>');\n      }\n    </script>\n\n    <script type=\"text/javascript\" src=\"diff_match_patch_test.js\"></script>\n\n    <script type=\"text/javascript\">\n      // Counters for unit test results.\n      var test_good = 0;\n      var test_bad = 0;\n\n      // If expected and actual are the identical, print 'Ok', otherwise 'Fail!'\n      function assertEquals(msg, expected, actual) {\n        if (typeof actual == 'undefined') {\n          // msg is optional.\n          actual = expected;\n          expected = msg;\n          msg = 'Expected: \\'' + expected + '\\' Actual: \\'' + actual + '\\'';\n        }\n        if (expected === actual) {\n          document.write('<FONT COLOR=\"#009900\">Ok</FONT><BR>');\n          test_good++;\n        } else {\n          document.write('<FONT COLOR=\"#990000\"><BIG>Fail!</BIG></FONT><BR>');\n          msg = msg.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n          document.write('<code>' + msg + '</code><BR>');\n          test_bad++;\n        }\n      }\n\n      function assertTrue(msg, actual) {\n        if (typeof actual == 'undefined') {\n          // msg is optional.\n          actual = msg;\n          assertEquals(true, actual);\n        } else {\n          assertEquals(msg, true, actual);\n        }\n      }\n\n      function assertFalse(msg, actual) {\n        if (typeof actual == 'undefined') {\n          // msg is optional.\n          actual = msg;\n          assertEquals(false, actual);\n        } else {\n          assertEquals(msg, false, actual);\n        }\n      }\n\n      function runTests() {\n        for (var x = 0; x < tests.length; x++) {\n          document.write('<H3>' + tests[x] + ':</H3>');\n          eval(tests[x] + '()');\n        }\n      }\n\n      var tests = [\n          'testDiffCommonPrefix',\n          'testDiffCommonSuffix',\n          'testDiffCommonOverlap',\n          'testDiffHalfMatch',\n          'testDiffLinesToChars',\n          'testDiffCharsToLines',\n          'testDiffCleanupMerge',\n          'testDiffCleanupSemanticLossless',\n          'testDiffCleanupSemantic',\n          'testDiffCleanupEfficiency',\n          'testDiffPrettyHtml',\n          'testDiffText',\n          'testDiffDelta',\n          'testDiffXIndex',\n          'testDiffLevenshtein',\n          'testDiffBisect',\n          'testDiffMain',\n\n          'testMatchAlphabet',\n          'testMatchBitap',\n          'testMatchMain',\n\n          'testPatchObj',\n          'testPatchFromText',\n          'testPatchToText',\n          'testPatchAddContext',\n          'testPatchMake',\n          'testPatchSplitMax',\n          'testPatchAddPadding',\n          'testPatchApply'];\n\n    </script>\n  </head>\n  <body>\n\n    <script type=\"text/javascript\">\n      if (compressed) {\n        document.write('<H1>Test harness for diff_match_patch.js</H1>');\n        document.write('[ Switch to <A HREF=\"?uncompressed\">Uncompressed</A>. ]');\n      } else {\n        document.write('<H1>Test harness for diff_match_patch_uncompressed.js</H1>');\n        document.write('[ Switch to <A HREF=\"?compressed\">Compressed</A>. ]');\n      }\n    </script>\n\n    <P>If debugging errors, start with the first reported error,\n    subsequent tests often rely on earlier ones.</P>\n\n    <script type=\"text/javascript\">\n      var startTime = (new Date()).getTime();\n      runTests();\n      var endTime = (new Date()).getTime();\n      document.write('<H3>Done.</H3>');\n      document.write('<P>Tests passed: ' + test_good + '<BR>Tests failed: ' + test_bad + '</P>');\n      document.write('<P>Total time: ' + (endTime - startTime) + ' ms</P>');\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/diff/lib/diff_match_patch_test.js",
    "content": "/**\n * Test Harness for Diff Match and Patch\n *\n * Copyright 2006 Google Inc.\n * http://code.google.com/p/google-diff-match-patch/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n// If expected and actual are the equivalent, pass the test.\nfunction assertEquivalent(msg, expected, actual) {\n  if (typeof actual == 'undefined') {\n    // msg is optional.\n    actual = expected;\n    expected = msg;\n    msg = 'Expected: \\'' + expected + '\\' Actual: \\'' + actual + '\\'';\n  }\n  if (_equivalent(expected, actual)) {\n    assertEquals(msg, String.toString(expected), String.toString(actual));\n  } else {\n    assertEquals(msg, expected, actual);\n  }\n}\n\n\n// Are a and b the equivalent? -- Recursive.\nfunction _equivalent(a, b) {\n  if (a == b) {\n    return true;\n  }\n  if (typeof a == 'object' && typeof b == 'object' && a !== null && b !== null) {\n    if (a.toString() != b.toString()) {\n      return false;\n    }\n    for (var p in a) {\n      if (!_equivalent(a[p], b[p])) {\n        return false;\n      }\n    }\n    for (var p in b) {\n      if (!_equivalent(a[p], b[p])) {\n        return false;\n      }\n    }\n    return true;\n  }\n  return false;\n}\n\n\nfunction diff_rebuildtexts(diffs) {\n  // Construct the two texts which made up the diff originally.\n  var text1 = '';\n  var text2 = '';\n  for (var x = 0; x < diffs.length; x++) {\n    if (diffs[x][0] != DIFF_INSERT) {\n      text1 += diffs[x][1];\n    }\n    if (diffs[x][0] != DIFF_DELETE) {\n      text2 += diffs[x][1];\n    }\n  }\n  return [text1, text2];\n}\n\nvar dmp = new diff_match_patch();\n\n\n// DIFF TEST FUNCTIONS\n\n\nfunction testDiffCommonPrefix() {\n  // Detect any common prefix.\n  // Null case.\n  assertEquals(0, dmp.diff_commonPrefix('abc', 'xyz'));\n\n  // Non-null case.\n  assertEquals(4, dmp.diff_commonPrefix('1234abcdef', '1234xyz'));\n\n  // Whole case.\n  assertEquals(4, dmp.diff_commonPrefix('1234', '1234xyz'));\n}\n\nfunction testDiffCommonSuffix() {\n  // Detect any common suffix.\n  // Null case.\n  assertEquals(0, dmp.diff_commonSuffix('abc', 'xyz'));\n\n  // Non-null case.\n  assertEquals(4, dmp.diff_commonSuffix('abcdef1234', 'xyz1234'));\n\n  // Whole case.\n  assertEquals(4, dmp.diff_commonSuffix('1234', 'xyz1234'));\n}\n\nfunction testDiffCommonOverlap() {\n  // Detect any suffix/prefix overlap.\n  // Null case.\n  assertEquals(0, dmp.diff_commonOverlap_('', 'abcd'));\n\n  // Whole case.\n  assertEquals(3, dmp.diff_commonOverlap_('abc', 'abcd'));\n\n  // No overlap.\n  assertEquals(0, dmp.diff_commonOverlap_('123456', 'abcd'));\n\n  // Overlap.\n  assertEquals(3, dmp.diff_commonOverlap_('123456xxx', 'xxxabcd'));\n\n  // Unicode.\n  // Some overly clever languages (C#) may treat ligatures as equal to their\n  // component letters.  E.g. U+FB01 == 'fi'\n  assertEquals(0, dmp.diff_commonOverlap_('fi', '\\ufb01i'));\n}\n\nfunction testDiffHalfMatch() {\n  // Detect a halfmatch.\n  dmp.Diff_Timeout = 1;\n  // No match.\n  assertEquals(null, dmp.diff_halfMatch_('1234567890', 'abcdef'));\n\n  assertEquals(null, dmp.diff_halfMatch_('12345', '23'));\n\n  // Single Match.\n  assertEquivalent(['12', '90', 'a', 'z', '345678'], dmp.diff_halfMatch_('1234567890', 'a345678z'));\n\n  assertEquivalent(['a', 'z', '12', '90', '345678'], dmp.diff_halfMatch_('a345678z', '1234567890'));\n\n  assertEquivalent(['abc', 'z', '1234', '0', '56789'], dmp.diff_halfMatch_('abc56789z', '1234567890'));\n\n  assertEquivalent(['a', 'xyz', '1', '7890', '23456'], dmp.diff_halfMatch_('a23456xyz', '1234567890'));\n\n  // Multiple Matches.\n  assertEquivalent(['12123', '123121', 'a', 'z', '1234123451234'], dmp.diff_halfMatch_('121231234123451234123121', 'a1234123451234z'));\n\n  assertEquivalent(['', '-=-=-=-=-=', 'x', '', 'x-=-=-=-=-=-=-='], dmp.diff_halfMatch_('x-=-=-=-=-=-=-=-=-=-=-=-=', 'xx-=-=-=-=-=-=-='));\n\n  assertEquivalent(['-=-=-=-=-=', '', '', 'y', '-=-=-=-=-=-=-=y'], dmp.diff_halfMatch_('-=-=-=-=-=-=-=-=-=-=-=-=y', '-=-=-=-=-=-=-=yy'));\n\n  // Non-optimal halfmatch.\n  // Optimal diff would be -q+x=H-i+e=lloHe+Hu=llo-Hew+y not -qHillo+x=HelloHe-w+Hulloy\n  assertEquivalent(['qHillo', 'w', 'x', 'Hulloy', 'HelloHe'], dmp.diff_halfMatch_('qHilloHelloHew', 'xHelloHeHulloy'));\n\n  // Optimal no halfmatch.\n  dmp.Diff_Timeout = 0;\n  assertEquals(null, dmp.diff_halfMatch_('qHilloHelloHew', 'xHelloHeHulloy'));\n}\n\nfunction testDiffLinesToChars() {\n  function assertLinesToCharsResultEquals(a, b) {\n    assertEquals(a.chars1, b.chars1);\n    assertEquals(a.chars2, b.chars2);\n    assertEquivalent(a.lineArray, b.lineArray);\n  }\n\n  // Convert lines down to characters.\n  assertLinesToCharsResultEquals({chars1: '\\x01\\x02\\x01', chars2: '\\x02\\x01\\x02', lineArray: ['', 'alpha\\n', 'beta\\n']}, dmp.diff_linesToChars_('alpha\\nbeta\\nalpha\\n', 'beta\\nalpha\\nbeta\\n'));\n\n  assertLinesToCharsResultEquals({chars1: '', chars2: '\\x01\\x02\\x03\\x03', lineArray: ['', 'alpha\\r\\n', 'beta\\r\\n', '\\r\\n']}, dmp.diff_linesToChars_('', 'alpha\\r\\nbeta\\r\\n\\r\\n\\r\\n'));\n\n  assertLinesToCharsResultEquals({chars1: '\\x01', chars2: '\\x02', lineArray: ['', 'a', 'b']}, dmp.diff_linesToChars_('a', 'b'));\n\n  // More than 256 to reveal any 8-bit limitations.\n  var n = 300;\n  var lineList = [];\n  var charList = [];\n  for (var x = 1; x < n + 1; x++) {\n    lineList[x - 1] = x + '\\n';\n    charList[x - 1] = String.fromCharCode(x);\n  }\n  assertEquals(n, lineList.length);\n  var lines = lineList.join('');\n  var chars = charList.join('');\n  assertEquals(n, chars.length);\n  lineList.unshift('');\n  assertLinesToCharsResultEquals({chars1: chars, chars2: '', lineArray: lineList}, dmp.diff_linesToChars_(lines, ''));\n}\n\nfunction testDiffCharsToLines() {\n  // Convert chars up to lines.\n  var diffs = [[DIFF_EQUAL, '\\x01\\x02\\x01'], [DIFF_INSERT, '\\x02\\x01\\x02']];\n  dmp.diff_charsToLines_(diffs, ['', 'alpha\\n', 'beta\\n']);\n  assertEquivalent([[DIFF_EQUAL, 'alpha\\nbeta\\nalpha\\n'], [DIFF_INSERT, 'beta\\nalpha\\nbeta\\n']], diffs);\n\n  // More than 256 to reveal any 8-bit limitations.\n  var n = 300;\n  var lineList = [];\n  var charList = [];\n  for (var x = 1; x < n + 1; x++) {\n    lineList[x - 1] = x + '\\n';\n    charList[x - 1] = String.fromCharCode(x);\n  }\n  assertEquals(n, lineList.length);\n  var lines = lineList.join('');\n  var chars = charList.join('');\n  assertEquals(n, chars.length);\n  lineList.unshift('');\n  var diffs = [[DIFF_DELETE, chars]];\n  dmp.diff_charsToLines_(diffs, lineList);\n  assertEquivalent([[DIFF_DELETE, lines]], diffs);\n}\n\nfunction testDiffCleanupMerge() {\n  // Cleanup a messy diff.\n  // Null case.\n  var diffs = [];\n  dmp.diff_cleanupMerge(diffs);\n  assertEquivalent([], diffs);\n\n  // No change case.\n  diffs = [[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'b'], [DIFF_INSERT, 'c']];\n  dmp.diff_cleanupMerge(diffs);\n  assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'b'], [DIFF_INSERT, 'c']], diffs);\n\n  // Merge equalities.\n  diffs = [[DIFF_EQUAL, 'a'], [DIFF_EQUAL, 'b'], [DIFF_EQUAL, 'c']];\n  dmp.diff_cleanupMerge(diffs);\n  assertEquivalent([[DIFF_EQUAL, 'abc']], diffs);\n\n  // Merge deletions.\n  diffs = [[DIFF_DELETE, 'a'], [DIFF_DELETE, 'b'], [DIFF_DELETE, 'c']];\n  dmp.diff_cleanupMerge(diffs);\n  assertEquivalent([[DIFF_DELETE, 'abc']], diffs);\n\n  // Merge insertions.\n  diffs = [[DIFF_INSERT, 'a'], [DIFF_INSERT, 'b'], [DIFF_INSERT, 'c']];\n  dmp.diff_cleanupMerge(diffs);\n  assertEquivalent([[DIFF_INSERT, 'abc']], diffs);\n\n  // Merge interweave.\n  diffs = [[DIFF_DELETE, 'a'], [DIFF_INSERT, 'b'], [DIFF_DELETE, 'c'], [DIFF_INSERT, 'd'], [DIFF_EQUAL, 'e'], [DIFF_EQUAL, 'f']];\n  dmp.diff_cleanupMerge(diffs);\n  assertEquivalent([[DIFF_DELETE, 'ac'], [DIFF_INSERT, 'bd'], [DIFF_EQUAL, 'ef']], diffs);\n\n  // Prefix and suffix detection.\n  diffs = [[DIFF_DELETE, 'a'], [DIFF_INSERT, 'abc'], [DIFF_DELETE, 'dc']];\n  dmp.diff_cleanupMerge(diffs);\n  assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'd'], [DIFF_INSERT, 'b'], [DIFF_EQUAL, 'c']], diffs);\n\n  // Prefix and suffix detection with equalities.\n  diffs = [[DIFF_EQUAL, 'x'], [DIFF_DELETE, 'a'], [DIFF_INSERT, 'abc'], [DIFF_DELETE, 'dc'], [DIFF_EQUAL, 'y']];\n  dmp.diff_cleanupMerge(diffs);\n  assertEquivalent([[DIFF_EQUAL, 'xa'], [DIFF_DELETE, 'd'], [DIFF_INSERT, 'b'], [DIFF_EQUAL, 'cy']], diffs);\n\n  // Slide edit left.\n  diffs = [[DIFF_EQUAL, 'a'], [DIFF_INSERT, 'ba'], [DIFF_EQUAL, 'c']];\n  dmp.diff_cleanupMerge(diffs);\n  assertEquivalent([[DIFF_INSERT, 'ab'], [DIFF_EQUAL, 'ac']], diffs);\n\n  // Slide edit right.\n  diffs = [[DIFF_EQUAL, 'c'], [DIFF_INSERT, 'ab'], [DIFF_EQUAL, 'a']];\n  dmp.diff_cleanupMerge(diffs);\n  assertEquivalent([[DIFF_EQUAL, 'ca'], [DIFF_INSERT, 'ba']], diffs);\n\n  // Slide edit left recursive.\n  diffs = [[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'b'], [DIFF_EQUAL, 'c'], [DIFF_DELETE, 'ac'], [DIFF_EQUAL, 'x']];\n  dmp.diff_cleanupMerge(diffs);\n  assertEquivalent([[DIFF_DELETE, 'abc'], [DIFF_EQUAL, 'acx']], diffs);\n\n  // Slide edit right recursive.\n  diffs = [[DIFF_EQUAL, 'x'], [DIFF_DELETE, 'ca'], [DIFF_EQUAL, 'c'], [DIFF_DELETE, 'b'], [DIFF_EQUAL, 'a']];\n  dmp.diff_cleanupMerge(diffs);\n  assertEquivalent([[DIFF_EQUAL, 'xca'], [DIFF_DELETE, 'cba']], diffs);\n}\n\nfunction testDiffCleanupSemanticLossless() {\n  // Slide diffs to match logical boundaries.\n  // Null case.\n  var diffs = [];\n  dmp.diff_cleanupSemanticLossless(diffs);\n  assertEquivalent([], diffs);\n\n  // Blank lines.\n  diffs = [[DIFF_EQUAL, 'AAA\\r\\n\\r\\nBBB'], [DIFF_INSERT, '\\r\\nDDD\\r\\n\\r\\nBBB'], [DIFF_EQUAL, '\\r\\nEEE']];\n  dmp.diff_cleanupSemanticLossless(diffs);\n  assertEquivalent([[DIFF_EQUAL, 'AAA\\r\\n\\r\\n'], [DIFF_INSERT, 'BBB\\r\\nDDD\\r\\n\\r\\n'], [DIFF_EQUAL, 'BBB\\r\\nEEE']], diffs);\n\n  // Line boundaries.\n  diffs = [[DIFF_EQUAL, 'AAA\\r\\nBBB'], [DIFF_INSERT, ' DDD\\r\\nBBB'], [DIFF_EQUAL, ' EEE']];\n  dmp.diff_cleanupSemanticLossless(diffs);\n  assertEquivalent([[DIFF_EQUAL, 'AAA\\r\\n'], [DIFF_INSERT, 'BBB DDD\\r\\n'], [DIFF_EQUAL, 'BBB EEE']], diffs);\n\n  // Word boundaries.\n  diffs = [[DIFF_EQUAL, 'The c'], [DIFF_INSERT, 'ow and the c'], [DIFF_EQUAL, 'at.']];\n  dmp.diff_cleanupSemanticLossless(diffs);\n  assertEquivalent([[DIFF_EQUAL, 'The '], [DIFF_INSERT, 'cow and the '], [DIFF_EQUAL, 'cat.']], diffs);\n\n  // Alphanumeric boundaries.\n  diffs = [[DIFF_EQUAL, 'The-c'], [DIFF_INSERT, 'ow-and-the-c'], [DIFF_EQUAL, 'at.']];\n  dmp.diff_cleanupSemanticLossless(diffs);\n  assertEquivalent([[DIFF_EQUAL, 'The-'], [DIFF_INSERT, 'cow-and-the-'], [DIFF_EQUAL, 'cat.']], diffs);\n\n  // Hitting the start.\n  diffs = [[DIFF_EQUAL, 'a'], [DIFF_DELETE, 'a'], [DIFF_EQUAL, 'ax']];\n  dmp.diff_cleanupSemanticLossless(diffs);\n  assertEquivalent([[DIFF_DELETE, 'a'], [DIFF_EQUAL, 'aax']], diffs);\n\n  // Hitting the end.\n  diffs = [[DIFF_EQUAL, 'xa'], [DIFF_DELETE, 'a'], [DIFF_EQUAL, 'a']];\n  dmp.diff_cleanupSemanticLossless(diffs);\n  assertEquivalent([[DIFF_EQUAL, 'xaa'], [DIFF_DELETE, 'a']], diffs);\n\n  // Sentence boundaries.\n  diffs = [[DIFF_EQUAL, 'The xxx. The '], [DIFF_INSERT, 'zzz. The '], [DIFF_EQUAL, 'yyy.']];\n  dmp.diff_cleanupSemanticLossless(diffs);\n  assertEquivalent([[DIFF_EQUAL, 'The xxx.'], [DIFF_INSERT, ' The zzz.'], [DIFF_EQUAL, ' The yyy.']], diffs);\n}\n\nfunction testDiffCleanupSemantic() {\n  // Cleanup semantically trivial equalities.\n  // Null case.\n  var diffs = [];\n  dmp.diff_cleanupSemantic(diffs);\n  assertEquivalent([], diffs);\n\n  // No elimination #1.\n  diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, 'cd'], [DIFF_EQUAL, '12'], [DIFF_DELETE, 'e']];\n  dmp.diff_cleanupSemantic(diffs);\n  assertEquivalent([[DIFF_DELETE, 'ab'], [DIFF_INSERT, 'cd'], [DIFF_EQUAL, '12'], [DIFF_DELETE, 'e']], diffs);\n\n  // No elimination #2.\n  diffs = [[DIFF_DELETE, 'abc'], [DIFF_INSERT, 'ABC'], [DIFF_EQUAL, '1234'], [DIFF_DELETE, 'wxyz']];\n  dmp.diff_cleanupSemantic(diffs);\n  assertEquivalent([[DIFF_DELETE, 'abc'], [DIFF_INSERT, 'ABC'], [DIFF_EQUAL, '1234'], [DIFF_DELETE, 'wxyz']], diffs);\n\n  // Simple elimination.\n  diffs = [[DIFF_DELETE, 'a'], [DIFF_EQUAL, 'b'], [DIFF_DELETE, 'c']];\n  dmp.diff_cleanupSemantic(diffs);\n  assertEquivalent([[DIFF_DELETE, 'abc'], [DIFF_INSERT, 'b']], diffs);\n\n  // Backpass elimination.\n  diffs = [[DIFF_DELETE, 'ab'], [DIFF_EQUAL, 'cd'], [DIFF_DELETE, 'e'], [DIFF_EQUAL, 'f'], [DIFF_INSERT, 'g']];\n  dmp.diff_cleanupSemantic(diffs);\n  assertEquivalent([[DIFF_DELETE, 'abcdef'], [DIFF_INSERT, 'cdfg']], diffs);\n\n  // Multiple eliminations.\n  diffs = [[DIFF_INSERT, '1'], [DIFF_EQUAL, 'A'], [DIFF_DELETE, 'B'], [DIFF_INSERT, '2'], [DIFF_EQUAL, '_'], [DIFF_INSERT, '1'], [DIFF_EQUAL, 'A'], [DIFF_DELETE, 'B'], [DIFF_INSERT, '2']];\n  dmp.diff_cleanupSemantic(diffs);\n  assertEquivalent([[DIFF_DELETE, 'AB_AB'], [DIFF_INSERT, '1A2_1A2']], diffs);\n\n  // Word boundaries.\n  diffs = [[DIFF_EQUAL, 'The c'], [DIFF_DELETE, 'ow and the c'], [DIFF_EQUAL, 'at.']];\n  dmp.diff_cleanupSemantic(diffs);\n  assertEquivalent([[DIFF_EQUAL, 'The '], [DIFF_DELETE, 'cow and the '], [DIFF_EQUAL, 'cat.']], diffs);\n\n  // No overlap elimination.\n  diffs = [[DIFF_DELETE, 'abcxx'], [DIFF_INSERT, 'xxdef']];\n  dmp.diff_cleanupSemantic(diffs);\n  assertEquivalent([[DIFF_DELETE, 'abcxx'], [DIFF_INSERT, 'xxdef']], diffs);\n\n  // Overlap elimination.\n  diffs = [[DIFF_DELETE, 'abcxxx'], [DIFF_INSERT, 'xxxdef']];\n  dmp.diff_cleanupSemantic(diffs);\n  assertEquivalent([[DIFF_DELETE, 'abc'], [DIFF_EQUAL, 'xxx'], [DIFF_INSERT, 'def']], diffs);\n\n  // Reverse overlap elimination.\n  diffs = [[DIFF_DELETE, 'xxxabc'], [DIFF_INSERT, 'defxxx']];\n  dmp.diff_cleanupSemantic(diffs);\n  assertEquivalent([[DIFF_INSERT, 'def'], [DIFF_EQUAL, 'xxx'], [DIFF_DELETE, 'abc']], diffs);\n\n  // Two overlap eliminations.\n  diffs = [[DIFF_DELETE, 'abcd1212'], [DIFF_INSERT, '1212efghi'], [DIFF_EQUAL, '----'], [DIFF_DELETE, 'A3'], [DIFF_INSERT, '3BC']];\n  dmp.diff_cleanupSemantic(diffs);\n  assertEquivalent([[DIFF_DELETE, 'abcd'], [DIFF_EQUAL, '1212'], [DIFF_INSERT, 'efghi'], [DIFF_EQUAL, '----'], [DIFF_DELETE, 'A'], [DIFF_EQUAL, '3'], [DIFF_INSERT, 'BC']], diffs);\n}\n\nfunction testDiffCleanupEfficiency() {\n  // Cleanup operationally trivial equalities.\n  dmp.Diff_EditCost = 4;\n  // Null case.\n  var diffs = [];\n  dmp.diff_cleanupEfficiency(diffs);\n  assertEquivalent([], diffs);\n\n  // No elimination.\n  diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'wxyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']];\n  dmp.diff_cleanupEfficiency(diffs);\n  assertEquivalent([[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'wxyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']], diffs);\n\n  // Four-edit elimination.\n  diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'xyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']];\n  dmp.diff_cleanupEfficiency(diffs);\n  assertEquivalent([[DIFF_DELETE, 'abxyzcd'], [DIFF_INSERT, '12xyz34']], diffs);\n\n  // Three-edit elimination.\n  diffs = [[DIFF_INSERT, '12'], [DIFF_EQUAL, 'x'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']];\n  dmp.diff_cleanupEfficiency(diffs);\n  assertEquivalent([[DIFF_DELETE, 'xcd'], [DIFF_INSERT, '12x34']], diffs);\n\n  // Backpass elimination.\n  diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'xy'], [DIFF_INSERT, '34'], [DIFF_EQUAL, 'z'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '56']];\n  dmp.diff_cleanupEfficiency(diffs);\n  assertEquivalent([[DIFF_DELETE, 'abxyzcd'], [DIFF_INSERT, '12xy34z56']], diffs);\n\n  // High cost elimination.\n  dmp.Diff_EditCost = 5;\n  diffs = [[DIFF_DELETE, 'ab'], [DIFF_INSERT, '12'], [DIFF_EQUAL, 'wxyz'], [DIFF_DELETE, 'cd'], [DIFF_INSERT, '34']];\n  dmp.diff_cleanupEfficiency(diffs);\n  assertEquivalent([[DIFF_DELETE, 'abwxyzcd'], [DIFF_INSERT, '12wxyz34']], diffs);\n  dmp.Diff_EditCost = 4;\n}\n\nfunction testDiffPrettyHtml() {\n  // Pretty print.\n  var diffs = [[DIFF_EQUAL, 'a\\n'], [DIFF_DELETE, '<B>b</B>'], [DIFF_INSERT, 'c&d']];\n  assertEquals('<span>a&para;<br></span><del style=\"background:#ffe6e6;\">&lt;B&gt;b&lt;/B&gt;</del><ins style=\"background:#e6ffe6;\">c&amp;d</ins>', dmp.diff_prettyHtml(diffs));\n}\n\nfunction testDiffText() {\n  // Compute the source and destination texts.\n  var diffs = [[DIFF_EQUAL, 'jump'], [DIFF_DELETE, 's'], [DIFF_INSERT, 'ed'], [DIFF_EQUAL, ' over '], [DIFF_DELETE, 'the'], [DIFF_INSERT, 'a'], [DIFF_EQUAL, ' lazy']];\n  assertEquals('jumps over the lazy', dmp.diff_text1(diffs));\n\n  assertEquals('jumped over a lazy', dmp.diff_text2(diffs));\n}\n\nfunction testDiffDelta() {\n  // Convert a diff into delta string.\n  var diffs = [[DIFF_EQUAL, 'jump'], [DIFF_DELETE, 's'], [DIFF_INSERT, 'ed'], [DIFF_EQUAL, ' over '], [DIFF_DELETE, 'the'], [DIFF_INSERT, 'a'], [DIFF_EQUAL, ' lazy'], [DIFF_INSERT, 'old dog']];\n  var text1 = dmp.diff_text1(diffs);\n  assertEquals('jumps over the lazy', text1);\n\n  var delta = dmp.diff_toDelta(diffs);\n  assertEquals('=4\\t-1\\t+ed\\t=6\\t-3\\t+a\\t=5\\t+old dog', delta);\n\n  // Convert delta string into a diff.\n  assertEquivalent(diffs, dmp.diff_fromDelta(text1, delta));\n\n  // Generates error (19 != 20).\n  try {\n    dmp.diff_fromDelta(text1 + 'x', delta);\n    assertEquals(Error, null);\n  } catch (e) {\n    // Exception expected.\n  }\n\n  // Generates error (19 != 18).\n  try {\n    dmp.diff_fromDelta(text1.substring(1), delta);\n    assertEquals(Error, null);\n  } catch (e) {\n    // Exception expected.\n  }\n\n  // Generates error (%c3%xy invalid Unicode).\n  try {\n    dmp.diff_fromDelta('', '+%c3%xy');\n    assertEquals(Error, null);\n  } catch (e) {\n    // Exception expected.\n  }\n\n  // Test deltas with special characters.\n  diffs = [[DIFF_EQUAL, '\\u0680 \\x00 \\t %'], [DIFF_DELETE, '\\u0681 \\x01 \\n ^'], [DIFF_INSERT, '\\u0682 \\x02 \\\\ |']];\n  text1 = dmp.diff_text1(diffs);\n  assertEquals('\\u0680 \\x00 \\t %\\u0681 \\x01 \\n ^', text1);\n\n  delta = dmp.diff_toDelta(diffs);\n  assertEquals('=7\\t-7\\t+%DA%82 %02 %5C %7C', delta);\n\n  // Convert delta string into a diff.\n  assertEquivalent(diffs, dmp.diff_fromDelta(text1, delta));\n\n  // Verify pool of unchanged characters.\n  diffs = [[DIFF_INSERT, 'A-Z a-z 0-9 - _ . ! ~ * \\' ( ) ; / ? : @ & = + $ , # ']];\n  var text2 = dmp.diff_text2(diffs);\n  assertEquals('A-Z a-z 0-9 - _ . ! ~ * \\' ( ) ; / ? : @ & = + $ , # ', text2);\n\n  delta = dmp.diff_toDelta(diffs);\n  assertEquals('+A-Z a-z 0-9 - _ . ! ~ * \\' ( ) ; / ? : @ & = + $ , # ', delta);\n\n  // Convert delta string into a diff.\n  assertEquivalent(diffs, dmp.diff_fromDelta('', delta));\n}\n\nfunction testDiffXIndex() {\n  // Translate a location in text1 to text2.\n  // Translation on equality.\n  assertEquals(5, dmp.diff_xIndex([[DIFF_DELETE, 'a'], [DIFF_INSERT, '1234'], [DIFF_EQUAL, 'xyz']], 2));\n\n  // Translation on deletion.\n  assertEquals(1, dmp.diff_xIndex([[DIFF_EQUAL, 'a'], [DIFF_DELETE, '1234'], [DIFF_EQUAL, 'xyz']], 3));\n}\n\nfunction testDiffLevenshtein() {\n  // Levenshtein with trailing equality.\n  assertEquals(4, dmp.diff_levenshtein([[DIFF_DELETE, 'abc'], [DIFF_INSERT, '1234'], [DIFF_EQUAL, 'xyz']]));\n  // Levenshtein with leading equality.\n  assertEquals(4, dmp.diff_levenshtein([[DIFF_EQUAL, 'xyz'], [DIFF_DELETE, 'abc'], [DIFF_INSERT, '1234']]));\n  // Levenshtein with middle equality.\n  assertEquals(7, dmp.diff_levenshtein([[DIFF_DELETE, 'abc'], [DIFF_EQUAL, 'xyz'], [DIFF_INSERT, '1234']]));\n}\n\nfunction testDiffBisect() {\n  // Normal.\n  var a = 'cat';\n  var b = 'map';\n  // Since the resulting diff hasn't been normalized, it would be ok if\n  // the insertion and deletion pairs are swapped.\n  // If the order changes, tweak this test as required.\n  assertEquivalent([[DIFF_DELETE, 'c'], [DIFF_INSERT, 'm'], [DIFF_EQUAL, 'a'], [DIFF_DELETE, 't'], [DIFF_INSERT, 'p']], dmp.diff_bisect_(a, b, Number.MAX_VALUE));\n\n  // Timeout.\n  assertEquivalent([[DIFF_DELETE, 'cat'], [DIFF_INSERT, 'map']], dmp.diff_bisect_(a, b, 0));\n}\n\nfunction testDiffMain() {\n  // Perform a trivial diff.\n  // Null case.\n  assertEquivalent([], dmp.diff_main('', '', false));\n\n  // Equality.\n  assertEquivalent([[DIFF_EQUAL, 'abc']], dmp.diff_main('abc', 'abc', false));\n\n  // Simple insertion.\n  assertEquivalent([[DIFF_EQUAL, 'ab'], [DIFF_INSERT, '123'], [DIFF_EQUAL, 'c']], dmp.diff_main('abc', 'ab123c', false));\n\n  // Simple deletion.\n  assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_DELETE, '123'], [DIFF_EQUAL, 'bc']], dmp.diff_main('a123bc', 'abc', false));\n\n  // Two insertions.\n  assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_INSERT, '123'], [DIFF_EQUAL, 'b'], [DIFF_INSERT, '456'], [DIFF_EQUAL, 'c']], dmp.diff_main('abc', 'a123b456c', false));\n\n  // Two deletions.\n  assertEquivalent([[DIFF_EQUAL, 'a'], [DIFF_DELETE, '123'], [DIFF_EQUAL, 'b'], [DIFF_DELETE, '456'], [DIFF_EQUAL, 'c']], dmp.diff_main('a123b456c', 'abc', false));\n\n  // Perform a real diff.\n  // Switch off the timeout.\n  dmp.Diff_Timeout = 0;\n  // Simple cases.\n  assertEquivalent([[DIFF_DELETE, 'a'], [DIFF_INSERT, 'b']], dmp.diff_main('a', 'b', false));\n\n  assertEquivalent([[DIFF_DELETE, 'Apple'], [DIFF_INSERT, 'Banana'], [DIFF_EQUAL, 's are a'], [DIFF_INSERT, 'lso'], [DIFF_EQUAL, ' fruit.']], dmp.diff_main('Apples are a fruit.', 'Bananas are also fruit.', false));\n\n  assertEquivalent([[DIFF_DELETE, 'a'], [DIFF_INSERT, '\\u0680'], [DIFF_EQUAL, 'x'], [DIFF_DELETE, '\\t'], [DIFF_INSERT, '\\0']], dmp.diff_main('ax\\t', '\\u0680x\\0', false));\n\n  // Overlaps.\n  assertEquivalent([[DIFF_DELETE, '1'], [DIFF_EQUAL, 'a'], [DIFF_DELETE, 'y'], [DIFF_EQUAL, 'b'], [DIFF_DELETE, '2'], [DIFF_INSERT, 'xab']], dmp.diff_main('1ayb2', 'abxab', false));\n\n  assertEquivalent([[DIFF_INSERT, 'xaxcx'], [DIFF_EQUAL, 'abc'], [DIFF_DELETE, 'y']], dmp.diff_main('abcy', 'xaxcxabc', false));\n\n  assertEquivalent([[DIFF_DELETE, 'ABCD'], [DIFF_EQUAL, 'a'], [DIFF_DELETE, '='], [DIFF_INSERT, '-'], [DIFF_EQUAL, 'bcd'], [DIFF_DELETE, '='], [DIFF_INSERT, '-'], [DIFF_EQUAL, 'efghijklmnopqrs'], [DIFF_DELETE, 'EFGHIJKLMNOefg']], dmp.diff_main('ABCDa=bcd=efghijklmnopqrsEFGHIJKLMNOefg', 'a-bcd-efghijklmnopqrs', false));\n\n  // Large equality.\n  assertEquivalent([[DIFF_INSERT, ' '], [DIFF_EQUAL, 'a'], [DIFF_INSERT, 'nd'], [DIFF_EQUAL, ' [[Pennsylvania]]'], [DIFF_DELETE, ' and [[New']], dmp.diff_main('a [[Pennsylvania]] and [[New', ' and [[Pennsylvania]]', false));\n\n  // Timeout.\n  dmp.Diff_Timeout = 0.1;  // 100ms\n  var a = '`Twas brillig, and the slithy toves\\nDid gyre and gimble in the wabe:\\nAll mimsy were the borogoves,\\nAnd the mome raths outgrabe.\\n';\n  var b = 'I am the very model of a modern major general,\\nI\\'ve information vegetable, animal, and mineral,\\nI know the kings of England, and I quote the fights historical,\\nFrom Marathon to Waterloo, in order categorical.\\n';\n  // Increase the text lengths by 1024 times to ensure a timeout.\n  for (var x = 0; x < 10; x++) {\n    a = a + a;\n    b = b + b;\n  }\n  var startTime = (new Date()).getTime();\n  dmp.diff_main(a, b);\n  var endTime = (new Date()).getTime();\n  // Test that we took at least the timeout period.\n  assertTrue(dmp.Diff_Timeout * 1000 <= endTime - startTime);\n  // Test that we didn't take forever (be forgiving).\n  // Theoretically this test could fail very occasionally if the\n  // OS task swaps or locks up for a second at the wrong moment.\n  // ****\n  // TODO(fraser): For unknown reasons this is taking 500 ms on Google's\n  // internal test system.  Whereas browsers take 140 ms.\n  //assertTrue(dmp.Diff_Timeout * 1000 * 2 > endTime - startTime);\n  // ****\n  dmp.Diff_Timeout = 0;\n\n  // Test the linemode speedup.\n  // Must be long to pass the 100 char cutoff.\n  // Simple line-mode.\n  a = '1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n';\n  b = 'abcdefghij\\nabcdefghij\\nabcdefghij\\nabcdefghij\\nabcdefghij\\nabcdefghij\\nabcdefghij\\nabcdefghij\\nabcdefghij\\nabcdefghij\\nabcdefghij\\nabcdefghij\\nabcdefghij\\n';\n  assertEquivalent(dmp.diff_main(a, b, false), dmp.diff_main(a, b, true));\n\n  // Single line-mode.\n  a = '1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890';\n  b = 'abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij';\n  assertEquivalent(dmp.diff_main(a, b, false), dmp.diff_main(a, b, true));\n\n  // Overlap line-mode.\n  a = '1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n1234567890\\n';\n  b = 'abcdefghij\\n1234567890\\n1234567890\\n1234567890\\nabcdefghij\\n1234567890\\n1234567890\\n1234567890\\nabcdefghij\\n1234567890\\n1234567890\\n1234567890\\nabcdefghij\\n';\n  var texts_linemode = diff_rebuildtexts(dmp.diff_main(a, b, true));\n  var texts_textmode = diff_rebuildtexts(dmp.diff_main(a, b, false));\n  assertEquivalent(texts_textmode, texts_linemode);\n\n  // Test null inputs.\n  try {\n    dmp.diff_main(null, null);\n    assertEquals(Error, null);\n  } catch (e) {\n    // Exception expected.\n  }\n}\n\n\n// MATCH TEST FUNCTIONS\n\n\nfunction testMatchAlphabet() {\n  // Initialise the bitmasks for Bitap.\n  // Unique.\n  assertEquivalent({'a':4, 'b':2, 'c':1}, dmp.match_alphabet_('abc'));\n\n  // Duplicates.\n  assertEquivalent({'a':37, 'b':18, 'c':8}, dmp.match_alphabet_('abcaba'));\n}\n\nfunction testMatchBitap() {\n  // Bitap algorithm.\n  dmp.Match_Distance = 100;\n  dmp.Match_Threshold = 0.5;\n  // Exact matches.\n  assertEquals(5, dmp.match_bitap_('abcdefghijk', 'fgh', 5));\n\n  assertEquals(5, dmp.match_bitap_('abcdefghijk', 'fgh', 0));\n\n  // Fuzzy matches.\n  assertEquals(4, dmp.match_bitap_('abcdefghijk', 'efxhi', 0));\n\n  assertEquals(2, dmp.match_bitap_('abcdefghijk', 'cdefxyhijk', 5));\n\n  assertEquals(-1, dmp.match_bitap_('abcdefghijk', 'bxy', 1));\n\n  // Overflow.\n  assertEquals(2, dmp.match_bitap_('123456789xx0', '3456789x0', 2));\n\n  // Threshold test.\n  dmp.Match_Threshold = 0.4;\n  assertEquals(4, dmp.match_bitap_('abcdefghijk', 'efxyhi', 1));\n\n  dmp.Match_Threshold = 0.3;\n  assertEquals(-1, dmp.match_bitap_('abcdefghijk', 'efxyhi', 1));\n\n  dmp.Match_Threshold = 0.0;\n  assertEquals(1, dmp.match_bitap_('abcdefghijk', 'bcdef', 1));\n  dmp.Match_Threshold = 0.5;\n\n  // Multiple select.\n  assertEquals(0, dmp.match_bitap_('abcdexyzabcde', 'abccde', 3));\n\n  assertEquals(8, dmp.match_bitap_('abcdexyzabcde', 'abccde', 5));\n\n  // Distance test.\n  dmp.Match_Distance = 10;  // Strict location.\n  assertEquals(-1, dmp.match_bitap_('abcdefghijklmnopqrstuvwxyz', 'abcdefg', 24));\n\n  assertEquals(0, dmp.match_bitap_('abcdefghijklmnopqrstuvwxyz', 'abcdxxefg', 1));\n\n  dmp.Match_Distance = 1000;  // Loose location.\n  assertEquals(0, dmp.match_bitap_('abcdefghijklmnopqrstuvwxyz', 'abcdefg', 24));\n}\n\nfunction testMatchMain() {\n  // Full match.\n  // Shortcut matches.\n  assertEquals(0, dmp.match_main('abcdef', 'abcdef', 1000));\n\n  assertEquals(-1, dmp.match_main('', 'abcdef', 1));\n\n  assertEquals(3, dmp.match_main('abcdef', '', 3));\n\n  assertEquals(3, dmp.match_main('abcdef', 'de', 3));\n\n  // Beyond end match.\n  assertEquals(3, dmp.match_main(\"abcdef\", \"defy\", 4));\n\n  // Oversized pattern.\n  assertEquals(0, dmp.match_main(\"abcdef\", \"abcdefy\", 0));\n\n  // Complex match.\n  assertEquals(4, dmp.match_main('I am the very model of a modern major general.', ' that berry ', 5));\n\n  // Test null inputs.\n  try {\n    dmp.match_main(null, null, 0);\n    assertEquals(Error, null);\n  } catch (e) {\n    // Exception expected.\n  }\n}\n\n\n// PATCH TEST FUNCTIONS\n\n\nfunction testPatchObj() {\n  // Patch Object.\n  var p = new diff_match_patch.patch_obj();\n  p.start1 = 20;\n  p.start2 = 21;\n  p.length1 = 18;\n  p.length2 = 17;\n  p.diffs = [[DIFF_EQUAL, 'jump'], [DIFF_DELETE, 's'], [DIFF_INSERT, 'ed'], [DIFF_EQUAL, ' over '], [DIFF_DELETE, 'the'], [DIFF_INSERT, 'a'], [DIFF_EQUAL, '\\nlaz']];\n  var strp = p.toString();\n  assertEquals('@@ -21,18 +22,17 @@\\n jump\\n-s\\n+ed\\n  over \\n-the\\n+a\\n %0Alaz\\n', strp);\n}\n\nfunction testPatchFromText() {\n  assertEquivalent([], dmp.patch_fromText(strp));\n\n  var strp = '@@ -21,18 +22,17 @@\\n jump\\n-s\\n+ed\\n  over \\n-the\\n+a\\n %0Alaz\\n';\n  assertEquals(strp, dmp.patch_fromText(strp)[0].toString());\n\n  assertEquals('@@ -1 +1 @@\\n-a\\n+b\\n', dmp.patch_fromText('@@ -1 +1 @@\\n-a\\n+b\\n')[0].toString());\n\n  assertEquals('@@ -1,3 +0,0 @@\\n-abc\\n', dmp.patch_fromText('@@ -1,3 +0,0 @@\\n-abc\\n')[0].toString());\n\n  assertEquals('@@ -0,0 +1,3 @@\\n+abc\\n', dmp.patch_fromText('@@ -0,0 +1,3 @@\\n+abc\\n')[0].toString());\n\n  // Generates error.\n  try {\n    dmp.patch_fromText('Bad\\nPatch\\n');\n    assertEquals(Error, null);\n  } catch (e) {\n    // Exception expected.\n  }\n}\n\nfunction testPatchToText() {\n  var strp = '@@ -21,18 +22,17 @@\\n jump\\n-s\\n+ed\\n  over \\n-the\\n+a\\n  laz\\n';\n  var p = dmp.patch_fromText(strp);\n  assertEquals(strp, dmp.patch_toText(p));\n\n  strp = '@@ -1,9 +1,9 @@\\n-f\\n+F\\n oo+fooba\\n@@ -7,9 +7,9 @@\\n obar\\n-,\\n+.\\n  tes\\n';\n  p = dmp.patch_fromText(strp);\n  assertEquals(strp, dmp.patch_toText(p));\n}\n\nfunction testPatchAddContext() {\n  dmp.Patch_Margin = 4;\n  var p = dmp.patch_fromText('@@ -21,4 +21,10 @@\\n-jump\\n+somersault\\n')[0];\n  dmp.patch_addContext_(p, 'The quick brown fox jumps over the lazy dog.');\n  assertEquals('@@ -17,12 +17,18 @@\\n fox \\n-jump\\n+somersault\\n s ov\\n', p.toString());\n\n  // Same, but not enough trailing context.\n  p = dmp.patch_fromText('@@ -21,4 +21,10 @@\\n-jump\\n+somersault\\n')[0];\n  dmp.patch_addContext_(p, 'The quick brown fox jumps.');\n  assertEquals('@@ -17,10 +17,16 @@\\n fox \\n-jump\\n+somersault\\n s.\\n', p.toString());\n\n  // Same, but not enough leading context.\n  p = dmp.patch_fromText('@@ -3 +3,2 @@\\n-e\\n+at\\n')[0];\n  dmp.patch_addContext_(p, 'The quick brown fox jumps.');\n  assertEquals('@@ -1,7 +1,8 @@\\n Th\\n-e\\n+at\\n  qui\\n', p.toString());\n\n  // Same, but with ambiguity.\n  p = dmp.patch_fromText('@@ -3 +3,2 @@\\n-e\\n+at\\n')[0];\n  dmp.patch_addContext_(p, 'The quick brown fox jumps.  The quick brown fox crashes.');\n  assertEquals('@@ -1,27 +1,28 @@\\n Th\\n-e\\n+at\\n  quick brown fox jumps. \\n', p.toString());\n}\n\nfunction testPatchMake() {\n  // Null case.\n  var patches = dmp.patch_make('', '');\n  assertEquals('', dmp.patch_toText(patches));\n\n  var text1 = 'The quick brown fox jumps over the lazy dog.';\n  var text2 = 'That quick brown fox jumped over a lazy dog.';\n  // Text2+Text1 inputs.\n  var expectedPatch = '@@ -1,8 +1,7 @@\\n Th\\n-at\\n+e\\n  qui\\n@@ -21,17 +21,18 @@\\n jump\\n-ed\\n+s\\n  over \\n-a\\n+the\\n  laz\\n';\n  // The second patch must be \"-21,17 +21,18\", not \"-22,17 +21,18\" due to rolling context.\n  patches = dmp.patch_make(text2, text1);\n  assertEquals(expectedPatch, dmp.patch_toText(patches));\n\n  // Text1+Text2 inputs.\n  expectedPatch = '@@ -1,11 +1,12 @@\\n Th\\n-e\\n+at\\n  quick b\\n@@ -22,18 +22,17 @@\\n jump\\n-s\\n+ed\\n  over \\n-the\\n+a\\n  laz\\n';\n  patches = dmp.patch_make(text1, text2);\n  assertEquals(expectedPatch, dmp.patch_toText(patches));\n\n  // Diff input.\n  var diffs = dmp.diff_main(text1, text2, false);\n  patches = dmp.patch_make(diffs);\n  assertEquals(expectedPatch, dmp.patch_toText(patches));\n\n  // Text1+Diff inputs.\n  patches = dmp.patch_make(text1, diffs);\n  assertEquals(expectedPatch, dmp.patch_toText(patches));\n\n  // Text1+Text2+Diff inputs (deprecated).\n  patches = dmp.patch_make(text1, text2, diffs);\n  assertEquals(expectedPatch, dmp.patch_toText(patches));\n\n  // Character encoding.\n  patches = dmp.patch_make('`1234567890-=[]\\\\;\\',./', '~!@#$%^&*()_+{}|:\"<>?');\n  assertEquals('@@ -1,21 +1,21 @@\\n-%601234567890-=%5B%5D%5C;\\',./\\n+~!@#$%25%5E&*()_+%7B%7D%7C:%22%3C%3E?\\n', dmp.patch_toText(patches));\n\n  // Character decoding.\n  diffs = [[DIFF_DELETE, '`1234567890-=[]\\\\;\\',./'], [DIFF_INSERT, '~!@#$%^&*()_+{}|:\"<>?']];\n  assertEquivalent(diffs, dmp.patch_fromText('@@ -1,21 +1,21 @@\\n-%601234567890-=%5B%5D%5C;\\',./\\n+~!@#$%25%5E&*()_+%7B%7D%7C:%22%3C%3E?\\n')[0].diffs);\n\n  // Long string with repeats.\n  text1 = '';\n  for (var x = 0; x < 100; x++) {\n    text1 += 'abcdef';\n  }\n  text2 = text1 + '123';\n  expectedPatch = '@@ -573,28 +573,31 @@\\n cdefabcdefabcdefabcdefabcdef\\n+123\\n';\n  patches = dmp.patch_make(text1, text2);\n  assertEquals(expectedPatch, dmp.patch_toText(patches));\n\n  // Test null inputs.\n  try {\n    dmp.patch_make(null);\n    assertEquals(Error, null);\n  } catch (e) {\n    // Exception expected.\n  }\n}\n\nfunction testPatchSplitMax() {\n  // Assumes that dmp.Match_MaxBits is 32.\n  var patches = dmp.patch_make('abcdefghijklmnopqrstuvwxyz01234567890', 'XabXcdXefXghXijXklXmnXopXqrXstXuvXwxXyzX01X23X45X67X89X0');\n  dmp.patch_splitMax(patches);\n  assertEquals('@@ -1,32 +1,46 @@\\n+X\\n ab\\n+X\\n cd\\n+X\\n ef\\n+X\\n gh\\n+X\\n ij\\n+X\\n kl\\n+X\\n mn\\n+X\\n op\\n+X\\n qr\\n+X\\n st\\n+X\\n uv\\n+X\\n wx\\n+X\\n yz\\n+X\\n 012345\\n@@ -25,13 +39,18 @@\\n zX01\\n+X\\n 23\\n+X\\n 45\\n+X\\n 67\\n+X\\n 89\\n+X\\n 0\\n', dmp.patch_toText(patches));\n\n  patches = dmp.patch_make('abcdef1234567890123456789012345678901234567890123456789012345678901234567890uvwxyz', 'abcdefuvwxyz');\n  var oldToText = dmp.patch_toText(patches);\n  dmp.patch_splitMax(patches);\n  assertEquals(oldToText, dmp.patch_toText(patches));\n\n  patches = dmp.patch_make('1234567890123456789012345678901234567890123456789012345678901234567890', 'abc');\n  dmp.patch_splitMax(patches);\n  assertEquals('@@ -1,32 +1,4 @@\\n-1234567890123456789012345678\\n 9012\\n@@ -29,32 +1,4 @@\\n-9012345678901234567890123456\\n 7890\\n@@ -57,14 +1,3 @@\\n-78901234567890\\n+abc\\n', dmp.patch_toText(patches));\n\n  patches = dmp.patch_make('abcdefghij , h : 0 , t : 1 abcdefghij , h : 0 , t : 1 abcdefghij , h : 0 , t : 1', 'abcdefghij , h : 1 , t : 1 abcdefghij , h : 1 , t : 1 abcdefghij , h : 0 , t : 1');\n  dmp.patch_splitMax(patches);\n  assertEquals('@@ -2,32 +2,32 @@\\n bcdefghij , h : \\n-0\\n+1\\n  , t : 1 abcdef\\n@@ -29,32 +29,32 @@\\n bcdefghij , h : \\n-0\\n+1\\n  , t : 1 abcdef\\n', dmp.patch_toText(patches));\n}\n\nfunction testPatchAddPadding() {\n  // Both edges full.\n  var patches = dmp.patch_make('', 'test');\n  assertEquals('@@ -0,0 +1,4 @@\\n+test\\n', dmp.patch_toText(patches));\n  dmp.patch_addPadding(patches);\n  assertEquals('@@ -1,8 +1,12 @@\\n %01%02%03%04\\n+test\\n %01%02%03%04\\n', dmp.patch_toText(patches));\n\n  // Both edges partial.\n  patches = dmp.patch_make('XY', 'XtestY');\n  assertEquals('@@ -1,2 +1,6 @@\\n X\\n+test\\n Y\\n', dmp.patch_toText(patches));\n  dmp.patch_addPadding(patches);\n  assertEquals('@@ -2,8 +2,12 @@\\n %02%03%04X\\n+test\\n Y%01%02%03\\n', dmp.patch_toText(patches));\n\n  // Both edges none.\n  patches = dmp.patch_make('XXXXYYYY', 'XXXXtestYYYY');\n  assertEquals('@@ -1,8 +1,12 @@\\n XXXX\\n+test\\n YYYY\\n', dmp.patch_toText(patches));\n  dmp.patch_addPadding(patches);\n  assertEquals('@@ -5,8 +5,12 @@\\n XXXX\\n+test\\n YYYY\\n', dmp.patch_toText(patches));\n}\n\nfunction testPatchApply() {\n  dmp.Match_Distance = 1000;\n  dmp.Match_Threshold = 0.5;\n  dmp.Patch_DeleteThreshold = 0.5;\n  // Null case.\n  var patches = dmp.patch_make('', '');\n  var results = dmp.patch_apply(patches, 'Hello world.');\n  assertEquivalent(['Hello world.', []], results);\n\n  // Exact match.\n  patches = dmp.patch_make('The quick brown fox jumps over the lazy dog.', 'That quick brown fox jumped over a lazy dog.');\n  results = dmp.patch_apply(patches, 'The quick brown fox jumps over the lazy dog.');\n  assertEquivalent(['That quick brown fox jumped over a lazy dog.', [true, true]], results);\n\n  // Partial match.\n  results = dmp.patch_apply(patches, 'The quick red rabbit jumps over the tired tiger.');\n  assertEquivalent(['That quick red rabbit jumped over a tired tiger.', [true, true]], results);\n\n  // Failed match.\n  results = dmp.patch_apply(patches, 'I am the very model of a modern major general.');\n  assertEquivalent(['I am the very model of a modern major general.', [false, false]], results);\n\n  // Big delete, small change.\n  patches = dmp.patch_make('x1234567890123456789012345678901234567890123456789012345678901234567890y', 'xabcy');\n  results = dmp.patch_apply(patches, 'x123456789012345678901234567890-----++++++++++-----123456789012345678901234567890y');\n  assertEquivalent(['xabcy', [true, true]], results);\n\n  // Big delete, big change 1.\n  patches = dmp.patch_make('x1234567890123456789012345678901234567890123456789012345678901234567890y', 'xabcy');\n  results = dmp.patch_apply(patches, 'x12345678901234567890---------------++++++++++---------------12345678901234567890y');\n  assertEquivalent(['xabc12345678901234567890---------------++++++++++---------------12345678901234567890y', [false, true]], results);\n\n  // Big delete, big change 2.\n  dmp.Patch_DeleteThreshold = 0.6;\n  patches = dmp.patch_make('x1234567890123456789012345678901234567890123456789012345678901234567890y', 'xabcy');\n  results = dmp.patch_apply(patches, 'x12345678901234567890---------------++++++++++---------------12345678901234567890y');\n  assertEquivalent(['xabcy', [true, true]], results);\n  dmp.Patch_DeleteThreshold = 0.5;\n\n  // Compensate for failed patch.\n  dmp.Match_Threshold = 0.0;\n  dmp.Match_Distance = 0;\n  patches = dmp.patch_make('abcdefghijklmnopqrstuvwxyz--------------------1234567890', 'abcXXXXXXXXXXdefghijklmnopqrstuvwxyz--------------------1234567YYYYYYYYYY890');\n  results = dmp.patch_apply(patches, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ--------------------1234567890');\n  assertEquivalent(['ABCDEFGHIJKLMNOPQRSTUVWXYZ--------------------1234567YYYYYYYYYY890', [false, true]], results);\n  dmp.Match_Threshold = 0.5;\n  dmp.Match_Distance = 1000;\n\n  // No side effects.\n  patches = dmp.patch_make('', 'test');\n  var patchstr = dmp.patch_toText(patches);\n  dmp.patch_apply(patches, '');\n  assertEquals(patchstr, dmp.patch_toText(patches));\n\n  // No side effects with major delete.\n  patches = dmp.patch_make('The quick brown fox jumps over the lazy dog.', 'Woof');\n  patchstr = dmp.patch_toText(patches);\n  dmp.patch_apply(patches, 'The quick brown fox jumps over the lazy dog.');\n  assertEquals(patchstr, dmp.patch_toText(patches));\n\n  // Edge exact match.\n  patches = dmp.patch_make('', 'test');\n  results = dmp.patch_apply(patches, '');\n  assertEquivalent(['test', [true]], results);\n\n  // Near edge exact match.\n  patches = dmp.patch_make('XY', 'XtestY');\n  results = dmp.patch_apply(patches, 'XY');\n  assertEquivalent(['XtestY', [true]], results);\n\n  // Edge partial match.\n  patches = dmp.patch_make('y', 'y123');\n  results = dmp.patch_apply(patches, 'x');\n  assertEquivalent(['x123', [true]], results);\n}\n"
  },
  {
    "path": "_archive/apps/samples/diff/lib/diff_match_patch_uncompressed.js",
    "content": "/**\n * Diff Match and Patch\n *\n * Copyright 2006 Google Inc.\n * http://code.google.com/p/google-diff-match-patch/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Computes the difference between two texts to create a patch.\n * Applies the patch onto another text, allowing for errors.\n * @author fraser@google.com (Neil Fraser)\n */\n\n/**\n * Class containing the diff, match and patch methods.\n * @constructor\n */\nfunction diff_match_patch() {\n\n  // Defaults.\n  // Redefine these in your program to override the defaults.\n\n  // Number of seconds to map a diff before giving up (0 for infinity).\n  this.Diff_Timeout = 1.0;\n  // Cost of an empty edit operation in terms of edit characters.\n  this.Diff_EditCost = 4;\n  // At what point is no match declared (0.0 = perfection, 1.0 = very loose).\n  this.Match_Threshold = 0.5;\n  // How far to search for a match (0 = exact location, 1000+ = broad match).\n  // A match this many characters away from the expected location will add\n  // 1.0 to the score (0.0 is a perfect match).\n  this.Match_Distance = 1000;\n  // When deleting a large block of text (over ~64 characters), how close do\n  // the contents have to be to match the expected contents. (0.0 = perfection,\n  // 1.0 = very loose).  Note that Match_Threshold controls how closely the\n  // end points of a delete need to match.\n  this.Patch_DeleteThreshold = 0.5;\n  // Chunk size for context length.\n  this.Patch_Margin = 4;\n\n  // The number of bits in an int.\n  this.Match_MaxBits = 32;\n}\n\n\n//  DIFF FUNCTIONS\n\n\n/**\n * The data structure representing a diff is an array of tuples:\n * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]\n * which means: delete 'Hello', add 'Goodbye' and keep ' world.'\n */\nvar DIFF_DELETE = -1;\nvar DIFF_INSERT = 1;\nvar DIFF_EQUAL = 0;\n\n/** @typedef {{0: number, 1: string}} */\ndiff_match_patch.Diff;\n\n\n/**\n * Find the differences between two texts.  Simplifies the problem by stripping\n * any common prefix or suffix off the texts before diffing.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {boolean=} opt_checklines Optional speedup flag. If present and false,\n *     then don't run a line-level diff first to identify the changed areas.\n *     Defaults to true, which does a faster, slightly less optimal diff.\n * @param {number} opt_deadline Optional time when the diff should be complete\n *     by.  Used internally for recursive calls.  Users should set DiffTimeout\n *     instead.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_main = function(text1, text2, opt_checklines,\n    opt_deadline) {\n  // Set a deadline by which time the diff must be complete.\n  if (typeof opt_deadline == 'undefined') {\n    if (this.Diff_Timeout <= 0) {\n      opt_deadline = Number.MAX_VALUE;\n    } else {\n      opt_deadline = (new Date).getTime() + this.Diff_Timeout * 1000;\n    }\n  }\n  var deadline = opt_deadline;\n\n  // Check for null inputs.\n  if (text1 == null || text2 == null) {\n    throw new Error('Null input. (diff_main)');\n  }\n\n  // Check for equality (speedup).\n  if (text1 == text2) {\n    if (text1) {\n      return [[DIFF_EQUAL, text1]];\n    }\n    return [];\n  }\n\n  if (typeof opt_checklines == 'undefined') {\n    opt_checklines = true;\n  }\n  var checklines = opt_checklines;\n\n  // Trim off common prefix (speedup).\n  var commonlength = this.diff_commonPrefix(text1, text2);\n  var commonprefix = text1.substring(0, commonlength);\n  text1 = text1.substring(commonlength);\n  text2 = text2.substring(commonlength);\n\n  // Trim off common suffix (speedup).\n  commonlength = this.diff_commonSuffix(text1, text2);\n  var commonsuffix = text1.substring(text1.length - commonlength);\n  text1 = text1.substring(0, text1.length - commonlength);\n  text2 = text2.substring(0, text2.length - commonlength);\n\n  // Compute the diff on the middle block.\n  var diffs = this.diff_compute_(text1, text2, checklines, deadline);\n\n  // Restore the prefix and suffix.\n  if (commonprefix) {\n    diffs.unshift([DIFF_EQUAL, commonprefix]);\n  }\n  if (commonsuffix) {\n    diffs.push([DIFF_EQUAL, commonsuffix]);\n  }\n  this.diff_cleanupMerge(diffs);\n  return diffs;\n};\n\n\n/**\n * Find the differences between two texts.  Assumes that the texts do not\n * have any common prefix or suffix.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {boolean} checklines Speedup flag.  If false, then don't run a\n *     line-level diff first to identify the changed areas.\n *     If true, then run a faster, slightly less optimal diff.\n * @param {number} deadline Time when the diff should be complete by.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @private\n */\ndiff_match_patch.prototype.diff_compute_ = function(text1, text2, checklines,\n    deadline) {\n  var diffs;\n\n  if (!text1) {\n    // Just add some text (speedup).\n    return [[DIFF_INSERT, text2]];\n  }\n\n  if (!text2) {\n    // Just delete some text (speedup).\n    return [[DIFF_DELETE, text1]];\n  }\n\n  /** @type {?string} */\n  var longtext = text1.length > text2.length ? text1 : text2;\n  /** @type {?string} */\n  var shorttext = text1.length > text2.length ? text2 : text1;\n  var i = longtext.indexOf(shorttext);\n  if (i != -1) {\n    // Shorter text is inside the longer text (speedup).\n    diffs = [[DIFF_INSERT, longtext.substring(0, i)],\n             [DIFF_EQUAL, shorttext],\n             [DIFF_INSERT, longtext.substring(i + shorttext.length)]];\n    // Swap insertions for deletions if diff is reversed.\n    if (text1.length > text2.length) {\n      diffs[0][0] = diffs[2][0] = DIFF_DELETE;\n    }\n    return diffs;\n  }\n\n  if (shorttext.length == 1) {\n    // Single character string.\n    // After the previous speedup, the character can't be an equality.\n    return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];\n  }\n  longtext = shorttext = null;  // Garbage collect.\n\n  // Check to see if the problem can be split in two.\n  var hm = this.diff_halfMatch_(text1, text2);\n  if (hm) {\n    // A half-match was found, sort out the return data.\n    var text1_a = hm[0];\n    var text1_b = hm[1];\n    var text2_a = hm[2];\n    var text2_b = hm[3];\n    var mid_common = hm[4];\n    // Send both pairs off for separate processing.\n    var diffs_a = this.diff_main(text1_a, text2_a, checklines, deadline);\n    var diffs_b = this.diff_main(text1_b, text2_b, checklines, deadline);\n    // Merge the results.\n    return diffs_a.concat([[DIFF_EQUAL, mid_common]], diffs_b);\n  }\n\n  if (checklines && text1.length > 100 && text2.length > 100) {\n    return this.diff_lineMode_(text1, text2, deadline);\n  }\n\n  return this.diff_bisect_(text1, text2, deadline);\n};\n\n\n/**\n * Do a quick line-level diff on both strings, then rediff the parts for\n * greater accuracy.\n * This speedup can produce non-minimal diffs.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {number} deadline Time when the diff should be complete by.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @private\n */\ndiff_match_patch.prototype.diff_lineMode_ = function(text1, text2, deadline) {\n  // Scan the text on a line-by-line basis first.\n  var a = this.diff_linesToChars_(text1, text2);\n  text1 = a.chars1;\n  text2 = a.chars2;\n  var linearray = a.lineArray;\n\n  var diffs = this.diff_main(text1, text2, false, deadline);\n\n  // Convert the diff back to original text.\n  this.diff_charsToLines_(diffs, linearray);\n  // Eliminate freak matches (e.g. blank lines)\n  this.diff_cleanupSemantic(diffs);\n\n  // Rediff any replacement blocks, this time character-by-character.\n  // Add a dummy entry at the end.\n  diffs.push([DIFF_EQUAL, '']);\n  var pointer = 0;\n  var count_delete = 0;\n  var count_insert = 0;\n  var text_delete = '';\n  var text_insert = '';\n  while (pointer < diffs.length) {\n    switch (diffs[pointer][0]) {\n      case DIFF_INSERT:\n        count_insert++;\n        text_insert += diffs[pointer][1];\n        break;\n      case DIFF_DELETE:\n        count_delete++;\n        text_delete += diffs[pointer][1];\n        break;\n      case DIFF_EQUAL:\n        // Upon reaching an equality, check for prior redundancies.\n        if (count_delete >= 1 && count_insert >= 1) {\n          // Delete the offending records and add the merged ones.\n          diffs.splice(pointer - count_delete - count_insert,\n                       count_delete + count_insert);\n          pointer = pointer - count_delete - count_insert;\n          var a = this.diff_main(text_delete, text_insert, false, deadline);\n          for (var j = a.length - 1; j >= 0; j--) {\n            diffs.splice(pointer, 0, a[j]);\n          }\n          pointer = pointer + a.length;\n        }\n        count_insert = 0;\n        count_delete = 0;\n        text_delete = '';\n        text_insert = '';\n        break;\n    }\n    pointer++;\n  }\n  diffs.pop();  // Remove the dummy entry at the end.\n\n  return diffs;\n};\n\n\n/**\n * Find the 'middle snake' of a diff, split the problem in two\n * and return the recursively constructed diff.\n * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {number} deadline Time at which to bail if not yet complete.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @private\n */\ndiff_match_patch.prototype.diff_bisect_ = function(text1, text2, deadline) {\n  // Cache the text lengths to prevent multiple calls.\n  var text1_length = text1.length;\n  var text2_length = text2.length;\n  var max_d = Math.ceil((text1_length + text2_length) / 2);\n  var v_offset = max_d;\n  var v_length = 2 * max_d;\n  var v1 = new Array(v_length);\n  var v2 = new Array(v_length);\n  // Setting all elements to -1 is faster in Chrome & Firefox than mixing\n  // integers and undefined.\n  for (var x = 0; x < v_length; x++) {\n    v1[x] = -1;\n    v2[x] = -1;\n  }\n  v1[v_offset + 1] = 0;\n  v2[v_offset + 1] = 0;\n  var delta = text1_length - text2_length;\n  // If the total number of characters is odd, then the front path will collide\n  // with the reverse path.\n  var front = (delta % 2 != 0);\n  // Offsets for start and end of k loop.\n  // Prevents mapping of space beyond the grid.\n  var k1start = 0;\n  var k1end = 0;\n  var k2start = 0;\n  var k2end = 0;\n  for (var d = 0; d < max_d; d++) {\n    // Bail out if deadline is reached.\n    if ((new Date()).getTime() > deadline) {\n      break;\n    }\n\n    // Walk the front path one step.\n    for (var k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {\n      var k1_offset = v_offset + k1;\n      var x1;\n      if (k1 == -d || (k1 != d && v1[k1_offset - 1] < v1[k1_offset + 1])) {\n        x1 = v1[k1_offset + 1];\n      } else {\n        x1 = v1[k1_offset - 1] + 1;\n      }\n      var y1 = x1 - k1;\n      while (x1 < text1_length && y1 < text2_length &&\n             text1.charAt(x1) == text2.charAt(y1)) {\n        x1++;\n        y1++;\n      }\n      v1[k1_offset] = x1;\n      if (x1 > text1_length) {\n        // Ran off the right of the graph.\n        k1end += 2;\n      } else if (y1 > text2_length) {\n        // Ran off the bottom of the graph.\n        k1start += 2;\n      } else if (front) {\n        var k2_offset = v_offset + delta - k1;\n        if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] != -1) {\n          // Mirror x2 onto top-left coordinate system.\n          var x2 = text1_length - v2[k2_offset];\n          if (x1 >= x2) {\n            // Overlap detected.\n            return this.diff_bisectSplit_(text1, text2, x1, y1, deadline);\n          }\n        }\n      }\n    }\n\n    // Walk the reverse path one step.\n    for (var k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {\n      var k2_offset = v_offset + k2;\n      var x2;\n      if (k2 == -d || (k2 != d && v2[k2_offset - 1] < v2[k2_offset + 1])) {\n        x2 = v2[k2_offset + 1];\n      } else {\n        x2 = v2[k2_offset - 1] + 1;\n      }\n      var y2 = x2 - k2;\n      while (x2 < text1_length && y2 < text2_length &&\n             text1.charAt(text1_length - x2 - 1) ==\n             text2.charAt(text2_length - y2 - 1)) {\n        x2++;\n        y2++;\n      }\n      v2[k2_offset] = x2;\n      if (x2 > text1_length) {\n        // Ran off the left of the graph.\n        k2end += 2;\n      } else if (y2 > text2_length) {\n        // Ran off the top of the graph.\n        k2start += 2;\n      } else if (!front) {\n        var k1_offset = v_offset + delta - k2;\n        if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] != -1) {\n          var x1 = v1[k1_offset];\n          var y1 = v_offset + x1 - k1_offset;\n          // Mirror x2 onto top-left coordinate system.\n          x2 = text1_length - x2;\n          if (x1 >= x2) {\n            // Overlap detected.\n            return this.diff_bisectSplit_(text1, text2, x1, y1, deadline);\n          }\n        }\n      }\n    }\n  }\n  // Diff took too long and hit the deadline or\n  // number of diffs equals number of characters, no commonality at all.\n  return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];\n};\n\n\n/**\n * Given the location of the 'middle snake', split the diff in two parts\n * and recurse.\n * @param {string} text1 Old string to be diffed.\n * @param {string} text2 New string to be diffed.\n * @param {number} x Index of split point in text1.\n * @param {number} y Index of split point in text2.\n * @param {number} deadline Time at which to bail if not yet complete.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @private\n */\ndiff_match_patch.prototype.diff_bisectSplit_ = function(text1, text2, x, y,\n    deadline) {\n  var text1a = text1.substring(0, x);\n  var text2a = text2.substring(0, y);\n  var text1b = text1.substring(x);\n  var text2b = text2.substring(y);\n\n  // Compute both diffs serially.\n  var diffs = this.diff_main(text1a, text2a, false, deadline);\n  var diffsb = this.diff_main(text1b, text2b, false, deadline);\n\n  return diffs.concat(diffsb);\n};\n\n\n/**\n * Split two texts into an array of strings.  Reduce the texts to a string of\n * hashes where each Unicode character represents one line.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}\n *     An object containing the encoded text1, the encoded text2 and\n *     the array of unique strings.\n *     The zeroth element of the array of unique strings is intentionally blank.\n * @private\n */\ndiff_match_patch.prototype.diff_linesToChars_ = function(text1, text2) {\n  var lineArray = [];  // e.g. lineArray[4] == 'Hello\\n'\n  var lineHash = {};   // e.g. lineHash['Hello\\n'] == 4\n\n  // '\\x00' is a valid character, but various debuggers don't like it.\n  // So we'll insert a junk entry to avoid generating a null character.\n  lineArray[0] = '';\n\n  /**\n   * Split a text into an array of strings.  Reduce the texts to a string of\n   * hashes where each Unicode character represents one line.\n   * Modifies linearray and linehash through being a closure.\n   * @param {string} text String to encode.\n   * @return {string} Encoded string.\n   * @private\n   */\n  function diff_linesToCharsMunge_(text) {\n    var chars = '';\n    // Walk the text, pulling out a substring for each line.\n    // text.split('\\n') would would temporarily double our memory footprint.\n    // Modifying text would create many large strings to garbage collect.\n    var lineStart = 0;\n    var lineEnd = -1;\n    // Keeping our own length variable is faster than looking it up.\n    var lineArrayLength = lineArray.length;\n    while (lineEnd < text.length - 1) {\n      lineEnd = text.indexOf('\\n', lineStart);\n      if (lineEnd == -1) {\n        lineEnd = text.length - 1;\n      }\n      var line = text.substring(lineStart, lineEnd + 1);\n      lineStart = lineEnd + 1;\n\n      if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) :\n          (lineHash[line] !== undefined)) {\n        chars += String.fromCharCode(lineHash[line]);\n      } else {\n        chars += String.fromCharCode(lineArrayLength);\n        lineHash[line] = lineArrayLength;\n        lineArray[lineArrayLength++] = line;\n      }\n    }\n    return chars;\n  }\n\n  var chars1 = diff_linesToCharsMunge_(text1);\n  var chars2 = diff_linesToCharsMunge_(text2);\n  return {chars1: chars1, chars2: chars2, lineArray: lineArray};\n};\n\n\n/**\n * Rehydrate the text in a diff from a string of line hashes to real lines of\n * text.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @param {!Array.<string>} lineArray Array of unique strings.\n * @private\n */\ndiff_match_patch.prototype.diff_charsToLines_ = function(diffs, lineArray) {\n  for (var x = 0; x < diffs.length; x++) {\n    var chars = diffs[x][1];\n    var text = [];\n    for (var y = 0; y < chars.length; y++) {\n      text[y] = lineArray[chars.charCodeAt(y)];\n    }\n    diffs[x][1] = text.join('');\n  }\n};\n\n\n/**\n * Determine the common prefix of two strings.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {number} The number of characters common to the start of each\n *     string.\n */\ndiff_match_patch.prototype.diff_commonPrefix = function(text1, text2) {\n  // Quick check for common null cases.\n  if (!text1 || !text2 || text1.charAt(0) != text2.charAt(0)) {\n    return 0;\n  }\n  // Binary search.\n  // Performance analysis: http://neil.fraser.name/news/2007/10/09/\n  var pointermin = 0;\n  var pointermax = Math.min(text1.length, text2.length);\n  var pointermid = pointermax;\n  var pointerstart = 0;\n  while (pointermin < pointermid) {\n    if (text1.substring(pointerstart, pointermid) ==\n        text2.substring(pointerstart, pointermid)) {\n      pointermin = pointermid;\n      pointerstart = pointermin;\n    } else {\n      pointermax = pointermid;\n    }\n    pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);\n  }\n  return pointermid;\n};\n\n\n/**\n * Determine the common suffix of two strings.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {number} The number of characters common to the end of each string.\n */\ndiff_match_patch.prototype.diff_commonSuffix = function(text1, text2) {\n  // Quick check for common null cases.\n  if (!text1 || !text2 ||\n      text1.charAt(text1.length - 1) != text2.charAt(text2.length - 1)) {\n    return 0;\n  }\n  // Binary search.\n  // Performance analysis: http://neil.fraser.name/news/2007/10/09/\n  var pointermin = 0;\n  var pointermax = Math.min(text1.length, text2.length);\n  var pointermid = pointermax;\n  var pointerend = 0;\n  while (pointermin < pointermid) {\n    if (text1.substring(text1.length - pointermid, text1.length - pointerend) ==\n        text2.substring(text2.length - pointermid, text2.length - pointerend)) {\n      pointermin = pointermid;\n      pointerend = pointermin;\n    } else {\n      pointermax = pointermid;\n    }\n    pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);\n  }\n  return pointermid;\n};\n\n\n/**\n * Determine if the suffix of one string is the prefix of another.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {number} The number of characters common to the end of the first\n *     string and the start of the second string.\n * @private\n */\ndiff_match_patch.prototype.diff_commonOverlap_ = function(text1, text2) {\n  // Cache the text lengths to prevent multiple calls.\n  var text1_length = text1.length;\n  var text2_length = text2.length;\n  // Eliminate the null case.\n  if (text1_length == 0 || text2_length == 0) {\n    return 0;\n  }\n  // Truncate the longer string.\n  if (text1_length > text2_length) {\n    text1 = text1.substring(text1_length - text2_length);\n  } else if (text1_length < text2_length) {\n    text2 = text2.substring(0, text1_length);\n  }\n  var text_length = Math.min(text1_length, text2_length);\n  // Quick check for the worst case.\n  if (text1 == text2) {\n    return text_length;\n  }\n\n  // Start by looking for a single character match\n  // and increase length until no match is found.\n  // Performance analysis: http://neil.fraser.name/news/2010/11/04/\n  var best = 0;\n  var length = 1;\n  while (true) {\n    var pattern = text1.substring(text_length - length);\n    var found = text2.indexOf(pattern);\n    if (found == -1) {\n      return best;\n    }\n    length += found;\n    if (found == 0 || text1.substring(text_length - length) ==\n        text2.substring(0, length)) {\n      best = length;\n      length++;\n    }\n  }\n};\n\n\n/**\n * Do the two texts share a substring which is at least half the length of the\n * longer text?\n * This speedup can produce non-minimal diffs.\n * @param {string} text1 First string.\n * @param {string} text2 Second string.\n * @return {Array.<string>} Five element Array, containing the prefix of\n *     text1, the suffix of text1, the prefix of text2, the suffix of\n *     text2 and the common middle.  Or null if there was no match.\n * @private\n */\ndiff_match_patch.prototype.diff_halfMatch_ = function(text1, text2) {\n  if (this.Diff_Timeout <= 0) {\n    // Don't risk returning a non-optimal diff if we have unlimited time.\n    return null;\n  }\n  var longtext = text1.length > text2.length ? text1 : text2;\n  var shorttext = text1.length > text2.length ? text2 : text1;\n  if (longtext.length < 4 || shorttext.length * 2 < longtext.length) {\n    return null;  // Pointless.\n  }\n  var dmp = this;  // 'this' becomes 'window' in a closure.\n\n  /**\n   * Does a substring of shorttext exist within longtext such that the substring\n   * is at least half the length of longtext?\n   * Closure, but does not reference any external variables.\n   * @param {string} longtext Longer string.\n   * @param {string} shorttext Shorter string.\n   * @param {number} i Start index of quarter length substring within longtext.\n   * @return {Array.<string>} Five element Array, containing the prefix of\n   *     longtext, the suffix of longtext, the prefix of shorttext, the suffix\n   *     of shorttext and the common middle.  Or null if there was no match.\n   * @private\n   */\n  function diff_halfMatchI_(longtext, shorttext, i) {\n    // Start with a 1/4 length substring at position i as a seed.\n    var seed = longtext.substring(i, i + Math.floor(longtext.length / 4));\n    var j = -1;\n    var best_common = '';\n    var best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b;\n    while ((j = shorttext.indexOf(seed, j + 1)) != -1) {\n      var prefixLength = dmp.diff_commonPrefix(longtext.substring(i),\n                                               shorttext.substring(j));\n      var suffixLength = dmp.diff_commonSuffix(longtext.substring(0, i),\n                                               shorttext.substring(0, j));\n      if (best_common.length < suffixLength + prefixLength) {\n        best_common = shorttext.substring(j - suffixLength, j) +\n            shorttext.substring(j, j + prefixLength);\n        best_longtext_a = longtext.substring(0, i - suffixLength);\n        best_longtext_b = longtext.substring(i + prefixLength);\n        best_shorttext_a = shorttext.substring(0, j - suffixLength);\n        best_shorttext_b = shorttext.substring(j + prefixLength);\n      }\n    }\n    if (best_common.length * 2 >= longtext.length) {\n      return [best_longtext_a, best_longtext_b,\n              best_shorttext_a, best_shorttext_b, best_common];\n    } else {\n      return null;\n    }\n  }\n\n  // First check if the second quarter is the seed for a half-match.\n  var hm1 = diff_halfMatchI_(longtext, shorttext,\n                             Math.ceil(longtext.length / 4));\n  // Check again based on the third quarter.\n  var hm2 = diff_halfMatchI_(longtext, shorttext,\n                             Math.ceil(longtext.length / 2));\n  var hm;\n  if (!hm1 && !hm2) {\n    return null;\n  } else if (!hm2) {\n    hm = hm1;\n  } else if (!hm1) {\n    hm = hm2;\n  } else {\n    // Both matched.  Select the longest.\n    hm = hm1[4].length > hm2[4].length ? hm1 : hm2;\n  }\n\n  // A half-match was found, sort out the return data.\n  var text1_a, text1_b, text2_a, text2_b;\n  if (text1.length > text2.length) {\n    text1_a = hm[0];\n    text1_b = hm[1];\n    text2_a = hm[2];\n    text2_b = hm[3];\n  } else {\n    text2_a = hm[0];\n    text2_b = hm[1];\n    text1_a = hm[2];\n    text1_b = hm[3];\n  }\n  var mid_common = hm[4];\n  return [text1_a, text1_b, text2_a, text2_b, mid_common];\n};\n\n\n/**\n * Reduce the number of edits by eliminating semantically trivial equalities.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_cleanupSemantic = function(diffs) {\n  var changes = false;\n  var equalities = [];  // Stack of indices where equalities are found.\n  var equalitiesLength = 0;  // Keeping our own length var is faster in JS.\n  /** @type {?string} */\n  var lastequality = null;\n  // Always equal to diffs[equalities[equalitiesLength - 1]][1]\n  var pointer = 0;  // Index of current position.\n  // Number of characters that changed prior to the equality.\n  var length_insertions1 = 0;\n  var length_deletions1 = 0;\n  // Number of characters that changed after the equality.\n  var length_insertions2 = 0;\n  var length_deletions2 = 0;\n  while (pointer < diffs.length) {\n    if (diffs[pointer][0] == DIFF_EQUAL) {  // Equality found.\n      equalities[equalitiesLength++] = pointer;\n      length_insertions1 = length_insertions2;\n      length_deletions1 = length_deletions2;\n      length_insertions2 = 0;\n      length_deletions2 = 0;\n      lastequality = diffs[pointer][1];\n    } else {  // An insertion or deletion.\n      if (diffs[pointer][0] == DIFF_INSERT) {\n        length_insertions2 += diffs[pointer][1].length;\n      } else {\n        length_deletions2 += diffs[pointer][1].length;\n      }\n      // Eliminate an equality that is smaller or equal to the edits on both\n      // sides of it.\n      if (lastequality && (lastequality.length <=\n          Math.max(length_insertions1, length_deletions1)) &&\n          (lastequality.length <= Math.max(length_insertions2,\n                                           length_deletions2))) {\n        // Duplicate record.\n        diffs.splice(equalities[equalitiesLength - 1], 0,\n                     [DIFF_DELETE, lastequality]);\n        // Change second copy to insert.\n        diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;\n        // Throw away the equality we just deleted.\n        equalitiesLength--;\n        // Throw away the previous equality (it needs to be reevaluated).\n        equalitiesLength--;\n        pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;\n        length_insertions1 = 0;  // Reset the counters.\n        length_deletions1 = 0;\n        length_insertions2 = 0;\n        length_deletions2 = 0;\n        lastequality = null;\n        changes = true;\n      }\n    }\n    pointer++;\n  }\n\n  // Normalize the diff.\n  if (changes) {\n    this.diff_cleanupMerge(diffs);\n  }\n  this.diff_cleanupSemanticLossless(diffs);\n\n  // Find any overlaps between deletions and insertions.\n  // e.g: <del>abcxxx</del><ins>xxxdef</ins>\n  //   -> <del>abc</del>xxx<ins>def</ins>\n  // e.g: <del>xxxabc</del><ins>defxxx</ins>\n  //   -> <ins>def</ins>xxx<del>abc</del>\n  // Only extract an overlap if it is as big as the edit ahead or behind it.\n  pointer = 1;\n  while (pointer < diffs.length) {\n    if (diffs[pointer - 1][0] == DIFF_DELETE &&\n        diffs[pointer][0] == DIFF_INSERT) {\n      var deletion = diffs[pointer - 1][1];\n      var insertion = diffs[pointer][1];\n      var overlap_length1 = this.diff_commonOverlap_(deletion, insertion);\n      var overlap_length2 = this.diff_commonOverlap_(insertion, deletion);\n      if (overlap_length1 >= overlap_length2) {\n        if (overlap_length1 >= deletion.length / 2 ||\n            overlap_length1 >= insertion.length / 2) {\n          // Overlap found.  Insert an equality and trim the surrounding edits.\n          diffs.splice(pointer, 0,\n              [DIFF_EQUAL, insertion.substring(0, overlap_length1)]);\n          diffs[pointer - 1][1] =\n              deletion.substring(0, deletion.length - overlap_length1);\n          diffs[pointer + 1][1] = insertion.substring(overlap_length1);\n          pointer++;\n        }\n      } else {\n        if (overlap_length2 >= deletion.length / 2 ||\n            overlap_length2 >= insertion.length / 2) {\n          // Reverse overlap found.\n          // Insert an equality and swap and trim the surrounding edits.\n          diffs.splice(pointer, 0,\n              [DIFF_EQUAL, deletion.substring(0, overlap_length2)]);\n          diffs[pointer - 1][0] = DIFF_INSERT;\n          diffs[pointer - 1][1] =\n              insertion.substring(0, insertion.length - overlap_length2);\n          diffs[pointer + 1][0] = DIFF_DELETE;\n          diffs[pointer + 1][1] =\n              deletion.substring(overlap_length2);\n          pointer++;\n        }\n      }\n      pointer++;\n    }\n    pointer++;\n  }\n};\n\n\n/**\n * Look for single edits surrounded on both sides by equalities\n * which can be shifted sideways to align the edit to a word boundary.\n * e.g: The c<ins>at c</ins>ame. -> The <ins>cat </ins>came.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_cleanupSemanticLossless = function(diffs) {\n  /**\n   * Given two strings, compute a score representing whether the internal\n   * boundary falls on logical boundaries.\n   * Scores range from 6 (best) to 0 (worst).\n   * Closure, but does not reference any external variables.\n   * @param {string} one First string.\n   * @param {string} two Second string.\n   * @return {number} The score.\n   * @private\n   */\n  function diff_cleanupSemanticScore_(one, two) {\n    if (!one || !two) {\n      // Edges are the best.\n      return 6;\n    }\n\n    // Each port of this function behaves slightly differently due to\n    // subtle differences in each language's definition of things like\n    // 'whitespace'.  Since this function's purpose is largely cosmetic,\n    // the choice has been made to use each language's native features\n    // rather than force total conformity.\n    var char1 = one.charAt(one.length - 1);\n    var char2 = two.charAt(0);\n    var nonAlphaNumeric1 = char1.match(diff_match_patch.nonAlphaNumericRegex_);\n    var nonAlphaNumeric2 = char2.match(diff_match_patch.nonAlphaNumericRegex_);\n    var whitespace1 = nonAlphaNumeric1 &&\n        char1.match(diff_match_patch.whitespaceRegex_);\n    var whitespace2 = nonAlphaNumeric2 &&\n        char2.match(diff_match_patch.whitespaceRegex_);\n    var lineBreak1 = whitespace1 &&\n        char1.match(diff_match_patch.linebreakRegex_);\n    var lineBreak2 = whitespace2 &&\n        char2.match(diff_match_patch.linebreakRegex_);\n    var blankLine1 = lineBreak1 &&\n        one.match(diff_match_patch.blanklineEndRegex_);\n    var blankLine2 = lineBreak2 &&\n        two.match(diff_match_patch.blanklineStartRegex_);\n\n    if (blankLine1 || blankLine2) {\n      // Five points for blank lines.\n      return 5;\n    } else if (lineBreak1 || lineBreak2) {\n      // Four points for line breaks.\n      return 4;\n    } else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) {\n      // Three points for end of sentences.\n      return 3;\n    } else if (whitespace1 || whitespace2) {\n      // Two points for whitespace.\n      return 2;\n    } else if (nonAlphaNumeric1 || nonAlphaNumeric2) {\n      // One point for non-alphanumeric.\n      return 1;\n    }\n    return 0;\n  }\n\n  var pointer = 1;\n  // Intentionally ignore the first and last element (don't need checking).\n  while (pointer < diffs.length - 1) {\n    if (diffs[pointer - 1][0] == DIFF_EQUAL &&\n        diffs[pointer + 1][0] == DIFF_EQUAL) {\n      // This is a single edit surrounded by equalities.\n      var equality1 = diffs[pointer - 1][1];\n      var edit = diffs[pointer][1];\n      var equality2 = diffs[pointer + 1][1];\n\n      // First, shift the edit as far left as possible.\n      var commonOffset = this.diff_commonSuffix(equality1, edit);\n      if (commonOffset) {\n        var commonString = edit.substring(edit.length - commonOffset);\n        equality1 = equality1.substring(0, equality1.length - commonOffset);\n        edit = commonString + edit.substring(0, edit.length - commonOffset);\n        equality2 = commonString + equality2;\n      }\n\n      // Second, step character by character right, looking for the best fit.\n      var bestEquality1 = equality1;\n      var bestEdit = edit;\n      var bestEquality2 = equality2;\n      var bestScore = diff_cleanupSemanticScore_(equality1, edit) +\n          diff_cleanupSemanticScore_(edit, equality2);\n      while (edit.charAt(0) === equality2.charAt(0)) {\n        equality1 += edit.charAt(0);\n        edit = edit.substring(1) + equality2.charAt(0);\n        equality2 = equality2.substring(1);\n        var score = diff_cleanupSemanticScore_(equality1, edit) +\n            diff_cleanupSemanticScore_(edit, equality2);\n        // The >= encourages trailing rather than leading whitespace on edits.\n        if (score >= bestScore) {\n          bestScore = score;\n          bestEquality1 = equality1;\n          bestEdit = edit;\n          bestEquality2 = equality2;\n        }\n      }\n\n      if (diffs[pointer - 1][1] != bestEquality1) {\n        // We have an improvement, save it back to the diff.\n        if (bestEquality1) {\n          diffs[pointer - 1][1] = bestEquality1;\n        } else {\n          diffs.splice(pointer - 1, 1);\n          pointer--;\n        }\n        diffs[pointer][1] = bestEdit;\n        if (bestEquality2) {\n          diffs[pointer + 1][1] = bestEquality2;\n        } else {\n          diffs.splice(pointer + 1, 1);\n          pointer--;\n        }\n      }\n    }\n    pointer++;\n  }\n};\n\n// Define some regex patterns for matching boundaries.\ndiff_match_patch.nonAlphaNumericRegex_ = /[^a-zA-Z0-9]/;\ndiff_match_patch.whitespaceRegex_ = /\\s/;\ndiff_match_patch.linebreakRegex_ = /[\\r\\n]/;\ndiff_match_patch.blanklineEndRegex_ = /\\n\\r?\\n$/;\ndiff_match_patch.blanklineStartRegex_ = /^\\r?\\n\\r?\\n/;\n\n/**\n * Reduce the number of edits by eliminating operationally trivial equalities.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_cleanupEfficiency = function(diffs) {\n  var changes = false;\n  var equalities = [];  // Stack of indices where equalities are found.\n  var equalitiesLength = 0;  // Keeping our own length var is faster in JS.\n  /** @type {?string} */\n  var lastequality = null;\n  // Always equal to diffs[equalities[equalitiesLength - 1]][1]\n  var pointer = 0;  // Index of current position.\n  // Is there an insertion operation before the last equality.\n  var pre_ins = false;\n  // Is there a deletion operation before the last equality.\n  var pre_del = false;\n  // Is there an insertion operation after the last equality.\n  var post_ins = false;\n  // Is there a deletion operation after the last equality.\n  var post_del = false;\n  while (pointer < diffs.length) {\n    if (diffs[pointer][0] == DIFF_EQUAL) {  // Equality found.\n      if (diffs[pointer][1].length < this.Diff_EditCost &&\n          (post_ins || post_del)) {\n        // Candidate found.\n        equalities[equalitiesLength++] = pointer;\n        pre_ins = post_ins;\n        pre_del = post_del;\n        lastequality = diffs[pointer][1];\n      } else {\n        // Not a candidate, and can never become one.\n        equalitiesLength = 0;\n        lastequality = null;\n      }\n      post_ins = post_del = false;\n    } else {  // An insertion or deletion.\n      if (diffs[pointer][0] == DIFF_DELETE) {\n        post_del = true;\n      } else {\n        post_ins = true;\n      }\n      /*\n       * Five types to be split:\n       * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>\n       * <ins>A</ins>X<ins>C</ins><del>D</del>\n       * <ins>A</ins><del>B</del>X<ins>C</ins>\n       * <ins>A</del>X<ins>C</ins><del>D</del>\n       * <ins>A</ins><del>B</del>X<del>C</del>\n       */\n      if (lastequality && ((pre_ins && pre_del && post_ins && post_del) ||\n                           ((lastequality.length < this.Diff_EditCost / 2) &&\n                            (pre_ins + pre_del + post_ins + post_del) == 3))) {\n        // Duplicate record.\n        diffs.splice(equalities[equalitiesLength - 1], 0,\n                     [DIFF_DELETE, lastequality]);\n        // Change second copy to insert.\n        diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;\n        equalitiesLength--;  // Throw away the equality we just deleted;\n        lastequality = null;\n        if (pre_ins && pre_del) {\n          // No changes made which could affect previous entry, keep going.\n          post_ins = post_del = true;\n          equalitiesLength = 0;\n        } else {\n          equalitiesLength--;  // Throw away the previous equality.\n          pointer = equalitiesLength > 0 ?\n              equalities[equalitiesLength - 1] : -1;\n          post_ins = post_del = false;\n        }\n        changes = true;\n      }\n    }\n    pointer++;\n  }\n\n  if (changes) {\n    this.diff_cleanupMerge(diffs);\n  }\n};\n\n\n/**\n * Reorder and merge like edit sections.  Merge equalities.\n * Any edit section can move as long as it doesn't cross an equality.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n */\ndiff_match_patch.prototype.diff_cleanupMerge = function(diffs) {\n  diffs.push([DIFF_EQUAL, '']);  // Add a dummy entry at the end.\n  var pointer = 0;\n  var count_delete = 0;\n  var count_insert = 0;\n  var text_delete = '';\n  var text_insert = '';\n  var commonlength;\n  while (pointer < diffs.length) {\n    switch (diffs[pointer][0]) {\n      case DIFF_INSERT:\n        count_insert++;\n        text_insert += diffs[pointer][1];\n        pointer++;\n        break;\n      case DIFF_DELETE:\n        count_delete++;\n        text_delete += diffs[pointer][1];\n        pointer++;\n        break;\n      case DIFF_EQUAL:\n        // Upon reaching an equality, check for prior redundancies.\n        if (count_delete + count_insert > 1) {\n          if (count_delete !== 0 && count_insert !== 0) {\n            // Factor out any common prefixies.\n            commonlength = this.diff_commonPrefix(text_insert, text_delete);\n            if (commonlength !== 0) {\n              if ((pointer - count_delete - count_insert) > 0 &&\n                  diffs[pointer - count_delete - count_insert - 1][0] ==\n                  DIFF_EQUAL) {\n                diffs[pointer - count_delete - count_insert - 1][1] +=\n                    text_insert.substring(0, commonlength);\n              } else {\n                diffs.splice(0, 0, [DIFF_EQUAL,\n                                    text_insert.substring(0, commonlength)]);\n                pointer++;\n              }\n              text_insert = text_insert.substring(commonlength);\n              text_delete = text_delete.substring(commonlength);\n            }\n            // Factor out any common suffixies.\n            commonlength = this.diff_commonSuffix(text_insert, text_delete);\n            if (commonlength !== 0) {\n              diffs[pointer][1] = text_insert.substring(text_insert.length -\n                  commonlength) + diffs[pointer][1];\n              text_insert = text_insert.substring(0, text_insert.length -\n                  commonlength);\n              text_delete = text_delete.substring(0, text_delete.length -\n                  commonlength);\n            }\n          }\n          // Delete the offending records and add the merged ones.\n          if (count_delete === 0) {\n            diffs.splice(pointer - count_insert,\n                count_delete + count_insert, [DIFF_INSERT, text_insert]);\n          } else if (count_insert === 0) {\n            diffs.splice(pointer - count_delete,\n                count_delete + count_insert, [DIFF_DELETE, text_delete]);\n          } else {\n            diffs.splice(pointer - count_delete - count_insert,\n                count_delete + count_insert, [DIFF_DELETE, text_delete],\n                [DIFF_INSERT, text_insert]);\n          }\n          pointer = pointer - count_delete - count_insert +\n                    (count_delete ? 1 : 0) + (count_insert ? 1 : 0) + 1;\n        } else if (pointer !== 0 && diffs[pointer - 1][0] == DIFF_EQUAL) {\n          // Merge this equality with the previous one.\n          diffs[pointer - 1][1] += diffs[pointer][1];\n          diffs.splice(pointer, 1);\n        } else {\n          pointer++;\n        }\n        count_insert = 0;\n        count_delete = 0;\n        text_delete = '';\n        text_insert = '';\n        break;\n    }\n  }\n  if (diffs[diffs.length - 1][1] === '') {\n    diffs.pop();  // Remove the dummy entry at the end.\n  }\n\n  // Second pass: look for single edits surrounded on both sides by equalities\n  // which can be shifted sideways to eliminate an equality.\n  // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC\n  var changes = false;\n  pointer = 1;\n  // Intentionally ignore the first and last element (don't need checking).\n  while (pointer < diffs.length - 1) {\n    if (diffs[pointer - 1][0] == DIFF_EQUAL &&\n        diffs[pointer + 1][0] == DIFF_EQUAL) {\n      // This is a single edit surrounded by equalities.\n      if (diffs[pointer][1].substring(diffs[pointer][1].length -\n          diffs[pointer - 1][1].length) == diffs[pointer - 1][1]) {\n        // Shift the edit over the previous equality.\n        diffs[pointer][1] = diffs[pointer - 1][1] +\n            diffs[pointer][1].substring(0, diffs[pointer][1].length -\n                                        diffs[pointer - 1][1].length);\n        diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];\n        diffs.splice(pointer - 1, 1);\n        changes = true;\n      } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) ==\n          diffs[pointer + 1][1]) {\n        // Shift the edit over the next equality.\n        diffs[pointer - 1][1] += diffs[pointer + 1][1];\n        diffs[pointer][1] =\n            diffs[pointer][1].substring(diffs[pointer + 1][1].length) +\n            diffs[pointer + 1][1];\n        diffs.splice(pointer + 1, 1);\n        changes = true;\n      }\n    }\n    pointer++;\n  }\n  // If shifts were made, the diff needs reordering and another shift sweep.\n  if (changes) {\n    this.diff_cleanupMerge(diffs);\n  }\n};\n\n\n/**\n * loc is a location in text1, compute and return the equivalent location in\n * text2.\n * e.g. 'The cat' vs 'The big cat', 1->1, 5->8\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @param {number} loc Location within text1.\n * @return {number} Location within text2.\n */\ndiff_match_patch.prototype.diff_xIndex = function(diffs, loc) {\n  var chars1 = 0;\n  var chars2 = 0;\n  var last_chars1 = 0;\n  var last_chars2 = 0;\n  var x;\n  for (x = 0; x < diffs.length; x++) {\n    if (diffs[x][0] !== DIFF_INSERT) {  // Equality or deletion.\n      chars1 += diffs[x][1].length;\n    }\n    if (diffs[x][0] !== DIFF_DELETE) {  // Equality or insertion.\n      chars2 += diffs[x][1].length;\n    }\n    if (chars1 > loc) {  // Overshot the location.\n      break;\n    }\n    last_chars1 = chars1;\n    last_chars2 = chars2;\n  }\n  // Was the location was deleted?\n  if (diffs.length != x && diffs[x][0] === DIFF_DELETE) {\n    return last_chars2;\n  }\n  // Add the remaining character length.\n  return last_chars2 + (loc - last_chars1);\n};\n\n\n/**\n * Convert a diff array into a pretty HTML report.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {string} HTML representation.\n */\ndiff_match_patch.prototype.diff_prettyHtml = function(diffs) {\n  var html = [];\n  var pattern_amp = /&/g;\n  var pattern_lt = /</g;\n  var pattern_gt = />/g;\n  var pattern_para = /\\n/g;\n  for (var x = 0; x < diffs.length; x++) {\n    var op = diffs[x][0];    // Operation (insert, delete, equal)\n    var data = diffs[x][1];  // Text of change.\n    var text = data.replace(pattern_amp, '&amp;').replace(pattern_lt, '&lt;')\n        .replace(pattern_gt, '&gt;').replace(pattern_para, '&para;<br>');\n    switch (op) {\n      case DIFF_INSERT:\n        html[x] = '<ins style=\"background:#e6ffe6;\">' + text + '</ins>';\n        break;\n      case DIFF_DELETE:\n        html[x] = '<del style=\"background:#ffe6e6;\">' + text + '</del>';\n        break;\n      case DIFF_EQUAL:\n        html[x] = '<span>' + text + '</span>';\n        break;\n    }\n  }\n  return html.join('');\n};\n\n\n/**\n * Compute and return the source text (all equalities and deletions).\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {string} Source text.\n */\ndiff_match_patch.prototype.diff_text1 = function(diffs) {\n  var text = [];\n  for (var x = 0; x < diffs.length; x++) {\n    if (diffs[x][0] !== DIFF_INSERT) {\n      text[x] = diffs[x][1];\n    }\n  }\n  return text.join('');\n};\n\n\n/**\n * Compute and return the destination text (all equalities and insertions).\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {string} Destination text.\n */\ndiff_match_patch.prototype.diff_text2 = function(diffs) {\n  var text = [];\n  for (var x = 0; x < diffs.length; x++) {\n    if (diffs[x][0] !== DIFF_DELETE) {\n      text[x] = diffs[x][1];\n    }\n  }\n  return text.join('');\n};\n\n\n/**\n * Compute the Levenshtein distance; the number of inserted, deleted or\n * substituted characters.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {number} Number of changes.\n */\ndiff_match_patch.prototype.diff_levenshtein = function(diffs) {\n  var levenshtein = 0;\n  var insertions = 0;\n  var deletions = 0;\n  for (var x = 0; x < diffs.length; x++) {\n    var op = diffs[x][0];\n    var data = diffs[x][1];\n    switch (op) {\n      case DIFF_INSERT:\n        insertions += data.length;\n        break;\n      case DIFF_DELETE:\n        deletions += data.length;\n        break;\n      case DIFF_EQUAL:\n        // A deletion and an insertion is one substitution.\n        levenshtein += Math.max(insertions, deletions);\n        insertions = 0;\n        deletions = 0;\n        break;\n    }\n  }\n  levenshtein += Math.max(insertions, deletions);\n  return levenshtein;\n};\n\n\n/**\n * Crush the diff into an encoded string which describes the operations\n * required to transform text1 into text2.\n * E.g. =3\\t-2\\t+ing  -> Keep 3 chars, delete 2 chars, insert 'ing'.\n * Operations are tab-separated.  Inserted text is escaped using %xx notation.\n * @param {!Array.<!diff_match_patch.Diff>} diffs Array of diff tuples.\n * @return {string} Delta text.\n */\ndiff_match_patch.prototype.diff_toDelta = function(diffs) {\n  var text = [];\n  for (var x = 0; x < diffs.length; x++) {\n    switch (diffs[x][0]) {\n      case DIFF_INSERT:\n        text[x] = '+' + encodeURI(diffs[x][1]);\n        break;\n      case DIFF_DELETE:\n        text[x] = '-' + diffs[x][1].length;\n        break;\n      case DIFF_EQUAL:\n        text[x] = '=' + diffs[x][1].length;\n        break;\n    }\n  }\n  return text.join('\\t').replace(/%20/g, ' ');\n};\n\n\n/**\n * Given the original text1, and an encoded string which describes the\n * operations required to transform text1 into text2, compute the full diff.\n * @param {string} text1 Source string for the diff.\n * @param {string} delta Delta text.\n * @return {!Array.<!diff_match_patch.Diff>} Array of diff tuples.\n * @throws {!Error} If invalid input.\n */\ndiff_match_patch.prototype.diff_fromDelta = function(text1, delta) {\n  var diffs = [];\n  var diffsLength = 0;  // Keeping our own length var is faster in JS.\n  var pointer = 0;  // Cursor in text1\n  var tokens = delta.split(/\\t/g);\n  for (var x = 0; x < tokens.length; x++) {\n    // Each token begins with a one character parameter which specifies the\n    // operation of this token (delete, insert, equality).\n    var param = tokens[x].substring(1);\n    switch (tokens[x].charAt(0)) {\n      case '+':\n        try {\n          diffs[diffsLength++] = [DIFF_INSERT, decodeURI(param)];\n        } catch (ex) {\n          // Malformed URI sequence.\n          throw new Error('Illegal escape in diff_fromDelta: ' + param);\n        }\n        break;\n      case '-':\n        // Fall through.\n      case '=':\n        var n = parseInt(param, 10);\n        if (isNaN(n) || n < 0) {\n          throw new Error('Invalid number in diff_fromDelta: ' + param);\n        }\n        var text = text1.substring(pointer, pointer += n);\n        if (tokens[x].charAt(0) == '=') {\n          diffs[diffsLength++] = [DIFF_EQUAL, text];\n        } else {\n          diffs[diffsLength++] = [DIFF_DELETE, text];\n        }\n        break;\n      default:\n        // Blank tokens are ok (from a trailing \\t).\n        // Anything else is an error.\n        if (tokens[x]) {\n          throw new Error('Invalid diff operation in diff_fromDelta: ' +\n                          tokens[x]);\n        }\n    }\n  }\n  if (pointer != text1.length) {\n    throw new Error('Delta length (' + pointer +\n        ') does not equal source text length (' + text1.length + ').');\n  }\n  return diffs;\n};\n\n\n//  MATCH FUNCTIONS\n\n\n/**\n * Locate the best instance of 'pattern' in 'text' near 'loc'.\n * @param {string} text The text to search.\n * @param {string} pattern The pattern to search for.\n * @param {number} loc The location to search around.\n * @return {number} Best match index or -1.\n */\ndiff_match_patch.prototype.match_main = function(text, pattern, loc) {\n  // Check for null inputs.\n  if (text == null || pattern == null || loc == null) {\n    throw new Error('Null input. (match_main)');\n  }\n\n  loc = Math.max(0, Math.min(loc, text.length));\n  if (text == pattern) {\n    // Shortcut (potentially not guaranteed by the algorithm)\n    return 0;\n  } else if (!text.length) {\n    // Nothing to match.\n    return -1;\n  } else if (text.substring(loc, loc + pattern.length) == pattern) {\n    // Perfect match at the perfect spot!  (Includes case of null pattern)\n    return loc;\n  } else {\n    // Do a fuzzy compare.\n    return this.match_bitap_(text, pattern, loc);\n  }\n};\n\n\n/**\n * Locate the best instance of 'pattern' in 'text' near 'loc' using the\n * Bitap algorithm.\n * @param {string} text The text to search.\n * @param {string} pattern The pattern to search for.\n * @param {number} loc The location to search around.\n * @return {number} Best match index or -1.\n * @private\n */\ndiff_match_patch.prototype.match_bitap_ = function(text, pattern, loc) {\n  if (pattern.length > this.Match_MaxBits) {\n    throw new Error('Pattern too long for this browser.');\n  }\n\n  // Initialise the alphabet.\n  var s = this.match_alphabet_(pattern);\n\n  var dmp = this;  // 'this' becomes 'window' in a closure.\n\n  /**\n   * Compute and return the score for a match with e errors and x location.\n   * Accesses loc and pattern through being a closure.\n   * @param {number} e Number of errors in match.\n   * @param {number} x Location of match.\n   * @return {number} Overall score for match (0.0 = good, 1.0 = bad).\n   * @private\n   */\n  function match_bitapScore_(e, x) {\n    var accuracy = e / pattern.length;\n    var proximity = Math.abs(loc - x);\n    if (!dmp.Match_Distance) {\n      // Dodge divide by zero error.\n      return proximity ? 1.0 : accuracy;\n    }\n    return accuracy + (proximity / dmp.Match_Distance);\n  }\n\n  // Highest score beyond which we give up.\n  var score_threshold = this.Match_Threshold;\n  // Is there a nearby exact match? (speedup)\n  var best_loc = text.indexOf(pattern, loc);\n  if (best_loc != -1) {\n    score_threshold = Math.min(match_bitapScore_(0, best_loc), score_threshold);\n    // What about in the other direction? (speedup)\n    best_loc = text.lastIndexOf(pattern, loc + pattern.length);\n    if (best_loc != -1) {\n      score_threshold =\n          Math.min(match_bitapScore_(0, best_loc), score_threshold);\n    }\n  }\n\n  // Initialise the bit arrays.\n  var matchmask = 1 << (pattern.length - 1);\n  best_loc = -1;\n\n  var bin_min, bin_mid;\n  var bin_max = pattern.length + text.length;\n  var last_rd;\n  for (var d = 0; d < pattern.length; d++) {\n    // Scan for the best match; each iteration allows for one more error.\n    // Run a binary search to determine how far from 'loc' we can stray at this\n    // error level.\n    bin_min = 0;\n    bin_mid = bin_max;\n    while (bin_min < bin_mid) {\n      if (match_bitapScore_(d, loc + bin_mid) <= score_threshold) {\n        bin_min = bin_mid;\n      } else {\n        bin_max = bin_mid;\n      }\n      bin_mid = Math.floor((bin_max - bin_min) / 2 + bin_min);\n    }\n    // Use the result from this iteration as the maximum for the next.\n    bin_max = bin_mid;\n    var start = Math.max(1, loc - bin_mid + 1);\n    var finish = Math.min(loc + bin_mid, text.length) + pattern.length;\n\n    var rd = Array(finish + 2);\n    rd[finish + 1] = (1 << d) - 1;\n    for (var j = finish; j >= start; j--) {\n      // The alphabet (s) is a sparse hash, so the following line generates\n      // warnings.\n      var charMatch = s[text.charAt(j - 1)];\n      if (d === 0) {  // First pass: exact match.\n        rd[j] = ((rd[j + 1] << 1) | 1) & charMatch;\n      } else {  // Subsequent passes: fuzzy match.\n        rd[j] = (((rd[j + 1] << 1) | 1) & charMatch) |\n                (((last_rd[j + 1] | last_rd[j]) << 1) | 1) |\n                last_rd[j + 1];\n      }\n      if (rd[j] & matchmask) {\n        var score = match_bitapScore_(d, j - 1);\n        // This match will almost certainly be better than any existing match.\n        // But check anyway.\n        if (score <= score_threshold) {\n          // Told you so.\n          score_threshold = score;\n          best_loc = j - 1;\n          if (best_loc > loc) {\n            // When passing loc, don't exceed our current distance from loc.\n            start = Math.max(1, 2 * loc - best_loc);\n          } else {\n            // Already passed loc, downhill from here on in.\n            break;\n          }\n        }\n      }\n    }\n    // No hope for a (better) match at greater error levels.\n    if (match_bitapScore_(d + 1, loc) > score_threshold) {\n      break;\n    }\n    last_rd = rd;\n  }\n  return best_loc;\n};\n\n\n/**\n * Initialise the alphabet for the Bitap algorithm.\n * @param {string} pattern The text to encode.\n * @return {!Object} Hash of character locations.\n * @private\n */\ndiff_match_patch.prototype.match_alphabet_ = function(pattern) {\n  var s = {};\n  for (var i = 0; i < pattern.length; i++) {\n    s[pattern.charAt(i)] = 0;\n  }\n  for (var i = 0; i < pattern.length; i++) {\n    s[pattern.charAt(i)] |= 1 << (pattern.length - i - 1);\n  }\n  return s;\n};\n\n\n//  PATCH FUNCTIONS\n\n\n/**\n * Increase the context until it is unique,\n * but don't let the pattern expand beyond Match_MaxBits.\n * @param {!diff_match_patch.patch_obj} patch The patch to grow.\n * @param {string} text Source text.\n * @private\n */\ndiff_match_patch.prototype.patch_addContext_ = function(patch, text) {\n  if (text.length == 0) {\n    return;\n  }\n  var pattern = text.substring(patch.start2, patch.start2 + patch.length1);\n  var padding = 0;\n\n  // Look for the first and last matches of pattern in text.  If two different\n  // matches are found, increase the pattern length.\n  while (text.indexOf(pattern) != text.lastIndexOf(pattern) &&\n         pattern.length < this.Match_MaxBits - this.Patch_Margin -\n         this.Patch_Margin) {\n    padding += this.Patch_Margin;\n    pattern = text.substring(patch.start2 - padding,\n                             patch.start2 + patch.length1 + padding);\n  }\n  // Add one chunk for good luck.\n  padding += this.Patch_Margin;\n\n  // Add the prefix.\n  var prefix = text.substring(patch.start2 - padding, patch.start2);\n  if (prefix) {\n    patch.diffs.unshift([DIFF_EQUAL, prefix]);\n  }\n  // Add the suffix.\n  var suffix = text.substring(patch.start2 + patch.length1,\n                              patch.start2 + patch.length1 + padding);\n  if (suffix) {\n    patch.diffs.push([DIFF_EQUAL, suffix]);\n  }\n\n  // Roll back the start points.\n  patch.start1 -= prefix.length;\n  patch.start2 -= prefix.length;\n  // Extend the lengths.\n  patch.length1 += prefix.length + suffix.length;\n  patch.length2 += prefix.length + suffix.length;\n};\n\n\n/**\n * Compute a list of patches to turn text1 into text2.\n * Use diffs if provided, otherwise compute it ourselves.\n * There are four ways to call this function, depending on what data is\n * available to the caller:\n * Method 1:\n * a = text1, b = text2\n * Method 2:\n * a = diffs\n * Method 3 (optimal):\n * a = text1, b = diffs\n * Method 4 (deprecated, use method 3):\n * a = text1, b = text2, c = diffs\n *\n * @param {string|!Array.<!diff_match_patch.Diff>} a text1 (methods 1,3,4) or\n * Array of diff tuples for text1 to text2 (method 2).\n * @param {string|!Array.<!diff_match_patch.Diff>} opt_b text2 (methods 1,4) or\n * Array of diff tuples for text1 to text2 (method 3) or undefined (method 2).\n * @param {string|!Array.<!diff_match_patch.Diff>} opt_c Array of diff tuples\n * for text1 to text2 (method 4) or undefined (methods 1,2,3).\n * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.\n */\ndiff_match_patch.prototype.patch_make = function(a, opt_b, opt_c) {\n  var text1, diffs;\n  if (typeof a == 'string' && typeof opt_b == 'string' &&\n      typeof opt_c == 'undefined') {\n    // Method 1: text1, text2\n    // Compute diffs from text1 and text2.\n    text1 = /** @type {string} */(a);\n    diffs = this.diff_main(text1, /** @type {string} */(opt_b), true);\n    if (diffs.length > 2) {\n      this.diff_cleanupSemantic(diffs);\n      this.diff_cleanupEfficiency(diffs);\n    }\n  } else if (a && typeof a == 'object' && typeof opt_b == 'undefined' &&\n      typeof opt_c == 'undefined') {\n    // Method 2: diffs\n    // Compute text1 from diffs.\n    diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(a);\n    text1 = this.diff_text1(diffs);\n  } else if (typeof a == 'string' && opt_b && typeof opt_b == 'object' &&\n      typeof opt_c == 'undefined') {\n    // Method 3: text1, diffs\n    text1 = /** @type {string} */(a);\n    diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(opt_b);\n  } else if (typeof a == 'string' && typeof opt_b == 'string' &&\n      opt_c && typeof opt_c == 'object') {\n    // Method 4: text1, text2, diffs\n    // text2 is not used.\n    text1 = /** @type {string} */(a);\n    diffs = /** @type {!Array.<!diff_match_patch.Diff>} */(opt_c);\n  } else {\n    throw new Error('Unknown call format to patch_make.');\n  }\n\n  if (diffs.length === 0) {\n    return [];  // Get rid of the null case.\n  }\n  var patches = [];\n  var patch = new diff_match_patch.patch_obj();\n  var patchDiffLength = 0;  // Keeping our own length var is faster in JS.\n  var char_count1 = 0;  // Number of characters into the text1 string.\n  var char_count2 = 0;  // Number of characters into the text2 string.\n  // Start with text1 (prepatch_text) and apply the diffs until we arrive at\n  // text2 (postpatch_text).  We recreate the patches one by one to determine\n  // context info.\n  var prepatch_text = text1;\n  var postpatch_text = text1;\n  for (var x = 0; x < diffs.length; x++) {\n    var diff_type = diffs[x][0];\n    var diff_text = diffs[x][1];\n\n    if (!patchDiffLength && diff_type !== DIFF_EQUAL) {\n      // A new patch starts here.\n      patch.start1 = char_count1;\n      patch.start2 = char_count2;\n    }\n\n    switch (diff_type) {\n      case DIFF_INSERT:\n        patch.diffs[patchDiffLength++] = diffs[x];\n        patch.length2 += diff_text.length;\n        postpatch_text = postpatch_text.substring(0, char_count2) + diff_text +\n                         postpatch_text.substring(char_count2);\n        break;\n      case DIFF_DELETE:\n        patch.length1 += diff_text.length;\n        patch.diffs[patchDiffLength++] = diffs[x];\n        postpatch_text = postpatch_text.substring(0, char_count2) +\n                         postpatch_text.substring(char_count2 +\n                             diff_text.length);\n        break;\n      case DIFF_EQUAL:\n        if (diff_text.length <= 2 * this.Patch_Margin &&\n            patchDiffLength && diffs.length != x + 1) {\n          // Small equality inside a patch.\n          patch.diffs[patchDiffLength++] = diffs[x];\n          patch.length1 += diff_text.length;\n          patch.length2 += diff_text.length;\n        } else if (diff_text.length >= 2 * this.Patch_Margin) {\n          // Time for a new patch.\n          if (patchDiffLength) {\n            this.patch_addContext_(patch, prepatch_text);\n            patches.push(patch);\n            patch = new diff_match_patch.patch_obj();\n            patchDiffLength = 0;\n            // Unlike Unidiff, our patch lists have a rolling context.\n            // http://code.google.com/p/google-diff-match-patch/wiki/Unidiff\n            // Update prepatch text & pos to reflect the application of the\n            // just completed patch.\n            prepatch_text = postpatch_text;\n            char_count1 = char_count2;\n          }\n        }\n        break;\n    }\n\n    // Update the current character count.\n    if (diff_type !== DIFF_INSERT) {\n      char_count1 += diff_text.length;\n    }\n    if (diff_type !== DIFF_DELETE) {\n      char_count2 += diff_text.length;\n    }\n  }\n  // Pick up the leftover patch if not empty.\n  if (patchDiffLength) {\n    this.patch_addContext_(patch, prepatch_text);\n    patches.push(patch);\n  }\n\n  return patches;\n};\n\n\n/**\n * Given an array of patches, return another array that is identical.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.\n */\ndiff_match_patch.prototype.patch_deepCopy = function(patches) {\n  // Making deep copies is hard in JavaScript.\n  var patchesCopy = [];\n  for (var x = 0; x < patches.length; x++) {\n    var patch = patches[x];\n    var patchCopy = new diff_match_patch.patch_obj();\n    patchCopy.diffs = [];\n    for (var y = 0; y < patch.diffs.length; y++) {\n      patchCopy.diffs[y] = patch.diffs[y].slice();\n    }\n    patchCopy.start1 = patch.start1;\n    patchCopy.start2 = patch.start2;\n    patchCopy.length1 = patch.length1;\n    patchCopy.length2 = patch.length2;\n    patchesCopy[x] = patchCopy;\n  }\n  return patchesCopy;\n};\n\n\n/**\n * Merge a set of patches onto the text.  Return a patched text, as well\n * as a list of true/false values indicating which patches were applied.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n * @param {string} text Old text.\n * @return {!Array.<string|!Array.<boolean>>} Two element Array, containing the\n *      new text and an array of boolean values.\n */\ndiff_match_patch.prototype.patch_apply = function(patches, text) {\n  if (patches.length == 0) {\n    return [text, []];\n  }\n\n  // Deep copy the patches so that no changes are made to originals.\n  patches = this.patch_deepCopy(patches);\n\n  var nullPadding = this.patch_addPadding(patches);\n  text = nullPadding + text + nullPadding;\n\n  this.patch_splitMax(patches);\n  // delta keeps track of the offset between the expected and actual location\n  // of the previous patch.  If there are patches expected at positions 10 and\n  // 20, but the first patch was found at 12, delta is 2 and the second patch\n  // has an effective expected position of 22.\n  var delta = 0;\n  var results = [];\n  for (var x = 0; x < patches.length; x++) {\n    var expected_loc = patches[x].start2 + delta;\n    var text1 = this.diff_text1(patches[x].diffs);\n    var start_loc;\n    var end_loc = -1;\n    if (text1.length > this.Match_MaxBits) {\n      // patch_splitMax will only provide an oversized pattern in the case of\n      // a monster delete.\n      start_loc = this.match_main(text, text1.substring(0, this.Match_MaxBits),\n                                  expected_loc);\n      if (start_loc != -1) {\n        end_loc = this.match_main(text,\n            text1.substring(text1.length - this.Match_MaxBits),\n            expected_loc + text1.length - this.Match_MaxBits);\n        if (end_loc == -1 || start_loc >= end_loc) {\n          // Can't find valid trailing context.  Drop this patch.\n          start_loc = -1;\n        }\n      }\n    } else {\n      start_loc = this.match_main(text, text1, expected_loc);\n    }\n    if (start_loc == -1) {\n      // No match found.  :(\n      results[x] = false;\n      // Subtract the delta for this failed patch from subsequent patches.\n      delta -= patches[x].length2 - patches[x].length1;\n    } else {\n      // Found a match.  :)\n      results[x] = true;\n      delta = start_loc - expected_loc;\n      var text2;\n      if (end_loc == -1) {\n        text2 = text.substring(start_loc, start_loc + text1.length);\n      } else {\n        text2 = text.substring(start_loc, end_loc + this.Match_MaxBits);\n      }\n      if (text1 == text2) {\n        // Perfect match, just shove the replacement text in.\n        text = text.substring(0, start_loc) +\n               this.diff_text2(patches[x].diffs) +\n               text.substring(start_loc + text1.length);\n      } else {\n        // Imperfect match.  Run a diff to get a framework of equivalent\n        // indices.\n        var diffs = this.diff_main(text1, text2, false);\n        if (text1.length > this.Match_MaxBits &&\n            this.diff_levenshtein(diffs) / text1.length >\n            this.Patch_DeleteThreshold) {\n          // The end points match, but the content is unacceptably bad.\n          results[x] = false;\n        } else {\n          this.diff_cleanupSemanticLossless(diffs);\n          var index1 = 0;\n          var index2;\n          for (var y = 0; y < patches[x].diffs.length; y++) {\n            var mod = patches[x].diffs[y];\n            if (mod[0] !== DIFF_EQUAL) {\n              index2 = this.diff_xIndex(diffs, index1);\n            }\n            if (mod[0] === DIFF_INSERT) {  // Insertion\n              text = text.substring(0, start_loc + index2) + mod[1] +\n                     text.substring(start_loc + index2);\n            } else if (mod[0] === DIFF_DELETE) {  // Deletion\n              text = text.substring(0, start_loc + index2) +\n                     text.substring(start_loc + this.diff_xIndex(diffs,\n                         index1 + mod[1].length));\n            }\n            if (mod[0] !== DIFF_DELETE) {\n              index1 += mod[1].length;\n            }\n          }\n        }\n      }\n    }\n  }\n  // Strip the padding off.\n  text = text.substring(nullPadding.length, text.length - nullPadding.length);\n  return [text, results];\n};\n\n\n/**\n * Add some padding on text start and end so that edges can match something.\n * Intended to be called only from within patch_apply.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n * @return {string} The padding string added to each side.\n */\ndiff_match_patch.prototype.patch_addPadding = function(patches) {\n  var paddingLength = this.Patch_Margin;\n  var nullPadding = '';\n  for (var x = 1; x <= paddingLength; x++) {\n    nullPadding += String.fromCharCode(x);\n  }\n\n  // Bump all the patches forward.\n  for (var x = 0; x < patches.length; x++) {\n    patches[x].start1 += paddingLength;\n    patches[x].start2 += paddingLength;\n  }\n\n  // Add some padding on start of first diff.\n  var patch = patches[0];\n  var diffs = patch.diffs;\n  if (diffs.length == 0 || diffs[0][0] != DIFF_EQUAL) {\n    // Add nullPadding equality.\n    diffs.unshift([DIFF_EQUAL, nullPadding]);\n    patch.start1 -= paddingLength;  // Should be 0.\n    patch.start2 -= paddingLength;  // Should be 0.\n    patch.length1 += paddingLength;\n    patch.length2 += paddingLength;\n  } else if (paddingLength > diffs[0][1].length) {\n    // Grow first equality.\n    var extraLength = paddingLength - diffs[0][1].length;\n    diffs[0][1] = nullPadding.substring(diffs[0][1].length) + diffs[0][1];\n    patch.start1 -= extraLength;\n    patch.start2 -= extraLength;\n    patch.length1 += extraLength;\n    patch.length2 += extraLength;\n  }\n\n  // Add some padding on end of last diff.\n  patch = patches[patches.length - 1];\n  diffs = patch.diffs;\n  if (diffs.length == 0 || diffs[diffs.length - 1][0] != DIFF_EQUAL) {\n    // Add nullPadding equality.\n    diffs.push([DIFF_EQUAL, nullPadding]);\n    patch.length1 += paddingLength;\n    patch.length2 += paddingLength;\n  } else if (paddingLength > diffs[diffs.length - 1][1].length) {\n    // Grow last equality.\n    var extraLength = paddingLength - diffs[diffs.length - 1][1].length;\n    diffs[diffs.length - 1][1] += nullPadding.substring(0, extraLength);\n    patch.length1 += extraLength;\n    patch.length2 += extraLength;\n  }\n\n  return nullPadding;\n};\n\n\n/**\n * Look through the patches and break up any which are longer than the maximum\n * limit of the match algorithm.\n * Intended to be called only from within patch_apply.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n */\ndiff_match_patch.prototype.patch_splitMax = function(patches) {\n  var patch_size = this.Match_MaxBits;\n  for (var x = 0; x < patches.length; x++) {\n    if (patches[x].length1 <= patch_size) {\n      continue;\n    }\n    var bigpatch = patches[x];\n    // Remove the big old patch.\n    patches.splice(x--, 1);\n    var start1 = bigpatch.start1;\n    var start2 = bigpatch.start2;\n    var precontext = '';\n    while (bigpatch.diffs.length !== 0) {\n      // Create one of several smaller patches.\n      var patch = new diff_match_patch.patch_obj();\n      var empty = true;\n      patch.start1 = start1 - precontext.length;\n      patch.start2 = start2 - precontext.length;\n      if (precontext !== '') {\n        patch.length1 = patch.length2 = precontext.length;\n        patch.diffs.push([DIFF_EQUAL, precontext]);\n      }\n      while (bigpatch.diffs.length !== 0 &&\n             patch.length1 < patch_size - this.Patch_Margin) {\n        var diff_type = bigpatch.diffs[0][0];\n        var diff_text = bigpatch.diffs[0][1];\n        if (diff_type === DIFF_INSERT) {\n          // Insertions are harmless.\n          patch.length2 += diff_text.length;\n          start2 += diff_text.length;\n          patch.diffs.push(bigpatch.diffs.shift());\n          empty = false;\n        } else if (diff_type === DIFF_DELETE && patch.diffs.length == 1 &&\n                   patch.diffs[0][0] == DIFF_EQUAL &&\n                   diff_text.length > 2 * patch_size) {\n          // This is a large deletion.  Let it pass in one chunk.\n          patch.length1 += diff_text.length;\n          start1 += diff_text.length;\n          empty = false;\n          patch.diffs.push([diff_type, diff_text]);\n          bigpatch.diffs.shift();\n        } else {\n          // Deletion or equality.  Only take as much as we can stomach.\n          diff_text = diff_text.substring(0,\n              patch_size - patch.length1 - this.Patch_Margin);\n          patch.length1 += diff_text.length;\n          start1 += diff_text.length;\n          if (diff_type === DIFF_EQUAL) {\n            patch.length2 += diff_text.length;\n            start2 += diff_text.length;\n          } else {\n            empty = false;\n          }\n          patch.diffs.push([diff_type, diff_text]);\n          if (diff_text == bigpatch.diffs[0][1]) {\n            bigpatch.diffs.shift();\n          } else {\n            bigpatch.diffs[0][1] =\n                bigpatch.diffs[0][1].substring(diff_text.length);\n          }\n        }\n      }\n      // Compute the head context for the next patch.\n      precontext = this.diff_text2(patch.diffs);\n      precontext =\n          precontext.substring(precontext.length - this.Patch_Margin);\n      // Append the end context for this patch.\n      var postcontext = this.diff_text1(bigpatch.diffs)\n                            .substring(0, this.Patch_Margin);\n      if (postcontext !== '') {\n        patch.length1 += postcontext.length;\n        patch.length2 += postcontext.length;\n        if (patch.diffs.length !== 0 &&\n            patch.diffs[patch.diffs.length - 1][0] === DIFF_EQUAL) {\n          patch.diffs[patch.diffs.length - 1][1] += postcontext;\n        } else {\n          patch.diffs.push([DIFF_EQUAL, postcontext]);\n        }\n      }\n      if (!empty) {\n        patches.splice(++x, 0, patch);\n      }\n    }\n  }\n};\n\n\n/**\n * Take a list of patches and return a textual representation.\n * @param {!Array.<!diff_match_patch.patch_obj>} patches Array of Patch objects.\n * @return {string} Text representation of patches.\n */\ndiff_match_patch.prototype.patch_toText = function(patches) {\n  var text = [];\n  for (var x = 0; x < patches.length; x++) {\n    text[x] = patches[x];\n  }\n  return text.join('');\n};\n\n\n/**\n * Parse a textual representation of patches and return a list of Patch objects.\n * @param {string} textline Text representation of patches.\n * @return {!Array.<!diff_match_patch.patch_obj>} Array of Patch objects.\n * @throws {!Error} If invalid input.\n */\ndiff_match_patch.prototype.patch_fromText = function(textline) {\n  var patches = [];\n  if (!textline) {\n    return patches;\n  }\n  var text = textline.split('\\n');\n  var textPointer = 0;\n  var patchHeader = /^@@ -(\\d+),?(\\d*) \\+(\\d+),?(\\d*) @@$/;\n  while (textPointer < text.length) {\n    var m = text[textPointer].match(patchHeader);\n    if (!m) {\n      throw new Error('Invalid patch string: ' + text[textPointer]);\n    }\n    var patch = new diff_match_patch.patch_obj();\n    patches.push(patch);\n    patch.start1 = parseInt(m[1], 10);\n    if (m[2] === '') {\n      patch.start1--;\n      patch.length1 = 1;\n    } else if (m[2] == '0') {\n      patch.length1 = 0;\n    } else {\n      patch.start1--;\n      patch.length1 = parseInt(m[2], 10);\n    }\n\n    patch.start2 = parseInt(m[3], 10);\n    if (m[4] === '') {\n      patch.start2--;\n      patch.length2 = 1;\n    } else if (m[4] == '0') {\n      patch.length2 = 0;\n    } else {\n      patch.start2--;\n      patch.length2 = parseInt(m[4], 10);\n    }\n    textPointer++;\n\n    while (textPointer < text.length) {\n      var sign = text[textPointer].charAt(0);\n      try {\n        var line = decodeURI(text[textPointer].substring(1));\n      } catch (ex) {\n        // Malformed URI sequence.\n        throw new Error('Illegal escape in patch_fromText: ' + line);\n      }\n      if (sign == '-') {\n        // Deletion.\n        patch.diffs.push([DIFF_DELETE, line]);\n      } else if (sign == '+') {\n        // Insertion.\n        patch.diffs.push([DIFF_INSERT, line]);\n      } else if (sign == ' ') {\n        // Minor equality.\n        patch.diffs.push([DIFF_EQUAL, line]);\n      } else if (sign == '@') {\n        // Start of next patch.\n        break;\n      } else if (sign === '') {\n        // Blank line?  Whatever.\n      } else {\n        // WTF?\n        throw new Error('Invalid patch mode \"' + sign + '\" in: ' + line);\n      }\n      textPointer++;\n    }\n  }\n  return patches;\n};\n\n\n/**\n * Class representing one patch operation.\n * @constructor\n */\ndiff_match_patch.patch_obj = function() {\n  /** @type {!Array.<!diff_match_patch.Diff>} */\n  this.diffs = [];\n  /** @type {?number} */\n  this.start1 = null;\n  /** @type {?number} */\n  this.start2 = null;\n  /** @type {number} */\n  this.length1 = 0;\n  /** @type {number} */\n  this.length2 = 0;\n};\n\n\n/**\n * Emmulate GNU diff's format.\n * Header: @@ -382,8 +481,9 @@\n * Indicies are printed as 1-based, not 0-based.\n * @return {string} The GNU diff string.\n */\ndiff_match_patch.patch_obj.prototype.toString = function() {\n  var coords1, coords2;\n  if (this.length1 === 0) {\n    coords1 = this.start1 + ',0';\n  } else if (this.length1 == 1) {\n    coords1 = this.start1 + 1;\n  } else {\n    coords1 = (this.start1 + 1) + ',' + this.length1;\n  }\n  if (this.length2 === 0) {\n    coords2 = this.start2 + ',0';\n  } else if (this.length2 == 1) {\n    coords2 = this.start2 + 1;\n  } else {\n    coords2 = (this.start2 + 1) + ',' + this.length2;\n  }\n  var text = ['@@ -' + coords1 + ' +' + coords2 + ' @@\\n'];\n  var op;\n  // Escape the body of the patch with %xx notation.\n  for (var x = 0; x < this.diffs.length; x++) {\n    switch (this.diffs[x][0]) {\n      case DIFF_INSERT:\n        op = '+';\n        break;\n      case DIFF_DELETE:\n        op = '-';\n        break;\n      case DIFF_EQUAL:\n        op = ' ';\n        break;\n    }\n    text[x + 1] = op + encodeURI(this.diffs[x][1]) + '\\n';\n  }\n  return text.join('').replace(/%20/g, ' ');\n};\n\n\n// Export these global variables so that they survive Google's JS compiler.\n// In a browser, 'this' will be 'window'.\n// Users of node.js should 'require' the uncompressed version since Google's\n// JS compiler may break the following exports for non-browser environments.\nthis['diff_match_patch'] = diff_match_patch;\nthis['DIFF_DELETE'] = DIFF_DELETE;\nthis['DIFF_INSERT'] = DIFF_INSERT;\nthis['DIFF_EQUAL'] = DIFF_EQUAL;\n"
  },
  {
    "path": "_archive/apps/samples/diff/lib/jquery.activity-indicator.js",
    "content": "/*!\n * NETEYE Activity Indicator jQuery Plugin\n *\n * Copyright (c) 2010 NETEYE GmbH\n * Licensed under the MIT license\n *\n * Author: Felix Gnass [fgnass at neteye dot de]\n * Version: 1.0.0\n */\n \n/**\n * Plugin that renders a customisable activity indicator (spinner) using SVG or VML.\n */\n(function($) {\n\n\t$.fn.activity = function(opts) {\n\t\tthis.each(function() {\n\t\t\tvar $this = $(this);\n\t\t\tvar el = $this.data('activity');\n\t\t\tif (el) {\n\t\t\t\tclearInterval(el.data('interval'));\n\t\t\t\tel.remove();\n\t\t\t\t$this.removeData('activity');\n\t\t\t}\n\t\t\tif (opts !== false) {\n\t\t\t\topts = $.extend({color: $this.css('color')}, $.fn.activity.defaults, opts);\n\t\t\t\t\n\t\t\t\tel = render($this, opts).css('position', 'absolute').prependTo(opts.outside ? 'body' : $this);\n\t\t\t\tvar h = $this.outerHeight() - el.height();\n\t\t\t\tvar w = $this.outerWidth() - el.width();\n\t\t\t\tvar margin = {\n\t\t\t\t\ttop: opts.valign == 'top' ? opts.padding : opts.valign == 'bottom' ? h - opts.padding : Math.floor(h / 2),\n\t\t\t\t\tleft: opts.align == 'left' ? opts.padding : opts.align == 'right' ? w - opts.padding : Math.floor(w / 2)\n\t\t\t\t};\n\t\t\t\tvar offset = $this.offset();\n\t\t\t\tif (opts.outside) {\n\t\t\t\t\tel.css({top: offset.top + 'px', left: offset.left + 'px'});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tmargin.top -= el.offset().top - offset.top;\n\t\t\t\t\tmargin.left -= el.offset().left - offset.left;\n\t\t\t\t}\n\t\t\t\tel.css({marginTop: margin.top + 'px', marginLeft: margin.left + 'px'});\n\t\t\t\tanimate(el, opts.segments, Math.round(10 / opts.speed) / 10);\n\t\t\t\t$this.data('activity', el);\n\t\t\t}\n\t\t});\n\t\treturn this;\n\t};\n\t\n\t$.fn.activity.defaults = {\n\t\tsegments: 12,\n\t\tspace: 3,\n\t\tlength: 7,\n\t\twidth: 4,\n\t\tspeed: 1.2,\n\t\talign: 'center',\n\t\tvalign: 'center',\n\t\tpadding: 4\n\t};\n\t\n\t$.fn.activity.getOpacity = function(opts, i) {\n\t\tvar steps = opts.steps || opts.segments-1;\n\t\tvar end = opts.opacity !== undefined ? opts.opacity : 1/steps;\n\t\treturn 1 - Math.min(i, steps) * (1 - end) / steps;\n\t};\n\t\n\t/**\n\t * Default rendering strategy. If neither SVG nor VML is available, a div with class-name 'busy' \n\t * is inserted, that can be styled with CSS to display an animated gif as fallback.\n\t */\n\tvar render = function() {\n\t\treturn $('<div>').addClass('busy');\n\t};\n\t\n\t/**\n\t * The default animation strategy does nothing as we expect an animated gif as fallback.\n\t */\n\tvar animate = function() {\n\t};\n\t\n\t/**\n\t * Utility function to create elements in the SVG namespace.\n\t */\n\tfunction svg(tag, attr) {\n\t\tvar el = document.createElementNS(\"http://www.w3.org/2000/svg\", tag || 'svg');\n\t\tif (attr) {\n\t\t\t$.each(attr, function(k, v) {\n\t\t\t\tel.setAttributeNS(null, k, v);\n\t\t\t});\n\t\t}\n\t\treturn $(el);\n\t}\n\t\n\tif (document.createElementNS && document.createElementNS( \"http://www.w3.org/2000/svg\", \"svg\").createSVGRect) {\n\t\n\t\t// =======================================================================================\n\t\t// SVG Rendering\n\t\t// =======================================================================================\n\t\t\n\t\t/**\n\t\t * Rendering strategy that creates a SVG tree.\n\t\t */\n\t\trender = function(target, d) {\n\t\t\tvar innerRadius = d.width*2 + d.space;\n\t\t\tvar r = (innerRadius + d.length + Math.ceil(d.width / 2) + 1);\n\t\t\t\n\t\t\tvar el = svg().width(r*2).height(r*2);\n\t\t\t\n\t\t\tvar g = svg('g', {\n\t\t\t\t'stroke-width': d.width, \n\t\t\t\t'stroke-linecap': 'round', \n\t\t\t\tstroke: d.color\n\t\t\t}).appendTo(svg('g', {transform: 'translate('+ r +','+ r +')'}).appendTo(el));\n\t\t\t\n\t\t\tfor (var i = 0; i < d.segments; i++) {\n\t\t\t\tg.append(svg('line', {\n\t\t\t\t\tx1: 0, \n\t\t\t\t\ty1: innerRadius, \n\t\t\t\t\tx2: 0, \n\t\t\t\t\ty2: innerRadius + d.length, \n\t\t\t\t\ttransform: 'rotate(' + (360 / d.segments * i) + ', 0, 0)',\n\t\t\t\t\topacity: $.fn.activity.getOpacity(d, i)\n\t\t\t\t}));\n\t\t\t}\n\t\t\treturn $('<div>').append(el).width(2*r).height(2*r);\n\t\t};\n\t\t\t\t\n\t\t// Check if Webkit CSS animations are available, as they work much better on the iPad\n\t\t// than setTimeout() based animations.\n\t\t\n\t\tif (document.createElement('div').style.WebkitAnimationName !== undefined) {\n\n\t\t\tvar animations = {};\n\t\t\n\t\t\t/**\n\t\t\t * Animation strategy that uses dynamically created CSS animation rules.\n\t\t\t */\n\t\t\tanimate = function(el, steps, duration) {\n\t\t\t\tif (!animations[steps]) {\n\t\t\t\t\tvar name = 'spin' + steps;\n\t\t\t\t\tvar rule = '@-webkit-keyframes '+ name +' {';\n\t\t\t\t\tfor (var i=0; i < steps; i++) {\n\t\t\t\t\t\tvar p1 = Math.round(100000 / steps * i) / 1000;\n\t\t\t\t\t\tvar p2 = Math.round(100000 / steps * (i+1) - 1) / 1000;\n\t\t\t\t\t\tvar value = '% { -webkit-transform:rotate(' + Math.round(360 / steps * i) + 'deg); }\\n';\n\t\t\t\t\t\trule += p1 + value + p2 + value; \n\t\t\t\t\t}\n\t\t\t\t\trule += '100% { -webkit-transform:rotate(100deg); }\\n}';\n\t\t\t\t\tdocument.styleSheets[0].insertRule(rule);\n\t\t\t\t\tanimations[steps] = name;\n\t\t\t\t}\n\t\t\t\tel.css('-webkit-animation', animations[steps] + ' ' + duration +'s linear infinite');\n\t\t\t};\n\t\t}\n\t\telse {\n\t\t\n\t\t\t/**\n\t\t\t * Animation strategy that transforms a SVG element using setInterval().\n\t\t\t */\n\t\t\tanimate = function(el, steps, duration) {\n\t\t\t\tvar rotation = 0;\n\t\t\t\tvar g = el.find('g g').get(0);\n\t\t\t\tel.data('interval', setInterval(function() {\n\t\t\t\t\tg.setAttributeNS(null, 'transform', 'rotate(' + (++rotation % steps * (360 / steps)) + ')');\n\t\t\t\t},  duration * 1000 / steps));\n\t\t\t};\n\t\t}\n\t\t\n\t}\n\telse {\n\t\t\n\t\t// =======================================================================================\n\t\t// VML Rendering\n\t\t// =======================================================================================\n\t\t\n\t\tvar s = $('<shape>').css('behavior', 'url(#default#VML)').appendTo('body');\n\t\t\t\n\t\tif (s.get(0).adj) {\n\t\t\n\t\t\t// VML support detected. Insert CSS rules for group, shape and stroke.\n\t\t\tvar sheet = document.createStyleSheet();\n\t\t\t$.each(['group', 'shape', 'stroke'], function() {\n\t\t\t\tsheet.addRule(this, \"behavior:url(#default#VML);\");\n\t\t\t});\n\t\t\t\n\t\t\t/**\n\t\t\t * Rendering strategy that creates a VML tree. \n\t\t\t */\n\t\t\trender = function(target, d) {\n\t\t\t\n\t\t\t\tvar innerRadius = d.width*2 + d.space;\n\t\t\t\tvar r = (innerRadius + d.length + Math.ceil(d.width / 2) + 1);\n\t\t\t\tvar s = r*2;\n\t\t\t\tvar o = -Math.ceil(s/2);\n\t\t\t\t\n\t\t\t\tvar el = $('<group>', {coordsize: s + ' ' + s, coordorigin: o + ' ' + o}).css({top: o, left: o, width: s, height: s});\n\t\t\t\tfor (var i = 0; i < d.segments; i++) {\n\t\t\t\t\tel.append($('<shape>', {path: 'm ' + innerRadius + ',0  l ' + (innerRadius + d.length) + ',0'}).css({\n\t\t\t\t\t\twidth: s,\n\t\t\t\t\t\theight: s,\n\t\t\t\t\t\trotation: (360 / d.segments * i) + 'deg'\n\t\t\t\t\t}).append($('<stroke>', {color: d.color, weight: d.width + 'px', endcap: 'round', opacity: $.fn.activity.getOpacity(d, i)})));\n\t\t\t\t}\n\t\t\t\treturn $('<group>', {coordsize: s + ' ' + s}).css({width: s, height: s, overflow: 'hidden'}).append(el);\n\t\t\t};\n\t\t\n\t\t\t/**\n\t\t     * Animation strategy that modifies the VML rotation property using setInterval().\n\t\t     */\n\t\t\tanimate = function(el, steps, duration) {\n\t\t\t\tvar rotation = 0;\n\t\t\t\tvar g = el.get(0);\n\t\t\t\tel.data('interval', setInterval(function() {\n\t\t\t\t\tg.style.rotation = ++rotation % steps * (360 / steps);\n\t\t\t\t},  duration * 1000 / steps));\n\t\t\t};\n\t\t}\n\t\t$(s).remove();\n\t}\n\n})(jQuery);\n"
  },
  {
    "path": "_archive/apps/samples/diff/main.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n    <title>Diff Chrome Extension</title>\n\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"css/style.css\">\n\n    <script type=\"text/javascript\" src=\"lib/jquery-1.7.2.min.js\"></script>\n    <script type=\"text/javascript\" src=\"lib/diff_match_patch.js\"></script>\n\n    <script type=\"text/javascript\" src=\"js/diff.js\"></script>\n    <script type=\"text/javascript\" src=\"js/filesystem.js\"></script>\n  </head>\n  <body>\n    <div class=\"offline hidden\">\n      <span class=\"loader\"><span class=\"bolt\"></span></span>\n      <div class=\"text\">You are currently offline</div>\n    </div>\n\n    <div id=\"left-side\">\n      <div class=\"button new-diff\" id=\"new-diff\">\n        <img src=\"img/edit_diff.png\" />\n      </div>\n      <div class=\"tooltip new-diff hidden\">\n        New Diff<span class=\"pointer\"</span>\n      </div>\n      <div id=\"expand-all\" class=\"disabled\"></div>\n      <div class=\"tooltip expand-all hidden\">\n        Expand All<span class=\"pointer\"</span>\n      </div>\n      <div id=\"collapse-all\" class=\"disabled\"></div>\n      <div class=\"tooltip collapse-all hidden\">\n        Collapse All<span class=\"pointer\"</span>\n      </div>\n      <div id=\"prev-chunk\" class=\"disabled\"></div>\n      <div class=\"tooltip prev-chunk hidden\">\n        Previous Conflict<span class=\"pointer\"</span>\n      </div>\n      <div id=\"next-chunk\" class=\"disabled\"></div>\n      <div class=\"tooltip next-chunk hidden\">\n        Next Conflict<span class=\"pointer\"</span>\n      </div>\n    </div>\n\n    <div id=\"file0-container\">\n\n      ​<span class=\"button menubutton\">\n        <span class=\"label file-name 0\">No File Selected</span>\n      ​​​​​​​​​​​  <span class=\"indicator\"></span>\n        <ul class=\"menulist 0\">\n          <li class=\"menulistitem choose-new-file\">Choose File</li>\n        </ul>\n      </span>\n\n      <div class=\"file-diff 0\" id=\"drop-zone0\"></div>\n    </div>\n\n    <div id=\"arrow-container\"></div>\n    <div id=\"check-container\"></div>\n\n    <div id=\"file1-container\">\n\n      ​<span class=\"button menubutton\">\n        <span class=\"label file-name 1\">No File Selected</span>\n      ​​​​​​​​​​​  <span class=\"indicator\"></span>\n        <ul class=\"menulist 1\">\n          <li class=\"menulistitem choose-new-file\">Choose File</li>\n        </ul>\n      </span>\n\n      <div class=\"button save hidden\" id=\"save\"><img src=\"img/save.png\" /></div>\n      <div class=\"tooltip save hidden\">Save As<span class=\"pointer\"</span></div>\n      <div class=\"button edit hidden\" id=\"edit\"><img src=\"img/edit.png\" /></div>\n      <div class=\"tooltip edit hidden\">Edit<span class=\"pointer\"</span></div>\n      <div class=\"button done hidden\">Done</div>\n      <div id=\"num-diffs\"></div>\n      <br>\n      <div class=\"file-diff 1\" id=\"drop-zone1\"></div>\n      <textarea class=\"diff-text hidden\" id=\"editor\"></textarea>\n    </div>\n\n    <br>\n\n    <div class=\"expand-all\"></div>\n\n    <div class=\"new-diff modal-dialog prompt hidden\">\n      <div class=\"close-button\"></div>\n\n      <h1>File 1:  <span class=\"file-name 0\">No File Selected</span></h1>\n      <div class=\"button choose-file 0\">Choose File</div>\n      <label for=\"url\" class=\"url\">or select URL</label>\n      <input type=\"text\" name=\"url\" class=\"url 0\">\n      <div class=\"error-message 0\">Please enter a valid URL</div>\n      <br class=\"clear\">\n\n      <h1>File 2:  <span class=\"file-name 1\">No File Selected</span></h1>\n      <div class=\"button choose-file 1\">Choose File</div>\n      <label for=\"url\" class=\"url\">or select URL</label>\n      <input type=\"text\" name=\"url\" class=\"url 1\">\n      <div class=\"error-message 1\">Please enter a valid URL</div>\n      <br class=\"clear\">\n\n      <div class=\"button blue submit\">Submit</div>\n      <div class=\"button cancel\">Cancel</div>\n    </div>\n\n    <div id=\"modal-shield\" class=\"hidden\"></div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/diff/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"23\",\n  \"name\": \"Diff Tool\",\n  \"description\": \"View diff and merge two files.\",\n  \"version\": \"0.1.8\",\n  \"offline_enabled\": true,\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"js/background.js\"]\n    }\n  },\n  \"permissions\": [\"storage\",\n                  \"unlimitedStorage\",\n                  {\"fileSystem\": [\"write\"]},\n                  \"clipboardRead\",\n                  \"clipboardWrite\",\n                  \"<all_urls>\"\n                 ],\n  \"icons\": { \"16\": \"img/icon_16.png\",\n             \"48\": \"img/icon_48.png\",\n             \"128\": \"img/icon_128.png\"\n           }\n}\n"
  },
  {
    "path": "_archive/apps/samples/dojo/.gitignore",
    "content": "out\ntmp\ndojo.crx\n"
  },
  {
    "path": "_archive/apps/samples/dojo/Markdown_1.0.1/License.text",
    "content": "Copyright (c) 2004, John Gruber  \n<http://daringfireball.net/>  \nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n* Redistributions of source code must retain the above copyright notice,\n  this list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright\n  notice, this list of conditions and the following disclaimer in the\n  documentation and/or other materials provided with the distribution.\n\n* Neither the name \"Markdown\" nor the names of its contributors may\n  be used to endorse or promote products derived from this software\n  without specific prior written permission.\n\nThis software is provided by the copyright holders and contributors \"as\nis\" and any express or implied warranties, including, but not limited\nto, the implied warranties of merchantability and fitness for a\nparticular purpose are disclaimed. In no event shall the copyright owner\nor contributors be liable for any direct, indirect, incidental, special,\nexemplary, or consequential damages (including, but not limited to,\nprocurement of substitute goods or services; loss of use, data, or\nprofits; or business interruption) however caused and on any theory of\nliability, whether in contract, strict liability, or tort (including\nnegligence or otherwise) arising in any way out of the use of this\nsoftware, even if advised of the possibility of such damage.\n"
  },
  {
    "path": "_archive/apps/samples/dojo/Markdown_1.0.1/Markdown Readme.text",
    "content": "Markdown\n========\n\nVersion 1.0.1 - Tue 14 Dec 2004\n\nby John Gruber  \n<http://daringfireball.net/>\n\n\nIntroduction\n------------\n\nMarkdown is a text-to-HTML conversion tool for web writers. Markdown\nallows you to write using an easy-to-read, easy-to-write plain text\nformat, then convert it to structurally valid XHTML (or HTML).\n\nThus, \"Markdown\" is two things: a plain text markup syntax, and a\nsoftware tool, written in Perl, that converts the plain text markup \nto HTML.\n\nMarkdown works both as a Movable Type plug-in and as a standalone Perl\nscript -- which means it can also be used as a text filter in BBEdit\n(or any other application that supporst filters written in Perl).\n\nFull documentation of Markdown's syntax and configuration options is\navailable on the web: <http://daringfireball.net/projects/markdown/>.\n(Note: this readme file is formatted in Markdown.)\n\n\n\nInstallation and Requirements\n-----------------------------\n\nMarkdown requires Perl 5.6.0 or later. Welcome to the 21st Century.\nMarkdown also requires the standard Perl library module `Digest::MD5`. \n\n\n### Movable Type ###\n\nMarkdown works with Movable Type version 2.6 or later (including \nMT 3.0 or later).\n\n1.  Copy the \"Markdown.pl\" file into your Movable Type \"plugins\"\n    directory. The \"plugins\" directory should be in the same directory\n    as \"mt.cgi\"; if the \"plugins\" directory doesn't already exist, use\n    your FTP program to create it. Your installation should look like\n    this:\n\n        (mt home)/plugins/Markdown.pl\n\n2.  Once installed, Markdown will appear as an option in Movable Type's\n    Text Formatting pop-up menu. This is selectable on a per-post basis.\n    Markdown translates your posts to HTML when you publish; the posts\n    themselves are stored in your MT database in Markdown format.\n\n3.  If you also install SmartyPants 1.5 (or later), Markdown will offer\n    a second text formatting option: \"Markdown with SmartyPants\". This\n    option is the same as the regular \"Markdown\" formatter, except that\n    automatically uses SmartyPants to create typographically correct\n    curly quotes, em-dashes, and ellipses. See the SmartyPants web page\n    for more information: <http://daringfireball.net/projects/smartypants/>\n\n4.  To make Markdown (or \"Markdown with SmartyPants\") your default\n    text formatting option for new posts, go to Weblog Config ->\n    Preferences.\n\nNote that by default, Markdown produces XHTML output. To configure\nMarkdown to produce HTML 4 output, see \"Configuration\", below.\n\n\n### Blosxom ###\n\nMarkdown works with Blosxom version 2.x.\n\n1.  Rename the \"Markdown.pl\" plug-in to \"Markdown\" (case is\n    important). Movable Type requires plug-ins to have a \".pl\"\n    extension; Blosxom forbids it.\n\n2.  Copy the \"Markdown\" plug-in file to your Blosxom plug-ins folder.\n    If you're not sure where your Blosxom plug-ins folder is, see the\n    Blosxom documentation for information.\n\n3.  That's it. The entries in your weblog will now automatically be\n    processed by Markdown.\n\n4.  If you'd like to apply Markdown formatting only to certain posts,\n    rather than all of them, see Jason Clark's instructions for using\n    Markdown in conjunction with Blosxom's Meta plugin:\n    \n    <http://jclark.org/weblog/WebDev/Blosxom/Markdown.html>\n\n\n### BBEdit ###\n\nMarkdown works with BBEdit 6.1 or later on Mac OS X. (It also works\nwith BBEdit 5.1 or later and MacPerl 5.6.1 on Mac OS 8.6 or later.)\n\n1.  Copy the \"Markdown.pl\" file to appropriate filters folder in your\n    \"BBEdit Support\" folder. On Mac OS X, this should be:\n\n        BBEdit Support/Unix Support/Unix Filters/\n\n    See the BBEdit documentation for more details on the location of\n    these folders.\n\n    You can rename \"Markdown.pl\" to whatever you wish.\n\n2.  That's it. To use Markdown, select some text in a BBEdit document,\n    then choose Markdown from the Filters sub-menu in the \"#!\" menu, or\n    the Filters floating palette\n\n\n\nConfiguration\n-------------\n\nBy default, Markdown produces XHTML output for tags with empty elements.\nE.g.:\n\n    <br />\n\nMarkdown can be configured to produce HTML-style tags; e.g.:\n\n    <br>\n\n\n### Movable Type ###\n\nYou need to use a special `MTMarkdownOptions` container tag in each\nMovable Type template where you want HTML 4-style output:\n\n    <MTMarkdownOptions output='html4'>\n        ... put your entry content here ...\n    </MTMarkdownOptions>\n\nThe easiest way to use MTMarkdownOptions is probably to put the\nopening tag right after your `<body>` tag, and the closing tag right\nbefore `</body>`.\n\nTo suppress Markdown processing in a particular template, i.e. to\npublish the raw Markdown-formatted text without translation into\n(X)HTML, set the `output` attribute to 'raw':\n\n    <MTMarkdownOptions output='raw'>\n        ... put your entry content here ...\n    </MTMarkdownOptions>\n\n\n### Command-Line ###\n\nUse the `--html4tags` command-line switch to produce HTML output from a\nUnix-style command line. E.g.:\n\n    % perl Markdown.pl --html4tags foo.text\n\nType `perldoc Markdown.pl`, or read the POD documentation within the\nMarkdown.pl source code for more information.\n\n\n\nBugs\n----\n\nTo file bug reports or feature requests please send email to:\n<markdown@daringfireball.net>.\n\n\n\nVersion History\n---------------\n\n1.0.1 (14 Dec 2004):\n\n+\tChanged the syntax rules for code blocks and spans. Previously,\n\tbackslash escapes for special Markdown characters were processed\n\teverywhere other than within inline HTML tags. Now, the contents\n\tof code blocks and spans are no longer processed for backslash\n\tescapes. This means that code blocks and spans are now treated\n\tliterally, with no special rules to worry about regarding\n\tbackslashes.\n\n\t**NOTE**: This changes the syntax from all previous versions of\n\tMarkdown. Code blocks and spans involving backslash characters\n\twill now generate different output than before.\n\n+\tTweaked the rules for link definitions so that they must occur\n\twithin three spaces of the left margin. Thus if you indent a link\n\tdefinition by four spaces or a tab, it will now be a code block.\n\t\n\t\t   [a]: /url/  \"Indented 3 spaces, this is a link def\"\n\n\t\t    [b]: /url/  \"Indented 4 spaces, this is a code block\"\n\t\n\t**IMPORTANT**: This may affect existing Markdown content if it\n\tcontains link definitions indented by 4 or more spaces.\n\n+\tAdded `>`, `+`, and `-` to the list of backslash-escapable\n\tcharacters. These should have been done when these characters\n\twere added as unordered list item markers.\n\n+\tTrailing spaces and tabs following HTML comments and `<hr/>` tags\n\tare now ignored.\n\n+\tInline links using `<` and `>` URL delimiters weren't working:\n\n\t\tlike [this](<http://example.com/>)\n\n+\tAdded a bit of tolerance for trailing spaces and tabs after\n\tMarkdown hr's.\n\n+\tFixed bug where auto-links were being processed within code spans:\n\n\t\tlike this: `<http://example.com/>`\n\n+\tSort-of fixed a bug where lines in the middle of hard-wrapped\n\tparagraphs, which lines look like the start of a list item,\n\twould accidentally trigger the creation of a list. E.g. a\n\tparagraph that looked like this:\n\n\t\tI recommend upgrading to version\n\t\t8. Oops, now this line is treated\n\t\tas a sub-list.\n\n\tThis is fixed for top-level lists, but it can still happen for\n\tsub-lists. E.g., the following list item will not be parsed\n\tproperly:\n\n\t\t+\tI recommend upgrading to version\n\t\t\t8. Oops, now this line is treated\n\t\t\tas a sub-list.\n\n\tGiven Markdown's list-creation rules, I'm not sure this can\n\tbe fixed.\n\n+\tStandalone HTML comments are now handled; previously, they'd get\n\twrapped in a spurious `<p>` tag.\n\n+\tFix for horizontal rules preceded by 2 or 3 spaces.\n\n+\t`<hr>` HTML tags in must occur within three spaces of left\n\tmargin. (With 4 spaces or a tab, they should be code blocks, but\n\tweren't before this fix.)\n\n+\tCapitalized \"With\" in \"Markdown With SmartyPants\" for\n\tconsistency with the same string label in SmartyPants.pl.\n\t(This fix is specific to the MT plug-in interface.)\n\n+\tAuto-linked email address can now optionally contain\n\ta 'mailto:' protocol. I.e. these are equivalent:\n\n\t\t<mailto:user@example.com>\n\t\t<user@example.com>\n\n+\tFixed annoying bug where nested lists would wind up with\n\tspurious (and invalid) `<p>` tags.\n\n+\tYou can now write empty links:\n\n\t\t[like this]()\n\n\tand they'll be turned into anchor tags with empty href attributes.\n\tThis should have worked before, but didn't.\n\n+\t`***this***` and `___this___` are now turned into\n\n\t\t<strong><em>this</em></strong>\n\n\tInstead of\n\n\t\t<strong><em>this</strong></em>\n\n\twhich isn't valid. (Thanks to Michel Fortin for the fix.)\n\n+\tAdded a new substitution in `_EncodeCode()`: s/\\$/&#036;/g; This\n\tis only for the benefit of Blosxom users, because Blosxom\n\t(sometimes?) interpolates Perl scalars in your article bodies.\n\n+\tFixed problem for links defined with urls that include parens, e.g.:\n\n\t\t[1]: http://sources.wikipedia.org/wiki/Middle_East_Policy_(Chomsky)\n\n\t\"Chomsky\" was being erroneously treated as the URL's title.\n\n+\tAt some point during 1.0's beta cycle, I changed every sub's\n\targument fetching from this idiom:\n\n\t\tmy $text = shift;\n\n\tto:\n\n\t\tmy $text = shift || return '';\n\n\tThe idea was to keep Markdown from doing any work in a sub\n\tif the input was empty. This introduced a bug, though:\n\tif the input to any function was the single-character string\n\t\"0\", it would also evaluate as false and return immediately.\n\tHow silly. Now fixed.\n\n\n\nDonations\n---------\n\nDonations to support Markdown's development are happily accepted. See:\n<http://daringfireball.net/projects/markdown/> for details.\n\n\n\nCopyright and License\n---------------------\n\nCopyright (c) 2003-2004 John Gruber   \n<http://daringfireball.net/>   \nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n* Redistributions of source code must retain the above copyright notice,\n  this list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright\n  notice, this list of conditions and the following disclaimer in the\n  documentation and/or other materials provided with the distribution.\n\n* Neither the name \"Markdown\" nor the names of its contributors may\n  be used to endorse or promote products derived from this software\n  without specific prior written permission.\n\nThis software is provided by the copyright holders and contributors \"as\nis\" and any express or implied warranties, including, but not limited\nto, the implied warranties of merchantability and fitness for a\nparticular purpose are disclaimed. In no event shall the copyright owner\nor contributors be liable for any direct, indirect, incidental, special,\nexemplary, or consequential damages (including, but not limited to,\nprocurement of substitute goods or services; loss of use, data, or\nprofits; or business interruption) however caused and on any theory of\nliability, whether in contract, strict liability, or tort (including\nnegligence or otherwise) arising in any way out of the use of this\nsoftware, even if advised of the possibility of such damage.\n"
  },
  {
    "path": "_archive/apps/samples/dojo/Markdown_1.0.1/Markdown.pl",
    "content": "#!/usr/bin/perl\n\n#\n# Markdown -- A text-to-HTML conversion tool for web writers\n#\n# Copyright (c) 2004 John Gruber\n# <http://daringfireball.net/projects/markdown/>\n#\n\n\npackage Markdown;\nrequire 5.006_000;\nuse strict;\nuse warnings;\n\nuse Digest::MD5 qw(md5_hex);\nuse vars qw($VERSION);\n$VERSION = '1.0.1';\n# Tue 14 Dec 2004\n\n## Disabled; causes problems under Perl 5.6.1:\n# use utf8;\n# binmode( STDOUT, \":utf8\" );  # c.f.: http://acis.openlib.org/dev/perl-unicode-struggle.html\n\n\n#\n# Global default settings:\n#\nmy $g_empty_element_suffix = \" />\";     # Change to \">\" for HTML output\nmy $g_tab_width = 4;\n\n\n#\n# Globals:\n#\n\n# Regex to match balanced [brackets]. See Friedl's\n# \"Mastering Regular Expressions\", 2nd Ed., pp. 328-331.\nmy $g_nested_brackets;\n$g_nested_brackets = qr{\n\t(?> \t\t\t\t\t\t\t\t# Atomic matching\n\t   [^\\[\\]]+\t\t\t\t\t\t\t# Anything other than brackets\n\t | \n\t   \\[\n\t\t (??{ $g_nested_brackets })\t\t# Recursive set of nested brackets\n\t   \\]\n\t)*\n}x;\n\n\n# Table of hash values for escaped characters:\nmy %g_escape_table;\nforeach my $char (split //, '\\\\`*_{}[]()>#+-.!') {\n\t$g_escape_table{$char} = md5_hex($char);\n}\n\n\n# Global hashes, used by various utility routines\nmy %g_urls;\nmy %g_titles;\nmy %g_html_blocks;\n\n# Used to track when we're inside an ordered or unordered list\n# (see _ProcessListItems() for details):\nmy $g_list_level = 0;\n\n\n#### Blosxom plug-in interface ##########################################\n\n# Set $g_blosxom_use_meta to 1 to use Blosxom's meta plug-in to determine\n# which posts Markdown should process, using a \"meta-markup: markdown\"\n# header. If it's set to 0 (the default), Markdown will process all\n# entries.\nmy $g_blosxom_use_meta = 0;\n\nsub start { 1; }\nsub story {\n\tmy($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_;\n\n\tif ( (! $g_blosxom_use_meta) or\n\t     (defined($meta::markup) and ($meta::markup =~ /^\\s*markdown\\s*$/i))\n\t     ){\n\t\t\t$$body_ref  = Markdown($$body_ref);\n     }\n     1;\n}\n\n\n#### Movable Type plug-in interface #####################################\neval {require MT};  # Test to see if we're running in MT.\nunless ($@) {\n    require MT;\n    import  MT;\n    require MT::Template::Context;\n    import  MT::Template::Context;\n\n\teval {require MT::Plugin};  # Test to see if we're running >= MT 3.0.\n\tunless ($@) {\n\t\trequire MT::Plugin;\n\t\timport  MT::Plugin;\n\t\tmy $plugin = new MT::Plugin({\n\t\t\tname => \"Markdown\",\n\t\t\tdescription => \"A plain-text-to-HTML formatting plugin. (Version: $VERSION)\",\n\t\t\tdoc_link => 'http://daringfireball.net/projects/markdown/'\n\t\t});\n\t\tMT->add_plugin( $plugin );\n\t}\n\n\tMT::Template::Context->add_container_tag(MarkdownOptions => sub {\n\t\tmy $ctx\t = shift;\n\t\tmy $args = shift;\n\t\tmy $builder = $ctx->stash('builder');\n\t\tmy $tokens = $ctx->stash('tokens');\n\n\t\tif (defined ($args->{'output'}) ) {\n\t\t\t$ctx->stash('markdown_output', lc $args->{'output'});\n\t\t}\n\n\t\tdefined (my $str = $builder->build($ctx, $tokens) )\n\t\t\tor return $ctx->error($builder->errstr);\n\t\t$str;\t\t# return value\n\t});\n\n\tMT->add_text_filter('markdown' => {\n\t\tlabel     => 'Markdown',\n\t\tdocs      => 'http://daringfireball.net/projects/markdown/',\n\t\ton_format => sub {\n\t\t\tmy $text = shift;\n\t\t\tmy $ctx  = shift;\n\t\t\tmy $raw  = 0;\n\t\t    if (defined $ctx) {\n\t\t    \tmy $output = $ctx->stash('markdown_output'); \n\t\t\t\tif (defined $output  &&  $output =~ m/^html/i) {\n\t\t\t\t\t$g_empty_element_suffix = \">\";\n\t\t\t\t\t$ctx->stash('markdown_output', '');\n\t\t\t\t}\n\t\t\t\telsif (defined $output  &&  $output eq 'raw') {\n\t\t\t\t\t$raw = 1;\n\t\t\t\t\t$ctx->stash('markdown_output', '');\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t$raw = 0;\n\t\t\t\t\t$g_empty_element_suffix = \" />\";\n\t\t\t\t}\n\t\t\t}\n\t\t\t$text = $raw ? $text : Markdown($text);\n\t\t\t$text;\n\t\t},\n\t});\n\n\t# If SmartyPants is loaded, add a combo Markdown/SmartyPants text filter:\n\tmy $smartypants;\n\n\t{\n\t\tno warnings \"once\";\n\t\t$smartypants = $MT::Template::Context::Global_filters{'smarty_pants'};\n\t}\n\n\tif ($smartypants) {\n\t\tMT->add_text_filter('markdown_with_smartypants' => {\n\t\t\tlabel     => 'Markdown With SmartyPants',\n\t\t\tdocs      => 'http://daringfireball.net/projects/markdown/',\n\t\t\ton_format => sub {\n\t\t\t\tmy $text = shift;\n\t\t\t\tmy $ctx  = shift;\n\t\t\t\tif (defined $ctx) {\n\t\t\t\t\tmy $output = $ctx->stash('markdown_output'); \n\t\t\t\t\tif (defined $output  &&  $output eq 'html') {\n\t\t\t\t\t\t$g_empty_element_suffix = \">\";\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\t$g_empty_element_suffix = \" />\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$text = Markdown($text);\n\t\t\t\t$text = $smartypants->($text, '1');\n\t\t\t},\n\t\t});\n\t}\n}\nelse {\n#### BBEdit/command-line text filter interface ##########################\n# Needs to be hidden from MT (and Blosxom when running in static mode).\n\n    # We're only using $blosxom::version once; tell Perl not to warn us:\n\tno warnings 'once';\n    unless ( defined($blosxom::version) ) {\n\t\tuse warnings;\n\n\t\t#### Check for command-line switches: #################\n\t\tmy %cli_opts;\n\t\tuse Getopt::Long;\n\t\tGetopt::Long::Configure('pass_through');\n\t\tGetOptions(\\%cli_opts,\n\t\t\t'version',\n\t\t\t'shortversion',\n\t\t\t'html4tags',\n\t\t);\n\t\tif ($cli_opts{'version'}) {\t\t# Version info\n\t\t\tprint \"\\nThis is Markdown, version $VERSION.\\n\";\n\t\t\tprint \"Copyright 2004 John Gruber\\n\";\n\t\t\tprint \"http://daringfireball.net/projects/markdown/\\n\\n\";\n\t\t\texit 0;\n\t\t}\n\t\tif ($cli_opts{'shortversion'}) {\t\t# Just the version number string.\n\t\t\tprint $VERSION;\n\t\t\texit 0;\n\t\t}\n\t\tif ($cli_opts{'html4tags'}) {\t\t\t# Use HTML tag style instead of XHTML\n\t\t\t$g_empty_element_suffix = \">\";\n\t\t}\n\n\n\t\t#### Process incoming text: ###########################\n\t\tmy $text;\n\t\t{\n\t\t\tlocal $/;               # Slurp the whole file\n\t\t\t$text = <>;\n\t\t}\n        print Markdown($text);\n    }\n}\n\n\n\nsub Markdown {\n#\n# Main function. The order in which other subs are called here is\n# essential. Link and image substitutions need to happen before\n# _EscapeSpecialChars(), so that any *'s or _'s in the <a>\n# and <img> tags get encoded.\n#\n\tmy $text = shift;\n\n\t# Clear the global hashes. If we don't clear these, you get conflicts\n\t# from other articles when generating a page which contains more than\n\t# one article (e.g. an index page that shows the N most recent\n\t# articles):\n\t%g_urls = ();\n\t%g_titles = ();\n\t%g_html_blocks = ();\n\n\n\t# Standardize line endings:\n\t$text =~ s{\\r\\n}{\\n}g; \t# DOS to Unix\n\t$text =~ s{\\r}{\\n}g; \t# Mac to Unix\n\n\t# Make sure $text ends with a couple of newlines:\n\t$text .= \"\\n\\n\";\n\n\t# Convert all tabs to spaces.\n\t$text = _Detab($text);\n\n\t# Strip any lines consisting only of spaces and tabs.\n\t# This makes subsequent regexen easier to write, because we can\n\t# match consecutive blank lines with /\\n+/ instead of something\n\t# contorted like /[ \\t]*\\n+/ .\n\t$text =~ s/^[ \\t]+$//mg;\n\n\t# Turn block-level HTML blocks into hash entries\n\t$text = _HashHTMLBlocks($text);\n\n\t# Strip link definitions, store in hashes.\n\t$text = _StripLinkDefinitions($text);\n\n\t$text = _RunBlockGamut($text);\n\n\t$text = _UnescapeSpecialChars($text);\n\n\treturn $text . \"\\n\";\n}\n\n\nsub _StripLinkDefinitions {\n#\n# Strips link definitions from text, stores the URLs and titles in\n# hash references.\n#\n\tmy $text = shift;\n\tmy $less_than_tab = $g_tab_width - 1;\n\n\t# Link defs are in the form: ^[id]: url \"optional title\"\n\twhile ($text =~ s{\n\t\t\t\t\t\t^[ ]{0,$less_than_tab}\\[(.+)\\]:\t# id = $1\n\t\t\t\t\t\t  [ \\t]*\n\t\t\t\t\t\t  \\n?\t\t\t\t# maybe *one* newline\n\t\t\t\t\t\t  [ \\t]*\n\t\t\t\t\t\t<?(\\S+?)>?\t\t\t# url = $2\n\t\t\t\t\t\t  [ \\t]*\n\t\t\t\t\t\t  \\n?\t\t\t\t# maybe one newline\n\t\t\t\t\t\t  [ \\t]*\n\t\t\t\t\t\t(?:\n\t\t\t\t\t\t\t(?<=\\s)\t\t\t# lookbehind for whitespace\n\t\t\t\t\t\t\t[\"(]\n\t\t\t\t\t\t\t(.+?)\t\t\t# title = $3\n\t\t\t\t\t\t\t[\")]\n\t\t\t\t\t\t\t[ \\t]*\n\t\t\t\t\t\t)?\t# title is optional\n\t\t\t\t\t\t(?:\\n+|\\Z)\n\t\t\t\t\t}\n\t\t\t\t\t{}mx) {\n\t\t$g_urls{lc $1} = _EncodeAmpsAndAngles( $2 );\t# Link IDs are case-insensitive\n\t\tif ($3) {\n\t\t\t$g_titles{lc $1} = $3;\n\t\t\t$g_titles{lc $1} =~ s/\"/&quot;/g;\n\t\t}\n\t}\n\n\treturn $text;\n}\n\n\nsub _HashHTMLBlocks {\n\tmy $text = shift;\n\tmy $less_than_tab = $g_tab_width - 1;\n\n\t# Hashify HTML blocks:\n\t# We only want to do this for block-level HTML tags, such as headers,\n\t# lists, and tables. That's because we still want to wrap <p>s around\n\t# \"paragraphs\" that are wrapped in non-block-level tags, such as anchors,\n\t# phrase emphasis, and spans. The list of tags we're looking for is\n\t# hard-coded:\n\tmy $block_tags_a = qr/p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del/;\n\tmy $block_tags_b = qr/p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math/;\n\n\t# First, look for nested blocks, e.g.:\n\t# \t<div>\n\t# \t\t<div>\n\t# \t\ttags for inner block must be indented.\n\t# \t\t</div>\n\t# \t</div>\n\t#\n\t# The outermost tags must start at the left margin for this to match, and\n\t# the inner nested divs must be indented.\n\t# We need to do this before the next, more liberal match, because the next\n\t# match will start at the first `<div>` and stop at the first `</div>`.\n\t$text =~ s{\n\t\t\t\t(\t\t\t\t\t\t# save in $1\n\t\t\t\t\t^\t\t\t\t\t# start of line  (with /m)\n\t\t\t\t\t<($block_tags_a)\t# start tag = $2\n\t\t\t\t\t\\b\t\t\t\t\t# word break\n\t\t\t\t\t(.*\\n)*?\t\t\t# any number of lines, minimally matching\n\t\t\t\t\t</\\2>\t\t\t\t# the matching end tag\n\t\t\t\t\t[ \\t]*\t\t\t\t# trailing spaces/tabs\n\t\t\t\t\t(?=\\n+|\\Z)\t# followed by a newline or end of document\n\t\t\t\t)\n\t\t\t}{\n\t\t\t\tmy $key = md5_hex($1);\n\t\t\t\t$g_html_blocks{$key} = $1;\n\t\t\t\t\"\\n\\n\" . $key . \"\\n\\n\";\n\t\t\t}egmx;\n\n\n\t#\n\t# Now match more liberally, simply from `\\n<tag>` to `</tag>\\n`\n\t#\n\t$text =~ s{\n\t\t\t\t(\t\t\t\t\t\t# save in $1\n\t\t\t\t\t^\t\t\t\t\t# start of line  (with /m)\n\t\t\t\t\t<($block_tags_b)\t# start tag = $2\n\t\t\t\t\t\\b\t\t\t\t\t# word break\n\t\t\t\t\t(.*\\n)*?\t\t\t# any number of lines, minimally matching\n\t\t\t\t\t.*</\\2>\t\t\t\t# the matching end tag\n\t\t\t\t\t[ \\t]*\t\t\t\t# trailing spaces/tabs\n\t\t\t\t\t(?=\\n+|\\Z)\t# followed by a newline or end of document\n\t\t\t\t)\n\t\t\t}{\n\t\t\t\tmy $key = md5_hex($1);\n\t\t\t\t$g_html_blocks{$key} = $1;\n\t\t\t\t\"\\n\\n\" . $key . \"\\n\\n\";\n\t\t\t}egmx;\n\t# Special case just for <hr />. It was easier to make a special case than\n\t# to make the other regex more complicated.\t\n\t$text =~ s{\n\t\t\t\t(?:\n\t\t\t\t\t(?<=\\n\\n)\t\t# Starting after a blank line\n\t\t\t\t\t|\t\t\t\t# or\n\t\t\t\t\t\\A\\n?\t\t\t# the beginning of the doc\n\t\t\t\t)\n\t\t\t\t(\t\t\t\t\t\t# save in $1\n\t\t\t\t\t[ ]{0,$less_than_tab}\n\t\t\t\t\t<(hr)\t\t\t\t# start tag = $2\n\t\t\t\t\t\\b\t\t\t\t\t# word break\n\t\t\t\t\t([^<>])*?\t\t\t# \n\t\t\t\t\t/?>\t\t\t\t\t# the matching end tag\n\t\t\t\t\t[ \\t]*\n\t\t\t\t\t(?=\\n{2,}|\\Z)\t\t# followed by a blank line or end of document\n\t\t\t\t)\n\t\t\t}{\n\t\t\t\tmy $key = md5_hex($1);\n\t\t\t\t$g_html_blocks{$key} = $1;\n\t\t\t\t\"\\n\\n\" . $key . \"\\n\\n\";\n\t\t\t}egx;\n\n\t# Special case for standalone HTML comments:\n\t$text =~ s{\n\t\t\t\t(?:\n\t\t\t\t\t(?<=\\n\\n)\t\t# Starting after a blank line\n\t\t\t\t\t|\t\t\t\t# or\n\t\t\t\t\t\\A\\n?\t\t\t# the beginning of the doc\n\t\t\t\t)\n\t\t\t\t(\t\t\t\t\t\t# save in $1\n\t\t\t\t\t[ ]{0,$less_than_tab}\n\t\t\t\t\t(?s:\n\t\t\t\t\t\t<!\n\t\t\t\t\t\t(--.*?--\\s*)+\n\t\t\t\t\t\t>\n\t\t\t\t\t)\n\t\t\t\t\t[ \\t]*\n\t\t\t\t\t(?=\\n{2,}|\\Z)\t\t# followed by a blank line or end of document\n\t\t\t\t)\n\t\t\t}{\n\t\t\t\tmy $key = md5_hex($1);\n\t\t\t\t$g_html_blocks{$key} = $1;\n\t\t\t\t\"\\n\\n\" . $key . \"\\n\\n\";\n\t\t\t}egx;\n\n\n\treturn $text;\n}\n\n\nsub _RunBlockGamut {\n#\n# These are all the transformations that form block-level\n# tags like paragraphs, headers, and list items.\n#\n\tmy $text = shift;\n\n\t$text = _DoHeaders($text);\n\n\t# Do Horizontal Rules:\n\t$text =~ s{^[ ]{0,2}([ ]?\\*[ ]?){3,}[ \\t]*$}{\\n<hr$g_empty_element_suffix\\n}gmx;\n\t$text =~ s{^[ ]{0,2}([ ]? -[ ]?){3,}[ \\t]*$}{\\n<hr$g_empty_element_suffix\\n}gmx;\n\t$text =~ s{^[ ]{0,2}([ ]? _[ ]?){3,}[ \\t]*$}{\\n<hr$g_empty_element_suffix\\n}gmx;\n\n\t$text = _DoLists($text);\n\n\t$text = _DoCodeBlocks($text);\n\n\t$text = _DoBlockQuotes($text);\n\n\t# We already ran _HashHTMLBlocks() before, in Markdown(), but that\n\t# was to escape raw HTML in the original Markdown source. This time,\n\t# we're escaping the markup we've just created, so that we don't wrap\n\t# <p> tags around block-level tags.\n\t$text = _HashHTMLBlocks($text);\n\n\t$text = _FormParagraphs($text);\n\n\treturn $text;\n}\n\n\nsub _RunSpanGamut {\n#\n# These are all the transformations that occur *within* block-level\n# tags like paragraphs, headers, and list items.\n#\n\tmy $text = shift;\n\n\t$text = _DoCodeSpans($text);\n\n\t$text = _EscapeSpecialChars($text);\n\n\t# Process anchor and image tags. Images must come first,\n\t# because ![foo][f] looks like an anchor.\n\t$text = _DoImages($text);\n\t$text = _DoAnchors($text);\n\n\t# Make links out of things like `<http://example.com/>`\n\t# Must come after _DoAnchors(), because you can use < and >\n\t# delimiters in inline links like [this](<url>).\n\t$text = _DoAutoLinks($text);\n\n\t$text = _EncodeAmpsAndAngles($text);\n\n\t$text = _DoItalicsAndBold($text);\n\n\t# Do hard breaks:\n\t$text =~ s/ {2,}\\n/ <br$g_empty_element_suffix\\n/g;\n\n\treturn $text;\n}\n\n\nsub _EscapeSpecialChars {\n\tmy $text = shift;\n\tmy $tokens ||= _TokenizeHTML($text);\n\n\t$text = '';   # rebuild $text from the tokens\n# \tmy $in_pre = 0;\t # Keep track of when we're inside <pre> or <code> tags.\n# \tmy $tags_to_skip = qr!<(/?)(?:pre|code|kbd|script|math)[\\s>]!;\n\n\tforeach my $cur_token (@$tokens) {\n\t\tif ($cur_token->[0] eq \"tag\") {\n\t\t\t# Within tags, encode * and _ so they don't conflict\n\t\t\t# with their use in Markdown for italics and strong.\n\t\t\t# We're replacing each such character with its\n\t\t\t# corresponding MD5 checksum value; this is likely\n\t\t\t# overkill, but it should prevent us from colliding\n\t\t\t# with the escape values by accident.\n\t\t\t$cur_token->[1] =~  s! \\* !$g_escape_table{'*'}!gx;\n\t\t\t$cur_token->[1] =~  s! _  !$g_escape_table{'_'}!gx;\n\t\t\t$text .= $cur_token->[1];\n\t\t} else {\n\t\t\tmy $t = $cur_token->[1];\n\t\t\t$t = _EncodeBackslashEscapes($t);\n\t\t\t$text .= $t;\n\t\t}\n\t}\n\treturn $text;\n}\n\n\nsub _DoAnchors {\n#\n# Turn Markdown link shortcuts into XHTML <a> tags.\n#\n\tmy $text = shift;\n\n\t#\n\t# First, handle reference-style links: [link text] [id]\n\t#\n\t$text =~ s{\n\t\t(\t\t\t\t\t# wrap whole match in $1\n\t\t  \\[\n\t\t    ($g_nested_brackets)\t# link text = $2\n\t\t  \\]\n\n\t\t  [ ]?\t\t\t\t# one optional space\n\t\t  (?:\\n[ ]*)?\t\t# one optional newline followed by spaces\n\n\t\t  \\[\n\t\t    (.*?)\t\t# id = $3\n\t\t  \\]\n\t\t)\n\t}{\n\t\tmy $result;\n\t\tmy $whole_match = $1;\n\t\tmy $link_text   = $2;\n\t\tmy $link_id     = lc $3;\n\n\t\tif ($link_id eq \"\") {\n\t\t\t$link_id = lc $link_text;     # for shortcut links like [this][].\n\t\t}\n\n\t\tif (defined $g_urls{$link_id}) {\n\t\t\tmy $url = $g_urls{$link_id};\n\t\t\t$url =~ s! \\* !$g_escape_table{'*'}!gx;\t\t# We've got to encode these to avoid\n\t\t\t$url =~ s!  _ !$g_escape_table{'_'}!gx;\t\t# conflicting with italics/bold.\n\t\t\t$result = \"<a href=\\\"$url\\\"\";\n\t\t\tif ( defined $g_titles{$link_id} ) {\n\t\t\t\tmy $title = $g_titles{$link_id};\n\t\t\t\t$title =~ s! \\* !$g_escape_table{'*'}!gx;\n\t\t\t\t$title =~ s!  _ !$g_escape_table{'_'}!gx;\n\t\t\t\t$result .=  \" title=\\\"$title\\\"\";\n\t\t\t}\n\t\t\t$result .= \">$link_text</a>\";\n\t\t}\n\t\telse {\n\t\t\t$result = $whole_match;\n\t\t}\n\t\t$result;\n\t}xsge;\n\n\t#\n\t# Next, inline-style links: [link text](url \"optional title\")\n\t#\n\t$text =~ s{\n\t\t(\t\t\t\t# wrap whole match in $1\n\t\t  \\[\n\t\t    ($g_nested_brackets)\t# link text = $2\n\t\t  \\]\n\t\t  \\(\t\t\t# literal paren\n\t\t  \t[ \\t]*\n\t\t\t<?(.*?)>?\t# href = $3\n\t\t  \t[ \\t]*\n\t\t\t(\t\t\t# $4\n\t\t\t  (['\"])\t# quote char = $5\n\t\t\t  (.*?)\t\t# Title = $6\n\t\t\t  \\5\t\t# matching quote\n\t\t\t)?\t\t\t# title is optional\n\t\t  \\)\n\t\t)\n\t}{\n\t\tmy $result;\n\t\tmy $whole_match = $1;\n\t\tmy $link_text   = $2;\n\t\tmy $url\t  \t\t= $3;\n\t\tmy $title\t\t= $6;\n\n\t\t$url =~ s! \\* !$g_escape_table{'*'}!gx;\t\t# We've got to encode these to avoid\n\t\t$url =~ s!  _ !$g_escape_table{'_'}!gx;\t\t# conflicting with italics/bold.\n\t\t$result = \"<a href=\\\"$url\\\"\";\n\n\t\tif (defined $title) {\n\t\t\t$title =~ s/\"/&quot;/g;\n\t\t\t$title =~ s! \\* !$g_escape_table{'*'}!gx;\n\t\t\t$title =~ s!  _ !$g_escape_table{'_'}!gx;\n\t\t\t$result .=  \" title=\\\"$title\\\"\";\n\t\t}\n\n\t\t$result .= \">$link_text</a>\";\n\n\t\t$result;\n\t}xsge;\n\n\treturn $text;\n}\n\n\nsub _DoImages {\n#\n# Turn Markdown image shortcuts into <img> tags.\n#\n\tmy $text = shift;\n\n\t#\n\t# First, handle reference-style labeled images: ![alt text][id]\n\t#\n\t$text =~ s{\n\t\t(\t\t\t\t# wrap whole match in $1\n\t\t  !\\[\n\t\t    (.*?)\t\t# alt text = $2\n\t\t  \\]\n\n\t\t  [ ]?\t\t\t\t# one optional space\n\t\t  (?:\\n[ ]*)?\t\t# one optional newline followed by spaces\n\n\t\t  \\[\n\t\t    (.*?)\t\t# id = $3\n\t\t  \\]\n\n\t\t)\n\t}{\n\t\tmy $result;\n\t\tmy $whole_match = $1;\n\t\tmy $alt_text    = $2;\n\t\tmy $link_id     = lc $3;\n\n\t\tif ($link_id eq \"\") {\n\t\t\t$link_id = lc $alt_text;     # for shortcut links like ![this][].\n\t\t}\n\n\t\t$alt_text =~ s/\"/&quot;/g;\n\t\tif (defined $g_urls{$link_id}) {\n\t\t\tmy $url = $g_urls{$link_id};\n\t\t\t$url =~ s! \\* !$g_escape_table{'*'}!gx;\t\t# We've got to encode these to avoid\n\t\t\t$url =~ s!  _ !$g_escape_table{'_'}!gx;\t\t# conflicting with italics/bold.\n\t\t\t$result = \"<img src=\\\"$url\\\" alt=\\\"$alt_text\\\"\";\n\t\t\tif (defined $g_titles{$link_id}) {\n\t\t\t\tmy $title = $g_titles{$link_id};\n\t\t\t\t$title =~ s! \\* !$g_escape_table{'*'}!gx;\n\t\t\t\t$title =~ s!  _ !$g_escape_table{'_'}!gx;\n\t\t\t\t$result .=  \" title=\\\"$title\\\"\";\n\t\t\t}\n\t\t\t$result .= $g_empty_element_suffix;\n\t\t}\n\t\telse {\n\t\t\t# If there's no such link ID, leave intact:\n\t\t\t$result = $whole_match;\n\t\t}\n\n\t\t$result;\n\t}xsge;\n\n\t#\n\t# Next, handle inline images:  ![alt text](url \"optional title\")\n\t# Don't forget: encode * and _\n\n\t$text =~ s{\n\t\t(\t\t\t\t# wrap whole match in $1\n\t\t  !\\[\n\t\t    (.*?)\t\t# alt text = $2\n\t\t  \\]\n\t\t  \\(\t\t\t# literal paren\n\t\t  \t[ \\t]*\n\t\t\t<?(\\S+?)>?\t# src url = $3\n\t\t  \t[ \\t]*\n\t\t\t(\t\t\t# $4\n\t\t\t  (['\"])\t# quote char = $5\n\t\t\t  (.*?)\t\t# title = $6\n\t\t\t  \\5\t\t# matching quote\n\t\t\t  [ \\t]*\n\t\t\t)?\t\t\t# title is optional\n\t\t  \\)\n\t\t)\n\t}{\n\t\tmy $result;\n\t\tmy $whole_match = $1;\n\t\tmy $alt_text    = $2;\n\t\tmy $url\t  \t\t= $3;\n\t\tmy $title\t\t= '';\n\t\tif (defined($6)) {\n\t\t\t$title\t\t= $6;\n\t\t}\n\n\t\t$alt_text =~ s/\"/&quot;/g;\n\t\t$title    =~ s/\"/&quot;/g;\n\t\t$url =~ s! \\* !$g_escape_table{'*'}!gx;\t\t# We've got to encode these to avoid\n\t\t$url =~ s!  _ !$g_escape_table{'_'}!gx;\t\t# conflicting with italics/bold.\n\t\t$result = \"<img src=\\\"$url\\\" alt=\\\"$alt_text\\\"\";\n\t\tif (defined $title) {\n\t\t\t$title =~ s! \\* !$g_escape_table{'*'}!gx;\n\t\t\t$title =~ s!  _ !$g_escape_table{'_'}!gx;\n\t\t\t$result .=  \" title=\\\"$title\\\"\";\n\t\t}\n\t\t$result .= $g_empty_element_suffix;\n\n\t\t$result;\n\t}xsge;\n\n\treturn $text;\n}\n\n\nsub _DoHeaders {\n\tmy $text = shift;\n\n\t# Setext-style headers:\n\t#\t  Header 1\n\t#\t  ========\n\t#  \n\t#\t  Header 2\n\t#\t  --------\n\t#\n\t$text =~ s{ ^(.+)[ \\t]*\\n=+[ \\t]*\\n+ }{\n\t\t\"<h1>\"  .  _RunSpanGamut($1)  .  \"</h1>\\n\\n\";\n\t}egmx;\n\n\t$text =~ s{ ^(.+)[ \\t]*\\n-+[ \\t]*\\n+ }{\n\t\t\"<h2>\"  .  _RunSpanGamut($1)  .  \"</h2>\\n\\n\";\n\t}egmx;\n\n\n\t# atx-style headers:\n\t#\t# Header 1\n\t#\t## Header 2\n\t#\t## Header 2 with closing hashes ##\n\t#\t...\n\t#\t###### Header 6\n\t#\n\t$text =~ s{\n\t\t\t^(\\#{1,6})\t# $1 = string of #'s\n\t\t\t[ \\t]*\n\t\t\t(.+?)\t\t# $2 = Header text\n\t\t\t[ \\t]*\n\t\t\t\\#*\t\t\t# optional closing #'s (not counted)\n\t\t\t\\n+\n\t\t}{\n\t\t\tmy $h_level = length($1);\n\t\t\t\"<h$h_level>\"  .  _RunSpanGamut($2)  .  \"</h$h_level>\\n\\n\";\n\t\t}egmx;\n\n\treturn $text;\n}\n\n\nsub _DoLists {\n#\n# Form HTML ordered (numbered) and unordered (bulleted) lists.\n#\n\tmy $text = shift;\n\tmy $less_than_tab = $g_tab_width - 1;\n\n\t# Re-usable patterns to match list item bullets and number markers:\n\tmy $marker_ul  = qr/[*+-]/;\n\tmy $marker_ol  = qr/\\d+[.]/;\n\tmy $marker_any = qr/(?:$marker_ul|$marker_ol)/;\n\n\t# Re-usable pattern to match any entirel ul or ol list:\n\tmy $whole_list = qr{\n\t\t(\t\t\t\t\t\t\t\t# $1 = whole list\n\t\t  (\t\t\t\t\t\t\t\t# $2\n\t\t\t[ ]{0,$less_than_tab}\n\t\t\t(${marker_any})\t\t\t\t# $3 = first list item marker\n\t\t\t[ \\t]+\n\t\t  )\n\t\t  (?s:.+?)\n\t\t  (\t\t\t\t\t\t\t\t# $4\n\t\t\t  \\z\n\t\t\t|\n\t\t\t  \\n{2,}\n\t\t\t  (?=\\S)\n\t\t\t  (?!\t\t\t\t\t\t# Negative lookahead for another list item marker\n\t\t\t\t[ \\t]*\n\t\t\t\t${marker_any}[ \\t]+\n\t\t\t  )\n\t\t  )\n\t\t)\n\t}mx;\n\n\t# We use a different prefix before nested lists than top-level lists.\n\t# See extended comment in _ProcessListItems().\n\t#\n\t# Note: There's a bit of duplication here. My original implementation\n\t# created a scalar regex pattern as the conditional result of the test on\n\t# $g_list_level, and then only ran the $text =~ s{...}{...}egmx\n\t# substitution once, using the scalar as the pattern. This worked,\n\t# everywhere except when running under MT on my hosting account at Pair\n\t# Networks. There, this caused all rebuilds to be killed by the reaper (or\n\t# perhaps they crashed, but that seems incredibly unlikely given that the\n\t# same script on the same server ran fine *except* under MT. I've spent\n\t# more time trying to figure out why this is happening than I'd like to\n\t# admit. My only guess, backed up by the fact that this workaround works,\n\t# is that Perl optimizes the substition when it can figure out that the\n\t# pattern will never change, and when this optimization isn't on, we run\n\t# afoul of the reaper. Thus, the slightly redundant code to that uses two\n\t# static s/// patterns rather than one conditional pattern.\n\n\tif ($g_list_level) {\n\t\t$text =~ s{\n\t\t\t\t^\n\t\t\t\t$whole_list\n\t\t\t}{\n\t\t\t\tmy $list = $1;\n\t\t\t\tmy $list_type = ($3 =~ m/$marker_ul/) ? \"ul\" : \"ol\";\n\t\t\t\t# Turn double returns into triple returns, so that we can make a\n\t\t\t\t# paragraph for the last item in a list, if necessary:\n\t\t\t\t$list =~ s/\\n{2,}/\\n\\n\\n/g;\n\t\t\t\tmy $result = _ProcessListItems($list, $marker_any);\n\t\t\t\t$result = \"<$list_type>\\n\" . $result . \"</$list_type>\\n\";\n\t\t\t\t$result;\n\t\t\t}egmx;\n\t}\n\telse {\n\t\t$text =~ s{\n\t\t\t\t(?:(?<=\\n\\n)|\\A\\n?)\n\t\t\t\t$whole_list\n\t\t\t}{\n\t\t\t\tmy $list = $1;\n\t\t\t\tmy $list_type = ($3 =~ m/$marker_ul/) ? \"ul\" : \"ol\";\n\t\t\t\t# Turn double returns into triple returns, so that we can make a\n\t\t\t\t# paragraph for the last item in a list, if necessary:\n\t\t\t\t$list =~ s/\\n{2,}/\\n\\n\\n/g;\n\t\t\t\tmy $result = _ProcessListItems($list, $marker_any);\n\t\t\t\t$result = \"<$list_type>\\n\" . $result . \"</$list_type>\\n\";\n\t\t\t\t$result;\n\t\t\t}egmx;\n\t}\n\n\n\treturn $text;\n}\n\n\nsub _ProcessListItems {\n#\n#\tProcess the contents of a single ordered or unordered list, splitting it\n#\tinto individual list items.\n#\n\n\tmy $list_str = shift;\n\tmy $marker_any = shift;\n\n\n\t# The $g_list_level global keeps track of when we're inside a list.\n\t# Each time we enter a list, we increment it; when we leave a list,\n\t# we decrement. If it's zero, we're not in a list anymore.\n\t#\n\t# We do this because when we're not inside a list, we want to treat\n\t# something like this:\n\t#\n\t#\t\tI recommend upgrading to version\n\t#\t\t8. Oops, now this line is treated\n\t#\t\tas a sub-list.\n\t#\n\t# As a single paragraph, despite the fact that the second line starts\n\t# with a digit-period-space sequence.\n\t#\n\t# Whereas when we're inside a list (or sub-list), that line will be\n\t# treated as the start of a sub-list. What a kludge, huh? This is\n\t# an aspect of Markdown's syntax that's hard to parse perfectly\n\t# without resorting to mind-reading. Perhaps the solution is to\n\t# change the syntax rules such that sub-lists must start with a\n\t# starting cardinal number; e.g. \"1.\" or \"a.\".\n\n\t$g_list_level++;\n\n\t# trim trailing blank lines:\n\t$list_str =~ s/\\n{2,}\\z/\\n/;\n\n\n\t$list_str =~ s{\n\t\t(\\n)?\t\t\t\t\t\t\t# leading line = $1\n\t\t(^[ \\t]*)\t\t\t\t\t\t# leading whitespace = $2\n\t\t($marker_any) [ \\t]+\t\t\t# list marker = $3\n\t\t((?s:.+?)\t\t\t\t\t\t# list item text   = $4\n\t\t(\\n{1,2}))\n\t\t(?= \\n* (\\z | \\2 ($marker_any) [ \\t]+))\n\t}{\n\t\tmy $item = $4;\n\t\tmy $leading_line = $1;\n\t\tmy $leading_space = $2;\n\n\t\tif ($leading_line or ($item =~ m/\\n{2,}/)) {\n\t\t\t$item = _RunBlockGamut(_Outdent($item));\n\t\t}\n\t\telse {\n\t\t\t# Recursion for sub-lists:\n\t\t\t$item = _DoLists(_Outdent($item));\n\t\t\tchomp $item;\n\t\t\t$item = _RunSpanGamut($item);\n\t\t}\n\n\t\t\"<li>\" . $item . \"</li>\\n\";\n\t}egmx;\n\n\t$g_list_level--;\n\treturn $list_str;\n}\n\n\n\nsub _DoCodeBlocks {\n#\n#\tProcess Markdown `<pre><code>` blocks.\n#\t\n\n\tmy $text = shift;\n\n\t$text =~ s{\n\t\t\t(?:\\n\\n|\\A)\n\t\t\t(\t            # $1 = the code block -- one or more lines, starting with a space/tab\n\t\t\t  (?:\n\t\t\t    (?:[ ]{$g_tab_width} | \\t)  # Lines must start with a tab or a tab-width of spaces\n\t\t\t    .*\\n+\n\t\t\t  )+\n\t\t\t)\n\t\t\t((?=^[ ]{0,$g_tab_width}\\S)|\\Z)\t# Lookahead for non-space at line-start, or end of doc\n\t\t}{\n\t\t\tmy $codeblock = $1;\n\t\t\tmy $result; # return value\n\n\t\t\t$codeblock = _EncodeCode(_Outdent($codeblock));\n\t\t\t$codeblock = _Detab($codeblock);\n\t\t\t$codeblock =~ s/\\A\\n+//; # trim leading newlines\n\t\t\t$codeblock =~ s/\\s+\\z//; # trim trailing whitespace\n\n\t\t\t$result = \"\\n\\n<pre><code>\" . $codeblock . \"\\n</code></pre>\\n\\n\";\n\n\t\t\t$result;\n\t\t}egmx;\n\n\treturn $text;\n}\n\n\nsub _DoCodeSpans {\n#\n# \t*\tBacktick quotes are used for <code></code> spans.\n# \n# \t*\tYou can use multiple backticks as the delimiters if you want to\n# \t\tinclude literal backticks in the code span. So, this input:\n#     \n#         Just type ``foo `bar` baz`` at the prompt.\n#     \n#     \tWill translate to:\n#     \n#         <p>Just type <code>foo `bar` baz</code> at the prompt.</p>\n#     \n#\t\tThere's no arbitrary limit to the number of backticks you\n#\t\tcan use as delimters. If you need three consecutive backticks\n#\t\tin your code, use four for delimiters, etc.\n#\n#\t*\tYou can use spaces to get literal backticks at the edges:\n#     \n#         ... type `` `bar` `` ...\n#     \n#     \tTurns to:\n#     \n#         ... type <code>`bar`</code> ...\n#\n\n\tmy $text = shift;\n\n\t$text =~ s@\n\t\t\t(`+)\t\t# $1 = Opening run of `\n\t\t\t(.+?)\t\t# $2 = The code block\n\t\t\t(?<!`)\n\t\t\t\\1\t\t\t# Matching closer\n\t\t\t(?!`)\n\t\t@\n \t\t\tmy $c = \"$2\";\n \t\t\t$c =~ s/^[ \\t]*//g; # leading whitespace\n \t\t\t$c =~ s/[ \\t]*$//g; # trailing whitespace\n \t\t\t$c = _EncodeCode($c);\n\t\t\t\"<code>$c</code>\";\n\t\t@egsx;\n\n\treturn $text;\n}\n\n\nsub _EncodeCode {\n#\n# Encode/escape certain characters inside Markdown code runs.\n# The point is that in code, these characters are literals,\n# and lose their special Markdown meanings.\n#\n    local $_ = shift;\n\n\t# Encode all ampersands; HTML entities are not\n\t# entities within a Markdown code span.\n\ts/&/&amp;/g;\n\n\t# Encode $'s, but only if we're running under Blosxom.\n\t# (Blosxom interpolates Perl variables in article bodies.)\n\t{\n\t\tno warnings 'once';\n    \tif (defined($blosxom::version)) {\n    \t\ts/\\$/&#036;/g;\t\n    \t}\n    }\n\n\n\t# Do the angle bracket song and dance:\n\ts! <  !&lt;!gx;\n\ts! >  !&gt;!gx;\n\n\t# Now, escape characters that are magic in Markdown:\n\ts! \\* !$g_escape_table{'*'}!gx;\n\ts! _  !$g_escape_table{'_'}!gx;\n\ts! {  !$g_escape_table{'{'}!gx;\n\ts! }  !$g_escape_table{'}'}!gx;\n\ts! \\[ !$g_escape_table{'['}!gx;\n\ts! \\] !$g_escape_table{']'}!gx;\n\ts! \\\\ !$g_escape_table{'\\\\'}!gx;\n\n\treturn $_;\n}\n\n\nsub _DoItalicsAndBold {\n\tmy $text = shift;\n\n\t# <strong> must go first:\n\t$text =~ s{ (\\*\\*|__) (?=\\S) (.+?[*_]*) (?<=\\S) \\1 }\n\t\t{<strong>$2</strong>}gsx;\n\n\t$text =~ s{ (\\*|_) (?=\\S) (.+?) (?<=\\S) \\1 }\n\t\t{<em>$2</em>}gsx;\n\n\treturn $text;\n}\n\n\nsub _DoBlockQuotes {\n\tmy $text = shift;\n\n\t$text =~ s{\n\t\t  (\t\t\t\t\t\t\t\t# Wrap whole match in $1\n\t\t\t(\n\t\t\t  ^[ \\t]*>[ \\t]?\t\t\t# '>' at the start of a line\n\t\t\t    .+\\n\t\t\t\t\t# rest of the first line\n\t\t\t  (.+\\n)*\t\t\t\t\t# subsequent consecutive lines\n\t\t\t  \\n*\t\t\t\t\t\t# blanks\n\t\t\t)+\n\t\t  )\n\t\t}{\n\t\t\tmy $bq = $1;\n\t\t\t$bq =~ s/^[ \\t]*>[ \\t]?//gm;\t# trim one level of quoting\n\t\t\t$bq =~ s/^[ \\t]+$//mg;\t\t\t# trim whitespace-only lines\n\t\t\t$bq = _RunBlockGamut($bq);\t\t# recurse\n\n\t\t\t$bq =~ s/^/  /g;\n\t\t\t# These leading spaces screw with <pre> content, so we need to fix that:\n\t\t\t$bq =~ s{\n\t\t\t\t\t(\\s*<pre>.+?</pre>)\n\t\t\t\t}{\n\t\t\t\t\tmy $pre = $1;\n\t\t\t\t\t$pre =~ s/^  //mg;\n\t\t\t\t\t$pre;\n\t\t\t\t}egsx;\n\n\t\t\t\"<blockquote>\\n$bq\\n</blockquote>\\n\\n\";\n\t\t}egmx;\n\n\n\treturn $text;\n}\n\n\nsub _FormParagraphs {\n#\n#\tParams:\n#\t\t$text - string to process with html <p> tags\n#\n\tmy $text = shift;\n\n\t# Strip leading and trailing lines:\n\t$text =~ s/\\A\\n+//;\n\t$text =~ s/\\n+\\z//;\n\n\tmy @grafs = split(/\\n{2,}/, $text);\n\n\t#\n\t# Wrap <p> tags.\n\t#\n\tforeach (@grafs) {\n\t\tunless (defined( $g_html_blocks{$_} )) {\n\t\t\t$_ = _RunSpanGamut($_);\n\t\t\ts/^([ \\t]*)/<p>/;\n\t\t\t$_ .= \"</p>\";\n\t\t}\n\t}\n\n\t#\n\t# Unhashify HTML blocks\n\t#\n\tforeach (@grafs) {\n\t\tif (defined( $g_html_blocks{$_} )) {\n\t\t\t$_ = $g_html_blocks{$_};\n\t\t}\n\t}\n\n\treturn join \"\\n\\n\", @grafs;\n}\n\n\nsub _EncodeAmpsAndAngles {\n# Smart processing for ampersands and angle brackets that need to be encoded.\n\n\tmy $text = shift;\n\n\t# Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:\n\t#   http://bumppo.net/projects/amputator/\n \t$text =~ s/&(?!#?[xX]?(?:[0-9a-fA-F]+|\\w+);)/&amp;/g;\n\n\t# Encode naked <'s\n \t$text =~ s{<(?![a-z/?\\$!])}{&lt;}gi;\n\n\treturn $text;\n}\n\n\nsub _EncodeBackslashEscapes {\n#\n#   Parameter:  String.\n#   Returns:    The string, with after processing the following backslash\n#               escape sequences.\n#\n    local $_ = shift;\n\n    s! \\\\\\\\  !$g_escape_table{'\\\\'}!gx;\t\t# Must process escaped backslashes first.\n    s! \\\\`   !$g_escape_table{'`'}!gx;\n    s! \\\\\\*  !$g_escape_table{'*'}!gx;\n    s! \\\\_   !$g_escape_table{'_'}!gx;\n    s! \\\\\\{  !$g_escape_table{'{'}!gx;\n    s! \\\\\\}  !$g_escape_table{'}'}!gx;\n    s! \\\\\\[  !$g_escape_table{'['}!gx;\n    s! \\\\\\]  !$g_escape_table{']'}!gx;\n    s! \\\\\\(  !$g_escape_table{'('}!gx;\n    s! \\\\\\)  !$g_escape_table{')'}!gx;\n    s! \\\\>   !$g_escape_table{'>'}!gx;\n    s! \\\\\\#  !$g_escape_table{'#'}!gx;\n    s! \\\\\\+  !$g_escape_table{'+'}!gx;\n    s! \\\\\\-  !$g_escape_table{'-'}!gx;\n    s! \\\\\\.  !$g_escape_table{'.'}!gx;\n    s{ \\\\!  }{$g_escape_table{'!'}}gx;\n\n    return $_;\n}\n\n\nsub _DoAutoLinks {\n\tmy $text = shift;\n\n\t$text =~ s{<((https?|ftp):[^'\">\\s]+)>}{<a href=\"$1\">$1</a>}gi;\n\n\t# Email addresses: <address@domain.foo>\n\t$text =~ s{\n\t\t<\n        (?:mailto:)?\n\t\t(\n\t\t\t[-.\\w]+\n\t\t\t\\@\n\t\t\t[-a-z0-9]+(\\.[-a-z0-9]+)*\\.[a-z]+\n\t\t)\n\t\t>\n\t}{\n\t\t_EncodeEmailAddress( _UnescapeSpecialChars($1) );\n\t}egix;\n\n\treturn $text;\n}\n\n\nsub _EncodeEmailAddress {\n#\n#\tInput: an email address, e.g. \"foo@example.com\"\n#\n#\tOutput: the email address as a mailto link, with each character\n#\t\tof the address encoded as either a decimal or hex entity, in\n#\t\tthe hopes of foiling most address harvesting spam bots. E.g.:\n#\n#\t  <a href=\"&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101;\n#       x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;\">&#102;&#111;&#111;\n#       &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a>\n#\n#\tBased on a filter by Matthew Wickline, posted to the BBEdit-Talk\n#\tmailing list: <http://tinyurl.com/yu7ue>\n#\n\n\tmy $addr = shift;\n\n\tsrand;\n\tmy @encode = (\n\t\tsub { '&#' .                 ord(shift)   . ';' },\n\t\tsub { '&#x' . sprintf( \"%X\", ord(shift) ) . ';' },\n\t\tsub {                            shift          },\n\t);\n\n\t$addr = \"mailto:\" . $addr;\n\n\t$addr =~ s{(.)}{\n\t\tmy $char = $1;\n\t\tif ( $char eq '@' ) {\n\t\t\t# this *must* be encoded. I insist.\n\t\t\t$char = $encode[int rand 1]->($char);\n\t\t} elsif ( $char ne ':' ) {\n\t\t\t# leave ':' alone (to spot mailto: later)\n\t\t\tmy $r = rand;\n\t\t\t# roughly 10% raw, 45% hex, 45% dec\n\t\t\t$char = (\n\t\t\t\t$r > .9   ?  $encode[2]->($char)  :\n\t\t\t\t$r < .45  ?  $encode[1]->($char)  :\n\t\t\t\t\t\t\t $encode[0]->($char)\n\t\t\t);\n\t\t}\n\t\t$char;\n\t}gex;\n\n\t$addr = qq{<a href=\"$addr\">$addr</a>};\n\t$addr =~ s{\">.+?:}{\">}; # strip the mailto: from the visible part\n\n\treturn $addr;\n}\n\n\nsub _UnescapeSpecialChars {\n#\n# Swap back in all the special characters we've hidden.\n#\n\tmy $text = shift;\n\n\twhile( my($char, $hash) = each(%g_escape_table) ) {\n\t\t$text =~ s/$hash/$char/g;\n\t}\n    return $text;\n}\n\n\nsub _TokenizeHTML {\n#\n#   Parameter:  String containing HTML markup.\n#   Returns:    Reference to an array of the tokens comprising the input\n#               string. Each token is either a tag (possibly with nested,\n#               tags contained therein, such as <a href=\"<MTFoo>\">, or a\n#               run of text between tags. Each element of the array is a\n#               two-element array; the first is either 'tag' or 'text';\n#               the second is the actual value.\n#\n#\n#   Derived from the _tokenize() subroutine from Brad Choate's MTRegex plugin.\n#       <http://www.bradchoate.com/past/mtregex.php>\n#\n\n    my $str = shift;\n    my $pos = 0;\n    my $len = length $str;\n    my @tokens;\n\n    my $depth = 6;\n    my $nested_tags = join('|', ('(?:<[a-z/!$](?:[^<>]') x $depth) . (')*>)' x  $depth);\n    my $match = qr/(?s: <! ( -- .*? -- \\s* )+ > ) |  # comment\n                   (?s: <\\? .*? \\?> ) |              # processing instruction\n                   $nested_tags/ix;                   # nested tags\n\n    while ($str =~ m/($match)/g) {\n        my $whole_tag = $1;\n        my $sec_start = pos $str;\n        my $tag_start = $sec_start - length $whole_tag;\n        if ($pos < $tag_start) {\n            push @tokens, ['text', substr($str, $pos, $tag_start - $pos)];\n        }\n        push @tokens, ['tag', $whole_tag];\n        $pos = pos $str;\n    }\n    push @tokens, ['text', substr($str, $pos, $len - $pos)] if $pos < $len;\n    \\@tokens;\n}\n\n\nsub _Outdent {\n#\n# Remove one level of line-leading tabs or spaces\n#\n\tmy $text = shift;\n\n\t$text =~ s/^(\\t|[ ]{1,$g_tab_width})//gm;\n\treturn $text;\n}\n\n\nsub _Detab {\n#\n# Cribbed from a post by Bart Lateur:\n# <http://www.nntp.perl.org/group/perl.macperl.anyperl/154>\n#\n\tmy $text = shift;\n\n\t$text =~ s{(.*?)\\t}{$1.(' ' x ($g_tab_width - length($1) % $g_tab_width))}ge;\n\treturn $text;\n}\n\n\n1;\n\n__END__\n\n\n=pod\n\n=head1 NAME\n\nB<Markdown>\n\n\n=head1 SYNOPSIS\n\nB<Markdown.pl> [ B<--html4tags> ] [ B<--version> ] [ B<-shortversion> ]\n    [ I<file> ... ]\n\n\n=head1 DESCRIPTION\n\nMarkdown is a text-to-HTML filter; it translates an easy-to-read /\neasy-to-write structured text format into HTML. Markdown's text format\nis most similar to that of plain text email, and supports features such\nas headers, *emphasis*, code blocks, blockquotes, and links.\n\nMarkdown's syntax is designed not as a generic markup language, but\nspecifically to serve as a front-end to (X)HTML. You can  use span-level\nHTML tags anywhere in a Markdown document, and you can use block level\nHTML tags (like <div> and <table> as well).\n\nFor more information about Markdown's syntax, see:\n\n    http://daringfireball.net/projects/markdown/\n\n\n=head1 OPTIONS\n\nUse \"--\" to end switch parsing. For example, to open a file named \"-z\", use:\n\n\tMarkdown.pl -- -z\n\n=over 4\n\n\n=item B<--html4tags>\n\nUse HTML 4 style for empty element tags, e.g.:\n\n    <br>\n\ninstead of Markdown's default XHTML style tags, e.g.:\n\n    <br />\n\n\n=item B<-v>, B<--version>\n\nDisplay Markdown's version number and copyright information.\n\n\n=item B<-s>, B<--shortversion>\n\nDisplay the short-form version number.\n\n\n=back\n\n\n\n=head1 BUGS\n\nTo file bug reports or feature requests (other than topics listed in the\nCaveats section above) please send email to:\n\n    support@daringfireball.net\n\nPlease include with your report: (1) the example input; (2) the output\nyou expected; (3) the output Markdown actually produced.\n\n\n=head1 VERSION HISTORY\n\nSee the readme file for detailed release notes for this version.\n\n1.0.1 - 14 Dec 2004\n\n1.0 - 28 Aug 2004\n\n\n=head1 AUTHOR\n\n    John Gruber\n    http://daringfireball.net\n\n    PHP port and other contributions by Michel Fortin\n    http://michelf.com\n\n\n=head1 COPYRIGHT AND LICENSE\n\nCopyright (c) 2003-2004 John Gruber   \n<http://daringfireball.net/>   \nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n* Redistributions of source code must retain the above copyright notice,\n  this list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright\n  notice, this list of conditions and the following disclaimer in the\n  documentation and/or other materials provided with the distribution.\n\n* Neither the name \"Markdown\" nor the names of its contributors may\n  be used to endorse or promote products derived from this software\n  without specific prior written permission.\n\nThis software is provided by the copyright holders and contributors \"as\nis\" and any express or implied warranties, including, but not limited\nto, the implied warranties of merchantability and fitness for a\nparticular purpose are disclaimed. In no event shall the copyright owner\nor contributors be liable for any direct, indirect, incidental, special,\nexemplary, or consequential damages (including, but not limited to,\nprocurement of substitute goods or services; loss of use, data, or\nprofits; or business interruption) however caused and on any theory of\nliability, whether in contract, strict liability, or tort (including\nnegligence or otherwise) arising in any way out of the use of this\nsoftware, even if advised of the possibility of such damage.\n\n=cut\n"
  },
  {
    "path": "_archive/apps/samples/dojo/README.md",
    "content": "Dojo\n====\nThis directory contains a script (build.sh) to generate an \"one-app-to-rule-them-all\": an app that executes all the other apps in the repository.\n\nTo create the app, run `build.sh` on your Mac or Linux. It is necessary to have Perl installed (MacOsX and Linux both have by default). The generated kitchen-sink app will be in `dojo.crx`.\n\nSpecial thanks to @tomtasche for the idea and for the non-automatic implementation, which ultimately resulted in this script.\n\nPlease join the [Chromium Apps](https://groups.google.com/a/chromium.org/forum/?fromgroups#!forum/chromium-apps) group for general discussion. We're also available on IRC at #chromium-apps ([Freenode](http://freenode.net/)).\n"
  },
  {
    "path": "_archive/apps/samples/dojo/build.sh",
    "content": "#!/bin/bash\n\n# Subroutines\nfunction writeJS_header() {\n  cat > ${BUILDDIR}/main.js <<EOF\nvar _dojo_apps={};\n\nfunction _dojo_set_app_launcher(app, launcher) {\n  _dojo_apps[app]=launcher;\n}\n\nfunction _dojo_launch(app) {\n  if (_dojo_apps[app]) {\n    _dojo_apps[app]();\n  } else {\n    console.log(\"Could not find app \"+app);\n  }\n}\n\nfunction _dojo_readme(file) {\n  chrome.app.window.create(file,\n    {innerBounds: {width: 500, height: 700, left: 602}});\n}\nfunction _dojo_source(app) {\n  window.open(\"https://github.com/GoogleChrome/chrome-app-samples/tree/master/\"+app);\n}\n\nEOF\n}\n\n\nfunction writeJS_accumulatebgtasks() {\n  cat ../${app}/$BGSCRIPT | \\\n     perl -pe \"s/chrome.app.runtime.onLaunched.addListener\\(/_dojo_set_app_launcher(\\\"$app_norm\\\", /g\" |\\\n     perl -pe \"s%(chrome.app.window.create.*?[\\\"'])%\\1$app/%g\" \\\n     >> ${BUILDDIR}/main.js\n}\n\nfunction writeJS_showsource() {\n  cat >> ${BUILDDIR}/main.js <<EOF\n    document.getElementById(\"${app_norm}_source\").addEventListener(\"click\", function(e) { _dojo_source(\"${app}\"); });\nEOF\n}\n\nfunction writeJS_launchapp() {\n  cat >> ${BUILDDIR}/main.js <<EOF\n    document.getElementById(\"${app_norm}_launch\").addEventListener(\"click\", function(e) { _dojo_launch(\"${app_norm}\"); });\nEOF\n}\n\nfunction writeJS_launch() {\n  cat > ${BUILDDIR}/background.js <<EOF\n\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n    innerBounds: {\n      width: 600,\n      height: 800\n    }\n  });\n});\nEOF\n}\n\n\nfunction accumulate_appmanifestinfo() {\n    # accumulate this apps' permissions\n    if grep -q \"permissions\" ${MF} ; then\n      cat ${MF} | perl -pe 's/\\n/ /sg' | perl -pe 's/.*\"permissions\"[^[]*\\[(.*?)\\].*/\\1/g' | perl -pe 's/[^\"]*\"(.*?)\"[^\"]*/\\1\\n/g' >> $PERMFILE\n    fi\n    # accumulate this apps' sandboxed pages\n    if grep -q \"sandbox\" ${MF} ; then \n      cat ${MF} | perl -pe 's/\\n/ /sg' | perl -pe 's/.*\"sandbox\"[^[]*\\[(.*?)\\].*/\\1/g' | perl -pe \"s/[^\\\"]*\\\"(.*?)\\\"[^\\\"]*/${app}\\/\\1\\n/g\" >> $SBFILE\n    fi\n}\n\nfunction writeHTML_header() {\n  cat > ${BUILDDIR}/index.html <<EOF\n<html>\n  <head>\n    <title>Chrome Apps Dojo</title>\n    <link rel=\"stylesheet\" media=\"all\" href=\"main.css\"></link>\n  </head>\n\n  <body>\n    <p>Choose a sample to start with, or simply start hacking right here (<b>right-click - Inspect Element</b>!)<br/>\n    Read more at <a target=\"_blank\" href=\"http://developer.chrome.com/apps\">the Chrome Packaged Apps site</a></p>\n    <ul class=\"apps\">\nEOF\n}\n\nfunction writeHTML_readme() {\n  _readme=../${app}/README.md\n  if [ -f ${_readme} ] ; then\n    echo \"&nbsp;<a id=\\\"${app_norm}_readme\\\" href=\\\"#\\\" class=\\\"readme\\\">(read more...)</a>\" >> ${BUILDDIR}/index.html\n    Markdown_1.0.1/Markdown.pl ${_readme} >> ${BUILDDIR}/readme_${app_norm}.html\n    echo \"document.getElementById(\\\"${app_norm}_readme\\\").addEventListener(\\\"click\\\", function(e) { _dojo_readme(\\\"readme_${app_norm}.html\\\"); });\" >> ${BUILDDIR}/main.js \n  fi\n}\n\nfunction writeHTML_appicon() {\n  NEWICONFILE=\"noicon.png\"\n  if grep -q \"icons\" ${MF} ; then \n    ICON=`cat ${MF} | perl -pe 's/\\n/ /sg' | perl -pe 's/.*\"icons\".*?\"128\"[^\"]*\"(.*?)\".*/\\1/g'`\n    NEWICONFILE=\"icon_${app_norm}.png\"\n    cp \"../${app}/${ICON}\" ${BUILDDIR}/$NEWICONFILE\n  fi\n  echo \"<img src=\\\"${NEWICONFILE}\\\"></img>\" >> ${BUILDDIR}/index.html\n}\n\nfunction writeHTML_appitem() {\n  echo \"<li>\" >> ${BUILDDIR}/index.html\n  writeHTML_appicon\n  echo \"<h2>${app}</h2><p>${APPNAME}\" >> ${BUILDDIR}/index.html\n  writeHTML_readme\n  echo \"</p>\" >> ${BUILDDIR}/index.html\n  cat >> ${BUILDDIR}/index.html <<EOF\n        <div class=\"actions\">${_execute_button}<a href=\"#\" id=\"${app_norm}_source\">see source on GitHub</a></div>\n   </li>\nEOF\n}\n\nfunction writeHTML_footer() {\n  cat >> ${BUILDDIR}/index.html <<EOF\n    </ul>\n    Want more? Catch 'em all on <a target=\"_blank\" href=\"https://github.com/GoogleChrome/chrome-app-samples\">GitHub</a>.\n    \n    <script src=\"main.js\"></script>\n  </body>\n</html>\nEOF\n}\n\n\nfunction writeManifest() {\n  cat > ${BUILDDIR}/manifest.json <<EOF\n{\n  \"name\": \"Chrome Apps Dojo\",\n  \"version\": \"1\",\n  \"manifest_version\": 2,\n  \"icons\": {\n    \"16\": \"dojo.png\",\n    \"128\": \"dojo.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [${PERMISSIONS}],\n  \"sandbox\": {\n    \"pages\": [${SANDBOXES}]\n  }\n}\nEOF\n}\n\n\n\n# -----------  main code starts here\n\nBUILDDIR='out'\nTMP='tmp'\nPERMFILE=\"${TMP}/permissions\"\nSBFILE=\"${TMP}/sandboxes\"\nEXECUTABLES=\"executable_list\"\n\nrm -Rf ${BUILDDIR}\nrm -Rf ${TMP}\n\nmkdir -p ${BUILDDIR}\nmkdir -p ${TMP}\n\necho > ${PERMFILE}\necho > ${SBFILE}\n\nwriteJS_header\nwriteHTML_header\n\nNON_EXECUTABLE=\"\"\n\n# get all apps which have manifest.json\nfor app in `find .. -name \"manifest.json\" -not -path \"*/dojo/*\" | perl -pe \"s/\\.\\.\\/(.*?)\\/manifest.json/\\1/\"` ; do\n  app_norm=`echo $app | tr '/' '_'`\n  MF=../${app}/manifest.json\n  if [ ! -f $MF ] ; then\n   echo \"Ignoring ${app}: Could not find manifest file ${MF}\"\n   continue\n  fi\n  APPNAME=`cat ${MF} | perl -pe 's/\\n/ /sg' | perl -pe 's/.*\"name\"[^\"]*\"(.*?)\".*/\\1/g'`\n  # TODO: support more than one background script. Currently we don't have any case like this,\n  # but this code will break if we have\n  BGSCRIPT=`cat ${MF} | perl -pe 's/\\n/ /sg' | perl -pe 's/.*\"background\".*?\"scripts\"[^\"]*\"(.*?)\".*/\\1/g'`\n\n  writeJS_showsource\n\n  _execute_button=\"\"\n\n  # only allow inline execution of the app if it is in ${EXECUTABLES}\n  if grep -q ${app} ${EXECUTABLES} ; then \n    accumulate_appmanifestinfo\n\n    _execute_button=\"<button id=\\\"${app_norm}_launch\\\">execute</button><br/>\"\n\n    writeJS_accumulatebgtasks\n    writeJS_launchapp\n\n    mkdir -p ${BUILDDIR}/${app}\n    cp -R ../${app}/* ${BUILDDIR}/${app}\n  else\n    NON_EXECUTABLE=\"${NON_EXECUTABLE} $app\"\n  fi\n\n  writeHTML_appitem\n\ndone\n\nif [ \"x$NON_EXECUTABLE\"!=\"x\" ] ; then\n  echo \"Warning: the following apps are not in the ${EXECUTABLES} files, so they won't be executable from the Dojo app: ${NON_EXECUTABLE}\" \nfi\n\nPERMISSIONS=`cat $PERMFILE | sort | uniq | perl -pe 's/(.+)\\n/\"\\1\",/sg' | perl -pe 's/,$//g'`\nSANDBOXES=`cat $SBFILE | sort | uniq | perl -pe 's/(.+)\\n/\"\\1\",/sg' | perl -pe 's/,$//g'`\n\nwriteManifest\nwriteJS_launch\nwriteHTML_footer\n\n\ncp include/* ${BUILDDIR}\n\nif [ \"$1x\" == \"--nocrxx\" ] ; then\n  echo \"No CRX generated. Use the out/ directory\"\n  exit 0;\nfi\n\nPEMFILE=${TMP}/key.pem\n\nif [ ! -f ${PEMFILE} ] ; then\n  openssl genrsa -out ${PEMFILE} 1024\n  if [ ! -f ${PEMFILE} ] ; then\n    echo Could not generate a private key file. Please check if you have openssl installed.\n    exit 1\n  fi\nfi\n\n./crxmake.sh ${BUILDDIR} ${PEMFILE} \n\nif [ ! -f \"${BUILDDIR}.crx\" ] ; then\n  echo Could not create crx. Please try to run crxmake.sh by hand:\n  echo ./crxmake.sh ${BUILDDIR} ${PEMFILE}\n  exit 1\nfi\n\nmv ${BUILDDIR}.crx dojo.crx\n\necho \"Successfuly created dojo.crx. You may now drag and drop it on your Chrome Extensions page\"\n\n"
  },
  {
    "path": "_archive/apps/samples/dojo/crxmake.sh",
    "content": "#!/bin/bash -e\n#\n# Purpose: Pack a Chromium extension directory into crx format\nif test $# -ne 2; then\n  echo \"Usage: crxmake.sh <extension dir> <pem path>\"\n  exit 1\nfi\ndir=$1\nkey=$2\nname=$(basename \"$dir\")\ncrx=\"$name.crx\"\npub=\"$name.pub\"\nsig=\"$name.sig\"\nzip=\"$name.zip\"\ntrap 'rm -f \"$pub\" \"$sig\" \"$zip\"' EXIT\n# zip up the crx dir\ncwd=$(pwd -P)\n(cd \"$dir\" && zip -qr -9 -X \"$cwd/$zip\" .)\n# signature\nopenssl sha1 -sha1 -binary -sign \"$key\" < \"$zip\" > \"$sig\"\n# public key\nopenssl rsa -pubout -outform DER < \"$key\" > \"$pub\" 2>/dev/null\nbyte_swap () {\n  # Take \"abcdefgh\" and return it as \"ghefcdab\"\n  echo \"${1:6:2}${1:4:2}${1:2:2}${1:0:2}\"\n}\ncrmagic_hex=\"4372 3234\" # Cr24\nversion_hex=\"0200 0000\" # 2\npub_len_hex=$(byte_swap $(printf '%08x\\n' $(ls -l \"$pub\" | awk '{print $5}')))\nsig_len_hex=$(byte_swap $(printf '%08x\\n' $(ls -l \"$sig\" | awk '{print $5}')))\n(\n  echo \"$crmagic_hex $version_hex $pub_len_hex $sig_len_hex\" | xxd -r -p\n  cat \"$pub\" \"$sig\" \"$zip\"\n) > \"$crx\"\necho \"Wrote $crx\"\n"
  },
  {
    "path": "_archive/apps/samples/dojo/executable_list",
    "content": "frameless-window\nserial/adkjs/app\nanalytics\nappsquare\nbrowser-tag\ncalculator\ncamera-capture\ncontext-menu\ndiff\neval-in-iframe\nfilesystem-access\ngdocs\nhello-world\nidentity\nio2012-presentation\nioio\nmini-code-edit\nregex-tester\nsandboxed-content\nserial\nserial-control-signals\nservo\nstorage\ntext-editor\nusb/adkjs/app\nwebintents\nweather\nwindows\nzephyr_hxm\nwebgl-pointer-lock\nclock\n"
  },
  {
    "path": "_archive/apps/samples/dojo/include/main.css",
    "content": "body {\n  font-family: 'Open Sans', arial, sans-serif;  \n  font-size: 12px;\n}\n\n.apps {\n background-color: #E5E5E5;\n border-radius: 2px;\n border: 1px solid #ddd;\n box-shadow: 0 3px 15px rgba(0, 0, 0, 0.25);\n padding: 5px;\n margin: 0;\n}\na, a:visited, a:hover {\n  text-decoration: none;\n  cursor: pointer;\n  color: #00E;\n}\n\n.apps li {\n list-style: none; \n position: relative;\n border-bottom: 1px solid #C6C6C6;\n box-shadow: 0px 1px 0px 0px #FEFEFE;\n padding: 5px 0;\n}\n.apps li:hover {\n  background-color: #eee;\n}\n\n.apps li:last-child {\n border-bottom: 0;\n box-shadow: 0px;\n}\n\n.apps li:after {\n  content: \".\";\n  display: block;\n  height: 0;\n  visibility: hidden;\n  clear: both;\n}\n\n.apps h2 {\n  margin: 0 0 5px 0;\n}\n\n.apps li p {\n  margin: 0;\n}\n\n.apps li img {\n  width: 64px;\n  float: left;\n  margin: 0 10px 5px 5px;\n}\n\n.apps li:hover .actions {\n  visibility: visible;\n}\n\n.apps .actions {\n  visibility: hidden;\n  position: absolute;\n  text-align: right;\n  right: 5px;\n  bottom: 10px;\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/filesystem-access/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ehbhjpchdgepkgjhfkhpkjdbnljedllm\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Filesystem access\n\nShows basic usage of accessing (read/write) files and directories using the `chrome.fileSystem` API.\n\nNOTE: This sample requires Milestone 31 or later of Chrome, since it uses the new directory permission.\n\n## APIs\n\n* [chrome.fileSystem](http://developer.chrome.com/apps/fileSystem)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/filesystem-access/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/filesystem-access/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function(launchData) {\n  chrome.app.window.create('index.html', {id:\"fileWin\", innerBounds: {width: 800, height: 500}}, function(win) {\n    win.contentWindow.launchData = launchData;\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/filesystem-access/index.html",
    "content": "<html>\n<head>\n<title>Filesystem Access Example</title>\n<style>\nbody {\n  display: -webkit-flex;\n  -webkit-flex-direction: column;\n}\n.dropping {\n  background: #ffcc00;\n}\nnav {\n\tdisplay: -webkit-flex;\n\t-webkit-justify-content: center;\n\t-webkit-align-items: center;\n}\nvideo {\n\twidth: 640px;\n\theight: 480px;\n\tbackground: rgba(0,0,0,0.25);\n}\nbutton {\n  display: inline-block;\n  background: -webkit-linear-gradient(#F9F9F9 40%, #E3E3E3 70%);\n  background: linear-gradient(#F9F9F9 40%, #E3E3E3 70%);\n  border: 1px solid #999;\n  -webkit-border-radius: 3px;\n  border-radius: 3px;\n  padding: 5px 8px;\n  outline: none;\n  white-space: nowrap;\n  -webkit-user-select: none;\n  user-select: none;\n  cursor: pointer;\n  text-shadow: 1px 1px #fff;\n  font-weight: 700;\n  font-size: 10pt;\n}\nbutton:not(:disabled):hover {\n  border-color: black;\n}\nbutton:not(:disabled):active {\n  background: -webkit-linear-gradient(#E3E3E3 40%, #F9F9F9 70%);\n  background: linear-gradient(#E3E3E3 40%, #F9F9F9 70%);\n}\ninput {\n  width: 100%;\n  -webkit-user-select: none;\n}\ninput, textarea {\n  box-shadow: 1px 1px 5px #ccc inset;\n  border: none;\n  padding: 1em;\n}\n[readonly] {\n  background: #eee;\n}\n[hidden] {\n  display: none;\n}\ntextarea {\n  width: 100%;\n  height: 200px;\n  outline: none;\n  padding: 1px;\n  font-size: 14pt;\n  padding: 1em;\n}\noutput {\n  text-align: center;\n  padding: 1em;\n  display: block;\n}\n</style>\n</head>\n<body>\n\n<nav>\n  <button id=\"choose_file\">Choose File</button>\n  <button id=\"choose_dir\">Choose Directory</button>\n</nav>\n\nPath: <input type=\"text\" id=\"file_path\" readonly>\n<span>Size: <span id=\"file_size\"></span> bytes</span>\n\n<output></output>\n\n<textarea></textarea>\n\n<p><button id=\"save_file\" disabled>Save As</button></p>\n\n<script src=\"js/dnd.js\"></script>\n<script src=\"js/app.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/filesystem-access/js/app.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Eric Bidelman (ericbidelman@chromium.org)\nUpdated: Joe Marini (joemarini@google.com)\n*/\n\nvar chosenEntry = null;\nvar chooseFileButton = document.querySelector('#choose_file');\nvar chooseDirButton = document.querySelector('#choose_dir');\nvar saveFileButton = document.querySelector('#save_file');\nvar output = document.querySelector('output');\nvar textarea = document.querySelector('textarea');\n\nfunction errorHandler(e) {\n  console.error(e);\n}\n\nfunction displayEntryData(theEntry) {\n  if (theEntry.isFile) {\n    chrome.fileSystem.getDisplayPath(theEntry, function(path) {\n      document.querySelector('#file_path').value = path;\n    });\n    theEntry.getMetadata(function(data) {\n      document.querySelector('#file_size').textContent = data.size;\n    });    \n  }\n  else {\n    document.querySelector('#file_path').value = theEntry.fullPath;\n    document.querySelector('#file_size').textContent = \"N/A\";\n  }\n}\n\nfunction readAsText(fileEntry, callback) {\n  fileEntry.file(function(file) {\n    var reader = new FileReader();\n\n    reader.onerror = errorHandler;\n    reader.onload = function(e) {\n      callback(e.target.result);\n    };\n\n    reader.readAsText(file);\n  });\n}\n\nfunction writeFileEntry(writableEntry, opt_blob, callback) {\n  if (!writableEntry) {\n    output.textContent = 'Nothing selected.';\n    return;\n  }\n\n  writableEntry.createWriter(function(writer) {\n\n    writer.onerror = errorHandler;\n    writer.onwriteend = callback;\n\n    // If we have data, write it to the file. Otherwise, just use the file we\n    // loaded.\n    if (opt_blob) {\n      writer.truncate(opt_blob.size);\n      waitForIO(writer, function() {\n        writer.seek(0);\n        writer.write(opt_blob);\n      });\n    } \n    else {\n      chosenEntry.file(function(file) {\n        writer.truncate(file.fileSize);\n        waitForIO(writer, function() {\n          writer.seek(0);\n          writer.write(file);\n        });\n      });\n    }\n  }, errorHandler);\n}\n\nfunction waitForIO(writer, callback) {\n  // set a watchdog to avoid eventual locking:\n  var start = Date.now();\n  // wait for a few seconds\n  var reentrant = function() {\n    if (writer.readyState===writer.WRITING && Date.now()-start<4000) {\n      setTimeout(reentrant, 100);\n      return;\n    }\n    if (writer.readyState===writer.WRITING) {\n      console.error(\"Write operation taking too long, aborting!\"+\n        \" (current writer readyState is \"+writer.readyState+\")\");\n      writer.abort();\n    } \n    else {\n      callback();\n    }\n  };\n  setTimeout(reentrant, 100);\n}\n\n// for files, read the text content into the textarea\nfunction loadFileEntry(_chosenEntry) {\n  chosenEntry = _chosenEntry;\n  chosenEntry.file(function(file) {\n    readAsText(chosenEntry, function(result) {\n      textarea.value = result;\n    });\n    // Update display.\n    saveFileButton.disabled = false; // allow the user to save the content\n    displayEntryData(chosenEntry);\n  });\n}\n\n// for directories, read the contents of the top-level directory (ignore sub-dirs)\n// and put the results into the textarea, then disable the Save As button\nfunction loadDirEntry(_chosenEntry) {\n  chosenEntry = _chosenEntry;\n  if (chosenEntry.isDirectory) {\n    var dirReader = chosenEntry.createReader();\n    var entries = [];\n\n    // Call the reader.readEntries() until no more results are returned.\n    var readEntries = function() {\n       dirReader.readEntries (function(results) {\n        if (!results.length) {\n          textarea.value = entries.join(\"\\n\");\n          saveFileButton.disabled = true; // don't allow saving of the list\n          displayEntryData(chosenEntry);\n        } \n        else {\n          results.forEach(function(item) { \n            entries = entries.concat(item.fullPath);\n          });\n          readEntries();\n        }\n      }, errorHandler);\n    };\n\n    readEntries(); // Start reading dirs.    \n  }\n}\n\nfunction loadInitialFile(launchData) {\n  if (launchData && launchData.items && launchData.items[0]) {\n    loadFileEntry(launchData.items[0].entry);\n  } \n  else {\n    // see if the app retained access to an earlier file or directory\n    chrome.storage.local.get('chosenFile', function(items) {\n      if (items.chosenFile) {\n        // if an entry was retained earlier, see if it can be restored\n        chrome.fileSystem.isRestorable(items.chosenFile, function(bIsRestorable) {\n          // the entry is still there, load the content\n          console.info(\"Restoring \" + items.chosenFile);\n          chrome.fileSystem.restoreEntry(items.chosenFile, function(chosenEntry) {\n            if (chosenEntry) {\n              chosenEntry.isFile ? loadFileEntry(chosenEntry) : loadDirEntry(chosenEntry);\n            }\n          });\n        });\n      }\n    });\n  }\n}\n\nchooseFileButton.addEventListener('click', function(e) {\n  var accepts = [{\n    mimeTypes: ['text/*'],\n    extensions: ['js', 'css', 'txt', 'html', 'xml', 'tsv', 'csv', 'rtf']\n  }];\n  chrome.fileSystem.chooseEntry({type: 'openFile', accepts: accepts}, function(theEntry) {\n    if (!theEntry) {\n      output.textContent = 'No file selected.';\n      return;\n    }\n    // use local storage to retain access to this file\n    chrome.storage.local.set({'chosenFile': chrome.fileSystem.retainEntry(theEntry)});\n    loadFileEntry(theEntry);\n  });\n});\n\nchooseDirButton.addEventListener('click', function(e) {\n  chrome.fileSystem.chooseEntry({type: 'openDirectory'}, function(theEntry) {\n    if (!theEntry) {\n      output.textContent = 'No Directory selected.';\n      return;\n    }\n    // use local storage to retain access to this file\n    chrome.storage.local.set({'chosenFile': chrome.fileSystem.retainEntry(theEntry)});\n    loadDirEntry(theEntry);\n  });\n});\n\nsaveFileButton.addEventListener('click', function(e) {\n  var config = {type: 'saveFile', suggestedName: chosenEntry.name};\n  chrome.fileSystem.chooseEntry(config, function(writableEntry) {\n    var blob = new Blob([textarea.value], {type: 'text/plain'});\n    writeFileEntry(writableEntry, blob, function(e) {\n      output.textContent = 'Write complete :)';\n    });\n  });\n});\n\n// Support dropping a single file onto this app.\nvar dnd = new DnDFileController('body', function(data) {\n  chosenEntry = null;\n  for (var i = 0; i < data.items.length; i++) {\n    var item = data.items[i];\n    if (item.kind == 'file' &&\n        item.type.match('text/*') &&\n        item.webkitGetAsEntry()) {\n      chosenEntry = item.webkitGetAsEntry();\n      break;\n    }\n  };\n\n  if (!chosenEntry) {\n    output.textContent = \"Sorry. That's not a text file.\";\n    return;\n  } \n  else {\n    output.textContent = \"\";\n  }\n\n  readAsText(chosenEntry, function(result) {\n    textarea.value = result;\n  });\n  // Update display.\n  saveFileButton.disabled = false;\n  displayEntryData(chosenEntry);\n});\n\nloadInitialFile(launchData);\n"
  },
  {
    "path": "_archive/apps/samples/filesystem-access/js/dnd.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Eric Bidelman (ericbidelman@chromium.org)\n*/\n\nfunction DnDFileController(selector, onDropCallback) {\n  var el_ = document.querySelector(selector);\n  var overCount = 0;\n\n  this.dragenter = function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n    overCount++;\n    el_.classList.add('dropping');\n  };\n\n  this.dragover = function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n  };\n\n  this.dragleave = function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n    if (--overCount <= 0) {\n      el_.classList.remove('dropping');\n      overCount = 0;\n    }\n  };\n\n  this.drop = function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n\n    el_.classList.remove('dropping');\n\n    onDropCallback(e.dataTransfer)\n  };\n\n  el_.addEventListener('dragenter', this.dragenter, false);\n  el_.addEventListener('dragover', this.dragover, false);\n  el_.addEventListener('dragleave', this.dragleave, false);\n  el_.addEventListener('drop', this.drop, false);\n};\n"
  },
  {
    "path": "_archive/apps/samples/filesystem-access/manifest.json",
    "content": "{\n  \"name\": \"Filesystem Access Sample\",\n  \"version\": \"2.1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"31\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [\n    {\"fileSystem\": [\"write\", \"retainEntries\", \"directory\"]},\n    \"storage\"\n  ],\n  \"file_handlers\": {\n    \"text\": {\n      \"types\": [\n          \"text/*\"\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/frameless-window/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hjjdaddngnaofnfjpajdcbdmkegiakec\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Frameless window\n\nA sample application to showcase how you can use frame:'none' windows to allow total customization of the window's real estate. Initially, the window is open with no titlebar. When you check one of the titlebars, it is added to the appropriate position. Notice that the added titlebars are the only parts of the window that allow dragging. This is achieved through a special CSS property applied to what is draggable or non-draggable (by default, the whole window is not draggable): `-webkit-app-region: drag|no-drag;`\n\nCaveat: `-webkit-app-region: drag;` *will* disable some customizations such as custom mouse pointers.\n\n## APIs\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/frameless-window/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/frameless-window/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create(\"frameless_window.html\",\n    {  frame: \"none\",\n       id: \"framelessWinID\",\n       innerBounds: {\n         width: 360,\n         height: 300,\n         left: 600,\n         minWidth: 220,\n         minHeight: 220\n      }\n    }\n  );\n});\n"
  },
  {
    "path": "_archive/apps/samples/frameless-window/frameless_window.html",
    "content": "<html>\n\n<head>\n\n<title>Frameless Window</title>\n\n<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />\n<script src=\"titlebar.js\"></script>\n<script src=\"frameless_window.js\"></script>\n\n</head>\n\n<body>\n\n<div id=\"content\">\n\n<div id=\"inner-content\">\n\nSelect the titlebar to enable:<br/>\n<input type=\"checkbox\" id=\"top-box\">Top Titlebar\n<br/>\n<input type=\"checkbox\" id=\"bottom-box\">Bottom Titlebar\n<br/>\n<input type=\"checkbox\" id=\"left-box\">Left Titlebar\n<br/>\n<input type=\"checkbox\" id=\"right-box\">Right Titlebar\n<br/>\n<br/>\n<button id=\"close-window-button\">Close Window</button>\n\n</div>\n\n</div>\n\n</body>\n\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/frameless-window/frameless_window.js",
    "content": "function updateCheckbox() {\n  var top_checkbox = document.getElementById(\"top-box\");\n  var bottom_checkbox = document.getElementById(\"bottom-box\");\n  var left_checkbox = document.getElementById(\"left-box\");\n  var right_checkbox = document.getElementById(\"right-box\");\n  if (top_checkbox.checked || bottom_checkbox.checked) {\n    left_checkbox.disabled = true;\n    right_checkbox.disabled = true;\n  } else if (left_checkbox.checked || right_checkbox.checked) {\n    top_checkbox.disabled = true;\n    bottom_checkbox.disabled = true;\n  } else {\n    left_checkbox.disabled = false;\n    right_checkbox.disabled = false;\n    top_checkbox.disabled = false;\n    bottom_checkbox.disabled = false;\n  }\n}\n\nfunction initCheckbox(checkboxId, titlebar_name, titlebar_icon_url, titlebar_text) {\n  var elem = document.getElementById(checkboxId);\n  if (!elem)\n    return;\n  elem.onclick = function() {\n    if (document.getElementById(checkboxId).checked)\n      addTitlebar(titlebar_name, titlebar_icon_url, titlebar_text);\n    else\n      removeTitlebar(titlebar_name);\n    focusTitlebars(true);\n\n    updateContentStyle();\n    updateCheckbox();\n  }\n}\n\nwindow.onfocus = function() { \n  console.log(\"focus\");\n  focusTitlebars(true);\n}\n\nwindow.onblur = function() { \n  console.log(\"blur\");\n  focusTitlebars(false);\n}\n\nwindow.onresize = function() {\n  updateContentStyle();\n}\n\nwindow.onload = function() {\n  initCheckbox(\"top-box\", \"top-titlebar\", \"top-titlebar.png\", \"Top Titlebar\");\n  initCheckbox(\"bottom-box\", \"bottom-titlebar\", \"bottom-titlebar.png\", \"Bottom Titlebar\");\n  initCheckbox(\"left-box\", \"left-titlebar\", \"left-titlebar.png\", \"Left Titlebar\");\n  initCheckbox(\"right-box\", \"right-titlebar\", \"right-titlebar.png\", \"Right Titlebar\");\n  \n  document.getElementById(\"close-window-button\").onclick = function() {\n    window.close();\n  }\n  \n  updateContentStyle();\n}\n"
  },
  {
    "path": "_archive/apps/samples/frameless-window/manifest.json",
    "content": "{\n  \"name\": \"Frameless Window Sample\",\n  \"description\": \"Chrome platform app.\",\n  \"manifest_version\": 2,\n  \"version\": \"0.2\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/frameless-window/style.css",
    "content": "html {\n  margin: 0px;\n  padding: 0px;\n  overflow: hidden;\n}\n\nbody {\n  margin: 0px;\n  padding: 0px;\n}\n\n::-webkit-scrollbar-thumb {\n  display: none;\n}\n\ninput[type=\"checkbox\"]:disabled\n{\n  opacity: .3;\n}\n\ndiv#content {\n  background-color: #dddddd;\n  margin: 0px;\n  padding: 0px;\n}\n\ndiv#inner-content {\n  background-color: #dddddd;\n  margin: 10px;\n  width: 100%;\n  height: 100%;\n}\n\n.top-titlebar {\n  position: absolute;\n  left: 0px;\n  top: 0px;\n  width: 100%;\n  height: 32px;\n  background-color: #7a7c7c;\n  -webkit-app-region: drag;\n}\n\n.bottom-titlebar {\n  position: absolute;\n  left: 0px;\n  bottom: 0px;\n  width: 100%;\n  height: 32px;\n  background-color: #7a7c7c;\n  -webkit-app-region: drag;\n}\n\n.left-titlebar {\n  position: absolute;\n  left: 0px;\n  top: 0px;\n  width: 32px;\n  height: 100%;\n  background-color: #7a7c7c;\n  -webkit-app-region: drag;\n}\n\n.right-titlebar {\n  position: absolute;\n  right: 0px;\n  top: 0px;\n  width: 32px;\n  height: 100%;\n  background-color: #7a7c7c;\n  -webkit-app-region: drag;\n}\n\n.top-titlebar-icon,\n.bottom-titlebar-icon {\n  position: absolute;\n  left: 6px;\n  margin-top: 6px;\n  margin-bottom: 6px;\n}\n\n.left-titlebar-icon {\n  position: absolute;\n  bottom: 6px;\n  margin-left: 6px;\n  margin-right: 6px;\n}\n\n.right-titlebar-icon {\n  position: absolute;\n  top: 6px;\n  margin-left: 6px;\n  margin-right: 6px;\n}\n\n.top-titlebar-text,\n.bottom-titlebar-text {\n  position: absolute;\n  left: 32px;\n  width: 80%;\n  margin-top: 6px;\n  margin-bottom: 6px;\n  font-style: Arial;\n  font-size: 11pt;\n  color: #ffffff;\n}\n\n.left-titlebar-text {\n  position: absolute;\n  bottom: 32px;\n  width: 100px;\n  margin-left: 6px;\n  margin-right: 6px;\n  font-style: Arial;\n  font-size: 12pt;\n  color: #ffffff;\n  -webkit-transform: rotate(-90deg) translate(0, 100%);\n  -webkit-transform-origin: 0% 100%;\n}\n\n.right-titlebar-text {\n  position: absolute;\n  top: 0px;\n  width: 100px;\n  margin-left: 6px;\n  margin-right: 6px;\n  font-style: Arial;\n  font-size: 12pt;\n  color: #ffffff;\n  -webkit-transform: rotate(90deg) translate(0, 100%);\n  -webkit-transform-origin: 0% 200%;\n}\n\n.top-titlebar-close-button,\n.bottom-titlebar-close-button {\n  position: absolute;\n  right: 11px;\n  width: 17px;\n  height: 17px;\n  margin-top: 6px;\n  margin-bottom: 6px;\n  -webkit-app-region: no-drag;\n}\n\n.left-titlebar-close-button {\n  position: absolute;\n  top: 11px;\n  width: 17px;\n  height: 17px;\n  margin-left: 6px;\n  margin-right: 6px;\n  -webkit-app-region: no-drag;\n}\n\n.right-titlebar-close-button {\n  position: absolute;\n  bottom: 11px;\n  width: 17px;\n  height: 17px;\n  margin-left: 6px;\n  margin-right: 6px;\n  -webkit-app-region: no-drag;\n}\n\n.top-titlebar-divider {\n  position: absolute;\n  left: 0px;\n  top: 31px;\n  width: 100%;\n  height: 1px;\n  background-color: #2a2c2c;\n}\n\n.bottom-titlebar-divider {\n  position: absolute;\n  left: 0px;\n  bottom: 31px;\n  width: 100%;\n  height: 1px;\n  background-color: #2a2c2c;\n}\n\n.left-titlebar-divider {\n  position: absolute;\n  left: 31px;\n  top: 0px;\n  width: 1px;\n  height: 100%;\n  background-color: #2a2c2c;\n}\n\n.right-titlebar-divider {\n  position: absolute;\n  right: 31px;\n  top: 0px;\n  width: 1px;\n  height: 100%;\n  background-color: #2a2c2c;\n}\n"
  },
  {
    "path": "_archive/apps/samples/frameless-window/titlebar.js",
    "content": "function closeWindow() {\n  window.close();\n}\n\nfunction updateImageUrl(image_id, new_image_url) {\n  var image = document.getElementById(image_id);\n  if (image)\n    image.src = new_image_url;\n}\n\nfunction createImage(image_id, image_url) {\n  var image = document.createElement(\"img\");\n  image.setAttribute(\"id\", image_id);\n  image.src = image_url;\n  return image;\n}\n\nfunction createButton(button_id, button_name, normal_image_url,\n                       hover_image_url, click_func) {\n  var button = document.createElement(\"div\");\n  button.setAttribute(\"class\", button_name);\n  var button_img = createImage(button_id, normal_image_url);\n  button.appendChild(button_img);\n  button.onmouseover = function() {\n    updateImageUrl(button_id, hover_image_url);\n  }\n  button.onmouseout = function() {\n    updateImageUrl(button_id, normal_image_url);\n  }\n  button.onclick = click_func;\n  return button;\n}\n\nfunction focusTitlebars(focus) {\n  var bg_color = focus ? \"#3a3d3d\" : \"#7a7c7c\";\n    \n  var titlebar = document.getElementById(\"top-titlebar\");\n  if (titlebar)\n    titlebar.style.backgroundColor = bg_color;\n  titlebar = document.getElementById(\"bottom-titlebar\");\n  if (titlebar)\n    titlebar.style.backgroundColor = bg_color;\n  titlebar = document.getElementById(\"left-titlebar\");\n  if (titlebar)\n    titlebar.style.backgroundColor = bg_color;\n  titlebar = document.getElementById(\"right-titlebar\");\n  if (titlebar)\n    titlebar.style.backgroundColor = bg_color;\n}\n\nfunction addTitlebar(titlebar_name, titlebar_icon_url, titlebar_text) {\n  var titlebar = document.createElement(\"div\");\n  titlebar.setAttribute(\"id\", titlebar_name);\n  titlebar.setAttribute(\"class\", titlebar_name);\n\n  var icon = document.createElement(\"div\");\n  icon.setAttribute(\"class\", titlebar_name + \"-icon\");\n  icon.appendChild(createImage(titlebar_name + \"icon\", titlebar_icon_url));\n  titlebar.appendChild(icon);\n\n  var title = document.createElement(\"div\");\n  title.setAttribute(\"class\", titlebar_name + \"-text\");\n  title.innerText = titlebar_text;\n  titlebar.appendChild(title);\n\n  var closeButton = createButton(titlebar_name + \"-close-button\",\n                                 titlebar_name + \"-close-button\",\n                                 \"button_close.png\",\n                                 \"button_close_hover.png\",\n                                 closeWindow);\n  titlebar.appendChild(closeButton);\n\n  var divider = document.createElement(\"div\");\n  divider.setAttribute(\"class\", titlebar_name + \"-divider\");\n  titlebar.appendChild(divider);\n  \n  document.body.appendChild(titlebar);\n}\n\nfunction removeTitlebar(titlebar_name) {\n  var titlebar = document.getElementById(titlebar_name);\n  if (titlebar)\n    document.body.removeChild(titlebar);\n}\n\nfunction updateContentStyle() {\n  var content = document.getElementById(\"content\");\n  if (!content)\n    return;\n\n  var left = 0;\n  var top = 0;\n  var width = window.outerWidth;\n  var height = window.outerHeight;\n\n  var titlebar = document.getElementById(\"top-titlebar\");\n  if (titlebar) {\n    height -= titlebar.offsetHeight;\n    top += titlebar.offsetHeight;\n  }\n  titlebar = document.getElementById(\"bottom-titlebar\");\n  if (titlebar) {\n    height -= titlebar.offsetHeight;\n  }\n  titlebar = document.getElementById(\"left-titlebar\");\n  if (titlebar) {\n    width -= titlebar.offsetWidth;\n    left += titlebar.offsetWidth;\n  }\n  titlebar = document.getElementById(\"right-titlebar\");\n  if (titlebar) {\n    width -= titlebar.offsetWidth;\n  }\n\n  var contentStyle = \"position: absolute; \";\n  contentStyle += \"left: \" + left + \"px; \";\n  contentStyle += \"top: \" + top + \"px; \";\n  contentStyle += \"width: \" + width + \"px; \";\n  contentStyle += \"height: \" + height + \"px; \";\n  content.setAttribute(\"style\", contentStyle);\n}\n"
  },
  {
    "path": "_archive/apps/samples/gcm-notifications/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/gpededflkpcoehfjpdecdkoiagajloin\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# GCM Notifications Sample\n\nDemonstrates the capability to receive the push messages from Google Cloud Messaging (GCM) and show notifications.\n\n## APIs\n\n* [gcm](https://developer.chrome.com/apps/gcm)\n* [storage](https://developer.chrome.com/apps/storage)\n* [notifications](https://developer.chrome.com/apps/notifications)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/gcm-notifications/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/gcm-notifications/background.js",
    "content": "// Returns a new notification ID used in the notification.\r\nfunction getNotificationId() {\r\n  var id = Math.floor(Math.random() * 9007199254740992) + 1;\r\n  return id.toString();\r\n}\r\n\r\nfunction messageReceived(message) {\r\n  // A message is an object with a data property that\r\n  // consists of key-value pairs.\r\n\r\n  // Concatenate all key-value pairs to form a display string.\r\n  var messageString = \"\";\r\n  for (var key in message.data) {\r\n    if (messageString != \"\")\r\n      messageString += \", \"\r\n    messageString += key + \":\" + message.data[key];\r\n  }\r\n  console.log(\"Message received: \" + messageString);\r\n\r\n  // Pop up a notification to show the GCM message.\r\n  chrome.notifications.create(getNotificationId(), {\r\n    title: 'GCM Message',\r\n    iconUrl: 'gcm_128.png',\r\n    type: 'basic',\r\n    message: messageString\r\n  }, function() {});\r\n}\r\n\r\nvar registerWindowCreated = false;\r\n\r\nfunction firstTimeRegistration() {\r\n  chrome.storage.local.get(\"registered\", function(result) {\r\n    // If already registered, bail out.\r\n    if (result[\"registered\"])\r\n      return;\r\n\r\n    registerWindowCreated = true;\r\n    chrome.app.window.create(\r\n      \"register.html\",\r\n      {  width: 500,\r\n         height: 400,\r\n         frame: 'chrome'\r\n      },\r\n      function(appWin) {}\r\n    );\r\n  });\r\n}\r\n\r\n// Set up a listener for GCM message event.\r\nchrome.gcm.onMessage.addListener(messageReceived);\r\n\r\n// Set up listeners to trigger the first time registration.\r\nchrome.runtime.onInstalled.addListener(firstTimeRegistration);\r\nchrome.runtime.onStartup.addListener(firstTimeRegistration);\r\n"
  },
  {
    "path": "_archive/apps/samples/gcm-notifications/manifest.json",
    "content": "{\r\n  \"name\": \"GCM Notifications\",\r\n  \"description\": \"Chrome platform app.\",\r\n  \"manifest_version\": 2,\r\n  \"version\": \"0.1\",\r\n  \"app\": {\r\n    \"background\": {\r\n      \"scripts\": [\"background.js\"]\r\n    }\r\n  },\r\n  \"permissions\": [\"gcm\", \"storage\", \"notifications\"],\r\n  \"icons\": { \"128\": \"gcm_128.png\" }\r\n}\r\n"
  },
  {
    "path": "_archive/apps/samples/gcm-notifications/register.html",
    "content": "<html>\r\n\r\n<head>\r\n<title>GCM Registration</title>\r\n<script src=\"register.js\"></script>\r\n</head>\r\n\r\n<body>\r\n\r\nSender ID:<input id=\"senderId\" type=\"TEXT\" size=\"20\"><br/>\r\n<button id=\"register\">Register</button>\r\n<br/><br/>\r\n\r\n<div id=\"status\" style=\"background-color:#e5e5e5;padding:5px\">\r\n</div>\r\n<br/>\r\n\r\nAPI Key:<input id=\"apiKey\" type=\"TEXT\" size=\"30\"><br/>\r\nMessage: Key<input id=\"msgKey\" type=\"TEXT\" size=\"20\"> &nbsp; Value<input id=\"msgValue\" type=\"TEXT\" size=\"20\">\r\n\r\n<textarea id=\"console\" type=\"TEXT\" readonly style=\"width:460px;height:210px;\"></textarea>\r\n\r\n</body>\r\n\r\n</html>\r\n"
  },
  {
    "path": "_archive/apps/samples/gcm-notifications/register.js",
    "content": "var registrationId = \"\";\r\n\r\nfunction setStatus(status) {\r\n  document.getElementById(\"status\").innerHTML = status;\r\n}\r\n\r\nfunction register() {\r\n  var senderId = document.getElementById(\"senderId\").value;\r\n  chrome.gcm.register([senderId], registerCallback);\r\n\r\n  setStatus(\"Registering ...\");\r\n\r\n  // Prevent register button from being click again before the registration\r\n  // finishes.\r\n  document.getElementById(\"register\").disabled = true;\r\n}\r\n\r\nfunction registerCallback(regId) {\r\n  registrationId = regId;\r\n  document.getElementById(\"register\").disabled = false;\r\n\r\n  if (chrome.runtime.lastError) {\r\n    // When the registration fails, handle the error and retry the\r\n    // registration later.\r\n    setStatus(\"Registration failed: \" + chrome.runtime.lastError.message);\r\n    return;\r\n  }\r\n\r\n  setStatus(\"Registration succeeded. Please run the following command to send a message.\");\r\n\r\n  // Mark that the first-time registration is done.\r\n  chrome.storage.local.set({registered: true});\r\n\r\n  // Format and show the curl command that can be used to post a message.\r\n  updateCurlCommand();\r\n}\r\n\r\nfunction updateCurlCommand() {\r\n  var apiKey = document.getElementById(\"apiKey\").value;\r\n  if (!apiKey)\r\n    apiKey = \"YOUR_API_KEY\";\r\n\r\n  var msgKey = document.getElementById(\"msgKey\").value;\r\n  if (!msgKey)\r\n    msgKey = \"YOUR_MESSAGE_KEY\";\r\n\r\n  var msgValue = document.getElementById(\"msgValue\").value;\r\n  if (!msgValue)\r\n    msgValue = \"YOUR_MESSAGE_VALUE\";\r\n\r\n  var command = 'curl' +\r\n      ' -H \"Content-Type:application/x-www-form-urlencoded;charset=UTF-8\"' +\r\n      ' -H \"Authorization: key=' + apiKey + '\"' +\r\n      ' -d \"registration_id=' + registrationId + '\"' +\r\n      ' -d data.' + msgKey + '=' + msgValue +\r\n      ' https://android.googleapis.com/gcm/send';\r\n  document.getElementById(\"console\").innerText = command;\r\n}\r\n\r\nwindow.onload = function() {\r\n  document.getElementById(\"register\").onclick = register;\r\n  document.getElementById(\"apiKey\").onchange = updateCurlCommand;\r\n  document.getElementById(\"msgKey\").onchange = updateCurlCommand;\r\n  document.getElementById(\"msgValue\").onchange = updateCurlCommand;\r\n  setStatus(\"You have not registered yet. Please provider sender ID and register.\");\r\n}\r\n"
  },
  {
    "path": "_archive/apps/samples/gdrive/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/jpabeekbjicamajjcfejnochhmlbpgjh\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Google Drive Uploader\n\nUses the `chrome.identity.getAuthToken()` API to perform OAuth2 and\naccess the Google Drive API.\n\nTo upload files: drag in files from the desktop onto the app.\n\n## APIs\n\n* [Identity](http://developer.chrome.com/apps/identity.html)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/gdrive/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/gdrive/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.0.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n.clearfix {\n  *zoom: 1;\n}\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  content: \"\";\n}\n.clearfix:after {\n  clear: both;\n}\n.hide-text {\n  overflow: hidden;\n  text-indent: 100%;\n  white-space: nowrap;\n}\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 28px;\n  /* Make inputs at least the height of their button counterpart */\n\n  /* Makes inputs behave like true block-level elements */\n\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  -ms-box-sizing: border-box;\n  box-sizing: border-box;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\naudio:not([controls]) {\n  display: none;\n}\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n  -ms-text-size-adjust: 100%;\n}\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\na:hover,\na:active {\n  outline: 0;\n}\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\nsup {\n  top: -0.5em;\n}\nsub {\n  bottom: -0.25em;\n}\nimg {\n  height: auto;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n  vertical-align: middle;\n}\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\ninput[type=\"search\"] {\n  -webkit-appearance: textfield;\n  -webkit-box-sizing: content-box;\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  line-height: 18px;\n  color: #333333;\n  background-color: #ffffff;\n}\na {\n  color: #0088cc;\n  text-decoration: none;\n}\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n.row:before,\n.row:after {\n  display: table;\n  content: \"\";\n}\n.row:after {\n  clear: both;\n}\n[class*=\"span\"] {\n  float: left;\n  margin-left: 20px;\n}\n.container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n.span12 {\n  width: 940px;\n}\n.span11 {\n  width: 860px;\n}\n.span10 {\n  width: 780px;\n}\n.span9 {\n  width: 700px;\n}\n.span8 {\n  width: 620px;\n}\n.span7 {\n  width: 540px;\n}\n.span6 {\n  width: 460px;\n}\n.span5 {\n  width: 380px;\n}\n.span4 {\n  width: 300px;\n}\n.span3 {\n  width: 220px;\n}\n.span2 {\n  width: 140px;\n}\n.span1 {\n  width: 60px;\n}\n.offset12 {\n  margin-left: 980px;\n}\n.offset11 {\n  margin-left: 900px;\n}\n.offset10 {\n  margin-left: 820px;\n}\n.offset9 {\n  margin-left: 740px;\n}\n.offset8 {\n  margin-left: 660px;\n}\n.offset7 {\n  margin-left: 580px;\n}\n.offset6 {\n  margin-left: 500px;\n}\n.offset5 {\n  margin-left: 420px;\n}\n.offset4 {\n  margin-left: 340px;\n}\n.offset3 {\n  margin-left: 260px;\n}\n.offset2 {\n  margin-left: 180px;\n}\n.offset1 {\n  margin-left: 100px;\n}\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  content: \"\";\n}\n.row-fluid:after {\n  clear: both;\n}\n.row-fluid > [class*=\"span\"] {\n  float: left;\n  margin-left: 2.127659574%;\n}\n.row-fluid > [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n.row-fluid > .span12 {\n  width: 99.99999998999999%;\n}\n.row-fluid > .span11 {\n  width: 91.489361693%;\n}\n.row-fluid > .span10 {\n  width: 82.97872339599999%;\n}\n.row-fluid > .span9 {\n  width: 74.468085099%;\n}\n.row-fluid > .span8 {\n  width: 65.95744680199999%;\n}\n.row-fluid > .span7 {\n  width: 57.446808505%;\n}\n.row-fluid > .span6 {\n  width: 48.93617020799999%;\n}\n.row-fluid > .span5 {\n  width: 40.425531911%;\n}\n.row-fluid > .span4 {\n  width: 31.914893614%;\n}\n.row-fluid > .span3 {\n  width: 23.404255317%;\n}\n.row-fluid > .span2 {\n  width: 14.89361702%;\n}\n.row-fluid > .span1 {\n  width: 6.382978723%;\n}\n.container {\n  margin-left: auto;\n  margin-right: auto;\n  *zoom: 1;\n}\n.container:before,\n.container:after {\n  display: table;\n  content: \"\";\n}\n.container:after {\n  clear: both;\n}\n.container-fluid {\n  padding-left: 20px;\n  padding-right: 20px;\n  *zoom: 1;\n}\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  content: \"\";\n}\n.container-fluid:after {\n  clear: both;\n}\np {\n  margin: 0 0 9px;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  line-height: 18px;\n}\np small {\n  font-size: 11px;\n  color: #999999;\n}\n.lead {\n  margin-bottom: 18px;\n  font-size: 20px;\n  font-weight: 200;\n  line-height: 27px;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 0;\n  font-family: inherit;\n  font-weight: bold;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  color: #999999;\n}\nh1 {\n  font-size: 30px;\n  line-height: 36px;\n}\nh1 small {\n  font-size: 18px;\n}\nh2 {\n  font-size: 24px;\n  line-height: 36px;\n}\nh2 small {\n  font-size: 18px;\n}\nh3 {\n  line-height: 27px;\n  font-size: 18px;\n}\nh3 small {\n  font-size: 14px;\n}\nh4,\nh5,\nh6 {\n  line-height: 18px;\n}\nh4 {\n  font-size: 14px;\n}\nh4 small {\n  font-size: 12px;\n}\nh5 {\n  font-size: 12px;\n}\nh6 {\n  font-size: 11px;\n  color: #999999;\n  text-transform: uppercase;\n}\n.page-header {\n  padding-bottom: 17px;\n  margin: 18px 0;\n  border-bottom: 1px solid #eeeeee;\n}\n.page-header h1 {\n  line-height: 1;\n}\nul,\nol {\n  padding: 0;\n  margin: 0 0 9px 25px;\n}\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\nul {\n  list-style: disc;\n}\nol {\n  list-style: decimal;\n}\nli {\n  line-height: 18px;\n}\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\ndl {\n  margin-bottom: 18px;\n}\ndt,\ndd {\n  line-height: 18px;\n}\ndt {\n  font-weight: bold;\n  line-height: 17px;\n}\ndd {\n  margin-left: 9px;\n}\n.dl-horizontal dt {\n  float: left;\n  clear: left;\n  width: 120px;\n  text-align: right;\n}\n.dl-horizontal dd {\n  margin-left: 130px;\n}\nhr {\n  margin: 18px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\nstrong {\n  font-weight: bold;\n}\nem {\n  font-style: italic;\n}\n.muted {\n  color: #999999;\n}\nabbr[title] {\n  border-bottom: 1px dotted #ddd;\n  cursor: help;\n}\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 18px;\n  border-left: 5px solid #eeeeee;\n}\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 22.5px;\n}\nblockquote small {\n  display: block;\n  line-height: 18px;\n  color: #999999;\n}\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\nblockquote.pull-right {\n  float: right;\n  padding-left: 0;\n  padding-right: 15px;\n  border-left: 0;\n  border-right: 5px solid #eeeeee;\n}\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\naddress {\n  display: block;\n  margin-bottom: 18px;\n  line-height: 18px;\n  font-style: normal;\n}\nsmall {\n  font-size: 100%;\n}\ncite {\n  font-style: normal;\n}\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Menlo, Monaco, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n}\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\npre {\n  display: block;\n  padding: 8.5px;\n  margin: 0 0 9px;\n  font-size: 12.025px;\n  line-height: 18px;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n  white-space: pre;\n  white-space: pre-wrap;\n  word-break: break-all;\n  word-wrap: break-word;\n}\npre.prettyprint {\n  margin-bottom: 18px;\n}\npre code {\n  padding: 0;\n  color: inherit;\n  background-color: transparent;\n  border: 0;\n}\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n.label {\n  padding: 1px 4px 2px;\n  font-size: 10.998px;\n  font-weight: bold;\n  line-height: 13px;\n  color: #ffffff;\n  vertical-align: middle;\n  white-space: nowrap;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #999999;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n}\n.label:hover {\n  color: #ffffff;\n  text-decoration: none;\n}\n.label-important {\n  background-color: #b94a48;\n}\n.label-important:hover {\n  background-color: #953b39;\n}\n.label-warning {\n  background-color: #f89406;\n}\n.label-warning:hover {\n  background-color: #c67605;\n}\n.label-success {\n  background-color: #468847;\n}\n.label-success:hover {\n  background-color: #356635;\n}\n.label-info {\n  background-color: #3a87ad;\n}\n.label-info:hover {\n  background-color: #2d6987;\n}\n.label-inverse {\n  background-color: #333333;\n}\n.label-inverse:hover {\n  background-color: #1a1a1a;\n}\n.badge {\n  padding: 1px 9px 2px;\n  font-size: 12.025px;\n  font-weight: bold;\n  white-space: nowrap;\n  color: #ffffff;\n  background-color: #999999;\n  -webkit-border-radius: 9px;\n  -moz-border-radius: 9px;\n  border-radius: 9px;\n}\n.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n.badge-error {\n  background-color: #b94a48;\n}\n.badge-error:hover {\n  background-color: #953b39;\n}\n.badge-warning {\n  background-color: #f89406;\n}\n.badge-warning:hover {\n  background-color: #c67605;\n}\n.badge-success {\n  background-color: #468847;\n}\n.badge-success:hover {\n  background-color: #356635;\n}\n.badge-info {\n  background-color: #3a87ad;\n}\n.badge-info:hover {\n  background-color: #2d6987;\n}\n.badge-inverse {\n  background-color: #333333;\n}\n.badge-inverse:hover {\n  background-color: #1a1a1a;\n}\ntable {\n  max-width: 100%;\n  border-collapse: collapse;\n  border-spacing: 0;\n  background-color: transparent;\n}\n.table {\n  width: 100%;\n  margin-bottom: 18px;\n}\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 18px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n.table th {\n  font-weight: bold;\n}\n.table thead th {\n  vertical-align: bottom;\n}\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-left: 0;\n  border-collapse: separate;\n  *border-collapse: collapsed;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n.table-bordered thead:first-child tr:first-child th:first-child,\n.table-bordered tbody:first-child tr:first-child td:first-child {\n  -webkit-border-radius: 4px 0 0 0;\n  -moz-border-radius: 4px 0 0 0;\n  border-radius: 4px 0 0 0;\n}\n.table-bordered thead:first-child tr:first-child th:last-child,\n.table-bordered tbody:first-child tr:first-child td:last-child {\n  -webkit-border-radius: 0 4px 0 0;\n  -moz-border-radius: 0 4px 0 0;\n  border-radius: 0 4px 0 0;\n}\n.table-bordered thead:last-child tr:last-child th:first-child,\n.table-bordered tbody:last-child tr:last-child td:first-child {\n  -webkit-border-radius: 0 0 0 4px;\n  -moz-border-radius: 0 0 0 4px;\n  border-radius: 0 0 0 4px;\n}\n.table-bordered thead:last-child tr:last-child th:last-child,\n.table-bordered tbody:last-child tr:last-child td:last-child {\n  -webkit-border-radius: 0 0 4px 0;\n  -moz-border-radius: 0 0 4px 0;\n  border-radius: 0 0 4px 0;\n}\n.table-striped tbody tr:nth-child(odd) td,\n.table-striped tbody tr:nth-child(odd) th {\n  background-color: #f9f9f9;\n}\n.table tbody tr:hover td,\n.table tbody tr:hover th {\n  background-color: #f5f5f5;\n}\ntable .span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\ntable .span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\ntable .span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\ntable .span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\ntable .span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\ntable .span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\ntable .span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\ntable .span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\ntable .span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\ntable .span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\ntable .span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\ntable .span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\ntable .span13 {\n  float: none;\n  width: 1004px;\n  margin-left: 0;\n}\ntable .span14 {\n  float: none;\n  width: 1084px;\n  margin-left: 0;\n}\ntable .span15 {\n  float: none;\n  width: 1164px;\n  margin-left: 0;\n}\ntable .span16 {\n  float: none;\n  width: 1244px;\n  margin-left: 0;\n}\ntable .span17 {\n  float: none;\n  width: 1324px;\n  margin-left: 0;\n}\ntable .span18 {\n  float: none;\n  width: 1404px;\n  margin-left: 0;\n}\ntable .span19 {\n  float: none;\n  width: 1484px;\n  margin-left: 0;\n}\ntable .span20 {\n  float: none;\n  width: 1564px;\n  margin-left: 0;\n}\ntable .span21 {\n  float: none;\n  width: 1644px;\n  margin-left: 0;\n}\ntable .span22 {\n  float: none;\n  width: 1724px;\n  margin-left: 0;\n}\ntable .span23 {\n  float: none;\n  width: 1804px;\n  margin-left: 0;\n}\ntable .span24 {\n  float: none;\n  width: 1884px;\n  margin-left: 0;\n}\nform {\n  margin: 0 0 18px;\n}\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 27px;\n  font-size: 19.5px;\n  line-height: 36px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #eee;\n}\nlegend small {\n  font-size: 13.5px;\n  color: #999999;\n}\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 18px;\n}\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\nlabel {\n  display: block;\n  margin-bottom: 5px;\n  color: #333333;\n}\ninput,\ntextarea,\nselect,\n.uneditable-input {\n  display: inline-block;\n  width: 210px;\n  height: 18px;\n  padding: 4px;\n  margin-bottom: 9px;\n  font-size: 13px;\n  line-height: 18px;\n  color: #555555;\n  border: 1px solid #cccccc;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n}\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\nlabel input,\nlabel textarea,\nlabel select {\n  display: block;\n}\ninput[type=\"image\"],\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  width: auto;\n  height: auto;\n  padding: 0;\n  margin: 3px 0;\n  *margin-top: 0;\n  /* IE7 */\n\n  line-height: normal;\n  cursor: pointer;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n  border: 0 \\9;\n  /* IE9 and down */\n\n}\ninput[type=\"image\"] {\n  border: 0;\n}\ninput[type=\"file\"] {\n  width: auto;\n  padding: initial;\n  line-height: initial;\n  border: initial;\n  background-color: #ffffff;\n  background-color: initial;\n  -webkit-box-shadow: none;\n  -moz-box-shadow: none;\n  box-shadow: none;\n}\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  width: auto;\n  height: auto;\n}\nselect,\ninput[type=\"file\"] {\n  height: 28px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 28px;\n}\ninput[type=\"file\"] {\n  line-height: 18px \\9;\n}\nselect {\n  width: 220px;\n  background-color: #ffffff;\n}\nselect[multiple],\nselect[size] {\n  height: auto;\n}\ninput[type=\"image\"] {\n  -webkit-box-shadow: none;\n  -moz-box-shadow: none;\n  box-shadow: none;\n}\ntextarea {\n  height: auto;\n}\ninput[type=\"hidden\"] {\n  display: none;\n}\n.radio,\n.checkbox {\n  padding-left: 18px;\n}\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -18px;\n}\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\ninput,\ntextarea {\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;\n  -moz-transition: border linear 0.2s, box-shadow linear 0.2s;\n  -ms-transition: border linear 0.2s, box-shadow linear 0.2s;\n  -o-transition: border linear 0.2s, box-shadow linear 0.2s;\n  transition: border linear 0.2s, box-shadow linear 0.2s;\n}\ninput:focus,\ntextarea:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus,\nselect:focus {\n  -webkit-box-shadow: none;\n  -moz-box-shadow: none;\n  box-shadow: none;\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.input-mini {\n  width: 60px;\n}\n.input-small {\n  width: 90px;\n}\n.input-medium {\n  width: 150px;\n}\n.input-large {\n  width: 210px;\n}\n.input-xlarge {\n  width: 270px;\n}\n.input-xxlarge {\n  width: 530px;\n}\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input {\n  float: none;\n  margin-left: 0;\n}\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\ninput.span12, textarea.span12, .uneditable-input.span12 {\n  width: 930px;\n}\ninput.span11, textarea.span11, .uneditable-input.span11 {\n  width: 850px;\n}\ninput.span10, textarea.span10, .uneditable-input.span10 {\n  width: 770px;\n}\ninput.span9, textarea.span9, .uneditable-input.span9 {\n  width: 690px;\n}\ninput.span8, textarea.span8, .uneditable-input.span8 {\n  width: 610px;\n}\ninput.span7, textarea.span7, .uneditable-input.span7 {\n  width: 530px;\n}\ninput.span6, textarea.span6, .uneditable-input.span6 {\n  width: 450px;\n}\ninput.span5, textarea.span5, .uneditable-input.span5 {\n  width: 370px;\n}\ninput.span4, textarea.span4, .uneditable-input.span4 {\n  width: 290px;\n}\ninput.span3, textarea.span3, .uneditable-input.span3 {\n  width: 210px;\n}\ninput.span2, textarea.span2, .uneditable-input.span2 {\n  width: 130px;\n}\ninput.span1, textarea.span1, .uneditable-input.span1 {\n  width: 50px;\n}\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  background-color: #eeeeee;\n  border-color: #ddd;\n  cursor: not-allowed;\n}\n.control-group.warning > label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n  border-color: #c09853;\n}\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: 0 0 6px #dbc59e;\n  -moz-box-shadow: 0 0 6px #dbc59e;\n  box-shadow: 0 0 6px #dbc59e;\n}\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n.control-group.error > label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n  border-color: #b94a48;\n}\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: 0 0 6px #d59392;\n  -moz-box-shadow: 0 0 6px #d59392;\n  box-shadow: 0 0 6px #d59392;\n}\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n.control-group.success > label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n  border-color: #468847;\n}\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: 0 0 6px #7aba7b;\n  -moz-box-shadow: 0 0 6px #7aba7b;\n  box-shadow: 0 0 6px #7aba7b;\n}\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\ninput:focus:required:invalid,\ntextarea:focus:required:invalid,\nselect:focus:required:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\ninput:focus:required:invalid:focus,\ntextarea:focus:required:invalid:focus,\nselect:focus:required:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n  -moz-box-shadow: 0 0 6px #f8b9b7;\n  box-shadow: 0 0 6px #f8b9b7;\n}\n.form-actions {\n  padding: 17px 20px 18px;\n  margin-top: 18px;\n  margin-bottom: 18px;\n  background-color: #eeeeee;\n  border-top: 1px solid #ddd;\n  *zoom: 1;\n}\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  content: \"\";\n}\n.form-actions:after {\n  clear: both;\n}\n.uneditable-input {\n  display: block;\n  background-color: #ffffff;\n  border-color: #eee;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n  cursor: not-allowed;\n}\n:-moz-placeholder {\n  color: #999999;\n}\n::-webkit-input-placeholder {\n  color: #999999;\n}\n.help-block,\n.help-inline {\n  color: #555555;\n}\n.help-block {\n  display: block;\n  margin-bottom: 9px;\n}\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n  vertical-align: middle;\n  padding-left: 5px;\n}\n.input-prepend,\n.input-append {\n  margin-bottom: 5px;\n}\n.input-prepend input,\n.input-append input,\n.input-prepend select,\n.input-append select,\n.input-prepend .uneditable-input,\n.input-append .uneditable-input {\n  *margin-left: 0;\n  -webkit-border-radius: 0 3px 3px 0;\n  -moz-border-radius: 0 3px 3px 0;\n  border-radius: 0 3px 3px 0;\n}\n.input-prepend input:focus,\n.input-append input:focus,\n.input-prepend select:focus,\n.input-append select:focus,\n.input-prepend .uneditable-input:focus,\n.input-append .uneditable-input:focus {\n  position: relative;\n  z-index: 2;\n}\n.input-prepend .uneditable-input,\n.input-append .uneditable-input {\n  border-left-color: #ccc;\n}\n.input-prepend .add-on,\n.input-append .add-on {\n  display: inline-block;\n  width: auto;\n  min-width: 16px;\n  height: 18px;\n  padding: 4px 5px;\n  font-weight: normal;\n  line-height: 18px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  vertical-align: middle;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n.input-prepend .add-on,\n.input-append .add-on,\n.input-prepend .btn,\n.input-append .btn {\n  -webkit-border-radius: 3px 0 0 3px;\n  -moz-border-radius: 3px 0 0 3px;\n  border-radius: 3px 0 0 3px;\n}\n.input-prepend .active,\n.input-append .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n.input-append input,\n.input-append select .uneditable-input {\n  -webkit-border-radius: 3px 0 0 3px;\n  -moz-border-radius: 3px 0 0 3px;\n  border-radius: 3px 0 0 3px;\n}\n.input-append .uneditable-input {\n  border-left-color: #eee;\n  border-right-color: #ccc;\n}\n.input-append .add-on,\n.input-append .btn {\n  margin-left: -1px;\n  -webkit-border-radius: 0 3px 3px 0;\n  -moz-border-radius: 0 3px 3px 0;\n  border-radius: 0 3px 3px 0;\n}\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 3px 0 0 3px;\n  -moz-border-radius: 3px 0 0 3px;\n  border-radius: 3px 0 0 3px;\n}\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 3px 3px 0;\n  -moz-border-radius: 0 3px 3px 0;\n  border-radius: 0 3px 3px 0;\n}\n.search-query {\n  padding-left: 14px;\n  padding-right: 14px;\n  margin-bottom: 0;\n  -webkit-border-radius: 14px;\n  -moz-border-radius: 14px;\n  border-radius: 14px;\n}\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  margin-bottom: 0;\n}\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n.form-search label,\n.form-inline label {\n  display: inline-block;\n}\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: 0;\n  margin-right: 3px;\n}\n.control-group {\n  margin-bottom: 9px;\n}\nlegend + .control-group {\n  margin-top: 18px;\n  -webkit-margin-top-collapse: separate;\n}\n.form-horizontal .control-group {\n  margin-bottom: 18px;\n  *zoom: 1;\n}\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  content: \"\";\n}\n.form-horizontal .control-group:after {\n  clear: both;\n}\n.form-horizontal .control-label {\n  float: left;\n  width: 140px;\n  padding-top: 5px;\n  text-align: right;\n}\n.form-horizontal .controls {\n  margin-left: 160px;\n  /* Super jank IE7 fix to ensure the inputs in .input-append and input-prepend don't inherit the margin of the parent, in this case .controls */\n\n  *display: inline-block;\n  *margin-left: 0;\n  *padding-left: 20px;\n}\n.form-horizontal .help-block {\n  margin-top: 9px;\n  margin-bottom: 0;\n}\n.form-horizontal .form-actions {\n  padding-left: 160px;\n}\n.btn {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n  padding: 4px 10px 4px;\n  margin-bottom: 0;\n  font-size: 13px;\n  line-height: 18px;\n  color: #333333;\n  text-align: center;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  vertical-align: middle;\n  background-color: #f5f5f5;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -ms-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(top, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:dximagetransform.microsoft.gradient(enabled=false);\n  border: 1px solid #cccccc;\n  border-bottom-color: #b3b3b3;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n  -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n  cursor: pointer;\n  *margin-left: .3em;\n}\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  background-color: #e6e6e6;\n}\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n.btn:first-child {\n  *margin-left: 0;\n}\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: #e6e6e6;\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n  -moz-transition: background-position 0.1s linear;\n  -ms-transition: background-position 0.1s linear;\n  -o-transition: background-position 0.1s linear;\n  transition: background-position 0.1s linear;\n}\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.btn.active,\n.btn:active {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n  -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n  background-color: #e6e6e6;\n  background-color: #d9d9d9 \\9;\n  outline: 0;\n}\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-image: none;\n  background-color: #e6e6e6;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n  -moz-box-shadow: none;\n  box-shadow: none;\n}\n.btn-large {\n  padding: 9px 14px;\n  font-size: 15px;\n  line-height: normal;\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  border-radius: 5px;\n}\n.btn-large [class^=\"icon-\"] {\n  margin-top: 1px;\n}\n.btn-small {\n  padding: 5px 9px;\n  font-size: 11px;\n  line-height: 16px;\n}\n.btn-small [class^=\"icon-\"] {\n  margin-top: -1px;\n}\n.btn-mini {\n  padding: 2px 6px;\n  font-size: 11px;\n  line-height: 14px;\n}\n.btn-primary,\n.btn-primary:hover,\n.btn-warning,\n.btn-warning:hover,\n.btn-danger,\n.btn-danger:hover,\n.btn-success,\n.btn-success:hover,\n.btn-info,\n.btn-info:hover,\n.btn-inverse,\n.btn-inverse:hover {\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  color: #ffffff;\n}\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n.btn-primary {\n  background-color: #0074cc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0055cc);\n  background-image: -ms-linear-gradient(top, #0088cc, #0055cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0055cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0055cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0055cc);\n  background-image: linear-gradient(top, #0088cc, #0055cc);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0055cc', GradientType=0);\n  border-color: #0055cc #0055cc #003580;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:dximagetransform.microsoft.gradient(enabled=false);\n}\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  background-color: #0055cc;\n}\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #004099 \\9;\n}\n.btn-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -ms-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(top, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0);\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:dximagetransform.microsoft.gradient(enabled=false);\n}\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  background-color: #f89406;\n}\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n.btn-danger {\n  background-color: #da4f49;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -ms-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(top, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#bd362f', GradientType=0);\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:dximagetransform.microsoft.gradient(enabled=false);\n}\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  background-color: #bd362f;\n}\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n.btn-success {\n  background-color: #5bb75b;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -ms-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(top, #62c462, #51a351);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#51a351', GradientType=0);\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:dximagetransform.microsoft.gradient(enabled=false);\n}\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  background-color: #51a351;\n}\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n.btn-info {\n  background-color: #49afcd;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -ms-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(top, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#2f96b4', GradientType=0);\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:dximagetransform.microsoft.gradient(enabled=false);\n}\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  background-color: #2f96b4;\n}\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n.btn-inverse {\n  background-color: #414141;\n  background-image: -moz-linear-gradient(top, #555555, #222222);\n  background-image: -ms-linear-gradient(top, #555555, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#555555), to(#222222));\n  background-image: -webkit-linear-gradient(top, #555555, #222222);\n  background-image: -o-linear-gradient(top, #555555, #222222);\n  background-image: linear-gradient(top, #555555, #222222);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#555555', endColorstr='#222222', GradientType=0);\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:dximagetransform.microsoft.gradient(enabled=false);\n}\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  background-color: #222222;\n}\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 2px;\n  *padding-bottom: 2px;\n}\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n  *margin-right: .3em;\n}\n[class^=\"icon-\"]:last-child,\n[class*=\" icon-\"]:last-child {\n  *margin-left: 0;\n}\n.icon-white {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n.icon-glass {\n  background-position: 0      0;\n}\n.icon-music {\n  background-position: -24px 0;\n}\n.icon-search {\n  background-position: -48px 0;\n}\n.icon-envelope {\n  background-position: -72px 0;\n}\n.icon-heart {\n  background-position: -96px 0;\n}\n.icon-star {\n  background-position: -120px 0;\n}\n.icon-star-empty {\n  background-position: -144px 0;\n}\n.icon-user {\n  background-position: -168px 0;\n}\n.icon-film {\n  background-position: -192px 0;\n}\n.icon-th-large {\n  background-position: -216px 0;\n}\n.icon-th {\n  background-position: -240px 0;\n}\n.icon-th-list {\n  background-position: -264px 0;\n}\n.icon-ok {\n  background-position: -288px 0;\n}\n.icon-remove {\n  background-position: -312px 0;\n}\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n.icon-off {\n  background-position: -384px 0;\n}\n.icon-signal {\n  background-position: -408px 0;\n}\n.icon-cog {\n  background-position: -432px 0;\n}\n.icon-trash {\n  background-position: -456px 0;\n}\n.icon-home {\n  background-position: 0 -24px;\n}\n.icon-file {\n  background-position: -24px -24px;\n}\n.icon-time {\n  background-position: -48px -24px;\n}\n.icon-road {\n  background-position: -72px -24px;\n}\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n.icon-download {\n  background-position: -120px -24px;\n}\n.icon-upload {\n  background-position: -144px -24px;\n}\n.icon-inbox {\n  background-position: -168px -24px;\n}\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n.icon-repeat {\n  background-position: -216px -24px;\n}\n.icon-refresh {\n  background-position: -240px -24px;\n}\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n.icon-lock {\n  background-position: -287px -24px;\n}\n.icon-flag {\n  background-position: -312px -24px;\n}\n.icon-headphones {\n  background-position: -336px -24px;\n}\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n.icon-barcode {\n  background-position: -456px -24px;\n}\n.icon-tag {\n  background-position: 0 -48px;\n}\n.icon-tags {\n  background-position: -25px -48px;\n}\n.icon-book {\n  background-position: -48px -48px;\n}\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n.icon-print {\n  background-position: -96px -48px;\n}\n.icon-camera {\n  background-position: -120px -48px;\n}\n.icon-font {\n  background-position: -144px -48px;\n}\n.icon-bold {\n  background-position: -167px -48px;\n}\n.icon-italic {\n  background-position: -192px -48px;\n}\n.icon-text-height {\n  background-position: -216px -48px;\n}\n.icon-text-width {\n  background-position: -240px -48px;\n}\n.icon-align-left {\n  background-position: -264px -48px;\n}\n.icon-align-center {\n  background-position: -288px -48px;\n}\n.icon-align-right {\n  background-position: -312px -48px;\n}\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n.icon-list {\n  background-position: -360px -48px;\n}\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n.icon-picture {\n  background-position: -456px -48px;\n}\n.icon-pencil {\n  background-position: 0 -72px;\n}\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n.icon-adjust {\n  background-position: -48px -72px;\n}\n.icon-tint {\n  background-position: -72px -72px;\n}\n.icon-edit {\n  background-position: -96px -72px;\n}\n.icon-share {\n  background-position: -120px -72px;\n}\n.icon-check {\n  background-position: -144px -72px;\n}\n.icon-move {\n  background-position: -168px -72px;\n}\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n.icon-backward {\n  background-position: -240px -72px;\n}\n.icon-play {\n  background-position: -264px -72px;\n}\n.icon-pause {\n  background-position: -288px -72px;\n}\n.icon-stop {\n  background-position: -312px -72px;\n}\n.icon-forward {\n  background-position: -336px -72px;\n}\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n.icon-eject {\n  background-position: -408px -72px;\n}\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n.icon-plus {\n  background-position: -408px -96px;\n}\n.icon-minus {\n  background-position: -433px -96px;\n}\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n.icon-gift {\n  background-position: -24px -120px;\n}\n.icon-leaf {\n  background-position: -48px -120px;\n}\n.icon-fire {\n  background-position: -72px -120px;\n}\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n.icon-plane {\n  background-position: -168px -120px;\n}\n.icon-calendar {\n  background-position: -192px -120px;\n}\n.icon-random {\n  background-position: -216px -120px;\n}\n.icon-comment {\n  background-position: -240px -120px;\n}\n.icon-magnet {\n  background-position: -264px -120px;\n}\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n.icon-retweet {\n  background-position: -336px -120px;\n}\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n.icon-folder-open {\n  background-position: -408px -120px;\n}\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n.btn-group {\n  position: relative;\n  *zoom: 1;\n  *margin-left: .3em;\n}\n.btn-group:before,\n.btn-group:after {\n  display: table;\n  content: \"\";\n}\n.btn-group:after {\n  clear: both;\n}\n.btn-group:first-child {\n  *margin-left: 0;\n}\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n.btn-toolbar {\n  margin-top: 9px;\n  margin-bottom: 9px;\n}\n.btn-toolbar .btn-group {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n.btn-group .btn {\n  position: relative;\n  float: left;\n  margin-left: -1px;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.btn-group .btn:first-child {\n  margin-left: 0;\n  -webkit-border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n  border-top-left-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  border-bottom-left-radius: 4px;\n}\n.btn-group .btn:last-child,\n.btn-group .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  border-bottom-right-radius: 4px;\n}\n.btn-group .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-top-left-radius: 6px;\n  -moz-border-radius-topleft: 6px;\n  border-top-left-radius: 6px;\n  -webkit-border-bottom-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  border-bottom-left-radius: 6px;\n}\n.btn-group .btn.large:last-child,\n.btn-group .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n  -moz-border-radius-bottomright: 6px;\n  border-bottom-right-radius: 6px;\n}\n.btn-group .btn:hover,\n.btn-group .btn:focus,\n.btn-group .btn:active,\n.btn-group .btn.active {\n  z-index: 2;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n.btn-group .dropdown-toggle {\n  padding-left: 8px;\n  padding-right: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n  -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\n.btn-group .btn-mini.dropdown-toggle {\n  padding-left: 5px;\n  padding-right: 5px;\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n.btn-group .btn-small.dropdown-toggle {\n  *padding-top: 4px;\n  *padding-bottom: 4px;\n}\n.btn-group .btn-large.dropdown-toggle {\n  padding-left: 12px;\n  padding-right: 12px;\n}\n.btn-group.open {\n  *z-index: 1000;\n}\n.btn-group.open .dropdown-menu {\n  display: block;\n  margin-top: 1px;\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  border-radius: 5px;\n}\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n  -moz-box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 0 1px 6px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.btn .caret {\n  margin-top: 7px;\n  margin-left: 0;\n}\n.btn:hover .caret,\n.open.btn-group .caret {\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n.btn-mini .caret {\n  margin-top: 5px;\n}\n.btn-small .caret {\n  margin-top: 6px;\n}\n.btn-large .caret {\n  margin-top: 6px;\n  border-left: 5px solid transparent;\n  border-right: 5px solid transparent;\n  border-top: 5px solid #000000;\n}\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 0.75;\n  filter: alpha(opacity=75);\n}\n.nav {\n  margin-left: 0;\n  margin-bottom: 18px;\n  list-style: none;\n}\n.nav > li > a {\n  display: block;\n}\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n.nav .nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 18px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n.nav-list {\n  padding-left: 15px;\n  padding-right: 15px;\n  margin-bottom: 0;\n}\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-left: -15px;\n  margin-right: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n.nav-list [class^=\"icon-\"] {\n  margin-right: 2px;\n}\n.nav-list .divider {\n  height: 1px;\n  margin: 8px 1px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n  *width: 100%;\n  *margin: -5px 0 5px;\n}\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  content: \"\";\n}\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 18px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n  -moz-border-radius: 4px 4px 0 0;\n  border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n  cursor: default;\n}\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  border-radius: 5px;\n}\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n.nav-stacked > li {\n  float: none;\n}\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-radius: 4px 4px 0 0;\n  -moz-border-radius: 4px 4px 0 0;\n  border-radius: 4px 4px 0 0;\n}\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-radius: 0 0 4px 4px;\n  -moz-border-radius: 0 0 4px 4px;\n  border-radius: 0 0 4px 4px;\n}\n.nav-tabs.nav-stacked > li > a:hover {\n  border-color: #ddd;\n  z-index: 2;\n}\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n.nav-tabs .dropdown-menu,\n.nav-pills .dropdown-menu {\n  margin-top: 1px;\n  border-width: 1px;\n}\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.nav-tabs .dropdown-toggle .caret,\n.nav-pills .dropdown-toggle .caret {\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n  margin-top: 6px;\n}\n.nav-tabs .dropdown-toggle:hover .caret,\n.nav-pills .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n.nav-tabs .active .dropdown-toggle .caret,\n.nav-pills .active .dropdown-toggle .caret {\n  border-top-color: #333333;\n  border-bottom-color: #333333;\n}\n.nav > .dropdown.active > a:hover {\n  color: #000000;\n  cursor: pointer;\n}\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > .open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n.nav .open .caret,\n.nav .open.active .caret,\n.nav .open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n.tabbable {\n  *zoom: 1;\n}\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  content: \"\";\n}\n.tabbable:after {\n  clear: both;\n}\n.tab-content {\n  display: table;\n  width: 100%;\n}\n.tabs-below .nav-tabs,\n.tabs-right .nav-tabs,\n.tabs-left .nav-tabs {\n  border-bottom: 0;\n}\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n.tabs-below .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n.tabs-below .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n.tabs-below .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n  -moz-border-radius: 0 0 4px 4px;\n  border-radius: 0 0 4px 4px;\n}\n.tabs-below .nav-tabs > li > a:hover {\n  border-bottom-color: transparent;\n  border-top-color: #ddd;\n}\n.tabs-below .nav-tabs .active > a,\n.tabs-below .nav-tabs .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n.tabs-left .nav-tabs > li,\n.tabs-right .nav-tabs > li {\n  float: none;\n}\n.tabs-left .nav-tabs > li > a,\n.tabs-right .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n.tabs-left .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n.tabs-left .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n  -moz-border-radius: 4px 0 0 4px;\n  border-radius: 4px 0 0 4px;\n}\n.tabs-left .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n.tabs-left .nav-tabs .active > a,\n.tabs-left .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n.tabs-right .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n.tabs-right .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n  -moz-border-radius: 0 4px 4px 0;\n  border-radius: 0 4px 4px 0;\n}\n.tabs-right .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n.tabs-right .nav-tabs .active > a,\n.tabs-right .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n.navbar {\n  *position: relative;\n  *z-index: 2;\n  overflow: visible;\n  margin-bottom: 18px;\n}\n.navbar-inner {\n  padding-left: 20px;\n  padding-right: 20px;\n  background-color: #2c2c2c;\n  background-image: -moz-linear-gradient(top, #333333, #222222);\n  background-image: -ms-linear-gradient(top, #333333, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222));\n  background-image: -webkit-linear-gradient(top, #333333, #222222);\n  background-image: -o-linear-gradient(top, #333333, #222222);\n  background-image: linear-gradient(top, #333333, #222222);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);\n  -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);\n  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1);\n}\n.navbar .container {\n  width: auto;\n}\n.btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-left: 5px;\n  margin-right: 5px;\n  background-color: #2c2c2c;\n  background-image: -moz-linear-gradient(top, #333333, #222222);\n  background-image: -ms-linear-gradient(top, #333333, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#222222));\n  background-image: -webkit-linear-gradient(top, #333333, #222222);\n  background-image: -o-linear-gradient(top, #333333, #222222);\n  background-image: linear-gradient(top, #333333, #222222);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:dximagetransform.microsoft.gradient(enabled=false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n  -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n.btn-navbar:hover,\n.btn-navbar:active,\n.btn-navbar.active,\n.btn-navbar.disabled,\n.btn-navbar[disabled] {\n  background-color: #222222;\n}\n.btn-navbar:active,\n.btn-navbar.active {\n  background-color: #080808 \\9;\n}\n.btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n  -moz-border-radius: 1px;\n  border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n  -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n.nav-collapse.collapse {\n  height: auto;\n}\n.navbar {\n  color: #999999;\n}\n.navbar .brand:hover {\n  text-decoration: none;\n}\n.navbar .brand {\n  float: left;\n  display: block;\n  padding: 8px 20px 12px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  line-height: 1;\n  color: #ffffff;\n}\n.navbar .navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n}\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n.navbar .btn-group .btn {\n  margin-top: 0;\n}\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  content: \"\";\n}\n.navbar-form:after {\n  clear: both;\n}\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n.navbar-form input,\n.navbar-form select {\n  display: inline-block;\n  margin-bottom: 0;\n}\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 6px;\n  white-space: nowrap;\n}\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 6px;\n  margin-bottom: 0;\n}\n.navbar-search .search-query {\n  padding: 4px 9px;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  color: #ffffff;\n  background-color: #626262;\n  border: 1px solid #151515;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15);\n  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15);\n  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n  -moz-transition: none;\n  -ms-transition: none;\n  -o-transition: none;\n  transition: none;\n}\n.navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n.navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n.navbar-search .search-query:focus,\n.navbar-search .search-query.focused {\n  padding: 5px 10px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n  -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n  box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n  outline: 0;\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-left: 0;\n  padding-right: 0;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n.navbar-fixed-top {\n  top: 0;\n}\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n.navbar .nav.pull-right {\n  float: right;\n}\n.navbar .nav > li {\n  display: block;\n  float: left;\n}\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 10px 11px;\n  line-height: 19px;\n  color: #999999;\n  text-decoration: none;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar .nav > li > a:hover {\n  background-color: transparent;\n  color: #ffffff;\n  text-decoration: none;\n}\n.navbar .nav .active > a,\n.navbar .nav .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #222222;\n}\n.navbar .divider-vertical {\n  height: 40px;\n  width: 1px;\n  margin: 0 9px;\n  overflow: hidden;\n  background-color: #222222;\n  border-right: 1px solid #333333;\n}\n.navbar .nav.pull-right {\n  margin-left: 10px;\n  margin-right: 0;\n}\n.navbar .dropdown-menu {\n  margin-top: 1px;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.navbar .dropdown-menu:before {\n  content: '';\n  display: inline-block;\n  border-left: 7px solid transparent;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  position: absolute;\n  top: -7px;\n  left: 9px;\n}\n.navbar .dropdown-menu:after {\n  content: '';\n  display: inline-block;\n  border-left: 6px solid transparent;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  position: absolute;\n  top: -6px;\n  left: 10px;\n}\n.navbar-fixed-bottom .dropdown-menu:before {\n  border-top: 7px solid #ccc;\n  border-top-color: rgba(0, 0, 0, 0.2);\n  border-bottom: 0;\n  bottom: -7px;\n  top: auto;\n}\n.navbar-fixed-bottom .dropdown-menu:after {\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n  bottom: -6px;\n  top: auto;\n}\n.navbar .nav .dropdown-toggle .caret,\n.navbar .nav .open.dropdown .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n.navbar .nav .active .caret {\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n.navbar .nav .open > .dropdown-toggle,\n.navbar .nav .active > .dropdown-toggle,\n.navbar .nav .open.active > .dropdown-toggle {\n  background-color: transparent;\n}\n.navbar .nav .active > .dropdown-toggle:hover {\n  color: #ffffff;\n}\n.navbar .nav.pull-right .dropdown-menu,\n.navbar .nav .dropdown-menu.pull-right {\n  left: auto;\n  right: 0;\n}\n.navbar .nav.pull-right .dropdown-menu:before,\n.navbar .nav .dropdown-menu.pull-right:before {\n  left: auto;\n  right: 12px;\n}\n.navbar .nav.pull-right .dropdown-menu:after,\n.navbar .nav .dropdown-menu.pull-right:after {\n  left: auto;\n  right: 13px;\n}\n.breadcrumb {\n  padding: 7px 14px;\n  margin: 0 0 18px;\n  list-style: none;\n  background-color: #fbfbfb;\n  background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5);\n  background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5);\n  background-image: -o-linear-gradient(top, #ffffff, #f5f5f5);\n  background-image: linear-gradient(top, #ffffff, #f5f5f5);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);\n  border: 1px solid #ddd;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n  -moz-box-shadow: inset 0 1px 0 #ffffff;\n  box-shadow: inset 0 1px 0 #ffffff;\n}\n.breadcrumb li {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n  text-shadow: 0 1px 0 #ffffff;\n}\n.breadcrumb .divider {\n  padding: 0 5px;\n  color: #999999;\n}\n.breadcrumb .active a {\n  color: #333333;\n}\n.pagination {\n  height: 36px;\n  margin: 18px 0;\n}\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n  margin-left: 0;\n  margin-bottom: 0;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n  -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.pagination li {\n  display: inline;\n}\n.pagination a {\n  float: left;\n  padding: 0 14px;\n  line-height: 34px;\n  text-decoration: none;\n  border: 1px solid #ddd;\n  border-left-width: 0;\n}\n.pagination a:hover,\n.pagination .active a {\n  background-color: #f5f5f5;\n}\n.pagination .active a {\n  color: #999999;\n  cursor: default;\n}\n.pagination .disabled span,\n.pagination .disabled a,\n.pagination .disabled a:hover {\n  color: #999999;\n  background-color: transparent;\n  cursor: default;\n}\n.pagination li:first-child a {\n  border-left-width: 1px;\n  -webkit-border-radius: 3px 0 0 3px;\n  -moz-border-radius: 3px 0 0 3px;\n  border-radius: 3px 0 0 3px;\n}\n.pagination li:last-child a {\n  -webkit-border-radius: 0 3px 3px 0;\n  -moz-border-radius: 0 3px 3px 0;\n  border-radius: 0 3px 3px 0;\n}\n.pagination-centered {\n  text-align: center;\n}\n.pagination-right {\n  text-align: right;\n}\n.pager {\n  margin-left: 0;\n  margin-bottom: 18px;\n  list-style: none;\n  text-align: center;\n  *zoom: 1;\n}\n.pager:before,\n.pager:after {\n  display: table;\n  content: \"\";\n}\n.pager:after {\n  clear: both;\n}\n.pager li {\n  display: inline;\n}\n.pager a {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n  -moz-border-radius: 15px;\n  border-radius: 15px;\n}\n.pager a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n.pager .next a {\n  float: right;\n}\n.pager .previous a {\n  float: left;\n}\n.pager .disabled a,\n.pager .disabled a:hover {\n  color: #999999;\n  background-color: #fff;\n  cursor: default;\n}\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  content: \"\";\n}\n.thumbnails:after {\n  clear: both;\n}\n.thumbnails > li {\n  float: left;\n  margin: 0 0 18px 20px;\n}\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 1;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);\n  -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075);\n}\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n  -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n  box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-left: auto;\n  margin-right: auto;\n}\n.thumbnail .caption {\n  padding: 9px;\n}\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 18px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n  color: #c09853;\n}\n.alert-heading {\n  color: inherit;\n}\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 18px;\n}\n.alert-success {\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n  color: #468847;\n}\n.alert-danger,\n.alert-error {\n  background-color: #f2dede;\n  border-color: #eed3d7;\n  color: #b94a48;\n}\n.alert-info {\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n  color: #3a87ad;\n}\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n.alert-block p + p {\n  margin-top: 5px;\n}\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n.progress {\n  overflow: hidden;\n  height: 18px;\n  margin-bottom: 18px;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -ms-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.progress .bar {\n  width: 0%;\n  height: 18px;\n  color: #ffffff;\n  font-size: 12px;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -ms-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(top, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  -ms-box-sizing: border-box;\n  box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n  -moz-transition: width 0.6s ease;\n  -ms-transition: width 0.6s ease;\n  -o-transition: width 0.6s ease;\n  transition: width 0.6s ease;\n}\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n  -moz-background-size: 40px 40px;\n  -o-background-size: 40px 40px;\n  background-size: 40px 40px;\n}\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n  -moz-animation: progress-bar-stripes 2s linear infinite;\n  animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-danger .bar {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(top, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);\n}\n.progress-danger.progress-striped .bar {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-success .bar {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -ms-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(top, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);\n}\n.progress-success.progress-striped .bar {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-info .bar {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -ms-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(top, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);\n}\n.progress-info.progress-striped .bar {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-warning .bar {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -ms-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(top, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fbb450', endColorstr='#f89406', GradientType=0);\n}\n.progress-warning.progress-striped .bar {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n  -moz-border-radius: 6px;\n  border-radius: 6px;\n}\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  color: inherit;\n  letter-spacing: -1px;\n}\n.hero-unit p {\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 27px;\n  color: inherit;\n}\n.tooltip {\n  position: absolute;\n  z-index: 1020;\n  display: block;\n  visibility: visible;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n}\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n.tooltip.top {\n  margin-top: -2px;\n}\n.tooltip.right {\n  margin-left: 2px;\n}\n.tooltip.bottom {\n  margin-top: 2px;\n}\n.tooltip.left {\n  margin-left: -2px;\n}\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-left: 5px solid transparent;\n  border-right: 5px solid transparent;\n  border-top: 5px solid #000000;\n}\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-top: 5px solid transparent;\n  border-bottom: 5px solid transparent;\n  border-left: 5px solid #000000;\n}\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-left: 5px solid transparent;\n  border-right: 5px solid transparent;\n  border-bottom: 5px solid #000000;\n}\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-top: 5px solid transparent;\n  border-bottom: 5px solid transparent;\n  border-right: 5px solid #000000;\n}\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n}\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  padding: 5px;\n}\n.popover.top {\n  margin-top: -5px;\n}\n.popover.right {\n  margin-left: 5px;\n}\n.popover.bottom {\n  margin-top: 5px;\n}\n.popover.left {\n  margin-left: -5px;\n}\n.popover.top .arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-left: 5px solid transparent;\n  border-right: 5px solid transparent;\n  border-top: 5px solid #000000;\n}\n.popover.right .arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-top: 5px solid transparent;\n  border-bottom: 5px solid transparent;\n  border-right: 5px solid #000000;\n}\n.popover.bottom .arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-left: 5px solid transparent;\n  border-right: 5px solid transparent;\n  border-bottom: 5px solid #000000;\n}\n.popover.left .arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-top: 5px solid transparent;\n  border-bottom: 5px solid transparent;\n  border-left: 5px solid #000000;\n}\n.popover .arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n}\n.popover-inner {\n  padding: 3px;\n  width: 280px;\n  overflow: hidden;\n  background: #000000;\n  background: rgba(0, 0, 0, 0.8);\n  -webkit-border-radius: 6px;\n  -moz-border-radius: 6px;\n  border-radius: 6px;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n}\n.popover-title {\n  padding: 9px 15px;\n  line-height: 1;\n  background-color: #f5f5f5;\n  border-bottom: 1px solid #eee;\n  -webkit-border-radius: 3px 3px 0 0;\n  -moz-border-radius: 3px 3px 0 0;\n  border-radius: 3px 3px 0 0;\n}\n.popover-content {\n  padding: 14px;\n  background-color: #ffffff;\n  -webkit-border-radius: 0 0 3px 3px;\n  -moz-border-radius: 0 0 3px 3px;\n  border-radius: 0 0 3px 3px;\n  -webkit-background-clip: padding-box;\n  -moz-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.popover-content p,\n.popover-content ul,\n.popover-content ol {\n  margin-bottom: 0;\n}\n.modal-open .dropdown-menu {\n  z-index: 2050;\n}\n.modal-open .dropdown.open {\n  *z-index: 2050;\n}\n.modal-open .popover {\n  z-index: 2060;\n}\n.modal-open .tooltip {\n  z-index: 2070;\n}\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n.modal-backdrop.fade {\n  opacity: 0;\n}\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n.modal {\n  position: fixed;\n  top: 50%;\n  left: 50%;\n  z-index: 1050;\n  overflow: auto;\n  width: 560px;\n  margin: -250px 0 0 -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  /* IE6-7 */\n\n  -webkit-border-radius: 6px;\n  -moz-border-radius: 6px;\n  border-radius: 6px;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n  -moz-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.modal.fade {\n  -webkit-transition: opacity .3s linear, top .3s ease-out;\n  -moz-transition: opacity .3s linear, top .3s ease-out;\n  -ms-transition: opacity .3s linear, top .3s ease-out;\n  -o-transition: opacity .3s linear, top .3s ease-out;\n  transition: opacity .3s linear, top .3s ease-out;\n  top: -25%;\n}\n.modal.fade.in {\n  top: 50%;\n}\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n.modal-header .close {\n  margin-top: 2px;\n}\n.modal-body {\n  overflow-y: auto;\n  max-height: 400px;\n  padding: 15px;\n}\n.modal-form {\n  margin-bottom: 0;\n}\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n  -moz-border-radius: 0 0 6px 6px;\n  border-radius: 0 0 6px 6px;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n  -moz-box-shadow: inset 0 1px 0 #ffffff;\n  box-shadow: inset 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \"\";\n}\n.modal-footer:after {\n  clear: both;\n}\n.modal-footer .btn + .btn {\n  margin-left: 5px;\n  margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n.dropdown {\n  position: relative;\n}\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-left: 4px solid transparent;\n  border-right: 4px solid transparent;\n  border-top: 4px solid #000000;\n  opacity: 0.3;\n  filter: alpha(opacity=30);\n  content: \"\";\n}\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n.dropdown:hover .caret,\n.open.dropdown .caret {\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  float: left;\n  display: none;\n  min-width: 160px;\n  padding: 4px 0;\n  margin: 0;\n  list-style: none;\n  background-color: #ffffff;\n  border-color: #ccc;\n  border-color: rgba(0, 0, 0, 0.2);\n  border-style: solid;\n  border-width: 1px;\n  -webkit-border-radius: 0 0 5px 5px;\n  -moz-border-radius: 0 0 5px 5px;\n  border-radius: 0 0 5px 5px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n  -moz-background-clip: padding;\n  background-clip: padding-box;\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n}\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n.dropdown-menu .divider {\n  height: 1px;\n  margin: 8px 1px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n  *width: 100%;\n  *margin: -5px 0 5px;\n}\n.dropdown-menu a {\n  display: block;\n  padding: 3px 15px;\n  clear: both;\n  font-weight: normal;\n  line-height: 18px;\n  color: #333333;\n  white-space: nowrap;\n}\n.dropdown-menu li > a:hover,\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #0088cc;\n}\n.dropdown.open {\n  *z-index: 1000;\n}\n.dropdown.open .dropdown-toggle {\n  color: #ffffff;\n  background: #ccc;\n  background: rgba(0, 0, 0, 0.3);\n}\n.dropdown.open .dropdown-menu {\n  display: block;\n}\n.pull-right .dropdown-menu {\n  left: auto;\n  right: 0;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\\2191\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n.typeahead {\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.accordion {\n  margin-bottom: 18px;\n}\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.accordion-heading {\n  border-bottom: 0;\n}\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n.carousel {\n  position: relative;\n  margin-bottom: 18px;\n  line-height: 1;\n}\n.carousel-inner {\n  overflow: hidden;\n  width: 100%;\n  position: relative;\n}\n.carousel .item {\n  display: none;\n  position: relative;\n  -webkit-transition: 0.6s ease-in-out left;\n  -moz-transition: 0.6s ease-in-out left;\n  -ms-transition: 0.6s ease-in-out left;\n  -o-transition: 0.6s ease-in-out left;\n  transition: 0.6s ease-in-out left;\n}\n.carousel .item > img {\n  display: block;\n  line-height: 1;\n}\n.carousel .active,\n.carousel .next,\n.carousel .prev {\n  display: block;\n}\n.carousel .active {\n  left: 0;\n}\n.carousel .next,\n.carousel .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n.carousel .next {\n  left: 100%;\n}\n.carousel .prev {\n  left: -100%;\n}\n.carousel .next.left,\n.carousel .prev.right {\n  left: 0;\n}\n.carousel .active.left {\n  left: -100%;\n}\n.carousel .active.right {\n  left: 100%;\n}\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n  -moz-border-radius: 23px;\n  border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n.carousel-control.right {\n  left: auto;\n  right: 15px;\n}\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n.carousel-caption {\n  position: absolute;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  padding: 10px 15px 5px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n.carousel-caption h4,\n.carousel-caption p {\n  color: #ffffff;\n}\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #eee;\n  border: 1px solid rgba(0, 0, 0, 0.05);\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n  -moz-border-radius: 6px;\n  border-radius: 6px;\n}\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n}\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 18px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n  cursor: pointer;\n}\n.pull-right {\n  float: right;\n}\n.pull-left {\n  float: left;\n}\n.hide {\n  display: none;\n}\n.show {\n  display: block;\n}\n.invisible {\n  visibility: hidden;\n}\n.fade {\n  -webkit-transition: opacity 0.15s linear;\n  -moz-transition: opacity 0.15s linear;\n  -ms-transition: opacity 0.15s linear;\n  -o-transition: opacity 0.15s linear;\n  transition: opacity 0.15s linear;\n  opacity: 0;\n}\n.fade.in {\n  opacity: 1;\n}\n.collapse {\n  -webkit-transition: height 0.35s ease;\n  -moz-transition: height 0.35s ease;\n  -ms-transition: height 0.35s ease;\n  -o-transition: height 0.35s ease;\n  transition: height 0.35s ease;\n  position: relative;\n  overflow: hidden;\n  height: 0;\n}\n.collapse.in {\n  height: auto;\n}\n/*!\n * Bootstrap Responsive v2.0.2\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n.hidden {\n  display: none;\n  visibility: hidden;\n}\n.visible-phone {\n  display: none;\n}\n.visible-tablet {\n  display: none;\n}\n.visible-desktop {\n  display: block;\n}\n.hidden-phone {\n  display: block;\n}\n.hidden-tablet {\n  display: block;\n}\n.hidden-desktop {\n  display: none;\n}\n@media (max-width: 767px) {\n  .visible-phone {\n    display: block;\n  }\n  .hidden-phone {\n    display: none;\n  }\n  .hidden-desktop {\n    display: block;\n  }\n  .visible-desktop {\n    display: none;\n  }\n}\n@media (min-width: 768px) and (max-width: 979px) {\n  .visible-tablet {\n    display: block;\n  }\n  .hidden-tablet {\n    display: none;\n  }\n  .hidden-desktop {\n    display: block;\n  }\n  .visible-desktop {\n    display: none;\n  }\n}\n@media (max-width: 480px) {\n  .nav-collapse {\n    -webkit-transform: translate3d(0, 0, 0);\n  }\n  .page-header h1 small {\n    display: block;\n    line-height: 18px;\n  }\n  input[type=\"checkbox\"],\n  input[type=\"radio\"] {\n    border: 1px solid #ccc;\n  }\n  .form-horizontal .control-group > label {\n    float: none;\n    width: auto;\n    padding-top: 0;\n    text-align: left;\n  }\n  .form-horizontal .controls {\n    margin-left: 0;\n  }\n  .form-horizontal .control-list {\n    padding-top: 0;\n  }\n  .form-horizontal .form-actions {\n    padding-left: 10px;\n    padding-right: 10px;\n  }\n  .modal {\n    position: absolute;\n    top: 10px;\n    left: 10px;\n    right: 10px;\n    width: auto;\n    margin: 0;\n  }\n  .modal.fade.in {\n    top: auto;\n  }\n  .modal-header .close {\n    padding: 10px;\n    margin: -10px;\n  }\n  .carousel-caption {\n    position: static;\n  }\n}\n@media (max-width: 767px) {\n  body {\n    padding-left: 20px;\n    padding-right: 20px;\n  }\n  .navbar-fixed-top {\n    margin-left: -20px;\n    margin-right: -20px;\n  }\n  .container {\n    width: auto;\n  }\n  .row-fluid {\n    width: 100%;\n  }\n  .row {\n    margin-left: 0;\n  }\n  .row > [class*=\"span\"],\n  .row-fluid > [class*=\"span\"] {\n    float: none;\n    display: block;\n    width: auto;\n    margin: 0;\n  }\n  .thumbnails [class*=\"span\"] {\n    width: auto;\n  }\n  input[class*=\"span\"],\n  select[class*=\"span\"],\n  textarea[class*=\"span\"],\n  .uneditable-input {\n    display: block;\n    width: 100%;\n    min-height: 28px;\n    /* Make inputs at least the height of their button counterpart */\n  \n    /* Makes inputs behave like true block-level elements */\n  \n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -ms-box-sizing: border-box;\n    box-sizing: border-box;\n  }\n  .input-prepend input[class*=\"span\"],\n  .input-append input[class*=\"span\"] {\n    width: auto;\n  }\n}\n@media (min-width: 768px) and (max-width: 979px) {\n  .row {\n    margin-left: -20px;\n    *zoom: 1;\n  }\n  .row:before,\n  .row:after {\n    display: table;\n    content: \"\";\n  }\n  .row:after {\n    clear: both;\n  }\n  [class*=\"span\"] {\n    float: left;\n    margin-left: 20px;\n  }\n  .container,\n  .navbar-fixed-top .container,\n  .navbar-fixed-bottom .container {\n    width: 724px;\n  }\n  .span12 {\n    width: 724px;\n  }\n  .span11 {\n    width: 662px;\n  }\n  .span10 {\n    width: 600px;\n  }\n  .span9 {\n    width: 538px;\n  }\n  .span8 {\n    width: 476px;\n  }\n  .span7 {\n    width: 414px;\n  }\n  .span6 {\n    width: 352px;\n  }\n  .span5 {\n    width: 290px;\n  }\n  .span4 {\n    width: 228px;\n  }\n  .span3 {\n    width: 166px;\n  }\n  .span2 {\n    width: 104px;\n  }\n  .span1 {\n    width: 42px;\n  }\n  .offset12 {\n    margin-left: 764px;\n  }\n  .offset11 {\n    margin-left: 702px;\n  }\n  .offset10 {\n    margin-left: 640px;\n  }\n  .offset9 {\n    margin-left: 578px;\n  }\n  .offset8 {\n    margin-left: 516px;\n  }\n  .offset7 {\n    margin-left: 454px;\n  }\n  .offset6 {\n    margin-left: 392px;\n  }\n  .offset5 {\n    margin-left: 330px;\n  }\n  .offset4 {\n    margin-left: 268px;\n  }\n  .offset3 {\n    margin-left: 206px;\n  }\n  .offset2 {\n    margin-left: 144px;\n  }\n  .offset1 {\n    margin-left: 82px;\n  }\n  .row-fluid {\n    width: 100%;\n    *zoom: 1;\n  }\n  .row-fluid:before,\n  .row-fluid:after {\n    display: table;\n    content: \"\";\n  }\n  .row-fluid:after {\n    clear: both;\n  }\n  .row-fluid > [class*=\"span\"] {\n    float: left;\n    margin-left: 2.762430939%;\n  }\n  .row-fluid > [class*=\"span\"]:first-child {\n    margin-left: 0;\n  }\n  .row-fluid > .span12 {\n    width: 99.999999993%;\n  }\n  .row-fluid > .span11 {\n    width: 91.436464082%;\n  }\n  .row-fluid > .span10 {\n    width: 82.87292817100001%;\n  }\n  .row-fluid > .span9 {\n    width: 74.30939226%;\n  }\n  .row-fluid > .span8 {\n    width: 65.74585634900001%;\n  }\n  .row-fluid > .span7 {\n    width: 57.182320438000005%;\n  }\n  .row-fluid > .span6 {\n    width: 48.618784527%;\n  }\n  .row-fluid > .span5 {\n    width: 40.055248616%;\n  }\n  .row-fluid > .span4 {\n    width: 31.491712705%;\n  }\n  .row-fluid > .span3 {\n    width: 22.928176794%;\n  }\n  .row-fluid > .span2 {\n    width: 14.364640883%;\n  }\n  .row-fluid > .span1 {\n    width: 5.801104972%;\n  }\n  input,\n  textarea,\n  .uneditable-input {\n    margin-left: 0;\n  }\n  input.span12, textarea.span12, .uneditable-input.span12 {\n    width: 714px;\n  }\n  input.span11, textarea.span11, .uneditable-input.span11 {\n    width: 652px;\n  }\n  input.span10, textarea.span10, .uneditable-input.span10 {\n    width: 590px;\n  }\n  input.span9, textarea.span9, .uneditable-input.span9 {\n    width: 528px;\n  }\n  input.span8, textarea.span8, .uneditable-input.span8 {\n    width: 466px;\n  }\n  input.span7, textarea.span7, .uneditable-input.span7 {\n    width: 404px;\n  }\n  input.span6, textarea.span6, .uneditable-input.span6 {\n    width: 342px;\n  }\n  input.span5, textarea.span5, .uneditable-input.span5 {\n    width: 280px;\n  }\n  input.span4, textarea.span4, .uneditable-input.span4 {\n    width: 218px;\n  }\n  input.span3, textarea.span3, .uneditable-input.span3 {\n    width: 156px;\n  }\n  input.span2, textarea.span2, .uneditable-input.span2 {\n    width: 94px;\n  }\n  input.span1, textarea.span1, .uneditable-input.span1 {\n    width: 32px;\n  }\n}\n@media (max-width: 979px) {\n  body {\n    padding-top: 0;\n  }\n  .navbar-fixed-top {\n    position: static;\n    margin-bottom: 18px;\n  }\n  .navbar-fixed-top .navbar-inner {\n    padding: 5px;\n  }\n  .navbar .container {\n    width: auto;\n    padding: 0;\n  }\n  .navbar .brand {\n    padding-left: 10px;\n    padding-right: 10px;\n    margin: 0 0 0 -5px;\n  }\n  .navbar .nav-collapse {\n    clear: left;\n  }\n  .navbar .nav {\n    float: none;\n    margin: 0 0 9px;\n  }\n  .navbar .nav > li {\n    float: none;\n  }\n  .navbar .nav > li > a {\n    margin-bottom: 2px;\n  }\n  .navbar .nav > .divider-vertical {\n    display: none;\n  }\n  .navbar .nav .nav-header {\n    color: #999999;\n    text-shadow: none;\n  }\n  .navbar .nav > li > a,\n  .navbar .dropdown-menu a {\n    padding: 6px 15px;\n    font-weight: bold;\n    color: #999999;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n  }\n  .navbar .dropdown-menu li + li a {\n    margin-bottom: 2px;\n  }\n  .navbar .nav > li > a:hover,\n  .navbar .dropdown-menu a:hover {\n    background-color: #222222;\n  }\n  .navbar .dropdown-menu {\n    position: static;\n    top: auto;\n    left: auto;\n    float: none;\n    display: block;\n    max-width: none;\n    margin: 0 15px;\n    padding: 0;\n    background-color: transparent;\n    border: none;\n    -webkit-border-radius: 0;\n    -moz-border-radius: 0;\n    border-radius: 0;\n    -webkit-box-shadow: none;\n    -moz-box-shadow: none;\n    box-shadow: none;\n  }\n  .navbar .dropdown-menu:before,\n  .navbar .dropdown-menu:after {\n    display: none;\n  }\n  .navbar .dropdown-menu .divider {\n    display: none;\n  }\n  .navbar-form,\n  .navbar-search {\n    float: none;\n    padding: 9px 15px;\n    margin: 9px 0;\n    border-top: 1px solid #222222;\n    border-bottom: 1px solid #222222;\n    -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n    -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n  }\n  .navbar .nav.pull-right {\n    float: none;\n    margin-left: 0;\n  }\n  .navbar-static .navbar-inner {\n    padding-left: 10px;\n    padding-right: 10px;\n  }\n  .btn-navbar {\n    display: block;\n  }\n  .nav-collapse {\n    overflow: hidden;\n    height: 0;\n  }\n}\n@media (min-width: 980px) {\n  .nav-collapse.collapse {\n    height: auto !important;\n    overflow: visible !important;\n  }\n}\n@media (min-width: 1200px) {\n  .row {\n    margin-left: -30px;\n    *zoom: 1;\n  }\n  .row:before,\n  .row:after {\n    display: table;\n    content: \"\";\n  }\n  .row:after {\n    clear: both;\n  }\n  [class*=\"span\"] {\n    float: left;\n    margin-left: 30px;\n  }\n  .container,\n  .navbar-fixed-top .container,\n  .navbar-fixed-bottom .container {\n    width: 1170px;\n  }\n  .span12 {\n    width: 1170px;\n  }\n  .span11 {\n    width: 1070px;\n  }\n  .span10 {\n    width: 970px;\n  }\n  .span9 {\n    width: 870px;\n  }\n  .span8 {\n    width: 770px;\n  }\n  .span7 {\n    width: 670px;\n  }\n  .span6 {\n    width: 570px;\n  }\n  .span5 {\n    width: 470px;\n  }\n  .span4 {\n    width: 370px;\n  }\n  .span3 {\n    width: 270px;\n  }\n  .span2 {\n    width: 170px;\n  }\n  .span1 {\n    width: 70px;\n  }\n  .offset12 {\n    margin-left: 1230px;\n  }\n  .offset11 {\n    margin-left: 1130px;\n  }\n  .offset10 {\n    margin-left: 1030px;\n  }\n  .offset9 {\n    margin-left: 930px;\n  }\n  .offset8 {\n    margin-left: 830px;\n  }\n  .offset7 {\n    margin-left: 730px;\n  }\n  .offset6 {\n    margin-left: 630px;\n  }\n  .offset5 {\n    margin-left: 530px;\n  }\n  .offset4 {\n    margin-left: 430px;\n  }\n  .offset3 {\n    margin-left: 330px;\n  }\n  .offset2 {\n    margin-left: 230px;\n  }\n  .offset1 {\n    margin-left: 130px;\n  }\n  .row-fluid {\n    width: 100%;\n    *zoom: 1;\n  }\n  .row-fluid:before,\n  .row-fluid:after {\n    display: table;\n    content: \"\";\n  }\n  .row-fluid:after {\n    clear: both;\n  }\n  .row-fluid > [class*=\"span\"] {\n    float: left;\n    margin-left: 2.564102564%;\n  }\n  .row-fluid > [class*=\"span\"]:first-child {\n    margin-left: 0;\n  }\n  .row-fluid > .span12 {\n    width: 100%;\n  }\n  .row-fluid > .span11 {\n    width: 91.45299145300001%;\n  }\n  .row-fluid > .span10 {\n    width: 82.905982906%;\n  }\n  .row-fluid > .span9 {\n    width: 74.358974359%;\n  }\n  .row-fluid > .span8 {\n    width: 65.81196581200001%;\n  }\n  .row-fluid > .span7 {\n    width: 57.264957265%;\n  }\n  .row-fluid > .span6 {\n    width: 48.717948718%;\n  }\n  .row-fluid > .span5 {\n    width: 40.170940171000005%;\n  }\n  .row-fluid > .span4 {\n    width: 31.623931624%;\n  }\n  .row-fluid > .span3 {\n    width: 23.076923077%;\n  }\n  .row-fluid > .span2 {\n    width: 14.529914530000001%;\n  }\n  .row-fluid > .span1 {\n    width: 5.982905983%;\n  }\n  input,\n  textarea,\n  .uneditable-input {\n    margin-left: 0;\n  }\n  input.span12, textarea.span12, .uneditable-input.span12 {\n    width: 1160px;\n  }\n  input.span11, textarea.span11, .uneditable-input.span11 {\n    width: 1060px;\n  }\n  input.span10, textarea.span10, .uneditable-input.span10 {\n    width: 960px;\n  }\n  input.span9, textarea.span9, .uneditable-input.span9 {\n    width: 860px;\n  }\n  input.span8, textarea.span8, .uneditable-input.span8 {\n    width: 760px;\n  }\n  input.span7, textarea.span7, .uneditable-input.span7 {\n    width: 660px;\n  }\n  input.span6, textarea.span6, .uneditable-input.span6 {\n    width: 560px;\n  }\n  input.span5, textarea.span5, .uneditable-input.span5 {\n    width: 460px;\n  }\n  input.span4, textarea.span4, .uneditable-input.span4 {\n    width: 360px;\n  }\n  input.span3, textarea.span3, .uneditable-input.span3 {\n    width: 260px;\n  }\n  input.span2, textarea.span2, .uneditable-input.span2 {\n    width: 160px;\n  }\n  input.span1, textarea.span1, .uneditable-input.span1 {\n    width: 60px;\n  }\n  .thumbnails {\n    margin-left: -30px;\n  }\n  .thumbnails > li {\n    margin-left: 30px;\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/gdrive/css/main.css",
    "content": "@font-face {\n  font-family: 'Droid Sans';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Droid Sans'), local('DroidSans'), url(DroidSans.woff) format('woff');\n}\n\nhtml, body {\n  margin: 0;\n  height: 100%;\n}\n\nbody ::-webkit-scrollbar {\n  height: 16px;\n  overflow: visible;\n  width: 16px;\n}\nbody ::-webkit-scrollbar-thumb {\n  background-color: rgba(0, 0, 0, .1);\n  background-clip: padding-box;\n  border: solid transparent;\n  min-height: 28px;\n  padding: 100px 0 0;\n  box-shadow: inset 1px 1px 0 rgba(0,0,0,.1),inset 0 -1px 0 rgba(0,0,0,.07);\n  border-width: 1px 1px 1px 6px;\n}\nbody ::-webkit-scrollbar-thumb:hover {\n  background-color: rgba(0, 0, 0, 0.5);\n}\nbody ::-webkit-scrollbar-button {\n  height: 0;\n  width: 0;\n}\n::-webkit-scrollbar-track {\n  background-clip: padding-box;\n  border: solid transparent;\n  border-width: 0 0 0 4px;\n}\nbody ::-webkit-scrollbar-corner {\n  background: transparent;\n}\n\nbody {\n  padding: 0 15px 15px 15px;\n  overflow: hidden;\n  background: url(../img/google_drive_bg.png) no-repeat center center,\n              -webkit-linear-gradient(bottom, #eee, rgba(255,255,255,0));\n  background-size: 270px 215px, 100%;\n  font-family: 'Droid Sans', sans-serif;\n}\n\nbody.dropping > #main {\n  -webkit-filter: blur(2px);\n}\n\n#dropper {\n  visibility: hidden;\n}\n.dropping #dropper {\n  visibility: visible;\n  display: -webkit-flex;\n  opacity: 1;\n  pointer-events: all;\n}\n\nul {\n  margin: 0;\n  height: 525px;\n  overflow: auto;\n}\n\nli {\n  border: 1px solid #ccc;\n  border-radius: 3px;\n  padding: 5px;\n  margin-bottom: 3px;\n  background: -webkit-linear-gradient(right, #eee, rgba(255,255,255,0), #eee);\n  color: #666666;\n}\n\n#log {\n  display: block;\n}\n\n#dropper {\n  pointer-events: none;\n  opacity: 0;\n  background: rgba(255,255,255,0.5);\n  position: absolute;\n  z-index: 100;\n  width: 100%;\n  height: 100%;\n  left: 0;\n  top: 0;\n  box-sizing: border-box;\n  -webkit-align-items: center;\n  -webkit-justify-content: center;\n  -webkit-transition: opacity 0.1s ease-in-out;\n}\n\n.dropzone {\n  padding: 15px 50px;\n  border-radius: 10px;\n  border: 10px dashed #ccc;\n}\n\n.dropzone img {\n  width: 300px;\n  height: 300px;\n  opacity: 0.3;\n}\n\n#main > nav {\n  padding-top: 15px;\n  margin-bottom: 10px;\n  -webkit-app-region: drag;\n}\n\n#main > nav button {\n  -webkit-app-region: no-drag;\n} \n\nnav > h2 {\n  display: inline-block;\n  vertical-align: middle;\n  margin-right: 15px;\n}\n\nnav:hover #close-button {\n  opacity: 1;\n}\n\n#close-button {\n  float: right;\n  padding: 0 5px 2px 5px;\n  font-weight: bold;\n  opacity: 0;\n  -webkit-transition: all 0.3s ease-in-out;\n}\n\n.uploading progress {\n  visibility: visible;\n}\n\nprogress {\n  visibility: hidden;\n  width: 100%;\n}\n\n.date {\n  float: right;\n}\n"
  },
  {
    "path": "_archive/apps/samples/gdrive/js/app.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Eric Bidelman (ericbidelman@chromium.org)\n*/\n\nfunction onError(e) {\n  console.log(e);\n}\n\n// FILESYSTEM SUPPORT ----------------------------------------------------------\nvar fs = null;\nvar FOLDERNAME = 'test';\n\nfunction writeFile(blob) {\n  if (!fs) {\n    return;\n  }\n\n  fs.root.getDirectory(FOLDERNAME, {create: true}, function(dirEntry) {\n    dirEntry.getFile(blob.name, {create: true, exclusive: false}, function(fileEntry) {\n      // Create a FileWriter object for our FileEntry, and write out blob.\n      fileEntry.createWriter(function(fileWriter) {\n        fileWriter.onerror = onError;\n        fileWriter.onwriteend = function(e) {\n          console.log('Write completed.');\n        };\n        fileWriter.write(blob);\n      }, onError);\n    }, onError);\n  }, onError);\n}\n// -----------------------------------------------------------------------------\n\nvar gDriveApp = angular.module('gDriveApp', []);\n\ngDriveApp.factory('gdocs', function() {\n  var gdocs = new GDocs();\n\n  var dnd = new DnDFileController('body', function(files) {\n    var $scope = angular.element(this).scope();\n    Util.toArray(files).forEach(function(file, i) {\n      gdocs.upload(file, function() {\n        $scope.fetchDocs(true);\n      }, true);\n    });\n  });\n\n  return gdocs;\n});\n//gDriveApp.service('gdocs', GDocs);\n//gDriveApp.controller('DocsController', ['$scope', '$http', DocsController]);\n\n// Main Angular controller for app.\nfunction DocsController($scope, $http, gdocs) {\n  $scope.docs = [];\n\n  // Response handler that caches file icons in the filesystem API.\n  function successCallbackWithFsCaching(resp, status, headers, config) {\n    var docs = [];\n\n    var totalEntries = resp.items.length;\n\n    resp.items.forEach(function(entry, i) {\n      var doc = {\n        title: entry.title,\n        updatedDate: Util.formatDate(entry.modifiedDate),\n        updatedDateFull: entry.modifiedDate,\n        icon: entry.iconLink,\n        alternateLink: entry.alternateLink,\n        size: entry.fileSize ? '( ' + entry.fileSize + ' bytes)' : null\n      };\n\n      // 'http://gstatic.google.com/doc_icon_128.png' -> 'doc_icon_128.png'\n      doc.iconFilename = doc.icon.substring(doc.icon.lastIndexOf('/') + 1);\n\n      // If file exists, it we'll get back a FileEntry for the filesystem URL.\n      // Otherwise, the error callback will fire and we need to XHR it in and\n      // write it to the FS.\n      var fsURL = fs.root.toURL() + FOLDERNAME + '/' + doc.iconFilename;\n      window.webkitResolveLocalFileSystemURL(fsURL, function(entry) {\n        console.log('Fetched icon from the FS cache');\n\n        doc.icon = entry.toURL(); // should be === to fsURL, but whatevs.\n\n        $scope.docs.push(doc);\n\n        // Only want to sort and call $apply() when we have all entries.\n        if (totalEntries - 1 == i) {\n          $scope.docs.sort(Util.sortByDate);\n          $scope.$apply(function($scope) {}); // Inform angular we made changes.\n        }\n      }, function(e) {\n\n        $http.get(doc.icon, {responseType: 'blob'}).success(function(blob) {\n          console.log('Fetched icon via XHR');\n\n          blob.name = doc.iconFilename; // Add icon filename to blob.\n\n          writeFile(blob); // Write is async, but that's ok.\n\n          doc.icon = window.URL.createObjectURL(blob);\n\n          $scope.docs.push(doc);\n          if (totalEntries - 1 == i) {\n            $scope.docs.sort(Util.sortByDate);\n          }\n        });\n\n      });\n    });\n  }\n\n  $scope.clearDocs = function() {\n    $scope.docs = []; // Clear out old results.\n  };\n\n  $scope.fetchDocs = function(retry) {\n    this.clearDocs();\n\n    if (gdocs.accessToken) {\n      var config = {\n        params: {'alt': 'json'},\n        headers: {\n          'Authorization': 'Bearer ' + gdocs.accessToken\n        }\n      };\n\n      $http.get(gdocs.DOCLIST_FEED, config).\n        success(successCallbackWithFsCaching).\n        error(function(data, status, headers, config) {\n          if (status == 401 && retry) {\n            gdocs.removeCachedAuthToken(\n                gdocs.auth.bind(gdocs, true, \n                    $scope.fetchDocs.bind($scope, false)));\n          }\n        });\n    }\n  };\n\n  // Toggles the authorization state.\n  $scope.toggleAuth = function(interactive) {\n    if (!gdocs.accessToken) {\n      gdocs.auth(interactive, function() {\n        $scope.fetchDocs(false);\n      });\n    } else {\n      gdocs.revokeAuthToken(function() {});\n      this.clearDocs();\n    }\n  }\n\n  // Controls the label of the authorize/deauthorize button.\n  $scope.authButtonLabel = function() {\n    if (gdocs.accessToken)\n      return 'Deauthorize';\n    else\n      return 'Authorize';\n  };\n\n  $scope.toggleAuth(false);\n}\n\nDocsController.$inject = ['$scope', '$http', 'gdocs']; // For code minifiers.\n\n// Init setup and attach event listeners.\ndocument.addEventListener('DOMContentLoaded', function(e) {\n  var closeButton = document.querySelector('#close-button');\n  closeButton.addEventListener('click', function(e) {\n    window.close();\n  });\n\n  // FILESYSTEM SUPPORT --------------------------------------------------------\n  window.webkitRequestFileSystem(TEMPORARY, 1024 * 1024, function(localFs) {\n    fs = localFs;\n  }, onError);\n  // ---------------------------------------------------------------------------\n});\n"
  },
  {
    "path": "_archive/apps/samples/gdrive/js/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function(launchData) {\n  chrome.app.window.create('../main.html', {\n    id: \"GDriveExample\",\n    innerBounds: {\n      width: 500,\n      height: 600,\n      minWidth: 500,\n      minHeight: 600\n    },\n    frame: 'none'\n  });\n});\n\nchrome.runtime.onInstalled.addListener(function() {\n  console.log('installed');\n});\n\nchrome.runtime.onSuspend.addListener(function() { \n  // Do some simple clean-up tasks.\n});\n"
  },
  {
    "path": "_archive/apps/samples/gdrive/js/dnd.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Eric Bidelman (ericbidelman@chromium.org)\n*/\n\nfunction DnDFileController(selector, onDropCallback) {\n  var el_ = document.querySelector(selector);\n\n  this.dragenter = function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n    el_.classList.add('dropping');\n  };\n\n  this.dragover = function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n  };\n\n  this.dragleave = function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n    el_.classList.remove('dropping');\n  };\n\n  this.drop = function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n\n    el_.classList.remove('dropping');\n\n    onDropCallback.bind(this)(e.dataTransfer.files);\n  };\n\n  el_.addEventListener('dragenter', this.dragenter, false);\n  el_.addEventListener('dragover', this.dragover, false);\n  el_.addEventListener('dragleave', this.dragleave, false);\n  el_.addEventListener('drop', this.drop, false);\n};\n"
  },
  {
    "path": "_archive/apps/samples/gdrive/js/gdocs.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Eric Bidelman (ericbidelman@chromium.org)\n*/\n\n\"use strict\";\n\n\nfunction GDocs(selector) {\n\n  var SCOPE_ = 'https://www.googleapis.com/drive/v2/';\n\n  this.lastResponse = null;\n\n  this.__defineGetter__('SCOPE', function() {\n    return SCOPE_;\n  });\n\n  this.__defineGetter__('DOCLIST_FEED', function() {\n    return SCOPE_ + 'files';\n  });\n\n  this.__defineGetter__('CREATE_SESSION_URI', function() {\n    return 'https://www.googleapis.com/upload/drive/v2/files?uploadType=resumable';\n  });\n\n  this.__defineGetter__('DEFAULT_CHUNK_SIZE', function() {\n    return 1024 * 1024 * 5; // 5MB;\n  });\n};\n\nGDocs.prototype.auth = function(interactive, opt_callback) {\n  try {\n    chrome.identity.getAuthToken({interactive: interactive}, function(token) {\n      if (token) {\n        this.accessToken = token;\n        opt_callback && opt_callback();\n      }\n    }.bind(this));\n  } catch(e) {\n    console.log(e);\n  }\n};\n\nGDocs.prototype.removeCachedAuthToken = function(opt_callback) {\n  if (this.accessToken) {\n    var accessToken = this.accessToken;\n    this.accessToken = null;\n    // Remove token from the token cache.\n    chrome.identity.removeCachedAuthToken({ \n      token: accessToken\n    }, function() {\n      opt_callback && opt_callback();\n    });\n  } else {\n    opt_callback && opt_callback();\n  }\n};\n\nGDocs.prototype.revokeAuthToken = function(opt_callback) {\n  if (this.accessToken) {\n    // Make a request to revoke token\n    var xhr = new XMLHttpRequest();\n    xhr.open('GET', 'https://accounts.google.com/o/oauth2/revoke?token=' +\n             this.accessToken);\n    xhr.send();\n    this.removeCachedAuthToken(opt_callback);\n  }\n}\n\n/*\n * Generic HTTP AJAX request handler.\n */\nGDocs.prototype.makeRequest = function(method, url, callback, opt_data, opt_headers) {\n  var data = opt_data || null;\n  var headers = opt_headers || {};\n\n  var xhr = new XMLHttpRequest();\n  xhr.open(method, url, true);\n\n  // Include common headers (auth and version) and add rest. \n  xhr.setRequestHeader('Authorization', 'Bearer ' + this.accessToken);\n  for (var key in headers) {\n    xhr.setRequestHeader(key, headers[key]);\n  }\n\n  xhr.onload = function(e) {\n    this.lastResponse = this.response;\n    callback(this.lastResponse, this);\n  }.bind(this);\n  xhr.onerror = function(e) {\n    console.log(this, this.status, this.response,\n                this.getAllResponseHeaders());\n  };\n  xhr.send(data);\n};\n\n\n\n/**\n * Uploads a file to Google Docs.\n */\nGDocs.prototype.upload = function(blob, callback, retry) {\n\n  var onComplete = function(response) {\n      document.getElementById('main').classList.remove('uploading');\n      var entry = JSON.parse(response).entry;\n      callback.apply(this, [entry]);\n    }.bind(this);\n  var onError = function(response) {\n      if (retry) {\n        this.removeCachedAuthToken(\n            this.auth.bind(this, true, \n                this.upload.bind(this, blob, callback, false)));\n      } else {\n        document.getElementById('main').classList.remove('uploading');\n        throw new Error('Error: '+response);\n      }\n    }.bind(this);\n\n\n  var uploader = new MediaUploader({\n    token: this.accessToken,\n    file: blob,\n    onComplete: onComplete,\n    onError: onError\n  });\n\n  document.getElementById('main').classList.add('uploading');\n  uploader.upload();\n\n};\n\n\n"
  },
  {
    "path": "_archive/apps/samples/gdrive/js/upload.js",
    "content": "/**\n * Helper for implementing retries with backoff. Initial retry\n * delay is 1 second, increasing by 2x (+jitter) for subsequent retries\n * \n * @constructor\n */\nvar RetryHandler = function() {\n  this.interval = 1000; // Start at one second\n  this.maxInterval = 60 * 1000; // Don't wait longer than a minute \n};\n\n/**\n * Invoke the function after waiting \n *\n * @param {function} fn Function to invoke\n */\nRetryHandler.prototype.retry = function(fn) {\n  setTimeout(fn, this.interval);\n  this.interval = this.nextInterval_();\n};\n\n/**\n * Reset the counter (e.g. after successful request.)\n */\nRetryHandler.prototype.reset = function() {\n  this.interval = 1000;\n};\n\n/**\n * Calculate the next wait time.\n * @return {number} Next wait interval, in milliseconds\n *\n * @private\n */\nRetryHandler.prototype.nextInterval_ = function() {\n  var interval = this.interval * 2 + this.getRandomInt_(0, 1000);\n  return Math.min(interval, this.maxInterval);\n};\n\n/**\n * Get a random int in the range of min to max. Used to add jitter to wait times.\n *\n * @param {number} min Lower bounds\n * @param {number} max Upper bounds\n * @private\n */\nRetryHandler.prototype.getRandomInt_ = function(min, max) {\n  return Math.floor(Math.random() * (max - min + 1) + min);\n};\n\n\n/**\n * Helper class for resumable uploads using XHR/CORS. Can upload any Blob-like item, whether\n * files or in-memory constructs.\n *\n * @example\n * var content = new Blob([\"Hello world\"], {\"type\": \"text/plain\"});\n * var uploader = new MediaUploader({\n *   file: content,\n *   token: accessToken,\n *   onComplete: function(data) { ... }\n *   onError: function(data) { ... }\n * });\n * uploader.upload();\n *\n * @constructor\n * @param {object} options Hash of options\n * @param {string} options.token Access token\n * @param {blob} options.file Blob-like item to upload\n * @param {string} [options.fileId] ID of file if replacing\n * @param {object} [options.params] Additional query parameters\n * @param {string} [options.contentType] Content-type, if overriding the type of the blob.\n * @param {object} [options.metadata] File metadata\n * @param {function} [options.onComplete] Callback for when upload is complete\n * @param {function} [options.onError] Callback if upload fails\n */\nvar MediaUploader = function(options) {\n  var noop = function() {};\n  this.file = options.file;\n  this.contentType = options.contentType || this.file.type || 'application/octet-stream';\n  this.metadata = options.metadata || {\n    'title': this.file.name,\n    'mimeType': this.contentType\n  };\n  this.token = options.token;\n  this.onComplete = options.onComplete || noop;\n  this.onError = options.onError || noop;\n  this.offset = options.offset || 0;\n  this.chunkSize = options.chunkSize || 0;\n  this.retryHandler = new RetryHandler();\n\n  this.url = options.url;\n  if (!this.url) {\n    var params = options.params || {};\n    params.uploadType = 'resumable';\n    this.url = this.buildUrl_(options.fileId, params);\n  }\n  this.httpMethod = this.fileId ? 'PUT' : 'POST';\n};\n\n/**\n * Initiate the upload.\n */ \nMediaUploader.prototype.upload = function() {\n  var self = this;\n  var xhr = new XMLHttpRequest();\n\n  xhr.open(this.httpMethod, this.url, true);\n  xhr.setRequestHeader('Authorization', 'Bearer ' + this.token);\n  xhr.setRequestHeader('Content-Type', 'application/json');\n  xhr.setRequestHeader('X-Upload-Content-Length', this.file.size);\n  xhr.setRequestHeader('X-Upload-Content-Type', this.contentType);\n\n  xhr.onload = function(e) {\n    var location = e.target.getResponseHeader('Location');\n    this.url = location;\n    this.sendFile_();\n  }.bind(this);\n  xhr.onerror = this.onUploadError_.bind(this);\n  xhr.send(JSON.stringify(this.metadata));\n};\n\n/**\n * Send the actual file content.\n *\n * @private\n */ \nMediaUploader.prototype.sendFile_ = function() {\n  var content = this.file;\n  var end = this.file.size;\n  \n  if (this.offset || this.chunkSize) {\n    // Only bother to slice the file if we're either resuming or uploading in chunks\n    if (this.chunkSize) {\n      end = Math.min(this.offset + this.chunkSize, this.file.size);\n    }\n    content = content.slice(this.offset, end);\n  }\n  \n  var xhr = new XMLHttpRequest();\n  xhr.open('PUT', this.url, true);\n  xhr.setRequestHeader('Content-Type', this.contentType);\n  xhr.setRequestHeader('Content-Range', \"bytes \" + this.offset + \"-\" + (end - 1) + \"/\" + this.file.size);\n  xhr.setRequestHeader('X-Upload-Content-Type', this.file.type);\n  xhr.onload = this.onContentUploadSuccess_.bind(this);\n  xhr.onerror = this.onContentUploadError_.bind(this);\n  xhr.send(content);\n};\n\n/**\n * Query for the state of the file for resumption.\n * \n * @private\n */ \nMediaUploader.prototype.resume_ = function() {\n  var xhr = new XMLHttpRequest();\n  xhr.open('PUT', this.url, true);\n  xhr.setRequestHeader('Content-Range', \"bytes */\" + this.file.size);\n  xhr.setRequestHeader('X-Upload-Content-Type', this.file.type);\n  xhr.onload = this.onContentUploadSuccess_.bind(this);\n  xhr.onerror = this.onContentUploadError_.bind(this);\n  xhr.send();\n};\n\n/**\n * Extract the last saved range if available in the request.\n *\n * @param {XMLHttpRequest} xhr Request object\n */\nMediaUploader.prototype.extractRange_ = function(xhr) {\n var range = xhr.getResponseHeader('Range');\n if (range) {\n   this.offset = parseInt(range.match(/\\d+/g).pop(), 10) + 1;\n }\n};\n\n/**\n * Handle successful responses for uploads. Depending on the context,\n * may continue with uploading the next chunk of the file or, if complete,\n * invokes the caller's callback.\n *\n * @private\n * @param {object} e XHR event\n */\nMediaUploader.prototype.onContentUploadSuccess_ = function(e) {\n  if (e.target.status == 200 || e.target.status == 201) {\n    this.onComplete(e.target.response);\n  } else if (e.target.status == 308) {\n    this.extractRange_(e.target);\n    this.retryHandler.reset();\n    this.sendFile_();\n  }\n};\n\n/**\n * Handles errors for uploads. Either retries or aborts depending\n * on the error.\n *\n * @private\n * @param {object} e XHR event\n */\nMediaUploader.prototype.onContentUploadError_ = function(e) {\n  if (e.target.status && e.target.status < 500) {\n    this.onError(e.target.response);\n  } else {\n    this.retryHandler.retry(this.resume_.bind(this));\n  }\n};\n\n\n/**\n * Handles errors for the initial request.\n *\n * @private\n * @param {object} e XHR event\n */\nMediaUploader.prototype.onUploadError_ = function(e) {\n  this.onError(e.target.response); // TODO - Retries for initial upload\n};\n\n/**\n* Construct a query string from a hash/object\n*\n* @private\n* @param {object} [params] Key/value pairs for query string\n* @return {string} query string\n*/\nMediaUploader.prototype.buildQuery_ = function(params) {\n  params = params || {};\n  return Object.keys(params).map(function(key) {\n    return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);\n  }).join('&');\n};\n\n/**\n* Build the drive upload URL\n*\n* @private\n* @param {string} [id] File ID if replacing\n* @param {object} [params] Query parameters\n* @return {string} URL\n*/\nMediaUploader.prototype.buildUrl_ = function(id, params) {\n  var url = 'https://www.googleapis.com/upload/drive/v2/files/';\n  if (id) {\n    url += id;\n  }\n  var query = this.buildQuery_(params);\n  if (query) {\n    url += '?' + query;\n  }\n  return url;\n};\n\n\n\n"
  },
  {
    "path": "_archive/apps/samples/gdrive/js/util.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Eric Bidelman (ericbidelman@chromium.org)\n*/\n\nvar Util = Util || {};\n\n// Combines two JSON objects in one.\nUtil.merge = function(obj1, obj2) {\n  var obj = {};\n\n  for (var x in obj1) {\n    if (obj1.hasOwnProperty(x)) {\n      obj[x] = obj1[x];\n    }\n  }\n\n  for (var x in obj2) {\n    if (obj2.hasOwnProperty(x)) {\n      obj[x] = obj2[x];\n    }\n  }\n\n  return obj;\n};\n\n/**\n * Turns a NodeList into an array.\n *\n * @param {NodeList} list The array-like object.\n * @return {Array} The NodeList as an array.\n */\nUtil.toArray = function(list) {\n  return Array.prototype.slice.call(list || [], 0);\n};\n\n/**\n * Urlencodes a JSON object of key/value query parameters.\n * @param {Object} parameters Key value pairs representing URL parameters.\n * @return {string} query parameters concatenated together.\n */\nUtil.stringify = function(parameters) {\n  var params = [];\n  for(var p in parameters) {\n    params.push(encodeURIComponent(p) + '=' +\n                encodeURIComponent(parameters[p]));\n  }\n  return params.join('&');\n};\n\n/**\n * Creates a JSON object of key/value pairs\n * @param {string} paramStr A string of Url query parmeters.\n *    For example: max-results=5&startindex=2&showfolders=true\n * @return {Object} The query parameters as key/value pairs.\n */\nUtil.unstringify = function(paramStr) {\n  var parts = paramStr.split('&');\n\n  var params = {};\n  for (var i = 0, pair; pair = parts[i]; ++i) {\n    var param = pair.split('=');\n    params[decodeURIComponent(param[0])] = decodeURIComponent(param[1]);\n  }\n  return params;\n};\n\n/**\n * Utility for formatting a date string.\n * @param {string} msg The date in UTC format. Example: 2010-04-01T08:00:00Z.\n * @return {string} The date formated as mm/dd/yy. Example: 04/01/10.\n */\nUtil.formatDate = function(dateStr) {\n  var date = new Date(dateStr.split('T')[0]);\n  return [date.getMonth() + 1, date.getDate(),\n          date.getFullYear().toString().substring(2)].join('/');\n};\n\n/**\n * Utility for formatting a Date object as a string in ISO 8601 format using UTC.\n * @param {Date} d The date to format.\n * @return {string} The formated date string in ISO 8601 format.\n */\nUtil.ISODateString = function(d) {\n var pad = function(n) {\n   return n < 10 ? '0' + n : n;\n };\n return d.getUTCFullYear() + '-'\n        + pad(d.getUTCMonth() + 1) + '-'\n        + pad(d.getUTCDate()) + 'T'\n        + pad(d.getUTCHours()) + ':'\n        + pad(d.getUTCMinutes()) + ':'\n        + pad(d.getUTCSeconds());// + 'Z'\n};\n\n/** \n * Formats a string with the given parameters. The string to format must have\n * placeholders that correspond to the index of the arguments passed and surrounded \n * by curly braces (e.g. 'Some {0} string {1}').\n *\n * @param {string} var_args The string to be formatted should be the first \n *     argument followed by the variables to inject into the string\n * @return {string} The string with the specified parameters injected\n */\nUtil.format = function(var_args) {\n  var args = Array.prototype.slice.call(arguments, 1);\n  return var_args.replace(/\\{(\\d+)\\}/g, function(m, i) {\n    return args[i];\n  });\n};\n\nUtil.sortByDate = function(a, b) {\n  if (a.updatedDateFull < b.updatedDateFull) {\n    return 1;\n  }\n  if (a.updatedDateFull > b.updatedDateFull) {\n    return -1;\n  }\n  return 0;\n}\n\nUtil.sortByTitle = function(a, b) {\n  if (a.title < b.title) {\n    return 1;\n  }\n  if (a.title > b.title) {\n    return -1;\n  }\n  return 0;\n}\n"
  },
  {
    "path": "_archive/apps/samples/gdrive/main.html",
    "content": "<!DOCTYPE html>\n<!--\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Eric Bidelman (ericbidelman@chromium.org)\n-->\n<html data-ng-app=\"gDriveApp\" ng-csp=\"\">\n<head>\n<meta charset=\"utf-8\" />\n<title>Google Drive Uploader</title>\n<link rel=\"stylesheet\" media=\"all\" href=\"css/bootstrap.css\">\n<link rel=\"stylesheet\" media=\"all\" href=\"css/main.css\">\n<base target=\"_blank\">\n</head>\n<body data-ng-controller=\"DocsController\">\n\n<div id=\"dropper\">\n  <div class=\"dropzone\"><img src=\"img/upload.svg\"></div>\n</div>\n\n<section id=\"main\">\n  <nav>\n    <h2>Google Drive Uploader</h2>\n    <button id=\"authorize-button\" class=\"btn\" data-ng-click=\"toggleAuth(true)\">{{authButtonLabel()}}</button>\n    <button class=\"btn\" data-ng-click=\"fetchDocs(flase)\">Refresh</button>\n    <button class=\"btn\" id=\"close-button\" title=\"Close\">x</button>\n  </nav>\n\n  <progress></progress>\n  <ul>\n    <li data-ng-repeat=\"doc in docs\">\n      <!-- crbug.com/120693. Anchors need target=\"_blank\", but <base> is taking care of this for us :) -->\n      <img data-ng-src=\"{{doc.icon}}\"> <a href=\"{{doc.alternateLink}}\">{{doc.title}}</a>  {{doc.size}}\n      <span class=\"date\">{{doc.updatedDate}}</span>\n    </li>\n  </ul>\n</section>\n\n<script src=\"js/util.js\"></script>\n<script src=\"js/dnd.js\"></script>\n<script src=\"js/upload.js\"></script>\n<script src=\"js/gdocs.js\"></script>\n<script src=\"js/angular-1.1.0.min.js\"></script>\n<script src=\"js/app.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/gdrive/manifest.json",
    "content": "{\n  \"name\": \"Google Drive Sample\",\n  \"version\": \"0.0.5\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"29\",\n  \"oauth2\": {\n    \"client_id\": \"696763237280-bkfouv0030la6l9t2g1elim04no836fq.apps.googleusercontent.com\",\n    \"scopes\": [\n      \"https://www.googleapis.com/auth/drive\"\n    ]\n  },\n  \"icons\": {\n    \"128\": \"icon_128.png\"\n  },\n  \"key\": \"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCXaBUTn1PNjYo8fg+1JBmWBA3bdrn7siqzkY0tYeuNHIWi5ji+6V5Y3QWYRFQh3AFwrZaBItvaM3fsit7K++kDoD67VhYGrGd+mjl4Htmp+/HbzzCQMBJdTdTOvR722+VHmIttzbe/I7GB3a74KvPYfUENONj1tswyKkuXeMgFOQIDAQAB\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"js/background.js\"]\n    }\n  },\n  \"permissions\": [\n    \"identity\",\n    \"https://ssl.gstatic.com/\",\n    \"https://www.googleapis.com/\",\n    \"https://accounts.google.com/\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/github-auth/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/laolmfhjaobpboigjfbclcphckmjodlp\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# GitHub Auth\n\nA sample application that uses the\n[Identity API](https://developer.chrome.com/apps/identity) to\nrequest identification information about the user's GitHub account. After user\nlogs on to GitHub and authorizes the application to use their information, both\nusers name and email address (if available) will be displayed.\n\nThis app uses the launchWebAuthFlow flow of the Identity API, which is enabling\nauthorization with providers other than Google. For autorization using Google\nAccount check out the [Identity sample application](../identity).\n\n## APIs\n\n* [Identity](https://developer.chrome.com/apps/identity)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/github-auth/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/github-auth/index.html",
    "content": "<html>\n  <head>\n    <script src=\"index.js\"></script>\n  </head>\n  <body>\n    <div id=\"user_info\"></div>\n    <button id=\"signin\" style=\"display:none\">Sign in</button>\n    <button id=\"revoke\" style=\"display:none\">Revoke token</button>\n    <br><b>Your repos:</b> <br>\n    <textarea id=\"user_repos\" style=\"width: 95%; min-height: 200px\"></textarea>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/github-auth/index.js",
    "content": "var gh = (function() {\n  'use strict';\n\n  var signin_button;\n  var revoke_button;\n  var user_info_div;\n\n  var tokenFetcher = (function() {\n    // Replace clientId and clientSecret with values obtained by you for your\n    // application https://github.com/settings/applications.\n    var clientId = '11442b0924c8d6a98fb7';\n    // Note that in a real-production app, you may not want to store\n    // clientSecret in your App code.\n    var clientSecret = 'a1499b1a5780c8a21ed560b839741e803c4cc936';\n    var redirectUri = chrome.identity.getRedirectURL('provider_cb');\n    var redirectRe = new RegExp(redirectUri + '[#\\?](.*)');\n\n    var access_token = null;\n\n    return {\n      getToken: function(interactive, callback) {\n        // In case we already have an access_token cached, simply return it.\n        if (access_token) {\n          callback(null, access_token);\n          return;\n        }\n\n        var options = {\n          'interactive': interactive,\n          'url': 'https://github.com/login/oauth/authorize' +\n                 '?client_id=' + clientId +\n                 '&redirect_uri=' + encodeURIComponent(redirectUri)\n        }\n        chrome.identity.launchWebAuthFlow(options, function(redirectUri) {\n          console.log('launchWebAuthFlow completed', chrome.runtime.lastError,\n              redirectUri);\n\n          if (chrome.runtime.lastError) {\n            callback(new Error(chrome.runtime.lastError));\n            return;\n          }\n\n          // Upon success the response is appended to redirectUri, e.g.\n          // https://{app_id}.chromiumapp.org/provider_cb#access_token={value}\n          //     &refresh_token={value}\n          // or:\n          // https://{app_id}.chromiumapp.org/provider_cb#code={value}\n          var matches = redirectUri.match(redirectRe);\n          if (matches && matches.length > 1)\n            handleProviderResponse(parseRedirectFragment(matches[1]));\n          else\n            callback(new Error('Invalid redirect URI'));\n        });\n\n        function parseRedirectFragment(fragment) {\n          var pairs = fragment.split(/&/);\n          var values = {};\n\n          pairs.forEach(function(pair) {\n            var nameval = pair.split(/=/);\n            values[nameval[0]] = nameval[1];\n          });\n\n          return values;\n        }\n\n        function handleProviderResponse(values) {\n          console.log('providerResponse', values);\n          if (values.hasOwnProperty('access_token'))\n            setAccessToken(values.access_token);\n          // If response does not have an access_token, it might have the code,\n          // which can be used in exchange for token.\n          else if (values.hasOwnProperty('code'))\n            exchangeCodeForToken(values.code);\n          else \n            callback(new Error('Neither access_token nor code avialable.'));\n        }\n\n        function exchangeCodeForToken(code) {\n          var xhr = new XMLHttpRequest();\n          xhr.open('GET',\n                   'https://github.com/login/oauth/access_token?' +\n                   'client_id=' + clientId +\n                   '&client_secret=' + clientSecret +\n                   '&redirect_uri=' + redirectUri +\n                   '&code=' + code);\n          xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\n          xhr.setRequestHeader('Accept', 'application/json');\n          xhr.onload = function () {\n            // When exchanging code for token, the response comes as json, which\n            // can be easily parsed to an object.\n            if (this.status === 200) {\n              var response = JSON.parse(this.responseText);\n              console.log(response);\n              if (response.hasOwnProperty('access_token')) {\n                setAccessToken(response.access_token);\n              } else {\n                callback(new Error('Cannot obtain access_token from code.'));\n              }\n            } else {\n              console.log('code exchange status:', this.status);\n              callback(new Error('Code exchange failed'));\n            }\n          };\n          xhr.send();\n        }\n\n        function setAccessToken(token) {\n          access_token = token; \n          console.log('Setting access_token: ', access_token);\n          callback(null, access_token);\n        }\n      },\n\n      removeCachedToken: function(token_to_remove) {\n        if (access_token == token_to_remove)\n          access_token = null;\n      }\n    }\n  })();\n\n  function xhrWithAuth(method, url, interactive, callback) {\n    var retry = true;\n    var access_token;\n\n    console.log('xhrWithAuth', method, url, interactive);\n    getToken();\n\n    function getToken() {\n      tokenFetcher.getToken(interactive, function(error, token) {\n        console.log('token fetch', error, token);\n        if (error) {\n          callback(error);\n          return;\n        }\n\n        access_token = token;\n        requestStart();\n      });\n    }\n\n    function requestStart() {\n      var xhr = new XMLHttpRequest();\n      xhr.open(method, url);\n      xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);\n      xhr.onload = requestComplete;\n      xhr.send();\n    }\n\n    function requestComplete() {\n      console.log('requestComplete', this.status, this.response);\n      if ( ( this.status < 200 || this.status >=300 ) && retry) {\n        retry = false;\n        tokenFetcher.removeCachedToken(access_token);\n        access_token = null;\n        getToken();\n      } else {\n        callback(null, this.status, this.response);\n      }\n    }\n  }\n\n  function getUserInfo(interactive) {\n    xhrWithAuth('GET',\n                'https://api.github.com/user',\n                interactive,\n                onUserInfoFetched);\n  }\n\n  // Functions updating the User Interface:\n\n  function showButton(button) {\n    button.style.display = 'inline';\n    button.disabled = false;\n  }\n\n  function hideButton(button) {\n    button.style.display = 'none';\n  }\n\n  function disableButton(button) {\n    button.disabled = true;\n  }\n\n  function onUserInfoFetched(error, status, response) {\n    if (!error && status == 200) {\n      console.log(\"Got the following user info: \" + response);\n      var user_info = JSON.parse(response);\n      populateUserInfo(user_info);\n      hideButton(signin_button);\n      showButton(revoke_button);\n      fetchUserRepos(user_info[\"repos_url\"]);\n    } else {\n      console.log('infoFetch failed', error, status);\n      showButton(signin_button);\n    }\n  }\n\n  function populateUserInfo(user_info) {\n    var elem = user_info_div;\n    var nameElem = document.createElement('div');\n    nameElem.innerHTML = \"<b>Hello \" + user_info.name + \"</b><br>\"\n    \t+ \"Your github page is: \" + user_info.html_url;\n    elem.appendChild(nameElem);\n  }\n\n\n\n  function fetchUserRepos(repoUrl) {\n    xhrWithAuth('GET', repoUrl, false, onUserReposFetched);\n  }\n\n  function onUserReposFetched(error, status, response) {\n    var elem = document.querySelector('#user_repos');\n    elem.value='';\n    if (!error && status == 200) {\n      console.log(\"Got the following user repos:\", response);\n      var user_repos = JSON.parse(response);\n      user_repos.forEach(function(repo) {\n        if (repo.private) {\n          elem.value += \"[private repo]\";\n        } else {\n          elem.value += repo.name;\n        }\n        elem.value += '\\n';\n      });\n    } else {\n      console.log('infoFetch failed', error, status);\n    }\n    \n  }\n\n  // Handlers for the buttons's onclick events.\n\n  function interactiveSignIn() {\n    disableButton(signin_button);\n    tokenFetcher.getToken(true, function(error, access_token) {\n      if (error) {\n        showButton(signin_button);\n      } else {\n        getUserInfo(true);\n      }\n    });\n  }\n\n  function revokeToken() {\n    // We are opening the web page that allows user to revoke their token.\n    window.open('https://github.com/settings/applications');\n    // And then clear the user interface, showing the Sign in button only.\n    // If the user revokes the app authorization, they will be prompted to log\n    // in again. If the user dismissed the page they were presented with,\n    // Sign in button will simply sign them in.\n    user_info_div.textContent = '';\n    hideButton(revoke_button);\n    showButton(signin_button);\n  }\n\n  return {\n    onload: function () {\n      signin_button = document.querySelector('#signin');\n      signin_button.onclick = interactiveSignIn;\n\n      revoke_button = document.querySelector('#revoke');\n      revoke_button.onclick = revokeToken;\n\n      user_info_div = document.querySelector('#user_info');\n\n      console.log(signin_button, revoke_button, user_info_div);\n\n      showButton(signin_button);\n      getUserInfo(false);\n    }\n  };\n})();\n\n\nwindow.onload = gh.onload;\n"
  },
  {
    "path": "_archive/apps/samples/github-auth/main.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', \n    { \"innerBounds\": { \"width\": 400, \"height\": 300 },\n      \"id\": \"index\"\n    });\n});\n"
  },
  {
    "path": "_archive/apps/samples/github-auth/manifest.json",
    "content": "{\n  \"name\": \"GitHub Auth Sample\",\n  \"version\": \"3.1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"33\",\n  \"key\": \"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCXZ6+N4gRLyUUtj79Z3TClsrA32yU9ekkdKXlGylaRhtjMNLN+oBekfDsBfASdkGu35r48v+GiHgCTeySFgm/MfOBavutudcr1Cm/+CD6Y7XSQBMHQn06sJgsMk0eG6FcP797Ofig2MHmouaoHCPfpmXfcbgZZYioh29PWJ6oq7QIDAQAB\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"identity\",\n    \"https://github.com/\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/hello-world/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/nmfpplkdkcbhediajmbhljkafnlahcda\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Hello World\n\nThis is a starter application. It contains a basic manifest file with no\nadditional permissions. The manifest denotes a background script, main.js,\ndetailed below:\n\n```javascript\nchrome.app.runtime.onLaunched.addListener(function() {\n  // Center window on screen.\n  var screenWidth = screen.availWidth;\n  var screenHeight = screen.availHeight;\n  var width = 500;\n  var height = 300;\n\n  chrome.app.window.create('index.html', {\n    id: \"helloWorldID\",\n    outerBounds: {\n      width: width,\n      height: height,\n      left: Math.round((screenWidth-width)/2),\n      top: Math.round((screenHeight-height)/2)\n    }\n  });\n});\n```\n\nThis simply waits for the launch event for the application (`chrome.app.runtime.onLaunched.addListener`)\nand, at that point, creates a window using a basic HTML page, index.html, as the source.\n\n## Resources\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/hello-world/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/hello-world/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <title>Hello World</title>\n    <link href=\"styles/main.css\" rel=\"stylesheet\">\n</head>\n<body>\n    <h1>Hello, World!</h1>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/hello-world/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  // Center window on screen.\n  var screenWidth = screen.availWidth;\n  var screenHeight = screen.availHeight;\n  var width = 500;\n  var height = 300;\n\n  chrome.app.window.create('index.html', {\n    id: \"helloWorldID\",\n    outerBounds: {\n      width: width,\n      height: height,\n      left: Math.round((screenWidth-width)/2),\n      top: Math.round((screenHeight-height)/2)\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/hello-world/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Hello World\",\n  \"version\": \"2.1\",\n  \"minimum_chrome_version\": \"23\",\n  \"icons\": {\n    \"16\": \"icon_16.png\",\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/hello-world/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"hello-world\",\n  \"files_with_snippets\": [ ],\n  \"android\": {\"works\": true},\n  \"ios\": {\"works\": true}\n}\n"
  },
  {
    "path": "_archive/apps/samples/hello-world/styles/main.css",
    "content": "html, body {\n  height: 100%;\n}\n\nbody {\n  background-position: center center;\n  background-repeat: no-repeat;\n  background-image: url(\"../hello_world.png\"), -webkit-radial-gradient(center, ellipse cover,#FFFFFF 0%,#FAFAFA 50%,#F5F5F5 60%,#BEBEBE 100%);\n  margin: 0;\n  padding: 0;\n}\n\nh1 {\n  position: absolute;\n  bottom: 20px;\n  text-align: center;\n  width: 100%;\n  line-height: 120%;\n  font-family: Arial, sans-serif;\n  color: rgb(66,66,66);\n  letter-spacing: -0.05em;\n}\n"
  },
  {
    "path": "_archive/apps/samples/hello-world-sync/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ajjcafkkflbcealbcfjajolnkogffgcb\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Hello World storage.sync\n\nUse chrome.storage.sync to share small chunks of data among all of your Chrome devices. To test, open this app in two different devices, both signed in with the same user.\n\nImportant: needs \"key\" in manifest.json to support testing outside of CWS, so that sync storage is shared among different instances.\n\n\n    // app.js\n    chrome.storage.sync.set({\"myValue\": newValue}, mycallback);\n    ...\n    chrome.storage.onChanged.addListener(\n      function(changes, namespace) {\n        // do something\n      }\n    );\n    ...\n    chrome.storage.sync.get(\"myValue\",\n      function(val) {\n        // do something\n      }\n    );\n\n## APIs\n\n* [Storage sync](http://developer.chrome.com/extensions/storage)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/hello-world-sync/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/hello-world-sync/app.js",
    "content": "(function(){\n  var output = document.getElementById('output');\n  var input = document.getElementById('myValue');\n  var form = document.querySelector('form');\n  var logarea = document.querySelector('textarea');\n\n  function log(str) {\n    logarea.value=str+\"\\n\"+logarea.value;\n  }\n  \n  form.addEventListener('submit', function(ev) {\n    var newValue=input.value;\n    chrome.storage.sync.set({\"myValue\": newValue}, function() {\n      log(\"setting myValue to \"+newValue);\n    });\n    ev.preventDefault();\n  });\n\n  function valueChanged(newValue) {\n    output.innerText = newValue;\n    output.className=\"changed\";\n    window.setTimeout(function() {output.className=\"\";}, 200);\n    log(\"value myValue changed to \"+newValue);\n  }\n\n  // For debugging purposes:\n  function debugChanges(changes, namespace) {\n    for (key in changes) {\n      console.log('Storage change: key='+key+' value='+JSON.stringify(changes[key]));\n    }\n  }  \n\n  chrome.storage.onChanged.addListener(function(changes, namespace) {\n    if (changes[\"myValue\"]) {\n      valueChanged(changes[\"myValue\"].newValue);\n    }\n    debugChanges(changes, namespace);\n  });\n\n  chrome.storage.sync.get(\"myValue\", function(val) {valueChanged(val.myValue)});\n\n})();\n"
  },
  {
    "path": "_archive/apps/samples/hello-world-sync/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n</head>\n<body>\n    <h1>Syncable storage</h1>\n    <small>Use chrome.storage.sync to share small chunks of data among all of your Chrome devices. To test, open this app in two different devices, both signed in with the same user.</small>\n    <p>This is the current value in the storage:</p>\n    <div id=\"output\"></div>\n    <form>\n      <label>Want to change it?</label>\n      <input name=\"myValue\" id=\"myValue\" />\n      <input type=\"submit\" value=\"change\"></input>\n    </form>\n    <textarea id=\"log\"></textarea>\n    <script src=\"app.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/hello-world-sync/main.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n  \tid: \"helloWorldSyncID\",\n    innerBounds: {\n      width: 500,\n      height: 415\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/hello-world-sync/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"version\": \"2\",\n  \"name\": \"Syncable storage sample\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\"storage\"],\n\n  \"key\": \"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwhGKZ4KMgoHDmBGs+BrYueDkiiPAt7QjHbcxeNs3JBaPah/nNsz8e4E38TeEKNyHg+0DoVQlV6gvmuXy/bAbpCBSk3/y+/J5TFCjSgVLhm7nQPeE3RIR2/kVZIaY1YIabxqdC4N0RmAef+EBR+WB4RqFsV78TpzgpNqDinkhfPwIDAQAB\"\n}\n"
  },
  {
    "path": "_archive/apps/samples/hello-world-sync/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"hello-world-sync\",\n  \"files_with_snippets\": [ ],\n  \"android\": {\"works\": true, \"comments\": \"sync storage doesn't actually sync - works local\"},\n  \"ios\": {\"works\": true, \"comments\": \"sync storage doesn't actually sync - works local\"}\n}\n"
  },
  {
    "path": "_archive/apps/samples/hello-world-sync/style.css",
    "content": "\nbody {\n  font-family: Arial, sans-serif;\n}\n\n\n#output {\n\twidth: 200px;\n\tpadding: 5px 3px;\n\tborder: 1px dotted #666;\n\tmargin: 10px 0px;\n\tbackground-color: #def;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n\toverflow: hidden;\n\t-webkit-transition: background-color 0.8s ease-out 0.2s;\n}\n\n#output.changed {\n\tbackground-color: #fef;\n\t-webkit-transition: none;\n}\n\ntextarea {\n\twidth: 100%;\n\theight: 100px;\n\tmargin: 20px 0;\n\tborder: 1px solid #999;\n\tcolor: #666;\n}\n"
  },
  {
    "path": "_archive/apps/samples/hid/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ohndmecdhlgohpibepbboddcoecomnpc\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\nchrome.hid API Sample\n=====================\n\nThis sample demonstrates usage of the `chrome.hid` API.\n\n## APIs\n\n* [HID](https://developer.chrome.com/apps/hid)\n* [Runtime](https://developer.chrome.com/apps/runtime)\n* [Window](https://developer.chrome.com/apps/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/hid/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/hid/control-panel.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <link rel=\"stylesheet\" href=\"style.css\">\n    <script src=\"control-panel.js\"></script>\n  </head>\n  <body>\n    <div id=\"device-panel\">\n      <select id=\"device-selector\"></select>\n      <button id=\"connect\">Connect</button>\n      <button id=\"disconnect\">Disconnect</button>\n      <button id=\"add-device\">Add Device...</button>\n    </div>\n    <div id=\"output-panel\">\n      <h3>OUTPUT</h3>\n      <label>Report ID (0 for none):</label>\n      <input type=\"number\" id=\"out-id\" min=\"0\" max=\"255\" value=\"1\">\n      <br>\n      <label>Report Contents (ASCII; you may use \\xNN to escape bytes):</label><br>\n      <input id=\"out-data\" value=\"\" size=\"68\" style=\"width:100%\"><br>\n      <label>Report Size (bytes, not including report ID):</label>\n      <input type=\"number\" id=\"out-size\" min=\"0\" max=\"64\" value=\"63\"><br>\n      <label>Report Padding Byte<br>\n        (appended to |contents| up to |size| bytes):<br></label>\n      <input type=\"number\" id=\"out-pad\" min=\"0\" max=\"255\" value=\"0\"><br>\n      <button id=\"send\">Send Report</button>\n    </div>\n    <div id=\"input-panel\">\n      <h3>INPUT</h3>\n      <label>Expected Report Size</label>\n      <input type=\"number\" id=\"in-size\" value=\"64\" min=\"1\" max=\"64\"><br>\n      <label>Poll?</label>\n      <input type=\"checkbox\" id=\"in-poll\"><br>\n      <label>Input Log:</label><br>\n      <textarea id=\"input-log\" style=\"width:100%\" rows=\"20\" readonly></textarea><br>\n      <button id=\"receive\">Read Report (cancels polling)</button>\n      <button id=\"clear\">Clear Log</button>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/hid/control-panel.js",
    "content": "(function() {\n  var ui = {\n    deviceSelector: null,\n    connect: null,\n    disconnect: null,\n    addDevice: null,\n    outId: null,\n    outData: null,\n    outSize: null,\n    outPad: null,\n    send: null,\n    inSize: null,\n    inPoll: null,\n    inputLog: null,\n    receive: null,\n    clear: null,\n  };\n\n  var connection = -1;\n\n  var initializeWindow = function() {\n    for (var k in ui) {\n      var id = k.replace(/([A-Z])/, '-$1').toLowerCase();\n      var element = document.getElementById(id);\n      if (!element) {\n        throw \"Missing UI element: \" + k;\n      }\n      ui[k] = element;\n    }\n    enableIOControls(false);\n    ui.connect.addEventListener('click', onConnectClicked);\n    ui.disconnect.addEventListener('click', onDisconnectClicked);\n    ui.addDevice.addEventListener('click', onAddDeviceClicked);\n    ui.send.addEventListener('click', onSendClicked);\n    ui.inPoll.addEventListener('change', onPollToggled);\n    ui.receive.addEventListener('click', onReceiveClicked);\n    ui.clear.addEventListener('click', onClearClicked);\n    enumerateDevices();\n  };\n\n  var enableIOControls = function(ioEnabled) {\n    ui.deviceSelector.disabled = ioEnabled;\n    ui.connect.style.display = ioEnabled ? 'none' : 'inline';\n    ui.disconnect.style.display = ioEnabled ? 'inline' : 'none';\n    ui.inPoll.disabled = !ioEnabled;\n    ui.send.disabled = !ioEnabled;\n    ui.receive.disabled = !ioEnabled;\n  };\n\n  var enumerateDevices = function() {\n    chrome.hid.getDevices({}, onDevicesEnumerated);\n    chrome.hid.onDeviceAdded.addListener(onDeviceAdded);\n    chrome.hid.onDeviceRemoved.addListener(onDeviceRemoved);\n  };\n\n  var onDevicesEnumerated = function(devices) {\n    if (chrome.runtime.lastError) {\n      console.error(\"Unable to enumerate devices: \" +\n                    chrome.runtime.lastError.message);\n      return;\n    }\n\n    for (var device of devices) {\n      onDeviceAdded(device);\n    }\n  }\n\n  var onDeviceAdded = function(device) {\n    var optionId = 'device-' + device.deviceId;\n    if (ui.deviceSelector.namedItem(optionId)) {\n      return;\n    }\n\n    var selectedIndex = ui.deviceSelector.selectedIndex;\n    var option = document.createElement('option');\n    option.text = \"Device #\" + device.deviceId + \" [\" +\n                  device.vendorId.toString(16) + \":\" +\n                  device.productId.toString(16) + \"]\";\n    option.id = optionId;\n    ui.deviceSelector.options.add(option);\n    if (selectedIndex != -1) {\n      ui.deviceSelector.selectedIndex = selectedIndex;\n    }\n  };\n\n  var onDeviceRemoved = function(deviceId) {\n    var option = ui.deviceSelector.options.namedItem('device-' + deviceId);\n    if (!option) {\n      return;\n    }\n\n    if (option.selected) {\n      onDisconnectClicked();\n    }\n    ui.deviceSelector.remove(option.index);\n  };\n\n  var onConnectClicked = function() {\n    var selectedItem = ui.deviceSelector.options[ui.deviceSelector.selectedIndex];\n    if (!selectedItem) {\n      return;\n    }\n    var deviceId = parseInt(selectedItem.id.substr('device-'.length), 10);\n    if (!deviceId) {\n      return;\n    }\n    chrome.hid.connect(deviceId, function(connectInfo) {\n      if (!connectInfo) {\n        console.warn(\"Unable to connect to device.\");\n      }\n      connection = connectInfo.connectionId;\n      enableIOControls(true);\n    });\n  };\n\n  var onDisconnectClicked = function() {\n    if (connection === -1)\n      return;\n    chrome.hid.disconnect(connection, function() {\n      connection = -1;\n    });\n    enableIOControls(false);\n  };\n\n  var onAddDeviceClicked = function() {\n    chrome.hid.getUserSelectedDevices({ 'multiple': false },\n        function(devices) {\n      if (chrome.runtime.lastError != undefined) {\n        console.warn('chrome.hid.getUserSelectedDevices error: ' +\n                     chrome.runtime.lastError.message);\n        return;\n      }\n      for (var device of devices) {\n        onDeviceAdded(device);\n      }\n    });\n  };\n\n  var onSendClicked = function() {\n    var id = +ui.outId.value;\n    var bytes = new Uint8Array(+ui.outSize.value);\n    var contents = ui.outData.value;\n    contents = contents.replace(/\\\\x([a-fA-F0-9]{2})/g, function(match, capture) {\n      return String.fromCharCode(parseInt(capture, 16));\n    });\n    for (var i = 0; i < contents.length && i < bytes.length; ++i) {\n      if (contents.charCodeAt(i) > 255) {\n        throw \"I am not smart enough to decode non-ASCII data.\";\n      }\n      bytes[i] = contents.charCodeAt(i);\n    }\n    var pad = +ui.outPad.value;\n    for (var i = contents.length; i < bytes.length; ++i) {\n      bytes[i] = pad;\n    }\n    ui.send.disabled = true;\n    chrome.hid.send(connection, id, bytes.buffer, function() {\n      ui.send.disabled = false;\n    });\n  };\n\n  var isReceivePending = false;\n  var pollForInput = function() {\n    var size = +ui.inSize.value;\n    isReceivePending = true;\n    chrome.hid.receive(connection, function(reportId, data) {\n      isReceivePending = false;\n      logInput(new Uint8Array(data));\n      if (ui.inPoll.checked) {\n        setTimeout(pollForInput, 0);\n      }\n    });\n  };\n\n  var enablePolling = function(pollEnabled) {\n    ui.inPoll.checked = pollEnabled;\n    if (pollEnabled && !isReceivePending) {\n      pollForInput();\n    }\n  };\n\n  var onPollToggled = function() {\n    enablePolling(ui.inPoll.checked);\n  };\n\n  var onReceiveClicked = function() {\n    enablePolling(false);\n    if (!isReceivePending) {\n      pollForInput();\n    }\n  };\n\n  var byteToHex = function(value) {\n    if (value < 16)\n      return '0' + value.toString(16);\n    return value.toString(16);\n  };\n\n  var logInput = function(bytes) {\n    var log = '';\n    for (var i = 0; i < bytes.length; i += 16) {\n      var sliceLength = Math.min(bytes.length - i, 16);\n      var lineBytes = new Uint8Array(bytes.buffer, i, sliceLength);\n      for (var j = 0; j < lineBytes.length; ++j) {\n        log += byteToHex(lineBytes[j]) + ' ';\n      }\n      for (var j = 0; j < lineBytes.length; ++j) {\n        var ch = String.fromCharCode(lineBytes[j]);\n        if (lineBytes[j] < 32 || lineBytes[j] > 126)\n          ch = '.';\n        log += ch;\n      }\n      log += '\\n';\n    }\n    log += \"================================================================\\n\";\n    ui.inputLog.textContent += log;\n    ui.inputLog.scrollTop = ui.inputLog.scrollHeight;\n  };\n\n  var onClearClicked = function() {\n    ui.inputLog.textContent = \"\";\n  };\n\n  window.addEventListener('load', initializeWindow);\n}());\n"
  },
  {
    "path": "_archive/apps/samples/hid/main.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create(\n      \"control-panel.html\",\n      {\n        innerBounds: { width: 1060, height: 510, minWidth: 1060 }\n      });\n});\n\n"
  },
  {
    "path": "_archive/apps/samples/hid/manifest.json",
    "content": "{\n  \"name\": \"HID Sample App\",\n  \"manifest_version\": 2,\n  \"version\": \"0.3.2\",\n  \"minimum_chrome_version\": \"45.0.2439.3\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [ \"main.js\" ]\n    }\n  },\n  \"permissions\": [ \"hid\" ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/hid/style.css",
    "content": "body {\n  font-family: monospace;\n  font-size: 10pt;\n  display: flex;\n  flex-flow: row wrap;\n}\n\ndiv {\n  padding: 8px;\n  flex: 1 100%;\n}\n\n#output-panel,\n#input-panel {\n  flex: 1 0;\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/identity/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/oficlfehfenioickohognhdhmmcpceil\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Identity\n\nA sample application that uses the\n[Identity API](https://developer.chrome.com/apps/identity.html) to\nrequest information of the logged in user and present this info on the screen.\nIf the user has a profile picture, an XMLHttpRequest request is also sent to\ngrab the image and show it in the app.\n\nThis app uses the getAuthToken flow of the Identity API, so it only works with\nGoogle accounts. If you want to identify the user in a non-Google OAuth2 flow,\nyou should use the launchWebAuthFlow method instead.\n\n## APIs\n\n* [Identity](https://developer.chrome.com/docs/apps/app_identity/)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/identity/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/identity/identity.js",
    "content": "'use strict';\n\nvar googleProfileUserLoader = (function() {\n\n  var STATE_START=1;\n  var STATE_ACQUIRING_AUTHTOKEN=2;\n  var STATE_AUTHTOKEN_ACQUIRED=3;\n\n  var state = STATE_START;\n\n  var signin_button, xhr_button, revoke_button, user_info_div;\n\n function disableButton(button) {\n    button.setAttribute('disabled', 'disabled');\n  }\n\n  function enableButton(button) {\n    button.removeAttribute('disabled');\n  }\n\n  function changeState(newState) {\n    state = newState;\n    switch (state) {\n      case STATE_START:\n        enableButton(signin_button);\n        disableButton(xhr_button);\n        disableButton(revoke_button);\n        break;\n      case STATE_ACQUIRING_AUTHTOKEN:\n        sampleSupport.log('Acquiring token...');\n        disableButton(signin_button);\n        disableButton(xhr_button);\n        disableButton(revoke_button);\n        break;\n      case STATE_AUTHTOKEN_ACQUIRED:\n        disableButton(signin_button);\n        enableButton(xhr_button);\n        enableButton(revoke_button);\n        break;\n    }\n  }\n\n  // @corecode_begin getProtectedData\n  function xhrWithAuth(method, url, interactive, callback) {\n    var access_token;\n\n    var retry = true;\n\n    getToken();\n\n    function getToken() {\n      chrome.identity.getAuthToken({ interactive: interactive }, function(token) {\n        if (chrome.runtime.lastError) {\n          callback(chrome.runtime.lastError);\n          return;\n        }\n\n        access_token = token;\n        requestStart();\n      });\n    }\n\n    function requestStart() {\n      var xhr = new XMLHttpRequest();\n      xhr.open(method, url);\n      xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);\n      xhr.onload = requestComplete;\n      xhr.send();\n    }\n\n    function requestComplete() {\n      if (this.status == 401 && retry) {\n        retry = false;\n        chrome.identity.removeCachedAuthToken({ token: access_token },\n                                              getToken);\n      } else {\n        callback(null, this.status, this.response);\n      }\n    }\n  }\n\n  function getUserInfo(interactive) {\n    xhrWithAuth('GET',\n                'https://www.googleapis.com/oauth2/v1/userinfo',\n                interactive,\n                onUserInfoFetched);\n  }\n  // @corecode_end getProtectedData\n\n\n  // Code updating the user interface, when the user information has been\n  // fetched or displaying the error.\n  function onUserInfoFetched(error, status, response) {\n    if (!error && status == 200) {\n      changeState(STATE_AUTHTOKEN_ACQUIRED);\n      sampleSupport.log(response);\n      var user_info = JSON.parse(response);\n      populateUserInfo(user_info);\n    } else {\n      changeState(STATE_START);\n    }\n  }\n\n  function populateUserInfo(user_info) {\n    user_info_div.innerHTML = \"Hello \" + user_info.name;\n    fetchImageBytes(user_info);\n  }\n\n  function fetchImageBytes(user_info) {\n    if (!user_info || !user_info.picture) return;\n    var xhr = new XMLHttpRequest();\n    xhr.open('GET', user_info.picture, true);\n    xhr.responseType = 'blob';\n    xhr.onload = onImageFetched;\n    xhr.send();\n  }\n\n  function onImageFetched(e) {\n    if (this.status != 200) return;\n    var imgElem = document.createElement('img');\n    var objUrl = window.URL.createObjectURL(this.response);\n    imgElem.src = objUrl;\n    imgElem.style.width = '24px';\n    imgElem.onload = function() {\n      window.URL.revokeObjectURL(objUrl);\n    }\n    user_info_div.insertAdjacentElement(\"afterbegin\", imgElem);\n  }\n\n  // OnClick event handlers for the buttons.\n\n  /**\n    Retrieves a valid token. Since this is initiated by the user\n    clicking in the Sign In button, we want it to be interactive -\n    ie, when no token is found, the auth window is presented to the user.\n\n    Observe that the token does not need to be cached by the app.\n    Chrome caches tokens and takes care of renewing when it is expired.\n    In that sense, getAuthToken only goes to the server if there is\n    no cached token or if it is expired. If you want to force a new\n    token (for example when user changes the password on the service)\n    you need to call removeCachedAuthToken()\n  **/\n  function interactiveSignIn() {\n    changeState(STATE_ACQUIRING_AUTHTOKEN);\n\n    // @corecode_begin getAuthToken\n    // @description This is the normal flow for authentication/authorization\n    // on Google properties. You need to add the oauth2 client_id and scopes\n    // to the app manifest. The interactive param indicates if a new window\n    // will be opened when the user is not yet authenticated or not.\n    // @see http://developer.chrome.com/apps/app_identity.html\n    // @see http://developer.chrome.com/apps/identity.html#method-getAuthToken\n    chrome.identity.getAuthToken({ 'interactive': true }, function(token) {\n      if (chrome.runtime.lastError) {\n        sampleSupport.log(chrome.runtime.lastError);\n        changeState(STATE_START);\n      } else {\n        sampleSupport.log('Token acquired:'+token+\n          '. See chrome://identity-internals for details.');\n        changeState(STATE_AUTHTOKEN_ACQUIRED);\n      }\n    });\n    // @corecode_end getAuthToken\n  }\n\n  function revokeToken() {\n    user_info_div.innerHTML=\"\";\n    chrome.identity.getAuthToken({ 'interactive': false },\n      function(current_token) {\n        if (!chrome.runtime.lastError) {\n\n          // @corecode_begin removeAndRevokeAuthToken\n          // @corecode_begin removeCachedAuthToken\n          // Remove the local cached token\n          chrome.identity.removeCachedAuthToken({ token: current_token },\n            function() {});\n          // @corecode_end removeCachedAuthToken\n\n          // Make a request to revoke token in the server\n          var xhr = new XMLHttpRequest();\n          xhr.open('GET', 'https://accounts.google.com/o/oauth2/revoke?token=' +\n                   current_token);\n          xhr.send();\n          // @corecode_end removeAndRevokeAuthToken\n\n          // Update the user interface accordingly\n          changeState(STATE_START);\n          sampleSupport.log('Token revoked and removed from cache. '+\n            'Check chrome://identity-internals to confirm.');\n        }\n    });\n  }\n\n  return {\n    onload: function () {\n      signin_button = document.querySelector('#signin');\n      signin_button.addEventListener('click', interactiveSignIn);\n\n      xhr_button = document.querySelector('#getxhr');\n      xhr_button.addEventListener('click', getUserInfo.bind(xhr_button, true));\n\n      revoke_button = document.querySelector('#revoke');\n      revoke_button.addEventListener('click', revokeToken);\n\n      user_info_div = document.querySelector('#user_info');\n\n      // Trying to get user's info without signing in, it will work if the\n      // application was previously authorized by the user.\n      getUserInfo(false);\n    }\n  };\n\n})();\n\nwindow.onload = googleProfileUserLoader.onload;\n\n"
  },
  {
    "path": "_archive/apps/samples/identity/index.html",
    "content": "<html>\n  <head>\n    <title>Identity API Sample App</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"sample_support/standard.css\">\n    <script src=\"identity.js\"></script>\n    <script src=\"sample_support/sample_support.js\"></script>\n  </head>\n  <body>\n    <div class=\"header\">\n      <h1>Identity API</h1>\n      <div class=\"links\">\n        Learn more:\n          <a target=\"_blank\" href=\"http://developer.chrome.com/apps/app_identity.html\">API docs</a>\n          <a id=\"_open_snippets\" href=\"#\">Source</a>\n      </div>\n      <hr>\n    </div>\n    <div class=\"flows\">\n      <h2>OAuth on Google properties</h2>\n      <div class=\"flow\">\n        <button id=\"signin\">Sign in</button>\n        <button id=\"getxhr\" disabled>Get personal data</button>\n        <button id=\"revoke\" disabled>Revoke token</button>\n        <div id=\"user_info\"></div>\n      </div>\n    </div>\n   <div class=\"log\">\n      <textarea id=\"__sample_support_logarea\" disabled></textarea>\n   </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/identity/main.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html',\n    { \"id\": \"identitywin\",\n      \"innerBounds\": {\n        \"width\": 454,\n        \"height\": 540\n      }\n    });\n});\n"
  },
  {
    "path": "_archive/apps/samples/identity/manifest.json",
    "content": "{\n  \"name\": \"Identity API Sample\",\n  \"version\": \"3.2\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"29\",\n  \"key\": \"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDJB6ZGcGxtlr/34s+TKgi84QiP7DMekqOjSUS2ubmbhchlM6CN9gYdGQ1aBI3TBXG3YaAu+XyutFA8M8NLLWc4OOGByWaGV11DP6p67g8a+Ids/gX6cNSRnRHiDZXAd44ATxoN4OZjZJk9iQ26RIUjwX07bzntlI+frwwKCk4WQIDAQAB\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\"identity\", \"https://accounts.google.com/*\", \"https://www.googleapis.com/*\"],\n  \"oauth2\": {\n    // client_id below is specific to the application key. Follow the\n    // documentation to obtain one for your app.\n    \"client_id\": \"497291774654.apps.googleusercontent.com\",\n    \"scopes\": [\"https://www.googleapis.com/auth/userinfo.profile\"]\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/identity/sample_support/README.md",
    "content": "ATTENTION contributors: this directory (sample_support) should not be changed.\nIt is automatically updated and should not contain anything that is specific\nto this sample."
  },
  {
    "path": "_archive/apps/samples/identity/sample_support/google-code-prettify/lang-css.js",
    "content": "PR.registerLangHandler(PR.createSimpleLexer([[\"pln\",/^[\\t\\n\\f\\r ]+/,null,\" \\t\\r\\n\\u000c\"]],[[\"str\",/^\"(?:[^\\n\\f\\r\"\\\\]|\\\\(?:\\r\\n?|\\n|\\f)|\\\\[\\S\\s])*\"/,null],[\"str\",/^'(?:[^\\n\\f\\r'\\\\]|\\\\(?:\\r\\n?|\\n|\\f)|\\\\[\\S\\s])*'/,null],[\"lang-css-str\",/^url\\(([^\"')]+)\\)/i],[\"kwd\",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\\w-]|$)/i,null],[\"lang-css-kw\",/^(-?(?:[_a-z]|\\\\[\\da-f]+ ?)(?:[\\w-]|\\\\\\\\[\\da-f]+ ?)*)\\s*:/i],[\"com\",/^\\/\\*[^*]*\\*+(?:[^*/][^*]*\\*+)*\\//],\n[\"com\",/^(?:<\\!--|--\\>)/],[\"lit\",/^(?:\\d+|\\d*\\.\\d+)(?:%|[a-z]+)?/i],[\"lit\",/^#[\\da-f]{3,6}\\b/i],[\"pln\",/^-?(?:[_a-z]|\\\\[\\da-f]+ ?)(?:[\\w-]|\\\\\\\\[\\da-f]+ ?)*/i],[\"pun\",/^[^\\s\\w\"']+/]]),[\"css\"]);PR.registerLangHandler(PR.createSimpleLexer([],[[\"kwd\",/^-?(?:[_a-z]|\\\\[\\da-f]+ ?)(?:[\\w-]|\\\\\\\\[\\da-f]+ ?)*/i]]),[\"css-kw\"]);PR.registerLangHandler(PR.createSimpleLexer([],[[\"str\",/^[^\"')]+/]]),[\"css-str\"]);\n"
  },
  {
    "path": "_archive/apps/samples/identity/sample_support/google-code-prettify/run_prettify.js",
    "content": "!function(){var r=null;\n(function(){function X(e){function j(){try{J.doScroll(\"left\")}catch(e){P(j,50);return}w(\"poll\")}function w(j){if(!(j.type==\"readystatechange\"&&x.readyState!=\"complete\")&&((j.type==\"load\"?n:x)[z](i+j.type,w,!1),!m&&(m=!0)))e.call(n,j.type||j)}var Y=x.addEventListener,m=!1,C=!0,t=Y?\"addEventListener\":\"attachEvent\",z=Y?\"removeEventListener\":\"detachEvent\",i=Y?\"\":\"on\";if(x.readyState==\"complete\")e.call(n,\"lazy\");else{if(x.createEventObject&&J.doScroll){try{C=!n.frameElement}catch(A){}C&&j()}x[t](i+\"DOMContentLoaded\",\nw,!1);x[t](i+\"readystatechange\",w,!1);n[t](i+\"load\",w,!1)}}function Q(){S&&X(function(){var e=K.length;$(e?function(){for(var j=0;j<e;++j)(function(e){P(function(){n.exports[K[e]].apply(n,arguments)},0)})(j)}:void 0)})}for(var n=window,P=n.setTimeout,x=document,J=x.documentElement,L=x.head||x.getElementsByTagName(\"head\")[0]||J,z=\"\",A=x.scripts,m=A.length;--m>=0;){var M=A[m],T=M.src.match(/^[^#?]*\\/run_prettify\\.js(\\?[^#]*)?(?:#.*)?$/);if(T){z=T[1]||\"\";M.parentNode.removeChild(M);break}}var S=!0,D=\n[],N=[],K=[];z.replace(/[&?]([^&=]+)=([^&]+)/g,function(e,j,w){w=decodeURIComponent(w);j=decodeURIComponent(j);j==\"autorun\"?S=!/^[0fn]/i.test(w):j==\"lang\"?D.push(w):j==\"skin\"?N.push(w):j==\"callback\"&&K.push(w)});m=0;for(z=D.length;m<z;++m)(function(){var e=x.createElement(\"script\");e.onload=e.onerror=e.onreadystatechange=function(){if(e&&(!e.readyState||/loaded|complete/.test(e.readyState)))e.onerror=e.onload=e.onreadystatechange=r,--R,R||P(Q,0),e.parentNode&&e.parentNode.removeChild(e),e=r};e.type=\n\"text/javascript\";e.src=\"https://google-code-prettify.googlecode.com/svn/loader/lang-\"+encodeURIComponent(D[m])+\".js\";L.insertBefore(e,L.firstChild)})(D[m]);for(var R=D.length,A=[],m=0,z=N.length;m<z;++m)A.push(\"https://google-code-prettify.googlecode.com/svn/loader/skins/\"+encodeURIComponent(N[m])+\".css\");A.push(\"https://google-code-prettify.googlecode.com/svn/loader/prettify.css\");(function(e){function j(m){if(m!==w){var n=x.createElement(\"link\");n.rel=\"stylesheet\";n.type=\"text/css\";if(m+1<w)n.error=\nn.onerror=function(){j(m+1)};n.href=e[m];L.appendChild(n)}}var w=e.length;j(0)})(A);var $=function(){window.PR_SHOULD_USE_CONTINUATION=!0;var e;(function(){function j(a){function d(f){var b=f.charCodeAt(0);if(b!==92)return b;var a=f.charAt(1);return(b=i[a])?b:\"0\"<=a&&a<=\"7\"?parseInt(f.substring(1),8):a===\"u\"||a===\"x\"?parseInt(f.substring(2),16):f.charCodeAt(1)}function h(f){if(f<32)return(f<16?\"\\\\x0\":\"\\\\x\")+f.toString(16);f=String.fromCharCode(f);return f===\"\\\\\"||f===\"-\"||f===\"]\"||f===\"^\"?\"\\\\\"+f:\nf}function b(f){var b=f.substring(1,f.length-1).match(/\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\S\\s]|[^\\\\]/g),f=[],a=b[0]===\"^\",c=[\"[\"];a&&c.push(\"^\");for(var a=a?1:0,g=b.length;a<g;++a){var k=b[a];if(/\\\\[bdsw]/i.test(k))c.push(k);else{var k=d(k),o;a+2<g&&\"-\"===b[a+1]?(o=d(b[a+2]),a+=2):o=k;f.push([k,o]);o<65||k>122||(o<65||k>90||f.push([Math.max(65,k)|32,Math.min(o,90)|32]),o<97||k>122||f.push([Math.max(97,k)&-33,Math.min(o,122)&-33]))}}f.sort(function(f,a){return f[0]-\na[0]||a[1]-f[1]});b=[];g=[];for(a=0;a<f.length;++a)k=f[a],k[0]<=g[1]+1?g[1]=Math.max(g[1],k[1]):b.push(g=k);for(a=0;a<b.length;++a)k=b[a],c.push(h(k[0])),k[1]>k[0]&&(k[1]+1>k[0]&&c.push(\"-\"),c.push(h(k[1])));c.push(\"]\");return c.join(\"\")}function e(f){for(var a=f.source.match(/\\[(?:[^\\\\\\]]|\\\\[\\S\\s])*]|\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\\\d+|\\\\[^\\dux]|\\(\\?[!:=]|[()^]|[^()[\\\\^]+/g),c=a.length,d=[],g=0,k=0;g<c;++g){var o=a[g];o===\"(\"?++k:\"\\\\\"===o.charAt(0)&&(o=+o.substring(1))&&(o<=k?d[o]=-1:a[g]=h(o))}for(g=\n1;g<d.length;++g)-1===d[g]&&(d[g]=++j);for(k=g=0;g<c;++g)o=a[g],o===\"(\"?(++k,d[k]||(a[g]=\"(?:\")):\"\\\\\"===o.charAt(0)&&(o=+o.substring(1))&&o<=k&&(a[g]=\"\\\\\"+d[o]);for(g=0;g<c;++g)\"^\"===a[g]&&\"^\"!==a[g+1]&&(a[g]=\"\");if(f.ignoreCase&&F)for(g=0;g<c;++g)o=a[g],f=o.charAt(0),o.length>=2&&f===\"[\"?a[g]=b(o):f!==\"\\\\\"&&(a[g]=o.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return\"[\"+String.fromCharCode(a&-33,a|32)+\"]\"}));return a.join(\"\")}for(var j=0,F=!1,l=!1,I=0,c=a.length;I<c;++I){var p=a[I];if(p.ignoreCase)l=\n!0;else if(/[a-z]/i.test(p.source.replace(/\\\\u[\\da-f]{4}|\\\\x[\\da-f]{2}|\\\\[^UXux]/gi,\"\"))){F=!0;l=!1;break}}for(var i={b:8,t:9,n:10,v:11,f:12,r:13},q=[],I=0,c=a.length;I<c;++I){p=a[I];if(p.global||p.multiline)throw Error(\"\"+p);q.push(\"(?:\"+e(p)+\")\")}return RegExp(q.join(\"|\"),l?\"gi\":\"g\")}function m(a,d){function h(a){var c=a.nodeType;if(c==1){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)h(c);c=a.nodeName.toLowerCase();if(\"br\"===c||\"li\"===c)e[l]=\"\\n\",F[l<<1]=j++,F[l++<<1|1]=a}}else if(c==\n3||c==4)c=a.nodeValue,c.length&&(c=d?c.replace(/\\r\\n?/g,\"\\n\"):c.replace(/[\\t\\n\\r ]+/g,\" \"),e[l]=c,F[l<<1]=j,j+=c.length,F[l++<<1|1]=a)}var b=/(?:^|\\s)nocode(?:\\s|$)/,e=[],j=0,F=[],l=0;h(a);return{a:e.join(\"\").replace(/\\n$/,\"\"),d:F}}function n(a,d,h,b){d&&(a={a:d,e:a},h(a),b.push.apply(b,a.g))}function x(a){for(var d=void 0,h=a.firstChild;h;h=h.nextSibling)var b=h.nodeType,d=b===1?d?a:h:b===3?S.test(h.nodeValue)?a:d:d;return d===a?void 0:d}function C(a,d){function h(a){for(var l=a.e,j=[l,\"pln\"],c=\n0,p=a.a.match(e)||[],m={},q=0,f=p.length;q<f;++q){var B=p[q],y=m[B],u=void 0,g;if(typeof y===\"string\")g=!1;else{var k=b[B.charAt(0)];if(k)u=B.match(k[1]),y=k[0];else{for(g=0;g<i;++g)if(k=d[g],u=B.match(k[1])){y=k[0];break}u||(y=\"pln\")}if((g=y.length>=5&&\"lang-\"===y.substring(0,5))&&!(u&&typeof u[1]===\"string\"))g=!1,y=\"src\";g||(m[B]=y)}k=c;c+=B.length;if(g){g=u[1];var o=B.indexOf(g),H=o+g.length;u[2]&&(H=B.length-u[2].length,o=H-g.length);y=y.substring(5);n(l+k,B.substring(0,o),h,j);n(l+k+o,g,A(y,\ng),j);n(l+k+H,B.substring(H),h,j)}else j.push(l+k,y)}a.g=j}var b={},e;(function(){for(var h=a.concat(d),l=[],i={},c=0,p=h.length;c<p;++c){var m=h[c],q=m[3];if(q)for(var f=q.length;--f>=0;)b[q.charAt(f)]=m;m=m[1];q=\"\"+m;i.hasOwnProperty(q)||(l.push(m),i[q]=r)}l.push(/[\\S\\s]/);e=j(l)})();var i=d.length;return h}function t(a){var d=[],h=[];a.tripleQuotedStrings?d.push([\"str\",/^(?:'''(?:[^'\\\\]|\\\\[\\S\\s]|''?(?=[^']))*(?:'''|$)|\"\"\"(?:[^\"\\\\]|\\\\[\\S\\s]|\"\"?(?=[^\"]))*(?:\"\"\"|$)|'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$)|\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$))/,\nr,\"'\\\"\"]):a.multiLineStrings?d.push([\"str\",/^(?:'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$)|\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)|`(?:[^\\\\`]|\\\\[\\S\\s])*(?:`|$))/,r,\"'\\\"`\"]):d.push([\"str\",/^(?:'(?:[^\\n\\r'\\\\]|\\\\.)*(?:'|$)|\"(?:[^\\n\\r\"\\\\]|\\\\.)*(?:\"|$))/,r,\"\\\"'\"]);a.verbatimStrings&&h.push([\"str\",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,r]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push([\"com\",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,r,\"#\"]):d.push([\"com\",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\n\\r]*)/,\nr,\"#\"]),h.push([\"str\",/^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,r])):d.push([\"com\",/^#[^\\n\\r]*/,r,\"#\"]));a.cStyleComments&&(h.push([\"com\",/^\\/\\/[^\\n\\r]*/,r]),h.push([\"com\",/^\\/\\*[\\S\\s]*?(?:\\*\\/|$)/,r]));if(b=a.regexLiterals){var e=(b=b>1?\"\":\"\\n\\r\")?\".\":\"[\\\\S\\\\s]\";h.push([\"lang-regex\",RegExp(\"^(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*(\"+\n(\"/(?=[^/*\"+b+\"])(?:[^/\\\\x5B\\\\x5C\"+b+\"]|\\\\x5C\"+e+\"|\\\\x5B(?:[^\\\\x5C\\\\x5D\"+b+\"]|\\\\x5C\"+e+\")*(?:\\\\x5D|$))+/\")+\")\")])}(b=a.types)&&h.push([\"typ\",b]);b=(\"\"+a.keywords).replace(/^ | $/g,\"\");b.length&&h.push([\"kwd\",RegExp(\"^(?:\"+b.replace(/[\\s,]+/g,\"|\")+\")\\\\b\"),r]);d.push([\"pln\",/^\\s+/,r,\" \\r\\n\\t\\u00a0\"]);b=\"^.[^\\\\s\\\\w.$@'\\\"`/\\\\\\\\]*\";a.regexLiterals&&(b+=\"(?!s*/)\");h.push([\"lit\",/^@[$_a-z][\\w$@]*/i,r],[\"typ\",/^(?:[@_]?[A-Z]+[a-z][\\w$@]*|\\w+_t\\b)/,r],[\"pln\",/^[$_a-z][\\w$@]*/i,r],[\"lit\",/^(?:0x[\\da-f]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+-]?\\d+)?)[a-z]*/i,\nr,\"0123456789\"],[\"pln\",/^\\\\[\\S\\s]?/,r],[\"pun\",RegExp(b),r]);return C(d,h)}function z(a,d,h){function b(a){var c=a.nodeType;if(c==1&&!j.test(a.className))if(\"br\"===a.nodeName)e(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&h){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(l.createTextNode(d),a.nextSibling),e(a),c||a.parentNode.removeChild(a)}}\nfunction e(a){function b(a,c){var d=c?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),h=a.nextSibling;f.appendChild(d);for(var e=h;e;e=h)h=e.nextSibling,f.appendChild(e)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var j=/(?:^|\\s)nocode(?:\\s|$)/,m=/\\r\\n?|\\n/,l=a.ownerDocument,i=l.createElement(\"li\");a.firstChild;)i.appendChild(a.firstChild);for(var c=[i],p=0;p<c.length;++p)b(c[p]);d===(d|0)&&c[0].setAttribute(\"value\",\nd);var n=l.createElement(\"ol\");n.className=\"linenums\";for(var d=Math.max(0,d-1|0)||0,p=0,q=c.length;p<q;++p)i=c[p],i.className=\"L\"+(p+d)%10,i.firstChild||i.appendChild(l.createTextNode(\"\\u00a0\")),n.appendChild(i);a.appendChild(n)}function i(a,d){for(var h=d.length;--h>=0;){var b=d[h];U.hasOwnProperty(b)?V.console&&console.warn(\"cannot override language handler %s\",b):U[b]=a}}function A(a,d){if(!a||!U.hasOwnProperty(a))a=/^\\s*</.test(d)?\"default-markup\":\"default-code\";return U[a]}function D(a){var d=\na.h;try{var h=m(a.c,a.i),b=h.a;a.a=b;a.d=h.d;a.e=0;A(d,b)(a);var e=/\\bMSIE\\s(\\d+)/.exec(navigator.userAgent),e=e&&+e[1]<=8,d=/\\n/g,i=a.a,j=i.length,h=0,l=a.d,n=l.length,b=0,c=a.g,p=c.length,t=0;c[p]=j;var q,f;for(f=q=0;f<p;)c[f]!==c[f+2]?(c[q++]=c[f++],c[q++]=c[f++]):f+=2;p=q;for(f=q=0;f<p;){for(var x=c[f],y=c[f+1],u=f+2;u+2<=p&&c[u+1]===y;)u+=2;c[q++]=x;c[q++]=y;f=u}c.length=q;var g=a.c,k;if(g)k=g.style.display,g.style.display=\"none\";try{for(;b<n;){var o=l[b+2]||j,H=c[t+2]||j,u=Math.min(o,H),E=l[b+\n1],W;if(E.nodeType!==1&&(W=i.substring(h,u))){e&&(W=W.replace(d,\"\\r\"));E.nodeValue=W;var Z=E.ownerDocument,s=Z.createElement(\"span\");s.className=c[t+1];var z=E.parentNode;z.replaceChild(s,E);s.appendChild(E);h<o&&(l[b+1]=E=Z.createTextNode(i.substring(u,o)),z.insertBefore(E,s.nextSibling))}h=u;h>=o&&(b+=2);h>=H&&(t+=2)}}finally{if(g)g.style.display=k}}catch(v){V.console&&console.log(v&&v.stack||v)}}var V=window,G=[\"break,continue,do,else,for,if,return,while\"],O=[[G,\"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"],\n\"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof\"],J=[O,\"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where\"],K=[O,\"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient\"],\nL=[K,\"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where\"],O=[O,\"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN\"],M=[G,\"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None\"],\nN=[G,\"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END\"],R=[G,\"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use\"],G=[G,\"case,done,elif,esac,eval,fi,function,in,local,set,then,until\"],Q=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/,\nS=/\\S/,T=t({keywords:[J,L,O,\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\",M,N,G],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),U={};i(T,[\"default-code\"]);i(C([],[[\"pln\",/^[^<?]+/],[\"dec\",/^<!\\w[^>]*(?:>|$)/],[\"com\",/^<\\!--[\\S\\s]*?(?:--\\>|$)/],[\"lang-\",/^<\\?([\\S\\s]+?)(?:\\?>|$)/],[\"lang-\",/^<%([\\S\\s]+?)(?:%>|$)/],[\"pun\",/^(?:<[%?]|[%?]>)/],[\"lang-\",\n/^<xmp\\b[^>]*>([\\S\\s]+?)<\\/xmp\\b[^>]*>/i],[\"lang-js\",/^<script\\b[^>]*>([\\S\\s]*?)(<\\/script\\b[^>]*>)/i],[\"lang-css\",/^<style\\b[^>]*>([\\S\\s]*?)(<\\/style\\b[^>]*>)/i],[\"lang-in.tag\",/^(<\\/?[a-z][^<>]*>)/i]]),[\"default-markup\",\"htm\",\"html\",\"mxml\",\"xhtml\",\"xml\",\"xsl\"]);i(C([[\"pln\",/^\\s+/,r,\" \\t\\r\\n\"],[\"atv\",/^(?:\"[^\"]*\"?|'[^']*'?)/,r,\"\\\"'\"]],[[\"tag\",/^^<\\/?[a-z](?:[\\w-.:]*\\w)?|\\/?>$/i],[\"atn\",/^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],[\"lang-uq.val\",/^=\\s*([^\\s\"'>]*(?:[^\\s\"'/>]|\\/(?=\\s)))/],[\"pun\",/^[/<->]+/],\n[\"lang-js\",/^on\\w+\\s*=\\s*\"([^\"]+)\"/i],[\"lang-js\",/^on\\w+\\s*=\\s*'([^']+)'/i],[\"lang-js\",/^on\\w+\\s*=\\s*([^\\s\"'>]+)/i],[\"lang-css\",/^style\\s*=\\s*\"([^\"]+)\"/i],[\"lang-css\",/^style\\s*=\\s*'([^']+)'/i],[\"lang-css\",/^style\\s*=\\s*([^\\s\"'>]+)/i]]),[\"in.tag\"]);i(C([],[[\"atv\",/^[\\S\\s]+/]]),[\"uq.val\"]);i(t({keywords:J,hashComments:!0,cStyleComments:!0,types:Q}),[\"c\",\"cc\",\"cpp\",\"cxx\",\"cyc\",\"m\"]);i(t({keywords:\"null,true,false\"}),[\"json\"]);i(t({keywords:L,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:Q}),\n[\"cs\"]);i(t({keywords:K,cStyleComments:!0}),[\"java\"]);i(t({keywords:G,hashComments:!0,multiLineStrings:!0}),[\"bash\",\"bsh\",\"csh\",\"sh\"]);i(t({keywords:M,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),[\"cv\",\"py\",\"python\"]);i(t({keywords:\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),[\"perl\",\"pl\",\"pm\"]);i(t({keywords:N,\nhashComments:!0,multiLineStrings:!0,regexLiterals:!0}),[\"rb\",\"ruby\"]);i(t({keywords:O,cStyleComments:!0,regexLiterals:!0}),[\"javascript\",\"js\"]);i(t({keywords:\"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes\",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),[\"coffee\"]);i(t({keywords:R,cStyleComments:!0,multilineStrings:!0}),[\"rc\",\"rs\",\"rust\"]);\ni(C([],[[\"str\",/^[\\S\\s]+/]]),[\"regex\"]);var X=V.PR={createSimpleLexer:C,registerLangHandler:i,sourceDecorator:t,PR_ATTRIB_NAME:\"atn\",PR_ATTRIB_VALUE:\"atv\",PR_COMMENT:\"com\",PR_DECLARATION:\"dec\",PR_KEYWORD:\"kwd\",PR_LITERAL:\"lit\",PR_NOCODE:\"nocode\",PR_PLAIN:\"pln\",PR_PUNCTUATION:\"pun\",PR_SOURCE:\"src\",PR_STRING:\"str\",PR_TAG:\"tag\",PR_TYPE:\"typ\",prettyPrintOne:function(a,d,e){var b=document.createElement(\"div\");b.innerHTML=\"<pre>\"+a+\"</pre>\";b=b.firstChild;e&&z(b,e,!0);D({h:d,j:e,c:b,i:1});return b.innerHTML},\nprettyPrint:e=e=function(a,d){function e(){for(var b=V.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;p<j.length&&c.now()<b;p++){for(var d=j[p],m=k,l=d;l=l.previousSibling;){var n=l.nodeType,s=(n===7||n===8)&&l.nodeValue;if(s?!/^\\??prettify\\b/.test(s):n!==3||/\\S/.test(l.nodeValue))break;if(s){m={};s.replace(/\\b(\\w+)=([\\w%+\\-.:]+)/g,function(a,b,c){m[b]=c});break}}l=d.className;if((m!==k||f.test(l))&&!w.test(l)){n=!1;for(s=d.parentNode;s;s=s.parentNode)if(g.test(s.tagName)&&s.className&&f.test(s.className)){n=\n!0;break}if(!n){d.className+=\" prettyprinted\";n=m.lang;if(!n){var n=l.match(q),A;if(!n&&(A=x(d))&&u.test(A.tagName))n=A.className.match(q);n&&(n=n[1])}if(y.test(d.tagName))s=1;else var s=d.currentStyle,v=i.defaultView,s=(s=s?s.whiteSpace:v&&v.getComputedStyle?v.getComputedStyle(d,r).getPropertyValue(\"white-space\"):0)&&\"pre\"===s.substring(0,3);v=m.linenums;if(!(v=v===\"true\"||+v))v=(v=l.match(/\\blinenums\\b(?::(\\d+))?/))?v[1]&&v[1].length?+v[1]:!0:!1;v&&z(d,v,s);t={h:n,c:d,j:v,i:s};D(t)}}}p<j.length?\nP(e,250):\"function\"===typeof a&&a()}for(var b=d||document.body,i=b.ownerDocument||document,b=[b.getElementsByTagName(\"pre\"),b.getElementsByTagName(\"code\"),b.getElementsByTagName(\"xmp\")],j=[],m=0;m<b.length;++m)for(var l=0,n=b[m].length;l<n;++l)j.push(b[m][l]);var b=r,c=Date;c.now||(c={now:function(){return+new Date}});var p=0,t,q=/\\blang(?:uage)?-([\\w.]+)(?!\\S)/,f=/\\bprettyprint\\b/,w=/\\bprettyprinted\\b/,y=/pre|xmp/i,u=/^code$/i,g=/^(?:pre|code|xmp)$/i,k={};e()}};typeof define===\"function\"&&define.amd&&\ndefine(\"google-code-prettify\",[],function(){return X})})();return e}();R||P(Q,0)})();}()\n"
  },
  {
    "path": "_archive/apps/samples/identity/sample_support/prettify.css",
    "content": ".pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}"
  },
  {
    "path": "_archive/apps/samples/identity/sample_support/prettify.js",
    "content": "!function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;\n(function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:\"0\"<=a&&a<=\"7\"?parseInt(e.substring(1),8):a===\"u\"||a===\"x\"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?\"\\\\x0\":\"\\\\x\")+e.toString(16);e=String.fromCharCode(e);return e===\"\\\\\"||e===\"-\"||e===\"]\"||e===\"^\"?\"\\\\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\S\\s]|[^\\\\]/g),e=[],a=\nb[0]===\"^\",c=[\"[\"];a&&c.push(\"^\");for(var a=a?1:0,f=b.length;a<f;++a){var h=b[a];if(/\\\\[bdsw]/i.test(h))c.push(h);else{var h=d(h),l;a+2<f&&\"-\"===b[a+1]?(l=d(b[a+2]),a+=2):l=h;e.push([h,l]);l<65||h>122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;a<e.length;++a)h=e[a],h[0]<=f[1]+1?f[1]=Math.max(f[1],h[1]):b.push(f=h);for(a=0;a<b.length;++a)h=b[a],c.push(g(h[0])),\nh[1]>h[0]&&(h[1]+1>h[0]&&c.push(\"-\"),c.push(g(h[1])));c.push(\"]\");return c.join(\"\")}function s(e){for(var a=e.source.match(/\\[(?:[^\\\\\\]]|\\\\[\\S\\s])*]|\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\\\d+|\\\\[^\\dux]|\\(\\?[!:=]|[()^]|[^()[\\\\^]+/g),c=a.length,d=[],f=0,h=0;f<c;++f){var l=a[f];l===\"(\"?++h:\"\\\\\"===l.charAt(0)&&(l=+l.substring(1))&&(l<=h?d[l]=-1:a[f]=g(l))}for(f=1;f<d.length;++f)-1===d[f]&&(d[f]=++x);for(h=f=0;f<c;++f)l=a[f],l===\"(\"?(++h,d[h]||(a[f]=\"(?:\")):\"\\\\\"===l.charAt(0)&&(l=+l.substring(1))&&l<=h&&\n(a[f]=\"\\\\\"+d[l]);for(f=0;f<c;++f)\"^\"===a[f]&&\"^\"!==a[f+1]&&(a[f]=\"\");if(e.ignoreCase&&m)for(f=0;f<c;++f)l=a[f],e=l.charAt(0),l.length>=2&&e===\"[\"?a[f]=b(l):e!==\"\\\\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return\"[\"+String.fromCharCode(a&-33,a|32)+\"]\"}));return a.join(\"\")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k<c;++k){var i=a[k];if(i.ignoreCase)j=!0;else if(/[a-z]/i.test(i.source.replace(/\\\\u[\\da-f]{4}|\\\\x[\\da-f]{2}|\\\\[^UXux]/gi,\"\"))){m=!0;j=!1;break}}for(var r={b:8,t:9,n:10,v:11,\nf:12,r:13},n=[],k=0,c=a.length;k<c;++k){i=a[k];if(i.global||i.multiline)throw Error(\"\"+i);n.push(\"(?:\"+s(i)+\")\")}return RegExp(n.join(\"|\"),j?\"gi\":\"g\")}function T(a,d){function g(a){var c=a.nodeType;if(c==1){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)g(c);c=a.nodeName.toLowerCase();if(\"br\"===c||\"li\"===c)s[j]=\"\\n\",m[j<<1]=x++,m[j++<<1|1]=a}}else if(c==3||c==4)c=a.nodeValue,c.length&&(c=d?c.replace(/\\r\\n?/g,\"\\n\"):c.replace(/[\\t\\n\\r ]+/g,\" \"),s[j]=c,m[j<<1]=x,x+=c.length,m[j++<<1|1]=\na)}var b=/(?:^|\\s)nocode(?:\\s|$)/,s=[],x=0,m=[],j=0;g(a);return{a:s.join(\"\").replace(/\\n$/,\"\"),d:m}}function H(a,d,g,b){d&&(a={a:d,e:a},g(a),b.push.apply(b,a.g))}function U(a){for(var d=void 0,g=a.firstChild;g;g=g.nextSibling)var b=g.nodeType,d=b===1?d?a:g:b===3?V.test(g.nodeValue)?a:d:d;return d===a?void 0:d}function C(a,d){function g(a){for(var j=a.e,k=[j,\"pln\"],c=0,i=a.a.match(s)||[],r={},n=0,e=i.length;n<e;++n){var z=i[n],w=r[z],t=void 0,f;if(typeof w===\"string\")f=!1;else{var h=b[z.charAt(0)];\nif(h)t=z.match(h[1]),w=h[0];else{for(f=0;f<x;++f)if(h=d[f],t=z.match(h[1])){w=h[0];break}t||(w=\"pln\")}if((f=w.length>=5&&\"lang-\"===w.substring(0,5))&&!(t&&typeof t[1]===\"string\"))f=!1,w=\"src\";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c<i;++c){var r=\ng[c],n=r[3];if(n)for(var e=n.length;--e>=0;)b[n.charAt(e)]=r;r=r[1];n=\"\"+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\\S\\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push([\"str\",/^(?:'''(?:[^'\\\\]|\\\\[\\S\\s]|''?(?=[^']))*(?:'''|$)|\"\"\"(?:[^\"\\\\]|\\\\[\\S\\s]|\"\"?(?=[^\"]))*(?:\"\"\"|$)|'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$)|\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$))/,q,\"'\\\"\"]):a.multiLineStrings?d.push([\"str\",/^(?:'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$)|\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)|`(?:[^\\\\`]|\\\\[\\S\\s])*(?:`|$))/,\nq,\"'\\\"`\"]):d.push([\"str\",/^(?:'(?:[^\\n\\r'\\\\]|\\\\.)*(?:'|$)|\"(?:[^\\n\\r\"\\\\]|\\\\.)*(?:\"|$))/,q,\"\\\"'\"]);a.verbatimStrings&&g.push([\"str\",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push([\"com\",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,\"#\"]):d.push([\"com\",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\n\\r]*)/,q,\"#\"]),g.push([\"str\",/^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,q])):d.push([\"com\",\n/^#[^\\n\\r]*/,q,\"#\"]));a.cStyleComments&&(g.push([\"com\",/^\\/\\/[^\\n\\r]*/,q]),g.push([\"com\",/^\\/\\*[\\S\\s]*?(?:\\*\\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?\"\":\"\\n\\r\")?\".\":\"[\\\\S\\\\s]\";g.push([\"lang-regex\",RegExp(\"^(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<<?=?|>>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*(\"+(\"/(?=[^/*\"+b+\"])(?:[^/\\\\x5B\\\\x5C\"+b+\"]|\\\\x5C\"+s+\"|\\\\x5B(?:[^\\\\x5C\\\\x5D\"+b+\"]|\\\\x5C\"+\ns+\")*(?:\\\\x5D|$))+/\")+\")\")])}(b=a.types)&&g.push([\"typ\",b]);b=(\"\"+a.keywords).replace(/^ | $/g,\"\");b.length&&g.push([\"kwd\",RegExp(\"^(?:\"+b.replace(/[\\s,]+/g,\"|\")+\")\\\\b\"),q]);d.push([\"pln\",/^\\s+/,q,\" \\r\\n\\t\\u00a0\"]);b=\"^.[^\\\\s\\\\w.$@'\\\"`/\\\\\\\\]*\";a.regexLiterals&&(b+=\"(?!s*/)\");g.push([\"lit\",/^@[$_a-z][\\w$@]*/i,q],[\"typ\",/^(?:[@_]?[A-Z]+[a-z][\\w$@]*|\\w+_t\\b)/,q],[\"pln\",/^[$_a-z][\\w$@]*/i,q],[\"lit\",/^(?:0x[\\da-f]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+-]?\\d+)?)[a-z]*/i,q,\"0123456789\"],[\"pln\",/^\\\\[\\S\\s]?/,\nq],[\"pun\",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if(\"br\"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d=\nc?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\\s)nocode(?:\\s|$)/,m=/\\r\\n?|\\n/,j=a.ownerDocument,k=j.createElement(\"li\");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i<c.length;++i)b(c[i]);d===(d|0)&&c[0].setAttribute(\"value\",d);var r=j.createElement(\"ol\");\nr.className=\"linenums\";for(var d=Math.max(0,d-1|0)||0,i=0,n=c.length;i<n;++i)k=c[i],k.className=\"L\"+(i+d)%10,k.firstChild||k.appendChild(j.createTextNode(\"\\u00a0\")),r.appendChild(k);a.appendChild(r)}function p(a,d){for(var g=d.length;--g>=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn(\"cannot override language handler %s\",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\\s*</.test(d)?\"default-markup\":\"default-code\";return F[a]}function K(a){var d=a.h;try{var g=T(a.c,a.i),b=g.a;\na.a=b;a.d=g.d;a.e=0;I(d,b)(a);var s=/\\bMSIE\\s(\\d+)/.exec(navigator.userAgent),s=s&&+s[1]<=8,d=/\\n/g,x=a.a,m=x.length,g=0,j=a.d,k=j.length,b=0,c=a.g,i=c.length,r=0;c[i]=m;var n,e;for(e=n=0;e<i;)c[e]!==c[e+2]?(c[n++]=c[e++],c[n++]=c[e++]):e+=2;i=n;for(e=n=0;e<i;){for(var p=c[e],w=c[e+1],t=e+2;t+2<=i&&c[t+1]===w;)t+=2;c[n++]=p;c[n++]=w;e=t}c.length=n;var f=a.c,h;if(f)h=f.style.display,f.style.display=\"none\";try{for(;b<k;){var l=j[b+2]||m,B=c[r+2]||m,t=Math.min(l,B),A=j[b+1],G;if(A.nodeType!==1&&(G=x.substring(g,\nt))){s&&(G=G.replace(d,\"\\r\"));A.nodeValue=G;var L=A.ownerDocument,o=L.createElement(\"span\");o.className=c[r+1];var v=A.parentNode;v.replaceChild(o,A);o.appendChild(A);g<l&&(j[b+1]=A=L.createTextNode(x.substring(t,l)),v.insertBefore(A,o.nextSibling))}g=t;g>=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=[\"break,continue,do,else,for,if,return,while\"],E=[[y,\"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"],\n\"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof\"],M=[E,\"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where\"],N=[E,\"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient\"],\nO=[N,\"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where\"],E=[E,\"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN\"],P=[y,\"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None\"],\nQ=[y,\"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END\"],W=[y,\"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use\"],y=[y,\"case,done,elif,esac,eval,fi,function,in,local,set,then,until\"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/,\nV=/\\S/,X=v({keywords:[M,O,E,\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,[\"default-code\"]);p(C([],[[\"pln\",/^[^<?]+/],[\"dec\",/^<!\\w[^>]*(?:>|$)/],[\"com\",/^<\\!--[\\S\\s]*?(?:--\\>|$)/],[\"lang-\",/^<\\?([\\S\\s]+?)(?:\\?>|$)/],[\"lang-\",/^<%([\\S\\s]+?)(?:%>|$)/],[\"pun\",/^(?:<[%?]|[%?]>)/],[\"lang-\",\n/^<xmp\\b[^>]*>([\\S\\s]+?)<\\/xmp\\b[^>]*>/i],[\"lang-js\",/^<script\\b[^>]*>([\\S\\s]*?)(<\\/script\\b[^>]*>)/i],[\"lang-css\",/^<style\\b[^>]*>([\\S\\s]*?)(<\\/style\\b[^>]*>)/i],[\"lang-in.tag\",/^(<\\/?[a-z][^<>]*>)/i]]),[\"default-markup\",\"htm\",\"html\",\"mxml\",\"xhtml\",\"xml\",\"xsl\"]);p(C([[\"pln\",/^\\s+/,q,\" \\t\\r\\n\"],[\"atv\",/^(?:\"[^\"]*\"?|'[^']*'?)/,q,\"\\\"'\"]],[[\"tag\",/^^<\\/?[a-z](?:[\\w-.:]*\\w)?|\\/?>$/i],[\"atn\",/^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],[\"lang-uq.val\",/^=\\s*([^\\s\"'>]*(?:[^\\s\"'/>]|\\/(?=\\s)))/],[\"pun\",/^[/<->]+/],\n[\"lang-js\",/^on\\w+\\s*=\\s*\"([^\"]+)\"/i],[\"lang-js\",/^on\\w+\\s*=\\s*'([^']+)'/i],[\"lang-js\",/^on\\w+\\s*=\\s*([^\\s\"'>]+)/i],[\"lang-css\",/^style\\s*=\\s*\"([^\"]+)\"/i],[\"lang-css\",/^style\\s*=\\s*'([^']+)'/i],[\"lang-css\",/^style\\s*=\\s*([^\\s\"'>]+)/i]]),[\"in.tag\"]);p(C([],[[\"atv\",/^[\\S\\s]+/]]),[\"uq.val\"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:R}),[\"c\",\"cc\",\"cpp\",\"cxx\",\"cyc\",\"m\"]);p(v({keywords:\"null,true,false\"}),[\"json\"]);p(v({keywords:O,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:R}),\n[\"cs\"]);p(v({keywords:N,cStyleComments:!0}),[\"java\"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),[\"bash\",\"bsh\",\"csh\",\"sh\"]);p(v({keywords:P,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),[\"cv\",\"py\",\"python\"]);p(v({keywords:\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),[\"perl\",\"pl\",\"pm\"]);p(v({keywords:Q,\nhashComments:!0,multiLineStrings:!0,regexLiterals:!0}),[\"rb\",\"ruby\"]);p(v({keywords:E,cStyleComments:!0,regexLiterals:!0}),[\"javascript\",\"js\"]);p(v({keywords:\"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes\",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),[\"coffee\"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),[\"rc\",\"rs\",\"rust\"]);\np(C([],[[\"str\",/^[\\S\\s]+/]]),[\"regex\"]);var Y=D.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:\"atn\",PR_ATTRIB_VALUE:\"atv\",PR_COMMENT:\"com\",PR_DECLARATION:\"dec\",PR_KEYWORD:\"kwd\",PR_LITERAL:\"lit\",PR_NOCODE:\"nocode\",PR_PLAIN:\"pln\",PR_PUNCTUATION:\"pun\",PR_SOURCE:\"src\",PR_STRING:\"str\",PR_TAG:\"tag\",PR_TYPE:\"typ\",prettyPrintOne:D.prettyPrintOne=function(a,d,g){var b=document.createElement(\"div\");b.innerHTML=\"<pre>\"+a+\"</pre>\";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1});\nreturn b.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function g(){for(var b=D.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;i<p.length&&c.now()<b;i++){for(var d=p[i],j=h,k=d;k=k.previousSibling;){var m=k.nodeType,o=(m===7||m===8)&&k.nodeValue;if(o?!/^\\??prettify\\b/.test(o):m!==3||/\\S/.test(k.nodeValue))break;if(o){j={};o.replace(/\\b(\\w+)=([\\w%+\\-.:]+)/g,function(a,b,c){j[b]=c});break}}k=d.className;if((j!==h||e.test(k))&&!v.test(k)){m=!1;for(o=d.parentNode;o;o=o.parentNode)if(f.test(o.tagName)&&\no.className&&e.test(o.className)){m=!0;break}if(!m){d.className+=\" prettyprinted\";m=j.lang;if(!m){var m=k.match(n),y;if(!m&&(y=U(d))&&t.test(y.tagName))m=y.className.match(n);m&&(m=m[1])}if(w.test(d.tagName))o=1;else var o=d.currentStyle,u=s.defaultView,o=(o=o?o.whiteSpace:u&&u.getComputedStyle?u.getComputedStyle(d,q).getPropertyValue(\"white-space\"):0)&&\"pre\"===o.substring(0,3);u=j.linenums;if(!(u=u===\"true\"||+u))u=(u=k.match(/\\blinenums\\b(?::(\\d+))?/))?u[1]&&u[1].length?+u[1]:!0:!1;u&&J(d,u,o);r=\n{h:m,c:d,j:u,i:o};K(r)}}}i<p.length?setTimeout(g,250):\"function\"===typeof a&&a()}for(var b=d||document.body,s=b.ownerDocument||document,b=[b.getElementsByTagName(\"pre\"),b.getElementsByTagName(\"code\"),b.getElementsByTagName(\"xmp\")],p=[],m=0;m<b.length;++m)for(var j=0,k=b[m].length;j<k;++j)p.push(b[m][j]);var b=q,c=Date;c.now||(c={now:function(){return+new Date}});var i=0,r,n=/\\blang(?:uage)?-([\\w.]+)(?!\\S)/,e=/\\bprettyprint\\b/,v=/\\bprettyprinted\\b/,w=/pre|xmp/i,t=/^code$/i,f=/^(?:pre|code|xmp)$/i,\nh={};g()}};typeof define===\"function\"&&define.amd&&define(\"google-code-prettify\",[],function(){return Y})})();}()\n"
  },
  {
    "path": "_archive/apps/samples/identity/sample_support/prettify_theme.css",
    "content": "/* Pretty printing styles. Used with prettify.js. */\n/* Vim sunburst theme by David Leibovic */\n\npre .str, code .str { color: #65B042; } /* string  - green */\npre .kwd, code .kwd { color: #E28964; } /* keyword - dark pink */\npre .com, code .com { color: #AEAEAE; font-style: italic; } /* comment - gray */\npre .typ, code .typ { color: #89bdff; } /* type - light blue */\npre .lit, code .lit { color: #3387CC; } /* literal - blue */\npre .pun, code .pun { color: #fff; } /* punctuation - white */\npre .pln, code .pln { color: #fff; } /* plaintext - white */\npre .tag, code .tag { color: #89bdff; } /* html/xml tag    - light blue */\npre .atn, code .atn { color: #bdb76b; } /* html/xml attribute name  - khaki */\npre .atv, code .atv { color: #65B042; } /* html/xml attribute value - green */\npre .dec, code .dec { color: #3387CC; } /* decimal - blue */\n\npre.prettyprint, code.prettyprint {\n        background-color: #000;\n        -moz-border-radius: 8px;\n        -webkit-border-radius: 8px;\n        -o-border-radius: 8px;\n        -ms-border-radius: 8px;\n        -khtml-border-radius: 8px;\n        border-radius: 8px;\n}\n\npre.prettyprint {\n        width: 95%;\n        margin: 1em auto;\n        padding: 1em;\n        white-space: pre-wrap;\n}\n\n\n/* Specify class=linenums on a pre to get line numbering */\nol.linenums { margin-top: 0; margin-bottom: 0; color: #AEAEAE; } /* IE indents via margin-left */\nli.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8 { list-style-type: none }\n/* Alternate shading for lines */\nli.L1,li.L3,li.L5,li.L7,li.L9 { }\n\n@media print {\n  pre .str, code .str { color: #060; }\n  pre .kwd, code .kwd { color: #006; font-weight: bold; }\n  pre .com, code .com { color: #600; font-style: italic; }\n  pre .typ, code .typ { color: #404; font-weight: bold; }\n  pre .lit, code .lit { color: #044; }\n  pre .pun, code .pun { color: #440; }\n  pre .pln, code .pln { color: #000; }\n  pre .tag, code .tag { color: #006; font-weight: bold; }\n  pre .atn, code .atn { color: #404; }\n  pre .atv, code .atv { color: #060; }\n}"
  },
  {
    "path": "_archive/apps/samples/identity/sample_support/sample_support.js",
    "content": "\n'use strict';\n\n(function(context){\n\n  function Logger(log_area) {\n    this.setLogArea(log_area);\n  }\n\n  Logger.prototype.setLogArea = function(log_area) {\n    this.log_area = log_area;\n  }\n\n  Logger.prototype.log = function(message, currentWindow, currentAppWindowId) {\n\n    currentWindow.console.log(message);\n\n    if (this.log_area) {\n      // convert the message to string, if necessary\n      var messageStr = message;\n      if (typeof(message) != 'string') {\n        messageStr = JSON.stringify(message);\n      }\n\n      // log to the textarea HTML element\n      this.log_area.innerText += messageStr;\n\n      // if this is not the window with the log area, log to its console too\n      if (this.log_area.ownerDocument &&\n          this.log_area.ownerDocument.defaultView &&\n          this.log_area.ownerDocument.defaultView != currentWindow) {\n        this.log_area.ownerDocument.defaultView.console.log(\n          \"[WIN:\"+currentAppWindowId+\"]\",message);\n      }\n\n    }\n  };\n\n\n  function SampleSupport() {\n\n  }\n\n  SampleSupport.prototype.log = function(message) {\n    this.logger.log(message, window, chrome.app.window.current().id);\n  };\n\n  SampleSupport.SNIPPET_WIN_ID = 'show_snippets';\n  SampleSupport.OPEN_SNIPPETS_ANCHOR_ID = '_open_snippets';\n  SampleSupport.LOG_AREA_ID = '__sample_support_logarea';\n\n  SampleSupport.prototype.addListeners = function() {\n    var open_snippets = document.getElementById(\n      SampleSupport.OPEN_SNIPPETS_ANCHOR_ID);\n\n    if (open_snippets) {\n      open_snippets.addEventListener('click', function(e) {\n        e.preventDefault();\n        chrome.app.window.create('sample_support/show_snippets.html',\n          { \"id\": SampleSupport.SNIPPET_WIN_ID,\n            \"innerBounds\": {\n              \"width\": 760,\n              \"height\": 760\n            }\n          });\n      });\n    }\n\n\n  };\n\n  SampleSupport.prototype.initializeLogger = function() {\n    var log_area = document.getElementById(SampleSupport.LOG_AREA_ID);\n\n    // get Logger reference from background page, so\n    // all other windows can access it\n    chrome.runtime.getBackgroundPage( function(bgpage) {\n      this.logger = bgpage.sample_logger;\n\n      // replace existing log area if new log_area is valid\n      if (this.logger && log_area) {\n        this.logger.setLogArea(log_area);\n      }\n\n      // create a new logger\n      if (!this.logger) {\n        this.logger = new Logger(log_area);\n        bgpage.sample_logger = this.logger;\n      }\n\n    }.bind(this));\n\n  }\n\n\n  SampleSupport.prototype.init = function(e) {\n\n    this.initializeLogger();\n    this.addListeners();\n  };\n\n  context.SampleSupport = SampleSupport;\n\n})(window);\n\n\nwindow.sampleSupport = new SampleSupport();\nwindow.addEventListener('DOMContentLoaded',\n  window.sampleSupport.init.bind(window.sampleSupport));\n"
  },
  {
    "path": "_archive/apps/samples/identity/sample_support/show_snippets.html",
    "content": "<html>\n  <head>\n    <title>Source for Sample</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"standard.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"snippets.css\">\n    <link href=\"prettify.css\" type=\"text/css\" rel=\"stylesheet\" />\n    <link href=\"prettify_theme.css\" type=\"text/css\" rel=\"stylesheet\" />\n  </head>\n  <body>\n    <div class=\"snippets\">\n    </div>\n    <script src=\"show_snippets.js\"></script>\n    <script type=\"text/javascript\" src=\"prettify.js\"></script>\n    <script type=\"text/javascript\" src=\"sample_support.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/identity/sample_support/show_snippets.js",
    "content": "'uses strict';\n\nwindow.snippetSupport=(function() {\n\nvar sampleName = '';\n\nfunction processFilesWithSnippets() {\n  var xhr=new XMLHttpRequest();\n  xhr.responseType='json';\n  xhr.open('GET', '../sample_support_metadata.json');\n  xhr.onload=function() {\n    sampleName = this.response.sample;\n  \n    // extract from manifest:\n    extractFromManifest();\n\n    //extract from files with core snippets:\n    var snippetsCount=this.response.files_with_snippets.length;\n    for (var i=0; i<snippetsCount; i++) {\n      var filename = this.response.files_with_snippets[i];\n      var last = false;\n      if (i==snippetsCount-1) {\n        last = true;\n      }\n      getFileContents(filename, function(content) {\n        extractSnippets(content, filename)\n        if (last) {\n          prettyPrint();\n        }\n      });\n    }\n  };\n  xhr.send();\n}\n\nfunction extractFromManifest(content) {\n  var manifest = chrome.runtime.getManifest();\n  // remove common keys\n  delete manifest.key\n  delete manifest.name\n  delete manifest.description\n  delete manifest.manifest_version\n  delete manifest.app\n  delete manifest.version\n  var note=\"// these are only some of the keys relevant to this sample\\n\"+\n    \"// for the complete manifest, click in the 'manifest.json' link above\\n\";\n  addSnippet('Relevant manifest keys',\n    { 'filename': 'manifest.json',\n      'content': note+JSON.stringify(manifest, null, 2)\n    });\n}\n\nfunction getFileContents(filename, callback) {\n  var xhr=new XMLHttpRequest();\n  xhr.open('GET', '../'+filename);\n  xhr.onload=function() {\n    callback(this.responseText);\n  };\n  xhr.send();\n}\n\nfunction addSnippet(snippetName, snippet) {\n  var pre = document.createElement('pre');\n  pre.classList.add('prettyprint');\n  pre.innerText=snippet.content;\n  var h2 = document.createElement('h2');\n  h2.innerText=snippetName;\n  var linkToGithub = document.createElement('span');\n  var githubUrl='https://github.com/GoogleChrome/chrome-app-samples/tree/master/'+\n    'samples/'+sampleName+'/'+snippet.filename;\n  if (snippet.startLine) {\n    githubUrl+='#L'+snippet.startLine+'-L'+snippet.endLine;\n  }\n  var githubUrlHTML = '<a target=\"_blank\" href=\"'+githubUrl+'\">'+snippet.filename;\n  if (snippet.startLine) {\n    githubUrlHTML += ' lines '+snippet.startLine+' to '+snippet.endLine;\n  }\n  githubUrlHTML += '</a>';\n  linkToGithub.innerHTML = githubUrlHTML;\n  h2.appendChild(linkToGithub)\n  var div = document.createElement('div');\n  div.classList.add('snippet');\n  div.appendChild(h2);\n  div.appendChild(pre);\n  document.querySelector('.snippets').appendChild(div);\n}\n\nfunction extractSnippets(content, filename) {\n  var lines=content.split('\\n');\n  var linesCount=lines.length;\n  var reStart=/^\\s*\\/\\/\\s+@corecode_begin\\s*([^ ]*)\\s*$/;\n  var reStop=/^\\s*\\/\\/\\s+@corecode_end\\s*([^ ]*)\\s*$/;\n  var reSpaces=/^(\\s*)/;\n  var snippets={};\n  var openSnippets={};\n  var indentation={};\n  var exec;\n  for (var line=0; line<linesCount; line++) {\n    exec=reStart.exec(lines[line]);\n    if (exec && exec.length>1) {\n      var snippetName = exec[1];\n      // save the indentation\n      var indent = reSpaces.exec(lines[line])[1].length;\n      indentation[snippetName] = indent;\n      openSnippets[snippetName] = snippetName;\n      snippets[snippetName] = {\"content\": \"\", \"filename\": filename,\n        \"startLine\": line+2};\n    } else {\n      exec=reStop.exec(lines[line]);\n      if (exec && exec.length>1) {\n        snippets[snippetKey].endLine=line;\n        delete openSnippets[exec[1]];\n      } else {\n        for (var snippetKey in openSnippets) {\n          var indent = indentation[snippetKey];\n          var strippedLine=lines[line];\n          // make sure we are not stripping non-whitespaces\n          if (/^\\s*$/.test(lines[line].substr(0, indent))) {\n            strippedLine=lines[line].substr(indent);\n          }\n          snippets[snippetKey].content+=strippedLine+'\\n';\n        }\n      }\n    }\n  }\n\n  for (var snippetName in snippets) {\n    addSnippet(snippetName, snippets[snippetName]);\n  }\n}\n\nreturn {\n    \"processFilesWithSnippets\": processFilesWithSnippets\n  }\n\n})();\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  window.snippetSupport.processFilesWithSnippets();\n});\n"
  },
  {
    "path": "_archive/apps/samples/identity/sample_support/snippets.css",
    "content": "html {\n  overflow-y: auto;\n}\n\nbody {\n  padding: 1em;\n}\n\n.snippets {\n}\n\n.snippet {\n  background: white;\n  padding: 10px 20px 0px 20px;\n  margin-top: 20px;\n  border: 1px solid #ddd;\n}\n\n.snippet h2 {\n  margin-top: 0;\n  margin-left: -10px;\n}\n\n.snippet pre {\n  font-size: 13px;\n  overflow: auto;\n  -webkit-user-select: initial;\n}\n\n.snippet h2 span {\n  display: inline-block;\n  margin-left: 1em;\n  font-size: 10px;\n  font-weight: normal;\n}\n\n.snippet h2 span a {\n  text-decoration: none;\n}"
  },
  {
    "path": "_archive/apps/samples/identity/sample_support/standard.css",
    "content": "html, body {\n  margin: 0;\n  font-family: 'Open Sans Regular', sans;\n  color: #666;\n  background: #fafafa;\n}\n\n.header {\n  text-align: center;\n  padding: 10px 0 10px 0;\n}\n\n.header hr {\n  height: 6px;\n  border: none;\n  margin-top: 20px;\n  background: -webkit-linear-gradient(0deg,\n    rgb(51,105,232) 0%,\n    rgb(51,105,232) 25%,\n    rgb(222,30,37) 25%,\n    rgb(222,30,37) 50%,\n    rgb(255, 210, 0) 50%,\n    rgb(255, 210, 0) 75%,\n    rgb(76,187,71) 75%,\n    rgb(76,187,71) 100%\n    );\n }\n\n.header .links * {\n  margin-left: 5px;\n}\n\n.header .links a {\n  color: #666;\n}\n\n.header:hover .links a {\n  color: #3399cc;\n}\n\n.flows h2 {\n  margin-left: 5px;\n  margin-bottom: 10px;\n}\n\n.flow {\n  margin: 10px 20px 20px 20px;\n  border: 1px solid #ddd;\n  padding: 8px;\n  background: white;\n}\n\n.flow button {\n  cursor: pointer;\n  background: -webkit-linear-gradient(top,#008dfd 0,#0370ea 100%);\n  border: 1px solid #076bd2;\n  text-shadow: 1px 1px 1px #076bd2;\n  color: white;\n  font-weight: 700;\n  font-size: 13px;\n  margin: .5em 0 1em;\n  padding: 8px 17px 8px 17px;\n  border-radius: 3px;\n}\n\n.flow button.error {\n  background: -webkit-linear-gradient(top,#008dfd 0,#0370ea 100%);\n  border: 1px solid #076bd2;\n  text-shadow: 1px 1px 1px #076bd2;\n  color: white;\n  font-weight: 700;\n  font-size: 13px;\n  margin: .5em 0 1em;\n  padding: 8px 17px 8px 17px;\n  border-radius: 3px;\n}\n\n.flow button:disabled {\n  background: -webkit-linear-gradient(top, #dcdcdc 0, #fafafa 100%);\n  color: #999;\n  text-shadow: 1px 1px 1px #fafafa;\n  border: 1px solid #ddd;\n  cursor: auto;\n}\n\n.log {\n  margin: 10px 20px 20px 20px;\n}\n\n.log textarea {\n  width: 100%;\n  min-height: 200px;\n  font-family: \"Courier New\", Courier, monospace;\n  margin: 2px;\n  background: #FFFFFF;\n  color: #727272;\n  border: 1px solid rgb(182, 182, 182);\n}\n"
  },
  {
    "path": "_archive/apps/samples/identity/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"identity\",\n  \"files_with_snippets\": [ \"identity.js\" ],\n  \"android\": {\"works\": true, \"comments\": \"You need to add an Android OAuth app in the Cloud API console of the OAuth project. The app's SHA1 can be the debug one (see more <a href=\\\"https://developers.google.com/console/help/new/#installedapplications\\\">here</a>), and the package name is org.chromium.identity.MyApp. If you don't add the Android OAuth app and tries to use the OAuth client-id from the Chrome app, you will get a generic message GoogleAuthException\"}\n}\n"
  },
  {
    "path": "_archive/apps/samples/image-edit/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/foibnkkcggahkmckladbmgkajodpcjfh\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Crop Tool - Image Edit\n\nA tool to crop images.\n\nOpen files, or drag and drop them. Perform a simple crop and save the result.\n\nWorks offline.\n\n## Try it: [Crop Tool - Image Edit](https://chrome.google.com/webstore/detail/crop-tool-image-edit/foibnkkcggahkmckladbmgkajodpcjfh)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/image-edit/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/image-edit/app.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Eric Bidelman (ericbidelman@chromium.org)\n*/\n\nvar canvas = document.querySelector('canvas');\nvar canvasContext = canvas.getContext('2d');\nvar chooseFileButton = document.querySelector('#choose_file');\nvar chosenFileEntry = null;\nvar cropButton = document.querySelector('#crop');\nvar cropCanvas = document.createElement('canvas');\nvar cropCanvasContext = cropCanvas.getContext('2d');\nvar cropSquare = undefined;\nvar cropSquareHandlesSize = 50;\nvar displayOffset = undefined;\nvar displayScale = undefined;\nvar image_display = document.querySelector('#image_display');\nvar img = new Image();\nvar mouseMovingCropParameter = undefined;\nvar mouseLastCoords = undefined;\nvar output = document.querySelector('output');\nvar saveFileButton = document.querySelector('#save_file');\n\nfunction clearState() {\n  img.src = \"\";\n  drawCanvas(); // clear it.\n  resetCrop();\n}\n\nfunction errorHandler(e) {\n  console.error(e);\n}\n\nfunction displayText(text) {\n    output.textContent = text;\n}\n\nfunction displayfileEntryPath(fileEntry) {\n  chrome.fileSystem.getDisplayPath(fileEntry, displayText);\n}\n\nfunction resetCrop() {\n  cropSquare = {\n    x: 0,\n    y: 0,\n    w: img.width,\n    h: img.height\n  };\n}\n\nfunction getHandleHoverData(clientX, clientY) {\n  if (!img.width || !img.height)\n    return undefined;\n\n  var canvasRect = canvas.getBoundingClientRect();\n  var x = clientX - canvasRect.left;\n  var y = clientY - canvasRect.top;\n\n  var inner = getRectInCanvasCoords(cropSquare);\n  var outer = getCropSquareHandlesInCanvasCoords();\n  addRightAndBottomToRect(inner);\n  addRightAndBottomToRect(outer);\n\n  var movingParams = {\n    x: x >= outer.x && x <= inner.x && y >= outer.y && y <= outer.b,\n    w: x >= inner.r && x <= outer.r && y >= outer.y && y <= outer.b,\n    y: y >= outer.y && y <= inner.y && x >= outer.x && x <= outer.r,\n    h: y >= inner.b && y <= outer.b && x >= outer.x && x <= outer.r\n  };\n  return movingParams;\n}\n\nfunction mouseDown (e) {\n  mouseLastCoords = { x: e.clientX, y: e.clientY };\n  mouseMovingCropParameter = getHandleHoverData(e.clientX, e.clientY);\n}\n\nfunction stopTrackingMouseDrag () {\n  mouseLastCoords = undefined;\n  mouseMovingCropParameter = undefined;\n}\n\nfunction mouseMove(e) {\n  if (mouseLastCoords) {\n    moveCrop(e.clientX - mouseLastCoords.x,\n             e.clientY - mouseLastCoords.y);\n    mouseLastCoords = { x: e.clientX, y: e.clientY };\n  } else {\n    // Set mouse cursor.\n    var x = false;\n    var y = false;\n    var movingParams = getHandleHoverData(e.clientX, e.clientY);\n    var moveParamsString =\n        movingParams === undefined ? \"undefined\" :\n        (movingParams.y ? \"n\" : \"\") +\n        (movingParams.h ? \"s\" : \"\") +\n        (movingParams.x ? \"w\" : \"\") +\n        (movingParams.w ? \"e\" : \"\");\n    switch (moveParamsString) {\n      case \"n\":\n      case \"nw\":\n      case \"ne\":\n      case \"s\":\n      case \"sw\":\n      case \"se\":\n      case \"w\":\n      case \"e\":\n        moveParamsString += \"-resize\";\n        break;\n      case \"undefined\":\n        moveParamsString = \"auto\";\n        break;\n      default:\n        moveParamsString = \"move\";\n    };\n    canvas.style.cursor = moveParamsString;\n  }\n}\n\n// x, y, in canvas coordinates.\nfunction moveCrop(dx, dy) {\n  if (!displayScale || !cropSquare || !mouseMovingCropParameter)\n    return;\n\n  var dxs = dx / displayScale;\n  var dys = dy / displayScale;\n\n  if (mouseMovingCropParameter.x) {\n    cropSquare.x += dxs;\n    cropSquare.w = Math.max(cropSquare.w - dxs, 0);\n  }\n  if (mouseMovingCropParameter.y) {\n    cropSquare.y += dys;\n    cropSquare.h = Math.max(cropSquare.h - dys, 0);\n  }\n  if (mouseMovingCropParameter.w) {\n    cropSquare.w += dxs;\n    if (cropSquare.w < 0) {\n      cropSquare.x += cropSquare.w;\n      cropSquare.w = 0;\n    }\n  }\n  if (mouseMovingCropParameter.h) {\n    cropSquare.h += dys;\n    if (cropSquare.h < 0) {\n      cropSquare.y += cropSquare.h;\n      cropSquare.h = 0;\n    }\n  }\n\n  // If not moving a particular element, move the whole frame.\n  if (!mouseMovingCropParameter.x &&\n      !mouseMovingCropParameter.y &&\n      !mouseMovingCropParameter.w &&\n      !mouseMovingCropParameter.h) {\n    cropSquare.x += dxs;\n    cropSquare.y += dys;\n  }\n\n  webkitRequestAnimationFrame(drawCanvas);\n}\n\nfunction updateScaleAndOffset() {\n  if (!img.width || !img.height) {\n    displayScale = undefined;\n    displayOffset = undefined;\n    return;\n  }\n\n  // scale such that image fits on canvas.\n  displayScale = 0.9 * Math.min(\n    canvas.width / img.width,\n    canvas.height / img.height);\n\n  // offset such that image is centered.\n  displayOffset = {\n    x: Math.max(0, canvas.width / displayScale - img.width) / 2,\n    y: Math.max(0, canvas.height / displayScale - img.height) / 2\n  };\n}\n\nfunction getRectInCanvasCoords(rect) {\n  updateScaleAndOffset();\n  if (!displayScale || !displayOffset)\n    return rect;\n\n  return {\n    x: displayScale * (displayOffset.x + rect.x),\n    y: displayScale * (displayOffset.y + rect.y),\n    w: displayScale * rect.w,\n    h: displayScale * rect.h\n  };\n}\n\nfunction getRectInverted(rect) {\n  return {\n    x: rect.x,\n    y: rect.y + rect.h,\n    w: rect.w,\n    h: -rect.h\n  };\n}\n\nfunction addRightAndBottomToRect(rect) {\n  rect.r = rect.x + rect.w;\n  rect.b = rect.y + rect.h;\n}\n\nfunction getCropSquareHandlesInCanvasCoords() {\n  var cropSquareInCanvasCoords = getRectInCanvasCoords(cropSquare);\n  return {\n      x: cropSquareInCanvasCoords.x - cropSquareHandlesSize,\n      y: cropSquareInCanvasCoords.y - cropSquareHandlesSize,\n      w: cropSquareInCanvasCoords.w + 2 * cropSquareHandlesSize,\n      h: cropSquareInCanvasCoords.h + 2 * cropSquareHandlesSize\n  };\n}\n\nfunction canvasRect(rect) {\n  var rectAsInts = copyAsIntegerRect(rect);\n  canvasContext.rect(rectAsInts.x, rectAsInts.y, rectAsInts.w, rectAsInts.h);\n}\n\nfunction drawCanvas() {\n  canvas.width = canvas.clientWidth;\n  canvas.height = canvas.clientHeight;\n  var cc = canvasContext;\n\n  if (!img.width || !img.height || !canvas.width || !canvas.height)\n    return;  // No img, so just leave canvas cleared.\n\n  // Work in the coordinate space of the image.\n  // Scale and translate for optimal display on the canvas.\n  updateScaleAndOffset();\n  var imgRect = { x: 0, y: 0, w: img.width, h: img.height };\n  var imgRectXformed = getRectInCanvasCoords(imgRect);\n  var cropXformed = getRectInCanvasCoords(cropSquare);\n\n  if (displayScale >= 1)\n    cc.imageSmoothingEnabled = false;\n  console.log(cc.imageSmoothingEnabled);\n\n  // Dim area under image.\n  cc.save();\n  cc.beginPath();\n  cc.fillStyle = \"rgba(0, 0, 0, 0.1)\";\n  canvasRect(imgRectXformed);\n  cc.fill();\n  cc.restore();\n\n  cc.drawImage(img, imgRectXformed.x, imgRectXformed.y, imgRectXformed.w, imgRectXformed.h);\n\n  // Draw crop window.\n  cc.save();\n  cc.translate(0.5, 0.5); // draw lines directly on pixels, no anti-aliasing.\n  cc.beginPath();\n  canvasRect(cropXformed);\n  cc.lineWidth = 1;\n  cc.strokeStyle = \"rgba(255, 255, 255, 0.5)\";\n  cc.stroke(); // File whole line white.\n  cc.setLineDash([5]);\n  cc.strokeStyle = \"rgba(0, 0, 0, 0.5)\";\n  cc.strokeStyle = \"black\"; // Dash the line black.\n  cc.stroke();\n  cc.restore();\n}\n\nwindow.onresize = function () {\n  drawCanvas();\n}\n\nfunction loadImageFromFile(file) {\n  loadImageFromURL(URL.createObjectURL(file));\n}\n\nfunction loadImageFromURL(url) {\n  clearState();\n  img.onload = imageHasLoaded;\n  img.onerror = imageHasLoaded;\n  img.src = url;\n}\n\nfunction imageHasLoaded() {\n  if (img.width && img.height) {\n    cropButton.disabled = false;\n  } else {\n    displayText(\"Image failed to load.\");\n    saveFileButton.disabled = true;\n    cropButton.disabled = true;\n  }\n  resetCrop();\n  drawCanvas();\n}\n\nfunction writeFileEntry(writableEntry, opt_blob, callback) {\n  if (!writableEntry) {\n    displayText('Nothing selected.');\n    return;\n  }\n\n  writableEntry.createWriter(function(writer) {\n\n    writer.onerror = errorHandler;\n    writer.onwriteend = callback;\n\n    // If we have data, write it to the file. Otherwise, just use the file we\n    // loaded.\n    if (opt_blob) {\n      writer.truncate(opt_blob.size);\n      waitForIO(writer, function() {\n        writer.seek(0);\n        writer.write(opt_blob);\n      });\n    } else {\n      chosenFileEntry.file(function(file) {\n        writer.truncate(file.fileSize);\n        waitForIO(writer, function() {\n          writer.seek(0);\n          writer.write(file);\n        });\n      });\n    }\n  }, errorHandler);\n}\n\nfunction waitForIO(writer, callback) {\n  // set a watchdog to avoid eventual locking:\n  var start = Date.now();\n  // wait for a few seconds\n  var reentrant = function() {\n    if (writer.readyState===writer.WRITING && Date.now()-start<4000) {\n      setTimeout(reentrant, 100);\n      return;\n    }\n    if (writer.readyState===writer.WRITING) {\n      console.error(\"Write operation taking too long, aborting!\"+\n        \" (current writer readyState is \"+writer.readyState+\")\");\n      writer.abort();\n    } else {\n      callback();\n    }\n  };\n  setTimeout(reentrant, 100);\n}\n\nfunction loadFileEntry(_chosenFileEntry) {\n  chosenFileEntry = _chosenFileEntry;\n  chosenFileEntry.file(function(file) {\n    saveFileButton.disabled = true;\n    loadImageFromFile(file);\n    displayfileEntryPath(chosenFileEntry);\n  });\n}\n\nfunction loadInitialFile(launchData) {\n  if (launchData && launchData.items && launchData.items[0]) {\n    loadFileEntry(launchData.items[0].entry);\n  } else {\n    chrome.storage.local.get('chosenFile', function(items) {\n      if (items.chosenFile) {\n        chrome.fileSystem.restoreEntry(items.chosenFile, function(chosenEntry) {\n          if (chosenEntry) {\n            loadFileEntry(chosenEntry);\n          }\n        });\n      }\n    });\n  }\n}\n\n// Returns intersecting rect { x, y, w, h } of two inputs.\nfunction intersectRects(a, b) {\n  var out = {\n    x: Math.max(a.x, b.x),\n    y: Math.max(a.y, b.y),\n    w: 0,\n    h: 0\n  };\n  out.w = Math.min(a.x + a.w, b.x + b.w) - out.x;\n  out.h = Math.min(a.y + a.h, b.y + b.h) - out.y;\n  out.w = Math.max(out.w, 0);\n  out.w = Math.max(out.w, 0);\n  return out;\n}\n\n// Rounds a rect { x, y, w, h } to integers.\nfunction copyAsIntegerRect(sourceRect) {\n  var out = {\n    x: Math.round(sourceRect.x),\n    y: Math.round(sourceRect.y),\n    w: Math.round(sourceRect.w),\n    h: Math.round(sourceRect.h)\n  };\n  return out;\n}\n\nfunction crop () {\n  if (!cropCanvas ||\n      !cropSquare.w || !cropSquare.h ||\n      !img.width || !img.height)\n    return;\n  displayText(\"Cropped.\");\n  saveFileButton.disabled = false;\n  var clippedRect = intersectRects(\n    {x: 0, y: 0, w: img.width, h: img.height },\n    cropSquare);\n  var intRect = copyAsIntegerRect(clippedRect);\n  cropCanvas.width = intRect.w;\n  cropCanvas.height = intRect.h;\n  cropCanvasContext.drawImage(img, -intRect.x, -intRect.y);\n  loadImageFromURL(cropCanvas.toDataURL());\n}\n\nfunction chooseFile () {\n  var accepts = [{\n    mimeTypes: ['image/*'],\n    extensions: ['jpeg', 'png']\n  }];\n  chrome.fileSystem.chooseEntry({type: 'openFile', accepts: accepts}, function(readOnlyEntry) {\n    if (!readOnlyEntry) {\n      displayText('No file selected.');\n      return;\n    }\n    try { // TODO remove try once retain is in stable.\n    chrome.storage.local.set(\n        {'chosenFile': chrome.fileSystem.retainEntry(readOnlyEntry)});\n    } catch (e) {}\n    loadFileEntry(readOnlyEntry);\n  });\n}\n\nfunction dataURItoBlob(dataURI) {\n  // adapted from:\n  // http://stackoverflow.com/questions/6431281/save-png-canvas-image-to-html5-storage-javascript\n\n  // convert base64 to raw binary data held in a string\n  // doesn't handle URLEncoded DataURIs\n  var byteString = atob(dataURI.split(',')[1]);\n\n  // separate out the mime component\n  var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]\n\n  // write the bytes of the string to an ArrayBuffer\n  var ab = new ArrayBuffer(byteString.length);\n  var ia = new Uint8Array(ab);\n  for (var i = 0; i < byteString.length; i++) {\n      ia[i] = byteString.charCodeAt(i);\n  }\n\n  // write the ArrayBuffer to a blob, and you're done\n  var blob = new Blob([ab], { \"type\": mimeString });\n  return blob;\n};\n\nfunction saveFile() {\n  if (!cropCanvas || !img.width || !img.height)\n    return;\n  cropCanvas.width = img.width;\n  cropCanvas.height = img.height;\n  cropCanvasContext.drawImage(img, 0, 0);\n  var blob = dataURItoBlob(cropCanvas.toDataURL());\n\n  var config = {type: 'saveFile', suggestedName: chosenFileEntry.name};\n  chrome.fileSystem.chooseEntry(config, function(writableEntry) {\n    writeFileEntry(writableEntry, blob, function(e) {\n      displayText('Write complete :)');\n    });\n  });\n}\n\n// Support dropping a single file onto this app.\nfunction draggedDataDropped(data) {\n  items = data.items;\n  chosenFileEntry = null;\n  for (var i = 0; i < data.items.length; i++) {\n    var item = data.items[i];\n    if (item.kind == 'file' &&\n        item.type.match('image/*') &&\n        item.webkitGetAsEntry()) {\n      chosenFileEntry = item.webkitGetAsEntry();\n      break;\n    }\n  };\n\n  if (!chosenFileEntry) {\n    displayText(\"Sorry, could not load file.\");\n    return;\n  } else {\n    displayText(\"Loading dropped file.\");\n  }\n\n  loadFileEntry(chosenFileEntry);\n}\n\nchooseFileButton.addEventListener('click', chooseFile);\n// mousedown on canvas so that interaction only ever starts from the work area.\ncanvas.addEventListener('mousedown', mouseDown);\nwindow.addEventListener('mouseup', stopTrackingMouseDrag);\nwindow.addEventListener('blur', stopTrackingMouseDrag);\n// mousemove on window so that mouse is captured during a drag, keeping\n// updates coming to the window and updating the app.\nwindow.addEventListener('mousemove', mouseMove);\ncropButton.addEventListener('click', crop);\nsaveFileButton.addEventListener('click', saveFile);\nnew DnDFileController('body', draggedDataDropped);\n\nloadInitialFile(launchData);\n"
  },
  {
    "path": "_archive/apps/samples/image-edit/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(\r\n  function(launchData) {\r\n    chrome.app.window.create(\r\n      'index.html',\r\n      { id: \"window\" },\r\n      function(win) {\r\n        win.contentWindow.launchData = launchData;\r\n      });\r\n  });\r\n"
  },
  {
    "path": "_archive/apps/samples/image-edit/dnd.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Eric Bidelman (ericbidelman@chromium.org)\n*/\n\nfunction DnDFileController(selector, onDropCallback) {\n  var el_ = document.querySelector(selector);\n  var overCount = 0;\n\n  this.dragenter = function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n    overCount++;\n    el_.classList.add('dropping');\n  };\n\n  this.dragover = function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n  };\n\n  this.dragleave = function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n    if (--overCount <= 0) {\n      el_.classList.remove('dropping');\n      overCount = 0;\n    }\n  };\n\n  this.drop = function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n\n    el_.classList.remove('dropping');\n\n    onDropCallback(e.dataTransfer)\n  };\n\n  el_.addEventListener('dragenter', this.dragenter, false);\n  el_.addEventListener('dragover', this.dragover, false);\n  el_.addEventListener('dragleave', this.dragleave, false);\n  el_.addEventListener('drop', this.drop, false);\n};\n"
  },
  {
    "path": "_archive/apps/samples/image-edit/index.html",
    "content": "<html>\n<head>\n<style>\nbody {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  display: -webkit-flex;\n  -webkit-flex-direction: column;\n  -webkit-align-items: stretch;\n}\n.dropping {\n  background: #ffcc00;\n}\nnav {\n\tdisplay: -webkit-flex;\n\t-webkit-justify-content: center;\n\t-webkit-align-items: center;\n}\nvideo {\n\twidth: 640px;\n\theight: 480px;\n\tbackground: rgba(0,0,0,0.25);\n}\nbutton {\n  display: inline-block;\n  background: -webkit-linear-gradient(#F9F9F9 40%, #E3E3E3 70%);\n  background: linear-gradient(#F9F9F9 40%, #E3E3E3 70%);\n  border: 1px solid #999;\n  -webkit-border-radius: 3px;\n  border-radius: 3px;\n  padding: 5px 8px;\n  outline: none;\n  white-space: nowrap;\n  -webkit-user-select: none;\n  user-select: none;\n  cursor: pointer;\n  text-shadow: 1px 1px #fff;\n  font-weight: 700;\n  font-size: 10pt;\n}\nbutton:not(:disabled):hover {\n  border-color: black;\n}\nbutton:not(:disabled):active {\n  background: -webkit-linear-gradient(#E3E3E3 40%, #F9F9F9 70%);\n  background: linear-gradient(#E3E3E3 40%, #F9F9F9 70%);\n}\ninput, textarea {\n  box-shadow: 1px 1px 5px #ccc inset;\n  border: none;\n  padding: .5em;\n}\n[readonly] {\n  background: #eee;\n}\n[hidden] {\n  display: none;\n}\ntextarea {\n  width: 100%;\n  height: 200px;\n  outline: none;\n  padding: 1px;\n  font-size: 20px;\n  padding: 1em;\n}\noutput {\n  text-align: center;\n  padding: 1em;\n  display: block;\n}\n#image_display {\n  -webkit-flex: 1;\n  display: -webkit-flex;\n  -webkit-align-items: stretch;\n}\ncanvas {\n  -webkit-flex: 1;\n  min-width: 0;\n  min-height: 0;\n  border: 1px #aaa solid;\n  box-shadow: 0px 2px 10px rgba(0,0,0,0.5) inset;\n  background-image: url('assets/work_area_background.png');\n  background-repeat: repeat;\n}\n</style>\n</head>\n<body>\n  <nav>\n    <button id=\"choose_file\">Choose File</button>\n    <button id=\"crop\" disabled>Apply Crop</button>\n    <button id=\"save_file\" disabled>Save As</button>\n  </nav>\n\n  <output>Load a file.</output>\n\n  <div id=\"image_display\">\n    <canvas></canvas>\n  </div>\n\n  <script src=\"dnd.js\"></script>\n  <script src=\"app.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/image-edit/manifest.json",
    "content": "{\n  \"name\": \"Crop Tool - Image Edit\",\n  \"version\": \"8.1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"28\",\n  \"description\": \"A tool to crop images.\",\n  \"offline_enabled\": true,\n  \"icons\": { \"128\": \"assets/icon_128.png\" },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [\n    {\"fileSystem\": [\"write\", \"retainEntries\"]},\n    \"storage\"\n  ],\n  \"file_handlers\": {\n    \"image\": {\n      \"types\": [\n        \"image/png\",\n        \"image/jpeg\"\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/instagram-auth/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/baaenjnmlaejajnalldcecpdafeggelb\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Instagram Demo\n\nThis is a basic Instagram client implemented as a packaged app.  This demonstration simply displays the users logged-in view as raw JSON.\n\nTo log into Instagram, it uses the [identity API](http://developer.chrome.com/apps/identity.html) (specfically, the `launchWebAuthFlow` method). Once it gets the OAuth token it makes a request to an authenticated endpoint to get the JSON feed of the user's view.\n\nWhen running it unpacked, it will normally have a different ID (the unpacked\nextension ID is a hash of the path on disk). However, this will result in the\nauth API not working, since the redirect URL will be different. To force the\nunpacked app to have the same ID, add this key and value to `manifest.json`:\n\n    \"key\": \"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCM9NA1cLHYrp+htpkHWHmXKAXja/DNfyrSb2mkvfGRT/JVxbPDXJqeRXwhqwYpxgNxMxcD8skIqSy6zHWqtymzjqyFVbMg4ox7qyLC7dEMdx0TgstYjtC3KjEZNM7VM0gRlReJoQuSM/GSIGnAlUjP7Ahd1XF16JgZPICSoeFiTQIDAQAB\",\n\n(this is a base 64 encoded version of the app's public key)\n\nThe key *must* be removed before uploading it to the store.\n\n## Resources\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n* [Identity](https://developer.chrome.com/docs/apps/app_identity/)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/instagram-auth/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/instagram-auth/_locales/en/messages.json",
    "content": "{\n  \"appName\": {\n    \"message\": \"Sample of Instagram Integration\",\n    \"description\": \"The name of the application\"\n  },\n  \"appDescription\": {\n    \"message\": \"Displays the users logged-in view as raw JSON\",\n    \"description\": \"The description of the application\"\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/instagram-auth/index.html",
    "content": "<!doctype html>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>Step1</title>\n        <!-- build:css styles/app.css -->\n        <link rel=\"stylesheet\" href=\"styles/main.css\">\n        <!-- endbuild -->\n        <script src=\"index.js\"></script>\n        <style>\n          pre {\noverflow-y: scroll;\noverflow-x: hidden;\nposition: absolute;\nbottom: 0;\ntop: 120px;\nbox-shadow: inset 0px 0px 5px black;\npadding: 5px;\nright: 0;\nleft: 0;\n          }</style>\n    </head>\n    <body>\n        <h1>Step1</h1>\n        <button id=\"login\">Log in</button>\n        <pre id=\"output\">\n\n        </pre>\n    </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/instagram-auth/index.js",
    "content": "onload = function() {\n  var login = document.getElementById(\"login\");\n  var output = document.getElementById(\"output\");\n\n  login.onclick = function() {\n    var redirectUrl = chrome.identity.getRedirectURL();\n    var clientId = \"1ac94815c30440efa6f7de3c0d529515\";\n    var authUrl = \"https://instagram.com/oauth/authorize/?\" +\n        \"client_id=\" + clientId + \"&\" +\n        \"response_type=token&\" +\n        \"redirect_uri=\" + encodeURIComponent(redirectUrl);\n \n    chrome.identity.launchWebAuthFlow({url: authUrl, interactive: true},\n        function(responseUrl) {\n      console.log(responseUrl);\n      var accessToken = responseUrl.substring(responseUrl.indexOf(\"=\") + 1);\n      console.log(accessToken);\n\n      var api = new InstagramAPI(accessToken);\n      api.request(\"users/self/feed\", undefined, function(data) {  \n        console.log(data);\n        output.textContent = JSON.stringify(data, null, 4);\n        \n\n      });\n    });\n  };\n};\n\nvar InstagramAPI = function(accessToken) {\n  this.request = function(method, arguments, callback) {\n    var xhr = new XMLHttpRequest();\n    xhr.onload = function() {\n      callback(JSON.parse(xhr.response));\n    };\n\n    xhr.open(\"GET\", \"https://api.instagram.com/v1/\" + method + \"?access_token=\" + accessToken);\n    xhr.send();\n  };\n}\n"
  },
  {
    "path": "_archive/apps/samples/instagram-auth/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function(intentData) {\n    chrome.app.window.create('index.html', {\n    \tid: \"instagramAuthWinID\",\n        innerBounds: {\n            width: 500,\n            height: 309\n        }\n    });\n});\n"
  },
  {
    "path": "_archive/apps/samples/instagram-auth/manifest.json",
    "content": "{\n  \"name\": \"__MSG_appName__\",\n  \"version\": \"2.1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"33\",\n  \"description\": \"__MSG_appDescription__\",\n  \"default_locale\": \"en\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\"identity\", \"https://api.instagram.com/*\"]\n}\n"
  },
  {
    "path": "_archive/apps/samples/instagram-auth/styles/main.css",
    "content": "/* Will be compiled down to a single stylesheet with your sass files */"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/README.md",
    "content": "This is the slide deck for the Google I/O 2012 \"The Next Evolution of Chrome Apps\" session. It itself is a Chrome packaged app. It currently runs in Chrome 22.0.1190.0 or later (as of 6/29/2012, this means canary channel only).\n\nThe session itself (including live demos) is [available on YouTube](https://www.youtube.com/watch?v=j8oFAr1YR-0).\n\nThe text editor used in the presentation is itself a Chrome packaged app. It's [available in the samples repository](https://github.com/GoogleChrome/chrome-app-samples/tree/main/_archive/apps/samples/mini-code-edit).\n\nThe `helloworld` directory contains the \"Hello World!\" demo from the session, including the variant with the XSS issue (which can't be exploited due to CSP).\n\nThe `diff-sample-files` directory contains the two local files that were diff-ed during the offline diff tool demo (the diff tool itself is also [available in the samples repository](https://github.com/GoogleChrome/chrome-app-samples/tree/main/_archive/apps/samples/diff)).\n\nThe `servo` directory contains the standalone version of the serial port API spinner demo. It only does writes to the serial port. The [complete version in the samples repository](https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/servo) has the full read/write implementation.\n\nThe `windowing_api` directory contains the source for the custom window frame and windowing API documentation (it's launched via the \"Demo\" link on slide 7).\n\n## Screenshot\n![screenshot](/_archive/apps/samples/io2012-presentation/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/css/presentation.css",
    "content": "@font-face {\n  font-family: 'Inconsolata';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Inconsolata'), url(../theme/inconsolata.woff) format('woff');\n}\n.link {\n  color: blue;\n  text-decoration: underline;\n  cursor: pointer;\n}\n\n#remember_icons {\n  padding: 100px 20px;\n  text-align: center;\n}\n\n#remember_icons .icon {\n  width: 128px;\n  height: 128px;\n  padding: 0px 20px;\n}\n\n#remember_icons.build .to-build {\n  -webkit-transform: translateY(300px);\n}\n\n#remember_icons > * {\n  -webkit-transition: all 0.5s ease-in-out 0.2s;\n  transition: all 0.5s ease-in-out 0.2s;\n}\n\n#ecosystem {\n  background: url(../images/ecosystem.png) no-repeat bottom right;\n  background-size: 350px;\n  height: 500px;\n}\n\n#ecosystem_blocks {\n  padding-top: 100px;\n}\n\n#ecosystem_blocks > * {\n  -webkit-transition: all 0.5s ease-in-out 0.2s;\n}\n\n.ecoblock {\n  display: block;\n  min-height: 100px;\n  width: 600px;\n  vertical-align: top;\n  Xcolor: #515151;\n}\n\n.ecoblock.to-build {\n  -webkit-transform: rotateY(90deg);\n}\n\n.ecoblock_left {\n  display: inline-block;\n  vertical-align: top;\n  width: 180px;\n}\n\n.vdivider {\n  margin: 0px 10px;\n  display: inline-block;\n  width: 2px;\n  height: 40px;\n  background-color: #a9a9a9;\n}\n\n.ecoblock_right {\n  display: inline-block;\n  padding-left: 20px;\n  vertical-align: top;\n  font-size: 100%;\n}\n\n.ecoblock_right div {\n  display: inline-block;\n  font-weight: bold;\n}\n.ecoblock_right div:nth-child(1) {\n  font-size: 40px;\n  color: #4387fd;\n}\n\n.ecoblock_right div:nth-child(2) {\n  font-size: 16px;\n  text-transform: uppercase;\n}\n\n.bignumber {\n  font-size: 40px;\n  font-weight: bold;\n  display: inline-block;\n}\n\n#evolution_blocks {\n  margin: 150px auto;\n}\n\n#evolution_blocks > * {\n  -webkit-transition: all 0.5s ease-in-out 0.2s;\n}\n\n.evoblock {\n  padding: 5px 0px 0px 0px;\n  display: inline-block;\n  min-height: 120px;\n  width: 180px;\n  vertical-align: top;\n  font-size: 24px;\n}\n\n.evoblock.to-build {\n  -XXwebkit-transform: rotateY(90deg);\n}\n\n.bluebg {\n  border-top: 10px solid #4387fd;\n}\n\n.redbg {\n  border-top: 10px solid #f44a3f;\n}\n\n.greenbg {\n  border-top: 10px solid #0da861;\n}\n\n.yellowbg {\n  border-top: 10px solid #ffd14d;\n}\n\n.topborder hgroup {\n  margin-top: -20px;\n  padding-top: 10px;\n}\n\n.chromelogo {\n  font-size: 60px;\n  display: -webkit-box !important;\n  -webkit-box-orient: vertical;\n  -webkit-box-align: center;\n  -webkit-box-pack: center;\n  height: 100%;\n  width: 100%;\n}\n\n.chromelogo img {\n  width: 100px;\n  height: 100px;\n}\n\n#chrometext {\n  position: relative;\n  top: -30px;\n  left: 10px;\n  display: inline-block;\n  letter-spacing: -3px;\n}\n\n.spinner-demo {\n  -webkit-transition: all .5s ease-in-out;\n  opacity: 0;\n  position: absolute;\n  top: 90px;\n  right: 10px;\n  width: 640px;\n  height: 500px;\n  text-align: center;\n}\n\n.spinner-demo.visible {\n  opacity: 1;\n}\n\n#spinner-input {\n   -webkit-appearance:none !important;\n  width: 400px;\n  height: 6px;\n  background: rgb(13, 168, 97);\n}\n\n#spinner-input::-webkit-slider-thumb {\n  -webkit-appearance:none !important;\n  width: 30px;\n  height: 30px;\n  border-radius: 15px;\n  background: rgb(67, 135, 253);\n}\n\n#spinner-error {\n  -webkit-transition: all .5s ease-in-out;\n  opacity: 0;\n  font-size: 12px;\n}\n\n#spinner-error.visible {\n  opacity: 1.0;\n}\n\naside.demobutton {\n  height: 67px;\n  position: absolute;\n  right: -1px;\n  top: 125px;\n  -webkit-border-radius: 10px 0px 0px 10px;\n  background: -webkit-linear-gradient(left, #e6e6e6, #e6e6e6) no-repeat;\n  -webkit-transition: all 0.1s ease-out 0.1s;\n  padding: 30px 20px 0px 20px;\n}\n\n.demobutton:after {\n  content: \"Demo\";\n}\n\n.demobutton:hover {\n  color: #4387fd;\n}\n\n.demobutton.hidden {\n  display: none;\n}\n\n.ul {\n  margin-left: 1.2em;\n  margin-bottom: 1em;\n}\n\n.li {\n  margin-bottom: 0.5em;\n}\n\n.li:before {\n  content: '·';\n  margin-left: -1em;\n  position: absolute;\n  font-weight: 600;\n}\n\n#sandbox img {\n  height: 80px;\n  margin: 20px 20px 20px 0px;\n  display: block;\n}\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/css/theme.css",
    "content": "/* line 17, ../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */\nhtml, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, big, cite, code,\ndel, dfn, em, img, ins, kbd, q, s, samp,\nsmall, strike, strong, sub, sup, tt, var,\nb, u, i, center,\ndl, dt, dd, ol, ul, li,\nfieldset, form, label, legend,\ntable, caption, tbody, tfoot, thead, tr, th, td,\narticle, aside, canvas, details, embed,\nfigure, figcaption, footer, header, hgroup,\nmenu, nav, output, ruby, section, summary,\ntime, mark, audio, video {\n  margin: 0;\n  padding: 0;\n  border: 0;\n  font-size: 100%;\n  font: inherit;\n  vertical-align: baseline;\n}\n\n/* line 20, ../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */\nbody {\n  line-height: 1;\n}\n\n/* line 22, ../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */\nol, ul {\n  list-style: none;\n}\n\n/* line 24, ../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n/* line 26, ../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */\ncaption, th, td {\n  text-align: left;\n  font-weight: normal;\n  vertical-align: middle;\n}\n\n/* line 28, ../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */\nq, blockquote {\n  quotes: none;\n}\n/* line 101, ../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */\nq:before, q:after, blockquote:before, blockquote:after {\n  content: \"\";\n  content: none;\n}\n\n/* line 30, ../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */\na img {\n  border: none;\n}\n\n/* line 114, ../../../../../../Library/Ruby/Gems/1.8/gems/compass-0.12.1/frameworks/compass/stylesheets/compass/reset/_utilities.scss */\narticle, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary {\n  display: block;\n}\n\n/**\n * Base SlideDeck Styles\n */\n/* line 48, ../scss/_base.scss */\nhtml {\n  height: 100%;\n  overflow: hidden;\n}\n\n/* line 53, ../scss/_base.scss */\nbody {\n  margin: 0;\n  padding: 0;\n  opacity: 0;\n  height: 100%;\n  min-height: 740px;\n  width: 100%;\n  overflow: hidden;\n  color: #fff;\n  -webkit-font-smoothing: antialiased;\n  -moz-font-smoothing: antialiased;\n  -ms-font-smoothing: antialiased;\n  -o-font-smoothing: antialiased;\n  -webkit-transition: opacity 800ms ease-in 100ms;\n  -moz-transition: opacity 800ms ease-in 100ms;\n  -ms-transition: opacity 800ms ease-in 100ms;\n  -o-transition: opacity 800ms ease-in 100ms;\n  transition: opacity 800ms ease-in 100ms;\n}\n/* line 69, ../scss/_base.scss */\nbody.loaded {\n  opacity: 1 !important;\n}\n\n/* line 74, ../scss/_base.scss */\ninput, button {\n  vertical-align: middle;\n}\n\n/* line 78, ../scss/_base.scss */\nslides > slide[hidden] {\n  display: none !important;\n}\n\n/* line 82, ../scss/_base.scss */\nslides {\n  width: 100%;\n  height: 100%;\n  position: absolute;\n  left: 0;\n  top: 0;\n  -webkit-transform: translate3d(0, 0, 0);\n  -moz-transform: translate3d(0, 0, 0);\n  -ms-transform: translate3d(0, 0, 0);\n  -o-transform: translate3d(0, 0, 0);\n  transform: translate3d(0, 0, 0);\n  -webkit-perspective: 1000;\n  perspective: 1000;\n  -webkit-transform-style: preserve-3d;\n  transform-style: preserve-3d;\n  -webkit-transition: opacity 800ms ease-in 100ms;\n  -moz-transition: opacity 800ms ease-in 100ms;\n  -ms-transition: opacity 800ms ease-in 100ms;\n  -o-transition: opacity 800ms ease-in 100ms;\n  transition: opacity 800ms ease-in 100ms;\n}\n\n/* line 94, ../scss/_base.scss */\nslides > slide {\n  display: block;\n  position: absolute;\n  overflow: hidden;\n  left: 50%;\n  top: 50%;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\n/* Slide styles */\n/*article.fill iframe {\n  position: absolute;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n\n  border: 0;\n  margin: 0;\n\n  @include border-radius(10px);\n\n  z-index: -1;\n}\n\nslide.fill {\n  background-repeat: no-repeat;\n  @include background-size(cover);\n}\n\nslide.fill img {\n  position: absolute;\n  left: 0;\n  top: 0;\n  min-width: 100%;\n  min-height: 100%;\n\n  z-index: -1;\n}\n*/\n/**\n * Theme Styles\n */\n/* line 58, ../scss/default.scss */\n::selection {\n  color: white;\n  background-color: #ffd14d;\n  text-shadow: none;\n}\n\n/* line 64, ../scss/default.scss */\n::-webkit-scrollbar {\n  height: 16px;\n  overflow: visible;\n  width: 16px;\n}\n\n/* line 69, ../scss/default.scss */\n::-webkit-scrollbar-thumb {\n  background-color: rgba(0, 0, 0, 0.1);\n  background-clip: padding-box;\n  border: solid transparent;\n  min-height: 28px;\n  padding: 100px 0 0;\n  -webkit-box-shadow: inset 1px 1px 0 rgba(0, 0, 0, 0.1), inset 0 -1px 0 rgba(0, 0, 0, 0.07);\n  -moz-box-shadow: inset 1px 1px 0 rgba(0, 0, 0, 0.1), inset 0 -1px 0 rgba(0, 0, 0, 0.07);\n  box-shadow: inset 1px 1px 0 rgba(0, 0, 0, 0.1), inset 0 -1px 0 rgba(0, 0, 0, 0.07);\n  border-width: 1px 1px 1px 6px;\n}\n\n/* line 78, ../scss/default.scss */\n::-webkit-scrollbar-thumb:hover {\n  background-color: rgba(0, 0, 0, 0.5);\n}\n\n/* line 81, ../scss/default.scss */\n::-webkit-scrollbar-button {\n  height: 0;\n  width: 0;\n}\n\n/* line 85, ../scss/default.scss */\n::-webkit-scrollbar-track {\n  background-clip: padding-box;\n  border: solid transparent;\n  border-width: 0 0 0 4px;\n}\n\n/* line 90, ../scss/default.scss */\n::-webkit-scrollbar-corner {\n  background: transparent;\n}\n\n/* line 94, ../scss/default.scss */\nbody {\n  background: black;\n}\n\n/* line 98, ../scss/default.scss */\nslides > slide {\n  display: none;\n  font-family: 'Open Sans', Arial, sans-serif;\n  font-size: 26px;\n  color: #797979;\n  width: 900px;\n  height: 700px;\n  margin-left: -450px;\n  margin-top: -350px;\n  padding: 40px 60px;\n  -webkit-transition: all 0.6s ease-in-out;\n  -moz-transition: all 0.6s ease-in-out;\n  -ms-transition: all 0.6s ease-in-out;\n  -o-transition: all 0.6s ease-in-out;\n  transition: all 0.6s ease-in-out;\n}\n/* line 119, ../scss/default.scss */\nslides > slide.far-past {\n  display: none;\n}\n/* line 126, ../scss/default.scss */\nslides > slide.past {\n  display: block;\n  opacity: 0;\n}\n/* line 133, ../scss/default.scss */\nslides > slide.current {\n  display: block;\n  opacity: 1;\n}\n/* line 139, ../scss/default.scss */\nslides > slide.current .auto-fadein {\n  opacity: 1;\n}\n/* line 143, ../scss/default.scss */\nslides > slide.current .gdbar {\n  -webkit-background-size: 100% 100%;\n  -moz-background-size: 100% 100%;\n  -o-background-size: 100% 100%;\n  background-size: 100% 100%;\n}\n/* line 148, ../scss/default.scss */\nslides > slide.next {\n  display: block;\n  opacity: 0;\n  pointer-events: none;\n}\n/* line 156, ../scss/default.scss */\nslides > slide.far-next {\n  display: none;\n}\n/* line 163, ../scss/default.scss */\nslides > slide.dark {\n  background: #515151 !important;\n}\n/* line 171, ../scss/default.scss */\nslides > slide:not(.nobackground):before {\n  font-size: 12pt;\n  content: \"#io12\";\n  position: absolute;\n  bottom: 20px;\n  left: 60px;\n  background: url(../images/chrome-logo-tiny.png) no-repeat 0 50%;\n  -webkit-background-size: 30px 30px;\n  -moz-background-size: 30px 30px;\n  -o-background-size: 30px 30px;\n  background-size: 30px 30px;\n  padding-left: 40px;\n  height: 30px;\n  line-height: 1.9;\n}\n/* line 183, ../scss/default.scss */\nslides > slide:not(.nobackground):after {\n  font-size: 12pt;\n  content: attr(data-slide-num) \"/\" attr(data-total-slides);\n  position: absolute;\n  bottom: 20px;\n  right: 60px;\n  line-height: 1.9;\n}\n/* line 194, ../scss/default.scss */\nslides > slide.title-slide:after {\n  content: '';\n  background: url(../images/io2012-logo.png) no-repeat 100% 50%;\n  -webkit-background-size: contain;\n  -moz-background-size: contain;\n  -o-background-size: contain;\n  background-size: contain;\n  position: absolute;\n  bottom: 40px;\n  right: 40px;\n  width: 100%;\n  height: 60px;\n}\n/* line 206, ../scss/default.scss */\nslides > slide.backdrop {\n  z-index: -10;\n  display: block !important;\n  background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(85%, #ffffff), color-stop(100%, #e6e6e6));\n  background: -webkit-linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n  background: -moz-linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n  background: -o-linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n  background: -ms-linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n  background: linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n  background-color: white;\n}\n/* line 211, ../scss/default.scss */\nslides > slide.backdrop:after, slides > slide.backdrop:before {\n  display: none;\n}\n/* line 216, ../scss/default.scss */\nslides > slide > hgroup + article {\n  margin-top: 45px;\n}\n/* line 220, ../scss/default.scss */\nslides > slide > hgroup + article.flexbox.vcenter, slides > slide > hgroup + article.flexbox.vleft, slides > slide > hgroup + article.flexbox.vright {\n  height: 80%;\n}\n/* line 225, ../scss/default.scss */\nslides > slide > hgroup + article p {\n  margin-bottom: 1em;\n}\n/* line 230, ../scss/default.scss */\nslides > slide > article:only-child {\n  height: 100%;\n}\n/* line 233, ../scss/default.scss */\nslides > slide > article:only-child > iframe {\n  height: 100%;\n}\n\n/* line 239, ../scss/default.scss */\nslides.layout-faux-widescreen > slide {\n  padding: 40px 160px;\n}\n\n/* line 248, ../scss/default.scss */\nslides.layout-widescreen > slide,\nslides.layout-faux-widescreen > slide {\n  margin-left: -550px;\n  width: 1100px;\n}\n/* line 253, ../scss/default.scss */\nslides.layout-widescreen > slide.far-past,\nslides.layout-faux-widescreen > slide.far-past {\n  display: block;\n  display: none;\n  -webkit-transform: translate(-2260px);\n  -moz-transform: translate(-2260px);\n  -ms-transform: translate(-2260px);\n  -o-transform: translate(-2260px);\n  transform: translate(-2260px);\n  -webkit-transform: translate3d(-2260px, 0, 0);\n  -moz-transform: translate3d(-2260px, 0, 0);\n  -ms-transform: translate3d(-2260px, 0, 0);\n  -o-transform: translate3d(-2260px, 0, 0);\n  transform: translate3d(-2260px, 0, 0);\n}\n/* line 260, ../scss/default.scss */\nslides.layout-widescreen > slide.past,\nslides.layout-faux-widescreen > slide.past {\n  display: block;\n  opacity: 0;\n}\n/* line 267, ../scss/default.scss */\nslides.layout-widescreen > slide.current,\nslides.layout-faux-widescreen > slide.current {\n  display: block;\n  opacity: 1;\n}\n/* line 274, ../scss/default.scss */\nslides.layout-widescreen > slide.next,\nslides.layout-faux-widescreen > slide.next {\n  display: block;\n  opacity: 0;\n  pointer-events: none;\n}\n/* line 282, ../scss/default.scss */\nslides.layout-widescreen > slide.far-next,\nslides.layout-faux-widescreen > slide.far-next {\n  display: block;\n  display: none;\n  -webkit-transform: translate(2260px);\n  -moz-transform: translate(2260px);\n  -ms-transform: translate(2260px);\n  -o-transform: translate(2260px);\n  transform: translate(2260px);\n  -webkit-transform: translate3d(2260px, 0, 0);\n  -moz-transform: translate3d(2260px, 0, 0);\n  -ms-transform: translate3d(2260px, 0, 0);\n  -o-transform: translate3d(2260px, 0, 0);\n  transform: translate3d(2260px, 0, 0);\n}\n/* line 289, ../scss/default.scss */\nslides.layout-widescreen #prev-slide-area,\nslides.layout-faux-widescreen #prev-slide-area {\n  margin-left: -650px;\n}\n/* line 293, ../scss/default.scss */\nslides.layout-widescreen #next-slide-area,\nslides.layout-faux-widescreen #next-slide-area {\n  margin-left: 550px;\n}\n\n/* line 298, ../scss/default.scss */\nb {\n  font-weight: 600;\n}\n\n/* line 302, ../scss/default.scss */\na {\n  color: #2a7cdf;\n  text-decoration: none;\n  border-bottom: 1px solid rgba(42, 124, 223, 0.5);\n}\n/* line 307, ../scss/default.scss */\na:hover {\n  color: black !important;\n}\n\n/* line 312, ../scss/default.scss */\nh1, h2, h3 {\n  font-weight: 600;\n}\n\n/* line 316, ../scss/default.scss */\nh2 {\n  font-size: 45px;\n  line-height: 45px;\n  letter-spacing: -2px;\n  color: #515151;\n}\n\n/* line 323, ../scss/default.scss */\nh3 {\n  font-size: 30px;\n  letter-spacing: -1px;\n  line-height: 2;\n  font-weight: inherit;\n  color: #797979;\n}\n\n/* line 331, ../scss/default.scss */\nul {\n  margin-left: 1.2em;\n  margin-bottom: 1em;\n  position: relative;\n}\n/* line 336, ../scss/default.scss */\nul li {\n  margin-bottom: 0.5em;\n}\n/* line 339, ../scss/default.scss */\nul li ul {\n  margin-left: 2em;\n  margin-bottom: 0;\n}\n/* line 343, ../scss/default.scss */\nul li ul li:before {\n  content: '-';\n  font-weight: 600;\n}\n/* line 350, ../scss/default.scss */\nul > li:before {\n  content: '·';\n  margin-left: -1em;\n  position: absolute;\n  font-weight: 600;\n}\n/* line 357, ../scss/default.scss */\nul ul {\n  margin-top: .5em;\n}\n\n/* line 364, ../scss/default.scss */\n.highlight-code slide.current pre > * {\n  opacity: 0.25;\n  -webkit-transition: opacity 0.5s ease-in;\n  -moz-transition: opacity 0.5s ease-in;\n  -ms-transition: opacity 0.5s ease-in;\n  -o-transition: opacity 0.5s ease-in;\n  transition: opacity 0.5s ease-in;\n}\n/* line 368, ../scss/default.scss */\n.highlight-code slide.current b {\n  opacity: 1;\n}\n\n/* line 373, ../scss/default.scss */\npre {\n  font-family: 'Inconsolata', 'Courier New', monospace;\n  font-size: 20px;\n  line-height: 28px;\n  padding: 10px 0 10px 60px;\n  letter-spacing: -1px;\n  margin-bottom: 20px;\n  width: 106%;\n  background-color: #e6e6e6;\n  left: -60px;\n  position: relative;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  /*overflow: hidden;*/\n}\n/* line 387, ../scss/default.scss */\npre[data-lang]:after {\n  content: attr(data-lang);\n  background-color: #a9a9a9;\n  right: 0;\n  top: 0;\n  position: absolute;\n  font-size: 16pt;\n  color: white;\n  padding: 2px 25px;\n  text-transform: uppercase;\n}\n\n/* line 400, ../scss/default.scss */\npre[data-lang=\"go\"] {\n  color: #333;\n}\n\n/* line 404, ../scss/default.scss */\ncode {\n  font-size: 95%;\n  font-family: 'Inconsolata', 'Courier New', monospace;\n  color: black;\n}\n\n/* line 410, ../scss/default.scss */\niframe {\n  width: 100%;\n  height: 530px;\n  background: white;\n  border: 1px solid #e6e6e6;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\n/* line 418, ../scss/default.scss */\ndt {\n  font-weight: bold;\n}\n\n/* line 422, ../scss/default.scss */\nbutton {\n  display: inline-block;\n  background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(40%, #f9f9f9), color-stop(70%, #e3e3e3));\n  background: -webkit-linear-gradient(#f9f9f9 40%, #e3e3e3 70%);\n  background: -moz-linear-gradient(#f9f9f9 40%, #e3e3e3 70%);\n  background: -o-linear-gradient(#f9f9f9 40%, #e3e3e3 70%);\n  background: -ms-linear-gradient(#f9f9f9 40%, #e3e3e3 70%);\n  background: linear-gradient(#f9f9f9 40%, #e3e3e3 70%);\n  border: 1px solid #a9a9a9;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  -ms-border-radius: 3px;\n  -o-border-radius: 3px;\n  border-radius: 3px;\n  padding: 5px 8px;\n  outline: none;\n  white-space: nowrap;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  user-select: none;\n  cursor: pointer;\n  text-shadow: 1px 1px white;\n  font-size: 10pt;\n}\n\n/* line 436, ../scss/default.scss */\nbutton:not(:disabled):hover {\n  border-color: #515151;\n}\n\n/* line 440, ../scss/default.scss */\nbutton:not(:disabled):active {\n  background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(40%, #e3e3e3), color-stop(70%, #f9f9f9));\n  background: -webkit-linear-gradient(#e3e3e3 40%, #f9f9f9 70%);\n  background: -moz-linear-gradient(#e3e3e3 40%, #f9f9f9 70%);\n  background: -o-linear-gradient(#e3e3e3 40%, #f9f9f9 70%);\n  background: -ms-linear-gradient(#e3e3e3 40%, #f9f9f9 70%);\n  background: linear-gradient(#e3e3e3 40%, #f9f9f9 70%);\n}\n\n/* line 444, ../scss/default.scss */\n:disabled {\n  color: #a9a9a9;\n}\n\n/* line 448, ../scss/default.scss */\n.blue {\n  color: #4387fd;\n}\n\n/* line 451, ../scss/default.scss */\n.blue2 {\n  color: #3c8ef3;\n}\n\n/* line 454, ../scss/default.scss */\n.blue3 {\n  color: #2a7cdf;\n}\n\n/* line 457, ../scss/default.scss */\n.yellow {\n  color: #ffd14d;\n}\n\n/* line 460, ../scss/default.scss */\n.yellow2 {\n  color: #f9cc46;\n}\n\n/* line 463, ../scss/default.scss */\n.yellow3 {\n  color: #f6c000;\n}\n\n/* line 466, ../scss/default.scss */\n.green {\n  color: #0da861;\n}\n\n/* line 469, ../scss/default.scss */\n.green2 {\n  color: #00a86d;\n}\n\n/* line 472, ../scss/default.scss */\n.green3 {\n  color: #009f5d;\n}\n\n/* line 475, ../scss/default.scss */\n.red {\n  color: #f44a3f;\n}\n\n/* line 478, ../scss/default.scss */\n.red2 {\n  color: #e0543e;\n}\n\n/* line 481, ../scss/default.scss */\n.red3 {\n  color: #d94d3a;\n}\n\n/* line 484, ../scss/default.scss */\n.gray {\n  color: #e6e6e6;\n}\n\n/* line 487, ../scss/default.scss */\n.gray2 {\n  color: #a9a9a9;\n}\n\n/* line 490, ../scss/default.scss */\n.gray3 {\n  color: #797979;\n}\n\n/* line 493, ../scss/default.scss */\n.gray4 {\n  color: #515151;\n}\n\n/* line 497, ../scss/default.scss */\n.white {\n  color: white !important;\n}\n\n/* line 500, ../scss/default.scss */\n.black {\n  color: black !important;\n}\n\n/* line 504, ../scss/default.scss */\n.columns-2 {\n  -webkit-column-count: 2;\n  -moz-column-count: 2;\n  -o-column-count: 2;\n  column-count: 2;\n}\n\n/* line 508, ../scss/default.scss */\ntable {\n  width: 100%;\n  border-collapse: -moz-initial;\n  border-collapse: initial;\n  border-spacing: 2px;\n  border-bottom: 1px solid #797979;\n}\n/* line 515, ../scss/default.scss */\ntable tr > td:first-child, table th {\n  font-weight: 600;\n  color: #515151;\n}\n/* line 520, ../scss/default.scss */\ntable tr:nth-child(odd) {\n  background-color: #e6e6e6;\n}\n/* line 524, ../scss/default.scss */\ntable th {\n  color: white;\n  font-size: 18px;\n  background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(40%, #4387fd), color-stop(80%, #2a7cdf)) no-repeat;\n  background: -webkit-linear-gradient(top, #4387fd 40%, #2a7cdf 80%) no-repeat;\n  background: -moz-linear-gradient(top, #4387fd 40%, #2a7cdf 80%) no-repeat;\n  background: -o-linear-gradient(top, #4387fd 40%, #2a7cdf 80%) no-repeat;\n  background: -ms-linear-gradient(top, #4387fd 40%, #2a7cdf 80%) no-repeat;\n  background: linear-gradient(top, #4387fd 40%, #2a7cdf 80%) no-repeat;\n}\n/* line 530, ../scss/default.scss */\ntable td, table th {\n  font-size: 18px;\n  padding: 1em 0.5em;\n}\n/* line 535, ../scss/default.scss */\ntable td.highlight {\n  color: #515151;\n  background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(40%, #ffd14d), color-stop(80%, #f6c000)) no-repeat;\n  background: -webkit-linear-gradient(top, #ffd14d 40%, #f6c000 80%) no-repeat;\n  background: -moz-linear-gradient(top, #ffd14d 40%, #f6c000 80%) no-repeat;\n  background: -o-linear-gradient(top, #ffd14d 40%, #f6c000 80%) no-repeat;\n  background: -ms-linear-gradient(top, #ffd14d 40%, #f6c000 80%) no-repeat;\n  background: linear-gradient(top, #ffd14d 40%, #f6c000 80%) no-repeat;\n}\n/* line 540, ../scss/default.scss */\ntable.rows {\n  border-bottom: none;\n  border-right: 1px solid #797979;\n}\n\n/* line 546, ../scss/default.scss */\nq {\n  font-size: 45px;\n  line-height: 72px;\n}\n/* line 550, ../scss/default.scss */\nq:before {\n  content: '“';\n  position: absolute;\n  margin-left: -0.5em;\n}\n/* line 555, ../scss/default.scss */\nq:after {\n  content: '”';\n  position: absolute;\n  margin-left: 0.1em;\n}\n\n/* line 562, ../scss/default.scss */\nslide.fill {\n  background-repeat: no-repeat;\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  -ms-border-radius: 5px;\n  -o-border-radius: 5px;\n  border-radius: 5px;\n  -webkit-background-size: cover;\n  -moz-background-size: cover;\n  -o-background-size: cover;\n  background-size: cover;\n}\n\n/* Size variants */\n/* line 571, ../scss/default.scss */\narticle.smaller p, article.smaller ul {\n  font-size: 20px;\n  line-height: 24px;\n  letter-spacing: 0;\n}\n/* line 577, ../scss/default.scss */\narticle.smaller table td, article.smaller table th {\n  font-size: 14px;\n}\n/* line 581, ../scss/default.scss */\narticle.smaller pre {\n  font-size: 15px;\n  line-height: 20px;\n  letter-spacing: 0;\n}\n/* line 586, ../scss/default.scss */\narticle.smaller q {\n  font-size: 40px;\n  line-height: 48px;\n}\n/* line 590, ../scss/default.scss */\narticle.smaller q:before, article.smaller q:after {\n  font-size: 60px;\n}\n\n/* Builds */\n/* line 599, ../scss/default.scss */\n.build > * {\n  -webkit-transition: opacity 0.5s ease-in-out 0.2s;\n  -moz-transition: opacity 0.5s ease-in-out 0.2s;\n  -ms-transition: opacity 0.5s ease-in-out 0.2s;\n  -o-transition: opacity 0.5s ease-in-out 0.2s;\n  transition: opacity 0.5s ease-in-out 0.2s;\n}\n/* line 603, ../scss/default.scss */\n.build .to-build {\n  opacity: 0;\n}\n/* line 607, ../scss/default.scss */\n.build .build-fade {\n  opacity: 0.3;\n}\n/* line 610, ../scss/default.scss */\n.build .build-fade:hover {\n  opacity: 1.0;\n}\n\n/* Pretty print */\n/* line 629, ../scss/default.scss */\n.prettyprint .str,\n.prettyprint .atv {\n  /* a markup attribute value */\n  color: #009f5d;\n}\n\n/* line 633, ../scss/default.scss */\n.prettyprint .kwd,\n.prettyprint .tag {\n  /* a markup tag name */\n  color: #0066cc;\n}\n\n/* line 636, ../scss/default.scss */\n.prettyprint .com {\n  /* a comment */\n  color: #797979;\n  font-style: italic;\n}\n\n/* line 640, ../scss/default.scss */\n.prettyprint .lit {\n  /* a literal value */\n  color: #7f0000;\n}\n\n/* line 645, ../scss/default.scss */\n.prettyprint .pun,\n.prettyprint .opn,\n.prettyprint .clo {\n  color: #515151;\n}\n\n/* line 651, ../scss/default.scss */\n.prettyprint .typ,\n.prettyprint .atn,\n.prettyprint .dec,\n.prettyprint .var {\n  /* a declaration; a variable name */\n  color: #d94d3a;\n}\n\n/* line 654, ../scss/default.scss */\n.prettyprint .pln {\n  color: #515151;\n}\n\n/* line 658, ../scss/default.scss */\n.note {\n  position: absolute;\n  z-index: 100;\n  width: 100%;\n  height: 100%;\n  top: 0;\n  left: 0;\n  padding: 1em;\n  background: rgba(0, 0, 0, 0.3);\n  opacity: 0;\n  pointer-events: none;\n  display: -webkit-box !important;\n  display: -moz-box !important;\n  display: -ms-box !important;\n  display: -o-box !important;\n  display: box !important;\n  -webkit-box-orient: vertical;\n  -moz-box-orient: vertical;\n  -ms-box-orient: vertical;\n  box-orient: vertical;\n  -webkit-box-align: center;\n  -moz-box-align: center;\n  -ms-box-align: center;\n  box-align: center;\n  -webkit-box-pack: center;\n  -moz-box-pack: center;\n  -ms-box-pack: center;\n  box-pack: center;\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  -ms-border-radius: 5px;\n  -o-border-radius: 5px;\n  border-radius: 5px;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  -webkit-transform: translateY(350px);\n  -moz-transform: translateY(350px);\n  -ms-transform: translateY(350px);\n  -o-transform: translateY(350px);\n  transform: translateY(350px);\n  -webkit-transition: all 0.4s ease-in-out;\n  -moz-transition: all 0.4s ease-in-out;\n  -ms-transition: all 0.4s ease-in-out;\n  -o-transition: all 0.4s ease-in-out;\n  transition: all 0.4s ease-in-out;\n}\n/* line 676, ../scss/default.scss */\n.note > section {\n  background: #fff;\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  -ms-border-radius: 5px;\n  -o-border-radius: 5px;\n  border-radius: 5px;\n  -webkit-box-shadow: 0 0 10px #797979;\n  -moz-box-shadow: 0 0 10px #797979;\n  box-shadow: 0 0 10px #797979;\n  width: 60%;\n  padding: 2em;\n}\n\n/* line 693, ../scss/default.scss */\n.with-notes.popup slides.layout-widescreen slide.next,\n.with-notes.popup slides.layout-faux-widescreen slide.next {\n  -webkit-transform: translate3d(690px, 80px, 0) scale(0.35);\n  -moz-transform: translate3d(690px, 80px, 0) scale(0.35);\n  -ms-transform: translate3d(690px, 80px, 0) scale(0.35);\n  -o-transform: translate3d(690px, 80px, 0) scale(0.35);\n  transform: translate3d(690px, 80px, 0) scale(0.35);\n}\n/* line 696, ../scss/default.scss */\n.with-notes.popup slides.layout-widescreen slide .note,\n.with-notes.popup slides.layout-faux-widescreen slide .note {\n  -webkit-transform: translate3d(300px, 800px, 0) scale(1.5);\n  -moz-transform: translate3d(300px, 800px, 0) scale(1.5);\n  -ms-transform: translate3d(300px, 800px, 0) scale(1.5);\n  -o-transform: translate3d(300px, 800px, 0) scale(1.5);\n  transform: translate3d(300px, 800px, 0) scale(1.5);\n}\n/* line 702, ../scss/default.scss */\n.with-notes.popup slide {\n  overflow: visible;\n  background: white;\n  -webkit-transition: none;\n  -moz-transition: none;\n  -ms-transition: none;\n  -o-transition: none;\n  transition: none;\n  pointer-events: none;\n  -webkit-transform-origin: 0 0;\n  -moz-transform-origin: 0 0;\n  -ms-transform-origin: 0 0;\n  -o-transform-origin: 0 0;\n  transform-origin: 0 0;\n}\n/* line 709, ../scss/default.scss */\n.with-notes.popup slide:not(.backdrop) {\n  -webkit-transform: scale(0.6) translate3d(0.5em, 0.5em, 0);\n  -moz-transform: scale(0.6) translate3d(0.5em, 0.5em, 0);\n  -ms-transform: scale(0.6) translate3d(0.5em, 0.5em, 0);\n  -o-transform: scale(0.6) translate3d(0.5em, 0.5em, 0);\n  transform: scale(0.6) translate3d(0.5em, 0.5em, 0);\n  -webkit-box-shadow: 0 0 10px #797979;\n  -moz-box-shadow: 0 0 10px #797979;\n  box-shadow: 0 0 10px #797979;\n}\n/* line 714, ../scss/default.scss */\n.with-notes.popup slide.backdrop {\n  background-image: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 600, color-stop(0%, #b1dfff), color-stop(100%, #4387fd));\n  background-image: -webkit-radial-gradient(50% 50%, #b1dfff 0%, #4387fd 600px);\n  background-image: -moz-radial-gradient(50% 50%, #b1dfff 0%, #4387fd 600px);\n  background-image: -o-radial-gradient(50% 50%, #b1dfff 0%, #4387fd 600px);\n  background-image: -ms-radial-gradient(50% 50%, #b1dfff 0%, #4387fd 600px);\n  background-image: radial-gradient(50% 50%, #b1dfff 0%, #4387fd 600px);\n}\n/* line 720, ../scss/default.scss */\n.with-notes.popup slide.next {\n  -webkit-transform: translate3d(570px, 80px, 0) scale(0.35);\n  -moz-transform: translate3d(570px, 80px, 0) scale(0.35);\n  -ms-transform: translate3d(570px, 80px, 0) scale(0.35);\n  -o-transform: translate3d(570px, 80px, 0) scale(0.35);\n  transform: translate3d(570px, 80px, 0) scale(0.35);\n  opacity: 1 !important;\n}\n/* line 724, ../scss/default.scss */\n.with-notes.popup slide.next .note {\n  display: none !important;\n}\n/* line 730, ../scss/default.scss */\n.with-notes.popup .note {\n  width: 109%;\n  height: 260px;\n  background: #e6e6e6;\n  padding: 0;\n  -webkit-box-shadow: 0 0 10px #797979;\n  -moz-box-shadow: 0 0 10px #797979;\n  box-shadow: 0 0 10px #797979;\n  -webkit-transform: translate3d(250px, 800px, 0) scale(1.5);\n  -moz-transform: translate3d(250px, 800px, 0) scale(1.5);\n  -ms-transform: translate3d(250px, 800px, 0) scale(1.5);\n  -o-transform: translate3d(250px, 800px, 0) scale(1.5);\n  transform: translate3d(250px, 800px, 0) scale(1.5);\n  -webkit-transition: opacity 400ms ease-in-out;\n  -moz-transition: opacity 400ms ease-in-out;\n  -ms-transition: opacity 400ms ease-in-out;\n  -o-transition: opacity 400ms ease-in-out;\n  transition: opacity 400ms ease-in-out;\n}\n/* line 741, ../scss/default.scss */\n.with-notes.popup .note > section {\n  background: #fff;\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  -ms-border-radius: 5px;\n  -o-border-radius: 5px;\n  border-radius: 5px;\n  height: 100%;\n  width: 100%;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  -webkit-box-shadow: none;\n  -moz-box-shadow: none;\n  box-shadow: none;\n  overflow: auto;\n  padding: 1em;\n}\n/* line 754, ../scss/default.scss */\n.with-notes .note {\n  opacity: 1;\n  -webkit-transform: translateY(0);\n  -moz-transform: translateY(0);\n  -ms-transform: translateY(0);\n  -o-transform: translateY(0);\n  transform: translateY(0);\n  pointer-events: auto;\n}\n\n/* line 761, ../scss/default.scss */\n.source {\n  font-size: 14px;\n  color: #a9a9a9;\n  position: absolute;\n  bottom: 70px;\n  left: 60px;\n}\n\n/* line 769, ../scss/default.scss */\n.centered {\n  text-align: center;\n}\n\n/* line 773, ../scss/default.scss */\n.reflect {\n  -webkit-box-reflect: below 3px -webkit-linear-gradient(rgba(255, 255, 255, 0) 85%, white 150%);\n  -moz-box-reflect: below 3px -moz-linear-gradient(rgba(255, 255, 255, 0) 85%, white 150%);\n  -o-box-reflect: below 3px -o-linear-gradient(rgba(255, 255, 255, 0) 85%, white 150%);\n  -ms-box-reflect: below 3px -ms-linear-gradient(rgba(255, 255, 255, 0) 85%, white 150%);\n  box-reflect: below 3px linear-gradient(rgba(255, 255, 255, 0) 85%, #ffffff 150%);\n}\n\n/* line 781, ../scss/default.scss */\n.flexbox {\n  display: -webkit-box !important;\n  display: -moz-box !important;\n  display: -ms-box !important;\n  display: -o-box !important;\n  display: box !important;\n}\n\n/* line 785, ../scss/default.scss */\n.flexbox.vcenter {\n  -webkit-box-orient: vertical;\n  -moz-box-orient: vertical;\n  -ms-box-orient: vertical;\n  box-orient: vertical;\n  -webkit-box-align: center;\n  -moz-box-align: center;\n  -ms-box-align: center;\n  box-align: center;\n  -webkit-box-pack: center;\n  -moz-box-pack: center;\n  -ms-box-pack: center;\n  box-pack: center;\n  height: 100%;\n  width: 100%;\n}\n\n/* line 791, ../scss/default.scss */\n.flexbox.vleft {\n  -webkit-box-orient: vertical;\n  -moz-box-orient: vertical;\n  -ms-box-orient: vertical;\n  box-orient: vertical;\n  -webkit-box-align: left;\n  -moz-box-align: left;\n  -ms-box-align: left;\n  box-align: left;\n  -webkit-box-pack: center;\n  -moz-box-pack: center;\n  -ms-box-pack: center;\n  box-pack: center;\n  height: 100%;\n  width: 100%;\n}\n\n/* line 797, ../scss/default.scss */\n.flexbox.vright {\n  -webkit-box-orient: vertical;\n  -moz-box-orient: vertical;\n  -ms-box-orient: vertical;\n  box-orient: vertical;\n  -webkit-box-align: end;\n  -moz-box-align: end;\n  -ms-box-align: end;\n  box-align: end;\n  -webkit-box-pack: center;\n  -moz-box-pack: center;\n  -ms-box-pack: center;\n  box-pack: center;\n  height: 100%;\n  width: 100%;\n}\n\n/* line 803, ../scss/default.scss */\n.auto-fadein {\n  -webkit-transition: opacity 0.6s ease-in 1s;\n  -moz-transition: opacity 0.6s ease-in 1s;\n  -ms-transition: opacity 0.6s ease-in 1s;\n  -o-transition: opacity 0.6s ease-in 1s;\n  transition: opacity 0.6s ease-in 1s;\n  opacity: 0;\n}\n\n/* Clickable/tappable areas */\n/* line 809, ../scss/default.scss */\n.slide-area {\n  z-index: 1000;\n  position: absolute;\n  left: 0;\n  top: 0;\n  width: 100px;\n  height: 700px;\n  left: 50%;\n  top: 50%;\n  cursor: pointer;\n  margin-top: -350px;\n}\n\n/* line 826, ../scss/default.scss */\n#prev-slide-area {\n  margin-left: -550px;\n}\n\n/* line 831, ../scss/default.scss */\n#next-slide-area {\n  margin-left: 450px;\n}\n\n/* ===== SLIDE CONTENT ===== */\n/* line 839, ../scss/default.scss */\n.logoslide img {\n  width: 383px;\n  height: 92px;\n}\n\n/* line 845, ../scss/default.scss */\n.segue {\n  padding: 60px 120px;\n}\n/* line 848, ../scss/default.scss */\n.segue h2 {\n  color: #e6e6e6;\n  font-size: 60px;\n}\n/* line 852, ../scss/default.scss */\n.segue h3 {\n  color: #e6e6e6;\n  line-height: 2.8;\n}\n/* line 856, ../scss/default.scss */\n.segue hgroup {\n  position: absolute;\n  bottom: 225px;\n}\n\n/* line 862, ../scss/default.scss */\n.thank-you-slide {\n  background: #4387fd !important;\n  color: white;\n}\n/* line 866, ../scss/default.scss */\n.thank-you-slide h2 {\n  font-size: 60px;\n  color: inherit;\n}\n/* line 871, ../scss/default.scss */\n.thank-you-slide article > p {\n  margin-top: 2em;\n  margin-right: 200px;\n  font-size: 20pt;\n}\n/* line 876, ../scss/default.scss */\n.thank-you-slide > p {\n  position: absolute;\n  bottom: 80px;\n  font-size: 24pt;\n  line-height: 1.3;\n}\n\n/* line 884, ../scss/default.scss */\naside.gdbar {\n  height: 97px;\n  width: 215px;\n  position: absolute;\n  left: -1px;\n  top: 125px;\n  -webkit-border-radius: 0 10px 10px 0;\n  -moz-border-radius: 0 10px 10px 0;\n  -ms-border-radius: 0 10px 10px 0;\n  -o-border-radius: 0 10px 10px 0;\n  border-radius: 0 10px 10px 0;\n  background: -webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(0%, #e6e6e6), color-stop(100%, #e6e6e6)) no-repeat;\n  background: -webkit-linear-gradient(left, #e6e6e6, #e6e6e6) no-repeat;\n  background: -moz-linear-gradient(left, #e6e6e6, #e6e6e6) no-repeat;\n  background: -o-linear-gradient(left, #e6e6e6, #e6e6e6) no-repeat;\n  background: -ms-linear-gradient(left, #e6e6e6, #e6e6e6) no-repeat;\n  background: linear-gradient(left, #e6e6e6, #e6e6e6) no-repeat;\n  -webkit-background-size: 0% 100%;\n  -moz-background-size: 0% 100%;\n  -o-background-size: 0% 100%;\n  background-size: 0% 100%;\n  -webkit-transition: all 0.5s ease-out 0.5s;\n  -moz-transition: all 0.5s ease-out 0.5s;\n  -ms-transition: all 0.5s ease-out 0.5s;\n  -o-transition: all 0.5s ease-out 0.5s;\n  transition: all 0.5s ease-out 0.5s;\n  /* Better to transition only on background-size, but not sure how to do that with the mixin. */\n}\n/* line 895, ../scss/default.scss */\naside.gdbar.right {\n  right: 0;\n  left: -moz-initial;\n  left: initial;\n  top: 254px;\n  /* 96 is height of gray icon bar */\n  -webkit-transform: rotateZ(180deg);\n  -moz-transform: rotateZ(180deg);\n  -ms-transform: rotateZ(180deg);\n  -o-transform: rotateZ(180deg);\n  transform: rotateZ(180deg);\n}\n/* line 902, ../scss/default.scss */\naside.gdbar.right img {\n  -webkit-transform: rotateZ(180deg);\n  -moz-transform: rotateZ(180deg);\n  -ms-transform: rotateZ(180deg);\n  -o-transform: rotateZ(180deg);\n  transform: rotateZ(180deg);\n}\n/* line 907, ../scss/default.scss */\naside.gdbar.bottom {\n  top: -moz-initial;\n  top: initial;\n  bottom: 60px;\n}\n/* line 913, ../scss/default.scss */\naside.gdbar img {\n  width: 85px;\n  height: 85px;\n  position: absolute;\n  right: 0;\n  margin: 8px 15px;\n}\n\n/* line 924, ../scss/default.scss */\n.title-slide hgroup {\n  bottom: 100px;\n}\n/* line 927, ../scss/default.scss */\n.title-slide hgroup h1 {\n  font-size: 65px;\n  line-height: 1.4;\n  letter-spacing: -3px;\n  color: #515151;\n}\n/* line 934, ../scss/default.scss */\n.title-slide hgroup h2 {\n  font-size: 34px;\n  color: #a9a9a9;\n  font-weight: inherit;\n}\n/* line 940, ../scss/default.scss */\n.title-slide hgroup p {\n  font-size: 20px;\n  color: #797979;\n  line-height: 1.3;\n  margin-top: 2em;\n}\n\n/* line 949, ../scss/default.scss */\n.quote {\n  color: #e6e6e6;\n}\n/* line 952, ../scss/default.scss */\n.quote .author {\n  font-size: 24px;\n  position: absolute;\n  bottom: 80px;\n  line-height: 1.4;\n}\n\n/* line 961, ../scss/default.scss */\n[data-config-contact] a {\n  color: white;\n  border-bottom: none;\n}\n/* line 965, ../scss/default.scss */\n[data-config-contact] span {\n  width: 115px;\n  display: inline-block;\n}\n\n/* line 974, ../scss/default.scss */\n.overview.popup .note {\n  display: none !important;\n}\n/* line 980, ../scss/default.scss */\n.overview slides slide {\n  display: block;\n  cursor: pointer;\n  opacity: 0.5;\n  pointer-events: auto !important;\n  background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(85%, #ffffff), color-stop(100%, #e6e6e6));\n  background: -webkit-linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n  background: -moz-linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n  background: -o-linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n  background: -ms-linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n  background: linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n  background-color: white;\n}\n/* line 981, ../scss/default.scss */\n.overview slides slide.backdrop {\n  display: none !important;\n}\n/* line 996, ../scss/default.scss */\n.overview slides slide.far-past, .overview slides slide.past, .overview slides slide.next, .overview slides slide.far-next, .overview slides slide.far-past {\n  opacity: 0.5;\n  display: block;\n}\n/* line 1001, ../scss/default.scss */\n.overview slides slide.current {\n  opacity: 1;\n}\n/* line 1007, ../scss/default.scss */\n.overview .slide-area {\n  display: none;\n}\n\n@media print {\n  /* line 1014, ../scss/default.scss */\n  slides slide {\n    display: block !important;\n    position: relative;\n    background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(85%, #ffffff), color-stop(100%, #e6e6e6));\n    background: -webkit-linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n    background: -moz-linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n    background: -o-linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n    background: -ms-linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n    background: linear-gradient(#ffffff, #ffffff 85%, #e6e6e6);\n    background-color: white;\n    -webkit-transform: none !important;\n    -moz-transform: none !important;\n    -ms-transform: none !important;\n    -o-transform: none !important;\n    transform: none !important;\n    width: 100%;\n    height: 100%;\n    page-break-after: always;\n    top: auto !important;\n    left: auto !important;\n    margin-top: 0 !important;\n    margin-left: 0 !important;\n    opacity: 1 !important;\n    color: #555;\n  }\n  /* line 1034, ../scss/default.scss */\n  slides slide.far-past, slides slide.past, slides slide.next, slides slide.far-next, slides slide.far-past, slides slide.current {\n    opacity: 1 !important;\n    display: block !important;\n  }\n  /* line 1040, ../scss/default.scss */\n  slides slide .build > * {\n    -webkit-transition: none;\n    -moz-transition: none;\n    -ms-transition: none;\n    -o-transition: none;\n    transition: none;\n  }\n  /* line 1045, ../scss/default.scss */\n  slides slide .build .to-build,\n  slides slide .build .build-fade {\n    opacity: 1;\n  }\n  /* line 1050, ../scss/default.scss */\n  slides slide .auto-fadein {\n    opacity: 1 !important;\n  }\n  /* line 1054, ../scss/default.scss */\n  slides slide.backdrop {\n    display: none !important;\n  }\n  /* line 1058, ../scss/default.scss */\n  slides slide table.rows {\n    border-right: 0;\n  }\n  /* line 1063, ../scss/default.scss */\n  slides slide[hidden] {\n    display: none !important;\n  }\n\n  /* line 1068, ../scss/default.scss */\n  .slide-area {\n    display: none;\n  }\n\n  /* line 1072, ../scss/default.scss */\n  .reflect {\n    -webkit-box-reflect: none;\n    -moz-box-reflect: none;\n    -o-box-reflect: none;\n    -ms-box-reflect: none;\n    box-reflect: none;\n  }\n\n  /* line 1080, ../scss/default.scss */\n  pre, code {\n    font-family: monospace !important;\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/diff-sample-files/new-manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Hello world\",\n  \"version\": \"0.0.1\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"experimental\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/diff-sample-files/old-manifest.json",
    "content": "{\n  \"name\": \"Hello world\",\n  \"version\": \"0.0.1\",\n  \"app\": {\n    \"launch\": {\n      \"local_path\": \"main.html\"\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/helloworld/main.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('window.html', {\n    width: 400,\n    height: 400\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/helloworld/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Hello world\",\n  \"version\": \"0.0.2\",\n  \"minimum_chrome_version\": \"23\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/helloworld/snippets",
    "content": "manifest:\n{\n  \"name\": \"Hello world\",\n  \"version\": \"0.0.1\",\n  \"manifest_version\": 2,\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  }\n}\n\nmain.js:\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('window.html', {\n    width: 400,\n    height: 400\n  });\n});\n\nwindow.html:\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\" />\n\t<title>Hello World</title>\n\t<script src=\"window.js\"></script>\n</head>\n<body>\n\n<form id=\"main-form\">\n  <input id=\"your-name\" size=\"30\">\n  <input type=\"submit\">\n</form>\n\nYour name is: <div id=\"output\"></div>\n\n</body>\n</html>\n\nwindow.js:\nonload = function() {\n  document.getElementById('main-form').onsubmit = function(e) {\n    e.preventDefault();\n\n    document.getElementById('output').innerHTML =\n        document.getElementById('your-name').value;\n  };\n};\n\nXSS input\n<h1 onclick=\"document.body.style.background='red'\">hello</1>\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/helloworld/window.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\" />\n\t<title>Hello World</title>\n\t<script src=\"window.js\"></script>\n</head>\n<body>\n\n<form id=\"main-form\">\n  <input id=\"your-name\" size=\"30\">\n  <input type=\"submit\">\n</form>\n\nYour name is: <div id=\"output\"></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/helloworld/window.js",
    "content": "onload = function() {\n  document.getElementById('main-form').onsubmit = function(e) {\n    e.preventDefault();\n\n    document.getElementById('output').innerHTML =\n        document.getElementById('your-name').value;\n  };\n};\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/js/main.js",
    "content": "var PRESENTATION_WIDTH = 900;\nvar PRESENTATION_HEIGHT = 700;\n\nvar presentationWindow;\n\nchrome.app.runtime.onLaunched.addListener(function() {\n  if (presentationWindow && !presentationWindow.contentWindow.closed) {\n    presentationWindow.focus();\n    return;\n  }\n\n  var left = Math.max((screen.width - PRESENTATION_WIDTH)/2, 0);\n  var top = Math.max((screen.height - PRESENTATION_HEIGHT)/2, 0);\n\n  chrome.app.window.create('presentation.html?presentme=true', {\n      frame: 'chrome',\n      innerBounds: {\n        left: left, top: top,\n        width: PRESENTATION_WIDTH, height: PRESENTATION_HEIGHT,\n        minWidth: PRESENTATION_WIDTH, minHeight: PRESENTATION_HEIGHT,\n        maxWidth: PRESENTATION_WIDTH, maxHeight: PRESENTATION_HEIGHT\n      }\n  }, function(w) {\n    presentationWindow = w;\n  });\n});\n\n\nvar windowingApiDemo = {\n  windows: [],\n\n  clear: function() {\n    if (windowingApiDemo.updateInterval) {\n      clearInterval(windowingApiDemo.updateInterval);\n    }\n\n    windowingApiDemo.windows.forEach(function(w) {w.contentWindow.close()});\n    windowingApiDemo.windows = [];\n  },\n\n  launch: function() {\n    windowingApiDemo.clear();\n    chrome.app.window.create('windowing_api/original.html', {\n      outerBounds: {\n        top: 128,\n        left: 128,\n        width: 256,\n        height: 256\n      }\n    }, function(originalWindow) {\n\n      windowingApiDemo.windows.push(originalWindow);\n      chrome.app.window.create('windowing_api/copycat.html', {\n        outerBounds: {\n          top: 128,\n          left: 384 + 5,\n          width: 256,\n          height: 256,\n        },\n        frame: 'none'\n      }, function(copycatWindow) {\n        windowingApiDemo.windows.push(copycatWindow);\n\n        windowingApiDemo.updateInterval = setInterval(function() {\n          if (originalWindow.contentWindow.closed || copycatWindow.contentWindow.closed) {\n            windowingApiDemo.clear();\n            return;\n          }\n\n          copycatWindow.outerBounds.left = originalWindow.contentWindow.screenX + originalWindow.contentWindow.outerWidth + 5;\n          copycatWindow.outerBounds.top = originalWindow.contentWindow.screenY;\n          copycatWindow.outerBounds.width = originalWindow.contentWindow.outerWidth;\n          copycatWindow.outerBounds.height = originalWindow.contentWindow.outerHeight;\n\n        }, 10);\n\n        originalWindow.focus();\n      });\n    });\n  },\n\n  minimizeAll: function() {\n    windowingApiDemo.windows.forEach(function(w) { w.minimize() });\n    setTimeout(windowingApiDemo.clear, 2000);\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/js/servo.js",
    "content": "var servo = {\n\n  connectionId: -1,\n\n  onSend: function(sendInfo) {\n    if (sendInfo.bytesSent == -1) {\n      servo.fail('Could not write to serial device.');\n    }\n  },\n\n  setPosition: function(position) {\n    var buffer = new ArrayBuffer(1);\n    var uint8View = new Uint8Array(buffer);\n    uint8View[0] = 48 + position;\n    chrome.serial.send(servo.connectionId, buffer, servo.onSend);\n  },\n\n  onOpen: function(connectionInfo) {\n    if (!connectionInfo) {\n      servo.fail('Could not open device');\n      return;\n    }\n    servo.connectionId = connectionInfo.connectionId;\n\n    console.log('opened, got connection id: ' + servo.connectionId);\n    servo.setPosition(0);\n  },\n\n  onGetDevices: function(ports) {\n    var eligiblePorts = ports.filter(function(port) {\n      if (servo.shouldSkipPort(port.path)) {\n        console.log('Skipping port ' + port.path);\n        return false;\n      }\n\n      console.log('Maybe using port ' + port.path);\n      return true;\n    });\n\n    if (eligiblePorts.length == 0) {\n      servo.fail('Serial port not found.');\n      return;\n    }\n\n    var port = eligiblePorts[eligiblePorts.length - 1];\n    if (eligiblePorts.length > 1) {\n      servo.fail(eligiblePorts.length + ' eligible ports found, trying ' + port.path);\n    }\n\n    chrome.serial.connect(port.path, servo.onOpen);\n  },\n\n  onSliderChange: function() {\n    var value = parseInt(this.value);\n    servo.setPosition(value);\n  },\n\n  shouldSkipPort: function(portName) {\n    if (navigator.platform.indexOf('Linux') == 0) {\n      return !portName.match(/ACM/);\n    }\n    return portName.match(/[Bb]luetooth/);\n  },\n\n  init: function() {\n    if (servo.connectionId != -1) {\n      chrome.serial.disconnect(servo.connectionId, function() {\n        servo.connectionId = -1;\n        servo.init();\n      });\n      return;\n    }\n    document.getElementById('spinner-error').classList.remove('visible');\n    document.getElementById('spinner-input').onchange = servo.onSliderChange;\n\n    chrome.serial.getDevices(servo.onGetDevices);\n  },\n\n  shutDown: function() {\n    if (servo.connectionId == -1) {\n      return;\n    }\n\n    chrome.serial.disconnect(servo.connectionId, function() {\n      servo.connectionId = -1;\n    });\n  },\n\n  fail: function(message) {\n    document.getElementById('spinner-error').classList.add('visible');\n    document.getElementById('spinner-error').textContent = message;\n  }\n};\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/js/slide-config.js",
    "content": "var SLIDE_CONFIG = {\n  // Slide settings\n  settings: {\n    title: 'The Next Evolution of Chrome Apps',\n    //subtitle: '',\n    useBuilds: true, // Default: true. False will turn off slide animation builds.\n    enableSlideAreas: false, // Default: true. False turns off the click areas on either slide of the slides.\n    favIcon: 'images/chrome-logo-tiny.png',\n    fonts: [\n      'Open Sans:regular,semibold,italic,italicsemibold',\n      'Inconsolata'\n    ],\n    //theme: ['mytheme'], // Add your own custom themes or styles in /theme/css. Leave off the .css extension.\n  },\n\n  // Author information\n  presenters: [{\n    name: 'Erik Kay',\n    company: 'Engineering Manager',\n    gplus: 'https://plus.google.com/106818816637347055983',\n    github: 'http://github.com/erikkay'\n  }, {\n    name: 'Mihai Parparita',\n    gplus: 'https://plus.google.com/111567061469336027617',\n    company: 'Software Engineer',\n    twitter: '@mihai',\n    www: 'http://persistent.info',\n    github: 'http://github.com/mihaip'\n  }]\n};\n\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/js/slide-controller.js",
    "content": "(function(window) {\n\nvar ORIGIN_ = location.protocol + '//' + location.host;\n\nfunction SlideController() {\n  this.popup = null;\n  this.isPopup = window.opener;\n\n  if (this.setupDone()) {\n    window.addEventListener('message', this.onMessage_.bind(this), false);\n  }\n}\n\nSlideController.prototype.setupDone = function() {\n  return true;\n}\n\nSlideController.prototype.onMessage_ = function(e) {\n  var data = e.data;\n\n  // Restrict messages to being from this origin. Allow local developmet\n  // from file:// though.\n  // TODO: It would be dope if FF implemented location.origin!\n  if (e.origin != ORIGIN_ && ORIGIN_.indexOf('file://') != 0) {\n    alert('Someone tried to postMessage from an unknown origin');\n    return;\n  }\n\n  // if (e.source.location.hostname != 'localhost') {\n  //   alert('Someone tried to postMessage from an unknown origin');\n  //   return;\n  // }\n\n  if ('keyCode' in data) {\n    var evt = document.createEvent('Event');\n    evt.initEvent('keydown', true, true);\n    evt.keyCode = data.keyCode;\n    document.dispatchEvent(evt);\n  }\n};\n\nSlideController.prototype.sendMsg = function(msg) {\n  // // Send message to popup window.\n  // if (this.popup) {\n  //   this.popup.postMessage(msg, ORIGIN_);\n  // }\n\n  // Send message to main window.\n  if (this.isPopup) {\n    // TODO: It would be dope if FF implemented location.origin.\n    window.opener.postMessage(msg, '*');\n  }\n};\n\nwindow.SlideController = SlideController;\n\n})(window);\n\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/js/slide-deck.js",
    "content": "/**\n * @authors Luke Mahe\n * @authors Eric Bidelman\n * @fileoverview TODO\n */\ndocument.cancelFullScreen = document.webkitCancelFullScreen ||\n                            document.mozCancelFullScreen;\n\n/**\n * @constructor\n */\nfunction SlideDeck(el) {\n  this.curSlide_ = 0;\n  this.prevSlide_ = 0;\n  this.config_ = null;\n  this.container = el || document.querySelector('slides');\n  this.slides = [];\n  this.controller = null;\n\n  this.getSavedSlideNumber_((function(slideNumber) {\n    this.curSlide_ = slideNumber;\n    this.init_();\n  }).bind(this));\n}\n\n/**\n * @const\n * @private\n */\nSlideDeck.prototype.SLIDE_CLASSES_ = [\n  'far-past', 'past', 'current', 'next', 'far-next'];\n\n/**\n * @const\n * @private\n */\nSlideDeck.prototype.CSS_DIR_ = 'theme/css/';\n\n/**\n * @param {number} slideNo\n */\nSlideDeck.prototype.loadSlide = function(slideNo) {\n  if (slideNo) {\n    this.curSlide_ = slideNo - 1;\n    this.updateSlides_();\n  }\n};\n\n/**\n * @private\n */\nSlideDeck.prototype.init_ = function(e) {\n  document.body.classList.add('loaded'); // Add loaded class for templates to use.\n\n  this.slides = this.container.querySelectorAll('slide:not([hidden]):not(.backdrop)');\n\n  this.loadConfig_(SLIDE_CONFIG);\n  this.addEventListeners_();\n  this.updateSlides_();\n\n  // Add slide numbers and total slide count metadata to each slide.\n  var that = this;\n  for (var i = 0, slide; slide = this.slides[i]; ++i) {\n    slide.dataset.slideNum = i + 1;\n    slide.dataset.totalSlides = this.slides.length;\n\n    slide.addEventListener('click', function(e) {\n      if (document.body.classList.contains('overview')) {\n        that.loadSlide(this.dataset.slideNum);\n        e.preventDefault();\n        window.setTimeout(function() {\n          that.toggleOverview();\n        }, 500);\n      }\n    }, false);\n  }\n\n  // Note: this needs to come after addEventListeners_(), which adds a\n  // 'keydown' listener that this controller relies on.\n  this.controller = new SlideController(this);\n  if (this.controller.isPopup) {\n    document.body.classList.add('popup');\n  }\n};\n\n/**\n * @private\n */\nSlideDeck.prototype.addEventListeners_ = function() {\n  document.addEventListener('keydown', this.onBodyKeyDown_.bind(this), false);\n};\n\n/**\n * @param {Event} e\n */\nSlideDeck.prototype.onBodyKeyDown_ = function(e) {\n  if (/^(input|textarea)$/i.test(e.target.nodeName) ||\n      e.target.isContentEditable) {\n    return;\n  }\n\n  // Forward keydowns to the main slides if we're the popup.\n  if (this.controller && this.controller.isPopup) {\n    this.controller.sendMsg({keyCode: e.keyCode});\n  }\n\n  switch (e.keyCode) {\n    case 13: // Enter\n      if (document.body.classList.contains('overview')) {\n        this.toggleOverview();\n      }\n      break;\n\n    case 39: // right arrow\n    case 32: // space\n    case 34: // PgDn\n      this.nextSlide();\n      e.preventDefault();\n      break;\n\n    case 37: // left arrow\n    case 8: // Backspace\n    case 33: // PgUp\n      this.prevSlide();\n      e.preventDefault();\n      break;\n\n    case 40: // down arrow\n      this.nextSlide();\n      e.preventDefault();\n      break;\n\n    case 38: // up arrow\n      this.prevSlide();\n      e.preventDefault();\n      break;\n\n    case 72: // H: Toggle code highlighting\n      document.body.classList.toggle('highlight-code');\n      break;\n\n    case 79: // O: Toggle overview\n      this.toggleOverview();\n      break;\n\n    case 80: // P\n      if (this.controller && this.controller.isPopup) {\n        document.body.classList.toggle('with-notes');\n      } else if (this.controller && !this.controller.popup) {\n        document.body.classList.toggle('with-notes');\n      }\n      break;\n\n    case 82: // R\n      // TODO: implement refresh on main slides when popup is refreshed.\n      break;\n\n    case 27: // ESC: Hide notes and highlighting\n      document.body.classList.remove('with-notes');\n      document.body.classList.remove('highlight-code');\n\n      if (document.body.classList.contains('overview')) {\n        this.toggleOverview();\n      }\n      break;\n\n    case 70: // F: Toggle fullscreen\n       // Only respect 'f' on body. Don't want to capture keys from an <input>.\n       // Also, ignore browser's fullscreen shortcut (cmd+shift+f) so we don't\n       // get trapped in fullscreen!\n      if (e.target == document.body && !(e.shiftKey && e.metaKey)) {\n        if (document.mozFullScreen !== undefined && !document.mozFullScreen) {\n          document.body.mozRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);\n        } else if (document.webkitIsFullScreen !== undefined && !document.webkitIsFullScreen) {\n          document.body.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);\n        } else {\n          document.cancelFullScreen();\n        }\n      }\n      break;\n\n    case 87: // W: Toggle widescreen\n      // Only respect 'w' on body. Don't want to capture keys from an <input>.\n      if (e.target == document.body && !(e.shiftKey && e.metaKey)) {\n        this.container.classList.toggle('layout-widescreen');\n      }\n      break;\n\n    case 77: // M: Minimize\n      chrome.app.window.minimize();\n      break;\n  }\n};\n\n/**\n *\n */\nSlideDeck.prototype.focusOverview_ = function() {\n  var overview = document.body.classList.contains('overview');\n\n  for (var i = 0, slide; slide = this.slides[i]; i++) {\n    slide.style.webkitTransform = overview ?\n        'translateZ(-2500px) translate(' + (( i - this.curSlide_ ) * 105) +\n                                       '%, 0%)' : '';\n  }\n};\n\n/**\n */\nSlideDeck.prototype.toggleOverview = function() {\n  document.body.classList.toggle('overview');\n\n  this.focusOverview_();\n};\n\n/**\n * @private\n */\nSlideDeck.prototype.loadConfig_ = function(config) {\n  if (!config) {\n    return;\n  }\n\n  this.config_ = config;\n\n  var settings = this.config_.settings;\n\n  this.loadTheme_(settings.theme || []);\n\n  if (settings.favIcon) {\n    this.addFavIcon_(settings.favIcon);\n  }\n\n  if (settings.fonts) {\n    this.addFonts_(settings.fonts);\n  }\n\n  // Builds. Default to on.\n  if (!!!('useBuilds' in settings) || settings.useBuilds) {\n    this.makeBuildLists_();\n  }\n\n  if (settings.title) {\n    document.title = settings.title.replace(/<br\\/?>/, ' ') + ' - Google IO 2012';\n    document.querySelector('[data-config-title]').innerHTML = settings.title;\n  }\n\n  if (settings.subtitle) {\n    document.querySelector('[data-config-subtitle]').innerHTML = settings.subtitle;\n  }\n\n  if (this.config_.presenters) {\n    var presenters = this.config_.presenters;\n    var dataConfigContact = document.querySelector('[data-config-contact]');\n\n    var html = [];\n    if (presenters.length == 1) {\n      var p = presenters[0];\n\n      html = [p.name, p.company].join('<br>');\n\n      var gplus = p.gplus ? '<span>g+</span><a href=\"' + p.gplus +\n          '\">' + p.gplus.replace(/https?:\\/\\//, '') + '</a>' : '';\n\n      var twitter = p.twitter ? '<span>twitter</span>' +\n          '<a href=\"http://twitter.com/' + p.twitter + '\">' +\n          p.twitter + '</a>' : '';\n\n      var www = p.www ? '<span>www</span><a href=\"' + p.www +\n                        '\">' + p.www.replace(/https?:\\/\\//, '') + '</a>' : '';\n\n      var github = p.github ? '<span>github</span><a href=\"' + p.github +\n          '\">' + p.github.replace(/https?:\\/\\//, '') + '</a>' : '';\n\n      var html2 = [gplus, twitter, www, github].join('<br>');\n\n      if (dataConfigContact) {\n        dataConfigContact.innerHTML = html2;\n      }\n    } else {\n      for (var i = 0, p; p = presenters[i]; ++i) {\n        html.push(p.name + ' - ' + p.company);\n      }\n      html = html.join('<br>');\n      if (dataConfigContact) {\n        dataConfigContact.innerHTML = html;\n      }\n    }\n\n    var dataConfigPresenter = document.querySelector('[data-config-presenter]');\n    if (dataConfigPresenter) {\n      document.querySelector('[data-config-presenter]').innerHTML = html;\n    }\n  }\n\n  /* Left/Right tap areas. Default to including. */\n  if (!!!('enableSlideAreas' in settings) || settings.enableSlideAreas) {\n    var el = document.createElement('div');\n    el.classList.add('slide-area');\n    el.id = 'prev-slide-area';\n    el.addEventListener('click', this.prevSlide.bind(this), false);\n    this.container.appendChild(el);\n\n    var el = document.createElement('div');\n    el.classList.add('slide-area');\n    el.id = 'next-slide-area';\n    el.addEventListener('click', this.nextSlide.bind(this), false);\n    this.container.appendChild(el);\n  }\n};\n\n/**\n * @private\n * @param {Array.<string>} fonts\n */\nSlideDeck.prototype.addFonts_ = function(fonts) {\n  /* You need to add local fonts manually due to CSP.\n\n  var el = document.createElement('link');\n  el.rel = 'stylesheet';\n  el.href = ('https:' == document.location.protocol ? 'https' : 'http') +\n      '://fonts.googleapis.com/css?family=' + fonts.join('|') + '&v2';\n  document.querySelector('head').appendChild(el);\n  */\n};\n\n/**\n * @private\n */\nSlideDeck.prototype.buildNextItem_ = function() {\n  var slide = this.slides[this.curSlide_];\n  var toBuild = slide.querySelector('.to-build');\n  var built = slide.querySelector('.build-current');\n\n  if (built) {\n    built.classList.remove('build-current');\n    if (built.classList.contains('fade')) {\n      built.classList.add('build-fade');\n    }\n  }\n\n  if (!toBuild) {\n    var items = slide.querySelectorAll('.build-fade');\n    for (var j = 0, item; item = items[j]; j++) {\n      item.classList.remove('build-fade');\n    }\n    return false;\n  }\n\n  toBuild.classList.remove('to-build');\n  toBuild.classList.add('build-current');\n\n  return true;\n};\n\nSlideDeck.prototype.prevSlide = function() {\n  if (this.curSlide_ > 0) {\n    var bodyClassList = document.body.classList;\n    bodyClassList.remove('highlight-code');\n\n    // Toggle off speaker notes if they're showing when we move backwards on the\n    // main slides. If we're the speaker notes popup, leave them up.\n    if (this.controller && !this.controller.isPopup) {\n      bodyClassList.remove('with-notes');\n    } else if (!this.controller) {\n      bodyClassList.remove('with-notes');\n    }\n\n    this.prevSlide_ = this.curSlide_--;\n\n    this.updateSlides_();\n  }\n};\n\nSlideDeck.prototype.nextSlide = function() {\n  if (!document.body.classList.contains('overview') && this.buildNextItem_()) {\n    return;\n  }\n\n  if (this.curSlide_ < this.slides.length - 1) {\n    var bodyClassList = document.body.classList;\n    bodyClassList.remove('highlight-code');\n\n    // Toggle off speaker notes if they're showing when we advanced on the main\n    // slides. If we're the speaker notes popup, leave them up.\n    if (this.controller && !this.controller.isPopup) {\n      bodyClassList.remove('with-notes');\n    } else if (!this.controller) {\n      bodyClassList.remove('with-notes');\n    }\n\n    this.prevSlide_ = this.curSlide_++;\n\n    this.updateSlides_();\n  }\n};\n\n/* Slide events */\n\n/**\n * Triggered when a slide enter/leave event should be dispatched.\n *\n * @param {string} type The type of event to trigger\n *     (e.g. 'slideenter', 'slideleave').\n * @param {number} slideNo The index of the slide that is being left.\n */\nSlideDeck.prototype.triggerSlideEvent = function(type, slideNo) {\n  var el = this.getSlideEl_(slideNo);\n  if (!el) {\n    return;\n  }\n\n  // Call onslideenter/onslideleave if the attribute is defined on this slide.\n  var func = el.getAttribute(type);\n  if (func) {\n    new Function(func).call(el); // TODO: Don't use new Function() :(\n  }\n\n  // Dispatch event to listeners setup using addEventListener.\n  var evt = document.createEvent('Event');\n  evt.initEvent(type, true, true);\n  evt.slideNumber = slideNo + 1; // Make it readable\n  evt.slide = el;\n\n  el.dispatchEvent(evt);\n};\n\n/**\n * @private\n */\nSlideDeck.prototype.updateSlides_ = function() {\n  var curSlide = this.curSlide_;\n  for (var i = 0; i < this.slides.length; ++i) {\n    switch (i) {\n      case curSlide - 2:\n        this.updateSlideClass_(i, 'far-past');\n        break;\n      case curSlide - 1:\n        this.updateSlideClass_(i, 'past');\n        break;\n      case curSlide:\n        this.updateSlideClass_(i, 'current');\n        break;\n      case curSlide + 1:\n        this.updateSlideClass_(i, 'next');\n        break;\n      case curSlide + 2:\n        this.updateSlideClass_(i, 'far-next');\n        break;\n      default:\n        this.updateSlideClass_(i);\n        break;\n    }\n  };\n\n  this.triggerSlideEvent('slideleave', this.prevSlide_);\n  this.triggerSlideEvent('slideenter', curSlide);\n\n// window.setTimeout(this.disableSlideFrames_.bind(this, curSlide - 2), 301);\n//\n// this.enableSlideFrames_(curSlide - 1); // Previous slide.\n// this.enableSlideFrames_(curSlide + 1); // Current slide.\n// this.enableSlideFrames_(curSlide + 2); // Next slide.\n\n   // Enable current slide's iframes (needed for page loat at current slide).\n   this.enableSlideFrames_(curSlide + 1);\n\n   // No way to tell when all slide transitions + auto builds are done.\n   // Give ourselves a good buffer to preload the next slide's iframes.\n   window.setTimeout(this.enableSlideFrames_.bind(this, curSlide + 2), 1000);\n\n  this.saveSlideNumber_();\n\n  if (document.body.classList.contains('overview')) {\n    this.focusOverview_();\n    return;\n  }\n\n};\n\n/**\n * @private\n * @param {number} slideNo\n */\nSlideDeck.prototype.enableSlideFrames_ = function(slideNo) {\n  var el = this.slides[slideNo - 1];\n  if (!el) {\n    return;\n  }\n\n  var frames = el.querySelectorAll('iframe');\n  for (var i = 0, frame; frame = frames[i]; i++) {\n    this.enableFrame_(frame);\n  }\n};\n\n/**\n * @private\n * @param {number} slideNo\n */\nSlideDeck.prototype.enableFrame_ = function(frame) {\n  var src = frame.dataset.src;\n  if (src && frame.src != src) {\n    frame.src = src;\n  }\n};\n\n/**\n * @private\n * @param {number} slideNo\n */\nSlideDeck.prototype.disableSlideFrames_ = function(slideNo) {\n  var el = this.slides[slideNo - 1];\n  if (!el) {\n    return;\n  }\n\n  var frames = el.querySelectorAll('iframe');\n  for (var i = 0, frame; frame = frames[i]; i++) {\n    this.disableFrame_(frame);\n  }\n};\n\n/**\n * @private\n * @param {Node} frame\n */\nSlideDeck.prototype.disableFrame_ = function(frame) {\n  frame.src = 'about:blank';\n};\n\n/**\n * @private\n * @param {number} slideNo\n */\nSlideDeck.prototype.getSlideEl_ = function(no) {\n  if ((no < 0) || (no >= this.slides.length)) {\n    return null;\n  } else {\n    return this.slides[no];\n  }\n};\n\n/**\n * @private\n * @param {number} slideNo\n * @param {string} className\n */\nSlideDeck.prototype.updateSlideClass_ = function(slideNo, className) {\n  var el = this.getSlideEl_(slideNo);\n\n  if (!el) {\n    return;\n  }\n\n  if (className) {\n    el.classList.add(className);\n  }\n\n  for (var i = 0, slideClass; slideClass = this.SLIDE_CLASSES_[i]; ++i) {\n    if (className != slideClass) {\n      el.classList.remove(slideClass);\n    }\n  }\n};\n\n/**\n * @private\n */\nSlideDeck.prototype.makeBuildLists_ = function () {\n  for (var i = this.curSlide_, slide; slide = this.slides[i]; ++i) {\n    var items = slide.querySelectorAll('.build > *');\n    for (var j = 0, item; item = items[j]; ++j) {\n      if (item.classList) {\n        item.classList.add('to-build');\n        if (item.parentNode.classList.contains('fade')) {\n          item.classList.add('fade');\n        }\n      }\n    }\n  }\n};\n\n/**\n * Saves the current slide into persistent storage.\n *\n * @private\n */\nSlideDeck.prototype.saveSlideNumber_ = function() {\n  this.setStoredValue_(StorageKey.SLIDE_NUMBER, this.curSlide_);\n};\n\n/**\n * Gets the current slide from persistent storage.\n *\n * @private\n */SlideDeck.prototype.getSavedSlideNumber_ = function(callback) {\n  this.getStoredValue_(StorageKey.SLIDE_NUMBER, function(slideNumber) {\n    callback(slideNumber || 0);\n  });\n};\n\n/**\n * Persistent storage keys.\n *\n * @enum{string}\n */\nvar StorageKey = {\n  SLIDE_NUMBER: 'slide-number'\n};\n\n/**\n * Saves data into persistent storage.\n *\n * @param {string} key\n * @param {*} value\n * @param {Function} opt_callback\n * @private\n */\nSlideDeck.prototype.setStoredValue_ = function(key, value, opt_callback) {\n  var data = {};\n  data[key] = value;\n  if (chrome.storage) {\n    chrome.storage.local.set(data, opt_callback);\n  } else {\n    // We're running in a web page, not an app.\n    if (opt_callback) {\n      opt_callback();\n    }\n  }\n};\n\n/**\n * Gets data from persistent storage.\n *\n * @param {string} key\n * @param {Function.<*>} opt_callback\n * @private\n */\nSlideDeck.prototype.getStoredValue_ = function(key, callback) {\n  if (chrome.storage) {\n    chrome.storage.local.get(key, function(data) {\n      callback(data[key]);\n    });\n  } else {\n    // We're running in a web page, not an app.\n    callback(\"1\");\n  }\n};\n\n/**\n * @private\n * @param {string} favIcon\n */\nSlideDeck.prototype.addFavIcon_ = function(favIcon) {\n  var el = document.createElement('link');\n  el.rel = 'icon';\n  el.type = 'image/png';\n  el.href = favIcon;\n  document.querySelector('head').appendChild(el);\n};\n\n/**\n * @private\n * @param {string} theme\n */\nSlideDeck.prototype.loadTheme_ = function(theme) {\n  var styles = [];\n  if (theme.constructor.name === 'String') {\n    styles.push(theme);\n  } else {\n    styles = theme;\n  }\n\n  for (var i = 0, style; themeUrl = styles[i]; i++) {\n    var style = document.createElement('link');\n    style.rel = 'stylesheet';\n    style.type = 'text/css';\n    if (themeUrl.indexOf('http') == -1) {\n      style.href = this.CSS_DIR_ + themeUrl + '.css';\n    } else {\n      style.href = themeUrl;\n    }\n    document.querySelector('head').appendChild(style);\n  }\n};\n\nvar slidedeck = new SlideDeck();\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/js/slides.js",
    "content": "var spinnerDemoRunning = false;\n\ndocument.getElementById('windows-demo').onclick = function() {\n  opener.windowingApiDemo.launch();\n};\n\ndocument.getElementById('exit-fullscreen').onclick = function() {\n  document.webkitCancelFullScreen();\n};\n\nvar minimizeAndHideButton = function(e) {\n  minimize()\n  e.target.classList.toggle('hidden');\n};\n\nvar minimize = function () { chrome.app.window.current().minimize(); };\n\ndocument.getElementById(\"apis-slide\").addEventListener(\"slideleave\", function() {\n  if (spinnerDemoRunning) {\n    servo.shutDown();\n    spinnerDemoRunning = false;\n    document.getElementById('spinner-demo').classList.remove('visible')\n    document.getElementById('technical-difficulties').classList.remove('visible');\n  }\n  document.getElementById('spinner-demo-button').classList.remove('hidden');\n});\n\ndocument.getElementById('offline-demo').onclick = minimize;\ndocument.getElementById('programming-demo').onclick = minimize;\ndocument.getElementById('security-demo').onclick = minimize;\ndocument.getElementById('spinner-demo-button2').onclick = minimize;\n\ndocument.getElementById('spinner-demo-button').onclick = function() {\n  document.getElementById('spinner-demo-button').classList.add('hidden');\n  if (!spinnerDemoRunning) {\n    navigator.webkitGetUserMedia({video: true}, function(stream) {\n      document.getElementById('camera-output').src =\n          webkitURL.createObjectURL(stream);\n      servo.init();\n      spinnerDemoRunning = true;\n\n      setTimeout(function() {\n        document.getElementById('spinner-demo').classList.add('visible');\n      }, 1000);\n    }, function(e) {\n      document.getElementById('technical-difficulties').classList.add('visible');\n    });\n  }\n};\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Apps I/O 2012 Presentation\",\n  \"description\": \"Chrome Apps IO 2012 presentation.\",\n  \"version\": \"1.3\",\n  \"minimum_chrome_version\": \"23\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"js/main.js\"]\n    }\n  },\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"128\": \"images/icon-128.png\"\n  },\n  \"permissions\": [\n    \"webview\",\n    \"serial\",\n    \"storage\",\n    \"videoCapture\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/presentation.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>Google IO 2012</title>\n  <meta charset=\"utf-8\">\n  <link rel=\"stylesheet\" href=\"css/theme.css\">\n  <link rel=\"stylesheet\" href=\"css/presentation.css\">\n</head>\n<body style=\"opacity: 0\">\n\n<!-- removed class=\"layout-widescreen\" since we're using a chromebook -->\n<slides>\n\n  <slide class=\"logoslide nobackground\">\n    <article class=\"chromelogo\">\n      <img src=\"images/chrome-logo.png\"><div id=\"chrometext\">chrome</div>\n    </article>\n  </slide>\n\n  <slide class=\"title-slide segue nobackground\">\n    <aside class=\"gdbar\"><img src=\"images/chrome-logo.png\"></aside>\n    <!-- The content of this hgroup is replaced programmatically through the slide_config.json. -->\n    <hgroup class=\"auto-fadein\">\n      <h1 data-config-title><!-- populated from slide_config.json --></h1>\n      <h2 data-config-subtitle><!-- populated from slide_config.json --></h2>\n      <p data-config-presenter><!-- populated from slide_config.json --></p>\n    </hgroup>\n  </slide>\n\n  <slide>\n    <hgroup>\n      <h2>Remember Google I/O 2011?</h2>\n    </hgroup>\n    <article>\n      <div id=\"remember_icons\" class=\"build\">\n        <img class=\"icon\" src=\"images/remember-chrome.png\" alt=\"Chrome reached 160 million users\">\n        <img class=\"icon\" src=\"images/remember-wallet.png\" alt=\"Launched in-app payments\">\n        <img class=\"icon\" src=\"images/remember-i18n.png\" alt=\"Launched the store in 42 languages\">\n        <img class=\"icon\" src=\"images/remember-angry-birds.png\" alt=\"Launched Angry Birds in Chrome\">\n      </div>\n    </article>\n  </slide>\n\n  <slide>\n    <hgroup>\n      <h2>Ecosystem Is Thriving</h2>\n    </hgroup>\n    <article id=\"ecosystem\">\n    <div id=\"ecosystem_blocks\" class=\"build\">\n      <div class=\"ecoblock\">\n        <div class=\"ecoblock_left\">Native Client</div>\n        <div class=\"vdivider\"></div>\n        <div class=\"ecoblock_right\">Amazing Games</div>\n      </div>\n      <div class=\"ecoblock\">\n        <div class=\"ecoblock_left\">Web Store</div>\n        <div class=\"vdivider\"></div>\n        <div class=\"ecoblock_right\">\n          <div>750</div>\n          <div>\n            <span class=\"blue\">Million</span><br/>App Installs\n          </div>\n        </div>\n      </div>\n      <div class=\"ecoblock\">\n        <div class=\"ecoblock_left\">Chrome</div>\n        <div class=\"vdivider\"></div>\n        <div class=\"ecoblock_right\">\n          <div>310</div>\n          <div>\n            <span class=\"blue\">Million</span><br/>Active Users\n          </div>\n        </div>\n      </div>\n    </div>\n    </article>\n  </slide>\n\n  <slide>\n    <hgroup>\n      <h2>Apps Evolution</h2>\n    </hgroup>\n    <article>\n      <div id=\"evolution_blocks\" class=\"build\">\n        <div class=\"evoblock bluebg\">\n        Breaking Out of the Browser\n        </div>\n        <div class=\"evoblock redbg\">\n        Enhanced User Interface\n        </div>\n        <div class=\"evoblock yellowbg\">\n        Offline by Default\n        </div>\n        <div class=\"evoblock greenbg\">\n        New APIs\n        </div>\n      </div>\n    </article>\n  </slide>\n\n  <slide class=\"topborder\">\n    <hgroup class=\"bluebg\">\n      <h2>Breaking Out Of the Browser</h2>\n    </hgroup>\n    <article>\n      <div class=\"ul build\">\n        <div class=\"li\">Launch from outside of the browser.</div>\n        <div class=\"li\">First class OS windows (alt-tab, etc.)</div>\n        <aside id=\"exit-fullscreen\" class=\"demobutton\"></aside>\n      </div>\n    </article>\n  </slide>\n\n  <slide class=\"topborder\">\n    <hgroup class=\"redbg\">\n      <h2>Enhanced User Interface</h2>\n    </hgroup>\n    <article>\n      <div class=\"ul build\">\n        <div class=\"li\">Full control over multiple windows.</div>\n        <div class=\"li\">Custom window frame without browser chrome.</div>\n        <div class=\"li\"><a href=\"http://www.google.com\" target=\"_blank\">Links</a> open in browsers, not in the app.</div>\n        <aside id=\"windows-demo\" class=\"demobutton\"></aside>\n      </div>\n    </article>\n  </slide>\n\n  <slide class=\"topborder\">\n    <hgroup class=\"yellowbg\">\n      <h2>Offline by Default</h2>\n    </hgroup>\n    <article>\n      <div class=\"ul build\">\n        <div class=\"li\">Packaged app UI and logic is loaded and run locally.</div>\n        <div class=\"li\">Enforced separation of client UI and data.</div>\n        <div class=\"li\">APIs degrade gracefully when offline.</div>\n        <div class=\"li\">Apps are launched from outside of the browser.</div>\n        <aside id=\"offline-demo\" class=\"demobutton\"></aside>\n      </div>\n    </article>\n  </slide>\n\n  <slide id=\"apis-slide\" class=\"topborder\">\n    <div id=\"spinner-demo\" class=\"spinner-demo\">\n      <video id=\"camera-output\" width=\"640\" height=\"480\" autoplay></video>\n      <input id=\"spinner-input\" type=\"range\" min=\"0\" max=\"9\" value=\"0\">\n      <div id=\"spinner-error\"></div>\n    </div>\n\n    <div id=\"technical-difficulties\" class=\"spinner-demo\">\n      <img src=\"images/technical-difficulties.png\" width=\"640\" height=\"480\" alt=\"Please stand by\">\n    </div>\n\n    <hgroup class=\"greenbg\">\n      <h2>New APIs</h2>\n    </hgroup>\n    <article>\n      <div class=\"ul build\">\n        <div class=\"li\">System</div>\n        <div class=\"li\">Shared Data</div>\n        <div class=\"li\">Services</div>\n        <aside id=\"spinner-demo-button\" class=\"demobutton\"></aside>\n      </div>\n    </article>\n  </slide>\n\n  <slide>\n    <hgroup>\n      <h2>The Programming Model</h2>\n    </hgroup>\n    <article>\n      <div class=\"ul build\">\n        <div class=\"li\">Packaged apps.</div>\n        <div class=\"li\">Background page as the hub.</div>\n        <div class=\"li\">App lifetime controlled by runtime; event-driven.</div>\n        <aside id=\"programming-demo\" class=\"demobutton\"></aside>\n        <div class=\"li\">\"Single-page\", no navigation.</div>\n        <div class=\"li\">Some web features deprecated.</div>\n      </div>\n    </article>\n  </slide>\n\n  <slide>\n    <hgroup>\n      <h2>The Security Model</h2>\n    </hgroup>\n    <article>\n      <div class=\"ul build\">\n        <div class=\"li\">Process isolation.</div>\n        <div class=\"li\">Sandboxing.</div>\n        <div class=\"li\">Permissions model.</div>\n        <div class=\"li\">Content Security Policy (CSP).</div>\n        <aside id=\"security-demo\" class=\"demobutton\"></aside>\n        <div class=\"li\">Storage isolation.</div>\n        <div class=\"li\">Explicit shared data APIs.</div>\n        <div class=\"li\">No extension APIs.</div>\n      </div>\n    </article>\n  </slide>\n\n  <slide>\n    <hgroup>\n      <h2>&lt;webview&gt;</h2>\n    </hgroup>\n    <article>\n      <div>\n        <pre>&lt;webview src=\"http://news.google.com/\"&gt;</pre>\n        <webview src=\"http://news.google.com/news/section?pz=1&cf=all&ned=us&topic=s&ict=ln\"\n                style=\"width:750px;height:400px\"></webview>\n      </div>\n    </article>\n  </slide>\n\n  <slide>\n    <hgroup>\n      <h2>Take it For a Spin</h2>\n    </hgroup>\n    <article>\n    <img style=\"height: 500px; display:block; margin: auto;\" src=\"images/chrome-logo.svg\">\n    <aside id=\"spinner-demo-button2\" class=\"demobutton\"></aside>\n    </article>\n  </slide>\n\n  <slide>\n    <hgroup>\n      <h2>Apps Evolved</h2>\n    </hgroup>\n    <article>\n      <div id=\"evolution_blocks\" class=\"build\">\n        <div>\n          <div class=\"evoblock bluebg\">\n          Breaking Out of the Browser\n          </div>\n          <div class=\"evoblock redbg\">\n          Enhanced User Interface\n          </div>\n          <div class=\"evoblock yellowbg\">\n          Offline by Default\n          </div>\n          <div class=\"evoblock greenbg\">\n          New APIs\n          </div>\n        </div>\n        <div style=\"margin-top: 50px;\">· Available for testing on Canary</div>\n        <div style=\"margin-top: 10px;\">· System Applications working group</div>\n        <div style=\"margin-top: 10px;\">· Mobile coming</div>\n      </div>\n    </article>\n  </slide>\n\n  <slide>\n    <hgroup>\n      <h2>Check Out More Demos</h2>\n    </hgroup>\n    <article id=\"sandbox\">\n      <div class=\"ul\">\n        <div class=\"li\">Media player - Sencha</div>\n        <div class=\"li\">Photobooth - Kendo UI</div>\n        <div class=\"li\">Text Editor - AngularJS (Google)</div>\n        <div class=\"li\">\"Johnny\" - Google</div>\n        <div class=\"li\">github.com/GoogleChrome</div>\n      </div>\n    </article>\n  </slide>\n\n  <slide class=\"thank-you-slide segue nobackground\">\n    <aside class=\"gdbar right\"><img src=\"images/chrome-logo.png\"></aside>\n    <article class=\"flexbox vleft auto-fadein\">\n      <h2>Thank You!</h2>\n      <p>Try out the developer preview and send us feedback.</p>\n      <p>developer.chrome.com/apps</p>\n      <p>chromium-apps@chromium.org</p>\n      <p>#chromium-apps (freenode)</p>\n    </article>\n  </slide>\n\n  <slide class=\"logoslide dark nobackground\">\n    <article class=\"chromelogo\">\n      <img src=\"images/chrome-logo.png\"><div id=\"chrometext\">chrome</div>\n    </article>\n  </slide>\n  </slide>\n\n  <slide class=\"backdrop\"></slide>\n\n</slides>\n\n<script src=\"js/slide-config.js\"></script>\n<script src=\"js/slide-controller.js\"></script>\n<script src=\"js/slide-deck.js\"></script>\n<script src=\"js/servo.js\"></script>\n<script src=\"js/slides.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/servo/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('main.html', {\n    top: 0,\n    left: 0,\n    width: 640,\n    height: 720\n  });\n})\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/servo/main.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <script src=\"servo.js\"></script>\n  <link rel=\"stylesheet\" href=\"styles.css\">\n</head>\n<body>\n  <div id=\"container\">\n    <label>\n      Port:\n      <select id=\"port-picker\"></select>\n    </label>\n\n    <label>\n      Status:\n      <span id=\"status\">Loading</span>\n    </label>\n\n    <label>\n      Input:\n      <input id=\"position-input\" type=\"range\" min=\"0\" max=\"9\" value=\"0\">\n    </label>\n\n    <div id=\"image\"></div>\n  </div>\n\n  <div id=\"tv\" class=\"off\">\n    <video id=\"camera-output\" width=\"640\" height=\"480\" autoplay></video>\n    <img src=\"technical-difficulties.png\" width=\"640\" height=\"480\" alt=\"Please stand by\">\n  </div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/servo/manifest.json",
    "content": "{\n  \"name\": \"Servo Serial Sample\",\n  \"version\": \"0.4\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"23\",\n  \"description\": \"Show off serial functionality.\",\n\n  \"app\": {\n    \"background\": {\n      \"scripts\": [ \"background.js\" ]\n    }\n  },\n\n  \"permissions\": [\n    \"videoCapture\", \"serial\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/servo/servo.js",
    "content": "var connectionId = -1;\n\nfunction setPosition(position) {\n  var buffer = new ArrayBuffer(1);\n  var uint8View = new Uint8Array(buffer);\n  uint8View[0] = '0'.charCodeAt(0) + position;\n  chrome.serial.send(connectionId, buffer, function() {});\n};\n\nfunction onOpen(connectionInfo) {\n  if (!connectionInfo) {\n    setStatus('Could not open');\n    return;\n  }\n  connectionId = connectionInfo.connectionId;\n  setStatus('Connected');\n\n  setPosition(0);\n};\n\nfunction setStatus(status) {\n  document.getElementById('status').innerText = status;\n}\n\nfunction buildPortPicker(ports) {\n  var eligiblePorts = ports.filter(function(port) {\n    return !port.path.match(/[Bb]luetooth/);\n  });\n\n  var portPicker = document.getElementById('port-picker');\n  eligiblePorts.forEach(function(port) {\n    var portOption = document.createElement('option');\n    portOption.value = portOption.innerText = port.path;\n    portPicker.appendChild(portOption);\n  });\n\n  portPicker.onchange = function() {\n    if (connectionId != -1) {\n      chrome.serial.disconnect(connectionId, openSelectedPort);\n      return;\n    }\n    openSelectedPort();\n  };\n}\n\nfunction openSelectedPort() {\n  var portPicker = document.getElementById('port-picker');\n  var selectedPort = portPicker.options[portPicker.selectedIndex].value;\n  chrome.serial.connect(selectedPort, onOpen);\n}\n\nonload = function() {\n  var tv = document.getElementById('tv');\n  navigator.webkitGetUserMedia(\n      {video: true},\n      function(stream) {\n        tv.classList.add('working');\n        document.getElementById('camera-output').src =\n            webkitURL.createObjectURL(stream);\n      },\n      function() {\n        tv.classList.add('broken');\n      });\n\n  document.getElementById('position-input').onchange = function() {\n    setPosition(parseInt(this.value, 10));\n  };\n\n  chrome.serial.getDevices(function(ports) {\n    buildPortPicker(ports)\n    openSelectedPort();\n  });\n};\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/servo/styles.css",
    "content": "body {\n  background-color: #f8f8f8;\n  font-family: \"helvetica neue\", helvetica, sans-serif;\n  font-size: 16px;\n  overflow: hidden;\n}\n\nlabel {\n  display: block;\n  padding: 20px;\n  border-bottom: solid 1px #ddd;\n  border-right: solid 1px #ddd;\n  width: 300px;\n}\n\nlabel {\n  color: #999;\n}\n\n#port-picker,\n#status {\n  color: #000;\n}\n\n#port-picker {\n  max-width: 250px;\n  margin-right: 10px;\n}\n\n#position-input {\n  display: block;\n   -webkit-appearance:none !important;\n  width: 90%;\n  margin: 20px auto;\n  height: 6px;\n  background: rgb(13, 168, 97);\n}\n\n#position-input::-webkit-slider-thumb {\n  -webkit-appearance:none !important;\n  width: 30px;\n  height: 30px;\n  border-radius: 15px;\n  background: rgb(67, 135, 253);\n}\n\n#image {\n  position: absolute;\n  right: 10px;\n  top: -10px;\n  background-image: url(chrome-logo.svg);\n  background-size: contain;\n  background-repeat: no-repeat;\n  background-position: center;\n  width: 256px;\n  height: 256px;\n  -webkit-transition: all .2s linear;\n}\n\n#container {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 640px;\n}\n\n#tv {\n  position: absolute;\n  bottom: 0;\n  right: 0;\n  width: 640px;\n  height: 480px;\n  border-left: solid 1px #ddd;\n}\n\n#tv video,\n#tv img {\n  display: none;\n}\n\n#tv.working video,\n#tv.broken img {\n  display: block;\n}"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/windowing_api/copycat.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\" />\n\t<title>Untitled</title>\n\t<script src=\"window.js\"></script>\n\t<link rel=\"stylesheet\" href=\"window.css\">\n</head>\n<body class=\"copycat\">\n<div id=\"titlebar\">\n  <div id=\"close\"></div>\n</div>\n\n<h1>Bizarro World</h1>\n\n<pre>\n<b>     x</b>: <span id=\"screenX\"></span>\n<b>     y</b>: <span id=\"screenY\"></span>\n<b> width</b>: <span id=\"innerWidth\"></span>\n<b>height</b>: <span id=\"innerHeight\"></span>\n</pre>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/windowing_api/original.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"utf-8\" />\n\t<title>Untitled</title>\n\t<script src=\"window.js\"></script>\n\t<link rel=\"stylesheet\" href=\"window.css\">\n</head>\n<body>\n\n<h1>Original</h1>\n\n<pre>\n<b>     x</b>: <span id=\"screenX\"></span>\n<b>     y</b>: <span id=\"screenY\"></span>\n<b> width</b>: <span id=\"innerWidth\"></span>\n<b>height</b>: <span id=\"innerHeight\"></span>\n</pre>\n\n<p style=\"text-align: center\">\n<button id=\"minimize-button\">Minimize me!</button>\n</p>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/windowing_api/window.css",
    "content": "body {\n  font-family: Helvetica;\n  overflow: hidden;\n  padding: 0;\n  margin: 0;\n}\n\n.copycat {\n  background: #000;\n  color: #fff;\n}\n\n.copycat #titlebar {\n  height: 25px;\n  position: relative;\n}\n\n.copycat #close {\n  width: 16px;\n  height: 16px;\n  background: url(close-copycat.png) no-repeat;\n  position: absolute;\n  right: 4px;\n  top: 4px;\n}\n\nh1 {\n  background: #eee;\n  margin: 0;\n  padding: 2px;\n  text-align: center;\n  border-top: solid 1px #ccc;\n  border-bottom: solid 1px #ccc;\n}\n\n.copycat h1 {\n  background: #111;\n  border-color: #333;\n}\n\npre {\n  margin: 0;\n  font-size: 35px;\n  color: #333;\n  font-weight: bold;\n  padding: 2px 8px;\n}\n\n.copycat pre {\n  color: #ccc;\n}\n\np {\n  margin: 12px 0;\n}\n"
  },
  {
    "path": "_archive/apps/samples/io2012-presentation/windowing_api/window.js",
    "content": "onload = function() {\n  function update() {\n    ['screenX', 'screenY', 'innerWidth', 'innerHeight'].forEach(function(prop) {\n      document.getElementById(prop).innerText = window[prop];\n    });\n\n    webkitRequestAnimationFrame(update);\n  }\n\n  update();\n\n  var minimizeNode = document.getElementById('minimize-button');\n  if (minimizeNode) {\n    minimizeNode.onclick = function() {\n      opener.windowingApiDemo.minimizeAll();\n    };\n  }\n\n  var closeNode = document.getElementById('close');\n  if (closeNode) {\n    closeNode.onclick = function() {\n      window.close();\n    };\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/ioio/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hknlnnbpihcamokfeggmahjgldbcpkof\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# IOIO Bluetooth device\n\nVery simple IOIO client. Tested with [this hardware](http://www.adafruit.com/blog/2012/06/15/new-product-ioio-mint-portable-android-development-kit/)\n\nThe constants and information about the protocol was taken from https://github.com/ytai/ioio/wiki/\n\n## Caveats:\n* The bluetooth API is only available on dev-channel Chrom(e|ium)OS\n* Resource clean-up isn't happening properly yet: you will likely have to disable/enable bluetooth between runs of the program or the connection will fail\n\n## APIs\n\n* [Bluetooth](http://developer.chrome.com/apps/bluetooth)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/ioio/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/ioio/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n  \tid: \"window1\",\n    innerBounds: {\n      width: 640,\n      height: 480\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/ioio/index.html",
    "content": "<html>\n  <body>\n    <pre id=\"log\"></pre>\n  </body>\n  <script src=\"main.js\"></script>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/ioio/main.js",
    "content": "function log(msg) {\n  var msg_str = (typeof(msg) == 'object') ? JSON.stringify(msg) : msg;\n  console.log(msg_str);\n\n  var l = document.getElementById('log');\n  if (l) {\n    l.innerText += msg_str + '\\n';\n  }\n}\n\nvar kUUID = '00001101-0000-1000-8000-00805f9b34fb';\n\nvar level = 1;\nvar pin = 0;\nfunction runAtInterval(socket) {\n  return function() {\n    var buffer = new ArrayBuffer(4);\n    var view = new Uint8Array(buffer);\n\n    // Set the level of pin0 to level\n    // constants taken from here:\n    // https://github.com/ytai/ioio/wiki/\n    view[2] = 4;\n    view[3] = pin << 2 | level;\n    level = (level == 0) ? 1 : 0;\n\n    chrome.bluetooth.write({socketId:socket.id, data:buffer},\n        function(bytes) {\n          if (chrome.runtime.lastError) {\n            log('Write error: ' + chrome.runtime.lastError.message);\n          } else {\n            log('wrote ' + bytes + ' bytes');\n          }\n        });\n  };\n}\n\nvar socketId_;\nvar intervalId_;\nvar connectCallback = function(socket) {\n  if (socket) {\n    log('Connected!  Socket ID is: ' + socket.id + ' on service ' +\n        socket.serviceUuid);\n    socketId_ = socket.id;\n\n    // Set pin0 as output.\n    var buffer = new ArrayBuffer(2);\n    var view = new Uint8Array(buffer);\n    // constants taken from here:\n    // https://github.com/ytai/ioio/wiki/\n    view[0] = 3;\n    view[1] = pin << 2 | 2;\n    chrome.bluetooth.write({socketId:socket.id, data:buffer},\n        function(bytes) {\n          if (chrome.runtime.lastError) {\n            log('Write error: ' + chrome.runtime.lastError.message);\n          } else {\n            log('wrote ' + bytes + ' bytes');\n          }\n        });\n\n    intervalId_ = window.setInterval(runAtInterval(socket), 1000);\n  } else {\n    log('Failed to connect.');\n  }\n};\n\nvar connectToDevice = function(result) {\n  if (chrome.runtime.lastError) {\n    log('Error searching for a device to connect to.');\n    return;\n  }\n  if (result.length == 0) {\n    log('No devices found to connect to.');\n    return;\n  }\n  for (var i in result) {\n    var device = result[i];\n    log('Connecting to device: ' + device.name + ' @ ' + device.address);\n    chrome.bluetooth.connect(\n        {deviceAddress: device.address, serviceUuid: kUUID}, connectCallback);\n  }\n};\n\nlog('Starting IOIO demo...');\nchrome.bluetooth.getDevices({uuid: kUUID}, connectToDevice);\n"
  },
  {
    "path": "_archive/apps/samples/ioio/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"IOIO Sample\",\n  \"description\": \"Blinks the on-board LED\",\n  \"version\": \"1.1\",\n  \"minimum_chrome_version\": \"23\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [\n    \"bluetooth\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/keyboard-handler/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/keyboard-handler-sample/pcbbaldjljokfnnkphllabnpolciapjc\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Keyboard Handler Sample\n\nThis sample handles all keyboard events (preventing default behavior) and\nmaintains a dictionary of the state of each key.\n\nIt provides an easy way to check if the key strokes you are interested in can\nbe captured by a chrome packaged app, and learn what the appropriate keyCode\nis for them.\n\n## Screenshot\n![screenshot](/_archive/apps/samples/keyboard-handler/assets/screenshot_1280_800.png)\n\n## Credit\n\nIcon image adapted from [David Peters, Wikimedia Foundation](http://commons.wikimedia.org/wiki/File:Keyboard-icon_Wikipedians.svg)\n"
  },
  {
    "path": "_archive/apps/samples/keyboard-handler/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  // Center window on screen.\n  var screenWidth = screen.availWidth;\n  var screenHeight = screen.availHeight;\n\n  var b = {\n      width: Math.round(screenWidth * 2/4),\n      height: Math.round(screenHeight * 2/4),\n      left: Math.round(screenWidth * 1/4),\n      top: Math.round(screenHeight * 1/4)\n    };\n\n  chrome.app.window.create('window.html', {\n    id: \"keyboardWinID\",\n    outerBounds: b\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/keyboard-handler/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Keyboard Handler Sample\",\n  \"version\": \"3.1\",\n  \"icons\": {\n    \"128\": \"assets/icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/keyboard-handler/window.html",
    "content": "<!DOCTYPE html>\n<!-- Simple keyboard state handler, Vincent Scheib. -->\n<!-- Adapted from http://www.cryer.co.uk/resources/javascript/script20_respond_to_keypress.htm -->\n<html>\n<head>\n  <style>\n    body {\n      position: absolute;\n      top: 0;\n      bottom: 0;\n      left: 0;\n      right: 0;\n      overflow: auto;\n    }\n  </style>\n</head>\n<body>\n  <h1>Last events:</h1>\n  <table border=\"1\" cellspacing=\"0\">\n    <tbody>\n      <tr>\n        <th>KeyDown</th>\n        <th>KeyUp</th>\n        <th>KeyPress</th>\n      </tr>\n      <tr>\n        <td id=\"td-keydown\" style=\"width: 12em\" class=\"center\">.</td>\n        <td id=\"td-keyup\" style=\"width: 12em\" class=\"center\">.</td>\n        <td id=\"td-keypress\" style=\"width: 12em\" class=\"center\">.</td>\n      </tr>\n    </tbody>\n  </table>\n\n  <h1>Dictionary of all key's state:</h1>\n  <pre id=\"keyStateDisplay\">No key events captured yet.</pre>\n\n  <h1>Log of events:</h1>\n  <div id=\"keyLog\"></div>\n  <script src=\"window.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/keyboard-handler/window.js",
    "content": "/*\n  Adapted from\n  http://github.com/scheib/HTMLMisc/blob/gh-pages/KeyboardState.html and\n  http://www.cryer.co.uk/resources/javascript/script20_respond_to_keypress.htm\n*/\n\"use strict\";\n\nvar keyStateDict = {};\n\nfunction updateInnerHTML(idToUpdate, description)\n{\n  var cell = document.getElementById(idToUpdate);\n  cell.innerHTML = description;\n}\nfunction displayKeyState()\n{\n  var s = document.getElementById(\"keyStateDisplay\");\n  // Take JSON of keyStateDict and replace structure characters with new lines.\n  var ss = JSON.stringify(keyStateDict);\n  var re = new RegExp(\"[,{}] *\", \"g\");\n  ss = ss.replace(re, \"\\n\");\n  s.innerHTML = ss;\n}\nfunction updateKeyState(event, description)\n{\n  keyStateDict[GetCodeFor(event)] = description;\n  displayKeyState();\n}\nfunction logEvent(description)\n{\n  var logDiv = document.getElementById(\"keyLog\");\n  var entry = document.createElement(\"div\");\n  entry.innerText = description;\n  logDiv.insertBefore(entry, logDiv.firstChild)\n}\nfunction GetCodeFor(e)\n{\n  if ((e.charCode) && (e.keyCode==0))\n  {\n    return e.charCode;\n  } else {\n    return e.keyCode;\n  }\n}\nfunction GetDescriptionFor(e)\n{\n  var result, code;\n  if ((e.charCode) && (e.keyCode==0))\n  {\n    result = \"charCode: \" + e.charCode;\n    code = e.charCode;\n  } else {\n    result = \"keyCode: \" + e.keyCode;\n    code = e.keyCode;\n  }\n  if (code == 8) result += \" BKSP\"\n  else if (code == 9) result += \" TAB\"\n  else if (code == 46) result += \" DEL\"\n  else if ((code >= 41) && (code <=126)) result += \" '\" + String.fromCharCode(code) + \"'\";\n  if (e.shiftKey) result += \" shift\";\n  if (e.ctrlKey) result += \" ctrl\";\n  if (e.altKey) result += \" alt\";\n\n  return result;\n}\nfunction MonitorKeyDown(e)\n{\n  if (!e) e=window.event;\n  var d = GetDescriptionFor(e);\n  updateInnerHTML(\"td-keydown\", d);\n  updateKeyState(e, d + \" == DOWN\");\n  logEvent(d + \" == down\");\n  return false;\n}\nfunction MonitorKeyUp(e)\n{\n  if (!e) e=window.event;\n  var d = GetDescriptionFor(e);\n  updateInnerHTML(\"td-keyup\", d);\n  updateKeyState(e, d + \" == up\");\n  logEvent(d + \" == up\");\n  return false;\n}\nfunction MonitorKeyPress(e)\n{\n  if (!e) e=window.event;\n  var d = GetDescriptionFor(e);\n  updateInnerHTML(\"td-keypress\", d);\n  logEvent(d + \" == press\");\n  return false;\n}\nfunction MonitorBlur()\n{\n  for (key in keyStateDict)\n  {\n    if (keyStateDict[key].indexOf(\"blurred\") < 0)\n      keyStateDict[key] += \"; when document blurred\"\n  }\n  displayKeyState();\n  logEvent(\"blur\");\n}\nfunction MonitorFocus()\n{\n  logEvent(\"focus\");\n}\n\ndocument.addEventListener('keydown', MonitorKeyDown, false)\ndocument.addEventListener('keyup', MonitorKeyUp, false)\ndocument.addEventListener('keypress', MonitorKeyPress, false)\ndocument.body.onblur = MonitorBlur;\ndocument.body.onfocus = MonitorFocus;\n"
  },
  {
    "path": "_archive/apps/samples/managed-in-app-payments/README.md",
    "content": "# Managed In-App Payments with Google Wallet and the Chrome Web Store API\n\nYou can use [managed in-app payments with Google Wallet and the Chrome Web Store API](https://developer.chrome.com/webstore/payments-iap) to sell virtual\ngoods within a Chrome App. When you use managed in-app payments, the\nChrome In-App Payments Service (embedded in Chrome) communicates with:\n * The Chrome Web Store to get the list of available products, including:\n   * Items available for purchase\n   * Items purchased by the user\n * The Google Wallet servers to handle all the required checkout details.\n\nThis means that you can easily manage your virtual good inventory and licensing through the Chrome Web Store Developer Dashboard, and the Chrome Web Store will take care of the nitty gritty details, including financial transaction processing.\n\nThe actual integration work to enable managed in-app payments is similar to using the [Google Wallet for Digital Goods API](https://web.archive.org/web/20130308145345/https://developers.google.com/commerce/wallet/digital/docs/) (now deprecated), except that managed in-app payments require you to embed a piece of JavaScript ([buy.js](https://raw.githubusercontent.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/samples/managed-in-app-payments/scripts/buy.js)) within your app to trigger the payment flow.\n"
  },
  {
    "path": "_archive/apps/samples/managed-in-app-payments/css/app.css",
    "content": "body { padding-top: 60px; }\n\n\ntd:nth-of-type(4) {\n  text-align: center;\n}\n\n.btn {\n  width: 95px;\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/managed-in-app-payments/index.html",
    "content": "<html>\n  <head>\n    <title>IAP Sample App</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"/css/bootstrap.min.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"/css/app.css\">\n  </head>\n  <body>\n    <nav class=\"navbar navbar-default navbar-fixed-top\" role=\"navigation\">\n      <div class=\"navbar-header\">\n        <a class=\"navbar-brand\">Choose Your Avatar</a>\n      </div>\n\n      <p id=\"status\" class=\"navbar-text navbar-right\"></p>\n    </nav>\n\n    <table class=\"table table-striped\">\n      <thead>\n        <tr>\n          <th class=\"name\">Item</th>\n          <th class=\"desc\">Description</th>\n          <th class=\"price\">Price</th>\n          <th class=\"action\"></th>\n        </tr>\n      </thead>\n      <tbody>\n      </tbody>\n    </table>\n\n    <div id=\"modalLicense\" class=\"modal fade\">\n      <div class=\"modal-dialog\">\n        <div class=\"modal-content\">\n          <div class=\"modal-header\">\n            <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\">&times;</button>\n            <h4 class=\"modal-title\">License Data</h4>\n          </div>\n          <div class=\"modal-body\">\n            <pre class=\"license\">license data</pre>\n          </div>\n          <div class=\"modal-footer\">\n            <button type=\"button\" class=\"btn btn-primary\" data-dismiss=\"modal\">Close</button>\n          </div>\n        </div><!-- /.modal-content -->\n      </div><!-- /.modal-dialog -->\n    </div><!-- /.modal -->\n    <script type=\"text/javascript\" src=\"/scripts/jquery-2.0.3.min.js\"></script>\n    <script type=\"text/javascript\" src=\"/scripts/buy.js\"></script>\n    <script type=\"text/javascript\" src=\"/scripts/app.js\"></script>\n    <script type=\"text/javascript\" src=\"/scripts/bootstrap.min.js\"></script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/managed-in-app-payments/main.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n    \"id\": \"ManagedInAppPaymentsDemo\",\n    \"bounds\": {\n      \"width\": 680,\n      \"height\": 480\n    },\n    \"minWidth\": 650\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/managed-in-app-payments/manifest.json",
    "content": "{\n  \"name\": \"Managed In App Payment Sample\",\n  \"version\": \"0.1.0.1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"29\",\n  \"key\": \"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoUq1cKlKbPLfHlA+x/eTxPA5ZSz4bd/fgKInayClJQTc6RRATDfRshCXjn8Eu7VpgsfEG3nLGD0C+8SdDxSGxj51k5elLRcRhDLODjxMshjPpziRm8wxalrGDEVOjD8GX6DG1YXQDMq6Hd9fxSj/ZEBjGvDWtoL3wBZ1M2/+aop/5Z6y9rQDOKI8PmCaIpWmIBS1+zZub9wc/RVNA2glGaSb0N71FxN/W5PhlWwJciG/iIJHhCM888kIPODJq8JgFKz1jO8/3L8YfO9/lzbKZLPnRMrN5q5KZDbG22l6BccSXnqYu4JX9RzXK0HcRzO5SI1l5XPAeZAhNY5M+rZULwIDAQAB\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"icons\": {\n    \"128\": \"/images/128.png\"\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/managed-in-app-payments/scripts/app.js",
    "content": "var prodButPrefix = \"btnProdID-\";\nvar statusDiv;\n\nfunction init() {\n  console.log(\"App Init\");\n  statusDiv = $(\"#status\");\n  getProductList();\n}\n\n/*****************************************************************************\n* Get the list of available products from the Chrome Web Store\n*****************************************************************************/\n\nfunction getProductList() {\n  console.log(\"google.payments.inapp.getSkuDetails\");\n  statusDiv.text(\"Retreiving list of available products...\");\n  google.payments.inapp.getSkuDetails({\n    'parameters': {env: \"prod\"},\n    'success': onSkuDetails,\n    'failure': onSkuDetailsFailed\n  });\n}\n\nfunction onSkuDetails(response) {\n  console.log(\"onSkuDetails\", response);\n  var products = response.response.details.inAppProducts;\n  var count = products.length;\n  for (var i = 0; i < count; i++) {\n    var product = products[i];\n    addProductToUI(product);\n  }\n  statusDiv.text(\"\");\n  getLicenses();\n}\n\nfunction onSkuDetailsFailed(response) {\n  console.log(\"onSkuDetailsFailed\", response);\n  statusDiv.text(\"Error retreiving product list. (\" + response.response.errorType + \")\");\n}\n\n/*****************************************************************************\n* Get the list of purchased products from the Chrome Web Store\n*****************************************************************************/\n\nfunction getLicenses() {\n  console.log(\"google.payments.inapp.getPurchases\");\n  statusDiv.text(\"Retreiving list of purchased products...\");\n  google.payments.inapp.getPurchases({\n    'parameters': {env: \"prod\"},\n    'success': onLicenseUpdate,\n    'failure': onLicenseUpdateFailed\n  });\n}\n\nfunction onLicenseUpdate(response) {\n  console.log(\"onLicenseUpdate\", response);\n  var licenses = response.response.details;\n  var count = licenses.length;\n  for (var i = 0; i < count; i++) {\n    var license = licenses[i];\n    addLicenseDataToProduct(license);\n  }\n  statusDiv.text(\"\");\n}\n\nfunction onLicenseUpdateFailed(response) {\n  console.log(\"onLicenseUpdateFailed\", response);\n  statusDiv.text(\"Error retreiving list of purchased products.\");\n}\n\n\n/*****************************************************************************\n* Purchase an item\n*****************************************************************************/\n\nfunction buyProduct(sku) {\n  console.log(\"google.payments.inapp.buy\", sku);\n  statusDiv.text(\"Kicking off purchase flow for \" + sku);\n  google.payments.inapp.buy({\n    parameters: {'env': \"prod\"},\n    'sku': sku,\n    'success': onPurchase,\n    'failure': onPurchaseFailed\n  });\n}\n\nfunction onPurchase(purchase) {\n  console.log(\"onPurchase\", purchase);\n  var jwt = purchase.jwt;\n  var cartId = purchase.request.cardId;\n  var orderId = purchase.response.orderId;\n  statusDiv.text(\"Purchase completed. Order ID: \" + orderId);\n  getLicenses();\n}\n\nfunction onPurchaseFailed(purchase) {\n  console.log(\"onPurchaseFailed\", purchase);\n  var reason = purchase.response.errorType;\n  statusDiv.text(\"Purchase failed. \" + reason);\n}\n\n/*****************************************************************************\n* Update/handle the user interface actions\n*****************************************************************************/\n\nfunction addProductToUI(product) {\n  var row = $(\"<tr></tr>\");\n  var colName = $(\"<td></td>\").text(product.localeData[0].title);\n  var colDesc = $(\"<td></td>\").text(product.localeData[0].description);\n  var price = parseInt(product.prices[0].valueMicros, 10) / 1000000;\n  var colPrice = $(\"<td></td>\").text(\"$\" + price);\n  var butAct = $(\"<button type='button'></button>\")\n    .data(\"sku\", product.sku)\n    .attr(\"id\", prodButPrefix + product.sku)\n    .addClass(\"btn btn-sm\")\n    .click(onActionButton)\n    .text(\"Purchase\")\n    .addClass(\"btn-success\");\n  var colBut = $(\"<td></td>\").append(butAct);\n  row\n    .append(colName)\n    .append(colDesc)\n    .append(colPrice)\n    .append(colBut);\n  $(\"tbody\").append(row);\n}\n\nfunction addLicenseDataToProduct(license) {\n  var butAction = $(\"#\" + prodButPrefix + license.sku);\n  butAction\n    .text(\"View license\")\n    .removeClass(\"btn-success\")\n    .removeClass(\"btn-default\")\n    .addClass(\"btn-info\")\n    .data(\"license\", license);\n}\n\nfunction onActionButton(evt) {\n  console.log(\"onActionButton\", evt);\n  var actionButton = $(evt.currentTarget);\n  if (actionButton.data(\"license\")) {\n    showLicense(actionButton.data(\"license\"));\n  } else {\n    var sku = actionButton.data(\"sku\");\n    buyProduct(sku);\n  }\n}\n\nfunction showLicense(license) {\n  console.log(\"showLicense\", license);\n  var modal = $(\"#modalLicense\");\n  modal.find(\".license\").text(JSON.stringify(license, null, 2));\n  modal.modal('show');\n}\n\ninit();"
  },
  {
    "path": "_archive/apps/samples/managed-in-app-payments/scripts/buy.js",
    "content": "(function() { var f=this,g=function(a,d){var c=a.split(\".\"),b=window||f;c[0]in b||!b.execScript||b.execScript(\"var \"+c[0]);for(var e;c.length&&(e=c.shift());)c.length||void 0===d?b=b[e]?b[e]:b[e]={}:b[e]=d};var h=function(a){var d=chrome.runtime.connect(\"nmmhkkegccagdldgiimedpiccmgmieda\",{}),c=!1;d.onMessage.addListener(function(b){c=!0;\"response\"in b&&!(\"errorType\"in b.response)?a.success&&a.success(b):a.failure&&a.failure(b)});d.onDisconnect.addListener(function(){!c&&a.failure&&a.failure({request:{},response:{errorType:\"INTERNAL_SERVER_ERROR\"}})});d.postMessage(a)};g(\"google.payments.inapp.buy\",function(a){a.method=\"buy\";h(a)});\ng(\"google.payments.inapp.consumePurchase\",function(a){a.method=\"consumePurchase\";h(a)});g(\"google.payments.inapp.getPurchases\",function(a){a.method=\"getPurchases\";h(a)});g(\"google.payments.inapp.getSkuDetails\",function(a){a.method=\"getSkuDetails\";h(a)}); })();\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/cnehcenehakkickcnoiaemcpjpaigmbb\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Manga Camera\n\nChrome Packaged App with `videoCapture` permission can query user media without a warning. It is also possible to process the image captured by a video camera using WebGL. You can then save the pictures you take to the the sync file system. The pictures will be synced among your devices.\n\n## APIs\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n* [Sync File Systesm](http://developer.chrome.com/apps/syncFileSystem)\n* [videoCapture](http://developer.chrome.com/apps/manifest#permissions)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/manga-cam/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/background.js",
    "content": "var wind = null ,requestingWindow = null;\nvar fs = null;\n\nfunction onWindowLoaded() {\n  wind = this;\n  if (fs) {\n    this.onCreatedFileSystem(fs);\n  } else {\n    requestingWindow = wind;\n  }\n}\n\nchrome.app.runtime.onLaunched.addListener(function () {\n  chrome.app.window.create(\"index.html\", {\n    resizable: false,\n    frame: 'none',\n    id: \"index\",\n    innerBounds: {\n      width: 640,\n      height: 635\n    }\n  }, function(newWindow) {\n    if (newWindow.contentWindow != wind) {\n      newWindow.contentWindow.onload = onWindowLoaded;\n      newWindow.onClosed.addListener(function() {\n        wind = null;\n      });\n    }\n  });\n});\n\nchrome.syncFileSystem.requestFileSystem(function(syncFS) {\n  fs = syncFS;\n  if (requestingWindow) {\n    requestingWindow.onCreatedFileSystem(fs);\n  }\n});\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/css/index.css",
    "content": "html, div, body, canvas {\n  margin: 0;\n  padding: 0;\n  box-sizing: border-box;\n}\n\nbody {\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  margin: 0;\n  padding: 0;\n  -webkit-app-region: drag;\n  background: black;\n  overflow: hidden;\n}\n\n#container {\n  display: -webkit-flex;\n  -webkit-flex-direction: column;\n  text-align: center;\n}\n\ncanvas {\n  height: 480px;\n  -webkit-transition: 1s opacity;\n  background: black;\n}\n\n#main {\n  position: relative;\n  background: white;\n  height: 480px;\n  text-align: center;\n}\n\n#list {\n  position: absolute;\n  text-align: left;\n  padding: 10px;\n  padding-bottom: 25px;\n  height: 155px;\n  white-space: nowrap;\n  overflow-x: auto;\n  overflow-y: hidden;\n  background: white;\n  width: 640px;\n  border-top: 2px solid black;\n  -webkit-app-region: no-drag;\n}\n\n#list img {\n  height: 120px;\n  background: black;\n  margin-left: 10px;\n  -webkit-transition: 1s opacity;\n  border: 1px solid black;\n  -webkit-app-region: no-drag;\n}\n\n.invisible {\n  -webkit-transition: 0s opacity;\n  opacity: 0;\n}\n\n#list img:first-child {\n  margin-left: 0;\n}\n\nbutton {\n  width: 44px;\n  height: 44px;\n  border-radius: 22px;\n  border: 1px none;\n  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);\n  outline: none;\n  cursor: pointer;\n  background: url(../images/camera-button.png) center center, white;\n  background-size: 44px 44px;\n  position: absolute;\n  bottom: -22px;\n  margin-left: -22px;\n  z-index: 1000;\n  -webkit-transform: translate3d(0, 0, 0);\n  -webkit-app-region: no-drag;\n}\n\nbutton:disabled {\n  opacity: 0.3;\n}\n\nbutton:hover {\n  border-color: black;\n}\n\nbutton:active {\n  border-color: black;\n  -webkit-transform: translate3d(1px, 1px, 0);\n}\n\n#close-button {\n  position: absolute;\n  top: 5px;\n  right: 5px;\n  cursor: pointer;\n  width: 20px;\n  height: 20px;\n  background: white;\n  z-index: 1000;\n  -webkit-app-region: no-drag;\n}\n\n#close-button:hover {\n  font-weight: bold;\n}\n\n#no-camera {\n  top: 330px;\n  font-family: Impact;\n  font-size: 35px;\n  position: relative;\n  z-index: 1000;\n  height: 0;\n  color: white;\n  text-shadow: 0 0 2px black;\n  display: none;\n}\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <link href=\"css/index.css\" rel=\"stylesheet\"/>\n  <title>Manga Cam</title>\n</head>\n<body>\n<div id=\"container\">\n  <div id=\"main\">\n    <div id=\"no-camera\">Where is your recording device?<br/>I need your recording device.</div>\n    <div id=\"close-button\">x</div>\n    <canvas id=\"main-canvas\"></canvas>\n    <button disabled></button>\n  </div>\n  <div id=\"list\" title=\"Drag images to save them.\"></div>\n</div>\n</body>\n<script src=\"js/postproc.js\"></script>\n<script src=\"js/loader.js\"></script>\n<script src=\"js/index.js\"></script>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/js/index.js",
    "content": "'use strict';\n\nwindow.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame;\nnavigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;\n\nfunction createBlobFromeDataURL(base64DataURL) {\n  var strippedData = base64DataURL.substr(\n      base64DataURL.indexOf(';base64,') + ';base64,'.length);\n  strippedData = atob(strippedData);\n  var rawData = new Uint8Array(strippedData.length);\n  for (var i = 0; i < strippedData.length; i++) {\n    rawData[i] = strippedData.charCodeAt(i);\n  }\n  return new Blob([rawData.buffer], {type: 'image/png'});\n}\n\nfunction init(saveImage) {\n  loadShaders([\n    'shaders/blur.x.glsl',\n    'shaders/blur.y.glsl',\n    'shaders/sobel.fs.glsl',\n    'shaders/copy.fs.glsl',\n    'shaders/merge.fs.glsl',\n    'shaders/toonize.fs.glsl',\n    'shaders/flake.fs.glsl'\n  ], function (shaders) {\n    var srcCanvas = document.createElement('canvas');\n    srcCanvas.width = 1024;\n    srcCanvas.height = 1024;\n    var srcCtx = srcCanvas.getContext('2d');\n    var dstCanvas = document.getElementById('main-canvas');\n    var postproc = new PostProcessor(dstCanvas, 1024, 1024);\n\n    var blurXProgram = postproc.createProgram(shaders[0]);\n    var blurYProgram = postproc.createProgram(shaders[1]);\n    var sobelProgram = postproc.createProgram(shaders[2]);\n    var copyProgram = postproc.createProgram(shaders[3]);\n    var mergeProgram = postproc.createProgram(shaders[4]);\n    var toonizeProgram = postproc.createProgram(shaders[5]);\n    var flakeProgram = postproc.createProgram(shaders[6], {time: '1f'});\n\n    var origin = postproc.createInput();\n    var blurred1 = postproc.createInput();\n    var blurred2 = postproc.createInput();\n    var sobel = postproc.createInput();\n    var oagTexture= postproc.createInput();\n    var output = postproc.createInput();\n\n\n    var WIDTH = 640;\n    var HEIGHT = 480;\n    var video = document.createElement('video');\n\n    var oagImage = new Image();\n    oagImage.src = \"../images/oag.jpg\";\n    oagImage.onload = function () {\n      var canvas = document.createElement('canvas');\n      canvas.width = canvas.height = 1024;\n      var ctx = canvas.getContext('2d');\n      ctx.translate(WIDTH, HEIGHT);\n      ctx.scale(-1, -1);\n      ctx.drawImage(oagImage, 0, 0, oagImage.width, oagImage.height, 0, 0, WIDTH, HEIGHT);\n      postproc.gl.bindTexture(postproc.gl.TEXTURE_2D, oagTexture);\n      postproc.gl.texImage2D(postproc.gl.TEXTURE_2D, 0, postproc.gl.RGBA, postproc.gl.RGBA, postproc.gl.UNSIGNED_BYTE, canvas);\n    };\n\n    document.querySelector('#close-button').onclick = function() {\n      chrome.app.window.current().close();\n    };\n\n    function tick() {\n\n      // We require a power-of-2-sized image.\n      // Past the video to such a canvas first.\n      srcCtx.drawImage(video, 0, 0);\n      postproc.setupInputImage(srcCanvas);\n      postproc.copyTo(origin);\n\n      // Sobel operator\n      postproc.callProgram(sobelProgram, [origin], sobel);\n\n      // Feature preserving smoothing.\n      postproc.callProgram(blurXProgram, [sobel, origin], blurred1);\n      postproc.callProgram(blurYProgram, [sobel, blurred1], blurred2);\n\n      // Toonize image\n      postproc.callProgram(toonizeProgram, [sobel, blurred2], blurred1);\n\n      // Merge toonized image with edges.\n      postproc.callProgram(mergeProgram, [sobel, blurred1], output);\n\n      postproc.renderTexture(output);\n      window.requestAnimationFrame(tick);\n    }\n\n    function flake() {\n      postproc.callProgram(flakeProgram, [oagTexture], output, {time: performance.now()});\n      postproc.renderTexture(output);\n      window.requestAnimationFrame(flake);\n    }\n\n    function prependNewPicture(dataUrl) {\n      var blob = createBlobFromeDataURL(dataUrl);\n      // Inserts to list\n      var img = document.createElement('img');\n      img.className = \"invisible\";\n      img.draggable = true;\n      img.src = dataUrl;\n      var list = document.querySelector('#list');\n      list.insertBefore(img, list.childNodes[0]);\n      list.scrollLeft = 0;\n      setTimeout(function () {\n        img.classList.remove('invisible');\n      }, 0);\n\n      saveImage(blob);\n    }\n\n    function bindEvents() {\n      var button = document.querySelector('button');\n      var data = new Uint32Array(1024 * 1024);\n      button.onclick = function () {\n        button.disabled = true;\n        try {\n\n          var canvas = document.createElement('canvas');\n          canvas.width = WIDTH;\n          canvas.height = HEIGHT;\n          postproc.iterate(copyProgram);\n          postproc.readBackTexture(output, data);\n          var ctx = canvas.getContext('2d');\n          var imageData = ctx.createImageData(1024, 1024);\n          imageData.data.set(new Uint8Array(data.buffer));\n          ctx.putImageData(imageData, 0, 0);\n\n          // Flip the image\n          ctx.translate(0, HEIGHT);\n          ctx.scale(1, -1);\n          ctx.drawImage(canvas, 0, 0);\n\n          dstCanvas.classList.add('invisible');\n          setTimeout(function () {\n            dstCanvas.classList.remove('invisible');\n          });\n\n          prependNewPicture(canvas.toDataURL('image/png;base64'));\n        } finally {\n          setTimeout(function () {\n            button.disabled = false;\n          }, 1000);\n        }\n      };\n      button.disabled = false;\n    }\n\n    navigator.getUserMedia({video: true}, function (stream) {\n      video.src = URL.createObjectURL(stream);\n      video.play();\n\n      // wait for enough data to read videoWidth/videoHeight properties\n      video.addEventListener('loadeddata',function() {\n        WIDTH = video.videoWidth;\n        HEIGHT = video.videoHeight;\n        dstCanvas.width = WIDTH;\n        dstCanvas.height = HEIGHT;\n        srcCtx.translate(WIDTH, HEIGHT);\n        srcCtx.scale(-1, -1);\n\n        window.requestAnimationFrame(tick);\n      });\n\n      bindEvents();\n    }, function () {\n      console.error(\"Cannot acquire user media.\");\n      document.querySelector('#no-camera').style.display = 'block';\n      dstCanvas.width = WIDTH;\n      dstCanvas.height = HEIGHT;\n      srcCtx.translate(WIDTH, HEIGHT);\n      srcCtx.scale(-1, -1);\n      window.requestAnimationFrame(flake);\n    });\n  });\n}\n\nwindow.onCreatedFileSystem = function (fileSystem) {\n  if (chrome.runtime.lastError) {\n    console.error(chrome.runtime.lastError);\n    return;\n  }\n\n  var reader = fileSystem.root.createReader();\n  var entries = [];\n\n  function insertImage(fileEntry) {\n    fileEntry.file(function (file) {\n      var reader = new FileReader();\n      reader.onloadend = function (e) {\n        var img = document.createElement('img');\n        img.className = \"invisible\";\n        img.draggable = true;\n        img.src = this.result;\n        img.addEventListener('dragstart', function (event) {\n          event.dataTransfer.setData(\"image/png\", file);\n        });\n        var list = document.querySelector('#list');\n        list.appendChild(img);\n        list.scrollLeft = 0;\n        setTimeout(function () {\n          img.classList.remove('invisible');\n        }, 0);\n      };\n      reader.readAsDataURL(file);\n    });\n  }\n\n  function readEntries() {\n    reader.readEntries(function (results) {\n      if (results.length) {\n        entries.push.apply(entries, results);\n        readEntries();\n      } else {\n        entries.sort(function (a, b) {\n          return parseFloat(b.name.substr('image-'.length)) - parseFloat(a.name.substr('image-'.length));\n        });\n        for (var i = 0; i < entries.length; i++) {\n          insertImage(entries[i]);\n        }\n        saveImage = function (blob) {\n          // Writes to file system\n          var time = Date.now();\n          fileSystem.root.getFile('image-' + time + '.png', {create: true, exclusive: true}, function (fileEntry) {\n            fileEntry.createWriter(function (fileWriter) {\n              fileWriter.write(blob);\n            });\n          });\n        };\n        for (i = 0; i < imagesToSave.length; i++) {\n          (function (time, blob) {\n            fileSystem.root.getFile('image-' + time + '.png', {create: true, exclusive: true}, function (fileEntry) {\n              fileEntry.createWriter(function (fileWriter) {\n                fileWriter.write(blob);\n              });\n            });\n          }(imagesToSave[i][0], imagesToSave[i][1]));\n        }\n      }\n    });\n  }\n\n  readEntries();\n};\n\n\nvar saveImage = function (blob) { imagesToSave.push([Date.now(), blob]); },\n    imagesToSave = [];\n\ninit(function (blob) {\n  saveImage(blob);\n});\n\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/js/loader.js",
    "content": "'use strict';\n\n(function (global) {\n  var scripts = document.querySelectorAll('script');\n  var script_base_url = scripts[scripts.length - 1].src;\n  scripts = null;\n  var include_re = /^#include\\s*\"([\\w\\.]+?)\"\\s*$/m;\n  var rel_re = /(\\/[^\\/]+\\/\\.\\.)|([^\\/]+\\/\\.\\.\\/?)/g;\n  var root_re = /^[\\w\\-]*:\\/\\/\\/?[\\w\\-\\.]+/;\n  var loadingCache = {};\n\n  function resolveShader(code, file, callback) {\n    if (!include_re.test(code)) {\n      callback(code);\n      return;\n    }\n    loadShaderImpl(include_re.exec(code)[1], file, function (shader) {\n      code = code.replace(include_re, shader);\n      resolveShader(code, file, callback);\n    });\n  }\n\n  function loadShaderImpl(file, base_url, callback) {\n    if (loadingCache[file]) {\n      callback(loadingCache[file]);\n      return;\n    }\n\n    var nf = file.replace(rel_re, '');\n    while (nf != file) {\n      file = nf;\n      nf = file.replace(rel_re, '');\n    }\n\n    if (root_re.exec(file)) {\n      var xhr = new XMLHttpRequest();\n      xhr.open(\"GET\", file, true);\n      xhr.onload = function () {\n        var code = xhr.responseText;\n        resolveShader(code, file, function (resolved_code) {\n          loadingCache[file] = resolved_code;\n          callback(resolved_code);\n        });\n      };\n      xhr.send(null);\n      return;\n    }\n\n    if (base_url.charAt(base_url.length - 1) == '/') {\n      loadShaderImpl(base_url + file, base_url, callback);\n    } else {\n      loadShaderImpl(base_url.substring(0, base_url.lastIndexOf('/') + 1) + file, base_url, callback);\n    }\n  }\n\n  function loadShader(file, callback) {\n    loadShaderImpl(file, script_base_url, callback);\n  }\n\n  function loadShaders(files, callback) {\n    var result = [], finished = 0;\n\n    files.forEach(function (file, i) {\n      loadShader(file, function (code) {\n        result[i] = code;\n        finished++;\n        if (finished == files.length) {\n          callback(result);\n        }\n      });\n    });\n  }\n\n  global.loadShader = loadShader;\n  global.loadShaders = loadShaders;\n})(this);\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/js/postproc.js",
    "content": "'use strict';\n\nvar MAPPING_VERTEX_SHADER = \"attribute vec3 aPosition;\\n\" +\n    \"varying vec2 vTexCoord;\\n\" +\n    \"void main() {\\n\" +\n    \"  gl_Position = vec4((aPosition - 0.5) * 2.0, 1.0);\\n\" +\n    \"  vTexCoord = aPosition.xy;\\n\" +\n    \"}\";\nvar MAPPING_FRAGMENT_SHADER = \"#ifdef GL_ES\\n\" +\n    \"precision highp float;\\n\" +\n    \"#endif\\n\" +\n    \"uniform sampler2D tex0;\\n\" +\n    \"varying vec2 vTexCoord;\\n\" +\n    \"void main() {\\n\" +\n    \"  gl_FragColor = texture2D(tex0, vTexCoord);\\n\" +\n    \"}\";\n\nfunction PostProcessor(canvas, width, height) {\n  this.width = width;\n  this.height = height;\n  if (!canvas) {\n    canvas = document.createElement('canvas');\n    canvas.width = width;\n    canvas.height = height;\n  }\n  this.canvas = canvas;\n  var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n  this.gl = gl;\n\n  this.vbo = gl.createBuffer();\n  gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);\n  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0]), gl.STATIC_DRAW);\n  this.ibo = gl.createBuffer();\n  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.ibo);\n  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 2, 1, 3]), gl.STATIC_DRAW);\n  this.working_textures = [this.createTexture(), this.createTexture(), this.createTexture()];\n  this.frameBuffer = gl.createFramebuffer();\n  gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer);\n  this.copyProgram = this.createProgram(MAPPING_FRAGMENT_SHADER);\n}\n\nPostProcessor.prototype.installUniform = function (program, uniformName, uniformType) {\n  var gl = this.gl;\n  var uniformLocation = gl.getUniformLocation(program, uniformName);\n  if (uniformLocation) {\n    program.uniforms.__defineGetter__(uniformName, function () {\n      return gl[\"uniform\" + uniformType](uniformLocation);\n    });\n    program.uniforms.__defineSetter__(uniformName, function (value) {\n      gl[\"uniform\" + uniformType](uniformLocation, value);\n    });\n  }\n};\n\nPostProcessor.prototype.createProgram = function (calculation, uniforms) {\n  var gl = this.gl;\n  try {\n    var success = false;\n    var vertexShader = gl.createShader(gl.VERTEX_SHADER);\n    gl.shaderSource(vertexShader, MAPPING_VERTEX_SHADER);\n    gl.compileShader(vertexShader);\n    if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {\n      throw \"Failed to create vertex shader:\\n\" + gl.getShaderInfoLog(vertexShader);\n    }\n\n    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n    gl.shaderSource(fragmentShader, calculation);\n    gl.compileShader(fragmentShader);\n    if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\n      throw \"Failed to create fragment shader:\\n\" + gl.getShaderInfoLog(fragmentShader);\n    }\n\n    var program = gl.createProgram();\n    // attach our two shaders to the program\n    gl.attachShader(program, vertexShader);\n    gl.attachShader(program, fragmentShader);\n    gl.linkProgram(program);\n    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n      throw \"Failed to link program\";\n    }\n\n    gl.enableVertexAttribArray(gl.getAttribLocation(program, \"aPosition\"));\n    gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 12, 0); // position\n\n    gl.useProgram(program);\n    gl.uniform1i(gl.getUniformLocation(program, \"uTexture\"), 0);\n    program.uniforms = {};\n    this.installUniform(program, 'width', '1i');\n    this.installUniform(program, 'height', '1i');\n    program.uniforms.width = this.width;\n    program.uniforms.height = this.height;\n    if (uniforms) {\n      for (var name in uniforms) {\n        this.installUniform(program, name, uniforms[name]);\n      }\n    }\n    success = true;\n    return program;\n  } finally {\n    if (!success) {\n      if (program) {\n        gl.deleteProgram(program);\n        program = undefined;\n      }\n      if (vertexShader) {\n        gl.deleteShader(vertexShader);\n      }\n      if (fragmentShader) {\n        gl.deleteShader(fragmentShader);\n      }\n    }\n  }\n};\n\nPostProcessor.prototype.createTexture = function () {\n  var gl = this.gl;\n  var texture = gl.createTexture();\n  gl.bindTexture(gl.TEXTURE_2D, texture);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n  return texture;\n};\n\nPostProcessor.prototype.setupInputImage = function (image, width, height) {\n  var gl = this.gl;\n  gl.viewport(0, 0, this.width, this.height);\n  gl.bindTexture(gl.TEXTURE_2D, this.working_textures[0]);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,\n      this.width, this.height, 0, gl.RGBA,\n      gl.UNSIGNED_BYTE, null);\n  gl.bindTexture(gl.TEXTURE_2D, this.working_textures[1]);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,\n      gl.UNSIGNED_BYTE, image);\n};\n\nPostProcessor.prototype.setupInput = function (array) {\n  var gl = this.gl;\n  gl.viewport(0, 0, this.width, this.height);\n  gl.bindTexture(gl.TEXTURE_2D, this.working_textures[0]);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,\n      this.width, this.height, 0, gl.RGBA,\n      gl.UNSIGNED_BYTE, null);\n  gl.bindTexture(gl.TEXTURE_2D, this.working_textures[1]);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,\n      this.width, this.height, 0, gl.RGBA,\n      gl.UNSIGNED_BYTE, new Uint8Array(array.buffer));\n};\n\nPostProcessor.prototype.createInputImage = function (image, width, height) {\n  var gl = this.gl;\n  var texture = this.createTexture();\n  gl.viewport(0, 0, this.width, this.height);\n  gl.bindTexture(gl.TEXTURE_2D, texture);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,\n      gl.UNSIGNED_BYTE, image);\n  return texture;\n};\n\n/**\n *\n * @param [array]\n * @returns {*}\n */\nPostProcessor.prototype.createInput = function (array) {\n  var gl = this.gl;\n  var texture = this.createTexture();\n  gl.viewport(0, 0, this.width, this.height);\n  gl.bindTexture(gl.TEXTURE_2D, texture);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA,\n      this.width, this.height, 0, gl.RGBA,\n      gl.UNSIGNED_BYTE, array ? new Uint8Array(array.buffer) : null);\n  return texture;\n};\n\nPostProcessor.prototype.callProgram = function (program, inputs, output, uniforms) {\n  var gl = this.gl;\n  gl.useProgram(program);\n\n  // Output\n  gl.viewport(0, 0, this.width, this.height);\n  gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer);\n  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, output, 0);\n\n  // Input\n  for (var i = 0; i < inputs.length; i++) {\n    gl.uniform1i(gl.getUniformLocation(program, \"texture\" + i), i);\n    gl.activeTexture(gl.TEXTURE0 + i);\n    gl.bindTexture(gl.TEXTURE_2D, inputs[i]);\n  }\n\n  if (uniforms) {\n    for (var name in uniforms) {\n      program.uniforms[name] = uniforms[name];\n    }\n  }\n  gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);\n\n};\n\nPostProcessor.prototype.copyTo = function (output) {\n  this.callProgram(this.copyProgram, [this.working_textures[1]], output, {});\n};\n\nPostProcessor.prototype.swap = function () {\n  var temp = this.working_textures[1];\n  this.working_textures[1] = this.working_textures[0];\n  this.working_textures[0] = temp;\n};\n\nPostProcessor.prototype.iterate = function (program, uniforms) {\n  this.callProgram(program, [this.working_textures[1]], this.working_textures[0], uniforms);\n  this.swap();\n};\n\nPostProcessor.prototype.renderTexture = function (texture, width, height) {\n  var gl = this.gl;\n  // Output\n  gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n  // Input\n  gl.activeTexture(gl.TEXTURE0);\n  gl.bindTexture(gl.TEXTURE_2D, texture);\n\n  gl.useProgram(this.copyProgram);\n  gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);\n};\n\nPostProcessor.prototype.render = function (width, height) {\n  this.renderTexture(this.working_textures[1], width, height);\n};\n\nPostProcessor.prototype.readBackTexture = function (texture, array) {\n  this.callProgram(this.copyProgram, [texture], this.working_textures[0]);\n  this.readBack(array);\n};\n\nPostProcessor.prototype.readBack = function (array) {\n  var gl = this.gl;\n  var buffer = new Uint8Array(array.buffer);\n  gl.readPixels(0, 0, this.width, this.height, gl.RGBA, gl.UNSIGNED_BYTE, buffer);\n};\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/js/shaders/blur.x.glsl",
    "content": "#include \"packing.include.glsl\"\n#include \"index.include.glsl\"\n#line 3\n\nuniform sampler2D texture0, texture1;\n\nvoid main() {\n  vec4 color = getd(texture1, 0, 0);\n  float count = 1.0;\n  float a = 1.0;\n  float sobel = 0.0;\n  for (int i = 1; i < 5; i++) {\n    sobel = smoothstep(0.5, 0.9, 1.0 - length(getd(texture0, i, 0)) / 4.0);\n    a *= exp(-sobel * 25.0);\n    count += a;\n    color += getd(texture1, i, 0) * a;\n  }\n\n  a = 1.0;\n  for (int i = 1; i < 5; i++) {\n    sobel = smoothstep(0.5, 0.9, 1.0 - length(getd(texture0, -i, 0)) / 4.0);\n    a *= exp(-sobel * 25.0);\n    count += a;\n    color += getd(texture1, -i, 0) * a;\n  }\n\n  gl_FragColor = vec4(color.xyz / count, 1);\n}\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/js/shaders/blur.y.glsl",
    "content": "#include \"packing.include.glsl\"\n#include \"index.include.glsl\"\n#line 3\n\nuniform sampler2D texture0, texture1;\n\nvoid main() {\n  vec4 color = getd(texture1, 0, 0);\n  float count = 1.0;\n  float a = 1.0;\n  float sobel = 0.0;\n  for (int i = 1; i < 5; i++) {\n    sobel = smoothstep(0.5, 0.9, 1.0 - length(getd(texture0, 0, i)) / 4.0);\n    a *= exp(-sobel * 25.0);\n    count += a;\n    color += getd(texture1, 0, i) * a;\n  }\n\n  a = 1.0;\n  for (int i = 1; i < 5; i++) {\n    sobel = smoothstep(0.5, 0.9, 1.0 - length(getd(texture0, 0, -i)) / 4.0);\n    a *= exp(-sobel * 25.0);\n    count += a;\n    color += getd(texture1, 0, -i) * a;\n  }\n\n  gl_FragColor = vec4(color.xyz / count, 1);\n}\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/js/shaders/copy.fs.glsl",
    "content": "#ifdef GL_ES\nprecision highp float;\n#endif\n\nuniform sampler2D texture0;\nvarying vec2 vTexCoord;\nvoid main() {\n  gl_FragColor = texture2D(texture0, vTexCoord);\n}\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/js/shaders/flake.fs.glsl",
    "content": "#include \"packing.include.glsl\"\n#include \"index.include.glsl\"\n#line 3\n\nuniform float time;\nuniform sampler2D texture0;\n\nfloat random(float x) {\n  return fract(sin(x + fract(time/1000.0)) * 523621.2342) + 0.5;\n}\n\nvoid main() {\n  float r = random(vTexCoord.x + vTexCoord.y * float(width));\n  float oag = dot(vec3(0.33333), texture2D(texture0, vTexCoord).xyz);\n  r *= (oag + 2.0) / (3.0);\n  gl_FragColor = vec4(r, r, r, 1);\n}\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/js/shaders/index.include.glsl",
    "content": "#line 20001\nuniform int width, height;\nvarying vec2 vTexCoord;\n\nivec2 getIndex() {\n  return ivec2(int(vTexCoord.x * float(width)),\n               int(vTexCoord.y * float(height)));\n}\n\nvec4 get(sampler2D tex, int x, int y) {\n  return texture2D(tex, vec2(float(x) / float(width),\n                   float(y) / float(height)));\n}\n\nvec4 getd(sampler2D tex, int dx, int dy) {\n  ivec2 idx = getIndex();\n  return get(tex, dx + idx.x, dy + idx.y);\n}\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/js/shaders/merge.fs.glsl",
    "content": "#include \"packing.include.glsl\"\n#include \"index.include.glsl\"\n#line 3\n\nuniform sampler2D texture0, texture1;\nconst float V = 0.3;\n\nvoid main() {\n  vec4 sobelpx = getd(texture0, 0, 0);\n  vec3 color0 = getd(texture1, 0, 0).xyz;\n  float y = clamp(dot(color0, vec3(1.0 / 3.0)) + 0.3, 0.0, 1.0);\n  float sobel = smoothstep(0.8, 0.9, clamp(length(sobelpx) - 1.0, 0.0, 1.0));\n  gl_FragColor = vec4(color0 * sobel, 1);\n}\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/js/shaders/packing.include.glsl",
    "content": "#line 10001\n#ifdef GL_ES\nprecision highp float;\n#endif\n\nfloat b2f(vec4 fbytes) {\n    ivec4 bytes = ivec4(fbytes * 255.0 + 0.5);\n    float f = float(bytes[0] + bytes[1] * 256) +\n        float(bytes[2] - bytes[2] / 128 * 128 + 128) * 256.0 * 256.0;\n    int exp = 150 - (bytes[3] - bytes[3] / 128 * 128) * 2 - (bytes[2] / 128);\n    f /= exp2(float(exp));\n    return float(1 - (bytes[3] / 128) * 2) * f;\n}\n\nvec4 f2b(float f) {\n    if (f == 0.0)\n        return vec4(0);\n    bool pos = f > 0.0;\n    if (!pos)\n        f = -f;\n    int expo = int(floor(log2(f)));\n    f *= pow(2.0, 23.0 - float(expo));\n    f -= 8388608.0;\n    int b = int(floor(f + 0.5));\n    expo += 127;\n    int posbit = pos ? 0 : 128;\n    return vec4(b - b / 256 * 256, b / 256 - b / 256 / 256 * 256,\n                b / 256 / 256 + (expo - expo / 2 * 2) * 128,\n                expo / 2 + posbit) / 255.0;\n}\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/js/shaders/sobel.fs.glsl",
    "content": "#include \"packing.include.glsl\"\n#include \"index.include.glsl\"\n#line 3\n\nuniform sampler2D texture0;\n\nvoid main() {\n  vec4 gx = (getd(texture0, -1, -1) - getd(texture0, 1, -1)) +\n      (getd(texture0, -1, 0) - getd(texture0, 1, 0)) * 2.0 +\n      (getd(texture0, -1, 1) - getd(texture0, 1, 1));\n  vec4 gy = (getd(texture0, -1, -1) - getd(texture0, -1, 1)) +\n      (getd(texture0, 0, -1) - getd(texture0, 0, 1)) * 2.0 +\n      (getd(texture0, 1, -1) - getd(texture0, 1, 1));\n  gl_FragColor = 1.0 - sqrt(gx * gx + gy * gy);\n}\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/js/shaders/toonize.fs.glsl",
    "content": "#include \"packing.include.glsl\"\n#include \"index.include.glsl\"\n#line 3\n\nuniform sampler2D texture0, texture1;\n\nvoid main() {\n  vec3 color0 = getd(texture1, 0, 0).xyz;\n  float y = dot(color0, vec3(0.299, 0.587, 0.114));\n  y = (step(0.1, y) + step(0.2, y) + step(0.7, y) + step(0.9, y)) / 6.0;\n  vec2 blockxy = vec2(getIndex()) / 4.0;\n  vec2 blockxy1 = mat2(1, -1.732, 1.732, 1) * blockxy * 0.5;\n  float z1 = (sin(blockxy1.x * 6.28318530718) *\n      sin(blockxy1.y * 6.28318530718) + 1.0) / 2.0;\n  gl_FragColor = vec4(vec3(smoothstep(0.45, 0.55, z1 + y)), 1);\n}\n"
  },
  {
    "path": "_archive/apps/samples/manga-cam/manifest.json",
    "content": "{\n  \"name\": \"Manga Cam\",\n  \"version\": \"0.4\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"28\",\n  \"description\": \"Take photos and turn them into manga-style.\",\n  \"offline_enabled\": true,\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"icons\": {\n    \"16\": \"images/camera-128.png\",\n    \"48\": \"images/camera-128.png\",\n    \"128\": \"images/camera-128.png\"\n  },\n  \"requirements\": {\n    \"3D\": {\n      \"features\": [\"webgl\"]\n    }\n  },\n  \"permissions\": [ \"videoCapture\", \"syncFileSystem\" ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/mdns-browser/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/kipighjpklofchgbdgclfaoccdlghidp\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# mDNS browser\n\nThis is a non-trivial sample which uses the UDP multicast support in Chrome Packaged Apps to browse mDNS servers. mDNS protocol is usually used for home appliance devices, like the Apple's Bonjour. Read more about the mDNS protocol at this [Wikipedia's article](http://en.wikipedia.org/wiki/Multicast_DNS)\n\n# Known Issues\n\n* IPv6 is not supported.\n* Broadcast responses are not supported.\n\n## APIs\n\n* [Sockets](https://developer.chrome.com/apps/sockets_udp)\n* [Network](https://developer.chrome.com/apps/system_network)\n* [Runtime](http://developer.chrome.com/apps/app_runtime)\n* [Window](http://developer.chrome.com/apps/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/mdns-browser/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/mdns-browser/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('main.html', {\n    id: 'mainWindow',\n    frame: 'none',\n    innerBounds: {\n      width: 440,\n      height: 440,\n      minWidth: 440,\n      minHeight: 200\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/mdns-browser/dns.js",
    "content": "\n/**\n * DataWriter writes data to an ArrayBuffer, presenting it as the instance\n * variable 'buffer'.\n *\n * @constructor\n */\nvar DataWriter = function(opt_size) {\n  var loc = 0;\n  var view = new Uint8Array(new ArrayBuffer(opt_size || 512));\n\n  this.byte_ = function(v) {\n    view[loc] = v;\n    ++loc;\n    this.buffer = view.buffer.slice(0, loc);\n  }.bind(this);\n};\n\nDataWriter.prototype.byte = function(v) {\n  this.byte_(v);\n  return this;\n};\n\nDataWriter.prototype.short = function(v) {\n  return this.byte((v >> 8) & 0xff).byte(v & 0xff);\n};\n\nDataWriter.prototype.long = function(v) {\n  return this.short((v >> 16) & 0xffff).short(v & 0xffff);\n};\n\n/**\n * Writes a DNS name. If opt_ref is specified, will finish this name with a\n * suffix reference (i.e., 0xc0 <ref>). If not, then will terminate with a NULL\n * byte.\n */\nDataWriter.prototype.name = function(v, opt_ref) {\n  var parts = v.split('.');\n  parts.forEach(function(part) {\n    this.byte(part.length);\n    for (var i = 0; i < part.length; ++i) {\n      this.byte(part.charCodeAt(i));\n    }\n  }.bind(this));\n  if (opt_ref) {\n    this.byte(0xc0).byte(opt_ref);\n  } else {\n    this.byte(0);\n  }\n  return this;\n};\n\n/**\n * DataConsumer consumes data from an ArrayBuffer.\n *\n * @constructor\n */\nvar DataConsumer = function(arg) {\n  if (arg instanceof Uint8Array) {\n    this.view_ = arg;\n  } else {\n    this.view_ = new Uint8Array(arg);\n  }\n  this.loc_ = 0;\n};\n\n/**\n * @return whether this DataConsumer has consumed all its data\n */\nDataConsumer.prototype.isEOF = function() {\n  return this.loc_ >= this.view_.byteLength;\n};\n\n/**\n * @param length {integer} number of bytes to return from the front of the view\n * @return a Uint8Array \n */\nDataConsumer.prototype.slice = function(length) {\n  var view = this.view_.subarray(this.loc_, this.loc_ + length);\n  this.loc_ += length;\n  return view;\n};\n\nDataConsumer.prototype.byte = function() {\n  this.loc_ += 1;\n  return this.view_[this.loc_ - 1];\n};\n\nDataConsumer.prototype.short = function() {\n  return (this.byte() << 8) + this.byte();\n};\n\nDataConsumer.prototype.long = function() {\n  return (this.short() << 16) + this.short();\n};\n\n/**\n * Consumes a DNS name, which will either finish with a NULL byte or a suffix\n * reference (i.e., 0xc0 <ref>).\n */\nDataConsumer.prototype.name = function() {\n  var parts = [];\n  for (;;) {\n    var len = this.byte();\n    if (!len) {\n      break;\n    } else if (len == 0xc0) {\n      // TODO: This indicates a pointer to another valid name inside the\n      // DNSPacket, and is always a suffix: we're at the end of the name.\n      // We should probably hold onto this value instead of discarding it.\n      var ref = this.byte();\n      break;\n    }\n\n    // Otherwise, consume a string!\n    var v = '';\n    while (len-- > 0) {\n      v += String.fromCharCode(this.byte());\n    }\n    parts.push(v);\n  }\n  return parts.join('.');\n};\n\n/**\n * DNSPacket holds the state of a DNS packet. It can be modified or serialized\n * in-place.\n *\n * @constructor\n */\nvar DNSPacket = function(opt_flags) {\n  this.flags_ = opt_flags || 0; /* uint16 */\n  this.data_ = {'qd': [], 'an': [], 'ns': [], 'ar': []};\n};\n\n/**\n * Parse a DNSPacket from an ArrayBuffer (or Uint8Array).\n */\nDNSPacket.parse = function(buffer) {\n  var consumer = new DataConsumer(buffer);\n  if (consumer.short()) {\n    throw new Error('DNS packet must start with 00 00');\n  }\n  var flags = consumer.short();\n  var count = {\n    'qd': consumer.short(),\n    'an': consumer.short(),\n    'ns': consumer.short(),\n    'ar': consumer.short(),\n  };\n  var packet = new DNSPacket(flags);\n\n  // Parse the QUESTION section.\n  for (var i = 0; i < count['qd']; ++i) {\n    var part = new DNSRecord(\n        consumer.name(),\n        consumer.short(),  // type\n        consumer.short()); // class\n    packet.push('qd', part);\n  }\n\n  // Parse the ANSWER, AUTHORITY and ADDITIONAL sections.\n  ['an', 'ns', 'ar'].forEach(function(section) {\n    for (var i = 0; i < count[section]; ++i) {\n      var part = new DNSRecord(\n          consumer.name(),\n          consumer.short(), // type\n          consumer.short(), // class\n          consumer.long(),  // ttl\n          consumer.slice(consumer.short()));\n      packet.push(section, part);\n    }\n  });\n\n  consumer.isEOF() || console.warn('was not EOF on incoming packet');\n  return packet;\n};\n\nDNSPacket.prototype.push = function(section, record) {\n  this.data_[section].push(record);\n};\n\nDNSPacket.prototype.each = function(section) {\n  var filter = false;\n  var call;\n  if (arguments.length == 2) {\n    call = arguments[1];\n  } else {\n    filter = arguments[1];\n    call = arguments[2];\n  }\n  this.data_[section].forEach(function(rec) {\n    if (!filter || rec.type == filter) {\n      call(rec);\n    }\n  });\n};\n\n/**\n * Serialize this DNSPacket into an ArrayBuffer for sending over UDP.\n */\nDNSPacket.prototype.serialize = function() {\n  var out = new DataWriter();\n  var s = ['qd', 'an', 'ns', 'ar'];\n\n  out.short(0).short(this.flags_);\n\n  s.forEach(function(section) {\n    out.short(this.data_[section].length);\n  }.bind(this));\n\n  s.forEach(function(section) {\n    this.data_[section].forEach(function(rec) {\n      out.name(rec.name).short(rec.type).short(rec.cl);\n\n      if (section != 'qd') {\n        // TODO: implement .bytes()\n        throw new Error('can\\'t yet serialize non-QD records');\n//        out.long(rec.ttl).bytes(rec.data_);\n      }\n    });\n  }.bind(this));\n\n  return out.buffer;\n};\n\n/**\n * DNSRecord is a record inside a DNS packet; e.g. a QUESTION, or an ANSWER,\n * AUTHORITY, or ADDITIONAL record. Note that QUESTION records are special,\n * and do not have ttl or data.\n */\nvar DNSRecord = function(name, type, cl, opt_ttl, opt_data) {\n  this.name = name;\n  this.type = type;\n  this.cl = cl;\n\n  this.isQD = (arguments.length == 3);\n  if (!this.isQD) {\n    this.ttl = opt_ttl;\n    this.data_ = opt_data;\n  }\n};\n\nDNSRecord.prototype.asName = function() {\n  return new DataConsumer(this.data_).name();\n};\n"
  },
  {
    "path": "_archive/apps/samples/mdns-browser/header.css",
    "content": "\nheader {\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0px;\n  height: 42px;\n  border-bottom: 2px solid rgba(0, 0, 255, 0.2);\n  box-shadow: 0 0.125em 0.5em rgba(0, 0, 0, 0.1);\n  padding: 0 0.25em;\n  margin: 0;\n  z-index: 100;\n  font-family: Arial, Helvetica, Sans-Serif;\n  border-radius: 2px;\n  -webkit-app-region: drag;\n}\n\nheader li,\nheader button,\nheader input[type=\"text\"] {\n  top: 7px;\n  line-height: 20pt;\n  display: inline-block;\n  font-size: 8.5pt;\n  font-weight: bold;\n  margin: 0;\n  padding: 0;\n  min-width: 5.5em;\n  position: relative;\n  height: 28px;\n  box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  margin: 0 2.5pt;\n  border: 1px solid transparent;\n  text-align: center;\n}\n\nheader button,\nheader input[type=\"text\"] {\n  -webkit-app-region: no-drag;\n}\n\nheader .small {\n  min-width: 3em;\n}\n\nheader li {\n  border-radius: 2px;\n  background: #e2e2e2;\n  color: #222;\n  min-width: 10.5em;\n}\n\nheader button {\n  border-radius: 2px;\n  border-color: rgba(0, 0, 0, 0.0976563);\n  background: transparent -webkit-linear-gradient(top, whiteSmoke, #f1f1f1);\n  color: #444;\n  cursor: pointer;\n  min-width: 7em;\n  float: right;\n}\n\nheader button abbr {\n  color: black;\n}\n\nheader button.primary {\n  background: #d14836 -webkit-linear-gradient(top, #dd4b39, #d14836);\n  color: white;\n  text-shadow: rgba(0, 0, 0, 0.0976563) 0px 1px 0px;\n}\n\nheader button.feature {\n  background: #4d90fe -webkit-linear-gradient(top, #4d90fe, #4787ed);\n  color: white;\n  border-color: #3079ed;\n}\n\nheader button:focus {\n  border-color: #4d90fe;\n  outline: none;\n}\n\nheader button.primary:focus {\n  border-color: transparent;\n  box-shadow: rgba(255, 255, 255, 1) 0px 0px 0px 1px inset;\n}\n\nheader button.feature:focus {\n  border-color: transparent;\n  box-shadow: rgba(255, 255, 255, 1) 0px 0px 0px 1px inset;\n}\n\nheader button:hover,\nheader button:active,\nheader button.active {\n  background: transparent -webkit-linear-gradient(top, #f8f8f8, #f1f1f1);\n  border-color: #c6c6c6;\n  box-shadow: rgba(0, 0, 0, 0.0976563) 0px 1px 1px 0px;\n  color: #333;\n}\n\nheader button.primary:hover,\nheader button.primary:active,\nheader button.primary.active {\n  background: #c53727 -webkit-linear-gradient(top, #dd4b39, #c53727);\n  border-color: #b0281a;\n  box-shadow: rgba(0, 0, 0, 0.199219) 0px;\n  color: white;\n}\n\nheader button.feature:hover,\nheader button.feature:active,\nheader button.feature.active {\n  background: #357ae8 -webkit-linear-gradient(top, #4d90fe, #357ae8);\n  border-color: #2f5bb7;\n  box-shadow: rgba(0, 0, 0, 0.0976563) 0px 1px 1px 0px;\n  color: white;\n}\n\nheader button:active,\nheader button.active {\n  padding-top: 1px;\n  margin-top: -1px;\n  top: 8px;\n  height: 28px;\n  background: transparent -webkit-linear-gradient(top, #eee, #e0e0e0);\n  border-color: #ccc;\n  box-shadow: rgba(0, 0, 0, 0.0976563) 0px 1px 1px 0px inset;\n}\n\nheader button.primary:active,\nheader button.primary.active {\n  background: #b0281a -webkit-linear-gradient(top, #dd4b39, #b0281a);\n  box-shadow: rgba(0, 0, 0, 0.296875) 0px 1px 2px 0px inset;\n}\n\nheader button.feature:active,\nheader button.feature.active {\n  background: #b0281a -webkit-linear-gradient(top, #4d90fe, #2f5bb7);\n  box-shadow: rgba(0, 0, 0, 0.296875) 0px 1px 2px 0px inset;\n}\n"
  },
  {
    "path": "_archive/apps/samples/mdns-browser/main.css",
    "content": "body {\n  margin: 0;\n  padding: 0;\n  background: rgba(102, 102, 119, 0.85);\n  background: white;\n  width: 100%;\n  -webkit-app-region: drag;\n}\n\ndiv#main {\n  position: absolute;\n  top: 44px;\n  bottom: 0;\n  width: 100%;\n  overflow-y: scroll;\n  color: white;\n  color: black;\n  -webkit-app-region: no-drag;\n}\n\nul#results {\n  list-style: none;\n  font-family: Arial, Helvetica, Sans-Serif;\n  font-size: 12px;\n  line-height: 21px;\n  padding: 0em 0.5em;\n  padding-right: 2em;\n  margin: 0;\n}\n\nul.working#results {\n  background: url(img/working.gif) no-repeat center;\n  min-height: 80px;\n}\n\nul strong.warning {\n  color: #D14836;\n  text-align: center;\n  display: block;\n  padding: 0.5em;\n}\n\nul#results > ul {\n  list-style: square;\n}\n\nul#results > li {\n  font-weight: bold;\n  margin-left: 1em;\n  margin-top: 0.5em;\n}\n\nul.loading {\n  background: red;\n}\n\nul#results li em {\n  font-style: normal;\n  font-weight: normal;\n  opacity: 0.33;\n}\n\nul#results li em::before {\n  content: \"\\2014 \\a0\";\n  padding: 0 4px;\n}\n"
  },
  {
    "path": "_archive/apps/samples/mdns-browser/main.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <script src=\"dns.js\"></script>\n    <script src=\"service-types.js\"></script>\n    <script src=\"main.js\"></script>\n    <link href=\"header.css\" rel=\"stylesheet\" type=\"text/css\" />\n    <link href=\"main.css\" rel=\"stylesheet\" type=\"text/css\" />\n  </head>\n  <body>\n\n<header>\n  <button class=\"primary\" id=\"btn-close\" accessKey=\"l\">\n    C<u>l</u>ose</button>\n  </button>\n  <button class=\"feature\" id=\"btn-refresh\" accessKey=\"e\">\n    R<u>e</u>fresh\n  </button>\n  <button id=\"btn-mode\" accessKey=\"b\">\n    <u>B</u>y <span id=\"mode-span\">Mode</span>\n  </button>\n  <li>MDNS Browser</li>\n</header>\n<div id=\"main\">\n  <ul id=\"results\"></ul>\n</div>\n\n  </body>\n</html>\n\n"
  },
  {
    "path": "_archive/apps/samples/mdns-browser/main.js",
    "content": "\n/**\n * Construct a new ServiceFinder. This is a single-use object that does a DNS\n * multicast search on creation.\n * @constructor\n * @param {function} callback The callback to be invoked when this object is\n *                            updated, or when an error occurs (passes string).\n */\nvar ServiceFinder = function(callback) {\n  this.callback_ = callback;\n  this.byIP_ = {};\n  this.byService_ = {};\n\n  // Set up receive handlers.\n  this.onReceiveListener_ = this.onReceive_.bind(this);\n  chrome.sockets.udp.onReceive.addListener(this.onReceiveListener_);\n  this.onReceiveErrorListener_ = this.onReceiveError_.bind(this);\n  chrome.sockets.udp.onReceiveError.addListener(this.onReceiveErrorListener_);\n\n  ServiceFinder.forEachAddress_(function(address, error) {\n    if (error) {\n      this.callback_(error);\n      return true;\n    }\n    if (address.indexOf(':') != -1) {\n      // TODO: ipv6.\n      console.log('IPv6 address unsupported', address);\n      return true;\n    }\n    console.log('Broadcasting to address', address);\n\n    ServiceFinder.bindToAddress_(address, function(socket) {\n      if (!socket) {\n        this.callback_('could not bind UDP socket');\n        return true;\n      }\n      // Broadcast on it.\n      this.broadcast_(socket, address);\n    }.bind(this));\n  }.bind(this));\n\n  // After a short time, if our database is empty, report an error.\n  setTimeout(function() {\n    if (!Object.keys(this.byIP_).length) {\n      this.callback_('no mDNS services found!');\n    }\n  }.bind(this), 10 * 1000);\n};\n\n/**\n * Invokes the callback for every local network address on the system.\n * @private\n * @param {function} callback to invoke\n */\nServiceFinder.forEachAddress_ = function(callback) {\n  chrome.system.network.getNetworkInterfaces(function(networkInterfaces) {\n    if (!networkInterfaces.length) {\n      callback(null, 'no network available!');\n      return true;\n    }\n    networkInterfaces.forEach(function(networkInterface) {\n      callback(networkInterface['address'], null);\n    });\n  });\n};\n\n/**\n * Creates UDP socket bound to the specified address, passing it to the\n * callback. Passes null on failure.\n * @private\n * @param {string} address to bind to\n * @param {function} callback to invoke when done\n */\nServiceFinder.bindToAddress_ = function(address, callback) {\n  chrome.sockets.udp.create({}, function(createInfo) {\n    chrome.sockets.udp.bind(createInfo['socketId'], address, 0,\n        function(result) {\n      callback((result >= 0) ? createInfo['socketId'] : null);\n    });\n  });\n};\n\n/**\n * Sorts the passed list of string IPs in-place.\n * @private\n */\nServiceFinder.sortIps_ = function(arg) {\n  arg.sort(ServiceFinder.sortIps_.sort);\n  return arg;\n};\nServiceFinder.sortIps_.sort = function(l, r) {\n  // TODO: support v6.\n  var lp = l.split('.').map(ServiceFinder.sortIps_.toInt_);\n  var rp = r.split('.').map(ServiceFinder.sortIps_.toInt_);\n  for (var i = 0; i < Math.min(lp.length, rp.length); ++i) {\n    if (lp[i] < rp[i]) {\n      return -1;\n    } else if (lp[i] > rp[i]) {\n      return +1;\n    }\n  }\n  return 0;\n};\nServiceFinder.sortIps_.toInt_ = function(i) { return +i };\n\n/**\n * Returns the services found by this ServiceFinder, optionally filtered by IP.\n */\nServiceFinder.prototype.services = function(opt_ip) {\n  var k = Object.keys(opt_ip ? this.byIP_[opt_ip] : this.byService_);\n  k.sort();\n  return k;\n};\n\n/**\n * Returns the IPs found by this ServiceFinder, optionally filtered by service.\n */\nServiceFinder.prototype.ips = function(opt_service) {\n  var k = Object.keys(opt_service ? this.byService_[opt_service] : this.byIP_);\n  return ServiceFinder.sortIps_(k);\n};\n\n/**\n * Handles an incoming UDP packet.\n * @private\n */\nServiceFinder.prototype.onReceive_ = function(info) {\n  var getDefault_ = function(o, k, def) {\n    (k in o) || false == (o[k] = def);\n    return o[k];\n  };\n\n  // Update our local database.\n  // TODO: Resolve IPs using the dns extension.\n  var packet = DNSPacket.parse(info.data);\n  var byIP = getDefault_(this.byIP_, info.remoteAddress, {});\n\n  packet.each('an', 12, function(rec) {\n    var ptr = rec.asName();\n    var byService = getDefault_(this.byService_, ptr, {})\n    byService[info.remoteAddress] = true;\n    byIP[ptr] = true;\n  }.bind(this));\n\n  // Ping! Something new is here. Only update every 25ms.\n  if (!this.callback_pending_) {\n    this.callback_pending_ = true;\n    setTimeout(function() {\n      this.callback_pending_ = undefined;\n      this.callback_();\n    }.bind(this), 25);\n  }\n};\n\n/**\n * Handles network error occured while waiting for data.\n * @private\n */\nServiceFinder.prototype.onReceiveError_ = function(info) {\n  this.callback_(info.resultCode);\n  return true;\n}\n\n/**\n * Broadcasts for services on the given socket/address.\n * @private\n */\nServiceFinder.prototype.broadcast_ = function(sock, address) {\n  var packet = new DNSPacket();\n  packet.push('qd', new DNSRecord('_services._dns-sd._udp.local', 12, 1));\n\n  var raw = packet.serialize();\n  chrome.sockets.udp.send(sock, raw, '224.0.0.251', 5353, function(sendInfo) {\n    if (sendInfo.resultCode < 0)\n      this.callback_('Could not send data to:' + address);\n  });\n};\n\nServiceFinder.prototype.shutdown = function() {\n  // Remove event listeners.\n  chrome.sockets.udp.onReceive.removeListener(this.onReceiveListener_);\n  chrome.sockets.udp.onReceiveError.removeListener(this.onReceiveErrorListener_);\n  // Close opened sockets.\n  chrome.sockets.udp.getSockets(function(sockets) {\n    sockets.forEach(function(sock) {\n      chrome.sockets.udp.close(sock.socketId);\n    });\n  });\n}\n\nwindow.addEventListener('load', function() {\n  var results = document.getElementById('results');\n\n  var getHtml_ = function(category, key) {\n    if (category == finder.services && key in serviceTypes) {\n      return key + ' <em>' + serviceTypes[key] + '</em>';\n    }\n    return key;\n  };\n\n  var finder;\n  var mode = 'service';\n  var callback_ = function(opt_error) {\n    results.innerHTML = '';\n    results.classList.remove('working');\n\n    if (opt_error) {\n      var s = document.createElement('strong');\n      s.classList.add('warning');\n      s.innerText = opt_error;\n      results.appendChild(s);\n      return console.warn(opt_error);\n    }\n\n    var outer = finder.services;\n    var inner = finder.ips;\n    if (mode == 'ip') {\n      outer = finder.ips;\n      inner = finder.services;\n    }\n    // TODO: render information about outer/inner\n    // for IPs, render 'last seen at...'\n    // for services, render known service type.\n\n    results.innerHTML = '';\n    outer.apply(finder).forEach(function(o) {\n      var li = document.createElement('li');\n      li.innerHTML = getHtml_(outer, o);\n      results.appendChild(li);\n\n      var ul = document.createElement('ul');\n      inner.call(finder, o).forEach(function(i) {\n        var li = document.createElement('li');\n        li.innerHTML = getHtml_(inner, i);\n        ul.appendChild(li);\n      });\n      ul.childNodes.length && results.appendChild(ul);\n    });\n  };\n\n  // Configure the refresh button, then immediately invoke it.\n  var refreshBtn = document.getElementById('btn-refresh');\n  refreshBtn.addEventListener('click', function() {\n    results.innerHTML = '';\n    results.classList.add('working');\n\n    finder && finder.shutdown();\n    finder = new ServiceFinder(callback_);\n  });\n  refreshBtn.click();\n\n  // Configure the mode button, then immediately invoke it twice to reset to\n  // the default state (show by service).\n  var modeBtn = document.getElementById('btn-mode');\n  modeBtn.addEventListener('click', function() {\n    var h = document.getElementById('mode-span');\n    if (mode == 'service') {\n      mode = 'ip';\n      h.innerText = 'IP';\n    } else {\n      mode = 'service';\n      h.innerText = 'Service';\n    }\n    if (finder) {\n      callback_();\n    }\n  });\n  modeBtn.click(); modeBtn.click();\n\n  // Configure the close button.\n  document.getElementById('btn-close').addEventListener('click', function() {\n    window.close();\n  });\n});\n\n"
  },
  {
    "path": "_archive/apps/samples/mdns-browser/manifest.json",
    "content": "{\n  \"name\": \"mDNS Browser\",\n  \"description\": \"Browses mDNS services on the local network\",\n  \"manifest_version\": 2,\n  \"version\": \"0.7\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"sockets\": {\n     \"udp\": { \"bind\": \"*\", \"send\": \"*\" }\n  },\n  \"permissions\": [ \"system.network\" ],\n  \"icons\": { \"128\": \"img/icon-128.png\", \"16\": \"img/icon-16.png\" }\n}\n"
  },
  {
    "path": "_archive/apps/samples/mdns-browser/service-types.js",
    "content": "// This list is based on /usr/share/avahi/service-types.\n\nvar serviceTypes = {\n  '_acrobatSRV._tcp': 'Adobe Acrobat',\n  '_adisk._tcp': 'Apple TimeMachine',\n  '_adobe-vc._tcp': 'Adobe Version Cue',\n  '_afpovertcp._tcp': 'Apple File Sharing',\n  '_airport._tcp': 'Apple AirPort',\n  '_apt._tcp': 'APT Package Repository',\n  '_bzr._tcp': 'Bazaar',\n  '_cros_p2p._tcp': 'Chrome OS P2P Update',\n  '_daap._tcp': 'iTunes Audio Access',\n  '_dacp._tcp': 'iTunes Remote Control',\n  '_distcc._tcp': 'Distributed Compiler',\n  '_domain._udp': 'DNS Server',\n  '_dpap._tcp': 'Digital Photo Sharing',\n  '_ftp._tcp': 'FTP File Transfer',\n  '_h323._tcp': 'H.323 Telephony',\n  '_home-sharing._tcp': 'Apple Home Sharing',\n  '_https._tcp': 'Secure Web Site',\n  '_http._tcp': 'Web Site',\n  '_iax._udp': 'Asterisk Exchange',\n  '_imap._tcp': 'IMAP Mail Access',\n  '_ipp._tcp': 'Internet Printer',\n  '_ksysguard._tcp': 'KDE System Guard',\n  '_ldap._tcp': 'LDAP Directory Server',\n  '_libvirt._tcp': 'Virtual Machine Manager',\n  '_lobby._tcp': 'Gobby Collaborative Editor Session',\n  '_MacOSXDupSuppress._tcp': 'MacOS X Duplicate Machine Suppression',\n  '_mpd._tcp': 'Music Player Daemon',\n  '_mumble._tcp': 'Mumble Server',\n  '_net-assistant._udp': 'Apple Net Assistant',\n  '_nfs._tcp': 'Network File System',\n  '_ntp._udp': 'NTP Time Server',\n  '_odisk._tcp': 'DVD or CD Sharing',\n  '_omni-bookmark._tcp': 'OmniWeb Bookmark Sharing',\n  '_pdl-datastream._tcp': 'PDL Printer',\n  '_pgpkey-hkp._tcp': 'GnuPG/PGP HKP Key Server',\n  '_pop3._tcp': 'POP3 Mail Access',\n  '_pop3._tcp': 'Posta - POP3',\n  '_postgresql._tcp': 'PostgreSQL Server',\n  '_presence_olpc._tcp': 'OLPC Presence',\n  '_presence._tcp': 'iChat Presence',\n  '_printer._tcp': 'UNIX Printer',\n  '_pulse-server._tcp': 'PulseAudio Sound Server',\n  '_pulse-sink._tcp': 'PulseAudio Sound Sink',\n  '_pulse-source._tcp': 'PulseAudio Sound Source',\n  '_raop._tcp': 'AirTunes Remote Audio',\n  '_realplayfavs._tcp': 'RealPlayer Shared Favorites',\n  '_remote-jukebox._tcp': 'Remote Jukebox',\n  '_rfb._tcp': 'VNC Remote Access',\n  '_rss._tcp': 'Web Syndication RSS',\n  '_rtp._udp': 'RTP Realtime Streaming Server',\n  '_rtsp._tcp': 'RTSP Realtime Streaming Server',\n  '_see._tcp': 'SubEthaEdit Collaborative Text Editor',\n  '_sftp-ssh._tcp': 'SFTP File Transfer',\n  '_shifter._tcp': 'Window Shifter',\n  '_sip._udp': 'SIP Telephony',\n  '_skype._tcp': 'Skype VoIP',\n  '_smb._tcp': 'Microsoft Windows Network',\n  '_ssh._tcp': 'SSH Remote Terminal',\n  '_svn._tcp': 'Subversion Revision Control',\n  '_telnet._tcp': 'Telnet Remote Terminal',\n  '_tftp._udp': 'TFTP Trivial File Transfer',\n  '_timbuktu._tcp': 'Timbuktu Remote Desktop Control',\n  '_touch-able._tcp': 'iPod Touch Music Library',\n  '_tp-https._tcp': 'Thousand Parsec Server (Secure HTTP Tunnel)',\n  '_tp-http._tcp': 'Thousand Parsec Server (HTTP Tunnel)',\n  '_tps._tcp': 'Thousand Parsec Server (Secure)',\n  '_tp._tcp': 'Thousand Parsec Server',\n  '_udisks-ssh._tcp': 'Remote Disk Management',\n  '_vlc-http._tcp': 'VLC Streaming',\n  '_webdavs._tcp': 'Secure WebDAV File Share',\n  '_webdav._tcp': 'WebDAV File Share',\n  '_workstation._tcp': 'Workstation',\n};\n"
  },
  {
    "path": "_archive/apps/samples/media-gallery/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/lidepfgfmameopopgagobnpndcnfgbnk\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Media Gallery\n\nThis is a sample application that uses the [media gallery](http://developer.chrome.com/apps/mediaGalleries) API to read and show user's media without requiring direct filesystem permission.\n\n## APIs\n\n* [Media gallery](http://developer.chrome.com/apps/mediaGalleries)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/media-gallery/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/media-gallery/manifest.json",
    "content": "{\n  \"name\": \"Media Gallery Sample\",\n  \"version\": \"0.2.5\",\n  \"manifest_version\": 2,\n  \"description\": \"Used to test Media Gallery API\",\n  \"permissions\": [{\n      \"mediaGalleries\": [\"read\", \"scan\", \"allAutoDetected\"]\n  }],\n  \"icons\": {\n    \"128\": \"mga-128color.png\"\n  },\n  \"app\": {\n     \"background\": {\n       \"scripts\": [\"runtime.js\"]\n     }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/media-gallery/media-gallery.js",
    "content": "var gGalleryIndex = 0;     // gallery currently being iterated\nvar gGalleryReader = null; // the filesytem reader for the current gallery\nvar gDirectories = [];     // used to process subdirectories\nvar gGalleryArray = [];    // holds information about all top-level Galleries found - list of DomFileSystem\nvar gGalleryData = [];     // hold computed information about each Gallery\nvar gCurOptGrp = null;\nvar imgFormats = ['png', 'bmp', 'jpeg', 'jpg', 'gif', 'png', 'svg', 'xbm', 'webp'];\nvar audFormats = ['wav', 'mp3'];\nvar vidFormats = ['3gp', '3gpp', 'avi', 'flv', 'mov', 'mpeg', 'mpeg4', 'mp4', 'ogg', 'webm', 'wmv'];\n\nfunction errorPrintFactory(custom) {\n   return function(e) {\n      var msg = '';\n\n      switch (e.code) {\n         case FileError.QUOTA_EXCEEDED_ERR:\n            msg = 'QUOTA_EXCEEDED_ERR';\n            break;\n         case FileError.NOT_FOUND_ERR:\n            msg = 'NOT_FOUND_ERR';\n            break;\n         case FileError.SECURITY_ERR:\n            msg = 'SECURITY_ERR';\n            break;\n         case FileError.INVALID_MODIFICATION_ERR:\n            msg = 'INVALID_MODIFICATION_ERR';\n            break;\n         case FileError.INVALID_STATE_ERR:\n            msg = 'INVALID_STATE_ERR';\n            break;\n         default:\n            msg = 'Unknown Error';\n            break;\n      };\n\n      console.log(custom + ': ' + msg);\n   };\n}\n\nfunction GalleryData(id) {\n   this._id = id;\n   this.path = \"\";\n   this.sizeBytes = 0;\n   this.numFiles = 0;\n   this.numDirs = 0;\n}\n\nfunction addImageToContentDiv() {\n   var content_div = document.getElementById('content');\n   var image = document.createElement('img');\n   content_div.appendChild(image);\n   return image;\n}\n\nfunction addAudioToContentDiv() {\n   var content_div = document.getElementById('content');\n   var audio = document.createElement('audio');\n   audio.setAttribute(\"controls\",\"controls\");\n   content_div.appendChild(audio);\n   return audio;\n}\n\nfunction addVideoToContentDiv() {\n   var content_div = document.getElementById('content');\n   var audio = document.createElement('video');\n   audio.setAttribute(\"controls\",\"controls\");\n   content_div.appendChild(audio);\n   return audio;\n}\n\nfunction getFileType(filename) {\n   var ext = filename.substr(filename.lastIndexOf('.') + 1).toLowerCase();\n   if (imgFormats.indexOf(ext) >= 0)\n      return \"image\";\n   else if (audFormats.indexOf(ext) >= 0)\n      return \"audio\";\n   else if (vidFormats.indexOf(ext) >= 0)\n      return \"video\";\n   else return null;\n}\n\nfunction clearContentDiv() {\n   var content_div = document.getElementById('content');\n   while (content_div.childNodes.length >= 1) {\n      content_div.removeChild(content_div.firstChild);\n   }\n}\nfunction clearList() {\n   document.getElementById(\"GalleryList\").innerHTML = \"\";\n}\n\nfunction updateSelection(e) {\n   var selList = document.getElementById(\"GalleryList\");\n   var indx = selList.selectedIndex;\n   var fsId = selList.options[indx].getAttribute(\"data-fsid\");\n   var fs = null;\n\n   // get the filesystem that the selected file belongs to\n   for (var i=0; i < gGalleryArray.length; i++) {\n      var mData = chrome.mediaGalleries.getMediaFileSystemMetadata(gGalleryArray[i]);\n      if (mData.galleryId == fsId) {\n         fs = gGalleryArray[i];\n         break;\n      }\n   }\n   if (fs) {\n      var path = selList.options[indx].getAttribute(\"data-fullpath\");\n      fs.root.getFile(path, {create: false}, function(fileEntry) {\n         var newElem = null;\n         // show the file data\n         clearContentDiv();\n         var type = getFileType(path);\n         if (type == \"image\")\n            newElem = addImageToContentDiv();\n         else if (type == \"audio\")\n            newElem = addAudioToContentDiv();\n         else if (type == \"video\")\n            newElem = addVideoToContentDiv();\n\n         if (newElem) {\n            // Supported in Chrome M37 and later.\n            if (!chrome.mediaGalleries.getMetadata) {\n              newElem.setAttribute('src', fileEntry.toURL());\n            } else {\n              fileEntry.file(function(file) {\n                 chrome.mediaGalleries.getMetadata(file, {}, function(metadata) {\n                    if (metadata.attachedImages.length) {\n                       var blob = metadata.attachedImages[0];\n                       var posterBlobURL = URL.createObjectURL(blob);\n                       newElem.setAttribute('poster', posterBlobURL);\n                    }\n                    newElem.setAttribute('src', fileEntry.toURL());\n                 });\n              });\n            }\n         }\n      });\n   }\n}\n\nfunction addGallery(name, id) {\n   var optGrp = document.createElement(\"optgroup\");\n   optGrp.setAttribute(\"label\",name);\n   optGrp.setAttribute(\"id\", id);\n   document.getElementById(\"GalleryList\").appendChild(optGrp);\n   return optGrp;\n}\n\nfunction addItem(itemEntry) {\n   var opt = document.createElement(\"option\");\n   if (itemEntry.isFile) {\n      opt.setAttribute(\"data-fullpath\", itemEntry.fullPath);\n\n      var mData = chrome.mediaGalleries.getMediaFileSystemMetadata(itemEntry.filesystem);\n      opt.setAttribute(\"data-fsid\", mData.galleryId);\n   }\n   opt.appendChild(document.createTextNode(itemEntry.name));\n   gCurOptGrp.appendChild(opt);\n}\n\nfunction scanGallery(entries) {\n   // when the size of the entries array is 0, we've processed all the directory contents\n   if (entries.length == 0) {\n      if (gDirectories.length > 0) {\n         var dir_entry = gDirectories.shift();\n         console.log('Doing subdir: ' + dir_entry.fullPath);\n         gGalleryReader = dir_entry.createReader();\n         gGalleryReader.readEntries(scanGallery, errorPrintFactory('readEntries'));\n      }\n      else {\n         gGalleryIndex++;\n         if (gGalleryIndex < gGalleryArray.length) {\n            console.log('Doing next Gallery: ' + gGalleryArray[gGalleryIndex].name);\n            scanGalleries(gGalleryArray[gGalleryIndex]);\n         }\n      }\n      return;\n   }\n   for (var i = 0; i < entries.length; i++) {\n      console.log(entries[i].name);\n\n      if (entries[i].isFile) {\n         addItem(entries[i]);\n         gGalleryData[gGalleryIndex].numFiles++;\n         (function(galData) {\n            entries[i].getMetadata(function(metadata){\n               galData.sizeBytes += metadata.size;\n            });\n         }(gGalleryData[gGalleryIndex]));\n      }\n      else if (entries[i].isDirectory) {\n         gDirectories.push(entries[i]);\n      }\n      else {\n         console.log(\"Got something other than a file or directory.\");\n      }\n   }\n   // readEntries has to be called until it returns an empty array. According to the spec,\n   // the function might not return all of the directory's contents during a given call.\n   gGalleryReader.readEntries(scanGallery, errorPrintFactory('readMoreEntries'));\n}\n\nfunction scanGalleries(fs) {\n   var mData = chrome.mediaGalleries.getMediaFileSystemMetadata(fs);\n\n   console.log('Reading gallery: ' + mData.name);\n   gCurOptGrp = addGallery(mData.name, mData.galleryId);\n   gGalleryData[gGalleryIndex] = new GalleryData(mData.galleryId);\n   gGalleryReader = fs.root.createReader();\n   gGalleryReader.readEntries(scanGallery, errorPrintFactory('readEntries'));\n\n   chrome.mediaGalleries.addGalleryWatch(mData.galleryId, onGalleryWatchAdded);\n}\n\nfunction getGalleriesInfo(results) {\n   clearContentDiv();\n   if (results.length) {\n      var str = 'Gallery count: ' + results.length + ' ( ';\n      results.forEach(function(item, indx, arr) {\n         var mData = chrome.mediaGalleries.getMediaFileSystemMetadata(item);\n\n         if (mData) {\n            str += mData.name;\n            if (indx < arr.length-1)\n               str += \",\";\n            str += \" \";\n         }\n      });\n      str += ')';\n      document.getElementById(\"status\").innerText = str;\n      gGalleryArray = results; // store the list of gallery directories\n      gGalleryIndex = 0;\n\n      document.getElementById(\"read-button\").disabled = \"\";\n   }\n   else {\n      document.getElementById(\"status\").innerText = 'No galleries found';\n      document.getElementById(\"read-button\").disabled = \"disabled\";\n      clearList();\n   }\n}\n\nfunction onGalleryChanged(result) {\n  if (result.type === 'contents_changed') {\n    // read galleries again if change was detected.\n    document.getElementById('read-button').click();\n  }\n}\n\nfunction onGalleryWatchAdded() {\n  if (chrome.runtime.lastError) {\n    console.log(\"Gallery watch not added\", chrome.runtime.lastError.message);\n  }\n}\n\nwindow.addEventListener(\"load\", function() {\n   // __MGA__bRestart is set in the launcher code to indicate that the app was\n   // restarted instead of being normally launched\n   if (window.__MGA__bRestart) {\n      console.log(\"App was restarted\");\n      // if the app was restarted, get the media gallery information\n      chrome.mediaGalleries.getMediaFileSystems({\n         interactive : 'if_needed'\n      }, getGalleriesInfo);\n   }\n\n   document.getElementById('gallery-button').addEventListener(\"click\", function() {\n      chrome.mediaGalleries.getMediaFileSystems({\n         interactive : 'if_needed'\n      }, getGalleriesInfo);\n   });\n   document.getElementById('configure-button').addEventListener(\"click\", function() {\n      chrome.mediaGalleries.getMediaFileSystems({\n         interactive : 'yes'\n      }, getGalleriesInfo);\n   });\n   document.getElementById('add-folder-button').addEventListener(\"click\", function() {\n      chrome.mediaGalleries.addUserSelectedFolder(getGalleriesInfo);\n   });\n   document.getElementById('read-button').addEventListener(\"click\", function () {\n      clearContentDiv();\n      clearList();\n      gGalleryIndex = 0;\n      if (gGalleryArray.length > 0) {\n         scanGalleries(gGalleryArray[0]);\n      }\n   });\n   document.getElementById('GalleryList').addEventListener(\"change\", function(e) {\n      updateSelection(e);\n   });\n   var scan_button = document.getElementById('scan-button');\n   scan_button.addEventListener(\"click\", function () {\n     if (scan_button.innerHTML == 'Cancel Scan') {\n       chrome.mediaGalleries.cancelMediaScan();\n     } else {\n       scan_button.innerHTML = 'Cancel Scan';\n       chrome.mediaGalleries.startMediaScan();\n     }\n   });\n   document.getElementById('add-scan-results-button').addEventListener(\"click\", function () {\n     chrome.mediaGalleries.addScanResults(getGalleriesInfo);\n   });\n});\n\nchrome.mediaGalleries.onScanProgress.addListener(function(details) {\n  if (details.type == 'finish') {\n    document.getElementById('status').innerText =\n        'Scan found ' + details.galleryCount + ' galleries';\n  } else {\n    document.getElementById('status').innerText = 'Scanning: ' + details.type;\n  }\n  if (details.type != 'start')\n   document.getElementById('scan-button').innerHTML = 'Search for Galleries';\n});\n\nchrome.mediaGalleries.onGalleryChanged.addListener(onGalleryChanged);\n"
  },
  {
    "path": "_archive/apps/samples/media-gallery/page.html",
    "content": "<!-- Copyright (c) 2010 The Chromium Authors. All rights reserved.\nUse of this source code is governed by a BSD-style license that can be\nfound in the LICENSE file. -->\n<html>\n    <head>\n        <title>Media Gallery API Sample</title>\n        <link rel=\"stylesheet\" href=\"styles.css\">\n        <script src=\"media-gallery.js\"></script>\n    </head>\n    <body>\n        <h1>Media Gallery Explorer</h1>\n        <button id=\"gallery-button\">Get Galleries Info</button>\n        <button id=\"configure-button\">Select Galleries...</button>\n        <button id=\"add-folder-button\">Add a Gallery...</button>\n        <button id=\"read-button\" disabled=\"false\">Read Galleries</button>\n        <button id=\"scan-button\">Search for Galleries</button>\n        <button id=\"add-scan-results-button\">Add Scan Results</button>\n        <p id=\"info\">\n            <span id=\"status\">&nbsp;</span>\n        </p>\n        <div id=\"container\">\n            <div id=\"list\">\n            <select id=\"GalleryList\" size=\"10\" style=\"width:100%; height:100%\">\n            </select>\n            </div>\n            <div id=\"content\"></div>\n        </div>\n    </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/media-gallery/runtime.js",
    "content": "// Use the runtime event listeners to set a window property indicating whether the\n// app was launched normally or as a result of being restarted\n\nchrome.app.runtime.onLaunched.addListener(function(data) {\n    chrome.app.window.create('page.html', \n    \t{innerBounds: {width:900, height:600, minWidth:900, maxWidth: 900, minHeight:600, maxHeight: 600}, id:\"MGExp\"}, \n    \tfunction(app_win) {\n    \t\tapp_win.contentWindow.__MGA__bRestart = false;\n    \t}\n    );\n    console.log(\"app launched\");\n});\n\nchrome.app.runtime.onRestarted.addListener(function() {\n    chrome.app.window.create('page.html', \n    \t{innerBounds: {width:900, height:600, minWidth:900, maxWidth: 900, minHeight:600, maxHeight: 600}, id:\"MGExp\"}, \n    \tfunction(app_win) {\n    \t\tapp_win.contentWindow.__MGA__bRestart = true;\n    \t}\n    );\n    console.log(\"app restarted\");\n});\n"
  },
  {
    "path": "_archive/apps/samples/media-gallery/styles.css",
    "content": "body {\n   background: #555;\n   color: #eee;\n   font-family: \"Open Sans\", Arial, sans-serif;\n}\n\nh1 {\n\tfont-weight: 200;\n\tcolor: white;\n}\n\n#content {\n\theight: 75%;\n\twidth: 74%;\n\toverflow-y: scroll;\n\tborder: 1px solid #aaa;\n\tborder-radius: 5px;\n\tdisplay: inline-block;\n\tbackground-color: #777;\n}\n\n#list {\n\theight: 75%;\n\twidth: 25%;\n\tborder: 1px solid #aaa;\n\tborder-radius: 5px;\n\tdisplay: inline-block;\n\tvertical-align: top;\n\tbackground-color: #777;\n}\n\n#info {\n\tborder: 1px solid #aaa;\n\tbackground-color: #777;\n\twidth: auto;\n\tborder-radius: 5px;\n\toverflow: hidden;\n\tpadding: 5px;\n}\n"
  },
  {
    "path": "_archive/apps/samples/messaging/README.md",
    "content": "# Messaging\n\nThis sample shows how to communicate between two apps or one app and one extension. Add app1, app2 and extension to Chrome and play with sending messages between them.\n\n## Resources\n\n* [Messaging](https://developer.chrome.com/docs/extensions/reference/app_runtime#method-sendMessage)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/messaging/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/messaging/app1/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/mcfaknmahgbmjlbondlciokappnnjbnf\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n"
  },
  {
    "path": "_archive/apps/samples/messaging/app1/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <link href=\"main.css\" rel=\"stylesheet\">\n</head>\n<body>\n    <h3>Waiting for messages</h3>\n    <label>my Application ID is <input id=\"appid\" type=\"text\"  readonly></input></label>\n    <div>\n      <label for=\"sendText\">Send message:</label>\n      <input id=\"sendText\" type=\"text\"></input>\n      <label for=\"sendId\">to application ID </label>\n      <input id=\"sendId\" type=\"text\"></input>\n      <button id=\"send\">Send</button>\n    </div>\n    <div id=\"log\"></div>\n    <script src=\"index.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/messaging/app1/index.js",
    "content": "(function(context){\n\n  document.getElementById(\"appid\").value=chrome.runtime.id;  \n  var logField = document.getElementById(\"log\");\n  var sendText=document.getElementById(\"sendText\");\n  var sendText=document.getElementById(\"sendText\");\n  var sendId=document.getElementById(\"sendId\");\n  var send=document.getElementById(\"send\");\n\n  send.addEventListener('click', function() {\n    appendLog(\"sending to \"+sendId.value);\n    chrome.runtime.sendMessage(\n      sendId.value, \n      {myCustomMessage: sendText.value}, \n      function(response) { \n        appendLog(\"response: \"+JSON.stringify(response));\n      })\n  });\n\n\n  blocklistedIds = [\"none\"];\n\n  chrome.runtime.onMessageExternal.addListener(\n    function(request, sender, sendResponse) {\n      if (sender.id in blocklistedIds) {\n        sendResponse({\"result\":\"sorry, could not process your message\"});\n        return;  // don't allow this extension access\n      } else if (request.myCustomMessage) {\n        appendLog(\"from \"+sender.id+\": \"+request.myCustomMessage);\n        sendResponse({\"result\":\"Ok, got your message\"});\n      } else {\n        sendResponse({\"result\":\"Ops, I don't understand this message\"});\n      }\n    });\n\n\n\n  var appendLog = function(message) {\n    logField.innerText+=\"\\n\"+message;\n  }\n\n  context.appendLog = appendLog;\n\n})(window)\n"
  },
  {
    "path": "_archive/apps/samples/messaging/app1/main.css",
    "content": "input[type=\"text\"] {\n  width: 240px;\n}\n\n#log {\n  background-color: rgb(226, 226, 250);\n  padding: 10px 20px;\n  margin-top: 10px;\n  height: 300px;\n  border: 1px solid black;\n  overflow-y: scroll;\n  overflow-x: hidden;\n}"
  },
  {
    "path": "_archive/apps/samples/messaging/app1/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html',\n    {\n    \tid: \"messagingEx1ID\",\n    \tinnerBounds: {width: 800, height: 500}\n    });\n});\n//function addExternalMessageListener\n"
  },
  {
    "path": "_archive/apps/samples/messaging/app1/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Sample Messaging App1\",\n  \"description\": \"This sample shows how to communicate between two apps or one app and one extension.\",\n  \"version\": \"2\",\n  \"minimum_chrome_version\": \"23\",\n  \"icons\": {\n    \"16\": \"icon_16.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/messaging/app2/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hdligeegpimhdjepakblhneiekccbhol\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n"
  },
  {
    "path": "_archive/apps/samples/messaging/app2/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <link href=\"main.css\" rel=\"stylesheet\">\n</head>\n<body>\n    <h3>Waiting for messages</h3>\n    <label>my Application ID is <input id=\"appid\" type=\"text\"  readonly></input></label>\n    <div>\n      <label for=\"sendText\">Send message:</label>\n      <input id=\"sendText\" type=\"text\"></input>\n      <label for=\"sendId\">to application ID </label>\n      <input id=\"sendId\" type=\"text\"></input>\n      <button id=\"send\">Send</button>\n    </div>\n    <div id=\"log\"></div>\n    <script src=\"index.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/messaging/app2/index.js",
    "content": "(function(context){\n\n  document.getElementById(\"appid\").value=chrome.runtime.id;  \n  var logField = document.getElementById(\"log\");\n  var sendText=document.getElementById(\"sendText\");\n  var sendText=document.getElementById(\"sendText\");\n  var sendId=document.getElementById(\"sendId\");\n  var send=document.getElementById(\"send\");\n\n  send.addEventListener('click', function() {\n    appendLog(\"sending to \"+sendId.value);\n    chrome.runtime.sendMessage(\n      sendId.value, \n      {myCustomMessage: sendText.value}, \n      function(response) { \n        appendLog(\"response: \"+JSON.stringify(response));\n      })\n  });\n\n\n  blocklistedIds = [\"none\"];\n\n  chrome.runtime.onMessageExternal.addListener(\n    function(request, sender, sendResponse) {\n      if (sender.id in blocklistedIds) {\n        sendResponse({\"result\":\"sorry, could not process your message\"});\n        return;  // don't allow this extension access\n      } else if (request.myCustomMessage) {\n        appendLog(\"from \"+sender.id+\": \"+request.myCustomMessage);\n        sendResponse({\"result\":\"Ok, got your message\"});\n      } else {\n        sendResponse({\"result\":\"Ops, I don't understand this message\"});\n      }\n    });\n\n\n\n  var appendLog = function(message) {\n    logField.innerText+=\"\\n\"+message;\n  }\n\n  context.appendLog = appendLog;\n\n})(window)\n"
  },
  {
    "path": "_archive/apps/samples/messaging/app2/main.css",
    "content": "input[type=\"text\"] {\n  width: 240px;\n}\n\n#log {\n  background-color: rgb(226, 226, 250);\n  padding: 10px 20px;\n  margin-top: 10px;\n  height: 300px;\n  border: 1px solid black;\n  overflow-y: scroll;\n  overflow-x: hidden;\n}"
  },
  {
    "path": "_archive/apps/samples/messaging/app2/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html',\n    {\n    \tid: \"messagingEx2ID\",\n    \tinnerBounds: {width: 800, height: 500}\n    });\n});\n//function addExternalMessageListener\n"
  },
  {
    "path": "_archive/apps/samples/messaging/app2/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Sample Messaging App2\",\n  \"description\": \"This sample shows how to communicate between two apps or one app and one extension.\",\n  \"version\": \"2\",\n  \"minimum_chrome_version\": \"23\",\n  \"icons\": {\n    \"16\": \"icon_16.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/messaging/extension/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ihhkahhkmiddbnfhlglocakcdfbgddkj\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n"
  },
  {
    "path": "_archive/apps/samples/messaging/extension/eventPage.js",
    "content": "var blocklistedIds = [\"none\"];\n\nchrome.runtime.onMessageExternal.addListener(\n  function(request, sender, sendResponse) {\n    if (sender.id in blocklistedIds) {\n      sendResponse({\"result\":\"sorry, could not process your message\"});\n      return;  // don't allow this extension access\n    } else if (request.myCustomMessage) {\n      new Notification('Got message from '+sender.id,\n          { body: request.myCustomMessage });\n      sendResponse({\"result\":\"Ok, got your message\"});\n    } else {\n      sendResponse({\"result\":\"Ops, I don't understand this message\"});\n    }\n  });\n\n"
  },
  {
    "path": "_archive/apps/samples/messaging/extension/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <link href=\"main.css\" rel=\"stylesheet\">\n</head>\n<body>\n    <h3>Waiting for messages</h3>\n    <label>my extension ID is <input id=\"appid\" type=\"text\"  readonly></input></label>\n    <div>\n      <label for=\"sendText\">Send message:</label>\n      <input id=\"sendText\" type=\"text\"></input>\n      <label for=\"sendId\">to application ID </label>\n      <input id=\"sendId\" type=\"text\"></input>\n      <button id=\"send\">Send</button>\n    </div>\n    <div id=\"log\"></div>\n    <script src=\"index.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/messaging/extension/index.js",
    "content": "(function(context){\n\n  document.getElementById(\"appid\").value=chrome.runtime.id;  \n  var logField = document.getElementById(\"log\");\n  var sendText=document.getElementById(\"sendText\");\n  var sendText=document.getElementById(\"sendText\");\n  var sendId=document.getElementById(\"sendId\");\n  var send=document.getElementById(\"send\");\n\n  send.addEventListener('click', function() {\n    appendLog(\"sending to \"+sendId.value);\n    chrome.runtime.sendMessage(\n      sendId.value, \n      {myCustomMessage: sendText.value}, \n      function(response) { \n        appendLog(\"response: \"+JSON.stringify(response));\n      })\n  });\n\n  var appendLog = function(message) {\n    logField.innerText+=\"\\n\"+message;\n  }\n\n  context.appendLog = appendLog;\n\n})(window)\n"
  },
  {
    "path": "_archive/apps/samples/messaging/extension/main.css",
    "content": "input[type=\"text\"] {\n  width: 240px;\n}\n\n#log {\n  background-color: rgb(226, 226, 250);\n  padding: 10px 20px;\n  margin-top: 10px;\n  height: 300px;\n  border: 1px solid black;\n  overflow-y: scroll;\n  overflow-x: hidden;\n}"
  },
  {
    "path": "_archive/apps/samples/messaging/extension/manifest.json",
    "content": "{\n  \"name\": \"Sample Messaging extension\",\n  \"version\": \"1.3.1\",\n  \"description\": \"This sample shows how to communicate between two apps or one app and one extension.\",\n  \"browser_action\": {\n    \"default_title\": \"Send message to other apps\",\n    \"default_icon\": \"icon_16.png\",\n    \"default_popup\": \"index.html\"\n  },\n  \"background\": {\n    \"scripts\": [\"eventPage.js\"],\n    \"persistent\": false\n  },\n  \"permissions\": [\"notifications\"],\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/inbjbbebnhailhhkfaaokegkfjlmgabb\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Mini code editor\n\nA non-trivial sample with basic features of a code editor, like syntax detection and syntax highlight. If also uses the extended FileSystem API that allows a user to select files from the disk so the app can read and write to that file.\n\n## APIs\n\n* [chrome.fileSystem](http://developer.chrome.com/apps/fileSystem)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/mini-code-edit/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  // width 640 for font size 12\n  //       720 for font size 14\n  chrome.app.window.create('main.html', {\n    frame: 'chrome', id: \"codewin\", innerBounds: { width: 720, height: 400, minWidth:720, minHeight: 400 }\n  });\n});\n\n/** \n* Set up the Commands listener event\n* @see http://developer.chrome.com/apps/commands.html\n*/\nchrome.commands.onCommand.addListener(function(command) {\n   console.log(\"Command triggered: \" + command);\n\n   if (command == \"cmdNew\") {\n     chrome.app.window.create('main.html', {\n       frame: 'chrome', id: \"codewin\", innerBounds: { width: 720, height: 400, minWidth:720, minHeight: 400 }\n     });\n   }\n});\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/LICENSE",
    "content": "Copyright (C) 2012 by Marijn Haverbeke <marijnh@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\nPlease note that some subdirectories of the CodeMirror distribution\ninclude their own LICENSE files, and are released under different\nlicences.\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/README.md",
    "content": "# CodeMirror 2\n\nCodeMirror 2 is a rewrite of [CodeMirror\n1](http://github.com/marijnh/CodeMirror). The docs live\n[here](http://codemirror.net/doc/manual.html), and the project page is\n[http://codemirror.net/](http://codemirror.net/).\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/activeline.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Active Line Demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../mode/xml/xml.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n      .activeline {background: #e8f2ff !important;}\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Active Line Demo</h1>\n\n    <form><textarea id=\"code\" name=\"code\">\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rss xmlns:atom=\"http://www.w3.org/2005/Atom\" version=\"2.0\"\n     xmlns:georss=\"http://www.georss.org/georss\"\n     xmlns:twitter=\"http://api.twitter.com\">\n  <channel>\n    <title>Twitter / codemirror</title>\n    <link>http://twitter.com/codemirror</link>\n    <atom:link type=\"application/rss+xml\"\n               href=\"http://twitter.com/statuses/user_timeline/242283288.rss\" rel=\"self\"/>\n    <description>Twitter updates from CodeMirror / codemirror.</description>\n    <language>en-us</language>\n    <ttl>40</ttl>\n  <item>\n    <title>codemirror: http://cloud-ide.com &#8212; they're springing up like mushrooms. This one\n      uses CodeMirror as its editor.</title>\n    <description>codemirror: http://cloud-ide.com &#8212; they're springing up like mushrooms. This\n      one uses CodeMirror as its editor.</description>\n    <pubDate>Thu, 17 Mar 2011 23:34:47 +0000</pubDate>\n    <guid>http://twitter.com/codemirror/statuses/48527733722058752</guid>\n    <link>http://twitter.com/codemirror/statuses/48527733722058752</link>\n    <twitter:source>web</twitter:source>\n    <twitter:place/>\n  </item>\n  <item>\n    <title>codemirror: Posted a description of the CodeMirror 2 internals at\n      http://codemirror.net/2/internals.html</title>\n    <description>codemirror: Posted a description of the CodeMirror 2 internals at\n      http://codemirror.net/2/internals.html</description>\n    <pubDate>Wed, 02 Mar 2011 12:15:09 +0000</pubDate>\n    <guid>http://twitter.com/codemirror/statuses/42920879788789760</guid>\n    <link>http://twitter.com/codemirror/statuses/42920879788789760</link>\n    <twitter:source>web</twitter:source>\n    <twitter:place/>\n  </item>\n  </channel>\n</rss></textarea></form>\n\n    <script>\nvar editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n  mode: \"application/xml\",\n  lineNumbers: true,\n  lineWrapping: true,\n  onCursorActivity: function() {\n    editor.setLineClass(hlLine, null, null);\n    hlLine = editor.setLineClass(editor.getCursor().line, null, \"activeline\");\n  }\n});\nvar hlLine = editor.setLineClass(0, \"activeline\");\n</script>\n\n    <p>Styling the current cursor line.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/changemode.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Mode-Changing Demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../mode/javascript/javascript.js\"></script>\n    <script src=\"../mode/scheme/scheme.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror {border: 1px solid black;}\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Mode-Changing demo</h1>\n\n    <form><textarea id=\"code\" name=\"code\">\n;; If there is Scheme code in here, the editor will be in Scheme mode.\n;; If you put in JS instead, it'll switch to JS mode.\n\n(define (double x)\n  (* x x))\n</textarea></form>\n\n<p>On changes to the content of the above editor, a (crude) script\ntries to auto-detect the language used, and switches the editor to\neither JavaScript or Scheme mode based on that.</p>\n\n<script>\n  var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n    mode: \"scheme\",\n    lineNumbers: true,\n    matchBrackets: true,\n    tabMode: \"indent\",\n    onChange: function() {\n      clearTimeout(pending);\n      setTimeout(update, 400);\n    }\n  });\n  var pending;\n  function looksLikeScheme(code) {\n    return !/^\\s*\\(\\s*function\\b/.test(code) && /^\\s*[;\\(]/.test(code);\n  }\n  function update() {\n    editor.setOption(\"mode\", looksLikeScheme(editor.getValue()) ? \"scheme\" : \"javascript\");\n  }\n</script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/closetag.html",
    "content": "<!doctype html>\n<html>\n\t<head>\n\t\t<title>CodeMirror: Close-Tag Demo</title>\n\t\t<link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n\t\t<script src=\"../lib/codemirror.js\"></script>\n\t\t<script src=\"../lib/util/closetag.js\"></script>\n\t\t<script src=\"../mode/xml/xml.js\"></script>\n\t\t<script src=\"../mode/javascript/javascript.js\"></script>\n\t\t<script src=\"../mode/css/css.js\"></script>\n\t\t<script src=\"../mode/htmlmixed/htmlmixed.js\"></script>\n\t\t<link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\t\t<style type=\"text/css\">\n\t\t\t.CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}\n\t\t</style>\n\t</head>\n\t<body>\n\t\n\t\t<h1>Close-Tag Demo</h1>\n\t\t<ul>\n\t\t\t<li>Type an html tag.  When you type '>' or '/', the tag will auto-close/complete.  Block-level tags will indent.</li>\n\t\t\t<li>There are options for disabling tag closing or customizing the list of tags to indent.</li>\n\t\t\t<li>Works with \"text/html\" (based on htmlmixed.js or xml.js) mode.</li>\n\t\t\t<li>View source for key binding details.</li>\n\t\t</p>\n\n\t\t<form><textarea id=\"code\" name=\"code\"></textarea></form>\n\n\t\t<script type=\"text/javascript\">\n\t\tvar editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n\t\t\tmode: 'text/html',\n\t\t\t\n\t\t\t//closeTagEnabled: false, // Set this option to disable tag closing behavior without having to remove the key bindings.\n\t\t\t//closeTagIndent: false, // Pass false or an array of tag names to override the default indentation behavior.\n\t\t\t\n\t\t\textraKeys: {\n\t\t\t\t\"'>'\": function(cm) { cm.closeTag(cm, '>'); },\n\t\t\t\t\"'/'\": function(cm) { cm.closeTag(cm, '/'); }\n\t\t\t},\n\t\t\t\n\t\t\t/*\n\t\t\t// extraKeys is the easier way to go, but if you need native key event processing, this should work too.\n\t\t\tonKeyEvent: function(cm, e) {\n\t\t\t\tif (e.type == 'keydown') {\n\t\t\t\t\tvar c = e.keyCode || e.which;\n\t\t\t\t\tif (c == 190 || c == 191) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcm.closeTag(cm, c == 190 ? '>' : '/');\n\t\t\t\t\t\t\te.stop();\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tif (e != CodeMirror.Pass) throw e;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t*/\n\t\t\t\n\t\t\twordWrap: true\n\t\t});\n\t\t</script>\n\n\t</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/complete.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Autocomplete Demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../lib/util/simple-hint.js\"></script>\n    <link rel=\"stylesheet\" href=\"../lib/util/simple-hint.css\">\n    <script src=\"../lib/util/javascript-hint.js\"></script>\n    <script src=\"../mode/javascript/javascript.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n    <style type=\"text/css\">.CodeMirror {border: 1px solid #eee;} .CodeMirror-scroll { height: 100% }</style>\n  </head>\n  <body>\n    <h1>CodeMirror: Autocomplete demo</h1>\n\n    <form><textarea id=\"code\" name=\"code\">\nfunction getCompletions(token, context) {\n  var found = [], start = token.string;\n  function maybeAdd(str) {\n    if (str.indexOf(start) == 0) found.push(str);\n  }\n  function gatherCompletions(obj) {\n    if (typeof obj == \"string\") forEach(stringProps, maybeAdd);\n    else if (obj instanceof Array) forEach(arrayProps, maybeAdd);\n    else if (obj instanceof Function) forEach(funcProps, maybeAdd);\n    for (var name in obj) maybeAdd(name);\n  }\n\n  if (context) {\n    // If this is a property, see if it belongs to some object we can\n    // find in the current environment.\n    var obj = context.pop(), base;\n    if (obj.className == \"js-variable\")\n      base = window[obj.string];\n    else if (obj.className == \"js-string\")\n      base = \"\";\n    else if (obj.className == \"js-atom\")\n      base = 1;\n    while (base != null && context.length)\n      base = base[context.pop().string];\n    if (base != null) gatherCompletions(base);\n  }\n  else {\n    // If not, just look in the window object and any local scope\n    // (reading into JS mode internals to get at the local variables)\n    for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);\n    gatherCompletions(window);\n    forEach(keywords, maybeAdd);\n  }\n  return found;\n}\n</textarea></form>\n\n<p>Press <strong>ctrl-space</strong> to activate autocompletion. See\nthe code (<a href=\"../lib/util/simple-hint.js\">here</a>\nand <a href=\"../lib/util/javascript-hint.js\">here</a>) to figure out\nhow it works.</p>\n\n    <script>\n      CodeMirror.commands.autocomplete = function(cm) {\n        CodeMirror.simpleHint(cm, CodeMirror.javascriptHint);\n      }\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        extraKeys: {\"Ctrl-Space\": \"autocomplete\"}\n      });\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/emacs.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Emacs bindings demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../mode/clike/clike.js\"></script>\n    <script src=\"../keymap/emacs.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Emacs bindings demo</h1>\n\n    <form><textarea id=\"code\" name=\"code\">\n#include \"syscalls.h\"\n/* getchar:  simple buffered version */\nint getchar(void)\n{\n  static char buf[BUFSIZ];\n  static char *bufp = buf;\n  static int n = 0;\n  if (n == 0) {  /* buffer is empty */\n    n = read(0, buf, sizeof buf);\n    bufp = buf;\n  }\n  return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n}\n</textarea></form>\n\n<p>The emacs keybindings are enabled by\nincluding <a href=\"../keymap/emacs.js\">keymap/emacs.js</a> and setting\nthe <code>keyMap</code> option to <code>\"emacs\"</code>. Because\nCodeMirror's internal API is quite different from Emacs, they are only\na loose approximation of actual emacs bindings, though.</p>\n\n<p>Also note that a lot of browsers disallow certain keys from being\ncaptured. For example, Chrome blocks both Ctrl-W and Ctrl-N, with the\nresult that idiomatic use of Emacs keys will constantly close your tab\nor open a new window.</p>\n\n    <script>\n      CodeMirror.commands.save = function() {\n        var elt = editor.getWrapperElement();\n        elt.style.background = \"#def\";\n        setTimeout(function() { elt.style.background = \"\"; }, 300);\n      };\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        mode: \"text/x-csrc\",\n        keyMap: \"emacs\"\n      });\n    </script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/folding.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Code Folding Demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../lib/util/foldcode.js\"></script>\n    <script src=\"../mode/javascript/javascript.js\"></script>\n    <script src=\"../mode/xml/xml.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n      .CodeMirror-gutter {min-width: 2.6em; cursor: pointer;}\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Code Folding Demo</h1>\n\n    <p>Demonstration of code folding using the code\n    in <a href=\"../lib/util/foldcode.js\"><code>foldcode.js</code></a>.\n    Press ctrl-q or click on the gutter to fold a block, again\n    to unfold.</p>\n    <form>\n      <div style=\"max-width: 50em; margin-bottom: 1em\">JavaScript:<br><textarea id=\"code\" name=\"code\"></textarea></div>\n      <div style=\"max-width: 50em\">HTML:<br><textarea id=\"code-html\" name=\"code-html\"></textarea></div>\n    </form>\n    <script id=\"script\">\nwindow.onload = function() {\n  var te = document.getElementById(\"code\");\n  var sc = document.getElementById(\"script\");\n  te.value = (sc.textContent || sc.innerText || sc.innerHTML).replace(/^\\s*/, \"\");\n  sc.innerHTML = \"\";\n  var te_html = document.getElementById(\"code-html\");\n  te_html.value = \"<html>\\n  \" + document.documentElement.innerHTML + \"\\n</html>\";\n\n  var foldFunc = CodeMirror.newFoldFunction(CodeMirror.braceRangeFinder);\n  window.editor = CodeMirror.fromTextArea(te, {\n    mode: \"javascript\",\n    lineNumbers: true,\n    lineWrapping: true,\n    onGutterClick: foldFunc,\n    extraKeys: {\"Ctrl-Q\": function(cm){foldFunc(cm, cm.getCursor().line);}}\n  });\n  foldFunc(editor, 9);\n  foldFunc(editor, 20);\n\n  var foldFunc_html = CodeMirror.newFoldFunction(CodeMirror.tagRangeFinder);\n  window.editor_html = CodeMirror.fromTextArea(te_html, {\n    mode: \"text/html\",\n    lineNumbers: true,\n    lineWrapping: true,\n    onGutterClick: foldFunc_html,\n    extraKeys: {\"Ctrl-Q\": function(cm){foldFunc_html(cm, cm.getCursor().line);}}\n  })\n  foldFunc_html(editor_html, 1);\n  foldFunc_html(editor_html, 15);\n};\n</script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/formatting.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Formatting Demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../lib/util/formatting.js\"></script>\n    <script src=\"../mode/css/css.js\"></script>\n    <script src=\"../mode/xml/xml.js\"></script>\n    <script src=\"../mode/javascript/javascript.js\"></script>\n    <script src=\"../mode/htmlmixed/htmlmixed.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror {\n        border: 1px solid #eee;\n      }\n      td {\n        padding-right: 20px;\n      }\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Formatting demo</h1>\n\n    <form><textarea id=\"code\" name=\"code\"><script> function (s,e){ for(var i=0; i < 1; i++) test(\"test();a=1\");} </script>\n<script>\nfunction test(c){  for (var i = 0; i < 10; i++){\t          process(\"a.b();c = null;\", 300);}\n}\n</script>\n<table><tr><td>test 1</td></tr><tr><td>test 2</td></tr></table>\n<script> function test() { return 1;} </script>\n<style> .test { font-size: medium; font-family: monospace; }\n</style></textarea></form>\n\n<p>Select a piece of code and click one of the links below to apply automatic formatting to the selected text or comment/uncomment the selected text. Note that the formatting behavior depends on the current block's mode.\n    <table>\n      <tr>\n        <td>\n          <a href=\"javascript:autoFormatSelection()\">\n            Autoformat Selected\n          </a>\n        </td>\n        <td>\n          <a href=\"javascript:commentSelection(true)\">\n            Comment Selected\n          </a>\n        </td>\n        <td>\n          <a href=\"javascript:commentSelection(false)\">\n            Uncomment Selected\n          </a>\n        </td>\n      </tr>\n    </table>\n</p>    \n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        mode: \"htmlmixed\"\n      });\n      CodeMirror.commands[\"selectAll\"](editor);\n      \n      function getSelectedRange() {\n        return { from: editor.getCursor(true), to: editor.getCursor(false) };\n      }\n      \n      function autoFormatSelection() {\n        var range = getSelectedRange();\n        editor.autoFormatRange(range.from, range.to);\n      }\n      \n      function commentSelection(isComment) {\n        var range = getSelectedRange();\n        editor.commentRange(isComment, range.from, range.to);\n      }      \n    </script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/fullscreen.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Full Screen Editing</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <link rel=\"stylesheet\" href=\"../theme/night.css\">\n    <script src=\"../mode/xml/xml.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n        .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n        .CodeMirror-fullscreen {\n            display: block;\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            z-index: 9999;\n            margin: 0;\n            padding: 0;\n            border: 0px solid #BBBBBB;\n            opacity: 1;\n        }\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Full Screen Editing</h1>\n\n    <form><textarea id=\"code\" name=\"code\" rows=\"5\">\n  <dt id=\"option_indentWithTabs\"><code>indentWithTabs (boolean)</code></dt>\n  <dd>Whether, when indenting, the first N*8 spaces should be\n  replaced by N tabs. Default is false.</dd>\n\n  <dt id=\"option_tabMode\"><code>tabMode (string)</code></dt>\n  <dd>Determines what happens when the user presses the tab key.\n  Must be one of the following:\n    <dl>\n      <dt><code>\"classic\" (the default)</code></dt>\n      <dd>When nothing is selected, insert a tab. Otherwise,\n      behave like the <code>\"shift\"</code> mode. (When shift is\n      held, this behaves like the <code>\"indent\"</code> mode.)</dd>\n      <dt><code>\"shift\"</code></dt>\n      <dd>Indent all selected lines by\n      one <a href=\"#option_indentUnit\"><code>indentUnit</code></a>.\n      If shift was held while pressing tab, un-indent all selected\n      lines one unit.</dd>\n      <dt><code>\"indent\"</code></dt>\n      <dd>Indent the line the 'correctly', based on its syntactic\n      context. Only works if the\n      mode <a href=\"#indent\">supports</a> it.</dd>\n      <dt><code>\"default\"</code></dt>\n      <dd>Do not capture tab presses, let the browser apply its\n      default behaviour (which usually means it skips to the next\n      control).</dd>\n    </dl></dd>\n\n  <dt id=\"option_enterMode\"><code>enterMode (string)</code></dt>\n  <dd>Determines whether and how new lines are indented when the\n  enter key is pressed. The following modes are supported:\n    <dl>\n      <dt><code>\"indent\" (the default)</code></dt>\n      <dd>Use the mode's indentation rules to give the new line\n      the correct indentation.</dd>\n      <dt><code>\"keep\"</code></dt>\n      <dd>Indent the line the same as the previous line.</dd>\n      <dt><code>\"flat\"</code></dt>\n      <dd>Do not indent the new line.</dd>\n    </dl></dd>\n\n  <dt id=\"option_enterMode\"><code>enterMode (string)</code></dt>\n  <dd>Determines whether and how new lines are indented when the\n  enter key is pressed. The following modes are supported:\n    <dl>\n      <dt><code>\"indent\" (the default)</code></dt>\n      <dd>Use the mode's indentation rules to give the new line\n      the correct indentation.</dd>\n      <dt><code>\"keep\"</code></dt>\n      <dd>Indent the line the same as the previous line.</dd>\n      <dt><code>\"flat\"</code></dt>\n      <dd>Do not indent the new line.</dd>\n    </dl></dd>\n\n  <dt id=\"option_enterMode\"><code>enterMode (string)</code></dt>\n  <dd>Determines whether and how new lines are indented when the\n  enter key is pressed. The following modes are supported:\n    <dl>\n      <dt><code>\"indent\" (the default)</code></dt>\n      <dd>Use the mode's indentation rules to give the new line\n      the correct indentation.</dd>\n      <dt><code>\"keep\"</code></dt>\n      <dd>Indent the line the same as the previous line.</dd>\n      <dt><code>\"flat\"</code></dt>\n      <dd>Do not indent the new line.</dd>\n    </dl></dd>\n\n  <dt id=\"option_enterMode\"><code>enterMode (string)</code></dt>\n  <dd>Determines whether and how new lines are indented when the\n  enter key is pressed. The following modes are supported:\n    <dl>\n      <dt><code>\"indent\" (the default)</code></dt>\n      <dd>Use the mode's indentation rules to give the new line\n      the correct indentation.</dd>\n      <dt><code>\"keep\"</code></dt>\n      <dd>Indent the line the same as the previous line.</dd>\n      <dt><code>\"flat\"</code></dt>\n      <dd>Do not indent the new line.</dd>\n    </dl></dd>\n\n</textarea></form>\n <script>\n    var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        theme: \"night\",\n        extraKeys: {\n            \"F11\": function() {\n              var scroller = editor.getScrollerElement();\n              if (scroller.className.search(/\\bCodeMirror-fullscreen\\b/) === -1) {\n                scroller.className += \" CodeMirror-fullscreen\";\n                scroller.style.height = \"100%\";\n                scroller.style.width = \"100%\";\n                editor.refresh();\n              } else {\n                scroller.className = scroller.className.replace(\" CodeMirror-fullscreen\", \"\");\n                scroller.style.height = '';\n                scroller.style.width = '';\n                editor.refresh();\n              }\n            },\n            \"Esc\": function() {\n              var scroller = editor.getScrollerElement();\n              if (scroller.className.search(/\\bCodeMirror-fullscreen\\b/) !== -1) {\n                scroller.className = scroller.className.replace(\" CodeMirror-fullscreen\", \"\");\n                scroller.style.height = '';\n                scroller.style.width = '';\n                editor.refresh();\n              }\n            }\n        }\n    });\n\n</script>\n\n    <p>Press <strong>F11</strong> when cursor is in the editor to toggle full screen editing. <strong>Esc</strong> can also be used to <i>exit</i> full screen editing.</p>\n\n    <p><strong>Note:</strong> Does not currently work correctly in IE\n    6 and 7, where setting the height of something\n    to <code>100%</code> doesn't make it full screen.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/loadmode.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Lazy Mode Loading Demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../lib/util/loadmode.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Lazy Mode Loading</h1>\n\n    <form><textarea id=\"code\" name=\"code\">This is the editor.\n// It starts out in plain text mode,\n#  use the control below to load and apply a mode\n  \"you'll see the highlighting of\" this text /*change*/.\n</textarea></form>\n<p><input type=text value=javascript id=mode> <button type=button onclick=\"change()\">change mode</button></p>\n\n    <script>\nCodeMirror.modeURL = \"../mode/%N/%N.js\";\nvar editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n  lineNumbers: true\n});\nvar modeInput = document.getElementById(\"mode\");\nCodeMirror.connect(modeInput, \"keypress\", function(e) {\n  if (e.keyCode == 13) change();\n});\nfunction change() {\n   editor.setOption(\"mode\", modeInput.value);\n   CodeMirror.autoLoadMode(editor, modeInput.value);\n}\n</script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/marker.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Breakpoint Demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../mode/javascript/javascript.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror-gutter {\n        width: 3em;\n        background: white;\n      }\n      .CodeMirror {\n        border: 1px solid #aaa;\n      }\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Breakpoint demo</h1>\n\n    <form><textarea id=\"code\" name=\"code\">\nCodeMirror.fromTextArea(document.getElementById(\"code\"), {\n  lineNumbers: true,\n  onGutterClick: function(cm, n) {\n    var info = cm.lineInfo(n);\n    if (info.markerText)\n      cm.clearMarker(n);\n    else\n      cm.setMarker(n, \"<span style=\\\"color: #900\\\">●</span> %N%\");\n  }\n});\n</textarea></form>\n\n<p>Click the line-number gutter to add or remove 'breakpoints'.</p>\n\n    <script>\n      CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        onGutterClick: function(cm, n) {\n          var info = cm.lineInfo(n);\n          if (info.markerText)\n            cm.clearMarker(n);\n          else\n            cm.setMarker(n, \"<span style=\\\"color: #900\\\">●</span> %N%\");\n        }\n      });\n    </script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/matchhighlighter.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Match Highlighter Demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../lib/util/searchcursor.js\"></script>\n    <script src=\"../lib/util/match-highlighter.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n\t  \n      span.CodeMirror-matchhighlight { background: #e9e9e9 }\n      .CodeMirror-focused span.CodeMirror-matchhighlight { background: #e7e4ff; !important }\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Match Highlighter Demo</h1>\n\n    <form><textarea id=\"code\" name=\"code\">Select this text: hardToSpotVar\n\tAnd everywhere else in your code where hardToSpotVar appears will automatically illuminate.\nGive it a try!  No more hardToSpotVars.</textarea></form>\n\n    <script>\nvar editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n  lineNumbers : true,\n  onCursorActivity: function() {\n    editor.matchHighlight(\"CodeMirror-matchhighlight\");\n  }\n});\n</script>\n\n    <p>Highlight matches of selected text on select</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/mustache.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Overlay Parser Demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../lib/util/overlay.js\"></script>\n    <script src=\"../mode/xml/xml.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror {border: 1px solid black;}\n      .cm-mustache {color: #0ca;}\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Overlay Parser Demo</h1>\n\n    <form><textarea id=\"code\" name=\"code\">\n<html>\n  <body>\n    <h1>{{title}}</h1>\n    <p>These are links to {{things}}:</p>\n    <ul>{{#links}}\n      <li><a href=\"{{url}}\">{{text}}</a></li>\n    {{/links}}</ul>\n  </body>\n</html>\n</textarea></form>\n\n    <script>\nCodeMirror.defineMode(\"mustache\", function(config, parserConfig) {\n  var mustacheOverlay = {\n    token: function(stream, state) {\n      var ch;\n      if (stream.match(\"{{\")) {\n        while ((ch = stream.next()) != null)\n          if (ch == \"}\" && stream.next() == \"}\") break;\n        return \"mustache\";\n      }\n      while (stream.next() != null && !stream.match(\"{{\", false)) {}\n      return null;\n    }\n  };\n  return CodeMirror.overlayParser(CodeMirror.getMode(config, parserConfig.backdrop || \"text/html\"), mustacheOverlay);\n});\nvar editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {mode: \"mustache\"});\n</script>\n\n    <p>Demonstration of a mode that parses HTML, highlighting\n    the <a href=\"http://mustache.github.com/\">Mustache</a> templating\n    directives inside of it by using the code\n    in <a href=\"../lib/util/overlay.js\"><code>overlay.js</code></a>. View\n    source to see the 15 lines of code needed to accomplish this.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/preview.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: HTML5 preview</title>\n    <meta charset=utf-8>\n    <script src=../lib/codemirror.js></script>\n    <script src=../mode/xml/xml.js></script>\n    <script src=../mode/javascript/javascript.js></script>\n    <script src=../mode/css/css.js></script>\n    <script src=../mode/htmlmixed/htmlmixed.js></script>\n    <link rel=stylesheet href=../lib/codemirror.css>\n    <link rel=stylesheet href=../doc/docs.css>\n    <style type=text/css>\n      .CodeMirror {\n        float: left;\n        width: 50%;\n        border: 1px solid black;\n      }\n      iframe {\n        width: 49%;\n        float: left;\n        height: 300px;\n        border: 1px solid black;\n        border-left: 0px;\n      }\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: HTML5 preview</h1>\n    <textarea id=code name=code>\n<!doctype html>\n<html>\n  <head>\n    <meta charset=utf-8>\n    <title>HTML5 canvas demo</title>\n    <style>p {font-family: monospace;}</style>\n  </head>\n  <body>\n    <p>Canvas pane goes here:</p>\n    <canvas id=pane width=300 height=200></canvas>\n    <script>\n      var canvas = document.getElementById('pane');\n      var context = canvas.getContext('2d');\n\n      context.fillStyle = 'rgb(250,0,0)';\n      context.fillRect(10, 10, 55, 50);\n\n      context.fillStyle = 'rgba(0, 0, 250, 0.5)';\n      context.fillRect(30, 30, 55, 50);\n    </script>\n  </body>\n</html></textarea>\n    <iframe id=preview></iframe>\n    <script>\n      var delay;\n      // Initialize CodeMirror editor with a nice html5 canvas demo.\n      var editor = CodeMirror.fromTextArea(document.getElementById('code'), {\n        mode: 'text/html',\n        tabMode: 'indent',\n        onChange: function() {\n          clearTimeout(delay);\n          delay = setTimeout(updatePreview, 300);\n        }\n      });\n      \n      function updatePreview() {\n        var previewFrame = document.getElementById('preview');\n        var preview =  previewFrame.contentDocument ||  previewFrame.contentWindow.document;\n        preview.open();\n        preview.write(editor.getValue());\n        preview.close();\n      }\n      setTimeout(updatePreview, 300);\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/resize.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Autoresize Demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../mode/css/css.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror {\n        border: 1px solid #eee;\n      }\n      .CodeMirror-scroll {\n        height: auto;\n        overflow-y: hidden;\n        overflow-x: auto;\n        width: 100%;\n      }\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Autoresize demo</h1>\n\n    <form><textarea id=\"code\" name=\"code\">\n.CodeMirror-scroll {\n  height: auto;\n  overflow-y: hidden;\n  overflow-x: auto;\n  width: 100%\n}</textarea></form>\n\n<p>By setting a few CSS properties, CodeMirror can be made to\nautomatically resize to fit its content.</p>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true\n      });\n    </script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/runmode.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Mode Runner Demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../lib/util/runmode.js\"></script>\n    <script src=\"../mode/xml/xml.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Mode Runner Demo</h1>\n\n    <textarea id=\"code\" style=\"width: 90%; height: 7em; border: 1px solid black; padding: .2em .4em;\">\n<foobar>\n  <blah>Enter your xml here and press the button below to display\n    it as highlighted by the CodeMirror XML mode</blah>\n  <tag2 foo=\"2\" bar=\"&amp;quot;bar&amp;quot;\"/>\n</foobar></textarea><br>\n    <button onclick=\"doHighlight();\">Highlight!</button>\n    <pre id=\"output\" class=\"cm-s-default\"></pre>\n\n    <script>\nfunction doHighlight() {\n  CodeMirror.runMode(document.getElementById(\"code\").value, \"application/xml\",\n                     document.getElementById(\"output\"));\n}\n</script>\n\n    <p>Running a CodeMirror mode outside of the editor.\n    The <code>CodeMirror.runMode</code> function, defined\n    in <code><a href=\"../lib/util/runmode.js\">lib/runmode.js</a></code> takes the following arguments:</p>\n\n    <dl>\n      <dt><code>text (string)</code></dt>\n      <dd>The document to run through the highlighter.</dd>\n      <dt><code>mode (<a href=\"../doc/manual.html#option_mode\">mode spec</a>)</code></dt>\n      <dd>The mode to use (must be loaded as normal).</dd>\n      <dt><code>output (function or DOM node)</code></dt>\n      <dd>If this is a function, it will be called for each token with\n      two arguments, the token's text and the token's style class (may\n      be <code>null</code> for unstyled tokens). If it is a DOM node,\n      the tokens will be converted to <code>span</code> elements as in\n      an editor, and inserted into the node\n      (through <code>innerHTML</code>).</dd>\n    </dl>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/search.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Search/Replace Demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../mode/xml/xml.js\"></script>\n    <script src=\"../lib/util/dialog.js\"></script>\n    <link rel=\"stylesheet\" href=\"../lib/util/dialog.css\">\n    <script src=\"../lib/util/searchcursor.js\"></script>\n    <script src=\"../lib/util/search.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n      dt {font-family: monospace; color: #666;}\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Search/Replace Demo</h1>\n\n    <form><textarea id=\"code\" name=\"code\">\n  <dt id=\"option_indentWithTabs\"><code>indentWithTabs (boolean)</code></dt>\n  <dd>Whether, when indenting, the first N*8 spaces should be\n  replaced by N tabs. Default is false.</dd>\n\n  <dt id=\"option_tabMode\"><code>tabMode (string)</code></dt>\n  <dd>Determines what happens when the user presses the tab key.\n  Must be one of the following:\n    <dl>\n      <dt><code>\"classic\" (the default)</code></dt>\n      <dd>When nothing is selected, insert a tab. Otherwise,\n      behave like the <code>\"shift\"</code> mode. (When shift is\n      held, this behaves like the <code>\"indent\"</code> mode.)</dd>\n      <dt><code>\"shift\"</code></dt>\n      <dd>Indent all selected lines by\n      one <a href=\"#option_indentUnit\"><code>indentUnit</code></a>.\n      If shift was held while pressing tab, un-indent all selected\n      lines one unit.</dd>\n      <dt><code>\"indent\"</code></dt>\n      <dd>Indent the line the 'correctly', based on its syntactic\n      context. Only works if the\n      mode <a href=\"#indent\">supports</a> it.</dd>\n      <dt><code>\"default\"</code></dt>\n      <dd>Do not capture tab presses, let the browser apply its\n      default behaviour (which usually means it skips to the next\n      control).</dd>\n    </dl></dd>\n\n  <dt id=\"option_enterMode\"><code>enterMode (string)</code></dt>\n  <dd>Determines whether and how new lines are indented when the\n  enter key is pressed. The following modes are supported:\n    <dl>\n      <dt><code>\"indent\" (the default)</code></dt>\n      <dd>Use the mode's indentation rules to give the new line\n      the correct indentation.</dd>\n      <dt><code>\"keep\"</code></dt>\n      <dd>Indent the line the same as the previous line.</dd>\n      <dt><code>\"flat\"</code></dt>\n      <dd>Do not indent the new line.</dd>\n    </dl></dd>\n</textarea></form>\n\n    <script>\nvar editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {mode: \"text/html\", lineNumbers: true});\n</script>\n\n    <p>Demonstration of primitive search/replace functionality. The\n    keybindings (which can be overridden by custom keymaps) are:</p>\n    <dl>\n      <dt>Ctrl-F / Cmd-F</dt><dd>Start searching</dd>\n      <dt>Ctrl-G / Cmd-G</dt><dd>Find next</dd>\n      <dt>Shift-Ctrl-G / Shift-Cmd-G</dt><dd>Find previous</dd>\n      <dt>Shift-Ctrl-F / Cmd-Option-F</dt><dd>Replace</dd>\n      <dt>Shift-Ctrl-R / Shift-Cmd-Option-F</dt><dd>Replace all</dd>\n    </dl>\n    <p>Searching is enabled by\n    including <a href=\"../lib/util/search.js\">lib/util/search.js</a>.\n    For good-looking input dialogs, you also want to include\n    <a href=\"../lib/util/dialog.js\">lib/util/dialog.js</a>\n    and <a href=\"../lib/util/dialog.css\">lib/util/dialog.css</a>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/theme.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Theme Demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <link rel=\"stylesheet\" href=\"../theme/neat.css\">\n    <link rel=\"stylesheet\" href=\"../theme/elegant.css\">\n    <link rel=\"stylesheet\" href=\"../theme/erlang-dark.css\">\n    <link rel=\"stylesheet\" href=\"../theme/night.css\">\n    <link rel=\"stylesheet\" href=\"../theme/monokai.css\">\n    <link rel=\"stylesheet\" href=\"../theme/cobalt.css\">\n    <link rel=\"stylesheet\" href=\"../theme/eclipse.css\">\n    <link rel=\"stylesheet\" href=\"../theme/rubyblue.css\">\n    <link rel=\"stylesheet\" href=\"../theme/lesser-dark.css\">\n    <link rel=\"stylesheet\" href=\"../theme/xq-dark.css\">\n    <link rel=\"stylesheet\" href=\"../theme/ambiance.css\">\n    <link rel=\"stylesheet\" href=\"../theme/blackboard.css\">\n    <script src=\"../mode/javascript/javascript.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror {border: 1px solid black;}\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Theme demo</h1>\n\n    <form><textarea id=\"code\" name=\"code\">\nfunction findSequence(goal) {\n  function find(start, history) {\n    if (start == goal)\n      return history;\n    else if (start > goal)\n      return null;\n    else\n      return find(start + 5, \"(\" + history + \" + 5)\") ||\n             find(start * 3, \"(\" + history + \" * 3)\");\n  }\n  return find(1, \"1\");\n}</textarea></form>\n\n<p>Select a theme: <select onchange=\"selectTheme()\" id=select>\n    <option selected>default</option>\n    <option>ambiance</option>\n    <option>blackboard</option>\n    <option>cobalt</option>\n    <option>eclipse</option>\n    <option>elegant</option>\n    <option>erlang-dark</option>\n    <option>lesser-dark</option>\n    <option>monokai</option>\n    <option>neat</option>\n    <option>night</option>\n    <option>rubyblue</option>\n    <option>xq-dark</option>\n</select>\n</p>\n\n<script>\n  var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n    lineNumbers: true\n  });\n  var input = document.getElementById(\"select\");\n  function selectTheme() {\n    var theme = input.options[input.selectedIndex].innerHTML;\n    editor.setOption(\"theme\", theme);\n  }\n  var choice = document.location.search && document.location.search.slice(1);\n  if (choice) {\n    input.value = choice;\n    editor.setOption(\"theme\", choice);\n  }\n</script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/vim.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Vim bindings demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../mode/clike/clike.js\"></script>\n    <script src=\"../keymap/vim.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Vim bindings demo</h1>\n\n    <form><textarea id=\"code\" name=\"code\">\n#include \"syscalls.h\"\n/* getchar:  simple buffered version */\nint getchar(void)\n{\n  static char buf[BUFSIZ];\n  static char *bufp = buf;\n  static int n = 0;\n  if (n == 0) {  /* buffer is empty */\n    n = read(0, buf, sizeof buf);\n    bufp = buf;\n  }\n  return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n}\n</textarea></form>\n\n<p>The vim keybindings are enabled by\nincluding <a href=\"../keymap/vim.js\">keymap/vim.js</a> and setting\nthe <code>keyMap</code> option to <code>\"vim\"</code>. Because\nCodeMirror's internal API is quite different from Vim, they are only\na loose approximation of actual vim bindings, though.</p>\n\n    <script>\n      CodeMirror.commands.save = function(){ alert(\"Saving\"); };\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        mode: \"text/x-csrc\",\n        keyMap: \"vim\"\n      });\n    </script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/demo/visibletabs.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Visible tabs demo</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../mode/clike/clike.js\"></script>\n    <link rel=\"stylesheet\" href=\"../doc/docs.css\">\n\n    <style type=\"text/css\">\n      .CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}\n      .cm-tab:after {\n        content: \"\\21e5\";\n        display: -moz-inline-block;\n        display: -webkit-inline-block;\n        display: inline-block;\n        width: 0px;\n        position: relative;\n        overflow: visible;\n        left: -1.4em;\n        color: #aaa;\n      }\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Visible tabs demo</h1>\n\n    <form><textarea id=\"code\" name=\"code\">\n#include \"syscalls.h\"\n/* getchar:  simple buffered version */\nint getchar(void)\n{\n\tstatic char buf[BUFSIZ];\n\tstatic char *bufp = buf;\n\tstatic int n = 0;\n\tif (n == 0) {  /* buffer is empty */\n\t\tn = read(0, buf, sizeof buf);\n\t\tbufp = buf;\n\t}\n\treturn (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n}\n</textarea></form>\n\n<p>Tabs inside the editor are spans with the\nclass <code>cm-tab</code>, and can be styled. This demo uses\nan <code>:after</code> pseudo-class CSS hack that will not work on old\nbrowsers. You can use a more conservative technique like a background\nimage as an alternative.</p>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        tabSize: 4,\n        indentUnit: 4,\n        indentWithTabs: true,\n        mode: \"text/x-csrc\"\n      });\n    </script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/doc/compress.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Compression Helper</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans:bold\"/>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"docs.css\"/>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n  </head>\n  <body>\n\n<h1><span class=\"logo-braces\">{ }</span> <a href=\"http://codemirror.net/\">CodeMirror</a></h1>\n\n<pre class=\"grey\">\n<img src=\"baboon.png\" class=\"logo\" alt=\"logo\"/>/* Script compression\n   helper */\n</pre>\n\n    <p>To optimize loading CodeMirror, especially when including a\n    bunch of different modes, it is recommended that you combine and\n    minify (and preferably also gzip) the scripts. This page makes\n    those first two steps very easy. Simply select the version and\n    scripts you need in the form below, and\n    click <strong>Compress</strong> to download the minified script\n    file.</p>\n\n    <form id=\"form\" action=\"http://marijnhaverbeke.nl/uglifyjs\" method=\"post\">\n      <input type=\"hidden\" id=\"download\" name=\"download\" value=\"codemirror-compressed.js\"/>\n      <p>Version: <select id=\"version\" onchange=\"setVersion(this);\" style=\"padding: 1px\">\n        <option value=\"http://codemirror.net/\">HEAD</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.24;f=\">2.24</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.23;f=\">2.23</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.22;f=\">2.22</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.21;f=\">2.21</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.2;f=\">2.2</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.18;f=\">2.18</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.16;f=\">2.16</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.15;f=\">2.15</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.13;f=\">2.13</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.12;f=\">2.12</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.11;f=\">2.11</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.1;f=\">2.1</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.02;f=\">2.02</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.01;f=\">2.01</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=v2.0;f=\">2.0</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=beta2;f=\">beta2</option>\n        <option value=\"http://marijnhaverbeke.nl/git/codemirror2?a=blob_plain;hb=beta1;f=\">beta1</option>\n      </select></p>\n\n      <select multiple=\"multiple\" size=\"20\" name=\"code_url\" style=\"width: 40em;\" class=\"field\" id=\"files\">\n        <optgroup label=\"CodeMirror Library\">\n          <option value=\"http://codemirror.net/lib/codemirror.js\" selected>codemirror.js</option>\n        </optgroup>\n        <optgroup label=\"Modes\">\n          <option value=\"http://codemirror.net/mode/clike/clike.js\">clike.js</option>\n          <option value=\"http://codemirror.net/mode/clojure/clojure.js\">clojure.js</option>\n          <option value=\"http://codemirror.net/mode/coffeescript/coffeescript.js\">coffeescript.js</option>\n          <option value=\"http://codemirror.net/mode/css/css.js\">css.js</option>\n          <option value=\"http://codemirror.net/mode/diff/diff.js\">diff.js</option>\n          <option value=\"http://codemirror.net/mode/ecl/ecl.js\">ecl.js</option>\n          <option value=\"http://codemirror.net/mode/erlang/erlang.js\">erlang.js</option>\n          <option value=\"http://codemirror.net/mode/gfm/gfm.js\">gfm.js</option>\n          <option value=\"http://codemirror.net/mode/go/go.js\">go.js</option>\n          <option value=\"http://codemirror.net/mode/groovy/groovy.js\">groovy.js</option>\n          <option value=\"http://codemirror.net/mode/haskell/haskell.js\">haskell.js</option>\n          <option value=\"http://codemirror.net/mode/htmlembedded/htmlembedded.js\">htmlembedded.js</option>\n          <option value=\"http://codemirror.net/mode/htmlmixed/htmlmixed.js\">htmlmixed.js</option>\n          <option value=\"http://codemirror.net/mode/javascript/javascript.js\">javascript.js</option>\n          <option value=\"http://codemirror.net/mode/jinja2/jinja2.js\">jinja2.js</option>\n          <option value=\"http://codemirror.net/mode/less/less.js\">less.js</option>\n          <option value=\"http://codemirror.net/mode/lua/lua.js\">lua.js</option>\n          <option value=\"http://codemirror.net/mode/markdown/markdown.js\">markdown.js</option>\n          <option value=\"http://codemirror.net/mode/mysql/mysql.js\">mysql.js</option>\n          <option value=\"http://codemirror.net/mode/ntriples/ntriples.js\">ntriples.js</option>\n          <option value=\"http://codemirror.net/mode/pascal/pascal.js\">pascal.js</option>\n          <option value=\"http://codemirror.net/mode/perl/perl.js\">perl.js</option>\n          <option value=\"http://codemirror.net/mode/php/php.js\">php.js</option>\n          <option value=\"http://codemirror.net/mode/pig/pig.js\">pig.js</option>\n          <option value=\"http://codemirror.net/mode/plsql/plsql.js\">plsql.js</option>\n          <option value=\"http://codemirror.net/mode/properties/properties.js\">properties.js</option>\n          <option value=\"http://codemirror.net/mode/python/python.js\">python.js</option>\n          <option value=\"http://codemirror.net/mode/r/r.js\">r.js</option>\n          <option value=\"http://codemirror.net/mode/rpm/changes/changes.js\">rpm/changes.js</option>\n          <option value=\"http://codemirror.net/mode/rpm/spec/spec.js\">rpm/spec.js</option>\n          <option value=\"http://codemirror.net/mode/rst/rst.js\">rst.js</option>\n          <option value=\"http://codemirror.net/mode/ruby/ruby.js\">ruby.js</option>\n          <option value=\"http://codemirror.net/mode/rust/rust.js\">rust.js</option>\n          <option value=\"http://codemirror.net/mode/scheme/scheme.js\">scheme.js</option>\n          <option value=\"http://codemirror.net/mode/shell/shell.js\">shell.js</option>\n          <option value=\"http://codemirror.net/mode/smalltalk/smalltalk.js\">smalltalk.js</option>\n          <option value=\"http://codemirror.net/mode/smarty/smarty.js\">smarty.js</option>\n          <option value=\"http://codemirror.net/mode/sparql/sparql.js\">sparql.js</option>\n          <option value=\"http://codemirror.net/mode/stex/stex.js\">stex.js</option>\n          <option value=\"http://codemirror.net/mode/tiddlywiki/tiddlywiki.js\">tiddlywiki.js</option>\n          <option value=\"http://codemirror.net/mode/tiki/tiki.js\">tiki.js</option>\n          <option value=\"http://codemirror.net/mode/vbscript/vbscript.js\">vbscript.js</option>\n          <option value=\"http://codemirror.net/mode/velocity/velocity.js\">velocity.js</option>\n          <option value=\"http://codemirror.net/mode/verilog/verilog.js\">verilog.js</option>\n          <option value=\"http://codemirror.net/mode/xml/xml.js\">xml.js</option>\n          <option value=\"http://codemirror.net/mode/xquery/xquery.js\">xquery.js</option>\n          <option value=\"http://codemirror.net/mode/yaml/yaml.js\">yaml.js</option>\n        </optgroup>\n        <optgroup label=\"Utilities and add-ons\">\n          <option value=\"http://codemirror.net/lib/util/overlay.js\">overlay.js</option>\n          <option value=\"http://codemirror.net/lib/util/runmode.js\">runmode.js</option>\n          <option value=\"http://codemirror.net/lib/util/simple-hint.js\">simple-hint.js</option>\n          <option value=\"http://codemirror.net/lib/util/javascript-hint.js\">javascript-hint.js</option>\n          <option value=\"http://codemirror.net/lib/util/foldcode.js\">foldcode.js</option>\n          <option value=\"http://codemirror.net/lib/util/dialog.js\">dialog.js</option>\n          <option value=\"http://codemirror.net/lib/util/search.js\">search.js</option>\n          <option value=\"http://codemirror.net/lib/util/searchcursor.js\">searchcursor.js</option>\n          <option value=\"http://codemirror.net/lib/util/formatting.js\">formatting.js</option>\n          <option value=\"http://codemirror.net/lib/util/match-highlighter.js\">match-highlighter.js</option>\n          <option value=\"http://codemirror.net/lib/util/closetag.js\">closetag.js</option>\n          <option value=\"http://codemirror.net/lib/util/loadmode.js\">loadmode.js</option>\n        </optgroup>\n        <optgroup label=\"Keymaps\">\n          <option value=\"http://codemirror.net/keymap/emacs.js\">emacs.js</option>\n          <option value=\"http://codemirror.net/keymap/vim.js\">vim.js</option>\n        </optgroup>\n      </select></p>\n\n      <p>\n        <button type=\"submit\">Compress</button> with <a href=\"http://github.com/mishoo/UglifyJS/\">UglifyJS</a>\n      </p>\n\n      <p>Custom code to add to the compressed file:<textarea name=\"js_code\" style=\"width: 100%; height: 15em;\" class=\"field\"></textarea></p>\n    </form>\n\n    <script type=\"text/javascript\">\n      function setVersion(ver) {\n        var urlprefix = ver.options[ver.selectedIndex].value;\n        var select = document.getElementById(\"files\"), m;\n        for (var optgr = select.firstChild; optgr; optgr = optgr.nextSibling)\n          for (var opt = optgr.firstChild; opt; opt = opt.nextSibling) {\n            if (opt.nodeName != \"OPTION\")\n              continue;\n            else if (m = opt.value.match(/^http:\\/\\/codemirror.net\\/(.*)$/))\n              opt.value = urlprefix + m[1];\n            else if (m = opt.value.match(/http:\\/\\/marijnhaverbeke.nl\\/git\\/codemirror2\\?a=blob_plain;hb=[^;]+;f=(.*)$/))\n              opt.value = urlprefix + m[1];\n          }\n       }\n    </script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/doc/docs.css",
    "content": "body {\n  font-family: Droid Sans, Arial, sans-serif;\n  line-height: 1.5;\n  max-width: 64.3em;\n  margin: 3em auto;\n  padding: 0 1em;\n}\n\nh1 {\n  letter-spacing: -3px;\n  font-size: 3.23em;\n  font-weight: bold;\n  margin: 0;\n}\n\nh2 {\n  font-size: 1.23em;\n  font-weight: bold;\n  margin: .5em 0;\n  letter-spacing: -1px;\n}\n\nh3 {\n  font-size: 1em;\n  font-weight: bold;\n  margin: .4em 0;\n}\n\npre {\n  background-color: #eee;\n  -moz-border-radius: 6px;\n  -webkit-border-radius: 6px;\n  border-radius: 6px;\n  padding: 1em;\n}\n\npre.code {\n  margin: 0 1em;\n}\n\n.grey {\n  font-size: 2.2em;\n  padding: .5em 1em;\n  line-height: 1.2em;\n  margin-top: .5em;\n  position: relative;\n}\n\nimg.logo {\n  position: absolute;\n  right: -25px;\n  bottom: 4px;\n}\n\na:link, a:visited, .quasilink {\n  color: #df0019;\n  cursor: pointer;\n  text-decoration: none;\n}\n\na:hover, .quasilink:hover {\n  color: #800004;\n}\n\nh1 a:link, h1 a:visited, h1 a:hover {\n  color: black;\n}\n\nul {\n  margin: 0;\n  padding-left: 1.2em;\n}\n\na.download {\n  color: white;\n  background-color: #df0019;\n  width: 100%;\n  display: block;\n  text-align: center;\n  font-size: 1.23em;\n  font-weight: bold;\n  text-decoration: none;\n  -moz-border-radius: 6px;\n  -webkit-border-radius: 6px;\n  border-radius: 6px;\n  padding: .5em 0;\n  margin-bottom: 1em;\n}\n\na.download:hover {\n  background-color: #bb0010;\n}\n\n.rel {\n  margin-bottom: 0;\n}\n\n.rel-note {\n  color: #777;\n  font-size: .9em;\n  margin-top: .1em;\n}\n\n.logo-braces {\n  color: #df0019;\n  position: relative;\n  top: -4px;\n}\n\n.blk {\n  float: left;\n}\n\n.left {\n  width: 37em;\n  padding-right: 6.53em;\n  padding-bottom: 1em;\n}\n\n.left1 {\n  width: 15.24em;\n  padding-right: 6.45em;\n}\n\n.left2 {\n  width: 15.24em;\n}\n\n.right {\n  width: 20.68em;\n}\n\n.leftbig {\n  width: 42.44em;\n  padding-right: 6.53em;\n}\n\n.rightsmall {\n  width: 15.24em;\n}\n\n.clear:after {\n  visibility: hidden;\n  display: block;\n  font-size: 0;\n  content: \" \";\n  clear: both;\n  height: 0;\n}\n.clear { display: inline-block; }\n/* start commented backslash hack \\*/\n* html .clear { height: 1%; }\n.clear { display: block; }\n/* close commented backslash hack */\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/doc/internals.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Internals</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans:bold\"/>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"docs.css\"/>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n    <style>dl dl {margin: 0;} .update {color: #d40 !important}</style>\n  </head>\n  <body>\n\n<h1><span class=\"logo-braces\">{ }</span> <a href=\"http://codemirror.net/\">CodeMirror</a></h1>\n\n<pre class=\"grey\">\n<img src=\"baboon.png\" class=\"logo\" alt=\"logo\"/>/* (Re-) Implementing A Syntax-\n   Highlighting Editor in JavaScript */\n</pre>\n\n<div class=\"clear\"><div class=\"leftbig blk\">\n\n<p style=\"font-size: 85%\" id=\"intro\">\n  <strong>Topic:</strong> JavaScript, code editor implementation<br>\n  <strong>Author:</strong> Marijn Haverbeke<br>\n  <strong>Date:</strong> March 2nd 2011 (updated November 13th 2011)\n</p>\n\n<p>This is a followup to\nmy <a href=\"http://codemirror.net/story.html\">Brutal Odyssey to the\nDark Side of the DOM Tree</a> story. That one describes the\nmind-bending process of implementing (what would become) CodeMirror 1.\nThis one describes the internals of CodeMirror 2, a complete rewrite\nand rethink of the old code base. I wanted to give this piece another\nHunter Thompson copycat subtitle, but somehow that would be out of\nplace—the process this time around was one of straightforward\nengineering, requiring no serious mind-bending whatsoever.</p>\n\n<p>So, what is wrong with CodeMirror 1? I'd estimate, by mailing list\nactivity and general search-engine presence, that it has been\nintegrated into about a thousand systems by now. The most prominent\none, since a few weeks,\nbeing <a href=\"http://googlecode.blogspot.com/2011/01/make-quick-fixes-quicker-on-google.html\">Google\ncode's project hosting</a>. It works, and it's being used widely.</a>\n\n<p>Still, I did not start replacing it because I was bored. CodeMirror\n1 was heavily reliant on <code>designMode</code>\nor <code>contentEditable</code> (depending on the browser). Neither of\nthese are well specified (HTML5 tries\nto <a href=\"http://www.w3.org/TR/html5/editing.html#contenteditable\">specify</a>\ntheir basics), and, more importantly, they tend to be one of the more\nobscure and buggy areas of browser functionality—CodeMirror, by using\nthis functionality in a non-typical way, was constantly running up\nagainst browser bugs. WebKit wouldn't show an empty line at the end of\nthe document, and in some releases would suddenly get unbearably slow.\nFirefox would show the cursor in the wrong place. Internet Explorer\nwould insist on linkifying everything that looked like a URL or email\naddress, a behaviour that can't be turned off. Some bugs I managed to\nwork around (which was often a frustrating, painful process), others,\nsuch as the Firefox cursor placement, I gave up on, and had to tell\nuser after user that they were known problems, but not something I\ncould help.</p>\n\n<p>Also, there is the fact that <code>designMode</code> (which seemed\nto be less buggy than <code>contentEditable</code> in Webkit and\nFirefox, and was thus used by CodeMirror 1 in those browsers) requires\na frame. Frames are another tricky area. It takes some effort to\nprevent getting tripped up by domain restrictions, they don't\ninitialize synchronously, behave strangely in response to the back\nbutton, and, on several browsers, can't be moved around the DOM\nwithout having them re-initialize. They did provide a very nice way to\nnamespace the library, though—CodeMirror 1 could freely pollute the\nnamespace inside the frame.</p>\n\n<p>Finally, working with an editable document means working with\nselection in arbitrary DOM structures. Internet Explorer (8 and\nbefore) has an utterly different (and awkward) selection API than all\nof the other browsers, and even among the different implementations of\n<code>document.selection</code>, details about how exactly a selection\nis represented vary quite a bit. Add to that the fact that Opera's\nselection support tended to be very buggy until recently, and you can\nimagine why CodeMirror 1 contains 700 lines of selection-handling\ncode.</p>\n\n<p>And that brings us to the main issue with the CodeMirror 1\ncode base: The proportion of browser-bug-workarounds to real\napplication code was getting dangerously high. By building on top of a\nfew dodgy features, I put the system in a vulnerable position—any\nincompatibility and bugginess in these features, I had to paper over\nwith my own code. Not only did I have to do some serious stunt-work to\nget it to work on older browsers (as detailed in the\nprevious <a href=\"http://codemirror.net/story.html\">story</a>), things\nalso kept breaking in newly released versions, requiring me to come up\nwith <em>new</em> scary hacks in order to keep up. This was starting\nto lose its appeal.</p>\n\n<h2 id=\"approach\">General Approach</h2>\n\n<p>What CodeMirror 2 does is try to sidestep most of the hairy hacks\nthat came up in version 1. I owe a lot to the\n<a href=\"http://ace.ajax.org\">ACE</a> editor for inspiration on how to\napproach this.</p>\n\n<p>I absolutely did not want to be completely reliant on key events to\ngenerate my input. Every JavaScript programmer knows that key event\ninformation is horrible and incomplete. Some people (most awesomely\nMihai Bazon with <a href=\"http://ymacs.org\">Ymacs</a>) have been able\nto build more or less functioning editors by directly reading key\nevents, but it takes a lot of work (the kind of never-ending, fragile\nwork I described earlier), and will never be able to properly support\nthings like multi-keystoke international character\ninput. <a href=\"#keymap\" class=\"update\">[see below for caveat]</a></p>\n\n<p>So what I do is focus a hidden textarea, and let the browser\nbelieve that the user is typing into that. What we show to the user is\na DOM structure we built to represent his document. If this is updated\nquickly enough, and shows some kind of believable cursor, it feels\nlike a real text-input control.</p>\n\n<p>Another big win is that this DOM representation does not have to\nspan the whole document. Some CodeMirror 1 users insisted that they\nneeded to put a 30 thousand line XML document into CodeMirror. Putting\nall that into the DOM takes a while, especially since, for some\nreason, an editable DOM tree is slower than a normal one on most\nbrowsers. If we have full control over what we show, we must only\nensure that the visible part of the document has been added, and can\ndo the rest only when needed. (Fortunately, the <code>onscroll</code>\nevent works almost the same on all browsers, and lends itself well to\ndisplaying things only as they are scrolled into view.)</p>\n\n<h2 id=\"input\">Input</h2>\n\n<p>ACE uses its hidden textarea only as a text input shim, and does\nall cursor movement and things like text deletion itself by directly\nhandling key events. CodeMirror's way is to let the browser do its\nthing as much as possible, and not, for example, define its own set of\nkey bindings. One way to do this would have been to have the whole\ndocument inside the hidden textarea, and after each key event update\nthe display DOM to reflect what's in that textarea.</p>\n\n<p>That'd be simple, but it is not realistic. For even medium-sized\ndocument the editor would be constantly munging huge strings, and get\nterribly slow. What CodeMirror 2 does is put the current selection,\nalong with an extra line on the top and on the bottom, into the\ntextarea.</p>\n\n<p>This means that the arrow keys (and their ctrl-variations), home,\nend, etcetera, do not have to be handled specially. We just read the\ncursor position in the textarea, and update our cursor to match it.\nAlso, copy and paste work pretty much for free, and people get their\nnative key bindings, without any special work on my part. For example,\nI have emacs key bindings configured for Chrome and Firefox. There is\nno way for a script to detect this. <a class=\"update\"\nhref=\"#keymap\">[no longer the case]</a></p>\n\n<p>Of course, since only a small part of the document sits in the\ntextarea, keys like page up and ctrl-end won't do the right thing.\nCodeMirror is catching those events and handling them itself.</p>\n\n<h2 id=\"selection\">Selection</h2>\n\n<p>Getting and setting the selection range of a textarea in modern\nbrowsers is trivial—you just use the <code>selectionStart</code>\nand <code>selectionEnd</code> properties. On IE you have to do some\ninsane stuff with temporary ranges and compensating for the fact that\nmoving the selection by a 'character' will treat \\r\\n as a single\ncharacter, but even there it is possible to build functions that\nreliably set and get the selection range.</p>\n\n<p>But consider this typical case: When I'm somewhere in my document,\npress shift, and press the up arrow, something gets selected. Then, if\nI, still holding shift, press the up arrow again, the top of my\nselection is adjusted. The selection remembers where its <em>head</em>\nand its <em>anchor</em> are, and moves the head when we shift-move.\nThis is a generally accepted property of selections, and done right by\nevery editing component built in the past twenty years.</p>\n\n<p>But not something that the browser selection APIs expose.</p>\n\n<p>Great. So when someone creates an 'upside-down' selection, the next\ntime CodeMirror has to update the textarea, it'll re-create the\nselection as an 'upside-up' selection, with the anchor at the top, and\nthe next cursor motion will behave in an unexpected way—our second\nup-arrow press in the example above will not do anything, since it is\ninterpreted in exactly the same way as the first.</p>\n\n<p>No problem. We'll just, ehm, detect that the selection is\nupside-down (you can tell by the way it was created), and then, when\nan upside-down selection is present, and a cursor-moving key is\npressed in combination with shift, we quickly collapse the selection\nin the textarea to its start, allow the key to take effect, and then\ncombine its new head with its old anchor to get the <em>real</em>\nselection.</p>\n\n<p>In short, scary hacks could not be avoided entirely in CodeMirror\n2.</p>\n\n<p>And, the observant reader might ask, how do you even know that a\nkey combo is a cursor-moving combo, if you claim you support any\nnative key bindings? Well, we don't, but we can learn. The editor\nkeeps a set known cursor-movement combos (initialized to the\npredictable defaults), and updates this set when it observes that\npressing a certain key had (only) the effect of moving the cursor.\nThis, of course, doesn't work if the first time the key is used was\nfor extending an inverted selection, but it works most of the\ntime.</p>\n\n<h2 id=\"update\">Intelligent Updating</h2>\n\n<p>One thing that always comes up when you have a complicated internal\nstate that's reflected in some user-visible external representation\n(in this case, the displayed code and the textarea's content) is\nkeeping the two in sync. The naive way is to just update the display\nevery time you change your state, but this is not only error prone\n(you'll forget), it also easily leads to duplicate work on big,\ncomposite operations. Then you start passing around flags indicating\nwhether the display should be updated in an attempt to be efficient\nagain and, well, at that point you might as well give up completely.</p>\n\n<p>I did go down that road, but then switched to a much simpler model:\nsimply keep track of all the things that have been changed during an\naction, and then, only at the end, use this information to update the\nuser-visible display.</p>\n\n<p>CodeMirror uses a concept of <em>operations</em>, which start by\ncalling a specific set-up function that clears the state and end by\ncalling another function that reads this state and does the required\nupdating. Most event handlers, and all the user-visible methods that\nchange state are wrapped like this. There's a method\ncalled <code>operation</code> that accepts a function, and returns\nanother function that wraps the given function as an operation.</p>\n\n<p>It's trivial to extend this (as CodeMirror does) to detect nesting,\nand, when an operation is started inside an operation, simply\nincrement the nesting count, and only do the updating when this count\nreaches zero again.</p>\n\n<p>If we have a set of changed ranges and know the currently shown\nrange, we can (with some awkward code to deal with the fact that\nchanges can add and remove lines, so we're dealing with a changing\ncoordinate system) construct a map of the ranges that were left\nintact. We can then compare this map with the part of the document\nthat's currently visible (based on scroll offset and editor height) to\ndetermine whether something needs to be updated.</p>\n\n<p>CodeMirror uses two update algorithms—a full refresh, where it just\ndiscards the whole part of the DOM that contains the edited text and\nrebuilds it, and a patch algorithm, where it uses the information\nabout changed and intact ranges to update only the out-of-date parts\nof the DOM. When more than 30 percent (which is the current heuristic,\nmight change) of the lines need to be updated, the full refresh is\nchosen (since it's faster to do than painstakingly finding and\nupdating all the changed lines), in the other case it does the\npatching (so that, if you scroll a line or select another character,\nthe whole screen doesn't have to be\nre-rendered). <span class=\"update\">[the full-refresh\nalgorithm was dropped, it wasn't really faster than the patching\none]</span></p>\n\n<p>All updating uses <code>innerHTML</code> rather than direct DOM\nmanipulation, since that still seems to be by far the fastest way to\nbuild documents. There's a per-line function that combines the\nhighlighting, <a href=\"manual.html#markText\">marking</a>, and\nselection info for that line into a snippet of HTML. The patch updater\nuses this to reset individual lines, the refresh updater builds an\nHTML chunk for the whole visible document at once, and then uses a\nsingle <code>innerHTML</code> update to do the refresh.</p>\n\n<h2 id=\"parse\">Parsers can be Simple</h2>\n\n<p>When I wrote CodeMirror 1, I\nthought <a href=\"http://codemirror.net/story.html#parser\">interruptable\nparsers</a> were a hugely scary and complicated thing, and I used a\nbunch of heavyweight abstractions to keep this supposed complexity\nunder control: parsers\nwere <a href=\"http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/\">iterators</a>\nthat consumed input from another iterator, and used funny\nclosure-resetting tricks to copy and resume themselves.</p>\n\n<p>This made for a rather nice system, in that parsers formed strictly\nseparate modules, and could be composed in predictable ways.\nUnfortunately, it was quite slow (stacking three or four iterators on\ntop of each other), and extremely intimidating to people not used to a\nfunctional programming style.</p>\n\n<p>With a few small changes, however, we can keep all those\nadvantages, but simplify the API and make the whole thing less\nindirect and inefficient. CodeMirror\n2's <a href=\"manual.html#modeapi\">mode API</a> uses explicit state\nobjects, and makes the parser/tokenizer a function that simply takes a\nstate and a character stream abstraction, advances the stream one\ntoken, and returns the way the token should be styled. This state may\nbe copied, optionally in a mode-defined way, in order to be able to\ncontinue a parse at a given point. Even someone who's never touched a\nlambda in his life can understand this approach. Additionally, far\nfewer objects are allocated in the course of parsing now.</p>\n\n<p>The biggest speedup comes from the fact that the parsing no longer\nhas to touch the DOM though. In CodeMirror 1, on an older browser, you\ncould <em>see</em> the parser work its way through the document,\nmanaging some twenty lines in each 50-millisecond time slice it got. It\nwas reading its input from the DOM, and updating the DOM as it went\nalong, which any experienced JavaScript programmer will immediately\nspot as a recipe for slowness. In CodeMirror 2, the parser usually\nfinishes the whole document in a single 100-millisecond time slice—it\nmanages some 1500 lines during that time on Chrome. All it has to do\nis munge strings, so there is no real reason for it to be slow\nanymore.</p>\n\n<h2 id=\"summary\">What Gives?</h2>\n\n<p>Given all this, what can you expect from CodeMirror 2?</p>\n\n<ul>\n\n<li><strong>Small.</strong> the base library is\nsome <span class=\"update\">45k</span> when minified\nnow, <span class=\"update\">17k</span> when gzipped. It's smaller than\nits own logo.</li>\n\n<li><strong>Lightweight.</strong> CodeMirror 2 initializes very\nquickly, and does almost no work when it is not focused. This means\nyou can treat it almost like a textarea, have multiple instances on a\npage without trouble.</li>\n\n<li><strong>Huge document support.</strong> Since highlighting is\nreally fast, and no DOM structure is being built for non-visible\ncontent, you don't have to worry about locking up your browser when a\nuser enters a megabyte-sized document.</li>\n\n<li><strong>Extended API.</strong> Some things kept coming up in the\nmailing list, such as marking pieces of text or lines, which were\nextremely hard to do with CodeMirror 1. The new version has proper\nsupport for these built in.</li>\n\n<li><strong>Tab support.</strong> Tabs inside editable documents were,\nfor some reason, a no-go. At least six different people announced they\nwere going to add tab support to CodeMirror 1, none survived (I mean,\nnone delivered a working version). CodeMirror 2 no longer removes tabs\nfrom your document.</li>\n\n<li><strong>Sane styling.</strong> <code>iframe</code> nodes aren't\nreally known for respecting document flow. Now that an editor instance\nis a plain <code>div</code> element, it is much easier to size it to\nfit the surrounding elements. You don't even have to make it scroll if\nyou do not <a href=\"../demo/resize.html\">want to</a>.</li>\n\n</ul>\n\n<p>On the downside, a CodeMirror 2 instance is <em>not</em> a native\neditable component. Though it does its best to emulate such a\ncomponent as much as possible, there is functionality that browsers\njust do not allow us to hook into. Doing select-all from the context\nmenu, for example, is not currently detected by CodeMirror.</p>\n\n<p id=\"changes\" style=\"margin-top: 2em;\"><span style=\"font-weight:\nbold\">[Updates from November 13th 2011]</span> Recently, I've made\nsome changes to the codebase that cause some of the text above to no\nlonger be current. I've left the text intact, but added markers at the\npassages that are now inaccurate. The new situation is described\nbelow.</p>\n\n<h2 id=\"btree\">Content Representation</h2>\n\n<p>The original implementation of CodeMirror 2 represented the\ndocument as a flat array of line objects. This worked well—splicing\narrays will require the part of the array after the splice to be\nmoved, but this is basically just a simple <code>memmove</code> of a\nbunch of pointers, so it is cheap even for huge documents.</p>\n\n<p>However, I recently added line wrapping and code folding (line\ncollapsing, basically). Once lines start taking up a non-constant\namount of vertical space, looking up a line by vertical position\n(which is needed when someone clicks the document, and to determine\nthe visible part of the document during scrolling) can only be done\nwith a linear scan through the whole array, summing up line heights as\nyou go. Seeing how I've been going out of my way to make big documents\nfast, this is not acceptable.</p>\n\n<p>The new representation is based on a B-tree. The leaves of the tree\ncontain arrays of line objects, with a fixed minimum and maximum size,\nand the non-leaf nodes simply hold arrays of child nodes. Each node\nstores both the amount of lines that live below them and the vertical\nspace taken up by these lines. This allows the tree to be indexed both\nby line number and by vertical position, and all access has\nlogarithmic complexity in relation to the document size.</p>\n\n<p>I gave line objects and tree nodes parent pointers, to the node\nabove them. When a line has to update its height, it can simply walk\nthese pointers to the top of the tree, adding or subtracting the\ndifference in height from each node it encounters. The parent pointers\nalso make it cheaper (in complexity terms, the difference is probably\ntiny in normal-sized documents) to find the current line number when\ngiven a line object. In the old approach, the whole document array had\nto be searched. Now, we can just walk up the tree and count the sizes\nof the nodes coming before us at each level.</p>\n\n<p>I chose B-trees, not regular binary trees, mostly because they\nallow for very fast bulk insertions and deletions. When there is a big\nchange to a document, it typically involves adding, deleting, or\nreplacing a chunk of subsequent lines. In a regular balanced tree, all\nthese inserts or deletes would have to be done separately, which could\nbe really expensive. In a B-tree, to insert a chunk, you just walk\ndown the tree once to find where it should go, insert them all in one\nshot, and then break up the node if needed. This breaking up might\ninvolve breaking up nodes further up, but only requires a single pass\nback up the tree. For deletion, I'm somewhat lax in keeping things\nbalanced—I just collapse nodes into a leaf when their child count goes\nbelow a given number. This means that there are some weird editing\npatterns that may result in a seriously unbalanced tree, but even such\nan unbalanced tree will perform well, unless you spend a day making\nstrangely repeating edits to a really big document.</p>\n\n<h2 id=\"keymap\">Keymaps</h2>\n\n<p><a href=\"#approach\">Above</a>, I claimed that directly catching key\nevents for things like cursor movement is impractical because it\nrequires some browser-specific kludges. I then proceeded to explain\nsome awful <a href=\"#selection\">hacks</a> that were needed to make it\npossible for the selection changes to be detected through the\ntextarea. In fact, the second hack is about as bad as the first.</p>\n\n<p>On top of that, in the presence of user-configurable tab sizes and\ncollapsed and wrapped lines, lining up cursor movement in the textarea\nwith what's visible on the screen becomes a nightmare. Thus, I've\ndecided to move to a model where the textarea's selection is no longer\ndepended on.</p>\n\n<p>So I moved to a model where all cursor movement is handled by my\nown code. This adds support for a goal column, proper interaction of\ncursor movement with collapsed lines, and makes it possible for\nvertical movement to move through wrapped lines properly, instead of\njust treating them like non-wrapped lines.</p>\n\n<p>The key event handlers now translate the key event into a string,\nsomething like <code>Ctrl-Home</code> or <code>Shift-Cmd-R</code>, and\nuse that string to look up an action to perform. To make keybinding\ncustomizable, this lookup goes through\na <a href=\"manual.html#option_keyMap\">table</a>, using a scheme that\nallows such tables to be chained together (for example, the default\nMac bindings fall through to a table named 'emacsy', which defines\nbasic Emacs-style bindings like <code>Ctrl-F</code>, and which is also\nused by the custom Emacs bindings).</p>\n\n<p>A new\noption <a href=\"manual.html#option_extraKeys\"><code>extraKeys</code></a>\nallows ad-hoc keybindings to be defined in a much nicer way than what\nwas possible with the\nold <a href=\"manual.html#option_onKeyEvent\"><code>onKeyEvent</code></a>\ncallback. You simply provide an object mapping key identifiers to\nfunctions, instead of painstakingly looking at raw key events.</p>\n\n<p>Built-in commands map to strings, rather than functions, for\nexample <code>\"goLineUp\"</code> is the default action bound to the up\narrow key. This allows new keymaps to refer to them without\nduplicating any code. New commands can be defined by assigning to\nthe <code>CodeMirror.commands</code> object, which maps such commands\nto functions.</p>\n\n<p>The hidden textarea now only holds the current selection, with no\nextra characters around it. This has a nice advantage: polling for\ninput becomes much, much faster. If there's a big selection, this text\ndoes not have to be read from the textarea every time—when we poll,\njust noticing that something is still selected is enough to tell us\nthat no new text was typed.</p>\n\n<p>The reason that cheap polling is important is that many browsers do\nnot fire useful events on IME (input method engine) input, which is\nthe thing where people inputting a language like Japanese or Chinese\nuse multiple keystrokes to create a character or sequence of\ncharacters. Most modern browsers fire <code>input</code> when the\ncomposing is finished, but many don't fire anything when the character\nis updated <em>during</em> composition. So we poll, whenever the\neditor is focused, to provide immediate updates of the display.</p>\n\n</div><div class=\"rightsmall blk\">\n\n    <h2>Contents</h2>\n\n    <ul>\n      <li><a href=\"#intro\">Introduction</a></li>\n      <li><a href=\"#approach\">General Approach</a></li>\n      <li><a href=\"#input\">Input</a></li>\n      <li><a href=\"#selection\">Selection</a></li>\n      <li><a href=\"#update\">Intelligent Updating</a></li>\n      <li><a href=\"#parse\">Parsing</a></li>\n      <li><a href=\"#summary\">What Gives?</a></li>\n      <li><a href=\"#btree\">Content Representation</a></li>\n      <li><a href=\"#keymap\">Key Maps</a></li>\n    </ul>\n\n</div></div>\n\n<div style=\"height: 2em\">&nbsp;</div>\n\n</body></html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/doc/manual.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: User Manual</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans:bold\"/>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"docs.css\"/>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n    <style>dl dl {margin: 0;}</style>\n  </head>\n  <body>\n\n<h1><span class=\"logo-braces\">{ }</span> <a href=\"http://codemirror.net/\">CodeMirror</a></h1>\n\n<pre class=\"grey\">\n<img src=\"baboon.png\" class=\"logo\" alt=\"logo\"/>/* User manual and\n   reference guide */\n</pre>\n\n<div class=\"clear\"><div class=\"leftbig blk\">\n\n    <h2 id=\"overview\">Overview</h2>\n\n    <p>CodeMirror is a code-editor component that can be embedded in\n    Web pages. The code library provides <em>only</em> the editor\n    component, no accompanying buttons, auto-completion, or other IDE\n    functionality. It does provide a rich API on top of which such\n    functionality can be straightforwardly implemented. See\n    the <a href=\"#addons\">add-ons</a> included in the distribution,\n    and\n    the <a href=\"https://github.com/jagthedrummer/codemirror-ui\">CodeMirror\n    UI</a> project, for reusable implementations of extra features.</p>\n\n    <p>CodeMirror works with language-specific modes. Modes are\n    JavaScript programs that help color (and optionally indent) text\n    written in a given language. The distribution comes with a number\n    of modes (see the <code>mode/</code> directory), and it isn't hard\n    to <a href=\"#modeapi\">write new ones</a> for other languages.</p>\n\n    <h2 id=\"usage\">Basic Usage</h2>\n\n    <p>The easiest way to use CodeMirror is to simply load the script\n    and style sheet found under <code>lib/</code> in the distribution,\n    plus a mode script from one of the <code>mode/</code> directories\n    and a theme stylesheet from <code>theme/</code>. (See\n    also <a href=\"compress.html\">the compression helper</a>.) For\n    example:</p>\n\n    <pre>&lt;script src=\"lib/codemirror.js\">&lt;/script>\n&lt;link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n&lt;script src=\"mode/javascript/javascript.js\">&lt;/script></pre>\n\n    <p>Having done this, an editor instance can be created like\n    this:</p>\n\n    <pre>var myCodeMirror = CodeMirror(document.body);</pre>\n\n    <p>The editor will be appended to the document body, will start\n    empty, and will use the mode that we loaded. To have more control\n    over the new editor, a configuration object can be passed\n    to <code>CodeMirror</code> as a second argument:</p>\n\n    <pre>var myCodeMirror = CodeMirror(document.body, {\n  value: \"function myScript(){return 100;}\\n\",\n  mode:  \"javascript\"\n});</pre>\n\n    <p>This will initialize the editor with a piece of code already in\n    it, and explicitly tell it to use the JavaScript mode (which is\n    useful when multiple modes are loaded).\n    See <a href=\"#config\">below</a> for a full discussion of the\n    configuration options that CodeMirror accepts.</p>\n\n    <p>In cases where you don't want to append the editor to an\n    element, and need more control over the way it is inserted, the\n    first argument to the <code>CodeMirror</code> function can also\n    be a function that, when given a DOM element, inserts it into the\n    document somewhere. This could be used to, for example, replace a\n    textarea with a real editor:</p>\n\n    <pre>var myCodeMirror = CodeMirror(function(elt) {\n  myTextArea.parentNode.replaceChild(elt, myTextArea);\n}, {value: myTextArea.value});</pre>\n\n    <p>However, for this use case, which is a common way to use\n    CodeMirror, the library provides a much more powerful\n    shortcut:</p>\n\n    <pre>var myCodeMirror = CodeMirror.fromTextArea(myTextArea);</pre>\n\n    <p>This will, among other things, ensure that the textarea's value\n    is updated when the form (if it is part of a form) is submitted.\n    See the <a href=\"#fromTextArea\">API reference</a> for a full\n    description of this method.</p>\n\n    <h2 id=\"config\">Configuration</h2>\n\n    <p>Both the <code>CodeMirror</code> function and\n    its <code>fromTextArea</code> method take as second (optional)\n    argument an object containing configuration options. Any option\n    not supplied like this will be taken\n    from <code>CodeMirror.defaults</code>, an object containing the\n    default options. You can update this object to change the defaults\n    on your page.</p>\n\n    <p>Options are not checked in any way, so setting bogus option\n    values is bound to lead to odd errors.</p>\n\n    <p>These are the supported options:</p>\n\n    <dl>\n      <dt id=\"option_value\"><code>value (string)</code></dt>\n      <dd>The starting value of the editor.</dd>\n\n      <dt id=\"option_mode\"><code>mode (string or object)</code></dt>\n      <dd>The mode to use. When not given, this will default to the\n      first mode that was loaded. It may be a string, which either\n      simply names the mode or is\n      a <a href=\"http://en.wikipedia.org/wiki/MIME\">MIME</a> type\n      associated with the mode. Alternatively, it may be an object\n      containing configuration options for the mode, with\n      a <code>name</code> property that names the mode (for\n      example <code>{name: \"javascript\", json: true}</code>). The demo\n      pages for each mode contain information about what configuration\n      parameters the mode supports. You can ask CodeMirror which modes\n      and MIME types are loaded with\n      the <code>CodeMirror.listModes</code>\n      and <code>CodeMirror.listMIMEs</code> functions.</dd>\n\n      <dt id=\"option_theme\"><code>theme (string)</code></dt>\n      <dd>The theme to style the editor with. You must make sure the\n      CSS file defining the corresponding <code>.cm-s-[name]</code>\n      styles is loaded (see\n      the <a href=\"../theme/\"><code>theme</code></a> directory in the\n      distribution). The default is <code>\"default\"</code>, for which\n      colors are included in <code>codemirror.css</code>. It is\n      possible to use multiple theming classes at once—for\n      example <code>\"foo bar\"</code> will assign both\n      the <code>cm-s-foo</code> and the <code>cm-s-bar</code> classes\n      to the editor.</dd>\n\n      <dt id=\"option_indentUnit\"><code>indentUnit (integer)</code></dt>\n      <dd>How many spaces a block (whatever that means in the edited\n      language) should be indented. The default is 2.</dd>\n\n      <dt id=\"option_smartIndent\"><code>smartIndent (boolean)</code></dt>\n      <dd>Whether to use the context-sensitive indentation that the\n      mode provides (or just indent the same as the line before).\n      Defaults to true.</dd>\n\n      <dt id=\"option_tabSize\"><code>tabSize (integer)</code></dt>\n      <dd>The width of a tab character. Defaults to 4.</dd>\n\n      <dt id=\"option_indentWithTabs\"><code>indentWithTabs (boolean)</code></dt>\n      <dd>Whether, when indenting, the first N*<code>tabSize</code>\n      spaces should be replaced by N tabs. Default is false.</dd>\n\n      <dt id=\"option_electricChars\"><code>electricChars (boolean)</code></dt>\n      <dd>Configures whether the editor should re-indent the current\n      line when a character is typed that might change its proper\n      indentation (only works if the mode supports indentation).\n      Default is true.</dd>\n\n      <dt id=\"option_autoClearEmptyLines\"><code>autoClearEmptyLines (boolean)</code></dt>\n      <dd>When turned on (default is off), this will clear\n      automatically clear lines consisting only of whitespace when the\n      cursor leaves them. This is mostly useful to prevent auto\n      indentation from introducing trailing whitespace in a file.</dd>\n\n      <dt id=\"option_keyMap\"><code>keyMap (string)</code></dt>\n      <dd>Configures the keymap to use. The default\n      is <code>\"default\"</code>, which is the only keymap defined\n      in <code>codemirror.js</code> itself. Extra keymaps are found in\n      the <a href=\"../keymap/\"><code>keymap</code></a> directory. See\n      the <a href=\"#keymaps\">section on keymaps</a> for more\n      information.</dd>\n\n      <dt id=\"option_extraKeys\"><code>extraKeys (object)</code></dt>\n      <dd>Can be used to specify extra keybindings for the editor,\n      alongside the ones defined\n      by <a href=\"#option_keyMap\"><code>keyMap</code></a>. Should be\n      either null, or a valid <a href=\"#keymaps\">keymap</a> value.</dd>\n\n      <dt id=\"option_lineWrapping\"><code>lineWrapping (boolean)</code></dt>\n      <dd>Whether CodeMirror should scroll or wrap for long lines.\n      Defaults to <code>false</code> (scroll).</dd>\n\n      <dt id=\"option_lineNumbers\"><code>lineNumbers (boolean)</code></dt>\n      <dd>Whether to show line numbers to the left of the editor.</dd>\n\n      <dt id=\"option_firstLineNumber\"><code>firstLineNumber (integer)</code></dt>\n      <dd>At which number to start counting lines. Default is 1.</dd>\n\n      <dt id=\"option_gutter\"><code>gutter (boolean)</code></dt>\n      <dd>Can be used to force a 'gutter' (empty space on the left of\n      the editor) to be shown even when no line numbers are active.\n      This is useful for setting <a href=\"#setMarker\">markers</a>.</dd>\n\n      <dt id=\"option_fixedGutter\"><code>fixedGutter (boolean)</code></dt>\n      <dd>When enabled (off by default), this will make the gutter\n      stay visible when the document is scrolled horizontally.</dd>\n\n      <dt id=\"option_readOnly\"><code>readOnly (boolean)</code></dt>\n      <dd>This disables editing of the editor content by the user. If\n      the special value <code>\"nocursor\"</code> is given (instead of\n      simply <code>true</code>), focusing of the editor is also\n      disallowed.</dd>\n\n      <dt id=\"option_onChange\"><code>onChange (function)</code></dt>\n      <dd>When given, this function will be called every time the\n      content of the editor is changed. It will be given the editor\n      instance as first argument, and an <code>{from, to, text, next}</code>\n      object containing information about the changes\n      that occurred as second argument. <code>from</code>\n      and <code>to</code> are the positions (in the pre-change\n      coordinate system) where the change started and\n      ended (for example, it might be <code>{ch:0, line:18}</code> if the\n      position is at the beginning of line #19). <code>text</code>\n      is an array of strings representing the text that replaced the changed\n      range (split by line). If multiple changes happened during a single\n      operation, the object will have a <code>next</code> property pointing to\n      another change object (which may point to another, etc).</dd>\n\n      <dt id=\"option_onCursorActivity\"><code>onCursorActivity (function)</code></dt>\n      <dd>Will be called when the cursor or selection moves, or any\n      change is made to the editor content.</dd>\n\n      <dt id=\"option_onGutterClick\"><code>onGutterClick (function)</code></dt>\n      <dd>When given, will be called whenever the editor gutter (the\n      line-number area) is clicked. Will be given the editor instance\n      as first argument, the (zero-based) number of the line that was\n      clicked as second argument, and the raw <code>mousedown</code>\n      event object as third argument.</dd>\n\n      <dt id=\"option_onFocus\"><code>onFocus, onBlur (function)</code></dt>\n      <dd>The given functions will be called whenever the editor is\n      focused or unfocused.</dd>\n\n      <dt id=\"option_onScroll\"><code>onScroll (function)</code></dt>\n      <dd>When given, will be called whenever the editor is\n      scrolled.</dd>\n\n      <dt id=\"option_onHighlightComplete\"><code>onHighlightComplete (function)</code></dt>\n      <dd>Whenever the editor's content has been fully highlighted,\n      this function (if given) will be called. It'll be given a single\n      argument, the editor instance.</dd>\n\n      <dt id=\"option_onUpdate\"><code>onUpdate (function)</code></dt>\n      <dd>Will be called whenever CodeMirror updates its DOM display.</dd>\n\n      <dt id=\"option_matchBrackets\"><code>matchBrackets (boolean)</code></dt>\n      <dd>Determines whether brackets are matched whenever the cursor\n      is moved next to a bracket.</dd>\n\n      <dt id=\"option_workTime\"><code>workTime, workDelay (number)</code></dt>\n      <dd>Highlighting is done by a pseudo background-thread that will\n      work for <code>workTime</code> milliseconds, and then use\n      timeout to sleep for <code>workDelay</code> milliseconds. The\n      defaults are 200 and 300, you can change these options to make\n      the highlighting more or less aggressive.</dd>\n\n      <dt id=\"option_pollInterval\"><code>pollInterval (number)</code></dt>\n      <dd>Indicates how quickly CodeMirror should poll its input\n      textarea for changes. Most input is captured by events, but some\n      things, like IME input on some browsers, doesn't generate events\n      that allow CodeMirror to properly detect it. Thus, it polls.\n      Default is 100 milliseconds.</dd>\n\n      <dt id=\"option_undoDepth\"><code>undoDepth (integer)</code></dt>\n      <dd>The maximum number of undo levels that the editor stores.\n      Defaults to 40.</dd>\n\n      <dt id=\"option_tabindex\"><code>tabindex (integer)</code></dt>\n      <dd>The <a href=\"http://www.w3.org/TR/html401/interact/forms.html#adef-tabindex\">tab\n      index</a> to assign to the editor. If not given, no tab index\n      will be assigned.</dd>\n\n      <dt id=\"option_autofocus\"><code>autofocus (boolean)</code></dt>\n      <dd>Can be used to make CodeMirror focus itself on\n      initialization. Defaults to off.\n      When <a href=\"#fromTextArea\"><code>fromTextArea</code></a> is\n      used, and no explicit value is given for this option, it will\n      inherit the setting from the textarea's <code>autofocus</code>\n      attribute.</dd>\n\n      <dt id=\"option_dragDrop\"><code>dragDrop (boolean)</code></dt>\n      <dd>Controls whether drag-and-drop is enabled. On by default.</dd>\n\n      <dt id=\"option_onDragEvent\"><code>onDragEvent (function)</code></dt>\n      <dd>When given, this will be called when the editor is handling\n      a <code>dragenter</code>, <code>dragover</code>,\n      or <code>drop</code> event. It will be passed the editor instance\n      and the event object as arguments. The callback can choose to\n      handle the event itself, in which case it should\n      return <code>true</code> to indicate that CodeMirror should not\n      do anything further.</dd>\n\n      <dt id=\"option_onKeyEvent\"><code>onKeyEvent (function)</code></dt>\n      <dd>This provides a rather low-level hook into CodeMirror's key\n      handling. If provided, this function will be called on\n      every <code>keydown</code>, <code>keyup</code>,\n      and <code>keypress</code> event that CodeMirror captures. It\n      will be passed two arguments, the editor instance and the key\n      event. This key event is pretty much the raw key event, except\n      that a <code>stop()</code> method is always added to it. You\n      could feed it to, for example, <code>jQuery.Event</code> to\n      further normalize it.<br>This function can inspect the key\n      event, and handle it if it wants to. It may return true to tell\n      CodeMirror to ignore the event. Be wary that, on some browsers,\n      stopping a <code>keydown</code> does not stop\n      the <code>keypress</code> from firing, whereas on others it\n      does. If you respond to an event, you should probably inspect\n      its <code>type</code> property and only do something when it\n      is <code>keydown</code> (or <code>keypress</code> for actions\n      that need character data).</dd>\n    </dl>\n\n    <h2 id=\"keymaps\">Keymaps</h2>\n\n    <p>Keymaps are ways to associate keys with functionality. A keymap\n    is an object mapping strings that identify the keys to functions\n    that implement their functionality.</p>\n\n    <p>Keys are identified either by name or by character.\n    The <code>CodeMirror.keyNames</code> object defines names for\n    common keys and associates them with their key codes. Examples of\n    names defined here are <code>Enter</code>, <code>F5</code>,\n    and <code>Q</code>. These can be prefixed\n    with <code>Shift-</code>, <code>Cmd-</code>, <code>Ctrl-</code>,\n    and <code>Alt-</code> (in that order!) to specify a modifier. So\n    for example, <code>Shift-Ctrl-Space</code> would be a valid key\n    identifier.</p>\n\n    <p>Alternatively, a character can be specified directly by\n    surrounding it in single quotes, for example <code>'$'</code>\n    or <code>'q'</code>. Due to limitations in the way browsers fire\n    key events, these may not be prefixed with modifiers.</p>\n\n    <p>The <code>CodeMirror.keyMap</code> object associates keymaps\n    with names. User code and keymap definitions can assign extra\n    properties to this object. Anywhere where a keymap is expected, a\n    string can be given, which will be looked up in this object. It\n    also contains the <code>\"default\"</code> keymap holding the\n    default bindings.</p>\n\n    <p>The values of properties in keymaps can be either functions of\n    a single argument (the CodeMirror instance), or strings. Such\n    strings refer to properties of the\n    <code>CodeMirror.commands</code> object, which defines a number of\n    common commands that are used by the default keybindings, and maps\n    them to functions. A key handler function may throw\n    <code>CodeMirror.Pass</code> to indicate that it has decided not\n    to handle the key, and other handlers (or the default behavior)\n    should be given a turn.</p>\n\n    <p>Keys mapped to command names that start with the\n    characters <code>\"go\"</code> (which should be used for\n    cursor-movement actions) will be fired even when an\n    extra <code>Shift</code> modifier is present (i.e. <code>\"Up\":\n    \"goLineUp\"</code> matches both up and shift-up). This is used to\n    easily implement shift-selection.</p>\n\n    <p>Keymaps can defer to each other by defining\n    a <code>fallthrough</code> property. This indicates that when a\n    key is not found in the map itself, one or more other maps should\n    be searched. It can hold either a single keymap or an array of\n    keymaps.</p>\n\n    <p>When a keymap contains a <code>nofallthrough</code> property\n    set to <code>true</code>, keys matched against that map will be\n    ignored if they don't match any of the bindings in the map (no\n    further child maps will be tried, and the default effect of\n    inserting a character will not occur).</p>\n\n    <h2 id=\"styling\">Customized Styling</h2>\n\n    <p>Up to a certain extent, CodeMirror's look can be changed by\n    modifying style sheet files. The style sheets supplied by modes\n    simply provide the colors for that mode, and can be adapted in a\n    very straightforward way. To style the editor itself, it is\n    possible to alter or override the styles defined\n    in <a href=\"../lib/codemirror.css\"><code>codemirror.css</code></a>.</p>\n\n    <p>Some care must be taken there, since a lot of the rules in this\n    file are necessary to have CodeMirror function properly. Adjusting\n    colors should be safe, of course, and with some care a lot of\n    other things can be changed as well. The CSS classes defined in\n    this file serve the following roles:</p>\n\n    <dl>\n      <dt id=\"class_CodeMirror\"><code>CodeMirror</code></dt>\n      <dd>The outer element of the editor. This should be used for\n      borders and positioning. Can also be used to set styles that\n      should hold for everything inside the editor (such as font\n      and font size), or to set a background.</dd>\n\n      <dt id=\"class_CodeMirror_scroll\"><code>CodeMirror-scroll</code></dt>\n      <dd>This determines whether the editor scrolls (<code>overflow:\n      auto</code> + fixed height). By default, it does. Giving\n      this <code>height: auto; overflow: visible;</code> will cause\n      the editor to resize to fit its content.</dd>\n\n      <dt id=\"class_CodeMirror_focused\"><code>CodeMirror-focused</code></dt>\n      <dd>Whenever the editor is focused, the top element gets this\n      class. This is used to hide the cursor and give the selection a\n      different color when the editor is not focused.</dd>\n\n      <dt id=\"class_CodeMirror_gutter\"><code>CodeMirror-gutter</code></dt>\n      <dd>Use this for giving a background or a border to the editor\n      gutter. Don't set any padding here,\n      use <code>CodeMirror-gutter-text</code> for that. By default,\n      the gutter is 'fluid', meaning it will adjust its width to the\n      maximum line number or line marker width. You can also set a\n      fixed width if you want.</dd>\n\n      <dt id=\"class_CodeMirror_gutter_text\"><code>CodeMirror-gutter-text</code></dt>\n      <dd>Used to style the actual line numbers. For the numbers to\n      line up, you must make sure that the font in the gutter is the\n      same as the one in the rest of the editor, so you should\n      probably only set font style and size in\n      the <code>CodeMirror</code> class.</dd>\n\n      <dt id=\"class_CodeMirror_lines\"><code>CodeMirror-lines</code></dt>\n      <dd>The visible lines. If this has vertical\n      padding, <code>CodeMirror-gutter</code> should have the same\n      padding.</dd>\n\n      <dt id=\"class_CodeMirror_cursor\"><code>CodeMirror-cursor</code></dt>\n      <dd>The cursor is a block element that is absolutely positioned.\n      You can make it look whichever way you want.</dd>\n\n      <dt id=\"class_CodeMirror_selected\"><code>CodeMirror-selected</code></dt>\n      <dd>The selection is represented by <code>span</code> elements\n      with this class.</dd>\n\n      <dt id=\"class_CodeMirror_matchingbracket\"><code>CodeMirror-matchingbracket</code>,\n        <code>CodeMirror-nonmatchingbracket</code></dt>\n      <dd>These are used to style matched (or unmatched) brackets.</dd>\n    </dl>\n\n    <p>The actual lines, as well as the cursor, are represented\n    by <code>pre</code> elements. By default no text styling (such as\n    bold) that might change line height is applied. If you do want\n    such effects, you'll have to give <code>CodeMirror pre</code> a\n    fixed height. Also, you must still take care that character width\n    is constant.</p>\n\n    <p>If your page's style sheets do funky things to\n    all <code>div</code> or <code>pre</code> elements (you probably\n    shouldn't do that), you'll have to define rules to cancel these\n    effects out again for elements under the <code>CodeMirror</code>\n    class.</p>\n\n    <p>Themes are also simply CSS files, which define colors for\n    various syntactic elements. See the files in\n    the <a href=\"../theme/\"><code>theme</code></a> directory.</p>\n\n    <h2 id=\"api\">Programming API</h2>\n\n    <p>A lot of CodeMirror features are only available through its API.\n    This has the disadvantage that you need to do work to enable them,\n    and the advantage that CodeMirror will fit seamlessly into your\n    application.</p>\n\n    <p>Whenever points in the document are represented, the API uses\n    objects with <code>line</code> and <code>ch</code> properties.\n    Both are zero-based. CodeMirror makes sure to 'clip' any positions\n    passed by client code so that they fit inside the document, so you\n    shouldn't worry too much about sanitizing your coordinates. If you\n    give <code>ch</code> a value of <code>null</code>, or don't\n    specify it, it will be replaced with the length of the specified\n    line.</p>\n\n    <dl>\n      <dt id=\"getValue\"><code>getValue() → string</code></dt>\n      <dd>Get the current editor content.</dd>\n      <dt id=\"setValue\"><code>setValue(string)</code></dt>\n      <dd>Set the editor content.</dd>\n\n      <dt id=\"getSelection\"><code>getSelection() → string</code></dt>\n      <dd>Get the currently selected code.</dd>\n      <dt id=\"replaceSelection\"><code>replaceSelection(string)</code></dt>\n      <dd>Replace the selection with the given string.</dd>\n\n      <dt id=\"focus\"><code>focus()</code></dt>\n      <dd>Give the editor focus.</dd>\n      <dt id=\"scrollTo\"><code>scrollTo(x, y)</code></dt>\n      <dd>Scroll the editor to a given (pixel) position. Both\n      arguments may be left as <code>null</code>\n      or <code>undefined</code> to have no effect.</dd>\n\n      <dt id=\"setOption\"><code>setOption(option, value)</code></dt>\n      <dd>Change the configuration of the editor. <code>option</code>\n      should the name of an <a href=\"#config\">option</a>,\n      and <code>value</code> should be a valid value for that\n      option.</dd>\n      <dt id=\"getOption\"><code>getOption(option) → value</code></dt>\n      <dd>Retrieves the current value of the given option for this\n      editor instance.</dd>\n\n      <dt id=\"cursorCoords\"><code>cursorCoords(start, mode) → object</code></dt>\n      <dd>Returns an <code>{x, y, yBot}</code> object containing the\n      coordinates of the cursor. If <code>mode</code>\n      is <code>\"local\"</code>, they will be relative to the top-left\n      corner of the editable document. If it is <code>\"page\"</code> or\n      not given, they are relative to the top-left corner of the\n      page. <code>yBot</code> is the coordinate of the bottom of the\n      cursor. <code>start</code> is a boolean indicating whether you\n      want the start or the end of the selection.</dd>\n      <dt id=\"charCoords\"><code>charCoords(pos, mode) → object</code></dt>\n      <dd>Like <code>cursorCoords</code>, but returns the position of\n      an arbitrary characters. <code>pos</code> should be\n      a <code>{line, ch}</code> object.</dd>\n      <dt id=\"coordsChar\"><code>coordsChar(object) → pos</code></dt>\n      <dd>Given an <code>{x, y}</code> object (in page coordinates),\n      returns the <code>{line, ch}</code> position that corresponds to\n      it.</dd>\n\n      <dt id=\"undo\"><code>undo()</code></dt>\n      <dd>Undo one edit (if any undo events are stored).</dd>\n      <dt id=\"redo\"><code>redo()</code></dt>\n      <dd>Redo one undone edit.</dd>\n      <dt id=\"historySize\"><code>historySize() → object</code></dt>\n      <dd>Returns an object with <code>{undo, redo}</code> properties,\n      both of which hold integers, indicating the amount of stored\n      undo and redo operations.</dd>\n      <dt id=\"clearHistory\"><code>clearHistory()</code></dt>\n      <dd>Clears the editor's undo history.</dd>\n\n      <dt id=\"indentLine\"><code>indentLine(line, dir)</code></dt>\n      <dd>Reset the given line's indentation to the indentation\n      prescribed by the mode. If the second argument is given,\n      indentation will be increased (if <code>dir</code> is true) or\n      decreased (if false) by an <a href=\"#option_indentUnit\">indent\n      unit</a> instead.</dd>\n\n      <dt id=\"getTokenAt\"><code>getTokenAt(pos) → object</code></dt>\n      <dd>Retrieves information about the token the current mode found\n      at the given position (a <code>{line, ch}</code> object). The\n      returned object has the following properties:\n      <dl>\n        <dt><code>start</code></dt><dd>The character (on the given line) at which the token starts.</dd>\n        <dt><code>end</code></dt><dd>The character at which the token ends.</dd>\n        <dt><code>string</code></dt><dd>The token's string.</dd>\n        <dt><code>className</code></dt><dd>The class the mode assigned\n        to the token. (Can be null when no class was assigned.)</dd>\n        <dt><code>state</code></dt><dd>The mode's state at the end of this token.</dd>\n      </dl></dd>\n\n      <dt id=\"markText\"><code>markText(from, to, className) → object</code></dt>\n      <dd>Can be used to mark a range of text with a specific CSS\n      class name. <code>from</code> and <code>to</code> should\n      be <code>{line, ch}</code> objects. The method will return an\n      object with two methods, <code>clear()</code>, which removes the\n      mark, and <code>find()</code>, which returns a <code>{from,\n      to}</code> (both document positions), indicating the current\n      position of the marked range.</dd>\n\n      <dt id=\"setBookmark\"><code>setBookmark(pos) → object</code></dt>\n      <dd>Inserts a bookmark, a handle that follows the text around it\n      as it is being edited, at the given position. A bookmark has two\n      methods <code>find()</code> and <code>clear()</code>. The first\n      returns the current position of the bookmark, if it is still in\n      the document, and the second explicitly removes the\n      bookmark.</dd>\n\n      <dt id=\"findMarksAt\"><code>findMarksAt(pos) → array</code></dt>\n      <dd>Returns an array of all the bookmarks and marked ranges\n      present at the given position.</dd>\n\n      <dt id=\"setMarker\"><code>setMarker(line, text, className) → lineHandle</code></dt>\n      <dd>Add a gutter marker for the given line. Gutter markers are\n      shown in the line-number area (instead of the number for this\n      line). Both <code>text</code> and <code>className</code> are\n      optional. Setting <code>text</code> to a Unicode character like\n      ● tends to give a nice effect. To put a picture in the gutter,\n      set <code>text</code> to a space and <code>className</code> to\n      something that sets a background image. If you\n      specify <code>text</code>, the given text (which may contain\n      HTML) will, by default, replace the line number for that line.\n      If this is not what you want, you can include the\n      string <code>%N%</code> in the text, which will be replaced by\n      the line number.</dd>\n      <dt id=\"clearMarker\"><code>clearMarker(line)</code></dt>\n      <dd>Clears a marker created\n      with <code>setMarker</code>. <code>line</code> can be either a\n      number or a handle returned by <code>setMarker</code> (since a\n      number may now refer to a different line if something was added\n      or deleted).</dd>\n      <dt id=\"setLineClass\"><code>setLineClass(line, className, backgroundClassName) → lineHandle</code></dt>\n      <dd>Set a CSS class name for the given line. <code>line</code>\n      can be a number or a line handle (as returned\n      by <code>setMarker</code> or this\n      function). <code>className</code> will be used to style the text\n      for the line, and <code>backgroundClassName</code> to style its\n      background (which lies behind the selection).\n      Pass <code>null</code> to clear the classes for a line.</dd>\n      <dt id=\"hideLine\"><code>hideLine(line) → lineHandle</code></dt>\n      <dd>Hide the given line (either by number or by handle). Hidden\n      lines don't show up in the editor, and their numbers are skipped\n      when <a href=\"#option_lineNumbers\">line numbers</a> are enabled.\n      Deleting a region around them does delete them, and coping a\n      region around will include them in the copied text.</dd>\n      <dt id=\"showLine\"><code>showLine(line) → lineHandle</code></dt>\n      <dd>The inverse of <code>hideLine</code>—re-shows a previously\n      hidden line, by number or by handle.</dd>\n\n      <dt id=\"onDeleteLine\"><code>onDeleteLine(line, func)</code></dt>\n      <dd>Register a function that should be called when the line is\n      deleted from the document.</dd>\n\n      <dt id=\"lineInfo\"><code>lineInfo(line) → object</code></dt>\n      <dd>Returns the line number, text content, and marker status of\n      the given line, which can be either a number or a handle\n      returned by <code>setMarker</code>. The returned object has the\n      structure <code>{line, handle, text, markerText, markerClass,\n      lineClass, bgClass}</code>.</dd>\n\n      <dt id=\"getLineHandle\"><code>getLineHandle(num) → lineHandle</code></dt>\n      <dd>Fetches the line handle for the given line number.</dd>\n\n      <dt id=\"addWidget\"><code>addWidget(pos, node, scrollIntoView)</code></dt>\n      <dd>Puts <code>node</code>, which should be an absolutely\n      positioned DOM node, into the editor, positioned right below the\n      given <code>{line, ch}</code> position.\n      When <code>scrollIntoView</code> is true, the editor will ensure\n      that the entire node is visible (if possible). To remove the\n      widget again, simply use DOM methods (move it somewhere else, or\n      call <code>removeChild</code> on its parent).</dd>\n\n      <dt id=\"matchBrackets\"><code>matchBrackets()</code></dt>\n      <dd>Force matching-bracket-highlighting to happen.</dd>\n\n      <dt id=\"lineCount\"><code>lineCount() → number</code></dt>\n      <dd>Get the number of lines in the editor.</dd>\n\n      <dt id=\"getCursor\"><code>getCursor(start) → object</code></dt>\n      <dd><code>start</code> is a boolean indicating whether the start\n      or the end of the selection must be retrieved. If it is not\n      given, the current cursor pos, i.e. the side of the selection\n      that would move if you pressed an arrow key, is chosen.\n      A <code>{line, ch}</code> object will be returned.</dd>\n      <dt id=\"somethingSelected\"><code>somethingSelected() → boolean</code></dt>\n      <dd>Return true if any text is selected.</dd>\n      <dt id=\"setCursor\"><code>setCursor(pos)</code></dt>\n      <dd>Set the cursor position. You can either pass a\n      single <code>{line, ch}</code> object, or the line and the\n      character as two separate parameters.</dd>\n      <dt id=\"setSelection\"><code>setSelection(start, end)</code></dt>\n      <dd>Set the selection range. <code>start</code>\n      and <code>end</code> should be <code>{line, ch}</code> objects.</dd>\n\n      <dt id=\"getLine\"><code>getLine(n) → string</code></dt>\n      <dd>Get the content of line <code>n</code>.</dd>\n      <dt id=\"setLine\"><code>setLine(n, text)</code></dt>\n      <dd>Set the content of line <code>n</code>.</dd>\n      <dt id=\"removeLine\"><code>removeLine(n)</code></dt>\n      <dd>Remove the given line from the document.</dd>\n\n      <dt id=\"getRange\"><code>getRange(from, to) → string</code></td>\n      <dd>Get the text between the given points in the editor, which\n      should be <code>{line, ch}</code> objects.</dd>\n      <dt id=\"replaceRange\"><code>replaceRange(string, from, to)</code></dt>\n      <dd>Replace the part of the document between <code>from</code>\n      and <code>to</code> with the given string. <code>from</code>\n      and <code>to</code> must be <code>{line, ch}</code>\n      objects. <code>to</code> can be left off to simply insert the\n      string at position <code>from</code>.</dd>\n\n      <dt id=\"posFromIndex\"><code>posFromIndex(index) → object</code></dt>\n      <dd>Calculates and returns a <code>{line, ch}</code> object for a\n      zero-based <code>index</code> who's value is relative to the start of the\n      editor's text. If the <code>index</code> is out of range of the text then\n      the returned object is clipped to start or end of the text\n      respectively.</dd>\n      <dt id=\"indexFromPos\"><code>indexFromPos(object) → number</code></dt>\n      <dd>The reverse of <a href=\"#posFromIndex\"><code>posFromIndex</code></a>.</dd>\n    </dl>\n\n    <p>The following are more low-level methods:</p>\n\n    <dl>\n      <dt id=\"operation\"><code>operation(func) → result</code></dt>\n      <dd>CodeMirror internally buffers changes and only updates its\n      DOM structure after it has finished performing some operation.\n      If you need to perform a lot of operations on a CodeMirror\n      instance, you can call this method with a function argument. It\n      will call the function, buffering up all changes, and only doing\n      the expensive update after the function returns. This can be a\n      lot faster. The return value from this method will be the return\n      value of your function.</dd>\n\n      <dt id=\"compoundChange\"><code>compoundChange(func) → result</code></dt>\n      <dd>Will call the given function (and return its result),\n      combining all changes made while that function executes into a\n      single undo event.</dd>\n\n      <dt id=\"refresh\"><code>refresh()</code></dt>\n      <dd>If your code does something to change the size of the editor\n      element (window resizes are already listened for), or unhides\n      it, you should probably follow up by calling this method to\n      ensure CodeMirror is still looking as intended.</dd>\n\n      <dt id=\"getInputField\"><code>getInputField() → textarea</code></dt>\n      <dd>Returns the hidden textarea used to read input.</dd>\n      <dt id=\"getWrapperElement\"><code>getWrapperElement() → node</code></dt>\n      <dd>Returns the DOM node that represents the editor. Remove this\n      from your tree to delete an editor instance.</dd>\n      <dt id=\"getScrollerElement\"><code>getScrollerElement() → node</code></dt>\n      <dd>Returns the DOM node that is responsible for the sizing and\n      the scrolling of the editor. You can change\n      the <code>height</code> and <code>width</code> styles of this\n      element to resize an editor. (You might have to call\n      the <a href=\"#refresh\"><code>refresh</code></a> method\n      afterwards.)</dd>\n      <dt id=\"getGutterElement\"><code>getGutterElement() → node</code></dt>\n      <dd>Fetches the DOM node that represents the editor gutter.</dd>\n\n      <dt id=\"getStateAfter\"><code>getStateAfter(line) → state</code></dt>\n      <dd>Returns the mode's parser state, if any, at the end of the\n      given line number. If no line number is given, the state at the\n      end of the document is returned. This can be useful for storing\n      parsing errors in the state, or getting other kinds of\n      contextual information for a line.</dd>\n    </dl>\n\n    <p id=\"fromTextArea\">Finally, the <code>CodeMirror</code> object\n    itself has a method <code>fromTextArea</code>. This takes a\n    textarea DOM node as first argument and an optional configuration\n    object as second. It will replace the textarea with a CodeMirror\n    instance, and wire up the form of that textarea (if any) to make\n    sure the editor contents are put into the textarea when the form\n    is submitted. A CodeMirror instance created this way has two\n    additional methods:</p>\n\n    <dl>\n      <dt id=\"save\"><code>save()</code></dt>\n      <dd>Copy the content of the editor into the textarea.</dd>\n\n      <dt id=\"toTextArea\"><code>toTextArea()</code></dt>\n      <dd>Remove the editor, and restore the original textarea (with\n      the editor's current content).</dd>\n\n      <dt id=\"getTextArea\"><code>getTextArea() → textarea</code></dt>\n      <dd>Returns the textarea that the instance was based on.</dd>\n    </dl>\n\n    <p id=\"defineExtension\">If you want to define extra methods in terms\n    of the CodeMirror API, it is possible to\n    use <code>CodeMirror.defineExtension(name, value)</code>. This\n    will cause the given value (usually a method) to be added to all\n    CodeMirror instances created from then on.</p>\n\n    <h2 id=\"addons\">Add-ons</h2>\n\n    <p>The <code>lib/util</code> directory in the distribution\n    contains a number of reusable components that implement extra\n    editor functionality. In brief, they are:</p>\n\n    <dl>\n      <dt id=\"util_dialog\"><a href=\"../lib/util/dialog.js\"><code>dialog.js</code></a></dt>\n      <dd>Provides a very simple way to query users for text input.\n      Adds an <code>openDialog</code> method to CodeMirror instances,\n      which can be called with an HTML fragment that provides the\n      prompt (should include an <code>input</code> tag), and a\n      callback function that is called when text has been entered.\n      Depends on <code>lib/util/dialog.css</code>.</dd>\n      <dt id=\"util_searchcursor\"><a href=\"../lib/util/searchcursor.js\"><code>searchcursor.js</code></a></dt>\n      <dd>Adds the <code>getSearchCursor(query, start, caseFold) →\n      cursor</code> method to CodeMirror instances, which can be used\n      to implement search/replace functionality. <code>query</code>\n      can be a regular expression or a string (only strings will match\n      across lines—if they contain newlines). <code>start</code>\n      provides the starting position of the search. It can be\n      a <code>{line, ch}</code> object, or can be left off to default\n      to the start of the document. <code>caseFold</code> is only\n      relevant when matching a string. It will cause the search to be\n      case-insensitive. A search cursor has the following methods:\n        <dl>\n          <dt><code>findNext(), findPrevious() → boolean</code></dt>\n          <dd>Search forward or backward from the current position.\n          The return value indicates whether a match was found. If\n          matching a regular expression, the return value will be the\n          array returned by the <code>match</code> method, in case you\n          want to extract matched groups.</dd>\n          <dt><code>from(), to() → object</code></dt>\n          <dd>These are only valid when the last call\n          to <code>findNext</code> or <code>findPrevious</code> did\n          not return false. They will return <code>{line, ch}</code>\n          objects pointing at the start and end of the match.</dd>\n          <dt><code>replace(text)</code></dt>\n          <dd>Replaces the currently found match with the given text\n          and adjusts the cursor position to reflect the\n          replacement.</dd>\n        </dl></dd>\n\n      <dt id=\"util_search\"><a href=\"../lib/util/search.js\"><code>search.js</code></a></dt>\n      <dd>Implements the search commands. CodeMirror has keys bound to\n      these by default, but will not do anything with them unless an\n      implementation is provided. Depends\n      on <code>searchcursor.js</code>, and will make use\n      of <a href=\"#util_dialog\"><code>openDialog</code></a> when\n      available to make prompting for search queries less ugly.</dd>\n      <dt id=\"util_foldcode\"><a href=\"../lib/util/foldcode.js\"><code>foldcode.js</code></a></dt>\n      <dd>Helps with code folding.\n      See <a href=\"../demo/folding.html\">the demo</a> for an example.\n      Call <code>CodeMirror.newFoldFunction</code> with a range-finder\n      helper function to create a function that will, when applied to\n      a CodeMirror instance and a line number, attempt to fold or\n      unfold the block starting at the given line. A range-finder is a\n      language-specific function that also takes an instance and a\n      line number, and returns an end line for the block, or null if\n      no block is started on that line. This file\n      provides <code>CodeMirror.braceRangeFinder</code>, which finds\n      blocks in brace languages (JavaScript, C, Java,\n      etc), <code>CodeMirror.indentRangeFinder</code>, for languages\n      where indentation determines block structure (Python, Haskell),\n      and <code>CodeMirror.tagRangeFinder</code>, for XML-style\n      languages.</dd>\n      <dt id=\"util_runmode\"><a href=\"../lib/util/runmode.js\"><code>runmode.js</code></a></dt>\n      <dd>Can be used to run a CodeMirror mode over text without\n      actually opening an editor instance.\n      See <a href=\"../demo/runmode.html\">the demo</a> for an\n      example.</dd>\n      <dt id=\"util_simple-hint\"><a href=\"../lib/util/simple-hint.js\"><code>simple-hint.js</code></a></dt>\n      <dd>Provides a framework for showing autocompletion hints.\n      Defines <code>CodeMirror.simpleHint</code>, which takes a\n      CodeMirror instance and a hinting function, and pops up a widget\n      that allows the user to select a completion. Hinting functions\n      are function that take an editor instance, and return\n      a <code>{list, from, to}</code> object, where <code>list</code>\n      is an array of strings (the completions), and <code>from</code>\n      and <code>to</code> give the start and end of the token that is\n      being completed. Depends\n      on <code>lib/util/simple-hint.css</code>.</dd>\n      <dt id=\"util_javascript-hint\"><a href=\"../lib/util/javascript-hint.js\"><code>javascript-hint.js</code></a></dt>\n      <dd>Defines <code>CodeMirror.javascriptHint</code>\n      and <code>CodeMirror.coffeescriptHint</code>, which are simple\n      hinting functions for the JavaScript and CoffeeScript\n      modes.</dd>\n      <dt id=\"util_match-highlighter\"><a href=\"../lib/util/match-highlighter.js\"><code>match-highlighter.js</code></a></dt>\n      <dd>Adds a <code>matchHighlight</code> method to CodeMirror\n      instances that can be called (typically from\n      a <a href=\"#option_onCursorActivity\"><code>onCursorActivity</code></a>\n      handler) to highlight all instances of a currently selected word\n      with the a classname given as a first argument to the method.\n      Depends on\n      the <a href=\"#util_searchcursor\"><code>searchcursor</code></a>\n      add-on. Demo <a href=\"../demo/matchhighlighter.html\">here</a>.</dd>\n      <dt id=\"util_closetag\"><a href=\"../lib/util/closetag.js\"><code>closetag.js</code></a></dt>\n      <dd>Provides utility functions for adding automatic tag closing\n      to XML modes. See\n      the <a href=\"../demo/closetag.html\">demo</a>.</dd>\n      <dt id=\"util_loadmode\"><a href=\"../lib/util/loadmode.js\"><code>loadmode.js</code></a></dt>\n      <dd>Defines a <code>CodeMirror.requireMode(modename,\n      callback)</code> function that will try to load a given mode and\n      call the callback when it succeeded. You'll have to\n      set <code>CodeMirror.modeURL</code> to a string that mode paths\n      can be constructed from, for\n      example <code>\"mode/%N/%N.js\"</code>—the <code>%N</code>'s will\n      be replaced with the mode name. Also\n      defines <code>CodeMirror.autoLoadMode(instance, mode)</code>,\n      which will ensure the given mode is loaded and cause the given\n      editor instance to refresh its mode when the loading\n      succeeded. See the <a href=\"../demo/loadmode.html\">demo</a>.</dd>\n    </dl>\n\n    <h2 id=\"modeapi\">Writing CodeMirror Modes</h2>\n\n    <p>Modes typically consist of a single JavaScript file. This file\n    defines, in the simplest case, a lexer (tokenizer) for your\n    language—a function that takes a character stream as input,\n    advances it past a token, and returns a style for that token. More\n    advanced modes can also handle indentation for the language.</p>\n\n    <p id=\"defineMode\">The mode script should\n    call <code>CodeMirror.defineMode</code> to register itself with\n    CodeMirror. This function takes two arguments. The first should be\n    the name of the mode, for which you should use a lowercase string,\n    preferably one that is also the name of the files that define the\n    mode (i.e. <code>\"xml\"</code> is defined <code>xml.js</code>). The\n    second argument should be a function that, given a CodeMirror\n    configuration object (the thing passed to\n    the <code>CodeMirror</code> function) and an optional mode\n    configuration object (as in\n    the <a href=\"#option_mode\"><code>mode</code></a> option), returns\n    a mode object.</p>\n\n    <p>Typically, you should use this second argument\n    to <code>defineMode</code> as your module scope function (modes\n    should not leak anything into the global scope!), i.e. write your\n    whole mode inside this function.</p>\n\n    <p>The main responsibility of a mode script is <em>parsing</em>\n    the content of the editor. Depending on the language and the\n    amount of functionality desired, this can be done in really easy\n    or extremely complicated ways. Some parsers can be stateless,\n    meaning that they look at one element (<em>token</em>) of the code\n    at a time, with no memory of what came before. Most, however, will\n    need to remember something. This is done by using a <em>state\n    object</em>, which is an object that is always passed when\n    reading a token, and which can be mutated by the tokenizer.</p>\n\n    <p id=\"startState\">Modes that use a state must define\n    a <code>startState</code> method on their mode object. This is a\n    function of no arguments that produces a state object to be used\n    at the start of a document.</p>\n\n    <p id=\"token\">The most important part of a mode object is\n    its <code>token(stream, state)</code> method. All modes must\n    define this method. It should read one token from the stream it is\n    given as an argument, optionally update its state, and return a\n    style string, or <code>null</code> for tokens that do not have to\n    be styled. For your styles, you can either use the 'standard' ones\n    defined in the themes (without the <code>cm-</code> prefix), or\n    define your own and have people include a custom CSS file for your\n    mode.<p>\n\n    <p id=\"StringStream\">The stream object encapsulates a line of code\n    (tokens may never span lines) and our current position in that\n    line. It has the following API:</p>\n\n    <dl>\n      <dt><code>eol() → boolean</code></dt>\n      <dd>Returns true only if the stream is at the end of the\n      line.</dd>\n      <dt><code>sol() → boolean</code></dt>\n      <dd>Returns true only if the stream is at the start of the\n      line.</dd>\n\n      <dt><code>peek() → character</code></dt>\n      <dd>Returns the next character in the stream without advancing\n      it. Will return <code>undefined</code> at the end of the\n      line.</dd>\n      <dt><code>next() → character</code></dt>\n      <dd>Returns the next character in the stream and advances it.\n      Also returns <code>undefined</code> when no more characters are\n      available.</dd>\n\n      <dt><code>eat(match) → character</code></dt>\n      <dd><code>match</code> can be a character, a regular expression,\n      or a function that takes a character and returns a boolean. If\n      the next character in the stream 'matches' the given argument,\n      it is consumed and returned. Otherwise, <code>undefined</code>\n      is returned.</dd>\n      <dt><code>eatWhile(match) → boolean</code></dt>\n      <dd>Repeatedly calls <code>eat</code> with the given argument,\n      until it fails. Returns true if any characters were eaten.</dd>\n      <dt><code>eatSpace() → boolean</code></dt>\n      <dd>Shortcut for <code>eatWhile</code> when matching\n      white-space.</dd>\n      <dt><code>skipToEnd()</code></dt>\n      <dd>Moves the position to the end of the line.</dd>\n      <dt><code>skipTo(ch) → boolean</code></dt>\n      <dd>Skips to the next occurrence of the given character, if\n      found on the current line (doesn't advance the stream if the\n      character does not occur on the line). Returns true if the\n      character was found.</dd>\n      <dt><code>match(pattern, consume, caseFold) → boolean</code></dt>\n      <dd>Act like a\n      multi-character <code>eat</code>—if <code>consume</code> is true\n      or not given—or a look-ahead that doesn't update the stream\n      position—if it is false. <code>pattern</code> can be either a\n      string or a regular expression starting with <code>^</code>.\n      When it is a string, <code>caseFold</code> can be set to true to\n      make the match case-insensitive. When successfully matching a\n      regular expression, the returned value will be the array\n      returned by <code>match</code>, in case you need to extract\n      matched groups.</dd>\n\n      <dt><code>backUp(n)</code></dt>\n      <dd>Backs up the stream <code>n</code> characters. Backing it up\n      further than the start of the current token will cause things to\n      break, so be careful.</dd>\n      <dt><code>column() → integer</code></dt>\n      <dd>Returns the column (taking into account tabs) at which the\n      current token starts. Can be used to find out whether a token\n      starts a new line.</dd>\n      <dt><code>indentation() → integer</code></dt>\n      <dd>Tells you how far the current line has been indented, in\n      spaces. Corrects for tab characters.</dd>\n\n      <dt><code>current() → string</code></dt>\n      <dd>Get the string between the start of the current token and\n      the current stream position.</dd>\n    </dl>\n\n    <p id=\"blankLine\">By default, blank lines are simply skipped when\n    tokenizing a document. For languages that have significant blank\n    lines, you can define a <code>blankLine(state)</code> method on\n    your mode that will get called whenever a blank line is passed\n    over, so that it can update the parser state.</p>\n\n    <p id=\"copyState\">Because state object are mutated, and CodeMirror\n    needs to keep valid versions of a state around so that it can\n    restart a parse at any line, copies must be made of state objects.\n    The default algorithm used is that a new state object is created,\n    which gets all the properties of the old object. Any properties\n    which hold arrays get a copy of these arrays (since arrays tend to\n    be used as mutable stacks). When this is not correct, for example\n    because a mode mutates non-array properties of its state object, a\n    mode object should define a <code>copyState</code> method,\n    which is given a state and should return a safe copy of that\n    state.</p>\n\n    <p id=\"compareStates\">By default, CodeMirror will stop re-parsing\n    a document as soon as it encounters a few lines that were\n    highlighted the same in the old parse as in the new one. It is\n    possible to provide an explicit way to test whether a state is\n    equivalent to another one, which CodeMirror will use (instead of\n    the unchanged-lines heuristic) to decide when to stop\n    highlighting. You do this by providing\n    a <code>compareStates</code> method on your mode object, which\n    takes two state arguments and returns a boolean indicating whether\n    they are equivalent. See the XML mode, which uses this to provide\n    reliable highlighting of bad closing tags, as an example.</p>\n\n    <p id=\"indent\">If you want your mode to provide smart indentation\n    (though the <a href=\"#indentLine\"><code>indentLine</code></a>\n    method and the <code>indentAuto</code>\n    and <code>newlineAndIndent</code> commands, which keys can be\n    <a href=\"#option_extraKeys\">bound</a> to), you must define\n    an <code>indent(state, textAfter)</code> method on your mode\n    object.</p>\n\n    <p>The indentation method should inspect the given state object,\n    and optionally the <code>textAfter</code> string, which contains\n    the text on the line that is being indented, and return an\n    integer, the amount of spaces to indent. It should usually take\n    the <a href=\"#option_indentUnit\"><code>indentUnit</code></a>\n    option into account.</p>\n\n    <p id=\"electricChars\">Finally, a mode may define\n    an <code>electricChars</code> property, which should hold a string\n    containing all the characters that should trigger the behaviour\n    described for\n    the <a href=\"#option_electricChars\"><code>electricChars</code></a>\n    option.</p>\n\n    <p>So, to summarize, a mode <em>must</em> provide\n    a <code>token</code> method, and it <em>may</em>\n    provide <code>startState</code>, <code>copyState</code>,\n    <code>compareStates</code>, and <code>indent</code> methods. For\n    an example of a trivial mode, see\n    the <a href=\"../mode/diff/diff.js\">diff mode</a>, for a more involved\n    example, see the <a href=\"../mode/clike/clike.js\">C-like\n    mode</a>.</p>\n\n    <p>Sometimes, it is useful for modes to <em>nest</em>—to have one\n    mode delegate work to another mode. An example of this kind of\n    mode is the <a href=\"../mode/htmlmixed/htmlmixed.js\">mixed-mode HTML\n    mode</a>. To implement such nesting, it is usually necessary to\n    create mode objects and copy states yourself. To create a mode\n    object, there are <code>CodeMirror.getMode(options,\n    parserConfig)</code>, where the first argument is a configuration\n    object as passed to the mode constructor function, and the second\n    argument is a mode specification as in\n    the <a href=\"#option_mode\"><code>mode</code></a> option. To copy a\n    state object, call <code>CodeMirror.copyState(mode, state)</code>,\n    where <code>mode</code> is the mode that created the given\n    state.</p>\n\n    <p>To make indentation work properly in a nested parser, it is\n    advisable to give the <code>startState</code> method of modes that\n    are intended to be nested an optional argument that provides the\n    base indentation for the block of code. The JavaScript and CSS\n    parser do this, for example, to allow JavaScript and CSS code\n    inside the mixed-mode HTML mode to be properly indented.</p>\n\n    <p>Finally, it is possible to associate your mode, or a certain\n    configuration of your mode, with\n    a <a href=\"http://en.wikipedia.org/wiki/MIME\">MIME</a> type. For\n    example, the JavaScript mode associates itself\n    with <code>text/javascript</code>, and its JSON variant\n    with <code>application/json</code>. To do this,\n    call <code>CodeMirror.defineMIME(mime, modeSpec)</code>,\n    where <code>modeSpec</code> can be a string or object specifying a\n    mode, as in the <a href=\"#option_mode\"><code>mode</code></a>\n    option.</p>\n\n</div><div class=\"rightsmall blk\">\n\n    <h2>Contents</h2>\n\n    <ul>\n      <li><a href=\"#overview\">Overview</a></li>\n      <li><a href=\"#usage\">Basic Usage</a></li>\n      <li><a href=\"#config\">Configuration</a></li>\n      <li><a href=\"#keymaps\">Keymaps</a></li>\n      <li><a href=\"#styling\">Customized Styling</a></li>\n      <li><a href=\"#api\">Programming API</a></li>\n      <li><a href=\"#addons\">Add-ons</a></li>\n      <li><a href=\"#modeapi\">Writing CodeMirror Modes</a></li>\n    </ul>\n\n</div></div>\n\n<div style=\"height: 2em\">&nbsp;</div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/doc/oldrelease.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans:bold\"/>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"docs.css\"/>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n    <link rel=\"alternate\" href=\"http://twitter.com/statuses/user_timeline/242283288.rss\" type=\"application/rss+xml\"/>\n  </head>\n  <body>\n\n<h1><span class=\"logo-braces\">{ }</span> <a href=\"http://codemirror.net/\">CodeMirror</a></h1>\n\n<pre class=\"grey\">\n<img src=\"baboon.png\" class=\"logo\" alt=\"logo\"/>/* Old release history */\n\n</pre>\n\n  <p class=\"rel\">23-08-2011: <a href=\"http://codemirror.net/codemirror-2.13.zip\">Version 2.13</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Add <a href=\"../mode/ruby/index.html\">Ruby</a>, <a href=\"../mode/r/index.html\">R</a>, <a href=\"../mode/coffeescript/index.html\">CoffeeScript</a>, and <a href=\"../mode/velocity/index.html\">Velocity</a> modes.</li>\n    <li>Add <a href=\"manual.html#getGutterElement\"><code>getGutterElement</code></a> to API.</li>\n    <li>Several fixes to scrolling and positioning.</li>\n    <li>Add <a href=\"manual.html#option_smartHome\"><code>smartHome</code></a> option.</li>\n    <li>Add an experimental <a href=\"../mode/xmlpure/index.html\">pure XML</a> mode.</li>\n  </ul>\n\n  <p class=\"rel\">25-07-2011: <a href=\"http://codemirror.net/codemirror-2.12.zip\">Version 2.12</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Add a <a href=\"../mode/sparql/index.html\">SPARQL</a> mode.</li>\n    <li>Fix bug with cursor jumping around in an unfocused editor in IE.</li>\n    <li>Allow key and mouse events to bubble out of the editor. Ignore widget clicks.</li>\n    <li>Solve cursor flakiness after undo/redo.</li>\n    <li>Fix block-reindent ignoring the last few lines.</li>\n    <li>Fix parsing of multi-line attrs in XML mode.</li>\n    <li>Use <code>innerHTML</code> for HTML-escaping.</li>\n    <li>Some fixes to indentation in C-like mode.</li>\n    <li>Shrink horiz scrollbars when long lines removed.</li>\n    <li>Fix width feedback loop bug that caused the width of an inner DIV to shrink.</li>\n  </ul>\n\n  <p class=\"rel\">04-07-2011: <a href=\"http://codemirror.net/codemirror-2.11.zip\">Version 2.11</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Add a <a href=\"../mode/scheme/index.html\">Scheme mode</a>.</li>\n    <li>Add a <code>replace</code> method to search cursors, for cursor-preserving replacements.</li>\n    <li>Make the <a href=\"../mode/clike/index.html\">C-like mode</a> mode more customizable.</li>\n    <li>Update XML mode to spot mismatched tags.</li>\n    <li>Add <code>getStateAfter</code> API and <code>compareState</code> mode API methods for finer-grained mode magic.</li>\n    <li>Add a <code>getScrollerElement</code> API method to manipulate the scrolling DIV.</li>\n    <li>Fix drag-and-drop for Firefox.</li>\n    <li>Add a C# configuration for the <a href=\"../mode/clike/index.html\">C-like mode</a>.</li>\n    <li>Add <a href=\"../demo/fullscreen.html\">full-screen editing</a> and <a href=\"../demo/changemode.html\">mode-changing</a> demos.</li>\n  </ul>\n\n  <p class=\"rel\">07-06-2011: <a href=\"http://codemirror.net/codemirror-2.1.zip\">Version 2.1</a>:</p>\n  <p class=\"rel-note\">Add\n  a <a href=\"manual.html#option_theme\">theme</a> system\n  (<a href=\"../demo/theme.html\">demo</a>). Note that this is not\n  backwards-compatible—you'll have to update your styles and\n  modes!</p>\n\n  <p class=\"rel\">07-06-2011: <a href=\"http://codemirror.net/codemirror-2.02.zip\">Version 2.02</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Add a <a href=\"../mode/lua/index.html\">Lua mode</a>.</li>\n    <li>Fix reverse-searching for a regexp.</li>\n    <li>Empty lines can no longer break highlighting.</li>\n    <li>Rework scrolling model (the outer wrapper no longer does the scrolling).</li>\n    <li>Solve horizontal jittering on long lines.</li>\n    <li>Add <a href=\"../demo/runmode.html\">runmode.js</a>.</li>\n    <li>Immediately re-highlight text when typing.</li>\n    <li>Fix problem with 'sticking' horizontal scrollbar.</li>\n  </ul>\n\n  <p class=\"rel\">26-05-2011: <a href=\"http://codemirror.net/codemirror-2.01.zip\">Version 2.01</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Add a <a href=\"../mode/smalltalk/index.html\">Smalltalk mode</a>.</li>\n    <li>Add a <a href=\"../mode/rst/index.html\">reStructuredText mode</a>.</li>\n    <li>Add a <a href=\"../mode/python/index.html\">Python mode</a>.</li>\n    <li>Add a <a href=\"../mode/plsql/index.html\">PL/SQL mode</a>.</li>\n    <li><code>coordsChar</code> now works</li>\n    <li>Fix a problem where <code>onCursorActivity</code> interfered with <code>onChange</code>.</li>\n    <li>Fix a number of scrolling and mouse-click-position glitches.</li>\n    <li>Pass information about the changed lines to <code>onChange</code>.</li>\n    <li>Support cmd-up/down on OS X.</li>\n    <li>Add triple-click line selection.</li>\n    <li>Don't handle shift when changing the selection through the API.</li>\n    <li>Support <code>\"nocursor\"</code> mode for <code>readOnly</code> option.</li>\n    <li>Add an <code>onHighlightComplete</code> option.</li>\n    <li>Fix the context menu for Firefox.</li>\n  </ul>\n\n  <p class=\"rel\">28-03-2011: <a href=\"http://codemirror.net/codemirror-2.0.zip\">Version 2.0</a>:</p>\n  <p class=\"rel-note\">CodeMirror 2 is a complete rewrite that's\n  faster, smaller, simpler to use, and less dependent on browser\n  quirks. See <a href=\"internals.html\">this</a>\n  and <a href=\"http://groups.google.com/group/codemirror/browse_thread/thread/5a8e894024a9f580\">this</a>\n  for more information.</a>\n\n  <p class=\"rel\">28-03-2011: <a href=\"http://codemirror.net/codemirror-1.0.zip\">Version 1.0</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Fix error when debug history overflows.</li>\n    <li>Refine handling of C# verbatim strings.</li>\n    <li>Fix some issues with JavaScript indentation.</li>\n  </ul>\n\n  <p class=\"rel\">22-02-2011: <a href=\"https://github.com/marijnh/codemirror2/tree/beta2\">Version 2.0 beta 2</a>:</p>\n  <p class=\"rel-note\">Somewhat more mature API, lots of bugs shaken out.</a>\n\n  <p class=\"rel\">17-02-2011: <a href=\"http://codemirror.net/codemirror-0.94.zip\">Version 0.94</a>:</p>\n  <ul class=\"rel-note\">\n    <li><code>tabMode: \"spaces\"</code> was modified slightly (now indents when something is selected).</li>\n    <li>Fixes a bug that would cause the selection code to break on some IE versions.</li>\n    <li>Disabling spell-check on WebKit browsers now works.</li>\n  </ul>\n\n  <p class=\"rel\">08-02-2011: <a href=\"http://codemirror.net/\">Version 2.0 beta 1</a>:</p>\n  <p class=\"rel-note\">CodeMirror 2 is a complete rewrite of\n  CodeMirror, no longer depending on an editable frame.</p>\n\n  <p class=\"rel\">19-01-2011: <a href=\"http://codemirror.net/codemirror-0.93.zip\">Version 0.93</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Added a <a href=\"contrib/regex/index.html\">Regular Expression</a> parser.</li>\n    <li>Fixes to the PHP parser.</li>\n    <li>Support for regular expression in search/replace.</li>\n    <li>Add <code>save</code> method to instances created with <code>fromTextArea</code>.</li>\n    <li>Add support for MS T-SQL in the SQL parser.</li>\n    <li>Support use of CSS classes for highlighting brackets.</li>\n    <li>Fix yet another hang with line-numbering in hidden editors.</li>\n  </ul>\n\n  <p class=\"rel\">17-12-2010: <a href=\"http://codemirror.net/codemirror-0.92.zip\">Version 0.92</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Make CodeMirror work in XHTML documents.</li>\n    <li>Fix bug in handling of backslashes in Python strings.</li>\n    <li>The <code>styleNumbers</code> option is now officially\n    supported and documented.</li>\n    <li><code>onLineNumberClick</code> option added.</li>\n    <li>More consistent names <code>onLoad</code> and\n    <code>onCursorActivity</code> callbacks. Old names still work, but\n    are deprecated.</li>\n    <li>Add a <a href=\"contrib/freemarker/index.html\">Freemarker</a> mode.</li>\n  </ul>\n\n  <p class=\"rel\">11-11-2010: <a\n  href=\"http://codemirror.net/codemirror-0.91.zip\">Version 0.91</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Adds support for <a href=\"contrib/java\">Java</a>.</li>\n    <li>Small additions to the <a href=\"contrib/php\">PHP</a> and <a href=\"contrib/sql\">SQL</a> parsers.</li>\n    <li>Work around various <a href=\"https://bugs.webkit.org/show_bug.cgi?id=47806\">Webkit</a> <a href=\"https://bugs.webkit.org/show_bug.cgi?id=23474\">issues</a>.</li>\n    <li>Fix <code>toTextArea</code> to update the code in the textarea.</li>\n    <li>Add a <code>noScriptCaching</code> option (hack to ease development).</li>\n    <li>Make sub-modes of <a href=\"mixedtest.html\">HTML mixed</a> mode configurable.</li>\n  </ul>\n\n  <p class=\"rel\">02-10-2010: <a\n  href=\"http://codemirror.net/codemirror-0.9.zip\">Version 0.9</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Add support for searching backwards.</li>\n    <li>There are now parsers for <a href=\"contrib/scheme/index.html\">Scheme</a>, <a href=\"contrib/xquery/index.html\">XQuery</a>, and <a href=\"contrib/ometa/index.html\">OmetaJS</a>.</li>\n    <li>Makes <code>height: \"dynamic\"</code> more robust.</li>\n    <li>Fixes bug where paste did not work on OS X.</li>\n    <li>Add a <code>enterMode</code> and <code>electricChars</code> options to make indentation even more customizable.</li>\n    <li>Add <code>firstLineNumber</code> option.</li>\n    <li>Fix bad handling of <code>@media</code> rules by the CSS parser.</li>\n    <li>Take a new, more robust approach to working around the invisible-last-line bug in WebKit.</li>\n  </ul>\n\n  <p class=\"rel\">22-07-2010: <a\n  href=\"http://codemirror.net/codemirror-0.8.zip\">Version 0.8</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Add a <code>cursorCoords</code> method to find the screen\n    coordinates of the cursor.</li>\n    <li>A number of fixes and support for more syntax in the PHP parser.</li>\n    <li>Fix indentation problem with JSON-mode JS parser in Webkit.</li>\n    <li>Add a <a href=\"compress.html\">minification</a> UI.</li>\n    <li>Support a <code>height: dynamic</code> mode, where the editor's\n    height will adjust to the size of its content.</li>\n    <li>Better support for IME input mode.</li>\n    <li>Fix JavaScript parser getting confused when seeing a no-argument\n    function call.</li>\n    <li>Have CSS parser see the difference between selectors and other\n    identifiers.</li>\n    <li>Fix scrolling bug when pasting in a horizontally-scrolled\n    editor.</li>\n    <li>Support <code>toTextArea</code> method in instances created with\n    <code>fromTextArea</code>.</li>\n    <li>Work around new Opera cursor bug that causes the cursor to jump\n    when pressing backspace at the end of a line.</li>\n  </ul>\n\n  <p class=\"rel\">27-04-2010: <a\n  href=\"http://codemirror.net/codemirror-0.67.zip\">Version\n  0.67</a>:</p>\n  <p class=\"rel-note\">More consistent page-up/page-down behaviour\n  across browsers. Fix some issues with hidden editors looping forever\n  when line-numbers were enabled. Make PHP parser parse\n  <code>\"\\\\\"</code> correctly. Have <code>jumpToLine</code> work on\n  line handles, and add <code>cursorLine</code> function to fetch the\n  line handle where the cursor currently is. Add new\n  <code>setStylesheet</code> function to switch style-sheets in a\n  running editor.</p>\n\n  <p class=\"rel\">01-03-2010: <a\n  href=\"http://codemirror.net/codemirror-0.66.zip\">Version\n  0.66</a>:</p>\n  <p class=\"rel-note\">Adds <code>removeLine</code> method to API.\n  Introduces the <a href=\"contrib/plsql/index.html\">PLSQL parser</a>.\n  Marks XML errors by adding (rather than replacing) a CSS class, so\n  that they can be disabled by modifying their style. Fixes several\n  selection bugs, and a number of small glitches.</p>\n\n  <p class=\"rel\">12-11-2009: <a\n  href=\"http://codemirror.net/codemirror-0.65.zip\">Version\n  0.65</a>:</p>\n  <p class=\"rel-note\">Add support for having both line-wrapping and\n  line-numbers turned on, make paren-highlighting style customisable\n  (<code>markParen</code> and <code>unmarkParen</code> config\n  options), work around a selection bug that Opera\n  <em>re</em>introduced in version 10.</p>\n\n  <p class=\"rel\">23-10-2009: <a\n  href=\"http://codemirror.net/codemirror-0.64.zip\">Version\n  0.64</a>:</p>\n  <p class=\"rel-note\">Solves some issues introduced by the\n  paste-handling changes from the previous release. Adds\n  <code>setSpellcheck</code>, <code>setTextWrapping</code>,\n  <code>setIndentUnit</code>, <code>setUndoDepth</code>,\n  <code>setTabMode</code>, and <code>setLineNumbers</code> to\n  customise a running editor. Introduces an <a\n  href=\"contrib/sql/index.html\">SQL</a> parser. Fixes a few small\n  problems in the <a href=\"contrib/python/index.html\">Python</a>\n  parser. And, as usual, add workarounds for various newly discovered\n  browser incompatibilities.</p>\n\n<p class=\"rel\"><em>31-08-2009</em>: <a\nhref=\"http://codemirror.net/codemirror-0.63.zip\">Version\n0.63</a>:</p>\n<p class=\"rel-note\"> Overhaul of paste-handling (less fragile), fixes for several\nserious IE8 issues (cursor jumping, end-of-document bugs) and a number\nof small problems.</p>\n\n<p class=\"rel\"><em>30-05-2009</em>: <a\nhref=\"http://codemirror.net/codemirror-0.62.zip\">Version\n0.62</a>:</p>\n<p class=\"rel-note\">Introduces <a href=\"contrib/python/index.html\">Python</a>\nand <a href=\"contrib/lua/index.html\">Lua</a> parsers. Add\n<code>setParser</code> (on-the-fly mode changing) and\n<code>clearHistory</code> methods. Make parsing passes time-based\ninstead of lines-based (see the <code>passTime</code> option).</p>\n\n</body></html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/doc/reporting.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Reporting Bugs</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans:bold\"/>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"docs.css\"/>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n    <style>li { margin-top: 1em; }</style>\n  </head>\n  <body>\n\n<h1><span class=\"logo-braces\">{ }</span> <a href=\"http://codemirror.net/\">CodeMirror</a></h1>\n\n<pre class=\"grey\">\n<img src=\"baboon.png\" class=\"logo\" alt=\"logo\"/>/* Reporting bugs\n   effectively */\n</pre>\n\n<div class=\"left\">\n\n<p>So you found a problem in CodeMirror. By all means, report it! Bug\nreports from users are the main drive behind improvements to\nCodeMirror. But first, please read over these points:</p>\n\n<ol>\n  <li>CodeMirror is maintained by volunteers. They don't owe you\n  anything, so be polite. Reports with an indignant or belligerent\n  tone tend to be moved to the bottom of the pile.</li>\n\n  <li>Include information about <strong>the browser in which the\n  problem occurred</strong>. Even if you tested several browsers, and\n  the problem occurred in all of them, mention this fact in the bug\n  report. Also include browser version numbers and the operating\n  system that you're on.</li>\n\n  <li>Mention which release of CodeMirror you're using. Preferably,\n  try also with the current development snapshot, to ensure the\n  problem has not already been fixed.</li>\n\n  <li>Mention very precisely what went wrong. \"X is broken\" is not a\n  good bug report. What did you expect to happen? What happened\n  instead? Describe the exact steps a maintainer has to take to make\n  the problem occur. We can not fix something that we can not\n  observe.</li>\n\n  <li>If the problem can not be reproduced in any of the demos\n  included in the CodeMirror distribution, please provide an HTML\n  document that demonstrates the problem. The best way to do this is\n  to go to <a href=\"http://jsbin.com/ihunin/edit\">jsbin.com</a>, enter\n  it there, press save, and include the resulting link in your bug\n  report.</li>\n</ol>\n\n</div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/doc/upgrade_v2.2.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Upgrading to v2.2</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans:bold\"/>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"docs.css\"/>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n  </head>\n  <body>\n\n<h1><span class=\"logo-braces\">{ }</span> <a href=\"http://codemirror.net/\">CodeMirror</a></h1>\n\n<pre class=\"grey\">\n<img src=\"baboon.png\" class=\"logo\" alt=\"logo\"/>/* Upgrading to v2.2\n */\n</pre>\n\n<div class=\"left\">\n\n<p>There are a few things in the 2.2 release that require some care\nwhen upgrading.</p>\n\n<h2>No more default.css</h2>\n\n<p>The default theme is now included\nin <a href=\"../lib/codemirror.css\"><code>codemirror.css</code></a>, so\nyou do not have to included it separately anymore. (It was tiny, so\neven if you're not using it, the extra data overhead is negligible.)\n\n<h2>Different key customization</h2>\n\n<p>CodeMirror has moved to a system\nwhere <a href=\"manual.html#option_keyMap\">keymaps</a> are used to\nbind behavior to keys. This means <a href=\"../demo/emacs.html\">custom\nbindings</a> are now possible.</p>\n\n<p>Three options that influenced key\nbehavior, <code>tabMode</code>, <code>enterMode</code>,\nand <code>smartHome</code>, are no longer supported. Instead, you can\nprovide custom bindings to influence the way these keys act. This is\ndone through the\nnew <a href=\"manual.html#option_extraKeys\"><code>extraKeys</code></a>\noption, which can hold an object mapping key names to functionality. A\nsimple example would be:</p>\n\n<pre>  extraKeys: {\n    \"Ctrl-S\": function(instance) { saveText(instance.getValue()); },\n    \"Ctrl-/\": \"undo\"\n  }</pre>\n\n<p>Keys can be mapped either to functions, which will be given the\neditor instance as argument, or to strings, which are mapped through\nfunctions through the <code>CodeMirror.commands</code> table, which\ncontains all the built-in editing commands, and can be inspected and\nextended by external code.</p>\n\n<p>By default, the <code>Home</code> key is bound to\nthe <code>\"goLineStartSmart\"</code> command, which moves the cursor to\nthe first non-whitespace character on the line. You can set do this to\nmake it always go to the very start instead:</p>\n\n<pre>  extraKeys: {\"Home\": \"goLineStart\"}</pre>\n\n<p>Similarly, <code>Enter</code> is bound\nto <code>\"newlineAndIndent\"</code> by default. You can bind it to\nsomething else to get different behavior. To disable special handling\ncompletely and only get a newline character inserted, you can bind it\nto <code>false</code>:</p>\n\n<pre>  extraKeys: {\"Enter\": false}</pre>\n\n<p>The same works for <code>Tab</code>. If you don't want CodeMirror\nto handle it, bind it to <code>false</code>. The default behaviour is\nto indent the current line more (<code>\"indentMore\"</code> command),\nand indent it less when shift is held (<code>\"indentLess\"</code>).\nThere are also <code>\"indentAuto\"</code> (smart indent)\nand <code>\"insertTab\"</code> commands provided for alternate\nbehaviors. Or you can write your own handler function to do something\ndifferent altogether.</p>\n\n<h2>Tabs</h2>\n\n<p>Handling of tabs changed completely. The display width of tabs can\nnow be set with the <code>tabSize</code> option, and tabs can\nbe <a href=\"../demo/visibletabs.html\">styled</a> by setting CSS rules\nfor the <code>cm-tab</code> class.</p>\n\n<p>The default width for tabs is now 4, as opposed to the 8 that is\nhard-wired into browsers. If you are relying on 8-space tabs, make\nsure you explicitly set <code>tabSize: 8</code> in your options.</p>\n\n</div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"http://fonts.googleapis.com/css?family=Droid+Sans|Droid+Sans:bold\"/>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"doc/docs.css\"/>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n    <link rel=\"alternate\" href=\"http://twitter.com/statuses/user_timeline/242283288.rss\" type=\"application/rss+xml\"/>\n  </head>\n  <body>\n\n<h1><span class=\"logo-braces\">{ }</span> <a href=\"http://codemirror.net/\">CodeMirror</a></h1>\n\n<pre class=\"grey\">\n<img src=\"doc/baboon.png\" class=\"logo\" alt=\"logo\"/>/* In-browser code editing\n   made bearable */\n</pre>\n\n<div class=\"clear\"><div class=\"left blk\">\n\n  <p style=\"margin-top: 0\">CodeMirror is a JavaScript component that\n  provides a code editor in the browser. When a mode is available for\n  the language you are coding in, it will color your code, and\n  optionally help with indentation.</p>\n\n  <p>A <a href=\"doc/manual.html\">rich programming API</a> and a CSS\n  theming system are available for customizing CodeMirror to fit your\n  application, and extending it with new functionality.</p>\n\n  <div class=\"clear\"><div class=\"left1 blk\">\n\n    <h2 style=\"margin-top: 0\">Supported modes:</h2>\n\n    <ul>\n      <li><a href=\"mode/clike/index.html\">C, C++, C#, Java, and similar</a></li>\n      <li><a href=\"mode/clojure/index.html\">Clojure</a></li>\n      <li><a href=\"mode/coffeescript/index.html\">CoffeeScript</a></li>\n      <li><a href=\"mode/css/index.html\">CSS</a></li>\n      <li><a href=\"mode/diff/index.html\">diff</a></li>\n      <li><a href=\"mode/ecl/index.html\">ECL</a></li>\n      <li><a href=\"mode/erlang/index.html\">Erlang</a></li>\n      <li><a href=\"mode/go/index.html\">Go</a></li>\n      <li><a href=\"mode/groovy/index.html\">Groovy</a></li>\n      <li><a href=\"mode/haskell/index.html\">Haskell</a></li>\n      <li><a href=\"mode/htmlembedded/index.html\">HTML embedded scripts</a></li>\n      <li><a href=\"mode/htmlmixed/index.html\">HTML mixed-mode</a></li>\n      <li><a href=\"mode/javascript/index.html\">JavaScript</a></li>\n      <li><a href=\"mode/jinja2/index.html\">Jinja2</a></li>\n      <li><a href=\"mode/less/index.html\">LESS</a></li>\n      <li><a href=\"mode/lua/index.html\">Lua</a></li>\n      <li><a href=\"mode/markdown/index.html\">Markdown</a> (<a href=\"mode/gfm/index.html\">Github-flavour</a>)</li>\n      <li><a href=\"mode/mysql/index.html\">MySQL</a></li>\n      <li><a href=\"mode/ntriples/index.html\">NTriples</a></li>\n      <li><a href=\"mode/pascal/index.html\">Pascal</a></li>\n      <li><a href=\"mode/perl/index.html\">Perl</a></li>\n      <li><a href=\"mode/php/index.html\">PHP</a></li>\n      <li><a href=\"mode/pig/index.html\">Pig Latin</a></li>\n      <li><a href=\"mode/plsql/index.html\">PL/SQL</a></li>\n      <li><a href=\"mode/properties/index.html\">Properties files</a></li>\n      <li><a href=\"mode/python/index.html\">Python</a></li>\n      <li><a href=\"mode/r/index.html\">R</a></li>\n      <li>RPM <a href=\"mode/rpm/spec/index.html\">spec</a> and <a href=\"mode/rpm/changes/index.html\">changelog</a></li>\n      <li><a href=\"mode/rst/index.html\">reStructuredText</a></li>\n      <li><a href=\"mode/ruby/index.html\">Ruby</a></li>\n      <li><a href=\"mode/rust/index.html\">Rust</a></li>\n      <li><a href=\"mode/scheme/index.html\">Scheme</a></li>\n      <li><a href=\"mode/shell/index.html\">Shell</a></li>\n      <li><a href=\"mode/smalltalk/index.html\">Smalltalk</a></li>\n      <li><a href=\"mode/smarty/index.html\">Smarty</a></li>\n      <li><a href=\"mode/sparql/index.html\">SPARQL</a></li>\n      <li><a href=\"mode/stex/index.html\">sTeX, LaTeX</a></li>\n      <li><a href=\"mode/tiddlywiki/index.html\">Tiddlywiki</a></li>\n      <li><a href=\"mode/tiki/index.html\">Tiki wiki</a></li>\n      <li><a href=\"mode/vbscript/index.html\">VBScript</a></li>\n      <li><a href=\"mode/velocity/index.html\">Velocity</a></li>\n      <li><a href=\"mode/verilog/index.html\">Verilog</a></li>\n      <li><a href=\"mode/xml/index.html\">XML/HTML</a></li>\n      <li><a href=\"mode/xquery/index.html\">XQuery</a></li>\n      <li><a href=\"mode/yaml/index.html\">YAML</a></li>\n    </ul>\n\n  </div><div class=\"left2 blk\">\n\n    <h2 style=\"margin-top: 0\">Usage demos:</h2>\n\n    <ul>\n      <li><a href=\"demo/complete.html\">Autocompletion</a></li>\n      <li><a href=\"demo/mustache.html\">Mode overlays</a></li>\n      <li><a href=\"demo/search.html\">Search/replace</a></li>\n      <li><a href=\"demo/folding.html\">Code folding</a></li>\n      <li><a href=\"demo/preview.html\">HTML editor with preview</a></li>\n      <li><a href=\"demo/resize.html\">Auto-resizing editor</a></li>\n      <li><a href=\"demo/marker.html\">Setting breakpoints</a></li>\n      <li><a href=\"demo/activeline.html\">Highlighting the current line</a></li>\n      <li><a href=\"demo/matchhighlighter.html\">Highlighting selection matches</a></li>\n      <li><a href=\"demo/theme.html\">Theming</a></li>\n      <li><a href=\"demo/runmode.html\">Stand-alone highlighting</a></li>\n      <li><a href=\"demo/fullscreen.html\">Full-screen editing</a></li>\n      <li><a href=\"demo/changemode.html\">Mode auto-changing</a></li>\n      <li><a href=\"demo/visibletabs.html\">Visible tabs</a></li>\n      <li><a href=\"demo/formatting.html\">Autoformatting of code</a></li>\n      <li><a href=\"demo/emacs.html\">Emacs keybindings</a></li>\n      <li><a href=\"demo/vim.html\">Vim keybindings</a></li>\n      <li><a href=\"demo/closetag.html\">Automatic xml tag closing</a></li>\n      <li><a href=\"demo/loadmode.html\">Lazy mode loading</a></li>\n    </ul>\n\n    <h2>Real-world uses:</h2>\n\n    <ul>\n      <li><a href=\"http://jsbin.com\">jsbin.com</a> (JS playground)</li>\n      <li><a href=\"http://buzzard.ups.edu/\">Sage demo</a> (math system)</li>\n      <li><a href=\"http://www.sourcelair.com/\">sourceLair</a> (online IDE)</li>\n      <li><a href=\"http://eloquentjavascript.net/chapter1.html\">Eloquent JavaScript</a> (book)</a></li>\n      <li><a href=\"http://www.mergely.com/\">Mergely</a> (interactive diffing)</li>\n      <li><a href=\"http://paperjs.org/\">Paper.js</a> (graphics scripting)</li>\n      <li><a href=\"http://www.wescheme.org/\">WeScheme</a> (learning tool)</li>\n      <li><a href=\"http://webglplayground.net/\">WebGL playground</a></li>\n      <li><a href=\"http://ql.io/\">ql.io</a> (http API query helper)</li>\n      <li><a href=\"http://elm-lang.org/Examples.elm\">Elm language examples</a></li>\n      <li><a href=\"http://bluegriffon.org/\">BlueGriffon</a> (HTML editor)</li>\n      <li><a href=\"http://www.jshint.com/\">JSHint</a> (JS linter)</li>\n      <li><a href=\"http://kl1p.com/cmtest/1\">kl1p</a> (paste service)</li>\n      <li><a href=\"http://sqlfiddle.com\">SQLFiddle</a> (SQL playground)</li>\n      <li><a href=\"http://tour.golang.org\">Go language tour</a></li>\n      <li><a href=\"http://cssdeck.com/\">CSSDeck</a> (CSS showcase)</li>\n      <li><a href=\"http://www.ckwnc.com/\">CKWNC</a> (UML editor)</li>\n      <li><a href=\"http://www.sketchpatch.net/labs/livecodelabIntro.html\">sketchPatch Livecodelab</a></li>\n      <li><a href=\"https://thefiletree.com\">The File Tree</a> (collab editor)</li>\n      <li><a href=\"http://enjalot.com/tributary/2636296/sinwaves.js\">Tributary</a> (augmented editing)</li>\n    </ul>\n\n  </div></div>\n\n  <h2 id=\"code\">Getting the code</h2>\n\n  <p>All of CodeMirror is released under a <a\n  href=\"LICENSE\">MIT-style</a> license. To get it, you can download\n  the <a href=\"http://codemirror.net/codemirror.zip\">latest\n  release</a> or the current <a\n  href=\"http://codemirror.net/codemirror2-latest.zip\">development\n  snapshot</a> as zip files. To create a custom minified script file,\n  you can use the <a href=\"doc/compress.html\">compression API</a>.</p>\n\n  <p>We use <a href=\"http://git-scm.com/\">git</a> for version control.\n  The main repository can be fetched in this way:</p>\n\n  <pre class=\"code\">git clone http://marijnhaverbeke.nl/git/codemirror2</pre>\n\n  <p>CodeMirror can also be found on GitHub at <a\n  href=\"http://github.com/marijnh/CodeMirror2\">marijnh/CodeMirror2</a>.\n  If you plan to hack on the code and contribute patches, the best way\n  to do it is to create a GitHub fork, and send pull requests.</p>\n\n  <h2 id=\"documention\">Documentation</h2>\n\n  <p>The <a href=\"doc/manual.html\">manual</a> is your first stop for\n  learning how to use this library. It starts with a quick explanation\n  of how to use the editor, and then describes the API in detail.</p>\n\n  <p>For those who want to learn more about the code, there is\n  an <a href=\"doc/internals.html\">overview of the internals</a> available.\n  The <a href=\"http://github.com/marijnh/CodeMirror2\">source code</a>\n  itself is, for the most part, also well commented.</p>\n\n  <h2 id=\"support\">Support and bug reports</h2>\n\n  <p>There is\n  a <a href=\"http://groups.google.com/group/codemirror\">Google\n  group</a> (a sort of mailing list/newsgroup thing) for discussion\n  and news related to CodeMirror. When reporting a bug,\n  <a href=\"doc/reporting.html\">read this first</a>. If you have\n  a <a href=\"http://github.com\">github</a> account,\n  simply <a href=\"http://github.com/marijnh/CodeMirror2/issues\">open\n  an issue there</a>. Otherwise, post something to\n  the <a href=\"http://groups.google.com/group/codemirror\">group</a>,\n  or e-mail me directly: <a href=\"mailto:marijnh@gmail.com\">Marijn\n  Haverbeke</a>.</p>\n\n  <h2 id=\"supported\">Supported browsers</h2>\n\n  <p>The following browsers are able to run CodeMirror:</p>\n\n  <ul>\n    <li>Firefox 2 or higher</li>\n    <li>Chrome, any version</li>\n    <li>Safari 3 or higher</li>\n    <li>Internet Explorer 7 or higher in standards (<strong>non-quirks</strong>) mode</li>\n    <li>Opera 9 or higher (with some key-handling problems on OS X)</li>\n  </ul>\n\n  <p>I am not actively testing against every new browser release, and\n  vendors have a habit of introducing bugs all the time, so I am\n  relying on the community to tell me when something breaks.\n  See <a href=\"#support\">here</a> for information on how to contact\n  me.</p>\n\n  <h2 id=\"commercial\">Commercial support</h2>\n\n  <p>CodeMirror is developed and maintained by me, Marijn Haverbeke,\n  in my own time. If your company is getting value out of CodeMirror,\n  please consider purchasing a support contract.</p>\n\n  <ul>\n    <li>You'll be funding further work on CodeMirror.</li>\n    <li>You ensure that you get a quick response when you have a\n    problem, even when I am otherwise busy.</li>\n  </ul>\n\n  <p>CodeMirror support contracts exist in two\n  forms—<strong>basic</strong> at €100 per month,\n  and <strong>premium</strong> at €500 per\n  month. <a href=\"mailto:marijnh@gmail.com\">Contact me</a> for further\n  information.</p>\n\n</div>\n\n<div class=\"right blk\">\n\n  <a href=\"http://codemirror.net/codemirror.zip\" class=\"download\">Download the latest release</a>\n\n  <h2>Support CodeMirror</h2>\n\n  <ul>\n    <li>Donate\n    (<span onclick=\"document.getElementById('paypal').submit();\"\n    class=\"quasilink\">Paypal</span>\n    or <span onclick=\"document.getElementById('bankinfo').style.display = 'block';\"\n             class=\"quasilink\">bank</span>)</li>\n    <li>Purchase <a href=\"#commercial\">commercial support</a></li>\n  </ul>\n\n  <p id=\"bankinfo\" style=\"display: none;\">\n    Bank: <i>Rabobank</i><br/>\n    Country: <i>Netherlands</i><br/>\n    SWIFT: <i>RABONL2U</i><br/>\n    Account: <i>147850770</i><br/>\n    Name: <i>Marijn Haverbeke</i><br/>\n    IBAN: <i>NL26 RABO 0147 8507 70</i>\n  </p>\n\n  <h2>Releases:</h2>\n\n  <p class=\"rel\">23-05-2012: <a href=\"http://codemirror.net/codemirror-2.25.zip\">Version 2.25</a>:</p>\n\n  <ul class=\"rel-note\">\n    <li>New mode: <a href=\"mode/erlang/index.html\">Erlang</a>.</li>\n    <li><strong>Remove xmlpure mode</strong> (use <a href=\"mode/xml/index.html\">xml.js</a>).</li>\n    <li>Fix line-wrapping in Opera.</li>\n    <li>Fix X Windows middle-click paste in Chrome.</li>\n    <li>Fix bug that broke pasting of huge documents.</li>\n    <li>Fix backspace and tab key repeat in Opera.</li>\n  </ul>\n\n  <p class=\"rel\">23-04-2012: <a href=\"http://codemirror.net/codemirror-2.24.zip\">Version 2.24</a>:</p>\n\n  <ul class=\"rel-note\">\n    <li><strong>Drop support for Internet Explorer 6</strong>.</li>\n    <li>New\n    modes: <a href=\"mode/shell/index.html\">Shell</a>, <a href=\"mode/tiki/index.html\">Tiki\n    wiki</a>, <a href=\"mode/pig/index.html\">Pig Latin</a>.</li>\n    <li>New themes: <a href=\"demo/theme.html?ambiance\">Ambiance</a>, <a href=\"demo/theme.html?blackboard\">Blackboard</a>.</li>\n    <li>More control over drag/drop\n    with <a href=\"doc/manual.html#option_dragDrop\"><code>dragDrop</code></a>\n    and <a href=\"doc/manual.html#option_onDragEvent\"><code>onDragEvent</code></a>\n    options.</li>\n    <li>Make HTML mode a bit less pedantic.</li>\n    <li>Add <a href=\"doc/manual.html#compoundChange\"><code>compoundChange</code></a> API method.</li>\n    <li>Several fixes in undo history and line hiding.</li>\n    <li>Remove (broken) support for <code>catchall</code> in key maps,\n    add <code>nofallthrough</code> boolean field instead.</li>\n  </ul>\n\n  <p class=\"rel\">26-03-2012: <a href=\"http://codemirror.net/codemirror-2.23.zip\">Version 2.23</a>:</p>\n\n  <ul class=\"rel-note\">\n    <li>Change <strong>default binding for tab</strong> <a href=\"javascript:void(document.getElementById('tabbinding').style.display='')\">[more]</a>\n      <div style=\"display: none\" id=tabbinding>\n        Starting in 2.23, these bindings are default:\n        <ul><li>Tab: Insert tab character</li>\n          <li>Shift-tab: Reset line indentation to default</li>\n          <li>Ctrl/Cmd-[: Reduce line indentation (old tab behaviour)</li>\n          <li>Ctrl/Cmd-]: Increase line indentation (old shift-tab behaviour)</li>\n        </ul>\n      </div>\n    </li>\n    <li>New modes: <a href=\"mode/xquery/index.html\">XQuery</a> and <a href=\"mode/vbscript/index.html\">VBScript</a>.</li>\n    <li>Two new themes: <a href=\"mode/less/index.html\">lesser-dark</a> and <a href=\"mode/xquery/index.html\">xq-dark</a>.</li>\n    <li>Differentiate between background and text styles in <a href=\"doc/manual.html#setLineClass\"><code>setLineClass</code></a>.</li>\n    <li>Fix drag-and-drop in IE9+.</li>\n    <li>Extend <a href=\"doc/manual.html#charCoords\"><code>charCoords</code></a>\n    and <a href=\"doc/manual.html#cursorCoords\"><code>cursorCoords</code></a> with a <code>mode</code> argument.</li>\n    <li>Add <a href=\"doc/manual.html#option_autofocus\"><code>autofocus</code></a> option.</li>\n    <li>Add <a href=\"doc/manual.html#findMarksAt\"><code>findMarksAt</code></a> method.</li>\n  </ul>\n\n  <p class=\"rel\">27-02-2012: <a href=\"http://codemirror.net/codemirror-2.22.zip\">Version 2.22</a>:</p>\n\n  <ul class=\"rel-note\">\n    <li>Allow <a href=\"doc/manual.html#keymaps\">key handlers</a> to pass up events, allow binding characters.</li>\n    <li>Add <a href=\"doc/manual.html#option_autoClearEmptyLines\"><code>autoClearEmptyLines</code></a> option.</li>\n    <li>Properly use tab stops when rendering tabs.</li>\n    <li>Make PHP mode more robust.</li>\n    <li>Support indentation blocks in <a href=\"doc/manual.html#util_foldcode\">code folder</a>.</li>\n    <li>Add a script for <a href=\"doc/manual.html#util_match-highlighter\">highlighting instances of the selection</a>.</li>\n    <li>New <a href=\"mode/properties/index.html\">.properties</a> mode.</li>\n    <li>Fix many bugs.</li>\n  </ul>\n\n  <p class=\"rel\">27-01-2012: <a href=\"http://codemirror.net/codemirror-2.21.zip\">Version 2.21</a>:</p>\n\n  <ul class=\"rel-note\">\n    <li>Added <a href=\"mode/less/index.html\">LESS</a>, <a href=\"mode/mysql/index.html\">MySQL</a>,\n    <a href=\"mode/go/index.html\">Go</a>, and <a href=\"mode/verilog/index.html\">Verilog</a> modes.</li>\n    <li>Add <a href=\"doc/manual.html#option_smartIndent\"><code>smartIndent</code></a>\n    option.</li>\n    <li>Support a cursor in <a href=\"doc/manual.html#option_readOnly\"><code>readOnly</code></a>-mode.</li>\n    <li>Support assigning multiple styles to a token.</li>\n    <li>Use a new approach to drawing the selection.</li>\n    <li>Add <a href=\"doc/manual.html#scrollTo\"><code>scrollTo</code></a> method.</li>\n    <li>Allow undo/redo events to span non-adjacent lines.</li>\n    <li>Lots and lots of bugfixes.</li>\n  </ul>\n\n  <p class=\"rel\">20-12-2011: <a href=\"http://codemirror.net/codemirror-2.2.zip\">Version 2.2</a>:</p>\n\n  <ul class=\"rel-note\">\n    <li>Slightly incompatible API changes. Read <a href=\"doc/upgrade_v2.2.html\">this</a>.</li>\n    <li>New approach\n    to <a href=\"doc/manual.html#option_extraKeys\">binding</a> keys,\n    support for <a href=\"doc/manual.html#option_keyMap\">custom\n    bindings</a>.</li>\n    <li>Support for overwrite (insert).</li>\n    <li><a href=\"doc/manual.html#option_tabSize\">Custom-width</a>\n    and <a href=\"demo/visibletabs.html\">stylable</a> tabs.</li>\n    <li>Moved more code into <a href=\"doc/manual.html#addons\">add-on scripts</a>.</li>\n    <li>Support for sane vertical cursor movement in wrapped lines.</li>\n    <li>More reliable handling of\n    editing <a href=\"doc/manual.html#markText\">marked text</a>.</li>\n    <li>Add minimal <a href=\"demo/emacs.html\">emacs</a>\n    and <a href=\"demo/vim.html\">vim</a> bindings.</li>\n    <li>Rename <code>coordsFromIndex</code>\n    to <a href=\"doc/manual.html#posFromIndex\"><code>posFromIndex</code></a>,\n    add <a href=\"doc/manual.html#indexFromPos\"><code>indexFromPos</code></a>\n    method.</li>\n  </ul>\n\n  <p class=\"rel\">21-11-2011: <a href=\"http://codemirror.net/codemirror-2.18.zip\">Version 2.18</a>:</p>\n  <p class=\"rel-note\">Fixes <code>TextMarker.clear</code>, which is broken in 2.17.</p>\n\n  <p class=\"rel\">21-11-2011: <a href=\"http://codemirror.net/codemirror-2.17.zip\">Version 2.17</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Add support for <a href=\"doc/manual.html#option_lineWrapping\">line\n    wrapping</a> and <a href=\"doc/manual.html#hideLine\">code\n    folding</a>.</li>\n    <li>Add <a href=\"mode/gfm/index.html\">Github-style Markdown</a> mode.</li>\n    <li>Add <a href=\"theme/monokai.css\">Monokai</a>\n    and <a href=\"theme/rubyblue.css\">Rubyblue</a> themes.</li>\n    <li>Add <a href=\"doc/manual.html#setBookmark\"><code>setBookmark</code></a> method.</li>\n    <li>Move some of the demo code into reusable components\n    under <a href=\"lib/util/\"><code>lib/util</code></a>.</li>\n    <li>Make screen-coord-finding code faster and more reliable.</li>\n    <li>Fix drag-and-drop in Firefox.</li>\n    <li>Improve support for IME.</li>\n    <li>Speed up content rendering.</li>\n    <li>Fix browser's built-in search in Webkit.</li>\n    <li>Make double- and triple-click work in IE.</li>\n    <li>Various fixes to modes.</li>\n  </ul>\n\n  <p class=\"rel\">27-10-2011: <a href=\"http://codemirror.net/codemirror-2.16.zip\">Version 2.16</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Add <a href=\"mode/perl/index.html\">Perl</a>, <a href=\"mode/rust/index.html\">Rust</a>, <a href=\"mode/tiddlywiki/index.html\">TiddlyWiki</a>, and <a href=\"mode/groovy/index.html\">Groovy</a> modes.</li>\n    <li>Dragging text inside the editor now moves, rather than copies.</li>\n    <li>Add a <a href=\"doc/manual.html#coordsFromIndex\"><code>coordsFromIndex</code></a> method.</li>\n    <li><strong>API change</strong>: <code>setValue</code> now no longer clears history. Use <a href=\"doc/manual.html#clearHistory\"><code>clearHistory</code></a> for that.</li>\n    <li><strong>API change</strong>: <a href=\"doc/manual.html#markText\"><code>markText</code></a> now\n    returns an object with <code>clear</code> and <code>find</code>\n    methods. Marked text is now more robust when edited.</li>\n    <li>Fix editing code with tabs in Internet Explorer.</li>\n  </ul>\n\n  <p class=\"rel\">26-09-2011: <a href=\"http://codemirror.net/codemirror-2.15.zip\">Version 2.15</a>:</p>\n  <p class=\"rel-note\">Fix bug that snuck into 2.14: Clicking the\n  character that currently has the cursor didn't re-focus the\n  editor.</p>\n\n  <p class=\"rel\">26-09-2011: <a href=\"http://codemirror.net/codemirror-2.14.zip\">Version 2.14</a>:</p>\n  <ul class=\"rel-note\">\n    <li>Add <a href=\"mode/clojure/index.html\">Clojure</a>, <a href=\"mode/pascal/index.html\">Pascal</a>, <a href=\"mode/ntriples/index.html\">NTriples</a>, <a href=\"mode/jinja2/index.html\">Jinja2</a>, and <a href=\"mode/markdown/index.html\">Markdown</a> modes.</li>\n    <li>Add <a href=\"theme/cobalt.css\">Cobalt</a> and <a href=\"theme/eclipse.css\">Eclipse</a> themes.</li>\n    <li>Add a <a href=\"doc/manual.html#option_fixedGutter\"><code>fixedGutter</code></a> option.</li>\n    <li>Fix bug with <code>setValue</code> breaking cursor movement.</li>\n    <li>Make gutter updates much more efficient.</li>\n    <li>Allow dragging of text out of the editor (on modern browsers).</li>\n  </ul>\n\n  <p><a href=\"doc/oldrelease.html\">Older releases...</a></p>\n\n</div></div>\n\n<div style=\"height: 2em\">&nbsp;</div>\n\n  <form action=\"https://www.paypal.com/cgi-bin/webscr\" method=\"post\" id=\"paypal\">\n    <input type=\"hidden\" name=\"cmd\" value=\"_s-xclick\"/>\n    <input type=\"hidden\" name=\"hosted_button_id\" value=\"3FVHS5FGUY7CC\"/>\n  </form>\n\n  </body>\n</html>\n\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/keymap/emacs.js",
    "content": "// TODO number prefixes\n(function() {\n  // Really primitive kill-ring implementation.\n  var killRing = [];\n  function addToRing(str) {\n    killRing.push(str);\n    if (killRing.length > 50) killRing.shift();\n  }\n  function getFromRing() { return killRing[killRing.length - 1] || \"\"; }\n  function popFromRing() { if (killRing.length > 1) killRing.pop(); return getFromRing(); }\n\n  CodeMirror.keyMap.emacs = {\n    \"Ctrl-X\": function(cm) {cm.setOption(\"keyMap\", \"emacs-Ctrl-X\");},\n    \"Ctrl-W\": function(cm) {addToRing(cm.getSelection()); cm.replaceSelection(\"\");},\n    \"Ctrl-Alt-W\": function(cm) {addToRing(cm.getSelection()); cm.replaceSelection(\"\");},\n    \"Alt-W\": function(cm) {addToRing(cm.getSelection());},\n    \"Ctrl-Y\": function(cm) {cm.replaceSelection(getFromRing());},\n    \"Alt-Y\": function(cm) {cm.replaceSelection(popFromRing());},\n    \"Ctrl-/\": \"undo\", \"Shift-Ctrl--\": \"undo\", \"Shift-Alt-,\": \"goDocStart\", \"Shift-Alt-.\": \"goDocEnd\",\n    \"Ctrl-S\": \"findNext\", \"Ctrl-R\": \"findPrev\", \"Ctrl-G\": \"clearSearch\", \"Shift-Alt-5\": \"replace\",\n    \"Ctrl-Z\": \"undo\", \"Cmd-Z\": \"undo\", \"Alt-/\": \"autocomplete\",\n    fallthrough: [\"basic\", \"emacsy\"]\n  };\n\n  CodeMirror.keyMap[\"emacs-Ctrl-X\"] = {\n    \"Ctrl-S\": \"save\", \"Ctrl-W\": \"save\", \"S\": \"saveAll\", \"F\": \"open\", \"U\": \"undo\", \"K\": \"close\",\n    auto: \"emacs\", nofallthrough: true\n  };\n})();\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/keymap/vim.js",
    "content": "// Supported keybindings:\n// \n// Cursor movement:\n// h, j, k, l\n// e, E, w, W, b, B\n// Ctrl-f, Ctrl-b\n// Ctrl-n, Ctrl-p\n// $, ^, 0\n// G\n// ge, gE\n// gg\n// f<char>, F<char>, t<char>, T<char> \n// Ctrl-o, Ctrl-i TODO (FIXME - Ctrl-O wont work in Chrome)\n// /, ?, n, N TODO (does not work)\n// #, * TODO\n//\n// Entering insert mode:\n// i, I, a, A, o, O\n// s\n// ce, cb (without support for number of actions like c3e - TODO)\n// cc\n// S, C TODO\n// cf<char>, cF<char>, ct<char>, cT<char>\n//\n// Deleting text:\n// x, X \n// J\n// dd, D\n// de, db (without support for number of actions like d3e - TODO)\n// df<char>, dF<char>, dt<char>, dT<char> \n//\n// Yanking and pasting:\n// yy, Y\n// p, P\n// p'<char> TODO - test\n// y'<char> TODO - test\n// m<char> TODO - test\n//\n// Changing text in place:\n// ~\n// r<char>\n//\n// Visual mode:\n// v, V TODO\n//\n// Misc:\n// . TODO\n//\n\n\n(function() {\n  var count = \"\";\n  var sdir = \"f\";\n  var buf = \"\";\n  var yank = 0;\n  var mark = [];\n  function emptyBuffer() { buf = \"\"; }\n  function pushInBuffer(str) { buf += str; };\n  function pushCountDigit(digit) { return function(cm) {count += digit;} }\n  function popCount() { var i = parseInt(count); count = \"\"; return i || 1; }\n  function iterTimes(func) {\n    for (var i = 0, c = popCount(); i < c; ++i) func(i, i == c - 1);\n  }\n  function countTimes(func) {\n    if (typeof func == \"string\") func = CodeMirror.commands[func];\n    return function(cm) { iterTimes(function () { func(cm); }) };\n  }\n\n  function iterObj(o, f) {\n    for (var prop in o) if (o.hasOwnProperty(prop)) f(prop, o[prop]);\n  }\n  function iterList(l, f) {\n    for (var i in l) f(l[i]);\n  }\n  function toLetter(ch) {\n    // T -> t, Shift-T -> T, '*' -> *, \"Space\" -> \" \"\n    if (ch.slice(0, 6) == \"Shift-\") {\n      return ch.slice(0, 1);\n    } else {\n      if (ch == \"Space\") return \" \";\n      if (ch.length == 3 && ch[0] == \"'\" && ch[2] == \"'\") return ch[1];\n      return ch.toLowerCase();\n    }\n  }\n  var SPECIAL_SYMBOLS = \"~`!@#$%^&*()_-+=[{}]\\\\|/?.,<>:;\\\"\\'1234567890\"; \n  function toCombo(ch) { \n    // t -> T, T -> Shift-T, * -> '*', \" \" -> \"Space\"\n    if (ch == \" \") return \"Space\";\n    var specialIdx = SPECIAL_SYMBOLS.indexOf(ch);\n    if (specialIdx != -1) return \"'\" + ch + \"'\";\n    if (ch.toLowerCase() == ch) return ch.toUpperCase();\n    return \"Shift-\" + ch.toUpperCase();\n  }\n\n  var word = [/\\w/, /[^\\w\\s]/], bigWord = [/\\S/];\n  function findWord(line, pos, dir, regexps) {\n    var stop = 0, next = -1;\n    if (dir > 0) { stop = line.length; next = 0; }\n    var start = stop, end = stop;\n    // Find bounds of next one.\n    outer: for (; pos != stop; pos += dir) {\n      for (var i = 0; i < regexps.length; ++i) {\n        if (regexps[i].test(line.charAt(pos + next))) {\n          start = pos;\n          for (; pos != stop; pos += dir) {\n            if (!regexps[i].test(line.charAt(pos + next))) break;\n          }\n          end = pos;\n          break outer;\n        }\n      }\n    }\n    return {from: Math.min(start, end), to: Math.max(start, end)};\n  }\n  function moveToWord(cm, regexps, dir, where) {\n    var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line), word;\n    while (true) {\n      word = findWord(line, ch, dir, regexps);\n      ch = word[where == \"end\" ? \"to\" : \"from\"];\n      if (ch == cur.ch && word.from != word.to) ch = word[dir < 0 ? \"from\" : \"to\"];\n      else break;\n    }\n    cm.setCursor(cur.line, word[where == \"end\" ? \"to\" : \"from\"], true);\n  }\n  function joinLineNext(cm) {\n    var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line);\n    CodeMirror.commands.goLineEnd(cm); \n    if (cur.line != cm.lineCount()) {\n      CodeMirror.commands.goLineEnd(cm);\n      cm.replaceSelection(\" \", \"end\");\n      CodeMirror.commands.delCharRight(cm);\n    } \n  }\n  function delTillMark(cm, cHar) { \n    var i = mark[cHar];\n    if (i === undefined) {\n      // console.log(\"Mark not set\"); // TODO - show in status bar\n      return;\n    }\n    var l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;\n    cm.setCursor(start);\n    for (var c = start; c <= end; c++) {\n      pushInBuffer(\"\\n\"+cm.getLine(start)); \n      cm.removeLine(start);\n    }\n  }\n  function yankTillMark(cm, cHar) { \n    var i = mark[cHar];\n    if (i === undefined) {\n      // console.log(\"Mark not set\"); // TODO - show in status bar\n      return;\n    }\n    var l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;\n    for (var c = start; c <= end; c++) {\n      pushInBuffer(\"\\n\"+cm.getLine(c));\n    }\n    cm.setCursor(start);\n  }\n  function goLineStartText(cm) {\n    // Go to the start of the line where the text begins, or the end for whitespace-only lines\n    var cur = cm.getCursor(), firstNonWS = cm.getLine(cur.line).search(/\\S/);\n    cm.setCursor(cur.line, firstNonWS == -1 ? line.length : firstNonWS, true);\n  }\n\n  function charIdxInLine(cm, cHar, motion_options) {\n    // Search for cHar in line. \n    // motion_options: {forward, inclusive}\n    // If inclusive = true, include it too.\n    // If forward = true, search forward, else search backwards.\n    // If char is not found on this line, do nothing\n    var cur = cm.getCursor(), line = cm.getLine(cur.line), idx;\n    var ch = toLetter(cHar), mo = motion_options;\n    if (mo.forward) {\n      idx = line.indexOf(ch, cur.ch + 1); \n      if (idx != -1 && mo.inclusive) idx += 1;\n    } else {\n      idx = line.lastIndexOf(ch, cur.ch);\n      if (idx != -1 && !mo.inclusive) idx += 1;\n    }\n    return idx;\n  }\n\n  function moveTillChar(cm, cHar, motion_options) {\n    // Move to cHar in line, as found by charIdxInLine. \n    var idx = charIdxInLine(cm, cHar, motion_options), cur = cm.getCursor();\n    if (idx != -1) cm.setCursor({line: cur.line, ch: idx}); \n  }\n\n  function delTillChar(cm, cHar, motion_options) {\n    // delete text in this line, untill cHar is met,\n    // as found by charIdxInLine.\n    // If char is not found on this line, do nothing\n    var idx = charIdxInLine(cm, cHar, motion_options);\n    var cur = cm.getCursor();\n    if (idx !== -1) {\n      if (motion_options.forward) {\n        cm.replaceRange(\"\", {line: cur.line, ch: cur.ch}, {line: cur.line, ch: idx});\n      } else {\n        cm.replaceRange(\"\", {line: cur.line, ch: idx}, {line: cur.line, ch: cur.ch});\n      }\n    }\n  }\n\n  function enterInsertMode(cm) {\n    // enter insert mode: switch mode and cursor\n    if (!cm) console.log(\"call enterInsertMode with 'cm' as an argument\");\n    popCount();\n    cm.setOption(\"keyMap\", \"vim-insert\");\n  }\n\n  // main keymap\n  var map = CodeMirror.keyMap.vim = {\n    // Pipe (|); TODO: should be *screen* chars, so need a util function to turn tabs into spaces?\n    \"'|'\": function(cm) {\n      cm.setCursor(cm.getCursor().line, popCount() - 1, true);\n    },\n    \"'^'\": function(cm) { popCount(); goLineStartText(cm);},\n    \"A\": function(cm) {\n      cm.setCursor(cm.getCursor().line, cm.getCursor().ch+1, true);\n      enterInsertMode(cm);\n    },\n    \"Shift-A\": function(cm) { CodeMirror.commands.goLineEnd(cm); enterInsertMode(cm);},\n    \"I\": function(cm) { enterInsertMode(cm);},\n    \"Shift-I\": function(cm) { goLineStartText(cm); enterInsertMode(cm);},\n    \"O\": function(cm) {\n      CodeMirror.commands.goLineEnd(cm);\n      CodeMirror.commands.newlineAndIndent(cm);\n      enterInsertMode(cm);\n    },\n    \"Shift-O\": function(cm) {\n      CodeMirror.commands.goLineStart(cm);\n      cm.replaceSelection(\"\\n\", \"start\");\n      cm.indentLine(cm.getCursor().line);\n      enterInsertMode(cm);\n    },\n    \"G\": function(cm) { cm.setOption(\"keyMap\", \"vim-prefix-g\");},\n    \"Shift-D\": function(cm) {\n      // commented out verions works, but I left original, cause maybe \n      // I don't know vim enouth to see what it does\n      /* var cur = cm.getCursor();\n      var f = {line: cur.line, ch: cur.ch}, t = {line: cur.line};\n      pushInBuffer(cm.getRange(f, t));\n      cm.replaceRange(\"\", f, t);\n      */\n      emptyBuffer();\n      mark[\"Shift-D\"] = cm.getCursor(false).line;\n      cm.setCursor(cm.getCursor(true).line);\n      delTillMark(cm,\"Shift-D\"); mark = [];\n    },\n\n    \"S\": function (cm) {\n      countTimes(function (_cm) {\n        CodeMirror.commands.delCharRight(_cm);\n      })(cm);\n      enterInsertMode(cm);\n    },\n    \"M\": function(cm) {cm.setOption(\"keyMap\", \"vim-prefix-m\"); mark = [];},\n    \"Y\": function(cm) {cm.setOption(\"keyMap\", \"vim-prefix-y\"); emptyBuffer(); yank = 0;},\n    \"Shift-Y\": function(cm) {\n      emptyBuffer();\n      mark[\"Shift-D\"] = cm.getCursor(false).line;\n      cm.setCursor(cm.getCursor(true).line);\n      yankTillMark(cm,\"Shift-D\"); mark = [];\n    },\n    \"/\": function(cm) {var f = CodeMirror.commands.find; f && f(cm); sdir = \"f\";},\n    \"'?'\": function(cm) {\n      var f = CodeMirror.commands.find;\n      if (f) { f(cm); CodeMirror.commands.findPrev(cm); sdir = \"r\"; }\n    },\n    \"N\": function(cm) {\n      var fn = CodeMirror.commands.findNext;\n      if (fn) sdir != \"r\" ? fn(cm) : CodeMirror.commands.findPrev(cm);\n    },\n    \"Shift-N\": function(cm) {\n      var fn = CodeMirror.commands.findNext;\n      if (fn) sdir != \"r\" ? CodeMirror.commands.findPrev(cm) : fn.findNext(cm);\n    },\n    \"Shift-G\": function(cm) {\n      count == \"\" ? cm.setCursor(cm.lineCount()) : cm.setCursor(parseInt(count)-1);\n      popCount();\n      CodeMirror.commands.goLineStart(cm);\n    },\n    \"'$'\": function (cm) {\n      countTimes(\"goLineEnd\")(cm);\n      if (cm.getCursor().ch) CodeMirror.commands.goColumnLeft(cm);\n    },\n    nofallthrough: true, style: \"fat-cursor\"\n  };\n\n  // standard mode switching\n  iterList([\"d\", \"t\", \"T\", \"f\", \"F\", \"c\", \"r\"],\n      function (ch) {\n        CodeMirror.keyMap.vim[toCombo(ch)] = function (cm) {\n          cm.setOption(\"keyMap\", \"vim-prefix-\" + ch);\n          emptyBuffer();\n        };\n      });\n\n  function addCountBindings(keyMap) {\n    // Add bindings for number keys\n    keyMap[\"0\"] = function(cm) {\n      count.length > 0 ? pushCountDigit(\"0\")(cm) : CodeMirror.commands.goLineStart(cm);\n    };\n    for (var i = 1; i < 10; ++i) keyMap[i] = pushCountDigit(i);\n  }\n  addCountBindings(CodeMirror.keyMap.vim);\n\n  // main num keymap\n  // Add bindings that are influenced by number keys\n  iterObj({\n    \"H\": \"goColumnLeft\", \"L\": \"goColumnRight\", \"J\": \"goLineDown\",\n    \"K\": \"goLineUp\", \"Left\": \"goColumnLeft\", \"Right\": \"goColumnRight\",\n    \"Down\": \"goLineDown\", \"Up\": \"goLineUp\", \"Backspace\": \"goCharLeft\",\n    \"Space\": \"goCharRight\",\n    \"B\": function(cm) {moveToWord(cm, word, -1, \"end\");},\n    \"E\": function(cm) {moveToWord(cm, word, 1, \"end\");},\n    \"W\": function(cm) {moveToWord(cm, word, 1, \"start\");},\n    \"Shift-B\": function(cm) {moveToWord(cm, bigWord, -1, \"end\");},\n    \"Shift-E\": function(cm) {moveToWord(cm, bigWord, 1, \"end\");},\n    \"Shift-W\": function(cm) {moveToWord(cm, bigWord, 1, \"start\");},\n    \"X\": function(cm) {CodeMirror.commands.delCharRight(cm);},\n    \"P\": function(cm) {\n      var cur = cm.getCursor().line;\n      if (buf!= \"\") {\n        CodeMirror.commands.goLineEnd(cm); \n        cm.replaceSelection(buf, \"end\");\n      }\n      cm.setCursor(cur+1);\n    },\n    \"Shift-X\": function(cm) {CodeMirror.commands.delCharLeft(cm);},\n    \"Shift-J\": function(cm) {joinLineNext(cm);},\n    \"Shift-P\": function(cm) {\n      var cur = cm.getCursor().line;\n      if (buf!= \"\") {\n        CodeMirror.commands.goLineUp(cm); \n        CodeMirror.commands.goLineEnd(cm); \n        cm.replaceSelection(buf, \"end\");\n      }\n      cm.setCursor(cur+1);\n    },\n    \"'~'\": function(cm) {\n      var cur = cm.getCursor(), cHar = cm.getRange({line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});\n      cHar = cHar != cHar.toLowerCase() ? cHar.toLowerCase() : cHar.toUpperCase();\n      cm.replaceRange(cHar, {line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});\n      cm.setCursor(cur.line, cur.ch+1);\n    },\n    \"Ctrl-B\": function(cm) {CodeMirror.commands.goPageUp(cm);},\n    \"Ctrl-F\": function(cm) {CodeMirror.commands.goPageDown(cm);},\n    \"Ctrl-P\": \"goLineUp\", \"Ctrl-N\": \"goLineDown\", \n    \"U\": \"undo\", \"Ctrl-R\": \"redo\"\n  }, function(key, cmd) { map[key] = countTimes(cmd); });\n\n  // empty key maps\n  iterList([\n      \"vim-prefix-d'\", \n      \"vim-prefix-y'\", \n      \"vim-prefix-df\",\n      \"vim-prefix-dF\",\n      \"vim-prefix-dt\",\n      \"vim-prefix-dT\",\n      \"vim-prefix-c\",\n      \"vim-prefix-cf\",\n      \"vim-prefix-cF\",\n      \"vim-prefix-ct\",\n      \"vim-prefix-cT\",\n      \"vim-prefix-\",\n      \"vim-prefix-f\",\n      \"vim-prefix-F\",\n      \"vim-prefix-t\",\n      \"vim-prefix-T\",\n      \"vim-prefix-r\",\n      \"vim-prefix-m\"\n      ], \n      function (prefix) {\n        CodeMirror.keyMap[prefix] = {\n          auto: \"vim\", \n          nofallthrough: true\n        };\n      });\n\n  CodeMirror.keyMap[\"vim-prefix-g\"] = {\n    \"E\": countTimes(function(cm) { moveToWord(cm, word, -1, \"start\");}),\n    \"Shift-E\": countTimes(function(cm) { moveToWord(cm, bigWord, -1, \"start\");}),\n    \"G\": function (cm) { cm.setCursor({line: 0, ch: cm.getCursor().ch});},\n    auto: \"vim\", nofallthrough: true, style: \"fat-cursor\"\n  };\n\n  CodeMirror.keyMap[\"vim-prefix-d\"] = {\n    \"D\": countTimes(function(cm) {\n      pushInBuffer(\"\\n\"+cm.getLine(cm.getCursor().line));\n      cm.removeLine(cm.getCursor().line);\n    }),\n    \"'\": function(cm) {\n      cm.setOption(\"keyMap\", \"vim-prefix-d'\");\n      emptyBuffer();\n    },\n    \"E\": countTimes(\"delWordRight\"),\n    \"B\": countTimes(\"delWordLeft\"),\n    auto: \"vim\", nofallthrough: true, style: \"fat-cursor\"\n  }; \n  // FIXME - does not work for bindings like \"d3e\"\n  addCountBindings(CodeMirror.keyMap[\"vim-prefix-d\"]);\n\n  CodeMirror.keyMap[\"vim-prefix-c\"] = {\n    \"E\": function (cm) {\n      countTimes(\"delWordRight\")(cm);\n      enterInsertMode(cm);\n    },\n    \"B\": function (cm) {\n      countTimes(\"delWordLeft\")(cm);\n      enterInsertMode(cm);\n    },\n    \"C\": function (cm) {\n      iterTimes(function (i, last) {\n        CodeMirror.commands.deleteLine(cm);\n        if (i) {\n          CodeMirror.commands.delCharRight(cm);\n          if (last) CodeMirror.commands.deleteLine(cm);\n        }\n      });\n      enterInsertMode(cm);\n    },\n    auto: \"vim\", nofallthrough: true, style: \"fat-cursor\"\n  };\n\n  iterList([\"vim-prefix-d\", \"vim-prefix-c\", \"vim-prefix-\"], function (prefix) {\n    iterList([\"f\", \"F\", \"T\", \"t\"],\n      function (ch) {\n        CodeMirror.keyMap[prefix][toCombo(ch)] = function (cm) {\n          cm.setOption(\"keyMap\", prefix + ch);\n          emptyBuffer();\n        };\n      });\n  });\n\n  var MOTION_OPTIONS = {\n    \"t\": {inclusive: false, forward: true},\n    \"f\": {inclusive: true,  forward: true},\n    \"T\": {inclusive: false, forward: false},\n    \"F\": {inclusive: true,  forward: false}\n  };\n\n  function setupPrefixBindingForKey(m) {\n    CodeMirror.keyMap[\"vim-prefix-m\"][m] = function(cm) {\n      mark[m] = cm.getCursor().line;\n    };\n    CodeMirror.keyMap[\"vim-prefix-d'\"][m] = function(cm) {\n      delTillMark(cm,m);\n    };\n    CodeMirror.keyMap[\"vim-prefix-y'\"][m] = function(cm) {\n      yankTillMark(cm,m);\n    };\n    CodeMirror.keyMap[\"vim-prefix-r\"][m] = function (cm) {\n      var cur = cm.getCursor();\n      cm.replaceRange(toLetter(m), \n          {line: cur.line, ch: cur.ch},\n          {line: cur.line, ch: cur.ch + 1});\n      CodeMirror.commands.goColumnLeft(cm);\n    };\n    // all commands, related to motions till char in line\n    iterObj(MOTION_OPTIONS, function (ch, options) {\n      CodeMirror.keyMap[\"vim-prefix-\" + ch][m] = function(cm) {\n        moveTillChar(cm, m, options);\n      };\n      CodeMirror.keyMap[\"vim-prefix-d\" + ch][m] = function(cm) {\n        delTillChar(cm, m, options);\n      };\n      CodeMirror.keyMap[\"vim-prefix-c\" + ch][m] = function(cm) {\n        delTillChar(cm, m, options);\n        enterInsertMode(cm);\n      };\n    });\n  };\n  for (var i = 65; i < 65 + 26; i++) { // uppercase alphabet char codes\n    var ch = String.fromCharCode(i);\n    setupPrefixBindingForKey(toCombo(ch));\n    setupPrefixBindingForKey(toCombo(ch.toLowerCase()));\n  }\n  iterList(SPECIAL_SYMBOLS, function (ch) {\n    setupPrefixBindingForKey(toCombo(ch));\n  });\n  setupPrefixBindingForKey(\"Space\");\n\n  CodeMirror.keyMap[\"vim-prefix-y\"] = {\n    \"Y\": countTimes(function(cm) { pushInBuffer(\"\\n\"+cm.getLine(cm.getCursor().line+yank)); yank++; }),\n    \"'\": function(cm) {cm.setOption(\"keyMap\", \"vim-prefix-y'\"); emptyBuffer();},\n    auto: \"vim\", nofallthrough: true, style: \"fat-cursor\"\n  };\n\n  CodeMirror.keyMap[\"vim-insert\"] = {\n    // TODO: override navigation keys so that Esc will cancel automatic indentation from o, O, i_<CR>\n    \"Esc\": function(cm) {\n      cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true); \n      cm.setOption(\"keyMap\", \"vim\");\n    },\n    \"Ctrl-N\": \"autocomplete\",\n    \"Ctrl-P\": \"autocomplete\",\n    fallthrough: [\"default\"]\n  };\n})();\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/codemirror.css",
    "content": ".CodeMirror {\n  line-height: 1em;\n  font-family: monospace;\n}\n\n.CodeMirror-scroll {\n  overflow: auto;\n  height: 300px;\n  /* This is needed to prevent an IE[67] bug where the scrolled content\n     is visible outside of the scrolling box. */\n  position: relative;\n  outline: none;\n}\n\n.CodeMirror-gutter {\n  position: absolute; left: 0; top: 0;\n  z-index: 10;\n  background-color: #f7f7f7;\n  border-right: 1px solid #eee;\n  min-width: 2em;\n  height: 100%;\n}\n.CodeMirror-gutter-text {\n  color: #aaa;\n  text-align: right;\n  padding: .4em .2em .4em .4em;\n  white-space: pre !important;\n}\n.CodeMirror-lines {\n  padding: .4em;\n  white-space: pre;\n}\n\n.CodeMirror pre {\n  -moz-border-radius: 0;\n  -webkit-border-radius: 0;\n  -o-border-radius: 0;\n  border-radius: 0;\n  border-width: 0; margin: 0; padding: 0; background: transparent;\n  font-family: inherit;\n  font-size: inherit;\n  padding: 0; margin: 0;\n  white-space: pre;\n  word-wrap: normal;\n  line-height: inherit;\n  color: inherit;\n}\n\n.CodeMirror-wrap pre {\n  word-wrap: break-word;\n  white-space: pre-wrap;\n  word-break: normal;\n}\n.CodeMirror-wrap .CodeMirror-scroll {\n  overflow-x: hidden;\n}\n\n.CodeMirror textarea {\n  outline: none !important;\n}\n\n.CodeMirror pre.CodeMirror-cursor {\n  z-index: 10;\n  position: absolute;\n  visibility: hidden;\n  border-left: 1px solid black;\n  border-right: none;\n  width: 0;\n}\n.cm-keymap-fat-cursor pre.CodeMirror-cursor {\n  width: auto;\n  border: 0;\n  background: transparent;\n  background: rgba(0, 200, 0, .4);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);\n}\n/* Kludge to turn off filter in ie9+, which also accepts rgba */\n.cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) {\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n.CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {}\n.CodeMirror-focused pre.CodeMirror-cursor {\n  visibility: visible;\n}\n\ndiv.CodeMirror-selected { background: #d9d9d9; }\n.CodeMirror-focused div.CodeMirror-selected { background: #d7d4f0; }\n\n.CodeMirror-searching {\n  background: #ffa;\n  background: rgba(255, 255, 0, .4);\n}\n\n/* Default theme */\n\n.cm-s-default span.cm-keyword {color: #708;}\n.cm-s-default span.cm-atom {color: #219;}\n.cm-s-default span.cm-number {color: #164;}\n.cm-s-default span.cm-def {color: #00f;}\n.cm-s-default span.cm-variable {color: black;}\n.cm-s-default span.cm-variable-2 {color: #05a;}\n.cm-s-default span.cm-variable-3 {color: #085;}\n.cm-s-default span.cm-property {color: black;}\n.cm-s-default span.cm-operator {color: black;}\n.cm-s-default span.cm-comment {color: #a50;}\n.cm-s-default span.cm-string {color: #a11;}\n.cm-s-default span.cm-string-2 {color: #f50;}\n.cm-s-default span.cm-meta {color: #555;}\n.cm-s-default span.cm-error {color: #f00;}\n.cm-s-default span.cm-qualifier {color: #555;}\n.cm-s-default span.cm-builtin {color: #30a;}\n.cm-s-default span.cm-bracket {color: #cc7;}\n.cm-s-default span.cm-tag {color: #170;}\n.cm-s-default span.cm-attribute {color: #00c;}\n.cm-s-default span.cm-header {color: blue;}\n.cm-s-default span.cm-quote {color: #090;}\n.cm-s-default span.cm-hr {color: #999;}\n.cm-s-default span.cm-link {color: #00c;}\n\nspan.cm-header, span.cm-strong {font-weight: bold;}\nspan.cm-em {font-style: italic;}\nspan.cm-emstrong {font-style: italic; font-weight: bold;}\nspan.cm-link {text-decoration: underline;}\n\ndiv.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}\ndiv.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/codemirror.js",
    "content": "// CodeMirror version 2.25\n//\n// All functions that need access to the editor's state live inside\n// the CodeMirror function. Below that, at the bottom of the file,\n// some utilities are defined.\n\n// CodeMirror is the only global var we claim\nvar CodeMirror = (function() {\n  // This is the function that produces an editor instance. Its\n  // closure is used to store the editor state.\n  function CodeMirror(place, givenOptions) {\n    // Determine effective options based on given values and defaults.\n    var options = {}, defaults = CodeMirror.defaults;\n    for (var opt in defaults)\n      if (defaults.hasOwnProperty(opt))\n        options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt];\n\n    // The element in which the editor lives.\n    var wrapper = document.createElement(\"div\");\n    wrapper.className = \"CodeMirror\" + (options.lineWrapping ? \" CodeMirror-wrap\" : \"\");\n    // This mess creates the base DOM structure for the editor.\n    wrapper.innerHTML =\n      '<div style=\"overflow: hidden; position: relative; width: 3px; height: 0px;\">' + // Wraps and hides input textarea\n        '<textarea style=\"position: absolute; padding: 0; width: 1px; height: 1em\" wrap=\"off\" ' +\n          'autocorrect=\"off\" autocapitalize=\"off\"></textarea></div>' +\n      '<div class=\"CodeMirror-scroll\" tabindex=\"-1\">' +\n        '<div style=\"position: relative\">' + // Set to the height of the text, causes scrolling\n          '<div style=\"position: relative\">' + // Moved around its parent to cover visible view\n            '<div class=\"CodeMirror-gutter\"><div class=\"CodeMirror-gutter-text\"></div></div>' +\n            // Provides positioning relative to (visible) text origin\n            '<div class=\"CodeMirror-lines\"><div style=\"position: relative; z-index: 0\">' +\n              '<div style=\"position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden;\"></div>' +\n              '<pre class=\"CodeMirror-cursor\">&#160;</pre>' + // Absolutely positioned blinky cursor\n              '<div style=\"position: relative; z-index: -1\"></div><div></div>' + // DIVs containing the selection and the actual code\n            '</div></div></div></div></div>';\n    if (place.appendChild) place.appendChild(wrapper); else place(wrapper);\n    // I've never seen more elegant code in my life.\n    var inputDiv = wrapper.firstChild, input = inputDiv.firstChild,\n        scroller = wrapper.lastChild, code = scroller.firstChild,\n        mover = code.firstChild, gutter = mover.firstChild, gutterText = gutter.firstChild,\n        lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,\n        cursor = measure.nextSibling, selectionDiv = cursor.nextSibling,\n        lineDiv = selectionDiv.nextSibling;\n    themeChanged(); keyMapChanged();\n    // Needed to hide big blue blinking cursor on Mobile Safari\n    if (ios) input.style.width = \"0px\";\n    if (!webkit) lineSpace.draggable = true;\n    lineSpace.style.outline = \"none\";\n    if (options.tabindex != null) input.tabIndex = options.tabindex;\n    if (options.autofocus) focusInput();\n    if (!options.gutter && !options.lineNumbers) gutter.style.display = \"none\";\n    // Needed to handle Tab key in KHTML\n    if (khtml) inputDiv.style.height = \"1px\", inputDiv.style.position = \"absolute\";\n\n    // Check for problem with IE innerHTML not working when we have a\n    // P (or similar) parent node.\n    try { stringWidth(\"x\"); }\n    catch (e) {\n      if (e.message.match(/runtime/i))\n        e = new Error(\"A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)\");\n      throw e;\n    }\n\n    // Delayed object wrap timeouts, making sure only one is active. blinker holds an interval.\n    var poll = new Delayed(), highlight = new Delayed(), blinker;\n\n    // mode holds a mode API object. doc is the tree of Line objects,\n    // work an array of lines that should be parsed, and history the\n    // undo history (instance of History constructor).\n    var mode, doc = new BranchChunk([new LeafChunk([new Line(\"\")])]), work, focused;\n    loadMode();\n    // The selection. These are always maintained to point at valid\n    // positions. Inverted is used to remember that the user is\n    // selecting bottom-to-top.\n    var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false};\n    // Selection-related flags. shiftSelecting obviously tracks\n    // whether the user is holding shift.\n    var shiftSelecting, lastClick, lastDoubleClick, lastScrollPos = 0, draggingText,\n        overwrite = false, suppressEdits = false;\n    // Variables used by startOperation/endOperation to track what\n    // happened during the operation.\n    var updateInput, userSelChange, changes, textChanged, selectionChanged, leaveInputAlone,\n        gutterDirty, callbacks, maxLengthChanged;\n    // Current visible range (may be bigger than the view window).\n    var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;\n    // bracketHighlighted is used to remember that a bracket has been\n    // marked.\n    var bracketHighlighted;\n    // Tracks the maximum line length so that the horizontal scrollbar\n    // can be kept static when scrolling.\n    var maxLine = \"\", maxWidth;\n    var tabCache = {};\n\n    // Initialize the content.\n    operation(function(){setValue(options.value || \"\"); updateInput = false;})();\n    var history = new History();\n\n    // Register our event handlers.\n    connect(scroller, \"mousedown\", operation(onMouseDown));\n    connect(scroller, \"dblclick\", operation(onDoubleClick));\n    connect(lineSpace, \"selectstart\", e_preventDefault);\n    // Gecko browsers fire contextmenu *after* opening the menu, at\n    // which point we can't mess with it anymore. Context menu is\n    // handled in onMouseDown for Gecko.\n    if (!gecko) connect(scroller, \"contextmenu\", onContextMenu);\n    connect(scroller, \"scroll\", function() {\n      lastScrollPos = scroller.scrollTop;\n      updateDisplay([]);\n      if (options.fixedGutter) gutter.style.left = scroller.scrollLeft + \"px\";\n      if (options.onScroll) options.onScroll(instance);\n    });\n    connect(window, \"resize\", function() {updateDisplay(true);});\n    connect(input, \"keyup\", operation(onKeyUp));\n    connect(input, \"input\", fastPoll);\n    connect(input, \"keydown\", operation(onKeyDown));\n    connect(input, \"keypress\", operation(onKeyPress));\n    connect(input, \"focus\", onFocus);\n    connect(input, \"blur\", onBlur);\n\n    if (options.dragDrop) {\n      connect(lineSpace, \"dragstart\", onDragStart);\n      function drag_(e) {\n        if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;\n        e_stop(e);\n      }\n      connect(scroller, \"dragenter\", drag_);\n      connect(scroller, \"dragover\", drag_);\n      connect(scroller, \"drop\", operation(onDrop));\n    }\n    connect(scroller, \"paste\", function(){focusInput(); fastPoll();});\n    connect(input, \"paste\", fastPoll);\n    connect(input, \"cut\", operation(function(){\n      if (!options.readOnly) replaceSelection(\"\");\n    }));\n\n    // Needed to handle Tab key in KHTML\n    if (khtml) connect(code, \"mouseup\", function() {\n        if (document.activeElement == input) input.blur();\n        focusInput();\n    });\n\n    // IE throws unspecified error in certain cases, when\n    // trying to access activeElement before onload\n    var hasFocus; try { hasFocus = (document.activeElement == input); } catch(e) { }\n    if (hasFocus || options.autofocus) setTimeout(onFocus, 20);\n    else onBlur();\n\n    function isLine(l) {return l >= 0 && l < doc.size;}\n    // The instance object that we'll return. Mostly calls out to\n    // local functions in the CodeMirror function. Some do some extra\n    // range checking and/or clipping. operation is used to wrap the\n    // call so that changes it makes are tracked, and the display is\n    // updated afterwards.\n    var instance = wrapper.CodeMirror = {\n      getValue: getValue,\n      setValue: operation(setValue),\n      getSelection: getSelection,\n      replaceSelection: operation(replaceSelection),\n      focus: function(){window.focus(); focusInput(); onFocus(); fastPoll();},\n      setOption: function(option, value) {\n        var oldVal = options[option];\n        options[option] = value;\n        if (option == \"mode\" || option == \"indentUnit\") loadMode();\n        else if (option == \"readOnly\" && value == \"nocursor\") {onBlur(); input.blur();}\n        else if (option == \"readOnly\" && !value) {resetInput(true);}\n        else if (option == \"theme\") themeChanged();\n        else if (option == \"lineWrapping\" && oldVal != value) operation(wrappingChanged)();\n        else if (option == \"tabSize\") updateDisplay(true);\n        else if (option == \"keyMap\") keyMapChanged();\n        if (option == \"lineNumbers\" || option == \"gutter\" || option == \"firstLineNumber\" || option == \"theme\") {\n          gutterChanged();\n          updateDisplay(true);\n        }\n      },\n      getOption: function(option) {return options[option];},\n      undo: operation(undo),\n      redo: operation(redo),\n      indentLine: operation(function(n, dir) {\n        if (typeof dir != \"string\") {\n          if (dir == null) dir = options.smartIndent ? \"smart\" : \"prev\";\n          else dir = dir ? \"add\" : \"subtract\";\n        }\n        if (isLine(n)) indentLine(n, dir);\n      }),\n      indentSelection: operation(indentSelected),\n      historySize: function() {return {undo: history.done.length, redo: history.undone.length};},\n      clearHistory: function() {history = new History();},\n      matchBrackets: operation(function(){matchBrackets(true);}),\n      getTokenAt: operation(function(pos) {\n        pos = clipPos(pos);\n        return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), pos.ch);\n      }),\n      getStateAfter: function(line) {\n        line = clipLine(line == null ? doc.size - 1: line);\n        return getStateBefore(line + 1);\n      },\n      cursorCoords: function(start, mode) {\n        if (start == null) start = sel.inverted;\n        return this.charCoords(start ? sel.from : sel.to, mode);\n      },\n      charCoords: function(pos, mode) {\n        pos = clipPos(pos);\n        if (mode == \"local\") return localCoords(pos, false);\n        if (mode == \"div\") return localCoords(pos, true);\n        return pageCoords(pos);\n      },\n      coordsChar: function(coords) {\n        var off = eltOffset(lineSpace);\n        return coordsChar(coords.x - off.left, coords.y - off.top);\n      },\n      markText: operation(markText),\n      setBookmark: setBookmark,\n      findMarksAt: findMarksAt,\n      setMarker: operation(addGutterMarker),\n      clearMarker: operation(removeGutterMarker),\n      setLineClass: operation(setLineClass),\n      hideLine: operation(function(h) {return setLineHidden(h, true);}),\n      showLine: operation(function(h) {return setLineHidden(h, false);}),\n      onDeleteLine: function(line, f) {\n        if (typeof line == \"number\") {\n          if (!isLine(line)) return null;\n          line = getLine(line);\n        }\n        (line.handlers || (line.handlers = [])).push(f);\n        return line;\n      },\n      lineInfo: lineInfo,\n      addWidget: function(pos, node, scroll, vert, horiz) {\n        pos = localCoords(clipPos(pos));\n        var top = pos.yBot, left = pos.x;\n        node.style.position = \"absolute\";\n        code.appendChild(node);\n        if (vert == \"over\") top = pos.y;\n        else if (vert == \"near\") {\n          var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()),\n              hspace = Math.max(code.clientWidth, lineSpace.clientWidth) - paddingLeft();\n          if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight)\n            top = pos.y - node.offsetHeight;\n          if (left + node.offsetWidth > hspace)\n            left = hspace - node.offsetWidth;\n        }\n        node.style.top = (top + paddingTop()) + \"px\";\n        node.style.left = node.style.right = \"\";\n        if (horiz == \"right\") {\n          left = code.clientWidth - node.offsetWidth;\n          node.style.right = \"0px\";\n        } else {\n          if (horiz == \"left\") left = 0;\n          else if (horiz == \"middle\") left = (code.clientWidth - node.offsetWidth) / 2;\n          node.style.left = (left + paddingLeft()) + \"px\";\n        }\n        if (scroll)\n          scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight);\n      },\n\n      lineCount: function() {return doc.size;},\n      clipPos: clipPos,\n      getCursor: function(start) {\n        if (start == null) start = sel.inverted;\n        return copyPos(start ? sel.from : sel.to);\n      },\n      somethingSelected: function() {return !posEq(sel.from, sel.to);},\n      setCursor: operation(function(line, ch, user) {\n        if (ch == null && typeof line.line == \"number\") setCursor(line.line, line.ch, user);\n        else setCursor(line, ch, user);\n      }),\n      setSelection: operation(function(from, to, user) {\n        (user ? setSelectionUser : setSelection)(clipPos(from), clipPos(to || from));\n      }),\n      getLine: function(line) {if (isLine(line)) return getLine(line).text;},\n      getLineHandle: function(line) {if (isLine(line)) return getLine(line);},\n      setLine: operation(function(line, text) {\n        if (isLine(line)) replaceRange(text, {line: line, ch: 0}, {line: line, ch: getLine(line).text.length});\n      }),\n      removeLine: operation(function(line) {\n        if (isLine(line)) replaceRange(\"\", {line: line, ch: 0}, clipPos({line: line+1, ch: 0}));\n      }),\n      replaceRange: operation(replaceRange),\n      getRange: function(from, to) {return getRange(clipPos(from), clipPos(to));},\n\n      triggerOnKeyDown: operation(onKeyDown),\n      execCommand: function(cmd) {return commands[cmd](instance);},\n      // Stuff used by commands, probably not much use to outside code.\n      moveH: operation(moveH),\n      deleteH: operation(deleteH),\n      moveV: operation(moveV),\n      toggleOverwrite: function() {\n        if(overwrite){\n          overwrite = false;\n          cursor.className = cursor.className.replace(\" CodeMirror-overwrite\", \"\");\n        } else {\n          overwrite = true;\n          cursor.className += \" CodeMirror-overwrite\";\n        }\n      },\n\n      posFromIndex: function(off) {\n        var lineNo = 0, ch;\n        doc.iter(0, doc.size, function(line) {\n          var sz = line.text.length + 1;\n          if (sz > off) { ch = off; return true; }\n          off -= sz;\n          ++lineNo;\n        });\n        return clipPos({line: lineNo, ch: ch});\n      },\n      indexFromPos: function (coords) {\n        if (coords.line < 0 || coords.ch < 0) return 0;\n        var index = coords.ch;\n        doc.iter(0, coords.line, function (line) {\n          index += line.text.length + 1;\n        });\n        return index;\n      },\n      scrollTo: function(x, y) {\n        if (x != null) scroller.scrollLeft = x;\n        if (y != null) scroller.scrollTop = y;\n        updateDisplay([]);\n      },\n\n      operation: function(f){return operation(f)();},\n      compoundChange: function(f){return compoundChange(f);},\n      refresh: function(){\n        updateDisplay(true);\n        if (scroller.scrollHeight > lastScrollPos)\n          scroller.scrollTop = lastScrollPos;\n      },\n      getInputField: function(){return input;},\n      getWrapperElement: function(){return wrapper;},\n      getScrollerElement: function(){return scroller;},\n      getGutterElement: function(){return gutter;}\n    };\n\n    function getLine(n) { return getLineAt(doc, n); }\n    function updateLineHeight(line, height) {\n      gutterDirty = true;\n      var diff = height - line.height;\n      for (var n = line; n; n = n.parent) n.height += diff;\n    }\n\n    function setValue(code) {\n      var top = {line: 0, ch: 0};\n      updateLines(top, {line: doc.size - 1, ch: getLine(doc.size-1).text.length},\n                  splitLines(code), top, top);\n      updateInput = true;\n    }\n    function getValue() {\n      var text = [];\n      doc.iter(0, doc.size, function(line) { text.push(line.text); });\n      return text.join(\"\\n\");\n    }\n\n    function onMouseDown(e) {\n      setShift(e_prop(e, \"shiftKey\"));\n      // Check whether this is a click in a widget\n      for (var n = e_target(e); n != wrapper; n = n.parentNode)\n        if (n.parentNode == code && n != mover) return;\n\n      // See if this is a click in the gutter\n      for (var n = e_target(e); n != wrapper; n = n.parentNode)\n        if (n.parentNode == gutterText) {\n          if (options.onGutterClick)\n            options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom, e);\n          return e_preventDefault(e);\n        }\n\n      var start = posFromMouse(e);\n\n      switch (e_button(e)) {\n      case 3:\n        if (gecko && !mac) onContextMenu(e);\n        return;\n      case 2:\n        if (start) setCursor(start.line, start.ch, true);\n        setTimeout(focusInput, 20);\n        return;\n      }\n      // For button 1, if it was clicked inside the editor\n      // (posFromMouse returning non-null), we have to adjust the\n      // selection.\n      if (!start) {if (e_target(e) == scroller) e_preventDefault(e); return;}\n\n      if (!focused) onFocus();\n\n      var now = +new Date;\n      if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) {\n        e_preventDefault(e);\n        setTimeout(focusInput, 20);\n        return selectLine(start.line);\n      } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) {\n        lastDoubleClick = {time: now, pos: start};\n        e_preventDefault(e);\n        return selectWordAt(start);\n      } else { lastClick = {time: now, pos: start}; }\n\n      var last = start, going;\n      if (options.dragDrop && dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&\n          !posLess(start, sel.from) && !posLess(sel.to, start)) {\n        // Let the drag handler handle this.\n        if (webkit) lineSpace.draggable = true;\n        function dragEnd(e2) {\n          if (webkit) lineSpace.draggable = false;\n          draggingText = false;\n          up(); drop();\n          if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {\n            e_preventDefault(e2);\n            setCursor(start.line, start.ch, true);\n            focusInput();\n          }\n        }\n        var up = connect(document, \"mouseup\", operation(dragEnd), true);\n        var drop = connect(scroller, \"drop\", operation(dragEnd), true);\n        draggingText = true;\n        // IE's approach to draggable\n        if (lineSpace.dragDrop) lineSpace.dragDrop();\n        return;\n      }\n      e_preventDefault(e);\n      setCursor(start.line, start.ch, true);\n\n      function extend(e) {\n        var cur = posFromMouse(e, true);\n        if (cur && !posEq(cur, last)) {\n          if (!focused) onFocus();\n          last = cur;\n          setSelectionUser(start, cur);\n          updateInput = false;\n          var visible = visibleLines();\n          if (cur.line >= visible.to || cur.line < visible.from)\n            going = setTimeout(operation(function(){extend(e);}), 150);\n        }\n      }\n\n      function done(e) {\n        clearTimeout(going);\n        var cur = posFromMouse(e);\n        if (cur) setSelectionUser(start, cur);\n        e_preventDefault(e);\n        focusInput();\n        updateInput = true;\n        move(); up();\n      }\n      var move = connect(document, \"mousemove\", operation(function(e) {\n        clearTimeout(going);\n        e_preventDefault(e);\n        if (!ie && !e_button(e)) done(e);\n        else extend(e);\n      }), true);\n      var up = connect(document, \"mouseup\", operation(done), true);\n    }\n    function onDoubleClick(e) {\n      for (var n = e_target(e); n != wrapper; n = n.parentNode)\n        if (n.parentNode == gutterText) return e_preventDefault(e);\n      var start = posFromMouse(e);\n      if (!start) return;\n      lastDoubleClick = {time: +new Date, pos: start};\n      e_preventDefault(e);\n      selectWordAt(start);\n    }\n    function onDrop(e) {\n      if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;\n      e.preventDefault();\n      var pos = posFromMouse(e, true), files = e.dataTransfer.files;\n      if (!pos || options.readOnly) return;\n      if (files && files.length && window.FileReader && window.File) {\n        function loadFile(file, i) {\n          var reader = new FileReader;\n          reader.onload = function() {\n            text[i] = reader.result;\n            if (++read == n) {\n              pos = clipPos(pos);\n              operation(function() {\n                var end = replaceRange(text.join(\"\"), pos, pos);\n                setSelectionUser(pos, end);\n              })();\n            }\n          };\n          reader.readAsText(file);\n        }\n        var n = files.length, text = Array(n), read = 0;\n        for (var i = 0; i < n; ++i) loadFile(files[i], i);\n      }\n      else {\n        try {\n          var text = e.dataTransfer.getData(\"Text\");\n          if (text) {\n            compoundChange(function() {\n              var curFrom = sel.from, curTo = sel.to;\n              setSelectionUser(pos, pos);\n              if (draggingText) replaceRange(\"\", curFrom, curTo);\n              replaceSelection(text);\n              focusInput();\n            });\n          }\n        }\n        catch(e){}\n      }\n    }\n    function onDragStart(e) {\n      var txt = getSelection();\n      e.dataTransfer.setData(\"Text\", txt);\n      \n      // Use dummy image instead of default browsers image.\n      if (gecko || chrome) {\n        var img = document.createElement('img');\n        img.scr = 'data:image/gif;base64,R0lGODdhAgACAIAAAAAAAP///ywAAAAAAgACAAACAoRRADs='; //1x1 image\n        e.dataTransfer.setDragImage(img, 0, 0);\n      }\n    }\n\n    function doHandleBinding(bound, dropShift) {\n      if (typeof bound == \"string\") {\n        bound = commands[bound];\n        if (!bound) return false;\n      }\n      var prevShift = shiftSelecting;\n      try {\n        if (options.readOnly) suppressEdits = true;\n        if (dropShift) shiftSelecting = null;\n        bound(instance);\n      } catch(e) {\n        if (e != Pass) throw e;\n        return false;\n      } finally {\n        shiftSelecting = prevShift;\n        suppressEdits = false;\n      }\n      return true;\n    }\n    function handleKeyBinding(e) {\n      // Handle auto keymap transitions\n      var startMap = getKeyMap(options.keyMap), next = startMap.auto;\n      clearTimeout(maybeTransition);\n      if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() {\n        if (getKeyMap(options.keyMap) == startMap) {\n          options.keyMap = (next.call ? next.call(null, instance) : next);\n        }\n      }, 50);\n\n      var name = keyNames[e_prop(e, \"keyCode\")], handled = false;\n      if (name == null || e.altGraphKey) return false;\n      if (e_prop(e, \"altKey\")) name = \"Alt-\" + name;\n      if (e_prop(e, \"ctrlKey\")) name = \"Ctrl-\" + name;\n      if (e_prop(e, \"metaKey\")) name = \"Cmd-\" + name;\n\n      var stopped = false;\n      function stop() { stopped = true; }\n\n      if (e_prop(e, \"shiftKey\")) {\n        handled = lookupKey(\"Shift-\" + name, options.extraKeys, options.keyMap,\n                            function(b) {return doHandleBinding(b, true);}, stop)\n               || lookupKey(name, options.extraKeys, options.keyMap, function(b) {\n                 if (typeof b == \"string\" && /^go[A-Z]/.test(b)) return doHandleBinding(b);\n               }, stop);\n      } else {\n        handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding, stop);\n      }\n      if (stopped) handled = false;\n      if (handled) {\n        e_preventDefault(e);\n        restartBlink();\n        if (ie) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }\n      }\n      return handled;\n    }\n    function handleCharBinding(e, ch) {\n      var handled = lookupKey(\"'\" + ch + \"'\", options.extraKeys,\n                              options.keyMap, function(b) { return doHandleBinding(b, true); });\n      if (handled) {\n        e_preventDefault(e);\n        restartBlink();\n      }\n      return handled;\n    }\n\n    var lastStoppedKey = null, maybeTransition;\n    function onKeyDown(e) {\n      if (!focused) onFocus();\n      if (ie && e.keyCode == 27) { e.returnValue = false; }\n      if (pollingFast) { if (readInput()) pollingFast = false; }\n      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;\n      var code = e_prop(e, \"keyCode\");\n      // IE does strange things with escape.\n      setShift(code == 16 || e_prop(e, \"shiftKey\"));\n      // First give onKeyEvent option a chance to handle this.\n      var handled = handleKeyBinding(e);\n      if (window.opera) {\n        lastStoppedKey = handled ? code : null;\n        // Opera has no cut event... we try to at least catch the key combo\n        if (!handled && code == 88 && e_prop(e, mac ? \"metaKey\" : \"ctrlKey\"))\n          replaceSelection(\"\");\n      }\n    }\n    function onKeyPress(e) {\n      if (pollingFast) readInput();\n      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;\n      var keyCode = e_prop(e, \"keyCode\"), charCode = e_prop(e, \"charCode\");\n      if (window.opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}\n      if (((window.opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(e)) return;\n      var ch = String.fromCharCode(charCode == null ? keyCode : charCode);\n      if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {\n        if (mode.electricChars.indexOf(ch) > -1)\n          setTimeout(operation(function() {indentLine(sel.to.line, \"smart\");}), 75);\n      }\n      if (handleCharBinding(e, ch)) return;\n      fastPoll();\n    }\n    function onKeyUp(e) {\n      if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;\n      if (e_prop(e, \"keyCode\") == 16) shiftSelecting = null;\n    }\n\n    function onFocus() {\n      if (options.readOnly == \"nocursor\") return;\n      if (!focused) {\n        if (options.onFocus) options.onFocus(instance);\n        focused = true;\n        if (wrapper.className.search(/\\bCodeMirror-focused\\b/) == -1)\n          wrapper.className += \" CodeMirror-focused\";\n        if (!leaveInputAlone) resetInput(true);\n      }\n      slowPoll();\n      restartBlink();\n    }\n    function onBlur() {\n      if (focused) {\n        if (options.onBlur) options.onBlur(instance);\n        focused = false;\n        if (bracketHighlighted)\n          operation(function(){\n            if (bracketHighlighted) { bracketHighlighted(); bracketHighlighted = null; }\n          })();\n        wrapper.className = wrapper.className.replace(\" CodeMirror-focused\", \"\");\n      }\n      clearInterval(blinker);\n      setTimeout(function() {if (!focused) shiftSelecting = null;}, 150);\n    }\n\n    // Replace the range from from to to by the strings in newText.\n    // Afterwards, set the selection to selFrom, selTo.\n    function updateLines(from, to, newText, selFrom, selTo) {\n      if (suppressEdits) return;\n      if (history) {\n        var old = [];\n        doc.iter(from.line, to.line + 1, function(line) { old.push(line.text); });\n        history.addChange(from.line, newText.length, old);\n        while (history.done.length > options.undoDepth) history.done.shift();\n      }\n      updateLinesNoUndo(from, to, newText, selFrom, selTo);\n    }\n    function unredoHelper(from, to) {\n      if (!from.length) return;\n      var set = from.pop(), out = [];\n      for (var i = set.length - 1; i >= 0; i -= 1) {\n        var change = set[i];\n        var replaced = [], end = change.start + change.added;\n        doc.iter(change.start, end, function(line) { replaced.push(line.text); });\n        out.push({start: change.start, added: change.old.length, old: replaced});\n        var pos = clipPos({line: change.start + change.old.length - 1,\n                           ch: editEnd(replaced[replaced.length-1], change.old[change.old.length-1])});\n        updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, change.old, pos, pos);\n      }\n      updateInput = true;\n      to.push(out);\n    }\n    function undo() {unredoHelper(history.done, history.undone);}\n    function redo() {unredoHelper(history.undone, history.done);}\n\n    function updateLinesNoUndo(from, to, newText, selFrom, selTo) {\n      if (suppressEdits) return;\n      var recomputeMaxLength = false, maxLineLength = maxLine.length;\n      if (!options.lineWrapping)\n        doc.iter(from.line, to.line + 1, function(line) {\n          if (!line.hidden && line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}\n        });\n      if (from.line != to.line || newText.length > 1) gutterDirty = true;\n\n      var nlines = to.line - from.line, firstLine = getLine(from.line), lastLine = getLine(to.line);\n      // First adjust the line structure, taking some care to leave highlighting intact.\n      if (from.ch == 0 && to.ch == 0 && newText[newText.length - 1] == \"\") {\n        // This is a whole-line replace. Treated specially to make\n        // sure line objects move the way they are supposed to.\n        var added = [], prevLine = null;\n        if (from.line) {\n          prevLine = getLine(from.line - 1);\n          prevLine.fixMarkEnds(lastLine);\n        } else lastLine.fixMarkStarts();\n        for (var i = 0, e = newText.length - 1; i < e; ++i)\n          added.push(Line.inheritMarks(newText[i], prevLine));\n        if (nlines) doc.remove(from.line, nlines, callbacks);\n        if (added.length) doc.insert(from.line, added);\n      } else if (firstLine == lastLine) {\n        if (newText.length == 1)\n          firstLine.replace(from.ch, to.ch, newText[0]);\n        else {\n          lastLine = firstLine.split(to.ch, newText[newText.length-1]);\n          firstLine.replace(from.ch, null, newText[0]);\n          firstLine.fixMarkEnds(lastLine);\n          var added = [];\n          for (var i = 1, e = newText.length - 1; i < e; ++i)\n            added.push(Line.inheritMarks(newText[i], firstLine));\n          added.push(lastLine);\n          doc.insert(from.line + 1, added);\n        }\n      } else if (newText.length == 1) {\n        firstLine.replace(from.ch, null, newText[0]);\n        lastLine.replace(null, to.ch, \"\");\n        firstLine.append(lastLine);\n        doc.remove(from.line + 1, nlines, callbacks);\n      } else {\n        var added = [];\n        firstLine.replace(from.ch, null, newText[0]);\n        lastLine.replace(null, to.ch, newText[newText.length-1]);\n        firstLine.fixMarkEnds(lastLine);\n        for (var i = 1, e = newText.length - 1; i < e; ++i)\n          added.push(Line.inheritMarks(newText[i], firstLine));\n        if (nlines > 1) doc.remove(from.line + 1, nlines - 1, callbacks);\n        doc.insert(from.line + 1, added);\n      }\n      if (options.lineWrapping) {\n        var perLine = Math.max(5, scroller.clientWidth / charWidth() - 3);\n        doc.iter(from.line, from.line + newText.length, function(line) {\n          if (line.hidden) return;\n          var guess = Math.ceil(line.text.length / perLine) || 1;\n          if (guess != line.height) updateLineHeight(line, guess);\n        });\n      } else {\n        doc.iter(from.line, from.line + newText.length, function(line) {\n          var l = line.text;\n          if (!line.hidden && l.length > maxLineLength) {\n            maxLine = l; maxLineLength = l.length; maxWidth = null;\n            recomputeMaxLength = false;\n          }\n        });\n        if (recomputeMaxLength) maxLengthChanged = true;\n      }\n\n      // Add these lines to the work array, so that they will be\n      // highlighted. Adjust work lines if lines were added/removed.\n      var newWork = [], lendiff = newText.length - nlines - 1;\n      for (var i = 0, l = work.length; i < l; ++i) {\n        var task = work[i];\n        if (task < from.line) newWork.push(task);\n        else if (task > to.line) newWork.push(task + lendiff);\n      }\n      var hlEnd = from.line + Math.min(newText.length, 500);\n      highlightLines(from.line, hlEnd);\n      newWork.push(hlEnd);\n      work = newWork;\n      startWorker(100);\n      // Remember that these lines changed, for updating the display\n      changes.push({from: from.line, to: to.line + 1, diff: lendiff});\n      var changeObj = {from: from, to: to, text: newText};\n      if (textChanged) {\n        for (var cur = textChanged; cur.next; cur = cur.next) {}\n        cur.next = changeObj;\n      } else textChanged = changeObj;\n\n      // Update the selection\n      function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;}\n      setSelection(selFrom, selTo, updateLine(sel.from.line), updateLine(sel.to.line));\n\n      // Make sure the scroll-size div has the correct height.\n      if (scroller.clientHeight)\n        code.style.height = (doc.height * textHeight() + 2 * paddingTop()) + \"px\";\n    }\n    \n    function computeMaxLength() {\n      var maxLineLength = 0; \n      maxLine = \"\"; maxWidth = null;\n      doc.iter(0, doc.size, function(line) {\n        var l = line.text;\n        if (!line.hidden && l.length > maxLineLength) {\n          maxLineLength = l.length; maxLine = l;\n        }\n      });\n      maxLengthChanged = false;\n    }\n\n    function replaceRange(code, from, to) {\n      from = clipPos(from);\n      if (!to) to = from; else to = clipPos(to);\n      code = splitLines(code);\n      function adjustPos(pos) {\n        if (posLess(pos, from)) return pos;\n        if (!posLess(to, pos)) return end;\n        var line = pos.line + code.length - (to.line - from.line) - 1;\n        var ch = pos.ch;\n        if (pos.line == to.line)\n          ch += code[code.length-1].length - (to.ch - (to.line == from.line ? from.ch : 0));\n        return {line: line, ch: ch};\n      }\n      var end;\n      replaceRange1(code, from, to, function(end1) {\n        end = end1;\n        return {from: adjustPos(sel.from), to: adjustPos(sel.to)};\n      });\n      return end;\n    }\n    function replaceSelection(code, collapse) {\n      replaceRange1(splitLines(code), sel.from, sel.to, function(end) {\n        if (collapse == \"end\") return {from: end, to: end};\n        else if (collapse == \"start\") return {from: sel.from, to: sel.from};\n        else return {from: sel.from, to: end};\n      });\n    }\n    function replaceRange1(code, from, to, computeSel) {\n      var endch = code.length == 1 ? code[0].length + from.ch : code[code.length-1].length;\n      var newSel = computeSel({line: from.line + code.length - 1, ch: endch});\n      updateLines(from, to, code, newSel.from, newSel.to);\n    }\n\n    function getRange(from, to) {\n      var l1 = from.line, l2 = to.line;\n      if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch);\n      var code = [getLine(l1).text.slice(from.ch)];\n      doc.iter(l1 + 1, l2, function(line) { code.push(line.text); });\n      code.push(getLine(l2).text.slice(0, to.ch));\n      return code.join(\"\\n\");\n    }\n    function getSelection() {\n      return getRange(sel.from, sel.to);\n    }\n\n    var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll\n    function slowPoll() {\n      if (pollingFast) return;\n      poll.set(options.pollInterval, function() {\n        startOperation();\n        readInput();\n        if (focused) slowPoll();\n        endOperation();\n      });\n    }\n    function fastPoll() {\n      var missed = false;\n      pollingFast = true;\n      function p() {\n        startOperation();\n        var changed = readInput();\n        if (!changed && !missed) {missed = true; poll.set(60, p);}\n        else {pollingFast = false; slowPoll();}\n        endOperation();\n      }\n      poll.set(20, p);\n    }\n\n    // Previnput is a hack to work with IME. If we reset the textarea\n    // on every change, that breaks IME. So we look for changes\n    // compared to the previous content instead. (Modern browsers have\n    // events that indicate IME taking place, but these are not widely\n    // supported or compatible enough yet to rely on.)\n    var prevInput = \"\";\n    function readInput() {\n      if (leaveInputAlone || !focused || hasSelection(input) || options.readOnly) return false;\n      var text = input.value;\n      if (text == prevInput) return false;\n      shiftSelecting = null;\n      var same = 0, l = Math.min(prevInput.length, text.length);\n      while (same < l && prevInput[same] == text[same]) ++same;\n      if (same < prevInput.length)\n        sel.from = {line: sel.from.line, ch: sel.from.ch - (prevInput.length - same)};\n      else if (overwrite && posEq(sel.from, sel.to))\n        sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))};\n      replaceSelection(text.slice(same), \"end\");\n      if (text.length > 1000) { input.value = prevInput = \"\"; }\n      else prevInput = text;\n      return true;\n    }\n    function resetInput(user) {\n      if (!posEq(sel.from, sel.to)) {\n        prevInput = \"\";\n        input.value = getSelection();\n        selectInput(input);\n      } else if (user) prevInput = input.value = \"\";\n    }\n\n    function focusInput() {\n      if (options.readOnly != \"nocursor\") input.focus();\n    }\n\n    function scrollEditorIntoView() {\n      if (!cursor.getBoundingClientRect) return;\n      var rect = cursor.getBoundingClientRect();\n      // IE returns bogus coordinates when the instance sits inside of an iframe and the cursor is hidden\n      if (ie && rect.top == rect.bottom) return;\n      var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);\n      if (rect.top < 0 || rect.bottom > winH) cursor.scrollIntoView();\n    }\n    function scrollCursorIntoView() {\n      var cursor = localCoords(sel.inverted ? sel.from : sel.to);\n      var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x;\n      return scrollIntoView(x, cursor.y, x, cursor.yBot);\n    }\n    function scrollIntoView(x1, y1, x2, y2) {\n      var pl = paddingLeft(), pt = paddingTop();\n      y1 += pt; y2 += pt; x1 += pl; x2 += pl;\n      var screen = scroller.clientHeight, screentop = scroller.scrollTop, scrolled = false, result = true;\n      if (y1 < screentop) {scroller.scrollTop = Math.max(0, y1); scrolled = true;}\n      else if (y2 > screentop + screen) {scroller.scrollTop = y2 - screen; scrolled = true;}\n\n      var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;\n      var gutterw = options.fixedGutter ? gutter.clientWidth : 0;\n      var atLeft = x1 < gutterw + pl + 10;\n      if (x1 < screenleft + gutterw || atLeft) {\n        if (atLeft) x1 = 0;\n        scroller.scrollLeft = Math.max(0, x1 - 10 - gutterw);\n        scrolled = true;\n      }\n      else if (x2 > screenw + screenleft - 3) {\n        scroller.scrollLeft = x2 + 10 - screenw;\n        scrolled = true;\n        if (x2 > code.clientWidth) result = false;\n      }\n      if (scrolled && options.onScroll) options.onScroll(instance);\n      return result;\n    }\n\n    function visibleLines() {\n      var lh = textHeight(), top = scroller.scrollTop - paddingTop();\n      var fromHeight = Math.max(0, Math.floor(top / lh));\n      var toHeight = Math.ceil((top + scroller.clientHeight) / lh);\n      return {from: lineAtHeight(doc, fromHeight),\n              to: lineAtHeight(doc, toHeight)};\n    }\n    // Uses a set of changes plus the current scroll position to\n    // determine which DOM updates have to be made, and makes the\n    // updates.\n    function updateDisplay(changes, suppressCallback) {\n      if (!scroller.clientWidth) {\n        showingFrom = showingTo = displayOffset = 0;\n        return;\n      }\n      // Compute the new visible window\n      var visible = visibleLines();\n      // Bail out if the visible area is already rendered and nothing changed.\n      if (changes !== true && changes.length == 0 && visible.from > showingFrom && visible.to < showingTo) return;\n      var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100);\n      if (showingFrom < from && from - showingFrom < 20) from = showingFrom;\n      if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo);\n\n      // Create a range of theoretically intact lines, and punch holes\n      // in that using the change info.\n      var intact = changes === true ? [] :\n        computeIntact([{from: showingFrom, to: showingTo, domStart: 0}], changes);\n      // Clip off the parts that won't be visible\n      var intactLines = 0;\n      for (var i = 0; i < intact.length; ++i) {\n        var range = intact[i];\n        if (range.from < from) {range.domStart += (from - range.from); range.from = from;}\n        if (range.to > to) range.to = to;\n        if (range.from >= range.to) intact.splice(i--, 1);\n        else intactLines += range.to - range.from;\n      }\n      if (intactLines == to - from && from == showingFrom && to == showingTo) return;\n      intact.sort(function(a, b) {return a.domStart - b.domStart;});\n\n      var th = textHeight(), gutterDisplay = gutter.style.display;\n      lineDiv.style.display = \"none\";\n      patchDisplay(from, to, intact);\n      lineDiv.style.display = gutter.style.display = \"\";\n\n      // Position the mover div to align with the lines it's supposed\n      // to be showing (which will cover the visible display)\n      var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th;\n      // This is just a bogus formula that detects when the editor is\n      // resized or the font size changes.\n      if (different) lastSizeC = scroller.clientHeight + th;\n      showingFrom = from; showingTo = to;\n      displayOffset = heightAtLine(doc, from);\n      mover.style.top = (displayOffset * th) + \"px\";\n      if (scroller.clientHeight)\n        code.style.height = (doc.height * th + 2 * paddingTop()) + \"px\";\n\n      // Since this is all rather error prone, it is honoured with the\n      // only assertion in the whole file.\n      if (lineDiv.childNodes.length != showingTo - showingFrom)\n        throw new Error(\"BAD PATCH! \" + JSON.stringify(intact) + \" size=\" + (showingTo - showingFrom) +\n                        \" nodes=\" + lineDiv.childNodes.length);\n\n      function checkHeights() {\n        maxWidth = scroller.clientWidth;\n        var curNode = lineDiv.firstChild, heightChanged = false;\n        doc.iter(showingFrom, showingTo, function(line) {\n          if (!line.hidden) {\n            var height = Math.round(curNode.offsetHeight / th) || 1;\n            if (line.height != height) {\n              updateLineHeight(line, height);\n              gutterDirty = heightChanged = true;\n            }\n          }\n          curNode = curNode.nextSibling;\n        });\n        if (heightChanged)\n          code.style.height = (doc.height * th + 2 * paddingTop()) + \"px\";\n        return heightChanged;\n      }\n\n      if (options.lineWrapping) {\n        checkHeights();\n      } else {\n        if (maxWidth == null) maxWidth = stringWidth(maxLine);\n        if (maxWidth > scroller.clientWidth) {\n          lineSpace.style.width = maxWidth + \"px\";\n          // Needed to prevent odd wrapping/hiding of widgets placed in here.\n          code.style.width = \"\";\n          code.style.width = scroller.scrollWidth + \"px\";\n        } else {\n          lineSpace.style.width = code.style.width = \"\";\n        }\n      }\n\n      gutter.style.display = gutterDisplay;\n      if (different || gutterDirty) {\n        // If the gutter grew in size, re-check heights. If those changed, re-draw gutter.\n        updateGutter() && options.lineWrapping && checkHeights() && updateGutter();\n      }\n      updateSelection();\n      if (!suppressCallback && options.onUpdate) options.onUpdate(instance);\n      return true;\n    }\n\n    function computeIntact(intact, changes) {\n      for (var i = 0, l = changes.length || 0; i < l; ++i) {\n        var change = changes[i], intact2 = [], diff = change.diff || 0;\n        for (var j = 0, l2 = intact.length; j < l2; ++j) {\n          var range = intact[j];\n          if (change.to <= range.from && change.diff)\n            intact2.push({from: range.from + diff, to: range.to + diff,\n                          domStart: range.domStart});\n          else if (change.to <= range.from || change.from >= range.to)\n            intact2.push(range);\n          else {\n            if (change.from > range.from)\n              intact2.push({from: range.from, to: change.from, domStart: range.domStart});\n            if (change.to < range.to)\n              intact2.push({from: change.to + diff, to: range.to + diff,\n                            domStart: range.domStart + (change.to - range.from)});\n          }\n        }\n        intact = intact2;\n      }\n      return intact;\n    }\n\n    function patchDisplay(from, to, intact) {\n      // The first pass removes the DOM nodes that aren't intact.\n      if (!intact.length) lineDiv.innerHTML = \"\";\n      else {\n        function killNode(node) {\n          var tmp = node.nextSibling;\n          node.parentNode.removeChild(node);\n          return tmp;\n        }\n        var domPos = 0, curNode = lineDiv.firstChild, n;\n        for (var i = 0; i < intact.length; ++i) {\n          var cur = intact[i];\n          while (cur.domStart > domPos) {curNode = killNode(curNode); domPos++;}\n          for (var j = 0, e = cur.to - cur.from; j < e; ++j) {curNode = curNode.nextSibling; domPos++;}\n        }\n        while (curNode) curNode = killNode(curNode);\n      }\n      // This pass fills in the lines that actually changed.\n      var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from;\n      var scratch = document.createElement(\"div\");\n      doc.iter(from, to, function(line) {\n        if (nextIntact && nextIntact.to == j) nextIntact = intact.shift();\n        if (!nextIntact || nextIntact.from > j) {\n          if (line.hidden) var html = scratch.innerHTML = \"<pre></pre>\";\n          else {\n            var html = '<pre' + (line.className ? ' class=\"' + line.className + '\"' : '') + '>'\n              + line.getHTML(makeTab) + '</pre>';\n            // Kludge to make sure the styled element lies behind the selection (by z-index)\n            if (line.bgClassName)\n              html = '<div style=\"position: relative\"><pre class=\"' + line.bgClassName +\n              '\" style=\"position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2\">&#160;</pre>' + html + \"</div>\";\n          }\n          scratch.innerHTML = html;\n          lineDiv.insertBefore(scratch.firstChild, curNode);\n        } else {\n          curNode = curNode.nextSibling;\n        }\n        ++j;\n      });\n    }\n\n    function updateGutter() {\n      if (!options.gutter && !options.lineNumbers) return;\n      var hText = mover.offsetHeight, hEditor = scroller.clientHeight;\n      gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + \"px\";\n      var html = [], i = showingFrom, normalNode;\n      doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) {\n        if (line.hidden) {\n          html.push(\"<pre></pre>\");\n        } else {\n          var marker = line.gutterMarker;\n          var text = options.lineNumbers ? i + options.firstLineNumber : null;\n          if (marker && marker.text)\n            text = marker.text.replace(\"%N%\", text != null ? text : \"\");\n          else if (text == null)\n            text = \"\\u00a0\";\n          html.push((marker && marker.style ? '<pre class=\"' + marker.style + '\">' : \"<pre>\"), text);\n          for (var j = 1; j < line.height; ++j) html.push(\"<br/>&#160;\");\n          html.push(\"</pre>\");\n          if (!marker) normalNode = i;\n        }\n        ++i;\n      });\n      gutter.style.display = \"none\";\n      gutterText.innerHTML = html.join(\"\");\n      // Make sure scrolling doesn't cause number gutter size to pop\n      if (normalNode != null) {\n        var node = gutterText.childNodes[normalNode - showingFrom];\n        var minwidth = String(doc.size).length, val = eltText(node), pad = \"\";\n        while (val.length + pad.length < minwidth) pad += \"\\u00a0\";\n        if (pad) node.insertBefore(document.createTextNode(pad), node.firstChild);\n      }\n      gutter.style.display = \"\";\n      var resized = Math.abs((parseInt(lineSpace.style.marginLeft) || 0) - gutter.offsetWidth) > 2;\n      lineSpace.style.marginLeft = gutter.offsetWidth + \"px\";\n      gutterDirty = false;\n      return resized;\n    }\n    function updateSelection() {\n      var collapsed = posEq(sel.from, sel.to);\n      var fromPos = localCoords(sel.from, true);\n      var toPos = collapsed ? fromPos : localCoords(sel.to, true);\n      var headPos = sel.inverted ? fromPos : toPos, th = textHeight();\n      var wrapOff = eltOffset(wrapper), lineOff = eltOffset(lineDiv);\n      inputDiv.style.top = Math.max(0, Math.min(scroller.offsetHeight, headPos.y + lineOff.top - wrapOff.top)) + \"px\";\n      inputDiv.style.left = Math.max(0, Math.min(scroller.offsetWidth, headPos.x + lineOff.left - wrapOff.left)) + \"px\";\n      if (collapsed) {\n        cursor.style.top = headPos.y + \"px\";\n        cursor.style.left = (options.lineWrapping ? Math.min(headPos.x, lineSpace.offsetWidth) : headPos.x) + \"px\";\n        cursor.style.display = \"\";\n        selectionDiv.style.display = \"none\";\n      } else {\n        var sameLine = fromPos.y == toPos.y, html = \"\";\n        var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth;\n        var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight;\n        function add(left, top, right, height) {\n          var rstyle = quirksMode ? \"width: \" + (!right ? clientWidth : clientWidth - right - left) + \"px\"\n                                  : \"right: \" + right + \"px\";\n          html += '<div class=\"CodeMirror-selected\" style=\"position: absolute; left: ' + left +\n            'px; top: ' + top + 'px; ' + rstyle + '; height: ' + height + 'px\"></div>';\n        }\n        if (sel.from.ch && fromPos.y >= 0) {\n          var right = sameLine ? clientWidth - toPos.x : 0;\n          add(fromPos.x, fromPos.y, right, th);\n        }\n        var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0));\n        var middleHeight = Math.min(toPos.y, clientHeight) - middleStart;\n        if (middleHeight > 0.2 * th)\n          add(0, middleStart, 0, middleHeight);\n        if ((!sameLine || !sel.from.ch) && toPos.y < clientHeight - .5 * th)\n          add(0, toPos.y, clientWidth - toPos.x, th);\n        selectionDiv.innerHTML = html;\n        cursor.style.display = \"none\";\n        selectionDiv.style.display = \"\";\n      }\n    }\n\n    function setShift(val) {\n      if (val) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from);\n      else shiftSelecting = null;\n    }\n    function setSelectionUser(from, to) {\n      var sh = shiftSelecting && clipPos(shiftSelecting);\n      if (sh) {\n        if (posLess(sh, from)) from = sh;\n        else if (posLess(to, sh)) to = sh;\n      }\n      setSelection(from, to);\n      userSelChange = true;\n    }\n    // Update the selection. Last two args are only used by\n    // updateLines, since they have to be expressed in the line\n    // numbers before the update.\n    function setSelection(from, to, oldFrom, oldTo) {\n      goalColumn = null;\n      if (oldFrom == null) {oldFrom = sel.from.line; oldTo = sel.to.line;}\n      if (posEq(sel.from, from) && posEq(sel.to, to)) return;\n      if (posLess(to, from)) {var tmp = to; to = from; from = tmp;}\n\n      // Skip over hidden lines.\n      if (from.line != oldFrom) {\n        var from1 = skipHidden(from, oldFrom, sel.from.ch);\n        // If there is no non-hidden line left, force visibility on current line\n        if (!from1) setLineHidden(from.line, false);\n        else from = from1;\n      }\n      if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch);\n\n      if (posEq(from, to)) sel.inverted = false;\n      else if (posEq(from, sel.to)) sel.inverted = false;\n      else if (posEq(to, sel.from)) sel.inverted = true;\n\n      if (options.autoClearEmptyLines && posEq(sel.from, sel.to)) {\n        var head = sel.inverted ? from : to;\n        if (head.line != sel.from.line && sel.from.line < doc.size) {\n          var oldLine = getLine(sel.from.line);\n          if (/^\\s+$/.test(oldLine.text))\n            setTimeout(operation(function() {\n              if (oldLine.parent && /^\\s+$/.test(oldLine.text)) {\n                var no = lineNo(oldLine);\n                replaceRange(\"\", {line: no, ch: 0}, {line: no, ch: oldLine.text.length});\n              }\n            }, 10));\n        }\n      }\n\n      sel.from = from; sel.to = to;\n      selectionChanged = true;\n    }\n    function skipHidden(pos, oldLine, oldCh) {\n      function getNonHidden(dir) {\n        var lNo = pos.line + dir, end = dir == 1 ? doc.size : -1;\n        while (lNo != end) {\n          var line = getLine(lNo);\n          if (!line.hidden) {\n            var ch = pos.ch;\n            if (toEnd || ch > oldCh || ch > line.text.length) ch = line.text.length;\n            return {line: lNo, ch: ch};\n          }\n          lNo += dir;\n        }\n      }\n      var line = getLine(pos.line);\n      var toEnd = pos.ch == line.text.length && pos.ch != oldCh;\n      if (!line.hidden) return pos;\n      if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1);\n      else return getNonHidden(-1) || getNonHidden(1);\n    }\n    function setCursor(line, ch, user) {\n      var pos = clipPos({line: line, ch: ch || 0});\n      (user ? setSelectionUser : setSelection)(pos, pos);\n    }\n\n    function clipLine(n) {return Math.max(0, Math.min(n, doc.size-1));}\n    function clipPos(pos) {\n      if (pos.line < 0) return {line: 0, ch: 0};\n      if (pos.line >= doc.size) return {line: doc.size-1, ch: getLine(doc.size-1).text.length};\n      var ch = pos.ch, linelen = getLine(pos.line).text.length;\n      if (ch == null || ch > linelen) return {line: pos.line, ch: linelen};\n      else if (ch < 0) return {line: pos.line, ch: 0};\n      else return pos;\n    }\n\n    function findPosH(dir, unit) {\n      var end = sel.inverted ? sel.from : sel.to, line = end.line, ch = end.ch;\n      var lineObj = getLine(line);\n      function findNextLine() {\n        for (var l = line + dir, e = dir < 0 ? -1 : doc.size; l != e; l += dir) {\n          var lo = getLine(l);\n          if (!lo.hidden) { line = l; lineObj = lo; return true; }\n        }\n      }\n      function moveOnce(boundToLine) {\n        if (ch == (dir < 0 ? 0 : lineObj.text.length)) {\n          if (!boundToLine && findNextLine()) ch = dir < 0 ? lineObj.text.length : 0;\n          else return false;\n        } else ch += dir;\n        return true;\n      }\n      if (unit == \"char\") moveOnce();\n      else if (unit == \"column\") moveOnce(true);\n      else if (unit == \"word\") {\n        var sawWord = false;\n        for (;;) {\n          if (dir < 0) if (!moveOnce()) break;\n          if (isWordChar(lineObj.text.charAt(ch))) sawWord = true;\n          else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;}\n          if (dir > 0) if (!moveOnce()) break;\n        }\n      }\n      return {line: line, ch: ch};\n    }\n    function moveH(dir, unit) {\n      var pos = dir < 0 ? sel.from : sel.to;\n      if (shiftSelecting || posEq(sel.from, sel.to)) pos = findPosH(dir, unit);\n      setCursor(pos.line, pos.ch, true);\n    }\n    function deleteH(dir, unit) {\n      if (!posEq(sel.from, sel.to)) replaceRange(\"\", sel.from, sel.to);\n      else if (dir < 0) replaceRange(\"\", findPosH(dir, unit), sel.to);\n      else replaceRange(\"\", sel.from, findPosH(dir, unit));\n      userSelChange = true;\n    }\n    var goalColumn = null;\n    function moveV(dir, unit) {\n      var dist = 0, pos = localCoords(sel.inverted ? sel.from : sel.to, true);\n      if (goalColumn != null) pos.x = goalColumn;\n      if (unit == \"page\") dist = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight);\n      else if (unit == \"line\") dist = textHeight();\n      var target = coordsChar(pos.x, pos.y + dist * dir + 2);\n      if (unit == \"page\") scroller.scrollTop += localCoords(target, true).y - pos.y;\n      setCursor(target.line, target.ch, true);\n      goalColumn = pos.x;\n    }\n\n    function selectWordAt(pos) {\n      var line = getLine(pos.line).text;\n      var start = pos.ch, end = pos.ch;\n      while (start > 0 && isWordChar(line.charAt(start - 1))) --start;\n      while (end < line.length && isWordChar(line.charAt(end))) ++end;\n      setSelectionUser({line: pos.line, ch: start}, {line: pos.line, ch: end});\n    }\n    function selectLine(line) {\n      setSelectionUser({line: line, ch: 0}, clipPos({line: line + 1, ch: 0}));\n    }\n    function indentSelected(mode) {\n      if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode);\n      var e = sel.to.line - (sel.to.ch ? 0 : 1);\n      for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode);\n    }\n\n    function indentLine(n, how) {\n      if (!how) how = \"add\";\n      if (how == \"smart\") {\n        if (!mode.indent) how = \"prev\";\n        else var state = getStateBefore(n);\n      }\n\n      var line = getLine(n), curSpace = line.indentation(options.tabSize),\n          curSpaceString = line.text.match(/^\\s*/)[0], indentation;\n      if (how == \"prev\") {\n        if (n) indentation = getLine(n-1).indentation(options.tabSize);\n        else indentation = 0;\n      }\n      else if (how == \"smart\") indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text);\n      else if (how == \"add\") indentation = curSpace + options.indentUnit;\n      else if (how == \"subtract\") indentation = curSpace - options.indentUnit;\n      indentation = Math.max(0, indentation);\n      var diff = indentation - curSpace;\n\n      if (!diff) {\n        if (sel.from.line != n && sel.to.line != n) return;\n        var indentString = curSpaceString;\n      }\n      else {\n        var indentString = \"\", pos = 0;\n        if (options.indentWithTabs)\n          for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += \"\\t\";}\n        while (pos < indentation) {++pos; indentString += \" \";}\n      }\n\n      replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length});\n    }\n\n    function loadMode() {\n      mode = CodeMirror.getMode(options, options.mode);\n      doc.iter(0, doc.size, function(line) { line.stateAfter = null; });\n      work = [0];\n      startWorker();\n    }\n    function gutterChanged() {\n      var visible = options.gutter || options.lineNumbers;\n      gutter.style.display = visible ? \"\" : \"none\";\n      if (visible) gutterDirty = true;\n      else lineDiv.parentNode.style.marginLeft = 0;\n    }\n    function wrappingChanged(from, to) {\n      if (options.lineWrapping) {\n        wrapper.className += \" CodeMirror-wrap\";\n        var perLine = scroller.clientWidth / charWidth() - 3;\n        doc.iter(0, doc.size, function(line) {\n          if (line.hidden) return;\n          var guess = Math.ceil(line.text.length / perLine) || 1;\n          if (guess != 1) updateLineHeight(line, guess);\n        });\n        lineSpace.style.width = code.style.width = \"\";\n      } else {\n        wrapper.className = wrapper.className.replace(\" CodeMirror-wrap\", \"\");\n        maxWidth = null; maxLine = \"\";\n        doc.iter(0, doc.size, function(line) {\n          if (line.height != 1 && !line.hidden) updateLineHeight(line, 1);\n          if (line.text.length > maxLine.length) maxLine = line.text;\n        });\n      }\n      changes.push({from: 0, to: doc.size});\n    }\n    function makeTab(col) {\n      var w = options.tabSize - col % options.tabSize, cached = tabCache[w];\n      if (cached) return cached;\n      for (var str = '<span class=\"cm-tab\">', i = 0; i < w; ++i) str += \" \";\n      return (tabCache[w] = {html: str + \"</span>\", width: w});\n    }\n    function themeChanged() {\n      scroller.className = scroller.className.replace(/\\s*cm-s-\\S+/g, \"\") +\n        options.theme.replace(/(^|\\s)\\s*/g, \" cm-s-\");\n    }\n    function keyMapChanged() {\n      var style = keyMap[options.keyMap].style;\n      wrapper.className = wrapper.className.replace(/\\s*cm-keymap-\\S+/g, \"\") +\n        (style ? \" cm-keymap-\" + style : \"\");\n    }\n\n    function TextMarker() { this.set = []; }\n    TextMarker.prototype.clear = operation(function() {\n      var min = Infinity, max = -Infinity;\n      for (var i = 0, e = this.set.length; i < e; ++i) {\n        var line = this.set[i], mk = line.marked;\n        if (!mk || !line.parent) continue;\n        var lineN = lineNo(line);\n        min = Math.min(min, lineN); max = Math.max(max, lineN);\n        for (var j = 0; j < mk.length; ++j)\n          if (mk[j].marker == this) mk.splice(j--, 1);\n      }\n      if (min != Infinity)\n        changes.push({from: min, to: max + 1});\n    });\n    TextMarker.prototype.find = function() {\n      var from, to;\n      for (var i = 0, e = this.set.length; i < e; ++i) {\n        var line = this.set[i], mk = line.marked;\n        for (var j = 0; j < mk.length; ++j) {\n          var mark = mk[j];\n          if (mark.marker == this) {\n            if (mark.from != null || mark.to != null) {\n              var found = lineNo(line);\n              if (found != null) {\n                if (mark.from != null) from = {line: found, ch: mark.from};\n                if (mark.to != null) to = {line: found, ch: mark.to};\n              }\n            }\n          }\n        }\n      }\n      return {from: from, to: to};\n    };\n\n    function markText(from, to, className) {\n      from = clipPos(from); to = clipPos(to);\n      var tm = new TextMarker();\n      if (!posLess(from, to)) return tm;\n      function add(line, from, to, className) {\n        getLine(line).addMark(new MarkedText(from, to, className, tm));\n      }\n      if (from.line == to.line) add(from.line, from.ch, to.ch, className);\n      else {\n        add(from.line, from.ch, null, className);\n        for (var i = from.line + 1, e = to.line; i < e; ++i)\n          add(i, null, null, className);\n        add(to.line, null, to.ch, className);\n      }\n      changes.push({from: from.line, to: to.line + 1});\n      return tm;\n    }\n\n    function setBookmark(pos) {\n      pos = clipPos(pos);\n      var bm = new Bookmark(pos.ch);\n      getLine(pos.line).addMark(bm);\n      return bm;\n    }\n\n    function findMarksAt(pos) {\n      pos = clipPos(pos);\n      var markers = [], marked = getLine(pos.line).marked;\n      if (!marked) return markers;\n      for (var i = 0, e = marked.length; i < e; ++i) {\n        var m = marked[i];\n        if ((m.from == null || m.from <= pos.ch) &&\n            (m.to == null || m.to >= pos.ch))\n          markers.push(m.marker || m);\n      }\n      return markers;\n    }\n\n    function addGutterMarker(line, text, className) {\n      if (typeof line == \"number\") line = getLine(clipLine(line));\n      line.gutterMarker = {text: text, style: className};\n      gutterDirty = true;\n      return line;\n    }\n    function removeGutterMarker(line) {\n      if (typeof line == \"number\") line = getLine(clipLine(line));\n      line.gutterMarker = null;\n      gutterDirty = true;\n    }\n\n    function changeLine(handle, op) {\n      var no = handle, line = handle;\n      if (typeof handle == \"number\") line = getLine(clipLine(handle));\n      else no = lineNo(handle);\n      if (no == null) return null;\n      if (op(line, no)) changes.push({from: no, to: no + 1});\n      else return null;\n      return line;\n    }\n    function setLineClass(handle, className, bgClassName) {\n      return changeLine(handle, function(line) {\n        if (line.className != className || line.bgClassName != bgClassName) {\n          line.className = className;\n          line.bgClassName = bgClassName;\n          return true;\n        }\n      });\n    }\n    function setLineHidden(handle, hidden) {\n      return changeLine(handle, function(line, no) {\n        if (line.hidden != hidden) {\n          line.hidden = hidden;\n          if (!options.lineWrapping) {\n            var l = line.text;\n            if (hidden && l.length == maxLine.length) {\n              maxLengthChanged = true;\n            }\n            else if (!hidden && l.length > maxLine.length) {\n              maxLine = l; maxWidth = null;\n              maxLengthChanged = false;\n            }\n          }\n          updateLineHeight(line, hidden ? 0 : 1);\n          var fline = sel.from.line, tline = sel.to.line;\n          if (hidden && (fline == no || tline == no)) {\n            var from = fline == no ? skipHidden({line: fline, ch: 0}, fline, 0) : sel.from;\n            var to = tline == no ? skipHidden({line: tline, ch: 0}, tline, 0) : sel.to;\n            // Can't hide the last visible line, we'd have no place to put the cursor\n            if (!to) return;\n            setSelection(from, to);\n          }\n          return (gutterDirty = true);\n        }\n      });\n    }\n\n    function lineInfo(line) {\n      if (typeof line == \"number\") {\n        if (!isLine(line)) return null;\n        var n = line;\n        line = getLine(line);\n        if (!line) return null;\n      }\n      else {\n        var n = lineNo(line);\n        if (n == null) return null;\n      }\n      var marker = line.gutterMarker;\n      return {line: n, handle: line, text: line.text, markerText: marker && marker.text,\n              markerClass: marker && marker.style, lineClass: line.className, bgClass: line.bgClassName};\n    }\n\n    function stringWidth(str) {\n      measure.innerHTML = \"<pre><span>x</span></pre>\";\n      measure.firstChild.firstChild.firstChild.nodeValue = str;\n      return measure.firstChild.firstChild.offsetWidth || 10;\n    }\n    // These are used to go from pixel positions to character\n    // positions, taking varying character widths into account.\n    function charFromX(line, x) {\n      if (x <= 0) return 0;\n      var lineObj = getLine(line), text = lineObj.text;\n      function getX(len) {\n        return measureLine(lineObj, len).left;\n      }\n      var from = 0, fromX = 0, to = text.length, toX;\n      // Guess a suitable upper bound for our search.\n      var estimated = Math.min(to, Math.ceil(x / charWidth()));\n      for (;;) {\n        var estX = getX(estimated);\n        if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));\n        else {toX = estX; to = estimated; break;}\n      }\n      if (x > toX) return to;\n      // Try to guess a suitable lower bound as well.\n      estimated = Math.floor(to * 0.8); estX = getX(estimated);\n      if (estX < x) {from = estimated; fromX = estX;}\n      // Do a binary search between these bounds.\n      for (;;) {\n        if (to - from <= 1) return (toX - x > x - fromX) ? from : to;\n        var middle = Math.ceil((from + to) / 2), middleX = getX(middle);\n        if (middleX > x) {to = middle; toX = middleX;}\n        else {from = middle; fromX = middleX;}\n      }\n    }\n\n    var tempId = \"CodeMirror-temp-\" + Math.floor(Math.random() * 0xffffff).toString(16);\n    function measureLine(line, ch) {\n      if (ch == 0) return {top: 0, left: 0};\n      var wbr = options.lineWrapping && ch < line.text.length &&\n                spanAffectsWrapping.test(line.text.slice(ch - 1, ch + 1));\n      measure.innerHTML = \"<pre>\" + line.getHTML(makeTab, ch, tempId, wbr) + \"</pre>\";\n      var elt = document.getElementById(tempId);\n      var top = elt.offsetTop, left = elt.offsetLeft;\n      // Older IEs report zero offsets for spans directly after a wrap\n      if (ie && top == 0 && left == 0) {\n        var backup = document.createElement(\"span\");\n        backup.innerHTML = \"x\";\n        elt.parentNode.insertBefore(backup, elt.nextSibling);\n        top = backup.offsetTop;\n      }\n      return {top: top, left: left};\n    }\n    function localCoords(pos, inLineWrap) {\n      var x, lh = textHeight(), y = lh * (heightAtLine(doc, pos.line) - (inLineWrap ? displayOffset : 0));\n      if (pos.ch == 0) x = 0;\n      else {\n        var sp = measureLine(getLine(pos.line), pos.ch);\n        x = sp.left;\n        if (options.lineWrapping) y += Math.max(0, sp.top);\n      }\n      return {x: x, y: y, yBot: y + lh};\n    }\n    // Coords must be lineSpace-local\n    function coordsChar(x, y) {\n      if (y < 0) y = 0;\n      var th = textHeight(), cw = charWidth(), heightPos = displayOffset + Math.floor(y / th);\n      var lineNo = lineAtHeight(doc, heightPos);\n      if (lineNo >= doc.size) return {line: doc.size - 1, ch: getLine(doc.size - 1).text.length};\n      var lineObj = getLine(lineNo), text = lineObj.text;\n      var tw = options.lineWrapping, innerOff = tw ? heightPos - heightAtLine(doc, lineNo) : 0;\n      if (x <= 0 && innerOff == 0) return {line: lineNo, ch: 0};\n      function getX(len) {\n        var sp = measureLine(lineObj, len);\n        if (tw) {\n          var off = Math.round(sp.top / th);\n          return Math.max(0, sp.left + (off - innerOff) * scroller.clientWidth);\n        }\n        return sp.left;\n      }\n      var from = 0, fromX = 0, to = text.length, toX;\n      // Guess a suitable upper bound for our search.\n      var estimated = Math.min(to, Math.ceil((x + innerOff * scroller.clientWidth * .9) / cw));\n      for (;;) {\n        var estX = getX(estimated);\n        if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2));\n        else {toX = estX; to = estimated; break;}\n      }\n      if (x > toX) return {line: lineNo, ch: to};\n      // Try to guess a suitable lower bound as well.\n      estimated = Math.floor(to * 0.8); estX = getX(estimated);\n      if (estX < x) {from = estimated; fromX = estX;}\n      // Do a binary search between these bounds.\n      for (;;) {\n        if (to - from <= 1) return {line: lineNo, ch: (toX - x > x - fromX) ? from : to};\n        var middle = Math.ceil((from + to) / 2), middleX = getX(middle);\n        if (middleX > x) {to = middle; toX = middleX;}\n        else {from = middle; fromX = middleX;}\n      }\n    }\n    function pageCoords(pos) {\n      var local = localCoords(pos, true), off = eltOffset(lineSpace);\n      return {x: off.left + local.x, y: off.top + local.y, yBot: off.top + local.yBot};\n    }\n\n    var cachedHeight, cachedHeightFor, measureText;\n    function textHeight() {\n      if (measureText == null) {\n        measureText = \"<pre>\";\n        for (var i = 0; i < 49; ++i) measureText += \"x<br/>\";\n        measureText += \"x</pre>\";\n      }\n      var offsetHeight = lineDiv.clientHeight;\n      if (offsetHeight == cachedHeightFor) return cachedHeight;\n      cachedHeightFor = offsetHeight;\n      measure.innerHTML = measureText;\n      cachedHeight = measure.firstChild.offsetHeight / 50 || 1;\n      measure.innerHTML = \"\";\n      return cachedHeight;\n    }\n    var cachedWidth, cachedWidthFor = 0;\n    function charWidth() {\n      if (scroller.clientWidth == cachedWidthFor) return cachedWidth;\n      cachedWidthFor = scroller.clientWidth;\n      return (cachedWidth = stringWidth(\"x\"));\n    }\n    function paddingTop() {return lineSpace.offsetTop;}\n    function paddingLeft() {return lineSpace.offsetLeft;}\n\n    function posFromMouse(e, liberal) {\n      var offW = eltOffset(scroller, true), x, y;\n      // Fails unpredictably on IE[67] when mouse is dragged around quickly.\n      try { x = e.clientX; y = e.clientY; } catch (e) { return null; }\n      // This is a mess of a heuristic to try and determine whether a\n      // scroll-bar was clicked or not, and to return null if one was\n      // (and !liberal).\n      if (!liberal && (x - offW.left > scroller.clientWidth || y - offW.top > scroller.clientHeight))\n        return null;\n      var offL = eltOffset(lineSpace, true);\n      return coordsChar(x - offL.left, y - offL.top);\n    }\n    function onContextMenu(e) {\n      var pos = posFromMouse(e), scrollPos = scroller.scrollTop;\n      if (!pos || window.opera) return; // Opera is difficult.\n      if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to))\n        operation(setCursor)(pos.line, pos.ch);\n\n      var oldCSS = input.style.cssText;\n      inputDiv.style.position = \"absolute\";\n      input.style.cssText = \"position: fixed; width: 30px; height: 30px; top: \" + (e.clientY - 5) +\n        \"px; left: \" + (e.clientX - 5) + \"px; z-index: 1000; background: white; \" +\n        \"border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);\";\n      leaveInputAlone = true;\n      var val = input.value = getSelection();\n      focusInput();\n      selectInput(input);\n      function rehide() {\n        var newVal = splitLines(input.value).join(\"\\n\");\n        if (newVal != val) operation(replaceSelection)(newVal, \"end\");\n        inputDiv.style.position = \"relative\";\n        input.style.cssText = oldCSS;\n        if (ie_lt9) scroller.scrollTop = scrollPos;\n        leaveInputAlone = false;\n        resetInput(true);\n        slowPoll();\n      }\n\n      if (gecko) {\n        e_stop(e);\n        var mouseup = connect(window, \"mouseup\", function() {\n          mouseup();\n          setTimeout(rehide, 20);\n        }, true);\n      } else {\n        setTimeout(rehide, 50);\n      }\n    }\n\n    // Cursor-blinking\n    function restartBlink() {\n      clearInterval(blinker);\n      var on = true;\n      cursor.style.visibility = \"\";\n      blinker = setInterval(function() {\n        cursor.style.visibility = (on = !on) ? \"\" : \"hidden\";\n      }, 650);\n    }\n\n    var matching = {\"(\": \")>\", \")\": \"(<\", \"[\": \"]>\", \"]\": \"[<\", \"{\": \"}>\", \"}\": \"{<\"};\n    function matchBrackets(autoclear) {\n      var head = sel.inverted ? sel.from : sel.to, line = getLine(head.line), pos = head.ch - 1;\n      var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];\n      if (!match) return;\n      var ch = match.charAt(0), forward = match.charAt(1) == \">\", d = forward ? 1 : -1, st = line.styles;\n      for (var off = pos + 1, i = 0, e = st.length; i < e; i+=2)\n        if ((off -= st[i].length) <= 0) {var style = st[i+1]; break;}\n\n      var stack = [line.text.charAt(pos)], re = /[(){}[\\]]/;\n      function scan(line, from, to) {\n        if (!line.text) return;\n        var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur;\n        for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) {\n          var text = st[i];\n          if (st[i+1] != null && st[i+1] != style) {pos += d * text.length; continue;}\n          for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) {\n            if (pos >= from && pos < to && re.test(cur = text.charAt(j))) {\n              var match = matching[cur];\n              if (match.charAt(1) == \">\" == forward) stack.push(cur);\n              else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};\n              else if (!stack.length) return {pos: pos, match: true};\n            }\n          }\n        }\n      }\n      for (var i = head.line, e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); i != e; i+=d) {\n        var line = getLine(i), first = i == head.line;\n        var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length);\n        if (found) break;\n      }\n      if (!found) found = {pos: null, match: false};\n      var style = found.match ? \"CodeMirror-matchingbracket\" : \"CodeMirror-nonmatchingbracket\";\n      var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style),\n          two = found.pos != null && markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style);\n      var clear = operation(function(){one.clear(); two && two.clear();});\n      if (autoclear) setTimeout(clear, 800);\n      else bracketHighlighted = clear;\n    }\n\n    // Finds the line to start with when starting a parse. Tries to\n    // find a line with a stateAfter, so that it can start with a\n    // valid state. If that fails, it returns the line with the\n    // smallest indentation, which tends to need the least context to\n    // parse correctly.\n    function findStartLine(n) {\n      var minindent, minline;\n      for (var search = n, lim = n - 40; search > lim; --search) {\n        if (search == 0) return 0;\n        var line = getLine(search-1);\n        if (line.stateAfter) return search;\n        var indented = line.indentation(options.tabSize);\n        if (minline == null || minindent > indented) {\n          minline = search - 1;\n          minindent = indented;\n        }\n      }\n      return minline;\n    }\n    function getStateBefore(n) {\n      var start = findStartLine(n), state = start && getLine(start-1).stateAfter;\n      if (!state) state = startState(mode);\n      else state = copyState(mode, state);\n      doc.iter(start, n, function(line) {\n        line.highlight(mode, state, options.tabSize);\n        line.stateAfter = copyState(mode, state);\n      });\n      if (start < n) changes.push({from: start, to: n});\n      if (n < doc.size && !getLine(n).stateAfter) work.push(n);\n      return state;\n    }\n    function highlightLines(start, end) {\n      var state = getStateBefore(start);\n      doc.iter(start, end, function(line) {\n        line.highlight(mode, state, options.tabSize);\n        line.stateAfter = copyState(mode, state);\n      });\n    }\n    function highlightWorker() {\n      var end = +new Date + options.workTime;\n      var foundWork = work.length;\n      while (work.length) {\n        if (!getLine(showingFrom).stateAfter) var task = showingFrom;\n        else var task = work.pop();\n        if (task >= doc.size) continue;\n        var start = findStartLine(task), state = start && getLine(start-1).stateAfter;\n        if (state) state = copyState(mode, state);\n        else state = startState(mode);\n\n        var unchanged = 0, compare = mode.compareStates, realChange = false,\n            i = start, bail = false;\n        doc.iter(i, doc.size, function(line) {\n          var hadState = line.stateAfter;\n          if (+new Date > end) {\n            work.push(i);\n            startWorker(options.workDelay);\n            if (realChange) changes.push({from: task, to: i + 1});\n            return (bail = true);\n          }\n          var changed = line.highlight(mode, state, options.tabSize);\n          if (changed) realChange = true;\n          line.stateAfter = copyState(mode, state);\n          var done = null;\n          if (compare) {\n            var same = hadState && compare(hadState, state);\n            if (same != Pass) done = !!same;\n          }\n          if (done == null) {\n            if (changed !== false || !hadState) unchanged = 0;\n            else if (++unchanged > 3 && (!mode.indent || mode.indent(hadState, \"\") == mode.indent(state, \"\")))\n              done = true;\n          }\n          if (done) return true;\n          ++i;\n        });\n        if (bail) return;\n        if (realChange) changes.push({from: task, to: i + 1});\n      }\n      if (foundWork && options.onHighlightComplete)\n        options.onHighlightComplete(instance);\n    }\n    function startWorker(time) {\n      if (!work.length) return;\n      highlight.set(time, operation(highlightWorker));\n    }\n\n    // Operations are used to wrap changes in such a way that each\n    // change won't have to update the cursor and display (which would\n    // be awkward, slow, and error-prone), but instead updates are\n    // batched and then all combined and executed at once.\n    function startOperation() {\n      updateInput = userSelChange = textChanged = null;\n      changes = []; selectionChanged = false; callbacks = [];\n    }\n    function endOperation() {\n      var reScroll = false, updated;\n      if (maxLengthChanged) computeMaxLength();\n      if (selectionChanged) reScroll = !scrollCursorIntoView();\n      if (changes.length) updated = updateDisplay(changes, true);\n      else {\n        if (selectionChanged) updateSelection();\n        if (gutterDirty) updateGutter();\n      }\n      if (reScroll) scrollCursorIntoView();\n      if (selectionChanged) {scrollEditorIntoView(); restartBlink();}\n\n      if (focused && !leaveInputAlone &&\n          (updateInput === true || (updateInput !== false && selectionChanged)))\n        resetInput(userSelChange);\n\n      if (selectionChanged && options.matchBrackets)\n        setTimeout(operation(function() {\n          if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;}\n          if (posEq(sel.from, sel.to)) matchBrackets(false);\n        }), 20);\n      var tc = textChanged, cbs = callbacks; // these can be reset by callbacks\n      if (selectionChanged && options.onCursorActivity)\n        options.onCursorActivity(instance);\n      if (tc && options.onChange && instance)\n        options.onChange(instance, tc);\n      for (var i = 0; i < cbs.length; ++i) cbs[i](instance);\n      if (updated && options.onUpdate) options.onUpdate(instance);\n    }\n    var nestedOperation = 0;\n    function operation(f) {\n      return function() {\n        if (!nestedOperation++) startOperation();\n        try {var result = f.apply(this, arguments);}\n        finally {if (!--nestedOperation) endOperation();}\n        return result;\n      };\n    }\n\n    function compoundChange(f) {\n      history.startCompound();\n      try { return f(); } finally { history.endCompound(); }\n    }\n\n    for (var ext in extensions)\n      if (extensions.propertyIsEnumerable(ext) &&\n          !instance.propertyIsEnumerable(ext))\n        instance[ext] = extensions[ext];\n    return instance;\n  } // (end of function CodeMirror)\n\n  // The default configuration options.\n  CodeMirror.defaults = {\n    value: \"\",\n    mode: null,\n    theme: \"default\",\n    indentUnit: 2,\n    indentWithTabs: false,\n    smartIndent: true,\n    tabSize: 4,\n    keyMap: \"default\",\n    extraKeys: null,\n    electricChars: true,\n    autoClearEmptyLines: false,\n    onKeyEvent: null,\n    onDragEvent: null,\n    lineWrapping: false,\n    lineNumbers: false,\n    gutter: false,\n    fixedGutter: false,\n    firstLineNumber: 1,\n    readOnly: false,\n    dragDrop: true,\n    onChange: null,\n    onCursorActivity: null,\n    onGutterClick: null,\n    onHighlightComplete: null,\n    onUpdate: null,\n    onFocus: null, onBlur: null, onScroll: null,\n    matchBrackets: false,\n    workTime: 100,\n    workDelay: 200,\n    pollInterval: 100,\n    undoDepth: 40,\n    tabindex: null,\n    autofocus: null\n  };\n\n  var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\\/\\w+/.test(navigator.userAgent);\n  var mac = ios || /Mac/.test(navigator.platform);\n  var win = /Win/.test(navigator.platform);\n\n  // Known modes, by name and by MIME\n  var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};\n  CodeMirror.defineMode = function(name, mode) {\n    if (!CodeMirror.defaults.mode && name != \"null\") CodeMirror.defaults.mode = name;\n    if (arguments.length > 2) {\n      mode.dependencies = [];\n      for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);\n    }\n    modes[name] = mode;\n  };\n  CodeMirror.defineMIME = function(mime, spec) {\n    mimeModes[mime] = spec;\n  };\n  CodeMirror.resolveMode = function(spec) {\n    if (typeof spec == \"string\" && mimeModes.hasOwnProperty(spec))\n      spec = mimeModes[spec];\n    else if (typeof spec == \"string\" && /^[\\w\\-]+\\/[\\w\\-]+\\+xml$/.test(spec))\n      return CodeMirror.resolveMode(\"application/xml\");\n    if (typeof spec == \"string\") return {name: spec};\n    else return spec || {name: \"null\"};\n  };\n  CodeMirror.getMode = function(options, spec) {\n    var spec = CodeMirror.resolveMode(spec);\n    var mfactory = modes[spec.name];\n    if (!mfactory) return CodeMirror.getMode(options, \"text/plain\");\n    return mfactory(options, spec);\n  };\n  CodeMirror.listModes = function() {\n    var list = [];\n    for (var m in modes)\n      if (modes.propertyIsEnumerable(m)) list.push(m);\n    return list;\n  };\n  CodeMirror.listMIMEs = function() {\n    var list = [];\n    for (var m in mimeModes)\n      if (mimeModes.propertyIsEnumerable(m)) list.push({mime: m, mode: mimeModes[m]});\n    return list;\n  };\n\n  var extensions = CodeMirror.extensions = {};\n  CodeMirror.defineExtension = function(name, func) {\n    extensions[name] = func;\n  };\n\n  var commands = CodeMirror.commands = {\n    selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});},\n    killLine: function(cm) {\n      var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to);\n      if (!sel && cm.getLine(from.line).length == from.ch) cm.replaceRange(\"\", from, {line: from.line + 1, ch: 0});\n      else cm.replaceRange(\"\", from, sel ? to : {line: from.line});\n    },\n    deleteLine: function(cm) {var l = cm.getCursor().line; cm.replaceRange(\"\", {line: l, ch: 0}, {line: l});},\n    undo: function(cm) {cm.undo();},\n    redo: function(cm) {cm.redo();},\n    goDocStart: function(cm) {cm.setCursor(0, 0, true);},\n    goDocEnd: function(cm) {cm.setSelection({line: cm.lineCount() - 1}, null, true);},\n    goLineStart: function(cm) {cm.setCursor(cm.getCursor().line, 0, true);},\n    goLineStartSmart: function(cm) {\n      var cur = cm.getCursor();\n      var text = cm.getLine(cur.line), firstNonWS = Math.max(0, text.search(/\\S/));\n      cm.setCursor(cur.line, cur.ch <= firstNonWS && cur.ch ? 0 : firstNonWS, true);\n    },\n    goLineEnd: function(cm) {cm.setSelection({line: cm.getCursor().line}, null, true);},\n    goLineUp: function(cm) {cm.moveV(-1, \"line\");},\n    goLineDown: function(cm) {cm.moveV(1, \"line\");},\n    goPageUp: function(cm) {cm.moveV(-1, \"page\");},\n    goPageDown: function(cm) {cm.moveV(1, \"page\");},\n    goCharLeft: function(cm) {cm.moveH(-1, \"char\");},\n    goCharRight: function(cm) {cm.moveH(1, \"char\");},\n    goColumnLeft: function(cm) {cm.moveH(-1, \"column\");},\n    goColumnRight: function(cm) {cm.moveH(1, \"column\");},\n    goWordLeft: function(cm) {cm.moveH(-1, \"word\");},\n    goWordRight: function(cm) {cm.moveH(1, \"word\");},\n    delCharLeft: function(cm) {cm.deleteH(-1, \"char\");},\n    delCharRight: function(cm) {cm.deleteH(1, \"char\");},\n    delWordLeft: function(cm) {cm.deleteH(-1, \"word\");},\n    delWordRight: function(cm) {cm.deleteH(1, \"word\");},\n    indentAuto: function(cm) {cm.indentSelection(\"smart\");},\n    indentMore: function(cm) {cm.indentSelection(\"add\");},\n    indentLess: function(cm) {cm.indentSelection(\"subtract\");},\n    insertTab: function(cm) {cm.replaceSelection(\"\\t\", \"end\");},\n    defaultTab: function(cm) {\n      if (cm.somethingSelected()) cm.indentSelection(\"add\");\n      else cm.replaceSelection(\"\\t\", \"end\");\n    },\n    transposeChars: function(cm) {\n      var cur = cm.getCursor(), line = cm.getLine(cur.line);\n      if (cur.ch > 0 && cur.ch < line.length - 1)\n        cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1),\n                        {line: cur.line, ch: cur.ch - 1}, {line: cur.line, ch: cur.ch + 1});\n    },\n    newlineAndIndent: function(cm) {\n      cm.replaceSelection(\"\\n\", \"end\");\n      cm.indentLine(cm.getCursor().line);\n    },\n    toggleOverwrite: function(cm) {cm.toggleOverwrite();}\n  };\n\n  var keyMap = CodeMirror.keyMap = {};\n  keyMap.basic = {\n    \"Left\": \"goCharLeft\", \"Right\": \"goCharRight\", \"Up\": \"goLineUp\", \"Down\": \"goLineDown\",\n    \"End\": \"goLineEnd\", \"Home\": \"goLineStartSmart\", \"PageUp\": \"goPageUp\", \"PageDown\": \"goPageDown\",\n    \"Delete\": \"delCharRight\", \"Backspace\": \"delCharLeft\", \"Tab\": \"defaultTab\", \"Shift-Tab\": \"indentAuto\",\n    \"Enter\": \"newlineAndIndent\", \"Insert\": \"toggleOverwrite\"\n  };\n  // Note that the save and find-related commands aren't defined by\n  // default. Unknown commands are simply ignored.\n  keyMap.pcDefault = {\n    \"Ctrl-A\": \"selectAll\", \"Ctrl-D\": \"deleteLine\", \"Ctrl-Z\": \"undo\", \"Shift-Ctrl-Z\": \"redo\", \"Ctrl-Y\": \"redo\",\n    \"Ctrl-Home\": \"goDocStart\", \"Alt-Up\": \"goDocStart\", \"Ctrl-End\": \"goDocEnd\", \"Ctrl-Down\": \"goDocEnd\",\n    \"Ctrl-Left\": \"goWordLeft\", \"Ctrl-Right\": \"goWordRight\", \"Alt-Left\": \"goLineStart\", \"Alt-Right\": \"goLineEnd\",\n    \"Ctrl-Backspace\": \"delWordLeft\", \"Ctrl-Delete\": \"delWordRight\", \"Ctrl-S\": \"save\", \"Ctrl-F\": \"find\",\n    \"Ctrl-G\": \"findNext\", \"Shift-Ctrl-G\": \"findPrev\", \"Shift-Ctrl-F\": \"replace\", \"Shift-Ctrl-R\": \"replaceAll\",\n    \"Ctrl-[\": \"indentLess\", \"Ctrl-]\": \"indentMore\",\n    fallthrough: \"basic\"\n  };\n  keyMap.macDefault = {\n    \"Cmd-A\": \"selectAll\", \"Cmd-D\": \"deleteLine\", \"Cmd-Z\": \"undo\", \"Shift-Cmd-Z\": \"redo\", \"Cmd-Y\": \"redo\",\n    \"Cmd-Up\": \"goDocStart\", \"Cmd-End\": \"goDocEnd\", \"Cmd-Down\": \"goDocEnd\", \"Alt-Left\": \"goWordLeft\",\n    \"Alt-Right\": \"goWordRight\", \"Cmd-Left\": \"goLineStart\", \"Cmd-Right\": \"goLineEnd\", \"Alt-Backspace\": \"delWordLeft\",\n    \"Ctrl-Alt-Backspace\": \"delWordRight\", \"Alt-Delete\": \"delWordRight\", \"Cmd-S\": \"save\", \"Cmd-F\": \"find\",\n    \"Cmd-G\": \"findNext\", \"Shift-Cmd-G\": \"findPrev\", \"Cmd-Alt-F\": \"replace\", \"Shift-Cmd-Alt-F\": \"replaceAll\",\n    \"Cmd-[\": \"indentLess\", \"Cmd-]\": \"indentMore\",\n    fallthrough: [\"basic\", \"emacsy\"]\n  };\n  keyMap[\"default\"] = mac ? keyMap.macDefault : keyMap.pcDefault;\n  keyMap.emacsy = {\n    \"Ctrl-F\": \"goCharRight\", \"Ctrl-B\": \"goCharLeft\", \"Ctrl-P\": \"goLineUp\", \"Ctrl-N\": \"goLineDown\",\n    \"Alt-F\": \"goWordRight\", \"Alt-B\": \"goWordLeft\", \"Ctrl-A\": \"goLineStart\", \"Ctrl-E\": \"goLineEnd\",\n    \"Ctrl-V\": \"goPageUp\", \"Shift-Ctrl-V\": \"goPageDown\", \"Ctrl-D\": \"delCharRight\", \"Ctrl-H\": \"delCharLeft\",\n    \"Alt-D\": \"delWordRight\", \"Alt-Backspace\": \"delWordLeft\", \"Ctrl-K\": \"killLine\", \"Ctrl-T\": \"transposeChars\"\n  };\n\n  function getKeyMap(val) {\n    if (typeof val == \"string\") return keyMap[val];\n    else return val;\n  }\n  function lookupKey(name, extraMap, map, handle, stop) {\n    function lookup(map) {\n      map = getKeyMap(map);\n      var found = map[name];\n      if (found != null && handle(found)) return true;\n      if (map.nofallthrough) {\n        if (stop) stop();\n        return true;\n      }\n      var fallthrough = map.fallthrough;\n      if (fallthrough == null) return false;\n      if (Object.prototype.toString.call(fallthrough) != \"[object Array]\")\n        return lookup(fallthrough);\n      for (var i = 0, e = fallthrough.length; i < e; ++i) {\n        if (lookup(fallthrough[i])) return true;\n      }\n      return false;\n    }\n    if (extraMap && lookup(extraMap)) return true;\n    return lookup(map);\n  }\n  function isModifierKey(event) {\n    var name = keyNames[e_prop(event, \"keyCode\")];\n    return name == \"Ctrl\" || name == \"Alt\" || name == \"Shift\" || name == \"Mod\";\n  }\n\n  CodeMirror.fromTextArea = function(textarea, options) {\n    if (!options) options = {};\n    options.value = textarea.value;\n    if (!options.tabindex && textarea.tabindex)\n      options.tabindex = textarea.tabindex;\n    if (options.autofocus == null && textarea.getAttribute(\"autofocus\") != null)\n      options.autofocus = true;\n\n    function save() {textarea.value = instance.getValue();}\n    if (textarea.form) {\n      // Deplorable hack to make the submit method do the right thing.\n      var rmSubmit = connect(textarea.form, \"submit\", save, true);\n      if (typeof textarea.form.submit == \"function\") {\n        var realSubmit = textarea.form.submit;\n        function wrappedSubmit() {\n          save();\n          textarea.form.submit = realSubmit;\n          textarea.form.submit();\n          textarea.form.submit = wrappedSubmit;\n        }\n        textarea.form.submit = wrappedSubmit;\n      }\n    }\n\n    textarea.style.display = \"none\";\n    var instance = CodeMirror(function(node) {\n      textarea.parentNode.insertBefore(node, textarea.nextSibling);\n    }, options);\n    instance.save = save;\n    instance.getTextArea = function() { return textarea; };\n    instance.toTextArea = function() {\n      save();\n      textarea.parentNode.removeChild(instance.getWrapperElement());\n      textarea.style.display = \"\";\n      if (textarea.form) {\n        rmSubmit();\n        if (typeof textarea.form.submit == \"function\")\n          textarea.form.submit = realSubmit;\n      }\n    };\n    return instance;\n  };\n\n  // Utility functions for working with state. Exported because modes\n  // sometimes need to do this.\n  function copyState(mode, state) {\n    if (state === true) return state;\n    if (mode.copyState) return mode.copyState(state);\n    var nstate = {};\n    for (var n in state) {\n      var val = state[n];\n      if (val instanceof Array) val = val.concat([]);\n      nstate[n] = val;\n    }\n    return nstate;\n  }\n  CodeMirror.copyState = copyState;\n  function startState(mode, a1, a2) {\n    return mode.startState ? mode.startState(a1, a2) : true;\n  }\n  CodeMirror.startState = startState;\n\n  // The character stream used by a mode's parser.\n  function StringStream(string, tabSize) {\n    this.pos = this.start = 0;\n    this.string = string;\n    this.tabSize = tabSize || 8;\n  }\n  StringStream.prototype = {\n    eol: function() {return this.pos >= this.string.length;},\n    sol: function() {return this.pos == 0;},\n    peek: function() {return this.string.charAt(this.pos);},\n    next: function() {\n      if (this.pos < this.string.length)\n        return this.string.charAt(this.pos++);\n    },\n    eat: function(match) {\n      var ch = this.string.charAt(this.pos);\n      if (typeof match == \"string\") var ok = ch == match;\n      else var ok = ch && (match.test ? match.test(ch) : match(ch));\n      if (ok) {++this.pos; return ch;}\n    },\n    eatWhile: function(match) {\n      var start = this.pos;\n      while (this.eat(match)){}\n      return this.pos > start;\n    },\n    eatSpace: function() {\n      var start = this.pos;\n      while (/[\\s\\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;\n      return this.pos > start;\n    },\n    skipToEnd: function() {this.pos = this.string.length;},\n    skipTo: function(ch) {\n      var found = this.string.indexOf(ch, this.pos);\n      if (found > -1) {this.pos = found; return true;}\n    },\n    backUp: function(n) {this.pos -= n;},\n    column: function() {return countColumn(this.string, this.start, this.tabSize);},\n    indentation: function() {return countColumn(this.string, null, this.tabSize);},\n    match: function(pattern, consume, caseInsensitive) {\n      if (typeof pattern == \"string\") {\n        function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}\n        if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {\n          if (consume !== false) this.pos += pattern.length;\n          return true;\n        }\n      }\n      else {\n        var match = this.string.slice(this.pos).match(pattern);\n        if (match && consume !== false) this.pos += match[0].length;\n        return match;\n      }\n    },\n    current: function(){return this.string.slice(this.start, this.pos);}\n  };\n  CodeMirror.StringStream = StringStream;\n\n  function MarkedText(from, to, className, marker) {\n    this.from = from; this.to = to; this.style = className; this.marker = marker;\n  }\n  MarkedText.prototype = {\n    attach: function(line) { this.marker.set.push(line); },\n    detach: function(line) {\n      var ix = indexOf(this.marker.set, line);\n      if (ix > -1) this.marker.set.splice(ix, 1);\n    },\n    split: function(pos, lenBefore) {\n      if (this.to <= pos && this.to != null) return null;\n      var from = this.from < pos || this.from == null ? null : this.from - pos + lenBefore;\n      var to = this.to == null ? null : this.to - pos + lenBefore;\n      return new MarkedText(from, to, this.style, this.marker);\n    },\n    dup: function() { return new MarkedText(null, null, this.style, this.marker); },\n    clipTo: function(fromOpen, from, toOpen, to, diff) {\n      if (fromOpen && to > this.from && (to < this.to || this.to == null))\n        this.from = null;\n      else if (this.from != null && this.from >= from)\n        this.from = Math.max(to, this.from) + diff;\n      if (toOpen && (from < this.to || this.to == null) && (from > this.from || this.from == null))\n        this.to = null;\n      else if (this.to != null && this.to > from)\n        this.to = to < this.to ? this.to + diff : from;\n    },\n    isDead: function() { return this.from != null && this.to != null && this.from >= this.to; },\n    sameSet: function(x) { return this.marker == x.marker; }\n  };\n\n  function Bookmark(pos) {\n    this.from = pos; this.to = pos; this.line = null;\n  }\n  Bookmark.prototype = {\n    attach: function(line) { this.line = line; },\n    detach: function(line) { if (this.line == line) this.line = null; },\n    split: function(pos, lenBefore) {\n      if (pos < this.from) {\n        this.from = this.to = (this.from - pos) + lenBefore;\n        return this;\n      }\n    },\n    isDead: function() { return this.from > this.to; },\n    clipTo: function(fromOpen, from, toOpen, to, diff) {\n      if ((fromOpen || from < this.from) && (toOpen || to > this.to)) {\n        this.from = 0; this.to = -1;\n      } else if (this.from > from) {\n        this.from = this.to = Math.max(to, this.from) + diff;\n      }\n    },\n    sameSet: function(x) { return false; },\n    find: function() {\n      if (!this.line || !this.line.parent) return null;\n      return {line: lineNo(this.line), ch: this.from};\n    },\n    clear: function() {\n      if (this.line) {\n        var found = indexOf(this.line.marked, this);\n        if (found != -1) this.line.marked.splice(found, 1);\n        this.line = null;\n      }\n    }\n  };\n\n  // Line objects. These hold state related to a line, including\n  // highlighting info (the styles array).\n  function Line(text, styles) {\n    this.styles = styles || [text, null];\n    this.text = text;\n    this.height = 1;\n    this.marked = this.gutterMarker = this.className = this.bgClassName = this.handlers = null;\n    this.stateAfter = this.parent = this.hidden = null;\n  }\n  Line.inheritMarks = function(text, orig) {\n    var ln = new Line(text), mk = orig && orig.marked;\n    if (mk) {\n      for (var i = 0; i < mk.length; ++i) {\n        if (mk[i].to == null && mk[i].style) {\n          var newmk = ln.marked || (ln.marked = []), mark = mk[i];\n          var nmark = mark.dup(); newmk.push(nmark); nmark.attach(ln);\n        }\n      }\n    }\n    return ln;\n  }\n  Line.prototype = {\n    // Replace a piece of a line, keeping the styles around it intact.\n    replace: function(from, to_, text) {\n      var st = [], mk = this.marked, to = to_ == null ? this.text.length : to_;\n      copyStyles(0, from, this.styles, st);\n      if (text) st.push(text, null);\n      copyStyles(to, this.text.length, this.styles, st);\n      this.styles = st;\n      this.text = this.text.slice(0, from) + text + this.text.slice(to);\n      this.stateAfter = null;\n      if (mk) {\n        var diff = text.length - (to - from);\n        for (var i = 0; i < mk.length; ++i) {\n          var mark = mk[i];\n          mark.clipTo(from == null, from || 0, to_ == null, to, diff);\n          if (mark.isDead()) {mark.detach(this); mk.splice(i--, 1);}\n        }\n      }\n    },\n    // Split a part off a line, keeping styles and markers intact.\n    split: function(pos, textBefore) {\n      var st = [textBefore, null], mk = this.marked;\n      copyStyles(pos, this.text.length, this.styles, st);\n      var taken = new Line(textBefore + this.text.slice(pos), st);\n      if (mk) {\n        for (var i = 0; i < mk.length; ++i) {\n          var mark = mk[i];\n          var newmark = mark.split(pos, textBefore.length);\n          if (newmark) {\n            if (!taken.marked) taken.marked = [];\n            taken.marked.push(newmark); newmark.attach(taken);\n            if (newmark == mark) mk.splice(i--, 1);\n          }\n        }\n      }\n      return taken;\n    },\n    append: function(line) {\n      var mylen = this.text.length, mk = line.marked, mymk = this.marked;\n      this.text += line.text;\n      copyStyles(0, line.text.length, line.styles, this.styles);\n      if (mymk) {\n        for (var i = 0; i < mymk.length; ++i)\n          if (mymk[i].to == null) mymk[i].to = mylen;\n      }\n      if (mk && mk.length) {\n        if (!mymk) this.marked = mymk = [];\n        outer: for (var i = 0; i < mk.length; ++i) {\n          var mark = mk[i];\n          if (!mark.from) {\n            for (var j = 0; j < mymk.length; ++j) {\n              var mymark = mymk[j];\n              if (mymark.to == mylen && mymark.sameSet(mark)) {\n                mymark.to = mark.to == null ? null : mark.to + mylen;\n                if (mymark.isDead()) {\n                  mymark.detach(this);\n                  mk.splice(i--, 1);\n                }\n                continue outer;\n              }\n            }\n          }\n          mymk.push(mark);\n          mark.attach(this);\n          mark.from += mylen;\n          if (mark.to != null) mark.to += mylen;\n        }\n      }\n    },\n    fixMarkEnds: function(other) {\n      var mk = this.marked, omk = other.marked;\n      if (!mk) return;\n      for (var i = 0; i < mk.length; ++i) {\n        var mark = mk[i], close = mark.to == null;\n        if (close && omk) {\n          for (var j = 0; j < omk.length; ++j)\n            if (omk[j].sameSet(mark)) {close = false; break;}\n        }\n        if (close) mark.to = this.text.length;\n      }\n    },\n    fixMarkStarts: function() {\n      var mk = this.marked;\n      if (!mk) return;\n      for (var i = 0; i < mk.length; ++i)\n        if (mk[i].from == null) mk[i].from = 0;\n    },\n    addMark: function(mark) {\n      mark.attach(this);\n      if (this.marked == null) this.marked = [];\n      this.marked.push(mark);\n      this.marked.sort(function(a, b){return (a.from || 0) - (b.from || 0);});\n    },\n    // Run the given mode's parser over a line, update the styles\n    // array, which contains alternating fragments of text and CSS\n    // classes.\n    highlight: function(mode, state, tabSize) {\n      var stream = new StringStream(this.text, tabSize), st = this.styles, pos = 0;\n      var changed = false, curWord = st[0], prevWord;\n      if (this.text == \"\" && mode.blankLine) mode.blankLine(state);\n      while (!stream.eol()) {\n        var style = mode.token(stream, state);\n        var substr = this.text.slice(stream.start, stream.pos);\n        stream.start = stream.pos;\n        if (pos && st[pos-1] == style)\n          st[pos-2] += substr;\n        else if (substr) {\n          if (!changed && (st[pos+1] != style || (pos && st[pos-2] != prevWord))) changed = true;\n          st[pos++] = substr; st[pos++] = style;\n          prevWord = curWord; curWord = st[pos];\n        }\n        // Give up when line is ridiculously long\n        if (stream.pos > 5000) {\n          st[pos++] = this.text.slice(stream.pos); st[pos++] = null;\n          break;\n        }\n      }\n      if (st.length != pos) {st.length = pos; changed = true;}\n      if (pos && st[pos-2] != prevWord) changed = true;\n      // Short lines with simple highlights return null, and are\n      // counted as changed by the driver because they are likely to\n      // highlight the same way in various contexts.\n      return changed || (st.length < 5 && this.text.length < 10 ? null : false);\n    },\n    // Fetch the parser token for a given character. Useful for hacks\n    // that want to inspect the mode state (say, for completion).\n    getTokenAt: function(mode, state, ch) {\n      var txt = this.text, stream = new StringStream(txt);\n      while (stream.pos < ch && !stream.eol()) {\n        stream.start = stream.pos;\n        var style = mode.token(stream, state);\n      }\n      return {start: stream.start,\n              end: stream.pos,\n              string: stream.current(),\n              className: style || null,\n              state: state};\n    },\n    indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},\n    // Produces an HTML fragment for the line, taking selection,\n    // marking, and highlighting into account.\n    getHTML: function(makeTab, wrapAt, wrapId, wrapWBR) {\n      var html = [], first = true, col = 0;\n      function span_(text, style) {\n        if (!text) return;\n        // Work around a bug where, in some compat modes, IE ignores leading spaces\n        if (first && ie && text.charAt(0) == \" \") text = \"\\u00a0\" + text.slice(1);\n        first = false;\n        if (text.indexOf(\"\\t\") == -1) {\n          col += text.length;\n          var escaped = htmlEscape(text);\n        } else {\n          var escaped = \"\";\n          for (var pos = 0;;) {\n            var idx = text.indexOf(\"\\t\", pos);\n            if (idx == -1) {\n              escaped += htmlEscape(text.slice(pos));\n              col += text.length - pos;\n              break;\n            } else {\n              col += idx - pos;\n              var tab = makeTab(col);\n              escaped += htmlEscape(text.slice(pos, idx)) + tab.html;\n              col += tab.width;\n              pos = idx + 1;\n            }\n          }\n        }\n        if (style) html.push('<span class=\"', style, '\">', escaped, \"</span>\");\n        else html.push(escaped);\n      }\n      var span = span_;\n      if (wrapAt != null) {\n        var outPos = 0, open = \"<span id=\\\"\" + wrapId + \"\\\">\";\n        span = function(text, style) {\n          var l = text.length;\n          if (wrapAt >= outPos && wrapAt < outPos + l) {\n            if (wrapAt > outPos) {\n              span_(text.slice(0, wrapAt - outPos), style);\n              // See comment at the definition of spanAffectsWrapping\n              if (wrapWBR) html.push(\"<wbr>\");\n            }\n            html.push(open);\n            var cut = wrapAt - outPos;\n            span_(window.opera ? text.slice(cut, cut + 1) : text.slice(cut), style);\n            html.push(\"</span>\");\n            if (window.opera) span_(text.slice(cut + 1), style);\n            wrapAt--;\n            outPos += l;\n          } else {\n            outPos += l;\n            span_(text, style);\n            // Output empty wrapper when at end of line\n            if (outPos == wrapAt && outPos == len) html.push(open + \" </span>\");\n            // Stop outputting HTML when gone sufficiently far beyond measure\n            else if (outPos > wrapAt + 10 && /\\s/.test(text)) span = function(){};\n          }\n        }\n      }\n\n      var st = this.styles, allText = this.text, marked = this.marked;\n      var len = allText.length;\n      function styleToClass(style) {\n        if (!style) return null;\n        return \"cm-\" + style.replace(/ +/g, \" cm-\");\n      }\n\n      if (!allText && wrapAt == null) {\n        span(\" \");\n      } else if (!marked || !marked.length) {\n        for (var i = 0, ch = 0; ch < len; i+=2) {\n          var str = st[i], style = st[i+1], l = str.length;\n          if (ch + l > len) str = str.slice(0, len - ch);\n          ch += l;\n          span(str, styleToClass(style));\n        }\n      } else {\n        var pos = 0, i = 0, text = \"\", style, sg = 0;\n        var nextChange = marked[0].from || 0, marks = [], markpos = 0;\n        function advanceMarks() {\n          var m;\n          while (markpos < marked.length &&\n                 ((m = marked[markpos]).from == pos || m.from == null)) {\n            if (m.style != null) marks.push(m);\n            ++markpos;\n          }\n          nextChange = markpos < marked.length ? marked[markpos].from : Infinity;\n          for (var i = 0; i < marks.length; ++i) {\n            var to = marks[i].to || Infinity;\n            if (to == pos) marks.splice(i--, 1);\n            else nextChange = Math.min(to, nextChange);\n          }\n        }\n        var m = 0;\n        while (pos < len) {\n          if (nextChange == pos) advanceMarks();\n          var upto = Math.min(len, nextChange);\n          while (true) {\n            if (text) {\n              var end = pos + text.length;\n              var appliedStyle = style;\n              for (var j = 0; j < marks.length; ++j)\n                appliedStyle = (appliedStyle ? appliedStyle + \" \" : \"\") + marks[j].style;\n              span(end > upto ? text.slice(0, upto - pos) : text, appliedStyle);\n              if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}\n              pos = end;\n            }\n            text = st[i++]; style = styleToClass(st[i++]);\n          }\n        }\n      }\n      return html.join(\"\");\n    },\n    cleanUp: function() {\n      this.parent = null;\n      if (this.marked)\n        for (var i = 0, e = this.marked.length; i < e; ++i) this.marked[i].detach(this);\n    }\n  };\n  // Utility used by replace and split above\n  function copyStyles(from, to, source, dest) {\n    for (var i = 0, pos = 0, state = 0; pos < to; i+=2) {\n      var part = source[i], end = pos + part.length;\n      if (state == 0) {\n        if (end > from) dest.push(part.slice(from - pos, Math.min(part.length, to - pos)), source[i+1]);\n        if (end >= from) state = 1;\n      }\n      else if (state == 1) {\n        if (end > to) dest.push(part.slice(0, to - pos), source[i+1]);\n        else dest.push(part, source[i+1]);\n      }\n      pos = end;\n    }\n  }\n\n  // Data structure that holds the sequence of lines.\n  function LeafChunk(lines) {\n    this.lines = lines;\n    this.parent = null;\n    for (var i = 0, e = lines.length, height = 0; i < e; ++i) {\n      lines[i].parent = this;\n      height += lines[i].height;\n    }\n    this.height = height;\n  }\n  LeafChunk.prototype = {\n    chunkSize: function() { return this.lines.length; },\n    remove: function(at, n, callbacks) {\n      for (var i = at, e = at + n; i < e; ++i) {\n        var line = this.lines[i];\n        this.height -= line.height;\n        line.cleanUp();\n        if (line.handlers)\n          for (var j = 0; j < line.handlers.length; ++j) callbacks.push(line.handlers[j]);\n      }\n      this.lines.splice(at, n);\n    },\n    collapse: function(lines) {\n      lines.splice.apply(lines, [lines.length, 0].concat(this.lines));\n    },\n    insertHeight: function(at, lines, height) {\n      this.height += height;\n      this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));\n      for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;\n    },\n    iterN: function(at, n, op) {\n      for (var e = at + n; at < e; ++at)\n        if (op(this.lines[at])) return true;\n    }\n  };\n  function BranchChunk(children) {\n    this.children = children;\n    var size = 0, height = 0;\n    for (var i = 0, e = children.length; i < e; ++i) {\n      var ch = children[i];\n      size += ch.chunkSize(); height += ch.height;\n      ch.parent = this;\n    }\n    this.size = size;\n    this.height = height;\n    this.parent = null;\n  }\n  BranchChunk.prototype = {\n    chunkSize: function() { return this.size; },\n    remove: function(at, n, callbacks) {\n      this.size -= n;\n      for (var i = 0; i < this.children.length; ++i) {\n        var child = this.children[i], sz = child.chunkSize();\n        if (at < sz) {\n          var rm = Math.min(n, sz - at), oldHeight = child.height;\n          child.remove(at, rm, callbacks);\n          this.height -= oldHeight - child.height;\n          if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }\n          if ((n -= rm) == 0) break;\n          at = 0;\n        } else at -= sz;\n      }\n      if (this.size - n < 25) {\n        var lines = [];\n        this.collapse(lines);\n        this.children = [new LeafChunk(lines)];\n        this.children[0].parent = this;\n      }\n    },\n    collapse: function(lines) {\n      for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines);\n    },\n    insert: function(at, lines) {\n      var height = 0;\n      for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height;\n      this.insertHeight(at, lines, height);\n    },\n    insertHeight: function(at, lines, height) {\n      this.size += lines.length;\n      this.height += height;\n      for (var i = 0, e = this.children.length; i < e; ++i) {\n        var child = this.children[i], sz = child.chunkSize();\n        if (at <= sz) {\n          child.insertHeight(at, lines, height);\n          if (child.lines && child.lines.length > 50) {\n            while (child.lines.length > 50) {\n              var spilled = child.lines.splice(child.lines.length - 25, 25);\n              var newleaf = new LeafChunk(spilled);\n              child.height -= newleaf.height;\n              this.children.splice(i + 1, 0, newleaf);\n              newleaf.parent = this;\n            }\n            this.maybeSpill();\n          }\n          break;\n        }\n        at -= sz;\n      }\n    },\n    maybeSpill: function() {\n      if (this.children.length <= 10) return;\n      var me = this;\n      do {\n        var spilled = me.children.splice(me.children.length - 5, 5);\n        var sibling = new BranchChunk(spilled);\n        if (!me.parent) { // Become the parent node\n          var copy = new BranchChunk(me.children);\n          copy.parent = me;\n          me.children = [copy, sibling];\n          me = copy;\n        } else {\n          me.size -= sibling.size;\n          me.height -= sibling.height;\n          var myIndex = indexOf(me.parent.children, me);\n          me.parent.children.splice(myIndex + 1, 0, sibling);\n        }\n        sibling.parent = me.parent;\n      } while (me.children.length > 10);\n      me.parent.maybeSpill();\n    },\n    iter: function(from, to, op) { this.iterN(from, to - from, op); },\n    iterN: function(at, n, op) {\n      for (var i = 0, e = this.children.length; i < e; ++i) {\n        var child = this.children[i], sz = child.chunkSize();\n        if (at < sz) {\n          var used = Math.min(n, sz - at);\n          if (child.iterN(at, used, op)) return true;\n          if ((n -= used) == 0) break;\n          at = 0;\n        } else at -= sz;\n      }\n    }\n  };\n\n  function getLineAt(chunk, n) {\n    while (!chunk.lines) {\n      for (var i = 0;; ++i) {\n        var child = chunk.children[i], sz = child.chunkSize();\n        if (n < sz) { chunk = child; break; }\n        n -= sz;\n      }\n    }\n    return chunk.lines[n];\n  }\n  function lineNo(line) {\n    if (line.parent == null) return null;\n    var cur = line.parent, no = indexOf(cur.lines, line);\n    for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {\n      for (var i = 0, e = chunk.children.length; ; ++i) {\n        if (chunk.children[i] == cur) break;\n        no += chunk.children[i].chunkSize();\n      }\n    }\n    return no;\n  }\n  function lineAtHeight(chunk, h) {\n    var n = 0;\n    outer: do {\n      for (var i = 0, e = chunk.children.length; i < e; ++i) {\n        var child = chunk.children[i], ch = child.height;\n        if (h < ch) { chunk = child; continue outer; }\n        h -= ch;\n        n += child.chunkSize();\n      }\n      return n;\n    } while (!chunk.lines);\n    for (var i = 0, e = chunk.lines.length; i < e; ++i) {\n      var line = chunk.lines[i], lh = line.height;\n      if (h < lh) break;\n      h -= lh;\n    }\n    return n + i;\n  }\n  function heightAtLine(chunk, n) {\n    var h = 0;\n    outer: do {\n      for (var i = 0, e = chunk.children.length; i < e; ++i) {\n        var child = chunk.children[i], sz = child.chunkSize();\n        if (n < sz) { chunk = child; continue outer; }\n        n -= sz;\n        h += child.height;\n      }\n      return h;\n    } while (!chunk.lines);\n    for (var i = 0; i < n; ++i) h += chunk.lines[i].height;\n    return h;\n  }\n\n  // The history object 'chunks' changes that are made close together\n  // and at almost the same time into bigger undoable units.\n  function History() {\n    this.time = 0;\n    this.done = []; this.undone = [];\n    this.compound = 0;\n    this.closed = false;\n  }\n  History.prototype = {\n    addChange: function(start, added, old) {\n      this.undone.length = 0;\n      var time = +new Date, cur = this.done[this.done.length - 1], last = cur && cur[cur.length - 1];\n      var dtime = time - this.time;\n\n      if (this.compound && cur && !this.closed) {\n        cur.push({start: start, added: added, old: old});\n      } else if (dtime > 400 || !last || this.closed ||\n                 last.start > start + old.length || last.start + last.added < start) {\n        this.done.push([{start: start, added: added, old: old}]);\n        this.closed = false;\n      } else {\n        var startBefore = Math.max(0, last.start - start),\n            endAfter = Math.max(0, (start + old.length) - (last.start + last.added));\n        for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]);\n        for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]);\n        if (startBefore) last.start = start;\n        last.added += added - (old.length - startBefore - endAfter);\n      }\n      this.time = time;\n    },\n    startCompound: function() {\n      if (!this.compound++) this.closed = true;\n    },\n    endCompound: function() {\n      if (!--this.compound) this.closed = true;\n    }\n  };\n\n  function stopMethod() {e_stop(this);}\n  // Ensure an event has a stop method.\n  function addStop(event) {\n    if (!event.stop) event.stop = stopMethod;\n    return event;\n  }\n\n  function e_preventDefault(e) {\n    if (e.preventDefault) e.preventDefault();\n    else e.returnValue = false;\n  }\n  function e_stopPropagation(e) {\n    if (e.stopPropagation) e.stopPropagation();\n    else e.cancelBubble = true;\n  }\n  function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}\n  CodeMirror.e_stop = e_stop;\n  CodeMirror.e_preventDefault = e_preventDefault;\n  CodeMirror.e_stopPropagation = e_stopPropagation;\n\n  function e_target(e) {return e.target || e.srcElement;}\n  function e_button(e) {\n    if (e.which) return e.which;\n    else if (e.button & 1) return 1;\n    else if (e.button & 2) return 3;\n    else if (e.button & 4) return 2;\n  }\n\n  // Allow 3rd-party code to override event properties by adding an override\n  // object to an event object.\n  function e_prop(e, prop) {\n    var overridden = e.override && e.override.hasOwnProperty(prop);\n    return overridden ? e.override[prop] : e[prop];\n  }\n\n  // Event handler registration. If disconnect is true, it'll return a\n  // function that unregisters the handler.\n  function connect(node, type, handler, disconnect) {\n    if (typeof node.addEventListener == \"function\") {\n      node.addEventListener(type, handler, false);\n      if (disconnect) return function() {node.removeEventListener(type, handler, false);};\n    }\n    else {\n      var wrapHandler = function(event) {handler(event || window.event);};\n      node.attachEvent(\"on\" + type, wrapHandler);\n      if (disconnect) return function() {node.detachEvent(\"on\" + type, wrapHandler);};\n    }\n  }\n  CodeMirror.connect = connect;\n\n  function Delayed() {this.id = null;}\n  Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}};\n\n  var Pass = CodeMirror.Pass = {toString: function(){return \"CodeMirror.Pass\";}};\n\n  var gecko = /gecko\\/\\d{7}/i.test(navigator.userAgent);\n  var ie = /MSIE \\d/.test(navigator.userAgent);\n  var ie_lt9 = /MSIE [1-8]\\b/.test(navigator.userAgent);\n  var quirksMode = ie && document.documentMode == 5;\n  var webkit = /WebKit\\//.test(navigator.userAgent);\n  var chrome = /Chrome\\//.test(navigator.userAgent);\n  var safari = /Apple Computer/.test(navigator.vendor);\n  var khtml = /KHTML\\//.test(navigator.userAgent);\n\n  // Detect drag-and-drop\n  var dragAndDrop = function() {\n    // There is *some* kind of drag-and-drop support in IE6-8, but I\n    // couldn't get it to work yet.\n    if (ie_lt9) return false;\n    var div = document.createElement('div');\n    return \"draggable\" in div || \"dragDrop\" in div;\n  }();\n\n  // Feature-detect whether newlines in textareas are converted to \\r\\n\n  var lineSep = function () {\n    var te = document.createElement(\"textarea\");\n    te.value = \"foo\\nbar\";\n    if (te.value.indexOf(\"\\r\") > -1) return \"\\r\\n\";\n    return \"\\n\";\n  }();\n\n  // For a reason I have yet to figure out, some browsers disallow\n  // word wrapping between certain characters *only* if a new inline\n  // element is started between them. This makes it hard to reliably\n  // measure the position of things, since that requires inserting an\n  // extra span. This terribly fragile set of regexps matches the\n  // character combinations that suffer from this phenomenon on the\n  // various browsers.\n  var spanAffectsWrapping = /^$/; // Won't match any two-character string\n  if (gecko) spanAffectsWrapping = /$'/;\n  else if (safari) spanAffectsWrapping = /\\-[^ \\-?]|\\?[^ !'\\\"\\),.\\-\\/:;\\?\\]\\}]/;\n  else if (chrome) spanAffectsWrapping = /\\-[^ \\-\\.?]|\\?[^ \\-\\.?\\]\\}:;!'\\\"\\),\\/]|[\\.!\\\"#&%\\)*+,:;=>\\]|\\}~][\\(\\{\\[<]|\\$'/;\n\n  // Counts the column offset in a string, taking tabs into account.\n  // Used mostly to find indentation.\n  function countColumn(string, end, tabSize) {\n    if (end == null) {\n      end = string.search(/[^\\s\\u00a0]/);\n      if (end == -1) end = string.length;\n    }\n    for (var i = 0, n = 0; i < end; ++i) {\n      if (string.charAt(i) == \"\\t\") n += tabSize - (n % tabSize);\n      else ++n;\n    }\n    return n;\n  }\n\n  function computedStyle(elt) {\n    if (elt.currentStyle) return elt.currentStyle;\n    return window.getComputedStyle(elt, null);\n  }\n\n  // Find the position of an element by following the offsetParent chain.\n  // If screen==true, it returns screen (rather than page) coordinates.\n  function eltOffset(node, screen) {\n    var bod = node.ownerDocument.body;\n    var x = 0, y = 0, skipBody = false;\n    for (var n = node; n; n = n.offsetParent) {\n      var ol = n.offsetLeft, ot = n.offsetTop;\n      // Firefox reports weird inverted offsets when the body has a border.\n      if (n == bod) { x += Math.abs(ol); y += Math.abs(ot); }\n      else { x += ol, y += ot; }\n      if (screen && computedStyle(n).position == \"fixed\")\n        skipBody = true;\n    }\n    var e = screen && !skipBody ? null : bod;\n    for (var n = node.parentNode; n != e; n = n.parentNode)\n      if (n.scrollLeft != null) { x -= n.scrollLeft; y -= n.scrollTop;}\n    return {left: x, top: y};\n  }\n  // Use the faster and saner getBoundingClientRect method when possible.\n  if (document.documentElement.getBoundingClientRect != null) eltOffset = function(node, screen) {\n    // Take the parts of bounding client rect that we are interested in so we are able to edit if need be,\n    // since the returned value cannot be changed externally (they are kept in sync as the element moves within the page)\n    try { var box = node.getBoundingClientRect(); box = { top: box.top, left: box.left }; }\n    catch(e) { box = {top: 0, left: 0}; }\n    if (!screen) {\n      // Get the toplevel scroll, working around browser differences.\n      if (window.pageYOffset == null) {\n        var t = document.documentElement || document.body.parentNode;\n        if (t.scrollTop == null) t = document.body;\n        box.top += t.scrollTop; box.left += t.scrollLeft;\n      } else {\n        box.top += window.pageYOffset; box.left += window.pageXOffset;\n      }\n    }\n    return box;\n  };\n\n  // Get a node's text content.\n  function eltText(node) {\n    return node.textContent || node.innerText || node.nodeValue || \"\";\n  }\n  function selectInput(node) {\n    if (ios) { // Mobile Safari apparently has a bug where select() is broken.\n      node.selectionStart = 0;\n      node.selectionEnd = node.value.length;\n    } else node.select();\n  }\n\n  // Operations on {line, ch} objects.\n  function posEq(a, b) {return a.line == b.line && a.ch == b.ch;}\n  function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);}\n  function copyPos(x) {return {line: x.line, ch: x.ch};}\n\n  var escapeElement = document.createElement(\"pre\");\n  function htmlEscape(str) {\n    escapeElement.textContent = str;\n    return escapeElement.innerHTML;\n  }\n  // Recent (late 2011) Opera betas insert bogus newlines at the start\n  // of the textContent, so we strip those.\n  if (htmlEscape(\"a\") == \"\\na\")\n    htmlEscape = function(str) {\n      escapeElement.textContent = str;\n      return escapeElement.innerHTML.slice(1);\n    };\n  // Some IEs don't preserve tabs through innerHTML\n  else if (htmlEscape(\"\\t\") != \"\\t\")\n    htmlEscape = function(str) {\n      escapeElement.innerHTML = \"\";\n      escapeElement.appendChild(document.createTextNode(str));\n      return escapeElement.innerHTML;\n    };\n  CodeMirror.htmlEscape = htmlEscape;\n\n  // Used to position the cursor after an undo/redo by finding the\n  // last edited character.\n  function editEnd(from, to) {\n    if (!to) return 0;\n    if (!from) return to.length;\n    for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j)\n      if (from.charAt(i) != to.charAt(j)) break;\n    return j + 1;\n  }\n\n  function indexOf(collection, elt) {\n    if (collection.indexOf) return collection.indexOf(elt);\n    for (var i = 0, e = collection.length; i < e; ++i)\n      if (collection[i] == elt) return i;\n    return -1;\n  }\n  function isWordChar(ch) {\n    return /\\w/.test(ch) || ch.toUpperCase() != ch.toLowerCase();\n  }\n\n  // See if \"\".split is the broken IE version, if so, provide an\n  // alternative way to split lines.\n  var splitLines = \"\\n\\nb\".split(/\\n/).length != 3 ? function(string) {\n    var pos = 0, nl, result = [];\n    while ((nl = string.indexOf(\"\\n\", pos)) > -1) {\n      result.push(string.slice(pos, string.charAt(nl-1) == \"\\r\" ? nl - 1 : nl));\n      pos = nl + 1;\n    }\n    result.push(string.slice(pos));\n    return result;\n  } : function(string){return string.split(/\\r?\\n/);};\n  CodeMirror.splitLines = splitLines;\n\n  var hasSelection = window.getSelection ? function(te) {\n    try { return te.selectionStart != te.selectionEnd; }\n    catch(e) { return false; }\n  } : function(te) {\n    try {var range = te.ownerDocument.selection.createRange();}\n    catch(e) {}\n    if (!range || range.parentElement() != te) return false;\n    return range.compareEndPoints(\"StartToEnd\", range) != 0;\n  };\n\n  CodeMirror.defineMode(\"null\", function() {\n    return {token: function(stream) {stream.skipToEnd();}};\n  });\n  CodeMirror.defineMIME(\"text/plain\", \"null\");\n\n  var keyNames = {3: \"Enter\", 8: \"Backspace\", 9: \"Tab\", 13: \"Enter\", 16: \"Shift\", 17: \"Ctrl\", 18: \"Alt\",\n                  19: \"Pause\", 20: \"CapsLock\", 27: \"Esc\", 32: \"Space\", 33: \"PageUp\", 34: \"PageDown\", 35: \"End\",\n                  36: \"Home\", 37: \"Left\", 38: \"Up\", 39: \"Right\", 40: \"Down\", 44: \"PrintScrn\", 45: \"Insert\",\n                  46: \"Delete\", 59: \";\", 91: \"Mod\", 92: \"Mod\", 93: \"Mod\", 127: \"Delete\", 186: \";\", 187: \"=\", 188: \",\",\n                  189: \"-\", 190: \".\", 191: \"/\", 192: \"`\", 219: \"[\", 220: \"\\\\\", 221: \"]\", 222: \"'\", 63276: \"PageUp\",\n                  63277: \"PageDown\", 63275: \"End\", 63273: \"Home\", 63234: \"Left\", 63232: \"Up\", 63235: \"Right\",\n                  63233: \"Down\", 63302: \"Insert\", 63272: \"Delete\"};\n  CodeMirror.keyNames = keyNames;\n  (function() {\n    // Number keys\n    for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i);\n    // Alphabetic keys\n    for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);\n    // Function keys\n    for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = \"F\" + i;\n  })();\n\n  return CodeMirror;\n})();\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/closetag.js",
    "content": "/**\n * Tag-closer extension for CodeMirror.\n *\n * This extension adds a \"closeTag\" utility function that can be used with key bindings to \n * insert a matching end tag after the \">\" character of a start tag has been typed.  It can\n * also complete \"</\" if a matching start tag is found.  It will correctly ignore signal\n * characters for empty tags, comments, CDATA, etc.\n *\n * The function depends on internal parser state to identify tags.  It is compatible with the\n * following CodeMirror modes and will ignore all others:\n * - htmlmixed\n * - xml\n *\n * See demos/closetag.html for a usage example.\n * \n * @author Nathan Williams <nathan@nlwillia.net>\n * Contributed under the same license terms as CodeMirror.\n */\n(function() {\n\t/** Option that allows tag closing behavior to be toggled.  Default is true. */\n\tCodeMirror.defaults['closeTagEnabled'] = true;\n\t\n\t/** Array of tag names to add indentation after the start tag for.  Default is the list of block-level html tags. */\n\tCodeMirror.defaults['closeTagIndent'] = ['applet', 'blockquote', 'body', 'button', 'div', 'dl', 'fieldset', 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'html', 'iframe', 'layer', 'legend', 'object', 'ol', 'p', 'select', 'table', 'ul'];\n\n\t/**\n\t * Call during key processing to close tags.  Handles the key event if the tag is closed, otherwise throws CodeMirror.Pass.\n\t * - cm: The editor instance.\n\t * - ch: The character being processed.\n\t * - indent: Optional.  Omit or pass true to use the default indentation tag list defined in the 'closeTagIndent' option.\n\t *   Pass false to disable indentation.  Pass an array to override the default list of tag names.\n\t */\n\tCodeMirror.defineExtension(\"closeTag\", function(cm, ch, indent) {\n\t\tif (!cm.getOption('closeTagEnabled')) {\n\t\t\tthrow CodeMirror.Pass;\n\t\t}\n\t\t\n\t\tvar mode = cm.getOption('mode');\n\t\t\n\t\tif (mode == 'text/html') {\n\t\t\n\t\t\t/*\n\t\t\t * Relevant structure of token:\n\t\t\t *\n\t\t\t * htmlmixed\n\t\t\t * \t\tclassName\n\t\t\t * \t\tstate\n\t\t\t * \t\t\thtmlState\n\t\t\t * \t\t\t\ttype\n\t\t\t * \t\t\t\tcontext\n\t\t\t * \t\t\t\t\ttagName\n\t\t\t * \t\t\tmode\n\t\t\t * \n\t\t\t * xml\n\t\t\t * \t\tclassName\n\t\t\t * \t\tstate\n\t\t\t * \t\t\ttagName\n\t\t\t * \t\t\ttype\n\t\t\t */\n\t\t\n\t\t\tvar pos = cm.getCursor();\n\t\t\tvar tok = cm.getTokenAt(pos);\n\t\t\tvar state = tok.state;\n\t\t\t\n\t\t\tif (state.mode && state.mode != 'html') {\n\t\t\t\tthrow CodeMirror.Pass; // With htmlmixed, we only care about the html sub-mode.\n\t\t\t}\n\t\t\t\n\t\t\tif (ch == '>') {\n\t\t\t\tvar type = state.htmlState ? state.htmlState.type : state.type; // htmlmixed : xml\n\t\t\t\t\n\t\t\t\tif (tok.className == 'tag' && type == 'closeTag') {\n\t\t\t\t\tthrow CodeMirror.Pass; // Don't process the '>' at the end of an end-tag.\n\t\t\t\t}\n\t\t\t\n\t\t\t\tcm.replaceSelection('>'); // Mode state won't update until we finish the tag.\n\t\t\t\tpos = {line: pos.line, ch: pos.ch + 1};\n\t\t\t\tcm.setCursor(pos);\n\t\t\n\t\t\t\ttok = cm.getTokenAt(cm.getCursor());\n\t\t\t\tstate = tok.state;\n\t\t\t\ttype = state.htmlState ? state.htmlState.type : state.type; // htmlmixed : xml\n\n\t\t\t\tif (tok.className == 'tag' && type != 'selfcloseTag') {\n\t\t\t\t\tvar tagName = state.htmlState ? state.htmlState.context.tagName : state.tagName; // htmlmixed : xml\n\t\t\t\t\tif (tagName.length > 0) {\n\t\t\t\t\t\tinsertEndTag(cm, indent, pos, tagName);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// Undo the '>' insert and allow cm to handle the key instead.\n\t\t\t\tcm.setSelection({line: pos.line, ch: pos.ch - 1}, pos);\n\t\t\t\tcm.replaceSelection(\"\");\n\t\t\t\n\t\t\t} else if (ch == '/') {\n\t\t\t\tif (tok.className == 'tag' && tok.string == '<') {\n\t\t\t\t\tvar tagName = state.htmlState ? (state.htmlState.context ? state.htmlState.context.tagName : '') : state.context.tagName; // htmlmixed : xml # extra htmlmized check is for '</' edge case\n\t\t\t\t\tif (tagName.length > 0) {\n\t\t\t\t\t\tcompleteEndTag(cm, pos, tagName);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\n\t\t}\n\t\t\n\t\tthrow CodeMirror.Pass; // Bubble if not handled\n\t});\n\n\tfunction insertEndTag(cm, indent, pos, tagName) {\n\t\tif (shouldIndent(cm, indent, tagName)) {\n\t\t\tcm.replaceSelection('\\n\\n</' + tagName + '>', 'end');\n\t\t\tcm.indentLine(pos.line + 1);\n\t\t\tcm.indentLine(pos.line + 2);\n\t\t\tcm.setCursor({line: pos.line + 1, ch: cm.getLine(pos.line + 1).length});\n\t\t} else {\n\t\t\tcm.replaceSelection('</' + tagName + '>');\n\t\t\tcm.setCursor(pos);\n\t\t}\n\t}\n\t\n\tfunction shouldIndent(cm, indent, tagName) {\n\t\tif (typeof indent == 'undefined' || indent == null || indent == true) {\n\t\t\tindent = cm.getOption('closeTagIndent');\n\t\t}\n\t\tif (!indent) {\n\t\t\tindent = [];\n\t\t}\n\t\treturn indexOf(indent, tagName.toLowerCase()) != -1;\n\t}\n\t\n\t// C&P from codemirror.js...would be nice if this were visible to utilities.\n\tfunction indexOf(collection, elt) {\n\t\tif (collection.indexOf) return collection.indexOf(elt);\n\t\tfor (var i = 0, e = collection.length; i < e; ++i)\n\t\t\tif (collection[i] == elt) return i;\n\t\treturn -1;\n\t}\n\n\tfunction completeEndTag(cm, pos, tagName) {\n\t\tcm.replaceSelection('/' + tagName + '>');\n\t\tcm.setCursor({line: pos.line, ch: pos.ch + tagName.length + 2 });\n\t}\n\t\n})();\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/dialog.css",
    "content": ".CodeMirror-dialog {\n  position: relative;\n}\n\n.CodeMirror-dialog > div {\n  position: absolute;\n  top: 0; left: 0; right: 0;\n  background: white;\n  border-bottom: 1px solid #eee;\n  z-index: 15;\n  padding: .1em .8em;\n  overflow: hidden;\n  color: #333;\n}\n\n.CodeMirror-dialog input {\n  border: none;\n  outline: none;\n  background: transparent;\n  width: 20em;\n  color: inherit;\n  font-family: monospace;\n}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/dialog.js",
    "content": "// Open simple dialogs on top of an editor. Relies on dialog.css.\n\n(function() {\n  function dialogDiv(cm, template) {\n    var wrap = cm.getWrapperElement();\n    var dialog = wrap.insertBefore(document.createElement(\"div\"), wrap.firstChild);\n    dialog.className = \"CodeMirror-dialog\";\n    dialog.innerHTML = '<div>' + template + '</div>';\n    return dialog;\n  }\n\n  CodeMirror.defineExtension(\"openDialog\", function(template, callback) {\n    var dialog = dialogDiv(this, template);\n    var closed = false, me = this;\n    function close() {\n      if (closed) return;\n      closed = true;\n      dialog.parentNode.removeChild(dialog);\n    }\n    var inp = dialog.getElementsByTagName(\"input\")[0];\n    if (inp) {\n      CodeMirror.connect(inp, \"keydown\", function(e) {\n        if (e.keyCode == 13 || e.keyCode == 27) {\n          CodeMirror.e_stop(e);\n          close();\n          me.focus();\n          if (e.keyCode == 13) callback(inp.value);\n        }\n      });\n      inp.focus();\n      CodeMirror.connect(inp, \"blur\", close);\n    }\n    return close;\n  });\n\n  CodeMirror.defineExtension(\"openConfirm\", function(template, callbacks) {\n    var dialog = dialogDiv(this, template);\n    var buttons = dialog.getElementsByTagName(\"button\");\n    var closed = false, me = this, blurring = 1;\n    function close() {\n      if (closed) return;\n      closed = true;\n      dialog.parentNode.removeChild(dialog);\n      me.focus();\n    }\n    buttons[0].focus();\n    for (var i = 0; i < buttons.length; ++i) {\n      var b = buttons[i];\n      (function(callback) {\n        CodeMirror.connect(b, \"click\", function(e) {\n          CodeMirror.e_preventDefault(e);\n          close();\n          if (callback) callback(me);\n        });\n      })(callbacks[i]);\n      CodeMirror.connect(b, \"blur\", function() {\n        --blurring;\n        setTimeout(function() { if (blurring <= 0) close(); }, 200);\n      });\n      CodeMirror.connect(b, \"focus\", function() { ++blurring; });\n    }\n  });\n})();\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/foldcode.js",
    "content": "// the tagRangeFinder function is\n//   Copyright (C) 2011 by Daniel Glazman <daniel@glazman.org>\n// released under the MIT license (../../LICENSE) like the rest of CodeMirror\nCodeMirror.tagRangeFinder = function(cm, line, hideEnd) {\n  var nameStartChar = \"A-Z_a-z\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD\";\n  var nameChar = nameStartChar + \"\\-\\.0-9\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040\";\n  var xmlNAMERegExp = new RegExp(\"^[\" + nameStartChar + \"][\" + nameChar + \"]*\");\n\n  var lineText = cm.getLine(line);\n  var found = false;\n  var tag = null;\n  var pos = 0;\n  while (!found) {\n    pos = lineText.indexOf(\"<\", pos);\n    if (-1 == pos) // no tag on line\n      return;\n    if (pos + 1 < lineText.length && lineText[pos + 1] == \"/\") { // closing tag\n      pos++;\n      continue;\n    }\n    // ok we weem to have a start tag\n    if (!lineText.substr(pos + 1).match(xmlNAMERegExp)) { // not a tag name...\n      pos++;\n      continue;\n    }\n    var gtPos = lineText.indexOf(\">\", pos + 1);\n    if (-1 == gtPos) { // end of start tag not in line\n      var l = line + 1;\n      var foundGt = false;\n      var lastLine = cm.lineCount();\n      while (l < lastLine && !foundGt) {\n        var lt = cm.getLine(l);\n        var gt = lt.indexOf(\">\");\n        if (-1 != gt) { // found a >\n          foundGt = true;\n          var slash = lt.lastIndexOf(\"/\", gt);\n          if (-1 != slash && slash < gt) {\n            var str = lineText.substr(slash, gt - slash + 1);\n            if (!str.match( /\\/\\s*\\>/ )) { // yep, that's the end of empty tag\n              if (hideEnd === true) l++;\n              return l;\n            }\n          }\n        }\n        l++;\n      }\n      found = true;\n    }\n    else {\n      var slashPos = lineText.lastIndexOf(\"/\", gtPos);\n      if (-1 == slashPos) { // cannot be empty tag\n        found = true;\n        // don't continue\n      }\n      else { // empty tag?\n        // check if really empty tag\n        var str = lineText.substr(slashPos, gtPos - slashPos + 1);\n        if (!str.match( /\\/\\s*\\>/ )) { // finally not empty\n          found = true;\n          // don't continue\n        }\n      }\n    }\n    if (found) {\n      var subLine = lineText.substr(pos + 1);\n      tag = subLine.match(xmlNAMERegExp);\n      if (tag) {\n        // we have an element name, wooohooo !\n        tag = tag[0];\n        // do we have the close tag on same line ???\n        if (-1 != lineText.indexOf(\"</\" + tag + \">\", pos)) // yep\n        {\n          found = false;\n        }\n        // we don't, so we have a candidate...\n      }\n      else\n        found = false;\n    }\n    if (!found)\n      pos++;\n  }\n\n  if (found) {\n    var startTag = \"(\\\\<\\\\/\" + tag + \"\\\\>)|(\\\\<\" + tag + \"\\\\>)|(\\\\<\" + tag + \"\\\\s)|(\\\\<\" + tag + \"$)\";\n    var startTagRegExp = new RegExp(startTag, \"g\");\n    var endTag = \"</\" + tag + \">\";\n    var depth = 1;\n    var l = line + 1;\n    var lastLine = cm.lineCount();\n    while (l < lastLine) {\n      lineText = cm.getLine(l);\n      var match = lineText.match(startTagRegExp);\n      if (match) {\n        for (var i = 0; i < match.length; i++) {\n          if (match[i] == endTag)\n            depth--;\n          else\n            depth++;\n          if (!depth) {\n            if (hideEnd === true) l++;\n            return l;\n          }\n        }\n      }\n      l++;\n    }\n    return;\n  }\n};\n\nCodeMirror.braceRangeFinder = function(cm, line, hideEnd) {\n  var lineText = cm.getLine(line);\n  var startChar = lineText.lastIndexOf(\"{\");\n  if (startChar < 0 || lineText.lastIndexOf(\"}\") > startChar) return;\n  var tokenType = cm.getTokenAt({line: line, ch: startChar}).className;\n  var count = 1, lastLine = cm.lineCount(), end;\n  outer: for (var i = line + 1; i < lastLine; ++i) {\n    var text = cm.getLine(i), pos = 0;\n    for (;;) {\n      var nextOpen = text.indexOf(\"{\", pos), nextClose = text.indexOf(\"}\", pos);\n      if (nextOpen < 0) nextOpen = text.length;\n      if (nextClose < 0) nextClose = text.length;\n      pos = Math.min(nextOpen, nextClose);\n      if (pos == text.length) break;\n      if (cm.getTokenAt({line: i, ch: pos + 1}).className == tokenType) {\n        if (pos == nextOpen) ++count;\n        else if (!--count) { end = i; break outer; }\n      }\n      ++pos;\n    }\n  }\n  if (end == null || end == line + 1) return;\n  if (hideEnd === true) end++;\n  return end;\n};\n\nCodeMirror.indentRangeFinder = function(cm, line) {\n  var tabSize = cm.getOption(\"tabSize\");\n  var myIndent = cm.getLineHandle(line).indentation(tabSize), last;\n  for (var i = line + 1, end = cm.lineCount(); i < end; ++i) {\n    var handle = cm.getLineHandle(i);\n    if (!/^\\s*$/.test(handle.text)) {\n      if (handle.indentation(tabSize) <= myIndent) break;\n      last = i;\n    }\n  }\n  if (!last) return null;\n  return last + 1;\n};\n\nCodeMirror.newFoldFunction = function(rangeFinder, markText, hideEnd) {\n  var folded = [];\n  if (markText == null) markText = '<div style=\"position: absolute; left: 2px; color:#600\">&#x25bc;</div>%N%';\n\n  function isFolded(cm, n) {\n    for (var i = 0; i < folded.length; ++i) {\n      var start = cm.lineInfo(folded[i].start);\n      if (!start) folded.splice(i--, 1);\n      else if (start.line == n) return {pos: i, region: folded[i]};\n    }\n  }\n\n  function expand(cm, region) {\n    cm.clearMarker(region.start);\n    for (var i = 0; i < region.hidden.length; ++i)\n      cm.showLine(region.hidden[i]);\n  }\n\n  return function(cm, line) {\n    cm.operation(function() {\n      var known = isFolded(cm, line);\n      if (known) {\n        folded.splice(known.pos, 1);\n        expand(cm, known.region);\n      } else {\n        var end = rangeFinder(cm, line, hideEnd);\n        if (end == null) return;\n        var hidden = [];\n        for (var i = line + 1; i < end; ++i) {\n          var handle = cm.hideLine(i);\n          if (handle) hidden.push(handle);\n        }\n        var first = cm.setMarker(line, markText);\n        var region = {start: first, hidden: hidden};\n        cm.onDeleteLine(first, function() { expand(cm, region); });\n        folded.push(region);\n      }\n    });\n  };\n};\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/formatting.js",
    "content": "// ============== Formatting extensions ============================\n// A common storage for all mode-specific formatting features\nif (!CodeMirror.modeExtensions) CodeMirror.modeExtensions = {};\n\n// Returns the extension of the editor's current mode\nCodeMirror.defineExtension(\"getModeExt\", function () {\n  var mname = CodeMirror.resolveMode(this.getOption(\"mode\")).name;\n  var ext = CodeMirror.modeExtensions[mname];\n  if (!ext) throw new Error(\"No extensions found for mode \" + mname);\n  return ext;\n});\n\n// If the current mode is 'htmlmixed', returns the extension of a mode located at\n// the specified position (can be htmlmixed, css or javascript). Otherwise, simply\n// returns the extension of the editor's current mode.\nCodeMirror.defineExtension(\"getModeExtAtPos\", function (pos) {\n  var token = this.getTokenAt(pos);\n  if (token && token.state && token.state.mode)\n    return CodeMirror.modeExtensions[token.state.mode == \"html\" ? \"htmlmixed\" : token.state.mode];\n  else\n    return this.getModeExt();\n});\n\n// Comment/uncomment the specified range\nCodeMirror.defineExtension(\"commentRange\", function (isComment, from, to) {\n  var curMode = this.getModeExtAtPos(this.getCursor());\n  if (isComment) { // Comment range\n    var commentedText = this.getRange(from, to);\n    this.replaceRange(curMode.commentStart + this.getRange(from, to) + curMode.commentEnd\n      , from, to);\n    if (from.line == to.line && from.ch == to.ch) { // An empty comment inserted - put cursor inside\n      this.setCursor(from.line, from.ch + curMode.commentStart.length);\n    }\n  }\n  else { // Uncomment range\n    var selText = this.getRange(from, to);\n    var startIndex = selText.indexOf(curMode.commentStart);\n    var endIndex = selText.lastIndexOf(curMode.commentEnd);\n    if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {\n      // Take string till comment start\n      selText = selText.substr(0, startIndex)\n      // From comment start till comment end\n        + selText.substring(startIndex + curMode.commentStart.length, endIndex)\n      // From comment end till string end\n        + selText.substr(endIndex + curMode.commentEnd.length);\n    }\n    this.replaceRange(selText, from, to);\n  }\n});\n\n// Applies automatic mode-aware indentation to the specified range\nCodeMirror.defineExtension(\"autoIndentRange\", function (from, to) {\n  var cmInstance = this;\n  this.operation(function () {\n    for (var i = from.line; i <= to.line; i++) {\n      cmInstance.indentLine(i, \"smart\");\n    }\n  });\n});\n\n// Applies automatic formatting to the specified range\nCodeMirror.defineExtension(\"autoFormatRange\", function (from, to) {\n  var absStart = this.indexFromPos(from);\n  var absEnd = this.indexFromPos(to);\n  // Insert additional line breaks where necessary according to the\n  // mode's syntax\n  var res = this.getModeExt().autoFormatLineBreaks(this.getValue(), absStart, absEnd);\n  var cmInstance = this;\n\n  // Replace and auto-indent the range\n  this.operation(function () {\n    cmInstance.replaceRange(res, from, to);\n    var startLine = cmInstance.posFromIndex(absStart).line;\n    var endLine = cmInstance.posFromIndex(absStart + res.length).line;\n    for (var i = startLine; i <= endLine; i++) {\n      cmInstance.indentLine(i, \"smart\");\n    }\n  });\n});\n\n// Define extensions for a few modes\n\nCodeMirror.modeExtensions[\"css\"] = {\n  commentStart: \"/*\",\n  commentEnd: \"*/\",\n  wordWrapChars: [\";\", \"\\\\{\", \"\\\\}\"],\n  autoFormatLineBreaks: function (text) {\n    return text.replace(new RegExp(\"(;|\\\\{|\\\\})([^\\r\\n])\", \"g\"), \"$1\\n$2\");\n  }\n};\n\nCodeMirror.modeExtensions[\"javascript\"] = {\n  commentStart: \"/*\",\n  commentEnd: \"*/\",\n  wordWrapChars: [\";\", \"\\\\{\", \"\\\\}\"],\n\n  getNonBreakableBlocks: function (text) {\n    var nonBreakableRegexes = [\n        new RegExp(\"for\\\\s*?\\\\(([\\\\s\\\\S]*?)\\\\)\"),\n        new RegExp(\"'([\\\\s\\\\S]*?)('|$)\"),\n        new RegExp(\"\\\"([\\\\s\\\\S]*?)(\\\"|$)\"),\n        new RegExp(\"//.*([\\r\\n]|$)\")\n      ];\n    var nonBreakableBlocks = new Array();\n    for (var i = 0; i < nonBreakableRegexes.length; i++) {\n      var curPos = 0;\n      while (curPos < text.length) {\n        var m = text.substr(curPos).match(nonBreakableRegexes[i]);\n        if (m != null) {\n          nonBreakableBlocks.push({\n            start: curPos + m.index,\n            end: curPos + m.index + m[0].length\n          });\n          curPos += m.index + Math.max(1, m[0].length);\n        }\n        else { // No more matches\n          break;\n        }\n      }\n    }\n    nonBreakableBlocks.sort(function (a, b) {\n      return a.start - b.start;\n    });\n\n    return nonBreakableBlocks;\n  },\n\n  autoFormatLineBreaks: function (text) {\n    var curPos = 0;\n    var reLinesSplitter = new RegExp(\"(;|\\\\{|\\\\})([^\\r\\n])\", \"g\");\n    var nonBreakableBlocks = this.getNonBreakableBlocks(text);\n    if (nonBreakableBlocks != null) {\n      var res = \"\";\n      for (var i = 0; i < nonBreakableBlocks.length; i++) {\n        if (nonBreakableBlocks[i].start > curPos) { // Break lines till the block\n          res += text.substring(curPos, nonBreakableBlocks[i].start).replace(reLinesSplitter, \"$1\\n$2\");\n          curPos = nonBreakableBlocks[i].start;\n        }\n        if (nonBreakableBlocks[i].start <= curPos\n          && nonBreakableBlocks[i].end >= curPos) { // Skip non-breakable block\n          res += text.substring(curPos, nonBreakableBlocks[i].end);\n          curPos = nonBreakableBlocks[i].end;\n        }\n      }\n      if (curPos < text.length - 1) {\n        res += text.substr(curPos).replace(reLinesSplitter, \"$1\\n$2\");\n      }\n      return res;\n    }\n    else {\n      return text.replace(reLinesSplitter, \"$1\\n$2\");\n    }\n  }\n};\n\nCodeMirror.modeExtensions[\"xml\"] = {\n  commentStart: \"<!--\",\n  commentEnd: \"-->\",\n  wordWrapChars: [\">\"],\n\n  autoFormatLineBreaks: function (text) {\n    var lines = text.split(\"\\n\");\n    var reProcessedPortion = new RegExp(\"(^\\\\s*?<|^[^<]*?)(.+)(>\\\\s*?$|[^>]*?$)\");\n    var reOpenBrackets = new RegExp(\"<\", \"g\");\n    var reCloseBrackets = new RegExp(\"(>)([^\\r\\n])\", \"g\");\n    for (var i = 0; i < lines.length; i++) {\n      var mToProcess = lines[i].match(reProcessedPortion);\n      if (mToProcess != null && mToProcess.length > 3) { // The line starts with whitespaces and ends with whitespaces\n        lines[i] = mToProcess[1]\n            + mToProcess[2].replace(reOpenBrackets, \"\\n$&\").replace(reCloseBrackets, \"$1\\n$2\")\n            + mToProcess[3];\n        continue;\n      }\n    }\n\n    return lines.join(\"\\n\");\n  }\n};\n\nCodeMirror.modeExtensions[\"htmlmixed\"] = {\n  commentStart: \"<!--\",\n  commentEnd: \"-->\",\n  wordWrapChars: [\">\", \";\", \"\\\\{\", \"\\\\}\"],\n\n  getModeInfos: function (text, absPos) {\n    var modeInfos = new Array();\n    modeInfos[0] =\n      {\n        pos: 0,\n        modeExt: CodeMirror.modeExtensions[\"xml\"],\n        modeName: \"xml\"\n      };\n\n    var modeMatchers = new Array();\n    modeMatchers[0] =\n      {\n        regex: new RegExp(\"<style[^>]*>([\\\\s\\\\S]*?)(</style[^>]*>|$)\", \"i\"),\n        modeExt: CodeMirror.modeExtensions[\"css\"],\n        modeName: \"css\"\n      };\n    modeMatchers[1] =\n      {\n        regex: new RegExp(\"<script[^>]*>([\\\\s\\\\S]*?)(</script[^>]*>|$)\", \"i\"),\n        modeExt: CodeMirror.modeExtensions[\"javascript\"],\n        modeName: \"javascript\"\n      };\n\n    var lastCharPos = (typeof (absPos) !== \"undefined\" ? absPos : text.length - 1);\n    // Detect modes for the entire text\n    for (var i = 0; i < modeMatchers.length; i++) {\n      var curPos = 0;\n      while (curPos <= lastCharPos) {\n        var m = text.substr(curPos).match(modeMatchers[i].regex);\n        if (m != null) {\n          if (m.length > 1 && m[1].length > 0) {\n            // Push block begin pos\n            var blockBegin = curPos + m.index + m[0].indexOf(m[1]);\n            modeInfos.push(\n              {\n                pos: blockBegin,\n                modeExt: modeMatchers[i].modeExt,\n                modeName: modeMatchers[i].modeName\n              });\n            // Push block end pos\n            modeInfos.push(\n              {\n                pos: blockBegin + m[1].length,\n                modeExt: modeInfos[0].modeExt,\n                modeName: modeInfos[0].modeName\n              });\n            curPos += m.index + m[0].length;\n            continue;\n          }\n          else {\n            curPos += m.index + Math.max(m[0].length, 1);\n          }\n        }\n        else { // No more matches\n          break;\n        }\n      }\n    }\n    // Sort mode infos\n    modeInfos.sort(function sortModeInfo(a, b) {\n      return a.pos - b.pos;\n    });\n\n    return modeInfos;\n  },\n\n  autoFormatLineBreaks: function (text, startPos, endPos) {\n    var modeInfos = this.getModeInfos(text);\n    var reBlockStartsWithNewline = new RegExp(\"^\\\\s*?\\n\");\n    var reBlockEndsWithNewline = new RegExp(\"\\n\\\\s*?$\");\n    var res = \"\";\n    // Use modes info to break lines correspondingly\n    if (modeInfos.length > 1) { // Deal with multi-mode text\n      for (var i = 1; i <= modeInfos.length; i++) {\n        var selStart = modeInfos[i - 1].pos;\n        var selEnd = (i < modeInfos.length ? modeInfos[i].pos : endPos);\n\n        if (selStart >= endPos) { // The block starts later than the needed fragment\n          break;\n        }\n        if (selStart < startPos) {\n          if (selEnd <= startPos) { // The block starts earlier than the needed fragment\n            continue;\n          }\n          selStart = startPos;\n        }\n        if (selEnd > endPos) {\n          selEnd = endPos;\n        }\n        var textPortion = text.substring(selStart, selEnd);\n        if (modeInfos[i - 1].modeName != \"xml\") { // Starting a CSS or JavaScript block\n          if (!reBlockStartsWithNewline.test(textPortion)\n              && selStart > 0) { // The block does not start with a line break\n            textPortion = \"\\n\" + textPortion;\n          }\n          if (!reBlockEndsWithNewline.test(textPortion)\n              && selEnd < text.length - 1) { // The block does not end with a line break\n            textPortion += \"\\n\";\n          }\n        }\n        res += modeInfos[i - 1].modeExt.autoFormatLineBreaks(textPortion);\n      }\n    }\n    else { // Single-mode text\n      res = modeInfos[0].modeExt.autoFormatLineBreaks(text.substring(startPos, endPos));\n    }\n\n    return res;\n  }\n};\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/javascript-hint.js",
    "content": "(function () {\n  function forEach(arr, f) {\n    for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);\n  }\n  \n  function arrayContains(arr, item) {\n    if (!Array.prototype.indexOf) {\n      var i = arr.length;\n      while (i--) {\n        if (arr[i] === item) {\n          return true;\n        }\n      }\n      return false;\n    }\n    return arr.indexOf(item) != -1;\n  }\n\n  function scriptHint(editor, keywords, getToken) {\n    // Find the token at the cursor\n    var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;\n    // If it's not a 'word-style' token, ignore the token.\n\t\tif (!/^[\\w$_]*$/.test(token.string)) {\n      token = tprop = {start: cur.ch, end: cur.ch, string: \"\", state: token.state,\n                       className: token.string == \".\" ? \"property\" : null};\n    }\n    // If it is a property, find out what it is a property of.\n    while (tprop.className == \"property\") {\n      tprop = getToken(editor, {line: cur.line, ch: tprop.start});\n      if (tprop.string != \".\") return;\n      tprop = getToken(editor, {line: cur.line, ch: tprop.start});\n      if (tprop.string == ')') {\n        var level = 1;\n        do {\n          tprop = getToken(editor, {line: cur.line, ch: tprop.start});\n          switch (tprop.string) {\n          case ')': level++; break;\n          case '(': level--; break;\n          default: break;\n          }\n        } while (level > 0)\n        tprop = getToken(editor, {line: cur.line, ch: tprop.start});\n\t\t\t\tif (tprop.className == 'variable')\n\t\t\t\t\ttprop.className = 'function';\n\t\t\t\telse return; // no clue\n      }\n      if (!context) var context = [];\n      context.push(tprop);\n    }\n    return {list: getCompletions(token, context, keywords),\n            from: {line: cur.line, ch: token.start},\n            to: {line: cur.line, ch: token.end}};\n  }\n\n  CodeMirror.javascriptHint = function(editor) {\n    return scriptHint(editor, javascriptKeywords,\n                      function (e, cur) {return e.getTokenAt(cur);});\n  }\n\n  function getCoffeeScriptToken(editor, cur) {\n  // This getToken, it is for coffeescript, imitates the behavior of\n  // getTokenAt method in javascript.js, that is, returning \"property\"\n  // type and treat \".\" as indepenent token.\n    var token = editor.getTokenAt(cur);\n    if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {\n      token.end = token.start;\n      token.string = '.';\n      token.className = \"property\";\n    }\n    else if (/^\\.[\\w$_]*$/.test(token.string)) {\n      token.className = \"property\";\n      token.start++;\n      token.string = token.string.replace(/\\./, '');\n    }\n    return token;\n  }\n\n  CodeMirror.coffeescriptHint = function(editor) {\n    return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken);\n  }\n\n  var stringProps = (\"charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight \" +\n                     \"toUpperCase toLowerCase split concat match replace search\").split(\" \");\n  var arrayProps = (\"length concat join splice push pop shift unshift slice reverse sort indexOf \" +\n                    \"lastIndexOf every some filter forEach map reduce reduceRight \").split(\" \");\n  var funcProps = \"prototype apply call bind\".split(\" \");\n  var javascriptKeywords = (\"break case catch continue debugger default delete do else false finally for function \" +\n                  \"if in instanceof new null return switch throw true try typeof var void while with\").split(\" \");\n  var coffeescriptKeywords = (\"and break catch class continue delete do else extends false finally for \" +\n                  \"if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes\").split(\" \");\n\n  function getCompletions(token, context, keywords) {\n    var found = [], start = token.string;\n    function maybeAdd(str) {\n      if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);\n    }\n    function gatherCompletions(obj) {\n      if (typeof obj == \"string\") forEach(stringProps, maybeAdd);\n      else if (obj instanceof Array) forEach(arrayProps, maybeAdd);\n      else if (obj instanceof Function) forEach(funcProps, maybeAdd);\n      for (var name in obj) maybeAdd(name);\n    }\n\n    if (context) {\n      // If this is a property, see if it belongs to some object we can\n      // find in the current environment.\n      var obj = context.pop(), base;\n      if (obj.className == \"variable\")\n        base = window[obj.string];\n      else if (obj.className == \"string\")\n        base = \"\";\n      else if (obj.className == \"atom\")\n        base = 1;\n      else if (obj.className == \"function\") {\n        if (window.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&\n            (typeof window.jQuery == 'function'))\n          base = window.jQuery();\n        else if (window._ != null && (obj.string == '_') && (typeof window._ == 'function'))\n          base = window._();\n      }\n      while (base != null && context.length)\n        base = base[context.pop().string];\n      if (base != null) gatherCompletions(base);\n    }\n    else {\n      // If not, just look in the window object and any local scope\n      // (reading into JS mode internals to get at the local variables)\n      for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);\n      gatherCompletions(window);\n      forEach(keywords, maybeAdd);\n    }\n    return found;\n  }\n})();\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/loadmode.js",
    "content": "(function() {\n  if (!CodeMirror.modeURL) CodeMirror.modeURL = \"../mode/%N/%N.js\";\n\n  var loading = {};\n  function splitCallback(cont, n) {\n    var countDown = n;\n    return function() { if (--countDown == 0) cont(); }\n  }\n  function ensureDeps(mode, cont) {\n    var deps = CodeMirror.modes[mode].dependencies;\n    if (!deps) return cont();\n    var missing = [];\n    for (var i = 0; i < deps.length; ++i) {\n      if (!CodeMirror.modes.hasOwnProperty(deps[i]))\n        missing.push(deps[i]);\n    }\n    if (!missing.length) return cont();\n    var split = splitCallback(cont, missing.length);\n    for (var i = 0; i < missing.length; ++i)\n      CodeMirror.requireMode(missing[i], split);\n  }\n\n  CodeMirror.requireMode = function(mode, cont) {\n    if (typeof mode != \"string\") mode = mode.name;\n    if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);\n    if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);\n\n    var script = document.createElement(\"script\");\n    script.src = CodeMirror.modeURL.replace(/%N/g, mode);\n    var others = document.getElementsByTagName(\"script\")[0];\n    others.parentNode.insertBefore(script, others);\n    var list = loading[mode] = [cont];\n    var count = 0, poll = setInterval(function() {\n      if (++count > 100) return clearInterval(poll);\n      if (CodeMirror.modes.hasOwnProperty(mode)) {\n        clearInterval(poll);\n        loading[mode] = null;\n        ensureDeps(mode, function() {\n          for (var i = 0; i < list.length; ++i) list[i]();\n        });\n      }\n    }, 200);\n  };\n\n  CodeMirror.autoLoadMode = function(instance, mode) {\n    if (!CodeMirror.modes.hasOwnProperty(mode))\n      CodeMirror.requireMode(mode, function() {\n        instance.setOption(\"mode\", instance.getOption(\"mode\"));\n      });\n  };\n}());\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/match-highlighter.js",
    "content": "// Define match-highlighter commands. Depends on searchcursor.js\n// Use by attaching the following function call to the onCursorActivity event:\n\t//myCodeMirror.matchHighlight(minChars);\n// And including a special span.CodeMirror-matchhighlight css class (also optionally a separate one for .CodeMirror-focused -- see demo matchhighlighter.html)\n\n(function() {\n  var DEFAULT_MIN_CHARS = 2;\n  \n  function MatchHighlightState() {\n\tthis.marked = [];\n  }\n  function getMatchHighlightState(cm) {\n\treturn cm._matchHighlightState || (cm._matchHighlightState = new MatchHighlightState());\n  }\n  \n  function clearMarks(cm) {\n\tvar state = getMatchHighlightState(cm);\n\tfor (var i = 0; i < state.marked.length; ++i)\n\t\tstate.marked[i].clear();\n\tstate.marked = [];\n  }\n  \n  function markDocument(cm, className, minChars) {\n    clearMarks(cm);\n\tminChars = (typeof minChars !== 'undefined' ? minChars : DEFAULT_MIN_CHARS);\n\tif (cm.somethingSelected() && cm.getSelection().replace(/^\\s+|\\s+$/g, \"\").length >= minChars) {\n\t\tvar state = getMatchHighlightState(cm);\n\t\tvar query = cm.getSelection();\n\t\tcm.operation(function() {\n\t\t\tif (cm.lineCount() < 2000) { // This is too expensive on big documents.\n\t\t\t  for (var cursor = cm.getSearchCursor(query); cursor.findNext();) {\n\t\t\t\t//Only apply matchhighlight to the matches other than the one actually selected\n\t\t\t\tif (!(cursor.from().line === cm.getCursor(true).line && cursor.from().ch === cm.getCursor(true).ch))\n\t\t\t\t\tstate.marked.push(cm.markText(cursor.from(), cursor.to(), className));\n\t\t\t  }\n\t\t\t}\n\t\t  });\n\t}\n  }\n\n  CodeMirror.defineExtension(\"matchHighlight\", function(className, minChars) {\n    markDocument(this, className, minChars);\n  });\n})();\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/overlay.js",
    "content": "// Utility function that allows modes to be combined. The mode given\n// as the base argument takes care of most of the normal mode\n// functionality, but a second (typically simple) mode is used, which\n// can override the style of text. Both modes get to parse all of the\n// text, but when both assign a non-null style to a piece of code, the\n// overlay wins, unless the combine argument was true, in which case\n// the styles are combined.\n\nCodeMirror.overlayParser = function(base, overlay, combine) {\n  return {\n    startState: function() {\n      return {\n        base: CodeMirror.startState(base),\n        overlay: CodeMirror.startState(overlay),\n        basePos: 0, baseCur: null,\n        overlayPos: 0, overlayCur: null\n      };\n    },\n    copyState: function(state) {\n      return {\n        base: CodeMirror.copyState(base, state.base),\n        overlay: CodeMirror.copyState(overlay, state.overlay),\n        basePos: state.basePos, baseCur: null,\n        overlayPos: state.overlayPos, overlayCur: null\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.start == state.basePos) {\n        state.baseCur = base.token(stream, state.base);\n        state.basePos = stream.pos;\n      }\n      if (stream.start == state.overlayPos) {\n        stream.pos = stream.start;\n        state.overlayCur = overlay.token(stream, state.overlay);\n        state.overlayPos = stream.pos;\n      }\n      stream.pos = Math.min(state.basePos, state.overlayPos);\n      if (stream.eol()) state.basePos = state.overlayPos = 0;\n\n      if (state.overlayCur == null) return state.baseCur;\n      if (state.baseCur != null && combine) return state.baseCur + \" \" + state.overlayCur;\n      else return state.overlayCur;\n    },\n    \n    indent: base.indent && function(state, textAfter) {\n      return base.indent(state.base, textAfter);\n    },\n    electricChars: base.electricChars\n  };\n};\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/runmode.js",
    "content": "CodeMirror.runMode = function(string, modespec, callback, options) {\n  var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);\n  var isNode = callback.nodeType == 1;\n  var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;\n  if (isNode) {\n    var node = callback, accum = [], col = 0;\n    callback = function(text, style) {\n      if (text == \"\\n\") {\n        accum.push(\"<br>\");\n        col = 0;\n        return;\n      }\n      var escaped = \"\";\n      // HTML-escape and replace tabs\n      for (var pos = 0;;) {\n        var idx = text.indexOf(\"\\t\", pos);\n        if (idx == -1) {\n          escaped += CodeMirror.htmlEscape(text.slice(pos));\n          col += text.length - pos;\n          break;\n        } else {\n          col += idx - pos;\n          escaped += CodeMirror.htmlEscape(text.slice(pos, idx));\n          var size = tabSize - col % tabSize;\n          col += size;\n          for (var i = 0; i < size; ++i) escaped += \" \";\n          pos = idx + 1;\n        }\n      }\n\n      if (style) \n        accum.push(\"<span class=\\\"cm-\" + CodeMirror.htmlEscape(style) + \"\\\">\" + escaped + \"</span>\");\n      else\n        accum.push(escaped);\n    }\n  }\n  var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);\n  for (var i = 0, e = lines.length; i < e; ++i) {\n    if (i) callback(\"\\n\");\n    var stream = new CodeMirror.StringStream(lines[i]);\n    while (!stream.eol()) {\n      var style = mode.token(stream, state);\n      callback(stream.current(), style, i, stream.start);\n      stream.start = stream.pos;\n    }\n  }\n  if (isNode)\n    node.innerHTML = accum.join(\"\");\n};\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/search.js",
    "content": "// Define search commands. Depends on dialog.js or another\n// implementation of the openDialog method.\n\n// Replace works a little oddly -- it will do the replace on the next\n// Ctrl-G (or whatever is bound to findNext) press. You prevent a\n// replace by making sure the match is no longer selected when hitting\n// Ctrl-G.\n\n(function() {\n  function SearchState() {\n    this.posFrom = this.posTo = this.query = null;\n    this.marked = [];\n  }\n  function getSearchState(cm) {\n    return cm._searchState || (cm._searchState = new SearchState());\n  }\n  function dialog(cm, text, shortText, f) {\n    if (cm.openDialog) cm.openDialog(text, f);\n    else f(prompt(shortText, \"\"));\n  }\n  function confirmDialog(cm, text, shortText, fs) {\n    if (cm.openConfirm) cm.openConfirm(text, fs);\n    else if (confirm(shortText)) fs[0]();\n  }\n  function parseQuery(query) {\n    var isRE = query.match(/^\\/(.*)\\/$/);\n    return isRE ? new RegExp(isRE[1]) : query;\n  }\n  var queryDialog =\n    'Search: <input type=\"text\" style=\"width: 10em\"/> <span style=\"color: #888\">(Use /re/ syntax for regexp search)</span>';\n  function doSearch(cm, rev) {\n    var state = getSearchState(cm);\n    if (state.query) return findNext(cm, rev);\n    dialog(cm, queryDialog, \"Search for:\", function(query) {\n      cm.operation(function() {\n        if (!query || state.query) return;\n        state.query = parseQuery(query);\n        if (cm.lineCount() < 2000) { // This is too expensive on big documents.\n          for (var cursor = cm.getSearchCursor(query); cursor.findNext();)\n            state.marked.push(cm.markText(cursor.from(), cursor.to(), \"CodeMirror-searching\"));\n        }\n        state.posFrom = state.posTo = cm.getCursor();\n        findNext(cm, rev);\n      });\n    });\n  }\n  function findNext(cm, rev) {cm.operation(function() {\n    var state = getSearchState(cm);\n    var cursor = cm.getSearchCursor(state.query, rev ? state.posFrom : state.posTo);\n    if (!cursor.find(rev)) {\n      cursor = cm.getSearchCursor(state.query, rev ? {line: cm.lineCount() - 1} : {line: 0, ch: 0});\n      if (!cursor.find(rev)) return;\n    }\n    cm.setSelection(cursor.from(), cursor.to());\n    state.posFrom = cursor.from(); state.posTo = cursor.to();\n  })}\n  function clearSearch(cm) {cm.operation(function() {\n    var state = getSearchState(cm);\n    if (!state.query) return;\n    state.query = null;\n    for (var i = 0; i < state.marked.length; ++i) state.marked[i].clear();\n    state.marked.length = 0;\n  })}\n\n  var replaceQueryDialog =\n    'Replace: <input type=\"text\" style=\"width: 10em\"/> <span style=\"color: #888\">(Use /re/ syntax for regexp search)</span>';\n  var replacementQueryDialog = 'With: <input type=\"text\" style=\"width: 10em\"/>';\n  var doReplaceConfirm = \"Replace? <button>Yes</button> <button>No</button> <button>Stop</button>\";\n  function replace(cm, all) {\n    dialog(cm, replaceQueryDialog, \"Replace:\", function(query) {\n      if (!query) return;\n      query = parseQuery(query);\n      dialog(cm, replacementQueryDialog, \"Replace with:\", function(text) {\n        if (all) {\n          cm.compoundChange(function() { cm.operation(function() {\n            for (var cursor = cm.getSearchCursor(query); cursor.findNext();) {\n              if (typeof query != \"string\") {\n                var match = cm.getRange(cursor.from(), cursor.to()).match(query);\n                cursor.replace(text.replace(/\\$(\\d)/, function(w, i) {return match[i];}));\n              } else cursor.replace(text);\n            }\n          })});\n        } else {\n          clearSearch(cm);\n          var cursor = cm.getSearchCursor(query, cm.getCursor());\n          function advance() {\n            var start = cursor.from(), match;\n            if (!(match = cursor.findNext())) {\n              cursor = cm.getSearchCursor(query);\n              if (!(match = cursor.findNext()) ||\n                  (cursor.from().line == start.line && cursor.from().ch == start.ch)) return;\n            }\n            cm.setSelection(cursor.from(), cursor.to());\n            confirmDialog(cm, doReplaceConfirm, \"Replace?\",\n                          [function() {doReplace(match);}, advance]);\n          }\n          function doReplace(match) {\n            cursor.replace(typeof query == \"string\" ? text :\n                           text.replace(/\\$(\\d)/, function(w, i) {return match[i];}));\n            advance();\n          }\n          advance();\n        }\n      });\n    });\n  }\n\n  CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};\n  CodeMirror.commands.findNext = doSearch;\n  CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};\n  CodeMirror.commands.clearSearch = clearSearch;\n  CodeMirror.commands.replace = replace;\n  CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};\n})();\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/searchcursor.js",
    "content": "(function(){\n  function SearchCursor(cm, query, pos, caseFold) {\n    this.atOccurrence = false; this.cm = cm;\n    if (caseFold == null && typeof query == \"string\") caseFold = false;\n\n    pos = pos ? cm.clipPos(pos) : {line: 0, ch: 0};\n    this.pos = {from: pos, to: pos};\n\n    // The matches method is filled in based on the type of query.\n    // It takes a position and a direction, and returns an object\n    // describing the next occurrence of the query, or null if no\n    // more matches were found.\n    if (typeof query != \"string\") // Regexp match\n      this.matches = function(reverse, pos) {\n        if (reverse) {\n          var line = cm.getLine(pos.line).slice(0, pos.ch), match = line.match(query), start = 0;\n          while (match) {\n            var ind = line.indexOf(match[0]);\n            start += ind;\n            line = line.slice(ind + 1);\n            var newmatch = line.match(query);\n            if (newmatch) match = newmatch;\n            else break;\n            start++;\n          }\n        }\n        else {\n          var line = cm.getLine(pos.line).slice(pos.ch), match = line.match(query),\n          start = match && pos.ch + line.indexOf(match[0]);\n        }\n        if (match)\n          return {from: {line: pos.line, ch: start},\n                  to: {line: pos.line, ch: start + match[0].length},\n                  match: match};\n      };\n    else { // String query\n      if (caseFold) query = query.toLowerCase();\n      var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;};\n      var target = query.split(\"\\n\");\n      // Different methods for single-line and multi-line queries\n      if (target.length == 1)\n        this.matches = function(reverse, pos) {\n          var line = fold(cm.getLine(pos.line)), len = query.length, match;\n          if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1)\n              : (match = line.indexOf(query, pos.ch)) != -1)\n            return {from: {line: pos.line, ch: match},\n                    to: {line: pos.line, ch: match + len}};\n        };\n      else\n        this.matches = function(reverse, pos) {\n          var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(cm.getLine(ln));\n          var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match));\n          if (reverse ? offsetA >= pos.ch || offsetA != match.length\n              : offsetA <= pos.ch || offsetA != line.length - match.length)\n            return;\n          for (;;) {\n            if (reverse ? !ln : ln == cm.lineCount() - 1) return;\n            line = fold(cm.getLine(ln += reverse ? -1 : 1));\n            match = target[reverse ? --idx : ++idx];\n            if (idx > 0 && idx < target.length - 1) {\n              if (line != match) return;\n              else continue;\n            }\n            var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length);\n            if (reverse ? offsetB != line.length - match.length : offsetB != match.length)\n              return;\n            var start = {line: pos.line, ch: offsetA}, end = {line: ln, ch: offsetB};\n            return {from: reverse ? end : start, to: reverse ? start : end};\n          }\n        };\n    }\n  }\n\n  SearchCursor.prototype = {\n    findNext: function() {return this.find(false);},\n    findPrevious: function() {return this.find(true);},\n\n    find: function(reverse) {\n      var self = this, pos = this.cm.clipPos(reverse ? this.pos.from : this.pos.to);\n      function savePosAndFail(line) {\n        var pos = {line: line, ch: 0};\n        self.pos = {from: pos, to: pos};\n        self.atOccurrence = false;\n        return false;\n      }\n\n      for (;;) {\n        if (this.pos = this.matches(reverse, pos)) {\n          this.atOccurrence = true;\n          return this.pos.match || true;\n        }\n        if (reverse) {\n          if (!pos.line) return savePosAndFail(0);\n          pos = {line: pos.line-1, ch: this.cm.getLine(pos.line-1).length};\n        }\n        else {\n          var maxLine = this.cm.lineCount();\n          if (pos.line == maxLine - 1) return savePosAndFail(maxLine);\n          pos = {line: pos.line+1, ch: 0};\n        }\n      }\n    },\n\n    from: function() {if (this.atOccurrence) return this.pos.from;},\n    to: function() {if (this.atOccurrence) return this.pos.to;},\n\n    replace: function(newText) {\n      var self = this;\n      if (this.atOccurrence)\n        self.pos.to = this.cm.replaceRange(newText, self.pos.from, self.pos.to);\n    }\n  };\n\n  CodeMirror.defineExtension(\"getSearchCursor\", function(query, pos, caseFold) {\n    return new SearchCursor(this, query, pos, caseFold);\n  });\n})();\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/simple-hint.css",
    "content": ".CodeMirror-completions {\n  position: absolute;\n  z-index: 10;\n  overflow: hidden;\n  -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);\n  -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);\n  box-shadow: 2px 3px 5px rgba(0,0,0,.2);\n}\n.CodeMirror-completions select {\n  background: #fafafa;\n  outline: none;\n  border: none;\n  padding: 0;\n  margin: 0;\n  font-family: monospace;\n}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/lib/util/simple-hint.js",
    "content": "(function() {\n  CodeMirror.simpleHint = function(editor, getHints) {\n    // We want a single cursor position.\n    if (editor.somethingSelected()) return;\n    var result = getHints(editor);\n    if (!result || !result.list.length) return;\n    var completions = result.list;\n    function insert(str) {\n      editor.replaceRange(str, result.from, result.to);\n    }\n    // When there is only one completion, use it directly.\n    if (completions.length == 1) {insert(completions[0]); return true;}\n\n    // Build the select widget\n    var complete = document.createElement(\"div\");\n    complete.className = \"CodeMirror-completions\";\n    var sel = complete.appendChild(document.createElement(\"select\"));\n    // Opera doesn't move the selection when pressing up/down in a\n    // multi-select, but it does properly support the size property on\n    // single-selects, so no multi-select is necessary.\n    if (!window.opera) sel.multiple = true;\n    for (var i = 0; i < completions.length; ++i) {\n      var opt = sel.appendChild(document.createElement(\"option\"));\n      opt.appendChild(document.createTextNode(completions[i]));\n    }\n    sel.firstChild.selected = true;\n    sel.size = Math.min(10, completions.length);\n    var pos = editor.cursorCoords();\n    complete.style.left = pos.x + \"px\";\n    complete.style.top = pos.yBot + \"px\";\n    document.body.appendChild(complete);\n    // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.\n    var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);\n    if(winW - pos.x < sel.clientWidth)\n      complete.style.left = (pos.x - sel.clientWidth) + \"px\";\n    // Hack to hide the scrollbar.\n    if (completions.length <= 10)\n      complete.style.width = (sel.clientWidth - 1) + \"px\";\n\n    var done = false;\n    function close() {\n      if (done) return;\n      done = true;\n      complete.parentNode.removeChild(complete);\n    }\n    function pick() {\n      insert(completions[sel.selectedIndex]);\n      close();\n      setTimeout(function(){editor.focus();}, 50);\n    }\n    CodeMirror.connect(sel, \"blur\", close);\n    CodeMirror.connect(sel, \"keydown\", function(event) {\n      var code = event.keyCode;\n      // Enter\n      if (code == 13) {CodeMirror.e_stop(event); pick();}\n      // Escape\n      else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();}\n      else if (code != 38 && code != 40) {\n        close(); editor.focus();\n        // Pass the event to the CodeMirror instance so that it can handle things like backspace properly.\n        editor.triggerOnKeyDown(event);\n        setTimeout(function(){CodeMirror.simpleHint(editor, getHints);}, 50);\n      }\n    });\n    CodeMirror.connect(sel, \"dblclick\", pick);\n\n    sel.focus();\n    // Opera sometimes ignores focusing a freshly created node\n    if (window.opera) setTimeout(function(){if (!done) sel.focus();}, 100);\n    return true;\n  };\n})();\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/clike/clike.js",
    "content": "CodeMirror.defineMode(\"clike\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit,\n      keywords = parserConfig.keywords || {},\n      blockKeywords = parserConfig.blockKeywords || {},\n      atoms = parserConfig.atoms || {},\n      hooks = parserConfig.hooks || {},\n      multiLineStrings = parserConfig.multiLineStrings;\n  var isOperatorChar = /[+\\-*&%=<>!?|\\/]/;\n\n  var curPunc;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (hooks[ch]) {\n      var result = hooks[ch](stream, state);\n      if (result !== false) return result;\n    }\n    if (ch == '\"' || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      return \"number\";\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize = tokenComment;\n        return tokenComment(stream, state);\n      }\n      if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n    }\n    if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_]/);\n    var cur = stream.current();\n    if (keywords.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"keyword\";\n    }\n    if (atoms.propertyIsEnumerable(cur)) return \"atom\";\n    return \"word\";\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next, end = false;\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) {end = true; break;}\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end || !(escaped || multiLineStrings))\n        state.tokenize = null;\n      return \"string\";\n    };\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = null;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function Context(indented, column, type, align, prev) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.align = align;\n    this.prev = prev;\n  }\n  function pushContext(state, col, type) {\n    return state.context = new Context(state.indented, col, type, null, state.context);\n  }\n  function popContext(state) {\n    var t = state.context.type;\n    if (t == \")\" || t == \"]\" || t == \"}\")\n      state.indented = state.context.indented;\n    return state.context = state.context.prev;\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: null,\n        context: new Context((basecolumn || 0) - indentUnit, 0, \"top\", false),\n        indented: 0,\n        startOfLine: true\n      };\n    },\n\n    token: function(stream, state) {\n      var ctx = state.context;\n      if (stream.sol()) {\n        if (ctx.align == null) ctx.align = false;\n        state.indented = stream.indentation();\n        state.startOfLine = true;\n      }\n      if (stream.eatSpace()) return null;\n      curPunc = null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style == \"comment\" || style == \"meta\") return style;\n      if (ctx.align == null) ctx.align = true;\n\n      if ((curPunc == \";\" || curPunc == \":\") && ctx.type == \"statement\") popContext(state);\n      else if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n      else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n      else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n      else if (curPunc == \"}\") {\n        while (ctx.type == \"statement\") ctx = popContext(state);\n        if (ctx.type == \"}\") ctx = popContext(state);\n        while (ctx.type == \"statement\") ctx = popContext(state);\n      }\n      else if (curPunc == ctx.type) popContext(state);\n      else if (ctx.type == \"}\" || ctx.type == \"top\" || (ctx.type == \"statement\" && curPunc == \"newstatement\"))\n        pushContext(state, stream.column(), \"statement\");\n      state.startOfLine = false;\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase && state.tokenize != null) return 0;\n      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);\n      if (ctx.type == \"statement\" && firstChar == \"}\") ctx = ctx.prev;\n      var closing = firstChar == ctx.type;\n      if (ctx.type == \"statement\") return ctx.indented + (firstChar == \"{\" ? 0 : indentUnit);\n      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \"{}\"\n  };\n});\n\n(function() {\n  function words(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n  var cKeywords = \"auto if break int case long char register continue return default short do sizeof \" +\n    \"double static else struct entry switch extern typedef float union for unsigned \" +\n    \"goto while enum void const signed volatile\";\n\n  function cppHook(stream, state) {\n    if (!state.startOfLine) return false;\n    stream.skipToEnd();\n    return \"meta\";\n  }\n\n  // C#-style strings where \"\" escapes a quote.\n  function tokenAtString(stream, state) {\n    var next;\n    while ((next = stream.next()) != null) {\n      if (next == '\"' && !stream.eat('\"')) {\n        state.tokenize = null;\n        break;\n      }\n    }\n    return \"string\";\n  }\n\n  CodeMirror.defineMIME(\"text/x-csrc\", {\n    name: \"clike\",\n    keywords: words(cKeywords),\n    blockKeywords: words(\"case do else for if switch while struct\"),\n    atoms: words(\"null\"),\n    hooks: {\"#\": cppHook}\n  });\n  CodeMirror.defineMIME(\"text/x-c++src\", {\n    name: \"clike\",\n    keywords: words(cKeywords + \" asm dynamic_cast namespace reinterpret_cast try bool explicit new \" +\n                    \"static_cast typeid catch operator template typename class friend private \" +\n                    \"this using const_cast inline public throw virtual delete mutable protected \" +\n                    \"wchar_t\"),\n    blockKeywords: words(\"catch class do else finally for if struct switch try while\"),\n    atoms: words(\"true false null\"),\n    hooks: {\"#\": cppHook}\n  });\n  CodeMirror.defineMIME(\"text/x-java\", {\n    name: \"clike\",\n    keywords: words(\"abstract assert boolean break byte case catch char class const continue default \" + \n                    \"do double else enum extends final finally float for goto if implements import \" +\n                    \"instanceof int interface long native new package private protected public \" +\n                    \"return short static strictfp super switch synchronized this throw throws transient \" +\n                    \"try void volatile while\"),\n    blockKeywords: words(\"catch class do else finally for if switch try while\"),\n    atoms: words(\"true false null\"),\n    hooks: {\n      \"@\": function(stream, state) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    }\n  });\n  CodeMirror.defineMIME(\"text/x-csharp\", {\n    name: \"clike\",\n    keywords: words(\"abstract as base bool break byte case catch char checked class const continue decimal\" + \n                    \" default delegate do double else enum event explicit extern finally fixed float for\" + \n                    \" foreach goto if implicit in int interface internal is lock long namespace new object\" + \n                    \" operator out override params private protected public readonly ref return sbyte sealed short\" + \n                    \" sizeof stackalloc static string struct switch this throw try typeof uint ulong unchecked\" + \n                    \" unsafe ushort using virtual void volatile while add alias ascending descending dynamic from get\" + \n                    \" global group into join let orderby partial remove select set value var yield\"),\n    blockKeywords: words(\"catch class do else finally for foreach if struct switch try while\"),\n    atoms: words(\"true false null\"),\n    hooks: {\n      \"@\": function(stream, state) {\n        if (stream.eat('\"')) {\n          state.tokenize = tokenAtString;\n          return tokenAtString(stream, state);\n        }\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"meta\";\n      }\n    }\n  });\n}());\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/clike/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: C-like mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"clike.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style>.CodeMirror {border: 2px inset #dee;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: C-like mode</h1>\n\n<form><textarea id=\"code\" name=\"code\">\n/* C demo code */\n\n#include <zmq.h>\n#include <pthread.h>\n#include <semaphore.h>\n#include <time.h>\n#include <stdio.h>\n#include <fcntl.h>\n#include <malloc.h>\n\ntypedef struct {\n  void* arg_socket;\n  zmq_msg_t* arg_msg;\n  char* arg_string;\n  unsigned long arg_len;\n  int arg_int, arg_command;\n\n  int signal_fd;\n  int pad;\n  void* context;\n  sem_t sem;\n} acl_zmq_context;\n\n#define p(X) (context->arg_##X)\n\nvoid* zmq_thread(void* context_pointer) {\n  acl_zmq_context* context = (acl_zmq_context*)context_pointer;\n  char ok = 'K', err = 'X';\n  int res;\n\n  while (1) {\n    while ((res = sem_wait(&amp;context->sem)) == EINTR);\n    if (res) {write(context->signal_fd, &amp;err, 1); goto cleanup;}\n    switch(p(command)) {\n    case 0: goto cleanup;\n    case 1: p(socket) = zmq_socket(context->context, p(int)); break;\n    case 2: p(int) = zmq_close(p(socket)); break;\n    case 3: p(int) = zmq_bind(p(socket), p(string)); break;\n    case 4: p(int) = zmq_connect(p(socket), p(string)); break;\n    case 5: p(int) = zmq_getsockopt(p(socket), p(int), (void*)p(string), &amp;p(len)); break;\n    case 6: p(int) = zmq_setsockopt(p(socket), p(int), (void*)p(string), p(len)); break;\n    case 7: p(int) = zmq_send(p(socket), p(msg), p(int)); break;\n    case 8: p(int) = zmq_recv(p(socket), p(msg), p(int)); break;\n    case 9: p(int) = zmq_poll(p(socket), p(int), p(len)); break;\n    }\n    p(command) = errno;\n    write(context->signal_fd, &amp;ok, 1);\n  }\n cleanup:\n  close(context->signal_fd);\n  free(context_pointer);\n  return 0;\n}\n\nvoid* zmq_thread_init(void* zmq_context, int signal_fd) {\n  acl_zmq_context* context = malloc(sizeof(acl_zmq_context));\n  pthread_t thread;\n\n  context->context = zmq_context;\n  context->signal_fd = signal_fd;\n  sem_init(&amp;context->sem, 1, 0);\n  pthread_create(&amp;thread, 0, &amp;zmq_thread, context);\n  pthread_detach(thread);\n  return context;\n}\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-csrc\"\n      });\n    </script>\n\n    <p>Simple mode that tries to handle C-like languages as well as it\n    can. Takes two configuration parameters: <code>keywords</code>, an\n    object whose property names are the keywords in the language,\n    and <code>useCPP</code>, which determines whether C preprocessor\n    directives are recognized.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-csrc</code>\n    (C code), <code>text/x-c++src</code> (C++\n    code), <code>text/x-java</code> (Java\n    code), <code>text/x-csharp</code> (C#).</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/clojure/clojure.js",
    "content": "/**\n * Author: Hans Engel\n * Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun)\n */\nCodeMirror.defineMode(\"clojure\", function (config, mode) {\n    var BUILTIN = \"builtin\", COMMENT = \"comment\", STRING = \"string\", TAG = \"tag\",\n        ATOM = \"atom\", NUMBER = \"number\", BRACKET = \"bracket\", KEYWORD = \"keyword\";\n    var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;\n\n    function makeKeywords(str) {\n        var obj = {}, words = str.split(\" \");\n        for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n        return obj;\n    }\n\n    var atoms = makeKeywords(\"true false nil\");\n    \n    var keywords = makeKeywords(\n      \"defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle\");\n\n    var builtins = makeKeywords(\n        \"* *1 *2 *3 *agent* *allow-unresolved-vars* *assert *clojure-version* *command-line-args* *compile-files* *compile-path* *e *err* *file* *flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *use-context-classloader* *warn-on-reflection* + - / < <= = == > >= accessor aclone agent agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec decimal? declare definline defmacro defmethod defmulti defn defn- defonce defstruct delay delay? deliver deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall doc dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq eval even? every? extend extend-protocol extend-type extends? extenders false? ffirst file-seq filter find find-doc find-ns find-var first float float-array float? floats flush fn fn? fnext for force format future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator hash hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map? mapcat max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod name namespace neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? or parents partial partition pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-doc print-dup print-method print-namespace-doc print-simple print-special-doc print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string reify reduce ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure release-pending-sends rem remove remove-method remove-ns repeat repeatedly replace replicate require reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-validator! set? short short-array shorts shutdown-agents slurp some sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-form-anchor special-symbol? split-at split-with str stream? string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync syntax-symbol-anchor take take-last take-nth take-while test the-ns time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-dec unchecked-divide unchecked-inc unchecked-multiply unchecked-negate unchecked-remainder unchecked-subtract underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision xml-seq\");\n\n    var indentKeys = makeKeywords(\n        // Built-ins\n        \"ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type try catch \" +\n\n        // Binding forms\n        \"let letfn binding loop for doseq dotimes when-let if-let \" +\n\n        // Data structures\n        \"defstruct struct-map assoc \" +\n\n        // clojure.test\n        \"testing deftest \" +\n\n        // contrib\n        \"handler-case handle dotrace deftrace\");\n\n    var tests = {\n        digit: /\\d/,\n        digit_or_colon: /[\\d:]/,\n        hex: /[0-9a-fA-F]/,\n        sign: /[+-]/,\n        exponent: /[eE]/,\n        keyword_char: /[^\\s\\(\\[\\;\\)\\]]/,\n        basic: /[\\w\\$_\\-]/,\n        lang_keyword: /[\\w*+!\\-_?:\\/]/\n    };\n\n    function stateStack(indent, type, prev) { // represents a state stack object\n        this.indent = indent;\n        this.type = type;\n        this.prev = prev;\n    }\n\n    function pushStack(state, indent, type) {\n        state.indentStack = new stateStack(indent, type, state.indentStack);\n    }\n\n    function popStack(state) {\n        state.indentStack = state.indentStack.prev;\n    }\n\n    function isNumber(ch, stream){\n        // hex\n        if ( ch === '0' && 'x' == stream.peek().toLowerCase() ) {\n            stream.eat('x');\n            stream.eatWhile(tests.hex);\n            return true;\n        }\n\n        // leading sign\n        if ( ch == '+' || ch == '-' ) {\n          stream.eat(tests.sign);\n          ch = stream.next();\n        }\n\n        if ( tests.digit.test(ch) ) {\n            stream.eat(ch);\n            stream.eatWhile(tests.digit);\n\n            if ( '.' == stream.peek() ) {\n                stream.eat('.');\n                stream.eatWhile(tests.digit);\n            }\n\n            if ( 'e' == stream.peek().toLowerCase() ) {\n                stream.eat(tests.exponent);\n                stream.eat(tests.sign);\n                stream.eatWhile(tests.digit);\n            }\n\n            return true;\n        }\n\n        return false;\n    }\n\n    return {\n        startState: function () {\n            return {\n                indentStack: null,\n                indentation: 0,\n                mode: false\n            };\n        },\n\n        token: function (stream, state) {\n            if (state.indentStack == null && stream.sol()) {\n                // update indentation, but only if indentStack is empty\n                state.indentation = stream.indentation();\n            }\n\n            // skip spaces\n            if (stream.eatSpace()) {\n                return null;\n            }\n            var returnType = null;\n\n            switch(state.mode){\n                case \"string\": // multi-line string parsing mode\n                    var next, escaped = false;\n                    while ((next = stream.next()) != null) {\n                        if (next == \"\\\"\" && !escaped) {\n\n                            state.mode = false;\n                            break;\n                        }\n                        escaped = !escaped && next == \"\\\\\";\n                    }\n                    returnType = STRING; // continue on in string mode\n                    break;\n                default: // default parsing mode\n                    var ch = stream.next();\n\n                    if (ch == \"\\\"\") {\n                        state.mode = \"string\";\n                        returnType = STRING;\n                    } else if (ch == \"'\" && !( tests.digit_or_colon.test(stream.peek()) )) {\n                        returnType = ATOM;\n                    } else if (ch == \";\") { // comment\n                        stream.skipToEnd(); // rest of the line is a comment\n                        returnType = COMMENT;\n                    } else if (isNumber(ch,stream)){\n                        returnType = NUMBER;\n                    } else if (ch == \"(\" || ch == \"[\") {\n                        var keyWord = ''; var indentTemp = stream.column();\n                        /**\n                        Either\n                        (indent-word ..\n                        (non-indent-word ..\n                        (;something else, bracket, etc.\n                        */\n\n                        if (ch == \"(\") while ((letter = stream.eat(tests.keyword_char)) != null) {\n                            keyWord += letter;\n                        }\n\n                        if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word\n                            pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);\n                        } else { // non-indent word\n                            // we continue eating the spaces\n                            stream.eatSpace();\n                            if (stream.eol() || stream.peek() == \";\") {\n                                // nothing significant after\n                                // we restart indentation 1 space after\n                                pushStack(state, indentTemp + 1, ch);\n                            } else {\n                                pushStack(state, indentTemp + stream.current().length, ch); // else we match\n                            }\n                        }\n                        stream.backUp(stream.current().length - 1); // undo all the eating\n\n                        returnType = BRACKET;\n                    } else if (ch == \")\" || ch == \"]\") {\n                        returnType = BRACKET;\n                        if (state.indentStack != null && state.indentStack.type == (ch == \")\" ? \"(\" : \"[\")) {\n                            popStack(state);\n                        }\n                    } else if ( ch == \":\" ) {\n                        stream.eatWhile(tests.lang_keyword);\n                        return ATOM;\n                    } else {\n                        stream.eatWhile(tests.basic);\n\n                        if (keywords && keywords.propertyIsEnumerable(stream.current())) {\n                            returnType = KEYWORD;\n                        } else if (builtins && builtins.propertyIsEnumerable(stream.current())) {\n                            returnType = BUILTIN;\n                        } else if (atoms && atoms.propertyIsEnumerable(stream.current())) {\n                            returnType = ATOM;\n                        } else returnType = null;\n                    }\n            }\n\n            return returnType;\n        },\n\n        indent: function (state, textAfter) {\n            if (state.indentStack == null) return state.indentation;\n            return state.indentStack.indent;\n        }\n    };\n});\n\nCodeMirror.defineMIME(\"text/x-clojure\", \"clojure\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/clojure/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Clojure mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"clojure.js\"></script>\n    <style>.CodeMirror {background: #f8f8f8;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Clojure mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n; Conway's Game of Life, based on the work of:\n;; Laurent Petit https://gist.github.com/1200343\n;; Christophe Grand http://clj-me.cgrand.net/2011/08/19/conways-game-of-life\n\n(ns ^{:doc \"Conway's Game of Life.\"}\n game-of-life)\n\n;; Core game of life's algorithm functions\n\n(defn neighbours \n  \"Given a cell's coordinates, returns the coordinates of its neighbours.\"\n  [[x y]]\n  (for [dx [-1 0 1] dy (if (zero? dx) [-1 1] [-1 0 1])]\n    [(+ dx x) (+ dy y)]))\n\n(defn step \n  \"Given a set of living cells, computes the new set of living cells.\"\n  [cells]\n  (set (for [[cell n] (frequencies (mapcat neighbours cells))\n             :when (or (= n 3) (and (= n 2) (cells cell)))]\n         cell)))\n\n;; Utility methods for displaying game on a text terminal\n\n(defn print-board \n  \"Prints a board on *out*, representing a step in the game.\"\n  [board w h]\n  (doseq [x (range (inc w)) y (range (inc h))]\n    (if (= y 0) (print \"\\n\")) \n    (print (if (board [x y]) \"[X]\" \" . \"))))\n\n(defn display-grids \n  \"Prints a squence of boards on *out*, representing several steps.\"\n  [grids w h]\n  (doseq [board grids]\n    (print-board board w h)\n    (print \"\\n\")))\n\n;; Launches an example board\n\n(def \n  ^{:doc \"board represents the initial set of living cells\"}\n   board #{[2 1] [2 2] [2 3]})\n\n(display-grids (take 3 (iterate step board)) 5 5) </textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-clojure</code>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/coffeescript/LICENSE",
    "content": "The MIT License\n\nCopyright (c) 2011 Jeff Pickhardt\nModified from the Python CodeMirror mode, Copyright (c) 2010 Timothy Farrell\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/coffeescript/coffeescript.js",
    "content": "/**\n * Link to the project's GitHub page:\n * https://github.com/pickhardt/coffeescript-codemirror-mode\n */\nCodeMirror.defineMode('coffeescript', function(conf) {\n    var ERRORCLASS = 'error';\n\n    function wordRegexp(words) {\n        return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\");\n    }\n\n    var singleOperators = new RegExp(\"^[\\\\+\\\\-\\\\*/%&|\\\\^~<>!\\?]\");\n    var singleDelimiters = new RegExp('^[\\\\(\\\\)\\\\[\\\\]\\\\{\\\\}@,:`=;\\\\.]');\n    var doubleOperators = new RegExp(\"^((\\->)|(\\=>)|(\\\\+\\\\+)|(\\\\+\\\\=)|(\\\\-\\\\-)|(\\\\-\\\\=)|(\\\\*\\\\*)|(\\\\*\\\\=)|(\\\\/\\\\/)|(\\\\/\\\\=)|(==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//))\");\n    var doubleDelimiters = new RegExp(\"^((\\\\.\\\\.)|(\\\\+=)|(\\\\-=)|(\\\\*=)|(%=)|(/=)|(&=)|(\\\\|=)|(\\\\^=))\");\n    var tripleDelimiters = new RegExp(\"^((\\\\.\\\\.\\\\.)|(//=)|(>>=)|(<<=)|(\\\\*\\\\*=))\");\n    var identifiers = new RegExp(\"^[_A-Za-z$][_A-Za-z$0-9]*\");\n\n    var wordOperators = wordRegexp(['and', 'or', 'not',\n                                    'is', 'isnt', 'in',\n                                    'instanceof', 'typeof']);\n    var indentKeywords = ['for', 'while', 'loop', 'if', 'unless', 'else',\n                          'switch', 'try', 'catch', 'finally', 'class'];\n    var commonKeywords = ['break', 'by', 'continue', 'debugger', 'delete',\n                          'do', 'in', 'of', 'new', 'return', 'then',\n                          'this', 'throw', 'when', 'until'];\n\n    var keywords = wordRegexp(indentKeywords.concat(commonKeywords));\n\n    indentKeywords = wordRegexp(indentKeywords);\n\n\n    var stringPrefixes = new RegExp(\"^('{3}|\\\"{3}|['\\\"])\");\n    var regexPrefixes = new RegExp(\"^(/{3}|/)\");\n    var commonConstants = ['Infinity', 'NaN', 'undefined', 'null', 'true', 'false', 'on', 'off', 'yes', 'no'];\n    var constants = wordRegexp(commonConstants);\n\n    // Tokenizers\n    function tokenBase(stream, state) {\n        // Handle scope changes\n        if (stream.sol()) {\n            var scopeOffset = state.scopes[0].offset;\n            if (stream.eatSpace()) {\n                var lineOffset = stream.indentation();\n                if (lineOffset > scopeOffset) {\n                    return 'indent';\n                } else if (lineOffset < scopeOffset) {\n                    return 'dedent';\n                }\n                return null;\n            } else {\n                if (scopeOffset > 0) {\n                    dedent(stream, state);\n                }\n            }\n        }\n        if (stream.eatSpace()) {\n            return null;\n        }\n\n        var ch = stream.peek();\n\n        // Handle docco title comment (single line)\n        if (stream.match(\"####\")) {\n            stream.skipToEnd();\n            return 'comment';\n        }\n\n        // Handle multi line comments\n        if (stream.match(\"###\")) {\n            state.tokenize = longComment;\n            return state.tokenize(stream, state);\n        }\n\n        // Single line comment\n        if (ch === '#') {\n            stream.skipToEnd();\n            return 'comment';\n        }\n\n        // Handle number literals\n        if (stream.match(/^-?[0-9\\.]/, false)) {\n            var floatLiteral = false;\n            // Floats\n            if (stream.match(/^-?\\d*\\.\\d+(e[\\+\\-]?\\d+)?/i)) {\n              floatLiteral = true;\n            }\n            if (stream.match(/^-?\\d+\\.\\d*/)) {\n              floatLiteral = true;\n            }\n            if (stream.match(/^-?\\.\\d+/)) {\n              floatLiteral = true;\n            }\n\n            if (floatLiteral) {\n                // prevent from getting extra . on 1..\n                if (stream.peek() == \".\"){\n                    stream.backUp(1);\n                }\n                return 'number';\n            }\n            // Integers\n            var intLiteral = false;\n            // Hex\n            if (stream.match(/^-?0x[0-9a-f]+/i)) {\n              intLiteral = true;\n            }\n            // Decimal\n            if (stream.match(/^-?[1-9]\\d*(e[\\+\\-]?\\d+)?/)) {\n                intLiteral = true;\n            }\n            // Zero by itself with no other piece of number.\n            if (stream.match(/^-?0(?![\\dx])/i)) {\n              intLiteral = true;\n            }\n            if (intLiteral) {\n                return 'number';\n            }\n        }\n\n        // Handle strings\n        if (stream.match(stringPrefixes)) {\n            state.tokenize = tokenFactory(stream.current(), 'string');\n            return state.tokenize(stream, state);\n        }\n        // Handle regex literals\n        if (stream.match(regexPrefixes)) {\n            if (stream.current() != '/' || stream.match(/^.*\\//, false)) { // prevent highlight of division\n                state.tokenize = tokenFactory(stream.current(), 'string-2');\n                return state.tokenize(stream, state);\n            } else {\n                stream.backUp(1);\n            }\n        }\n\n        // Handle operators and delimiters\n        if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {\n            return 'punctuation';\n        }\n        if (stream.match(doubleOperators)\n            || stream.match(singleOperators)\n            || stream.match(wordOperators)) {\n            return 'operator';\n        }\n        if (stream.match(singleDelimiters)) {\n            return 'punctuation';\n        }\n\n        if (stream.match(constants)) {\n            return 'atom';\n        }\n\n        if (stream.match(keywords)) {\n            return 'keyword';\n        }\n\n        if (stream.match(identifiers)) {\n            return 'variable';\n        }\n\n        // Handle non-detected items\n        stream.next();\n        return ERRORCLASS;\n    }\n\n    function tokenFactory(delimiter, outclass) {\n        var singleline = delimiter.length == 1;\n        return function tokenString(stream, state) {\n            while (!stream.eol()) {\n                stream.eatWhile(/[^'\"\\/\\\\]/);\n                if (stream.eat('\\\\')) {\n                    stream.next();\n                    if (singleline && stream.eol()) {\n                        return outclass;\n                    }\n                } else if (stream.match(delimiter)) {\n                    state.tokenize = tokenBase;\n                    return outclass;\n                } else {\n                    stream.eat(/['\"\\/]/);\n                }\n            }\n            if (singleline) {\n                if (conf.mode.singleLineStringErrors) {\n                    outclass = ERRORCLASS\n                } else {\n                    state.tokenize = tokenBase;\n                }\n            }\n            return outclass;\n        };\n    }\n\n    function longComment(stream, state) {\n        while (!stream.eol()) {\n            stream.eatWhile(/[^#]/);\n            if (stream.match(\"###\")) {\n                state.tokenize = tokenBase;\n                break;\n            }\n            stream.eatWhile(\"#\");\n        }\n        return \"comment\"\n    }\n\n    function indent(stream, state, type) {\n        type = type || 'coffee';\n        var indentUnit = 0;\n        if (type === 'coffee') {\n            for (var i = 0; i < state.scopes.length; i++) {\n                if (state.scopes[i].type === 'coffee') {\n                    indentUnit = state.scopes[i].offset + conf.indentUnit;\n                    break;\n                }\n            }\n        } else {\n            indentUnit = stream.column() + stream.current().length;\n        }\n        state.scopes.unshift({\n            offset: indentUnit,\n            type: type\n        });\n    }\n\n    function dedent(stream, state) {\n        if (state.scopes.length == 1) return;\n        if (state.scopes[0].type === 'coffee') {\n            var _indent = stream.indentation();\n            var _indent_index = -1;\n            for (var i = 0; i < state.scopes.length; ++i) {\n                if (_indent === state.scopes[i].offset) {\n                    _indent_index = i;\n                    break;\n                }\n            }\n            if (_indent_index === -1) {\n                return true;\n            }\n            while (state.scopes[0].offset !== _indent) {\n                state.scopes.shift();\n            }\n            return false\n        } else {\n            state.scopes.shift();\n            return false;\n        }\n    }\n\n    function tokenLexer(stream, state) {\n        var style = state.tokenize(stream, state);\n        var current = stream.current();\n\n        // Handle '.' connected identifiers\n        if (current === '.') {\n            style = state.tokenize(stream, state);\n            current = stream.current();\n            if (style === 'variable') {\n                return 'variable';\n            } else {\n                return ERRORCLASS;\n            }\n        }\n\n        // Handle properties\n        if (current === '@') {\n            stream.eat('@');\n            return 'keyword';\n        }\n\n        // Handle scope changes.\n        if (current === 'return') {\n            state.dedent += 1;\n        }\n        if (((current === '->' || current === '=>') &&\n                  !state.lambda &&\n                  state.scopes[0].type == 'coffee' &&\n                  stream.peek() === '')\n               || style === 'indent') {\n            indent(stream, state);\n        }\n        var delimiter_index = '[({'.indexOf(current);\n        if (delimiter_index !== -1) {\n            indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));\n        }\n        if (indentKeywords.exec(current)){\n            indent(stream, state);\n        }\n        if (current == 'then'){\n            dedent(stream, state);\n        }\n\n\n        if (style === 'dedent') {\n            if (dedent(stream, state)) {\n                return ERRORCLASS;\n            }\n        }\n        delimiter_index = '])}'.indexOf(current);\n        if (delimiter_index !== -1) {\n            if (dedent(stream, state)) {\n                return ERRORCLASS;\n            }\n        }\n        if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'coffee') {\n            if (state.scopes.length > 1) state.scopes.shift();\n            state.dedent -= 1;\n        }\n\n        return style;\n    }\n\n    var external = {\n        startState: function(basecolumn) {\n            return {\n              tokenize: tokenBase,\n              scopes: [{offset:basecolumn || 0, type:'coffee'}],\n              lastToken: null,\n              lambda: false,\n              dedent: 0\n          };\n        },\n\n        token: function(stream, state) {\n            var style = tokenLexer(stream, state);\n\n            state.lastToken = {style:style, content: stream.current()};\n\n            if (stream.eol() && stream.lambda) {\n                state.lambda = false;\n            }\n\n            return style;\n        },\n\n        indent: function(state, textAfter) {\n            if (state.tokenize != tokenBase) {\n                return 0;\n            }\n\n            return state.scopes[0].offset;\n        }\n\n    };\n    return external;\n});\n\nCodeMirror.defineMIME('text/x-coffeescript', 'coffeescript');\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/coffeescript/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: CoffeeScript mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"coffeescript.js\"></script>\n    <style>.CodeMirror {border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: CoffeeScript mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n# CoffeeScript mode for CodeMirror\n# Copyright (c) 2011 Jeff Pickhardt, released under\n# the MIT License.\n#\n# Modified from the Python CodeMirror mode, which also is \n# under the MIT License Copyright (c) 2010 Timothy Farrell.\n#\n# The following script, Underscore.coffee, is used to \n# demonstrate CoffeeScript mode for CodeMirror.\n#\n# To download CoffeeScript mode for CodeMirror, go to:\n# https://github.com/pickhardt/coffeescript-codemirror-mode\n\n# **Underscore.coffee\n# (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.**\n# Underscore is freely distributable under the terms of the\n# [MIT license](http://en.wikipedia.org/wiki/MIT_License).\n# Portions of Underscore are inspired by or borrowed from\n# [Prototype.js](http://prototypejs.org/api), Oliver Steele's\n# [Functional](http://osteele.com), and John Resig's\n# [Micro-Templating](http://ejohn.org).\n# For all details and documentation:\n# http://documentcloud.github.com/underscore/\n\n\n# Baseline setup\n# --------------\n\n# Establish the root object, `window` in the browser, or `global` on the server.\nroot = this\n\n\n# Save the previous value of the `_` variable.\npreviousUnderscore = root._\n\n### Multiline\n    comment\n###\n\n# Establish the object that gets thrown to break out of a loop iteration.\n# `StopIteration` is SOP on Mozilla.\nbreaker = if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration\n\n\n#### Docco style single line comment (title)\n\n\n# Helper function to escape **RegExp** contents, because JS doesn't have one.\nescapeRegExp = (string) -> string.replace(/([.*+?^${}()|[\\]\\/\\\\])/g, '\\\\$1')\n\n\n# Save bytes in the minified (but not gzipped) version:\nArrayProto = Array.prototype\nObjProto = Object.prototype\n\n\n# Create quick reference variables for speed access to core prototypes.\nslice = ArrayProto.slice\nunshift = ArrayProto.unshift\ntoString = ObjProto.toString\nhasOwnProperty = ObjProto.hasOwnProperty\npropertyIsEnumerable = ObjProto.propertyIsEnumerable\n\n\n# All **ECMA5** native implementations we hope to use are declared here.\nnativeForEach = ArrayProto.forEach\nnativeMap = ArrayProto.map\nnativeReduce = ArrayProto.reduce\nnativeReduceRight = ArrayProto.reduceRight\nnativeFilter = ArrayProto.filter\nnativeEvery = ArrayProto.every\nnativeSome = ArrayProto.some\nnativeIndexOf = ArrayProto.indexOf\nnativeLastIndexOf = ArrayProto.lastIndexOf\nnativeIsArray = Array.isArray\nnativeKeys = Object.keys\n\n\n# Create a safe reference to the Underscore object for use below.\n_ = (obj) -> new wrapper(obj)\n\n\n# Export the Underscore object for **CommonJS**.\nif typeof(exports) != 'undefined' then exports._ = _\n\n\n# Export Underscore to global scope.\nroot._ = _\n\n\n# Current version.\n_.VERSION = '1.1.0'\n\n\n# Collection Functions\n# --------------------\n\n# The cornerstone, an **each** implementation.\n# Handles objects implementing **forEach**, arrays, and raw objects.\n_.each = (obj, iterator, context) ->\n  try\n    if nativeForEach and obj.forEach is nativeForEach\n      obj.forEach iterator, context\n    else if _.isNumber obj.length\n      iterator.call context, obj[i], i, obj for i in [0...obj.length]\n    else\n      iterator.call context, val, key, obj for own key, val of obj\n  catch e\n    throw e if e isnt breaker\n  obj\n\n\n# Return the results of applying the iterator to each element. Use JavaScript\n# 1.6's version of **map**, if possible.\n_.map = (obj, iterator, context) ->\n  return obj.map(iterator, context) if nativeMap and obj.map is nativeMap\n  results = []\n  _.each obj, (value, index, list) ->\n    results.push iterator.call context, value, index, list\n  results\n\n\n# **Reduce** builds up a single result from a list of values. Also known as\n# **inject**, or **foldl**. Uses JavaScript 1.8's version of **reduce**, if possible.\n_.reduce = (obj, iterator, memo, context) ->\n  if nativeReduce and obj.reduce is nativeReduce\n    iterator = _.bind iterator, context if context\n    return obj.reduce iterator, memo\n  _.each obj, (value, index, list) ->\n    memo = iterator.call context, memo, value, index, list\n  memo\n\n\n# The right-associative version of **reduce**, also known as **foldr**. Uses\n# JavaScript 1.8's version of **reduceRight**, if available.\n_.reduceRight = (obj, iterator, memo, context) ->\n  if nativeReduceRight and obj.reduceRight is nativeReduceRight\n    iterator = _.bind iterator, context if context\n    return obj.reduceRight iterator, memo\n  reversed = _.clone(_.toArray(obj)).reverse()\n  _.reduce reversed, iterator, memo, context\n\n\n# Return the first value which passes a truth test.\n_.detect = (obj, iterator, context) ->\n  result = null\n  _.each obj, (value, index, list) ->\n    if iterator.call context, value, index, list\n      result = value\n      _.breakLoop()\n  result\n\n\n# Return all the elements that pass a truth test. Use JavaScript 1.6's\n# **filter**, if it exists.\n_.filter = (obj, iterator, context) ->\n  return obj.filter iterator, context if nativeFilter and obj.filter is nativeFilter\n  results = []\n  _.each obj, (value, index, list) ->\n    results.push value if iterator.call context, value, index, list\n  results\n\n\n# Return all the elements for which a truth test fails.\n_.reject = (obj, iterator, context) ->\n  results = []\n  _.each obj, (value, index, list) ->\n    results.push value if not iterator.call context, value, index, list\n  results\n\n\n# Determine whether all of the elements match a truth test. Delegate to\n# JavaScript 1.6's **every**, if it is present.\n_.every = (obj, iterator, context) ->\n  iterator ||= _.identity\n  return obj.every iterator, context if nativeEvery and obj.every is nativeEvery\n  result = true\n  _.each obj, (value, index, list) ->\n    _.breakLoop() unless (result = result and iterator.call(context, value, index, list))\n  result\n\n\n# Determine if at least one element in the object matches a truth test. Use\n# JavaScript 1.6's **some**, if it exists.\n_.some = (obj, iterator, context) ->\n  iterator ||= _.identity\n  return obj.some iterator, context if nativeSome and obj.some is nativeSome\n  result = false\n  _.each obj, (value, index, list) ->\n    _.breakLoop() if (result = iterator.call(context, value, index, list))\n  result\n\n\n# Determine if a given value is included in the array or object,\n# based on `===`.\n_.include = (obj, target) ->\n  return _.indexOf(obj, target) isnt -1 if nativeIndexOf and obj.indexOf is nativeIndexOf\n  return true for own key, val of obj when val is target\n  false\n\n\n# Invoke a method with arguments on every item in a collection.\n_.invoke = (obj, method) ->\n  args = _.rest arguments, 2\n  (if method then val[method] else val).apply(val, args) for val in obj\n\n\n# Convenience version of a common use case of **map**: fetching a property.\n_.pluck = (obj, key) ->\n  _.map(obj, (val) -> val[key])\n\n\n# Return the maximum item or (item-based computation).\n_.max = (obj, iterator, context) ->\n  return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)\n  result = computed: -Infinity\n  _.each obj, (value, index, list) ->\n    computed = if iterator then iterator.call(context, value, index, list) else value\n    computed >= result.computed and (result = {value: value, computed: computed})\n  result.value\n\n\n# Return the minimum element (or element-based computation).\n_.min = (obj, iterator, context) ->\n  return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)\n  result = computed: Infinity\n  _.each obj, (value, index, list) ->\n    computed = if iterator then iterator.call(context, value, index, list) else value\n    computed < result.computed and (result = {value: value, computed: computed})\n  result.value\n\n\n# Sort the object's values by a criterion produced by an iterator.\n_.sortBy = (obj, iterator, context) ->\n  _.pluck(((_.map obj, (value, index, list) ->\n    {value: value, criteria: iterator.call(context, value, index, list)}\n  ).sort((left, right) ->\n    a = left.criteria; b = right.criteria\n    if a < b then -1 else if a > b then 1 else 0\n  )), 'value')\n\n\n# Use a comparator function to figure out at what index an object should\n# be inserted so as to maintain order. Uses binary search.\n_.sortedIndex = (array, obj, iterator) ->\n  iterator ||= _.identity\n  low = 0\n  high = array.length\n  while low < high\n    mid = (low + high) >> 1\n    if iterator(array[mid]) < iterator(obj) then low = mid + 1 else high = mid\n  low\n\n\n# Convert anything iterable into a real, live array.\n_.toArray = (iterable) ->\n  return [] if (!iterable)\n  return iterable.toArray() if (iterable.toArray)\n  return iterable if (_.isArray(iterable))\n  return slice.call(iterable) if (_.isArguments(iterable))\n  _.values(iterable)\n\n\n# Return the number of elements in an object.\n_.size = (obj) -> _.toArray(obj).length\n\n\n# Array Functions\n# ---------------\n\n# Get the first element of an array. Passing `n` will return the first N\n# values in the array. Aliased as **head**. The `guard` check allows it to work\n# with **map**.\n_.first = (array, n, guard) ->\n  if n and not guard then slice.call(array, 0, n) else array[0]\n\n\n# Returns everything but the first entry of the array. Aliased as **tail**.\n# Especially useful on the arguments object. Passing an `index` will return\n# the rest of the values in the array from that index onward. The `guard`\n# check allows it to work with **map**.\n_.rest = (array, index, guard) ->\n  slice.call(array, if _.isUndefined(index) or guard then 1 else index)\n\n\n# Get the last element of an array.\n_.last = (array) -> array[array.length - 1]\n\n\n# Trim out all falsy values from an array.\n_.compact = (array) -> item for item in array when item\n\n\n# Return a completely flattened version of an array.\n_.flatten = (array) ->\n  _.reduce array, (memo, value) ->\n    return memo.concat(_.flatten(value)) if _.isArray value\n    memo.push value\n    memo\n  , []\n\n\n# Return a version of the array that does not contain the specified value(s).\n_.without = (array) ->\n  values = _.rest arguments\n  val for val in _.toArray(array) when not _.include values, val\n\n\n# Produce a duplicate-free version of the array. If the array has already\n# been sorted, you have the option of using a faster algorithm.\n_.uniq = (array, isSorted) ->\n  memo = []\n  for el, i in _.toArray array\n    memo.push el if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))\n  memo\n\n\n# Produce an array that contains every item shared between all the\n# passed-in arrays.\n_.intersect = (array) ->\n  rest = _.rest arguments\n  _.select _.uniq(array), (item) ->\n    _.all rest, (other) ->\n      _.indexOf(other, item) >= 0\n\n\n# Zip together multiple lists into a single array -- elements that share\n# an index go together.\n_.zip = ->\n  length = _.max _.pluck arguments, 'length'\n  results = new Array length\n  for i in [0...length]\n    results[i] = _.pluck arguments, String i\n  results\n\n\n# If the browser doesn't supply us with **indexOf** (I'm looking at you, MSIE),\n# we need this function. Return the position of the first occurrence of an\n# item in an array, or -1 if the item is not included in the array.\n_.indexOf = (array, item) ->\n  return array.indexOf item if nativeIndexOf and array.indexOf is nativeIndexOf\n  i = 0; l = array.length\n  while l - i\n    if array[i] is item then return i else i++\n  -1\n\n\n# Provide JavaScript 1.6's **lastIndexOf**, delegating to the native function,\n# if possible.\n_.lastIndexOf = (array, item) ->\n  return array.lastIndexOf(item) if nativeLastIndexOf and array.lastIndexOf is nativeLastIndexOf\n  i = array.length\n  while i\n    if array[i] is item then return i else i--\n  -1\n\n\n# Generate an integer Array containing an arithmetic progression. A port of\n# [the native Python **range** function](http://docs.python.org/library/functions.html#range).\n_.range = (start, stop, step) ->\n  a = arguments\n  solo = a.length <= 1\n  i = start = if solo then 0 else a[0]\n  stop = if solo then a[0] else a[1]\n  step = a[2] or 1\n  len = Math.ceil((stop - start) / step)\n  return [] if len <= 0\n  range = new Array len\n  idx = 0\n  loop\n    return range if (if step > 0 then i - stop else stop - i) >= 0\n    range[idx] = i\n    idx++\n    i+= step\n\n\n# Function Functions\n# ------------------\n\n# Create a function bound to a given object (assigning `this`, and arguments,\n# optionally). Binding with arguments is also known as **curry**.\n_.bind = (func, obj) ->\n  args = _.rest arguments, 2\n  -> func.apply obj or root, args.concat arguments\n\n\n# Bind all of an object's methods to that object. Useful for ensuring that\n# all callbacks defined on an object belong to it.\n_.bindAll = (obj) ->\n  funcs = if arguments.length > 1 then _.rest(arguments) else _.functions(obj)\n  _.each funcs, (f) -> obj[f] = _.bind obj[f], obj\n  obj\n\n\n# Delays a function for the given number of milliseconds, and then calls\n# it with the arguments supplied.\n_.delay = (func, wait) ->\n  args = _.rest arguments, 2\n  setTimeout((-> func.apply(func, args)), wait)\n\n\n# Memoize an expensive function by storing its results.\n_.memoize = (func, hasher) ->\n  memo = {}\n  hasher or= _.identity\n  ->\n    key = hasher.apply this, arguments\n    return memo[key] if key of memo\n    memo[key] = func.apply this, arguments\n\n\n# Defers a function, scheduling it to run after the current call stack has\n# cleared.\n_.defer = (func) ->\n  _.delay.apply _, [func, 1].concat _.rest arguments\n\n\n# Returns the first function passed as an argument to the second,\n# allowing you to adjust arguments, run code before and after, and\n# conditionally execute the original function.\n_.wrap = (func, wrapper) ->\n  -> wrapper.apply wrapper, [func].concat arguments\n\n\n# Returns a function that is the composition of a list of functions, each\n# consuming the return value of the function that follows.\n_.compose = ->\n  funcs = arguments\n  ->\n    args = arguments\n    for i in [funcs.length - 1..0] by -1\n      args = [funcs[i].apply(this, args)]\n    args[0]\n\n\n# Object Functions\n# ----------------\n\n# Retrieve the names of an object's properties.\n_.keys = nativeKeys or (obj) ->\n  return _.range 0, obj.length if _.isArray(obj)\n  key for key, val of obj\n\n\n# Retrieve the values of an object's properties.\n_.values = (obj) ->\n  _.map obj, _.identity\n\n\n# Return a sorted list of the function names available in Underscore.\n_.functions = (obj) ->\n  _.filter(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()\n\n\n# Extend a given object with all of the properties in a source object.\n_.extend = (obj) ->\n  for source in _.rest(arguments)\n    obj[key] = val for key, val of source\n  obj\n\n\n# Create a (shallow-cloned) duplicate of an object.\n_.clone = (obj) ->\n  return obj.slice 0 if _.isArray obj\n  _.extend {}, obj\n\n\n# Invokes interceptor with the obj, and then returns obj.\n# The primary purpose of this method is to \"tap into\" a method chain,\n# in order to perform operations on intermediate results within\n the chain.\n_.tap = (obj, interceptor) ->\n  interceptor obj\n  obj\n\n\n# Perform a deep comparison to check if two objects are equal.\n_.isEqual = (a, b) ->\n  # Check object identity.\n  return true if a is b\n  # Different types?\n  atype = typeof(a); btype = typeof(b)\n  return false if atype isnt btype\n  # Basic equality test (watch out for coercions).\n  return true if `a == b`\n  # One is falsy and the other truthy.\n  return false if (!a and b) or (a and !b)\n  # One of them implements an `isEqual()`?\n  return a.isEqual(b) if a.isEqual\n  # Check dates' integer values.\n  return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)\n  # Both are NaN?\n  return false if _.isNaN(a) and _.isNaN(b)\n  # Compare regular expressions.\n  if _.isRegExp(a) and _.isRegExp(b)\n    return a.source is b.source and\n           a.global is b.global and\n           a.ignoreCase is b.ignoreCase and\n           a.multiline is b.multiline\n  # If a is not an object by this point, we can't handle it.\n  return false if atype isnt 'object'\n  # Check for different array lengths before comparing contents.\n  return false if a.length and (a.length isnt b.length)\n  # Nothing else worked, deep compare the contents.\n  aKeys = _.keys(a); bKeys = _.keys(b)\n  # Different object sizes?\n  return false if aKeys.length isnt bKeys.length\n  # Recursive comparison of contents.\n  return false for key, val of a when !(key of b) or !_.isEqual(val, b[key])\n  true\n\n\n# Is a given array or object empty?\n_.isEmpty = (obj) ->\n  return obj.length is 0 if _.isArray(obj) or _.isString(obj)\n  return false for own key of obj\n  true\n\n\n# Is a given value a DOM element?\n_.isElement = (obj) -> obj and obj.nodeType is 1\n\n\n# Is a given value an array?\n_.isArray = nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift and not obj.callee)\n\n\n# Is a given variable an arguments object?\n_.isArguments = (obj) -> obj and obj.callee\n\n\n# Is the given value a function?\n_.isFunction = (obj) -> !!(obj and obj.constructor and obj.call and obj.apply)\n\n\n# Is the given value a string?\n_.isString = (obj) -> !!(obj is '' or (obj and obj.charCodeAt and obj.substr))\n\n\n# Is a given value a number?\n_.isNumber = (obj) -> (obj is +obj) or toString.call(obj) is '[object Number]'\n\n\n# Is a given value a boolean?\n_.isBoolean = (obj) -> obj is true or obj is false\n\n\n# Is a given value a Date?\n_.isDate = (obj) -> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)\n\n\n# Is the given value a regular expression?\n_.isRegExp = (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))\n\n\n# Is the given value NaN -- this one is interesting. `NaN != NaN`, and\n# `isNaN(undefined) == true`, so we make sure it's a number first.\n_.isNaN = (obj) -> _.isNumber(obj) and window.isNaN(obj)\n\n\n# Is a given value equal to null?\n_.isNull = (obj) -> obj is null\n\n\n# Is a given variable undefined?\n_.isUndefined = (obj) -> typeof obj is 'undefined'\n\n\n# Utility Functions\n# -----------------\n\n# Run Underscore.js in noConflict mode, returning the `_` variable to its\n# previous owner. Returns a reference to the Underscore object.\n_.noConflict = ->\n  root._ = previousUnderscore\n  this\n\n\n# Keep the identity function around for default iterators.\n_.identity = (value) -> value\n\n\n# Run a function `n` times.\n_.times = (n, iterator, context) ->\n  iterator.call context, i for i in [0...n]\n\n\n# Break out of the middle of an iteration.\n_.breakLoop = -> throw breaker\n\n\n# Add your own custom functions to the Underscore object, ensuring that\n# they're correctly added to the OOP wrapper as well.\n_.mixin = (obj) ->\n  for name in _.functions(obj)\n    addToWrapper name, _[name] = obj[name]\n\n\n# Generate a unique integer id (unique within the entire client session).\n# Useful for temporary DOM ids.\nidCounter = 0\n_.uniqueId = (prefix) ->\n  (prefix or '') + idCounter++\n\n\n# By default, Underscore uses **ERB**-style template delimiters, change the\n# following template settings to use alternative delimiters.\n_.templateSettings = {\n  start: '<%'\n  end: '%>'\n  interpolate: /<%=(.+?)%>/g\n}\n\n\n# JavaScript templating a-la **ERB**, pilfered from John Resig's\n# *Secrets of the JavaScript Ninja*, page 83.\n# Single-quote fix from Rick Strahl.\n# With alterations for arbitrary delimiters, and to preserve whitespace.\n_.template = (str, data) ->\n  c = _.templateSettings\n  endMatch = new RegExp(\"'(?=[^\"+c.end.substr(0, 1)+\"]*\"+escapeRegExp(c.end)+\")\",\"g\")\n  fn = new Function 'obj',\n    'var p=[],print=function(){p.push.apply(p,arguments);};' +\n    'with(obj||{}){p.push(\\'' +\n    str.replace(/\\r/g, '\\\\r')\n       .replace(/\\n/g, '\\\\n')\n       .replace(/\\t/g, '\\\\t')\n       .replace(endMatch,\"���\")\n       .split(\"'\").join(\"\\\\'\")\n       .split(\"���\").join(\"'\")\n       .replace(c.interpolate, \"',$1,'\")\n       .split(c.start).join(\"');\")\n       .split(c.end).join(\"p.push('\") +\n       \"');}return p.join('');\"\n  if data then fn(data) else fn\n\n\n# Aliases\n# -------\n\n_.forEach = _.each\n_.foldl = _.inject = _.reduce\n_.foldr = _.reduceRight\n_.select = _.filter\n_.all = _.every\n_.any = _.some\n_.contains = _.include\n_.head = _.first\n_.tail = _.rest\n_.methods = _.functions\n\n\n# Setup the OOP Wrapper\n# ---------------------\n\n# If Underscore is called as a function, it returns a wrapped object that\n# can be used OO-style. This wrapper holds altered versions of all the\n# underscore functions. Wrapped objects may be chained.\nwrapper = (obj) ->\n  this._wrapped = obj\n  this\n\n\n# Helper function to continue chaining intermediate results.\nresult = (obj, chain) ->\n  if chain then _(obj).chain() else obj\n\n\n# A method to easily add functions to the OOP wrapper.\naddToWrapper = (name, func) ->\n  wrapper.prototype[name] = ->\n    args = _.toArray arguments\n    unshift.call args, this._wrapped\n    result func.apply(_, args), this._chain\n\n\n# Add all ofthe Underscore functions to the wrapper object.\n_.mixin _\n\n\n# Add all mutator Array functions to the wrapper.\n_.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name) ->\n  method = Array.prototype[name]\n  wrapper.prototype[name] = ->\n    method.apply(this._wrapped, arguments)\n    result(this._wrapped, this._chain)\n\n\n# Add all accessor Array functions to the wrapper.\n_.each ['concat', 'join', 'slice'], (name) ->\n  method = Array.prototype[name]\n  wrapper.prototype[name] = ->\n    result(method.apply(this._wrapped, arguments), this._chain)\n\n\n# Start chaining a wrapped Underscore object.\nwrapper::chain = ->\n  this._chain = true\n  this\n\n\n# Extracts the result from a wrapped and chained object.\nwrapper::value = -> this._wrapped\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-coffeescript</code>.</p>\n\n    <p>The CoffeeScript mode was written by Jeff Pickhardt (<a href=\"LICENSE\">license</a>).</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/css/css.js",
    "content": "CodeMirror.defineMode(\"css\", function(config) {\n  var indentUnit = config.indentUnit, type;\n  function ret(style, tp) {type = tp; return style;}\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == \"@\") {stream.eatWhile(/[\\w\\\\\\-]/); return ret(\"meta\", stream.current());}\n    else if (ch == \"/\" && stream.eat(\"*\")) {\n      state.tokenize = tokenCComment;\n      return tokenCComment(stream, state);\n    }\n    else if (ch == \"<\" && stream.eat(\"!\")) {\n      state.tokenize = tokenSGMLComment;\n      return tokenSGMLComment(stream, state);\n    }\n    else if (ch == \"=\") ret(null, \"compare\");\n    else if ((ch == \"~\" || ch == \"|\") && stream.eat(\"=\")) return ret(null, \"compare\");\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (ch == \"#\") {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"atom\", \"hash\");\n    }\n    else if (ch == \"!\") {\n      stream.match(/^\\s*\\w*/);\n      return ret(\"keyword\", \"important\");\n    }\n    else if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w.%]/);\n      return ret(\"number\", \"unit\");\n    }\n    else if (/[,.+>*\\/]/.test(ch)) {\n      return ret(null, \"select-op\");\n    }\n    else if (/[;{}:\\[\\]]/.test(ch)) {\n      return ret(null, ch);\n    }\n    else {\n      stream.eatWhile(/[\\w\\\\\\-]/);\n      return ret(\"variable\", \"variable\");\n    }\n  }\n\n  function tokenCComment(stream, state) {\n    var maybeEnd = false, ch;\n    while ((ch = stream.next()) != null) {\n      if (maybeEnd && ch == \"/\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenSGMLComment(stream, state) {\n    var dashes = 0, ch;\n    while ((ch = stream.next()) != null) {\n      if (dashes >= 2 && ch == \">\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      dashes = (ch == \"-\") ? dashes + 1 : 0;\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped)\n          break;\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      if (!escaped) state.tokenize = tokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  return {\n    startState: function(base) {\n      return {tokenize: tokenBase,\n              baseIndent: base || 0,\n              stack: []};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      var context = state.stack[state.stack.length-1];\n      if (type == \"hash\" && context != \"rule\") style = \"string-2\";\n      else if (style == \"variable\") {\n        if (context == \"rule\") style = \"number\";\n        else if (!context || context == \"@media{\") style = \"tag\";\n      }\n\n      if (context == \"rule\" && /^[\\{\\};]$/.test(type))\n        state.stack.pop();\n      if (type == \"{\") {\n        if (context == \"@media\") state.stack[state.stack.length-1] = \"@media{\";\n        else state.stack.push(\"{\");\n      }\n      else if (type == \"}\") state.stack.pop();\n      else if (type == \"@media\") state.stack.push(\"@media\");\n      else if (context == \"{\" && type != \"comment\") state.stack.push(\"rule\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var n = state.stack.length;\n      if (/^\\}/.test(textAfter))\n        n -= state.stack[state.stack.length-1] == \"rule\" ? 2 : 1;\n      return state.baseIndent + n * indentUnit;\n    },\n\n    electricChars: \"}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/css\", \"css\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/css/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: CSS mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"css.js\"></script>\n    <style>.CodeMirror {background: #f8f8f8;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: CSS mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n/* Some example CSS */\n\n@import url(\"something.css\");\n\nbody {\n  margin: 0;\n  padding: 3em 6em;\n  font-family: tahoma, arial, sans-serif;\n  color: #000;\n}\n\n#navigation a {\n  font-weight: bold;\n  text-decoration: none !important;\n}\n\nh1 {\n  font-size: 2.5em;\n}\n\nh2 {\n  font-size: 1.7em;\n}\n\nh1:before, h2:before {\n  content: \"::\";\n}\n\ncode {\n  font-family: courier, monospace;\n  font-size: 80%;\n  color: #418A8A;\n}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/css</code>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/diff/diff.js",
    "content": "CodeMirror.defineMode(\"diff\", function() {\n\n  var TOKEN_NAMES = {\n    '+': 'tag',\n    '-': 'string',\n    '@': 'meta'\n  };\n\n  return {\n    token: function(stream) {\n      var tw_pos = stream.string.search(/[\\t ]+?$/);\n\n      if (!stream.sol() || tw_pos === 0) {\n        stream.skipToEnd();\n        return (\"error \" + (\n          TOKEN_NAMES[stream.string.charAt(0)] || '')).replace(/ $/, '');\n      }\n\n      var token_name = TOKEN_NAMES[stream.peek()] || stream.skipToEnd();\n\n      if (tw_pos === -1) {\n        stream.skipToEnd();\n      } else {\n        stream.pos = tw_pos;\n      }\n\n      return token_name;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-diff\", \"diff\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/diff/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Diff mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"diff.js\"></script>\n    <style>\n      .CodeMirror {border-top: 1px solid #ddd; border-bottom: 1px solid #ddd;}\n      span.cm-meta {color: #a0b !important;}\n      span.cm-error { background-color: black; opacity: 0.4;}\n      span.cm-error.cm-string { background-color: red; }\n      span.cm-error.cm-tag { background-color: #2b2; }\n    </style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Diff mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\ndiff --git a/index.html b/index.html\nindex c1d9156..7764744 100644\n--- a/index.html\n+++ b/index.html\n@@ -95,7 +95,8 @@ StringStream.prototype = {\n     <script>\n       var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n         lineNumbers: true,\n-        autoMatchBrackets: true\n+        autoMatchBrackets: true,\n+      onGutterClick: function(x){console.log(x);}\n       });\n     </script>\n   </body>\ndiff --git a/lib/codemirror.js b/lib/codemirror.js\nindex 04646a9..9a39cc7 100644\n--- a/lib/codemirror.js\n+++ b/lib/codemirror.js\n@@ -399,10 +399,16 @@ var CodeMirror = (function() {\n     }\n \n     function onMouseDown(e) {\n-      var start = posFromMouse(e), last = start;    \n+      var start = posFromMouse(e), last = start, target = e.target();\n       if (!start) return;\n       setCursor(start.line, start.ch, false);\n       if (e.button() != 1) return;\n+      if (target.parentNode == gutter) {    \n+        if (options.onGutterClick)\n+          options.onGutterClick(indexOf(gutter.childNodes, target) + showingFrom);\n+        return;\n+      }\n+\n       if (!focused) onFocus();\n \n       e.stop();\n@@ -808,7 +814,7 @@ var CodeMirror = (function() {\n       for (var i = showingFrom; i < showingTo; ++i) {\n         var marker = lines[i].gutterMarker;\n         if (marker) html.push('<div class=\"' + marker.style + '\">' + htmlEscape(marker.text) + '</div>');\n-        else html.push(\"<div>\" + (options.lineNumbers ? i + 1 : \"\\u00a0\") + \"</div>\");\n+        else html.push(\"<div>\" + (options.lineNumbers ? i + options.firstLineNumber : \"\\u00a0\") + \"</div>\");\n       }\n       gutter.style.display = \"none\"; // TODO test whether this actually helps\n       gutter.innerHTML = html.join(\"\");\n@@ -1371,10 +1377,8 @@ var CodeMirror = (function() {\n         if (option == \"parser\") setParser(value);\n         else if (option === \"lineNumbers\") setLineNumbers(value);\n         else if (option === \"gutter\") setGutter(value);\n-        else if (option === \"readOnly\") options.readOnly = value;\n-        else if (option === \"indentUnit\") {options.indentUnit = indentUnit = value; setParser(options.parser);}\n-        else if (/^(?:enterMode|tabMode|indentWithTabs|readOnly|autoMatchBrackets|undoDepth)$/.test(option)) options[option] = value;\n-        else throw new Error(\"Can't set option \" + option);\n+        else if (option === \"indentUnit\") {options.indentUnit = value; setParser(options.parser);}\n+        else options[option] = value;\n       },\n       cursorCoords: cursorCoords,\n       undo: operation(undo),\n@@ -1402,7 +1406,8 @@ var CodeMirror = (function() {\n       replaceRange: operation(replaceRange),\n \n       operation: function(f){return operation(f)();},\n-      refresh: function(){updateDisplay([{from: 0, to: lines.length}]);}\n+      refresh: function(){updateDisplay([{from: 0, to: lines.length}]);},\n+      getInputField: function(){return input;}\n     };\n     return instance;\n   }\n@@ -1420,6 +1425,7 @@ var CodeMirror = (function() {\n     readOnly: false,\n     onChange: null,\n     onCursorActivity: null,\n+    onGutterClick: null,\n     autoMatchBrackets: false,\n     workTime: 200,\n     workDelay: 300,\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-diff</code>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/ecl/ecl.js",
    "content": "CodeMirror.defineMode(\"ecl\", function(config) {\n\n  function words(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n\n  function metaHook(stream, state) {\n    if (!state.startOfLine) return false;\n    stream.skipToEnd();\n    return \"meta\";\n  }\n\n  function tokenAtString(stream, state) {\n    var next;\n    while ((next = stream.next()) != null) {\n      if (next == '\"' && !stream.eat('\"')) {\n        state.tokenize = null;\n        break;\n      }\n    }\n    return \"string\";\n  }\n\n  var indentUnit = config.indentUnit;\n  var keyword = words(\"abs acos allnodes ascii asin asstring atan atan2 ave case choose choosen choosesets clustersize combine correlation cos cosh count covariance cron dataset dedup define denormalize distribute distributed distribution ebcdic enth error evaluate event eventextra eventname exists exp failcode failmessage fetch fromunicode getisvalid global graph group hash hash32 hash64 hashcrc hashmd5 having if index intformat isvalid iterate join keyunicode length library limit ln local log loop map matched matchlength matchposition matchtext matchunicode max merge mergejoin min nolocal nonempty normalize parse pipe power preload process project pull random range rank ranked realformat recordof regexfind regexreplace regroup rejected rollup round roundup row rowdiff sample set sin sinh sizeof soapcall sort sorted sqrt stepped stored sum table tan tanh thisnode topn tounicode transfer trim truncate typeof ungroup unicodeorder variance which workunit xmldecode xmlencode xmltext xmlunicode\");\n  var variable = words(\"apply assert build buildindex evaluate fail keydiff keypatch loadxml nothor notify output parallel sequential soapcall wait\");\n  var variable_2 = words(\"__compressed__ all and any as atmost before beginc++ best between case const counter csv descend encrypt end endc++ endmacro except exclusive expire export extend false few first flat from full function group header heading hole ifblock import in interface joined keep keyed last left limit load local locale lookup macro many maxcount maxlength min skew module named nocase noroot noscan nosort not of only opt or outer overwrite packed partition penalty physicallength pipe quote record relationship repeat return right scan self separator service shared skew skip sql store terminator thor threshold token transform trim true type unicodeorder unsorted validate virtual whole wild within xml xpath\");\n  var variable_3 = words(\"ascii big_endian boolean data decimal ebcdic integer pattern qstring real record rule set of string token udecimal unicode unsigned varstring varunicode\");\n  var builtin = words(\"checkpoint deprecated failcode failmessage failure global independent onwarning persist priority recovery stored success wait when\");\n  var blockKeywords = words(\"catch class do else finally for if switch try while\");\n  var atoms = words(\"true false null\");\n  var hooks = {\"#\": metaHook};\n  var multiLineStrings;\n  var isOperatorChar = /[+\\-*&%=<>!?|\\/]/;\n\n  var curPunc;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (hooks[ch]) {\n      var result = hooks[ch](stream, state);\n      if (result !== false) return result;\n    }\n    if (ch == '\"' || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      curPunc = ch;\n      return null\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      return \"number\";\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize = tokenComment;\n        return tokenComment(stream, state);\n      }\n      if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n    }\n    if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_]/);\n    var cur = stream.current().toLowerCase();\n    if (keyword.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"keyword\";\n    } else if (variable.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"variable\";\n    } else if (variable_2.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"variable-2\";\n    } else if (variable_3.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"variable-3\";\n    } else if (builtin.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"builtin\";\n    } else { //Data types are of from KEYWORD## \n\t\tvar i = cur.length - 1;\n\t\twhile(i >= 0 && (!isNaN(cur[i]) || cur[i] == '_'))\n\t\t\t--i;\n\t\t\n\t\tif (i > 0) {\n\t\t\tvar cur2 = cur.substr(0, i + 1);\n\t    \tif (variable_3.propertyIsEnumerable(cur2)) {\n\t      \t\tif (blockKeywords.propertyIsEnumerable(cur2)) curPunc = \"newstatement\";\n\t      \t\treturn \"variable-3\";\n\t      \t}\n\t    }\n    }\n    if (atoms.propertyIsEnumerable(cur)) return \"atom\";\n    return \"word\";\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next, end = false;\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) {end = true; break;}\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end || !(escaped || multiLineStrings))\n        state.tokenize = tokenBase;\n      return \"string\";\n    };\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function Context(indented, column, type, align, prev) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.align = align;\n    this.prev = prev;\n  }\n  function pushContext(state, col, type) {\n    return state.context = new Context(state.indented, col, type, null, state.context);\n  }\n  function popContext(state) {\n    var t = state.context.type;\n    if (t == \")\" || t == \"]\" || t == \"}\")\n      state.indented = state.context.indented;\n    return state.context = state.context.prev;\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: null,\n        context: new Context((basecolumn || 0) - indentUnit, 0, \"top\", false),\n        indented: 0,\n        startOfLine: true\n      };\n    },\n\n    token: function(stream, state) {\n      var ctx = state.context;\n      if (stream.sol()) {\n        if (ctx.align == null) ctx.align = false;\n        state.indented = stream.indentation();\n        state.startOfLine = true;\n      }\n      if (stream.eatSpace()) return null;\n      curPunc = null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style == \"comment\" || style == \"meta\") return style;\n      if (ctx.align == null) ctx.align = true;\n\n      if ((curPunc == \";\" || curPunc == \":\") && ctx.type == \"statement\") popContext(state);\n      else if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n      else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n      else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n      else if (curPunc == \"}\") {\n        while (ctx.type == \"statement\") ctx = popContext(state);\n        if (ctx.type == \"}\") ctx = popContext(state);\n        while (ctx.type == \"statement\") ctx = popContext(state);\n      }\n      else if (curPunc == ctx.type) popContext(state);\n      else if (ctx.type == \"}\" || ctx.type == \"top\" || (ctx.type == \"statement\" && curPunc == \"newstatement\"))\n        pushContext(state, stream.column(), \"statement\");\n      state.startOfLine = false;\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase && state.tokenize != null) return 0;\n      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);\n      if (ctx.type == \"statement\" && firstChar == \"}\") ctx = ctx.prev;\n      var closing = firstChar == ctx.type;\n      if (ctx.type == \"statement\") return ctx.indented + (firstChar == \"{\" ? 0 : indentUnit);\n      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \"{}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-ecl\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/ecl/index.html",
    "content": "﻿<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: ECL mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"ecl.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style>.CodeMirror {border: 1px solid black;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: ECL mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n/*\nsample useless code to demonstrate ecl syntax highlighting\nthis is a multiline comment!\n*/\n\n//  this is a singleline comment!\n\nimport ut;\nr := \n  record\n   string22 s1 := '123';\n   integer4 i1 := 123;\n  end;\n#option('tmp', true);\nd := dataset('tmp::qb', r, thor);\noutput(d);\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        tabMode: \"indent\",\n        matchBrackets: true,\n      });\n    </script>\n\n    <p>Based on CodeMirror's clike mode.  For more information see <a href=\"http://hpccsystems.com\">HPCC Systems</a> web site.</p>\n    <p><strong>MIME types defined:</strong> <code>text/x-ecl</code>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/erlang/erlang.js",
    "content": "// erlang    -> CodeMirror tag\n//\n// atom      -> atom\n// attribute -> attribute\n// builtin   -> builtin\n// comment   -> comment\n// error     -> error\n// fun       -> meta\n// function  -> tag\n// guard     -> property\n// keyword   -> keyword\n// macro     -> variable-2\n// number    -> number\n// operator  -> operator\n// record    -> bracket\n// string    -> string\n// type      -> def\n// variable  -> variable\n\nCodeMirror.defineMIME(\"text/x-erlang\", \"erlang\");\n\nCodeMirror.defineMode(\"erlang\", function(cmCfg, modeCfg) {\n\n  var typeWords = [\n    \"-type\", \"-spec\", \"-export_type\", \"-opaque\"];\n\n  var keywordWords = [\n    \"after\",\"begin\",\"catch\",\"case\",\"cond\",\"end\",\"fun\",\"if\",\n    \"let\",\"of\",\"query\",\"receive\",\"try\",\"when\"];\n\n  var operatorWords = [\n    \"and\",\"andalso\",\"band\",\"bnot\",\"bor\",\"bsl\",\"bsr\",\"bxor\",\n    \"div\",\"not\",\"or\",\"orelse\",\"rem\",\"xor\"];\n\n  var operatorSymbols = [\n    \"+\",\"-\",\"*\",\"/\",\">\",\">=\",\"<\",\"=<\",\"=:=\",\"==\",\"=/=\",\"/=\",\"||\",\"<-\"];\n\n  var guardWords = [\n    \"is_atom\",\"is_binary\",\"is_bitstring\",\"is_boolean\",\"is_float\",\n    \"is_function\",\"is_integer\",\"is_list\",\"is_number\",\"is_pid\",\n    \"is_port\",\"is_record\",\"is_reference\",\"is_tuple\",\n    \"atom\",\"binary\",\"bitstring\",\"boolean\",\"function\",\"integer\",\"list\",\n    \"number\",\"pid\",\"port\",\"record\",\"reference\",\"tuple\"];\n\n  var bifWords = [\n    \"abs\",\"adler32\",\"adler32_combine\",\"alive\",\"apply\",\"atom_to_binary\",\n    \"atom_to_list\",\"binary_to_atom\",\"binary_to_existing_atom\",\n    \"binary_to_list\",\"binary_to_term\",\"bit_size\",\"bitstring_to_list\",\n    \"byte_size\",\"check_process_code\",\"contact_binary\",\"crc32\",\n    \"crc32_combine\",\"date\",\"decode_packet\",\"delete_module\",\n    \"disconnect_node\",\"element\",\"erase\",\"exit\",\"float\",\"float_to_list\",\n    \"garbage_collect\",\"get\",\"get_keys\",\"group_leader\",\"halt\",\"hd\",\n    \"integer_to_list\",\"internal_bif\",\"iolist_size\",\"iolist_to_binary\",\n    \"is_alive\",\"is_atom\",\"is_binary\",\"is_bitstring\",\"is_boolean\",\n    \"is_float\",\"is_function\",\"is_integer\",\"is_list\",\"is_number\",\"is_pid\",\n    \"is_port\",\"is_process_alive\",\"is_record\",\"is_reference\",\"is_tuple\",\n    \"length\",\"link\",\"list_to_atom\",\"list_to_binary\",\"list_to_bitstring\",\n    \"list_to_existing_atom\",\"list_to_float\",\"list_to_integer\",\n    \"list_to_pid\",\"list_to_tuple\",\"load_module\",\"make_ref\",\"module_loaded\",\n    \"monitor_node\",\"node\",\"node_link\",\"node_unlink\",\"nodes\",\"notalive\",\n    \"now\",\"open_port\",\"pid_to_list\",\"port_close\",\"port_command\",\n    \"port_connect\",\"port_control\",\"pre_loaded\",\"process_flag\",\n    \"process_info\",\"processes\",\"purge_module\",\"put\",\"register\",\n    \"registered\",\"round\",\"self\",\"setelement\",\"size\",\"spawn\",\"spawn_link\",\n    \"spawn_monitor\",\"spawn_opt\",\"split_binary\",\"statistics\",\n    \"term_to_binary\",\"time\",\"throw\",\"tl\",\"trunc\",\"tuple_size\",\n    \"tuple_to_list\",\"unlink\",\"unregister\",\"whereis\"];\n\n  function isMember(element,list) {\n    return (-1 < list.indexOf(element));\n  }\n\n  function isPrev(stream,string) {\n    var start = stream.start;\n    var len = string.length;\n    if (len <= start) {\n      var word = stream.string.slice(start-len,start);\n      return word == string;\n    }else{\n      return false;\n    }\n  }\n\n  var smallRE = /[a-z_]/;\n  var largeRE = /[A-Z_]/;\n  var digitRE = /[0-9]/;\n  var octitRE = /[0-7]/;\n  var idRE = /[a-z_A-Z0-9]/;\n\n  function tokenize(stream, state) {\n    if (stream.eatSpace()) {\n      return null;\n    }\n\n    // attributes and type specs\n    if (stream.sol() && stream.peek() == '-') {\n      stream.next();\n      if (stream.eat(smallRE) && stream.eatWhile(idRE)) {\n        if (stream.peek() == \"(\") {\n          return \"attribute\";\n        }else if (isMember(stream.current(),typeWords)) {\n          return \"def\";\n        }else{\n          return null;\n        }\n      }\n      stream.backUp(1);\n    }\n\n    var ch = stream.next();\n\n    // comment\n    if (ch == '%') {\n      stream.skipToEnd();\n      return \"comment\";\n    }\n\n    // macro\n    if (ch == '?') {\n      stream.eatWhile(idRE);\n      return \"variable-2\";\n    }\n\n    // record\n    if ( ch == \"#\") {\n      stream.eatWhile(idRE);\n      return \"bracket\";\n    }\n\n    // char\n    if ( ch == \"$\") {\n      if (stream.next() == \"\\\\\") {\n        if (!stream.eatWhile(octitRE)) {\n          stream.next();\n        }\n      }\n      return \"string\";\n    }\n\n    // quoted atom\n    if (ch == '\\'') {\n      return singleQuote(stream);\n    }\n\n    // string\n    if (ch == '\"') {\n      return doubleQuote(stream);\n    }\n\n    // variable\n    if (largeRE.test(ch)) {\n      stream.eatWhile(idRE);\n      return \"variable\";\n    }\n\n    // atom/keyword/BIF/function\n    if (smallRE.test(ch)) {\n      stream.eatWhile(idRE);\n\n      if (stream.peek() == \"/\") {\n        stream.next();\n        if (stream.eatWhile(digitRE)) {\n          return \"meta\";      // f/0 style fun\n        }else{\n          stream.backUp(1);\n          return \"atom\";\n        }\n      }\n\n      var w = stream.current();\n\n      if (isMember(w,keywordWords)) {\n        return \"keyword\";           // keyword\n      }\n      if (stream.peek() == \"(\") {\n        if (isMember(w,bifWords) &&\n            (!isPrev(stream,\":\") || isPrev(stream,\"erlang:\"))) {\n          return \"builtin\";         // BIF\n        }else{\n          return \"tag\";             // function\n        }\n      }\n      if (isMember(w,guardWords)) {\n        return \"property\";          // guard\n      }\n      if (isMember(w,operatorWords)) {\n        return \"operator\";          // operator\n      }\n\n\n      if (stream.peek() == \":\") {\n        if (w == \"erlang\") {         // f:now() is highlighted incorrectly\n          return \"builtin\";\n        } else {\n          return \"tag\";              // function application\n        }\n      }\n\n      return \"atom\";\n    }\n\n    // number\n    if (digitRE.test(ch)) {\n      stream.eatWhile(digitRE);\n      if (stream.eat('#')) {\n        stream.eatWhile(digitRE);    // 16#10  style integer\n      } else {\n        if (stream.eat('.')) {       // float\n          stream.eatWhile(digitRE);\n        }\n        if (stream.eat(/[eE]/)) {\n          stream.eat(/[-+]/);        // float with exponent\n          stream.eatWhile(digitRE);\n        }\n      }\n      return \"number\";               // normal integer\n    }\n\n    return null;\n  }\n\n  function doubleQuote(stream) {\n    return Quote(stream, '\"', '\\\\', \"string\");\n  }\n\n  function singleQuote(stream) {\n    return Quote(stream,'\\'','\\\\',\"atom\");\n  }\n\n  function Quote(stream,quoteChar,escapeChar,tag) {\n    while (!stream.eol()) {\n      var ch = stream.next();\n      if (ch == quoteChar) {\n        return tag;\n      }else if (ch == escapeChar) {\n        stream.next();\n      }\n    }\n    return \"error\";\n  }\n\n  return {\n    startState: function() {\n      return {};\n    },\n\n    token: function(stream, state) {\n      return tokenize(stream, state);\n    }\n  };\n});\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/erlang/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Erlang mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"erlang.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../theme/erlang-dark.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Erlang mode</h1>\n\n<form><textarea id=\"code\" name=\"code\">\n%% -*- mode: erlang; erlang-indent-level: 2 -*-\n%%% Created :  7 May 2012 by mats cronqvist <masse@klarna.com>\n\n%% @doc\n%% Demonstrates how to print a record.\n%% @end\n\n-module('ex').\n-author('mats cronqvist').\n-export([demo/0,\n         rec_info/1]).\n\n-record(demo,{a=\"One\",b=\"Two\",c=\"Three\",d=\"Four\"}).\n\nrec_info(demo) -> record_info(fields,demo).\n\ndemo() -> expand_recs(?MODULE,#demo{a=\"A\",b=\"BB\"}).\n  \nexpand_recs(M,List) when is_list(List) ->\n  [expand_recs(M,L)||L<-List];\nexpand_recs(M,Tup) when is_tuple(Tup) ->\n  case tuple_size(Tup) of\n    L when L < 1 -> Tup;\n    L ->\n      try Fields = M:rec_info(element(1,Tup)),\n          L = length(Fields)+1,\n          lists:zip(Fields,expand_recs(M,tl(tuple_to_list(Tup))))\n      catch _:_ ->\n          list_to_tuple(expand_recs(M,tuple_to_list(Tup)))\n      end\n  end;\nexpand_recs(_,Term) ->\n  Term.\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        theme: \"erlang-dark\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-erlang</code>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/gfm/gfm.js",
    "content": "CodeMirror.defineMode(\"gfm\", function(config, parserConfig) {\n  var mdMode = CodeMirror.getMode(config, \"markdown\");\n  var aliases = {\n    html: \"htmlmixed\",\n    js: \"javascript\",\n    json: \"application/json\",\n    c: \"text/x-csrc\",\n    \"c++\": \"text/x-c++src\",\n    java: \"text/x-java\",\n    csharp: \"text/x-csharp\",\n    \"c#\": \"text/x-csharp\"\n  };\n\n  // make this lazy so that we don't need to load GFM last\n  var getMode = (function () {\n    var i, modes = {}, mimes = {}, mime;\n\n    var list = CodeMirror.listModes();\n    for (i = 0; i < list.length; i++) {\n      modes[list[i]] = list[i];\n    }\n    var mimesList = CodeMirror.listMIMEs();\n    for (i = 0; i < mimesList.length; i++) {\n      mime = mimesList[i].mime;\n      mimes[mime] = mimesList[i].mime;\n    }\n\n    for (var a in aliases) {\n      if (aliases[a] in modes || aliases[a] in mimes)\n        modes[a] = aliases[a];\n    }\n    \n    return function (lang) {\n      return modes[lang] ? CodeMirror.getMode(config, modes[lang]) : null;\n    }\n  }());\n\n  function markdown(stream, state) {\n    // intercept fenced code blocks\n    if (stream.sol() && stream.match(/^```([\\w+#]*)/)) {\n      // try switching mode\n      state.localMode = getMode(RegExp.$1)\n      if (state.localMode)\n        state.localState = state.localMode.startState();\n\n      state.token = local;\n      return 'code';\n    }\n\n    return mdMode.token(stream, state.mdState);\n  }\n\n  function local(stream, state) {\n    if (stream.sol() && stream.match(/^```/)) {\n      state.localMode = state.localState = null;\n      state.token = markdown;\n      return 'code';\n    }\n    else if (state.localMode) {\n      return state.localMode.token(stream, state.localState);\n    } else {\n      stream.skipToEnd();\n      return 'code';\n    }\n  }\n\n  // custom handleText to prevent emphasis in the middle of a word\n  // and add autolinking\n  function handleText(stream, mdState) {\n    var match;\n    if (stream.match(/^\\w+:\\/\\/\\S+/)) {\n      return 'linkhref';\n    }\n    if (stream.match(/^[^\\[*\\\\<>` _][^\\[*\\\\<>` ]*[^\\[*\\\\<>` _]/)) {\n      return mdMode.getType(mdState);\n    }\n    if (match = stream.match(/^[^\\[*\\\\<>` ]+/)) {\n      var word = match[0];\n      if (word[0] === '_' && word[word.length-1] === '_') {\n        stream.backUp(word.length);\n        return undefined;\n      }\n      return mdMode.getType(mdState);\n    }\n    if (stream.eatSpace()) {\n      return null;\n    }\n  }\n\n  return {\n    startState: function() {\n      var mdState = mdMode.startState();\n      mdState.text = handleText;\n      return {token: markdown, mode: \"markdown\", mdState: mdState,\n              localMode: null, localState: null};\n    },\n\n    copyState: function(state) {\n      return {token: state.token, mode: state.mode, mdState: CodeMirror.copyState(mdMode, state.mdState),\n              localMode: state.localMode,\n              localState: state.localMode ? CodeMirror.copyState(state.localMode, state.localState) : null};\n    },\n\n    token: function(stream, state) {\n      return state.token(stream, state);\n    }\n  }\n}, \"markdown\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/gfm/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: GFM mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"../xml/xml.js\"></script>\n    <script src=\"../markdown/markdown.js\"></script>\n    <script src=\"gfm.js\"></script>\n    <script src=\"../javascript/javascript.js\"></script>\n    <link rel=\"stylesheet\" href=\"../markdown/markdown.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: GFM mode</h1>\n\n<!-- source: http://daringfireball.net/projects/markdown/basics.text -->\n<form><textarea id=\"code\" name=\"code\">\nGithub Flavored Markdown\n========================\n\nEverything from markdown plus GFM features:\n\n## Fenced code blocks\n\n```javascript\nfor (var i = 0; i &lt; items.length; i++) {\n    console.log(items[i], i); // log them\n}\n```\n\nSee http://github.github.com/github-flavored-markdown/\n\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: 'gfm',\n        lineNumbers: true,\n        matchBrackets: true,\n        theme: \"default\"\n      });\n    </script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/go/go.js",
    "content": "CodeMirror.defineMode(\"go\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n\n  var keywords = {\n    \"break\":true, \"case\":true, \"chan\":true, \"const\":true, \"continue\":true,\n    \"default\":true, \"defer\":true, \"else\":true, \"fallthrough\":true, \"for\":true,\n    \"func\":true, \"go\":true, \"goto\":true, \"if\":true, \"import\":true,\n    \"interface\":true, \"map\":true, \"package\":true, \"range\":true, \"return\":true,\n    \"select\":true, \"struct\":true, \"switch\":true, \"type\":true, \"var\":true,\n    \"bool\":true, \"byte\":true, \"complex64\":true, \"complex128\":true,\n    \"float32\":true, \"float64\":true, \"int8\":true, \"int16\":true, \"int32\":true,\n    \"int64\":true, \"string\":true, \"uint8\":true, \"uint16\":true, \"uint32\":true,\n    \"uint64\":true, \"int\":true, \"uint\":true, \"uintptr\":true\n  };\n\n  var atoms = {\n    \"true\":true, \"false\":true, \"iota\":true, \"nil\":true, \"append\":true,\n    \"cap\":true, \"close\":true, \"complex\":true, \"copy\":true, \"imag\":true,\n    \"len\":true, \"make\":true, \"new\":true, \"panic\":true, \"print\":true,\n    \"println\":true, \"real\":true, \"recover\":true\n  };\n\n  var blockKeywords = {\n    \"else\":true, \"for\":true, \"func\":true, \"if\":true, \"interface\":true,\n    \"select\":true, \"struct\":true, \"switch\":true\n  };\n\n  var isOperatorChar = /[+\\-*&^%:=<>!|\\/]/;\n\n  var curPunc;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\" || ch == \"`\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    if (/[\\d\\.]/.test(ch)) {\n      if (ch == \".\") {\n        stream.match(/^[0-9]+([eE][\\-+]?[0-9]+)?/);\n      } else if (ch == \"0\") {\n        stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/);\n      } else {\n        stream.match(/^[0-9]*\\.?[0-9]*([eE][\\-+]?[0-9]+)?/);\n      }\n      return \"number\";\n    }\n    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      curPunc = ch;\n      return null\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize = tokenComment;\n        return tokenComment(stream, state);\n      }\n      if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n    }\n    if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_]/);\n    var cur = stream.current();\n    if (keywords.propertyIsEnumerable(cur)) {\n      if (cur == \"case\" || cur == \"default\") curPunc = \"case\";\n      return \"keyword\";\n    }\n    if (atoms.propertyIsEnumerable(cur)) return \"atom\";\n    return \"word\";\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next, end = false;\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) {end = true; break;}\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end || !(escaped || quote == \"`\"))\n        state.tokenize = tokenBase;\n      return \"string\";\n    };\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function Context(indented, column, type, align, prev) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.align = align;\n    this.prev = prev;\n  }\n  function pushContext(state, col, type) {\n    return state.context = new Context(state.indented, col, type, null, state.context);\n  }\n  function popContext(state) {\n    var t = state.context.type;\n    if (t == \")\" || t == \"]\" || t == \"}\")\n      state.indented = state.context.indented;\n    return state.context = state.context.prev;\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: null,\n        context: new Context((basecolumn || 0) - indentUnit, 0, \"top\", false),\n        indented: 0,\n        startOfLine: true\n      };\n    },\n\n    token: function(stream, state) {\n      var ctx = state.context;\n      if (stream.sol()) {\n        if (ctx.align == null) ctx.align = false;\n        state.indented = stream.indentation();\n        state.startOfLine = true;\n        if (ctx.type == \"case\") ctx.type = \"}\";\n      }\n      if (stream.eatSpace()) return null;\n      curPunc = null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style == \"comment\") return style;\n      if (ctx.align == null) ctx.align = true;\n\n      if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n      else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n      else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n      else if (curPunc == \"case\") ctx.type = \"case\"\n      else if (curPunc == \"}\" && ctx.type == \"}\") ctx = popContext(state);\n      else if (curPunc == ctx.type) popContext(state);\n      state.startOfLine = false;\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase && state.tokenize != null) return 0;\n      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);\n      if (ctx.type == \"case\" && /^(?:case|default)\\b/.test(textAfter)) {\n        state.context.type = \"}\";\n        return ctx.indented;\n      }\n      var closing = firstChar == ctx.type;\n      if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \"{}:\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-go\", \"go\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/go/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Go mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <link rel=\"stylesheet\" href=\"../../theme/elegant.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"go.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style>.CodeMirror {border:1px solid #999; background:#ffc}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: Go mode</h1>\n\n<form><textarea id=\"code\" name=\"code\">\n// Prime Sieve in Go.\n// Taken from the Go specification.\n// Copyright © The Go Authors.\n\npackage main\n\nimport \"fmt\"\n\n// Send the sequence 2, 3, 4, ... to channel 'ch'.\nfunc generate(ch chan&lt;- int) {\n\tfor i := 2; ; i++ {\n\t\tch &lt;- i  // Send 'i' to channel 'ch'\n\t}\n}\n\n// Copy the values from channel 'src' to channel 'dst',\n// removing those divisible by 'prime'.\nfunc filter(src &lt;-chan int, dst chan&lt;- int, prime int) {\n\tfor i := range src {    // Loop over values received from 'src'.\n\t\tif i%prime != 0 {\n\t\t\tdst &lt;- i  // Send 'i' to channel 'dst'.\n\t\t}\n\t}\n}\n\n// The prime sieve: Daisy-chain filter processes together.\nfunc sieve() {\n\tch := make(chan int)  // Create a new channel.\n\tgo generate(ch)       // Start generate() as a subprocess.\n\tfor {\n\t\tprime := &lt;-ch\n\t\tfmt.Print(prime, \"\\n\")\n\t\tch1 := make(chan int)\n\t\tgo filter(ch, ch1, prime)\n\t\tch = ch1\n\t}\n}\n\nfunc main() {\n\tsieve()\n}\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        theme: \"elegant\",\n        matchBrackets: true,\n        indentUnit: 8,\n        tabSize: 8,\n        indentWithTabs: true,\n        mode: \"text/x-go\"\n      });\n    </script>\n\n    <p><strong>MIME type:</strong> <code>text/x-go</code></p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/groovy/groovy.js",
    "content": "CodeMirror.defineMode(\"groovy\", function(config, parserConfig) {\n  function words(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n  var keywords = words(\n    \"abstract as assert boolean break byte case catch char class const continue def default \" +\n    \"do double else enum extends final finally float for goto if implements import in \" +\n    \"instanceof int interface long native new package private protected public return \" +\n    \"short static strictfp super switch synchronized threadsafe throw throws transient \" +\n    \"try void volatile while\");\n  var blockKeywords = words(\"catch class do else finally for if switch try while enum interface def\");\n  var atoms = words(\"null true false this\");\n\n  var curPunc;\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\") {\n      return startString(ch, stream, state);\n    }\n    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      curPunc = ch;\n      return null\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      if (stream.eat(/eE/)) { stream.eat(/\\+\\-/); stream.eatWhile(/\\d/); }\n      return \"number\";\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize.push(tokenComment);\n        return tokenComment(stream, state);\n      }\n      if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n      if (expectExpression(state.lastToken)) {\n        return startString(ch, stream, state);\n      }\n    }\n    if (ch == \"-\" && stream.eat(\">\")) {\n      curPunc = \"->\";\n      return null;\n    }\n    if (/[+\\-*&%=<>!?|\\/~]/.test(ch)) {\n      stream.eatWhile(/[+\\-*&%=<>|~]/);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_]/);\n    if (ch == \"@\") { stream.eatWhile(/[\\w\\$_\\.]/); return \"meta\"; }\n    if (state.lastToken == \".\") return \"property\";\n    if (stream.eat(\":\")) { curPunc = \"proplabel\"; return \"property\"; }\n    var cur = stream.current();\n    if (atoms.propertyIsEnumerable(cur)) { return \"atom\"; }\n    if (keywords.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"keyword\";\n    }\n    return \"word\";\n  }\n  tokenBase.isBase = true;\n\n  function startString(quote, stream, state) {\n    var tripleQuoted = false;\n    if (quote != \"/\" && stream.eat(quote)) {\n      if (stream.eat(quote)) tripleQuoted = true;\n      else return \"string\";\n    }\n    function t(stream, state) {\n      var escaped = false, next, end = !tripleQuoted;\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) {\n          if (!tripleQuoted) { break; }\n          if (stream.match(quote + quote)) { end = true; break; }\n        }\n        if (quote == '\"' && next == \"$\" && !escaped && stream.eat(\"{\")) {\n          state.tokenize.push(tokenBaseUntilBrace());\n          return \"string\";\n        }\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end) state.tokenize.pop();\n      return \"string\";\n    }\n    state.tokenize.push(t);\n    return t(stream, state);\n  }\n\n  function tokenBaseUntilBrace() {\n    var depth = 1;\n    function t(stream, state) {\n      if (stream.peek() == \"}\") {\n        depth--;\n        if (depth == 0) {\n          state.tokenize.pop();\n          return state.tokenize[state.tokenize.length-1](stream, state);\n        }\n      } else if (stream.peek() == \"{\") {\n        depth++;\n      }\n      return tokenBase(stream, state);\n    }\n    t.isBase = true;\n    return t;\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize.pop();\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function expectExpression(last) {\n    return !last || last == \"operator\" || last == \"->\" || /[\\.\\[\\{\\(,;:]/.test(last) ||\n      last == \"newstatement\" || last == \"keyword\" || last == \"proplabel\";\n  }\n\n  function Context(indented, column, type, align, prev) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.align = align;\n    this.prev = prev;\n  }\n  function pushContext(state, col, type) {\n    return state.context = new Context(state.indented, col, type, null, state.context);\n  }\n  function popContext(state) {\n    var t = state.context.type;\n    if (t == \")\" || t == \"]\" || t == \"}\")\n      state.indented = state.context.indented;\n    return state.context = state.context.prev;\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: [tokenBase],\n        context: new Context((basecolumn || 0) - config.indentUnit, 0, \"top\", false),\n        indented: 0,\n        startOfLine: true,\n        lastToken: null\n      };\n    },\n\n    token: function(stream, state) {\n      var ctx = state.context;\n      if (stream.sol()) {\n        if (ctx.align == null) ctx.align = false;\n        state.indented = stream.indentation();\n        state.startOfLine = true;\n        // Automatic semicolon insertion\n        if (ctx.type == \"statement\" && !expectExpression(state.lastToken)) {\n          popContext(state); ctx = state.context;\n        }\n      }\n      if (stream.eatSpace()) return null;\n      curPunc = null;\n      var style = state.tokenize[state.tokenize.length-1](stream, state);\n      if (style == \"comment\") return style;\n      if (ctx.align == null) ctx.align = true;\n\n      if ((curPunc == \";\" || curPunc == \":\") && ctx.type == \"statement\") popContext(state);\n      // Handle indentation for {x -> \\n ... }\n      else if (curPunc == \"->\" && ctx.type == \"statement\" && ctx.prev.type == \"}\") {\n        popContext(state);\n        state.context.align = false;\n      }\n      else if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n      else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n      else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n      else if (curPunc == \"}\") {\n        while (ctx.type == \"statement\") ctx = popContext(state);\n        if (ctx.type == \"}\") ctx = popContext(state);\n        while (ctx.type == \"statement\") ctx = popContext(state);\n      }\n      else if (curPunc == ctx.type) popContext(state);\n      else if (ctx.type == \"}\" || ctx.type == \"top\" || (ctx.type == \"statement\" && curPunc == \"newstatement\"))\n        pushContext(state, stream.column(), \"statement\");\n      state.startOfLine = false;\n      state.lastToken = curPunc || style;\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (!state.tokenize[state.tokenize.length-1].isBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;\n      if (ctx.type == \"statement\" && !expectExpression(state.lastToken)) ctx = ctx.prev;\n      var closing = firstChar == ctx.type;\n      if (ctx.type == \"statement\") return ctx.indented + (firstChar == \"{\" ? 0 : config.indentUnit);\n      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indented + (closing ? 0 : config.indentUnit);\n    },\n\n    electricChars: \"{}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-groovy\", \"groovy\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/groovy/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Groovy mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"groovy.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style>.CodeMirror {border-top: 1px solid #500; border-bottom: 1px solid #500;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: Groovy mode</h1>\n\n<form><textarea id=\"code\" name=\"code\">\n//Pattern for groovy script\ndef p = ~/.*\\.groovy/\nnew File( 'd:\\\\scripts' ).eachFileMatch(p) {f ->\n  // imports list\n  def imports = []\n  f.eachLine {\n    // condition to detect an import instruction\n    ln -> if ( ln =~ '^import .*' ) {\n      imports << \"${ln - 'import '}\"\n    }\n  }\n  // print thmen\n  if ( ! imports.empty ) {\n    println f\n    imports.each{ println \"   $it\" }\n  }\n}\n\n/* Coin changer demo code from http://groovy.codehaus.org */\n\nenum UsCoin {\n  quarter(25), dime(10), nickel(5), penny(1)\n  UsCoin(v) { value = v }\n  final value\n}\n\nenum OzzieCoin {\n  fifty(50), twenty(20), ten(10), five(5)\n  OzzieCoin(v) { value = v }\n  final value\n}\n\ndef plural(word, count) {\n  if (count == 1) return word\n  word[-1] == 'y' ? word[0..-2] + \"ies\" : word + \"s\"\n}\n\ndef change(currency, amount) {\n  currency.values().inject([]){ list, coin ->\n     int count = amount / coin.value\n     amount = amount % coin.value\n     list += \"$count ${plural(coin.toString(), count)}\"\n  }\n}\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-groovy\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-groovy</code></p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/haskell/haskell.js",
    "content": "CodeMirror.defineMode(\"haskell\", function(cmCfg, modeCfg) {\n\n  function switchState(source, setState, f) {\n    setState(f);\n    return f(source, setState);\n  }\n  \n  // These should all be Unicode extended, as per the Haskell 2010 report\n  var smallRE = /[a-z_]/;\n  var largeRE = /[A-Z]/;\n  var digitRE = /[0-9]/;\n  var hexitRE = /[0-9A-Fa-f]/;\n  var octitRE = /[0-7]/;\n  var idRE = /[a-z_A-Z0-9']/;\n  var symbolRE = /[-!#$%&*+.\\/<=>?@\\\\^|~:]/;\n  var specialRE = /[(),;[\\]`{}]/;\n  var whiteCharRE = /[ \\t\\v\\f]/; // newlines are handled in tokenizer\n    \n  function normal(source, setState) {\n    if (source.eatWhile(whiteCharRE)) {\n      return null;\n    }\n      \n    var ch = source.next();\n    if (specialRE.test(ch)) {\n      if (ch == '{' && source.eat('-')) {\n        var t = \"comment\";\n        if (source.eat('#')) {\n          t = \"meta\";\n        }\n        return switchState(source, setState, ncomment(t, 1));\n      }\n      return null;\n    }\n    \n    if (ch == '\\'') {\n      if (source.eat('\\\\')) {\n        source.next();  // should handle other escapes here\n      }\n      else {\n        source.next();\n      }\n      if (source.eat('\\'')) {\n        return \"string\";\n      }\n      return \"error\";\n    }\n    \n    if (ch == '\"') {\n      return switchState(source, setState, stringLiteral);\n    }\n      \n    if (largeRE.test(ch)) {\n      source.eatWhile(idRE);\n      if (source.eat('.')) {\n        return \"qualifier\";\n      }\n      return \"variable-2\";\n    }\n      \n    if (smallRE.test(ch)) {\n      source.eatWhile(idRE);\n      return \"variable\";\n    }\n      \n    if (digitRE.test(ch)) {\n      if (ch == '0') {\n        if (source.eat(/[xX]/)) {\n          source.eatWhile(hexitRE); // should require at least 1\n          return \"integer\";\n        }\n        if (source.eat(/[oO]/)) {\n          source.eatWhile(octitRE); // should require at least 1\n          return \"number\";\n        }\n      }\n      source.eatWhile(digitRE);\n      var t = \"number\";\n      if (source.eat('.')) {\n        t = \"number\";\n        source.eatWhile(digitRE); // should require at least 1\n      }\n      if (source.eat(/[eE]/)) {\n        t = \"number\";\n        source.eat(/[-+]/);\n        source.eatWhile(digitRE); // should require at least 1\n      }\n      return t;\n    }\n      \n    if (symbolRE.test(ch)) {\n      if (ch == '-' && source.eat(/-/)) {\n        source.eatWhile(/-/);\n        if (!source.eat(symbolRE)) {\n          source.skipToEnd();\n          return \"comment\";\n        }\n      }\n      var t = \"variable\";\n      if (ch == ':') {\n        t = \"variable-2\";\n      }\n      source.eatWhile(symbolRE);\n      return t;    \n    }\n      \n    return \"error\";\n  }\n    \n  function ncomment(type, nest) {\n    if (nest == 0) {\n      return normal;\n    }\n    return function(source, setState) {\n      var currNest = nest;\n      while (!source.eol()) {\n        var ch = source.next();\n        if (ch == '{' && source.eat('-')) {\n          ++currNest;\n        }\n        else if (ch == '-' && source.eat('}')) {\n          --currNest;\n          if (currNest == 0) {\n            setState(normal);\n            return type;\n          }\n        }\n      }\n      setState(ncomment(type, currNest));\n      return type;\n    }\n  }\n    \n  function stringLiteral(source, setState) {\n    while (!source.eol()) {\n      var ch = source.next();\n      if (ch == '\"') {\n        setState(normal);\n        return \"string\";\n      }\n      if (ch == '\\\\') {\n        if (source.eol() || source.eat(whiteCharRE)) {\n          setState(stringGap);\n          return \"string\";\n        }\n        if (source.eat('&')) {\n        }\n        else {\n          source.next(); // should handle other escapes here\n        }\n      }\n    }\n    setState(normal);\n    return \"error\";\n  }\n  \n  function stringGap(source, setState) {\n    if (source.eat('\\\\')) {\n      return switchState(source, setState, stringLiteral);\n    }\n    source.next();\n    setState(normal);\n    return \"error\";\n  }\n  \n  \n  var wellKnownWords = (function() {\n    var wkw = {};\n    function setType(t) {\n      return function () {\n        for (var i = 0; i < arguments.length; i++)\n          wkw[arguments[i]] = t;\n      }\n    }\n    \n    setType(\"keyword\")(\n      \"case\", \"class\", \"data\", \"default\", \"deriving\", \"do\", \"else\", \"foreign\",\n      \"if\", \"import\", \"in\", \"infix\", \"infixl\", \"infixr\", \"instance\", \"let\",\n      \"module\", \"newtype\", \"of\", \"then\", \"type\", \"where\", \"_\");\n      \n    setType(\"keyword\")(\n      \"\\.\\.\", \":\", \"::\", \"=\", \"\\\\\", \"\\\"\", \"<-\", \"->\", \"@\", \"~\", \"=>\");\n      \n    setType(\"builtin\")(\n      \"!!\", \"$!\", \"$\", \"&&\", \"+\", \"++\", \"-\", \".\", \"/\", \"/=\", \"<\", \"<=\", \"=<<\",\n      \"==\", \">\", \">=\", \">>\", \">>=\", \"^\", \"^^\", \"||\", \"*\", \"**\");\n      \n    setType(\"builtin\")(\n      \"Bool\", \"Bounded\", \"Char\", \"Double\", \"EQ\", \"Either\", \"Enum\", \"Eq\",\n      \"False\", \"FilePath\", \"Float\", \"Floating\", \"Fractional\", \"Functor\", \"GT\",\n      \"IO\", \"IOError\", \"Int\", \"Integer\", \"Integral\", \"Just\", \"LT\", \"Left\",\n      \"Maybe\", \"Monad\", \"Nothing\", \"Num\", \"Ord\", \"Ordering\", \"Rational\", \"Read\",\n      \"ReadS\", \"Real\", \"RealFloat\", \"RealFrac\", \"Right\", \"Show\", \"ShowS\",\n      \"String\", \"True\");\n      \n    setType(\"builtin\")(\n      \"abs\", \"acos\", \"acosh\", \"all\", \"and\", \"any\", \"appendFile\", \"asTypeOf\",\n      \"asin\", \"asinh\", \"atan\", \"atan2\", \"atanh\", \"break\", \"catch\", \"ceiling\",\n      \"compare\", \"concat\", \"concatMap\", \"const\", \"cos\", \"cosh\", \"curry\",\n      \"cycle\", \"decodeFloat\", \"div\", \"divMod\", \"drop\", \"dropWhile\", \"either\",\n      \"elem\", \"encodeFloat\", \"enumFrom\", \"enumFromThen\", \"enumFromThenTo\",\n      \"enumFromTo\", \"error\", \"even\", \"exp\", \"exponent\", \"fail\", \"filter\",\n      \"flip\", \"floatDigits\", \"floatRadix\", \"floatRange\", \"floor\", \"fmap\",\n      \"foldl\", \"foldl1\", \"foldr\", \"foldr1\", \"fromEnum\", \"fromInteger\",\n      \"fromIntegral\", \"fromRational\", \"fst\", \"gcd\", \"getChar\", \"getContents\",\n      \"getLine\", \"head\", \"id\", \"init\", \"interact\", \"ioError\", \"isDenormalized\",\n      \"isIEEE\", \"isInfinite\", \"isNaN\", \"isNegativeZero\", \"iterate\", \"last\",\n      \"lcm\", \"length\", \"lex\", \"lines\", \"log\", \"logBase\", \"lookup\", \"map\",\n      \"mapM\", \"mapM_\", \"max\", \"maxBound\", \"maximum\", \"maybe\", \"min\", \"minBound\",\n      \"minimum\", \"mod\", \"negate\", \"not\", \"notElem\", \"null\", \"odd\", \"or\",\n      \"otherwise\", \"pi\", \"pred\", \"print\", \"product\", \"properFraction\",\n      \"putChar\", \"putStr\", \"putStrLn\", \"quot\", \"quotRem\", \"read\", \"readFile\",\n      \"readIO\", \"readList\", \"readLn\", \"readParen\", \"reads\", \"readsPrec\",\n      \"realToFrac\", \"recip\", \"rem\", \"repeat\", \"replicate\", \"return\", \"reverse\",\n      \"round\", \"scaleFloat\", \"scanl\", \"scanl1\", \"scanr\", \"scanr1\", \"seq\",\n      \"sequence\", \"sequence_\", \"show\", \"showChar\", \"showList\", \"showParen\",\n      \"showString\", \"shows\", \"showsPrec\", \"significand\", \"signum\", \"sin\",\n      \"sinh\", \"snd\", \"span\", \"splitAt\", \"sqrt\", \"subtract\", \"succ\", \"sum\",\n      \"tail\", \"take\", \"takeWhile\", \"tan\", \"tanh\", \"toEnum\", \"toInteger\",\n      \"toRational\", \"truncate\", \"uncurry\", \"undefined\", \"unlines\", \"until\",\n      \"unwords\", \"unzip\", \"unzip3\", \"userError\", \"words\", \"writeFile\", \"zip\",\n      \"zip3\", \"zipWith\", \"zipWith3\");\n      \n    return wkw;\n  })();\n    \n  \n  \n  return {\n    startState: function ()  { return { f: normal }; },\n    copyState:  function (s) { return { f: s.f }; },\n    \n    token: function(stream, state) {\n      var t = state.f(stream, function(s) { state.f = s; });\n      var w = stream.current();\n      return (w in wellKnownWords) ? wellKnownWords[w] : t;\n    }\n  };\n\n});\n\nCodeMirror.defineMIME(\"text/x-haskell\", \"haskell\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/haskell/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Haskell mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"haskell.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../theme/elegant.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Haskell mode</h1>\n\n<form><textarea id=\"code\" name=\"code\">\nmodule UniquePerms (\n    uniquePerms\n    )\nwhere\n\n-- | Find all unique permutations of a list where there might be duplicates.\nuniquePerms :: (Eq a) => [a] -> [[a]]\nuniquePerms = permBag . makeBag\n\n-- | An unordered collection where duplicate values are allowed,\n-- but represented with a single value and a count.\ntype Bag a = [(a, Int)]\n\nmakeBag :: (Eq a) => [a] -> Bag a\nmakeBag [] = []\nmakeBag (a:as) = mix a $ makeBag as\n  where\n    mix a []                        = [(a,1)]\n    mix a (bn@(b,n):bs) | a == b    = (b,n+1):bs\n                        | otherwise = bn : mix a bs\n\npermBag :: Bag a -> [[a]]\npermBag [] = [[]]\npermBag bs = concatMap (\\(f,cs) -> map (f:) $ permBag cs) . oneOfEach $ bs\n  where\n    oneOfEach [] = []\n    oneOfEach (an@(a,n):bs) =\n        let bs' = if n == 1 then bs else (a,n-1):bs\n        in (a,bs') : mapSnd (an:) (oneOfEach bs)\n    \n    apSnd f (a,b) = (a, f b)\n    mapSnd = map . apSnd\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        theme: \"elegant\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-haskell</code>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/htmlembedded/htmlembedded.js",
    "content": "CodeMirror.defineMode(\"htmlembedded\", function(config, parserConfig) {\n  \n  //config settings\n  var scriptStartRegex = parserConfig.scriptStartRegex || /^<%/i,\n      scriptEndRegex = parserConfig.scriptEndRegex || /^%>/i;\n  \n  //inner modes\n  var scriptingMode, htmlMixedMode;\n  \n  //tokenizer when in html mode\n  function htmlDispatch(stream, state) {\n      if (stream.match(scriptStartRegex, false)) {\n          state.token=scriptingDispatch;\n          return scriptingMode.token(stream, state.scriptState);\n          }\n      else\n          return htmlMixedMode.token(stream, state.htmlState);\n    }\n\n  //tokenizer when in scripting mode\n  function scriptingDispatch(stream, state) {\n      if (stream.match(scriptEndRegex, false))  {\n          state.token=htmlDispatch;\n          return htmlMixedMode.token(stream, state.htmlState);\n         }\n      else\n          return scriptingMode.token(stream, state.scriptState);\n         }\n\n\n  return {\n    startState: function() {\n      scriptingMode = scriptingMode || CodeMirror.getMode(config, parserConfig.scriptingModeSpec);\n      htmlMixedMode = htmlMixedMode || CodeMirror.getMode(config, \"htmlmixed\");\n      return { \n          token :  parserConfig.startOpen ? scriptingDispatch : htmlDispatch,\n          htmlState : htmlMixedMode.startState(),\n          scriptState : scriptingMode.startState()\n          }\n    },\n\n    token: function(stream, state) {\n      return state.token(stream, state);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.token == htmlDispatch)\n        return htmlMixedMode.indent(state.htmlState, textAfter);\n      else\n        return scriptingMode.indent(state.scriptState, textAfter);\n    },\n    \n    copyState: function(state) {\n      return {\n       token : state.token,\n       htmlState : CodeMirror.copyState(htmlMixedMode, state.htmlState),\n       scriptState : CodeMirror.copyState(scriptingMode, state.scriptState)\n       }\n    },\n    \n\n    electricChars: \"/{}:\"\n  }\n}, \"htmlmixed\");\n\nCodeMirror.defineMIME(\"application/x-ejs\", { name: \"htmlembedded\", scriptingModeSpec:\"javascript\"});\nCodeMirror.defineMIME(\"application/x-aspx\", { name: \"htmlembedded\", scriptingModeSpec:\"text/x-csharp\"});\nCodeMirror.defineMIME(\"application/x-jsp\", { name: \"htmlembedded\", scriptingModeSpec:\"text/x-java\"});\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/htmlembedded/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Html Embedded Scripts mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"../xml/xml.js\"></script>\n    <script src=\"../javascript/javascript.js\"></script>\n    <script src=\"../css/css.js\"></script>\n    <script src=\"../htmlmixed/htmlmixed.js\"></script>\n    <script src=\"htmlembedded.js\"></script>\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Html Embedded Scripts mode</h1>\n\n<form><textarea id=\"code\" name=\"code\">\n<%\nfunction hello(who) {\n\treturn \"Hello \" + who;\n}\n%>\nThis is an example of EJS (embedded javascript)\n<p>The program says <%= hello(\"world\") %>.</p>\n<script>\n\talert(\"And here is some normal JS code\"); // also colored\n</script>\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"application/x-ejs\",\n        indentUnit: 4,\n        indentWithTabs: true,\n        enterMode: \"keep\",\n        tabMode: \"shift\"\n      });\n    </script>\n\n    <p>Mode for html embedded scripts like JSP and ASP.NET. Depends on HtmlMixed which in turn depends on\n    JavaScript, CSS and XML.<br />Other dependancies include those of the scriping language chosen.</p>\n\n    <p><strong>MIME types defined:</strong> <code>application/x-aspx</code> (ASP.NET), \n    <code>application/x-ejs</code> (Embedded Javascript), <code>application/x-jsp</code> (JavaServer Pages)</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/htmlmixed/htmlmixed.js",
    "content": "CodeMirror.defineMode(\"htmlmixed\", function(config, parserConfig) {\n  var htmlMode = CodeMirror.getMode(config, {name: \"xml\", htmlMode: true});\n  var jsMode = CodeMirror.getMode(config, \"javascript\");\n  var cssMode = CodeMirror.getMode(config, \"css\");\n\n  function html(stream, state) {\n    var style = htmlMode.token(stream, state.htmlState);\n    if (style == \"tag\" && stream.current() == \">\" && state.htmlState.context) {\n      if (/^script$/i.test(state.htmlState.context.tagName)) {\n        state.token = javascript;\n        state.localState = jsMode.startState(htmlMode.indent(state.htmlState, \"\"));\n        state.mode = \"javascript\";\n      }\n      else if (/^style$/i.test(state.htmlState.context.tagName)) {\n        state.token = css;\n        state.localState = cssMode.startState(htmlMode.indent(state.htmlState, \"\"));\n        state.mode = \"css\";\n      }\n    }\n    return style;\n  }\n  function maybeBackup(stream, pat, style) {\n    var cur = stream.current();\n    var close = cur.search(pat);\n    if (close > -1) stream.backUp(cur.length - close);\n    return style;\n  }\n  function javascript(stream, state) {\n    if (stream.match(/^<\\/\\s*script\\s*>/i, false)) {\n      state.token = html;\n      state.localState = null;\n      state.mode = \"html\";\n      return html(stream, state);\n    }\n    return maybeBackup(stream, /<\\/\\s*script\\s*>/,\n                       jsMode.token(stream, state.localState));\n  }\n  function css(stream, state) {\n    if (stream.match(/^<\\/\\s*style\\s*>/i, false)) {\n      state.token = html;\n      state.localState = null;\n      state.mode = \"html\";\n      return html(stream, state);\n    }\n    return maybeBackup(stream, /<\\/\\s*style\\s*>/,\n                       cssMode.token(stream, state.localState));\n  }\n\n  return {\n    startState: function() {\n      var state = htmlMode.startState();\n      return {token: html, localState: null, mode: \"html\", htmlState: state};\n    },\n\n    copyState: function(state) {\n      if (state.localState)\n        var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState);\n      return {token: state.token, localState: local, mode: state.mode,\n              htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};\n    },\n\n    token: function(stream, state) {\n      return state.token(stream, state);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.token == html || /^\\s*<\\//.test(textAfter))\n        return htmlMode.indent(state.htmlState, textAfter);\n      else if (state.token == javascript)\n        return jsMode.indent(state.localState, textAfter);\n      else\n        return cssMode.indent(state.localState, textAfter);\n    },\n\n    compareStates: function(a, b) {\n      if (a.mode != b.mode) return false;\n      if (a.localState) return CodeMirror.Pass;\n      return htmlMode.compareStates(a.htmlState, b.htmlState);\n    },\n\n    electricChars: \"/{}:\"\n  }\n}, \"xml\", \"javascript\", \"css\");\n\nCodeMirror.defineMIME(\"text/html\", \"htmlmixed\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/htmlmixed/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: HTML mixed mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"../xml/xml.js\"></script>\n    <script src=\"../javascript/javascript.js\"></script>\n    <script src=\"../css/css.js\"></script>\n    <script src=\"htmlmixed.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: HTML mixed mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n<html style=\"color: green\">\n  <!-- this is a comment -->\n  <head>\n    <title>Mixed HTML Example</title>\n    <style type=\"text/css\">\n      h1 {font-family: comic sans; color: #f0f;}\n      div {background: yellow !important;}\n      body {\n        max-width: 50em;\n        margin: 1em 2em 1em 5em;\n      }\n    </style>\n  </head>\n  <body>\n    <h1>Mixed HTML Example</h1>\n    <script>\n      function jsFunc(arg1, arg2) {\n        if (arg1 && arg2) document.body.innerHTML = \"achoo\";\n      }\n    </script>\n  </body>\n</html>\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {mode: \"text/html\", tabMode: \"indent\"});\n    </script>\n\n    <p>The HTML mixed mode depends on the XML, JavaScript, and CSS modes.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/html</code>\n    (redefined, only takes effect if you load this parser after the\n    XML parser).</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/javascript/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: JavaScript mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"javascript.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: JavaScript mode</h1>\n\n<div><textarea id=\"code\" name=\"code\">\n// Demo code (the actual new parser character stream implementation)\n\nfunction StringStream(string) {\n  this.pos = 0;\n  this.string = string;\n}\n\nStringStream.prototype = {\n  done: function() {return this.pos >= this.string.length;},\n  peek: function() {return this.string.charAt(this.pos);},\n  next: function() {\n    if (this.pos &lt; this.string.length)\n      return this.string.charAt(this.pos++);\n  },\n  eat: function(match) {\n    var ch = this.string.charAt(this.pos);\n    if (typeof match == \"string\") var ok = ch == match;\n    else var ok = ch &amp;&amp; match.test ? match.test(ch) : match(ch);\n    if (ok) {this.pos++; return ch;}\n  },\n  eatWhile: function(match) {\n    var start = this.pos;\n    while (this.eat(match));\n    if (this.pos > start) return this.string.slice(start, this.pos);\n  },\n  backUp: function(n) {this.pos -= n;},\n  column: function() {return this.pos;},\n  eatSpace: function() {\n    var start = this.pos;\n    while (/\\s/.test(this.string.charAt(this.pos))) this.pos++;\n    return this.pos - start;\n  },\n  match: function(pattern, consume, caseInsensitive) {\n    if (typeof pattern == \"string\") {\n      function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}\n      if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {\n        if (consume !== false) this.pos += str.length;\n        return true;\n      }\n    }\n    else {\n      var match = this.string.slice(this.pos).match(pattern);\n      if (match &amp;&amp; consume !== false) this.pos += match[0].length;\n      return match;\n    }\n  }\n};\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true\n      });\n    </script>\n\n    <p>JavaScript mode supports a single configuration\n    option, <code>json</code>, which will set the mode to expect JSON\n    data rather than a JavaScript program.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/javascript</code>, <code>application/json</code>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/javascript/javascript.js",
    "content": "CodeMirror.defineMode(\"javascript\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var jsonMode = parserConfig.json;\n\n  // Tokenizer\n\n  var keywords = function(){\n    function kw(type) {return {type: type, style: \"keyword\"};}\n    var A = kw(\"keyword a\"), B = kw(\"keyword b\"), C = kw(\"keyword c\");\n    var operator = kw(\"operator\"), atom = {type: \"atom\", style: \"atom\"};\n    return {\n      \"if\": A, \"while\": A, \"with\": A, \"else\": B, \"do\": B, \"try\": B, \"finally\": B,\n      \"return\": C, \"break\": C, \"continue\": C, \"new\": C, \"delete\": C, \"throw\": C,\n      \"var\": kw(\"var\"), \"const\": kw(\"var\"), \"let\": kw(\"var\"),\n      \"function\": kw(\"function\"), \"catch\": kw(\"catch\"),\n      \"for\": kw(\"for\"), \"switch\": kw(\"switch\"), \"case\": kw(\"case\"), \"default\": kw(\"default\"),\n      \"in\": operator, \"typeof\": operator, \"instanceof\": operator,\n      \"true\": atom, \"false\": atom, \"null\": atom, \"undefined\": atom, \"NaN\": atom, \"Infinity\": atom\n    };\n  }();\n\n  var isOperatorChar = /[+\\-*&%=<>!?|]/;\n\n  function chain(stream, state, f) {\n    state.tokenize = f;\n    return f(stream, state);\n  }\n\n  function nextUntilUnescaped(stream, end) {\n    var escaped = false, next;\n    while ((next = stream.next()) != null) {\n      if (next == end && !escaped)\n        return false;\n      escaped = !escaped && next == \"\\\\\";\n    }\n    return escaped;\n  }\n\n  // Used as scratch variables to communicate multiple values without\n  // consing up tons of objects.\n  var type, content;\n  function ret(tp, style, cont) {\n    type = tp; content = cont;\n    return style;\n  }\n\n  function jsTokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"' || ch == \"'\")\n      return chain(stream, state, jsTokenString(ch));\n    else if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch))\n      return ret(ch);\n    else if (ch == \"0\" && stream.eat(/x/i)) {\n      stream.eatWhile(/[\\da-f]/i);\n      return ret(\"number\", \"number\");\n    }      \n    else if (/\\d/.test(ch) || ch == \"-\" && stream.eat(/\\d/)) {\n      stream.match(/^\\d*(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/);\n      return ret(\"number\", \"number\");\n    }\n    else if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        return chain(stream, state, jsTokenComment);\n      }\n      else if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return ret(\"comment\", \"comment\");\n      }\n      else if (state.reAllowed) {\n        nextUntilUnescaped(stream, \"/\");\n        stream.eatWhile(/[gimy]/); // 'y' is \"sticky\" option in Mozilla\n        return ret(\"regexp\", \"string-2\");\n      }\n      else {\n        stream.eatWhile(isOperatorChar);\n        return ret(\"operator\", null, stream.current());\n      }\n    }\n    else if (ch == \"#\") {\n        stream.skipToEnd();\n        return ret(\"error\", \"error\");\n    }\n    else if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return ret(\"operator\", null, stream.current());\n    }\n    else {\n      stream.eatWhile(/[\\w\\$_]/);\n      var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];\n      return (known && state.kwAllowed) ? ret(known.type, known.style, word) :\n                     ret(\"variable\", \"variable\", word);\n    }\n  }\n\n  function jsTokenString(quote) {\n    return function(stream, state) {\n      if (!nextUntilUnescaped(stream, quote))\n        state.tokenize = jsTokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  function jsTokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = jsTokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  // Parser\n\n  var atomicTypes = {\"atom\": true, \"number\": true, \"variable\": true, \"string\": true, \"regexp\": true};\n\n  function JSLexical(indented, column, type, align, prev, info) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.prev = prev;\n    this.info = info;\n    if (align != null) this.align = align;\n  }\n\n  function inScope(state, varname) {\n    for (var v = state.localVars; v; v = v.next)\n      if (v.name == varname) return true;\n  }\n\n  function parseJS(state, style, type, content, stream) {\n    var cc = state.cc;\n    // Communicate our context to the combinators.\n    // (Less wasteful than consing up a hundred closures on every call.)\n    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;\n  \n    if (!state.lexical.hasOwnProperty(\"align\"))\n      state.lexical.align = true;\n\n    while(true) {\n      var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;\n      if (combinator(type, content)) {\n        while(cc.length && cc[cc.length - 1].lex)\n          cc.pop()();\n        if (cx.marked) return cx.marked;\n        if (type == \"variable\" && inScope(state, content)) return \"variable-2\";\n        return style;\n      }\n    }\n  }\n\n  // Combinator utils\n\n  var cx = {state: null, column: null, marked: null, cc: null};\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n  function register(varname) {\n    var state = cx.state;\n    if (state.context) {\n      cx.marked = \"def\";\n      for (var v = state.localVars; v; v = v.next)\n        if (v.name == varname) return;\n      state.localVars = {name: varname, next: state.localVars};\n    }\n  }\n\n  // Combinators\n\n  var defaultVars = {name: \"this\", next: {name: \"arguments\"}};\n  function pushcontext() {\n    if (!cx.state.context) cx.state.localVars = defaultVars;\n    cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};\n  }\n  function popcontext() {\n    cx.state.localVars = cx.state.context.vars;\n    cx.state.context = cx.state.context.prev;\n  }\n  function pushlex(type, info) {\n    var result = function() {\n      var state = cx.state;\n      state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info)\n    };\n    result.lex = true;\n    return result;\n  }\n  function poplex() {\n    var state = cx.state;\n    if (state.lexical.prev) {\n      if (state.lexical.type == \")\")\n        state.indented = state.lexical.indented;\n      state.lexical = state.lexical.prev;\n    }\n  }\n  poplex.lex = true;\n\n  function expect(wanted) {\n    return function expecting(type) {\n      if (type == wanted) return cont();\n      else if (wanted == \";\") return pass();\n      else return cont(arguments.callee);\n    };\n  }\n\n  function statement(type) {\n    if (type == \"var\") return cont(pushlex(\"vardef\"), vardef1, expect(\";\"), poplex);\n    if (type == \"keyword a\") return cont(pushlex(\"form\"), expression, statement, poplex);\n    if (type == \"keyword b\") return cont(pushlex(\"form\"), statement, poplex);\n    if (type == \"{\") return cont(pushlex(\"}\"), block, poplex);\n    if (type == \";\") return cont();\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"for\") return cont(pushlex(\"form\"), expect(\"(\"), pushlex(\")\"), forspec1, expect(\")\"),\n                                      poplex, statement, poplex);\n    if (type == \"variable\") return cont(pushlex(\"stat\"), maybelabel);\n    if (type == \"switch\") return cont(pushlex(\"form\"), expression, pushlex(\"}\", \"switch\"), expect(\"{\"),\n                                         block, poplex, poplex);\n    if (type == \"case\") return cont(expression, expect(\":\"));\n    if (type == \"default\") return cont(expect(\":\"));\n    if (type == \"catch\") return cont(pushlex(\"form\"), pushcontext, expect(\"(\"), funarg, expect(\")\"),\n                                        statement, poplex, popcontext);\n    return pass(pushlex(\"stat\"), expression, expect(\";\"), poplex);\n  }\n  function expression(type) {\n    if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);\n    if (type == \"function\") return cont(functiondef);\n    if (type == \"keyword c\") return cont(maybeexpression);\n    if (type == \"(\") return cont(pushlex(\")\"), maybeexpression, expect(\")\"), poplex, maybeoperator);\n    if (type == \"operator\") return cont(expression);\n    if (type == \"[\") return cont(pushlex(\"]\"), commasep(expression, \"]\"), poplex, maybeoperator);\n    if (type == \"{\") return cont(pushlex(\"}\"), commasep(objprop, \"}\"), poplex, maybeoperator);\n    return cont();\n  }\n  function maybeexpression(type) {\n    if (type.match(/[;\\}\\)\\],]/)) return pass();\n    return pass(expression);\n  }\n    \n  function maybeoperator(type, value) {\n    if (type == \"operator\" && /\\+\\+|--/.test(value)) return cont(maybeoperator);\n    if (type == \"operator\" || type == \":\") return cont(expression);\n    if (type == \";\") return;\n    if (type == \"(\") return cont(pushlex(\")\"), commasep(expression, \")\"), poplex, maybeoperator);\n    if (type == \".\") return cont(property, maybeoperator);\n    if (type == \"[\") return cont(pushlex(\"]\"), expression, expect(\"]\"), poplex, maybeoperator);\n  }\n  function maybelabel(type) {\n    if (type == \":\") return cont(poplex, statement);\n    return pass(maybeoperator, expect(\";\"), poplex);\n  }\n  function property(type) {\n    if (type == \"variable\") {cx.marked = \"property\"; return cont();}\n  }\n  function objprop(type) {\n    if (type == \"variable\") cx.marked = \"property\";\n    if (atomicTypes.hasOwnProperty(type)) return cont(expect(\":\"), expression);\n  }\n  function commasep(what, end) {\n    function proceed(type) {\n      if (type == \",\") return cont(what, proceed);\n      if (type == end) return cont();\n      return cont(expect(end));\n    }\n    return function commaSeparated(type) {\n      if (type == end) return cont();\n      else return pass(what, proceed);\n    };\n  }\n  function block(type) {\n    if (type == \"}\") return cont();\n    return pass(statement, block);\n  }\n  function vardef1(type, value) {\n    if (type == \"variable\"){register(value); return cont(vardef2);}\n    return cont();\n  }\n  function vardef2(type, value) {\n    if (value == \"=\") return cont(expression, vardef2);\n    if (type == \",\") return cont(vardef1);\n  }\n  function forspec1(type) {\n    if (type == \"var\") return cont(vardef1, forspec2);\n    if (type == \";\") return pass(forspec2);\n    if (type == \"variable\") return cont(formaybein);\n    return pass(forspec2);\n  }\n  function formaybein(type, value) {\n    if (value == \"in\") return cont(expression);\n    return cont(maybeoperator, forspec2);\n  }\n  function forspec2(type, value) {\n    if (type == \";\") return cont(forspec3);\n    if (value == \"in\") return cont(expression);\n    return cont(expression, expect(\";\"), forspec3);\n  }\n  function forspec3(type) {\n    if (type != \")\") cont(expression);\n  }\n  function functiondef(type, value) {\n    if (type == \"variable\") {register(value); return cont(functiondef);}\n    if (type == \"(\") return cont(pushlex(\")\"), pushcontext, commasep(funarg, \")\"), poplex, statement, popcontext);\n  }\n  function funarg(type, value) {\n    if (type == \"variable\") {register(value); return cont();}\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: jsTokenBase,\n        reAllowed: true,\n        kwAllowed: true,\n        cc: [],\n        lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, \"block\", false),\n        localVars: parserConfig.localVars,\n        context: parserConfig.localVars && {vars: parserConfig.localVars},\n        indented: 0\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (!state.lexical.hasOwnProperty(\"align\"))\n          state.lexical.align = false;\n        state.indented = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      if (type == \"comment\") return style;\n      state.reAllowed = !!(type == \"operator\" || type == \"keyword c\" || type.match(/^[\\[{}\\(,;:]$/));\n      state.kwAllowed = type != '.';\n      return parseJS(state, style, type, content, stream);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != jsTokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;\n      if (lexical.type == \"stat\" && firstChar == \"}\") lexical = lexical.prev;\n      var type = lexical.type, closing = firstChar == type;\n      if (type == \"vardef\") return lexical.indented + 4;\n      else if (type == \"form\" && firstChar == \"{\") return lexical.indented;\n      else if (type == \"stat\" || type == \"form\") return lexical.indented + indentUnit;\n      else if (lexical.info == \"switch\" && !closing)\n        return lexical.indented + (/^(?:case|default)\\b/.test(textAfter) ? indentUnit : 2 * indentUnit);\n      else if (lexical.align) return lexical.column + (closing ? 0 : 1);\n      else return lexical.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \":{}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/javascript\", \"javascript\");\nCodeMirror.defineMIME(\"application/json\", {name: \"javascript\", json: true});\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/jinja2/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Jinja2 mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"jinja2.js\"></script>\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Jinja2 mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n&lt;html style=\"color: green\"&gt;\n  &lt;!-- this is a comment --&gt;\n  &lt;head&gt;\n    &lt;title&gt;Jinja2 Example&lt;/title&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n    &lt;ul&gt;\n    {# this is a comment #}\n    {%- for item in li -%}\n      &lt;li&gt;\n        {{ item.label }}\n      &lt;/li&gt;\n    {% endfor -%}\n    &lt;/ul&gt;\n  &lt;/body&gt;\n&lt;/html&gt;\n</textarea></form>\n    <script>\n      var editor =\n      CodeMirror.fromTextArea(document.getElementById(\"code\"), {mode:\n        {name: \"jinja2\", htmlMode: true}});\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/jinja2/jinja2.js",
    "content": "CodeMirror.defineMode(\"jinja2\", function(config, parserConf) {\n    var keywords = [\"block\", \"endblock\", \"for\", \"endfor\", \"in\", \"true\", \"false\", \n                    \"loop\", \"none\", \"self\", \"super\", \"if\", \"as\", \"not\", \"and\",\n                    \"else\", \"import\", \"with\", \"without\", \"context\"];\n    keywords = new RegExp(\"^((\" + keywords.join(\")|(\") + \"))\\\\b\");\n\n    function tokenBase (stream, state) {\n        var ch = stream.next();\n        if (ch == \"{\") {\n            if (ch = stream.eat(/\\{|%|#/)) {\n                stream.eat(\"-\");\n                state.tokenize = inTag(ch);\n                return \"tag\";\n            }\n        }\n    }\n    function inTag (close) {\n        if (close == \"{\") {\n            close = \"}\";\n        }\n        return function (stream, state) {\n            var ch = stream.next();\n            if ((ch == close || (ch == \"-\" && stream.eat(close)))\n                && stream.eat(\"}\")) {\n                state.tokenize = tokenBase;\n                return \"tag\";\n            }\n            if (stream.match(keywords)) {\n                return \"keyword\";\n            }\n            return close == \"#\" ? \"comment\" : \"string\";\n        };\n    }\n    return {\n        startState: function () {\n            return {tokenize: tokenBase};\n        },\n        token: function (stream, state) {\n            return state.tokenize(stream, state);\n        }\n    }; \n});\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/less/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: LESS mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"less.js\"></script>\n    <style>.CodeMirror {background: #f8f8f8; border: 1px solid #ddd;} .CodeMirror-scroll {height: 400px}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <link rel=\"stylesheet\" href=\"../../theme/lesser-dark.css\">\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n  </head>\n  <body>\n    <h1>CodeMirror: LESS mode</h1>\n    <form><textarea id=\"code\" name=\"code\">/* Some LESS code */\n\nbutton {\n    width:  32px;\n    height: 32px;\n    border: 0;\n    margin: 4px;\n    cursor: pointer;\n}\nbutton.icon-plus { background: url(http://dahlström.net/tmp/sharp-icons/svg-icon-target.svg#plus) no-repeat; }\nbutton.icon-chart { background: url(http://dahlström.net/tmp/sharp-icons/svg-icon-target.svg#chart) no-repeat; }\n\nbutton:hover { background-color: #999; }\nbutton:active { background-color: #666; }\n\n@test_a: #eeeQQQ;//this is not a valid hex value and thus parsed as an element id\n@test_b: #eeeFFF //this is a valid hex value but the declaration doesn't end with a semicolon and thus parsed as an element id\n\n#eee aaa .box\n{\n  #test bbb {\n    width: 500px;\n    height: 250px;\n    background-image: url(dir/output/sheep.png), url( betweengrassandsky.png );\n    background-position: center bottom, left top;\n    background-repeat: no-repeat;\n  }\n}\n\n@base: #f938ab;\n\n.box-shadow(@style, @c) when (iscolor(@c)) {\n  box-shadow:         @style @c;\n  -webkit-box-shadow: @style @c;\n  -moz-box-shadow:    @style @c;\n}\n.box-shadow(@style, @alpha: 50%) when (isnumber(@alpha)) {\n  .box-shadow(@style, rgba(0, 0, 0, @alpha));\n}\n\n@color: #4D926F;\n\n#header {\n  color: @color;\n  color: #000000;\n}\nh2 {\n  color: @color;\n}\n\n.rounded-corners (@radius: 5px) {\n  border-radius: @radius;\n  -webkit-border-radius: @radius;\n  -moz-border-radius: @radius;\n}\n\n#header {\n  .rounded-corners;\n}\n#footer {\n  .rounded-corners(10px);\n}\n\n.box-shadow (@x: 0, @y: 0, @blur: 1px, @alpha) {\n  @val: @x @y @blur rgba(0, 0, 0, @alpha);\n\n  box-shadow:         @val;\n  -webkit-box-shadow: @val;\n  -moz-box-shadow:    @val;\n}\n.box { @base: #f938ab;\n  color:        saturate(@base, 5%);\n  border-color: lighten(@base, 30%);\n  div { .box-shadow(0, 0, 5px, 0.4) }\n}\n\n@import url(\"something.css\");\n\n@light-blue:   hsl(190, 50%, 65%);\n@light-yellow: desaturate(#fefec8, 10%);\n@dark-yellow:  desaturate(darken(@light-yellow, 10%), 40%);\n@darkest:      hsl(20, 0%, 15%);\n@dark:         hsl(190, 20%, 30%);\n@medium:       hsl(10, 60%, 30%);\n@light:        hsl(90, 40%, 20%);\n@lightest:     hsl(90, 20%, 90%);\n@highlight:    hsl(80, 50%, 90%);\n@blue:         hsl(210, 60%, 20%);\n@alpha-blue:   hsla(210, 60%, 40%, 0.5);\n\n.box-shadow (@x, @y, @blur, @alpha) {\n  @value: @x @y @blur rgba(0, 0, 0, @alpha);\n  box-shadow:         @value;\n  -moz-box-shadow:    @value;\n  -webkit-box-shadow: @value;\n}\n.border-radius (@radius) {\n  border-radius: @radius;\n  -moz-border-radius: @radius;\n  -webkit-border-radius: @radius;\n}\n\n.border-radius (@radius, bottom) {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n  -moz-border-top-right-radius: 0;\n  -moz-border-top-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n  -webkit-border-top-right-radius: 0;\n}\n.border-radius (@radius, right) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n  -moz-border-bottom-left-radius: 0;\n  -moz-border-top-left-radius: 0;\n  -webkit-border-bottom-left-radius: 0;\n  -webkit-border-top-left-radius: 0;\n}\n.box-shadow-inset (@x, @y, @blur, @color) {\n  box-shadow: @x @y @blur @color inset;\n  -moz-box-shadow: @x @y @blur @color inset;\n  -webkit-box-shadow: @x @y @blur @color inset;\n}\n.code () {\n  font-family: 'Bitstream Vera Sans Mono',\n               'DejaVu Sans Mono',\n               'Monaco',\n               Courier,\n               monospace !important;\n}\n.wrap () {\n  text-wrap: wrap;\n  white-space: pre-wrap;       /* css-3 */\n  white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */\n  white-space: -pre-wrap;      /* Opera 4-6 */\n  white-space: -o-pre-wrap;    /* Opera 7 */\n  word-wrap: break-word;       /* Internet Explorer 5.5+ */\n}\n\nhtml { margin: 0 }\nbody {\n  background-color: @darkest;\n  margin: 0 auto;\n  font-family: Arial, sans-serif;\n  font-size: 100%;\n  overflow-x: hidden;\n}\nnav, header, footer, section, article {\n  display: block;\n}\na {\n  color: #b83000;\n}\nh1 a {\n  color: black;\n  text-decoration: none;\n}\na:hover {\n  text-decoration: underline;\n}\nh1, h2, h3, h4 {\n  margin: 0;\n  font-weight: normal;\n}\nul, li {\n  list-style-type: none;\n}\ncode { .code; }\ncode {\n  .string, .regexp { color: @dark }\n  .keyword { font-weight: bold }\n  .comment { color: rgba(0, 0, 0, 0.5) }\n  .number { color: @blue }\n  .class, .special { color: rgba(0, 50, 100, 0.8) }\n}\npre {\n  padding: 0 30px;\n  .wrap;\n}\nblockquote {\n  font-style: italic;\n}\nbody > footer {\n  text-align: left;\n  margin-left: 10px;\n  font-style: italic;\n  font-size: 18px;\n  color: #888;\n}\n\n#logo {\n  margin-top: 30px;\n  margin-bottom: 30px;\n  display: block;\n  width: 199px;\n  height: 81px;\n  background: url(/images/logo.png) no-repeat;\n}\nnav {\n  margin-left: 15px;\n}\nnav a, #dropdown li {\n  display: inline-block;\n  color: white;\n  line-height: 42px;\n  margin: 0;\n  padding: 0px 15px;\n  text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.5);\n  text-decoration: none;\n  border: 2px solid transparent;\n  border-width: 0 2px;\n  &:hover {\n    .dark-red; \n    text-decoration: none;\n  }\n}\n.dark-red {\n    @red: @medium;\n    border: 2px solid darken(@red, 25%);\n    border-left-color: darken(@red, 15%);\n    border-right-color: darken(@red, 15%);\n    border-bottom: 0;\n    border-top: 0;\n    background-color: darken(@red, 10%);\n}\n\n.content {\n  margin: 0 auto;\n  width: 980px;\n}\n\n#menu {\n  position: absolute;\n  width: 100%;\n  z-index: 3;\n  clear: both;\n  display: block;\n  background-color: @blue;\n  height: 42px;\n  border-top: 2px solid lighten(@alpha-blue, 20%);\n  border-bottom: 2px solid darken(@alpha-blue, 25%);\n  .box-shadow(0, 1px, 8px, 0.6);\n  -moz-box-shadow: 0 0 0 #000; // Because firefox sucks.\n\n  &.docked {\n    background-color: hsla(210, 60%, 40%, 0.4);\n  }\n  &:hover {\n    background-color: @blue;\n  }\n\n  #dropdown {\n    margin: 0 0 0 117px;\n    padding: 0;\n    padding-top: 5px;\n    display: none;\n    width: 190px;\n    border-top: 2px solid @medium;\n    color: @highlight;\n    border: 2px solid darken(@medium, 25%);\n    border-left-color: darken(@medium, 15%);\n    border-right-color: darken(@medium, 15%);\n    border-top-width: 0;\n    background-color: darken(@medium, 10%);\n    ul {\n      padding: 0px;  \n    }\n    li {\n      font-size: 14px;\n      display: block;\n      text-align: left;\n      padding: 0;\n      border: 0;\n      a {\n        display: block;\n        padding: 0px 15px;  \n        text-decoration: none;\n        color: white;  \n        &:hover {\n          background-color: darken(@medium, 15%);\n          text-decoration: none;\n        }\n      }\n    }\n    .border-radius(5px, bottom);\n    .box-shadow(0, 6px, 8px, 0.5);\n  }\n}\n\n#main {\n  margin: 0 auto;\n  width: 100%;\n  background-color: @light-blue;\n  border-top: 8px solid darken(@light-blue, 5%);\n\n  #intro {\n    background-color: lighten(@light-blue, 25%);\n    float: left;\n    margin-top: -8px;\n    margin-right: 5px;\n\n    height: 380px;\n    position: relative;\n    z-index: 2;\n    font-family: 'Droid Serif', 'Georgia';\n    width: 395px;\n    padding: 45px 20px 23px 30px;\n    border: 2px dashed darken(@light-blue, 10%);\n    .box-shadow(1px, 0px, 6px, 0.5);\n    border-bottom: 0;\n    border-top: 0;\n    #download { color: transparent; border: 0; float: left; display: inline-block; margin: 15px 0 15px -5px; }\n    #download img { display: inline-block}\n    #download-info {\n      code {\n        font-size: 13px;  \n      }\n      color: @blue + #333; display: inline; float: left; margin: 36px 0 0 15px }\n  }\n  h2 {\n    span {\n      color: @medium;  \n    }\n    color: @blue;\n    margin: 20px 0;\n    font-size: 24px;\n    line-height: 1.2em;\n  }\n  h3 {\n    color: @blue;\n    line-height: 1.4em;\n    margin: 30px 0 15px 0;\n    font-size: 1em;\n    text-shadow: 0px 0px 0px @lightest;\n    span { color: @medium }\n  }\n  #example {\n    p {\n      font-size: 18px;\n      color: @blue;\n      font-weight: bold;\n      text-shadow: 0px 1px 1px @lightest;\n    }\n    pre {\n      margin: 0;\n      text-shadow: 0 -1px 1px @darkest;\n      margin-top: 20px;\n      background-color: desaturate(@darkest, 8%);\n      border: 0;\n      width: 450px;\n      color: lighten(@lightest, 2%);\n      background-repeat: repeat;\n      padding: 15px;\n      border: 1px dashed @lightest;\n      line-height: 15px;\n      .box-shadow(0, 0px, 15px, 0.5);\n      .code;\n      .border-radius(2px);\n      code .attribute { color: hsl(40, 50%, 70%) }\n      code .variable  { color: hsl(120, 10%, 50%) }\n      code .element   { color: hsl(170, 20%, 50%) }\n\n      code .string, .regexp { color: hsl(75, 50%, 65%) }\n      code .class { color: hsl(40, 40%, 60%); font-weight: normal }\n      code .id { color: hsl(50, 40%, 60%); font-weight: normal }\n      code .comment { color: rgba(255, 255, 255, 0.2) }\n      code .number, .color { color: hsl(10, 40%, 50%) }\n      code .class, code .mixin, .special { color: hsl(190, 20%, 50%) }\n      #time { color: #aaa }\n    }\n    float: right;\n    font-size: 12px;\n    margin: 0;\n    margin-top: 15px;\n    padding: 0;\n    width: 500px;\n  }\n}\n\n\n.page {\n  .content {\n    width: 870px;\n    padding: 45px;\n  }\n  margin: 0 auto;\n  font-family: 'Georgia', serif;\n  font-size: 18px;\n  line-height: 26px;\n  padding: 0 60px;\n  code {\n    font-size: 16px;  \n  }\n  pre {\n    border-width: 1px;\n    border-style: dashed;\n    padding: 15px;\n    margin: 15px 0;\n  }\n  h1 {\n    text-align: left;\n    font-size: 40px;\n    margin-top: 15px;\n    margin-bottom: 35px;\n  }\n  p + h1 { margin-top: 60px }\n  h2, h3 {\n    margin: 30px 0 15px 0;\n  }\n  p + h2, pre + h2, code + h2 {\n    border-top: 6px solid rgba(255, 255, 255, 0.1);\n    padding-top: 30px;\n  }\n  h3 {\n    margin: 15px 0;\n  }\n}\n\n\n#docs {\n  @bg: lighten(@light-blue, 5%);\n  border-top: 2px solid lighten(@bg, 5%);\n  color: @blue;\n  background-color: @light-blue;\n  .box-shadow(0, -2px, 5px, 0.2);\n\n  h1 {\n    font-family: 'Droid Serif', 'Georgia', serif;\n    padding-top: 30px;\n    padding-left: 45px;\n    font-size: 44px;\n    text-align: left;\n    margin: 30px 0 !important;\n    text-shadow: 0px 1px 1px @lightest;\n    font-weight: bold;\n  }\n  .content {\n    clear: both;\n    border-color: transparent;\n    background-color: lighten(@light-blue, 25%);\n    .box-shadow(0, 5px, 5px, 0.4);\n  }\n  pre {\n    @background: lighten(@bg, 30%);\n    color: lighten(@blue, 10%);\n    background-color: @background;\n    border-color: lighten(@light-blue, 25%);\n    border-width: 2px;\n    code .attribute { color: hsl(40, 50%, 30%) }\n    code .variable  { color: hsl(120, 10%, 30%) }\n    code .element   { color: hsl(170, 20%, 30%) }\n\n    code .string, .regexp { color: hsl(75, 50%, 35%) }\n    code .class { color: hsl(40, 40%, 30%); font-weight: normal }\n    code .id { color: hsl(50, 40%, 30%); font-weight: normal }\n    code .comment { color: rgba(0, 0, 0, 0.4) }\n    code .number, .color { color: hsl(10, 40%, 30%) }\n    code .class, code .mixin, .special { color: hsl(190, 20%, 30%) }\n  }\n  pre code                    { font-size: 15px  }\n  p + h2, pre + h2, code + h2 { border-top-color: rgba(0, 0, 0, 0.1) }\n}\n\ntd {\n  padding-right: 30px;  \n}\n#synopsis {\n  .box-shadow(0, 5px, 5px, 0.2);\n}\n#synopsis, #about {\n  h2 {\n    font-size: 30px;  \n    padding: 10px 0;\n  }\n  h1 + h2 {\n      margin-top: 15px;  \n  }\n  h3 { font-size: 22px }\n\n  .code-example {\n    border-spacing: 0;\n    border-width: 1px;\n    border-style: dashed;\n    padding: 0;\n    pre { border: 0; margin: 0 }\n    td {\n      border: 0;\n      margin: 0;\n      background-color: desaturate(darken(@darkest, 5%), 20%);\n      vertical-align: top;\n      padding: 0;\n    }\n    tr { padding: 0 }\n  }\n  .css-output {\n    td {\n      border-left: 0;  \n    }\n  }\n  .less-example {\n    //border-right: 1px dotted rgba(255, 255, 255, 0.5) !important;\n  }\n  .css-output, .less-example {\n    width: 390px;\n  }\n  pre {\n    padding: 20px;\n    line-height: 20px;\n    font-size: 14px;\n  }\n}\n#about, #synopsis, #guide {\n  a {\n    text-decoration: none;\n    color: @light-yellow;\n    border-bottom: 1px dashed rgba(255, 255, 255, 0.2);\n    &:hover {\n      text-decoration: none;\n      border-bottom: 1px dashed @light-yellow;\n    }\n  }\n  @bg: desaturate(darken(@darkest, 5%), 20%);\n  text-shadow: 0 -1px 1px lighten(@bg, 5%);\n  color: @highlight;\n  background-color: @bg;\n  .content {\n    background-color: desaturate(@darkest, 20%);\n    clear: both;\n    .box-shadow(0, 5px, 5px, 0.4);\n  }\n  h1, h2, h3 {\n    color: @dark-yellow;\n  }\n  pre {\n      code .attribute { color: hsl(40, 50%, 70%) }\n      code .variable  { color: hsl(120, 10%, 50%) }\n      code .element   { color: hsl(170, 20%, 50%) }\n\n      code .string, .regexp { color: hsl(75, 50%, 65%) }\n      code .class { color: hsl(40, 40%, 60%); font-weight: normal }\n      code .id { color: hsl(50, 40%, 60%); font-weight: normal }\n      code .comment { color: rgba(255, 255, 255, 0.2) }\n      code .number, .color { color: hsl(10, 40%, 50%) }\n      code .class, code .mixin, .special { color: hsl(190, 20%, 50%) }\n    background-color: @bg;\n    border-color: darken(@light-yellow, 5%);\n  }\n  code {\n    color: darken(@dark-yellow, 5%);\n    .string, .regexp { color: desaturate(@light-blue, 15%) }\n    .keyword { color: hsl(40, 40%, 60%); font-weight: normal }\n    .comment { color: rgba(255, 255, 255, 0.2) }\n    .number { color: lighten(@blue, 10%) }\n    .class, .special { color: hsl(190, 20%, 50%) }\n  }\n}\n#guide {\n  background-color: @darkest;\n  .content {\n    background-color: transparent;\n  }\n\n}\n\n#about {\n  background-color: @darkest !important;\n  .content {\n    background-color: desaturate(lighten(@darkest, 3%), 5%);\n  }\n}\n#synopsis {\n  background-color: desaturate(lighten(@darkest, 3%), 5%) !important;\n  .content {\n    background-color: desaturate(lighten(@darkest, 3%), 5%);\n  }\n  pre {}\n}\n#synopsis, #guide {\n  .content {\n    .box-shadow(0, 0px, 0px, 0.0);\n  }\n}\n#about footer {\n  margin-top: 30px;\n  padding-top: 30px;\n  border-top: 6px solid rgba(0, 0, 0, 0.1);\n  text-align: center;\n  font-size: 16px;\n  color: rgba(255, 255, 255, 0.35);\n  #copy { font-size: 12px }\n  text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.02);\n}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        theme: \"lesser-dark\",\n        lineNumbers : true,\n        matchBrackets : true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-less</code>, <code>text/css</code> (if not previously defined).</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/less/less.js",
    "content": "/*\nLESS mode - http://www.lesscss.org/\nPorted to CodeMirror by Peter Kroon\n*/\n\nCodeMirror.defineMode(\"less\", function(config) {\n  var indentUnit = config.indentUnit, type;\n  function ret(style, tp) {type = tp; return style;}\n  //html5 tags\n  var tags = [\"a\",\"abbr\",\"acronym\",\"address\",\"applet\",\"area\",\"article\",\"aside\",\"audio\",\"b\",\"base\",\"basefont\",\"bdi\",\"bdo\",\"big\",\"blockquote\",\"body\",\"br\",\"button\",\"canvas\",\"caption\",\"cite\",\"code\",\"col\",\"colgroup\",\"command\",\"datalist\",\"dd\",\"del\",\"details\",\"dfn\",\"dir\",\"div\",\"dl\",\"dt\",\"em\",\"embed\",\"fieldset\",\"figcaption\",\"figure\",\"font\",\"footer\",\"form\",\"frame\",\"frameset\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"head\",\"header\",\"hgroup\",\"hr\",\"html\",\"i\",\"iframe\",\"img\",\"input\",\"ins\",\"keygen\",\"kbd\",\"label\",\"legend\",\"li\",\"link\",\"map\",\"mark\",\"menu\",\"meta\",\"meter\",\"nav\",\"noframes\",\"noscript\",\"object\",\"ol\",\"optgroup\",\"option\",\"output\",\"p\",\"param\",\"pre\",\"progress\",\"q\",\"rp\",\"rt\",\"ruby\",\"s\",\"samp\",\"script\",\"section\",\"select\",\"small\",\"source\",\"span\",\"strike\",\"strong\",\"style\",\"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"textarea\",\"tfoot\",\"th\",\"thead\",\"time\",\"title\",\"tr\",\"track\",\"tt\",\"u\",\"ul\",\"var\",\"video\",\"wbr\"];\n  \n  function inTagsArray(val){\n\t  for(var i=0; i<tags.length; i++){\n\t\t  if(val === tags[i]){\n\t\t\t  return true;\n\t\t  }\n\t  }\n  }\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n\n\tif (ch == \"@\") {stream.eatWhile(/[\\w\\-]/); return ret(\"meta\", stream.current());}\n    else if (ch == \"/\" && stream.eat(\"*\")) {\n      state.tokenize = tokenCComment;\n      return tokenCComment(stream, state);\n    }\n    else if (ch == \"<\" && stream.eat(\"!\")) {\n      state.tokenize = tokenSGMLComment;\n      return tokenSGMLComment(stream, state);\n    }\n    else if (ch == \"=\") ret(null, \"compare\");\n    else if ((ch == \"~\" || ch == \"|\") && stream.eat(\"=\")) return ret(null, \"compare\");\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n\telse if (ch == \"/\") { // lesscss e.g.: .png will not be parsed as a class\n\t  if(stream.eat(\"/\")){\n\t\tstate.tokenize = tokenSComment\n      \treturn tokenSComment(stream, state);\n\t  }else{\n\t    stream.eatWhile(/[\\a-zA-Z0-9\\-_.\\s]/);\n\t\tif(/\\/|\\)|#/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == \")\")))return ret(\"string\", \"string\");//let url(/images/logo.png) without quotes return as string\n        return ret(\"number\", \"unit\");\n\t  }\n    }\n    else if (ch == \"!\") {\n      stream.match(/^\\s*\\w*/);\n      return ret(\"keyword\", \"important\");\n    }\n    else if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w.%]/);\n      return ret(\"number\", \"unit\");\n    }\n    else if (/[,+<>*\\/]/.test(ch)) {//removed . dot character original was [,.+>*\\/]\n      return ret(null, \"select-op\");\n    }\n    else if (/[;{}:\\[\\]()]/.test(ch)) { //added () char for lesscss original was [;{}:\\[\\]]\n      if(ch == \":\"){\n\t\tstream.eatWhile(/[active|hover|link|visited]/);\n\t\tif( stream.current().match(/active|hover|link|visited/)){\n\t\t  return ret(\"tag\", \"tag\");\n\t\t}else{\n\t\t  return ret(null, ch);\t\n\t\t}\n\t  }else{\n  \t    return ret(null, ch);\n\t  }\n    }\n\telse if (ch == \".\") { // lesscss\n\t  stream.eatWhile(/[\\a-zA-Z0-9\\-_]/);\n      return ret(\"tag\", \"tag\");\n    }\n\telse if (ch == \"#\") { // lesscss\n\t  //we don't eat white-space, we want the hex color and or id only\n\t  stream.eatWhile(/[A-Za-z0-9]/);\n\t  //check if there is a proper hex color length e.g. #eee || #eeeEEE\n\t  if(stream.current().length ===4 || stream.current().length ===7){\n\t\t  if(stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false) != null){//is there a valid hex color value present in the current stream\n\t\t  \t//when not a valid hex value, parse as id\n\t\t\tif(stream.current().substring(1) != stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false))return ret(\"atom\", \"tag\");\n\t\t\t//eat white-space\n\t\t\tstream.eatSpace();\n\t\t\t//when hex value declaration doesn't end with [;,] but is does with a slash/cc comment treat it as an id, just like the other hex values that don't end with[;,]\n\t\t\tif( /[\\/<>.(){!$%^&*_\\-\\\\?=+\\|#'~`]/.test(stream.peek()) )return ret(\"atom\", \"tag\");\n\t\t\t//#time { color: #aaa }\n\t\t\telse if(stream.peek() == \"}\" )return ret(\"number\", \"unit\");\n\t\t\t//we have a valid hex color value, parse as id whenever an element/class is defined after the hex(id) value e.g. #eee aaa || #eee .aaa\n\t\t\telse if( /[a-zA-Z\\\\]/.test(stream.peek()) )return ret(\"atom\", \"tag\");\n\t\t\t//when a hex value is on the end of a line, parse as id\n\t\t\telse if(stream.eol())return ret(\"atom\", \"tag\");\n\t\t\t//default\n\t\t\telse return ret(\"number\", \"unit\");\n\t\t  }else{//when not a valid hexvalue in the current stream e.g. #footer\n\t\t\tstream.eatWhile(/[\\w\\\\\\-]/);\n\t\t\treturn ret(\"atom\", \"tag\"); \n\t\t  }\n\t  }else{\n\t\tstream.eatWhile(/[\\w\\\\\\-]/);\t\t\n\t\treturn ret(\"atom\", \"tag\");\n\t  }\n    }\n\telse if (ch == \"&\") {\n\t  stream.eatWhile(/[\\w\\-]/);\n\t  return ret(null, ch);\n\t}\n    else {\n      stream.eatWhile(/[\\w\\\\\\-_%.{]/);\n\t  if(stream.current().match(/http|https/) != null){\n\t\tstream.eatWhile(/[\\w\\\\\\-_%.{:\\/]/);\n\t\treturn ret(\"string\", \"string\");\n\t  }else if(stream.peek() == \"<\" || stream.peek() == \">\"){\n\t\treturn ret(\"tag\", \"tag\");\n\t  }else if( stream.peek().match(/\\(/) != null ){// lessc\n\t\treturn ret(null, ch);\n\t  }else if (stream.peek() == \"/\" && state.stack[state.stack.length-1] != undefined){ // url(dir/center/image.png)\n\t  \treturn ret(\"string\", \"string\");\n\t  }else if( stream.current().match(/\\-\\d|\\-.\\d/) ){ // lesscss match e.g.: -5px -0.4 etc... only colorize the minus sign\n\t\t//stream.backUp(stream.current().length-1); //commment out these 2 comment if you want the minus sign to be parsed as null -500px\n\t  \t//return ret(null, ch);\n\t\treturn ret(\"number\", \"unit\");\n\t  }else if( inTagsArray(stream.current()) ){ // lesscss match html tags\n\t  \treturn ret(\"tag\", \"tag\");\n\t  }else if( /\\/|[\\s\\)]/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == \"/\")) && stream.current().indexOf(\".\") !== -1){\n\t\tif(stream.current().substring(stream.current().length-1,stream.current().length) == \"{\"){\n\t\t\tstream.backUp(1);\n\t\t\treturn ret(\"tag\", \"tag\");\n\t\t}//end if\n\t\tif( (stream.eatSpace() && stream.peek().match(/[{<>.a-zA-Z]/) != null)  || stream.eol() )return ret(\"tag\", \"tag\");//e.g. button.icon-plus\n\t\treturn ret(\"string\", \"string\");//let url(/images/logo.png) without quotes return as string\n\t  }else if( stream.eol() ){\n\t\t  if(stream.current().substring(stream.current().length-1,stream.current().length) == \"{\")stream.backUp(1);\n\t\t  return ret(\"tag\", \"tag\");\n\t  }else{\n      \treturn ret(\"variable\", \"variable\");\n\t  }\n    }\n    \n  }\n\n  function tokenSComment(stream, state) {// SComment = Slash comment\n    stream.skipToEnd();\n\tstate.tokenize = tokenBase;\n    return ret(\"comment\", \"comment\");\n  }\n    \n  function tokenCComment(stream, state) {\n    var maybeEnd = false, ch;\n    while ((ch = stream.next()) != null) {\n      if (maybeEnd && ch == \"/\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenSGMLComment(stream, state) {\n    var dashes = 0, ch;\n    while ((ch = stream.next()) != null) {\n      if (dashes >= 2 && ch == \">\") {\n        state.tokenize = tokenBase;\n        break;\n      }\n      dashes = (ch == \"-\") ? dashes + 1 : 0;\n    }\n    return ret(\"comment\", \"comment\");\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped)\n          break;\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      if (!escaped) state.tokenize = tokenBase;\n      return ret(\"string\", \"string\");\n    };\n  }\n\n  return {\n    startState: function(base) { \n      return {tokenize: tokenBase,\n              baseIndent: base || 0,\n              stack: []};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      var context = state.stack[state.stack.length-1];\n      if (type == \"hash\" && context == \"rule\") style = \"atom\";\n      else if (style == \"variable\") {\n        if (context == \"rule\") style = null; //\"tag\"\n        else if (!context || context == \"@media{\"){ \n\t\t\tstyle = stream.current() \t== \"when\" \t? \"variable\" \t: \n\t\t\tstream.string.match(/#/g) \t!= undefined \t? null \t\t: \n\t\t\t/[\\s,|\\s\\)]/.test(stream.peek()) \t\t? \"tag\" \t: null;\n\t\t}\n      }\n\n      if (context == \"rule\" && /^[\\{\\};]$/.test(type))\n        state.stack.pop();\n      if (type == \"{\") {\n        if (context == \"@media\") state.stack[state.stack.length-1] = \"@media{\";\n        else state.stack.push(\"{\");\n      }\n      else if (type == \"}\") state.stack.pop();\n      else if (type == \"@media\") state.stack.push(\"@media\");\n      else if (context == \"{\" && type != \"comment\") state.stack.push(\"rule\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var n = state.stack.length;\n      if (/^\\}/.test(textAfter))\n        n -= state.stack[state.stack.length-1] == \"rule\" ? 2 : 1;\n      return state.baseIndent + n * indentUnit;\n    },\n\n    electricChars: \"}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-less\", \"less\");\nif (!CodeMirror.mimeModes.hasOwnProperty(\"text/css\"))\n  CodeMirror.defineMIME(\"text/css\", \"less\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/lua/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Lua mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"lua.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../theme/neat.css\">\n    <style>.CodeMirror {border: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Lua mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n--[[\nexample useless code to show lua syntax highlighting\nthis is multiline comment\n]]\n\nfunction blahblahblah(x)\n\n  local table = {\n    \"asd\" = 123,\n    \"x\" = 0.34,  \n  }\n  if x ~= 3 then\n    print( x )\n  elseif x == \"string\"\n    my_custom_function( 0x34 )\n  else\n    unknown_function( \"some string\" )\n  end\n\n  --single line comment\n  \nend\n\nfunction blablabla3()\n\n  for k,v in ipairs( table ) do\n    --abcde..\n    y=[=[\n  x=[[\n      x is a multi line string\n   ]]\n  but its definition is iside a highest level string!\n  ]=]\n    print(\" \\\"\\\" \")\n\n    s = math.sin( x )\n  end\n\nend\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        tabMode: \"indent\",\n        matchBrackets: true,\n        theme: \"neat\"\n      });\n    </script>\n\n    <p>Loosely based on Franciszek\n    Wawrzak's <a href=\"http://codemirror.net/1/contrib/lua\">CodeMirror\n    1 mode</a>. One configuration parameter is\n    supported, <code>specials</code>, to which you can provide an\n    array of strings to have those identifiers highlighted with\n    the <code>lua-special</code> style.</p>\n    <p><strong>MIME types defined:</strong> <code>text/x-lua</code>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/lua/lua.js",
    "content": "// LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's\n// CodeMirror 1 mode.\n// highlights keywords, strings, comments (no leveling supported! (\"[==[\")), tokens, basic indenting\n \nCodeMirror.defineMode(\"lua\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n\n  function prefixRE(words) {\n    return new RegExp(\"^(?:\" + words.join(\"|\") + \")\", \"i\");\n  }\n  function wordRE(words) {\n    return new RegExp(\"^(?:\" + words.join(\"|\") + \")$\", \"i\");\n  }\n  var specials = wordRE(parserConfig.specials || []);\n \n  // long list of standard functions from lua manual\n  var builtins = wordRE([\n    \"_G\",\"_VERSION\",\"assert\",\"collectgarbage\",\"dofile\",\"error\",\"getfenv\",\"getmetatable\",\"ipairs\",\"load\",\n    \"loadfile\",\"loadstring\",\"module\",\"next\",\"pairs\",\"pcall\",\"print\",\"rawequal\",\"rawget\",\"rawset\",\"require\",\n    \"select\",\"setfenv\",\"setmetatable\",\"tonumber\",\"tostring\",\"type\",\"unpack\",\"xpcall\",\n\n    \"coroutine.create\",\"coroutine.resume\",\"coroutine.running\",\"coroutine.status\",\"coroutine.wrap\",\"coroutine.yield\",\n\n    \"debug.debug\",\"debug.getfenv\",\"debug.gethook\",\"debug.getinfo\",\"debug.getlocal\",\"debug.getmetatable\",\n    \"debug.getregistry\",\"debug.getupvalue\",\"debug.setfenv\",\"debug.sethook\",\"debug.setlocal\",\"debug.setmetatable\",\n    \"debug.setupvalue\",\"debug.traceback\",\n\n    \"close\",\"flush\",\"lines\",\"read\",\"seek\",\"setvbuf\",\"write\",\n\n    \"io.close\",\"io.flush\",\"io.input\",\"io.lines\",\"io.open\",\"io.output\",\"io.popen\",\"io.read\",\"io.stderr\",\"io.stdin\",\n    \"io.stdout\",\"io.tmpfile\",\"io.type\",\"io.write\",\n\n    \"math.abs\",\"math.acos\",\"math.asin\",\"math.atan\",\"math.atan2\",\"math.ceil\",\"math.cos\",\"math.cosh\",\"math.deg\",\n    \"math.exp\",\"math.floor\",\"math.fmod\",\"math.frexp\",\"math.huge\",\"math.ldexp\",\"math.log\",\"math.log10\",\"math.max\",\n    \"math.min\",\"math.modf\",\"math.pi\",\"math.pow\",\"math.rad\",\"math.random\",\"math.randomseed\",\"math.sin\",\"math.sinh\",\n    \"math.sqrt\",\"math.tan\",\"math.tanh\",\n\n    \"os.clock\",\"os.date\",\"os.difftime\",\"os.execute\",\"os.exit\",\"os.getenv\",\"os.remove\",\"os.rename\",\"os.setlocale\",\n    \"os.time\",\"os.tmpname\",\n\n    \"package.cpath\",\"package.loaded\",\"package.loaders\",\"package.loadlib\",\"package.path\",\"package.preload\",\n    \"package.seeall\",\n\n    \"string.byte\",\"string.char\",\"string.dump\",\"string.find\",\"string.format\",\"string.gmatch\",\"string.gsub\",\n    \"string.len\",\"string.lower\",\"string.match\",\"string.rep\",\"string.reverse\",\"string.sub\",\"string.upper\",\n\n    \"table.concat\",\"table.insert\",\"table.maxn\",\"table.remove\",\"table.sort\"\n  ]);\n  var keywords = wordRE([\"and\",\"break\",\"elseif\",\"false\",\"nil\",\"not\",\"or\",\"return\",\n\t\t\t \"true\",\"function\", \"end\", \"if\", \"then\", \"else\", \"do\", \n\t\t\t \"while\", \"repeat\", \"until\", \"for\", \"in\", \"local\" ]);\n\n  var indentTokens = wordRE([\"function\", \"if\",\"repeat\",\"do\", \"\\\\(\", \"{\"]);\n  var dedentTokens = wordRE([\"end\", \"until\", \"\\\\)\", \"}\"]);\n  var dedentPartial = prefixRE([\"end\", \"until\", \"\\\\)\", \"}\", \"else\", \"elseif\"]);\n\n  function readBracket(stream) {\n    var level = 0;\n    while (stream.eat(\"=\")) ++level;\n    stream.eat(\"[\");\n    return level;\n  }\n\n  function normal(stream, state) {\n    var ch = stream.next();\n    if (ch == \"-\" && stream.eat(\"-\")) {\n      if (stream.eat(\"[\"))\n        return (state.cur = bracketed(readBracket(stream), \"comment\"))(stream, state);\n      stream.skipToEnd();\n      return \"comment\";\n    } \n    if (ch == \"\\\"\" || ch == \"'\")\n      return (state.cur = string(ch))(stream, state);\n    if (ch == \"[\" && /[\\[=]/.test(stream.peek()))\n      return (state.cur = bracketed(readBracket(stream), \"string\"))(stream, state);\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w.%]/);\n      return \"number\";\n    }\n    if (/[\\w_]/.test(ch)) {\n      stream.eatWhile(/[\\w\\\\\\-_.]/);\n      return \"variable\";\n    }\n    return null;\n  }\n\n  function bracketed(level, style) {\n    return function(stream, state) {\n      var curlev = null, ch;\n      while ((ch = stream.next()) != null) {\n        if (curlev == null) {if (ch == \"]\") curlev = 0;}\n        else if (ch == \"=\") ++curlev;\n        else if (ch == \"]\" && curlev == level) { state.cur = normal; break; }\n        else curlev = null;\n      }\n      return style;\n    };\n  }\n\n  function string(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) break;\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      if (!escaped) state.cur = normal;\n      return \"string\";\n    };\n  }\n    \n  return {\n    startState: function(basecol) {\n      return {basecol: basecol || 0, indentDepth: 0, cur: normal};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.cur(stream, state);\n      var word = stream.current();\n      if (style == \"variable\") {\n        if (keywords.test(word)) style = \"keyword\";\n        else if (builtins.test(word)) style = \"builtin\";\n\telse if (specials.test(word)) style = \"variable-2\";\n      }\n      if ((style != \"comment\") && (style != \"string\")){\n        if (indentTokens.test(word)) ++state.indentDepth;\n        else if (dedentTokens.test(word)) --state.indentDepth;\n      }\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var closing = dedentPartial.test(textAfter);\n      return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0));\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-lua\", \"lua\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/markdown/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Markdown mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"../xml/xml.js\"></script>\n    <script src=\"markdown.js\"></script>\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Markdown mode</h1>\n\n<!-- source: http://daringfireball.net/projects/markdown/basics.text -->\n<form><textarea id=\"code\" name=\"code\">\nMarkdown: Basics\n================\n\n&lt;ul id=\"ProjectSubmenu\"&gt;\n    &lt;li&gt;&lt;a href=\"/projects/markdown/\" title=\"Markdown Project Page\"&gt;Main&lt;/a&gt;&lt;/li&gt;\n    &lt;li&gt;&lt;a class=\"selected\" title=\"Markdown Basics\"&gt;Basics&lt;/a&gt;&lt;/li&gt;\n    &lt;li&gt;&lt;a href=\"/projects/markdown/syntax\" title=\"Markdown Syntax Documentation\"&gt;Syntax&lt;/a&gt;&lt;/li&gt;\n    &lt;li&gt;&lt;a href=\"/projects/markdown/license\" title=\"Pricing and License Information\"&gt;License&lt;/a&gt;&lt;/li&gt;\n    &lt;li&gt;&lt;a href=\"/projects/markdown/dingus\" title=\"Online Markdown Web Form\"&gt;Dingus&lt;/a&gt;&lt;/li&gt;\n&lt;/ul&gt;\n\n\nGetting the Gist of Markdown's Formatting Syntax\n------------------------------------------------\n\nThis page offers a brief overview of what it's like to use Markdown.\nThe [syntax page] [s] provides complete, detailed documentation for\nevery feature, but Markdown should be very easy to pick up simply by\nlooking at a few examples of it in action. The examples on this page\nare written in a before/after style, showing example syntax and the\nHTML output produced by Markdown.\n\nIt's also helpful to simply try Markdown out; the [Dingus] [d] is a\nweb application that allows you type your own Markdown-formatted text\nand translate it to XHTML.\n\n**Note:** This document is itself written using Markdown; you\ncan [see the source for it by adding '.text' to the URL] [src].\n\n  [s]: /projects/markdown/syntax  \"Markdown Syntax\"\n  [d]: /projects/markdown/dingus  \"Markdown Dingus\"\n  [src]: /projects/markdown/basics.text\n\n\n## Paragraphs, Headers, Blockquotes ##\n\nA paragraph is simply one or more consecutive lines of text, separated\nby one or more blank lines. (A blank line is any line that looks like\na blank line -- a line containing nothing but spaces or tabs is\nconsidered blank.) Normal paragraphs should not be indented with\nspaces or tabs.\n\nMarkdown offers two styles of headers: *Setext* and *atx*.\nSetext-style headers for `&lt;h1&gt;` and `&lt;h2&gt;` are created by\n\"underlining\" with equal signs (`=`) and hyphens (`-`), respectively.\nTo create an atx-style header, you put 1-6 hash marks (`#`) at the\nbeginning of the line -- the number of hashes equals the resulting\nHTML header level.\n\nBlockquotes are indicated using email-style '`&gt;`' angle brackets.\n\nMarkdown:\n\n    A First Level Header\n    ====================\n    \n    A Second Level Header\n    ---------------------\n\n    Now is the time for all good men to come to\n    the aid of their country. This is just a\n    regular paragraph.\n\n    The quick brown fox jumped over the lazy\n    dog's back.\n    \n    ### Header 3\n\n    &gt; This is a blockquote.\n    &gt; \n    &gt; This is the second paragraph in the blockquote.\n    &gt;\n    &gt; ## This is an H2 in a blockquote\n\n\nOutput:\n\n    &lt;h1&gt;A First Level Header&lt;/h1&gt;\n    \n    &lt;h2&gt;A Second Level Header&lt;/h2&gt;\n    \n    &lt;p&gt;Now is the time for all good men to come to\n    the aid of their country. This is just a\n    regular paragraph.&lt;/p&gt;\n    \n    &lt;p&gt;The quick brown fox jumped over the lazy\n    dog's back.&lt;/p&gt;\n    \n    &lt;h3&gt;Header 3&lt;/h3&gt;\n    \n    &lt;blockquote&gt;\n        &lt;p&gt;This is a blockquote.&lt;/p&gt;\n        \n        &lt;p&gt;This is the second paragraph in the blockquote.&lt;/p&gt;\n        \n        &lt;h2&gt;This is an H2 in a blockquote&lt;/h2&gt;\n    &lt;/blockquote&gt;\n\n\n\n### Phrase Emphasis ###\n\nMarkdown uses asterisks and underscores to indicate spans of emphasis.\n\nMarkdown:\n\n    Some of these words *are emphasized*.\n    Some of these words _are emphasized also_.\n    \n    Use two asterisks for **strong emphasis**.\n    Or, if you prefer, __use two underscores instead__.\n\nOutput:\n\n    &lt;p&gt;Some of these words &lt;em&gt;are emphasized&lt;/em&gt;.\n    Some of these words &lt;em&gt;are emphasized also&lt;/em&gt;.&lt;/p&gt;\n    \n    &lt;p&gt;Use two asterisks for &lt;strong&gt;strong emphasis&lt;/strong&gt;.\n    Or, if you prefer, &lt;strong&gt;use two underscores instead&lt;/strong&gt;.&lt;/p&gt;\n   \n\n\n## Lists ##\n\nUnordered (bulleted) lists use asterisks, pluses, and hyphens (`*`,\n`+`, and `-`) as list markers. These three markers are\ninterchangable; this:\n\n    *   Candy.\n    *   Gum.\n    *   Booze.\n\nthis:\n\n    +   Candy.\n    +   Gum.\n    +   Booze.\n\nand this:\n\n    -   Candy.\n    -   Gum.\n    -   Booze.\n\nall produce the same output:\n\n    &lt;ul&gt;\n    &lt;li&gt;Candy.&lt;/li&gt;\n    &lt;li&gt;Gum.&lt;/li&gt;\n    &lt;li&gt;Booze.&lt;/li&gt;\n    &lt;/ul&gt;\n\nOrdered (numbered) lists use regular numbers, followed by periods, as\nlist markers:\n\n    1.  Red\n    2.  Green\n    3.  Blue\n\nOutput:\n\n    &lt;ol&gt;\n    &lt;li&gt;Red&lt;/li&gt;\n    &lt;li&gt;Green&lt;/li&gt;\n    &lt;li&gt;Blue&lt;/li&gt;\n    &lt;/ol&gt;\n\nIf you put blank lines between items, you'll get `&lt;p&gt;` tags for the\nlist item text. You can create multi-paragraph list items by indenting\nthe paragraphs by 4 spaces or 1 tab:\n\n    *   A list item.\n    \n        With multiple paragraphs.\n\n    *   Another item in the list.\n\nOutput:\n\n    &lt;ul&gt;\n    &lt;li&gt;&lt;p&gt;A list item.&lt;/p&gt;\n    &lt;p&gt;With multiple paragraphs.&lt;/p&gt;&lt;/li&gt;\n    &lt;li&gt;&lt;p&gt;Another item in the list.&lt;/p&gt;&lt;/li&gt;\n    &lt;/ul&gt;\n    \n\n\n### Links ###\n\nMarkdown supports two styles for creating links: *inline* and\n*reference*. With both styles, you use square brackets to delimit the\ntext you want to turn into a link.\n\nInline-style links use parentheses immediately after the link text.\nFor example:\n\n    This is an [example link](http://example.com/).\n\nOutput:\n\n    &lt;p&gt;This is an &lt;a href=\"http://example.com/\"&gt;\n    example link&lt;/a&gt;.&lt;/p&gt;\n\nOptionally, you may include a title attribute in the parentheses:\n\n    This is an [example link](http://example.com/ \"With a Title\").\n\nOutput:\n\n    &lt;p&gt;This is an &lt;a href=\"http://example.com/\" title=\"With a Title\"&gt;\n    example link&lt;/a&gt;.&lt;/p&gt;\n\nReference-style links allow you to refer to your links by names, which\nyou define elsewhere in your document:\n\n    I get 10 times more traffic from [Google][1] than from\n    [Yahoo][2] or [MSN][3].\n\n    [1]: http://google.com/        \"Google\"\n    [2]: http://search.yahoo.com/  \"Yahoo Search\"\n    [3]: http://search.msn.com/    \"MSN Search\"\n\nOutput:\n\n    &lt;p&gt;I get 10 times more traffic from &lt;a href=\"http://google.com/\"\n    title=\"Google\"&gt;Google&lt;/a&gt; than from &lt;a href=\"http://search.yahoo.com/\"\n    title=\"Yahoo Search\"&gt;Yahoo&lt;/a&gt; or &lt;a href=\"http://search.msn.com/\"\n    title=\"MSN Search\"&gt;MSN&lt;/a&gt;.&lt;/p&gt;\n\nThe title attribute is optional. Link names may contain letters,\nnumbers and spaces, but are *not* case sensitive:\n\n    I start my morning with a cup of coffee and\n    [The New York Times][NY Times].\n\n    [ny times]: http://www.nytimes.com/\n\nOutput:\n\n    &lt;p&gt;I start my morning with a cup of coffee and\n    &lt;a href=\"http://www.nytimes.com/\"&gt;The New York Times&lt;/a&gt;.&lt;/p&gt;\n\n\n### Images ###\n\nImage syntax is very much like link syntax.\n\nInline (titles are optional):\n\n    ![alt text](/path/to/img.jpg \"Title\")\n\nReference-style:\n\n    ![alt text][id]\n\n    [id]: /path/to/img.jpg \"Title\"\n\nBoth of the above examples produce the same output:\n\n    &lt;img src=\"/path/to/img.jpg\" alt=\"alt text\" title=\"Title\" /&gt;\n\n\n\n### Code ###\n\nIn a regular paragraph, you can create code span by wrapping text in\nbacktick quotes. Any ampersands (`&amp;`) and angle brackets (`&lt;` or\n`&gt;`) will automatically be translated into HTML entities. This makes\nit easy to use Markdown to write about HTML example code:\n\n    I strongly recommend against using any `&lt;blink&gt;` tags.\n\n    I wish SmartyPants used named entities like `&amp;mdash;`\n    instead of decimal-encoded entites like `&amp;#8212;`.\n\nOutput:\n\n    &lt;p&gt;I strongly recommend against using any\n    &lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;\n    \n    &lt;p&gt;I wish SmartyPants used named entities like\n    &lt;code&gt;&amp;amp;mdash;&lt;/code&gt; instead of decimal-encoded\n    entites like &lt;code&gt;&amp;amp;#8212;&lt;/code&gt;.&lt;/p&gt;\n\n\nTo specify an entire block of pre-formatted code, indent every line of\nthe block by 4 spaces or 1 tab. Just like with code spans, `&amp;`, `&lt;`,\nand `&gt;` characters will be escaped automatically.\n\nMarkdown:\n\n    If you want your page to validate under XHTML 1.0 Strict,\n    you've got to put paragraph tags in your blockquotes:\n\n        &lt;blockquote&gt;\n            &lt;p&gt;For example.&lt;/p&gt;\n        &lt;/blockquote&gt;\n\nOutput:\n\n    &lt;p&gt;If you want your page to validate under XHTML 1.0 Strict,\n    you've got to put paragraph tags in your blockquotes:&lt;/p&gt;\n    \n    &lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;\n        &amp;lt;p&amp;gt;For example.&amp;lt;/p&amp;gt;\n    &amp;lt;/blockquote&amp;gt;\n    &lt;/code&gt;&lt;/pre&gt;\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: 'markdown',\n        lineNumbers: true,\n        matchBrackets: true,\n        theme: \"default\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-markdown</code>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/markdown/markdown.js",
    "content": "CodeMirror.defineMode(\"markdown\", function(cmCfg, modeCfg) {\n\n  var htmlMode = CodeMirror.getMode(cmCfg, { name: 'xml', htmlMode: true });\n\n  var header   = 'header'\n  ,   code     = 'comment'\n  ,   quote    = 'quote'\n  ,   list     = 'string'\n  ,   hr       = 'hr'\n  ,   linktext = 'link'\n  ,   linkhref = 'string'\n  ,   em       = 'em'\n  ,   strong   = 'strong'\n  ,   emstrong = 'emstrong';\n\n  var hrRE = /^([*\\-=_])(?:\\s*\\1){2,}\\s*$/\n  ,   ulRE = /^[*\\-+]\\s+/\n  ,   olRE = /^[0-9]+\\.\\s+/\n  ,   headerRE = /^(?:\\={3,}|-{3,})$/\n  ,   textRE = /^[^\\[*_\\\\<>`]+/;\n\n  function switchInline(stream, state, f) {\n    state.f = state.inline = f;\n    return f(stream, state);\n  }\n\n  function switchBlock(stream, state, f) {\n    state.f = state.block = f;\n    return f(stream, state);\n  }\n\n\n  // Blocks\n\n  function blankLine(state) {\n    // Reset EM state\n    state.em = false;\n    // Reset STRONG state\n    state.strong = false;\n    return null;\n  }\n\n  function blockNormal(stream, state) {\n    var match;\n    if (state.indentationDiff >= 4) {\n      state.indentation -= state.indentationDiff;\n      stream.skipToEnd();\n      return code;\n    } else if (stream.eatSpace()) {\n      return null;\n    } else if (stream.peek() === '#' || stream.match(headerRE)) {\n      state.header = true;\n    } else if (stream.eat('>')) {\n      state.indentation++;\n      state.quote = true;\n    } else if (stream.peek() === '[') {\n      return switchInline(stream, state, footnoteLink);\n    } else if (stream.match(hrRE, true)) {\n      return hr;\n    } else if (match = stream.match(ulRE, true) || stream.match(olRE, true)) {\n      state.indentation += match[0].length;\n      return list;\n    }\n    \n    return switchInline(stream, state, state.inline);\n  }\n\n  function htmlBlock(stream, state) {\n    var style = htmlMode.token(stream, state.htmlState);\n    if (style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) {\n      state.f = inlineNormal;\n      state.block = blockNormal;\n    }\n    return style;\n  }\n\n\n  // Inline\n  function getType(state) {\n    var styles = [];\n    \n    if (state.strong) { styles.push(state.em ? emstrong : strong); }\n    else if (state.em) { styles.push(em); }\n    \n    if (state.header) { styles.push(header); }\n    if (state.quote) { styles.push(quote); }\n\n    return styles.length ? styles.join(' ') : null;\n  }\n\n  function handleText(stream, state) {\n    if (stream.match(textRE, true)) {\n      return getType(state);\n    }\n    return undefined;        \n  }\n\n  function inlineNormal(stream, state) {\n    var style = state.text(stream, state)\n    if (typeof style !== 'undefined')\n      return style;\n    \n    var ch = stream.next();\n    \n    if (ch === '\\\\') {\n      stream.next();\n      return getType(state);\n    }\n    if (ch === '`') {\n      return switchInline(stream, state, inlineElement(code, '`'));\n    }\n    if (ch === '[') {\n      return switchInline(stream, state, linkText);\n    }\n    if (ch === '<' && stream.match(/^\\w/, false)) {\n      stream.backUp(1);\n      return switchBlock(stream, state, htmlBlock);\n    }\n\n    var t = getType(state);\n    if (ch === '*' || ch === '_') {\n      if (stream.eat(ch)) {\n        return (state.strong = !state.strong) ? getType(state) : t;\n      }\n      return (state.em = !state.em) ? getType(state) : t;\n    }\n    \n    return getType(state);\n  }\n\n  function linkText(stream, state) {\n    while (!stream.eol()) {\n      var ch = stream.next();\n      if (ch === '\\\\') stream.next();\n      if (ch === ']') {\n        state.inline = state.f = linkHref;\n        return linktext;\n      }\n    }\n    return linktext;\n  }\n\n  function linkHref(stream, state) {\n    stream.eatSpace();\n    var ch = stream.next();\n    if (ch === '(' || ch === '[') {\n      return switchInline(stream, state, inlineElement(linkhref, ch === '(' ? ')' : ']'));\n    }\n    return 'error';\n  }\n\n  function footnoteLink(stream, state) {\n    if (stream.match(/^[^\\]]*\\]:/, true)) {\n      state.f = footnoteUrl;\n      return linktext;\n    }\n    return switchInline(stream, state, inlineNormal);\n  }\n\n  function footnoteUrl(stream, state) {\n    stream.eatSpace();\n    stream.match(/^[^\\s]+/, true);\n    state.f = state.inline = inlineNormal;\n    return linkhref;\n  }\n\n  function inlineRE(endChar) {\n    if (!inlineRE[endChar]) {\n      // match any not-escaped-non-endChar and any escaped char\n      // then match endChar or eol\n      inlineRE[endChar] = new RegExp('^(?:[^\\\\\\\\\\\\' + endChar + ']|\\\\\\\\.)*(?:\\\\' + endChar + '|$)');\n    }\n    return inlineRE[endChar];\n  }\n\n  function inlineElement(type, endChar, next) {\n    next = next || inlineNormal;\n    return function(stream, state) {\n      stream.match(inlineRE(endChar));\n      state.inline = state.f = next;\n      return type;\n    };\n  }\n\n  return {\n    startState: function() {\n      return {\n        f: blockNormal,\n        \n        block: blockNormal,\n        htmlState: htmlMode.startState(),\n        indentation: 0,\n        \n        inline: inlineNormal,\n        text: handleText,\n        em: false,\n        strong: false,\n        header: false,\n        quote: false\n      };\n    },\n\n    copyState: function(s) {\n      return {\n        f: s.f,\n        \n        block: s.block,\n        htmlState: CodeMirror.copyState(htmlMode, s.htmlState),\n        indentation: s.indentation,\n        \n        inline: s.inline,\n        text: s.text,\n        em: s.em,\n        strong: s.strong,\n        header: s.header,\n        quote: s.quote\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (stream.match(/^\\s*$/, true)) { return blankLine(state); }\n\n        // Reset state.header\n        state.header = false;\n        // Reset state.quote\n        state.quote = false;\n\n        state.f = state.block;\n        var indentation = stream.match(/^\\s*/, true)[0].replace(/\\t/g, '    ').length;\n        state.indentationDiff = indentation - state.indentation;\n        state.indentation = indentation;\n        if (indentation > 0) { return null; }\n      }\n      return state.f(stream, state);\n    },\n\n    blankLine: blankLine,\n\n    getType: getType\n  };\n\n}, \"xml\");\n\nCodeMirror.defineMIME(\"text/x-markdown\", \"markdown\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/mysql/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: MySQL mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"mysql.js\"></script>\n    <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: MySQL mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n-- Comment for the code\n-- MySQL Mode for CodeMirror2 by MySQLTools http://github.com/partydroid/MySQL-Tools\nSELECT  UNIQUE `var1` as `variable`,\n        MAX(`var5`) as `max`,\n        MIN(`var5`) as `min`,\n        STDEV(`var5`) as `dev`\nFROM `table`\n\nLEFT JOIN `table2` ON `var2` = `variable`\n\nORDER BY `var3` DESC\nGROUP BY `groupvar`\n\nLIMIT 0,30;\n\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: \"text/x-mysql\",\n        tabMode: \"indent\",\n        matchBrackets: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-mysql</code>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/mysql/mysql.js",
    "content": "/*\n *\tMySQL Mode for CodeMirror 2 by MySQL-Tools\n *\t@author James Thorne (partydroid)\n *\t@link \thttp://github.com/partydroid/MySQL-Tools\n * \t@link \thttp://mysqltools.org\n *\t@version 02/Jan/2012\n*/\nCodeMirror.defineMode(\"mysql\", function(config) {\n  var indentUnit = config.indentUnit;\n  var curPunc;\n\n  function wordRegexp(words) {\n    return new RegExp(\"^(?:\" + words.join(\"|\") + \")$\", \"i\");\n  }\n  var ops = wordRegexp([\"str\", \"lang\", \"langmatches\", \"datatype\", \"bound\", \"sameterm\", \"isiri\", \"isuri\",\n                        \"isblank\", \"isliteral\", \"union\", \"a\"]);\n  var keywords = wordRegexp([\n  \t('ACCESSIBLE'),('ALTER'),('AS'),('BEFORE'),('BINARY'),('BY'),('CASE'),('CHARACTER'),('COLUMN'),('CONTINUE'),('CROSS'),('CURRENT_TIMESTAMP'),('DATABASE'),('DAY_MICROSECOND'),('DEC'),('DEFAULT'),\n\t('DESC'),('DISTINCT'),('DOUBLE'),('EACH'),('ENCLOSED'),('EXIT'),('FETCH'),('FLOAT8'),('FOREIGN'),('GRANT'),('HIGH_PRIORITY'),('HOUR_SECOND'),('IN'),('INNER'),('INSERT'),('INT2'),('INT8'),\n\t('INTO'),('JOIN'),('KILL'),('LEFT'),('LINEAR'),('LOCALTIME'),('LONG'),('LOOP'),('MATCH'),('MEDIUMTEXT'),('MINUTE_SECOND'),('NATURAL'),('NULL'),('OPTIMIZE'),('OR'),('OUTER'),('PRIMARY'),\n\t('RANGE'),('READ_WRITE'),('REGEXP'),('REPEAT'),('RESTRICT'),('RIGHT'),('SCHEMAS'),('SENSITIVE'),('SHOW'),('SPECIFIC'),('SQLSTATE'),('SQL_CALC_FOUND_ROWS'),('STARTING'),('TERMINATED'),\n\t('TINYINT'),('TRAILING'),('UNDO'),('UNLOCK'),('USAGE'),('UTC_DATE'),('VALUES'),('VARCHARACTER'),('WHERE'),('WRITE'),('ZEROFILL'),('ALL'),('AND'),('ASENSITIVE'),('BIGINT'),('BOTH'),('CASCADE'),\n\t('CHAR'),('COLLATE'),('CONSTRAINT'),('CREATE'),('CURRENT_TIME'),('CURSOR'),('DAY_HOUR'),('DAY_SECOND'),('DECLARE'),('DELETE'),('DETERMINISTIC'),('DIV'),('DUAL'),('ELSEIF'),('EXISTS'),('FALSE'),\n\t('FLOAT4'),('FORCE'),('FULLTEXT'),('HAVING'),('HOUR_MINUTE'),('IGNORE'),('INFILE'),('INSENSITIVE'),('INT1'),('INT4'),('INTERVAL'),('ITERATE'),('KEYS'),('LEAVE'),('LIMIT'),('LOAD'),('LOCK'),\n\t('LONGTEXT'),('MASTER_SSL_VERIFY_SERVER_CERT'),('MEDIUMINT'),('MINUTE_MICROSECOND'),('MODIFIES'),('NO_WRITE_TO_BINLOG'),('ON'),('OPTIONALLY'),('OUT'),('PRECISION'),('PURGE'),('READS'),\n\t('REFERENCES'),('RENAME'),('REQUIRE'),('REVOKE'),('SCHEMA'),('SELECT'),('SET'),('SPATIAL'),('SQLEXCEPTION'),('SQL_BIG_RESULT'),('SSL'),('TABLE'),('TINYBLOB'),('TO'),('TRUE'),('UNIQUE'),\n\t('UPDATE'),('USING'),('UTC_TIMESTAMP'),('VARCHAR'),('WHEN'),('WITH'),('YEAR_MONTH'),('ADD'),('ANALYZE'),('ASC'),('BETWEEN'),('BLOB'),('CALL'),('CHANGE'),('CHECK'),('CONDITION'),('CONVERT'),\n\t('CURRENT_DATE'),('CURRENT_USER'),('DATABASES'),('DAY_MINUTE'),('DECIMAL'),('DELAYED'),('DESCRIBE'),('DISTINCTROW'),('DROP'),('ELSE'),('ESCAPED'),('EXPLAIN'),('FLOAT'),('FOR'),('FROM'),\n\t('GROUP'),('HOUR_MICROSECOND'),('IF'),('INDEX'),('INOUT'),('INT'),('INT3'),('INTEGER'),('IS'),('KEY'),('LEADING'),('LIKE'),('LINES'),('LOCALTIMESTAMP'),('LONGBLOB'),('LOW_PRIORITY'),\n\t('MEDIUMBLOB'),('MIDDLEINT'),('MOD'),('NOT'),('NUMERIC'),('OPTION'),('ORDER'),('OUTFILE'),('PROCEDURE'),('READ'),('REAL'),('RELEASE'),('REPLACE'),('RETURN'),('RLIKE'),('SECOND_MICROSECOND'),\n\t('SEPARATOR'),('SMALLINT'),('SQL'),('SQLWARNING'),('SQL_SMALL_RESULT'),('STRAIGHT_JOIN'),('THEN'),('TINYTEXT'),('TRIGGER'),('UNION'),('UNSIGNED'),('USE'),('UTC_TIME'),('VARBINARY'),('VARYING'),\n\t('WHILE'),('XOR'),('FULL'),('COLUMNS'),('MIN'),('MAX'),('STDEV'),('COUNT')\n  ]);\n  var operatorChars = /[*+\\-<>=&|]/;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    curPunc = null;\n    if (ch == \"$\" || ch == \"?\") {\n      stream.match(/^[\\w\\d]*/);\n      return \"variable-2\";\n    }\n    else if (ch == \"<\" && !stream.match(/^[\\s\\u00a0=]/, false)) {\n      stream.match(/^[^\\s\\u00a0>]*>?/);\n      return \"atom\";\n    }\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenLiteral(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (ch == \"`\") {\n      state.tokenize = tokenOpLiteral(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (/[{}\\(\\),\\.;\\[\\]]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    else if (ch == \"-\") {\n\t\tch2 = stream.next();\n\t\tif(ch2==\"-\")\n\t\t{\n\t\t\tstream.skipToEnd();\n\t\t\treturn \"comment\";\n\t\t}\n\n    }\n    else if (operatorChars.test(ch)) {\n      stream.eatWhile(operatorChars);\n      return null;\n    }\n    else if (ch == \":\") {\n      stream.eatWhile(/[\\w\\d\\._\\-]/);\n      return \"atom\";\n    }\n    else {\n      stream.eatWhile(/[_\\w\\d]/);\n      if (stream.eat(\":\")) {\n        stream.eatWhile(/[\\w\\d_\\-]/);\n        return \"atom\";\n      }\n      var word = stream.current(), type;\n      if (ops.test(word))\n        return null;\n      else if (keywords.test(word))\n        return \"keyword\";\n      else\n        return \"variable\";\n    }\n  }\n\n  function tokenLiteral(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return \"string\";\n    };\n  }\n\n  function tokenOpLiteral(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return \"variable-2\";\n    };\n  }\n\n\n  function pushContext(state, type, col) {\n    state.context = {prev: state.context, indent: state.indent, col: col, type: type};\n  }\n  function popContext(state) {\n    state.indent = state.context.indent;\n    state.context = state.context.prev;\n  }\n\n  return {\n    startState: function(base) {\n      return {tokenize: tokenBase,\n              context: null,\n              indent: 0,\n              col: 0};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (state.context && state.context.align == null) state.context.align = false;\n        state.indent = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      if (style != \"comment\" && state.context && state.context.align == null && state.context.type != \"pattern\") {\n        state.context.align = true;\n      }\n\n      if (curPunc == \"(\") pushContext(state, \")\", stream.column());\n      else if (curPunc == \"[\") pushContext(state, \"]\", stream.column());\n      else if (curPunc == \"{\") pushContext(state, \"}\", stream.column());\n      else if (/[\\]\\}\\)]/.test(curPunc)) {\n        while (state.context && state.context.type == \"pattern\") popContext(state);\n        if (state.context && curPunc == state.context.type) popContext(state);\n      }\n      else if (curPunc == \".\" && state.context && state.context.type == \"pattern\") popContext(state);\n      else if (/atom|string|variable/.test(style) && state.context) {\n        if (/[\\}\\]]/.test(state.context.type))\n          pushContext(state, \"pattern\", stream.column());\n        else if (state.context.type == \"pattern\" && !state.context.align) {\n          state.context.align = true;\n          state.context.col = stream.column();\n        }\n      }\n\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var firstChar = textAfter && textAfter.charAt(0);\n      var context = state.context;\n      if (/[\\]\\}]/.test(firstChar))\n        while (context && context.type == \"pattern\") context = context.prev;\n\n      var closing = context && firstChar == context.type;\n      if (!context)\n        return 0;\n      else if (context.type == \"pattern\")\n        return context.col;\n      else if (context.align)\n        return context.col + (closing ? 0 : 1);\n      else\n        return context.indent + (closing ? 0 : indentUnit);\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-mysql\", \"mysql\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/ntriples/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: NTriples mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"ntriples.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style type=\"text/css\">\n      .CodeMirror {\n        border: 1px solid #eee;\n      }\n    </style>   \n  </head>\n  <body>\n    <h1>CodeMirror: NTriples mode</h1>\n<form>\n<textarea id=\"ntriples\" name=\"ntriples\">    \n<http://Sub1>     <http://pred1>     <http://obj> .\n<http://Sub2>     <http://pred2#an2> \"literal 1\" .\n<http://Sub3#an3> <http://pred3>     _:bnode3 .\n_:bnode4          <http://pred4>     \"literal 2\"@lang .\n_:bnode5          <http://pred5>     \"literal 3\"^^<http://type> .\n</textarea>\n</form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"ntriples\"), {});\n    </script>\n    <p><strong>MIME types defined:</strong> <code>text/n-triples</code>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/ntriples/ntriples.js",
    "content": "/**********************************************************\n* This script provides syntax highlighting support for \n* the Ntriples format.\n* Ntriples format specification: \n*     http://www.w3.org/TR/rdf-testcases/#ntriples\n***********************************************************/\n\n/* \n    The following expression defines the defined ASF grammar transitions.\n\n    pre_subject ->\n        {\n        ( writing_subject_uri | writing_bnode_uri )\n            -> pre_predicate \n                -> writing_predicate_uri \n                    -> pre_object \n                        -> writing_object_uri | writing_object_bnode | \n                          ( \n                            writing_object_literal \n                                -> writing_literal_lang | writing_literal_type\n                          )\n                            -> post_object\n                                -> BEGIN\n         } otherwise {\n             -> ERROR\n         }\n*/\nCodeMirror.defineMode(\"ntriples\", function() {  \n\n  Location = {\n    PRE_SUBJECT         : 0,\n    WRITING_SUB_URI     : 1,\n    WRITING_BNODE_URI   : 2,\n    PRE_PRED            : 3,\n    WRITING_PRED_URI    : 4,\n    PRE_OBJ             : 5,\n    WRITING_OBJ_URI     : 6,\n    WRITING_OBJ_BNODE   : 7,\n    WRITING_OBJ_LITERAL : 8,\n    WRITING_LIT_LANG    : 9,\n    WRITING_LIT_TYPE    : 10,\n    POST_OBJ            : 11,\n    ERROR               : 12\n  };\n  function transitState(currState, c) {\n    var currLocation = currState.location;\n    var ret;\n    \n    // Opening.\n    if     (currLocation == Location.PRE_SUBJECT && c == '<') ret = Location.WRITING_SUB_URI;\n    else if(currLocation == Location.PRE_SUBJECT && c == '_') ret = Location.WRITING_BNODE_URI;\n    else if(currLocation == Location.PRE_PRED    && c == '<') ret = Location.WRITING_PRED_URI;\n    else if(currLocation == Location.PRE_OBJ     && c == '<') ret = Location.WRITING_OBJ_URI;\n    else if(currLocation == Location.PRE_OBJ     && c == '_') ret = Location.WRITING_OBJ_BNODE;\n    else if(currLocation == Location.PRE_OBJ     && c == '\"') ret = Location.WRITING_OBJ_LITERAL;\n    \n    // Closing.\n    else if(currLocation == Location.WRITING_SUB_URI     && c == '>') ret = Location.PRE_PRED;\n    else if(currLocation == Location.WRITING_BNODE_URI   && c == ' ') ret = Location.PRE_PRED;\n    else if(currLocation == Location.WRITING_PRED_URI    && c == '>') ret = Location.PRE_OBJ;\n    else if(currLocation == Location.WRITING_OBJ_URI     && c == '>') ret = Location.POST_OBJ;\n    else if(currLocation == Location.WRITING_OBJ_BNODE   && c == ' ') ret = Location.POST_OBJ;\n    else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '\"') ret = Location.POST_OBJ;\n    else if(currLocation == Location.WRITING_LIT_LANG && c == ' ') ret = Location.POST_OBJ;\n    else if(currLocation == Location.WRITING_LIT_TYPE && c == '>') ret = Location.POST_OBJ;\n    \n    // Closing typed and language literal.\n    else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '@') ret = Location.WRITING_LIT_LANG;\n    else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '^') ret = Location.WRITING_LIT_TYPE;\n\n    // Spaces.\n    else if( c == ' ' &&                             \n             (\n               currLocation == Location.PRE_SUBJECT || \n               currLocation == Location.PRE_PRED    || \n               currLocation == Location.PRE_OBJ     || \n               currLocation == Location.POST_OBJ\n             )\n           ) ret = currLocation;\n    \n    // Reset.\n    else if(currLocation == Location.POST_OBJ && c == '.') ret = Location.PRE_SUBJECT;    \n    \n    // Error\n    else ret = Location.ERROR;\n    \n    currState.location=ret;\n  }\n\n  untilSpace  = function(c) { return c != ' '; };\n  untilEndURI = function(c) { return c != '>'; };\n  return {\n    startState: function() {\n       return { \n           location : Location.PRE_SUBJECT,\n           uris     : [],\n           anchors  : [],\n           bnodes   : [],\n           langs    : [],\n           types    : []\n       };\n    },\n    token: function(stream, state) {\n      var ch = stream.next();\n      if(ch == '<') {\n         transitState(state, ch);\n         var parsedURI = '';\n         stream.eatWhile( function(c) { if( c != '#' && c != '>' ) { parsedURI += c; return true; } return false;} );\n         state.uris.push(parsedURI);\n         if( stream.match('#', false) ) return 'variable';\n         stream.next();\n         transitState(state, '>');\n         return 'variable';\n      }\n      if(ch == '#') {\n        var parsedAnchor = '';\n        stream.eatWhile(function(c) { if(c != '>' && c != ' ') { parsedAnchor+= c; return true; } return false});\n        state.anchors.push(parsedAnchor);\n        return 'variable-2';\n      }\n      if(ch == '>') {\n          transitState(state, '>');\n          return 'variable';\n      }\n      if(ch == '_') {\n          transitState(state, ch);\n          var parsedBNode = '';\n          stream.eatWhile(function(c) { if( c != ' ' ) { parsedBNode += c; return true; } return false;});\n          state.bnodes.push(parsedBNode);\n          stream.next();\n          transitState(state, ' ');\n          return 'builtin';\n      }\n      if(ch == '\"') {\n          transitState(state, ch);\n          stream.eatWhile( function(c) { return c != '\"'; } );\n          stream.next();\n          if( stream.peek() != '@' && stream.peek() != '^' ) {\n              transitState(state, '\"');\n          }\n          return 'string';\n      }\n      if( ch == '@' ) {\n          transitState(state, '@');\n          var parsedLang = '';\n          stream.eatWhile(function(c) { if( c != ' ' ) { parsedLang += c; return true; } return false;});\n          state.langs.push(parsedLang);\n          stream.next();\n          transitState(state, ' ');\n          return 'string-2';\n      }\n      if( ch == '^' ) {\n          stream.next();\n          transitState(state, '^');\n          var parsedType = '';\n          stream.eatWhile(function(c) { if( c != '>' ) { parsedType += c; return true; } return false;} );\n          state.types.push(parsedType);\n          stream.next();\n          transitState(state, '>');\n          return 'variable';\n      }\n      if( ch == ' ' ) {\n          transitState(state, ch);\n      }\n      if( ch == '.' ) {\n          transitState(state, ch);\n      }\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/n-triples\", \"ntriples\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/pascal/LICENSE",
    "content": "Copyright (c) 2011 souceLair <support@sourcelair.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/pascal/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Pascal mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"pascal.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: Pascal mode</h1>\n\n<div><textarea id=\"code\" name=\"code\">\n(* Example Pascal code *)\n\nwhile a <> b do writeln('Waiting');\n \nif a > b then \n  writeln('Condition met')\nelse \n  writeln('Condition not met');\n \nfor i := 1 to 10 do \n  writeln('Iteration: ', i:1);\n \nrepeat\n  a := a + 1\nuntil a = 10;\n \ncase i of\n  0: write('zero');\n  1: write('one');\n  2: write('two')\nend;\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-pascal\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-pascal</code>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/pascal/pascal.js",
    "content": "CodeMirror.defineMode(\"pascal\", function(config) {\n  function words(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n  var keywords = words(\"and array begin case const div do downto else end file for forward integer \" +\n                       \"boolean char function goto if in label mod nil not of or packed procedure \" +\n                       \"program record repeat set string then to type until var while with\");\n  var atoms = {\"null\": true};\n\n  var isOperatorChar = /[+\\-*&%=<>!?|\\/]/;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == \"#\" && state.startOfLine) {\n      stream.skipToEnd();\n      return \"meta\";\n    }\n    if (ch == '\"' || ch == \"'\") {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    if (ch == \"(\" && stream.eat(\"*\")) {\n      state.tokenize = tokenComment;\n      return tokenComment(stream, state);\n    }\n    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      return null\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      return \"number\";\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n    }\n    if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_]/);\n    var cur = stream.current();\n    if (keywords.propertyIsEnumerable(cur)) return \"keyword\";\n    if (atoms.propertyIsEnumerable(cur)) return \"atom\";\n    return \"word\";\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next, end = false;\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) {end = true; break;}\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end || !escaped) state.tokenize = null;\n      return \"string\";\n    };\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \")\" && maybeEnd) {\n        state.tokenize = null;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {tokenize: null};\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style == \"comment\" || style == \"meta\") return style;\n      return style;\n    },\n\n    electricChars: \"{}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-pascal\", \"pascal\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/perl/LICENSE",
    "content": "Copyright (C) 2011 by Sabaca <mail@sabaca.com> under the MIT license.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/perl/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Perl mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"perl.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: Perl mode</h1>\n\n<div><textarea id=\"code\" name=\"code\">\n#!/usr/bin/perl\n\nuse Something qw(func1 func2);\n\n# strings\nmy $s1 = qq'single line';\nour $s2 = q(multi-\n              line);\n\n=item Something\n\tExample.\n=cut\n\nmy $html=<<'HTML'\n<html>\n<title>hi!</title>\n</html>\nHTML\n\nprint \"first,\".join(',', 'second', qq~third~);\n\nif($s1 =~ m[(?<!\\s)(l.ne)\\z]o) {\n\t$h->{$1}=$$.' predefined variables';\n\t$s2 =~ s/\\-line//ox;\n\t$s1 =~ s[\n\t\t  line ]\n\t\t[\n\t\t  block\n\t\t]ox;\n}\n\n1; # numbers and comments\n\n__END__\nsomething...\n\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-perl</code>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/perl/perl.js",
    "content": "// CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08)\n// This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com)\nCodeMirror.defineMode(\"perl\",function(config,parserConfig){\n\t// http://perldoc.perl.org\n\tvar PERL={\t\t\t\t    \t//   null - magic touch\n\t\t\t\t\t\t\t//   1 - keyword\n\t\t\t\t\t\t\t//   2 - def\n\t\t\t\t\t\t\t//   3 - atom\n\t\t\t\t\t\t\t//   4 - operator\n\t\t\t\t\t\t\t//   5 - variable-2 (predefined)\n\t\t\t\t\t\t\t//   [x,y] - x=1,2,3; y=must be defined if x{...}\n\t\t\t\t\t\t//\tPERL operators\n\t\t'->'\t\t\t\t:   4,\n\t\t'++'\t\t\t\t:   4,\n\t\t'--'\t\t\t\t:   4,\n\t\t'**'\t\t\t\t:   4,\n\t\t\t\t\t\t\t//   ! ~ \\ and unary + and -\n\t\t'=~'\t\t\t\t:   4,\n\t\t'!~'\t\t\t\t:   4,\n\t\t'*'\t\t\t\t:   4,\n\t\t'/'\t\t\t\t:   4,\n\t\t'%'\t\t\t\t:   4,\n\t\t'x'\t\t\t\t:   4,\n\t\t'+'\t\t\t\t:   4,\n\t\t'-'\t\t\t\t:   4,\n\t\t'.'\t\t\t\t:   4,\n\t\t'<<'\t\t\t\t:   4,\n\t\t'>>'\t\t\t\t:   4,\n\t\t\t\t\t\t\t//   named unary operators\n\t\t'<'\t\t\t\t:   4,\n\t\t'>'\t\t\t\t:   4,\n\t\t'<='\t\t\t\t:   4,\n\t\t'>='\t\t\t\t:   4,\n\t\t'lt'\t\t\t\t:   4,\n\t\t'gt'\t\t\t\t:   4,\n\t\t'le'\t\t\t\t:   4,\n\t\t'ge'\t\t\t\t:   4,\n\t\t'=='\t\t\t\t:   4,\n\t\t'!='\t\t\t\t:   4,\n\t\t'<=>'\t\t\t\t:   4,\n\t\t'eq'\t\t\t\t:   4,\n\t\t'ne'\t\t\t\t:   4,\n\t\t'cmp'\t\t\t\t:   4,\n\t\t'~~'\t\t\t\t:   4,\n\t\t'&'\t\t\t\t:   4,\n\t\t'|'\t\t\t\t:   4,\n\t\t'^'\t\t\t\t:   4,\n\t\t'&&'\t\t\t\t:   4,\n\t\t'||'\t\t\t\t:   4,\n\t\t'//'\t\t\t\t:   4,\n\t\t'..'\t\t\t\t:   4,\n\t\t'...'\t\t\t\t:   4,\n\t\t'?'\t\t\t\t:   4,\n\t\t':'\t\t\t\t:   4,\n\t\t'='\t\t\t\t:   4,\n\t\t'+='\t\t\t\t:   4,\n\t\t'-='\t\t\t\t:   4,\n\t\t'*='\t\t\t\t:   4,\t//   etc. ???\n\t\t','\t\t\t\t:   4,\n\t\t'=>'\t\t\t\t:   4,\n\t\t'::'\t\t\t\t:   4,\n\t\t\t\t   \t\t\t//   list operators (rightward)\n\t\t'not'\t\t\t\t:   4,\n\t\t'and'\t\t\t\t:   4,\n\t\t'or'\t\t\t\t:   4,\n\t\t'xor'\t\t\t\t:   4,\n\t\t\t\t\t\t//\tPERL predefined variables (I know, what this is a paranoid idea, but may be needed for people, who learn PERL, and for me as well, ...and may be for you?;)\n\t\t'BEGIN'\t\t\t\t:   [5,1],\n\t\t'END'\t\t\t\t:   [5,1],\n\t\t'PRINT'\t\t\t\t:   [5,1],\n\t\t'PRINTF'\t\t\t:   [5,1],\n\t\t'GETC'\t\t\t\t:   [5,1],\n\t\t'READ'\t\t\t\t:   [5,1],\n\t\t'READLINE'\t\t\t:   [5,1],\n\t\t'DESTROY'\t\t\t:   [5,1],\n\t\t'TIE'\t\t\t\t:   [5,1],\n\t\t'TIEHANDLE'\t\t\t:   [5,1],\n\t\t'UNTIE'\t\t\t\t:   [5,1],\n\t\t'STDIN'\t\t\t\t:    5,\n\t\t'STDIN_TOP'\t\t\t:    5,\n\t\t'STDOUT'\t\t\t:    5,\n\t\t'STDOUT_TOP'\t\t\t:    5,\n\t\t'STDERR'\t\t\t:    5,\n\t\t'STDERR_TOP'\t\t\t:    5,\n\t\t'$ARG'\t\t\t\t:    5,\n\t\t'$_'\t\t\t\t:    5,\n\t\t'@ARG'\t\t\t\t:    5,\n\t\t'@_'\t\t\t\t:    5,\n\t\t'$LIST_SEPARATOR'\t\t:    5,\n\t\t'$\"'\t\t\t\t:    5,\n\t\t'$PROCESS_ID'\t\t\t:    5,\n\t\t'$PID'\t\t\t\t:    5,\n\t\t'$$'\t\t\t\t:    5,\n\t\t'$REAL_GROUP_ID'\t\t:    5,\n\t\t'$GID'\t\t\t\t:    5,\n\t\t'$('\t\t\t\t:    5,\n\t\t'$EFFECTIVE_GROUP_ID'\t\t:    5,\n\t\t'$EGID'\t\t\t\t:    5,\n\t\t'$)'\t\t\t\t:    5,\n\t\t'$PROGRAM_NAME'\t\t\t:    5,\n\t\t'$0'\t\t\t\t:    5,\n\t\t'$SUBSCRIPT_SEPARATOR'\t\t:    5,\n\t\t'$SUBSEP'\t\t\t:    5,\n\t\t'$;'\t\t\t\t:    5,\n\t\t'$REAL_USER_ID'\t\t\t:    5,\n\t\t'$UID'\t\t\t\t:    5,\n\t\t'$<'\t\t\t\t:    5,\n\t\t'$EFFECTIVE_USER_ID'\t\t:    5,\n\t\t'$EUID'\t\t\t\t:    5,\n\t\t'$>'\t\t\t\t:    5,\n\t\t'$a'\t\t\t\t:    5,\n\t\t'$b'\t\t\t\t:    5,\n\t\t'$COMPILING'\t\t\t:    5,\n\t\t'$^C'\t\t\t\t:    5,\n\t\t'$DEBUGGING'\t\t\t:    5,\n\t\t'$^D'\t\t\t\t:    5,\n\t\t'${^ENCODING}'\t\t\t:    5,\n\t\t'$ENV'\t\t\t\t:    5,\n\t\t'%ENV'\t\t\t\t:    5,\n\t\t'$SYSTEM_FD_MAX'\t\t:    5,\n\t\t'$^F'\t\t\t\t:    5,\n\t\t'@F'\t\t\t\t:    5,\n\t\t'${^GLOBAL_PHASE}'\t\t:    5,\n\t\t'$^H'\t\t\t\t:    5,\n\t\t'%^H'\t\t\t\t:    5,\n\t\t'@INC'\t\t\t\t:    5,\n\t\t'%INC'\t\t\t\t:    5,\n\t\t'$INPLACE_EDIT'\t\t\t:    5,\n\t\t'$^I'\t\t\t\t:    5,\n\t\t'$^M'\t\t\t\t:    5,\n\t\t'$OSNAME'\t\t\t:    5,\n\t\t'$^O'\t\t\t\t:    5,\n\t\t'${^OPEN}'\t\t\t:    5,\n\t\t'$PERLDB'\t\t\t:    5,\n\t\t'$^P'\t\t\t\t:    5,\n\t\t'$SIG'\t\t\t\t:    5,\n\t\t'%SIG'\t\t\t\t:    5,\n\t\t'$BASETIME'\t\t\t:    5,\n\t\t'$^T'\t\t\t\t:    5,\n\t\t'${^TAINT}'\t\t\t:    5,\n\t\t'${^UNICODE}'\t\t\t:    5,\n\t\t'${^UTF8CACHE}'\t\t\t:    5,\n\t\t'${^UTF8LOCALE}'\t\t:    5,\n\t\t'$PERL_VERSION'\t\t\t:    5,\n\t\t'$^V'\t\t\t\t:    5,\n\t\t'${^WIN32_SLOPPY_STAT}'\t\t:    5,\n\t\t'$EXECUTABLE_NAME'\t\t:    5,\n\t\t'$^X'\t\t\t\t:    5,\n\t\t'$1'\t\t\t\t:    5,\t// - regexp $1, $2...\n\t\t'$MATCH'\t\t\t:    5,\n\t\t'$&'\t\t\t\t:    5,\n\t\t'${^MATCH}'\t\t\t:    5,\n\t\t'$PREMATCH'\t\t\t:    5,\n\t\t'$`'\t\t\t\t:    5,\n\t\t'${^PREMATCH}'\t\t\t:    5,\n\t\t'$POSTMATCH'\t\t\t:    5,\n\t\t\"$'\"\t\t\t\t:    5,\n\t\t'${^POSTMATCH}'\t\t\t:    5,\n\t\t'$LAST_PAREN_MATCH'\t\t:    5,\n\t\t'$+'\t\t\t\t:    5,\n\t\t'$LAST_SUBMATCH_RESULT'\t\t:    5,\n\t\t'$^N'\t\t\t\t:    5,\n\t\t'@LAST_MATCH_END'\t\t:    5,\n\t\t'@+'\t\t\t\t:    5,\n\t\t'%LAST_PAREN_MATCH'\t\t:    5,\n\t\t'%+'\t\t\t\t:    5,\n\t\t'@LAST_MATCH_START'\t\t:    5,\n\t\t'@-'\t\t\t\t:    5,\n\t\t'%LAST_MATCH_START'\t\t:    5,\n\t\t'%-'\t\t\t\t:    5,\n\t\t'$LAST_REGEXP_CODE_RESULT'\t:    5,\n\t\t'$^R'\t\t\t\t:    5,\n\t\t'${^RE_DEBUG_FLAGS}'\t\t:    5,\n\t\t'${^RE_TRIE_MAXBUF}'\t\t:    5,\n\t\t'$ARGV'\t\t\t\t:    5,\n\t\t'@ARGV'\t\t\t\t:    5,\n\t\t'ARGV'\t\t\t\t:    5,\n\t\t'ARGVOUT'\t\t\t:    5,\n\t\t'$OUTPUT_FIELD_SEPARATOR'\t:    5,\n\t\t'$OFS'\t\t\t\t:    5,\n\t\t'$,'\t\t\t\t:    5,\n\t\t'$INPUT_LINE_NUMBER'\t\t:    5,\n\t\t'$NR'\t\t\t\t:    5,\n\t\t'$.'\t\t\t\t:    5,\n\t\t'$INPUT_RECORD_SEPARATOR'\t:    5,\n\t\t'$RS'\t\t\t\t:    5,\n\t\t'$/'\t\t\t\t:    5,\n\t\t'$OUTPUT_RECORD_SEPARATOR'\t:    5,\n\t\t'$ORS'\t\t\t\t:    5,\n\t\t'$\\\\'\t\t\t\t:    5,\n\t\t'$OUTPUT_AUTOFLUSH'\t\t:    5,\n\t\t'$|'\t\t\t\t:    5,\n\t\t'$ACCUMULATOR'\t\t\t:    5,\n\t\t'$^A'\t\t\t\t:    5,\n\t\t'$FORMAT_FORMFEED'\t\t:    5,\n\t\t'$^L'\t\t\t\t:    5,\n\t\t'$FORMAT_PAGE_NUMBER'\t\t:    5,\n\t\t'$%'\t\t\t\t:    5,\n\t\t'$FORMAT_LINES_LEFT'\t\t:    5,\n\t\t'$-'\t\t\t\t:    5,\n\t\t'$FORMAT_LINE_BREAK_CHARACTERS'\t:    5,\n\t\t'$:'\t\t\t\t:    5,\n\t\t'$FORMAT_LINES_PER_PAGE'\t:    5,\n\t\t'$='\t\t\t\t:    5,\n\t\t'$FORMAT_TOP_NAME'\t\t:    5,\n\t\t'$^'\t\t\t\t:    5,\n\t\t'$FORMAT_NAME'\t\t\t:    5,\n\t\t'$~'\t\t\t\t:    5,\n\t\t'${^CHILD_ERROR_NATIVE}'\t:    5,\n\t\t'$EXTENDED_OS_ERROR'\t\t:    5,\n\t\t'$^E'\t\t\t\t:    5,\n\t\t'$EXCEPTIONS_BEING_CAUGHT'\t:    5,\n\t\t'$^S'\t\t\t\t:    5,\n\t\t'$WARNING'\t\t\t:    5,\n\t\t'$^W'\t\t\t\t:    5,\n\t\t'${^WARNING_BITS}'\t\t:    5,\n\t\t'$OS_ERROR'\t\t\t:    5,\n\t\t'$ERRNO'\t\t\t:    5,\n\t\t'$!'\t\t\t\t:    5,\n\t\t'%OS_ERROR'\t\t\t:    5,\n\t\t'%ERRNO'\t\t\t:    5,\n\t\t'%!'\t\t\t\t:    5,\n\t\t'$CHILD_ERROR'\t\t\t:    5,\n\t\t'$?'\t\t\t\t:    5,\n\t\t'$EVAL_ERROR'\t\t\t:    5,\n\t\t'$@'\t\t\t\t:    5,\n\t\t'$OFMT'\t\t\t\t:    5,\n\t\t'$#'\t\t\t\t:    5,\n\t\t'$*'\t\t\t\t:    5,\n\t\t'$ARRAY_BASE'\t\t\t:    5,\n\t\t'$['\t\t\t\t:    5,\n\t\t'$OLD_PERL_VERSION'\t\t:    5,\n\t\t'$]'\t\t\t\t:    5,\n\t\t\t\t\t\t//\tPERL blocks\n\t\t'if'\t\t\t\t:[1,1],\n\t\telsif\t\t\t\t:[1,1],\n\t\t'else'\t\t\t\t:[1,1],\n\t\t'while'\t\t\t\t:[1,1],\n\t\tunless\t\t\t\t:[1,1],\n\t\t'for'\t\t\t\t:[1,1],\n\t\tforeach\t\t\t\t:[1,1],\n\t\t\t\t\t\t//\tPERL functions\n\t\t'abs'\t\t\t\t:1,\t// - absolute value function\n\t\taccept\t\t\t\t:1,\t// - accept an incoming socket connect\n\t\talarm\t\t\t\t:1,\t// - schedule a SIGALRM\n\t\t'atan2'\t\t\t\t:1,\t// - arctangent of Y/X in the range -PI to PI\n\t\tbind\t\t\t\t:1,\t// - binds an address to a socket\n\t\tbinmode\t\t\t\t:1,\t// - prepare binary files for I/O\n\t\tbless\t\t\t\t:1,\t// - create an object\n\t\tbootstrap\t\t\t:1,\t//\n\t\t'break'\t\t\t\t:1,\t// - break out of a \"given\" block\n\t\tcaller\t\t\t\t:1,\t// - get context of the current subroutine call\n\t\tchdir\t\t\t\t:1,\t// - change your current working directory\n\t\tchmod\t\t\t\t:1,\t// - changes the permissions on a list of files\n\t\tchomp\t\t\t\t:1,\t// - remove a trailing record separator from a string\n\t\tchop\t\t\t\t:1,\t// - remove the last character from a string\n\t\tchown\t\t\t\t:1,\t// - change the owership on a list of files\n\t\tchr\t\t\t\t:1,\t// - get character this number represents\n\t\tchroot\t\t\t\t:1,\t// - make directory new root for path lookups\n\t\tclose\t\t\t\t:1,\t// - close file (or pipe or socket) handle\n\t\tclosedir\t\t\t:1,\t// - close directory handle\n\t\tconnect\t\t\t\t:1,\t// - connect to a remote socket\n\t\t'continue'\t\t\t:[1,1],\t// - optional trailing block in a while or foreach\n\t\t'cos'\t\t\t\t:1,\t// - cosine function\n\t\tcrypt\t\t\t\t:1,\t// - one-way passwd-style encryption\n\t\tdbmclose\t\t\t:1,\t// - breaks binding on a tied dbm file\n\t\tdbmopen\t\t\t\t:1,\t// - create binding on a tied dbm file\n\t\t'default'\t\t\t:1,\t//\n\t\tdefined\t\t\t\t:1,\t// - test whether a value, variable, or function is defined\n\t\t'delete'\t\t\t:1,\t// - deletes a value from a hash\n\t\tdie\t\t\t\t:1,\t// - raise an exception or bail out\n\t\t'do'\t\t\t\t:1,\t// - turn a BLOCK into a TERM\n\t\tdump\t\t\t\t:1,\t// - create an immediate core dump\n\t\teach\t\t\t\t:1,\t// - retrieve the next key/value pair from a hash\n\t\tendgrent\t\t\t:1,\t// - be done using group file\n\t\tendhostent\t\t\t:1,\t// - be done using hosts file\n\t\tendnetent\t\t\t:1,\t// - be done using networks file\n\t\tendprotoent\t\t\t:1,\t// - be done using protocols file\n\t\tendpwent\t\t\t:1,\t// - be done using passwd file\n\t\tendservent\t\t\t:1,\t// - be done using services file\n\t\teof\t\t\t\t:1,\t// - test a filehandle for its end\n\t\t'eval'\t\t\t\t:1,\t// - catch exceptions or compile and run code\n\t\t'exec'\t\t\t\t:1,\t// - abandon this program to run another\n\t\texists\t\t\t\t:1,\t// - test whether a hash key is present\n\t\texit\t\t\t\t:1,\t// - terminate this program\n\t\t'exp'\t\t\t\t:1,\t// - raise I to a power\n\t\tfcntl\t\t\t\t:1,\t// - file control system call\n\t\tfileno\t\t\t\t:1,\t// - return file descriptor from filehandle\n\t\tflock\t\t\t\t:1,\t// - lock an entire file with an advisory lock\n\t\tfork\t\t\t\t:1,\t// - create a new process just like this one\n\t\tformat\t\t\t\t:1,\t// - declare a picture format with use by the write() function\n\t\tformline\t\t\t:1,\t// - internal function used for formats\n\t\tgetc\t\t\t\t:1,\t// - get the next character from the filehandle\n\t\tgetgrent\t\t\t:1,\t// - get next group record\n\t\tgetgrgid\t\t\t:1,\t// - get group record given group user ID\n\t\tgetgrnam\t\t\t:1,\t// - get group record given group name\n\t\tgethostbyaddr\t\t\t:1,\t// - get host record given its address\n\t\tgethostbyname\t\t\t:1,\t// - get host record given name\n\t\tgethostent\t\t\t:1,\t// - get next hosts record\n\t\tgetlogin\t\t\t:1,\t// - return who logged in at this tty\n\t\tgetnetbyaddr\t\t\t:1,\t// - get network record given its address\n\t\tgetnetbyname\t\t\t:1,\t// - get networks record given name\n\t\tgetnetent\t\t\t:1,\t// - get next networks record\n\t\tgetpeername\t\t\t:1,\t// - find the other end of a socket connection\n\t\tgetpgrp\t\t\t\t:1,\t// - get process group\n\t\tgetppid\t\t\t\t:1,\t// - get parent process ID\n\t\tgetpriority\t\t\t:1,\t// - get current nice value\n\t\tgetprotobyname\t\t\t:1,\t// - get protocol record given name\n\t\tgetprotobynumber\t\t:1,\t// - get protocol record numeric protocol\n\t\tgetprotoent\t\t\t:1,\t// - get next protocols record\n\t\tgetpwent\t\t\t:1,\t// - get next passwd record\n\t\tgetpwnam\t\t\t:1,\t// - get passwd record given user login name\n\t\tgetpwuid\t\t\t:1,\t// - get passwd record given user ID\n\t\tgetservbyname\t\t\t:1,\t// - get services record given its name\n\t\tgetservbyport\t\t\t:1,\t// - get services record given numeric port\n\t\tgetservent\t\t\t:1,\t// - get next services record\n\t\tgetsockname\t\t\t:1,\t// - retrieve the sockaddr for a given socket\n\t\tgetsockopt\t\t\t:1,\t// - get socket options on a given socket\n\t\tgiven\t\t\t\t:1,\t//\n\t\tglob\t\t\t\t:1,\t// - expand filenames using wildcards\n\t\tgmtime\t\t\t\t:1,\t// - convert UNIX time into record or string using Greenwich time\n\t\t'goto'\t\t\t\t:1,\t// - create spaghetti code\n\t\tgrep\t\t\t\t:1,\t// - locate elements in a list test true against a given criterion\n\t\thex\t\t\t\t:1,\t// - convert a string to a hexadecimal number\n\t\t'import'\t\t\t:1,\t// - patch a module's namespace into your own\n\t\tindex\t\t\t\t:1,\t// - find a substring within a string\n\t\t'int'\t\t\t\t:1,\t// - get the integer portion of a number\n\t\tioctl\t\t\t\t:1,\t// - system-dependent device control system call\n\t\t'join'\t\t\t\t:1,\t// - join a list into a string using a separator\n\t\tkeys\t\t\t\t:1,\t// - retrieve list of indices from a hash\n\t\tkill\t\t\t\t:1,\t// - send a signal to a process or process group\n\t\tlast\t\t\t\t:1,\t// - exit a block prematurely\n\t\tlc\t\t\t\t:1,\t// - return lower-case version of a string\n\t\tlcfirst\t\t\t\t:1,\t// - return a string with just the next letter in lower case\n\t\tlength\t\t\t\t:1,\t// - return the number of bytes in a string\n\t\t'link'\t\t\t\t:1,\t// - create a hard link in the filesytem\n\t\tlisten\t\t\t\t:1,\t// - register your socket as a server\n\t\tlocal\t\t\t\t: 2,\t// - create a temporary value for a global variable (dynamic scoping)\n\t\tlocaltime\t\t\t:1,\t// - convert UNIX time into record or string using local time\n\t\tlock\t\t\t\t:1,\t// - get a thread lock on a variable, subroutine, or method\n\t\t'log'\t\t\t\t:1,\t// - retrieve the natural logarithm for a number\n\t\tlstat\t\t\t\t:1,\t// - stat a symbolic link\n\t\tm\t\t\t\t:null,\t// - match a string with a regular expression pattern\n\t\tmap\t\t\t\t:1,\t// - apply a change to a list to get back a new list with the changes\n\t\tmkdir\t\t\t\t:1,\t// - create a directory\n\t\tmsgctl\t\t\t\t:1,\t// - SysV IPC message control operations\n\t\tmsgget\t\t\t\t:1,\t// - get SysV IPC message queue\n\t\tmsgrcv\t\t\t\t:1,\t// - receive a SysV IPC message from a message queue\n\t\tmsgsnd\t\t\t\t:1,\t// - send a SysV IPC message to a message queue\n\t\tmy\t\t\t\t: 2,\t// - declare and assign a local variable (lexical scoping)\n\t\t'new'\t\t\t\t:1,\t//\n\t\tnext\t\t\t\t:1,\t// - iterate a block prematurely\n\t\tno\t\t\t\t:1,\t// - unimport some module symbols or semantics at compile time\n\t\toct\t\t\t\t:1,\t// - convert a string to an octal number\n\t\topen\t\t\t\t:1,\t// - open a file, pipe, or descriptor\n\t\topendir\t\t\t\t:1,\t// - open a directory\n\t\tord\t\t\t\t:1,\t// - find a character's numeric representation\n\t\tour\t\t\t\t: 2,\t// - declare and assign a package variable (lexical scoping)\n\t\tpack\t\t\t\t:1,\t// - convert a list into a binary representation\n\t\t'package'\t\t\t:1,\t// - declare a separate global namespace\n\t\tpipe\t\t\t\t:1,\t// - open a pair of connected filehandles\n\t\tpop\t\t\t\t:1,\t// - remove the last element from an array and return it\n\t\tpos\t\t\t\t:1,\t// - find or set the offset for the last/next m//g search\n\t\tprint\t\t\t\t:1,\t// - output a list to a filehandle\n\t\tprintf\t\t\t\t:1,\t// - output a formatted list to a filehandle\n\t\tprototype\t\t\t:1,\t// - get the prototype (if any) of a subroutine\n\t\tpush\t\t\t\t:1,\t// - append one or more elements to an array\n\t\tq\t\t\t\t:null,\t// - singly quote a string\n\t\tqq\t\t\t\t:null,\t// - doubly quote a string\n\t\tqr\t\t\t\t:null,\t// - Compile pattern\n\t\tquotemeta\t\t\t:null,\t// - quote regular expression magic characters\n\t\tqw\t\t\t\t:null,\t// - quote a list of words\n\t\tqx\t\t\t\t:null,\t// - backquote quote a string\n\t\trand\t\t\t\t:1,\t// - retrieve the next pseudorandom number\n\t\tread\t\t\t\t:1,\t// - fixed-length buffered input from a filehandle\n\t\treaddir\t\t\t\t:1,\t// - get a directory from a directory handle\n\t\treadline\t\t\t:1,\t// - fetch a record from a file\n\t\treadlink\t\t\t:1,\t// - determine where a symbolic link is pointing\n\t\treadpipe\t\t\t:1,\t// - execute a system command and collect standard output\n\t\trecv\t\t\t\t:1,\t// - receive a message over a Socket\n\t\tredo\t\t\t\t:1,\t// - start this loop iteration over again\n\t\tref\t\t\t\t:1,\t// - find out the type of thing being referenced\n\t\trename\t\t\t\t:1,\t// - change a filename\n\t\trequire\t\t\t\t:1,\t// - load in external functions from a library at runtime\n\t\treset\t\t\t\t:1,\t// - clear all variables of a given name\n\t\t'return'\t\t\t:1,\t// - get out of a function early\n\t\treverse\t\t\t\t:1,\t// - flip a string or a list\n\t\trewinddir\t\t\t:1,\t// - reset directory handle\n\t\trindex\t\t\t\t:1,\t// - right-to-left substring search\n\t\trmdir\t\t\t\t:1,\t// - remove a directory\n\t\ts\t\t\t\t:null,\t// - replace a pattern with a string\n\t\tsay\t\t\t\t:1,\t// - print with newline\n\t\tscalar\t\t\t\t:1,\t// - force a scalar context\n\t\tseek\t\t\t\t:1,\t// - reposition file pointer for random-access I/O\n\t\tseekdir\t\t\t\t:1,\t// - reposition directory pointer\n\t\tselect\t\t\t\t:1,\t// - reset default output or do I/O multiplexing\n\t\tsemctl\t\t\t\t:1,\t// - SysV semaphore control operations\n\t\tsemget\t\t\t\t:1,\t// - get set of SysV semaphores\n\t\tsemop\t\t\t\t:1,\t// - SysV semaphore operations\n\t\tsend\t\t\t\t:1,\t// - send a message over a socket\n\t\tsetgrent\t\t\t:1,\t// - prepare group file for use\n\t\tsethostent\t\t\t:1,\t// - prepare hosts file for use\n\t\tsetnetent\t\t\t:1,\t// - prepare networks file for use\n\t\tsetpgrp\t\t\t\t:1,\t// - set the process group of a process\n\t\tsetpriority\t\t\t:1,\t// - set a process's nice value\n\t\tsetprotoent\t\t\t:1,\t// - prepare protocols file for use\n\t\tsetpwent\t\t\t:1,\t// - prepare passwd file for use\n\t\tsetservent\t\t\t:1,\t// - prepare services file for use\n\t\tsetsockopt\t\t\t:1,\t// - set some socket options\n\t\tshift\t\t\t\t:1,\t// - remove the first element of an array, and return it\n\t\tshmctl\t\t\t\t:1,\t// - SysV shared memory operations\n\t\tshmget\t\t\t\t:1,\t// - get SysV shared memory segment identifier\n\t\tshmread\t\t\t\t:1,\t// - read SysV shared memory\n\t\tshmwrite\t\t\t:1,\t// - write SysV shared memory\n\t\tshutdown\t\t\t:1,\t// - close down just half of a socket connection\n\t\t'sin'\t\t\t\t:1,\t// - return the sine of a number\n\t\tsleep\t\t\t\t:1,\t// - block for some number of seconds\n\t\tsocket\t\t\t\t:1,\t// - create a socket\n\t\tsocketpair\t\t\t:1,\t// - create a pair of sockets\n\t\t'sort'\t\t\t\t:1,\t// - sort a list of values\n\t\tsplice\t\t\t\t:1,\t// - add or remove elements anywhere in an array\n\t\t'split'\t\t\t\t:1,\t// - split up a string using a regexp delimiter\n\t\tsprintf\t\t\t\t:1,\t// - formatted print into a string\n\t\t'sqrt'\t\t\t\t:1,\t// - square root function\n\t\tsrand\t\t\t\t:1,\t// - seed the random number generator\n\t\tstat\t\t\t\t:1,\t// - get a file's status information\n\t\tstate\t\t\t\t:1,\t// - declare and assign a state variable (persistent lexical scoping)\n\t\tstudy\t\t\t\t:1,\t// - optimize input data for repeated searches\n\t\t'sub'\t\t\t\t:1,\t// - declare a subroutine, possibly anonymously\n\t\t'substr'\t\t\t:1,\t// - get or alter a portion of a stirng\n\t\tsymlink\t\t\t\t:1,\t// - create a symbolic link to a file\n\t\tsyscall\t\t\t\t:1,\t// - execute an arbitrary system call\n\t\tsysopen\t\t\t\t:1,\t// - open a file, pipe, or descriptor\n\t\tsysread\t\t\t\t:1,\t// - fixed-length unbuffered input from a filehandle\n\t\tsysseek\t\t\t\t:1,\t// - position I/O pointer on handle used with sysread and syswrite\n\t\tsystem\t\t\t\t:1,\t// - run a separate program\n\t\tsyswrite\t\t\t:1,\t// - fixed-length unbuffered output to a filehandle\n\t\ttell\t\t\t\t:1,\t// - get current seekpointer on a filehandle\n\t\ttelldir\t\t\t\t:1,\t// - get current seekpointer on a directory handle\n\t\ttie\t\t\t\t:1,\t// - bind a variable to an object class\n\t\ttied\t\t\t\t:1,\t// - get a reference to the object underlying a tied variable\n\t\ttime\t\t\t\t:1,\t// - return number of seconds since 1970\n\t\ttimes\t\t\t\t:1,\t// - return elapsed time for self and child processes\n\t\ttr\t\t\t\t:null,\t// - transliterate a string\n\t\ttruncate\t\t\t:1,\t// - shorten a file\n\t\tuc\t\t\t\t:1,\t// - return upper-case version of a string\n\t\tucfirst\t\t\t\t:1,\t// - return a string with just the next letter in upper case\n\t\tumask\t\t\t\t:1,\t// - set file creation mode mask\n\t\tundef\t\t\t\t:1,\t// - remove a variable or function definition\n\t\tunlink\t\t\t\t:1,\t// - remove one link to a file\n\t\tunpack\t\t\t\t:1,\t// - convert binary structure into normal perl variables\n\t\tunshift\t\t\t\t:1,\t// - prepend more elements to the beginning of a list\n\t\tuntie\t\t\t\t:1,\t// - break a tie binding to a variable\n\t\tuse\t\t\t\t:1,\t// - load in a module at compile time\n\t\tutime\t\t\t\t:1,\t// - set a file's last access and modify times\n\t\tvalues\t\t\t\t:1,\t// - return a list of the values in a hash\n\t\tvec\t\t\t\t:1,\t// - test or set particular bits in a string\n\t\twait\t\t\t\t:1,\t// - wait for any child process to die\n\t\twaitpid\t\t\t\t:1,\t// - wait for a particular child process to die\n\t\twantarray\t\t\t:1,\t// - get void vs scalar vs list context of current subroutine call\n\t\twarn\t\t\t\t:1,\t// - print debugging info\n\t\twhen\t\t\t\t:1,\t//\n\t\twrite\t\t\t\t:1,\t// - print a picture record\n\t\ty\t\t\t\t:null};\t// - transliterate a string\n\n\tvar RXstyle=\"string-2\";\n\tvar RXmodifiers=/[goseximacplud]/;\t\t// NOTE: \"m\", \"s\", \"y\" and \"tr\" need to correct real modifiers for each regexp type\n\n\tfunction tokenChain(stream,state,chain,style,tail){\t// NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;)\n\t\tstate.chain=null;                               //                                                          12   3tail\n\t\tstate.style=null;\n\t\tstate.tail=null;\n\t\tstate.tokenize=function(stream,state){\n\t\t\tvar e=false,c,i=0;\n\t\t\twhile(c=stream.next()){\n\t\t\t\tif(c===chain[i]&&!e){\n\t\t\t\t\tif(chain[++i]!==undefined){\n\t\t\t\t\t\tstate.chain=chain[i];\n\t\t\t\t\t\tstate.style=style;\n\t\t\t\t\t\tstate.tail=tail}\n\t\t\t\t\telse if(tail)\n\t\t\t\t\t\tstream.eatWhile(tail);\n\t\t\t\t\tstate.tokenize=tokenPerl;\n\t\t\t\t\treturn style}\n\t\t\t\te=!e&&c==\"\\\\\"}\n\t\t\treturn style};\n\t\treturn state.tokenize(stream,state)}\n\n\tfunction tokenSOMETHING(stream,state,string){\n\t\tstate.tokenize=function(stream,state){\n\t\t\tif(stream.string==string)\n\t\t\t\tstate.tokenize=tokenPerl;\n\t\t\tstream.skipToEnd();\n\t\t\treturn \"string\"};\n\t\treturn state.tokenize(stream,state)}\n\n\tfunction tokenPerl(stream,state){\n\t\tif(stream.eatSpace())\n\t\t\treturn null;\n\t\tif(state.chain)\n\t\t\treturn tokenChain(stream,state,state.chain,state.style,state.tail);\n\t\tif(stream.match(/^\\-?[\\d\\.]/,false))\n\t\t\tif(stream.match(/^(\\-?(\\d*\\.\\d+(e[+-]?\\d+)?|\\d+\\.\\d*)|0x[\\da-fA-F]+|0b[01]+|\\d+(e[+-]?\\d+)?)/))\n\t\t\t\treturn 'number';\n\t\tif(stream.match(/^<<(?=\\w)/)){\t\t\t// NOTE: <<SOMETHING\\n...\\nSOMETHING\\n\n\t\t\tstream.eatWhile(/\\w/);\n\t\t\treturn tokenSOMETHING(stream,state,stream.current().substr(2))}\n\t\tif(stream.sol()&&stream.match(/^\\=item(?!\\w)/)){// NOTE: \\n=item...\\n=cut\\n\n\t\t\treturn tokenSOMETHING(stream,state,'=cut')}\n\t\tvar ch=stream.next();\n\t\tif(ch=='\"'||ch==\"'\"){\t\t\t\t// NOTE: ' or \" or <<'SOMETHING'\\n...\\nSOMETHING\\n or <<\"SOMETHING\"\\n...\\nSOMETHING\\n\n\t\t\tif(stream.prefix(3)==\"<<\"+ch){\n\t\t\t\tvar p=stream.pos;\n\t\t\t\tstream.eatWhile(/\\w/);\n\t\t\t\tvar n=stream.current().substr(1);\n\t\t\t\tif(n&&stream.eat(ch))\n\t\t\t\t\treturn tokenSOMETHING(stream,state,n);\n\t\t\t\tstream.pos=p}\n\t\t\treturn tokenChain(stream,state,[ch],\"string\")}\n\t\tif(ch==\"q\"){\n\t\t\tvar c=stream.look(-2);\n\t\t\tif(!(c&&/\\w/.test(c))){\n\t\t\t\tc=stream.look(0);\n\t\t\t\tif(c==\"x\"){\n\t\t\t\t\tc=stream.look(1);\n\t\t\t\t\tif(c==\"(\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"[\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"{\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"<\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(/[\\^'\"!~\\/]/.test(c)){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers)}}\n\t\t\t\telse if(c==\"q\"){\n\t\t\t\t\tc=stream.look(1);\n\t\t\t\t\tif(c==\"(\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\"],\"string\")}\n\t\t\t\t\tif(c==\"[\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\"],\"string\")}\n\t\t\t\t\tif(c==\"{\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\"],\"string\")}\n\t\t\t\t\tif(c==\"<\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\"],\"string\")}\n\t\t\t\t\tif(/[\\^'\"!~\\/]/.test(c)){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[stream.eat(c)],\"string\")}}\n\t\t\t\telse if(c==\"w\"){\n\t\t\t\t\tc=stream.look(1);\n\t\t\t\t\tif(c==\"(\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\"],\"bracket\")}\n\t\t\t\t\tif(c==\"[\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\"],\"bracket\")}\n\t\t\t\t\tif(c==\"{\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\"],\"bracket\")}\n\t\t\t\t\tif(c==\"<\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\"],\"bracket\")}\n\t\t\t\t\tif(/[\\^'\"!~\\/]/.test(c)){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[stream.eat(c)],\"bracket\")}}\n\t\t\t\telse if(c==\"r\"){\n\t\t\t\t\tc=stream.look(1);\n\t\t\t\t\tif(c==\"(\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"[\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"{\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"<\"){\n\t\t\t\t\t\tstream.eatSuffix(2);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(/[\\^'\"!~\\/]/.test(c)){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers)}}\n\t\t\t\telse if(/[\\^'\"!~\\/(\\[{<]/.test(c)){\n\t\t\t\t\tif(c==\"(\"){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\"],\"string\")}\n\t\t\t\t\tif(c==\"[\"){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\"],\"string\")}\n\t\t\t\t\tif(c==\"{\"){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\"],\"string\")}\n\t\t\t\t\tif(c==\"<\"){\n\t\t\t\t\t\tstream.eatSuffix(1);\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\"],\"string\")}\n\t\t\t\t\tif(/[\\^'\"!~\\/]/.test(c)){\n\t\t\t\t\t\treturn tokenChain(stream,state,[stream.eat(c)],\"string\")}}}}\n\t\tif(ch==\"m\"){\n\t\t\tvar c=stream.look(-2);\n\t\t\tif(!(c&&/\\w/.test(c))){\n\t\t\t\tc=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n\t\t\t\tif(c){\n\t\t\t\t\tif(/[\\^'\"!~\\/]/.test(c)){\n\t\t\t\t\t\treturn tokenChain(stream,state,[c],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"(\"){\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"[\"){\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"{\"){\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\"],RXstyle,RXmodifiers)}\n\t\t\t\t\tif(c==\"<\"){\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\"],RXstyle,RXmodifiers)}}}}\n\t\tif(ch==\"s\"){\n\t\t\tvar c=/[\\/>\\]})\\w]/.test(stream.look(-2));\n\t\t\tif(!c){\n\t\t\t\tc=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n\t\t\t\tif(c){\n\t\t\t\t\tif(c==\"[\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\",\"]\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"{\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\",\"}\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"<\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\",\">\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"(\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\",\")\"],RXstyle,RXmodifiers);\n\t\t\t\t\treturn tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}\n\t\tif(ch==\"y\"){\n\t\t\tvar c=/[\\/>\\]})\\w]/.test(stream.look(-2));\n\t\t\tif(!c){\n\t\t\t\tc=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n\t\t\t\tif(c){\n\t\t\t\t\tif(c==\"[\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\",\"]\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"{\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\",\"}\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"<\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\",\">\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"(\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\",\")\"],RXstyle,RXmodifiers);\n\t\t\t\t\treturn tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}\n\t\tif(ch==\"t\"){\n\t\t\tvar c=/[\\/>\\]})\\w]/.test(stream.look(-2));\n\t\t\tif(!c){\n\t\t\t\tc=stream.eat(\"r\");if(c){\n\t\t\t\tc=stream.eat(/[(\\[{<\\^'\"!~\\/]/);\n\t\t\t\tif(c){\n\t\t\t\t\tif(c==\"[\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"]\",\"]\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"{\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\"}\",\"}\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"<\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\">\",\">\"],RXstyle,RXmodifiers);\n\t\t\t\t\tif(c==\"(\")\n\t\t\t\t\t\treturn tokenChain(stream,state,[\")\",\")\"],RXstyle,RXmodifiers);\n\t\t\t\t\treturn tokenChain(stream,state,[c,c],RXstyle,RXmodifiers)}}}}\n\t\tif(ch==\"`\"){\n\t\t\treturn tokenChain(stream,state,[ch],\"variable-2\")}\n\t\tif(ch==\"/\"){\n\t\t\tif(!/~\\s*$/.test(stream.prefix()))\n\t\t\t\treturn \"operator\";\n\t\t\telse\n\t\t\t\treturn tokenChain(stream,state,[ch],RXstyle,RXmodifiers)}\n\t\tif(ch==\"$\"){\n\t\t\tvar p=stream.pos;\n\t\t\tif(stream.eatWhile(/\\d/)||stream.eat(\"{\")&&stream.eatWhile(/\\d/)&&stream.eat(\"}\"))\n\t\t\t\treturn \"variable-2\";\n\t\t\telse\n\t\t\t\tstream.pos=p}\n\t\tif(/[$@%]/.test(ch)){\n\t\t\tvar p=stream.pos;\n\t\t\tif(stream.eat(\"^\")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(stream.look(-2))&&stream.eat(/[=|\\\\\\-#?@;:&`~\\^!\\[\\]*'\"$+.,\\/<>()]/)){\n\t\t\t\tvar c=stream.current();\n\t\t\t\tif(PERL[c])\n\t\t\t\t\treturn \"variable-2\"}\n\t\t\tstream.pos=p}\n\t\tif(/[$@%&]/.test(ch)){\n\t\t\tif(stream.eatWhile(/[\\w$\\[\\]]/)||stream.eat(\"{\")&&stream.eatWhile(/[\\w$\\[\\]]/)&&stream.eat(\"}\")){\n\t\t\t\tvar c=stream.current();\n\t\t\t\tif(PERL[c])\n\t\t\t\t\treturn \"variable-2\";\n\t\t\t\telse\n\t\t\t\t\treturn \"variable\"}}\n\t\tif(ch==\"#\"){\n\t\t\tif(stream.look(-2)!=\"$\"){\n\t\t\t\tstream.skipToEnd();\n\t\t\t\treturn \"comment\"}}\n\t\tif(/[:+\\-\\^*$&%@=<>!?|\\/~\\.]/.test(ch)){\n\t\t\tvar p=stream.pos;\n\t\t\tstream.eatWhile(/[:+\\-\\^*$&%@=<>!?|\\/~\\.]/);\n\t\t\tif(PERL[stream.current()])\n\t\t\t\treturn \"operator\";\n\t\t\telse\n\t\t\t\tstream.pos=p}\n\t\tif(ch==\"_\"){\n\t\t\tif(stream.pos==1){\n\t\t\t\tif(stream.suffix(6)==\"_END__\"){\n\t\t\t\t\treturn tokenChain(stream,state,['\\0'],\"comment\")}\n\t\t\t\telse if(stream.suffix(7)==\"_DATA__\"){\n\t\t\t\t\treturn tokenChain(stream,state,['\\0'],\"variable-2\")}\n\t\t\t\telse if(stream.suffix(7)==\"_C__\"){\n\t\t\t\t\treturn tokenChain(stream,state,['\\0'],\"string\")}}}\n\t\tif(/\\w/.test(ch)){\n\t\t\tvar p=stream.pos;\n\t\t\tif(stream.look(-2)==\"{\"&&(stream.look(0)==\"}\"||stream.eatWhile(/\\w/)&&stream.look(0)==\"}\"))\n\t\t\t\treturn \"string\";\n\t\t\telse\n\t\t\t\tstream.pos=p}\n\t\tif(/[A-Z]/.test(ch)){\n\t\t\tvar l=stream.look(-2);\n\t\t\tvar p=stream.pos;\n\t\t\tstream.eatWhile(/[A-Z_]/);\n\t\t\tif(/[\\da-z]/.test(stream.look(0))){\n\t\t\t\tstream.pos=p}\n\t\t\telse{\n\t\t\t\tvar c=PERL[stream.current()];\n\t\t\t\tif(!c)\n\t\t\t\t\treturn \"meta\";\n\t\t\t\tif(c[1])\n\t\t\t\t\tc=c[0];\n\t\t\t\tif(l!=\":\"){\n\t\t\t\t\tif(c==1)\n\t\t\t\t\t\treturn \"keyword\";\n\t\t\t\t\telse if(c==2)\n\t\t\t\t\t\treturn \"def\";\n\t\t\t\t\telse if(c==3)\n\t\t\t\t\t\treturn \"atom\";\n\t\t\t\t\telse if(c==4)\n\t\t\t\t\t\treturn \"operator\";\n\t\t\t\t\telse if(c==5)\n\t\t\t\t\t\treturn \"variable-2\";\n\t\t\t\t\telse\n\t\t\t\t\t\treturn \"meta\"}\n\t\t\t\telse\n\t\t\t\t\treturn \"meta\"}}\n\t\tif(/[a-zA-Z_]/.test(ch)){\n\t\t\tvar l=stream.look(-2);\n\t\t\tstream.eatWhile(/\\w/);\n\t\t\tvar c=PERL[stream.current()];\n\t\t\tif(!c)\n\t\t\t\treturn \"meta\";\n\t\t\tif(c[1])\n\t\t\t\tc=c[0];\n\t\t\tif(l!=\":\"){\n\t\t\t\tif(c==1)\n\t\t\t\t\treturn \"keyword\";\n\t\t\t\telse if(c==2)\n\t\t\t\t\treturn \"def\";\n\t\t\t\telse if(c==3)\n\t\t\t\t\treturn \"atom\";\n\t\t\t\telse if(c==4)\n\t\t\t\t\treturn \"operator\";\n\t\t\t\telse if(c==5)\n\t\t\t\t\treturn \"variable-2\";\n\t\t\t\telse\n\t\t\t\t\treturn \"meta\"}\n\t\t\telse\n\t\t\t\treturn \"meta\"}\n\t\treturn null}\n\n\treturn{\n\t\tstartState:function(){\n\t\t\treturn{\n\t\t\t\ttokenize:tokenPerl,\n\t\t\t\tchain:null,\n\t\t\t\tstyle:null,\n\t\t\t\ttail:null}},\n\t\ttoken:function(stream,state){\n\t\t\treturn (state.tokenize||tokenPerl)(stream,state)},\n\t\telectricChars:\"{}\"}});\n\nCodeMirror.defineMIME(\"text/x-perl\", \"perl\");\n\n// it's like \"peek\", but need for look-ahead or look-behind if index < 0\nCodeMirror.StringStream.prototype.look=function(c){\n\treturn this.string.charAt(this.pos+(c||0))};\n\n// return a part of prefix of current stream from current position\nCodeMirror.StringStream.prototype.prefix=function(c){\n\tif(c){\n\t\tvar x=this.pos-c;\n\t\treturn this.string.substr((x>=0?x:0),c)}\n\telse{\n\t\treturn this.string.substr(0,this.pos-1)}};\n\n// return a part of suffix of current stream from current position\nCodeMirror.StringStream.prototype.suffix=function(c){\n\tvar y=this.string.length;\n\tvar x=y-this.pos+1;\n\treturn this.string.substr(this.pos,(c&&c<y?c:x))};\n\n// return a part of suffix of current stream from current position and change current position\nCodeMirror.StringStream.prototype.nsuffix=function(c){\n\tvar p=this.pos;\n\tvar l=c||(this.string.length-this.pos+1);\n\tthis.pos+=l;\n\treturn this.string.substr(p,l)};\n\n// eating and vomiting a part of stream from current position\nCodeMirror.StringStream.prototype.eatSuffix=function(c){\n\tvar x=this.pos+c;\n\tvar y;\n\tif(x<=0)\n\t\tthis.pos=0;\n\telse if(x>=(y=this.string.length-1))\n\t\tthis.pos=y;\n\telse\n\t\tthis.pos=x};\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/php/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: PHP mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"../xml/xml.js\"></script>\n    <script src=\"../javascript/javascript.js\"></script>\n    <script src=\"../css/css.js\"></script>\n    <script src=\"../clike/clike.js\"></script>\n    <script src=\"php.js\"></script>\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: PHP mode</h1>\n\n<form><textarea id=\"code\" name=\"code\">\n<?php\nfunction hello($who) {\n\treturn \"Hello \" . $who;\n}\n?>\n<p>The program says <?= hello(\"World\") ?>.</p>\n<script>\n\talert(\"And here is some JS code\"); // also colored\n</script>\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"application/x-httpd-php\",\n        indentUnit: 4,\n        indentWithTabs: true,\n        enterMode: \"keep\",\n        tabMode: \"shift\"\n      });\n    </script>\n\n    <p>Simple HTML/PHP mode based on\n    the <a href=\"../clike/\">C-like</a> mode. Depends on XML,\n    JavaScript, CSS, and C-like modes.</p>\n\n    <p><strong>MIME types defined:</strong> <code>application/x-httpd-php</code> (HTML with PHP code), <code>text/x-php</code> (plain, non-wrapped PHP code).</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/php/php.js",
    "content": "(function() {\n  function keywords(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n  function heredoc(delim) {\n    return function(stream, state) {\n      if (stream.match(delim)) state.tokenize = null;\n      else stream.skipToEnd();\n      return \"string\";\n    }\n  }\n  var phpConfig = {\n    name: \"clike\",\n    keywords: keywords(\"abstract and array as break case catch class clone const continue declare default \" +\n                       \"do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final \" +\n                       \"for foreach function global goto if implements interface instanceof namespace \" +\n                       \"new or private protected public static switch throw trait try use var while xor \" +\n                       \"die echo empty exit eval include include_once isset list require require_once return \" +\n                       \"print unset __halt_compiler self static parent\"),\n    blockKeywords: keywords(\"catch do else elseif for foreach if switch try while\"),\n    atoms: keywords(\"true false null TRUE FALSE NULL\"),\n    multiLineStrings: true,\n    hooks: {\n      \"$\": function(stream, state) {\n        stream.eatWhile(/[\\w\\$_]/);\n        return \"variable-2\";\n      },\n      \"<\": function(stream, state) {\n        if (stream.match(/<</)) {\n          stream.eatWhile(/[\\w\\.]/);\n          state.tokenize = heredoc(stream.current().slice(3));\n          return state.tokenize(stream, state);\n        }\n        return false;\n      },\n      \"#\": function(stream, state) {\n        while (!stream.eol() && !stream.match(\"?>\", false)) stream.next();\n        return \"comment\";\n      },\n      \"/\": function(stream, state) {\n        if (stream.eat(\"/\")) {\n          while (!stream.eol() && !stream.match(\"?>\", false)) stream.next();\n          return \"comment\";\n        }\n        return false;\n      }\n    }\n  };\n\n  CodeMirror.defineMode(\"php\", function(config, parserConfig) {\n    var htmlMode = CodeMirror.getMode(config, {name: \"xml\", htmlMode: true});\n    var jsMode = CodeMirror.getMode(config, \"javascript\");\n    var cssMode = CodeMirror.getMode(config, \"css\");\n    var phpMode = CodeMirror.getMode(config, phpConfig);\n\n    function dispatch(stream, state) { // TODO open PHP inside text/css\n      var isPHP = state.mode == \"php\";\n      if (stream.sol() && state.pending != '\"') state.pending = null;\n      if (state.curMode == htmlMode) {\n        if (stream.match(/^<\\?\\w*/)) {\n          state.curMode = phpMode;\n          state.curState = state.php;\n          state.curClose = \"?>\";\n\t  state.mode = \"php\";\n          return \"meta\";\n        }\n        if (state.pending == '\"') {\n          while (!stream.eol() && stream.next() != '\"') {}\n          var style = \"string\";\n        } else if (state.pending && stream.pos < state.pending.end) {\n          stream.pos = state.pending.end;\n          var style = state.pending.style;\n        } else {\n          var style = htmlMode.token(stream, state.curState);\n        }\n        state.pending = null;\n        var cur = stream.current(), openPHP = cur.search(/<\\?/);\n        if (openPHP != -1) {\n          if (style == \"string\" && /\\\"$/.test(cur) && !/\\?>/.test(cur)) state.pending = '\"';\n          else state.pending = {end: stream.pos, style: style};\n          stream.backUp(cur.length - openPHP);\n        } else if (style == \"tag\" && stream.current() == \">\" && state.curState.context) {\n          if (/^script$/i.test(state.curState.context.tagName)) {\n            state.curMode = jsMode;\n            state.curState = jsMode.startState(htmlMode.indent(state.curState, \"\"));\n            state.curClose = /^<\\/\\s*script\\s*>/i;\n\t    state.mode = \"javascript\";\n          }\n          else if (/^style$/i.test(state.curState.context.tagName)) {\n            state.curMode = cssMode;\n            state.curState = cssMode.startState(htmlMode.indent(state.curState, \"\"));\n            state.curClose = /^<\\/\\s*style\\s*>/i;\n            state.mode = \"css\";\n          }\n        }\n        return style;\n      } else if ((!isPHP || state.php.tokenize == null) &&\n                 stream.match(state.curClose, isPHP)) {\n        state.curMode = htmlMode;\n        state.curState = state.html;\n        state.curClose = null;\n\tstate.mode = \"html\";\n        if (isPHP) return \"meta\";\n        else return dispatch(stream, state);\n      } else {\n        return state.curMode.token(stream, state.curState);\n      }\n    }\n\n    return {\n      startState: function() {\n        var html = htmlMode.startState();\n        return {html: html,\n                php: phpMode.startState(),\n                curMode: parserConfig.startOpen ? phpMode : htmlMode,\n                curState: parserConfig.startOpen ? phpMode.startState() : html,\n                curClose: parserConfig.startOpen ? /^\\?>/ : null,\n\t\tmode: parserConfig.startOpen ? \"php\" : \"html\",\n                pending: null}\n      },\n\n      copyState: function(state) {\n        var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),\n            php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;\n        if (state.curState == html) cur = htmlNew;\n        else if (state.curState == php) cur = phpNew;\n        else cur = CodeMirror.copyState(state.curMode, state.curState);\n        return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,\n                curClose: state.curClose, mode: state.mode,\n                pending: state.pending};\n      },\n\n      token: dispatch,\n\n      indent: function(state, textAfter) {\n        if ((state.curMode != phpMode && /^\\s*<\\//.test(textAfter)) ||\n            (state.curMode == phpMode && /^\\?>/.test(textAfter)))\n          return htmlMode.indent(state.html, textAfter);\n        return state.curMode.indent(state.curState, textAfter);\n      },\n\n      electricChars: \"/{}:\"\n    }\n  }, \"xml\", \"clike\", \"javascript\", \"css\");\n  CodeMirror.defineMIME(\"application/x-httpd-php\", \"php\");\n  CodeMirror.defineMIME(\"application/x-httpd-php-open\", {name: \"php\", startOpen: true});\n  CodeMirror.defineMIME(\"text/x-php\", phpConfig);\n})();\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/pig/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Pig Latin mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"pig.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style>.CodeMirror {border: 2px inset #dee;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: Pig Latin mode</h1>\n\n<form><textarea id=\"code\" name=\"code\">\n-- Apache Pig (Pig Latin Language) Demo\n/* \nThis is a multiline comment.\n*/\na = LOAD \"\\path\\to\\input\" USING PigStorage('\\t') AS (x:long, y:chararray, z:bytearray);\nb = GROUP a BY (x,y,3+4);\nc = FOREACH b GENERATE flatten(group) as (x,y), SUM(group.$2) as z;\nSTORE c INTO \"\\path\\to\\output\";\n\n--\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        indentUnit: 4,\n        mode: \"text/x-pig\"\n      });\n    </script>\n\n    <p>\n        Simple mode that handles Pig Latin language.\n    </p>\n\n    <p><strong>MIME type defined:</strong> <code>text/x-pig</code>\n    (PIG code)\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/pig/pig.js",
    "content": "/*\n *\tPig Latin Mode for CodeMirror 2 \n *\t@author Prasanth Jayachandran\n *\t@link \thttps://github.com/prasanthj/pig-codemirror-2\n *  This implementation is adapted from PL/SQL mode in CodeMirror 2.\n*/\nCodeMirror.defineMode(\"pig\", function(config, parserConfig) {\n\tvar indentUnit = config.indentUnit,\n\t\tkeywords = parserConfig.keywords,\n\t\tbuiltins = parserConfig.builtins,\n\t\ttypes = parserConfig.types,\n\t\tmultiLineStrings = parserConfig.multiLineStrings;\n\t\n\tvar isOperatorChar = /[*+\\-%<>=&?:\\/!|]/;\n\t\n\tfunction chain(stream, state, f) {\n\t\tstate.tokenize = f;\n\t\treturn f(stream, state);\n\t}\n\t\n\tvar type;\n\tfunction ret(tp, style) {\n\t\ttype = tp;\n\t\treturn style;\n\t}\n\t\n\tfunction tokenComment(stream, state) {\n\t\tvar isEnd = false;\n\t\tvar ch;\n\t\twhile(ch = stream.next()) {\n\t\t\tif(ch == \"/\" && isEnd) {\n\t\t\t\tstate.tokenize = tokenBase;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tisEnd = (ch == \"*\");\n\t\t}\n\t\treturn ret(\"comment\", \"comment\");\n\t}\n\t\n\tfunction tokenString(quote) {\n\t\treturn function(stream, state) {\n\t\t\tvar escaped = false, next, end = false;\n\t\t\twhile((next = stream.next()) != null) {\n\t\t\t\tif (next == quote && !escaped) {\n\t\t\t\t\tend = true; break;\n\t\t\t\t}\n\t\t\t\tescaped = !escaped && next == \"\\\\\";\n\t\t\t}\n\t\t\tif (end || !(escaped || multiLineStrings))\n\t\t\t\tstate.tokenize = tokenBase;\n\t\t\treturn ret(\"string\", \"error\");\n\t\t};\n\t}\n\t\n\tfunction tokenBase(stream, state) {\n\t\tvar ch = stream.next();\n\t\t\n\t\t// is a start of string?\n\t\tif (ch == '\"' || ch == \"'\")\n\t\t\treturn chain(stream, state, tokenString(ch));\n\t\t// is it one of the special chars\n\t\telse if(/[\\[\\]{}\\(\\),;\\.]/.test(ch))\n\t\t\treturn ret(ch);\n\t\t// is it a number?\n\t\telse if(/\\d/.test(ch)) {\n\t\t\tstream.eatWhile(/[\\w\\.]/);\n\t\t\treturn ret(\"number\", \"number\");\n\t\t}\n\t\t// multi line comment or operator\n\t\telse if (ch == \"/\") {\n\t\t\tif (stream.eat(\"*\")) {\n\t\t\t\treturn chain(stream, state, tokenComment);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tstream.eatWhile(isOperatorChar);\n\t\t\t\treturn ret(\"operator\", \"operator\");\n\t\t\t}\n\t\t}\n\t\t// single line comment or operator\n\t\telse if (ch==\"-\") {\n\t\t\tif(stream.eat(\"-\")){\n\t\t\t\tstream.skipToEnd();\n\t\t\t\treturn ret(\"comment\", \"comment\");\n\t\t\t}\n\t\t\telse {\n\t\t\t\tstream.eatWhile(isOperatorChar);\n\t\t\t\treturn ret(\"operator\", \"operator\");\n\t\t\t}\n\t\t}\n\t\t// is it an operator\n\t\telse if (isOperatorChar.test(ch)) {\n\t\t\tstream.eatWhile(isOperatorChar);\n\t\t\treturn ret(\"operator\", \"operator\");\n\t\t}\n\t\telse {\n\t\t\t// get the while word\n\t\t\tstream.eatWhile(/[\\w\\$_]/);\n\t\t\t// is it one of the listed keywords?\n\t\t\tif (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {\n\t\t\t\tif (stream.eat(\")\") || stream.eat(\".\")) {\n\t\t\t\t\t//keywords can be used as variables like flatten(group), group.$0 etc..\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\treturn (\"keyword\", \"keyword\");\n\t\t\t\t}\n\t\t\t}\n\t\t\t// is it one of the builtin functions?\n\t\t\tif (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase()))\n\t\t\t{\n\t\t\t\treturn (\"keyword\", \"variable-2\")\n\t\t\t}\n\t\t\t// is it one of the listed types?\n\t\t\tif (types && types.propertyIsEnumerable(stream.current().toUpperCase()))\n\t\t\t\treturn (\"keyword\", \"variable-3\")\n\t\t\t// default is a 'word'\n\t\t\treturn ret(\"word\", \"pig-word\");\n\t\t}\n\t}\n\t\n\t// Interface\n\treturn {\n\t\tstartState: function(basecolumn) {\n\t\t\treturn {\n\t\t\t\ttokenize: tokenBase,\n\t\t\t\tstartOfLine: true\n\t\t\t};\n\t\t},\n\t\t\n\t\ttoken: function(stream, state) {\n\t\t\tif(stream.eatSpace()) return null;\n\t\t\tvar style = state.tokenize(stream, state);\n\t\t\treturn style;\n\t\t}\n\t};\n});\n\n(function() {\n\tfunction keywords(str) {\n\t\tvar obj = {}, words = str.split(\" \");\n\t\tfor (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n \t\treturn obj;\n \t}\n\n\t// builtin funcs taken from trunk revision 1303237\n\tvar pBuiltins = \"ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL \" \n\t+ \"CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS \"\n\t+ \"DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG \"\n\t+ \"FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN \"\n\t+ \"INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER \"\n\t+ \"ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS \"\n\t+ \"LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA  \"\n\t+ \"PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE \"\n\t+ \"SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG \"\n\t+ \"TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER \"; \n\t\n\t// taken from QueryLexer.g\n\tvar pKeywords = \"VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP \"\n\t+ \"JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL \"\n\t+ \"PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE \"\n\t+ \"SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE \" \n\t+ \"NEQ MATCHES TRUE FALSE \"; \n\t\n\t// data types\n\tvar pTypes = \"BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP \"\n\t\n\tCodeMirror.defineMIME(\"text/x-pig\", {\n\t name: \"pig\",\n\t builtins: keywords(pBuiltins),\n\t keywords: keywords(pKeywords),\n\t types: keywords(pTypes)\n\t });\n}());\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/plsql/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Oracle PL/SQL mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"plsql.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style>.CodeMirror {border: 2px inset #dee;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: Oracle PL/SQL mode</h1>\n\n<form><textarea id=\"code\" name=\"code\">\n-- Oracle PL/SQL Code Demo\n/*\n   based on c-like mode, adapted to PL/SQL by Peter Raganitsch ( http://www.oracle-and-apex.com/ )\n   April 2011\n*/\nDECLARE\n    vIdx    NUMBER;\n    vString VARCHAR2(100);\n    cText   CONSTANT VARCHAR2(100) := 'That''s it! Have fun with CodeMirror 2';\nBEGIN\n    vIdx := 0;\n    --\n    FOR rDATA IN\n      ( SELECT *\n          FROM EMP\n         ORDER BY EMPNO\n      )\n    LOOP\n        vIdx    := vIdx + 1;\n        vString := rDATA.EMPNO || ' - ' || rDATA.ENAME;\n        --\n        UPDATE EMP\n           SET SAL   = SAL * 101/100\n         WHERE EMPNO = rDATA.EMPNO\n        ;\n    END LOOP;\n    --\n    SYS.DBMS_OUTPUT.Put_Line (cText);\nEND;\n--\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        indentUnit: 4,\n        mode: \"text/x-plsql\"\n      });\n    </script>\n\n    <p>\n        Simple mode that handles Oracle PL/SQL language (and Oracle SQL, of course).\n    </p>\n\n    <p><strong>MIME type defined:</strong> <code>text/x-plsql</code>\n    (PLSQL code)\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/plsql/plsql.js",
    "content": "CodeMirror.defineMode(\"plsql\", function(config, parserConfig) {\n  var indentUnit       = config.indentUnit,\n      keywords         = parserConfig.keywords,\n      functions        = parserConfig.functions,\n      types            = parserConfig.types,\n      sqlplus          = parserConfig.sqlplus,\n      multiLineStrings = parserConfig.multiLineStrings;\n  var isOperatorChar   = /[+\\-*&%=<>!?:\\/|]/;\n  function chain(stream, state, f) {\n    state.tokenize = f;\n    return f(stream, state);\n  }\n\n  var type;\n  function ret(tp, style) {\n    type = tp;\n    return style;\n  }\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    // start of string?\n    if (ch == '\"' || ch == \"'\")\n      return chain(stream, state, tokenString(ch));\n    // is it one of the special signs []{}().,;? Seperator?\n    else if (/[\\[\\]{}\\(\\),;\\.]/.test(ch))\n      return ret(ch);\n    // start of a number value?\n    else if (/\\d/.test(ch)) {\n      stream.eatWhile(/[\\w\\.]/);\n      return ret(\"number\", \"number\");\n    }\n    // multi line comment or simple operator?\n    else if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        return chain(stream, state, tokenComment);\n      }\n      else {\n        stream.eatWhile(isOperatorChar);\n        return ret(\"operator\", \"operator\");\n      }\n    }\n    // single line comment or simple operator?\n    else if (ch == \"-\") {\n      if (stream.eat(\"-\")) {\n        stream.skipToEnd();\n        return ret(\"comment\", \"comment\");\n      }\n      else {\n        stream.eatWhile(isOperatorChar);\n        return ret(\"operator\", \"operator\");\n      }\n    }\n    // pl/sql variable?\n    else if (ch == \"@\" || ch == \"$\") {\n      stream.eatWhile(/[\\w\\d\\$_]/);\n      return ret(\"word\", \"variable\");\n    }\n    // is it a operator?\n    else if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return ret(\"operator\", \"operator\");\n    }\n    else {\n      // get the whole word\n      stream.eatWhile(/[\\w\\$_]/);\n      // is it one of the listed keywords?\n      if (keywords && keywords.propertyIsEnumerable(stream.current().toLowerCase())) return ret(\"keyword\", \"keyword\");\n      // is it one of the listed functions?\n      if (functions && functions.propertyIsEnumerable(stream.current().toLowerCase())) return ret(\"keyword\", \"builtin\");\n      // is it one of the listed types?\n      if (types && types.propertyIsEnumerable(stream.current().toLowerCase())) return ret(\"keyword\", \"variable-2\");\n      // is it one of the listed sqlplus keywords?\n      if (sqlplus && sqlplus.propertyIsEnumerable(stream.current().toLowerCase())) return ret(\"keyword\", \"variable-3\");\n      // default: just a \"word\"\n      return ret(\"word\", \"plsql-word\");\n    }\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next, end = false;\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) {end = true; break;}\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end || !(escaped || multiLineStrings))\n        state.tokenize = tokenBase;\n      return ret(\"string\", \"plsql-string\");\n    };\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return ret(\"comment\", \"plsql-comment\");\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: tokenBase,\n        startOfLine: true\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      return style;\n    }\n  };\n});\n\n(function() {\n  function keywords(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n  var cKeywords = \"abort accept access add all alter and any array arraylen as asc assert assign at attributes audit \" +\n        \"authorization avg \" +\n        \"base_table begin between binary_integer body boolean by \" +\n        \"case cast char char_base check close cluster clusters colauth column comment commit compress connect \" +\n        \"connected constant constraint crash create current currval cursor \" +\n        \"data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete \" +\n        \"desc digits dispose distinct do drop \" +\n        \"else elsif enable end entry escape exception exception_init exchange exclusive exists exit external \" +\n        \"fast fetch file for force form from function \" +\n        \"generic goto grant group \" +\n        \"having \" +\n        \"identified if immediate in increment index indexes indicator initial initrans insert interface intersect \" +\n        \"into is \" +\n        \"key \" +\n        \"level library like limited local lock log logging long loop \" +\n        \"master maxextents maxtrans member minextents minus mislabel mode modify multiset \" +\n        \"new next no noaudit nocompress nologging noparallel not nowait number_base \" +\n        \"object of off offline on online only open option or order out \" +\n        \"package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior \" +\n        \"private privileges procedure public \" +\n        \"raise range raw read rebuild record ref references refresh release rename replace resource restrict return \" +\n        \"returning reverse revoke rollback row rowid rowlabel rownum rows run \" +\n        \"savepoint schema segment select separate session set share snapshot some space split sql start statement \" +\n        \"storage subtype successful synonym \" +\n        \"tabauth table tables tablespace task terminate then to trigger truncate type \" +\n        \"union unique unlimited unrecoverable unusable update use using \" +\n        \"validate value values variable view views \" +\n        \"when whenever where while with work\";\n\n  var cFunctions = \"abs acos add_months ascii asin atan atan2 average \" +\n        \"bfilename \" +\n        \"ceil chartorowid chr concat convert cos cosh count \" +\n        \"decode deref dual dump dup_val_on_index \" +\n        \"empty error exp \" +\n        \"false floor found \" +\n        \"glb greatest \" +\n        \"hextoraw \" +\n        \"initcap instr instrb isopen \" +\n        \"last_day least lenght lenghtb ln lower lpad ltrim lub \" +\n        \"make_ref max min mod months_between \" +\n        \"new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower \" +\n        \"nls_sort nls_upper nlssort no_data_found notfound null nvl \" +\n        \"others \" +\n        \"power \" +\n        \"rawtohex reftohex round rowcount rowidtochar rpad rtrim \" +\n        \"sign sin sinh soundex sqlcode sqlerrm sqrt stddev substr substrb sum sysdate \" +\n        \"tan tanh to_char to_date to_label to_multi_byte to_number to_single_byte translate true trunc \" +\n        \"uid upper user userenv \" +\n        \"variance vsize\";\n\n  var cTypes = \"bfile blob \" +\n        \"character clob \" +\n        \"dec \" +\n        \"float \" +\n        \"int integer \" +\n        \"mlslabel \" +\n        \"natural naturaln nchar nclob number numeric nvarchar2 \" +\n        \"real rowtype \" +\n        \"signtype smallint string \" +\n        \"varchar varchar2\";\n\n  var cSqlplus = \"appinfo arraysize autocommit autoprint autorecovery autotrace \" +\n        \"blockterminator break btitle \" +\n        \"cmdsep colsep compatibility compute concat copycommit copytypecheck \" +\n        \"define describe \" +\n        \"echo editfile embedded escape exec execute \" +\n        \"feedback flagger flush \" +\n        \"heading headsep \" +\n        \"instance \" +\n        \"linesize lno loboffset logsource long longchunksize \" +\n        \"markup \" +\n        \"native newpage numformat numwidth \" +\n        \"pagesize pause pno \" +\n        \"recsep recsepchar release repfooter repheader \" +\n        \"serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber \" +\n        \"sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix \" +\n        \"tab term termout time timing trimout trimspool ttitle \" +\n        \"underline \" +\n        \"verify version \" +\n        \"wrap\";\n\n  CodeMirror.defineMIME(\"text/x-plsql\", {\n    name: \"plsql\",\n    keywords: keywords(cKeywords),\n    functions: keywords(cFunctions),\n    types: keywords(cTypes),\n    sqlplus: keywords(cSqlplus)\n  });\n}());\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/properties/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Properties files mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"properties.js\"></script>\n    <style>.CodeMirror {border-top: 1px solid #ddd; border-bottom: 1px solid #ddd;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Properties files mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n# This is a properties file\na.key = A value\nanother.key = http://example.com\n! Exclamation mark as comment\nbut.not=Within ! A value # indeed\n   # Spaces at the beginning of a line\n   spaces.before.key=value\nbackslash=Used for multi\\\n          line entries,\\\n          that's convenient.\n# Unicode sequences\nunicode.key=This is \\u0020 Unicode\nno.multiline=here\n# Colons\ncolons : can be used too\n# Spaces\nspaces\\ in\\ keys=Not very common...\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-properties</code>,\n    <code>text/x-ini</code>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/properties/properties.js",
    "content": "CodeMirror.defineMode(\"properties\", function() {\n  return {\n    token: function(stream, state) {\n      var sol = stream.sol() || state.afterSection;\n      var eol = stream.eol();\n\n      state.afterSection = false;\n\n      if (sol) {\n        if (state.nextMultiline) {\n          state.inMultiline = true;\n          state.nextMultiline = false;\n        } else {\n          state.position = \"def\";\n        }\n      }\n\n      if (eol && ! state.nextMultiline) {\n        state.inMultiline = false;\n        state.position = \"def\";\n      }\n\n      if (sol) {\n        while(stream.eatSpace());\n      }\n\n      var ch = stream.next();\n\n      if (sol && (ch === \"#\" || ch === \"!\" || ch === \";\")) {\n        state.position = \"comment\";\n        stream.skipToEnd();\n        return \"comment\";\n      } else if (sol && ch === \"[\") {\n        state.afterSection = true;\n        stream.skipTo(\"]\"); stream.eat(\"]\");\n        return \"header\";\n      } else if (ch === \"=\" || ch === \":\") {\n        state.position = \"quote\";\n        return null;\n      } else if (ch === \"\\\\\" && state.position === \"quote\") {\n        if (stream.next() !== \"u\") {    // u = Unicode sequence \\u1234\n          // Multiline value\n          state.nextMultiline = true;\n        }\n      }\n\n      return state.position;\n    },\n\n    startState: function() {\n      return {\n        position : \"def\",       // Current position, \"def\", \"quote\" or \"comment\"\n        nextMultiline : false,  // Is the next line multiline value\n        inMultiline : false,    // Is the current line a multiline value\n        afterSection : false    // Did we just open a section\n      };\n    }\n\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-properties\", \"properties\");\nCodeMirror.defineMIME(\"text/x-ini\", \"properties\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/python/LICENSE.txt",
    "content": "The MIT License\n\nCopyright (c) 2010 Timothy Farrell\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/python/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Python mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"python.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: Python mode</h1>\n    \n    <div><textarea id=\"code\" name=\"code\">\n# Literals\n1234\n0.0e101\n.123\n0b01010011100\n0o01234567\n0x0987654321abcdef\n7\n2147483647\n3L\n79228162514264337593543950336L\n0x100000000L\n79228162514264337593543950336\n0xdeadbeef\n3.14j\n10.j\n10j\n.001j\n1e100j\n3.14e-10j\n\n\n# String Literals\n'For\\''\n\"God\\\"\"\n\"\"\"so loved\nthe world\"\"\"\n'''that he gave\nhis only begotten\\' '''\n'that whosoever believeth \\\nin him'\n''\n\n# Identifiers\n__a__\na.b\na.b.c\n\n# Operators\n+ - * / % & | ^ ~ < >\n== != <= >= <> << >> // **\nand or not in is\n\n# Delimiters\n() [] {} , : ` = ; @ .  # Note that @ and . require the proper context.\n+= -= *= /= %= &= |= ^=\n//= >>= <<= **=\n\n# Keywords\nas assert break class continue def del elif else except\nfinally for from global if import lambda pass raise\nreturn try while with yield\n\n# Python 2 Keywords (otherwise Identifiers)\nexec print\n\n# Python 3 Keywords (otherwise Identifiers)\nnonlocal\n\n# Types\nbool classmethod complex dict enumerate float frozenset int list object\nproperty reversed set slice staticmethod str super tuple type\n\n# Python 2 Types (otherwise Identifiers)\nbasestring buffer file long unicode xrange\n\n# Python 3 Types (otherwise Identifiers)\nbytearray bytes filter map memoryview open range zip\n\n# Some Example code\nimport os\nfrom package import ParentClass\n\n@nonsenseDecorator\ndef doesNothing():\n    pass\n\nclass ExampleClass(ParentClass):\n    @staticmethod\n    def example(inputStr):\n        a = list(inputStr)\n        a.reverse()\n        return ''.join(a)\n\n    def __init__(self, mixin = 'Hello'):\n        self.mixin = mixin\n\n</textarea></div>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: {name: \"python\",\n               version: 2,\n               singleLineStringErrors: false},\n        lineNumbers: true,\n        indentUnit: 4,\n        tabMode: \"shift\",\n        matchBrackets: true\n      });\n    </script>\n    <h2>Configuration Options:</h2>\n    <ul>\n      <li>version - 2/3 - The version of Python to recognize.  Default is 2.</li>\n      <li>singleLineStringErrors - true/false - If you have a single-line string that is not terminated at the end of the line, this will show subsequent lines as errors if true, otherwise it will consider the newline as the end of the string. Default is false.</li>\n    </ul>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-python</code>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/python/python.js",
    "content": "CodeMirror.defineMode(\"python\", function(conf, parserConf) {\n    var ERRORCLASS = 'error';\n    \n    function wordRegexp(words) {\n        return new RegExp(\"^((\" + words.join(\")|(\") + \"))\\\\b\");\n    }\n    \n    var singleOperators = new RegExp(\"^[\\\\+\\\\-\\\\*/%&|\\\\^~<>!]\");\n    var singleDelimiters = new RegExp('^[\\\\(\\\\)\\\\[\\\\]\\\\{\\\\}@,:`=;\\\\.]');\n    var doubleOperators = new RegExp(\"^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\\\*\\\\*))\");\n    var doubleDelimiters = new RegExp(\"^((\\\\+=)|(\\\\-=)|(\\\\*=)|(%=)|(/=)|(&=)|(\\\\|=)|(\\\\^=))\");\n    var tripleDelimiters = new RegExp(\"^((//=)|(>>=)|(<<=)|(\\\\*\\\\*=))\");\n    var identifiers = new RegExp(\"^[_A-Za-z][_A-Za-z0-9]*\");\n\n    var wordOperators = wordRegexp(['and', 'or', 'not', 'is', 'in']);\n    var commonkeywords = ['as', 'assert', 'break', 'class', 'continue',\n                          'def', 'del', 'elif', 'else', 'except', 'finally',\n                          'for', 'from', 'global', 'if', 'import',\n                          'lambda', 'pass', 'raise', 'return',\n                          'try', 'while', 'with', 'yield'];\n    var commonBuiltins = ['abs', 'all', 'any', 'bin', 'bool', 'bytearray', 'callable', 'chr',\n                          'classmethod', 'compile', 'complex', 'delattr', 'dict', 'dir', 'divmod',\n                          'enumerate', 'eval', 'filter', 'float', 'format', 'frozenset',\n                          'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id',\n                          'input', 'int', 'isinstance', 'issubclass', 'iter', 'len',\n                          'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next',\n                          'object', 'oct', 'open', 'ord', 'pow', 'property', 'range',\n                          'repr', 'reversed', 'round', 'set', 'setattr', 'slice',\n                          'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple',\n                          'type', 'vars', 'zip', '__import__', 'NotImplemented',\n                          'Ellipsis', '__debug__'];\n    var py2 = {'builtins': ['apply', 'basestring', 'buffer', 'cmp', 'coerce', 'execfile',\n                            'file', 'intern', 'long', 'raw_input', 'reduce', 'reload',\n                            'unichr', 'unicode', 'xrange', 'False', 'True', 'None'],\n               'keywords': ['exec', 'print']};\n    var py3 = {'builtins': ['ascii', 'bytes', 'exec', 'print'],\n               'keywords': ['nonlocal', 'False', 'True', 'None']};\n\n    if (!!parserConf.version && parseInt(parserConf.version, 10) === 3) {\n        commonkeywords = commonkeywords.concat(py3.keywords);\n        commonBuiltins = commonBuiltins.concat(py3.builtins);\n        var stringPrefixes = new RegExp(\"^(([rb]|(br))?('{3}|\\\"{3}|['\\\"]))\", \"i\");\n    } else {\n        commonkeywords = commonkeywords.concat(py2.keywords);\n        commonBuiltins = commonBuiltins.concat(py2.builtins);\n        var stringPrefixes = new RegExp(\"^(([rub]|(ur)|(br))?('{3}|\\\"{3}|['\\\"]))\", \"i\");\n    }\n    var keywords = wordRegexp(commonkeywords);\n    var builtins = wordRegexp(commonBuiltins);\n\n    var indentInfo = null;\n\n    // tokenizers\n    function tokenBase(stream, state) {\n        // Handle scope changes\n        if (stream.sol()) {\n            var scopeOffset = state.scopes[0].offset;\n            if (stream.eatSpace()) {\n                var lineOffset = stream.indentation();\n                if (lineOffset > scopeOffset) {\n                    indentInfo = 'indent';\n                } else if (lineOffset < scopeOffset) {\n                    indentInfo = 'dedent';\n                }\n                return null;\n            } else {\n                if (scopeOffset > 0) {\n                    dedent(stream, state);\n                }\n            }\n        }\n        if (stream.eatSpace()) {\n            return null;\n        }\n        \n        var ch = stream.peek();\n        \n        // Handle Comments\n        if (ch === '#') {\n            stream.skipToEnd();\n            return 'comment';\n        }\n        \n        // Handle Number Literals\n        if (stream.match(/^[0-9\\.]/, false)) {\n            var floatLiteral = false;\n            // Floats\n            if (stream.match(/^\\d*\\.\\d+(e[\\+\\-]?\\d+)?/i)) { floatLiteral = true; }\n            if (stream.match(/^\\d+\\.\\d*/)) { floatLiteral = true; }\n            if (stream.match(/^\\.\\d+/)) { floatLiteral = true; }\n            if (floatLiteral) {\n                // Float literals may be \"imaginary\"\n                stream.eat(/J/i);\n                return 'number';\n            }\n            // Integers\n            var intLiteral = false;\n            // Hex\n            if (stream.match(/^0x[0-9a-f]+/i)) { intLiteral = true; }\n            // Binary\n            if (stream.match(/^0b[01]+/i)) { intLiteral = true; }\n            // Octal\n            if (stream.match(/^0o[0-7]+/i)) { intLiteral = true; }\n            // Decimal\n            if (stream.match(/^[1-9]\\d*(e[\\+\\-]?\\d+)?/)) {\n                // Decimal literals may be \"imaginary\"\n                stream.eat(/J/i);\n                // TODO - Can you have imaginary longs?\n                intLiteral = true;\n            }\n            // Zero by itself with no other piece of number.\n            if (stream.match(/^0(?![\\dx])/i)) { intLiteral = true; }\n            if (intLiteral) {\n                // Integer literals may be \"long\"\n                stream.eat(/L/i);\n                return 'number';\n            }\n        }\n        \n        // Handle Strings\n        if (stream.match(stringPrefixes)) {\n            state.tokenize = tokenStringFactory(stream.current());\n            return state.tokenize(stream, state);\n        }\n        \n        // Handle operators and Delimiters\n        if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {\n            return null;\n        }\n        if (stream.match(doubleOperators)\n            || stream.match(singleOperators)\n            || stream.match(wordOperators)) {\n            return 'operator';\n        }\n        if (stream.match(singleDelimiters)) {\n            return null;\n        }\n        \n        if (stream.match(keywords)) {\n            return 'keyword';\n        }\n        \n        if (stream.match(builtins)) {\n            return 'builtin';\n        }\n        \n        if (stream.match(identifiers)) {\n            return 'variable';\n        }\n        \n        // Handle non-detected items\n        stream.next();\n        return ERRORCLASS;\n    }\n    \n    function tokenStringFactory(delimiter) {\n        while ('rub'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) {\n            delimiter = delimiter.substr(1);\n        }\n        var singleline = delimiter.length == 1;\n        var OUTCLASS = 'string';\n        \n        return function tokenString(stream, state) {\n            while (!stream.eol()) {\n                stream.eatWhile(/[^'\"\\\\]/);\n                if (stream.eat('\\\\')) {\n                    stream.next();\n                    if (singleline && stream.eol()) {\n                        return OUTCLASS;\n                    }\n                } else if (stream.match(delimiter)) {\n                    state.tokenize = tokenBase;\n                    return OUTCLASS;\n                } else {\n                    stream.eat(/['\"]/);\n                }\n            }\n            if (singleline) {\n                if (parserConf.singleLineStringErrors) {\n                    return ERRORCLASS;\n                } else {\n                    state.tokenize = tokenBase;\n                }\n            }\n            return OUTCLASS;\n        };\n    }\n    \n    function indent(stream, state, type) {\n        type = type || 'py';\n        var indentUnit = 0;\n        if (type === 'py') {\n            if (state.scopes[0].type !== 'py') {\n                state.scopes[0].offset = stream.indentation();\n                return;\n            }\n            for (var i = 0; i < state.scopes.length; ++i) {\n                if (state.scopes[i].type === 'py') {\n                    indentUnit = state.scopes[i].offset + conf.indentUnit;\n                    break;\n                }\n            }\n        } else {\n            indentUnit = stream.column() + stream.current().length;\n        }\n        state.scopes.unshift({\n            offset: indentUnit,\n            type: type\n        });\n    }\n    \n    function dedent(stream, state, type) {\n        type = type || 'py';\n        if (state.scopes.length == 1) return;\n        if (state.scopes[0].type === 'py') {\n            var _indent = stream.indentation();\n            var _indent_index = -1;\n            for (var i = 0; i < state.scopes.length; ++i) {\n                if (_indent === state.scopes[i].offset) {\n                    _indent_index = i;\n                    break;\n                }\n            }\n            if (_indent_index === -1) {\n                return true;\n            }\n            while (state.scopes[0].offset !== _indent) {\n                state.scopes.shift();\n            }\n            return false\n        } else {\n            if (type === 'py') {\n                state.scopes[0].offset = stream.indentation();\n                return false;\n            } else {\n                if (state.scopes[0].type != type) {\n                    return true;\n                }\n                state.scopes.shift();\n                return false;\n            }\n        }\n    }\n\n    function tokenLexer(stream, state) {\n        indentInfo = null;\n        var style = state.tokenize(stream, state);\n        var current = stream.current();\n\n        // Handle '.' connected identifiers\n        if (current === '.') {\n            style = stream.match(identifiers, false) ? null : ERRORCLASS;\n            if (style === null && state.lastToken === 'meta') {\n                // Apply 'meta' style to '.' connected identifiers when\n                // appropriate.\n                style = 'meta';\n            }\n            return style;\n        }\n        \n        // Handle decorators\n        if (current === '@') {\n            return stream.match(identifiers, false) ? 'meta' : ERRORCLASS;\n        }\n\n        if ((style === 'variable' || style === 'builtin')\n            && state.lastToken === 'meta') {\n            style = 'meta';\n        }\n        \n        // Handle scope changes.\n        if (current === 'pass' || current === 'return') {\n            state.dedent += 1;\n        }\n        if (current === 'lambda') state.lambda = true;\n        if ((current === ':' && !state.lambda && state.scopes[0].type == 'py')\n            || indentInfo === 'indent') {\n            indent(stream, state);\n        }\n        var delimiter_index = '[({'.indexOf(current);\n        if (delimiter_index !== -1) {\n            indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));\n        }\n        if (indentInfo === 'dedent') {\n            if (dedent(stream, state)) {\n                return ERRORCLASS;\n            }\n        }\n        delimiter_index = '])}'.indexOf(current);\n        if (delimiter_index !== -1) {\n            if (dedent(stream, state, current)) {\n                return ERRORCLASS;\n            }\n        }\n        if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'py') {\n            if (state.scopes.length > 1) state.scopes.shift();\n            state.dedent -= 1;\n        }\n        \n        return style;\n    }\n\n    var external = {\n        startState: function(basecolumn) {\n            return {\n              tokenize: tokenBase,\n              scopes: [{offset:basecolumn || 0, type:'py'}],\n              lastToken: null,\n              lambda: false,\n              dedent: 0\n          };\n        },\n        \n        token: function(stream, state) {\n            var style = tokenLexer(stream, state);\n            \n            state.lastToken = style;\n            \n            if (stream.eol() && stream.lambda) {\n                state.lambda = false;\n            }\n            \n            return style;\n        },\n        \n        indent: function(state, textAfter) {\n            if (state.tokenize != tokenBase) {\n                return 0;\n            }\n            \n            return state.scopes[0].offset;\n        }\n        \n    };\n    return external;\n});\n\nCodeMirror.defineMIME(\"text/x-python\", \"python\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/r/LICENSE",
    "content": "Copyright (c) 2011, Ubalo, Inc.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the Ubalo, Inc nor the names of its\n      contributors may be used to endorse or promote products derived\n      from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL UBALO, INC BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/r/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: R mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"r.js\"></script>\n    <style>\n      .CodeMirror { border-top: 1px solid silver; border-bottom: 1px solid silver; }\n      .cm-s-default span.cm-semi { color: blue; font-weight: bold; }\n      .cm-s-default span.cm-dollar { color: orange; font-weight: bold; }\n      .cm-s-default span.cm-arrow { color: brown; }\n      .cm-s-default span.cm-arg-is { color: brown; }\n    </style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: R mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n# Code from http://www.mayin.org/ajayshah/KB/R/\n\n# FIRST LEARN ABOUT LISTS --\nX = list(height=5.4, weight=54)\nprint(\"Use default printing --\")\nprint(X)\nprint(\"Accessing individual elements --\")\ncat(\"Your height is \", X$height, \" and your weight is \", X$weight, \"\\n\")\n\n# FUNCTIONS --\nsquare <- function(x) {\n  return(x*x)\n}\ncat(\"The square of 3 is \", square(3), \"\\n\")\n\n                 # default value of the arg is set to 5.\ncube <- function(x=5) {\n  return(x*x*x);\n}\ncat(\"Calling cube with 2 : \", cube(2), \"\\n\")    # will give 2^3\ncat(\"Calling cube        : \", cube(), \"\\n\")     # will default to 5^3.\n\n# LEARN ABOUT FUNCTIONS THAT RETURN MULTIPLE OBJECTS --\npowers <- function(x) {\n  parcel = list(x2=x*x, x3=x*x*x, x4=x*x*x*x);\n  return(parcel);\n}\n\nX = powers(3);\nprint(\"Showing powers of 3 --\"); print(X);\n\n# WRITING THIS COMPACTLY (4 lines instead of 7)\n\npowerful <- function(x) {\n  return(list(x2=x*x, x3=x*x*x, x4=x*x*x*x));\n}\nprint(\"Showing powers of 3 --\"); print(powerful(3));\n\n# In R, the last expression in a function is, by default, what is\n# returned. So you could equally just say:\npowerful <- function(x) {list(x2=x*x, x3=x*x*x, x4=x*x*x*x)}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-rsrc</code>.</p>\n\n    <p>Development of the CodeMirror R mode was kindly sponsored\n    by <a href=\"http://ubalo.com/\">Ubalo</a>, who hold\n    the <a href=\"LICENSE\">license</a>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/r/r.js",
    "content": "CodeMirror.defineMode(\"r\", function(config) {\n  function wordObj(str) {\n    var words = str.split(\" \"), res = {};\n    for (var i = 0; i < words.length; ++i) res[words[i]] = true;\n    return res;\n  }\n  var atoms = wordObj(\"NULL NA Inf NaN NA_integer_ NA_real_ NA_complex_ NA_character_\");\n  var builtins = wordObj(\"list quote bquote eval return call parse deparse\");\n  var keywords = wordObj(\"if else repeat while function for in next break\");\n  var blockkeywords = wordObj(\"if else repeat while function for\");\n  var opChars = /[+\\-*\\/^<>=!&|~$:]/;\n  var curPunc;\n\n  function tokenBase(stream, state) {\n    curPunc = null;\n    var ch = stream.next();\n    if (ch == \"#\") {\n      stream.skipToEnd();\n      return \"comment\";\n    } else if (ch == \"0\" && stream.eat(\"x\")) {\n      stream.eatWhile(/[\\da-f]/i);\n      return \"number\";\n    } else if (ch == \".\" && stream.eat(/\\d/)) {\n      stream.match(/\\d*(?:e[+\\-]?\\d+)?/);\n      return \"number\";\n    } else if (/\\d/.test(ch)) {\n      stream.match(/\\d*(?:\\.\\d+)?(?:e[+\\-]\\d+)?L?/);\n      return \"number\";\n    } else if (ch == \"'\" || ch == '\"') {\n      state.tokenize = tokenString(ch);\n      return \"string\";\n    } else if (ch == \".\" && stream.match(/.[.\\d]+/)) {\n      return \"keyword\";\n    } else if (/[\\w\\.]/.test(ch) && ch != \"_\") {\n      stream.eatWhile(/[\\w\\.]/);\n      var word = stream.current();\n      if (atoms.propertyIsEnumerable(word)) return \"atom\";\n      if (keywords.propertyIsEnumerable(word)) {\n        if (blockkeywords.propertyIsEnumerable(word)) curPunc = \"block\";\n        return \"keyword\";\n      }\n      if (builtins.propertyIsEnumerable(word)) return \"builtin\";\n      return \"variable\";\n    } else if (ch == \"%\") {\n      if (stream.skipTo(\"%\")) stream.next();\n      return \"variable-2\";\n    } else if (ch == \"<\" && stream.eat(\"-\")) {\n      return \"arrow\";\n    } else if (ch == \"=\" && state.ctx.argList) {\n      return \"arg-is\";\n    } else if (opChars.test(ch)) {\n      if (ch == \"$\") return \"dollar\";\n      stream.eatWhile(opChars);\n      return \"operator\";\n    } else if (/[\\(\\){}\\[\\];]/.test(ch)) {\n      curPunc = ch;\n      if (ch == \";\") return \"semi\";\n      return null;\n    } else {\n      return null;\n    }\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      if (stream.eat(\"\\\\\")) {\n        var ch = stream.next();\n        if (ch == \"x\") stream.match(/^[a-f0-9]{2}/i);\n        else if ((ch == \"u\" || ch == \"U\") && stream.eat(\"{\") && stream.skipTo(\"}\")) stream.next();\n        else if (ch == \"u\") stream.match(/^[a-f0-9]{4}/i);\n        else if (ch == \"U\") stream.match(/^[a-f0-9]{8}/i);\n        else if (/[0-7]/.test(ch)) stream.match(/^[0-7]{1,2}/);\n        return \"string-2\";\n      } else {\n        var next;\n        while ((next = stream.next()) != null) {\n          if (next == quote) { state.tokenize = tokenBase; break; }\n          if (next == \"\\\\\") { stream.backUp(1); break; }\n        }\n        return \"string\";\n      }\n    };\n  }\n\n  function push(state, type, stream) {\n    state.ctx = {type: type,\n                 indent: state.indent,\n                 align: null,\n                 column: stream.column(),\n                 prev: state.ctx};\n  }\n  function pop(state) {\n    state.indent = state.ctx.indent;\n    state.ctx = state.ctx.prev;\n  }\n\n  return {\n    startState: function(base) {\n      return {tokenize: tokenBase,\n              ctx: {type: \"top\",\n                    indent: -config.indentUnit,\n                    align: false},\n              indent: 0,\n              afterIdent: false};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (state.ctx.align == null) state.ctx.align = false;\n        state.indent = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      if (style != \"comment\" && state.ctx.align == null) state.ctx.align = true;\n\n      var ctype = state.ctx.type;\n      if ((curPunc == \";\" || curPunc == \"{\" || curPunc == \"}\") && ctype == \"block\") pop(state);\n      if (curPunc == \"{\") push(state, \"}\", stream);\n      else if (curPunc == \"(\") {\n        push(state, \")\", stream);\n        if (state.afterIdent) state.ctx.argList = true;\n      }\n      else if (curPunc == \"[\") push(state, \"]\", stream);\n      else if (curPunc == \"block\") push(state, \"block\", stream);\n      else if (curPunc == ctype) pop(state);\n      state.afterIdent = style == \"variable\" || style == \"keyword\";\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), ctx = state.ctx,\n          closing = firstChar == ctx.type;\n      if (ctx.type == \"block\") return ctx.indent + (firstChar == \"{\" ? 0 : config.indentUnit);\n      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indent + (closing ? 0 : config.indentUnit);\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-rsrc\", \"r\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/rpm/changes/changes.js",
    "content": "CodeMirror.defineMode(\"changes\", function(config, modeConfig) {\n  var headerSeperator = /^-+$/;\n  var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)  ?\\d{1,2} \\d{2}:\\d{2}(:\\d{2})? [A-Z]{3,4} \\d{4} - /;\n  var simpleEmail = /^[\\w+.-]+@[\\w.-]+/;\n\n  return {\n    token: function(stream) {\n      if (stream.sol()) {\n        if (stream.match(headerSeperator)) { return 'tag'; }\n        if (stream.match(headerLine)) { return 'tag'; }\n      }\n      if (stream.match(simpleEmail)) { return 'string'; }\n      stream.next();\n      return null;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-rpm-changes\", \"changes\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/rpm/changes/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: RPM changes mode</title>\n    <link rel=\"stylesheet\" href=\"../../../lib/codemirror.css\">\n    <script src=\"../../../lib/codemirror.js\"></script>\n    <script src=\"changes.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../../doc/docs.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: RPM changes mode</h1>\n    \n    <div><textarea id=\"code\" name=\"code\">\n-------------------------------------------------------------------\nTue Oct 18 13:58:40 UTC 2011 - misterx@example.com\n\n- Update to r60.3\n- Fixes bug in the reflect package\n  * disallow Interface method on Value obtained via unexported name\n\n-------------------------------------------------------------------\nThu Oct  6 08:14:24 UTC 2011 - misterx@example.com\n\n- Update to r60.2\n- Fixes memory leak in certain map types\n\n-------------------------------------------------------------------\nWed Oct  5 14:34:10 UTC 2011 - misterx@example.com\n\n- Tweaks for gdb debugging\n- go.spec changes:\n  - move %go_arch definition to %prep section\n  - pass correct location of go specific gdb pretty printer and\n    functions to cpp as HOST_EXTRA_CFLAGS macro\n  - install go gdb functions & printer\n- gdb-printer.patch\n  - patch linker (src/cmd/ld/dwarf.c) to emit correct location of go\n    gdb functions and pretty printer\n</textarea></div>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: {name: \"changes\"},\n        lineNumbers: true,\n        indentUnit: 4,\n        tabMode: \"shift\",\n        matchBrackets: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-rpm-changes</code>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/rpm/spec/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: RPM spec mode</title>\n    <link rel=\"stylesheet\" href=\"../../../lib/codemirror.css\">\n    <script src=\"../../../lib/codemirror.js\"></script>\n    <script src=\"spec.js\"></script>\n    <link rel=\"stylesheet\" href=\"spec.css\">\n    <link rel=\"stylesheet\" href=\"../../../doc/docs.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: RPM spec mode</h1>\n    \n    <div><textarea id=\"code\" name=\"code\">\n#\n# spec file for package minidlna\n#\n# Copyright (c) 2011, Sascha Peilicke <saschpe@gmx.de>\n#\n# All modifications and additions to the file contributed by third parties\n# remain the property of their copyright owners, unless otherwise agreed\n# upon. The license for this file, and modifications and additions to the\n# file, is the same license as for the pristine package itself (unless the\n# license for the pristine package is not an Open Source License, in which\n# case the license is the MIT License). An \"Open Source License\" is a\n# license that conforms to the Open Source Definition (Version 1.9)\n# published by the Open Source Initiative.\n\n\nName:           libupnp6\nVersion:        1.6.13\nRelease:        0\nSummary:        Portable Universal Plug and Play (UPnP) SDK\nGroup:          System/Libraries\nLicense:        BSD-3-Clause\nUrl:            http://sourceforge.net/projects/pupnp/\nSource0:        http://downloads.sourceforge.net/pupnp/libupnp-%{version}.tar.bz2\nBuildRoot:      %{_tmppath}/%{name}-%{version}-build\n\n%description\nThe portable Universal Plug and Play (UPnP) SDK provides support for building\nUPnP-compliant control points, devices, and bridges on several operating\nsystems.\n\n%package -n libupnp-devel\nSummary:        Portable Universal Plug and Play (UPnP) SDK\nGroup:          Development/Libraries/C and C++\nProvides:       pkgconfig(libupnp)\nRequires:       %{name} = %{version}\n\n%description -n libupnp-devel\nThe portable Universal Plug and Play (UPnP) SDK provides support for building\nUPnP-compliant control points, devices, and bridges on several operating\nsystems.\n\n%prep\n%setup -n libupnp-%{version}\n\n%build\n%configure --disable-static\nmake %{?_smp_mflags}\n\n%install\n%makeinstall\nfind %{buildroot} -type f -name '*.la' -exec rm -f {} ';'\n\n%post -p /sbin/ldconfig\n\n%postun -p /sbin/ldconfig\n\n%files\n%defattr(-,root,root,-)\n%doc ChangeLog NEWS README TODO\n%{_libdir}/libixml.so.*\n%{_libdir}/libthreadutil.so.*\n%{_libdir}/libupnp.so.*\n\n%files -n libupnp-devel\n%defattr(-,root,root,-)\n%{_libdir}/pkgconfig/libupnp.pc\n%{_libdir}/libixml.so\n%{_libdir}/libthreadutil.so\n%{_libdir}/libupnp.so\n%{_includedir}/upnp/\n\n%changelog</textarea></div>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: {name: \"spec\"},\n        lineNumbers: true,\n        indentUnit: 4,\n        matchBrackets: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-rpm-spec</code>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/rpm/spec/spec.css",
    "content": ".cm-s-default span.cm-preamble {color: #b26818; font-weight: bold;}\n.cm-s-default span.cm-macro {color: #b218b2;}\n.cm-s-default span.cm-section {color: green; font-weight: bold;}\n.cm-s-default span.cm-script {color: red;}\n.cm-s-default span.cm-issue {color: yellow;}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/rpm/spec/spec.js",
    "content": "// Quick and dirty spec file highlighting\n\nCodeMirror.defineMode(\"spec\", function(config, modeConfig) {\n  var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;\n\n  var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\\(\\w+\\))?|Obsoletes|Conflicts|Recommends|Source\\d*|Patch\\d*|ExclusiveArch|NoSource|Supplements):/;\n  var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preun|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/;\n  var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros\n  var control_flow_simple = /^%(else|endif)/; // rpm control flow macros\n  var operators = /^(\\!|\\?|\\<\\=|\\<|\\>\\=|\\>|\\=\\=|\\&\\&|\\|\\|)/; // operators in control flow macros\n\n  return {\n    startState: function () {\n        return {\n          controlFlow: false,\n          macroParameters: false,\n          section: false\n        };\n    },\n    token: function (stream, state) {\n      var ch = stream.peek();\n      if (ch == \"#\") { stream.skipToEnd(); return \"comment\"; }\n\n      if (stream.sol()) {\n        if (stream.match(preamble)) { return \"preamble\"; }\n        if (stream.match(section)) { return \"section\"; }\n      }\n\n      if (stream.match(/^\\$\\w+/)) { return \"def\"; } // Variables like '$RPM_BUILD_ROOT'\n      if (stream.match(/^\\$\\{\\w+\\}/)) { return \"def\"; } // Variables like '${RPM_BUILD_ROOT}'\n\n      if (stream.match(control_flow_simple)) { return \"keyword\"; }\n      if (stream.match(control_flow_complex)) {\n        state.controlFlow = true;\n        return \"keyword\";\n      }\n      if (state.controlFlow) {\n        if (stream.match(operators)) { return \"operator\"; }\n        if (stream.match(/^(\\d+)/)) { return \"number\"; }\n        if (stream.eol()) { state.controlFlow = false; }\n      }\n\n      if (stream.match(arch)) { return \"number\"; }\n\n      // Macros like '%make_install' or '%attr(0775,root,root)'\n      if (stream.match(/^%[\\w]+/)) {\n        if (stream.match(/^\\(/)) { state.macroParameters = true; }\n        return \"macro\";\n      }\n      if (state.macroParameters) {\n        if (stream.match(/^\\d+/)) { return \"number\";}\n        if (stream.match(/^\\)/)) {\n          state.macroParameters = false;\n          return \"macro\";\n        }\n      }\n      if (stream.match(/^%\\{\\??[\\w \\-]+\\}/)) { return \"macro\"; } // Macros like '%{defined fedora}'\n\n      //TODO: Include bash script sub-parser (CodeMirror supports that)\n      stream.next();\n      return null;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-rpm-spec\", \"spec\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/rst/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: reStructuredText mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"rst.js\"></script>\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: reStructuredText mode</h1>\n\n<form><textarea id=\"code\" name=\"code\">\n.. This is an excerpt from Sphinx documentation: http://sphinx.pocoo.org/_sources/rest.txt\n\n.. highlightlang:: rest\n\n.. _rst-primer:\n\nreStructuredText Primer\n=======================\n\nThis section is a brief introduction to reStructuredText (reST) concepts and\nsyntax, intended to provide authors with enough information to author documents\nproductively.  Since reST was designed to be a simple, unobtrusive markup\nlanguage, this will not take too long.\n\n.. seealso::\n\n   The authoritative `reStructuredText User Documentation\n   &lt;http://docutils.sourceforge.net/rst.html&gt;`_.  The \"ref\" links in this\n   document link to the description of the individual constructs in the reST\n   reference.\n\n\nParagraphs\n----------\n\nThe paragraph (:duref:`ref &lt;paragraphs&gt;`) is the most basic block in a reST\ndocument.  Paragraphs are simply chunks of text separated by one or more blank\nlines.  As in Python, indentation is significant in reST, so all lines of the\nsame paragraph must be left-aligned to the same level of indentation.\n\n\n.. _inlinemarkup:\n\nInline markup\n-------------\n\nThe standard reST inline markup is quite simple: use\n\n* one asterisk: ``*text*`` for emphasis (italics),\n* two asterisks: ``**text**`` for strong emphasis (boldface), and\n* backquotes: ````text```` for code samples.\n\nIf asterisks or backquotes appear in running text and could be confused with\ninline markup delimiters, they have to be escaped with a backslash.\n\nBe aware of some restrictions of this markup:\n\n* it may not be nested,\n* content may not start or end with whitespace: ``* text*`` is wrong,\n* it must be separated from surrounding text by non-word characters.  Use a\n  backslash escaped space to work around that: ``thisis\\ *one*\\ word``.\n\nThese restrictions may be lifted in future versions of the docutils.\n\nreST also allows for custom \"interpreted text roles\"', which signify that the\nenclosed text should be interpreted in a specific way.  Sphinx uses this to\nprovide semantic markup and cross-referencing of identifiers, as described in\nthe appropriate section.  The general syntax is ``:rolename:`content```.\n\nStandard reST provides the following roles:\n\n* :durole:`emphasis` -- alternate spelling for ``*emphasis*``\n* :durole:`strong` -- alternate spelling for ``**strong**``\n* :durole:`literal` -- alternate spelling for ````literal````\n* :durole:`subscript` -- subscript text\n* :durole:`superscript` -- superscript text\n* :durole:`title-reference` -- for titles of books, periodicals, and other\n  materials\n\nSee :ref:`inline-markup` for roles added by Sphinx.\n\n\nLists and Quote-like blocks\n---------------------------\n\nList markup (:duref:`ref &lt;bullet-lists&gt;`) is natural: just place an asterisk at\nthe start of a paragraph and indent properly.  The same goes for numbered lists;\nthey can also be autonumbered using a ``#`` sign::\n\n   * This is a bulleted list.\n   * It has two items, the second\n     item uses two lines.\n\n   1. This is a numbered list.\n   2. It has two items too.\n\n   #. This is a numbered list.\n   #. It has two items too.\n\n\nNested lists are possible, but be aware that they must be separated from the\nparent list items by blank lines::\n\n   * this is\n   * a list\n\n     * with a nested list\n     * and some subitems\n\n   * and here the parent list continues\n\nDefinition lists (:duref:`ref &lt;definition-lists&gt;`) are created as follows::\n\n   term (up to a line of text)\n      Definition of the term, which must be indented\n\n      and can even consist of multiple paragraphs\n\n   next term\n      Description.\n\nNote that the term cannot have more than one line of text.\n\nQuoted paragraphs (:duref:`ref &lt;block-quotes&gt;`) are created by just indenting\nthem more than the surrounding paragraphs.\n\nLine blocks (:duref:`ref &lt;line-blocks&gt;`) are a way of preserving line breaks::\n\n   | These lines are\n   | broken exactly like in\n   | the source file.\n\nThere are also several more special blocks available:\n\n* field lists (:duref:`ref &lt;field-lists&gt;`)\n* option lists (:duref:`ref &lt;option-lists&gt;`)\n* quoted literal blocks (:duref:`ref &lt;quoted-literal-blocks&gt;`)\n* doctest blocks (:duref:`ref &lt;doctest-blocks&gt;`)\n\n\nSource Code\n-----------\n\nLiteral code blocks (:duref:`ref &lt;literal-blocks&gt;`) are introduced by ending a\nparagraph with the special marker ``::``.  The literal block must be indented\n(and, like all paragraphs, separated from the surrounding ones by blank lines)::\n\n   This is a normal text paragraph. The next paragraph is a code sample::\n\n      It is not processed in any way, except\n      that the indentation is removed.\n\n      It can span multiple lines.\n\n   This is a normal text paragraph again.\n\nThe handling of the ``::`` marker is smart:\n\n* If it occurs as a paragraph of its own, that paragraph is completely left\n  out of the document.\n* If it is preceded by whitespace, the marker is removed.\n* If it is preceded by non-whitespace, the marker is replaced by a single\n  colon.\n\nThat way, the second sentence in the above example's first paragraph would be\nrendered as \"The next paragraph is a code sample:\".\n\n\n.. _rst-tables:\n\nTables\n------\n\nTwo forms of tables are supported.  For *grid tables* (:duref:`ref\n&lt;grid-tables&gt;`), you have to \"paint\" the cell grid yourself.  They look like\nthis::\n\n   +------------------------+------------+----------+----------+\n   | Header row, column 1   | Header 2   | Header 3 | Header 4 |\n   | (header rows optional) |            |          |          |\n   +========================+============+==========+==========+\n   | body row 1, column 1   | column 2   | column 3 | column 4 |\n   +------------------------+------------+----------+----------+\n   | body row 2             | ...        | ...      |          |\n   +------------------------+------------+----------+----------+\n\n*Simple tables* (:duref:`ref &lt;simple-tables&gt;`) are easier to write, but\nlimited: they must contain more than one row, and the first column cannot\ncontain multiple lines.  They look like this::\n\n   =====  =====  =======\n   A      B      A and B\n   =====  =====  =======\n   False  False  False\n   True   False  False\n   False  True   False\n   True   True   True\n   =====  =====  =======\n\n\nHyperlinks\n----------\n\nExternal links\n^^^^^^^^^^^^^^\n\nUse ```Link text &lt;http://example.com/&gt;`_`` for inline web links.  If the link\ntext should be the web address, you don't need special markup at all, the parser\nfinds links and mail addresses in ordinary text.\n\nYou can also separate the link and the target definition (:duref:`ref\n&lt;hyperlink-targets&gt;`), like this::\n\n   This is a paragraph that contains `a link`_.\n\n   .. _a link: http://example.com/\n\n\nInternal links\n^^^^^^^^^^^^^^\n\nInternal linking is done via a special reST role provided by Sphinx, see the\nsection on specific markup, :ref:`ref-role`.\n\n\nSections\n--------\n\nSection headers (:duref:`ref &lt;sections&gt;`) are created by underlining (and\noptionally overlining) the section title with a punctuation character, at least\nas long as the text::\n\n   =================\n   This is a heading\n   =================\n\nNormally, there are no heading levels assigned to certain characters as the\nstructure is determined from the succession of headings.  However, for the\nPython documentation, this convention is used which you may follow:\n\n* ``#`` with overline, for parts\n* ``*`` with overline, for chapters\n* ``=``, for sections\n* ``-``, for subsections\n* ``^``, for subsubsections\n* ``\"``, for paragraphs\n\nOf course, you are free to use your own marker characters (see the reST\ndocumentation), and use a deeper nesting level, but keep in mind that most\ntarget formats (HTML, LaTeX) have a limited supported nesting depth.\n\n\nExplicit Markup\n---------------\n\n\"Explicit markup\" (:duref:`ref &lt;explicit-markup-blocks&gt;`) is used in reST for\nmost constructs that need special handling, such as footnotes,\nspecially-highlighted paragraphs, comments, and generic directives.\n\nAn explicit markup block begins with a line starting with ``..`` followed by\nwhitespace and is terminated by the next paragraph at the same level of\nindentation.  (There needs to be a blank line between explicit markup and normal\nparagraphs.  This may all sound a bit complicated, but it is intuitive enough\nwhen you write it.)\n\n\n.. _directives:\n\nDirectives\n----------\n\nA directive (:duref:`ref &lt;directives&gt;`) is a generic block of explicit markup.\nBesides roles, it is one of the extension mechanisms of reST, and Sphinx makes\nheavy use of it.\n\nDocutils supports the following directives:\n\n* Admonitions: :dudir:`attention`, :dudir:`caution`, :dudir:`danger`,\n  :dudir:`error`, :dudir:`hint`, :dudir:`important`, :dudir:`note`,\n  :dudir:`tip`, :dudir:`warning` and the generic :dudir:`admonition`.\n  (Most themes style only \"note\" and \"warning\" specially.)\n\n* Images:\n\n  - :dudir:`image` (see also Images_ below)\n  - :dudir:`figure` (an image with caption and optional legend)\n\n* Additional body elements:\n\n  - :dudir:`contents` (a local, i.e. for the current file only, table of\n    contents)\n  - :dudir:`container` (a container with a custom class, useful to generate an\n    outer ``&lt;div&gt;`` in HTML)\n  - :dudir:`rubric` (a heading without relation to the document sectioning)\n  - :dudir:`topic`, :dudir:`sidebar` (special highlighted body elements)\n  - :dudir:`parsed-literal` (literal block that supports inline markup)\n  - :dudir:`epigraph` (a block quote with optional attribution line)\n  - :dudir:`highlights`, :dudir:`pull-quote` (block quotes with their own\n    class attribute)\n  - :dudir:`compound` (a compound paragraph)\n\n* Special tables:\n\n  - :dudir:`table` (a table with title)\n  - :dudir:`csv-table` (a table generated from comma-separated values)\n  - :dudir:`list-table` (a table generated from a list of lists)\n\n* Special directives:\n\n  - :dudir:`raw` (include raw target-format markup)\n  - :dudir:`include` (include reStructuredText from another file)\n    -- in Sphinx, when given an absolute include file path, this directive takes\n    it as relative to the source directory\n  - :dudir:`class` (assign a class attribute to the next element) [1]_\n\n* HTML specifics:\n\n  - :dudir:`meta` (generation of HTML ``&lt;meta&gt;`` tags)\n  - :dudir:`title` (override document title)\n\n* Influencing markup:\n\n  - :dudir:`default-role` (set a new default role)\n  - :dudir:`role` (create a new role)\n\n  Since these are only per-file, better use Sphinx' facilities for setting the\n  :confval:`default_role`.\n\nDo *not* use the directives :dudir:`sectnum`, :dudir:`header` and\n:dudir:`footer`.\n\nDirectives added by Sphinx are described in :ref:`sphinxmarkup`.\n\nBasically, a directive consists of a name, arguments, options and content. (Keep\nthis terminology in mind, it is used in the next chapter describing custom\ndirectives.)  Looking at this example, ::\n\n   .. function:: foo(x)\n                 foo(y, z)\n      :module: some.module.name\n\n      Return a line of text input from the user.\n\n``function`` is the directive name.  It is given two arguments here, the\nremainder of the first line and the second line, as well as one option\n``module`` (as you can see, options are given in the lines immediately following\nthe arguments and indicated by the colons).  Options must be indented to the\nsame level as the directive content.\n\nThe directive content follows after a blank line and is indented relative to the\ndirective start.\n\n\nImages\n------\n\nreST supports an image directive (:dudir:`ref &lt;image&gt;`), used like so::\n\n   .. image:: gnu.png\n      (options)\n\nWhen used within Sphinx, the file name given (here ``gnu.png``) must either be\nrelative to the source file, or absolute which means that they are relative to\nthe top source directory.  For example, the file ``sketch/spam.rst`` could refer\nto the image ``images/spam.png`` as ``../images/spam.png`` or\n``/images/spam.png``.\n\nSphinx will automatically copy image files over to a subdirectory of the output\ndirectory on building (e.g. the ``_static`` directory for HTML output.)\n\nInterpretation of image size options (``width`` and ``height``) is as follows:\nif the size has no unit or the unit is pixels, the given size will only be\nrespected for output channels that support pixels (i.e. not in LaTeX output).\nOther units (like ``pt`` for points) will be used for HTML and LaTeX output.\n\nSphinx extends the standard docutils behavior by allowing an asterisk for the\nextension::\n\n   .. image:: gnu.*\n\nSphinx then searches for all images matching the provided pattern and determines\ntheir type.  Each builder then chooses the best image out of these candidates.\nFor instance, if the file name ``gnu.*`` was given and two files :file:`gnu.pdf`\nand :file:`gnu.png` existed in the source tree, the LaTeX builder would choose\nthe former, while the HTML builder would prefer the latter.\n\n.. versionchanged:: 0.4\n   Added the support for file names ending in an asterisk.\n\n.. versionchanged:: 0.6\n   Image paths can now be absolute.\n\n\nFootnotes\n---------\n\nFor footnotes (:duref:`ref &lt;footnotes&gt;`), use ``[#name]_`` to mark the footnote\nlocation, and add the footnote body at the bottom of the document after a\n\"Footnotes\" rubric heading, like so::\n\n   Lorem ipsum [#f1]_ dolor sit amet ... [#f2]_\n\n   .. rubric:: Footnotes\n\n   .. [#f1] Text of the first footnote.\n   .. [#f2] Text of the second footnote.\n\nYou can also explicitly number the footnotes (``[1]_``) or use auto-numbered\nfootnotes without names (``[#]_``).\n\n\nCitations\n---------\n\nStandard reST citations (:duref:`ref &lt;citations&gt;`) are supported, with the\nadditional feature that they are \"global\", i.e. all citations can be referenced\nfrom all files.  Use them like so::\n\n   Lorem ipsum [Ref]_ dolor sit amet.\n\n   .. [Ref] Book or article reference, URL or whatever.\n\nCitation usage is similar to footnote usage, but with a label that is not\nnumeric or begins with ``#``.\n\n\nSubstitutions\n-------------\n\nreST supports \"substitutions\" (:duref:`ref &lt;substitution-definitions&gt;`), which\nare pieces of text and/or markup referred to in the text by ``|name|``.  They\nare defined like footnotes with explicit markup blocks, like this::\n\n   .. |name| replace:: replacement *text*\n\nor this::\n\n   .. |caution| image:: warning.png\n                :alt: Warning!\n\nSee the :duref:`reST reference for substitutions &lt;substitution-definitions&gt;`\nfor details.\n\nIf you want to use some substitutions for all documents, put them into\n:confval:`rst_prolog` or put them into a separate file and include it into all\ndocuments you want to use them in, using the :rst:dir:`include` directive.  (Be\nsure to give the include file a file name extension differing from that of other\nsource files, to avoid Sphinx finding it as a standalone document.)\n\nSphinx defines some default substitutions, see :ref:`default-substitutions`.\n\n\nComments\n--------\n\nEvery explicit markup block which isn't a valid markup construct (like the\nfootnotes above) is regarded as a comment (:duref:`ref &lt;comments&gt;`).  For\nexample::\n\n   .. This is a comment.\n\nYou can indent text after a comment start to form multiline comments::\n\n   ..\n      This whole indented block\n      is a comment.\n\n      Still in the comment.\n\n\nSource encoding\n---------------\n\nSince the easiest way to include special characters like em dashes or copyright\nsigns in reST is to directly write them as Unicode characters, one has to\nspecify an encoding.  Sphinx assumes source files to be encoded in UTF-8 by\ndefault; you can change this with the :confval:`source_encoding` config value.\n\n\nGotchas\n-------\n\nThere are some problems one commonly runs into while authoring reST documents:\n\n* **Separation of inline markup:** As said above, inline markup spans must be\n  separated from the surrounding text by non-word characters, you have to use a\n  backslash-escaped space to get around that.  See `the reference\n  &lt;http://docutils.sf.net/docs/ref/rst/restructuredtext.html#inline-markup&gt;`_\n  for the details.\n\n* **No nested inline markup:** Something like ``*see :func:`foo`*`` is not\n  possible.\n\n\n.. rubric:: Footnotes\n\n.. [1] When the default domain contains a :rst:dir:`class` directive, this directive\n       will be shadowed.  Therefore, Sphinx re-exports it as :rst:dir:`rst-class`.\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n      });\n    </script>\n    <p>The reStructuredText mode supports one configuration parameter:</p>\n    <dl>\n      <dt><code>verbatim (string)</code></dt>\n      <dd>A name or MIME type of a mode that will be used for highlighting\n      verbatim blocks. By default, reStructuredText mode uses uniform color\n      for whole block of verbatim text if no mode is given.</dd>\n    </dl>\n    <p>If <code>python</code> mode is available,\n    it will be used for highlighting blocks containing Python/IPython terminal\n    sessions (blocks starting with <code>&gt;&gt;&gt;</code> (for Python) or\n    <code>In [num]:</code> (for IPython).\n\n    <p><strong>MIME types defined:</strong> <code>text/x-rst</code>.</p>\n  </body>\n</html>\n\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/rst/rst.js",
    "content": "CodeMirror.defineMode('rst', function(config, options) {\n    function setState(state, fn, ctx) {\n        state.fn = fn;\n        setCtx(state, ctx);\n    }\n\n    function setCtx(state, ctx) {\n        state.ctx = ctx || {};\n    }\n\n    function setNormal(state, ch) {\n        if (ch && (typeof ch !== 'string')) {\n            var str = ch.current();\n            ch = str[str.length-1];\n        }\n\n        setState(state, normal, {back: ch});\n    }\n\n    function hasMode(mode) {\n        if (mode) {\n            var modes = CodeMirror.listModes();\n\n            for (var i in modes) {\n                if (modes[i] == mode) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    function getMode(mode) {\n        if (hasMode(mode)) {\n            return CodeMirror.getMode(config, mode);\n        } else {\n            return null;\n        }\n    }\n\n    var verbatimMode = getMode(options.verbatim);\n    var pythonMode = getMode('python');\n\n    var reSection = /^[!\"#$%&'()*+,-./:;<=>?@[\\\\\\]^_`{|}~]/;\n    var reDirective = /^\\s*\\w([-:.\\w]*\\w)?::(\\s|$)/;\n    var reHyperlink = /^\\s*_[\\w-]+:(\\s|$)/;\n    var reFootnote = /^\\s*\\[(\\d+|#)\\](\\s|$)/;\n    var reCitation = /^\\s*\\[[A-Za-z][\\w-]*\\](\\s|$)/;\n    var reFootnoteRef = /^\\[(\\d+|#)\\]_/;\n    var reCitationRef = /^\\[[A-Za-z][\\w-]*\\]_/;\n    var reDirectiveMarker = /^\\.\\.(\\s|$)/;\n    var reVerbatimMarker = /^::\\s*$/;\n    var rePreInline = /^[-\\s\"([{</:]/;\n    var rePostInline = /^[-\\s`'\")\\]}>/:.,;!?\\\\_]/;\n    var reEnumeratedList = /^\\s*((\\d+|[A-Za-z#])[.)]|\\((\\d+|[A-Z-a-z#])\\))\\s/;\n    var reBulletedList = /^\\s*[-\\+\\*]\\s/;\n    var reExamples = /^\\s+(>>>|In \\[\\d+\\]:)\\s/;\n\n    function normal(stream, state) {\n        var ch, sol, i;\n\n        if (stream.eat(/\\\\/)) {\n            ch = stream.next();\n            setNormal(state, ch);\n            return null;\n        }\n\n        sol = stream.sol();\n\n        if (sol && (ch = stream.eat(reSection))) {\n            for (i = 0; stream.eat(ch); i++);\n\n            if (i >= 3 && stream.match(/^\\s*$/)) {\n                setNormal(state, null);\n                return 'header';\n            } else {\n                stream.backUp(i + 1);\n            }\n        }\n\n        if (sol && stream.match(reDirectiveMarker)) {\n            if (!stream.eol()) {\n                setState(state, directive);\n            }\n            return 'meta';\n        }\n\n        if (stream.match(reVerbatimMarker)) {\n            if (!verbatimMode) {\n                setState(state, verbatim);\n            } else {\n                var mode = verbatimMode;\n\n                setState(state, verbatim, {\n                    mode: mode,\n                    local: mode.startState()\n                });\n            }\n            return 'meta';\n        }\n\n        if (sol && stream.match(reExamples, false)) {\n            if (!pythonMode) {\n                setState(state, verbatim);\n                return 'meta';\n            } else {\n                var mode = pythonMode;\n\n                setState(state, verbatim, {\n                    mode: mode,\n                    local: mode.startState()\n                });\n\n                return null;\n            }\n        }\n\n        function testBackward(re) {\n            return sol || !state.ctx.back || re.test(state.ctx.back);\n        }\n\n        function testForward(re) {\n            return stream.eol() || stream.match(re, false);\n        }\n\n        function testInline(re) {\n            return stream.match(re) && testBackward(/\\W/) && testForward(/\\W/);\n        }\n\n        if (testInline(reFootnoteRef)) {\n            setNormal(state, stream);\n            return 'footnote';\n        }\n\n        if (testInline(reCitationRef)) {\n            setNormal(state, stream);\n            return 'citation';\n        }\n\n        ch = stream.next();\n\n        if (testBackward(rePreInline)) {\n            if ((ch === ':' || ch === '|') && stream.eat(/\\S/)) {\n                var token;\n\n                if (ch === ':') {\n                    token = 'builtin';\n                } else {\n                    token = 'atom';\n                }\n\n                setState(state, inline, {\n                    ch: ch,\n                    wide: false,\n                    prev: null,\n                    token: token\n                });\n\n                return token;\n            }\n\n            if (ch === '*' || ch === '`') {\n                var orig = ch,\n                    wide = false;\n\n                ch = stream.next();\n\n                if (ch == orig) {\n                    wide = true;\n                    ch = stream.next();\n                }\n\n                if (ch && !/\\s/.test(ch)) {\n                    var token;\n\n                    if (orig === '*') {\n                        token = wide ? 'strong' : 'em';\n                    } else {\n                        token = wide ? 'string' : 'string-2';\n                    }\n\n                    setState(state, inline, {\n                        ch: orig,               // inline() has to know what to search for\n                        wide: wide,             // are we looking for `ch` or `chch`\n                        prev: null,             // terminator must not be preceeded with whitespace\n                        token: token            // I don't want to recompute this all the time\n                    });\n\n                    return token;\n                }\n            }\n        }\n\n        setNormal(state, ch);\n        return null;\n    }\n\n    function inline(stream, state) {\n        var ch = stream.next(),\n            token = state.ctx.token;\n\n        function finish(ch) {\n            state.ctx.prev = ch;\n            return token;\n        }\n\n        if (ch != state.ctx.ch) {\n            return finish(ch);\n        }\n\n        if (/\\s/.test(state.ctx.prev)) {\n            return finish(ch);\n        }\n\n        if (state.ctx.wide) {\n            ch = stream.next();\n\n            if (ch != state.ctx.ch) {\n                return finish(ch);\n            }\n        }\n\n        if (!stream.eol() && !rePostInline.test(stream.peek())) {\n            if (state.ctx.wide) {\n                stream.backUp(1);\n            }\n\n            return finish(ch);\n        }\n\n        setState(state, normal);\n        setNormal(state, ch);\n\n        return token;\n    }\n\n    function directive(stream, state) {\n        var token = null;\n\n        if (stream.match(reDirective)) {\n            token = 'attribute';\n        } else if (stream.match(reHyperlink)) {\n            token = 'link';\n        } else if (stream.match(reFootnote)) {\n            token = 'quote';\n        } else if (stream.match(reCitation)) {\n            token = 'quote';\n        } else {\n            stream.eatSpace();\n\n            if (stream.eol()) {\n                setNormal(state, stream);\n                return null;\n            } else {\n                stream.skipToEnd();\n                setState(state, comment);\n                return 'comment';\n            }\n        }\n\n        // FIXME this is unreachable\n        setState(state, body, {start: true});\n        return token;\n    }\n\n    function body(stream, state) {\n        var token = 'body';\n\n        if (!state.ctx.start || stream.sol()) {\n            return block(stream, state, token);\n        }\n\n        stream.skipToEnd();\n        setCtx(state);\n\n        return token;\n    }\n\n    function comment(stream, state) {\n        return block(stream, state, 'comment');\n    }\n\n    function verbatim(stream, state) {\n        if (!verbatimMode) {\n            return block(stream, state, 'meta');\n        } else {\n            if (stream.sol()) {\n                if (!stream.eatSpace()) {\n                    setNormal(state, stream);\n                }\n\n                return null;\n            }\n\n            return verbatimMode.token(stream, state.ctx.local);\n        }\n    }\n\n    function block(stream, state, token) {\n        if (stream.eol() || stream.eatSpace()) {\n            stream.skipToEnd();\n            return token;\n        } else {\n            setNormal(state, stream);\n            return null;\n        }\n    }\n\n    return {\n        startState: function() {\n            return {fn: normal, ctx: {}};\n        },\n\n        copyState: function(state) {\n            return {fn: state.fn, ctx: state.ctx};\n        },\n\n        token: function(stream, state) {\n            var token = state.fn(stream, state);\n            return token;\n        }\n    };\n}, \"python\");\n\nCodeMirror.defineMIME(\"text/x-rst\", \"rst\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/ruby/LICENSE",
    "content": "Copyright (c) 2011, Ubalo, Inc.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the Ubalo, Inc. nor the names of its\n      contributors may be used to endorse or promote products derived\n      from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL UBALO, INC BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/ruby/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Ruby mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"ruby.js\"></script>\n    <style>\n      .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n      .cm-s-default span.cm-arrow { color: red; }\n    </style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Ruby mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n# Code from http://sandbox.mc.edu/~bennet/ruby/code/poly_rb.html\n#\n# This program evaluates polynomials.  It first asks for the coefficients\n# of a polynomial, which must be entered on one line, highest-order first.\n# It then requests values of x and will compute the value of the poly for\n# each x.  It will repeatly ask for x values, unless you the user enters\n# a blank line.  It that case, it will ask for another polynomial.  If the\n# user types quit for either input, the program immediately exits.\n#\n\n#\n# Function to evaluate a polynomial at x.  The polynomial is given\n# as a list of coefficients, from the greatest to the least.\ndef polyval(x, coef)\n    sum = 0\n    coef = coef.clone           # Don't want to destroy the original\n    while true\n        sum += coef.shift       # Add and remove the next coef\n        break if coef.empty?    # If no more, done entirely.\n        sum *= x                # This happens the right number of times.\n    end\n    return sum\nend\n\n#\n# Function to read a line containing a list of integers and return\n# them as an array of integers.  If the string conversion fails, it\n# throws TypeError.  If the input line is the word 'quit', then it\n# converts it to an end-of-file exception\ndef readints(prompt)\n    # Read a line\n    print prompt\n    line = readline.chomp\n    raise EOFError.new if line == 'quit' # You can also use a real EOF.\n            \n    # Go through each item on the line, converting each one and adding it\n    # to retval.\n    retval = [ ]\n    for str in line.split(/\\s+/)\n        if str =~ /^\\-?\\d+$/\n            retval.push(str.to_i)\n        else\n            raise TypeError.new\n        end\n    end\n\n    return retval\nend\n\n#\n# Take a coeff and an exponent and return the string representation, ignoring\n# the sign of the coefficient.\ndef term_to_str(coef, exp)\n    ret = \"\"\n\n    # Show coeff, unless it's 1 or at the right\n    coef = coef.abs\n    ret = coef.to_s     unless coef == 1 && exp > 0\n    ret += \"x\" if exp > 0                               # x if exponent not 0\n    ret += \"^\" + exp.to_s if exp > 1                    # ^exponent, if > 1.\n\n    return ret\nend\n\n#\n# Create a string of the polynomial in sort-of-readable form.\ndef polystr(p)\n    # Get the exponent of first coefficient, plus 1.\n    exp = p.length\n\n    # Assign exponents to each term, making pairs of coeff and exponent,\n    # Then get rid of the zero terms.\n    p = (p.map { |c| exp -= 1; [ c, exp ] }).select { |p| p[0] != 0 }\n\n    # If there's nothing left, it's a zero\n    return \"0\" if p.empty?\n\n    # *** Now p is a non-empty list of [ coef, exponent ] pairs. ***\n\n    # Convert the first term, preceded by a \"-\" if it's negative.\n    result = (if p[0][0] < 0 then \"-\" else \"\" end) + term_to_str(*p[0])\n\n    # Convert the rest of the terms, in each case adding the appropriate\n    # + or - separating them.  \n    for term in p[1...p.length]\n        # Add the separator then the rep. of the term.\n        result += (if term[0] < 0 then \" - \" else \" + \" end) + \n                term_to_str(*term)\n    end\n\n    return result\nend\n        \n#\n# Run until some kind of endfile.\nbegin\n    # Repeat until an exception or quit gets us out.\n    while true\n        # Read a poly until it works.  An EOF will except out of the\n        # program.\n        print \"\\n\"\n        begin\n            poly = readints(\"Enter a polynomial coefficients: \")\n        rescue TypeError\n            print \"Try again.\\n\"\n            retry\n        end\n        break if poly.empty?\n\n        # Read and evaluate x values until the user types a blank line.\n        # Again, an EOF will except out of the pgm.\n        while true\n            # Request an integer.\n            print \"Enter x value or blank line: \"\n            x = readline.chomp\n            break if x == ''\n            raise EOFError.new if x == 'quit'\n\n            # If it looks bad, let's try again.\n            if x !~ /^\\-?\\d+$/\n                print \"That doesn't look like an integer.  Please try again.\\n\"\n                next\n            end\n\n            # Convert to an integer and print the result.\n            x = x.to_i\n            print \"p(x) = \", polystr(poly), \"\\n\"\n            print \"p(\", x, \") = \", polyval(x, poly), \"\\n\"\n        end\n    end\nrescue EOFError\n    print \"\\n=== EOF ===\\n\"\nrescue Interrupt, SignalException\n    print \"\\n=== Interrupted ===\\n\"\nelse\n    print \"--- Bye ---\\n\"\nend\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: \"text/x-ruby\",\n        tabMode: \"indent\",\n        matchBrackets: true,\n        indentUnit: 4\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-ruby</code>.</p>\n\n    <p>Development of the CodeMirror Ruby mode was kindly sponsored\n    by <a href=\"http://ubalo.com/\">Ubalo</a>, who hold\n    the <a href=\"LICENSE\">license</a>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/ruby/ruby.js",
    "content": "CodeMirror.defineMode(\"ruby\", function(config, parserConfig) {\n  function wordObj(words) {\n    var o = {};\n    for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;\n    return o;\n  }\n  var keywords = wordObj([\n    \"alias\", \"and\", \"BEGIN\", \"begin\", \"break\", \"case\", \"class\", \"def\", \"defined?\", \"do\", \"else\",\n    \"elsif\", \"END\", \"end\", \"ensure\", \"false\", \"for\", \"if\", \"in\", \"module\", \"next\", \"not\", \"or\",\n    \"redo\", \"rescue\", \"retry\", \"return\", \"self\", \"super\", \"then\", \"true\", \"undef\", \"unless\",\n    \"until\", \"when\", \"while\", \"yield\", \"nil\", \"raise\", \"throw\", \"catch\", \"fail\", \"loop\", \"callcc\",\n    \"caller\", \"lambda\", \"proc\", \"public\", \"protected\", \"private\", \"require\", \"load\",\n    \"require_relative\", \"extend\", \"autoload\"\n  ]);\n  var indentWords = wordObj([\"def\", \"class\", \"case\", \"for\", \"while\", \"do\", \"module\", \"then\",\n                             \"catch\", \"loop\", \"proc\", \"begin\"]);\n  var dedentWords = wordObj([\"end\", \"until\"]);\n  var matching = {\"[\": \"]\", \"{\": \"}\", \"(\": \")\"};\n  var curPunc;\n\n  function chain(newtok, stream, state) {\n    state.tokenize.push(newtok);\n    return newtok(stream, state);\n  }\n\n  function tokenBase(stream, state) {\n    curPunc = null;\n    if (stream.sol() && stream.match(\"=begin\") && stream.eol()) {\n      state.tokenize.push(readBlockComment);\n      return \"comment\";\n    }\n    if (stream.eatSpace()) return null;\n    var ch = stream.next();\n    if (ch == \"`\" || ch == \"'\" || ch == '\"' ||\n        (ch == \"/\" && !stream.eol() && stream.peek() != \" \")) {\n      return chain(readQuoted(ch, \"string\", ch == '\"' || ch == \"`\"), stream, state);\n    } else if (ch == \"%\") {\n      var style, embed = false;\n      if (stream.eat(\"s\")) style = \"atom\";\n      else if (stream.eat(/[WQ]/)) { style = \"string\"; embed = true; }\n      else if (stream.eat(/[wxqr]/)) style = \"string\";\n      var delim = stream.eat(/[^\\w\\s]/);\n      if (!delim) return \"operator\";\n      if (matching.propertyIsEnumerable(delim)) delim = matching[delim];\n      return chain(readQuoted(delim, style, embed, true), stream, state);\n    } else if (ch == \"#\") {\n      stream.skipToEnd();\n      return \"comment\";\n    } else if (ch == \"<\" && stream.eat(\"<\")) {\n      stream.eat(\"-\");\n      stream.eat(/[\\'\\\"\\`]/);\n      var match = stream.match(/^\\w+/);\n      stream.eat(/[\\'\\\"\\`]/);\n      if (match) return chain(readHereDoc(match[0]), stream, state);\n      return null;\n    } else if (ch == \"0\") {\n      if (stream.eat(\"x\")) stream.eatWhile(/[\\da-fA-F]/);\n      else if (stream.eat(\"b\")) stream.eatWhile(/[01]/);\n      else stream.eatWhile(/[0-7]/);\n      return \"number\";\n    } else if (/\\d/.test(ch)) {\n      stream.match(/^[\\d_]*(?:\\.[\\d_]+)?(?:[eE][+\\-]?[\\d_]+)?/);\n      return \"number\";\n    } else if (ch == \"?\") {\n      while (stream.match(/^\\\\[CM]-/)) {}\n      if (stream.eat(\"\\\\\")) stream.eatWhile(/\\w/);\n      else stream.next();\n      return \"string\";\n    } else if (ch == \":\") {\n      if (stream.eat(\"'\")) return chain(readQuoted(\"'\", \"atom\", false), stream, state);\n      if (stream.eat('\"')) return chain(readQuoted('\"', \"atom\", true), stream, state);\n      stream.eatWhile(/[\\w\\?]/);\n      return \"atom\";\n    } else if (ch == \"@\") {\n      stream.eat(\"@\");\n      stream.eatWhile(/[\\w\\?]/);\n      return \"variable-2\";\n    } else if (ch == \"$\") {\n      stream.next();\n      stream.eatWhile(/[\\w\\?]/);\n      return \"variable-3\";\n    } else if (/\\w/.test(ch)) {\n      stream.eatWhile(/[\\w\\?]/);\n      if (stream.eat(\":\")) return \"atom\";\n      return \"ident\";\n    } else if (ch == \"|\" && (state.varList || state.lastTok == \"{\" || state.lastTok == \"do\")) {\n      curPunc = \"|\";\n      return null;\n    } else if (/[\\(\\)\\[\\]{}\\\\;]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    } else if (ch == \"-\" && stream.eat(\">\")) {\n      return \"arrow\";\n    } else if (/[=+\\-\\/*:\\.^%<>~|]/.test(ch)) {\n      stream.eatWhile(/[=+\\-\\/*:\\.^%<>~|]/);\n      return \"operator\";\n    } else {\n      return null;\n    }\n  }\n\n  function tokenBaseUntilBrace() {\n    var depth = 1;\n    return function(stream, state) {\n      if (stream.peek() == \"}\") {\n        depth--;\n        if (depth == 0) {\n          state.tokenize.pop();\n          return state.tokenize[state.tokenize.length-1](stream, state);\n        }\n      } else if (stream.peek() == \"{\") {\n        depth++;\n      }\n      return tokenBase(stream, state);\n    };\n  }\n  function readQuoted(quote, style, embed, unescaped) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && (unescaped || !escaped)) {\n          state.tokenize.pop();\n          break;\n        }\n        if (embed && ch == \"#\" && !escaped && stream.eat(\"{\")) {\n          state.tokenize.push(tokenBaseUntilBrace(arguments.callee));\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return style;\n    };\n  }\n  function readHereDoc(phrase) {\n    return function(stream, state) {\n      if (stream.match(phrase)) state.tokenize.pop();\n      else stream.skipToEnd();\n      return \"string\";\n    };\n  }\n  function readBlockComment(stream, state) {\n    if (stream.sol() && stream.match(\"=end\") && stream.eol())\n      state.tokenize.pop();\n    stream.skipToEnd();\n    return \"comment\";\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: [tokenBase],\n              indented: 0,\n              context: {type: \"top\", indented: -config.indentUnit},\n              continuedLine: false,\n              lastTok: null,\n              varList: false};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) state.indented = stream.indentation();\n      var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype;\n      if (style == \"ident\") {\n        var word = stream.current();\n        style = keywords.propertyIsEnumerable(stream.current()) ? \"keyword\"\n          : /^[A-Z]/.test(word) ? \"tag\"\n          : (state.lastTok == \"def\" || state.lastTok == \"class\" || state.varList) ? \"def\"\n          : \"variable\";\n        if (indentWords.propertyIsEnumerable(word)) kwtype = \"indent\";\n        else if (dedentWords.propertyIsEnumerable(word)) kwtype = \"dedent\";\n        else if ((word == \"if\" || word == \"unless\") && stream.column() == stream.indentation())\n          kwtype = \"indent\";\n      }\n      if (curPunc || (style && style != \"comment\")) state.lastTok = word || curPunc || style;\n      if (curPunc == \"|\") state.varList = !state.varList;\n\n      if (kwtype == \"indent\" || /[\\(\\[\\{]/.test(curPunc))\n        state.context = {prev: state.context, type: curPunc || style, indented: state.indented};\n      else if ((kwtype == \"dedent\" || /[\\)\\]\\}]/.test(curPunc)) && state.context.prev)\n        state.context = state.context.prev;\n\n      if (stream.eol())\n        state.continuedLine = (curPunc == \"\\\\\" || style == \"operator\");\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0);\n      var ct = state.context;\n      var closing = ct.type == matching[firstChar] ||\n        ct.type == \"keyword\" && /^(?:end|until|else|elsif|when|rescue)\\b/.test(textAfter);\n      return ct.indented + (closing ? 0 : config.indentUnit) +\n        (state.continuedLine ? config.indentUnit : 0);\n    },\n     electricChars: \"}de\" // enD and rescuE\n\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-ruby\", \"ruby\");\n\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/rust/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Rust mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"rust.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: Rust mode</h1>\n\n<div><textarea id=\"code\" name=\"code\">\n// Demo code.\n\ntype foo<T> = int;\nenum bar {\n    some(int, foo<float>),\n    none\n}\n\nfn check_crate(x: int) {\n    let v = 10;\n    alt foo {\n      1 to 3 {\n        print_foo();\n        if x {\n            blah() + 10;\n        }\n      }\n      (x, y) { \"bye\" }\n      _ { \"hi\" }\n    }\n}\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        tabMode: \"indent\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-rustsrc</code>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/rust/rust.js",
    "content": "CodeMirror.defineMode(\"rust\", function() {\n  var indentUnit = 4, altIndentUnit = 2;\n  var valKeywords = {\n    \"if\": \"if-style\", \"while\": \"if-style\", \"else\": \"else-style\",\n    \"do\": \"else-style\", \"ret\": \"else-style\", \"fail\": \"else-style\",\n    \"break\": \"atom\", \"cont\": \"atom\", \"const\": \"let\", \"resource\": \"fn\",\n    \"let\": \"let\", \"fn\": \"fn\", \"for\": \"for\", \"alt\": \"alt\", \"iface\": \"iface\",\n    \"impl\": \"impl\", \"type\": \"type\", \"enum\": \"enum\", \"mod\": \"mod\",\n    \"as\": \"op\", \"true\": \"atom\", \"false\": \"atom\", \"assert\": \"op\", \"check\": \"op\",\n    \"claim\": \"op\", \"native\": \"ignore\", \"unsafe\": \"ignore\", \"import\": \"else-style\",\n    \"export\": \"else-style\", \"copy\": \"op\", \"log\": \"op\", \"log_err\": \"op\",\n    \"use\": \"op\", \"bind\": \"op\", \"self\": \"atom\"\n  };\n  var typeKeywords = function() {\n    var keywords = {\"fn\": \"fn\", \"block\": \"fn\", \"obj\": \"obj\"};\n    var atoms = \"bool uint int i8 i16 i32 i64 u8 u16 u32 u64 float f32 f64 str char\".split(\" \");\n    for (var i = 0, e = atoms.length; i < e; ++i) keywords[atoms[i]] = \"atom\";\n    return keywords;\n  }();\n  var operatorChar = /[+\\-*&%=<>!?|\\.@]/;\n\n  // Tokenizer\n\n  // Used as scratch variable to communicate multiple values without\n  // consing up tons of objects.\n  var tcat, content;\n  function r(tc, style) {\n    tcat = tc;\n    return style;\n  }\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (ch == '\"') {\n      state.tokenize = tokenString;\n      return state.tokenize(stream, state);\n    }\n    if (ch == \"'\") {\n      tcat = \"atom\";\n      if (stream.eat(\"\\\\\")) {\n        if (stream.skipTo(\"'\")) { stream.next(); return \"string\"; }\n        else { return \"error\"; }\n      } else {\n        stream.next();\n        return stream.eat(\"'\") ? \"string\" : \"error\";\n      }\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"/\")) { stream.skipToEnd(); return \"comment\"; }\n      if (stream.eat(\"*\")) {\n        state.tokenize = tokenComment(1);\n        return state.tokenize(stream, state);\n      }\n    }\n    if (ch == \"#\") {\n      if (stream.eat(\"[\")) { tcat = \"open-attr\"; return null; }\n      stream.eatWhile(/\\w/);\n      return r(\"macro\", \"meta\");\n    }\n    if (ch == \":\" && stream.match(\":<\")) {\n      return r(\"op\", null);\n    }\n    if (ch.match(/\\d/) || (ch == \".\" && stream.eat(/\\d/))) {\n      var flp = false;\n      if (!stream.match(/^x[\\da-f]+/i) && !stream.match(/^b[01]+/)) {\n        stream.eatWhile(/\\d/);\n        if (stream.eat(\".\")) { flp = true; stream.eatWhile(/\\d/); }\n        if (stream.match(/^e[+\\-]?\\d+/i)) { flp = true; }\n      }\n      if (flp) stream.match(/^f(?:32|64)/);\n      else stream.match(/^[ui](?:8|16|32|64)/);\n      return r(\"atom\", \"number\");\n    }\n    if (ch.match(/[()\\[\\]{}:;,]/)) return r(ch, null);\n    if (ch == \"-\" && stream.eat(\">\")) return r(\"->\", null);\n    if (ch.match(operatorChar)) {\n      stream.eatWhile(operatorChar);\n      return r(\"op\", null);\n    }\n    stream.eatWhile(/\\w/);\n    content = stream.current();\n    if (stream.match(/^::\\w/)) {\n      stream.backUp(1);\n      return r(\"prefix\", \"variable-2\");\n    }\n    if (state.keywords.propertyIsEnumerable(content))\n      return r(state.keywords[content], content.match(/true|false/) ? \"atom\" : \"keyword\");\n    return r(\"name\", \"variable\");\n  }\n\n  function tokenString(stream, state) {\n    var ch, escaped = false;\n    while (ch = stream.next()) {\n      if (ch == '\"' && !escaped) {\n        state.tokenize = tokenBase;\n        return r(\"atom\", \"string\");\n      }\n      escaped = !escaped && ch == \"\\\\\";\n    }\n    // Hack to not confuse the parser when a string is split in\n    // pieces.\n    return r(\"op\", \"string\");\n  }\n\n  function tokenComment(depth) {\n    return function(stream, state) {\n      var lastCh = null, ch;\n      while (ch = stream.next()) {\n        if (ch == \"/\" && lastCh == \"*\") {\n          if (depth == 1) {\n            state.tokenize = tokenBase;\n            break;\n          } else {\n            state.tokenize = tokenComment(depth - 1);\n            return state.tokenize(stream, state);\n          }\n        }\n        if (ch == \"*\" && lastCh == \"/\") {\n          state.tokenize = tokenComment(depth + 1);\n          return state.tokenize(stream, state);\n        }\n        lastCh = ch;\n      }\n      return \"comment\";\n    };\n  }\n\n  // Parser\n\n  var cx = {state: null, stream: null, marked: null, cc: null};\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n\n  function pushlex(type, info) {\n    var result = function() {\n      var state = cx.state;\n      state.lexical = {indented: state.indented, column: cx.stream.column(),\n                       type: type, prev: state.lexical, info: info};\n    };\n    result.lex = true;\n    return result;\n  }\n  function poplex() {\n    var state = cx.state;\n    if (state.lexical.prev) {\n      if (state.lexical.type == \")\")\n        state.indented = state.lexical.indented;\n      state.lexical = state.lexical.prev;\n    }\n  }\n  function typecx() { cx.state.keywords = typeKeywords; }\n  function valcx() { cx.state.keywords = valKeywords; }\n  poplex.lex = typecx.lex = valcx.lex = true;\n\n  function commasep(comb, end) {\n    function more(type) {\n      if (type == \",\") return cont(comb, more);\n      if (type == end) return cont();\n      return cont(more);\n    }\n    return function(type) {\n      if (type == end) return cont();\n      return pass(comb, more);\n    };\n  }\n\n  function stat_of(comb, tag) {\n    return cont(pushlex(\"stat\", tag), comb, poplex, block);\n  }\n  function block(type) {\n    if (type == \"}\") return cont();\n    if (type == \"let\") return stat_of(letdef1, \"let\");\n    if (type == \"fn\") return stat_of(fndef);\n    if (type == \"type\") return cont(pushlex(\"stat\"), tydef, endstatement, poplex, block);\n    if (type == \"enum\") return stat_of(enumdef);\n    if (type == \"mod\") return stat_of(mod);\n    if (type == \"iface\") return stat_of(iface);\n    if (type == \"impl\") return stat_of(impl);\n    if (type == \"open-attr\") return cont(pushlex(\"]\"), commasep(expression, \"]\"), poplex);\n    if (type == \"ignore\" || type.match(/[\\]\\);,]/)) return cont(block);\n    return pass(pushlex(\"stat\"), expression, poplex, endstatement, block);\n  }\n  function endstatement(type) {\n    if (type == \";\") return cont();\n    return pass();\n  }\n  function expression(type) {\n    if (type == \"atom\" || type == \"name\") return cont(maybeop);\n    if (type == \"{\") return cont(pushlex(\"}\"), exprbrace, poplex);\n    if (type.match(/[\\[\\(]/)) return matchBrackets(type, expression);\n    if (type.match(/[\\]\\)\\};,]/)) return pass();\n    if (type == \"if-style\") return cont(expression, expression);\n    if (type == \"else-style\" || type == \"op\") return cont(expression);\n    if (type == \"for\") return cont(pattern, maybetype, inop, expression, expression);\n    if (type == \"alt\") return cont(expression, altbody);\n    if (type == \"fn\") return cont(fndef);\n    if (type == \"macro\") return cont(macro);\n    return cont();\n  }\n  function maybeop(type) {\n    if (content == \".\") return cont(maybeprop);\n    if (content == \"::<\"){return cont(typarams, maybeop);}\n    if (type == \"op\" || content == \":\") return cont(expression);\n    if (type == \"(\" || type == \"[\") return matchBrackets(type, expression);\n    return pass();\n  }\n  function maybeprop(type) {\n    if (content.match(/^\\w+$/)) {cx.marked = \"variable\"; return cont(maybeop);}\n    return pass(expression);\n  }\n  function exprbrace(type) {\n    if (type == \"op\") {\n      if (content == \"|\") return cont(blockvars, poplex, pushlex(\"}\", \"block\"), block);\n      if (content == \"||\") return cont(poplex, pushlex(\"}\", \"block\"), block);\n    }\n    if (content == \"mutable\" || (content.match(/^\\w+$/) && cx.stream.peek() == \":\"\n                                 && !cx.stream.match(\"::\", false)))\n      return pass(record_of(expression));\n    return pass(block);\n  }\n  function record_of(comb) {\n    function ro(type) {\n      if (content == \"mutable\" || content == \"with\") {cx.marked = \"keyword\"; return cont(ro);}\n      if (content.match(/^\\w*$/)) {cx.marked = \"variable\"; return cont(ro);}\n      if (type == \":\") return cont(comb, ro);\n      if (type == \"}\") return cont();\n      return cont(ro);\n    }\n    return ro;\n  }\n  function blockvars(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(blockvars);}\n    if (type == \"op\" && content == \"|\") return cont();\n    return cont(blockvars);\n  }\n\n  function letdef1(type) {\n    if (type.match(/[\\]\\)\\};]/)) return cont();\n    if (content == \"=\") return cont(expression, letdef2);\n    if (type == \",\") return cont(letdef1);\n    return pass(pattern, maybetype, letdef1);\n  }\n  function letdef2(type) {\n    if (type.match(/[\\]\\)\\};,]/)) return pass(letdef1);\n    else return pass(expression, letdef2);\n  }\n  function maybetype(type) {\n    if (type == \":\") return cont(typecx, rtype, valcx);\n    return pass();\n  }\n  function inop(type) {\n    if (type == \"name\" && content == \"in\") {cx.marked = \"keyword\"; return cont();}\n    return pass();\n  }\n  function fndef(type) {\n    if (content == \"@\" || content == \"~\") {cx.marked = \"keyword\"; return cont(fndef);}\n    if (type == \"name\") {cx.marked = \"def\"; return cont(fndef);}\n    if (content == \"<\") return cont(typarams, fndef);\n    if (type == \"{\") return pass(expression);\n    if (type == \"(\") return cont(pushlex(\")\"), commasep(argdef, \")\"), poplex, fndef);\n    if (type == \"->\") return cont(typecx, rtype, valcx, fndef);\n    if (type == \";\") return cont();\n    return cont(fndef);\n  }\n  function tydef(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(tydef);}\n    if (content == \"<\") return cont(typarams, tydef);\n    if (content == \"=\") return cont(typecx, rtype, valcx);\n    return cont(tydef);\n  }\n  function enumdef(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(enumdef);}\n    if (content == \"<\") return cont(typarams, enumdef);\n    if (content == \"=\") return cont(typecx, rtype, valcx, endstatement);\n    if (type == \"{\") return cont(pushlex(\"}\"), typecx, enumblock, valcx, poplex);\n    return cont(enumdef);\n  }\n  function enumblock(type) {\n    if (type == \"}\") return cont();\n    if (type == \"(\") return cont(pushlex(\")\"), commasep(rtype, \")\"), poplex, enumblock);\n    if (content.match(/^\\w+$/)) cx.marked = \"def\";\n    return cont(enumblock);\n  }\n  function mod(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(mod);}\n    if (type == \"{\") return cont(pushlex(\"}\"), block, poplex);\n    return pass();\n  }\n  function iface(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(iface);}\n    if (content == \"<\") return cont(typarams, iface);\n    if (type == \"{\") return cont(pushlex(\"}\"), block, poplex);\n    return pass();\n  }\n  function impl(type) {\n    if (content == \"<\") return cont(typarams, impl);\n    if (content == \"of\" || content == \"for\") {cx.marked = \"keyword\"; return cont(rtype, impl);}\n    if (type == \"name\") {cx.marked = \"def\"; return cont(impl);}\n    if (type == \"{\") return cont(pushlex(\"}\"), block, poplex);\n    return pass();\n  }\n  function typarams(type) {\n    if (content == \">\") return cont();\n    if (content == \",\") return cont(typarams);\n    if (content == \":\") return cont(rtype, typarams);\n    return pass(rtype, typarams);\n  }\n  function argdef(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(argdef);}\n    if (type == \":\") return cont(typecx, rtype, valcx);\n    return pass();\n  }\n  function rtype(type) {\n    if (type == \"name\") {cx.marked = \"variable-3\"; return cont(rtypemaybeparam); }\n    if (content == \"mutable\") {cx.marked = \"keyword\"; return cont(rtype);}\n    if (type == \"atom\") return cont(rtypemaybeparam);\n    if (type == \"op\" || type == \"obj\") return cont(rtype);\n    if (type == \"fn\") return cont(fntype);\n    if (type == \"{\") return cont(pushlex(\"{\"), record_of(rtype), poplex);\n    return matchBrackets(type, rtype);\n  }\n  function rtypemaybeparam(type) {\n    if (content == \"<\") return cont(typarams);\n    return pass();\n  }\n  function fntype(type) {\n    if (type == \"(\") return cont(pushlex(\"(\"), commasep(rtype, \")\"), poplex, fntype);\n    if (type == \"->\") return cont(rtype);\n    return pass();\n  }\n  function pattern(type) {\n    if (type == \"name\") {cx.marked = \"def\"; return cont(patternmaybeop);}\n    if (type == \"atom\") return cont(patternmaybeop);\n    if (type == \"op\") return cont(pattern);\n    if (type.match(/[\\]\\)\\};,]/)) return pass();\n    return matchBrackets(type, pattern);\n  }\n  function patternmaybeop(type) {\n    if (type == \"op\" && content == \".\") return cont();\n    if (content == \"to\") {cx.marked = \"keyword\"; return cont(pattern);}\n    else return pass();\n  }\n  function altbody(type) {\n    if (type == \"{\") return cont(pushlex(\"}\", \"alt\"), altblock1, poplex);\n    return pass();\n  }\n  function altblock1(type) {\n    if (type == \"}\") return cont();\n    if (type == \"|\") return cont(altblock1);\n    if (content == \"when\") {cx.marked = \"keyword\"; return cont(expression, altblock2);}\n    if (type.match(/[\\]\\);,]/)) return cont(altblock1);\n    return pass(pattern, altblock2);\n  }\n  function altblock2(type) {\n    if (type == \"{\") return cont(pushlex(\"}\", \"alt\"), block, poplex, altblock1);\n    else return pass(altblock1);\n  }\n\n  function macro(type) {\n    if (type.match(/[\\[\\(\\{]/)) return matchBrackets(type, expression);\n    return pass();\n  }\n  function matchBrackets(type, comb) {\n    if (type == \"[\") return cont(pushlex(\"]\"), commasep(comb, \"]\"), poplex);\n    if (type == \"(\") return cont(pushlex(\")\"), commasep(comb, \")\"), poplex);\n    if (type == \"{\") return cont(pushlex(\"}\"), commasep(comb, \"}\"), poplex);\n    return cont();\n  }\n\n  function parse(state, stream, style) {\n    var cc = state.cc;\n    // Communicate our context to the combinators.\n    // (Less wasteful than consing up a hundred closures on every call.)\n    cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;\n\n    while (true) {\n      var combinator = cc.length ? cc.pop() : block;\n      if (combinator(tcat)) {\n        while(cc.length && cc[cc.length - 1].lex)\n          cc.pop()();\n        return cx.marked || style;\n      }\n    }\n  }\n\n  return {\n    startState: function() {\n      return {\n        tokenize: tokenBase,\n        cc: [],\n        lexical: {indented: -indentUnit, column: 0, type: \"top\", align: false},\n        keywords: valKeywords,\n        indented: 0\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (!state.lexical.hasOwnProperty(\"align\"))\n          state.lexical.align = false;\n        state.indented = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      tcat = content = null;\n      var style = state.tokenize(stream, state);\n      if (style == \"comment\") return style;\n      if (!state.lexical.hasOwnProperty(\"align\"))\n        state.lexical.align = true;\n      if (tcat == \"prefix\") return style;\n      if (!content) content = stream.current();\n      return parse(state, stream, style);\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,\n          type = lexical.type, closing = firstChar == type;\n      if (type == \"stat\") return lexical.indented + indentUnit;\n      if (lexical.align) return lexical.column + (closing ? 0 : 1);\n      return lexical.indented + (closing ? 0 : (lexical.info == \"alt\" ? altIndentUnit : indentUnit));\n    },\n\n    electricChars: \"{}\"\n  };\n});\n\nCodeMirror.defineMIME(\"text/x-rustsrc\", \"rust\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/scheme/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Scheme mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"scheme.js\"></script>\n    <style>.CodeMirror {background: #f8f8f8;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Scheme mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n; See if the input starts with a given symbol.\n(define (match-symbol input pattern)\n  (cond ((null? (remain input)) #f)\n\t((eqv? (car (remain input)) pattern) (r-cdr input))\n\t(else #f)))\n\n; Allow the input to start with one of a list of patterns.\n(define (match-or input pattern)\n  (cond ((null? pattern) #f)\n\t((match-pattern input (car pattern)))\n\t(else (match-or input (cdr pattern)))))\n\n; Allow a sequence of patterns.\n(define (match-seq input pattern)\n  (if (null? pattern)\n      input\n      (let ((match (match-pattern input (car pattern))))\n\t(if match (match-seq match (cdr pattern)) #f))))\n\n; Match with the pattern but no problem if it does not match.\n(define (match-opt input pattern)\n  (let ((match (match-pattern input (car pattern))))\n    (if match match input)))\n\n; Match anything (other than '()), until pattern is found. The rather\n; clumsy form of requiring an ending pattern is needed to decide where\n; the end of the match is. If none is given, this will match the rest\n; of the sentence.\n(define (match-any input pattern)\n  (cond ((null? (remain input)) #f)\n\t((null? pattern) (f-cons (remain input) (clear-remain input)))\n\t(else\n\t (let ((accum-any (collector)))\n\t   (define (match-pattern-any input pattern)\n\t     (cond ((null? (remain input)) #f)\n\t\t   (else (accum-any (car (remain input)))\n\t\t\t (cond ((match-pattern (r-cdr input) pattern))\n\t\t\t       (else (match-pattern-any (r-cdr input) pattern))))))\n\t   (let ((retval (match-pattern-any input (car pattern))))\n\t     (if retval\n\t\t (f-cons (accum-any) retval)\n\t\t #f))))))\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-scheme</code>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/scheme/scheme.js",
    "content": "/**\n * Author: Koh Zi Han, based on implementation by Koh Zi Chun\n */\nCodeMirror.defineMode(\"scheme\", function (config, mode) {\n    var BUILTIN = \"builtin\", COMMENT = \"comment\", STRING = \"string\",\n        ATOM = \"atom\", NUMBER = \"number\", BRACKET = \"bracket\", KEYWORD=\"keyword\";\n    var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;\n\n    function makeKeywords(str) {\n        var obj = {}, words = str.split(\" \");\n        for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n        return obj;\n    }\n\n    var keywords = makeKeywords(\"λ case-lambda call/cc class define-class exit-handler field import inherit init-field interface let*-values let-values let/ec mixin opt-lambda override protect provide public rename require require-for-syntax syntax syntax-case syntax-error unit/sig unless when with-syntax and begin call-with-current-continuation call-with-input-file call-with-output-file case cond define define-syntax delay do dynamic-wind else for-each if lambda let let* let-syntax letrec letrec-syntax map or syntax-rules abs acos angle append apply asin assoc assq assv atan boolean? caar cadr call-with-input-file call-with-output-file call-with-values car cdddar cddddr cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char<? char=? char>=? char>? char? close-input-port close-output-port complex? cons cos current-input-port current-output-port denominator display eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt #f floor force gcd imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lcm length list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file output-port? pair? peek-char port? positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci<? string-ci=? string-ci>=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string<? string=? string>=? string>? string? substring symbol->string symbol? #t tan transcript-off transcript-on truncate values vector vector->list vector-fill! vector-length vector-ref vector-set! with-input-from-file with-output-to-file write write-char zero?\");\n    var indentKeys = makeKeywords(\"define let letrec let* lambda\");\n\n    function stateStack(indent, type, prev) { // represents a state stack object\n        this.indent = indent;\n        this.type = type;\n        this.prev = prev;\n    }\n\n    function pushStack(state, indent, type) {\n        state.indentStack = new stateStack(indent, type, state.indentStack);\n    }\n\n    function popStack(state) {\n        state.indentStack = state.indentStack.prev;\n    }\n\n    /**\n     * Scheme numbers are complicated unfortunately.\n     * Checks if we're looking at a number, which might be possibly a fraction.\n     * Also checks that it is not part of a longer identifier. Returns true/false accordingly.\n     */\n    function isNumber(ch, stream){\n        if (!stream.eatWhile(/[0-9]/)) {\n            if (stream.eat(/\\//)) stream.eatWhile(/[0-9]/);\n            if (stream.eol() || !(/[a-zA-Z\\-\\_\\/]/.test(stream.peek()))) return true;\n            stream.backUp(stream.current().length - 1); // undo all the eating\n        }\n        return false;\n    }\n\n    return {\n        startState: function () {\n            return {\n                indentStack: null,\n                indentation: 0,\n                mode: false,\n                sExprComment: false\n            };\n        },\n\n        token: function (stream, state) {\n            if (state.indentStack == null && stream.sol()) {\n                // update indentation, but only if indentStack is empty\n                state.indentation = stream.indentation();\n            }\n\n            // skip spaces\n            if (stream.eatSpace()) {\n                return null;\n            }\n            var returnType = null;\n\n            switch(state.mode){\n                case \"string\": // multi-line string parsing mode\n                    var next, escaped = false;\n                    while ((next = stream.next()) != null) {\n                        if (next == \"\\\"\" && !escaped) {\n\n                            state.mode = false;\n                            break;\n                        }\n                        escaped = !escaped && next == \"\\\\\";\n                    }\n                    returnType = STRING; // continue on in scheme-string mode\n                    break;\n                case \"comment\": // comment parsing mode\n                    var next, maybeEnd = false;\n                    while ((next = stream.next()) != null) {\n                        if (next == \"#\" && maybeEnd) {\n\n                            state.mode = false;\n                            break;\n                        }\n                        maybeEnd = (next == \"|\");\n                    }\n                    returnType = COMMENT;\n                    break;\n                case \"s-expr-comment\": // s-expr commenting mode\n                    state.mode = false;\n                    if(stream.peek() == \"(\" || stream.peek() == \"[\"){\n                        // actually start scheme s-expr commenting mode\n                        state.sExprComment = 0;\n                    }else{\n                        // if not we just comment the entire of the next token\n                        stream.eatWhile(/[^/s]/); // eat non spaces\n                        returnType = COMMENT;\n                        break;\n                    }\n                default: // default parsing mode\n                    var ch = stream.next();\n\n                    if (ch == \"\\\"\") {\n                        state.mode = \"string\";\n                        returnType = STRING;\n\n                    } else if (ch == \"'\") {\n                        returnType = ATOM;\n                    } else if (ch == '#') {\n                        if (stream.eat(\"|\")) {\t\t\t\t\t// Multi-line comment\n                            state.mode = \"comment\"; // toggle to comment mode\n                            returnType = COMMENT;\n                        } else if (stream.eat(/[tf]/)) {\t\t\t// #t/#f (atom)\n                            returnType = ATOM;\n                        } else if (stream.eat(';')) {\t\t\t\t// S-Expr comment\n                            state.mode = \"s-expr-comment\";\n                            returnType = COMMENT;\n                        }\n\n                    } else if (ch == \";\") { // comment\n                        stream.skipToEnd(); // rest of the line is a comment\n                        returnType = COMMENT;\n                    } else if (ch == \"-\"){\n\n                        if(!isNaN(parseInt(stream.peek()))){\n                            stream.eatWhile(/[\\/0-9]/);\n                            returnType = NUMBER;\n                        }else{\n                            returnType = null;\n                        }\n                    } else if (isNumber(ch,stream)){\n                        returnType = NUMBER;\n                    } else if (ch == \"(\" || ch == \"[\") {\n                        var keyWord = ''; var indentTemp = stream.column();\n                        /**\n                        Either\n                        (indent-word ..\n                        (non-indent-word ..\n                        (;something else, bracket, etc.\n                        */\n\n                        while ((letter = stream.eat(/[^\\s\\(\\[\\;\\)\\]]/)) != null) {\n                            keyWord += letter;\n                        }\n\n                        if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word\n\n                            pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);\n                        } else { // non-indent word\n                            // we continue eating the spaces\n                            stream.eatSpace();\n                            if (stream.eol() || stream.peek() == \";\") {\n                                // nothing significant after\n                                // we restart indentation 1 space after\n                                pushStack(state, indentTemp + 1, ch);\n                            } else {\n                                pushStack(state, indentTemp + stream.current().length, ch); // else we match\n                            }\n                        }\n                        stream.backUp(stream.current().length - 1); // undo all the eating\n\n                        if(typeof state.sExprComment == \"number\") state.sExprComment++;\n\n                        returnType = BRACKET;\n                    } else if (ch == \")\" || ch == \"]\") {\n                        returnType = BRACKET;\n                        if (state.indentStack != null && state.indentStack.type == (ch == \")\" ? \"(\" : \"[\")) {\n                            popStack(state);\n\n                            if(typeof state.sExprComment == \"number\"){\n                                if(--state.sExprComment == 0){\n                                    returnType = COMMENT; // final closing bracket\n                                    state.sExprComment = false; // turn off s-expr commenting mode\n                                }\n                            }\n                        }\n                    } else {\n                        stream.eatWhile(/[\\w\\$_\\-!$%&*+\\.\\/:<=>?@\\^~]/);\n\n                        if (keywords && keywords.propertyIsEnumerable(stream.current())) {\n                            returnType = BUILTIN;\n                        } else returnType = \"variable\";\n                    }\n            }\n            return (typeof state.sExprComment == \"number\") ? COMMENT : returnType;\n        },\n\n        indent: function (state, textAfter) {\n            if (state.indentStack == null) return state.indentation;\n            return state.indentStack.indent;\n        }\n    };\n});\n\nCodeMirror.defineMIME(\"text/x-scheme\", \"scheme\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/shell/index.html",
    "content": "<!doctype html>\n<meta charset=utf-8>\n<title>CodeMirror: Shell mode</title>\n\n<link rel=stylesheet href=../../lib/codemirror.css>\n<link rel=stylesheet href=../../doc/docs.css>\n\n<style type=text/css>\n  .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}\n</style>\n\n<script src=../../lib/codemirror.js></script>\n<script src=shell.js></script>\n\n<h1>CodeMirror: Shell mode</h1>\n\n<textarea id=code>\n#!/bin/bash\n\n# clone the repository\ngit clone http://github.com/garden/tree\n\n# generate HTTPS credentials\ncd tree\nopenssl genrsa -aes256 -out https.key 1024\nopenssl req -new -nodes -key https.key -out https.csr\nopenssl x509 -req -days 365 -in https.csr -signkey https.key -out https.crt\ncp https.key{,.orig}\nopenssl rsa -in https.key.orig -out https.key\n\n# start the server in HTTPS mode\ncd web\nsudo node ../server.js 443 'yes' &gt;&gt; ../node.log &amp;\n\n# here is how to stop the server\nfor pid in `ps aux | grep 'node ../server.js' | awk '{print $2}'` ; do\n  sudo kill -9 $pid 2&gt; /dev/null\ndone\n\nexit 0</textarea>\n\n<script>\n  var editor = CodeMirror.fromTextArea(document.getElementById('code'), {\n    mode: 'shell',\n    lineNumbers: true,\n    matchBrackets: true\n  });\n</script>\n\n<p><strong>MIME types defined:</strong> <code>text/x-sh</code>.</p>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/shell/shell.js",
    "content": "CodeMirror.defineMode('shell', function(config) {\n\n  var atoms = ['true','false'],\n      keywords = ['if','then','do','else','elif','while','until','for','in','esac','fi','fin','fil','done','exit','set','unset','export','function'],\n      commands = ['ab','awk','bash','beep','cat','cc','cd','chown','chmod','chroot','clear','cp','curl','cut','diff','echo','find','gawk','gcc','get','git','grep','kill','killall','ls','make','mkdir','openssl','mv','nc','node','npm','ping','ps','restart','rm','rmdir','sed','service','sh','shopt','shred','source','sort','sleep','ssh','start','stop','su','sudo','tee','telnet','top','touch','vi','vim','wall','wc','wget','who','write','yes','zsh'];\n\n  function tokenBase(stream, state) {\n\n    var sol = stream.sol();\n    var ch = stream.next();\n\n    if (ch === '\\'' || ch === '\"' || ch === '`') {\n      state.tokens.unshift(tokenString(ch));\n      return tokenize(stream, state);\n    }\n    if (ch === '#') {\n      if (sol && stream.eat('!')) {\n        stream.skipToEnd();\n        return 'meta'; // 'comment'?\n      }\n      stream.skipToEnd();\n      return 'comment';\n    }\n    if (ch === '$') {\n      state.tokens.unshift(tokenDollar);\n      return tokenize(stream, state);\n    }\n    if (ch === '+' || ch === '=') {\n      return 'operator';\n    }\n    if (ch === '-') {\n      stream.eat('-');\n      stream.eatWhile(/\\w/);\n      return 'attribute';\n    }\n    if (/\\d/.test(ch)) {\n      stream.eatWhile(/\\d/);\n      if(!/\\w/.test(stream.peek())) {\n        return 'number';\n      }\n    }\n    stream.eatWhile(/\\w/);\n    var cur = stream.current();\n    if (stream.peek() === '=' && /\\w+/.test(cur)) return 'def';\n    if (atoms.indexOf(cur) !== -1) return 'atom';\n    if (commands.indexOf(cur) !== -1) return 'builtin';\n    if (keywords.indexOf(cur) !== -1) return 'keyword';\n    return 'word';\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var next, end = false, escaped = false;\n      while ((next = stream.next()) != null) {\n        if (next === quote && !escaped) {\n          end = true;\n          break;\n        }\n        if (next === '$' && !escaped && quote !== '\\'') {\n          escaped = true;\n          stream.backUp(1);\n          state.tokens.unshift(tokenDollar);\n          break;\n        }\n        escaped = !escaped && next === '\\\\';\n      }\n      if (end || !escaped) {\n        state.tokens.shift();\n      }\n      return (quote === '`' || quote === ')' ? 'quote' : 'string');\n    };\n  };\n\n  var tokenDollar = function(stream, state) {\n    if (state.tokens.length > 1) stream.eat('$');\n    var ch = stream.next(), hungry = /\\w/;\n    if (ch === '{') hungry = /[^}]/;\n    if (ch === '(') {\n      state.tokens[0] = tokenString(')');\n      return tokenize(stream, state);\n    }\n    if (!/\\d/.test(ch)) {\n      stream.eatWhile(hungry);\n      stream.eat('}');\n    }\n    state.tokens.shift();\n    return 'def';\n  };\n\n  function tokenize(stream, state) {\n    return (state.tokens[0] || tokenBase) (stream, state);\n  };\n\n  return {\n    startState: function() {return {tokens:[]}},\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      return tokenize(stream, state);\n    }\n  };\n});\n  \nCodeMirror.defineMIME('text/x-sh', 'shell');\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/smalltalk/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Smalltalk mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"smalltalk.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style>\n      .CodeMirror {border: 2px solid #dee; border-right-width: 10px;}\n      .CodeMirror-gutter {border: none; background: #dee;}\n      .CodeMirror-gutter pre {color: white; font-weight: bold;}\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Smalltalk mode</h1>\n\n<form><textarea id=\"code\" name=\"code\">\n\" \n    This is a test of the Smalltalk code\n\"\nSeaside.WAComponent subclass: #MyCounter [\n    | count |\n    MyCounter class &gt;&gt; canBeRoot [ ^true ]\n\n    initialize [\n        super initialize.\n        count := 0.\n    ]\n    states [ ^{ self } ]\n    renderContentOn: html [\n        html heading: count.\n        html anchor callback: [ count := count + 1 ]; with: '++'.\n        html space.\n        html anchor callback: [ count := count - 1 ]; with: '--'.\n    ]\n]\n\nMyCounter registerAsApplication: 'mycounter'\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-stsrc\",\n        indentUnit: 4\n      });\n    </script>\n\n    <p>Simple Smalltalk mode.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-stsrc</code>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/smalltalk/smalltalk.js",
    "content": "CodeMirror.defineMode('smalltalk', function(config, modeConfig) {\n\n\tvar specialChars = /[+\\-/\\\\*~<>=@%|&?!.:;^]/;\n\tvar keywords = /true|false|nil|self|super|thisContext/;\n\n\tvar Context = function(tokenizer, parent) {\n\t\tthis.next = tokenizer;\n\t\tthis.parent = parent;\n\t};\n\n\tvar Token = function(name, context, eos) {\n\t\tthis.name = name;\n\t\tthis.context = context;\n\t\tthis.eos = eos;\n\t};\n\n\tvar State = function() {\n\t\tthis.context = new Context(next, null);\n\t\tthis.expectVariable = true;\n\t\tthis.indentation = 0;\n\t\tthis.userIndentationDelta = 0;\n\t};\n\n\tState.prototype.userIndent = function(indentation) {\n\t\tthis.userIndentationDelta = indentation > 0 ? (indentation / config.indentUnit - this.indentation) : 0;\n\t};\n\n\tvar next = function(stream, context, state) {\n\t\tvar token = new Token(null, context, false);\n\t\tvar aChar = stream.next();\n\n\t\tif (aChar === '\"') {\n\t\t\ttoken = nextComment(stream, new Context(nextComment, context));\n\n\t\t} else if (aChar === '\\'') {\n\t\t\ttoken = nextString(stream, new Context(nextString, context));\n\n\t\t} else if (aChar === '#') {\n\t\t\tstream.eatWhile(/[^ .]/);\n\t\t\ttoken.name = 'string-2';\n\n\t\t} else if (aChar === '$') {\n\t\t\tstream.eatWhile(/[^ ]/);\n\t\t\ttoken.name = 'string-2';\n\n\t\t} else if (aChar === '|' && state.expectVariable) {\n\t\t\ttoken.context = new Context(nextTemporaries, context);\n\n\t\t} else if (/[\\[\\]{}()]/.test(aChar)) {\n\t\t\ttoken.name = 'bracket';\n\t\t\ttoken.eos = /[\\[{(]/.test(aChar);\n\n\t\t\tif (aChar === '[') {\n\t\t\t\tstate.indentation++;\n\t\t\t} else if (aChar === ']') {\n\t\t\t\tstate.indentation = Math.max(0, state.indentation - 1);\n\t\t\t}\n\n\t\t} else if (specialChars.test(aChar)) {\n\t\t\tstream.eatWhile(specialChars);\n\t\t\ttoken.name = 'operator';\n\t\t\ttoken.eos = aChar !== ';'; // ; cascaded message expression\n\n\t\t} else if (/\\d/.test(aChar)) {\n\t\t\tstream.eatWhile(/[\\w\\d]/);\n\t\t\ttoken.name = 'number'\n\n\t\t} else if (/[\\w_]/.test(aChar)) {\n\t\t\tstream.eatWhile(/[\\w\\d_]/);\n\t\t\ttoken.name = state.expectVariable ? (keywords.test(stream.current()) ? 'keyword' : 'variable') : null;\n\n\t\t} else {\n\t\t\ttoken.eos = state.expectVariable;\n\t\t}\n\n\t\treturn token;\n\t};\n\n\tvar nextComment = function(stream, context) {\n\t\tstream.eatWhile(/[^\"]/);\n\t\treturn new Token('comment', stream.eat('\"') ? context.parent : context, true);\n\t};\n\n\tvar nextString = function(stream, context) {\n\t\tstream.eatWhile(/[^']/);\n\t\treturn new Token('string', stream.eat('\\'') ? context.parent : context, false);\n\t};\n\n\tvar nextTemporaries = function(stream, context, state) {\n\t\tvar token = new Token(null, context, false);\n\t\tvar aChar = stream.next();\n\n\t\tif (aChar === '|') {\n\t\t\ttoken.context = context.parent;\n\t\t\ttoken.eos = true;\n\n\t\t} else {\n\t\t\tstream.eatWhile(/[^|]/);\n\t\t\ttoken.name = 'variable';\n\t\t}\n\n\t\treturn token;\n\t}\n\n\treturn {\n\t\tstartState: function() {\n\t\t\treturn new State;\n\t\t},\n\n\t\ttoken: function(stream, state) {\n\t\t\tstate.userIndent(stream.indentation());\n\n\t\t\tif (stream.eatSpace()) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tvar token = state.context.next(stream, state.context, state);\n\t\t\tstate.context = token.context;\n\t\t\tstate.expectVariable = token.eos;\n\n\t\t\tstate.lastToken = token;\n\t\t\treturn token.name;\n\t\t},\n\n\t\tblankLine: function(state) {\n\t\t\tstate.userIndent(0);\n\t\t},\n\n\t\tindent: function(state, textAfter) {\n\t\t\tvar i = state.context.next === next && textAfter && textAfter.charAt(0) === ']' ? -1 : state.userIndentationDelta;\n\t\t\treturn (state.indentation + i) * config.indentUnit;\n\t\t},\n\n\t\telectricChars: ']'\n\t};\n\n});\n\nCodeMirror.defineMIME('text/x-stsrc', {name: 'smalltalk'});\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/smarty/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Smarty mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"smarty.js\"></script>\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Smarty mode</h1>\n\n    <form><textarea id=\"code\" name=\"code\">\n{extends file=\"parent.tpl\"}\n{include file=\"template.tpl\"}\n\n{* some example Smarty content *}\n{if isset($name) && $name == 'Blog'}\n  This is a {$var}.\n  {$integer = 451}, {$array[] = \"a\"}, {$stringvar = \"string\"}\n  {assign var='bob' value=$var.prop}\n{elseif $name == $foo}\n  {function name=menu level=0}\n    {foreach $data as $entry}\n      {if is_array($entry)}\n        - {$entry@key}\n        {menu data=$entry level=$level+1}\n      {else}\n        {$entry}\n      {/if}\n    {/foreach}\n  {/function}\n{/if}</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        mode: \"smarty\"\n      });\n    </script>\n\n    <br />\n\n    <form><textarea id=\"code2\" name=\"code2\">\n{--extends file=\"parent.tpl\"--}\n{--include file=\"template.tpl\"--}\n\n{--* some example Smarty content *--}\n{--if isset($name) && $name == 'Blog'--}\n  This is a {--$var--}.\n  {--$integer = 451--}, {--$array[] = \"a\"--}, {--$stringvar = \"string\"--}\n  {--assign var='bob' value=$var.prop--}\n{--elseif $name == $foo--}\n  {--function name=menu level=0--}\n    {--foreach $data as $entry--}\n      {--if is_array($entry)--}\n        - {--$entry@key--}\n        {--menu data=$entry level=$level+1--}\n      {--else--}\n        {--$entry--}\n      {--/if--}\n    {--/foreach--}\n  {--/function--}\n{--/if--}</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code2\"), {\n        lineNumbers: true,\n        mode: {\n          name: \"smarty\",\n          leftDelimiter: \"{--\",\n          rightDelimiter: \"--}\"\n        }\n      });\n    </script>\n\n    <p>A plain text/Smarty mode which allows for custom delimiter tags (defaults to <b>{</b> and <b>}</b>).</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-smarty</code></p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/smarty/smarty.js",
    "content": "CodeMirror.defineMode(\"smarty\", function(config, parserConfig) {\n  var keyFuncs = [\"debug\", \"extends\", \"function\", \"include\", \"literal\"];\n  var last;\n  var regs = {\n    operatorChars: /[+\\-*&%=<>!?]/,\n    validIdentifier: /[a-zA-Z0-9\\_]/,\n    stringChar: /[\\'\\\"]/\n  }\n  var leftDelim = (typeof config.mode.leftDelimiter != 'undefined') ? config.mode.leftDelimiter : \"{\";\n  var rightDelim = (typeof config.mode.rightDelimiter != 'undefined') ? config.mode.rightDelimiter : \"}\";\n  function ret(style, lst) { last = lst; return style; }\n\n\n  function tokenizer(stream, state) {\n    function chain(parser) {\n      state.tokenize = parser;\n      return parser(stream, state);\n    }\n\n    if (stream.match(leftDelim, true)) {\n      if (stream.eat(\"*\")) {\n        return chain(inBlock(\"comment\", \"*\" + rightDelim));\n      }\n      else {\n        state.tokenize = inSmarty;\n        return \"tag\";\n      }\n    }\n    else {\n      // I'd like to do an eatWhile() here, but I can't get it to eat only up to the rightDelim string/char\n      stream.next();\n      return null;\n    }\n  }\n\n  function inSmarty(stream, state) {\n    if (stream.match(rightDelim, true)) {\n      state.tokenize = tokenizer;\n      return ret(\"tag\", null);\n    }\n\n    var ch = stream.next();\n    if (ch == \"$\") {\n      stream.eatWhile(regs.validIdentifier);\n      return ret(\"variable-2\", \"variable\");\n    }\n    else if (ch == \".\") {\n      return ret(\"operator\", \"property\");\n    }\n    else if (regs.stringChar.test(ch)) {\n      state.tokenize = inAttribute(ch);\n      return ret(\"string\", \"string\");\n    }\n    else if (regs.operatorChars.test(ch)) {\n      stream.eatWhile(regs.operatorChars);\n      return ret(\"operator\", \"operator\");\n    }\n    else if (ch == \"[\" || ch == \"]\") {\n      return ret(\"bracket\", \"bracket\");\n    }\n    else if (/\\d/.test(ch)) {\n      stream.eatWhile(/\\d/);\n      return ret(\"number\", \"number\");\n    }\n    else {\n      if (state.last == \"variable\") {\n        if (ch == \"@\") {\n          stream.eatWhile(regs.validIdentifier);\n          return ret(\"property\", \"property\");\n        }\n        else if (ch == \"|\") {\n          stream.eatWhile(regs.validIdentifier);\n          return ret(\"qualifier\", \"modifier\");\n        }\n      }\n      else if (state.last == \"whitespace\") {\n        stream.eatWhile(regs.validIdentifier);\n        return ret(\"attribute\", \"modifier\");\n      }\n      else if (state.last == \"property\") {\n        stream.eatWhile(regs.validIdentifier);\n        return ret(\"property\", null);\n      }\n      else if (/\\s/.test(ch)) {\n        last = \"whitespace\";\n        return null;\n      }\n\n      var str = \"\";\n      if (ch != \"/\") {\n    \tstr += ch;\n      }\n      var c = \"\";\n      while ((c = stream.eat(regs.validIdentifier))) {\n        str += c;\n      }\n      var i, j;\n      for (i=0, j=keyFuncs.length; i<j; i++) {\n        if (keyFuncs[i] == str) {\n          return ret(\"keyword\", \"keyword\");\n        }\n      }\n      if (/\\s/.test(ch)) {\n    \treturn null;\n      }\n      return ret(\"tag\", \"tag\");\n    }\n  }\n\n  function inAttribute(quote) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.next() == quote) {\n          state.tokenize = inSmarty;\n          break;\n        }\n      }\n      return \"string\";\n    };\n  }\n\n  function inBlock(style, terminator) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.match(terminator)) {\n          state.tokenize = tokenizer;\n          break;\n        }\n        stream.next();\n      }\n      return style;\n    };\n  }\n\n  return {\n    startState: function() {\n      return { tokenize: tokenizer, mode: \"smarty\", last: null };\n    },\n    token: function(stream, state) {\n      var style = state.tokenize(stream, state);\n      state.last = last;\n      return style;\n    },\n    electricChars: \"\"\n  }\n});\n\nCodeMirror.defineMIME(\"text/x-smarty\", \"smarty\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/sparql/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: SPARQL mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"sparql.js\"></script>\n    <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: SPARQL mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\nPREFIX a: &lt;http://www.w3.org/2000/10/annotation-ns#>\nPREFIX dc: &lt;http://purl.org/dc/elements/1.1/>\nPREFIX foaf: &lt;http://xmlns.com/foaf/0.1/>\n\n# Comment!\n\nSELECT ?given ?family\nWHERE {\n  ?annot a:annotates &lt;http://www.w3.org/TR/rdf-sparql-query/> .\n  ?annot dc:creator ?c .\n  OPTIONAL {?c foaf:given ?given ;\n               foaf:family ?family } .\n  FILTER isBlank(?c)\n}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: \"application/x-sparql-query\",\n        tabMode: \"indent\",\n        matchBrackets: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>application/x-sparql-query</code>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/sparql/sparql.js",
    "content": "CodeMirror.defineMode(\"sparql\", function(config) {\n  var indentUnit = config.indentUnit;\n  var curPunc;\n\n  function wordRegexp(words) {\n    return new RegExp(\"^(?:\" + words.join(\"|\") + \")$\", \"i\");\n  }\n  var ops = wordRegexp([\"str\", \"lang\", \"langmatches\", \"datatype\", \"bound\", \"sameterm\", \"isiri\", \"isuri\",\n                        \"isblank\", \"isliteral\", \"union\", \"a\"]);\n  var keywords = wordRegexp([\"base\", \"prefix\", \"select\", \"distinct\", \"reduced\", \"construct\", \"describe\",\n                             \"ask\", \"from\", \"named\", \"where\", \"order\", \"limit\", \"offset\", \"filter\", \"optional\",\n                             \"graph\", \"by\", \"asc\", \"desc\"]);\n  var operatorChars = /[*+\\-<>=&|]/;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    curPunc = null;\n    if (ch == \"$\" || ch == \"?\") {\n      stream.match(/^[\\w\\d]*/);\n      return \"variable-2\";\n    }\n    else if (ch == \"<\" && !stream.match(/^[\\s\\u00a0=]/, false)) {\n      stream.match(/^[^\\s\\u00a0>]*>?/);\n      return \"atom\";\n    }\n    else if (ch == \"\\\"\" || ch == \"'\") {\n      state.tokenize = tokenLiteral(ch);\n      return state.tokenize(stream, state);\n    }\n    else if (/[{}\\(\\),\\.;\\[\\]]/.test(ch)) {\n      curPunc = ch;\n      return null;\n    }\n    else if (ch == \"#\") {\n      stream.skipToEnd();\n      return \"comment\";\n    }\n    else if (operatorChars.test(ch)) {\n      stream.eatWhile(operatorChars);\n      return null;\n    }\n    else if (ch == \":\") {\n      stream.eatWhile(/[\\w\\d\\._\\-]/);\n      return \"atom\";\n    }\n    else {\n      stream.eatWhile(/[_\\w\\d]/);\n      if (stream.eat(\":\")) {\n        stream.eatWhile(/[\\w\\d_\\-]/);\n        return \"atom\";\n      }\n      var word = stream.current(), type;\n      if (ops.test(word))\n        return null;\n      else if (keywords.test(word))\n        return \"keyword\";\n      else\n        return \"variable\";\n    }\n  }\n\n  function tokenLiteral(quote) {\n    return function(stream, state) {\n      var escaped = false, ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == quote && !escaped) {\n          state.tokenize = tokenBase;\n          break;\n        }\n        escaped = !escaped && ch == \"\\\\\";\n      }\n      return \"string\";\n    };\n  }\n\n  function pushContext(state, type, col) {\n    state.context = {prev: state.context, indent: state.indent, col: col, type: type};\n  }\n  function popContext(state) {\n    state.indent = state.context.indent;\n    state.context = state.context.prev;\n  }\n\n  return {\n    startState: function(base) {\n      return {tokenize: tokenBase,\n              context: null,\n              indent: 0,\n              col: 0};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        if (state.context && state.context.align == null) state.context.align = false;\n        state.indent = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n\n      if (style != \"comment\" && state.context && state.context.align == null && state.context.type != \"pattern\") {\n        state.context.align = true;\n      }\n\n      if (curPunc == \"(\") pushContext(state, \")\", stream.column());\n      else if (curPunc == \"[\") pushContext(state, \"]\", stream.column());\n      else if (curPunc == \"{\") pushContext(state, \"}\", stream.column());\n      else if (/[\\]\\}\\)]/.test(curPunc)) {\n        while (state.context && state.context.type == \"pattern\") popContext(state);\n        if (state.context && curPunc == state.context.type) popContext(state);\n      }\n      else if (curPunc == \".\" && state.context && state.context.type == \"pattern\") popContext(state);\n      else if (/atom|string|variable/.test(style) && state.context) {\n        if (/[\\}\\]]/.test(state.context.type))\n          pushContext(state, \"pattern\", stream.column());\n        else if (state.context.type == \"pattern\" && !state.context.align) {\n          state.context.align = true;\n          state.context.col = stream.column();\n        }\n      }\n      \n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      var firstChar = textAfter && textAfter.charAt(0);\n      var context = state.context;\n      if (/[\\]\\}]/.test(firstChar))\n        while (context && context.type == \"pattern\") context = context.prev;\n\n      var closing = context && firstChar == context.type;\n      if (!context)\n        return 0;\n      else if (context.type == \"pattern\")\n        return context.col;\n      else if (context.align)\n        return context.col + (closing ? 0 : 1);\n      else\n        return context.indent + (closing ? 0 : indentUnit);\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"application/x-sparql-query\", \"sparql\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/stex/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: sTeX mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"stex.js\"></script>\n    <style>.CodeMirror {background: #f8f8f8;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: sTeX mode</h1>\n     <form><textarea id=\"code\" name=\"code\">\n\\begin{module}[id=bbt-size]\n\\importmodule[balanced-binary-trees]{balanced-binary-trees}\n\\importmodule[\\KWARCslides{dmath/en/cardinality}]{cardinality}\n\n\\begin{frame}\n  \\frametitle{Size Lemma for Balanced Trees}\n  \\begin{itemize}\n  \\item\n    \\begin{assertion}[id=size-lemma,type=lemma] \n    Let $G=\\tup{V,E}$ be a \\termref[cd=binary-trees]{balanced binary tree} \n    of \\termref[cd=graph-depth,name=vertex-depth]{depth}$n>i$, then the set\n     $\\defeq{\\livar{V}i}{\\setst{\\inset{v}{V}}{\\gdepth{v} = i}}$ of\n    \\termref[cd=graphs-intro,name=node]{nodes} at \n    \\termref[cd=graph-depth,name=vertex-depth]{depth} $i$ has\n    \\termref[cd=cardinality,name=cardinality]{cardinality} $\\power2i$.\n   \\end{assertion}\n  \\item\n    \\begin{sproof}[id=size-lemma-pf,proofend=,for=size-lemma]{via induction over the depth $i$.}\n      \\begin{spfcases}{We have to consider two cases}\n        \\begin{spfcase}{$i=0$}\n          \\begin{spfstep}[display=flow]\n            then $\\livar{V}i=\\set{\\livar{v}r}$, where $\\livar{v}r$ is the root, so\n            $\\eq{\\card{\\livar{V}0},\\card{\\set{\\livar{v}r}},1,\\power20}$.\n          \\end{spfstep}\n        \\end{spfcase}\n        \\begin{spfcase}{$i>0$}\n          \\begin{spfstep}[display=flow]\n           then $\\livar{V}{i-1}$ contains $\\power2{i-1}$ vertexes \n           \\begin{justification}[method=byIH](IH)\\end{justification}\n          \\end{spfstep}\n          \\begin{spfstep}\n           By the \\begin{justification}[method=byDef]definition of a binary\n              tree\\end{justification}, each $\\inset{v}{\\livar{V}{i-1}}$ is a leaf or has\n            two children that are at depth $i$.\n          \\end{spfstep}\n          \\begin{spfstep}\n           As $G$ is \\termref[cd=balanced-binary-trees,name=balanced-binary-tree]{balanced} and $\\gdepth{G}=n>i$, $\\livar{V}{i-1}$ cannot contain\n            leaves.\n          \\end{spfstep}\n          \\begin{spfstep}[type=conclusion]\n           Thus $\\eq{\\card{\\livar{V}i},{\\atimes[cdot]{2,\\card{\\livar{V}{i-1}}}},{\\atimes[cdot]{2,\\power2{i-1}}},\\power2i}$.\n          \\end{spfstep}\n        \\end{spfcase}\n      \\end{spfcases}\n    \\end{sproof}\n  \\item \n    \\begin{assertion}[id=fbbt,type=corollary]\t\n      A fully balanced tree of depth $d$ has $\\power2{d+1}-1$ nodes.\n    \\end{assertion}\n  \\item\n      \\begin{sproof}[for=fbbt,id=fbbt-pf]{}\n        \\begin{spfstep}\n          Let $\\defeq{G}{\\tup{V,E}}$ be a fully balanced tree\n        \\end{spfstep}\n        \\begin{spfstep}\n          Then $\\card{V}=\\Sumfromto{i}1d{\\power2i}= \\power2{d+1}-1$.\n        \\end{spfstep}\n      \\end{sproof}\n    \\end{itemize}\n  \\end{frame}\n\\begin{note}\n  \\begin{omtext}[type=conclusion,for=binary-tree]\n    This shows that balanced binary trees grow in breadth very quickly, a consequence of\n    this is that they are very shallow (and this compute very fast), which is the essence of\n    the next result.\n  \\end{omtext}\n\\end{note}\n\\end{module}\n\n%%% Local Variables: \n%%% mode: LaTeX\n%%% TeX-master: \"all\"\n%%% End: \\end{document}\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-stex</code>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/stex/stex.js",
    "content": "/*\n * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de)\n * Licence: MIT\n */\n\nCodeMirror.defineMode(\"stex\", function(cmCfg, modeCfg) \n{    \n    function pushCommand(state, command) {\n\tstate.cmdState.push(command);\n    }\n\n    function peekCommand(state) { \n\tif (state.cmdState.length>0)\n\t    return state.cmdState[state.cmdState.length-1];\n\telse\n\t    return null;\n    }\n\n    function popCommand(state) {\n\tif (state.cmdState.length>0) {\n\t    var plug = state.cmdState.pop();\n\t    plug.closeBracket();\n\t}\t    \n    }\n\n    function applyMostPowerful(state) {\n      var context = state.cmdState;\n      for (var i = context.length - 1; i >= 0; i--) {\n\t  var plug = context[i];\n\t  if (plug.name==\"DEFAULT\")\n\t      continue;\n\t  return plug.styleIdentifier();\n      }\n      return null;\n    }\n\n    function addPluginPattern(pluginName, cmdStyle, brackets, styles) {\n\treturn function () {\n\t    this.name=pluginName;\n\t    this.bracketNo = 0;\n\t    this.style=cmdStyle;\n\t    this.styles = styles;\n\t    this.brackets = brackets;\n\n\t    this.styleIdentifier = function(content) {\n\t\tif (this.bracketNo<=this.styles.length)\n\t\t    return this.styles[this.bracketNo-1];\n\t\telse\n\t\t    return null;\n\t    };\n\t    this.openBracket = function(content) {\n\t\tthis.bracketNo++;\n\t\treturn \"bracket\";\n\t    };\n\t    this.closeBracket = function(content) {\n\t    };\n\t}\n    }\n\n    var plugins = new Array();\n   \n    plugins[\"importmodule\"] = addPluginPattern(\"importmodule\", \"tag\", \"{[\", [\"string\", \"builtin\"]);\n    plugins[\"documentclass\"] = addPluginPattern(\"documentclass\", \"tag\", \"{[\", [\"\", \"atom\"]);\n    plugins[\"usepackage\"] = addPluginPattern(\"documentclass\", \"tag\", \"[\", [\"atom\"]);\n    plugins[\"begin\"] = addPluginPattern(\"documentclass\", \"tag\", \"[\", [\"atom\"]);\n    plugins[\"end\"] = addPluginPattern(\"documentclass\", \"tag\", \"[\", [\"atom\"]);\n\n    plugins[\"DEFAULT\"] = function () {\n\tthis.name=\"DEFAULT\";\n\tthis.style=\"tag\";\n\n\tthis.styleIdentifier = function(content) {\n\t};\n\tthis.openBracket = function(content) {\n\t};\n\tthis.closeBracket = function(content) {\n\t};\n    };\n\n    function setState(state, f) {\n\tstate.f = f;\n    }\n\n    function normal(source, state) {\n\tif (source.match(/^\\\\[a-zA-Z@]+/)) {\n\t    var cmdName = source.current();\n\t    cmdName = cmdName.substr(1, cmdName.length-1);\n\t    var plug = plugins[cmdName];\n\t    if (typeof(plug) == 'undefined') {\n\t\tplug = plugins[\"DEFAULT\"];\n\t    }\n\t    plug = new plug();\n\t    pushCommand(state, plug);\n\t    setState(state, beginParams);\n\t    return plug.style;\n\t}\n\n        // escape characters \n        if (source.match(/^\\\\[$&%#{}_]/)) {\n          return \"tag\";\n        }\n\n        // white space control characters\n        if (source.match(/^\\\\[,;!\\/]/)) {\n          return \"tag\";\n        }\n\n\tvar ch = source.next();\n\tif (ch == \"%\") {\n            // special case: % at end of its own line; stay in same state\n            if (!source.eol()) {\n              setState(state, inCComment);\n            }\n\t    return \"comment\";\n\t} \n\telse if (ch=='}' || ch==']') {\n\t    plug = peekCommand(state);\n\t    if (plug) {\n\t\tplug.closeBracket(ch);\n\t\tsetState(state, beginParams);\n\t    } else\n\t\treturn \"error\";\n\t    return \"bracket\";\n\t} else if (ch=='{' || ch=='[') {\n\t    plug = plugins[\"DEFAULT\"];\t    \n\t    plug = new plug();\n\t    pushCommand(state, plug);\n\t    return \"bracket\";\t    \n\t}\n\telse if (/\\d/.test(ch)) {\n\t    source.eatWhile(/[\\w.%]/);\n\t    return \"atom\";\n\t}\n\telse {\n\t    source.eatWhile(/[\\w-_]/);\n\t    return applyMostPowerful(state);\n\t}\n    }\n\n    function inCComment(source, state) {\n\tsource.skipToEnd();\n\tsetState(state, normal);\n\treturn \"comment\";\n    }\n\n    function beginParams(source, state) {\n\tvar ch = source.peek();\n\tif (ch == '{' || ch == '[') {\n\t   var lastPlug = peekCommand(state);\n\t   var style = lastPlug.openBracket(ch);\n\t   source.eat(ch);\n\t   setState(state, normal);\n\t   return \"bracket\";\n\t}\n\tif (/[ \\t\\r]/.test(ch)) {\n\t    source.eat(ch);\n\t    return null;\n\t}\n\tsetState(state, normal);\n\tlastPlug = peekCommand(state);\n\tif (lastPlug) {\n\t    popCommand(state);\n\t}\n        return normal(source, state);\n    }\n\n    return {\n     startState: function() { return { f:normal, cmdState:[] }; },\n\t copyState: function(s) { return { f: s.f, cmdState: s.cmdState.slice(0, s.cmdState.length) }; },\n\t \n\t token: function(stream, state) {\n\t var t = state.f(stream, state);\n\t var w = stream.current();\n\t return t;\n     }\n };\n});\n\n\nCodeMirror.defineMIME(\"text/x-stex\", \"stex\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/stex/test.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: sTeX mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"stex.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../test/mode_test.css\">\n    <script src=\"../../test/mode_test.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>Tests for the sTeX Mode</h1>\n    <h2>Basics</h2>\n    <script language=\"javascript\">\n      MT = ModeTest;\n\n      MT.test('foo',\n        null, 'foo');\n\n      MT.test('foo bar',\n        null, 'foo',\n        null, ' bar');\n    </script>\n\n    <h2>Tags</h2>\n    <script language=\"javascript\">\n      MT.test('\\\\begin{document}\\n\\\\end{document}',\n        'tag',     '\\\\begin',\n        'bracket', '{',\n        'atom',    'document',\n        'bracket', '}',\n        'tag',     '\\\\end',\n        'bracket', '{',\n        'atom',    'document',\n        'bracket', '}');\n\n      MT.test('\\\\begin{equation}\\n  E=mc^2\\n\\\\end{equation}',\n        'tag',     '\\\\begin',\n        'bracket', '{',\n        'atom',    'equation',\n        'bracket', '}',\n        null,      ' ',\n        null,      ' ',\n        null,      'E',\n        null,      '=mc',\n        null,      '^2',\n        'tag',     '\\\\end',\n        'bracket', '{',\n        'atom',    'equation',\n        'bracket', '}');\n\n      MT.test('\\\\begin{module}[]',\n        'tag',     '\\\\begin',\n        'bracket', '{',\n        'atom',    'module',\n        'bracket', '}',\n        'bracket', '[',\n        'bracket', ']');\n\n      MT.test('\\\\begin{module}[id=bbt-size]',\n        'tag',     '\\\\begin',\n        'bracket', '{',\n        'atom',    'module',\n        'bracket', '}',\n        'bracket', '[',\n        null,      'id',\n        null,      '=bbt-size',\n        'bracket', ']');\n\n      MT.test('\\\\importmodule[b-b-t]{b-b-t}',\n        'tag',     '\\\\importmodule',\n        'bracket', '[',\n        'string',   'b-b-t',\n        'bracket', ']',\n        'bracket', '{',\n        'builtin', 'b-b-t',\n        'bracket', '}');\n\n      MT.test('\\\\importmodule[\\\\KWARCslides{dmath/en/cardinality}]{card}',\n        'tag',     '\\\\importmodule',\n        'bracket', '[',\n        'tag',     '\\\\KWARCslides',\n        'bracket', '{',\n        'string',   'dmath',\n        'string',   '/en',\n        'string',   '/cardinality',\n        'bracket', '}',\n        'bracket', ']',\n        'bracket', '{',\n        'builtin', 'card',\n        'bracket', '}');\n\n      MT.test('\\\\PSforPDF[1]{#1}', // could treat #1 specially\n        'tag',     '\\\\PSforPDF',\n        'bracket', '[',\n        'atom',    '1',\n        'bracket', ']',\n        'bracket', '{',\n        null,      '#1',\n        'bracket', '}');\n    </script>\n\n    <h2>Comments</h2>\n    <script language=\"javascript\">\n      MT.test('% foo',\n        'comment', '%',\n        'comment', ' foo');\n\n      MT.test('\\\\item% bar',\n        'tag',     '\\\\item',\n        'comment', '%',\n        'comment', ' bar');\n\n      MT.test(' % \\\\item',\n        null,      ' ',\n        'comment', '%',\n        'comment', ' \\\\item');\n\n      MT.test('%\\nfoo',\n        'comment', '%',\n        null, 'foo');\n    </script>\n\n    <h2>Errors</h2>\n    <script language=\"javascript\">\n      MT.test('\\\\begin}{',\n        'tag',     '\\\\begin',\n        'error',   '}',\n        'bracket', '{');\n\n      MT.test('\\\\item]{',\n        'tag',     '\\\\item',\n        'error',   ']',\n        'bracket', '{');\n\n      MT.test('% }',\n        'comment', '%',\n        'comment', ' }');\n    </script>\n\n    <h2>Character Escapes</h2>\n    <script language=\"javascript\">\n      MT.test('the \\\\# key',\n        null,  'the',\n        null,  ' ',\n        'tag', '\\\\#',\n        null,  ' key');\n\n      MT.test('a \\\\$5 stetson',\n        null, 'a',\n        null, ' ',\n        'tag', '\\\\$',\n        'atom', 5,\n        null, ' stetson');\n\n      MT.test('100\\\\% beef',\n        'atom', '100',\n        'tag', '\\\\%',\n        null, ' beef');\n\n      MT.test('L \\\\& N',\n        null, 'L',\n        null, ' ',\n        'tag', '\\\\&',\n        null, ' N');\n\n      MT.test('foo\\\\_bar',\n        null, 'foo',\n        'tag', '\\\\_',\n        null, 'bar');\n\n      MT.test('\\\\emph{\\\\{}',\n        'tag',    '\\\\emph',\n        'bracket','{',\n        'tag',    '\\\\{',\n        'bracket','}');\n\n      MT.test('\\\\emph{\\\\}}',\n        'tag',    '\\\\emph',\n        'bracket','{',\n        'tag',    '\\\\}',\n        'bracket','}');\n\n      MT.test('section \\\\S1',\n        null,  'section',\n        null,  ' ',\n        'tag', '\\\\S',\n        'atom',  '1');\n\n      MT.test('para \\\\P2',\n        null,  'para',\n        null,  ' ',\n        'tag', '\\\\P',\n        'atom',  '2');\n\n    </script>\n\n    <h2>Spacing control</h2>\n\n    <script language=\"javascript\">\n      MT.test('x\\\\,y', // thinspace\n        null,  'x',\n        'tag', '\\\\,',\n        null,  'y');\n\n      MT.test('x\\\\;y', // thickspace\n        null,  'x',\n        'tag', '\\\\;',\n        null,  'y');\n\n      MT.test('x\\\\!y', // negative thinspace\n        null,  'x',\n        'tag', '\\\\!',\n        null,  'y');\n\n      MT.test('J.\\\\ L.\\\\ is', // period not ending a sentence\n        null, 'J',\n        null, '.',\n        null, '\\\\',\n        null, ' L',\n        null, '.',\n        null, '\\\\',\n        null, ' is'); // maybe could be better\n\n      MT.test('X\\\\@. The', // period ending a sentence\n        null,  'X',\n        'tag', '\\\\@',\n        null,  '.',\n        null,  ' The');\n\n      MT.test('{\\\\em If\\\\/} I', // italic correction\n        'bracket', '{',\n        'tag',     '\\\\em',\n        null,      ' ',\n        null,      'If',\n        'tag',     '\\\\/',\n        'bracket', '}',\n        null,      ' ',\n        null,      'I');\n\n    </script>\n\n    <h2>Summary</h2>\n    <script language=\"javascript\">\n      MT.printSummary();\n    </script>\n\n  </body>\n</html>\n\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/tiddlywiki/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: TiddlyWiki mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"tiddlywiki.js\"></script>\n    <link rel=\"stylesheet\" href=\"tiddlywiki.css\">\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: TiddlyWiki mode</h1>\n\n<div><textarea id=\"code\" name=\"code\">\n!TiddlyWiki Formatting\n* Rendered versions can be found at: http://www.tiddlywiki.com/#Reference\n\n|!Option            | !Syntax            |\n|bold font          | ''bold''           |\n|italic type        | //italic//         |\n|underlined text    | __underlined__     |\n|strikethrough text | --strikethrough--  |\n|superscript text   | super^^script^^    |\n|subscript text     | sub~~script~~      |\n|highlighted text   | @@highlighted@@    |\n|preformatted text  | {{{preformatted}}} |\n\n!Block Elements\n<<<\n!Heading 1\n\n!!Heading 2\n\n!!!Heading 3\n\n!!!!Heading 4\n\n!!!!!Heading 5\n<<<\n\n!!Lists\n<<<\n* unordered list, level 1\n** unordered list, level 2\n*** unordered list, level 3\n\n# ordered list, level 1\n## ordered list, level 2\n### unordered list, level 3\n\n; definition list, term\n: definition list, description\n<<<\n\n!!Blockquotes\n<<<\n> blockquote, level 1\n>> blockquote, level 2\n>>> blockquote, level 3\n\n> blockquote\n<<<\n\n!!Preformatted Text\n<<<\n{{{\npreformatted (e.g. code)\n}}}\n<<<\n\n!!Code Sections\n<<<\n{{{\nText style code\n}}}\n\n//{{{\nJS styled code. TiddlyWiki mixed mode should support highlighter switching in the future.\n//}}}\n\n<!--{{{-->\nXML styled code. TiddlyWiki mixed mode should support highlighter switching in the future.\n<!--}}}-->\n<<<\n\n!!Tables\n<<<\n|CssClass|k\n|!heading column 1|!heading column 2|\n|row 1, column 1|row 1, column 2|\n|row 2, column 1|row 2, column 2|\n|>|COLSPAN|\n|ROWSPAN| ... |\n|~| ... |\n|CssProperty:value;...| ... |\n|caption|c\n\n''Annotation:''\n* The {{{>}}} marker creates a \"colspan\", causing the current cell to merge with the one to the right.\n* The {{{~}}} marker creates a \"rowspan\", causing the current cell to merge with the one above.\n<<<\n!!Images /% TODO %/\ncf. [[TiddlyWiki.com|http://www.tiddlywiki.com/#EmbeddedImages]]\n\n!Hyperlinks\n* [[WikiWords|WikiWord]] are automatically transformed to hyperlinks to the respective tiddler\n** the automatic transformation can be suppressed by preceding the respective WikiWord with a tilde ({{{~}}}): {{{~WikiWord}}}\n* [[PrettyLinks]] are enclosed in square brackets and contain the desired tiddler name: {{{[[tiddler name]]}}}\n** optionally, a custom title or description can be added, separated by a pipe character ({{{|}}}): {{{[[title|target]]}}}<br>'''N.B.:''' In this case, the target can also be any website (i.e. URL).\n\n!Custom Styling\n* {{{@@CssProperty:value;CssProperty:value;...@@}}}<br>''N.B.:'' CSS color definitions should use lowercase letters to prevent the inadvertent creation of WikiWords.\n* <html><code>{{customCssClass{...}}}</code></html>\n* raw HTML can be inserted by enclosing the respective code in HTML tags: {{{<html> ... </html>}}}\n\n!Special Markers\n* {{{<br>}}} forces a manual line break\n* {{{----}}} creates a horizontal ruler\n* [[HTML entities|http://www.tiddlywiki.com/#HtmlEntities]]\n* [[HTML entities local|HtmlEntities]]\n* {{{<<macroName>>}}} calls the respective [[macro|Macros]]\n* To hide text within a tiddler so that it is not displayed, it can be wrapped in {{{/%}}} and {{{%/}}}.<br/>This can be a useful trick for hiding drafts or annotating complex markup.\n* To prevent wiki markup from taking effect for a particular section, that section can be enclosed in three double quotes: e.g. {{{\"\"\"WikiWord\"\"\"}}}.\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: 'tiddlywiki',      \n        lineNumbers: true,\n        enterMode: 'keep',\n        matchBrackets: true\n      });\n    </script>\n\n    <p>TiddlyWiki mode supports a single configuration.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-tiddlywiki</code>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/tiddlywiki/tiddlywiki.css",
    "content": "span.cm-underlined {\n  text-decoration: underline;\n}\nspan.cm-strikethrough {\n  text-decoration: line-through;\n}\nspan.cm-brace {\n  color: #170;\n  font-weight: bold;\n}\nspan.cm-table {\n  color: blue;\n  font-weight: bold;\n}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/tiddlywiki/tiddlywiki.js",
    "content": "/***\n|''Name''|tiddlywiki.js|\n|''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror|\n|''Author''|PMario|\n|''Version''|0.1.7|\n|''Status''|''stable''|\n|''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]|\n|''Documentation''|http://codemirror.tiddlyspace.com/|\n|''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|\n|''CoreVersion''|2.5.0|\n|''Requires''|codemirror.js|\n|''Keywords''|syntax highlighting color code mirror codemirror|\n! Info\nCoreVersion parameter is needed for TiddlyWiki only!\n***/\n//{{{\nCodeMirror.defineMode(\"tiddlywiki\", function (config, parserConfig) {\n\tvar indentUnit = config.indentUnit;\n\n\t// Tokenizer\n\tvar textwords = function () {\n\t\tfunction kw(type) {\n\t\t\treturn {\n\t\t\t\ttype: type,\n\t\t\t\tstyle: \"text\"\n\t\t\t};\n\t\t}\n\t\treturn {};\n\t}();\n\n\tvar keywords = function () {\n\t\tfunction kw(type) {\n\t\t\treturn { type: type, style: \"macro\"};\n\t\t}\n\t\treturn {\n\t\t\t\"allTags\": kw('allTags'), \"closeAll\": kw('closeAll'), \"list\": kw('list'),\n\t\t\t\"newJournal\": kw('newJournal'), \"newTiddler\": kw('newTiddler'),\n\t\t\t\"permaview\": kw('permaview'), \"saveChanges\": kw('saveChanges'),\n\t\t\t\"search\": kw('search'), \"slider\": kw('slider'),\t\"tabs\": kw('tabs'),\n\t\t\t\"tag\": kw('tag'), \"tagging\": kw('tagging'),\t\"tags\": kw('tags'),\n\t\t\t\"tiddler\": kw('tiddler'), \"timeline\": kw('timeline'),\n\t\t\t\"today\": kw('today'), \"version\": kw('version'),\t\"option\": kw('option'),\n\n\t\t\t\"with\": kw('with'),\n\t\t\t\"filter\": kw('filter')\n\t\t};\n\t}();\n\n\tvar isSpaceName = /[\\w_\\-]/i,\n\t\treHR = /^\\-\\-\\-\\-+$/,\t\t\t\t\t// <hr>\n\t\treWikiCommentStart = /^\\/\\*\\*\\*$/,\t\t// /***\n\t\treWikiCommentStop = /^\\*\\*\\*\\/$/,\t\t// ***/\n\t\treBlockQuote = /^<<<$/,\n\n\t\treJsCodeStart = /^\\/\\/\\{\\{\\{$/,\t\t\t// //{{{ js block start\n\t\treJsCodeStop = /^\\/\\/\\}\\}\\}$/,\t\t\t// //}}} js stop\n\t\treXmlCodeStart = /^<!--\\{\\{\\{-->$/,\t\t// xml block start\n\t\treXmlCodeStop = /^<!--\\}\\}\\}-->$/,\t\t// xml stop\n\n\t\treCodeBlockStart = /^\\{\\{\\{$/,\t\t\t// {{{ TW text div block start\n\t\treCodeBlockStop = /^\\}\\}\\}$/,\t\t\t// }}} TW text stop\n\n\t\treCodeStart = /\\{\\{\\{/,\t\t\t\t\t// {{{ code span start\n\t\treUntilCodeStop = /.*?\\}\\}\\}/;\n\n\tfunction chain(stream, state, f) {\n\t\tstate.tokenize = f;\n\t\treturn f(stream, state);\n\t}\n\n\t// used for strings\n\tfunction nextUntilUnescaped(stream, end) {\n\t\tvar escaped = false,\n\t\t\tnext;\n\t\twhile ((next = stream.next()) != null) {\n\t\t\tif (next == end && !escaped) return false;\n\t\t\tescaped = !escaped && next == \"\\\\\";\n\t\t}\n\t\treturn escaped;\n\t}\n\n\t// Used as scratch variables to communicate multiple values without\n\t// consing up tons of objects.\n\tvar type, content;\n\n\tfunction ret(tp, style, cont) {\n\t\ttype = tp;\n\t\tcontent = cont;\n\t\treturn style;\n\t}\n\n\tfunction jsTokenBase(stream, state) {\n\t\tvar sol = stream.sol(), \n\t\t\tch, tch;\n\t\t\t\n\t\tstate.block = false;\t// indicates the start of a code block.\n\n\t\tch = stream.peek(); \t// don't eat, to make matching simpler\n\t\t\n\t\t// check start of  blocks\n\t\tif (sol && /[<\\/\\*{}\\-]/.test(ch)) {\n\t\t\tif (stream.match(reCodeBlockStart)) {\n\t\t\t\tstate.block = true;\n\t\t\t\treturn chain(stream, state, twTokenCode);\n\t\t\t}\n\t\t\tif (stream.match(reBlockQuote)) {\n\t\t\t\treturn ret('quote', 'quote');\n\t\t\t}\n\t\t\tif (stream.match(reWikiCommentStart) || stream.match(reWikiCommentStop)) {\n\t\t\t\treturn ret('code', 'comment');\n\t\t\t}\n\t\t\tif (stream.match(reJsCodeStart) || stream.match(reJsCodeStop) || stream.match(reXmlCodeStart) || stream.match(reXmlCodeStop)) {\n\t\t\t\treturn ret('code', 'comment');\n\t\t\t}\n\t\t\tif (stream.match(reHR)) {\n\t\t\t\treturn ret('hr', 'hr');\n\t\t\t}\n\t\t} // sol\n\t\tch = stream.next();\n\n\t\tif (sol && /[\\/\\*!#;:>|]/.test(ch)) {\n\t\t\tif (ch == \"!\") { // tw header\n\t\t\t\tstream.skipToEnd();\n\t\t\t\treturn ret(\"header\", \"header\");\n\t\t\t}\n\t\t\tif (ch == \"*\") { // tw list\n\t\t\t\tstream.eatWhile('*');\n\t\t\t\treturn ret(\"list\", \"comment\");\n\t\t\t}\n\t\t\tif (ch == \"#\") { // tw numbered list\n\t\t\t\tstream.eatWhile('#');\n\t\t\t\treturn ret(\"list\", \"comment\");\n\t\t\t}\n\t\t\tif (ch == \";\") { // definition list, term\n\t\t\t\tstream.eatWhile(';');\n\t\t\t\treturn ret(\"list\", \"comment\");\n\t\t\t}\n\t\t\tif (ch == \":\") { // definition list, description\n\t\t\t\tstream.eatWhile(':');\n\t\t\t\treturn ret(\"list\", \"comment\");\n\t\t\t}\n\t\t\tif (ch == \">\") { // single line quote\n\t\t\t\tstream.eatWhile(\">\");\n\t\t\t\treturn ret(\"quote\", \"quote\");\n\t\t\t}\n\t\t\tif (ch == '|') {\n\t\t\t\treturn ret('table', 'header');\n\t\t\t}\n\t\t}\n\n\t\tif (ch == '{' && stream.match(/\\{\\{/)) {\n\t\t\treturn chain(stream, state, twTokenCode);\n\t\t}\n\n\t\t// rudimentary html:// file:// link matching. TW knows much more ...\n\t\tif (/[hf]/i.test(ch)) {\n\t\t\tif (/[ti]/i.test(stream.peek()) && stream.match(/\\b(ttps?|tp|ile):\\/\\/[\\-A-Z0-9+&@#\\/%?=~_|$!:,.;]*[A-Z0-9+&@#\\/%=~_|$]/i)) {\n\t\t\t\treturn ret(\"link\", \"link\");\n\t\t\t}\n\t\t}\n\t\t// just a little string indicator, don't want to have the whole string covered\n\t\tif (ch == '\"') {\n\t\t\treturn ret('string', 'string');\n\t\t}\n\t\tif (ch == '~') {\t// _no_ CamelCase indicator should be bold\n\t\t\treturn ret('text', 'brace');\n\t\t}\n\t\tif (/[\\[\\]]/.test(ch)) { // check for [[..]]\n\t\t\tif (stream.peek() == ch) {\n\t\t\t\tstream.next();\n\t\t\t\treturn ret('brace', 'brace');\n\t\t\t}\n\t\t}\n\t\tif (ch == \"@\") {\t// check for space link. TODO fix @@...@@ highlighting\n\t\t\tstream.eatWhile(isSpaceName);\n\t\t\treturn ret(\"link\", \"link\");\n\t\t}\n\t\tif (/\\d/.test(ch)) {\t// numbers\n\t\t\tstream.eatWhile(/\\d/);\n\t\t\treturn ret(\"number\", \"number\");\n\t\t}\n\t\tif (ch == \"/\") { // tw invisible comment\n\t\t\tif (stream.eat(\"%\")) {\n\t\t\t\treturn chain(stream, state, twTokenComment);\n\t\t\t}\n\t\t\telse if (stream.eat(\"/\")) { // \n\t\t\t\treturn chain(stream, state, twTokenEm);\n\t\t\t}\n\t\t}\n\t\tif (ch == \"_\") { // tw underline\n\t\t\tif (stream.eat(\"_\")) {\n\t\t\t\treturn chain(stream, state, twTokenUnderline);\n\t\t\t}\n\t\t}\n\t\t// strikethrough and mdash handling\n\t\tif (ch == \"-\") {\n\t\t\tif (stream.eat(\"-\")) {\n\t\t\t\t// if strikethrough looks ugly, change CSS.\n\t\t\t\tif (stream.peek() != ' ')\n\t\t\t\t\treturn chain(stream, state, twTokenStrike);\n\t\t\t\t// mdash\n\t\t\t\tif (stream.peek() == ' ')\n\t\t\t\t\treturn ret('text', 'brace');\n\t\t\t}\n\t\t}\n\t\tif (ch == \"'\") { // tw bold\n\t\t\tif (stream.eat(\"'\")) {\n\t\t\t\treturn chain(stream, state, twTokenStrong);\n\t\t\t}\n\t\t}\n\t\tif (ch == \"<\") { // tw macro\n\t\t\tif (stream.eat(\"<\")) {\n\t\t\t\treturn chain(stream, state, twTokenMacro);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\treturn ret(ch);\n\t\t}\n\n\t\t// core macro handling\n\t\tstream.eatWhile(/[\\w\\$_]/);\n\t\tvar word = stream.current(),\n\t\t\tknown = textwords.propertyIsEnumerable(word) && textwords[word];\n\n\t\treturn known ? ret(known.type, known.style, word) : ret(\"text\", null, word);\n\n\t} // jsTokenBase()\n\n\tfunction twTokenString(quote) {\n\t\treturn function (stream, state) {\n\t\t\tif (!nextUntilUnescaped(stream, quote)) state.tokenize = jsTokenBase;\n\t\t\treturn ret(\"string\", \"string\");\n\t\t};\n\t}\n\n\t// tw invisible comment\n\tfunction twTokenComment(stream, state) {\n\t\tvar maybeEnd = false,\n\t\t\tch;\n\t\twhile (ch = stream.next()) {\n\t\t\tif (ch == \"/\" && maybeEnd) {\n\t\t\t\tstate.tokenize = jsTokenBase;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmaybeEnd = (ch == \"%\");\n\t\t}\n\t\treturn ret(\"comment\", \"comment\");\n\t}\n\n\t// tw strong / bold\n\tfunction twTokenStrong(stream, state) {\n\t\tvar maybeEnd = false,\n\t\t\tch;\n\t\twhile (ch = stream.next()) {\n\t\t\tif (ch == \"'\" && maybeEnd) {\n\t\t\t\tstate.tokenize = jsTokenBase;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmaybeEnd = (ch == \"'\");\n\t\t}\n\t\treturn ret(\"text\", \"strong\");\n\t}\n\n\t// tw code\n\tfunction twTokenCode(stream, state) {\n\t\tvar ch, sb = state.block;\n\t\t\n\t\tif (sb && stream.current()) {\n\t\t\treturn ret(\"code\", \"comment\");\n\t\t}\n\n\t\tif (!sb && stream.match(reUntilCodeStop)) {\n\t\t\tstate.tokenize = jsTokenBase;\n\t\t\treturn ret(\"code\", \"comment\");\n\t\t}\n\n\t\tif (sb && stream.sol() && stream.match(reCodeBlockStop)) {\n\t\t\tstate.tokenize = jsTokenBase;\n\t\t\treturn ret(\"code\", \"comment\");\n\t\t}\n\n\t\tch = stream.next();\n\t\treturn (sb) ? ret(\"code\", \"comment\") : ret(\"code\", \"comment\");\n\t}\n\n\t// tw em / italic\n\tfunction twTokenEm(stream, state) {\n\t\tvar maybeEnd = false,\n\t\t\tch;\n\t\twhile (ch = stream.next()) {\n\t\t\tif (ch == \"/\" && maybeEnd) {\n\t\t\t\tstate.tokenize = jsTokenBase;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmaybeEnd = (ch == \"/\");\n\t\t}\n\t\treturn ret(\"text\", \"em\");\n\t}\n\n\t// tw underlined text\n\tfunction twTokenUnderline(stream, state) {\n\t\tvar maybeEnd = false,\n\t\t\tch;\n\t\twhile (ch = stream.next()) {\n\t\t\tif (ch == \"_\" && maybeEnd) {\n\t\t\t\tstate.tokenize = jsTokenBase;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmaybeEnd = (ch == \"_\");\n\t\t}\n\t\treturn ret(\"text\", \"underlined\");\n\t}\n\n\t// tw strike through text looks ugly\n\t// change CSS if needed\n\tfunction twTokenStrike(stream, state) {\n\t\tvar maybeEnd = false,\n\t\t\tch, nr;\n\t\t\t\n\t\twhile (ch = stream.next()) {\n\t\t\tif (ch == \"-\" && maybeEnd) {\n\t\t\t\tstate.tokenize = jsTokenBase;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmaybeEnd = (ch == \"-\");\n\t\t}\n\t\treturn ret(\"text\", \"strikethrough\");\n\t}\n\n\t// macro\n\tfunction twTokenMacro(stream, state) {\n\t\tvar ch, tmp, word, known;\n\n\t\tif (stream.current() == '<<') {\n\t\t\treturn ret('brace', 'macro');\n\t\t}\n\n\t\tch = stream.next();\n\t\tif (!ch) {\n\t\t\tstate.tokenize = jsTokenBase;\n\t\t\treturn ret(ch);\n\t\t}\n\t\tif (ch == \">\") {\n\t\t\tif (stream.peek() == '>') {\n\t\t\t\tstream.next();\n\t\t\t\tstate.tokenize = jsTokenBase;\n\t\t\t\treturn ret(\"brace\", \"macro\");\n\t\t\t}\n\t\t}\n\n\t\tstream.eatWhile(/[\\w\\$_]/);\n\t\tword = stream.current();\n\t\tknown = keywords.propertyIsEnumerable(word) && keywords[word];\n\n\t\tif (known) {\n\t\t\treturn ret(known.type, known.style, word);\n\t\t}\n\t\telse {\n\t\t\treturn ret(\"macro\", null, word);\n\t\t}\n\t}\n\n\t// Interface\n\treturn {\n\t\tstartState: function (basecolumn) {\n\t\t\treturn {\n\t\t\t\ttokenize: jsTokenBase,\n\t\t\t\tindented: 0,\n\t\t\t\tlevel: 0\n\t\t\t};\n\t\t},\n\n\t\ttoken: function (stream, state) {\n\t\t\tif (stream.eatSpace()) return null;\n\t\t\tvar style = state.tokenize(stream, state);\n\t\t\treturn style;\n\t\t},\n\n\t\telectricChars: \"\"\n\t};\n});\n\nCodeMirror.defineMIME(\"text/x-tiddlywiki\", \"tiddlywiki\");\n//}}}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/tiki/index.html",
    "content": "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n  <head>\n    <title>CodeMirror: Tiki wiki mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"tiki.js\"></script>\n    <link rel=\"stylesheet\" href=\"tiki.css\">\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n  </head>\n  <body style=\"padding: 20px;\">\n    <h1>CodeMirror: Tiki wiki mode</h1>\n\n<div><textarea id=\"code\" name=\"code\">\nHeadings\n!Header 1\n!!Header 2\n!!!Header 3\n!!!!Header 4\n!!!!!Header 5\n!!!!!!Header 6\n\nStyling\n-=titlebar=-\n^^ Box on multi\nlines\nof content^^\n__bold__\n''italic''\n===underline===\n::center::\n--Line Through--\n\nOperators\n~np~No parse~/np~\n\nLink\n[link|desc|nocache]\n\nWiki\n((Wiki))\n((Wiki|desc))\n((Wiki|desc|timeout))\n\nTable\n||row1 col1|row1 col2|row1 col3\nrow2 col1|row2 col2|row2 col3\nrow3 col1|row3 col2|row3 col3||\n\nLists:\n*bla\n**bla-1\n++continue-bla-1\n***bla-2\n++continue-bla-1\n*bla\n+continue-bla\n#bla\n** tra-la-la\n+continue-bla\n#bla\n\nPlugin (standard):\n{PLUGIN(attr=\"my attr\")}\nPlugin Body\n{PLUGIN}\n\nPlugin (inline):\n{plugin attr=\"my attr\"}\n</textarea></div>\n\n<script type=\"text/javascript\">\n\tvar editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: 'tiki',      \n        lineNumbers: true,\n        enterMode: 'keep',\n        matchBrackets: true\n    });\n</script>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/tiki/tiki.css",
    "content": ".cm-tw-syntaxerror {\n\tcolor: #FFFFFF;\n\tbackground-color: #990000;\n}\n\n.cm-tw-deleted {\n\ttext-decoration: line-through;\n}\n\n.cm-tw-header5 {\n\tfont-weight: bold;\n}\n.cm-tw-listitem:first-child { /*Added first child to fix duplicate padding when highlighting*/\n\tpadding-left: 10px;\n}\n\n.cm-tw-box {\n\tborder-top-width: 0px ! important;\n\tborder-style: solid;\n\tborder-width: 1px;\n\tborder-color: inherit;\n}\n\n.cm-tw-underline {\n\ttext-decoration: underline;\n}"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/tiki/tiki.js",
    "content": "CodeMirror.defineMode('tiki', function(config, parserConfig) {\n\tfunction inBlock(style, terminator, returnTokenizer) {\n\t\treturn function(stream, state) {\n\t\t\twhile (!stream.eol()) {\n\t\t\t\tif (stream.match(terminator)) {\n\t\t\t\t\tstate.tokenize = inText;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tstream.next();\n\t\t\t}\n\t\t\t\n\t\t\tif (returnTokenizer) state.tokenize = returnTokenizer;\n\t\t\t\n\t\t\treturn style;\n\t\t};\n\t}\n\t\n\tfunction inLine(style, terminator) {\n\t\treturn function(stream, state) {\n\t\t\twhile(!stream.eol()) {\n\t\t\t\tstream.next()\n\t\t\t}\n\t\t\tstate.tokenize = inText;\n\t\t\treturn style;\n\t\t};\n\t}\n\t\n\tfunction inText(stream, state) {\n\t\tfunction chain(parser) {\n\t\t\tstate.tokenize = parser;\n\t\t\treturn parser(stream, state);\n\t\t}\n\t\t\n\t\tvar sol = stream.sol();\n\t\tvar ch = stream.next();\n\t\t\n\t\t//non start of line\n\t\tswitch (ch) { //switch is generally much faster than if, so it is used here\n\t\t\tcase \"{\": //plugin\n\t\t\t\ttype = stream.eat(\"/\") ? \"closeTag\" : \"openTag\";\n\t\t\t\tstream.eatSpace();\n\t\t\t\ttagName = \"\";\n\t\t\t\tvar c;\n\t\t\t\twhile ((c = stream.eat(/[^\\s\\u00a0=\\\"\\'\\/?(}]/))) tagName += c;\n\t\t\t\tstate.tokenize = inPlugin;\n\t\t\t\treturn \"tag\";\n\t\t\t\tbreak;\n\t\t\tcase \"_\": //bold\n\t\t\t\tif (stream.eat(\"_\")) {\n\t\t\t\t\treturn chain(inBlock(\"strong\", \"__\", inText));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"'\": //italics\n\t\t\t\tif (stream.eat(\"'\")) {\n\t\t\t\t\t// Italic text\n\t\t\t\t\treturn chain(inBlock(\"em\", \"''\", inText));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"(\":// Wiki Link\n\t\t\t\tif (stream.eat(\"(\")) {\n\t\t\t\t\treturn chain(inBlock(\"variable-2\", \"))\", inText));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"[\":// Weblink\n\t\t\t\treturn chain(inBlock(\"variable-3\", \"]\", inText));\n\t\t\t\tbreak;\n\t\t\tcase \"|\": //table\n\t\t\t\tif (stream.eat(\"|\")) {\n\t\t\t\t\treturn chain(inBlock(\"comment\", \"||\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"-\": \n\t\t\t\tif (stream.eat(\"=\")) {//titleBar\n\t\t\t\t\treturn chain(inBlock(\"header string\", \"=-\", inText));\n\t\t\t\t} else if (stream.eat(\"-\")) {//deleted\n\t\t\t\t\treturn chain(inBlock(\"error tw-deleted\", \"--\", inText));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"=\": //underline\n\t\t\t\tif (stream.match(\"==\")) {\n\t\t\t\t\treturn chain(inBlock(\"tw-underline\", \"===\", inText));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \":\":\n\t\t\t\tif (stream.eat(\":\")) {\n\t\t\t\t\treturn chain(inBlock(\"comment\", \"::\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"^\": //box\n\t\t\t\treturn chain(inBlock(\"tw-box\", \"^\"));\n\t\t\t\tbreak;\n\t\t\tcase \"~\": //np\n\t\t\t\tif (stream.match(\"np~\")) {\n\t\t\t\t\treturn chain(inBlock(\"meta\", \"~/np~\"));\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\t//start of line types\n\t\tif (sol) {\n\t\t\tswitch (ch) {\n\t\t\t\tcase \"!\": //header at start of line\n\t\t\t\t\tif (stream.match('!!!!!')) {\n\t\t\t\t\t\treturn chain(inLine(\"header string\"));\n\t\t\t\t\t} else if (stream.match('!!!!')) {\n\t\t\t\t\t\treturn chain(inLine(\"header string\"));\n\t\t\t\t\t} else if (stream.match('!!!')) {\n\t\t\t\t\t\treturn chain(inLine(\"header string\"));\n\t\t\t\t\t} else if (stream.match('!!')) {\n\t\t\t\t\t\treturn chain(inLine(\"header string\"));\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn chain(inLine(\"header string\"));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"*\": //unordered list line item, or <li /> at start of line\n\t\t\t\tcase \"#\": //ordered list line item, or <li /> at start of line\n\t\t\t\tcase \"+\": //ordered list line item, or <li /> at start of line\n\t\t\t\t\treturn chain(inLine(\"tw-listitem bracket\"));\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\t//stream.eatWhile(/[&{]/); was eating up plugins, turned off to act less like html and more like tiki\n\t\treturn null;\n\t}\n\t\n\tvar indentUnit = config.indentUnit;\n\n\t// Return variables for tokenizers\n\tvar pluginName, type;\n\tfunction inPlugin(stream, state) {\n\t\tvar ch = stream.next();\n\t\tvar peek = stream.peek();\n\t\t\n\t\tif (ch == \"}\") {\n\t\t\tstate.tokenize = inText;\n\t\t\t//type = ch == \")\" ? \"endPlugin\" : \"selfclosePlugin\"; inPlugin\n\t\t\treturn \"tag\";\n\t\t} else if (ch == \"(\" || ch == \")\") {\n\t\t\treturn \"bracket\";\n\t\t} else if (ch == \"=\") {\n\t\t\ttype = \"equals\";\n\t\t\t\n\t\t\tif (peek == \">\") {\n\t\t\t\tch = stream.next();\n\t\t\t\tpeek = stream.peek();\n\t\t\t}\n\t\t\t\n\t\t\t//here we detect values directly after equal character with no quotes\n\t\t\tif (!/[\\'\\\"]/.test(peek)) {\n\t\t\t\tstate.tokenize = inAttributeNoQuote();\n\t\t\t}\n\t\t\t//end detect values\n\t\t\t\n\t\t\treturn \"operator\";\n\t\t} else if (/[\\'\\\"]/.test(ch)) {\n\t\t\tstate.tokenize = inAttribute(ch);\n\t\t\treturn state.tokenize(stream, state);\n\t\t} else {\n\t\t\tstream.eatWhile(/[^\\s\\u00a0=\\\"\\'\\/?]/);\n\t\t\treturn \"keyword\";\n\t\t}\n\t}\n\n\tfunction inAttribute(quote) {\n\t\treturn function(stream, state) {\n\t\t\twhile (!stream.eol()) {\n\t\t\t\tif (stream.next() == quote) {\n\t\t\t\t\tstate.tokenize = inPlugin;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn \"string\";\n\t\t};\n\t}\n\t\n\tfunction inAttributeNoQuote() {\n\t\treturn function(stream, state) {\n\t\t\twhile (!stream.eol()) {\n\t\t\t\tvar ch = stream.next();\n\t\t\t\tvar peek = stream.peek();\n\t\t\t\tif (ch == \" \" || ch == \",\" || /[ )}]/.test(peek)) {\n\t\t\t\t\tstate.tokenize = inPlugin;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn \"string\";\n\t\t};\n\t}\n\n\tvar curState, setStyle;\n\tfunction pass() {\n\t\tfor (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);\n\t}\n\t\n\tfunction cont() {\n\t\tpass.apply(null, arguments);\n\t\treturn true;\n\t}\n\n\tfunction pushContext(pluginName, startOfLine) {\n\t\tvar noIndent = curState.context && curState.context.noIndent;\n\t\tcurState.context = {\n\t\t\tprev: curState.context,\n\t\t\tpluginName: pluginName,\n\t\t\tindent: curState.indented,\n\t\t\tstartOfLine: startOfLine,\n\t\t\tnoIndent: noIndent\n\t\t};\n\t}\n\t\n\tfunction popContext() {\n\t\tif (curState.context) curState.context = curState.context.prev;\n\t}\n\n\tfunction element(type) {\n\t\tif (type == \"openPlugin\") {curState.pluginName = pluginName; return cont(attributes, endplugin(curState.startOfLine));}\n\t\telse if (type == \"closePlugin\") {\n\t\t\tvar err = false;\n\t\t\tif (curState.context) {\n\t\t\t\terr = curState.context.pluginName != pluginName;\n\t\t\t\tpopContext();\n\t\t\t} else {\n\t\t\t\terr = true;\n\t\t\t}\n\t\t\tif (err) setStyle = \"error\";\n\t\t\treturn cont(endcloseplugin(err));\n\t\t}\n\t\telse if (type == \"string\") {\n\t\t\tif (!curState.context || curState.context.name != \"!cdata\") pushContext(\"!cdata\");\n\t\t\tif (curState.tokenize == inText) popContext();\n\t\t\treturn cont();\n\t\t}\n\t\telse return cont();\n\t}\n\t\n\tfunction endplugin(startOfLine) {\n\t\treturn function(type) {\n\t\t\tif (\n\t\t\ttype == \"selfclosePlugin\" ||\n\t\t\ttype == \"endPlugin\"\n\t\t)\n\t\t\t\treturn cont();\n\t\t\tif (type == \"endPlugin\") {pushContext(curState.pluginName, startOfLine); return cont();}\n\t\t\treturn cont();\n\t\t};\n\t}\n\t\n\tfunction endcloseplugin(err) {\n\t\treturn function(type) {\n\t\t\tif (err) setStyle = \"error\";\n\t\t\tif (type == \"endPlugin\") return cont();\n\t\t\treturn pass();\n\t\t}\n\t}\n\n\tfunction attributes(type) {\n\t\tif (type == \"keyword\") {setStyle = \"attribute\"; return cont(attributes);}\n\t\tif (type == \"equals\") return cont(attvalue, attributes);\n\t\treturn pass();\n\t}\n\tfunction attvalue(type) {\n\t\tif (type == \"keyword\") {setStyle = \"string\"; return cont();}\n\t\tif (type == \"string\") return cont(attvaluemaybe);\n\t\t\treturn pass();\n\t}\n\tfunction attvaluemaybe(type) {\n\t\tif (type == \"string\") return cont(attvaluemaybe);\n\t\telse return pass();\n\t}\n\treturn {\n\t\tstartState: function() {\n\t\t\treturn {tokenize: inText, cc: [], indented: 0, startOfLine: true, pluginName: null, context: null};\n\t\t},\n\t\ttoken: function(stream, state) {\n\t\t\tif (stream.sol()) {\n\t\t\t\tstate.startOfLine = true;\n\t\t\t\tstate.indented = stream.indentation();\n\t\t\t}\n\t\t\tif (stream.eatSpace()) return null;\n\n\t\t\tsetStyle = type = pluginName = null;\n\t\t\tvar style = state.tokenize(stream, state);\n\t\t\t\tif ((style || type) && style != \"comment\") {\n\t\t\t\tcurState = state;\n\t\t\t\twhile (true) {\n\t\t\t\t\tvar comb = state.cc.pop() || element;\n\t\t\t\t\tif (comb(type || style)) break;\n\t\t\t\t}\n\t\t\t}\n\t\t\tstate.startOfLine = false;\n\t\t\treturn setStyle || style;\n\t\t\t\t},\n\t\tindent: function(state, textAfter) {\n\t\t\tvar context = state.context;\n\t\t\tif (context && context.noIndent) return 0;\n\t\t\tif (context && /^{\\//.test(textAfter))\n\t\t\t\tcontext = context.prev;\n\t\t\twhile (context && !context.startOfLine)\n\t\t\t\tcontext = context.prev;\n\t\t\tif (context) return context.indent + indentUnit;\n\t\t\telse return 0;\n\t\t},\n\t\tcompareStates: function(a, b) {\n\t\t\tif (a.indented != b.indented || a.pluginName != b.pluginName) return false;\n\t\t\tfor (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) {\n\t\t\t\tif (!ca || !cb) return ca == cb;\n\t\t\t\tif (ca.pluginName != cb.pluginName) return false;\n\t\t\t}\n\t\t},\n\t\telectricChars: \"/\"\n\t};\n});\n\n//I figure, why not\nCodeMirror.defineMIME(\"text/tiki\", \"tiki\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/vbscript/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: VBScript mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"vbscript.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: VBScript mode</h1>\n\n<div><textarea id=\"code\" name=\"code\">\n' Pete Guhl\n' 03-04-2012\n'\n' Basic VBScript support for codemirror2\n\nConst ForReading = 1, ForWriting = 2, ForAppending = 8\n\nCall Sub020_PostBroadcastToUrbanAirship(strUserName, strPassword, intTransmitID, strResponse)\n\nIf Not IsNull(strResponse) AND Len(strResponse) = 0 Then\n\tboolTransmitOkYN = False\nElse\n\t' WScript.Echo \"Oh Happy Day! Oh Happy DAY!\"\n\tboolTransmitOkYN = True\nEnd If\n</textarea></div>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/vbscript</code>.</p>\n  </body>\n</html>\n\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/vbscript/vbscript.js",
    "content": "CodeMirror.defineMode(\"vbscript\", function() {\n  var regexVBScriptKeyword = /^(?:Call|Case|CDate|Clear|CInt|CLng|Const|CStr|Description|Dim|Do|Each|Else|ElseIf|End|Err|Error|Exit|False|For|Function|If|LCase|Loop|LTrim|Next|Nothing|Now|Number|On|Preserve|Quit|ReDim|Resume|RTrim|Select|Set|Sub|Then|To|Trim|True|UBound|UCase|Until|VbCr|VbCrLf|VbLf|VbTab)$/im;\n\n  return {\n    token: function(stream) {\n      if (stream.eatSpace()) return null;\n      var ch = stream.next();\n      if (ch == \"'\") {\n      \tstream.skipToEnd();\n      \treturn \"comment\";\n      }\n      if (ch == '\"') {\n      \tstream.skipTo('\"');\n      \treturn \"string\";\n      }\n\n      if (/\\w/.test(ch)) {\n        stream.eatWhile(/\\w/);\n        if (regexVBScriptKeyword.test(stream.current())) return \"keyword\";\n      }\n      return null;\n    }\n  };\n});\n\nCodeMirror.defineMIME(\"text/vbscript\", \"vbscript\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/velocity/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Velocity mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"velocity.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../theme/night.css\">\n    <style>.CodeMirror {border: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: Velocity mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n## Velocity Code Demo\n#*\n   based on PL/SQL mode by Peter Raganitsch, adapted to Velocity by Steve O'Hara ( http://www.pivotal-solutions.co.uk )\n   August 2011\n*#\n\n#*\n   This is a multiline comment.\n   This is the second line\n*#\n\n#[[ hello steve\n   This has invalid syntax that would normally need \"poor man's escaping\" like:\n\n   #define()\n\n   ${blah\n]]#\n\n#include( \"disclaimer.txt\" \"opinion.txt\" )\n#include( $foo $bar )\n\n#parse( \"lecorbusier.vm\" )\n#parse( $foo )\n\n#evaluate( 'string with VTL #if(true)will be displayed#end' )\n\n#define( $hello ) Hello $who #end #set( $who = \"World!\") $hello ## displays Hello World!\n\n#foreach( $customer in $customerList )\n\n    $foreach.count $customer.Name\n\n    #if( $foo == ${bar})\n        it's true!\n        #break\n    #{else}\n        it's not!\n        #stop\n    #end\n\n    #if ($foreach.parent.hasNext)\n        $velocityCount\n    #end\n#end\n\n$someObject.getValues(\"this is a string split\n        across lines\")\n\n#macro( tablerows $color $somelist )\n    #foreach( $something in $somelist )\n        <tr><td bgcolor=$color>$something</td></tr>\n    #end\n#end\n\n#tablerows(\"red\" [\"dadsdf\",\"dsa\"])\n\n   Variable reference: #set( $monkey = $bill )\n   String literal: #set( $monkey.Friend = 'monica' )\n   Property reference: #set( $monkey.Blame = $whitehouse.Leak )\n   Method reference: #set( $monkey.Plan = $spindoctor.weave($web) )\n   Number literal: #set( $monkey.Number = 123 )\n   Range operator: #set( $monkey.Numbers = [1..3] )\n   Object list: #set( $monkey.Say = [\"Not\", $my, \"fault\"] )\n   Object map: #set( $monkey.Map = {\"banana\" : \"good\", \"roast beef\" : \"bad\"})\n\nThe RHS can also be a simple arithmetic expression, such as:\nAddition: #set( $value = $foo + 1 )\n   Subtraction: #set( $value = $bar - 1 )\n   Multiplication: #set( $value = $foo * $bar )\n   Division: #set( $value = $foo / $bar )\n   Remainder: #set( $value = $foo % $bar )\n\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        tabMode: \"indent\",\n        matchBrackets: true,\n        theme: \"night\",\n        lineNumbers: true,\n        indentUnit: 4,\n        mode: \"text/velocity\"\n      });\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/velocity</code>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/velocity/velocity.js",
    "content": "CodeMirror.defineMode(\"velocity\", function(config) {\n    function parseWords(str) {\n        var obj = {}, words = str.split(\" \");\n        for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n        return obj;\n    }\n\n    var indentUnit = config.indentUnit\n    var keywords = parseWords(\"#end #else #break #stop #[[ #]] \" +\n                              \"#{end} #{else} #{break} #{stop}\");\n    var functions = parseWords(\"#if #elseif #foreach #set #include #parse #macro #define #evaluate \" +\n                               \"#{if} #{elseif} #{foreach} #{set} #{include} #{parse} #{macro} #{define} #{evaluate}\");\n    var specials = parseWords(\"$foreach.count $foreach.hasNext $foreach.first $foreach.last $foreach.topmost $foreach.parent $velocityCount\");\n    var isOperatorChar = /[+\\-*&%=<>!?:\\/|]/;\n    var multiLineStrings =true;\n\n    function chain(stream, state, f) {\n        state.tokenize = f;\n        return f(stream, state);\n    }\n    function tokenBase(stream, state) {\n        var beforeParams = state.beforeParams;\n        state.beforeParams = false;\n        var ch = stream.next();\n        // start of string?\n        if ((ch == '\"' || ch == \"'\") && state.inParams)\n            return chain(stream, state, tokenString(ch));\n        // is it one of the special signs []{}().,;? Seperator?\n        else if (/[\\[\\]{}\\(\\),;\\.]/.test(ch)) {\n            if (ch == \"(\" && beforeParams) state.inParams = true;\n            else if (ch == \")\") state.inParams = false;\n            return null;\n        }\n        // start of a number value?\n        else if (/\\d/.test(ch)) {\n            stream.eatWhile(/[\\w\\.]/);\n            return \"number\";\n        }\n        // multi line comment?\n        else if (ch == \"#\" && stream.eat(\"*\")) {\n            return chain(stream, state, tokenComment);\n        }\n        // unparsed content?\n        else if (ch == \"#\" && stream.match(/ *\\[ *\\[/)) {\n            return chain(stream, state, tokenUnparsed);\n        }\n        // single line comment?\n        else if (ch == \"#\" && stream.eat(\"#\")) {\n            stream.skipToEnd();\n            return \"comment\";\n        }\n        // variable?\n        else if (ch == \"$\") {\n            stream.eatWhile(/[\\w\\d\\$_\\.{}]/);\n            // is it one of the specials?\n            if (specials && specials.propertyIsEnumerable(stream.current().toLowerCase())) {\n                return \"keyword\";\n            }\n            else {\n                state.beforeParams = true;\n                return \"builtin\";\n            }\n        }\n        // is it a operator?\n        else if (isOperatorChar.test(ch)) {\n            stream.eatWhile(isOperatorChar);\n            return \"operator\";\n        }\n        else {\n            // get the whole word\n            stream.eatWhile(/[\\w\\$_{}]/);\n            var word = stream.current().toLowerCase();\n            // is it one of the listed keywords?\n            if (keywords && keywords.propertyIsEnumerable(word))\n                return \"keyword\";\n            // is it one of the listed functions?\n            if (functions && functions.propertyIsEnumerable(word) ||\n                stream.current().match(/^#[a-z0-9_]+ *$/i) && stream.peek()==\"(\") {\n                state.beforeParams = true;\n                return \"keyword\";\n            }\n            // default: just a \"word\"\n            return null;\n        }\n    }\n\n    function tokenString(quote) {\n        return function(stream, state) {\n            var escaped = false, next, end = false;\n            while ((next = stream.next()) != null) {\n                if (next == quote && !escaped) {\n                    end = true;\n                    break;\n                }\n                escaped = !escaped && next == \"\\\\\";\n            }\n            if (end) state.tokenize = tokenBase;\n            return \"string\";\n        };\n    }\n\n    function tokenComment(stream, state) {\n        var maybeEnd = false, ch;\n        while (ch = stream.next()) {\n            if (ch == \"#\" && maybeEnd) {\n                state.tokenize = tokenBase;\n                break;\n            }\n            maybeEnd = (ch == \"*\");\n        }\n        return \"comment\";\n    }\n\n    function tokenUnparsed(stream, state) {\n        var maybeEnd = 0, ch;\n        while (ch = stream.next()) {\n            if (ch == \"#\" && maybeEnd == 2) {\n                state.tokenize = tokenBase;\n                break;\n            }\n            if (ch == \"]\")\n                maybeEnd++;\n            else if (ch != \" \")\n                maybeEnd = 0;\n        }\n        return \"meta\";\n    }\n    // Interface\n\n    return {\n        startState: function(basecolumn) {\n            return {\n                tokenize: tokenBase,\n                beforeParams: false,\n                inParams: false\n            };\n        },\n\n        token: function(stream, state) {\n            if (stream.eatSpace()) return null;\n            return state.tokenize(stream, state);\n        }\n    };\n});\n\nCodeMirror.defineMIME(\"text/velocity\", \"velocity\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/verilog/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Verilog mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"verilog.js\"></script>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n    <style>.CodeMirror {border: 2px inset #dee;}</style>\n  </head>\n  <body>\n    <h1>CodeMirror: Verilog mode</h1>\n\n<form><textarea id=\"code\" name=\"code\">\n/** Verilog code required */\n</textarea></form>\n\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        mode: \"text/x-verilog\"\n      });\n    </script>\n\n    <p>Simple mode that tries to handle Verilog-like languages as well as it\n    can. Takes one configuration parameters: <code>keywords</code>, an\n    object whose property names are the keywords in the language.</p>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-verilog</code> (Verilog code).</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/verilog/verilog.js",
    "content": "CodeMirror.defineMode(\"verilog\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit,\n      keywords = parserConfig.keywords || {},\n      blockKeywords = parserConfig.blockKeywords || {},\n      atoms = parserConfig.atoms || {},\n      hooks = parserConfig.hooks || {},\n      multiLineStrings = parserConfig.multiLineStrings;\n  var isOperatorChar = /[&|~><!\\)\\(*#%@+\\/=?\\:;}{,\\.\\^\\-\\[\\]]/;\n\n  var curPunc;\n\n  function tokenBase(stream, state) {\n    var ch = stream.next();\n    if (hooks[ch]) {\n      var result = hooks[ch](stream, state);\n      if (result !== false) return result;\n    }\n    if (ch == '\"') {\n      state.tokenize = tokenString(ch);\n      return state.tokenize(stream, state);\n    }\n    if (/[\\[\\]{}\\(\\),;\\:\\.]/.test(ch)) {\n      curPunc = ch;\n      return null\n    }\n    if (/[\\d']/.test(ch)) {\n      stream.eatWhile(/[\\w\\.']/);\n      return \"number\";\n    }\n    if (ch == \"/\") {\n      if (stream.eat(\"*\")) {\n        state.tokenize = tokenComment;\n        return tokenComment(stream, state);\n      }\n      if (stream.eat(\"/\")) {\n        stream.skipToEnd();\n        return \"comment\";\n      }\n    }\n    if (isOperatorChar.test(ch)) {\n      stream.eatWhile(isOperatorChar);\n      return \"operator\";\n    }\n    stream.eatWhile(/[\\w\\$_]/);\n    var cur = stream.current();\n    if (keywords.propertyIsEnumerable(cur)) {\n      if (blockKeywords.propertyIsEnumerable(cur)) curPunc = \"newstatement\";\n      return \"keyword\";\n    }\n    if (atoms.propertyIsEnumerable(cur)) return \"atom\";\n    return \"word\";\n  }\n\n  function tokenString(quote) {\n    return function(stream, state) {\n      var escaped = false, next, end = false;\n      while ((next = stream.next()) != null) {\n        if (next == quote && !escaped) {end = true; break;}\n        escaped = !escaped && next == \"\\\\\";\n      }\n      if (end || !(escaped || multiLineStrings))\n        state.tokenize = tokenBase;\n      return \"string\";\n    };\n  }\n\n  function tokenComment(stream, state) {\n    var maybeEnd = false, ch;\n    while (ch = stream.next()) {\n      if (ch == \"/\" && maybeEnd) {\n        state.tokenize = tokenBase;\n        break;\n      }\n      maybeEnd = (ch == \"*\");\n    }\n    return \"comment\";\n  }\n\n  function Context(indented, column, type, align, prev) {\n    this.indented = indented;\n    this.column = column;\n    this.type = type;\n    this.align = align;\n    this.prev = prev;\n  }\n  function pushContext(state, col, type) {\n    return state.context = new Context(state.indented, col, type, null, state.context);\n  }\n  function popContext(state) {\n    var t = state.context.type;\n    if (t == \")\" || t == \"]\" || t == \"}\")\n      state.indented = state.context.indented;\n    return state.context = state.context.prev;\n  }\n\n  // Interface\n\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: null,\n        context: new Context((basecolumn || 0) - indentUnit, 0, \"top\", false),\n        indented: 0,\n        startOfLine: true\n      };\n    },\n\n    token: function(stream, state) {\n      var ctx = state.context;\n      if (stream.sol()) {\n        if (ctx.align == null) ctx.align = false;\n        state.indented = stream.indentation();\n        state.startOfLine = true;\n      }\n      if (stream.eatSpace()) return null;\n      curPunc = null;\n      var style = (state.tokenize || tokenBase)(stream, state);\n      if (style == \"comment\" || style == \"meta\") return style;\n      if (ctx.align == null) ctx.align = true;\n\n      if ((curPunc == \";\" || curPunc == \":\") && ctx.type == \"statement\") popContext(state);\n      else if (curPunc == \"{\") pushContext(state, stream.column(), \"}\");\n      else if (curPunc == \"[\") pushContext(state, stream.column(), \"]\");\n      else if (curPunc == \"(\") pushContext(state, stream.column(), \")\");\n      else if (curPunc == \"}\") {\n        while (ctx.type == \"statement\") ctx = popContext(state);\n        if (ctx.type == \"}\") ctx = popContext(state);\n        while (ctx.type == \"statement\") ctx = popContext(state);\n      }\n      else if (curPunc == ctx.type) popContext(state);\n      else if (ctx.type == \"}\" || ctx.type == \"top\" || (ctx.type == \"statement\" && curPunc == \"newstatement\"))\n        pushContext(state, stream.column(), \"statement\");\n      state.startOfLine = false;\n      return style;\n    },\n\n    indent: function(state, textAfter) {\n      if (state.tokenize != tokenBase && state.tokenize != null) return 0;\n      var firstChar = textAfter && textAfter.charAt(0), ctx = state.context, closing = firstChar == ctx.type;\n      if (ctx.type == \"statement\") return ctx.indented + (firstChar == \"{\" ? 0 : indentUnit);\n      else if (ctx.align) return ctx.column + (closing ? 0 : 1);\n      else return ctx.indented + (closing ? 0 : indentUnit);\n    },\n\n    electricChars: \"{}\"\n  };\n});\n\n(function() {\n  function words(str) {\n    var obj = {}, words = str.split(\" \");\n    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;\n    return obj;\n  }\n\n  var verilogKeywords = \"always and assign automatic begin buf bufif0 bufif1 case casex casez cell cmos config \" +\n    \"deassign default defparam design disable edge else end endcase endconfig endfunction endgenerate endmodule \" +\n    \"endprimitive endspecify endtable endtask event for force forever fork function generate genvar highz0 \" +\n    \"highz1 if ifnone incdir include initial inout input instance integer join large liblist library localparam \" +\n    \"macromodule medium module nand negedge nmos nor noshowcancelled not notif0 notif1 or output parameter pmos \" +\n    \"posedge primitive pull0 pull1 pulldown pullup pulsestyle_onevent pulsestyle_ondetect rcmos real realtime \" +\n    \"reg release repeat rnmos rpmos rtran rtranif0 rtranif1 scalared showcancelled signed small specify specparam \" +\n    \"strong0 strong1 supply0 supply1 table task time tran tranif0 tranif1 tri tri0 tri1 triand trior trireg \" +\n    \"unsigned use vectored wait wand weak0 weak1 while wire wor xnor xor\";\n\n  var verilogBlockKeywords = \"begin bufif0 bufif1 case casex casez config else end endcase endconfig endfunction \" +\n    \"endgenerate endmodule endprimitive endspecify endtable endtask for forever function generate if ifnone \" +\n    \"macromodule module primitive repeat specify table task while\";\n\n  function metaHook(stream, state) {\n    stream.eatWhile(/[\\w\\$_]/);\n    return \"meta\";\n  }\n\n  // C#-style strings where \"\" escapes a quote.\n  function tokenAtString(stream, state) {\n    var next;\n    while ((next = stream.next()) != null) {\n      if (next == '\"' && !stream.eat('\"')) {\n        state.tokenize = null;\n        break;\n      }\n    }\n    return \"string\";\n  }\n\n  CodeMirror.defineMIME(\"text/x-verilog\", {\n    name: \"verilog\",\n    keywords: words(verilogKeywords),\n    blockKeywords: words(verilogBlockKeywords),\n    atoms: words(\"null\"),\n    hooks: {\"`\": metaHook, \"$\": metaHook}\n  });\n}());\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/xml/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: XML mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"xml.js\"></script>\n    <style type=\"text/css\">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: XML mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n&lt;html style=\"color: green\"&gt;\n  &lt;!-- this is a comment --&gt;\n  &lt;head&gt;\n    &lt;title&gt;HTML Example&lt;/title&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n    The indentation tries to be &lt;em&gt;somewhat &amp;quot;do what\n    I mean&amp;quot;&lt;/em&gt;... but might not match your style.\n  &lt;/body&gt;\n&lt;/html&gt;\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        mode: {name: \"xml\", alignCDATA: true},\n        lineNumbers: true\n      });\n    </script>\n    <p>The XML mode supports two configuration parameters:</p>\n    <dl>\n      <dt><code>htmlMode (boolean)</code></dt>\n      <dd>This switches the mode to parse HTML instead of XML. This\n      means attributes do not have to be quoted, and some elements\n      (such as <code>br</code>) do not require a closing tag.</dd>\n      <dt><code>alignCDATA (boolean)</code></dt>\n      <dd>Setting this to true will force the opening tag of CDATA\n      blocks to not be indented.</dd>\n    </dl>\n\n    <p><strong>MIME types defined:</strong> <code>application/xml</code>, <code>text/html</code>.</p>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/xml/xml.js",
    "content": "CodeMirror.defineMode(\"xml\", function(config, parserConfig) {\n  var indentUnit = config.indentUnit;\n  var Kludges = parserConfig.htmlMode ? {\n    autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,\n                      'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,\n                      'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,\n                      'track': true, 'wbr': true},\n    implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,\n                       'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,\n                       'th': true, 'tr': true},\n    contextGrabbers: {\n      'dd': {'dd': true, 'dt': true},\n      'dt': {'dd': true, 'dt': true},\n      'li': {'li': true},\n      'option': {'option': true, 'optgroup': true},\n      'optgroup': {'optgroup': true},\n      'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,\n            'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,\n            'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,\n            'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,\n            'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},\n      'rp': {'rp': true, 'rt': true},\n      'rt': {'rp': true, 'rt': true},\n      'tbody': {'tbody': true, 'tfoot': true},\n      'td': {'td': true, 'th': true},\n      'tfoot': {'tbody': true},\n      'th': {'td': true, 'th': true},\n      'thead': {'tbody': true, 'tfoot': true},\n      'tr': {'tr': true}\n    },\n    doNotIndent: {\"pre\": true},\n    allowUnquoted: true,\n    allowMissing: false\n  } : {\n    autoSelfClosers: {},\n    implicitlyClosed: {},\n    contextGrabbers: {},\n    doNotIndent: {},\n    allowUnquoted: false,\n    allowMissing: false\n  };\n  var alignCDATA = parserConfig.alignCDATA;\n\n  // Return variables for tokenizers\n  var tagName, type;\n\n  function inText(stream, state) {\n    function chain(parser) {\n      state.tokenize = parser;\n      return parser(stream, state);\n    }\n\n    var ch = stream.next();\n    if (ch == \"<\") {\n      if (stream.eat(\"!\")) {\n        if (stream.eat(\"[\")) {\n          if (stream.match(\"CDATA[\")) return chain(inBlock(\"atom\", \"]]>\"));\n          else return null;\n        }\n        else if (stream.match(\"--\")) return chain(inBlock(\"comment\", \"-->\"));\n        else if (stream.match(\"DOCTYPE\", true, true)) {\n          stream.eatWhile(/[\\w\\._\\-]/);\n          return chain(doctype(1));\n        }\n        else return null;\n      }\n      else if (stream.eat(\"?\")) {\n        stream.eatWhile(/[\\w\\._\\-]/);\n        state.tokenize = inBlock(\"meta\", \"?>\");\n        return \"meta\";\n      }\n      else {\n        type = stream.eat(\"/\") ? \"closeTag\" : \"openTag\";\n        stream.eatSpace();\n        tagName = \"\";\n        var c;\n        while ((c = stream.eat(/[^\\s\\u00a0=<>\\\"\\'\\/?]/))) tagName += c;\n        state.tokenize = inTag;\n        return \"tag\";\n      }\n    }\n    else if (ch == \"&\") {\n      var ok;\n      if (stream.eat(\"#\")) {\n        if (stream.eat(\"x\")) {\n          ok = stream.eatWhile(/[a-fA-F\\d]/) && stream.eat(\";\");          \n        } else {\n          ok = stream.eatWhile(/[\\d]/) && stream.eat(\";\");\n        }\n      } else {\n        ok = stream.eatWhile(/[\\w\\.\\-:]/) && stream.eat(\";\");\n      }\n      return ok ? \"atom\" : \"error\";\n    }\n    else {\n      stream.eatWhile(/[^&<]/);\n      return null;\n    }\n  }\n\n  function inTag(stream, state) {\n    var ch = stream.next();\n    if (ch == \">\" || (ch == \"/\" && stream.eat(\">\"))) {\n      state.tokenize = inText;\n      type = ch == \">\" ? \"endTag\" : \"selfcloseTag\";\n      return \"tag\";\n    }\n    else if (ch == \"=\") {\n      type = \"equals\";\n      return null;\n    }\n    else if (/[\\'\\\"]/.test(ch)) {\n      state.tokenize = inAttribute(ch);\n      return state.tokenize(stream, state);\n    }\n    else {\n      stream.eatWhile(/[^\\s\\u00a0=<>\\\"\\'\\/?]/);\n      return \"word\";\n    }\n  }\n\n  function inAttribute(quote) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.next() == quote) {\n          state.tokenize = inTag;\n          break;\n        }\n      }\n      return \"string\";\n    };\n  }\n\n  function inBlock(style, terminator) {\n    return function(stream, state) {\n      while (!stream.eol()) {\n        if (stream.match(terminator)) {\n          state.tokenize = inText;\n          break;\n        }\n        stream.next();\n      }\n      return style;\n    };\n  }\n  function doctype(depth) {\n    return function(stream, state) {\n      var ch;\n      while ((ch = stream.next()) != null) {\n        if (ch == \"<\") {\n          state.tokenize = doctype(depth + 1);\n          return state.tokenize(stream, state);\n        } else if (ch == \">\") {\n          if (depth == 1) {\n            state.tokenize = inText;\n            break;\n          } else {\n            state.tokenize = doctype(depth - 1);\n            return state.tokenize(stream, state);\n          }\n        }\n      }\n      return \"meta\";\n    };\n  }\n\n  var curState, setStyle;\n  function pass() {\n    for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);\n  }\n  function cont() {\n    pass.apply(null, arguments);\n    return true;\n  }\n\n  function pushContext(tagName, startOfLine) {\n    var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent);\n    curState.context = {\n      prev: curState.context,\n      tagName: tagName,\n      indent: curState.indented,\n      startOfLine: startOfLine,\n      noIndent: noIndent\n    };\n  }\n  function popContext() {\n    if (curState.context) curState.context = curState.context.prev;\n  }\n\n  function element(type) {\n    if (type == \"openTag\") {\n      curState.tagName = tagName;\n      return cont(attributes, endtag(curState.startOfLine));\n    } else if (type == \"closeTag\") {\n      var err = false;\n      if (curState.context) {\n        if (curState.context.tagName != tagName) {\n          if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {\n            popContext();\n          }\n          err = !curState.context || curState.context.tagName != tagName;\n        }\n      } else {\n        err = true;\n      }\n      if (err) setStyle = \"error\";\n      return cont(endclosetag(err));\n    }\n    return cont();\n  }\n  function endtag(startOfLine) {\n    return function(type) {\n      if (type == \"selfcloseTag\" ||\n          (type == \"endTag\" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) {\n        maybePopContext(curState.tagName.toLowerCase());\n        return cont();\n      }\n      if (type == \"endTag\") {\n        maybePopContext(curState.tagName.toLowerCase());\n        pushContext(curState.tagName, startOfLine);\n        return cont();\n      }\n      return cont();\n    };\n  }\n  function endclosetag(err) {\n    return function(type) {\n      if (err) setStyle = \"error\";\n      if (type == \"endTag\") { popContext(); return cont(); }\n      setStyle = \"error\";\n      return cont(arguments.callee);\n    }\n  }\n  function maybePopContext(nextTagName) {\n    var parentTagName;\n    while (true) {\n      if (!curState.context) {\n        return;\n      }\n      parentTagName = curState.context.tagName.toLowerCase();\n      if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||\n          !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {\n        return;\n      }\n      popContext();\n    }\n  }\n\n  function attributes(type) {\n    if (type == \"word\") {setStyle = \"attribute\"; return cont(attribute, attributes);}\n    if (type == \"endTag\" || type == \"selfcloseTag\") return pass();\n    setStyle = \"error\";\n    return cont(attributes);\n  }\n  function attribute(type) {\n    if (type == \"equals\") return cont(attvalue, attributes);\n    if (!Kludges.allowMissing) setStyle = \"error\";\n    return (type == \"endTag\" || type == \"selfcloseTag\") ? pass() : cont();\n  }\n  function attvalue(type) {\n    if (type == \"string\") return cont(attvaluemaybe);\n    if (type == \"word\" && Kludges.allowUnquoted) {setStyle = \"string\"; return cont();}\n    setStyle = \"error\";\n    return (type == \"endTag\" || type == \"selfCloseTag\") ? pass() : cont();\n  }\n  function attvaluemaybe(type) {\n    if (type == \"string\") return cont(attvaluemaybe);\n    else return pass();\n  }\n\n  return {\n    startState: function() {\n      return {tokenize: inText, cc: [], indented: 0, startOfLine: true, tagName: null, context: null};\n    },\n\n    token: function(stream, state) {\n      if (stream.sol()) {\n        state.startOfLine = true;\n        state.indented = stream.indentation();\n      }\n      if (stream.eatSpace()) return null;\n\n      setStyle = type = tagName = null;\n      var style = state.tokenize(stream, state);\n      state.type = type;\n      if ((style || type) && style != \"comment\") {\n        curState = state;\n        while (true) {\n          var comb = state.cc.pop() || element;\n          if (comb(type || style)) break;\n        }\n      }\n      state.startOfLine = false;\n      return setStyle || style;\n    },\n\n    indent: function(state, textAfter, fullLine) {\n      var context = state.context;\n      if ((state.tokenize != inTag && state.tokenize != inText) ||\n          context && context.noIndent)\n        return fullLine ? fullLine.match(/^(\\s*)/)[0].length : 0;\n      if (alignCDATA && /<!\\[CDATA\\[/.test(textAfter)) return 0;\n      if (context && /^<\\//.test(textAfter))\n        context = context.prev;\n      while (context && !context.startOfLine)\n        context = context.prev;\n      if (context) return context.indent + indentUnit;\n      else return 0;\n    },\n\n    compareStates: function(a, b) {\n      if (a.indented != b.indented || a.tokenize != b.tokenize) return false;\n      for (var ca = a.context, cb = b.context; ; ca = ca.prev, cb = cb.prev) {\n        if (!ca || !cb) return ca == cb;\n        if (ca.tagName != cb.tagName) return false;\n      }\n    },\n\n    electricChars: \"/\"\n  };\n});\n\nCodeMirror.defineMIME(\"application/xml\", \"xml\");\nif (!CodeMirror.mimeModes.hasOwnProperty(\"text/html\"))\n  CodeMirror.defineMIME(\"text/html\", {name: \"xml\", htmlMode: true});\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/xquery/LICENSE",
    "content": "Copyright (C) 2011 by MarkLogic Corporation\nAuthor: Mike Brevoort <mike@brevoort.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE."
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/xquery/index.html",
    "content": "<!doctype html> \n<html> \n<!--\n/*\nCopyright (C) 2011 by MarkLogic Corporation\nAuthor: Mike Brevoort <mike@brevoort.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n-->\n  <head> \n    <title>CodeMirror 2: JavaScript mode</title> \n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\"> \n    <script src=\"http://codemirror.net/lib/codemirror.js\"></script> \n    <script src=\"xquery.js\"></script> \n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\"> \n    <link rel=\"stylesheet\" href=\"../../theme/xq-dark.css\"> \n    <style type=\"text/css\">\n\t\t\t.CodeMirror {\n\t\t\t\tborder-top: 1px solid black; border-bottom: 1px solid black;\n\t\t\t}\n\t\t\t.CodeMirror-scroll {\n\t\t\t\theight:400px;\n\t\t\t}\n\t\t</style> \n  </head> \n  <body> \n    <h1>CodeMirror 2: XQuery mode</h1> \n \n<div class=\"cm-s-default\"> \n\t<textarea id=\"code\" name=\"code\"> \nxquery version &quot;1.0-ml&quot;;\n(: this is\n : a \n   \"comment\" :)\nlet $let := &lt;x attr=&quot;value&quot;&gt;&quot;test&quot;&lt;func&gt;function() $var {function()} {$var}&lt;/func&gt;&lt;/x&gt;\nlet $joe:=1\nreturn element element {\n\tattribute attribute { 1 },\n\telement test { &#39;a&#39; }, \n\tattribute foo { &quot;bar&quot; },\n\tfn:doc()[ foo/@bar eq $let ],\n\t//x }    \n \n(: a more 'evil' test :)\n(: Modified Blakeley example (: with nested comment :) ... :)\ndeclare private function local:declare() {()};\ndeclare private function local:private() {()};\ndeclare private function local:function() {()};\ndeclare private function local:local() {()};\nlet $let := &lt;let&gt;let $let := &quot;let&quot;&lt;/let&gt;\nreturn element element {\n\tattribute attribute { try { xdmp:version() } catch($e) { xdmp:log($e) } },\n\tattribute fn:doc { &quot;bar&quot; castable as xs:string },\n\telement text { text { &quot;text&quot; } },\n\tfn:doc()[ child::eq/(@bar | attribute::attribute) eq $let ],\n\t//fn:doc\n}\n\n\n\nxquery version &quot;1.0-ml&quot;;\n\n(: Copyright 2006-2010 Mark Logic Corporation. :)\n\n(:\n : Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);\n : you may not use this file except in compliance with the License.\n : You may obtain a copy of the License at\n :\n :     http://www.apache.org/licenses/LICENSE-2.0\n :\n : Unless required by applicable law or agreed to in writing, software\n : distributed under the License is distributed on an &quot;AS IS&quot; BASIS,\n : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n : See the License for the specific language governing permissions and\n : limitations under the License.\n :)\n\nmodule namespace json = &quot;http://marklogic.com/json&quot;;\ndeclare default function namespace &quot;http://www.w3.org/2005/xpath-functions&quot;;\n\n(: Need to backslash escape any double quotes, backslashes, and newlines :)\ndeclare function json:escape($s as xs:string) as xs:string {\n  let $s := replace($s, &quot;\\\\&quot;, &quot;\\\\\\\\&quot;)\n  let $s := replace($s, &quot;&quot;&quot;&quot;, &quot;\\\\&quot;&quot;&quot;)\n  let $s := replace($s, codepoints-to-string((13, 10)), &quot;\\\\n&quot;)\n  let $s := replace($s, codepoints-to-string(13), &quot;\\\\n&quot;)\n  let $s := replace($s, codepoints-to-string(10), &quot;\\\\n&quot;)\n  return $s\n};\n\ndeclare function json:atomize($x as element()) as xs:string {\n  if (count($x/node()) = 0) then 'null'\n  else if ($x/@type = &quot;number&quot;) then\n    let $castable := $x castable as xs:float or\n                     $x castable as xs:double or\n                     $x castable as xs:decimal\n    return\n    if ($castable) then xs:string($x)\n    else error(concat(&quot;Not a number: &quot;, xdmp:describe($x)))\n  else if ($x/@type = &quot;boolean&quot;) then\n    let $castable := $x castable as xs:boolean\n    return\n    if ($castable) then xs:string(xs:boolean($x))\n    else error(concat(&quot;Not a boolean: &quot;, xdmp:describe($x)))\n  else concat('&quot;', json:escape($x), '&quot;')\n};\n\n(: Print the thing that comes after the colon :)\ndeclare function json:print-value($x as element()) as xs:string {\n  if (count($x/*) = 0) then\n    json:atomize($x)\n  else if ($x/@quote = &quot;true&quot;) then\n    concat('&quot;', json:escape(xdmp:quote($x/node())), '&quot;')\n  else\n    string-join(('{',\n      string-join(for $i in $x/* return json:print-name-value($i), &quot;,&quot;),\n    '}'), &quot;&quot;)\n};\n\n(: Print the name and value both :)\ndeclare function json:print-name-value($x as element()) as xs:string? {\n  let $name := name($x)\n  let $first-in-array :=\n    count($x/preceding-sibling::*[name(.) = $name]) = 0 and\n    (count($x/following-sibling::*[name(.) = $name]) &gt; 0 or $x/@array = &quot;true&quot;)\n  let $later-in-array := count($x/preceding-sibling::*[name(.) = $name]) &gt; 0\n  return\n\n  if ($later-in-array) then\n    ()  (: I was handled previously :)\n  else if ($first-in-array) then\n    string-join(('&quot;', json:escape($name), '&quot;:[',\n      string-join((for $i in ($x, $x/following-sibling::*[name(.) = $name]) return json:print-value($i)), &quot;,&quot;),\n    ']'), &quot;&quot;)\n   else\n     string-join(('&quot;', json:escape($name), '&quot;:', json:print-value($x)), &quot;&quot;)\n};\n\n(:~\n  Transforms an XML element into a JSON string representation.  See http://json.org.\n  &lt;p/&gt;\n  Sample usage:\n  &lt;pre&gt;\n    xquery version &quot;1.0-ml&quot;;\n    import module namespace json=&quot;http://marklogic.com/json&quot; at &quot;json.xqy&quot;;\n    json:serialize(&amp;lt;foo&amp;gt;&amp;lt;bar&amp;gt;kid&amp;lt;/bar&amp;gt;&amp;lt;/foo&amp;gt;)\n  &lt;/pre&gt;\n  Sample transformations:\n  &lt;pre&gt;\n  &amp;lt;e/&amp;gt; becomes {&quot;e&quot;:null}\n  &amp;lt;e&amp;gt;text&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;text&quot;}\n  &amp;lt;e&amp;gt;quote &quot; escaping&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;quote \\&quot; escaping&quot;}\n  &amp;lt;e&amp;gt;backslash \\ escaping&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;backslash \\\\ escaping&quot;}\n  &amp;lt;e&amp;gt;&amp;lt;a&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;b&amp;gt;text2&amp;lt;/b&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:&quot;text1&quot;,&quot;b&quot;:&quot;text2&quot;}}\n  &amp;lt;e&amp;gt;&amp;lt;a&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;a&amp;gt;text2&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:[&quot;text1&quot;,&quot;text2&quot;]}}\n  &amp;lt;e&amp;gt;&amp;lt;a array=&quot;true&quot;&amp;gt;text1&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:[&quot;text1&quot;]}}\n  &amp;lt;e&amp;gt;&amp;lt;a type=&quot;boolean&quot;&amp;gt;false&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:false}}\n  &amp;lt;e&amp;gt;&amp;lt;a type=&quot;number&quot;&amp;gt;123.5&amp;lt;/a&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:{&quot;a&quot;:123.5}}\n  &amp;lt;e quote=&quot;true&quot;&amp;gt;&amp;lt;div attrib=&quot;value&quot;/&amp;gt;&amp;lt;/e&amp;gt; becomes {&quot;e&quot;:&quot;&amp;lt;div attrib=\\&quot;value\\&quot;/&amp;gt;&quot;}\n  &lt;/pre&gt;\n  &lt;p/&gt;\n  Namespace URIs are ignored.  Namespace prefixes are included in the JSON name.\n  &lt;p/&gt;\n  Attributes are ignored, except for the special attribute @array=&quot;true&quot; that\n  indicates the JSON serialization should write the node, even if single, as an\n  array, and the attribute @type that can be set to &quot;boolean&quot; or &quot;number&quot; to\n  dictate the value should be written as that type (unquoted).  There's also\n  an @quote attribute that when set to true writes the inner content as text\n  rather than as structured JSON, useful for sending some XHTML over the\n  wire.\n  &lt;p/&gt;\n  Text nodes within mixed content are ignored.\n\n  @param $x Element node to convert\n  @return String holding JSON serialized representation of $x\n\n  @author Jason Hunter\n  @version 1.0.1\n  \n  Ported to xquery 1.0-ml; double escaped backslashes in json:escape\n:)\ndeclare function json:serialize($x as element())  as xs:string {\n  string-join(('{', json:print-name-value($x), '}'), &quot;&quot;)\n};\n  </textarea> \n</div> \n \n    <script> \n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {\n        lineNumbers: true,\n        matchBrackets: true,\n        theme: \"xq-dark\"\n      });\n    </script> \n \n    <p><strong>MIME types defined:</strong> <code>application/xquery</code>.</p> \n \n    <p>Development of the CodeMirror XQuery mode was sponsored by \n      <a href=\"http://marklogic.com\">MarkLogic</a> and developed by \n      <a href=\"https://twitter.com/mbrevoort\">Mike Brevoort</a>.\n    </p>\n \n  </body> \n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/xquery/test/index.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n      \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n  <head>\n    <link rel=\"stylesheet\" href=\"http://code.jquery.com/qunit/qunit-git.css\" type=\"text/css\"/>\n    <script src=\"http://code.jquery.com/jquery-latest.js\"> </script>\n    <script type=\"text/javascript\" src=\"http://code.jquery.com/qunit/qunit-git.js\"></script>\n\n    <script src=\"../../../lib/codemirror.js\"></script> \n    <script src=\"../xquery.js\"></script>\n\n    <script type=\"text/javascript\" src=\"testBase.js\"></script>\n    <script type=\"text/javascript\" src=\"testMultiAttr.js\"></script>\n    <script type=\"text/javascript\" src=\"testQuotes.js\"></script>\n    <script type=\"text/javascript\" src=\"testEmptySequenceKeyword.js\"></script>\n    <script type=\"text/javascript\" src=\"testProcessingInstructions.js\"></script>\n    <script type=\"text/javascript\" src=\"testNamespaces.js\"></script>\n  </head>\n  <body>\n    <h1 id=\"qunit-header\">XQuery CodeMirror Mode</h1>\n    <h2 id=\"qunit-banner\"></h2>\n    <h2 id=\"qunit-userAgent\"></h2>\n    <ol id=\"qunit-tests\">\n    </ol>\n    <div id=\"sandbox\" style=\"right:5000px; position:absolute; \"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/xquery/test/testBase.js",
    "content": "  $(document).ready(function(){\n    module(\"testBase\");\n    test(\"eviltest\", function() {\n      expect(1);\n\n      var input = 'xquery version &quot;1.0-ml&quot;;\\\n      (: this is\\\n       : a \\\n         \"comment\" :)\\\n      let $let := &lt;x attr=&quot;value&quot;&gt;&quot;test&quot;&lt;func&gt;function() $var {function()} {$var}&lt;/func&gt;&lt;/x&gt;\\\n      let $joe:=1\\\n      return element element {\\\n          attribute attribute { 1 },\\\n          element test { &#39;a&#39; }, \\\n          attribute foo { &quot;bar&quot; },\\\n          fn:doc()[ foo/@bar eq $let ],\\\n          //x }    \\\n       \\\n      (: a more \\'evil\\' test :)\\\n      (: Modified Blakeley example (: with nested comment :) ... :)\\\n      declare private function local:declare() {()};\\\n      declare private function local:private() {()};\\\n      declare private function local:function() {()};\\\n      declare private function local:local() {()};\\\n      let $let := &lt;let&gt;let $let := &quot;let&quot;&lt;/let&gt;\\\n      return element element {\\\n          attribute attribute { try { xdmp:version() } catch($e) { xdmp:log($e) } },\\\n          attribute fn:doc { &quot;bar&quot; castable as xs:string },\\\n          element text { text { &quot;text&quot; } },\\\n          fn:doc()[ child::eq/(@bar | attribute::attribute) eq $let ],\\\n          //fn:doc\\\n      }';\n      var expected = '<span class=\"cm-keyword\">xquery</span> <span class=\"cm-keyword\">version</span> <span class=\"cm-string\">\"1.0-ml\"</span><span class=\"cm-variable cm-def\">;</span>      <span class=\"cm-comment\">(: this is       : a          \"comment\" :)</span>      <span class=\"cm-keyword\">let</span> <span class=\"cm-variable\">$let</span> <span class=\"cm-keyword\">:=</span> <span class=\"cm-tag\">&lt;x </span><span class=\"cm-attribute\">attr</span>=<span class=\"cm-string\">\"value\"</span><span class=\"cm-tag\">&gt;</span><span class=\"cm-word\">\"test\"</span><span class=\"cm-tag\">&lt;func&gt;</span><span class=\"cm-word\">function()</span> <span class=\"cm-word\">$var</span> {<span class=\"cm-keyword\">function</span>()} {<span class=\"cm-variable\">$var</span>}<span class=\"cm-tag\">&lt;/func&gt;&lt;/x&gt;</span>      <span class=\"cm-keyword\">let</span> <span class=\"cm-variable\">$joe</span><span class=\"cm-keyword\">:=</span><span class=\"cm-atom\">1</span>      <span class=\"cm-keyword\">return</span> <span class=\"cm-keyword\">element</span> <span class=\"cm-word\">element</span> {          <span class=\"cm-keyword\">attribute</span> <span class=\"cm-word\">attribute</span> { <span class=\"cm-atom\">1</span> },          <span class=\"cm-keyword\">element</span> <span class=\"cm-word\">test</span> { <span class=\"cm-string\">\\'a\\'</span> },           <span class=\"cm-keyword\">attribute</span> <span class=\"cm-word\">foo</span> { <span class=\"cm-string\">\"bar\"</span> },          <span class=\"cm-variable cm-def\">fn:doc</span>()[ <span class=\"cm-word\">foo</span><span class=\"cm-keyword\">/</span><span class=\"cm-word\">@bar</span> <span class=\"cm-keyword\">eq</span> <span class=\"cm-variable\">$let</span> ],          <span class=\"cm-keyword\">//</span><span class=\"cm-word\">x</span> }                 <span class=\"cm-comment\">(: a more \\'evil\\' test :)</span>      <span class=\"cm-comment\">(: Modified Blakeley example (: with nested comment :) ... :)</span>      <span class=\"cm-keyword\">declare</span> <span class=\"cm-keyword\">private</span> <span class=\"cm-keyword\">function</span> <span class=\"cm-variable cm-def\">local:declare</span>() {()}<span class=\"cm-word\">;</span>      <span class=\"cm-keyword\">declare</span> <span class=\"cm-keyword\">private</span> <span class=\"cm-keyword\">function</span> <span class=\"cm-variable cm-def\">local:private</span>() {()}<span class=\"cm-word\">;</span>      <span class=\"cm-keyword\">declare</span> <span class=\"cm-keyword\">private</span> <span class=\"cm-keyword\">function</span> <span class=\"cm-variable cm-def\">local:function</span>() {()}<span class=\"cm-word\">;</span>      <span class=\"cm-keyword\">declare</span> <span class=\"cm-keyword\">private</span> <span class=\"cm-keyword\">function</span> <span class=\"cm-variable cm-def\">local:local</span>() {()}<span class=\"cm-word\">;</span>      <span class=\"cm-keyword\">let</span> <span class=\"cm-variable\">$let</span> <span class=\"cm-keyword\">:=</span> <span class=\"cm-tag\">&lt;let&gt;</span><span class=\"cm-word\">let</span> <span class=\"cm-word\">$let</span> <span class=\"cm-word\">:=</span> <span class=\"cm-word\">\"let\"</span><span class=\"cm-tag\">&lt;/let&gt;</span>      <span class=\"cm-keyword\">return</span> <span class=\"cm-keyword\">element</span> <span class=\"cm-word\">element</span> {          <span class=\"cm-keyword\">attribute</span> <span class=\"cm-word\">attribute</span> { <span class=\"cm-keyword\">try</span> { <span class=\"cm-variable cm-def\">xdmp:version</span>() } <span class=\"cm-keyword\">catch</span>(<span class=\"cm-variable\">$e</span>) { <span class=\"cm-variable cm-def\">xdmp:log</span>(<span class=\"cm-variable\">$e</span>) } },          <span class=\"cm-keyword\">attribute</span> <span class=\"cm-word\">fn:doc</span> { <span class=\"cm-string\">\"bar\"</span> <span class=\"cm-word\">castable</span> <span class=\"cm-keyword\">as</span> <span class=\"cm-atom\">xs:string</span> },          <span class=\"cm-keyword\">element</span> <span class=\"cm-word\">text</span> { <span class=\"cm-keyword\">text</span> { <span class=\"cm-string\">\"text\"</span> } },          <span class=\"cm-variable cm-def\">fn:doc</span>()[ <span class=\"cm-qualifier\">child::</span><span class=\"cm-word\">eq</span><span class=\"cm-keyword\">/</span>(<span class=\"cm-word\">@bar</span> <span class=\"cm-keyword\">|</span> <span class=\"cm-qualifier\">attribute::</span><span class=\"cm-word\">attribute</span>) <span class=\"cm-keyword\">eq</span> <span class=\"cm-variable\">$let</span> ],          <span class=\"cm-keyword\">//</span><span class=\"cm-word\">fn:doc</span>      }';\n\n      $(\"#sandbox\").html('<textarea id=\"editor\">' + input + '</textarea>');\n      var editor = CodeMirror.fromTextArea($(\"#editor\")[0]);\n      var result = $(\".CodeMirror-lines div div pre\")[0].innerHTML;\n\n       equal(result, expected);\n       $(\"#editor\").html(\"\");\n    });\n  });\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/xquery/test/testEmptySequenceKeyword.js",
    "content": "$(document).ready(function(){\n  module(\"testEmptySequenceKeyword\");\n  test(\"testEmptySequenceKeyword\", function() {\n    expect(1);\n\n    var input = '\"foo\" instance of empty-sequence()';\n    var expected = '<span class=\"cm-string\">\"foo\"</span> <span class=\"cm-keyword\">instance</span> <span class=\"cm-keyword\">of</span> <span class=\"cm-keyword\">empty-sequence</span>()';\n\n    $(\"#sandbox\").html('<textarea id=\"editor\">' + input + '</textarea>');\n    var editor = CodeMirror.fromTextArea($(\"#editor\")[0]);\n    var result = $(\".CodeMirror-lines div div pre\")[0].innerHTML;\n\n     equal(result, expected);\n     $(\"#editor\").html(\"\");\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/xquery/test/testMultiAttr.js",
    "content": "  $(document).ready(function(){\n    module(\"testMultiAttr\");\n    test(\"test1\", function() {\n      expect(1);\n\n      var expected = '<span class=\"cm-tag\">&lt;p </span><span class=\"cm-attribute\">a1</span>=<span class=\"cm-string\">\"foo\"</span> <span class=\"cm-attribute\">a2</span>=<span class=\"cm-string\">\"bar\"</span><span class=\"cm-tag\">&gt;</span><span class=\"cm-word\">hello</span> <span class=\"cm-word\">world</span><span class=\"cm-tag\">&lt;/p&gt;</span>';\n\n      $(\"#sandbox\").html('<textarea id=\"editor\"></textarea>');\n      $(\"#editor\").html('<p a1=\"foo\" a2=\"bar\">hello world</p>');\n      var editor = CodeMirror.fromTextArea($(\"#editor\")[0]);\n      var result = $(\".CodeMirror-lines div div pre\")[0].innerHTML;\n\n       equal(result, expected);\n       $(\"#editor\").html(\"\");\n    });\n  });\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/xquery/test/testNamespaces.js",
    "content": "$(document).ready(function(){\n  module(\"test namespaces\");\n\n// --------------------------------------------------------------------------------\n// this test is based on this:\n//http://mbrevoort.github.com/CodeMirror2/#!exprSeqTypes/PrologExpr/VariableProlog/ExternalVariablesWith/K2-ExternalVariablesWith-10.xq\n// --------------------------------------------------------------------------------\n  test(\"test namespaced variable\", function() {\n    expect(1);\n\n    var input = 'declare namespace e = \"http://example.com/ANamespace\";\\\ndeclare variable $e:exampleComThisVarIsNotRecognized as element(*) external;';\n\n    var expected = '<span class=\"cm-keyword\">declare</span> <span class=\"cm-keyword\">namespace</span> <span class=\"cm-word\">e</span> <span class=\"cm-keyword\">=</span> <span class=\"cm-string\">\"http://example.com/ANamespace\"</span><span class=\"cm-word\">;declare</span> <span class=\"cm-keyword\">variable</span> <span class=\"cm-variable\">$e:exampleComThisVarIsNotRecognized</span> <span class=\"cm-keyword\">as</span> <span class=\"cm-keyword\">element</span>(<span class=\"cm-keyword\">*</span>) <span class=\"cm-word\">external;</span>';\n\n    $(\"#sandbox\").html('<textarea id=\"editor\">' + input + '</textarea>');\n    var editor = CodeMirror.fromTextArea($(\"#editor\")[0]);\n    var result = $(\".CodeMirror-lines div div pre\")[0].innerHTML;\n\n     equal(result, expected);\n     $(\"#editor\").html(\"\");\n  });\n\n\n// --------------------------------------------------------------------------------\n// this test is based on:\n// http://mbrevoort.github.com/CodeMirror2/#!Basics/EQNames/eqname-002.xq  \n// --------------------------------------------------------------------------------\n  test(\"test EQName variable\", function() {\n    expect(1);\n\n    var input = 'declare variable $\"http://www.example.com/ns/my\":var := 12;\\\n<out>{$\"http://www.example.com/ns/my\":var}</out>';\n\n    var expected = '<span class=\"cm-keyword\">declare</span> <span class=\"cm-keyword\">variable</span> <span class=\"cm-variable\">$\"http://www.example.com/ns/my\":var</span> <span class=\"cm-keyword\">:=</span> <span class=\"cm-atom\">12</span><span class=\"cm-word\">;</span><span class=\"cm-tag\">&lt;out&gt;</span>{<span class=\"cm-variable\">$\"http://www.example.com/ns/my\":var</span>}<span class=\"cm-tag\">&lt;/out&gt;</span>';\n\n    $(\"#sandbox\").html('<textarea id=\"editor\">' + input + '</textarea>');\n    var editor = CodeMirror.fromTextArea($(\"#editor\")[0]);\n    var result = $(\".CodeMirror-lines div div pre\")[0].innerHTML;\n\n     equal(result, expected);\n     $(\"#editor\").html(\"\");\n  });\n\n// --------------------------------------------------------------------------------\n// this test is based on:\n// http://mbrevoort.github.com/CodeMirror2/#!Basics/EQNames/eqname-003.xq\n// --------------------------------------------------------------------------------\n  test(\"test EQName function\", function() {\n    expect(1);\n\n    var input = 'declare function \"http://www.example.com/ns/my\":fn ($a as xs:integer) as xs:integer {\\\n   $a + 2\\\n};\\\n<out>{\"http://www.example.com/ns/my\":fn(12)}</out>';\n\n    var expected = '<span class=\"cm-keyword\">declare</span> <span class=\"cm-keyword\">function</span> <span class=\"cm-variable cm-def\">\"http://www.example.com/ns/my\":fn</span> (<span class=\"cm-variable\">$a</span> <span class=\"cm-keyword\">as</span> <span class=\"cm-atom\">xs:integer</span>) <span class=\"cm-keyword\">as</span> <span class=\"cm-atom\">xs:integer</span> {   <span class=\"cm-variable\">$a</span> <span class=\"cm-keyword\">+</span> <span class=\"cm-atom\">2</span>}<span class=\"cm-word\">;</span><span class=\"cm-tag\">&lt;out&gt;</span>{<span class=\"cm-variable cm-def\">\"http://www.example.com/ns/my\":fn</span>(<span class=\"cm-atom\">12</span>)}<span class=\"cm-tag\">&lt;/out&gt;</span>';\n\n    $(\"#sandbox\").html('<textarea id=\"editor\">' + input + '</textarea>');\n    var editor = CodeMirror.fromTextArea($(\"#editor\")[0]);\n    var result = $(\".CodeMirror-lines div div pre\")[0].innerHTML;\n\n     equal(result, expected);\n     $(\"#editor\").html(\"\");\n  });\n\n// --------------------------------------------------------------------------------\n// this test is based on:\n// http://mbrevoort.github.com/CodeMirror2/#!Basics/EQNames/eqname-003.xq\n// --------------------------------------------------------------------------------\n  test(\"test EQName function with single quotes\", function() {\n    expect(1);\n\n    var input = 'declare function \\'http://www.example.com/ns/my\\':fn ($a as xs:integer) as xs:integer {\\\n   $a + 2\\\n};\\\n<out>{\\'http://www.example.com/ns/my\\':fn(12)}</out>';\n\n    var expected = '<span class=\"cm-keyword\">declare</span> <span class=\"cm-keyword\">function</span> <span class=\"cm-variable cm-def\">\\'http://www.example.com/ns/my\\':fn</span> (<span class=\"cm-variable\">$a</span> <span class=\"cm-keyword\">as</span> <span class=\"cm-atom\">xs:integer</span>) <span class=\"cm-keyword\">as</span> <span class=\"cm-atom\">xs:integer</span> {   <span class=\"cm-variable\">$a</span> <span class=\"cm-keyword\">+</span> <span class=\"cm-atom\">2</span>}<span class=\"cm-word\">;</span><span class=\"cm-tag\">&lt;out&gt;</span>{<span class=\"cm-variable cm-def\">\\'http://www.example.com/ns/my\\':fn</span>(<span class=\"cm-atom\">12</span>)}<span class=\"cm-tag\">&lt;/out&gt;</span>';\n\n    $(\"#sandbox\").html('<textarea id=\"editor\">' + input + '</textarea>');\n    var editor = CodeMirror.fromTextArea($(\"#editor\")[0]);\n    var result = $(\".CodeMirror-lines div div pre\")[0].innerHTML;\n\n     equal(result, expected);\n     $(\"#editor\").html(\"\");\n  });\n\n});\n\n\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/xquery/test/testProcessingInstructions.js",
    "content": "$(document).ready(function(){\n  module(\"testProcessingInstructions\");\n  test(\"testProcessingInstructions\", function() {\n    expect(1);\n\n    var input = 'data(<?target content?>) instance of xs:string';\n    var expected = '<span class=\"cm-variable cm-def\">data</span>(<span class=\"cm-comment cm-meta\">&lt;?target content?&gt;</span>) <span class=\"cm-keyword\">instance</span> <span class=\"cm-keyword\">of</span> <span class=\"cm-atom\">xs:string</span>';\n\n    $(\"#sandbox\").html('<textarea id=\"editor\">' + input + '</textarea>');\n    var editor = CodeMirror.fromTextArea($(\"#editor\")[0]);\n    var result = $(\".CodeMirror-lines div div pre\")[0].innerHTML;\n\n     equal(result, expected);\n     $(\"#editor\").html(\"\");\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/xquery/test/testQuotes.js",
    "content": "  $(document).ready(function(){\n    module(\"testQuoteEscape\");\n    test(\"testQuoteEscapeDouble\", function() {\n      expect(1);\n\n      var input = 'let $rootfolder := \"c:\\\\builds\\\\winnt\\\\HEAD\\\\qa\\\\scripts\\\\\"\\\nlet $keysfolder := concat($rootfolder, \"keys\\\\\")\\\nreturn\\\n$keysfolder';\n      var expected = '<span class=\"cm-keyword\">let</span> <span class=\"cm-variable\">$rootfolder</span> <span class=\"cm-keyword\">:=</span> <span class=\"cm-string\">\"c:\\\\builds\\\\winnt\\\\HEAD\\\\qa\\\\scripts\\\\\"</span><span class=\"cm-keyword\">let</span> <span class=\"cm-variable\">$keysfolder</span> <span class=\"cm-keyword\">:=</span> <span class=\"cm-variable cm-def\">concat</span>(<span class=\"cm-variable\">$rootfolder</span>, <span class=\"cm-string\">\"keys\\\\\"</span>)<span class=\"cm-word\">return$keysfolder</span>';\n\n      $(\"#sandbox\").html('<textarea id=\"editor\">' + input + '</textarea>');\n      var editor = CodeMirror.fromTextArea($(\"#editor\")[0]);\n      var result = $(\".CodeMirror-lines div div pre\")[0].innerHTML;\n\n       equal(result, expected);\n       $(\"#editor\").html(\"\");\n    });\n  });\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/xquery/xquery.js",
    "content": "/*\nCopyright (C) 2011 by MarkLogic Corporation\nAuthor: Mike Brevoort <mike@brevoort.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\nCodeMirror.defineMode(\"xquery\", function(config, parserConfig) {\n\n  // The keywords object is set to the result of this self executing\n  // function. Each keyword is a property of the keywords object whose\n  // value is {type: atype, style: astyle}\n  var keywords = function(){\n    // conveinence functions used to build keywords object\n    function kw(type) {return {type: type, style: \"keyword\"};}\n    var A = kw(\"keyword a\")\n      , B = kw(\"keyword b\")\n      , C = kw(\"keyword c\")\n      , operator = kw(\"operator\")\n      , atom = {type: \"atom\", style: \"atom\"}\n      , punctuation = {type: \"punctuation\", style: \"\"}\n      , qualifier = {type: \"axis_specifier\", style: \"qualifier\"};\n    \n    // kwObj is what is return from this function at the end\n    var kwObj = {\n      'if': A, 'switch': A, 'while': A, 'for': A,\n      'else': B, 'then': B, 'try': B, 'finally': B, 'catch': B,\n      'element': C, 'attribute': C, 'let': C, 'implements': C, 'import': C, 'module': C, 'namespace': C, \n      'return': C, 'super': C, 'this': C, 'throws': C, 'where': C, 'private': C,      \n      ',': punctuation,\n      'null': atom, 'fn:false()': atom, 'fn:true()': atom\n    };\n    \n    // a list of 'basic' keywords. For each add a property to kwObj with the value of \n    // {type: basic[i], style: \"keyword\"} e.g. 'after' --> {type: \"after\", style: \"keyword\"}\n    var basic = ['after','ancestor','ancestor-or-self','and','as','ascending','assert','attribute','before',\n    'by','case','cast','child','comment','declare','default','define','descendant','descendant-or-self',\n    'descending','document','document-node','element','else','eq','every','except','external','following',\n    'following-sibling','follows','for','function','if','import','in','instance','intersect','item',\n    'let','module','namespace','node','node','of','only','or','order','parent','precedes','preceding',\n    'preceding-sibling','processing-instruction','ref','return','returns','satisfies','schema','schema-element',\n    'self','some','sortby','stable','text','then','to','treat','typeswitch','union','variable','version','where',\n    'xquery', 'empty-sequence'];\n    for(var i=0, l=basic.length; i < l; i++) { kwObj[basic[i]] = kw(basic[i])};\n    \n    // a list of types. For each add a property to kwObj with the value of \n    // {type: \"atom\", style: \"atom\"}\n    var types = ['xs:string', 'xs:float', 'xs:decimal', 'xs:double', 'xs:integer', 'xs:boolean', 'xs:date', 'xs:dateTime', \n    'xs:time', 'xs:duration', 'xs:dayTimeDuration', 'xs:time', 'xs:yearMonthDuration', 'numeric', 'xs:hexBinary', \n    'xs:base64Binary', 'xs:anyURI', 'xs:QName', 'xs:byte','xs:boolean','xs:anyURI','xf:yearMonthDuration'];\n    for(var i=0, l=types.length; i < l; i++) { kwObj[types[i]] = atom;};\n    \n    // each operator will add a property to kwObj with value of {type: \"operator\", style: \"keyword\"}\n    var operators = ['eq', 'ne', 'lt', 'le', 'gt', 'ge', ':=', '=', '>', '>=', '<', '<=', '.', '|', '?', 'and', 'or', 'div', 'idiv', 'mod', '*', '/', '+', '-'];\n    for(var i=0, l=operators.length; i < l; i++) { kwObj[operators[i]] = operator;};\n    \n    // each axis_specifiers will add a property to kwObj with value of {type: \"axis_specifier\", style: \"qualifier\"}\n    var axis_specifiers = [\"self::\", \"attribute::\", \"child::\", \"descendant::\", \"descendant-or-self::\", \"parent::\", \n    \"ancestor::\", \"ancestor-or-self::\", \"following::\", \"preceding::\", \"following-sibling::\", \"preceding-sibling::\"];\n    for(var i=0, l=axis_specifiers.length; i < l; i++) { kwObj[axis_specifiers[i]] = qualifier; };\n\n    return kwObj;\n  }();\n\n  // Used as scratch variables to communicate multiple values without\n  // consing up tons of objects.\n  var type, content;\n  \n  function ret(tp, style, cont) {\n    type = tp; content = cont;\n    return style;\n  }\n  \n  function chain(stream, state, f) {\n    state.tokenize = f;\n    return f(stream, state);\n  }\n  \n  // the primary mode tokenizer\n  function tokenBase(stream, state) {\n    var ch = stream.next(), \n        mightBeFunction = false,\n        isEQName = isEQNameAhead(stream);\n    \n    // an XML tag (if not in some sub, chained tokenizer)\n    if (ch == \"<\") {\n      if(stream.match(\"!--\", true))\n        return chain(stream, state, tokenXMLComment);\n        \n      if(stream.match(\"![CDATA\", false)) {\n        state.tokenize = tokenCDATA;\n        return ret(\"tag\", \"tag\");\n      }\n      \n      if(stream.match(\"?\", false)) {\n        return chain(stream, state, tokenPreProcessing);\n      }\n      \n      var isclose = stream.eat(\"/\");\n      stream.eatSpace();\n      var tagName = \"\", c;\n      while ((c = stream.eat(/[^\\s\\u00a0=<>\\\"\\'\\/?]/))) tagName += c;\n      \n      return chain(stream, state, tokenTag(tagName, isclose));\n    }\n    // start code block\n    else if(ch == \"{\") {\n      pushStateStack(state,{ type: \"codeblock\"});\n      return ret(\"\", \"\");\n    }\n    // end code block\n    else if(ch == \"}\") {\n      popStateStack(state);\n      return ret(\"\", \"\");\n    }\n    // if we're in an XML block\n    else if(isInXmlBlock(state)) {\n      if(ch == \">\")\n        return ret(\"tag\", \"tag\");\n      else if(ch == \"/\" && stream.eat(\">\")) {\n        popStateStack(state);\n        return ret(\"tag\", \"tag\");\n      }\n      else  \n        return ret(\"word\", \"word\");\n    }\n    // if a number\n    else if (/\\d/.test(ch)) {\n      stream.match(/^\\d*(?:\\.\\d*)?(?:E[+\\-]?\\d+)?/);\n      return ret(\"number\", \"atom\");\n    }\n    // comment start\n    else if (ch === \"(\" && stream.eat(\":\")) {\n      pushStateStack(state, { type: \"comment\"});\n      return chain(stream, state, tokenComment);\n    }\n    // quoted string\n    else if (  !isEQName && (ch === '\"' || ch === \"'\"))\n      return chain(stream, state, tokenString(ch));\n    // variable\n    else if(ch === \"$\") {\n      return chain(stream, state, tokenVariable);\n    }\n    // assignment\n    else if(ch ===\":\" && stream.eat(\"=\")) {\n      return ret(\"operator\", \"keyword\");\n    }\n    // open paren\n    else if(ch === \"(\") {\n      pushStateStack(state, { type: \"paren\"});\n      return ret(\"\", \"\");\n    }\n    // close paren\n    else if(ch === \")\") {\n      popStateStack(state);\n      return ret(\"\", \"\");\n    }\n    // open paren\n    else if(ch === \"[\") {\n      pushStateStack(state, { type: \"bracket\"});\n      return ret(\"\", \"\");\n    }\n    // close paren\n    else if(ch === \"]\") {\n      popStateStack(state);\n      return ret(\"\", \"\");\n    }\n    else {\n      var known = keywords.propertyIsEnumerable(ch) && keywords[ch];\n\n      // if there's a EQName ahead, consume the rest of the string portion, it's likely a function\n      if(isEQName && ch === '\\\"') while(stream.next() !== '\"'){}\n      if(isEQName && ch === '\\'') while(stream.next() !== '\\''){}\n      \n      // gobble up a word if the character is not known\n      if(!known) stream.eatWhile(/[\\w\\$_-]/);\n      \n      // gobble a colon in the case that is a lib func type call fn:doc\n      var foundColon = stream.eat(\":\")\n      \n      // if there's not a second colon, gobble another word. Otherwise, it's probably an axis specifier\n      // which should get matched as a keyword\n      if(!stream.eat(\":\") && foundColon) {\n        stream.eatWhile(/[\\w\\$_-]/);\n      }\n      // if the next non whitespace character is an open paren, this is probably a function (if not a keyword of other sort)\n      if(stream.match(/^[ \\t]*\\(/, false)) {\n        mightBeFunction = true;\n      }\n      // is the word a keyword?\n      var word = stream.current();\n      known = keywords.propertyIsEnumerable(word) && keywords[word];\n      \n      // if we think it's a function call but not yet known, \n      // set style to variable for now for lack of something better\n      if(mightBeFunction && !known) known = {type: \"function_call\", style: \"variable def\"};\n      \n      // if the previous word was element, attribute, axis specifier, this word should be the name of that\n      if(isInXmlConstructor(state)) {\n        popStateStack(state);\n        return ret(\"word\", \"word\", word);\n      }\n      // as previously checked, if the word is element,attribute, axis specifier, call it an \"xmlconstructor\" and \n      // push the stack so we know to look for it on the next word\n      if(word == \"element\" || word == \"attribute\" || known.type == \"axis_specifier\") pushStateStack(state, {type: \"xmlconstructor\"});\n      \n      // if the word is known, return the details of that else just call this a generic 'word'\n      return known ? ret(known.type, known.style, word) :\n                     ret(\"word\", \"word\", word);\n    }\n  }\n\n  // handle comments, including nested \n  function tokenComment(stream, state) {\n    var maybeEnd = false, maybeNested = false, nestedCount = 0, ch;\n    while (ch = stream.next()) {\n      if (ch == \")\" && maybeEnd) {\n        if(nestedCount > 0)\n          nestedCount--;\n        else {\n          popStateStack(state);\n          break;\n        }\n      }\n      else if(ch == \":\" && maybeNested) {\n        nestedCount++;\n      }\n      maybeEnd = (ch == \":\");\n      maybeNested = (ch == \"(\");\n    }\n    \n    return ret(\"comment\", \"comment\");\n  }\n\n  // tokenizer for string literals\n  // optionally pass a tokenizer function to set state.tokenize back to when finished\n  function tokenString(quote, f) {\n    return function(stream, state) {\n      var ch;\n\n      if(isInString(state) && stream.current() == quote) {\n        popStateStack(state);\n        if(f) state.tokenize = f;\n        return ret(\"string\", \"string\");\n      }\n\n      pushStateStack(state, { type: \"string\", name: quote, tokenize: tokenString(quote, f) });\n\n      // if we're in a string and in an XML block, allow an embedded code block\n      if(stream.match(\"{\", false) && isInXmlAttributeBlock(state)) {\n        state.tokenize = tokenBase;\n        return ret(\"string\", \"string\"); \n      }\n\n      \n      while (ch = stream.next()) {\n        if (ch ==  quote) {\n          popStateStack(state);\n          if(f) state.tokenize = f;\n          break;\n        }\n        else {\n          // if we're in a string and in an XML block, allow an embedded code block in an attribute\n          if(stream.match(\"{\", false) && isInXmlAttributeBlock(state)) {\n            state.tokenize = tokenBase;\n            return ret(\"string\", \"string\"); \n          }\n\n        }\n      }\n      \n      return ret(\"string\", \"string\");\n    };\n  }\n  \n  // tokenizer for variables\n  function tokenVariable(stream, state) {\n    var isVariableChar = /[\\w\\$_-]/;\n\n    // a variable may start with a quoted EQName so if the next character is quote, consume to the next quote\n    if(stream.eat(\"\\\"\")) {\n      while(stream.next() !== '\\\"'){};\n      stream.eat(\":\");\n    } else {\n      stream.eatWhile(isVariableChar);\n      if(!stream.match(\":=\", false)) stream.eat(\":\");\n    }\n    stream.eatWhile(isVariableChar);\n    state.tokenize = tokenBase;\n    return ret(\"variable\", \"variable\");\n  }\n  \n  // tokenizer for XML tags\n  function tokenTag(name, isclose) {\n    return function(stream, state) {\n      stream.eatSpace();\n      if(isclose && stream.eat(\">\")) {\n        popStateStack(state);\n        state.tokenize = tokenBase;\n        return ret(\"tag\", \"tag\");\n      }\n      // self closing tag without attributes?\n      if(!stream.eat(\"/\"))\n        pushStateStack(state, { type: \"tag\", name: name, tokenize: tokenBase});\n      if(!stream.eat(\">\")) {\n        state.tokenize = tokenAttribute;\n        return ret(\"tag\", \"tag\");\n      }\n      else {\n        state.tokenize = tokenBase;        \n      }\n      return ret(\"tag\", \"tag\");\n    }\n  }\n\n  // tokenizer for XML attributes\n  function tokenAttribute(stream, state) {\n    var ch = stream.next();\n    \n    if(ch == \"/\" && stream.eat(\">\")) {\n      if(isInXmlAttributeBlock(state)) popStateStack(state);\n      if(isInXmlBlock(state)) popStateStack(state);\n      return ret(\"tag\", \"tag\");\n    }\n    if(ch == \">\") {\n      if(isInXmlAttributeBlock(state)) popStateStack(state);\n      return ret(\"tag\", \"tag\");\n    }\n    if(ch == \"=\")\n      return ret(\"\", \"\");\n    // quoted string\n    if (ch == '\"' || ch == \"'\")\n      return chain(stream, state, tokenString(ch, tokenAttribute));\n\n    if(!isInXmlAttributeBlock(state)) \n      pushStateStack(state, { type: \"attribute\", name: name, tokenize: tokenAttribute});\n\n    stream.eat(/[a-zA-Z_:]/);\n    stream.eatWhile(/[-a-zA-Z0-9_:.]/);\n    stream.eatSpace();\n\n    // the case where the attribute has not value and the tag was closed\n    if(stream.match(\">\", false) || stream.match(\"/\", false)) {\n      popStateStack(state);\n      state.tokenize = tokenBase;      \n    }\n\n    return ret(\"attribute\", \"attribute\");\n  }\n  \n  // handle comments, including nested \n  function tokenXMLComment(stream, state) {\n    while (ch = stream.next()) {\n      if (ch == \"-\" && stream.match(\"->\", true)) {\n        state.tokenize = tokenBase;        \n        return ret(\"comment\", \"comment\");\n      }\n    }\n  }\n\n\n  // handle CDATA\n  function tokenCDATA(stream, state) {\n    while (ch = stream.next()) {\n      if (ch == \"]\" && stream.match(\"]\", true)) {\n        state.tokenize = tokenBase;        \n        return ret(\"comment\", \"comment\");\n      }\n    }\n  }\n\n  // handle preprocessing instructions\n  function tokenPreProcessing(stream, state) {\n    while (ch = stream.next()) {\n      if (ch == \"?\" && stream.match(\">\", true)) {\n        state.tokenize = tokenBase;        \n        return ret(\"comment\", \"comment meta\");\n      }\n    }\n  }\n  \n  \n  // functions to test the current context of the state\n  function isInXmlBlock(state) { return isIn(state, \"tag\"); }\n  function isInXmlAttributeBlock(state) { return isIn(state, \"attribute\"); }\n  function isInCodeBlock(state) { return isIn(state, \"codeblock\"); }\n  function isInXmlConstructor(state) { return isIn(state, \"xmlconstructor\"); }\n  function isInString(state) { return isIn(state, \"string\"); }\n\n  function isEQNameAhead(stream) { \n    // assume we've already eaten a quote (\")\n    if(stream.current() === '\"')\n      return stream.match(/^[^\\\"]+\\\"\\:/, false);\n    else if(stream.current() === '\\'')\n      return stream.match(/^[^\\\"]+\\'\\:/, false);\n    else\n      return false;\n  }\n  \n  function isIn(state, type) {\n    return (state.stack.length && state.stack[state.stack.length - 1].type == type);    \n  }\n  \n  function pushStateStack(state, newState) {\n    state.stack.push(newState);\n  }\n  \n  function popStateStack(state) {\n    var popped = state.stack.pop();\n    var reinstateTokenize = state.stack.length && state.stack[state.stack.length-1].tokenize\n    state.tokenize = reinstateTokenize || tokenBase;\n  }\n  \n  // the interface for the mode API\n  return {\n    startState: function(basecolumn) {\n      return {\n        tokenize: tokenBase,\n        cc: [],\n        stack: []\n      };\n    },\n\n    token: function(stream, state) {\n      if (stream.eatSpace()) return null;\n      var style = state.tokenize(stream, state);\n      return style;\n    }\n  };\n\n});\n\nCodeMirror.defineMIME(\"application/xquery\", \"xquery\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/yaml/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: YAML mode</title>\n    <link rel=\"stylesheet\" href=\"../../lib/codemirror.css\">\n    <script src=\"../../lib/codemirror.js\"></script>\n    <script src=\"yaml.js\"></script>\n    <style>.CodeMirror { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; }</style>\n    <link rel=\"stylesheet\" href=\"../../doc/docs.css\">\n  </head>\n  <body>\n    <h1>CodeMirror: YAML mode</h1>\n    <form><textarea id=\"code\" name=\"code\">\n--- # Favorite movies\n- Casablanca\n- North by Northwest\n- The Man Who Wasn't There\n--- # Shopping list\n[milk, pumpkin pie, eggs, juice]\n--- # Indented Blocks, common in YAML data files, use indentation and new lines to separate the key: value pairs\n  name: John Smith\n  age: 33\n--- # Inline Blocks, common in YAML data streams, use commas to separate the key: value pairs between braces\n{name: John Smith, age: 33}\n---\nreceipt:     Oz-Ware Purchase Invoice\ndate:        2007-08-06\ncustomer:\n    given:   Dorothy\n    family:  Gale\n\nitems:\n    - part_no:   A4786\n      descrip:   Water Bucket (Filled)\n      price:     1.47\n      quantity:  4\n\n    - part_no:   E1628\n      descrip:   High Heeled \"Ruby\" Slippers\n      size:       8\n      price:     100.27\n      quantity:  1\n\nbill-to:  &id001\n    street: |\n            123 Tornado Alley\n            Suite 16\n    city:   East Centerville\n    state:  KS\n\nship-to:  *id001\n\nspecialDelivery:  >\n    Follow the Yellow Brick\n    Road to the Emerald City.\n    Pay no attention to the\n    man behind the curtain.\n...\n</textarea></form>\n    <script>\n      var editor = CodeMirror.fromTextArea(document.getElementById(\"code\"), {});\n    </script>\n\n    <p><strong>MIME types defined:</strong> <code>text/x-yaml</code>.</p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/mode/yaml/yaml.js",
    "content": "CodeMirror.defineMode(\"yaml\", function() {\n\t\n\tvar cons = ['true', 'false', 'on', 'off', 'yes', 'no'];\n\tvar keywordRegex = new RegExp(\"\\\\b((\"+cons.join(\")|(\")+\"))$\", 'i');\n\t\n\treturn {\n\t\ttoken: function(stream, state) {\n\t\t\tvar ch = stream.peek();\n\t\t\tvar esc = state.escaped;\n\t\t\tstate.escaped = false;\n\t\t\t/* comments */\n\t\t\tif (ch == \"#\") { stream.skipToEnd(); return \"comment\"; }\n\t\t\tif (state.literal && stream.indentation() > state.keyCol) {\n\t\t\t\tstream.skipToEnd(); return \"string\";\n\t\t\t} else if (state.literal) { state.literal = false; }\n\t\t\tif (stream.sol()) {\n\t\t\t\tstate.keyCol = 0;\n\t\t\t\tstate.pair = false;\n\t\t\t\tstate.pairStart = false;\n\t\t\t\t/* document start */\n\t\t\t\tif(stream.match(/---/)) { return \"def\"; }\n\t\t\t\t/* document end */\n\t\t\t\tif (stream.match(/\\.\\.\\./)) { return \"def\"; }\n\t\t\t\t/* array list item */\n\t\t\t\tif (stream.match(/\\s*-\\s+/)) { return 'meta'; }\n\t\t\t}\n\t\t\t/* pairs (associative arrays) -> key */\n\t\t\tif (!state.pair && stream.match(/^\\s*([a-z0-9\\._-])+(?=\\s*:)/i)) {\n\t\t\t\tstate.pair = true;\n\t\t\t\tstate.keyCol = stream.indentation();\n\t\t\t\treturn \"atom\";\n\t\t\t}\n\t\t\tif (state.pair && stream.match(/^:\\s*/)) { state.pairStart = true; return 'meta'; }\n\t\t\t\n\t\t\t/* inline pairs/lists */\n\t\t\tif (stream.match(/^(\\{|\\}|\\[|\\])/)) {\n\t\t\t\tif (ch == '{')\n\t\t\t\t\tstate.inlinePairs++;\n\t\t\t\telse if (ch == '}')\n\t\t\t\t\tstate.inlinePairs--;\n\t\t\t\telse if (ch == '[')\n\t\t\t\t\tstate.inlineList++;\n\t\t\t\telse\n\t\t\t\t\tstate.inlineList--;\n\t\t\t\treturn 'meta';\n\t\t\t}\n\t\t\t\n\t\t\t/* list seperator */\n\t\t\tif (state.inlineList > 0 && !esc && ch == ',') {\n\t\t\t\tstream.next();\n\t\t\t\treturn 'meta';\n\t\t\t}\n\t\t\t/* pairs seperator */\n\t\t\tif (state.inlinePairs > 0 && !esc && ch == ',') {\n\t\t\t\tstate.keyCol = 0;\n\t\t\t\tstate.pair = false;\n\t\t\t\tstate.pairStart = false;\n\t\t\t\tstream.next();\n\t\t\t\treturn 'meta';\n\t\t\t}\n\t\t\t\n\t\t\t/* start of value of a pair */\n\t\t\tif (state.pairStart) {\n\t\t\t\t/* block literals */\n\t\t\t\tif (stream.match(/^\\s*(\\||\\>)\\s*/)) { state.literal = true; return 'meta'; };\n\t\t\t\t/* references */\n\t\t\t\tif (stream.match(/^\\s*(\\&|\\*)[a-z0-9\\._-]+\\b/i)) { return 'variable-2'; }\n\t\t\t\t/* numbers */\n\t\t\t\tif (state.inlinePairs == 0 && stream.match(/^\\s*-?[0-9\\.\\,]+\\s?$/)) { return 'number'; }\n\t\t\t\tif (state.inlinePairs > 0 && stream.match(/^\\s*-?[0-9\\.\\,]+\\s?(?=(,|}))/)) { return 'number'; }\n\t\t\t\t/* keywords */\n\t\t\t\tif (stream.match(keywordRegex)) { return 'keyword'; }\n\t\t\t}\n\n\t\t\t/* nothing found, continue */\n\t\t\tstate.pairStart = false;\n\t\t\tstate.escaped = (ch == '\\\\');\n\t\t\tstream.next();\n\t\t\treturn null;\n\t\t},\n\t\tstartState: function() {\n\t\t\treturn {\n\t\t\t\tpair: false,\n\t\t\t\tpairStart: false,\n\t\t\t\tkeyCol: 0,\n\t\t\t\tinlinePairs: 0,\n\t\t\t\tinlineList: 0,\n\t\t\t\tliteral: false,\n\t\t\t\tescaped: false\n\t\t\t};\n\t\t}\n\t};\n});\n\nCodeMirror.defineMIME(\"text/x-yaml\", \"yaml\");\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/test/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>CodeMirror: Test Suite</title>\n    <link rel=\"stylesheet\" href=\"../lib/codemirror.css\">\n    <script src=\"../lib/codemirror.js\"></script>\n    <script src=\"../mode/javascript/javascript.js\"></script>\n\n    <style type=\"text/css\">\n      .ok {color: #0e0;}\n      .failure {color: #e00;}\n      .error {color: #c90;}\n    </style>\n  </head>\n  <body>\n    <h1>CodeMirror: Test Suite</h1>\n\n    <p>A limited set of programmatic sanity tests for CodeMirror.</p>\n\n    <pre id=output></pre>\n\n    <div style=\"visibility: hidden\" id=testground>\n      <form><textarea id=\"code\" name=\"code\"></textarea><input type=submit value=ok name=submit></form>\n    </div>\n\n    <script src=\"test.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/test/mode_test.css",
    "content": ".mt-output .mt-token {\n  border: 1px solid #ddd;\n  white-space: pre;\n  font-family: \"Consolas\", monospace;\n  text-align: center;\n}\n\n.mt-output .mt-style {\n  font-size: x-small;\n}\n\n.mt-test {\n  border-left: 10px solid #fff;\n}\n\n.mt-pass {\n  border-left: 10px solid #cfc;\n}\n\n.mt-fail {\n  border-left: 10px solid #fcc;\n}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/test/mode_test.js",
    "content": "/**\n * Helper to test CodeMirror highlighting modes. It pretty prints output of the\n * highlighter and can check against expected styles.\n *\n * See test.html in the stex mode for examples.\n */\nModeTest = {};\n\nModeTest.modeOptions = {};\nModeTest.modeName = CodeMirror.defaults.mode;\n\n/* keep track of results for printSummary */\nModeTest.tests = 0;\nModeTest.passes = 0;\n\n/**\n * Run a test; prettyprints the results using document.write().\n *\n * @param string to highlight\n *\n * @param style[i] expected style of the i'th token in string\n *\n * @param token[i] expected value for the i'th token in string\n */\nModeTest.test = function() {\n  ModeTest.tests += 1;\n\n  var mode = CodeMirror.getMode(ModeTest.modeOptions, ModeTest.modeName);\n\n  if (arguments.length < 1) {\n    throw \"must have text for test\";\n  }\n  if (arguments.length % 2 != 1) {\n    throw \"must have text for test plus expected (style, token) pairs\";\n  }\n\n  var text = arguments[0];\n  var expectedOutput = [];\n  for (var i = 1; i < arguments.length; i += 2) {\n    expectedOutput.push([arguments[i],arguments[i + 1]]);\n  }\n\n  var observedOutput = ModeTest.highlight(text, mode)\n\n  var pass, passStyle = \"\";\n  if (expectedOutput.length > 0) {\n    pass = ModeTest.highlightOutputsEqual(expectedOutput, observedOutput);\n    passStyle = pass ? 'mt-pass' : 'mt-fail';\n    ModeTest.passes += pass ? 1 : 0;\n  }\n\n  var s = '';\n  s += '<div class=\"mt-test ' + passStyle + '\">';\n  s +=   '<pre>' + ModeTest.htmlEscape(text) + '</pre>';\n  s +=   '<div class=\"cm-s-default\">';\n  if (pass || expectedOutput.length == 0) {\n    s +=   ModeTest.prettyPrintOutputTable(observedOutput);\n  } else {\n    s += 'expected:';\n    s +=   ModeTest.prettyPrintOutputTable(expectedOutput);\n    s += 'observed:';\n    s +=   ModeTest.prettyPrintOutputTable(observedOutput);\n  }\n  s +=   '</div>';\n  s += '</div>';\n  document.write(s);\n}\n\n/**\n * Emulation of CodeMirror's internal highlight routine for testing. Multi-line\n * input is supported.\n *\n * @param string to highlight\n *\n * @param mode the mode that will do the actual highlighting\n *\n * @return array of [style, token] pairs\n */\nModeTest.highlight = function(string, mode) {\n  var state = mode.startState()\n\n  var lines = string.replace(/\\r\\n/g,'\\n').split('\\n');\n  var output = [];\n  for (var i = 0; i < lines.length; ++i) {\n    var line = lines[i];\n    var stream = new CodeMirror.StringStream(line);\n    if (line == \"\" && mode.blankLine) mode.blankLine(state);\n    while (!stream.eol()) {\n      var style = mode.token(stream, state);\n      var substr = line.slice(stream.start, stream.pos);\n      output.push([style, substr]);\n      stream.start = stream.pos;\n    }\n  }\n\n  return output;\n}\n\n/**\n * Compare two arrays of output from ModeTest.highlight.\n *\n * @param o1 array of [style, token] pairs\n *\n * @param o2 array of [style, token] pairs\n *\n * @return boolean; true iff outputs equal\n */\nModeTest.highlightOutputsEqual = function(o1, o2) {\n  var eq = (o1.length == o2.length);\n  if (eq) {\n    for (var j in o1) {\n      eq = eq &&\n        o1[j].length == 2 && o1[j][0] == o2[j][0] && o1[j][1] == o2[j][1];\n    }\n  }\n  return eq;\n}\n\n/**\n * Print tokens and corresponding styles in a table. Spaces in the token are\n * replaced with 'interpunct' dots (&middot;).\n *\n * @param output array of [style, token] pairs\n *\n * @return html string\n */\nModeTest.prettyPrintOutputTable = function(output) {\n  var s = '<table class=\"mt-output\">';\n  s += '<tr>';\n  for (var i = 0; i < output.length; ++i) {\n    var token = output[i];\n    s +=\n      '<td class=\"mt-token\">' +\n        '<span class=\"cm-' + token[0] + '\">' +\n          ModeTest.htmlEscape(token[1]).replace(/ /g,'&middot;') +\n        '</span>' +\n      '</td>';\n  }\n  s += '</tr><tr>';\n  for (var i = 0; i < output.length; ++i) {\n    var token = output[i];\n    s +=\n      '<td class=\"mt-style\"><span>' + token[0] + '</span></td>';\n  }\n  s += '</table>';\n  return s;\n}\n\n/**\n * Print how many tests have run so far and how many of those passed.\n */\nModeTest.printSummary = function() {\n  document.write(ModeTest.passes + ' passes for ' + ModeTest.tests + ' tests');\n}\n\n/**\n * Basic HTML escaping.\n */\nModeTest.htmlEscape = function(str) {\n  str = str.toString();\n  return str.replace(/[<&]/g,\n      function(str) {return str == \"&\" ? \"&amp;\" : \"&lt;\";});\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/test/test.js",
    "content": "var tests = [];\n\ntest(\"fromTextArea\", function() {\n  var te = document.getElementById(\"code\");\n  te.value = \"CONTENT\";\n  var cm = CodeMirror.fromTextArea(te);\n  is(!te.offsetHeight);\n  eq(cm.getValue(), \"CONTENT\");\n  cm.setValue(\"foo\\nbar\");\n  eq(cm.getValue(), \"foo\\nbar\");\n  cm.save();\n  is(/^foo\\r?\\nbar$/.test(te.value));\n  cm.setValue(\"xxx\");\n  cm.toTextArea();\n  is(te.offsetHeight);\n  eq(te.value, \"xxx\");\n});\n\ntestCM(\"getRange\", function(cm) {\n  eq(cm.getLine(0), \"1234\");\n  eq(cm.getLine(1), \"5678\");\n  eq(cm.getLine(2), null);\n  eq(cm.getLine(-1), null);\n  eq(cm.getRange({line: 0, ch: 0}, {line: 0, ch: 3}), \"123\");\n  eq(cm.getRange({line: 0, ch: -1}, {line: 0, ch: 200}), \"1234\");\n  eq(cm.getRange({line: 0, ch: 2}, {line: 1, ch: 2}), \"34\\n56\");\n  eq(cm.getRange({line: 1, ch: 2}, {line: 100, ch: 0}), \"78\");\n}, {value: \"1234\\n5678\"});\n\ntestCM(\"replaceRange\", function(cm) {\n  eq(cm.getValue(), \"\");\n  cm.replaceRange(\"foo\\n\", {line: 0, ch: 0});\n  eq(cm.getValue(), \"foo\\n\");\n  cm.replaceRange(\"a\\nb\", {line: 0, ch: 1});\n  eq(cm.getValue(), \"fa\\nboo\\n\");\n  eq(cm.lineCount(), 3);\n  cm.replaceRange(\"xyzzy\", {line: 0, ch: 0}, {line: 1, ch: 1});\n  eq(cm.getValue(), \"xyzzyoo\\n\");\n  cm.replaceRange(\"abc\", {line: 0, ch: 0}, {line: 10, ch: 0});\n  eq(cm.getValue(), \"abc\");\n  eq(cm.lineCount(), 1);\n});\n\ntestCM(\"selection\", function(cm) {\n  cm.setSelection({line: 0, ch: 4}, {line: 2, ch: 2});\n  is(cm.somethingSelected());\n  eq(cm.getSelection(), \"11\\n222222\\n33\");\n  eqPos(cm.getCursor(false), {line: 2, ch: 2});\n  eqPos(cm.getCursor(true), {line: 0, ch: 4});\n  cm.setSelection({line: 1, ch: 0});\n  is(!cm.somethingSelected());\n  eq(cm.getSelection(), \"\");\n  eqPos(cm.getCursor(true), {line: 1, ch: 0});\n  cm.replaceSelection(\"abc\");\n  eq(cm.getSelection(), \"abc\");\n  eq(cm.getValue(), \"111111\\nabc222222\\n333333\");\n  cm.replaceSelection(\"def\", \"end\");\n  eq(cm.getSelection(), \"\");\n  eqPos(cm.getCursor(true), {line: 1, ch: 3});\n  cm.setCursor({line: 2, ch: 1});\n  eqPos(cm.getCursor(true), {line: 2, ch: 1});\n  cm.setCursor(1, 2);\n  eqPos(cm.getCursor(true), {line: 1, ch: 2});\n}, {value: \"111111\\n222222\\n333333\"});\n\ntestCM(\"lines\", function(cm) {\n  eq(cm.getLine(0), \"111111\");\n  eq(cm.getLine(1), \"222222\");\n  eq(cm.getLine(-1), null);\n  cm.removeLine(1);\n  cm.setLine(1, \"abc\");\n  eq(cm.getValue(), \"111111\\nabc\");\n}, {value: \"111111\\n222222\\n333333\"});\n\ntestCM(\"indent\", function(cm) {\n  cm.indentLine(1);\n  eq(cm.getLine(1), \"   blah();\");\n  cm.setOption(\"indentUnit\", 8);\n  cm.indentLine(1);\n  eq(cm.getLine(1), \"\\tblah();\");\n}, {value: \"if (x) {\\nblah();\\n}\", indentUnit: 3, indentWithTabs: true, tabSize: 8});\n\ntest(\"defaults\", function() {\n  var olddefaults = CodeMirror.defaults, defs = CodeMirror.defaults = {};\n  for (var opt in olddefaults) defs[opt] = olddefaults[opt];\n  defs.indentUnit = 5;\n  defs.value = \"uu\";\n  defs.enterMode = \"keep\";\n  defs.tabindex = 55;\n  var place = document.getElementById(\"testground\"), cm = CodeMirror(place);\n  try {\n    eq(cm.getOption(\"indentUnit\"), 5);\n    cm.setOption(\"indentUnit\", 10);\n    eq(defs.indentUnit, 5);\n    eq(cm.getValue(), \"uu\");\n    eq(cm.getOption(\"enterMode\"), \"keep\");\n    eq(cm.getInputField().tabIndex, 55);\n  }\n  finally {\n    CodeMirror.defaults = olddefaults;\n    place.removeChild(cm.getWrapperElement());\n  }\n});\n\ntestCM(\"lineInfo\", function(cm) {\n  eq(cm.lineInfo(-1), null);\n  var lh = cm.setMarker(1, \"FOO\", \"bar\");\n  var info = cm.lineInfo(1);\n  eq(info.text, \"222222\");\n  eq(info.markerText, \"FOO\");\n  eq(info.markerClass, \"bar\");\n  eq(info.line, 1);\n  eq(cm.lineInfo(2).markerText, null);\n  cm.clearMarker(lh);\n  eq(cm.lineInfo(1).markerText, null);\n}, {value: \"111111\\n222222\\n333333\"});\n\ntestCM(\"coords\", function(cm) {\n  var scroller = cm.getScrollerElement();\n  scroller.style.height = \"100px\";\n  var content = [];\n  for (var i = 0; i < 200; ++i) content.push(\"------------------------------\" + i);\n  cm.setValue(content.join(\"\\n\"));\n  var top = cm.charCoords({line: 0, ch: 0});\n  var bot = cm.charCoords({line: 200, ch: 30});\n  is(top.x < bot.x);\n  is(top.y < bot.y);\n  is(top.y < top.yBot);\n  cm.scrollTo(null, 100);\n  var top2 = cm.charCoords({line: 0, ch: 0});\n  is(top.y > top2.y);\n  eq(top.x, top2.x);\n});\n\ntestCM(\"coordsChar\", function(cm) {\n  var content = [];\n  for (var i = 0; i < 70; ++i) content.push(\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\");\n  cm.setValue(content.join(\"\\n\"));\n  for (var ch = 0; ch < 35; ch += 2) {\n    for (var line = 0; line < 70; line += 5) {\n      cm.setCursor(line, ch);\n      var coords = cm.charCoords({line: line, ch: ch});\n      var pos = cm.coordsChar({x: coords.x, y: coords.y + 1});\n      eq(pos.line, line);\n      eq(pos.ch, ch);\n    }\n  }\n});\n\ntestCM(\"posFromIndex\", function(cm) {\n  cm.setValue(\n    \"This function should\\n\" +\n    \"convert a zero based index\\n\" +\n    \"to line and ch.\"\n  );\n\n  var examples = [\n    { index: -1, line: 0, ch: 0  }, // <- Tests clipping\n    { index: 0,  line: 0, ch: 0  },\n    { index: 10, line: 0, ch: 10 },\n    { index: 39, line: 1, ch: 18 },\n    { index: 55, line: 2, ch: 7  },\n    { index: 63, line: 2, ch: 15 },\n    { index: 64, line: 2, ch: 15 }  // <- Tests clipping\n  ];\n\n  for (var i = 0; i < examples.length; i++) {\n    var example = examples[i];\n    var pos = cm.posFromIndex(example.index);\n    eq(pos.line, example.line);\n    eq(pos.ch, example.ch);\n    if (example.index >= 0 && example.index < 64)\n      eq(cm.indexFromPos(pos), example.index);\n  }  \n});\n\ntestCM(\"undo\", function(cm) {\n  cm.setLine(0, \"def\");\n  eq(cm.historySize().undo, 1);\n  cm.undo();\n  eq(cm.getValue(), \"abc\");\n  eq(cm.historySize().undo, 0);\n  eq(cm.historySize().redo, 1);\n  cm.redo();\n  eq(cm.getValue(), \"def\");\n  eq(cm.historySize().undo, 1);\n  eq(cm.historySize().redo, 0);\n  cm.setValue(\"1\\n\\n\\n2\");\n  cm.clearHistory();\n  eq(cm.historySize().undo, 0);\n  for (var i = 0; i < 20; ++i) {\n    cm.replaceRange(\"a\", {line: 0, ch: 0});\n    cm.replaceRange(\"b\", {line: 3, ch: 0});\n  }\n  eq(cm.historySize().undo, 40);\n  for (var i = 0; i < 40; ++i)\n    cm.undo();\n  eq(cm.historySize().redo, 40);\n  eq(cm.getValue(), \"1\\n\\n\\n2\");\n}, {value: \"abc\"});\n\ntestCM(\"undoMultiLine\", function(cm) {\n  cm.replaceRange(\"x\", {line:0, ch: 0});\n  cm.replaceRange(\"y\", {line:1, ch: 0});\n  cm.undo();\n  eq(cm.getValue(), \"abc\\ndef\\nghi\");\n  cm.replaceRange(\"y\", {line:1, ch: 0});\n  cm.replaceRange(\"x\", {line:0, ch: 0});\n  cm.undo();\n  eq(cm.getValue(), \"abc\\ndef\\nghi\");\n  cm.replaceRange(\"y\", {line:2, ch: 0});\n  cm.replaceRange(\"x\", {line:1, ch: 0});\n  cm.replaceRange(\"z\", {line:2, ch: 0});\n  cm.undo();\n  eq(cm.getValue(), \"abc\\ndef\\nghi\");\n}, {value: \"abc\\ndef\\nghi\"});\n\ntestCM(\"markTextSingleLine\", function(cm) {\n  forEach([{a: 0, b: 1, c: \"\", f: 2, t: 5},\n           {a: 0, b: 4, c: \"\", f: 0, t: 2},\n           {a: 1, b: 2, c: \"x\", f: 3, t: 6},\n           {a: 4, b: 5, c: \"\", f: 3, t: 5},\n           {a: 4, b: 5, c: \"xx\", f: 3, t: 7},\n           {a: 2, b: 5, c: \"\", f: 2, t: 3},\n           {a: 2, b: 5, c: \"abcd\", f: 6, t: 7},\n           {a: 2, b: 6, c: \"x\", f: null, t: null},\n           {a: 3, b: 6, c: \"\", f: null, t: null},\n           {a: 0, b: 9, c: \"hallo\", f: null, t: null},\n           {a: 4, b: 6, c: \"x\", f: 3, t: 4},\n           {a: 4, b: 8, c: \"\", f: 3, t: 4},\n           {a: 6, b: 6, c: \"a\", f: 3, t: 6},\n           {a: 8, b: 9, c: \"\", f: 3, t: 6}], function(test) {\n    cm.setValue(\"1234567890\");\n    var r = cm.markText({line: 0, ch: 3}, {line: 0, ch: 6}, \"foo\");\n    cm.replaceRange(test.c, {line: 0, ch: test.a}, {line: 0, ch: test.b});\n    var f = r.find();\n    eq(f.from && f.from.ch, test.f); eq(f.to && f.to.ch, test.t);\n  });\n});\n\ntestCM(\"markTextMultiLine\", function(cm) {\n  function p(v) { return v && {line: v[0], ch: v[1]}; }\n  forEach([{a: [0, 0], b: [0, 5], c: \"\", f: [0, 0], t: [2, 5]},\n           {a: [0, 1], b: [0, 10], c: \"\", f: [0, 1], t: [2, 5]},\n           {a: [0, 5], b: [0, 6], c: \"x\", f: [0, 6], t: [2, 5]},\n           {a: [0, 0], b: [1, 0], c: \"\", f: [0, 0], t: [1, 5]},\n           {a: [0, 6], b: [2, 4], c: \"\", f: [0, 5], t: [0, 7]},\n           {a: [0, 6], b: [2, 4], c: \"aa\", f: [0, 5], t: [0, 9]},\n           {a: [1, 2], b: [1, 8], c: \"\", f: [0, 5], t: [2, 5]},\n           {a: [0, 5], b: [2, 5], c: \"xx\", f: null, t: null},\n           {a: [0, 0], b: [2, 10], c: \"x\", f: null, t: null},\n           {a: [1, 5], b: [2, 5], c: \"\", f: [0, 5], t: [1, 5]},\n           {a: [2, 0], b: [2, 3], c: \"\", f: [0, 5], t: [2, 2]},\n           {a: [2, 5], b: [3, 0], c: \"a\\nb\", f: [0, 5], t: [2, 5]},\n           {a: [2, 3], b: [3, 0], c: \"x\", f: [0, 5], t: [2, 4]},\n           {a: [1, 1], b: [1, 9], c: \"1\\n2\\n3\", f: [0, 5], t: [4, 5]}], function(test) {\n    cm.setValue(\"aaaaaaaaaa\\nbbbbbbbbbb\\ncccccccccc\\ndddddddd\\n\");\n    var r = cm.markText({line: 0, ch: 5}, {line: 2, ch: 5}, \"foo\");\n    cm.replaceRange(test.c, p(test.a), p(test.b));\n    var f = r.find();\n    eqPos(f.from, p(test.f)); eqPos(f.to, p(test.t));\n  });\n});\n\ntestCM(\"bookmark\", function(cm) {\n  function p(v) { return v && {line: v[0], ch: v[1]}; }\n  forEach([{a: [1, 0], b: [1, 1], c: \"\", d: [1, 4]},\n           {a: [1, 1], b: [1, 1], c: \"xx\", d: [1, 7]},\n           {a: [1, 4], b: [1, 5], c: \"ab\", d: [1, 6]},\n           {a: [1, 4], b: [1, 6], c: \"\", d: null},\n           {a: [1, 5], b: [1, 6], c: \"abc\", d: [1, 5]},\n           {a: [1, 6], b: [1, 8], c: \"\", d: [1, 5]},\n           {a: [1, 4], b: [1, 4], c: \"\\n\\n\", d: [3, 1]},\n           {bm: [1, 9], a: [1, 1], b: [1, 1], c: \"\\n\", d: [2, 8]}], function(test) {\n    cm.setValue(\"1234567890\\n1234567890\\n1234567890\");\n    var b = cm.setBookmark(p(test.bm) || {line: 1, ch: 5});\n    cm.replaceRange(test.c, p(test.a), p(test.b));\n    eqPos(b.find(), p(test.d));\n  });\n});\n\n// Scaffolding\n\nfunction htmlEscape(str) {\n  return str.replace(/[<&]/g, function(str) {return str == \"&\" ? \"&amp;\" : \"&lt;\";});\n}\nfunction forEach(arr, f) {\n  for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);\n}\n\nfunction Failure(why) {this.message = why;}\n\nfunction test(name, run) {tests.push({name: name, func: run});}\nfunction testCM(name, run, opts) {\n  test(name, function() {\n    var place = document.getElementById(\"testground\"), cm = CodeMirror(place, opts);\n    try {run(cm);}\n    finally {place.removeChild(cm.getWrapperElement());}\n  });\n}\n\nfunction runTests() {\n  var failures = [], run = 0;\n  for (var i = 0; i < tests.length; ++i) {\n    var test = tests[i];\n    try {test.func();}\n    catch(e) {\n      if (e instanceof Failure)\n        failures.push({type: \"failure\", test: test.name, text: e.message});\n      else\n        failures.push({type: \"error\", test: test.name, text: e.toString()});\n    }\n    run++;\n  }\n  var html = [run + \" tests run.\"];\n  if (failures.length)\n    forEach(failures, function(fail) {\n      html.push(fail.test + ': <span class=\"' + fail.type + '\">' + htmlEscape(fail.text) + \"</span>\");\n    });\n  else html.push('<span class=\"ok\">All passed.</span>');\n  document.getElementById(\"output\").innerHTML = html.join(\"\\n\");\n}\n\nfunction eq(a, b, msg) {\n  if (a != b) throw new Failure(a + \" != \" + b + (msg ? \" (\" + msg + \")\" : \"\"));\n}\nfunction eqPos(a, b, msg) {\n  if (a == b) return;\n  if (a == null || b == null) throw new Failure(\"comparing point to null\");\n  eq(a.line, b.line, msg);\n  eq(a.ch, b.ch, msg);\n}\nfunction is(a, msg) {\n  if (!a) throw new Failure(\"assertion failed\" + (msg ? \" (\" + msg + \")\" : \"\"));\n}\n\nwindow.onload = runTests;\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/theme/ambiance.css",
    "content": "/* ambiance theme for code-mirror */\n\n/* Color scheme */\n\n.cm-s-ambiance .cm-keyword { color: #cda869; }\n.cm-s-ambiance .cm-atom { color: #CF7EA9; }\n.cm-s-ambiance .cm-number { color: #78CF8A; }\n.cm-s-ambiance .cm-def { color: #aac6e3; }\n.cm-s-ambiance .cm-variable { color: #ffb795; }\n.cm-s-ambiance .cm-variable-2 { color: #eed1b3; }\n.cm-s-ambiance .cm-variable-3 { color: #faded3; }\n.cm-s-ambiance .cm-property { color: #eed1b3; }\n.cm-s-ambiance .cm-operator {color: #fa8d6a;}\n.cm-s-ambiance .cm-comment { color: #555; font-style:italic; }\n.cm-s-ambiance .cm-string { color: #8f9d6a; }\n.cm-s-ambiance .cm-string-2 { color: #9d937c; }\n.cm-s-ambiance .cm-meta { color: #D2A8A1; }\n.cm-s-ambiance .cm-error { color: #AF2018; }\n.cm-s-ambiance .cm-qualifier { color: yellow; }\n.cm-s-ambiance .cm-builtin { color: #9999cc; }\n.cm-s-ambiance .cm-bracket { color: #24C2C7; }\n.cm-s-ambiance .cm-tag { color: #fee4ff }\n.cm-s-ambiance .cm-attribute {  color: #9B859D; }\n.cm-s-ambiance .cm-header {color: #blue;}\n.cm-s-ambiance .cm-quote { color: #24C2C7; }\n.cm-s-ambiance .cm-hr { color: pink; }\n.cm-s-ambiance .cm-link { color: #F4C20B; }\n.cm-s-ambiance .cm-special { color: #FF9D00; }\n\n.cm-s-ambiance .CodeMirror-matchingbracket { color: #0f0; }\n.cm-s-ambiance .CodeMirror-nonmatchingbracket { color: #f22; }\n\n.cm-s-ambiance .CodeMirror-selected {\n  background: rgba(255, 255, 255, 0.15);\n}\n.CodeMirror-focused .cm-s-ambiance .CodeMirror-selected {\n  background: rgba(255, 255, 255, 0.10);\n}\n\n/* Editor styling */\n\n.cm-s-ambiance {\n  line-height: 1.40em;\n  font-family: Monaco, Menlo,\"Andale Mono\",\"lucida console\",\"Courier New\",monospace !important;\n  font-size: 12px;\n  color: #E6E1DC;\n  background-color: #202020;\n  -webkit-box-shadow: inset 0 0 10px black;\n  -moz-box-shadow: inset 0 0 10px black;\n  -o-box-shadow: inset 0 0 10px black;\n  box-shadow: inset 0 0 10px black;\n}\n\n.cm-s-ambiance .CodeMirror-gutter {\n  background: #3D3D3D;\n  padding: 0 5px;\n  text-shadow: #333 1px 1px;\n  border-right: 1px solid #4D4D4D;\n  box-shadow: 0 10px 20px black;\n}\n\n.cm-s-ambiance .CodeMirror-gutter .CodeMirror-gutter-text {\n  text-shadow: 0px 1px 1px #4d4d4d;\n  color: #222;\n}\n\n.cm-s-ambiance .CodeMirror-lines {\n  \n}\n\n.cm-s-ambiance .CodeMirror-lines .CodeMirror-cursor {\n  border-left: 1px solid #7991E8;\n}\n\n.cm-s-ambiance .activeline {\n  background: none repeat scroll 0% 0% rgba(255, 255, 255, 0.031);\n}\n\n.cm-s-ambiance,\n.cm-s-ambiance .CodeMirror-gutter {\n  background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAQAAAAHUWYVAABFFUlEQVQYGbzBCeDVU/74/6fj9HIcx/FRHx9JCFmzMyGRURhLZIkUsoeRfUjS2FNDtr6WkMhO9sm+S8maJfu+Jcsg+/o/c+Z4z/t97/vezy3z+z8ekGlnYICG/o7gdk+wmSHZ1z4pJItqapjoKXWahm8NmV6eOTbWUOp6/6a/XIg6GQqmenJ2lDHyvCFZ2cBDbmtHA043VFhHwXxClWmeYAdLhV00Bd85go8VmaFCkbVkzlQENzfBDZ5gtN7HwF0KDrTwJ0dypSOzpaKCMwQHKTIreYIxlmhXTzTWkVm+LTynZhiSBT3RZQ7aGfjGEd3qyXQ1FDymqbKxpspERQN2MiRjNZlFFQXfCNFm9nM1zpAsoYjmtRTc5ajwuaXc5xrWskT97RaKzAGe5ARHhVUsDbjKklziiX5WROcJwSNCNI+9w1Jwv4Zb2r7lCMZ4oq5C0EdTx+2GzNuKpJ+iFf38JEWkHJn9DNF7mmBDITrWEg0VWL3pHU20tSZnuqWu+R3BtYa8XxV1HO7GyD32UkOpL/yDloINFTmvtId+nmAjxRw40VMwVKiwrKLE4bK5UOVntYwhOcSSXKrJHKPJedocpGjVz/ZMIbnYUPB10/eKCrs5apqpgVmWzBYWpmtKHecJPjaUuEgRDDaU0oZghCJ6zNMQ5ZhDYx05r5v2muQdM0EILtXUsaKiQX9WMEUotagQzFbUNN6NUPC2nm5pxEWGCjMc3GdJHjSU2kORLK/JGSrkfGEIjncU/CYUnOipoYemwj8tST9NsJmB7TUVXtbUtXATJVZXBMvYeTXJfobgJUPmGMP/yFaWonaa6BcFO3nqcIqCozSZoZoSr1g4zJOzuyGnxTEX3lUEJ7WcZgme8ddaWvWJo2AJR9DZU3CUIbhCSG6ybSwN6qtJVnCU2svDTP2ZInOw2cBTrqtQahtNZn9NcJ4l2NaSmSkkP1noZWnVwkLmdUPOwLZEwy2Z3S3R+4rIG9hcbpPXHFVWcQdZkn2FOta3cKWQnNRC5g1LsJah4GCzSVsKnCOY5OAFRTBekyyryeyilhFKva75r4Mc0aWanGEaThcy31s439KKxTzJYY5WTHPU1FtIHjQU3Oip4xlNzj/lBw23dYZVliQa7WAXf4shetcQfatI+jWRDBPmyNeW6A1P5kdDgyYJlba0BIM8BZu1JfrFwItyjcAMR3K0BWOIrtMEXyhyrlVEx3ui5dUBjmB/Q3CXW85R4mBD0s7B+4q5tKUjOlb9qqmhi5AZ6GFIC5HXtOobdYGlVdMVbNJ8toNTFcHxnoL+muBagcctjWnbNMuR00uI7nQESwg5q2qqrKWIfrNUmeQocY6HuyxJV02wj36w00yhpmUFenv4p6fUkZYqLyuinx2RGOjhCXYyJF84oiU00YMOOhhquNdfbOB7gU88pY4xJO8LVdp6/q2voeB4R04vIdhSE40xZObx1HGGJ/ja0LBthFInKaLPPFzuCaYaoj8JjPME8yoyxo6zlBqkiUZYgq00OYMswbWO5NGmq+xhipxHLRW29ARjNKXO0wRnear8XSg4XFPLKEPUS1GqvyLwiuBUoa7zpZ0l5xxFwWmWZC1H5h5FwU8eQ7K+g8UcVY6TMQreVQT/8uQ8Z+ALIXnSEa2pYZQneE9RZbSBNYXfWYJzW/h/4j4Dp1tYVcFIC5019Vyi4ThPqSFCzjGWaHQTBU8q6vrVwgxP9Lkm840imWKpcLCjYTtrKuwvsKSnrvHCXGkSMk9p6lhckfRpIeis+N2PiszT+mFLspyGleUhDwcLrZqmyeylxwjBcKHEapqkmyangyLZRVOijwOtCY5SsG5zL0OwlCJ4y5KznF3EUNDDrinwiyLZRzOXtlBbK5ITHFGLp8Q0R6ab6mS7enI2cFrxOyHvOCFaT1HThS1krjCwqWeurCkk+willhCC+RSZnRXBiZaC5RXRIZYKp2lyfrHwiKPKR0JDzrdU2EFgpidawlFDR6FgXUMNa+g1FY3bUQh2cLCwosRdnuQTS/S+JVrGLeWIvtQUvONJxlqSQYYKpwoN2kaocLjdVsis4Mk80ESF2YpSkzwldjHkjFCUutI/r+EHDU8oCs6yzL3PhWiEooZdFMkymlas4AcI3KmoMMNSQ3tHzjGWCrcJJdYyZC7QFGwjRL9p+MrRkAGWzIaWCn9W0F3TsK01c2ZvQw0byvxuQU0r1lM0qJO7wW0kRIMdDTtXEdzi4VIh+EoIHm0mWtAtpCixlabgn83fKTI7anJe9ST7WIK1DMGpQmYeA58ImV6ezOGOzK2Kgq01pd60cKWiUi9Lievb/0vIDPHQ05Kzt4ddPckQBQtoaurjyHnek/nKzpQLrVgKPjIkh2v4uyezpv+Xoo7fPFXaGFp1vaLKxQ4uUpQQS5VuQs7BCq4xRJv7fwpVvvFEB3j+620haOuocqMhWd6TTPAEx+mdFNGHdranFe95WrWmIvlY4F1Dle2ECgc6cto7SryuqGGGha0tFQ5V53migUKmg6XKAo4qS3mik+0OZpAhOLeZKicacgaYcyx5hypYQE02ZA4xi/pNhOQxR4klNKyqacj+mpxnLTnnGSo85++3ZCZq6lrZkXlGEX3o+C9FieccJbZWVFjC0Yo1FZnJhoYMFoI1hEZ9r6hwg75HwzBNhbZCdJEfJwTPGzJvaKImw1yYX1HDAmpXR+ZJQ/SmgqMNVQb5vgamGwLtt7VwvP7Qk1xpiM5x5Cyv93E06MZmgs0Nya2azIKOYKCGBQQW97RmhKNKF02JZqHEJ4o58qp7X5EcZmc56trXEqzjCBZ1MFGR87Ql2tSTs6CGxS05PTzRQorkbw7aKoKXFDXsYW42VJih/q+FP2BdTzDTwVqOYB13liM50vG7wy28qagyuIXMeQI/Oqq8bcn5wJI50xH00CRntyfpL1T4hydYpoXgNiFzoIUTDZnLNRzh4TBHwbYGDvZkxmlyJloyr6tRihpeUG94GnKtIznREF0tzJG/OOr73JBcrSh1k6WuTprgLU+mnSGnv6Zge0NNz+kTDdH8nuAuTdJDCNb21LCiIuqlYbqGzT3RAoZofQfjFazkqeNWdYaGvYTM001EW2oKPvVk1ldUGSgUtHFwjKM1h9jnFcmy5lChoLNaQMGGDsYbKixlaMBmmsx1QjCfflwTfO/gckW0ruZ3jugKR3R5W9hGUWqCgxuFgsuaCHorotGKzGaeZB9DMsaTnKCpMtwTvOzhYk0rdrArKCqcaWmVk1+F372ur1YkKxgatI8Qfe1gIX9wE9FgS8ESmuABIXnRUbCapcKe+nO7slClSZFzpV/LkLncEb1qiO42fS3R855Su2mCLh62t1SYZZYVmKwIHjREF2uihTzB20JOkz7dkxzYQnK0UOU494wh+VWRc6Un2kpTaVgLDFEkJ/uhzRcI0YKGgpGWOlocBU/a4fKoJ/pEaNV6jip3+Es9VXY078rGnmAdf7t9ylPXS34RBSuYPs1UecZTU78WanhBCHpZ5sAoTz0LGZKjPf9TRypqWEiTvOFglL1fCEY3wY/++rbk7C8bWebA6p6om6PgOL2kp44TFJlVNBXae2rqqdZztOJpT87GQsE9jqCPIe9VReZuQ/CIgacsyZdCpIScSYqcZk8r+nsyCzhyfhOqHGOIvrLknC8wTpFcaYiGC/RU1NRbUeUpocQOnkRpGOrIOcNRx+1uA0UrzhSSt+VyS3SJpnFWkzNDqOFGIWcfR86DnmARTQ1HKIL33ExPiemeOhYSSjzlSUZZuE4TveoJLnBUOFof6KiysCbnAEcZgcUNTDOwkqWu3RWtmGpZwlHhJENdZ3miGz0lJlsKnjbwqSHQjpxnFDlTLLwqJPMZMjd7KrzkSG7VsxXBZE+F8YZkb01Oe00yyRK9psh5SYh29ySPKBo2ylNht7ZkZnsKenjKNJu9PNEyZpaCHv4Kt6RQsLvAVp7M9kIimmCUwGeWqLMmGuIotYMmWNpSahkhZw9FqZsVnKJhsjAHvtHMsTM9fCI06Dx/u3vfUXCqfsKRc4oFY2jMsoo/7DJDwZ1CsIKnJu+J9ldkpmiCxQx1rWjI+T9FwcWWzOuaYH0Hj7klNRVWEQpmaqosakiGNTFHdjS/qnUdmf0NJW5xsL0HhimCCZZSRzmSPTXJQ4aaztAwtZnoabebJ+htCaZ7Cm535ByoqXKbX1WRc4Eh2MkRXWzImVc96Cj4VdOKVxR84VdQsIUM8Psoou2byVHyZFuq7O8otbSQ2UAoeEWTudATLGSpZzVLlXVkPU2Jc+27lsw2jmg5T5VhbeE3BT083K9WsTTkFU/Osi0rC5lRlpwRHUiesNS0sOvmqGML1aRbPAxTJD9ZKtxuob+hhl8cwYGWpJ8nub7t5p6coYbMovZ1BTdaKn1jYD6h4GFDNFyT/Kqe1XCXphXHOKLZmuRSRdBPEfVUXQzJm5YGPGGJdvAEr7hHNdGZnuBvrpciGmopOLf5N0uVMy0FfYToJk90uUCbJupaVpO53UJXR2bVpoU00V2KOo4zMFrBd0Jtz2pa0clT5Q5L8IpQ177mWQejPMEJhuQjS10ref6HHjdEhy1P1EYR7GtO0uSsKJQYLiTnG1rVScj5lyazpqWGl5uBbRWl7m6ixGOOnEsMJR7z8J0n6KMnCdxhiNYQCoZ6CmYLnO8omC3MkW3bktlPmEt/VQQHejL3+dOE5FlPdK/Mq8hZxxJtLyRrepLThYKbLZxkSb5W52vYxNOaOxUF0yxMUPwBTYqCzy01XayYK0sJyWBLqX0MwU5CzoymRzV0EjjeUeLgDpTo6ij42ZAzvD01dHUUTPLU96MdLbBME8nFBn7zJCMtJcZokn8YoqU0FS5WFKyniHobguMcmW8N0XkWZjkyN3hqOMtS08r+/xTBwpZSZ3qiVRX8SzMHHjfUNFjgHEPmY9PL3ykEzxkSre/1ZD6z/NuznuB0RcE1TWTm9zRgfUWVJiG6yrzgmWPXC8EAR4Wxhlad0ZbgQyEz3pG5RVEwwDJH2mgKpjcTiCOzn1lfUWANFbZ2BA8balnEweJC9J0iuaeZoI+ippFCztEKVvckR2iice1JvhVytrQwUAZpgsubCPaU7xUe9vWnaOpaSBEspalykhC9bUlOMpT42ZHca6hyrqKmw/wMR8H5ZmdFoBVJb03O4UL0tSNnvIeRmkrLWqrs78gcrEn2tpcboh0UPOW3UUR9PMk4T4nnNKWmCjlrefhCwxRNztfmIQVdDElvS4m1/WuOujoZCs5XVOjtKPGokJzsYCtFYoWonSPT21DheU/wWhM19FcElwqNGOsp9Q8N/cwXaiND1MmeL1Q5XROtYYgGeFq1aTMsoMmcrKjQrOFQTQ1fmBYhmW6o8Jkjc7iDJRTBIo5kgJD5yMEYA3srCg7VFKwiVJkmRCc5ohGOKhsYMn/XBLdo5taZjlb9YAlGWRimqbCsoY7HFAXLa5I1HPRxMMsQDHFkWtRNniqT9UEeNjcE7RUlrCJ4R2CSJuqlKHWvJXjAUNcITYkenuBRB84TbeepcqTj3zZyFJzgYQdHnqfgI0ddUwS6GqWpsKWhjq9cV0vBAEMN2znq+EBfIWT+pClYw5xsTlJU6GeIBsjGmmANTzJZiIYpgrM0Oa8ZMjd7NP87jxhqGOhJlnQtjuQpB+8aEE00wZFznSJPyHxgH3HkPOsJFvYk8zqCHzTs1BYOa4J3PFU+UVRZxlHDM4YavlNUuMoRveiZA2d7grMNc2g+RbSCEKzmgYsUmWmazFJyoiOZ4KnyhKOGRzWJa0+moyV4TVHDzn51Awtqaphfk/lRQ08FX1iiqxTB/kLwd0VynKfEvI6cd4XMV5bMhZ7gZUWVzYQ6Nm2BYzxJbw3bGthEUUMfgbGeorae6DxHtJoZ6alhZ0+ytiVoK1R4z5PTrOECT/SugseEOlb1MMNR4VRNcJy+V1Hg9ONClSZFZjdHlc6W6FBLdJja2MC5hhpu0DBYEY1TFGwiFAxRRCsYkiM9JRb0JNMVkW6CZYT/2EiTGWmo8k+h4FhDNE7BvppoTSFnmCV5xZKzvcCdDo7VVPnIU+I+Rc68juApC90MwcFCsJ5hDqxgScYKreruyQwTqrzoqDCmhWi4IbhB0Yrt3RGa6GfDv52rKXWhh28dyZaWUvcZeMTBaZoSGyiCtRU5J8iviioHaErs7Jkj61syVzTTgOcUOQ8buFBTYWdL5g3T4qlpe0+wvD63heAXRfCCIed9RbCsp2CiI7raUOYOTU13N8PNHvpaGvayo4a3LLT1lDrVEPT2zLUlheB1R+ZTRfKWJ+dcocLJfi11vyJ51lLqJ0WD7tRwryezjiV5W28uJO9qykzX8JDe2lHl/9oyBwa2UMfOngpXCixvKdXTk3wrsKmiVYdZIqsoWEERjbcUNDuiaQomGoIbFdEHmsyWnuR+IeriKDVLnlawlyNHKwKlSU631PKep8J4Q+ayjkSLKYLhalNHlYvttb6fHm0p6OApsZ4l2VfdqZkjuysy6ysKLlckf1KUutCTs39bmCgEyyoasIWlVaMF7mgmWtBT8Kol5xpH9IGllo8cJdopcvZ2sImlDmMIbtDk3KIpeNiS08lQw11NFPTwVFlPP6pJ2gvRfI7gQUfmNAtf6Gs0wQxDsKGlVBdF8rCa3jzdwMaGHOsItrZk7hAyOzpK9VS06j5F49b0VNGOOfKs3lDToMsMBe9ZWtHFEgxTJLs7qrygKZjUnmCYoeAqeU6jqWuLJup4WghOdvCYJnrSkSzoyRkm5M2StQwVltPkfCAk58tET/CSg+8MUecmotMEnhBKfWBIZsg2ihruMJQaoIm+tkTLKEqspMh00w95gvFCQRtDwTT1gVDDSEVdlwqZfxoQRbK0g+tbiBZxzKlpnpypejdDwTaeOvorMk/IJE10h9CqRe28hhLbe0pMsdSwv4ZbhKivo2BjDWfL8UKJgeavwlwb5KlwhyE4u4XkGE2ytZCznKLCDZZq42VzT8HLCrpruFbIfOIINmh/qCdZ1ZBc65kLHR1Bkyf5zn6pN3SvGKIlFNGplhrO9QSXanLOMQTLCa0YJCRrCZm/CZmrLTm7WzCK4GJDiWUdFeYx1LCFg3NMd0XmCuF3Y5rITLDUsYS9zoHVzwnJoYpSTQoObyEzr4cFBNqYTopoaU/wkyLZ2lPhX/5Y95ulxGTV7KjhWrOZgl8MyUUafjYraNjNU1N3IWcjT5WzWqjwtoarHSUObGYO3GCJZpsBlnJGPd6ZYLyl1GdCA2625IwwJDP8GUKymbzuyPlZlvTUsaUh5zFDhRWFzPKKZLAlWdcQbObgF9tOqOsmB1dqcqYJmWstFbZRRI9poolmqiLnU0POvxScpah2iSL5UJNzgScY5+AuIbpO0YD3NCW+dLMszFSdFCWGqG6eVq2uYVNDdICGD6W7EPRWZEY5gpsE9rUkS3mijzzJnm6UpUFXG1hCUeVoS5WfNcFpblELL2qqrCvMvRfd45oalvKU2tiQ6ePJOVMRXase9iTtLJztPxJKLWpo2CRDcJwn2sWSLKIO1WQWNTCvpVUvOZhgSC40JD0dOctaSqzkCRbXsKlb11Oip6PCJ0IwSJM31j3akRxlP7Rwn6aGaUL0qiLnJkvB3xWZ2+Q1TfCwpQH3G0o92UzmX4o/oJNQMMSQc547wVHhdk+VCw01DFYEnTxzZKAm74QmeNNR1w6WzEhNK15VJzuCdxQ53dRUDws5KvwgBMOEgpcVNe0hZI6RXT1Jd0cyj5nsaEAHgVmGaJIlWdsc5Ui2ElrRR6jrRAttNMEAIWrTDFubkZaok7/AkzfIwfuWVq0jHzuCK4QabtLUMVPB3kJ0oyHTSVFlqMALilJf2Rf8k5aaHtMfayocLBS8L89oKoxpJvnAkDPa0qp5DAUTHKWmCcnthlou8iCKaFFLHWcINd1nyIwXqrSxMNmSs6KmoL2QrKuWtlQ5V0120xQ5vRyZS1rgFkWwhiOwiuQbR0OOVhQM9iS3tiXp4RawRPMp5tDletOOBL95MpM01dZTBM9pkn5qF010rIeHFcFZhmSGpYpTsI6nwhqe5C9ynhlpp5ophuRb6WcJFldkVnVEwwxVfrVkvnWUuNLCg5bgboFHPDlDPDmnK7hUrWiIbjadDclujlZcaokOFup4Ri1kacV6jmrrK1hN9bGwpKEBQ4Q6DvIUXOmo6U5LqQM6EPyiKNjVkPnJkDPNEaxhiFay5ExW1NXVUGqcpYYdPcGiCq7z/TSlbhL4pplWXKd7NZO5QQFrefhRQW/NHOsqcIglc4UhWklR8K0QzbAw08CBDnpbgqXdeD/QUsM4RZXDFBW6WJKe/mFPdH0LtBgiq57wFLzlyQzz82qYx5D5WJP5yVJDW01BfyHnS6HKO/reZqId1WGa4Hkh2kWodJ8i6KoIPlAj2hPt76CzXsVR6koPRzWTfKqIentatYpQw2me4AA3y1Kind3SwoOKZDcFXTwl9tWU6mfgRk9d71sKtlNwrjnYw5tC5n5LdKiGry3JKNlHEd3oaMCFHrazBPMp/uNJ+V7IudcSbeOIdjUEdwl0VHCOZo5t6YluEuaC9mQeMgSfOyKnYGFHcIeQ84yQWbuJYJpZw5CzglDH7gKnWqqM9ZTaXcN0TeYhR84eQtJT76JJ1lREe7WnnvsMmRc9FQ7SBBM9mV3lCUdmHk/S2RAMt0QjFNFqQpWjDPQ01DXWUdDBkXziKPjGEP3VP+zIWU2t7im41FOloyWzn/L6dkUy3VLDaZ6appgDLHPjJEsyvJngWEPUyVBiAaHCTEXwrLvSEbV1e1gKJniicWorC1MUrVjB3uDhJE/wgSOzk1DXpk0k73qCM8xw2UvD5kJmDUfOomqMpWCkJRlvKXGmoeBm18USjVIk04SClxTB6YrgLAPLWYK9HLUt5cmc0vYES8GnTeRc6skZbQkWdxRsIcyBRzx1DbTk9FbU0caTPOgJHhJKnOGIVhQqvKmo0llRw9sabrZkDtdg3PqaKi9oatjY8B+G371paMg6+mZFNNtQ04mWBq3rYLOmtWWQp8KJnpy9DdFensyjdqZ+yY40VJlH8wcdLzC8PZnvHMFUTZUrDTkLyQaGus5X5LzpYAf3i+e/ZlhqGqWhh6Ou6xTR9Z6oi5AZZtp7Mj2EEm8oSpxiYZCHU/1fbGdNNNRRoZMhmilEb2gqHOEJDtXkHK/JnG6IrvbPCwV3NhONVdS1thBMs1T4QOBcTWa2IzhMk2nW5Kyn9tXUtpv9RsG2msxk+ZsQzRQacJncpgke0+T8y5Fzj8BiGo7XlJjaTIlpQs7KFjpqGnKuoyEPeIKnFMkZHvopgh81ySxNFWvJWcKRs70j2FOT012IllEEO1n4pD1513Yg2ssQPOThOkvyrqHUdEXOSEsihmBbTbKX1kLBPWqWkLOqJbjB3GBIZmoa8qWl4CG/iZ7oiA72ZL7TJNeZUY7kFQftDcHHluBzRbCegzMtrRjVQpX2lgoPKKLJAkcbMl01XK2p7yhL8pCBbQ3BN2avJgKvttcrWDK3CiUOVxQ8ZP+pqXKyIxnmBymCg5vJjNfkPK4+c8cIfK8ocVt7kmfd/I5SR1hKvCzUtb+lhgc00ZaO6CyhIQP1Uv4yIZjload72PXX0OIJvnFU+0Zf6MhsJwTfW0r0UwQfW4LNLZl5HK261JCZ4qnBaAreVAS3WrjV0LBnNDUNNDToCEeFfwgcb4gOEqLRhirWkexrCEYKVV711DLYEE1XBEsp5tpTGjorkomKYF9FDXv7fR3BGwbettSxnyL53MBPjsxDZjMh+VUW9NRxq1DhVk+FSxQcaGjV9Pawv6eGByw5qzoy7xk4RsOShqjJwWKe/1pEEfzkobeD/dQJmpqedcyBTy2sr4nGNRH0c0SPWTLrqAc0OQcb/gemKgqucQT7ySWKCn2EUotoCvpZct7RO2sy/QW0IWcXd7pQRQyZVwT2USRO87uhjioTLKV2brpMUcMQRbKH/N2T+UlTpaMls6cmc6CCNy3JdYYSUzzJQ4oSD3oKLncULOiJvjBEC2oqnCJkJluCYy2ZQ5so9YYlZ1VLlQU1mXEW1jZERwj/MUSRc24TdexlqLKfQBtDTScJUV8FszXBEY5ktpD5Ur9hYB4Nb1iikw3JoYpkKX+RodRKFt53MMuRnKSpY31PwYaGaILh3wxJGz9TkTPEETxoCWZrgvOlmyMzxFEwVJE5xZKzvyJ4WxEc16Gd4Xe3Weq4XH2jKRikqOkGQ87hQnC7wBmGYLAnesX3M+S87eFATauuN+Qcrh7xIxXJbUIdMw3JGE3ylCWzrieaqCn4zhGM19TQ3z1oH1AX+pWEqIc7wNGAkULBo/ZxRaV9NNyh4Br3rCHZzbzmSfawBL0dNRwpW1kK9mxPXR9povcdrGSZK9c2k0xwFGzjuniCtRSZCZ6ccZ7gaktmgAOtKbG/JnOkJrjcQTdFMsxRQ2cLY3WTIrlCw1eWKn8R6pvt4GFDso3QoL4a3nLk3G6JrtME3dSenpx7PNFTmga0EaJTLQ061sEeQoWXhSo9LTXsaSjoJQRXeZLtDclbCrYzfzHHeaKjHCVOUkQHO3JeEepr56mhiyaYYKjjNU+Fed1wS5VlhWSqI/hYUdDOkaxiKehoyOnrCV5yBHtbWFqTHCCwtpDcYolesVR5yUzTZBb3RNMd0d6WP+SvhuBmRcGxnuQzT95IC285cr41cLGQ6aJJhmi4TMGempxeimBRQw1tFKV+8jd6KuzoSTqqDxzRtpZkurvKEHxlqXKRIjjfUNNXQsNOsRScoWFLT+YeRZVD3GRN0MdQcKqQjHDMrdGGVu3iYJpQx3WGUvfbmxwFfR20WBq0oYY7LMFhhgYtr8jpaEnaOzjawWWaTP8mMr0t/EPDPoqcnxTBI5o58L7uoWnMrpoqPwgVrlAUWE+V+TQl9rawoyP6QGAlQw2TPRX+YSkxyBC8Z6jhHkXBgQL7WII3DVFnRfCrBfxewv9D6xsyjys4VkhWb9pUU627JllV0YDNHMku/ldNMMXDEo4aFnAkk4U6frNEU4XgZUPmEKHUl44KrzmYamjAbh0JFvGnaTLPu1s9jPCwjFpYiN7z1DTOk/nc07CfDFzmCf7i+bfNHXhDtLeBXzTBT5rkMvWOIxpl4EMh2LGJBu2syDnAEx2naEhHDWMMzPZEhygyS1mS5RTJr5ZkoKbEUoYqr2kqdDUE8ztK7OaIntJkFrIECwv8LJTaVx5XJE86go8dFeZ3FN3rjabCAYpoYEeC9zzJVULBbmZhDyd7ko09ydpNZ3nm2Kee4FPPXHnYEF1nqOFEC08LUVcDvYXkJHW8gTaKCk9YGOeIJhqiE4ToPEepdp7IWFjdwnWaufGMwJJCMtUTTBBK9BGCOy2tGGrJTHIwyEOzp6aPzNMOtlZkDvcEWpP5SVNhfkvDxhmSazTJXYrM9U1E0xwFVwqZQwzJxw6+kGGGUj2FglGGmnb1/G51udRSMNlTw6GGnCcUwVcOpmsqTHa06o72sw1RL02p9z0VbnMLOaIX3QKaYKSCFQzBKEUNHTSc48k53RH9wxGMtpQa5KjjW0W0n6XCCCG4yxNNdhQ4R4l1Ff+2sSd6UFHiIEOyqqFgT01mEUMD+joy75jPhOA+oVVLm309FR4yVOlp4RhLiScNmSmaYF5Pw0STrOIoWMSR2UkRXOMp+M4SHW8o8Zoi6OZgjKOaFar8zZDzkWzvKOjkKBjmCXby8JahhjXULY4KlzgKLvAwxVGhvyd4zxB1d9T0piazmKLCVZY5sKiD0y2ZSYrkUEPUbIk+dlQ4SJHTR50k1DPaUWIdTZW9NJwnJMOECgd7ou/MnppMJ02O1VT4Wsh85MnZzcFTngpXGKo84qmwgKbCL/orR/SzJ2crA+t6Mp94KvxJUeIbT3CQu1uIdlQEOzlKfS3UMcrTiFmOuroocrZrT2AcmamOKg8YomeEKm/rlT2sociMaybaUlFhuqHCM2qIJ+rg4EcDFymiDSxzaHdPcpE62pD5kyM5SBMoA1PaUtfIthS85ig1VPiPPYXgYEMNk4Qq7TXBgo7oT57gPUdwgCHzhIVFPFU6OYJzHAX9m5oNrVjeE61miDrqQ4VSa1oiURTsKHC0IfjNwU2WzK6eqK8jWln4g15TVBnqmDteCJ501PGAocJhhqjZdtBEB6lnhLreFJKxmlKbeGrqLiSThVIbCdGzloasa6lpMQXHCME2boLpJgT7yWaemu6wBONbqGNVRS0PKIL7LckbjmQtR7K8I5qtqel+T/ChJTNIKLjdUMNIRyvOEko9YYl2cwQveBikCNawJKcLBbc7+JM92mysNvd/Fqp8a0k6CNEe7cnZrxlW0wQXaXjaktnRwNOGZKYiONwS7a1JVheq3WgJHlQUGKHKmp4KAxXR/ULURcNgoa4zhKSLpZR3kxRRb0NmD0OFn+UCS7CzI1nbP6+o4x47QZE5xRCt3ZagnYcvmpYQktXdk5YKXTzBC57kKEe0VVuiSYqapssMS3C9p2CKkHOg8B8Pa8p5atrIw3qezIWanMGa5HRDNF6RM9wcacl0N+Q8Z8hsIkSnaIIdHRUOEebAPy1zbCkhM062FCJtif7PU+UtoVXzWKqM1PxXO8cfdruhFQ/a6x3JKYagvVDhQEtNiyiiSQ7OsuRsZUku0CRNDs4Sog6KKjsZgk2bYJqijgsEenoKeniinRXBn/U3lgpPdyDZynQx8IiioMnCep5Ky8mjGs6Wty0l1hUQTcNWswS3WRp2kCNZwJG8omG8JphPUaFbC8lEfabwP7VtM9yoaNCAjpR41VNhrD9LkbN722v0CoZMByFzhaW+MyzRYEWFDQwN2M4/JiT76PuljT3VU/A36eaIThb+R9oZGOAJ9tewkgGvqOMNRWYjT/Cwu99Q8LqDE4TgbLWxJ1jaDDAERsFOFrobgjUsBScaguXU8kKm2RL19tRypSHnHNlHiIZqgufs4opgQdVdwxBNNFBR6kVFqb8ogimOzB6a6HTzrlDHEpYaxjiiA4TMQobkDg2vejjfwJGWmnbVFAw3H3hq2NyQfG7hz4aC+w3BbwbesG0swYayvpAs6++Ri1Vfzx93mFChvyN5xVHTS+0p9aqCAxyZ6ZacZyw5+7uuQkFPR9DDk9NOiE7X1PCYJVjVUqq7JlrHwWALF5nfHNGjApdpqgzx5OwilDhCiDYTgnc9waGW4BdLNNUQvOtpzDOWHDH8D7TR/A/85KljEQu3NREc4Pl/6B1Hhc8Umb5CsKMmGC9EPcxoT2amwHNCmeOEnOPbklnMkbOgIvO5UMOpQrS9UGVdt6iH/fURjhI/WOpaW9OKLYRod6HCUEdOX000wpDZQ6hwg6LgZfOqo1RfT/CrJzjekXOGhpc1VW71ZLbXyyp+93ILbC1kPtIEYx0FIx1VDrLoVzXRKRYWk809yYlC9ImcrinxtabKnzRJk3lAU1OLEN1j2zrYzr2myHRXJFf4h4QKT1qSTzTB5+ZNTzTRkAxX8FcLV2uS8eoQQ2aAkFzvCM72sJIcJET3WPjRk5wi32uSS9rfZajpWEvj9hW42F4o5NytSXYy8IKHay10VYdrcl4SkqscrXpMwyGOgtkajheSxdQqmpxP1L3t4R5PqasFnrQEjytq6qgp9Y09Qx9o4S1FzhUCn1kyHSzBWLemoSGvOqLNhZyBjmCaAUYpMgt4Ck7wBBMMwWKWgjsUwTaGVsxWC1mYoKiyqqeGKYqonSIRQ3KIkHO0pmAxTdBHkbOvfllfr+AA+7gnc50huVKYK393FOyg7rbPO/izI7hE4CnHHHnJ0ogNPRUGeUpsrZZTBJcrovUcJe51BPsr6GkJdhCCsZ6aTtMEb2pqWkqeVtDXE/QVggsU/Nl86d9RMF3DxvZTA58agu810RWawCiSzzXBeU3MMW9oyJUedvNEvQyNu1f10BSMddR1vaLCYpYa/mGocLSiYDcLbQz8aMn5iyF4xBNMs1P0QEOV7o5gaWGuzSeLue4tt3ro7y4Tgm4G/mopdZgl6q0o6KzJWE3mMksNr3r+a6CbT8g5wZNzT9O7fi/zpaOmnz3BRoqos+tv9zMbdpxsqDBOEewtJLt7cg5wtKKbvldpSzRRCD43VFheCI7yZLppggMVBS/KMAdHODJvOwq2NQSbKKKPLdFWQs7Fqo+mpl01JXYRgq8dnGLhTiFzqmWsUMdpllZdbKlyvSdYxhI9YghOtxR8LgSLWHK62mGGVoxzBE8LNWzqH9CUesQzFy5RQzTc56mhi6fgXEWwpKfE5Z7M05ZgZUPmo6auiv8YKzDYwWBLMErIbKHJvOwIrvEdhOBcQ9JdU1NHQ7CXn2XIDFBKU2WAgcX9UAUzDXWd5alwuyJ41Z9rjKLCL4aCp4WarhPm2rH+SaHUYE001JDZ2ZAzXPjdMpZWvC9wmqIB2lLhQ01D5jO06hghWMndbM7yRJMsoCj1vYbnFQVrW9jak3OlEJ3s/96+p33dEPRV5GxiqaGjIthUU6FFEZyqCa5qJrpBdzSw95IUnOPIrCUUjRZQFrbw5PR0R1qiYx3cb6nrWUMrBmmiBQxVHtTew5ICP/ip6g4hed/Akob/32wvBHsIOX83cI8hGeNeNPCIkPmXe8fPKx84OMSRM1MTdXSwjCZ4S30jVGhvqTRak/OVhgGazHuOCud5onEO1lJr6ecVyaOK6H7zqlBlIaHE0oroCgfvGJIdPcmfLNGLjpz7hZwZQpUbFME0A1cIJa7VNORkgfsMBatbKgwwJM9bSvQXeNOvbIjelg6WWvo5kvbKaJJNHexkKNHL9xRyFlH8Ti2riB5wVPhUk7nGkJnoCe428LR/wRGdYIlmWebCyxou1rCk4g/ShugBDX0V0ZQWkh0dOVsagkM0yV6OoLd5ye+pRlsCr0n+KiQrGuq5yJDzrTAXHtLUMduTDBVKrSm3eHL+6ijxhFDX9Z5gVU/wliHYTMiMFpKLNMEywu80wd3meoFmt6VbRMPenhrOc6DVe4pgXU8DnnHakLOIIrlF4FZPIw6R+zxBP0dyq6OOZ4Q5sLKCcz084ok+VsMMyQhNZmmBgX5xIXOEJTmi7VsGTvMTNdHHhpzdbE8Du2oKxgvBqQKdDDnTFOylCFaxR1syz2iqrOI/FEpNc3C6f11/7+ASS6l2inq2ciTrCCzgyemrCL5SVPjQkdPZUmGy2c9Sw9FtR1sS30RmsKPCS4rkIC/2U0MduwucYolGaPjKEyhzmiPYXagyWbYz8LWBDdzRimAXzxx4z8K9hpzlhLq+NiQ97HuKorMUfK/OVvC2JfiHUPCQI/q7J2gjK+tTDNxkCc4TMssqCs4TGtLVwQihyoAWgj9bosU80XGW6Ac9TJGziaUh5+hnFcHOnlaM1iRn29NaqGENTTTSUHCH2tWTeV0osUhH6psuVLjRUmGWhm6OZEshGeNowABHcJ2Bpy2ZszRcKkRXd2QuKVEeXnbfaEq825FguqfgfE2whlChSRMdron+LATTPQ2Z369t4B9C5gs/ylzv+CMmepIDPclFQl13W0rspPd1JOcbghGOEutqCv5qacURQl3dDKyvyJlqKXGPgcM9FfawJAMVmdcspcYKOZc4GjDYkFlK05olNMHyHn4zFNykyOxt99RkHlfwmiHo60l2EKI+mhreEKp080Tbug08BVPcgoqC5zWt+NLDTZ7oNSF51N1qie7Va3uCCwyZbkINf/NED6jzOsBdZjFN8oqG3wxVunqCSYYKf3EdhJyf9YWGf7tRU2oH3VHgPr1fe5J9hOgHd7xQ0y7qBwXr23aGErP0cm64JVjZwsOGqL+mhNgZmhJLW2oY4UhedsyBgzrCKrq7BmcpNVhR6jBPq64Vgi+kn6XE68pp8J5/+0wRHGOpsKenQn9DZntPzjRLZpDAdD2fnSgkG9tmIXnUwQ6WVighs7Yi2MxQ0N3CqYaCXkJ0oyOztMDJjmSSpcpvlrk0RMMOjmArQ04PRV1DO1FwhCVaUVPpKUM03JK5SxPsIWRu8/CGHi8UHChiqGFDTbSRJWeYUDDcH6vJWUxR4k1FXbMUwV6e4AJFXS8oMqsZKqzvYQ9DDQdZckY4aGsIhtlubbd2r3j4QBMoTamdPZk7O/Bf62lacZwneNjQoGcdVU7zJOd7ghsUHOkosagic6cnWc8+4gg285R6zZP5s1/LUbCKIznTwK36PkdwlOrl4U1LwfdCCa+IrvFkmgw1PCAUXKWo0sURXWcI2muKJlgyFzhynCY4RBOsqCjoI1R5zREco0n2Vt09BQtYSizgKNHfUmUrQ5UOCh51BFcLmY7umhYqXKQomOop8bUnWNNQcIiBcYaC6xzMNOS8JQQfeqKBmmglB+97ok/lfk3ygaHSyZaCRTzRxQo6GzLfa2jWBPepw+UmT7SQEJyiyRkhBLMVOfcoMjcK0eZChfUNzFAUzCsEN5vP/X1uP/n/aoMX+K+nw/Hjr/9xOo7j7Pju61tLcgvJpTWXNbfN5jLpi6VfCOviTktKlFusQixdEKWmEBUKNaIpjZRSSOXSgzaaKLdabrm1/9nZ+/f+vd/vz/v9+Xy+zZ7PRorYoZqyLrCwQdEAixxVOEXNNnjX2nUSRlkqGmWowk8lxR50JPy9Bo6qJXaXwNvREBvnThPEPrewryLhcAnj5WE15Fqi8W7R1sAuEu86S4ENikItFN4xkv9Af4nXSnUVcLiA9xzesFpivRRVeFKtsMRaKBhuSbjOELnAUtlSQUpXgdfB4Z1oSbnFEetbQ0IrAe+Y+pqnDcEJFj6S8LDZzZHwY4e3XONNlARraomNEt2bkvGsosA3ioyHm+6jCMbI59wqt4eeara28IzEmyPgoRaUOEDhTVdEJhmCoTWfC0p8aNkCp0oYqih2iqGi4yXeMkOsn4LdLLnmKfh/YogjNsPebeFGR4m9BJHLzB61XQ3BtpISfS2FugsK9FAtLWX1dCRcrCnUp44CNzuCowUZmxSRgYaE6Za0W2u/E7CVXCiI/UOR8aAm1+OSyE3mOUcwyc1zBBeoX1kiKy0Zfxck1Gsyulti11i83QTBF5Kg3pDQThFMVHiPSlK+0cSedng/VaS8bOZbtsBcTcZAR8JP5KeqQ1OYKAi20njdNNRpgnsU//K+JnaXJaGTomr7aYIphoRn9aeShJWKEq9LcozSF7QleEfDI5LYm5bgVkFkRwVDBCVu0DDIkGupo8TZBq+/pMQURYErJQmPKGKjNDkWOLx7Jd5QizdUweIaKrlP7SwJDhZvONjLkOsBBX9UpGxnydhXkfBLQ8IxgojQbLFnJf81JytSljclYYyEFyx0kVBvKWOFJmONpshGAcsduQY5giVNCV51eOdJYo/pLhbvM0uDHSevNKRcrKZIqnCtJeEsO95RoqcgGK4ocZcho1tTYtcZvH41pNQ7vA0WrhIfOSraIIntIAi+NXWCErdbkvrWwjRLrt0NKUdL6KSOscTOdMSOUtBHwL6OLA0vNSdynaWQEnCpIvKaIrJJEbvHkmuNhn6OjM8VkSGSqn1uYJCGHnq9I3aLhNME3t6GjIkO7xrNFumpyTNX/NrwX7CrIRiqqWijI9JO4d1iieykyfiposQIQ8YjjsjlBh6oHWbwRjgYJQn2NgSnNycmJAk3NiXhx44Sxykihxm8ybUwT1OVKySc7vi3OXVkdBJ4AyXBeksDXG0IhgtYY0lY5ahCD0ehborIk5aUWRJviMA7Xt5kyRjonrXENkm8yYqgs8VzgrJmClK20uMM3jRJ0FiQICQF9hdETlLQWRIb5ki6WDfWRPobvO6a4GP5mcOrNzDFELtTkONLh9dXE8xypEg7z8A9jkhrQ6Fhjlg/QVktJXxt4WXzT/03Q8IaQWSqIuEvloQ2mqC9Jfi7wRul4RX3pSPlzpoVlmCtI2jvKHCFhjcM3sN6lqF6HxnKelLjXWbwrpR4xzuCrTUZx2qq9oAh8p6ixCUGr78g8oyjRAtB5CZFwi80VerVpI0h+IeBxa6Zg6kWvpDHaioYYuEsRbDC3eOmC2JvGYLeioxGknL2UATNJN6hmtj1DlpLvDVmocYbrGCVJKOrg4X6DgddLA203BKMFngdJJFtFd7vJLm6KEpc5yjQrkk7M80SGe34X24nSex1Ra5Omgb71JKyg8SrU3i/kARKwWpH0kOGhKkObyfd0ZGjvyXlAkVZ4xRbYJ2irFMkFY1SwyWxr2oo4zlNiV+7zmaweFpT4kR3kaDAFW6xpSqzJay05FtYR4HmZhc9UxKbbfF2V8RG1MBmSaE+kmC6JnaRXK9gsiXhJHl/U0qM0WTcbyhwkYIvFGwjSbjfwhiJt8ZSQU+Bd5+marPMOkVkD0muxYLIfEuhh60x/J92itguihJSEMySVPQnTewnEm+620rTQEMsOfo4/kP/0ARvWjitlpSX7GxBgcMEsd3EEeYWvdytd+Saawi6aCIj1CkGb6Aj9rwhx16Cf3vAwFy5pyLhVonXzy51FDpdEblbkdJbUcEPDEFzQ8qNmhzzLTmmKWKbFCXeEuRabp6rxbvAtLF442QjQ+wEA9eL1xSR7Q0JXzlSHjJ4exq89yR0laScJ/FW6z4a73pFMEfDiRZvuvijIt86RaSFOl01riV2mD1UEvxGk/Geg5aWwGki1zgKPG9J2U8PEg8qYvMsZeytiTRXBMslCU8JSlxi8EabjwUldlDNLfzTUmCgxWsjqWCOHavYAqsknKFIO0yQ61VL5AVFxk6WhEaCAkdJgt9aSkzXlKNX2jEa79waYuc7gq0N3GDJGCBhoiTXUEPsdknCUE1CK0fwsiaylSF2uiDyO4XX3pFhNd7R4itFGc0k/ElBZwWvq+GC6szVeEoS/MZ+qylwpKNKv9Z469UOjqCjwlusicyTxG6VpNxcQ8IncoR4RhLbR+NdpGGmJWOcIzJGUuKPGpQg8rrG21dOMqQssJQ4RxH5jaUqnZuQ0F4Q+cjxLwPtpZbIAk3QTJHQWBE5S1BokoVtDd6lhqr9UpHSUxMcIYl9pojsb8h4SBOsMQcqvOWC2E8EVehqiJ1hrrAEbQxeK0NGZ0Gkq+guSRgniM23bIHVkqwx4hiHd7smaOyglyIyQuM978j4VS08J/A2G1KeMBRo4fBaSNhKUEZfQewVQ/C1I+MgfbEleEzCUw7mKXI0M3hd1EESVji8x5uQ41nxs1q4RMJCCXs7Iq9acpxn22oSDnQ/sJTxsCbHIYZiLyhY05TY0ZLIOQrGaSJDDN4t8pVaIrsqqFdEegtizc1iTew5Q4ayBDMUsQMkXocaYkc0hZua412siZ1rSXlR460zRJ5SlHGe5j801RLMlJTxtaOM3Q1pvxJ45zUlWFD7rsAbpfEm1JHxG0eh8w2R7QQVzBUw28FhFp5QZzq8t2rx2joqulYTWSuJdTYfWwqMFMcovFmSyJPNyLhE4E10pHzYjOC3huArRa571ZsGajQpQx38SBP5pyZB6lMU3khDnp0MBV51BE9o2E+TY5Ml2E8S7C0o6w1xvCZjf0HkVEHCzFoyNmqC+9wdcqN+Tp7jSDheE9ws8Y5V0NJCn2bk2tqSY4okdrEhx1iDN8cSudwepWmAGXKcJXK65H9to8jYQRH7SBF01ESUJdd0TayVInaWhLkOjlXE5irKGOnI6GSWGCJa482zBI9rCr0jyTVcEuzriC1vcr6mwFGSiqy5zMwxBH/TJHwjSPhL8+01kaaSUuMFKTcLEvaUePcrSmwn8DZrgikWb7CGPxkSjhQwrRk57tctmxLsb9sZvL9LSlyuSLlWkqOjwduo8b6Uv1DkmudIeFF2dHCgxVtk8dpIvHpBxhEOdhKk7OLIUSdJ+cSRY57B+0DgGUUlNfpthTfGkauzxrvTsUUaCVhlKeteTXCoJDCa2NOKhOmC4G1H8JBd4OBZReSRGkqcb/CO1PyLJTLB4j1q8JYaIutEjSLX8YKM+a6phdMsdLFUoV5RTm9JSkuDN8WcIon0NZMNZWh1q8C7SJEwV5HxrmnnTrf3KoJBlmCYI2ilSLlfEvlE4011NNgjgthzEua0oKK7JLE7HZHlEl60BLMVFewg4EWNt0ThrVNEVkkiTwpKXSWJzdRENgvKGq4IhjsiezgSFtsfCUq8qki5S1LRQeYQQ4nemmCkImWMw3tFUoUBZk4NOeZYEp4XRKTGa6wJjrWNHBVJR4m3FCnbuD6aak2WsMTh3SZImGCIPKNgsDpVwnsa70K31lCFJZYcwwSMFcQulGTsZuEaSdBXkPGZhu0FsdUO73RHjq8MPGGIfaGIbVTk6iuI3GFgucHrIQkmWSJdBd7BBu+uOryWAhY7+Lki9rK5wtEQzWwvtbqGhIMFwWRJsElsY4m9IIg9L6lCX0VklaPAYkfkZEGDnOWowlBJjtMUkcGK4Lg6EtoZInMUBVYLgn0UsdmCyCz7gIGHFfk+k1QwTh5We7A9x+IdJ6CvIkEagms0hR50eH9UnTQJ+2oiKyVlLFUE+8gBGu8MQ3CppUHesnjTHN4QB/UGPhCTHLFPHMFrCqa73gqObUJGa03wgbhHkrCfpEpzNLE7JDS25FMKhlhKKWKfCgqstLCPu1zBXy0J2ztwjtixBu8UTRn9LVtkmCN2iyFhtME70JHRQ1KVZXqKI/KNIKYMCYs1GUMEKbM1bKOI9LDXC7zbHS+bt+1MTWS9odA9DtrYtpbImQJ2VHh/lisEwaHqUk1kjKTAKknkBEXkbkdMGwq0dnhzLJF3NJH3JVwrqOB4Sca2hti75nmJN0WzxS6UxDYoEpxpa4htVlRjkYE7DZGzJVU72uC9IyhQL4i8YfGWSYLLNcHXloyz7QhNifmKSE9JgfGmuyLhc403Xm9vqcp6gXe3xuuv8F6VJNxkyTHEkHG2g0aKXL0MsXc1bGfgas2//dCONXiNLCX+5mB7eZIl1kHh7ajwpikyzlUUWOVOsjSQlsS+M0R+pPje/dzBXRZGO0rMtgQrLLG9VSu9n6CMXS3BhwYmSoIBhsjNBmZbgusE9BCPCP5triU4VhNbJfE+swSP27aayE8tuTpYYjtrYjMVGZdp2NpS1s6aBnKSHDsbKuplKbHM4a0wMFd/5/DmGyKrJSUaW4IBrqUhx0vyfzTBBLPIUcnZdrAkNsKR0sWRspumSns6Ch0v/qqIbBYUWKvPU/CFoyrDJGwSNFhbA/MlzKqjrO80hRbpKx0Jewsi/STftwGSlKc1JZyAzx05dhLEdnfQvhZOqiHWWEAHC7+30FuRcZUgaO5gpaIK+xsiHRUsqaPElTV40xQZQ107Q9BZE1nryDVGU9ZSQ47bmhBpLcYpUt7S+xuK/FiT8qKjwXYw5ypS2iuCv7q1gtgjhuBuB8LCFY5cUuCNtsQOFcT+4Ih9JX+k8Ea6v0iCIRZOtCT0Et00JW5UeC85Cg0ScK0k411HcG1zKtre3SeITBRk7WfwDhEvaYLTHP9le0m8By0JDwn4TlLW/aJOvGHxdjYUes+ScZigCkYQdNdEOhkiezgShqkx8ueKjI8lDfK2oNiOFvrZH1hS+tk7NV7nOmLHicGWEgubkXKdwdtZknCLJXaCpkrjZBtLZFsDP9CdxWsSr05Sxl6CMmoFbCOgryX40uDtamB7SVmXW4Ihlgpmq+00tBKUUa83WbjLUNkzDmY7cow1JDygyPGlhgGKYKz4vcV7QBNbJIgM11TUqZaMdwTeSguH6rOaw1JRKzaaGyxVm2EJ/uCIrVWUcZUkcp2grMsEjK+DMwS59jQk3Kd6SEq1d0S6uVmO4Bc1lDXTUcHjluCXEq+1OlBDj1pi9zgiXxnKuE0SqTXwhqbETW6RggMEnGl/q49UT2iCzgJvRwVXS2K/d6+ZkyUl7jawSVLit46EwxVljDZwoSQ20sDBihztHfk2yA8NVZghiXwrYHQdfKAOtzsayjhY9bY0yE2CWEeJ9xfzO423xhL5syS2TFJofO2pboHob0nY4GiAgRrvGQEDa/FWSsoaaYl0syRsEt3kWoH3B01shCXhTUWe9w3Bt44SC9QCh3eShQctwbaK2ApLroGCMlZrYqvlY3qYhM0aXpFkPOuoqJ3Dm6fxXrGwVF9gCWZagjPqznfkuMKQ8DPTQRO8ZqG1hPGKEm9IgpGW4DZDgTNriTxvFiq+Lz+0cKfp4wj6OCK9JSnzNSn9LFU7UhKZZMnYwcJ8s8yRsECScK4j5UOB95HFO0CzhY4xJxuCix0lDlEUeMdS6EZBkTsUkZ4K74dugyTXS7aNgL8aqjDfkCE0ZbwkCXpaWCKhl8P7VD5jxykivSyxyZrYERbe168LYu9ZYh86IkscgVLE7tWPKmJv11CgoyJltMEbrohtVAQfO4ImltiHEroYEs7RxAarVpY8AwXMcMReFOTYWe5iiLRQxJ5Q8DtJ8LQhWOhIeFESPGsILhbNDRljNbHzNRlTFbk2S3L0NOS6V1KFJYKUbSTcIIhM0wQ/s2TM0SRMNcQmSap3jCH4yhJZKSkwyRHpYYgsFeQ4U7xoCB7VVOExhXepo9ABBsYbvGWKXPME3lyH95YioZ0gssQRWWbI+FaSMkXijZXwgiTlYdPdkNLaETxlyDVIwqeaEus0aTcYcg0RVOkpR3CSJqIddK+90JCxzsDVloyrFd5ZAr4TBKfaWa6boEA7C7s6EpYaeFPjveooY72mjIccLHJ9HUwVlDhKkmutJDJBwnp1rvulJZggKDRfbXAkvC/4l3ozQOG9a8lxjx0i7nV4jSXc7vhe3OwIxjgSHjdEhhsif9YkPGlus3iLFDnWOFhtCZbJg0UbQcIaR67JjthoCyMEZRwhiXWyxO5QxI6w5NhT4U1WsJvDO60J34fW9hwzwlKij6ZAW9ne4L0s8C6XeBMEkd/LQy1VucBRot6QMlbivaBhoBgjqGiCJNhsqVp/S2SsG6DIONCR0dXhvWbJ+MRRZJkkuEjgDXJjFQW6SSL7GXK8Z2CZg7cVsbWGoKmEpzQ5elpiy8Ryg7dMkLLUEauzeO86CuwlSOlgYLojZWeJ9xM3S1PWfEfKl5ISLQ0MEKR8YOB2QfCxJBjrKPCN4f9MkaSsqoVXJBmP7EpFZ9UQfOoOFwSzBN4MQ8LsGrymlipcJQhmy0GaQjPqCHaXRwuCZwRbqK2Fg9wlClZqYicrIgMdZfxTQ0c7TBIbrChxmuzoKG8XRaSrIhhiyNFJkrC7oIAWMEOQa5aBekPCRknCo4IKPrYkvCDI8aYmY7WFtprgekcJZ3oLIqssCSMtFbQTJKwXYy3BY5oCh2iKPCpJOE+zRdpYgi6O2KmOAgvVCYaU4ySRek1sgyFhJ403QFHiVEmJHwtybO1gs8Hr5+BETQX3War0qZngYGgtVZtoqd6vFSk/UwdZElYqyjrF4HXUeFspIi9IGKf4j92pKGAdCYMVsbcV3kRF0N+R8LUd5PCsIGWoxDtBkCI0nKofdJQxT+LtZflvuc8Q3CjwWkq8KwUpHzkK/NmSsclCL0nseQdj5FRH5CNHSgtLiW80Of5HU9Hhlsga9bnBq3fEVltKfO5IaSTmGjjc4J0otcP7QsJUSQM8pEj5/wCuUuC2DWz8AAAAAElFTkSuQmCC\");\n}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/theme/blackboard.css",
    "content": "/* Port of TextMate's Blackboard theme */\n\n.cm-s-blackboard { background: #0C1021; color: #F8F8F8; }\n.cm-s-blackboard .CodeMirror-selected { background: #253B76 !important; }\n.cm-s-blackboard .CodeMirror-gutter { background: #0C1021; border-right: 0; }\n.cm-s-blackboard .CodeMirror-gutter-text { color: #888; }\n.cm-s-blackboard .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; }\n\n.cm-s-blackboard .cm-keyword { color: #FBDE2D; }\n.cm-s-blackboard .cm-atom { color: #D8FA3C; }\n.cm-s-blackboard .cm-number { color: #D8FA3C; }\n.cm-s-blackboard .cm-def { color: #8DA6CE; }\n.cm-s-blackboard .cm-variable { color: #FF6400; }\n.cm-s-blackboard .cm-operator { color: #FBDE2D;}\n.cm-s-blackboard .cm-comment { color: #AEAEAE; }\n.cm-s-blackboard .cm-string { color: #61CE3C; }\n.cm-s-blackboard .cm-string-2 { color: #61CE3C; }\n.cm-s-blackboard .cm-meta { color: #D8FA3C; }\n.cm-s-blackboard .cm-error { background: #9D1E15; color: #F8F8F8; }\n.cm-s-blackboard .cm-builtin { color: #8DA6CE; }\n.cm-s-blackboard .cm-tag { color: #8DA6CE; }\n.cm-s-blackboard .cm-attribute { color: #8DA6CE; }\n.cm-s-blackboard .cm-header { color: #FF6400; }\n.cm-s-blackboard .cm-hr { color: #AEAEAE; }\n.cm-s-blackboard .cm-link { color: #8DA6CE; }\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/theme/cobalt.css",
    "content": ".cm-s-cobalt { background: #002240; color: white; }\n.cm-s-cobalt div.CodeMirror-selected { background: #b36539 !important; }\n.cm-s-cobalt .CodeMirror-gutter { background: #002240; border-right: 1px solid #aaa; }\n.cm-s-cobalt .CodeMirror-gutter-text { color: #d0d0d0; }\n.cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white !important; }\n\n.cm-s-cobalt span.cm-comment { color: #08f; }\n.cm-s-cobalt span.cm-atom { color: #845dc4; }\n.cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; }\n.cm-s-cobalt span.cm-keyword { color: #ffee80; }\n.cm-s-cobalt span.cm-string { color: #3ad900; }\n.cm-s-cobalt span.cm-meta { color: #ff9d00; }\n.cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; }\n.cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; }\n.cm-s-cobalt span.cm-error { color: #9d1e15; }\n.cm-s-cobalt span.cm-bracket { color: #d8d8d8; }\n.cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; }\n.cm-s-cobalt span.cm-link { color: #845dc4; }\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/theme/eclipse.css",
    "content": ".cm-s-eclipse span.cm-meta {color: #FF1717;}\n.cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; }\n.cm-s-eclipse span.cm-atom {color: #219;}\n.cm-s-eclipse span.cm-number {color: #164;}\n.cm-s-eclipse span.cm-def {color: #00f;}\n.cm-s-eclipse span.cm-variable {color: black;}\n.cm-s-eclipse span.cm-variable-2 {color: #0000C0;}\n.cm-s-eclipse span.cm-variable-3 {color: #0000C0;}\n.cm-s-eclipse span.cm-property {color: black;}\n.cm-s-eclipse span.cm-operator {color: black;}\n.cm-s-eclipse span.cm-comment {color: #3F7F5F;}\n.cm-s-eclipse span.cm-string {color: #2A00FF;}\n.cm-s-eclipse span.cm-string-2 {color: #f50;}\n.cm-s-eclipse span.cm-error {color: #f00;}\n.cm-s-eclipse span.cm-qualifier {color: #555;}\n.cm-s-eclipse span.cm-builtin {color: #30a;}\n.cm-s-eclipse span.cm-bracket {color: #cc7;}\n.cm-s-eclipse span.cm-tag {color: #170;}\n.cm-s-eclipse span.cm-attribute {color: #00c;}\n.cm-s-eclipse span.cm-link {color: #219;}\n\n.cm-s-eclipse .CodeMirror-matchingbracket {\n\tborder:1px solid grey;\n\tcolor:black !important;;\n}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/theme/elegant.css",
    "content": ".cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom {color: #762;}\n.cm-s-elegant span.cm-comment {color: #262; font-style: italic; line-height: 1em;}\n.cm-s-elegant span.cm-meta {color: #555; font-style: italic; line-height: 1em;}\n.cm-s-elegant span.cm-variable {color: black;}\n.cm-s-elegant span.cm-variable-2 {color: #b11;}\n.cm-s-elegant span.cm-qualifier {color: #555;}\n.cm-s-elegant span.cm-keyword {color: #730;}\n.cm-s-elegant span.cm-builtin {color: #30a;}\n.cm-s-elegant span.cm-error {background-color: #fdd;}\n.cm-s-elegant span.cm-link {color: #762;}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/theme/erlang-dark.css",
    "content": ".cm-s-erlang-dark { background: #002240; color: white; }\n.cm-s-erlang-dark div.CodeMirror-selected { background: #b36539 !important; }\n.cm-s-erlang-dark .CodeMirror-gutter { background: #002240; border-right: 1px solid #aaa; }\n.cm-s-erlang-dark .CodeMirror-gutter-text { color: #d0d0d0; }\n.cm-s-erlang-dark .CodeMirror-cursor { border-left: 1px solid white !important; }\n\n.cm-s-erlang-dark span.cm-atom       { color: #845dc4; }\n.cm-s-erlang-dark span.cm-attribute  { color: #ff80e1; }\n.cm-s-erlang-dark span.cm-bracket    { color: #ff9d00; }\n.cm-s-erlang-dark span.cm-builtin    { color: #eeaaaa; }\n.cm-s-erlang-dark span.cm-comment    { color: #7777ff; }\n.cm-s-erlang-dark span.cm-def        { color: #ee77aa; }\n.cm-s-erlang-dark span.cm-error      { color: #9d1e15; }\n.cm-s-erlang-dark span.cm-keyword    { color: #ffee80; }\n.cm-s-erlang-dark span.cm-meta       { color: #50fefe; }\n.cm-s-erlang-dark span.cm-number     { color: #ffd0d0; }\n.cm-s-erlang-dark span.cm-operator   { color: #dd1111; }\n.cm-s-erlang-dark span.cm-string     { color: #3ad900; }\n.cm-s-erlang-dark span.cm-tag        { color: #9effff; }\n.cm-s-erlang-dark span.cm-variable   { color: #50fe50; }\n.cm-s-erlang-dark span.cm-variable-2 { color: #ee00ee; }\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/theme/lesser-dark.css",
    "content": "/*\nhttp://lesscss.org/ dark theme\nPorted to CodeMirror by Peter Kroon\n*/\n.CodeMirror{\n  line-height: 17px;\n}\n.cm-s-lesser-dark {\n  font-family: 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Monaco', Courier, monospace !important;\n  font-size:14px;\n}\n\n.cm-s-lesser-dark { background: #262626; color: #EBEFE7; text-shadow: 0 -1px 1px #262626; }\n.cm-s-lesser-dark div.CodeMirror-selected {background: #45443B !important;} /* 33322B*/\n.cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white !important; }\n.cm-s-lesser-dark .CodeMirror-lines { margin-left:3px; margin-right:3px; }/*editable code holder*/\n\ndiv.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/\n\n.cm-s-lesser-dark .CodeMirror-gutter { background: #262626; border-right:1px solid #aaa; padding-right:3px; min-width:2.5em; }\n.cm-s-lesser-dark .CodeMirror-gutter-text { color: #777; }\n\n.cm-s-lesser-dark span.cm-keyword { color: #599eff; }\n.cm-s-lesser-dark span.cm-atom { color: #C2B470; }\n.cm-s-lesser-dark span.cm-number { color: #B35E4D; }\n.cm-s-lesser-dark span.cm-def {color: white;}\n.cm-s-lesser-dark span.cm-variable { color:#D9BF8C; }\n.cm-s-lesser-dark span.cm-variable-2 { color: #669199; }\n.cm-s-lesser-dark span.cm-variable-3 { color: white; }\n.cm-s-lesser-dark span.cm-property {color: #92A75C;}\n.cm-s-lesser-dark span.cm-operator {color: #92A75C;}\n.cm-s-lesser-dark span.cm-comment { color: #666; }\n.cm-s-lesser-dark span.cm-string { color: #BCD279; }\n.cm-s-lesser-dark span.cm-string-2 {color: #f50;}\n.cm-s-lesser-dark span.cm-meta { color: #738C73; }\n.cm-s-lesser-dark span.cm-error { color: #9d1e15; }\n.cm-s-lesser-dark span.cm-qualifier {color: #555;}\n.cm-s-lesser-dark span.cm-builtin { color: #ff9e59; }\n.cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; }\n.cm-s-lesser-dark span.cm-tag { color: #669199; }\n.cm-s-lesser-dark span.cm-attribute {color: #66c;}\n.cm-s-lesser-dark span.cm-header {color: #a0a;}\n.cm-s-lesser-dark span.cm-quote {color: #090;}\n.cm-s-lesser-dark span.cm-hr {color: #999;}\n.cm-s-lesser-dark span.cm-link {color: #00c;}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/theme/monokai.css",
    "content": "/* Based on Sublime Text's Monokai theme */\n\n.cm-s-monokai {background: #272822; color: #f8f8f2;}\n.cm-s-monokai div.CodeMirror-selected {background: #49483E !important;}\n.cm-s-monokai .CodeMirror-gutter {background: #272822; border-right: 0px;}\n.cm-s-monokai .CodeMirror-gutter-text {color: #d0d0d0;}\n.cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;}\n\n.cm-s-monokai span.cm-comment {color: #75715e;}\n.cm-s-monokai span.cm-atom {color: #ae81ff;}\n.cm-s-monokai span.cm-number {color: #ae81ff;}\n\n.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;}\n.cm-s-monokai span.cm-keyword {color: #f92672;}\n.cm-s-monokai span.cm-string {color: #e6db74;}\n\n.cm-s-monokai span.cm-variable {color: #a6e22e;}\n.cm-s-monokai span.cm-variable-2 {color: #9effff;}\n.cm-s-monokai span.cm-def {color: #fd971f;}\n.cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;}\n.cm-s-monokai span.cm-bracket {color: #f8f8f2;}\n.cm-s-monokai span.cm-tag {color: #f92672;}\n.cm-s-monokai span.cm-link {color: #ae81ff;}\n\n.cm-s-monokai .CodeMirror-matchingbracket {\n  text-decoration: underline;\n  color: white !important;\n}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/theme/neat.css",
    "content": ".cm-s-neat span.cm-comment { color: #a86; }\n.cm-s-neat span.cm-keyword { line-height: 1em; font-weight: bold; color: blue; }\n.cm-s-neat span.cm-string { color: #a22; }\n.cm-s-neat span.cm-builtin { line-height: 1em; font-weight: bold; color: #077; }\n.cm-s-neat span.cm-special { line-height: 1em; font-weight: bold; color: #0aa; }\n.cm-s-neat span.cm-variable { color: black; }\n.cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; }\n.cm-s-neat span.cm-meta {color: #555;}\n.cm-s-neat span.cm-link { color: #3a3; }\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/theme/night.css",
    "content": "/* Loosely based on the Midnight Textmate theme */\n\n.cm-s-night { background: #0a001f; color: #f8f8f8; }\n.cm-s-night div.CodeMirror-selected { background: #a8f !important; }\n.cm-s-night .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; }\n.cm-s-night .CodeMirror-gutter-text { color: #f8f8f8; }\n.cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; }\n\n.cm-s-night span.cm-comment { color: #6900a1; }\n.cm-s-night span.cm-atom { color: #845dc4; }\n.cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; }\n.cm-s-night span.cm-keyword { color: #599eff; }\n.cm-s-night span.cm-string { color: #37f14a; }\n.cm-s-night span.cm-meta { color: #7678e2; }\n.cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; }\n.cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; }\n.cm-s-night span.cm-error { color: #9d1e15; }\n.cm-s-night span.cm-bracket { color: #8da6ce; }\n.cm-s-night span.cm-comment { color: #6900a1; }\n.cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; }\n.cm-s-night span.cm-link { color: #845dc4; }\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/theme/rubyblue.css",
    "content": ".cm-s-rubyblue { font:13px/1.4em Trebuchet, Verdana, sans-serif; }\t/* - customized editor font - */\n\n.cm-s-rubyblue { background: #112435; color: white; }\n.cm-s-rubyblue div.CodeMirror-selected { background: #38566F !important; }\n.cm-s-rubyblue .CodeMirror-gutter { background: #1F4661; border-right: 7px solid #3E7087; min-width:2.5em; }\n.cm-s-rubyblue .CodeMirror-gutter-text { color: white; }\n.cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white !important; }\n\n.cm-s-rubyblue span.cm-comment { color: #999; font-style:italic; line-height: 1em; }\n.cm-s-rubyblue span.cm-atom { color: #F4C20B; }\n.cm-s-rubyblue span.cm-number, .cm-s-rubyblue span.cm-attribute { color: #82C6E0; }\n.cm-s-rubyblue span.cm-keyword { color: #F0F; }\n.cm-s-rubyblue span.cm-string { color: #F08047; }\n.cm-s-rubyblue span.cm-meta { color: #F0F; }\n.cm-s-rubyblue span.cm-variable-2, .cm-s-rubyblue span.cm-tag { color: #7BD827; }\n.cm-s-rubyblue span.cm-variable-3, .cm-s-rubyblue span.cm-def { color: white; }\n.cm-s-rubyblue span.cm-error { color: #AF2018; }\n.cm-s-rubyblue span.cm-bracket { color: #F0F; }\n.cm-s-rubyblue span.cm-link { color: #F4C20B; }\n.cm-s-rubyblue span.CodeMirror-matchingbracket { color:#F0F !important; }\n.cm-s-rubyblue span.cm-builtin, .cm-s-rubyblue span.cm-special { color: #FF9D00; }\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/cm/theme/xq-dark.css",
    "content": "/*\nCopyright (C) 2011 by MarkLogic Corporation\nAuthor: Mike Brevoort <mike@brevoort.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n*/\n.cm-s-xq-dark { background: #0a001f; color: #f8f8f8; }\n.cm-s-xq-dark span.CodeMirror-selected { background: #a8f !important; }\n.cm-s-xq-dark .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; }\n.cm-s-xq-dark .CodeMirror-gutter-text { color: #f8f8f8; }\n.cm-s-xq-dark .CodeMirror-cursor { border-left: 1px solid white !important; }\n\n.cm-s-xq-dark span.cm-keyword {color: #FFBD40;}\n.cm-s-xq-dark span.cm-atom {color: #6C8CD5;}\n.cm-s-xq-dark span.cm-number {color: #164;}\n.cm-s-xq-dark span.cm-def {color: #FFF; text-decoration:underline;}\n.cm-s-xq-dark span.cm-variable {color: #FFF;}\n.cm-s-xq-dark span.cm-variable-2 {color: #EEE;}\n.cm-s-xq-dark span.cm-variable-3 {color: #DDD;}\n.cm-s-xq-dark span.cm-property {}\n.cm-s-xq-dark span.cm-operator {}\n.cm-s-xq-dark span.cm-comment {color: gray;}\n.cm-s-xq-dark span.cm-string {color: #9FEE00;}\n.cm-s-xq-dark span.cm-meta {color: yellow;}\n.cm-s-xq-dark span.cm-error {color: #f00;}\n.cm-s-xq-dark span.cm-qualifier {color: #FFF700;}\n.cm-s-xq-dark span.cm-builtin {color: #30a;}\n.cm-s-xq-dark span.cm-bracket {color: #cc7;}\n.cm-s-xq-dark span.cm-tag {color: #FFBD40;}\n.cm-s-xq-dark span.cm-attribute {color: #FFF700;}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/editor.js",
    "content": "var newButton, openButton, saveButton;\nvar editor;\nvar fileEntry;\nvar hasWriteAccess;\n\nfunction errorHandler(e) {\n  var msg = \"\";\n\n  switch (e.code) {\n    case FileError.QUOTA_EXCEEDED_ERR:\n    msg = \"QUOTA_EXCEEDED_ERR\";\n    break;\n    case FileError.NOT_FOUND_ERR:\n    msg = \"NOT_FOUND_ERR\";\n    break;\n    case FileError.SECURITY_ERR:\n    msg = \"SECURITY_ERR\";\n    break;\n    case FileError.INVALID_MODIFICATION_ERR:\n    msg = \"INVALID_MODIFICATION_ERR\";\n    break;\n    case FileError.INVALID_STATE_ERR:\n    msg = \"INVALID_STATE_ERR\";\n    break;\n    default:\n    msg = \"Unknown Error\";\n    break;\n  };\n\n  console.log(\"Error: \" + msg);\n}\n\nfunction handleDocumentChange(title) {\n  var mode = \"javascript\";\n  var modeName = \"JavaScript\";\n  if (title) {\n    title = title.match(/[^/]+$/)[0];\n    document.getElementById(\"title\").innerHTML = title;\n    document.title = title;\n    if (title.match(/.json$/)) {\n      mode = {name: \"javascript\", json: true};\n      modeName = \"JavaScript (JSON)\";\n    } else if (title.match(/.html$/)) {\n      mode = \"htmlmixed\";\n      modeName = \"HTML\";\n    } else if (title.match(/.css$/)) {\n      mode = \"css\";\n      modeName = \"CSS\";\n    }\n  } else {\n    document.getElementById(\"title\").innerHTML = \"[no document loaded]\";\n  }\n  editor.setOption(\"mode\", mode);\n  document.getElementById(\"mode\").innerHTML = modeName;\n}\n\nfunction newFile() {\n  fileEntry = null;\n  hasWriteAccess = false;\n  handleDocumentChange(null);\n}\n\nfunction setFile(theFileEntry, isWritable) {\n  fileEntry = theFileEntry;\n  hasWriteAccess = isWritable;\n}\n\nfunction readFileIntoEditor(theFileEntry) {\n  if (theFileEntry) {\n    theFileEntry.file(function(file) {\n      var fileReader = new FileReader();\n\n      fileReader.onload = function(e) {\n        handleDocumentChange(theFileEntry.fullPath);\n        editor.setValue(e.target.result);\n      };\n\n      fileReader.onerror = function(e) {\n        console.log(\"Read failed: \" + e.toString());\n      };\n\n      fileReader.readAsText(file);\n    }, errorHandler);\n  }\n}\n\nfunction writeEditorToFile(theFileEntry) {\n  theFileEntry.createWriter(function(fileWriter) {\n    fileWriter.onerror = function(e) {\n      console.log(\"Write failed: \" + e.toString());\n    };\n\n    var blob = new Blob([editor.getValue()]);\n    fileWriter.truncate(blob.size);\n    fileWriter.onwriteend = function() {\n      fileWriter.onwriteend = function(e) {\n        handleDocumentChange(theFileEntry.fullPath);\n        console.log(\"Write completed.\");\n      };\n\n      fileWriter.write(blob);\n    }\n  }, errorHandler);\n}\n\nvar onChosenFileToOpen = function(theFileEntry) {\n  setFile(theFileEntry, false);\n  readFileIntoEditor(theFileEntry);\n};\n\nvar onWritableFileToOpen = function(theFileEntry) {\n  setFile(theFileEntry, true);\n  readFileIntoEditor(theFileEntry);\n};\n\nvar onChosenFileToSave = function(theFileEntry) {\n  setFile(theFileEntry, true);\n  writeEditorToFile(theFileEntry);\n};\n\nfunction handleNewButton() {\n  if (false) {\n    newFile();\n    editor.setValue(\"\");\n  } else {\n    chrome.app.window.create('main.html', {\n      frame: 'chrome', id: \"codewin\", innerBounds: { width: 720, height: 400}\n    });\n  }\n}\n\nfunction handleOpenButton() {\n  chrome.fileSystem.chooseEntry({ type: 'openWritableFile' }, onWritableFileToOpen);\n}\n\nfunction handleSaveButton() {\n  if (fileEntry && hasWriteAccess) {\n    writeEditorToFile(fileEntry);\n  } else {\n    chrome.fileSystem.chooseEntry({ type: 'saveFile' }, onChosenFileToSave);\n  }\n}\n\nfunction initContextMenu() {\n  chrome.contextMenus.removeAll(function() {\n    for (var snippetName in SNIPPETS) {\n      chrome.contextMenus.create({\n        title: snippetName,\n        id: snippetName,\n        contexts: ['all']\n      });\n    }\n  });\n}\n\nchrome.contextMenus.onClicked.addListener(function(info) {\n  // Context menu command wasn't meant for us.\n  if (!document.hasFocus()) {\n    return;\n  }\n\n  editor.replaceSelection(SNIPPETS[info.menuItemId]);\n});\n\nonload = function() {\n  initContextMenu();\n\n  newButton = document.getElementById(\"new\");\n  openButton = document.getElementById(\"open\");\n  saveButton = document.getElementById(\"save\");\n\n  newButton.addEventListener(\"click\", handleNewButton);\n  openButton.addEventListener(\"click\", handleOpenButton);\n  saveButton.addEventListener(\"click\", handleSaveButton);\n\n  editor = CodeMirror(\n    document.getElementById(\"editor\"),\n    {\n      mode: {name: \"javascript\", json: true },\n      lineNumbers: true,\n      theme: \"lesser-dark\",\n      fixedGutter: true,\n      extraKeys: {\n        \"Cmd-S\": function(instance) { handleSaveButton() },\n        \"Ctrl-S\": function(instance) { handleSaveButton() },\n      }\n    });\n\n  newFile();\n  onresize();\n};\n\nonresize = function() {\n  var container = document.getElementById('editor');\n  var containerWidth = container.offsetWidth;\n  var containerHeight = container.offsetHeight;\n\n  var scrollerElement = editor.getScrollerElement();\n  scrollerElement.style.width = containerWidth + 'px';\n  scrollerElement.style.height = containerHeight + 'px';\n\n  editor.refresh();\n}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/img/README.txt",
    "content": "Icons from http://www.smashingmagazine.com/2008/09/02/simplicio-a-free-icon-set/"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/main.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\n<script src=\"snippets.js\"></script>\n<script src=\"editor.js\"></script>\n\n<script src=\"cm/lib/codemirror.js\"></script>\n<script src=\"cm/mode/css/css.js\"></script>\n<script src=\"cm/mode/xml/xml.js\"></script>\n<script src=\"cm/mode/javascript/javascript.js\"></script>\n<script src=\"cm/mode/htmlmixed/htmlmixed.js\"></script>\n\n<link rel=\"stylesheet\" href=\"style.css\">\n<link rel=\"stylesheet\" href=\"cm/lib/codemirror.css\">\n<link rel=\"stylesheet\" href=\"cm/theme/lesser-dark.css\">\n</head>\n\n<body>\n\n<div class=\"buttons\">\n\t<button id=\"new\"> <img src=\"img/16x16/file_add.png\"/> New </button>\n\t<button id=\"open\"><img src=\"img/16x16/file.png\"/> Open </button>\n\t<button id=\"save\"><img src=\"img/16x16/diskette.png\"/> Save </button>\n</div>\n\n<div id=\"editor\"></div>\n\n<div class=\"info\">\n  <label>Filename: </label><span id=\"title\"></span>\n  <label>Mode: </label><span id=\"mode\"></span>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/manifest.json",
    "content": "{\n  \"name\": \"MiniCodeEdit\",\n  \"version\": \"0.1.12\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"23\",\n  \"description\": \"A very small code editor.\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n\n  \"permissions\": [\n    {\"fileSystem\": [\"write\"]},\n    \"unlimitedStorage\",\n    \"contextMenus\"\n  ],\n\n  \"icons\": {\n    \"16\":  \"img/16x16/file_edit.png\",\n    \"32\":  \"img/32x32/file_edit.png\",\n    \"64\":  \"img/64x64/file_edit.png\",\n    \"128\": \"img/128x128/file_edit.png\"\n  },\n\n  \"commands\" : {\n    \"cmdNew\": {\n        \"suggested_key\": {\n          \"default\": \"Ctrl+Shift+1\"\n        },\n        \"global\": true,\n        \"description\": \"Create new window\"\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/snippets.js",
    "content": "// These snippets contain code that was valid at the time of the June 2012 Google I/O\n// presentation during which we used this code editor. The APIs have evolved since then,\n// but we are not necessarily keeping these snippets up to date. Please don't expect\n// that they'll work.\nvar SNIPPETS = {\n  \"Hello World: Manifest\": '{\\n  \"manifest_version\": 2,\\n  \"name\": \"Hello World\",\\n  \"version\": \"0.0.1\",\\n  \"app\": {\\n    \"background\": {\\n      \"scripts\": [\"main.js\"]\\n    }\\n  },\\n}\\n',\n  \"Hello World: main.js\": \"chrome.app.runtime.onLaunched.addListener(function() {\\n  chrome.app.window.create('window.html', {\\n    bounds: { \\n      width: 400,\\n      height: 400\\n    }});\\n})\",\n  \"Hello World: window.html\": '<!DOCTYPE html>\\n<html>\\n  <body>\\n    <h1>Hello World!</h1>\\n  </body>\\n</html>',\n  \"Hello World: window.html w/form\": '<!DOCTYPE html>\\n<html>\\n  <script src=\"window.js\"></script>\\n  </head>\\n  <body>  \\n\\n    <form id=\"name-form\">\\n      <input id=\"name-input\" size=\"40\">\\n      <input type=\"submit\">\\n    </form>\\n  \\n    <h2>Hello <span id=\"output\"></span></h2> \\n  </body>\\n</html>',\n  \"Hello World: window.js\": \"onload = function() {\\n  document.getElementById('name-form').onsubmit = function(e) {\\n    e.preventDefault();\\n\\n    document.getElementById('output').innerHTML =\\n        document.getElementById('name-input').value;\\n  };\\n};\\n\",\n  \"Servo: onRead\": \"function onRead(readInfo) {\\n  var uint8View = new Uint8Array(readInfo.data);\\n  var value = uint8View[0] - '0'.charCodeAt(0);\\n  var rotation = value * 18.0;\\n\\n  document.getElementById('image').style.webkitTransform =\\n    'rotateZ(' + rotation + 'deg)';\\n\\n  // Keep on reading.\\n  chrome.serial.read(connectionId, onRead);\\n};\"\n};\n"
  },
  {
    "path": "_archive/apps/samples/mini-code-edit/style.css",
    "content": "body {\n  margin: 0;\n  padding: 0;\n  overflow: hidden;\n}\n\nbutton {\n  margin: 0;\n}\n\n.CodeMirror {\n  margin: 0;\n  padding: 0;\n}\n\n.CodeMirror-scroll {\n  height: auto;\n  overflow-y: hidden;\n  overflow-x: auto;\n}\n\n#editor {\n  position: absolute;\n  top: 29px;\n  bottom: 24px;\n  left: 0;\n  right: 0;\n  background: #262626;\n}\n\n.info {\n  font-family: monospace;\n  white-space: nowrap;\n  position: absolute;\n  bottom: 0;\n  background: #eee;\n  padding: 2px;\n  height: 20px;\n  left: 0;\n  right: 0;\n}\n\n.info label {\n  font-weight: bold;\n}\n\n.buttons {\n  padding: 2px;\n  height: 25px;\n}\n"
  },
  {
    "path": "_archive/apps/samples/multicast/ChatClient.js",
    "content": "function ChatClient(config) {\n  this.name = config.name || \"Anonymous\";\n  this.knownUsers = {};\n  this.knownUsersCount = 0;\n  MulticastSocket.call(this, config);\n}\nfunction emptyFn() {\n}\nvar invalidCharRe = /[^\\w \\(\\)'\"\\.,\\\\\\/\\?]/g;\nvar proto = ChatClient.prototype =\n  Object.create(MulticastSocket.prototype);\nproto.connected = false;\n\nproto.onError = function (err) {\n  this.onInfo(err, \"error\");\n};\n\nproto.onConnected = function () {\n  var me = this;\n  this.onInfo(\"Connected as [\" + this.name + \"]\");\n  this.connected = true;\n};\n\nproto.onDisconnected = function () {\n  this.clearUser();\n  this.onInfo(\"Disconnected\");\n  this.connected = false;\n};\n\nproto.onDiagram = function (message, address) {\n  message = this.arrayBufferToString(message);\n  try {\n    var obj = JSON.parse(message);\n  } catch (e) {\n    return;\n  }\n  if (!obj) {\n    return;\n  }\n  switch (obj.type) {\n    case 'message':\n      this.onMessage(obj.message, obj.name, address);\n      break;\n    case 'hello':\n      this.sendDiagram(JSON.stringify({\n        type: \"ack\",\n        name: this.name\n      }));\n      this.addUser(obj.name, address);\n      break;\n    case 'ack':\n      this.addUser(obj.name, address);\n      break;\n    case 'goodbye':\n      this.removeUser(obj.name, address);\n      break;\n  }\n};\n\nproto.addUser = function (name, ip) {\n  name = name.replace(invalidCharRe, '');\n  if (this.knownUsers.hasOwnProperty(name)) {\n    if (this.knownUsers[name].hasOwnProperty(ip)) {\n      return;\n    }\n  } else {\n    this.knownUsers[name] = {};\n  }\n  this.knownUsersCount++;\n  this.knownUsers[name][ip] = true;\n  this.onAddUser(name, ip);\n};\n\nproto.removeUser = function (name, ip) {\n  if (this.knownUsers.hasOwnProperty(name)) {\n    if (this.knownUsers[name].hasOwnProperty(ip)) {\n      this.knownUsersCount--;\n      delete this.knownUsers[name][ip];\n      this.onRemoveUser(name, ip);\n    }\n    if (Object.keys(this.knownUsers[name]) == 0) {\n      delete this.knownUsers[name];\n    }\n  }\n};\n\nproto.clearUser = function () {\n  var users = [];\n  for (var name in this.knownUsers) {\n    for (var ip in this.knownUsers[name]) {\n      users.push(name, ip);\n    }\n  }\n  for (var i = 0; i < users.length; i += 2) {\n    this.removeUser(users[i], users[i + 1]);\n  }\n};\n\nproto.onInfo = function (message, level) {\n\n};\n\nproto.onAddUser = function (name, ip) {\n\n};\n\nproto.onRemoveUser = function (name, ip) {\n\n};\n\nproto.onMessage = function (message, name, ip) {\n\n};\n\nproto.enter = function (callback) {\n  if (!this.connected) {\n    this.connect(function () {\n      this.sendDiagram(JSON.stringify({\n        type: 'hello',\n        name: this.name\n      }), callback);\n    });\n  } else {\n    callback.call(this);\n  }\n};\n\nproto.exit = function (callback) {\n  if (!callback) {\n    callback = emptyFn;\n  }\n  if (this.connected) {\n    this.sendDiagram(JSON.stringify({\n      type: 'goodbye',\n      name: this.name\n    }), function () {\n      this.disconnect(callback);\n    });\n  } else {\n    callback.call(this);\n  }\n};\n\nproto.renameTo = function (newName, callback) {\n  newName = newName.replace(invalidCharRe, '');\n  if (this.name != newName) {\n    this.sendDiagram(JSON.stringify({\n      type: 'goodbye',\n      name: this.name\n    }), function () {\n      this.name = newName;\n      this.sendDiagram(JSON.stringify({\n        type: 'hello',\n        name: this.name\n      }), function () {\n        this.onInfo(\"Renamed to [\" + newName + \"]\", \"info\");\n        callback.call(this, newName);\n      });\n    });\n  } else if (callback) {\n    callback.call(this, newName);\n  }\n};\n\nproto.sendMessage = function (message, callback) {\n  var me = this;\n  this.sendDiagram(JSON.stringify({\n    type: 'message',\n    name: this.name,\n    message: message\n  }), callback, function() {\n    me.onError(\"Error sending message (probably too large). Reconnecting soon.\");\n    me.disconnect();\n    setTimeout(function() {\n      me.enter(callback);\n    }, 100);\n  });\n};"
  },
  {
    "path": "_archive/apps/samples/multicast/Collection.js",
    "content": "var Collection = (function () {\n  function Collection() {\n    this._array = [];\n    this._map = {};\n    this.length = 0;\n  }\n\n  Collection.prototype.get = function (key) {\n    if (this._map.hasOwnProperty(key)) {\n      return this._array[this._map[key]].value;\n    }\n    return undefined;\n  };\n\n  Collection.prototype.getByIndex = function (index) {\n    if (this.length <= index) {\n      return undefined;\n    }\n    return this._array[index].value;\n  };\n\n  Collection.prototype.put = function (key, object) {\n    if (typeof object === 'undefined') {\n      this.remove(key);\n    } else if (!this._map.hasOwnProperty(key)) {\n      this._map[key] = this._array.length;\n      this._array.push({\n        value: object,\n        key: key\n      });\n      this.length++;\n    } else {\n      this._array[this._map[key]].value = object;\n    }\n  };\n\n  Collection.prototype.remove = function (key) {\n    if (this._map.hasOwnProperty(key)) {\n      var index = this._map[key];\n      delete this._map[key];\n      for (var name in this._map) {\n        if (this._map.hasOwnProperty(name) && this._map[name] >= index) {\n          this._map[name]--;\n        }\n      }\n      this._array.splice(index, 1);\n      this.length--;\n    }\n  };\n\n  Collection.prototype.forEach = function (callback, thisObject) {\n    if (!thisObject) {\n      thisObject = this;\n    }\n    for (var i = 0, arr = this._array, ln = arr.length; i < ln; i++) {\n      if (typeof arr[i].value !== 'undefined') {\n        callback.call(thisObject, arr[i].value, i, arr[i].key, this);\n      }\n    }\n  };\n\n  function defaultCompare(a, b) {\n    if (a == b) {\n      return 0;\n    } else if (a < b) {\n      return -1;\n    }\n    return 1;\n  }\n\n  Collection.prototype.sortByKeys = function (cmp) {\n    if (!cmp) {\n      cmp = defaultCompare;\n    }\n    this._array.sort(function (a, b) {\n      return cmp(a.key, b.key);\n    });\n    for (var i = 0, arr = this._array, ln = arr.length; i < ln; i++) {\n      this._map[arr[i].key] = i;\n    }\n  };\n\n  Collection.prototype.keys = function () {\n    var result = [];\n    this.forEach(function (value, key) {\n      result.push(key);\n    });\n    return result;\n  };\n\n  return Collection;\n})();"
  },
  {
    "path": "_archive/apps/samples/multicast/MulticastSocket.js",
    "content": "/**\n *\n * @param {Object} config\n * @param {String} config.address\n * @param {Number} config.port\n * @constructor\n */\nfunction MulticastSocket(config) {\n  this.config = config;\n}\n\nMulticastSocket.prototype.onError = function (message) {};\nMulticastSocket.prototype.onConnected = function () {};\nMulticastSocket.prototype.onDiagram = function (arrayBuffer, remote_address, remote_port) {};\nMulticastSocket.prototype.onDisconnected = function () {};\n\nMulticastSocket.prototype.connect = function (callback) {\n  var me = this;\n  chrome.sockets.udp.create({bufferSize: 1024 * 1024}, function (createInfo) {\n    var socketId = createInfo.socketId;\n    var ttl = 12;\n    chrome.sockets.udp.setMulticastTimeToLive(socketId, ttl, function (result) {\n      if (result != 0) {\n        me.handleError(\"Set TTL Error: \", \"Unknown error\");\n      }\n      chrome.sockets.udp.bind(socketId, \"0.0.0.0\", me.config.port, function (result) {\n        if (result != 0) {\n          chrome.sockets.udp.close(socketId, function () {\n            me.handleError(\"Error on bind(): \", result);\n          });\n        } else {\n          chrome.sockets.udp.joinGroup(socketId, me.config.address, function (result) {\n            if (result != 0) {\n              chrome.sockets.udp.close(socketId, function () {\n                me.handleError(\"Error on joinGroup(): \", result);\n              });\n            } else {\n              me.socketId = socketId;\n              chrome.sockets.udp.onReceive.addListener(me.onReceive.bind(me));\n              chrome.sockets.udp.onReceiveError.addListener(me.onReceiveError.bind(me));\n              me.onConnected();\n              if (callback) {\n                callback.call(me);\n              }\n            }\n          });\n        }\n      });\n    });\n  });\n};\n\nMulticastSocket.prototype.disconnect = function (callback) {\n  var me = this;\n  chrome.sockets.udp.onReceive.removeListener(me.onReceive.bind(me));\n  chrome.sockets.udp.onReceiveError.removeListener(me.onReceiveError.bind(me));\n  chrome.sockets.udp.close(me.socketId, function () {\n    me.socketId = undefined;\n    me.onDisconnected();\n    if (callback) {\n      callback.call(me);\n    }\n  });\n};\n\nMulticastSocket.prototype.handleError = function (additionalMessage, alternativeMessage) {\n  var err = chrome.runtime.lastError;\n  err = err && err.message || alternativeMessage;\n  this.onError(additionalMessage + err);\n};\n\nMulticastSocket.prototype.onReceive = function (info) {\n  this.onDiagram(info.data, info.remoteAddress, info.remotePort);\n};\n\nMulticastSocket.prototype.onReceiveError = function (socketId, resultCode) {\n  this.handleError(\"\", resultCode);\n  this.disconnect();\n};\n\nMulticastSocket.prototype.arrayBufferToString = function (arrayBuffer) {\n  // UTF-16LE\n  return String.fromCharCode.apply(String, new Uint16Array(arrayBuffer));\n};\n\nMulticastSocket.prototype.stringToArrayBuffer = function (string) {\n  // UTF-16LE\n  var buf = new ArrayBuffer(string.length * 2);\n  var bufView = new Uint16Array(buf);\n  for (var i = 0, strLen = string.length; i < strLen; i++) {\n    bufView[i] = string.charCodeAt(i);\n  }\n  return buf;\n};\n\nMulticastSocket.prototype.sendDiagram = function (message, callback, errCallback) {\n  if (typeof message === 'string') {\n    message = this.stringToArrayBuffer(message);\n  }\n  if (!message || message.byteLength == 0 || !this.socketId) {\n    if (callback) {\n      callback.call(this);\n    }\n    return;\n  }\n  var me = this;\n  chrome.sockets.udp.send(me.socketId, message, me.config.address, me.config.port,\n      function (sendInfo) {\n    if (sendInfo.resultCode >= 0 && sendInfo.bytesSent >= 0) {\n      if (callback) {\n        callback.call(me);\n      }\n    } else {\n      if (errCallback) {\n        errCallback();\n      } else {\n        me.handleError(\"\");\n        if (result.bytesSent == -15) {\n          me.disconnect();\n        }\n      }\n    }\n  });\n};\n"
  },
  {
    "path": "_archive/apps/samples/multicast/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/bnheobjndkaipbloffigkiddhcbblihl\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Multicast Chatting\n\n![snapshot](snapshot.png \"Snapshot of the app\")\n\nThis sample shows how to send and receive [multicast\nsocket](http://en.wikipedia.org/wiki/Multicast) diagrams in local network from\nChrome apps. It joins the multicast socket group 237.132.123.123 and listens on\nport 3038.\n\nTo support multicast socket messaging in your local network requires the\nsupport of your router. The connectivity of this app varies depending on the\nnetwork configuration.\n\n__Warning: This is a simple chatting app demonstrating the usage of multicast\nsocket Chrome app API. It is not designed for reliable communication. Privacy\nand reachability of the message is NOT guaranteed. It is also possible that a\nuser is able to send to another user while not being able to receive from the\nlatter.__\n\n## APIs\n* [Messaging](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Runtime](https://developer.chrome.com/apps/app.runtime.html)\n* [Storage](https://developer.chrome.com/apps/storage.html)\n* [Sockets](https://developer.chrome.com/apps/sockets_udp)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/multicast/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/multicast/background.js",
    "content": "var kIP = \"237.132.123.123\";\nvar kPort = 3038;\nvar chatClient;\nvar clientId;\n\nfunction random_string(length) {\n  var str = '';\n  for (var i = 0; i < length; i++) {\n    str += (Math.random() * 16 >> 0).toString(16);\n  }\n  return str;\n}\n\nfunction rtm(message, callback) {\n  if (callback) {\n    chrome.runtime.sendMessage(chrome.runtime.id, message, callback);\n  } else {\n    chrome.runtime.sendMessage(chrome.runtime.id, message);\n  }\n}\n\nfunction onInitWindow(appWindow) {\n  appWindow.show();\n  var document = appWindow.contentWindow.document;\n  document.addEventListener('DOMContentLoaded', function () {\n    rtm({\n      \"type\": 'init',\n      clientId: clientId\n    }, function () {\n      chatClient.enter();\n    });\n  });\n  appWindow.onClosed.addListener(function(){\n    chatClient.exit();\n  });\n}\n\nfunction createMainWindow() {\n  chrome.app.window.create('index.html', {\n    id: 'main-window',\n    frame: 'none',\n    innerBounds: {\n      left: 100,\n      top: 100,\n      width: 650,\n      height: 520,\n      minWidth: 400,\n      minHeight: 275\n    },\n    hidden: true\n  }, onInitWindow);\n}\n\nchrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {\n  if (message) {\n    switch (message.type) {\n      case 'set-client-id':\n        chatClient.renameTo(message.value, function (name) {\n          chrome.storage.local.set({\n            'client_id': message.value\n          }, function(){\n            sendResponse(name);\n            clientId = name;\n            rtm({\n              type: 'refresh-user-list'\n            });\n          });\n        });\n        return true;\n        break;\n      case 'query-users':\n        sendResponse(chatClient.knownUsers);\n        break;\n      case 'send-message':\n        chatClient.sendMessage(message.message, function () {\n          sendResponse(true);\n        });\n        return true;\n        break;\n    }\n  }\n  return false;\n});\n\nfunction initClient(id) {\n  var cc = new ChatClient({\n    name: id,\n    address: kIP,\n    port: kPort\n  });\n  cc.onInfo = function (message, level) {\n    level = level || 'info';\n    rtm({\n      type: 'info',\n      level: level,\n      message: message\n    });\n  };\n  cc.onAddUser = function (name, ip) {\n    rtm({\n      type: 'add-user',\n      name: name,\n      ip: ip\n    })\n  };\n  cc.onRemoveUser = function (name, ip) {\n    rtm({\n      type: 'remove-user',\n      name: name,\n      ip: ip\n    })\n  };\n  cc.onMessage = function (message, name, ip) {\n    rtm({\n      type: 'message',\n      name: name,\n      message: message\n    })\n  };\n  clientId = id;\n  chatClient = cc;\n}\n\nchrome.storage.local.get('client_id', function (result) {\n  if (result && ('client_id' in result)) {\n    initClient(result.client_id);\n  } else {\n    var id = 'client' + random_string(16);\n    chrome.storage.local.set({\n      'client_id': id\n    }, function () {\n      initClient(id);\n    });\n  }\n});\n\nchrome.app.runtime.onLaunched.addListener(function () {\n  function waitForChatClient() {\n    if (clientId) {\n      createMainWindow();\n    } else {\n      setTimeout(waitForChatClient);\n    }\n  }\n  waitForChatClient();\n});\n"
  },
  {
    "path": "_archive/apps/samples/multicast/index.css",
    "content": "div, ul, li, input, button {\n    margin: 0;\n    padding: 0;\n    box-sizing: border-box;\n    -webkit-user-select: none;\n    -webkit-user-drag: none;\n    user-select: none;\n    user-drag: none;\n    min-width: 0;\n    min-height: 0;\n}\n\nbody {\n    display: -webkit-flex;\n    display: flex;\n    -webkit-flex-direction: column;\n    flex-direction: column;\n    box-sizing: border-box;\n    position: fixed;\n    width: 100%;\n    height: 100%;\n    margin: 0;\n    font-family: sans-serif;\n}\n\n#title-bar {\n    position: relative;\n    padding: 5px;\n    -webkit-app-region: drag;\n    display: -webkit-flex;\n    display: flex;\n    -webkit-align-items: center;\n    align-items: center;\n    background: #41413e;\n\n}\n\n#title-bar img {\n    position: absolute;\n    width: 20px;\n}\n\n#title {\n    display: -webkit-flex;\n    display: flex;\n    margin-left: 25px;\n    margin-top: 1px;\n    color: white;\n    text-shadow: #000 1px 1px 0;\n    height: 20px;\n}\n\ninput {\n    border: 0;\n    margin: 0;\n}\n\n.list-cnt {\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    font-family: monospace;\n    line-height: 1.5;\n    bottom: 0;\n    min-height: 150px;\n    overflow: auto;\n}\n\n#container {\n    display: -webkit-flex;\n    display: flex;\n    position: relative;\n    -webkit-flex: 1;\n    flex: 1;\n    width: 100%;\n    border: 4px solid #41413e;\n    border-top: 0;\n    overflow: hidden;\n}\n\n#main-block {\n    display: -webkit-flex;\n    display: flex;\n    -webkit-flex-direction: column;\n    flex-direction: column;\n    -webkit-flex: 1;\n    flex: 1;\n    box-shadow: #CCC 0 0 8px;\n    border-right: 1px solid #CCC;\n    min-width: 0;\n    min-height: 0;\n}\n\n#message-container {\n    -webkit-flex: 1;\n    -webkit-flex-grow: 1;\n    -webkit-flex-shrink: 1;\n    flex: 1;\n    flex-grow: 1;\n    flex-shrink: 1;\n    position: relative;\n    min-width: 0;\n    min-height: 0;\n    border-bottom: 1px solid #CCCCCC;\n    overflow: auto;\n    padding: 15px;\n    background: #feffd3;\n}\n\n#messages {\n    font-family: monospace;\n    font-size: 13px;\n    padding: 0 15px;\n    color: #444;\n    list-style: none;\n}\n\n#messages * {\n    -webkit-user-select: text;\n    -webkit-user-drag: text;\n}\n\n.help-text {\n    border: 1px solid #CCC;\n    border-radius: 8px;\n    margin-top: 7px;\n    padding: 12px;\n    padding-left: 25px;\n    background: rgba(255,255,255,0.3);\n    overflow: hidden; /* This helps constraint the selection highlights. */\n}\n\n#messages .help {\n    margin-left: -14px;\n}\n\n#messages .help > ul {\n}\n\n#messages .help > ul > li {\n    margin-left: 0;\n}\n\n#messages .hide-help > ul {\n    display: none;\n}\n\n#messages > li {\n    text-indent: 0;\n    margin-bottom: 6px;\n    -webkit-user-drag: none;\n}\n\n#messages li.info {\n    color: #494;\n    margin-left: -14px;\n}\n\n#messages li.warning {\n    color: #B89D11;\n    font-weight: bold;\n}\n\n#messages li.error {\n    color: #b82a05;\n    font-weight: bold;\n}\n\n#messages li pre {\n    margin: 0;\n    word-wrap: break-word;\n}\n\n#messages h3 {\n    margin-left: -14px;\n}\n\n#messages li h4 {\n    margin: 7px;\n    margin-top: 15px;\n    margin-left: -14px;\n}\n\n#input-panel {\n    position: relative;\n    height: 150px;\n    background: #EEE;\n    border-top: 1px solid white;\n    padding: 7px;\n    display: -webkit-flex;\n    -webkit-flex-direction: column;\n    -webkit-flex-align: stretch;\n}\n\n#input-panel > .text-input {\n    -webkit-flex: 1;\n    margin: 3px;\n    position: relative;\n    display: -webkit-flex;\n    padding: -3px;\n    border: 1px solid grey;\n    border-radius: 7px;\n    box-shadow: inset #999 0 0 3px;\n    background: white;\n}\n\n#input-panel > .text-input textarea {\n    background: transparent;\n    position: absolute;\n    top: -3px;\n    bottom: -3px;\n    left: -3px;\n    right: -3px;\n    padding: 10px;\n    box-sizing: border-box;\n    border: 0;\n    resize: none;\n    outline: none;\n    width: 100%;\n}\n\n#splitter {\n    position: absolute;\n    top: -2px;\n    left: 0;\n    right: 0;\n    height: 5px;\n    cursor: ns-resize;\n}\n\n#client-id-line {\n    margin-bottom: 5px;\n}\n\n#client-id {\n    margin: 3px;\n    font-family: monospace;\n    background: transparent;\n    -webkit-user-select: element;\n    display: inline-block;\n    font-weight: bold;\n}\n\n#client-id[contenteditable] {\n    -webkit-user-select: text;\n    background: rgba(0, 0, 0, 0.1);\n}\n\n#input-box {\n    font-family: monospace;\n    font-size: 13px;\n}\n\n#input-box[readonly] {\n    color: grey;\n}\n\n#send-text {\n    box-sizing: border-box;\n    height: 100%;\n}\n\n#user-panel {\n    width: 150px;\n    overflow: auto;\n}\n\n#user-list {\n    padding: 10px 0;\n}\n\n#user-list > li {\n    padding: 3px 15px;\n    -webkit-user-drag: element;\n    user-drag: element;\n    user-select: element;\n    white-space: nowrap;\n}\n\n#close {\n    width: 18px;\n    height: 18px;\n    padding: 0;\n    line-height: 0;\n    background: #6e6e6b;\n    border: 1px solid grey;\n    -webkit-user-drag: none;\n    -webkit-user-select: none;\n    -webkit-app-region: no-drag;\n    text-align: center;\n    color: white;\n    border-radius: 3px;\n}\n\n#close:hover {\n    background: #a5a5a2;\n}\n"
  },
  {
    "path": "_archive/apps/samples/multicast/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>Multicast Chat App</title>\n    <link href=\"index.css\" rel=\"stylesheet\"/>\n    <script src=\"Collection.js\"></script>\n    <script src=\"index.js\"></script>\n</head>\n<body>\n<div id=\"title-bar\">\n    <img src=\"128.png\"/>\n\n    <div id=\"title\" style=\"-webkit-flex: 1\">Multicast Chat Demo App</div>\n    <button id=\"close\" href=\"#\">&times;</button>\n</div>\n<div id=\"container\">\n    <div id=\"main-block\">\n        <div id=\"message-container\">\n            <ul id=\"messages\">\n                <h3>Welcome to Multicast Chat Demo App!</h3>\n                <li>This app allows you to send messages to you local network\n                    without help of any server.\n                </li>\n                <li id=\"help\" class=\"hide-help help\">\n                    <a href=\"#help\" id=\"toggle-help\">[Show help]</a>\n                    <ul class=\"help-text\">\n                        <li>Whoever installed this app in your local network can\n                            see the messages you send. They are listed on the\n                            right panel.\n                        </li>\n                        <li>Press <span style=\"font-weight: bold\">Enter</span>\n                            to send message; Press <span\n                                    style=\"font-weight: bold\">Shift+Enter</span>\n                            for new lines.\n                        </li>\n                        <li>Double click on your name to edit it.</li>\n                        <li class=\"info warning\">[Warning] Messages are\n                            transferred in public with plain text. Due to the\n                            nature of UDP protocol, your message could be lost\n                            randomly.\n                        </li>\n                    </ul>\n                </li>\n                <li>\n            </ul>\n        </div>\n        <div id=\"input-panel\">\n            <div id=\"splitter\">\n            </div>\n            <div id=\"client-id-line\">\n                <div id=\"client-id\" title=\"Double click to change.\"></div>\n                :\n            </div>\n            <div class=\"text-input\">\n                <textarea id=\"input-box\" tabindex=\"0\"\n                          title=\"Press Enter to send.\"></textarea>\n            </div>\n        </div>\n    </div>\n    <div id=\"user-panel\" title=\"People in you local network.\">\n        <div class=\"list-cnt\">\n            <ul id=\"user-list\">\n                <li>(No user found)</li>\n            </ul>\n        </div>\n    </div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "_archive/apps/samples/multicast/index.js",
    "content": "function rtm(message, callback) {\n  if (callback) {\n    chrome.runtime.sendMessage(chrome.runtime.id, message, callback);\n  } else {\n    chrome.runtime.sendMessage(chrome.runtime.id, message);\n  }\n}\n\nfunction setClientId(name, callback) {\n  chrome.runtime.sendMessage(chrome.runtime.id, {\n    type: \"set-client-id\",\n    value: name\n  }, callback);\n}\n\nfunction startEditClientId() {\n  var clientIdBox = document.getElementById('client-id');\n\n  setTimeout(function () {\n    clientIdBox.setAttribute('contenteditable', 'true');\n    clientIdBox.focus();\n    clientIdBox.onblur = function () {\n      clientIdBox.onblur = null;\n      clientIdBox.removeAttribute('contenteditable');\n      setClientId(clientIdBox.textContent, function (name) {\n        clientIdBox.textContent = name;\n      });\n    };\n  }, 1);\n}\n\nvar knowUsers = new Collection();\n\nfunction refreshUserList() {\n  rtm({\n    type: 'query-users'\n  }, function (result) {\n    var names = Object.keys(result);\n    names.sort();\n    var userList = document.getElementById('user-list');\n    if (names.length == 0) {\n      userList.innerHTML = '<li>(No user found)</li>';\n    } else {\n      userList.innerHTML = '';\n      names.forEach(function (name) {\n        for (var ip in result[name]) {\n          var userItem = document.createElement('li');\n          userItem.textContent = '[' + name + ']';\n          userItem.title = \"From: \" + ip;\n          knowUsers.put(name + ' ' + ip, userItem);\n        }\n      });\n      knowUsers.sortByKeys();\n      knowUsers.forEach(function (value, key) {\n        userList.appendChild(value);\n      });\n    }\n  });\n}\n\nfunction removeUser(name, ip) {\n  var key = name + ' ' + ip;\n  var node = knowUsers.get(key);\n  if (node) {\n    node.parentNode.removeChild(node);\n    knowUsers.remove(key);\n  }\n  if (knowUsers.length == 0) {\n    document.getElementById('user-list').innerHTML = '<li>(No user found)</li>';\n  }\n}\n\nfunction addUser(name, ip) {\n  var key = name + ' ' + ip;\n  if (knowUsers.get(key)) {\n    return;\n  }\n  var userList = document.getElementById('user-list');\n  var userItem = document.createElement('li');\n  userItem.textContent = '[' + name + ']';\n  userItem.title = \"From: \" + ip;\n  var keys = knowUsers.keys();\n  if (keys.length == 0) {\n    userList.innerHTML = '';\n  }\n  for (var i = 0; i < keys.length; i++) {\n    if (keys[i] > key) {\n      break;\n    }\n  }\n  if (i < keys.length) {\n    userList.insertBefore(userItem, knowUsers.getByIndex(i));\n  } else {\n    userList.appendChild(userItem);\n  }\n  knowUsers.put(key, userItem);\n}\n\nfunction sendMessage() {\n  var messageInputBox = document.getElementById('input-box');\n  var message = messageInputBox.value;\n  messageInputBox.setAttribute('readonly', '');\n  rtm({\n    type: 'send-message',\n    message: message\n  }, function () {\n    messageInputBox.value = '';\n    messageInputBox.removeAttribute('readonly');\n  });\n\n}\n\nfunction init(clientId) {\n  var clientIdBox = document.getElementById('client-id');\n  clientIdBox.textContent = clientId;\n  clientIdBox.ondblclick = startEditClientId;\n  var messageInputBox = document.getElementById('input-box');\n  messageInputBox.addEventListener('keydown', function (e) {\n    if (e.keyCode == 13 && !e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {\n      sendMessage();\n    }\n  });\n\n  var toggleHelp = document.getElementById('toggle-help');\n  toggleHelp.onclick = function () {\n    var helpText = document.getElementById('help');\n    helpText.classList.toggle('hide-help');\n  };\n\n  var closeBox = document.getElementById('close');\n  closeBox.onclick = function () {\n    chrome.app.window.current().close();\n  };\n\n  var splitter = document.getElementById('splitter');\n  chrome.storage.local.get('input-panel-size', function (obj) {\n    if (obj['input-panel-size']) {\n      var inputPanel = document.getElementById('input-panel');\n      inputPanel.style.height = obj['input-panel-size'] + 1 + 'px';\n    }\n  });\n  splitter.onmousedown = function (e) {\n    if (e.button != 0) {\n      return;\n    }\n    e.stopPropagation();\n    e.preventDefault();\n    var inputPanel = document.getElementById('input-panel');\n    var totalHeight = document.body.scrollHeight;\n    var panelHeight = inputPanel.scrollHeight;\n    var startY = e.pageY;\n    var MouseMove;\n    document.addEventListener('mousemove', MouseMove = function (e) {\n      e.stopPropagation();\n      e.preventDefault();\n      var dy = e.pageY - startY;\n      if (panelHeight - dy < 120) {\n        dy = panelHeight - 120;\n      }\n      if (totalHeight - panelHeight + dy < 120) {\n        dy = 120 - totalHeight + panelHeight;\n      }\n      inputPanel.style.height = panelHeight - dy + 1 + 'px';\n      chrome.storage.local.set({'input-panel-size': panelHeight - dy});\n    });\n    document.addEventListener('mouseup', function MouseUp(e) {\n      MouseMove(e);\n      document.removeEventListener('mousemove', MouseMove);\n      document.removeEventListener('mouseup', MouseUp);\n    });\n  };\n  refreshUserList();\n}\n\nfunction onMessageArrived(message, name) {\n  var newMessageLi = document.createElement('li');\n  var nameBlock = document.createElement('h4');\n  nameBlock.textContent = name + \":\";\n  newMessageLi.appendChild(nameBlock);\n  var messageBlock = document.createElement('pre');\n  messageBlock.textContent = message;\n  newMessageLi.appendChild(messageBlock);\n  document.getElementById('messages').appendChild(newMessageLi);\n}\n\nchrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {\n  var newMessageLi;\n  var messages = document.getElementById('messages');\n  if (message) {\n    switch (message.type) {\n      case 'init':\n        init(message.clientId);\n        sendResponse(\"Done\");\n        return true;\n      case 'set-client-id':\n        document.getElementById('client-id').textContent = message.value;\n        break;\n      case 'message':\n        onMessageArrived(message.message, message.name);\n        break;\n      case 'remove-user':\n        removeUser(message.name, message.ip);\n        break;\n      case 'add-user':\n        addUser(message.name, message.ip);\n        break;\n      case 'refresh-user-list':\n        refreshUserList();\n        break;\n      case 'info':\n        newMessageLi = document.createElement('li');\n        newMessageLi.textContent = message.message;\n        newMessageLi.setAttribute(\"class\", message.level);\n        messages.appendChild(newMessageLi);\n        break;\n    }\n  }\n});"
  },
  {
    "path": "_archive/apps/samples/multicast/manifest.json",
    "content": "{\n  \"name\": \"Multicast Chat Sample\",\n  \"version\": \"0.3\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"33\",\n  \"description\": \"Sending/Receiving multicast diagrams.\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\n        \"MulticastSocket.js\",\n        \"ChatClient.js\",\n        \"background.js\"]\n    }\n  },\n\n  \"icons\": {\n    \"128\": \"128.png\"\n  },\n\n  \"sockets\": {\n    \"udp\": {\n      \"bind\": \"*\",\n      \"send\": \"*\",\n      \"multicastMembership\": \"\"\n    }\n  },\n  \"permissions\": [ \"storage\" ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/one-time-payment/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ebcgmmcbgnpoclkoibogeiokfdmjbbob\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n# One time payments & free trials in Chrome Apps\n\nIf you choose to charge users for your Chrome App, there are several options\navailable to you. The Chrome Web Store has a built-in\n[one-time payment system](https://developers.google.com/chrome/web-store/docs/payments-otp)\ncalled Chrome Web Store Payments.  With one-time payments, you can also\noffer a free trial experience for your users.\n\n### Note:\nThe version that is published in the Chrome Web Store is not available for sale! This is to prevent people from accidentally purchasing a sample.  When installed, the user will be issued with a FREE_TRIAL license.  If you want to see the end to end flow, complete with the ability to purchase the app, you'll need to publish it in the store yourself and enable one time payments.  See the [documentation](https://developers.google.com/chrome/web-store/docs/payments-otp#using-otps) for full details.\n\nTo test with the version that is in the Chrome Web Store, you'll need\nto add the the key below to your manifest:\n\n```\"key\": \"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtqhlRmNTTzJXvfYcLEW9sTzOJzDxJr5M80XgolHc1EYdvjdg1/e4+fPadq3vAueArzwvEtFji2Ax4Aqo99kA1qYyw9ji8RdlUArvJCTIq/7xPMoMPWHCb3wPfZ7IYV4U6h841dUjrOng7yxN9RIYSLHPpqQG0tBSh3sx7pxjYWx6DxhxOlP9BAQ9W8McSaoI8Wy/4hCJb0k6hkGrD1q7mQIWODg7aF03+LvWuF+GNZJfVFU37w6IFo2bcmfJugW/Lu4oG4eYuYziWFXNfgnwaHyrA5MLPrQJ3jZKiETx1AzCClAyYKafkwKEXXhb0mA1H/fJf1ePfMWjT4Yj0E8SWwIDAQAB\"```\n\n## APIs\n* [Identity](http://developer.chrome.com/apps/identity.html)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/one-time-payment/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/one-time-payment/css/app.css",
    "content": "body { \n  padding-top: 50px; \n}\n\nfooter {\n  position: absolute;\n  bottom: 0;\n  margin: 0;\n  width: 100%;\n  background-color: #f5f5f5;\n  border-top: inset;\n}\n\nfooter p {\n  padding: 2px;\n  margin: 0;\n}\n\npre {\n  vertical-align: top;\n  overflow-y: auto;\n  background-color: #F5F5F5;\n}\n\ndiv.alert span:first-child{\n  display: inline-block;\n  width: 50%;\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/one-time-payment/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v3.0.3\n *\n * Copyright 2013 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n\n/*! normalize.css v2.1.3 | MIT License | git.io/normalize */\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n}\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n[hidden],\ntemplate {\n  display: none;\n}\nhtml {\n  font-family: sans-serif;\n  -ms-text-size-adjust: 100%;\n  -webkit-text-size-adjust: 100%;\n}\nbody {\n  margin: 0;\n}\na {\n  background: transparent;\n}\na:focus {\n  outline: thin dotted;\n}\na:active,\na:hover {\n  outline: 0;\n}\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\nabbr[title] {\n  border-bottom: 1px dotted;\n}\nb,\nstrong {\n  font-weight: bold;\n}\ndfn {\n  font-style: italic;\n}\nhr {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  height: 0;\n}\nmark {\n  background: #ff0;\n  color: #000;\n}\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, serif;\n  font-size: 1em;\n}\npre {\n  white-space: pre-wrap;\n}\nq {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\nsmall {\n  font-size: 80%;\n}\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\nsup {\n  top: -0.5em;\n}\nsub {\n  bottom: -0.25em;\n}\nimg {\n  border: 0;\n}\nsvg:not(:root) {\n  overflow: hidden;\n}\nfigure {\n  margin: 0;\n}\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n  border: 0;\n  padding: 0;\n}\nbutton,\ninput,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: 100%;\n  margin: 0;\n}\nbutton,\ninput {\n  line-height: normal;\n}\nbutton,\nselect {\n  text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button;\n  cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  box-sizing: border-box;\n  padding: 0;\n}\ninput[type=\"search\"] {\n  -webkit-appearance: textfield;\n  -moz-box-sizing: content-box;\n  -webkit-box-sizing: content-box;\n  box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n*,\n*:before,\n*:after {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\nhtml {\n  font-size: 62.5%;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #333333;\n  background-color: #ffffff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\na {\n  color: #428bca;\n  text-decoration: none;\n}\na:hover,\na:focus {\n  color: #2a6496;\n  text-decoration: underline;\n}\na:focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\nimg {\n  vertical-align: middle;\n}\n.img-responsive {\n  display: block;\n  max-width: 100%;\n  height: auto;\n}\n.img-rounded {\n  border-radius: 6px;\n}\n.img-thumbnail {\n  padding: 4px;\n  line-height: 1.428571429;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n  -webkit-transition: all 0.2s ease-in-out;\n  transition: all 0.2s ease-in-out;\n  display: inline-block;\n  max-width: 100%;\n  height: auto;\n}\n.img-circle {\n  border-radius: 50%;\n}\nhr {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n}\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  margin: -1px;\n  padding: 0;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  border: 0;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-weight: 500;\n  line-height: 1.1;\n  color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\nh1,\nh2,\nh3 {\n  margin-top: 20px;\n  margin-bottom: 10px;\n}\nh1 small,\nh2 small,\nh3 small,\nh1 .small,\nh2 .small,\nh3 .small {\n  font-size: 65%;\n}\nh4,\nh5,\nh6 {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\nh4 small,\nh5 small,\nh6 small,\nh4 .small,\nh5 .small,\nh6 .small {\n  font-size: 75%;\n}\nh1,\n.h1 {\n  font-size: 36px;\n}\nh2,\n.h2 {\n  font-size: 30px;\n}\nh3,\n.h3 {\n  font-size: 24px;\n}\nh4,\n.h4 {\n  font-size: 18px;\n}\nh5,\n.h5 {\n  font-size: 14px;\n}\nh6,\n.h6 {\n  font-size: 12px;\n}\np {\n  margin: 0 0 10px;\n}\n.lead {\n  margin-bottom: 20px;\n  font-size: 16px;\n  font-weight: 200;\n  line-height: 1.4;\n}\n@media (min-width: 768px) {\n  .lead {\n    font-size: 21px;\n  }\n}\nsmall,\n.small {\n  font-size: 85%;\n}\ncite {\n  font-style: normal;\n}\n.text-muted {\n  color: #999999;\n}\n.text-primary {\n  color: #428bca;\n}\n.text-primary:hover {\n  color: #3071a9;\n}\n.text-warning {\n  color: #8a6d3b;\n}\n.text-warning:hover {\n  color: #66512c;\n}\n.text-danger {\n  color: #a94442;\n}\n.text-danger:hover {\n  color: #843534;\n}\n.text-success {\n  color: #3c763d;\n}\n.text-success:hover {\n  color: #2b542c;\n}\n.text-info {\n  color: #31708f;\n}\n.text-info:hover {\n  color: #245269;\n}\n.text-left {\n  text-align: left;\n}\n.text-right {\n  text-align: right;\n}\n.text-center {\n  text-align: center;\n}\n.page-header {\n  padding-bottom: 9px;\n  margin: 40px 0 20px;\n  border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n  margin-top: 0;\n  margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n  margin-bottom: 0;\n}\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n.list-inline {\n  padding-left: 0;\n  list-style: none;\n}\n.list-inline > li {\n  display: inline-block;\n  padding-left: 5px;\n  padding-right: 5px;\n}\n.list-inline > li:first-child {\n  padding-left: 0;\n}\ndl {\n  margin-top: 0;\n  margin-bottom: 20px;\n}\ndt,\ndd {\n  line-height: 1.428571429;\n}\ndt {\n  font-weight: bold;\n}\ndd {\n  margin-left: 0;\n}\n@media (min-width: 1px) {\n  .dl-horizontal dt {\n    float: left;\n    width: 160px;\n    clear: left;\n    text-align: right;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n  .dl-horizontal dd {\n    margin-left: 180px;\n  }\n  .dl-horizontal dd:before,\n  .dl-horizontal dd:after {\n    content: \" \";\n    display: table;\n  }\n  .dl-horizontal dd:after {\n    clear: both;\n  }\n  .dl-horizontal dd:before,\n  .dl-horizontal dd:after {\n    content: \" \";\n    display: table;\n  }\n  .dl-horizontal dd:after {\n    clear: both;\n  }\n}\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\nblockquote {\n  padding: 10px 20px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\nblockquote p {\n  font-size: 17.5px;\n  font-weight: 300;\n  line-height: 1.25;\n}\nblockquote p:last-child {\n  margin-bottom: 0;\n}\nblockquote small,\nblockquote .small {\n  display: block;\n  line-height: 1.428571429;\n  color: #999999;\n}\nblockquote small:before,\nblockquote .small:before {\n  content: '\\2014 \\00A0';\n}\nblockquote.pull-right {\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\nblockquote.pull-right p,\nblockquote.pull-right small,\nblockquote.pull-right .small {\n  text-align: right;\n}\nblockquote.pull-right small:before,\nblockquote.pull-right .small:before {\n  content: '';\n}\nblockquote.pull-right small:after,\nblockquote.pull-right .small:after {\n  content: '\\00A0 \\2014';\n}\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\naddress {\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 1.428571429;\n}\ncode,\nkbd,\npre,\nsamp {\n  font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: #c7254e;\n  background-color: #f9f2f4;\n  white-space: nowrap;\n  border-radius: 4px;\n}\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 1.428571429;\n  word-break: break-all;\n  word-wrap: break-word;\n  color: #333333;\n  background-color: #f5f5f5;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n}\npre code {\n  padding: 0;\n  font-size: inherit;\n  color: inherit;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border-radius: 0;\n}\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: inherit;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n\n  line-height: normal;\n}\ninput[type=\"file\"] {\n  display: block;\n}\nselect[multiple],\nselect[size] {\n  height: auto;\n}\nselect optgroup {\n  font-size: inherit;\n  font-style: inherit;\n  font-family: inherit;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\ninput[type=\"number\"]::-webkit-outer-spin-button,\ninput[type=\"number\"]::-webkit-inner-spin-button {\n  height: auto;\n}\noutput {\n  display: block;\n  padding-top: 7px;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #555555;\n  vertical-align: middle;\n}\n.form-control {\n  display: block;\n  width: 100%;\n  height: 34px;\n  padding: 6px 12px;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #555555;\n  vertical-align: middle;\n  background-color: #ffffff;\n  background-image: none;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n  transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n  border-color: #66afe9;\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n  box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control:-moz-placeholder {\n  color: #999999;\n}\n.form-control::-moz-placeholder {\n  color: #999999;\n  opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n  color: #999999;\n}\n.form-control::-webkit-input-placeholder {\n  color: #999999;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\ntextarea.form-control {\n  height: auto;\n}\n.form-group {\n  margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n  display: block;\n  min-height: 20px;\n  margin-top: 10px;\n  margin-bottom: 10px;\n  padding-left: 20px;\n  vertical-align: middle;\n}\n.radio label,\n.checkbox label {\n  display: inline;\n  margin-bottom: 0;\n  font-weight: normal;\n  cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  vertical-align: middle;\n  font-weight: normal;\n  cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\n.radio[disabled],\n.radio-inline[disabled],\n.checkbox[disabled],\n.checkbox-inline[disabled],\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"],\nfieldset[disabled] .radio,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox,\nfieldset[disabled] .checkbox-inline {\n  cursor: not-allowed;\n}\n.input-sm {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\nselect.input-sm {\n  height: 30px;\n  line-height: 30px;\n}\ntextarea.input-sm {\n  height: auto;\n}\n.input-lg {\n  height: 46px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\nselect.input-lg {\n  height: 46px;\n  line-height: 46px;\n}\ntextarea.input-lg {\n  height: auto;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline {\n  color: #8a6d3b;\n}\n.has-warning .form-control {\n  border-color: #8a6d3b;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n  border-color: #66512c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n  color: #8a6d3b;\n  border-color: #8a6d3b;\n  background-color: #fcf8e3;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline {\n  color: #a94442;\n}\n.has-error .form-control {\n  border-color: #a94442;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n  border-color: #843534;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n  color: #a94442;\n  border-color: #a94442;\n  background-color: #f2dede;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline {\n  color: #3c763d;\n}\n.has-success .form-control {\n  border-color: #3c763d;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n  border-color: #2b542c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n  color: #3c763d;\n  border-color: #3c763d;\n  background-color: #dff0d8;\n}\n.form-control-static {\n  margin-bottom: 0;\n}\n.help-block {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #737373;\n}\n@media (min-width: 768px) {\n  .form-inline .form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .form-inline .form-control {\n    display: inline-block;\n  }\n  .form-inline select.form-control {\n    width: auto;\n  }\n  .form-inline .radio,\n  .form-inline .checkbox {\n    display: inline-block;\n    margin-top: 0;\n    margin-bottom: 0;\n    padding-left: 0;\n  }\n  .form-inline .radio input[type=\"radio\"],\n  .form-inline .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n.form-horizontal .control-label,\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n  margin-top: 0;\n  margin-bottom: 0;\n  padding-top: 7px;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n  min-height: 27px;\n}\n.form-horizontal .form-group {\n  margin-left: -15px;\n  margin-right: -15px;\n}\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after {\n  content: \" \";\n  display: table;\n}\n.form-horizontal .form-group:after {\n  clear: both;\n}\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after {\n  content: \" \";\n  display: table;\n}\n.form-horizontal .form-group:after {\n  clear: both;\n}\n.form-horizontal .form-control-static {\n  padding-top: 7px;\n}\n@media (min-width: 768px) {\n  .form-horizontal .control-label {\n    text-align: right;\n  }\n}\n.btn {\n  display: inline-block;\n  margin-bottom: 0;\n  font-weight: normal;\n  text-align: center;\n  vertical-align: middle;\n  cursor: pointer;\n  background-image: none;\n  border: 1px solid transparent;\n  white-space: nowrap;\n  padding: 6px 12px;\n  font-size: 14px;\n  line-height: 1.428571429;\n  border-radius: 4px;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  -o-user-select: none;\n  user-select: none;\n}\n.btn:focus {\n  outline: thin dotted;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus {\n  color: #333333;\n  text-decoration: none;\n}\n.btn:active,\n.btn.active {\n  outline: 0;\n  background-image: none;\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n  cursor: not-allowed;\n  pointer-events: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\n.btn-default {\n  color: #333333;\n  background-color: #ffffff;\n  border-color: #cccccc;\n}\n.btn-default:hover,\n.btn-default:focus,\n.btn-default:active,\n.btn-default.active,\n.open .dropdown-toggle.btn-default {\n  color: #333333;\n  background-color: #ebebeb;\n  border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open .dropdown-toggle.btn-default {\n  background-image: none;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n  background-color: #ffffff;\n  border-color: #cccccc;\n}\n.btn-default .badge {\n  color: #ffffff;\n  background-color: #fff;\n}\n.btn-primary {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #357ebd;\n}\n.btn-primary:hover,\n.btn-primary:focus,\n.btn-primary:active,\n.btn-primary.active,\n.open .dropdown-toggle.btn-primary {\n  color: #ffffff;\n  background-color: #3276b1;\n  border-color: #285e8e;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open .dropdown-toggle.btn-primary {\n  background-image: none;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n  background-color: #428bca;\n  border-color: #357ebd;\n}\n.btn-primary .badge {\n  color: #428bca;\n  background-color: #fff;\n}\n.btn-warning {\n  color: #ffffff;\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\n.btn-warning:hover,\n.btn-warning:focus,\n.btn-warning:active,\n.btn-warning.active,\n.open .dropdown-toggle.btn-warning {\n  color: #ffffff;\n  background-color: #ed9c28;\n  border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open .dropdown-toggle.btn-warning {\n  background-image: none;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\n.btn-warning .badge {\n  color: #f0ad4e;\n  background-color: #fff;\n}\n.btn-danger {\n  color: #ffffff;\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\n.btn-danger:hover,\n.btn-danger:focus,\n.btn-danger:active,\n.btn-danger.active,\n.open .dropdown-toggle.btn-danger {\n  color: #ffffff;\n  background-color: #d2322d;\n  border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open .dropdown-toggle.btn-danger {\n  background-image: none;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\n.btn-danger .badge {\n  color: #d9534f;\n  background-color: #fff;\n}\n.btn-success {\n  color: #ffffff;\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\n.btn-success:hover,\n.btn-success:focus,\n.btn-success:active,\n.btn-success.active,\n.open .dropdown-toggle.btn-success {\n  color: #ffffff;\n  background-color: #47a447;\n  border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open .dropdown-toggle.btn-success {\n  background-image: none;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\n.btn-success .badge {\n  color: #5cb85c;\n  background-color: #fff;\n}\n.btn-info {\n  color: #ffffff;\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\n.btn-info:hover,\n.btn-info:focus,\n.btn-info:active,\n.btn-info.active,\n.open .dropdown-toggle.btn-info {\n  color: #ffffff;\n  background-color: #39b3d7;\n  border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open .dropdown-toggle.btn-info {\n  background-image: none;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\n.btn-info .badge {\n  color: #5bc0de;\n  background-color: #fff;\n}\n.btn-link {\n  color: #428bca;\n  font-weight: normal;\n  cursor: pointer;\n  border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n  background-color: transparent;\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n  border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n  color: #2a6496;\n  text-decoration: underline;\n  background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n  color: #999999;\n  text-decoration: none;\n}\n.btn-lg {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n.btn-sm {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.btn-xs {\n  padding: 1px 5px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n}\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n.nav {\n  margin-bottom: 0;\n  padding-left: 0;\n  list-style: none;\n}\n.nav:before,\n.nav:after {\n  content: \" \";\n  display: table;\n}\n.nav:after {\n  clear: both;\n}\n.nav:before,\n.nav:after {\n  content: \" \";\n  display: table;\n}\n.nav:after {\n  clear: both;\n}\n.nav > li {\n  position: relative;\n  display: block;\n}\n.nav > li > a {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n  color: #999999;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n  color: #999999;\n  text-decoration: none;\n  background-color: transparent;\n  cursor: not-allowed;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n  background-color: #eeeeee;\n  border-color: #428bca;\n}\n.nav .nav-divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n.nav > li > a > img {\n  max-width: none;\n}\n.nav-tabs {\n  border-bottom: 1px solid #dddddd;\n}\n.nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n  margin-right: 2px;\n  line-height: 1.428571429;\n  border: 1px solid transparent;\n  border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n  color: #555555;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-bottom-color: transparent;\n  cursor: default;\n}\n.nav-tabs.nav-justified {\n  width: 100%;\n  border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n  float: none;\n}\n.nav-tabs.nav-justified > li > a {\n  text-align: center;\n  margin-bottom: 5px;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n  top: auto;\n  left: auto;\n}\n@media (min-width: 768px) {\n  .nav-tabs.nav-justified > li {\n    display: table-cell;\n    width: 1%;\n  }\n  .nav-tabs.nav-justified > li > a {\n    margin-bottom: 0;\n  }\n}\n.nav-tabs.nav-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n  border: 1px solid #dddddd;\n}\n@media (min-width: 768px) {\n  .nav-tabs.nav-justified > li > a {\n    border-bottom: 1px solid #dddddd;\n    border-radius: 4px 4px 0 0;\n  }\n  .nav-tabs.nav-justified > .active > a,\n  .nav-tabs.nav-justified > .active > a:hover,\n  .nav-tabs.nav-justified > .active > a:focus {\n    border-bottom-color: #ffffff;\n  }\n}\n.nav-pills > li {\n  float: left;\n}\n.nav-pills > li > a {\n  border-radius: 4px;\n}\n.nav-pills > li + li {\n  margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n  color: #ffffff;\n  background-color: #428bca;\n}\n.nav-stacked > li {\n  float: none;\n}\n.nav-stacked > li + li {\n  margin-top: 2px;\n  margin-left: 0;\n}\n.nav-justified {\n  width: 100%;\n}\n.nav-justified > li {\n  float: none;\n}\n.nav-justified > li > a {\n  text-align: center;\n  margin-bottom: 5px;\n}\n.nav-justified > .dropdown .dropdown-menu {\n  top: auto;\n  left: auto;\n}\n@media (min-width: 768px) {\n  .nav-justified > li {\n    display: table-cell;\n    width: 1%;\n  }\n  .nav-justified > li > a {\n    margin-bottom: 0;\n  }\n}\n.nav-tabs-justified {\n  border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n  border: 1px solid #dddddd;\n}\n@media (min-width: 768px) {\n  .nav-tabs-justified > li > a {\n    border-bottom: 1px solid #dddddd;\n    border-radius: 4px 4px 0 0;\n  }\n  .nav-tabs-justified > .active > a,\n  .nav-tabs-justified > .active > a:hover,\n  .nav-tabs-justified > .active > a:focus {\n    border-bottom-color: #ffffff;\n  }\n}\n.tab-content > .tab-pane {\n  display: none;\n}\n.tab-content > .active {\n  display: block;\n}\n.nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.navbar {\n  position: relative;\n  min-height: 50px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n}\n.navbar:before,\n.navbar:after {\n  content: \" \";\n  display: table;\n}\n.navbar:after {\n  clear: both;\n}\n.navbar:before,\n.navbar:after {\n  content: \" \";\n  display: table;\n}\n.navbar:after {\n  clear: both;\n}\n@media (min-width: 1px) {\n  .navbar {\n    border-radius: 4px;\n  }\n}\n.navbar-header:before,\n.navbar-header:after {\n  content: \" \";\n  display: table;\n}\n.navbar-header:after {\n  clear: both;\n}\n.navbar-header:before,\n.navbar-header:after {\n  content: \" \";\n  display: table;\n}\n.navbar-header:after {\n  clear: both;\n}\n@media (min-width: 1px) {\n  .navbar-header {\n    float: left;\n  }\n}\n.navbar-collapse {\n  max-height: 340px;\n  overflow-x: visible;\n  padding-right: 15px;\n  padding-left: 15px;\n  border-top: 1px solid transparent;\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n  -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse:before,\n.navbar-collapse:after {\n  content: \" \";\n  display: table;\n}\n.navbar-collapse:after {\n  clear: both;\n}\n.navbar-collapse:before,\n.navbar-collapse:after {\n  content: \" \";\n  display: table;\n}\n.navbar-collapse:after {\n  clear: both;\n}\n.navbar-collapse.in {\n  overflow-y: auto;\n}\n@media (min-width: 1px) {\n  .navbar-collapse {\n    width: auto;\n    border-top: 0;\n    box-shadow: none;\n  }\n  .navbar-collapse.collapse {\n    display: block !important;\n    height: auto !important;\n    padding-bottom: 0;\n    overflow: visible !important;\n  }\n  .navbar-collapse.in {\n    overflow-y: visible;\n  }\n  .navbar-fixed-top .navbar-collapse,\n  .navbar-static-top .navbar-collapse,\n  .navbar-fixed-bottom .navbar-collapse {\n    padding-left: 0;\n    padding-right: 0;\n  }\n}\n.container > .navbar-header,\n.container > .navbar-collapse {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n@media (min-width: 1px) {\n  .container > .navbar-header,\n  .container > .navbar-collapse {\n    margin-right: 0;\n    margin-left: 0;\n  }\n}\n.navbar-static-top {\n  z-index: 1000;\n  border-width: 0 0 1px;\n}\n@media (min-width: 1px) {\n  .navbar-static-top {\n    border-radius: 0;\n  }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n}\n@media (min-width: 1px) {\n  .navbar-fixed-top,\n  .navbar-fixed-bottom {\n    border-radius: 0;\n  }\n}\n.navbar-fixed-top {\n  top: 0;\n  border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n  border-width: 1px 0 0;\n}\n.navbar-brand {\n  float: left;\n  padding: 15px 15px;\n  font-size: 18px;\n  line-height: 20px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n  text-decoration: none;\n}\n@media (min-width: 1px) {\n  .navbar > .container .navbar-brand {\n    margin-left: -15px;\n  }\n}\n.navbar-toggle {\n  position: relative;\n  float: right;\n  margin-right: 15px;\n  padding: 9px 10px;\n  margin-top: 8px;\n  margin-bottom: 8px;\n  background-color: transparent;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n.navbar-toggle .icon-bar {\n  display: block;\n  width: 22px;\n  height: 2px;\n  border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n  margin-top: 4px;\n}\n@media (min-width: 1px) {\n  .navbar-toggle {\n    display: none;\n  }\n}\n.navbar-nav {\n  margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n  padding-top: 10px;\n  padding-bottom: 10px;\n  line-height: 20px;\n}\n@media (max-width: 0px) {\n  .navbar-nav .open .dropdown-menu {\n    position: static;\n    float: none;\n    width: auto;\n    margin-top: 0;\n    background-color: transparent;\n    border: 0;\n    box-shadow: none;\n  }\n  .navbar-nav .open .dropdown-menu > li > a,\n  .navbar-nav .open .dropdown-menu .dropdown-header {\n    padding: 5px 15px 5px 25px;\n  }\n  .navbar-nav .open .dropdown-menu > li > a {\n    line-height: 20px;\n  }\n  .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-nav .open .dropdown-menu > li > a:focus {\n    background-image: none;\n  }\n}\n@media (min-width: 1px) {\n  .navbar-nav {\n    float: left;\n    margin: 0;\n  }\n  .navbar-nav > li {\n    float: left;\n  }\n  .navbar-nav > li > a {\n    padding-top: 15px;\n    padding-bottom: 15px;\n  }\n  .navbar-nav.navbar-right:last-child {\n    margin-right: -15px;\n  }\n}\n@media (min-width: 1px) {\n  .navbar-left {\n    float: left !important;\n  }\n  .navbar-right {\n    float: right !important;\n  }\n}\n.navbar-form {\n  margin-left: -15px;\n  margin-right: -15px;\n  padding: 10px 15px;\n  border-top: 1px solid transparent;\n  border-bottom: 1px solid transparent;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n  margin-top: 8px;\n  margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n  .navbar-form .form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .navbar-form .form-control {\n    display: inline-block;\n  }\n  .navbar-form select.form-control {\n    width: auto;\n  }\n  .navbar-form .radio,\n  .navbar-form .checkbox {\n    display: inline-block;\n    margin-top: 0;\n    margin-bottom: 0;\n    padding-left: 0;\n  }\n  .navbar-form .radio input[type=\"radio\"],\n  .navbar-form .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n@media (max-width: 0px) {\n  .navbar-form .form-group {\n    margin-bottom: 5px;\n  }\n}\n@media (min-width: 1px) {\n  .navbar-form {\n    width: auto;\n    border: 0;\n    margin-left: 0;\n    margin-right: 0;\n    padding-top: 0;\n    padding-bottom: 0;\n    -webkit-box-shadow: none;\n    box-shadow: none;\n  }\n  .navbar-form.navbar-right:last-child {\n    margin-right: -15px;\n  }\n}\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.navbar-nav.pull-right > li > .dropdown-menu,\n.navbar-nav > li > .dropdown-menu.pull-right {\n  left: auto;\n  right: 0;\n}\n.navbar-btn {\n  margin-top: 8px;\n  margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n  margin-top: 14px;\n  margin-bottom: 14px;\n}\n.navbar-text {\n  margin-top: 15px;\n  margin-bottom: 15px;\n}\n@media (min-width: 1px) {\n  .navbar-text {\n    float: left;\n    margin-left: 15px;\n    margin-right: 15px;\n  }\n  .navbar-text.navbar-right:last-child {\n    margin-right: 0;\n  }\n}\n.navbar-default {\n  background-color: #f8f8f8;\n  border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n  color: #777777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n  color: #5e5e5e;\n  background-color: transparent;\n}\n.navbar-default .navbar-text {\n  color: #777777;\n}\n.navbar-default .navbar-nav > li > a {\n  color: #777777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n  color: #333333;\n  background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n  color: #555555;\n  background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n  color: #cccccc;\n  background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n  border-color: #dddddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n  background-color: #dddddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n  background-color: #cccccc;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n  border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n  background-color: #e7e7e7;\n  color: #555555;\n}\n@media (max-width: 0px) {\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n    color: #777777;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #333333;\n    background-color: transparent;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #555555;\n    background-color: #e7e7e7;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #cccccc;\n    background-color: transparent;\n  }\n}\n.navbar-default .navbar-link {\n  color: #777777;\n}\n.navbar-default .navbar-link:hover {\n  color: #333333;\n}\n.navbar-inverse {\n  background-color: #222222;\n  border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n  color: #999999;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n.navbar-inverse .navbar-nav > li > a {\n  color: #999999;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n  color: #ffffff;\n  background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n  color: #444444;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n  border-color: #333333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n  background-color: #333333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n  background-color: #ffffff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n  border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n  background-color: #080808;\n  color: #ffffff;\n}\n@media (max-width: 0px) {\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n    border-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n    background-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n    color: #999999;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #ffffff;\n    background-color: transparent;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #ffffff;\n    background-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #444444;\n    background-color: transparent;\n  }\n}\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n.label {\n  display: inline;\n  padding: .2em .6em .3em;\n  font-size: 75%;\n  font-weight: bold;\n  line-height: 1;\n  color: #ffffff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: .25em;\n}\n.label[href]:hover,\n.label[href]:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n.label:empty {\n  display: none;\n}\n.btn .label {\n  position: relative;\n  top: -1px;\n}\n.label-default {\n  background-color: #999999;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n  background-color: #808080;\n}\n.label-primary {\n  background-color: #428bca;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n  background-color: #3071a9;\n}\n.label-success {\n  background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n  background-color: #449d44;\n}\n.label-info {\n  background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n  background-color: #31b0d5;\n}\n.label-warning {\n  background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n  background-color: #ec971f;\n}\n.label-danger {\n  background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n  background-color: #c9302c;\n}\n.badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 3px 7px;\n  font-size: 12px;\n  font-weight: bold;\n  color: #ffffff;\n  line-height: 1;\n  vertical-align: baseline;\n  white-space: nowrap;\n  text-align: center;\n  background-color: #999999;\n  border-radius: 10px;\n}\n.badge:empty {\n  display: none;\n}\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\na.badge:hover,\na.badge:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n  color: #428bca;\n  background-color: #ffffff;\n}\n.nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\n.alert {\n  padding: 15px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n.alert h4 {\n  margin-top: 0;\n  color: inherit;\n}\n.alert .alert-link {\n  font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n  margin-bottom: 0;\n}\n.alert > p + p {\n  margin-top: 5px;\n}\n.alert-dismissable {\n  padding-right: 35px;\n}\n.alert-dismissable .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  color: inherit;\n}\n.alert-success {\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n  color: #3c763d;\n}\n.alert-success hr {\n  border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n  color: #2b542c;\n}\n.alert-info {\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n  color: #31708f;\n}\n.alert-info hr {\n  border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n  color: #245269;\n}\n.alert-warning {\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n  color: #8a6d3b;\n}\n.alert-warning hr {\n  border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n  color: #66512c;\n}\n.alert-danger {\n  background-color: #f2dede;\n  border-color: #ebccd1;\n  color: #a94442;\n}\n.alert-danger hr {\n  border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n  color: #843534;\n}\n.clearfix:before,\n.clearfix:after {\n  content: \" \";\n  display: table;\n}\n.clearfix:after {\n  clear: both;\n}\n.center-block {\n  display: block;\n  margin-left: auto;\n  margin-right: auto;\n}\n.pull-right {\n  float: right !important;\n}\n.pull-left {\n  float: left !important;\n}\n.hide {\n  display: none !important;\n}\n.show {\n  display: block !important;\n}\n.invisible {\n  visibility: hidden;\n}\n.text-hide {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n.affix {\n  position: fixed;\n}\n"
  },
  {
    "path": "_archive/apps/samples/one-time-payment/index.html",
    "content": "<html>\n  <head>\n    <title>Identity API Sample App</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"/css/bootstrap.css\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"/css/app.css\">\n  </head>\n  <body> \n    <nav class=\"navbar navbar-default navbar-fixed-top\" role=\"navigation\">\n      <div class=\"navbar-header\">\n        <a class=\"navbar-brand\">One Time Payment Sample</a>  \n      </div>   \n    </nav>\n\n    <div id=\"licenseState\" class=\"alert\">\n      <span><b>License Status: </b> <span id=\"licenseStatus\">loading...</span></span>\n      <span><b>Created:</b> <span id=\"dateCreated\">loading...</span></span>\n    </div>\n\n    <pre id=\"license_info\">\n      Loading license data...\n    </pre>\n\n    <footer>\n      <p id=\"status\">&nbsp;</p>\n    </footer>\n    <script type=\"text/javascript\" src=\"/scripts/zepto-1.1.2.min.js\"></script>\n    <script type=\"text/javascript\" src=\"/scripts/moment-2.4.0.min.js\"></script>\n    <script type=\"text/javascript\" src=\"/scripts/app.js\"></script>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/one-time-payment/main.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n    \"id\": \"One-Time-Payment-Demo\",\n    \"innerBounds\": {\n      \"width\": 640,\n      \"height\": 310,\n      \"minWidth\": 640,\n      \"minHeight\": 310\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/one-time-payment/manifest.json",
    "content": "{\n  \"name\": \"One Time Payment Sample\",\n  \"version\": \"0.4.1.1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"29\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"storage\",\n    \"identity\"\n  ],\n  \"icons\": {\n    \"128\": \"/images/128.png\"\n  },\n  \"oauth2\": {\n    \"client_id\": \"912609627511-naonel81buqhb6egeqk4r531m75lbsr7.apps.googleusercontent.com\",\n    \"scopes\": [\n      \"https://www.googleapis.com/auth/chromewebstore.readonly\"\n    ]\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/one-time-payment/scripts/app.js",
    "content": "var CWS_LICENSE_API_URL = 'https://www.googleapis.com/chromewebstore/v1.1/userlicenses/';\nvar TRIAL_PERIOD_DAYS = 2;\nvar statusDiv;\n\nfunction init() {\n  statusDiv = $(\"#status\");\n  getLicense();\n}\n\n/*****************************************************************************\n* Call to license server to request the license\n*****************************************************************************/\n\nfunction getLicense() {\n  xhrWithAuth('GET', CWS_LICENSE_API_URL + chrome.runtime.id, true, onLicenseFetched);\n}\n\nfunction onLicenseFetched(error, status, response) {\n  console.log(error, status, response);\n  statusDiv.text(\"Parsing license...\");\n  response = JSON.parse(response);\n  $(\"#license_info\").text(JSON.stringify(response, null, 2));\n  if (status === 200) {\n    parseLicense(response);\n  } else {\n    $(\"#dateCreated\").text(\"N/A\");\n    $(\"#licenseState\").addClass(\"alert-danger\");\n    $(\"#licenseStatus\").text(\"Error\");\n    statusDiv.html(\"Error reading license server.\");\n  }\n}\n\n/*****************************************************************************\n* Parse the license and determine if the user should get a free trial\n*  - if license.accessLevel == \"FULL\", they've paid for the app\n*  - if license.accessLevel == \"FREE_TRIAL\" they haven't paid\n*    - If they've used the app for less than TRIAL_PERIOD_DAYS days, free trial\n*    - Otherwise, the free trial has expired \n*****************************************************************************/\n\nfunction parseLicense(license) {\n  var licenseStatus;\n  var licenseStatusText;\n  if (license.result && license.accessLevel == \"FULL\") {\n    console.log(\"Fully paid & properly licensed.\");\n    licenseStatusText = \"FULL\";\n    licenseStatus = \"alert-success\";\n  } else if (license.result && license.accessLevel == \"FREE_TRIAL\") {\n    var daysAgoLicenseIssued = Date.now() - parseInt(license.createdTime, 10);\n    daysAgoLicenseIssued = daysAgoLicenseIssued / 1000 / 60 / 60 / 24;\n    if (daysAgoLicenseIssued <= TRIAL_PERIOD_DAYS) {\n      console.log(\"Free trial, still within trial period\");\n      licenseStatusText = \"FREE_TRIAL\";\n      licenseStatus = \"alert-info\";\n    } else {\n      console.log(\"Free trial, trial period expired.\");\n      licenseStatusText = \"FREE_TRIAL_EXPIRED\";\n      licenseStatus = \"alert-warning\";\n    }\n  } else {\n    console.log(\"No license ever issued.\");\n    licenseStatusText = \"NONE\";\n    licenseStatus = \"alert-danger\";\n  }\n  $(\"#dateCreated\").text(moment(parseInt(license.createdTime, 10)).format(\"llll\"));\n  $(\"#licenseState\").addClass(licenseStatus);\n  $(\"#licenseStatus\").text(licenseStatusText);\n  statusDiv.html(\"&nbsp;\");\n}\n\n/*****************************************************************************\n* Helper method for making authenticated requests\n*****************************************************************************/\n\n// Helper Util for making authenticated XHRs\nfunction xhrWithAuth(method, url, interactive, callback) {\n  var retry = true;\n  getToken();\n\n  function getToken() {\n    statusDiv.text(\"Getting auth token...\");\n    console.log(\"Calling chrome.identity.getAuthToken\", interactive);\n    chrome.identity.getAuthToken({ interactive: interactive }, function(token) {\n      if (chrome.runtime.lastError) {\n        callback(chrome.runtime.lastError);\n        return;\n      }\n      console.log(\"chrome.identity.getAuthToken returned a token\", token);\n      access_token = token;\n      requestStart();\n    });\n  }\n\n  function requestStart() {\n    statusDiv.text(\"Starting authenticated XHR...\");\n    var xhr = new XMLHttpRequest();\n    xhr.open(method, url);\n    xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);\n    xhr.onload = requestComplete;\n    xhr.send();\n  }\n\n  function requestComplete() {\n    statusDiv.text(\"Authenticated XHR completed.\");\n    if (this.status == 401 && retry) {\n      retry = false;\n      chrome.identity.removeCachedAuthToken({ token: access_token },\n                                            getToken);\n    } else {\n      callback(null, this.status, this.response);\n    }\n  }\n}\n\n\ninit();"
  },
  {
    "path": "_archive/apps/samples/optional-permissions/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ggkojffeaocnfigijnfbnliopcilipgg\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Optional permissions API\n\nThis app shows how to use the permissions API to request optional permissions. It can list the attached serial devices, but only if the \"serial\" permission is granted. The app shows how to check if the permission is granted and how to request it if it is not.\n\n## APIs\n\n* [Serial API](http://developer.chrome.com/apps/app_serial)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n* [Permissions](http://developer.chrome.com/apps/permissions)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/optional-permissions/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/optional-permissions/main.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('permissions.html', {\n    id: 'permissions',\n    innerBounds: {\n      width: 640,\n      height: 480\n    }\n  });\n})\n"
  },
  {
    "path": "_archive/apps/samples/optional-permissions/manifest.json",
    "content": "{\n  \"name\": \"Optional Permissions Sample\",\n  \"version\": \"2.1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"23\",\n  \"description\": \"Shows how to use the optional permissions API\",\n\n  \"app\": {\n    \"background\": {\n      \"scripts\": [ \"main.js\" ]\n    }\n  },\n\n  \"optional_permissions\": [\n    \"serial\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/optional-permissions/permissions.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <style>\n    body {\n      margin: 0;\n      padding: 0;\n    }\n\n    #controls {\n      border-bottom: solid 1px #ccc;\n      padding: 2px;\n    }\n\n    #log {\n      white-space: pre-wrap;\n      font-family: monospace;\n      padding: 2px;\n    }\n  </style>\n</head>\n<body>\n  <div id=\"controls\">\n    <button id=\"list-devices\">List Serial Devices</button>\n    <button id=\"request-permission\">Request \"serial\" permission</button>\n    <button id=\"check-permission\">Check \"serial\" permission</button>\n    <script src=\"permissions.js\"></script>\n  </div>\n\n  <div id=\"log\"></div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/optional-permissions/permissions.js",
    "content": "function log(message) {\n  document.querySelector('#log').textContent += message + '\\n';\n}\n\ndocument.querySelector('#list-devices').onclick = function() {\n  try {\n    chrome.serial.getDevices(function(devices) {\n      if (chrome.runtime.lastError) {\n        log('Error when listing devices: ' + chrome.runtime.lastError.message);\n        return;\n      }\n      log('Serial devices: ');\n      devices.forEach(function(device) {\n        log('  ' + device.path);\n      });\n    });\n  } catch (ex) {\n    log('Exception when listing devices: ' + ex);\n  }\n};\n\ndocument.querySelector('#request-permission').onclick = function() {\n  chrome.permissions.request({permissions: ['serial']}, function(result) {\n    if (result) {\n      log('App was granted the \"serial\" permission.');\n    } else {\n      log('App was not granted the \"serial\" permission.');\n    }\n  });\n};\n\ndocument.querySelector('#check-permission').onclick = function() {\n  chrome.permissions.contains({permissions: ['serial']}, function(result) {\n    if (result) {\n      log('App has the \"serial\" permission.');\n    } else {\n      log('App does not have the \"serial\" permission.');\n    }\n  });\n};\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/lhdfniaagbjbipjmgfbnlbcmlbcgklkh\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Parrot AR.Drone 2.0 Controller\n\nThis app uses the [Gamepad API](http://www.html5rocks.com/en/tutorials/doodles/gamepad/) and the [chrome.socket API](https://developer.chrome.com/docs/extensions/reference/socket) to communicate with\na [Parrot AR.Drone 2.0](https://www.parrot.com/us/support/documentation/ar-drone).\n\nThe SDK specifies that there are 4 socket connections:\n\n* UDP 5554: Receiving navdata, i.e. battery, velocities, control state\n* TCP 5555: Receiving H264 video [not implemented]\n* UDP 5556: Sending AT commands for tilt, rotation and elevation\n* UDP 5559: Sending Admin commands\n\nThe app connects to port 5556 and sends commands to the Drone depending on which\nbuttons are pressed on the gamepad. The commands themselves are AT commands, which\nare essentially strings in a specific format. The command strings are concatenated\nand converted to an ArrayBuffer and sent over the socket connection. Since the\nprotocol in use is UDP there is no guarantee of packet delivery so all commands\nare sent approximately every 30ms.\n\nWhen data comes back in it is parsed according to the navdata specification in\nthe Drone SDK documentation. The navdata comes back in as an ArrayBuffer from which\nnumbers are read from fixed byte positions. This includes data on the control\nstate of the drone (flying, hovering, landing, taking off), the battery percentage,\nits angles, altitudes and velcocities.\n\n_Please note: this has only been tested with an Xbox 360 controller_\n\n## Resources\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n* [Socket](https://developer.chrome.com/docs/extensions/reference/socket)\n\n_Thanks to felixge for the [Node AR Drone lib](https://github.com/felixge/node-ar-drone), which served as a helpful reference._\n     \n## Screenshot\n![screenshot](/_archive/apps/samples/parrot-ar-drone/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <title>AR.Drone 2.0</title>\n    <link href=\"styles/drone.css\" rel=\"stylesheet\"></link>\n</head>\n<body>\n\n  <h1>AR.Drone 2.0</h1>\n  <p id=\"message\">Connect to the AR.Drone's Wifi network. Then press X\n    on your gamepad to get started.</p>\n  <div id=\"instructions\">\n    <h3>Instructions</h3>\n    <span><strong>X button:</strong> Connect to drone</span>\n    <span><strong>O button:</strong> Land / TakeOff</span>\n    <span><strong>□ button:</strong> Flat</span>\n    <span><strong>∆ button:</strong> Flip</span>\n    <span><strong>Left stick:</strong> Move</span>\n    <span><strong>Right stick:</strong> Rotate left-right / raise and lower</span>\n    <span><strong>Left shoulder button:</strong> Emergency</span>\n    <span><strong>Select button:</strong> Shutdown</span>\n  </div>\n  <div id=\"state\">\n    <h3>Drone states</h3>\n    <span><strong>drone state:</strong><label id=\"droneState\">?</label></span>\n    <span><strong>vison flag:</strong><label id=\"visonFlag\">?</label></span>\n    <span><strong>control state:</strong><label id=\"controlState\">?</label></span>\n    <span><strong>battery%:</strong><label id=\"batteryPercentage\">?</label></span>\n    <span><strong>theta:</strong><label id=\"theta\">?</label></span>\n    <span><strong>phi:</strong><label id=\"phi\">?</label></span>\n    <span><strong>psi:</strong><label id=\"psi\">?</label></span>\n    <span><strong>altitude:</strong><label id=\"altitude\">?</label></span>\n    <span><strong>vx:</strong><label id=\"vx\">?</label></span>\n    <span><strong>vy:</strong><label id=\"vy\">?</label></span>\n    <span><strong>vz:</strong><label id=\"vz\">?</label></span>\n  </div>\n\n  <div id=\"commands\">\n    <h2>Command log</h2>\n    <textarea id=\"log\"></textarea>\n  </div>\n\n  <script src=\"third-party/gamepad.js\"></script>\n\n  <script src=\"lib/Util.js\"></script>\n  <script src=\"lib/NavData.js\"></script>\n  <script src=\"lib/Command.js\"></script>\n  <script src=\"lib/Sequence.js\"></script>\n  <script src=\"lib/API.js\"></script>\n  <script src=\"lib/Gamepad.js\"></script>\n\n  <script src=\"scripts/app.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/lib/API.js",
    "content": "/**\n * API which opens the sockets and handles sending the data to\n * and receiving the data from the AR Drone\n *\n * Additional thanks to Felix Geisendörfer (felixge) for the Node AR Drone lib\n * which served as a helpful reference.\n *\n * @see https://github.com/felixge/node-ar-drone\n */\nvar DRONE = DRONE || {};\nDRONE.API = (function() {\n\n  var SIMULATE = false;\n\n  // Constants\n  var TO_DRONE = 0;\n  var TO_CLIENT = 1;\n  var DRONE_IP = \"192.168.1.1\";\n  var CLIENT_IP = \"192.168.1.2\";\n  var ONE_BUFFER = DRONE.Util.uint8ToArrayBuffer(1);\n  var BASE = (1 << 18) + (1 << 20) + (1 << 22) + (1 << 24) + (1 << 28);\n  var LAND = BASE + 0;\n  var TAKEOFF = BASE + (1 << 9);\n  var EMERGENCY = BASE + (1 << 8);\n\n  // Vars\n  var noop = function() {};\n  var keepAliveTimeout = 0;\n  var CONNECTIONS = 3;\n  var connectionsOutstanding = CONNECTIONS;\n  var looping = false;\n  var sockets = {\n    \"nav\": {\n      protocol: \"udp\",\n      port: 5554,\n      socket: null,\n    },\n    \"vid\": {\n      protocol: \"tcp\",\n      port: 5555,\n      socket: null,\n    },\n    \"at\": {\n      protocol: \"udp\",\n      port: 5556,\n      socket: null,\n    },\n    \"control\": {\n      protocol: \"tcp\",\n      port: 5559,\n      socket: null,\n    }\n  };\n  var status = {\n    verticalSpeed: 0,\n    angularSpeed: 0,\n    leftRightTilt: 0,\n    frontBackTilt: 0,\n    enabled: 0,\n    mode: LAND\n  };\n\n  callbacks = {\n\n    /**\n     * Called whenever one of our sockets has connected\n     */\n    onConnected: function(connectionResult) {\n\n      // if we have 0 or higher we're good\n      if(connectionResult >= 0) {\n\n        connectionsOutstanding--;\n\n        // if we're all done with our connecting\n        if(connectionsOutstanding === 0 && callbacks.onAllConnected) {\n\n          // start sending commands\n          sendKeepAliveCommand();\n          sendFlatTrim();\n          setConfigurations();\n\n          // now enable controls\n          status.enabled = 1;\n\n          if(callbacks.onAllConnected) {\n            callbacks.onAllConnected();\n          }\n        }\n\n      } else {\n        // Flag that there was an issue\n        if(callbacks.onConnectionError) {\n          callbacks.onConnectionError();\n        }\n      }\n    },\n\n    /**\n     * Called whenever one of our udp sockets receive messages\n     */\n    onReceive: function(info) {\n      if (info.remotePort == 5554) {\n        if(info.data.byteLength > 0) {\n          DRONE.NavData.parse(info.data);\n        } else {\n          shutdown();\n        }\n      } else if (info.remotePort == 5556) {\n        console.log(\"at socket receive data of size:\" + info.data.byteLength);\n      } else if (info.remotePort == 5559) {\n        console.log(\"control socket receive data of size:\" + info.data.byteLength);\n      } else {\n        console.log(\"unexpected data are received by port:\" + info.remotePort);\n      }\n    },\n\n    onReceiveError: function(info) {\n      console.log(\"network in trouble socketId:\" + info.socketId + \" resultCode:\" + info.resultCode);\n      shutdown();\n    },\n\n    /* Placeholder callbacks */\n    onAllConnected: null,\n    onConnectionError: null\n  };\n\n  // -- Bootstrap\n\n  function bootstrapClientIp() {\n    // double check the Client IP (sometimes the Drone assignes 192.168.1.3)\n    chrome.socket.getNetworkList(function(entries) {\n      if (entries) {\n        for (var i = 0; i < entries.length; i++) {\n          if (entries[i] && entries[i].address\n            && entries[i].address.indexOf(\"192.168.1.\") == 0) {\n            if (CLIENT_IP != entries[i].address) {\n              CLIENT_IP = entries[i].address;\n              log(\"Client IP changed to \"+CLIENT_IP);\n            }\n            connectDrone();\n            return;\n          }\n        }\n      }\n      callbacks.onConnectionError();\n    });\n  }\n\n  /**\n   * Initialises client IP\n   */\n  function init(cbConnected, cbConnectionError) {\n    if (sockets['at'].socket != null) {\n      return;\n    }\n    bootstrapClientIp();\n\n    // assign the callbacks\n    callbacks.onAllConnected = cbConnected;\n    callbacks.onConnectionError = cbConnectionError;\n  }\n\n  /**\n   * Initialises the connections to the Drone\n   */\n  function connectDrone() {\n    // send the drone AT commands\n    connect(sockets['at']);\n\n    // get navigation data from the drone\n    connect(sockets['nav']);\n\n    // get a video stream from the drone\n    // TODO: connect(sockets['vid'], 'tcp');\n\n    // send admin commands to the drone\n    connect(sockets['control']);\n\n    chrome.sockets.tcp.onReceive.addListener(callbacks.onReceive);\n    chrome.sockets.tcp.onReceiveError.addListener(callbacks.onReceiveError);\n    chrome.sockets.udp.onReceive.addListener(callbacks.onReceive);\n    chrome.sockets.udp.onReceiveError.addListener(callbacks.onReceiveError);\n    log(\"connection completed.\");\n  }\n\n\n  /**\n   * Closes and discards all the socket connections\n   */\n  function shutdown() {\n  try {\n    connectionsOutstanding = CONNECTIONS;\n    if (keepAliveTimeout) clearTimeout(keepAliveTimeout);\n    status.mode = LAND;\n    status.enabled = 0;\n    disconnect(sockets['at']);\n    disconnect(sockets['nav']);\n    disconnect(sockets['control']);\n  } catch (err) {\n    sockets['at'].socket = null;\n    sockets['nav'].socket = null;\n    sockets['control'].socket = null;\n  }\n  log(\"disconnected. press X to reconnect\");\n    // TODO: disconnect(sockets['vid'].socket);\n  }\n\n  /**\n   * Creates and connects a socket connection\n   *\n   * @see http://developer.chrome.com/apps/socket.html\n   */\n  function connect(sockRef) {\n\n    // grab the protocol, type, port and IP from\n    // the sockRef passed in and use that\n    // to create the socket\n    if (SIMULATE) {\n      callbacks.onConnected(1);\n    } else {\n      if (sockRef.protocol === \"tcp\") {\n        chrome.sockets.tcp.create({}, function(createInfo) {\n          sockRef.socket = createInfo.socketId;\n          chrome.sockets.tcp.connect(sockRef.socket,\n            DRONE_IP,\n            sockRef.port,\n            callbacks.onConnected);\n        });\n      } else if (sockRef.protocol === \"udp\") {\n        chrome.sockets.udp.create({}, function(createInfo) {\n          sockRef.socket = createInfo.socketId;\n          chrome.sockets.udp.bind(sockRef.socket,\n            CLIENT_IP, sockRef.port, callbacks.onConnected);\n        });\n      }\n    }\n  }\n\n  /**\n   * Disconnects and destroys the socket connection\n   */\n  function disconnect(sockRef) {\n    if (!SIMULATE) {\n      if (sockRef.protocol === \"tcp\") {\n        chrome.sockets.tcp.disconnect(sockRef.socket, function(result) {\n          chrome.sockets.tcp.close(sockRef.socket, noop);\n          sockRef.socket = null;\n        });\n      } else if (sockRef.protocol === \"udp\") {\n        chrome.sockets.udp.close(sockRef.socket, noop);\n        sockRef.socket = null;\n      }\n    }\n  }\n\n  // -- Stream functions\n\n  /**\n   * Converts an array of commands to a string and then\n   * an ArrayBuffer to send over the socket to the drone\n   */\n  function sendCommands(commands) {\n    var atSock = sockets['at'];\n    var commandBuffer = DRONE.Util.stringToArrayBuffer(commands.join(\"\"));\n\n    // output the commands\n    log(commands.join(\"\")+\"   \"+JSON.stringify(status));\n\n    // send all the commands\n    if (!SIMULATE) {\n      try {\n        chrome.sockets.udp.send(\n          atSock.socket,\n          commandBuffer,\n          DRONE_IP,\n          atSock.port,\n          function(sendInfo) {\n            if (sendInfo.resultCode < 0) {\n              shutdown();\n            }\n          });\n      } catch(err) {\n        shutdown();\n      }\n    }\n  }\n\n  /**\n   * Helper function that tells the drone what sensitivity\n   * we want. This is quite a high value (min = 0, max = 0.52)\n   */\n  function setConfigurations() {\n    var outdoor = 'FALSE';\n    sendCommands([\n      // Set sensitivity; This is quite a high value (min = 0, max = 0.52)\n      new DRONE.Command('CONFIG', ['\"control:euler_angle_max\"', '\"0.11\"']),\n      new DRONE.Command('CONFIG', ['\"control:indoor_euler_angle_max\"', '\"0.11\"']),\n      new DRONE.Command('CONFIG', ['\"control:outdoor_euler_angle_max\"', '\"0.11\"']),\n      // Informs the drone that it is going to be flying outdoors\n      new DRONE.Command('CONFIG', ['\"control:outdoor\"', '\"' + outdoor + '\"']),\n      // Set navdata_demo to receive navdata\n      new DRONE.Command('CONFIG', ['\"general:navdata_demo\"', '\"TRUE\"']),\n    ]);\n  }\n\n  /**\n   * Sends a keepalive command and attempts to read\n   * back the latest data from the drone\n   */\n  function sendKeepAliveCommand() {\n    var navSock = sockets['nav'];\n    if (!SIMULATE) {\n      try {\n        chrome.sockets.udp.send(\n          navSock.socket,\n          (new Uint8Array([1])).buffer,\n          DRONE_IP,\n          navSock.port,\n          function(sendInfo) {\n            if (sendInfo.resultCode < 0) {\n              shutdown();\n            }\n          });\n      } catch(err) {\n        shutdown();\n      }\n\n    }\n\n    // set up a keepalive because The drone does not receive any traffic for more than 2000ms;\n    // it will then stop all communication with the client\n    if (keepAliveTimeout) clearTimeout(keepAliveTimeout);\n    keepAliveTimeout = setTimeout(sendKeepAliveCommand, 1000);\n  }\n\n  var takeoffLandStart = 0;\n  var previousTakeoffStatus = LAND;\n\n  /**\n   * The takeoff loop. This should keep sending the REF command until the \n   * navdata shows that it has taken off, but since we don't yet interpret navdata,\n   * let's just keep it doing this for four seconds.\n   */\n  function takeOffOrLandInternal() {\n    looping = false;\n    if (!takeoffLandStart || previousTakeoffStatus != status.mode) {\n      takeoffLandStart = Date.now();\n      previousTakeoffStatus = status.mode;\n    } else {\n      // five seconds\n      if (takeoffLandStart + 5000 < Date.now()) {\n        takeoffLandStart = 0;\n        if (status.mode == TAKEOFF) {\n          looping = true;\n          loop();\n        }\n        return;\n      }\n    }\n\n    commands = [\n      // Take off\n      new DRONE.Command('REF', [\n        status.mode\n      ])\n\n    ];\n\n    // send and reschedule\n    sendCommands(commands);\n    setTimeout(takeOffOrLandInternal, 500);\n  }\n\n  /**\n   * The main loop. This sends the commands to the drone, including\n   * the tilt, speed and whether or not we want it to take off or land\n   */\n  function loop() {\n    if (looping == false) {\n      return;\n    }\n\n    commands = [\n      // Take off\n      new DRONE.Command('REF', [\n        status.mode\n      ]),\n\n      new DRONE.Command('PCMD', [\n        // Enables/Disables commands\n        status.enabled,\n        // Left - Right tilt\n        DRONE.Util.float32ToInt32(status.leftRightTilt),\n        // Front - Back tilt\n        DRONE.Util.float32ToInt32(status.frontBackTilt),\n        // Vertical Speed\n        DRONE.Util.float32ToInt32(status.verticalSpeed),\n        // Angular Speed\n        DRONE.Util.float32ToInt32(status.angularSpeed)\n\n      ])\n   ];\n\n    // send and schedule the update\n    sendCommands(commands);\n    setTimeout(loop, 60);\n  }\n\n  // -- Actions\n\n  function takeOffOrLand() {\n    if (status.mode == TAKEOFF) {\n      status.mode = LAND;\n    } else if (status.mode == LAND) {\n      status.mode = TAKEOFF;\n    }\n    if (takeoffLandStart == 0) {\n      takeOffOrLandInternal();\n    }\n  }\n\n  function emergency() {\n    // don't want drone to fly immediately after going to normal mode.\n    status.mode = LAND;\n    sendCommands([new DRONE.Command('REF', [EMERGENCY])]);\n  }\n\n  function raiseLower(val) {\n    val = check(val, 0);\n    status.verticalSpeed = val;\n  }\n\n  function tiltLeftRight(val) {\n    val = check(val, 0);\n    status.leftRightTilt = val;\n  }\n\n  function tiltFrontBack(val) {\n    val = check(val, 0);\n    status.frontBackTilt = val;\n  }\n\n  function rotateLeftRight(val) {\n    val = check(val, 0);\n    status.angularSpeed = -val;\n  }\n\n  function check(val, defaultVal) {\n    if(typeof val === \"undefined\") {\n      val = defaultVal;\n    }\n    return val;\n  }\n\n  /**\n   * Helper function we use before letting the drone take off\n   * that we use to let it know that it's horizontal\n   */\n  function sendFlatTrim() {\n    if (status.mode == LAND) {\n      sendCommands([new DRONE.Command('FTRIM')]);\n    }\n  }\n\n  // from ARDrone_SDK_2_0/ControlEngine/iPhone/Release/ARDroneGeneratedTypes.h\n  var ANIMATIONS = [\n    'phiM30Deg',\n    'phi30Deg',\n    'thetaM30Deg',\n    'theta30Deg',\n    'theta20degYaw200deg',\n    'theta20degYawM200deg',\n    'turnaround',\n    'turnaroundGodown',\n    'yawShake',\n    'yawDance',\n    'phiDance',\n    'thetaDance',\n    'vzDance',\n    'wave',\n    'phiThetaMixed',\n    'doublePhiThetaMixed',\n    'flipAhead',\n    'flipBehind',\n    'flipLeft',\n    'flipRight',\n  ];\n\n  function flipAnimation() {\n    if (status.mode == LAND) {\n      return;\n    }\n    looping = false;\n    sendCommands([new DRONE.Command('ANIM', [ANIMATIONS.indexOf('flipLeft'), 500])]);\n    setTimeout(function() {\n      looping = true;\n      loop();\n    }, 1000);\n  }\n\n  return {\n    init: init,\n    takeOffOrLand: takeOffOrLand,\n    emergency: emergency,\n    sendFlatTrim: sendFlatTrim,\n    raiseLower: raiseLower,\n    tiltLeftRight: tiltLeftRight,\n    tiltFrontBack: tiltFrontBack,\n    rotateLeftRight: rotateLeftRight,\n    shutdown: shutdown,\n    flipAnimation: flipAnimation,\n  };\n\n})();\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/lib/Command.js",
    "content": "var DRONE = DRONE || {};\nDRONE.Command = function(command, parts) {\n  this.command = command;\n  this.parts = parts || [];\n};\n\nDRONE.Command.prototype.create = function(command, parts) {\n  return new DRONE.Command(command, parts);\n};\n\nDRONE.Command.prototype.toString = function() {\n  return \"AT*\" + this.command + \"=\" +\n    DRONE.Sequence.next() + (this.parts.length ? \",\" : \"\") +\n    this.parts.join(\",\") + \"\\r\";\n};\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/lib/Gamepad.js",
    "content": "var DRONE = DRONE || {};\nDRONE.Gamepad = (function() {\n  var AXIS_THRESHOLD = 0.1;\n  var ANALOGUE_BUTTON_THRESHOLD = 0.5;\n\n  function showNotSupported() {\n    // TODO Show a connection message\n    log(\"Press a button to connect the gamepad\");\n  }\n\n  function updateGamepads() {\n    // Not implemented\n  }\n\n  function updateButton(button, gamepadId, label) {\n    var value, pressed;\n    if (typeof(button) == 'object') {\n      value = button.value;\n      pressed = button.pressed;\n    } else {\n      value = button;\n      pressed = button > tester.ANALOGUE_BUTTON_THRESHOLD;\n    }\n\n    if(pressed == true) {\n      switch(label) {\n        case 'button-left-shoulder-top':\n          DRONE.API.emergency();\n          break;\n        case 'button-select':\n          DRONE.API.shutdown();\n          break;\n        case 'button-1':\n          if(!!this.onConnected) {\n            this.onConnected();\n          }\n          break;\n        case 'button-2':\n          DRONE.API.takeOffOrLand();\n          break;\n        case 'button-3':\n          DRONE.API.sendFlatTrim();\n          break;\n        case 'button-4':\n          DRONE.API.flipAnimation();\n          break;\n      }\n    }\n  }\n\n  function updateAxis(value, gamepadId, label, stick, xAxis) {\n    value = (Math.floor(value * 100) / 100);\n\n    if(Math.abs(value) < AXIS_THRESHOLD) {\n      value = 0;\n    }\n\n    switch(stick) {\n      case \"stick-1\":\n        // tilt\n        if(xAxis) {\n          DRONE.API.tiltLeftRight(value);\n        } else {\n          DRONE.API.tiltFrontBack(value);\n        }\n        break;\n      case \"stick-2\":\n        // rotate, raise, lower\n        value *= -1;\n\n        if(xAxis) {\n          DRONE.API.rotateLeftRight(value);\n        } else {\n          DRONE.API.raiseLower(value);\n        }\n        break;\n    }\n\n  }\n\n  return {\n    onConnected: function() { console.log(\"Override DRONE.Gamepad.onConnected\"); },\n    showNotSupported: showNotSupported,\n    updateGamepads: updateGamepads,\n    updateButton: updateButton,\n    updateAxis: updateAxis\n  };\n\n})();\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/lib/NavData.js",
    "content": "var DRONE = DRONE || {};\nDRONE.NavData = (function() {\n  function parse(data) {\n  // See ARDroneLib/Soft/Common/navdata_common.h\n    var start = 16, checksum_block = 8;\n    var view = new DataView(data),\n        dataLen = data.byteLength;\n\n    if(start + checksum_block >= dataLen) {\n      return;\n    }\n\n    var header = view.getInt32(0, true);\n    var droneState = view.getInt32(4, true);\n    var sequence = view.getInt32(8, true);\n    var visonFlag = view.getInt32(12, true);\n    var options = null;\n\n    var optionId = view.getInt16(start, true);\n    if (optionId == 0) {\n      options = {\n          optionId: optionId,\n          optionSize: view.getInt16(start + 2, true),\n          controlState: view.getUint32(start + 4, true),\n          batteryPercentage: view.getUint32(start + 8, true),\n          theta: view.getFloat32(start + 12, true),\n          phi: view.getFloat32(start + 16, true),\n          psi: view.getFloat32(start + 20, true),\n          altitude: view.getInt32(start + 24, true),\n          vx: view.getFloat32(start + 28, true),\n          vy: view.getFloat32(start + 32, true),\n          vz: view.getFloat32(start + 36, true)\n        };\n    }\n\n    // TODO: parse droneState and controlState\n    document.getElementById('droneState').innerHTML = droneState;\n    document.getElementById('visonFlag').innerHTML = visonFlag;\n    document.getElementById('controlState').innerHTML = options.controlState;\n    document.getElementById('batteryPercentage').innerHTML = options.batteryPercentage;\n    document.getElementById('theta').innerHTML = options.theta;\n    document.getElementById('phi').innerHTML = options.phi;\n    document.getElementById('psi').innerHTML = options.psi;\n    document.getElementById('altitude').innerHTML = options.altitude;\n    document.getElementById('vx').innerHTML = options.vx;\n    document.getElementById('vy').innerHTML = options.vy;\n    document.getElementById('vz').innerHTML = options.vz;\n  }\n\n  return {\n    parse: parse\n  };\n\n})();\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/lib/Sequence.js",
    "content": "var DRONE = DRONE || {};\nDRONE.Sequence = (function() {\n\n  var sequence = 0;\n\n  function next() {\n    sequence++;\n    return sequence;\n  }\n\n  function reset() {\n    sequence = 0;\n  }\n\n  return {\n    next: next,\n    reset: reset\n  };\n})();\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/lib/Util.js",
    "content": "var DRONE = DRONE || {};\nDRONE.Util = (function() {\n\n  function stringToArrayBuffer(string) {\n    var buffer = new ArrayBuffer(string.length);\n    var view = new Uint8Array(buffer);\n    for(var i = 0; i < string.length; i++) {\n      view[i] = string.charCodeAt(i);\n    }\n    return buffer;\n  }\n\n  function float32ToInt32(floatVal) {\n    var buffer = new ArrayBuffer(4);\n    var view = new DataView(buffer);\n    view.setFloat32(0, floatVal, true);\n    return view.getInt32(0, true);\n  }\n\n  function uint8ToArrayBuffer(intVal) {\n    var view = new Uint8Array([intVal]);\n    return view.buffer;\n  }\n\n  function uint8ArrayToString(uArrayVal) {\n    var str = '';\n    for(var s = 0; s < uArrayVal.length; s++) {\n      str += String.fromCharCode(uArrayVal[s]);\n    }\n    return str;\n  }\n\n  function uint8ArrayToHex(uArrayVal) {\n    var str = '';\n    for(var s = 0; s < uArrayVal.length; s++) {\n      str += uArrayVal[s].toString(16) + ' ';\n    }\n    return str;\n  }\n\n  return {\n    stringToArrayBuffer: stringToArrayBuffer,\n    float32ToInt32: float32ToInt32,\n    uint8ToArrayBuffer: uint8ToArrayBuffer,\n    uint8ArrayToString: uint8ArrayToString,\n    uint8ArrayToHex: uint8ArrayToHex\n  };\n\n})();\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/main.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n\n  var isAliveCheck = 0,\n      appWindow = null;\n\n  isAliveCheck = setInterval(function() {\n    if(appWindow && appWindow.closed && appWindow.DRONE) {\n      appWindow.DRONE.API.shutdown();\n      appWindow=null;\n      if (isAliveCheck) clearInterval(isAliveCheck);\n    }\n  }, 1000);\n\n  chrome.app.window.create('index.html', {\n    id: \"mainwin\", \n    innerBounds: {\n      width: 600,\n      height: 800\n    }\n  }, function(createdWindow) {\n    appWindow = createdWindow.dom;\n  });\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"version\": \"0.3\",\n  \"name\": \"Drone Controller Sample\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [{\n    \"socket\": [\"udp-send-to::*\"]\n    }],\n  \"sockets\": {\n    \"tcpServer\": { \"listen\": \"\" },\n    \"tcp\": { \"connect\": [\"*:5555\", \"*:5559\"] },\n    \"udp\": { \"bind\": [\"*:5554\", \"*:5556\"], \"send\": [\"*:5554\", \"*:5556\"] }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"parrot-ar-drone\",\n  \"files_with_snippets\": [ ],\n  \"android\": {\"works\": true, \"comments\": \"Communication to the Drone works, but the UI requires a connected gamepad.\"}\n}\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/scripts/app.js",
    "content": "var logEl = document.getElementById('log');\nvar commandLog = document.getElementById('commands');\nvar message = document.getElementById('message');\n\nfunction clearLog() {\n  logEl.textContent = \"\";\n}\n\nfunction log(msg) {\n  logEl.textContent = msg;\n//  logEl.scrollTop = 10000000;\n}\n\nfunction onDroneConnected() {\n  message.style.display = \"none\";\n  instructions.style.display = \"block\";\n  state.style.display = \"block\";\n}\n\nfunction onDroneConnectionFailed() {\n  log(\"Connectioned failed - Are you attached to the Drone's Wifi network?\");\n}\n\nDRONE.Gamepad.onConnected = function() {\n  commandLog.style.display = \"block\";\n  DRONE.API.init(onDroneConnected, onDroneConnectionFailed);\n};\n\n// start the gamepad\ngamepadSupport.init();\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/styles/drone.css",
    "content": "html,\nbody {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  background: #E2E2E2;\n  color: #555;\n  text-shadow: 0 1px 1px rgba(255,255,255,0.4);\n  line-height: 140%;\n}\n\nh1 {\n  padding: 0 10px;\n  color: #333;\n  text-shadow: 0 1px 1px rgba(255,255,255,0.6);\n}\n\nh2 {\n  margin: 15px 0 10px 0;\n  padding: 0 10px;\n}\n\nh3 {\n  margin: 10px 0 0px 0;\n  padding: 0 0px;\n}\n\nspan {\n  margin: 15px 0 10px 0;\n  padding: 0 10px;\n}\n\nlabel {\n  color: #339;\n}\n\n#instructions, #state {\n  padding: 0 10px;\n}\n\ntextarea {\n  display: block;\n  width: 540px;\n  height: 150px;\n}\n\n#commands, #instructions, #state {\n  display: none;\n}\n"
  },
  {
    "path": "_archive/apps/samples/parrot-ar-drone/third-party/gamepad.js",
    "content": "/**\n * Code from http://www.html5rocks.com/en/tutorials/doodles/gamepad/\n * with tester switched out for DRONE.Gamepad\n */\nvar gamepadSupport = {\n    TYPICAL_BUTTON_COUNT: 16,\n    TYPICAL_AXIS_COUNT: 4,\n    BUTTON_THROTTLE_MILLISECOND: 100,\n    buttonPressedTime: 0,\n    ticking: false,\n    gamepads: [],\n    prevRawGamepadTypes: [],\n    prevTimestamps: [],\n    init: function () {\n        var gamepadSupportAvailable = navigator.getGamepads ||\n            !!navigator.webkitGetGamepads ||\n            !!navigator.webkitGamepads;\n        if (!gamepadSupportAvailable) {\n            DRONE.Gamepad.showNotSupported();\n        } else {\n            // Check and see if gamepadconnected/gamepaddisconnected is supported.\n            // If so, listen for those events and don't start polling until a gamepad\n            // has been connected.\n            if ('ongamepadconnected' in window) {\n              window.addEventListener('gamepadconnected',\n                                    gamepadSupport.onGamepadConnect, false);\n              window.addEventListener('gamepaddisconnected',\n                                      gamepadSupport.onGamepadDisconnect, false);\n            } else {\n              // If connection events are not supported just start polling\n              gamepadSupport.startPolling();\n            }\n        }\n    },\n    onGamepadConnect: function (event) {\n        gamepadSupport.gamepads.push(event.gamepad);\n        DRONE.Gamepad.updateGamepads(gamepadSupport.gamepads);\n        gamepadSupport.startPolling();\n    },\n    onGamepadDisconnect: function (event) {\n        for (var i in gamepadSupport.gamepads) {\n            if (gamepadSupport.gamepads[i].index == event.gamepad.index) {\n                gamepadSupport.gamepads.splice(i, 1);\n                break;\n            }\n        }\n        if (gamepadSupport.gamepads.length === 0) {\n            gamepadSupport.stopPolling();\n        }\n        DRONE.Gamepad.updateGamepads(gamepadSupport.gamepads);\n    },\n    startPolling: function () {\n        if (!gamepadSupport.ticking) {\n            gamepadSupport.ticking = true;\n            gamepadSupport.tick();\n        }\n    },\n    stopPolling: function () {\n        gamepadSupport.ticking = false;\n    },\n    tick: function () {\n        gamepadSupport.pollStatus();\n        gamepadSupport.scheduleNextTick();\n    },\n    scheduleNextTick: function () {\n        if (gamepadSupport.ticking) {\n            if (window.requestAnimationFrame) {\n                window.requestAnimationFrame(gamepadSupport.tick);\n            } else if (window.mozRequestAnimationFrame) {\n                window.mozRequestAnimationFrame(gamepadSupport.tick);\n            } else if (window.webkitRequestAnimationFrame) {\n                window.webkitRequestAnimationFrame(gamepadSupport.tick);\n            }\n        }\n    },\n    pollStatus: function () {\n        gamepadSupport.pollGamepads();\n        for (var i in gamepadSupport.gamepads) {\n            var gamepad = gamepadSupport.gamepads[i];\n            if (gamepad.timestamp &&\n                (gamepad.timestamp == gamepadSupport.prevTimestamps[i])) {\n              continue;\n            }\n            gamepadSupport.prevTimestamps[i] = gamepad.timestamp;\n            gamepadSupport.updateDisplay(i);\n        }\n    },\n    pollGamepads: function () {\n        var rawGamepads =\n            (navigator.getGamepads && navigator.getGamepads()) ||\n            (navigator.webkitGetGamepads && navigator.webkitGetGamepads());\n        if (rawGamepads) {\n            gamepadSupport.gamepads = [];\n            var gamepadsChanged = false;\n            for (var i = 0; i < rawGamepads.length; i++) {\n                if (typeof rawGamepads[i] != gamepadSupport.prevRawGamepadTypes[i]) {\n                    gamepadsChanged = true;\n                    gamepadSupport.prevRawGamepadTypes[i] = typeof rawGamepads[i];\n                }\n                if (rawGamepads[i]) {\n                    gamepadSupport.gamepads.push(rawGamepads[i]);\n                }\n            }\n\n            DRONE.Gamepad.updateGamepads(gamepadSupport.gamepads);\n\n        }\n    },\n    updateDisplay: function (gamepadId) {\n        var gamepad = gamepadSupport.gamepads[gamepadId];\n        DRONE.Gamepad.updateAxis(gamepad.axes[0], gamepadId, 'stick-1-axis-x', 'stick-1', true);\n        DRONE.Gamepad.updateAxis(gamepad.axes[1], gamepadId, 'stick-1-axis-y', 'stick-1', false);\n        DRONE.Gamepad.updateAxis(gamepad.axes[2], gamepadId, 'stick-2-axis-x', 'stick-2', true);\n        DRONE.Gamepad.updateAxis(gamepad.axes[3], gamepadId, 'stick-2-axis-y', 'stick-2', false);\n\n        if (Date.now() - gamepadSupport.buttonPressedTime < gamepadSupport.BUTTON_THROTTLE_MILLISECOND) {\n          return;\n        }\n        gamepadSupport.buttonPressedTime = Date.now();\n        DRONE.Gamepad.updateButton(gamepad.buttons[0], gamepadId, 'button-1');\n        DRONE.Gamepad.updateButton(gamepad.buttons[1], gamepadId, 'button-2');\n        DRONE.Gamepad.updateButton(gamepad.buttons[2], gamepadId, 'button-3');\n        DRONE.Gamepad.updateButton(gamepad.buttons[3], gamepadId, 'button-4');\n        DRONE.Gamepad.updateButton(gamepad.buttons[4], gamepadId, 'button-left-shoulder-top');\n        DRONE.Gamepad.updateButton(gamepad.buttons[6], gamepadId, 'button-left-shoulder-bottom');\n        DRONE.Gamepad.updateButton(gamepad.buttons[5], gamepadId, 'button-right-shoulder-top');\n        DRONE.Gamepad.updateButton(gamepad.buttons[7], gamepadId, 'button-right-shoulder-bottom');\n        DRONE.Gamepad.updateButton(gamepad.buttons[8], gamepadId, 'button-select');\n        DRONE.Gamepad.updateButton(gamepad.buttons[9], gamepadId, 'button-start');\n        DRONE.Gamepad.updateButton(gamepad.buttons[10], gamepadId, 'stick-1');\n        DRONE.Gamepad.updateButton(gamepad.buttons[11], gamepadId, 'stick-2');\n        DRONE.Gamepad.updateButton(gamepad.buttons[12], gamepadId, 'button-dpad-top');\n        DRONE.Gamepad.updateButton(gamepad.buttons[13], gamepadId, 'button-dpad-bottom');\n        DRONE.Gamepad.updateButton(gamepad.buttons[14], gamepadId, 'button-dpad-left');\n        DRONE.Gamepad.updateButton(gamepad.buttons[15], gamepadId, 'button-dpad-right');\n\n        var extraButtonId = gamepadSupport.TYPICAL_BUTTON_COUNT;\n        while (typeof gamepad.buttons[extraButtonId] != 'undefined') {\n            DRONE.Gamepad.updateButton(gamepad.buttons[extraButtonId], gamepadId, 'extra-button-' + extraButtonId);\n            extraButtonId++;\n        }\n        var extraAxisId = gamepadSupport.TYPICAL_AXIS_COUNT;\n        while (typeof gamepad.axes[extraAxisId] != 'undefined') {\n            DRONE.Gamepad.updateAxis(gamepad.axes[extraAxisId], gamepadId, 'extra-axis-' + extraAxisId);\n            extraAxisId++;\n        }\n    }\n};\n"
  },
  {
    "path": "_archive/apps/samples/platform-title/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/gdpimhplfcmbiakglpomcdcchbmgfiaj\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Titlebar Sample App\n\nThis is a basic demo showing alternate titlebars, written in HTML/CSS, depending on target platform.\n\n## Resources\n\n* [chrome.runtime.getPlatformInfo](https://developer.chrome.com/extensions/runtime#method-getPlatformInfo)\n* [chrome.app.runtime.onLaunched](https://developer.chrome.com/docs/extensions/reference/app_runtime#event-onLaunched)\n\n## Screenshot\n\n### Mac\n\n![screenshot](/_archive/apps/samples/platform-title/assets/screenshot_mac.png)\n\n### Chrome OS\n\n![screenshot](/_archive/apps/samples/platform-title/assets/screenshot_cros.png)\n"
  },
  {
    "path": "_archive/apps/samples/platform-title/background.js",
    "content": "var platformInfo = {};\n\nchrome.app.runtime.onLaunched.addListener(function() {\n\n  // Load platformInfo before continuing.\n  chrome.runtime.getPlatformInfo(function(info) {\n    platformInfo = info;\n\n    chrome.app.window.create('main.html', {\n      id: 'main',\n      frame: 'none',\n      // alphaEnabled: true,\n      innerBounds: {\n        width: 880,\n        height: 480\n      }\n    });\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/platform-title/main.css",
    "content": "* {\n  font: inherit;\n  color: inherit;\n  margin: 0;\n  padding: 0;\n}\n\nhtml {\n  overflow: hidden;\n}\n\nbody {\n  background: rgba(255, 255, 255, 0.5);\n  font-size: 16px;\n  line-height: 24px;\n  font-family: Roboto, RobotoDraft, Helvetica, Arial, sans-serif;\n  font-weight: 300;\n  overflow: hidden;\n  font-weight: 300;\n}\n\np {\n  margin-bottom: 8px;\n}\n\n.scroll {\n  position: absolute;\n  top: 2em;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  overflow-y: visible;\n  overflow-x: hidden;\n  padding: 8px 24px;\n  text-align: justify;\n}\n\n.titlebar {\n  position: fixed;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 2em;\n  line-height: 2em;\n  background: #7489fc;\n  transition: all 0.25s;\n  text-align: center;\n  color: white;\n  -webkit-app-region: drag;\n  app-region: drag;\n}\n\n.titlebar h1 {\n  font-size: 1.5em;\n}\n\n.titlebar .buttons {\n  margin: 0 8px;\n  display: block;\n  float: right;\n  font-size: 1em;\n  transition: 0.25s all;\n  word-wrap: none;\n  text-overflow: visible;\n\n  /**\n   * Mac supports dragging of interactive elements; ChromeOS (possibly others)\n   * makes the buttons unusable unless the drag bit is cleared.\n   */\n  -webkit-app-region: no-drag;\n  app-region: no-drag;\n}\n\n.titlebar .buttons button {\n  padding: 0;\n  margin: 0;\n  display: inline-block;\n  border: 0;\n  min-width: 2em;\n  text-align: center;\n  background: transparent;\n  cursor: pointer;\n  margin-right: 4px;\n  position: relative;\n  background: rgba(0, 0, 0, 0.1);\n  transition: all 0.25s;\n}\n\n.titlebar .buttons button:focus {\n  outline: 0;\n}\n\n.titlebar .buttons button:active {\n  color: rgba(255, 255, 255, 0.75);\n}\n\n.titlebar .buttons button:hover {\n  background: rgba(255, 255, 255, 0.25);\n}\n\n.titlebar.shadow {\n  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.3);\n  background: #fd6598;\n}\n\n.titlebar.fullscreen button.window {\n  display: none;\n}"
  },
  {
    "path": "_archive/apps/samples/platform-title/main.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>Native Window</title>\n  <link type=\"text/css\" rel=\"stylesheet\" href=\"main.css\" />\n  <script src=\"main.js\"></script>\n</head>\n<body>\n\n<div class=\"titlebar\">\n  <div class=\"buttons\">\n    <button id=\"title-close\">x</button>\n    <button class=\"window\" id=\"title-minimize\">-</button>\n    <button class=\"window\" id=\"title-maximize\">+</button>\n    <button id=\"title-fullscreen\">&#11799;</button>\n  </div>\n  <h1>\n    Custom Title\n  </h1>\n</div>\n\n<div class=\"scroll\">\n\n<p>\n  Wes Anderson gluten-free post-ironic PBR&amp;B. Synth chillwave post-ironic disrupt mustache ethical. Fixie Shoreditch ugh, narwhal synth Vice you probably haven't heard of them. Irony polaroid squid lomo Truffaut Bushwick iPhone Pitchfork, pour-over sustainable. Ennui scenester tattooed tousled. Carles leggings typewriter, pour-over Vice meggings vinyl Bushwick pork belly next level meditation hoodie farm-to-table. Beard ugh bitters, Pinterest Schlitz VHS heirloom farm-to-table blog.\n</p>\n<p>\n  Dreamcatcher craft beer salvia, ethical jean shorts Pitchfork yr disrupt fap try-hard Portland flexitarian Odd Future keytar Godard. Brunch mustache Vice beard. American Apparel hashtag Williamsburg, next level lomo XOXO High Life synth pour-over deep v mixtape messenger bag gluten-free Brooklyn salvia. Literally umami wolf lomo biodiesel. Mixtape typewriter blog, whatever Bushwick ennui leggings dreamcatcher pickled Blue Bottle. Skateboard Cosby sweater deep v, sriracha Thundercats hella shabby chic fingerstache aesthetic. 90's kale chips chia occupy banh mi.\n</p>\n\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/platform-title/main.js",
    "content": "// Determine platform and add platform-specific CSS. This should block the page\n// load, otherwise users will see a 'flash' of the page changing CSS.\n(function() {\n  var backgroundPage = window.opener;\n  var link = document.createElement('link');\n  link.type = 'text/css';\n  link.rel = 'stylesheet';\n  link.href = 'platform-' + backgroundPage.platformInfo.os + '.css';\n  document.head.appendChild(link);\n  console.info('inserting platform css', link.href);\n})();\n\nwindow.addEventListener('load', function() {\n  // Add 'shadow' when page is scrolled > 0.\n  var scroll = document.querySelector('.scroll');\n  var titlebar = document.querySelector('.titlebar');\n  scroll.addEventListener('scroll', function() {\n    titlebar.classList.toggle('shadow', scroll.scrollTop > 0);\n  });\n\n  function titleButtonClick(type, fn) {\n    var button = document.getElementById('title-' + type);\n    button.addEventListener('click', fn);\n  }\n  var win = chrome.app.window.current();\n\n  // Title button handlers for default actions..\n  titleButtonClick('close', function() { win.close(); });\n  titleButtonClick('minimize', function() { win.minimize(); });\n  titleButtonClick('maximize', function() {\n    if (win.isMaximized()) {\n      win.restore();\n    } else {\n      win.maximize();\n    }\n  });\n  titleButtonClick('fullscreen', function() {\n    if (win.isFullscreen()) {\n      win.restore();\n    } else {\n      win.fullscreen();\n    }\n  });\n\n  // If launched as fullscreen, set class.\n  if (win.isFullscreen()) {\n    titlebar.classList.add('fullscreen');\n  }\n\n  // When transitioning to fullscreen, set class.\n  win.onFullscreened.addListener(function() {\n    titlebar.classList.add('fullscreen');\n  });\n\n  // When being restored (to 'normal'), remove fullscreen class.\n  win.onRestored.addListener(function() {\n    titlebar.classList.remove('fullscreen');\n  });\n});\n\n"
  },
  {
    "path": "_archive/apps/samples/platform-title/manifest.json",
    "content": "{\n  \"name\": \"Titlebar\",\n  \"version\": \"1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"36\",\n\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\n        \"background.js\"\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/platform-title/platform-mac.css",
    "content": ".titlebar .buttons {\n  float: left;\n}\n\n.titlebar .buttons button {\n  border-radius: 2000px;\n  min-width: 1.5em;\n  height: 1.5em;\n  line-height: 1.5em;\n  background: linear-gradient(rgba(255, 255, 255, 0.3), rgba(192, 192, 192, 0.3));\n  color: transparent;\n  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);\n}\n\n.titlebar .buttons button:hover {\n  color: #333;\n  font-weight: 500;\n}"
  },
  {
    "path": "_archive/apps/samples/printing/LICENSE",
    "content": "// Copyright (c) 2013 The Chromium Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n//    * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n//    * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n//    * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "_archive/apps/samples/printing/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/eahldfpkmibbaajaoeifhjeehfgdagdm\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Printest\n\nThis application demonstrates printing. It supports the creation of any number\nof windows, each of which can be printed by a button on the window, and the most\nrecently accessed window can be printed from a control window. A timer based\nanimation can be displayed on the control window to demonstrates how timers are\nsuspended while printing.\n\n## Screenshot\n![screenshot](/_archive/apps/samples/printing/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/printing/a.js",
    "content": "/**\n * Copyright (c) 2013 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\n// A collection of utility objects for Chrome applications, used to separate\n// code likely to be found in different types of Chrome applications from code\n// specific to this particular application. Although general in nature, these\n// objects were specifically written for this application and not tested in any\n// other context, so they should not be considered part of a reusable framework\n// and caution should be exercised when reusing this code outside of this\n// application.\n\n\"use strict\";\n\nvar A = A || {};\n\n////////////////////////////////////////////////////////////////////////////////\n// Base object. All its methods are intentially generic and can be applied using\n// call() or apply() to objects not derived from A.object.\n\nA.object = {\n  // Multiple sets of properties can be provided as separate arguments.\n  // They will be merged to form the properties of the created object.\n  // To derive objects from prototypes other than A.object, use\n  // \"A.object.create.apply(prototype, arguments)\".\n  create: function(properties) {\n    var object = Object.create(this);\n    Array.prototype.forEach.call(arguments, this.copyFrom, object);\n    return object;\n  },\n\n  // Returns the first of the values identified by the specified paths that is\n  // defined. Multiple paths can be specified as separate arguments. No error\n  // is raised if components of any of the paths are undefined, so for example\n  // \"this.firstDefined('a.b', 'c')\" will not raise an error if |a| is undefined\n  // whereas the otherwise equivalent \"this.a.b || this.c\" would.\n  firstDefined: function(paths) {\n    var value, i;\n    for (i = 0; i < arguments.length && typeof value === 'undefined'; i += 1) {\n      if (arguments[i]) {\n        value = this;\n        arguments[i].split('.').forEach(function (key) {\n          value = (typeof value === 'undefined') ? value :\n                  (typeof value === 'boolean') ? new Boolean(value)[key] :\n                  (typeof value === 'number') ? new Number(value)[key] :\n                  value[key];\n        });\n      }\n    }\n    return value;\n  },\n\n  // Makes a shallow copy of the properties and returns the resulting object,\n  // creating that object if |this| is undefined.\n  copyFrom: function(from) {\n    var copy = this || {};\n    var keys = from ? Object.keys(from) : [];\n    keys.forEach(function(key) { copy[key] = from[key]; }, this);\n    return copy;\n  },\n\n  // Makes a shallow copy of the properties and returns the resulting object,\n  // creating that object if |to| is undefined.\n  copyTo: function(to) {\n    return A.object.copyFrom.call(to, this);\n  },\n\n  // Adds a listener for the specified event to the specified target. If the\n  // specified listener is a string, an event with that name will be added to\n  // the receiving object. Listeners for that new event can then be added with\n  // separate addListener calls. If the listener is a function, it will be bound\n  // to the receiving object.\n  addListener: function(target, event, listener) {\n    if (A.object.isPrototypeOf(target)) {\n      target.listeners_ = target.listeners_ || {};\n      target.listeners_[event] = target.listeners_[event] || [];\n      target.listeners_[event].push(this.makeListener_(listener));\n    } else if (target && target[event] && target[event].addListener) {\n      target[event].addListener(this.makeListener_(listener));\n    } else if (target) {\n      target.addEventListener(event, this.makeListener_(listener));\n    }\n  },\n\n  // Triggers the listeners added for the specified event.\n  callListeners: function(event) {\n    if (this.listeners_ && this.listeners_[event]) {\n      this.listeners_[event].forEach(function(listener) {\n        listener.apply(this.callee, this.arguments);\n      }, {callee: this, arguments: Array.prototype.slice.call(arguments, 1)});\n    }\n  },\n\n  /** @private */\n  makeListener_: function(listener) {\n    var event = (typeof listener == 'string' && A.object.isPrototypeOf(this));\n    return event ? this.callListeners.bind(this, listener) :\n           listener.bind ? listener.bind(this) :\n           listener;\n  }\n};\n\n////////////////////////////////////////////////////////////////////////////////\n// Logging. This object's methods can be invoked with any |this| value.\n\nA.console = A.object.create({\n  log: function() {\n    A.console.console_.log.apply(A.console.console_, arguments);\n  },\n\n  logError: function(message, url, line, column, error) {\n    A.console.log(error ? error.stack : (message + ':' + line + ':' + column));\n  }\n});\n\nA.console.console_ = (function() {\n  window.onerror = A.console.logError;\n  return window.console;\n}()),\n\n////////////////////////////////////////////////////////////////////////////////\n// Prototype for minimally functional promises objects (http://goo.gl/73FE3B).\n\n// properties = {\n//   value = value,       /* Optional, promise fulfilled if present */\n// }\nA.promise = A.object.create({\n  create: function(properties) {\n    var promise = A.object.create.apply(this, arguments);\n    return promise;\n  },\n\n  then: function(onFulfilled) {\n    var promise = A.promise.create();\n    if (this.hasOwnProperty('value')) {\n      this.propagateTo_({promise: promise, onFulfilled: onFulfilled});\n    } else {\n      this.derived_ = this.derived_ || [];\n      this.derived_.push({promise: promise, onFulfilled: onFulfilled});\n    }\n    return promise;\n  },\n\n  fulfill: function(value) {\n    if (!this.hasOwnProperty('value')) {\n      this.value = value;\n      if (this.derived_)\n        this.derived_.forEach(this.propagateTo_, this);\n    }\n    return this;\n  },\n\n  /** @private */\n  propagateTo_: function(derived) {\n    var propagated;\n    if (derived.onFulfilled)\n      propagated = derived.onFulfilled.call(this, this.value);\n    if (typeof propagated === 'undefined')\n      propagated = this.value;\n    if (!A.promise.isPrototypeOf(propagated)) {\n      derived.promise.fulfill(propagated);\n    } else if (typeof propagated.value !== 'undefined') {\n      derived.promise.fulfill(propagated.value);\n    } else {\n      propagated.derived_ = propagated.derived_ || [];\n      propagated.derived_.push({promise: derived.promise});\n    }\n  }\n});\n\n////////////////////////////////////////////////////////////////////////////////\n// Prototype for objects that control window contents.\n\n// properties = {\n//   domWindow = domWindow,        /* Optional, overrides other properties */\n//   appWindow = appWindow,        /* Optional, overrides other properties */\n//   url = 'example.html',         /* Optional, default = 'window.html' */\n//   id = 'example',               /* Optional */\n//   frame = 'chrome' || 'none',   /* Optional, default = 'chrome' */\n//   size = [width, height],       /* Pixels, optional, default = 400 x 300 */\n//   sizes = {                     /* Optional, overrides |size| */\n//     default = [width, height],  /* Pixels, optional, default = 400 x 300 */\n//     minimum = [width, height],  /* Pixels, optional, default = |size| */\n//     maximum = [width, height],  /* Pixels, optional, default = |size| */\n//   }\n// }\nA.controller = A.object.create({\n  create: function(properties) {\n    var controller = A.object.create.apply(this, arguments);\n    return controller.getDomWindow_().then(function(domWindow) {\n      this.domWindow = domWindow;\n      this.domDocument = domWindow && domWindow.document;\n      this.addListener(this.appWindow, 'onClosed', 'windowclosed');\n      this.addListener(this.appWindow, 'onBoundsChanged', this.boundsChanged_);\n      this.addListener(domWindow, 'focus', 'windowfocused');\n      this.addListener(domWindow, 'resize', 'windowresized');\n      this.addListener('#close', 'click', window.close.bind(domWindow));\n      (domWindow || {}).onerror = A.console.logError;\n      return this;\n    }.bind(controller));\n  },\n\n  getSizes: function() {\n    var sizes = this.sizes || {};\n    sizes.default = sizes.default || this.size || [400, 300];\n    sizes.minimum = sizes.minimum || this.size;\n    sizes.maximum = sizes.maximum || this.size;\n    return sizes;\n  },\n\n  getFrameSize: function() {\n    return {width: this.domWindow.outerWidth - this.domWindow.innerWidth,\n            height: this.domWindow.outerHeight - this.domWindow.innerHeight};\n  },\n\n  // |innerBounds| is optional and defaults to the window's inner bounds.\n  getOuterBounds: function(innerBounds) {\n    // Currently assumes all of the frame height is in the title bar.\n    var inner = innerBounds || this.bounds || this.appWindow.getBounds();\n    var frame = this.getFrameSize();\n    return {left: inner.left - Math.round(frame.width / 2),\n            top: inner.top - frame.height,\n            width: inner.width + frame.width,\n            height: inner.height + frame.height};\n    \n  },\n\n  // |outerBounds| is optional and defaults to the window's outer bounds.\n  getInnerBounds: function(outerBounds) {\n    // Currently assumes all of the frame height is in the title bar.\n    var outer = outerBounds || this.getOuterBounds();\n    var frame = this.getFrameSize();\n    return {left: outer.left + Math.round(frame.width / 2),\n            top: outer.top + frame.height,\n            width: outer.width - frame.width,\n            height: outer.height - frame.height};\n  },\n\n  queryElement: function(elementOrSelector) {\n    return (typeof elementOrSelector !== 'string') ? elementOrSelector :\n           this.domDocument.querySelector(elementOrSelector);\n  },\n\n  queryElements: function(elementsOrSelector) {\n    return (Array.isArray(elementsOrSelector)) ? elementsOrSelector :\n           (typeof elementsOrSelector !== 'string') ? [elementsOrSelector] :\n           this.domDocument.querySelectorAll(elementsOrSelector);\n  },\n\n  removeAllChildren: function(elementsOrSelector) {\n    elementsOrSelector = elementsOrSelector || this.domDocument.body;\n    this.queryElements(elementsOrSelector).forEach(function(element) {\n      while (element.lastChild)\n        element.removeChild(element.lastChild);\n    });\n  },\n\n  appendChild: function(child, parent) {\n    parent = parent || this.domDocument.body;\n    return parent.appendChild(child);\n  },\n\n  createElement: function(tag, text) {\n    var element = this.domDocument.createElement(tag);\n    element.textContent = text || '';\n    return element;\n  },\n\n  createDiv: function(text) {\n    return this.createElement('div', text);\n  },\n\n  addListener: function(target, event, listener) {\n    var elements = this.queryElements(target);\n    Array.prototype.forEach.call(elements, function(element) {\n      A.object.addListener.call(this, element, event, listener);\n    }, this);\n  },\n\n  /** @private */\n  getDomWindow_: function() {\n    var domWindow = this.firstDefined('domWindow', 'appWindow.contentWindow');\n    return domWindow ? A.promise.create().fulfill(domWindow) :\n                       this.createDomWindow_();\n  },\n\n  /** @private */\n  createDomWindow_: function() {\n    return this.createAppWindow_().then(function(appWindow) {\n      this.appWindow = appWindow;\n      return appWindow.contentWindow;\n    }.bind(this));\n  },\n\n  /** @private */\n  createAppWindow_: function(promise) {\n    var promise = A.promise.create();\n    var url = this.url || 'window.html';\n    var options = this.getWindowOptions_();\n    chrome.app.window.create(url, options, function(appWindow) {\n      appWindow.contentWindow.onload = promise.fulfill.bind(promise, appWindow);\n    });\n    return promise;\n  },\n\n  /** @private */\n  getWindowOptions_: function() {\n    var options = {};\n    var sizes = this.getSizes();\n    options.defaultWidth = sizes.default[0];\n    options.defaultHeight = sizes.default[1];\n    options.minWidth = sizes.minimum && sizes.minimum[0];\n    options.minHeight = sizes.minimum && sizes.minimum[1];\n    options.maxWidth = sizes.maximum && sizes.maximum[0];\n    options.maxHeight = sizes.maximum && sizes.maximum[1];\n    options.bounds = this.bounds;\n    options.id = this.id;\n    options.frame = this.frame || 'chrome';\n    return options;\n  },\n\n  /** @private */\n  boundsChanged_: function(promise) {\n    this.bounds = this.appWindow.getBounds();\n    this.callListeners('boundschanged');\n  }\n});\n\n////////////////////////////////////////////////////////////////////////////////\n// Prototype for objects that control applications.\n\nA.application = A.object.create({\n  documents: [],\n\n  create: function() {\n    if (!A.application.instance) {\n      A.application.instance = A.object.create.apply(this, arguments);\n    }\n    return A.promise.create().fulfill(A.application.instance);\n  },\n\n  // Designed to be bound, must be invoked so |this| is the focussed document.\n  documentWasFocused: function() {\n    Printest.application.documentWasClosed.call(this);\n    Printest.application.documents.push(this);\n  },\n\n  // Designed to be bound, must be invoked so |this| is the closed document.\n  documentWasClosed: function() {\n    var index = Printest.application.documents.indexOf(this);\n    if (index >= 0)\n      Printest.application.documents.splice(index, 1);\n  },\n\n  closeAllDocuments: function() {\n    // The documents array is copied as it will change during document closure.\n    this.documents.slice().forEach(function(document) {\n      document.appWindow.close();\n    });\n  },\n\n  getCenteredBounds: function(area, width, height) {\n    return {left: area.left + Math.round((area.width - width) / 2),\n            top: area.top + Math.round((area.height - height) / 2),\n            width: width,\n            height: height};\n  },\n\n  areBoundsInSameScreen: function(bounds, controller) {\n    var screen = controller.domWindow.screen;\n    var outer = controller.getOuterBounds(bounds);\n    return outer.left >= screen.availLeft &&\n           outer.top >= screen.availTop &&\n           outer.left + outer.width <= screen.availLeft + screen.availWidth &&\n           outer.top + outer.height <= screen.availTop + screen.availHeight;\n  },\n\n  doBoundsOverlapDocument: function(bounds) {\n    var outer = this.documents[0] && this.documents[0].getOuterBounds(bounds) || {};\n    return this.documents.some(function(document) {\n      document = document.getOuterBounds();\n      return (outer.left < document.left + document.width &&\n              document.left < outer.left + outer.width &&\n              outer.top < document.top + document.height &&\n              document.top < outer.top + outer.height);\n    });\n  }\n});\n"
  },
  {
    "path": "_archive/apps/samples/printing/application.js",
    "content": "/**\n * Copyright (c) 2013 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\n\"use strict\";\n\nvar Printest = Printest || A.object.create({});\n\nPrintest.application = A.object.create.call(A.application, {\n\n  create: function() {\n    return A.application.create.call(this).then(function(application) {\n      return application.getSettings_().then(function(settings) {\n        return settings.bounds || application.getDefaultControlBounds_();\n      }).then(function(bounds) {\n        return application.createControls_(bounds);\n      }).then(function(controls) {\n        application.controls = controls;\n        return application.createNewDocument_();\n      }).then(function(document) {\n        return application;\n      });\n    });\n  },\n\n  documentWasFocused: function() {\n    var application = Printest.application.instance;\n    A.application.documentWasFocused.apply(this, arguments);\n    application.controls.documentsChanged(application.documents);\n  },\n\n  documentWasClosed: function() {\n    var application = Printest.application.instance;\n    A.application.documentWasClosed.apply(this, arguments);\n    application.controls.documentsChanged(application.documents);\n  },\n\n  /** @private */\n  getSettings_: function() {\n    var promise = A.promise.create();\n    chrome.storage.sync.get('settings', function(items) {\n      promise.fulfill(items.settings || {});\n    });\n    return promise;\n  },\n\n  /** @private */\n  getDefaultControlBounds_: function() {\n    var promise = A.promise.create();\n    // chrome.system.display.getInfo is stubbed for <http://crbug.com/310289>.\n    this.chromeSystemDisplayGetInfoStub_(function(displays) {\n      displays.forEach(function(display) {\n        if (display.isPrimary)\n          promise.fulfill(this.getCenteredControlBounds_(display.workArea));\n      }, this);\n    }.bind(this));\n    return promise;\n  },\n\n  /** @private */\n  chromeSystemDisplayGetInfoStub_: function(callback) {\n    callback.call(this, [{isPrimary: true,\n                          workArea: {left: 0, top: 0,\n                                     width: 1024, height: 768}}]);\n  },\n\n  /** @private */\n  getCenteredControlBounds_: function(area) {\n    var width = Printest.document.getSizes().default[0];\n    var height = Printest.controls.getSizes().default[1];\n    var center = this.getCenteredBounds(area, width, height);\n    return {left: center.left,\n            top: center.top - Printest.document.getSizes().default[1],\n            width: width,\n            height: height};\n  },\n\n  /** @private */\n  createControls_: function(bounds) {\n    return Printest.controls.create({bounds: bounds}).then(function(controls) {\n      this.addListener(controls, 'createnew', this.createNewDocument_);\n      this.addListener(controls, 'printcurrent', this.printCurrentDocument_);\n      this.addListener(controls, 'windowclosed', this.closeAllDocuments);\n      this.addListener(controls, 'boundschanged', this.saveSettings_);\n    }.bind(this));\n  },\n\n  /** @private */\n  createNewDocument_: function() {\n    var properties = {bounds: this.getNextDocumentBounds_()};\n    return Printest.document.create(properties).then(function(document) {\n      document.addListener(document, 'windowfocused', this.documentWasFocused);\n      document.addListener(document, 'windowclosed', this.documentWasClosed);\n      this.documentWasFocused.call(document);\n    }.bind(this));\n  },\n\n  /** @private */\n  printCurrentDocument_: function() {\n    if (this.documents && this.documents.length)\n      this.documents[this.documents.length - 1].print();\n  },\n\n  /** @private */\n  saveSettings_: function() {\n    if (!this.settingsTimeout_) {\n      this.settingsTimeout_ = window.setTimeout(function() {\n        var bounds = this.controls.getInnerBounds();\n        chrome.storage.sync.set({settings: {bounds: bounds}});\n        delete this.settingsTimeout_;\n      }.bind(this), 0);\n    }\n  },\n\n  /** @private */\n  getNextDocumentBounds_: function() {\n    // Try with bounds below the controls window, then with bounds below each of\n    // the existing document window starting with the most recently focussed\n    // one, stopping and using the first bounds that aren't offscreen and don't\n    // overlap any existing document window. All bounds here are inner bounds.\n    var i, controller, bounds, found = false;\n    for (i = this.documents.length; !found && i >= 0; i -= 1) {\n      bounds = this.getBoundsBelow_(this.documents[i] || this.controls);\n      bounds.height = Printest.document.getSizes().default[1];\n      found = this.areBoundsInSameScreen(bounds, this.controls) &&\n              !this.doBoundsOverlapDocument(bounds);\n    }\n    return found ? bounds : undefined;\n  },\n\n  /** @private */\n  getBoundsBelow_: function(controller) {\n    var bounds = controller.getInnerBounds();\n    var offset = bounds.height + controller.getFrameSize().height + 10;\n    return {left: bounds.left, top: bounds.top + offset,\n            width: bounds.width, height: bounds.height};\n  }\n});\n"
  },
  {
    "path": "_archive/apps/samples/printing/controls.html",
    "content": "<html>\n  <head>\n    <title>Controls</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n  </head>\n  <body id=\"controls\">\n    <div id=\"animation\">\n      <label class=\"checkbox\">\n        <input type=\"checkbox\">\n        <span>\n          <a>A</a><a>n</a><a>i</a><a>m</a><a>a</a><!--\n          --><a>t</a><a>i</a><a>o</a><a>n</a>\n        </span>\n      </label>\n    </div>\n    <div><button id=\"create-new\">New window</button></div>\n    <div><button id=\"print-current\">Print current window</button></div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/printing/controls.js",
    "content": "/**\n * Copyright (c) 2013 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\n\"use strict\";\n\nvar Printest = Printest || {};\n\nPrintest.controls = A.object.create.call(A.controller, {\n  url: 'controls.html',\n  frame: 'chrome',\n  sizes: {minimum: [184, 103], default: [184, 103], maximum: [999999, 103]},\n\n  create: function(properties) {\n    // Make the width the same as a document window so things will look nice\n    // when document windows are created below the controls window.\n    var width = Printest.document.sizes.default[0];\n    this.sizes.minimum[0] = this.sizes.default[0] = width;\n\n    return A.controller.create.apply(this, arguments).then(function (view) {\n      view.animation = view.queryElement('#animation');\n      view.checkbox = view.queryElement('#animation input');\n      view.addListener('#animation input', 'click', view.toggleAnimation_);\n      view.addListener('#create-new', 'click', 'createnew');\n      view.addListener('#print-current', 'click', 'printcurrent');\n    });\n  },\n\n  documentsChanged: function(documents) {\n    this.queryElement('#print-current').disabled = (documents.length == 0);\n  },\n\n  /** @private */\n  // The animation created here serves to demonstrate that setInterval() and\n  // setTimeout() timers are paused while the print preview dialog is open.\n  toggleAnimation_: function(event) {\n    this.animated = !this.animated;\n    this.checkbox.checked = this.animated;\n    if (this.animated) {\n      this.animation.dataset.state = 1;\n      this.timerId = this.domWindow.setInterval(function() {\n        if (this.animated) {\n          this.animation.dataset.state = (this.animation.dataset.state % 9) + 1;\n        } else {\n          this.domWindow.clearInterval(this.timerId);\n          delete this.animation.dataset.state;\n        }\n      }.bind(this), 1 / 9 * 1000);\n    }\n  }\n});\n"
  },
  {
    "path": "_archive/apps/samples/printing/document.html",
    "content": "<html>\n  <head>\n    <title>Printest</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n  </head>\n  <body>\n    <div id=\"fill-contents\">\n      <div id=\"centered-container\">\n        <div id=\"centered-contents\">\n          Numbers from <span id=\"from\"></span> to <span id=\"to\"></span>\n        </div>\n      </div>\n    </div>\n    <div id=\"fill-footer\"><button id=\"print\">Print</button></div>\n    <iframe name=\"print\" src=\"printout.html\">\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/printing/document.js",
    "content": "/**\n * Copyright (c) 2013 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\n\"use strict\";\n\nvar Printest = Printest || {};\n\nPrintest.document = A.object.create.call(A.controller, {\n  // The minimum window size set below allow the print preview panel to be large\n  // enough to be usable (even before http://crbug.com/307839 is fixed).\n  url: 'document.html',\n  frame: 'chrome',\n  sizes: {minimum: [438, 219], default: [438, 219]},\n\n  create: function(properties) {\n    return A.controller.create.apply(this, arguments).then(function(document) {\n      document.queryElement('#from').textContent = document.from = 1;\n      document.queryElement('#to').textContent = document.to = 99;\n      document.addListener('#print', 'click', document.print);\n      document.addListener(document, 'windowresized', document.onResize_);\n      document.onResize_();\n      return document.createPrintout_();\n    }).then(function(printout) {\n      printout.document.printout = printout;\n      return printout.document;\n    });\n  },\n\n  print: function() {\n    this.printout.printNumbers(this.from, this.to);\n  },\n\n  /** @private */\n  createPrintout_: function() {\n    return Printest.printout.create({\n      domWindow: this.domWindow.frames['print'],\n      document: this\n    });\n  },\n\n  /** @private */\n  onResize_: function() {\n    var height = this.queryElement('#fill-footer').scrollHeight;\n    this.queryElement('#fill-contents').style.bottom = height + 'px';\n  }\n});\n"
  },
  {
    "path": "_archive/apps/samples/printing/main.js",
    "content": "/**\n * Copyright (c) 2013 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\n\"use strict\";\n\nchrome.app.runtime.onLaunched.addListener(function() {\n  Printest.application.create();\n});\n"
  },
  {
    "path": "_archive/apps/samples/printing/manifest.json",
    "content": "{\n  \"name\": \"Printest\",\n  \"description\": \"A printing testbed\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"32\",\n  \"version\": \"0.1.7\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\n        \"a.js\",\n        \"printout.js\",\n        \"document.js\",\n        \"controls.js\",\n        \"application.js\",\n        \"main.js\"\n      ]\n    }\n  },\n  \"permissions\": [\n    \"storage\",\n    \"system.display\"\n  ],\n  \"icons\": {\n    \"16\": \"icon-16x16.png\",\n    \"128\": \"icon-128x128.png\"\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/printing/printout.html",
    "content": "<html>\n  <head>\n    <title>Printing Sample</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/printing/printout.js",
    "content": "/**\n * Copyright (c) 2013 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\n\"use strict\";\n\nvar Printest = Printest || {};\n\nPrintest.printout = A.object.create.call(A.controller, {\n  url: 'printout.html',\n  size: [240, 100],\n\n  printNumbers: function(from, to) {\n    this.removeAllChildren();\n    this.appendNumbers_(from, to);\n    this.domWindow.print();\n  },\n\n  /** @private */\n  appendNumbers_: function(from, to) {\n    var i;\n    for (i = from; i <= to; ++i)\n      this.appendChild(this.createDiv(this.spellNumber_(i)));\n  },\n\n  /** @private */\n  spellNumber_: function(number) {\n    return (number < 20) ? this.spellUnits_(number) :\n           (number < 100) ? this.spellTens_(number) :\n           (number < 1000) ? this.spellHundreds_(number) :\n           this.spellThousands_(number);\n  },\n\n  /** @private */\n  spellThousands_: function(number) {\n    // We ignore millions, billions, trillions, etc...\n    var separator = (number % 1000) ? ' thousand ' : ' thousand';\n    var suffix = (number % 1000) ? this.spellNumber_(number % 1000) : '';\n    return this.spellNumber_(Math.floor(number / 1000)) + separator + suffix;\n  },\n\n  /** @private */\n  spellHundreds_: function(number) {\n    var separator = (number % 100) ? ' hundred ' : ' hundred';\n    var suffix = (number % 100) ? this.spellNumber_(number % 100) : '';\n    return this.spellNumber_(Math.floor(number / 100)) + separator + suffix;\n  },\n\n  /** @private */\n  spellTens_: function(number) {\n    var separator = (number % 10) ? ' ' : '';\n    var suffix = (number % 10) ? this.spellUnits_(number % 10) : '';\n    return (number >= 90) ? 'ninety' + separator + suffix :\n           (number >= 80) ? 'eighty' + separator + suffix :\n           (number >= 70) ? 'seventy' + separator + suffix :\n           (number >= 60) ? 'sixty' + separator + suffix :\n           (number >= 50) ? 'fifty' + separator + suffix :\n           (number >= 40) ? 'forty' + separator + suffix :\n           (number >= 30) ? 'thirty' + separator + suffix :\n                            'twenty' + separator + suffix;\n  },\n\n  /** @private */\n  spellUnits_: function(number) {\n    return (number >= 19) ? 'nineteen' :\n           (number >= 18) ? 'eighteen' :\n           (number >= 17) ? 'seventeen' :\n           (number >= 16) ? 'sixteen' :\n           (number >= 15) ? 'fifteen' :\n           (number >= 14) ? 'fourteen' :\n           (number >= 13) ? 'thirteen' :\n           (number >= 12) ? 'twelve' :\n           (number >= 11) ? 'eleven' :\n           (number >= 10) ? 'ten' :\n           (number >= 9) ? 'nine' :\n           (number >= 8) ? 'eight' :\n           (number >= 7) ? 'seven' :\n           (number >= 6) ? 'six' :\n           (number >= 5) ? 'five' :\n           (number >= 4) ? 'four' :\n           (number >= 3) ? 'three' :\n           (number >= 2) ? 'two' :\n           (number >= 1) ? 'one' :\n                           'zero';\n  }\n});\n"
  },
  {
    "path": "_archive/apps/samples/printing/style.css",
    "content": "/**\n * Copyright (c) 2013 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\n@media screen {\n  #animation[data-state=\"1\"] a:nth-child(9n + 2),\n  #animation[data-state=\"2\"] a:nth-child(9n + 3),\n  #animation[data-state=\"3\"] a:nth-child(9n + 4),\n  #animation[data-state=\"4\"] a:nth-child(9n + 5),\n  #animation[data-state=\"5\"] a:nth-child(9n + 6),\n  #animation[data-state=\"6\"] a:nth-child(9n + 7),\n  #animation[data-state=\"7\"] a:nth-child(9n + 8),\n  #animation[data-state=\"8\"] a:nth-child(9n),\n  #animation[data-state=\"9\"] a:nth-child(9n + 1) {\n    color: red;\n  }\n\n  body {\n    /* -webkit-app-region: drag;  (disabled for <http://crbug.com/309783>) */\n    border-top: 1px solid lightgray;\n    font: normal 14px 'Lucida Grande', sans-serif;\n    margin: 0;\n    padding: 3px 5px 0;\n    position: relative;\n    text-align: center;\n  }\n\n  body#controls {\n    text-align: left;\n  }\n\n  button,\n  input[type='checkbox'] {\n    /* -webkit-app-region: no-drag;  (disabled for <http://crbug.com/309783>) */\n    -webkit-appearance: none;\n    background-image: -webkit-linear-gradient(rgb(237, 237, 237),\n                                              rgb(237, 237, 237) 38%,\n                                              rgb(222, 222, 222));\n    border: 1px solid rgba(0, 0, 0, 0.25);\n    border-radius: 2px;\n    box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.08),\n                inset 0 1px 2px 0 rgba(255, 255, 255, 0.75);\n    color: rgb(68, 68, 68);\n    font: inherit;\n    margin: 0 1px 0 0;\n    text-shadow: 0 1px 0 rgb(240, 240, 240);\n    -webkit-user-select: none;\n  }\n\n  button {\n    padding: 2px 10px 3px;\n    text-align: center;\n    width: 100%;\n  }\n\n  button:disabled {\n    background-image: -webkit-linear-gradient(rgb(241, 241, 241),\n                                              rgb(241, 241, 241) 38%,\n                                              rgb(230, 230, 230));\n    border-color: rgba(80, 80, 80, 0.2);\n    box-shadow: 0 1px 0 rgba(80, 80, 80, 0.08),\n                inset 0 1px 2px rgba(255, 255, 255, 0.75);\n    color: #aaa;\n  }\n\n  button:enabled:active,\n  button:enabled:active:hover,\n  input[type='checkbox']:active {\n    background-image: -webkit-linear-gradient(rgb(231, 231, 231),\n                                              rgb(231, 231, 231) 38%,\n                                              rgb(215, 215, 215));\n    box-shadow: none;\n    text-shadow: none;\n  }\n\n  button:enabled:hover,\n  input[type='checkbox']:hover {\n    background-image: -webkit-linear-gradient(rgb(240, 240, 240),\n                                              rgb(240, 240, 240) 38%,\n                                              rgb(224, 224, 224));\n    border-color: rgba(0, 0, 0, 0.3);\n    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12),\n                inset 0 1px 2px rgba(255, 255, 255, 0.95);\n    color: black;\n  }\n\n  #centered-container {\n    display: table;\n    height: 100%;\n    margin: 0;\n    padding: 0;\n    width: 100%;\n  }\n\n  #centered-contents {\n    display: table-cell;\n    margin: 0;\n    padding: 7px 10px;\n    vertical-align: middle;\n  }\n\n  div {\n    padding: 5px;\n  }\n\n  #fill-contents {\n    left: 0;\n    padding: 0;\n    position: absolute;\n    right: 0;\n    top: 0;\n  }\n\n  #fill-footer {\n    bottom: 0px;\n    left: 0px;\n    padding: 0 10px 10px;\n    position: absolute;\n    right: 0px;\n  }\n\n  iframe {\n    display: none;\n  }\n\n  input[type='checkbox'] {\n    bottom: -2px;\n    height: 13px;\n    position: relative;\n    vertical-align: middle;\n    width: 13px;\n  }\n\n  input[type='checkbox']:checked::before {\n    -webkit-user-select: none;\n    background-image: url('check-11x11.png');\n    background-size: 100% 100%;\n    content: '';\n    display: block;\n    height: 100%;\n    width: 100%;\n  }\n\n  label.checkbox {\n    display: -webkit-inline-box;\n  }\n\n  label.checkbox span {\n    display: block;\n    -webkit-margin-start: 0.6em;\n  }\n\n  *:focus {\n    outline: none;\n  }\n}\n\n@media print {\n  body {\n    text-align: center;\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/restarted-demo/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ljngdccbopfaompkjfhepllagnijbdne\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# onRestarted event\n\nWhen an app is restored after being unexpectedly terminated (eg, when the browser restarts) it will be sent an onRestarted event which should restore the app to the state it was in when it was last running.\n\nThis demo app creates a new counter on launch and restores any existing counters across app restarts.\n\n\n## APIs\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Storage](http://developer.chrome.com/apps/storage)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/restarted-demo/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/restarted-demo/background.js",
    "content": "// All the counters.\nCounter.all = [];\n\nfunction Counter(id, clicks, startedBy) {\n  this.id = id;\n  this.clicks = clicks;\n  this.startedBy = startedBy;\n  this.saving = false;\n  this.listeners = [];\n  this.save();\n  Counter.all.push(this);\n}\n\nCounter.prototype.attachToWindow = function(win, document) {\n  win.onClosed.addListener(this.close.bind(this));\n\n  var self = this;\n  document.getElementById('started-by').innerText = this.startedBy;\n  this.addListener(function(clicks) {\n    document.getElementById('number').innerText = clicks;\n  });\n\n  document.getElementById('clickButton').addEventListener('click', function(e) {\n    self.increment();\n  }, false);\n\n  document.getElementById('logLocalStorage').addEventListener('click', function(e) {\n    logLocalStorage();\n  }, false);\n};\n\nCounter.prototype.addListener = function(l) {\n  this.listeners.push(l);\n  this.notifyClickCount();\n};\n\nCounter.prototype.clearListeners = function() {\n  this.listeners = [];\n};\n\nCounter.prototype.notifyClickCount = function() {\n  for (var i = 0; i < this.listeners.length; i++) {\n    this.listeners[i](this.clicks);\n  }\n};\n\nCounter.prototype.increment = function() {\n  this.clicks++;\n  this.notifyClickCount();\n  this.save();\n};\n\nCounter.prototype.save = function() {\n  if (this.saving)\n    return;\n\n  this.saving = true;\n\n  var self = this;\n  (function(clicks) {\n    var counters = {};\n    counters[self.id] = {'clicks': clicks};\n    var data = {'counters': counters};\n    chrome.storage.local.get('counters', function(data) {\n      if (!data.counters) {\n        data.counters = {};\n      }\n      data.counters[self.id] = {'clicks': clicks};\n      chrome.storage.local.set(data, function() {\n        self.saving = false;\n        if (self.clicks != clicks) {\n          // self.clicks changed while we were saving, so save again.\n          self.save();\n        }\n      });\n    });\n  })(this.clicks);\n};\n\nCounter.prototype.close = function() {\n  this.clearListeners();\n  var self = this;\n  chrome.storage.local.get('counters', function(data) {\n    delete data.counters[self.id];\n    chrome.storage.local.set(data);\n  });\n\n  // Remove self from global list.\n  var i = Counter.all.indexOf(this);\n  if (i != -1)\n    Counter.splice(i, 1);\n};\n\nfunction runApp(counter) {\n  chrome.app.window.create('main.html', {\n    id: counter.id + '',\n    innerBounds: {\n      width: 800,\n      height: 600\n    }\n  }, function(win) {\n    win.contentWindow.onload = function() {\n      counter.attachToWindow(win, win.contentWindow.document);\n    };\n  });\n}\n\nchrome.app.runtime.onLaunched.addListener(function() {\n  if (Counter.all.length == 0) {\n    // We might have left over state from a previous hard shutdown.\n    chrome.storage.local.clear();\n  }\n  chrome.storage.local.get('nextId', function(data) {\n    if (!data.nextId)\n      data.nextId = 0;\n    var id = data.nextId++;\n    var counter = new Counter(id, 0, 'launched');\n    runApp(counter);\n    chrome.storage.local.set(data);\n  });\n});\n\nchrome.app.runtime.onRestarted.addListener(function() {\n  chrome.storage.local.get(null, function(data) {\n    for (var id in data.counters) {\n      var clicks = data.counters[id].clicks;\n      var counter = new Counter(id, clicks, 'restarted');\n      runApp(counter);\n    }\n  });\n});\n\nfunction logLocalStorage() {\n  chrome.storage.local.get(null, function(data) {\n    console.log(\"local storage:\", data);\n  });\n}\n"
  },
  {
    "path": "_archive/apps/samples/restarted-demo/main.html",
    "content": "<body>\n<p>\nThis app starts with a click count of zero when launched, but preserves that count when restarted.\n</p>\n<table>\n  <tr>\n    <td>Started by</td><td id='started-by'></td>\n  </tr>\n  <tr>\n    <td>Clicks</td><td id='number'></td>\n  </tr>\n</table>\n<input id='clickButton' type='submit' value='Click'></input>\n<input id='logLocalStorage' type='submit' value='Log local storage'></input>\n</body>\n"
  },
  {
    "path": "_archive/apps/samples/restarted-demo/manifest.json",
    "content": "{\n  \"name\": \"Restarted Event Sample\",\n  \"version\": \"2\",\n  \"manifest_version\": 2,\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\n        \"background.js\"\n      ]\n    }\n  },\n  \"permissions\": [\n    \"storage\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/restarted-demo/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"restarted-demo\",\n  \"files_with_snippets\": [ ],\n  \"ios\": {\"works\": true, \"comments\": \"Restart must be done via Safari remote debugging.\"}\n}\n"
  },
  {
    "path": "_archive/apps/samples/rich-notifications/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/cndmbddaappldijonoekcdfdlhemhejm\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Rich notifications\n\nThis sample shows how to use the \"templated\" notifications API,\naka Rich Notifications, which allows an app to show feature-rich notifications\nin the system tray. This API is still in experimental state.\n\n\n> WARNING: currently this API only works on ChromeOS and Windows. Linux should fail gracefully by displaying normal HTML5 notifications, but some info might not be presented on these platforms.\n\n## Resources\n\n* [Notification API documentation](http://developer.chrome.com/apps/notifications)\n\n## Screenshot\n\n![screenshot](/_archive/apps/samples/rich-notifications/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/rich-notifications/app.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function () {\n  chrome.app.window.create(\"window.html\", {\n    id: \"mainwin\",\n    innerBounds: {width:600, height:400}\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/rich-notifications/main.js",
    "content": "// Declare a variable to generate unique notification IDs\nvar notID = 0;\n\n// partial URLs to the images used in the example\nvar asURLs = [\n\t\"/images/inbox-64x64.png\",\n\t\"/images/inbox-08-64x64.png\",\n\t\"/images/white-64x64.png\",\n\t\"/images/africa-400x400.png\",\n\t\"/images/antartica-400x400.png\",\n\t\"/images/asia-400x400.png\",\n\t\"/images/europe-400x400.png\",\n\t\"/images/north-america-400x400.png\",\n\t\"/images/oceania-400x400.png\",\n\t\"/images/south-america-400x400.png\"\n];\n\n// List of sample notifications. These are further customized \n// in the code according the UI settings.\nvar notOptions = [\n\t{\n\t\ttype : \"basic\",\n\t\ttitle: \"Basic Notification\",\n\t\tmessage: \"Short message part\",\n\t\texpandedMessage: \"Longer part of the message\",\n\t},\n\t{\n\t\ttype : \"image\",\n\t\ttitle: \"Image Notification\",\n\t\tmessage: \"Short message plus an image\",\n\t},\n\t{\n\t\ttype : \"list\",\n\t\ttitle: \"List Notification\",\n\t\tmessage: \"List of items in a message\",\n\t\titems: [\n\t\t\t{ title: \"Item1\", message: \"This is item 1\"},\n\t\t\t{ title: \"Item2\", message: \"This is item 2\"},\n\t\t\t{ title: \"Item3\", message: \"This is item 3\"},\n\t\t\t{ title: \"Item4\", message: \"This is item 4\"},\n\t\t\t{ title: \"Item5\", message: \"This is item 5\"},\n\t\t\t{ title: \"Item6\", message: \"This is item 6\"},\n\t\t]\n\t},\n\t{\n\t\ttype : \"progress\",\n\t\ttitle: \"Progress Notification\",\n\t\tmessage: \"Short message plus an image\",\n\t\tprogress: 60\n\t}\n\t\n];\n\n// Window initialization code. Set up the various event handlers\nwindow.addEventListener(\"load\", function() {\n\tdocument.getElementById(\"basic\").addEventListener(\"click\", doNotify);\n\tdocument.getElementById(\"image\").addEventListener(\"click\", doNotify);\n\tdocument.getElementById(\"list\").addEventListener(\"click\", doNotify);\n\tdocument.getElementById(\"progress\").addEventListener(\"click\", doNotify);\n\n\t// set up the event listeners\n\tchrome.notifications.onClosed.addListener(notificationClosed);\n\tchrome.notifications.onClicked.addListener(notificationClicked);\n\tchrome.notifications.onButtonClicked.addListener(notificationBtnClick);\n});\n\n// Create the notification with the given parameters as they are set in the UI\nfunction doNotify(evt) {\n\tvar path = chrome.runtime.getURL(asURLs[document.getElementById(\"img\").options.selectedIndex]);\n\tvar options = null;\n\tvar sBtn1 = document.getElementById(\"btn1\").value;\n\tvar sBtn2 = document.getElementById(\"btn2\").value;\n\t// Create the right notification for the selected type\n\tif (evt.srcElement.id == \"basic\") {\n\t\toptions = notOptions[0];\n\t}\n\telse if (evt.srcElement.id == \"image\") {\n\t\toptions = notOptions[1];\n\t\toptions.imageUrl = chrome.runtime.getURL(\"/images/tahoe-320x215.png\");\n\t}\n\telse if (evt.srcElement.id == \"list\") {\n\t\toptions = notOptions[2];\n\t}\n\telse if (evt.srcElement.id == \"progress\") {\n\t\toptions = notOptions[3];\n\t}\n\n\toptions.iconUrl = path;\n\t// priority is from -2 to 2. The API makes no guarantee about how notifications are\n\t// visually handled by the OS - they simply represent hints that the OS can use to \n\t// order or display them however it wishes.\n\toptions.priority = document.getElementById(\"pri\").options.selectedIndex - 2;\n\n\toptions.buttons = [];\n\tif (sBtn1.length)\n\t\toptions.buttons.push({ title: sBtn1 });\n\tif (sBtn2.length)\n\t\toptions.buttons.push({ title: sBtn2 });\n\t\t\n\tchrome.notifications.create(\"id\"+notID++, options, creationCallback);\n}\n\nfunction creationCallback(notID) {\n\tconsole.log(\"Succesfully created \" + notID + \" notification\");\n\tif (document.getElementById(\"clear\").checked) {\n\t\tsetTimeout(function() {\n\t\t\tchrome.notifications.clear(notID, function(wasCleared) {\n\t\t\t\tconsole.log(\"Notification \" + notID + \" cleared: \" + wasCleared);\n\t\t\t});\n\t\t}, 3000);\n\t}\n}\n\n// Event handlers for the various notification events\nfunction notificationClosed(notID, bByUser) {\n\tconsole.log(\"The notification '\" + notID + \"' was closed\" + (bByUser ? \" by the user\" : \"\"));\n}\n\nfunction notificationClicked(notID) {\n\tconsole.log(\"The notification '\" + notID + \"' was clicked\");\n}\n\nfunction notificationBtnClick(notID, iBtn) {\n\tconsole.log(\"The notification '\" + notID + \"' had button \" + iBtn + \" clicked\");\n}\n"
  },
  {
    "path": "_archive/apps/samples/rich-notifications/manifest.json",
    "content": "{\n  \"name\": \"Notification API Sample\",\n  \"description\": \"Tests the notification API\",\n  \"manifest_version\" : 2,\n  \"version\" : \"0.3.1\",\n  \"app\" : {\n    \"background\" : {\n    \"scripts\" : [\"app.js\"]\n    }\n  },\n  \"permissions\" : [\n     \"notifications\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/rich-notifications/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"rich-notifications\",\n  \"files_with_snippets\": [ ],\n  \"android\": {\"works\": true}\n}\n"
  },
  {
    "path": "_archive/apps/samples/rich-notifications/styles.css",
    "content": "#settings {\r\n  padding: 10px;\r\n  border: 1px solid silver;\r\n  margin-bottom: 5px;\r\n}\r\n\r\nh1, h3 {\r\n  margin-top: 0\r\n}\r\n\r\nbody {\r\n  font-family: \"Open Sans\", Helvetica, Arial;\r\n  font-size: 10pt;\r\n}\r\n\r\nbutton {\r\n  width: 140px;\r\n  margin-right: 20px;\r\n}\r\n\r\n.sample {\r\n  margin-bottom:5px;\r\n}\r\n"
  },
  {
    "path": "_archive/apps/samples/rich-notifications/window.html",
    "content": "<!DOCTYPE HTML>\n<!-- Copyright (c) 2013 The Chromium Authors. All rights reserved.\n  -- Use of this source code is governed by a BSD-style license that can be\n  -- found in the LICENSE file. -->\n<html>\n\t<head>\n\t\t<title>Rich Notifications Sample</title>\n\t\t<link rel=\"stylesheet\" href=\"styles.css\">\n\t</head>\n\t<body>\n\t\t<h1>Rich Notifications Sample</h1>\n\t\t<p>This sample demonstrates the use of the Rich Notifications API. Use the controls and buttons below to create various different rich notifications.</p>\n\t\t<div id=\"settings\">\n\t\t\t<h3>Settings</h3>\n\t\t\t<div>\n\t\t\t\t<label for=\"pri\">Priority: </label>\n\t\t\t\t<select id=\"pri\">\n\t\t\t\t\t<option>-2</option>\n\t\t\t\t\t<option>-1</option>\n\t\t\t\t\t<option selected>0</option>\n\t\t\t\t\t<option>1</option>\n\t\t\t\t\t<option>2</option>\n\t\t\t\t</select>\n\t\t\t\t<label for=\"img\">Image: </label>\n\t\t\t\t<select id=\"img\">\n\t\t\t\t\t<option>Mail</option>\n\t\t\t\t\t<option>Multiple Mail</option>\n\t\t\t\t\t<option>White</option>\n\t\t\t\t\t<option>Africa</option>\n\t\t\t\t\t<option>Antarctica</option>\n\t\t\t\t</select>\n\t\t\t\t<input id=\"clear\" type=\"checkbox\">\n\t\t\t\t<label for=\"clear\">Clear after 3 seconds</label>\n\t\t\t</div>\n\t\t\t<div>\n\t\t\t\t<label for=\"btn1\">Button 1: </label><input id=\"btn1\" type=\"text\">\n\t\t\t\t<label for=\"btn2\">Button 2: </label><input id=\"btn2\" type=\"text\">\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"sample\">\n\t\t\t<button id=\"basic\">Basic Notification</button>\n\t\t\t<span>Basic notification: icon, title, and message, up to two buttons</span>\n\t\t</div>\n\t\t<div class=\"sample\">\n\t\t\t<button id=\"image\">Image Notification</button>\n\t\t\t<span>Image notification: icon, title, image, and message, up to two buttons</span>\n\t\t</div>\n\t\t<div class=\"sample\">\n\t\t\t<button id=\"list\">List Notification</button>\n\t\t\t<span>List notification: icon, title, list of items, up to two buttons</span>\n\t\t</div>\n\t\t<div class=\"sample\">\n\t\t\t<button id=\"progress\">Progress Notification</button>\n\t\t\t<span>Progress notification: icon, title, message, progress</span>\n\t\t</div>\n\t\t<script src=\"main.js\"></script>\n\t</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/sandbox/LICENSE.handlebars",
    "content": "Copyright (C) 2011 by Yehuda Katz\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n"
  },
  {
    "path": "_archive/apps/samples/sandbox/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ipchbpppeafbpnmnjbkljpfhkkiaeikd\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Sandbox\n\nThis sample creates a sandboxed iframe (`sandbox.html`) to which the main page (`mainpage.html`)\npasses a counter variable. The sandboxed page uses the\n[Handlebars template library](http://handlebarsjs.com/) to evaluate and compose a message\nusing the counter variable which is then passed back to the main page for rendering.\n\nThe default packaged app Content Security Policy (CSP) value\n[disallows](https://developer.chrome.com/docs/apps/contentSecurityPolicy/) the use of\n`eval()` or `new Function()` (or variants like `Function.apply()`) so using a\nsandbox is necessary for this process. To enable sandboxing in your app you\nadd the `sandbox` property to your app's [manifest file](http://developer.chrome.com/apps/manifest#sandbox).\n\nSee more info on [using eval safely in packaged apps](http://developer.chrome.com/apps/sandboxingEval).\n\n## APIs\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/sandbox/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/sandbox/handlebars-1.0.0.beta.6.js",
    "content": "// Copyright (C) 2011 by Yehuda Katz\n// Licensing details in LICENSE.handlebars\n\n// lib/handlebars/base.js\nvar Handlebars = {};\n\nHandlebars.VERSION = \"1.0.beta.6\";\n\nHandlebars.helpers  = {};\nHandlebars.partials = {};\n\nHandlebars.registerHelper = function(name, fn, inverse) {\n  if(inverse) { fn.not = inverse; }\n  this.helpers[name] = fn;\n};\n\nHandlebars.registerPartial = function(name, str) {\n  this.partials[name] = str;\n};\n\nHandlebars.registerHelper('helperMissing', function(arg) {\n  if(arguments.length === 2) {\n    return undefined;\n  } else {\n    throw new Error(\"Could not find property '\" + arg + \"'\");\n  }\n});\n\nvar toString = Object.prototype.toString, functionType = \"[object Function]\";\n\nHandlebars.registerHelper('blockHelperMissing', function(context, options) {\n  var inverse = options.inverse || function() {}, fn = options.fn;\n\n\n  var ret = \"\";\n  var type = toString.call(context);\n\n  if(type === functionType) { context = context.call(this); }\n\n  if(context === true) {\n    return fn(this);\n  } else if(context === false || context == null) {\n    return inverse(this);\n  } else if(type === \"[object Array]\") {\n    if(context.length > 0) {\n      for(var i=0, j=context.length; i<j; i++) {\n        ret = ret + fn(context[i]);\n      }\n    } else {\n      ret = inverse(this);\n    }\n    return ret;\n  } else {\n    return fn(context);\n  }\n});\n\nHandlebars.registerHelper('each', function(context, options) {\n  var fn = options.fn, inverse = options.inverse;\n  var ret = \"\";\n\n  if(context && context.length > 0) {\n    for(var i=0, j=context.length; i<j; i++) {\n      ret = ret + fn(context[i]);\n    }\n  } else {\n    ret = inverse(this);\n  }\n  return ret;\n});\n\nHandlebars.registerHelper('if', function(context, options) {\n  var type = toString.call(context);\n  if(type === functionType) { context = context.call(this); }\n\n  if(!context || Handlebars.Utils.isEmpty(context)) {\n    return options.inverse(this);\n  } else {\n    return options.fn(this);\n  }\n});\n\nHandlebars.registerHelper('unless', function(context, options) {\n  var fn = options.fn, inverse = options.inverse;\n  options.fn = inverse;\n  options.inverse = fn;\n\n  return Handlebars.helpers['if'].call(this, context, options);\n});\n\nHandlebars.registerHelper('with', function(context, options) {\n  return options.fn(context);\n});\n\nHandlebars.registerHelper('log', function(context) {\n  Handlebars.log(context);\n});\n;\n// lib/handlebars/compiler/parser.js\n/* Jison generated parser */\nvar handlebars = (function(){\n\nvar parser = {trace: function trace() { },\nyy: {},\nsymbols_: {\"error\":2,\"root\":3,\"program\":4,\"EOF\":5,\"statements\":6,\"simpleInverse\":7,\"statement\":8,\"openInverse\":9,\"closeBlock\":10,\"openBlock\":11,\"mustache\":12,\"partial\":13,\"CONTENT\":14,\"COMMENT\":15,\"OPEN_BLOCK\":16,\"inMustache\":17,\"CLOSE\":18,\"OPEN_INVERSE\":19,\"OPEN_ENDBLOCK\":20,\"path\":21,\"OPEN\":22,\"OPEN_UNESCAPED\":23,\"OPEN_PARTIAL\":24,\"params\":25,\"hash\":26,\"param\":27,\"STRING\":28,\"INTEGER\":29,\"BOOLEAN\":30,\"hashSegments\":31,\"hashSegment\":32,\"ID\":33,\"EQUALS\":34,\"pathSegments\":35,\"SEP\":36,\"$accept\":0,\"$end\":1},\nterminals_: {2:\"error\",5:\"EOF\",14:\"CONTENT\",15:\"COMMENT\",16:\"OPEN_BLOCK\",18:\"CLOSE\",19:\"OPEN_INVERSE\",20:\"OPEN_ENDBLOCK\",22:\"OPEN\",23:\"OPEN_UNESCAPED\",24:\"OPEN_PARTIAL\",28:\"STRING\",29:\"INTEGER\",30:\"BOOLEAN\",33:\"ID\",34:\"EQUALS\",36:\"SEP\"},\nproductions_: [0,[3,2],[4,3],[4,1],[4,0],[6,1],[6,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,3],[13,4],[7,2],[17,3],[17,2],[17,2],[17,1],[25,2],[25,1],[27,1],[27,1],[27,1],[27,1],[26,1],[31,2],[31,1],[32,3],[32,3],[32,3],[32,3],[21,1],[35,3],[35,1]],\nperformAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {\n\nvar $0 = $$.length - 1;\nswitch (yystate) {\ncase 1: return $$[$0-1] \nbreak;\ncase 2: this.$ = new yy.ProgramNode($$[$0-2], $$[$0]) \nbreak;\ncase 3: this.$ = new yy.ProgramNode($$[$0]) \nbreak;\ncase 4: this.$ = new yy.ProgramNode([]) \nbreak;\ncase 5: this.$ = [$$[$0]] \nbreak;\ncase 6: $$[$0-1].push($$[$0]); this.$ = $$[$0-1] \nbreak;\ncase 7: this.$ = new yy.InverseNode($$[$0-2], $$[$0-1], $$[$0]) \nbreak;\ncase 8: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0]) \nbreak;\ncase 9: this.$ = $$[$0] \nbreak;\ncase 10: this.$ = $$[$0] \nbreak;\ncase 11: this.$ = new yy.ContentNode($$[$0]) \nbreak;\ncase 12: this.$ = new yy.CommentNode($$[$0]) \nbreak;\ncase 13: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) \nbreak;\ncase 14: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) \nbreak;\ncase 15: this.$ = $$[$0-1] \nbreak;\ncase 16: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) \nbreak;\ncase 17: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], true) \nbreak;\ncase 18: this.$ = new yy.PartialNode($$[$0-1]) \nbreak;\ncase 19: this.$ = new yy.PartialNode($$[$0-2], $$[$0-1]) \nbreak;\ncase 20: \nbreak;\ncase 21: this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]] \nbreak;\ncase 22: this.$ = [[$$[$0-1]].concat($$[$0]), null] \nbreak;\ncase 23: this.$ = [[$$[$0-1]], $$[$0]] \nbreak;\ncase 24: this.$ = [[$$[$0]], null] \nbreak;\ncase 25: $$[$0-1].push($$[$0]); this.$ = $$[$0-1]; \nbreak;\ncase 26: this.$ = [$$[$0]] \nbreak;\ncase 27: this.$ = $$[$0] \nbreak;\ncase 28: this.$ = new yy.StringNode($$[$0]) \nbreak;\ncase 29: this.$ = new yy.IntegerNode($$[$0]) \nbreak;\ncase 30: this.$ = new yy.BooleanNode($$[$0]) \nbreak;\ncase 31: this.$ = new yy.HashNode($$[$0]) \nbreak;\ncase 32: $$[$0-1].push($$[$0]); this.$ = $$[$0-1] \nbreak;\ncase 33: this.$ = [$$[$0]] \nbreak;\ncase 34: this.$ = [$$[$0-2], $$[$0]] \nbreak;\ncase 35: this.$ = [$$[$0-2], new yy.StringNode($$[$0])] \nbreak;\ncase 36: this.$ = [$$[$0-2], new yy.IntegerNode($$[$0])] \nbreak;\ncase 37: this.$ = [$$[$0-2], new yy.BooleanNode($$[$0])] \nbreak;\ncase 38: this.$ = new yy.IdNode($$[$0]) \nbreak;\ncase 39: $$[$0-2].push($$[$0]); this.$ = $$[$0-2]; \nbreak;\ncase 40: this.$ = [$$[$0]] \nbreak;\n}\n},\ntable: [{3:1,4:2,5:[2,4],6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{1:[3]},{5:[1,16]},{5:[2,3],7:17,8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,19],20:[2,3],22:[1,13],23:[1,14],24:[1,15]},{5:[2,5],14:[2,5],15:[2,5],16:[2,5],19:[2,5],20:[2,5],22:[2,5],23:[2,5],24:[2,5]},{4:20,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{4:21,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],24:[2,9]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],24:[2,10]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],24:[2,11]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],24:[2,12]},{17:22,21:23,33:[1,25],35:24},{17:26,21:23,33:[1,25],35:24},{17:27,21:23,33:[1,25],35:24},{17:28,21:23,33:[1,25],35:24},{21:29,33:[1,25],35:24},{1:[2,1]},{6:30,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{5:[2,6],14:[2,6],15:[2,6],16:[2,6],19:[2,6],20:[2,6],22:[2,6],23:[2,6],24:[2,6]},{17:22,18:[1,31],21:23,33:[1,25],35:24},{10:32,20:[1,33]},{10:34,20:[1,33]},{18:[1,35]},{18:[2,24],21:40,25:36,26:37,27:38,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,38],28:[2,38],29:[2,38],30:[2,38],33:[2,38],36:[1,46]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],36:[2,40]},{18:[1,47]},{18:[1,48]},{18:[1,49]},{18:[1,50],21:51,33:[1,25],35:24},{5:[2,2],8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,2],22:[1,13],23:[1,14],24:[1,15]},{14:[2,20],15:[2,20],16:[2,20],19:[2,20],22:[2,20],23:[2,20],24:[2,20]},{5:[2,7],14:[2,7],15:[2,7],16:[2,7],19:[2,7],20:[2,7],22:[2,7],23:[2,7],24:[2,7]},{21:52,33:[1,25],35:24},{5:[2,8],14:[2,8],15:[2,8],16:[2,8],19:[2,8],20:[2,8],22:[2,8],23:[2,8],24:[2,8]},{14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],24:[2,14]},{18:[2,22],21:40,26:53,27:54,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,23]},{18:[2,26],28:[2,26],29:[2,26],30:[2,26],33:[2,26]},{18:[2,31],32:55,33:[1,56]},{18:[2,27],28:[2,27],29:[2,27],30:[2,27],33:[2,27]},{18:[2,28],28:[2,28],29:[2,28],30:[2,28],33:[2,28]},{18:[2,29],28:[2,29],29:[2,29],30:[2,29],33:[2,29]},{18:[2,30],28:[2,30],29:[2,30],30:[2,30],33:[2,30]},{18:[2,33],33:[2,33]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],34:[1,57],36:[2,40]},{33:[1,58]},{14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],24:[2,13]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],24:[2,16]},{5:[2,17],14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],24:[2,17]},{5:[2,18],14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],24:[2,18]},{18:[1,59]},{18:[1,60]},{18:[2,21]},{18:[2,25],28:[2,25],29:[2,25],30:[2,25],33:[2,25]},{18:[2,32],33:[2,32]},{34:[1,57]},{21:61,28:[1,62],29:[1,63],30:[1,64],33:[1,25],35:24},{18:[2,39],28:[2,39],29:[2,39],30:[2,39],33:[2,39],36:[2,39]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],24:[2,19]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],24:[2,15]},{18:[2,34],33:[2,34]},{18:[2,35],33:[2,35]},{18:[2,36],33:[2,36]},{18:[2,37],33:[2,37]}],\ndefaultActions: {16:[2,1],37:[2,23],53:[2,21]},\nparseError: function parseError(str, hash) {\n    throw new Error(str);\n},\nparse: function parse(input) {\n    var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = \"\", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;\n    this.lexer.setInput(input);\n    this.lexer.yy = this.yy;\n    this.yy.lexer = this.lexer;\n    if (typeof this.lexer.yylloc == \"undefined\")\n        this.lexer.yylloc = {};\n    var yyloc = this.lexer.yylloc;\n    lstack.push(yyloc);\n    if (typeof this.yy.parseError === \"function\")\n        this.parseError = this.yy.parseError;\n    function popStack(n) {\n        stack.length = stack.length - 2 * n;\n        vstack.length = vstack.length - n;\n        lstack.length = lstack.length - n;\n    }\n    function lex() {\n        var token;\n        token = self.lexer.lex() || 1;\n        if (typeof token !== \"number\") {\n            token = self.symbols_[token] || token;\n        }\n        return token;\n    }\n    var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;\n    while (true) {\n        state = stack[stack.length - 1];\n        if (this.defaultActions[state]) {\n            action = this.defaultActions[state];\n        } else {\n            if (symbol == null)\n                symbol = lex();\n            action = table[state] && table[state][symbol];\n        }\n        if (typeof action === \"undefined\" || !action.length || !action[0]) {\n            if (!recovering) {\n                expected = [];\n                for (p in table[state])\n                    if (this.terminals_[p] && p > 2) {\n                        expected.push(\"'\" + this.terminals_[p] + \"'\");\n                    }\n                var errStr = \"\";\n                if (this.lexer.showPosition) {\n                    errStr = \"Parse error on line \" + (yylineno + 1) + \":\\n\" + this.lexer.showPosition() + \"\\nExpecting \" + expected.join(\", \") + \", got '\" + this.terminals_[symbol] + \"'\";\n                } else {\n                    errStr = \"Parse error on line \" + (yylineno + 1) + \": Unexpected \" + (symbol == 1?\"end of input\":\"'\" + (this.terminals_[symbol] || symbol) + \"'\");\n                }\n                this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});\n            }\n        }\n        if (action[0] instanceof Array && action.length > 1) {\n            throw new Error(\"Parse Error: multiple actions possible at state: \" + state + \", token: \" + symbol);\n        }\n        switch (action[0]) {\n        case 1:\n            stack.push(symbol);\n            vstack.push(this.lexer.yytext);\n            lstack.push(this.lexer.yylloc);\n            stack.push(action[1]);\n            symbol = null;\n            if (!preErrorSymbol) {\n                yyleng = this.lexer.yyleng;\n                yytext = this.lexer.yytext;\n                yylineno = this.lexer.yylineno;\n                yyloc = this.lexer.yylloc;\n                if (recovering > 0)\n                    recovering--;\n            } else {\n                symbol = preErrorSymbol;\n                preErrorSymbol = null;\n            }\n            break;\n        case 2:\n            len = this.productions_[action[1]][1];\n            yyval.$ = vstack[vstack.length - len];\n            yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column};\n            r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);\n            if (typeof r !== \"undefined\") {\n                return r;\n            }\n            if (len) {\n                stack = stack.slice(0, -1 * len * 2);\n                vstack = vstack.slice(0, -1 * len);\n                lstack = lstack.slice(0, -1 * len);\n            }\n            stack.push(this.productions_[action[1]][0]);\n            vstack.push(yyval.$);\n            lstack.push(yyval._$);\n            newState = table[stack[stack.length - 2]][stack[stack.length - 1]];\n            stack.push(newState);\n            break;\n        case 3:\n            return true;\n        }\n    }\n    return true;\n}\n};/* Jison generated lexer */\nvar lexer = (function(){\n\nvar lexer = ({EOF:1,\nparseError:function parseError(str, hash) {\n        if (this.yy.parseError) {\n            this.yy.parseError(str, hash);\n        } else {\n            throw new Error(str);\n        }\n    },\nsetInput:function (input) {\n        this._input = input;\n        this._more = this._less = this.done = false;\n        this.yylineno = this.yyleng = 0;\n        this.yytext = this.matched = this.match = '';\n        this.conditionStack = ['INITIAL'];\n        this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};\n        return this;\n    },\ninput:function () {\n        var ch = this._input[0];\n        this.yytext+=ch;\n        this.yyleng++;\n        this.match+=ch;\n        this.matched+=ch;\n        var lines = ch.match(/\\n/);\n        if (lines) this.yylineno++;\n        this._input = this._input.slice(1);\n        return ch;\n    },\nunput:function (ch) {\n        this._input = ch + this._input;\n        return this;\n    },\nmore:function () {\n        this._more = true;\n        return this;\n    },\npastInput:function () {\n        var past = this.matched.substr(0, this.matched.length - this.match.length);\n        return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\\n/g, \"\");\n    },\nupcomingInput:function () {\n        var next = this.match;\n        if (next.length < 20) {\n            next += this._input.substr(0, 20-next.length);\n        }\n        return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\\n/g, \"\");\n    },\nshowPosition:function () {\n        var pre = this.pastInput();\n        var c = new Array(pre.length + 1).join(\"-\");\n        return pre + this.upcomingInput() + \"\\n\" + c+\"^\";\n    },\nnext:function () {\n        if (this.done) {\n            return this.EOF;\n        }\n        if (!this._input) this.done = true;\n\n        var token,\n            match,\n            col,\n            lines;\n        if (!this._more) {\n            this.yytext = '';\n            this.match = '';\n        }\n        var rules = this._currentRules();\n        for (var i=0;i < rules.length; i++) {\n            match = this._input.match(this.rules[rules[i]]);\n            if (match) {\n                lines = match[0].match(/\\n.*/g);\n                if (lines) this.yylineno += lines.length;\n                this.yylloc = {first_line: this.yylloc.last_line,\n                               last_line: this.yylineno+1,\n                               first_column: this.yylloc.last_column,\n                               last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}\n                this.yytext += match[0];\n                this.match += match[0];\n                this.matches = match;\n                this.yyleng = this.yytext.length;\n                this._more = false;\n                this._input = this._input.slice(match[0].length);\n                this.matched += match[0];\n                token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]);\n                if (token) return token;\n                else return;\n            }\n        }\n        if (this._input === \"\") {\n            return this.EOF;\n        } else {\n            this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\\n'+this.showPosition(), \n                    {text: \"\", token: null, line: this.yylineno});\n        }\n    },\nlex:function lex() {\n        var r = this.next();\n        if (typeof r !== 'undefined') {\n            return r;\n        } else {\n            return this.lex();\n        }\n    },\nbegin:function begin(condition) {\n        this.conditionStack.push(condition);\n    },\npopState:function popState() {\n        return this.conditionStack.pop();\n    },\n_currentRules:function _currentRules() {\n        return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;\n    },\ntopState:function () {\n        return this.conditionStack[this.conditionStack.length-2];\n    },\npushState:function begin(condition) {\n        this.begin(condition);\n    }});\nlexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {\n\nvar YYSTATE=YY_START\nswitch($avoiding_name_collisions) {\ncase 0:\n                                   if(yy_.yytext.slice(-1) !== \"\\\\\") this.begin(\"mu\");\n                                   if(yy_.yytext.slice(-1) === \"\\\\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1), this.begin(\"emu\");\n                                   if(yy_.yytext) return 14;\n                                 \nbreak;\ncase 1: return 14; \nbreak;\ncase 2: this.popState(); return 14; \nbreak;\ncase 3: return 24; \nbreak;\ncase 4: return 16; \nbreak;\ncase 5: return 20; \nbreak;\ncase 6: return 19; \nbreak;\ncase 7: return 19; \nbreak;\ncase 8: return 23; \nbreak;\ncase 9: return 23; \nbreak;\ncase 10: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15; \nbreak;\ncase 11: return 22; \nbreak;\ncase 12: return 34; \nbreak;\ncase 13: return 33; \nbreak;\ncase 14: return 33; \nbreak;\ncase 15: return 36; \nbreak;\ncase 16: /*ignore whitespace*/ \nbreak;\ncase 17: this.popState(); return 18; \nbreak;\ncase 18: this.popState(); return 18; \nbreak;\ncase 19: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\\\\"/g,'\"'); return 28; \nbreak;\ncase 20: return 30; \nbreak;\ncase 21: return 30; \nbreak;\ncase 22: return 29; \nbreak;\ncase 23: return 33; \nbreak;\ncase 24: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 33; \nbreak;\ncase 25: return 'INVALID'; \nbreak;\ncase 26: return 5; \nbreak;\n}\n};\nlexer.rules = [/^[^\\x00]*?(?=(\\{\\{))/,/^[^\\x00]+/,/^[^\\x00]{2,}?(?=(\\{\\{))/,/^\\{\\{>/,/^\\{\\{#/,/^\\{\\{\\//,/^\\{\\{\\^/,/^\\{\\{\\s*else\\b/,/^\\{\\{\\{/,/^\\{\\{&/,/^\\{\\{![\\s\\S]*?\\}\\}/,/^\\{\\{/,/^=/,/^\\.(?=[} ])/,/^\\.\\./,/^[\\/.]/,/^\\s+/,/^\\}\\}\\}/,/^\\}\\}/,/^\"(\\\\[\"]|[^\"])*\"/,/^true(?=[}\\s])/,/^false(?=[}\\s])/,/^[0-9]+(?=[}\\s])/,/^[a-zA-Z0-9_$-]+(?=[=}\\s\\/.])/,/^\\[[^\\]]*\\]/,/^./,/^$/];\nlexer.conditions = {\"mu\":{\"rules\":[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],\"inclusive\":false},\"emu\":{\"rules\":[2],\"inclusive\":false},\"INITIAL\":{\"rules\":[0,1,26],\"inclusive\":true}};return lexer;})()\nparser.lexer = lexer;\nreturn parser;\n})();\nif (typeof require !== 'undefined' && typeof exports !== 'undefined') {\nexports.parser = handlebars;\nexports.parse = function () { return handlebars.parse.apply(handlebars, arguments); }\nexports.main = function commonjsMain(args) {\n    if (!args[1])\n        throw new Error('Usage: '+args[0]+' FILE');\n    if (typeof process !== 'undefined') {\n        var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), \"utf8\");\n    } else {\n        var cwd = require(\"file\").path(require(\"file\").cwd());\n        var source = cwd.join(args[1]).read({charset: \"utf-8\"});\n    }\n    return exports.parser.parse(source);\n}\nif (typeof module !== 'undefined' && require.main === module) {\n  exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require(\"system\").args);\n}\n};\n;\n// lib/handlebars/compiler/base.js\nHandlebars.Parser = handlebars;\n\nHandlebars.parse = function(string) {\n  Handlebars.Parser.yy = Handlebars.AST;\n  return Handlebars.Parser.parse(string);\n};\n\nHandlebars.print = function(ast) {\n  return new Handlebars.PrintVisitor().accept(ast);\n};\n\nHandlebars.logger = {\n  DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3,\n\n  // override in the host environment\n  log: function(level, str) {}\n};\n\nHandlebars.log = function(level, str) { Handlebars.logger.log(level, str); };\n;\n// lib/handlebars/compiler/ast.js\n(function() {\n\n  Handlebars.AST = {};\n\n  Handlebars.AST.ProgramNode = function(statements, inverse) {\n    this.type = \"program\";\n    this.statements = statements;\n    if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); }\n  };\n\n  Handlebars.AST.MustacheNode = function(params, hash, unescaped) {\n    this.type = \"mustache\";\n    this.id = params[0];\n    this.params = params.slice(1);\n    this.hash = hash;\n    this.escaped = !unescaped;\n  };\n\n  Handlebars.AST.PartialNode = function(id, context) {\n    this.type    = \"partial\";\n\n    // TODO: disallow complex IDs\n\n    this.id      = id;\n    this.context = context;\n  };\n\n  var verifyMatch = function(open, close) {\n    if(open.original !== close.original) {\n      throw new Handlebars.Exception(open.original + \" doesn't match \" + close.original);\n    }\n  };\n\n  Handlebars.AST.BlockNode = function(mustache, program, close) {\n    verifyMatch(mustache.id, close);\n    this.type = \"block\";\n    this.mustache = mustache;\n    this.program  = program;\n  };\n\n  Handlebars.AST.InverseNode = function(mustache, program, close) {\n    verifyMatch(mustache.id, close);\n    this.type = \"inverse\";\n    this.mustache = mustache;\n    this.program  = program;\n  };\n\n  Handlebars.AST.ContentNode = function(string) {\n    this.type = \"content\";\n    this.string = string;\n  };\n\n  Handlebars.AST.HashNode = function(pairs) {\n    this.type = \"hash\";\n    this.pairs = pairs;\n  };\n\n  Handlebars.AST.IdNode = function(parts) {\n    this.type = \"ID\";\n    this.original = parts.join(\".\");\n\n    var dig = [], depth = 0;\n\n    for(var i=0,l=parts.length; i<l; i++) {\n      var part = parts[i];\n\n      if(part === \"..\") { depth++; }\n      else if(part === \".\" || part === \"this\") { this.isScoped = true; }\n      else { dig.push(part); }\n    }\n\n    this.parts    = dig;\n    this.string   = dig.join('.');\n    this.depth    = depth;\n    this.isSimple = (dig.length === 1) && (depth === 0);\n  };\n\n  Handlebars.AST.StringNode = function(string) {\n    this.type = \"STRING\";\n    this.string = string;\n  };\n\n  Handlebars.AST.IntegerNode = function(integer) {\n    this.type = \"INTEGER\";\n    this.integer = integer;\n  };\n\n  Handlebars.AST.BooleanNode = function(bool) {\n    this.type = \"BOOLEAN\";\n    this.bool = bool;\n  };\n\n  Handlebars.AST.CommentNode = function(comment) {\n    this.type = \"comment\";\n    this.comment = comment;\n  };\n\n})();;\n// lib/handlebars/utils.js\nHandlebars.Exception = function(message) {\n  var tmp = Error.prototype.constructor.apply(this, arguments);\n\n  for (var p in tmp) {\n    if (tmp.hasOwnProperty(p)) { this[p] = tmp[p]; }\n  }\n\n  this.message = tmp.message;\n};\nHandlebars.Exception.prototype = new Error;\n\n// Build out our basic SafeString type\nHandlebars.SafeString = function(string) {\n  this.string = string;\n};\nHandlebars.SafeString.prototype.toString = function() {\n  return this.string.toString();\n};\n\n(function() {\n  var escape = {\n    \"<\": \"&lt;\",\n    \">\": \"&gt;\",\n    '\"': \"&quot;\",\n    \"'\": \"&#x27;\",\n    \"`\": \"&#x60;\"\n  };\n\n  var badChars = /&(?!\\w+;)|[<>\"'`]/g;\n  var possible = /[&<>\"'`]/;\n\n  var escapeChar = function(chr) {\n    return escape[chr] || \"&amp;\";\n  };\n\n  Handlebars.Utils = {\n    escapeExpression: function(string) {\n      // don't escape SafeStrings, since they're already safe\n      if (string instanceof Handlebars.SafeString) {\n        return string.toString();\n      } else if (string == null || string === false) {\n        return \"\";\n      }\n\n      if(!possible.test(string)) { return string; }\n      return string.replace(badChars, escapeChar);\n    },\n\n    isEmpty: function(value) {\n      if (typeof value === \"undefined\") {\n        return true;\n      } else if (value === null) {\n        return true;\n      } else if (value === false) {\n        return true;\n      } else if(Object.prototype.toString.call(value) === \"[object Array]\" && value.length === 0) {\n        return true;\n      } else {\n        return false;\n      }\n    }\n  };\n})();;\n// lib/handlebars/compiler/compiler.js\nHandlebars.Compiler = function() {};\nHandlebars.JavaScriptCompiler = function() {};\n\n(function(Compiler, JavaScriptCompiler) {\n  Compiler.OPCODE_MAP = {\n    appendContent: 1,\n    getContext: 2,\n    lookupWithHelpers: 3,\n    lookup: 4,\n    append: 5,\n    invokeMustache: 6,\n    appendEscaped: 7,\n    pushString: 8,\n    truthyOrFallback: 9,\n    functionOrFallback: 10,\n    invokeProgram: 11,\n    invokePartial: 12,\n    push: 13,\n    assignToHash: 15,\n    pushStringParam: 16\n  };\n\n  Compiler.MULTI_PARAM_OPCODES = {\n    appendContent: 1,\n    getContext: 1,\n    lookupWithHelpers: 2,\n    lookup: 1,\n    invokeMustache: 3,\n    pushString: 1,\n    truthyOrFallback: 1,\n    functionOrFallback: 1,\n    invokeProgram: 3,\n    invokePartial: 1,\n    push: 1,\n    assignToHash: 1,\n    pushStringParam: 1\n  };\n\n  Compiler.DISASSEMBLE_MAP = {};\n\n  for(var prop in Compiler.OPCODE_MAP) {\n    var value = Compiler.OPCODE_MAP[prop];\n    Compiler.DISASSEMBLE_MAP[value] = prop;\n  }\n\n  Compiler.multiParamSize = function(code) {\n    return Compiler.MULTI_PARAM_OPCODES[Compiler.DISASSEMBLE_MAP[code]];\n  };\n\n  Compiler.prototype = {\n    compiler: Compiler,\n\n    disassemble: function() {\n      var opcodes = this.opcodes, opcode, nextCode;\n      var out = [], str, name, value;\n\n      for(var i=0, l=opcodes.length; i<l; i++) {\n        opcode = opcodes[i];\n\n        if(opcode === 'DECLARE') {\n          name = opcodes[++i];\n          value = opcodes[++i];\n          out.push(\"DECLARE \" + name + \" = \" + value);\n        } else {\n          str = Compiler.DISASSEMBLE_MAP[opcode];\n\n          var extraParams = Compiler.multiParamSize(opcode);\n          var codes = [];\n\n          for(var j=0; j<extraParams; j++) {\n            nextCode = opcodes[++i];\n\n            if(typeof nextCode === \"string\") {\n              nextCode = \"\\\"\" + nextCode.replace(\"\\n\", \"\\\\n\") + \"\\\"\";\n            }\n\n            codes.push(nextCode);\n          }\n\n          str = str + \" \" + codes.join(\" \");\n\n          out.push(str);\n        }\n      }\n\n      return out.join(\"\\n\");\n    },\n\n    guid: 0,\n\n    compile: function(program, options) {\n      this.children = [];\n      this.depths = {list: []};\n      this.options = options;\n\n      // These changes will propagate to the other compiler components\n      var knownHelpers = this.options.knownHelpers;\n      this.options.knownHelpers = {\n        'helperMissing': true,\n        'blockHelperMissing': true,\n        'each': true,\n        'if': true,\n        'unless': true,\n        'with': true,\n        'log': true\n      };\n      if (knownHelpers) {\n        for (var name in knownHelpers) {\n          this.options.knownHelpers[name] = knownHelpers[name];\n        }\n      }\n\n      return this.program(program);\n    },\n\n    accept: function(node) {\n      return this[node.type](node);\n    },\n\n    program: function(program) {\n      var statements = program.statements, statement;\n      this.opcodes = [];\n\n      for(var i=0, l=statements.length; i<l; i++) {\n        statement = statements[i];\n        this[statement.type](statement);\n      }\n      this.isSimple = l === 1;\n\n      this.depths.list = this.depths.list.sort(function(a, b) {\n        return a - b;\n      });\n\n      return this;\n    },\n\n    compileProgram: function(program) {\n      var result = new this.compiler().compile(program, this.options);\n      var guid = this.guid++;\n\n      this.usePartial = this.usePartial || result.usePartial;\n\n      this.children[guid] = result;\n\n      for(var i=0, l=result.depths.list.length; i<l; i++) {\n        depth = result.depths.list[i];\n\n        if(depth < 2) { continue; }\n        else { this.addDepth(depth - 1); }\n      }\n\n      return guid;\n    },\n\n    block: function(block) {\n      var mustache = block.mustache;\n      var depth, child, inverse, inverseGuid;\n\n      var params = this.setupStackForMustache(mustache);\n\n      var programGuid = this.compileProgram(block.program);\n\n      if(block.program.inverse) {\n        inverseGuid = this.compileProgram(block.program.inverse);\n        this.declare('inverse', inverseGuid);\n      }\n\n      this.opcode('invokeProgram', programGuid, params.length, !!mustache.hash);\n      this.declare('inverse', null);\n      this.opcode('append');\n    },\n\n    inverse: function(block) {\n      var params = this.setupStackForMustache(block.mustache);\n\n      var programGuid = this.compileProgram(block.program);\n\n      this.declare('inverse', programGuid);\n\n      this.opcode('invokeProgram', null, params.length, !!block.mustache.hash);\n      this.declare('inverse', null);\n      this.opcode('append');\n    },\n\n    hash: function(hash) {\n      var pairs = hash.pairs, pair, val;\n\n      this.opcode('push', '{}');\n\n      for(var i=0, l=pairs.length; i<l; i++) {\n        pair = pairs[i];\n        val  = pair[1];\n\n        this.accept(val);\n        this.opcode('assignToHash', pair[0]);\n      }\n    },\n\n    partial: function(partial) {\n      var id = partial.id;\n      this.usePartial = true;\n\n      if(partial.context) {\n        this.ID(partial.context);\n      } else {\n        this.opcode('push', 'depth0');\n      }\n\n      this.opcode('invokePartial', id.original);\n      this.opcode('append');\n    },\n\n    content: function(content) {\n      this.opcode('appendContent', content.string);\n    },\n\n    mustache: function(mustache) {\n      var params = this.setupStackForMustache(mustache);\n\n      this.opcode('invokeMustache', params.length, mustache.id.original, !!mustache.hash);\n\n      if(mustache.escaped && !this.options.noEscape) {\n        this.opcode('appendEscaped');\n      } else {\n        this.opcode('append');\n      }\n    },\n\n    ID: function(id) {\n      this.addDepth(id.depth);\n\n      this.opcode('getContext', id.depth);\n\n      this.opcode('lookupWithHelpers', id.parts[0] || null, id.isScoped || false);\n\n      for(var i=1, l=id.parts.length; i<l; i++) {\n        this.opcode('lookup', id.parts[i]);\n      }\n    },\n\n    STRING: function(string) {\n      this.opcode('pushString', string.string);\n    },\n\n    INTEGER: function(integer) {\n      this.opcode('push', integer.integer);\n    },\n\n    BOOLEAN: function(bool) {\n      this.opcode('push', bool.bool);\n    },\n\n    comment: function() {},\n\n    // HELPERS\n    pushParams: function(params) {\n      var i = params.length, param;\n\n      while(i--) {\n        param = params[i];\n\n        if(this.options.stringParams) {\n          if(param.depth) {\n            this.addDepth(param.depth);\n          }\n\n          this.opcode('getContext', param.depth || 0);\n          this.opcode('pushStringParam', param.string);\n        } else {\n          this[param.type](param);\n        }\n      }\n    },\n\n    opcode: function(name, val1, val2, val3) {\n      this.opcodes.push(Compiler.OPCODE_MAP[name]);\n      if(val1 !== undefined) { this.opcodes.push(val1); }\n      if(val2 !== undefined) { this.opcodes.push(val2); }\n      if(val3 !== undefined) { this.opcodes.push(val3); }\n    },\n\n    declare: function(name, value) {\n      this.opcodes.push('DECLARE');\n      this.opcodes.push(name);\n      this.opcodes.push(value);\n    },\n\n    addDepth: function(depth) {\n      if(depth === 0) { return; }\n\n      if(!this.depths[depth]) {\n        this.depths[depth] = true;\n        this.depths.list.push(depth);\n      }\n    },\n\n    setupStackForMustache: function(mustache) {\n      var params = mustache.params;\n\n      this.pushParams(params);\n\n      if(mustache.hash) {\n        this.hash(mustache.hash);\n      }\n\n      this.ID(mustache.id);\n\n      return params;\n    }\n  };\n\n  JavaScriptCompiler.prototype = {\n    // PUBLIC API: You can override these methods in a subclass to provide\n    // alternative compiled forms for name lookup and buffering semantics\n    nameLookup: function(parent, name, type) {\n      if (/^[0-9]+$/.test(name)) {\n        return parent + \"[\" + name + \"]\";\n      } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {\n        return parent + \".\" + name;\n      }\n      else {\n        return parent + \"['\" + name + \"']\";\n      }\n    },\n\n    appendToBuffer: function(string) {\n      if (this.environment.isSimple) {\n        return \"return \" + string + \";\";\n      } else {\n        return \"buffer += \" + string + \";\";\n      }\n    },\n\n    initializeBuffer: function() {\n      return this.quotedString(\"\");\n    },\n\n    namespace: \"Handlebars\",\n    // END PUBLIC API\n\n    compile: function(environment, options, context, asObject) {\n      this.environment = environment;\n      this.options = options || {};\n\n      this.name = this.environment.name;\n      this.isChild = !!context;\n      this.context = context || {\n        programs: [],\n        aliases: { self: 'this' },\n        registers: {list: []}\n      };\n\n      this.preamble();\n\n      this.stackSlot = 0;\n      this.stackVars = [];\n\n      this.compileChildren(environment, options);\n\n      var opcodes = environment.opcodes, opcode;\n\n      this.i = 0;\n\n      for(l=opcodes.length; this.i<l; this.i++) {\n        opcode = this.nextOpcode(0);\n\n        if(opcode[0] === 'DECLARE') {\n          this.i = this.i + 2;\n          this[opcode[1]] = opcode[2];\n        } else {\n          this.i = this.i + opcode[1].length;\n          this[opcode[0]].apply(this, opcode[1]);\n        }\n      }\n\n      return this.createFunctionContext(asObject);\n    },\n\n    nextOpcode: function(n) {\n      var opcodes = this.environment.opcodes, opcode = opcodes[this.i + n], name, val;\n      var extraParams, codes;\n\n      if(opcode === 'DECLARE') {\n        name = opcodes[this.i + 1];\n        val  = opcodes[this.i + 2];\n        return ['DECLARE', name, val];\n      } else {\n        name = Compiler.DISASSEMBLE_MAP[opcode];\n\n        extraParams = Compiler.multiParamSize(opcode);\n        codes = [];\n\n        for(var j=0; j<extraParams; j++) {\n          codes.push(opcodes[this.i + j + 1 + n]);\n        }\n\n        return [name, codes];\n      }\n    },\n\n    eat: function(opcode) {\n      this.i = this.i + opcode.length;\n    },\n\n    preamble: function() {\n      var out = [];\n\n      // this register will disambiguate helper lookup from finding a function in\n      // a context. This is necessary for mustache compatibility, which requires\n      // that context functions in blocks are evaluated by blockHelperMissing, and\n      // then proceed as if the resulting value was provided to blockHelperMissing.\n      this.useRegister('foundHelper');\n\n      if (!this.isChild) {\n        var namespace = this.namespace;\n        var copies = \"helpers = helpers || \" + namespace + \".helpers;\";\n        if(this.environment.usePartial) { copies = copies + \" partials = partials || \" + namespace + \".partials;\"; }\n        out.push(copies);\n      } else {\n        out.push('');\n      }\n\n      if (!this.environment.isSimple) {\n        out.push(\", buffer = \" + this.initializeBuffer());\n      } else {\n        out.push(\"\");\n      }\n\n      // track the last context pushed into place to allow skipping the\n      // getContext opcode when it would be a noop\n      this.lastContext = 0;\n      this.source = out;\n    },\n\n    createFunctionContext: function(asObject) {\n      var locals = this.stackVars;\n      if (!this.isChild) {\n        locals = locals.concat(this.context.registers.list);\n      }\n\n      if(locals.length > 0) {\n        this.source[1] = this.source[1] + \", \" + locals.join(\", \");\n      }\n\n      // Generate minimizer alias mappings\n      if (!this.isChild) {\n        var aliases = []\n        for (var alias in this.context.aliases) {\n          this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];\n        }\n      }\n\n      if (this.source[1]) {\n        this.source[1] = \"var \" + this.source[1].substring(2) + \";\";\n      }\n\n      // Merge children\n      if (!this.isChild) {\n        this.source[1] += '\\n' + this.context.programs.join('\\n') + '\\n';\n      }\n\n      if (!this.environment.isSimple) {\n        this.source.push(\"return buffer;\");\n      }\n\n      var params = this.isChild ? [\"depth0\", \"data\"] : [\"Handlebars\", \"depth0\", \"helpers\", \"partials\", \"data\"];\n\n      for(var i=0, l=this.environment.depths.list.length; i<l; i++) {\n        params.push(\"depth\" + this.environment.depths.list[i]);\n      }\n\n      if (asObject) {\n        params.push(this.source.join(\"\\n  \"));\n\n        return Function.apply(this, params);\n      } else {\n        var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\\n  ' + this.source.join(\"\\n  \") + '}';\n        Handlebars.log(Handlebars.logger.DEBUG, functionSource + \"\\n\\n\");\n        return functionSource;\n      }\n    },\n\n    appendContent: function(content) {\n      this.source.push(this.appendToBuffer(this.quotedString(content)));\n    },\n\n    append: function() {\n      var local = this.popStack();\n      this.source.push(\"if(\" + local + \" || \" + local + \" === 0) { \" + this.appendToBuffer(local) + \" }\");\n      if (this.environment.isSimple) {\n        this.source.push(\"else { \" + this.appendToBuffer(\"''\") + \" }\");\n      }\n    },\n\n    appendEscaped: function() {\n      var opcode = this.nextOpcode(1), extra = \"\";\n      this.context.aliases.escapeExpression = 'this.escapeExpression';\n\n      if(opcode[0] === 'appendContent') {\n        extra = \" + \" + this.quotedString(opcode[1][0]);\n        this.eat(opcode);\n      }\n\n      this.source.push(this.appendToBuffer(\"escapeExpression(\" + this.popStack() + \")\" + extra));\n    },\n\n    getContext: function(depth) {\n      if(this.lastContext !== depth) {\n        this.lastContext = depth;\n      }\n    },\n\n    lookupWithHelpers: function(name, isScoped) {\n      if(name) {\n        var topStack = this.nextStack();\n\n        this.usingKnownHelper = false;\n\n        var toPush;\n        if (!isScoped && this.options.knownHelpers[name]) {\n          toPush = topStack + \" = \" + this.nameLookup('helpers', name, 'helper');\n          this.usingKnownHelper = true;\n        } else if (isScoped || this.options.knownHelpersOnly) {\n          toPush = topStack + \" = \" + this.nameLookup('depth' + this.lastContext, name, 'context');\n        } else {\n          this.register('foundHelper', this.nameLookup('helpers', name, 'helper'));\n          toPush = topStack + \" = foundHelper || \" + this.nameLookup('depth' + this.lastContext, name, 'context');\n        }\n\n        toPush += ';';\n        this.source.push(toPush);\n      } else {\n        this.pushStack('depth' + this.lastContext);\n      }\n    },\n\n    lookup: function(name) {\n      var topStack = this.topStack();\n      this.source.push(topStack + \" = (\" + topStack + \" === null || \" + topStack + \" === undefined || \" + topStack + \" === false ? \" +\n        topStack + \" : \" + this.nameLookup(topStack, name, 'context') + \");\");\n    },\n\n    pushStringParam: function(string) {\n      this.pushStack('depth' + this.lastContext);\n      this.pushString(string);\n    },\n\n    pushString: function(string) {\n      this.pushStack(this.quotedString(string));\n    },\n\n    push: function(name) {\n      this.pushStack(name);\n    },\n\n    invokeMustache: function(paramSize, original, hasHash) {\n      this.populateParams(paramSize, this.quotedString(original), \"{}\", null, hasHash, function(nextStack, helperMissingString, id) {\n        if (!this.usingKnownHelper) {\n          this.context.aliases.helperMissing = 'helpers.helperMissing';\n          this.context.aliases.undef = 'void 0';\n          this.source.push(\"else if(\" + id + \"=== undef) { \" + nextStack + \" = helperMissing.call(\" + helperMissingString + \"); }\");\n          if (nextStack !== id) {\n            this.source.push(\"else { \" + nextStack + \" = \" + id + \"; }\");\n          }\n        }\n      });\n    },\n\n    invokeProgram: function(guid, paramSize, hasHash) {\n      var inverse = this.programExpression(this.inverse);\n      var mainProgram = this.programExpression(guid);\n\n      this.populateParams(paramSize, null, mainProgram, inverse, hasHash, function(nextStack, helperMissingString, id) {\n        if (!this.usingKnownHelper) {\n          this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';\n          this.source.push(\"else { \" + nextStack + \" = blockHelperMissing.call(\" + helperMissingString + \"); }\");\n        }\n      });\n    },\n\n    populateParams: function(paramSize, helperId, program, inverse, hasHash, fn) {\n      var needsRegister = hasHash || this.options.stringParams || inverse || this.options.data;\n      var id = this.popStack(), nextStack;\n      var params = [], param, stringParam, stringOptions;\n\n      if (needsRegister) {\n        this.register('tmp1', program);\n        stringOptions = 'tmp1';\n      } else {\n        stringOptions = '{ hash: {} }';\n      }\n\n      if (needsRegister) {\n        var hash = (hasHash ? this.popStack() : '{}');\n        this.source.push('tmp1.hash = ' + hash + ';');\n      }\n\n      if(this.options.stringParams) {\n        this.source.push('tmp1.contexts = [];');\n      }\n\n      for(var i=0; i<paramSize; i++) {\n        param = this.popStack();\n        params.push(param);\n\n        if(this.options.stringParams) {\n          this.source.push('tmp1.contexts.push(' + this.popStack() + ');');\n        }\n      }\n\n      if(inverse) {\n        this.source.push('tmp1.fn = tmp1;');\n        this.source.push('tmp1.inverse = ' + inverse + ';');\n      }\n\n      if(this.options.data) {\n        this.source.push('tmp1.data = data;');\n      }\n\n      params.push(stringOptions);\n\n      this.populateCall(params, id, helperId || id, fn, program !== '{}');\n    },\n\n    populateCall: function(params, id, helperId, fn, program) {\n      var paramString = [\"depth0\"].concat(params).join(\", \");\n      var helperMissingString = [\"depth0\"].concat(helperId).concat(params).join(\", \");\n\n      var nextStack = this.nextStack();\n\n      if (this.usingKnownHelper) {\n        this.source.push(nextStack + \" = \" + id + \".call(\" + paramString + \");\");\n      } else {\n        this.context.aliases.functionType = '\"function\"';\n        var condition = program ? \"foundHelper && \" : \"\"\n        this.source.push(\"if(\" + condition + \"typeof \" + id + \" === functionType) { \" + nextStack + \" = \" + id + \".call(\" + paramString + \"); }\");\n      }\n      fn.call(this, nextStack, helperMissingString, id);\n      this.usingKnownHelper = false;\n    },\n\n    invokePartial: function(context) {\n      params = [this.nameLookup('partials', context, 'partial'), \"'\" + context + \"'\", this.popStack(), \"helpers\", \"partials\"];\n\n      if (this.options.data) {\n        params.push(\"data\");\n      }\n\n      this.pushStack(\"self.invokePartial(\" + params.join(\", \") + \");\");\n    },\n\n    assignToHash: function(key) {\n      var value = this.popStack();\n      var hash = this.topStack();\n\n      this.source.push(hash + \"['\" + key + \"'] = \" + value + \";\");\n    },\n\n    // HELPERS\n\n    compiler: JavaScriptCompiler,\n\n    compileChildren: function(environment, options) {\n      var children = environment.children, child, compiler;\n\n      for(var i=0, l=children.length; i<l; i++) {\n        child = children[i];\n        compiler = new this.compiler();\n\n        this.context.programs.push('');     // Placeholder to prevent name conflicts for nested children\n        var index = this.context.programs.length;\n        child.index = index;\n        child.name = 'program' + index;\n        this.context.programs[index] = compiler.compile(child, options, this.context);\n      }\n    },\n\n    programExpression: function(guid) {\n      if(guid == null) { return \"self.noop\"; }\n\n      var child = this.environment.children[guid],\n          depths = child.depths.list;\n      var programParams = [child.index, child.name, \"data\"];\n\n      for(var i=0, l = depths.length; i<l; i++) {\n        depth = depths[i];\n\n        if(depth === 1) { programParams.push(\"depth0\"); }\n        else { programParams.push(\"depth\" + (depth - 1)); }\n      }\n\n      if(depths.length === 0) {\n        return \"self.program(\" + programParams.join(\", \") + \")\";\n      } else {\n        programParams.shift();\n        return \"self.programWithDepth(\" + programParams.join(\", \") + \")\";\n      }\n    },\n\n    register: function(name, val) {\n      this.useRegister(name);\n      this.source.push(name + \" = \" + val + \";\");\n    },\n\n    useRegister: function(name) {\n      if(!this.context.registers[name]) {\n        this.context.registers[name] = true;\n        this.context.registers.list.push(name);\n      }\n    },\n\n    pushStack: function(item) {\n      this.source.push(this.nextStack() + \" = \" + item + \";\");\n      return \"stack\" + this.stackSlot;\n    },\n\n    nextStack: function() {\n      this.stackSlot++;\n      if(this.stackSlot > this.stackVars.length) { this.stackVars.push(\"stack\" + this.stackSlot); }\n      return \"stack\" + this.stackSlot;\n    },\n\n    popStack: function() {\n      return \"stack\" + this.stackSlot--;\n    },\n\n    topStack: function() {\n      return \"stack\" + this.stackSlot;\n    },\n\n    quotedString: function(str) {\n      return '\"' + str\n        .replace(/\\\\/g, '\\\\\\\\')\n        .replace(/\"/g, '\\\\\"')\n        .replace(/\\n/g, '\\\\n')\n        .replace(/\\r/g, '\\\\r') + '\"';\n    }\n  };\n\n  var reservedWords = (\n    \"break else new var\" +\n    \" case finally return void\" +\n    \" catch for switch while\" +\n    \" continue function this with\" +\n    \" default if throw\" +\n    \" delete in try\" +\n    \" do instanceof typeof\" +\n    \" abstract enum int short\" +\n    \" boolean export interface static\" +\n    \" byte extends long super\" +\n    \" char final native synchronized\" +\n    \" class float package throws\" +\n    \" const goto private transient\" +\n    \" debugger implements protected volatile\" +\n    \" double import public let yield\"\n  ).split(\" \");\n\n  var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};\n\n  for(var i=0, l=reservedWords.length; i<l; i++) {\n    compilerWords[reservedWords[i]] = true;\n  }\n\n  JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {\n    if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) {\n      return true;\n    }\n    return false;\n  }\n\n})(Handlebars.Compiler, Handlebars.JavaScriptCompiler);\n\nHandlebars.precompile = function(string, options) {\n  options = options || {};\n\n  var ast = Handlebars.parse(string);\n  var environment = new Handlebars.Compiler().compile(ast, options);\n  return new Handlebars.JavaScriptCompiler().compile(environment, options);\n};\n\nHandlebars.compile = function(string, options) {\n  options = options || {};\n\n  var compiled;\n  function compile() {\n    var ast = Handlebars.parse(string);\n    var environment = new Handlebars.Compiler().compile(ast, options);\n    var templateSpec = new Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);\n    return Handlebars.template(templateSpec);\n  }\n\n  // Template is only compiled on first use and cached after that point.\n  return function(context, options) {\n    if (!compiled) {\n      compiled = compile();\n    }\n    return compiled.call(this, context, options);\n  };\n};\n;\n// lib/handlebars/runtime.js\nHandlebars.VM = {\n  template: function(templateSpec) {\n    // Just add water\n    var container = {\n      escapeExpression: Handlebars.Utils.escapeExpression,\n      invokePartial: Handlebars.VM.invokePartial,\n      programs: [],\n      program: function(i, fn, data) {\n        var programWrapper = this.programs[i];\n        if(data) {\n          return Handlebars.VM.program(fn, data);\n        } else if(programWrapper) {\n          return programWrapper;\n        } else {\n          programWrapper = this.programs[i] = Handlebars.VM.program(fn);\n          return programWrapper;\n        }\n      },\n      programWithDepth: Handlebars.VM.programWithDepth,\n      noop: Handlebars.VM.noop\n    };\n\n    return function(context, options) {\n      options = options || {};\n      return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);\n    };\n  },\n\n  programWithDepth: function(fn, data, $depth) {\n    var args = Array.prototype.slice.call(arguments, 2);\n\n    return function(context, options) {\n      options = options || {};\n\n      return fn.apply(this, [context, options.data || data].concat(args));\n    };\n  },\n  program: function(fn, data) {\n    return function(context, options) {\n      options = options || {};\n\n      return fn(context, options.data || data);\n    };\n  },\n  noop: function() { return \"\"; },\n  invokePartial: function(partial, name, context, helpers, partials, data) {\n    options = { helpers: helpers, partials: partials, data: data };\n\n    if(partial === undefined) {\n      throw new Handlebars.Exception(\"The partial \" + name + \" could not be found\");\n    } else if(partial instanceof Function) {\n      return partial(context, options);\n    } else if (!Handlebars.compile) {\n      throw new Handlebars.Exception(\"The partial \" + name + \" could not be compiled when running in runtime-only mode\");\n    } else {\n      partials[name] = Handlebars.compile(partial);\n      return partials[name](context, options);\n    }\n  }\n};\n\nHandlebars.template = Handlebars.VM.template;\n;\n"
  },
  {
    "path": "_archive/apps/samples/sandbox/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('mainpage.html',\n    {\n    \tid: \"mainwin\",\n    \tinnerBounds: {width: 500, height: 309}\n    });\n});\n"
  },
  {
    "path": "_archive/apps/samples/sandbox/mainpage.html",
    "content": "<!--\n  - Copyright (c) 2012 The Chromium Authors. All rights reserved.\n  - Use of this source code is governed by a BSD-style license that can be\n  - found in the LICENSE file.\n  -->\n<!doctype html>\n<html>\n  <head>\n    <script src=\"mainpage.js\"></script>\n    <link href=\"styles/main.css\" rel=\"stylesheet\">\n  </head>\n  <body>\n\n    <div id=\"buttons\">\n      <button id=\"sendMessage\">Click me</button>\n      <button id=\"reset\">Reset counter</button>\n    </div>\n\n    <div id=\"result\"></div>\n\n    <iframe id=\"theFrame\" src=\"sandbox.html\" style=\"display: none;\"></iframe>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/sandbox/mainpage.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar counter=0;\ndocument.addEventListener('DOMContentLoaded', function() {\n\n  document.getElementById('reset').addEventListener('click', function(event) {\n    counter=0;\n    document.querySelector(\"#result\").innerHTML=\"\";\n  });\n\n  document.getElementById('sendMessage').addEventListener('click', function(event) {\n    counter++;\n    var message = {\n      command: 'render',\n      templateName: 'sample-template-'+counter,\n      context: {'counter': counter}\n    };\n    document.getElementById('theFrame').contentWindow.postMessage(message, '*');\n  });\n\n  // on result from sandboxed frame:\n  window.addEventListener('message', function(event) {\n    document.querySelector(\"#result\").innerHTML=event.data.result || \"invalid result\"\n  });\n});\n\n"
  },
  {
    "path": "_archive/apps/samples/sandbox/manifest.json",
    "content": "{\n  \"name\": \"Sandboxed Frame Sample\",\n  \"version\": \"1.0.2\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"23\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"icons\": {\n    \"128\": \"icon_128.png\"\n  },\n  \"sandbox\": {\n    \"pages\": [\"sandbox.html\"]\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/sandbox/sandbox.html",
    "content": "<!--\n  - Copyright (c) 2012 The Chromium Authors. All rights reserved.\n  - Use of this source code is governed by a BSD-style license that can be\n  - found in the LICENSE file.\n  -->\n<!doctype html>\n<html>\n  <head>\n    <script src=\"handlebars-1.0.0.beta.6.js\"></script>\n  </head>\n  <body>\n\n    <script id=\"sample-template-1\" type=\"text/x-handlebars-template\">\n      <div class=\"entry\">\n        <h1>Hello</h1>\n        <p>This is a Handlebar template compiled inside a hidden sandboxed iframe.</p>\n        <p>The counter parameter from postMessage (outer frame) is: {{counter}}</p>\n      </div>\n    </script>\n\n    <script id=\"sample-template-2\" type=\"text/x-handlebars-template\">\n      <div class=\"entry\">\n        <h1>Welcome back</h1>\n        <p>This is another Handlebar template compiled inside a hidden sandboxed iframe.</p>\n        <p>The counter parameter from postMessage (outer frame) is: {{counter}}</p>\n      </div>\n    </script>\n\n    <script>\n      var templatesElements = document.querySelectorAll(\"script[type='text/x-handlebars-template']\"),\n          templates = {},\n          source, name;\n\n      // precompile all templates in this page\n      for (var i=0; i<templatesElements.length; i++) {\n        source = templatesElements[i].innerHTML;\n        name = templatesElements[i].id;\n        templates[name] = Handlebars.compile(source);\n      }\n\n      // Set up message event handler:\n      window.addEventListener('message', function(event) {\n        var command = event.data.command,\n            template = templates[event.data.templateName],\n            result = \"invalid request\";\n\n        // if we don't know the templateName requested, return an error message\n        if (!template) {\n          result = 'Unknown template: ' + event.data.templateName;\n        } else {\n          switch(command) {\n            case 'render':\n              result = template(event.data.context);\n              break;\n          // you could even do dynamic compilation, by accepting a command\n          // to compile a new template instead of using static ones, for example:\n          // case 'new':\n          //   template = Handlebars.compile(event.data.templateSource);\n          //   result = template(event.data.context);\n          //   break;\n          }\n        }\n        event.source.postMessage({'result': result}, event.origin);\n      });\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/sandbox/styles/main.css",
    "content": "html,\nbody {\n  font-family: Helvetica, Arial, sans-serif;\n}\n\nbutton {\n  width: 150px;\n  line-height: 26px;\n  font-size: 14px;\n  border-radius:4px;\n  border: 1px solid #666;\n  background: -webkit-linear-gradient(top, #ffffff 0%, #f2f2f2 99%);\n  box-shadow: 0 1px 1px rgba(0,0,0,0.3);\n  color: #555;\n}\n\nbutton:hover {\n  color: #333;\n}\n\nbutton:active {\n  color: #000;\n}\n\n#buttons {\n  text-align: center;\n  padding: 15px;\n  background: #fcfcfc;\n  border-bottom: 1px solid #f2f2f2;\n}\n\n#result {\n  padding: 20px;\n}\n\n#result h1 {\n  margin: 0 0 0.2em 0;\n}\n\n#result p {\n  line-height: 140%\n}\n"
  },
  {
    "path": "_archive/apps/samples/sandboxed-content/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/gaaeficfcmngmogaejhikdnkdijlpgec\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Sandbox\n\nThis sample creates a window containing a sandboxed iframe (`sandbox.html`).\nThe sandbox uses `eval()` function to write some HTML to its own document.\n\nThe default packaged app Content Security Policy (CSP) value\n[disallows](https://developer.chrome.com/docs/apps/contentSecurityPolicy/) the use of\n`eval()` or `new Function()` (or variants like `Function.apply()`) so using a\nsandbox is necessary for this process. To enable sandboxing in your app you\nadd the `sandbox` property to your app's [manifest file](http://developer.chrome.com/apps/manifest#sandbox).\n\nSee more info on [using eval safely in packaged apps](http://developer.chrome.com/apps/sandboxingEval).\n\n## APIs\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime/)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/sandboxed-content/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/sandboxed-content/main.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <title>Sandboxed Content</title>\n    <link rel=\"stylesheet\" href=\"styles/main.css\">\n</head>\n<body>\n    <h1>Main Window</h1>\n    <p>I am the main window. I am not sandboxed.</p>\n    <iframe src=\"sandboxed.html\" width=\"380\" height=\"140\"></iframe>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/sandboxed-content/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('main.html',\n    {\n    \tid: \"mainwin\",\n    \tinnerBounds: {width: 400, height: 350}\n    });\n});\n"
  },
  {
    "path": "_archive/apps/samples/sandboxed-content/manifest.json",
    "content": "{\n  \"name\": \"Sandboxed Content Sample\",\n  \"version\": \"1.0.2\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"23\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"icons\": {\n    \"128\": \"icon_128.png\"\n  },\n  \"sandbox\": {\n    \"pages\": [\"sandboxed.html\"]\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/sandboxed-content/sandboxed.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <title>Sandboxed Content</title>\n    <link rel=\"stylesheet\" href=\"styles/main.css\">\n</head>\n<body>\n    <h1>Sandboxed Content</h1>\n    <p>I am the sandboxed iframe.</p>\n    <div id=\"message\"></div>\n    <script>\n      eval('document.getElementById(\\'message\\').innerHTML = \\'<p>I am the ' +\n        'output of an eval-ed inline script.</p>\\'');\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/sandboxed-content/styles/main.css",
    "content": "html, body {\n  font-family: Helvetica, Arial;\n  color: #444;\n}\n\nh1 {\n  margin: 0 0 0.3em 0;\n}\n\np {\n  color: #888;\n  margin: 0 0 1em 0;\n}\n\niframe {\n  border: 1px solid #CCC;\n  margin-top: 20px;\n}\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ieoiddehfkbacdideciijbdjfjegmpjo\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# ADK kit in Javascript\n\nThis demo is composed of two parts and require a ADK 1.0 hardware (Arduino board+shield shipped at Google I/O 2011) to demonstrate Android hardware integration.\n\nThe demo simulates the same visual interface of the Android application, but in HTML5. There are UI widgets to control the servo motors, led lights and relays, and it gets sensors and buttons events.\n\nIn the firmware directory, there is the Arduino app you must upload. We could not use exactly the same arduino code from the original Android ADK because it uses a USB port where the board is the USB host, and that woudl conflict with the computer USB port that is always the host. Upload the arduino firmware code to the board and you are set.\n\nIn the app directory, you will find the Chrome Packaged App.\n\n## APIs\n\n* [Serial API](http://developer.chrome.com/apps/app.hardware.html#serial)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/serial/adkjs/app/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/app/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ieoiddehfkbacdideciijbdjfjegmpjo\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/app/comm.html",
    "content": "<!DOCTYPE html>\n<!--\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Renato Mangini (mangini@chromium.org)\nAuthor: Luis Leao (luisleao@gmail.com)\n-->\n\n<html>\n<head>\n  <meta charset=\"utf-8\" />\n  <link rel=\"stylesheet\" media=\"all\" href=\"css/main.css\"></link>\n  <title>Chrome ADK control</title>\n</head>\n<body>\n  <header>\n    <div id=\"expand\" class=\"expandable\">\n      <div id=\"status\">Hover here to connect</div>\n      <div id=\"handler\">settings</div>\n      <div class=\"commands\">\n        <select class=\"serial_devices\">\n        </select>\n        <button class=\"refresh\">refresh</button><br/>\n        <button class=\"open\">open</button>\n        <button class=\"close\">close</button>\n        <div class=\"log\"></div>\n      </div>\n    </div>\n    <nav>\n      <ul>\n        <li><a id=\"inlink\" href=\"#inlink\">In</a></li>\n        <li><a id=\"outlink\" href=\"#outlink\">Out</a></li>\n      </ul>\n    </nav>\n  </header>\n  <section id=\"in\">\n    <article class=\"temp\">\n      <p>Temp<label><span id=\"temp\">80</span>&deg;</label></p>\n    </article>\n    <article class=\"light\">\n      <p>Light\n         <label><span id=\"light\">86.4</span><small>%</small></label>\n         <strong><span id=\"lightv1\">885</span></strong>/1024\n      </p>\n    </article>\n    <article class=\"buttons\">\n      <p>Buttons<br/>\n      <div id=\"b1\"></div>\n      <div id=\"b2\"></div>\n      <div id=\"b3\"></div>\n      <div id=\"bc\"></div></p>\n    </article>\n    <article class=\"joys\">\n      <p>Joystick<br/>\n      <div id=\"joy\">\n        <div class=\"pointer\">0,0</div>\n      </div>\n    </article>\n  </section>\n  <section id=\"out\" class=\"hidden\">\n    <article class=\"servos\">\n      <p>Servo<sub>1</sub></p>\n      <input type=\"range\" min=\"0\" max=\"100\" value=\"0\"/>\n      <p>Servo<sub>2</sub></p>\n      <input type=\"range\" min=\"0\" max=\"100\" value=\"0\"/>\n      <p>Servo<sub>3</sub></p>\n      <input type=\"range\" min=\"0\" max=\"100\" value=\"0\"/>\n    </article>\n    <article class=\"relays\">\n      <p>Relay<sub>1</sub><button class=\"r1\">Off</button></p>\n      <p>Relay<sub>2</sub><button class=\"r2\">Off</button></p>\n    </article>\n    <article class=\"leds\">\n      <p id=\"led1\"><label>Led<sub>1</sub></label>\n      <input class=\"r\" type=\"range\" min=\"0\" max=\"255\" value=\"0\"/><span>0</span>\n      <input class=\"g\" type=\"range\" min=\"0\" max=\"255\" value=\"0\"/><span>0</span>\n      <input class=\"b\" type=\"range\" min=\"0\" max=\"255\" value=\"0\"/><span>0</span></p>\n      <p id=\"led2\"><label>Led<sub>2</sub></label>\n      <input class=\"r\" type=\"range\" min=\"0\" max=\"255\" value=\"0\"/><span>0</span>\n      <input class=\"g\" type=\"range\" min=\"0\" max=\"255\" value=\"0\"/><span>0</span>\n      <input class=\"b\" type=\"range\" min=\"0\" max=\"255\" value=\"0\"/><span>0</span></p>\n      <p id=\"led3\"><label>Led<sub>3</sub></label>\n      <input class=\"r\" type=\"range\" min=\"0\" max=\"255\" value=\"0\"/><span>0</span>\n      <input class=\"g\" type=\"range\" min=\"0\" max=\"255\" value=\"0\"/><span>0</span>\n      <input class=\"b\" type=\"range\" min=\"0\" max=\"255\" value=\"0\"/><span>0</span></p>\n    </article>\n  </section>\n  <script src=\"js/serial.js\"></script>\n  <script src=\"js/adk.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/app/css/main.css",
    "content": "html, body {\n  margin: 0;\n  padding: 0;\n  background-color: #000;\n}\n\nbody {\n  background-image: url(../img/background_holo_dark.png);\n  background-repeat: no-repeat;\n  background-size: 100%;\n  color: #fff;\n  font-family: 'Open Sans', arial, sans-serif;\n  font-size: 15px;\n  overflow: hidden;\n}\n\nheader {\n position: relative;\n}\nheader:after {\n  clear: left;\n  content: \"\";\n  display: block;\n}\nheader .expandable {\n position: absolute;\n z-index: 2;\n -webkit-transition: height 0.5s;\n height: 16px;\n overflow: hidden;\n margin:0;\n background: black;\n padding: 3px;\n font-size: 13px;\n left: 0;\n right: 0;\n}\nheader .expandable:hover #status {\n  color: transparent;\n}\nheader #status {\n float: left;\n}\nheader #status.error {\n color: red;\n}\nheader #status.on {\n color: green;\n}\nheader #handler {\n float: right;\n}\nheader .commands {\n  clear: both;\n  padding: 10px;\n}\n\nheader .expandable:hover {\n height: 220px;\n background: -webkit-linear-gradient(#000, #186404);\n}\n\n.log {\n width: 100%; \n height: 140px;\n background: white;\n border: 1px solid #333;\n overflow: auto;\n font-size: 12px;\n}\n\nnav ul {\n  margin: 0;\n  padding: 22px 0 0 0;\n  list-style: none;\n  line-height: 24px;\n  width: 100%;\n}\nnav li {\n  float:left;\n  margin:0;\n  padding:0;\n  width: 50%;\n}\nnav a {\n  display: block;\n  text-decoration:none;\n  background: -webkit-linear-gradient(#212121, #131313);\n  color: white;\n  float: left;\n  width: 100%;\n  font-size: 22px;\n  text-align: center;\n  padding: 10px 0;\n}\nnav a:hover,\nnav a:active,\nnav a:target\n{\n  background: #2ac7e1;\n}\n\nsection {\n  padding: 0 10px;\n  color: #666;\n}\n\n.hidden {\n  display: none;\n}\n\narticle {\n  display: block;\n}\narticle.servos {\n  float: left;\n  width: 60%;\n}\narticle.relays {\n  float: right;\n  width: 35%;\n}\narticle.leds {\n  float: left;\n  clear: both;\n}\nsection article span {\n  color: white;\n}\nsection#in article label {\n  font-size: 36px;\n  display: block;\n  color: white;\n  margin-top: -3px;\n}\nsmall {\n  font-size: 16px;\n}\n.temp, .light {\n  float: left;\n  width: 48%;\n}\n.light label {\n  margin-bottom: -6px;\n}\n\n.buttons {\n clear: left;\n}\n\n.buttons div {\n  width: 60px;\n  height: 60px;\n  border: 0px;\n  float: left;\n  margin-left: 15px;\n}\n#b1 {\n  background: url(\"../img/indicator_button1_off_holo_dark.png\");\n} \n#b1.on {\n  background: url(\"../img/indicator_button1_on_holo_dark.png\");\n} \n#b2 {\n  background: url(\"../img/indicator_button2_off_holo_dark.png\");\n} \n#b2.on {\n  background: url(\"../img/indicator_button2_on_holo_dark.png\");\n} \n#b3 {\n  background: url(\"../img/indicator_button3_off_holo_dark.png\");\n} \n#b3.on {\n  background: url(\"../img/indicator_button3_on_holo_dark.png\");\n} \n#bc {\n  background: url(\"../img/indicator_button_capacitive_off_holo_dark.png\");\n} \n#bc.on {\n  background: url(\"../img/indicator_button_capacitive_on_holo_dark.png\");\n} \n\n.joys {\n clear: left;\n}\narticle p {\n  margin-bottom: 3px;\n  margin-top: 0;\n  padding-top: 5px;\n}\n#out p {\n  margin: 0;\n  padding: 0;\n}\n\n#joy {\n  background: url(\"../img/joystick_background.png\");\n  background-repeat: no-repeat;\n  background-position: center;\n  width: 100%;\n  height: 242px;\n  position: relative;\n} \n#joy .pointer {\n  background-image: url(\"../img/joystick_normal_holo_dark.png\");\n  background-position: -11px center;\n  background-repeat: no-repeat;\n  padding-left: 12px;\n  color: white;\n  font-size: 10px;\n  position: absolute;\n  left: 50%;\n  top: 50%;\n  margin-left: -5px;\n  margin-top: -7px;\n}\n#joy .pointer.on {\n  background-image: url(\"../img/joystick_pressed_holo_dark.png\");\n  color: #2ac7e1;\n}\n\ninput[type='range'] {\n  margin: 0;\n}\n.servos input[type='range'] {\n    -webkit-appearance: none;\n    background: url('../img/scrubber_horizontal_holo_dark.png');\n    width: 100%;\n    background-position: center;\n    background-size: -webkit-calc(100% - 5px) 100%;\n    background-repeat: no-repeat;\n}\n\n.leds p {\n  position: relative;\n}\n\n.leds label, .leds span {\n  position: absolute;\n}\n\n.leds span {\n  right: 0;\n  padding-top: 8px;\n  color: #666;\n}\n\n.leds input[type='range'] {\n    -webkit-appearance: none;\n    background: url('../img/scrubber_horizontal_green_holo_dark.png');\n    width: 80%;\n    margin-left: 35px;\n    background-position: center;\n    background-size: -webkit-calc(100% - 25px) 3px;\n    background-repeat: no-repeat;\n}\n.leds input[type='range'].r {\n    background-image: url('../img/scrubber_horizontal_red_holo_dark.png');\n}\n.leds input[type='range'].b {\n    background-image: url('../img/scrubber_horizontal_blue_holo_dark.png');\n}\n\ninput[type='range']::-webkit-slider-thumb {\n    -webkit-appearance: none;\n    width: 26px;\n    height: 26px;\n    background: url('../img/scrubber_control.png');\n    background-repeat: no-repeat;\n    cursor: pointer;\n}\n\n.relays button {\n  background-color: transparent;\n  display: block;\n  color: white;\n  width: 100%;\n  height: 50px;\n  background-repeat: no-repeat;\n  background-position: center;\n  border: none;\n  cursor: pointer;\n}\n.relays button,\n.relays button.on:hover {\n  background-image: url('../img/toggle_button_off_holo_dark.png');\n}\n.relays button:hover,\n.relays button.on {\n  background-image: url('../img/toggle_button_on_holo_dark.png');\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/app/js/adk.js",
    "content": "/**\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Renato Mangini (mangini@chromium.org)\nAuthor: Luis Leao (luisleao@gmail.com)\nAuthor: Ken Rockot (rockot@chromium.org)\n**/\n\nconst SENSOR_REFRESH_INTERVAL=200;\n\n(function() {\n  var btnOpen = document.querySelector(\".open\");\n  var btnClose = document.querySelector(\".close\");\n  var logArea = document.querySelector(\".log\");\n  var statusLine = document.querySelector(\"#status\");\n  var serialDevices = document.querySelector(\".serial_devices\");\n  var connection = null;\n\n  var logObj = function(obj) {\n    console.log(obj);\n  }\n\n  var logSuccess = function(msg) {\n    log(\"<span style='color: green;'>\" + msg + \"</span>\");\n  };\n\n  var logError = function(msg) {\n    statusLine.className = \"error\";\n    statusLine.textContent = msg;\n    log(\"<span style='color: red;'>\" + msg + \"</span>\");\n  };\n\n  var log = function(msg) {\n    console.log(msg);\n    logArea.innerHTML = msg + \"<br/>\" + logArea.innerHTML;\n  };\n\n  var changeTab = function() {\n    var _in = document.querySelector(\"#in\");\n    var _out = document.querySelector(\"#out\");\n    if (window.location.hash === \"#outlink\") {\n      _out.className = \"\";\n      _in.className = \"hidden\";\n    } else {\n      _in.className = \"\";\n      _out.className = \"hidden\";\n    }\n  };\n\n  var init = function() {\n    if (!serial_lib)\n      throw \"You must include serial.js before\";\n\n    enableOpenButton(true);\n    btnOpen.addEventListener(\"click\", openDevice);\n    btnClose.addEventListener(\"click\", closeDevice);\n    window.addEventListener(\"hashchange\", changeTab);\n    document.querySelector(\".refresh\").addEventListener(\"click\", refreshPorts);\n    initADKListeners();\n    refreshPorts();\n  };\n\n  var initADKListeners = function() {\n    addListenerToElements(\"change\", \".servos input[type='range']\", function(e, index) {\n        sendSerial(\"s\" + index + toHexString(parseInt(this.value)));\n    });\n    addListenerToElements(\"change\", \".leds input[type='range']\", function(e, index) {\n        this.nextSibling.textContent = this.value;\n        sendSerial(\"c\" + index + toHexString(parseInt(this.value)));\n    });\n    addListenerToElements(\"click\", \".relays button\", function(e, index) {\n      if (this.classList.contains(\"on\")) {\n        // turn it off\n        this.classList.remove(\"on\");\n        this.textContent = \"Off\";\n        sendSerial(\"t\" + index + \"0\");\n      } else {\n        // turn it on\n        this.classList.add(\"on\");\n        this.textContent = \"On\";\n        sendSerial(\"t\" + index + \"1\");\n      }\n    });\n    setInterval(function() { sendSerial(\"data\"); }, SENSOR_REFRESH_INTERVAL);\n  };\n\n  var addListenerToElements = function(eventType, selector, listener) {\n    var addListener = function(type, element, index) {\n      element.addEventListener(type, function(e) {\n        listener.apply(this, [e, index]);\n      });\n    };\n    var elements = document.querySelectorAll(selector);\n    for (var i = 0; i < elements.length; ++i) {\n      addListener(eventType, elements[i], i);\n    }\n  };\n\n  var toHexString = function(i) {\n    return (\"00\" + i.toString(16)).substr(-2);\n  };\n\n  var enableOpenButton = function(enable) {\n    btnOpen.disabled = !enable;\n    btnClose.disabled = enable;\n  };\n\n  var refreshPorts = function() {\n    while (serialDevices.options.length > 0)\n      serialDevices.options.remove(0);\n\n    serial_lib.getDevices(function(items) {\n      logSuccess(\"got \" + items.length + \" ports\");\n      for (var i = 0; i < items.length; ++i) {\n        var path = items[i].path;\n        serialDevices.options.add(new Option(path, path));\n        if (i === 1 || /usb/i.test(path) && /tty/i.test(path)) {\n          serialDevices.selectionIndex = i;\n          logSuccess(\"auto-selected \" + path);\n        }\n      }\n    });\n  };\n\n  var openDevice = function() {\n    var selection = serialDevices.selectedOptions[0];\n    if (!selection) {\n      logError(\"No port selected.\");\n      return;\n    }\n    var path = selection.value;\n    statusLine.classList.add(\"on\");\n    statusLine.textContent = \"Connecting\";\n    enableOpenButton(false);\n    serial_lib.openDevice(path, onOpen);\n  };\n\n  var onOpen = function(newConnection) {\n    if (newConnection === null) {\n      logError(\"Failed to open device.\");\n      return;\n    }\n    connection = newConnection;\n    connection.onReceive.addListener(onReceive);\n    connection.onError.addListener(onError);\n    connection.onClose.addListener(onClose);\n    logSuccess(\"Device opened.\");\n    enableOpenButton(false);\n    statusLine.textContent = \"Connected\";\n  };\n\n  var sendSerial = function(message) {\n    if (connection === null) {\n      return;\n    }\n    if (!message) {\n      logError(\"Nothing to send!\");\n      return;\n    }\n    if (message.charAt(message.length - 1) !== '\\n') {\n      message += \"\\n\";\n    }\n    connection.send(message);\n  };\n\n  var onError = function(errorInfo) {\n    if (errorInfo.error !== 'timeout') {\n      logError(\"Fatal error encounted. Dropping connection.\");\n      closeDevice();\n    }\n  };\n\n  var onReceive = function(data) {\n    if (data.indexOf(\"log:\") >= 0) {\n      return;\n    }\n    var m = /([^:]+):([-]?\\d+)(?:,([-]?\\d+))?/.exec(data);\n    if (m && m.length > 0) {\n      switch (m[1]) {\n        case \"b1\":\n          document.querySelector(\"#b1\").className = m[2] === \"0\" ? \"\" : \"on\";\n          break;\n        case \"b2\":\n          document.querySelector(\"#b2\").className = m[2] === \"0\" ? \"\" : \"on\";\n          break;\n        case \"b3\":\n          document.querySelector(\"#b3\").className = m[2] === \"0\" ? \"\" : \"on\";\n          break;\n        case \"c\":\n          document.querySelector(\"#bc\").className = m[2] === \"0\" ? \"\" : \"on\";\n          log(data);\n          break;\n        case \"js\":\n          document.querySelector(\"#joy .pointer\").className = m[2] === \"0\" ? \"pointer\" : \"pointer on\";\n          break;\n        case \"t\":\n          document.querySelector(\"#temp\").textContent = convertTemperature(m[2]);\n          break;\n        case \"l\":\n          document.querySelector(\"#light\").textContent = Math.round((1000 * parseInt(m[2]) / 1024)) / 10;\n          document.querySelector(\"#lightv1\").textContent = m[2];\n          break;\n        case \"jxy\":\n          var el = document.querySelector(\"#joy .pointer\");\n          el.style.left = ((128 + parseInt(m[2]) * 0.6) / 256.0 * el.parentElement.offsetWidth) + \"px\";\n          el.style.top = ((128 + parseInt(m[3]) * 0.9) / 256.0 * el.parentElement.offsetHeight) + \"px\";\n          el.textContent = m[2] + \",\" + m[3];\n          break;\n      }\n    }\n  };\n\n  var convertTemperature=function(temperatureFromArduino) {\n    // from ADK Android code:\n    /*\n     * Arduino board contains a 6 channel (8 channels on the Mini and Nano,\n     * 16 on the Mega), 10-bit analog to digital converter. This means that\n     * it will map input voltages between 0 and 5 volts into integer values\n     * between 0 and 1023. This yields a resolution between readings of: 5\n     * volts / 1024 units or, .0049 volts (4.9 mV) per unit.\n    */\n    var voltagemv = temperatureFromArduino * 4.9;\n    /*\n     * The change in voltage is scaled to a temperature coefficient of 10.0\n     * mV/degC (typical) for the MCP9700/9700A and 19.5 mV/degC (typical)\n     * for the MCP9701/9701A. The out- put voltage at 0 degC is also scaled\n     * to 500 mV (typical) and 400 mV (typical) for the MCP9700/9700A and\n     * MCP9701/9701A, respectively. VOUT = TC¥TA+V0degC\n     */\n    var kVoltageAtZeroCmv = 400,\n        kTemperatureCoefficientmvperC = 19.5;\n    var ambientTemperatureC = (voltagemv - kVoltageAtZeroCmv) / kTemperatureCoefficientmvperC;\n    var temperatureF = (9.0 / 5.0) * ambientTemperatureC + 32.0;\n    return Math.round(temperatureF);\n  };\n\n  var closeDevice = function() {\n   if (connection !== null) {\n     connection.close();\n   }\n  };\n\n  var onClose = function(result) {\n    connection = null;\n    enableOpenButton(true);\n    statusLine.textContent = \"Hover here to connect\";\n    statusLine.className = \"\";\n  }\n\n  init();\n})();\n\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/app/js/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('comm.html#inlink',\n     {\n     \tframe: 'custom', \n     \tid: \"mainwin\",\n     \tinnerBounds: {width: 343, height: 600}\n     });\n});\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/app/js/serial.js",
    "content": "/**\nCopyright 2013 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Renato Mangini (mangini@chromium.org)\nAuthor: Luis Leao (luisleao@gmail.com)\nAuthor: Ken Rockot (rockot@chromium.org)\n**/\n\nvar serial_lib = (function() {\n  var logObj = function(obj) {\n    console.log(obj);\n  }\n\n  var log = function(msg) {\n    console.log(msg);\n  };\n\n  // Enapsulates an active serial device connection.\n  var DeviceConnection = function(connectionId) {\n    var onReceive = new chrome.Event();\n    var onError = new chrome.Event();\n    var onClose = new chrome.Event();\n    var send = function(msg) {\n      chrome.serial.send(connectionId, str2ab(msg), function() {});\n    };\n    var close = function() {\n      chrome.serial.disconnect(connectionId, function(success) {\n        if (success) {\n          onClose.dispatch();\n        }\n      });\n    };\n    chrome.serial.onReceive.addListener(function(receiveInfo) {\n      if (receiveInfo.connectionId === connectionId) {\n        onReceive.dispatch(ab2str(receiveInfo.data));\n      }\n    });\n    chrome.serial.onReceiveError.addListener(function(errorInfo) {\n      if (errorInfo.connectionId === connectionId) {\n        onError.dispatch(errorInfo.error);\n      }\n    });\n    return {\n      \"onReceive\": onReceive,\n      \"onError\": onError,\n      \"onClose\": onClose,\n      \"send\": send,\n      \"close\": close\n    };\n  };\n\n  var getDevices = function(callback) {\n    chrome.serial.getDevices(callback);\n  };\n\n  var openDevice = function(path, callback) {\n    chrome.serial.connect(path, { bitrate: 57600 }, function(connectionInfo) {\n      var device = null;\n      if (connectionInfo) {\n        device = new DeviceConnection(connectionInfo.connectionId);\n      }\n      callback(device);\n    });\n  };\n  \n  /* Interprets an ArrayBuffer as UTF-8 encoded string data. */\n  var ab2str = function(buf) {\n    var bufView = new Uint8Array(buf);\n    var encodedString = String.fromCharCode.apply(null, bufView);\n    return decodeURIComponent(escape(encodedString));\n  };\n\n  /* Converts a string to UTF-8 encoding in a Uint8Array; returns the array buffer. */\n  var str2ab = function(str) {\n    var encodedString = unescape(encodeURIComponent(str));\n    var bytes = new Uint8Array(encodedString.length);\n    for (var i = 0; i < encodedString.length; ++i) {\n      bytes[i] = encodedString.charCodeAt(i);\n    }\n    return bytes.buffer;\n  }\n\n  return {\n    \"getDevices\": getDevices,\n    \"openDevice\": openDevice,\n  };\n}());\n\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/app/manifest.json",
    "content": "{\n  \"name\": \"ADK Controller Sample\",\n  \"version\": \"2\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"js/background.js\"]\n    }\n  },\n  \"icons\": {\n    \"128\": \"img/icon_128.png\"\n  },\n  \"permissions\" : [\"serial\"],\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/AndroidAccessory/AndroidAccessory.cpp",
    "content": "/*\n * Copyright (C) 2011 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n#include <Max3421e.h>\n#include <Usb.h>\n#include <AndroidAccessory.h>\n\n#define USB_ACCESSORY_VENDOR_ID         0x18D1\n#define USB_ACCESSORY_PRODUCT_ID        0x2D00\n\n#define USB_ACCESSORY_ADB_PRODUCT_ID    0x2D01\n#define ACCESSORY_STRING_MANUFACTURER   0\n#define ACCESSORY_STRING_MODEL          1\n#define ACCESSORY_STRING_DESCRIPTION    2\n#define ACCESSORY_STRING_VERSION        3\n#define ACCESSORY_STRING_URI            4\n#define ACCESSORY_STRING_SERIAL         5\n\n#define ACCESSORY_GET_PROTOCOL          51\n#define ACCESSORY_SEND_STRING           52\n#define ACCESSORY_START                 53\n\n\nAndroidAccessory::AndroidAccessory(const char *manufacturer,\n                                   const char *model,\n                                   const char *description,\n                                   const char *version,\n                                   const char *uri,\n                                   const char *serial) : manufacturer(manufacturer),\n                                                         model(model),\n                                                         description(description),\n                                                         version(version),\n                                                         uri(uri),\n                                                         serial(serial),\n                                                         connected(false)\n{\n\n}\n\nvoid AndroidAccessory::powerOn(void)\n{\n    max.powerOn();\n    delay(200);\n}\n\nint AndroidAccessory::getProtocol(byte addr)\n{\n    uint16_t protocol = -1;\n    usb.ctrlReq(addr, 0,\n                USB_SETUP_DEVICE_TO_HOST |\n                USB_SETUP_TYPE_VENDOR |\n                USB_SETUP_RECIPIENT_DEVICE,\n                ACCESSORY_GET_PROTOCOL, 0, 0, 0, 2, (char *)&protocol);\n    return protocol;\n}\n\nvoid AndroidAccessory::sendString(byte addr, int index, const char *str)\n{\n    usb.ctrlReq(addr, 0,\n                USB_SETUP_HOST_TO_DEVICE |\n                USB_SETUP_TYPE_VENDOR |\n                USB_SETUP_RECIPIENT_DEVICE,\n                ACCESSORY_SEND_STRING, 0, 0, index,\n                strlen(str) + 1, (char *)str);\n}\n\n\nbool AndroidAccessory::switchDevice(byte addr)\n{\n    int protocol = getProtocol(addr);\n\n    if (protocol == 1) {\n        Serial.print(\"device supports protcol 1\\n\");\n    } else {\n        Serial.print(\"could not read device protocol version\\n\");\n        return false;\n    }\n\n    sendString(addr, ACCESSORY_STRING_MANUFACTURER, manufacturer);\n    sendString(addr, ACCESSORY_STRING_MODEL, model);\n    sendString(addr, ACCESSORY_STRING_DESCRIPTION, description);\n    sendString(addr, ACCESSORY_STRING_VERSION, version);\n    sendString(addr, ACCESSORY_STRING_URI, uri);\n    sendString(addr, ACCESSORY_STRING_SERIAL, serial);\n\n    usb.ctrlReq(addr, 0,\n                USB_SETUP_HOST_TO_DEVICE |\n                USB_SETUP_TYPE_VENDOR |\n                USB_SETUP_RECIPIENT_DEVICE,\n                ACCESSORY_START, 0, 0, 0, 0, NULL);\n\n    while (usb.getUsbTaskState() != USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) {\n        max.Task();\n        usb.Task();\n    }\n\n    return true;\n}\n\n// Finds the first bulk IN and bulk OUT endpoints\nbool AndroidAccessory::findEndpoints(byte addr, EP_RECORD *inEp, EP_RECORD *outEp)\n{\n    int len;\n    byte err;\n    uint8_t *p;\n\n    err = usb.getConfDescr(addr, 0, 4, 0, (char *)descBuff);\n    if (err) {\n        Serial.print(\"Can't get config descriptor length\\n\");\n        return false;\n    }\n\n\n    len = descBuff[2] | ((int)descBuff[3] << 8);\n    if (len > sizeof(descBuff)) {\n        Serial.print(\"config descriptor too large\\n\");\n            /* might want to truncate here */\n        return false;\n    }\n\n    err = usb.getConfDescr(addr, 0, len, 0, (char *)descBuff);\n    if (err) {\n        Serial.print(\"Can't get config descriptor\\n\");\n        return false;\n    }\n\n    p = descBuff;\n    inEp->epAddr = 0;\n    outEp->epAddr = 0;\n    while (p < (descBuff + len)){\n        uint8_t descLen = p[0];\n        uint8_t descType = p[1];\n        USB_ENDPOINT_DESCRIPTOR *epDesc;\n        EP_RECORD *ep;\n\n        switch (descType) {\n        case USB_DESCRIPTOR_CONFIGURATION:\n            Serial.print(\"config desc\\n\");\n            break;\n\n        case USB_DESCRIPTOR_INTERFACE:\n            Serial.print(\"interface desc\\n\");\n            break;\n\n        case USB_DESCRIPTOR_ENDPOINT:\n            epDesc = (USB_ENDPOINT_DESCRIPTOR *)p;\n            if (!inEp->epAddr && (epDesc->bEndpointAddress & 0x80))\n                ep = inEp;\n            else if (!outEp->epAddr)\n                ep = outEp;\n            else\n                ep = NULL;\n\n            if (ep) {\n                ep->epAddr = epDesc->bEndpointAddress & 0x7f;\n                ep->Attr = epDesc->bmAttributes;\n                ep->MaxPktSize = epDesc->wMaxPacketSize;\n                ep->sndToggle = bmSNDTOG0;\n                ep->rcvToggle = bmRCVTOG0;\n            }\n            break;\n\n        default:\n            Serial.print(\"unkown desc type \");\n            Serial.println( descType, HEX);\n            break;\n        }\n\n        p += descLen;\n    }\n\n    if (!(inEp->epAddr && outEp->epAddr))\n        Serial.println(\"can't find accessory endpoints\");\n\n    return inEp->epAddr && outEp->epAddr;\n}\n\nbool AndroidAccessory::configureAndroid(void)\n{\n    byte err;\n    EP_RECORD inEp, outEp;\n\n    if (!findEndpoints(1, &inEp, &outEp))\n        return false;\n\n    memset(&epRecord, 0x0, sizeof(epRecord));\n\n    epRecord[inEp.epAddr] = inEp;\n    if (outEp.epAddr != inEp.epAddr)\n        epRecord[outEp.epAddr] = outEp;\n\n    in = inEp.epAddr;\n    out = outEp.epAddr;\n\n    Serial.println(inEp.epAddr, HEX);\n    Serial.println(outEp.epAddr, HEX);\n\n    epRecord[0] = *(usb.getDevTableEntry(0,0));\n    usb.setDevTableEntry(1, epRecord);\n\n    err = usb.setConf( 1, 0, 1 );\n    if (err) {\n        Serial.print(\"Can't set config to 1\\n\");\n        return false;\n    }\n\n    usb.setUsbTaskState( USB_STATE_RUNNING );\n\n    return true;\n}\n\nbool AndroidAccessory::isConnected(void)\n{\n    USB_DEVICE_DESCRIPTOR *devDesc = (USB_DEVICE_DESCRIPTOR *) descBuff;\n    byte err;\n\n    max.Task();\n    usb.Task();\n\n    if (!connected &&\n        usb.getUsbTaskState() >= USB_STATE_CONFIGURING &&\n        usb.getUsbTaskState() != USB_STATE_RUNNING) {\n        Serial.print(\"\\nDevice addressed... \");\n        Serial.print(\"Requesting device descriptor.\\n\");\n\n        err = usb.getDevDescr(1, 0, 0x12, (char *) devDesc);\n        if (err) {\n            Serial.print(\"\\nDevice descriptor cannot be retrieved. Trying again\\n\");\n            return false;\n        }\n\n        if (isAccessoryDevice(devDesc)) {\n            Serial.print(\"found android acessory device\\n\");\n\n            connected = configureAndroid();\n        } else {\n            Serial.print(\"found possible device. swithcing to serial mode\\n\");\n            switchDevice(1);\n        }\n    } else if (usb.getUsbTaskState() == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) {\n        if (connected)\n            Serial.println(\"disconnect\\n\");\n        connected = false;\n    }\n\n    return connected;\n}\n\nint AndroidAccessory::read(void *buff, int len, unsigned int nakLimit)\n{\n    return usb.newInTransfer(1, in, len, (char *)buff, nakLimit);\n}\n\nint AndroidAccessory::write(void *buff, int len)\n{\n    usb.outTransfer(1, out, len, (char *)buff);\n    return len;\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/AndroidAccessory/AndroidAccessory.h",
    "content": "/*\n * Copyright (C) 2011 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n#ifndef __AndroidAccessory_h__\n#define __AndroidAccessory_h__\n\n#include \"WProgram.h\"\n\nclass AndroidAccessory {\nprivate:\n    const char *manufacturer;\n    const char *model;\n    const char *description;\n    const char *version;\n    const char *uri;\n    const char *serial;\n\n    MAX3421E max;\n    USB usb;\n    bool connected;\n    uint8_t in;\n    uint8_t out;\n\n    EP_RECORD epRecord[8];\n\n    uint8_t descBuff[256];\n\n    bool isAccessoryDevice(USB_DEVICE_DESCRIPTOR *desc)\n    {\n        return desc->idVendor == 0x18d1 &&\n            (desc->idProduct == 0x2D00 || desc->idProduct == 0x2D01);\n    }\n\n    int getProtocol(byte addr);\n    void sendString(byte addr, int index, const char *str);\n    bool switchDevice(byte addr);\n    bool findEndpoints(byte addr, EP_RECORD *inEp, EP_RECORD *outEp);\n    bool configureAndroid(void);\n\npublic:\n    AndroidAccessory(const char *manufacturer,\n                     const char *model,\n                     const char *description,\n                     const char *version,\n                     const char *uri,\n                     const char *serial);\n\n    void powerOn(void);\n\n    bool isConnected(void);\n    int read(void *buff, int len, unsigned int nakLimit = USB_NAK_LIMIT);\n    int write(void *buff, int len);\n};\n\n#endif /* __AndroidAccessory_h__ */\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/CapSense/CapSense.cpp",
    "content": "/*\n CapacitiveSense.h v.04 - Capacitive Sensing Library for 'duino / Wiring\n Copyright (c) 2009 Paul Bagder  All right reserved.\n Version 04 by Paul Stoffregen - Arduino 1.0 compatibility, issue 146 fix\n vim: set ts=4:\n */\n\n#if ARDUINO >= 100\n#include \"Arduino.h\"\n#else\n#include \"WProgram.h\"\n#include \"pins_arduino.h\"\n#include \"WConstants.h\"\n#endif\n\n#include \"CapSense.h\"\n\n// Constructor /////////////////////////////////////////////////////////////////\n// Function that handles the creation and setup of instances\n\nCapSense::CapSense(uint8_t sendPin, uint8_t receivePin)\n{\n\tuint8_t sPort, rPort;\n\n\t// initialize this instance's variables\n\t// Serial.begin(9600);\t\t// for debugging\n\terror = 1;\n\tloopTimingFactor = 310;\t\t// determined empirically -  a hack\n\t\n\tCS_Timeout_Millis = (2000 * (float)loopTimingFactor * (float)F_CPU) / 16000000;\n\tCS_AutocaL_Millis = 20000;\n    \n\t// Serial.print(\"timwOut =  \");\n\t// Serial.println(CS_Timeout_Millis);\n\t\n\t// get pin mapping and port for send Pin - from PinMode function in core\n\n#ifdef NUM_DIGITAL_PINS\n\tif (sendPin >= NUM_DIGITAL_PINS) error = -1;\n\tif (receivePin >= NUM_DIGITAL_PINS) error = -1;\n#endif\n\t\n\tsBit =  digitalPinToBitMask(sendPin);\t\t\t// get send pin's ports and bitmask\n\tsPort = digitalPinToPort(sendPin);\n\tsReg = portModeRegister(sPort);\n\tsOut = portOutputRegister(sPort);\t\t\t\t// get pointer to output register   \n\n\trBit = digitalPinToBitMask(receivePin);\t\t\t// get receive pin's ports and bitmask \n\trPort = digitalPinToPort(receivePin);\n\trReg = portModeRegister(rPort);\n\trIn  = portInputRegister(rPort);\n   \trOut = portOutputRegister(rPort);\n\t\n\t// get pin mapping and port for receive Pin - from digital pin functions in Wiring.c\n    noInterrupts();\n\t*sReg |= sBit;              // set sendpin to OUTPUT \n    interrupts();\n\tleastTotal = 0x0FFFFFFFL;   // input large value for autocalibrate begin\n\tlastCal = millis();         // set millis for start\n}\n\n// Public Methods //////////////////////////////////////////////////////////////\n// Functions available in Wiring sketches, this library, and other libraries\n\nlong CapSense::capSense(uint8_t samples)\n{\n\ttotal = 0;\n\tif (samples == 0) return 0;\n\tif (error < 0) return -1;            // bad pin\n\n\n\tfor (uint8_t i = 0; i < samples; i++) {    // loop for samples parameter - simple lowpass filter\n\t\tif (SenseOneCycle() < 0)  return -2;   // variable over timeout\n}\n\n\t\t// only calibrate if time is greater than CS_AutocaL_Millis and total is less than 10% of baseline\n\t\t// this is an attempt to keep from calibrating when the sensor is seeing a \"touched\" signal\n\n\t\tif ( (millis() - lastCal > CS_AutocaL_Millis) && abs(total  - leastTotal) < (int)(.10 * (float)leastTotal) ) {\n\n\t\t\t// Serial.println();               // debugging\n\t\t\t// Serial.println(\"auto-calibrate\");\n\t\t\t// Serial.println();\n\t\t\t// delay(2000); */\n\n\t\t\tleastTotal = 0x0FFFFFFFL;          // reset for \"autocalibrate\"\n\t\t\tlastCal = millis();\n\t\t}\n\t\t/*else{                                // debugging \n\t\t\tSerial.print(\"  total =  \");\n\t\t\tSerial.print(total);\n\n\t\t\tSerial.print(\"   leastTotal  =  \");\n\t\t\tSerial.println(leastTotal);\n\n\t\t\tSerial.print(\"total - leastTotal =  \");\n\t\t\tx = total - leastTotal ;\n\t\t\tSerial.print(x);\n\t\t\tSerial.print(\"     .1 * leastTotal = \");\n\t\t\tx = (int)(.1 * (float)leastTotal);\n\t\t\tSerial.println(x);   \n\t\t} */\n\n\t// routine to subtract baseline (non-sensed capacitance) from sensor return\n\tif (total < leastTotal) leastTotal = total;                 // set floor value to subtract from sensed value         \n\treturn(total - leastTotal);\n\n}\n\nlong CapSense::capSenseRaw(uint8_t samples)\n{\n\ttotal = 0;\n\tif (samples == 0) return 0;\n\tif (error < 0) return -1;                  // bad pin - this appears not to work\n\n\tfor (uint8_t i = 0; i < samples; i++) {    // loop for samples parameter - simple lowpass filter\n\t\tif (SenseOneCycle() < 0)  return -2;   // variable over timeout\n\t}\n\n\treturn total;\n}\n\n\nvoid CapSense::reset_CS_AutoCal(void){\n\tleastTotal = 0x0FFFFFFFL;\n}\n\nvoid CapSense::set_CS_AutocaL_Millis(unsigned long autoCal_millis){\n\tCS_AutocaL_Millis = autoCal_millis;\n}\n\nvoid CapSense::set_CS_Timeout_Millis(unsigned long timeout_millis){\n\tCS_Timeout_Millis = (timeout_millis * (float)loopTimingFactor * (float)F_CPU) / 16000000;  // floats to deal with large numbers\n}\n\n// Private Methods /////////////////////////////////////////////////////////////\n// Functions only available to other functions in this library\n\nint CapSense::SenseOneCycle(void)\n{\n    noInterrupts();\n\t*sOut &= ~sBit;        // set Send Pin Register low\n\t\n\t*rReg &= ~rBit;        // set receivePin to input\n\t*rOut &= ~rBit;        // set receivePin Register low to make sure pullups are off\n\t\n\t*rReg |= rBit;         // set pin to OUTPUT - pin is now LOW AND OUTPUT\n\t*rReg &= ~rBit;        // set pin to INPUT \n\n\t*sOut |= sBit;         // set send Pin High\n    interrupts();\n\n\twhile ( !(*rIn & rBit)  && (total < CS_Timeout_Millis) ) {  // while receive pin is LOW AND total is positive value\n\t\ttotal++;\n\t}\n    \n\tif (total > CS_Timeout_Millis) {\n\t\treturn -2;         //  total variable over timeout\n\t}\n   \n\t// set receive pin HIGH briefly to charge up fully - because the while loop above will exit when pin is ~ 2.5V \n    noInterrupts();\n\t*rOut  |= rBit;        // set receive pin HIGH - turns on pullup \n\t*rReg |= rBit;         // set pin to OUTPUT - pin is now HIGH AND OUTPUT\n\t*rReg &= ~rBit;        // set pin to INPUT \n\t*rOut  &= ~rBit;       // turn off pullup\n\n\t*sOut &= ~sBit;        // set send Pin LOW\n    interrupts();\n\n\twhile ( (*rIn & rBit) && (total < CS_Timeout_Millis) ) {  // while receive pin is HIGH  AND total is less than timeout\n\t\ttotal++;\n\t}\n\t// Serial.println(total);\n\n\tif (total >= CS_Timeout_Millis) {\n\t\treturn -2;     // total variable over timeout\n\t} else {\n\t\treturn 1;\n\t}\n}\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/CapSense/CapSense.h",
    "content": "/*\n  CapacitiveSense.h v.04 - Capacitive Sensing Library for 'duino / Wiring\n  Copyright (c) 2008 Paul Bagder  All rights reserved.\n  Version 04 by Paul Stoffregen - Arduino 1.0 compatibility, issue 146 fix\n  vim: set ts=4:\n*/\n\n// ensure this library description is only included once\n#ifndef CapSense_h\n#define CapSense_h\n\n#if ARDUINO >= 100\n#include \"Arduino.h\"\n#else\n#include \"WProgram.h\"\n#endif\n\n// library interface description\nclass CapSense\n{\n  // user-accessible \"public\" interface\n  public:\n  // methods\n\tCapSense(uint8_t sendPin, uint8_t receivePin);\n\tlong capSenseRaw(uint8_t samples);\n\tlong capSense(uint8_t samples);\n\tvoid set_CS_Timeout_Millis(unsigned long timeout_millis);\n\tvoid reset_CS_AutoCal();\n\tvoid set_CS_AutocaL_Millis(unsigned long autoCal_millis);\n  // library-accessible \"private\" interface\n  private:\n  // variables\n\tint error;\n\tunsigned long  leastTotal;\n\tunsigned int   loopTimingFactor;\n\tunsigned long  CS_Timeout_Millis;\n\tunsigned long  CS_AutocaL_Millis;\n\tunsigned long  lastCal;\n\tunsigned long  total;\n\tuint8_t sBit;   // send pin's ports and bitmask\n\tvolatile uint8_t *sReg;\n\tvolatile uint8_t *sOut;\n\tuint8_t rBit;    // receive pin's ports and bitmask \n\tvolatile uint8_t *rReg;\n\tvolatile uint8_t *rIn;\n\tvolatile uint8_t *rOut;\n  // methods\n\tint SenseOneCycle(void);\n};\n\n#endif\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/TimedAction/TimedAction.cpp",
    "content": "#include \"TimedAction.h\"\n\n/*\n|| <<constructor>>\n*/\nTimedAction::TimedAction(unsigned long intervl,void (*function)()){\n    active = true;\n\tprevious = 0;\n\tinterval = intervl;\n\texecute = function;\n}\n\n/*\n|| <<constructor>>\n*/\nTimedAction::TimedAction(unsigned long prev,unsigned long intervl,void (*function)()){\n    active = true;\n\tprevious = prev;\n\tinterval = intervl;\n\texecute = function;\n}\n\nvoid TimedAction::reset(){\n    previous = millis();\n}\n\nvoid TimedAction::disable(){\n    active = false;\n}\n\nvoid TimedAction::enable(){\n\tactive = true;\n}\n\nvoid TimedAction::check(){\n  if ( active && (millis()-previous >= interval) ) {\n    previous = millis();\n    execute();\n  }\n}\n\nvoid TimedAction::setInterval( unsigned long intervl){\n\tinterval = intervl;\n}"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/TimedAction/TimedAction.h",
    "content": "/*\n||\n|| @file \tTimedAction.cpp\n|| @version\t1.6\n|| @author\tAlexander Brevig\n|| @contact\talexanderbrevig@gmail.com\n||\n|| @description\n|| | Provide an easy way of triggering functions at a set interval\n|| #\n||\n|| @license\n|| | This library is free software; you can redistribute it and/or\n|| | modify it under the terms of the GNU Lesser General Public\n|| | License as published by the Free Software Foundation; version\n|| | 2.1 of the License.\n|| |\n|| | This library is distributed in the hope that it will be useful,\n|| | but WITHOUT ANY WARRANTY; without even the implied warranty of\n|| | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n|| | Lesser General Public License for more details.\n|| |\n|| | You should have received a copy of the GNU Lesser General Public\n|| | License along with this library; if not, write to the Free Software\n|| | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n|| #\n||\n*/\n\n#ifndef TIMEDACTION_H\n#define TIMEDACTION_H\n\n#include \"WProgram.h\"\n\n#define NO_PREDELAY 0\n\nclass TimedAction {\n  \n  public:\n    TimedAction(unsigned long interval,void (*function)());\n    TimedAction(unsigned long prev,unsigned long interval,void (*function)());\n\t\n\tvoid reset();\n\tvoid disable();\n\tvoid enable();\n\tvoid check();\n\t\n\tvoid setInterval( unsigned long interval );\n\n  private: \n    bool active;\n    unsigned long previous;\n    unsigned long interval;\n    void (*execute)();\n\t\t\n};\n\n#endif\n\n/*\n|| @changelog\n|| | 1.6 2010-10-08 - Alexander Brevig : Changed datatype of interval from unsigned int to unsigned long\n|| | 1.5 2009-10-25 - Alexander Brevig : Added setInterval , requested by: Boris Neumann\n|| | 1.4 2009-05-06 - Alexander Brevig : Added reset()\n|| | 1.3 2009-04-16 - Alexander Brevig : Added disable() and enable(), requested by: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?action=viewprofile;username=ryno\n|| | 1.2 2009-04-13 - Alexander Brevig : Added a constructor\n|| | 1.1 2009-04-08 - Alexander Brevig : Added an example that demonstrates three arduino examples at once\n|| | 1.0 2009-03-23 - Alexander Brevig : Initial Release\n|| #\n*/"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/USB_Host_Shield/Max3421e.cpp",
    "content": "/*\n * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com\n * MAX3421E USB host controller support\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the authors nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n/* MAX3421E USB host controller support */\n\n#include \"Max3421e.h\"\n// #include \"Max3421e_constants.h\"\n\nstatic byte vbusState;\n\n/* Functions    */\n\n#define INT\t\tPE6\n#define INT_PORT\tPORTE\n#define INT_DDR\t\tDDRE\n#define INT_PIN\t\tPINE\n\n#define RST\t\tPJ2\n#define RST_PORT\tPORTJ\n#define RST_DDR\t\tDDRJ\n#define RST_PIN\t\tPINJ\n\n#define GPX\t\tPJ3\n#define GPX_PORT\tPORTJ\n#define GPX_DDR\t\tDDRJ\n#define GPX_PIN\t\tPINJ\n\n\nvoid MAX3421E::setRST(uint8_t val)\n{\n\tif (val == LOW)\n\t\tRST_PORT &= ~_BV(RST);\n\telse\n\t\tRST_PORT |= _BV(RST);\n}\n\nuint8_t MAX3421E::readINT(void)\n{\n\treturn INT_PIN & _BV(INT) ? HIGH : LOW;\n}\n\nuint8_t MAX3421E::readGPX(void)\n{\n\t// return GPX_PIN & _BV(GPX) ? HIGH : LOW;\n\treturn LOW;\n}\n\n\nvoid MAX3421E::pinInit(void)\n{\n\tINT_DDR &= ~_BV(INT);\n\tRST_DDR |= _BV(RST);\n\tdigitalWrite(MAX_SS,HIGH);   \n\tsetRST(HIGH);\n}\n\n\n/* Constructor */\nMAX3421E::MAX3421E()\n{\n    spi_init();  \n\tpinInit();\n}\n\nbyte MAX3421E::getVbusState( void )\n{ \n    return( vbusState );\n}\n/* initialization */\n//void MAX3421E::init()\n//{\n//    /* setup pins */\n//    pinMode( MAX_INT, INPUT);\n//    pinMode( MAX_GPX, INPUT );\n//    pinMode( MAX_SS, OUTPUT );\n//    //pinMode( BPNT_0, OUTPUT );\n//    //pinMode( BPNT_1, OUTPUT );\n//    //digitalWrite( BPNT_0, LOW );\n//    //digitalWrite( BPNT_1, LOW );\n//    Deselect_MAX3421E;              \n//    pinMode( MAX_RESET, OUTPUT );\n//    digitalWrite( MAX_RESET, HIGH );  //release MAX3421E from reset\n//}\n//byte MAX3421E::getVbusState( void )\n//{\n//    return( vbusState );\n//}\n//void MAX3421E::toggle( byte pin )\n//{\n//    digitalWrite( pin, HIGH );\n//    digitalWrite( pin, LOW );\n//}\n/* Single host register write   */\nvoid MAX3421E::regWr( byte reg, byte val)\n{\n      digitalWrite(MAX_SS,LOW);\n      SPDR = ( reg | 0x02 );\n      while(!( SPSR & ( 1 << SPIF )));\n      SPDR = val;\n      while(!( SPSR & ( 1 << SPIF )));\n      digitalWrite(MAX_SS,HIGH);\n      return;\n}\n/* multiple-byte write */\n/* returns a pointer to a memory position after last written */\nchar * MAX3421E::bytesWr( byte reg, byte nbytes, char * data )\n{\n    digitalWrite(MAX_SS,LOW);\n    SPDR = ( reg | 0x02 );\n    while( nbytes-- ) {\n      while(!( SPSR & ( 1 << SPIF )));  //check if previous byte was sent\n      SPDR = ( *data );               // send next data byte\n      data++;                         // advance data pointer\n    }\n    while(!( SPSR & ( 1 << SPIF )));\n    digitalWrite(MAX_SS,HIGH);\n    return( data );\n}\n/* GPIO write. GPIO byte is split between 2 registers, so two writes are needed to write one byte */\n/* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */\n/* upper 4 bits of IOPINS1, IOPINS2 are read-only, so no masking is necessary */\nvoid MAX3421E::gpioWr( byte val )\n{\n    regWr( rIOPINS1, val );\n    val = val >>4;\n    regWr( rIOPINS2, val );\n    \n    return;     \n}\n/* Single host register read        */\nbyte MAX3421E::regRd( byte reg )    \n{\n  byte tmp;\n    digitalWrite(MAX_SS,LOW);\n    SPDR = reg;\n    while(!( SPSR & ( 1 << SPIF )));\n    SPDR = 0; //send empty byte\n    while(!( SPSR & ( 1 << SPIF )));\n    digitalWrite(MAX_SS,HIGH); \n    return( SPDR );\n}\n/* multiple-bytes register read                             */\n/* returns a pointer to a memory position after last read   */\nchar * MAX3421E::bytesRd ( byte reg, byte nbytes, char  * data )\n{\n    digitalWrite(MAX_SS,LOW);\n    SPDR = reg;      \n    while(!( SPSR & ( 1 << SPIF )));    //wait\n    while( nbytes ) {\n      SPDR = 0; //send empty byte\n      nbytes--;\n      while(!( SPSR & ( 1 << SPIF )));\n      *data = SPDR;\n      data++;\n    }\n    digitalWrite(MAX_SS,HIGH);\n    return( data );   \n}\n/* GPIO read. See gpioWr for explanation */\n/* GPIN pins are in high nibbles of IOPINS1, IOPINS2    */\nbyte MAX3421E::gpioRd( void )\n{\n byte tmpbyte = 0;\n    tmpbyte = regRd( rIOPINS2 );            //pins 4-7\n    tmpbyte &= 0xf0;                        //clean lower nibble\n    tmpbyte |= ( regRd( rIOPINS1 ) >>4 ) ;  //shift low bits and OR with upper from previous operation. Upper nibble zeroes during shift, at least with this compiler\n    return( tmpbyte );\n}\n/* reset MAX3421E using chip reset bit. SPI configuration is not affected   */\nboolean MAX3421E::reset()\n{\n  byte tmp = 0;\n    regWr( rUSBCTL, bmCHIPRES );                        //Chip reset. This stops the oscillator\n    regWr( rUSBCTL, 0x00 );                             //Remove the reset\n    while(!(regRd( rUSBIRQ ) & bmOSCOKIRQ )) {          //wait until the PLL is stable\n        tmp++;                                          //timeout after 256 attempts\n        if( tmp == 0 ) {\n            return( false );\n        }\n    }\n    return( true );\n}\n/* turn USB power on/off                                                */\n/* does nothing, returns TRUE. Left for compatibility with old sketches               */\n/* will be deleted eventually                                           */\n///* ON pin of VBUS switch (MAX4793 or similar) is connected to GPOUT7    */\n///* OVERLOAD pin of Vbus switch is connected to GPIN7                    */\n///* OVERLOAD state low. NO OVERLOAD or VBUS OFF state high.              */\nboolean MAX3421E::vbusPwr ( boolean action )\n{\n//  byte tmp;\n//    tmp = regRd( rIOPINS2 );                //copy of IOPINS2\n//    if( action ) {                          //turn on by setting GPOUT7\n//        tmp |= bmGPOUT7;\n//    }\n//    else {                                  //turn off by clearing GPOUT7\n//        tmp &= ~bmGPOUT7;\n//    }\n//    regWr( rIOPINS2, tmp );                 //send GPOUT7\n//    if( action ) {\n//        delay( 60 );\n//    }\n//    if (( regRd( rIOPINS2 ) & bmGPIN7 ) == 0 ) {     // check if overload is present. MAX4793 /FLAG ( pin 4 ) goes low if overload\n//        return( false );\n//    }                      \n    return( true );                                             // power on/off successful                       \n}\n/* probe bus to determine device presense and speed and switch host to this speed */\nvoid MAX3421E::busprobe( void )\n{\n byte bus_sample;\n    bus_sample = regRd( rHRSL );            //Get J,K status\n    bus_sample &= ( bmJSTATUS|bmKSTATUS );      //zero the rest of the byte\n    switch( bus_sample ) {                          //start full-speed or low-speed host \n        case( bmJSTATUS ):\n            if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) {\n                regWr( rMODE, MODE_FS_HOST );       //start full-speed host\n                vbusState = FSHOST;\n            }\n            else {\n                regWr( rMODE, MODE_LS_HOST);        //start low-speed host\n                vbusState = LSHOST;\n            }\n            break;\n        case( bmKSTATUS ):\n            if(( regRd( rMODE ) & bmLOWSPEED ) == 0 ) {\n                regWr( rMODE, MODE_LS_HOST );       //start low-speed host\n                vbusState = LSHOST;\n            }\n            else {\n                regWr( rMODE, MODE_FS_HOST );       //start full-speed host\n                vbusState = FSHOST;\n            }\n            break;\n        case( bmSE1 ):              //illegal state\n            vbusState = SE1;\n            break;\n        case( bmSE0 ):              //disconnected state\n\t\tregWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST|bmSEPIRQ);\n            vbusState = SE0;\n            break;\n        }//end switch( bus_sample )\n}\n/* MAX3421E initialization after power-on   */\nvoid MAX3421E::powerOn()\n{\n    /* Configure full-duplex SPI, interrupt pulse   */\n    regWr( rPINCTL,( bmFDUPSPI + bmINTLEVEL + bmGPXB ));    //Full-duplex SPI, level interrupt, GPX\n    if( reset() == false ) {                                //stop/start the oscillator\n        Serial.println(\"Error: OSCOKIRQ failed to assert\");\n    }\n\n    /* configure host operation */\n    regWr( rMODE, bmDPPULLDN|bmDMPULLDN|bmHOST|bmSEPIRQ );      // set pull-downs, Host, Separate GPIN IRQ on GPX\n    regWr( rHIEN, bmCONDETIE|bmFRAMEIE );                                             //connection detection\n    /* check if device is connected */\n    regWr( rHCTL,bmSAMPLEBUS );                                             // sample USB bus\n    while(!(regRd( rHCTL ) & bmSAMPLEBUS ));                                //wait for sample operation to finish\n    busprobe();                                                             //check if anything is connected\n    regWr( rHIRQ, bmCONDETIRQ );                                            //clear connection detect interrupt                 \n    regWr( rCPUCTL, 0x01 );                                                 //enable interrupt pin\n}\n/* MAX3421 state change task and interrupt handler */\nbyte MAX3421E::Task( void )\n{\n byte rcode = 0;\n byte pinvalue;\n    //Serial.print(\"Vbus state: \");\n    //Serial.println( vbusState, HEX );\n pinvalue = readINT();\n if( pinvalue  == LOW ) {\n        rcode = IntHandler();\n    }\n    pinvalue = readGPX();\n    if( pinvalue == LOW ) {\n        GpxHandler();\n    }\n//    usbSM();                                //USB state machine                            \n    return( rcode );   \n}   \nbyte MAX3421E::IntHandler()\n{\n byte HIRQ;\n byte HIRQ_sendback = 0x00;\n    HIRQ = regRd( rHIRQ );                  //determine interrupt source\n    //if( HIRQ & bmFRAMEIRQ ) {               //->1ms SOF interrupt handler\n    //    HIRQ_sendback |= bmFRAMEIRQ;\n    //}//end FRAMEIRQ handling\n    if( HIRQ & bmCONDETIRQ ) {\n        busprobe();\n        HIRQ_sendback |= bmCONDETIRQ;\n    }\n    /* End HIRQ interrupts handling, clear serviced IRQs    */\n    regWr( rHIRQ, HIRQ_sendback );\n    return( HIRQ_sendback );\n}\nbyte MAX3421E::GpxHandler()\n{\n byte GPINIRQ = regRd( rGPINIRQ );          //read GPIN IRQ register\n//    if( GPINIRQ & bmGPINIRQ7 ) {            //vbus overload\n//        vbusPwr( OFF );                     //attempt powercycle\n//        delay( 1000 );\n//        vbusPwr( ON );\n//        regWr( rGPINIRQ, bmGPINIRQ7 );\n//    }       \n    return( GPINIRQ );\n}\n\n//void MAX3421E::usbSM( void )                //USB state machine\n//{\n//    \n//\n//}\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/USB_Host_Shield/Max3421e.h",
    "content": "/*\n * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com\n * MAX3421E USB host controller support\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the authors nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n/* MAX3421E functions */\n#ifndef _MAX3421E_H_\n#define _MAX3421E_H_\n\n\n//#include <Spi.h>\n//#include <WProgram.h>\n#include \"WProgram.h\"\n#include \"Max3421e_constants.h\"\n\nclass MAX3421E /* : public SPI */ {\n    // byte vbusState;\n    public:\n        MAX3421E( void );\n        byte getVbusState( void );\n//        void toggle( byte pin );\n        static void regWr( byte, byte );\n        char * bytesWr( byte, byte, char * );\n        static void gpioWr( byte );\n        byte regRd( byte );\n        char * bytesRd( byte, byte, char * );\n        byte gpioRd( void );\n        boolean reset();\n        boolean vbusPwr ( boolean );\n        void busprobe( void );\n        void powerOn();\n        byte IntHandler();\n        byte GpxHandler();\n        byte Task();\n    private:\n\tstatic void pinInit(void);\n\tstatic void setRST(uint8_t val);\n\tstatic uint8_t readINT(void);\n\tstatic uint8_t readGPX(void);\n\n      static void spi_init() {\n        uint8_t tmp;\n        // initialize SPI pins\n        pinMode(SCK_PIN, OUTPUT);\n        pinMode(MOSI_PIN, OUTPUT);\n        pinMode(MISO_PIN, INPUT);\n        pinMode(SS_PIN, OUTPUT);\n        /* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */\n        SPCR = 0x50;\n        SPSR = 0x01;\n        /**/\n        tmp = SPSR;\n        tmp = SPDR;\n    }\n//        void init();\n    friend class Max_LCD;        \n};\n\n\n\n\n#endif //_MAX3421E_H_\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/USB_Host_Shield/Max3421e_constants.h",
    "content": "/*\n * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com\n * MAX3421E USB host controller support\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the authors nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n/* MAX3421E register/bit names and bitmasks */\n\n#ifndef _MAX3421Econstants_h_\n#define _MAX3421Econstants_h_\n\n/* SPI pins for diffrent Arduinos */\n\n#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__)\n  #define SCK_PIN   52\n  #define MISO_PIN  50\n  #define MOSI_PIN  51\n  #define SS_PIN    53\n#endif\n#if  defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)\n  #define SCK_PIN   13\n  #define MISO_PIN  12\n  #define MOSI_PIN  11\n  #define SS_PIN    10\n#endif\n\n#define MAX_SS    53\n#define MAX_INT   9\n#define MAX_GPX   8\n#define MAX_RESET 7\n\n/* \"Breakpoint\" pins for debugging */\n//#define BPNT_0      3\n//#define BPNT_1      2\n     \n//#define Select_MAX3421E     digitalWrite(MAX_SS,LOW)\n//#define Deselect_MAX3421E   digitalWrite(MAX_SS,HIGH)\n\n/* */\n\n#define ON  true\n#define OFF false\n\n/* VBUS states */\n#define SE0     0\n#define SE1     1\n#define FSHOST  2\n#define LSHOST  3\n\n/* MAX3421E command byte format: rrrrr0wa where 'r' is register number  */\n//\n// MAX3421E Registers in HOST mode. \n//\n#define rRCVFIFO    0x08    //1<<3\n#define rSNDFIFO    0x10    //2<<3\n#define rSUDFIFO    0x20    //4<<3\n#define rRCVBC      0x30    //6<<3\n#define rSNDBC      0x38    //7<<3\n\n#define rUSBIRQ     0x68    //13<<3\n/* USBIRQ Bits  */\n#define bmVBUSIRQ   0x40    //b6\n#define bmNOVBUSIRQ 0x20    //b5\n#define bmOSCOKIRQ  0x01    //b0\n\n#define rUSBIEN     0x70    //14<<3\n/* USBIEN Bits  */\n#define bmVBUSIE    0x40    //b6\n#define bmNOVBUSIE  0x20    //b5\n#define bmOSCOKIE   0x01    //b0\n\n#define rUSBCTL     0x78    //15<<3\n/* USBCTL Bits  */\n#define bmCHIPRES   0x20    //b5\n#define bmPWRDOWN   0x10    //b4\n\n#define rCPUCTL     0x80    //16<<3\n/* CPUCTL Bits  */\n#define bmPUSLEWID1 0x80    //b7\n#define bmPULSEWID0 0x40    //b6\n#define bmIE        0x01    //b0\n\n#define rPINCTL     0x88    //17<<3\n/* PINCTL Bits  */\n#define bmFDUPSPI   0x10    //b4\n#define bmINTLEVEL  0x08    //b3\n#define bmPOSINT    0x04    //b2\n#define bmGPXB      0x02    //b1\n#define bmGPXA      0x01    //b0\n// GPX pin selections\n#define GPX_OPERATE 0x00\n#define GPX_VBDET   0x01\n#define GPX_BUSACT  0x02\n#define GPX_SOF     0x03\n\n#define rREVISION   0x90    //18<<3\n\n#define rIOPINS1    0xa0    //20<<3\n\n/* IOPINS1 Bits */\n#define bmGPOUT0    0x01\n#define bmGPOUT1    0x02\n#define bmGPOUT2    0x04\n#define bmGPOUT3    0x08\n#define bmGPIN0     0x10\n#define bmGPIN1     0x20\n#define bmGPIN2     0x40\n#define bmGPIN3     0x80\n\n#define rIOPINS2    0xa8    //21<<3\n/* IOPINS2 Bits */\n#define bmGPOUT4    0x01\n#define bmGPOUT5    0x02\n#define bmGPOUT6    0x04\n#define bmGPOUT7    0x08\n#define bmGPIN4     0x10\n#define bmGPIN5     0x20\n#define bmGPIN6     0x40\n#define bmGPIN7     0x80\n\n#define rGPINIRQ    0xb0    //22<<3\n/* GPINIRQ Bits */\n#define bmGPINIRQ0 0x01\n#define bmGPINIRQ1 0x02\n#define bmGPINIRQ2 0x04\n#define bmGPINIRQ3 0x08\n#define bmGPINIRQ4 0x10\n#define bmGPINIRQ5 0x20\n#define bmGPINIRQ6 0x40\n#define bmGPINIRQ7 0x80\n\n#define rGPINIEN    0xb8    //23<<3\n/* GPINIEN Bits */\n#define bmGPINIEN0 0x01\n#define bmGPINIEN1 0x02\n#define bmGPINIEN2 0x04\n#define bmGPINIEN3 0x08\n#define bmGPINIEN4 0x10\n#define bmGPINIEN5 0x20\n#define bmGPINIEN6 0x40\n#define bmGPINIEN7 0x80\n\n#define rGPINPOL    0xc0    //24<<3\n/* GPINPOL Bits */\n#define bmGPINPOL0 0x01\n#define bmGPINPOL1 0x02\n#define bmGPINPOL2 0x04\n#define bmGPINPOL3 0x08\n#define bmGPINPOL4 0x10\n#define bmGPINPOL5 0x20\n#define bmGPINPOL6 0x40\n#define bmGPINPOL7 0x80\n\n#define rHIRQ       0xc8    //25<<3\n/* HIRQ Bits */\n#define bmBUSEVENTIRQ   0x01   // indicates BUS Reset Done or BUS Resume     \n#define bmRWUIRQ        0x02\n#define bmRCVDAVIRQ     0x04\n#define bmSNDBAVIRQ     0x08\n#define bmSUSDNIRQ      0x10\n#define bmCONDETIRQ     0x20\n#define bmFRAMEIRQ      0x40\n#define bmHXFRDNIRQ     0x80\n\n#define rHIEN       0xd0    //26<<3\n/* HIEN Bits */\n#define bmBUSEVENTIE    0x01\n#define bmRWUIE         0x02\n#define bmRCVDAVIE      0x04\n#define bmSNDBAVIE      0x08\n#define bmSUSDNIE       0x10\n#define bmCONDETIE      0x20\n#define bmFRAMEIE       0x40\n#define bmHXFRDNIE      0x80\n\n#define rMODE       0xd8    //27<<3\n/* MODE Bits */\n#define bmHOST          0x01\n#define bmLOWSPEED      0x02\n#define bmHUBPRE        0x04\n#define bmSOFKAENAB     0x08\n#define bmSEPIRQ        0x10\n#define bmDELAYISO      0x20\n#define bmDMPULLDN      0x40\n#define bmDPPULLDN      0x80\n\n#define rPERADDR    0xe0    //28<<3\n\n#define rHCTL       0xe8    //29<<3\n/* HCTL Bits */\n#define bmBUSRST        0x01\n#define bmFRMRST        0x02\n#define bmSAMPLEBUS     0x04\n#define bmSIGRSM        0x08\n#define bmRCVTOG0       0x10\n#define bmRCVTOG1       0x20\n#define bmSNDTOG0       0x40\n#define bmSNDTOG1       0x80\n\n#define rHXFR       0xf0    //30<<3\n/* Host transfer token values for writing the HXFR register (R30)   */\n/* OR this bit field with the endpoint number in bits 3:0               */\n#define tokSETUP  0x10  // HS=0, ISO=0, OUTNIN=0, SETUP=1\n#define tokIN     0x00  // HS=0, ISO=0, OUTNIN=0, SETUP=0\n#define tokOUT    0x20  // HS=0, ISO=0, OUTNIN=1, SETUP=0\n#define tokINHS   0x80  // HS=1, ISO=0, OUTNIN=0, SETUP=0\n#define tokOUTHS  0xA0  // HS=1, ISO=0, OUTNIN=1, SETUP=0 \n#define tokISOIN  0x40  // HS=0, ISO=1, OUTNIN=0, SETUP=0\n#define tokISOOUT 0x60  // HS=0, ISO=1, OUTNIN=1, SETUP=0\n\n#define rHRSL       0xf8    //31<<3\n/* HRSL Bits */\n#define bmRCVTOGRD  0x10\n#define bmSNDTOGRD  0x20\n#define bmKSTATUS   0x40\n#define bmJSTATUS   0x80\n#define bmSE0       0x00    //SE0 - disconnect state\n#define bmSE1       0xc0    //SE1 - illegal state       \n/* Host error result codes, the 4 LSB's in the HRSL register */\n#define hrSUCCESS   0x00\n#define hrBUSY      0x01\n#define hrBADREQ    0x02\n#define hrUNDEF     0x03\n#define hrNAK       0x04\n#define hrSTALL     0x05\n#define hrTOGERR    0x06\n#define hrWRONGPID  0x07\n#define hrBADBC     0x08\n#define hrPIDERR    0x09\n#define hrPKTERR    0x0A\n#define hrCRCERR    0x0B\n#define hrKERR      0x0C\n#define hrJERR      0x0D\n#define hrTIMEOUT   0x0E\n#define hrBABBLE    0x0F\n\n#define MODE_FS_HOST    (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB)\n#define MODE_LS_HOST    (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB)\n\n\n#endif //_MAX3421Econstants_h_\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/USB_Host_Shield/Max_LCD.cpp",
    "content": "/*\n * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com\n * MAX3421E USB host controller support\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the authors nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n//this code is heavily borrowed from official Arduino source v.0017\n// link to original http://code.google.com/p/arduino/source/browse/trunk/hardware/libraries/LiquidCrystal/LiquidCrystal.cpp\n#include \"Max_LCD.h\"\n#include \"Max3421e.h\"\n\n#include <stdio.h>\n#include <string.h>\n#include <inttypes.h>\n#include \"WProgram.h\"\n\n// When the display powers up, it is configured as follows:\n//\n// 1. Display clear\n// 2. Function set:\n//    DL = 1; 8-bit interface data\n//    N = 0; 1-line display\n//    F = 0; 5x8 dot character font\n// 3. Display on/off control:\n//    D = 0; Display off\n//    C = 0; Cursor off\n//    B = 0; Blinking off\n// 4. Entry mode set:\n//    I/D = 1; Increment by 1\n//    S = 0; No shift\n//\n// Note, however, that resetting the Arduino doesn't reset the LCD, so we\n// can't assume that it's in that state when a sketch starts\n\n// pin definition and set/clear\n\n#define RS  0x04    // RS pin\n#define E   0x08    // E pin\n\n#define SET_RS  lcdPins |= RS\n#define CLR_RS  lcdPins &= ~RS\n#define SET_E   lcdPins |= E\n#define CLR_E   lcdPins &= ~E\n\n#define SENDlcdPins()   MAX3421E::gpioWr( lcdPins )\n    \n#define LCD_sendcmd(a)  {   CLR_RS;             \\\n                            sendbyte(a);    \\\n                        }\n \n#define LCD_sendchar(a) {   SET_RS;             \\\n                            sendbyte(a);    \\\n                        }\n                            \nstatic byte lcdPins;    //copy of LCD pins\n\nMax_LCD::Max_LCD()\n{\n    lcdPins = 0;\n}\n\n\nvoid Max_LCD::init()\n{\n    _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;\n \n //   MAX3421E::gpioWr(0x55);\n \n  begin(16, 1);  \n}\n\nvoid Max_LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {\n  if (lines > 1) {\n    _displayfunction |= LCD_2LINE;\n  }\n  _numlines = lines;\n  _currline = 0;\n\n  // for some 1 line displays you can select a 10 pixel high font\n  if ((dotsize != 0) && (lines == 1)) {\n    _displayfunction |= LCD_5x10DOTS;\n  }\n\n  // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!\n  // according to datasheet, we need at least 40ms after power rises above 2.7V\n  // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50\n  delayMicroseconds(50000);\n  lcdPins = 0x30;\n  SET_E;\n  SENDlcdPins();\n  CLR_E;\n  SENDlcdPins();\n  delayMicroseconds(10000); // wait min 4.1ms\n  //second try\n  SET_E;\n  SENDlcdPins();\n  CLR_E;\n  SENDlcdPins();\n  delayMicroseconds(10000); // wait min 4.1ms\n  // third go!\n  SET_E;\n  SENDlcdPins();\n  CLR_E;\n  SENDlcdPins();\n  delayMicroseconds(10000);\n  // finally, set to 4-bit interface\n    lcdPins = 0x20;\n    //SET_RS;\n    SET_E;\n    SENDlcdPins();\n    //CLR_RS;\n    CLR_E;\n    SENDlcdPins();\n    delayMicroseconds(10000);\n  // finally, set # lines, font size, etc.\n  command(LCD_FUNCTIONSET | _displayfunction);  \n\n  // turn the display on with no cursor or blinking default\n  _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;  \n  display();\n\n  // clear it off\n  clear();\n\n  // Initialize to default text direction (for romance languages)\n  _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;\n  // set the entry mode\n  command(LCD_ENTRYMODESET | _displaymode);\n}\n\n/********** high level commands, for the user! */\nvoid Max_LCD::clear()\n{\n  command(LCD_CLEARDISPLAY);  // clear display, set cursor position to zero\n  delayMicroseconds(2000);  // this command takes a long time!\n}\n\nvoid Max_LCD::home()\n{\n  command(LCD_RETURNHOME);  // set cursor position to zero\n  delayMicroseconds(2000);  // this command takes a long time!\n}\n\nvoid Max_LCD::setCursor(uint8_t col, uint8_t row)\n{\n  int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };\n  if ( row > _numlines ) {\n    row = _numlines-1;    // we count rows starting w/0\n  }\n \n  command(LCD_SETDDRAMADDR | (col + row_offsets[row]));\n}\n\n// Turn the display on/off (quickly)\nvoid Max_LCD::noDisplay() {\n  _displaycontrol &= ~LCD_DISPLAYON;\n  command(LCD_DISPLAYCONTROL | _displaycontrol);\n}\nvoid Max_LCD::display() {\n  _displaycontrol |= LCD_DISPLAYON;\n  command(LCD_DISPLAYCONTROL | _displaycontrol);\n}\n\n// Turns the underline cursor on/off\nvoid Max_LCD::noCursor() {\n  _displaycontrol &= ~LCD_CURSORON;\n  command(LCD_DISPLAYCONTROL | _displaycontrol);\n}\nvoid Max_LCD::cursor() {\n  _displaycontrol |= LCD_CURSORON;\n  command(LCD_DISPLAYCONTROL | _displaycontrol);\n}\n\n\n// Turn on and off the blinking cursor\nvoid Max_LCD::noBlink() {\n  _displaycontrol &= ~LCD_BLINKON;\n  command(LCD_DISPLAYCONTROL | _displaycontrol);\n}\nvoid Max_LCD::blink() {\n  _displaycontrol |= LCD_BLINKON;\n  command(LCD_DISPLAYCONTROL | _displaycontrol);\n}\n\n// These commands scroll the display without changing the RAM\nvoid Max_LCD::scrollDisplayLeft(void) {\n  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);\n}\nvoid Max_LCD::scrollDisplayRight(void) {\n  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);\n}\n\n// This is for text that flows Left to Right\nvoid Max_LCD::leftToRight(void) {\n  _displaymode |= LCD_ENTRYLEFT;\n  command(LCD_ENTRYMODESET | _displaymode);\n}\n\n// This is for text that flows Right to Left\nvoid Max_LCD::rightToLeft(void) {\n  _displaymode &= ~LCD_ENTRYLEFT;\n  command(LCD_ENTRYMODESET | _displaymode);\n}\n\n// This will 'right justify' text from the cursor\nvoid Max_LCD::autoscroll(void) {\n  _displaymode |= LCD_ENTRYSHIFTINCREMENT;\n  command(LCD_ENTRYMODESET | _displaymode);\n}\n\n// This will 'left justify' text from the cursor\nvoid Max_LCD::noAutoscroll(void) {\n  _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;\n  command(LCD_ENTRYMODESET | _displaymode);\n}\n\n// Allows us to fill the first 8 CGRAM locations\n// with custom characters\nvoid Max_LCD::createChar(uint8_t location, uint8_t charmap[]) {\n  location &= 0x7; // we only have 8 locations 0-7\n  command(LCD_SETCGRAMADDR | (location << 3));\n  for (int i=0; i<8; i++) {\n    write(charmap[i]);\n  }\n}\n\n/*********** mid level commands, for sending data/cmds */\n\ninline void Max_LCD::command(uint8_t value) {\n  LCD_sendcmd(value);\n  delayMicroseconds(100);\n}\n\ninline void Max_LCD::write(uint8_t value) {\n  LCD_sendchar(value);\n}\n\nvoid Max_LCD::sendbyte( uint8_t val )\n{\n    lcdPins &= 0x0f;                //prepare place for the upper nibble\n    lcdPins |= ( val & 0xf0 );      //copy upper nibble to LCD variable\n    SET_E;                          //send\n    SENDlcdPins();\n    delayMicroseconds(2);  \n    CLR_E;\n    delayMicroseconds(2);\n    SENDlcdPins();\n    lcdPins &= 0x0f;                    //prepare place for the lower nibble\n    lcdPins |= ( val << 4 ) & 0xf0;    //copy lower nibble to LCD variable\n    SET_E;                              //send\n    SENDlcdPins();  \n    CLR_E;\n    SENDlcdPins();\n    delayMicroseconds(100);\n}\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/USB_Host_Shield/Max_LCD.h",
    "content": "/*\n * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com\n * MAX3421E USB host controller support\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the authors nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n//HD44780 compatible LCD display via MAX3421E GPOUT support header\n//pinout: D[4-7] -> GPOUT[4-7], RS-> GPOUT[2], E ->GPOUT[3]\n//\n//this code is heavily borrowed from official Arduino source v.0017\n// link to original http://code.google.com/p/arduino/source/browse/trunk/hardware/libraries/LiquidCrystal/LiquidCrystal.h\n//\n#ifndef _Max_LCD_h_\n#define _Max_LCD_h_\n\n#include <inttypes.h>\n#include \"Print.h\"\n\n// commands\n#define LCD_CLEARDISPLAY 0x01\n#define LCD_RETURNHOME 0x02\n#define LCD_ENTRYMODESET 0x04\n#define LCD_DISPLAYCONTROL 0x08\n#define LCD_CURSORSHIFT 0x10\n#define LCD_FUNCTIONSET 0x20\n#define LCD_SETCGRAMADDR 0x40\n#define LCD_SETDDRAMADDR 0x80\n\n// flags for display entry mode\n#define LCD_ENTRYRIGHT 0x00\n#define LCD_ENTRYLEFT 0x02\n#define LCD_ENTRYSHIFTINCREMENT 0x01\n#define LCD_ENTRYSHIFTDECREMENT 0x00\n\n// flags for display on/off control\n#define LCD_DISPLAYON 0x04\n#define LCD_DISPLAYOFF 0x00\n#define LCD_CURSORON 0x02\n#define LCD_CURSOROFF 0x00\n#define LCD_BLINKON 0x01\n#define LCD_BLINKOFF 0x00\n\n// flags for display/cursor shift\n#define LCD_DISPLAYMOVE 0x08\n#define LCD_CURSORMOVE 0x00\n#define LCD_MOVERIGHT 0x04\n#define LCD_MOVELEFT 0x00\n\n// flags for function set\n#define LCD_8BITMODE 0x10\n#define LCD_4BITMODE 0x00\n#define LCD_2LINE 0x08\n#define LCD_1LINE 0x00\n#define LCD_5x10DOTS 0x04\n#define LCD_5x8DOTS 0x00\n\nclass Max_LCD : public Print {\npublic:\n  Max_LCD();\n  void init();\n  void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);\n  void clear();\n  void home();\n  void noDisplay();\n  void display();\n  void noBlink();\n  void blink();\n  void noCursor();\n  void cursor();\n  void scrollDisplayLeft();\n  void scrollDisplayRight();\n  void leftToRight();\n  void rightToLeft();\n  void autoscroll();\n  void noAutoscroll();\n  void createChar(uint8_t, uint8_t[]);\n  void setCursor(uint8_t, uint8_t); \n  virtual void write(uint8_t);\n  void command(uint8_t);\nprivate:\n  void sendbyte( uint8_t val );\n  uint8_t _displayfunction; //tokill\n  uint8_t _displaycontrol;\n  uint8_t _displaymode;\n  uint8_t _initialized;\n  uint8_t _numlines,_currline;\n};\n\n\n\n\n#endif\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/USB_Host_Shield/README",
    "content": "This is a library for MAX3421E-based USB Host Shield for Arduino -> http://www.circuitsathome.com/arduino_usb_host_shield_projects\n\nMore information can be found at http://www.circuitsathome.com\n\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/USB_Host_Shield/Usb.cpp",
    "content": "/*\n * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com\n * MAX3421E USB host controller support\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the authors nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n/* USB functions */\n\n#include \"Usb.h\"\n\nstatic byte usb_error = 0;\nstatic byte usb_task_state;\nDEV_RECORD devtable[ USB_NUMDEVICES + 1 ];\nEP_RECORD dev0ep;           //Endpoint data structure used during enumeration for uninitialized device\n\n\n/* constructor */\n\nUSB::USB () {\n    usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;  //set up state machine\n    init(); \n}\n/* Initialize data structures */\nvoid USB::init()\n{\n  byte i;\n    for( i = 0; i < ( USB_NUMDEVICES + 1 ); i++ ) {\n        devtable[ i ].epinfo = NULL;       //clear device table\n        devtable[ i ].devclass = 0;\n    }\n    devtable[ 0 ].epinfo = &dev0ep; //set single ep for uninitialized device  \n    // not necessary dev0ep.MaxPktSize = 8;          //minimum possible                        \t\n    dev0ep.sndToggle = bmSNDTOG0;   //set DATA0/1 toggles to 0\n    dev0ep.rcvToggle = bmRCVTOG0;\n}\nbyte USB::getUsbTaskState( void )\n{\n    return( usb_task_state );\n}\nvoid USB::setUsbTaskState( byte state )\n{\n    usb_task_state = state;\n}     \nEP_RECORD* USB::getDevTableEntry( byte addr, byte ep )\n{\n  EP_RECORD* ptr;\n    ptr = devtable[ addr ].epinfo;\n    ptr += ep;\n    return( ptr );\n}\n/* set device table entry */\n/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */\nvoid USB::setDevTableEntry( byte addr, EP_RECORD* eprecord_ptr )\n{\n    devtable[ addr ].epinfo = eprecord_ptr;\n    //return();\n}\n/* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer,   */\n/* depending on request. Actual requests are defined as inlines                                                                                      */\n/* return codes:                */\n/* 00       =   success         */\n/* 01-0f    =   non-zero HRSLT  */\nbyte USB::ctrlReq( byte addr, byte ep, byte bmReqType, byte bRequest, byte wValLo, byte wValHi, unsigned int wInd, unsigned int nbytes, char* dataptr, unsigned int nak_limit )\n{\n boolean direction = false;     //request direction, IN or OUT\n byte rcode;   \n SETUP_PKT setup_pkt;\n\n  regWr( rPERADDR, addr );                    //set peripheral address\n  if( bmReqType & 0x80 ) {\n    direction = true;                       //determine request direction\n  }\n    /* fill in setup packet */\n    setup_pkt.ReqType_u.bmRequestType = bmReqType;\n    setup_pkt.bRequest = bRequest;\n    setup_pkt.wVal_u.wValueLo = wValLo;\n    setup_pkt.wVal_u.wValueHi = wValHi;\n    setup_pkt.wIndex = wInd;\n    setup_pkt.wLength = nbytes;\n    bytesWr( rSUDFIFO, 8, ( char *)&setup_pkt );    //transfer to setup packet FIFO\n    rcode = dispatchPkt( tokSETUP, ep, nak_limit );            //dispatch packet\n    //Serial.println(\"Setup packet\");   //DEBUG\n    if( rcode ) {                                   //return HRSLT if not zero\n        Serial.print(\"Setup packet error: \");\n        Serial.print( rcode, HEX );                                          \n        return( rcode );\n    }\n    //Serial.println( direction, HEX ); \n    if( dataptr != NULL ) {                         //data stage, if present\n        rcode = ctrlData( addr, ep, nbytes, dataptr, direction );\n    }\n    if( rcode ) {   //return error\n        Serial.print(\"Data packet error: \");\n        Serial.print( rcode, HEX );                                          \n        return( rcode );\n    }\n    rcode = ctrlStatus( ep, direction );                //status stage\n    return( rcode );\n}\n/* Control transfer with status stage and no data stage */\n/* Assumed peripheral address is already set */\nbyte USB::ctrlStatus( byte ep, boolean direction, unsigned int nak_limit )\n{\n  byte rcode;\n    if( direction ) { //GET\n        rcode = dispatchPkt( tokOUTHS, ep, nak_limit );\n    }\n    else {\n        rcode = dispatchPkt( tokINHS, ep, nak_limit );\n    }\n    return( rcode );\n}\n/* Control transfer with data stage. Stages 2 and 3 of control transfer. Assumes preipheral address is set and setup packet has been sent */\nbyte USB::ctrlData( byte addr, byte ep, unsigned int nbytes, char* dataptr, boolean direction, unsigned int nak_limit )\n{\n byte rcode;\n  if( direction ) {                      //IN transfer\n    devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;\n    rcode = inTransfer( addr, ep, nbytes, dataptr, nak_limit );\n    return( rcode );\n  }\n  else {              //OUT transfer\n    devtable[ addr ].epinfo[ ep ].sndToggle = bmSNDTOG1;\n    rcode = outTransfer( addr, ep, nbytes, dataptr, nak_limit );\n    return( rcode );\n  }    \n}\n/* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */\n/* Keep sending INs and writes data to memory area pointed by 'data'                                                           */\n/* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,\n            fe USB xfer timeout */\nbyte USB::inTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit )\n{\n byte rcode;\n byte pktsize;\n byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize; \n unsigned int xfrlen = 0;\n    regWr( rHCTL, devtable[ addr ].epinfo[ ep ].rcvToggle );    //set toggle value\n    while( 1 ) { // use a 'return' to exit this loop\n        rcode = dispatchPkt( tokIN, ep, nak_limit );           //IN packet to EP-'endpoint'. Function takes care of NAKS.\n        if( rcode ) {\n            return( rcode );                            //should be 0, indicating ACK. Else return error code.\n        }\n        /* check for RCVDAVIRQ and generate error if not present */ \n        /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */\n        if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) {\n            return ( 0xf0 );                            //receive error\n        }\n        pktsize = regRd( rRCVBC );                      //number of received bytes\n        data = bytesRd( rRCVFIFO, pktsize, data );\n        regWr( rHIRQ, bmRCVDAVIRQ );                    // Clear the IRQ & free the buffer\n        xfrlen += pktsize;                              // add this packet's byte count to total transfer length\n        /* The transfer is complete under two conditions:           */\n        /* 1. The device sent a short packet (L.T. maxPacketSize)   */\n        /* 2. 'nbytes' have been transferred.                       */\n        if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) {      // have we transferred 'nbytes' bytes?\n            if( regRd( rHRSL ) & bmRCVTOGRD ) {                     //save toggle value\n                devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;\n            }\n            else {\n                devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG0;\n            }\n            return( 0 );\n        }\n  }//while( 1 )\n}\n\nint USB::newInTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit )\n{\n byte rcode;\n byte pktsize;\n byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize; \n unsigned int xfrlen = 0;\n    regWr( rHCTL, devtable[ addr ].epinfo[ ep ].rcvToggle );    //set toggle value\n    while( 1 ) { // use a 'return' to exit this loop\n        rcode = dispatchPkt( tokIN, ep, nak_limit );           //IN packet to EP-'endpoint'. Function takes care of NAKS.\n        if( rcode ) {\n\t\treturn -1;                            //should be 0, indicating ACK. Else return error code.\n        }\n        /* check for RCVDAVIRQ and generate error if not present */ \n        /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */\n        if(( regRd( rHIRQ ) & bmRCVDAVIRQ ) == 0 ) {\n            return -1;                            //receive error\n        }\n        pktsize = regRd( rRCVBC );                      //number of received bytes\n        data = bytesRd( rRCVFIFO, pktsize, data );\n        regWr( rHIRQ, bmRCVDAVIRQ );                    // Clear the IRQ & free the buffer\n        xfrlen += pktsize;                              // add this packet's byte count to total transfer length\n        /* The transfer is complete under two conditions:           */\n        /* 1. The device sent a short packet (L.T. maxPacketSize)   */\n        /* 2. 'nbytes' have been transferred.                       */\n        if (( pktsize < maxpktsize ) || (xfrlen >= nbytes )) {      // have we transferred 'nbytes' bytes?\n            if( regRd( rHRSL ) & bmRCVTOGRD ) {                     //save toggle value\n                devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG1;\n            }\n            else {\n                devtable[ addr ].epinfo[ ep ].rcvToggle = bmRCVTOG0;\n            }\n            return xfrlen;\n        }\n  }//while( 1 )\n}\n\n/* OUT transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */\n/* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer   */\n/* rcode 0 if no errors. rcode 01-0f is relayed from HRSL                       */\n/* major part of this function borrowed from code shared by Richard Ibbotson    */\nbyte USB::outTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit )\n{\n byte rcode, retry_count;\n char* data_p = data;   //local copy of the data pointer\n unsigned int bytes_tosend, nak_count;\n unsigned int bytes_left = nbytes;\n byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize; \n unsigned long timeout = millis() + USB_XFER_TIMEOUT;\n \n  if (!maxpktsize) { //todo: move this check close to epinfo init. Make it 1< pktsize <64\n    return 0xFE;\n  }\n \n  regWr( rHCTL, devtable[ addr ].epinfo[ ep ].sndToggle );    //set toggle value\n  while( bytes_left ) {\n    retry_count = 0;\n    nak_count = 0;\n    bytes_tosend = ( bytes_left >= maxpktsize ) ? maxpktsize : bytes_left;\n    bytesWr( rSNDFIFO, bytes_tosend, data_p );      //filling output FIFO\n    regWr( rSNDBC, bytes_tosend );                  //set number of bytes    \n    regWr( rHXFR, ( tokOUT | ep ));                 //dispatch packet\n    while(!(regRd( rHIRQ ) & bmHXFRDNIRQ ));        //wait for the completion IRQ\n    regWr( rHIRQ, bmHXFRDNIRQ );                    //clear IRQ\n    rcode = ( regRd( rHRSL ) & 0x0f );\n    while( rcode && ( timeout > millis())) {\n      switch( rcode ) {\n        case hrNAK:\n          nak_count++;\n          if( nak_limit && ( nak_count == USB_NAK_LIMIT )) {\n            return( rcode);                                   //return NAK\n          }\n          break;\n        case hrTIMEOUT:\n          retry_count++;\n          if( retry_count == USB_RETRY_LIMIT ) {\n            return( rcode );    //return TIMEOUT\n          }\n          break;\n        default:  \n          return( rcode );\n      }//switch( rcode...\n      /* process NAK according to Host out NAK bug */\n      regWr( rSNDBC, 0 );\n      regWr( rSNDFIFO, *data_p );\n      regWr( rSNDBC, bytes_tosend );\n      regWr( rHXFR, ( tokOUT | ep ));                 //dispatch packet\n      while(!(regRd( rHIRQ ) & bmHXFRDNIRQ ));        //wait for the completion IRQ\n      regWr( rHIRQ, bmHXFRDNIRQ );                    //clear IRQ\n      rcode = ( regRd( rHRSL ) & 0x0f );\n    }//while( rcode && ....\n    bytes_left -= bytes_tosend;\n    data_p += bytes_tosend;\n  }//while( bytes_left...\n  devtable[ addr ].epinfo[ ep ].sndToggle = ( regRd( rHRSL ) & bmSNDTOGRD ) ? bmSNDTOG1 : bmSNDTOG0;  //update toggle\n  return( rcode );    //should be 0 in all cases\n}\n/* dispatch usb packet. Assumes peripheral address is set and relevant buffer is loaded/empty       */\n/* If NAK, tries to re-send up to nak_limit times                                                   */\n/* If nak_limit == 0, do not count NAKs, exit after timeout                                         */\n/* If bus timeout, re-sends up to USB_RETRY_LIMIT times                                             */\n/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout                       */\nbyte USB::dispatchPkt( byte token, byte ep, unsigned int nak_limit )\n{\n unsigned long timeout = millis() + USB_XFER_TIMEOUT;\n byte tmpdata;   \n byte rcode;\n unsigned int nak_count = 0;\n char retry_count = 0;\n\n  while( timeout > millis() ) {\n    regWr( rHXFR, ( token|ep ));            //launch the transfer\n    rcode = 0xff;   \n    while( millis() < timeout ) {           //wait for transfer completion\n      tmpdata = regRd( rHIRQ );\n      if( tmpdata & bmHXFRDNIRQ ) {\n        regWr( rHIRQ, bmHXFRDNIRQ );    //clear the interrupt\n        rcode = 0x00;\n        break;\n      }//if( tmpdata & bmHXFRDNIRQ\n    }//while ( millis() < timeout\n    if( rcode != 0x00 ) {                //exit if timeout\n      return( rcode );\n    }\n    rcode = ( regRd( rHRSL ) & 0x0f );  //analyze transfer result\n    switch( rcode ) {\n      case hrNAK:\n        nak_count ++;\n        if( nak_limit && ( nak_count == nak_limit )) {\n          return( rcode );\n        }\n        break;\n      case hrTIMEOUT:\n        retry_count ++;\n        if( retry_count == USB_RETRY_LIMIT ) {\n          return( rcode );\n        }\n        break;\n      default:\n        return( rcode );\n    }//switch( rcode\n  }//while( timeout > millis() \n  return( rcode );\n}\n/* USB main task. Performs enumeration/cleanup */\nvoid USB::Task( void )      //USB state machine\n{\n  byte i;   \n  byte rcode;\n  static byte tmpaddr; \n  byte tmpdata;\n  static unsigned long delay = 0;\n  USB_DEVICE_DESCRIPTOR buf;\n    tmpdata = getVbusState();\n    /* modify USB task state if Vbus changed */\n\n    switch( tmpdata ) {\n        case SE1:   //illegal state\n            usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;\n            break;\n        case SE0:   //disconnected\n            if(( usb_task_state & USB_STATE_MASK ) != USB_STATE_DETACHED ) {\n                usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;\n            }\n            break;\n        case FSHOST:    //attached\n        case LSHOST:\n            if(( usb_task_state & USB_STATE_MASK ) == USB_STATE_DETACHED ) {\n                delay = millis() + USB_SETTLE_DELAY;\n                usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;\n            }\n            break;\n        }// switch( tmpdata\n    //Serial.print(\"USB task state: \");\n    //Serial.println( usb_task_state, HEX );\n    switch( usb_task_state ) {\n        case USB_DETACHED_SUBSTATE_INITIALIZE:\n            init();\n            usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;\n            break;\n        case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE:     //just sit here\n            break;\n        case USB_DETACHED_SUBSTATE_ILLEGAL:             //just sit here\n            break;\n        case USB_ATTACHED_SUBSTATE_SETTLE:              //setlle time for just attached device                  \n            if( delay < millis() ) {\n                usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;\n            }\n            break;\n        case USB_ATTACHED_SUBSTATE_RESET_DEVICE:\n            regWr( rHCTL, bmBUSRST );                   //issue bus reset\n            usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;\n            break;\n        case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:\n            if(( regRd( rHCTL ) & bmBUSRST ) == 0 ) {\n                tmpdata = regRd( rMODE ) | bmSOFKAENAB;                 //start SOF generation\n                regWr( rMODE, tmpdata );\n//                  regWr( rMODE, bmSOFKAENAB );\n                usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;\n                delay = millis() + 20; //20ms wait after reset per USB spec\n            }\n            break;\n        case USB_ATTACHED_SUBSTATE_WAIT_SOF:  //todo: change check order\n            if( regRd( rHIRQ ) & bmFRAMEIRQ ) {                         //when first SOF received we can continue\n              if( delay < millis() ) {                                    //20ms passed\n                usb_task_state = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;\n              }\n            }\n            break;\n        case USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE:\n            // toggle( BPNT_0 );\n            devtable[ 0 ].epinfo->MaxPktSize = 8;   //set max.packet size to min.allowed\n            rcode = getDevDescr( 0, 0, 8, ( char* )&buf );\n            if( rcode == 0 ) {\n                devtable[ 0 ].epinfo->MaxPktSize = buf.bMaxPacketSize0;\n                usb_task_state = USB_STATE_ADDRESSING;\n            }\n            else {\n                usb_error = USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE;\n                usb_task_state = USB_STATE_ERROR;\n            }\n            break;\n        case USB_STATE_ADDRESSING:\n            for( i = 1; i < USB_NUMDEVICES; i++ ) {\n                if( devtable[ i ].epinfo == NULL ) {\n                    devtable[ i ].epinfo = devtable[ 0 ].epinfo;        //set correct MaxPktSize\n                                                                        //temporary record\n                                                                        //until plugged with real device endpoint structure\n                    rcode = setAddr( 0, 0, i );\n                    if( rcode == 0 ) {\n                        tmpaddr = i;\n                        usb_task_state = USB_STATE_CONFIGURING;\n                    }\n                    else {\n                        usb_error = USB_STATE_ADDRESSING;          //set address error\n                        usb_task_state = USB_STATE_ERROR;\n                    }\n                    break;  //break if address assigned or error occured during address assignment attempt                      \n                }\n            }//for( i = 1; i < USB_NUMDEVICES; i++\n            if( usb_task_state == USB_STATE_ADDRESSING ) {     //no vacant place in devtable\n                usb_error = 0xfe;\n                usb_task_state = USB_STATE_ERROR;\n            }\n            break;\n        case USB_STATE_CONFIGURING:\n            break;\n        case USB_STATE_RUNNING:\n            break;\n        case USB_STATE_ERROR:\n            break;\n    }// switch( usb_task_state\n}    \n  \n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/USB_Host_Shield/Usb.h",
    "content": "/*\n * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com\n * MAX3421E USB host controller support\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the authors nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n/* USB functions */\n#ifndef _usb_h_\n#define _usb_h_\n\n#include <Max3421e.h>\n#include \"ch9.h\"\n\n/* Common setup data constant combinations  */\n#define bmREQ_GET_DESCR     USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE     //get descriptor request type\n#define bmREQ_SET           USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE     //set request type for all but 'set feature' and 'set interface'\n#define bmREQ_CL_GET_INTF   USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE     //get interface request type\n/* HID requests */\n#define bmREQ_HIDOUT        USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE\n#define bmREQ_HIDIN         USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE \n#define bmREQ_HIDREPORT     USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE\n\n#define USB_XFER_TIMEOUT    5000    //USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec\n#define USB_NAK_LIMIT       32000   //NAK limit for a transfer. o meand NAKs are not counted\n#define USB_RETRY_LIMIT     3       //retry limit for a transfer\n#define USB_SETTLE_DELAY    200     //settle delay in milliseconds\n#define USB_NAK_NOWAIT      1       //used in Richard's PS2/Wiimote code\n\n#define USB_NUMDEVICES  2           //number of USB devices\n\n/* USB state machine states */\n\n#define USB_STATE_MASK                                      0xf0\n\n#define USB_STATE_DETACHED                                  0x10\n#define USB_DETACHED_SUBSTATE_INITIALIZE                    0x11        \n#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE               0x12\n#define USB_DETACHED_SUBSTATE_ILLEGAL                       0x13\n#define USB_ATTACHED_SUBSTATE_SETTLE                        0x20\n#define USB_ATTACHED_SUBSTATE_RESET_DEVICE                  0x30    \n#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE           0x40\n#define USB_ATTACHED_SUBSTATE_WAIT_SOF                      0x50\n#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE    0x60\n#define USB_STATE_ADDRESSING                                0x70\n#define USB_STATE_CONFIGURING                               0x80\n#define USB_STATE_RUNNING                                   0x90\n#define USB_STATE_ERROR                                     0xa0\n\n// byte usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE\n\n/* USB Setup Packet Structure   */\ntypedef struct {\n    union {                          // offset   description\n        byte bmRequestType;         //   0      Bit-map of request type\n        struct {\n            byte    recipient:  5;  //          Recipient of the request\n            byte    type:       2;  //          Type of request\n            byte    direction:  1;  //          Direction of data X-fer\n        };\n    }ReqType_u;\n    byte    bRequest;               //   1      Request\n    union {\n        unsigned int    wValue;             //   2      Depends on bRequest\n        struct {\n        byte    wValueLo;\n        byte    wValueHi;\n        };\n    }wVal_u;\n    unsigned int    wIndex;                 //   4      Depends on bRequest\n    unsigned int    wLength;                //   6      Depends on bRequest\n} SETUP_PKT, *PSETUP_PKT;\n\n/* Endpoint information structure               */\n/* bToggle of endpoint 0 initialized to 0xff    */\n/* during enumeration bToggle is set to 00      */\ntypedef struct {        \n    byte epAddr;        //copy from endpoint descriptor. Bit 7 indicates direction ( ignored for control endpoints )\n    byte Attr;          // Endpoint transfer type.\n    unsigned int MaxPktSize;    // Maximum packet size.\n    byte Interval;      // Polling interval in frames.\n    byte sndToggle;     //last toggle value, bitmask for HCTL toggle bits\n    byte rcvToggle;     //last toggle value, bitmask for HCTL toggle bits\n    /* not sure if both are necessary */\n} EP_RECORD;\n/* device record structure */\ntypedef struct {\n    EP_RECORD* epinfo;      //device endpoint information\n    byte devclass;          //device class    \n} DEV_RECORD;\n\n\n\nclass USB : public MAX3421E {\n//data structures    \n/* device table. Filled during enumeration              */\n/* index corresponds to device address                  */\n/* each entry contains pointer to endpoint structure    */\n/* and device class to use in various places            */             \n//DEV_RECORD devtable[ USB_NUMDEVICES + 1 ];\n//EP_RECORD dev0ep;         //Endpoint data structure used during enumeration for uninitialized device\n\n//byte usb_task_state;\n\n    public:\n        USB( void );\n        byte getUsbTaskState( void );\n        void setUsbTaskState( byte state );\n        EP_RECORD* getDevTableEntry( byte addr, byte ep );\n        void setDevTableEntry( byte addr, EP_RECORD* eprecord_ptr );\n        byte ctrlReq( byte addr, byte ep, byte bmReqType, byte bRequest, byte wValLo, byte wValHi, unsigned int wInd, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );\n        /* Control requests */\n        byte getDevDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );\n        byte getConfDescr( byte addr, byte ep, unsigned int nbytes, byte conf, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );\n        byte getStrDescr( byte addr, byte ep, unsigned int nbytes, byte index, unsigned int langid, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );\n        byte setAddr( byte oldaddr, byte ep, byte newaddr, unsigned int nak_limit = USB_NAK_LIMIT );\n        byte setConf( byte addr, byte ep, byte conf_value, unsigned int nak_limit = USB_NAK_LIMIT );\n        /**/\n        byte setProto( byte addr, byte ep, byte interface, byte protocol, unsigned int nak_limit = USB_NAK_LIMIT );\n        byte getProto( byte addr, byte ep, byte interface, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );\n        byte getReportDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );\n        byte setReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );\n\t      byte getReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );\n        byte getIdle( byte addr, byte ep, byte interface, byte reportID, char* dataptr, unsigned int nak_limit = USB_NAK_LIMIT );\n        byte setIdle( byte addr, byte ep, byte interface, byte reportID, byte duration, unsigned int nak_limit = USB_NAK_LIMIT );\n        /**/\n        byte ctrlData( byte addr, byte ep, unsigned int nbytes, char* dataptr, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT );\n        byte ctrlStatus( byte ep, boolean direction, unsigned int nak_limit = USB_NAK_LIMIT );\n        byte inTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit = USB_NAK_LIMIT );\n\t\tint newInTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit  = USB_NAK_LIMIT);\n        byte outTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit = USB_NAK_LIMIT );\n        byte dispatchPkt( byte token, byte ep, unsigned int nak_limit = USB_NAK_LIMIT );\n        void Task( void );\n    private:\n        void init();\n};\n\n//get device descriptor\ninline byte USB::getDevDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit ) {\n    return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr, nak_limit ));\n}\n//get configuration descriptor  \ninline byte USB::getConfDescr( byte addr, byte ep, unsigned int nbytes, byte conf, char* dataptr, unsigned int nak_limit ) {\n        return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr, nak_limit ));\n}\n//get string descriptor\ninline byte USB::getStrDescr( byte addr, byte ep, unsigned int nbytes, byte index, unsigned int langid, char* dataptr, unsigned int nak_limit ) {\n    return( ctrlReq( addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nbytes, dataptr, nak_limit ));\n}\n//set address \ninline byte USB::setAddr( byte oldaddr, byte ep, byte newaddr, unsigned int nak_limit ) {\n    return( ctrlReq( oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL, nak_limit ));\n}\n//set configuration\ninline byte USB::setConf( byte addr, byte ep, byte conf_value, unsigned int nak_limit ) {\n    return( ctrlReq( addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL, nak_limit ));         \n}\n//class requests\ninline byte USB::setProto( byte addr, byte ep, byte interface, byte protocol, unsigned int nak_limit ) {\n        return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, interface, 0x0000, NULL, nak_limit ));\n}\ninline byte USB::getProto( byte addr, byte ep, byte interface, char* dataptr, unsigned int nak_limit ) {\n        return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, interface, 0x0001, dataptr, nak_limit ));        \n}\n//get HID report descriptor \ninline byte USB::getReportDescr( byte addr, byte ep, unsigned int nbytes, char* dataptr, unsigned int nak_limit ) {\n        return( ctrlReq( addr, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_REPORT, 0x0000, nbytes, dataptr, nak_limit ));\n}\ninline byte USB::setReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit ) {\n    return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit ));\n}\ninline byte USB::getReport( byte addr, byte ep, unsigned int nbytes, byte interface, byte report_type, byte report_id, char* dataptr, unsigned int nak_limit ) { // ** RI 04/11/09\n    return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, interface, nbytes, dataptr, nak_limit ));\n}\n/* returns one byte of data in dataptr */\ninline byte USB::getIdle( byte addr, byte ep, byte interface, byte reportID, char* dataptr, unsigned int nak_limit ) {\n        return( ctrlReq( addr, ep, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, interface, 0x0001, dataptr, nak_limit ));    \n}\ninline byte USB::setIdle( byte addr, byte ep, byte interface, byte reportID, byte duration, unsigned int nak_limit ) {\n           return( ctrlReq( addr, ep, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, interface, 0x0000, NULL, nak_limit ));\n          }\n#endif //_usb_h_\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/arduino_libs/USB_Host_Shield/ch9.h",
    "content": "/*\n * Copyright 2009-2011 Oleg Mazurov, Circuits At Home, http://www.circuitsathome.com\n * MAX3421E USB host controller support\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the authors nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n */\n\n/* USB chapter 9 structures */\n#ifndef _ch9_h_\n#define _ch9_h_\n\n/* Misc.USB constants */\n#define DEV_DESCR_LEN   18      //device descriptor length\n#define CONF_DESCR_LEN  9       //configuration descriptor length\n#define INTR_DESCR_LEN  9       //interface descriptor length\n#define EP_DESCR_LEN    7       //endpoint descriptor length\n\n/* Standard Device Requests */\n\n#define USB_REQUEST_GET_STATUS                  0       // Standard Device Request - GET STATUS\n#define USB_REQUEST_CLEAR_FEATURE               1       // Standard Device Request - CLEAR FEATURE\n#define USB_REQUEST_SET_FEATURE                 3       // Standard Device Request - SET FEATURE\n#define USB_REQUEST_SET_ADDRESS                 5       // Standard Device Request - SET ADDRESS\n#define USB_REQUEST_GET_DESCRIPTOR              6       // Standard Device Request - GET DESCRIPTOR\n#define USB_REQUEST_SET_DESCRIPTOR              7       // Standard Device Request - SET DESCRIPTOR\n#define USB_REQUEST_GET_CONFIGURATION           8       // Standard Device Request - GET CONFIGURATION\n#define USB_REQUEST_SET_CONFIGURATION           9       // Standard Device Request - SET CONFIGURATION\n#define USB_REQUEST_GET_INTERFACE               10      // Standard Device Request - GET INTERFACE\n#define USB_REQUEST_SET_INTERFACE               11      // Standard Device Request - SET INTERFACE\n#define USB_REQUEST_SYNCH_FRAME                 12      // Standard Device Request - SYNCH FRAME\n\n#define USB_FEATURE_ENDPOINT_HALT               0       // CLEAR/SET FEATURE - Endpoint Halt\n#define USB_FEATURE_DEVICE_REMOTE_WAKEUP        1       // CLEAR/SET FEATURE - Device remote wake-up\n#define USB_FEATURE_TEST_MODE                   2       // CLEAR/SET FEATURE - Test mode\n\n/* Setup Data Constants */\n\n#define USB_SETUP_HOST_TO_DEVICE                0x00    // Device Request bmRequestType transfer direction - host to device transfer\n#define USB_SETUP_DEVICE_TO_HOST                0x80    // Device Request bmRequestType transfer direction - device to host transfer\n#define USB_SETUP_TYPE_STANDARD                 0x00    // Device Request bmRequestType type - standard\n#define USB_SETUP_TYPE_CLASS                    0x20    // Device Request bmRequestType type - class\n#define USB_SETUP_TYPE_VENDOR                   0x40    // Device Request bmRequestType type - vendor\n#define USB_SETUP_RECIPIENT_DEVICE              0x00    // Device Request bmRequestType recipient - device\n#define USB_SETUP_RECIPIENT_INTERFACE           0x01    // Device Request bmRequestType recipient - interface\n#define USB_SETUP_RECIPIENT_ENDPOINT            0x02    // Device Request bmRequestType recipient - endpoint\n#define USB_SETUP_RECIPIENT_OTHER               0x03    // Device Request bmRequestType recipient - other\n\n/* USB descriptors  */\n\n#define USB_DESCRIPTOR_DEVICE           0x01    // bDescriptorType for a Device Descriptor.\n#define USB_DESCRIPTOR_CONFIGURATION    0x02    // bDescriptorType for a Configuration Descriptor.\n#define USB_DESCRIPTOR_STRING           0x03    // bDescriptorType for a String Descriptor.\n#define USB_DESCRIPTOR_INTERFACE        0x04    // bDescriptorType for an Interface Descriptor.\n#define USB_DESCRIPTOR_ENDPOINT         0x05    // bDescriptorType for an Endpoint Descriptor.\n#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06    // bDescriptorType for a Device Qualifier.\n#define USB_DESCRIPTOR_OTHER_SPEED      0x07    // bDescriptorType for a Other Speed Configuration.\n#define USB_DESCRIPTOR_INTERFACE_POWER  0x08    // bDescriptorType for Interface Power.\n#define USB_DESCRIPTOR_OTG              0x09    // bDescriptorType for an OTG Descriptor.\n\n/* OTG SET FEATURE Constants    */\n#define OTG_FEATURE_B_HNP_ENABLE                3       // SET FEATURE OTG - Enable B device to perform HNP\n#define OTG_FEATURE_A_HNP_SUPPORT               4       // SET FEATURE OTG - A device supports HNP\n#define OTG_FEATURE_A_ALT_HNP_SUPPORT           5       // SET FEATURE OTG - Another port on the A device supports HNP\n\n/* USB Endpoint Transfer Types  */\n#define USB_TRANSFER_TYPE_CONTROL               0x00    // Endpoint is a control endpoint.\n#define USB_TRANSFER_TYPE_ISOCHRONOUS           0x01    // Endpoint is an isochronous endpoint.\n#define USB_TRANSFER_TYPE_BULK                  0x02    // Endpoint is a bulk endpoint.\n#define USB_TRANSFER_TYPE_INTERRUPT             0x03    // Endpoint is an interrupt endpoint.\n#define bmUSB_TRANSFER_TYPE                     0x03    // bit mask to separate transfer type from ISO attributes\n\n\n/* Standard Feature Selectors for CLEAR_FEATURE Requests    */\n#define USB_FEATURE_ENDPOINT_STALL              0       // Endpoint recipient\n#define USB_FEATURE_DEVICE_REMOTE_WAKEUP        1       // Device recipient\n#define USB_FEATURE_TEST_MODE                   2       // Device recipient\n\n/* HID constants. Not part of chapter 9 */\n/* Class-Specific Requests */\n#define HID_REQUEST_GET_REPORT      0x01\n#define HID_REQUEST_GET_IDLE        0x02\n#define HID_REQUEST_GET_PROTOCOL    0x03\n#define HID_REQUEST_SET_REPORT      0x09\n#define HID_REQUEST_SET_IDLE        0x0A\n#define HID_REQUEST_SET_PROTOCOL    0x0B\n\n/* Class Descriptor Types */\n#define HID_DESCRIPTOR_HID      0x21\n#define HID_DESCRIPTOR_REPORT   0x22\n#define HID_DESRIPTOR_PHY       0x23\n\n/* Protocol Selection */\n#define BOOT_PROTOCOL   0x00\n#define RPT_PROTOCOL    0x01\n/* HID Interface Class Code */\n#define HID_INTF                    0x03\n/* HID Interface Class SubClass Codes */\n#define BOOT_INTF_SUBCLASS          0x01\n/* HID Interface Class Protocol Codes */\n#define HID_PROTOCOL_NONE           0x00\n#define HID_PROTOCOL_KEYBOARD       0x01\n#define HID_PROTOCOL_MOUSE          0x02\n\n\n/* descriptor data structures */\n\n/* Device descriptor structure */\ntypedef struct {\n    byte bLength;               // Length of this descriptor.\n    byte bDescriptorType;       // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE).\n    unsigned int bcdUSB;        // USB Spec Release Number (BCD).\n    byte bDeviceClass;          // Class code (assigned by the USB-IF). 0xFF-Vendor specific.\n    byte bDeviceSubClass;       // Subclass code (assigned by the USB-IF).\n    byte bDeviceProtocol;       // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.\n    byte bMaxPacketSize0;       // Maximum packet size for endpoint 0.\n    unsigned int idVendor;      // Vendor ID (assigned by the USB-IF).\n    unsigned int idProduct;     // Product ID (assigned by the manufacturer).\n    unsigned int bcdDevice;      // Device release number (BCD).\n    byte iManufacturer;         // Index of String Descriptor describing the manufacturer.\n    byte iProduct;              // Index of String Descriptor describing the product.\n    byte iSerialNumber;         // Index of String Descriptor with the device's serial number.\n    byte bNumConfigurations;    // Number of possible configurations.\n} USB_DEVICE_DESCRIPTOR;\n\n/* Configuration descriptor structure */\ntypedef struct\n{\n    byte bLength;               // Length of this descriptor.\n    byte bDescriptorType;       // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).\n    unsigned int wTotalLength;          // Total length of all descriptors for this configuration.\n    byte bNumInterfaces;        // Number of interfaces in this configuration.\n    byte bConfigurationValue;   // Value of this configuration (1 based).\n    byte iConfiguration;        // Index of String Descriptor describing the configuration.\n    byte bmAttributes;          // Configuration characteristics.\n    byte bMaxPower;             // Maximum power consumed by this configuration.\n} USB_CONFIGURATION_DESCRIPTOR;\n\n/* Interface descriptor structure */\ntypedef struct\n{\n    byte bLength;               // Length of this descriptor.\n    byte bDescriptorType;       // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).\n    byte bInterfaceNumber;      // Number of this interface (0 based).\n    byte bAlternateSetting;     // Value of this alternate interface setting.\n    byte bNumEndpoints;         // Number of endpoints in this interface.\n    byte bInterfaceClass;       // Class code (assigned by the USB-IF).  0xFF-Vendor specific.\n    byte bInterfaceSubClass;    // Subclass code (assigned by the USB-IF).\n    byte bInterfaceProtocol;    // Protocol code (assigned by the USB-IF).  0xFF-Vendor specific.\n    byte iInterface;            // Index of String Descriptor describing the interface.\n} USB_INTERFACE_DESCRIPTOR;\n\n/* Endpoint descriptor structure */\ntypedef struct\n{\n    byte bLength;               // Length of this descriptor.\n    byte bDescriptorType;       // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).\n    byte bEndpointAddress;      // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).\n    byte bmAttributes;          // Endpoint transfer type.\n    unsigned int wMaxPacketSize;        // Maximum packet size.\n    byte bInterval;             // Polling interval in frames.\n} USB_ENDPOINT_DESCRIPTOR;\n\n/* HID descriptor */\ntypedef struct {\n    byte bLength;                       \n        byte bDescriptorType;   \n        unsigned int bcdHID;                    \n    byte bCountryCode;          \n        byte bNumDescriptors;\n        byte bDescrType;                        \n    unsigned int wDescriptorLength;\n} USB_HID_DESCRIPTOR;\n\n#endif // _ch9_h_\n"
  },
  {
    "path": "_archive/apps/samples/serial/adkjs/firmware/demokitclient/demokitclient.ino",
    "content": "#include <Wire.h>\n#include <Servo.h>\n#include <CapSense.h>\n\n\nString inputString = \"\";         // a string to hold incoming data\nboolean inputComplete = false;  // whether the string is complete\nboolean sendSensors = false;\n\nlong count_timer = 0;\n\n\n/*\n\nRX commands:\n  \n  0x1: reset board (turn all off and default servo's position)\n  0x2: set servos and leds\n       0x0..0x2: led 1\n       0x3..0x5: led 2\n       0x6..0x8: led 3\n       0x10: servo 1\n       0x11: servo 2\n       0x12: servo 3\n       \n  0x3: set relays\n       0x0: relay 1\n       0x1: relay 2\n\nTX commands:\n  \n  0x1: button statuses\n  \n       0x0 button 1\n       0x1 button 2\n       0x2 button 3\n       0x3: cap sense\n       0x4: joy switch\n  \n  0x4: temp\n  0x5: light\n  0x6: joy analogic\n\n\n*/\n\n\n\n\n#define  LED3_RED       2\n#define  LED3_GREEN     4\n#define  LED3_BLUE      3\n\n#define  LED2_RED       5\n#define  LED2_GREEN     7\n#define  LED2_BLUE      6\n\n#define  LED1_RED       8\n#define  LED1_GREEN     10\n#define  LED1_BLUE      9\n\n#define  SERVO1         11\n#define  SERVO2         12\n#define  SERVO3         13\n\n#define  TOUCH_RECV     14\n#define  TOUCH_SEND     15\n\n#define  RELAY1         A0\n#define  RELAY2         A1\n\n#define  LIGHT_SENSOR   A2\n#define  TEMP_SENSOR    A3\n\n#define  BUTTON1        A6\n#define  BUTTON2        A7\n#define  BUTTON3        A8\n\n#define  JOY_SWITCH     A9      // pulls line down when pressed\n#define  JOY_nINT       A10     // active low interrupt input\n#define  JOY_nRESET     A11     // active low reset output\n\n\nServo servos[3];\n\n// 10M ohm resistor on demo shield\nCapSense   touch_robot = CapSense(TOUCH_SEND, TOUCH_RECV);\n\nvoid setup();\nvoid loop();\n\nvoid init_buttons()\n{\n  pinMode(BUTTON1, INPUT);\n  pinMode(BUTTON2, INPUT);\n  pinMode(BUTTON3, INPUT);\n  pinMode(JOY_SWITCH, INPUT);\n  \n  // enable the internal pullups\n  digitalWrite(BUTTON1, HIGH);\n  digitalWrite(BUTTON2, HIGH);\n  digitalWrite(BUTTON3, HIGH);\n  digitalWrite(JOY_SWITCH, HIGH);\n}\n\n\nvoid init_relays()\n{\n  pinMode(RELAY1, OUTPUT);\n  pinMode(RELAY2, OUTPUT);\n}\n\n\nvoid init_leds()\n{\n  digitalWrite(LED1_RED, 1);\n  digitalWrite(LED1_GREEN, 1);\n  digitalWrite(LED1_BLUE, 1);\n  \n  pinMode(LED1_RED, OUTPUT);\n  pinMode(LED1_GREEN, OUTPUT);\n  pinMode(LED1_BLUE, OUTPUT);\n  \n  digitalWrite(LED2_RED, 1);\n  digitalWrite(LED2_GREEN, 1);\n  digitalWrite(LED2_BLUE, 1);\n  \n  pinMode(LED2_RED, OUTPUT);\n  pinMode(LED2_GREEN, OUTPUT);\n  pinMode(LED2_BLUE, OUTPUT);\n  \n  digitalWrite(LED3_RED, 1);\n  digitalWrite(LED3_GREEN, 1);\n  digitalWrite(LED3_BLUE, 1);\n  \n  pinMode(LED3_RED, OUTPUT);\n  pinMode(LED3_GREEN, OUTPUT);\n  pinMode(LED3_BLUE, OUTPUT);\n}\n\nvoid init_joystick(int threshold);\n\nbyte b1, b2, b3, b4;\nboolean c;\n\nvoid setup()\n{\n  inputString.reserve(200);\n\n  Serial.begin(57600);\n  Serial.println(\"\\r\\nStart\");\n  \n  init_leds();\n  init_relays();\n  init_buttons();\n  init_joystick( 5 );\n  \n  // autocalibrate OFF\n  touch_robot.set_CS_AutocaL_Millis(0xFFFFFFFF);\n  \n  servos[0].attach(SERVO1);\n  servos[0].write(90);\n  servos[1].attach(SERVO2);\n  servos[1].write(90);\n  servos[2].attach(SERVO3);\n  servos[2].write(90);\n  \n  \n  b1 = digitalRead(BUTTON1);\n  b2 = digitalRead(BUTTON2);\n  b3 = digitalRead(BUTTON3);\n  b4 = digitalRead(JOY_SWITCH);\n  c = 0;\n  \n  count_timer = millis();\n\n}\n\n\nvoid serialEvent() {\n  while (Serial.available()) {\n    // get the new byte:\n    char inChar = (char)Serial.read(); \n    // if the incoming character is a newline, set a flag\n    // so the main loop can do something about it:\n    if (inChar == '\\n' || inChar == '.') {\n      inputComplete = true;\n    } else {\n      // add it to the inputString:\n      inputString += inChar;\n    }\n  }\n}\n\n\nvoid getData() {\n  inputComplete = false;\n\n  \n  if (inputString==\"data\") {\n    sendSensors=true;\n  } else if (inputString.length() > 0) {\n    char cmd = inputString[0];\n    char control = inputString[1];\n    char v1 = inputString[2];\n    char v2 = inputString[3];\n    char value=0;\n    if (v1>='0' && v1<='9') {\n      value+=(v1-'0');\n    } else if (v1>='a' && v1<='f'){\n      value+=(10+v1-'a');\n    }\n    value=value<<4;\n    if (v2>='0' && v2<='9') {\n      value+=(v2-'0');\n    } else if (v2>='a' && v2<='f'){\n      value+=(10+v2-'a');\n    }\n    \n    \n    Serial.print(\"log:\"); Serial.println(inputString);\n    \n    // assumes only one command per packet\n    if (cmd == 'r') {\n      // reset outputs to default values on disconnect\n      analogWrite(LED1_RED, 255);\n      analogWrite(LED1_GREEN, 255);\n      analogWrite(LED1_BLUE, 255);\n      analogWrite(LED2_RED, 255);\n      analogWrite(LED2_GREEN, 255);\n      analogWrite(LED2_BLUE, 255);\n      analogWrite(LED3_RED, 255);\n      analogWrite(LED3_GREEN, 255);\n      analogWrite(LED3_BLUE, 255);\n      servos[0].write(90);\n      servos[0].write(90);\n      servos[0].write(90);\n      digitalWrite(RELAY1, LOW);\n      digitalWrite(RELAY2, LOW);\n      \n    } else if (cmd == 'c') {\n      if (control == '0')\n        analogWrite(LED1_RED, 255 - value);\n      else if (control == '1')\n        analogWrite(LED1_GREEN, 255 - value);\n      else if (control == '2')\n        analogWrite(LED1_BLUE, 255 - value);\n        \n      else if (control == '3')\n        analogWrite(LED2_RED, 255 - value);\n      else if (control == '4')\n        analogWrite(LED2_GREEN, 255 - value);\n      else if (control == '5')\n        analogWrite(LED2_BLUE, 255 - value);\n        \n      else if (control == '6')\n        analogWrite(LED3_RED, 255 - value);\n      else if (control == '7')\n        analogWrite(LED3_GREEN, 255 - value);\n      else if (control == '8')\n        analogWrite(LED3_BLUE, 255 - value);\n        \n    } else if (cmd == 's') {\n      if (control == '0')\n        servos[0].write(map(value, 0, 255, 0, 180));\n      else if (control == '1')\n        servos[1].write(map(value, 0, 255, 0, 180));\n      else if (control == '2')\n        servos[2].write(map(value, 0, 255, 0, 180));\n        \n    } else if (cmd == 't') {\n      if (control == '0')\n        digitalWrite(RELAY1, value ? HIGH : LOW);\n      else if (control == '1')\n        digitalWrite(RELAY2, value ? HIGH : LOW);\n    }\n  }\n  inputString = \"\";\n}\n\n\nvoid sendData() {\n  int i;\n  byte b;\n  uint16_t val;\n  int x, y;\n  boolean c0;\n  \n  static byte count = 0;\n  long touchcount;\n\n  \n  char msg[4];\n\n  msg[0] = '1';\n  \n  b = digitalRead(BUTTON1);\n  if (b != b1) {\n    Serial.print(\"b1:\"); Serial.println((b ? '0' : '1'));\n    //acc.write(msg, 3);\n    b1 = b;\n  }\n  \n  b = digitalRead(BUTTON2);\n  if (b != b2) {\n    Serial.print(\"b2:\"); Serial.println((b ? '0' : '1'));\n    //acc.write(msg, 3);\n    b2 = b;\n  }\n  \n  b = digitalRead(BUTTON3);\n  if (b != b3) {\n    Serial.print(\"b3:\"); Serial.println((b ? '0' : '1'));\n    //acc.write(msg, 3);\n    b3 = b;\n  }\n  \n  \n  b = digitalRead(JOY_SWITCH);\n  if (b != b4) {\n    Serial.print(\"js:\"); Serial.println((b ? '0' : '1'));\n    //acc.write(msg, 3);\n    b4 = b;\n  }\n  \n  touchcount = touch_robot.capSense(5);\n  c0 = touchcount > 300;\n  if (c0 != c) {\n    Serial.print(\"c:\"); Serial.print(c0 ? '1' : '0');\n    c = c0;\n  }\n\n  \n  \n  if (sendSensors) {\n    sendSensors=false;\n\n    val = analogRead(TEMP_SENSOR);\n    Serial.print(\"t:\"); Serial.println(val);\n\n    val = analogRead(LIGHT_SENSOR);\n    Serial.print(\"l:\"); Serial.println(val);\n\n    read_joystick(&x, &y);\n\n    Serial.print(\"jxy:\"); Serial.print(constrain(x, -128, 127));\n    Serial.print(\",\"); Serial.println(constrain(y, -128, 127));\n\n\n  }\n\n}\n\nvoid loop()\n{\n\n  if (inputComplete) {\n    getData();\n    // clear the string:\n    inputString = \"\";\n    inputComplete = false;\n  }\n  \n  if (millis() - count_timer > 10) {\n    count_timer = millis();\n    sendData();\n  }\n  //delay(10);\n}\n\n// ==============================================================================\n// Austria Microsystems i2c Joystick\nvoid init_joystick(int threshold)\n{\n  byte status = 0;\n  \n  pinMode(JOY_SWITCH, INPUT);\n  digitalWrite(JOY_SWITCH, HIGH);\n  \n  pinMode(JOY_nINT, INPUT);\n  digitalWrite(JOY_nINT, HIGH);\n  \n  pinMode(JOY_nRESET, OUTPUT);\n  \n  digitalWrite(JOY_nRESET, 1);\n  delay(1);\n  digitalWrite(JOY_nRESET, 0);\n  delay(1);\n  digitalWrite(JOY_nRESET, 1);\n  \n  Wire.begin();\n  \n  do {\n    status = read_joy_reg(0x0f);\n  } while ((status & 0xf0) != 0xf0);\n  \n  // invert magnet polarity setting, per datasheet\n  write_joy_reg(0x2e, 0x86);\n  \n  calibrate_joystick(threshold);\n}\n\n\nint offset_X, offset_Y;\n\nvoid calibrate_joystick(int dz)\n{\n  char iii;\n  int x_cal = 0;\n  int y_cal = 0;\n  \n  // Low Power Mode, 20ms auto wakeup\n  // INTn output enabled\n  // INTn active after each measurement\n  // Normal (non-Reset) mode\n  write_joy_reg(0x0f, 0x00);\n  delay(1);\n  \n  // dummy read of Y_reg to reset interrupt\n  read_joy_reg(0x11);\n  \n  for(iii = 0; iii != 16; iii++) {\n    while(!joystick_interrupt()) {}\n    \n    x_cal += read_joy_reg(0x10);\n    y_cal += read_joy_reg(0x11);\n  }\n  \n  // divide by 16 to get average\n  offset_X = -(x_cal>>4);\n  offset_Y = -(y_cal>>4);\n  \n  write_joy_reg(0x12, dz - offset_X);  // Xp, LEFT threshold for INTn\n  write_joy_reg(0x13, -dz - offset_X);  // Xn, RIGHT threshold for INTn\n  write_joy_reg(0x14, dz - offset_Y);  // Yp, UP threshold for INTn\n  write_joy_reg(0x15, -dz - offset_Y);  // Yn, DOWN threshold for INTn\n  \n  // dead zone threshold detect requested?\n  if (dz)\n  write_joy_reg(0x0f, 0x04);\n}\n\n\nvoid read_joystick(int *x, int *y)\n{\n  *x = read_joy_reg(0x10) + offset_X;\n  *y = read_joy_reg(0x11) + offset_Y;  // reading Y clears the interrupt\n}\n\nchar joystick_interrupt()\n{\n  return digitalRead(JOY_nINT) == 0;\n}\n\n\n#define  JOY_I2C_ADDR    0x40\n\nchar read_joy_reg(char reg_addr)\n{\n  char c;\n  \n  Wire.beginTransmission(JOY_I2C_ADDR);\n  Wire.write(reg_addr);\n  Wire.endTransmission();\n  \n  Wire.requestFrom(JOY_I2C_ADDR, 1);\n  \n  while(Wire.available())\n    c = Wire.read();\n  \n  return c;\n}\n\nvoid write_joy_reg(char reg_addr, char val)\n{\n  Wire.beginTransmission(JOY_I2C_ADDR);\n  Wire.write(reg_addr);\n  Wire.write(val);\n  Wire.endTransmission();\n}\n"
  },
  {
    "path": "_archive/apps/samples/serial/espruino/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ghbnaccmkndoembcopnaklidmocbdkfp\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Espruino LED toggle\n\nThis sample lets you toggle the state of an LED on an [Espruino JavaScript board](http://www.espruino.com) as well as reading back its current temperature. The board runs JavaScript, so it's easy to control it by sending JavaScript commands directly to it as strings.\n\n1. Connect the Espruino Board\n2. Install and launch this packaged app.\n3. Make sure the drop-down box shows the correct serial device\n4. Click `Connect`\n3. Press the buttons to either toggle the state of an LED, flash it 3 times, or read back the chip's current temperature.\n\n\n## APIs\n\n* [Serial API](http://developer.chrome.com/apps/app.hardware.html#serial)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/serial/espruino/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/serial/espruino/index.html",
    "content": "<!-- Box for choosing the port to connect to -->\n<div id=\"connect_box\" style=\"position: absolute; left : 0; top: 0\">\n  <select id=\"port_list\"><option>Please Wait...</option></select>\n  <button id=\"connect_button\">Connect</button>\n</div>\n\n<!-- Buttons -->\n<div id=\"control_box\" style=\"position: absolute; left : 0; bottom: 0; display : none;\">\n  <button id=\"toggle\">Toggle LED1</button>\n  <button id=\"flash\">Flash LED2</button>\n  <button id=\"get_temperature\">Get Temperature</button>\n</div>\n<!-- Box for log messages -->\n<div id=\"buffer\" style=\"width:100%;height:100%;overflow:auto;\">\n</div>\n<!-- Include main code -->\n<script src=\"main.js\"></script>\n"
  },
  {
    "path": "_archive/apps/samples/serial/espruino/launch.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n\tid: \"mainwin\",\n    innerBounds: {\n      width: 320,\n      height: 240\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/serial/espruino/main.js",
    "content": "const serial = chrome.serial;\n\n/* Interprets an ArrayBuffer as UTF-8 encoded string data. */\nvar ab2str = function(buf) {\n  var bufView = new Uint8Array(buf);\n  var encodedString = String.fromCharCode.apply(null, bufView);\n  return decodeURIComponent(escape(encodedString));\n};\n\n/* Converts a string to UTF-8 encoding in a Uint8Array; returns the array buffer. */\nvar str2ab = function(str) {\n  var encodedString = unescape(encodeURIComponent(str));\n  var bytes = new Uint8Array(encodedString.length);\n  for (var i = 0; i < encodedString.length; ++i) {\n    bytes[i] = encodedString.charCodeAt(i);\n  }\n  return bytes.buffer;\n};\n\n////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////\n\nvar SerialConnection = function() {\n  this.connectionId = -1;\n  this.lineBuffer = \"\";\n  this.boundOnReceive = this.onReceive.bind(this);\n  this.boundOnReceiveError = this.onReceiveError.bind(this);\n  this.onConnect = new chrome.Event();\n  this.onReadLine = new chrome.Event();\n  this.onError = new chrome.Event();\n};\n\nSerialConnection.prototype.onConnectComplete = function(connectionInfo) {\n  if (!connectionInfo) {\n    log(\"Connection failed.\");\n    return;\n  }\n  this.connectionId = connectionInfo.connectionId;\n  serial.onReceive.addListener(this.boundOnReceive);\n  serial.onReceiveError.addListener(this.boundOnReceiveError);\n  this.onConnect.dispatch();\n};\n\nSerialConnection.prototype.onReceive = function(receiveInfo) {\n  if (receiveInfo.connectionId !== this.connectionId) {\n    return;\n  }\n\n  this.lineBuffer += ab2str(receiveInfo.data);\n\n  var index;\n  while ((index = this.lineBuffer.indexOf('\\n')) >= 0) {\n    var line = this.lineBuffer.substr(0, index + 1);\n    this.onReadLine.dispatch(line);\n    this.lineBuffer = this.lineBuffer.substr(index + 1);\n  }\n};\n\nSerialConnection.prototype.onReceiveError = function(errorInfo) {\n  if (errorInfo.connectionId === this.connectionId) {\n    this.onError.dispatch(errorInfo.error);\n  }\n};\n\nSerialConnection.prototype.getDevices = function(callback) {\n  serial.getDevices(callback)\n};\n\nSerialConnection.prototype.connect = function(path) {\n  serial.connect(path, this.onConnectComplete.bind(this))\n};\n\nSerialConnection.prototype.send = function(msg) {\n  if (this.connectionId < 0) {\n    throw 'Invalid connection';\n  }\n  serial.send(this.connectionId, str2ab(msg), function() {});\n};\n\nSerialConnection.prototype.disconnect = function() {\n  if (this.connectionId < 0) {\n    throw 'Invalid connection';\n  }\n  \n};\n\n////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////\n\n\nfunction log(msg) {\n  var buffer = document.querySelector('#buffer');\n  buffer.innerHTML += msg + '<br/>';\n}\n\n\nvar connection = new SerialConnection();\n\nconnection.onConnect.addListener(function() {\n  log('connected...');\n  // remove the connection drop-down\n  document.querySelector('#connect_box').style.display = 'none';\n  document.querySelector('#control_box').style.display = 'block';\n  // Simply send text to Espruino\n  connection.send('\"Hello \"+\"Espruino\"\\n');\n});\n\nconnection.onReadLine.addListener(function(line) {\n  log('read line: ' + line);\n  // if the line 'TEMPERATURE=' foo is returned, set the\n  // set the button's text\n  if (line.indexOf(\"TEMPERATURE=\")==0)\n    document.querySelector('#get_temperature').innerHTML = \"Temp = \"+line.substr(12);\n});\n\n// Populate the list of available devices\nconnection.getDevices(function(ports) {\n  // get drop-down port selector\n  var dropDown = document.querySelector('#port_list');\n  // clear existing options\n  dropDown.innerHTML = \"\";\n  // add new options\n  ports.forEach(function (port) {\n    var displayName = port[\"displayName\"] + \"(\"+port.path+\")\";\n    if (!displayName) displayName = port.path;\n    \n    var newOption = document.createElement(\"option\");\n    newOption.text = displayName;\n    newOption.value = port.path;\n    dropDown.appendChild(newOption);\n  });\n});\n\n// Handle the 'Connect' button\ndocument.querySelector('#connect_button').addEventListener('click', function() {\n  // get the device to connect to\n  var dropDown = document.querySelector('#port_list');\n  var devicePath = dropDown.options[dropDown.selectedIndex].value;\n  // connect\n  log(\"Connecting to \"+devicePath);\n  connection.connect(devicePath);\n});\n\n////////////////////////////////////////////////////////\n\n// Toggle LED state\nvar is_on = false;\ndocument.querySelector('#toggle').addEventListener('click', function() {\n  is_on = !is_on;\n  connection.send(\"digitalWrite(LED1, \"+(is_on ? '1' : '0')+\");\\n\");\n});\n\n// Flash 3 times\ndocument.querySelector('#flash').addEventListener('click', function() {\n  connection.send(\"l=0; var interval = setInterval(function() { digitalWrite(LED2, l&1); if (++l>6) clearInterval(interval); }, 200);\\n\");\n});\n\n// Get temperature\ndocument.querySelector('#get_temperature').addEventListener('click', function() {\n  connection.send(\"console.log('TEMPERATURE='+E.getTemperature().toFixed(1));\\n\");\n});\n\n\n\n"
  },
  {
    "path": "_archive/apps/samples/serial/espruino/manifest.json",
    "content": "{\n  \"name\": \"Espruino Test\",\n  \"version\": \"1\",\n  \"manifest_version\": 2,\n  \"permissions\": [\"serial\"],\n  \"minimum_chrome_version\": \"23\",\n  \"icons\": {\n    \"16\": \"icon_16.png\",\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"launch.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/serial/ledtoggle/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/bdiclhdalonemjdeeaglackjgdboboem\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Arduino LED toggle\n\nNote: on Mac OS X Lion, it's necessary to update USB Serial drivers:\nhttps://web.archive.org/web/20160630184514/http://blog.geekscape.org/wordpress/2011/07/22/mac-os-x-17-lion-upgrading-ftdi-usb-serial-dr\n\nThis sample shows a big button that lets you toggle between the on/off\nstate of an LED connected to an Arduino.\n\n1. Install the LED sketch on your Duo.\n2. Attach a LED to pin 2 (with a resistor to not burn it out).\n3. Install and launch this packaged app.\n4. Press the button to toggle the LED.\n\nFuture version: use the standard Firmata sketch and build a JS firmata driver\nfor Chrome packaged apps.\n\n## APIs\n\n* [Serial API](http://developer.chrome.com/apps/app.hardware.html#serial)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/serial/ledtoggle/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/serial/ledtoggle/index.html",
    "content": "<button style=\"position: absolute; bottom: 0\">Press me</button>\n<div id=\"buffer\">\n</div>\n<script src=\"main.js\"></script>\n"
  },
  {
    "path": "_archive/apps/samples/serial/ledtoggle/launch.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n\tid: \"mainwin\",\n    innerBounds: {\n      width: 320,\n      height: 240\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/serial/ledtoggle/main.js",
    "content": "const DEVICE_PATH = '/dev/ttyACM0';\nconst serial = chrome.serial;\n\n/* Interprets an ArrayBuffer as UTF-8 encoded string data. */\nvar ab2str = function(buf) {\n  var bufView = new Uint8Array(buf);\n  var encodedString = String.fromCharCode.apply(null, bufView);\n  return decodeURIComponent(escape(encodedString));\n};\n\n/* Converts a string to UTF-8 encoding in a Uint8Array; returns the array buffer. */\nvar str2ab = function(str) {\n  var encodedString = unescape(encodeURIComponent(str));\n  var bytes = new Uint8Array(encodedString.length);\n  for (var i = 0; i < encodedString.length; ++i) {\n    bytes[i] = encodedString.charCodeAt(i);\n  }\n  return bytes.buffer;\n};\n\n////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////\n\nvar SerialConnection = function() {\n  this.connectionId = -1;\n  this.lineBuffer = \"\";\n  this.boundOnReceive = this.onReceive.bind(this);\n  this.boundOnReceiveError = this.onReceiveError.bind(this);\n  this.onConnect = new chrome.Event();\n  this.onReadLine = new chrome.Event();\n  this.onError = new chrome.Event();\n};\n\nSerialConnection.prototype.onConnectComplete = function(connectionInfo) {\n  if (!connectionInfo) {\n    log(\"Connection failed.\");\n    return;\n  }\n  this.connectionId = connectionInfo.connectionId;\n  chrome.serial.onReceive.addListener(this.boundOnReceive);\n  chrome.serial.onReceiveError.addListener(this.boundOnReceiveError);\n  this.onConnect.dispatch();\n};\n\nSerialConnection.prototype.onReceive = function(receiveInfo) {\n  if (receiveInfo.connectionId !== this.connectionId) {\n    return;\n  }\n\n  this.lineBuffer += ab2str(receiveInfo.data);\n\n  var index;\n  while ((index = this.lineBuffer.indexOf('\\n')) >= 0) {\n    var line = this.lineBuffer.substr(0, index + 1);\n    this.onReadLine.dispatch(line);\n    this.lineBuffer = this.lineBuffer.substr(index + 1);\n  }\n};\n\nSerialConnection.prototype.onReceiveError = function(errorInfo) {\n  if (errorInfo.connectionId === this.connectionId) {\n    this.onError.dispatch(errorInfo.error);\n  }\n};\n\nSerialConnection.prototype.connect = function(path) {\n  serial.connect(path, this.onConnectComplete.bind(this))\n};\n\nSerialConnection.prototype.send = function(msg) {\n  if (this.connectionId < 0) {\n    throw 'Invalid connection';\n  }\n  serial.send(this.connectionId, str2ab(msg), function() {});\n};\n\nSerialConnection.prototype.disconnect = function() {\n  if (this.connectionId < 0) {\n    throw 'Invalid connection';\n  }\n  serial.disconnect(this.connectionId, function() {});\n};\n\n////////////////////////////////////////////////////////\n////////////////////////////////////////////////////////\n\nvar connection = new SerialConnection();\n\nconnection.onConnect.addListener(function() {\n  log('connected to: ' + DEVICE_PATH);\n  connection.send(\"hello arduino\");\n});\n\nconnection.onReadLine.addListener(function(line) {\n  log('read line: ' + line);\n});\n\nconnection.connect(DEVICE_PATH);\n\nfunction log(msg) {\n  var buffer = document.querySelector('#buffer');\n  buffer.innerHTML += msg + '<br/>';\n}\n\nvar is_on = false;\ndocument.querySelector('button').addEventListener('click', function() {\n  is_on = !is_on;\n  connection.send(is_on ? 'y' : 'n');\n});\n\n"
  },
  {
    "path": "_archive/apps/samples/serial/ledtoggle/manifest.json",
    "content": "{\n  \"name\": \"Serial Test\",\n  \"version\": \"3\",\n  \"manifest_version\": 2,\n  \"permissions\": [\"serial\"],\n  \"minimum_chrome_version\": \"23\",\n  \"icons\": {\n    \"16\": \"icon_16.png\",\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"launch.js\"],\n      \"transient\": true\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/serial/ledtoggle/sketches/serial_light/serial_light.ino",
    "content": "#define LED 13\n\nvoid setup() {\n  Serial.begin(9600);\n  Serial.print(\"\\r\\nStart\");\n\n\n  pinMode(LED, OUTPUT);\n  // Turn it off for now.\n  digitalWrite(LED, LOW);\n}\n\nint incomingByte = 0;\nvoid loop() {\n  // Check if there's a serial message waiting.\n  if (Serial.available() > 0) {\n    // If there is, read the incoming byte.\n    incomingByte = Serial.read();\n    if (incomingByte == 'y') {\n      digitalWrite(LED, HIGH);\n    } else if (incomingByte == 'n') {\n      digitalWrite(LED, LOW);\n    }\n    Serial.println(incomingByte);\n  }\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/serial-control-signals/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/gmlopmidlcfikepbnklkochchhehjpak\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Serial Control Signals\n\nThis sample demonstrates how you can send and receive control signals (DTR, RTS, DCD and CTS) to/from a serial port.\n\n## APIs\n\n* [Serial API](http://developer.chrome.com/apps/app.hardware.html#serial)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/serial-control-signals/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/serial-control-signals/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('main.html', {\n    id: \"mainwin\",\n    innerBounds: {\n      top: 0,\n      left: 0,\n      width: 640,\n      height: 720\n    }\n  });\n})\n"
  },
  {
    "path": "_archive/apps/samples/serial-control-signals/logic.js",
    "content": "var connectionId = -1;\nvar e_dtr, e_rts, e_dcd, e_cts, e_ri, e_dsr;\nvar dtr, rts;\n\nfunction onSetControlSignals(result) {\n  console.log(\"onSetControlSignals: \" + result);\n};\n\nfunction changeSignals() {\n  chrome.serial.setControlSignals(connectionId,\n                                  { dtr: dtr, rts: rts },\n                                  onSetControlSignals);\n}\n\nfunction onGetControlSignals(signals) {\n  e_dcd.innerText = signals.dcd;\n  e_cts.innerText = signals.cts;\n  e_ri.innerText = signals.ri;\n  e_dsr.innerText = signals.dsr;\n}\n\nfunction readSignals() {\n  chrome.serial.getControlSignals(connectionId,\n                                  onGetControlSignals);\n}\n\nfunction onConnect(connectionInfo) {\n  if (!connectionInfo) {\n    setStatus('Could not open');\n    return;\n  }\n  connectionId = connectionInfo.connectionId;\n  setStatus('Connected');\n\n  dtr = false;\n  rts = false;\n  changeSignals();\n\n  setInterval(readSignals, 1000);\n};\n\nfunction setStatus(status) {\n  document.getElementById('status').innerText = status;\n}\n\nfunction buildPortPicker(ports) {\n  var eligiblePorts = ports.filter(function(port) {\n    return !port.path.match(/[Bb]luetooth/);\n  });\n\n  var portPicker = document.getElementById('port-picker');\n  eligiblePorts.forEach(function(port) {\n    var portOption = document.createElement('option');\n    portOption.value = portOption.innerText = port.path;\n    portPicker.appendChild(portOption);\n  });\n\n  portPicker.onchange = function() {\n    if (connectionId != -1) {\n      chrome.serial.disconnect(connectionId, openSelectedPort);\n      return;\n    }\n    openSelectedPort();\n  };\n}\n\nfunction openSelectedPort() {\n  var portPicker = document.getElementById('port-picker');\n  var selectedPort = portPicker.options[portPicker.selectedIndex].value;\n  chrome.serial.connect(selectedPort, onConnect);\n}\n\nonload = function() {\n  e_dtr = document.getElementById('dtr_input');\n  e_rts = document.getElementById('rts_input');\n  e_dtr.onchange = function() {\n    dtr = e_dtr.checked;\n    changeSignals();\n  }\n  e_rts.onchange = function() {\n    rts = e_rts.checked;\n    changeSignals();\n  }\n\n  e_dcd = document.getElementById('dcd_status');\n  e_cts = document.getElementById('cts_status');\n  e_ri = document.getElementById('ri_status');\n  e_dsr = document.getElementById('dsr_status');\n\n  chrome.serial.getDevices(function(devices) {\n    buildPortPicker(devices)\n    openSelectedPort();\n  });\n};\n\n"
  },
  {
    "path": "_archive/apps/samples/serial-control-signals/main.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <script src=\"logic.js\"></script>\n    <link rel=\"stylesheet\" href=\"styles.css\">\n  </head>\n  <body>\n    <div id=\"container\">\n      <label>\n        Port:\n        <select id=\"port-picker\"></select>\n      </label>\n\n      <label>\n        Status:\n        <span id=\"status\">Loading</span>\n      </label>\n    </div>\n\n    <div id=\"inputs\">\n      <label>\n        DCD:\n        <span id=\"dcd_status\">---</span>\n      </label>\n\n      <label>\n        CTS:\n        <span id=\"cts_status\">---</span>\n      </label>\n\n      <label>\n        RI:\n        <span id=\"ri_status\">---</span>\n      </label>\n\n      <label>\n        DSR:\n        <span id=\"dsr_status\">---</span>\n      </label>\n\n      <div id=\"outputs\">\n        <label>\n          DTR:\n          <input type=\"checkbox\" id=\"dtr_input\"></input>\n        </label>\n\n        <label>\n          RTS:\n          <input type=\"checkbox\" id=\"rts_input\"></input>\n        </label>\n\n      </div>\n\n<h3>How to use</h3>\n<ol>\n<li>Identify a serial port on your machine. These days you might need to plug in a USB-to-serial adapter.</li>\n<li>Connect up to six wires to DCD (pin 1), DTR (pin 4), DSR (pin 6), RTS (pin 7), CTS (pin 8), and RI (pin 9). Write down which is which.</li>\n<li>Fire up this app.</li>\n<li>Make sure that the port dropdown matches your serial port.</li>\n<li>Using a multimeter, confirm that any connected outputs (DTR or RTS) swing from negative voltage (true, or checked checkbox) to positive voltage (false, or unchecked checkbox) in sync with their respective checkboxes in the app.</li>\n<li>Provide a reference voltage to any of the inputs (DCD, CTS, RI, and DSR) and confirm that the app's true/false indicators properly update themselves. If you want a quickie reference voltage, just connect one of the outputs to one of the inputs (e.g., DTR to DCD) and flick the output on and off. Note that the input-reading code is on a 1-second timer, so there's often a bit of latency.</li>\n</ol>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/serial-control-signals/manifest.json",
    "content": "{\n  \"name\": \"Serial Control Signals\",\n  \"version\": \"1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"23\",\n  \"description\": \"Test serial control signal API.\",\n\n  \"app\": {\n    \"background\": {\n      \"scripts\": [ \"background.js\" ]\n    }\n  },\n\n  \"permissions\": [\n    \"serial\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/serial-control-signals/styles.css",
    "content": "body {\n  font-family: \"Helvetica Neue\", Helvetica, sans-serif;\n  font-size: 13px;\n}\n"
  },
  {
    "path": "_archive/apps/samples/servo/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/lhedgapiolhajjkgokaplenafmdppmak\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Arduino servo control\n\nNote: on Mac OS X Lion, it's necessary to update USB Serial drivers:\nhttp://blog.geekscape.org/wordpress/2011/07/22/mac-os-x-17-lion-upgrading-ftdi-usb-serial-dr/\n\nThis app displays a slider that, when dragged, causes a servo attached to an Arduino to move. The Arduino sketch is included and should be uploaded to the Arduino.\n\n## APIs\n\n* [Serial API](http://developer.chrome.com/apps/app.hardware.html#serial)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/servo/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/servo/Servo/Servo.ino",
    "content": "#include <Servo.h>\n\n#if 1\n// Normal servo that doesn't freak out with standard zero range.\n#define MIN_PULSE_WIDTH (544)\n#else\n// Off-brand servo that does freak out.\n#define MIN_PULSE_WIDTH (800)\n#endif\n\n#define SERVO_PIN (2)\n#define POT_PIN (7)\nServo myservo;\n\nvoid handle_commands() {\n  if (Serial.available()) {\n    char b = Serial.read();\n    if (b >= '0' && b <= '9') {\n      int d = (b - '0') * 18;\n      myservo.write(d);\n    }\n  }\n}\n\nvoid generate_status() {\n  static char last_pot_char = 0;\n  int pot = analogRead(0);\n  char pot_char = '0' + pot / 103;\n  if (pot_char != last_pot_char) {\n    Serial.print(pot_char);\n    last_pot_char = pot_char;\n  }\n}\n\nvoid set_up_servo() {\n  myservo.attach(SERVO_PIN, MIN_PULSE_WIDTH, 2400);\n\n  // Run through full range to make sure we're working.\n  myservo.write(180);\n  delay(500);\n  myservo.write(0);\n  delay(500);\n}\n\nvoid set_up_pot() {\n  // AREF should equal power supply voltage (5V).\n  analogReference(DEFAULT);\n\n  // Supply current to pot. We did this because we'd already used\n  // up the 5V socket for the servo.\n  pinMode(POT_PIN, OUTPUT);\n  digitalWrite(POT_PIN, HIGH);\n}\n\nvoid setup() {\n  Serial.begin(57600);\n  set_up_pot();\n  set_up_servo();\n}\n\nvoid loop() {\n  handle_commands();\n  generate_status();\n}\n"
  },
  {
    "path": "_archive/apps/samples/servo/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('main.html', {\n    innerBounds: {\n      top: 0,\n      left: 0,\n      width: 640,\n      height: 720\n    }\n  });\n})\n"
  },
  {
    "path": "_archive/apps/samples/servo/main.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <script src=\"servo.js\"></script>\n  <link rel=\"stylesheet\" href=\"styles.css\">\n</head>\n<body>\n  <div id=\"container\">\n    <label>\n      Port:\n      <select id=\"port-picker\"></select>\n    </label>\n\n    <label>\n      Status:\n      <span id=\"status\">Loading</span>\n    </label>\n\n    <label>\n      Input:\n      <input id=\"position-input\" type=\"range\" min=\"0\" max=\"9\" value=\"0\">\n    </label>\n\n    <div id=\"image\"></div>\n  </div>\n\n  <div id=\"tv\" class=\"off\">\n    <video id=\"camera-output\" width=\"640\" height=\"480\" autoplay></video>\n    <img src=\"technical-difficulties.png\" width=\"640\" height=\"480\" alt=\"Please stand by\">\n  </div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/servo/manifest.json",
    "content": "{\n  \"name\": \"Servo Serial Sample\",\n  \"version\": \"0.4\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"23\",\n  \"description\": \"Show off serial functionality.\",\n\n  \"app\": {\n    \"background\": {\n      \"scripts\": [ \"background.js\" ]\n    }\n  },\n\n  \"icons\": {\n    \"16\": \"assets/icon-16x16.jpeg\",\n    \"128\": \"assets/icon-128x128.jpeg\"\n  },\n\n  \"permissions\": [\n    \"serial\",\n    \"videoCapture\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/servo/servo.js",
    "content": "var connectionId = -1;\n\nfunction setPosition(position) {\n  var buffer = new ArrayBuffer(1);\n  var uint8View = new Uint8Array(buffer);\n  uint8View[0] = '0'.charCodeAt(0) + position;\n  chrome.serial.send(connectionId, buffer, function() {});\n};\n\nfunction onReceive(receiveInfo) {\n  if (receiveInfo.connectionId !== connectionId)\n    return;\n\n  var uint8View = new Uint8Array(receiveInfo.data);\n  var value = uint8View[uint8View.length - 1] - '0'.charCodeAt(0);\n  var rotation = value * 18.0;\n  document.getElementById('image').style.webkitTransform =\n    'rotateZ(' + rotation + 'deg)';\n};\n\nfunction onError(errorInfo) {\n  console.warn(\"Receive error on serial connection: \" + errorInfo.error);\n};\n\nchrome.serial.onReceive.addListener(onReceive);\nchrome.serial.onReceiveError.addListener(onError);\n\nfunction onOpen(connectionInfo) {\n  if (!connectionInfo) {\n    setStatus('Could not open');\n    return;\n  }\n  connectionId = connectionInfo.connectionId;\n  setStatus('Connected');\n  setPosition(0);\n};\n\nfunction setStatus(status) {\n  document.getElementById('status').innerText = status;\n}\n\nfunction buildPortPicker(ports) {\n  var eligiblePorts = ports.filter(function(port) {\n    return !port.path.match(/[Bb]luetooth/);\n  });\n\n  var portPicker = document.getElementById('port-picker');\n  eligiblePorts.forEach(function(port) {\n    var portOption = document.createElement('option');\n    portOption.value = portOption.innerText = port.path;\n    portPicker.appendChild(portOption);\n  });\n\n  portPicker.onchange = function() {\n    if (connectionId != -1) {\n      chrome.serial.disconnect(connectionId, openSelectedPort);\n      return;\n    }\n    openSelectedPort();\n  };\n}\n\nfunction openSelectedPort() {\n  var portPicker = document.getElementById('port-picker');\n  var selectedPort = portPicker.options[portPicker.selectedIndex].value;\n  chrome.serial.connect(selectedPort, onOpen);\n}\n\nonload = function() {\n  var tv = document.getElementById('tv');\n  navigator.webkitGetUserMedia(\n      {video: true},\n      function(stream) {\n        tv.classList.add('working');\n        document.getElementById('camera-output').src =\n            webkitURL.createObjectURL(stream);\n      },\n      function() {\n        tv.classList.add('broken');\n      });\n\n  document.getElementById('position-input').onchange = function() {\n    setPosition(parseInt(this.value, 10));\n  };\n\n  chrome.serial.getDevices(function(ports) {\n    buildPortPicker(ports)\n    openSelectedPort();\n  });\n};\n"
  },
  {
    "path": "_archive/apps/samples/servo/styles.css",
    "content": "body {\n  background-color: #f8f8f8;\n  font-family: \"helvetica neue\", helvetica, sans-serif;\n  font-size: 16px;\n  overflow: hidden;\n}\n\nlabel {\n  display: block;\n  padding: 20px;\n  border-bottom: solid 1px #ddd;\n  border-right: solid 1px #ddd;\n  width: 300px;\n}\n\nlabel {\n  color: #999;\n}\n\n#port-picker,\n#status {\n  color: #000;\n}\n\n#port-picker {\n  max-width: 250px;\n  margin-right: 10px;\n}\n\n#position-input {\n  display: block;\n   -webkit-appearance:none !important;\n  width: 90%;\n  margin: 20px auto;\n  height: 6px;\n  background: rgb(13, 168, 97);\n}\n\n#position-input::-webkit-slider-thumb {\n  -webkit-appearance:none !important;\n  width: 30px;\n  height: 30px;\n  border-radius: 15px;\n  background: rgb(67, 135, 253);\n}\n\n#image {\n  position: absolute;\n  right: 10px;\n  top: -10px;\n  background-image: url(chrome-logo.svg);\n  background-size: contain;\n  background-repeat: no-repeat;\n  background-position: center;\n  width: 256px;\n  height: 256px;\n  -webkit-transition: all .2s linear;\n}\n\n#container {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 640px;\n}\n\n#tv {\n  position: absolute;\n  bottom: 0;\n  right: 0;\n  width: 640px;\n  height: 480px;\n  border-left: solid 1px #ddd;\n}\n\n#tv video,\n#tv img {\n  display: none;\n}\n\n#tv.working video,\n#tv.broken img {\n  display: block;\n}"
  },
  {
    "path": "_archive/apps/samples/storage/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/bpncolcpekidijienghhkibflikohggn\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Storage simple test\n\nA very basic application that demonstrates the Filesystem API. It allows you to request a filesystem, write a sample file to it and query how many bytes are available.\n\n## APIs\n\n* [Filesystem](http://developer.chrome.com/apps/app_storage.html)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/storage/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/storage/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('main.html', {\n\tid: \"mainwin\",\n    innerBounds: {\n      'width': 400,\n      'height': 500\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/storage/main.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\" />\n\t<title>Storage test</title>\n\t<script src=\"main.js\"></script>\n</head>\n<body>\n<button id=\"request-quota\">Request Quota</button>\n<button id=\"query-quota\">Query Quota</button>\n<button id=\"request-filesystem\">Request FileSystem and write file</button>\n\n<pre id=\"log\"></pre>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/storage/main.js",
    "content": "var BIG_FILE = 30 * 1024 * 1024;\n\nfunction log(message) {\n  document.getElementById('log').textContent += message + '\\n';\n}\n\nonload = function() {\n  document.getElementById('request-quota').onclick = function() {\n    window.webkitStorageInfo.requestQuota(\n        window.PERSISTENT,\n        BIG_FILE,\n        function(grantedBytes) { log('Granted ' + grantedBytes) },\n        function(e) { log('Error: ' + e); });\n  };\n\n  document.getElementById('query-quota').onclick = function() {\n    window.webkitStorageInfo.queryUsageAndQuota(\n        window.PERSISTENT,\n        function(usage, quota) { log('usage ' + usage + ' quota ' + quota) },\n        function(e) { log('Error: ' + e); });\n  };\n\n  document.getElementById('request-filesystem').onclick = function() {\n    window.webkitRequestFileSystem(\n        PERSISTENT,\n        BIG_FILE,\n        function(fs) {\n            log('Filesystem: ' + fs);\n\n            fs.root.getFile(\n                'test.txt',\n                {create: true, exclusive: true},\n                function(fileEntry) {\n                  log('fileEntry: ' + fileEntry);\n                  fileEntry.createWriter(function(fileWriter) {\n                    log('fileWriter: ' + fileWriter);\n                    fileWriter.onwriteend = function(e) {\n                      log('Write completed.');\n                    };\n\n                    fileWriter.onerror = function(e) {\n                      log('Write failed: ' + e.toString());\n                    };\n\n                  var bb = new WebKitBlobBuilder(); // Note: window.WebKitBlobBuilder in Chrome 12.\n                  for (var i = 0; i < BIG_FILE/50; i++) {\n                    bb.append('01234567890123456789012345678901234567890123456789');\n                  }\n                  fileWriter.write(bb.getBlob('text/plain'));\n                }, function(e) {\n                  log('Error: ' + e);\n                });\n              });\n        },\n        function(e) {log('Error' + e);});\n  };\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/storage/manifest.json",
    "content": "{\n  \"name\": \"Syncable Storage Sample\",\n  \"version\": \"1.1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"23\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [\n    \"unlimitedStorage\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/syncfs-editor/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ccphiekjjhfnhbmpcbmkmjjhbfhlijkc\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\nsyncfs-editor\n=============\n\nCloud-backed text editor using the new chrome.syncFileSystem API.\n(You need to use Chrome M27+ Canary for try this out)\n\nLICENSE:\n-\n\nCopyright 2012, 2013 {kinuko,tzik,nhiroki,calvinlo}@chromium.org\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n## Screenshot\n![screenshot](/_archive/apps/samples/syncfs-editor/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/syncfs-editor/css/editor.css",
    "content": "body {\n  font-family: Verdana, Arial, Helvetica, \"Liberation Sans\", sans-serif;\n  color: #222;\n  background: #fff;\n}\n\n.hide {\n  display: none;\n}\n\n.info {\n  color: #930;\n  font-size: 12px;\n  clear: both;\n}\n\n.error {\n  color: #f00;\n  font-weight: bold;\n  font-size: 12px;\n  clear: both;\n}\n\n#conflict-policy {\n  float: right;\n  font-size: 12px;\n}\n\n#log {\n  color: #666;\n  font-size: 12px;\n  clear: both;\n  border-top: solid 1px #ccc;\n  padding: 3px;\n}\n\n.button, .fs-button {\n  -webkit-border-radius:3px;\n  padding: 1px 4px;\n  margin: 2px 4px;\n  border: solid 1px #ccc;\n}\n\n#fs-selector {\n  margin-top: -1px;\n  padding-bottom: 3px;\n  margin-bottom: 3px;\n  border-bottom: solid 1px #ccc;\n}\n\n.fs-button {\n  font-size: 13px;\n  background: #acf;\n}\n\n.fs-button.selected {\n  color: white;\n  background: #009;\n}\n\n.fs-button:hover {\n  color: white;\n  background: #009;\n}\n\n.button {\n  background: #eee;\n}\n\n.button:hover {\n  background: #fb9;\n}\n\n/* Filer ------------------------------------------------------*/\n\n.filer {\n  height: 400px;\n  width: 250px;\n  float: left;\n  padding: 2px;\n  border-right: solid 1px #ccc;\n}\n\n.filer-tools {\n  margin: 2px 4px;\n  padding: 2px;\n  font-size: 12px;\n  color: #666;\n}\n\n#filer-empty-label {\n  margin-top: 20px;\n  text-align: center;\n  font-size: 12px;\n  color: #ccc;\n}\n\n#filer ul {\n  margin: 0;\n  padding: 0;\n  border: 0;\n  font-size: 100%;\n  font-style: normal;\n  font-weight: normal;\n  list-style: none;\n  text-decoration: none;\n  background: transparent;\n  vertical-align: baseline;\n}\n#filer ul * {\n  font-size: 12px;\n}\n#filer ul ul {\n  margin-top: 1px;\n}\n#filer ul li {\n  margin: 0;\n  padding: 2px 0 1px;\n  position: relative;\n}\n#filer ul li li {\n  padding-left: 20px;\n}\n#filer .dir ul {\n  height: 0;\n  opacity: 0;\n  -webkit-transition: .25s;\n  transition: .15s;\n}\n#filer .dir.open > ul {\n  height: auto;\n  opacity: 1;\n  -webkit-transition: .25s;\n  transition: .15s;\n}\n#filer ul li .entry {\n  padding: 2px 3px;\n  line-height: 18px;\n  border-bottom: solid 1px #ddd;\n}\n#filer ul li .entry *:first-child {\n  text-decoration: none;\n  color: #222222;\n  display: block;\n  width: 70%;\n}\n#filer ul li .entry *:first-child:before {\n  display: inline-block;\n  content: url(../img/filler.png);\n  width: 16px;\n  height: 16px;\n}\n#filer ul li .entry.synced *:first-child:before {\n  display: inline-block;\n  content: url(../img/icon-synced.png);\n  width: 16px;\n  height: 16px;\n}\n#filer ul li .entry.pending *:first-child:before {\n  display: inline-block;\n  content: url(../img/icon-pending.png);\n  width: 16px;\n  height: 16px;\n}\n#filer ul li .entry.conflicting *:first-child:before {\n  display: inline-block;\n  content: url(../img/icon-conflicting.png);\n  width: 16px;\n  height: 16px;\n}\n#filer ul li .entry .size {\n  color: #03a;\n  text-align: right;\n  position: absolute;\n  display: block;\n  top: 3px;\n  font-size: 11px;\n  right: 38px;\n  width: 38px;\n}\n#filer ul li .entry button:last-child {\n  position: absolute;\n  top: 3px;\n  right: 5px;\n  font-size: 11px;\n  background: white;\n  padding: 1px 4px;\n  -webkit-border-radius:3px;\n}\n#filer ul li .entry * {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n#filer ul li .entry .button:hover {\n  background: #fb9;\n}\n#filer .file { background: url(../img/icon_file.png) no-repeat 0; }\n#filer .dir { background: url(../img/icon_folder.png) no-repeat 0; }\n#filer .dir.open { background: url(../img/icon_folder_open.png) no-repeat 0; }\n\n/* Editor -----------------------------------------------------*/\n\n.editor {\n  float: left;\n  margin-left: 10px;\n  height: 400px;\n  width: 480px;\n}\n\n#editor-path {\n  color: #666;\n  font-weight: bold;\n  font-size: 13px;\n}\n\n.editor-tools {\n  margin: 2px 4px;\n  padding: 2px;\n}\n\n.editor-dialog {\n  position: absolute;\n  top: 30%;\n  left: 25%;\n  padding: 30px;\n  background: #eee;\n  z-index: 100;\n  -webkit-border-radius:3px;\n}\n\n.editor-dialog-buttons {\n  text-align: center;\n  margin-top: 5px;\n}\n\n#editor-content {\n  border: solid 1px #ccc;\n  margin: 2px 4px;\n  padding: 2px;\n  font-size: 12px;\n  height: 350px;\n  width: 450px;\n  resize: none;\n}\n"
  },
  {
    "path": "_archive/apps/samples/syncfs-editor/js/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function (arg) {\n  chrome.app.window.create(\n    'main.html',\n    { \n    \tid: \"mainwin\",\n    \tinnerBounds: { width:780, height:490}\n    });\n});\n"
  },
  {
    "path": "_archive/apps/samples/syncfs-editor/js/editor.js",
    "content": "Editor = function(filesystem, container, filer) {\n  this.filesystem = filesystem;\n  this.filer = filer;\n\n  this.container = document.getElementById(container);\n  this.container.innerHTML = '';\n\n  var tools = createElement('div', {class:'editor-tools'});\n  tools.appendChild(createElement('span', {id:'editor-path'}));\n  tools.appendChild(createElement(\n      'button', {id:'editor-save', class:'button',\n                 disabled:true, innerText:'Save'}));\n  tools.appendChild(createElement(\n      'button', {id:'editor-saveas', class:'button',\n                 innerText:'Save As'}));\n  tools.appendChild(createElement(\n      'button', {id:'editor-new', class:'button',\n                 innerText:'New'}));\n  this.container.appendChild(tools);\n\n  appendEditor.call(this, createElement('textarea'));\n\n  function appendEditor(editor) {\n    this.container.appendChild(editor);\n    editor.setAttribute('id', 'editor-content');\n\n    var scratchPath = '* scratch *';\n    this.setCurrentPath(scratchPath);\n    this.isScratch = function() {\n      return ($('#editor-path').innerText == scratchPath);\n    };\n\n    $('#editor-new').addEventListener('click', function() {\n      this.setContent('');\n      this.setCurrentPath(scratchPath);\n    }.bind(this));\n    $('#editor-save').addEventListener('click', this.save.bind(this));\n    $('#editor-saveas').addEventListener('click', this.saveAs.bind(this));\n    $('#editor-content').addEventListener('keydown', function() {\n      if (!this.isScratch())\n        $('#editor-save').disabled = false;\n    }.bind(this));\n    $('body').addEventListener('keydown', function(e) {\n      if (e.keyCode == 27) {\n        var dialog = $('.editor-dialog');\n        if (dialog) dialog.parentNode.removeChild(dialog);\n      }\n    });\n  };\n}\n\nEditor.prototype.open = function(path) {\n  this.filesystem.root.getFile(\n      path, {},\n      this.load.bind(this),\n      error.bind(null, \"getFile \" + path));\n};\n\nEditor.prototype.load = function(entry) {\n  log('Opening: ' + entry.fullPath);\n  this.fileHasNewData = false;\n  this.setCurrentPath(entry.fullPath);\n  entry.file(function(file) {\n    var reader = new FileReader();\n    reader.readAsText(file, \"utf-8\");\n    reader.onload = function(ev) {\n      this.setContent(ev.target.result);\n      $('#editor-save').disabled = true;\n    }.bind(this);\n  }.bind(this), error);\n};\n\nEditor.prototype.save = function() {\n  if (this.isScratch()) {\n    return;\n  }\n  if (this.fileHasNewData) {\n    this.showDialog({\n      dialogLabel: 'The file is updated. Do you want to overwrite it?',\n      submitLabel: 'Overwrite',\n      cancelLabel: 'Cancel',\n      submitCallback: function() {\n        this.fileHasNewData = false;\n        this.save();\n      }.bind(this)\n    });\n    return;\n  }\n  var path = this.getCurrentPath();\n  log('Saving to:' + path);\n  this.filesystem.root.getFile(\n      path, {create: true},\n      function(entry) {\n        entry.createWriter(function (writer) {\n          writer.truncate(0);\n          writer.onerror = error.bind(null, 'writer.truncate');\n          writer.onwriteend = function() {\n            var content = this.getContent();\n            var blob = new Blob([content]);\n            var size = content.length;\n            writer.write(blob);\n            writer.onerror = error;\n            writer.onwriteend = this.onSave.bind(this, entry, size);\n          }.bind(this);\n        }.bind(this));\n      }.bind(this));\n};\n\nEditor.prototype.saveAs = function() {\n  this.showDialog({\n    inputLabel: 'Save as: ',\n    submitLabel: 'Save',\n    cancelLabel: 'Cancel',\n    submitCallback: this.onSaveAs.bind(this),\n  });\n};\n\nEditor.prototype.onSave = function(entry, size) {\n  $('#editor-save').disabled = true;\n  this.fileHasNewData = false;\n  log('File saved: ' + size + ' bytes');\n  this.filer.reload();\n};\n\nEditor.prototype.onSaveAs = function(path) {\n  if (!validFileName(path))\n    return;\n  this.filesystem.root.getFile(\n      path, {create: true, exclusive: true},\n      function(entry) {\n        this.setCurrentPath(entry.fullPath);\n        this.save();\n      }.bind(this),\n      function(e) {\n        error('The path already exists.');\n        this.saveAs();\n      }.bind(this));\n};\n\n// dialogOptions {\n//   dialogLabel: a string value to be shown at the top of the dialog.\n//   inputLabel: a string value to be shown next to the input box.\n//   submitLabel: a string value to be shown on the submit button.\n//   cancelLabel: a string value to be shown on the cancel button.\n//   submitCallback: a callback to be dispatched upon submit.\n//   cancelCallback: callback to be dispatched upon cancel.\n// }\nEditor.prototype.showDialog = function(dialogOptions) {\n  dialogOptions.submitCallback = dialogOptions.submitCallback || function() {};\n  dialogOptions.cancelCallback = dialogOptions.cancelCallback || function() {};\n  var dialog = createElement('div', {class:'editor-dialog'});\n  if (dialogOptions.dialogLabel) {\n    dialog.appendChild(createElement(\n      'div', {innerText: dialogOptions.dialogLabel}));\n  }\n  var getInputValue = function() { return null; };\n  if (dialogOptions.inputLabel) {\n    dialog.appendChild(createElement(\n      'span', {innerText: dialogOptions.inputLabel}));\n    dialog.appendChild(createElement(\n      'input', {id:'editor-dialog-input', type:'text', size:40}));\n    getInputValue = function() { return $('#editor-dialog-input').value; };\n  }\n  var buttons = createElement('div', {class:'editor-dialog-buttons'});\n  buttons.appendChild(createElement(\n    'input', {id:'editor-dialog-submit',\n              value:dialogOptions.submitLabel,\n              type:'button'}));\n  buttons.appendChild(createElement(\n    'input', {id:'editor-dialog-cancel',\n              value:dialogOptions.cancelLabel,\n              type:'button'}));\n  dialog.appendChild(buttons);\n  this.container.appendChild(dialog);\n  if (dialogOptions.inputLabel) {\n    $('#editor-dialog-input').focus();\n    $('#editor-dialog-input').addEventListener('keydown', function(e) {\n      if (e.keyCode == 13) {\n        dialogOptions.submitCallback(getInputValue());\n        dialog.parentNode.removeChild(dialog);\n      }\n    }.bind(this));\n  }\n  $('#editor-dialog-submit').addEventListener('click', function() {\n    dialogOptions.submitCallback(getInputValue());\n    dialog.parentNode.removeChild(dialog);\n  }.bind(this));\n  $('#editor-dialog-cancel').addEventListener('click', function() {\n    dialogOptions.cancelCallback();\n    dialog.parentNode.removeChild(dialog);\n  }.bind(this));\n};\n\nEditor.prototype.getCurrentPath = function() {\n  return $('#editor-path').innerText;\n};\n\nEditor.prototype.setCurrentPath = function(path) {\n  $('#editor-path').innerText = path;\n};\n\nEditor.prototype.getContent = function() {\n  return $('#editor-content').value;\n}\n\nEditor.prototype.setContent = function(content) {\n  $('#editor-content').value = content;\n}\n"
  },
  {
    "path": "_archive/apps/samples/syncfs-editor/js/filer.js",
    "content": "Filer = function(filesystem, container, editor, isSyncable) {\n  this.filesystem = filesystem;\n  this.editor = editor;\n  this.isSyncable = isSyncable;\n\n  // Directory path => ul node mapping.\n  var nodes = {};\n  this.getListNode = function(path) { return nodes[path]; };\n  this.setListNode = function(path, node) { nodes[path] = node; };\n\n  var container = document.getElementById(container);\n  container.innerHTML = '';\n\n  var tools = createElement('div', {class: 'filer-tools'});\n  tools.appendChild(createElement('span', {id:'filer-usage'}));\n  tools.appendChild(createElement(\n      'button', {id:'filer-reload', class:'button', innerText:'Reload'}));\n  container.appendChild(tools);\n  container.appendChild(createElement(\n      'div', {id:'filer-empty-label', innerText:'-- empty --'}));\n\n  // Accept dropping file(s).\n  this.setupDragAndDrop(container);\n\n  // Set up the root node.\n  var rootNode = createElement('ul');\n  this.setListNode('/', rootNode);\n  container.appendChild(rootNode);\n\n  this.reload = function() {\n    rootNode.innerHTML = '';\n    this.showUsage();\n    this.list(filesystem.root);\n  };\n  $('#filer-reload').addEventListener('click', this.reload.bind(this));\n  this.reload();\n\n  if (this.isSyncable) {\n    if (chrome.syncFileSystem.onFileStatusChanged) {\n      chrome.syncFileSystem.onFileStatusChanged.addListener(\n          function(detail) {\n            if (detail.direction == 'remote_to_local') {\n              info('File ' + detail.fileEntry.fullPath +\n                   ' is ' + detail.action + ' by background sync.');\n              if (this.editor.getCurrentPath() == detail.fileEntry.fullPath &&\n                  detail.action == 'updated') {\n                this.editor.fileHasNewData = true;\n              }\n            }\n            this.reload();\n          }.bind(this));\n    }\n    if (chrome.syncFileSystem.onServiceStatusChanged) {\n      chrome.syncFileSystem.onServiceStatusChanged.addListener(\n          function(detail) {\n            log('Service state updated: ' + detail.state + ': '\n                + detail.description);\n          }.bind(this));\n    }\n  }\n};\n\nFiler.prototype.list = function(dir) {\n  // TODO(kinuko): This should be queued up.\n  var node = this.getListNode(dir.fullPath);\n  if (node.fetching)\n    return;\n  node.fetching = true;\n  var reader = dir.createReader();\n  reader.readEntries(this.didReadEntries.bind(this, dir, reader), error);\n};\n\nFiler.prototype.didReadEntries = function(dir, reader, entries) {\n  var node = this.getListNode(dir.fullPath);\n  if (!entries.length) {\n    node.fetching = false;\n    return;\n  }\n\n  hide('#filer-empty-label');\n\n  for (var i = 0; i < entries.length; ++i) {\n    if (entries[i].isFile) {\n      // Get File object so that we can show the file size.\n      entries[i].file(this.addEntry.bind(this, node, entries[i]),\n                      error.bind(null, \"Entry.file:\", entries[i]));\n    } else {\n      this.addEntry(node, entries[i]);\n    }\n  }\n\n  // Continue reading.\n  reader.readEntries(this.didReadEntries.bind(this, dir, reader), error);\n};\n\nFiler.prototype.rename = function(oldName, newName) {\n  this.filesystem.root.getFile(\n    oldName, {create:false},\n    function(entry) {\n      entry.moveTo(this.filesystem.root, newName,\n                   log.bind(null, 'Renamed: ' + oldName + ' -> ' + newName),\n                   error);\n    }.bind(this), error.bind(null, 'getFile:' + oldName));\n};\n\nFiler.prototype.addEntry = function(parentNode, entry, file) {\n  var li = createElement('li', {title: entry.name});\n  var node = createElement('div');\n  node.classList.add(entry.isFile ? 'file' : 'dir');\n  node.classList.add('entry');\n  var a = createElement('a', {href: '#'});\n  var nameNode = document.createTextNode(entry.name);\n  a.appendChild(nameNode);\n  node.appendChild(a);\n  li.appendChild(node);\n\n  if (this.isSyncable && chrome.syncFileSystem.getFileStatus) {\n    chrome.syncFileSystem.getFileStatus(entry, function(status) {\n      node.classList.add(status);\n    });\n  }\n\n  if (!entry.isFile) {\n    console.log('Skipping directory:' + entry.fullPath);\n    return;\n  }\n\n  // Show size in a separate div '<div>[size] KB</div>'\n  var sizeDiv = createElement('div', {class:'size'});\n  sizeDiv.appendChild(document.createTextNode(this.formatSize(file.size)));\n  node.appendChild(sizeDiv);\n\n  // Set up an input field and double-click handler for rename oepration.\n  var inputNode = createElement(\n    'input', {type:'text', value:entry.name, style:'display:inline-block'});\n  inputNode.addEventListener('keydown', function(ev) {\n    if (ev.keyCode == 13) {\n      this.resetRenameFocus = null;\n      var oldName = nameNode.textContent;\n      var newName = inputNode.value;\n      if (!validFileName(newName)) {\n        inputNode.value = oldName;\n        return;\n      }\n      nameNode.textContent = newName;\n      a.replaceChild(nameNode, inputNode);\n      if (oldName != newName)\n        this.rename(oldName, newName);\n    }\n  }.bind(this));\n\n  a.addEventListener('dblclick', function(ev) {\n    if (this.resetRenameFocus)\n      this.resetRenameFocus();\n    this.resetRenameFocus = function() { a.replaceChild(nameNode, inputNode); };\n    a.replaceChild(inputNode, nameNode);\n    inputNode.focus();\n  }.bind(this));\n\n  // Set up click handler to open the file in the editor.\n  a.addEventListener('click', function(ev) {\n    if (this.resetRenameFocus) {\n      this.resetRenameFocus();\n      this.resetRenameFocus = null;\n    }\n    this.editor.open(nameNode.textContent);\n  }.bind(this));\n\n  // Show delete button.\n  var deleteButton = createElement('button',\n    {class:'button delete-button', innerText:'x'});\n  node.appendChild(deleteButton);\n  deleteButton.addEventListener('click', function(ev) {\n    ev.stopPropagation();\n    this.filesystem.root.getFile(\n      nameNode.textContent, {create:false},\n      function(entry) {\n        entry.remove(function() {\n          parentNode.removeChild.bind(parentNode, li),\n          this.reload();\n        }.bind(this), error.bind(this, \"remove:\", entry));\n      }.bind(this));\n  }.bind(this));\n\n  parentNode.appendChild(li);\n};\n\nFiler.prototype.showUsage = function() {\n  if (this.isSyncable && chrome && chrome.syncFileSystem) {\n    chrome.syncFileSystem.getUsageAndQuota(\n      this.filesystem,\n      function(info) {\n        if (chrome.runtime.lastError) {\n          error('getUsageAndQuota: ' + chrome.runtime.lastError.message);\n          return;\n        }\n        $('#filer-usage').innerText =\n            'Usage:' + this.formatSize(info.usageBytes);\n      }.bind(this));\n    return;\n  }\n  webkitStorageInfo.queryUsageAndQuota(\n      this.filesystem,\n      function(usage, quota) {\n        $('#filer-usage').innerText =\n            'Usage:' + this.formatSize(usage);\n      }.bind(this));\n};\n\nFiler.prototype.formatSize = function(size) {\n  var unit = 0;\n  while (size > 1024 && unit < 5) {\n    size /= 1024;\n    unit++;\n  }\n  size = Math.floor(size);\n  return size + ' ' + ['', 'K', 'M', 'G', 'T'][unit] + 'B';\n};\n\nFiler.prototype.setupDragAndDrop = function(elem) {\n  elem.addEventListener('dragover', function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n  }, false);\n  elem.addEventListener('drop', function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n    var items = e.dataTransfer.items;\n    for (var i = 0; i < items.length; ++i) {\n      if (items[i].kind != 'file') {\n        log('Skipping non-file entry:' + items[i].kind);\n        continue;\n      }\n      if (!items[i].webkitGetAsEntry) {\n        error('Entries in drag-and-drop not supported in your browser.');\n        break;\n      }\n      var entry = items[i].webkitGetAsEntry();\n      if (!entry || !entry.isFile) {\n        log('Skipping non-file entries:' + items[i].getAsFile().name);\n        continue;\n      }\n      log('Copying file:' + entry.name);\n      entry.copyTo(this.filesystem.root, entry.name, function(copied) {\n        copied.file(function(file) {\n          log('Copied file:' + copied.name);\n          var node = this.getListNode('/');\n          this.addEntry(node, copied, file);\n        }.bind(this), error);\n      }.bind(this), error);\n    }\n  }.bind(this), false);\n}\n"
  },
  {
    "path": "_archive/apps/samples/syncfs-editor/js/main.js",
    "content": "var supportsSyncFileSystem = chrome && chrome.syncFileSystem;\n\ndocument.addEventListener(\n  'DOMContentLoaded',\n  function() {\n    $('#fs-syncable').addEventListener('click', openSyncableFileSystem);\n    $('#fs-temporary').addEventListener('click', openTemporaryFileSystem);\n\n    if (supportsSyncFileSystem)\n      openSyncableFileSystem();\n    else\n      openTemporaryFileSystem();\n  }\n);\n\nfunction onFileSystemOpened(fs, isSyncable) {\n  log('Got Syncable FileSystem.');\n  console.log('Got FileSystem:' + fs.name);\n  var editor = new Editor(fs, 'editor');\n  var filer = new Filer(fs, 'filer', editor, isSyncable);\n  editor.filer = filer;\n}\n\nfunction openTemporaryFileSystem() {\n  $('#fs-temporary').classList.add('selected');\n  $('#fs-syncable').classList.remove('selected');\n  hide('#conflict-policy')\n  webkitRequestFileSystem(TEMPORARY, 1024,\n                          onFileSystemOpened,\n                          error.bind(null, 'requestFileSystem'));\n}\n\nfunction openSyncableFileSystem() {\n  if (!chrome || !chrome.syncFileSystem ||\n      !chrome.syncFileSystem.requestFileSystem) {\n    error('Syncable FileSystem is not supported in your environment.');\n    return;\n  }\n  $('#fs-syncable').classList.add('selected');\n  $('#fs-temporary').classList.remove('selected');\n  if (chrome.syncFileSystem.setConflictResolutionPolicy) {\n    chrome.syncFileSystem.setConflictResolutionPolicy('last_write_win');\n    show('#conflict-policy')\n  }\n  log('Obtaining syncable FileSystem...');\n  chrome.syncFileSystem.requestFileSystem(function (fs) {\n    if (chrome.runtime.lastError) {\n      error('requestFileSystem: ' + chrome.runtime.lastError.message);\n      $('#fs-syncable').classList.remove('selected');\n      hide('#conflict-policy')\n      return;\n    }\n    onFileSystemOpened(fs, true);\n  });\n}\n\n$('#conflict-policy').addEventListener('click', function() {\n  if ($('#auto-conflict-resolve').checked)\n    policy = 'last_write_win';\n  else\n    policy = 'manual';\n  chrome.syncFileSystem.setConflictResolutionPolicy(policy);\n  log('Changed conflict resolution policy to: ' + policy);\n});\n"
  },
  {
    "path": "_archive/apps/samples/syncfs-editor/js/utils.js",
    "content": "function $(q) {\n  return document.querySelector(q);\n}\n\nfunction show(q) {\n  $(q).classList.remove('hide');\n}\n\nfunction hide(q) {\n  $(q).classList.add('hide');\n}\n\nfunction validFileName(path) {\n  if (!path.length) {\n    error('Empty name was given.');\n    return false;\n  }\n  if (path.indexOf('/') >= 0) {\n    error('File name should not contain any slash (/): \"' + path + '\"');\n    return false;\n  }\n  return true;\n}\n\nfunction log(msg) {\n  document.getElementById('log').innerHTML = msg;\n  console.log(msg, arguments);\n}\n\nfunction createElement(name, attributes) {\n  var elem = document.createElement(name);\n  for (var key in attributes) {\n    if (key == 'id')\n      elem.id = attributes[key];\n    else if (key == 'innerText')\n      elem.innerText = attributes[key];\n    else\n      elem.setAttribute(key, attributes[key]);\n  }\n  return elem;\n}\n\nfunction info(msg) {\n  console.log('INFO: ', arguments);\n  var e = document.getElementById('info');\n  e.innerText = msg;\n  e.classList.remove('hide');\n  window.setTimeout(function() { e.innerHTML = ''; }, 5000);\n}\n\nfunction error(msg) {\n  console.log('ERROR: ', arguments);\n  var message = '';\n  for (var i = 0; i < arguments.length; i++) {\n    var description = '';\n    if (arguments[i] instanceof FileError) {\n      switch (arguments[i].code) {\n        case FileError.QUOTA_EXCEEDED_ERR:\n          description = 'QUOTA_EXCEEDED_ERR';\n          break;\n        case FileError.NOT_FOUND_ERR:\n          description = 'NOT_FOUND_ERR';\n          break;\n        case FileError.SECURITY_ERR:\n          description = 'SECURITY_ERR';\n          break;\n        case FileError.INVALID_MODIFICATION_ERR:\n          description = 'INVALID_MODIFICATION_ERR';\n          break;\n        case FileError.INVALID_STATE_ERR:\n          description = 'INVALID_STATE_ERR';\n          break;\n        default:\n          description = 'Unknown Error';\n          break;\n      }\n      message += ': ' + description;\n    } else if (arguments[i].fullPath) {\n      message += arguments[i].fullPath + ' ';\n    } else {\n      message += arguments[i] + ' ';\n    }\n  }\n  var e = document.getElementById('error');\n  e.innerText = 'ERROR:' + message;\n  e.classList.remove('hide');\n  window.setTimeout(function() { e.innerHTML = ''; }, 5000);\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/syncfs-editor/main.html",
    "content": "<!DOCTYPE html>\n<head>\n  <link rel=\"stylesheet\" href=\"css/editor.css\" type=\"text/css\" />\n  <script type=\"text/javascript\" src=\"js/utils.js\"></script>\n  <script type=\"text/javascript\" src=\"js/filer.js\"></script>\n  <script type=\"text/javascript\" src=\"js/editor.js\"></script>\n  <title>Cloud editor (SyncFileSystem sample)</title>\n</head>\n<body>\n  <div id=\"fs-selector\">\n    <div id=\"conflict-policy\" class=\"hide\">\n      <input id=\"auto-conflict-resolve\" type=\"checkbox\" checked>\n      Resolves Conflicts Automatically\n      </input>\n    </div>\n    <button id=\"fs-syncable\" class=\"fs-button\">Syncable</button>\n    <button id=\"fs-temporary\" class=\"fs-button\">Temporary</button>\n  </div>\n\n  <div id=\"error\" class=\"error\" class=\"hide\"></div>\n\n  <div class=\"filer\" id=\"filer\"></div>\n  <div class=\"editor\" id=\"editor\"></div>\n\n  <div id=\"log\"></div>\n  <div id=\"info\" class=\"info\" class=\"hide\"></div>\n  <script src=\"js/main.js\"></script>\n</body>\n"
  },
  {
    "path": "_archive/apps/samples/syncfs-editor/manifest.json",
    "content": "{\n  \"name\": \"Sync FileSystem Sample\",\n  \"version\": \"0.289\",\n  \"manifest_version\": 2,\n  \"description\": \"SyncFS editor (syncFileSystem sample)\",\n  \"icons\": {\n    \"16\": \"img/icon-16.png\",\n    \"24\": \"img/icon-24.png\",\n    \"128\": \"img/icon-128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"js/background.js\"]\n    }\n  },\n  \"permissions\": [\"syncFileSystem\"]\n}\n"
  },
  {
    "path": "_archive/apps/samples/systemInfo/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/lfkebofdngpbnooppdhiibpdpepgjoch\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# SystemInfo Sample\n\nShows how to use experimental systemInfo APIs to query system information, such\nas CPU, memory and disk storage etc.\n\n## APIs\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n* [Display](http://developer.chrome.com/apps/system_display)\n* [CPU](http://developer.chrome.com/apps/system_cpu)\n* [Memory](http://developer.chrome.com/apps/system_memory)\n* [Storage](http://developer.chrome.com/apps/system_storage)\n\n## Screenshot\n\n![screenshot](/_archive/apps/samples/systemInfo/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/systemInfo/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<title>System Information</title>\n<script src=\"systemInfo.js\"></script>\n<style>\n  html, body {\n    height: 100%;\n  }\n  body {\n    margin: 0 auto;\n    overflow: scroll;\n  }\n  td {\n    white-space: nowrap;\n  }\n</style>\n</head>\n<body>\n<h2>Display Information</h2>\n<div id=\"display-list\">\n   <i> Loading ...</i>\n</div>\n<h2>CPU Information</h2>\n<div id=\"cpu-info\">\n   <i> Loading ...</i>\n</div>\n<h2>Memory Information</h2>\n<div id=\"memory-info\">\n  <i>Loading...</i>\n</div>\n<h2>Storage Information</h2>\n<div id=\"storage-list\">\n  <i>Loading ...</i>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/systemInfo/main.js",
    "content": "/**\n * Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\n\n/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\n chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n\tid: \"mainwin\",\n    innerBounds: {\n      height: 550,\n      width: 800\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/systemInfo/manifest.json",
    "content": "{\n \"name\": \"SystemInfo Sample\",\n \"version\": \"0.5\",\n \"permissions\": [\"system.cpu\", \"system.memory\", \"system.storage\", \"system.display\"],\n \"minimum_chrome_version\": \"34\",\n \"manifest_version\": 2,\n \"description\": \"Show several system information via SystemInfo API\",\n \"app\": {\n   \"background\": {\n     \"scripts\": [\"main.js\"]\n   }\n }\n}\n"
  },
  {
    "path": "_archive/apps/samples/systemInfo/systemInfo.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar systemInfo = chrome.system;\n\nfunction showBounds(bounds) {\n  return bounds.left + \", \" + bounds.top + \", \" +\n      bounds.width + \", \" + bounds.height;\n}\n\nfunction showInsets(bounds) {\n  return bounds.left + \", \" + bounds.top + \", \" +\n      bounds.right + \", \" + bounds.bottom;\n}\n\nfunction showDisplayInfo(display) {\n  table = \"<tr><td>\" + display.id + \"</td>\" +\n    \"<td>\" + display.name + \"</td>\" +\n    \"<td>\" + display.mirroringSourceId + \"</td>\" +\n    \"<td>\" + display.isPrimary + \"</td>\" +\n    \"<td>\" + display.isInternal + \"</td>\" +\n    \"<td>\" + display.isEnabled + \"</td>\" +\n    \"<td>\" + display.dpiX + \"</td>\" +\n    \"<td>\" + display.dpiY + \"</td>\" +\n    \"<td>\" + display.rotation + \"</td>\" +\n    \"<td>\" + showBounds(display.bounds) + \"</td>\" +\n    \"<td>\" + showInsets(display.overscan) + \"</td>\" +\n    \"<td>\" + showBounds(display.workArea) + \"</td>\" +\n    \"</tr>\\n\";\n  return table;\n}\n\nfunction bytesToMegaBytes(number) {\n  return Math.round(number / 1024 / 1024);\n}\n\nfunction showStorageInfo(unit) {\n  table = \"<tr><td>\" + unit.id + \"</td>\" +\n    \"<td>\" + unit.type + \"</td>\" +\n    \"<td>\" + bytesToMegaBytes(unit.capacity) + \"</td>\" +\n    \"<td>\" + bytesToMegaBytes(unit.availableCapacity) + \"</td>\" +\n    \"</tr>\\n\";\n  return table;\n}\n\nfunction showCpuProcessorInfo(processor_number, processor) {\n  table = \"<tr><td>\" + processor_number + \"</td>\" +\n    \"<td>\" + processor.usage.idle + \"</td>\" +\n    \"<td>\" + processor.usage.kernel + \"</td>\" +\n    \"<td>\" + processor.usage.user + \"</td>\" +\n    \"<td>\" + processor.usage.total + \"</td>\" +\n    \"</tr>\\n\";\n  return table;\n}\n\nfunction init() {\n  // Get display information.\n  (function getDisplayInfo() {\n    systemInfo.display.getInfo(function(displays) {\n      var table = \"<table width=70% border=\\\"1\\\">\\n\" +\n        \"<tr><td><b>ID</b></td>\" +\n        \"<td><b>Name</b></td>\" +\n        \"<td><b>Mirroring Source Id</b></td>\" +\n        \"<td><b>Is Primary</b></td>\" +\n        \"<td><b>Is Internal</b></td>\" +\n        \"<td><b>Is Enabled</b></td>\" +\n        \"<td><b>DPI X</b></td>\" +\n        \"<td><b>DPI Y</b></td>\" +\n        \"<td><b>Rotation</b></td>\" +\n        \"<td><b>Bounds</b></td>\" +\n        \"<td><b>Overscan</b></td>\" +\n        \"<td><b>Work Area</b></td>\" +\n        \"</tr>\\n\";\n      for (var i = 0; i < displays.length; i++) {\n        table += showDisplayInfo(displays[i]);\n      }\n      table += \"</table>\\n\";\n      var div = document.getElementById(\"display-list\");\n      div.innerHTML = table;\n    });\n\n    systemInfo.display.onDisplayChanged.addListener(getDisplayInfo);\n  })();\n\n  // Get CPU information.\n  (function getCpuInfo() {\n     systemInfo.cpu.getInfo(function(cpu) {\n       var cpuInfo = \"<b>Architecture:</b> \" + cpu.archName +\n         \"<br><b>Model Name: </b>\" + cpu.modelName +\n         \"<br><b>Number of Processors: </b>\" + cpu.numOfProcessors +\n         \"<br><b>Features: </b>\" + cpu.features.join(' ');\n       cpuInfo += \"<table width=70% border=\\\"1\\\">\\n\" +\n         \"<tr><td><b>Processor</b></td>\" +\n         \"<td><b>Idle time (ms)</b></td>\" +\n         \"<td><b>Kernel time (ms)</b></td>\" +\n         \"<td><b>User time (ms)</b></td>\" +\n         \"<td><b>Total time (ms)</b></td>\" +\n         \"</tr>\\n\";\n       cpu.processors.forEach(function(processor, index) {\n         cpuInfo += showCpuProcessorInfo(index+1, processor);\n       });\n\n       cpuInfo += \"</table>\\n\";\n       var div = document.getElementById(\"cpu-info\");\n       div.innerHTML = cpuInfo;\n     });\n\n     setTimeout(getCpuInfo, 1000);\n  })();\n\n  // Get memory information.\n  (function getMemoryInfo() {\n    systemInfo.memory.getInfo(function(memory) {\n      var memoryInfo =\n      \"<b>Total Capacity:</b> \" + bytesToMegaBytes(memory.capacity) + \"MB\" +\n      \"<br><b>Available Capacity: </b>\" +\n      bytesToMegaBytes(memory.availableCapacity) + \"MB\"\n      var div = document.getElementById(\"memory-info\");\n      div.innerHTML = memoryInfo;\n    });\n\n    setTimeout(getMemoryInfo, 1000);\n  })();\n\n  // Get storage information.\n  (function getStorageInfo() {\n    systemInfo.storage.getInfo(function(units) {\n      var table = \"<table width=70% border=\\\"1\\\">\\n\" +\n        \"<tr><td><b>ID</b></td>\" +\n        \"<td><b>Type</b></td>\" +\n        \"<td><b>Total Capacity (MB)</b></td>\" +\n        \"<td><b>Available Capacity (MB)</b></td>\" +\n        \"</tr>\\n\";\n      function showTable() {\n        table += \"</table>\\n\";\n        var div = document.getElementById(\"storage-list\");\n        div.innerHTML = table;\n      }\n      if (units.length == 0)\n        return showTable();\n      units.forEach(function(unit, index) {\n        systemInfo.storage.getAvailableCapacity(unit.id, function(info) {\n          unit.availableCapacity = info.availableCapacity;\n          table += showStorageInfo(unit);\n          if (index == units.length - 1)\n            showTable();\n        })\n      });\n    });\n\n    systemInfo.storage.onAttached.addListener(getStorageInfo);\n    systemInfo.storage.onDetached.addListener(getStorageInfo);\n  })();\n}\n\ndocument.addEventListener('DOMContentLoaded', init);\n"
  },
  {
    "path": "_archive/apps/samples/tasks/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/tasks-sample-using-gapi/licakmgdnppmfjlkgijcbnobnkoaegko\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Tasks app using GAPI\n\nDemonstrates the usage of GAPI by listing user's Google Tasks. It can be either\nused as a Chrome app, in which case the [GAPI Chrome Apps Lib](https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/libraries/gapi-chrome-apps-lib)\nis used, or as a web page, running on http://localhost:8000, taking advantage\nof the [JavaScript Client Library](https://developers.google.com/api-client-library/javascript/reference/referencedocs).\n\n## Resources\n\n* [JavaScript Client Library Reference](https://developers.google.com/api-client-library/javascript/reference/referencedocs)\n* [GAPI Chrome Apps Lib](https://github.com/GoogleChrome/chrome-app-samples/tree/master/gapi-chrome-apps-lib)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/tasks/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/tasks/gapi-chrome-apps.js",
    "content": "/**\n * Copyright 2013 Google Inc. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n/**\n * gapi-chrome-apps version 0.001\n *\n * Provides the Google API javascript client 'gapi' as\n * appropriate for hosted websites, or if in a Chrome packaged\n * app implement a minimal set of functionality that is Content\n * Security Policy compliant and uses the chrome identity api.\n *\n * https://github.com/GoogleChrome/chrome-app-samples/tree/master/gapi-chrome-apps-lib\n *\n */\n\"use strict\";\n\n(function () {\n  if (typeof gapi !== 'undefined')\n    throw new Error('gapi already defined.');\n  if (typeof gapiIsLoaded !== 'function')\n    throw new Error('gapiIsLoaded callback function must be defined prior to ' +\n                    'loading gapi-chrome-apps.js');\n\n  // If not running in a chrome packaged app, load web gapi:\n  if (!(chrome && chrome.app && chrome.app.runtime)) {\n    // Load web gapi.\n    var script = document.createElement('script');\n    script.src = 'https://apis.google.com/js/client.js?onload=gapiIsLoaded';\n    document.documentElement.appendChild(script);\n    return;\n  }\n\n  window.gapi = {};\n  window.gapi.auth = {};\n  window.gapi.client = {};\n\n  var access_token = undefined;\n\n  gapi.auth.authorize = function (params, callback) {\n    if (typeof callback !== 'function')\n      throw new Error('callback required');\n\n    var details = {};\n    details.interactive = params.immediate === false || false;\n    if (params.accountHint) {\n      // Specifying this prevents the account chooser from appearing on Android.\n      details.accountHint = params.accountHint;\n    }\n    console.assert(!params.response_type || params.response_type == 'token');\n\n    var callbackWrapper = function (getAuthTokenCallbackParam) {\n      access_token = getAuthTokenCallbackParam;\n      // TODO: error conditions?\n      if (typeof access_token !== 'undefined')\n        callback({ access_token: access_token});\n      else\n        callback();\n    }\n\n    chrome.identity.getAuthToken(details, callbackWrapper);\n  };\n\n\n  gapi.client.request = function (args) {\n    if (typeof args !== 'object')\n      throw new Error('args required');\n    if (typeof args.callback !== 'function')\n      throw new Error('callback required');\n    if (typeof args.path !== 'string')\n      throw new Error('path required');\n\n    if (args.root && args.root === 'string') {\n      var path = args.root + args.path;\n    } else {\n      var path = 'https://www.googleapis.com' + args.path;\n    }\n\n    if (typeof args.params === 'object') {\n      var deliminator = '?';\n      for (var i in args.params) {\n        path += deliminator + encodeURIComponent(i) + \"=\"\n          + encodeURIComponent(args.params[i]);\n        deliminator = '&';\n      }\n    }\n\n    var xhr = new XMLHttpRequest();\n    xhr.open(args.method || 'GET', path);\n    xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);\n    if (typeof args.body !== 'undefined') {\n      xhr.setRequestHeader('content-type', 'application/json');\n      xhr.send(JSON.stringify(args.body));\n    } else {\n      xhr.send();\n    }\n\n    xhr.onerror = function () {\n      // TODO, error handling.\n      debugger;\n    };\n\n    xhr.onload = function() {\n      var rawResponseObject = {\n        // TODO: body, headers.\n        gapiRequest: {\n          data: {\n            status: this.status,\n            statusText: this.statusText\n          }\n        }\n      };\n\n      var rawResp = JSON.stringify(rawResponseObject);\n      if (this.response) {\n        var jsonResp = JSON.parse(this.response);\n        args.callback(jsonResp, rawResp);\n      } else {\n        args.callback(null, rawResp);\n      }\n    };\n  };\n\n  // Call client handler when gapi is ready.\n  setTimeout(function () { gapiIsLoaded(); }, 0);\n})();\n"
  },
  {
    "path": "_archive/apps/samples/tasks/gapiCallback.js",
    "content": "/**\n * Prints a list of tasks on a list with a specified |listId|.\n */\nfunction printTasks(listId, jsonResp, rawResp) {\n  if (jsonResp) {\n    var taskListsList = document.querySelector('#' + listId);\n    jsonResp.items.forEach(function(item) {\n      var entry = document.createElement('li');\n      entry.textContent = item.title;\n      taskListsList.appendChild(entry);\n    });\n  }\n}\n\n/**\n * Gets all of the tasks on a task list identitfied by a specified |listId| and\n * then prints them.\n */\nfunction getTasksOnList(listId) {\n  gapi.client.request({\n    'path': '/tasks/v1/lists/' + listId + '/tasks',\n    'callback': printTasks.bind(null, listId)\n  });\n}\n\n/**\n * Takes the |jsonResp| and prints all of the lists of tasks found in the items\n * property.\n */\nfunction printTaskLists(jsonResp, rawResp) {\n  if (jsonResp && jsonResp.items && jsonResp.items.length > 0) {\n    var documentBody = document.querySelector(\"body\");\n    jsonResp.items.forEach(function(item) {\n      var listHeader = document.createElement(\"h2\");\n      listHeader.textContent = item.title;\n      documentBody.appendChild(listHeader);\n      var list = document.createElement(\"ul\");\n      list.id = item.id;\n      documentBody.appendChild(list);\n      getTasksOnList(item.id);\n    });\n  }\n}\n\n/**\n * Gets the list of task lists owned by the user.\n */\nfunction getListsOfTasks() {\n  gapi.client.request({\n    'path': '/tasks/v1/users/@me/lists',\n    'callback': printTaskLists\n  });\n}\n\n/**\n * Prompts the user for authorization and then proceeds to \n */\nfunction authorize(params, callback) {\n  gapi.auth.authorize(params, function(accessToken) {\n    if (!accessToken) {\n      var error = document.createElement(\"p\");\n      error.textContent = 'Unauthorized';\n      document.querySelector(\"body\").appendChild(error);\n    } else {\n      callback();\n    }\n  });\n}\n\nfunction gapiIsLoaded() {\n  var params = { 'immediate': false };\n  if (!(chrome && chrome.app && chrome.app.runtime)) {\n    // This part of the sample assumes that the code is run as a web page, and\n    // not an actual Chrome application, which means it takes advantage of the\n    // GAPI lib loaded from https://apis.google.com/. The client used below\n    // should be working on http://localhost:8000 to avoid origin_mismatch error\n    // when making the authorize calls.\n    params.scope = \"https://www.googleapis.com/auth/tasks.readonly\";\n    params.client_id = \"966771758693-dlbl9dr57ufeovdll13bb0evko6al7o3.apps.googleusercontent.com\";\n    gapi.auth.init(authorize.bind(null, params, getListsOfTasks));\n  } else {\n    authorize(params, getListsOfTasks);\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/tasks/index.html",
    "content": "<html>\n  <head>\n    <title>GAPI Sample App</title>\n    <script src=\"gapiCallback.js\"></script>\n    <script src=\"gapi-chrome-apps.js\"></script>\n  </head>\n  <body>\n    <h2>GAPI Sample Task app</h2>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/tasks/main.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n      id: \"mainwin\",\n      \"innerBounds\": { \"width\": 1024, \"height\": 768 }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/tasks/manifest.json",
    "content": "{\n  \"name\": \"Tasks Sample using GAPI\",\n  \"version\": \"2.1\",\n  \"manifest_version\": 2,\n  \"key\": \"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+EyucIyETym2OR3mPl2EVQULs+1p50pf6dyTdEG+igD41fSpAfEQiXS4Dp+E8ye5HdyBnKUDnSQJ08bAYeTP7z+udV990ddkSSk6uqZTa/o1dr8jv1KDE+MQAF8Qe/XzzddLkaHGQMmATFRbq6IwY8Emk3p7QDcVdTNGFBMxphQIDAQAB\",\n  \"minimum_chrome_version\": \"29\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\"identity\", \"https://www.googleapis.com/*\"],\n  \"oauth2\": {\n    \"client_id\": \"788341667074-i889rgdtvmo60rav3pk4kflmb5rf7cqa.apps.googleusercontent.com\",\n    \"scopes\": [\"https://www.googleapis.com/auth/tasks.readonly\"]\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/tasks/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"tasks\",\n  \"files_with_snippets\": [ ],\n  \"android\": {\"works\": true}\n}\n"
  },
  {
    "path": "_archive/apps/samples/tcpserver/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ahlcocbkjpjkobcdpjcobmibmpbeecpg\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Chrome Commando TCP server\n\nThis is a sample that shows how you can run a network TCP server in a packaged app. This sample allows you to start a server in an arbitrary address and port. Telnet to the listening port and you will be able to remotely control your browser by sending some commands such as `open` and `echo`.\n\n## APIs\n\n* [Sockets](https://developer.chrome.com/apps/sockets_tcp)\n* [Runtime](https://developer.chrome.com/apps/app_runtime)\n* [Window](https://developer.chrome.com/apps/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/tcpserver/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/tcpserver/commands/BrowserCommands.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Renato Mangini (mangini@chromium.org)\n*/\n\n(function(exports) {\n\n  function Commands() {\n  \tthis.commands={};\n  }\n\n  Commands.prototype.addCommand=function(name, help, runnable) {\n  \tif (name in this.commands) {\n  \t\tconsole.log(\"WARNING: ignoring duplicate command \"+name);\n  \t\treturn;\n  \t}\n  \tthis.commands[name] = {help: help, runnable: runnable};\n  }\n\n  Commands.prototype.help=function(name, args) {\n    var result='';\n    for (var command in this.commands) {\n      result+=command+'\\t'+this.commands[command].help+\"\\n\";\n    }\n    return result;\n  \t/*if (! (name in this.commands)) {\n  \t\treturn \"Unknown command \"+name;\n  \t}\n  \tvar context={out: out};\n  \treturn this.commands[name].help.apply(context, args);*/\n  }\n\n  Commands.prototype.run=function(name, args) {\n    if (name === 'help') {\n      return this.help(name, args);\n    }\n  \tif (! (name in this.commands)) {\n  \t\tthrow 'Unknown command '+name+'. Try \"help\"';\n  \t}\n  \tvar context={};\n  \treturn this.commands[name].runnable.call(context, args);\n  }\n\n  exports.Commands=new Commands();\n\n})(window);\n\n\nCommands.addCommand(\"echo\", \n\t\"Echo the arguments\", \n\tfunction(args) {\n\t\treturn args.join(' ');\n\t});\n\nCommands.addCommand(\"open\", \n  \"Open the given URL\", \n  function(args) {\n    chrome.app.window.create('commands/webview.html', {innerBounds: {width: 600, height: 400}},\n      function(w) {\n        w.contentWindow.addEventListener(\"DOMContentLoaded\", function() {\n          var doc=w.contentWindow.document;\n          var el=doc.querySelector(\"webview\");\n          el.src=args[0];\n        });\n      });\n    return \"ok, url \"+args[0]+\" open\";\n  });\n"
  },
  {
    "path": "_archive/apps/samples/tcpserver/commands/webview.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <link href=\"/styles/webview.css\" rel=\"stylesheet\">\n</head>\n<body>\n  <webview autosize=\"on\"></webview>\n</body>\n</html>\n\n"
  },
  {
    "path": "_archive/apps/samples/tcpserver/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>Chrome Remote Comando</title>\n  <link href=\"styles/main.css\" rel=\"stylesheet\">\n</head>\n<body>\n  <section id=\"server\">\n  <h1>Chrome Remote Commando</h1>\n  <div class=\"hide-when-connected\">Serve at \n    <select id=\"addresses\"><option>127.0.0.1</option></select>:\n    <input type=\"number\" id=\"serverPort\" value=\"8888\"></input>\n    <button id=\"serverStart\">Start!</button>\n  </div>\n  <div class=\"hide-when-not-connected\">\n    <p>Serving at <span class=\"serving-at\"></span>\n      <button id=\"serverStop\">Stop!</button></p>\n    <div id=\"serverlog\"></div>\n  </div>\n  </section>\n  <script src=\"server.js\"></script>\n</body>\n</html>\n\n"
  },
  {
    "path": "_archive/apps/samples/tcpserver/main.js",
    "content": "\nvar tcpServer;\nvar commandWindow;\n\n/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/apps/app_runtime\n * @see https://developer.chrome.com/apps/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n\tif (commandWindow && !commandWindow.contentWindow.closed) {\n\t\tcommandWindow.focus();\n\t} else {\n\t\tchrome.app.window.create('index.html',\n\t\t\t{id: \"mainwin\", innerBounds: {width: 500, height: 309, left: 0}},\n\t\t\tfunction(w) {\n\t\t\t\tcommandWindow = w;\n\t\t\t});\n\t}\n});\n\n\n// event logger\nvar log = (function(){\n  var logLines = [];\n  var logListener = null;\n\n  var output=function(str) {\n    if (str.length>0 && str.charAt(str.length-1)!='\\n') {\n      str+='\\n'\n    }\n    logLines.push(str);\n    if (logListener) {\n      logListener(str);\n    }\n  };\n\n  var addListener=function(listener) {\n    logListener=listener;\n    // let's call the new listener with all the old log lines\n    for (var i=0; i<logLines.length; i++) {\n      logListener(logLines[i]);\n    }\n  };\n\n  return {output: output, addListener: addListener};\n})();\n\n\n\nfunction onAcceptCallback(tcpConnection, socketInfo) {\n  var info=\"[\"+socketInfo.peerAddress+\":\"+socketInfo.peerPort+\"] Connection accepted!\";\n  log.output(info);\n  console.log(socketInfo);\n  tcpConnection.addDataReceivedListener(function(data) {\n    var lines = data.split(/[\\n\\r]+/);\n    for (var i=0; i<lines.length; i++) {\n      var line=lines[i];\n      if (line.length>0) {\n        var info=\"[\"+socketInfo.peerAddress+\":\"+socketInfo.peerPort+\"] \"+line;\n        log.output(info);\n\n        var cmd=line.split(/\\s+/);\n        try {\n          tcpConnection.sendMessage(Commands.run(cmd[0], cmd.slice(1)));\n        } catch (ex) {\n          tcpConnection.sendMessage(ex);\n        }\n      }\n    }\n  });\n};\n\nfunction startServer(addr, port) {\n  if (tcpServer) {\n    tcpServer.disconnect();\n  }\n  tcpServer = new TcpServer(addr, port);\n  tcpServer.listen(onAcceptCallback);\n}\n\n\nfunction stopServer() {\n  if (tcpServer) {\n    tcpServer.disconnect();\n    tcpServer=null;\n  }\n}\n\nfunction getServerState() {\n  if (tcpServer) {\n    return {isConnected: tcpServer.isConnected(),\n      addr: tcpServer.addr,\n      port: tcpServer.port};\n  } else {\n    return {isConnected: false};\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/tcpserver/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"TCP Server Sample\",\n  \"version\": \"3.1\",\n  \"minimum_chrome_version\": \"33.0.1715.0\",\n  \"permissions\": [\"webview\", \"system.network\"],\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"tcp-server.js\", \"commands/BrowserCommands.js\", \"main.js\"]\n    }\n  },\n  \"sockets\": {\n    \"tcpServer\": {\n      \"listen\": \"\"\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/tcpserver/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"tcpserver\",\n  \"files_with_snippets\": [ ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/tcpserver/server.js",
    "content": "\n// quick terminal->textarea simulation\nvar log = (function(){\n  var area=document.querySelector(\"#serverlog\");\n  var output=function(str) {\n    if (str.length>0 && str.charAt(str.length-1)!='\\n') {\n      str+='\\n'\n    }\n    area.innerText=str+area.innerText;\n    if (console) console.log(str);\n  };\n  return {output: output};\n})();\n\n\nchrome.runtime.getBackgroundPage(function(bgPage) {\n\n bgPage.log.addListener(function(str) {\n    log.output(str);\n  });\n\n bgPage.TcpServer.getNetworkAddresses(function(list) {\n    var addr=document.querySelector(\"#addresses\");\n    for (var i=0; i<list.length; i++) {\n      if (/^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(list[i].address)) {\n        var option = document.createElement('option');\n        option.text = list[i].name+\" (\"+list[i].address+\")\";\n        option.value = list[i].address;\n        addr.appendChild(option);\n      }\n    };\n  });\n\n  function setConnectedState(addr, port) {\n    document.querySelector(\".serving-at\").innerText=addr+\":\"+port;\n    document.querySelector(\"#server\").className=\"connected\";\n  }\n\n  document.getElementById('serverStart').addEventListener('click', function() {\n    var addr=document.getElementById(\"addresses\").value;\n    var port=parseInt(document.getElementById(\"serverPort\").value);\n    setConnectedState(addr, port);\n    bgPage.startServer(addr, port);\n  });\n\n  document.getElementById('serverStop').addEventListener('click', function() {\n    document.querySelector(\"#server\").className=\"\";\n    bgPage.stopServer();\n  })\n\n  var currentState=bgPage.getServerState();\n  if (currentState.isConnected) {\n    setConnectedState(currentState.addr, currentState.port);\n  }\n\n})\n"
  },
  {
    "path": "_archive/apps/samples/tcpserver/styles/main.css",
    "content": "body {\n  font-family: Arial, sans-serif;\n  background: #333;\n  color: white;\n}\n\n.hide-when-not-connected {\n  display: none;\n}\n\n.connected .hide-when-not-connected {\n  display: block;\n}\n\n\n.connected .hide-when-not-connected p {\n  color: #33ff44\n}\n\n.connected .hide-when-connected {\n  display: none;\n}\n\ninput[type=\"number\"] {\n  width: 5em;\n}\n\nbutton {\n  cursor: pointer;\n  margin-left: 20px;\n}\n\n#serverStop {\n  background-color: #D14836;\n  background-image: -webkit-linear-gradient(top,#DD4B39,#D14836);\n  border: 1px solid transparent;\n  color: white;\n  border-radius: 2px;\n}\n\n#serverStop:hover {\n  background-color: #C53727;\n  background-image: -webkit-linear-gradient(top, #DD4B39, #C53727);\n  border: 1px solid #B0281A;\n}\n#serverlog {\n  background: #444;\n  color: #999;\n\twidth: 480px;\n\theight: 180px;\n\tborder: 1px solid #666;\n\tpadding: 3px;\n\toverflow: auto;\n}"
  },
  {
    "path": "_archive/apps/samples/tcpserver/styles/webview.css",
    "content": "html, body, webview {\n  height: 100%;\n  width: 100%;\n}\n\nbody {\n  margin: 0;\n}\n"
  },
  {
    "path": "_archive/apps/samples/tcpserver/tcp-server.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Renato Mangini (mangini@chromium.org)\n*/\n\nconst DEFAULT_MAX_CONNECTIONS=5;\n\n(function(exports) {\n\n  // Define some local variables here.\n  var socket = chrome.sockets.tcpServer;\n\n  /**\n   * Creates an instance of the client\n   *\n   * @param {String} host The remote host to connect to\n   * @param {Number} port The port to connect to at the remote host\n   */\n  function TcpServer(addr, port, options) {\n    this.addr = addr;\n    this.port = port;\n    this.maxConnections = typeof(options) != 'undefined'\n        && options.maxConnections || DEFAULT_MAX_CONNECTIONS;\n\n    this._onAccept = this._onAccept.bind(this);\n    this._onAcceptError = this._onAcceptError.bind(this);\n\n    // Callback functions.\n    this.callbacks = {\n      listen: null,    // Called when socket is connected.\n      connect: null,    // Called when socket is connected.\n      disconnect: null, // Called when socket is disconnected.\n      recv: null,       // Called when client receives data from server.\n      sent: null        // Called when client sends data to server.\n    };\n\n    // Sockets open\n    this.openSockets=[];\n\n    // server socket (one server connection, accepts and opens one socket per client)\n    this.serverSocketId = null;\n\n    log('initialized tcp server, not listening yet');\n  }\n\n\n  /**\n   * Static method to return available network interfaces.\n   *\n   * @see https://developer.chrome.com/apps/system_network#method-getNetworkInterfaces\n   *\n   * @param {Function} callback The function to call with the available network\n   * interfaces. The callback parameter is an array of\n   * {name(string), address(string)} objects. Use the address property of the\n   * preferred network as the addr parameter on TcpServer contructor.\n   */\n  TcpServer.getNetworkAddresses=function(callback) {\n    chrome.system.network.getNetworkInterfaces(callback);\n  }\n\n  TcpServer.prototype.isConnected=function() {\n    return this.serverSocketId > 0;\n  }\n\n  /**\n   * Connects to the TCP socket, and creates an open socket.\n   *\n   * @see https://developer.chrome.com/apps/sockets_tcpServer#method-create\n   * @param {Function} callback The function to call on connection\n   */\n  TcpServer.prototype.listen = function(callback) {\n    // Register connect callback.\n    this.callbacks.connect = callback;\n    socket.create({}, this._onCreate.bind(this));\n  };\n\n\n  /**\n   * Disconnects from the remote side\n   *\n   * @see https://developer.chrome.com/apps/sockets_tcpServer#method-disconnect\n   */\n  TcpServer.prototype.disconnect = function() {\n    if (this.serverSocketId) {\n      socket.onAccept.removeListener(this._onAccept);\n      socket.onAcceptError.removeListener(this._onAcceptError);\n      socket.close(this.serverSocketId);\n    }\n    for (var i=0; i<this.openSockets.length; i++) {\n      try {\n        this.openSockets[i].close();\n      } catch (ex) {\n        console.log(ex);\n      }\n    }\n    this.openSockets=[];\n    this.serverSocketId=0;\n  };\n\n  /**\n   * The callback function used for when we attempt to have Chrome\n   * create a socket. If the socket is successfully created\n   * we go ahead and start listening for incoming connections.\n   *\n   * @private\n   * @see https://developer.chrome.com/apps/sockets_tcpServer#method-listen\n   * @param {Object} createInfo The socket details\n   */\n  TcpServer.prototype._onCreate = function(createInfo) {\n    this.serverSocketId = createInfo.socketId;\n    if (this.serverSocketId > 0) {\n      socket.onAccept.addListener(this._onAccept);\n      socket.onAcceptError.addListener(this._onAcceptError);\n      socket.listen(this.serverSocketId, this.addr, this.port, 50,\n        this._onListenComplete.bind(this));\n      this.isListening = true;\n    } else {\n      error('Unable to create socket');\n    }\n  };\n\n  /**\n   * The callback function used for when we attempt to have Chrome\n   * connect to the remote side. If a successful connection is\n   * made then we accept it by opening it in a new socket (accept method)\n   *\n   * @private\n   */\n  TcpServer.prototype._onListenComplete = function(resultCode) {\n    if (resultCode !==0) {\n      error('Unable to listen to socket. Resultcode='+resultCode);\n    }\n  }\n\n  TcpServer.prototype._onAccept = function (info) {\n    if (info.socketId != this.serverSocketId)\n      return;\n\n    if (this.openSockets.length >= this.maxConnections) {\n      this._onNoMoreConnectionsAvailable(info.clientSocketId);\n      return;\n    }\n\n    var tcpConnection = new TcpConnection(info.clientSocketId);\n    this.openSockets.push(tcpConnection);\n\n    tcpConnection.requestSocketInfo(this._onSocketInfo.bind(this));\n    log('Incoming connection handled.');\n  }\n\n  TcpServer.prototype._onAcceptError = function(info) {\n    if (info.socketId != this.serverSocketId)\n      return;\n\n    error('Unable to accept incoming connection. Error code=' + info.resultCode);\n  }\n\n  TcpServer.prototype._onNoMoreConnectionsAvailable = function(socketId) {\n    var msg=\"No more connections available. Try again later\\n\";\n    _stringToArrayBuffer(msg, function(arrayBuffer) {\n      chrome.sockets.tcp.send(socketId, arrayBuffer,\n        function() {\n          chrome.sockets.tcp.close(socketId);\n        });\n    });\n  }\n\n  TcpServer.prototype._onSocketInfo = function(tcpConnection, socketInfo) {\n    if (this.callbacks.connect) {\n      this.callbacks.connect(tcpConnection, socketInfo);\n    }\n  }\n\n  /**\n   * Holds a connection to a client\n   *\n   * @param {number} socketId The ID of the server<->client socket\n   */\n  function TcpConnection(socketId) {\n    this.socketId = socketId;\n    this.socketInfo = null;\n\n    // Callback functions.\n    this.callbacks = {\n      disconnect: null, // Called when socket is disconnected.\n      recv: null,       // Called when client receives data from server.\n      sent: null        // Called when client sends data to server.\n    };\n\n    log('Established client connection. Listening...');\n\n  };\n\n  TcpConnection.prototype.setSocketInfo = function(socketInfo) {\n    this.socketInfo = socketInfo;\n  };\n\n  TcpConnection.prototype.requestSocketInfo = function(callback) {\n    chrome.sockets.tcp.getInfo(this.socketId,\n      this._onSocketInfo.bind(this, callback));\n  };\n\n  /**\n   * Add receive listeners for when a message is received\n   *\n   * @param {Function} callback The function to call when a message has arrived\n   */\n  TcpConnection.prototype.startListening = function(callback) {\n    this.callbacks.recv = callback;\n\n    // Add receive listeners.\n    this._onReceive = this._onReceive.bind(this);\n    this._onReceiveError = this._onReceiveError.bind(this);\n    chrome.sockets.tcp.onReceive.addListener(this._onReceive);\n    chrome.sockets.tcp.onReceiveError.addListener(this._onReceiveError);\n\n    chrome.sockets.tcp.setPaused(this.socketId, false);\n  };\n\n  /**\n   * Sets the callback for when a message is received\n   *\n   * @param {Function} callback The function to call when a message has arrived\n   */\n  TcpConnection.prototype.addDataReceivedListener = function(callback) {\n    // If this is the first time a callback is set, start listening for incoming data.\n    if (!this.callbacks.recv) {\n      this.startListening(callback);\n    } else {\n      this.callbacks.recv = callback;\n    }\n  };\n\n\n  /**\n   * Sends a message down the wire to the remote side\n   *\n   * @see https://developer.chrome.com/apps/sockets_tcp#method-send\n   * @param {String} msg The message to send\n   * @param {Function} callback The function to call when the message has sent\n   */\n  TcpConnection.prototype.sendMessage = function(msg, callback) {\n    _stringToArrayBuffer(msg + '\\n', function(arrayBuffer) {\n      chrome.sockets.tcp.send(this.socketId, arrayBuffer, this._onWriteComplete.bind(this));\n    }.bind(this));\n\n    // Register sent callback.\n    this.callbacks.sent = callback;\n  };\n\n\n  /**\n   * Disconnects from the remote side\n   *\n   * @see https://developer.chrome.com/apps/sockets_tcp#method-close\n   */\n  TcpConnection.prototype.close = function() {\n    if (this.socketId) {\n      chrome.sockets.tcp.onReceive.removeListener(this._onReceive);\n      chrome.sockets.tcp.onReceiveError.removeListener(this._onReceiveError);\n      chrome.sockets.tcp.close(this.socketId);\n    }\n  };\n\n\n  /**\n   * Callback function for when socket details (socketInfo) is received.\n   * Stores the socketInfo for future reference and pass it to the\n   * callback sent in its parameter.\n   *\n   * @private\n   */\n  TcpConnection.prototype._onSocketInfo = function(callback, socketInfo) {\n    if (callback && typeof(callback)!='function') {\n      throw \"Illegal value for callback: \"+callback;\n    }\n    this.socketInfo = socketInfo;\n    callback(this, socketInfo);\n  }\n\n  /**\n   * Callback function for when data has been read from the socket.\n   * Converts the array buffer that is read in to a string\n   * and sends it on for further processing by passing it to\n   * the previously assigned callback function.\n   *\n   * @private\n   * @see TcpConnection.prototype.addDataReceivedListener\n   * @param {Object} readInfo The incoming message\n   */\n  TcpConnection.prototype._onReceive = function(info) {\n    if (this.socketId != info.socketId)\n      return;\n\n    // Call received callback if there's data in the response.\n    if (this.callbacks.recv) {\n      log('onDataRead');\n      // Convert ArrayBuffer to string.\n      _arrayBufferToString(info.data, this.callbacks.recv.bind(this));\n    }\n  };\n\n  TcpConnection.prototype._onReceiveError = function (info) {\n    if (this.socketId != info.socketId)\n      return;\n    this.close();\n  };\n\n  /**\n   * Callback for when data has been successfully\n   * written to the socket.\n   *\n   * @private\n   * @param {Object} writeInfo The outgoing message\n   */\n  TcpConnection.prototype._onWriteComplete = function(writeInfo) {\n    log('onWriteComplete');\n    // Call sent callback.\n    if (this.callbacks.sent) {\n      this.callbacks.sent(writeInfo);\n    }\n  };\n\n\n\n  /**\n   * Converts an array buffer to a string\n   *\n   * @private\n   * @param {ArrayBuffer} buf The buffer to convert\n   * @param {Function} callback The function to call when conversion is complete\n   */\n  function _arrayBufferToString(buf, callback) {\n    var bb = new Blob([new Uint8Array(buf)]);\n    var f = new FileReader();\n    f.onload = function(e) {\n      callback(e.target.result);\n    };\n    f.readAsText(bb);\n  }\n\n  /**\n   * Converts a string to an array buffer\n   *\n   * @private\n   * @param {String} str The string to convert\n   * @param {Function} callback The function to call when conversion is complete\n   */\n  function _stringToArrayBuffer(str, callback) {\n    var bb = new Blob([str]);\n    var f = new FileReader();\n    f.onload = function(e) {\n        callback(e.target.result);\n    };\n    f.readAsArrayBuffer(bb);\n  }\n\n\n  /**\n   * Wrapper function for logging\n   */\n  function log(msg) {\n    console.log(msg);\n  }\n\n  /**\n   * Wrapper function for error logging\n   */\n  function error(msg) {\n    console.error(msg);\n  }\n\n  exports.TcpServer = TcpServer;\n  exports.TcpConnection = TcpConnection;\n\n})(window);\n"
  },
  {
    "path": "_archive/apps/samples/telnet/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ebckmolcafdmfjbkmamhoacnmmkiohpe\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Telnet\n\nUses the Socket API to connect as a TCP client to aardmud.org on port 4000.\nRenders it in glorious ANSIColor for your viewing joy.\n\n* TCP client\n* ANSI color renderer\n* DNS resolver [Deprecated]\n\n## Resources\n\n* [Sockets](https://developer.chrome.com/apps/sockets_tcp)\n* [Runtime](https://developer.chrome.com/apps/app_runtime)\n* [Window](https://developer.chrome.com/apps/app_window)\n\n## Credits\n\nNetworking stuff, ANSI colors by Boris Smus.\nTerminal by Eric Bidelman: http://www.htmlfivewow.com/demos/terminal/terminal.html\n\n## Screenshot\n![screenshot](/_archive/apps/samples/telnet/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/telnet/ansi-converter.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Boris Smus (smus@chromium.org)\n*/\n\n(function(exports) {\n  var COLOR_TABLE = {\n    0: 'black',\n    1: 'red',\n    2: 'green',\n    3: 'yellow',\n    4: 'blue',\n    5: 'magenta',\n    6: 'cyan',\n    7: 'white'\n  };\n\n  var ANSI_ESC = String.fromCharCode(0x1B);\n  var ANSI_CODE_REGEX = new RegExp(ANSI_ESC + '\\\\[(.+?)m', 'g');\n\n  function A() {\n  }\n\n  /**\n   * Given an ANSI string, format it in HTML.\n   *\n   * @param {String} ansiString The string to format\n   */\n  A.prototype.formatAnsi = function(ansiString) {\n    var out = ansiString;\n    // Remove all of the control characters.\n    out = out.replace(new RegExp(String.fromCharCode(65533), 'g'), '');\n    // Replace every space with a nbsp.\n    out = out.replace(/ /g, '&nbsp;');\n    // Replace every ANSI code in the string with the appropriate span.\n    out = out.replace(ANSI_CODE_REGEX, this._replaceCodeWithHTML);\n    return out;\n  };\n\n  /**\n   * Replaces an ANSI Code in the string\n   * with a span-wrapped version. Used as\n   * a callback in the formatAnsi function\n   *\n   * @param {String} matched The substring that matched\n   * @param {String} ansiString The actual matched string\n   * @param {Number} index The offset of the match within the overall string\n   * @param {String} s The overall string\n   */\n  A.prototype._replaceCodeWithHTML = function(matched, ansiString, index, s) {\n    // Extract the ansiCode from the string.\n    var split = ansiString.split(';');\n    var ansiCode = parseInt(split[split.length - 1], 10);\n    // Convert code to color code.\n    var colorCode = ansiCode - 30;\n    // Lookup the corresponding style.\n    var style = 'color: ' + COLOR_TABLE[colorCode];\n    return '<span style=\"' + style + ';\">';\n  };\n\n  exports.AnsiConverter = A;\n})(window);\n"
  },
  {
    "path": "_archive/apps/samples/telnet/launch.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('terminal.html', {\n  \tid: \"mainwin\",\n    innerBounds: {\n      width: 880,\n      height: 480\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/telnet/main.js",
    "content": "/**\n * Shows and hides the help panel\n */\nfunction toggleHelp() {\n  document.querySelector('.help').classList.toggle('hidden');\n  document.body.classList.toggle('dim');\n}\n\n(function() {\n\n  // Create and init the terminal\n  var term = new Terminal('container');\n  term.initFS(false, 1024 * 1024);\n\n  // Capture key presses\n  document.body.addEventListener('keydown', function(e) {\n    if (e.keyCode == 27) { // Esc\n      toggleHelp();\n      e.stopPropagation();\n      e.preventDefault();\n    }\n  }, false);\n\n  term.output('Press Esc for options.<br/>');\n\n  // Make an ANSI Color converter.\n  var ansiConv = new AnsiConverter();\n\n  // Connect to aardmud by default.\n  var host = 'aardmud.org';\n  var port = 4000;\n  connect(host, port);\n\n  // Bind the connect dialog to real stuff.\n  var button = document.getElementById('connect');\n  button.addEventListener('click', function() {\n\n    // Disconnect from previous socket.\n    var host = document.getElementById('host').value;\n    var port = parseInt(document.getElementById('port').value, 10);\n    tcpClient.disconnect();\n    connect(host, port);\n    toggleHelp();\n\n  });\n\n  /**\n   * Connects to a host and port\n   *\n   * @param {String} host The remote host to connect to\n   * @param {Number} port The port to connect to at the remote host\n   */\n  function connect(host, port) {\n    tcpClient = new TcpClient(host, port);\n    tcpClient.connect(function() {\n      term.output('Connected to ' + host + ':' + port + '<br/>');\n      tcpClient.addResponseListener(function(data) {\n        // Run response through ANSI colorizer.\n        var formattedData = ansiConv.formatAnsi(data);\n        // Split into multiple lines.\n        var lines = formattedData.split('\\n');\n        // Render response in the terminal.\n        var output = lines.join('<br/>');\n        term.output(output);\n      });\n    });\n  }\n\n})();\n\n"
  },
  {
    "path": "_archive/apps/samples/telnet/manifest.json",
    "content": "{\n  \"name\": \"Telnet Client\",\n  \"version\": \"2.1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"33.0.1715.0\",\n  \"icons\": {\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"launch.js\"]\n    }\n  },\n  \"sockets\": {\n    \"tcp\": {\n      \"connect\": \"*:*\"\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/telnet/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"telnet\",\n  \"files_with_snippets\": [ ],\n  \"android\": {\"works\": false, \"comments\": \"Can't enter CR/LF in virtual keyboards\"},\n  \"ios\": {\"works\": false, \"comments\": \"Can't enter CR/LF in virtual keyboards and display issues\"}\n}\n"
  },
  {
    "path": "_archive/apps/samples/telnet/tcp-client.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Boris Smus (smus@chromium.org)\n*/\n\n(function(exports) {\n\n  /**\n   * Creates an instance of the client\n   *\n   * @param {String} host The remote host to connect to\n   * @param {Number} port The port to connect to at the remote host\n   */\n  function TcpClient(host, port) {\n    this.host = host;\n    this.port = port;\n    this._onReceive = this._onReceive.bind(this);\n    this._onReceiveError = this._onReceiveError.bind(this);\n\n    // Callback functions.\n    this.callbacks = {\n      connect: null,    // Called when socket is connected.\n      disconnect: null, // Called when socket is disconnected.\n      recv: null,       // Called when client receives data from server.\n      sent: null        // Called when client sends data to server.\n    };\n\n    // Socket.\n    this.socketId = null;\n    this.isConnected = false;\n\n    log('initialized tcp client');\n  }\n\n  /**\n   * Connects to the TCP socket, and creates an open socket.\n   *\n   * @see http://developer.chrome.com/apps/sockets_tcp.html#method-create\n   * @param {Function} callback The function to call on connection\n   */\n  TcpClient.prototype.connect = function(callback) {\n    // Register connect callback.\n    this.callbacks.connect = callback;\n\n    chrome.sockets.tcp.create({}, this._onCreate.bind(this));\n  };\n\n  /**\n   * Sends a message down the wire to the remote side\n   *\n   * @see http://developer.chrome.com/apps/sockets_tcp.html#method-send\n   * @param {String} msg The message to send\n   * @param {Function} callback The function to call when the message has sent\n   */\n  TcpClient.prototype.sendMessage = function(msg, callback) {\n    // Register sent callback.\n    this.callbacks.sent = callback;\n\n    this._stringToArrayBuffer(msg + '\\n', function(arrayBuffer) {\n      chrome.sockets.tcp.send(this.socketId, arrayBuffer, this._onSendComplete.bind(this));\n    }.bind(this));\n  };\n\n  /**\n   * Sets the callback for when a message is received\n   *\n   * @param {Function} callback The function to call when a message has arrived\n   */\n  TcpClient.prototype.addResponseListener = function(callback) {\n    // Register received callback.\n    this.callbacks.recv = callback;\n  };\n\n  /**\n   * Disconnects from the remote side\n   *\n   * @see http://developer.chrome.com/apps/sockets_tcp.html#method-disconnect\n   */\n  TcpClient.prototype.disconnect = function() {\n    chrome.sockets.tcp.onReceive.removeListener(this._onReceive);\n    chrome.sockets.tcp.onReceiveError.removeListener(this._onReceiveError);\n    chrome.sockets.tcp.disconnect(this.socketId);\n    chrome.sockets.tcp.close(this.socketId);\n    this.socketId = null;\n    this.isConnected = false;\n  };\n\n  /**\n   * The callback function used for when we attempt to have Chrome\n   * create a socket. If the socket is successfully created\n   * we go ahead and connect to the remote side.\n   *\n   * @private\n   * @see http://developer.chrome.com/apps/sockets_tcp.html#method-connect\n   * @param {Object} createInfo The socket details\n   */\n  TcpClient.prototype._onCreate = function(createInfo) {\n    if (chrome.runtime.lastError) {\n      error('Unable to create socket: ' + chrome.runtime.lastError.message);\n    }\n\n    this.socketId = createInfo.socketId;\n    this.isConnected = true;\n    chrome.sockets.tcp.connect(this.socketId, this.host, this.port, this._onConnectComplete.bind(this));\n  };\n\n  /**\n   * The callback function used for when we attempt to have Chrome\n   * connect to the remote side. If a successful connection is\n   * made then polling starts to check for data to read\n   *\n   * @private\n   * @param {Number} resultCode Indicates whether the connection was successful\n   */\n  TcpClient.prototype._onConnectComplete = function(resultCode) {\n    if (resultCode < 0) {\n      error('Unable to connect to server');\n      return;\n    }\n\n    // Start listening to message events.\n    chrome.sockets.tcp.onReceive.addListener(this._onReceive);\n    chrome.sockets.tcp.onReceiveError.addListener(this._onReceiveError);\n\n    if (this.callbacks.connect) {\n      console.log('connect complete');\n      this.callbacks.connect();\n    }\n    log('onConnectComplete');\n  };\n\n  /**\n   * Callback function for when data has been read from the socket.\n   * Converts the array buffer that is read in to a string\n   * and sends it on for further processing by passing it to\n   * the previously assigned callback function.\n   *\n   * @see http://developer.chrome.com/apps/sockets_tcp.html#event-onReceive\n   *\n   * @private\n   * @see TcpClient.prototype.addResponseListener\n   * @param {Object} receiveInfo The incoming message\n   */\n  TcpClient.prototype._onReceive = function(receiveInfo) {\n    if (receiveInfo.socketId != this.socketId)\n      return;\n\n    if (this.callbacks.recv) {\n      log('onDataRead');\n      // Convert ArrayBuffer to string.\n      this._arrayBufferToString(receiveInfo.data, function(str) {\n        this.callbacks.recv(str);\n      }.bind(this));\n    }\n  };\n\n  /**\n   * Callback function for an error occurs on the socket.\n   *\n   * @see http://developer.chrome.com/apps/sockets_tcp.html#event-onReceiveError\n   *\n   * @private\n   * @param {Object} info The incoming message\n   */\n  TcpClient.prototype._onReceiveError = function(info) {\n    if (info.socketId != this.socketId)\n      return;\n\n    error('Unable to receive data from socket: ' + info.resultCode);\n  };\n\n  /**\n   * Callback for when data has been successfully\n   * sent to the socket.\n   *\n   * @private\n   * @param {Object} sendInfo The outgoing message\n   */\n  TcpClient.prototype._onSendComplete = function(sendInfo) {\n    log('onSendComplete');\n    // Call sent callback.\n    if (this.callbacks.sent) {\n      this.callbacks.sent(sendInfo);\n    }\n  };\n\n  /**\n   * Converts an array buffer to a string\n   *\n   * @private\n   * @param {ArrayBuffer} buf The buffer to convert\n   * @param {Function} callback The function to call when conversion is complete\n   */\n  TcpClient.prototype._arrayBufferToString = function(buf, callback) {\n    var reader = new FileReader();\n    reader.onload = function(e) {\n      callback(e.target.result);\n    };\n    var blob=new Blob([ buf ], { type: 'application/octet-stream' });\n    reader.readAsText(blob);\n  };\n\n  /**\n   * Converts a string to an array buffer\n   *\n   * @private\n   * @param {String} str The string to convert\n   * @param {Function} callback The function to call when conversion is complete\n   */\n  TcpClient.prototype._stringToArrayBuffer = function(str, callback) {\n    var bb = new Blob([str]);\n    var f = new FileReader();\n    f.onload = function(e) {\n       callback(e.target.result);\n    };\n    f.readAsArrayBuffer(bb);\n  };\n\n\n  /**\n   * Wrapper function for logging\n   */\n  function log(msg) {\n    console.log(msg);\n  }\n\n  /**\n   * Wrapper function for error logging\n   */\n  function error(msg) {\n    console.error(msg);\n  }\n\n  exports.TcpClient = TcpClient;\n\n})(window);\n"
  },
  {
    "path": "_archive/apps/samples/telnet/terminal.css",
    "content": "@font-face {\n  font-family: 'Inconsolata';\n  font-style: normal;\n  font-weight: normal;\n  src: local('Inconsolata'), url('Inconsolata.woff') format('woff');\n}\n\n/*@-webkit-keyframes pulse {\n 0% {\n  opacity: 0;\n }\n 25% {\n  opacity: 0.2;\n }\n 50% {\n  opacity: 0;\n }\n 75% {\n  opacity: 0;\n }\n 100% {\n   opacity: 0.2;\n }\n}\n*/\n/*\n@-webkit-keyframes flicker {\n  0% { opacity: 0.95; }\n  10% { opacity: 0.9; }\n  20% { opacity: 0.85; }\n  30% { opacity: 0.9; }\n  40% { opacity: 0.95; }\n  50% { opacity: 0.9; }\n  60% { opacity: 0.95; }\n  70% { opacity: 0.92; }\n  80% { opacity: 0.85; }\n  90% { opacity: 0.92; }\n  100% { opacity: 0.9; }\n}\n*/\n@-webkit-keyframes flicker {\n  0% { opacity: 0.75; }\n  10% { opacity: 0.7; }\n  20% { opacity: 0.65; }\n  30% { opacity: 0.7; }\n  40% { opacity: 0.75; }\n  50% { opacity: 0.65; }\n  60% { opacity: 0.75; }\n  70% { opacity: 0.72; }\n  80% { opacity: 0.65; }\n  90% { opacity: 0.72; }\n  100% { opacity: 0.7; }\n}\n\n::selection {\n  background: #0080FF;\n  text-shadow: none !important;\n}\nhtml, body {\n  margin: 0;\n  height: 100%;\n}\nbody {\n  font-family: Inconsolata, monospace;\n  color: white;\n  background: #222;\n}\n.offscreen {\n  background: -webkit-linear-gradient(top, #000, #333);\n}\n.offscreen #container {\n  background: rgba(0,0,0,0.7);\n  height: 100%;\n  position: fixed;\n  text-shadow: none;\n  box-shadow: 0 0 15px black;\n}\n.offscreen #container output {\n  overflow-x: hidden;\n  display: inline-block;\n  height: 100px;\n}\n.offscreen .interlace {\n  display: none;\n}\n#container {\n  -webkit-transition: -webkit-transform 1.5s ease-in-out;\n  width: 100%;\n  -webkit-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\n.dropping {\n  /*background: -webkit-linear-gradient(\n    bottom,\n    rgb(209,144,23) 13%,\n    rgb(251,173,51) 57%,\n    rgb(255,208,77) 79%\n  );*/\n  background: #333;\n}\n/*\n.crt {\n  z-index: 50;\n  width: 100%;\n  height: 50px;\n  position: fixed;\n  /*margin: 15px 31px 0px 32px;\n  border-bottom-left-radius: 10px;\n  border-bottom-right-radius: 10px;\n  background: -webkit-gradient(radial, 50% 10057%, 4999, 50% 10055%, 5000, from(transparent), to(black) ) transparent no-repeat 10% 100%;\n}\n.crt.top {\n  top: -20px;\n}\n.crt.bottom {\n  -webkit-transform: rotate(180deg);\n  bottom: -20px;\n}*/\n.crt {\n  z-index: 50;\n  width: 100%;\n  height: 50px;\n  position: fixed;\n  background: black;\n}\n.crt.top {\n  top: 0;\n}\n.crt.bottom {\n  bottom: 0;\n  -webkit-transform: rotate(180deg);\n}\n.hz {\n  -webkit-animation-name: hz;\n  -webkit-animation-duration: 30s;\n  -webkit-animation-iteration-count: infinite;\n}\n\n.flicker {\n  -webkit-animation-name: flicker;\n  -webkit-animation-duration: 1s;\n  -webkit-animation-iteration-count: infinite;\n  -webkit-animation-timing-function: ease-in-out;\n}\n.interlace {\n  position: absolute;\n  left: 0;\n  top: 0;\n  background: url(interlace.png) top left repeat, rgba(255,255,255,0.5);\n  width: 100%;\n  height: 100%;\n  opacity: 0.2;\n  z-index: 10;\n  pointer-events: none;\n  /*border-top-left-radius: 150px 50px;\n  border-top-right-radius: 150px 50px;\n  border-bottom-left-radius: 150px 50px;\n  border-bottom-right-radius: 150px 50px;*/\n}\n.hidden {\n  display: none !important;\n}\n.dim > * {\n  opacity: 0.4;\n}\n.dim .help {\n  opacity: 1;\n}\niframe#fsn {\n  position: absolute;\n  height: 100%;\n  width: 100%;\n  border: none;\n}\n#container {\n  padding: 1em 1.5em 1em 1em;\n  text-shadow: 0 0 2px #C8C8C8;\n  /*overflow: hidden;\n  white-space: nowrap;*/\n\n  /*box-shadow: 10px 5px 20px rgba(255,255,255,0.2) inset,\n              -10px -5px 20px rgba(255,255,255,0.2) inset;\n  border-radius: 50px;\n  background: rgba(255, 255, 255, 0.1);*/\n}\n#container output {\n  clear: both;\n  width: 100%;\n}\n#container output h3 {\n  margin: 0;\n}\n#container output pre {\n  margin: 0;\n}\n#container output textarea {\n  width: 100%;\n  height: 200px;\n  background-color: rgba(255,255,255,0.1);\n  border: none;\n  color: inherit;\n  font: inherit;\n  outline: 0;\n  border-radius: 10px;\n  padding: 5px;\n}\n#container output textarea::selection {\n  background: red;\n}\n#container output textarea::-webkit-scrollbar {\n  width: 1ex;\n}\n#container output textarea::-webkit-scrollbar-thumb {\n  border-top: 1px solid #fff;\n  background: #ccc -webkit-linear-gradient(rgb(240, 240, 240), rgb(210, 210, 210));\n  border-radius: 1ex;\n  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);\n}\n.input-line {\n  display: -webkit-box;\n  -webkit-box-orient: horizontal;\n  -webkit-box-align: stretch;\n  display: box;\n  box-orient: horizontal;\n  box-align: stretch;\n  clear: both;\n}\n.input-line > div:nth-child(2) {\n  -webkit-box-flex: 1;\n  box-flex: 1;\n}\n.prompt {\n  white-space: nowrap;\n  color: #ffcc00; /*green;*/\n  margin-right: 7px;\n  display: -webkit-box;\n  -webkit-box-pack: center;\n  -webkit-box-orient: vertical;\n  display: box;\n  box-pack: center;\n  box-orient: vertical;\n  -webkit-user-select: none;\n  user-select: none;\n}\n.cmdline {\n  outline: none;\n  background-color: transparent;\n  margin: 0;\n  width: 100%;\n  font: inherit;\n  border: none;\n  color: inherit;\n}\n.folder {\n  color: #ffcc00;\n}\n.ls-files {\n  /*height: 45px;*/\n  /* Default, but changed by js depending on length of filename */\n  -webkit-column-width: 100px;\n  column-width: 100px;\n}\n.ls-files span {\n  cursor: pointer;\n}\n.ls-files span:hover {\n  text-decoration: underline;\n}\nbutton {\n  background: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#F9F9F9), to(#E3E3E3));\n  border: 1px solid #ccc;\n  border-radius: 3px;\n  color: black;\n  padding: 5px 8px;\n  outline: none;\n  white-space: nowrap;\n  vertical-align: middle;\n  -webkit-user-select:none;\n  user-select: none;\n  cursor: pointer;\n}\nbutton:not([disabled]):hover {\n  border-color: #ffcc00;\n}\nbutton:not([disabled]):active {\n  background: -webkit-gradient(linear, 0% 40%, 0% 70%, from(#E3E3E3), to(#F9F9F9));\n}\nbutton[disabled] {\n  color: #ccc;\n}\n.help {\n  font-family: 'Droid Sans', Arial, sans-serif;\n  -webkit-font-smoothing: antialiased;\n  position: fixed;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  z-index: 100;\n  display: -webkit-box;\n  -webkit-box-align: center;\n  -webkit-box-pack: center;\n  -webkit-box-orient: vertical;\n  -webkit-user-select: none;\n  user-select: none;\n  font-size: 10pt;\n}\n.help,\n.help > section {\n  border-radius: 10px;\n}\n.help > section {\n  padding: 10px;\n  background: rgba(255, 255, 255, 0.3);\n  -webkit-box-shadow: 3px 3px 5px rgba(0,0,0,0.6);\n  border-radius: 10px;\n  color: white;\n  position: relative;\n  width: 610px;\n}\n.help section > div:first-child {\n  border-top-left-radius: 10px;\n  border-top-right-radius: 10px;\n}\n.help section > div:last-child {\n  padding-top: 0;\n  border-bottom-left-radius: 10px;\n  border-bottom-right-radius: 10px;\n}\n.help > section > div {\n  background: rgba(0, 0, 0, 1);\n  padding: 20px;\n}\n.help h2 {\n  padding-bottom: 8px;\n  margin-top: 0;\n  margin-bottom: 25px;\n  border-bottom: 1px solid #fff;\n  color: #ffcc00;\n}\n.help p strong {\n  width: 60px;\n  display: inline-block;\n}\n.help #close {\n  border-radius: 20px;\n  padding: 2px 6px 2px 7px;\n  border: 2px solid #fff;\n  position: absolute;\n  right: 20px;\n  top: 20px;\n  cursor: pointer;\n  font-size: 90%;\n  font-weight: bold;\n  line-height: 17px;\n}\n.help #close:active {\n  right: 19px;\n  top: 21px;\n}\n.help .shortcuts {\n  -webkit-columns: 2;\n  columns: 2;\n}\n\n\n/* Themes */\n.cream {\n  color: black;\n  background: #fffff3;\n}\n.cream .interlace {\n  opacity: 0.1;\n}\n.cream .prompt {\n  color: purple;\n}\n.cream .cmdline {\n  color: black;\n}\n\n#port { width: 50px; }\n"
  },
  {
    "path": "_archive/apps/samples/telnet/terminal.html",
    "content": "<!DOCTYPE html>\n<!--\nCopyright 2011 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Eric Bidelman (ericbidelman@chromium.org)\n        Boris Smus (smus@chromium.org)\n-->\n<html>\n<head>\n<meta charset=\"utf-8\" />\n<meta http-equiv=\"X-UA-Compatible\" content=\"chrome=1\">\n<title>HTML5 Terminal</title>\n<link rel=\"stylesheet\" media=\"all\" href=\"terminal.css\">\n<link rel=\"chrome-application-definition\" href=\"manifest.json\">\n</head>\n<body>\n\n<aside class=\"help hidden\">\n  <section>\n  <div>\n    <h2>Connect</h2>\n    <label for=\"host\">Hostname:</label>\n    <input type=\"text\" id=\"host\" placeholder=\"aardmud.org\">\n    <label for=\"port\">Port:</label>\n    <input type=\"number\" id=\"port\" placeholder=\"4000\">\n    <button id=\"connect\">Connect</button>\n  </div>\n  <div>\n    <h2>What is this?</h2>\n    <p>An apps V2 telnet client.</p>\n  </div>\n  </section>\n</aside>\n\n<!--<div class=\"crt top\"></div>-->\n<div class=\"interlace\"></div>\n<div id=\"container\"></div>\n<!--<div class=\"crt bottom\"></div>-->\n\n<script src=\"tcp-client.js\"></script>\n<script src=\"ansi-converter.js\"></script>\n<script src=\"terminal.js\"></script>\n<script src=\"main.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/telnet/terminal.js",
    "content": "/*\nCopyright 2012 Google Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nAuthor: Eric Bidelman (ericbidelman@chromium.org)\n        Boris Smus (smus@chromium.org)\n*/\n\nvar util = util || {};\nutil.toArray = function(list) {\n  return Array.prototype.slice.call(list || [], 0);\n};\n\n// Cross-browser impl to get document's height.\nutil.getDocHeight = function() {\n  var d = document;\n  return Math.max(\n      Math.max(d.body.scrollHeight, d.documentElement.scrollHeight),\n      Math.max(d.body.offsetHeight, d.documentElement.offsetHeight),\n      Math.max(d.body.clientHeight, d.documentElement.clientHeight)\n  );\n};\n\n\n/**\n * Creates a audio context to play sounds\n */\nfunction Sound(opt_loop) {\n\n  var self_ = this;\n  var context_ = null;\n  var source_ = null;\n  var loop_ = opt_loop || false;\n\n  // Get the context\n  window.AudioContext = window.AudioContext || window.webkitAudioContext;\n  if (window.AudioContext) {\n    context_ = new window.AudioContext();\n  }\n\n  /**\n   * Loads in a sound file using XHR.\n   *\n   * @param {String} url The URL to load\n   * @param {Boolean} mixToMono If the sound should be mixed down to mono\n   * @param {Function} opt_callback A function to call when the file has loaded\n   */\n  this.load = function(url, mixToMono, opt_callback) {\n    if (context_) {\n      var xhr = new XMLHttpRequest();\n      xhr.open('GET', url, true);\n      xhr.responseType = 'arraybuffer';\n      xhr.onload = function() {\n        context_.decodeAudioData(this.response, function(audioBuffer) {\n          self_.sample = audioBuffer;\n          opt_callback && opt_callback();\n        }, function(e) {\n          console.log(e);\n        });\n      };\n      xhr.send();\n    }\n  };\n\n  /**\n   * Plays the sound\n   */\n  this.play = function() {\n    if (context_) {\n      source_ = context_.createBufferSource();\n      source_.buffer = self_.sample;\n      source_.looping = loop_;\n      source_.connect(context_.destination);\n      source_.noteOn(0);\n    }\n  };\n\n  /**\n   * Stops the sound\n   */\n  this.stop = function() {\n    if (source_) {\n      source_.noteOff(0);\n      source_.disconnect(0);\n    }\n  };\n}\n\n/**\n * Represents the terminal\n */\nvar Terminal = Terminal || function(containerId) {\n\n  window.URL = window.URL || window.webkitURL;\n  window.requestFileSystem = window.requestFileSystem ||\n                             window.webkitRequestFileSystem;\n\n  const VERSION_ = '1.0.0';\n  const CMDS_ = [\n    '3d', 'cat', 'cd', 'cp', 'clear', 'date', 'help', 'install', 'ls', 'mkdir',\n    'mv', 'open', 'pwd', 'rm', 'rmdir', 'theme', 'version', 'who', 'wget'\n  ];\n  const THEMES_ = ['default', 'cream'];\n\n  var fs_ = null;\n  var cwd_ = null;\n  var history_ = [];\n  var histpos_ = 0;\n  var histtemp_ = 0;\n\n  var timer_ = null;\n  var magicWord_ = null;\n\n  var fsn_ = null;\n  var is3D_ = false;\n\n  // Create terminal and cache DOM nodes;\n  var container_ = document.getElementById(containerId);\n  container_.insertAdjacentHTML('beforeEnd',\n      ['<output></output>',\n       '<div id=\"input-line\" class=\"input-line\">',\n       '<div class=\"prompt\">$&gt;</div><div><input class=\"cmdline\" autofocus /></div>',\n       '</div>'].join(''));\n\n  var cmdLine_ = container_.querySelector('#input-line .cmdline');\n  var output_ = container_.querySelector('output');\n  var interlace_ = document.querySelector('.interlace');\n  var bell_ = new Sound(false);\n  bell_.load('beep.mp3', false);\n\n  // Hackery to resize the interlace background image as the container grows.\n  output_.addEventListener('DOMSubtreeModified', function(e) {\n\n    var docHeight = util.getDocHeight();\n    document.documentElement.style.height = docHeight + 'px';\n    interlace_.style.height = docHeight + 'px';\n\n    // Need this wrapped in a setTimeout. Chrome is jupming to top :(\n    setTimeout(function() {\n      cmdLine_.scrollIntoView();\n    }, 0);\n\n  }, false);\n\n  output_.addEventListener('click', function(e) {\n    var el = e.target;\n    if (el.classList.contains('file') || el.classList.contains('folder')) {\n      cmdLine_.value += ' ' + el.textContent;\n    }\n  }, false);\n\n  window.addEventListener('click', function(e) {\n    if (e.target.nodeName.toLowerCase() != 'input') {\n      cmdLine_.focus();\n    }\n  }, false);\n\n  // Always force text cursor to end of input line.\n  cmdLine_.addEventListener('click', inputTextClick_, false);\n\n  // Handle up/down key presses for shell history and enter for new command.\n  cmdLine_.addEventListener('keydown', keyboardShortcutHandler_, false);\n  cmdLine_.addEventListener('keyup', historyHandler_, false); // keyup needed for input blinker to appear at end of input.\n  cmdLine_.addEventListener('keydown', processNewCommand_, false);\n\n  /**\n   * Click handler for the text cursor\n   *\n   * @param {Event} e The click event\n   */\n  function inputTextClick_(e) {\n    this.value = this.value;\n  }\n\n  /**\n   * Handler for keyboard shortcuts\n   *\n   * @param {Event} e The click event\n   */\n  function keyboardShortcutHandler_(e) {\n    // Toggle CRT screen flicker.\n    if ((e.ctrlKey || e.metaKey) && e.keyCode == 83) { // crtl+s\n      container_.classList.toggle('flicker');\n      output('<div>Screen flicker: ' +\n             (container_.classList.contains('flicker') ? 'on' : 'off') +\n             '</div>');\n      e.preventDefault();\n      e.stopPropagation();\n    }\n  }\n\n  /**\n   * Callback for keyboard events that scolls through the\n   * history of commands put into the terminal\n   *\n   * @param {Event} e The keyboard event\n   */\n  function historyHandler_(e) { // Tab needs to be keydown.\n\n    if (history_.length) {\n      if (e.keyCode == 38 || e.keyCode == 40) {\n        if (history_[histpos_]) {\n          history_[histpos_] = this.value;\n        } else {\n          histtemp_ = this.value;\n        }\n      }\n\n      if (e.keyCode == 38) { // up\n        histpos_--;\n        if (histpos_ < 0) {\n          histpos_ = 0;\n        }\n      } else if (e.keyCode == 40) { // down\n        histpos_++;\n        if (histpos_ > history_.length) {\n          histpos_ = history_.length;\n        }\n      }\n\n      if (e.keyCode == 38 || e.keyCode == 40) {\n        this.value = history_[histpos_] ? history_[histpos_] : histtemp_;\n        this.value = this.value; // Sets cursor to end of input.\n      }\n    }\n  }\n\n  /**\n   * Takes the current command and processes it. Stores it\n   * in the history and sends it over TCP to the remote side\n   *\n   * @param {Event} e The keyboard event (likely enter / return)\n   */\n  function processNewCommand_(e) {\n    // Beep on backspace and no value on command line.\n    if (!this.value && e.keyCode == 8) {\n      bell_.stop();\n      bell_.play();\n      return;\n    }\n\n    if (e.keyCode == 9) { // Tab\n      e.preventDefault();\n      // TODO(ericbidelman): Implement tab suggest.\n    } else if (e.keyCode == 13) { // enter\n\n      // Save shell history.\n      if (this.value) {\n        history_[history_.length] = this.value;\n        histpos_ = history_.length;\n      }\n\n      // Duplicate current input and append to output section.\n      var line = this.parentNode.parentNode.cloneNode(true);\n      line.removeAttribute('id');\n      line.classList.add('line');\n      var input = line.querySelector('input.cmdline');\n      input.autofocus = false;\n      input.readOnly = true;\n      output_.appendChild(line);\n\n      // Send the command!\n      if (window.tcpClient) {\n        tcpClient.sendMessage(this.value);\n      }\n\n      this.value = ''; // Clear/setup line for next input.\n    }\n  }\n\n  /**\n   * Updates the styles depending on the number of files\n   * that need to be displayed in the terminal.\n   *\n   * @param {Array} entries The file listing\n   */\n  function formatColumns_(entries) {\n    var maxName = entries[0].name;\n    util.toArray(entries).forEach(function(entry, i) {\n      if (entry.name.length > maxName.length) {\n        maxName = entry.name;\n      }\n    });\n\n    // If we have 3 or less entries, shorten the output container's height.\n    // 15px height with a monospace font-size of ~12px;\n    var height = entries.length == 1 ? 'height: ' + (entries.length * 30) + 'px;' :\n                 entries.length <= 3 ? 'height: ' + (entries.length * 18) + 'px;' : '';\n\n    // ~12px monospace font yields ~8px screen width.\n    var colWidth = maxName.length * 16;//;8;\n\n    return ['<div class=\"ls-files\" style=\"-webkit-column-width:',\n            colWidth, 'px;', height, '\">'];\n  }\n\n  /**\n   * Helper function to output an error code in a helpful message\n   *\n   * @param {Error} e The generated error\n   * @param {String} cmd The attempted command\n   * @param {String} dest The attempted command target\n   */\n  function invalidOpForEntryType_(e, cmd, dest) {\n    if (e.code == FileError.NOT_FOUND_ERR) {\n      output(cmd + ': ' + dest + ': No such file or directory<br>');\n    } else if (e.code == FileError.INVALID_STATE_ERR) {\n      output(cmd + ': ' + dest + ': Not a directory<br>');\n    } else if (e.code == FileError.INVALID_MODIFICATION_ERR) {\n      output(cmd + ': ' + dest + ': File already exists<br>');\n    } else {\n      errorHandler_(e);\n    }\n  }\n\n  /**\n   * Handler to convert errors to messages\n   *\n   * @param {Error} e The generated error\n   */\n  function errorHandler_(e) {\n    var msg = '';\n    switch (e.code) {\n      case FileError.QUOTA_EXCEEDED_ERR:\n        msg = 'QUOTA_EXCEEDED_ERR';\n        break;\n      case FileError.NOT_FOUND_ERR:\n        msg = 'NOT_FOUND_ERR';\n        break;\n      case FileError.SECURITY_ERR:\n        msg = 'SECURITY_ERR';\n        break;\n      case FileError.INVALID_MODIFICATION_ERR:\n        msg = 'INVALID_MODIFICATION_ERR';\n        break;\n      case FileError.INVALID_STATE_ERR:\n        msg = 'INVALID_STATE_ERR';\n        break;\n      default:\n        msg = 'Unknown Error';\n        break;\n    }\n    output('<div>Error: ' + msg + '</div>');\n  }\n\n  /**\n   * Creates a directory\n   *\n   * @param {DirectoryEntry} rooDirEntry The start point\n   * @param {Array} folders The subfolders to add\n   * @param {Function} opt_errorCallback Callback for errors\n   */\n  function createDir_(rootDirEntry, folders, opt_errorCallback) {\n    var errorCallback = opt_errorCallback || errorHandler_;\n\n    rootDirEntry.getDirectory(folders[0], {create: true}, function(dirEntry) {\n\n      // Recursively add the new subfolder if we still have a subfolder to create.\n      if (folders.length) {\n        createDir_(dirEntry, folders.slice(1));\n      }\n    }, errorCallback);\n  }\n\n  /**\n   * Gets a reference to a file\n   *\n   * @param {String} cmd The attempted command\n   * @param {String} path The file path\n   * @param {Function} successCallback Callback to pass the file reference\n   */\n  function open_(cmd, path, successCallback) {\n    if (!fs_) {\n      return;\n    }\n\n    cwd_.getFile(path, {}, successCallback, function(e) {\n      if (e.code == FileError.NOT_FOUND_ERR) {\n        output(cmd + ': ' + path + ': No such file or directory<br>');\n      }\n    });\n  }\n\n  /**\n   * Reads a file\n   *\n   * @param {String} cmd The attempted command\n   * @param {String} path The file path\n   * @param {Function} successCallback Callback to pass the file reference\n   */\n  function read_(cmd, path, successCallback) {\n    if (!fs_) {\n      return;\n    }\n\n    cwd_.getFile(path, {}, function(fileEntry) {\n      fileEntry.file(function(file) {\n        var reader = new FileReader();\n\n        reader.onloadend = function(e) {\n          successCallback(this.result);\n        };\n\n        reader.readAsText(file);\n      }, errorHandler_);\n    }, function(e) {\n      if (e.code == FileError.INVALID_STATE_ERR) {\n        output(cmd + ': ' + path + ': is a directory<br>');\n      } else if (e.code == FileError.NOT_FOUND_ERR) {\n        output(cmd + ': ' + path + ': No such file or directory<br>');\n      }\n    });\n  }\n\n  /**\n   * Read contents of current working directory. According to spec, need to\n   * keep calling readEntries() until length of result array is 0. We're\n   * guaranteed the same entry won't be returned again.\n   *\n   * @param {Function} successCallback Function to call when listing is done\n   */\n  function ls_(successCallback) {\n    if (!fs_) {\n      return;\n    }\n\n    var entries = [];\n    var reader = cwd_.createReader();\n\n    var readEntries = function() {\n      reader.readEntries(function(results) {\n        if (!results.length) {\n          entries = entries.sort();\n          successCallback(entries);\n        } else {\n          entries = entries.concat(util.toArray(results));\n          readEntries();\n        }\n      }, errorHandler_);\n    };\n\n    readEntries();\n  }\n\n  /**\n   * Clears the terminal\n   *\n   * @param {HTMLInputElement} input The input element to clear\n   */\n  function clear_(input) {\n    output_.innerHTML = '';\n    input.value = '';\n    document.documentElement.style.height = '100%';\n    interlace_.style.height = '100%';\n  }\n\n  /**\n   * Sets the terminal's theme by adding a class\n   * onto the document's body.\n   *\n   * @param {String} theme The name of the theme\n   */\n  function setTheme_(theme) {\n    var currentUrl = document.location.pathname;\n\n    if (!theme || theme == 'default') {\n      localStorage.removeItem('theme');\n      document.body.className = '';\n      return;\n    }\n\n    if (theme) {\n      document.body.classList.add(theme);\n      localStorage.theme = theme;\n    }\n  }\n\n  /**\n   * Toggles the terminal's CSS3D view\n   */\n  function toggle3DView_() {\n    var body = document.body;\n    body.classList.toggle('offscreen');\n\n    is3D_ = !is3D_;\n\n    if (body.classList.contains('offscreen')) {\n\n      container_.style.webkitTransform =\n          'translateY(' + (util.getDocHeight() - 175) + 'px)';\n\n      var transEnd_ = function(e) {\n        var iframe = document.createElement('iframe');\n        iframe.id = 'fsn';\n        iframe.src = '../fsn/fsn_proto.html';\n\n        fsn_ = body.insertBefore(iframe, body.firstElementChild);\n\n        iframe.contentWindow.onload = function() {\n          worker_.postMessage({cmd: 'read', type: type_, size: size_});\n        };\n        container_.removeEventListener('webkitTransitionEnd', transEnd_, false);\n      };\n      container_.addEventListener('webkitTransitionEnd', transEnd_, false);\n    } else {\n      container_.style.webkitTransform = 'translateY(0)';\n      body.removeChild(fsn_);\n      fsn_ = null;\n    }\n  }\n\n  /**\n   * Writes to the terminal\n   *\n   * @param {String} html The HTML to add to the output\n   */\n  function output(html) {\n    output_.insertAdjacentHTML('beforeEnd', html);\n    cmdLine_.scrollIntoView();\n  }\n\n  return {\n    initFS: function(persistent, size) {\n      if (!!!window.requestFileSystem) {\n        output('<div>Sorry! The FileSystem APIs are not available in your browser.</div>');\n        return;\n      }\n\n      var type = persistent ? window.PERSISTENT : window.TEMPORARY;\n      type = type || 0;\n\n      window.requestFileSystem(type, size, function(filesystem) {\n        fs_ = filesystem;\n        cwd_ = fs_.root;\n        type_ = type;\n        size_ = size;\n\n        // If we get this far, attempt to create a folder to test if the\n        // --unlimited-quota-for-files fag is set.\n        cwd_.getDirectory('testquotaforfsfolder', {create: true}, function(dirEntry) {\n          dirEntry.remove(function() { // If successfully created, just delete it.\n            // noop.\n          });\n        }, function(e) {\n          if (e.code == FileError.QUOTA_EXCEEDED_ERR) {\n            output('ERROR: Write access to the FileSystem is unavailable.<br>');\n            output('Type \"install\" or run Chrome with the --unlimited-quota-for-files flag.');\n          } else {\n            errorHandler_(e);\n          }\n        });\n\n      }, errorHandler_);\n    },\n    output: output,\n    setTheme: setTheme_,\n    getCmdLine: function() { return cmdLine_; },\n    addDroppedFiles: function(files) {\n      util.toArray(files).forEach(function(file, i) {\n        cwd_.getFile(file.name, {create: true, exclusive: true}, function(fileEntry) {\n\n          // Tell FSN visualizer we've added a file.\n          if (fsn_) {\n            fsn_.contentWindow.postMessage({cmd: 'touch', data: file.name}, location.origin);\n          }\n\n          fileEntry.createWriter(function(fileWriter) {\n            fileWriter.write(file);\n          }, errorHandler_);\n        }, errorHandler_);\n      });\n    },\n    toggle3DView: toggle3DView_\n  };\n};\n\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/jkgbibkjioaefdopcdbhjehefhajgadh\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Code editor\n\nA non-trivial sample with basic features of a code editor, like language detection and syntax highlight. If also uses the extended FileSystem API that allows a user to select files from the disk so the app can read and write to that file. This sample is very similar to the [mini-code-editor](https://github.com/GoogleChrome/chrome-app-samples/tree/master/mini-code-edit)\n\n## APIs\n\n* [chrome.fileSystem](http://developer.chrome.com/apps/fileSystem)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/text-editor/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function (launchData) {\n  chrome.app.window.create('editor.html', function(win) {\n    win.contentWindow.launchData = launchData;\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/editor.html",
    "content": "<html>\n<head>\n  <title>Platform App Text Editor Demo</title>\n  <meta name=\"author\" content=\"Ben Wells\">\n  <link rel=\"stylesheet\" href=\"styles.css\" type=\"text/css\">\n</head>\n<body>\n  <div id=\"toolbar\">\n    <div id=\"new\" class=\"toolbarbutton enabled\"></div>\n    <div id=\"openfile\" class=\"toolbarbutton enabled\"></div>\n    <div id=\"openweb\" class=\"toolbarbutton hidden\"></div>\n    <div id=\"save\" class=\"toolbarbutton enabled\"></div>\n    <div id=\"saveas\" class=\"toolbarbutton enabled\"></div>\n  </div>\n  <div id=\"editarea\">\n    <div id=\"status\">\n      <div id=\"path\">[new file]</div>\n      <div id=\"error\"></div>\n    </div>\n    <div id=\"editor\"></div>\n  </div>\n  <script src=\"require_config.js\" type=\"text/javascript\"></script>\n  <script src=\"require.js\" data-main=\"editor\" type=\"text/javascript\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/editor.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\n// Load dependent modules\nvar EditSession = require(\"ace/edit_session\").EditSession;\nvar UndoManager = require(\"ace/undomanager\").UndoManager;\nvar Editor = require(\"ace/editor\").Editor;\nvar Renderer = require(\"ace/virtual_renderer\").VirtualRenderer;\nvar modes = require(\"modes\");\nvar event = require(\"ace/lib/event\");\n\n// Load theme info\nvar theme = require(\"ace/theme/textmate\");\n\n// Setup edited document and put it in the container\nvar container = document.getElementById(\"editor\");\nvar editor = new Editor(new Renderer(container, theme));\nvar session = new EditSession('');\nsession.setUndoManager(new UndoManager());\neditor.setSession(session);\n\n// Make sure editor is kept to an appropriate size\nfunction onResize() {\n  var left = container.offsetLeft;\n  var top = container.offsetTop;\n  var width = document.documentElement.clientWidth - left;\n  var height = document.documentElement.clientHeight - top;\n  container.style.width = width + 'px';\n  container.style.height = height + 'px';\n  editor.resize();\n}\nwindow.onresize = onResize;\n// Do resize once to get everything in a happy place.\nonResize();\n\nvar fileEntry;\nvar gotWritable = false;\nvar modeDescription = '';\n\nfunction updatePathTo(aPath) {\n  var pathDisplay = aPath;\n  if (modeDescription) {\n    pathDisplay = pathDisplay + ' [' + modeDescription + ']';\n  }\n  document.getElementById('path').innerHTML = pathDisplay;\n}\n\nfunction updatePath() {\n  if (fileEntry) {\n    chrome.fileSystem.getDisplayPath(fileEntry, updatePathTo);\n  } else {\n    updatePathTo('[new file]');\n  }\n}\n\nfunction updateModeForBaseName(aBaseName) {\n  modeDescription = '';\n  var mode = modes.getModeFromBaseName(aBaseName);\n  if (mode) {\n    editor.getSession().setMode(mode.mode);\n    modeDescription = mode.desc;\n  }\n}\n\nfunction showError(anError) {\n  var errorEl = document.getElementById('error');\n  errorEl.innerHTML = anError;\n  document.getElementById('error').style.display = 'default';\n}\n\nfunction clearError() {\n  document.getElementById('error').style.display = 'none';\n}\n\nfunction replaceDocContentsFromString(string) {\n  editor.getSession().setValue(string);\n}\n\nfunction replaceDocContentsFromFile(file) {\n  if (window.FileReader) {\n    var reader = new FileReader();\n    reader.onload = function() {\n      replaceDocContentsFromString(reader.result);\n    };\n    reader.readAsText(file);\n  }\n}\n\nfunction replaceDocContentsFromFileEntry() {\n  fileEntry.file(replaceDocContentsFromFile);\n}\n\nfunction saveToEntry() {\n  fileEntry.createWriter(function(fileWriter) {\n    fileWriter.onwriteend = function(e) {\n      if (this.error)\n        gStatusEl.innerHTML = 'Error during write: ' + this.error.toString();\n      else\n        clearError();\n    };\n\n    var blob = new Blob([editor.getSession().getValue()], {type: 'text/plain'});\n    fileWriter.write(blob);\n  });\n}\n\nfunction setEntry(anEntry, isWritable, name) {\n  fileEntry = anEntry;\n  gotWritable = isWritable;\n  if (fileEntry) {\n    updateModeForBaseName(fileEntry.name);\n  } else if (name) {\n    updateModeForBaseName(name);\n  }\n  updatePath();\n}\n\n// Create a new document. This just wipes the old document.\nfunction createNew() {\n  replaceDocContentsFromString();\n  setEntry(null, false);\n}\n\nfunction openFile() {\n  chrome.fileSystem.chooseEntry(function (entry) {\n    if (chrome.runtime.lastError) {\n      showError(chrome.runtime.lastError.message);\n      return;\n    }\n    clearError();\n    setEntry(entry, false);\n    replaceDocContentsFromFileEntry();\n  });\n}\n\nfunction saveFile() {\n  if (gotWritable) {\n    saveToEntry();\n  } else if (fileEntry) {\n    chrome.fileSystem.getWritableEntry(fileEntry, function(entry) {\n      if (chrome.runtime.lastError) {\n        showError(chrome.runtime.lastError.message);\n        return;\n      }\n      clearError();\n      setEntry(entry, true);\n      saveToEntry();\n    });\n  } else {\n    saveAs();\n  }\n}\n\nfunction saveAs() {\n  chrome.fileSystem.chooseEntry({type: 'saveFile'}, function(entry) {\n    if (chrome.runtime.lastError) {\n      showError(chrome.runtime.lastError.message);\n      return;\n    }\n    clearError();\n    setEntry(entry, true);\n    saveToEntry();\n  });\n}\n\n// Setup commands\n// New probably should warn the user as there is no undo!\ndocument.getElementById('new').onclick = createNew;\ndocument.getElementById('openfile').onclick = openFile;\ndocument.getElementById('save').onclick = saveFile;\ndocument.getElementById('saveas').onclick = saveAs;\n\neditor.commands.addCommand({\n    name: \"new\",\n    bindKey: {\n        win: \"Ctrl-N\",\n        mac: \"Command-N\",\n        sender: \"editor\"\n    },\n    exec: function() {\n        createNew();\n    }\n});\n\neditor.commands.addCommand({\n    name: \"open\",\n    bindKey: {\n        win: \"Ctrl-O\",\n        mac: \"Command-O\",\n        sender: \"editor\"\n    },\n    exec: function() {\n        openFile();\n    }\n});\n\neditor.commands.addCommand({\n    name: \"save\",\n    bindKey: {\n        win: \"Ctrl-S\",\n        mac: \"Command-S\",\n        sender: \"editor\"\n    },\n    exec: function() {\n        saveFile();\n    }\n});\n\neditor.commands.addCommand({\n    name: \"saveas\",\n    bindKey: {\n        win: \"Ctrl-Shift-S\",\n        mac: \"Command-Shift-S\",\n        sender: \"editor\"\n    },\n    exec: function() {\n        saveAs();\n    }\n});\n\neditor.commands.addCommand({\n    name: \"copy\",\n    bindKey: {\n        win: \"Ctrl-C\",\n        mac: \"Command-C\",\n        sender: \"editor\"\n    },\n    exec: function() {\n        document.execCommand(\"copy\");\n    }\n});\n\neditor.commands.addCommand({\n    name: \"paste\",\n    bindKey: {\n        win: \"Ctrl-V\",\n        mac: \"Command-V\",\n        sender: \"editor\"\n    },\n    exec: function() {\n        document.execCommand(\"paste\");\n    }\n});\n\neditor.commands.addCommand({\n    name: \"cutX\",\n    bindKey: {\n        win: \"Ctrl-X\",\n        mac: \"Command-X\",\n        sender: \"editor\"\n    },\n    exec: function() {\n        document.execCommand(\"cut\");\n    }\n});\n\n// Handle drop events.\nevent.addListener(container, \"drop\", function(e) {\n  var file = e.dataTransfer.files[0];\n  replaceDocContentsFromFile(file);\n  setEntry(null, false, file.name);\n  return event.preventDefault(e);\n});\n\n// Setup any launch data.\nif (launchData) {\n  setEntry(launchData.intent.data, false);\n  replaceDocContentsFromFileEntry();\n}\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/icons/Readme.txt",
    "content": "The icons in this project are awesome and come from http://www.silvestre.com.ar/.\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/ace.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Mozilla Skywriter.\n *\n * The Initial Developer of the Original Code is\n * Mozilla.\n * Portions created by the Initial Developer are Copyright (C) 2009\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Kevin Dangoor (kdangoor@mozilla.com)\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nrequire(\"./lib/fixoldbrowsers\");\n\nvar Dom = require(\"./lib/dom\");\nvar Event = require(\"./lib/event\");\n\nvar Editor = require(\"./editor\").Editor;\nvar EditSession = require(\"./edit_session\").EditSession;\nvar UndoManager = require(\"./undomanager\").UndoManager;\nvar Renderer = require(\"./virtual_renderer\").VirtualRenderer;\nvar MultiSelect = require(\"./multi_select\").MultiSelect;\n\n// The following require()s are for inclusion in the built ace file\nrequire(\"./worker/worker_client\");\nrequire(\"./keyboard/hash_handler\");\nrequire(\"./keyboard/state_handler\");\nrequire(\"./placeholder\");\nrequire(\"./config\").init();\n\nexports.edit = function(el) {\n    if (typeof(el) == \"string\") {\n        el = document.getElementById(el);\n    }\n\n    var doc = new EditSession(Dom.getInnerText(el));\n    doc.setUndoManager(new UndoManager());\n    el.innerHTML = '';\n\n    var editor = new Editor(new Renderer(el, require(\"./theme/textmate\")));\n    new MultiSelect(editor);\n    editor.setSession(doc);\n\n    var env = {};\n    env.document = doc;\n    env.editor = editor;\n    editor.resize();\n    Event.addListener(window, \"resize\", function() {\n        editor.resize();\n    });\n    el.env = env;\n    // Store env on editor such that it can be accessed later on from\n    // the returned object.\n    editor.env = env;\n    return editor;\n};\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/anchor.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"./lib/oop\");\nvar EventEmitter = require(\"./lib/event_emitter\").EventEmitter;\n\n/**\n * An Anchor is a floating pointer in the document. Whenever text is inserted or\n * deleted before the cursor, the position of the cursor is updated\n */\nvar Anchor = exports.Anchor = function(doc, row, column) {\n    this.document = doc;\n    \n    if (typeof column == \"undefined\")\n        this.setPosition(row.row, row.column);\n    else\n        this.setPosition(row, column);\n\n    this.$onChange = this.onChange.bind(this);\n    doc.on(\"change\", this.$onChange);\n};\n\n(function() {\n\n    oop.implement(this, EventEmitter);\n    \n    this.getPosition = function() {\n        return this.$clipPositionToDocument(this.row, this.column);\n    };\n    \n    this.getDocument = function() {\n        return this.document;\n    };\n    \n    this.onChange = function(e) {\n        var delta = e.data;\n        var range = delta.range;\n            \n        if (range.start.row == range.end.row && range.start.row != this.row)\n            return;\n            \n        if (range.start.row > this.row)\n            return;\n            \n        if (range.start.row == this.row && range.start.column > this.column)\n            return;\n    \n        var row = this.row;\n        var column = this.column;\n        \n        if (delta.action === \"insertText\") {\n            if (range.start.row === row && range.start.column <= column) {\n                if (range.start.row === range.end.row) {\n                    column += range.end.column - range.start.column;\n                }\n                else {\n                    column -= range.start.column;\n                    row += range.end.row - range.start.row;\n                }\n            }\n            else if (range.start.row !== range.end.row && range.start.row < row) {\n                row += range.end.row - range.start.row;\n            }\n        } else if (delta.action === \"insertLines\") {\n            if (range.start.row <= row) {\n                row += range.end.row - range.start.row;\n            }\n        }\n        else if (delta.action == \"removeText\") {\n            if (range.start.row == row && range.start.column < column) {\n                if (range.end.column >= column)\n                    column = range.start.column;\n                else\n                    column = Math.max(0, column - (range.end.column - range.start.column));\n                \n            } else if (range.start.row !== range.end.row && range.start.row < row) {\n                if (range.end.row == row) {\n                    column = Math.max(0, column - range.end.column) + range.start.column;\n                }\n                row -= (range.end.row - range.start.row);\n            }\n            else if (range.end.row == row) {\n                row -= range.end.row - range.start.row;\n                column = Math.max(0, column - range.end.column) + range.start.column;\n            }\n        } else if (delta.action == \"removeLines\") {\n            if (range.start.row <= row) {\n                if (range.end.row <= row)\n                    row -= range.end.row - range.start.row;\n                else {\n                    row = range.start.row;\n                    column = 0;\n                }\n            }\n        }\n\n        this.setPosition(row, column, true);\n    };\n\n    this.setPosition = function(row, column, noClip) {\n        var pos;\n        if (noClip) {\n            pos = {\n                row: row,\n                column: column\n            };\n        }\n        else {\n            pos = this.$clipPositionToDocument(row, column);\n        }\n        \n        if (this.row == pos.row && this.column == pos.column)\n            return;\n            \n        var old = {\n            row: this.row,\n            column: this.column\n        };\n        \n        this.row = pos.row;\n        this.column = pos.column;\n        this._emit(\"change\", {\n            old: old,\n            value: pos\n        });\n    };\n    \n    this.detach = function() {\n        this.document.removeEventListener(\"change\", this.$onChange);\n    };\n    \n    this.$clipPositionToDocument = function(row, column) {\n        var pos = {};\n    \n        if (row >= this.document.getLength()) {\n            pos.row = Math.max(0, this.document.getLength() - 1);\n            pos.column = this.document.getLine(pos.row).length;\n        }\n        else if (row < 0) {\n            pos.row = 0;\n            pos.column = 0;\n        }\n        else {\n            pos.row = row;\n            pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));\n        }\n        \n        if (column < 0)\n            pos.column = 0;\n            \n        return pos;\n    };\n    \n}).call(Anchor.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/anchor_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Document = require(\"./document\").Document;\nvar Anchor = require(\"./anchor\").Anchor;\nvar Range = require(\"./range\").Range;\nvar assert = require(\"./test/assertions\");\n\nmodule.exports = {\n\n    \"test create anchor\" : function() {\n        var doc = new Document(\"juhu\");\n        var anchor = new Anchor(doc, 0, 0);\n        \n        assert.position(anchor.getPosition(), 0, 0);\n        assert.equal(anchor.getDocument(), doc);\n    },\n    \n    \"test insert text in same row before cursor should move anchor column\": function() {\n        var doc = new Document(\"juhu\\nkinners\");\n        var anchor = new Anchor(doc, 1, 4);\n        \n        doc.insert({row: 1, column: 1}, \"123\");\n        assert.position(anchor.getPosition(), 1, 7);\n    },\n    \n    \"test insert lines before cursor should move anchor row\": function() {\n        var doc = new Document(\"juhu\\nkinners\");\n        var anchor = new Anchor(doc, 1, 4);\n        \n        doc.insertLines(1, [\"123\", \"456\"]);\n        assert.position(anchor.getPosition(), 3, 4);    \n    },\n    \n    \"test insert new line before cursor should move anchor column\": function() {\n        var doc = new Document(\"juhu\\nkinners\");\n        var anchor = new Anchor(doc, 1, 4);\n        \n        doc.insertNewLine({row: 0, column: 0});\n        assert.position(anchor.getPosition(), 2, 4);    \n    },\n    \n    \"test insert new line in anchor line before anchor should move anchor column and row\": function() {\n        var doc = new Document(\"juhu\\nkinners\");\n        var anchor = new Anchor(doc, 1, 4);\n        \n        doc.insertNewLine({row: 1, column: 2});\n        assert.position(anchor.getPosition(), 2, 2);\n    },\n    \n    \"test delete text in anchor line before anchor should move anchor column\": function() {\n        var doc = new Document(\"juhu\\nkinners\");\n        var anchor = new Anchor(doc, 1, 4);\n        \n        doc.remove(new Range(1, 1, 1, 3));\n        assert.position(anchor.getPosition(), 1, 2);\n    },\n    \n    \"test remove range which contains the anchor should move the anchor to the start of the range\": function() {\n        var doc = new Document(\"juhu\\nkinners\");\n        var anchor = new Anchor(doc, 0, 3);\n        \n        doc.remove(new Range(0, 1, 1, 3));\n        assert.position(anchor.getPosition(), 0, 1);\n    },\n    \n    \"test delete character before the anchor should have no effect\": function() {\n        var doc = new Document(\"juhu\\nkinners\");\n        var anchor = new Anchor(doc, 1, 4);\n        \n        doc.remove(new Range(1, 4, 1, 5));\n        assert.position(anchor.getPosition(), 1, 4);\n    },\n    \n    \"test delete lines in anchor line before anchor should move anchor row\": function() {\n        var doc = new Document(\"juhu\\n1\\n2\\nkinners\");\n        var anchor = new Anchor(doc, 3, 4);\n        \n        doc.removeLines(1, 2);\n        assert.position(anchor.getPosition(), 1, 4);\n    },\n    \n    \"test remove new line before the cursor\": function() {\n        var doc = new Document(\"juhu\\nkinners\");\n        var anchor = new Anchor(doc, 1, 4);\n        \n        doc.removeNewLine(0);\n        assert.position(anchor.getPosition(), 0, 8);\n    },\n    \n    \"test delete range which contains the anchor should move anchor to the end of the range\": function() {\n        var doc = new Document(\"juhu\\nkinners\");\n        var anchor = new Anchor(doc, 1, 4);\n        \n        doc.remove(new Range(0, 2, 1, 2));\n        assert.position(anchor.getPosition(), 0, 4);\n    },\n    \n    \"test delete line which contains the anchor should move anchor to the end of the range\": function() {\n        var doc = new Document(\"juhu\\nkinners\\n123\");\n        var anchor = new Anchor(doc, 1, 5);\n        \n        doc.removeLines(1, 1);\n        assert.position(anchor.getPosition(), 1, 0);\n    },\n    \n    \"test remove after the anchor should have no effect\": function() {\n        var doc = new Document(\"juhu\\nkinners\\n123\");\n        var anchor = new Anchor(doc, 1, 2);\n        \n        doc.remove(new Range(1, 4, 2, 2));\n        assert.position(anchor.getPosition(), 1, 2);\n    },\n    \n    \"test anchor changes triggered by document changes should emit change event\": function(next) {\n        var doc = new Document(\"juhu\\nkinners\\n123\");\n        var anchor = new Anchor(doc, 1, 5);\n        \n        anchor.on(\"change\", function(e) {\n            assert.position(anchor.getPosition(), 0, 0);\n            next();\n        });\n        \n        doc.remove(new Range(0, 0, 2, 1));\n    },\n    \n    \"test only fire change event if position changes\": function() {\n        var doc = new Document(\"juhu\\nkinners\\n123\");\n        var anchor = new Anchor(doc, 1, 5);\n        \n        anchor.on(\"change\", function(e) {\n            assert.fail();\n        });\n        \n        doc.remove(new Range(2, 0, 2, 1));\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/background_tokenizer.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"./lib/oop\");\nvar EventEmitter = require(\"./lib/event_emitter\").EventEmitter;\n\nvar BackgroundTokenizer = function(tokenizer, editor) {\n    this.running = false;    \n    this.lines = [];\n    this.currentLine = 0;\n    this.tokenizer = tokenizer;\n\n    var self = this;\n\n    this.$worker = function() {\n        if (!self.running) { return; }\n\n        var workerStart = new Date();\n        var startLine = self.currentLine;\n        var doc = self.doc;\n\n        var processedLines = 0;\n\n        var len = doc.getLength();\n        while (self.currentLine < len) {\n            self.lines[self.currentLine] = self.$tokenizeRows(self.currentLine, self.currentLine)[0];\n            self.currentLine++;\n\n            // only check every 5 lines\n            processedLines += 1;\n            if ((processedLines % 5 == 0) && (new Date() - workerStart) > 20) {\n                self.fireUpdateEvent(startLine, self.currentLine-1);\n                self.running = setTimeout(self.$worker, 20);\n                return;\n            }\n        }\n\n        self.running = false;\n\n        self.fireUpdateEvent(startLine, len - 1);\n    };\n};\n\n(function(){\n\n    oop.implement(this, EventEmitter);\n\n    this.setTokenizer = function(tokenizer) {\n        this.tokenizer = tokenizer;\n        this.lines = [];\n\n        this.start(0);\n    };\n\n    this.setDocument = function(doc) {\n        this.doc = doc;\n        this.lines = [];\n\n        this.stop();\n    };\n\n    this.fireUpdateEvent = function(firstRow, lastRow) {\n        var data = {\n            first: firstRow,\n            last: lastRow\n        };\n        this._emit(\"update\", {data: data});\n    };\n\n    this.start = function(startRow) {\n        this.currentLine = Math.min(startRow || 0, this.currentLine,\n                                    this.doc.getLength());\n\n        // remove all cached items below this line\n        this.lines.splice(this.currentLine, this.lines.length);\n\n        this.stop();\n        // pretty long delay to prevent the tokenizer from interfering with the user\n        this.running = setTimeout(this.$worker, 700);\n    };\n\n    this.stop = function() {\n        if (this.running)\n            clearTimeout(this.running);\n        this.running = false;\n    };\n\n    this.getTokens = function(firstRow, lastRow) {\n        return this.$tokenizeRows(firstRow, lastRow);\n    };\n\n    this.getState = function(row) {\n        return this.$tokenizeRows(row, row)[0].state;\n    };\n\n    this.$tokenizeRows = function(firstRow, lastRow) {\n        if (!this.doc || isNaN(firstRow) || isNaN(lastRow))\n            return [{'state':'start','tokens':[]}];\n            \n        var rows = [];\n\n        // determine start state\n        var state = \"start\";\n        var doCache = false;\n        if (firstRow > 0 && this.lines[firstRow - 1]) {\n            state = this.lines[firstRow - 1].state;\n            doCache = true;\n        } else if (firstRow == 0) {\n            state = \"start\";\n            doCache = true;\n        } else if (this.lines.length > 0) {\n            // Guess that we haven't changed state.\n            state = this.lines[this.lines.length-1].state;\n        }\n\n        var lines = this.doc.getLines(firstRow, lastRow);\n        for (var row=firstRow; row<=lastRow; row++) {\n            if (!this.lines[row]) {\n                var tokens = this.tokenizer.getLineTokens(lines[row-firstRow] || \"\", state);\n                var state = tokens.state;\n                rows.push(tokens);\n\n                if (doCache) {\n                    this.lines[row] = tokens;\n                }\n            }\n            else {\n                var tokens = this.lines[row];\n                state = tokens.state;\n                rows.push(tokens);\n            }\n        }\n        return rows;\n    };\n\n}).call(BackgroundTokenizer.prototype);\n\nexports.BackgroundTokenizer = BackgroundTokenizer;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/commands/command_manager.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar HashHandler = require(\"../keyboard/hash_handler\").HashHandler;\nvar EventEmitter = require(\"../lib/event_emitter\").EventEmitter;\n\nvar CommandManager = function(platform, commands) {\n    this.platform = platform;\n    this.commands = {};\n    this.commmandKeyBinding = {};\n\n    this.addCommands(commands);\n    \n    this.setDefaultHandler(\"exec\", function(e) {\n        e.command.exec(e.editor, e.args || {});\n    });\n};\n\noop.inherits(CommandManager, HashHandler);\n\n(function() {\n\n    oop.implement(this, EventEmitter);\n\n    this.exec = function(command, editor, args) {\n        if (typeof command === 'string')\n            command = this.commands[command];\n\n        if (!command)\n            return false;\n\n        if (editor && editor.$readOnly && !command.readOnly)\n            return false;\n\n        this._emit(\"exec\", {editor: editor, command: command, args: args});\n        return true;\n    };\n\n    this.toggleRecording = function() {\n        if (this.$inReplay)\n            return;\n        if (this.recording) {\n            this.macro.pop();\n            this.removeEventListener(\"exec\", this.$addCommandToMacro);\n\n            if (!this.macro.length)\n                this.macro = this.oldMacro;\n\n            return this.recording = false;\n        }\n        if (!this.$addCommandToMacro) {\n            this.$addCommandToMacro = function(e) {\n                    this.macro.push([e.command, e.args]);\n                }.bind(this);\n        }\n\n        this.oldMacro = this.macro;\n        this.macro = [];\n        this.on(\"exec\", this.$addCommandToMacro);\n        return this.recording = true;\n    };\n\n    this.replay = function(editor) {\n        if (this.$inReplay || !this.macro)\n            return;\n\n        if (this.recording)\n            return this.toggleRecording();\n\n        try {\n            this.$inReplay = true;\n            this.macro.forEach(function(x) {\n                if (typeof x == \"string\")\n                    this.exec(x, editor);\n                else\n                    this.exec(x[0], editor, x[1]);\n            }, this);\n        } finally {\n            this.$inReplay = false;\n        }\n    };\n\n    this.trimMacro = function(m) {\n        return m.map(function(x){\n            if (typeof x[0] != \"string\")\n                x[0] = x[0].name;\n            if (!x[1])\n                x = x[0];\n            return x;\n        });\n    };\n\n}).call(CommandManager.prototype);\n\nexports.CommandManager = CommandManager;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/commands/command_manager_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar CommandManager = require(\"./command_manager\").CommandManager;\nvar keys = require(\"../lib/keys\");\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n\n    setUp: function() {\n        this.command = {\n            name: \"gotoline\",\n            bindKey: {\n                mac: \"Command-L\",\n                win: \"Ctrl-L\"\n            },\n            called: false,\n            exec: function(editor) { this.called = true; }\n        };\n\n        this.cm = new CommandManager(\"mac\", [this.command]);\n    },\n\n    \"test: register command\": function() {\n        this.cm.exec(\"gotoline\");\n        assert.ok(this.command.called);\n    },\n\n    \"test: mac hotkeys\": function() {\n        var command = this.cm.findKeyCommand(keys.KEY_MODS.command, \"L\");\n        assert.equal(command, this.command);\n\n        var command = this.cm.findKeyCommand(keys.KEY_MODS.ctrl, \"L\");\n        assert.equal(command, undefined);\n    },\n\n    \"test: win hotkeys\": function() {\n        var cm = new CommandManager(\"win\", [this.command]);\n\n        var command = cm.findKeyCommand(keys.KEY_MODS.command, \"L\");\n        assert.equal(command, undefined);\n\n        var command = cm.findKeyCommand(keys.KEY_MODS.ctrl, \"L\");\n        assert.equal(command, this.command);\n    },\n\n    \"test: remove command by object\": function() {\n        this.cm.removeCommand(this.command);\n\n        this.cm.exec(\"gotoline\");\n        assert.ok(!this.command.called);\n\n        var command = this.cm.findKeyCommand(keys.KEY_MODS.command, \"L\");\n        assert.equal(command, null);\n    },\n\n    \"test: remove command by name\": function() {\n        this.cm.removeCommand(\"gotoline\");\n\n        this.cm.exec(\"gotoline\");\n        assert.ok(!this.command.called);\n\n        var command = this.cm.findKeyCommand(keys.KEY_MODS.command, \"L\");\n        assert.equal(command, null);\n    },\n\n    \"test: adding a new command with the same name as an existing one should remove the old one first\": function() {\n        var command = {\n            name: \"gotoline\",\n            bindKey: {\n                mac: \"Command-L\",\n                win: \"Ctrl-L\"\n            },\n            called: false,\n            exec: function(editor) { this.called = true; }\n        };\n        this.cm.addCommand(command);\n\n        this.cm.exec(\"gotoline\");\n        assert.ok(command.called);\n        assert.ok(!this.command.called);\n\n        assert.equal(this.cm.findKeyCommand(keys.KEY_MODS.command, \"L\"), command);\n    },\n\n    \"test: adding commands and recording a macro\": function() {\n        var called = \"\";\n        this.cm.addCommands({\n            togglerecording: function(editor) {\n                editor.cm.toggleRecording();\n            },\n            replay: function(editor) {\n                editor.cm.replay();\n            },\n            cm1: function(editor, arg) {\n                called += \"1\" + (arg || \"\");\n            },\n            cm2: function(editor) {\n                called += \"2\";\n            }\n        });\n\n        this.cm.exec(\"togglerecording\", this);\n        assert.ok(this.cm.recording);\n\n        this.cm.exec(\"cm1\", this, \"-\");\n        this.cm.exec(\"cm2\");\n        this.cm.exec(\"replay\", this);\n        assert.ok(!this.cm.recording);\n        assert.equal(called, \"1-2\");\n\n        called = \"\";\n        this.cm.exec(\"replay\", this);\n        assert.equal(called, \"1-2\");\n    },\n\n    \"test: bindkeys\": function() {\n        var called = \"\";\n        this.cm.addCommands({\n            cm1: function(editor, arg) {\n                called += \"1\" + (arg || \"\");\n            },\n            cm2: function(editor) {\n                called += \"2\";\n            }\n        });\n\n        this.cm.bindKeys({\n            \"Ctrl-L|Command-C\": \"cm1\",\n            \"Ctrl-R\": \"cm2\"\n        });\n\n        var command = this.cm.findKeyCommand(keys.KEY_MODS.command, \"C\");\n        assert.equal(command, \"cm1\");\n\n        var command = this.cm.findKeyCommand(keys.KEY_MODS.ctrl, \"R\");\n        assert.equal(command, \"cm2\");\n\n        this.cm.bindKeys({\n            \"Ctrl-R\": null\n        });\n\n        var command = this.cm.findKeyCommand(keys.KEY_MODS.ctrl, \"R\");\n        assert.equal(command, null);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/commands/default_commands.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Julian Viereck <julian.viereck@gmail.com>\n *      Mihai Sucan <mihai.sucan@gmail.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar lang = require(\"../lib/lang\");\n\nfunction bindKey(win, mac) {\n    return {\n        win: win,\n        mac: mac\n    };\n}\n\nexports.commands = [{\n    name: \"selectall\",\n    bindKey: bindKey(\"Ctrl-A\", \"Command-A\"),\n    exec: function(editor) { editor.selectAll(); },\n    readOnly: true\n}, {\n    name: \"centerselection\",\n    bindKey: bindKey(null, \"Ctrl-L\"),\n    exec: function(editor) { editor.centerSelection(); },\n    readOnly: true\n}, {\n    name: \"gotoline\",\n    bindKey: bindKey(\"Ctrl-L\", \"Command-L\"),\n    exec: function(editor) {\n        var line = parseInt(prompt(\"Enter line number:\"), 10);\n        if (!isNaN(line)) {\n            editor.gotoLine(line);\n        }\n    },\n    readOnly: true\n}, {\n    name: \"fold\",\n    bindKey: bindKey(\"Alt-L\", \"Alt-L\"),\n    exec: function(editor) { editor.session.toggleFold(false); },\n    readOnly: true\n}, {\n    name: \"unfold\",\n    bindKey: bindKey(\"Alt-Shift-L\", \"Alt-Shift-L\"),\n    exec: function(editor) { editor.session.toggleFold(true); },\n    readOnly: true\n}, {\n    name: \"foldall\",\n    bindKey: bindKey(\"Alt-0\", \"Alt-0\"),\n    exec: function(editor) { editor.session.foldAll(); },\n    readOnly: true\n}, {\n    name: \"unfoldall\",\n    bindKey: bindKey(\"Alt-Shift-0\", \"Alt-Shift-0\"),\n    exec: function(editor) { editor.session.unfold(); },\n    readOnly: true\n}, {\n    name: \"findnext\",\n    bindKey: bindKey(\"Ctrl-K\", \"Command-G\"),\n    exec: function(editor) { editor.findNext(); },\n    readOnly: true\n}, {\n    name: \"findprevious\",\n    bindKey: bindKey(\"Ctrl-Shift-K\", \"Command-Shift-G\"),\n    exec: function(editor) { editor.findPrevious(); },\n    readOnly: true\n}, {\n    name: \"find\",\n    bindKey: bindKey(\"Ctrl-F\", \"Command-F\"),\n    exec: function(editor) {\n        var needle = prompt(\"Find:\", editor.getCopyText());\n        editor.find(needle);\n    },\n    readOnly: true\n}, {\n    name: \"overwrite\",\n    bindKey: bindKey(\"Insert\", \"Insert\"),\n    exec: function(editor) { editor.toggleOverwrite(); },\n    readOnly: true\n}, {\n    name: \"selecttostart\",\n    bindKey: bindKey(\"Ctrl-Shift-Home|Alt-Shift-Up\", \"Command-Shift-Up\"),\n    exec: function(editor) { editor.getSelection().selectFileStart(); },\n    readOnly: true\n}, {\n    name: \"gotostart\",\n    bindKey: bindKey(\"Ctrl-Home|Ctrl-Up\", \"Command-Home|Command-Up\"),\n    exec: function(editor) { editor.navigateFileStart(); },\n    readOnly: true\n}, {\n    name: \"selectup\",\n    bindKey: bindKey(\"Shift-Up\", \"Shift-Up\"),\n    exec: function(editor) { editor.getSelection().selectUp(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"golineup\",\n    bindKey: bindKey(\"Up\", \"Up|Ctrl-P\"),\n    exec: function(editor, args) { editor.navigateUp(args.times); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"selecttoend\",\n    bindKey: bindKey(\"Ctrl-Shift-End|Alt-Shift-Down\", \"Command-Shift-Down\"),\n    exec: function(editor) { editor.getSelection().selectFileEnd(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"gotoend\",\n    bindKey: bindKey(\"Ctrl-End|Ctrl-Down\", \"Command-End|Command-Down\"),\n    exec: function(editor) { editor.navigateFileEnd(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"selectdown\",\n    bindKey: bindKey(\"Shift-Down\", \"Shift-Down\"),\n    exec: function(editor) { editor.getSelection().selectDown(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"golinedown\",\n    bindKey: bindKey(\"Down\", \"Down|Ctrl-N\"),\n    exec: function(editor, args) { editor.navigateDown(args.times); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"selectwordleft\",\n    bindKey: bindKey(\"Ctrl-Shift-Left\", \"Option-Shift-Left\"),\n    exec: function(editor) { editor.getSelection().selectWordLeft(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"gotowordleft\",\n    bindKey: bindKey(\"Ctrl-Left\", \"Option-Left\"),\n    exec: function(editor) { editor.navigateWordLeft(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"selecttolinestart\",\n    bindKey: bindKey(\"Alt-Shift-Left\", \"Command-Shift-Left\"),\n    exec: function(editor) { editor.getSelection().selectLineStart(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"gotolinestart\",\n    bindKey: bindKey(\"Alt-Left|Home\", \"Command-Left|Home|Ctrl-A\"),\n    exec: function(editor) { editor.navigateLineStart(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"selectleft\",\n    bindKey: bindKey(\"Shift-Left\", \"Shift-Left\"),\n    exec: function(editor) { editor.getSelection().selectLeft(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"gotoleft\",\n    bindKey: bindKey(\"Left\", \"Left|Ctrl-B\"),\n    exec: function(editor, args) { editor.navigateLeft(args.times); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"selectwordright\",\n    bindKey: bindKey(\"Ctrl-Shift-Right\", \"Option-Shift-Right\"),\n    exec: function(editor) { editor.getSelection().selectWordRight(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"gotowordright\",\n    bindKey: bindKey(\"Ctrl-Right\", \"Option-Right\"),\n    exec: function(editor) { editor.navigateWordRight(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"selecttolineend\",\n    bindKey: bindKey(\"Alt-Shift-Right\", \"Command-Shift-Right\"),\n    exec: function(editor) { editor.getSelection().selectLineEnd(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"gotolineend\",\n    bindKey: bindKey(\"Alt-Right|End\", \"Command-Right|End|Ctrl-E\"),\n    exec: function(editor) { editor.navigateLineEnd(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"selectright\",\n    bindKey: bindKey(\"Shift-Right\", \"Shift-Right\"),\n    exec: function(editor) { editor.getSelection().selectRight(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"gotoright\",\n    bindKey: bindKey(\"Right\", \"Right|Ctrl-F\"),\n    exec: function(editor, args) { editor.navigateRight(args.times); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"selectpagedown\",\n    bindKey: bindKey(\"Shift-PageDown\", \"Shift-PageDown\"),\n    exec: function(editor) { editor.selectPageDown(); },\n    readOnly: true\n}, {\n    name: \"pagedown\",\n    bindKey: bindKey(null, \"PageDown\"),\n    exec: function(editor) { editor.scrollPageDown(); },\n    readOnly: true\n}, {\n    name: \"gotopagedown\",\n    bindKey: bindKey(\"PageDown\", \"Option-PageDown|Ctrl-V\"),\n    exec: function(editor) { editor.gotoPageDown(); },\n    readOnly: true\n}, {\n    name: \"selectpageup\",\n    bindKey: bindKey(\"Shift-PageUp\", \"Shift-PageUp\"),\n    exec: function(editor) { editor.selectPageUp(); },\n    readOnly: true\n}, {\n    name: \"pageup\",\n    bindKey: bindKey(null, \"PageUp\"),\n    exec: function(editor) { editor.scrollPageUp(); },\n    readOnly: true\n}, {\n    name: \"gotopageup\",\n    bindKey: bindKey(\"PageUp\", \"Option-PageUp\"),\n    exec: function(editor) { editor.gotoPageUp(); },\n    readOnly: true\n}, {\n    name: \"selectlinestart\",\n    bindKey: bindKey(\"Shift-Home\", \"Shift-Home\"),\n    exec: function(editor) { editor.getSelection().selectLineStart(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"selectlineend\",\n    bindKey: bindKey(\"Shift-End\", \"Shift-End\"),\n    exec: function(editor) { editor.getSelection().selectLineEnd(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, {\n    name: \"togglerecording\",\n    bindKey: bindKey(\"Ctrl-Alt-E\", \"Command-Option-E\"),\n    exec: function(editor) { editor.commands.toggleRecording(); },\n    readOnly: true\n}, {\n    name: \"replaymacro\",\n    bindKey: bindKey(\"Ctrl-Shift-E\", \"Command-Shift-E\"),\n    exec: function(editor) { editor.commands.replay(editor); },\n    readOnly: true\n}, {\n    name: \"jumptomatching\",\n    bindKey: bindKey(\"Ctrl-Shift-P\", \"Ctrl-Shift-P\"),\n    exec: function(editor) { editor.jumpToMatching(); },\n    multiSelectAction: \"forEach\",\n    readOnly: true\n}, \n\n// commands disabled in readOnly mode\n{\n    name: \"cut\",\n    exec: function(editor) {\n        var range = editor.getSelectionRange();\n        editor._emit(\"cut\", range);\n\n        if (!editor.selection.isEmpty()) {\n            editor.session.remove(range);\n            editor.clearSelection();\n        }\n    },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"removeline\",\n    bindKey: bindKey(\"Ctrl-D\", \"Command-D\"),\n    exec: function(editor) { editor.removeLines(); },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"togglecomment\",\n    bindKey: bindKey(\"Ctrl-7\", \"Command-7\"),\n    exec: function(editor) { editor.toggleCommentLines(); },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"replace\",\n    bindKey: bindKey(\"Ctrl-R\", \"Command-Option-F\"),\n    exec: function(editor) {\n        var needle = prompt(\"Find:\", editor.getCopyText());\n        if (!needle)\n            return;\n        var replacement = prompt(\"Replacement:\");\n        if (!replacement)\n            return;\n        editor.replace(replacement, {needle: needle});\n    }\n}, {\n    name: \"replaceall\",\n    bindKey: bindKey(\"Ctrl-Shift-R\", \"Command-Shift-Option-F\"),\n    exec: function(editor) {\n        var needle = prompt(\"Find:\");\n        if (!needle)\n            return;\n        var replacement = prompt(\"Replacement:\");\n        if (!replacement)\n            return;\n        editor.replaceAll(replacement, {needle: needle});\n    }\n}, {\n    name: \"undo\",\n    bindKey: bindKey(\"Ctrl-Z\", \"Command-Z\"),\n    exec: function(editor) { editor.undo(); }\n}, {\n    name: \"redo\",\n    bindKey: bindKey(\"Ctrl-Shift-Z|Ctrl-Y\", \"Command-Shift-Z|Command-Y\"),\n    exec: function(editor) { editor.redo(); }\n}, {\n    name: \"copylinesup\",\n    bindKey: bindKey(\"Ctrl-Alt-Up\", \"Command-Option-Up\"),\n    exec: function(editor) { editor.copyLinesUp(); }\n}, {\n    name: \"movelinesup\",\n    bindKey: bindKey(\"Alt-Up\", \"Option-Up\"),\n    exec: function(editor) { editor.moveLinesUp(); }\n}, {\n    name: \"copylinesdown\",\n    bindKey: bindKey(\"Ctrl-Alt-Down\", \"Command-Option-Down\"),\n    exec: function(editor) { editor.copyLinesDown(); }\n}, {\n    name: \"movelinesdown\",\n    bindKey: bindKey(\"Alt-Down\", \"Option-Down\"),\n    exec: function(editor) { editor.moveLinesDown(); }\n}, {\n    name: \"del\",\n    bindKey: bindKey(\"Delete\", \"Delete|Ctrl-D\"),\n    exec: function(editor) { editor.remove(\"right\"); },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"backspace\",\n    bindKey: bindKey(\n        \"Command-Backspace|Option-Backspace|Shift-Backspace|Backspace\",\n        \"Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H\"\n    ),\n    exec: function(editor) { editor.remove(\"left\"); },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"removetolinestart\",\n    bindKey: bindKey(\"Alt-Backspace\", \"Command-Backspace\"),\n    exec: function(editor) { editor.removeToLineStart(); },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"removetolineend\",\n    bindKey: bindKey(\"Alt-Delete\", \"Ctrl-K\"),\n    exec: function(editor) { editor.removeToLineEnd(); },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"removewordleft\",\n    bindKey: bindKey(\"Ctrl-Backspace\", \"Alt-Backspace|Ctrl-Alt-Backspace\"),\n    exec: function(editor) { editor.removeWordLeft(); },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"removewordright\",\n    bindKey: bindKey(\"Ctrl-Delete\", \"Alt-Delete\"),\n    exec: function(editor) { editor.removeWordRight(); },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"outdent\",\n    bindKey: bindKey(\"Shift-Tab\", \"Shift-Tab\"),\n    exec: function(editor) { editor.blockOutdent(); },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"indent\",\n    bindKey: bindKey(\"Tab\", \"Tab\"),\n    exec: function(editor) { editor.indent(); },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"insertstring\",\n    exec: function(editor, str) { editor.insert(str); },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"inserttext\",\n    exec: function(editor, args) {\n        editor.insert(lang.stringRepeat(args.text  || \"\", args.times || 1));\n    },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"splitline\",\n    bindKey: bindKey(null, \"Ctrl-O\"),\n    exec: function(editor) { editor.splitLine(); },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"transposeletters\",\n    bindKey: bindKey(\"Ctrl-T\", \"Ctrl-T\"),\n    exec: function(editor) { editor.transposeLetters(); },\n    multiSelectAction: function(editor) {editor.transposeSelections(1); }\n}, {\n    name: \"touppercase\",\n    bindKey: bindKey(\"Ctrl-U\", \"Ctrl-U\"),\n    exec: function(editor) { editor.toUpperCase(); },\n    multiSelectAction: \"forEach\"\n}, {\n    name: \"tolowercase\",\n    bindKey: bindKey(\"Ctrl-Shift-U\", \"Ctrl-Shift-U\"),\n    exec: function(editor) { editor.toLowerCase(); },\n    multiSelectAction: \"forEach\"\n}];\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/commands/multi_select_commands.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Harutyun Amirjanyan <amirjanyan AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\n// commands to enter multiselect mode\nexports.defaultCommands = [{\n    name: \"addCursorAbove\",\n    exec: function(editor) { editor.selectMoreLines(-1); },\n    bindKey: {win: \"Ctrl-Alt-Up\", mac: \"Ctrl-Alt-Up\"},\n    readonly: true\n}, {\n    name: \"addCursorBelow\",\n    exec: function(editor) { editor.selectMoreLines(1); },\n    bindKey: {win: \"Ctrl-Alt-Down\", mac: \"Ctrl-Alt-Down\"},\n    readonly: true\n}, {\n    name: \"addCursorAboveSkipCurrent\",\n    exec: function(editor) { editor.selectMoreLines(-1, true); },\n    bindKey: {win: \"Ctrl-Alt-Shift-Up\", mac: \"Ctrl-Alt-Shift-Up\"},\n    readonly: true\n}, {\n    name: \"addCursorBelowSkipCurrent\",\n    exec: function(editor) { editor.selectMoreLines(1, true); },\n    bindKey: {win: \"Ctrl-Alt-Shift-Down\", mac: \"Ctrl-Alt-Shift-Down\"},\n    readonly: true\n}, {\n    name: \"selectMoreBefore\",\n    exec: function(editor) { editor.selectMore(-1); },\n    bindKey: {win: \"Ctrl-Alt-Left\", mac: \"Ctrl-Alt-Left\"},\n    readonly: true\n}, {\n    name: \"selectMoreAfter\",\n    exec: function(editor) { editor.selectMore(1); },\n    bindKey: {win: \"Ctrl-Alt-Right\", mac: \"Ctrl-Alt-Right\"},\n    readonly: true\n}, {\n    name: \"selectNextBefore\",\n    exec: function(editor) { editor.selectMore(-1, true); },\n    bindKey: {win: \"Ctrl-Alt-Shift-Left\", mac: \"Ctrl-Alt-Shift-Left\"},\n    readonly: true\n}, {\n    name: \"selectNextAfter\",\n    exec: function(editor) { editor.selectMore(1, true); },\n    bindKey: {win: \"Ctrl-Alt-Shift-Right\", mac: \"Ctrl-Alt-Shift-Right\"},\n    readonly: true\n},  {\n    name: \"splitIntoLines\",\n    exec: function(editor) { editor.multiSelect.splitIntoLines(); },\n    bindKey: {win: \"Ctrl-Shift-L\", mac: \"Ctrl-Shift-L\"},\n    readonly: true\n}];\n\n// commands active in multiselect mode\nexports.multiEditCommands = [{\n    name: \"singleSelection\",\n    bindKey: \"esc\",\n    exec: function(editor) { editor.exitMultiSelectMode(); },\n    readonly: true\n}];\n\nvar HashHandler = require(\"../keyboard/hash_handler\").HashHandler;\nexports.keyboardHandler = new HashHandler(exports.multiEditCommands);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/config.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"no use strict\";\n\nvar lang = require(\"./lib/lang\");\n\nvar global = (function() {\n    return this;\n})();\n\nvar options = {\n    packaged: false,\n    workerPath: \"\",\n    modePath: \"\",\n    themePath: \"\",\n    suffix: \".js\"\n};\n\nexports.get = function(key) {\n    if (!options.hasOwnProperty(key))\n        throw new Error(\"Unknown confik key: \" + key);\n        \n    return options[key];\n};\n\nexports.set = function(key, value) {\n    if (!options.hasOwnProperty(key))\n        throw new Error(\"Unknown confik key: \" + key);\n        \n    options[key] = value;\n};\n\nexports.all = function() {\n    return lang.copyObject(options);\n};\n\nexports.init = function() {\n    options.packaged = require.packaged || module.packaged || (global.define && define.packaged);\n\n    if (!global.document)\n        return \"\";\n\n    var scriptOptions = {};\n    var scriptUrl = \"\";\n    var suffix;\n    \n    var scripts = document.getElementsByTagName(\"script\");\n    for (var i=0; i<scripts.length; i++) {\n        var script = scripts[i];\n\n        var src = script.src || script.getAttribute(\"src\");\n        if (!src) {\n            continue;\n        }\n        \n        var attributes = script.attributes;\n        for (var j=0, l=attributes.length; j < l; j++) {\n            var attr = attributes[j];\n            if (attr.name.indexOf(\"data-ace-\") === 0) {\n                scriptOptions[deHyphenate(attr.name.replace(/^data-ace-/, \"\"))] = attr.value;\n            }\n        }\n\n        var m = src.match(/^(?:(.*\\/)ace\\.js|(.*\\/)ace((-uncompressed)?(-noconflict)?\\.js))(?:\\?|$)/);\n        if (m) {\n            scriptUrl = m[1] || m[2];\n            suffix = m[3];\n        }\n    }\n    \n    if (scriptUrl) {\n        scriptOptions.base = scriptOptions.base || scriptUrl;\n        scriptOptions.packaged = true;\n    }\n    \n    scriptOptions.suffix = scriptOptions.suffix || suffix;\n    scriptOptions.workerPath = scriptOptions.workerPath || scriptOptions.base;\n    scriptOptions.modePath = scriptOptions.modePath || scriptOptions.base;\n    scriptOptions.themePath = scriptOptions.themePath || scriptOptions.base;\n    delete scriptOptions.base;\n    \n    for (var key in scriptOptions)\n        if (typeof scriptOptions[key] !== \"undefined\")\n            exports.set(key, scriptOptions[key]);\n};\n\nfunction deHyphenate(str) {\n    return str.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); });\n}\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/css/editor.css",
    "content": "@import url(//fonts.googleapis.com/css?family=Droid+Sans+Mono);\n\n.ace_editor {\n    position: absolute;\n    overflow: hidden;\n    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Droid Sans Mono', 'Consolas', monospace;\n    font-size: 12px;\n}\n\n.ace_scroller {\n    position: absolute;\n    overflow-x: scroll;\n    overflow-y: hidden;\n}\n\n.ace_content {\n    position: absolute;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    cursor: text;\n}\n\n.ace_composition {\n    position: absolute;\n    background: #555;\n    color: #DDD;\n    z-index: 4;\n}\n\n.ace_gutter {\n    position: absolute;\n    overflow : hidden;\n    height: 100%;\n    width: auto;\n    cursor: default;\n    z-index: 1000;\n}\n\n.ace_gutter.horscroll {\n    box-shadow: 0px 0px 20px rgba(0,0,0,0.4);\n}\n\n.ace_gutter-cell {\n    padding-left: 19px;\n    padding-right: 6px;\n}\n\n.ace_gutter-cell.ace_error {\n    background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%F5or%F5%87%88%F5nr%F4ns%EBmq%F5z%7F%DDJT%DEKS%DFOW%F1Yc%F2ah%CE(7%CE)8%D18E%DD%40M%F2KZ%EBU%60%F4%60m%DCir%C8%16(%C8%19*%CE%255%F1%3FR%F1%3FS%E6%AB%B5%CA%5DI%CEn%5E%F7%A2%9A%C9G%3E%E0a%5B%F7%89%85%F5yy%F6%82%80%ED%82%80%FF%BF%BF%E3%C4%C4%FF%FF%FF%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%25%00%2C%00%00%00%00%10%00%10%00%00%06p%C0%92pH%2C%1A%8F%C8%D2H%93%E1d4%23%E4%88%D3%09mB%1DN%B48%F5%90%40%60%92G%5B%94%20%3E%22%D2%87%24%FA%20%24%C5%06A%00%20%B1%07%02B%A38%89X.v%17%82%11%13q%10%0Fi%24%0F%8B%10%7BD%12%0Ei%09%92%09%0EpD%18%15%24%0A%9Ci%05%0C%18F%18%0B%07%04%01%04%06%A0H%18%12%0D%14%0D%12%A1I%B3%B4%B5IA%00%3B\");\n    background-repeat: no-repeat;\n    background-position: 2px center;\n}\n\n.ace_gutter-cell.ace_warning {\n    background-image: url(\"data:image/gif,GIF89a%10%00%10%00%D5%00%00%FF%DBr%FF%DE%81%FF%E2%8D%FF%E2%8F%FF%E4%96%FF%E3%97%FF%E5%9D%FF%E6%9E%FF%EE%C1%FF%C8Z%FF%CDk%FF%D0s%FF%D4%81%FF%D5%82%FF%D5%83%FF%DC%97%FF%DE%9D%FF%E7%B8%FF%CCl%7BQ%13%80U%15%82W%16%81U%16%89%5B%18%87%5B%18%8C%5E%1A%94d%1D%C5%83-%C9%87%2F%C6%84.%C6%85.%CD%8B2%C9%871%CB%8A3%CD%8B5%DC%98%3F%DF%9BB%E0%9CC%E1%A5U%CB%871%CF%8B5%D1%8D6%DB%97%40%DF%9AB%DD%99B%E3%B0p%E7%CC%AE%FF%FF%FF%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00!%F9%04%01%00%00%2F%00%2C%00%00%00%00%10%00%10%00%00%06a%C0%97pH%2C%1A%8FH%A1%ABTr%25%87%2B%04%82%F4%7C%B9X%91%08%CB%99%1C!%26%13%84*iJ9(%15G%CA%84%14%01%1A%97%0C%03%80%3A%9A%3E%81%84%3E%11%08%B1%8B%20%02%12%0F%18%1A%0F%0A%03'F%1C%04%0B%10%16%18%10%0B%05%1CF%1D-%06%07%9A%9A-%1EG%1B%A0%A1%A0U%A4%A5%A6BA%00%3B\");\n    background-repeat: no-repeat;\n    background-position: 2px center;\n}\n\n.ace_gutter-cell.ace_info {\n    background-image: url(\"data:image/gif;base64,R0lGODlhEAAQAMQAAAAAAEFBQVJSUl5eXmRkZGtra39/f4WFhYmJiZGRkaampry8vMPDw8zMzNXV1dzc3OTk5Orq6vDw8P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABQALAAAAAAQABAAAAUuICWOZGmeaBml5XGwFCQSBGyXRSAwtqQIiRuiwIM5BoYVbEFIyGCQoeJGrVptIQA7\");\n    background-repeat: no-repeat;\n    background-position: 2px center;\n}\n\n.ace_editor .ace_sb {\n    position: absolute;\n    overflow-x: hidden;\n    overflow-y: scroll;\n    right: 0;\n}\n\n.ace_editor .ace_sb div {\n    position: absolute;\n    width: 1px;\n    left: 0;\n}\n\n.ace_editor .ace_print_margin_layer {\n    z-index: 0;\n    position: absolute;\n    overflow: hidden;\n    margin: 0;\n    left: 0;\n    height: 100%;\n    width: 100%;\n}\n\n.ace_editor .ace_print_margin {\n    position: absolute;\n    height: 100%;\n}\n\n.ace_editor textarea {\n    position: fixed;\n    z-index: 0;\n    width: 10px;\n    height: 30px;\n    opacity: 0;\n    background: transparent;\n    appearance: none;\n    -moz-appearance: none;\n    border: none;\n    resize: none;\n    outline: none;\n    overflow: hidden;\n}\n\n.ace_layer {\n    z-index: 1;\n    position: absolute;\n    overflow: hidden;\n    white-space: nowrap;\n    height: 100%;\n    width: 100%;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    /* setting pointer-events: auto; on node under the mouse, which changes\n        during scroll, will break mouse wheel scrolling in Safari */\n    pointer-events: none;\n}\n\n.ace_gutter .ace_layer {\n    position: relative;\n    min-width: 40px;\n    text-align: right;\n    pointer-events: auto;\n}\n\n.ace_text-layer {\n    color: black;\n}\n\n.ace_cjk {\n    display: inline-block;\n    text-align: center;\n}\n\n.ace_cursor-layer {\n    z-index: 4;\n}\n\n.ace_cursor {\n    z-index: 4;\n    position: absolute;\n}\n\n.ace_cursor.ace_hidden {\n    opacity: 0.2;\n}\n\n.ace_editor.multiselect .ace_cursor {\n    border-left-width: 1px;\n}\n\n.ace_line {\n    white-space: nowrap;\n}\n\n.ace_marker-layer .ace_step {\n    position: absolute;\n    z-index: 3;\n}\n\n.ace_marker-layer .ace_selection {\n    position: absolute;\n    z-index: 5;\n}\n\n.ace_marker-layer .ace_bracket {\n    position: absolute;\n    z-index: 6;\n}\n\n.ace_marker-layer .ace_active_line {\n    position: absolute;\n    z-index: 2;\n}\n\n.ace_gutter .ace_gutter_active_line{\n    background-color : #dcdcdc;\n}\n\n.ace_marker-layer .ace_selected_word {\n    position: absolute;\n    z-index: 4;\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n}\n\n.ace_line .ace_fold {\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n    \n    display: inline-block;\n    height: 11px;\n    margin-top: -2px;\n    vertical-align: middle;\n\n    background-image: \n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),\n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%3AIDAT8%11c%FC%FF%FF%7F%18%03%1A%60%01%F2%3F%A0%891%80%04%FF%11-%F8%17%9BJ%E2%05%B1ZD%81v%26t%E7%80%F8%A3%82h%A12%1A%20%A3%01%02%0F%01%BA%25%06%00%19%C0%0D%AEF%D5%3ES%00%00%00%00IEND%AEB%60%82\");\n    background-repeat: no-repeat, repeat-x;\n    background-position: center center, top left;\n    color: transparent;\n\n    border: 1px solid black;\n    -moz-border-radius: 2px;\n    -webkit-border-radius: 2px;\n    border-radius: 2px;\n    \n    cursor: pointer;\n    pointer-events: auto;\n}\n\n.ace_dark .ace_fold {\n}\n\n.ace_fold:hover{\n    background-image: \n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),\n        url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%003IDAT8%11c%FC%FF%FF%7F%3E%03%1A%60%01%F2%3F%A3%891%80%04%FFQ%26%F8w%C0%B43%A1%DB%0C%E2%8F%0A%A2%85%CAh%80%8C%06%08%3C%04%E8%96%18%00%A3S%0D%CD%CF%D8%C1%9D%00%00%00%00IEND%AEB%60%82\");\n    background-repeat: no-repeat, repeat-x;\n    background-position: center center, top left;\n}\n\n.ace_dragging .ace_content {\n    cursor: move;\n}\n\n.ace_folding-enabled > .ace_gutter-cell {\n    padding-right: 13px;\n}\n\n.ace_fold-widget {\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    -webkit-box-sizing: border-box;\n\n    margin: 0 -12px 1px 1px;\n    display: inline-block;\n    height: 14px;\n    width: 11px;\n    vertical-align: text-bottom;\n    \n    background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAe%8A%B1%0D%000%0C%C2%F2%2CK%96%BC%D0%8F9%81%88H%E9%D0%0E%96%C0%10%92%3E%02%80%5E%82%E4%A9*-%EEsw%C8%CC%11%EE%96w%D8%DC%E9*Eh%0C%151(%00%00%00%00IEND%AEB%60%82\");\n    background-repeat: no-repeat;\n    background-position: center 5px;\n\n    border-radius: 3px;\n}\n\n.ace_fold-widget.end {\n    background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAm%C7%C1%09%000%08C%D1%8C%ECE%C8E(%8E%EC%02)%1EZJ%F1%C1'%04%07I%E1%E5%EE%CAL%F5%A2%99%99%22%E2%D6%1FU%B5%FE0%D9x%A7%26Wz5%0E%D5%00%00%00%00IEND%AEB%60%82\");\n}\n\n.ace_fold-widget.closed {\n    background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%03%00%00%00%06%08%06%00%00%00%06%E5%24%0C%00%00%009IDATx%DA5%CA%C1%09%000%08%03%C0%AC*(%3E%04%C1%0D%BA%B1%23%A4Uh%E0%20%81%C0%CC%F8%82%81%AA%A2%AArGfr%88%08%11%11%1C%DD%7D%E0%EE%5B%F6%F6%CB%B8%05Q%2F%E9tai%D9%00%00%00%00IEND%AEB%60%82\");\n}\n\n.ace_fold-widget:hover {\n    border: 1px solid rgba(0, 0, 0, 0.3);\n    background-color: rgba(255, 255, 255, 0.2);\n    -moz-box-shadow:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n    -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n    -webkit-box-shadow:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n    -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n    box-shadow:inset 0 1px 1px rgba(255, 255, 255, 0.7);\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\n    background-position: center 4px;\n}\n\n.ace_fold-widget:active {\n    border: 1px solid rgba(0, 0, 0, 0.4);\n    background-color: rgba(0, 0, 0, 0.05);\n    -moz-box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n    -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n    -webkit-box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n    -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n    box-shadow:inset 0 1px 1px rgba(255, 255, 255);\n    box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\n}\n\n.ace_fold-widget.invalid {\n    background-color: #FFB4B4;\n    border-color: #DE5555;\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/document.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"./lib/oop\");\nvar EventEmitter = require(\"./lib/event_emitter\").EventEmitter;\nvar Range = require(\"./range\").Range;\nvar Anchor = require(\"./anchor\").Anchor;\n\nvar Document = function(text) {\n    this.$lines = [];\n\n    if (Array.isArray(text)) {\n        this.insertLines(0, text);\n    }\n    // There has to be one line at least in the document. If you pass an empty\n    // string to the insert function, nothing will happen. Workaround.\n    else if (text.length == 0) {\n        this.$lines = [\"\"];\n    } else {\n        this.insert({row: 0, column:0}, text);\n    }\n};\n\n(function() {\n\n    oop.implement(this, EventEmitter);\n\n    this.setValue = function(text) {\n        var len = this.getLength();\n        this.remove(new Range(0, 0, len, this.getLine(len-1).length));\n        this.insert({row: 0, column:0}, text);\n    };\n\n    this.getValue = function() {\n        return this.getAllLines().join(this.getNewLineCharacter());\n    };\n\n    this.createAnchor = function(row, column) {\n        return new Anchor(this, row, column);\n    };\n\n    // check for IE split bug\n    if (\"aaa\".split(/a/).length == 0)\n        this.$split = function(text) {\n            return text.replace(/\\r\\n|\\r/g, \"\\n\").split(\"\\n\");\n        }\n    else\n        this.$split = function(text) {\n            return text.split(/\\r\\n|\\r|\\n/);\n        };\n\n\n    this.$detectNewLine = function(text) {\n        var match = text.match(/^.*?(\\r\\n|\\r|\\n)/m);\n        if (match) {\n            this.$autoNewLine = match[1];\n        } else {\n            this.$autoNewLine = \"\\n\";\n        }\n    };\n\n    this.getNewLineCharacter = function() {\n      switch (this.$newLineMode) {\n          case \"windows\":\n              return \"\\r\\n\";\n\n          case \"unix\":\n              return \"\\n\";\n\n          case \"auto\":\n              return this.$autoNewLine;\n      }\n    };\n\n    this.$autoNewLine = \"\\n\";\n    this.$newLineMode = \"auto\";\n    this.setNewLineMode = function(newLineMode) {\n        if (this.$newLineMode === newLineMode)\n            return;\n\n        this.$newLineMode = newLineMode;\n    };\n\n    this.getNewLineMode = function() {\n        return this.$newLineMode;\n    };\n\n    this.isNewLine = function(text) {\n        return (text == \"\\r\\n\" || text == \"\\r\" || text == \"\\n\");\n    };\n\n    /**\n     * Get a verbatim copy of the given line as it is in the document\n     */\n    this.getLine = function(row) {\n        return this.$lines[row] || \"\";\n    };\n\n    this.getLines = function(firstRow, lastRow) {\n        return this.$lines.slice(firstRow, lastRow + 1);\n    };\n\n    /**\n     * Returns all lines in the document as string array. Warning: The caller\n     * should not modify this array!\n     */\n    this.getAllLines = function() {\n        return this.getLines(0, this.getLength());\n    };\n\n    this.getLength = function() {\n        return this.$lines.length;\n    };\n\n    this.getTextRange = function(range) {\n        if (range.start.row == range.end.row) {\n            return this.$lines[range.start.row].substring(range.start.column,\n                                                         range.end.column);\n        }\n        else {\n            var lines = [];\n            lines.push(this.$lines[range.start.row].substring(range.start.column));\n            lines.push.apply(lines, this.getLines(range.start.row+1, range.end.row-1));\n            lines.push(this.$lines[range.end.row].substring(0, range.end.column));\n            return lines.join(this.getNewLineCharacter());\n        }\n    };\n\n    this.$clipPosition = function(position) {\n        var length = this.getLength();\n        if (position.row >= length) {\n            position.row = Math.max(0, length - 1);\n            position.column = this.getLine(length-1).length;\n        }\n        return position;\n    };\n\n    this.insert = function(position, text) {\n        if (!text || text.length === 0)\n            return position;\n\n        position = this.$clipPosition(position);\n\n        // only detect new lines if the document has no line break yet\n        if (this.getLength() <= 1)\n            this.$detectNewLine(text);\n\n        var lines = this.$split(text);\n        var firstLine = lines.splice(0, 1)[0];\n        var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0];\n\n        position = this.insertInLine(position, firstLine);\n        if (lastLine !== null) {\n            position = this.insertNewLine(position); // terminate first line\n            position = this.insertLines(position.row, lines);\n            position = this.insertInLine(position, lastLine || \"\");\n        }\n        return position;\n    };\n\n    this.insertLines = function(row, lines) {\n        if (lines.length == 0)\n            return {row: row, column: 0};\n\n        var args = [row, 0];\n        args.push.apply(args, lines);\n        this.$lines.splice.apply(this.$lines, args);\n\n        var range = new Range(row, 0, row + lines.length, 0);\n        var delta = {\n            action: \"insertLines\",\n            range: range,\n            lines: lines\n        };\n        this._emit(\"change\", { data: delta });\n        return range.end;\n    };\n\n    this.insertNewLine = function(position) {\n        position = this.$clipPosition(position);\n        var line = this.$lines[position.row] || \"\";\n\n        this.$lines[position.row] = line.substring(0, position.column);\n        this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length));\n\n        var end = {\n            row : position.row + 1,\n            column : 0\n        };\n\n        var delta = {\n            action: \"insertText\",\n            range: Range.fromPoints(position, end),\n            text: this.getNewLineCharacter()\n        };\n        this._emit(\"change\", { data: delta });\n\n        return end;\n    };\n\n    this.insertInLine = function(position, text) {\n        if (text.length == 0)\n            return position;\n\n        var line = this.$lines[position.row] || \"\";\n\n        this.$lines[position.row] = line.substring(0, position.column) + text\n                + line.substring(position.column);\n\n        var end = {\n            row : position.row,\n            column : position.column + text.length\n        };\n\n        var delta = {\n            action: \"insertText\",\n            range: Range.fromPoints(position, end),\n            text: text\n        };\n        this._emit(\"change\", { data: delta });\n\n        return end;\n    };\n\n    this.remove = function(range) {\n        // clip to document\n        range.start = this.$clipPosition(range.start);\n        range.end = this.$clipPosition(range.end);\n\n        if (range.isEmpty())\n            return range.start;\n\n        var firstRow = range.start.row;\n        var lastRow = range.end.row;\n\n        if (range.isMultiLine()) {\n            var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1;\n            var lastFullRow = lastRow - 1;\n\n            if (range.end.column > 0)\n                this.removeInLine(lastRow, 0, range.end.column);\n\n            if (lastFullRow >= firstFullRow)\n                this.removeLines(firstFullRow, lastFullRow);\n\n            if (firstFullRow != firstRow) {\n                this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length);\n                this.removeNewLine(range.start.row);\n            }\n        }\n        else {\n            this.removeInLine(firstRow, range.start.column, range.end.column);\n        }\n        return range.start;\n    };\n\n    this.removeInLine = function(row, startColumn, endColumn) {\n        if (startColumn == endColumn)\n            return;\n\n        var range = new Range(row, startColumn, row, endColumn);\n        var line = this.getLine(row);\n        var removed = line.substring(startColumn, endColumn);\n        var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length);\n        this.$lines.splice(row, 1, newLine);\n\n        var delta = {\n            action: \"removeText\",\n            range: range,\n            text: removed\n        };\n        this._emit(\"change\", { data: delta });\n        return range.start;\n    };\n\n    /**\n     * Removes a range of full lines\n     *\n     * @param firstRow {Integer} The first row to be removed\n     * @param lastRow {Integer} The last row to be removed\n     * @return {String[]} The removed lines\n     */\n    this.removeLines = function(firstRow, lastRow) {\n        var range = new Range(firstRow, 0, lastRow + 1, 0);\n        var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1);\n\n        var delta = {\n            action: \"removeLines\",\n            range: range,\n            nl: this.getNewLineCharacter(),\n            lines: removed\n        };\n        this._emit(\"change\", { data: delta });\n        return removed;\n    };\n\n    this.removeNewLine = function(row) {\n        var firstLine = this.getLine(row);\n        var secondLine = this.getLine(row+1);\n\n        var range = new Range(row, firstLine.length, row+1, 0);\n        var line = firstLine + secondLine;\n\n        this.$lines.splice(row, 2, line);\n\n        var delta = {\n            action: \"removeText\",\n            range: range,\n            text: this.getNewLineCharacter()\n        };\n        this._emit(\"change\", { data: delta });\n    };\n\n    this.replace = function(range, text) {\n        if (text.length == 0 && range.isEmpty())\n            return range.start;\n\n        // Shortcut: If the text we want to insert is the same as it is already\n        // in the document, we don't have to replace anything.\n        if (text == this.getTextRange(range))\n            return range.end;\n\n        this.remove(range);\n        if (text) {\n            var end = this.insert(range.start, text);\n        }\n        else {\n            end = range.start;\n        }\n\n        return end;\n    };\n\n    this.applyDeltas = function(deltas) {\n        for (var i=0; i<deltas.length; i++) {\n            var delta = deltas[i];\n            var range = Range.fromPoints(delta.range.start, delta.range.end);\n\n            if (delta.action == \"insertLines\")\n                this.insertLines(range.start.row, delta.lines);\n            else if (delta.action == \"insertText\")\n                this.insert(range.start, delta.text);\n            else if (delta.action == \"removeLines\")\n                this.removeLines(range.start.row, range.end.row - 1);\n            else if (delta.action == \"removeText\")\n                this.remove(range);\n        }\n    };\n\n    this.revertDeltas = function(deltas) {\n        for (var i=deltas.length-1; i>=0; i--) {\n            var delta = deltas[i];\n\n            var range = Range.fromPoints(delta.range.start, delta.range.end);\n\n            if (delta.action == \"insertLines\")\n                this.removeLines(range.start.row, range.end.row - 1);\n            else if (delta.action == \"insertText\")\n                this.remove(range);\n            else if (delta.action == \"removeLines\")\n                this.insertLines(range.start.row, delta.lines);\n            else if (delta.action == \"removeText\")\n                this.insert(range.start, delta.text);\n        }\n    };\n\n}).call(Document.prototype);\n\nexports.Document = Document;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/document_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Julian Viereck <julian.viereck@gmail.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n    require(\"./test/mockdom\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Document = require(\"./document\").Document;\nvar Range = require(\"./range\").Range;\nvar assert = require(\"./test/assertions\");\n\nmodule.exports = {\n\n    \"test: insert text in line\" : function() {\n        var doc = new Document([\"12\", \"34\"]);\n\n        var deltas = [];\n        doc.on(\"change\", function(e) { deltas.push(e.data); });\n\n        doc.insert({row: 0, column: 1}, \"juhu\");\n        assert.equal(doc.getValue(), [\"1juhu2\", \"34\"].join(\"\\n\"));\n\n        var d = deltas.concat();\n        doc.revertDeltas(d);\n        assert.equal(doc.getValue(), [\"12\", \"34\"].join(\"\\n\"));\n\n        doc.applyDeltas(d);\n        assert.equal(doc.getValue(), [\"1juhu2\", \"34\"].join(\"\\n\"));\n    },\n\n    \"test: insert new line\" : function() {\n        var doc = new Document([\"12\", \"34\"]);\n\n        var deltas = [];\n        doc.on(\"change\", function(e) { deltas.push(e.data); });\n\n        doc.insertNewLine({row: 0, column: 1});\n        assert.equal(doc.getValue(), [\"1\", \"2\", \"34\"].join(\"\\n\"));\n\n        var d = deltas.concat();\n        doc.revertDeltas(d);\n        assert.equal(doc.getValue(), [\"12\", \"34\"].join(\"\\n\"));\n\n        doc.applyDeltas(d);\n        assert.equal(doc.getValue(), [\"1\", \"2\", \"34\"].join(\"\\n\"));\n    },\n\n    \"test: insert lines at the beginning\" : function() {\n        var doc = new Document([\"12\", \"34\"]);\n\n        var deltas = [];\n        doc.on(\"change\", function(e) { deltas.push(e.data); });\n\n        doc.insertLines(0, [\"aa\", \"bb\"]);\n        assert.equal(doc.getValue(), [\"aa\", \"bb\", \"12\", \"34\"].join(\"\\n\"));\n\n        var d = deltas.concat();\n        doc.revertDeltas(d);\n        assert.equal(doc.getValue(), [\"12\", \"34\"].join(\"\\n\"));\n\n        doc.applyDeltas(d);\n        assert.equal(doc.getValue(), [\"aa\", \"bb\", \"12\", \"34\"].join(\"\\n\"));\n    },\n\n    \"test: insert lines at the end\" : function() {\n        var doc = new Document([\"12\", \"34\"]);\n\n        var deltas = [];\n        doc.on(\"change\", function(e) { deltas.push(e.data); });\n\n        doc.insertLines(2, [\"aa\", \"bb\"]);\n        assert.equal(doc.getValue(), [\"12\", \"34\", \"aa\", \"bb\"].join(\"\\n\"));\n    },\n\n    \"test: insert lines in the middle\" : function() {\n        var doc = new Document([\"12\", \"34\"]);\n\n        var deltas = [];\n        doc.on(\"change\", function(e) { deltas.push(e.data); });\n\n        doc.insertLines(1, [\"aa\", \"bb\"]);\n        assert.equal(doc.getValue(), [\"12\", \"aa\", \"bb\", \"34\"].join(\"\\n\"));\n\n        var d = deltas.concat();\n        doc.revertDeltas(d);\n        assert.equal(doc.getValue(), [\"12\", \"34\"].join(\"\\n\"));\n\n        doc.applyDeltas(d);\n        assert.equal(doc.getValue(), [\"12\", \"aa\", \"bb\", \"34\"].join(\"\\n\"));\n    },\n\n    \"test: insert multi line string at the start\" : function() {\n        var doc = new Document([\"12\", \"34\"]);\n\n        var deltas = [];\n        doc.on(\"change\", function(e) { deltas.push(e.data); });\n\n        doc.insert({row: 0, column: 0}, \"aa\\nbb\\ncc\");\n        assert.equal(doc.getValue(), [\"aa\", \"bb\", \"cc12\", \"34\"].join(\"\\n\"));\n\n        var d = deltas.concat();\n        doc.revertDeltas(d);\n        assert.equal(doc.getValue(), [\"12\", \"34\"].join(\"\\n\"));\n\n        doc.applyDeltas(d);\n        assert.equal(doc.getValue(), [\"aa\", \"bb\", \"cc12\", \"34\"].join(\"\\n\"));\n    },\n\n    \"test: insert multi line string at the end\" : function() {\n        var doc = new Document([\"12\", \"34\"]);\n\n        var deltas = [];\n        doc.on(\"change\", function(e) { deltas.push(e.data); });\n\n        doc.insert({row: 2, column: 0}, \"aa\\nbb\\ncc\");\n        assert.equal(doc.getValue(), [\"12\", \"34aa\", \"bb\", \"cc\"].join(\"\\n\"));\n\n        var d = deltas.concat();\n        doc.revertDeltas(d);\n        assert.equal(doc.getValue(), [\"12\", \"34\"].join(\"\\n\"));\n\n        doc.applyDeltas(d);\n        assert.equal(doc.getValue(), [\"12\", \"34aa\", \"bb\", \"cc\"].join(\"\\n\"));\n    },\n\n    \"test: insert multi line string in the middle\" : function() {\n        var doc = new Document([\"12\", \"34\"]);\n\n        var deltas = [];\n        doc.on(\"change\", function(e) { deltas.push(e.data); });\n\n        doc.insert({row: 0, column: 1}, \"aa\\nbb\\ncc\");\n        assert.equal(doc.getValue(), [\"1aa\", \"bb\", \"cc2\", \"34\"].join(\"\\n\"));\n\n        var d = deltas.concat();\n        doc.revertDeltas(d);\n        assert.equal(doc.getValue(), [\"12\", \"34\"].join(\"\\n\"));\n\n        doc.applyDeltas(d);\n        assert.equal(doc.getValue(), [\"1aa\", \"bb\", \"cc2\", \"34\"].join(\"\\n\"));\n    },\n\n    \"test: delete in line\" : function() {\n        var doc = new Document([\"1234\", \"5678\"]);\n\n        var deltas = [];\n        doc.on(\"change\", function(e) { deltas.push(e.data); });\n\n        doc.remove(new Range(0, 1, 0, 3));\n        assert.equal(doc.getValue(), [\"14\", \"5678\"].join(\"\\n\"));\n\n        var d = deltas.concat();\n        doc.revertDeltas(d);\n        assert.equal(doc.getValue(), [\"1234\", \"5678\"].join(\"\\n\"));\n\n        doc.applyDeltas(d);\n        assert.equal(doc.getValue(), [\"14\", \"5678\"].join(\"\\n\"));\n    },\n\n    \"test: delete new line\" : function() {\n        var doc = new Document([\"1234\", \"5678\"]);\n\n        var deltas = [];\n        doc.on(\"change\", function(e) { deltas.push(e.data); });\n\n        doc.remove(new Range(0, 4, 1, 0));\n        assert.equal(doc.getValue(), [\"12345678\"].join(\"\\n\"));\n\n        var d = deltas.concat();\n        doc.revertDeltas(d);\n        assert.equal(doc.getValue(), [\"1234\", \"5678\"].join(\"\\n\"));\n\n        doc.applyDeltas(d);\n        assert.equal(doc.getValue(), [\"12345678\"].join(\"\\n\"));\n    },\n\n    \"test: delete multi line range line\" : function() {\n        var doc = new Document([\"1234\", \"5678\", \"abcd\"]);\n\n        var deltas = [];\n        doc.on(\"change\", function(e) { deltas.push(e.data); });\n\n        doc.remove(new Range(0, 2, 2, 2));\n        assert.equal(doc.getValue(), [\"12cd\"].join(\"\\n\"));\n\n        var d = deltas.concat();\n        doc.revertDeltas(d);\n        assert.equal(doc.getValue(), [\"1234\", \"5678\", \"abcd\"].join(\"\\n\"));\n\n        doc.applyDeltas(d);\n        assert.equal(doc.getValue(), [\"12cd\"].join(\"\\n\"));\n    },\n\n    \"test: delete full lines\" : function() {\n        var doc = new Document([\"1234\", \"5678\", \"abcd\"]);\n\n        var deltas = [];\n        doc.on(\"change\", function(e) { deltas.push(e.data); });\n\n        doc.remove(new Range(1, 0, 3, 0));\n        assert.equal(doc.getValue(), [\"1234\", \"\"].join(\"\\n\"));\n    },\n\n    \"test: remove lines should return the removed lines\" : function() {\n        var doc = new Document([\"1234\", \"5678\", \"abcd\"]);\n\n        var removed = doc.removeLines(1, 2);\n        assert.equal(removed.join(\"\\n\"), [\"5678\", \"abcd\"].join(\"\\n\"));\n    },\n\n    \"test: should handle unix style new lines\" : function() {\n        var doc = new Document([\"1\", \"2\", \"3\"]);\n        assert.equal(doc.getValue(), [\"1\", \"2\", \"3\"].join(\"\\n\"));\n    },\n\n    \"test: should handle windows style new lines\" : function() {\n        var doc = new Document([\"1\", \"2\", \"3\"].join(\"\\r\\n\"));\n\n        doc.setNewLineMode(\"unix\");\n        assert.equal(doc.getValue(), [\"1\", \"2\", \"3\"].join(\"\\n\"));\n    },\n\n    \"test: set new line mode to 'windows' should use '\\\\r\\\\n' as new lines\": function() {\n        var doc = new Document([\"1\", \"2\", \"3\"].join(\"\\n\"));\n        doc.setNewLineMode(\"windows\");\n        assert.equal(doc.getValue(), [\"1\", \"2\", \"3\"].join(\"\\r\\n\"));\n    },\n\n    \"test: set new line mode to 'unix' should use '\\\\n' as new lines\": function() {\n        var doc = new Document([\"1\", \"2\", \"3\"].join(\"\\r\\n\"));\n\n        doc.setNewLineMode(\"unix\");\n        assert.equal(doc.getValue(), [\"1\", \"2\", \"3\"].join(\"\\n\"));\n    },\n\n    \"test: set new line mode to 'auto' should detect the incoming nl type\": function() {\n        var doc = new Document([\"1\", \"2\", \"3\"].join(\"\\n\"));\n\n        doc.setNewLineMode(\"auto\");\n        assert.equal(doc.getValue(), [\"1\", \"2\", \"3\"].join(\"\\n\"));\n\n        var doc = new Document([\"1\", \"2\", \"3\"].join(\"\\r\\n\"));\n\n        doc.setNewLineMode(\"auto\");\n        assert.equal(doc.getValue(), [\"1\", \"2\", \"3\"].join(\"\\r\\n\"));\n\n        doc.replace(new Range(0, 0, 2, 1), [\"4\", \"5\", \"6\"].join(\"\\n\"));\n        assert.equal([\"4\", \"5\", \"6\"].join(\"\\n\"), doc.getValue());\n    },\n\n    \"test: set value\": function() {\n        var doc = new Document(\"1\");\n        assert.equal(\"1\", doc.getValue());\n\n        doc.setValue(doc.getValue());\n        assert.equal(\"1\", doc.getValue());\n\n        var doc = new Document(\"1\\n2\");\n        assert.equal(\"1\\n2\", doc.getValue());\n\n        doc.setValue(doc.getValue());\n        assert.equal(\"1\\n2\", doc.getValue());\n    },\n\n    \"test: empty document has to contain one line\": function() {\n        var doc = new Document(\"\");\n        assert.equal(doc.$lines.length, 1);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/edit_session/bracket_match.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar TokenIterator = require(\"../token_iterator\").TokenIterator;\n\nfunction BracketMatch() {\n\n    this.findMatchingBracket = function(position) {\n        if (position.column == 0) return null;\n\n        var charBeforeCursor = this.getLine(position.row).charAt(position.column-1);\n        if (charBeforeCursor == \"\") return null;\n\n        var match = charBeforeCursor.match(/([\\(\\[\\{])|([\\)\\]\\}])/);\n        if (!match) {\n            return null;\n        }\n\n        if (match[1]) {\n            return this.$findClosingBracket(match[1], position);\n        } else {\n            return this.$findOpeningBracket(match[2], position);\n        }\n    };\n\n    this.$brackets = {\n        \")\": \"(\",\n        \"(\": \")\",\n        \"]\": \"[\",\n        \"[\": \"]\",\n        \"{\": \"}\",\n        \"}\": \"{\"\n    };\n\n    this.$findOpeningBracket = function(bracket, position) {\n        var openBracket = this.$brackets[bracket];\n        var depth = 1;\n\n        var iterator = new TokenIterator(this, position.row, position.column);\n        var token = iterator.getCurrentToken();\n        if (!token) return null;\n        \n        // token.type contains a period-delimited list of token identifiers\n        // (e.g.: \"constant.numeric\" or \"paren.lparen\").  Create a pattern that\n        // matches any token containing the same identifiers or a subset.  In\n        // addition, if token.type includes \"rparen\", then also match \"lparen\".\n        // So if type.token is \"paren.rparen\", then typeRe will match \"lparen.paren\".\n        var typeRe = new RegExp(\"(\\\\.?\" +\n            token.type.replace(\".\", \"|\").replace(\"rparen\", \"lparen|rparen\") + \")+\");\n        \n        // Start searching in token, just before the character at position.column\n        var valueIndex = position.column - iterator.getCurrentTokenColumn() - 2;\n        var value = token.value;\n        \n        while (true) {\n        \n            while (valueIndex >= 0) {\n                var chr = value.charAt(valueIndex);\n                if (chr == openBracket) {\n                    depth -= 1;\n                    if (depth == 0) {\n                        return {row: iterator.getCurrentTokenRow(),\n                            column: valueIndex + iterator.getCurrentTokenColumn()};\n                    }\n                }\n                else if (chr == bracket) {\n                    depth += 1;\n                }\n                valueIndex -= 1;\n            }\n\n            // Scan backward through the document, looking for the next token\n            // whose type matches typeRe\n            do {\n                token = iterator.stepBackward();\n            } while (token && !typeRe.test(token.type));\n\n            if (token == null)\n                break;\n                \n            value = token.value;\n            valueIndex = value.length - 1;\n        }\n        \n        return null;\n    };\n\n    this.$findClosingBracket = function(bracket, position) {\n        var closingBracket = this.$brackets[bracket];\n        var depth = 1;\n\n        var iterator = new TokenIterator(this, position.row, position.column);\n        var token = iterator.getCurrentToken();\n        if (!token) return null;\n\n        // token.type contains a period-delimited list of token identifiers\n        // (e.g.: \"constant.numeric\" or \"paren.lparen\").  Create a pattern that\n        // matches any token containing the same identifiers or a subset.  In\n        // addition, if token.type includes \"lparen\", then also match \"rparen\".\n        // So if type.token is \"lparen.paren\", then typeRe will match \"paren.rparen\".\n        var typeRe = new RegExp(\"(\\\\.?\" +\n            token.type.replace(\".\", \"|\").replace(\"lparen\", \"lparen|rparen\") + \")+\");\n\n        // Start searching in token, after the character at position.column\n        var valueIndex = position.column - iterator.getCurrentTokenColumn();\n\n        while (true) {\n\n            var value = token.value;\n            var valueLength = value.length;\n            while (valueIndex < valueLength) {\n                var chr = value.charAt(valueIndex);\n                if (chr == closingBracket) {\n                    depth -= 1;\n                    if (depth == 0) {\n                        return {row: iterator.getCurrentTokenRow(),\n                            column: valueIndex + iterator.getCurrentTokenColumn()};\n                    }\n                }\n                else if (chr == bracket) {\n                    depth += 1;\n                }\n                valueIndex += 1;\n            }\n\n            // Scan forward through the document, looking for the next token\n            // whose type matches typeRe\n            do {\n                token = iterator.stepForward();\n            } while (token && !typeRe.test(token.type));\n\n            if (token == null)\n                break;\n\n            valueIndex = 0;\n        }\n        \n        return null;\n    };\n}\nexports.BracketMatch = BracketMatch;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/edit_session/fold.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Julian Viereck <julian DOT viereck AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\n/**\n * Simple fold-data struct.\n **/\nvar Fold = exports.Fold = function(range, placeholder) {\n    this.foldLine = null;\n    this.placeholder = placeholder;\n    this.range = range;\n    this.start = range.start;\n    this.end = range.end;\n\n    this.sameRow = range.start.row == range.end.row;\n    this.subFolds = [];\n};\n\n(function() {\n\n    this.toString = function() {\n        return '\"' + this.placeholder + '\" ' + this.range.toString();\n    };\n\n    this.setFoldLine = function(foldLine) {\n        this.foldLine = foldLine;\n        this.subFolds.forEach(function(fold) {\n            fold.setFoldLine(foldLine);\n        });\n    };\n\n    this.clone = function() {\n        var range = this.range.clone();\n        var fold = new Fold(range, this.placeholder);\n        this.subFolds.forEach(function(subFold) {\n            fold.subFolds.push(subFold.clone());\n        });\n        return fold;\n    };\n\n    this.addSubFold = function(fold) {\n        if (this.range.isEqual(fold))\n            return this;\n\n        if (!this.range.containsRange(fold))\n            throw \"A fold can't intersect already existing fold\" + fold.range + this.range;\n\n        var row = fold.range.start.row, column = fold.range.start.column;\n        for (var i = 0, cmp = -1; i < this.subFolds.length; i++) {\n            cmp = this.subFolds[i].range.compare(row, column);\n            if (cmp != 1)\n                break;\n        }\n        var afterStart = this.subFolds[i];\n\n        if (cmp == 0)\n            return afterStart.addSubFold(fold)\n\n        // cmp == -1\n        var row = fold.range.end.row, column = fold.range.end.column;\n        for (var j = i, cmp = -1; j < this.subFolds.length; j++) {\n            cmp = this.subFolds[j].range.compare(row, column);\n            if (cmp != 1)\n                break;\n        }\n        var afterEnd = this.subFolds[j];\n\n        if (cmp == 0)\n            throw \"A fold can't intersect already existing fold\" + fold.range + this.range;\n\n        var consumedFolds = this.subFolds.splice(i, j - i, fold)\n        fold.setFoldLine(this.foldLine);\n\n        return fold;\n    }\n\n}).call(Fold.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/edit_session/fold_line.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Julian Viereck <julian DOT viereck AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Range = require(\"../range\").Range;\n\n/**\n * If an array is passed in, the folds are expected to be sorted already.\n */\nfunction FoldLine(foldData, folds) {\n    this.foldData = foldData;\n    if (Array.isArray(folds)) {\n        this.folds = folds;\n    } else {\n        folds = this.folds = [ folds ];\n    }\n\n    var last = folds[folds.length - 1]\n    this.range = new Range(folds[0].start.row, folds[0].start.column,\n                           last.end.row, last.end.column);\n    this.start = this.range.start;\n    this.end   = this.range.end;\n\n    this.folds.forEach(function(fold) {\n        fold.setFoldLine(this);\n    }, this);\n}\n\n(function() {\n    /**\n     * Note: This doesn't update wrapData!\n     */\n    this.shiftRow = function(shift) {\n        this.start.row += shift;\n        this.end.row += shift;\n        this.folds.forEach(function(fold) {\n            fold.start.row += shift;\n            fold.end.row += shift;\n        });\n    }\n\n    this.addFold = function(fold) {\n        if (fold.sameRow) {\n            if (fold.start.row < this.startRow || fold.endRow > this.endRow) {\n                throw \"Can't add a fold to this FoldLine as it has no connection\";\n            }\n            this.folds.push(fold);\n            this.folds.sort(function(a, b) {\n                return -a.range.compareEnd(b.start.row, b.start.column);\n            });\n            if (this.range.compareEnd(fold.start.row, fold.start.column) > 0) {\n                this.end.row = fold.end.row;\n                this.end.column =  fold.end.column;\n            } else if (this.range.compareStart(fold.end.row, fold.end.column) < 0) {\n                this.start.row = fold.start.row;\n                this.start.column = fold.start.column;\n            }\n        } else if (fold.start.row == this.end.row) {\n            this.folds.push(fold);\n            this.end.row = fold.end.row;\n            this.end.column = fold.end.column;\n        } else if (fold.end.row == this.start.row) {\n            this.folds.unshift(fold);\n            this.start.row = fold.start.row;\n            this.start.column = fold.start.column;\n        } else {\n            throw \"Trying to add fold to FoldRow that doesn't have a matching row\";\n        }\n        fold.foldLine = this;\n    }\n\n    this.containsRow = function(row) {\n        return row >= this.start.row && row <= this.end.row;\n    }\n\n    this.walk = function(callback, endRow, endColumn) {\n        var lastEnd = 0,\n            folds = this.folds,\n            fold,\n            comp, stop, isNewRow = true;\n\n        if (endRow == null) {\n            endRow = this.end.row;\n            endColumn = this.end.column;\n        }\n\n        for (var i = 0; i < folds.length; i++) {\n            fold = folds[i];\n\n            comp = fold.range.compareStart(endRow, endColumn);\n            // This fold is after the endRow/Column.\n            if (comp == -1) {\n                callback(null, endRow, endColumn, lastEnd, isNewRow);\n                return;\n            }\n\n            stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow);\n            stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd);\n\n            // If the user requested to stop the walk or endRow/endColumn is\n            // inside of this fold (comp == 0), then end here.\n            if (stop || comp == 0) {\n                return;\n            }\n\n            // Note the new lastEnd might not be on the same line. However,\n            // it's the callback's job to recognize this.\n            isNewRow = !fold.sameRow;\n            lastEnd = fold.end.column;\n        }\n        callback(null, endRow, endColumn, lastEnd, isNewRow);\n    }\n\n    this.getNextFoldTo = function(row, column) {\n        var fold, cmp;\n        for (var i = 0; i < this.folds.length; i++) {\n            fold = this.folds[i];\n            cmp = fold.range.compareEnd(row, column);\n            if (cmp == -1) {\n                return {\n                    fold: fold,\n                    kind: \"after\"\n                };\n            } else if (cmp == 0) {\n                return {\n                    fold: fold,\n                    kind: \"inside\"\n                }\n            }\n        }\n        return null;\n    }\n\n    this.addRemoveChars = function(row, column, len) {\n        var ret = this.getNextFoldTo(row, column),\n            fold, folds;\n        if (ret) {\n            fold = ret.fold;\n            if (ret.kind == \"inside\"\n                && fold.start.column != column\n                && fold.start.row != row)\n            {\n                throw \"Moving characters inside of a fold should never be reached\";\n            } else if (fold.start.row == row) {\n                folds = this.folds;\n                var i = folds.indexOf(fold);\n                if (i == 0) {\n                    this.start.column += len;\n                }\n                for (i; i < folds.length; i++) {\n                    fold = folds[i];\n                    fold.start.column += len;\n                    if (!fold.sameRow) {\n                        return;\n                    }\n                    fold.end.column += len;\n                }\n                this.end.column += len;\n            }\n        }\n    }\n\n    this.split = function(row, column) {\n        var fold = this.getNextFoldTo(row, column).fold,\n            folds = this.folds;\n        var foldData = this.foldData;\n\n        if (!fold) {\n            return null;\n        }\n        var i = folds.indexOf(fold);\n        var foldBefore = folds[i - 1];\n        this.end.row = foldBefore.end.row;\n        this.end.column = foldBefore.end.column;\n\n        // Remove the folds after row/column and create a new FoldLine\n        // containing these removed folds.\n        folds = folds.splice(i, folds.length - i);\n\n        var newFoldLine = new FoldLine(foldData, folds);\n        foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine);\n        return newFoldLine;\n    }\n\n    this.merge = function(foldLineNext) {\n        var folds = foldLineNext.folds;\n        for (var i = 0; i < folds.length; i++) {\n            this.addFold(folds[i]);\n        }\n        // Remove the foldLineNext - no longer needed, as\n        // it's merged now with foldLineNext.\n        var foldData = this.foldData;\n        foldData.splice(foldData.indexOf(foldLineNext), 1);\n    }\n\n    this.toString = function() {\n        var ret = [this.range.toString() + \": [\" ];\n\n        this.folds.forEach(function(fold) {\n            ret.push(\"  \" + fold.toString());\n        });\n        ret.push(\"]\")\n        return ret.join(\"\\n\");\n    }\n\n    this.idxToPosition = function(idx) {\n        var lastFoldEndColumn = 0;\n        var fold;\n\n        for (var i = 0; i < this.folds.length; i++) {\n            var fold = this.folds[i];\n\n            idx -= fold.start.column - lastFoldEndColumn;\n            if (idx < 0) {\n                return {\n                    row: fold.start.row,\n                    column: fold.start.column + idx\n                };\n            }\n\n            idx -= fold.placeholder.length;\n            if (idx < 0) {\n                return fold.start;\n            }\n\n            lastFoldEndColumn = fold.end.column;\n        }\n\n        return {\n            row: this.end.row,\n            column: this.end.column + idx\n        };\n    }\n}).call(FoldLine.prototype);\n\nexports.FoldLine = FoldLine;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/edit_session/folding.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Julian Viereck <julian DOT viereck AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Range = require(\"../range\").Range;\nvar FoldLine = require(\"./fold_line\").FoldLine;\nvar Fold = require(\"./fold\").Fold;\nvar TokenIterator = require(\"../token_iterator\").TokenIterator;\n\nfunction Folding() {\n    /**\n     * Looks up a fold at a given row/column. Possible values for side:\n     *   -1: ignore a fold if fold.start = row/column\n     *   +1: ignore a fold if fold.end = row/column\n     */\n    this.getFoldAt = function(row, column, side) {\n        var foldLine = this.getFoldLine(row);\n        if (!foldLine)\n            return null;\n\n        var folds = foldLine.folds;\n        for (var i = 0; i < folds.length; i++) {\n            var fold = folds[i];\n            if (fold.range.contains(row, column)) {\n                if (side == 1 && fold.range.isEnd(row, column)) {\n                    continue;\n                } else if (side == -1 && fold.range.isStart(row, column)) {\n                    continue;\n                }\n                return fold;\n            }\n        }\n    };\n\n    /**\n     * Returns all folds in the given range. Note, that this will return folds\n     *\n     */\n    this.getFoldsInRange = function(range) {\n        range = range.clone();\n        var start = range.start;\n        var end = range.end;\n        var foldLines = this.$foldData;\n        var foundFolds = [];\n\n        start.column += 1;\n        end.column -= 1;\n\n        for (var i = 0; i < foldLines.length; i++) {\n            var cmp = foldLines[i].range.compareRange(range);\n            if (cmp == 2) {\n                // Range is before foldLine. No intersection. This means,\n                // there might be other foldLines that intersect.\n                continue;\n            }\n            else if (cmp == -2) {\n                // Range is after foldLine. There can't be any other foldLines then,\n                // so let's give up.\n                break;\n            }\n\n            var folds = foldLines[i].folds;\n            for (var j = 0; j < folds.length; j++) {\n                var fold = folds[j];\n                cmp = fold.range.compareRange(range);\n                if (cmp == -2) {\n                    break;\n                } else if (cmp == 2) {\n                    continue;\n                } else\n                // WTF-state: Can happen due to -1/+1 to start/end column.\n                if (cmp == 42) {\n                    break;\n                }\n                foundFolds.push(fold);\n            }\n        }\n        return foundFolds;\n    };\n    \n    /**\n     * Returns all folds in the document\n     */\n    this.getAllFolds = function() {\n        var folds = [];\n        var foldLines = this.$foldData;\n        \n        function addFold(fold) {\n            folds.push(fold);\n            if (!fold.subFolds)\n                return;\n                \n            for (var i = 0; i < fold.subFolds.length; i++)\n                addFold(fold.subFolds[i]);\n        }\n        \n        for (var i = 0; i < foldLines.length; i++)\n            for (var j = 0; j < foldLines[i].folds.length; j++)\n                addFold(foldLines[i].folds[j]);\n\n        return folds;\n    };\n\n    /**\n     * Returns the string between folds at the given position.\n     * E.g.\n     *  foo<fold>b|ar<fold>wolrd -> \"bar\"\n     *  foo<fold>bar<fold>wol|rd -> \"world\"\n     *  foo<fold>bar<fo|ld>wolrd -> <null>\n     *\n     * where | means the position of row/column\n     *\n     * The trim option determs if the return string should be trimed according\n     * to the \"side\" passed with the trim value:\n     *\n     * E.g.\n     *  foo<fold>b|ar<fold>wolrd -trim=-1> \"b\"\n     *  foo<fold>bar<fold>wol|rd -trim=+1> \"rld\"\n     *  fo|o<fold>bar<fold>wolrd -trim=00> \"foo\"\n     */\n    this.getFoldStringAt = function(row, column, trim, foldLine) {\n        foldLine = foldLine || this.getFoldLine(row);\n        if (!foldLine)\n            return null;\n\n        var lastFold = {\n            end: { column: 0 }\n        };\n        // TODO: Refactor to use getNextFoldTo function.\n        var str, fold;\n        for (var i = 0; i < foldLine.folds.length; i++) {\n            fold = foldLine.folds[i];\n            var cmp = fold.range.compareEnd(row, column);\n            if (cmp == -1) {\n                str = this\n                    .getLine(fold.start.row)\n                    .substring(lastFold.end.column, fold.start.column);\n                break;\n            }\n            else if (cmp === 0) {\n                return null;\n            }\n            lastFold = fold;\n        }\n        if (!str)\n            str = this.getLine(fold.start.row).substring(lastFold.end.column);\n\n        if (trim == -1)\n            return str.substring(0, column - lastFold.end.column);\n        else if (trim == 1)\n            return str.substring(column - lastFold.end.column);\n        else\n            return str;\n    };\n\n    this.getFoldLine = function(docRow, startFoldLine) {\n        var foldData = this.$foldData;\n        var i = 0;\n        if (startFoldLine)\n            i = foldData.indexOf(startFoldLine);\n        if (i == -1)\n            i = 0;\n        for (i; i < foldData.length; i++) {\n            var foldLine = foldData[i];\n            if (foldLine.start.row <= docRow && foldLine.end.row >= docRow) {\n                return foldLine;\n            } else if (foldLine.end.row > docRow) {\n                return null;\n            }\n        }\n        return null;\n    };\n\n    // returns the fold which starts after or contains docRow\n    this.getNextFoldLine = function(docRow, startFoldLine) {\n        var foldData = this.$foldData;\n        var i = 0;\n        if (startFoldLine)\n            i = foldData.indexOf(startFoldLine);\n        if (i == -1)\n            i = 0;\n        for (i; i < foldData.length; i++) {\n            var foldLine = foldData[i];\n            if (foldLine.end.row >= docRow) {\n                return foldLine;\n            }\n        }\n        return null;\n    };\n\n    this.getFoldedRowCount = function(first, last) {\n        var foldData = this.$foldData, rowCount = last-first+1;\n        for (var i = 0; i < foldData.length; i++) {\n            var foldLine = foldData[i],\n                end = foldLine.end.row,\n                start = foldLine.start.row;\n            if (end >= last) {\n                if(start < last) {\n                    if(start >= first)\n                        rowCount -= last-start;\n                    else\n                        rowCount = 0;//in one fold\n                }\n                break;\n            } else if(end >= first){\n                if (start >= first) //fold inside range\n                    rowCount -=  end-start;\n                else\n                    rowCount -=  end-first+1;\n            }\n        }\n        return rowCount;\n    };\n\n    this.$addFoldLine = function(foldLine) {\n        this.$foldData.push(foldLine);\n        this.$foldData.sort(function(a, b) {\n            return a.start.row - b.start.row;\n        });\n        return foldLine;\n    };\n\n    /**\n     * Adds a new fold.\n     *\n     * @returns\n     *      The new created Fold object or an existing fold object in case the\n     *      passed in range fits an existing fold exactly.\n     */\n    this.addFold = function(placeholder, range) {\n        var foldData = this.$foldData;\n        var added = false;\n        var fold;\n        \n        if (placeholder instanceof Fold)\n            fold = placeholder;\n        else\n            fold = new Fold(range, placeholder);\n\n        this.$clipRangeToDocument(fold.range);\n\n        var startRow = fold.start.row;\n        var startColumn = fold.start.column;\n        var endRow = fold.end.row;\n        var endColumn = fold.end.column;\n\n        // --- Some checking ---\n        if (fold.placeholder.length < 2)\n            throw \"Placeholder has to be at least 2 characters\";\n\n        if (startRow == endRow && endColumn - startColumn < 2)\n            throw \"The range has to be at least 2 characters width\";\n\n        var startFold = this.getFoldAt(startRow, startColumn, 1);\n        var endFold = this.getFoldAt(endRow, endColumn, -1);\n        if (startFold && endFold == startFold)\n            return startFold.addSubFold(fold);\n\n        if (\n            (startFold && !startFold.range.isStart(startRow, startColumn))\n            || (endFold && !endFold.range.isEnd(endRow, endColumn))\n        ) {\n            throw \"A fold can't intersect already existing fold\" + fold.range + startFold.range;\n        }\n\n        // Check if there are folds in the range we create the new fold for.\n        var folds = this.getFoldsInRange(fold.range);\n        if (folds.length > 0) {\n            // Remove the folds from fold data.\n            this.removeFolds(folds);\n            // Add the removed folds as subfolds on the new fold.\n            fold.subFolds = folds;\n        }\n\n        for (var i = 0; i < foldData.length; i++) {\n            var foldLine = foldData[i];\n            if (endRow == foldLine.start.row) {\n                foldLine.addFold(fold);\n                added = true;\n                break;\n            }\n            else if (startRow == foldLine.end.row) {\n                foldLine.addFold(fold);\n                added = true;\n                if (!fold.sameRow) {\n                    // Check if we might have to merge two FoldLines.\n                    var foldLineNext = foldData[i + 1];\n                    if (foldLineNext && foldLineNext.start.row == endRow) {\n                        // We need to merge!\n                        foldLine.merge(foldLineNext);\n                        break;\n                    }\n                }\n                break;\n            }\n            else if (endRow <= foldLine.start.row) {\n                break;\n            }\n        }\n\n        if (!added)\n            foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold));\n\n        if (this.$useWrapMode)\n            this.$updateWrapData(foldLine.start.row, foldLine.start.row);\n\n        // Notify that fold data has changed.\n        this.$modified = true;\n        this._emit(\"changeFold\", { data: fold });\n\n        return fold;\n    };\n\n    this.addFolds = function(folds) {\n        folds.forEach(function(fold) {\n            this.addFold(fold);\n        }, this);\n    };\n\n    this.removeFold = function(fold) {\n        var foldLine = fold.foldLine;\n        var startRow = foldLine.start.row;\n        var endRow = foldLine.end.row;\n\n        var foldLines = this.$foldData;\n        var folds = foldLine.folds;\n        // Simple case where there is only one fold in the FoldLine such that\n        // the entire fold line can get removed directly.\n        if (folds.length == 1) {\n            foldLines.splice(foldLines.indexOf(foldLine), 1);\n        } else\n        // If the fold is the last fold of the foldLine, just remove it.\n        if (foldLine.range.isEnd(fold.end.row, fold.end.column)) {\n            folds.pop();\n            foldLine.end.row = folds[folds.length - 1].end.row;\n            foldLine.end.column = folds[folds.length - 1].end.column;\n        } else\n        // If the fold is the first fold of the foldLine, just remove it.\n        if (foldLine.range.isStart(fold.start.row, fold.start.column)) {\n            folds.shift();\n            foldLine.start.row = folds[0].start.row;\n            foldLine.start.column = folds[0].start.column;\n        } else\n        // We know there are more then 2 folds and the fold is not at the edge.\n        // This means, the fold is somewhere in between.\n        //\n        // If the fold is in one row, we just can remove it.\n        if (fold.sameRow) {\n            folds.splice(folds.indexOf(fold), 1);\n        } else\n        // The fold goes over more then one row. This means remvoing this fold\n        // will cause the fold line to get splitted up. newFoldLine is the second part\n        {\n            var newFoldLine = foldLine.split(fold.start.row, fold.start.column);\n            folds = newFoldLine.folds;\n            folds.shift();\n            newFoldLine.start.row = folds[0].start.row;\n            newFoldLine.start.column = folds[0].start.column;\n        }\n\n        if (this.$useWrapMode) {\n            this.$updateWrapData(startRow, endRow);\n        }\n\n        // Notify that fold data has changed.\n        this.$modified = true;\n        this._emit(\"changeFold\", { data: fold });\n    };\n\n    this.removeFolds = function(folds) {\n        // We need to clone the folds array passed in as it might be the folds\n        // array of a fold line and as we call this.removeFold(fold), folds\n        // are removed from folds and changes the current index.\n        var cloneFolds = [];\n        for (var i = 0; i < folds.length; i++) {\n            cloneFolds.push(folds[i]);\n        }\n\n        cloneFolds.forEach(function(fold) {\n            this.removeFold(fold);\n        }, this);\n        this.$modified = true;\n    };\n\n    this.expandFold = function(fold) {\n        this.removeFold(fold);\n        fold.subFolds.forEach(function(fold) {\n            this.addFold(fold);\n        }, this);\n        fold.subFolds = [];\n    };\n\n    this.expandFolds = function(folds) {\n        folds.forEach(function(fold) {\n            this.expandFold(fold);\n        }, this);\n    };\n\n    this.unfold = function(location, expandInner) {\n        var range, folds;\n        if (location == null)\n            range = new Range(0, 0, this.getLength(), 0);\n        else if (typeof location == \"number\")\n            range = new Range(location, 0, location, this.getLine(location).length);\n        else if (\"row\" in location)\n            range = Range.fromPoints(location, location);\n        else\n            range = location;\n\n        folds = this.getFoldsInRange(range);\n        if (expandInner) {\n            this.removeFolds(folds);\n        } else {\n            // TODO: might need to remove and add folds in one go instead of using\n            // expandFolds several times.\n            while (folds.length) {\n                this.expandFolds(folds);\n                folds = this.getFoldsInRange(range);\n            }\n        }\n    };\n\n    /**\n     * Checks if a given documentRow is folded. This is true if there are some\n     * folded parts such that some parts of the line is still visible.\n     **/\n    this.isRowFolded = function(docRow, startFoldRow) {\n        return !!this.getFoldLine(docRow, startFoldRow);\n    };\n\n    this.getRowFoldEnd = function(docRow, startFoldRow) {\n        var foldLine = this.getFoldLine(docRow, startFoldRow);\n        return (foldLine\n            ? foldLine.end.row\n            : docRow);\n    };\n\n    this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) {\n        if (startRow == null) {\n            startRow = foldLine.start.row;\n            startColumn = 0;\n        }\n\n        if (endRow == null) {\n            endRow = foldLine.end.row;\n            endColumn = this.getLine(endRow).length;\n        }\n\n        // Build the textline using the FoldLine walker.\n        var doc = this.doc;\n        var textLine = \"\";\n\n        foldLine.walk(function(placeholder, row, column, lastColumn) {\n            if (row < startRow) {\n                return;\n            } else if (row == startRow) {\n                if (column < startColumn) {\n                    return;\n                }\n                lastColumn = Math.max(startColumn, lastColumn);\n            }\n            if (placeholder) {\n                textLine += placeholder;\n            } else {\n                textLine += doc.getLine(row).substring(lastColumn, column);\n            }\n        }.bind(this), endRow, endColumn);\n        return textLine;\n    };\n\n    this.getDisplayLine = function(row, endColumn, startRow, startColumn) {\n        var foldLine = this.getFoldLine(row);\n\n        if (!foldLine) {\n            var line;\n            line = this.doc.getLine(row);\n            return line.substring(startColumn || 0, endColumn || line.length);\n        } else {\n            return this.getFoldDisplayLine(\n                foldLine, row, endColumn, startRow, startColumn);\n        }\n    };\n\n    this.$cloneFoldData = function() {\n        var fd = [];\n        fd = this.$foldData.map(function(foldLine) {\n            var folds = foldLine.folds.map(function(fold) {\n                return fold.clone();\n            });\n            return new FoldLine(fd, folds);\n        });\n\n        return fd;\n    };\n\n    this.toggleFold = function(tryToUnfold) {\n        var selection = this.selection;\n        var range = selection.getRange();\n        var fold;\n        var bracketPos;\n\n        if (range.isEmpty()) {\n            var cursor = range.start;\n            fold = this.getFoldAt(cursor.row, cursor.column);\n\n            if (fold) {\n                this.expandFold(fold);\n                return;\n            }\n            else if (bracketPos = this.findMatchingBracket(cursor)) {\n                if (range.comparePoint(bracketPos) == 1) {\n                    range.end = bracketPos;\n                } \n                else {\n                    range.start = bracketPos;\n                    range.start.column++;\n                    range.end.column--;\n                }\n            }\n            else if (bracketPos = this.findMatchingBracket({row: cursor.row, column: cursor.column + 1})) {\n                if (range.comparePoint(bracketPos) == 1)\n                    range.end = bracketPos;\n                else\n                    range.start = bracketPos;\n\n                range.start.column++;\n            }\n            else {\n                range = this.getCommentFoldRange(cursor.row, cursor.column) || range;\n            }\n        } else {\n            var folds = this.getFoldsInRange(range);\n            if (tryToUnfold && folds.length) {\n                this.expandFolds(folds);\n                return;\n            } \n            else if (folds.length == 1 ) {\n                fold = folds[0];\n            }\n        }\n\n        if (!fold)\n            fold = this.getFoldAt(range.start.row, range.start.column);\n\n        if (fold && fold.range.toString() == range.toString()) {\n            this.expandFold(fold);\n            return;\n        }\n\n        var placeholder = \"...\";\n        if (!range.isMultiLine()) {\n            placeholder = this.getTextRange(range);\n            if(placeholder.length < 4)\n                return;\n            placeholder = placeholder.trim().substring(0, 2) + \"..\";\n        }\n\n        this.addFold(placeholder, range);\n    };\n\n    this.getCommentFoldRange = function(row, column) {\n        var iterator = new TokenIterator(this, row, column);\n        var token = iterator.getCurrentToken();\n        if (token && /^comment|string/.test(token.type)) {\n            var range = new Range();\n            var re = new RegExp(token.type.replace(/\\..*/, \"\\\\.\"));\n            do {\n                token = iterator.stepBackward();\n            } while(token && re.test(token.type));\n\n            iterator.stepForward();\n            range.start.row = iterator.getCurrentTokenRow();\n            range.start.column = iterator.getCurrentTokenColumn() + 2;\n\n            iterator = new TokenIterator(this, row, column);\n\n            do {\n                token = iterator.stepForward();\n            } while(token && re.test(token.type));\n            \n            token = iterator.stepBackward();\n\n            range.end.row = iterator.getCurrentTokenRow();\n            range.end.column = iterator.getCurrentTokenColumn() + token.value.length;\n            return range;\n        }\n    };\n\n    this.foldAll = function(startRow, endRow) {\n        var foldWidgets = this.foldWidgets;\n        endRow = endRow || this.getLength();\n        for (var row = startRow || 0; row < endRow; row++) {\n            if (foldWidgets[row] == null)\n                foldWidgets[row] = this.getFoldWidget(row);\n            if (foldWidgets[row] != \"start\")\n                continue;\n\n            var range = this.getFoldWidgetRange(row);\n            // sometimes range can be incompatible with existing fold\n            // wouldn't it be better for addFold to return null istead of throwing?\n            if (range && range.end.row < endRow) try {\n                this.addFold(\"...\", range);\n            } catch(e) {}\n        }\n    };\n    \n    this.$foldStyles = {\n        \"manual\": 1,\n        \"markbegin\": 1,\n        \"markbeginend\": 1\n    };\n    this.$foldStyle = \"markbegin\";\n    this.setFoldStyle = function(style) {\n        if (!this.$foldStyles[style])\n            throw new Error(\"invalid fold style: \" + style + \"[\" + Object.keys(this.$foldStyles).join(\", \") + \"]\");\n        \n        if (this.$foldStyle == style)\n            return;\n\n        this.$foldStyle = style;\n        \n        if (style == \"manual\")\n            this.unfold();\n        \n        // reset folding\n        var mode = this.$foldMode;\n        this.$setFolding(null);\n        this.$setFolding(mode);\n    };\n\n    // structured folding\n    this.$setFolding = function(foldMode) {\n        if (this.$foldMode == foldMode)\n            return;\n            \n        this.$foldMode = foldMode;\n        \n        this.removeListener('change', this.$updateFoldWidgets);\n        this._emit(\"changeAnnotation\");\n        \n        if (!foldMode || this.$foldStyle == \"manual\") {\n            this.foldWidgets = null;\n            return;\n        }\n        \n        this.foldWidgets = [];\n        this.getFoldWidget = foldMode.getFoldWidget.bind(foldMode, this, this.$foldStyle);\n        this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle);\n        \n        this.$updateFoldWidgets = this.updateFoldWidgets.bind(this);\n        this.on('change', this.$updateFoldWidgets);\n        \n    };\n\n    this.onFoldWidgetClick = function(row, e) {\n        var type = this.getFoldWidget(row);\n        var line = this.getLine(row);\n        var onlySubfolds = e.shiftKey;\n        var addSubfolds = onlySubfolds || e.ctrlKey || e.altKey || e.metaKey;\n        var fold;\n\n        if (type == \"end\")\n            fold = this.getFoldAt(row, 0, -1);\n        else\n            fold = this.getFoldAt(row, line.length, 1);\n\n        if (fold) {\n            if (addSubfolds)\n                this.removeFold(fold);\n            else\n                this.expandFold(fold);\n            return;\n        }\n\n        var range = this.getFoldWidgetRange(row);\n        if (range) {\n            // sometimes singleline folds can be missed by the code above\n            if (!range.isMultiLine()) {\n                fold = this.getFoldAt(range.start.row, range.start.column, 1);\n                if (fold && range.isEqual(fold.range)) {\n                    this.removeFold(fold);\n                    return;\n                }\n            }\n            \n            if (!onlySubfolds)\n                this.addFold(\"...\", range);\n\n            if (addSubfolds)\n                this.foldAll(range.start.row + 1, range.end.row);\n        } else {\n            if (addSubfolds)\n                this.foldAll(row + 1, this.getLength());\n            e.target.className += \" invalid\"\n        }\n    };\n    \n    this.updateFoldWidgets = function(e) {\n        var delta = e.data;\n        var range = delta.range;\n        var firstRow = range.start.row;\n        var len = range.end.row - firstRow;\n\n        if (len === 0) {\n            this.foldWidgets[firstRow] = null;\n        } else if (delta.action == \"removeText\" || delta.action == \"removeLines\") {\n            this.foldWidgets.splice(firstRow, len + 1, null);\n        } else {\n            var args = Array(len + 1);\n            args.unshift(firstRow, 1);\n            this.foldWidgets.splice.apply(this.foldWidgets, args);\n        }\n    };\n\n}\n\nexports.Folding = Folding;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/edit_session.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Mihai Sucan <mihai DOT sucan AT gmail DOT com>\n *      Julian Viereck <julian DOT viereck AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar config = require(\"./config\");\nvar oop = require(\"./lib/oop\");\nvar lang = require(\"./lib/lang\");\nvar net = require(\"./lib/net\");\nvar EventEmitter = require(\"./lib/event_emitter\").EventEmitter;\nvar Selection = require(\"./selection\").Selection;\nvar TextMode = require(\"./mode/text\").Mode;\nvar Range = require(\"./range\").Range;\nvar Document = require(\"./document\").Document;\nvar BackgroundTokenizer = require(\"./background_tokenizer\").BackgroundTokenizer;\n\nvar EditSession = function(text, mode) {\n    this.$modified = true;\n    this.$breakpoints = [];\n    this.$frontMarkers = {};\n    this.$backMarkers = {};\n    this.$markerId = 1;\n    this.$rowCache = [];\n    this.$wrapData = [];\n    this.$foldData = [];\n    this.$undoSelect = true;\n    this.$foldData.toString = function() {\n        var str = \"\";\n        this.forEach(function(foldLine) {\n            str += \"\\n\" + foldLine.toString();\n        });\n        return str;\n    }\n\n    if (text instanceof Document) {\n        this.setDocument(text);\n    } else {\n        this.setDocument(new Document(text));\n    }\n\n    this.selection = new Selection(this);\n    if (mode)\n        this.setMode(mode);\n    else\n        this.setMode(new TextMode());\n};\n\n\n(function() {\n\n    oop.implement(this, EventEmitter);\n\n    this.setDocument = function(doc) {\n        if (this.doc)\n            throw new Error(\"Document is already set\");\n\n        this.doc = doc;\n        doc.on(\"change\", this.onChange.bind(this));\n        this.on(\"changeFold\", this.onChangeFold.bind(this));\n\n        if (this.bgTokenizer) {\n            this.bgTokenizer.setDocument(this.getDocument());\n            this.bgTokenizer.start(0);\n        }\n    };\n\n    this.getDocument = function() {\n        return this.doc;\n    };\n\n    this.$resetRowCache = function(row) {\n        if (row == 0) {\n            this.$rowCache = [];\n            return;\n        }\n        var rowCache = this.$rowCache;\n        for (var i = 0; i < rowCache.length; i++) {\n            if (rowCache[i].docRow >= row) {\n                rowCache.splice(i, rowCache.length);\n                return;\n            }\n        }\n    };\n\n    this.onChangeFold = function(e) {\n        var fold = e.data;\n        this.$resetRowCache(fold.start.row);\n    };\n\n    this.onChange = function(e) {\n        var delta = e.data;\n        this.$modified = true;\n\n        this.$resetRowCache(delta.range.start.row);\n\n        var removedFolds = this.$updateInternalDataOnChange(e);\n        if (!this.$fromUndo && this.$undoManager && !delta.ignore) {\n            this.$deltasDoc.push(delta);\n            if (removedFolds && removedFolds.length != 0) {\n                this.$deltasFold.push({\n                    action: \"removeFolds\",\n                    folds:  removedFolds\n                });\n            }\n\n            this.$informUndoManager.schedule();\n        }\n\n        this.bgTokenizer.start(delta.range.start.row);\n        this._emit(\"change\", e);\n    };\n\n    this.setValue = function(text) {\n        this.doc.setValue(text);\n        this.selection.moveCursorTo(0, 0);\n        this.selection.clearSelection();\n\n        this.$resetRowCache(0);\n        this.$deltas = [];\n        this.$deltasDoc = [];\n        this.$deltasFold = [];\n        this.getUndoManager().reset();\n    };\n\n    this.getValue =\n    this.toString = function() {\n        return this.doc.getValue();\n    };\n\n    this.getSelection = function() {\n        return this.selection;\n    };\n\n    this.getState = function(row) {\n        return this.bgTokenizer.getState(row);\n    };\n\n    this.getTokens = function(firstRow, lastRow) {\n        return this.bgTokenizer.getTokens(firstRow, lastRow);\n    };\n\n    this.getTokenAt = function(row, column) {\n        var tokens = this.bgTokenizer.getTokens(row, row)[0].tokens;\n        var token, c = 0;\n        if (column == null) {\n            i = tokens.length - 1;\n            c = this.getLine(row).length;\n        } else {\n            for (var i = 0; i < tokens.length; i++) {\n                c += tokens[i].value.length;\n                if (c >= column)\n                    break;\n            }\n        }\n        token = tokens[i];\n        if (!token)\n            return null;\n        token.index = i;\n        token.start = c - token.value.length;\n        return token;\n    };\n\n    this.setUndoManager = function(undoManager) {\n        this.$undoManager = undoManager;\n        this.$resetRowCache(0);\n        this.$deltas = [];\n        this.$deltasDoc = [];\n        this.$deltasFold = [];\n\n        if (this.$informUndoManager)\n            this.$informUndoManager.cancel();\n\n        if (undoManager) {\n            var self = this;\n            this.$syncInformUndoManager = function() {\n                self.$informUndoManager.cancel();\n\n                if (self.$deltasFold.length) {\n                    self.$deltas.push({\n                        group: \"fold\",\n                        deltas: self.$deltasFold\n                    });\n                    self.$deltasFold = [];\n                }\n\n                if (self.$deltasDoc.length) {\n                    self.$deltas.push({\n                        group: \"doc\",\n                        deltas: self.$deltasDoc\n                    });\n                    self.$deltasDoc = [];\n                }\n\n                if (self.$deltas.length > 0) {\n                    undoManager.execute({\n                        action: \"aceupdate\",\n                        args: [self.$deltas, self]\n                    });\n                }\n\n                self.$deltas = [];\n            }\n            this.$informUndoManager =\n                lang.deferredCall(this.$syncInformUndoManager);\n        }\n    };\n\n    this.$defaultUndoManager = {\n        undo: function() {},\n        redo: function() {},\n        reset: function() {}\n    };\n\n    this.getUndoManager = function() {\n        return this.$undoManager || this.$defaultUndoManager;\n    },\n\n    this.getTabString = function() {\n        if (this.getUseSoftTabs()) {\n            return lang.stringRepeat(\" \", this.getTabSize());\n        } else {\n            return \"\\t\";\n        }\n    };\n\n    this.$useSoftTabs = true;\n    this.setUseSoftTabs = function(useSoftTabs) {\n        if (this.$useSoftTabs === useSoftTabs) return;\n\n        this.$useSoftTabs = useSoftTabs;\n    };\n\n    this.getUseSoftTabs = function() {\n        return this.$useSoftTabs;\n    };\n\n    this.$tabSize = 4;\n    this.setTabSize = function(tabSize) {\n        if (isNaN(tabSize) || this.$tabSize === tabSize) return;\n\n        this.$modified = true;\n        this.$tabSize = tabSize;\n        this._emit(\"changeTabSize\");\n    };\n\n    this.getTabSize = function() {\n        return this.$tabSize;\n    };\n\n    this.isTabStop = function(position) {\n        return this.$useSoftTabs && (position.column % this.$tabSize == 0);\n    };\n\n    this.$overwrite = false;\n    this.setOverwrite = function(overwrite) {\n        if (this.$overwrite == overwrite) return;\n\n        this.$overwrite = overwrite;\n        this._emit(\"changeOverwrite\");\n    };\n\n    this.getOverwrite = function() {\n        return this.$overwrite;\n    };\n\n    this.toggleOverwrite = function() {\n        this.setOverwrite(!this.$overwrite);\n    };\n\n    this.getBreakpoints = function() {\n        return this.$breakpoints;\n    };\n\n    this.setBreakpoints = function(rows) {\n        this.$breakpoints = [];\n        for (var i=0; i<rows.length; i++) {\n            this.$breakpoints[rows[i]] = true;\n        }\n        this._emit(\"changeBreakpoint\", {});\n    };\n\n    this.clearBreakpoints = function() {\n        this.$breakpoints = [];\n        this._emit(\"changeBreakpoint\", {});\n    };\n\n    this.setBreakpoint = function(row) {\n        this.$breakpoints[row] = true;\n        this._emit(\"changeBreakpoint\", {});\n    };\n\n    this.clearBreakpoint = function(row) {\n        delete this.$breakpoints[row];\n        this._emit(\"changeBreakpoint\", {});\n    };\n\n    this.getBreakpoints = function() {\n        return this.$breakpoints;\n    };\n\n    this.addMarker = function(range, clazz, type, inFront) {\n        var id = this.$markerId++;\n\n        var marker = {\n            range : range,\n            type : type || \"line\",\n            renderer: typeof type == \"function\" ? type : null,\n            clazz : clazz,\n            inFront: !!inFront\n        }\n\n        if (inFront) {\n            this.$frontMarkers[id] = marker;\n            this._emit(\"changeFrontMarker\")\n        } else {\n            this.$backMarkers[id] = marker;\n            this._emit(\"changeBackMarker\")\n        }\n\n        return id;\n    };\n\n    this.removeMarker = function(markerId) {\n        var marker = this.$frontMarkers[markerId] || this.$backMarkers[markerId];\n        if (!marker)\n            return;\n\n        var markers = marker.inFront ? this.$frontMarkers : this.$backMarkers;\n        if (marker) {\n            delete (markers[markerId]);\n            this._emit(marker.inFront ? \"changeFrontMarker\" : \"changeBackMarker\");\n        }\n    };\n\n    this.getMarkers = function(inFront) {\n        return inFront ? this.$frontMarkers : this.$backMarkers;\n    };\n\n    /**\n     * Error:\n     *  {\n     *    row: 12,\n     *    column: 2, //can be undefined\n     *    text: \"Missing argument\",\n     *    type: \"error\" // or \"warning\" or \"info\"\n     *  }\n     */\n    this.setAnnotations = function(annotations) {\n        this.$annotations = {};\n        for (var i=0; i<annotations.length; i++) {\n            var annotation = annotations[i];\n            var row = annotation.row;\n            if (this.$annotations[row])\n                this.$annotations[row].push(annotation);\n            else\n                this.$annotations[row] = [annotation];\n        }\n        this._emit(\"changeAnnotation\", {});\n    };\n\n    this.getAnnotations = function() {\n        return this.$annotations || {};\n    };\n\n    this.clearAnnotations = function() {\n        this.$annotations = {};\n        this._emit(\"changeAnnotation\", {});\n    };\n\n    this.$detectNewLine = function(text) {\n        var match = text.match(/^.*?(\\r?\\n)/m);\n        if (match) {\n            this.$autoNewLine = match[1];\n        } else {\n            this.$autoNewLine = \"\\n\";\n        }\n    };\n\n    this.getWordRange = function(row, column) {\n        var line = this.getLine(row);\n\n        var inToken = false;\n        if (column > 0) {\n            inToken = !!line.charAt(column - 1).match(this.tokenRe);\n        }\n\n        if (!inToken) {\n            inToken = !!line.charAt(column).match(this.tokenRe);\n        }\n\n        var re = inToken ? this.tokenRe : this.nonTokenRe;\n\n        var start = column;\n        if (start > 0) {\n            do {\n                start--;\n            }\n            while (start >= 0 && line.charAt(start).match(re));\n            start++;\n        }\n\n        var end = column;\n        while (end < line.length && line.charAt(end).match(re)) {\n            end++;\n        }\n\n        return new Range(row, start, row, end);\n    };\n\n    // Gets the range of a word including its right whitespace\n    this.getAWordRange = function(row, column) {\n        var wordRange = this.getWordRange(row, column);\n        var line = this.getLine(wordRange.end.row);\n\n        while (line.charAt(wordRange.end.column).match(/[ \\t]/)) {\n            wordRange.end.column += 1;\n        }\n        return wordRange;\n    };\n\n    this.setNewLineMode = function(newLineMode) {\n        this.doc.setNewLineMode(newLineMode);\n    };\n\n    this.getNewLineMode = function() {\n        return this.doc.getNewLineMode();\n    };\n\n    this.$useWorker = true;\n    this.setUseWorker = function(useWorker) {\n        if (this.$useWorker == useWorker)\n            return;\n\n        this.$useWorker = useWorker;\n\n        this.$stopWorker();\n        if (useWorker)\n            this.$startWorker();\n    };\n\n    this.getUseWorker = function() {\n        return this.$useWorker;\n    };\n\n    this.onReloadTokenizer = function(e) {\n        var rows = e.data;\n        this.bgTokenizer.start(rows.first);\n        this._emit(\"tokenizerUpdate\", e);\n    };\n\n    this.$modes = {};\n    this._loadMode = function(mode, callback) {\n        if (this.$modes[mode])\n            return callback(this.$modes[mode]);\n        \n        var _self = this;\n        var module;\n        try {\n            module = require(mode);\n        } catch (e) {};\n        if (module)\n            return done(module);\n            \n        fetch(function() {\n            require([mode], done);\n        });\n        \n        function done(module) {\n            if (_self.$modes[mode])\n                return callback(_self.$modes[mode]);\n            \n            _self.$modes[mode] = new module.Mode();\n            _self._emit(\"loadmode\", {\n                name: mode,\n                mode: _self.$modes[mode]\n            });\n            callback(_self.$modes[mode]);\n        }\n\n        function fetch(callback) {\n            if (!config.get(\"packaged\"))\n                return callback();\n                \n            var base = mode.split(\"/\").pop();\n            var filename = config.get(\"modePath\") + \"/mode-\" + base + config.get(\"suffix\");\n            net.loadScript(filename, callback);\n        }\n    };\n\n    this.$mode = null;\n    this.$origMode = null;\n    this.setMode = function(mode) {\n        this.$origMode = mode;\n        \n        // load on demand\n        if (typeof mode === \"string\") {\n            var _self = this;\n            this._loadMode(mode, function(module) {\n                if (_self.$origMode !== mode)\n                    return;\n            \n                _self.setMode(module);\n            });\n            return;\n        }\n        \n        if (this.$mode === mode) return;\n        this.$mode = mode;\n        \n\n        this.$stopWorker();\n\n        if (this.$useWorker)\n            this.$startWorker();\n\n        var tokenizer = mode.getTokenizer();\n\n        if(tokenizer.addEventListener !== undefined) {\n            var onReloadTokenizer = this.onReloadTokenizer.bind(this);\n            tokenizer.addEventListener(\"update\", onReloadTokenizer);\n        }\n\n        if (!this.bgTokenizer) {\n            this.bgTokenizer = new BackgroundTokenizer(tokenizer);\n            var _self = this;\n            this.bgTokenizer.addEventListener(\"update\", function(e) {\n                _self._emit(\"tokenizerUpdate\", e);\n            });\n        } else {\n            this.bgTokenizer.setTokenizer(tokenizer);\n        }\n\n        this.bgTokenizer.setDocument(this.getDocument());\n        this.bgTokenizer.start(0);\n\n        this.tokenRe = mode.tokenRe;\n        this.nonTokenRe = mode.nonTokenRe;\n\n        this.$setFolding(mode.foldingRules);\n\n        this._emit(\"changeMode\");\n    };\n\n    this.$stopWorker = function() {\n        if (this.$worker)\n            this.$worker.terminate();\n\n        this.$worker = null;\n    };\n\n    this.$startWorker = function() {\n        if (typeof Worker !== \"undefined\" && !require.noWorker) {\n            try {\n                this.$worker = this.$mode.createWorker(this);\n            } catch (e) {\n                console.log(\"Could not load worker\");\n                console.log(e);\n                this.$worker = null;\n            }\n        }\n        else\n            this.$worker = null;\n    };\n\n    this.getMode = function() {\n        return this.$mode;\n    };\n    \n    this.$scrollTop = 0;\n    this.setScrollTop = function(scrollTop) {\n        scrollTop = Math.round(Math.max(0, scrollTop));\n        if (this.$scrollTop === scrollTop)\n            return;\n\n        this.$scrollTop = scrollTop;\n        this._emit(\"changeScrollTop\", scrollTop);\n    };\n\n    this.getScrollTop = function() {\n        return this.$scrollTop;\n    };\n    \n    this.$scrollLeft = 0;\n    this.setScrollLeft = function(scrollLeft) {\n        scrollLeft = Math.round(Math.max(0, scrollLeft));\n        if (this.$scrollLeft === scrollLeft)\n            return;\n\n        this.$scrollLeft = scrollLeft;\n        this._emit(\"changeScrollLeft\", scrollLeft);\n    };\n\n    this.getScrollLeft = function() {\n        return this.$scrollLeft;\n    };\n\n    this.getWidth = function() {\n        this.$computeWidth();\n        return this.width;\n    };\n\n    this.getScreenWidth = function() {\n        this.$computeWidth();\n        return this.screenWidth;\n    };\n\n    this.$computeWidth = function(force) {\n        if (this.$modified || force) {\n            this.$modified = false;\n\n            var lines = this.doc.getAllLines();\n            var longestLine = 0;\n            var longestScreenLine = 0;\n\n            for ( var i = 0; i < lines.length; i++) {\n                var foldLine = this.getFoldLine(i),\n                    line, len;\n\n                line = lines[i];\n                if (foldLine) {\n                    var end = foldLine.range.end;\n                    line = this.getFoldDisplayLine(foldLine);\n                    // Continue after the foldLine.end.row. All the lines in\n                    // between are folded.\n                    i = end.row;\n                }\n                len = line.length;\n                longestLine = Math.max(longestLine, len);\n                if (!this.$useWrapMode) {\n                    longestScreenLine = Math.max(\n                        longestScreenLine,\n                        this.$getStringScreenWidth(line)[0]\n                    );\n                }\n            }\n            this.width = longestLine;\n\n            if (this.$useWrapMode) {\n                this.screenWidth = this.$wrapLimit;\n            } else {\n                this.screenWidth = longestScreenLine;\n            }\n        }\n    };\n\n    /**\n     * Get a verbatim copy of the given line as it is in the document\n     */\n    this.getLine = function(row) {\n        return this.doc.getLine(row);\n    };\n\n    this.getLines = function(firstRow, lastRow) {\n        return this.doc.getLines(firstRow, lastRow);\n    };\n\n    this.getLength = function() {\n        return this.doc.getLength();\n    };\n\n    this.getTextRange = function(range) {\n        return this.doc.getTextRange(range);\n    };\n\n    this.insert = function(position, text) {\n        return this.doc.insert(position, text);\n    };\n\n    this.remove = function(range) {\n        return this.doc.remove(range);\n    };\n\n    this.undoChanges = function(deltas, dontSelect) {\n        if (!deltas.length)\n            return;\n\n        this.$fromUndo = true;\n        var lastUndoRange = null;\n        for (var i = deltas.length - 1; i != -1; i--) {\n            var delta = deltas[i];\n            if (delta.group == \"doc\") {\n                this.doc.revertDeltas(delta.deltas);\n                lastUndoRange =\n                    this.$getUndoSelection(delta.deltas, true, lastUndoRange);\n            } else {\n                delta.deltas.forEach(function(foldDelta) {\n                    this.addFolds(foldDelta.folds);\n                }, this);\n            }\n        }\n        this.$fromUndo = false;\n        lastUndoRange &&\n            this.$undoSelect &&\n            !dontSelect &&\n            this.selection.setSelectionRange(lastUndoRange);\n        return lastUndoRange;\n    };\n\n    this.redoChanges = function(deltas, dontSelect) {\n        if (!deltas.length)\n            return;\n\n        this.$fromUndo = true;\n        var lastUndoRange = null;\n        for (var i = 0; i < deltas.length; i++) {\n            var delta = deltas[i];\n            if (delta.group == \"doc\") {\n                this.doc.applyDeltas(delta.deltas);\n                lastUndoRange =\n                    this.$getUndoSelection(delta.deltas, false, lastUndoRange);\n            }\n        }\n        this.$fromUndo = false;\n        lastUndoRange &&\n            this.$undoSelect &&\n            !dontSelect &&\n            this.selection.setSelectionRange(lastUndoRange);\n        return lastUndoRange;\n    };\n    \n    this.setUndoSelect = function(enable) {\n        this.$undoSelect = enable;\n    };\n\n    this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) {\n        function isInsert(delta) {\n            var insert =\n                delta.action == \"insertText\" || delta.action == \"insertLines\";\n            return isUndo ? !insert : insert;\n        }\n\n        var delta = deltas[0];\n        var range, point;\n        var lastDeltaIsInsert = false;\n        if (isInsert(delta)) {\n            range = delta.range.clone();\n            lastDeltaIsInsert = true;\n        } else {\n            range = Range.fromPoints(delta.range.start, delta.range.start);\n            lastDeltaIsInsert = false;\n        }\n\n        for (var i = 1; i < deltas.length; i++) {\n            delta = deltas[i];\n            if (isInsert(delta)) {\n                point = delta.range.start;\n                if (range.compare(point.row, point.column) == -1) {\n                    range.setStart(delta.range.start);\n                }\n                point = delta.range.end;\n                if (range.compare(point.row, point.column) == 1) {\n                    range.setEnd(delta.range.end);\n                }\n                lastDeltaIsInsert = true;\n            } else {\n                point = delta.range.start;\n                if (range.compare(point.row, point.column) == -1) {\n                    range =\n                        Range.fromPoints(delta.range.start, delta.range.start);\n                }\n                lastDeltaIsInsert = false;\n            }\n        }\n\n        // Check if this range and the last undo range has something in common.\n        // If true, merge the ranges.\n        if (lastUndoRange != null) {\n            var cmp = lastUndoRange.compareRange(range);\n            if (cmp == 1) {\n                range.setStart(lastUndoRange.start);\n            } else if (cmp == -1) {\n                range.setEnd(lastUndoRange.end);\n            }\n        }\n\n        return range;\n    },\n\n    this.replace = function(range, text) {\n        return this.doc.replace(range, text);\n    };\n\n    /**\n     * Move a range of text from the given range to the given position.\n     *\n     * @param fromRange {Range} The range of text you want moved within the\n     * document.\n     * @param toPosition {Object} The location (row and column) where you want\n     * to move the text to.\n     * @return {Range} The new range where the text was moved to.\n     */\n    this.moveText = function(fromRange, toPosition) {\n        var text = this.getTextRange(fromRange);\n        this.remove(fromRange);\n\n        var toRow = toPosition.row;\n        var toColumn = toPosition.column;\n\n        // Make sure to update the insert location, when text is removed in\n        // front of the chosen point of insertion.\n        if (!fromRange.isMultiLine() && fromRange.start.row == toRow &&\n            fromRange.end.column < toColumn)\n            toColumn -= text.length;\n\n        if (fromRange.isMultiLine() && fromRange.end.row < toRow) {\n            var lines = this.doc.$split(text);\n            toRow -= lines.length - 1;\n        }\n\n        var endRow = toRow + fromRange.end.row - fromRange.start.row;\n        var endColumn = fromRange.isMultiLine() ?\n                        fromRange.end.column :\n                        toColumn + fromRange.end.column - fromRange.start.column;\n\n        var toRange = new Range(toRow, toColumn, endRow, endColumn);\n\n        this.insert(toRange.start, text);\n\n        return toRange;\n    };\n\n    this.indentRows = function(startRow, endRow, indentString) {\n        indentString = indentString.replace(/\\t/g, this.getTabString());\n        for (var row=startRow; row<=endRow; row++)\n            this.insert({row: row, column:0}, indentString);\n    };\n\n    this.outdentRows = function (range) {\n        var rowRange = range.collapseRows();\n        var deleteRange = new Range(0, 0, 0, 0);\n        var size = this.getTabSize();\n\n        for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) {\n            var line = this.getLine(i);\n\n            deleteRange.start.row = i;\n            deleteRange.end.row = i;\n            for (var j = 0; j < size; ++j)\n                if (line.charAt(j) != ' ')\n                    break;\n            if (j < size && line.charAt(j) == '\\t') {\n                deleteRange.start.column = j;\n                deleteRange.end.column = j + 1;\n            } else {\n                deleteRange.start.column = 0;\n                deleteRange.end.column = j;\n            }\n            this.remove(deleteRange);\n        }\n    };\n\n    this.moveLinesUp = function(firstRow, lastRow) {\n        if (firstRow <= 0) return 0;\n\n        var removed = this.doc.removeLines(firstRow, lastRow);\n        this.doc.insertLines(firstRow - 1, removed);\n        return -1;\n    };\n\n    this.moveLinesDown = function(firstRow, lastRow) {\n        if (lastRow >= this.doc.getLength()-1) return 0;\n\n        var removed = this.doc.removeLines(firstRow, lastRow);\n        this.doc.insertLines(firstRow+1, removed);\n        return 1;\n    };\n\n    this.duplicateLines = function(firstRow, lastRow) {\n        var firstRow = this.$clipRowToDocument(firstRow);\n        var lastRow = this.$clipRowToDocument(lastRow);\n\n        var lines = this.getLines(firstRow, lastRow);\n        this.doc.insertLines(firstRow, lines);\n\n        var addedRows = lastRow - firstRow + 1;\n        return addedRows;\n    };\n\n    this.$clipRowToDocument = function(row) {\n        return Math.max(0, Math.min(row, this.doc.getLength()-1));\n    };\n\n    this.$clipColumnToRow = function(row, column) {\n        if (column < 0)\n            return 0;\n        return Math.min(this.doc.getLine(row).length, column);\n    };\n\n    this.$clipPositionToDocument = function(row, column) {\n        column = Math.max(0, column);\n\n        if (row < 0) {\n            row = 0;\n            column = 0;\n        } else {\n            var len = this.doc.getLength();\n            if (row >= len) {\n                row = len - 1;\n                column = this.doc.getLine(len-1).length;\n            } else {\n                column = Math.min(this.doc.getLine(row).length, column);\n            }\n        }\n\n        return {\n            row: row,\n            column: column\n        };\n    };\n\n    this.$clipRangeToDocument = function(range) {\n        if (range.start.row < 0) {\n            range.start.row = 0;\n            range.start.column = 0\n        } else {\n            range.start.column = this.$clipColumnToRow(\n                range.start.row,\n                range.start.column\n            );\n        }\n        \n        var len = this.doc.getLength() - 1;\n        if (range.end.row > len) {\n            range.end.row = len;\n            range.end.column = this.doc.getLine(len).length;\n        } else {\n            range.end.column = this.$clipColumnToRow(\n                range.end.row,\n                range.end.column\n            );\n        }\n        return range;\n    };\n\n    // WRAPMODE\n    this.$wrapLimit = 80;\n    this.$useWrapMode = false;\n    this.$wrapLimitRange = {\n        min : null,\n        max : null\n    };\n\n    this.setUseWrapMode = function(useWrapMode) {\n        if (useWrapMode != this.$useWrapMode) {\n            this.$useWrapMode = useWrapMode;\n            this.$modified = true;\n            this.$resetRowCache(0);\n\n            // If wrapMode is activaed, the wrapData array has to be initialized.\n            if (useWrapMode) {\n                var len = this.getLength();\n                this.$wrapData = [];\n                for (var i = 0; i < len; i++) {\n                    this.$wrapData.push([]);\n                }\n                this.$updateWrapData(0, len - 1);\n            }\n\n            this._emit(\"changeWrapMode\");\n        }\n    };\n\n    this.getUseWrapMode = function() {\n        return this.$useWrapMode;\n    };\n\n    // Allow the wrap limit to move freely between min and max. Either\n    // parameter can be null to allow the wrap limit to be unconstrained\n    // in that direction. Or set both parameters to the same number to pin\n    // the limit to that value.\n    this.setWrapLimitRange = function(min, max) {\n        if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) {\n            this.$wrapLimitRange.min = min;\n            this.$wrapLimitRange.max = max;\n            this.$modified = true;\n            // This will force a recalculation of the wrap limit\n            this._emit(\"changeWrapMode\");\n        }\n    };\n\n    // This should generally only be called by the renderer when a resize\n    // is detected.\n    this.adjustWrapLimit = function(desiredLimit) {\n        var wrapLimit = this.$constrainWrapLimit(desiredLimit);\n        if (wrapLimit != this.$wrapLimit && wrapLimit > 0) {\n            this.$wrapLimit = wrapLimit;\n            this.$modified = true;\n            if (this.$useWrapMode) {\n                this.$updateWrapData(0, this.getLength() - 1);\n                this.$resetRowCache(0)\n                this._emit(\"changeWrapLimit\");\n            }\n            return true;\n        }\n        return false;\n    };\n\n    this.$constrainWrapLimit = function(wrapLimit) {\n        var min = this.$wrapLimitRange.min;\n        if (min)\n            wrapLimit = Math.max(min, wrapLimit);\n\n        var max = this.$wrapLimitRange.max;\n        if (max)\n            wrapLimit = Math.min(max, wrapLimit);\n\n        // What would a limit of 0 even mean?\n        return Math.max(1, wrapLimit);\n    };\n\n    this.getWrapLimit = function() {\n        return this.$wrapLimit;\n    };\n\n    this.getWrapLimitRange = function() {\n        // Avoid unexpected mutation by returning a copy\n        return {\n            min : this.$wrapLimitRange.min,\n            max : this.$wrapLimitRange.max\n        };\n    };\n\n    this.$updateInternalDataOnChange = function(e) {\n        var useWrapMode = this.$useWrapMode;\n        var len;\n        var action = e.data.action;\n        var firstRow = e.data.range.start.row;\n        var lastRow = e.data.range.end.row;\n        var start = e.data.range.start;\n        var end = e.data.range.end;\n        var removedFolds = null;\n\n        if (action.indexOf(\"Lines\") != -1) {\n            if (action == \"insertLines\") {\n                lastRow = firstRow + (e.data.lines.length);\n            } else {\n                lastRow = firstRow;\n            }\n            len = e.data.lines ? e.data.lines.length : lastRow - firstRow;\n        } else {\n            len = lastRow - firstRow;\n        }\n\n        if (len != 0) {\n            if (action.indexOf(\"remove\") != -1) {\n                useWrapMode && this.$wrapData.splice(firstRow, len);\n\n                var foldLines = this.$foldData;\n                removedFolds = this.getFoldsInRange(e.data.range);\n                this.removeFolds(removedFolds);\n\n                var foldLine = this.getFoldLine(end.row);\n                var idx = 0;\n                if (foldLine) {\n                    foldLine.addRemoveChars(end.row, end.column, start.column - end.column);\n                    foldLine.shiftRow(-len);\n\n                    var foldLineBefore = this.getFoldLine(firstRow);\n                    if (foldLineBefore && foldLineBefore !== foldLine) {\n                        foldLineBefore.merge(foldLine);\n                        foldLine = foldLineBefore;\n                    }\n                    idx = foldLines.indexOf(foldLine) + 1;\n                }\n\n                for (idx; idx < foldLines.length; idx++) {\n                    var foldLine = foldLines[idx];\n                    if (foldLine.start.row >= end.row) {\n                        foldLine.shiftRow(-len);\n                    }\n                }\n\n                lastRow = firstRow;\n            } else {\n                var args;\n                if (useWrapMode) {\n                    args = [firstRow, 0];\n                    for (var i = 0; i < len; i++) args.push([]);\n                    this.$wrapData.splice.apply(this.$wrapData, args);\n                }\n\n                // If some new line is added inside of a foldLine, then split\n                // the fold line up.\n                var foldLines = this.$foldData;\n                var foldLine = this.getFoldLine(firstRow);\n                var idx = 0;\n                if (foldLine) {\n                    var cmp = foldLine.range.compareInside(start.row, start.column)\n                    // Inside of the foldLine range. Need to split stuff up.\n                    if (cmp == 0) {\n                        foldLine = foldLine.split(start.row, start.column);\n                        foldLine.shiftRow(len);\n                        foldLine.addRemoveChars(\n                            lastRow, 0, end.column - start.column);\n                    } else\n                    // Infront of the foldLine but same row. Need to shift column.\n                    if (cmp == -1) {\n                        foldLine.addRemoveChars(firstRow, 0, end.column - start.column);\n                        foldLine.shiftRow(len);\n                    }\n                    // Nothing to do if the insert is after the foldLine.\n                    idx = foldLines.indexOf(foldLine) + 1;\n                }\n\n                for (idx; idx < foldLines.length; idx++) {\n                    var foldLine = foldLines[idx];\n                    if (foldLine.start.row >= firstRow) {\n                        foldLine.shiftRow(len);\n                    }\n                }\n            }\n        } else {\n            // Realign folds. E.g. if you add some new chars before a fold, the\n            // fold should \"move\" to the right.\n            len = Math.abs(e.data.range.start.column - e.data.range.end.column);\n            if (action.indexOf(\"remove\") != -1) {\n                // Get all the folds in the change range and remove them.\n                removedFolds = this.getFoldsInRange(e.data.range);\n                this.removeFolds(removedFolds);\n\n                len = -len;\n            }\n            var foldLine = this.getFoldLine(firstRow);\n            if (foldLine) {\n                foldLine.addRemoveChars(firstRow, start.column, len);\n            }\n        }\n\n        if (useWrapMode && this.$wrapData.length != this.doc.getLength()) {\n            console.error(\"doc.getLength() and $wrapData.length have to be the same!\");\n        }\n\n        useWrapMode && this.$updateWrapData(firstRow, lastRow);\n\n        return removedFolds;\n    };\n\n    this.$updateWrapData = function(firstRow, lastRow) {\n        var lines = this.doc.getAllLines();\n        var tabSize = this.getTabSize();\n        var wrapData = this.$wrapData;\n        var wrapLimit = this.$wrapLimit;\n        var tokens;\n        var foldLine;\n\n        var row = firstRow;\n        lastRow = Math.min(lastRow, lines.length - 1);\n        while (row <= lastRow) {\n            foldLine = this.getFoldLine(row, foldLine);\n            if (!foldLine) {\n                tokens = this.$getDisplayTokens(lang.stringTrimRight(lines[row]));\n                wrapData[row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize);\n                row ++;\n            } else {\n                tokens = [];\n                foldLine.walk(\n                    function(placeholder, row, column, lastColumn) {\n                        var walkTokens;\n                        if (placeholder) {\n                            walkTokens = this.$getDisplayTokens(\n                                            placeholder, tokens.length);\n                            walkTokens[0] = PLACEHOLDER_START;\n                            for (var i = 1; i < walkTokens.length; i++) {\n                                walkTokens[i] = PLACEHOLDER_BODY;\n                            }\n                        } else {\n                            walkTokens = this.$getDisplayTokens(\n                                lines[row].substring(lastColumn, column),\n                                tokens.length);\n                        }\n                        tokens = tokens.concat(walkTokens);\n                    }.bind(this),\n                    foldLine.end.row,\n                    lines[foldLine.end.row].length + 1\n                );\n                // Remove spaces/tabs from the back of the token array.\n                while (tokens.length != 0 && tokens[tokens.length - 1] >= SPACE)\n                    tokens.pop();\n\n                wrapData[foldLine.start.row]\n                    = this.$computeWrapSplits(tokens, wrapLimit, tabSize);\n                row = foldLine.end.row + 1;\n            }\n        }\n    };\n\n    // \"Tokens\"\n    var CHAR = 1,\n        CHAR_EXT = 2,\n        PLACEHOLDER_START = 3,\n        PLACEHOLDER_BODY =  4,\n        PUNCTUATION = 9,\n        SPACE = 10,\n        TAB = 11,\n        TAB_SPACE = 12;\n\n    this.$computeWrapSplits = function(tokens, wrapLimit) {\n        if (tokens.length == 0) {\n            return [];\n        }\n\n        var splits = [];\n        var displayLength = tokens.length;\n        var lastSplit = 0, lastDocSplit = 0;\n\n        function addSplit(screenPos) {\n            var displayed = tokens.slice(lastSplit, screenPos);\n\n            // The document size is the current size - the extra width for tabs\n            // and multipleWidth characters.\n            var len = displayed.length;\n            displayed.join(\"\").\n                // Get all the TAB_SPACEs.\n                replace(/12/g, function() {\n                    len -= 1;\n                }).\n                // Get all the CHAR_EXT/multipleWidth characters.\n                replace(/2/g, function() {\n                    len -= 1;\n                });\n\n            lastDocSplit += len;\n            splits.push(lastDocSplit);\n            lastSplit = screenPos;\n        }\n\n        while (displayLength - lastSplit > wrapLimit) {\n            // This is, where the split should be.\n            var split = lastSplit + wrapLimit;\n\n            // If there is a space or tab at this split position, then making\n            // a split is simple.\n            if (tokens[split] >= SPACE) {\n                // Include all following spaces + tabs in this split as well.\n                while (tokens[split] >= SPACE) {\n                    split ++;\n                }\n                addSplit(split);\n                continue;\n            }\n\n            // === ELSE ===\n            // Check if split is inside of a placeholder. Placeholder are\n            // not splitable. Therefore, seek the beginning of the placeholder\n            // and try to place the split beofre the placeholder's start.\n            if (tokens[split] == PLACEHOLDER_START\n                || tokens[split] == PLACEHOLDER_BODY)\n            {\n                // Seek the start of the placeholder and do the split\n                // before the placeholder. By definition there always\n                // a PLACEHOLDER_START between split and lastSplit.\n                for (split; split != lastSplit - 1; split--) {\n                    if (tokens[split] == PLACEHOLDER_START) {\n                        // split++; << No incremental here as we want to\n                        //  have the position before the Placeholder.\n                        break;\n                    }\n                }\n\n                // If the PLACEHOLDER_START is not the index of the\n                // last split, then we can do the split\n                if (split > lastSplit) {\n                    addSplit(split);\n                    continue;\n                }\n\n                // If the PLACEHOLDER_START IS the index of the last\n                // split, then we have to place the split after the\n                // placeholder. So, let's seek for the end of the placeholder.\n                split = lastSplit + wrapLimit;\n                for (split; split < tokens.length; split++) {\n                    if (tokens[split] != PLACEHOLDER_BODY)\n                    {\n                        break;\n                    }\n                }\n\n                // If spilt == tokens.length, then the placeholder is the last\n                // thing in the line and adding a new split doesn't make sense.\n                if (split == tokens.length) {\n                    break;  // Breaks the while-loop.\n                }\n\n                // Finally, add the split...\n                addSplit(split);\n                continue;\n            }\n\n            // === ELSE ===\n            // Search for the first non space/tab/placeholder/punctuation token backwards.\n            var minSplit = Math.max(split - 10, lastSplit - 1);\n            while (split > minSplit && tokens[split] < PLACEHOLDER_START) {\n                split --;\n            }\n            while (split > minSplit && tokens[split] == PUNCTUATION) {\n                split --;\n            }\n            // If we found one, then add the split.\n            if (split > minSplit) {\n                addSplit(++split);\n                continue;\n            }\n\n            // === ELSE ===\n            split = lastSplit + wrapLimit;\n            // The split is inside of a CHAR or CHAR_EXT token and no space\n            // around -> force a split.\n            addSplit(split);\n        }\n        return splits;\n    }\n\n    /**\n     * @param\n     *   offset: The offset in screenColumn at which position str starts.\n     *           Important for calculating the realTabSize.\n     */\n    this.$getDisplayTokens = function(str, offset) {\n        var arr = [];\n        var tabSize;\n        offset = offset || 0;\n\n        for (var i = 0; i < str.length; i++) {\n            var c = str.charCodeAt(i);\n            // Tab\n            if (c == 9) {\n                tabSize = this.getScreenTabSize(arr.length + offset);\n                arr.push(TAB);\n                for (var n = 1; n < tabSize; n++) {\n                    arr.push(TAB_SPACE);\n                }\n            }\n            // Space\n            else if (c == 32) {\n                arr.push(SPACE);\n            } else if((c > 39 && c < 48) || (c > 57 && c < 64)) {\n                arr.push(PUNCTUATION);\n            }\n            // full width characters\n            else if (c >= 0x1100 && isFullWidth(c)) {\n                arr.push(CHAR, CHAR_EXT);\n            } else {\n                arr.push(CHAR);\n            }\n        }\n        return arr;\n    }\n\n    /**\n     * Calculates the width of the a string on the screen while assuming that\n     * the string starts at the first column on the screen.\n     *\n     * @param string str String to calculate the screen width of\n     * @return array\n     *      [0]: number of columns for str on screen.\n     *      [1]: docColumn position that was read until (useful with screenColumn)\n     */\n    this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) {\n        if (maxScreenColumn == 0) {\n            return [0, 0];\n        }\n        if (maxScreenColumn == null) {\n            maxScreenColumn = screenColumn +\n                str.length * Math.max(this.getTabSize(), 2);\n        }\n        screenColumn = screenColumn || 0;\n\n        var c, column;\n        for (column = 0; column < str.length; column++) {\n            c = str.charCodeAt(column);\n            // tab\n            if (c == 9) {\n                screenColumn += this.getScreenTabSize(screenColumn);\n            }\n            // full width characters\n            else if (c >= 0x1100 && isFullWidth(c)) {\n                screenColumn += 2;\n            } else {\n                screenColumn += 1;\n            }\n            if (screenColumn > maxScreenColumn) {\n                break\n            }\n        }\n\n        return [screenColumn, column];\n    }\n\n    /**\n     * Returns the number of rows required to render this row on the screen\n     */\n    this.getRowLength = function(row) {\n        if (!this.$useWrapMode || !this.$wrapData[row]) {\n            return 1;\n        } else {\n            return this.$wrapData[row].length + 1;\n        }\n    }\n\n    /**\n     * Returns the height in pixels required to render this row on the screen\n     **/\n    this.getRowHeight = function(config, row) {\n        return this.getRowLength(row) * config.lineHeight;\n    }\n\n    this.getScreenLastRowColumn = function(screenRow) {\n        var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE)\n        return this.documentToScreenColumn(pos.row, pos.column);\n    };\n\n    this.getDocumentLastRowColumn = function(docRow, docColumn) {\n        var screenRow = this.documentToScreenRow(docRow, docColumn);\n        return this.getScreenLastRowColumn(screenRow);\n    };\n\n    this.getDocumentLastRowColumnPosition = function(docRow, docColumn) {\n        var screenRow = this.documentToScreenRow(docRow, docColumn);\n        return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10);\n    };\n\n    this.getRowSplitData = function(row) {\n        if (!this.$useWrapMode) {\n            return undefined;\n        } else {\n            return this.$wrapData[row];\n        }\n    };\n\n    /**\n     * Returns the width of a tab character at screenColumn.\n     */\n    this.getScreenTabSize = function(screenColumn) {\n        return this.$tabSize - screenColumn % this.$tabSize;\n    };\n\n    this.screenToDocumentRow = function(screenRow, screenColumn) {\n        return this.screenToDocumentPosition(screenRow, screenColumn).row;\n    };\n\n    this.screenToDocumentColumn = function(screenRow, screenColumn) {\n        return this.screenToDocumentPosition(screenRow, screenColumn).column;\n    };\n\n    this.screenToDocumentPosition = function(screenRow, screenColumn) {\n        if (screenRow < 0) {\n            return {\n                row: 0,\n                column: 0\n            }\n        }\n\n        var line;\n        var docRow = 0;\n        var docColumn = 0;\n        var column;\n        var row = 0;\n        var rowLength = 0;\n\n        var rowCache = this.$rowCache;\n        for (var i = 0; i < rowCache.length; i++) {\n            if (rowCache[i].screenRow < screenRow) {\n                row = rowCache[i].screenRow;\n                docRow = rowCache[i].docRow;\n            }\n            else {\n                break;\n            }\n        }\n        var doCache = !rowCache.length || i == rowCache.length;\n\n        var maxRow = this.getLength() - 1;\n        var foldLine = this.getNextFoldLine(docRow);\n        var foldStart = foldLine ? foldLine.start.row : Infinity;\n\n        while (row <= screenRow) {\n            rowLength = this.getRowLength(docRow);\n            if (row + rowLength - 1 >= screenRow || docRow >= maxRow) {\n                break;\n            } else {\n                row += rowLength;\n                docRow++;\n                if (docRow > foldStart) {\n                    docRow = foldLine.end.row+1;\n                    foldLine = this.getNextFoldLine(docRow, foldLine);\n                    foldStart = foldLine ? foldLine.start.row : Infinity;\n                }\n            }\n            if (doCache) {\n                rowCache.push({\n                    docRow: docRow,\n                    screenRow: row\n                });\n            }\n        }\n\n        if (foldLine && foldLine.start.row <= docRow) {\n            line = this.getFoldDisplayLine(foldLine);\n            docRow = foldLine.start.row;\n        } else if (row + rowLength <= screenRow || docRow > maxRow) {\n            // clip at the end of the document\n            return {\n                row: maxRow,\n                column: this.getLine(maxRow).length\n            }\n        } else {\n            line = this.getLine(docRow);\n            foldLine = null;\n        }\n\n        if (this.$useWrapMode) {\n            var splits = this.$wrapData[docRow];\n            if (splits) {\n                column = splits[screenRow - row];\n                if(screenRow > row && splits.length) {\n                    docColumn = splits[screenRow - row - 1] || splits[splits.length - 1];\n                    line = line.substring(docColumn);\n                }\n            }\n        }\n\n        docColumn += this.$getStringScreenWidth(line, screenColumn)[1];\n\n        // We remove one character at the end so that the docColumn\n        // position returned is not associated to the next row on the screen.\n        if (this.$useWrapMode && docColumn >= column) {\n            docColumn = column - 1;\n        }\n\n        if (foldLine) {\n            return foldLine.idxToPosition(docColumn);\n        }\n\n        return {\n            row: docRow,\n            column: docColumn\n        }\n    };\n\n    this.documentToScreenPosition = function(docRow, docColumn) {\n        // Normalize the passed in arguments.\n        if (typeof docColumn === \"undefined\")\n            var pos = this.$clipPositionToDocument(docRow.row, docRow.column);\n        else\n            pos = this.$clipPositionToDocument(docRow, docColumn);\n\n        docRow = pos.row;\n        docColumn = pos.column;\n\n        var wrapData;\n        // Special case in wrapMode if the doc is at the end of the document.\n        if (this.$useWrapMode) {\n            wrapData = this.$wrapData;\n            if (docRow > wrapData.length - 1) {\n                return {\n                    row: this.getScreenLength(),\n                    column: wrapData.length == 0\n                        ? 0\n                        : (wrapData[wrapData.length - 1].length - 1)\n                };\n            }\n        }\n\n        var screenRow = 0;\n        var foldStartRow = null;\n        var fold = null;\n\n        // Clamp the docRow position in case it's inside of a folded block.\n        fold = this.getFoldAt(docRow, docColumn, 1);\n        if (fold) {\n            docRow = fold.start.row;\n            docColumn = fold.start.column;\n        }\n\n        var rowEnd, row = 0;\n        var rowCache = this.$rowCache;\n\n        for (var i = 0; i < rowCache.length; i++) {\n            if (rowCache[i].docRow < docRow) {\n                screenRow = rowCache[i].screenRow;\n                row = rowCache[i].docRow;\n            } else {\n                break;\n            }\n        }\n        var doCache = !rowCache.length || i == rowCache.length;\n\n        var foldLine = this.getNextFoldLine(row);\n        var foldStart = foldLine ?foldLine.start.row :Infinity;\n\n        while (row < docRow) {\n            if (row >= foldStart) {\n                rowEnd = foldLine.end.row + 1;\n                if (rowEnd > docRow)\n                    break;\n                foldLine = this.getNextFoldLine(rowEnd, foldLine);\n                foldStart = foldLine ?foldLine.start.row :Infinity;\n            }\n            else {\n                rowEnd = row + 1;\n            }\n\n            screenRow += this.getRowLength(row);\n            row = rowEnd;\n\n            if (doCache) {\n                rowCache.push({\n                    docRow: row,\n                    screenRow: screenRow\n                });\n            }\n        }\n\n        // Calculate the text line that is displayed in docRow on the screen.\n        var textLine = \"\";\n        // Check if the final row we want to reach is inside of a fold.\n        if (foldLine && row >= foldStart) {\n            textLine = this.getFoldDisplayLine(foldLine, docRow, docColumn);\n            foldStartRow = foldLine.start.row;\n        } else {\n            textLine = this.getLine(docRow).substring(0, docColumn);\n            foldStartRow = docRow;\n        }\n        // Clamp textLine if in wrapMode.\n        if (this.$useWrapMode) {\n            var wrapRow = wrapData[foldStartRow];\n            var screenRowOffset = 0;\n            while (textLine.length >= wrapRow[screenRowOffset]) {\n                screenRow ++;\n                screenRowOffset++;\n            }\n            textLine = textLine.substring(\n                wrapRow[screenRowOffset - 1] || 0, textLine.length\n            );\n        }\n\n        return {\n            row: screenRow,\n            column: this.$getStringScreenWidth(textLine)[0]\n        };\n    };\n\n    this.documentToScreenColumn = function(row, docColumn) {\n        return this.documentToScreenPosition(row, docColumn).column;\n    };\n\n    this.documentToScreenRow = function(docRow, docColumn) {\n        return this.documentToScreenPosition(docRow, docColumn).row;\n    };\n\n    this.getScreenLength = function() {\n        var screenRows = 0;\n        var fold = null;\n        if (!this.$useWrapMode) {\n            screenRows = this.getLength();\n\n            // Remove the folded lines again.\n            var foldData = this.$foldData;\n            for (var i = 0; i < foldData.length; i++) {\n                fold = foldData[i];\n                screenRows -= fold.end.row - fold.start.row;\n            }\n        } else {\n            var lastRow = this.$wrapData.length;\n            var row = 0, i = 0;\n            var fold = this.$foldData[i++];\n            var foldStart = fold ? fold.start.row :Infinity;\n\n            while (row < lastRow) {\n                screenRows += this.$wrapData[row].length + 1;\n                row ++;\n                if (row > foldStart) {\n                    row = fold.end.row+1;\n                    fold = this.$foldData[i++];\n                    foldStart = fold ?fold.start.row :Infinity;\n                }\n            }\n        }\n\n        return screenRows;\n    }\n\n    // For every keystroke this gets called once per char in the whole doc!!\n    // Wouldn't hurt to make it a bit faster for c >= 0x1100\n    function isFullWidth(c) {\n        if (c < 0x1100)\n            return false;\n        return c >= 0x1100 && c <= 0x115F ||\n               c >= 0x11A3 && c <= 0x11A7 ||\n               c >= 0x11FA && c <= 0x11FF ||\n               c >= 0x2329 && c <= 0x232A ||\n               c >= 0x2E80 && c <= 0x2E99 ||\n               c >= 0x2E9B && c <= 0x2EF3 ||\n               c >= 0x2F00 && c <= 0x2FD5 ||\n               c >= 0x2FF0 && c <= 0x2FFB ||\n               c >= 0x3000 && c <= 0x303E ||\n               c >= 0x3041 && c <= 0x3096 ||\n               c >= 0x3099 && c <= 0x30FF ||\n               c >= 0x3105 && c <= 0x312D ||\n               c >= 0x3131 && c <= 0x318E ||\n               c >= 0x3190 && c <= 0x31BA ||\n               c >= 0x31C0 && c <= 0x31E3 ||\n               c >= 0x31F0 && c <= 0x321E ||\n               c >= 0x3220 && c <= 0x3247 ||\n               c >= 0x3250 && c <= 0x32FE ||\n               c >= 0x3300 && c <= 0x4DBF ||\n               c >= 0x4E00 && c <= 0xA48C ||\n               c >= 0xA490 && c <= 0xA4C6 ||\n               c >= 0xA960 && c <= 0xA97C ||\n               c >= 0xAC00 && c <= 0xD7A3 ||\n               c >= 0xD7B0 && c <= 0xD7C6 ||\n               c >= 0xD7CB && c <= 0xD7FB ||\n               c >= 0xF900 && c <= 0xFAFF ||\n               c >= 0xFE10 && c <= 0xFE19 ||\n               c >= 0xFE30 && c <= 0xFE52 ||\n               c >= 0xFE54 && c <= 0xFE66 ||\n               c >= 0xFE68 && c <= 0xFE6B ||\n               c >= 0xFF01 && c <= 0xFF60 ||\n               c >= 0xFFE0 && c <= 0xFFE6;\n    };\n\n}).call(EditSession.prototype);\n\nrequire(\"./edit_session/folding\").Folding.call(EditSession.prototype);\nrequire(\"./edit_session/bracket_match\").BracketMatch.call(EditSession.prototype);\n\nexports.EditSession = EditSession;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/edit_session_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Julian Viereck <julian DOT viereck AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n    require(\"./test/mockdom\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar lang = require(\"./lib/lang\");\nvar EditSession = require(\"./edit_session\").EditSession;\nvar Editor = require(\"./editor\").Editor;\nvar UndoManager = require(\"./undomanager\").UndoManager;\nvar MockRenderer = require(\"./test/mockrenderer\").MockRenderer;\nvar Range = require(\"./range\").Range;\nvar assert = require(\"./test/assertions\");\nvar JavaScriptMode = require(\"./mode/javascript\").Mode;\n\nfunction createFoldTestSession() {\n    var lines = [\n        \"function foo(items) {\",\n        \"    for (var i=0; i<items.length; i++) {\",\n        \"        alert(items[i] + \\\"juhu\\\");\",\n        \"    }    // Real Tab.\",\n        \"}\"\n    ];\n    var session = new EditSession(lines.join(\"\\n\"));\n    session.setUndoManager(new UndoManager());\n    session.addFold(\"args...\", new Range(0, 13, 0, 18));\n    session.addFold(\"foo...\", new Range(1, 10, 2, 10));\n    session.addFold(\"bar...\", new Range(2, 20, 2, 25));\n    return session;\n}\n\nmodule.exports = {\n\n   \"test: find matching opening bracket in Text mode\" : function() {\n        var session = new EditSession([\"(()(\", \"())))\"]);\n\n        assert.position(session.findMatchingBracket({row: 0, column: 3}), 0, 1);\n        assert.position(session.findMatchingBracket({row: 1, column: 2}), 1, 0);\n        assert.position(session.findMatchingBracket({row: 1, column: 3}), 0, 3);\n        assert.position(session.findMatchingBracket({row: 1, column: 4}), 0, 0);\n        assert.equal(session.findMatchingBracket({row: 1, column: 5}), null);\n    },\n\n    \"test: find matching closing bracket in Text mode\" : function() {\n        var session = new EditSession([\"(()(\", \"())))\"]);\n\n        assert.position(session.findMatchingBracket({row: 1, column: 1}), 1, 1);\n        assert.position(session.findMatchingBracket({row: 1, column: 1}), 1, 1);\n        assert.position(session.findMatchingBracket({row: 0, column: 4}), 1, 2);\n        assert.position(session.findMatchingBracket({row: 0, column: 2}), 0, 2);\n        assert.position(session.findMatchingBracket({row: 0, column: 1}), 1, 3);\n        assert.equal(session.findMatchingBracket({row: 0, column: 0}), null);\n    },\n\n    \"test: find matching opening bracket in JavaScript mode\" : function() {\n        var lines = [\n            \"function foo() {\",\n            \"    var str = \\\"{ foo()\\\";\",\n            \"    if (debug) {\",\n            \"        // write str (a string) to the console\",\n            \"        console.log(str);\",\n            \"    }\",\n            \"    str += \\\" bar() }\\\";\",\n            \"}\"\n        ];\n        var session = new EditSession(lines.join(\"\\n\"), new JavaScriptMode());\n\n        assert.position(session.findMatchingBracket({row: 0, column: 14}), 0, 12);\n        assert.position(session.findMatchingBracket({row: 7, column: 1}), 0, 15);\n        assert.position(session.findMatchingBracket({row: 6, column: 20}), 1, 15);\n        assert.position(session.findMatchingBracket({row: 1, column: 22}), 1, 20);\n        assert.position(session.findMatchingBracket({row: 3, column: 31}), 3, 21);\n        assert.position(session.findMatchingBracket({row: 4, column: 24}), 4, 19);\n        assert.equal(session.findMatchingBracket({row: 0, column: 1}), null);\n    },\n\n    \"test: find matching closing bracket in JavaScript mode\" : function() {\n        var lines = [\n            \"function foo() {\",\n            \"    var str = \\\"{ foo()\\\";\",\n            \"    if (debug) {\",\n            \"        // write str (a string) to the console\",\n            \"        console.log(str);\",\n            \"    }\",\n            \"    str += \\\" bar() }\\\";\",\n            \"}\"\n        ];\n        var session = new EditSession(lines.join(\"\\n\"), new JavaScriptMode());\n\n        assert.position(session.findMatchingBracket({row: 0, column: 13}), 0, 13);\n        assert.position(session.findMatchingBracket({row: 0, column: 16}), 7, 0);\n        assert.position(session.findMatchingBracket({row: 1, column: 16}), 6, 19);\n        assert.position(session.findMatchingBracket({row: 1, column: 21}), 1, 21);\n        assert.position(session.findMatchingBracket({row: 3, column: 22}), 3, 30);\n        assert.position(session.findMatchingBracket({row: 4, column: 20}), 4, 23);\n    },\n\n    \"test: handle unbalanced brackets in JavaScript mode\" : function() {\n        var lines = [\n            \"function foo() {\",\n            \"    var str = \\\"{ foo()\\\";\",\n            \"    if (debug) {\",\n            \"        // write str a string) to the console\",\n            \"        console.log(str);\",\n            \"    \",\n            \"    str += \\\" bar() \\\";\",\n            \"}\"\n        ];\n        var session = new EditSession(lines.join(\"\\n\"), new JavaScriptMode());\n\n        assert.equal(session.findMatchingBracket({row: 0, column: 16}), null);\n        assert.equal(session.findMatchingBracket({row: 3, column: 30}), null);\n        assert.equal(session.findMatchingBracket({row: 1, column: 16}), null);\n    },\n\n    \"test: match different bracket types\" : function() {\n        var session = new EditSession([\"({[\", \")]}\"]);\n\n        assert.position(session.findMatchingBracket({row: 0, column: 1}), 1, 0);\n        assert.position(session.findMatchingBracket({row: 0, column: 2}), 1, 2);\n        assert.position(session.findMatchingBracket({row: 0, column: 3}), 1, 1);\n\n        assert.position(session.findMatchingBracket({row: 1, column: 1}), 0, 0);\n        assert.position(session.findMatchingBracket({row: 1, column: 2}), 0, 2);\n        assert.position(session.findMatchingBracket({row: 1, column: 3}), 0, 1);\n    },\n\n    \"test: move lines down\" : function() {\n        var session = new EditSession([\"a1\", \"a2\", \"a3\", \"a4\"]);\n\n        session.moveLinesDown(0, 1);\n        assert.equal(session.getValue(), [\"a3\", \"a1\", \"a2\", \"a4\"].join(\"\\n\"));\n\n        session.moveLinesDown(1, 2);\n        assert.equal(session.getValue(), [\"a3\", \"a4\", \"a1\", \"a2\"].join(\"\\n\"));\n\n        session.moveLinesDown(2, 3);\n        assert.equal(session.getValue(), [\"a3\", \"a4\", \"a1\", \"a2\"].join(\"\\n\"));\n\n        session.moveLinesDown(2, 2);\n        assert.equal(session.getValue(), [\"a3\", \"a4\", \"a2\", \"a1\"].join(\"\\n\"));\n    },\n\n    \"test: move lines up\" : function() {\n        var session = new EditSession([\"a1\", \"a2\", \"a3\", \"a4\"]);\n\n        session.moveLinesUp(2, 3);\n        assert.equal(session.getValue(), [\"a1\", \"a3\", \"a4\", \"a2\"].join(\"\\n\"));\n\n        session.moveLinesUp(1, 2);\n        assert.equal(session.getValue(), [\"a3\", \"a4\", \"a1\", \"a2\"].join(\"\\n\"));\n\n        session.moveLinesUp(0, 1);\n        assert.equal(session.getValue(), [\"a3\", \"a4\", \"a1\", \"a2\"].join(\"\\n\"));\n\n        session.moveLinesUp(2, 2);\n        assert.equal(session.getValue(), [\"a3\", \"a1\", \"a4\", \"a2\"].join(\"\\n\"));\n    },\n\n    \"test: duplicate lines\" : function() {\n        var session = new EditSession([\"1\", \"2\", \"3\", \"4\"]);\n\n        session.duplicateLines(1, 2);\n        assert.equal(session.getValue(), [\"1\", \"2\", \"3\", \"2\", \"3\", \"4\"].join(\"\\n\"));\n    },\n\n    \"test: duplicate last line\" : function() {\n        var session = new EditSession([\"1\", \"2\", \"3\"]);\n\n        session.duplicateLines(2, 2);\n        assert.equal(session.getValue(), [\"1\", \"2\", \"3\", \"3\"].join(\"\\n\"));\n    },\n\n    \"test: duplicate first line\" : function() {\n        var session = new EditSession([\"1\", \"2\", \"3\"]);\n\n        session.duplicateLines(0, 0);\n        assert.equal(session.getValue(), [\"1\", \"1\", \"2\", \"3\"].join(\"\\n\"));\n    },\n\n    \"test: getScreenLastRowColumn\": function() {\n        var session = new EditSession([\n            \"juhu\",\n            \"12\\t\\t34\",\n            \"ぁぁa\"\n        ]);\n\n        assert.equal(session.getScreenLastRowColumn(0), 4);\n        assert.equal(session.getScreenLastRowColumn(1), 10);\n        assert.equal(session.getScreenLastRowColumn(2), 5);\n    },\n\n    \"test: convert document to screen coordinates\" : function() {\n        var session = new EditSession(\"01234\\t567890\\t1234\");\n        session.setTabSize(4);\n\n        assert.equal(session.documentToScreenColumn(0, 0), 0);\n        assert.equal(session.documentToScreenColumn(0, 4), 4);\n        assert.equal(session.documentToScreenColumn(0, 5), 5);\n        assert.equal(session.documentToScreenColumn(0, 6), 8);\n        assert.equal(session.documentToScreenColumn(0, 12), 14);\n        assert.equal(session.documentToScreenColumn(0, 13), 16);\n\n        session.setTabSize(2);\n\n        assert.equal(session.documentToScreenColumn(0, 0), 0);\n        assert.equal(session.documentToScreenColumn(0, 4), 4);\n        assert.equal(session.documentToScreenColumn(0, 5), 5);\n        assert.equal(session.documentToScreenColumn(0, 6), 6);\n        assert.equal(session.documentToScreenColumn(0, 7), 7);\n        assert.equal(session.documentToScreenColumn(0, 12), 12);\n        assert.equal(session.documentToScreenColumn(0, 13), 14);\n    },\n\n    \"test: convert document to screen coordinates with leading tabs\": function() {\n        var session = new EditSession(\"\\t\\t123\");\n        session.setTabSize(4);\n\n        assert.equal(session.documentToScreenColumn(0, 0), 0);\n        assert.equal(session.documentToScreenColumn(0, 1), 4);\n        assert.equal(session.documentToScreenColumn(0, 2), 8);\n        assert.equal(session.documentToScreenColumn(0, 3), 9);\n    },\n\n    \"test: documentToScreen without soft wrap\": function() {\n        var session = new EditSession([\n            \"juhu\",\n            \"12\\t\\t34\",\n            \"ぁぁa\"\n        ]);\n\n        assert.position(session.documentToScreenPosition(0, 3), 0, 3);\n        assert.position(session.documentToScreenPosition(1, 3), 1, 4);\n        assert.position(session.documentToScreenPosition(1, 4), 1, 8);\n        assert.position(session.documentToScreenPosition(2, 2), 2, 4);\n    },\n\n    \"test: documentToScreen with soft wrap\": function() {\n        var session = new EditSession([\"foo bar foo bar\"]);\n        session.setUseWrapMode(true);\n        session.setWrapLimitRange(12, 12);\n        session.adjustWrapLimit(80);\n\n        assert.position(session.documentToScreenPosition(0, 11), 0, 11);\n        assert.position(session.documentToScreenPosition(0, 12), 1, 0);\n    },\n\n    \"test: documentToScreen with soft wrap and multibyte characters\": function() {\n        var session = new EditSession([\"ぁぁa\"]);\n        session.setUseWrapMode(true);\n        session.setWrapLimitRange(2, 2);\n        session.adjustWrapLimit(80);\n\n        assert.position(session.documentToScreenPosition(0, 1), 1, 0);\n        assert.position(session.documentToScreenPosition(0, 2), 2, 0);\n        assert.position(session.documentToScreenPosition(0, 4), 2, 1);\n    },\n\n    \"test: documentToScreen should clip position to the document boundaries\": function() {\n        var session = new EditSession(\"foo bar\\njuhu kinners\");\n\n        assert.position(session.documentToScreenPosition(-1, 4), 0, 0);\n        assert.position(session.documentToScreenPosition(3, 0), 1, 12);\n    },\n\n    \"test: convert screen to document coordinates\" : function() {\n        var session = new EditSession(\"01234\\t567890\\t1234\");\n        session.setTabSize(4);\n\n        assert.equal(session.screenToDocumentColumn(0, 0), 0);\n        assert.equal(session.screenToDocumentColumn(0, 4), 4);\n        assert.equal(session.screenToDocumentColumn(0, 5), 5);\n        assert.equal(session.screenToDocumentColumn(0, 6), 5);\n        assert.equal(session.screenToDocumentColumn(0, 7), 5);\n        assert.equal(session.screenToDocumentColumn(0, 8), 6);\n        assert.equal(session.screenToDocumentColumn(0, 9), 7);\n        assert.equal(session.screenToDocumentColumn(0, 15), 12);\n        assert.equal(session.screenToDocumentColumn(0, 19), 16);\n\n        session.setTabSize(2);\n\n        assert.equal(session.screenToDocumentColumn(0, 0), 0);\n        assert.equal(session.screenToDocumentColumn(0, 4), 4);\n        assert.equal(session.screenToDocumentColumn(0, 5), 5);\n        assert.equal(session.screenToDocumentColumn(0, 6), 6);\n        assert.equal(session.screenToDocumentColumn(0, 12), 12);\n        assert.equal(session.screenToDocumentColumn(0, 13), 12);\n        assert.equal(session.screenToDocumentColumn(0, 14), 13);\n    },\n\n    \"test: screenToDocument with soft wrap\": function() {\n        var session = new EditSession([\"foo bar foo bar\"]);\n        session.setUseWrapMode(true);\n        session.setWrapLimitRange(12, 12);\n        session.adjustWrapLimit(80);\n\n        assert.position(session.screenToDocumentPosition(1, 0), 0, 12);\n        assert.position(session.screenToDocumentPosition(0, 11), 0, 11);\n        // Check if the position is clamped the right way.\n        assert.position(session.screenToDocumentPosition(0, 12), 0, 11);\n        assert.position(session.screenToDocumentPosition(0, 20), 0, 11);\n    },\n\n    \"test: screenToDocument with soft wrap and multi byte characters\": function() {\n        var session = new EditSession([\"ぁ a\"]);\n        session.setUseWrapMode(true);\n        session.adjustWrapLimit(80);\n\n        assert.position(session.screenToDocumentPosition(0, 1), 0, 0);\n        assert.position(session.screenToDocumentPosition(0, 2), 0, 1);\n        assert.position(session.screenToDocumentPosition(0, 3), 0, 2);\n        assert.position(session.screenToDocumentPosition(0, 4), 0, 3);\n        assert.position(session.screenToDocumentPosition(0, 5), 0, 3);\n    },\n\n    \"test: screenToDocument should clip position to the document boundaries\": function() {\n        var session = new EditSession(\"foo bar\\njuhu kinners\");\n\n        assert.position(session.screenToDocumentPosition(-1, 4), 0, 0);\n        assert.position(session.screenToDocumentPosition(0, -1), 0, 0);\n        assert.position(session.screenToDocumentPosition(0, 30), 0, 7);\n        assert.position(session.screenToDocumentPosition(2, 4), 1, 12);\n        assert.position(session.screenToDocumentPosition(1, 30), 1, 12);\n        assert.position(session.screenToDocumentPosition(20, 50), 1, 12);\n        assert.position(session.screenToDocumentPosition(20, 5), 1, 12);\n\n        // and the same for folded rows\n        session.addFold(\"...\", new Range(0,1,1,3));\n        assert.position(session.screenToDocumentPosition(1, 2), 1, 12);\n        // for wrapped rows\n        session.setUseWrapMode(true);\n        session.setWrapLimitRange(5,5);\n        assert.position(session.screenToDocumentPosition(4, 1), 1, 12);\n    },\n\n    \"test: wrapLine split function\" : function() {\n        function computeAndAssert(line, assertEqual, wrapLimit, tabSize) {\n            wrapLimit = wrapLimit || 12;\n            tabSize = tabSize || 4;\n            line = lang.stringTrimRight(line);\n            var tokens = EditSession.prototype.$getDisplayTokens(line);\n            var splits = EditSession.prototype.$computeWrapSplits(tokens, wrapLimit, tabSize);\n            // console.log(\"String:\", line, \"Result:\", splits, \"Expected:\", assertEqual);\n            assert.ok(splits.length == assertEqual.length);\n            for (var i = 0; i < splits.length; i++) {\n                assert.ok(splits[i] == assertEqual[i]);\n            }\n        }\n\n        // Basic splitting.\n        computeAndAssert(\"foo bar foo bar\", [ 12 ]);\n        computeAndAssert(\"foo bar f   bar\", [ 12 ]);\n        computeAndAssert(\"foo bar f     r\", [ 14 ]);\n        computeAndAssert(\"foo bar foo bar foo bara foo\", [12, 25]);\n\n        // Don't split if there is only whitespaces/tabs at the end of the line.\n        computeAndAssert(\"foo foo foo \\t \\t\", [ ]);\n\n        // If there is no space to split, force split.\n        computeAndAssert(\"foooooooooooooo\", [ 12 ]);\n        computeAndAssert(\"fooooooooooooooooooooooooooo\", [12, 24]);\n        computeAndAssert(\"foo bar fooooooooooobooooooo\", [8,  20]);\n\n        // Basic splitting + tabs.\n        computeAndAssert(\"foo \\t\\tbar\", [ 6 ]);\n        computeAndAssert(\"foo \\t \\tbar\", [ 7 ]);\n\n        // Ignore spaces/tabs at beginning of split.\n        computeAndAssert(\"foo \\t \\t   \\t \\t bar\", [ 14 ]);\n\n        // Test wrapping for asian characters.\n        computeAndAssert(\"ぁぁ\", [1], 2);\n        computeAndAssert(\" ぁぁ\", [1, 2], 2);\n        computeAndAssert(\" ぁ\\tぁ\", [1, 3], 2);\n        computeAndAssert(\" ぁぁ\\tぁ\", [1, 4], 4);\n\n        // Test wrapping for punctuation.\n        computeAndAssert(\" ab.c;ef++\", [1, 3, 5, 7, 8], 2);\n        computeAndAssert(\" a.b\", [1, 2, 3], 1);\n        computeAndAssert(\"#>>\", [1, 2], 1);\n    },\n\n    \"test get longest line\" : function() {\n        var session = new EditSession([\"12\"]);\n        session.setTabSize(4);\n        assert.equal(session.getWidth(), 2);\n        assert.equal(session.getScreenWidth(), 2);\n\n        session.doc.insertNewLine(0);\n        session.doc.insertLines(1, [\"123\"]);\n        assert.equal(session.getWidth(), 3);\n        assert.equal(session.getScreenWidth(), 3);\n\n        session.doc.insertNewLine(0);\n        session.doc.insertLines(1, [\"\\t\\t\"]);\n\n        assert.equal(session.getWidth(), 3);\n        assert.equal(session.getScreenWidth(), 8);\n\n        session.setTabSize(2);\n        assert.equal(session.getWidth(), 3);\n        assert.equal(session.getScreenWidth(), 4);\n    },\n\n    \"test getDisplayString\": function() {\n        var session = new EditSession([\"12\"]);\n        session.setTabSize(4);\n\n        assert.equal(session.$getDisplayTokens(\"\\t\").length, 4);\n        assert.equal(session.$getDisplayTokens(\"abc\").length, 3);\n        assert.equal(session.$getDisplayTokens(\"abc\\t\").length, 4);\n    },\n\n    \"test issue 83\": function() {\n        var session = new EditSession(\"\");\n        var editor = new Editor(new MockRenderer(), session);\n        var document = session.getDocument();\n\n        session.setUseWrapMode(true);\n\n        document.insertLines(0, [\"a\", \"b\"]);\n        document.insertLines(2, [\"c\", \"d\"]);\n        document.removeLines(1, 2);\n    },\n\n    \"test wrapMode init has to create wrapData array\": function() {\n        var session = new EditSession(\"foo bar\\nfoo bar\");\n        var editor = new Editor(new MockRenderer(), session);\n        var document = session.getDocument();\n\n        session.setUseWrapMode(true);\n        session.setWrapLimitRange(3, 3);\n        session.adjustWrapLimit(80);\n\n        // Test if wrapData is there and was computed.\n        assert.equal(session.$wrapData.length, 2);\n        assert.equal(session.$wrapData[0].length, 1);\n        assert.equal(session.$wrapData[1].length, 1);\n    },\n\n    \"test first line blank with wrap\": function() {\n        var session = new EditSession(\"\\nfoo\");\n        session.setUseWrapMode(true);\n        assert.equal(session.doc.getValue(), [\"\", \"foo\"].join(\"\\n\"));\n    },\n\n    \"test first line blank with wrap 2\" : function() {\n        var session = new EditSession(\"\");\n        session.setUseWrapMode(true);\n        session.setValue(\"\\nfoo\");\n\n        assert.equal(session.doc.getValue(), [\"\", \"foo\"].join(\"\\n\"));\n    },\n\n    \"test fold getFoldDisplayLine\": function() {\n        var session = createFoldTestSession();\n        function assertDisplayLine(foldLine, str) {\n            var line = session.getLine(foldLine.end.row);\n            var displayLine =\n                session.getFoldDisplayLine(foldLine, foldLine.end.row, line.length);\n            assert.equal(displayLine, str);\n        }\n\n        assertDisplayLine(session.$foldData[0], \"function foo(args...) {\")\n        assertDisplayLine(session.$foldData[1], \"    for (vfoo...ert(items[bar...\\\"juhu\\\");\");\n    },\n\n    \"test foldLine idxToPosition\": function() {\n        var session = createFoldTestSession();\n\n        function assertIdx2Pos(foldLineIdx, idx, row, column) {\n            var foldLine = session.$foldData[foldLineIdx];\n            assert.position(foldLine.idxToPosition(idx), row, column);\n        }\n\n//        \"function foo(items) {\",\n//        \"    for (var i=0; i<items.length; i++) {\",\n//        \"        alert(items[i] + \\\"juhu\\\");\",\n//        \"    }    // Real Tab.\",\n//        \"}\"\n\n        assertIdx2Pos(0, 12, 0, 12);\n        assertIdx2Pos(0, 13, 0, 13);\n        assertIdx2Pos(0, 14, 0, 13);\n        assertIdx2Pos(0, 19, 0, 13);\n        assertIdx2Pos(0, 20, 0, 18);\n\n        assertIdx2Pos(1, 10, 1, 10);\n        assertIdx2Pos(1, 11, 1, 10);\n        assertIdx2Pos(1, 15, 1, 10);\n        assertIdx2Pos(1, 16, 2, 10);\n        assertIdx2Pos(1, 26, 2, 20);\n        assertIdx2Pos(1, 27, 2, 20);\n        assertIdx2Pos(1, 32, 2, 25);\n    },\n\n    \"test fold documentToScreen\": function() {\n        var session = createFoldTestSession();\n        function assertDoc2Screen(docRow, docCol, screenRow, screenCol) {\n            assert.position(\n                session.documentToScreenPosition(docRow, docCol),\n                screenRow, screenCol\n            );\n        }\n\n        // One fold ending in the same row.\n        assertDoc2Screen(0,  0, 0, 0);\n        assertDoc2Screen(0, 13, 0, 13);\n        assertDoc2Screen(0, 14, 0, 13);\n        assertDoc2Screen(0, 17, 0, 13);\n        assertDoc2Screen(0, 18, 0, 20);\n\n        // Fold ending on some other row.\n        assertDoc2Screen(1,  0, 1, 0);\n        assertDoc2Screen(1, 10, 1, 10);\n        assertDoc2Screen(1, 11, 1, 10);\n        assertDoc2Screen(1, 99, 1, 10);\n\n        assertDoc2Screen(2,  0, 1, 10);\n        assertDoc2Screen(2,  9, 1, 10);\n        assertDoc2Screen(2, 10, 1, 16);\n        assertDoc2Screen(2, 11, 1, 17);\n\n        // Fold in the same row with fold over more then one row in the same row.\n        assertDoc2Screen(2, 19, 1, 25);\n        assertDoc2Screen(2, 20, 1, 26);\n        assertDoc2Screen(2, 21, 1, 26);\n\n        assertDoc2Screen(2, 24, 1, 26);\n        assertDoc2Screen(2, 25, 1, 32);\n        assertDoc2Screen(2, 26, 1, 33);\n        assertDoc2Screen(2, 99, 1, 40);\n\n        // Test one position after the folds. Should be all like normal.\n        assertDoc2Screen(3,  0, 2,  0);\n    },\n\n    \"test fold screenToDocument\": function() {\n        var session = createFoldTestSession();\n        function assertScreen2Doc(docRow, docCol, screenRow, screenCol) {\n            assert.position(\n                session.screenToDocumentPosition(screenRow, screenCol),\n                docRow, docCol\n            );\n        }\n\n        // One fold ending in the same row.\n        assertScreen2Doc(0,  0, 0, 0);\n        assertScreen2Doc(0, 13, 0, 13);\n        assertScreen2Doc(0, 13, 0, 14);\n        assertScreen2Doc(0, 18, 0, 20);\n        assertScreen2Doc(0, 19, 0, 21);\n\n        // Fold ending on some other row.\n        assertScreen2Doc(1,  0, 1, 0);\n        assertScreen2Doc(1, 10, 1, 10);\n        assertScreen2Doc(1, 10, 1, 11);\n\n        assertScreen2Doc(1, 10, 1, 15);\n        assertScreen2Doc(2, 10, 1, 16);\n        assertScreen2Doc(2, 11, 1, 17);\n\n        // Fold in the same row with fold over more then one row in the same row.\n        assertScreen2Doc(2, 19, 1, 25);\n        assertScreen2Doc(2, 20, 1, 26);\n        assertScreen2Doc(2, 20, 1, 27);\n\n        assertScreen2Doc(2, 20, 1, 31);\n        assertScreen2Doc(2, 25, 1, 32);\n        assertScreen2Doc(2, 26, 1, 33);\n        assertScreen2Doc(2, 33, 1, 99);\n\n        // Test one position after the folds. Should be all like normal.\n        assertScreen2Doc(3,  0, 2,  0);\n    },\n\n    \"test getFoldsInRange()\": function() {\n        var session = createFoldTestSession();\n        var foldLines = session.$foldData;\n        var folds = foldLines[0].folds.concat(foldLines[1].folds);\n\n        function test(startRow, startColumn, endColumn, endRow, folds) {\n            var r = new Range(startRow, startColumn, endColumn, endRow);\n            var retFolds = session.getFoldsInRange(r);\n\n            assert.ok(retFolds.length == folds.length);\n            for (var i = 0; i < retFolds.length; i++) {\n                assert.equal(retFolds[i].range + \"\", folds[i].range + \"\");\n            }\n        }\n\n        test(0, 0, 0, 13,  [ ]);\n        test(0, 0, 0, 14,  [ folds[0] ]);\n        test(0, 0, 0, 18,  [ folds[0] ]);\n        test(0, 0, 1, 10,  [ folds[0] ]);\n        test(0, 0, 1, 11,  [ folds[0], folds[1] ]);\n        test(0, 18, 1, 11, [ folds[1] ]);\n        test(2, 0,  2, 13, [ folds[1] ]);\n        test(2, 10, 2, 20, [ ]);\n        test(2, 10, 2, 11, [ ]);\n        test(2, 19, 2, 20, [ ]);\n    },\n\n    \"test fold one-line text insert\": function() {\n        // These are mostly test for the FoldLine.addRemoveChars function.\n        var session = createFoldTestSession();\n        var undoManager = session.getUndoManager();\n        var foldLines = session.$foldData;\n\n        function insert(row, column, text) {\n            session.insert({row: row, column: column}, text);\n\n            // Force the session to store all changes made to the document NOW\n            // on the undoManager's queue. Otherwise we can't undo in separate\n            // steps later.\n            session.$syncInformUndoManager();\n        }\n\n        var foldLine, fold, folds;\n        // First line.\n        foldLine = session.$foldData[0];\n        fold = foldLine.folds[0];\n\n        insert(0, 0, \"0\");\n        assert.range(foldLine.range, 0, 14, 0, 19);\n        assert.range(fold.range,     0, 14, 0, 19);\n        insert(0, 14, \"1\");\n        assert.range(foldLine.range, 0, 15, 0, 20);\n        assert.range(fold.range,     0, 15, 0, 20);\n        insert(0, 20, \"2\");\n        assert.range(foldLine.range, 0, 15, 0, 20);\n        assert.range(fold.range,     0, 15, 0, 20);\n\n        // Second line.\n        foldLine = session.$foldData[1];\n        folds = foldLine.folds;\n\n        insert(1, 0, \"3\");\n        assert.range(foldLine.range, 1, 11, 2, 25);\n        assert.range(folds[0].range, 1, 11, 2, 10);\n        assert.range(folds[1].range, 2, 20, 2, 25);\n\n        insert(1, 11, \"4\");\n        assert.range(foldLine.range, 1, 12, 2, 25);\n        assert.range(folds[0].range, 1, 12, 2, 10);\n        assert.range(folds[1].range, 2, 20, 2, 25);\n\n        insert(2, 10, \"5\");\n        assert.range(foldLine.range, 1, 12, 2, 26);\n        assert.range(folds[0].range, 1, 12, 2, 10);\n        assert.range(folds[1].range, 2, 21, 2, 26);\n\n        insert(2, 21, \"6\");\n        assert.range(foldLine.range, 1, 12, 2, 27);\n        assert.range(folds[0].range, 1, 12, 2, 10);\n        assert.range(folds[1].range, 2, 22, 2, 27);\n\n        insert(2, 27, \"7\");\n        assert.range(foldLine.range, 1, 12, 2, 27);\n        assert.range(folds[0].range, 1, 12, 2, 10);\n        assert.range(folds[1].range, 2, 22, 2, 27);\n\n        // UNDO = REMOVE\n        undoManager.undo(); // 6\n        assert.range(foldLine.range, 1, 12, 2, 27);\n        assert.range(folds[0].range, 1, 12, 2, 10);\n        assert.range(folds[1].range, 2, 22, 2, 27);\n\n        undoManager.undo(); // 5\n        assert.range(foldLine.range, 1, 12, 2, 26);\n        assert.range(folds[0].range, 1, 12, 2, 10);\n        assert.range(folds[1].range, 2, 21, 2, 26);\n\n        undoManager.undo(); // 4\n        assert.range(foldLine.range, 1, 12, 2, 25);\n        assert.range(folds[0].range, 1, 12, 2, 10);\n        assert.range(folds[1].range, 2, 20, 2, 25);\n\n        undoManager.undo(); // 3\n        assert.range(foldLine.range, 1, 11, 2, 25);\n        assert.range(folds[0].range, 1, 11, 2, 10);\n        assert.range(folds[1].range, 2, 20, 2, 25);\n\n        undoManager.undo(); // Beginning first line.\n        assert.equal(foldLines.length, 2);\n        assert.range(foldLines[0].range, 0, 15, 0, 20);\n        assert.range(foldLines[1].range, 1, 10, 2, 25);\n\n        foldLine = session.$foldData[0];\n        fold = foldLine.folds[0];\n\n        undoManager.undo(); // 2\n        assert.range(foldLine.range, 0, 15, 0, 20);\n        assert.range(fold.range,     0, 15, 0, 20);\n\n        undoManager.undo(); // 1\n        assert.range(foldLine.range, 0, 14, 0, 19);\n        assert.range(fold.range,     0, 14, 0, 19);\n\n        undoManager.undo(); // 0\n        assert.range(foldLine.range, 0, 13, 0, 18);\n        assert.range(fold.range,     0, 13, 0, 18);\n    },\n\n    \"test fold multi-line insert/remove\": function() {\n        var session = createFoldTestSession(),\n            undoManager = session.getUndoManager(),\n            foldLines = session.$foldData;\n        function insert(row, column, text) {\n            session.insert({row: row, column: column}, text);\n            // Force the session to store all changes made to the document NOW\n            // on the undoManager's queue. Otherwise we can't undo in separate\n            // steps later.\n            session.$syncInformUndoManager();\n        }\n\n        var foldLines = session.$foldData, foldLine, fold, folds;\n\n        insert(0, 0, \"\\nfo0\");\n        assert.equal(foldLines.length, 2);\n        assert.range(foldLines[0].range, 1, 16, 1, 21);\n        assert.range(foldLines[1].range, 2, 10, 3, 25);\n\n        insert(2, 0, \"\\nba1\");\n        assert.equal(foldLines.length, 2);\n        assert.range(foldLines[0].range, 1, 16, 1, 21);\n        assert.range(foldLines[1].range, 3, 13, 4, 25);\n\n        insert(3, 10, \"\\nfo2\");\n        assert.equal(foldLines.length, 2);\n        assert.range(foldLines[0].range, 1, 16, 1, 21);\n        assert.range(foldLines[1].range, 4,  6, 5, 25);\n\n        insert(5, 10, \"\\nba3\");\n        assert.equal(foldLines.length, 3);\n        assert.range(foldLines[0].range, 1, 16, 1, 21);\n        assert.range(foldLines[1].range, 4,  6, 5, 10);\n        assert.range(foldLines[2].range, 6, 13, 6, 18);\n\n        insert(6, 18, \"\\nfo4\");\n        assert.equal(foldLines.length, 3);\n        assert.range(foldLines[0].range, 1, 16, 1, 21);\n        assert.range(foldLines[1].range, 4,  6, 5, 10);\n        assert.range(foldLines[2].range, 6, 13, 6, 18);\n\n        undoManager.undo(); // 3\n        assert.equal(foldLines.length, 3);\n        assert.range(foldLines[0].range, 1, 16, 1, 21);\n        assert.range(foldLines[1].range, 4,  6, 5, 10);\n        assert.range(foldLines[2].range, 6, 13, 6, 18);\n\n        undoManager.undo(); // 2\n        assert.equal(foldLines.length, 2);\n        assert.range(foldLines[0].range, 1, 16, 1, 21);\n        assert.range(foldLines[1].range, 4,  6, 5, 25);\n\n        undoManager.undo(); // 1\n        assert.equal(foldLines.length, 2);\n        assert.range(foldLines[0].range, 1, 16, 1, 21);\n        assert.range(foldLines[1].range, 3, 13, 4, 25);\n\n        undoManager.undo(); // 0\n        assert.equal(foldLines.length, 2);\n        assert.range(foldLines[0].range, 1, 16, 1, 21);\n        assert.range(foldLines[1].range, 2, 10, 3, 25);\n\n        undoManager.undo(); // Beginning\n        assert.equal(foldLines.length, 2);\n        assert.range(foldLines[0].range, 0, 13, 0, 18);\n        assert.range(foldLines[1].range, 1, 10, 2, 25);\n        // TODO: Add test for inseration inside of folds.\n    },\n\n    \"test fold wrap data compution\": function() {\n        function assertArray(a, b) {\n            assert.ok(a.length == b.length);\n            for (var i = 0; i < a.length; i++) {\n                assert.equal(a[i], b[i]);\n            }\n        }\n\n        function assertWrap(line0, line1, line2) {\n            line0 && assertArray(wrapData[0], line0);\n            line1 && assertArray(wrapData[1], line1);\n            line2 && assertArray(wrapData[2], line2);\n        }\n\n        function removeFoldAssertWrap(docRow, docColumn, line0, line1, line2) {\n            session.removeFold(session.getFoldAt(docRow, docColumn));\n            assertWrap(line0, line1, line2);\n        }\n\n        var lines = [\n            \"foo bar foo bar\",\n            \"foo bar foo bar\",\n            \"foo bar foo bar\"\n        ];\n\n        var session = new EditSession(lines.join(\"\\n\"));\n        session.setUseWrapMode(true);\n        session.$wrapLimit = 7;\n        session.$updateWrapData(0, 2);\n        var wrapData = session.$wrapData;\n\n        // Do a simple assertion without folds to check basic functionallity.\n        assertWrap([8], [8], [8]);\n\n        // --- Do in line folding ---\n\n        // Adding a fold. The split position is inside of the fold. As placeholder\n        // are not splitable, the split should be before the split.\n        session.addFold(\"woot\", new Range(0, 4, 0, 15));\n        assertWrap([4], [8], [8]);\n\n        // Remove the fold again which should reset the wrapData.\n        removeFoldAssertWrap(0, 4, [8], [8], [8]);\n\n        session.addFold(\"woot\", new Range(0, 6, 0, 9));\n        assertWrap([6, 13], [8], [8]);\n        removeFoldAssertWrap(0, 6, [8], [8], [8]);\n\n        // The fold fits into the wrap limit - no split expected.\n        session.addFold(\"woot\", new Range(0, 3, 0, 15));\n        assertWrap([], [8], [8]);\n        removeFoldAssertWrap(0, 4, [8], [8], [8]);\n\n        // Fold after split position should be all fine.\n        session.addFold(\"woot\", new Range(0, 8, 0, 15));\n        assertWrap([8], [8], [8]);\n        removeFoldAssertWrap(0, 8, [8], [8], [8]);\n\n        // Fold's placeholder is far too long for wrapSplit.\n        session.addFold(\"woot0123456789\", new Range(0, 8, 0, 15));\n        assertWrap([8], [8], [8]);\n        removeFoldAssertWrap(0, 8, [8], [8], [8]);\n\n        // Fold's placeholder is far too long for wrapSplit\n        // + content at the end of the line\n        session.addFold(\"woot0123456789\", new Range(0, 6, 0, 8));\n        assertWrap([6, 20], [8], [8]);\n        removeFoldAssertWrap(0, 8, [8], [8], [8]);\n\n        session.addFold(\"woot0123456789\", new Range(0, 6, 0, 8));\n        session.addFold(\"woot0123456789\", new Range(0, 8, 0, 10));\n        assertWrap([6, 20, 34], [8], [8]);\n        session.removeFold(session.getFoldAt(0, 7));\n        removeFoldAssertWrap(0, 8, [8], [8], [8]);\n\n        session.addFold(\"woot0123456789\", new Range(0, 7, 0, 9));\n        session.addFold(\"woot0123456789\", new Range(0, 13, 0, 15));\n        assertWrap([7, 21, 25], [8], [8]);\n        session.removeFold(session.getFoldAt(0, 7));\n        removeFoldAssertWrap(0, 14, [8], [8], [8]);\n\n        // --- Do some multiline folding ---\n\n        // Add a fold over two lines. Note, that the wrapData[1] stays the\n        // same. This is an implementation detail and expected behavior.\n        session.addFold(\"woot\", new Range(0, 8, 1, 15));\n        assertWrap([8], [8 /* See comments */], [8]);\n        removeFoldAssertWrap(0, 8, [8], [8], [8]);\n\n        session.addFold(\"woot\", new Range(0, 9, 1, 11));\n        assertWrap([8, 14], [8 /* See comments */], [8]);\n        removeFoldAssertWrap(0, 9, [8], [8], [8]);\n\n        session.addFold(\"woot\", new Range(0, 9, 1, 15));\n        assertWrap([8], [8 /* See comments */], [8]);\n        removeFoldAssertWrap(0, 9, [8], [8], [8]);\n\n        return session;\n    },\n\n    \"test add fold\": function() {\n        var session = createFoldTestSession();\n        var fold;\n\n        function tryAddFold(placeholder, range, shouldFail) {\n            var fail = false;\n            try {\n                fold = session.addFold(placeholder, range);\n            } catch (e) {\n                fail = true;\n            }\n            if (fail != shouldFail) {\n                throw \"Expected to get an exception\";\n            }\n        }\n\n        tryAddFold(\"foo\", new Range(0, 13, 0, 17), false);\n        tryAddFold(\"foo\", new Range(0, 14, 0, 18), true);\n        tryAddFold(\"foo\", new Range(0, 13, 0, 18), false);\n        assert.equal(session.$foldData[0].folds.length, 1);\n\n        tryAddFold(\"f\", new Range(0, 13, 0, 18), true);\n        tryAddFold(\"foo\", new Range(0, 18, 0, 21), false);\n        assert.equal(session.$foldData[0].folds.length, 2);\n        session.removeFold(fold);\n\n        tryAddFold(\"foo\", new Range(0, 18, 0, 22), false);\n        tryAddFold(\"foo\", new Range(0, 18, 0, 19), true);\n        tryAddFold(\"foo\", new Range(0, 22, 1, 10), false);\n    },\n\n    \"test add subfolds\": function() {\n        var session = createFoldTestSession();\n        var fold, oldFold;\n        var foldData = session.$foldData;\n\n        oldFold = foldData[0].folds[0];\n\n        fold = session.addFold(\"fold0\", new Range(0, 10, 0, 21));\n        assert.equal(foldData[0].folds.length, 1);\n        assert.equal(fold.subFolds.length, 1);\n        assert.equal(fold.subFolds[0], oldFold);\n\n        session.expandFold(fold);\n        assert.equal(foldData[0].folds.length, 1);\n        assert.equal(foldData[0].folds[0], oldFold);\n        assert.equal(fold.subFolds.length, 0);\n\n        fold = session.addFold(\"fold0\", new Range(0, 13, 2, 10));\n        assert.equal(foldData.length, 1);\n        assert.equal(fold.subFolds.length, 2);\n        assert.equal(fold.subFolds[0], oldFold);\n\n        session.expandFold(fold);\n        assert.equal(foldData.length, 2);\n        assert.equal(foldData[0].folds.length, 1);\n        assert.equal(foldData[0].folds[0], oldFold);\n        assert.equal(fold.subFolds.length, 0);\n\n        session.unfold(null, true);\n        fold = session.addFold(\"fold0\", new Range(0, 0, 0, 21));\n        session.addFold(\"fold0\", new Range(0, 1, 0, 5));\n        session.addFold(\"fold0\", new Range(0, 6, 0, 8));\n        assert.equal(fold.subFolds.length, 2);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/editor.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)\n *      Julian Viereck <julian.viereck@gmail.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nrequire(\"./lib/fixoldbrowsers\");\n\nvar oop = require(\"./lib/oop\");\nvar lang = require(\"./lib/lang\");\nvar useragent = require(\"./lib/useragent\");\nvar TextInput = require(\"./keyboard/textinput\").TextInput;\nvar MouseHandler = require(\"./mouse/mouse_handler\").MouseHandler;\nvar FoldHandler = require(\"./mouse/fold_handler\").FoldHandler;\n//var TouchHandler = require(\"./touch_handler\").TouchHandler;\nvar KeyBinding = require(\"./keyboard/keybinding\").KeyBinding;\nvar EditSession = require(\"./edit_session\").EditSession;\nvar Search = require(\"./search\").Search;\nvar Range = require(\"./range\").Range;\nvar EventEmitter = require(\"./lib/event_emitter\").EventEmitter;\nvar CommandManager = require(\"./commands/command_manager\").CommandManager;\nvar defaultCommands = require(\"./commands/default_commands\").commands;\n\nvar Editor = function(renderer, session) {\n    var container = renderer.getContainerElement();\n    this.container = container;\n    this.renderer = renderer;\n\n    this.textInput  = new TextInput(renderer.getTextAreaContainer(), this);\n    this.keyBinding = new KeyBinding(this);\n\n    // TODO detect touch event support\n    if (useragent.isIPad) {\n        //this.$mouseHandler = new TouchHandler(this);\n    } else {\n        this.$mouseHandler = new MouseHandler(this);\n        new FoldHandler(this);\n    }\n\n    this.$blockScrolling = 0;\n    this.$search = new Search().set({\n        wrap: true\n    });\n\n    this.commands = new CommandManager(useragent.isMac ? \"mac\" : \"win\", defaultCommands);\n    this.setSession(session || new EditSession(\"\"));\n};\n\n(function(){\n\n    oop.implement(this, EventEmitter);\n\n    this.setKeyboardHandler = function(keyboardHandler) {\n        this.keyBinding.setKeyboardHandler(keyboardHandler);\n    };\n\n    this.getKeyboardHandler = function() {\n        return this.keyBinding.getKeyboardHandler();\n    };\n\n    this.setSession = function(session) {\n        if (this.session == session)\n            return;\n\n        if (this.session) {\n            var oldSession = this.session;\n            this.session.removeEventListener(\"change\", this.$onDocumentChange);\n            this.session.removeEventListener(\"changeMode\", this.$onChangeMode);\n            this.session.removeEventListener(\"tokenizerUpdate\", this.$onTokenizerUpdate);\n            this.session.removeEventListener(\"changeTabSize\", this.$onChangeTabSize);\n            this.session.removeEventListener(\"changeWrapLimit\", this.$onChangeWrapLimit);\n            this.session.removeEventListener(\"changeWrapMode\", this.$onChangeWrapMode);\n            this.session.removeEventListener(\"onChangeFold\", this.$onChangeFold);\n            this.session.removeEventListener(\"changeFrontMarker\", this.$onChangeFrontMarker);\n            this.session.removeEventListener(\"changeBackMarker\", this.$onChangeBackMarker);\n            this.session.removeEventListener(\"changeBreakpoint\", this.$onChangeBreakpoint);\n            this.session.removeEventListener(\"changeAnnotation\", this.$onChangeAnnotation);\n            this.session.removeEventListener(\"changeOverwrite\", this.$onCursorChange);\n            this.session.removeEventListener(\"changeScrollTop\", this.$onScrollTopChange);\n            this.session.removeEventListener(\"changeLeftTop\", this.$onScrollLeftChange);\n\n            var selection = this.session.getSelection();\n            selection.removeEventListener(\"changeCursor\", this.$onCursorChange);\n            selection.removeEventListener(\"changeSelection\", this.$onSelectionChange);\n        }\n\n        this.session = session;\n\n        this.$onDocumentChange = this.onDocumentChange.bind(this);\n        session.addEventListener(\"change\", this.$onDocumentChange);\n        this.renderer.setSession(session);\n\n        this.$onChangeMode = this.onChangeMode.bind(this);\n        session.addEventListener(\"changeMode\", this.$onChangeMode);\n\n        this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this);\n        session.addEventListener(\"tokenizerUpdate\", this.$onTokenizerUpdate);\n\n        this.$onChangeTabSize = this.renderer.updateText.bind(this.renderer);\n        session.addEventListener(\"changeTabSize\", this.$onChangeTabSize);\n\n        this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this);\n        session.addEventListener(\"changeWrapLimit\", this.$onChangeWrapLimit);\n\n        this.$onChangeWrapMode = this.onChangeWrapMode.bind(this);\n        session.addEventListener(\"changeWrapMode\", this.$onChangeWrapMode);\n\n        this.$onChangeFold = this.onChangeFold.bind(this);\n        session.addEventListener(\"changeFold\", this.$onChangeFold);\n\n        this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this);\n        this.session.addEventListener(\"changeFrontMarker\", this.$onChangeFrontMarker);\n\n        this.$onChangeBackMarker = this.onChangeBackMarker.bind(this);\n        this.session.addEventListener(\"changeBackMarker\", this.$onChangeBackMarker);\n\n        this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this);\n        this.session.addEventListener(\"changeBreakpoint\", this.$onChangeBreakpoint);\n\n        this.$onChangeAnnotation = this.onChangeAnnotation.bind(this);\n        this.session.addEventListener(\"changeAnnotation\", this.$onChangeAnnotation);\n\n        this.$onCursorChange = this.onCursorChange.bind(this);\n        this.session.addEventListener(\"changeOverwrite\", this.$onCursorChange);\n\n        this.$onScrollTopChange = this.onScrollTopChange.bind(this);\n        this.session.addEventListener(\"changeScrollTop\", this.$onScrollTopChange);\n\n        this.$onScrollLeftChange = this.onScrollLeftChange.bind(this);\n        this.session.addEventListener(\"changeScrollLeft\", this.$onScrollLeftChange);\n\n        this.selection = session.getSelection();\n        this.selection.addEventListener(\"changeCursor\", this.$onCursorChange);\n\n        this.$onSelectionChange = this.onSelectionChange.bind(this);\n        this.selection.addEventListener(\"changeSelection\", this.$onSelectionChange);\n\n        this.onChangeMode();\n\n        this.$blockScrolling += 1;\n        this.onCursorChange();\n        this.$blockScrolling -= 1;\n\n        this.onScrollTopChange();\n        this.onScrollLeftChange();\n        this.onSelectionChange();\n        this.onChangeFrontMarker();\n        this.onChangeBackMarker();\n        this.onChangeBreakpoint();\n        this.onChangeAnnotation();\n        this.session.getUseWrapMode() && this.renderer.adjustWrapLimit();\n        this.renderer.updateFull();\n\n        this._emit(\"changeSession\", {\n            session: session,\n            oldSession: oldSession\n        });\n    };\n\n    this.getSession = function() {\n        return this.session;\n    };\n\n    this.getSelection = function() {\n        return this.selection;\n    };\n\n    this.resize = function() {\n        this.renderer.onResize();\n    };\n\n    this.setTheme = function(theme) {\n        this.renderer.setTheme(theme);\n    };\n\n    this.getTheme = function() {\n        return this.renderer.getTheme();\n    };\n\n    this.setStyle = function(style) {\n        this.renderer.setStyle(style);\n    };\n\n    this.unsetStyle = function(style) {\n        this.renderer.unsetStyle(style);\n    };\n\n    this.setFontSize = function(size) {\n        this.container.style.fontSize = size;\n        this.renderer.updateFontSize();\n    };\n\n    this.$highlightBrackets = function() {\n        if (this.session.$bracketHighlight) {\n            this.session.removeMarker(this.session.$bracketHighlight);\n            this.session.$bracketHighlight = null;\n        }\n\n        if (this.$highlightPending) {\n            return;\n        }\n\n        // perform highlight async to not block the browser during navigation\n        var self = this;\n        this.$highlightPending = true;\n        setTimeout(function() {\n            self.$highlightPending = false;\n\n            var pos = self.session.findMatchingBracket(self.getCursorPosition());\n            if (pos) {\n                var range = new Range(pos.row, pos.column, pos.row, pos.column+1);\n                self.session.$bracketHighlight = self.session.addMarker(range, \"ace_bracket\", \"text\");\n            }\n        }, 10);\n    };\n\n    this.focus = function() {\n        // Safari needs the timeout\n        // iOS and Firefox need it called immediately\n        // to be on the save side we do both\n        var _self = this;\n        setTimeout(function() {\n            _self.textInput.focus();\n        });\n        this.textInput.focus();\n    };\n\n    this.isFocused = function() {\n        return this.textInput.isFocused();\n    };\n\n    this.blur = function() {\n        this.textInput.blur();\n    };\n\n    this.onFocus = function() {\n        this.renderer.showCursor();\n        this.renderer.visualizeFocus();\n        this._emit(\"focus\");\n    };\n\n    this.onBlur = function() {\n        this.renderer.hideCursor();\n        this.renderer.visualizeBlur();\n        this._emit(\"blur\");\n    };\n\n    this.onDocumentChange = function(e) {\n        var delta = e.data;\n        var range = delta.range;\n        var lastRow;\n\n        if (range.start.row == range.end.row && delta.action != \"insertLines\" && delta.action != \"removeLines\")\n            lastRow = range.end.row;\n        else\n            lastRow = Infinity;\n        this.renderer.updateLines(range.start.row, lastRow);\n\n        this._emit(\"change\", e);\n\n        // update cursor because tab characters can influence the cursor position\n        this.onCursorChange();\n    };\n\n    this.onTokenizerUpdate = function(e) {\n        var rows = e.data;\n        this.renderer.updateLines(rows.first, rows.last);\n    };\n\n    this.onScrollTopChange = function() {\n        this.renderer.scrollToY(this.session.getScrollTop());\n    };\n\n    this.onScrollLeftChange = function() {\n        this.renderer.scrollToX(this.session.getScrollLeft());\n    };\n\n    this.onCursorChange = function() {\n        this.renderer.updateCursor();\n\n        if (!this.$blockScrolling) {\n            this.renderer.scrollCursorIntoView();\n        }\n\n        // move text input over the cursor\n        // this is required for iOS and IME\n        this.renderer.moveTextAreaToCursor(this.textInput.getElement());\n\n        this.$highlightBrackets();\n        this.$updateHighlightActiveLine();\n    };\n\n    this.$updateHighlightActiveLine = function() {\n        var session = this.getSession();\n\n        if (session.$highlightLineMarker)\n            session.removeMarker(session.$highlightLineMarker);\n        if (typeof this.$lastrow == \"number\")\n            this.renderer.removeGutterDecoration(this.$lastrow, \"ace_gutter_active_line\");\n\n        session.$highlightLineMarker = null;\n        this.$lastrow = null;\n\n        if (this.getHighlightActiveLine()) {\n            var cursor = this.getCursorPosition(),\n                foldLine = this.session.getFoldLine(cursor.row);\n\n            if ((this.getSelectionStyle() != \"line\" || !this.selection.isMultiLine())) {\n                var range;\n                if (foldLine) {\n                    range = new Range(foldLine.start.row, 0, foldLine.end.row + 1, 0);\n                } else {\n                    range = new Range(cursor.row, 0, cursor.row+1, 0);\n                }\n                session.$highlightLineMarker = session.addMarker(range, \"ace_active_line\", \"background\");\n            }\n\n            this.renderer.addGutterDecoration(this.$lastrow = cursor.row, \"ace_gutter_active_line\");\n        }\n    };\n\n    this.onSelectionChange = function(e) {\n        var session = this.getSession();\n\n        if (session.$selectionMarker) {\n            session.removeMarker(session.$selectionMarker);\n        }\n        session.$selectionMarker = null;\n\n        if (!this.selection.isEmpty()) {\n            var range = this.selection.getRange();\n            var style = this.getSelectionStyle();\n            session.$selectionMarker = session.addMarker(range, \"ace_selection\", style);\n        } else {\n            this.$updateHighlightActiveLine();\n        }\n\n        if (this.$highlightSelectedWord)\n            this.session.getMode().highlightSelection(this);\n    };\n\n    this.onChangeFrontMarker = function() {\n        this.renderer.updateFrontMarkers();\n    };\n\n    this.onChangeBackMarker = function() {\n        this.renderer.updateBackMarkers();\n    };\n\n    this.onChangeBreakpoint = function() {\n        this.renderer.setBreakpoints(this.session.getBreakpoints());\n    };\n\n    this.onChangeAnnotation = function() {\n        this.renderer.setAnnotations(this.session.getAnnotations());\n    };\n\n    this.onChangeMode = function() {\n        this.renderer.updateText();\n    };\n\n    this.onChangeWrapLimit = function() {\n        this.renderer.updateFull();\n    };\n\n    this.onChangeWrapMode = function() {\n        this.renderer.onResize(true);\n    };\n\n    this.onChangeFold = function() {\n        // Update the active line marker as due to folding changes the current\n        // line range on the screen might have changed.\n        this.$updateHighlightActiveLine();\n        // TODO: This might be too much updating. Okay for now.\n        this.renderer.updateFull();\n    };\n\n    this.getCopyText = function() {\n        var text = \"\";\n        if (!this.selection.isEmpty())\n            text = this.session.getTextRange(this.getSelectionRange());\n\n        this._emit(\"copy\", text);\n        return text;\n    };\n\n    this.onCut = function() {\n        this.commands.exec(\"cut\", this);\n    };\n\n    this.insert = function(text) {\n        var session = this.session;\n        var mode = session.getMode();\n\n        var cursor = this.getCursorPosition();\n\n        if (this.getBehavioursEnabled()) {\n            // Get a transform if the current mode wants one.\n            var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text);\n            if (transform)\n                text = transform.text;\n        }\n\n        text = text.replace(\"\\t\", this.session.getTabString());\n\n        // remove selected text\n        if (!this.selection.isEmpty()) {\n            cursor = this.session.remove(this.getSelectionRange());\n            this.clearSelection();\n        }\n        else if (this.session.getOverwrite()) {\n            var range = new Range.fromPoints(cursor, cursor);\n            range.end.column += text.length;\n            this.session.remove(range);\n        }\n\n        this.clearSelection();\n\n        var start = cursor.column;\n        var lineState = session.getState(cursor.row);\n        var shouldOutdent = mode.checkOutdent(lineState, session.getLine(cursor.row), text);\n        var line = session.getLine(cursor.row);\n        var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString());\n        var end = session.insert(cursor, text);\n\n        if (transform && transform.selection) {\n            if (transform.selection.length == 2) { // Transform relative to the current column\n                this.selection.setSelectionRange(\n                    new Range(cursor.row, start + transform.selection[0],\n                              cursor.row, start + transform.selection[1]));\n            } else { // Transform relative to the current row.\n                this.selection.setSelectionRange(\n                    new Range(cursor.row + transform.selection[0],\n                              transform.selection[1],\n                              cursor.row + transform.selection[2],\n                              transform.selection[3]));\n            }\n        }\n\n        var lineState = session.getState(cursor.row);\n\n        // TODO disabled multiline auto indent\n        // possibly doing the indent before inserting the text\n        // if (cursor.row !== end.row) {\n        if (session.getDocument().isNewLine(text)) {\n            this.moveCursorTo(cursor.row+1, 0);\n\n            var size = session.getTabSize();\n            var minIndent = Number.MAX_VALUE;\n\n            for (var row = cursor.row + 1; row <= end.row; ++row) {\n                var indent = 0;\n\n                line = session.getLine(row);\n                for (var i = 0; i < line.length; ++i)\n                    if (line.charAt(i) == '\\t')\n                        indent += size;\n                    else if (line.charAt(i) == ' ')\n                        indent += 1;\n                    else\n                        break;\n                if (/[^\\s]/.test(line))\n                    minIndent = Math.min(indent, minIndent);\n            }\n\n            for (var row = cursor.row + 1; row <= end.row; ++row) {\n                var outdent = minIndent;\n\n                line = session.getLine(row);\n                for (var i = 0; i < line.length && outdent > 0; ++i)\n                    if (line.charAt(i) == '\\t')\n                        outdent -= size;\n                    else if (line.charAt(i) == ' ')\n                        outdent -= 1;\n                session.remove(new Range(row, 0, row, i));\n            }\n            session.indentRows(cursor.row + 1, end.row, lineIndent);\n        }\n        if (shouldOutdent)\n            mode.autoOutdent(lineState, session, cursor.row);\n    };\n\n    this.onTextInput = function(text, pasted) {\n        if (pasted)\n            this._emit(\"paste\", text);\n\n        this.keyBinding.onTextInput(text, pasted);\n    };\n\n    this.onCommandKey = function(e, hashId, keyCode) {\n        this.keyBinding.onCommandKey(e, hashId, keyCode);\n    };\n\n    this.setOverwrite = function(overwrite) {\n        this.session.setOverwrite(overwrite);\n    };\n\n    this.getOverwrite = function() {\n        return this.session.getOverwrite();\n    };\n\n    this.toggleOverwrite = function() {\n        this.session.toggleOverwrite();\n    };\n\n    this.setScrollSpeed = function(speed) {\n        this.$mouseHandler.setScrollSpeed(speed);\n    };\n\n    this.getScrollSpeed = function() {\n        return this.$mouseHandler.getScrollSpeed();\n    };\n\n    this.setDragDelay = function(dragDelay) {\n        this.$mouseHandler.setDragDelay(dragDelay);\n    };\n\n    this.getDragDelay = function() {\n        return this.$mouseHandler.getDragDelay();\n    };\n\n    this.$selectionStyle = \"line\";\n    this.setSelectionStyle = function(style) {\n        if (this.$selectionStyle == style) return;\n\n        this.$selectionStyle = style;\n        this.onSelectionChange();\n        this._emit(\"changeSelectionStyle\", {data: style});\n    };\n\n    this.getSelectionStyle = function() {\n        return this.$selectionStyle;\n    };\n\n    this.$highlightActiveLine = true;\n    this.setHighlightActiveLine = function(shouldHighlight) {\n        if (this.$highlightActiveLine == shouldHighlight) return;\n\n        this.$highlightActiveLine = shouldHighlight;\n        this.$updateHighlightActiveLine();\n    };\n\n    this.getHighlightActiveLine = function() {\n        return this.$highlightActiveLine;\n    };\n\n    this.$highlightSelectedWord = true;\n    this.setHighlightSelectedWord = function(shouldHighlight) {\n        if (this.$highlightSelectedWord == shouldHighlight)\n            return;\n\n        this.$highlightSelectedWord = shouldHighlight;\n        if (shouldHighlight)\n            this.session.getMode().highlightSelection(this);\n        else\n            this.session.getMode().clearSelectionHighlight(this);\n    };\n\n    this.getHighlightSelectedWord = function() {\n        return this.$highlightSelectedWord;\n    };\n\n    this.setAnimatedScroll = function(shouldAnimate){\n        this.renderer.setAnimatedScroll(shouldAnimate);\n    };\n\n    this.getAnimatedScroll = function(){\n        return this.renderer.getAnimatedScroll();\n    };\n\n    this.setShowInvisibles = function(showInvisibles) {\n        if (this.getShowInvisibles() == showInvisibles)\n            return;\n\n        this.renderer.setShowInvisibles(showInvisibles);\n    };\n\n    this.getShowInvisibles = function() {\n        return this.renderer.getShowInvisibles();\n    };\n\n    this.setShowPrintMargin = function(showPrintMargin) {\n        this.renderer.setShowPrintMargin(showPrintMargin);\n    };\n\n    this.getShowPrintMargin = function() {\n        return this.renderer.getShowPrintMargin();\n    };\n\n    this.setPrintMarginColumn = function(showPrintMargin) {\n        this.renderer.setPrintMarginColumn(showPrintMargin);\n    };\n\n    this.getPrintMarginColumn = function() {\n        return this.renderer.getPrintMarginColumn();\n    };\n\n    this.$readOnly = false;\n    this.setReadOnly = function(readOnly) {\n        this.$readOnly = readOnly;\n    };\n\n    this.getReadOnly = function() {\n        return this.$readOnly;\n    };\n\n    this.$modeBehaviours = true;\n    this.setBehavioursEnabled = function (enabled) {\n        this.$modeBehaviours = enabled;\n    };\n\n    this.getBehavioursEnabled = function () {\n        return this.$modeBehaviours;\n    };\n\n    this.setShowFoldWidgets = function(show) {\n        var gutter = this.renderer.$gutterLayer;\n        if (gutter.getShowFoldWidgets() == show)\n            return;\n\n        this.renderer.$gutterLayer.setShowFoldWidgets(show);\n        this.$showFoldWidgets = show;\n        this.renderer.updateFull();\n    };\n\n    this.getShowFoldWidgets = function() {\n        return this.renderer.$gutterLayer.getShowFoldWidgets();\n    };\n\n    this.remove = function(dir) {\n        if (this.selection.isEmpty()){\n            if(dir == \"left\")\n                this.selection.selectLeft();\n            else\n                this.selection.selectRight();\n        }\n\n        var range = this.getSelectionRange();\n        if (this.getBehavioursEnabled()) {\n            var session = this.session;\n            var state = session.getState(range.start.row);\n            var new_range = session.getMode().transformAction(state, 'deletion', this, session, range);\n            if (new_range)\n                range = new_range;\n        }\n\n        this.session.remove(range);\n        this.clearSelection();\n    };\n\n    this.removeWordRight = function() {\n        if (this.selection.isEmpty())\n            this.selection.selectWordRight();\n\n        this.session.remove(this.getSelectionRange());\n        this.clearSelection();\n    };\n\n    this.removeWordLeft = function() {\n        if (this.selection.isEmpty())\n            this.selection.selectWordLeft();\n\n        this.session.remove(this.getSelectionRange());\n        this.clearSelection();\n    };\n\n    this.removeToLineStart = function() {\n        if (this.selection.isEmpty())\n            this.selection.selectLineStart();\n\n        this.session.remove(this.getSelectionRange());\n        this.clearSelection();\n    };\n\n    this.removeToLineEnd = function() {\n        if (this.selection.isEmpty())\n            this.selection.selectLineEnd();\n\n        var range = this.getSelectionRange();\n        if (range.start.column == range.end.column && range.start.row == range.end.row) {\n            range.end.column = 0;\n            range.end.row++;\n        }\n\n        this.session.remove(range);\n        this.clearSelection();\n    };\n\n    this.splitLine = function() {\n        if (!this.selection.isEmpty()) {\n            this.session.remove(this.getSelectionRange());\n            this.clearSelection();\n        }\n\n        var cursor = this.getCursorPosition();\n        this.insert(\"\\n\");\n        this.moveCursorToPosition(cursor);\n    };\n\n    this.transposeLetters = function() {\n        if (!this.selection.isEmpty()) {\n            return;\n        }\n\n        var cursor = this.getCursorPosition();\n        var column = cursor.column;\n        if (column === 0)\n            return;\n\n        var line = this.session.getLine(cursor.row);\n        var swap, range;\n        if (column < line.length) {\n            swap = line.charAt(column) + line.charAt(column-1);\n            range = new Range(cursor.row, column-1, cursor.row, column+1);\n        }\n        else {\n            swap = line.charAt(column-1) + line.charAt(column-2);\n            range = new Range(cursor.row, column-2, cursor.row, column);\n        }\n        this.session.replace(range, swap);\n    };\n\n    this.toLowerCase = function() {\n        var originalRange = this.getSelectionRange();\n        if (this.selection.isEmpty()) {\n            this.selection.selectWord();\n        }\n\n        var range = this.getSelectionRange();\n        var text = this.session.getTextRange(range);\n        this.session.replace(range, text.toLowerCase());\n        this.selection.setSelectionRange(originalRange);\n    };\n\n    this.toUpperCase = function() {\n        var originalRange = this.getSelectionRange();\n        if (this.selection.isEmpty()) {\n            this.selection.selectWord();\n        }\n\n        var range = this.getSelectionRange();\n        var text = this.session.getTextRange(range);\n        this.session.replace(range, text.toUpperCase());\n        this.selection.setSelectionRange(originalRange);\n    };\n\n    this.indent = function() {\n        var session = this.session;\n        var range = this.getSelectionRange();\n\n        if (range.start.row < range.end.row || range.start.column < range.end.column) {\n            var rows = this.$getSelectedRows();\n            session.indentRows(rows.first, rows.last, \"\\t\");\n        } else {\n            var indentString;\n\n            if (this.session.getUseSoftTabs()) {\n                var size        = session.getTabSize(),\n                    position    = this.getCursorPosition(),\n                    column      = session.documentToScreenColumn(position.row, position.column),\n                    count       = (size - column % size);\n\n                indentString = lang.stringRepeat(\" \", count);\n            } else\n                indentString = \"\\t\";\n            return this.insert(indentString);\n        }\n    };\n\n    this.blockOutdent = function() {\n        var selection = this.session.getSelection();\n        this.session.outdentRows(selection.getRange());\n    };\n\n    this.toggleCommentLines = function() {\n        var state = this.session.getState(this.getCursorPosition().row);\n        var rows = this.$getSelectedRows();\n        this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last);\n    };\n\n    this.removeLines = function() {\n        var rows = this.$getSelectedRows();\n        var range;\n        if (rows.first === 0 || rows.last+1 < this.session.getLength())\n            range = new Range(rows.first, 0, rows.last+1, 0);\n        else\n            range = new Range(\n                rows.first-1, this.session.getLine(rows.first-1).length,\n                rows.last, this.session.getLine(rows.last).length\n            );\n        this.session.remove(range);\n        this.clearSelection();\n    };\n\n    this.moveLinesDown = function() {\n        this.$moveLines(function(firstRow, lastRow) {\n            return this.session.moveLinesDown(firstRow, lastRow);\n        });\n    };\n\n    this.moveLinesUp = function() {\n        this.$moveLines(function(firstRow, lastRow) {\n            return this.session.moveLinesUp(firstRow, lastRow);\n        });\n    };\n\n    this.moveText = function(range, toPosition) {\n        if (this.$readOnly)\n            return null;\n\n        return this.session.moveText(range, toPosition);\n    };\n\n    this.copyLinesUp = function() {\n        this.$moveLines(function(firstRow, lastRow) {\n            this.session.duplicateLines(firstRow, lastRow);\n            return 0;\n        });\n    };\n\n    this.copyLinesDown = function() {\n        this.$moveLines(function(firstRow, lastRow) {\n            return this.session.duplicateLines(firstRow, lastRow);\n        });\n    };\n\n\n    this.$moveLines = function(mover) {\n        var rows = this.$getSelectedRows();\n        var selection = this.selection;\n        if (!selection.isMultiLine()) {\n            var range = selection.getRange();\n            var reverse = selection.isBackwards();\n        }\n\n        var linesMoved = mover.call(this, rows.first, rows.last);\n\n        if (range) {\n            range.start.row += linesMoved;\n            range.end.row += linesMoved;\n            selection.setSelectionRange(range, reverse);\n        }\n        else {\n            selection.setSelectionAnchor(rows.last+linesMoved+1, 0);\n            selection.$moveSelection(function() {\n                selection.moveCursorTo(rows.first+linesMoved, 0);\n            });\n        }\n    };\n\n    this.$getSelectedRows = function() {\n        var range = this.getSelectionRange().collapseRows();\n\n        return {\n            first: range.start.row,\n            last: range.end.row\n        };\n    };\n\n    this.onCompositionStart = function(text) {\n        this.renderer.showComposition(this.getCursorPosition());\n    };\n\n    this.onCompositionUpdate = function(text) {\n        this.renderer.setCompositionText(text);\n    };\n\n    this.onCompositionEnd = function() {\n        this.renderer.hideComposition();\n    };\n\n    this.getFirstVisibleRow = function() {\n        return this.renderer.getFirstVisibleRow();\n    };\n\n    this.getLastVisibleRow = function() {\n        return this.renderer.getLastVisibleRow();\n    };\n\n    this.isRowVisible = function(row) {\n        return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow());\n    };\n\n    this.isRowFullyVisible = function(row) {\n        return (row >= this.renderer.getFirstFullyVisibleRow() && row <= this.renderer.getLastFullyVisibleRow());\n    };\n\n    this.$getVisibleRowCount = function() {\n        return this.renderer.getScrollBottomRow() - this.renderer.getScrollTopRow() + 1;\n    };\n\n    this.$getPageDownRow = function() {\n        return this.renderer.getScrollBottomRow();\n    };\n\n    this.$getPageUpRow = function() {\n        var firstRow = this.renderer.getScrollTopRow();\n        var lastRow = this.renderer.getScrollBottomRow();\n\n        return firstRow - (lastRow - firstRow);\n    };\n\n    this.selectPageDown = function() {\n        var row = this.$getPageDownRow() + Math.floor(this.$getVisibleRowCount() / 2);\n\n        this.scrollPageDown();\n\n        var selection = this.getSelection();\n        var leadScreenPos = this.session.documentToScreenPosition(selection.getSelectionLead());\n        var dest = this.session.screenToDocumentPosition(row, leadScreenPos.column);\n        selection.selectTo(dest.row, dest.column);\n    };\n\n    this.selectPageUp = function() {\n        var visibleRows = this.renderer.getScrollTopRow() - this.renderer.getScrollBottomRow();\n        var row = this.$getPageUpRow() + Math.round(visibleRows / 2);\n\n        this.scrollPageUp();\n\n        var selection = this.getSelection();\n        var leadScreenPos = this.session.documentToScreenPosition(selection.getSelectionLead());\n        var dest = this.session.screenToDocumentPosition(row, leadScreenPos.column);\n        selection.selectTo(dest.row, dest.column);\n    };\n\n    this.gotoPageDown = function() {\n        var row = this.$getPageDownRow();\n        var column = this.getCursorPositionScreen().column;\n\n        this.scrollToRow(row);\n        this.getSelection().moveCursorToScreen(row, column);\n    };\n\n    this.gotoPageUp = function() {\n        var row = this.$getPageUpRow();\n        var column = this.getCursorPositionScreen().column;\n\n       this.scrollToRow(row);\n       this.getSelection().moveCursorToScreen(row, column);\n    };\n\n    this.scrollPageDown = function() {\n        this.scrollToRow(this.$getPageDownRow());\n    };\n\n    this.scrollPageUp = function() {\n        this.renderer.scrollToRow(this.$getPageUpRow());\n    };\n\n    this.scrollToRow = function(row) {\n        this.renderer.scrollToRow(row);\n    };\n\n    this.scrollToLine = function(line, center) {\n        this.renderer.scrollToLine(line, center);\n    };\n\n    this.centerSelection = function() {\n        var range = this.getSelectionRange();\n        var line = Math.floor(range.start.row + (range.end.row - range.start.row) / 2);\n        this.renderer.scrollToLine(line, true);\n    };\n\n    this.getCursorPosition = function() {\n        return this.selection.getCursor();\n    };\n\n    this.getCursorPositionScreen = function() {\n        return this.session.documentToScreenPosition(this.getCursorPosition());\n    };\n\n    this.getSelectionRange = function() {\n        return this.selection.getRange();\n    };\n\n\n    this.selectAll = function() {\n        this.$blockScrolling += 1;\n        this.selection.selectAll();\n        this.$blockScrolling -= 1;\n    };\n\n    this.clearSelection = function() {\n        this.selection.clearSelection();\n    };\n\n    this.moveCursorTo = function(row, column) {\n        this.selection.moveCursorTo(row, column);\n    };\n\n    this.moveCursorToPosition = function(pos) {\n        this.selection.moveCursorToPosition(pos);\n    };\n\n    this.jumpToMatching = function() {\n        var cursor = this.getCursorPosition();\n        var pos = this.session.findMatchingBracket(cursor);\n        if (!pos) {\n            cursor.column += 1;\n            pos = this.session.findMatchingBracket(cursor);\n        }\n        if (!pos) {\n            cursor.column -= 2;\n            pos = this.session.findMatchingBracket(cursor);\n        }\n\n        if (pos) {\n            this.clearSelection();\n            this.moveCursorTo(pos.row, pos.column);\n        }\n    };\n\n    this.gotoLine = function(lineNumber, column) {\n        this.selection.clearSelection();\n        this.session.unfold({row: lineNumber - 1, column: column || 0});\n\n        this.$blockScrolling += 1;\n        this.moveCursorTo(lineNumber-1, column || 0);\n        this.$blockScrolling -= 1;\n        if (!this.isRowFullyVisible(this.getCursorPosition().row))\n            this.scrollToLine(lineNumber, true);\n    };\n\n    this.navigateTo = function(row, column) {\n        this.clearSelection();\n        this.moveCursorTo(row, column);\n    };\n\n    this.navigateUp = function(times) {\n        this.selection.clearSelection();\n        times = times || 1;\n        this.selection.moveCursorBy(-times, 0);\n    };\n\n    this.navigateDown = function(times) {\n        this.selection.clearSelection();\n        times = times || 1;\n        this.selection.moveCursorBy(times, 0);\n    };\n\n    this.navigateLeft = function(times) {\n        if (!this.selection.isEmpty()) {\n            var selectionStart = this.getSelectionRange().start;\n            this.moveCursorToPosition(selectionStart);\n        }\n        else {\n            times = times || 1;\n            while (times--) {\n                this.selection.moveCursorLeft();\n            }\n        }\n        this.clearSelection();\n    };\n\n    this.navigateRight = function(times) {\n        if (!this.selection.isEmpty()) {\n            var selectionEnd = this.getSelectionRange().end;\n            this.moveCursorToPosition(selectionEnd);\n        }\n        else {\n            times = times || 1;\n            while (times--) {\n                this.selection.moveCursorRight();\n            }\n        }\n        this.clearSelection();\n    };\n\n    this.navigateLineStart = function() {\n        this.selection.moveCursorLineStart();\n        this.clearSelection();\n    };\n\n    this.navigateLineEnd = function() {\n        this.selection.moveCursorLineEnd();\n        this.clearSelection();\n    };\n\n    this.navigateFileEnd = function() {\n        this.selection.moveCursorFileEnd();\n        this.clearSelection();\n    };\n\n    this.navigateFileStart = function() {\n        this.selection.moveCursorFileStart();\n        this.clearSelection();\n    };\n\n    this.navigateWordRight = function() {\n        this.selection.moveCursorWordRight();\n        this.clearSelection();\n    };\n\n    this.navigateWordLeft = function() {\n        this.selection.moveCursorWordLeft();\n        this.clearSelection();\n    };\n\n    this.replace = function(replacement, options) {\n        if (options)\n            this.$search.set(options);\n\n        var range = this.$search.find(this.session);\n        var replaced = 0;\n        if (!range)\n            return replaced;\n\n        if (this.$tryReplace(range, replacement)) {\n            replaced = 1;\n        }\n        if (range !== null) {\n            this.selection.setSelectionRange(range);\n            this.renderer.scrollSelectionIntoView(range.start, range.end);\n        }\n\n        return replaced;\n    };\n\n    this.replaceAll = function(replacement, options) {\n        if (options) {\n            this.$search.set(options);\n        }\n\n        var ranges = this.$search.findAll(this.session);\n        var replaced = 0;\n        if (!ranges.length)\n            return replaced;\n\n        this.$blockScrolling += 1;\n\n        var selection = this.getSelectionRange();\n        this.clearSelection();\n        this.selection.moveCursorTo(0, 0);\n\n        for (var i = ranges.length - 1; i >= 0; --i) {\n            if(this.$tryReplace(ranges[i], replacement)) {\n                replaced++;\n            }\n        }\n\n        this.selection.setSelectionRange(selection);\n        this.$blockScrolling -= 1;\n\n        return replaced;\n    };\n\n    this.$tryReplace = function(range, replacement) {\n        var input = this.session.getTextRange(range);\n        replacement = this.$search.replace(input, replacement);\n        if (replacement !== null) {\n            range.end = this.session.replace(range, replacement);\n            return range;\n        } else {\n            return null;\n        }\n    };\n\n    this.getLastSearchOptions = function() {\n        return this.$search.getOptions();\n    };\n\n    this.find = function(needle, options) {\n        this.clearSelection();\n        options = options || {};\n        options.needle = needle;\n        this.$search.set(options);\n        this.$find();\n    };\n\n    this.findNext = function(options) {\n        options = options || {};\n        if (typeof options.backwards == \"undefined\")\n            options.backwards = false;\n        this.$search.set(options);\n        this.$find();\n    };\n\n    this.findPrevious = function(options) {\n        options = options || {};\n        if (typeof options.backwards == \"undefined\")\n            options.backwards = true;\n        this.$search.set(options);\n        this.$find();\n    };\n\n    this.$find = function(backwards) {\n        if (!this.selection.isEmpty())\n            this.$search.set({needle: this.session.getTextRange(this.getSelectionRange())});\n\n        if (typeof backwards != \"undefined\")\n            this.$search.set({backwards: backwards});\n\n        var range = this.$search.find(this.session);\n        if (range) {\n            this.session.unfold(range);\n\n            this.$blockScrolling += 1;\n            this.selection.setSelectionRange(range);\n            this.$blockScrolling -= 1;\n\n            if (this.getAnimatedScroll()) {\n                var cursor = this.getCursorPosition();\n                if (!this.isRowFullyVisible(cursor.row))\n                    this.scrollToLine(cursor.row, true);\n    \n                //@todo scroll X\n                //if (!this.isColumnFullyVisible(cursor.column))\n                    //this.scrollToRow(cursor.column);\n            }\n            else {\n                this.renderer.scrollSelectionIntoView(range.start, range.end);\n            }\n        }\n    };\n\n    this.undo = function() {\n        this.session.getUndoManager().undo();\n    };\n\n    this.redo = function() {\n        this.session.getUndoManager().redo();\n    };\n\n    this.destroy = function() {\n        this.renderer.destroy();\n    };\n\n}).call(Editor.prototype);\n\n\nexports.Editor = Editor;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/editor_change_document_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n    require(\"./test/mockdom\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"./edit_session\").EditSession;\nvar Editor = require(\"./editor\").Editor;\nvar Text = require(\"./mode/text\").Mode;\nvar JavaScriptMode = require(\"./mode/javascript\").Mode;\nvar CssMode = require(\"./mode/css\").Mode;\nvar HtmlMode = require(\"./mode/html\").Mode;\nvar MockRenderer = require(\"./test/mockrenderer\").MockRenderer;\nvar assert = require(\"./test/assertions\");\n\nmodule.exports = {\n\n    setUp : function(next) {\n        this.session1 = new EditSession([\"abc\", \"def\"]);\n        this.session2 = new EditSession([\"ghi\", \"jkl\"]);\n        \n        \n        this.editor = new Editor(new MockRenderer());\n        next();\n    },\n\n    \"test: change document\" : function() {\n        this.editor.setSession(this.session1);\n        assert.equal(this.editor.getSession(), this.session1);\n\n        this.editor.setSession(this.session2);\n        assert.equal(this.editor.getSession(), this.session2);\n    },\n\n    \"test: only changes to the new document should have effect\" : function() {\n        var called = false;\n        this.editor.onDocumentChange = function() {\n            called = true;\n        };\n\n        this.editor.setSession(this.session1);\n        this.editor.setSession(this.session2);\n\n        this.session1.duplicateLines(0, 0);\n        assert.notOk(called);\n\n        this.session2.duplicateLines(0, 0);\n        assert.ok(called);\n    },\n\n    \"test: should use cursor of new document\" : function() {\n        this.session1.getSelection().moveCursorTo(0, 1);\n        this.session2.getSelection().moveCursorTo(1, 0);\n\n        this.editor.setSession(this.session1);\n        assert.position(this.editor.getCursorPosition(), 0, 1);\n\n        this.editor.setSession(this.session2);\n        assert.position(this.editor.getCursorPosition(), 1, 0);\n    },\n\n    \"test: only changing the cursor of the new doc should not have an effect\" : function() {\n        this.editor.onCursorChange = function() {\n            called = true;\n        };\n\n        this.editor.setSession(this.session1);\n        this.editor.setSession(this.session2);\n        assert.position(this.editor.getCursorPosition(), 0, 0);\n\n        var called = false;\n        this.session1.getSelection().moveCursorTo(0, 1);\n        assert.position(this.editor.getCursorPosition(), 0, 0);\n        assert.notOk(called);\n\n        this.session2.getSelection().moveCursorTo(1, 1);\n        assert.position(this.editor.getCursorPosition(), 1, 1);\n        assert.ok(called);\n    },\n\n    \"test: should use selection of new document\" : function() {\n        this.session1.getSelection().selectTo(0, 1);\n        this.session2.getSelection().selectTo(1, 0);\n\n        this.editor.setSession(this.session1);\n        assert.position(this.editor.getSelection().getSelectionLead(), 0, 1);\n\n        this.editor.setSession(this.session2);\n        assert.position(this.editor.getSelection().getSelectionLead(), 1, 0);\n    },\n\n    \"test: only changing the selection of the new doc should not have an effect\" : function() {\n        this.editor.onSelectionChange = function() {\n            called = true;\n        };\n\n        this.editor.setSession(this.session1);\n        this.editor.setSession(this.session2);\n        assert.position(this.editor.getSelection().getSelectionLead(), 0, 0);\n\n        var called = false;\n        this.session1.getSelection().selectTo(0, 1);\n        assert.position(this.editor.getSelection().getSelectionLead(), 0, 0);\n        assert.notOk(called);\n\n        this.session2.getSelection().selectTo(1, 1);\n        assert.position(this.editor.getSelection().getSelectionLead(), 1, 1);\n        assert.ok(called);\n    },\n\n    \"test: should use mode of new document\" : function() {\n        this.editor.onChangeMode = function() {\n            called = true;\n        };\n        this.editor.setSession(this.session1);\n        this.editor.setSession(this.session2);\n\n        var called = false;\n        this.session1.setMode(new Text());\n        assert.notOk(called);\n\n        this.session2.setMode(new JavaScriptMode());\n        assert.ok(called);\n    },\n    \n    \"test: should use stop worker of old document\" : function(next) {\n        var self = this;\n        \n        // 1. Open an editor and set the session to CssMode\n        self.editor.setSession(self.session1);\n        self.session1.setMode(new CssMode());\n        \n        // 2. Add a line or two of valid CSS.\n        self.session1.setValue(\"DIV { color: red; }\");\n        \n        // 3. Clear the session value.\n        self.session1.setValue(\"\");\n        \n        // 4. Set the session to HtmlMode\n        self.session1.setMode(new HtmlMode());\n\n        // 5. Try to type valid HTML\n        self.session1.insert({row: 0, column: 0}, \"<html></html>\");\n        \n        setTimeout(function() {\n            assert.equal(Object.keys(self.session1.getAnnotations()).length, 0);\n            next();\n        }, 600);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/editor_highlight_selected_word_test.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Mihai Sucan.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *   Mihai Sucan <mihai.sucan@gmail.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n    require(\"./test/mockdom\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"./edit_session\").EditSession;\nvar Editor = require(\"./editor\").Editor;\nvar MockRenderer = require(\"./test/mockrenderer\").MockRenderer;\nvar assert = require(\"./test/assertions\");\n\nvar lipsum = \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. \" +\n             \"Mauris at arcu mi, eu lobortis mauris. Quisque ut libero eget \" +\n             \"diam congue vehicula. Quisque ut odio ut mi aliquam tincidunt. \" +\n             \"Duis lacinia aliquam lorem eget eleifend. Morbi eget felis mi. \" +\n             \"Duis quam ligula, consequat vitae convallis volutpat, blandit \" +\n             \"nec neque. Nulla facilisi. Etiam suscipit lorem ac justo \" +\n             \"sollicitudin tristique. Phasellus ut posuere nunc. Aliquam \" +\n             \"scelerisque mollis felis non gravida. Vestibulum lacus sem, \" +\n             \"posuere non bibendum id, luctus non dolor. Aenean id metus \" +\n             \"lorem, vel dapibus est. Donec gravida feugiat augue nec \" +\n             \"accumsan.Lorem ipsum dolor sit amet, consectetur adipiscing \" +\n             \"elit. Nulla vulputate, velit vitae tincidunt congue, nunc \" +\n             \"augue accumsan velit, eu consequat turpis lectus ac orci. \" +\n             \"Pellentesque ornare dolor feugiat dui auctor eu varius nulla \" +\n             \"fermentum. Sed aliquam odio at velit lacinia vel fermentum \" +\n             \"felis sodales. In dignissim magna eget nunc lobortis non \" +\n             \"fringilla nibh ullamcorper. Donec facilisis malesuada elit \" +\n             \"at egestas. Etiam bibendum, diam vitae tempor aliquet, dui \" +\n             \"libero vehicula odio, eget bibendum mauris velit eu lorem.\\n\" +\n             \"consectetur\";\n\nmodule.exports = {\n    setUp: function(next) {\n        this.session = new EditSession(lipsum);\n        this.editor = new Editor(new MockRenderer(), this.session);\n        this.selection = this.session.getSelection();\n        this.search = this.editor.$search;\n        next();\n    },\n\n    \"test: highlight selected words by default\": function() {\n        assert.equal(this.editor.getHighlightSelectedWord(), true);\n    },\n\n    \"test: highlight a word\": function() {\n        this.editor.moveCursorTo(0, 9);\n        this.selection.selectWord();\n\n        var range = this.selection.getRange();\n        assert.equal(this.session.getTextRange(range), \"ipsum\");\n        assert.equal(this.session.$selectionOccurrences.length, 1);\n    },\n\n    \"test: highlight a word and clear highlight\": function() {\n        this.editor.moveCursorTo(0, 8);\n        this.selection.selectWord();\n\n        var range = this.selection.getRange();\n        assert.equal(this.session.getTextRange(range), \"ipsum\");\n        assert.equal(this.session.$selectionOccurrences.length, 1);\n\n        this.session.getMode().clearSelectionHighlight(this.editor);\n        assert.equal(this.session.$selectionOccurrences.length, 0);\n    },\n\n    \"test: highlight another word\": function() {\n        this.selection.moveCursorTo(0, 14);\n        this.selection.selectWord();\n\n        var range = this.selection.getRange();\n        assert.equal(this.session.getTextRange(range), \"dolor\");\n        assert.equal(this.session.$selectionOccurrences.length, 3);\n    },\n\n    \"test: no selection, no highlight\": function() {\n        this.selection.clearSelection();\n        assert.equal(this.session.$selectionOccurrences.length, 0);\n    },\n\n    \"test: select a word, no highlight\": function() {\n        this.editor.setHighlightSelectedWord(false);\n        this.selection.moveCursorTo(0, 14);\n        this.selection.selectWord();\n\n        var range = this.selection.getRange();\n        assert.equal(this.session.getTextRange(range), \"dolor\");\n        assert.equal(this.session.$selectionOccurrences.length, 0);\n    },\n\n    \"test: select a word with no matches\": function() {\n        this.editor.setHighlightSelectedWord(true);\n\n        var currentOptions = this.search.getOptions();\n        var newOptions = {\n            wrap: true,\n            wholeWord: true,\n            caseSensitive: true,\n            needle: \"Mauris\"\n        };\n        this.search.set(newOptions);\n\n        var match = this.search.find(this.session);\n        assert.notEqual(match, null, \"found a match for 'Mauris'\");\n\n        this.search.set(currentOptions);\n\n        this.selection.setSelectionRange(match);\n\n        assert.equal(this.session.getTextRange(match), \"Mauris\");\n        assert.equal(this.session.$selectionOccurrences.length, 0);\n    },\n\n    \"test: partial word selection 1\": function() {\n        this.selection.moveCursorTo(0, 14);\n        this.selection.selectWord();\n        this.selection.selectLeft();\n\n        var range = this.selection.getRange();\n        assert.equal(this.session.getTextRange(range), \"dolo\");\n        assert.equal(this.session.$selectionOccurrences.length, 0);\n    },\n\n    \"test: partial word selection 2\": function() {\n        this.selection.moveCursorTo(0, 13);\n        this.selection.selectWord();\n        this.selection.selectRight();\n\n        var range = this.selection.getRange();\n        assert.equal(this.session.getTextRange(range), \"dolor \");\n        assert.equal(this.session.$selectionOccurrences.length, 0);\n    },\n\n    \"test: partial word selection 3\": function() {\n        this.selection.moveCursorTo(0, 14);\n        this.selection.selectWord();\n        this.selection.selectLeft();\n        this.selection.shiftSelection(1);\n\n        var range = this.selection.getRange();\n        assert.equal(this.session.getTextRange(range), \"olor\");\n        assert.equal(this.session.$selectionOccurrences.length, 0);\n    },\n\n    \"test: select last word\": function() {\n        this.selection.moveCursorTo(0, 1);\n\n        var currentOptions = this.search.getOptions();\n        var newOptions = {\n            wrap: true,\n            wholeWord: true,\n            caseSensitive: true,\n            backwards: true,\n            needle: \"consectetur\"\n        };\n        this.search.set(newOptions);\n\n        var match = this.search.find(this.session);\n        assert.notEqual(match, null, \"found a match for 'consectetur'\");\n        assert.position(match.start, 1, 0);\n\n        this.search.set(currentOptions);\n\n        this.selection.setSelectionRange(match);\n\n        assert.equal(this.session.getTextRange(match), \"consectetur\");\n        assert.equal(this.session.$selectionOccurrences.length, 2);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/editor_navigation_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n    require(\"./test/mockdom\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"./edit_session\").EditSession;\nvar Editor = require(\"./editor\").Editor;\nvar MockRenderer = require(\"./test/mockrenderer\").MockRenderer;\nvar assert = require(\"./test/assertions\");\n\nmodule.exports = {\n    createEditSession : function(rows, cols) {\n        var line = new Array(cols + 1).join(\"a\");\n        var text = new Array(rows).join(line + \"\\n\") + line;\n        return new EditSession(text);\n    },\n\n    \"test: navigate to end of file should scroll the last line into view\" : function() {\n        var doc = this.createEditSession(200, 10);\n        var editor = new Editor(new MockRenderer(), doc);\n\n        editor.navigateFileEnd();\n        var cursor = editor.getCursorPosition();\n\n        assert.ok(editor.getFirstVisibleRow() <= cursor.row);\n        assert.ok(editor.getLastVisibleRow() >= cursor.row);\n    },\n\n    \"test: navigate to start of file should scroll the first row into view\" : function() {\n        var doc = this.createEditSession(200, 10);\n        var editor = new Editor(new MockRenderer(), doc);\n\n        editor.moveCursorTo(editor.getLastVisibleRow() + 20);\n        editor.navigateFileStart();\n\n        assert.equal(editor.getFirstVisibleRow(), 0);\n    },\n\n    \"test: goto hidden line should scroll the line into the middle of the viewport\" : function() {\n        var editor = new Editor(new MockRenderer(), this.createEditSession(200, 5));\n\n        editor.navigateTo(0, 0);\n        editor.gotoLine(101);\n        assert.position(editor.getCursorPosition(), 100, 0);\n        assert.equal(editor.getFirstVisibleRow(), 90);\n\n        editor.navigateTo(100, 0);\n        editor.gotoLine(11);\n        assert.position(editor.getCursorPosition(), 10, 0);\n        assert.equal(editor.getFirstVisibleRow(), 0);\n\n        editor.navigateTo(100, 0);\n        editor.gotoLine(6);\n        assert.position(editor.getCursorPosition(), 5, 0);\n        assert.equal(0, editor.getFirstVisibleRow(), 0);\n\n        editor.navigateTo(100, 0);\n        editor.gotoLine(1);\n        assert.position(editor.getCursorPosition(), 0, 0);\n        assert.equal(editor.getFirstVisibleRow(), 0);\n\n        editor.navigateTo(0, 0);\n        editor.gotoLine(191);\n        assert.position(editor.getCursorPosition(), 190, 0);\n        assert.equal(editor.getFirstVisibleRow(), 180);\n\n        editor.navigateTo(0, 0);\n        editor.gotoLine(196);\n        assert.position(editor.getCursorPosition(), 195, 0);\n        assert.equal(editor.getFirstVisibleRow(), 180);\n    },\n\n    \"test: goto visible line should only move the cursor and not scroll\": function() {\n        var editor = new Editor(new MockRenderer(), this.createEditSession(200, 5));\n\n        editor.navigateTo(0, 0);\n        editor.gotoLine(12);\n        assert.position(editor.getCursorPosition(), 11, 0);\n        assert.equal(editor.getFirstVisibleRow(), 0);\n\n        editor.navigateTo(30, 0);\n        editor.gotoLine(33);\n        assert.position(editor.getCursorPosition(), 32, 0);\n        assert.equal(editor.getFirstVisibleRow(), 30);\n    },\n\n    \"test: navigate from the end of a long line down to a short line and back should maintain the curser column\": function() {\n        var editor = new Editor(new MockRenderer(), new EditSession([\"123456\", \"1\"]));\n\n        editor.navigateTo(0, 6);\n        assert.position(editor.getCursorPosition(), 0, 6);\n\n        editor.navigateDown();\n        assert.position(editor.getCursorPosition(), 1, 1);\n\n        editor.navigateUp();\n        assert.position(editor.getCursorPosition(), 0, 6);\n    },\n\n    \"test: reset desired column on navigate left or right\": function() {\n        var editor = new Editor(new MockRenderer(), new EditSession([\"123456\", \"12\"]));\n\n        editor.navigateTo(0, 6);\n        assert.position(editor.getCursorPosition(), 0, 6);\n\n        editor.navigateDown();\n        assert.position(editor.getCursorPosition(), 1, 2);\n\n        editor.navigateLeft();\n        assert.position(editor.getCursorPosition(), 1, 1);\n\n        editor.navigateUp();\n        assert.position(editor.getCursorPosition(), 0, 1);\n    },\n    \n    \"test: typing text should update the desired column\": function() {\n        var editor = new Editor(new MockRenderer(), new EditSession([\"1234\", \"1234567890\"]));\n\n        editor.navigateTo(0, 3);\n        editor.insert(\"juhu\");\n        \n        editor.navigateDown();\n        assert.position(editor.getCursorPosition(), 1, 7);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/editor_text_edit_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n    require(\"./test/mockdom\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"./edit_session\").EditSession;\nvar Editor = require(\"./editor\").Editor;\nvar JavaScriptMode = require(\"./mode/javascript\").Mode;\nvar UndoManager = require(\"./undomanager\").UndoManager;\nvar MockRenderer = require(\"./test/mockrenderer\").MockRenderer;\nvar assert = require(\"./test/assertions\");\n\nmodule.exports = {\n    \"test: delete line from the middle\" : function() {\n        var session = new EditSession([\"a\", \"b\", \"c\", \"d\"].join(\"\\n\"));\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(1, 1);\n        editor.removeLines();\n\n        assert.equal(session.toString(), \"a\\nc\\nd\");\n        assert.position(editor.getCursorPosition(), 1, 0);\n\n        editor.removeLines();\n\n        assert.equal(session.toString(), \"a\\nd\");\n        assert.position(editor.getCursorPosition(), 1, 0);\n\n        editor.removeLines();\n\n        assert.equal(session.toString(), \"a\");\n        assert.position(editor.getCursorPosition(), 0, 1);\n\n        editor.removeLines();\n\n        assert.equal(session.toString(), \"\");\n        assert.position(editor.getCursorPosition(), 0, 0);\n    },\n\n    \"test: delete multiple selected lines\" : function() {\n        var session = new EditSession([\"a\", \"b\", \"c\", \"d\"].join(\"\\n\"));\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(1, 1);\n        editor.getSelection().selectDown();\n\n        editor.removeLines();\n        assert.equal(session.toString(), \"a\\nd\");\n        assert.position(editor.getCursorPosition(), 1, 0);\n    },\n\n    \"test: delete first line\" : function() {\n        var session = new EditSession([\"a\", \"b\", \"c\"].join(\"\\n\"));\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.removeLines();\n\n        assert.equal(session.toString(), \"b\\nc\");\n        assert.position(editor.getCursorPosition(), 0, 0);\n    },\n\n    \"test: delete last should also delete the new line of the previous line\" : function() {\n        var session = new EditSession([\"a\", \"b\", \"c\", \"\"].join(\"\\n\"));\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(3, 0);\n\n        editor.removeLines();\n        assert.equal(session.toString(), \"a\\nb\\nc\");\n        assert.position(editor.getCursorPosition(), 2, 1);\n\n        editor.removeLines();\n        assert.equal(session.toString(), \"a\\nb\");\n        assert.position(editor.getCursorPosition(), 1, 1);\n    },\n\n    \"test: indent block\" : function() {\n        var session = new EditSession([\"a12345\", \"b12345\", \"c12345\"].join(\"\\n\"));\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(1, 3);\n        editor.getSelection().selectDown();\n\n        editor.indent();\n\n        assert.equal([\"a12345\", \"    b12345\", \"    c12345\"].join(\"\\n\"), session.toString());\n\n        assert.position(editor.getCursorPosition(), 2, 7);\n\n        var range = editor.getSelectionRange();\n        assert.position(range.start, 1, 7);\n        assert.position(range.end, 2, 7);\n    },\n\n    \"test: indent selected lines\" : function() {\n        var session = new EditSession([\"a12345\", \"b12345\", \"c12345\"].join(\"\\n\"));\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(1, 0);\n        editor.getSelection().selectDown();\n\n        editor.indent();\n        assert.equal([\"a12345\", \"    b12345\", \"c12345\"].join(\"\\n\"), session.toString());\n    },\n\n    \"test: no auto indent if cursor is before the {\" : function() {\n        var session = new EditSession(\"{\", new JavaScriptMode());\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(0, 0);\n        editor.onTextInput(\"\\n\");\n        assert.equal([\"\", \"{\"].join(\"\\n\"), session.toString());\n    },\n\t\n    \"test: outdent block\" : function() {\n        var session = new EditSession([\"        a12345\", \"    b12345\", \"        c12345\"].join(\"\\n\"));\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(0, 5);\n        editor.getSelection().selectDown();\n        editor.getSelection().selectDown();\n\n        editor.blockOutdent();\n        assert.equal(session.toString(), [\"    a12345\", \"b12345\", \"    c12345\"].join(\"\\n\"));\n\n        assert.position(editor.getCursorPosition(), 2, 1);\n\n        var range = editor.getSelectionRange();\n        assert.position(range.start, 0, 1);\n        assert.position(range.end, 2, 1);\n\n        editor.blockOutdent();\n        assert.equal(session.toString(), [\"a12345\", \"b12345\", \"c12345\"].join(\"\\n\"));\n\n        var range = editor.getSelectionRange();\n        assert.position(range.start, 0, 0);\n        assert.position(range.end, 2, 0);\n    },\n\n    \"test: outent without a selection should update cursor\" : function() {\n        var session = new EditSession(\"        12\");\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(0, 3);\n        editor.blockOutdent(\"  \");\n\n        assert.equal(session.toString(), \"    12\");\n        assert.position(editor.getCursorPosition(), 0, 0);\n    },\n\n    \"test: comment lines should perserve selection\" : function() {\n        var session = new EditSession([\"  abc\", \"cde\"].join(\"\\n\"), new JavaScriptMode());\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(0, 2);\n        editor.getSelection().selectDown();\n        editor.toggleCommentLines();\n\n        assert.equal([\"//  abc\", \"//cde\"].join(\"\\n\"), session.toString());\n\n        var selection = editor.getSelectionRange();\n        assert.position(selection.start, 0, 4);\n        assert.position(selection.end, 1, 4);\n    },\n\n    \"test: uncomment lines should perserve selection\" : function() {\n        var session = new EditSession([\"//  abc\", \"//cde\"].join(\"\\n\"), new JavaScriptMode());\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(0, 1);\n        editor.getSelection().selectDown();\n        editor.getSelection().selectRight();\n        editor.getSelection().selectRight();\n\n        editor.toggleCommentLines();\n\n        assert.equal([\"  abc\", \"cde\"].join(\"\\n\"), session.toString());\n        assert.range(editor.getSelectionRange(), 0, 0, 1, 1);\n    },\n\n    \"test: toggle comment lines twice should return the original text\" : function() {\n        var session = new EditSession([\"  abc\", \"cde\", \"fg\"], new JavaScriptMode());\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(0, 0);\n        editor.getSelection().selectDown();\n        editor.getSelection().selectDown();\n\n        editor.toggleCommentLines();\n        editor.toggleCommentLines();\n\n        assert.equal([\"  abc\", \"cde\", \"fg\"].join(\"\\n\"), session.toString());\n    },\n\n\n    \"test: comment lines - if the selection end is at the line start it should stay there\": function() {\n        //select down\n        var session = new EditSession([\"abc\", \"cde\"].join(\"\\n\"), new JavaScriptMode());\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(0, 0);\n        editor.getSelection().selectDown();\n\n        editor.toggleCommentLines();\n        assert.range(editor.getSelectionRange(), 0, 2, 1, 0);\n\n        // select up\n        var session = new EditSession([\"abc\", \"cde\"].join(\"\\n\"), new JavaScriptMode());\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(1, 0);\n        editor.getSelection().selectUp();\n\n        editor.toggleCommentLines();\n        assert.range(editor.getSelectionRange(), 0, 2, 1, 0);\n    },\n\n    \"test: move lines down should select moved lines\" : function() {\n        var session = new EditSession([\"11\", \"22\", \"33\", \"44\"].join(\"\\n\"));\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(0, 1);\n        editor.getSelection().selectDown();\n\n        editor.moveLinesDown();\n        assert.equal([\"33\", \"11\", \"22\", \"44\"].join(\"\\n\"), session.toString());\n        assert.position(editor.getCursorPosition(), 1, 0);\n        assert.position(editor.getSelection().getSelectionAnchor(), 3, 0);\n        assert.position(editor.getSelection().getSelectionLead(), 1, 0);\n\n        editor.moveLinesDown();\n        assert.equal([\"33\", \"44\", \"11\", \"22\"].join(\"\\n\"), session.toString());\n        assert.position(editor.getCursorPosition(), 2, 0);\n        assert.position(editor.getSelection().getSelectionAnchor(), 3, 2);\n        assert.position(editor.getSelection().getSelectionLead(), 2, 0);\n\n        // moving again should have no effect\n        editor.moveLinesDown();\n        assert.equal([\"33\", \"44\", \"11\", \"22\"].join(\"\\n\"), session.toString());\n        assert.position(editor.getCursorPosition(), 2, 0);\n        assert.position(editor.getSelection().getSelectionAnchor(), 3, 2);\n        assert.position(editor.getSelection().getSelectionLead(), 2, 0);\n    },\n\n    \"test: move lines up should select moved lines\" : function() {\n        var session = new EditSession([\"11\", \"22\", \"33\", \"44\"].join(\"\\n\"));\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(2, 1);\n        editor.getSelection().selectDown();\n\n        editor.moveLinesUp();\n        assert.equal(session.toString(), [\"11\", \"33\", \"44\", \"22\"].join(\"\\n\"));\n        assert.position(editor.getCursorPosition(), 1, 0);\n        assert.position(editor.getSelection().getSelectionAnchor(), 3, 0);\n        assert.position(editor.getSelection().getSelectionLead(), 1, 0);\n\n        editor.moveLinesUp();\n        assert.equal(session.toString(), [\"33\", \"44\", \"11\", \"22\"].join(\"\\n\"));\n        assert.position(editor.getCursorPosition(), 0, 0);\n        assert.position(editor.getSelection().getSelectionAnchor(), 2, 0);\n        assert.position(editor.getSelection().getSelectionLead(), 0, 0);\n    },\n\n    \"test: move line without active selection should not move cursor relative to the moved line\" : function()\n    {\n        var session = new EditSession([\"11\", \"22\", \"33\", \"44\"].join(\"\\n\"));\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(1, 1);\n        editor.clearSelection();\n\n        editor.moveLinesDown();\n        assert.equal([\"11\", \"33\", \"22\", \"44\"].join(\"\\n\"), session.toString());\n        assert.position(editor.getCursorPosition(), 2, 1);\n\n        editor.clearSelection();\n\n        editor.moveLinesUp();\n        assert.equal([\"11\", \"22\", \"33\", \"44\"].join(\"\\n\"), session.toString());\n        assert.position(editor.getCursorPosition(), 1, 1);\n    },\n\n    \"test: copy lines down should select lines and place cursor at the selection start\" : function() {\n        var session = new EditSession([\"11\", \"22\", \"33\", \"44\"].join(\"\\n\"));\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(1, 1);\n        editor.getSelection().selectDown();\n\n        editor.copyLinesDown();\n        assert.equal([\"11\", \"22\", \"33\", \"22\", \"33\", \"44\"].join(\"\\n\"), session.toString());\n\n        assert.position(editor.getCursorPosition(), 3, 0);\n        assert.position(editor.getSelection().getSelectionAnchor(), 5, 0);\n        assert.position(editor.getSelection().getSelectionLead(), 3, 0);\n    },\n\n    \"test: copy lines up should select lines and place cursor at the selection start\" : function() {\n        var session = new EditSession([\"11\", \"22\", \"33\", \"44\"].join(\"\\n\"));\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.moveCursorTo(1, 1);\n        editor.getSelection().selectDown();\n\n        editor.copyLinesUp();\n        assert.equal([\"11\", \"22\", \"33\", \"22\", \"33\", \"44\"].join(\"\\n\"), session.toString());\n\n        assert.position(editor.getCursorPosition(), 1, 0);\n        assert.position(editor.getSelection().getSelectionAnchor(), 3, 0);\n        assert.position(editor.getSelection().getSelectionLead(), 1, 0);\n    },\n\n    \"test: input a tab with soft tab should convert it to spaces\" : function() {\n        var session = new EditSession(\"\");\n        var editor = new Editor(new MockRenderer(), session);\n\n        session.setTabSize(2);\n        session.setUseSoftTabs(true);\n\n        editor.onTextInput(\"\\t\");\n        assert.equal(session.toString(), \"  \");\n\n        session.setTabSize(5);\n        editor.onTextInput(\"\\t\");\n        assert.equal(session.toString(), \"       \");\n    },\n\n    \"test: input tab without soft tabs should keep the tab character\" : function() {\n        var session = new EditSession(\"\");\n        var editor = new Editor(new MockRenderer(), session);\n\n        session.setUseSoftTabs(false);\n\n        editor.onTextInput(\"\\t\");\n        assert.equal(session.toString(), \"\\t\");\n    },\n\n    \"test: undo/redo for delete line\" : function() {\n        var session = new EditSession([\"111\", \"222\", \"333\"]);\n        var undoManager = new UndoManager();\n        session.setUndoManager(undoManager);\n\n        var initialText = session.toString();\n        var editor = new Editor(new MockRenderer(), session);\n\n        editor.removeLines();\n        var step1 = session.toString();\n        assert.equal(step1, \"222\\n333\");\n        session.$syncInformUndoManager();\n\n        editor.removeLines();\n        var step2 = session.toString();\n        assert.equal(step2, \"333\");\n        session.$syncInformUndoManager();\n\n        editor.removeLines();\n        var step3 = session.toString();\n        assert.equal(step3, \"\");\n        session.$syncInformUndoManager();\n\n        undoManager.undo();\n        session.$syncInformUndoManager();\n        assert.equal(session.toString(), step2);\n\n        undoManager.undo();\n        session.$syncInformUndoManager();\n        assert.equal(session.toString(), step1);\n\n        undoManager.undo();\n        session.$syncInformUndoManager();\n        assert.equal(session.toString(), initialText);\n\n        undoManager.undo();\n        session.$syncInformUndoManager();\n        assert.equal(session.toString(), initialText);\n    },\n\n    \"test: remove left should remove character left of the cursor\" : function() {\n        var session = new EditSession([\"123\", \"456\"]);\n\n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 1);\n        editor.remove(\"left\");\n        assert.equal(session.toString(), \"123\\n56\");\n    },\n\n    \"test: remove left should remove line break if cursor is at line start\" : function() {\n        var session = new EditSession([\"123\", \"456\"]);\n\n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 0);\n        editor.remove(\"left\");\n        assert.equal(session.toString(), \"123456\");\n    },\n\n    \"test: remove left should remove tabsize spaces if cursor is on a tab stop and preceeded by spaces\" : function() {\n        var session = new EditSession([\"123\", \"        456\"]);\n        session.setUseSoftTabs(true);\n        session.setTabSize(4);\n\n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 8);\n        editor.remove(\"left\");\n        assert.equal(session.toString(), \"123\\n    456\");\n    },\n    \n    \"test: transpose at line start should be a noop\": function() {\n        var session = new EditSession([\"123\", \"4567\", \"89\"]);\n        \n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 0);\n        editor.transposeLetters();\n        \n        assert.equal(session.getValue(), [\"123\", \"4567\", \"89\"].join(\"\\n\"));\n    },\n    \n    \"test: transpose in line should swap the charaters before and after the cursor\": function() {\n        var session = new EditSession([\"123\", \"4567\", \"89\"]);\n        \n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 2);\n        editor.transposeLetters();\n        \n        assert.equal(session.getValue(), [\"123\", \"4657\", \"89\"].join(\"\\n\"));\n    },\n    \n    \"test: transpose at line end should swap the last two characters\": function() {\n        var session = new EditSession([\"123\", \"4567\", \"89\"]);\n        \n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 4);\n        editor.transposeLetters();\n        \n        assert.equal(session.getValue(), [\"123\", \"4576\", \"89\"].join(\"\\n\"));\n    },\n    \n    \"test: transpose with non empty selection should be a noop\": function() {\n        var session = new EditSession([\"123\", \"4567\", \"89\"]);\n        \n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 1);\n        editor.getSelection().selectRight();\n        editor.transposeLetters();\n        \n        assert.equal(session.getValue(), [\"123\", \"4567\", \"89\"].join(\"\\n\"));\n    },\n    \n    \"test: transpose should move the cursor behind the last swapped character\": function() {\n        var session = new EditSession([\"123\", \"4567\", \"89\"]);\n        \n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 2);\n        editor.transposeLetters();\n        assert.position(editor.getCursorPosition(), 1, 3);\n    },\n    \n    \"test: remove to line end\": function() {\n        var session = new EditSession([\"123\", \"4567\", \"89\"]);\n        \n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 2);\n        editor.removeToLineEnd();\n        assert.equal(session.getValue(), [\"123\", \"45\", \"89\"].join(\"\\n\"));\n    },\n    \n    \"test: remove to line end at line end should remove the new line\": function() {\n        var session = new EditSession([\"123\", \"4567\", \"89\"]);\n        \n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 4);\n        editor.removeToLineEnd();\n        assert.position(editor.getCursorPosition(), 1, 4);\n        assert.equal(session.getValue(), [\"123\", \"456789\"].join(\"\\n\"));\n    },\n\n    \"test: transform selection to uppercase\": function() {\n        var session = new EditSession([\"ajax\", \"dot\", \"org\"]);\n\n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 0);\n        editor.getSelection().selectLineEnd();\n        editor.toUpperCase()\n        assert.equal(session.getValue(), [\"ajax\", \"DOT\", \"org\"].join(\"\\n\"));\n    },\n\n    \"test: transform word to uppercase\": function() {\n        var session = new EditSession([\"ajax\", \"dot\", \"org\"]);\n\n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 0);\n        editor.toUpperCase()\n        assert.equal(session.getValue(), [\"ajax\", \"DOT\", \"org\"].join(\"\\n\"));\n        assert.position(editor.getCursorPosition(), 1, 0);\n    },\n\n    \"test: transform selection to lowercase\": function() {\n        var session = new EditSession([\"AJAX\", \"DOT\", \"ORG\"]);\n\n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 0);\n        editor.getSelection().selectLineEnd();\n        editor.toLowerCase()\n        assert.equal(session.getValue(), [\"AJAX\", \"dot\", \"ORG\"].join(\"\\n\"));\n    },\n\n    \"test: transform word to lowercase\": function() {\n        var session = new EditSession([\"AJAX\", \"DOT\", \"ORG\"]);\n\n        var editor = new Editor(new MockRenderer(), session);\n        editor.moveCursorTo(1, 0);\n        editor.toLowerCase()\n        assert.equal(session.getValue(), [\"AJAX\", \"dot\", \"ORG\"].join(\"\\n\"));\n        assert.position(editor.getCursorPosition(), 1, 0);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/ext/static.css",
    "content": ".ace_editor {\n   font-family: 'Monaco', 'Menlo', 'Droid Sans Mono', 'Courier New', monospace;\n   font-size: 12px;\n}\n\n.ace_editor .ace_gutter { \n    width: 25px !important;\n    display: block;\n    float: left;\n    text-align: right; \n    padding: 0 3px 0 0; \n    margin-right: 3px;\n}\n\n.ace_line { clear: both; }\n\n*.ace_gutter-cell {\n  -moz-user-select: -moz-none;\n  -khtml-user-select: none;\n  -webkit-user-select: none;\n  user-select: none;\n}"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/ext/static_highlight.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Jan Jongboom <fabian AT ajax DOT org>\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"../edit_session\").EditSession;\nvar TextLayer = require(\"../layer/text\").Text;\nvar baseStyles = require(\"../requirejs/text!./static.css\");\n\n/** Transforms a given input code snippet into HTML using the given mode\n*\n* @param {string} input Code snippet\n* @param {mode} mode Mode loaded from /ace/mode (use 'ServerSideHiglighter.getMode')\n* @param {string} r Code snippet\n* @returns {object} An object containing: html, css\n*/\n\nexports.render = function(input, mode, theme, lineStart) {\n    lineStart = parseInt(lineStart || 1, 10);\n    \n    var session = new EditSession(\"\");\n    session.setMode(mode);\n    session.setUseWorker(false);\n    \n    var textLayer = new TextLayer(document.createElement(\"div\"));\n    textLayer.setSession(session);\n    textLayer.config = {\n        characterWidth: 10,\n        lineHeight: 20\n    };\n    \n    session.setValue(input);\n            \n    var stringBuilder = [];\n    var length =  session.getLength();\n    var tokens = session.getTokens(0, length - 1);\n    \n    for(var ix = 0; ix < length; ix++) {\n        var lineTokens = tokens[ix].tokens;\n        stringBuilder.push(\"<div class='ace_line'>\");\n        stringBuilder.push(\"<span class='ace_gutter ace_gutter-cell' unselectable='on'>\" + (ix + lineStart) + \"</span>\");\n        textLayer.$renderLine(stringBuilder, 0, lineTokens, true);\n        stringBuilder.push(\"</div>\");\n    }\n    \n    // let's prepare the whole html\n    var html = \"<div class=':cssClass'>\\\n        <div class='ace_editor ace_scroller ace_text-layer'>\\\n            :code\\\n        </div>\\\n    </div>\".replace(/:cssClass/, theme.cssClass).replace(/:code/, stringBuilder.join(\"\"));\n        \n    textLayer.destroy();\n            \n    return {\n        css: baseStyles + theme.cssText,\n        html: html\n    };\n};\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/ext/static_highlight_test.js",
    "content": "if (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n    require(\"../test/mockdom\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar assert = require(\"assert\");\nvar highlighter = require(\"./static_highlight\");\nvar JavaScriptMode = require(\"../mode/javascript\").Mode;\n\n// Execution ORDER: test.setUpSuite, setUp, testFn, tearDown, test.tearDownSuite\nmodule.exports = {\n    timeout: 10000,\n    \n    \"test simple snippet\": function(next) {\n        var theme = require(\"../theme/tomorrow\");\n        var snippet = \"/** this is a function\\n\\\n*\\n\\\n*/\\n\\\nfunction hello (a, b, c) {\\n\\\n    console.log(a * b + c + 'sup?');\\n\\\n}\";\n        var mode = new JavaScriptMode();\n        \n        var isError = false, result;\n        try {\n            result = highlighter.render(snippet, mode, theme);\n        }\n        catch (e) {\n            console.log(e);\n            isError = true;\n        }\n        // todo: write something more meaningful\n        assert.equal(isError, false);\n        \n        next();\n    },\n    \n    \"test css from theme is used\": function(next) {\n        var theme = require(\"../theme/tomorrow\");\n        var snippet = \"/** this is a function\\n\\\n*\\n\\\n*/\\n\\\nfunction hello (a, b, c) {\\n\\\n    console.log(a * b + c + 'sup?');\\n\\\n}\";\n        var mode = new JavaScriptMode();\n        \n        var isError = false, result;\n        result = highlighter.render(snippet, mode, theme);\n        \n        assert.ok(result.css.indexOf(theme.cssText) !== -1);\n        \n        next();\n    },\n    \n    \"test theme classname should be in output html\": function (next) {\n        var theme = require(\"../theme/tomorrow\");\n        var snippet = \"/** this is a function\\n\\\n*\\n\\\n*/\\n\\\nfunction hello (a, b, c) {\\n\\\n    console.log(a * b + c + 'sup?');\\n\\\n}\";\n        var mode = new JavaScriptMode();\n        \n        var isError = false, result;\n        result = highlighter.render(snippet, mode, theme);\n        assert.equal(!!result.html.match(/<div class='ace-tomorrow'>/), true);\n        \n        next();\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/ext/textarea.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Mozilla Skywriter.\n *\n * The Initial Developer of the Original Code is\n * Mozilla.\n * Portions created by the Initial Developer are Copyright (C) 2009\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Kevin Dangoor (kdangoor@mozilla.com)\n *      Julian Viereck <julian.viereck@gmail.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Event = require(\"../lib/event\");\nvar UA = require(\"../lib/useragent\");\nvar net = require(\"../lib/net\");\nvar ace = require(\"../ace\");\n\nrequire(\"ace/theme/textmate\");\n\n/**\n * Returns the CSS property of element.\n *   1) If the CSS property is on the style object of the element, use it, OR\n *   2) Compute the CSS property\n *\n * If the property can't get computed, is 'auto' or 'intrinsic', the former\n * calculated property is uesd (this can happen in cases where the textarea\n * is hidden and has no dimension styles).\n */\nvar getCSSProperty = function(element, container, property) {\n    var ret = element.style[property];\n\n    if (!ret) {\n        if (window.getComputedStyle) {\n            ret = window.getComputedStyle(element, '').getPropertyValue(property);\n        } else {\n            ret = element.currentStyle[property];\n        }\n    }\n\n    if (!ret || ret == 'auto' || ret == 'intrinsic') {\n        ret = container.style[property];\n    }\n    return ret;\n};\n\nfunction applyStyles(elm, styles) {\n    for (var style in styles) {\n        elm.style[style] = styles[style];\n    }\n}\n\nfunction setupContainer(element, getValue) {\n        if (element.type != 'textarea') {\n        throw \"Textarea required!\";\n    }\n\n    var parentNode = element.parentNode;\n\n    // This will hold the editor.\n    var container = document.createElement('div');\n\n    // To put Ace in the place of the textarea, we have to copy a few of the\n    // textarea's style attributes to the div container.\n    //\n    // The problem is that the properties have to get computed (they might be\n    // defined by a CSS file on the page - you can't access such rules that\n    // apply to an element via elm.style). Computed properties are converted to\n    // pixels although the dimension might be given as percentage. When the\n    // window resizes, the dimensions defined by percentages changes, so the\n    // properties have to get recomputed to get the new/true pixels.\n    var resizeEvent = function() {\n        var style = 'position:relative;';\n        [\n            'margin-top', 'margin-left', 'margin-right', 'margin-bottom'\n        ].forEach(function(item) {\n            style += item + ':' +\n                        getCSSProperty(element, container, item) + ';';\n        });\n\n        // Calculating the width/height of the textarea is somewhat tricky. To\n        // do it right, you have to include the paddings to the sides as well\n        // (eg. width = width + padding-left, -right).  This works well, as\n        // long as the width of the element is not set or given in pixels. In\n        // this case and after the textarea is hidden, getCSSProperty(element,\n        // container, 'width') will still return pixel value. If the element\n        // has realtiv dimensions (e.g. width='95<percent>')\n        // getCSSProperty(...) will return pixel values only as long as the\n        // textarea is visible. After it is hidden getCSSProperty will return\n        // the relative dimensions as they are set on the element (in the case\n        // of width, 95<percent>).\n        // Making the sum of pixel vaules (e.g. padding) and realtive values\n        // (e.g. <percent>) is not possible. As such the padding styles are\n        // ignored.\n\n        // The complete width is the width of the textarea + the padding\n        // to the left and right.\n        var width = getCSSProperty(element, container, 'width') || (element.clientWidth + \"px\");\n        var height = getCSSProperty(element, container, 'height')  || (element.clientHeight + \"px\");\n        style += 'height:' + height + ';width:' + width + ';';\n\n        // Set the display property to 'inline-block'.\n        style += 'display:inline-block;';\n        container.setAttribute('style', style);\n    };\n    Event.addListener(window, 'resize', resizeEvent);\n\n    // Call the resizeEvent once, so that the size of the container is\n    // calculated.\n    resizeEvent();\n\n    // Insert the div container after the element.\n    if (element.nextSibling) {\n        parentNode.insertBefore(container, element.nextSibling);\n    } else {\n        parentNode.appendChild(container);\n    }\n\n    // Override the forms onsubmit function. Set the innerHTML and value\n    // of the textarea before submitting.\n    while (parentNode !== document) {\n        if (parentNode.tagName.toUpperCase() === 'FORM') {\n            var oldSumit = parentNode.onsubmit;\n            // Override the onsubmit function of the form.\n            parentNode.onsubmit = function(evt) {\n                element.innerHTML = getValue();\n                element.value = getValue();\n                // If there is a onsubmit function already, then call\n                // it with the current context and pass the event.\n                if (oldSumit) {\n                    oldSumit.call(this, evt);\n                }\n            };\n            break;\n        }\n        parentNode = parentNode.parentNode;\n    }\n    return container;\n}\n\nexports.transformTextarea = function(element, loader) {\n    var session;\n    var container = setupContainer(element, function() {\n        return session.getValue();\n    });\n\n    // Hide the element.\n    element.style.display = 'none';\n    container.style.background = 'white';\n\n    //\n    var editorDiv = document.createElement(\"div\");\n    applyStyles(editorDiv, {\n        top: \"0px\",\n        left: \"0px\",\n        right: \"0px\",\n        bottom: \"0px\",\n        border: \"1px solid gray\"\n    });\n    container.appendChild(editorDiv);\n\n    var settingOpener = document.createElement(\"div\");\n    applyStyles(settingOpener, {\n        position: \"absolute\",\n        width: \"15px\",\n        right: \"0px\",\n        bottom: \"0px\",\n        background: \"red\",\n        cursor: \"pointer\",\n        textAlign: \"center\",\n        fontSize: \"12px\"\n    });\n    settingOpener.innerHTML = \"I\";\n\n    var settingDiv = document.createElement(\"div\");\n    var settingDivStyles = {\n        top: \"0px\",\n        left: \"0px\",\n        right: \"0px\",\n        bottom: \"0px\",\n        position: \"absolute\",\n        padding: \"5px\",\n        zIndex: 100,\n        color: \"white\",\n        display: \"none\",\n        overflow: \"auto\",\n        fontSize: \"14px\"\n    };\n    if (!UA.isOldIE) {\n        settingDivStyles.backgroundColor = \"rgba(0, 0, 0, 0.6)\";\n    } else {\n        settingDivStyles.backgroundColor = \"#333\";\n    }\n\n    applyStyles(settingDiv, settingDivStyles);\n    container.appendChild(settingDiv);\n\n    // Power up ace on the textarea:\n    var options = {};\n\n    var editor = ace.edit(editorDiv);\n    session = editor.getSession();\n\n    session.setValue(element.value || element.innerHTML);\n    editor.focus();\n\n    // Add the settingPanel opener to the editor's div.\n    editorDiv.appendChild(settingOpener);\n\n    // Create the API.\n    var api = setupApi(editor, editorDiv, settingDiv, ace, options, loader);\n\n    // Create the setting's panel.\n    setupSettingPanel(settingDiv, settingOpener, api, options);\n\n    return api;\n};\n\nfunction load(url, module, callback) {\n    net.loadScript(url, function() {\n        require([module], callback);\n    });\n}\n\nfunction setupApi(editor, editorDiv, settingDiv, ace, options, loader) {\n    var session = editor.getSession();\n    var renderer = editor.renderer;\n    loader = loader || load;\n\n    function toBool(value) {\n        return value == \"true\";\n    }\n\n    var ret = {\n        setDisplaySettings: function(display) {\n            settingDiv.style.display = display ? \"block\" : \"none\";\n        },\n\n        setOption: function(key, value) {\n            if (options[key] == value) return;\n\n            switch (key) {\n                case \"gutter\":\n                    renderer.setShowGutter(toBool(value));\n                break;\n\n                case \"mode\":\n                    if (value != \"text\") {\n                        // Load the required mode file. Files get loaded only once.\n                        loader(\"mode-\" + value + \".js\", \"ace/mode/\" + value, function() {\n                            var aceMode = require(\"../mode/\" + value).Mode;\n                            session.setMode(new aceMode());\n                        });\n                    } else {\n                        session.setMode(new (require(\"../mode/text\").Mode));\n                    }\n                break;\n\n                case \"theme\":\n                    if (value != \"textmate\") {\n                        // Load the required theme file. Files get loaded only once.\n                        loader(\"theme-\" + value + \".js\", \"ace/theme/\" + value, function() {\n                            editor.setTheme(\"ace/theme/\" + value);\n                        });\n                    } else {\n                        editor.setTheme(\"ace/theme/textmate\");\n                    }\n                break;\n\n                case \"fontSize\":\n                    editorDiv.style.fontSize = value;\n                break;\n\n                case \"softWrap\":\n                    switch (value) {\n                        case \"off\":\n                            session.setUseWrapMode(false);\n                            renderer.setPrintMarginColumn(80);\n                        break;\n                        case \"40\":\n                            session.setUseWrapMode(true);\n                            session.setWrapLimitRange(40, 40);\n                            renderer.setPrintMarginColumn(40);\n                        break;\n                        case \"80\":\n                            session.setUseWrapMode(true);\n                            session.setWrapLimitRange(80, 80);\n                            renderer.setPrintMarginColumn(80);\n                        break;\n                        case \"free\":\n                            session.setUseWrapMode(true);\n                            session.setWrapLimitRange(null, null);\n                            renderer.setPrintMarginColumn(80);\n                        break;\n                    }\n                break;\n\n                case \"useSoftTabs\":\n                    session.setUseSoftTabs(toBool(value));\n                break;\n\n                case \"showPrintMargin\":\n                    renderer.setShowPrintMargin(toBool(value));\n                break;\n\n                case \"showInvisibles\":\n                    editor.setShowInvisibles(toBool(value));\n                break;\n            }\n\n            options[key] = value;\n        },\n\n        getOption: function(key) {\n            return options[key];\n        },\n\n        getOptions: function() {\n            return options;\n        }\n    };\n\n    for (var option in exports.options) {\n        ret.setOption(option, exports.options[option]);\n    }\n\n    return ret;\n}\n\nfunction setupSettingPanel(settingDiv, settingOpener, api, options) {\n    var BOOL = {\n        \"true\":  true,\n        \"false\": false\n    };\n\n    var desc = {\n        mode:            \"Mode:\",\n        gutter:          \"Display Gutter:\",\n        theme:           \"Theme:\",\n        fontSize:        \"Font Size:\",\n        softWrap:        \"Soft Wrap:\",\n        showPrintMargin: \"Show Print Margin:\",\n        useSoftTabs:     \"Use Soft Tabs:\",\n        showInvisibles:  \"Show Invisibles\"\n    };\n\n    var optionValues = {\n        mode: {\n            text:       \"Plain\",\n            javascript: \"JavaScript\",\n            xml:        \"XML\",\n            html:       \"HTML\",\n            css:        \"CSS\",\n            scss:       \"SCSS\",\n            python:     \"Python\",\n            php:        \"PHP\",\n            java:       \"Java\",\n            ruby:       \"Ruby\",\n            c_cpp:      \"C/C++\",\n            coffee:     \"CoffeeScript\",\n            json:       \"json\",\n            perl:       \"Perl\",\n            clojure:    \"Clojure\",\n            ocaml:      \"OCaml\",\n            csharp:     \"C#\",\n            haxe:       \"haXe\",\n            svg:        \"SVG\",\n            textile:    \"Textile\",\n            groovy:     \"Groovy\",\n            liquid:     \"Liquid\",\n            Scala:      \"Scala\"\n        },\n        theme: {\n            clouds:           \"Clouds\",\n            clouds_midnight:  \"Clouds Midnight\",\n            cobalt:           \"Cobalt\",\n            crimson_editor:   \"Crimson Editor\",\n            dawn:             \"Dawn\",\n            eclipse:          \"Eclipse\",\n            idle_fingers:     \"Idle Fingers\",\n            kr_theme:         \"Kr Theme\",\n            merbivore:        \"Merbivore\",\n            merbivore_soft:   \"Merbivore Soft\",\n            mono_industrial:  \"Mono Industrial\",\n            monokai:          \"Monokai\",\n            pastel_on_dark:   \"Pastel On Dark\",\n            solarized_dark:   \"Solarized Dark\",\n            solarized_light:  \"Solarized Light\",\n            textmate:         \"Textmate\",\n            twilight:         \"Twilight\",\n            vibrant_ink:      \"Vibrant Ink\"\n        },\n        gutter: BOOL,\n        fontSize: {\n            \"10px\": \"10px\",\n            \"11px\": \"11px\",\n            \"12px\": \"12px\",\n            \"14px\": \"14px\",\n            \"16px\": \"16px\"\n        },\n        softWrap: {\n            off:    \"Off\",\n            40:     \"40\",\n            80:     \"80\",\n            free:   \"Free\"\n        },\n        showPrintMargin:    BOOL,\n        useSoftTabs:        BOOL,\n        showInvisibles:     BOOL\n    };\n\n    var table = [];\n    table.push(\"<table><tr><th>Setting</th><th>Value</th></tr>\");\n\n    function renderOption(builder, option, obj, cValue) {\n        builder.push(\"<select title='\" + option + \"'>\");\n        for (var value in obj) {\n            builder.push(\"<option value='\" + value + \"' \");\n\n            if (cValue == value) {\n                builder.push(\" selected \");\n            }\n\n            builder.push(\">\",\n                obj[value],\n                \"</option>\");\n        }\n        builder.push(\"</select>\");\n    }\n\n    for (var option in options) {\n        table.push(\"<tr><td>\", desc[option], \"</td>\");\n        table.push(\"<td>\");\n        renderOption(table, option, optionValues[option], options[option]);\n        table.push(\"</td></tr>\");\n    }\n    table.push(\"</table>\");\n    settingDiv.innerHTML = table.join(\"\");\n\n    var selects = settingDiv.getElementsByTagName(\"select\");\n    for (var i = 0; i < selects.length; i++) {\n        var onChange = (function() {\n            var select = selects[i];\n            return function() {\n                var option = select.title;\n                var value  = select.value;\n                api.setOption(option, value);\n            };\n        })();\n        selects[i].onchange = onChange;\n    }\n\n    var button = document.createElement(\"input\");\n    button.type = \"button\";\n    button.value = \"Hide\";\n    button.onclick = function() {\n        api.setDisplaySettings(false);\n    };\n    settingDiv.appendChild(button);\n\n    settingOpener.onclick = function() {\n        api.setDisplaySettings(true);\n    };\n}\n\n// Default startup options.\nexports.options = {\n    mode:               \"text\",\n    theme:              \"textmate\",\n    gutter:             \"false\",\n    fontSize:           \"12px\",\n    softWrap:           \"off\",\n    showPrintMargin:    \"false\",\n    useSoftTabs:        \"true\",\n    showInvisibles:     \"true\"\n};\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/keyboard/hash_handler.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Mozilla Skywriter.\n *\n * The Initial Developer of the Original Code is\n * Mozilla.\n * Portions created by the Initial Developer are Copyright (C) 2009\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *   Fabian Jakobs <fabian AT ajax DOT org>\n *   Julian Viereck (julian.viereck@gmail.com)\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar keyUtil  = require(\"../lib/keys\");\n\nfunction HashHandler(config, platform) {\n    this.platform = platform;\n    this.commands = {};\n    this.commmandKeyBinding = {};\n\n    this.addCommands(config);\n};\n\n(function() {\n\n    this.addCommand = function(command) {\n        if (this.commands[command.name])\n            this.removeCommand(command);\n\n        this.commands[command.name] = command;\n\n        if (command.bindKey) {\n            this._buildKeyHash(command);\n        }\n    };\n\n    this.removeCommand = function(command) {\n        var name = (typeof command === 'string' ? command : command.name);\n        command = this.commands[name];\n        delete this.commands[name];\n\n        // exhaustive search is brute force but since removeCommand is\n        // not a performance critical operation this should be OK\n        var ckb = this.commmandKeyBinding;\n        for (var hashId in ckb) {\n            for (var key in ckb[hashId]) {\n                if (ckb[hashId][key] == command)\n                    delete ckb[hashId][key];\n            }\n        }\n    };\n\n    this.addCommands = function(commands) {\n        commands && Object.keys(commands).forEach(function(name) {\n            var command = commands[name];\n            if (typeof command === \"string\")\n                return this.bindKey(command, name);\n\n            if (typeof command === \"function\")\n                command = { exec: command };\n\n            if (!command.name)\n                command.name = name;\n\n            this.addCommand(command);\n        }, this);\n    };\n\n    this.removeCommands = function(commands) {\n        Object.keys(commands).forEach(function(name) {\n            this.removeCommand(commands[name]);\n        }, this);\n    };\n\n    this.bindKey = function(key, command) {\n        if(!key)\n            return;\n\n        var ckb = this.commmandKeyBinding;\n        key.split(\"|\").forEach(function(keyPart) {\n            var binding = parseKeys(keyPart, command);\n            var hashId = binding.hashId;\n            (ckb[hashId] || (ckb[hashId] = {}))[binding.key] = command;\n        });\n    };\n\n    this.bindKeys = function(keyList) {\n        Object.keys(keyList).forEach(function(key) {\n            this.bindKey(key, keyList[key]);\n        }, this);\n    };\n\n    this._buildKeyHash = function(command) {\n        var binding = command.bindKey;\n        if (!binding)\n            return;\n\n        var key = typeof binding == \"string\" ? binding: binding[this.platform];\n        this.bindKey(key, command);\n    };\n\n    function parseKeys(keys, val, ret) {\n        var key;\n        var hashId = 0;\n        var parts = splitSafe(keys.toLowerCase());\n\n        for (var i = 0, l = parts.length; i < l; i++) {\n            if (keyUtil.KEY_MODS[parts[i]])\n                hashId = hashId | keyUtil.KEY_MODS[parts[i]];\n            else\n                key = parts[i] || \"-\"; //when empty, the splitSafe removed a '-'\n        }\n\n        return {\n            key: key,\n            hashId: hashId\n        };\n    }\n\n    function splitSafe(s) {\n        return (s.trim()\n            .split(new RegExp(\"[\\\\s ]*\\\\-[\\\\s ]*\", \"g\"), 999));\n    }\n\n    this.findKeyCommand = function findKeyCommand(hashId, keyString) {\n        var ckbr = this.commmandKeyBinding;\n        return ckbr[hashId] && ckbr[hashId][keyString.toLowerCase()];\n    }\n\n    this.handleKeyboard = function(data, hashId, keyString, keyCode) {\n        return {\n            command: this.findKeyCommand(hashId, keyString)\n        };\n    };\n\n}).call(HashHandler.prototype)\n\nexports.HashHandler = HashHandler;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/keyboard/keybinding/emacs.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Mozilla Skywriter.\n *\n * The Initial Developer of the Original Code is\n * Mozilla.\n * Portions created by the Initial Developer are Copyright (C) 2009\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *   Julian Viereck (julian.viereck@gmail.com)\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar StateHandler = require(\"../state_handler\").StateHandler;\nvar matchCharacterOnly =  require(\"../state_handler\").matchCharacterOnly;\n\nvar emacsState = {\n    start: [\n        {\n            key:    \"ctrl-x\",\n            then:   \"c-x\"\n        },\n        {\n            regex:  [ \"(?:command-([0-9]*))*\", \"(down|ctrl-n)\" ],\n            exec:   \"golinedown\",\n            params: [\n                {\n                    name: \"times\",\n                    match: 1,\n                    type: \"number\",\n                    defaultValue: 1\n                }\n            ]\n        },\n        {\n            regex: [ \"(?:command-([0-9]*))*\", \"(right|ctrl-f)\" ],\n            exec: \"gotoright\",\n            params: [\n                {\n                    name: \"times\",\n                    match: 1,\n                    type: \"number\",\n                    defaultValue: 1\n                }\n            ]\n        },\n        {\n            regex: [ \"(?:command-([0-9]*))*\", \"(up|ctrl-p)\" ],\n            exec: \"golineup\",\n            params: [\n                {\n                    name: \"times\",\n                    match: 1,\n                    type: \"number\",\n                    defaultValue: 1\n                }\n            ]\n        },\n        {\n            regex: [ \"(?:command-([0-9]*))*\", \"(left|ctrl-b)\" ],\n            exec: \"gotoleft\",\n            params: [\n                {\n                    name: \"times\",\n                    match: 1,\n                    type: \"number\",\n                    defaultValue: 1\n                }\n            ]\n        },\n        {\n            comment: \"This binding matches all printable characters except numbers as long as they are no numbers and print them n times.\",\n            regex:  [ \"(?:command-([0-9]*))\", \"([^0-9]+)*\" ],\n            match:  matchCharacterOnly,\n            exec:   \"inserttext\",\n            params: [\n                {\n                    name: \"times\",\n                    match: 1,\n                    type: \"number\",\n                    defaultValue: \"1\"\n                },\n                {\n                    name: \"text\",\n                    match: 2\n                }\n            ]\n        },\n        {\n            comment: \"This binding matches numbers as long as there is no meta_number in the buffer.\",\n            regex:  [ \"(command-[0-9]*)*\", \"([0-9]+)\" ],\n            match:  matchCharacterOnly,\n            disallowMatches:  [ 1 ],\n            exec:   \"inserttext\",\n            params: [\n                {\n                    name: \"text\",\n                    match: 2,\n                    type: \"text\"\n                }\n            ]\n        },\n        {\n            regex: [ \"command-([0-9]*)\", \"(command-[0-9]|[0-9])\" ],\n            comment: \"Stops execution if the regex /meta_[0-9]+/ matches to avoid resetting the buffer.\"\n        }\n    ],\n    \"c-x\": [\n        {\n            key: \"ctrl-g\",\n            then: \"start\"\n        },\n        {\n            key: \"ctrl-s\",\n            exec: \"save\",\n            then: \"start\"\n        }\n    ]\n};\n\nexports.Emacs = new StateHandler(emacsState);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/keyboard/keybinding/vim.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Mozilla Skywriter.\n *\n * The Initial Developer of the Original Code is\n * Mozilla.\n * Portions created by the Initial Developer are Copyright (C) 2009\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *   Julian Viereck (julian.viereck@gmail.com)\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar StateHandler = require(\"../state_handler\").StateHandler;\nvar matchCharacterOnly =  require(\"../state_handler\").matchCharacterOnly;\n\nvar vimcommand = function(key, exec, then) {\n    return {\n        regex:  [ \"([0-9]*)\", key ],\n        exec:   exec,\n        params: [\n            {\n                name:     \"times\",\n                match:    1,\n                type:     \"number\",\n                defaultValue:     1\n            }\n        ],\n        then:   then\n    }\n}\n\nvar vimStates = {\n    start: [\n        {\n            key:    \"i\",\n            then:   \"insertMode\"\n        },\n        {\n            key:    \"d\",\n            then:   \"deleteMode\"\n        },\n        {\n            key:    \"a\",\n            exec:   \"gotoright\",\n            then:   \"insertMode\"\n        },\n        {\n            key:    \"shift-i\",\n            exec:   \"gotolinestart\",\n            then:   \"insertMode\"\n        },\n        {\n            key:    \"shift-a\",\n            exec:   \"gotolineend\",\n            then:   \"insertMode\"\n        },\n        {\n            key:    \"shift-c\",\n            exec:   \"removetolineend\",\n            then:   \"insertMode\"\n        },\n        {\n            key:    \"shift-r\",\n            exec:   \"overwrite\",\n            then:   \"replaceMode\"\n        },\n        vimcommand(\"(k|up)\", \"golineup\"),\n        vimcommand(\"(j|down)\", \"golinedown\"),\n        vimcommand(\"(l|right)\", \"gotoright\"),\n        vimcommand(\"(h|left)\", \"gotoleft\"),\n        {\n            key:    \"shift-g\",\n            exec:   \"gotoend\"\n        },\n        vimcommand(\"b\", \"gotowordleft\"),\n        vimcommand(\"e\", \"gotowordright\"),\n        vimcommand(\"x\", \"del\"),\n        vimcommand(\"shift-x\", \"backspace\"),\n        vimcommand(\"shift-d\", \"removetolineend\"),\n        vimcommand(\"u\", \"undo\"), // [count] on this may/may not work, depending on browser implementation...\n        {\n            comment:    \"Catch some keyboard input to stop it here\",\n            match:      matchCharacterOnly\n        }\n    ],\n    insertMode: [\n        {\n            key:      \"esc\",\n            then:     \"start\"\n        }\n    ],\n    replaceMode: [\n        {\n            key:      \"esc\",\n            exec:     \"overwrite\",\n            then:     \"start\"\n        }\n    ],\n    deleteMode: [\n        {\n            key:      \"d\",\n            exec:     \"removeline\",\n            then:     \"start\"\n        }\n    ]\n};\n\nexports.Vim = new StateHandler(vimStates);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/keyboard/keybinding.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Julian Viereck <julian.viereck@gmail.com>\n *      Harutyun Amirjanyan <amirjanyan@gmail.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar keyUtil  = require(\"../lib/keys\");\nvar event = require(\"../lib/event\");\nrequire(\"../commands/default_commands\");\n\nvar KeyBinding = function(editor) {\n    this.$editor = editor;\n    this.$data = { };\n    this.$handlers = [this];\n};\n\n(function() {\n    this.setKeyboardHandler = function(keyboardHandler) {\n        if (this.$handlers[this.$handlers.length - 1] == keyboardHandler)\n            return;\n        this.$data = { };\n        this.$handlers = keyboardHandler ? [this, keyboardHandler] : [this];\n    };\n\n    this.addKeyboardHandler = function(keyboardHandler) {\n        this.removeKeyboardHandler(keyboardHandler);\n        this.$handlers.push(keyboardHandler);\n    };\n\n    this.removeKeyboardHandler = function(keyboardHandler) {\n        var i = this.$handlers.indexOf(keyboardHandler);\n        if (i == -1)\n            return false;\n        this.$handlers.splice(i, 1);\n        return true;\n    };\n\n    this.getKeyboardHandler = function() {\n        return this.$handlers[this.$handlers.length - 1];\n    };\n\n    this.$callKeyboardHandlers = function (hashId, keyString, keyCode, e) {\n        var toExecute;\n        for (var i = this.$handlers.length; i--;) {\n            toExecute = this.$handlers[i].handleKeyboard(\n                this.$data, hashId, keyString, keyCode, e\n            );\n            if (toExecute && toExecute.command)\n                break;\n        }\n\n        if (!toExecute || !toExecute.command)\n            return false;\n\n        var success = false;\n        var commands = this.$editor.commands;\n\n        // allow keyboardHandler to consume keys\n        if (toExecute.command != \"null\")\n            success = commands.exec(toExecute.command, this.$editor, toExecute.args);\n        else\n            success = true;\n\n        if (success && e)\n            event.stopEvent(e);\n\n        return success;\n    };\n\n    this.handleKeyboard = function(data, hashId, keyString) {\n        return {\n            command: this.$editor.commands.findKeyCommand(hashId, keyString)\n        };\n    };\n\n    this.onCommandKey = function(e, hashId, keyCode) {\n        var keyString = keyUtil.keyCodeToString(keyCode);\n        this.$callKeyboardHandlers(hashId, keyString, keyCode, e);\n    };\n\n    this.onTextInput = function(text, pasted) {\n        var success = false;\n        if (!pasted && text.length == 1)\n            success = this.$callKeyboardHandlers(0, text);\n        if (!success)\n            this.$editor.commands.exec(\"insertstring\", this.$editor, text);\n    };\n\n}).call(KeyBinding.prototype);\n\nexports.KeyBinding = KeyBinding;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/keyboard/state_handler.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Mozilla Skywriter.\n *\n * The Initial Developer of the Original Code is\n * Mozilla.\n * Portions created by the Initial Developer are Copyright (C) 2009\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *   Julian Viereck (julian.viereck@gmail.com)\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\n// If you're developing a new keymapping and want to get an idea what's going\n// on, then enable debugging.\nvar DEBUG = false;\n\nfunction StateHandler(keymapping) {\n    this.keymapping = this.$buildKeymappingRegex(keymapping);\n}\n\nStateHandler.prototype = {\n    /**\n     * Build the RegExp from the keymapping as RegExp can't stored directly\n     * in the metadata JSON and as the RegExp used to match the keys/buffer\n     * need to be adapted.\n     */\n    $buildKeymappingRegex: function(keymapping) {\n        for (var state in keymapping) {\n            this.$buildBindingsRegex(keymapping[state]);\n        }\n        return keymapping;\n    },\n\n    $buildBindingsRegex: function(bindings) {\n        // Escape a given Regex string.\n        bindings.forEach(function(binding) {\n            if (binding.key) {\n                binding.key = new RegExp('^' + binding.key + '$');\n            } else if (Array.isArray(binding.regex)) {\n                if (!('key' in binding))\n                  binding.key = new RegExp('^' + binding.regex[1] + '$');\n                binding.regex = new RegExp(binding.regex.join('') + '$');\n            } else if (binding.regex) {\n                binding.regex = new RegExp(binding.regex + '$');\n            }\n        });\n    },\n\n    $composeBuffer: function(data, hashId, key, e) {\n        // Initialize the data object.\n        if (data.state == null || data.buffer == null) {\n            data.state = \"start\";\n            data.buffer = \"\";\n        }\n\n        var keyArray = [];\n        if (hashId & 1) keyArray.push(\"ctrl\");\n        if (hashId & 8) keyArray.push(\"command\");\n        if (hashId & 2) keyArray.push(\"option\");\n        if (hashId & 4) keyArray.push(\"shift\");\n        if (key)        keyArray.push(key);\n\n        var symbolicName = keyArray.join(\"-\");\n        var bufferToUse = data.buffer + symbolicName;\n\n        // Don't add the symbolic name to the key buffer if the alt_ key is\n        // part of the symbolic name. If it starts with alt_, this means\n        // that the user hit an alt keycombo and there will be a single,\n        // new character detected after this event, which then will be\n        // added to the buffer (e.g. alt_j will result in ∆).\n        //\n        // We test for 2 and not for & 2 as we only want to exclude the case where\n        // the option key is pressed alone.\n        if (hashId != 2) {\n            data.buffer = bufferToUse;\n        }\n\n        var bufferObj = {\n            bufferToUse: bufferToUse,\n            symbolicName: symbolicName,\n        };\n\n        if (e) {\n            bufferObj.keyIdentifier = e.keyIdentifier\n        }\n\n        return bufferObj;\n    },\n\n    $find: function(data, buffer, symbolicName, hashId, key, keyIdentifier) {\n        // Holds the command to execute and the args if a command matched.\n        var result = {};\n\n        // Loop over all the bindings of the keymap until a match is found.\n        this.keymapping[data.state].some(function(binding) {\n            var match;\n\n            // Check if the key matches.\n            if (binding.key && !binding.key.test(symbolicName)) {\n                return false;\n            }\n\n            // Check if the regex matches.\n            if (binding.regex && !(match = binding.regex.exec(buffer))) {\n                return false;\n            }\n\n            // Check if the match function matches.\n            if (binding.match && !binding.match(buffer, hashId, key, symbolicName, keyIdentifier)) {\n                return false;\n            }\n\n            // Check for disallowed matches.\n            if (binding.disallowMatches) {\n                for (var i = 0; i < binding.disallowMatches.length; i++) {\n                    if (!!match[binding.disallowMatches[i]]) {\n                        return false;\n                    }\n                }\n            }\n\n            // If there is a command to execute, then figure out the\n            // command and the arguments.\n            if (binding.exec) {\n                result.command = binding.exec;\n\n                // Build the arguments.\n                if (binding.params) {\n                    var value;\n                    result.args = {};\n                    binding.params.forEach(function(param) {\n                        if (param.match != null && match != null) {\n                            value = match[param.match] || param.defaultValue;\n                        } else {\n                            value = param.defaultValue;\n                        }\n\n                        if (param.type === 'number') {\n                            value = parseInt(value);\n                        }\n\n                        result.args[param.name] = value;\n                    });\n                }\n                data.buffer = \"\";\n            }\n\n            // Handle the 'then' property.\n            if (binding.then) {\n                data.state = binding.then;\n                data.buffer = \"\";\n            }\n\n            // If no command is set, then execute the \"null\" fake command.\n            if (result.command == null) {\n                result.command = \"null\";\n            }\n\n            if (DEBUG) {\n                console.log(\"KeyboardStateMapper#find\", binding);\n            }\n            return true;\n        });\n\n        if (result.command) {\n            return result;\n        } else {\n            data.buffer = \"\";\n            return false;\n        }\n    },\n\n    /**\n     * This function is called by keyBinding.\n     */\n    handleKeyboard: function(data, hashId, key, keyCode, e) {\n        // If we pressed any command key but no other key, then ignore the input.\n        // Otherwise \"shift-\" is added to the buffer, and later on \"shift-g\"\n        // which results in \"shift-shift-g\" which doesn't make sense.\n        if (hashId != 0 && (key == \"\" || key == String.fromCharCode(0))) {\n            return null;\n        }\n\n        // Compute the current value of the keyboard input buffer.\n        var r = this.$composeBuffer(data, hashId, key, e);\n        var buffer = r.bufferToUse;\n        var symbolicName = r.symbolicName;\n        var keyId = r.keyIdentifier;\n\n        r = this.$find(data, buffer, symbolicName, hashId, key, keyId);\n        if (DEBUG) {\n            console.log(\"KeyboardStateMapper#match\", buffer, symbolicName, r);\n        }\n\n        return r;\n    }\n}\n\n/**\n * This is a useful matching function and therefore is defined here so that\n * users of KeyboardStateMapper can use it.\n *\n * @return boolean\n *          If no command key (Command|Option|Shift|Ctrl) is pressed, it\n *          returns true. If the only the Shift key is pressed + a character\n *          true is returned as well. Otherwise, false is returned.\n *          Summing up, the function returns true whenever the user typed\n *          a normal character on the keyboard and no shortcut.\n */\nexports.matchCharacterOnly = function(buffer, hashId, key, symbolicName) {\n    // If no command keys are pressed, then catch the input.\n    if (hashId == 0) {\n        return true;\n    }\n    // If only the shift key is pressed and a character key, then\n    // catch that input as well.\n    else if ((hashId == 4) && key.length == 1) {\n        return true;\n    }\n    // Otherwise, we let the input got through.\n    else {\n        return false;\n    }\n};\n\nexports.StateHandler = StateHandler;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/keyboard/textinput.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Mihai Sucan <mihai DOT sucan AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar event = require(\"../lib/event\");\nvar useragent = require(\"../lib/useragent\");\nvar dom = require(\"../lib/dom\");\n\nvar TextInput = function(parentNode, host) {\n\n    var text = dom.createElement(\"textarea\");\n    if (useragent.isTouchPad)\n        text.setAttribute(\"x-palm-disable-auto-cap\", true);\n        \n    text.style.left = \"-10000px\";\n    text.style.position = \"fixed\";\n    parentNode.insertBefore(text, parentNode.firstChild);\n\n    var PLACEHOLDER = String.fromCharCode(0);\n    sendText();\n\n    var inCompostion = false;\n    var copied = false;\n    var pasted = false;\n    var tempStyle = '';\n\n    function select() {\n        try {\n            text.select();\n        } catch (e) {}\n    }\n\n    function sendText(valueToSend) {\n        if (!copied) {\n            var value = valueToSend || text.value;\n            if (value) {\n                if (value.charCodeAt(value.length-1) == PLACEHOLDER.charCodeAt(0)) {\n                    value = value.slice(0, -1);\n                    if (value)\n                        host.onTextInput(value, pasted);\n                }\n                else {\n                    host.onTextInput(value, pasted);\n                }\n\n                // If editor is no longer focused we quit immediately, since\n                // it means that something else is in charge now.\n                if (!isFocused())\n                    return false;\n            }\n        }\n\n        copied = false;\n        pasted = false;\n\n        // Safari doesn't fire copy events if no text is selected\n        text.value = PLACEHOLDER;\n        select();\n    }\n\n    var onTextInput = function(e) {\n        setTimeout(function () {\n            if (!inCompostion)\n                sendText(e.data);                \n        }, 0);\n    };\n    \n    var onPropertyChange = function(e) {\n        if (useragent.isOldIE && text.value.charCodeAt(0) > 128) return;\n        setTimeout(function() {\n            if (!inCompostion)\n                sendText();\n        }, 0);\n    };\n\n    var onCompositionStart = function(e) {\n        inCompostion = true;\n        host.onCompositionStart();\n        if (!useragent.isGecko) setTimeout(onCompositionUpdate, 0);\n    };\n\n    var onCompositionUpdate = function() {\n        if (!inCompostion) return;\n        host.onCompositionUpdate(text.value);\n    };\n\n    var onCompositionEnd = function(e) {\n        inCompostion = false;\n        host.onCompositionEnd();\n    };\n\n    var onCopy = function(e) {\n        copied = true;\n        var copyText = host.getCopyText();\n        if(copyText)\n            text.value = copyText;\n        else\n            e.preventDefault();\n        select();\n        setTimeout(function () {\n            sendText();\n        }, 0);\n    };\n    \n    var onCut = function(e) {\n        copied = true;\n        var copyText = host.getCopyText();\n        if(copyText) {\n            text.value = copyText;\n            host.onCut();\n        } else\n            e.preventDefault();\n        select();\n        setTimeout(function () {\n            sendText();\n        }, 0);\n    };\n\n    event.addCommandKeyListener(text, host.onCommandKey.bind(host));\n    if (useragent.isOldIE) {\n        var keytable = { 13:1, 27:1 };\n        event.addListener(text, \"keyup\", function (e) {\n            if (inCompostion && (!text.value || keytable[e.keyCode]))\n                setTimeout(onCompositionEnd, 0);\n            if ((text.value.charCodeAt(0)|0) < 129) {\n                return;\n            }\n            inCompostion ? onCompositionUpdate() : onCompositionStart();\n        });\n    }\n    \n    if (\"onpropertychange\" in text && !(\"oninput\" in text))\n        event.addListener(text, \"propertychange\", onPropertyChange);\n    else\n        event.addListener(text, \"input\", onTextInput);\n    \n    event.addListener(text, \"paste\", function(e) {\n        // Mark that the next input text comes from past.\n        pasted = true;\n        // Some browsers support the event.clipboardData API. Use this to get\n        // the pasted content which increases speed if pasting a lot of lines.\n        if (e.clipboardData && e.clipboardData.getData) {\n            sendText(e.clipboardData.getData(\"text/plain\"));\n            e.preventDefault();\n        } \n        else {\n            // If a browser doesn't support any of the things above, use the regular\n            // method to detect the pasted input.\n            onPropertyChange();\n        }\n    });\n\n    if (\"onbeforecopy\" in text && typeof clipboardData !== \"undefined\") {\n        event.addListener(text, \"beforecopy\", function(e) {\n            var copyText = host.getCopyText();\n            if (copyText)\n                clipboardData.setData(\"Text\", copyText);\n            else\n                e.preventDefault();\n        });\n        event.addListener(parentNode, \"keydown\", function(e) {\n            if (e.ctrlKey && e.keyCode == 88) {\n                var copyText = host.getCopyText();\n                if (copyText) {\n                    clipboardData.setData(\"Text\", copyText);\n                    host.onCut();\n                }\n                event.preventDefault(e);\n            }\n        });\n    }\n    else {\n        event.addListener(text, \"copy\", onCopy);\n        event.addListener(text, \"cut\", onCut);\n    }\n\n    event.addListener(text, \"compositionstart\", onCompositionStart);\n    if (useragent.isGecko) {\n        event.addListener(text, \"text\", onCompositionUpdate);\n    }\n    if (useragent.isWebKit) {\n        event.addListener(text, \"keyup\", onCompositionUpdate);\n    }\n    event.addListener(text, \"compositionend\", onCompositionEnd);\n\n    event.addListener(text, \"blur\", function() {\n        host.onBlur();\n    });\n\n    event.addListener(text, \"focus\", function() {\n        host.onFocus();\n        select();\n    });\n\n    this.focus = function() {\n        host.onFocus();\n        select();\n        text.focus();\n    };\n\n    this.blur = function() {\n        text.blur();\n    };\n\n    function isFocused() {\n        return document.activeElement === text;\n    }\n    this.isFocused = isFocused;\n\n    this.getElement = function() {\n        return text;\n    };\n\n    this.onContextMenu = function(mousePos, isEmpty){\n        if (mousePos) {\n            if (!tempStyle)\n                tempStyle = text.style.cssText;\n                \n            text.style.cssText = \n                'position:fixed; z-index:1000;' +\n                'left:' + (mousePos.x - 2) + 'px; top:' + (mousePos.y - 2) + 'px;';\n\n        }\n        if (isEmpty)\n            text.value='';\n    };\n\n    this.onContextMenuClose = function(){\n        setTimeout(function () {\n            if (tempStyle) {\n                text.style.cssText = tempStyle;\n                tempStyle = '';\n            }\n            sendText();\n        }, 0);\n    };\n};\n\nexports.TextInput = TextInput;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/layer/cursor.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Julian Viereck <julian.viereck@gmail.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar dom = require(\"../lib/dom\");\n\nvar Cursor = function(parentEl) {\n    this.element = dom.createElement(\"div\");\n    this.element.className = \"ace_layer ace_cursor-layer\";\n    parentEl.appendChild(this.element);\n\n    this.isVisible = false;\n\n    this.cursors = [];\n    this.cursor = this.addCursor();\n};\n\n(function() {\n\n    this.$padding = 0;\n    this.setPadding = function(padding) {\n        this.$padding = padding;\n    };\n\n    this.setSession = function(session) {\n        this.session = session;\n    };\n\n    this.addCursor = function() {\n        var el = dom.createElement(\"div\");\n        var className = \"ace_cursor\";\n        if (!this.isVisible)\n            className += \" ace_hidden\";\n        if (this.overwrite)\n            className += \" ace_overwrite\";\n\n        el.className = className;\n        this.element.appendChild(el);\n        this.cursors.push(el);\n        return el;\n    };\n\n    this.removeCursor = function() {\n        if (this.cursors.length > 1) {\n            var el = this.cursors.pop();\n            el.parentNode.removeChild(el);\n            return el;\n        }\n    };\n\n    this.hideCursor = function() {\n        this.isVisible = false;\n        for (var i = this.cursors.length; i--; )\n            dom.addCssClass(this.cursors[i], \"ace_hidden\");\n        clearInterval(this.blinkId);\n    };\n\n    this.showCursor = function() {\n        this.isVisible = true;\n        for (var i = this.cursors.length; i--; )\n            dom.removeCssClass(this.cursors[i], \"ace_hidden\");\n\n        this.element.style.visibility = \"\";\n        this.restartTimer();\n    };\n\n    this.restartTimer = function() {\n        clearInterval(this.blinkId);\n        if (!this.isVisible)\n            return;\n\n        var element = this.cursors.length == 1 ? this.cursor : this.element;\n        this.blinkId = setInterval(function() {\n            element.style.visibility = \"hidden\";\n            setTimeout(function() {\n                element.style.visibility = \"\";\n            }, 400);\n        }, 1000);\n    };\n\n    this.getPixelPosition = function(position, onScreen) {\n        if (!this.config || !this.session) {\n            return {\n                left : 0,\n                top : 0\n            };\n        }\n\n        if (!position)\n            position = this.session.selection.getCursor();\n        var pos = this.session.documentToScreenPosition(position);\n        var cursorLeft = Math.round(this.$padding +\n                                    pos.column * this.config.characterWidth);\n        var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) *\n            this.config.lineHeight;\n\n        return {\n            left : cursorLeft,\n            top : cursorTop\n        };\n    };\n\n    this.update = function(config) {\n        this.config = config;\n\n        if (this.session.selectionMarkerCount > 0) {\n            var selections = this.session.$selectionMarkers;\n            var i = 0, sel, cursorIndex = 0;\n\n            for (var i = selections.length; i--; ) {\n                sel = selections[i];\n                var pixelPos = this.getPixelPosition(sel.cursor, true);\n\n                var style = (this.cursors[cursorIndex++] || this.addCursor()).style;\n\n                style.left = pixelPos.left + \"px\";\n                style.top = pixelPos.top + \"px\";\n                style.width = config.characterWidth + \"px\";\n                style.height = config.lineHeight + \"px\";\n            }\n            if (cursorIndex > 1)\n                while (this.cursors.length > cursorIndex)\n                    this.removeCursor();\n        } else {\n            var pixelPos = this.getPixelPosition(null, true);\n            var style = this.cursor.style;\n            style.left = pixelPos.left + \"px\";\n            style.top = pixelPos.top + \"px\";\n            style.width = config.characterWidth + \"px\";\n            style.height = config.lineHeight + \"px\";\n\n            while (this.cursors.length > 1)\n                this.removeCursor();\n        }\n\n        var overwrite = this.session.getOverwrite();\n        if (overwrite != this.overwrite)\n            this.$setOverite(overwrite);\n\n        this.restartTimer();\n    };\n\n    this.$setOverite = function(overwrite) {\n        this.overwrite = overwrite;\n        for (var i = this.cursors.length; i--; ) {\n            if (overwrite)\n                dom.addCssClass(this.cursors[i], \"ace_overwrite\");\n            else\n                dom.removeCssClass(this.cursors[i], \"ace_overwrite\");\n        }\n    };\n\n    this.destroy = function() {\n        clearInterval(this.blinkId);\n    }\n\n}).call(Cursor.prototype);\n\nexports.Cursor = Cursor;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/layer/gutter.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Julian Viereck <julian DOT viereck AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar dom = require(\"../lib/dom\");\nvar oop = require(\"../lib/oop\");\nvar EventEmitter = require(\"../lib/event_emitter\").EventEmitter;\n\nvar Gutter = function(parentEl) {\n    this.element = dom.createElement(\"div\");\n    this.element.className = \"ace_layer ace_gutter-layer\";\n    parentEl.appendChild(this.element);\n    this.setShowFoldWidgets(this.$showFoldWidgets);\n    \n    this.gutterWidth = 0;\n\n    this.$breakpoints = [];\n    this.$annotations = [];\n    this.$decorations = [];\n};\n\n(function() {\n\n    oop.implement(this, EventEmitter);\n    \n    this.setSession = function(session) {\n        this.session = session;\n    };\n\n    this.addGutterDecoration = function(row, className){\n        if (!this.$decorations[row])\n            this.$decorations[row] = \"\";\n        this.$decorations[row] += \" \" + className;\n    };\n\n    this.removeGutterDecoration = function(row, className){\n        this.$decorations[row] = this.$decorations[row].replace(\" \" + className, \"\");\n    };\n\n    this.setBreakpoints = function(rows) {\n        this.$breakpoints = rows.concat();\n    };\n\n    this.setAnnotations = function(annotations) {\n        // iterate over sparse array\n        this.$annotations = [];\n        for (var row in annotations) if (annotations.hasOwnProperty(row)) {\n            var rowAnnotations = annotations[row];\n            if (!rowAnnotations)\n                continue;\n\n            var rowInfo = this.$annotations[row] = {\n                text: []\n            };\n            for (var i=0; i<rowAnnotations.length; i++) {\n                var annotation = rowAnnotations[i];\n                var annoText = annotation.text.replace(/\"/g, \"&quot;\").replace(/'/g, \"&#8217;\").replace(/</, \"&lt;\");\n                if (rowInfo.text.indexOf(annoText) === -1)\n                    rowInfo.text.push(annoText);\n                var type = annotation.type;\n                if (type == \"error\")\n                    rowInfo.className = \"ace_error\";\n                else if (type == \"warning\" && rowInfo.className != \"ace_error\")\n                    rowInfo.className = \"ace_warning\";\n                else if (type == \"info\" && (!rowInfo.className))\n                    rowInfo.className = \"ace_info\";\n            }\n        }\n    };\n\n    this.update = function(config) {\n        this.$config = config;\n\n        var emptyAnno = {className: \"\", text: []};\n        var html = [];\n        var i = config.firstRow;\n        var lastRow = config.lastRow;\n        var fold = this.session.getNextFoldLine(i);\n        var foldStart = fold ? fold.start.row : Infinity;\n        var foldWidgets = this.$showFoldWidgets && this.session.foldWidgets;\n\n        while (true) {\n            if(i > foldStart) {\n                i = fold.end.row + 1;\n                fold = this.session.getNextFoldLine(i, fold);\n                foldStart = fold ?fold.start.row :Infinity;\n            }\n            if(i > lastRow)\n                break;\n\n            var annotation = this.$annotations[i] || emptyAnno;\n            html.push(\"<div class='ace_gutter-cell\",\n                this.$decorations[i] || \"\",\n                this.$breakpoints[i] ? \" ace_breakpoint \" : \" \",\n                annotation.className,\n                \"' title='\", annotation.text.join(\"\\n\"),\n                \"' style='height:\", config.lineHeight, \"px;'>\", (i+1));\n\n            if (foldWidgets) {\n                var c = foldWidgets[i];\n                // check if cached value is invalidated and we need to recompute\n                if (c == null)\n                    c = foldWidgets[i] = this.session.getFoldWidget(i);\n                if (c)\n                    html.push(\n                        \"<span class='ace_fold-widget \", c,\n                        c == \"start\" && i == foldStart && i < fold.end.row ? \" closed\" : \" open\",\n                        \"'></span>\"\n                    );\n            }\n\n            var wrappedRowLength = this.session.getRowLength(i) - 1;\n            while (wrappedRowLength--) {\n                html.push(\"</div><div class='ace_gutter-cell' style='height:\", config.lineHeight, \"px'>\\xA6\");\n            }\n\n            html.push(\"</div>\");\n\n            i++;\n        }\n        this.element = dom.setInnerHtml(this.element, html.join(\"\"));\n        this.element.style.height = config.minHeight + \"px\";\n        \n        var gutterWidth = this.element.offsetWidth;\n        if (gutterWidth !== this.gutterWidth) {\n            this.gutterWidth = gutterWidth;\n            this._emit(\"changeGutterWidth\", gutterWidth);\n        }\n    };\n\n    this.$showFoldWidgets = true;\n    this.setShowFoldWidgets = function(show) {\n        if (show)\n            dom.addCssClass(this.element, \"ace_folding-enabled\");\n        else\n            dom.removeCssClass(this.element, \"ace_folding-enabled\");\n\n        this.$showFoldWidgets = show;\n    };\n    \n    this.getShowFoldWidgets = function() {\n        return this.$showFoldWidgets;\n    };\n\n}).call(Gutter.prototype);\n\nexports.Gutter = Gutter;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/layer/marker.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Julian Viereck <julian.viereck@gmail.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Range = require(\"../range\").Range;\nvar dom = require(\"../lib/dom\");\n\nvar Marker = function(parentEl) {\n    this.element = dom.createElement(\"div\");\n    this.element.className = \"ace_layer ace_marker-layer\";\n    parentEl.appendChild(this.element);\n};\n\n(function() {\n\n    this.$padding = 0;\n\n    this.setPadding = function(padding) {\n        this.$padding = padding;\n    };\n    this.setSession = function(session) {\n        this.session = session;\n    };\n    \n    this.setMarkers = function(markers) {\n        this.markers = markers;\n    };\n\n    this.update = function(config) {\n        var config = config || this.config;\n        if (!config)\n            return;\n\n        this.config = config;\n\n\n        var html = [];\n        for ( var key in this.markers) {\n            var marker = this.markers[key];\n\n            var range = marker.range.clipRows(config.firstRow, config.lastRow);\n            if (range.isEmpty()) continue;\n\n            range = range.toScreenRange(this.session);\n            if (marker.renderer) {\n                var top = this.$getTop(range.start.row, config);\n                var left = Math.round(\n                    this.$padding + range.start.column * config.characterWidth\n                );\n                marker.renderer(html, range, left, top, config);\n            }\n            else if (range.isMultiLine()) {\n                if (marker.type == \"text\") {\n                    this.drawTextMarker(html, range, marker.clazz, config);\n                } else {\n                    this.drawMultiLineMarker(\n                        html, range, marker.clazz, config,\n                        marker.type\n                    );\n                }\n            }\n            else {\n                this.drawSingleLineMarker(\n                    html, range, marker.clazz + \" start\", config,\n                    null, marker.type\n                );\n            }\n        }\n        this.element = dom.setInnerHtml(this.element, html.join(\"\"));\n    };\n\n    this.$getTop = function(row, layerConfig) {\n        return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;\n    };\n\n    /**\n     * Draws a marker, which spans a range of text on multiple lines\n     */ \n    this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) {\n        // selection start\n        var row = range.start.row;\n\n        var lineRange = new Range(\n            row, range.start.column,\n            row, this.session.getScreenLastRowColumn(row)\n        );\n        this.drawSingleLineMarker(stringBuilder, lineRange, clazz + \" start\", layerConfig, 1, \"text\");\n\n        // selection end\n        row = range.end.row;\n        lineRange = new Range(row, 0, row, range.end.column);\n        this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, \"text\");\n\n        for (row = range.start.row + 1; row < range.end.row; row++) {\n            lineRange.start.row = row;\n            lineRange.end.row = row;\n            lineRange.end.column = this.session.getScreenLastRowColumn(row);\n            this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, \"text\");\n        }\n    };\n\n    /**\n     * Draws a multi line marker, where lines span the full width\n     */\n     this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig, type) {\n        var padding = type === \"background\" ? 0 : this.$padding;\n        var layerWidth = layerConfig.width + 2 * this.$padding - padding;\n        // from selection start to the end of the line\n        var height = layerConfig.lineHeight;\n        var width = Math.round(layerWidth - (range.start.column * layerConfig.characterWidth));\n        var top = this.$getTop(range.start.row, layerConfig);\n        var left = Math.round(\n            padding + range.start.column * layerConfig.characterWidth\n        );\n\n        stringBuilder.push(\n            \"<div class='\", clazz, \" start' style='\",\n            \"height:\", height, \"px;\",\n            \"width:\", width, \"px;\",\n            \"top:\", top, \"px;\",\n            \"left:\", left, \"px;'></div>\"\n        );\n\n        // from start of the last line to the selection end\n        top = this.$getTop(range.end.row, layerConfig);\n        width = Math.round(range.end.column * layerConfig.characterWidth);\n\n        stringBuilder.push(\n            \"<div class='\", clazz, \"' style='\",\n            \"height:\", height, \"px;\",\n            \"width:\", width, \"px;\",\n            \"top:\", top, \"px;\",\n            \"left:\", padding, \"px;'></div>\"\n        );\n\n        // all the complete lines\n        height = (range.end.row - range.start.row - 1) * layerConfig.lineHeight;\n        if (height < 0)\n            return;\n        top = this.$getTop(range.start.row + 1, layerConfig);\n\n        stringBuilder.push(\n            \"<div class='\", clazz, \"' style='\",\n            \"height:\", height, \"px;\",\n            \"width:\", layerWidth, \"px;\",\n            \"top:\", top, \"px;\",\n            \"left:\", padding, \"px;'></div>\"\n        );\n    };\n\n    /**\n     * Draws a marker which covers part or whole width of a single screen line\n     */\n    this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig, extraLength, type) {\n        var padding = type === \"background\" ? 0 : this.$padding;\n        var height = layerConfig.lineHeight;\n\n        if (type === \"background\")\n            var width = layerConfig.width;\n        else\n            width = Math.round((range.end.column + (extraLength || 0) - range.start.column) * layerConfig.characterWidth);\n\n        var top = this.$getTop(range.start.row, layerConfig);\n        var left = Math.round(\n            padding + range.start.column * layerConfig.characterWidth\n        );\n\n        stringBuilder.push(\n            \"<div class='\", clazz, \"' style='\",\n            \"height:\", height, \"px;\",\n            \"width:\", width, \"px;\",\n            \"top:\", top, \"px;\",\n            \"left:\", left,\"px;'></div>\"\n        );\n    };\n\n}).call(Marker.prototype);\n\nexports.Marker = Marker;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/layer/text.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Julian Viereck <julian DOT viereck AT gmail DOT com>\n *      Mihai Sucan <mihai.sucan@gmail.com>\n *      Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar dom = require(\"../lib/dom\");\nvar lang = require(\"../lib/lang\");\nvar useragent = require(\"../lib/useragent\");\nvar EventEmitter = require(\"../lib/event_emitter\").EventEmitter;\n\nvar Text = function(parentEl) {\n    this.element = dom.createElement(\"div\");\n    this.element.className = \"ace_layer ace_text-layer\";\n    parentEl.appendChild(this.element);\n\n    this.$characterSize = this.$measureSizes() || {width: 0, height: 0};\n    this.$pollSizeChanges();\n};\n\n(function() {\n\n    oop.implement(this, EventEmitter);\n\n    this.EOF_CHAR = \"\\xB6\"; //\"&para;\";\n    this.EOL_CHAR = \"\\xAC\"; //\"&not;\";\n    this.TAB_CHAR = \"\\u2192\"; //\"&rarr;\";\n    this.SPACE_CHAR = \"\\xB7\"; //\"&middot;\";\n    this.$padding = 0;\n\n    this.setPadding = function(padding) {\n        this.$padding = padding;\n        this.element.style.padding = \"0 \" + padding + \"px\";\n    };\n\n    this.getLineHeight = function() {\n        return this.$characterSize.height || 1;\n    };\n\n    this.getCharacterWidth = function() {\n        return this.$characterSize.width || 1;\n    };\n\n    this.checkForSizeChanges = function() {\n        var size = this.$measureSizes();\n        if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) {\n            this.$characterSize = size;\n            this._emit(\"changeCharacterSize\", {data: size});\n        }\n    };\n\n    this.$pollSizeChanges = function() {\n        var self = this;\n        this.$pollSizeChangesTimer = setInterval(function() {\n            self.checkForSizeChanges();\n        }, 500);\n    };\n\n    this.$fontStyles = {\n        fontFamily : 1,\n        fontSize : 1,\n        fontWeight : 1,\n        fontStyle : 1,\n        lineHeight : 1\n    };\n\n    this.$measureSizes = useragent.isIE || useragent.isOldGecko ? function() {\n        var n = 1000;\n        if (!this.$measureNode) {\n            var measureNode = this.$measureNode = dom.createElement(\"div\");\n            var style = measureNode.style;\n\n            style.width = style.height = \"auto\";\n            style.left = style.top = (-n * 40)  + \"px\";\n\n            style.visibility = \"hidden\";\n            style.position = \"fixed\";\n            style.overflow = \"visible\";\n            style.whiteSpace = \"nowrap\";\n\n            // in FF 3.6 monospace fonts can have a fixed sub pixel width.\n            // that's why we have to measure many characters\n            // Note: characterWidth can be a float!\n            measureNode.innerHTML = lang.stringRepeat(\"Xy\", n);\n\n            if (this.element.ownerDocument.body) {\n                this.element.ownerDocument.body.appendChild(measureNode);\n            } else {\n                var container = this.element.parentNode;\n                while (!dom.hasCssClass(container, \"ace_editor\"))\n                    container = container.parentNode;\n                container.appendChild(measureNode);\n            }\n        }\n        \n        // Size and width can be null if the editor is not visible or\n        // detached from the document\n        if (!this.element.offsetWidth)\n            return null;\n\n        var style = this.$measureNode.style;\n        var computedStyle = dom.computedStyle(this.element);\n        for (var prop in this.$fontStyles)\n            style[prop] = computedStyle[prop];\n\n        var size = {\n            height: this.$measureNode.offsetHeight,\n            width: this.$measureNode.offsetWidth / (n * 2)\n        };\n\n        // Size and width can be null if the editor is not visible or\n        // detached from the document\n        if (size.width == 0 || size.height == 0)\n            return null;\n\n        return size;\n    } \n    : function() {\n        if (!this.$measureNode) {\n            var measureNode = this.$measureNode = dom.createElement(\"div\");\n            var style = measureNode.style;\n\n            style.width = style.height = \"auto\";\n            style.left = style.top = -100 + \"px\";\n\n            style.visibility = \"hidden\";\n            style.position = \"fixed\";\n            style.overflow = \"visible\";\n            style.whiteSpace = \"nowrap\";\n\n            measureNode.innerHTML = \"X\";\n\n            var container = this.element.parentNode;\n            while (container && !dom.hasCssClass(container, \"ace_editor\"))\n                container = container.parentNode;\n\n            if (!container)\n                return this.$measureNode = null;\n\n            container.appendChild(measureNode);\n        }\n        \n        var rect = this.$measureNode.getBoundingClientRect();\n\n        var size = {\n            height: rect.height,\n            width: rect.width\n        };\n\n        // Size and width can be null if the editor is not visible or\n        // detached from the document\n        if (size.width == 0 || size.height == 0)\n            return null;\n\n        return size;\n    };\n\n    this.setSession = function(session) {\n        this.session = session;\n    };\n\n    this.showInvisibles = false;\n    this.setShowInvisibles = function(showInvisibles) {\n        if (this.showInvisibles == showInvisibles)\n            return false;\n\n        this.showInvisibles = showInvisibles;\n        return true;\n    };\n\n    this.$tabStrings = [];\n    this.$computeTabString = function() {\n        var tabSize = this.session.getTabSize();\n        var tabStr = this.$tabStrings = [0];\n        for (var i = 1; i < tabSize + 1; i++) {\n            if (this.showInvisibles) {\n                tabStr.push(\"<span class='ace_invisible'>\"\n                    + this.TAB_CHAR\n                    + new Array(i).join(\"&#160;\")\n                    + \"</span>\");\n            } else {\n                tabStr.push(new Array(i+1).join(\"&#160;\"));\n            }\n        }\n\n    };\n\n    this.updateLines = function(config, firstRow, lastRow) {\n        this.$computeTabString();\n        // Due to wrap line changes there can be new lines if e.g.\n        // the line to updated wrapped in the meantime.\n        if (this.config.lastRow != config.lastRow ||\n            this.config.firstRow != config.firstRow) {\n            this.scrollLines(config);\n        }\n        this.config = config;\n\n        var first = Math.max(firstRow, config.firstRow);\n        var last = Math.min(lastRow, config.lastRow);\n\n        var lineElements = this.element.childNodes;\n        var lineElementsIdx = 0;\n\n        for (var row = config.firstRow; row < first; row++) {\n            var foldLine = this.session.getFoldLine(row);\n            if (foldLine) {\n                if (foldLine.containsRow(first)) {\n                    first = foldLine.start.row;\n                    break;\n                } else {\n                    row = foldLine.end.row;\n                }\n            }\n            lineElementsIdx ++;\n        }\n\n        for (var i=first; i<=last; i++) {\n            var lineElement = lineElements[lineElementsIdx++];\n            if (!lineElement)\n                continue;\n\n            var html = [];\n            var tokens = this.session.getTokens(i, i);\n            this.$renderLine(html, i, tokens[0].tokens, !this.$useLineGroups());\n            lineElement = dom.setInnerHtml(lineElement, html.join(\"\"));\n\n            i = this.session.getRowFoldEnd(i);\n        }\n    };\n\n    this.scrollLines = function(config) {\n        this.$computeTabString();\n        var oldConfig = this.config;\n        this.config = config;\n\n        if (!oldConfig || oldConfig.lastRow < config.firstRow)\n            return this.update(config);\n\n        if (config.lastRow < oldConfig.firstRow)\n            return this.update(config);\n\n        var el = this.element;\n        if (oldConfig.firstRow < config.firstRow)\n            for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--)\n                el.removeChild(el.firstChild);\n\n        if (oldConfig.lastRow > config.lastRow)\n            for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--)\n                el.removeChild(el.lastChild);\n\n        if (config.firstRow < oldConfig.firstRow) {\n            var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1);\n            if (el.firstChild)\n                el.insertBefore(fragment, el.firstChild);\n            else\n                el.appendChild(fragment);\n        }\n\n        if (config.lastRow > oldConfig.lastRow) {\n            var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow);\n            el.appendChild(fragment);\n        }\n    };\n\n    this.$renderLinesFragment = function(config, firstRow, lastRow) {\n        var fragment = this.element.ownerDocument.createDocumentFragment();\n        var row = firstRow;\n        var foldLine = this.session.getNextFoldLine(row);\n        var foldStart = foldLine ? foldLine.start.row : Infinity;\n\n        while (true) {\n            if (row > foldStart) {\n                row = foldLine.end.row+1;\n                foldLine = this.session.getNextFoldLine(row, foldLine);\n                foldStart = foldLine ? foldLine.start.row : Infinity;\n            }\n            if (row > lastRow)\n                break;\n\n            var container = dom.createElement(\"div\");\n\n            var html = [];\n            // Get the tokens per line as there might be some lines in between\n            // beeing folded.\n            // OPTIMIZE: If there is a long block of unfolded lines, just make\n            // this call once for that big block of unfolded lines.\n            var tokens = this.session.getTokens(row, row);\n            if (tokens.length == 1)\n                this.$renderLine(html, row, tokens[0].tokens, false);\n\n            // don't use setInnerHtml since we are working with an empty DIV\n            container.innerHTML = html.join(\"\");\n            if (this.$useLineGroups()) {\n                container.className = 'ace_line_group';\n                fragment.appendChild(container);\n            } else {\n                var lines = container.childNodes\n                while(lines.length)\n                    fragment.appendChild(lines[0]);\n            }\n\n            row++;\n        }\n        return fragment;\n    };\n\n    this.update = function(config) {\n        this.$computeTabString();\n        this.config = config;\n\n        var html = [];\n        var firstRow = config.firstRow, lastRow = config.lastRow;\n\n        var row = firstRow;\n        var foldLine = this.session.getNextFoldLine(row);\n        var foldStart = foldLine ? foldLine.start.row : Infinity;\n\n        while (true) {\n            if (row > foldStart) {\n                row = foldLine.end.row+1;\n                foldLine = this.session.getNextFoldLine(row, foldLine);\n                foldStart = foldLine ? foldLine.start.row :Infinity;\n            }\n            if (row > lastRow)\n                break;\n\n            if (this.$useLineGroups())\n                html.push(\"<div class='ace_line_group'>\")\n\n            // Get the tokens per line as there might be some lines in between\n            // beeing folded.\n            // OPTIMIZE: If there is a long block of unfolded lines, just make\n            // this call once for that big block of unfolded lines.\n            var tokens = this.session.getTokens(row, row);\n            if (tokens.length == 1)\n                this.$renderLine(html, row, tokens[0].tokens, false);\n\n            if (this.$useLineGroups())\n                html.push(\"</div>\"); // end the line group\n\n            row++;\n        }\n        this.element = dom.setInnerHtml(this.element, html.join(\"\"));\n    };\n\n    this.$textToken = {\n        \"text\": true,\n        \"rparen\": true,\n        \"lparen\": true\n    };\n\n    this.$renderToken = function(stringBuilder, screenColumn, token, value) {        \n        var self = this;\n        var replaceReg = /\\t|&|<|( +)|([\\v\\f \\u00a0\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u200b\\u2028\\u2029\\u3000])|[\\u1100-\\u115F]|[\\u11A3-\\u11A7]|[\\u11FA-\\u11FF]|[\\u2329-\\u232A]|[\\u2E80-\\u2E99]|[\\u2E9B-\\u2EF3]|[\\u2F00-\\u2FD5]|[\\u2FF0-\\u2FFB]|[\\u3000-\\u303E]|[\\u3041-\\u3096]|[\\u3099-\\u30FF]|[\\u3105-\\u312D]|[\\u3131-\\u318E]|[\\u3190-\\u31BA]|[\\u31C0-\\u31E3]|[\\u31F0-\\u321E]|[\\u3220-\\u3247]|[\\u3250-\\u32FE]|[\\u3300-\\u4DBF]|[\\u4E00-\\uA48C]|[\\uA490-\\uA4C6]|[\\uA960-\\uA97C]|[\\uAC00-\\uD7A3]|[\\uD7B0-\\uD7C6]|[\\uD7CB-\\uD7FB]|[\\uF900-\\uFAFF]|[\\uFE10-\\uFE19]|[\\uFE30-\\uFE52]|[\\uFE54-\\uFE66]|[\\uFE68-\\uFE6B]|[\\uFF01-\\uFF60]|[\\uFFE0-\\uFFE6]/g;\n        var replaceFunc = function(c, a, b, tabIdx, idx4) {\n            if (c.charCodeAt(0) == 32) {\n                return new Array(c.length+1).join(\"&#160;\");\n            } else if (c == \"\\t\") {\n                var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx);\n                screenColumn += tabSize - 1;\n                return self.$tabStrings[tabSize];\n            } else if (c == \"&\") {\n                if (useragent.isOldGecko)\n                    return \"&\";\n                else\n                    return \"&amp;\";\n            } else if (c == \"<\") {\n                return \"&lt;\";\n            } else if (c == \"\\u3000\") {\n                // U+3000 is both invisible AND full-width, so must be handled uniquely\n                var classToUse = self.showInvisibles ? \"ace_cjk ace_invisible\" : \"ace_cjk\";\n                var space = self.showInvisibles ? self.SPACE_CHAR : \"\";\n                screenColumn += 1;\n                return \"<span class='\" + classToUse + \"' style='width:\" +\n                    (self.config.characterWidth * 2) +\n                    \"px'>\" + space + \"</span>\";\n            } else if (c.match(/[\\v\\f \\u00a0\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u200b\\u2028\\u2029\\u3000]/)) {\n                if (self.showInvisibles) {\n                    var space = new Array(c.length+1).join(self.SPACE_CHAR);\n                    return \"<span class='ace_invisible'>\" + space + \"</span>\";\n                } else {\n                    return \"&#160;\";\n                }\n            } else {\n                screenColumn += 1;\n                return \"<span class='ace_cjk' style='width:\" +\n                    (self.config.characterWidth * 2) +\n                    \"px'>\" + c + \"</span>\";\n            }\n        };\n\n        var output = value.replace(replaceReg, replaceFunc);\n\n        if (!this.$textToken[token.type]) {\n            var classes = \"ace_\" + token.type.replace(/\\./g, \" ace_\");\n            var style = \"\";\n            if (token.type == \"fold\")\n                style = \" style='width:\" + (token.value.length * this.config.characterWidth) + \"px;' \";\n            stringBuilder.push(\"<span class='\", classes, \"'\", style, \">\", output, \"</span>\");\n        }\n        else {\n            stringBuilder.push(output);\n        }\n        return screenColumn + value.length;\n    };\n\n    this.$renderLineCore = function(stringBuilder, lastRow, tokens, splits, onlyContents) {\n        var chars = 0;\n        var split = 0;\n        var splitChars;\n        var screenColumn = 0;\n        var self = this;\n\n        if (!splits || splits.length == 0)\n            splitChars = Number.MAX_VALUE;\n        else\n            splitChars = splits[0];\n\n        if (!onlyContents) {\n            stringBuilder.push(\"<div class='ace_line' style='height:\",\n                this.config.lineHeight, \"px\",\n                \"'>\"\n            );\n        }\n        \n        for (var i = 0; i < tokens.length; i++) {\n            var token = tokens[i];\n            var value = token.value;\n\n            if (chars + value.length < splitChars) {\n                screenColumn = self.$renderToken(\n                    stringBuilder, screenColumn, token, value\n                );\n                chars += value.length;\n            }\n            else {\n                while (chars + value.length >= splitChars) {\n                    screenColumn = self.$renderToken(\n                        stringBuilder, screenColumn, \n                        token, value.substring(0, splitChars - chars)\n                    );\n                    value = value.substring(splitChars - chars);\n                    chars = splitChars;\n                    \n                    if (!onlyContents) {\n                        stringBuilder.push(\"</div>\",\n                            \"<div class='ace_line' style='height:\",\n                            this.config.lineHeight, \"px\",\n                            \"'>\"\n                        );\n                    }\n\n                    split ++;\n                    screenColumn = 0;\n                    splitChars = splits[split] || Number.MAX_VALUE;\n                }\n                if (value.length != 0) {\n                    chars += value.length;\n                    screenColumn = self.$renderToken(\n                        stringBuilder, screenColumn, token, value\n                    );\n                }\n            }\n        }\n\n        if (this.showInvisibles) {\n            if (lastRow !== this.session.getLength() - 1)\n                stringBuilder.push(\"<span class='ace_invisible'>\" + this.EOL_CHAR + \"</span>\");\n            else\n                stringBuilder.push(\"<span class='ace_invisible'>\" + this.EOF_CHAR + \"</span>\");\n        }\n        if (!onlyContents)\n            stringBuilder.push(\"</div>\");\n    };\n\n    this.$renderLine = function(stringBuilder, row, tokens, onlyContents) {\n        // Check if the line to render is folded or not. If not, things are\n        // simple, otherwise, we need to fake some things...\n        if (!this.session.isRowFolded(row)) {\n            var splits = this.session.getRowSplitData(row);\n            this.$renderLineCore(stringBuilder, row, tokens, splits, onlyContents);\n        } else {\n            this.$renderFoldLine(stringBuilder, row, tokens, onlyContents);\n        }\n    };\n\n    this.$renderFoldLine = function(stringBuilder, row, tokens, onlyContents) {\n        var session = this.session,\n            foldLine = session.getFoldLine(row),\n            renderTokens = [];\n\n        function addTokens(tokens, from, to) {\n            var idx = 0, col = 0;\n            while ((col + tokens[idx].value.length) < from) {\n                col += tokens[idx].value.length;\n                idx++;\n\n                if (idx == tokens.length) {\n                    return;\n                }\n            }\n            if (col != from) {\n                var value = tokens[idx].value.substring(from - col);\n                // Check if the token value is longer then the from...to spacing.\n                if (value.length > (to - from)) {\n                    value = value.substring(0, to - from);\n                }\n\n                renderTokens.push({\n                    type: tokens[idx].type,\n                    value: value\n                });\n\n                col = from + value.length;\n                idx += 1;\n            }\n\n            while (col < to) {\n                var value = tokens[idx].value;\n                if (value.length + col > to) {\n                    value = value.substring(0, to - col);\n                }\n                renderTokens.push({\n                    type: tokens[idx].type,\n                    value: value\n                });\n                col += value.length;\n                idx += 1;\n            }\n        }\n\n        foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) {\n            if (placeholder) {\n               renderTokens.push({\n                    type: \"fold\",\n                    value: placeholder\n                });\n            } else {\n                if (isNewRow) {\n                   tokens = this.session.getTokens(row, row)[0].tokens;\n                }\n                if (tokens.length != 0) {\n                    addTokens(tokens, lastColumn, column);\n                }\n            }\n        }.bind(this), foldLine.end.row, this.session.getLine(foldLine.end.row).length);\n\n        // TODO: Build a fake splits array!\n        var splits = this.session.$useWrapMode?this.session.$wrapData[row]:null;\n        this.$renderLineCore(stringBuilder, row, renderTokens, splits, onlyContents);\n    };\n    \n    this.$useLineGroups = function() {\n        // For the updateLines function to work correctly, it's important that the\n        // child nodes of this.element correspond on a 1-to-1 basis to rows in the \n        // document (as distinct from lines on the screen). For sessions that are\n        // wrapped, this means we need to add a layer to the node hierarchy (tagged\n        // with the class name ace_line_group).\n        return this.session.getUseWrapMode();\n    };\n\n    this.destroy = function() {\n        clearInterval(this.$pollSizeChangesTimer);\n        if (this.$measureNode)\n            this.$measureNode.parentNode.removeChild(this.$measureNode);\n        delete this.$measureNode;\n    };\n\n}).call(Text.prototype);\n\nexports.Text = Text;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/layer/text_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n    require(\"../test/mockdom\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar assert = require(\"../test/assertions\");\nvar EditSession = require(\"../edit_session\").EditSession;\nvar TextLayer = require(\"./text\").Text;\nvar JavaScriptMode = require(\"../mode/javascript\").Mode;\n\nmodule.exports = {\n\n    setUp: function(next) {\n        this.session = new EditSession(\"\");\n        this.session.setMode(new JavaScriptMode());\n        this.textLayer = new TextLayer(document.createElement(\"div\"));\n        this.textLayer.setSession(this.session);\n        this.textLayer.config = {\n            characterWidth: 10,\n            lineHeight: 20\n        };\n        next()\n    },\n\n    \"test: render line with hard tabs should render the same as lines with soft tabs\" : function() {\n        this.session.setValue(\"a\\ta\\ta\\t\\na   a   a   \\n\");\n        this.textLayer.$computeTabString();\n        \n        // row with hard tabs\n        var row = 0;\n        var tokens = this.session.getTokens(row, row)[0].tokens;\n        var stringBuilder = [];\n        this.textLayer.$renderLine(stringBuilder, row, tokens);\n        \n        // row with soft tabs\n        row = 1;\n        tokens = this.session.getTokens(row, row)[0].tokens;\n        var stringBuilder2 = [];\n        this.textLayer.$renderLine(stringBuilder2, row, tokens);\n        assert.equal(stringBuilder.join(\"\"), stringBuilder2.join(\"\"));\n    },\n    \n    \"test rendering width of ideographic space (U+3000)\" : function() {\n        this.session.setValue(\"\\u3000\");\n        \n        var tokens = this.session.getTokens(0, 0)[0].tokens;\n        var stringBuilder = [];\n        this.textLayer.$renderLine(stringBuilder, 0, tokens, true);\n        assert.equal(stringBuilder.join(\"\"), \"<span class='ace_cjk' style='width:20px'></span>\");\n\n        this.textLayer.setShowInvisibles(true);\n        var stringBuilder = [];\n        this.textLayer.$renderLine(stringBuilder, 0, tokens, true);\n        assert.equal(\n            stringBuilder.join(\"\"),\n            \"<span class='ace_cjk ace_invisible' style='width:20px'>\" + this.textLayer.SPACE_CHAR + \"</span>\"\n            + \"<span class='ace_invisible'>\\xB6</span>\"\n        );\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/lib/browser_focus.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)\n *      Julian Viereck <julian.viereck@gmail.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"./oop\");\nvar event = require(\"./event\");\nvar EventEmitter = require(\"./event_emitter\").EventEmitter;\n\n/**\n * This class keeps track of the focus state of the given window.\n * Focus changes for example when the user switches a browser tab,\n * goes to the location bar or switches to another application.\n */ \nvar BrowserFocus = function(win) {\n    win = win || window;\n    \n    this.lastFocus = new Date().getTime();\n    this._isFocused = true;\n    \n    var _self = this;\n\n    // IE < 9 supports focusin and focusout events\n    if (\"onfocusin\" in win.document) {\n        event.addListener(win.document, \"focusin\", function(e) {\n            _self._setFocused(true);\n        });\n\n        event.addListener(win.document, \"focusout\", function(e) {\n            _self._setFocused(!!e.toElement);\n        });\n    }\n    else {\n        event.addListener(win, \"blur\", function(e) {\n            _self._setFocused(false);\n        });\n\n        event.addListener(win, \"focus\", function(e) {\n            _self._setFocused(true);\n        });\n    }\n};\n\n(function(){\n\n    oop.implement(this, EventEmitter);\n    \n    this.isFocused = function() {\n        return this._isFocused;\n    };\n    \n    this._setFocused = function(isFocused) {\n        if (this._isFocused == isFocused)\n            return;\n            \n        if (isFocused)\n            this.lastFocus = new Date().getTime();\n            \n        this._isFocused = isFocused;\n        this._emit(\"changeFocus\");\n    };\n\n}).call(BrowserFocus.prototype);\n\n\nexports.BrowserFocus = BrowserFocus;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/lib/dom.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Mihai Sucan <mihai AT sucan AT gmail ODT com>\n *      Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar XHTML_NS = \"http://www.w3.org/1999/xhtml\";\n\nexports.createElement = function(tag, ns) {\n    return document.createElementNS ?\n           document.createElementNS(ns || XHTML_NS, tag) :\n           document.createElement(tag);\n};\n\nexports.setText = function(elem, text) {\n    if (elem.innerText !== undefined) {\n        elem.innerText = text;\n    }\n    if (elem.textContent !== undefined) {\n        elem.textContent = text;\n    }\n};\n\nexports.hasCssClass = function(el, name) {\n    var classes = el.className.split(/\\s+/g);\n    return classes.indexOf(name) !== -1;\n};\n\n/**\n* Add a CSS class to the list of classes on the given node\n*/\nexports.addCssClass = function(el, name) {\n    if (!exports.hasCssClass(el, name)) {\n        el.className += \" \" + name;\n    }\n};\n\n/**\n* Remove a CSS class from the list of classes on the given node\n*/\nexports.removeCssClass = function(el, name) {\n    var classes = el.className.split(/\\s+/g);\n    while (true) {\n        var index = classes.indexOf(name);\n        if (index == -1) {\n            break;\n        }\n        classes.splice(index, 1);\n    }\n    el.className = classes.join(\" \");\n};\n\nexports.toggleCssClass = function(el, name) {\n    var classes = el.className.split(/\\s+/g), add = true;\n    while (true) {\n        var index = classes.indexOf(name);\n        if (index == -1) {\n            break;\n        }\n        add = false;\n        classes.splice(index, 1);\n    }\n    if(add)\n        classes.push(name);\n\n    el.className = classes.join(\" \");\n    return add;\n};\n\n/**\n * Add or remove a CSS class from the list of classes on the given node\n * depending on the value of <tt>include</tt>\n */\nexports.setCssClass = function(node, className, include) {\n    if (include) {\n        exports.addCssClass(node, className);\n    } else {\n        exports.removeCssClass(node, className);\n    }\n};\n\nexports.hasCssString = function(id, doc) {\n    var index = 0, sheets;\n    doc = doc || document;\n\n    if (doc.createStyleSheet && (sheets = doc.styleSheets)) {\n        while (index < sheets.length)\n            if (sheets[index++].owningElement.id === id) return true;\n    } else if ((sheets = doc.getElementsByTagName(\"style\"))) {\n        while (index < sheets.length)\n            if (sheets[index++].id === id) return true;\n    }\n\n    return false;\n};\n\nexports.importCssString = function importCssString(cssText, id, doc) {\n    doc = doc || document;\n    // If style is already imported return immediately.\n    if (id && exports.hasCssString(id, doc))\n        return null;\n    \n    var style;\n    \n    if (doc.createStyleSheet) {\n        style = doc.createStyleSheet();\n        style.cssText = cssText;\n        if (id)\n            style.owningElement.id = id;\n    } else {\n        style = doc.createElementNS\n            ? doc.createElementNS(XHTML_NS, \"style\")\n            : doc.createElement(\"style\");\n\n        style.appendChild(doc.createTextNode(cssText));\n        if (id)\n            style.id = id;\n\n        var head = doc.getElementsByTagName(\"head\")[0] || doc.documentElement;\n        head.appendChild(style);\n    }\n};\n\nexports.importCssStylsheet = function(uri, doc) {\n    if (doc.createStyleSheet) {\n        doc.createStyleSheet(uri);\n    } else {\n        var link = exports.createElement('link');\n        link.rel = 'stylesheet';\n        link.href = uri;\n\n        var head = doc.getElementsByTagName(\"head\")[0] || doc.documentElement;\n        head.appendChild(link);\n    }\n};\n\nexports.getInnerWidth = function(element) {\n    return (\n        parseInt(exports.computedStyle(element, \"paddingLeft\"), 10) +\n        parseInt(exports.computedStyle(element, \"paddingRight\"), 10) + \n        element.clientWidth\n    );\n};\n\nexports.getInnerHeight = function(element) {\n    return (\n        parseInt(exports.computedStyle(element, \"paddingTop\"), 10) +\n        parseInt(exports.computedStyle(element, \"paddingBottom\"), 10) +\n        element.clientHeight\n    );\n};\n\nif (window.pageYOffset !== undefined) {\n    exports.getPageScrollTop = function() {\n        return window.pageYOffset;\n    };\n\n    exports.getPageScrollLeft = function() {\n        return window.pageXOffset;\n    };\n}\nelse {\n    exports.getPageScrollTop = function() {\n        return document.body.scrollTop;\n    };\n\n    exports.getPageScrollLeft = function() {\n        return document.body.scrollLeft;\n    };\n}\n\nif (window.getComputedStyle)\n    exports.computedStyle = function(element, style) {\n        if (style)\n            return (window.getComputedStyle(element, \"\") || {})[style] || \"\";\n        return window.getComputedStyle(element, \"\") || {};\n    };\nelse\n    exports.computedStyle = function(element, style) {\n        if (style)\n            return element.currentStyle[style];\n        return element.currentStyle;\n    };\n\nexports.scrollbarWidth = function(document) {\n\n    var inner = exports.createElement(\"p\");\n    inner.style.width = \"100%\";\n    inner.style.minWidth = \"0px\";\n    inner.style.height = \"200px\";\n\n    var outer = exports.createElement(\"div\");\n    var style = outer.style;\n\n    style.position = \"absolute\";\n    style.left = \"-10000px\";\n    style.overflow = \"hidden\";\n    style.width = \"200px\";\n    style.minWidth = \"0px\";\n    style.height = \"150px\";\n\n    outer.appendChild(inner);\n\n    var body = document.body || document.documentElement;\n    body.appendChild(outer);\n\n    var noScrollbar = inner.offsetWidth;\n\n    style.overflow = \"scroll\";\n    var withScrollbar = inner.offsetWidth;\n\n    if (noScrollbar == withScrollbar) {\n        withScrollbar = outer.clientWidth;\n    }\n\n    body.removeChild(outer);\n\n    return noScrollbar-withScrollbar;\n};\n\n/**\n * Optimized set innerHTML. This is faster than plain innerHTML if the element\n * already contains a lot of child elements.\n *\n * See http://blog.stevenlevithan.com/archives/faster-than-innerhtml for details\n */\nexports.setInnerHtml = function(el, innerHtml) {\n    var element = el.cloneNode(false);//document.createElement(\"div\");\n    element.innerHTML = innerHtml;\n    el.parentNode.replaceChild(element, el);\n    return element;\n};\n\nexports.setInnerText = function(el, innerText) {\n    var document = el.ownerDocument;\n    if (document.body && \"textContent\" in document.body)\n        el.textContent = innerText;\n    else\n        el.innerText = innerText;\n\n};\n\nexports.getInnerText = function(el) {\n    var document = el.ownerDocument;\n    if (document.body && \"textContent\" in document.body)\n        return el.textContent;\n    else\n         return el.innerText || el.textContent || \"\";\n};\n\nexports.getParentWindow = function(document) {\n    return document.defaultView || document.parentWindow;\n};\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/lib/es5-shim.js",
    "content": "// vim: ts=4 sts=4 sw=4 expandtab\n// -- kriskowal Kris Kowal Copyright (C) 2009-2011 MIT License\n// -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project)\n// -- dantman Daniel Friesen Copyright (C) 2010 XXX TODO License or CLA\n// -- fschaefer Florian Schäfer Copyright (C) 2010 MIT License\n// -- Gozala Irakli Gozalishvili Copyright (C) 2010 MIT License\n// -- kitcambridge Kit Cambridge Copyright (C) 2011 MIT License\n// -- kossnocorp Sasha Koss XXX TODO License or CLA\n// -- bryanforbes Bryan Forbes XXX TODO License or CLA\n// -- killdream Quildreen Motta Copyright (C) 2011 MIT Licence\n// -- michaelficarra Michael Ficarra Copyright (C) 2011 3-clause BSD License\n// -- sharkbrainguy Gerard Paapu Copyright (C) 2011 MIT License\n// -- bbqsrc Brendan Molloy (C) 2011 Creative Commons Zero (public domain)\n// -- iwyg XXX TODO License or CLA\n// -- DomenicDenicola Domenic Denicola Copyright (C) 2011 MIT License\n// -- xavierm02 Montillet Xavier XXX TODO License or CLA\n// -- Raynos Raynos XXX TODO License or CLA\n// -- samsonjs Sami Samhuri Copyright (C) 2010 MIT License\n// -- rwldrn Rick Waldron Copyright (C) 2011 MIT License\n// -- lexer Alexey Zakharov XXX TODO License or CLA\n\n/*!\n    Copyright (c) 2009, 280 North Inc. http://280north.com/\n    MIT License. http://github.com/280north/narwhal/blob/master/README.md\n*/\n\ndefine(function(require, exports, module) {\n\n/**\n * Brings an environment as close to ECMAScript 5 compliance\n * as is possible with the facilities of erstwhile engines.\n *\n * Annotated ES5: http://es5.github.com/ (specific links below)\n * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf\n *\n * @module\n */\n\n/*whatsupdoc*/\n\n//\n// Function\n// ========\n//\n\n// ES-5 15.3.4.5\n// http://es5.github.com/#x15.3.4.5\n\nif (!Function.prototype.bind) {\n    Function.prototype.bind = function bind(that) { // .length is 1\n        // 1. Let Target be the this value.\n        var target = this;\n        // 2. If IsCallable(Target) is false, throw a TypeError exception.\n        if (typeof target != \"function\")\n            throw new TypeError(); // TODO message\n        // 3. Let A be a new (possibly empty) internal list of all of the\n        //   argument values provided after thisArg (arg1, arg2 etc), in order.\n        // XXX slicedArgs will stand in for \"A\" if used\n        var args = slice.call(arguments, 1); // for normal call\n        // 4. Let F be a new native ECMAScript object.\n        // 11. Set the [[Prototype]] internal property of F to the standard\n        //   built-in Function prototype object as specified in 15.3.3.1.\n        // 12. Set the [[Call]] internal property of F as described in\n        //   15.3.4.5.1.\n        // 13. Set the [[Construct]] internal property of F as described in\n        //   15.3.4.5.2.\n        // 14. Set the [[HasInstance]] internal property of F as described in\n        //   15.3.4.5.3.\n        var bound = function () {\n\n            if (this instanceof bound) {\n                // 15.3.4.5.2 [[Construct]]\n                // When the [[Construct]] internal method of a function object,\n                // F that was created using the bind function is called with a\n                // list of arguments ExtraArgs, the following steps are taken:\n                // 1. Let target be the value of F's [[TargetFunction]]\n                //   internal property.\n                // 2. If target has no [[Construct]] internal method, a\n                //   TypeError exception is thrown.\n                // 3. Let boundArgs be the value of F's [[BoundArgs]] internal\n                //   property.\n                // 4. Let args be a new list containing the same values as the\n                //   list boundArgs in the same order followed by the same\n                //   values as the list ExtraArgs in the same order.\n                // 5. Return the result of calling the [[Construct]] internal \n                //   method of target providing args as the arguments.\n\n                var F = function(){};\n                F.prototype = target.prototype;\n                var self = new F;\n\n                var result = target.apply(\n                    self,\n                    args.concat(slice.call(arguments))\n                );\n                if (result !== null && Object(result) === result)\n                    return result;\n                return self;\n\n            } else {\n                // 15.3.4.5.1 [[Call]]\n                // When the [[Call]] internal method of a function object, F,\n                // which was created using the bind function is called with a\n                // this value and a list of arguments ExtraArgs, the following\n                // steps are taken:\n                // 1. Let boundArgs be the value of F's [[BoundArgs]] internal\n                //   property.\n                // 2. Let boundThis be the value of F's [[BoundThis]] internal\n                //   property.\n                // 3. Let target be the value of F's [[TargetFunction]] internal\n                //   property.\n                // 4. Let args be a new list containing the same values as the \n                //   list boundArgs in the same order followed by the same \n                //   values as the list ExtraArgs in the same order.\n                // 5. Return the result of calling the [[Call]] internal method \n                //   of target providing boundThis as the this value and \n                //   providing args as the arguments.\n\n                // equiv: target.call(this, ...boundArgs, ...args)\n                return target.apply(\n                    that,\n                    args.concat(slice.call(arguments))\n                );\n\n            }\n\n        };\n        // XXX bound.length is never writable, so don't even try\n        //\n        // 15. If the [[Class]] internal property of Target is \"Function\", then\n        //     a. Let L be the length property of Target minus the length of A.\n        //     b. Set the length own property of F to either 0 or L, whichever is \n        //       larger.\n        // 16. Else set the length own property of F to 0.\n        // 17. Set the attributes of the length own property of F to the values\n        //   specified in 15.3.5.1.\n\n        // TODO\n        // 18. Set the [[Extensible]] internal property of F to true.\n        \n        // TODO\n        // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).\n        // 20. Call the [[DefineOwnProperty]] internal method of F with \n        //   arguments \"caller\", PropertyDescriptor {[[Get]]: thrower, [[Set]]:\n        //   thrower, [[Enumerable]]: false, [[Configurable]]: false}, and \n        //   false.\n        // 21. Call the [[DefineOwnProperty]] internal method of F with \n        //   arguments \"arguments\", PropertyDescriptor {[[Get]]: thrower, \n        //   [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},\n        //   and false.\n\n        // TODO\n        // NOTE Function objects created using Function.prototype.bind do not \n        // have a prototype property or the [[Code]], [[FormalParameters]], and\n        // [[Scope]] internal properties.\n        // XXX can't delete prototype in pure-js.\n\n        // 22. Return F.\n        return bound;\n    };\n}\n\n// Shortcut to an often accessed properties, in order to avoid multiple\n// dereference that costs universally.\n// _Please note: Shortcuts are defined after `Function.prototype.bind` as we\n// us it in defining shortcuts.\nvar call = Function.prototype.call;\nvar prototypeOfArray = Array.prototype;\nvar prototypeOfObject = Object.prototype;\nvar slice = prototypeOfArray.slice;\nvar toString = call.bind(prototypeOfObject.toString);\nvar owns = call.bind(prototypeOfObject.hasOwnProperty);\n\n// If JS engine supports accessors creating shortcuts.\nvar defineGetter;\nvar defineSetter;\nvar lookupGetter;\nvar lookupSetter;\nvar supportsAccessors;\nif ((supportsAccessors = owns(prototypeOfObject, \"__defineGetter__\"))) {\n    defineGetter = call.bind(prototypeOfObject.__defineGetter__);\n    defineSetter = call.bind(prototypeOfObject.__defineSetter__);\n    lookupGetter = call.bind(prototypeOfObject.__lookupGetter__);\n    lookupSetter = call.bind(prototypeOfObject.__lookupSetter__);\n}\n\n//\n// Array\n// =====\n//\n\n// ES5 15.4.3.2\n// http://es5.github.com/#x15.4.3.2\n// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray\nif (!Array.isArray) {\n    Array.isArray = function isArray(obj) {\n        return toString(obj) == \"[object Array]\";\n    };\n}\n\n// The IsCallable() check in the Array functions\n// has been replaced with a strict check on the\n// internal class of the object to trap cases where\n// the provided function was actually a regular\n// expression literal, which in V8 and\n// JavaScriptCore is a typeof \"function\".  Only in\n// V8 are regular expression literals permitted as\n// reduce parameters, so it is desirable in the\n// general case for the shim to match the more\n// strict and common behavior of rejecting regular\n// expressions.\n\n// ES5 15.4.4.18\n// http://es5.github.com/#x15.4.4.18\n// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach\nif (!Array.prototype.forEach) {\n    Array.prototype.forEach = function forEach(fun /*, thisp*/) {\n        var self = toObject(this),\n            thisp = arguments[1],\n            i = 0,\n            length = self.length >>> 0;\n\n        // If no callback function or if callback is not a callable function\n        if (toString(fun) != \"[object Function]\") {\n            throw new TypeError(); // TODO message\n        }\n\n        while (i < length) {\n            if (i in self) {\n                // Invoke the callback function with call, passing arguments:\n                // context, property value, property key, thisArg object context\n                fun.call(thisp, self[i], i, self);\n            }\n            i++;\n        }\n    };\n}\n\n// ES5 15.4.4.19\n// http://es5.github.com/#x15.4.4.19\n// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map\nif (!Array.prototype.map) {\n    Array.prototype.map = function map(fun /*, thisp*/) {\n        var self = toObject(this),\n            length = self.length >>> 0,\n            result = Array(length),\n            thisp = arguments[1];\n\n        // If no callback function or if callback is not a callable function\n        if (toString(fun) != \"[object Function]\") {\n            throw new TypeError(); // TODO message\n        }\n\n        for (var i = 0; i < length; i++) {\n            if (i in self)\n                result[i] = fun.call(thisp, self[i], i, self);\n        }\n        return result;\n    };\n}\n\n// ES5 15.4.4.20\n// http://es5.github.com/#x15.4.4.20\n// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter\nif (!Array.prototype.filter) {\n    Array.prototype.filter = function filter(fun /*, thisp */) {\n        var self = toObject(this),\n            length = self.length >>> 0,\n            result = [],\n            thisp = arguments[1];\n\n        // If no callback function or if callback is not a callable function\n        if (toString(fun) != \"[object Function]\") {\n            throw new TypeError(); // TODO message\n        }\n\n        for (var i = 0; i < length; i++) {\n            if (i in self && fun.call(thisp, self[i], i, self))\n                result.push(self[i]);\n        }\n        return result;\n    };\n}\n\n// ES5 15.4.4.16\n// http://es5.github.com/#x15.4.4.16\n// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every\nif (!Array.prototype.every) {\n    Array.prototype.every = function every(fun /*, thisp */) {\n        var self = toObject(this),\n            length = self.length >>> 0,\n            thisp = arguments[1];\n\n        // If no callback function or if callback is not a callable function\n        if (toString(fun) != \"[object Function]\") {\n            throw new TypeError(); // TODO message\n        }\n\n        for (var i = 0; i < length; i++) {\n            if (i in self && !fun.call(thisp, self[i], i, self))\n                return false;\n        }\n        return true;\n    };\n}\n\n// ES5 15.4.4.17\n// http://es5.github.com/#x15.4.4.17\n// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some\nif (!Array.prototype.some) {\n    Array.prototype.some = function some(fun /*, thisp */) {\n        var self = toObject(this),\n            length = self.length >>> 0,\n            thisp = arguments[1];\n\n        // If no callback function or if callback is not a callable function\n        if (toString(fun) != \"[object Function]\") {\n            throw new TypeError(); // TODO message\n        }\n\n        for (var i = 0; i < length; i++) {\n            if (i in self && fun.call(thisp, self[i], i, self))\n                return true;\n        }\n        return false;\n    };\n}\n\n// ES5 15.4.4.21\n// http://es5.github.com/#x15.4.4.21\n// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce\nif (!Array.prototype.reduce) {\n    Array.prototype.reduce = function reduce(fun /*, initial*/) {\n        var self = toObject(this),\n            length = self.length >>> 0;\n\n        // If no callback function or if callback is not a callable function\n        if (toString(fun) != \"[object Function]\") {\n            throw new TypeError(); // TODO message\n        }\n\n        // no value to return if no initial value and an empty array\n        if (!length && arguments.length == 1)\n            throw new TypeError(); // TODO message\n\n        var i = 0;\n        var result;\n        if (arguments.length >= 2) {\n            result = arguments[1];\n        } else {\n            do {\n                if (i in self) {\n                    result = self[i++];\n                    break;\n                }\n\n                // if array contains no values, no initial value to return\n                if (++i >= length)\n                    throw new TypeError(); // TODO message\n            } while (true);\n        }\n\n        for (; i < length; i++) {\n            if (i in self)\n                result = fun.call(void 0, result, self[i], i, self);\n        }\n\n        return result;\n    };\n}\n\n// ES5 15.4.4.22\n// http://es5.github.com/#x15.4.4.22\n// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight\nif (!Array.prototype.reduceRight) {\n    Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) {\n        var self = toObject(this),\n            length = self.length >>> 0;\n\n        // If no callback function or if callback is not a callable function\n        if (toString(fun) != \"[object Function]\") {\n            throw new TypeError(); // TODO message\n        }\n\n        // no value to return if no initial value, empty array\n        if (!length && arguments.length == 1)\n            throw new TypeError(); // TODO message\n\n        var result, i = length - 1;\n        if (arguments.length >= 2) {\n            result = arguments[1];\n        } else {\n            do {\n                if (i in self) {\n                    result = self[i--];\n                    break;\n                }\n\n                // if array contains no values, no initial value to return\n                if (--i < 0)\n                    throw new TypeError(); // TODO message\n            } while (true);\n        }\n\n        do {\n            if (i in this)\n                result = fun.call(void 0, result, self[i], i, self);\n        } while (i--);\n\n        return result;\n    };\n}\n\n// ES5 15.4.4.14\n// http://es5.github.com/#x15.4.4.14\n// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf\nif (!Array.prototype.indexOf) {\n    Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) {\n        var self = toObject(this),\n            length = self.length >>> 0;\n\n        if (!length)\n            return -1;\n\n        var i = 0;\n        if (arguments.length > 1)\n            i = toInteger(arguments[1]);\n\n        // handle negative indices\n        i = i >= 0 ? i : Math.max(0, length + i);\n        for (; i < length; i++) {\n            if (i in self && self[i] === sought) {\n                return i;\n            }\n        }\n        return -1;\n    };\n}\n\n// ES5 15.4.4.15\n// http://es5.github.com/#x15.4.4.15\n// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf\nif (!Array.prototype.lastIndexOf) {\n    Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) {\n        var self = toObject(this),\n            length = self.length >>> 0;\n\n        if (!length)\n            return -1;\n        var i = length - 1;\n        if (arguments.length > 1)\n            i = Math.min(i, toInteger(arguments[1]));\n        // handle negative indices\n        i = i >= 0 ? i : length - Math.abs(i);\n        for (; i >= 0; i--) {\n            if (i in self && sought === self[i])\n                return i;\n        }\n        return -1;\n    };\n}\n\n//\n// Object\n// ======\n//\n\n// ES5 15.2.3.2\n// http://es5.github.com/#x15.2.3.2\nif (!Object.getPrototypeOf) {\n    // https://github.com/kriskowal/es5-shim/issues#issue/2\n    // http://ejohn.org/blog/objectgetprototypeof/\n    // recommended by fschaefer on github\n    Object.getPrototypeOf = function getPrototypeOf(object) {\n        return object.__proto__ || (\n            object.constructor ?\n            object.constructor.prototype :\n            prototypeOfObject\n        );\n    };\n}\n\n// ES5 15.2.3.3\n// http://es5.github.com/#x15.2.3.3\nif (!Object.getOwnPropertyDescriptor) {\n    var ERR_NON_OBJECT = \"Object.getOwnPropertyDescriptor called on a \" +\n                         \"non-object: \";\n    Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) {\n        if ((typeof object != \"object\" && typeof object != \"function\") || object === null)\n            throw new TypeError(ERR_NON_OBJECT + object);\n        // If object does not owns property return undefined immediately.\n        if (!owns(object, property))\n            return;\n\n        var descriptor, getter, setter;\n\n        // If object has a property then it's for sure both `enumerable` and\n        // `configurable`.\n        descriptor =  { enumerable: true, configurable: true };\n\n        // If JS engine supports accessor properties then property may be a\n        // getter or setter.\n        if (supportsAccessors) {\n            // Unfortunately `__lookupGetter__` will return a getter even\n            // if object has own non getter property along with a same named\n            // inherited getter. To avoid misbehavior we temporary remove\n            // `__proto__` so that `__lookupGetter__` will return getter only\n            // if it's owned by an object.\n            var prototype = object.__proto__;\n            object.__proto__ = prototypeOfObject;\n\n            var getter = lookupGetter(object, property);\n            var setter = lookupSetter(object, property);\n\n            // Once we have getter and setter we can put values back.\n            object.__proto__ = prototype;\n\n            if (getter || setter) {\n                if (getter) descriptor.get = getter;\n                if (setter) descriptor.set = setter;\n\n                // If it was accessor property we're done and return here\n                // in order to avoid adding `value` to the descriptor.\n                return descriptor;\n            }\n        }\n\n        // If we got this far we know that object has an own property that is\n        // not an accessor so we set it as a value and return descriptor.\n        descriptor.value = object[property];\n        return descriptor;\n    };\n}\n\n// ES5 15.2.3.4\n// http://es5.github.com/#x15.2.3.4\nif (!Object.getOwnPropertyNames) {\n    Object.getOwnPropertyNames = function getOwnPropertyNames(object) {\n        return Object.keys(object);\n    };\n}\n\n// ES5 15.2.3.5\n// http://es5.github.com/#x15.2.3.5\nif (!Object.create) {\n    Object.create = function create(prototype, properties) {\n        var object;\n        if (prototype === null) {\n            object = { \"__proto__\": null };\n        } else {\n            if (typeof prototype != \"object\")\n                throw new TypeError(\"typeof prototype[\"+(typeof prototype)+\"] != 'object'\");\n            var Type = function () {};\n            Type.prototype = prototype;\n            object = new Type();\n            // IE has no built-in implementation of `Object.getPrototypeOf`\n            // neither `__proto__`, but this manually setting `__proto__` will\n            // guarantee that `Object.getPrototypeOf` will work as expected with\n            // objects created using `Object.create`\n            object.__proto__ = prototype;\n        }\n        if (properties !== void 0)\n            Object.defineProperties(object, properties);\n        return object;\n    };\n}\n\n// ES5 15.2.3.6\n// http://es5.github.com/#x15.2.3.6\n\n// Patch for WebKit and IE8 standard mode\n// Designed by hax <hax.github.com>\n// related issue: https://github.com/kriskowal/es5-shim/issues#issue/5\n// IE8 Reference:\n//     http://msdn.microsoft.com/en-us/library/dd282900.aspx\n//     http://msdn.microsoft.com/en-us/library/dd229916.aspx\n// WebKit Bugs:\n//     https://bugs.webkit.org/show_bug.cgi?id=36423\n\nfunction doesDefinePropertyWork(object) {\n    try {\n        Object.defineProperty(object, \"sentinel\", {});\n        return \"sentinel\" in object;\n    } catch (exception) {\n        // returns falsy\n    }\n}\n\n// check whether defineProperty works if it's given. Otherwise,\n// shim partially.\nif (Object.defineProperty) {\n    var definePropertyWorksOnObject = doesDefinePropertyWork({});\n    var definePropertyWorksOnDom = typeof document == \"undefined\" ||\n        doesDefinePropertyWork(document.createElement(\"div\"));\n    if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) {\n        var definePropertyFallback = Object.defineProperty;\n    }\n}\n\nif (!Object.defineProperty || definePropertyFallback) {\n    var ERR_NON_OBJECT_DESCRIPTOR = \"Property description must be an object: \";\n    var ERR_NON_OBJECT_TARGET = \"Object.defineProperty called on non-object: \"\n    var ERR_ACCESSORS_NOT_SUPPORTED = \"getters & setters can not be defined \" +\n                                      \"on this javascript engine\";\n\n    Object.defineProperty = function defineProperty(object, property, descriptor) {\n        if ((typeof object != \"object\" && typeof object != \"function\") || object === null)\n            throw new TypeError(ERR_NON_OBJECT_TARGET + object);\n        if ((typeof descriptor != \"object\" && typeof descriptor != \"function\") || descriptor === null)\n            throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor);\n\n        // make a valiant attempt to use the real defineProperty\n        // for I8's DOM elements.\n        if (definePropertyFallback) {\n            try {\n                return definePropertyFallback.call(Object, object, property, descriptor);\n            } catch (exception) {\n                // try the shim if the real one doesn't work\n            }\n        }\n\n        // If it's a data property.\n        if (owns(descriptor, \"value\")) {\n            // fail silently if \"writable\", \"enumerable\", or \"configurable\"\n            // are requested but not supported\n            /*\n            // alternate approach:\n            if ( // can't implement these features; allow false but not true\n                !(owns(descriptor, \"writable\") ? descriptor.writable : true) ||\n                !(owns(descriptor, \"enumerable\") ? descriptor.enumerable : true) ||\n                !(owns(descriptor, \"configurable\") ? descriptor.configurable : true)\n            )\n                throw new RangeError(\n                    \"This implementation of Object.defineProperty does not \" +\n                    \"support configurable, enumerable, or writable.\"\n                );\n            */\n\n            if (supportsAccessors && (lookupGetter(object, property) ||\n                                      lookupSetter(object, property)))\n            {\n                // As accessors are supported only on engines implementing\n                // `__proto__` we can safely override `__proto__` while defining\n                // a property to make sure that we don't hit an inherited\n                // accessor.\n                var prototype = object.__proto__;\n                object.__proto__ = prototypeOfObject;\n                // Deleting a property anyway since getter / setter may be\n                // defined on object itself.\n                delete object[property];\n                object[property] = descriptor.value;\n                // Setting original `__proto__` back now.\n                object.__proto__ = prototype;\n            } else {\n                object[property] = descriptor.value;\n            }\n        } else {\n            if (!supportsAccessors)\n                throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED);\n            // If we got that far then getters and setters can be defined !!\n            if (owns(descriptor, \"get\"))\n                defineGetter(object, property, descriptor.get);\n            if (owns(descriptor, \"set\"))\n                defineSetter(object, property, descriptor.set);\n        }\n\n        return object;\n    };\n}\n\n// ES5 15.2.3.7\n// http://es5.github.com/#x15.2.3.7\nif (!Object.defineProperties) {\n    Object.defineProperties = function defineProperties(object, properties) {\n        for (var property in properties) {\n            if (owns(properties, property))\n                Object.defineProperty(object, property, properties[property]);\n        }\n        return object;\n    };\n}\n\n// ES5 15.2.3.8\n// http://es5.github.com/#x15.2.3.8\nif (!Object.seal) {\n    Object.seal = function seal(object) {\n        // this is misleading and breaks feature-detection, but\n        // allows \"securable\" code to \"gracefully\" degrade to working\n        // but insecure code.\n        return object;\n    };\n}\n\n// ES5 15.2.3.9\n// http://es5.github.com/#x15.2.3.9\nif (!Object.freeze) {\n    Object.freeze = function freeze(object) {\n        // this is misleading and breaks feature-detection, but\n        // allows \"securable\" code to \"gracefully\" degrade to working\n        // but insecure code.\n        return object;\n    };\n}\n\n// detect a Rhino bug and patch it\ntry {\n    Object.freeze(function () {});\n} catch (exception) {\n    Object.freeze = (function freeze(freezeObject) {\n        return function freeze(object) {\n            if (typeof object == \"function\") {\n                return object;\n            } else {\n                return freezeObject(object);\n            }\n        };\n    })(Object.freeze);\n}\n\n// ES5 15.2.3.10\n// http://es5.github.com/#x15.2.3.10\nif (!Object.preventExtensions) {\n    Object.preventExtensions = function preventExtensions(object) {\n        // this is misleading and breaks feature-detection, but\n        // allows \"securable\" code to \"gracefully\" degrade to working\n        // but insecure code.\n        return object;\n    };\n}\n\n// ES5 15.2.3.11\n// http://es5.github.com/#x15.2.3.11\nif (!Object.isSealed) {\n    Object.isSealed = function isSealed(object) {\n        return false;\n    };\n}\n\n// ES5 15.2.3.12\n// http://es5.github.com/#x15.2.3.12\nif (!Object.isFrozen) {\n    Object.isFrozen = function isFrozen(object) {\n        return false;\n    };\n}\n\n// ES5 15.2.3.13\n// http://es5.github.com/#x15.2.3.13\nif (!Object.isExtensible) {\n    Object.isExtensible = function isExtensible(object) {\n        // 1. If Type(O) is not Object throw a TypeError exception.\n        if (Object(object) === object) {\n            throw new TypeError(); // TODO message\n        }\n        // 2. Return the Boolean value of the [[Extensible]] internal property of O.\n        var name = '';\n        while (owns(object, name)) {\n            name += '?';\n        }\n        object[name] = true;\n        var returnValue = owns(object, name);\n        delete object[name];\n        return returnValue;\n    };\n}\n\n// ES5 15.2.3.14\n// http://es5.github.com/#x15.2.3.14\nif (!Object.keys) {\n    // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation\n    var hasDontEnumBug = true,\n        dontEnums = [\n            \"toString\",\n            \"toLocaleString\",\n            \"valueOf\",\n            \"hasOwnProperty\",\n            \"isPrototypeOf\",\n            \"propertyIsEnumerable\",\n            \"constructor\"\n        ],\n        dontEnumsLength = dontEnums.length;\n\n    for (var key in {\"toString\": null})\n        hasDontEnumBug = false;\n\n    Object.keys = function keys(object) {\n\n        if ((typeof object != \"object\" && typeof object != \"function\") || object === null)\n            throw new TypeError(\"Object.keys called on a non-object\");\n\n        var keys = [];\n        for (var name in object) {\n            if (owns(object, name)) {\n                keys.push(name);\n            }\n        }\n\n        if (hasDontEnumBug) {\n            for (var i = 0, ii = dontEnumsLength; i < ii; i++) {\n                var dontEnum = dontEnums[i];\n                if (owns(object, dontEnum)) {\n                    keys.push(dontEnum);\n                }\n            }\n        }\n\n        return keys;\n    };\n\n}\n\n//\n// Date\n// ====\n//\n\n// ES5 15.9.5.43\n// http://es5.github.com/#x15.9.5.43\n// This function returns a String value represent the instance in time \n// represented by this Date object. The format of the String is the Date Time \n// string format defined in 15.9.1.15. All fields are present in the String. \n// The time zone is always UTC, denoted by the suffix Z. If the time value of \n// this object is not a finite Number a RangeError exception is thrown.\nif (!Date.prototype.toISOString || (new Date(-62198755200000).toISOString().indexOf('-000001') === -1)) {\n    Date.prototype.toISOString = function toISOString() {\n        var result, length, value, year;\n        if (!isFinite(this))\n            throw new RangeError;\n\n        // the date time string format is specified in 15.9.1.15.\n        result = [this.getUTCMonth() + 1, this.getUTCDate(),\n            this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];\n        year = this.getUTCFullYear();\n        year = (year < 0 ? '-' : (year > 9999 ? '+' : '')) + ('00000' + Math.abs(year)).slice(0 <= year && year <= 9999 ? -4 : -6);\n\n        length = result.length;\n        while (length--) {\n            value = result[length];\n            // pad months, days, hours, minutes, and seconds to have two digits.\n            if (value < 10)\n                result[length] = \"0\" + value;\n        }\n        // pad milliseconds to have three digits.\n        return year + \"-\" + result.slice(0, 2).join(\"-\") + \"T\" + result.slice(2).join(\":\") + \".\" +\n            (\"000\" + this.getUTCMilliseconds()).slice(-3) + \"Z\";\n    }\n}\n\n// ES5 15.9.4.4\n// http://es5.github.com/#x15.9.4.4\nif (!Date.now) {\n    Date.now = function now() {\n        return new Date().getTime();\n    };\n}\n\n// ES5 15.9.5.44\n// http://es5.github.com/#x15.9.5.44\n// This function provides a String representation of a Date object for use by \n// JSON.stringify (15.12.3).\nif (!Date.prototype.toJSON) {\n    Date.prototype.toJSON = function toJSON(key) {\n        // When the toJSON method is called with argument key, the following \n        // steps are taken:\n\n        // 1.  Let O be the result of calling ToObject, giving it the this\n        // value as its argument.\n        // 2. Let tv be ToPrimitive(O, hint Number).\n        // 3. If tv is a Number and is not finite, return null.\n        // XXX\n        // 4. Let toISO be the result of calling the [[Get]] internal method of\n        // O with argument \"toISOString\".\n        // 5. If IsCallable(toISO) is false, throw a TypeError exception.\n        if (typeof this.toISOString != \"function\")\n            throw new TypeError(); // TODO message\n        // 6. Return the result of calling the [[Call]] internal method of\n        //  toISO with O as the this value and an empty argument list.\n        return this.toISOString();\n\n        // NOTE 1 The argument is ignored.\n\n        // NOTE 2 The toJSON function is intentionally generic; it does not\n        // require that its this value be a Date object. Therefore, it can be\n        // transferred to other kinds of objects for use as a method. However,\n        // it does require that any such object have a toISOString method. An\n        // object is free to use the argument key to filter its\n        // stringification.\n    };\n}\n\n// ES5 15.9.4.2\n// http://es5.github.com/#x15.9.4.2\n// based on work shared by Daniel Friesen (dantman)\n// http://gist.github.com/303249\nif (Date.parse(\"+275760-09-13T00:00:00.000Z\") !== 8.64e15) {\n    // XXX global assignment won't work in embeddings that use\n    // an alternate object for the context.\n    Date = (function(NativeDate) {\n\n        // Date.length === 7\n        var Date = function Date(Y, M, D, h, m, s, ms) {\n            var length = arguments.length;\n            if (this instanceof NativeDate) {\n                var date = length == 1 && String(Y) === Y ? // isString(Y)\n                    // We explicitly pass it through parse:\n                    new NativeDate(Date.parse(Y)) :\n                    // We have to manually make calls depending on argument\n                    // length here\n                    length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) :\n                    length >= 6 ? new NativeDate(Y, M, D, h, m, s) :\n                    length >= 5 ? new NativeDate(Y, M, D, h, m) :\n                    length >= 4 ? new NativeDate(Y, M, D, h) :\n                    length >= 3 ? new NativeDate(Y, M, D) :\n                    length >= 2 ? new NativeDate(Y, M) :\n                    length >= 1 ? new NativeDate(Y) :\n                                  new NativeDate();\n                // Prevent mixups with unfixed Date object\n                date.constructor = Date;\n                return date;\n            }\n            return NativeDate.apply(this, arguments);\n        };\n\n        // 15.9.1.15 Date Time String Format.\n        var isoDateExpression = new RegExp(\"^\" +\n            \"(\\\\d{4}|[\\+\\-]\\\\d{6})\" + // four-digit year capture or sign + 6-digit extended year\n            \"(?:-(\\\\d{2})\" + // optional month capture\n            \"(?:-(\\\\d{2})\" + // optional day capture\n            \"(?:\" + // capture hours:minutes:seconds.milliseconds\n                \"T(\\\\d{2})\" + // hours capture\n                \":(\\\\d{2})\" + // minutes capture\n                \"(?:\" + // optional :seconds.milliseconds\n                    \":(\\\\d{2})\" + // seconds capture\n                    \"(?:\\\\.(\\\\d{3}))?\" + // milliseconds capture\n                \")?\" +\n            \"(?:\" + // capture UTC offset component\n                \"Z|\" + // UTC capture\n                \"(?:\" + // offset specifier +/-hours:minutes\n                    \"([-+])\" + // sign capture\n                    \"(\\\\d{2})\" + // hours offset capture\n                    \":(\\\\d{2})\" + // minutes offset capture\n                \")\" +\n            \")?)?)?)?\" +\n        \"$\");\n\n        // Copy any custom methods a 3rd party library may have added\n        for (var key in NativeDate)\n            Date[key] = NativeDate[key];\n\n        // Copy \"native\" methods explicitly; they may be non-enumerable\n        Date.now = NativeDate.now;\n        Date.UTC = NativeDate.UTC;\n        Date.prototype = NativeDate.prototype;\n        Date.prototype.constructor = Date;\n\n        // Upgrade Date.parse to handle simplified ISO 8601 strings\n        Date.parse = function parse(string) {\n            var match = isoDateExpression.exec(string);\n            if (match) {\n                match.shift(); // kill match[0], the full match\n                // parse months, days, hours, minutes, seconds, and milliseconds\n                for (var i = 1; i < 7; i++) {\n                    // provide default values if necessary\n                    match[i] = +(match[i] || (i < 3 ? 1 : 0));\n                    // match[1] is the month. Months are 0-11 in JavaScript\n                    // `Date` objects, but 1-12 in ISO notation, so we\n                    // decrement.\n                    if (i == 1)\n                        match[i]--;\n                }\n\n                // parse the UTC offset component\n                var minuteOffset = +match.pop(), hourOffset = +match.pop(), sign = match.pop();\n\n                // compute the explicit time zone offset if specified\n                var offset = 0;\n                if (sign) {\n                    // detect invalid offsets and return early\n                    if (hourOffset > 23 || minuteOffset > 59)\n                        return NaN;\n\n                    // express the provided time zone offset in minutes. The offset is\n                    // negative for time zones west of UTC; positive otherwise.\n                    offset = (hourOffset * 60 + minuteOffset) * 6e4 * (sign == \"+\" ? -1 : 1);\n                }\n\n                // Date.UTC for years between 0 and 99 converts year to 1900 + year\n                // The Gregorian calendar has a 400-year cycle, so \n                // to Date.UTC(year + 400, .... ) - 12622780800000 == Date.UTC(year, ...),\n                // where 12622780800000 - number of milliseconds in Gregorian calendar 400 years\n                var year = +match[0];\n                if (0 <= year && year <= 99) {\n                    match[0] = year + 400;\n                    return NativeDate.UTC.apply(this, match) + offset - 12622780800000;\n                }\n\n                // compute a new UTC date value, accounting for the optional offset\n                return NativeDate.UTC.apply(this, match) + offset;\n            }\n            return NativeDate.parse.apply(this, arguments);\n        };\n\n        return Date;\n    })(Date);\n}\n\n//\n// String\n// ======\n//\n\n// ES5 15.5.4.20\n// http://es5.github.com/#x15.5.4.20\nvar ws = \"\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\" +\n    \"\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\" +\n    \"\\u2029\\uFEFF\";\nif (!String.prototype.trim || ws.trim()) {\n    // http://blog.stevenlevithan.com/archives/faster-trim-javascript\n    // http://perfectionkills.com/whitespace-deviations/\n    ws = \"[\" + ws + \"]\";\n    var trimBeginRegexp = new RegExp(\"^\" + ws + ws + \"*\"),\n        trimEndRegexp = new RegExp(ws + ws + \"*$\");\n    String.prototype.trim = function trim() {\n        return String(this).replace(trimBeginRegexp, \"\").replace(trimEndRegexp, \"\");\n    };\n}\n\n//\n// Util\n// ======\n//\n\n// ES5 9.4\n// http://es5.github.com/#x9.4\n// http://jsperf.com/to-integer\nvar toInteger = function (n) {\n    n = +n;\n    if (n !== n) // isNaN\n        n = 0;\n    else if (n !== 0 && n !== (1/0) && n !== -(1/0))\n        n = (n > 0 || -1) * Math.floor(Math.abs(n));\n    return n;\n};\n\nvar prepareString = \"a\"[0] != \"a\",\n    // ES5 9.9\n    // http://es5.github.com/#x9.9\n    toObject = function (o) {\n        if (o == null) { // this matches both null and undefined\n            throw new TypeError(); // TODO message\n        }\n        // If the implementation doesn't support by-index access of\n        // string characters (ex. IE < 7), split the string\n        if (prepareString && typeof o == \"string\" && o) {\n            return o.split(\"\");\n        }\n        return Object(o);\n    };\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/lib/event.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar keys = require(\"./keys\");\nvar useragent = require(\"./useragent\");\nvar dom = require(\"./dom\");\n\nexports.addListener = function(elem, type, callback) {\n    if (elem.addEventListener) {\n        return elem.addEventListener(type, callback, false);\n    }\n    if (elem.attachEvent) {\n        var wrapper = function() {\n            callback(window.event);\n        };\n        callback._wrapper = wrapper;\n        elem.attachEvent(\"on\" + type, wrapper);\n    }\n};\n\nexports.removeListener = function(elem, type, callback) {\n    if (elem.removeEventListener) {\n        return elem.removeEventListener(type, callback, false);\n    }\n    if (elem.detachEvent) {\n        elem.detachEvent(\"on\" + type, callback._wrapper || callback);\n    }\n};\n\n/**\n* Prevents propagation and clobbers the default action of the passed event\n*/\nexports.stopEvent = function(e) {\n    exports.stopPropagation(e);\n    exports.preventDefault(e);\n    return false;\n};\n\nexports.stopPropagation = function(e) {\n    if (e.stopPropagation)\n        e.stopPropagation();\n    else\n        e.cancelBubble = true;\n};\n\nexports.preventDefault = function(e) {\n    if (e.preventDefault)\n        e.preventDefault();\n    else\n        e.returnValue = false;\n};\n\nexports.getDocumentX = function(e) {\n    if (e.clientX) {\n        return e.clientX + dom.getPageScrollLeft();\n    } else {\n        return e.pageX;\n    }\n};\n\nexports.getDocumentY = function(e) {\n    if (e.clientY) {\n        return e.clientY + dom.getPageScrollTop();\n    } else {\n        return e.pageY;\n    }\n};\n\n/**\n * @return {Number} 0 for left button, 1 for middle button, 2 for right button\n */\nexports.getButton = function(e) {\n    if (e.type == \"dblclick\")\n        return 0;\n    else if (e.type == \"contextmenu\")\n        return 2;\n\n    // DOM Event\n    if (e.preventDefault) {\n        return e.button;\n    }\n    // old IE\n    else {\n        return {1:0, 2:2, 4:1}[e.button];\n    }\n};\n\nif (document.documentElement.setCapture) {\n    exports.capture = function(el, eventHandler, releaseCaptureHandler) {\n        function onMouseMove(e) {\n            eventHandler(e);\n            return exports.stopPropagation(e);\n        }\n\n        var called = false;\n        function onReleaseCapture(e) {\n            eventHandler(e);\n\n            if (!called) {\n                called = true;\n                releaseCaptureHandler(e);\n            }\n\n            exports.removeListener(el, \"mousemove\", eventHandler);\n            exports.removeListener(el, \"mouseup\", onReleaseCapture);\n            exports.removeListener(el, \"losecapture\", onReleaseCapture);\n\n            el.releaseCapture();\n        }\n\n        exports.addListener(el, \"mousemove\", eventHandler);\n        exports.addListener(el, \"mouseup\", onReleaseCapture);\n        exports.addListener(el, \"losecapture\", onReleaseCapture);\n        el.setCapture();\n    };\n}\nelse {\n    exports.capture = function(el, eventHandler, releaseCaptureHandler) {\n        function onMouseMove(e) {\n            eventHandler(e);\n            e.stopPropagation();\n        }\n\n        function onMouseUp(e) {\n            eventHandler && eventHandler(e);\n            releaseCaptureHandler && releaseCaptureHandler(e);\n\n            document.removeEventListener(\"mousemove\", onMouseMove, true);\n            document.removeEventListener(\"mouseup\", onMouseUp, true);\n\n            e.stopPropagation();\n        }\n\n        document.addEventListener(\"mousemove\", onMouseMove, true);\n        document.addEventListener(\"mouseup\", onMouseUp, true);\n    };\n}\n\nexports.addMouseWheelListener = function(el, callback) {\n    var factor = 8;\n    var listener = function(e) {\n        if (e.wheelDelta !== undefined) {\n            if (e.wheelDeltaX !== undefined) {\n                e.wheelX = -e.wheelDeltaX / factor;\n                e.wheelY = -e.wheelDeltaY / factor;\n            } else {\n                e.wheelX = 0;\n                e.wheelY = -e.wheelDelta / factor;\n            }\n        }\n        else {\n            if (e.axis && e.axis == e.HORIZONTAL_AXIS) {\n                e.wheelX = (e.detail || 0) * 5;\n                e.wheelY = 0;\n            } else {\n                e.wheelX = 0;\n                e.wheelY = (e.detail || 0) * 5;\n            }\n        }\n        callback(e);\n    };\n    exports.addListener(el, \"DOMMouseScroll\", listener);\n    exports.addListener(el, \"mousewheel\", listener);\n};\n\nexports.addMultiMouseDownListener = function(el, button, count, timeout, callback) {\n    var clicks = 0;\n    var startX, startY;\n\n    var listener = function(e) {\n        clicks += 1;\n        if (clicks == 1) {\n            startX = e.clientX;\n            startY = e.clientY;\n\n            setTimeout(function() {\n                clicks = 0;\n            }, timeout || 600);\n        }\n\n        var isButton = exports.getButton(e) == button;\n        if (!isButton || Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5)\n            clicks = 0;\n\n        if (clicks == count) {\n            clicks = 0;\n            callback(e);\n        }\n\n        if (isButton)\n            return exports.preventDefault(e);\n    };\n\n    exports.addListener(el, \"mousedown\", listener);\n    useragent.isOldIE && exports.addListener(el, \"dblclick\", listener);\n};\n\nfunction normalizeCommandKeys(callback, e, keyCode) {\n    var hashId = 0;\n    if (useragent.isOpera && useragent.isMac) {\n        hashId = 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0)\n            | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0);\n    } else {\n        hashId = 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0)\n            | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0);\n    }\n\n    if (keyCode in keys.MODIFIER_KEYS) {\n        switch (keys.MODIFIER_KEYS[keyCode]) {\n            case \"Alt\":\n                hashId = 2;\n                break;\n            case \"Shift\":\n                hashId = 4;\n                break;\n            case \"Ctrl\":\n                hashId = 1;\n                break;\n            default:\n                hashId = 8;\n                break;\n        }\n        keyCode = 0;\n    }\n\n    if (hashId & 8 && (keyCode == 91 || keyCode == 93)) {\n        keyCode = 0;\n    }\n\n    // If there is no hashID and the keyCode is not a function key, then\n    // we don't call the callback as we don't handle a command key here\n    // (it's a normal key/character input).\n    if (!hashId && !(keyCode in keys.FUNCTION_KEYS) && !(keyCode in keys.PRINTABLE_KEYS)) {\n        return false;\n    }\n    return callback(e, hashId, keyCode);\n}\n\nexports.addCommandKeyListener = function(el, callback) {\n    var addListener = exports.addListener;\n    if (useragent.isOldGecko || useragent.isOpera) {\n        // Old versions of Gecko aka. Firefox < 4.0 didn't repeat the keydown\n        // event if the user pressed the key for a longer time. Instead, the\n        // keydown event was fired once and later on only the keypress event.\n        // To emulate the 'right' keydown behavior, the keyCode of the initial\n        // keyDown event is stored and in the following keypress events the\n        // stores keyCode is used to emulate a keyDown event.\n        var lastKeyDownKeyCode = null;\n        addListener(el, \"keydown\", function(e) {\n            lastKeyDownKeyCode = e.keyCode;\n        });\n        addListener(el, \"keypress\", function(e) {\n            return normalizeCommandKeys(callback, e, lastKeyDownKeyCode);\n        });\n    } else {\n        var lastDown = null;\n\n        addListener(el, \"keydown\", function(e) {\n            lastDown = e.keyIdentifier || e.keyCode;\n            return normalizeCommandKeys(callback, e, e.keyCode);\n        });\n    }\n};\n\nif (window.postMessage) {\n    var postMessageId = 1;\n    exports.nextTick = function(callback, win) {\n        win = win || window;\n        var messageName = \"zero-timeout-message-\" + postMessageId;            \n        exports.addListener(win, \"message\", function listener(e) {\n            if (e.data == messageName) {\n                exports.stopPropagation(e);\n                exports.removeListener(win, \"message\", listener);\n                callback();\n            }\n        });\n        win.postMessage(messageName, \"*\");\n    };\n}\nelse {\n    exports.nextTick = function(callback, win) {\n        win = win || window;\n        window.setTimeout(callback, 0);\n    };\n}\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/lib/event_emitter.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)\n *      Mike de Boer <mike AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EventEmitter = {};\n\nEventEmitter._emit =\nEventEmitter._dispatchEvent = function(eventName, e) {\n    this._eventRegistry = this._eventRegistry || {};\n    this._defaultHandlers = this._defaultHandlers || {};\n\n    var listeners = this._eventRegistry[eventName] || [];\n    var defaultHandler = this._defaultHandlers[eventName];\n    if (!listeners.length && !defaultHandler)\n        return;\n\n    e = e || {};\n    e.type = eventName;\n    \n    if (!e.stopPropagation) {\n        e.stopPropagation = function() {\n            this.propagationStopped = true;\n        };\n    }\n    \n    if (!e.preventDefault) {\n        e.preventDefault = function() {\n            this.defaultPrevented = true;\n        };\n    }\n\n    for (var i=0; i<listeners.length; i++) {\n        listeners[i](e);\n        if (e.propagationStopped)\n            break;\n    }\n    \n    if (defaultHandler && !e.defaultPrevented)\n        defaultHandler(e);\n};\n\nEventEmitter.setDefaultHandler = function(eventName, callback) {\n    this._defaultHandlers = this._defaultHandlers || {};\n    \n    if (this._defaultHandlers[eventName])\n        throw new Error(\"The default handler for '\" + eventName + \"' is already set\");\n        \n    this._defaultHandlers[eventName] = callback;\n};\n\nEventEmitter.on =\nEventEmitter.addEventListener = function(eventName, callback) {\n    this._eventRegistry = this._eventRegistry || {};\n\n    var listeners = this._eventRegistry[eventName];\n    if (!listeners)\n        var listeners = this._eventRegistry[eventName] = [];\n\n    if (listeners.indexOf(callback) == -1)\n        listeners.push(callback);\n};\n\nEventEmitter.removeListener =\nEventEmitter.removeEventListener = function(eventName, callback) {\n    this._eventRegistry = this._eventRegistry || {};\n\n    var listeners = this._eventRegistry[eventName];\n    if (!listeners)\n        return;\n\n    var index = listeners.indexOf(callback);\n    if (index !== -1)\n        listeners.splice(index, 1);\n};\n\nEventEmitter.removeAllListeners = function(eventName) {\n    if (this._eventRegistry) this._eventRegistry[eventName] = [];\n};\n\nexports.EventEmitter = EventEmitter;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/lib/event_emitter_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar EventEmitter = require(\"./event_emitter\").EventEmitter;\nvar assert = require(\"../test/assertions\");\n\nvar Emitter = function() {};\n\noop.implement(Emitter.prototype, EventEmitter);\n\nmodule.exports = {\n    \"test: dispatch event with no data\" : function() {\n        var emitter = new Emitter();\n\n        var called = false;\n        emitter.addEventListener(\"juhu\", function(e) {\n           called = true;\n           assert.equal(e.type, \"juhu\");\n        });\n\n        emitter._emit(\"juhu\");\n        assert.ok(called);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/lib/fixoldbrowsers.js",
    "content": "// vim:set ts=4 sts=4 sw=4 st:\n// -- kriskowal Kris Kowal Copyright (C) 2009-2010 MIT License\n// -- tlrobinson Tom Robinson Copyright (C) 2009-2010 MIT License (Narwhal Project)\n// -- dantman Daniel Friesen Copyright(C) 2010 XXX No License Specified\n// -- fschaefer Florian Schäfer Copyright (C) 2010 MIT License\n// -- Irakli Gozalishvili Copyright (C) 2010 MIT License\n\n/*!\n    Copyright (c) 2009, 280 North Inc. http://280north.com/\n    MIT License. http://github.com/280north/narwhal/blob/master/README.md\n*/\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nrequire(\"./regexp\");\nrequire(\"./es5-shim\");\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/lib/keys.js",
    "content": "/*! @license\n==========================================================================\nSproutCore -- JavaScript Application Framework\ncopyright 2006-2009, Sprout Systems Inc., Apple Inc. and contributors.\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the \"Software\"),\nto deal in the Software without restriction, including without limitation\nthe rights to use, copy, modify, merge, publish, distribute, sublicense,\nand/or sell copies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n\nSproutCore and the SproutCore logo are trademarks of Sprout Systems, Inc.\n\nFor more information about SproutCore, visit http://www.sproutcore.com\n\n\n==========================================================================\n@license */\n\n// Most of the following code is taken from SproutCore with a few changes.\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"./oop\");\n\n/**\n * Helper functions and hashes for key handling.\n */\nvar Keys = (function() {\n    var ret = {\n        MODIFIER_KEYS: {\n            16: 'Shift', 17: 'Ctrl', 18: 'Alt', 224: 'Meta'\n        },\n\n        KEY_MODS: {\n            \"ctrl\": 1, \"alt\": 2, \"option\" : 2,\n            \"shift\": 4, \"meta\": 8, \"command\": 8\n        },\n\n        FUNCTION_KEYS : {\n            8  : \"Backspace\",\n            9  : \"Tab\",\n            13 : \"Return\",\n            19 : \"Pause\",\n            27 : \"Esc\",\n            32 : \"Space\",\n            33 : \"PageUp\",\n            34 : \"PageDown\",\n            35 : \"End\",\n            36 : \"Home\",\n            37 : \"Left\",\n            38 : \"Up\",\n            39 : \"Right\",\n            40 : \"Down\",\n            44 : \"Print\",\n            45 : \"Insert\",\n            46 : \"Delete\",\n            96 : \"Numpad0\",\n            97 : \"Numpad1\",\n            98 : \"Numpad2\",\n            99 : \"Numpad3\",\n            100: \"Numpad4\",\n            101: \"Numpad5\",\n            102: \"Numpad6\",\n            103: \"Numpad7\",\n            104: \"Numpad8\",\n            105: \"Numpad9\",\n            112: \"F1\",\n            113: \"F2\",\n            114: \"F3\",\n            115: \"F4\",\n            116: \"F5\",\n            117: \"F6\",\n            118: \"F7\",\n            119: \"F8\",\n            120: \"F9\",\n            121: \"F10\",\n            122: \"F11\",\n            123: \"F12\",\n            144: \"Numlock\",\n            145: \"Scrolllock\"\n        },\n\n        PRINTABLE_KEYS: {\n           32: ' ',  48: '0',  49: '1',  50: '2',  51: '3',  52: '4', 53:  '5',\n           54: '6',  55: '7',  56: '8',  57: '9',  59: ';',  61: '=', 65:  'a',\n           66: 'b',  67: 'c',  68: 'd',  69: 'e',  70: 'f',  71: 'g', 72:  'h',\n           73: 'i',  74: 'j',  75: 'k',  76: 'l',  77: 'm',  78: 'n', 79:  'o',\n           80: 'p',  81: 'q',  82: 'r',  83: 's',  84: 't',  85: 'u', 86:  'v',\n           87: 'w',  88: 'x',  89: 'y',  90: 'z', 107: '+', 109: '-', 110: '.',\n          188: ',', 190: '.', 191: '/', 192: '`', 219: '[', 220: '\\\\',\n          221: ']', 222: '\\\"'\n        }\n    };\n\n    // A reverse map of FUNCTION_KEYS\n    for (var i in ret.FUNCTION_KEYS) {\n        var name = ret.FUNCTION_KEYS[i].toUpperCase();\n        ret[name] = parseInt(i, 10);\n    }\n\n    // Add the MODIFIER_KEYS, FUNCTION_KEYS and PRINTABLE_KEYS to the KEY\n    // variables as well.\n    oop.mixin(ret, ret.MODIFIER_KEYS);\n    oop.mixin(ret, ret.PRINTABLE_KEYS);\n    oop.mixin(ret, ret.FUNCTION_KEYS);\n\n    return ret;\n})();\noop.mixin(exports, Keys);\n\nexports.keyCodeToString = function(keyCode) {\n    return (Keys[keyCode] || String.fromCharCode(keyCode)).toLowerCase();\n}\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/lib/lang.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nexports.stringReverse = function(string) {\n    return string.split(\"\").reverse().join(\"\");\n};\n\nexports.stringRepeat = function (string, count) {\n     return new Array(count + 1).join(string);\n};\n\nvar trimBeginRegexp = /^\\s\\s*/;\nvar trimEndRegexp = /\\s\\s*$/;\n\nexports.stringTrimLeft = function (string) {\n    return string.replace(trimBeginRegexp, '');\n};\n\nexports.stringTrimRight = function (string) {\n    return string.replace(trimEndRegexp, '');\n};\n\nexports.copyObject = function(obj) {\n    var copy = {};\n    for (var key in obj) {\n        copy[key] = obj[key];\n    }\n    return copy;\n};\n\nexports.copyArray = function(array){\n    var copy = [];\n    for (var i=0, l=array.length; i<l; i++) {\n        if (array[i] && typeof array[i] == \"object\")\n            copy[i] = this.copyObject( array[i] );\n        else \n            copy[i] = array[i];\n    }\n    return copy;\n};\n\nexports.deepCopy = function (obj) {\n    if (typeof obj != \"object\") {\n        return obj;\n    }\n    \n    var copy = obj.constructor();\n    for (var key in obj) {\n        if (typeof obj[key] == \"object\") {\n            copy[key] = this.deepCopy(obj[key]);\n        } else {\n            copy[key] = obj[key];\n        }\n    }\n    return copy;\n};\n\nexports.arrayToMap = function(arr) {\n    var map = {};\n    for (var i=0; i<arr.length; i++) {\n        map[arr[i]] = 1;\n    }\n    return map;\n\n};\n\n/**\n * splice out of 'array' anything that === 'value'\n */\nexports.arrayRemove = function(array, value) {\n  for (var i = 0; i <= array.length; i++) {\n    if (value === array[i]) {\n      array.splice(i, 1);\n    }\n  }\n};\n\nexports.escapeRegExp = function(str) {\n    return str.replace(/([.*+?^${}()|[\\]\\/\\\\])/g, '\\\\$1');\n};\n\nexports.deferredCall = function(fcn) {\n\n    var timer = null;\n    var callback = function() {\n        timer = null;\n        fcn();\n    };\n\n    var deferred = function(timeout) {\n        deferred.cancel();\n        timer = setTimeout(callback, timeout || 0);\n        return deferred;\n    };\n\n    deferred.schedule = deferred;\n\n    deferred.call = function() {\n        this.cancel();\n        fcn();\n        return deferred;\n    };\n\n    deferred.cancel = function() {\n        clearTimeout(timer);\n        timer = null;\n        return deferred;\n    };\n\n    return deferred;\n};\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/lib/net.js",
    "content": "/**\n * based on code from:\n * \n * @license RequireJS text 0.25.0 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/jrburke/requirejs for details\n */\ndefine(function(require, exports, module) {\n\"use strict\";\n\nexports.get = function (url, callback) {\n    var xhr = exports.createXhr();\n    xhr.open('GET', url, true);\n    xhr.onreadystatechange = function (evt) {\n        //Do not explicitly handle errors, those should be\n        //visible via console output in the browser.\n        if (xhr.readyState === 4) {\n            callback(xhr.responseText);\n        }\n    };\n    xhr.send(null);\n};\n\nvar progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];\n\nexports.createXhr = function() {\n    //Would love to dump the ActiveX crap in here. Need IE 6 to die first.\n    var xhr, i, progId;\n    if (typeof XMLHttpRequest !== \"undefined\") {\n        return new XMLHttpRequest();\n    } else {\n        for (i = 0; i < 3; i++) {\n            progId = progIds[i];\n            try {\n                xhr = new ActiveXObject(progId);\n            } catch (e) {}\n\n            if (xhr) {\n                progIds = [progId];  // so faster next time\n                break;\n            }\n        }\n    }\n\n    if (!xhr) {\n        throw new Error(\"createXhr(): XMLHttpRequest not available\");\n    }\n\n    return xhr;\n};\n\nexports.loadScript = function(path, callback) {\n    var head = document.getElementsByTagName('head')[0];\n    var s = document.createElement('script');\n\n    s.src = path;\n    head.appendChild(s);\n    \n    s.onload = callback;\n};\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/lib/oop.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nexports.inherits = (function() {\n    var tempCtor = function() {};\n    return function(ctor, superCtor) {\n        tempCtor.prototype = superCtor.prototype;\n        ctor.super_ = superCtor.prototype;\n        ctor.prototype = new tempCtor();\n        ctor.prototype.constructor = ctor;\n    };\n}());\n\nexports.mixin = function(obj, mixin) {\n    for (var key in mixin) {\n        obj[key] = mixin[key];\n    }\n};\n\nexports.implement = function(proto, mixin) {\n    exports.mixin(proto, mixin);\n};\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/lib/regexp.js",
    "content": "/**\n *  Based on code from:\n *\n * XRegExp 1.5.0\n * (c) 2007-2010 Steven Levithan\n * MIT License\n * <http://xregexp.com>\n * Provides an augmented, extensible, cross-browser implementation of regular expressions,\n * including support for additional syntax, flags, and methods\n */\n \ndefine(function(require, exports, module) {\n\"use strict\";\n\n    //---------------------------------\n    //  Private variables\n    //---------------------------------\n\n    var real = {\n            exec: RegExp.prototype.exec,\n            test: RegExp.prototype.test,\n            match: String.prototype.match,\n            replace: String.prototype.replace,\n            split: String.prototype.split\n        },\n        compliantExecNpcg = real.exec.call(/()??/, \"\")[1] === undefined, // check `exec` handling of nonparticipating capturing groups\n        compliantLastIndexIncrement = function () {\n            var x = /^/g;\n            real.test.call(x, \"\");\n            return !x.lastIndex;\n        }();\n\n    //---------------------------------\n    //  Overriden native methods\n    //---------------------------------\n\n    // Adds named capture support (with backreferences returned as `result.name`), and fixes two\n    // cross-browser issues per ES3:\n    // - Captured values for nonparticipating capturing groups should be returned as `undefined`,\n    //   rather than the empty string.\n    // - `lastIndex` should not be incremented after zero-length matches.\n    RegExp.prototype.exec = function (str) {\n        var match = real.exec.apply(this, arguments),\n            name, r2;\n        if ( typeof(str) == 'string' && match) {\n            // Fix browsers whose `exec` methods don't consistently return `undefined` for\n            // nonparticipating capturing groups\n            if (!compliantExecNpcg && match.length > 1 && indexOf(match, \"\") > -1) {\n                r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), \"g\", \"\"));\n                // Using `str.slice(match.index)` rather than `match[0]` in case lookahead allowed\n                // matching due to characters outside the match\n                real.replace.call(str.slice(match.index), r2, function () {\n                    for (var i = 1; i < arguments.length - 2; i++) {\n                        if (arguments[i] === undefined)\n                            match[i] = undefined;\n                    }\n                });\n            }\n            // Attach named capture properties\n            if (this._xregexp && this._xregexp.captureNames) {\n                for (var i = 1; i < match.length; i++) {\n                    name = this._xregexp.captureNames[i - 1];\n                    if (name)\n                       match[name] = match[i];\n                }\n            }\n            // Fix browsers that increment `lastIndex` after zero-length matches\n            if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index))\n                this.lastIndex--;\n        }\n        return match;\n    };\n\n    // Don't override `test` if it won't change anything\n    if (!compliantLastIndexIncrement) {\n        // Fix browser bug in native method\n        RegExp.prototype.test = function (str) {\n            // Use the native `exec` to skip some processing overhead, even though the overriden\n            // `exec` would take care of the `lastIndex` fix\n            var match = real.exec.call(this, str);\n            // Fix browsers that increment `lastIndex` after zero-length matches\n            if (match && this.global && !match[0].length && (this.lastIndex > match.index))\n                this.lastIndex--;\n            return !!match;\n        };\n    }\n\n    //---------------------------------\n    //  Private helper functions\n    //---------------------------------\n\n    function getNativeFlags (regex) {\n        return (regex.global     ? \"g\" : \"\") +\n               (regex.ignoreCase ? \"i\" : \"\") +\n               (regex.multiline  ? \"m\" : \"\") +\n               (regex.extended   ? \"x\" : \"\") + // Proposed for ES4; included in AS3\n               (regex.sticky     ? \"y\" : \"\");\n    };\n\n    function indexOf (array, item, from) {\n        if (Array.prototype.indexOf) // Use the native array method if available\n            return array.indexOf(item, from);\n        for (var i = from || 0; i < array.length; i++) {\n            if (array[i] === item)\n                return i;\n        }\n        return -1;\n    };\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/lib/useragent.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar os = (navigator.platform.match(/mac|win|linux/i) || [\"other\"])[0].toLowerCase();\nvar ua = navigator.userAgent;\n\n/** Is the user using a browser that identifies itself as Windows */\nexports.isWin = (os == \"win\");\n\n/** Is the user using a browser that identifies itself as Mac OS */\nexports.isMac = (os == \"mac\");\n\n/** Is the user using a browser that identifies itself as Linux */\nexports.isLinux = (os == \"linux\");\n\nexports.isIE = \n    navigator.appName == \"Microsoft Internet Explorer\"\n    && parseFloat(navigator.userAgent.match(/MSIE ([0-9]+[\\.0-9]+)/)[1]);\n    \nexports.isOldIE = exports.isIE && exports.isIE < 9;\n\n/** Is this Firefox or related? */\nexports.isGecko = exports.isMozilla = window.controllers && window.navigator.product === \"Gecko\";\n\n/** oldGecko == rev < 2.0 **/\nexports.isOldGecko = exports.isGecko && parseInt((navigator.userAgent.match(/rv\\:(\\d+)/)||[])[1], 10) < 4;\n\n/** Is this Opera */\nexports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == \"[object Opera]\";\n\n/** Is the user using a browser that identifies itself as WebKit */\nexports.isWebKit = parseFloat(ua.split(\"WebKit/\")[1]) || undefined;\n\nexports.isChrome = parseFloat(ua.split(\" Chrome/\")[1]) || undefined;\n\nexports.isAIR = ua.indexOf(\"AdobeAIR\") >= 0;\n\nexports.isIPad = ua.indexOf(\"iPad\") >= 0;\n\nexports.isTouchPad = ua.indexOf(\"TouchPad\") >= 0;\n\n/**\n * I hate doing this, but we need some way to determine if the user is on a Mac\n * The reason is that users have different expectations of their key combinations.\n *\n * Take copy as an example, Mac people expect to use CMD or APPLE + C\n * Windows folks expect to use CTRL + C\n */\nexports.OS = {\n    LINUX: \"LINUX\",\n    MAC: \"MAC\",\n    WINDOWS: \"WINDOWS\"\n};\n\n/**\n * Return an exports.OS constant\n */\nexports.getOS = function() {\n    if (exports.isMac) {\n        return exports.OS.MAC;\n    } else if (exports.isLinux) {\n        return exports.OS.LINUX;\n    } else {\n        return exports.OS.WINDOWS;\n    }\n};\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/behaviour/cstyle.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Chris Spencer <chris.ag.spencer AT googlemail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../../lib/oop\");\nvar Behaviour = require('../behaviour').Behaviour;\n\nvar CstyleBehaviour = function () {\n\n    this.add(\"braces\", \"insertion\", function (state, action, editor, session, text) {\n        if (text == '{') {\n            var selection = editor.getSelectionRange();\n            var selected = session.doc.getTextRange(selection);\n            if (selected !== \"\") {\n                return {\n                    text: '{' + selected + '}',\n                    selection: false\n                };\n            } else {\n                return {\n                    text: '{}',\n                    selection: [1, 1]\n                };\n            }\n        } else if (text == '}') {\n            var cursor = editor.getCursorPosition();\n            var line = session.doc.getLine(cursor.row);\n            var rightChar = line.substring(cursor.column, cursor.column + 1);\n            if (rightChar == '}') {\n                var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row});\n                if (matching !== null) {\n                    return {\n                        text: '',\n                        selection: [1, 1]\n                    };\n                }\n            }\n        } else if (text == \"\\n\") {\n            var cursor = editor.getCursorPosition();\n            var line = session.doc.getLine(cursor.row);\n            var rightChar = line.substring(cursor.column, cursor.column + 1);\n            if (rightChar == '}') {\n                var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column + 1});\n                if (!openBracePos)\n                     return null;\n\n                var indent = this.getNextLineIndent(state, line.substring(0, line.length - 1), session.getTabString());\n                var next_indent = this.$getIndent(session.doc.getLine(openBracePos.row));\n\n                return {\n                    text: '\\n' + indent + '\\n' + next_indent,\n                    selection: [1, indent.length, 1, indent.length]\n                };\n            }\n        }\n    });\n\n    this.add(\"braces\", \"deletion\", function (state, action, editor, session, range) {\n        var selected = session.doc.getTextRange(range);\n        if (!range.isMultiLine() && selected == '{') {\n            var line = session.doc.getLine(range.start.row);\n            var rightChar = line.substring(range.end.column, range.end.column + 1);\n            if (rightChar == '}') {\n                range.end.column++;\n                return range;\n            }\n        }\n    });\n\n    this.add(\"parens\", \"insertion\", function (state, action, editor, session, text) {\n        if (text == '(') {\n            var selection = editor.getSelectionRange();\n            var selected = session.doc.getTextRange(selection);\n            if (selected !== \"\") {\n                return {\n                    text: '(' + selected + ')',\n                    selection: false\n                };\n            } else {\n                return {\n                    text: '()',\n                    selection: [1, 1]\n                };\n            }\n        } else if (text == ')') {\n            var cursor = editor.getCursorPosition();\n            var line = session.doc.getLine(cursor.row);\n            var rightChar = line.substring(cursor.column, cursor.column + 1);\n            if (rightChar == ')') {\n                var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row});\n                if (matching !== null) {\n                    return {\n                        text: '',\n                        selection: [1, 1]\n                    };\n                }\n            }\n        }\n    });\n\n    this.add(\"parens\", \"deletion\", function (state, action, editor, session, range) {\n        var selected = session.doc.getTextRange(range);\n        if (!range.isMultiLine() && selected == '(') {\n            var line = session.doc.getLine(range.start.row);\n            var rightChar = line.substring(range.start.column + 1, range.start.column + 2);\n            if (rightChar == ')') {\n                range.end.column++;\n                return range;\n            }\n        }\n    });\n\n    this.add(\"string_dquotes\", \"insertion\", function (state, action, editor, session, text) {\n        if (text == '\"' || text == \"'\") {\n            var quote = text;\n            var selection = editor.getSelectionRange();\n            var selected = session.doc.getTextRange(selection);\n            if (selected !== \"\") {\n                return {\n                    text: quote + selected + quote,\n                    selection: false\n                };\n            } else {\n                var cursor = editor.getCursorPosition();\n                var line = session.doc.getLine(cursor.row);\n                var leftChar = line.substring(cursor.column-1, cursor.column);\n\n                // We're escaped.\n                if (leftChar == '\\\\') {\n                    return null;\n                }\n\n                // Find what token we're inside.\n                var tokens = session.getTokens(selection.start.row, selection.start.row)[0].tokens;\n                var col = 0, token;\n                var quotepos = -1; // Track whether we're inside an open quote.\n\n                for (var x = 0; x < tokens.length; x++) {\n                    token = tokens[x];\n                    if (token.type == \"string\") {\n                      quotepos = -1;\n                    } else if (quotepos < 0) {\n                      quotepos = token.value.indexOf(quote);\n                    }\n                    if ((token.value.length + col) > selection.start.column) {\n                        break;\n                    }\n                    col += tokens[x].value.length;\n                }\n\n                // Try and be smart about when we auto insert.\n                if (!token || (quotepos < 0 && token.type !== \"comment\" && (token.type !== \"string\" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) {\n                    return {\n                        text: quote + quote,\n                        selection: [1,1]\n                    };\n                } else if (token && token.type === \"string\") {\n                    // Ignore input and move right one if we're typing over the closing quote.\n                    var rightChar = line.substring(cursor.column, cursor.column + 1);\n                    if (rightChar == quote) {\n                        return {\n                            text: '',\n                            selection: [1, 1]\n                        };\n                    }\n                }\n            }\n        }\n    });\n\n    this.add(\"string_dquotes\", \"deletion\", function (state, action, editor, session, range) {\n        var selected = session.doc.getTextRange(range);\n        if (!range.isMultiLine() && (selected == '\"' || selected == \"'\")) {\n            var line = session.doc.getLine(range.start.row);\n            var rightChar = line.substring(range.start.column + 1, range.start.column + 2);\n            if (rightChar == '\"') {\n                range.end.column++;\n                return range;\n            }\n        }\n    });\n\n};\n\noop.inherits(CstyleBehaviour, Behaviour);\n\nexports.CstyleBehaviour = CstyleBehaviour;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/behaviour/xml.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Chris Spencer <chris.ag.spencer AT googlemail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../../lib/oop\");\nvar Behaviour = require(\"../behaviour\").Behaviour;\nvar CstyleBehaviour = require(\"./cstyle\").CstyleBehaviour;\n\nvar XmlBehaviour = function () {\n    \n    this.inherit(CstyleBehaviour, [\"string_dquotes\"]); // Get string behaviour\n    \n    this.add(\"brackets\", \"insertion\", function (state, action, editor, session, text) {\n        if (text == '<') {\n            var selection = editor.getSelectionRange();\n            var selected = session.doc.getTextRange(selection);\n            if (selected !== \"\") {\n                return false;\n            } else {\n                return {\n                    text: '<>',\n                    selection: [1, 1]\n                }\n            }\n        } else if (text == '>') {\n            var cursor = editor.getCursorPosition();\n            var line = session.doc.getLine(cursor.row);\n            var rightChar = line.substring(cursor.column, cursor.column + 1);\n            if (rightChar == '>') { // need some kind of matching check here\n                return {\n                    text: '',\n                    selection: [1, 1]\n                }\n            }\n        } else if (text == \"\\n\") {\n            var cursor = editor.getCursorPosition();\n            var line = session.doc.getLine(cursor.row);\n            var rightChars = line.substring(cursor.column, cursor.column + 2);\n            if (rightChars == '</') {\n                var indent = this.$getIndent(session.doc.getLine(cursor.row)) + session.getTabString();\n                var next_indent = this.$getIndent(session.doc.getLine(cursor.row));\n\n                return {\n                    text: '\\n' + indent + '\\n' + next_indent,\n                    selection: [1, indent.length, 1, indent.length]\n                }\n            }\n        }\n    });\n    \n}\noop.inherits(XmlBehaviour, Behaviour);\n\nexports.XmlBehaviour = XmlBehaviour;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/behaviour/xquery.js",
    "content": "/*\n*  eXide - web-based XQuery IDE\n*  \n*  Copyright (C) 2011 Wolfgang Meier\n*\n*  This program is free software: you can redistribute it and/or modify\n*  it under the terms of the GNU General Public License as published by\n*  the Free Software Foundation, either version 3 of the License, or\n*  (at your option) any later version.\n*\n*  This program is distributed in the hope that it will be useful,\n*  but WITHOUT ANY WARRANTY; without even the implied warranty of\n*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n*  GNU General Public License for more details.\n*\n*  You should have received a copy of the GNU General Public License\n*  along with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\ndefine(function(require, exports, module) {\n\"use strict\";\n\n  var oop = require(\"../../lib/oop\");\n  var Behaviour = require('../behaviour').Behaviour;\n  var CstyleBehaviour = require('./cstyle').CstyleBehaviour;\n\n  var XQueryBehaviour = function (parent) {\n      \n      this.inherit(CstyleBehaviour, [\"braces\", \"parens\", \"string_dquotes\"]); // Get string behaviour\n      this.parent = parent;\n      \n      this.add(\"brackets\", \"insertion\", function (state, action, editor, session, text) {\n          if (text == \"\\n\") {\n              var cursor = editor.getCursorPosition();\n              var line = session.doc.getLine(cursor.row);\n              var rightChars = line.substring(cursor.column, cursor.column + 2);\n              if (rightChars == '</') {\n                  var indent = this.$getIndent(session.doc.getLine(cursor.row)) + session.getTabString();\n                  var next_indent = this.$getIndent(session.doc.getLine(cursor.row));\n\n                  return {\n                      text: '\\n' + indent + '\\n' + next_indent,\n                      selection: [1, indent.length, 1, indent.length]\n                  }\n              }\n          }\n          return false;\n      });\n\n      // Check for open tag if user enters / and auto-close it.\n      this.add(\"slash\", \"insertion\", function (state, action, editor, session, text) {\n        if (text == \"/\") {\n          var cursor = editor.getCursorPosition();\n        var line = session.doc.getLine(cursor.row);\n        if (cursor.column > 0 && line.charAt(cursor.column - 1) == \"<\") {\n          line = line.substring(0, cursor.column) + \"/\" + line.substring(cursor.column);\n          var lines = session.doc.getAllLines();\n          lines[cursor.row] = line;\n          // call mode helper to close the tag if possible\n          parent.exec(\"closeTag\", lines.join(session.doc.getNewLineCharacter()), cursor.row);\n        }\n        }\n      return false;\n      });\n  }\n  oop.inherits(XQueryBehaviour, Behaviour);\n\n  exports.XQueryBehaviour = XQueryBehaviour;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/behaviour.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Chris Spencer <chris.ag.spencer AT googlemail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Behaviour = function() {\n   this.$behaviours = {};\n};\n\n(function () {\n\n    this.add = function (name, action, callback) {\n        switch (undefined) {\n          case this.$behaviours:\n              this.$behaviours = {};\n          case this.$behaviours[name]:\n              this.$behaviours[name] = {};\n        }\n        this.$behaviours[name][action] = callback;\n    }\n    \n    this.addBehaviours = function (behaviours) {\n        for (var key in behaviours) {\n            for (var action in behaviours[key]) {\n                this.add(key, action, behaviours[key][action]);\n            }\n        }\n    }\n    \n    this.remove = function (name) {\n        if (this.$behaviours && this.$behaviours[name]) {\n            delete this.$behaviours[name];\n        }\n    }\n    \n    this.inherit = function (mode, filter) {\n        if (typeof mode === \"function\") {\n            var behaviours = new mode().getBehaviours(filter);\n        } else {\n            var behaviours = mode.getBehaviours(filter);\n        }\n        this.addBehaviours(behaviours);\n    }\n    \n    this.getBehaviours = function (filter) {\n        if (!filter) {\n            return this.$behaviours;\n        } else {\n            var ret = {}\n            for (var i = 0; i < filter.length; i++) {\n                if (this.$behaviours[filter[i]]) {\n                    ret[filter[i]] = this.$behaviours[filter[i]];\n                }\n            }\n            return ret;\n        }\n    }\n\n}).call(Behaviour.prototype);\n\nexports.Behaviour = Behaviour;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/c_cpp.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Gastón Kleiman <gaston.kleiman AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar c_cppHighlightRules = require(\"./c_cpp_highlight_rules\").c_cppHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar Range = require(\"../range\").Range;\nvar CstyleBehaviour = require(\"./behaviour/cstyle\").CstyleBehaviour;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new c_cppHighlightRules().getRules());\n    this.$outdent = new MatchingBraceOutdent();\n    this.$behaviour = new CstyleBehaviour();\n    this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        var outdent = true;\n        var re = /^(\\s*)\\/\\//;\n\n        for (var i=startRow; i<= endRow; i++) {\n            if (!re.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        if (outdent) {\n            var deleteRange = new Range(0, 0, 0, 0);\n            for (var i=startRow; i<= endRow; i++)\n            {\n                var line = doc.getLine(i);\n                var m = line.match(re);\n                deleteRange.start.row = i;\n                deleteRange.end.row = i;\n                deleteRange.end.column = m[0].length;\n                doc.replace(deleteRange, m[1]);\n            }\n        }\n        else {\n            doc.indentRows(startRow, endRow, \"//\");\n        }\n    };\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n        var endState = tokenizedLine.state;\n\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n\n        if (state == \"start\") {\n            var match = line.match(/^.*[\\{\\(\\[]\\s*$/);\n            if (match) {\n                indent += tab;\n            }\n        } else if (state == \"doc-start\") {\n            if (endState == \"start\") {\n                return \"\";\n            }\n            var match = line.match(/^\\s*(\\/?)\\*/);\n            if (match) {\n                if (match[1]) {\n                    indent += \" \";\n                }\n                indent += \"* \";\n            }\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/c_cpp_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Gastón Kleiman <gaston.kleiman AT gmail DOT com>\n *\n * Based on Bespin's C/C++ Syntax Plugin by Marc McIntyre.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar DocCommentHighlightRules = require(\"./doc_comment_highlight_rules\").DocCommentHighlightRules;\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar c_cppHighlightRules = function() {\n\n    var keywords = lang.arrayToMap(\n        (\"and|double|not_eq|throw|and_eq|dynamic_cast|operator|true|\" +\n        \"asm|else|or|try|auto|enum|or_eq|typedef|bitand|explicit|private|\" +\n        \"typeid|bitor|extern|protected|typename|bool|false|public|union|\" +\n        \"break|float|register|unsigned|case|fro|reinterpret-cast|using|catch|\" +\n        \"friend|return|virtual|char|goto|short|void|class|if|signed|volatile|\" +\n        \"compl|inline|sizeof|wchar_t|const|int|static|while|const-cast|long|\" +\n        \"static_cast|xor|continue|mutable|struct|xor_eq|default|namespace|\" +\n        \"switch|delete|new|template|do|not|this|for\").split(\"|\")\n    );\n\n    var buildinConstants = lang.arrayToMap(\n        (\"NULL\").split(\"|\")\n    );\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \"\\\\/\\\\/.*$\"\n            },\n            DocCommentHighlightRules.getStartRule(\"doc-start\"),\n            {\n                token : \"comment\", // multi line comment\n                merge : true,\n                regex : \"\\\\/\\\\*\",\n                next : \"comment\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // multi line string start\n                merge : true,\n                regex : '[\"].*\\\\\\\\$',\n                next : \"qqstring\"\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"string\", // multi line string start\n                merge : true,\n                regex : \"['].*\\\\\\\\$\",\n                next : \"qstring\"\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n              token : \"constant\", // <CONSTANT>\n              regex : \"<[a-zA-Z0-9.]+>\"\n            }, {\n              token : \"keyword\", // pre-compiler directivs\n              regex : \"(?:#include|#pragma|#line|#define|#undef|#ifdef|#else|#elif|#endif|#ifndef)\"\n          }, {\n                token : function(value) {\n                    if (value == \"this\")\n                        return \"variable.language\";\n                    else if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (buildinConstants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else\n                        return \"identifier\";\n                },\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"!|\\\\$|%|&|\\\\*|\\\\-\\\\-|\\\\-|\\\\+\\\\+|\\\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\\\|\\\\||\\\\?\\\\:|\\\\*=|%=|\\\\+=|\\\\-=|&=|\\\\^=|\\\\b(?:in|new|delete|typeof|void)\"\n            }, {\n              token : \"punctuation.operator\",\n              regex : \"\\\\?|\\\\:|\\\\,|\\\\;|\\\\.\"\n            }, {\n                token : \"paren.lparen\",\n                regex : \"[[({]\"\n            }, {\n                token : \"paren.rparen\",\n                regex : \"[\\\\])}]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ],\n        \"qqstring\" : [\n            {\n                token : \"string\",\n                regex : '(?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?\"',\n                next : \"start\"\n            }, {\n                token : \"string\",\n                merge : true,\n                regex : '.+'\n            }\n        ],\n        \"qstring\" : [\n            {\n                token : \"string\",\n                regex : \"(?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?'\",\n                next : \"start\"\n            }, {\n                token : \"string\",\n                merge : true,\n                regex : '.+'\n            }\n        ]\n    };\n    \n    this.embedRules(DocCommentHighlightRules, \"doc-\",\n        [ DocCommentHighlightRules.getEndRule(\"start\") ]);\n};\n\noop.inherits(c_cppHighlightRules, TextHighlightRules);\n\nexports.c_cppHighlightRules = c_cppHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/clojure.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Shlomo Zalman Heigh <shlomozalmanheigh AT gmail DOT com>\n *      Carin Meier\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar ClojureHighlightRules = require(\"./clojure_highlight_rules\").ClojureHighlightRules;\nvar MatchingParensOutdent = require(\"./matching_parens_outdent\").MatchingParensOutdent;\nvar Range = require(\"../range\").Range;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new ClojureHighlightRules().getRules());\n    this.$outdent = new MatchingParensOutdent();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        var outdent = true;\n        var re = /^(\\s*)#/;\n\n        for (var i=startRow; i<= endRow; i++) {\n            if (!re.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        if (outdent) {\n            var deleteRange = new Range(0, 0, 0, 0);\n            for (var i=startRow; i<= endRow; i++)\n            {\n                var line = doc.getLine(i);\n                var m = line.match(re);\n                deleteRange.start.row = i;\n                deleteRange.end.row = i;\n                deleteRange.end.column = m[0].length;\n                doc.replace(deleteRange, m[1]);\n            }\n        }\n        else {\n            doc.indentRows(startRow, endRow, \";\");\n        }\n    };\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n        \n        if (state == \"start\") {\n            var match = line.match(/[\\(\\[]/);\n            if (match) {\n                indent += \"  \";\n            }\n            match = line.match(/[\\)]/);\n            if (match) {\n              indent = \"\";\n            }\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/clojure_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Shlomo Zalman Heigh <shlomozalmanheigh AT gmail DOT com>\n *      Carin Meier\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\n\n\nvar ClojureHighlightRules = function() {\n\n       var builtinFunctions = lang.arrayToMap(\n        ('* *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* ' +\n            '*command-line-args* *compile-files* *compile-path* *e *err* *file* ' +\n            '*flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* ' +\n            '*print-dup* *print-length* *print-level* *print-meta* *print-readably* ' +\n            '*read-eval* *source-path* *use-context-classloader* ' +\n            '*warn-on-reflection* + - -> -&gt; ->> -&gt;&gt; .. / < &lt; <= &lt;= = ' +\n            '== > &gt; >= &gt;= accessor aclone ' +\n            'add-classpath add-watch agent agent-errors aget alength alias all-ns ' +\n            'alter alter-meta! alter-var-root amap ancestors and apply areduce ' +\n            'array-map aset aset-boolean aset-byte aset-char aset-double aset-float ' +\n            'aset-int aset-long aset-short assert assoc assoc! assoc-in associative? ' +\n            'atom await await-for await1 bases bean bigdec bigint binding bit-and ' +\n            'bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left ' +\n            'bit-shift-right bit-test bit-xor boolean boolean-array booleans ' +\n            'bound-fn bound-fn* butlast byte byte-array bytes cast char char-array ' +\n            'char-escape-string char-name-string char? chars chunk chunk-append ' +\n            'chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? ' +\n            'class class? clear-agent-errors clojure-version coll? comment commute ' +\n            'comp comparator compare compare-and-set! compile complement concat cond ' +\n            'condp conj conj! cons constantly construct-proxy contains? count ' +\n            'counted? create-ns create-struct cycle dec decimal? declare definline ' +\n            'defmacro defmethod defmulti defn defn- defonce defstruct delay delay? ' +\n            'deliver deref derive descendants destructure disj disj! dissoc dissoc! ' +\n            'distinct distinct? doall doc dorun doseq dosync dotimes doto double ' +\n            'double-array doubles drop drop-last drop-while empty empty? ensure ' +\n            'enumeration-seq eval even? every? false? ffirst file-seq filter find ' +\n            'find-doc find-ns find-var first float float-array float? floats flush ' +\n            'fn fn? fnext for force format future future-call future-cancel ' +\n            'future-cancelled? future-done? future? gen-class gen-interface gensym ' +\n            'get get-in get-method get-proxy-class get-thread-bindings get-validator ' +\n            'hash hash-map hash-set identical? identity if-let if-not ifn? import ' +\n            'in-ns inc init-proxy instance? int int-array integer? interleave intern ' +\n            'interpose into into-array ints io! isa? iterate iterator-seq juxt key ' +\n            'keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list ' +\n            'list* list? load load-file load-reader load-string loaded-libs locking ' +\n            'long long-array longs loop macroexpand macroexpand-1 make-array ' +\n            'make-hierarchy map map? mapcat max max-key memfn memoize merge ' +\n            'merge-with meta method-sig methods min min-key mod name namespace neg? ' +\n            'newline next nfirst nil? nnext not not-any? not-empty not-every? not= ' +\n            'ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ' +\n            'ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? ' +\n            'or parents partial partition pcalls peek persistent! pmap pop pop! ' +\n            'pop-thread-bindings pos? pr pr-str prefer-method prefers ' +\n            'primitives-classnames print print-ctor print-doc print-dup print-method ' +\n            'print-namespace-doc print-simple print-special-doc print-str printf ' +\n            'println println-str prn prn-str promise proxy proxy-call-with-super ' +\n            'proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot ' +\n            'rand rand-int range ratio? rational? rationalize re-find re-groups ' +\n            're-matcher re-matches re-pattern re-seq read read-line read-string ' +\n            'reduce ref ref-history-count ref-max-history ref-min-history ref-set ' +\n            'refer refer-clojure release-pending-sends rem remove remove-method ' +\n            'remove-ns remove-watch repeat repeatedly replace replicate require ' +\n            'reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq ' +\n            'rsubseq second select-keys send send-off seq seq? seque sequence ' +\n            'sequential? set set-validator! set? short short-array shorts ' +\n            'shutdown-agents slurp some sort sort-by sorted-map sorted-map-by ' +\n            'sorted-set sorted-set-by sorted? special-form-anchor special-symbol? ' +\n            'split-at split-with str stream? string? struct struct-map subs subseq ' +\n            'subvec supers swap! symbol symbol? sync syntax-symbol-anchor take ' +\n            'take-last take-nth take-while test the-ns time to-array to-array-2d ' +\n            'trampoline transient tree-seq true? type unchecked-add unchecked-dec ' +\n            'unchecked-divide unchecked-inc unchecked-multiply unchecked-negate ' +\n            'unchecked-remainder unchecked-subtract underive unquote ' +\n            'unquote-splicing update-in update-proxy use val vals var-get var-set ' +\n            'var? vary-meta vec vector vector? when when-first when-let when-not ' +\n            'while with-bindings with-bindings* with-in-str with-loading-context ' +\n            'with-local-vars with-meta with-open with-out-str with-precision xml-seq ' +\n            'zero? zipmap ').split(\" \")\n    );\n\n    var keywords = lang.arrayToMap(\n        ('def do fn if let loop monitor-enter monitor-exit new quote recur set! ' +\n            'throw try var').split(\" \")\n    );\n\n    var buildinConstants = lang.arrayToMap(\n        (\"true false nil\").split(\" \")\n    );\n\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \";.*$\"\n            }, {\n                token : \"comment\", // multi line comment\n                regex : \"^=begin$\",\n                next : \"comment\"\n            }, {\n                token : \"keyword\", //parens\n                regex : \"[\\\\(|\\\\)]\"\n            }, {\n                token : \"keyword\", //lists\n                regex : \"[\\\\'\\\\(]\"\n            }, {\n                token : \"keyword\", //vectors\n                regex : \"[\\\\[|\\\\]]\"\n            }, {\n                token : \"keyword\", //sets and maps\n                regex : \"[\\\\{|\\\\}|\\\\#\\\\{|\\\\#\\\\}]\"\n            }, {\n                    token : \"keyword\", // ampersands\n                    regex : '[\\\\&]'\n            }, {\n                    token : \"keyword\", // metadata\n                    regex : '[\\\\#\\\\^\\\\{]'\n            }, {\n                    token : \"keyword\", // anonymous fn syntactic sugar\n                    regex : '[\\\\%]'\n            }, {\n                    token : \"keyword\", // deref reader macro\n                    regex : '[@]'\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n                token : \"constant.language\",\n                regex : '[!|\\\\$|%|&|\\\\*|\\\\-\\\\-|\\\\-|\\\\+\\\\+|\\\\+||=|!=|<=|>=|<>|<|>|!|&&]'\n            }, {\n                token : function(value) {\n                    if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (buildinConstants.hasOwnProperty(value))\n                        return \"constant.language\";\n                        else if (builtinFunctions.hasOwnProperty(value))\n                        return \"support.function\";\n                    else\n                        return \"identifier\";\n                },\n                // TODO: Unicode escape sequences\n                // TODO: Unicode identifiers\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // symbol\n                regex : \"[:](?:[a-zA-Z]|\\\\d)+\"\n            }, {\n                token : \"string.regexp\", //Regular Expressions\n                regex : '/#\"(?:\\\\.|(?:\\\\\\\")|[^\\\"\"\\n])*\"/g'\n            }\n\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \"^=end$\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ]\n    };\n};\n\noop.inherits(ClojureHighlightRules, TextHighlightRules);\n\nexports.ClojureHighlightRules = ClojureHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coffee/coffee-script.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n \ndefine(function(require, exports, module) {\n    \n    var Lexer = require(\"./lexer\").Lexer;\n    var parser = require(\"./parser\");\n\n    var lexer = new Lexer();\n    parser.lexer = {\n        lex: function() {\n            var tag, _ref2;\n            _ref2 = this.tokens[this.pos++] || [''], tag = _ref2[0], this.yytext = _ref2[1], this.yylineno = _ref2[2];\n            return tag;\n        },\n        setInput: function(tokens) {\n            this.tokens = tokens;\n            return this.pos = 0;\n        },\n        upcomingInput: function() {\n            return \"\";\n        }\n    };\n    parser.yy = require('./nodes');\n    \n    exports.parse = function(code) {\n        return parser.parse(lexer.tokenize(code));\n    };\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coffee/helpers.js",
    "content": "/**\n * Copyright (c) 2011 Jeremy Ashkenas\n * \n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n * \n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\ndefine(function(require, exports, module) {\n// Generated by CoffeeScript 1.2.1-pre\n\n  var extend, flatten;\n\n  exports.starts = function(string, literal, start) {\n    return literal === string.substr(start, literal.length);\n  };\n\n  exports.ends = function(string, literal, back) {\n    var len;\n    len = literal.length;\n    return literal === string.substr(string.length - len - (back || 0), len);\n  };\n\n  exports.compact = function(array) {\n    var item, _i, _len, _results;\n    _results = [];\n    for (_i = 0, _len = array.length; _i < _len; _i++) {\n      item = array[_i];\n      if (item) _results.push(item);\n    }\n    return _results;\n  };\n\n  exports.count = function(string, substr) {\n    var num, pos;\n    num = pos = 0;\n    if (!substr.length) return 1 / 0;\n    while (pos = 1 + string.indexOf(substr, pos)) {\n      num++;\n    }\n    return num;\n  };\n\n  exports.merge = function(options, overrides) {\n    return extend(extend({}, options), overrides);\n  };\n\n  extend = exports.extend = function(object, properties) {\n    var key, val;\n    for (key in properties) {\n      val = properties[key];\n      object[key] = val;\n    }\n    return object;\n  };\n\n  exports.flatten = flatten = function(array) {\n    var element, flattened, _i, _len;\n    flattened = [];\n    for (_i = 0, _len = array.length; _i < _len; _i++) {\n      element = array[_i];\n      if (element instanceof Array) {\n        flattened = flattened.concat(flatten(element));\n      } else {\n        flattened.push(element);\n      }\n    }\n    return flattened;\n  };\n\n  exports.del = function(obj, key) {\n    var val;\n    val = obj[key];\n    delete obj[key];\n    return val;\n  };\n\n  exports.last = function(array, back) {\n    return array[array.length - (back || 0) - 1];\n  };\n\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coffee/lexer.js",
    "content": "/**\n * Copyright (c) 2011 Jeremy Ashkenas\n * \n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n * \n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\ndefine(function(require, exports, module) {\n// Generated by CoffeeScript 1.2.1-pre\n\n  var BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, STRICT_PROSCRIBED, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref, _ref1,\n    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };\n\n  _ref = require('./rewriter'), Rewriter = _ref.Rewriter, INVERSES = _ref.INVERSES;\n\n  _ref1 = require('./helpers'), count = _ref1.count, starts = _ref1.starts, compact = _ref1.compact, last = _ref1.last;\n\n  exports.Lexer = Lexer = (function() {\n\n    Lexer.name = 'Lexer';\n\n    function Lexer() {}\n\n    Lexer.prototype.tokenize = function(code, opts) {\n      var i, tag;\n      if (opts == null) opts = {};\n      if (WHITESPACE.test(code)) code = \"\\n\" + code;\n      code = code.replace(/\\r/g, '').replace(TRAILING_SPACES, '');\n      this.code = code;\n      this.line = opts.line || 0;\n      this.indent = 0;\n      this.indebt = 0;\n      this.outdebt = 0;\n      this.indents = [];\n      this.ends = [];\n      this.tokens = [];\n      i = 0;\n      while (this.chunk = code.slice(i)) {\n        i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();\n      }\n      this.closeIndentation();\n      if (tag = this.ends.pop()) this.error(\"missing \" + tag);\n      if (opts.rewrite === false) return this.tokens;\n      return (new Rewriter).rewrite(this.tokens);\n    };\n\n    Lexer.prototype.identifierToken = function() {\n      var colon, forcedIdentifier, id, input, match, prev, tag, _ref2, _ref3;\n      if (!(match = IDENTIFIER.exec(this.chunk))) return 0;\n      input = match[0], id = match[1], colon = match[2];\n      if (id === 'own' && this.tag() === 'FOR') {\n        this.token('OWN', id);\n        return id.length;\n      }\n      forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@');\n      tag = 'IDENTIFIER';\n      if (!forcedIdentifier && (__indexOf.call(JS_KEYWORDS, id) >= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {\n        tag = id.toUpperCase();\n        if (tag === 'WHEN' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) {\n          tag = 'LEADING_WHEN';\n        } else if (tag === 'FOR') {\n          this.seenFor = true;\n        } else if (tag === 'UNLESS') {\n          tag = 'IF';\n        } else if (__indexOf.call(UNARY, tag) >= 0) {\n          tag = 'UNARY';\n        } else if (__indexOf.call(RELATION, tag) >= 0) {\n          if (tag !== 'INSTANCEOF' && this.seenFor) {\n            tag = 'FOR' + tag;\n            this.seenFor = false;\n          } else {\n            tag = 'RELATION';\n            if (this.value() === '!') {\n              this.tokens.pop();\n              id = '!' + id;\n            }\n          }\n        }\n      }\n      if (__indexOf.call(JS_FORBIDDEN, id) >= 0) {\n        if (forcedIdentifier) {\n          tag = 'IDENTIFIER';\n          id = new String(id);\n          id.reserved = true;\n        } else if (__indexOf.call(RESERVED, id) >= 0) {\n          this.error(\"reserved word \\\"\" + id + \"\\\"\");\n        }\n      }\n      if (!forcedIdentifier) {\n        if (__indexOf.call(COFFEE_ALIASES, id) >= 0) id = COFFEE_ALIAS_MAP[id];\n        tag = (function() {\n          switch (id) {\n            case '!':\n              return 'UNARY';\n            case '==':\n            case '!=':\n              return 'COMPARE';\n            case '&&':\n            case '||':\n              return 'LOGIC';\n            case 'true':\n            case 'false':\n            case 'null':\n            case 'undefined':\n              return 'BOOL';\n            case 'break':\n            case 'continue':\n              return 'STATEMENT';\n            default:\n              return tag;\n          }\n        })();\n      }\n      this.token(tag, id);\n      if (colon) this.token(':', ':');\n      return input.length;\n    };\n\n    Lexer.prototype.numberToken = function() {\n      var binaryLiteral, lexedLength, match, number, octalLiteral;\n      if (!(match = NUMBER.exec(this.chunk))) return 0;\n      number = match[0];\n      if (/E/.test(number)) {\n        this.error(\"exponential notation '\" + number + \"' must be indicated with a lowercase 'e'\");\n      } else if (/[BOX]/.test(number)) {\n        this.error(\"radix prefix '\" + number + \"' must be lowercase\");\n      } else if (/^0[89]/.test(number)) {\n        this.error(\"decimal literal '\" + number + \"' must not be prefixed with '0'\");\n      } else if (/^0[0-7]/.test(number)) {\n        this.error(\"octal literal '\" + number + \"' must be prefixed with '0o'\");\n      }\n      lexedLength = number.length;\n      if (octalLiteral = /0o([0-7]+)/.exec(number)) {\n        number = (parseInt(octalLiteral[1], 8)).toString();\n      }\n      if (binaryLiteral = /0b([01]+)/.exec(number)) {\n        number = (parseInt(binaryLiteral[1], 2)).toString();\n      }\n      this.token('NUMBER', number);\n      return lexedLength;\n    };\n\n    Lexer.prototype.stringToken = function() {\n      var match, octalEsc, string;\n      switch (this.chunk.charAt(0)) {\n        case \"'\":\n          if (!(match = SIMPLESTR.exec(this.chunk))) return 0;\n          this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\\\\n'));\n          break;\n        case '\"':\n          if (!(string = this.balancedString(this.chunk, '\"'))) return 0;\n          if (0 < string.indexOf('#{', 1)) {\n            this.interpolateString(string.slice(1, -1));\n          } else {\n            this.token('STRING', this.escapeLines(string));\n          }\n          break;\n        default:\n          return 0;\n      }\n      if (octalEsc = /^(?:\\\\.|[^\\\\])*\\\\[0-7]/.test(string)) {\n        this.error(\"octal escape sequences \" + string + \" are not allowed\");\n      }\n      this.line += count(string, '\\n');\n      return string.length;\n    };\n\n    Lexer.prototype.heredocToken = function() {\n      var doc, heredoc, match, quote;\n      if (!(match = HEREDOC.exec(this.chunk))) return 0;\n      heredoc = match[0];\n      quote = heredoc.charAt(0);\n      doc = this.sanitizeHeredoc(match[2], {\n        quote: quote,\n        indent: null\n      });\n      if (quote === '\"' && 0 <= doc.indexOf('#{')) {\n        this.interpolateString(doc, {\n          heredoc: true\n        });\n      } else {\n        this.token('STRING', this.makeString(doc, quote, true));\n      }\n      this.line += count(heredoc, '\\n');\n      return heredoc.length;\n    };\n\n    Lexer.prototype.commentToken = function() {\n      var comment, here, match;\n      if (!(match = this.chunk.match(COMMENT))) return 0;\n      comment = match[0], here = match[1];\n      if (here) {\n        this.token('HERECOMMENT', this.sanitizeHeredoc(here, {\n          herecomment: true,\n          indent: Array(this.indent + 1).join(' ')\n        }));\n      }\n      this.line += count(comment, '\\n');\n      return comment.length;\n    };\n\n    Lexer.prototype.jsToken = function() {\n      var match, script;\n      if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) {\n        return 0;\n      }\n      this.token('JS', (script = match[0]).slice(1, -1));\n      return script.length;\n    };\n\n    Lexer.prototype.regexToken = function() {\n      var flags, length, match, prev, regex, _ref2, _ref3;\n      if (this.chunk.charAt(0) !== '/') return 0;\n      if (match = HEREGEX.exec(this.chunk)) {\n        length = this.heregexToken(match);\n        this.line += count(match[0], '\\n');\n        return length;\n      }\n      prev = last(this.tokens);\n      if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) {\n        return 0;\n      }\n      if (!(match = REGEX.exec(this.chunk))) return 0;\n      _ref3 = match, match = _ref3[0], regex = _ref3[1], flags = _ref3[2];\n      if (regex.slice(0, 2) === '/*') {\n        this.error('regular expressions cannot begin with `*`');\n      }\n      if (regex === '//') regex = '/(?:)/';\n      this.token('REGEX', \"\" + regex + flags);\n      return match.length;\n    };\n\n    Lexer.prototype.heregexToken = function(match) {\n      var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4, _ref5;\n      heregex = match[0], body = match[1], flags = match[2];\n      if (0 > body.indexOf('#{')) {\n        re = body.replace(HEREGEX_OMIT, '').replace(/\\//g, '\\\\/');\n        if (re.match(/^\\*/)) {\n          this.error('regular expressions cannot begin with `*`');\n        }\n        this.token('REGEX', \"/\" + (re || '(?:)') + \"/\" + flags);\n        return heregex.length;\n      }\n      this.token('IDENTIFIER', 'RegExp');\n      this.tokens.push(['CALL_START', '(']);\n      tokens = [];\n      _ref2 = this.interpolateString(body, {\n        regex: true\n      });\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        _ref3 = _ref2[_i], tag = _ref3[0], value = _ref3[1];\n        if (tag === 'TOKENS') {\n          tokens.push.apply(tokens, value);\n        } else {\n          if (!(value = value.replace(HEREGEX_OMIT, ''))) continue;\n          value = value.replace(/\\\\/g, '\\\\\\\\');\n          tokens.push(['STRING', this.makeString(value, '\"', true)]);\n        }\n        tokens.push(['+', '+']);\n      }\n      tokens.pop();\n      if (((_ref4 = tokens[0]) != null ? _ref4[0] : void 0) !== 'STRING') {\n        this.tokens.push(['STRING', '\"\"'], ['+', '+']);\n      }\n      (_ref5 = this.tokens).push.apply(_ref5, tokens);\n      if (flags) this.tokens.push([',', ','], ['STRING', '\"' + flags + '\"']);\n      this.token(')', ')');\n      return heregex.length;\n    };\n\n    Lexer.prototype.lineToken = function() {\n      var diff, indent, match, noNewlines, prev, size;\n      if (!(match = MULTI_DENT.exec(this.chunk))) return 0;\n      indent = match[0];\n      this.line += count(indent, '\\n');\n      this.seenFor = false;\n      prev = last(this.tokens, 1);\n      size = indent.length - 1 - indent.lastIndexOf('\\n');\n      noNewlines = this.unfinished();\n      if (size - this.indebt === this.indent) {\n        if (noNewlines) {\n          this.suppressNewlines();\n        } else {\n          this.newlineToken();\n        }\n        return indent.length;\n      }\n      if (size > this.indent) {\n        if (noNewlines) {\n          this.indebt = size - this.indent;\n          this.suppressNewlines();\n          return indent.length;\n        }\n        diff = size - this.indent + this.outdebt;\n        this.token('INDENT', diff);\n        this.indents.push(diff);\n        this.ends.push('OUTDENT');\n        this.outdebt = this.indebt = 0;\n      } else {\n        this.indebt = 0;\n        this.outdentToken(this.indent - size, noNewlines);\n      }\n      this.indent = size;\n      return indent.length;\n    };\n\n    Lexer.prototype.outdentToken = function(moveOut, noNewlines) {\n      var dent, len;\n      while (moveOut > 0) {\n        len = this.indents.length - 1;\n        if (this.indents[len] === void 0) {\n          moveOut = 0;\n        } else if (this.indents[len] === this.outdebt) {\n          moveOut -= this.outdebt;\n          this.outdebt = 0;\n        } else if (this.indents[len] < this.outdebt) {\n          this.outdebt -= this.indents[len];\n          moveOut -= this.indents[len];\n        } else {\n          dent = this.indents.pop() - this.outdebt;\n          moveOut -= dent;\n          this.outdebt = 0;\n          this.pair('OUTDENT');\n          this.token('OUTDENT', dent);\n        }\n      }\n      if (dent) this.outdebt -= moveOut;\n      while (this.value() === ';') {\n        this.tokens.pop();\n      }\n      if (!(this.tag() === 'TERMINATOR' || noNewlines)) {\n        this.token('TERMINATOR', '\\n');\n      }\n      return this;\n    };\n\n    Lexer.prototype.whitespaceToken = function() {\n      var match, nline, prev;\n      if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\\n'))) {\n        return 0;\n      }\n      prev = last(this.tokens);\n      if (prev) prev[match ? 'spaced' : 'newLine'] = true;\n      if (match) {\n        return match[0].length;\n      } else {\n        return 0;\n      }\n    };\n\n    Lexer.prototype.newlineToken = function() {\n      while (this.value() === ';') {\n        this.tokens.pop();\n      }\n      if (this.tag() !== 'TERMINATOR') this.token('TERMINATOR', '\\n');\n      return this;\n    };\n\n    Lexer.prototype.suppressNewlines = function() {\n      if (this.value() === '\\\\') this.tokens.pop();\n      return this;\n    };\n\n    Lexer.prototype.literalToken = function() {\n      var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5;\n      if (match = OPERATOR.exec(this.chunk)) {\n        value = match[0];\n        if (CODE.test(value)) this.tagParameters();\n      } else {\n        value = this.chunk.charAt(0);\n      }\n      tag = value;\n      prev = last(this.tokens);\n      if (value === '=' && prev) {\n        if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) {\n          this.error(\"reserved word \\\"\" + (this.value()) + \"\\\" can't be assigned\");\n        }\n        if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') {\n          prev[0] = 'COMPOUND_ASSIGN';\n          prev[1] += '=';\n          return value.length;\n        }\n      }\n      if (value === ';') {\n        this.seenFor = false;\n        tag = 'TERMINATOR';\n      } else if (__indexOf.call(MATH, value) >= 0) {\n        tag = 'MATH';\n      } else if (__indexOf.call(COMPARE, value) >= 0) {\n        tag = 'COMPARE';\n      } else if (__indexOf.call(COMPOUND_ASSIGN, value) >= 0) {\n        tag = 'COMPOUND_ASSIGN';\n      } else if (__indexOf.call(UNARY, value) >= 0) {\n        tag = 'UNARY';\n      } else if (__indexOf.call(SHIFT, value) >= 0) {\n        tag = 'SHIFT';\n      } else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) {\n        tag = 'LOGIC';\n      } else if (prev && !prev.spaced) {\n        if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) {\n          if (prev[0] === '?') prev[0] = 'FUNC_EXIST';\n          tag = 'CALL_START';\n        } else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) {\n          tag = 'INDEX_START';\n          switch (prev[0]) {\n            case '?':\n              prev[0] = 'INDEX_SOAK';\n          }\n        }\n      }\n      switch (value) {\n        case '(':\n        case '{':\n        case '[':\n          this.ends.push(INVERSES[value]);\n          break;\n        case ')':\n        case '}':\n        case ']':\n          this.pair(value);\n      }\n      this.token(tag, value);\n      return value.length;\n    };\n\n    Lexer.prototype.sanitizeHeredoc = function(doc, options) {\n      var attempt, herecomment, indent, match, _ref2;\n      indent = options.indent, herecomment = options.herecomment;\n      if (herecomment) {\n        if (HEREDOC_ILLEGAL.test(doc)) {\n          this.error(\"block comment cannot contain \\\"*/\\\", starting\");\n        }\n        if (doc.indexOf('\\n') <= 0) return doc;\n      } else {\n        while (match = HEREDOC_INDENT.exec(doc)) {\n          attempt = match[1];\n          if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) {\n            indent = attempt;\n          }\n        }\n      }\n      if (indent) doc = doc.replace(RegExp(\"\\\\n\" + indent, \"g\"), '\\n');\n      if (!herecomment) doc = doc.replace(/^\\n/, '');\n      return doc;\n    };\n\n    Lexer.prototype.tagParameters = function() {\n      var i, stack, tok, tokens;\n      if (this.tag() !== ')') return this;\n      stack = [];\n      tokens = this.tokens;\n      i = tokens.length;\n      tokens[--i][0] = 'PARAM_END';\n      while (tok = tokens[--i]) {\n        switch (tok[0]) {\n          case ')':\n            stack.push(tok);\n            break;\n          case '(':\n          case 'CALL_START':\n            if (stack.length) {\n              stack.pop();\n            } else if (tok[0] === '(') {\n              tok[0] = 'PARAM_START';\n              return this;\n            } else {\n              return this;\n            }\n        }\n      }\n      return this;\n    };\n\n    Lexer.prototype.closeIndentation = function() {\n      return this.outdentToken(this.indent);\n    };\n\n    Lexer.prototype.balancedString = function(str, end) {\n      var continueCount, i, letter, match, prev, stack, _i, _ref2;\n      continueCount = 0;\n      stack = [end];\n      for (i = _i = 1, _ref2 = str.length; 1 <= _ref2 ? _i < _ref2 : _i > _ref2; i = 1 <= _ref2 ? ++_i : --_i) {\n        if (continueCount) {\n          --continueCount;\n          continue;\n        }\n        switch (letter = str.charAt(i)) {\n          case '\\\\':\n            ++continueCount;\n            continue;\n          case end:\n            stack.pop();\n            if (!stack.length) return str.slice(0, i + 1 || 9e9);\n            end = stack[stack.length - 1];\n            continue;\n        }\n        if (end === '}' && (letter === '\"' || letter === \"'\")) {\n          stack.push(end = letter);\n        } else if (end === '}' && letter === '/' && (match = HEREGEX.exec(str.slice(i)) || REGEX.exec(str.slice(i)))) {\n          continueCount += match[0].length - 1;\n        } else if (end === '}' && letter === '{') {\n          stack.push(end = '}');\n        } else if (end === '\"' && prev === '#' && letter === '{') {\n          stack.push(end = '}');\n        }\n        prev = letter;\n      }\n      return this.error(\"missing \" + (stack.pop()) + \", starting\");\n    };\n\n    Lexer.prototype.interpolateString = function(str, options) {\n      var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4;\n      if (options == null) options = {};\n      heredoc = options.heredoc, regex = options.regex;\n      tokens = [];\n      pi = 0;\n      i = -1;\n      while (letter = str.charAt(i += 1)) {\n        if (letter === '\\\\') {\n          i += 1;\n          continue;\n        }\n        if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) {\n          continue;\n        }\n        if (pi < i) tokens.push(['NEOSTRING', str.slice(pi, i)]);\n        inner = expr.slice(1, -1);\n        if (inner.length) {\n          nested = new Lexer().tokenize(inner, {\n            line: this.line,\n            rewrite: false\n          });\n          nested.pop();\n          if (((_ref2 = nested[0]) != null ? _ref2[0] : void 0) === 'TERMINATOR') {\n            nested.shift();\n          }\n          if (len = nested.length) {\n            if (len > 1) {\n              nested.unshift(['(', '(', this.line]);\n              nested.push([')', ')', this.line]);\n            }\n            tokens.push(['TOKENS', nested]);\n          }\n        }\n        i += expr.length;\n        pi = i + 1;\n      }\n      if ((i > pi && pi < str.length)) tokens.push(['NEOSTRING', str.slice(pi)]);\n      if (regex) return tokens;\n      if (!tokens.length) return this.token('STRING', '\"\"');\n      if (tokens[0][0] !== 'NEOSTRING') tokens.unshift(['', '']);\n      if (interpolated = tokens.length > 1) this.token('(', '(');\n      for (i = _i = 0, _len = tokens.length; _i < _len; i = ++_i) {\n        _ref3 = tokens[i], tag = _ref3[0], value = _ref3[1];\n        if (i) this.token('+', '+');\n        if (tag === 'TOKENS') {\n          (_ref4 = this.tokens).push.apply(_ref4, value);\n        } else {\n          this.token('STRING', this.makeString(value, '\"', heredoc));\n        }\n      }\n      if (interpolated) this.token(')', ')');\n      return tokens;\n    };\n\n    Lexer.prototype.pair = function(tag) {\n      var size, wanted;\n      if (tag !== (wanted = last(this.ends))) {\n        if ('OUTDENT' !== wanted) this.error(\"unmatched \" + tag);\n        this.indent -= size = last(this.indents);\n        this.outdentToken(size, true);\n        return this.pair(tag);\n      }\n      return this.ends.pop();\n    };\n\n    Lexer.prototype.token = function(tag, value) {\n      return this.tokens.push([tag, value, this.line]);\n    };\n\n    Lexer.prototype.tag = function(index, tag) {\n      var tok;\n      return (tok = last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]);\n    };\n\n    Lexer.prototype.value = function(index, val) {\n      var tok;\n      return (tok = last(this.tokens, index)) && (val ? tok[1] = val : tok[1]);\n    };\n\n    Lexer.prototype.unfinished = function() {\n      var _ref2;\n      return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS');\n    };\n\n    Lexer.prototype.escapeLines = function(str, heredoc) {\n      return str.replace(MULTILINER, heredoc ? '\\\\n' : '');\n    };\n\n    Lexer.prototype.makeString = function(body, quote, heredoc) {\n      if (!body) return quote + quote;\n      body = body.replace(/\\\\([\\s\\S])/g, function(match, contents) {\n        if (contents === '\\n' || contents === quote) {\n          return contents;\n        } else {\n          return match;\n        }\n      });\n      body = body.replace(RegExp(\"\" + quote, \"g\"), '\\\\$&');\n      return quote + this.escapeLines(body, heredoc) + quote;\n    };\n\n    Lexer.prototype.error = function(message) {\n      throw SyntaxError(\"\" + message + \" on line \" + (this.line + 1));\n    };\n\n    return Lexer;\n\n  })();\n\n  JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super'];\n\n  COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when'];\n\n  COFFEE_ALIAS_MAP = {\n    and: '&&',\n    or: '||',\n    is: '==',\n    isnt: '!=',\n    not: '!',\n    yes: 'true',\n    no: 'false',\n    on: 'true',\n    off: 'false'\n  };\n\n  COFFEE_ALIASES = (function() {\n    var _results;\n    _results = [];\n    for (key in COFFEE_ALIAS_MAP) {\n      _results.push(key);\n    }\n    return _results;\n  })();\n\n  COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES);\n\n  RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf', 'implements', 'interface', 'let', 'package', 'private', 'protected', 'public', 'static', 'yield'];\n\n  STRICT_PROSCRIBED = ['arguments', 'eval'];\n\n  JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED).concat(STRICT_PROSCRIBED);\n\n  exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS).concat(STRICT_PROSCRIBED);\n\n  exports.STRICT_PROSCRIBED = STRICT_PROSCRIBED;\n\n  IDENTIFIER = /^([$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*)([^\\n\\S]*:(?!:))?/;\n\n  NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\\da-f]+|^\\d*\\.?\\d+(?:e[+-]?\\d+)?/i;\n\n  HEREDOC = /^(\"\"\"|''')([\\s\\S]*?)(?:\\n[^\\n\\S]*)?\\1/;\n\n  OPERATOR = /^(?:[-=]>|[-+*\\/%<>&|^!?=]=|>>>=?|([-+:])\\1|([&|<>])\\2=?|\\?\\.|\\.{2,3})/;\n\n  WHITESPACE = /^[^\\n\\S]+/;\n\n  COMMENT = /^###([^#][\\s\\S]*?)(?:###[^\\n\\S]*|(?:###)?$)|^(?:\\s*#(?!##[^#]).*)+/;\n\n  CODE = /^[-=]>/;\n\n  MULTI_DENT = /^(?:\\n[^\\n\\S]*)+/;\n\n  SIMPLESTR = /^'[^\\\\']*(?:\\\\.[^\\\\']*)*'/;\n\n  JSTOKEN = /^`[^\\\\`]*(?:\\\\.[^\\\\`]*)*`/;\n\n  REGEX = /^(\\/(?![\\s=])[^[\\/\\n\\\\]*(?:(?:\\\\[\\s\\S]|\\[[^\\]\\n\\\\]*(?:\\\\[\\s\\S][^\\]\\n\\\\]*)*])[^[\\/\\n\\\\]*)*\\/)([imgy]{0,4})(?!\\w)/;\n\n  HEREGEX = /^\\/{3}([\\s\\S]+?)\\/{3}([imgy]{0,4})(?!\\w)/;\n\n  HEREGEX_OMIT = /\\s+(?:#.*)?/g;\n\n  MULTILINER = /\\n/g;\n\n  HEREDOC_INDENT = /\\n+([^\\n\\S]*)/g;\n\n  HEREDOC_ILLEGAL = /\\*\\//;\n\n  LINE_CONTINUER = /^\\s*(?:,|\\??\\.(?![.\\d])|::)/;\n\n  TRAILING_SPACES = /\\s+$/;\n\n  COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];\n\n  UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO'];\n\n  LOGIC = ['&&', '||', '&', '|', '^'];\n\n  SHIFT = ['<<', '>>', '>>>'];\n\n  COMPARE = ['==', '!=', '<', '>', '<=', '>='];\n\n  MATH = ['*', '/', '%'];\n\n  RELATION = ['IN', 'OF', 'INSTANCEOF'];\n\n  BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED'];\n\n  NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']'];\n\n  NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING');\n\n  CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER'];\n\n  INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL');\n\n  LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];\n\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coffee/nodes.js",
    "content": "/**\n * Copyright (c) 2011 Jeremy Ashkenas\n * \n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n * \n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\ndefine(function(require, exports, module) {\n// Generated by CoffeeScript 1.2.1-pre\n\n  var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, Comment, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, STRICT_PROSCRIBED, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, compact, del, ends, extend, flatten, last, merge, multident, starts, unfoldSoak, utility, _ref, _ref1,\n    __hasProp = {}.hasOwnProperty,\n    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; },\n    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };\n\n  Scope = require('./scope').Scope;\n\n  _ref = require('./lexer'), RESERVED = _ref.RESERVED, STRICT_PROSCRIBED = _ref.STRICT_PROSCRIBED;\n\n  _ref1 = require('./helpers'), compact = _ref1.compact, flatten = _ref1.flatten, extend = _ref1.extend, merge = _ref1.merge, del = _ref1.del, starts = _ref1.starts, ends = _ref1.ends, last = _ref1.last;\n\n  exports.extend = extend;\n\n  YES = function() {\n    return true;\n  };\n\n  NO = function() {\n    return false;\n  };\n\n  THIS = function() {\n    return this;\n  };\n\n  NEGATE = function() {\n    this.negated = !this.negated;\n    return this;\n  };\n\n  exports.Base = Base = (function() {\n\n    Base.name = 'Base';\n\n    function Base() {}\n\n    Base.prototype.compile = function(o, lvl) {\n      var node;\n      o = extend({}, o);\n      if (lvl) o.level = lvl;\n      node = this.unfoldSoak(o) || this;\n      node.tab = o.indent;\n      if (o.level === LEVEL_TOP || !node.isStatement(o)) {\n        return node.compileNode(o);\n      } else {\n        return node.compileClosure(o);\n      }\n    };\n\n    Base.prototype.compileClosure = function(o) {\n      if (this.jumps()) {\n        throw SyntaxError('cannot use a pure statement in an expression.');\n      }\n      o.sharedScope = true;\n      return Closure.wrap(this).compileNode(o);\n    };\n\n    Base.prototype.cache = function(o, level, reused) {\n      var ref, sub;\n      if (!this.isComplex()) {\n        ref = level ? this.compile(o, level) : this;\n        return [ref, ref];\n      } else {\n        ref = new Literal(reused || o.scope.freeVariable('ref'));\n        sub = new Assign(ref, this);\n        if (level) {\n          return [sub.compile(o, level), ref.value];\n        } else {\n          return [sub, ref];\n        }\n      }\n    };\n\n    Base.prototype.compileLoopReference = function(o, name) {\n      var src, tmp;\n      src = tmp = this.compile(o, LEVEL_LIST);\n      if (!((-Infinity < +src && +src < Infinity) || IDENTIFIER.test(src) && o.scope.check(src, true))) {\n        src = \"\" + (tmp = o.scope.freeVariable(name)) + \" = \" + src;\n      }\n      return [src, tmp];\n    };\n\n    Base.prototype.makeReturn = function(res) {\n      var me;\n      me = this.unwrapAll();\n      if (res) {\n        return new Call(new Literal(\"\" + res + \".push\"), [me]);\n      } else {\n        return new Return(me);\n      }\n    };\n\n    Base.prototype.contains = function(pred) {\n      var contains;\n      contains = false;\n      this.traverseChildren(false, function(node) {\n        if (pred(node)) {\n          contains = true;\n          return false;\n        }\n      });\n      return contains;\n    };\n\n    Base.prototype.containsType = function(type) {\n      return this instanceof type || this.contains(function(node) {\n        return node instanceof type;\n      });\n    };\n\n    Base.prototype.lastNonComment = function(list) {\n      var i;\n      i = list.length;\n      while (i--) {\n        if (!(list[i] instanceof Comment)) return list[i];\n      }\n      return null;\n    };\n\n    Base.prototype.toString = function(idt, name) {\n      var tree;\n      if (idt == null) idt = '';\n      if (name == null) name = this.constructor.name;\n      tree = '\\n' + idt + name;\n      if (this.soak) tree += '?';\n      this.eachChild(function(node) {\n        return tree += node.toString(idt + TAB);\n      });\n      return tree;\n    };\n\n    Base.prototype.eachChild = function(func) {\n      var attr, child, _i, _j, _len, _len1, _ref2, _ref3;\n      if (!this.children) return this;\n      _ref2 = this.children;\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        attr = _ref2[_i];\n        if (this[attr]) {\n          _ref3 = flatten([this[attr]]);\n          for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {\n            child = _ref3[_j];\n            if (func(child) === false) return this;\n          }\n        }\n      }\n      return this;\n    };\n\n    Base.prototype.traverseChildren = function(crossScope, func) {\n      return this.eachChild(function(child) {\n        if (func(child) === false) return false;\n        return child.traverseChildren(crossScope, func);\n      });\n    };\n\n    Base.prototype.invert = function() {\n      return new Op('!', this);\n    };\n\n    Base.prototype.unwrapAll = function() {\n      var node;\n      node = this;\n      while (node !== (node = node.unwrap())) {\n        continue;\n      }\n      return node;\n    };\n\n    Base.prototype.children = [];\n\n    Base.prototype.isStatement = NO;\n\n    Base.prototype.jumps = NO;\n\n    Base.prototype.isComplex = YES;\n\n    Base.prototype.isChainable = NO;\n\n    Base.prototype.isAssignable = NO;\n\n    Base.prototype.unwrap = THIS;\n\n    Base.prototype.unfoldSoak = NO;\n\n    Base.prototype.assigns = NO;\n\n    return Base;\n\n  })();\n\n  exports.Block = Block = (function(_super) {\n\n    __extends(Block, _super);\n\n    Block.name = 'Block';\n\n    function Block(nodes) {\n      this.expressions = compact(flatten(nodes || []));\n    }\n\n    Block.prototype.children = ['expressions'];\n\n    Block.prototype.push = function(node) {\n      this.expressions.push(node);\n      return this;\n    };\n\n    Block.prototype.pop = function() {\n      return this.expressions.pop();\n    };\n\n    Block.prototype.unshift = function(node) {\n      this.expressions.unshift(node);\n      return this;\n    };\n\n    Block.prototype.unwrap = function() {\n      if (this.expressions.length === 1) {\n        return this.expressions[0];\n      } else {\n        return this;\n      }\n    };\n\n    Block.prototype.isEmpty = function() {\n      return !this.expressions.length;\n    };\n\n    Block.prototype.isStatement = function(o) {\n      var exp, _i, _len, _ref2;\n      _ref2 = this.expressions;\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        exp = _ref2[_i];\n        if (exp.isStatement(o)) return true;\n      }\n      return false;\n    };\n\n    Block.prototype.jumps = function(o) {\n      var exp, _i, _len, _ref2;\n      _ref2 = this.expressions;\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        exp = _ref2[_i];\n        if (exp.jumps(o)) return exp;\n      }\n    };\n\n    Block.prototype.makeReturn = function(res) {\n      var expr, len;\n      len = this.expressions.length;\n      while (len--) {\n        expr = this.expressions[len];\n        if (!(expr instanceof Comment)) {\n          this.expressions[len] = expr.makeReturn(res);\n          if (expr instanceof Return && !expr.expression) {\n            this.expressions.splice(len, 1);\n          }\n          break;\n        }\n      }\n      return this;\n    };\n\n    Block.prototype.compile = function(o, level) {\n      if (o == null) o = {};\n      if (o.scope) {\n        return Block.__super__.compile.call(this, o, level);\n      } else {\n        return this.compileRoot(o);\n      }\n    };\n\n    Block.prototype.compileNode = function(o) {\n      var code, codes, node, top, _i, _len, _ref2;\n      this.tab = o.indent;\n      top = o.level === LEVEL_TOP;\n      codes = [];\n      _ref2 = this.expressions;\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        node = _ref2[_i];\n        node = node.unwrapAll();\n        node = node.unfoldSoak(o) || node;\n        if (node instanceof Block) {\n          codes.push(node.compileNode(o));\n        } else if (top) {\n          node.front = true;\n          code = node.compile(o);\n          if (!node.isStatement(o)) {\n            code = \"\" + this.tab + code + \";\";\n            if (node instanceof Literal) code = \"\" + code + \"\\n\";\n          }\n          codes.push(code);\n        } else {\n          codes.push(node.compile(o, LEVEL_LIST));\n        }\n      }\n      if (top) {\n        if (this.spaced) {\n          return \"\\n\" + (codes.join('\\n\\n')) + \"\\n\";\n        } else {\n          return codes.join('\\n');\n        }\n      }\n      code = codes.join(', ') || 'void 0';\n      if (codes.length > 1 && o.level >= LEVEL_LIST) {\n        return \"(\" + code + \")\";\n      } else {\n        return code;\n      }\n    };\n\n    Block.prototype.compileRoot = function(o) {\n      var code, exp, i, prelude, preludeExps, rest;\n      o.indent = o.bare ? '' : TAB;\n      o.scope = new Scope(null, this, null);\n      o.level = LEVEL_TOP;\n      this.spaced = true;\n      prelude = \"\";\n      if (!o.bare) {\n        preludeExps = (function() {\n          var _i, _len, _ref2, _results;\n          _ref2 = this.expressions;\n          _results = [];\n          for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) {\n            exp = _ref2[i];\n            if (!(exp.unwrap() instanceof Comment)) break;\n            _results.push(exp);\n          }\n          return _results;\n        }).call(this);\n        rest = this.expressions.slice(preludeExps.length);\n        this.expressions = preludeExps;\n        if (preludeExps.length) {\n          prelude = \"\" + (this.compileNode(merge(o, {\n            indent: ''\n          }))) + \"\\n\";\n        }\n        this.expressions = rest;\n      }\n      code = this.compileWithDeclarations(o);\n      if (o.bare) return code;\n      return \"\" + prelude + \"(function() {\\n\" + code + \"\\n}).call(this);\\n\";\n    };\n\n    Block.prototype.compileWithDeclarations = function(o) {\n      var assigns, code, declars, exp, i, post, rest, scope, spaced, _i, _len, _ref2, _ref3, _ref4;\n      code = post = '';\n      _ref2 = this.expressions;\n      for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) {\n        exp = _ref2[i];\n        exp = exp.unwrap();\n        if (!(exp instanceof Comment || exp instanceof Literal)) break;\n      }\n      o = merge(o, {\n        level: LEVEL_TOP\n      });\n      if (i) {\n        rest = this.expressions.splice(i, 9e9);\n        _ref3 = [this.spaced, false], spaced = _ref3[0], this.spaced = _ref3[1];\n        _ref4 = [this.compileNode(o), spaced], code = _ref4[0], this.spaced = _ref4[1];\n        this.expressions = rest;\n      }\n      post = this.compileNode(o);\n      scope = o.scope;\n      if (scope.expressions === this) {\n        declars = o.scope.hasDeclarations();\n        assigns = scope.hasAssignments;\n        if (declars || assigns) {\n          if (i) code += '\\n';\n          code += \"\" + this.tab + \"var \";\n          if (declars) code += scope.declaredVariables().join(', ');\n          if (assigns) {\n            if (declars) code += \",\\n\" + (this.tab + TAB);\n            code += scope.assignedVariables().join(\",\\n\" + (this.tab + TAB));\n          }\n          code += ';\\n';\n        }\n      }\n      return code + post;\n    };\n\n    Block.wrap = function(nodes) {\n      if (nodes.length === 1 && nodes[0] instanceof Block) return nodes[0];\n      return new Block(nodes);\n    };\n\n    return Block;\n\n  })(Base);\n\n  exports.Literal = Literal = (function(_super) {\n\n    __extends(Literal, _super);\n\n    Literal.name = 'Literal';\n\n    function Literal(value) {\n      this.value = value;\n    }\n\n    Literal.prototype.makeReturn = function() {\n      if (this.isStatement()) {\n        return this;\n      } else {\n        return Literal.__super__.makeReturn.apply(this, arguments);\n      }\n    };\n\n    Literal.prototype.isAssignable = function() {\n      return IDENTIFIER.test(this.value);\n    };\n\n    Literal.prototype.isStatement = function() {\n      var _ref2;\n      return (_ref2 = this.value) === 'break' || _ref2 === 'continue' || _ref2 === 'debugger';\n    };\n\n    Literal.prototype.isComplex = NO;\n\n    Literal.prototype.assigns = function(name) {\n      return name === this.value;\n    };\n\n    Literal.prototype.jumps = function(o) {\n      if (this.value === 'break' && !((o != null ? o.loop : void 0) || (o != null ? o.block : void 0))) {\n        return this;\n      }\n      if (this.value === 'continue' && !(o != null ? o.loop : void 0)) return this;\n    };\n\n    Literal.prototype.compileNode = function(o) {\n      var code, _ref2;\n      code = this.isUndefined ? o.level >= LEVEL_ACCESS ? '(void 0)' : 'void 0' : this.value === 'this' ? ((_ref2 = o.scope.method) != null ? _ref2.bound : void 0) ? o.scope.method.context : this.value : this.value.reserved ? \"\\\"\" + this.value + \"\\\"\" : this.value;\n      if (this.isStatement()) {\n        return \"\" + this.tab + code + \";\";\n      } else {\n        return code;\n      }\n    };\n\n    Literal.prototype.toString = function() {\n      return ' \"' + this.value + '\"';\n    };\n\n    return Literal;\n\n  })(Base);\n\n  exports.Return = Return = (function(_super) {\n\n    __extends(Return, _super);\n\n    Return.name = 'Return';\n\n    function Return(expr) {\n      if (expr && !expr.unwrap().isUndefined) this.expression = expr;\n    }\n\n    Return.prototype.children = ['expression'];\n\n    Return.prototype.isStatement = YES;\n\n    Return.prototype.makeReturn = THIS;\n\n    Return.prototype.jumps = THIS;\n\n    Return.prototype.compile = function(o, level) {\n      var expr, _ref2;\n      expr = (_ref2 = this.expression) != null ? _ref2.makeReturn() : void 0;\n      if (expr && !(expr instanceof Return)) {\n        return expr.compile(o, level);\n      } else {\n        return Return.__super__.compile.call(this, o, level);\n      }\n    };\n\n    Return.prototype.compileNode = function(o) {\n      return this.tab + (\"return\" + [this.expression ? \" \" + (this.expression.compile(o, LEVEL_PAREN)) : void 0] + \";\");\n    };\n\n    return Return;\n\n  })(Base);\n\n  exports.Value = Value = (function(_super) {\n\n    __extends(Value, _super);\n\n    Value.name = 'Value';\n\n    function Value(base, props, tag) {\n      if (!props && base instanceof Value) return base;\n      this.base = base;\n      this.properties = props || [];\n      if (tag) this[tag] = true;\n      return this;\n    }\n\n    Value.prototype.children = ['base', 'properties'];\n\n    Value.prototype.add = function(props) {\n      this.properties = this.properties.concat(props);\n      return this;\n    };\n\n    Value.prototype.hasProperties = function() {\n      return !!this.properties.length;\n    };\n\n    Value.prototype.isArray = function() {\n      return !this.properties.length && this.base instanceof Arr;\n    };\n\n    Value.prototype.isComplex = function() {\n      return this.hasProperties() || this.base.isComplex();\n    };\n\n    Value.prototype.isAssignable = function() {\n      return this.hasProperties() || this.base.isAssignable();\n    };\n\n    Value.prototype.isSimpleNumber = function() {\n      return this.base instanceof Literal && SIMPLENUM.test(this.base.value);\n    };\n\n    Value.prototype.isString = function() {\n      return this.base instanceof Literal && IS_STRING.test(this.base.value);\n    };\n\n    Value.prototype.isAtomic = function() {\n      var node, _i, _len, _ref2;\n      _ref2 = this.properties.concat(this.base);\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        node = _ref2[_i];\n        if (node.soak || node instanceof Call) return false;\n      }\n      return true;\n    };\n\n    Value.prototype.isStatement = function(o) {\n      return !this.properties.length && this.base.isStatement(o);\n    };\n\n    Value.prototype.assigns = function(name) {\n      return !this.properties.length && this.base.assigns(name);\n    };\n\n    Value.prototype.jumps = function(o) {\n      return !this.properties.length && this.base.jumps(o);\n    };\n\n    Value.prototype.isObject = function(onlyGenerated) {\n      if (this.properties.length) return false;\n      return (this.base instanceof Obj) && (!onlyGenerated || this.base.generated);\n    };\n\n    Value.prototype.isSplice = function() {\n      return last(this.properties) instanceof Slice;\n    };\n\n    Value.prototype.unwrap = function() {\n      if (this.properties.length) {\n        return this;\n      } else {\n        return this.base;\n      }\n    };\n\n    Value.prototype.cacheReference = function(o) {\n      var base, bref, name, nref;\n      name = last(this.properties);\n      if (this.properties.length < 2 && !this.base.isComplex() && !(name != null ? name.isComplex() : void 0)) {\n        return [this, this];\n      }\n      base = new Value(this.base, this.properties.slice(0, -1));\n      if (base.isComplex()) {\n        bref = new Literal(o.scope.freeVariable('base'));\n        base = new Value(new Parens(new Assign(bref, base)));\n      }\n      if (!name) return [base, bref];\n      if (name.isComplex()) {\n        nref = new Literal(o.scope.freeVariable('name'));\n        name = new Index(new Assign(nref, name.index));\n        nref = new Index(nref);\n      }\n      return [base.add(name), new Value(bref || base.base, [nref || name])];\n    };\n\n    Value.prototype.compileNode = function(o) {\n      var code, prop, props, _i, _len;\n      this.base.front = this.front;\n      props = this.properties;\n      code = this.base.compile(o, props.length ? LEVEL_ACCESS : null);\n      if ((this.base instanceof Parens || props.length) && SIMPLENUM.test(code)) {\n        code = \"\" + code + \".\";\n      }\n      for (_i = 0, _len = props.length; _i < _len; _i++) {\n        prop = props[_i];\n        code += prop.compile(o);\n      }\n      return code;\n    };\n\n    Value.prototype.unfoldSoak = function(o) {\n      var result,\n        _this = this;\n      if (this.unfoldedSoak != null) return this.unfoldedSoak;\n      result = (function() {\n        var fst, i, ifn, prop, ref, snd, _i, _len, _ref2;\n        if (ifn = _this.base.unfoldSoak(o)) {\n          Array.prototype.push.apply(ifn.body.properties, _this.properties);\n          return ifn;\n        }\n        _ref2 = _this.properties;\n        for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) {\n          prop = _ref2[i];\n          if (!prop.soak) continue;\n          prop.soak = false;\n          fst = new Value(_this.base, _this.properties.slice(0, i));\n          snd = new Value(_this.base, _this.properties.slice(i));\n          if (fst.isComplex()) {\n            ref = new Literal(o.scope.freeVariable('ref'));\n            fst = new Parens(new Assign(ref, fst));\n            snd.base = ref;\n          }\n          return new If(new Existence(fst), snd, {\n            soak: true\n          });\n        }\n        return null;\n      })();\n      return this.unfoldedSoak = result || false;\n    };\n\n    return Value;\n\n  })(Base);\n\n  exports.Comment = Comment = (function(_super) {\n\n    __extends(Comment, _super);\n\n    Comment.name = 'Comment';\n\n    function Comment(comment) {\n      this.comment = comment;\n    }\n\n    Comment.prototype.isStatement = YES;\n\n    Comment.prototype.makeReturn = THIS;\n\n    Comment.prototype.compileNode = function(o, level) {\n      var code;\n      code = '/*' + multident(this.comment, this.tab) + (\"\\n\" + this.tab + \"*/\\n\");\n      if ((level || o.level) === LEVEL_TOP) code = o.indent + code;\n      return code;\n    };\n\n    return Comment;\n\n  })(Base);\n\n  exports.Call = Call = (function(_super) {\n\n    __extends(Call, _super);\n\n    Call.name = 'Call';\n\n    function Call(variable, args, soak) {\n      this.args = args != null ? args : [];\n      this.soak = soak;\n      this.isNew = false;\n      this.isSuper = variable === 'super';\n      this.variable = this.isSuper ? null : variable;\n    }\n\n    Call.prototype.children = ['variable', 'args'];\n\n    Call.prototype.newInstance = function() {\n      var base, _ref2;\n      base = ((_ref2 = this.variable) != null ? _ref2.base : void 0) || this.variable;\n      if (base instanceof Call && !base.isNew) {\n        base.newInstance();\n      } else {\n        this.isNew = true;\n      }\n      return this;\n    };\n\n    Call.prototype.superReference = function(o) {\n      var accesses, method, name;\n      method = o.scope.method;\n      if (!method) throw SyntaxError('cannot call super outside of a function.');\n      name = method.name;\n      if (name == null) {\n        throw SyntaxError('cannot call super on an anonymous function.');\n      }\n      if (method.klass) {\n        accesses = [new Access(new Literal('__super__'))];\n        if (method[\"static\"]) {\n          accesses.push(new Access(new Literal('constructor')));\n        }\n        accesses.push(new Access(new Literal(name)));\n        return (new Value(new Literal(method.klass), accesses)).compile(o);\n      } else {\n        return \"\" + name + \".__super__.constructor\";\n      }\n    };\n\n    Call.prototype.unfoldSoak = function(o) {\n      var call, ifn, left, list, rite, _i, _len, _ref2, _ref3;\n      if (this.soak) {\n        if (this.variable) {\n          if (ifn = unfoldSoak(o, this, 'variable')) return ifn;\n          _ref2 = new Value(this.variable).cacheReference(o), left = _ref2[0], rite = _ref2[1];\n        } else {\n          left = new Literal(this.superReference(o));\n          rite = new Value(left);\n        }\n        rite = new Call(rite, this.args);\n        rite.isNew = this.isNew;\n        left = new Literal(\"typeof \" + (left.compile(o)) + \" === \\\"function\\\"\");\n        return new If(left, new Value(rite), {\n          soak: true\n        });\n      }\n      call = this;\n      list = [];\n      while (true) {\n        if (call.variable instanceof Call) {\n          list.push(call);\n          call = call.variable;\n          continue;\n        }\n        if (!(call.variable instanceof Value)) break;\n        list.push(call);\n        if (!((call = call.variable.base) instanceof Call)) break;\n      }\n      _ref3 = list.reverse();\n      for (_i = 0, _len = _ref3.length; _i < _len; _i++) {\n        call = _ref3[_i];\n        if (ifn) {\n          if (call.variable instanceof Call) {\n            call.variable = ifn;\n          } else {\n            call.variable.base = ifn;\n          }\n        }\n        ifn = unfoldSoak(o, call, 'variable');\n      }\n      return ifn;\n    };\n\n    Call.prototype.filterImplicitObjects = function(list) {\n      var node, nodes, obj, prop, properties, _i, _j, _len, _len1, _ref2;\n      nodes = [];\n      for (_i = 0, _len = list.length; _i < _len; _i++) {\n        node = list[_i];\n        if (!((typeof node.isObject === \"function\" ? node.isObject() : void 0) && node.base.generated)) {\n          nodes.push(node);\n          continue;\n        }\n        obj = null;\n        _ref2 = node.base.properties;\n        for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {\n          prop = _ref2[_j];\n          if (prop instanceof Assign || prop instanceof Comment) {\n            if (!obj) nodes.push(obj = new Obj(properties = [], true));\n            properties.push(prop);\n          } else {\n            nodes.push(prop);\n            obj = null;\n          }\n        }\n      }\n      return nodes;\n    };\n\n    Call.prototype.compileNode = function(o) {\n      var arg, args, code, _ref2;\n      if ((_ref2 = this.variable) != null) _ref2.front = this.front;\n      if (code = Splat.compileSplattedArray(o, this.args, true)) {\n        return this.compileSplat(o, code);\n      }\n      args = this.filterImplicitObjects(this.args);\n      args = ((function() {\n        var _i, _len, _results;\n        _results = [];\n        for (_i = 0, _len = args.length; _i < _len; _i++) {\n          arg = args[_i];\n          _results.push(arg.compile(o, LEVEL_LIST));\n        }\n        return _results;\n      })()).join(', ');\n      if (this.isSuper) {\n        return this.superReference(o) + (\".call(this\" + (args && ', ' + args) + \")\");\n      } else {\n        return (this.isNew ? 'new ' : '') + this.variable.compile(o, LEVEL_ACCESS) + (\"(\" + args + \")\");\n      }\n    };\n\n    Call.prototype.compileSuper = function(args, o) {\n      return \"\" + (this.superReference(o)) + \".call(this\" + (args.length ? ', ' : '') + args + \")\";\n    };\n\n    Call.prototype.compileSplat = function(o, splatArgs) {\n      var base, fun, idt, name, ref;\n      if (this.isSuper) {\n        return \"\" + (this.superReference(o)) + \".apply(this, \" + splatArgs + \")\";\n      }\n      if (this.isNew) {\n        idt = this.tab + TAB;\n        return \"(function(func, args, ctor) {\\n\" + idt + \"ctor.prototype = func.prototype;\\n\" + idt + \"var child = new ctor, result = func.apply(child, args), t = typeof result;\\n\" + idt + \"return t == \\\"object\\\" || t == \\\"function\\\" ? result || child : child;\\n\" + this.tab + \"})(\" + (this.variable.compile(o, LEVEL_LIST)) + \", \" + splatArgs + \", function(){})\";\n      }\n      base = new Value(this.variable);\n      if ((name = base.properties.pop()) && base.isComplex()) {\n        ref = o.scope.freeVariable('ref');\n        fun = \"(\" + ref + \" = \" + (base.compile(o, LEVEL_LIST)) + \")\" + (name.compile(o));\n      } else {\n        fun = base.compile(o, LEVEL_ACCESS);\n        if (SIMPLENUM.test(fun)) fun = \"(\" + fun + \")\";\n        if (name) {\n          ref = fun;\n          fun += name.compile(o);\n        } else {\n          ref = 'null';\n        }\n      }\n      return \"\" + fun + \".apply(\" + ref + \", \" + splatArgs + \")\";\n    };\n\n    return Call;\n\n  })(Base);\n\n  exports.Extends = Extends = (function(_super) {\n\n    __extends(Extends, _super);\n\n    Extends.name = 'Extends';\n\n    function Extends(child, parent) {\n      this.child = child;\n      this.parent = parent;\n    }\n\n    Extends.prototype.children = ['child', 'parent'];\n\n    Extends.prototype.compile = function(o) {\n      return new Call(new Value(new Literal(utility('extends'))), [this.child, this.parent]).compile(o);\n    };\n\n    return Extends;\n\n  })(Base);\n\n  exports.Access = Access = (function(_super) {\n\n    __extends(Access, _super);\n\n    Access.name = 'Access';\n\n    function Access(name, tag) {\n      this.name = name;\n      this.name.asKey = true;\n      this.soak = tag === 'soak';\n    }\n\n    Access.prototype.children = ['name'];\n\n    Access.prototype.compile = function(o) {\n      var name;\n      name = this.name.compile(o);\n      if (IDENTIFIER.test(name)) {\n        return \".\" + name;\n      } else {\n        return \"[\" + name + \"]\";\n      }\n    };\n\n    Access.prototype.isComplex = NO;\n\n    return Access;\n\n  })(Base);\n\n  exports.Index = Index = (function(_super) {\n\n    __extends(Index, _super);\n\n    Index.name = 'Index';\n\n    function Index(index) {\n      this.index = index;\n    }\n\n    Index.prototype.children = ['index'];\n\n    Index.prototype.compile = function(o) {\n      return \"[\" + (this.index.compile(o, LEVEL_PAREN)) + \"]\";\n    };\n\n    Index.prototype.isComplex = function() {\n      return this.index.isComplex();\n    };\n\n    return Index;\n\n  })(Base);\n\n  exports.Range = Range = (function(_super) {\n\n    __extends(Range, _super);\n\n    Range.name = 'Range';\n\n    Range.prototype.children = ['from', 'to'];\n\n    function Range(from, to, tag) {\n      this.from = from;\n      this.to = to;\n      this.exclusive = tag === 'exclusive';\n      this.equals = this.exclusive ? '' : '=';\n    }\n\n    Range.prototype.compileVariables = function(o) {\n      var step, _ref2, _ref3, _ref4, _ref5;\n      o = merge(o, {\n        top: true\n      });\n      _ref2 = this.from.cache(o, LEVEL_LIST), this.fromC = _ref2[0], this.fromVar = _ref2[1];\n      _ref3 = this.to.cache(o, LEVEL_LIST), this.toC = _ref3[0], this.toVar = _ref3[1];\n      if (step = del(o, 'step')) {\n        _ref4 = step.cache(o, LEVEL_LIST), this.step = _ref4[0], this.stepVar = _ref4[1];\n      }\n      _ref5 = [this.fromVar.match(SIMPLENUM), this.toVar.match(SIMPLENUM)], this.fromNum = _ref5[0], this.toNum = _ref5[1];\n      if (this.stepVar) return this.stepNum = this.stepVar.match(SIMPLENUM);\n    };\n\n    Range.prototype.compileNode = function(o) {\n      var cond, condPart, from, gt, idx, idxName, known, lt, namedIndex, stepPart, to, varPart, _ref2, _ref3;\n      if (!this.fromVar) this.compileVariables(o);\n      if (!o.index) return this.compileArray(o);\n      known = this.fromNum && this.toNum;\n      idx = del(o, 'index');\n      idxName = del(o, 'name');\n      namedIndex = idxName && idxName !== idx;\n      varPart = \"\" + idx + \" = \" + this.fromC;\n      if (this.toC !== this.toVar) varPart += \", \" + this.toC;\n      if (this.step !== this.stepVar) varPart += \", \" + this.step;\n      _ref2 = [\"\" + idx + \" <\" + this.equals, \"\" + idx + \" >\" + this.equals], lt = _ref2[0], gt = _ref2[1];\n      condPart = this.stepNum ? +this.stepNum > 0 ? \"\" + lt + \" \" + this.toVar : \"\" + gt + \" \" + this.toVar : known ? ((_ref3 = [+this.fromNum, +this.toNum], from = _ref3[0], to = _ref3[1], _ref3), from <= to ? \"\" + lt + \" \" + to : \"\" + gt + \" \" + to) : (cond = \"\" + this.fromVar + \" <= \" + this.toVar, \"\" + cond + \" ? \" + lt + \" \" + this.toVar + \" : \" + gt + \" \" + this.toVar);\n      stepPart = this.stepVar ? \"\" + idx + \" += \" + this.stepVar : known ? namedIndex ? from <= to ? \"++\" + idx : \"--\" + idx : from <= to ? \"\" + idx + \"++\" : \"\" + idx + \"--\" : namedIndex ? \"\" + cond + \" ? ++\" + idx + \" : --\" + idx : \"\" + cond + \" ? \" + idx + \"++ : \" + idx + \"--\";\n      if (namedIndex) varPart = \"\" + idxName + \" = \" + varPart;\n      if (namedIndex) stepPart = \"\" + idxName + \" = \" + stepPart;\n      return \"\" + varPart + \"; \" + condPart + \"; \" + stepPart;\n    };\n\n    Range.prototype.compileArray = function(o) {\n      var args, body, cond, hasArgs, i, idt, post, pre, range, result, vars, _i, _ref2, _ref3, _results;\n      if (this.fromNum && this.toNum && Math.abs(this.fromNum - this.toNum) <= 20) {\n        range = (function() {\n          _results = [];\n          for (var _i = _ref2 = +this.fromNum, _ref3 = +this.toNum; _ref2 <= _ref3 ? _i <= _ref3 : _i >= _ref3; _ref2 <= _ref3 ? _i++ : _i--){ _results.push(_i); }\n          return _results;\n        }).apply(this);\n        if (this.exclusive) range.pop();\n        return \"[\" + (range.join(', ')) + \"]\";\n      }\n      idt = this.tab + TAB;\n      i = o.scope.freeVariable('i');\n      result = o.scope.freeVariable('results');\n      pre = \"\\n\" + idt + result + \" = [];\";\n      if (this.fromNum && this.toNum) {\n        o.index = i;\n        body = this.compileNode(o);\n      } else {\n        vars = (\"\" + i + \" = \" + this.fromC) + (this.toC !== this.toVar ? \", \" + this.toC : '');\n        cond = \"\" + this.fromVar + \" <= \" + this.toVar;\n        body = \"var \" + vars + \"; \" + cond + \" ? \" + i + \" <\" + this.equals + \" \" + this.toVar + \" : \" + i + \" >\" + this.equals + \" \" + this.toVar + \"; \" + cond + \" ? \" + i + \"++ : \" + i + \"--\";\n      }\n      post = \"{ \" + result + \".push(\" + i + \"); }\\n\" + idt + \"return \" + result + \";\\n\" + o.indent;\n      hasArgs = function(node) {\n        return node != null ? node.contains(function(n) {\n          return n instanceof Literal && n.value === 'arguments' && !n.asKey;\n        }) : void 0;\n      };\n      if (hasArgs(this.from) || hasArgs(this.to)) args = ', arguments';\n      return \"(function() {\" + pre + \"\\n\" + idt + \"for (\" + body + \")\" + post + \"}).apply(this\" + (args != null ? args : '') + \")\";\n    };\n\n    return Range;\n\n  })(Base);\n\n  exports.Slice = Slice = (function(_super) {\n\n    __extends(Slice, _super);\n\n    Slice.name = 'Slice';\n\n    Slice.prototype.children = ['range'];\n\n    function Slice(range) {\n      this.range = range;\n      Slice.__super__.constructor.call(this);\n    }\n\n    Slice.prototype.compileNode = function(o) {\n      var compiled, from, fromStr, to, toStr, _ref2;\n      _ref2 = this.range, to = _ref2.to, from = _ref2.from;\n      fromStr = from && from.compile(o, LEVEL_PAREN) || '0';\n      compiled = to && to.compile(o, LEVEL_PAREN);\n      if (to && !(!this.range.exclusive && +compiled === -1)) {\n        toStr = ', ' + (this.range.exclusive ? compiled : SIMPLENUM.test(compiled) ? \"\" + (+compiled + 1) : (compiled = to.compile(o, LEVEL_ACCESS), \"\" + compiled + \" + 1 || 9e9\"));\n      }\n      return \".slice(\" + fromStr + (toStr || '') + \")\";\n    };\n\n    return Slice;\n\n  })(Base);\n\n  exports.Obj = Obj = (function(_super) {\n\n    __extends(Obj, _super);\n\n    Obj.name = 'Obj';\n\n    function Obj(props, generated) {\n      this.generated = generated != null ? generated : false;\n      this.objects = this.properties = props || [];\n    }\n\n    Obj.prototype.children = ['properties'];\n\n    Obj.prototype.compileNode = function(o) {\n      var i, idt, indent, join, lastNoncom, node, obj, prop, propName, propNames, props, _i, _j, _len, _len1, _ref2;\n      props = this.properties;\n      propNames = [];\n      _ref2 = this.properties;\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        prop = _ref2[_i];\n        if (prop.isComplex()) prop = prop.variable;\n        if (prop != null) {\n          propName = prop.unwrapAll().value.toString();\n          if (__indexOf.call(propNames, propName) >= 0) {\n            throw SyntaxError(\"multiple object literal properties named \\\"\" + propName + \"\\\"\");\n          }\n          propNames.push(propName);\n        }\n      }\n      if (!props.length) return (this.front ? '({})' : '{}');\n      if (this.generated) {\n        for (_j = 0, _len1 = props.length; _j < _len1; _j++) {\n          node = props[_j];\n          if (node instanceof Value) {\n            throw new Error('cannot have an implicit value in an implicit object');\n          }\n        }\n      }\n      idt = o.indent += TAB;\n      lastNoncom = this.lastNonComment(this.properties);\n      props = (function() {\n        var _k, _len2, _results;\n        _results = [];\n        for (i = _k = 0, _len2 = props.length; _k < _len2; i = ++_k) {\n          prop = props[i];\n          join = i === props.length - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\\n' : ',\\n';\n          indent = prop instanceof Comment ? '' : idt;\n          if (prop instanceof Value && prop[\"this\"]) {\n            prop = new Assign(prop.properties[0].name, prop, 'object');\n          }\n          if (!(prop instanceof Comment)) {\n            if (!(prop instanceof Assign)) prop = new Assign(prop, prop, 'object');\n            (prop.variable.base || prop.variable).asKey = true;\n          }\n          _results.push(indent + prop.compile(o, LEVEL_TOP) + join);\n        }\n        return _results;\n      })();\n      props = props.join('');\n      obj = \"{\" + (props && '\\n' + props + '\\n' + this.tab) + \"}\";\n      if (this.front) {\n        return \"(\" + obj + \")\";\n      } else {\n        return obj;\n      }\n    };\n\n    Obj.prototype.assigns = function(name) {\n      var prop, _i, _len, _ref2;\n      _ref2 = this.properties;\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        prop = _ref2[_i];\n        if (prop.assigns(name)) return true;\n      }\n      return false;\n    };\n\n    return Obj;\n\n  })(Base);\n\n  exports.Arr = Arr = (function(_super) {\n\n    __extends(Arr, _super);\n\n    Arr.name = 'Arr';\n\n    function Arr(objs) {\n      this.objects = objs || [];\n    }\n\n    Arr.prototype.children = ['objects'];\n\n    Arr.prototype.filterImplicitObjects = Call.prototype.filterImplicitObjects;\n\n    Arr.prototype.compileNode = function(o) {\n      var code, obj, objs;\n      if (!this.objects.length) return '[]';\n      o.indent += TAB;\n      objs = this.filterImplicitObjects(this.objects);\n      if (code = Splat.compileSplattedArray(o, objs)) return code;\n      code = ((function() {\n        var _i, _len, _results;\n        _results = [];\n        for (_i = 0, _len = objs.length; _i < _len; _i++) {\n          obj = objs[_i];\n          _results.push(obj.compile(o, LEVEL_LIST));\n        }\n        return _results;\n      })()).join(', ');\n      if (code.indexOf('\\n') >= 0) {\n        return \"[\\n\" + o.indent + code + \"\\n\" + this.tab + \"]\";\n      } else {\n        return \"[\" + code + \"]\";\n      }\n    };\n\n    Arr.prototype.assigns = function(name) {\n      var obj, _i, _len, _ref2;\n      _ref2 = this.objects;\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        obj = _ref2[_i];\n        if (obj.assigns(name)) return true;\n      }\n      return false;\n    };\n\n    return Arr;\n\n  })(Base);\n\n  exports.Class = Class = (function(_super) {\n\n    __extends(Class, _super);\n\n    Class.name = 'Class';\n\n    function Class(variable, parent, body) {\n      this.variable = variable;\n      this.parent = parent;\n      this.body = body != null ? body : new Block;\n      this.boundFuncs = [];\n      this.body.classBody = true;\n    }\n\n    Class.prototype.children = ['variable', 'parent', 'body'];\n\n    Class.prototype.determineName = function() {\n      var decl, tail;\n      if (!this.variable) return null;\n      decl = (tail = last(this.variable.properties)) ? tail instanceof Access && tail.name.value : this.variable.base.value;\n      if (__indexOf.call(STRICT_PROSCRIBED, decl) >= 0) {\n        throw SyntaxError(\"variable name may not be \" + decl);\n      }\n      return decl && (decl = IDENTIFIER.test(decl) && decl);\n    };\n\n    Class.prototype.setContext = function(name) {\n      return this.body.traverseChildren(false, function(node) {\n        if (node.classBody) return false;\n        if (node instanceof Literal && node.value === 'this') {\n          return node.value = name;\n        } else if (node instanceof Code) {\n          node.klass = name;\n          if (node.bound) return node.context = name;\n        }\n      });\n    };\n\n    Class.prototype.addBoundFunctions = function(o) {\n      var bvar, lhs, _i, _len, _ref2, _results;\n      if (this.boundFuncs.length) {\n        _ref2 = this.boundFuncs;\n        _results = [];\n        for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n          bvar = _ref2[_i];\n          lhs = (new Value(new Literal(\"this\"), [new Access(bvar)])).compile(o);\n          _results.push(this.ctor.body.unshift(new Literal(\"\" + lhs + \" = \" + (utility('bind')) + \"(\" + lhs + \", this)\")));\n        }\n        return _results;\n      }\n    };\n\n    Class.prototype.addProperties = function(node, name, o) {\n      var assign, base, exprs, func, props;\n      props = node.base.properties.slice(0);\n      exprs = (function() {\n        var _results;\n        _results = [];\n        while (assign = props.shift()) {\n          if (assign instanceof Assign) {\n            base = assign.variable.base;\n            delete assign.context;\n            func = assign.value;\n            if (base.value === 'constructor') {\n              if (this.ctor) {\n                throw new Error('cannot define more than one constructor in a class');\n              }\n              if (func.bound) {\n                throw new Error('cannot define a constructor as a bound function');\n              }\n              if (func instanceof Code) {\n                assign = this.ctor = func;\n              } else {\n                this.externalCtor = o.scope.freeVariable('class');\n                assign = new Assign(new Literal(this.externalCtor), func);\n              }\n            } else {\n              if (assign.variable[\"this\"]) {\n                func[\"static\"] = true;\n                if (func.bound) func.context = name;\n              } else {\n                assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]);\n                if (func instanceof Code && func.bound) {\n                  this.boundFuncs.push(base);\n                  func.bound = false;\n                }\n              }\n            }\n          }\n          _results.push(assign);\n        }\n        return _results;\n      }).call(this);\n      return compact(exprs);\n    };\n\n    Class.prototype.walkBody = function(name, o) {\n      var _this = this;\n      return this.traverseChildren(false, function(child) {\n        var exps, i, node, _i, _len, _ref2;\n        if (child instanceof Class) return false;\n        if (child instanceof Block) {\n          _ref2 = exps = child.expressions;\n          for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) {\n            node = _ref2[i];\n            if (node instanceof Value && node.isObject(true)) {\n              exps[i] = _this.addProperties(node, name, o);\n            }\n          }\n          return child.expressions = exps = flatten(exps);\n        }\n      });\n    };\n\n    Class.prototype.hoistDirectivePrologue = function() {\n      var expressions, index, node;\n      index = 0;\n      expressions = this.body.expressions;\n      while ((node = expressions[index]) && node instanceof Comment || node instanceof Value && node.isString()) {\n        ++index;\n      }\n      return this.directives = expressions.splice(0, index);\n    };\n\n    Class.prototype.ensureConstructor = function(name) {\n      if (!this.ctor) {\n        this.ctor = new Code;\n        if (this.parent) {\n          this.ctor.body.push(new Literal(\"\" + name + \".__super__.constructor.apply(this, arguments)\"));\n        }\n        if (this.externalCtor) {\n          this.ctor.body.push(new Literal(\"\" + this.externalCtor + \".apply(this, arguments)\"));\n        }\n        this.ctor.body.makeReturn();\n        this.body.expressions.unshift(this.ctor);\n      }\n      this.ctor.ctor = this.ctor.name = name;\n      this.ctor.klass = null;\n      return this.ctor.noReturn = true;\n    };\n\n    Class.prototype.compileNode = function(o) {\n      var call, decl, klass, lname, name, params, _ref2;\n      decl = this.determineName();\n      name = decl || '_Class';\n      if (name.reserved) name = \"_\" + name;\n      lname = new Literal(name);\n      this.hoistDirectivePrologue();\n      this.setContext(name);\n      this.walkBody(name, o);\n      this.ensureConstructor(name);\n      this.body.spaced = true;\n      if (!(this.ctor instanceof Code)) this.body.expressions.unshift(this.ctor);\n      if (decl) {\n        this.body.expressions.unshift(new Assign(new Value(new Literal(name), [new Access(new Literal('name'))]), new Literal(\"'\" + name + \"'\")));\n      }\n      this.body.expressions.push(lname);\n      (_ref2 = this.body.expressions).unshift.apply(_ref2, this.directives);\n      this.addBoundFunctions(o);\n      call = Closure.wrap(this.body);\n      if (this.parent) {\n        this.superClass = new Literal(o.scope.freeVariable('super', false));\n        this.body.expressions.unshift(new Extends(lname, this.superClass));\n        call.args.push(this.parent);\n        params = call.variable.params || call.variable.base.params;\n        params.push(new Param(this.superClass));\n      }\n      klass = new Parens(call, true);\n      if (this.variable) klass = new Assign(this.variable, klass);\n      return klass.compile(o);\n    };\n\n    return Class;\n\n  })(Base);\n\n  exports.Assign = Assign = (function(_super) {\n\n    __extends(Assign, _super);\n\n    Assign.name = 'Assign';\n\n    function Assign(variable, value, context, options) {\n      var forbidden, name, _ref2;\n      this.variable = variable;\n      this.value = value;\n      this.context = context;\n      this.param = options && options.param;\n      this.subpattern = options && options.subpattern;\n      forbidden = (_ref2 = (name = this.variable.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0);\n      if (forbidden && this.context !== 'object') {\n        throw SyntaxError(\"variable name may not be \\\"\" + name + \"\\\"\");\n      }\n    }\n\n    Assign.prototype.children = ['variable', 'value'];\n\n    Assign.prototype.isStatement = function(o) {\n      return (o != null ? o.level : void 0) === LEVEL_TOP && (this.context != null) && __indexOf.call(this.context, \"?\") >= 0;\n    };\n\n    Assign.prototype.assigns = function(name) {\n      return this[this.context === 'object' ? 'value' : 'variable'].assigns(name);\n    };\n\n    Assign.prototype.unfoldSoak = function(o) {\n      return unfoldSoak(o, this, 'variable');\n    };\n\n    Assign.prototype.compileNode = function(o) {\n      var isValue, match, name, val, varBase, _ref2, _ref3, _ref4, _ref5;\n      if (isValue = this.variable instanceof Value) {\n        if (this.variable.isArray() || this.variable.isObject()) {\n          return this.compilePatternMatch(o);\n        }\n        if (this.variable.isSplice()) return this.compileSplice(o);\n        if ((_ref2 = this.context) === '||=' || _ref2 === '&&=' || _ref2 === '?=') {\n          return this.compileConditional(o);\n        }\n      }\n      name = this.variable.compile(o, LEVEL_LIST);\n      if (!this.context) {\n        if (!(varBase = this.variable.unwrapAll()).isAssignable()) {\n          throw SyntaxError(\"\\\"\" + (this.variable.compile(o)) + \"\\\" cannot be assigned.\");\n        }\n        if (!(typeof varBase.hasProperties === \"function\" ? varBase.hasProperties() : void 0)) {\n          if (this.param) {\n            o.scope.add(name, 'var');\n          } else {\n            o.scope.find(name);\n          }\n        }\n      }\n      if (this.value instanceof Code && (match = METHOD_DEF.exec(name))) {\n        if (match[1]) this.value.klass = match[1];\n        this.value.name = (_ref3 = (_ref4 = (_ref5 = match[2]) != null ? _ref5 : match[3]) != null ? _ref4 : match[4]) != null ? _ref3 : match[5];\n      }\n      val = this.value.compile(o, LEVEL_LIST);\n      if (this.context === 'object') return \"\" + name + \": \" + val;\n      val = name + (\" \" + (this.context || '=') + \" \") + val;\n      if (o.level <= LEVEL_LIST) {\n        return val;\n      } else {\n        return \"(\" + val + \")\";\n      }\n    };\n\n    Assign.prototype.compilePatternMatch = function(o) {\n      var acc, assigns, code, i, idx, isObject, ivar, name, obj, objects, olen, ref, rest, splat, top, val, value, vvar, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8;\n      top = o.level === LEVEL_TOP;\n      value = this.value;\n      objects = this.variable.base.objects;\n      if (!(olen = objects.length)) {\n        code = value.compile(o);\n        if (o.level >= LEVEL_OP) {\n          return \"(\" + code + \")\";\n        } else {\n          return code;\n        }\n      }\n      isObject = this.variable.isObject();\n      if (top && olen === 1 && !((obj = objects[0]) instanceof Splat)) {\n        if (obj instanceof Assign) {\n          _ref2 = obj, (_ref3 = _ref2.variable, idx = _ref3.base), obj = _ref2.value;\n        } else {\n          if (obj.base instanceof Parens) {\n            _ref4 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref4[0], idx = _ref4[1];\n          } else {\n            idx = isObject ? obj[\"this\"] ? obj.properties[0].name : obj : new Literal(0);\n          }\n        }\n        acc = IDENTIFIER.test(idx.unwrap().value || 0);\n        value = new Value(value);\n        value.properties.push(new (acc ? Access : Index)(idx));\n        if (_ref5 = obj.unwrap().value, __indexOf.call(RESERVED, _ref5) >= 0) {\n          throw new SyntaxError(\"assignment to a reserved word: \" + (obj.compile(o)) + \" = \" + (value.compile(o)));\n        }\n        return new Assign(obj, value, null, {\n          param: this.param\n        }).compile(o, LEVEL_TOP);\n      }\n      vvar = value.compile(o, LEVEL_LIST);\n      assigns = [];\n      splat = false;\n      if (!IDENTIFIER.test(vvar) || this.variable.assigns(vvar)) {\n        assigns.push(\"\" + (ref = o.scope.freeVariable('ref')) + \" = \" + vvar);\n        vvar = ref;\n      }\n      for (i = _i = 0, _len = objects.length; _i < _len; i = ++_i) {\n        obj = objects[i];\n        idx = i;\n        if (isObject) {\n          if (obj instanceof Assign) {\n            _ref6 = obj, (_ref7 = _ref6.variable, idx = _ref7.base), obj = _ref6.value;\n          } else {\n            if (obj.base instanceof Parens) {\n              _ref8 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref8[0], idx = _ref8[1];\n            } else {\n              idx = obj[\"this\"] ? obj.properties[0].name : obj;\n            }\n          }\n        }\n        if (!splat && obj instanceof Splat) {\n          name = obj.name.unwrap().value;\n          obj = obj.unwrap();\n          val = \"\" + olen + \" <= \" + vvar + \".length ? \" + (utility('slice')) + \".call(\" + vvar + \", \" + i;\n          if (rest = olen - i - 1) {\n            ivar = o.scope.freeVariable('i');\n            val += \", \" + ivar + \" = \" + vvar + \".length - \" + rest + \") : (\" + ivar + \" = \" + i + \", [])\";\n          } else {\n            val += \") : []\";\n          }\n          val = new Literal(val);\n          splat = \"\" + ivar + \"++\";\n        } else {\n          name = obj.unwrap().value;\n          if (obj instanceof Splat) {\n            obj = obj.name.compile(o);\n            throw new SyntaxError(\"multiple splats are disallowed in an assignment: \" + obj + \"...\");\n          }\n          if (typeof idx === 'number') {\n            idx = new Literal(splat || idx);\n            acc = false;\n          } else {\n            acc = isObject && IDENTIFIER.test(idx.unwrap().value || 0);\n          }\n          val = new Value(new Literal(vvar), [new (acc ? Access : Index)(idx)]);\n        }\n        if ((name != null) && __indexOf.call(RESERVED, name) >= 0) {\n          throw new SyntaxError(\"assignment to a reserved word: \" + (obj.compile(o)) + \" = \" + (val.compile(o)));\n        }\n        assigns.push(new Assign(obj, val, null, {\n          param: this.param,\n          subpattern: true\n        }).compile(o, LEVEL_LIST));\n      }\n      if (!(top || this.subpattern)) assigns.push(vvar);\n      code = assigns.join(', ');\n      if (o.level < LEVEL_LIST) {\n        return code;\n      } else {\n        return \"(\" + code + \")\";\n      }\n    };\n\n    Assign.prototype.compileConditional = function(o) {\n      var left, right, _ref2;\n      _ref2 = this.variable.cacheReference(o), left = _ref2[0], right = _ref2[1];\n      if (left.base instanceof Literal && left.base.value !== \"this\" && !o.scope.check(left.base.value)) {\n        throw new Error(\"the variable \\\"\" + left.base.value + \"\\\" can't be assigned with \" + this.context + \" because it has not been defined.\");\n      }\n      if (__indexOf.call(this.context, \"?\") >= 0) o.isExistentialEquals = true;\n      return new Op(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compile(o);\n    };\n\n    Assign.prototype.compileSplice = function(o) {\n      var code, exclusive, from, fromDecl, fromRef, name, to, valDef, valRef, _ref2, _ref3, _ref4;\n      _ref2 = this.variable.properties.pop().range, from = _ref2.from, to = _ref2.to, exclusive = _ref2.exclusive;\n      name = this.variable.compile(o);\n      _ref3 = (from != null ? from.cache(o, LEVEL_OP) : void 0) || ['0', '0'], fromDecl = _ref3[0], fromRef = _ref3[1];\n      if (to) {\n        if ((from != null ? from.isSimpleNumber() : void 0) && to.isSimpleNumber()) {\n          to = +to.compile(o) - +fromRef;\n          if (!exclusive) to += 1;\n        } else {\n          to = to.compile(o, LEVEL_ACCESS) + ' - ' + fromRef;\n          if (!exclusive) to += ' + 1';\n        }\n      } else {\n        to = \"9e9\";\n      }\n      _ref4 = this.value.cache(o, LEVEL_LIST), valDef = _ref4[0], valRef = _ref4[1];\n      code = \"[].splice.apply(\" + name + \", [\" + fromDecl + \", \" + to + \"].concat(\" + valDef + \")), \" + valRef;\n      if (o.level > LEVEL_TOP) {\n        return \"(\" + code + \")\";\n      } else {\n        return code;\n      }\n    };\n\n    return Assign;\n\n  })(Base);\n\n  exports.Code = Code = (function(_super) {\n\n    __extends(Code, _super);\n\n    Code.name = 'Code';\n\n    function Code(params, body, tag) {\n      this.params = params || [];\n      this.body = body || new Block;\n      this.bound = tag === 'boundfunc';\n      if (this.bound) this.context = '_this';\n    }\n\n    Code.prototype.children = ['params', 'body'];\n\n    Code.prototype.isStatement = function() {\n      return !!this.ctor;\n    };\n\n    Code.prototype.jumps = NO;\n\n    Code.prototype.compileNode = function(o) {\n      var code, exprs, i, idt, lit, name, p, param, params, ref, splats, uniqs, val, wasEmpty, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _m, _n, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8;\n      o.scope = new Scope(o.scope, this.body, this);\n      o.scope.shared = del(o, 'sharedScope');\n      o.indent += TAB;\n      delete o.bare;\n      delete o.isExistentialEquals;\n      params = [];\n      exprs = [];\n      _ref2 = this.paramNames();\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        name = _ref2[_i];\n        if (!o.scope.check(name)) o.scope.parameter(name);\n      }\n      _ref3 = this.params;\n      for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {\n        param = _ref3[_j];\n        if (!param.splat) continue;\n        _ref4 = this.params;\n        for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) {\n          p = _ref4[_k];\n          if (p.name.value) o.scope.add(p.name.value, 'var', true);\n        }\n        splats = new Assign(new Value(new Arr((function() {\n          var _l, _len3, _ref5, _results;\n          _ref5 = this.params;\n          _results = [];\n          for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) {\n            p = _ref5[_l];\n            _results.push(p.asReference(o));\n          }\n          return _results;\n        }).call(this))), new Value(new Literal('arguments')));\n        break;\n      }\n      _ref5 = this.params;\n      for (_l = 0, _len3 = _ref5.length; _l < _len3; _l++) {\n        param = _ref5[_l];\n        if (param.isComplex()) {\n          val = ref = param.asReference(o);\n          if (param.value) val = new Op('?', ref, param.value);\n          exprs.push(new Assign(new Value(param.name), val, '=', {\n            param: true\n          }));\n        } else {\n          ref = param;\n          if (param.value) {\n            lit = new Literal(ref.name.value + ' == null');\n            val = new Assign(new Value(param.name), param.value, '=');\n            exprs.push(new If(lit, val));\n          }\n        }\n        if (!splats) params.push(ref);\n      }\n      wasEmpty = this.body.isEmpty();\n      if (splats) exprs.unshift(splats);\n      if (exprs.length) {\n        (_ref6 = this.body.expressions).unshift.apply(_ref6, exprs);\n      }\n      for (i = _m = 0, _len4 = params.length; _m < _len4; i = ++_m) {\n        p = params[i];\n        o.scope.parameter(params[i] = p.compile(o));\n      }\n      uniqs = [];\n      _ref7 = this.paramNames();\n      for (_n = 0, _len5 = _ref7.length; _n < _len5; _n++) {\n        name = _ref7[_n];\n        if (__indexOf.call(uniqs, name) >= 0) {\n          throw SyntaxError(\"multiple parameters named '\" + name + \"'\");\n        }\n        uniqs.push(name);\n      }\n      if (!(wasEmpty || this.noReturn)) this.body.makeReturn();\n      if (this.bound) {\n        if ((_ref8 = o.scope.parent.method) != null ? _ref8.bound : void 0) {\n          this.bound = this.context = o.scope.parent.method.context;\n        } else if (!this[\"static\"]) {\n          o.scope.parent.assign('_this', 'this');\n        }\n      }\n      idt = o.indent;\n      code = 'function';\n      if (this.ctor) code += ' ' + this.name;\n      code += '(' + params.join(', ') + ') {';\n      if (!this.body.isEmpty()) {\n        code += \"\\n\" + (this.body.compileWithDeclarations(o)) + \"\\n\" + this.tab;\n      }\n      code += '}';\n      if (this.ctor) return this.tab + code;\n      if (this.front || (o.level >= LEVEL_ACCESS)) {\n        return \"(\" + code + \")\";\n      } else {\n        return code;\n      }\n    };\n\n    Code.prototype.paramNames = function() {\n      var names, param, _i, _len, _ref2;\n      names = [];\n      _ref2 = this.params;\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        param = _ref2[_i];\n        names.push.apply(names, param.names());\n      }\n      return names;\n    };\n\n    Code.prototype.traverseChildren = function(crossScope, func) {\n      if (crossScope) {\n        return Code.__super__.traverseChildren.call(this, crossScope, func);\n      }\n    };\n\n    return Code;\n\n  })(Base);\n\n  exports.Param = Param = (function(_super) {\n\n    __extends(Param, _super);\n\n    Param.name = 'Param';\n\n    function Param(name, value, splat) {\n      var _ref2;\n      this.name = name;\n      this.value = value;\n      this.splat = splat;\n      if (_ref2 = (name = this.name.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) {\n        throw SyntaxError(\"parameter name \\\"\" + name + \"\\\" is not allowed\");\n      }\n    }\n\n    Param.prototype.children = ['name', 'value'];\n\n    Param.prototype.compile = function(o) {\n      return this.name.compile(o, LEVEL_LIST);\n    };\n\n    Param.prototype.asReference = function(o) {\n      var node;\n      if (this.reference) return this.reference;\n      node = this.name;\n      if (node[\"this\"]) {\n        node = node.properties[0].name;\n        if (node.value.reserved) {\n          node = new Literal(o.scope.freeVariable(node.value));\n        }\n      } else if (node.isComplex()) {\n        node = new Literal(o.scope.freeVariable('arg'));\n      }\n      node = new Value(node);\n      if (this.splat) node = new Splat(node);\n      return this.reference = node;\n    };\n\n    Param.prototype.isComplex = function() {\n      return this.name.isComplex();\n    };\n\n    Param.prototype.names = function(name) {\n      var atParam, names, obj, _i, _len, _ref2;\n      if (name == null) name = this.name;\n      atParam = function(obj) {\n        var value;\n        value = obj.properties[0].name.value;\n        if (value.reserved) {\n          return [];\n        } else {\n          return [value];\n        }\n      };\n      if (name instanceof Literal) return [name.value];\n      if (name instanceof Value) return atParam(name);\n      names = [];\n      _ref2 = name.objects;\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        obj = _ref2[_i];\n        if (obj instanceof Assign) {\n          names.push(obj.variable.base.value);\n        } else if (obj.isArray() || obj.isObject()) {\n          names.push.apply(names, this.names(obj.base));\n        } else if (obj[\"this\"]) {\n          names.push.apply(names, atParam(obj));\n        } else {\n          names.push(obj.base.value);\n        }\n      }\n      return names;\n    };\n\n    return Param;\n\n  })(Base);\n\n  exports.Splat = Splat = (function(_super) {\n\n    __extends(Splat, _super);\n\n    Splat.name = 'Splat';\n\n    Splat.prototype.children = ['name'];\n\n    Splat.prototype.isAssignable = YES;\n\n    function Splat(name) {\n      this.name = name.compile ? name : new Literal(name);\n    }\n\n    Splat.prototype.assigns = function(name) {\n      return this.name.assigns(name);\n    };\n\n    Splat.prototype.compile = function(o) {\n      if (this.index != null) {\n        return this.compileParam(o);\n      } else {\n        return this.name.compile(o);\n      }\n    };\n\n    Splat.prototype.unwrap = function() {\n      return this.name;\n    };\n\n    Splat.compileSplattedArray = function(o, list, apply) {\n      var args, base, code, i, index, node, _i, _len;\n      index = -1;\n      while ((node = list[++index]) && !(node instanceof Splat)) {\n        continue;\n      }\n      if (index >= list.length) return '';\n      if (list.length === 1) {\n        code = list[0].compile(o, LEVEL_LIST);\n        if (apply) return code;\n        return \"\" + (utility('slice')) + \".call(\" + code + \")\";\n      }\n      args = list.slice(index);\n      for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) {\n        node = args[i];\n        code = node.compile(o, LEVEL_LIST);\n        args[i] = node instanceof Splat ? \"\" + (utility('slice')) + \".call(\" + code + \")\" : \"[\" + code + \"]\";\n      }\n      if (index === 0) {\n        return args[0] + (\".concat(\" + (args.slice(1).join(', ')) + \")\");\n      }\n      base = (function() {\n        var _j, _len1, _ref2, _results;\n        _ref2 = list.slice(0, index);\n        _results = [];\n        for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {\n          node = _ref2[_j];\n          _results.push(node.compile(o, LEVEL_LIST));\n        }\n        return _results;\n      })();\n      return \"[\" + (base.join(', ')) + \"].concat(\" + (args.join(', ')) + \")\";\n    };\n\n    return Splat;\n\n  })(Base);\n\n  exports.While = While = (function(_super) {\n\n    __extends(While, _super);\n\n    While.name = 'While';\n\n    function While(condition, options) {\n      this.condition = (options != null ? options.invert : void 0) ? condition.invert() : condition;\n      this.guard = options != null ? options.guard : void 0;\n    }\n\n    While.prototype.children = ['condition', 'guard', 'body'];\n\n    While.prototype.isStatement = YES;\n\n    While.prototype.makeReturn = function(res) {\n      if (res) {\n        return While.__super__.makeReturn.apply(this, arguments);\n      } else {\n        this.returns = !this.jumps({\n          loop: true\n        });\n        return this;\n      }\n    };\n\n    While.prototype.addBody = function(body) {\n      this.body = body;\n      return this;\n    };\n\n    While.prototype.jumps = function() {\n      var expressions, node, _i, _len;\n      expressions = this.body.expressions;\n      if (!expressions.length) return false;\n      for (_i = 0, _len = expressions.length; _i < _len; _i++) {\n        node = expressions[_i];\n        if (node.jumps({\n          loop: true\n        })) return node;\n      }\n      return false;\n    };\n\n    While.prototype.compileNode = function(o) {\n      var body, code, rvar, set;\n      o.indent += TAB;\n      set = '';\n      body = this.body;\n      if (body.isEmpty()) {\n        body = '';\n      } else {\n        if (this.returns) {\n          body.makeReturn(rvar = o.scope.freeVariable('results'));\n          set = \"\" + this.tab + rvar + \" = [];\\n\";\n        }\n        if (this.guard) {\n          if (body.expressions.length > 1) {\n            body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal(\"continue\")));\n          } else {\n            if (this.guard) body = Block.wrap([new If(this.guard, body)]);\n          }\n        }\n        body = \"\\n\" + (body.compile(o, LEVEL_TOP)) + \"\\n\" + this.tab;\n      }\n      code = set + this.tab + (\"while (\" + (this.condition.compile(o, LEVEL_PAREN)) + \") {\" + body + \"}\");\n      if (this.returns) code += \"\\n\" + this.tab + \"return \" + rvar + \";\";\n      return code;\n    };\n\n    return While;\n\n  })(Base);\n\n  exports.Op = Op = (function(_super) {\n    var CONVERSIONS, INVERSIONS;\n\n    __extends(Op, _super);\n\n    Op.name = 'Op';\n\n    function Op(op, first, second, flip) {\n      if (op === 'in') return new In(first, second);\n      if (op === 'do') return this.generateDo(first);\n      if (op === 'new') {\n        if (first instanceof Call && !first[\"do\"] && !first.isNew) {\n          return first.newInstance();\n        }\n        if (first instanceof Code && first.bound || first[\"do\"]) {\n          first = new Parens(first);\n        }\n      }\n      this.operator = CONVERSIONS[op] || op;\n      this.first = first;\n      this.second = second;\n      this.flip = !!flip;\n      return this;\n    }\n\n    CONVERSIONS = {\n      '==': '===',\n      '!=': '!==',\n      'of': 'in'\n    };\n\n    INVERSIONS = {\n      '!==': '===',\n      '===': '!=='\n    };\n\n    Op.prototype.children = ['first', 'second'];\n\n    Op.prototype.isSimpleNumber = NO;\n\n    Op.prototype.isUnary = function() {\n      return !this.second;\n    };\n\n    Op.prototype.isComplex = function() {\n      var _ref2;\n      return !(this.isUnary() && ((_ref2 = this.operator) === '+' || _ref2 === '-')) || this.first.isComplex();\n    };\n\n    Op.prototype.isChainable = function() {\n      var _ref2;\n      return (_ref2 = this.operator) === '<' || _ref2 === '>' || _ref2 === '>=' || _ref2 === '<=' || _ref2 === '===' || _ref2 === '!==';\n    };\n\n    Op.prototype.invert = function() {\n      var allInvertable, curr, fst, op, _ref2;\n      if (this.isChainable() && this.first.isChainable()) {\n        allInvertable = true;\n        curr = this;\n        while (curr && curr.operator) {\n          allInvertable && (allInvertable = curr.operator in INVERSIONS);\n          curr = curr.first;\n        }\n        if (!allInvertable) return new Parens(this).invert();\n        curr = this;\n        while (curr && curr.operator) {\n          curr.invert = !curr.invert;\n          curr.operator = INVERSIONS[curr.operator];\n          curr = curr.first;\n        }\n        return this;\n      } else if (op = INVERSIONS[this.operator]) {\n        this.operator = op;\n        if (this.first.unwrap() instanceof Op) this.first.invert();\n        return this;\n      } else if (this.second) {\n        return new Parens(this).invert();\n      } else if (this.operator === '!' && (fst = this.first.unwrap()) instanceof Op && ((_ref2 = fst.operator) === '!' || _ref2 === 'in' || _ref2 === 'instanceof')) {\n        return fst;\n      } else {\n        return new Op('!', this);\n      }\n    };\n\n    Op.prototype.unfoldSoak = function(o) {\n      var _ref2;\n      return ((_ref2 = this.operator) === '++' || _ref2 === '--' || _ref2 === 'delete') && unfoldSoak(o, this, 'first');\n    };\n\n    Op.prototype.generateDo = function(exp) {\n      var call, func, param, passedParams, ref, _i, _len, _ref2;\n      passedParams = [];\n      func = exp instanceof Assign && (ref = exp.value.unwrap()) instanceof Code ? ref : exp;\n      _ref2 = func.params || [];\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        param = _ref2[_i];\n        if (param.value) {\n          passedParams.push(param.value);\n          delete param.value;\n        } else {\n          passedParams.push(param);\n        }\n      }\n      call = new Call(exp, passedParams);\n      call[\"do\"] = true;\n      return call;\n    };\n\n    Op.prototype.compileNode = function(o) {\n      var code, isChain, _ref2, _ref3;\n      isChain = this.isChainable() && this.first.isChainable();\n      if (!isChain) this.first.front = this.front;\n      if (this.operator === 'delete' && o.scope.check(this.first.unwrapAll().value)) {\n        throw SyntaxError('delete operand may not be argument or var');\n      }\n      if (((_ref2 = this.operator) === '--' || _ref2 === '++') && (_ref3 = this.first.unwrapAll().value, __indexOf.call(STRICT_PROSCRIBED, _ref3) >= 0)) {\n        throw SyntaxError('prefix increment/decrement may not have eval or arguments operand');\n      }\n      if (this.isUnary()) return this.compileUnary(o);\n      if (isChain) return this.compileChain(o);\n      if (this.operator === '?') return this.compileExistence(o);\n      code = this.first.compile(o, LEVEL_OP) + ' ' + this.operator + ' ' + this.second.compile(o, LEVEL_OP);\n      if (o.level <= LEVEL_OP) {\n        return code;\n      } else {\n        return \"(\" + code + \")\";\n      }\n    };\n\n    Op.prototype.compileChain = function(o) {\n      var code, fst, shared, _ref2;\n      _ref2 = this.first.second.cache(o), this.first.second = _ref2[0], shared = _ref2[1];\n      fst = this.first.compile(o, LEVEL_OP);\n      code = \"\" + fst + \" \" + (this.invert ? '&&' : '||') + \" \" + (shared.compile(o)) + \" \" + this.operator + \" \" + (this.second.compile(o, LEVEL_OP));\n      return \"(\" + code + \")\";\n    };\n\n    Op.prototype.compileExistence = function(o) {\n      var fst, ref;\n      if (this.first.isComplex() && o.level > LEVEL_TOP) {\n        ref = new Literal(o.scope.freeVariable('ref'));\n        fst = new Parens(new Assign(ref, this.first));\n      } else {\n        fst = this.first;\n        ref = fst;\n      }\n      return new If(new Existence(fst), ref, {\n        type: 'if'\n      }).addElse(this.second).compile(o);\n    };\n\n    Op.prototype.compileUnary = function(o) {\n      var op, parts, plusMinus;\n      if (o.level >= LEVEL_ACCESS) return (new Parens(this)).compile(o);\n      parts = [op = this.operator];\n      plusMinus = op === '+' || op === '-';\n      if ((op === 'new' || op === 'typeof' || op === 'delete') || plusMinus && this.first instanceof Op && this.first.operator === op) {\n        parts.push(' ');\n      }\n      if ((plusMinus && this.first instanceof Op) || (op === 'new' && this.first.isStatement(o))) {\n        this.first = new Parens(this.first);\n      }\n      parts.push(this.first.compile(o, LEVEL_OP));\n      if (this.flip) parts.reverse();\n      return parts.join('');\n    };\n\n    Op.prototype.toString = function(idt) {\n      return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator);\n    };\n\n    return Op;\n\n  })(Base);\n\n  exports.In = In = (function(_super) {\n\n    __extends(In, _super);\n\n    In.name = 'In';\n\n    function In(object, array) {\n      this.object = object;\n      this.array = array;\n    }\n\n    In.prototype.children = ['object', 'array'];\n\n    In.prototype.invert = NEGATE;\n\n    In.prototype.compileNode = function(o) {\n      var hasSplat, obj, _i, _len, _ref2;\n      if (this.array instanceof Value && this.array.isArray()) {\n        _ref2 = this.array.base.objects;\n        for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n          obj = _ref2[_i];\n          if (!(obj instanceof Splat)) continue;\n          hasSplat = true;\n          break;\n        }\n        if (!hasSplat) return this.compileOrTest(o);\n      }\n      return this.compileLoopTest(o);\n    };\n\n    In.prototype.compileOrTest = function(o) {\n      var cmp, cnj, i, item, ref, sub, tests, _ref2, _ref3;\n      if (this.array.base.objects.length === 0) return \"\" + (!!this.negated);\n      _ref2 = this.object.cache(o, LEVEL_OP), sub = _ref2[0], ref = _ref2[1];\n      _ref3 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref3[0], cnj = _ref3[1];\n      tests = (function() {\n        var _i, _len, _ref4, _results;\n        _ref4 = this.array.base.objects;\n        _results = [];\n        for (i = _i = 0, _len = _ref4.length; _i < _len; i = ++_i) {\n          item = _ref4[i];\n          _results.push((i ? ref : sub) + cmp + item.compile(o, LEVEL_ACCESS));\n        }\n        return _results;\n      }).call(this);\n      tests = tests.join(cnj);\n      if (o.level < LEVEL_OP) {\n        return tests;\n      } else {\n        return \"(\" + tests + \")\";\n      }\n    };\n\n    In.prototype.compileLoopTest = function(o) {\n      var code, ref, sub, _ref2;\n      _ref2 = this.object.cache(o, LEVEL_LIST), sub = _ref2[0], ref = _ref2[1];\n      code = utility('indexOf') + (\".call(\" + (this.array.compile(o, LEVEL_LIST)) + \", \" + ref + \") \") + (this.negated ? '< 0' : '>= 0');\n      if (sub === ref) return code;\n      code = sub + ', ' + code;\n      if (o.level < LEVEL_LIST) {\n        return code;\n      } else {\n        return \"(\" + code + \")\";\n      }\n    };\n\n    In.prototype.toString = function(idt) {\n      return In.__super__.toString.call(this, idt, this.constructor.name + (this.negated ? '!' : ''));\n    };\n\n    return In;\n\n  })(Base);\n\n  exports.Try = Try = (function(_super) {\n\n    __extends(Try, _super);\n\n    Try.name = 'Try';\n\n    function Try(attempt, error, recovery, ensure) {\n      this.attempt = attempt;\n      this.error = error;\n      this.recovery = recovery;\n      this.ensure = ensure;\n    }\n\n    Try.prototype.children = ['attempt', 'recovery', 'ensure'];\n\n    Try.prototype.isStatement = YES;\n\n    Try.prototype.jumps = function(o) {\n      var _ref2;\n      return this.attempt.jumps(o) || ((_ref2 = this.recovery) != null ? _ref2.jumps(o) : void 0);\n    };\n\n    Try.prototype.makeReturn = function(res) {\n      if (this.attempt) this.attempt = this.attempt.makeReturn(res);\n      if (this.recovery) this.recovery = this.recovery.makeReturn(res);\n      return this;\n    };\n\n    Try.prototype.compileNode = function(o) {\n      var catchPart, ensurePart, errorPart, tryPart;\n      o.indent += TAB;\n      errorPart = this.error ? \" (\" + (this.error.compile(o)) + \") \" : ' ';\n      tryPart = this.attempt.compile(o, LEVEL_TOP);\n      catchPart = (function() {\n        var _ref2;\n        if (this.recovery) {\n          if (_ref2 = this.error.value, __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) {\n            throw SyntaxError(\"catch variable may not be \\\"\" + this.error.value + \"\\\"\");\n          }\n          if (!o.scope.check(this.error.value)) {\n            o.scope.add(this.error.value, 'param');\n          }\n          return \" catch\" + errorPart + \"{\\n\" + (this.recovery.compile(o, LEVEL_TOP)) + \"\\n\" + this.tab + \"}\";\n        } else if (!(this.ensure || this.recovery)) {\n          return ' catch (_error) {}';\n        }\n      }).call(this);\n      ensurePart = this.ensure ? \" finally {\\n\" + (this.ensure.compile(o, LEVEL_TOP)) + \"\\n\" + this.tab + \"}\" : '';\n      return \"\" + this.tab + \"try {\\n\" + tryPart + \"\\n\" + this.tab + \"}\" + (catchPart || '') + ensurePart;\n    };\n\n    return Try;\n\n  })(Base);\n\n  exports.Throw = Throw = (function(_super) {\n\n    __extends(Throw, _super);\n\n    Throw.name = 'Throw';\n\n    function Throw(expression) {\n      this.expression = expression;\n    }\n\n    Throw.prototype.children = ['expression'];\n\n    Throw.prototype.isStatement = YES;\n\n    Throw.prototype.jumps = NO;\n\n    Throw.prototype.makeReturn = THIS;\n\n    Throw.prototype.compileNode = function(o) {\n      return this.tab + (\"throw \" + (this.expression.compile(o)) + \";\");\n    };\n\n    return Throw;\n\n  })(Base);\n\n  exports.Existence = Existence = (function(_super) {\n\n    __extends(Existence, _super);\n\n    Existence.name = 'Existence';\n\n    function Existence(expression) {\n      this.expression = expression;\n    }\n\n    Existence.prototype.children = ['expression'];\n\n    Existence.prototype.invert = NEGATE;\n\n    Existence.prototype.compileNode = function(o) {\n      var cmp, cnj, code, _ref2;\n      this.expression.front = this.front;\n      code = this.expression.compile(o, LEVEL_OP);\n      if (IDENTIFIER.test(code) && !o.scope.check(code)) {\n        _ref2 = this.negated ? ['===', '||'] : ['!==', '&&'], cmp = _ref2[0], cnj = _ref2[1];\n        code = \"typeof \" + code + \" \" + cmp + \" \\\"undefined\\\" \" + cnj + \" \" + code + \" \" + cmp + \" null\";\n      } else {\n        code = \"\" + code + \" \" + (this.negated ? '==' : '!=') + \" null\";\n      }\n      if (o.level <= LEVEL_COND) {\n        return code;\n      } else {\n        return \"(\" + code + \")\";\n      }\n    };\n\n    return Existence;\n\n  })(Base);\n\n  exports.Parens = Parens = (function(_super) {\n\n    __extends(Parens, _super);\n\n    Parens.name = 'Parens';\n\n    function Parens(body) {\n      this.body = body;\n    }\n\n    Parens.prototype.children = ['body'];\n\n    Parens.prototype.unwrap = function() {\n      return this.body;\n    };\n\n    Parens.prototype.isComplex = function() {\n      return this.body.isComplex();\n    };\n\n    Parens.prototype.compileNode = function(o) {\n      var bare, code, expr;\n      expr = this.body.unwrap();\n      if (expr instanceof Value && expr.isAtomic()) {\n        expr.front = this.front;\n        return expr.compile(o);\n      }\n      code = expr.compile(o, LEVEL_PAREN);\n      bare = o.level < LEVEL_OP && (expr instanceof Op || expr instanceof Call || (expr instanceof For && expr.returns));\n      if (bare) {\n        return code;\n      } else {\n        return \"(\" + code + \")\";\n      }\n    };\n\n    return Parens;\n\n  })(Base);\n\n  exports.For = For = (function(_super) {\n\n    __extends(For, _super);\n\n    For.name = 'For';\n\n    function For(body, source) {\n      var _ref2;\n      this.source = source.source, this.guard = source.guard, this.step = source.step, this.name = source.name, this.index = source.index;\n      this.body = Block.wrap([body]);\n      this.own = !!source.own;\n      this.object = !!source.object;\n      if (this.object) {\n        _ref2 = [this.index, this.name], this.name = _ref2[0], this.index = _ref2[1];\n      }\n      if (this.index instanceof Value) {\n        throw SyntaxError('index cannot be a pattern matching expression');\n      }\n      this.range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length;\n      this.pattern = this.name instanceof Value;\n      if (this.range && this.index) {\n        throw SyntaxError('indexes do not apply to range loops');\n      }\n      if (this.range && this.pattern) {\n        throw SyntaxError('cannot pattern match over range loops');\n      }\n      this.returns = false;\n    }\n\n    For.prototype.children = ['body', 'source', 'guard', 'step'];\n\n    For.prototype.compileNode = function(o) {\n      var body, defPart, forPart, forVarPart, guardPart, idt1, index, ivar, kvar, kvarAssign, lastJumps, lvar, name, namePart, ref, resultPart, returnResult, rvar, scope, source, stepPart, stepvar, svar, varPart, _ref2;\n      body = Block.wrap([this.body]);\n      lastJumps = (_ref2 = last(body.expressions)) != null ? _ref2.jumps() : void 0;\n      if (lastJumps && lastJumps instanceof Return) this.returns = false;\n      source = this.range ? this.source.base : this.source;\n      scope = o.scope;\n      name = this.name && this.name.compile(o, LEVEL_LIST);\n      index = this.index && this.index.compile(o, LEVEL_LIST);\n      if (name && !this.pattern) {\n        scope.find(name, {\n          immediate: true\n        });\n      }\n      if (index) {\n        scope.find(index, {\n          immediate: true\n        });\n      }\n      if (this.returns) rvar = scope.freeVariable('results');\n      ivar = (this.object && index) || scope.freeVariable('i');\n      kvar = (this.range && name) || index || ivar;\n      kvarAssign = kvar !== ivar ? \"\" + kvar + \" = \" : \"\";\n      if (this.step && !this.range) stepvar = scope.freeVariable(\"step\");\n      if (this.pattern) name = ivar;\n      varPart = '';\n      guardPart = '';\n      defPart = '';\n      idt1 = this.tab + TAB;\n      if (this.range) {\n        forPart = source.compile(merge(o, {\n          index: ivar,\n          name: name,\n          step: this.step\n        }));\n      } else {\n        svar = this.source.compile(o, LEVEL_LIST);\n        if ((name || this.own) && !IDENTIFIER.test(svar)) {\n          defPart = \"\" + this.tab + (ref = scope.freeVariable('ref')) + \" = \" + svar + \";\\n\";\n          svar = ref;\n        }\n        if (name && !this.pattern) {\n          namePart = \"\" + name + \" = \" + svar + \"[\" + kvar + \"]\";\n        }\n        if (!this.object) {\n          lvar = scope.freeVariable('len');\n          forVarPart = \"\" + kvarAssign + ivar + \" = 0, \" + lvar + \" = \" + svar + \".length\";\n          if (this.step) {\n            forVarPart += \", \" + stepvar + \" = \" + (this.step.compile(o, LEVEL_OP));\n          }\n          stepPart = \"\" + kvarAssign + (this.step ? \"\" + ivar + \" += \" + stepvar : (kvar !== ivar ? \"++\" + ivar : \"\" + ivar + \"++\"));\n          forPart = \"\" + forVarPart + \"; \" + ivar + \" < \" + lvar + \"; \" + stepPart;\n        }\n      }\n      if (this.returns) {\n        resultPart = \"\" + this.tab + rvar + \" = [];\\n\";\n        returnResult = \"\\n\" + this.tab + \"return \" + rvar + \";\";\n        body.makeReturn(rvar);\n      }\n      if (this.guard) {\n        if (body.expressions.length > 1) {\n          body.expressions.unshift(new If((new Parens(this.guard)).invert(), new Literal(\"continue\")));\n        } else {\n          if (this.guard) body = Block.wrap([new If(this.guard, body)]);\n        }\n      }\n      if (this.pattern) {\n        body.expressions.unshift(new Assign(this.name, new Literal(\"\" + svar + \"[\" + kvar + \"]\")));\n      }\n      defPart += this.pluckDirectCall(o, body);\n      if (namePart) varPart = \"\\n\" + idt1 + namePart + \";\";\n      if (this.object) {\n        forPart = \"\" + kvar + \" in \" + svar;\n        if (this.own) {\n          guardPart = \"\\n\" + idt1 + \"if (!\" + (utility('hasProp')) + \".call(\" + svar + \", \" + kvar + \")) continue;\";\n        }\n      }\n      body = body.compile(merge(o, {\n        indent: idt1\n      }), LEVEL_TOP);\n      if (body) body = '\\n' + body + '\\n';\n      return \"\" + defPart + (resultPart || '') + this.tab + \"for (\" + forPart + \") {\" + guardPart + varPart + body + this.tab + \"}\" + (returnResult || '');\n    };\n\n    For.prototype.pluckDirectCall = function(o, body) {\n      var base, defs, expr, fn, idx, ref, val, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7;\n      defs = '';\n      _ref2 = body.expressions;\n      for (idx = _i = 0, _len = _ref2.length; _i < _len; idx = ++_i) {\n        expr = _ref2[idx];\n        expr = expr.unwrapAll();\n        if (!(expr instanceof Call)) continue;\n        val = expr.variable.unwrapAll();\n        if (!((val instanceof Code) || (val instanceof Value && ((_ref3 = val.base) != null ? _ref3.unwrapAll() : void 0) instanceof Code && val.properties.length === 1 && ((_ref4 = (_ref5 = val.properties[0].name) != null ? _ref5.value : void 0) === 'call' || _ref4 === 'apply')))) {\n          continue;\n        }\n        fn = ((_ref6 = val.base) != null ? _ref6.unwrapAll() : void 0) || val;\n        ref = new Literal(o.scope.freeVariable('fn'));\n        base = new Value(ref);\n        if (val.base) _ref7 = [base, val], val.base = _ref7[0], base = _ref7[1];\n        body.expressions[idx] = new Call(base, expr.args);\n        defs += this.tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\\n';\n      }\n      return defs;\n    };\n\n    return For;\n\n  })(While);\n\n  exports.Switch = Switch = (function(_super) {\n\n    __extends(Switch, _super);\n\n    Switch.name = 'Switch';\n\n    function Switch(subject, cases, otherwise) {\n      this.subject = subject;\n      this.cases = cases;\n      this.otherwise = otherwise;\n    }\n\n    Switch.prototype.children = ['subject', 'cases', 'otherwise'];\n\n    Switch.prototype.isStatement = YES;\n\n    Switch.prototype.jumps = function(o) {\n      var block, conds, _i, _len, _ref2, _ref3, _ref4;\n      if (o == null) {\n        o = {\n          block: true\n        };\n      }\n      _ref2 = this.cases;\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        _ref3 = _ref2[_i], conds = _ref3[0], block = _ref3[1];\n        if (block.jumps(o)) return block;\n      }\n      return (_ref4 = this.otherwise) != null ? _ref4.jumps(o) : void 0;\n    };\n\n    Switch.prototype.makeReturn = function(res) {\n      var pair, _i, _len, _ref2, _ref3;\n      _ref2 = this.cases;\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        pair = _ref2[_i];\n        pair[1].makeReturn(res);\n      }\n      if (res) {\n        this.otherwise || (this.otherwise = new Block([new Literal('void 0')]));\n      }\n      if ((_ref3 = this.otherwise) != null) _ref3.makeReturn(res);\n      return this;\n    };\n\n    Switch.prototype.compileNode = function(o) {\n      var block, body, code, cond, conditions, expr, i, idt1, idt2, _i, _j, _len, _len1, _ref2, _ref3, _ref4, _ref5;\n      idt1 = o.indent + TAB;\n      idt2 = o.indent = idt1 + TAB;\n      code = this.tab + (\"switch (\" + (((_ref2 = this.subject) != null ? _ref2.compile(o, LEVEL_PAREN) : void 0) || false) + \") {\\n\");\n      _ref3 = this.cases;\n      for (i = _i = 0, _len = _ref3.length; _i < _len; i = ++_i) {\n        _ref4 = _ref3[i], conditions = _ref4[0], block = _ref4[1];\n        _ref5 = flatten([conditions]);\n        for (_j = 0, _len1 = _ref5.length; _j < _len1; _j++) {\n          cond = _ref5[_j];\n          if (!this.subject) cond = cond.invert();\n          code += idt1 + (\"case \" + (cond.compile(o, LEVEL_PAREN)) + \":\\n\");\n        }\n        if (body = block.compile(o, LEVEL_TOP)) code += body + '\\n';\n        if (i === this.cases.length - 1 && !this.otherwise) break;\n        expr = this.lastNonComment(block.expressions);\n        if (expr instanceof Return || (expr instanceof Literal && expr.jumps() && expr.value !== 'debugger')) {\n          continue;\n        }\n        code += idt2 + 'break;\\n';\n      }\n      if (this.otherwise && this.otherwise.expressions.length) {\n        code += idt1 + (\"default:\\n\" + (this.otherwise.compile(o, LEVEL_TOP)) + \"\\n\");\n      }\n      return code + this.tab + '}';\n    };\n\n    return Switch;\n\n  })(Base);\n\n  exports.If = If = (function(_super) {\n\n    __extends(If, _super);\n\n    If.name = 'If';\n\n    function If(condition, body, options) {\n      this.body = body;\n      if (options == null) options = {};\n      this.condition = options.type === 'unless' ? condition.invert() : condition;\n      this.elseBody = null;\n      this.isChain = false;\n      this.soak = options.soak;\n    }\n\n    If.prototype.children = ['condition', 'body', 'elseBody'];\n\n    If.prototype.bodyNode = function() {\n      var _ref2;\n      return (_ref2 = this.body) != null ? _ref2.unwrap() : void 0;\n    };\n\n    If.prototype.elseBodyNode = function() {\n      var _ref2;\n      return (_ref2 = this.elseBody) != null ? _ref2.unwrap() : void 0;\n    };\n\n    If.prototype.addElse = function(elseBody) {\n      if (this.isChain) {\n        this.elseBodyNode().addElse(elseBody);\n      } else {\n        this.isChain = elseBody instanceof If;\n        this.elseBody = this.ensureBlock(elseBody);\n      }\n      return this;\n    };\n\n    If.prototype.isStatement = function(o) {\n      var _ref2;\n      return (o != null ? o.level : void 0) === LEVEL_TOP || this.bodyNode().isStatement(o) || ((_ref2 = this.elseBodyNode()) != null ? _ref2.isStatement(o) : void 0);\n    };\n\n    If.prototype.jumps = function(o) {\n      var _ref2;\n      return this.body.jumps(o) || ((_ref2 = this.elseBody) != null ? _ref2.jumps(o) : void 0);\n    };\n\n    If.prototype.compileNode = function(o) {\n      if (this.isStatement(o)) {\n        return this.compileStatement(o);\n      } else {\n        return this.compileExpression(o);\n      }\n    };\n\n    If.prototype.makeReturn = function(res) {\n      if (res) {\n        this.elseBody || (this.elseBody = new Block([new Literal('void 0')]));\n      }\n      this.body && (this.body = new Block([this.body.makeReturn(res)]));\n      this.elseBody && (this.elseBody = new Block([this.elseBody.makeReturn(res)]));\n      return this;\n    };\n\n    If.prototype.ensureBlock = function(node) {\n      if (node instanceof Block) {\n        return node;\n      } else {\n        return new Block([node]);\n      }\n    };\n\n    If.prototype.compileStatement = function(o) {\n      var body, bodyc, child, cond, exeq, ifPart, _ref2;\n      child = del(o, 'chainChild');\n      exeq = del(o, 'isExistentialEquals');\n      if (exeq) {\n        return new If(this.condition.invert(), this.elseBodyNode(), {\n          type: 'if'\n        }).compile(o);\n      }\n      cond = this.condition.compile(o, LEVEL_PAREN);\n      o.indent += TAB;\n      body = this.ensureBlock(this.body);\n      bodyc = body.compile(o);\n      if (1 === ((_ref2 = body.expressions) != null ? _ref2.length : void 0) && !this.elseBody && !child && bodyc && cond && -1 === (bodyc.indexOf('\\n')) && 80 > cond.length + bodyc.length) {\n        return \"\" + this.tab + \"if (\" + cond + \") \" + (bodyc.replace(/^\\s+/, ''));\n      }\n      if (bodyc) bodyc = \"\\n\" + bodyc + \"\\n\" + this.tab;\n      ifPart = \"if (\" + cond + \") {\" + bodyc + \"}\";\n      if (!child) ifPart = this.tab + ifPart;\n      if (!this.elseBody) return ifPart;\n      return ifPart + ' else ' + (this.isChain ? (o.indent = this.tab, o.chainChild = true, this.elseBody.unwrap().compile(o, LEVEL_TOP)) : \"{\\n\" + (this.elseBody.compile(o, LEVEL_TOP)) + \"\\n\" + this.tab + \"}\");\n    };\n\n    If.prototype.compileExpression = function(o) {\n      var alt, body, code, cond;\n      cond = this.condition.compile(o, LEVEL_COND);\n      body = this.bodyNode().compile(o, LEVEL_LIST);\n      alt = this.elseBodyNode() ? this.elseBodyNode().compile(o, LEVEL_LIST) : 'void 0';\n      code = \"\" + cond + \" ? \" + body + \" : \" + alt;\n      if (o.level >= LEVEL_COND) {\n        return \"(\" + code + \")\";\n      } else {\n        return code;\n      }\n    };\n\n    If.prototype.unfoldSoak = function() {\n      return this.soak && this;\n    };\n\n    return If;\n\n  })(Base);\n\n  Closure = {\n    wrap: function(expressions, statement, noReturn) {\n      var args, call, func, mentionsArgs, meth;\n      if (expressions.jumps()) return expressions;\n      func = new Code([], Block.wrap([expressions]));\n      args = [];\n      if ((mentionsArgs = expressions.contains(this.literalArgs)) || expressions.contains(this.literalThis)) {\n        meth = new Literal(mentionsArgs ? 'apply' : 'call');\n        args = [new Literal('this')];\n        if (mentionsArgs) args.push(new Literal('arguments'));\n        func = new Value(func, [new Access(meth)]);\n      }\n      func.noReturn = noReturn;\n      call = new Call(func, args);\n      if (statement) {\n        return Block.wrap([call]);\n      } else {\n        return call;\n      }\n    },\n    literalArgs: function(node) {\n      return node instanceof Literal && node.value === 'arguments' && !node.asKey;\n    },\n    literalThis: function(node) {\n      return (node instanceof Literal && node.value === 'this' && !node.asKey) || (node instanceof Code && node.bound);\n    }\n  };\n\n  unfoldSoak = function(o, parent, name) {\n    var ifn;\n    if (!(ifn = parent[name].unfoldSoak(o))) return;\n    parent[name] = ifn.body;\n    ifn.body = new Value(parent);\n    return ifn;\n  };\n\n  UTILITIES = {\n    \"extends\": function() {\n      return \"function(child, parent) { for (var key in parent) { if (\" + (utility('hasProp')) + \".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }\";\n    },\n    bind: function() {\n      return 'function(fn, me){ return function(){ return fn.apply(me, arguments); }; }';\n    },\n    indexOf: function() {\n      return \"[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }\";\n    },\n    hasProp: function() {\n      return '{}.hasOwnProperty';\n    },\n    slice: function() {\n      return '[].slice';\n    }\n  };\n\n  LEVEL_TOP = 1;\n\n  LEVEL_PAREN = 2;\n\n  LEVEL_LIST = 3;\n\n  LEVEL_COND = 4;\n\n  LEVEL_OP = 5;\n\n  LEVEL_ACCESS = 6;\n\n  TAB = '  ';\n\n  IDENTIFIER_STR = \"[$A-Za-z_\\\\x7f-\\\\uffff][$\\\\w\\\\x7f-\\\\uffff]*\";\n\n  IDENTIFIER = RegExp(\"^\" + IDENTIFIER_STR + \"$\");\n\n  SIMPLENUM = /^[+-]?\\d+$/;\n\n  METHOD_DEF = RegExp(\"^(?:(\" + IDENTIFIER_STR + \")\\\\.prototype(?:\\\\.(\" + IDENTIFIER_STR + \")|\\\\[(\\\"(?:[^\\\\\\\\\\\"\\\\r\\\\n]|\\\\\\\\.)*\\\"|'(?:[^\\\\\\\\'\\\\r\\\\n]|\\\\\\\\.)*')\\\\]|\\\\[(0x[\\\\da-fA-F]+|\\\\d*\\\\.?\\\\d+(?:[eE][+-]?\\\\d+)?)\\\\]))|(\" + IDENTIFIER_STR + \")$\");\n\n  IS_STRING = /^['\"]/;\n\n  utility = function(name) {\n    var ref;\n    ref = \"__\" + name;\n    Scope.root.assign(ref, UTILITIES[name]());\n    return ref;\n  };\n\n  multident = function(code, tab) {\n    code = code.replace(/\\n/g, '$&' + tab);\n    return code.replace(/\\s+$/, '');\n  };\n\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coffee/parser.js",
    "content": "/**\n * Copyright (c) 2011 Jeremy Ashkenas\n * \n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n * \n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\ndefine(function(require, exports, module) {\n/* Jison generated parser */\n\nundefined\nvar parser = {trace: function trace() { },\nyy: {},\nsymbols_: {\"error\":2,\"Root\":3,\"Body\":4,\"Block\":5,\"TERMINATOR\":6,\"Line\":7,\"Expression\":8,\"Statement\":9,\"Return\":10,\"Comment\":11,\"STATEMENT\":12,\"Value\":13,\"Invocation\":14,\"Code\":15,\"Operation\":16,\"Assign\":17,\"If\":18,\"Try\":19,\"While\":20,\"For\":21,\"Switch\":22,\"Class\":23,\"Throw\":24,\"INDENT\":25,\"OUTDENT\":26,\"Identifier\":27,\"IDENTIFIER\":28,\"AlphaNumeric\":29,\"NUMBER\":30,\"STRING\":31,\"Literal\":32,\"JS\":33,\"REGEX\":34,\"DEBUGGER\":35,\"BOOL\":36,\"Assignable\":37,\"=\":38,\"AssignObj\":39,\"ObjAssignable\":40,\":\":41,\"ThisProperty\":42,\"RETURN\":43,\"HERECOMMENT\":44,\"PARAM_START\":45,\"ParamList\":46,\"PARAM_END\":47,\"FuncGlyph\":48,\"->\":49,\"=>\":50,\"OptComma\":51,\",\":52,\"Param\":53,\"ParamVar\":54,\"...\":55,\"Array\":56,\"Object\":57,\"Splat\":58,\"SimpleAssignable\":59,\"Accessor\":60,\"Parenthetical\":61,\"Range\":62,\"This\":63,\".\":64,\"?.\":65,\"::\":66,\"Index\":67,\"INDEX_START\":68,\"IndexValue\":69,\"INDEX_END\":70,\"INDEX_SOAK\":71,\"Slice\":72,\"{\":73,\"AssignList\":74,\"}\":75,\"CLASS\":76,\"EXTENDS\":77,\"OptFuncExist\":78,\"Arguments\":79,\"SUPER\":80,\"FUNC_EXIST\":81,\"CALL_START\":82,\"CALL_END\":83,\"ArgList\":84,\"THIS\":85,\"@\":86,\"[\":87,\"]\":88,\"RangeDots\":89,\"..\":90,\"Arg\":91,\"SimpleArgs\":92,\"TRY\":93,\"Catch\":94,\"FINALLY\":95,\"CATCH\":96,\"THROW\":97,\"(\":98,\")\":99,\"WhileSource\":100,\"WHILE\":101,\"WHEN\":102,\"UNTIL\":103,\"Loop\":104,\"LOOP\":105,\"ForBody\":106,\"FOR\":107,\"ForStart\":108,\"ForSource\":109,\"ForVariables\":110,\"OWN\":111,\"ForValue\":112,\"FORIN\":113,\"FOROF\":114,\"BY\":115,\"SWITCH\":116,\"Whens\":117,\"ELSE\":118,\"When\":119,\"LEADING_WHEN\":120,\"IfBlock\":121,\"IF\":122,\"POST_IF\":123,\"UNARY\":124,\"-\":125,\"+\":126,\"--\":127,\"++\":128,\"?\":129,\"MATH\":130,\"SHIFT\":131,\"COMPARE\":132,\"LOGIC\":133,\"RELATION\":134,\"COMPOUND_ASSIGN\":135,\"$accept\":0,\"$end\":1},\nterminals_: {2:\"error\",6:\"TERMINATOR\",12:\"STATEMENT\",25:\"INDENT\",26:\"OUTDENT\",28:\"IDENTIFIER\",30:\"NUMBER\",31:\"STRING\",33:\"JS\",34:\"REGEX\",35:\"DEBUGGER\",36:\"BOOL\",38:\"=\",41:\":\",43:\"RETURN\",44:\"HERECOMMENT\",45:\"PARAM_START\",47:\"PARAM_END\",49:\"->\",50:\"=>\",52:\",\",55:\"...\",64:\".\",65:\"?.\",66:\"::\",68:\"INDEX_START\",70:\"INDEX_END\",71:\"INDEX_SOAK\",73:\"{\",75:\"}\",76:\"CLASS\",77:\"EXTENDS\",80:\"SUPER\",81:\"FUNC_EXIST\",82:\"CALL_START\",83:\"CALL_END\",85:\"THIS\",86:\"@\",87:\"[\",88:\"]\",90:\"..\",93:\"TRY\",95:\"FINALLY\",96:\"CATCH\",97:\"THROW\",98:\"(\",99:\")\",101:\"WHILE\",102:\"WHEN\",103:\"UNTIL\",105:\"LOOP\",107:\"FOR\",111:\"OWN\",113:\"FORIN\",114:\"FOROF\",115:\"BY\",116:\"SWITCH\",118:\"ELSE\",120:\"LEADING_WHEN\",122:\"IF\",123:\"POST_IF\",124:\"UNARY\",125:\"-\",126:\"+\",127:\"--\",128:\"++\",129:\"?\",130:\"MATH\",131:\"SHIFT\",132:\"COMPARE\",133:\"LOGIC\",134:\"RELATION\",135:\"COMPOUND_ASSIGN\"},\nproductions_: [0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[32,1],[17,3],[17,4],[17,5],[39,1],[39,3],[39,5],[39,1],[40,1],[40,1],[40,1],[10,2],[10,1],[11,1],[15,5],[15,2],[48,1],[48,1],[51,0],[51,1],[46,0],[46,1],[46,3],[53,1],[53,2],[53,3],[54,1],[54,1],[54,1],[54,1],[58,2],[59,1],[59,2],[59,2],[59,1],[37,1],[37,1],[37,1],[13,1],[13,1],[13,1],[13,1],[13,1],[60,2],[60,2],[60,2],[60,1],[60,1],[67,3],[67,2],[69,1],[69,1],[57,4],[74,0],[74,1],[74,3],[74,4],[74,6],[23,1],[23,2],[23,3],[23,4],[23,2],[23,3],[23,4],[23,5],[14,3],[14,3],[14,1],[14,2],[78,0],[78,1],[79,2],[79,4],[63,1],[63,1],[42,2],[56,2],[56,4],[89,1],[89,1],[62,5],[72,3],[72,2],[72,2],[72,1],[84,1],[84,3],[84,4],[84,4],[84,6],[91,1],[91,1],[92,1],[92,3],[19,2],[19,3],[19,4],[19,5],[94,3],[24,2],[61,3],[61,5],[100,2],[100,4],[100,2],[100,4],[20,2],[20,2],[20,2],[20,1],[104,2],[104,2],[21,2],[21,2],[21,2],[106,2],[106,2],[108,2],[108,3],[112,1],[112,1],[112,1],[110,1],[110,3],[109,2],[109,2],[109,4],[109,4],[109,4],[109,6],[109,6],[22,5],[22,7],[22,4],[22,6],[117,1],[117,2],[119,3],[119,4],[121,3],[121,5],[18,1],[18,3],[18,3],[18,3],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,5],[16,3]],\nperformAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {\n\nvar $0 = $$.length - 1;\nswitch (yystate) {\ncase 1:return this.$ = new yy.Block;\nbreak;\ncase 2:return this.$ = $$[$0];\nbreak;\ncase 3:return this.$ = $$[$0-1];\nbreak;\ncase 4:this.$ = yy.Block.wrap([$$[$0]]);\nbreak;\ncase 5:this.$ = $$[$0-2].push($$[$0]);\nbreak;\ncase 6:this.$ = $$[$0-1];\nbreak;\ncase 7:this.$ = $$[$0];\nbreak;\ncase 8:this.$ = $$[$0];\nbreak;\ncase 9:this.$ = $$[$0];\nbreak;\ncase 10:this.$ = $$[$0];\nbreak;\ncase 11:this.$ = new yy.Literal($$[$0]);\nbreak;\ncase 12:this.$ = $$[$0];\nbreak;\ncase 13:this.$ = $$[$0];\nbreak;\ncase 14:this.$ = $$[$0];\nbreak;\ncase 15:this.$ = $$[$0];\nbreak;\ncase 16:this.$ = $$[$0];\nbreak;\ncase 17:this.$ = $$[$0];\nbreak;\ncase 18:this.$ = $$[$0];\nbreak;\ncase 19:this.$ = $$[$0];\nbreak;\ncase 20:this.$ = $$[$0];\nbreak;\ncase 21:this.$ = $$[$0];\nbreak;\ncase 22:this.$ = $$[$0];\nbreak;\ncase 23:this.$ = $$[$0];\nbreak;\ncase 24:this.$ = new yy.Block;\nbreak;\ncase 25:this.$ = $$[$0-1];\nbreak;\ncase 26:this.$ = new yy.Literal($$[$0]);\nbreak;\ncase 27:this.$ = new yy.Literal($$[$0]);\nbreak;\ncase 28:this.$ = new yy.Literal($$[$0]);\nbreak;\ncase 29:this.$ = $$[$0];\nbreak;\ncase 30:this.$ = new yy.Literal($$[$0]);\nbreak;\ncase 31:this.$ = new yy.Literal($$[$0]);\nbreak;\ncase 32:this.$ = new yy.Literal($$[$0]);\nbreak;\ncase 33:this.$ = (function () {\n        var val;\n        val = new yy.Literal($$[$0]);\n        if ($$[$0] === 'undefined') val.isUndefined = true;\n        return val;\n      }());\nbreak;\ncase 34:this.$ = new yy.Assign($$[$0-2], $$[$0]);\nbreak;\ncase 35:this.$ = new yy.Assign($$[$0-3], $$[$0]);\nbreak;\ncase 36:this.$ = new yy.Assign($$[$0-4], $$[$0-1]);\nbreak;\ncase 37:this.$ = new yy.Value($$[$0]);\nbreak;\ncase 38:this.$ = new yy.Assign(new yy.Value($$[$0-2]), $$[$0], 'object');\nbreak;\ncase 39:this.$ = new yy.Assign(new yy.Value($$[$0-4]), $$[$0-1], 'object');\nbreak;\ncase 40:this.$ = $$[$0];\nbreak;\ncase 41:this.$ = $$[$0];\nbreak;\ncase 42:this.$ = $$[$0];\nbreak;\ncase 43:this.$ = $$[$0];\nbreak;\ncase 44:this.$ = new yy.Return($$[$0]);\nbreak;\ncase 45:this.$ = new yy.Return;\nbreak;\ncase 46:this.$ = new yy.Comment($$[$0]);\nbreak;\ncase 47:this.$ = new yy.Code($$[$0-3], $$[$0], $$[$0-1]);\nbreak;\ncase 48:this.$ = new yy.Code([], $$[$0], $$[$0-1]);\nbreak;\ncase 49:this.$ = 'func';\nbreak;\ncase 50:this.$ = 'boundfunc';\nbreak;\ncase 51:this.$ = $$[$0];\nbreak;\ncase 52:this.$ = $$[$0];\nbreak;\ncase 53:this.$ = [];\nbreak;\ncase 54:this.$ = [$$[$0]];\nbreak;\ncase 55:this.$ = $$[$0-2].concat($$[$0]);\nbreak;\ncase 56:this.$ = new yy.Param($$[$0]);\nbreak;\ncase 57:this.$ = new yy.Param($$[$0-1], null, true);\nbreak;\ncase 58:this.$ = new yy.Param($$[$0-2], $$[$0]);\nbreak;\ncase 59:this.$ = $$[$0];\nbreak;\ncase 60:this.$ = $$[$0];\nbreak;\ncase 61:this.$ = $$[$0];\nbreak;\ncase 62:this.$ = $$[$0];\nbreak;\ncase 63:this.$ = new yy.Splat($$[$0-1]);\nbreak;\ncase 64:this.$ = new yy.Value($$[$0]);\nbreak;\ncase 65:this.$ = $$[$0-1].add($$[$0]);\nbreak;\ncase 66:this.$ = new yy.Value($$[$0-1], [].concat($$[$0]));\nbreak;\ncase 67:this.$ = $$[$0];\nbreak;\ncase 68:this.$ = $$[$0];\nbreak;\ncase 69:this.$ = new yy.Value($$[$0]);\nbreak;\ncase 70:this.$ = new yy.Value($$[$0]);\nbreak;\ncase 71:this.$ = $$[$0];\nbreak;\ncase 72:this.$ = new yy.Value($$[$0]);\nbreak;\ncase 73:this.$ = new yy.Value($$[$0]);\nbreak;\ncase 74:this.$ = new yy.Value($$[$0]);\nbreak;\ncase 75:this.$ = $$[$0];\nbreak;\ncase 76:this.$ = new yy.Access($$[$0]);\nbreak;\ncase 77:this.$ = new yy.Access($$[$0], 'soak');\nbreak;\ncase 78:this.$ = [new yy.Access(new yy.Literal('prototype')), new yy.Access($$[$0])];\nbreak;\ncase 79:this.$ = new yy.Access(new yy.Literal('prototype'));\nbreak;\ncase 80:this.$ = $$[$0];\nbreak;\ncase 81:this.$ = $$[$0-1];\nbreak;\ncase 82:this.$ = yy.extend($$[$0], {\n          soak: true\n        });\nbreak;\ncase 83:this.$ = new yy.Index($$[$0]);\nbreak;\ncase 84:this.$ = new yy.Slice($$[$0]);\nbreak;\ncase 85:this.$ = new yy.Obj($$[$0-2], $$[$0-3].generated);\nbreak;\ncase 86:this.$ = [];\nbreak;\ncase 87:this.$ = [$$[$0]];\nbreak;\ncase 88:this.$ = $$[$0-2].concat($$[$0]);\nbreak;\ncase 89:this.$ = $$[$0-3].concat($$[$0]);\nbreak;\ncase 90:this.$ = $$[$0-5].concat($$[$0-2]);\nbreak;\ncase 91:this.$ = new yy.Class;\nbreak;\ncase 92:this.$ = new yy.Class(null, null, $$[$0]);\nbreak;\ncase 93:this.$ = new yy.Class(null, $$[$0]);\nbreak;\ncase 94:this.$ = new yy.Class(null, $$[$0-1], $$[$0]);\nbreak;\ncase 95:this.$ = new yy.Class($$[$0]);\nbreak;\ncase 96:this.$ = new yy.Class($$[$0-1], null, $$[$0]);\nbreak;\ncase 97:this.$ = new yy.Class($$[$0-2], $$[$0]);\nbreak;\ncase 98:this.$ = new yy.Class($$[$0-3], $$[$0-1], $$[$0]);\nbreak;\ncase 99:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]);\nbreak;\ncase 100:this.$ = new yy.Call($$[$0-2], $$[$0], $$[$0-1]);\nbreak;\ncase 101:this.$ = new yy.Call('super', [new yy.Splat(new yy.Literal('arguments'))]);\nbreak;\ncase 102:this.$ = new yy.Call('super', $$[$0]);\nbreak;\ncase 103:this.$ = false;\nbreak;\ncase 104:this.$ = true;\nbreak;\ncase 105:this.$ = [];\nbreak;\ncase 106:this.$ = $$[$0-2];\nbreak;\ncase 107:this.$ = new yy.Value(new yy.Literal('this'));\nbreak;\ncase 108:this.$ = new yy.Value(new yy.Literal('this'));\nbreak;\ncase 109:this.$ = new yy.Value(new yy.Literal('this'), [new yy.Access($$[$0])], 'this');\nbreak;\ncase 110:this.$ = new yy.Arr([]);\nbreak;\ncase 111:this.$ = new yy.Arr($$[$0-2]);\nbreak;\ncase 112:this.$ = 'inclusive';\nbreak;\ncase 113:this.$ = 'exclusive';\nbreak;\ncase 114:this.$ = new yy.Range($$[$0-3], $$[$0-1], $$[$0-2]);\nbreak;\ncase 115:this.$ = new yy.Range($$[$0-2], $$[$0], $$[$0-1]);\nbreak;\ncase 116:this.$ = new yy.Range($$[$0-1], null, $$[$0]);\nbreak;\ncase 117:this.$ = new yy.Range(null, $$[$0], $$[$0-1]);\nbreak;\ncase 118:this.$ = new yy.Range(null, null, $$[$0]);\nbreak;\ncase 119:this.$ = [$$[$0]];\nbreak;\ncase 120:this.$ = $$[$0-2].concat($$[$0]);\nbreak;\ncase 121:this.$ = $$[$0-3].concat($$[$0]);\nbreak;\ncase 122:this.$ = $$[$0-2];\nbreak;\ncase 123:this.$ = $$[$0-5].concat($$[$0-2]);\nbreak;\ncase 124:this.$ = $$[$0];\nbreak;\ncase 125:this.$ = $$[$0];\nbreak;\ncase 126:this.$ = $$[$0];\nbreak;\ncase 127:this.$ = [].concat($$[$0-2], $$[$0]);\nbreak;\ncase 128:this.$ = new yy.Try($$[$0]);\nbreak;\ncase 129:this.$ = new yy.Try($$[$0-1], $$[$0][0], $$[$0][1]);\nbreak;\ncase 130:this.$ = new yy.Try($$[$0-2], null, null, $$[$0]);\nbreak;\ncase 131:this.$ = new yy.Try($$[$0-3], $$[$0-2][0], $$[$0-2][1], $$[$0]);\nbreak;\ncase 132:this.$ = [$$[$0-1], $$[$0]];\nbreak;\ncase 133:this.$ = new yy.Throw($$[$0]);\nbreak;\ncase 134:this.$ = new yy.Parens($$[$0-1]);\nbreak;\ncase 135:this.$ = new yy.Parens($$[$0-2]);\nbreak;\ncase 136:this.$ = new yy.While($$[$0]);\nbreak;\ncase 137:this.$ = new yy.While($$[$0-2], {\n          guard: $$[$0]\n        });\nbreak;\ncase 138:this.$ = new yy.While($$[$0], {\n          invert: true\n        });\nbreak;\ncase 139:this.$ = new yy.While($$[$0-2], {\n          invert: true,\n          guard: $$[$0]\n        });\nbreak;\ncase 140:this.$ = $$[$0-1].addBody($$[$0]);\nbreak;\ncase 141:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]]));\nbreak;\ncase 142:this.$ = $$[$0].addBody(yy.Block.wrap([$$[$0-1]]));\nbreak;\ncase 143:this.$ = $$[$0];\nbreak;\ncase 144:this.$ = new yy.While(new yy.Literal('true')).addBody($$[$0]);\nbreak;\ncase 145:this.$ = new yy.While(new yy.Literal('true')).addBody(yy.Block.wrap([$$[$0]]));\nbreak;\ncase 146:this.$ = new yy.For($$[$0-1], $$[$0]);\nbreak;\ncase 147:this.$ = new yy.For($$[$0-1], $$[$0]);\nbreak;\ncase 148:this.$ = new yy.For($$[$0], $$[$0-1]);\nbreak;\ncase 149:this.$ = {\n          source: new yy.Value($$[$0])\n        };\nbreak;\ncase 150:this.$ = (function () {\n        $$[$0].own = $$[$0-1].own;\n        $$[$0].name = $$[$0-1][0];\n        $$[$0].index = $$[$0-1][1];\n        return $$[$0];\n      }());\nbreak;\ncase 151:this.$ = $$[$0];\nbreak;\ncase 152:this.$ = (function () {\n        $$[$0].own = true;\n        return $$[$0];\n      }());\nbreak;\ncase 153:this.$ = $$[$0];\nbreak;\ncase 154:this.$ = new yy.Value($$[$0]);\nbreak;\ncase 155:this.$ = new yy.Value($$[$0]);\nbreak;\ncase 156:this.$ = [$$[$0]];\nbreak;\ncase 157:this.$ = [$$[$0-2], $$[$0]];\nbreak;\ncase 158:this.$ = {\n          source: $$[$0]\n        };\nbreak;\ncase 159:this.$ = {\n          source: $$[$0],\n          object: true\n        };\nbreak;\ncase 160:this.$ = {\n          source: $$[$0-2],\n          guard: $$[$0]\n        };\nbreak;\ncase 161:this.$ = {\n          source: $$[$0-2],\n          guard: $$[$0],\n          object: true\n        };\nbreak;\ncase 162:this.$ = {\n          source: $$[$0-2],\n          step: $$[$0]\n        };\nbreak;\ncase 163:this.$ = {\n          source: $$[$0-4],\n          guard: $$[$0-2],\n          step: $$[$0]\n        };\nbreak;\ncase 164:this.$ = {\n          source: $$[$0-4],\n          step: $$[$0-2],\n          guard: $$[$0]\n        };\nbreak;\ncase 165:this.$ = new yy.Switch($$[$0-3], $$[$0-1]);\nbreak;\ncase 166:this.$ = new yy.Switch($$[$0-5], $$[$0-3], $$[$0-1]);\nbreak;\ncase 167:this.$ = new yy.Switch(null, $$[$0-1]);\nbreak;\ncase 168:this.$ = new yy.Switch(null, $$[$0-3], $$[$0-1]);\nbreak;\ncase 169:this.$ = $$[$0];\nbreak;\ncase 170:this.$ = $$[$0-1].concat($$[$0]);\nbreak;\ncase 171:this.$ = [[$$[$0-1], $$[$0]]];\nbreak;\ncase 172:this.$ = [[$$[$0-2], $$[$0-1]]];\nbreak;\ncase 173:this.$ = new yy.If($$[$0-1], $$[$0], {\n          type: $$[$0-2]\n        });\nbreak;\ncase 174:this.$ = $$[$0-4].addElse(new yy.If($$[$0-1], $$[$0], {\n          type: $$[$0-2]\n        }));\nbreak;\ncase 175:this.$ = $$[$0];\nbreak;\ncase 176:this.$ = $$[$0-2].addElse($$[$0]);\nbreak;\ncase 177:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), {\n          type: $$[$0-1],\n          statement: true\n        });\nbreak;\ncase 178:this.$ = new yy.If($$[$0], yy.Block.wrap([$$[$0-2]]), {\n          type: $$[$0-1],\n          statement: true\n        });\nbreak;\ncase 179:this.$ = new yy.Op($$[$0-1], $$[$0]);\nbreak;\ncase 180:this.$ = new yy.Op('-', $$[$0]);\nbreak;\ncase 181:this.$ = new yy.Op('+', $$[$0]);\nbreak;\ncase 182:this.$ = new yy.Op('--', $$[$0]);\nbreak;\ncase 183:this.$ = new yy.Op('++', $$[$0]);\nbreak;\ncase 184:this.$ = new yy.Op('--', $$[$0-1], null, true);\nbreak;\ncase 185:this.$ = new yy.Op('++', $$[$0-1], null, true);\nbreak;\ncase 186:this.$ = new yy.Existence($$[$0-1]);\nbreak;\ncase 187:this.$ = new yy.Op('+', $$[$0-2], $$[$0]);\nbreak;\ncase 188:this.$ = new yy.Op('-', $$[$0-2], $$[$0]);\nbreak;\ncase 189:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);\nbreak;\ncase 190:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);\nbreak;\ncase 191:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);\nbreak;\ncase 192:this.$ = new yy.Op($$[$0-1], $$[$0-2], $$[$0]);\nbreak;\ncase 193:this.$ = (function () {\n        if ($$[$0-1].charAt(0) === '!') {\n          return new yy.Op($$[$0-1].slice(1), $$[$0-2], $$[$0]).invert();\n        } else {\n          return new yy.Op($$[$0-1], $$[$0-2], $$[$0]);\n        }\n      }());\nbreak;\ncase 194:this.$ = new yy.Assign($$[$0-2], $$[$0], $$[$0-1]);\nbreak;\ncase 195:this.$ = new yy.Assign($$[$0-4], $$[$0-1], $$[$0-3]);\nbreak;\ncase 196:this.$ = new yy.Extends($$[$0-2], $$[$0]);\nbreak;\n}\n},\ntable: [{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[3]},{1:[2,2],6:[1,72]},{6:[1,73]},{1:[2,4],6:[2,4],26:[2,4],99:[2,4]},{4:75,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[1,74],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,7],6:[2,7],26:[2,7],99:[2,7],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,8],6:[2,8],26:[2,8],99:[2,8],100:88,101:[1,63],103:[1,64],106:89,107:[1,66],108:67,123:[1,87]},{1:[2,12],6:[2,12],25:[2,12],26:[2,12],47:[2,12],52:[2,12],55:[2,12],60:91,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],70:[2,12],71:[1,98],75:[2,12],78:90,81:[1,92],82:[2,103],83:[2,12],88:[2,12],90:[2,12],99:[2,12],101:[2,12],102:[2,12],103:[2,12],107:[2,12],115:[2,12],123:[2,12],125:[2,12],126:[2,12],129:[2,12],130:[2,12],131:[2,12],132:[2,12],133:[2,12],134:[2,12]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],47:[2,13],52:[2,13],55:[2,13],60:100,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],70:[2,13],71:[1,98],75:[2,13],78:99,81:[1,92],82:[2,103],83:[2,13],88:[2,13],90:[2,13],99:[2,13],101:[2,13],102:[2,13],103:[2,13],107:[2,13],115:[2,13],123:[2,13],125:[2,13],126:[2,13],129:[2,13],130:[2,13],131:[2,13],132:[2,13],133:[2,13],134:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],47:[2,14],52:[2,14],55:[2,14],70:[2,14],75:[2,14],83:[2,14],88:[2,14],90:[2,14],99:[2,14],101:[2,14],102:[2,14],103:[2,14],107:[2,14],115:[2,14],123:[2,14],125:[2,14],126:[2,14],129:[2,14],130:[2,14],131:[2,14],132:[2,14],133:[2,14],134:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],47:[2,15],52:[2,15],55:[2,15],70:[2,15],75:[2,15],83:[2,15],88:[2,15],90:[2,15],99:[2,15],101:[2,15],102:[2,15],103:[2,15],107:[2,15],115:[2,15],123:[2,15],125:[2,15],126:[2,15],129:[2,15],130:[2,15],131:[2,15],132:[2,15],133:[2,15],134:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],47:[2,16],52:[2,16],55:[2,16],70:[2,16],75:[2,16],83:[2,16],88:[2,16],90:[2,16],99:[2,16],101:[2,16],102:[2,16],103:[2,16],107:[2,16],115:[2,16],123:[2,16],125:[2,16],126:[2,16],129:[2,16],130:[2,16],131:[2,16],132:[2,16],133:[2,16],134:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],47:[2,17],52:[2,17],55:[2,17],70:[2,17],75:[2,17],83:[2,17],88:[2,17],90:[2,17],99:[2,17],101:[2,17],102:[2,17],103:[2,17],107:[2,17],115:[2,17],123:[2,17],125:[2,17],126:[2,17],129:[2,17],130:[2,17],131:[2,17],132:[2,17],133:[2,17],134:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],47:[2,18],52:[2,18],55:[2,18],70:[2,18],75:[2,18],83:[2,18],88:[2,18],90:[2,18],99:[2,18],101:[2,18],102:[2,18],103:[2,18],107:[2,18],115:[2,18],123:[2,18],125:[2,18],126:[2,18],129:[2,18],130:[2,18],131:[2,18],132:[2,18],133:[2,18],134:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],47:[2,19],52:[2,19],55:[2,19],70:[2,19],75:[2,19],83:[2,19],88:[2,19],90:[2,19],99:[2,19],101:[2,19],102:[2,19],103:[2,19],107:[2,19],115:[2,19],123:[2,19],125:[2,19],126:[2,19],129:[2,19],130:[2,19],131:[2,19],132:[2,19],133:[2,19],134:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],47:[2,20],52:[2,20],55:[2,20],70:[2,20],75:[2,20],83:[2,20],88:[2,20],90:[2,20],99:[2,20],101:[2,20],102:[2,20],103:[2,20],107:[2,20],115:[2,20],123:[2,20],125:[2,20],126:[2,20],129:[2,20],130:[2,20],131:[2,20],132:[2,20],133:[2,20],134:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],47:[2,21],52:[2,21],55:[2,21],70:[2,21],75:[2,21],83:[2,21],88:[2,21],90:[2,21],99:[2,21],101:[2,21],102:[2,21],103:[2,21],107:[2,21],115:[2,21],123:[2,21],125:[2,21],126:[2,21],129:[2,21],130:[2,21],131:[2,21],132:[2,21],133:[2,21],134:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],47:[2,22],52:[2,22],55:[2,22],70:[2,22],75:[2,22],83:[2,22],88:[2,22],90:[2,22],99:[2,22],101:[2,22],102:[2,22],103:[2,22],107:[2,22],115:[2,22],123:[2,22],125:[2,22],126:[2,22],129:[2,22],130:[2,22],131:[2,22],132:[2,22],133:[2,22],134:[2,22]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],47:[2,23],52:[2,23],55:[2,23],70:[2,23],75:[2,23],83:[2,23],88:[2,23],90:[2,23],99:[2,23],101:[2,23],102:[2,23],103:[2,23],107:[2,23],115:[2,23],123:[2,23],125:[2,23],126:[2,23],129:[2,23],130:[2,23],131:[2,23],132:[2,23],133:[2,23],134:[2,23]},{1:[2,9],6:[2,9],26:[2,9],99:[2,9],101:[2,9],103:[2,9],107:[2,9],123:[2,9]},{1:[2,10],6:[2,10],26:[2,10],99:[2,10],101:[2,10],103:[2,10],107:[2,10],123:[2,10]},{1:[2,11],6:[2,11],26:[2,11],99:[2,11],101:[2,11],103:[2,11],107:[2,11],123:[2,11]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],38:[1,101],47:[2,71],52:[2,71],55:[2,71],64:[2,71],65:[2,71],66:[2,71],68:[2,71],70:[2,71],71:[2,71],75:[2,71],81:[2,71],82:[2,71],83:[2,71],88:[2,71],90:[2,71],99:[2,71],101:[2,71],102:[2,71],103:[2,71],107:[2,71],115:[2,71],123:[2,71],125:[2,71],126:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],47:[2,72],52:[2,72],55:[2,72],64:[2,72],65:[2,72],66:[2,72],68:[2,72],70:[2,72],71:[2,72],75:[2,72],81:[2,72],82:[2,72],83:[2,72],88:[2,72],90:[2,72],99:[2,72],101:[2,72],102:[2,72],103:[2,72],107:[2,72],115:[2,72],123:[2,72],125:[2,72],126:[2,72],129:[2,72],130:[2,72],131:[2,72],132:[2,72],133:[2,72],134:[2,72]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],47:[2,73],52:[2,73],55:[2,73],64:[2,73],65:[2,73],66:[2,73],68:[2,73],70:[2,73],71:[2,73],75:[2,73],81:[2,73],82:[2,73],83:[2,73],88:[2,73],90:[2,73],99:[2,73],101:[2,73],102:[2,73],103:[2,73],107:[2,73],115:[2,73],123:[2,73],125:[2,73],126:[2,73],129:[2,73],130:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],47:[2,74],52:[2,74],55:[2,74],64:[2,74],65:[2,74],66:[2,74],68:[2,74],70:[2,74],71:[2,74],75:[2,74],81:[2,74],82:[2,74],83:[2,74],88:[2,74],90:[2,74],99:[2,74],101:[2,74],102:[2,74],103:[2,74],107:[2,74],115:[2,74],123:[2,74],125:[2,74],126:[2,74],129:[2,74],130:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],47:[2,75],52:[2,75],55:[2,75],64:[2,75],65:[2,75],66:[2,75],68:[2,75],70:[2,75],71:[2,75],75:[2,75],81:[2,75],82:[2,75],83:[2,75],88:[2,75],90:[2,75],99:[2,75],101:[2,75],102:[2,75],103:[2,75],107:[2,75],115:[2,75],123:[2,75],125:[2,75],126:[2,75],129:[2,75],130:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75]},{1:[2,101],6:[2,101],25:[2,101],26:[2,101],47:[2,101],52:[2,101],55:[2,101],64:[2,101],65:[2,101],66:[2,101],68:[2,101],70:[2,101],71:[2,101],75:[2,101],79:102,81:[2,101],82:[1,103],83:[2,101],88:[2,101],90:[2,101],99:[2,101],101:[2,101],102:[2,101],103:[2,101],107:[2,101],115:[2,101],123:[2,101],125:[2,101],126:[2,101],129:[2,101],130:[2,101],131:[2,101],132:[2,101],133:[2,101],134:[2,101]},{27:107,28:[1,71],42:108,46:104,47:[2,53],52:[2,53],53:105,54:106,56:109,57:110,73:[1,68],86:[1,111],87:[1,112]},{5:113,25:[1,5]},{8:114,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:116,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:117,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{13:119,14:120,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,56:47,57:48,59:118,61:25,62:26,63:27,73:[1,68],80:[1,28],85:[1,56],86:[1,57],87:[1,55],98:[1,54]},{13:119,14:120,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,56:47,57:48,59:122,61:25,62:26,63:27,73:[1,68],80:[1,28],85:[1,56],86:[1,57],87:[1,55],98:[1,54]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],38:[2,68],47:[2,68],52:[2,68],55:[2,68],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,68],71:[2,68],75:[2,68],77:[1,126],81:[2,68],82:[2,68],83:[2,68],88:[2,68],90:[2,68],99:[2,68],101:[2,68],102:[2,68],103:[2,68],107:[2,68],115:[2,68],123:[2,68],125:[2,68],126:[2,68],127:[1,123],128:[1,124],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68],135:[1,125]},{1:[2,175],6:[2,175],25:[2,175],26:[2,175],47:[2,175],52:[2,175],55:[2,175],70:[2,175],75:[2,175],83:[2,175],88:[2,175],90:[2,175],99:[2,175],101:[2,175],102:[2,175],103:[2,175],107:[2,175],115:[2,175],118:[1,127],123:[2,175],125:[2,175],126:[2,175],129:[2,175],130:[2,175],131:[2,175],132:[2,175],133:[2,175],134:[2,175]},{5:128,25:[1,5]},{5:129,25:[1,5]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],47:[2,143],52:[2,143],55:[2,143],70:[2,143],75:[2,143],83:[2,143],88:[2,143],90:[2,143],99:[2,143],101:[2,143],102:[2,143],103:[2,143],107:[2,143],115:[2,143],123:[2,143],125:[2,143],126:[2,143],129:[2,143],130:[2,143],131:[2,143],132:[2,143],133:[2,143],134:[2,143]},{5:130,25:[1,5]},{8:131,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,132],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,91],5:133,6:[2,91],13:119,14:120,25:[1,5],26:[2,91],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:121,42:61,47:[2,91],52:[2,91],55:[2,91],56:47,57:48,59:135,61:25,62:26,63:27,70:[2,91],73:[1,68],75:[2,91],77:[1,134],80:[1,28],83:[2,91],85:[1,56],86:[1,57],87:[1,55],88:[2,91],90:[2,91],98:[1,54],99:[2,91],101:[2,91],102:[2,91],103:[2,91],107:[2,91],115:[2,91],123:[2,91],125:[2,91],126:[2,91],129:[2,91],130:[2,91],131:[2,91],132:[2,91],133:[2,91],134:[2,91]},{8:136,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,45],6:[2,45],8:137,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,45],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],99:[2,45],100:39,101:[2,45],103:[2,45],104:40,105:[1,65],106:41,107:[2,45],108:67,116:[1,42],121:37,122:[1,62],123:[2,45],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,46],6:[2,46],25:[2,46],26:[2,46],52:[2,46],75:[2,46],99:[2,46],101:[2,46],103:[2,46],107:[2,46],123:[2,46]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],38:[2,69],47:[2,69],52:[2,69],55:[2,69],64:[2,69],65:[2,69],66:[2,69],68:[2,69],70:[2,69],71:[2,69],75:[2,69],81:[2,69],82:[2,69],83:[2,69],88:[2,69],90:[2,69],99:[2,69],101:[2,69],102:[2,69],103:[2,69],107:[2,69],115:[2,69],123:[2,69],125:[2,69],126:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],38:[2,70],47:[2,70],52:[2,70],55:[2,70],64:[2,70],65:[2,70],66:[2,70],68:[2,70],70:[2,70],71:[2,70],75:[2,70],81:[2,70],82:[2,70],83:[2,70],88:[2,70],90:[2,70],99:[2,70],101:[2,70],102:[2,70],103:[2,70],107:[2,70],115:[2,70],123:[2,70],125:[2,70],126:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],47:[2,29],52:[2,29],55:[2,29],64:[2,29],65:[2,29],66:[2,29],68:[2,29],70:[2,29],71:[2,29],75:[2,29],81:[2,29],82:[2,29],83:[2,29],88:[2,29],90:[2,29],99:[2,29],101:[2,29],102:[2,29],103:[2,29],107:[2,29],115:[2,29],123:[2,29],125:[2,29],126:[2,29],129:[2,29],130:[2,29],131:[2,29],132:[2,29],133:[2,29],134:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],47:[2,30],52:[2,30],55:[2,30],64:[2,30],65:[2,30],66:[2,30],68:[2,30],70:[2,30],71:[2,30],75:[2,30],81:[2,30],82:[2,30],83:[2,30],88:[2,30],90:[2,30],99:[2,30],101:[2,30],102:[2,30],103:[2,30],107:[2,30],115:[2,30],123:[2,30],125:[2,30],126:[2,30],129:[2,30],130:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],47:[2,31],52:[2,31],55:[2,31],64:[2,31],65:[2,31],66:[2,31],68:[2,31],70:[2,31],71:[2,31],75:[2,31],81:[2,31],82:[2,31],83:[2,31],88:[2,31],90:[2,31],99:[2,31],101:[2,31],102:[2,31],103:[2,31],107:[2,31],115:[2,31],123:[2,31],125:[2,31],126:[2,31],129:[2,31],130:[2,31],131:[2,31],132:[2,31],133:[2,31],134:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],47:[2,32],52:[2,32],55:[2,32],64:[2,32],65:[2,32],66:[2,32],68:[2,32],70:[2,32],71:[2,32],75:[2,32],81:[2,32],82:[2,32],83:[2,32],88:[2,32],90:[2,32],99:[2,32],101:[2,32],102:[2,32],103:[2,32],107:[2,32],115:[2,32],123:[2,32],125:[2,32],126:[2,32],129:[2,32],130:[2,32],131:[2,32],132:[2,32],133:[2,32],134:[2,32]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],47:[2,33],52:[2,33],55:[2,33],64:[2,33],65:[2,33],66:[2,33],68:[2,33],70:[2,33],71:[2,33],75:[2,33],81:[2,33],82:[2,33],83:[2,33],88:[2,33],90:[2,33],99:[2,33],101:[2,33],102:[2,33],103:[2,33],107:[2,33],115:[2,33],123:[2,33],125:[2,33],126:[2,33],129:[2,33],130:[2,33],131:[2,33],132:[2,33],133:[2,33],134:[2,33]},{4:138,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,139],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:140,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:142,85:[1,56],86:[1,57],87:[1,55],88:[1,141],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,107],6:[2,107],25:[2,107],26:[2,107],47:[2,107],52:[2,107],55:[2,107],64:[2,107],65:[2,107],66:[2,107],68:[2,107],70:[2,107],71:[2,107],75:[2,107],81:[2,107],82:[2,107],83:[2,107],88:[2,107],90:[2,107],99:[2,107],101:[2,107],102:[2,107],103:[2,107],107:[2,107],115:[2,107],123:[2,107],125:[2,107],126:[2,107],129:[2,107],130:[2,107],131:[2,107],132:[2,107],133:[2,107],134:[2,107]},{1:[2,108],6:[2,108],25:[2,108],26:[2,108],27:146,28:[1,71],47:[2,108],52:[2,108],55:[2,108],64:[2,108],65:[2,108],66:[2,108],68:[2,108],70:[2,108],71:[2,108],75:[2,108],81:[2,108],82:[2,108],83:[2,108],88:[2,108],90:[2,108],99:[2,108],101:[2,108],102:[2,108],103:[2,108],107:[2,108],115:[2,108],123:[2,108],125:[2,108],126:[2,108],129:[2,108],130:[2,108],131:[2,108],132:[2,108],133:[2,108],134:[2,108]},{25:[2,49]},{25:[2,50]},{1:[2,64],6:[2,64],25:[2,64],26:[2,64],38:[2,64],47:[2,64],52:[2,64],55:[2,64],64:[2,64],65:[2,64],66:[2,64],68:[2,64],70:[2,64],71:[2,64],75:[2,64],77:[2,64],81:[2,64],82:[2,64],83:[2,64],88:[2,64],90:[2,64],99:[2,64],101:[2,64],102:[2,64],103:[2,64],107:[2,64],115:[2,64],123:[2,64],125:[2,64],126:[2,64],127:[2,64],128:[2,64],129:[2,64],130:[2,64],131:[2,64],132:[2,64],133:[2,64],134:[2,64],135:[2,64]},{1:[2,67],6:[2,67],25:[2,67],26:[2,67],38:[2,67],47:[2,67],52:[2,67],55:[2,67],64:[2,67],65:[2,67],66:[2,67],68:[2,67],70:[2,67],71:[2,67],75:[2,67],77:[2,67],81:[2,67],82:[2,67],83:[2,67],88:[2,67],90:[2,67],99:[2,67],101:[2,67],102:[2,67],103:[2,67],107:[2,67],115:[2,67],123:[2,67],125:[2,67],126:[2,67],127:[2,67],128:[2,67],129:[2,67],130:[2,67],131:[2,67],132:[2,67],133:[2,67],134:[2,67],135:[2,67]},{8:147,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:148,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:149,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:150,8:151,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{27:156,28:[1,71],56:157,57:158,62:152,73:[1,68],87:[1,55],110:153,111:[1,154],112:155},{109:159,113:[1,160],114:[1,161]},{6:[2,86],11:165,25:[2,86],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:163,40:164,42:168,44:[1,46],52:[2,86],74:162,75:[2,86],86:[1,111]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],41:[2,27],47:[2,27],52:[2,27],55:[2,27],64:[2,27],65:[2,27],66:[2,27],68:[2,27],70:[2,27],71:[2,27],75:[2,27],81:[2,27],82:[2,27],83:[2,27],88:[2,27],90:[2,27],99:[2,27],101:[2,27],102:[2,27],103:[2,27],107:[2,27],115:[2,27],123:[2,27],125:[2,27],126:[2,27],129:[2,27],130:[2,27],131:[2,27],132:[2,27],133:[2,27],134:[2,27]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],41:[2,28],47:[2,28],52:[2,28],55:[2,28],64:[2,28],65:[2,28],66:[2,28],68:[2,28],70:[2,28],71:[2,28],75:[2,28],81:[2,28],82:[2,28],83:[2,28],88:[2,28],90:[2,28],99:[2,28],101:[2,28],102:[2,28],103:[2,28],107:[2,28],115:[2,28],123:[2,28],125:[2,28],126:[2,28],129:[2,28],130:[2,28],131:[2,28],132:[2,28],133:[2,28],134:[2,28]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],38:[2,26],41:[2,26],47:[2,26],52:[2,26],55:[2,26],64:[2,26],65:[2,26],66:[2,26],68:[2,26],70:[2,26],71:[2,26],75:[2,26],77:[2,26],81:[2,26],82:[2,26],83:[2,26],88:[2,26],90:[2,26],99:[2,26],101:[2,26],102:[2,26],103:[2,26],107:[2,26],113:[2,26],114:[2,26],115:[2,26],123:[2,26],125:[2,26],126:[2,26],127:[2,26],128:[2,26],129:[2,26],130:[2,26],131:[2,26],132:[2,26],133:[2,26],134:[2,26],135:[2,26]},{1:[2,6],6:[2,6],7:169,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,6],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],99:[2,6],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,3]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],47:[2,24],52:[2,24],55:[2,24],70:[2,24],75:[2,24],83:[2,24],88:[2,24],90:[2,24],95:[2,24],96:[2,24],99:[2,24],101:[2,24],102:[2,24],103:[2,24],107:[2,24],115:[2,24],118:[2,24],120:[2,24],123:[2,24],125:[2,24],126:[2,24],129:[2,24],130:[2,24],131:[2,24],132:[2,24],133:[2,24],134:[2,24]},{6:[1,72],26:[1,170]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],47:[2,186],52:[2,186],55:[2,186],70:[2,186],75:[2,186],83:[2,186],88:[2,186],90:[2,186],99:[2,186],101:[2,186],102:[2,186],103:[2,186],107:[2,186],115:[2,186],123:[2,186],125:[2,186],126:[2,186],129:[2,186],130:[2,186],131:[2,186],132:[2,186],133:[2,186],134:[2,186]},{8:171,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:172,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:173,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:174,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:175,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:176,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:177,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:178,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],47:[2,142],52:[2,142],55:[2,142],70:[2,142],75:[2,142],83:[2,142],88:[2,142],90:[2,142],99:[2,142],101:[2,142],102:[2,142],103:[2,142],107:[2,142],115:[2,142],123:[2,142],125:[2,142],126:[2,142],129:[2,142],130:[2,142],131:[2,142],132:[2,142],133:[2,142],134:[2,142]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],47:[2,147],52:[2,147],55:[2,147],70:[2,147],75:[2,147],83:[2,147],88:[2,147],90:[2,147],99:[2,147],101:[2,147],102:[2,147],103:[2,147],107:[2,147],115:[2,147],123:[2,147],125:[2,147],126:[2,147],129:[2,147],130:[2,147],131:[2,147],132:[2,147],133:[2,147],134:[2,147]},{8:179,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],47:[2,141],52:[2,141],55:[2,141],70:[2,141],75:[2,141],83:[2,141],88:[2,141],90:[2,141],99:[2,141],101:[2,141],102:[2,141],103:[2,141],107:[2,141],115:[2,141],123:[2,141],125:[2,141],126:[2,141],129:[2,141],130:[2,141],131:[2,141],132:[2,141],133:[2,141],134:[2,141]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],47:[2,146],52:[2,146],55:[2,146],70:[2,146],75:[2,146],83:[2,146],88:[2,146],90:[2,146],99:[2,146],101:[2,146],102:[2,146],103:[2,146],107:[2,146],115:[2,146],123:[2,146],125:[2,146],126:[2,146],129:[2,146],130:[2,146],131:[2,146],132:[2,146],133:[2,146],134:[2,146]},{79:180,82:[1,103]},{1:[2,65],6:[2,65],25:[2,65],26:[2,65],38:[2,65],47:[2,65],52:[2,65],55:[2,65],64:[2,65],65:[2,65],66:[2,65],68:[2,65],70:[2,65],71:[2,65],75:[2,65],77:[2,65],81:[2,65],82:[2,65],83:[2,65],88:[2,65],90:[2,65],99:[2,65],101:[2,65],102:[2,65],103:[2,65],107:[2,65],115:[2,65],123:[2,65],125:[2,65],126:[2,65],127:[2,65],128:[2,65],129:[2,65],130:[2,65],131:[2,65],132:[2,65],133:[2,65],134:[2,65],135:[2,65]},{82:[2,104]},{27:181,28:[1,71]},{27:182,28:[1,71]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],27:183,28:[1,71],38:[2,79],47:[2,79],52:[2,79],55:[2,79],64:[2,79],65:[2,79],66:[2,79],68:[2,79],70:[2,79],71:[2,79],75:[2,79],77:[2,79],81:[2,79],82:[2,79],83:[2,79],88:[2,79],90:[2,79],99:[2,79],101:[2,79],102:[2,79],103:[2,79],107:[2,79],115:[2,79],123:[2,79],125:[2,79],126:[2,79],127:[2,79],128:[2,79],129:[2,79],130:[2,79],131:[2,79],132:[2,79],133:[2,79],134:[2,79],135:[2,79]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],38:[2,80],47:[2,80],52:[2,80],55:[2,80],64:[2,80],65:[2,80],66:[2,80],68:[2,80],70:[2,80],71:[2,80],75:[2,80],77:[2,80],81:[2,80],82:[2,80],83:[2,80],88:[2,80],90:[2,80],99:[2,80],101:[2,80],102:[2,80],103:[2,80],107:[2,80],115:[2,80],123:[2,80],125:[2,80],126:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80]},{8:185,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],55:[1,189],56:47,57:48,59:36,61:25,62:26,63:27,69:184,72:186,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],89:187,90:[1,188],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{67:190,68:[1,97],71:[1,98]},{79:191,82:[1,103]},{1:[2,66],6:[2,66],25:[2,66],26:[2,66],38:[2,66],47:[2,66],52:[2,66],55:[2,66],64:[2,66],65:[2,66],66:[2,66],68:[2,66],70:[2,66],71:[2,66],75:[2,66],77:[2,66],81:[2,66],82:[2,66],83:[2,66],88:[2,66],90:[2,66],99:[2,66],101:[2,66],102:[2,66],103:[2,66],107:[2,66],115:[2,66],123:[2,66],125:[2,66],126:[2,66],127:[2,66],128:[2,66],129:[2,66],130:[2,66],131:[2,66],132:[2,66],133:[2,66],134:[2,66],135:[2,66]},{6:[1,193],8:192,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,194],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,102],6:[2,102],25:[2,102],26:[2,102],47:[2,102],52:[2,102],55:[2,102],64:[2,102],65:[2,102],66:[2,102],68:[2,102],70:[2,102],71:[2,102],75:[2,102],81:[2,102],82:[2,102],83:[2,102],88:[2,102],90:[2,102],99:[2,102],101:[2,102],102:[2,102],103:[2,102],107:[2,102],115:[2,102],123:[2,102],125:[2,102],126:[2,102],129:[2,102],130:[2,102],131:[2,102],132:[2,102],133:[2,102],134:[2,102]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],83:[1,195],84:196,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{47:[1,198],52:[1,199]},{47:[2,54],52:[2,54]},{38:[1,201],47:[2,56],52:[2,56],55:[1,200]},{38:[2,59],47:[2,59],52:[2,59],55:[2,59]},{38:[2,60],47:[2,60],52:[2,60],55:[2,60]},{38:[2,61],47:[2,61],52:[2,61],55:[2,61]},{38:[2,62],47:[2,62],52:[2,62],55:[2,62]},{27:146,28:[1,71]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:142,85:[1,56],86:[1,57],87:[1,55],88:[1,141],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,48],6:[2,48],25:[2,48],26:[2,48],47:[2,48],52:[2,48],55:[2,48],70:[2,48],75:[2,48],83:[2,48],88:[2,48],90:[2,48],99:[2,48],101:[2,48],102:[2,48],103:[2,48],107:[2,48],115:[2,48],123:[2,48],125:[2,48],126:[2,48],129:[2,48],130:[2,48],131:[2,48],132:[2,48],133:[2,48],134:[2,48]},{1:[2,179],6:[2,179],25:[2,179],26:[2,179],47:[2,179],52:[2,179],55:[2,179],70:[2,179],75:[2,179],83:[2,179],88:[2,179],90:[2,179],99:[2,179],100:85,101:[2,179],102:[2,179],103:[2,179],106:86,107:[2,179],108:67,115:[2,179],123:[2,179],125:[2,179],126:[2,179],129:[1,76],130:[2,179],131:[2,179],132:[2,179],133:[2,179],134:[2,179]},{100:88,101:[1,63],103:[1,64],106:89,107:[1,66],108:67,123:[1,87]},{1:[2,180],6:[2,180],25:[2,180],26:[2,180],47:[2,180],52:[2,180],55:[2,180],70:[2,180],75:[2,180],83:[2,180],88:[2,180],90:[2,180],99:[2,180],100:85,101:[2,180],102:[2,180],103:[2,180],106:86,107:[2,180],108:67,115:[2,180],123:[2,180],125:[2,180],126:[2,180],129:[1,76],130:[2,180],131:[2,180],132:[2,180],133:[2,180],134:[2,180]},{1:[2,181],6:[2,181],25:[2,181],26:[2,181],47:[2,181],52:[2,181],55:[2,181],70:[2,181],75:[2,181],83:[2,181],88:[2,181],90:[2,181],99:[2,181],100:85,101:[2,181],102:[2,181],103:[2,181],106:86,107:[2,181],108:67,115:[2,181],123:[2,181],125:[2,181],126:[2,181],129:[1,76],130:[2,181],131:[2,181],132:[2,181],133:[2,181],134:[2,181]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],47:[2,182],52:[2,182],55:[2,182],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,182],71:[2,68],75:[2,182],81:[2,68],82:[2,68],83:[2,182],88:[2,182],90:[2,182],99:[2,182],101:[2,182],102:[2,182],103:[2,182],107:[2,182],115:[2,182],123:[2,182],125:[2,182],126:[2,182],129:[2,182],130:[2,182],131:[2,182],132:[2,182],133:[2,182],134:[2,182]},{60:91,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],71:[1,98],78:90,81:[1,92],82:[2,103]},{60:100,64:[1,93],65:[1,94],66:[1,95],67:96,68:[1,97],71:[1,98],78:99,81:[1,92],82:[2,103]},{64:[2,71],65:[2,71],66:[2,71],68:[2,71],71:[2,71],81:[2,71],82:[2,71]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],47:[2,183],52:[2,183],55:[2,183],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,183],71:[2,68],75:[2,183],81:[2,68],82:[2,68],83:[2,183],88:[2,183],90:[2,183],99:[2,183],101:[2,183],102:[2,183],103:[2,183],107:[2,183],115:[2,183],123:[2,183],125:[2,183],126:[2,183],129:[2,183],130:[2,183],131:[2,183],132:[2,183],133:[2,183],134:[2,183]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],47:[2,184],52:[2,184],55:[2,184],70:[2,184],75:[2,184],83:[2,184],88:[2,184],90:[2,184],99:[2,184],101:[2,184],102:[2,184],103:[2,184],107:[2,184],115:[2,184],123:[2,184],125:[2,184],126:[2,184],129:[2,184],130:[2,184],131:[2,184],132:[2,184],133:[2,184],134:[2,184]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],47:[2,185],52:[2,185],55:[2,185],70:[2,185],75:[2,185],83:[2,185],88:[2,185],90:[2,185],99:[2,185],101:[2,185],102:[2,185],103:[2,185],107:[2,185],115:[2,185],123:[2,185],125:[2,185],126:[2,185],129:[2,185],130:[2,185],131:[2,185],132:[2,185],133:[2,185],134:[2,185]},{8:202,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,203],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:204,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{5:205,25:[1,5],122:[1,206]},{1:[2,128],6:[2,128],25:[2,128],26:[2,128],47:[2,128],52:[2,128],55:[2,128],70:[2,128],75:[2,128],83:[2,128],88:[2,128],90:[2,128],94:207,95:[1,208],96:[1,209],99:[2,128],101:[2,128],102:[2,128],103:[2,128],107:[2,128],115:[2,128],123:[2,128],125:[2,128],126:[2,128],129:[2,128],130:[2,128],131:[2,128],132:[2,128],133:[2,128],134:[2,128]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],47:[2,140],52:[2,140],55:[2,140],70:[2,140],75:[2,140],83:[2,140],88:[2,140],90:[2,140],99:[2,140],101:[2,140],102:[2,140],103:[2,140],107:[2,140],115:[2,140],123:[2,140],125:[2,140],126:[2,140],129:[2,140],130:[2,140],131:[2,140],132:[2,140],133:[2,140],134:[2,140]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],47:[2,148],52:[2,148],55:[2,148],70:[2,148],75:[2,148],83:[2,148],88:[2,148],90:[2,148],99:[2,148],101:[2,148],102:[2,148],103:[2,148],107:[2,148],115:[2,148],123:[2,148],125:[2,148],126:[2,148],129:[2,148],130:[2,148],131:[2,148],132:[2,148],133:[2,148],134:[2,148]},{25:[1,210],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{117:211,119:212,120:[1,213]},{1:[2,92],6:[2,92],25:[2,92],26:[2,92],47:[2,92],52:[2,92],55:[2,92],70:[2,92],75:[2,92],83:[2,92],88:[2,92],90:[2,92],99:[2,92],101:[2,92],102:[2,92],103:[2,92],107:[2,92],115:[2,92],123:[2,92],125:[2,92],126:[2,92],129:[2,92],130:[2,92],131:[2,92],132:[2,92],133:[2,92],134:[2,92]},{8:214,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,95],5:215,6:[2,95],25:[1,5],26:[2,95],47:[2,95],52:[2,95],55:[2,95],64:[2,68],65:[2,68],66:[2,68],68:[2,68],70:[2,95],71:[2,68],75:[2,95],77:[1,216],81:[2,68],82:[2,68],83:[2,95],88:[2,95],90:[2,95],99:[2,95],101:[2,95],102:[2,95],103:[2,95],107:[2,95],115:[2,95],123:[2,95],125:[2,95],126:[2,95],129:[2,95],130:[2,95],131:[2,95],132:[2,95],133:[2,95],134:[2,95]},{1:[2,133],6:[2,133],25:[2,133],26:[2,133],47:[2,133],52:[2,133],55:[2,133],70:[2,133],75:[2,133],83:[2,133],88:[2,133],90:[2,133],99:[2,133],100:85,101:[2,133],102:[2,133],103:[2,133],106:86,107:[2,133],108:67,115:[2,133],123:[2,133],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,44],6:[2,44],26:[2,44],99:[2,44],100:85,101:[2,44],103:[2,44],106:86,107:[2,44],108:67,123:[2,44],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,72],99:[1,217]},{4:218,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,124],25:[2,124],52:[2,124],55:[1,220],88:[2,124],89:219,90:[1,188],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],38:[2,110],47:[2,110],52:[2,110],55:[2,110],64:[2,110],65:[2,110],66:[2,110],68:[2,110],70:[2,110],71:[2,110],75:[2,110],81:[2,110],82:[2,110],83:[2,110],88:[2,110],90:[2,110],99:[2,110],101:[2,110],102:[2,110],103:[2,110],107:[2,110],113:[2,110],114:[2,110],115:[2,110],123:[2,110],125:[2,110],126:[2,110],129:[2,110],130:[2,110],131:[2,110],132:[2,110],133:[2,110],134:[2,110]},{6:[2,51],25:[2,51],51:221,52:[1,222],88:[2,51]},{6:[2,119],25:[2,119],26:[2,119],52:[2,119],83:[2,119],88:[2,119]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:223,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,125],25:[2,125],26:[2,125],52:[2,125],83:[2,125],88:[2,125]},{1:[2,109],6:[2,109],25:[2,109],26:[2,109],38:[2,109],41:[2,109],47:[2,109],52:[2,109],55:[2,109],64:[2,109],65:[2,109],66:[2,109],68:[2,109],70:[2,109],71:[2,109],75:[2,109],77:[2,109],81:[2,109],82:[2,109],83:[2,109],88:[2,109],90:[2,109],99:[2,109],101:[2,109],102:[2,109],103:[2,109],107:[2,109],115:[2,109],123:[2,109],125:[2,109],126:[2,109],127:[2,109],128:[2,109],129:[2,109],130:[2,109],131:[2,109],132:[2,109],133:[2,109],134:[2,109],135:[2,109]},{5:224,25:[1,5],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],47:[2,136],52:[2,136],55:[2,136],70:[2,136],75:[2,136],83:[2,136],88:[2,136],90:[2,136],99:[2,136],100:85,101:[1,63],102:[1,225],103:[1,64],106:86,107:[1,66],108:67,115:[2,136],123:[2,136],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],47:[2,138],52:[2,138],55:[2,138],70:[2,138],75:[2,138],83:[2,138],88:[2,138],90:[2,138],99:[2,138],100:85,101:[1,63],102:[1,226],103:[1,64],106:86,107:[1,66],108:67,115:[2,138],123:[2,138],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],47:[2,144],52:[2,144],55:[2,144],70:[2,144],75:[2,144],83:[2,144],88:[2,144],90:[2,144],99:[2,144],101:[2,144],102:[2,144],103:[2,144],107:[2,144],115:[2,144],123:[2,144],125:[2,144],126:[2,144],129:[2,144],130:[2,144],131:[2,144],132:[2,144],133:[2,144],134:[2,144]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],47:[2,145],52:[2,145],55:[2,145],70:[2,145],75:[2,145],83:[2,145],88:[2,145],90:[2,145],99:[2,145],100:85,101:[1,63],102:[2,145],103:[1,64],106:86,107:[1,66],108:67,115:[2,145],123:[2,145],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,149],6:[2,149],25:[2,149],26:[2,149],47:[2,149],52:[2,149],55:[2,149],70:[2,149],75:[2,149],83:[2,149],88:[2,149],90:[2,149],99:[2,149],101:[2,149],102:[2,149],103:[2,149],107:[2,149],115:[2,149],123:[2,149],125:[2,149],126:[2,149],129:[2,149],130:[2,149],131:[2,149],132:[2,149],133:[2,149],134:[2,149]},{113:[2,151],114:[2,151]},{27:156,28:[1,71],56:157,57:158,73:[1,68],87:[1,112],110:227,112:155},{52:[1,228],113:[2,156],114:[2,156]},{52:[2,153],113:[2,153],114:[2,153]},{52:[2,154],113:[2,154],114:[2,154]},{52:[2,155],113:[2,155],114:[2,155]},{1:[2,150],6:[2,150],25:[2,150],26:[2,150],47:[2,150],52:[2,150],55:[2,150],70:[2,150],75:[2,150],83:[2,150],88:[2,150],90:[2,150],99:[2,150],101:[2,150],102:[2,150],103:[2,150],107:[2,150],115:[2,150],123:[2,150],125:[2,150],126:[2,150],129:[2,150],130:[2,150],131:[2,150],132:[2,150],133:[2,150],134:[2,150]},{8:229,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:230,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,51],25:[2,51],51:231,52:[1,232],75:[2,51]},{6:[2,87],25:[2,87],26:[2,87],52:[2,87],75:[2,87]},{6:[2,37],25:[2,37],26:[2,37],41:[1,233],52:[2,37],75:[2,37]},{6:[2,40],25:[2,40],26:[2,40],52:[2,40],75:[2,40]},{6:[2,41],25:[2,41],26:[2,41],41:[2,41],52:[2,41],75:[2,41]},{6:[2,42],25:[2,42],26:[2,42],41:[2,42],52:[2,42],75:[2,42]},{6:[2,43],25:[2,43],26:[2,43],41:[2,43],52:[2,43],75:[2,43]},{1:[2,5],6:[2,5],26:[2,5],99:[2,5]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],47:[2,25],52:[2,25],55:[2,25],70:[2,25],75:[2,25],83:[2,25],88:[2,25],90:[2,25],95:[2,25],96:[2,25],99:[2,25],101:[2,25],102:[2,25],103:[2,25],107:[2,25],115:[2,25],118:[2,25],120:[2,25],123:[2,25],125:[2,25],126:[2,25],129:[2,25],130:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],47:[2,187],52:[2,187],55:[2,187],70:[2,187],75:[2,187],83:[2,187],88:[2,187],90:[2,187],99:[2,187],100:85,101:[2,187],102:[2,187],103:[2,187],106:86,107:[2,187],108:67,115:[2,187],123:[2,187],125:[2,187],126:[2,187],129:[1,76],130:[1,79],131:[2,187],132:[2,187],133:[2,187],134:[2,187]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],47:[2,188],52:[2,188],55:[2,188],70:[2,188],75:[2,188],83:[2,188],88:[2,188],90:[2,188],99:[2,188],100:85,101:[2,188],102:[2,188],103:[2,188],106:86,107:[2,188],108:67,115:[2,188],123:[2,188],125:[2,188],126:[2,188],129:[1,76],130:[1,79],131:[2,188],132:[2,188],133:[2,188],134:[2,188]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],47:[2,189],52:[2,189],55:[2,189],70:[2,189],75:[2,189],83:[2,189],88:[2,189],90:[2,189],99:[2,189],100:85,101:[2,189],102:[2,189],103:[2,189],106:86,107:[2,189],108:67,115:[2,189],123:[2,189],125:[2,189],126:[2,189],129:[1,76],130:[2,189],131:[2,189],132:[2,189],133:[2,189],134:[2,189]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],47:[2,190],52:[2,190],55:[2,190],70:[2,190],75:[2,190],83:[2,190],88:[2,190],90:[2,190],99:[2,190],100:85,101:[2,190],102:[2,190],103:[2,190],106:86,107:[2,190],108:67,115:[2,190],123:[2,190],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[2,190],132:[2,190],133:[2,190],134:[2,190]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],47:[2,191],52:[2,191],55:[2,191],70:[2,191],75:[2,191],83:[2,191],88:[2,191],90:[2,191],99:[2,191],100:85,101:[2,191],102:[2,191],103:[2,191],106:86,107:[2,191],108:67,115:[2,191],123:[2,191],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[2,191],133:[2,191],134:[1,83]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],47:[2,192],52:[2,192],55:[2,192],70:[2,192],75:[2,192],83:[2,192],88:[2,192],90:[2,192],99:[2,192],100:85,101:[2,192],102:[2,192],103:[2,192],106:86,107:[2,192],108:67,115:[2,192],123:[2,192],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[2,192],134:[1,83]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],47:[2,193],52:[2,193],55:[2,193],70:[2,193],75:[2,193],83:[2,193],88:[2,193],90:[2,193],99:[2,193],100:85,101:[2,193],102:[2,193],103:[2,193],106:86,107:[2,193],108:67,115:[2,193],123:[2,193],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[2,193],133:[2,193],134:[2,193]},{1:[2,178],6:[2,178],25:[2,178],26:[2,178],47:[2,178],52:[2,178],55:[2,178],70:[2,178],75:[2,178],83:[2,178],88:[2,178],90:[2,178],99:[2,178],100:85,101:[1,63],102:[2,178],103:[1,64],106:86,107:[1,66],108:67,115:[2,178],123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,177],6:[2,177],25:[2,177],26:[2,177],47:[2,177],52:[2,177],55:[2,177],70:[2,177],75:[2,177],83:[2,177],88:[2,177],90:[2,177],99:[2,177],100:85,101:[1,63],102:[2,177],103:[1,64],106:86,107:[1,66],108:67,115:[2,177],123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,99],6:[2,99],25:[2,99],26:[2,99],47:[2,99],52:[2,99],55:[2,99],64:[2,99],65:[2,99],66:[2,99],68:[2,99],70:[2,99],71:[2,99],75:[2,99],81:[2,99],82:[2,99],83:[2,99],88:[2,99],90:[2,99],99:[2,99],101:[2,99],102:[2,99],103:[2,99],107:[2,99],115:[2,99],123:[2,99],125:[2,99],126:[2,99],129:[2,99],130:[2,99],131:[2,99],132:[2,99],133:[2,99],134:[2,99]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],38:[2,76],47:[2,76],52:[2,76],55:[2,76],64:[2,76],65:[2,76],66:[2,76],68:[2,76],70:[2,76],71:[2,76],75:[2,76],77:[2,76],81:[2,76],82:[2,76],83:[2,76],88:[2,76],90:[2,76],99:[2,76],101:[2,76],102:[2,76],103:[2,76],107:[2,76],115:[2,76],123:[2,76],125:[2,76],126:[2,76],127:[2,76],128:[2,76],129:[2,76],130:[2,76],131:[2,76],132:[2,76],133:[2,76],134:[2,76],135:[2,76]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],38:[2,77],47:[2,77],52:[2,77],55:[2,77],64:[2,77],65:[2,77],66:[2,77],68:[2,77],70:[2,77],71:[2,77],75:[2,77],77:[2,77],81:[2,77],82:[2,77],83:[2,77],88:[2,77],90:[2,77],99:[2,77],101:[2,77],102:[2,77],103:[2,77],107:[2,77],115:[2,77],123:[2,77],125:[2,77],126:[2,77],127:[2,77],128:[2,77],129:[2,77],130:[2,77],131:[2,77],132:[2,77],133:[2,77],134:[2,77],135:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],38:[2,78],47:[2,78],52:[2,78],55:[2,78],64:[2,78],65:[2,78],66:[2,78],68:[2,78],70:[2,78],71:[2,78],75:[2,78],77:[2,78],81:[2,78],82:[2,78],83:[2,78],88:[2,78],90:[2,78],99:[2,78],101:[2,78],102:[2,78],103:[2,78],107:[2,78],115:[2,78],123:[2,78],125:[2,78],126:[2,78],127:[2,78],128:[2,78],129:[2,78],130:[2,78],131:[2,78],132:[2,78],133:[2,78],134:[2,78],135:[2,78]},{70:[1,234]},{55:[1,189],70:[2,83],89:235,90:[1,188],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{70:[2,84]},{8:236,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,70:[2,118],73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{12:[2,112],28:[2,112],30:[2,112],31:[2,112],33:[2,112],34:[2,112],35:[2,112],36:[2,112],43:[2,112],44:[2,112],45:[2,112],49:[2,112],50:[2,112],70:[2,112],73:[2,112],76:[2,112],80:[2,112],85:[2,112],86:[2,112],87:[2,112],93:[2,112],97:[2,112],98:[2,112],101:[2,112],103:[2,112],105:[2,112],107:[2,112],116:[2,112],122:[2,112],124:[2,112],125:[2,112],126:[2,112],127:[2,112],128:[2,112]},{12:[2,113],28:[2,113],30:[2,113],31:[2,113],33:[2,113],34:[2,113],35:[2,113],36:[2,113],43:[2,113],44:[2,113],45:[2,113],49:[2,113],50:[2,113],70:[2,113],73:[2,113],76:[2,113],80:[2,113],85:[2,113],86:[2,113],87:[2,113],93:[2,113],97:[2,113],98:[2,113],101:[2,113],103:[2,113],105:[2,113],107:[2,113],116:[2,113],122:[2,113],124:[2,113],125:[2,113],126:[2,113],127:[2,113],128:[2,113]},{1:[2,82],6:[2,82],25:[2,82],26:[2,82],38:[2,82],47:[2,82],52:[2,82],55:[2,82],64:[2,82],65:[2,82],66:[2,82],68:[2,82],70:[2,82],71:[2,82],75:[2,82],77:[2,82],81:[2,82],82:[2,82],83:[2,82],88:[2,82],90:[2,82],99:[2,82],101:[2,82],102:[2,82],103:[2,82],107:[2,82],115:[2,82],123:[2,82],125:[2,82],126:[2,82],127:[2,82],128:[2,82],129:[2,82],130:[2,82],131:[2,82],132:[2,82],133:[2,82],134:[2,82],135:[2,82]},{1:[2,100],6:[2,100],25:[2,100],26:[2,100],47:[2,100],52:[2,100],55:[2,100],64:[2,100],65:[2,100],66:[2,100],68:[2,100],70:[2,100],71:[2,100],75:[2,100],81:[2,100],82:[2,100],83:[2,100],88:[2,100],90:[2,100],99:[2,100],101:[2,100],102:[2,100],103:[2,100],107:[2,100],115:[2,100],123:[2,100],125:[2,100],126:[2,100],129:[2,100],130:[2,100],131:[2,100],132:[2,100],133:[2,100],134:[2,100]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],47:[2,34],52:[2,34],55:[2,34],70:[2,34],75:[2,34],83:[2,34],88:[2,34],90:[2,34],99:[2,34],100:85,101:[2,34],102:[2,34],103:[2,34],106:86,107:[2,34],108:67,115:[2,34],123:[2,34],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:237,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:238,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],47:[2,105],52:[2,105],55:[2,105],64:[2,105],65:[2,105],66:[2,105],68:[2,105],70:[2,105],71:[2,105],75:[2,105],81:[2,105],82:[2,105],83:[2,105],88:[2,105],90:[2,105],99:[2,105],101:[2,105],102:[2,105],103:[2,105],107:[2,105],115:[2,105],123:[2,105],125:[2,105],126:[2,105],129:[2,105],130:[2,105],131:[2,105],132:[2,105],133:[2,105],134:[2,105]},{6:[2,51],25:[2,51],51:239,52:[1,222],83:[2,51]},{6:[2,124],25:[2,124],26:[2,124],52:[2,124],55:[1,240],83:[2,124],88:[2,124],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{48:241,49:[1,58],50:[1,59]},{27:107,28:[1,71],42:108,53:242,54:106,56:109,57:110,73:[1,68],86:[1,111],87:[1,112]},{47:[2,57],52:[2,57]},{8:243,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],47:[2,194],52:[2,194],55:[2,194],70:[2,194],75:[2,194],83:[2,194],88:[2,194],90:[2,194],99:[2,194],100:85,101:[2,194],102:[2,194],103:[2,194],106:86,107:[2,194],108:67,115:[2,194],123:[2,194],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:244,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,196],6:[2,196],25:[2,196],26:[2,196],47:[2,196],52:[2,196],55:[2,196],70:[2,196],75:[2,196],83:[2,196],88:[2,196],90:[2,196],99:[2,196],100:85,101:[2,196],102:[2,196],103:[2,196],106:86,107:[2,196],108:67,115:[2,196],123:[2,196],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,176],6:[2,176],25:[2,176],26:[2,176],47:[2,176],52:[2,176],55:[2,176],70:[2,176],75:[2,176],83:[2,176],88:[2,176],90:[2,176],99:[2,176],101:[2,176],102:[2,176],103:[2,176],107:[2,176],115:[2,176],123:[2,176],125:[2,176],126:[2,176],129:[2,176],130:[2,176],131:[2,176],132:[2,176],133:[2,176],134:[2,176]},{8:245,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,129],6:[2,129],25:[2,129],26:[2,129],47:[2,129],52:[2,129],55:[2,129],70:[2,129],75:[2,129],83:[2,129],88:[2,129],90:[2,129],95:[1,246],99:[2,129],101:[2,129],102:[2,129],103:[2,129],107:[2,129],115:[2,129],123:[2,129],125:[2,129],126:[2,129],129:[2,129],130:[2,129],131:[2,129],132:[2,129],133:[2,129],134:[2,129]},{5:247,25:[1,5]},{27:248,28:[1,71]},{117:249,119:212,120:[1,213]},{26:[1,250],118:[1,251],119:252,120:[1,213]},{26:[2,169],118:[2,169],120:[2,169]},{8:254,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],92:253,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,93],5:255,6:[2,93],25:[1,5],26:[2,93],47:[2,93],52:[2,93],55:[2,93],70:[2,93],75:[2,93],83:[2,93],88:[2,93],90:[2,93],99:[2,93],100:85,101:[1,63],102:[2,93],103:[1,64],106:86,107:[1,66],108:67,115:[2,93],123:[2,93],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,96],6:[2,96],25:[2,96],26:[2,96],47:[2,96],52:[2,96],55:[2,96],70:[2,96],75:[2,96],83:[2,96],88:[2,96],90:[2,96],99:[2,96],101:[2,96],102:[2,96],103:[2,96],107:[2,96],115:[2,96],123:[2,96],125:[2,96],126:[2,96],129:[2,96],130:[2,96],131:[2,96],132:[2,96],133:[2,96],134:[2,96]},{8:256,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],47:[2,134],52:[2,134],55:[2,134],64:[2,134],65:[2,134],66:[2,134],68:[2,134],70:[2,134],71:[2,134],75:[2,134],81:[2,134],82:[2,134],83:[2,134],88:[2,134],90:[2,134],99:[2,134],101:[2,134],102:[2,134],103:[2,134],107:[2,134],115:[2,134],123:[2,134],125:[2,134],126:[2,134],129:[2,134],130:[2,134],131:[2,134],132:[2,134],133:[2,134],134:[2,134]},{6:[1,72],26:[1,257]},{8:258,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,63],12:[2,113],25:[2,63],28:[2,113],30:[2,113],31:[2,113],33:[2,113],34:[2,113],35:[2,113],36:[2,113],43:[2,113],44:[2,113],45:[2,113],49:[2,113],50:[2,113],52:[2,63],73:[2,113],76:[2,113],80:[2,113],85:[2,113],86:[2,113],87:[2,113],88:[2,63],93:[2,113],97:[2,113],98:[2,113],101:[2,113],103:[2,113],105:[2,113],107:[2,113],116:[2,113],122:[2,113],124:[2,113],125:[2,113],126:[2,113],127:[2,113],128:[2,113]},{6:[1,260],25:[1,261],88:[1,259]},{6:[2,52],8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[2,52],26:[2,52],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],83:[2,52],85:[1,56],86:[1,57],87:[1,55],88:[2,52],91:262,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,51],25:[2,51],26:[2,51],51:263,52:[1,222]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],47:[2,173],52:[2,173],55:[2,173],70:[2,173],75:[2,173],83:[2,173],88:[2,173],90:[2,173],99:[2,173],101:[2,173],102:[2,173],103:[2,173],107:[2,173],115:[2,173],118:[2,173],123:[2,173],125:[2,173],126:[2,173],129:[2,173],130:[2,173],131:[2,173],132:[2,173],133:[2,173],134:[2,173]},{8:264,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:265,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{113:[2,152],114:[2,152]},{27:156,28:[1,71],56:157,57:158,73:[1,68],87:[1,112],112:266},{1:[2,158],6:[2,158],25:[2,158],26:[2,158],47:[2,158],52:[2,158],55:[2,158],70:[2,158],75:[2,158],83:[2,158],88:[2,158],90:[2,158],99:[2,158],100:85,101:[2,158],102:[1,267],103:[2,158],106:86,107:[2,158],108:67,115:[1,268],123:[2,158],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,159],6:[2,159],25:[2,159],26:[2,159],47:[2,159],52:[2,159],55:[2,159],70:[2,159],75:[2,159],83:[2,159],88:[2,159],90:[2,159],99:[2,159],100:85,101:[2,159],102:[1,269],103:[2,159],106:86,107:[2,159],108:67,115:[2,159],123:[2,159],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,271],25:[1,272],75:[1,270]},{6:[2,52],11:165,25:[2,52],26:[2,52],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:273,40:164,42:168,44:[1,46],75:[2,52],86:[1,111]},{8:274,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,275],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],38:[2,81],47:[2,81],52:[2,81],55:[2,81],64:[2,81],65:[2,81],66:[2,81],68:[2,81],70:[2,81],71:[2,81],75:[2,81],77:[2,81],81:[2,81],82:[2,81],83:[2,81],88:[2,81],90:[2,81],99:[2,81],101:[2,81],102:[2,81],103:[2,81],107:[2,81],115:[2,81],123:[2,81],125:[2,81],126:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81]},{8:276,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,70:[2,116],73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{70:[2,117],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,35],6:[2,35],25:[2,35],26:[2,35],47:[2,35],52:[2,35],55:[2,35],70:[2,35],75:[2,35],83:[2,35],88:[2,35],90:[2,35],99:[2,35],100:85,101:[2,35],102:[2,35],103:[2,35],106:86,107:[2,35],108:67,115:[2,35],123:[2,35],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,277],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,260],25:[1,261],83:[1,278]},{6:[2,63],25:[2,63],26:[2,63],52:[2,63],83:[2,63],88:[2,63]},{5:279,25:[1,5]},{47:[2,55],52:[2,55]},{47:[2,58],52:[2,58],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,280],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{5:281,25:[1,5],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{5:282,25:[1,5]},{1:[2,130],6:[2,130],25:[2,130],26:[2,130],47:[2,130],52:[2,130],55:[2,130],70:[2,130],75:[2,130],83:[2,130],88:[2,130],90:[2,130],99:[2,130],101:[2,130],102:[2,130],103:[2,130],107:[2,130],115:[2,130],123:[2,130],125:[2,130],126:[2,130],129:[2,130],130:[2,130],131:[2,130],132:[2,130],133:[2,130],134:[2,130]},{5:283,25:[1,5]},{26:[1,284],118:[1,285],119:252,120:[1,213]},{1:[2,167],6:[2,167],25:[2,167],26:[2,167],47:[2,167],52:[2,167],55:[2,167],70:[2,167],75:[2,167],83:[2,167],88:[2,167],90:[2,167],99:[2,167],101:[2,167],102:[2,167],103:[2,167],107:[2,167],115:[2,167],123:[2,167],125:[2,167],126:[2,167],129:[2,167],130:[2,167],131:[2,167],132:[2,167],133:[2,167],134:[2,167]},{5:286,25:[1,5]},{26:[2,170],118:[2,170],120:[2,170]},{5:287,25:[1,5],52:[1,288]},{25:[2,126],52:[2,126],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,94],6:[2,94],25:[2,94],26:[2,94],47:[2,94],52:[2,94],55:[2,94],70:[2,94],75:[2,94],83:[2,94],88:[2,94],90:[2,94],99:[2,94],101:[2,94],102:[2,94],103:[2,94],107:[2,94],115:[2,94],123:[2,94],125:[2,94],126:[2,94],129:[2,94],130:[2,94],131:[2,94],132:[2,94],133:[2,94],134:[2,94]},{1:[2,97],5:289,6:[2,97],25:[1,5],26:[2,97],47:[2,97],52:[2,97],55:[2,97],70:[2,97],75:[2,97],83:[2,97],88:[2,97],90:[2,97],99:[2,97],100:85,101:[1,63],102:[2,97],103:[1,64],106:86,107:[1,66],108:67,115:[2,97],123:[2,97],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{99:[1,290]},{88:[1,291],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,111],6:[2,111],25:[2,111],26:[2,111],38:[2,111],47:[2,111],52:[2,111],55:[2,111],64:[2,111],65:[2,111],66:[2,111],68:[2,111],70:[2,111],71:[2,111],75:[2,111],81:[2,111],82:[2,111],83:[2,111],88:[2,111],90:[2,111],99:[2,111],101:[2,111],102:[2,111],103:[2,111],107:[2,111],113:[2,111],114:[2,111],115:[2,111],123:[2,111],125:[2,111],126:[2,111],129:[2,111],130:[2,111],131:[2,111],132:[2,111],133:[2,111],134:[2,111]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],91:292,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:197,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,144],27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,58:145,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],84:293,85:[1,56],86:[1,57],87:[1,55],91:143,93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[2,120],25:[2,120],26:[2,120],52:[2,120],83:[2,120],88:[2,120]},{6:[1,260],25:[1,261],26:[1,294]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],47:[2,137],52:[2,137],55:[2,137],70:[2,137],75:[2,137],83:[2,137],88:[2,137],90:[2,137],99:[2,137],100:85,101:[1,63],102:[2,137],103:[1,64],106:86,107:[1,66],108:67,115:[2,137],123:[2,137],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],47:[2,139],52:[2,139],55:[2,139],70:[2,139],75:[2,139],83:[2,139],88:[2,139],90:[2,139],99:[2,139],100:85,101:[1,63],102:[2,139],103:[1,64],106:86,107:[1,66],108:67,115:[2,139],123:[2,139],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{113:[2,157],114:[2,157]},{8:295,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:296,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:297,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,85],6:[2,85],25:[2,85],26:[2,85],38:[2,85],47:[2,85],52:[2,85],55:[2,85],64:[2,85],65:[2,85],66:[2,85],68:[2,85],70:[2,85],71:[2,85],75:[2,85],81:[2,85],82:[2,85],83:[2,85],88:[2,85],90:[2,85],99:[2,85],101:[2,85],102:[2,85],103:[2,85],107:[2,85],113:[2,85],114:[2,85],115:[2,85],123:[2,85],125:[2,85],126:[2,85],129:[2,85],130:[2,85],131:[2,85],132:[2,85],133:[2,85],134:[2,85]},{11:165,27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:298,40:164,42:168,44:[1,46],86:[1,111]},{6:[2,86],11:165,25:[2,86],26:[2,86],27:166,28:[1,71],29:167,30:[1,69],31:[1,70],39:163,40:164,42:168,44:[1,46],52:[2,86],74:299,86:[1,111]},{6:[2,88],25:[2,88],26:[2,88],52:[2,88],75:[2,88]},{6:[2,38],25:[2,38],26:[2,38],52:[2,38],75:[2,38],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{8:300,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{70:[2,115],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,36],6:[2,36],25:[2,36],26:[2,36],47:[2,36],52:[2,36],55:[2,36],70:[2,36],75:[2,36],83:[2,36],88:[2,36],90:[2,36],99:[2,36],101:[2,36],102:[2,36],103:[2,36],107:[2,36],115:[2,36],123:[2,36],125:[2,36],126:[2,36],129:[2,36],130:[2,36],131:[2,36],132:[2,36],133:[2,36],134:[2,36]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],47:[2,106],52:[2,106],55:[2,106],64:[2,106],65:[2,106],66:[2,106],68:[2,106],70:[2,106],71:[2,106],75:[2,106],81:[2,106],82:[2,106],83:[2,106],88:[2,106],90:[2,106],99:[2,106],101:[2,106],102:[2,106],103:[2,106],107:[2,106],115:[2,106],123:[2,106],125:[2,106],126:[2,106],129:[2,106],130:[2,106],131:[2,106],132:[2,106],133:[2,106],134:[2,106]},{1:[2,47],6:[2,47],25:[2,47],26:[2,47],47:[2,47],52:[2,47],55:[2,47],70:[2,47],75:[2,47],83:[2,47],88:[2,47],90:[2,47],99:[2,47],101:[2,47],102:[2,47],103:[2,47],107:[2,47],115:[2,47],123:[2,47],125:[2,47],126:[2,47],129:[2,47],130:[2,47],131:[2,47],132:[2,47],133:[2,47],134:[2,47]},{1:[2,195],6:[2,195],25:[2,195],26:[2,195],47:[2,195],52:[2,195],55:[2,195],70:[2,195],75:[2,195],83:[2,195],88:[2,195],90:[2,195],99:[2,195],101:[2,195],102:[2,195],103:[2,195],107:[2,195],115:[2,195],123:[2,195],125:[2,195],126:[2,195],129:[2,195],130:[2,195],131:[2,195],132:[2,195],133:[2,195],134:[2,195]},{1:[2,174],6:[2,174],25:[2,174],26:[2,174],47:[2,174],52:[2,174],55:[2,174],70:[2,174],75:[2,174],83:[2,174],88:[2,174],90:[2,174],99:[2,174],101:[2,174],102:[2,174],103:[2,174],107:[2,174],115:[2,174],118:[2,174],123:[2,174],125:[2,174],126:[2,174],129:[2,174],130:[2,174],131:[2,174],132:[2,174],133:[2,174],134:[2,174]},{1:[2,131],6:[2,131],25:[2,131],26:[2,131],47:[2,131],52:[2,131],55:[2,131],70:[2,131],75:[2,131],83:[2,131],88:[2,131],90:[2,131],99:[2,131],101:[2,131],102:[2,131],103:[2,131],107:[2,131],115:[2,131],123:[2,131],125:[2,131],126:[2,131],129:[2,131],130:[2,131],131:[2,131],132:[2,131],133:[2,131],134:[2,131]},{1:[2,132],6:[2,132],25:[2,132],26:[2,132],47:[2,132],52:[2,132],55:[2,132],70:[2,132],75:[2,132],83:[2,132],88:[2,132],90:[2,132],95:[2,132],99:[2,132],101:[2,132],102:[2,132],103:[2,132],107:[2,132],115:[2,132],123:[2,132],125:[2,132],126:[2,132],129:[2,132],130:[2,132],131:[2,132],132:[2,132],133:[2,132],134:[2,132]},{1:[2,165],6:[2,165],25:[2,165],26:[2,165],47:[2,165],52:[2,165],55:[2,165],70:[2,165],75:[2,165],83:[2,165],88:[2,165],90:[2,165],99:[2,165],101:[2,165],102:[2,165],103:[2,165],107:[2,165],115:[2,165],123:[2,165],125:[2,165],126:[2,165],129:[2,165],130:[2,165],131:[2,165],132:[2,165],133:[2,165],134:[2,165]},{5:301,25:[1,5]},{26:[1,302]},{6:[1,303],26:[2,171],118:[2,171],120:[2,171]},{8:304,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{1:[2,98],6:[2,98],25:[2,98],26:[2,98],47:[2,98],52:[2,98],55:[2,98],70:[2,98],75:[2,98],83:[2,98],88:[2,98],90:[2,98],99:[2,98],101:[2,98],102:[2,98],103:[2,98],107:[2,98],115:[2,98],123:[2,98],125:[2,98],126:[2,98],129:[2,98],130:[2,98],131:[2,98],132:[2,98],133:[2,98],134:[2,98]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],47:[2,135],52:[2,135],55:[2,135],64:[2,135],65:[2,135],66:[2,135],68:[2,135],70:[2,135],71:[2,135],75:[2,135],81:[2,135],82:[2,135],83:[2,135],88:[2,135],90:[2,135],99:[2,135],101:[2,135],102:[2,135],103:[2,135],107:[2,135],115:[2,135],123:[2,135],125:[2,135],126:[2,135],129:[2,135],130:[2,135],131:[2,135],132:[2,135],133:[2,135],134:[2,135]},{1:[2,114],6:[2,114],25:[2,114],26:[2,114],47:[2,114],52:[2,114],55:[2,114],64:[2,114],65:[2,114],66:[2,114],68:[2,114],70:[2,114],71:[2,114],75:[2,114],81:[2,114],82:[2,114],83:[2,114],88:[2,114],90:[2,114],99:[2,114],101:[2,114],102:[2,114],103:[2,114],107:[2,114],115:[2,114],123:[2,114],125:[2,114],126:[2,114],129:[2,114],130:[2,114],131:[2,114],132:[2,114],133:[2,114],134:[2,114]},{6:[2,121],25:[2,121],26:[2,121],52:[2,121],83:[2,121],88:[2,121]},{6:[2,51],25:[2,51],26:[2,51],51:305,52:[1,222]},{6:[2,122],25:[2,122],26:[2,122],52:[2,122],83:[2,122],88:[2,122]},{1:[2,160],6:[2,160],25:[2,160],26:[2,160],47:[2,160],52:[2,160],55:[2,160],70:[2,160],75:[2,160],83:[2,160],88:[2,160],90:[2,160],99:[2,160],100:85,101:[2,160],102:[2,160],103:[2,160],106:86,107:[2,160],108:67,115:[1,306],123:[2,160],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,162],6:[2,162],25:[2,162],26:[2,162],47:[2,162],52:[2,162],55:[2,162],70:[2,162],75:[2,162],83:[2,162],88:[2,162],90:[2,162],99:[2,162],100:85,101:[2,162],102:[1,307],103:[2,162],106:86,107:[2,162],108:67,115:[2,162],123:[2,162],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,161],6:[2,161],25:[2,161],26:[2,161],47:[2,161],52:[2,161],55:[2,161],70:[2,161],75:[2,161],83:[2,161],88:[2,161],90:[2,161],99:[2,161],100:85,101:[2,161],102:[2,161],103:[2,161],106:86,107:[2,161],108:67,115:[2,161],123:[2,161],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[2,89],25:[2,89],26:[2,89],52:[2,89],75:[2,89]},{6:[2,51],25:[2,51],26:[2,51],51:308,52:[1,232]},{26:[1,309],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{26:[1,310]},{1:[2,168],6:[2,168],25:[2,168],26:[2,168],47:[2,168],52:[2,168],55:[2,168],70:[2,168],75:[2,168],83:[2,168],88:[2,168],90:[2,168],99:[2,168],101:[2,168],102:[2,168],103:[2,168],107:[2,168],115:[2,168],123:[2,168],125:[2,168],126:[2,168],129:[2,168],130:[2,168],131:[2,168],132:[2,168],133:[2,168],134:[2,168]},{26:[2,172],118:[2,172],120:[2,172]},{25:[2,127],52:[2,127],100:85,101:[1,63],103:[1,64],106:86,107:[1,66],108:67,123:[1,84],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[1,260],25:[1,261],26:[1,311]},{8:312,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{8:313,9:115,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:60,28:[1,71],29:49,30:[1,69],31:[1,70],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:23,42:61,43:[1,45],44:[1,46],45:[1,29],48:30,49:[1,58],50:[1,59],56:47,57:48,59:36,61:25,62:26,63:27,73:[1,68],76:[1,43],80:[1,28],85:[1,56],86:[1,57],87:[1,55],93:[1,38],97:[1,44],98:[1,54],100:39,101:[1,63],103:[1,64],104:40,105:[1,65],106:41,107:[1,66],108:67,116:[1,42],121:37,122:[1,62],124:[1,31],125:[1,32],126:[1,33],127:[1,34],128:[1,35]},{6:[1,271],25:[1,272],26:[1,314]},{6:[2,39],25:[2,39],26:[2,39],52:[2,39],75:[2,39]},{1:[2,166],6:[2,166],25:[2,166],26:[2,166],47:[2,166],52:[2,166],55:[2,166],70:[2,166],75:[2,166],83:[2,166],88:[2,166],90:[2,166],99:[2,166],101:[2,166],102:[2,166],103:[2,166],107:[2,166],115:[2,166],123:[2,166],125:[2,166],126:[2,166],129:[2,166],130:[2,166],131:[2,166],132:[2,166],133:[2,166],134:[2,166]},{6:[2,123],25:[2,123],26:[2,123],52:[2,123],83:[2,123],88:[2,123]},{1:[2,163],6:[2,163],25:[2,163],26:[2,163],47:[2,163],52:[2,163],55:[2,163],70:[2,163],75:[2,163],83:[2,163],88:[2,163],90:[2,163],99:[2,163],100:85,101:[2,163],102:[2,163],103:[2,163],106:86,107:[2,163],108:67,115:[2,163],123:[2,163],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{1:[2,164],6:[2,164],25:[2,164],26:[2,164],47:[2,164],52:[2,164],55:[2,164],70:[2,164],75:[2,164],83:[2,164],88:[2,164],90:[2,164],99:[2,164],100:85,101:[2,164],102:[2,164],103:[2,164],106:86,107:[2,164],108:67,115:[2,164],123:[2,164],125:[1,78],126:[1,77],129:[1,76],130:[1,79],131:[1,80],132:[1,81],133:[1,82],134:[1,83]},{6:[2,90],25:[2,90],26:[2,90],52:[2,90],75:[2,90]}],\ndefaultActions: {58:[2,49],59:[2,50],73:[2,3],92:[2,104],186:[2,84]},\nparseError: function parseError(str, hash) {\n    throw new Error(str);\n},\nparse: function parse(input) {\n    var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = \"\", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;\n    this.lexer.setInput(input);\n    this.lexer.yy = this.yy;\n    this.yy.lexer = this.lexer;\n    if (typeof this.lexer.yylloc == \"undefined\")\n        this.lexer.yylloc = {};\n    var yyloc = this.lexer.yylloc;\n    lstack.push(yyloc);\n    if (typeof this.yy.parseError === \"function\")\n        this.parseError = this.yy.parseError;\n    function popStack(n) {\n        stack.length = stack.length - 2 * n;\n        vstack.length = vstack.length - n;\n        lstack.length = lstack.length - n;\n    }\n    function lex() {\n        var token;\n        token = self.lexer.lex() || 1;\n        if (typeof token !== \"number\") {\n            token = self.symbols_[token] || token;\n        }\n        return token;\n    }\n    var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;\n    while (true) {\n        state = stack[stack.length - 1];\n        if (this.defaultActions[state]) {\n            action = this.defaultActions[state];\n        } else {\n            if (symbol == null)\n                symbol = lex();\n            action = table[state] && table[state][symbol];\n        }\n        if (typeof action === \"undefined\" || !action.length || !action[0]) {\n            if (!recovering) {\n                expected = [];\n                for (p in table[state])\n                    if (this.terminals_[p] && p > 2) {\n                        expected.push(\"'\" + this.terminals_[p] + \"'\");\n                    }\n                var errStr = \"\";\n                if (this.lexer.showPosition) {\n                    errStr = \"Parse error on line \" + (yylineno + 1) + \":\\n\" + this.lexer.showPosition() + \"\\nExpecting \" + expected.join(\", \") + \", got '\" + this.terminals_[symbol] + \"'\";\n                } else {\n                    errStr = \"Parse error on line \" + (yylineno + 1) + \": Unexpected \" + (symbol == 1?\"end of input\":\"'\" + (this.terminals_[symbol] || symbol) + \"'\");\n                }\n                this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});\n            }\n        }\n        if (action[0] instanceof Array && action.length > 1) {\n            throw new Error(\"Parse Error: multiple actions possible at state: \" + state + \", token: \" + symbol);\n        }\n        switch (action[0]) {\n        case 1:\n            stack.push(symbol);\n            vstack.push(this.lexer.yytext);\n            lstack.push(this.lexer.yylloc);\n            stack.push(action[1]);\n            symbol = null;\n            if (!preErrorSymbol) {\n                yyleng = this.lexer.yyleng;\n                yytext = this.lexer.yytext;\n                yylineno = this.lexer.yylineno;\n                yyloc = this.lexer.yylloc;\n                if (recovering > 0)\n                    recovering--;\n            } else {\n                symbol = preErrorSymbol;\n                preErrorSymbol = null;\n            }\n            break;\n        case 2:\n            len = this.productions_[action[1]][1];\n            yyval.$ = vstack[vstack.length - len];\n            yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column};\n            r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);\n            if (typeof r !== \"undefined\") {\n                return r;\n            }\n            if (len) {\n                stack = stack.slice(0, -1 * len * 2);\n                vstack = vstack.slice(0, -1 * len);\n                lstack = lstack.slice(0, -1 * len);\n            }\n            stack.push(this.productions_[action[1]][0]);\n            vstack.push(yyval.$);\n            lstack.push(yyval._$);\n            newState = table[stack[stack.length - 2]][stack[stack.length - 1]];\n            stack.push(newState);\n            break;\n        case 3:\n            return true;\n        }\n    }\n    return true;\n}\n};\n\nmodule.exports = parser;\n\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coffee/parser_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar assert = require(\"../../test/assertions\");\nvar coffee = require(\"../coffee/coffee-script\");\n\n\nmodule.exports = {\n\n    \"test parse valid coffee script\": function() {\n        coffee.parse(\"square = (x) -> x * x\");\n    },\n    \n    \"test parse invalid coffee script\": function() {\n        try {\n            coffee.parse(\"a = 12 f\");\n        } catch (e) {\n            assert.ok((e + \"\").indexOf(\"Parse error on line 1: Unexpected 'IDENTIFIER'\") >= 0);\n        }\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coffee/rewriter.js",
    "content": "/**\n * Copyright (c) 2011 Jeremy Ashkenas\n * \n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n * \n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\ndefine(function(require, exports, module) {\n// Generated by CoffeeScript 1.2.1-pre\n\n  var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref,\n    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },\n    __slice = [].slice;\n\n  exports.Rewriter = (function() {\n\n    Rewriter.name = 'Rewriter';\n\n    function Rewriter() {}\n\n    Rewriter.prototype.rewrite = function(tokens) {\n      this.tokens = tokens;\n      this.removeLeadingNewlines();\n      this.removeMidExpressionNewlines();\n      this.closeOpenCalls();\n      this.closeOpenIndexes();\n      this.addImplicitIndentation();\n      this.tagPostfixConditionals();\n      this.addImplicitBraces();\n      this.addImplicitParentheses();\n      return this.tokens;\n    };\n\n    Rewriter.prototype.scanTokens = function(block) {\n      var i, token, tokens;\n      tokens = this.tokens;\n      i = 0;\n      while (token = tokens[i]) {\n        i += block.call(this, token, i, tokens);\n      }\n      return true;\n    };\n\n    Rewriter.prototype.detectEnd = function(i, condition, action) {\n      var levels, token, tokens, _ref, _ref1;\n      tokens = this.tokens;\n      levels = 0;\n      while (token = tokens[i]) {\n        if (levels === 0 && condition.call(this, token, i)) {\n          return action.call(this, token, i);\n        }\n        if (!token || levels < 0) return action.call(this, token, i - 1);\n        if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) {\n          levels += 1;\n        } else if (_ref1 = token[0], __indexOf.call(EXPRESSION_END, _ref1) >= 0) {\n          levels -= 1;\n        }\n        i += 1;\n      }\n      return i - 1;\n    };\n\n    Rewriter.prototype.removeLeadingNewlines = function() {\n      var i, tag, _i, _len, _ref;\n      _ref = this.tokens;\n      for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {\n        tag = _ref[i][0];\n        if (tag !== 'TERMINATOR') break;\n      }\n      if (i) return this.tokens.splice(0, i);\n    };\n\n    Rewriter.prototype.removeMidExpressionNewlines = function() {\n      return this.scanTokens(function(token, i, tokens) {\n        var _ref;\n        if (!(token[0] === 'TERMINATOR' && (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0))) {\n          return 1;\n        }\n        tokens.splice(i, 1);\n        return 0;\n      });\n    };\n\n    Rewriter.prototype.closeOpenCalls = function() {\n      var action, condition;\n      condition = function(token, i) {\n        var _ref;\n        return ((_ref = token[0]) === ')' || _ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')';\n      };\n      action = function(token, i) {\n        return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';\n      };\n      return this.scanTokens(function(token, i) {\n        if (token[0] === 'CALL_START') this.detectEnd(i + 1, condition, action);\n        return 1;\n      });\n    };\n\n    Rewriter.prototype.closeOpenIndexes = function() {\n      var action, condition;\n      condition = function(token, i) {\n        var _ref;\n        return (_ref = token[0]) === ']' || _ref === 'INDEX_END';\n      };\n      action = function(token, i) {\n        return token[0] = 'INDEX_END';\n      };\n      return this.scanTokens(function(token, i) {\n        if (token[0] === 'INDEX_START') this.detectEnd(i + 1, condition, action);\n        return 1;\n      });\n    };\n\n    Rewriter.prototype.addImplicitBraces = function() {\n      var action, condition, sameLine, stack, start, startIndent, startsLine;\n      stack = [];\n      start = null;\n      startsLine = null;\n      sameLine = true;\n      startIndent = 0;\n      condition = function(token, i) {\n        var one, tag, three, two, _ref, _ref1;\n        _ref = this.tokens.slice(i + 1, (i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];\n        if ('HERECOMMENT' === (one != null ? one[0] : void 0)) return false;\n        tag = token[0];\n        if (__indexOf.call(LINEBREAKS, tag) >= 0) sameLine = false;\n        return (((tag === 'TERMINATOR' || tag === 'OUTDENT') || (__indexOf.call(IMPLICIT_END, tag) >= 0 && sameLine)) && ((!startsLine && this.tag(i - 1) !== ',') || !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':'))) || (tag === ',' && one && ((_ref1 = one[0]) !== 'IDENTIFIER' && _ref1 !== 'NUMBER' && _ref1 !== 'STRING' && _ref1 !== '@' && _ref1 !== 'TERMINATOR' && _ref1 !== 'OUTDENT'));\n      };\n      action = function(token, i) {\n        var tok;\n        tok = this.generate('}', '}', token[2]);\n        return this.tokens.splice(i, 0, tok);\n      };\n      return this.scanTokens(function(token, i, tokens) {\n        var ago, idx, prevTag, tag, tok, value, _ref, _ref1;\n        if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {\n          stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]);\n          return 1;\n        }\n        if (__indexOf.call(EXPRESSION_END, tag) >= 0) {\n          start = stack.pop();\n          return 1;\n        }\n        if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref1 = stack[stack.length - 1]) != null ? _ref1[0] : void 0) !== '{'))) {\n          return 1;\n        }\n        sameLine = true;\n        stack.push(['{']);\n        idx = ago === '@' ? i - 2 : i - 1;\n        while (this.tag(idx - 2) === 'HERECOMMENT') {\n          idx -= 2;\n        }\n        prevTag = this.tag(idx - 1);\n        startsLine = !prevTag || (__indexOf.call(LINEBREAKS, prevTag) >= 0);\n        value = new String('{');\n        value.generated = true;\n        tok = this.generate('{', value, token[2]);\n        tokens.splice(idx, 0, tok);\n        this.detectEnd(i + 2, condition, action);\n        return 2;\n      });\n    };\n\n    Rewriter.prototype.addImplicitParentheses = function() {\n      var action, condition, noCall, seenControl, seenSingle;\n      noCall = seenSingle = seenControl = false;\n      condition = function(token, i) {\n        var post, tag, _ref, _ref1;\n        tag = token[0];\n        if (!seenSingle && token.fromThen) return true;\n        if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>' || tag === 'CLASS') {\n          seenSingle = true;\n        }\n        if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY' || tag === '=') {\n          seenControl = true;\n        }\n        if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {\n          return true;\n        }\n        return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (((_ref = this.tag(i - 2)) !== 'CLASS' && _ref !== 'EXTENDS') && (_ref1 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref1) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));\n      };\n      action = function(token, i) {\n        return this.tokens.splice(i, 0, this.generate('CALL_END', ')', token[2]));\n      };\n      return this.scanTokens(function(token, i, tokens) {\n        var callObject, current, next, prev, tag, _ref, _ref1, _ref2;\n        tag = token[0];\n        if (tag === 'CLASS' || tag === 'IF' || tag === 'FOR' || tag === 'WHILE') {\n          noCall = true;\n        }\n        _ref = tokens.slice(i - 1, (i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];\n        callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref1 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref1) >= 0);\n        seenSingle = false;\n        seenControl = false;\n        if (__indexOf.call(LINEBREAKS, tag) >= 0) noCall = false;\n        if (prev && !prev.spaced && tag === '?') token.call = true;\n        if (token.fromThen) return 1;\n        if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {\n          return 1;\n        }\n        tokens.splice(i, 0, this.generate('CALL_START', '(', token[2]));\n        this.detectEnd(i + 1, condition, action);\n        if (prev[0] === '?') prev[0] = 'FUNC_EXIST';\n        return 2;\n      });\n    };\n\n    Rewriter.prototype.addImplicitIndentation = function() {\n      var action, condition, indent, outdent, starter;\n      starter = indent = outdent = null;\n      condition = function(token, i) {\n        var _ref;\n        return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));\n      };\n      action = function(token, i) {\n        return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);\n      };\n      return this.scanTokens(function(token, i, tokens) {\n        var tag, _ref, _ref1;\n        tag = token[0];\n        if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') {\n          tokens.splice(i, 1);\n          return 0;\n        }\n        if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {\n          tokens.splice.apply(tokens, [i, 0].concat(__slice.call(this.indentation(token))));\n          return 2;\n        }\n        if (tag === 'CATCH' && ((_ref = this.tag(i + 2)) === 'OUTDENT' || _ref === 'TERMINATOR' || _ref === 'FINALLY')) {\n          tokens.splice.apply(tokens, [i + 2, 0].concat(__slice.call(this.indentation(token))));\n          return 4;\n        }\n        if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {\n          starter = tag;\n          _ref1 = this.indentation(token, true), indent = _ref1[0], outdent = _ref1[1];\n          if (starter === 'THEN') indent.fromThen = true;\n          tokens.splice(i + 1, 0, indent);\n          this.detectEnd(i + 2, condition, action);\n          if (tag === 'THEN') tokens.splice(i, 1);\n          return 1;\n        }\n        return 1;\n      });\n    };\n\n    Rewriter.prototype.tagPostfixConditionals = function() {\n      var action, condition, original;\n      original = null;\n      condition = function(token, i) {\n        var _ref;\n        return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT';\n      };\n      action = function(token, i) {\n        if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) {\n          return original[0] = 'POST_' + original[0];\n        }\n      };\n      return this.scanTokens(function(token, i) {\n        if (token[0] !== 'IF') return 1;\n        original = token;\n        this.detectEnd(i + 1, condition, action);\n        return 1;\n      });\n    };\n\n    Rewriter.prototype.indentation = function(token, implicit) {\n      var indent, outdent;\n      if (implicit == null) implicit = false;\n      indent = ['INDENT', 2, token[2]];\n      outdent = ['OUTDENT', 2, token[2]];\n      if (implicit) indent.generated = outdent.generated = true;\n      return [indent, outdent];\n    };\n\n    Rewriter.prototype.generate = function(tag, value, line) {\n      var tok;\n      tok = [tag, value, line];\n      tok.generated = true;\n      return tok;\n    };\n\n    Rewriter.prototype.tag = function(i) {\n      var _ref;\n      return (_ref = this.tokens[i]) != null ? _ref[0] : void 0;\n    };\n\n    return Rewriter;\n\n  })();\n\n  BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']];\n\n  exports.INVERSES = INVERSES = {};\n\n  EXPRESSION_START = [];\n\n  EXPRESSION_END = [];\n\n  for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) {\n    _ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1];\n    EXPRESSION_START.push(INVERSES[rite] = left);\n    EXPRESSION_END.push(INVERSES[left] = rite);\n  }\n\n  EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);\n\n  IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];\n\n  IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++'];\n\n  IMPLICIT_UNSPACED_CALL = ['+', '-'];\n\n  IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];\n\n  IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];\n\n  SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];\n\n  SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];\n\n  LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];\n\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coffee/scope.js",
    "content": "/**\n * Copyright (c) 2011 Jeremy Ashkenas\n * \n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n * \n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\ndefine(function(require, exports, module) {\n// Generated by CoffeeScript 1.2.1-pre\n\n  var Scope, extend, last, _ref;\n\n  _ref = require('./helpers'), extend = _ref.extend, last = _ref.last;\n\n  exports.Scope = Scope = (function() {\n\n    Scope.name = 'Scope';\n\n    Scope.root = null;\n\n    function Scope(parent, expressions, method) {\n      this.parent = parent;\n      this.expressions = expressions;\n      this.method = method;\n      this.variables = [\n        {\n          name: 'arguments',\n          type: 'arguments'\n        }\n      ];\n      this.positions = {};\n      if (!this.parent) Scope.root = this;\n    }\n\n    Scope.prototype.add = function(name, type, immediate) {\n      if (this.shared && !immediate) return this.parent.add(name, type, immediate);\n      if (Object.prototype.hasOwnProperty.call(this.positions, name)) {\n        return this.variables[this.positions[name]].type = type;\n      } else {\n        return this.positions[name] = this.variables.push({\n          name: name,\n          type: type\n        }) - 1;\n      }\n    };\n\n    Scope.prototype.find = function(name, options) {\n      if (this.check(name, options)) return true;\n      this.add(name, 'var');\n      return false;\n    };\n\n    Scope.prototype.parameter = function(name) {\n      if (this.shared && this.parent.check(name, true)) return;\n      return this.add(name, 'param');\n    };\n\n    Scope.prototype.check = function(name, immediate) {\n      var found, _ref1;\n      found = !!this.type(name);\n      if (found || immediate) return found;\n      return !!((_ref1 = this.parent) != null ? _ref1.check(name) : void 0);\n    };\n\n    Scope.prototype.temporary = function(name, index) {\n      if (name.length > 1) {\n        return '_' + name + (index > 1 ? index - 1 : '');\n      } else {\n        return '_' + (index + parseInt(name, 36)).toString(36).replace(/\\d/g, 'a');\n      }\n    };\n\n    Scope.prototype.type = function(name) {\n      var v, _i, _len, _ref1;\n      _ref1 = this.variables;\n      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n        v = _ref1[_i];\n        if (v.name === name) return v.type;\n      }\n      return null;\n    };\n\n    Scope.prototype.freeVariable = function(name, reserve) {\n      var index, temp;\n      if (reserve == null) reserve = true;\n      index = 0;\n      while (this.check((temp = this.temporary(name, index)))) {\n        index++;\n      }\n      if (reserve) this.add(temp, 'var', true);\n      return temp;\n    };\n\n    Scope.prototype.assign = function(name, value) {\n      this.add(name, {\n        value: value,\n        assigned: true\n      }, true);\n      return this.hasAssignments = true;\n    };\n\n    Scope.prototype.hasDeclarations = function() {\n      return !!this.declaredVariables().length;\n    };\n\n    Scope.prototype.declaredVariables = function() {\n      var realVars, tempVars, v, _i, _len, _ref1;\n      realVars = [];\n      tempVars = [];\n      _ref1 = this.variables;\n      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n        v = _ref1[_i];\n        if (v.type === 'var') {\n          (v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);\n        }\n      }\n      return realVars.sort().concat(tempVars.sort());\n    };\n\n    Scope.prototype.assignedVariables = function() {\n      var v, _i, _len, _ref1, _results;\n      _ref1 = this.variables;\n      _results = [];\n      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n        v = _ref1[_i];\n        if (v.type.assigned) _results.push(\"\" + v.name + \" = \" + v.type.value);\n      }\n      return _results;\n    };\n\n    return Scope;\n\n  })();\n\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coffee.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Satoshi Murakami <murky.satyr AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar Rules = require(\"./coffee_highlight_rules\").CoffeeHighlightRules;\nvar Outdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar PythonFoldMode = require(\"./folding/pythonic\").FoldMode;\nvar Range = require(\"../range\").Range;\nvar TextMode = require(\"./text\").Mode;\nvar WorkerClient = require(\"../worker/worker_client\").WorkerClient;\nvar oop = require(\"../lib/oop\");\n\nfunction Mode() {\n    this.$tokenizer = new Tokenizer(new Rules().getRules());\n    this.$outdent   = new Outdent();\n    this.foldingRules = new PythonFoldMode(\"=|=>|->|\\\\s*class [^#]*\");\n}\n\noop.inherits(Mode, TextMode);\n\n(function() {\n    \n    var indenter = /(?:[({[=:]|[-=]>|\\b(?:else|switch|try|catch(?:\\s*[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*)?|finally))\\s*$/;\n    var commentLine = /^(\\s*)#/;\n    var hereComment = /^\\s*###(?!#)/;\n    var indentation = /^\\s*/;\n    \n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n        var tokens = this.$tokenizer.getLineTokens(line, state).tokens;\n    \n        if (!(tokens.length && tokens[tokens.length - 1].type === 'comment') &&\n            state === 'start' && indenter.test(line))\n            indent += tab;\n        return indent;\n    };\n    \n    this.toggleCommentLines = function(state, doc, startRow, endRow){\n        console.log(\"toggle\");\n        var range = new Range(0, 0, 0, 0);\n        for (var i = startRow; i <= endRow; ++i) {\n            var line = doc.getLine(i);\n            if (hereComment.test(line))\n                continue;\n                \n            if (commentLine.test(line))\n                line = line.replace(commentLine, '$1');\n            else\n                line = line.replace(indentation, '$&#');\n    \n            range.end.row = range.start.row = i;\n            range.end.column = line.length + 1;\n            doc.replace(range, line);\n        }\n    };\n    \n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n    \n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n    \n    this.createWorker = function(session) {\n        var worker = new WorkerClient([\"ace\"], \"worker-coffee.js\", \"ace/mode/coffee_worker\", \"Worker\");\n        worker.attachToDocument(session.getDocument());\n        \n        worker.on(\"error\", function(e) {\n            session.setAnnotations([e.data]);\n        });\n        \n        worker.on(\"ok\", function(e) {\n            session.clearAnnotations();\n        });\n        \n        return worker;\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coffee_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Satoshi Murakami <murky.satyr AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\n    var lang = require(\"../lib/lang\");\n    var oop = require(\"../lib/oop\");\n    var TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n    \n    oop.inherits(CoffeeHighlightRules, TextHighlightRules);\n\n    function CoffeeHighlightRules() {\n        var identifier = \"[$A-Za-z_\\\\x7f-\\\\uffff][$\\\\w\\\\x7f-\\\\uffff]*\";\n        var stringfill = {\n            token : \"string\",\n            merge : true,\n            regex : \".+\"\n        };\n\n        var keywords = lang.arrayToMap((\n            \"this|throw|then|try|typeof|super|switch|return|break|by)|continue|\" +\n            \"catch|class|in|instanceof|is|isnt|if|else|extends|for|forown|\" +\n            \"finally|function|while|when|new|no|not|delete|debugger|do|loop|of|off|\" +\n            \"or|on|unless|until|and|yes\").split(\"|\")\n        );\n        \n        var langConstant = lang.arrayToMap((\n            \"true|false|null|undefined\").split(\"|\")\n        );\n        \n        var illegal = lang.arrayToMap((\n            \"case|const|default|function|var|void|with|enum|export|implements|\" +\n            \"interface|let|package|private|protected|public|static|yield|\" +\n            \"__hasProp|extends|slice|bind|indexOf\").split(\"|\")\n        );\n        \n        var supportClass = lang.arrayToMap((\n            \"Array|Boolean|Date|Function|Number|Object|RegExp|ReferenceError|\" +\n            \"RangeError|String|SyntaxError|Error|EvalError|TypeError|URIError\").split(\"|\")\n        );\n        \n        var supportFunction = lang.arrayToMap((\n            \"Math|JSON|isNaN|isFinite|parseInt|parseFloat|encodeURI|\" +\n            \"encodeURIComponent|decodeURI|decodeURIComponent|RangeError|String|\" +\n            \"SyntaxError|Error|EvalError|TypeError|URIError\").split(\"|\")\n        );\n\n        this.$rules = {\n            start : [\n                {\n                    token : \"identifier\",\n                    regex : \"(?:(?:\\\\.|::)\\\\s*)\" + identifier\n                }, {\n                    token : \"variable\",\n                    regex : \"@(?:\" + identifier + \")?\"\n                }, {\n                    token: function(value) {\n                        if (keywords.hasOwnProperty(value))\n                            return \"keyword\";\n                        else if (langConstant.hasOwnProperty(value))\n                            return \"constant.language\";\n                        else if (illegal.hasOwnProperty(value))\n                            return \"invalid.illegal\";\n                        else if (supportClass.hasOwnProperty(value))\n                            return \"language.support.class\";\n                        else if (supportFunction.hasOwnProperty(value))\n                            return \"language.support.function\";\n                        else\n                            return \"identifier\";\n                    },\n                    regex : identifier\n                }, {\n                    token : \"constant.numeric\",\n                    regex : \"(?:0x[\\\\da-fA-F]+|(?:\\\\d+(?:\\\\.\\\\d+)?|\\\\.\\\\d+)(?:[eE][+-]?\\\\d+)?)\"\n                }, {\n                    token : \"string\",\n                    merge : true,\n                    regex : \"'''\",\n                    next : \"qdoc\"\n                }, {\n                    token : \"string\",\n                    merge : true,\n                    regex : '\"\"\"',\n                    next : \"qqdoc\"\n                }, {\n                    token : \"string\",\n                    merge : true,\n                    regex : \"'\",\n                    next : \"qstring\"\n                }, {\n                    token : \"string\",\n                    merge : true,\n                    regex : '\"',\n                    next : \"qqstring\"\n                }, {\n                    token : \"string\",\n                    merge : true,\n                    regex : \"`\",\n                    next : \"js\"\n                }, {\n                    token : \"string.regex\",\n                    merge : true,\n                    regex : \"///\",\n                    next : \"heregex\"\n                }, {\n                    token : \"string.regex\",\n                    regex : \"/(?!\\\\s)[^[/\\\\n\\\\\\\\]*(?: (?:\\\\\\\\.|\\\\[[^\\\\]\\\\n\\\\\\\\]*(?:\\\\\\\\.[^\\\\]\\\\n\\\\\\\\]*)*\\\\])[^[/\\\\n\\\\\\\\]*)*/[imgy]{0,4}(?!\\\\w)\"\n                }, {\n                    token : \"comment\",\n                    merge : true,\n                    regex : \"###(?!#)\",\n                    next : \"comment\"\n                }, {\n                    token : \"comment\",\n                    regex : \"#.*\"\n                }, {\n                    token : \"punctuation.operator\",\n                    regex : \"\\\\?|\\\\:|\\\\,|\\\\.\"\n                }, {\n                    token : \"keyword.operator\",\n                    regex : \"(?:[\\\\-=]>|[-+*/%<>&|^!?=]=|>>>=?|\\\\-\\\\-|\\\\+\\\\+|::|&&=|\\\\|\\\\|=|<<=|>>=|\\\\?\\\\.|\\\\.{2,3}|\\\\!)\"\n                }, {\n                    token : \"paren.lparen\",\n                    regex : \"[({[]\"\n                }, {\n                    token : \"paren.rparen\",\n                    regex : \"[\\\\]})]\"\n                }, {\n                    token : \"text\",\n                    regex : \"\\\\s+\"\n                }],\n            \n            qdoc : [{\n                token : \"string\",\n                regex : \".*?'''\",\n                next : \"start\"\n            }, stringfill],\n            \n            qqdoc : [{\n                token : \"string\",\n                regex : '.*?\"\"\"',\n                next : \"start\"\n            }, stringfill],\n            \n            qstring : [{\n                token : \"string\",\n                regex : \"[^\\\\\\\\']*(?:\\\\\\\\.[^\\\\\\\\']*)*'\",\n                merge : true,\n                next : \"start\"\n            }, stringfill],\n            \n            qqstring : [{\n                token : \"string\",\n                regex : '[^\\\\\\\\\"]*(?:\\\\\\\\.[^\\\\\\\\\"]*)*\"',\n                merge : true,\n                next : \"start\"\n            }, stringfill],\n            \n            js : [{\n                token : \"string\",\n                merge : true,\n                regex : \"[^\\\\\\\\`]*(?:\\\\\\\\.[^\\\\\\\\`]*)*`\",\n                next : \"start\"\n            }, stringfill],\n            \n            heregex : [{\n                token : \"string.regex\",\n                regex : '.*?///[imgy]{0,4}',\n                next : \"start\"\n            }, {\n                token : \"comment.regex\",\n                regex : \"\\\\s+(?:#.*)?\"\n            }, {\n                token : \"string.regex\",\n                merge : true,\n                regex : \"\\\\S+\"\n            }],\n            \n            comment : [{\n                token : \"comment\",\n                regex : '.*?###',\n                next : \"start\"\n            }, {\n                token : \"comment\",\n                merge : true,\n                regex : \".+\"\n            }]\n        };\n    }\n\n    exports.CoffeeHighlightRules = CoffeeHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coffee_highlight_rules_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Mode = require(\"./coffee\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n    setUp : function() {\n        this.tokenizer = new Mode().getTokenizer();\n    },\n\n    \"test: tokenize keyword\": function() {\n        var tokens = this.tokenizer.getLineTokens(\"for\", \"start\").tokens;\n        assert.equal(tokens.length, 1);\n        assert.equal(tokens[0].type, \"keyword\");\n    },\n    \n    // TODO: disable. not yet implemented\n    \"!test tokenize string with interpolation\": function() {\n        var tokens = this.tokenizer.getLineTokens('\"#{ 22 / 7 } is a decent approximation of π\"', \"start\").tokens;\n        console.log(tokens);\n        assert.equal(tokens.length, 12);\n        //assert.equal(tokens[0].type, \"keyword\");\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coffee_worker.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar Mirror = require(\"../worker/mirror\").Mirror;\nvar coffee = require(\"../mode/coffee/coffee-script\");\n\nwindow.addEventListener = function() {};\n\n\nvar Worker = exports.Worker = function(sender) {\n    Mirror.call(this, sender);\n    this.setTimeout(200);\n};\n\noop.inherits(Worker, Mirror);\n\n(function() {\n\n    this.onUpdate = function() {\n        var value = this.doc.getValue();\n\n        try {\n            coffee.parse(value);\n        } catch(e) {\n            var m = e.message.match(/Parse error on line (\\d+): (.*)/);\n            if (m) {\n                this.sender.emit(\"error\", {\n                    row: parseInt(m[1], 10) - 1,\n                    column: null,\n                    text: m[2],\n                    type: \"error\"\n                });\n                return;\n            }\n\n            if (e instanceof SyntaxError) {\n                var m = e.message.match(/ on line (\\d+)/);\n                if (m) {\n                    this.sender.emit(\"error\", {\n                        row: parseInt(m[1], 10) - 1,\n                        column: null,\n                        text: e.message.replace(m[0], \"\"),\n                        type: \"error\"\n                    });\n                }\n            }\n            return;\n        }\n        this.sender.emit(\"ok\");\n    };\n\n}).call(Worker.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coldfusion.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar XmlMode = require(\"./xml\").Mode;\nvar JavaScriptMode = require(\"./javascript\").Mode;\nvar CssMode = require(\"./css\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar ColdfusionHighlightRules = require(\"./coldfusion_highlight_rules\").ColdfusionHighlightRules;\n\nvar Mode = function() {\n    XmlMode.call(this);\n    \n    var highlighter = new ColdfusionHighlightRules();\n    this.$tokenizer = new Tokenizer(highlighter.getRules());\n    \n    this.$embeds = highlighter.getEmbeds();\n    this.createModeDelegates({\n      \"js-\": JavaScriptMode,\n      \"css-\": CssMode\n    });\n};\noop.inherits(Mode, XmlMode);\n\n(function() {\n\n    this.getNextLineIndent = function(state, line, tab) {\n        return this.$getIndent(line);\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coldfusion_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar CssHighlightRules = require(\"./css_highlight_rules\").CssHighlightRules;\nvar JavaScriptHighlightRules = require(\"./javascript_highlight_rules\").JavaScriptHighlightRules;\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\nvar xml_util = require(\"./xml_util\");\n\nvar ColdfusionHighlightRules = function() {\n\n    // regexp must not have capturing parentheses\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        start : [ {\n            token : \"text\",\n            merge : true,\n            regex : \"<\\\\!\\\\[CDATA\\\\[\",\n            next : \"cdata\"\n        }, {\n            token : \"xml_pe\",\n            regex : \"<\\\\?.*?\\\\?>\"\n        }, {\n            token : \"comment\",\n            merge : true,\n            regex : \"<\\\\!--\",\n            next : \"comment\"\n        }, {\n            token : \"meta.tag\",\n            regex : \"<(?=\\s*script)\",\n            next : \"script\"\n        }, {\n            token : \"meta.tag\",\n            regex : \"<(?=\\s*style)\",\n            next : \"style\"\n        }, {\n            token : \"meta.tag\", // opening tag\n            regex : \"<\\\\/?\",\n            next : \"tag\"\n        }, {\n            token : \"text\",\n            regex : \"\\\\s+\"\n        }, {\n            token : \"text\",\n            regex : \"[^<]+\"\n        } ],\n    \n        cdata : [ {\n            token : \"text\",\n            regex : \"\\\\]\\\\]>\",\n            next : \"start\"\n        }, {\n            token : \"text\",\n            merge : true,\n            regex : \"\\\\s+\"\n        }, {\n            token : \"text\",\n            merge : true,\n            regex : \".+\"\n        } ],\n\n        comment : [ {\n            token : \"comment\",\n            regex : \".*?-->\",\n            next : \"start\"\n        }, {\n            token : \"comment\",\n            merge : true,\n            regex : \".+\"\n        } ]\n    };\n    \n    xml_util.tag(this.$rules, \"tag\", \"start\");\n    xml_util.tag(this.$rules, \"style\", \"css-start\");\n    xml_util.tag(this.$rules, \"script\", \"js-start\");\n    \n    this.embedRules(JavaScriptHighlightRules, \"js-\", [{\n        token: \"comment\",\n        regex: \"\\\\/\\\\/.*(?=<\\\\/script>)\",\n        next: \"tag\"\n    }, {\n        token: \"meta.tag\",\n        regex: \"<\\\\/(?=script)\",\n        next: \"tag\"\n    }]);\n    \n    this.embedRules(CssHighlightRules, \"css-\", [{\n        token: \"meta.tag\",\n        regex: \"<\\\\/(?=style)\",\n        next: \"tag\"\n    }]);\n};\n\noop.inherits(ColdfusionHighlightRules, TextHighlightRules);\n\nexports.ColdfusionHighlightRules = ColdfusionHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/coldfusion_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"../edit_session\").EditSession;\nvar Range = require(\"../range\").Range;\nvar ColdfusionMode = require(\"./coldfusion\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n    setUp : function() {    \n        this.mode = new ColdfusionMode();\n    },\n\n    \"test: toggle comment lines should not do anything\" : function() {\n        var session = new EditSession([\"  abc\", \"cde\", \"fg\"]);\n\n        var range = new Range(0, 3, 1, 1);\n        var comment = this.mode.toggleCommentLines(\"start\", session, 0, 1);\n        assert.equal([\"  abc\", \"cde\", \"fg\"].join(\"\\n\"), session.toString());\n    },\n\n    \"test: next line indent should be the same as the current line indent\" : function() {\n        assert.equal(\"     \", this.mode.getNextLineIndent(\"start\", \"     abc\"));\n        assert.equal(\"\", this.mode.getNextLineIndent(\"start\", \"abc\"));\n        assert.equal(\"\\t\", this.mode.getNextLineIndent(\"start\", \"\\tabc\"));\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/csharp.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar CSharpHighlightRules = require(\"./csharp_highlight_rules\").CSharpHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar CstyleBehaviour = require(\"./behaviour/cstyle\").CstyleBehaviour;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new CSharpHighlightRules().getRules());\n    this.$outdent = new MatchingBraceOutdent();\n    this.$behaviour = new CstyleBehaviour();\n    this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n    \n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n  \n        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n  \n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n    \n        if (state == \"start\") {\n            var match = line.match(/^.*[\\{\\(\\[]\\s*$/);\n            if (match) {\n                indent += tab;\n            }\n        }\n  \n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n  \n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n\n    this.createWorker = function(session) {\n        return null;\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/csharp_highlight_rules.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar DocCommentHighlightRules = require(\"./doc_comment_highlight_rules\").DocCommentHighlightRules;\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar CSharpHighlightRules = function() {\n    \n    var keywords = lang.arrayToMap(\n    (\"abstract|event|new|struct|as|explicit|null|switch|base|extern|object|this|bool|false|operator|throw|break|finally|out|true|byte|fixed|override|try|case|float|params|typeof|catch|for|private|uint|char|foreach|protected|ulong|checked|goto|public|unchecked|class|if|readonly|unsafe|const|implicit|ref|ushort|continue|in|return|using|decimal|int|sbyte|virtual|default|interface|sealed|volatile|delegate|internal|short|void|do|is|sizeof|while|double|lock|stackalloc|else|long|static|enum|namespace|string|var|dynamic\").split(\"|\")\n    );\n\n    var buildinConstants = lang.arrayToMap(\n        (\"null|true|false\").split(\"|\")\n    );\n\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \"\\\\/\\\\/.*$\"\n            },\n            new DocCommentHighlightRules().getStartRule(\"doc-start\"),\n            {\n                token : \"comment\", // multi line comment\n                regex : \"\\\\/\\\\*\",\n                merge : true,\n                next : \"comment\"\n            }, {\n                token : \"string.regexp\",\n                regex : \"[/](?:(?:\\\\[(?:\\\\\\\\]|[^\\\\]])+\\\\])|(?:\\\\\\\\/|[^\\\\]/]))*[/]\\\\w*\\\\s*(?=[).,;]|$)\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n                token : \"constant.language.boolean\",\n                regex : \"(?:true|false)\\\\b\"\n            }, {\n                token : function(value) {\n                    if (value == \"this\")\n                        return \"variable.language\";\n                    else if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (buildinConstants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else\n                        return \"identifier\";\n                },\n                // TODO: Unicode escape sequences\n                // TODO: Unicode identifiers\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"!|\\\\$|%|&|\\\\*|\\\\-\\\\-|\\\\-|\\\\+\\\\+|\\\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\\\|\\\\||\\\\?\\\\:|\\\\*=|%=|\\\\+=|\\\\-=|&=|\\\\^=|\\\\b(?:in|instanceof|new|delete|typeof|void)\"\n            }, {\n                token : \"punctuation.operator\",\n                regex : \"\\\\?|\\\\:|\\\\,|\\\\;|\\\\.\"\n            }, {\n                token : \"paren.lparen\",\n                regex : \"[[({]\"\n            }, {\n                token : \"paren.rparen\",\n                regex : \"[\\\\])}]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ]\n    };\n    \n    this.embedRules(DocCommentHighlightRules, \"doc-\",\n        [ new DocCommentHighlightRules().getEndRule(\"start\") ]);\n};\n\noop.inherits(CSharpHighlightRules, TextHighlightRules);\n\nexports.CSharpHighlightRules = CSharpHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/css/csslint.js",
    "content": "define(function(require, exports, module) {\n/*!\nCSSLint\nCopyright (c) 2011 Nicole Sullivan and Nicholas C. Zakas. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n/* Build time: 2-March-2012 02:47:11 */\n\n/*!\nParser-Lib\nCopyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n/* Version v0.1.6, Build time: 2-March-2012 02:44:32 */\nvar parserlib = {};\n(function(){\n\n\n/**\n * A generic base to inherit from for any object\n * that needs event handling.\n * @class EventTarget\n * @constructor\n */\nfunction EventTarget(){\n\n    /**\n     * The array of listeners for various events.\n     * @type Object\n     * @property _listeners\n     * @private\n     */\n    this._listeners = {};    \n}\n\nEventTarget.prototype = {\n\n    //restore constructor\n    constructor: EventTarget,\n\n    /**\n     * Adds a listener for a given event type.\n     * @param {String} type The type of event to add a listener for.\n     * @param {Function} listener The function to call when the event occurs.\n     * @return {void}\n     * @method addListener\n     */\n    addListener: function(type, listener){\n        if (!this._listeners[type]){\n            this._listeners[type] = [];\n        }\n\n        this._listeners[type].push(listener);\n    },\n    \n    /**\n     * Fires an event based on the passed-in object.\n     * @param {Object|String} event An object with at least a 'type' attribute\n     *      or a string indicating the event name.\n     * @return {void}\n     * @method fire\n     */    \n    fire: function(event){\n        if (typeof event == \"string\"){\n            event = { type: event };\n        }\n        if (typeof event.target != \"undefined\"){\n            event.target = this;\n        }\n        \n        if (typeof event.type == \"undefined\"){\n            throw new Error(\"Event object missing 'type' property.\");\n        }\n        \n        if (this._listeners[event.type]){\n        \n            //create a copy of the array and use that so listeners can't chane\n            var listeners = this._listeners[event.type].concat();\n            for (var i=0, len=listeners.length; i < len; i++){\n                listeners[i].call(this, event);\n            }\n        }            \n    },\n\n    /**\n     * Removes a listener for a given event type.\n     * @param {String} type The type of event to remove a listener from.\n     * @param {Function} listener The function to remove from the event.\n     * @return {void}\n     * @method removeListener\n     */\n    removeListener: function(type, listener){\n        if (this._listeners[type]){\n            var listeners = this._listeners[type];\n            for (var i=0, len=listeners.length; i < len; i++){\n                if (listeners[i] === listener){\n                    listeners.splice(i, 1);\n                    break;\n                }\n            }\n            \n            \n        }            \n    }\n};\n/**\n * Convenient way to read through strings.\n * @namespace parserlib.util\n * @class StringReader\n * @constructor\n * @param {String} text The text to read.\n */\nfunction StringReader(text){\n\n    /**\n     * The input text with line endings normalized.\n     * @property _input\n     * @type String\n     * @private\n     */\n    this._input = text.replace(/\\n\\r?/g, \"\\n\");\n\n\n    /**\n     * The row for the character to be read next.\n     * @property _line\n     * @type int\n     * @private\n     */\n    this._line = 1;\n\n\n    /**\n     * The column for the character to be read next.\n     * @property _col\n     * @type int\n     * @private\n     */\n    this._col = 1;\n\n    /**\n     * The index of the character in the input to be read next.\n     * @property _cursor\n     * @type int\n     * @private\n     */\n    this._cursor = 0;\n}\n\nStringReader.prototype = {\n\n    //restore constructor\n    constructor: StringReader,\n\n    //-------------------------------------------------------------------------\n    // Position info\n    //-------------------------------------------------------------------------\n\n    /**\n     * Returns the column of the character to be read next.\n     * @return {int} The column of the character to be read next.\n     * @method getCol\n     */\n    getCol: function(){\n        return this._col;\n    },\n\n    /**\n     * Returns the row of the character to be read next.\n     * @return {int} The row of the character to be read next.\n     * @method getLine\n     */\n    getLine: function(){\n        return this._line ;\n    },\n\n    /**\n     * Determines if you're at the end of the input.\n     * @return {Boolean} True if there's no more input, false otherwise.\n     * @method eof\n     */\n    eof: function(){\n        return (this._cursor == this._input.length);\n    },\n\n    //-------------------------------------------------------------------------\n    // Basic reading\n    //-------------------------------------------------------------------------\n\n    /**\n     * Reads the next character without advancing the cursor.\n     * @param {int} count How many characters to look ahead (default is 1).\n     * @return {String} The next character or null if there is no next character.\n     * @method peek\n     */\n    peek: function(count){\n        var c = null;\n        count = (typeof count == \"undefined\" ? 1 : count);\n\n        //if we're not at the end of the input...\n        if (this._cursor < this._input.length){\n\n            //get character and increment cursor and column\n            c = this._input.charAt(this._cursor + count - 1);\n        }\n\n        return c;\n    },\n\n    /**\n     * Reads the next character from the input and adjusts the row and column\n     * accordingly.\n     * @return {String} The next character or null if there is no next character.\n     * @method read\n     */\n    read: function(){\n        var c = null;\n\n        //if we're not at the end of the input...\n        if (this._cursor < this._input.length){\n\n            //if the last character was a newline, increment row count\n            //and reset column count\n            if (this._input.charAt(this._cursor) == \"\\n\"){\n                this._line++;\n                this._col=1;\n            } else {\n                this._col++;\n            }\n\n            //get character and increment cursor and column\n            c = this._input.charAt(this._cursor++);\n        }\n\n        return c;\n    },\n\n    //-------------------------------------------------------------------------\n    // Misc\n    //-------------------------------------------------------------------------\n\n    /**\n     * Saves the current location so it can be returned to later.\n     * @method mark\n     * @return {void}\n     */\n    mark: function(){\n        this._bookmark = {\n            cursor: this._cursor,\n            line:   this._line,\n            col:    this._col\n        };\n    },\n\n    reset: function(){\n        if (this._bookmark){\n            this._cursor = this._bookmark.cursor;\n            this._line = this._bookmark.line;\n            this._col = this._bookmark.col;\n            delete this._bookmark;\n        }\n    },\n\n    //-------------------------------------------------------------------------\n    // Advanced reading\n    //-------------------------------------------------------------------------\n\n    /**\n     * Reads up to and including the given string. Throws an error if that\n     * string is not found.\n     * @param {String} pattern The string to read.\n     * @return {String} The string when it is found.\n     * @throws Error when the string pattern is not found.\n     * @method readTo\n     */\n    readTo: function(pattern){\n\n        var buffer = \"\",\n            c;\n\n        /*\n         * First, buffer must be the same length as the pattern.\n         * Then, buffer must end with the pattern or else reach the\n         * end of the input.\n         */\n        while (buffer.length < pattern.length || buffer.lastIndexOf(pattern) != buffer.length - pattern.length){\n            c = this.read();\n            if (c){\n                buffer += c;\n            } else {\n                throw new Error(\"Expected \\\"\" + pattern + \"\\\" at line \" + this._line  + \", col \" + this._col + \".\");\n            }\n        }\n\n        return buffer;\n\n    },\n\n    /**\n     * Reads characters while each character causes the given\n     * filter function to return true. The function is passed\n     * in each character and either returns true to continue\n     * reading or false to stop.\n     * @param {Function} filter The function to read on each character.\n     * @return {String} The string made up of all characters that passed the\n     *      filter check.\n     * @method readWhile\n     */\n    readWhile: function(filter){\n\n        var buffer = \"\",\n            c = this.read();\n\n        while(c !== null && filter(c)){\n            buffer += c;\n            c = this.read();\n        }\n\n        return buffer;\n\n    },\n\n    /**\n     * Reads characters that match either text or a regular expression and\n     * returns those characters. If a match is found, the row and column\n     * are adjusted; if no match is found, the reader's state is unchanged.\n     * reading or false to stop.\n     * @param {String|RegExp} matchter If a string, then the literal string\n     *      value is searched for. If a regular expression, then any string\n     *      matching the pattern is search for.\n     * @return {String} The string made up of all characters that matched or\n     *      null if there was no match.\n     * @method readMatch\n     */\n    readMatch: function(matcher){\n\n        var source = this._input.substring(this._cursor),\n            value = null;\n\n        //if it's a string, just do a straight match\n        if (typeof matcher == \"string\"){\n            if (source.indexOf(matcher) === 0){\n                value = this.readCount(matcher.length);\n            }\n        } else if (matcher instanceof RegExp){\n            if (matcher.test(source)){\n                value = this.readCount(RegExp.lastMatch.length);\n            }\n        }\n\n        return value;\n    },\n\n\n    /**\n     * Reads a given number of characters. If the end of the input is reached,\n     * it reads only the remaining characters and does not throw an error.\n     * @param {int} count The number of characters to read.\n     * @return {String} The string made up the read characters.\n     * @method readCount\n     */\n    readCount: function(count){\n        var buffer = \"\";\n\n        while(count--){\n            buffer += this.read();\n        }\n\n        return buffer;\n    }\n\n};\n/**\n * Type to use when a syntax error occurs.\n * @class SyntaxError\n * @namespace parserlib.util\n * @constructor\n * @param {String} message The error message.\n * @param {int} line The line at which the error occurred.\n * @param {int} col The column at which the error occurred.\n */\nfunction SyntaxError(message, line, col){\n\n    /**\n     * The column at which the error occurred.\n     * @type int\n     * @property col\n     */\n    this.col = col;\n\n    /**\n     * The line at which the error occurred.\n     * @type int\n     * @property line\n     */\n    this.line = line;\n\n    /**\n     * The text representation of the unit.\n     * @type String\n     * @property text\n     */\n    this.message = message;\n\n}\n\n//inherit from Error\nSyntaxError.prototype = new Error();\n/**\n * Base type to represent a single syntactic unit.\n * @class SyntaxUnit\n * @namespace parserlib.util\n * @constructor\n * @param {String} text The text of the unit.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction SyntaxUnit(text, line, col, type){\n\n\n    /**\n     * The column of text on which the unit resides.\n     * @type int\n     * @property col\n     */\n    this.col = col;\n\n    /**\n     * The line of text on which the unit resides.\n     * @type int\n     * @property line\n     */\n    this.line = line;\n\n    /**\n     * The text representation of the unit.\n     * @type String\n     * @property text\n     */\n    this.text = text;\n\n    /**\n     * The type of syntax unit.\n     * @type int\n     * @property type\n     */\n    this.type = type;\n}\n\n/**\n * Create a new syntax unit based solely on the given token.\n * Convenience method for creating a new syntax unit when\n * it represents a single token instead of multiple.\n * @param {Object} token The token object to represent.\n * @return {parserlib.util.SyntaxUnit} The object representing the token.\n * @static\n * @method fromToken\n */\nSyntaxUnit.fromToken = function(token){\n    return new SyntaxUnit(token.value, token.startLine, token.startCol);\n};\n\nSyntaxUnit.prototype = {\n\n    //restore constructor\n    constructor: SyntaxUnit,\n    \n    /**\n     * Returns the text representation of the unit.\n     * @return {String} The text representation of the unit.\n     * @method valueOf\n     */\n    valueOf: function(){\n        return this.toString();\n    },\n    \n    /**\n     * Returns the text representation of the unit.\n     * @return {String} The text representation of the unit.\n     * @method toString\n     */\n    toString: function(){\n        return this.text;\n    }\n\n};\n/*global StringReader, SyntaxError*/\n\n/**\n * Generic TokenStream providing base functionality.\n * @class TokenStreamBase\n * @namespace parserlib.util\n * @constructor\n * @param {String|StringReader} input The text to tokenize or a reader from \n *      which to read the input.\n */\nfunction TokenStreamBase(input, tokenData){\n\n    /**\n     * The string reader for easy access to the text.\n     * @type StringReader\n     * @property _reader\n     * @private\n     */\n    this._reader = input ? new StringReader(input.toString()) : null;\n    \n    /**\n     * Token object for the last consumed token.\n     * @type Token\n     * @property _token\n     * @private\n     */\n    this._token = null;    \n    \n    /**\n     * The array of token information.\n     * @type Array\n     * @property _tokenData\n     * @private\n     */\n    this._tokenData = tokenData;\n    \n    /**\n     * Lookahead token buffer.\n     * @type Array\n     * @property _lt\n     * @private\n     */\n    this._lt = [];\n    \n    /**\n     * Lookahead token buffer index.\n     * @type int\n     * @property _ltIndex\n     * @private\n     */\n    this._ltIndex = 0;\n    \n    this._ltIndexCache = [];\n}\n\n/**\n * Accepts an array of token information and outputs\n * an array of token data containing key-value mappings\n * and matching functions that the TokenStream needs.\n * @param {Array} tokens An array of token descriptors.\n * @return {Array} An array of processed token data.\n * @method createTokenData\n * @static\n */\nTokenStreamBase.createTokenData = function(tokens){\n\n    var nameMap     = [],\n        typeMap     = {},\n        tokenData     = tokens.concat([]),\n        i            = 0,\n        len            = tokenData.length+1;\n    \n    tokenData.UNKNOWN = -1;\n    tokenData.unshift({name:\"EOF\"});\n\n    for (; i < len; i++){\n        nameMap.push(tokenData[i].name);\n        tokenData[tokenData[i].name] = i;\n        if (tokenData[i].text){\n            typeMap[tokenData[i].text] = i;\n        }\n    }\n    \n    tokenData.name = function(tt){\n        return nameMap[tt];\n    };\n    \n    tokenData.type = function(c){\n        return typeMap[c];\n    };\n    \n    return tokenData;\n};\n\nTokenStreamBase.prototype = {\n\n    //restore constructor\n    constructor: TokenStreamBase,    \n    \n    //-------------------------------------------------------------------------\n    // Matching methods\n    //-------------------------------------------------------------------------\n    \n    /**\n     * Determines if the next token matches the given token type.\n     * If so, that token is consumed; if not, the token is placed\n     * back onto the token stream. You can pass in any number of\n     * token types and this will return true if any of the token\n     * types is found.\n     * @param {int|int[]} tokenTypes Either a single token type or an array of\n     *      token types that the next token might be. If an array is passed,\n     *      it's assumed that the token can be any of these.\n     * @param {variant} channel (Optional) The channel to read from. If not\n     *      provided, reads from the default (unnamed) channel.\n     * @return {Boolean} True if the token type matches, false if not.\n     * @method match\n     */\n    match: function(tokenTypes, channel){\n    \n        //always convert to an array, makes things easier\n        if (!(tokenTypes instanceof Array)){\n            tokenTypes = [tokenTypes];\n        }\n                \n        var tt  = this.get(channel),\n            i   = 0,\n            len = tokenTypes.length;\n            \n        while(i < len){\n            if (tt == tokenTypes[i++]){\n                return true;\n            }\n        }\n        \n        //no match found, put the token back\n        this.unget();\n        return false;\n    },    \n    \n    /**\n     * Determines if the next token matches the given token type.\n     * If so, that token is consumed; if not, an error is thrown.\n     * @param {int|int[]} tokenTypes Either a single token type or an array of\n     *      token types that the next token should be. If an array is passed,\n     *      it's assumed that the token must be one of these.\n     * @param {variant} channel (Optional) The channel to read from. If not\n     *      provided, reads from the default (unnamed) channel.\n     * @return {void}\n     * @method mustMatch\n     */    \n    mustMatch: function(tokenTypes, channel){\n\n        var token;\n\n        //always convert to an array, makes things easier\n        if (!(tokenTypes instanceof Array)){\n            tokenTypes = [tokenTypes];\n        }\n\n        if (!this.match.apply(this, arguments)){    \n            token = this.LT(1);\n            throw new SyntaxError(\"Expected \" + this._tokenData[tokenTypes[0]].name + \n                \" at line \" + token.startLine + \", col \" + token.startCol + \".\", token.startLine, token.startCol);\n        }\n    },\n    \n    //-------------------------------------------------------------------------\n    // Consuming methods\n    //-------------------------------------------------------------------------\n    \n    /**\n     * Keeps reading from the token stream until either one of the specified\n     * token types is found or until the end of the input is reached.\n     * @param {int|int[]} tokenTypes Either a single token type or an array of\n     *      token types that the next token should be. If an array is passed,\n     *      it's assumed that the token must be one of these.\n     * @param {variant} channel (Optional) The channel to read from. If not\n     *      provided, reads from the default (unnamed) channel.\n     * @return {void}\n     * @method advance\n     */\n    advance: function(tokenTypes, channel){\n        \n        while(this.LA(0) !== 0 && !this.match(tokenTypes, channel)){\n            this.get();\n        }\n\n        return this.LA(0);    \n    },\n    \n    /**\n     * Consumes the next token from the token stream. \n     * @return {int} The token type of the token that was just consumed.\n     * @method get\n     */      \n    get: function(channel){\n    \n        var tokenInfo   = this._tokenData,\n            reader      = this._reader,\n            value,\n            i           =0,\n            len         = tokenInfo.length,\n            found       = false,\n            token,\n            info;\n            \n        //check the lookahead buffer first\n        if (this._lt.length && this._ltIndex >= 0 && this._ltIndex < this._lt.length){  \n                           \n            i++;\n            this._token = this._lt[this._ltIndex++];\n            info = tokenInfo[this._token.type];\n            \n            //obey channels logic\n            while((info.channel !== undefined && channel !== info.channel) &&\n                    this._ltIndex < this._lt.length){\n                this._token = this._lt[this._ltIndex++];\n                info = tokenInfo[this._token.type];\n                i++;\n            }\n            \n            //here be dragons\n            if ((info.channel === undefined || channel === info.channel) &&\n                    this._ltIndex <= this._lt.length){\n                this._ltIndexCache.push(i);\n                return this._token.type;\n            }\n        }\n        \n        //call token retriever method\n        token = this._getToken();\n\n        //if it should be hidden, don't save a token\n        if (token.type > -1 && !tokenInfo[token.type].hide){\n                     \n            //apply token channel\n            token.channel = tokenInfo[token.type].channel;\n         \n            //save for later\n            this._token = token;\n            this._lt.push(token);\n\n            //save space that will be moved (must be done before array is truncated)\n            this._ltIndexCache.push(this._lt.length - this._ltIndex + i);  \n        \n            //keep the buffer under 5 items\n            if (this._lt.length > 5){\n                this._lt.shift();                \n            }\n            \n            //also keep the shift buffer under 5 items\n            if (this._ltIndexCache.length > 5){\n                this._ltIndexCache.shift();\n            }\n                \n            //update lookahead index\n            this._ltIndex = this._lt.length;\n        }\n            \n        /*\n         * Skip to the next token if:\n         * 1. The token type is marked as hidden.\n         * 2. The token type has a channel specified and it isn't the current channel.\n         */\n        info = tokenInfo[token.type];\n        if (info && \n                (info.hide || \n                (info.channel !== undefined && channel !== info.channel))){\n            return this.get(channel);\n        } else {\n            //return just the type\n            return token.type;\n        }\n    },\n    \n    /**\n     * Looks ahead a certain number of tokens and returns the token type at\n     * that position. This will throw an error if you lookahead past the\n     * end of input, past the size of the lookahead buffer, or back past\n     * the first token in the lookahead buffer.\n     * @param {int} The index of the token type to retrieve. 0 for the\n     *      current token, 1 for the next, -1 for the previous, etc.\n     * @return {int} The token type of the token in the given position.\n     * @method LA\n     */\n    LA: function(index){\n        var total = index,\n            tt;\n        if (index > 0){\n            //TODO: Store 5 somewhere\n            if (index > 5){\n                throw new Error(\"Too much lookahead.\");\n            }\n        \n            //get all those tokens\n            while(total){\n                tt = this.get();   \n                total--;                            \n            }\n            \n            //unget all those tokens\n            while(total < index){\n                this.unget();\n                total++;\n            }\n        } else if (index < 0){\n        \n            if(this._lt[this._ltIndex+index]){\n                tt = this._lt[this._ltIndex+index].type;\n            } else {\n                throw new Error(\"Too much lookbehind.\");\n            }\n        \n        } else {\n            tt = this._token.type;\n        }\n        \n        return tt;\n    \n    },\n    \n    /**\n     * Looks ahead a certain number of tokens and returns the token at\n     * that position. This will throw an error if you lookahead past the\n     * end of input, past the size of the lookahead buffer, or back past\n     * the first token in the lookahead buffer.\n     * @param {int} The index of the token type to retrieve. 0 for the\n     *      current token, 1 for the next, -1 for the previous, etc.\n     * @return {Object} The token of the token in the given position.\n     * @method LA\n     */    \n    LT: function(index){\n    \n        //lookahead first to prime the token buffer\n        this.LA(index);\n        \n        //now find the token, subtract one because _ltIndex is already at the next index\n        return this._lt[this._ltIndex+index-1];    \n    },\n    \n    /**\n     * Returns the token type for the next token in the stream without \n     * consuming it.\n     * @return {int} The token type of the next token in the stream.\n     * @method peek\n     */\n    peek: function(){\n        return this.LA(1);\n    },\n    \n    /**\n     * Returns the actual token object for the last consumed token.\n     * @return {Token} The token object for the last consumed token.\n     * @method token\n     */\n    token: function(){\n        return this._token;\n    },\n    \n    /**\n     * Returns the name of the token for the given token type.\n     * @param {int} tokenType The type of token to get the name of.\n     * @return {String} The name of the token or \"UNKNOWN_TOKEN\" for any\n     *      invalid token type.\n     * @method tokenName\n     */\n    tokenName: function(tokenType){\n        if (tokenType < 0 || tokenType > this._tokenData.length){\n            return \"UNKNOWN_TOKEN\";\n        } else {\n            return this._tokenData[tokenType].name;\n        }\n    },\n    \n    /**\n     * Returns the token type value for the given token name.\n     * @param {String} tokenName The name of the token whose value should be returned.\n     * @return {int} The token type value for the given token name or -1\n     *      for an unknown token.\n     * @method tokenName\n     */    \n    tokenType: function(tokenName){\n        return this._tokenData[tokenName] || -1;\n    },\n    \n    /**\n     * Returns the last consumed token to the token stream.\n     * @method unget\n     */      \n    unget: function(){\n        //if (this._ltIndex > -1){\n        if (this._ltIndexCache.length){\n            this._ltIndex -= this._ltIndexCache.pop();//--;\n            this._token = this._lt[this._ltIndex - 1];\n        } else {\n            throw new Error(\"Too much lookahead.\");\n        }\n    }\n\n};\n\n\n\n\nparserlib.util = {\nStringReader: StringReader,\nSyntaxError : SyntaxError,\nSyntaxUnit  : SyntaxUnit,\nEventTarget : EventTarget,\nTokenStreamBase : TokenStreamBase\n};\n})();\n\n\n/* \nParser-Lib\nCopyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n/* Version v0.1.6, Build time: 2-March-2012 02:44:32 */\n(function(){\nvar EventTarget = parserlib.util.EventTarget,\nTokenStreamBase = parserlib.util.TokenStreamBase,\nStringReader = parserlib.util.StringReader,\nSyntaxError = parserlib.util.SyntaxError,\nSyntaxUnit  = parserlib.util.SyntaxUnit;\n\n\nvar Colors = {\n    aliceblue       :\"#f0f8ff\",\n    antiquewhite    :\"#faebd7\",\n    aqua            :\"#00ffff\",\n    aquamarine      :\"#7fffd4\",\n    azure           :\"#f0ffff\",\n    beige           :\"#f5f5dc\",\n    bisque          :\"#ffe4c4\",\n    black           :\"#000000\",\n    blanchedalmond  :\"#ffebcd\",\n    blue            :\"#0000ff\",\n    blueviolet      :\"#8a2be2\",\n    brown           :\"#a52a2a\",\n    burlywood       :\"#deb887\",\n    cadetblue       :\"#5f9ea0\",\n    chartreuse      :\"#7fff00\",\n    chocolate       :\"#d2691e\",\n    coral           :\"#ff7f50\",\n    cornflowerblue  :\"#6495ed\",\n    cornsilk        :\"#fff8dc\",\n    crimson         :\"#dc143c\",\n    cyan            :\"#00ffff\",\n    darkblue        :\"#00008b\",\n    darkcyan        :\"#008b8b\",\n    darkgoldenrod   :\"#b8860b\",\n    darkgray        :\"#a9a9a9\",\n    darkgreen       :\"#006400\",\n    darkkhaki       :\"#bdb76b\",\n    darkmagenta     :\"#8b008b\",\n    darkolivegreen  :\"#556b2f\",\n    darkorange      :\"#ff8c00\",\n    darkorchid      :\"#9932cc\",\n    darkred         :\"#8b0000\",\n    darksalmon      :\"#e9967a\",\n    darkseagreen    :\"#8fbc8f\",\n    darkslateblue   :\"#483d8b\",\n    darkslategray   :\"#2f4f4f\",\n    darkturquoise   :\"#00ced1\",\n    darkviolet      :\"#9400d3\",\n    deeppink        :\"#ff1493\",\n    deepskyblue     :\"#00bfff\",\n    dimgray         :\"#696969\",\n    dodgerblue      :\"#1e90ff\",\n    firebrick       :\"#b22222\",\n    floralwhite     :\"#fffaf0\",\n    forestgreen     :\"#228b22\",\n    fuchsia         :\"#ff00ff\",\n    gainsboro       :\"#dcdcdc\",\n    ghostwhite      :\"#f8f8ff\",\n    gold            :\"#ffd700\",\n    goldenrod       :\"#daa520\",\n    gray            :\"#808080\",\n    green           :\"#008000\",\n    greenyellow     :\"#adff2f\",\n    honeydew        :\"#f0fff0\",\n    hotpink         :\"#ff69b4\",\n    indianred       :\"#cd5c5c\",\n    indigo          :\"#4b0082\",\n    ivory           :\"#fffff0\",\n    khaki           :\"#f0e68c\",\n    lavender        :\"#e6e6fa\",\n    lavenderblush   :\"#fff0f5\",\n    lawngreen       :\"#7cfc00\",\n    lemonchiffon    :\"#fffacd\",\n    lightblue       :\"#add8e6\",\n    lightcoral      :\"#f08080\",\n    lightcyan       :\"#e0ffff\",\n    lightgoldenrodyellow  :\"#fafad2\",\n    lightgray       :\"#d3d3d3\",\n    lightgreen      :\"#90ee90\",\n    lightpink       :\"#ffb6c1\",\n    lightsalmon     :\"#ffa07a\",\n    lightseagreen   :\"#20b2aa\",\n    lightskyblue    :\"#87cefa\",\n    lightslategray  :\"#778899\",\n    lightsteelblue  :\"#b0c4de\",\n    lightyellow     :\"#ffffe0\",\n    lime            :\"#00ff00\",\n    limegreen       :\"#32cd32\",\n    linen           :\"#faf0e6\",\n    magenta         :\"#ff00ff\",\n    maroon          :\"#800000\",\n    mediumaquamarine:\"#66cdaa\",\n    mediumblue      :\"#0000cd\",\n    mediumorchid    :\"#ba55d3\",\n    mediumpurple    :\"#9370d8\",\n    mediumseagreen  :\"#3cb371\",\n    mediumslateblue :\"#7b68ee\",\n    mediumspringgreen   :\"#00fa9a\",\n    mediumturquoise :\"#48d1cc\",\n    mediumvioletred :\"#c71585\",\n    midnightblue    :\"#191970\",\n    mintcream       :\"#f5fffa\",\n    mistyrose       :\"#ffe4e1\",\n    moccasin        :\"#ffe4b5\",\n    navajowhite     :\"#ffdead\",\n    navy            :\"#000080\",\n    oldlace         :\"#fdf5e6\",\n    olive           :\"#808000\",\n    olivedrab       :\"#6b8e23\",\n    orange          :\"#ffa500\",\n    orangered       :\"#ff4500\",\n    orchid          :\"#da70d6\",\n    palegoldenrod   :\"#eee8aa\",\n    palegreen       :\"#98fb98\",\n    paleturquoise   :\"#afeeee\",\n    palevioletred   :\"#d87093\",\n    papayawhip      :\"#ffefd5\",\n    peachpuff       :\"#ffdab9\",\n    peru            :\"#cd853f\",\n    pink            :\"#ffc0cb\",\n    plum            :\"#dda0dd\",\n    powderblue      :\"#b0e0e6\",\n    purple          :\"#800080\",\n    red             :\"#ff0000\",\n    rosybrown       :\"#bc8f8f\",\n    royalblue       :\"#4169e1\",\n    saddlebrown     :\"#8b4513\",\n    salmon          :\"#fa8072\",\n    sandybrown      :\"#f4a460\",\n    seagreen        :\"#2e8b57\",\n    seashell        :\"#fff5ee\",\n    sienna          :\"#a0522d\",\n    silver          :\"#c0c0c0\",\n    skyblue         :\"#87ceeb\",\n    slateblue       :\"#6a5acd\",\n    slategray       :\"#708090\",\n    snow            :\"#fffafa\",\n    springgreen     :\"#00ff7f\",\n    steelblue       :\"#4682b4\",\n    tan             :\"#d2b48c\",\n    teal            :\"#008080\",\n    thistle         :\"#d8bfd8\",\n    tomato          :\"#ff6347\",\n    turquoise       :\"#40e0d0\",\n    violet          :\"#ee82ee\",\n    wheat           :\"#f5deb3\",\n    white           :\"#ffffff\",\n    whitesmoke      :\"#f5f5f5\",\n    yellow          :\"#ffff00\",\n    yellowgreen     :\"#9acd32\"\n};\n/*global SyntaxUnit, Parser*/\n/**\n * Represents a selector combinator (whitespace, +, >).\n * @namespace parserlib.css\n * @class Combinator\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} text The text representation of the unit. \n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction Combinator(text, line, col){\n    \n    SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE);\n\n    /**\n     * The type of modifier.\n     * @type String\n     * @property type\n     */\n    this.type = \"unknown\";\n    \n    //pretty simple\n    if (/^\\s+$/.test(text)){\n        this.type = \"descendant\";\n    } else if (text == \">\"){\n        this.type = \"child\";\n    } else if (text == \"+\"){\n        this.type = \"adjacent-sibling\";\n    } else if (text == \"~\"){\n        this.type = \"sibling\";\n    }\n\n}\n\nCombinator.prototype = new SyntaxUnit();\nCombinator.prototype.constructor = Combinator;\n\n\n/*global SyntaxUnit, Parser*/\n/**\n * Represents a media feature, such as max-width:500.\n * @namespace parserlib.css\n * @class MediaFeature\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {SyntaxUnit} name The name of the feature.\n * @param {SyntaxUnit} value The value of the feature or null if none.\n */\nfunction MediaFeature(name, value){\n    \n    SyntaxUnit.call(this, \"(\" + name + (value !== null ? \":\" + value : \"\") + \")\", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE);\n\n    /**\n     * The name of the media feature\n     * @type String\n     * @property name\n     */\n    this.name = name;\n\n    /**\n     * The value for the feature or null if there is none.\n     * @type SyntaxUnit\n     * @property value\n     */\n    this.value = value;\n}\n\nMediaFeature.prototype = new SyntaxUnit();\nMediaFeature.prototype.constructor = MediaFeature;\n\n\n/*global SyntaxUnit, Parser*/\n/**\n * Represents an individual media query.\n * @namespace parserlib.css\n * @class MediaQuery\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} modifier The modifier \"not\" or \"only\" (or null).\n * @param {String} mediaType The type of media (i.e., \"print\").\n * @param {Array} parts Array of selectors parts making up this selector.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction MediaQuery(modifier, mediaType, features, line, col){\n    \n    SyntaxUnit.call(this, (modifier ? modifier + \" \": \"\") + (mediaType ? mediaType + \" \" : \"\") + features.join(\" and \"), line, col, Parser.MEDIA_QUERY_TYPE);\n\n    /**\n     * The media modifier (\"not\" or \"only\")\n     * @type String\n     * @property modifier\n     */\n    this.modifier = modifier;\n\n    /**\n     * The mediaType (i.e., \"print\")\n     * @type String\n     * @property mediaType\n     */\n    this.mediaType = mediaType;    \n    \n    /**\n     * The parts that make up the selector.\n     * @type Array\n     * @property features\n     */\n    this.features = features;\n\n}\n\nMediaQuery.prototype = new SyntaxUnit();\nMediaQuery.prototype.constructor = MediaQuery;\n\n\n/*global Tokens, TokenStream, SyntaxError, Properties, Validation, ValidationError, SyntaxUnit,\n    PropertyValue, PropertyValuePart, SelectorPart, SelectorSubPart, Selector,\n    PropertyName, Combinator, MediaFeature, MediaQuery, EventTarget */\n\n/**\n * A CSS3 parser.\n * @namespace parserlib.css\n * @class Parser\n * @constructor\n * @param {Object} options (Optional) Various options for the parser:\n *      starHack (true|false) to allow IE6 star hack as valid,\n *      underscoreHack (true|false) to interpret leading underscores\n *      as IE6-7 targeting for known properties, ieFilters (true|false)\n *      to indicate that IE < 8 filters should be accepted and not throw\n *      syntax errors.\n */\nfunction Parser(options){\n\n    //inherit event functionality\n    EventTarget.call(this);\n\n\n    this.options = options || {};\n\n    this._tokenStream = null;\n}\n\n//Static constants\nParser.DEFAULT_TYPE = 0;\nParser.COMBINATOR_TYPE = 1;\nParser.MEDIA_FEATURE_TYPE = 2;\nParser.MEDIA_QUERY_TYPE = 3;\nParser.PROPERTY_NAME_TYPE = 4;\nParser.PROPERTY_VALUE_TYPE = 5;\nParser.PROPERTY_VALUE_PART_TYPE = 6;\nParser.SELECTOR_TYPE = 7;\nParser.SELECTOR_PART_TYPE = 8;\nParser.SELECTOR_SUB_PART_TYPE = 9;\n\nParser.prototype = function(){\n\n    var proto = new EventTarget(),  //new prototype\n        prop,\n        additions =  {\n        \n            //restore constructor\n            constructor: Parser,\n                        \n            //instance constants - yuck\n            DEFAULT_TYPE : 0,\n            COMBINATOR_TYPE : 1,\n            MEDIA_FEATURE_TYPE : 2,\n            MEDIA_QUERY_TYPE : 3,\n            PROPERTY_NAME_TYPE : 4,\n            PROPERTY_VALUE_TYPE : 5,\n            PROPERTY_VALUE_PART_TYPE : 6,\n            SELECTOR_TYPE : 7,\n            SELECTOR_PART_TYPE : 8,\n            SELECTOR_SUB_PART_TYPE : 9,            \n        \n            //-----------------------------------------------------------------\n            // Grammar\n            //-----------------------------------------------------------------\n        \n            _stylesheet: function(){\n            \n                /*\n                 * stylesheet\n                 *  : [ CHARSET_SYM S* STRING S* ';' ]?\n                 *    [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*\n                 *    [ namespace [S|CDO|CDC]* ]*\n                 *    [ [ ruleset | media | page | font_face | keyframes ] [S|CDO|CDC]* ]*\n                 *  ;\n                 */ \n               \n                var tokenStream = this._tokenStream,\n                    charset     = null,\n                    count,\n                    token,\n                    tt;\n                    \n                this.fire(\"startstylesheet\");\n            \n                //try to read character set\n                this._charset();\n                \n                this._skipCruft();\n\n                //try to read imports - may be more than one\n                while (tokenStream.peek() == Tokens.IMPORT_SYM){\n                    this._import();\n                    this._skipCruft();\n                }\n                \n                //try to read namespaces - may be more than one\n                while (tokenStream.peek() == Tokens.NAMESPACE_SYM){\n                    this._namespace();\n                    this._skipCruft();\n                }\n                \n                //get the next token\n                tt = tokenStream.peek();\n                \n                //try to read the rest\n                while(tt > Tokens.EOF){\n                \n                    try {\n                \n                        switch(tt){\n                            case Tokens.MEDIA_SYM:\n                                this._media();\n                                this._skipCruft();\n                                break;\n                            case Tokens.PAGE_SYM:\n                                this._page(); \n                                this._skipCruft();\n                                break;                   \n                            case Tokens.FONT_FACE_SYM:\n                                this._font_face(); \n                                this._skipCruft();\n                                break;  \n                            case Tokens.KEYFRAMES_SYM:\n                                this._keyframes(); \n                                this._skipCruft();\n                                break;                                \n                            case Tokens.UNKNOWN_SYM:  //unknown @ rule\n                                tokenStream.get();\n                                if (!this.options.strict){\n                                \n                                    //fire error event\n                                    this.fire({\n                                        type:       \"error\",\n                                        error:      null,\n                                        message:    \"Unknown @ rule: \" + tokenStream.LT(0).value + \".\",\n                                        line:       tokenStream.LT(0).startLine,\n                                        col:        tokenStream.LT(0).startCol\n                                    });                          \n                                    \n                                    //skip braces\n                                    count=0;\n                                    while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) == Tokens.LBRACE){\n                                        count++;    //keep track of nesting depth\n                                    }\n                                    \n                                    while(count){\n                                        tokenStream.advance([Tokens.RBRACE]);\n                                        count--;\n                                    }\n                                    \n                                } else {\n                                    //not a syntax error, rethrow it\n                                    throw new SyntaxError(\"Unknown @ rule.\", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);\n                                }                                \n                                break;\n                            case Tokens.S:\n                                this._readWhitespace();\n                                break;\n                            default:                            \n                                if(!this._ruleset()){\n                                \n                                    //error handling for known issues\n                                    switch(tt){\n                                        case Tokens.CHARSET_SYM:\n                                            token = tokenStream.LT(1);\n                                            this._charset(false);\n                                            throw new SyntaxError(\"@charset not allowed here.\", token.startLine, token.startCol);\n                                        case Tokens.IMPORT_SYM:\n                                            token = tokenStream.LT(1);\n                                            this._import(false);\n                                            throw new SyntaxError(\"@import not allowed here.\", token.startLine, token.startCol);\n                                        case Tokens.NAMESPACE_SYM:\n                                            token = tokenStream.LT(1);\n                                            this._namespace(false);\n                                            throw new SyntaxError(\"@namespace not allowed here.\", token.startLine, token.startCol);\n                                        default:\n                                            tokenStream.get();  //get the last token\n                                            this._unexpectedToken(tokenStream.token());\n                                    }\n                                \n                                }\n                        }\n                    } catch(ex) {\n                        if (ex instanceof SyntaxError && !this.options.strict){\n                            this.fire({\n                                type:       \"error\",\n                                error:      ex,\n                                message:    ex.message,\n                                line:       ex.line,\n                                col:        ex.col\n                            });                     \n                        } else {\n                            throw ex;\n                        }\n                    }\n                    \n                    tt = tokenStream.peek();\n                }\n                \n                if (tt != Tokens.EOF){\n                    this._unexpectedToken(tokenStream.token());\n                }\n            \n                this.fire(\"endstylesheet\");\n            },\n            \n            _charset: function(emit){\n                var tokenStream = this._tokenStream,\n                    charset,\n                    token,\n                    line,\n                    col;\n                    \n                if (tokenStream.match(Tokens.CHARSET_SYM)){\n                    line = tokenStream.token().startLine;\n                    col = tokenStream.token().startCol;\n                \n                    this._readWhitespace();\n                    tokenStream.mustMatch(Tokens.STRING);\n                    \n                    token = tokenStream.token();\n                    charset = token.value;\n                    \n                    this._readWhitespace();\n                    tokenStream.mustMatch(Tokens.SEMICOLON);\n                    \n                    if (emit !== false){\n                        this.fire({ \n                            type:   \"charset\",\n                            charset:charset,\n                            line:   line,\n                            col:    col\n                        });\n                    }\n                }            \n            },\n            \n            _import: function(emit){\n                /*\n                 * import\n                 *   : IMPORT_SYM S*\n                 *    [STRING|URI] S* media_query_list? ';' S*\n                 */    \n            \n                var tokenStream = this._tokenStream,\n                    tt,\n                    uri,\n                    importToken,\n                    mediaList   = [];\n                \n                //read import symbol\n                tokenStream.mustMatch(Tokens.IMPORT_SYM);\n                importToken = tokenStream.token();\n                this._readWhitespace();\n                \n                tokenStream.mustMatch([Tokens.STRING, Tokens.URI]);\n                \n                //grab the URI value\n                uri = tokenStream.token().value.replace(/(?:url\\()?[\"']([^\"']+)[\"']\\)?/, \"$1\");                \n\n                this._readWhitespace();\n                \n                mediaList = this._media_query_list();\n                \n                //must end with a semicolon\n                tokenStream.mustMatch(Tokens.SEMICOLON);\n                this._readWhitespace();\n                \n                if (emit !== false){\n                    this.fire({\n                        type:   \"import\",\n                        uri:    uri,\n                        media:  mediaList,\n                        line:   importToken.startLine,\n                        col:    importToken.startCol\n                    });\n                }\n        \n            },\n            \n            _namespace: function(emit){\n                /*\n                 * namespace\n                 *   : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S*\n                 */    \n            \n                var tokenStream = this._tokenStream,\n                    line,\n                    col,\n                    prefix,\n                    uri;\n                \n                //read import symbol\n                tokenStream.mustMatch(Tokens.NAMESPACE_SYM);\n                line = tokenStream.token().startLine;\n                col = tokenStream.token().startCol;\n                this._readWhitespace();\n                \n                //it's a namespace prefix - no _namespace_prefix() method because it's just an IDENT\n                if (tokenStream.match(Tokens.IDENT)){\n                    prefix = tokenStream.token().value;\n                    this._readWhitespace();\n                }\n                \n                tokenStream.mustMatch([Tokens.STRING, Tokens.URI]);\n                /*if (!tokenStream.match(Tokens.STRING)){\n                    tokenStream.mustMatch(Tokens.URI);\n                }*/\n                \n                //grab the URI value\n                uri = tokenStream.token().value.replace(/(?:url\\()?[\"']([^\"']+)[\"']\\)?/, \"$1\");                \n\n                this._readWhitespace();\n\n                //must end with a semicolon\n                tokenStream.mustMatch(Tokens.SEMICOLON);\n                this._readWhitespace();\n                \n                if (emit !== false){\n                    this.fire({\n                        type:   \"namespace\",\n                        prefix: prefix,\n                        uri:    uri,\n                        line:   line,\n                        col:    col\n                    });\n                }\n        \n            },            \n                       \n            _media: function(){\n                /*\n                 * media\n                 *   : MEDIA_SYM S* media_query_list S* '{' S* ruleset* '}' S*\n                 *   ;\n                 */\n                var tokenStream     = this._tokenStream,\n                    line,\n                    col,\n                    mediaList;//       = [];\n                \n                //look for @media\n                tokenStream.mustMatch(Tokens.MEDIA_SYM);\n                line = tokenStream.token().startLine;\n                col = tokenStream.token().startCol;\n                \n                this._readWhitespace();               \n\n                mediaList = this._media_query_list();\n\n                tokenStream.mustMatch(Tokens.LBRACE);\n                this._readWhitespace();\n                \n                this.fire({\n                    type:   \"startmedia\",\n                    media:  mediaList,\n                    line:   line,\n                    col:    col\n                });\n                \n                while(true) {\n                    if (tokenStream.peek() == Tokens.PAGE_SYM){\n                        this._page();\n                    } else if (!this._ruleset()){\n                        break;\n                    }                \n                }\n                \n                tokenStream.mustMatch(Tokens.RBRACE);\n                this._readWhitespace();\n        \n                this.fire({\n                    type:   \"endmedia\",\n                    media:  mediaList,\n                    line:   line,\n                    col:    col\n                });\n            },                           \n        \n\n            //CSS3 Media Queries\n            _media_query_list: function(){\n                /*\n                 * media_query_list\n                 *   : S* [media_query [ ',' S* media_query ]* ]?\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    mediaList   = [];\n                \n                \n                this._readWhitespace();\n                \n                if (tokenStream.peek() == Tokens.IDENT || tokenStream.peek() == Tokens.LPAREN){\n                    mediaList.push(this._media_query());\n                }\n                \n                while(tokenStream.match(Tokens.COMMA)){\n                    this._readWhitespace();\n                    mediaList.push(this._media_query());\n                }\n                \n                return mediaList;\n            },\n            \n            /*\n             * Note: \"expression\" in the grammar maps to the _media_expression\n             * method.\n             \n             */\n            _media_query: function(){\n                /*\n                 * media_query\n                 *   : [ONLY | NOT]? S* media_type S* [ AND S* expression ]*\n                 *   | expression [ AND S* expression ]*\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    type        = null,\n                    ident       = null,\n                    token       = null,\n                    expressions = [];\n                    \n                if (tokenStream.match(Tokens.IDENT)){\n                    ident = tokenStream.token().value.toLowerCase();\n                    \n                    //since there's no custom tokens for these, need to manually check\n                    if (ident != \"only\" && ident != \"not\"){\n                        tokenStream.unget();\n                        ident = null;\n                    } else {\n                        token = tokenStream.token();\n                    }\n                }\n                                \n                this._readWhitespace();\n                \n                if (tokenStream.peek() == Tokens.IDENT){\n                    type = this._media_type();\n                    if (token === null){\n                        token = tokenStream.token();\n                    }\n                } else if (tokenStream.peek() == Tokens.LPAREN){\n                    if (token === null){\n                        token = tokenStream.LT(1);\n                    }\n                    expressions.push(this._media_expression());\n                }                               \n                \n                if (type === null && expressions.length === 0){\n                    return null;\n                } else {                \n                    this._readWhitespace();\n                    while (tokenStream.match(Tokens.IDENT)){\n                        if (tokenStream.token().value.toLowerCase() != \"and\"){\n                            this._unexpectedToken(tokenStream.token());\n                        }\n                        \n                        this._readWhitespace();\n                        expressions.push(this._media_expression());\n                    }\n                }\n\n                return new MediaQuery(ident, type, expressions, token.startLine, token.startCol);\n            },\n\n            //CSS3 Media Queries\n            _media_type: function(){\n                /*\n                 * media_type\n                 *   : IDENT\n                 *   ;\n                 */\n                return this._media_feature();           \n            },\n\n            /**\n             * Note: in CSS3 Media Queries, this is called \"expression\".\n             * Renamed here to avoid conflict with CSS3 Selectors\n             * definition of \"expression\". Also note that \"expr\" in the\n             * grammar now maps to \"expression\" from CSS3 selectors.\n             * @method _media_expression\n             * @private\n             */\n            _media_expression: function(){\n                /*\n                 * expression\n                 *  : '(' S* media_feature S* [ ':' S* expr ]? ')' S*\n                 *  ;\n                 */\n                var tokenStream = this._tokenStream,\n                    feature     = null,\n                    token,\n                    expression  = null;\n                \n                tokenStream.mustMatch(Tokens.LPAREN);\n                \n                feature = this._media_feature();\n                this._readWhitespace();\n                \n                if (tokenStream.match(Tokens.COLON)){\n                    this._readWhitespace();\n                    token = tokenStream.LT(1);\n                    expression = this._expression();\n                }\n                \n                tokenStream.mustMatch(Tokens.RPAREN);\n                this._readWhitespace();\n\n                return new MediaFeature(feature, (expression ? new SyntaxUnit(expression, token.startLine, token.startCol) : null));            \n            },\n\n            //CSS3 Media Queries\n            _media_feature: function(){\n                /*\n                 * media_feature\n                 *   : IDENT\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream;\n                    \n                tokenStream.mustMatch(Tokens.IDENT);\n                \n                return SyntaxUnit.fromToken(tokenStream.token());            \n            },\n            \n            //CSS3 Paged Media\n            _page: function(){\n                /*\n                 * page:\n                 *    PAGE_SYM S* IDENT? pseudo_page? S* \n                 *    '{' S* [ declaration | margin ]? [ ';' S* [ declaration | margin ]? ]* '}' S*\n                 *    ;\n                 */            \n                var tokenStream = this._tokenStream,\n                    line,\n                    col,\n                    identifier  = null,\n                    pseudoPage  = null;\n                \n                //look for @page\n                tokenStream.mustMatch(Tokens.PAGE_SYM);\n                line = tokenStream.token().startLine;\n                col = tokenStream.token().startCol;\n                \n                this._readWhitespace();\n                \n                if (tokenStream.match(Tokens.IDENT)){\n                    identifier = tokenStream.token().value;\n\n                    //The value 'auto' may not be used as a page name and MUST be treated as a syntax error.\n                    if (identifier.toLowerCase() === \"auto\"){\n                        this._unexpectedToken(tokenStream.token());\n                    }\n                }                \n                \n                //see if there's a colon upcoming\n                if (tokenStream.peek() == Tokens.COLON){\n                    pseudoPage = this._pseudo_page();\n                }\n            \n                this._readWhitespace();\n                \n                this.fire({\n                    type:   \"startpage\",\n                    id:     identifier,\n                    pseudo: pseudoPage,\n                    line:   line,\n                    col:    col\n                });                   \n\n                this._readDeclarations(true, true);                \n                \n                this.fire({\n                    type:   \"endpage\",\n                    id:     identifier,\n                    pseudo: pseudoPage,\n                    line:   line,\n                    col:    col\n                });             \n            \n            },\n            \n            //CSS3 Paged Media\n            _margin: function(){\n                /*\n                 * margin :\n                 *    margin_sym S* '{' declaration [ ';' S* declaration? ]* '}' S*\n                 *    ;\n                 */\n                var tokenStream = this._tokenStream,\n                    line,\n                    col,\n                    marginSym   = this._margin_sym();\n\n                if (marginSym){\n                    line = tokenStream.token().startLine;\n                    col = tokenStream.token().startCol;\n                \n                    this.fire({\n                        type: \"startpagemargin\",\n                        margin: marginSym,\n                        line:   line,\n                        col:    col\n                    });    \n                    \n                    this._readDeclarations(true);\n\n                    this.fire({\n                        type: \"endpagemargin\",\n                        margin: marginSym,\n                        line:   line,\n                        col:    col\n                    });    \n                    return true;\n                } else {\n                    return false;\n                }\n            },\n\n            //CSS3 Paged Media\n            _margin_sym: function(){\n            \n                /*\n                 * margin_sym :\n                 *    TOPLEFTCORNER_SYM | \n                 *    TOPLEFT_SYM | \n                 *    TOPCENTER_SYM | \n                 *    TOPRIGHT_SYM | \n                 *    TOPRIGHTCORNER_SYM |\n                 *    BOTTOMLEFTCORNER_SYM | \n                 *    BOTTOMLEFT_SYM | \n                 *    BOTTOMCENTER_SYM | \n                 *    BOTTOMRIGHT_SYM |\n                 *    BOTTOMRIGHTCORNER_SYM |\n                 *    LEFTTOP_SYM |\n                 *    LEFTMIDDLE_SYM |\n                 *    LEFTBOTTOM_SYM |\n                 *    RIGHTTOP_SYM |\n                 *    RIGHTMIDDLE_SYM |\n                 *    RIGHTBOTTOM_SYM \n                 *    ;\n                 */\n            \n                var tokenStream = this._tokenStream;\n            \n                if(tokenStream.match([Tokens.TOPLEFTCORNER_SYM, Tokens.TOPLEFT_SYM,\n                        Tokens.TOPCENTER_SYM, Tokens.TOPRIGHT_SYM, Tokens.TOPRIGHTCORNER_SYM,\n                        Tokens.BOTTOMLEFTCORNER_SYM, Tokens.BOTTOMLEFT_SYM, \n                        Tokens.BOTTOMCENTER_SYM, Tokens.BOTTOMRIGHT_SYM,\n                        Tokens.BOTTOMRIGHTCORNER_SYM, Tokens.LEFTTOP_SYM, \n                        Tokens.LEFTMIDDLE_SYM, Tokens.LEFTBOTTOM_SYM, Tokens.RIGHTTOP_SYM,\n                        Tokens.RIGHTMIDDLE_SYM, Tokens.RIGHTBOTTOM_SYM]))\n                {\n                    return SyntaxUnit.fromToken(tokenStream.token());                \n                } else {\n                    return null;\n                }\n            \n            },\n            \n            _pseudo_page: function(){\n                /*\n                 * pseudo_page\n                 *   : ':' IDENT\n                 *   ;    \n                 */\n        \n                var tokenStream = this._tokenStream;\n                \n                tokenStream.mustMatch(Tokens.COLON);\n                tokenStream.mustMatch(Tokens.IDENT);\n                \n                //TODO: CSS3 Paged Media says only \"left\", \"center\", and \"right\" are allowed\n                \n                return tokenStream.token().value;\n            },\n            \n            _font_face: function(){\n                /*\n                 * font_face\n                 *   : FONT_FACE_SYM S* \n                 *     '{' S* declaration [ ';' S* declaration ]* '}' S*\n                 *   ;\n                 */     \n                var tokenStream = this._tokenStream,\n                    line,\n                    col;\n                \n                //look for @page\n                tokenStream.mustMatch(Tokens.FONT_FACE_SYM);\n                line = tokenStream.token().startLine;\n                col = tokenStream.token().startCol;\n                \n                this._readWhitespace();\n\n                this.fire({\n                    type:   \"startfontface\",\n                    line:   line,\n                    col:    col\n                });                    \n                \n                this._readDeclarations(true);\n                \n                this.fire({\n                    type:   \"endfontface\",\n                    line:   line,\n                    col:    col\n                });              \n            },\n\n            _operator: function(){\n            \n                /*\n                 * operator\n                 *  : '/' S* | ',' S* | /( empty )/\n                 *  ;\n                 */    \n                 \n                var tokenStream = this._tokenStream,\n                    token       = null;\n                \n                if (tokenStream.match([Tokens.SLASH, Tokens.COMMA])){\n                    token =  tokenStream.token();\n                    this._readWhitespace();\n                } \n                return token ? PropertyValuePart.fromToken(token) : null;\n                \n            },\n            \n            _combinator: function(){\n            \n                /*\n                 * combinator\n                 *  : PLUS S* | GREATER S* | TILDE S* | S+\n                 *  ;\n                 */    \n                 \n                var tokenStream = this._tokenStream,\n                    value       = null,\n                    token;\n                \n                if(tokenStream.match([Tokens.PLUS, Tokens.GREATER, Tokens.TILDE])){                \n                    token = tokenStream.token();\n                    value = new Combinator(token.value, token.startLine, token.startCol);\n                    this._readWhitespace();\n                }\n                \n                return value;\n            },\n            \n            _unary_operator: function(){\n            \n                /*\n                 * unary_operator\n                 *  : '-' | '+'\n                 *  ;\n                 */\n                 \n                var tokenStream = this._tokenStream;\n                \n                if (tokenStream.match([Tokens.MINUS, Tokens.PLUS])){\n                    return tokenStream.token().value;\n                } else {\n                    return null;\n                }         \n            },\n            \n            _property: function(){\n            \n                /*\n                 * property\n                 *   : IDENT S*\n                 *   ;        \n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    value       = null,\n                    hack        = null,\n                    tokenValue,\n                    token,\n                    line,\n                    col;\n                    \n                //check for star hack - throws error if not allowed\n                if (tokenStream.peek() == Tokens.STAR && this.options.starHack){\n                    tokenStream.get();\n                    token = tokenStream.token();\n                    hack = token.value;\n                    line = token.startLine;\n                    col = token.startCol;\n                }\n                \n                if(tokenStream.match(Tokens.IDENT)){\n                    token = tokenStream.token();\n                    tokenValue = token.value;\n                    \n                    //check for underscore hack - no error if not allowed because it's valid CSS syntax\n                    if (tokenValue.charAt(0) == \"_\" && this.options.underscoreHack){\n                        hack = \"_\";\n                        tokenValue = tokenValue.substring(1);\n                    }\n                    \n                    value = new PropertyName(tokenValue, hack, (line||token.startLine), (col||token.startCol));\n                    this._readWhitespace();\n                }\n                \n                return value;\n            },\n        \n            //Augmented with CSS3 Selectors\n            _ruleset: function(){\n                /*\n                 * ruleset\n                 *   : selectors_group\n                 *     '{' S* declaration? [ ';' S* declaration? ]* '}' S*\n                 *   ;    \n                 */    \n                 \n                var tokenStream = this._tokenStream,\n                    tt,\n                    selectors;\n\n\n                /*\n                 * Error Recovery: If even a single selector fails to parse,\n                 * then the entire ruleset should be thrown away.\n                 */\n                try {\n                    selectors = this._selectors_group();\n                } catch (ex){\n                    if (ex instanceof SyntaxError && !this.options.strict){\n                    \n                        //fire error event\n                        this.fire({\n                            type:       \"error\",\n                            error:      ex,\n                            message:    ex.message,\n                            line:       ex.line,\n                            col:        ex.col\n                        });                          \n                        \n                        //skip over everything until closing brace\n                        tt = tokenStream.advance([Tokens.RBRACE]);\n                        if (tt == Tokens.RBRACE){\n                            //if there's a right brace, the rule is finished so don't do anything\n                        } else {\n                            //otherwise, rethrow the error because it wasn't handled properly\n                            throw ex;\n                        }                        \n                        \n                    } else {\n                        //not a syntax error, rethrow it\n                        throw ex;\n                    }                \n                \n                    //trigger parser to continue\n                    return true;\n                }\n                \n                //if it got here, all selectors parsed\n                if (selectors){ \n                                    \n                    this.fire({\n                        type:       \"startrule\",\n                        selectors:  selectors,\n                        line:       selectors[0].line,\n                        col:        selectors[0].col\n                    });                \n                    \n                    this._readDeclarations(true);                \n                    \n                    this.fire({\n                        type:       \"endrule\",\n                        selectors:  selectors,\n                        line:       selectors[0].line,\n                        col:        selectors[0].col\n                    });  \n                    \n                }\n                \n                return selectors;\n                \n            },\n\n            //CSS3 Selectors\n            _selectors_group: function(){\n            \n                /*            \n                 * selectors_group\n                 *   : selector [ COMMA S* selector ]*\n                 *   ;\n                 */           \n                var tokenStream = this._tokenStream,\n                    selectors   = [],\n                    selector;\n                    \n                selector = this._selector();\n                if (selector !== null){\n                \n                    selectors.push(selector);\n                    while(tokenStream.match(Tokens.COMMA)){\n                        this._readWhitespace();\n                        selector = this._selector();\n                        if (selector !== null){\n                            selectors.push(selector);\n                        } else {\n                            this._unexpectedToken(tokenStream.LT(1));\n                        }\n                    }\n                }\n\n                return selectors.length ? selectors : null;\n            },\n                \n            //CSS3 Selectors\n            _selector: function(){\n                /*\n                 * selector\n                 *   : simple_selector_sequence [ combinator simple_selector_sequence ]*\n                 *   ;    \n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    selector    = [],\n                    nextSelector = null,\n                    combinator  = null,\n                    ws          = null;\n                \n                //if there's no simple selector, then there's no selector\n                nextSelector = this._simple_selector_sequence();\n                if (nextSelector === null){\n                    return null;\n                }\n                \n                selector.push(nextSelector);\n                \n                do {\n                    \n                    //look for a combinator\n                    combinator = this._combinator();\n                    \n                    if (combinator !== null){\n                        selector.push(combinator);\n                        nextSelector = this._simple_selector_sequence();\n                        \n                        //there must be a next selector\n                        if (nextSelector === null){\n                            this._unexpectedToken(this.LT(1));\n                        } else {\n                        \n                            //nextSelector is an instance of SelectorPart\n                            selector.push(nextSelector);\n                        }\n                    } else {\n                        \n                        //if there's not whitespace, we're done\n                        if (this._readWhitespace()){           \n        \n                            //add whitespace separator\n                            ws = new Combinator(tokenStream.token().value, tokenStream.token().startLine, tokenStream.token().startCol);\n                            \n                            //combinator is not required\n                            combinator = this._combinator();\n                            \n                            //selector is required if there's a combinator\n                            nextSelector = this._simple_selector_sequence();\n                            if (nextSelector === null){                        \n                                if (combinator !== null){\n                                    this._unexpectedToken(tokenStream.LT(1));\n                                }\n                            } else {\n                                \n                                if (combinator !== null){\n                                    selector.push(combinator);\n                                } else {\n                                    selector.push(ws);\n                                }\n                                \n                                selector.push(nextSelector);\n                            }     \n                        } else {\n                            break;\n                        }               \n                    \n                    }\n                } while(true);\n                \n                return new Selector(selector, selector[0].line, selector[0].col);\n            },\n            \n            //CSS3 Selectors\n            _simple_selector_sequence: function(){\n                /*\n                 * simple_selector_sequence\n                 *   : [ type_selector | universal ]\n                 *     [ HASH | class | attrib | pseudo | negation ]*\n                 *   | [ HASH | class | attrib | pseudo | negation ]+\n                 *   ;\n                 */\n                 \n                var tokenStream = this._tokenStream,\n                \n                    //parts of a simple selector\n                    elementName = null,\n                    modifiers   = [],\n                    \n                    //complete selector text\n                    selectorText= \"\",\n\n                    //the different parts after the element name to search for\n                    components  = [\n                        //HASH\n                        function(){\n                            return tokenStream.match(Tokens.HASH) ?\n                                    new SelectorSubPart(tokenStream.token().value, \"id\", tokenStream.token().startLine, tokenStream.token().startCol) :\n                                    null;\n                        },\n                        this._class,\n                        this._attrib,\n                        this._pseudo,\n                        this._negation\n                    ],\n                    i           = 0,\n                    len         = components.length,\n                    component   = null,\n                    found       = false,\n                    line,\n                    col;\n                    \n                    \n                //get starting line and column for the selector\n                line = tokenStream.LT(1).startLine;\n                col = tokenStream.LT(1).startCol;\n                                        \n                elementName = this._type_selector();\n                if (!elementName){\n                    elementName = this._universal();\n                }\n                \n                if (elementName !== null){\n                    selectorText += elementName;\n                }                \n                \n                while(true){\n\n                    //whitespace means we're done\n                    if (tokenStream.peek() === Tokens.S){\n                        break;\n                    }\n                \n                    //check for each component\n                    while(i < len && component === null){\n                        component = components[i++].call(this);\n                    }\n        \n                    if (component === null){\n                    \n                        //we don't have a selector\n                        if (selectorText === \"\"){\n                            return null;\n                        } else {\n                            break;\n                        }\n                    } else {\n                        i = 0;\n                        modifiers.push(component);\n                        selectorText += component.toString(); \n                        component = null;\n                    }\n                }\n\n                 \n                return selectorText !== \"\" ?\n                        new SelectorPart(elementName, modifiers, selectorText, line, col) :\n                        null;\n            },            \n            \n            //CSS3 Selectors\n            _type_selector: function(){\n                /*\n                 * type_selector\n                 *   : [ namespace_prefix ]? element_name\n                 *   ;\n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    ns          = this._namespace_prefix(),\n                    elementName = this._element_name();\n                    \n                if (!elementName){                    \n                    /*\n                     * Need to back out the namespace that was read due to both\n                     * type_selector and universal reading namespace_prefix\n                     * first. Kind of hacky, but only way I can figure out\n                     * right now how to not change the grammar.\n                     */\n                    if (ns){\n                        tokenStream.unget();\n                        if (ns.length > 1){\n                            tokenStream.unget();\n                        }\n                    }\n                \n                    return null;\n                } else {     \n                    if (ns){\n                        elementName.text = ns + elementName.text;\n                        elementName.col -= ns.length;\n                    }\n                    return elementName;\n                }\n            },\n            \n            //CSS3 Selectors\n            _class: function(){\n                /*\n                 * class\n                 *   : '.' IDENT\n                 *   ;\n                 */    \n                 \n                var tokenStream = this._tokenStream,\n                    token;\n                \n                if (tokenStream.match(Tokens.DOT)){\n                    tokenStream.mustMatch(Tokens.IDENT);    \n                    token = tokenStream.token();\n                    return new SelectorSubPart(\".\" + token.value, \"class\", token.startLine, token.startCol - 1);        \n                } else {\n                    return null;\n                }\n        \n            },\n            \n            //CSS3 Selectors\n            _element_name: function(){\n                /*\n                 * element_name\n                 *   : IDENT\n                 *   ;\n                 */    \n                \n                var tokenStream = this._tokenStream,\n                    token;\n                \n                if (tokenStream.match(Tokens.IDENT)){\n                    token = tokenStream.token();\n                    return new SelectorSubPart(token.value, \"elementName\", token.startLine, token.startCol);        \n                \n                } else {\n                    return null;\n                }\n            },\n            \n            //CSS3 Selectors\n            _namespace_prefix: function(){\n                /*            \n                 * namespace_prefix\n                 *   : [ IDENT | '*' ]? '|'\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    value       = \"\";\n                    \n                //verify that this is a namespace prefix\n                if (tokenStream.LA(1) === Tokens.PIPE || tokenStream.LA(2) === Tokens.PIPE){\n                        \n                    if(tokenStream.match([Tokens.IDENT, Tokens.STAR])){\n                        value += tokenStream.token().value;\n                    }\n                    \n                    tokenStream.mustMatch(Tokens.PIPE);\n                    value += \"|\";\n                    \n                }\n                \n                return value.length ? value : null;                \n            },\n            \n            //CSS3 Selectors\n            _universal: function(){\n                /*\n                 * universal\n                 *   : [ namespace_prefix ]? '*'\n                 *   ;            \n                 */\n                var tokenStream = this._tokenStream,\n                    value       = \"\",\n                    ns;\n                    \n                ns = this._namespace_prefix();\n                if(ns){\n                    value += ns;\n                }\n                \n                if(tokenStream.match(Tokens.STAR)){\n                    value += \"*\";\n                }\n                \n                return value.length ? value : null;\n                \n           },\n            \n            //CSS3 Selectors\n            _attrib: function(){\n                /*\n                 * attrib\n                 *   : '[' S* [ namespace_prefix ]? IDENT S*\n                 *         [ [ PREFIXMATCH |\n                 *             SUFFIXMATCH |\n                 *             SUBSTRINGMATCH |\n                 *             '=' |\n                 *             INCLUDES |\n                 *             DASHMATCH ] S* [ IDENT | STRING ] S*\n                 *         ]? ']'\n                 *   ;    \n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    value       = null,\n                    ns,\n                    token;\n                \n                if (tokenStream.match(Tokens.LBRACKET)){\n                    token = tokenStream.token();\n                    value = token.value;\n                    value += this._readWhitespace();\n                    \n                    ns = this._namespace_prefix();\n                    \n                    if (ns){\n                        value += ns;\n                    }\n                                        \n                    tokenStream.mustMatch(Tokens.IDENT);\n                    value += tokenStream.token().value;                    \n                    value += this._readWhitespace();\n                    \n                    if(tokenStream.match([Tokens.PREFIXMATCH, Tokens.SUFFIXMATCH, Tokens.SUBSTRINGMATCH,\n                            Tokens.EQUALS, Tokens.INCLUDES, Tokens.DASHMATCH])){\n                    \n                        value += tokenStream.token().value;                    \n                        value += this._readWhitespace();\n                        \n                        tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]);\n                        value += tokenStream.token().value;                    \n                        value += this._readWhitespace();\n                    }\n                    \n                    tokenStream.mustMatch(Tokens.RBRACKET);\n                                        \n                    return new SelectorSubPart(value + \"]\", \"attribute\", token.startLine, token.startCol);\n                } else {\n                    return null;\n                }\n            },\n            \n            //CSS3 Selectors\n            _pseudo: function(){\n            \n                /*\n                 * pseudo\n                 *   : ':' ':'? [ IDENT | functional_pseudo ]\n                 *   ;    \n                 */   \n            \n                var tokenStream = this._tokenStream,\n                    pseudo      = null,\n                    colons      = \":\",\n                    line,\n                    col;\n                \n                if (tokenStream.match(Tokens.COLON)){\n                \n                    if (tokenStream.match(Tokens.COLON)){\n                        colons += \":\";\n                    }\n                \n                    if (tokenStream.match(Tokens.IDENT)){\n                        pseudo = tokenStream.token().value;\n                        line = tokenStream.token().startLine;\n                        col = tokenStream.token().startCol - colons.length;\n                    } else if (tokenStream.peek() == Tokens.FUNCTION){\n                        line = tokenStream.LT(1).startLine;\n                        col = tokenStream.LT(1).startCol - colons.length;\n                        pseudo = this._functional_pseudo();\n                    }\n                    \n                    if (pseudo){\n                        pseudo = new SelectorSubPart(colons + pseudo, \"pseudo\", line, col);\n                    }\n                }\n        \n                return pseudo;\n            },\n            \n            //CSS3 Selectors\n            _functional_pseudo: function(){\n                /*\n                 * functional_pseudo\n                 *   : FUNCTION S* expression ')'\n                 *   ;\n                */            \n                \n                var tokenStream = this._tokenStream,\n                    value = null;\n                \n                if(tokenStream.match(Tokens.FUNCTION)){\n                    value = tokenStream.token().value;\n                    value += this._readWhitespace();\n                    value += this._expression();\n                    tokenStream.mustMatch(Tokens.RPAREN);\n                    value += \")\";\n                }\n                \n                return value;\n            },\n            \n            //CSS3 Selectors\n            _expression: function(){\n                /*\n                 * expression\n                 *   : [ [ PLUS | '-' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+\n                 *   ;\n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    value       = \"\";\n                    \n                while(tokenStream.match([Tokens.PLUS, Tokens.MINUS, Tokens.DIMENSION,\n                        Tokens.NUMBER, Tokens.STRING, Tokens.IDENT, Tokens.LENGTH,\n                        Tokens.FREQ, Tokens.ANGLE, Tokens.TIME,\n                        Tokens.RESOLUTION])){\n                    \n                    value += tokenStream.token().value;\n                    value += this._readWhitespace();                        \n                }\n                \n                return value.length ? value : null;\n                \n            },\n\n            //CSS3 Selectors\n            _negation: function(){\n                /*            \n                 * negation\n                 *   : NOT S* negation_arg S* ')'\n                 *   ;\n                 */\n\n                var tokenStream = this._tokenStream,\n                    line,\n                    col,\n                    value       = \"\",\n                    arg,\n                    subpart     = null;\n                    \n                if (tokenStream.match(Tokens.NOT)){\n                    value = tokenStream.token().value;\n                    line = tokenStream.token().startLine;\n                    col = tokenStream.token().startCol;\n                    value += this._readWhitespace();\n                    arg = this._negation_arg();\n                    value += arg;\n                    value += this._readWhitespace();\n                    tokenStream.match(Tokens.RPAREN);\n                    value += tokenStream.token().value;\n                    \n                    subpart = new SelectorSubPart(value, \"not\", line, col);\n                    subpart.args.push(arg);\n                }\n                \n                return subpart;\n            },\n            \n            //CSS3 Selectors\n            _negation_arg: function(){            \n                /*\n                 * negation_arg\n                 *   : type_selector | universal | HASH | class | attrib | pseudo\n                 *   ;            \n                 */           \n                 \n                var tokenStream = this._tokenStream,\n                    args        = [\n                        this._type_selector,\n                        this._universal,\n                        function(){\n                            return tokenStream.match(Tokens.HASH) ?\n                                    new SelectorSubPart(tokenStream.token().value, \"id\", tokenStream.token().startLine, tokenStream.token().startCol) :\n                                    null;                        \n                        },\n                        this._class,\n                        this._attrib,\n                        this._pseudo                    \n                    ],\n                    arg         = null,\n                    i           = 0,\n                    len         = args.length,\n                    elementName,\n                    line,\n                    col,\n                    part;\n                    \n                line = tokenStream.LT(1).startLine;\n                col = tokenStream.LT(1).startCol;\n                \n                while(i < len && arg === null){\n                    \n                    arg = args[i].call(this);\n                    i++;\n                }\n                \n                //must be a negation arg\n                if (arg === null){\n                    this._unexpectedToken(tokenStream.LT(1));\n                }\n \n                //it's an element name\n                if (arg.type == \"elementName\"){\n                    part = new SelectorPart(arg, [], arg.toString(), line, col);\n                } else {\n                    part = new SelectorPart(null, [arg], arg.toString(), line, col);\n                }\n                \n                return part;                \n            },\n            \n            _declaration: function(){\n            \n                /*\n                 * declaration\n                 *   : property ':' S* expr prio?\n                 *   | /( empty )/\n                 *   ;     \n                 */    \n            \n                var tokenStream = this._tokenStream,\n                    property    = null,\n                    expr        = null,\n                    prio        = null,\n                    error       = null,\n                    invalid     = null;\n                \n                property = this._property();\n                if (property !== null){\n\n                    tokenStream.mustMatch(Tokens.COLON);\n                    this._readWhitespace();\n                    \n                    expr = this._expr();\n                    \n                    //if there's no parts for the value, it's an error\n                    if (!expr || expr.length === 0){\n                        this._unexpectedToken(tokenStream.LT(1));\n                    }\n                    \n                    prio = this._prio();\n                    \n                    try {\n                        this._validateProperty(property, expr);\n                    } catch (ex) {\n                        invalid = ex;\n                    }\n                    \n                    this.fire({\n                        type:       \"property\",\n                        property:   property,\n                        value:      expr,\n                        important:  prio,\n                        line:       property.line,\n                        col:        property.col,\n                        invalid:    invalid\n                    });                      \n                    \n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            \n            _prio: function(){\n                /*\n                 * prio\n                 *   : IMPORTANT_SYM S*\n                 *   ;    \n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    result      = tokenStream.match(Tokens.IMPORTANT_SYM);\n                    \n                this._readWhitespace();\n                return result;\n            },\n            \n            _expr: function(){\n                /*\n                 * expr\n                 *   : term [ operator term ]*\n                 *   ;\n                 */\n        \n                var tokenStream = this._tokenStream,\n                    values      = [],\n\t\t\t\t\t//valueParts\t= [],\n                    value       = null,\n                    operator    = null;\n                    \n                value = this._term();\n                if (value !== null){\n                \n                    values.push(value);\n                    \n                    do {\n                        operator = this._operator();\n        \n                        //if there's an operator, keep building up the value parts\n                        if (operator){\n                            values.push(operator);\n                        } /*else {\n                            //if there's not an operator, you have a full value\n\t\t\t\t\t\t\tvalues.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));\n\t\t\t\t\t\t\tvalueParts = [];\n\t\t\t\t\t\t}*/\n                        \n                        value = this._term();\n                        \n                        if (value === null){\n                            break;\n                        } else {\n                            values.push(value);\n                        }\n                    } while(true);\n                }\n\t\t\t\t\n\t\t\t\t//cleanup\n                /*if (valueParts.length){\n                    values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));\n                }*/\n        \n                return values.length > 0 ? new PropertyValue(values, values[0].line, values[0].col) : null;\n            },\n            \n            _term: function(){                       \n            \n                /*\n                 * term\n                 *   : unary_operator?\n                 *     [ NUMBER S* | PERCENTAGE S* | LENGTH S* | ANGLE S* |\n                 *       TIME S* | FREQ S* | function | ie_function ]\n                 *   | STRING S* | IDENT S* | URI S* | UNICODERANGE S* | hexcolor\n                 *   ;\n                 */    \n        \n                var tokenStream = this._tokenStream,\n                    unary       = null,\n                    value       = null,\n                    token,\n                    line,\n                    col;\n                    \n                //returns the operator or null\n                unary = this._unary_operator();\n                if (unary !== null){\n                    line = tokenStream.token().startLine;\n                    col = tokenStream.token().startCol;\n                }                \n               \n                //exception for IE filters\n                if (tokenStream.peek() == Tokens.IE_FUNCTION && this.options.ieFilters){\n                \n                    value = this._ie_function();\n                    if (unary === null){\n                        line = tokenStream.token().startLine;\n                        col = tokenStream.token().startCol;\n                    }\n                \n                //see if there's a simple match\n                } else if (tokenStream.match([Tokens.NUMBER, Tokens.PERCENTAGE, Tokens.LENGTH,\n                        Tokens.ANGLE, Tokens.TIME,\n                        Tokens.FREQ, Tokens.STRING, Tokens.IDENT, Tokens.URI, Tokens.UNICODE_RANGE])){\n                 \n                    value = tokenStream.token().value;\n                    if (unary === null){\n                        line = tokenStream.token().startLine;\n                        col = tokenStream.token().startCol;\n                    }\n                    this._readWhitespace();\n                } else {\n                \n                    //see if it's a color\n                    token = this._hexcolor();\n                    if (token === null){\n                    \n                        //if there's no unary, get the start of the next token for line/col info\n                        if (unary === null){\n                            line = tokenStream.LT(1).startLine;\n                            col = tokenStream.LT(1).startCol;\n                        }                    \n                    \n                        //has to be a function\n                        if (value === null){\n                            \n                            /*\n                             * This checks for alpha(opacity=0) style of IE\n                             * functions. IE_FUNCTION only presents progid: style.\n                             */\n                            if (tokenStream.LA(3) == Tokens.EQUALS && this.options.ieFilters){\n                                value = this._ie_function();\n                            } else {\n                                value = this._function();\n                            }\n                        }\n\n                        /*if (value === null){\n                            return null;\n                            //throw new Error(\"Expected identifier at line \" + tokenStream.token().startLine + \", character \" +  tokenStream.token().startCol + \".\");\n                        }*/\n                    \n                    } else {\n                        value = token.value;\n                        if (unary === null){\n                            line = token.startLine;\n                            col = token.startCol;\n                        }                    \n                    }\n                \n                }                \n                \n                return value !== null ?\n                        new PropertyValuePart(unary !== null ? unary + value : value, line, col) :\n                        null;\n        \n            },\n            \n            _function: function(){\n            \n                /*\n                 * function\n                 *   : FUNCTION S* expr ')' S*\n                 *   ;\n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    functionText = null,\n                    expr        = null,\n                    lt;\n                    \n                if (tokenStream.match(Tokens.FUNCTION)){\n                    functionText = tokenStream.token().value;\n                    this._readWhitespace();\n                    expr = this._expr();\n                    functionText += expr;\n                    \n                    //START: Horrible hack in case it's an IE filter\n                    if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){\n                        do {\n                        \n                            if (this._readWhitespace()){\n                                functionText += tokenStream.token().value;\n                            }\n                            \n                            //might be second time in the loop\n                            if (tokenStream.LA(0) == Tokens.COMMA){\n                                functionText += tokenStream.token().value;\n                            }\n                        \n                            tokenStream.match(Tokens.IDENT);\n                            functionText += tokenStream.token().value;\n                            \n                            tokenStream.match(Tokens.EQUALS);\n                            functionText += tokenStream.token().value;\n                            \n                            //functionText += this._term();\n                            lt = tokenStream.peek();\n                            while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){\n                                tokenStream.get();\n                                functionText += tokenStream.token().value;\n                                lt = tokenStream.peek();\n                            }\n                        } while(tokenStream.match([Tokens.COMMA, Tokens.S]));\n                    }\n\n                    //END: Horrible Hack\n                    \n                    tokenStream.match(Tokens.RPAREN);    \n                    functionText += \")\";\n                    this._readWhitespace();\n                }                \n                \n                return functionText;\n            }, \n            \n            _ie_function: function(){\n            \n                /* (My own extension)\n                 * ie_function\n                 *   : IE_FUNCTION S* IDENT '=' term [S* ','? IDENT '=' term]+ ')' S*\n                 *   ;\n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    functionText = null,\n                    expr        = null,\n                    lt;\n                    \n                //IE function can begin like a regular function, too\n                if (tokenStream.match([Tokens.IE_FUNCTION, Tokens.FUNCTION])){\n                    functionText = tokenStream.token().value;\n                    \n                    do {\n                    \n                        if (this._readWhitespace()){\n                            functionText += tokenStream.token().value;\n                        }\n                        \n                        //might be second time in the loop\n                        if (tokenStream.LA(0) == Tokens.COMMA){\n                            functionText += tokenStream.token().value;\n                        }\n                    \n                        tokenStream.match(Tokens.IDENT);\n                        functionText += tokenStream.token().value;\n                        \n                        tokenStream.match(Tokens.EQUALS);\n                        functionText += tokenStream.token().value;\n                        \n                        //functionText += this._term();\n                        lt = tokenStream.peek();\n                        while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){\n                            tokenStream.get();\n                            functionText += tokenStream.token().value;\n                            lt = tokenStream.peek();\n                        }\n                    } while(tokenStream.match([Tokens.COMMA, Tokens.S]));                    \n                    \n                    tokenStream.match(Tokens.RPAREN);    \n                    functionText += \")\";\n                    this._readWhitespace();\n                }                \n                \n                return functionText;\n            }, \n            \n            _hexcolor: function(){\n                /*\n                 * There is a constraint on the color that it must\n                 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])\n                 * after the \"#\"; e.g., \"#000\" is OK, but \"#abcd\" is not.\n                 *\n                 * hexcolor\n                 *   : HASH S*\n                 *   ;\n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    token = null,\n                    color;\n                    \n                if(tokenStream.match(Tokens.HASH)){\n                \n                    //need to do some validation here\n                    \n                    token = tokenStream.token();\n                    color = token.value;\n                    if (!/#[a-f0-9]{3,6}/i.test(color)){\n                        throw new SyntaxError(\"Expected a hex color but found '\" + color + \"' at line \" + token.startLine + \", col \" + token.startCol + \".\", token.startLine, token.startCol);\n                    }\n                    this._readWhitespace();\n                }\n                \n                return token;\n            },\n            \n            //-----------------------------------------------------------------\n            // Animations methods\n            //-----------------------------------------------------------------\n            \n            _keyframes: function(){\n            \n                /*\n                 * keyframes:\n                 *   : KEYFRAMES_SYM S* keyframe_name S* '{' S* keyframe_rule* '}' {\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    token,\n                    tt,\n                    name;            \n                    \n                tokenStream.mustMatch(Tokens.KEYFRAMES_SYM);\n                this._readWhitespace();\n                name = this._keyframe_name();\n                \n                this._readWhitespace();\n                tokenStream.mustMatch(Tokens.LBRACE);\n                    \n                this.fire({\n                    type:   \"startkeyframes\",\n                    name:   name,\n                    line:   name.line,\n                    col:    name.col\n                });                \n                \n                this._readWhitespace();\n                tt = tokenStream.peek();\n                \n                //check for key\n                while(tt == Tokens.IDENT || tt == Tokens.PERCENTAGE) {\n                    this._keyframe_rule();\n                    this._readWhitespace();\n                    tt = tokenStream.peek();\n                }           \n                \n                this.fire({\n                    type:   \"endkeyframes\",\n                    name:   name,\n                    line:   name.line,\n                    col:    name.col\n                });                      \n                    \n                this._readWhitespace();\n                tokenStream.mustMatch(Tokens.RBRACE);                    \n                \n            },\n            \n            _keyframe_name: function(){\n            \n                /*\n                 * keyframe_name:\n                 *   : IDENT\n                 *   | STRING\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    token;\n\n                tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]);\n                return SyntaxUnit.fromToken(tokenStream.token());            \n            },\n            \n            _keyframe_rule: function(){\n            \n                /*\n                 * keyframe_rule:\n                 *   : key_list S* \n                 *     '{' S* declaration [ ';' S* declaration ]* '}' S*\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    token,\n                    keyList = this._key_list();\n                                    \n                this.fire({\n                    type:   \"startkeyframerule\",\n                    keys:   keyList,\n                    line:   keyList[0].line,\n                    col:    keyList[0].col\n                });                \n                \n                this._readDeclarations(true);                \n                \n                this.fire({\n                    type:   \"endkeyframerule\",\n                    keys:   keyList,\n                    line:   keyList[0].line,\n                    col:    keyList[0].col\n                });  \n                \n            },\n            \n            _key_list: function(){\n            \n                /*\n                 * key_list:\n                 *   : key [ S* ',' S* key]*\n                 *   ;\n                 */\n                var tokenStream = this._tokenStream,\n                    token,\n                    key,\n                    keyList = [];\n                    \n                //must be least one key\n                keyList.push(this._key());\n                    \n                this._readWhitespace();\n                    \n                while(tokenStream.match(Tokens.COMMA)){\n                    this._readWhitespace();\n                    keyList.push(this._key());\n                    this._readWhitespace();\n                }\n\n                return keyList;\n            },\n                        \n            _key: function(){\n                /*\n                 * There is a restriction that IDENT can be only \"from\" or \"to\".\n                 *\n                 * key\n                 *   : PERCENTAGE\n                 *   | IDENT\n                 *   ;\n                 */\n                 \n                var tokenStream = this._tokenStream,\n                    token;\n                    \n                if (tokenStream.match(Tokens.PERCENTAGE)){\n                    return SyntaxUnit.fromToken(tokenStream.token());\n                } else if (tokenStream.match(Tokens.IDENT)){\n                    token = tokenStream.token();                    \n                    \n                    if (/from|to/i.test(token.value)){\n                        return SyntaxUnit.fromToken(token);\n                    }\n                    \n                    tokenStream.unget();\n                }\n                \n                //if it gets here, there wasn't a valid token, so time to explode\n                this._unexpectedToken(tokenStream.LT(1));\n            },\n            \n            //-----------------------------------------------------------------\n            // Helper methods\n            //-----------------------------------------------------------------\n            \n            /**\n             * Not part of CSS grammar, but useful for skipping over\n             * combination of white space and HTML-style comments.\n             * @return {void}\n             * @method _skipCruft\n             * @private\n             */\n            _skipCruft: function(){\n                while(this._tokenStream.match([Tokens.S, Tokens.CDO, Tokens.CDC])){\n                    //noop\n                }\n            },\n\n            /**\n             * Not part of CSS grammar, but this pattern occurs frequently\n             * in the official CSS grammar. Split out here to eliminate\n             * duplicate code.\n             * @param {Boolean} checkStart Indicates if the rule should check\n             *      for the left brace at the beginning.\n             * @param {Boolean} readMargins Indicates if the rule should check\n             *      for margin patterns.\n             * @return {void}\n             * @method _readDeclarations\n             * @private\n             */\n            _readDeclarations: function(checkStart, readMargins){\n                /*\n                 * Reads the pattern\n                 * S* '{' S* declaration [ ';' S* declaration ]* '}' S*\n                 * or\n                 * S* '{' S* [ declaration | margin ]? [ ';' S* [ declaration | margin ]? ]* '}' S*\n                 * Note that this is how it is described in CSS3 Paged Media, but is actually incorrect.\n                 * A semicolon is only necessary following a delcaration is there's another declaration\n                 * or margin afterwards. \n                 */\n                var tokenStream = this._tokenStream,\n                    tt;\n                       \n\n                this._readWhitespace();\n                \n                if (checkStart){\n                    tokenStream.mustMatch(Tokens.LBRACE);            \n                }\n                \n                this._readWhitespace();\n\n                try {\n                    \n                    while(true){\n                    \n                        if (tokenStream.match(Tokens.SEMICOLON) || (readMargins && this._margin())){\n                            //noop\n                        } else if (this._declaration()){\n                            if (!tokenStream.match(Tokens.SEMICOLON)){\n                                break;\n                            }\n                        } else {\n                            break;\n                        }\n                    \n                        //if ((!this._margin() && !this._declaration()) || !tokenStream.match(Tokens.SEMICOLON)){\n                        //    break;\n                        //}\n                        this._readWhitespace();\n                    }\n                    \n                    tokenStream.mustMatch(Tokens.RBRACE);\n                    this._readWhitespace();\n                    \n                } catch (ex) {\n                    if (ex instanceof SyntaxError && !this.options.strict){\n                    \n                        //fire error event\n                        this.fire({\n                            type:       \"error\",\n                            error:      ex,\n                            message:    ex.message,\n                            line:       ex.line,\n                            col:        ex.col\n                        });                          \n                        \n                        //see if there's another declaration\n                        tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]);\n                        if (tt == Tokens.SEMICOLON){\n                            //if there's a semicolon, then there might be another declaration\n                            this._readDeclarations(false, readMargins);                            \n                        } else if (tt != Tokens.RBRACE){\n                            //if there's a right brace, the rule is finished so don't do anything\n                            //otherwise, rethrow the error because it wasn't handled properly\n                            throw ex;\n                        }                        \n                        \n                    } else {\n                        //not a syntax error, rethrow it\n                        throw ex;\n                    }\n                }    \n            \n            },      \n            \n            /**\n             * In some cases, you can end up with two white space tokens in a\n             * row. Instead of making a change in every function that looks for\n             * white space, this function is used to match as much white space\n             * as necessary.\n             * @method _readWhitespace\n             * @return {String} The white space if found, empty string if not.\n             * @private\n             */\n            _readWhitespace: function(){\n            \n                var tokenStream = this._tokenStream,\n                    ws = \"\";\n                    \n                while(tokenStream.match(Tokens.S)){\n                    ws += tokenStream.token().value;\n                }\n                \n                return ws;\n            },\n          \n\n            /**\n             * Throws an error when an unexpected token is found.\n             * @param {Object} token The token that was found.\n             * @method _unexpectedToken\n             * @return {void}\n             * @private\n             */\n            _unexpectedToken: function(token){\n                throw new SyntaxError(\"Unexpected token '\" + token.value + \"' at line \" + token.startLine + \", col \" + token.startCol + \".\", token.startLine, token.startCol);\n            },\n            \n            /**\n             * Helper method used for parsing subparts of a style sheet.\n             * @return {void}\n             * @method _verifyEnd\n             * @private\n             */\n            _verifyEnd: function(){\n                if (this._tokenStream.LA(1) != Tokens.EOF){\n                    this._unexpectedToken(this._tokenStream.LT(1));\n                }            \n            },\n            \n            //-----------------------------------------------------------------\n            // Validation methods\n            //-----------------------------------------------------------------\n            _validateProperty: function(property, value){\n                Validation.validate(property, value);\n            },\n            \n            //-----------------------------------------------------------------\n            // Parsing methods\n            //-----------------------------------------------------------------\n            \n            parse: function(input){    \n                this._tokenStream = new TokenStream(input, Tokens);\n                this._stylesheet();\n            },\n            \n            parseStyleSheet: function(input){\n                //just passthrough\n                return this.parse(input);\n            },\n            \n            parseMediaQuery: function(input){\n                this._tokenStream = new TokenStream(input, Tokens);\n                var result = this._media_query();\n                \n                //if there's anything more, then it's an invalid selector\n                this._verifyEnd();\n                \n                //otherwise return result\n                return result;            \n            },\n            \n            /**\n             * Parses a property value (everything after the semicolon).\n             * @return {parserlib.css.PropertyValue} The property value.\n             * @throws parserlib.util.SyntaxError If an unexpected token is found.\n             * @method parserPropertyValue\n             */             \n            parsePropertyValue: function(input){\n            \n                this._tokenStream = new TokenStream(input, Tokens);\n                this._readWhitespace();\n                \n                var result = this._expr();\n                \n                //okay to have a trailing white space\n                this._readWhitespace();\n                \n                //if there's anything more, then it's an invalid selector\n                this._verifyEnd();\n                \n                //otherwise return result\n                return result;\n            },\n            \n            /**\n             * Parses a complete CSS rule, including selectors and\n             * properties.\n             * @param {String} input The text to parser.\n             * @return {Boolean} True if the parse completed successfully, false if not.\n             * @method parseRule\n             */\n            parseRule: function(input){\n                this._tokenStream = new TokenStream(input, Tokens);\n                \n                //skip any leading white space\n                this._readWhitespace();\n                \n                var result = this._ruleset();\n                \n                //skip any trailing white space\n                this._readWhitespace();\n\n                //if there's anything more, then it's an invalid selector\n                this._verifyEnd();\n                \n                //otherwise return result\n                return result;            \n            },\n            \n            /**\n             * Parses a single CSS selector (no comma)\n             * @param {String} input The text to parse as a CSS selector.\n             * @return {Selector} An object representing the selector.\n             * @throws parserlib.util.SyntaxError If an unexpected token is found.\n             * @method parseSelector\n             */\n            parseSelector: function(input){\n            \n                this._tokenStream = new TokenStream(input, Tokens);\n                \n                //skip any leading white space\n                this._readWhitespace();\n                \n                var result = this._selector();\n                \n                //skip any trailing white space\n                this._readWhitespace();\n\n                //if there's anything more, then it's an invalid selector\n                this._verifyEnd();\n                \n                //otherwise return result\n                return result;\n            },\n\n            /**\n             * Parses an HTML style attribute: a set of CSS declarations \n             * separated by semicolons.\n             * @param {String} input The text to parse as a style attribute\n             * @return {void} \n             * @method parseStyleAttribute\n             */\n            parseStyleAttribute: function(input){\n                input += \"}\"; // for error recovery in _readDeclarations()\n                this._tokenStream = new TokenStream(input, Tokens);\n                this._readDeclarations();\n            }\n        };\n        \n    //copy over onto prototype\n    for (prop in additions){\n        if (additions.hasOwnProperty(prop)){\n            proto[prop] = additions[prop];\n        }\n    }   \n    \n    return proto;\n}();\n\n\n/*\nnth\n  : S* [ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]? |\n         ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S*\n  ;\n*/\n/*global Validation, ValidationTypes, ValidationError*/\nvar Properties = {\n\n    //A\n    \"alignment-adjust\"              : \"auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | <percentage> | <length>\",\n    \"alignment-baseline\"            : \"baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical\",\n    \"animation\"                     : 1,\n    \"animation-delay\"               : { multi: \"<time>\", comma: true },\n    \"animation-direction\"           : { multi: \"normal | alternate\", comma: true },\n    \"animation-duration\"            : { multi: \"<time>\", comma: true },\n    \"animation-iteration-count\"     : { multi: \"<number> | infinite\", comma: true },\n    \"animation-name\"                : { multi: \"none | <ident>\", comma: true },\n    \"animation-play-state\"          : { multi: \"running | paused\", comma: true },\n    \"animation-timing-function\"     : 1,\n    \n    //vendor prefixed\n    \"-moz-animation-delay\"               : { multi: \"<time>\", comma: true },\n    \"-moz-animation-direction\"           : { multi: \"normal | alternate\", comma: true },\n    \"-moz-animation-duration\"            : { multi: \"<time>\", comma: true },\n    \"-moz-animation-iteration-count\"     : { multi: \"<number> | infinite\", comma: true },\n    \"-moz-animation-name\"                : { multi: \"none | <ident>\", comma: true },\n    \"-moz-animation-play-state\"          : { multi: \"running | paused\", comma: true },\n    \n    \"-ms-animation-delay\"               : { multi: \"<time>\", comma: true },\n    \"-ms-animation-direction\"           : { multi: \"normal | alternate\", comma: true },\n    \"-ms-animation-duration\"            : { multi: \"<time>\", comma: true },\n    \"-ms-animation-iteration-count\"     : { multi: \"<number> | infinite\", comma: true },\n    \"-ms-animation-name\"                : { multi: \"none | <ident>\", comma: true },\n    \"-ms-animation-play-state\"          : { multi: \"running | paused\", comma: true },\n    \n    \"-webkit-animation-delay\"               : { multi: \"<time>\", comma: true },\n    \"-webkit-animation-direction\"           : { multi: \"normal | alternate\", comma: true },\n    \"-webkit-animation-duration\"            : { multi: \"<time>\", comma: true },\n    \"-webkit-animation-iteration-count\"     : { multi: \"<number> | infinite\", comma: true },\n    \"-webkit-animation-name\"                : { multi: \"none | <ident>\", comma: true },\n    \"-webkit-animation-play-state\"          : { multi: \"running | paused\", comma: true },\n    \n    \"-o-animation-delay\"               : { multi: \"<time>\", comma: true },\n    \"-o-animation-direction\"           : { multi: \"normal | alternate\", comma: true },\n    \"-o-animation-duration\"            : { multi: \"<time>\", comma: true },\n    \"-o-animation-iteration-count\"     : { multi: \"<number> | infinite\", comma: true },\n    \"-o-animation-name\"                : { multi: \"none | <ident>\", comma: true },\n    \"-o-animation-play-state\"          : { multi: \"running | paused\", comma: true },        \n    \n    \"appearance\"                    : \"icon | window | desktop | workspace | document | tooltip | dialog | button | push-button | hyperlink | radio-button | checkbox | menu-item | tab | menu | menubar | pull-down-menu | pop-up-menu | list-menu | radio-group | checkbox-group | outline-tree | range | field | combo-box | signature | password | normal | inherit\",\n    \"azimuth\"                       : function (expression) {\n        var simple      = \"<angle> | leftwards | rightwards | inherit\",\n            direction   = \"left-side | far-left | left | center-left | center | center-right | right | far-right | right-side\",\n            behind      = false,\n            valid       = false,\n            part;\n        \n        if (!ValidationTypes.isAny(expression, simple)) {\n            if (ValidationTypes.isAny(expression, \"behind\")) {\n                behind = true;\n                valid = true;\n            }\n            \n            if (ValidationTypes.isAny(expression, direction)) {\n                valid = true;\n                if (!behind) {\n                    ValidationTypes.isAny(expression, \"behind\");\n                }\n            }\n        }\n        \n        if (expression.hasNext()) {\n            part = expression.next();\n            if (valid) {\n                throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            } else {\n                throw new ValidationError(\"Expected (<'azimuth'>) but found '\" + part + \"'.\", part.line, part.col);\n            }\n        }        \n    },\n    \n    //B\n    \"backface-visibility\"           : \"visible | hidden\",\n    \"background\"                    : 1,\n    \"background-attachment\"         : { multi: \"<attachment>\", comma: true },\n    \"background-clip\"               : { multi: \"<box>\", comma: true },\n    \"background-color\"              : \"<color> | inherit\",\n    \"background-image\"              : { multi: \"<bg-image>\", comma: true },\n    \"background-origin\"             : { multi: \"<box>\", comma: true },\n    \"background-position\"           : { multi: \"<bg-position>\", comma: true },\n    \"background-repeat\"             : { multi: \"<repeat-style>\" },\n    \"background-size\"               : { multi: \"<bg-size>\", comma: true },\n    \"baseline-shift\"                : \"baseline | sub | super | <percentage> | <length>\",\n    \"binding\"                       : 1,\n    \"bleed\"                         : \"<length>\",\n    \"bookmark-label\"                : \"<content> | <attr> | <string>\",\n    \"bookmark-level\"                : \"none | <integer>\",\n    \"bookmark-state\"                : \"open | closed\",\n    \"bookmark-target\"               : \"none | <uri> | <attr>\",\n    \"border\"                        : \"<border-width> || <border-style> || <color>\",\n    \"border-bottom\"                 : \"<border-width> || <border-style> || <color>\",\n    \"border-bottom-color\"           : \"<color>\",\n    \"border-bottom-left-radius\"     :  \"<x-one-radius>\",\n    \"border-bottom-right-radius\"    :  \"<x-one-radius>\",\n    \"border-bottom-style\"           : \"<border-style>\",\n    \"border-bottom-width\"           : \"<border-width>\",\n    \"border-collapse\"               : \"collapse | separate | inherit\",\n    \"border-color\"                  : { multi: \"<color> | inherit\", max: 4 },\n    \"border-image\"                  : 1,\n    \"border-image-outset\"           : { multi: \"<length> | <number>\", max: 4 },\n    \"border-image-repeat\"           : { multi: \"stretch | repeat | round\", max: 2 },\n    \"border-image-slice\"            : function(expression) {\n        \n        var valid   = false,\n            numeric = \"<number> | <percentage>\",\n            fill    = false,\n            count   = 0,\n            max     = 4,\n            part;\n        \n        if (ValidationTypes.isAny(expression, \"fill\")) {\n            fill = true;\n            valid = true;\n        }\n        \n        while (expression.hasNext() && count < max) {\n            valid = ValidationTypes.isAny(expression, numeric);\n            if (!valid) {\n                break;\n            }\n            count++;\n        }\n        \n        \n        if (!fill) {\n            ValidationTypes.isAny(expression, \"fill\");\n        } else {\n            valid = true;\n        }\n        \n        if (expression.hasNext()) {\n            part = expression.next();\n            if (valid) {\n                throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            } else {\n                throw new ValidationError(\"Expected ([<number> | <percentage>]{1,4} && fill?) but found '\" + part + \"'.\", part.line, part.col);\n            }\n        }         \n    },\n    \"border-image-source\"           : \"<image> | none\",\n    \"border-image-width\"            : { multi: \"<length> | <percentage> | <number> | auto\", max: 4 },\n    \"border-left\"                   : \"<border-width> || <border-style> || <color>\",\n    \"border-left-color\"             : \"<color> | inherit\",\n    \"border-left-style\"             : \"<border-style>\",\n    \"border-left-width\"             : \"<border-width>\",\n    \"border-radius\"                 : function(expression) {\n        \n        var valid   = false,\n            numeric = \"<length> | <percentage>\",\n            slash   = false,\n            fill    = false,\n            count   = 0,\n            max     = 8,\n            part;\n\n        while (expression.hasNext() && count < max) {\n            valid = ValidationTypes.isAny(expression, numeric);\n            if (!valid) {\n            \n                if (expression.peek() == \"/\" && count > 1 && !slash) {\n                    slash = true;\n                    max = count + 5;\n                    expression.next();\n                } else {\n                    break;\n                }\n            }\n            count++;\n        }\n        \n        if (expression.hasNext()) {\n            part = expression.next();\n            if (valid) {\n                throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            } else {\n                throw new ValidationError(\"Expected (<'border-radius'>) but found '\" + part + \"'.\", part.line, part.col);\n            }\n        }         \n    },\n    \"border-right\"                  : \"<border-width> || <border-style> || <color>\",\n    \"border-right-color\"            : \"<color> | inherit\",\n    \"border-right-style\"            : \"<border-style>\",\n    \"border-right-width\"            : \"<border-width>\",\n    \"border-spacing\"                : { multi: \"<length> | inherit\", max: 2 },\n    \"border-style\"                  : { multi: \"<border-style>\", max: 4 },\n    \"border-top\"                    : \"<border-width> || <border-style> || <color>\",\n    \"border-top-color\"              : \"<color> | inherit\",\n    \"border-top-left-radius\"        : \"<x-one-radius>\",\n    \"border-top-right-radius\"       : \"<x-one-radius>\",\n    \"border-top-style\"              : \"<border-style>\",\n    \"border-top-width\"              : \"<border-width>\",\n    \"border-width\"                  : { multi: \"<border-width>\", max: 4 },\n    \"bottom\"                        : \"<margin-width> | inherit\", \n    \"box-align\"                     : \"start | end | center | baseline | stretch\",        //http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/\n    \"box-decoration-break\"          : \"slice |clone\",\n    \"box-direction\"                 : \"normal | reverse | inherit\",\n    \"box-flex\"                      : \"<number>\",\n    \"box-flex-group\"                : \"<integer>\",\n    \"box-lines\"                     : \"single | multiple\",\n    \"box-ordinal-group\"             : \"<integer>\",\n    \"box-orient\"                    : \"horizontal | vertical | inline-axis | block-axis | inherit\",\n    \"box-pack\"                      : \"start | end | center | justify\",\n    \"box-shadow\"                    : function (expression) {\n        var result      = false,\n            part;\n\n        if (!ValidationTypes.isAny(expression, \"none\")) {\n            Validation.multiProperty(\"<shadow>\", expression, true, Infinity);                       \n        } else {\n            if (expression.hasNext()) {\n                part = expression.next();\n                throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            }   \n        }\n    },\n    \"box-sizing\"                    : \"content-box | border-box | inherit\",\n    \"break-after\"                   : \"auto | always | avoid | left | right | page | column | avoid-page | avoid-column\",\n    \"break-before\"                  : \"auto | always | avoid | left | right | page | column | avoid-page | avoid-column\",\n    \"break-inside\"                  : \"auto | avoid | avoid-page | avoid-column\",\n    \n    //C\n    \"caption-side\"                  : \"top | bottom | inherit\",\n    \"clear\"                         : \"none | right | left | both | inherit\",\n    \"clip\"                          : 1,\n    \"color\"                         : \"<color> | inherit\",\n    \"color-profile\"                 : 1,\n    \"column-count\"                  : \"<integer> | auto\",                      //http://www.w3.org/TR/css3-multicol/\n    \"column-fill\"                   : \"auto | balance\",\n    \"column-gap\"                    : \"<length> | normal\",\n    \"column-rule\"                   : \"<border-width> || <border-style> || <color>\",\n    \"column-rule-color\"             : \"<color>\",\n    \"column-rule-style\"             : \"<border-style>\",\n    \"column-rule-width\"             : \"<border-width>\",\n    \"column-span\"                   : \"none | all\",\n    \"column-width\"                  : \"<length> | auto\",\n    \"columns\"                       : 1,\n    \"content\"                       : 1,\n    \"counter-increment\"             : 1,\n    \"counter-reset\"                 : 1,\n    \"crop\"                          : \"<shape> | auto\",\n    \"cue\"                           : \"cue-after | cue-before | inherit\",\n    \"cue-after\"                     : 1,\n    \"cue-before\"                    : 1,\n    \"cursor\"                        : 1,\n    \n    //D\n    \"direction\"                     : \"ltr | rtl | inherit\",\n    \"display\"                       : \"inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | box | inline-box | grid | inline-grid | none | inherit\",\n    \"dominant-baseline\"             : 1,\n    \"drop-initial-after-adjust\"     : \"central | middle | after-edge | text-after-edge | ideographic | alphabetic | mathematical | <percentage> | <length>\",\n    \"drop-initial-after-align\"      : \"baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical\",\n    \"drop-initial-before-adjust\"    : \"before-edge | text-before-edge | central | middle | hanging | mathematical | <percentage> | <length>\",\n    \"drop-initial-before-align\"     : \"caps-height | baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical\",\n    \"drop-initial-size\"             : \"auto | line | <length> | <percentage>\",\n    \"drop-initial-value\"            : \"initial | <integer>\",\n    \n    //E\n    \"elevation\"                     : \"<angle> | below | level | above | higher | lower | inherit\",\n    \"empty-cells\"                   : \"show | hide | inherit\",\n    \n    //F\n    \"filter\"                        : 1,\n    \"fit\"                           : \"fill | hidden | meet | slice\",\n    \"fit-position\"                  : 1,\n    \"float\"                         : \"left | right | none | inherit\",    \n    \"float-offset\"                  : 1,\n    \"font\"                          : 1,\n    \"font-family\"                   : 1,\n    \"font-size\"                     : \"<absolute-size> | <relative-size> | <length> | <percentage> | inherit\",\n    \"font-size-adjust\"              : \"<number> | none | inherit\",\n    \"font-stretch\"                  : \"normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded | inherit\",\n    \"font-style\"                    : \"normal | italic | oblique | inherit\",\n    \"font-variant\"                  : \"normal | small-caps | inherit\",\n    \"font-weight\"                   : \"normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit\",\n    \n    //G\n    \"grid-cell-stacking\"            : \"columns | rows | layer\",\n    \"grid-column\"                   : 1,\n    \"grid-columns\"                  : 1,\n    \"grid-column-align\"             : \"start | end | center | stretch\",\n    \"grid-column-sizing\"            : 1,\n    \"grid-column-span\"              : \"<integer>\",\n    \"grid-flow\"                     : \"none | rows | columns\",\n    \"grid-layer\"                    : \"<integer>\",\n    \"grid-row\"                      : 1,\n    \"grid-rows\"                     : 1,\n    \"grid-row-align\"                : \"start | end | center | stretch\",\n    \"grid-row-span\"                 : \"<integer>\",\n    \"grid-row-sizing\"               : 1,\n    \n    //H\n    \"hanging-punctuation\"           : 1,\n    \"height\"                        : \"<margin-width> | inherit\",\n    \"hyphenate-after\"               : \"<integer> | auto\",\n    \"hyphenate-before\"              : \"<integer> | auto\",\n    \"hyphenate-character\"           : \"<string> | auto\",\n    \"hyphenate-lines\"               : \"no-limit | <integer>\",\n    \"hyphenate-resource\"            : 1,\n    \"hyphens\"                       : \"none | manual | auto\",\n    \n    //I\n    \"icon\"                          : 1,\n    \"image-orientation\"             : \"angle | auto\",\n    \"image-rendering\"               : 1,\n    \"image-resolution\"              : 1,\n    \"inline-box-align\"              : \"initial | last | <integer>\",\n    \n    //L\n    \"left\"                          : \"<margin-width> | inherit\",\n    \"letter-spacing\"                : \"<length> | normal | inherit\",\n    \"line-height\"                   : \"<number> | <length> | <percentage> | normal | inherit\",\n    \"line-break\"                    : \"auto | loose | normal | strict\",\n    \"line-stacking\"                 : 1,\n    \"line-stacking-ruby\"            : \"exclude-ruby | include-ruby\",\n    \"line-stacking-shift\"           : \"consider-shifts | disregard-shifts\",\n    \"line-stacking-strategy\"        : \"inline-line-height | block-line-height | max-height | grid-height\",\n    \"list-style\"                    : 1,\n    \"list-style-image\"              : \"<uri> | none | inherit\",\n    \"list-style-position\"           : \"inside | outside | inherit\",\n    \"list-style-type\"               : \"disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit\",\n    \n    //M\n    \"margin\"                        : { multi: \"<margin-width> | inherit\", max: 4 },\n    \"margin-bottom\"                 : \"<margin-width> | inherit\",\n    \"margin-left\"                   : \"<margin-width> | inherit\",\n    \"margin-right\"                  : \"<margin-width> | inherit\",\n    \"margin-top\"                    : \"<margin-width> | inherit\",\n    \"mark\"                          : 1,\n    \"mark-after\"                    : 1,\n    \"mark-before\"                   : 1,\n    \"marks\"                         : 1,\n    \"marquee-direction\"             : 1,\n    \"marquee-play-count\"            : 1,\n    \"marquee-speed\"                 : 1,\n    \"marquee-style\"                 : 1,\n    \"max-height\"                    : \"<length> | <percentage> | none | inherit\",\n    \"max-width\"                     : \"<length> | <percentage> | none | inherit\",\n    \"min-height\"                    : \"<length> | <percentage> | inherit\",\n    \"min-width\"                     : \"<length> | <percentage> | inherit\",\n    \"move-to\"                       : 1,\n    \n    //N\n    \"nav-down\"                      : 1,\n    \"nav-index\"                     : 1,\n    \"nav-left\"                      : 1,\n    \"nav-right\"                     : 1,\n    \"nav-up\"                        : 1,\n    \n    //O\n    \"opacity\"                       : \"<number> | inherit\",\n    \"orphans\"                       : \"<integer> | inherit\",\n    \"outline\"                       : 1,\n    \"outline-color\"                 : \"<color> | invert | inherit\",\n    \"outline-offset\"                : 1,\n    \"outline-style\"                 : \"<border-style> | inherit\",\n    \"outline-width\"                 : \"<border-width> | inherit\",\n    \"overflow\"                      : \"visible | hidden | scroll | auto | inherit\",\n    \"overflow-style\"                : 1,\n    \"overflow-x\"                    : 1,\n    \"overflow-y\"                    : 1,\n    \n    //P\n    \"padding\"                       : { multi: \"<padding-width> | inherit\", max: 4 },\n    \"padding-bottom\"                : \"<padding-width> | inherit\",\n    \"padding-left\"                  : \"<padding-width> | inherit\",\n    \"padding-right\"                 : \"<padding-width> | inherit\",\n    \"padding-top\"                   : \"<padding-width> | inherit\",\n    \"page\"                          : 1,\n    \"page-break-after\"              : \"auto | always | avoid | left | right | inherit\",\n    \"page-break-before\"             : \"auto | always | avoid | left | right | inherit\",\n    \"page-break-inside\"             : \"auto | avoid | inherit\",\n    \"page-policy\"                   : 1,\n    \"pause\"                         : 1,\n    \"pause-after\"                   : 1,\n    \"pause-before\"                  : 1,\n    \"perspective\"                   : 1,\n    \"perspective-origin\"            : 1,\n    \"phonemes\"                      : 1,\n    \"pitch\"                         : 1,\n    \"pitch-range\"                   : 1,\n    \"play-during\"                   : 1,\n    \"position\"                      : \"static | relative | absolute | fixed | inherit\",\n    \"presentation-level\"            : 1,\n    \"punctuation-trim\"              : 1,\n    \n    //Q\n    \"quotes\"                        : 1,\n    \n    //R\n    \"rendering-intent\"              : 1,\n    \"resize\"                        : 1,\n    \"rest\"                          : 1,\n    \"rest-after\"                    : 1,\n    \"rest-before\"                   : 1,\n    \"richness\"                      : 1,\n    \"right\"                         : \"<margin-width> | inherit\",\n    \"rotation\"                      : 1,\n    \"rotation-point\"                : 1,\n    \"ruby-align\"                    : 1,\n    \"ruby-overhang\"                 : 1,\n    \"ruby-position\"                 : 1,\n    \"ruby-span\"                     : 1,\n    \n    //S\n    \"size\"                          : 1,\n    \"speak\"                         : \"normal | none | spell-out | inherit\",\n    \"speak-header\"                  : \"once | always | inherit\",\n    \"speak-numeral\"                 : \"digits | continuous | inherit\",\n    \"speak-punctuation\"             : \"code | none | inherit\",\n    \"speech-rate\"                   : 1,\n    \"src\"                           : 1,\n    \"stress\"                        : 1,\n    \"string-set\"                    : 1,\n    \n    \"table-layout\"                  : \"auto | fixed | inherit\",\n    \"tab-size\"                      : \"<integer> | <length>\",\n    \"target\"                        : 1,\n    \"target-name\"                   : 1,\n    \"target-new\"                    : 1,\n    \"target-position\"               : 1,\n    \"text-align\"                    : \"left | right | center | justify | inherit\" ,\n    \"text-align-last\"               : 1,\n    \"text-decoration\"               : 1,\n    \"text-emphasis\"                 : 1,\n    \"text-height\"                   : 1,\n    \"text-indent\"                   : \"<length> | <percentage> | inherit\",\n    \"text-justify\"                  : \"auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida\",\n    \"text-outline\"                  : 1,\n    \"text-overflow\"                 : 1,\n    \"text-shadow\"                   : 1,\n    \"text-transform\"                : \"capitalize | uppercase | lowercase | none | inherit\",\n    \"text-wrap\"                     : \"normal | none | avoid\",\n    \"top\"                           : \"<margin-width> | inherit\",\n    \"transform\"                     : 1,\n    \"transform-origin\"              : 1,\n    \"transform-style\"               : 1,\n    \"transition\"                    : 1,\n    \"transition-delay\"              : 1,\n    \"transition-duration\"           : 1,\n    \"transition-property\"           : 1,\n    \"transition-timing-function\"    : 1,\n    \n    //U\n    \"unicode-bidi\"                  : \"normal | embed | bidi-override | inherit\",\n    \"user-modify\"                   : \"read-only | read-write | write-only | inherit\",\n    \"user-select\"                   : \"none | text | toggle | element | elements | all | inherit\",\n    \n    //V\n    \"vertical-align\"                : \"<percentage> | <length> | baseline | sub | super | top | text-top | middle | bottom | text-bottom | inherit\",\n    \"visibility\"                    : \"visible | hidden | collapse | inherit\",\n    \"voice-balance\"                 : 1,\n    \"voice-duration\"                : 1,\n    \"voice-family\"                  : 1,\n    \"voice-pitch\"                   : 1,\n    \"voice-pitch-range\"             : 1,\n    \"voice-rate\"                    : 1,\n    \"voice-stress\"                  : 1,\n    \"voice-volume\"                  : 1,\n    \"volume\"                        : 1,\n    \n    //W\n    \"white-space\"                   : \"normal | pre | nowrap | pre-wrap | pre-line | inherit\",\n    \"white-space-collapse\"          : 1,\n    \"widows\"                        : \"<integer> | inherit\",\n    \"width\"                         : \"<length> | <percentage> | auto | inherit\" ,\n    \"word-break\"                    : \"normal | keep-all | break-all\",\n    \"word-spacing\"                  : \"<length> | normal | inherit\",\n    \"word-wrap\"                     : 1,\n    \n    //Z\n    \"z-index\"                       : \"<integer> | auto | inherit\",\n    \"zoom\"                          : \"<number> | <percentage> | normal\"\n};\n/*global SyntaxUnit, Parser*/\n/**\n * Represents a selector combinator (whitespace, +, >).\n * @namespace parserlib.css\n * @class PropertyName\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} text The text representation of the unit. \n * @param {String} hack The type of IE hack applied (\"*\", \"_\", or null).\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction PropertyName(text, hack, line, col){\n    \n    SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_NAME_TYPE);\n\n    /**\n     * The type of IE hack applied (\"*\", \"_\", or null).\n     * @type String\n     * @property hack\n     */\n    this.hack = hack;\n\n}\n\nPropertyName.prototype = new SyntaxUnit();\nPropertyName.prototype.constructor = PropertyName;\nPropertyName.prototype.toString = function(){\n    return (this.hack ? this.hack : \"\") + this.text;\n};\n\n/*global SyntaxUnit, Parser*/\n/**\n * Represents a single part of a CSS property value, meaning that it represents\n * just everything single part between \":\" and \";\". If there are multiple values\n * separated by commas, this type represents just one of the values.\n * @param {String[]} parts An array of value parts making up this value.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n * @namespace parserlib.css\n * @class PropertyValue\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n */\nfunction PropertyValue(parts, line, col){\n\n    SyntaxUnit.call(this, parts.join(\" \"), line, col, Parser.PROPERTY_VALUE_TYPE);\n    \n    /**\n     * The parts that make up the selector.\n     * @type Array\n     * @property parts\n     */\n    this.parts = parts;\n    \n}\n\nPropertyValue.prototype = new SyntaxUnit();\nPropertyValue.prototype.constructor = PropertyValue;\n\n\n/*global SyntaxUnit, Parser*/\n/**\n * A utility class that allows for easy iteration over the various parts of a\n * property value.\n * @param {parserlib.css.PropertyValue} value The property value to iterate over.\n * @namespace parserlib.css\n * @class PropertyValueIterator\n * @constructor\n */\nfunction PropertyValueIterator(value){\n\n    /** \n     * Iterator value\n     * @type int\n     * @property _i\n     * @private\n     */\n    this._i = 0;\n    \n    /**\n     * The parts that make up the value.\n     * @type Array\n     * @property _parts\n     * @private\n     */\n    this._parts = value.parts;\n    \n    /**\n     * Keeps track of bookmarks along the way.\n     * @type Array\n     * @property _marks\n     * @private\n     */\n    this._marks = [];\n    \n    /**\n     * Holds the original property value.\n     * @type parserlib.css.PropertyValue\n     * @property value\n     */\n    this.value = value;\n    \n}\n\n/**\n * Returns the total number of parts in the value.\n * @return {int} The total number of parts in the value.\n * @method count\n */\nPropertyValueIterator.prototype.count = function(){\n    return this._parts.length;\n};\n\n/**\n * Indicates if the iterator is positioned at the first item.\n * @return {Boolean} True if positioned at first item, false if not.\n * @method isFirst\n */\nPropertyValueIterator.prototype.isFirst = function(){\n    return this._i === 0;\n};\n\n/**\n * Indicates if there are more parts of the property value.\n * @return {Boolean} True if there are more parts, false if not.\n * @method hasNext\n */\nPropertyValueIterator.prototype.hasNext = function(){\n    return (this._i < this._parts.length);\n};\n\n/**\n * Marks the current spot in the iteration so it can be restored to\n * later on.\n * @return {void}\n * @method mark\n */\nPropertyValueIterator.prototype.mark = function(){\n    this._marks.push(this._i);\n};\n\n/**\n * Returns the next part of the property value or null if there is no next\n * part. Does not move the internal counter forward.\n * @return {parserlib.css.PropertyValuePart} The next part of the property value or null if there is no next\n * part.\n * @method peek\n */\nPropertyValueIterator.prototype.peek = function(count){\n    return this.hasNext() ? this._parts[this._i + (count || 0)] : null;\n};\n\n/**\n * Returns the next part of the property value or null if there is no next\n * part.\n * @return {parserlib.css.PropertyValuePart} The next part of the property value or null if there is no next\n * part.\n * @method next\n */\nPropertyValueIterator.prototype.next = function(){\n    return this.hasNext() ? this._parts[this._i++] : null;\n};\n\n/**\n * Returns the previous part of the property value or null if there is no\n * previous part.\n * @return {parserlib.css.PropertyValuePart} The previous part of the \n * property value or null if there is no next part.\n * @method previous\n */\nPropertyValueIterator.prototype.previous = function(){\n    return this._i > 0 ? this._parts[--this._i] : null;\n};\n\n/**\n * Restores the last saved bookmark.\n * @return {void}\n * @method restore\n */\nPropertyValueIterator.prototype.restore = function(){\n    if (this._marks.length){\n        this._i = this._marks.pop();\n    }\n};\n\n\n/*global SyntaxUnit, Parser, Colors*/\n/**\n * Represents a single part of a CSS property value, meaning that it represents\n * just one part of the data between \":\" and \";\".\n * @param {String} text The text representation of the unit.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n * @namespace parserlib.css\n * @class PropertyValuePart\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n */\nfunction PropertyValuePart(text, line, col){\n\n    SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_VALUE_PART_TYPE);\n    \n    /**\n     * Indicates the type of value unit.\n     * @type String\n     * @property type\n     */\n    this.type = \"unknown\";\n\n    //figure out what type of data it is\n    \n    var temp;\n    \n    //it is a measurement?\n    if (/^([+\\-]?[\\d\\.]+)([a-z]+)$/i.test(text)){  //dimension\n        this.type = \"dimension\";\n        this.value = +RegExp.$1;\n        this.units = RegExp.$2;\n        \n        //try to narrow down\n        switch(this.units.toLowerCase()){\n        \n            case \"em\":\n            case \"rem\":\n            case \"ex\":\n            case \"px\":\n            case \"cm\":\n            case \"mm\":\n            case \"in\":\n            case \"pt\":\n            case \"pc\":\n            case \"ch\":\n                this.type = \"length\";\n                break;\n                \n            case \"deg\":\n            case \"rad\":\n            case \"grad\":\n                this.type = \"angle\";\n                break;\n            \n            case \"ms\":\n            case \"s\":\n                this.type = \"time\";\n                break;\n            \n            case \"hz\":\n            case \"khz\":\n                this.type = \"frequency\";\n                break;\n            \n            case \"dpi\":\n            case \"dpcm\":\n                this.type = \"resolution\";\n                break;\n                \n            //default\n                \n        }\n        \n    } else if (/^([+\\-]?[\\d\\.]+)%$/i.test(text)){  //percentage\n        this.type = \"percentage\";\n        this.value = +RegExp.$1;\n    } else if (/^([+\\-]?[\\d\\.]+)%$/i.test(text)){  //percentage\n        this.type = \"percentage\";\n        this.value = +RegExp.$1;\n    } else if (/^([+\\-]?\\d+)$/i.test(text)){  //integer\n        this.type = \"integer\";\n        this.value = +RegExp.$1;\n    } else if (/^([+\\-]?[\\d\\.]+)$/i.test(text)){  //number\n        this.type = \"number\";\n        this.value = +RegExp.$1;\n    \n    } else if (/^#([a-f0-9]{3,6})/i.test(text)){  //hexcolor\n        this.type = \"color\";\n        temp = RegExp.$1;\n        if (temp.length == 3){\n            this.red    = parseInt(temp.charAt(0)+temp.charAt(0),16);\n            this.green  = parseInt(temp.charAt(1)+temp.charAt(1),16);\n            this.blue   = parseInt(temp.charAt(2)+temp.charAt(2),16);            \n        } else {\n            this.red    = parseInt(temp.substring(0,2),16);\n            this.green  = parseInt(temp.substring(2,4),16);\n            this.blue   = parseInt(temp.substring(4,6),16);            \n        }\n    } else if (/^rgb\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)/i.test(text)){ //rgb() color with absolute numbers\n        this.type   = \"color\";\n        this.red    = +RegExp.$1;\n        this.green  = +RegExp.$2;\n        this.blue   = +RegExp.$3;\n    } else if (/^rgb\\(\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*\\)/i.test(text)){ //rgb() color with percentages\n        this.type   = \"color\";\n        this.red    = +RegExp.$1 * 255 / 100;\n        this.green  = +RegExp.$2 * 255 / 100;\n        this.blue   = +RegExp.$3 * 255 / 100;\n    } else if (/^rgba\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*([\\d\\.]+)\\s*\\)/i.test(text)){ //rgba() color with absolute numbers\n        this.type   = \"color\";\n        this.red    = +RegExp.$1;\n        this.green  = +RegExp.$2;\n        this.blue   = +RegExp.$3;\n        this.alpha  = +RegExp.$4;\n    } else if (/^rgba\\(\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*,\\s*([\\d\\.]+)\\s*\\)/i.test(text)){ //rgba() color with percentages\n        this.type   = \"color\";\n        this.red    = +RegExp.$1 * 255 / 100;\n        this.green  = +RegExp.$2 * 255 / 100;\n        this.blue   = +RegExp.$3 * 255 / 100;\n        this.alpha  = +RegExp.$4;        \n    } else if (/^hsl\\(\\s*(\\d+)\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*\\)/i.test(text)){ //hsl()\n        this.type   = \"color\";\n        this.hue    = +RegExp.$1;\n        this.saturation = +RegExp.$2 / 100;\n        this.lightness  = +RegExp.$3 / 100;        \n    } else if (/^hsla\\(\\s*(\\d+)\\s*,\\s*(\\d+)%\\s*,\\s*(\\d+)%\\s*,\\s*([\\d\\.]+)\\s*\\)/i.test(text)){ //hsla() color with percentages\n        this.type   = \"color\";\n        this.hue    = +RegExp.$1;\n        this.saturation = +RegExp.$2 / 100;\n        this.lightness  = +RegExp.$3 / 100;        \n        this.alpha  = +RegExp.$4;        \n    } else if (/^url\\([\"']?([^\\)\"']+)[\"']?\\)/i.test(text)){ //URI\n        this.type   = \"uri\";\n        this.uri    = RegExp.$1;\n    } else if (/^([^\\(]+)\\(/i.test(text)){\n        this.type   = \"function\";\n        this.name   = RegExp.$1;\n        this.value  = text;\n    } else if (/^[\"'][^\"']*[\"']/.test(text)){    //string\n        this.type   = \"string\";\n        this.value  = eval(text);\n    } else if (Colors[text.toLowerCase()]){  //named color\n        this.type   = \"color\";\n        temp        = Colors[text.toLowerCase()].substring(1);\n        this.red    = parseInt(temp.substring(0,2),16);\n        this.green  = parseInt(temp.substring(2,4),16);\n        this.blue   = parseInt(temp.substring(4,6),16);         \n    } else if (/^[\\,\\/]$/.test(text)){\n        this.type   = \"operator\";\n        this.value  = text;\n    } else if (/^[a-z\\-\\u0080-\\uFFFF][a-z0-9\\-\\u0080-\\uFFFF]*$/i.test(text)){\n        this.type   = \"identifier\";\n        this.value  = text;\n    }\n\n}\n\nPropertyValuePart.prototype = new SyntaxUnit();\nPropertyValuePart.prototype.constructor = PropertyValuePart;\n\n/**\n * Create a new syntax unit based solely on the given token.\n * Convenience method for creating a new syntax unit when\n * it represents a single token instead of multiple.\n * @param {Object} token The token object to represent.\n * @return {parserlib.css.PropertyValuePart} The object representing the token.\n * @static\n * @method fromToken\n */\nPropertyValuePart.fromToken = function(token){\n    return new PropertyValuePart(token.value, token.startLine, token.startCol);\n};\nvar Pseudos = {\n    \":first-letter\": 1,\n    \":first-line\":   1,\n    \":before\":       1,\n    \":after\":        1\n};\n\nPseudos.ELEMENT = 1;\nPseudos.CLASS = 2;\n\nPseudos.isElement = function(pseudo){\n    return pseudo.indexOf(\"::\") === 0 || Pseudos[pseudo.toLowerCase()] == Pseudos.ELEMENT;\n};\n/*global SyntaxUnit, Parser, Specificity*/\n/**\n * Represents an entire single selector, including all parts but not\n * including multiple selectors (those separated by commas).\n * @namespace parserlib.css\n * @class Selector\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {Array} parts Array of selectors parts making up this selector.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction Selector(parts, line, col){\n    \n    SyntaxUnit.call(this, parts.join(\" \"), line, col, Parser.SELECTOR_TYPE);\n    \n    /**\n     * The parts that make up the selector.\n     * @type Array\n     * @property parts\n     */\n    this.parts = parts;\n    \n    /**\n     * The specificity of the selector.\n     * @type parserlib.css.Specificity\n     * @property specificity\n     */\n    this.specificity = Specificity.calculate(this);\n\n}\n\nSelector.prototype = new SyntaxUnit();\nSelector.prototype.constructor = Selector;\n\n\n/*global SyntaxUnit, Parser*/\n/**\n * Represents a single part of a selector string, meaning a single set of\n * element name and modifiers. This does not include combinators such as\n * spaces, +, >, etc.\n * @namespace parserlib.css\n * @class SelectorPart\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} elementName The element name in the selector or null\n *      if there is no element name.\n * @param {Array} modifiers Array of individual modifiers for the element.\n *      May be empty if there are none.\n * @param {String} text The text representation of the unit. \n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction SelectorPart(elementName, modifiers, text, line, col){\n    \n    SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_PART_TYPE);\n\n    /**\n     * The tag name of the element to which this part\n     * of the selector affects.\n     * @type String\n     * @property elementName\n     */\n    this.elementName = elementName;\n    \n    /**\n     * The parts that come after the element name, such as class names, IDs,\n     * pseudo classes/elements, etc.\n     * @type Array\n     * @property modifiers\n     */\n    this.modifiers = modifiers;\n\n}\n\nSelectorPart.prototype = new SyntaxUnit();\nSelectorPart.prototype.constructor = SelectorPart;\n\n\n/*global SyntaxUnit, Parser*/\n/**\n * Represents a selector modifier string, meaning a class name, element name,\n * element ID, pseudo rule, etc.\n * @namespace parserlib.css\n * @class SelectorSubPart\n * @extends parserlib.util.SyntaxUnit\n * @constructor\n * @param {String} text The text representation of the unit. \n * @param {String} type The type of selector modifier.\n * @param {int} line The line of text on which the unit resides.\n * @param {int} col The column of text on which the unit resides.\n */\nfunction SelectorSubPart(text, type, line, col){\n    \n    SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_SUB_PART_TYPE);\n\n    /**\n     * The type of modifier.\n     * @type String\n     * @property type\n     */\n    this.type = type;\n    \n    /**\n     * Some subparts have arguments, this represents them.\n     * @type Array\n     * @property args\n     */\n    this.args = [];\n\n}\n\nSelectorSubPart.prototype = new SyntaxUnit();\nSelectorSubPart.prototype.constructor = SelectorSubPart;\n\n\n/*global Pseudos, SelectorPart*/\n/**\n * Represents a selector's specificity.\n * @namespace parserlib.css\n * @class Specificity\n * @constructor\n * @param {int} a Should be 1 for inline styles, zero for stylesheet styles\n * @param {int} b Number of ID selectors\n * @param {int} c Number of classes and pseudo classes\n * @param {int} d Number of element names and pseudo elements\n */\nfunction Specificity(a, b, c, d){\n    this.a = a;\n    this.b = b;\n    this.c = c;\n    this.d = d;\n}\n\nSpecificity.prototype = {\n    constructor: Specificity,\n    \n    /**\n     * Compare this specificity to another.\n     * @param {Specificity} other The other specificity to compare to.\n     * @return {int} -1 if the other specificity is larger, 1 if smaller, 0 if equal.\n     * @method compare\n     */\n    compare: function(other){\n        var comps = [\"a\", \"b\", \"c\", \"d\"],\n            i, len;\n            \n        for (i=0, len=comps.length; i < len; i++){\n            if (this[comps[i]] < other[comps[i]]){\n                return -1;\n            } else if (this[comps[i]] > other[comps[i]]){\n                return 1;\n            }\n        }\n        \n        return 0;\n    },\n    \n    /**\n     * Creates a numeric value for the specificity.\n     * @return {int} The numeric value for the specificity.\n     * @method valueOf\n     */\n    valueOf: function(){\n        return (this.a * 1000) + (this.b * 100) + (this.c * 10) + this.d;\n    },\n    \n    /**\n     * Returns a string representation for specificity.\n     * @return {String} The string representation of specificity.\n     * @method toString\n     */\n    toString: function(){\n        return this.a + \",\" + this.b + \",\" + this.c + \",\" + this.d;\n    }\n\n};\n\n/**\n * Calculates the specificity of the given selector.\n * @param {parserlib.css.Selector} The selector to calculate specificity for.\n * @return {parserlib.css.Specificity} The specificity of the selector.\n * @static\n * @method calculate\n */\nSpecificity.calculate = function(selector){\n\n    var i, len,\n        part,\n        b=0, c=0, d=0;\n        \n    function updateValues(part){\n    \n        var i, j, len, num,\n            elementName = part.elementName ? part.elementName.text : \"\",\n            modifier;\n    \n        if (elementName && elementName.charAt(elementName.length-1) != \"*\") {\n            d++;\n        }    \n    \n        for (i=0, len=part.modifiers.length; i < len; i++){\n            modifier = part.modifiers[i];\n            switch(modifier.type){\n                case \"class\":\n                case \"attribute\":\n                    c++;\n                    break;\n                    \n                case \"id\":\n                    b++;\n                    break;\n                    \n                case \"pseudo\":\n                    if (Pseudos.isElement(modifier.text)){\n                        d++;\n                    } else {\n                        c++;\n                    }                    \n                    break;\n                    \n                case \"not\":\n                    for (j=0, num=modifier.args.length; j < num; j++){\n                        updateValues(modifier.args[j]);\n                    }\n            }    \n         }\n    }\n    \n    for (i=0, len=selector.parts.length; i < len; i++){\n        part = selector.parts[i];\n        \n        if (part instanceof SelectorPart){\n            updateValues(part);                \n        }\n    }\n    \n    return new Specificity(0, b, c, d);\n};\n\n/*global Tokens, TokenStreamBase*/\n\nvar h = /^[0-9a-fA-F]$/,\n    nonascii = /^[\\u0080-\\uFFFF]$/,\n    nl = /\\n|\\r\\n|\\r|\\f/;\n\n//-----------------------------------------------------------------------------\n// Helper functions\n//-----------------------------------------------------------------------------\n\n\nfunction isHexDigit(c){\n    return c !== null && h.test(c);\n}\n\nfunction isDigit(c){\n    return c !== null && /\\d/.test(c);\n}\n\nfunction isWhitespace(c){\n    return c !== null && /\\s/.test(c);\n}\n\nfunction isNewLine(c){\n    return c !== null && nl.test(c);\n}\n\nfunction isNameStart(c){\n    return c !== null && (/[a-z_\\u0080-\\uFFFF\\\\]/i.test(c));\n}\n\nfunction isNameChar(c){\n    return c !== null && (isNameStart(c) || /[0-9\\-\\\\]/.test(c));\n}\n\nfunction isIdentStart(c){\n    return c !== null && (isNameStart(c) || /\\-\\\\/.test(c));\n}\n\nfunction mix(receiver, supplier){\n\tfor (var prop in supplier){\n\t\tif (supplier.hasOwnProperty(prop)){\n\t\t\treceiver[prop] = supplier[prop];\n\t\t}\n\t}\n\treturn receiver;\n}\n\n//-----------------------------------------------------------------------------\n// CSS Token Stream\n//-----------------------------------------------------------------------------\n\n\n/**\n * A token stream that produces CSS tokens.\n * @param {String|Reader} input The source of text to tokenize.\n * @constructor\n * @class TokenStream\n * @namespace parserlib.css\n */\nfunction TokenStream(input){\n\tTokenStreamBase.call(this, input, Tokens);\n}\n\nTokenStream.prototype = mix(new TokenStreamBase(), {\n\n    /**\n     * Overrides the TokenStreamBase method of the same name\n     * to produce CSS tokens.\n     * @param {variant} channel The name of the channel to use\n     *      for the next token.\n     * @return {Object} A token object representing the next token.\n     * @method _getToken\n     * @private\n     */\n    _getToken: function(channel){\n\n        var c,\n            reader = this._reader,\n            token   = null,\n            startLine   = reader.getLine(),\n            startCol    = reader.getCol();\n\n        c = reader.read();\n\n\n        while(c){\n            switch(c){\n\n                /*\n                 * Potential tokens:\n                 * - COMMENT\n                 * - SLASH\n                 * - CHAR\n                 */\n                case \"/\":\n\n                    if(reader.peek() == \"*\"){\n                        token = this.commentToken(c, startLine, startCol);\n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - DASHMATCH\n                 * - INCLUDES\n                 * - PREFIXMATCH\n                 * - SUFFIXMATCH\n                 * - SUBSTRINGMATCH\n                 * - CHAR\n                 */\n                case \"|\":\n                case \"~\":\n                case \"^\":\n                case \"$\":\n                case \"*\":\n                    if(reader.peek() == \"=\"){\n                        token = this.comparisonToken(c, startLine, startCol);\n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - STRING\n                 * - INVALID\n                 */\n                case \"\\\"\":\n                case \"'\":\n                    token = this.stringToken(c, startLine, startCol);\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - HASH\n                 * - CHAR\n                 */\n                case \"#\":\n                    if (isNameChar(reader.peek())){\n                        token = this.hashToken(c, startLine, startCol);\n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - DOT\n                 * - NUMBER\n                 * - DIMENSION\n                 * - PERCENTAGE\n                 */\n                case \".\":\n                    if (isDigit(reader.peek())){\n                        token = this.numberToken(c, startLine, startCol);\n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - CDC\n                 * - MINUS\n                 * - NUMBER\n                 * - DIMENSION\n                 * - PERCENTAGE\n                 */\n                case \"-\":\n                    if (reader.peek() == \"-\"){  //could be closing HTML-style comment\n                        token = this.htmlCommentEndToken(c, startLine, startCol);\n                    } else if (isNameStart(reader.peek())){\n                        token = this.identOrFunctionToken(c, startLine, startCol);\n                    } else {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - IMPORTANT_SYM\n                 * - CHAR\n                 */\n                case \"!\":\n                    token = this.importantToken(c, startLine, startCol);\n                    break;\n\n                /*\n                 * Any at-keyword or CHAR\n                 */\n                case \"@\":\n                    token = this.atRuleToken(c, startLine, startCol);\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - NOT\n                 * - CHAR\n                 */\n                case \":\":\n                    token = this.notToken(c, startLine, startCol);\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - CDO\n                 * - CHAR\n                 */\n                case \"<\":\n                    token = this.htmlCommentStartToken(c, startLine, startCol);\n                    break;\n\n                /*\n                 * Potential tokens:\n                 * - UNICODE_RANGE\n                 * - URL\n                 * - CHAR\n                 */\n                case \"U\":\n                case \"u\":\n                    if (reader.peek() == \"+\"){\n                        token = this.unicodeRangeToken(c, startLine, startCol);\n                        break;\n                    }\n                    /* falls through */\n                default:\n\n                    /*\n                     * Potential tokens:\n                     * - NUMBER\n                     * - DIMENSION\n                     * - LENGTH\n                     * - FREQ\n                     * - TIME\n                     * - EMS\n                     * - EXS\n                     * - ANGLE\n                     */\n                    if (isDigit(c)){\n                        token = this.numberToken(c, startLine, startCol);\n                    } else\n\n                    /*\n                     * Potential tokens:\n                     * - S\n                     */\n                    if (isWhitespace(c)){\n                        token = this.whitespaceToken(c, startLine, startCol);\n                    } else\n\n                    /*\n                     * Potential tokens:\n                     * - IDENT\n                     */\n                    if (isIdentStart(c)){\n                        token = this.identOrFunctionToken(c, startLine, startCol);\n                    } else\n\n                    /*\n                     * Potential tokens:\n                     * - CHAR\n                     * - PLUS\n                     */\n                    {\n                        token = this.charToken(c, startLine, startCol);\n                    }\n\n\n\n\n\n\n            }\n\n            //make sure this token is wanted\n            //TODO: check channel\n            break;\n        }\n\n        if (!token && c === null){\n            token = this.createToken(Tokens.EOF,null,startLine,startCol);\n        }\n\n        return token;\n    },\n\n    //-------------------------------------------------------------------------\n    // Methods to create tokens\n    //-------------------------------------------------------------------------\n\n    /**\n     * Produces a token based on available data and the current\n     * reader position information. This method is called by other\n     * private methods to create tokens and is never called directly.\n     * @param {int} tt The token type.\n     * @param {String} value The text value of the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @param {Object} options (Optional) Specifies a channel property\n     *      to indicate that a different channel should be scanned\n     *      and/or a hide property indicating that the token should\n     *      be hidden.\n     * @return {Object} A token object.\n     * @method createToken\n     */\n    createToken: function(tt, value, startLine, startCol, options){\n        var reader = this._reader;\n        options = options || {};\n\n        return {\n            value:      value,\n            type:       tt,\n            channel:    options.channel,\n            hide:       options.hide || false,\n            startLine:  startLine,\n            startCol:   startCol,\n            endLine:    reader.getLine(),\n            endCol:     reader.getCol()\n        };\n    },\n\n    //-------------------------------------------------------------------------\n    // Methods to create specific tokens\n    //-------------------------------------------------------------------------\n\n    /**\n     * Produces a token for any at-rule. If the at-rule is unknown, then\n     * the token is for a single \"@\" character.\n     * @param {String} first The first character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method atRuleToken\n     */\n    atRuleToken: function(first, startLine, startCol){\n        var rule    = first,\n            reader  = this._reader,\n            tt      = Tokens.CHAR,\n            valid   = false,\n            ident,\n            c;\n\n        /*\n         * First, mark where we are. There are only four @ rules,\n         * so anything else is really just an invalid token.\n         * Basically, if this doesn't match one of the known @\n         * rules, just return '@' as an unknown token and allow\n         * parsing to continue after that point.\n         */\n        reader.mark();\n\n        //try to find the at-keyword\n        ident = this.readName();\n        rule = first + ident;\n        tt = Tokens.type(rule.toLowerCase());\n\n        //if it's not valid, use the first character only and reset the reader\n        if (tt == Tokens.CHAR || tt == Tokens.UNKNOWN){\n            if (rule.length > 1){\n                tt = Tokens.UNKNOWN_SYM;                \n            } else {\n                tt = Tokens.CHAR;\n                rule = first;\n                reader.reset();\n            }\n        }\n\n        return this.createToken(tt, rule, startLine, startCol);\n    },\n\n    /**\n     * Produces a character token based on the given character\n     * and location in the stream. If there's a special (non-standard)\n     * token name, this is used; otherwise CHAR is used.\n     * @param {String} c The character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method charToken\n     */\n    charToken: function(c, startLine, startCol){\n        var tt = Tokens.type(c);\n\n        if (tt == -1){\n            tt = Tokens.CHAR;\n        }\n\n        return this.createToken(tt, c, startLine, startCol);\n    },\n\n    /**\n     * Produces a character token based on the given character\n     * and location in the stream. If there's a special (non-standard)\n     * token name, this is used; otherwise CHAR is used.\n     * @param {String} first The first character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method commentToken\n     */\n    commentToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            comment = this.readComment(first);\n\n        return this.createToken(Tokens.COMMENT, comment, startLine, startCol);\n    },\n\n    /**\n     * Produces a comparison token based on the given character\n     * and location in the stream. The next character must be\n     * read and is already known to be an equals sign.\n     * @param {String} c The character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method comparisonToken\n     */\n    comparisonToken: function(c, startLine, startCol){\n        var reader  = this._reader,\n            comparison  = c + reader.read(),\n            tt      = Tokens.type(comparison) || Tokens.CHAR;\n\n        return this.createToken(tt, comparison, startLine, startCol);\n    },\n\n    /**\n     * Produces a hash token based on the specified information. The\n     * first character provided is the pound sign (#) and then this\n     * method reads a name afterward.\n     * @param {String} first The first character (#) in the hash name.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method hashToken\n     */\n    hashToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            name    = this.readName(first);\n\n        return this.createToken(Tokens.HASH, name, startLine, startCol);\n    },\n\n    /**\n     * Produces a CDO or CHAR token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method htmlCommentStartToken\n     */\n    htmlCommentStartToken: function(first, startLine, startCol){\n        var reader      = this._reader,\n            text        = first;\n\n        reader.mark();\n        text += reader.readCount(3);\n\n        if (text == \"<!--\"){\n            return this.createToken(Tokens.CDO, text, startLine, startCol);\n        } else {\n            reader.reset();\n            return this.charToken(first, startLine, startCol);\n        }\n    },\n\n    /**\n     * Produces a CDC or CHAR token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method htmlCommentEndToken\n     */\n    htmlCommentEndToken: function(first, startLine, startCol){\n        var reader      = this._reader,\n            text        = first;\n\n        reader.mark();\n        text += reader.readCount(2);\n\n        if (text == \"-->\"){\n            return this.createToken(Tokens.CDC, text, startLine, startCol);\n        } else {\n            reader.reset();\n            return this.charToken(first, startLine, startCol);\n        }\n    },\n\n    /**\n     * Produces an IDENT or FUNCTION token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the identifier.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method identOrFunctionToken\n     */\n    identOrFunctionToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            ident   = this.readName(first),\n            tt      = Tokens.IDENT;\n\n        //if there's a left paren immediately after, it's a URI or function\n        if (reader.peek() == \"(\"){\n            ident += reader.read();\n            if (ident.toLowerCase() == \"url(\"){\n                tt = Tokens.URI;\n                ident = this.readURI(ident);\n\n                //didn't find a valid URL or there's no closing paren\n                if (ident.toLowerCase() == \"url(\"){\n                    tt = Tokens.FUNCTION;\n                }\n            } else {\n                tt = Tokens.FUNCTION;\n            }\n        } else if (reader.peek() == \":\"){  //might be an IE function\n\n            //IE-specific functions always being with progid:\n            if (ident.toLowerCase() == \"progid\"){\n                ident += reader.readTo(\"(\");\n                tt = Tokens.IE_FUNCTION;\n            }\n        }\n\n        return this.createToken(tt, ident, startLine, startCol);\n    },\n\n    /**\n     * Produces an IMPORTANT_SYM or CHAR token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method importantToken\n     */\n    importantToken: function(first, startLine, startCol){\n        var reader      = this._reader,\n            important   = first,\n            tt          = Tokens.CHAR,\n            temp,\n            c;\n\n        reader.mark();\n        c = reader.read();\n\n        while(c){\n\n            //there can be a comment in here\n            if (c == \"/\"){\n\n                //if the next character isn't a star, then this isn't a valid !important token\n                if (reader.peek() != \"*\"){\n                    break;\n                } else {\n                    temp = this.readComment(c);\n                    if (temp === \"\"){    //broken!\n                        break;\n                    }\n                }\n            } else if (isWhitespace(c)){\n                important += c + this.readWhitespace();\n            } else if (/i/i.test(c)){\n                temp = reader.readCount(8);\n                if (/mportant/i.test(temp)){\n                    important += c + temp;\n                    tt = Tokens.IMPORTANT_SYM;\n\n                }\n                break;  //we're done\n            } else {\n                break;\n            }\n\n            c = reader.read();\n        }\n\n        if (tt == Tokens.CHAR){\n            reader.reset();\n            return this.charToken(first, startLine, startCol);\n        } else {\n            return this.createToken(tt, important, startLine, startCol);\n        }\n\n\n    },\n\n    /**\n     * Produces a NOT or CHAR token based on the specified information. The\n     * first character is provided and the rest is read by the function to determine\n     * the correct token to create.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method notToken\n     */\n    notToken: function(first, startLine, startCol){\n        var reader      = this._reader,\n            text        = first;\n\n        reader.mark();\n        text += reader.readCount(4);\n\n        if (text.toLowerCase() == \":not(\"){\n            return this.createToken(Tokens.NOT, text, startLine, startCol);\n        } else {\n            reader.reset();\n            return this.charToken(first, startLine, startCol);\n        }\n    },\n\n    /**\n     * Produces a number token based on the given character\n     * and location in the stream. This may return a token of\n     * NUMBER, EMS, EXS, LENGTH, ANGLE, TIME, FREQ, DIMENSION,\n     * or PERCENTAGE.\n     * @param {String} first The first character for the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method numberToken\n     */\n    numberToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            value   = this.readNumber(first),\n            ident,\n            tt      = Tokens.NUMBER,\n            c       = reader.peek();\n\n        if (isIdentStart(c)){\n            ident = this.readName(reader.read());\n            value += ident;\n\n            if (/^em$|^ex$|^px$|^gd$|^rem$|^vw$|^vh$|^vm$|^ch$|^cm$|^mm$|^in$|^pt$|^pc$/i.test(ident)){\n                tt = Tokens.LENGTH;\n            } else if (/^deg|^rad$|^grad$/i.test(ident)){\n                tt = Tokens.ANGLE;\n            } else if (/^ms$|^s$/i.test(ident)){\n                tt = Tokens.TIME;\n            } else if (/^hz$|^khz$/i.test(ident)){\n                tt = Tokens.FREQ;\n            } else if (/^dpi$|^dpcm$/i.test(ident)){\n                tt = Tokens.RESOLUTION;\n            } else {\n                tt = Tokens.DIMENSION;\n            }\n\n        } else if (c == \"%\"){\n            value += reader.read();\n            tt = Tokens.PERCENTAGE;\n        }\n\n        return this.createToken(tt, value, startLine, startCol);\n    },\n\n    /**\n     * Produces a string token based on the given character\n     * and location in the stream. Since strings may be indicated\n     * by single or double quotes, a failure to match starting\n     * and ending quotes results in an INVALID token being generated.\n     * The first character in the string is passed in and then\n     * the rest are read up to and including the final quotation mark.\n     * @param {String} first The first character in the string.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method stringToken\n     */\n    stringToken: function(first, startLine, startCol){\n        var delim   = first,\n            string  = first,\n            reader  = this._reader,\n            prev    = first,\n            tt      = Tokens.STRING,\n            c       = reader.read();\n\n        while(c){\n            string += c;\n\n            //if the delimiter is found with an escapement, we're done.\n            if (c == delim && prev != \"\\\\\"){\n                break;\n            }\n\n            //if there's a newline without an escapement, it's an invalid string\n            if (isNewLine(reader.peek()) && c != \"\\\\\"){\n                tt = Tokens.INVALID;\n                break;\n            }\n\n            //save previous and get next\n            prev = c;\n            c = reader.read();\n        }\n\n        //if c is null, that means we're out of input and the string was never closed\n        if (c === null){\n            tt = Tokens.INVALID;\n        }\n\n        return this.createToken(tt, string, startLine, startCol);\n    },\n\n    unicodeRangeToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            value   = first,\n            temp,\n            tt      = Tokens.CHAR;\n\n        //then it should be a unicode range\n        if (reader.peek() == \"+\"){\n            reader.mark();\n            value += reader.read();\n            value += this.readUnicodeRangePart(true);\n\n            //ensure there's an actual unicode range here\n            if (value.length == 2){\n                reader.reset();\n            } else {\n\n                tt = Tokens.UNICODE_RANGE;\n\n                //if there's a ? in the first part, there can't be a second part\n                if (value.indexOf(\"?\") == -1){\n\n                    if (reader.peek() == \"-\"){\n                        reader.mark();\n                        temp = reader.read();\n                        temp += this.readUnicodeRangePart(false);\n\n                        //if there's not another value, back up and just take the first\n                        if (temp.length == 1){\n                            reader.reset();\n                        } else {\n                            value += temp;\n                        }\n                    }\n\n                }\n            }\n        }\n\n        return this.createToken(tt, value, startLine, startCol);\n    },\n\n    /**\n     * Produces a S token based on the specified information. Since whitespace\n     * may have multiple characters, this consumes all whitespace characters\n     * into a single token.\n     * @param {String} first The first character in the token.\n     * @param {int} startLine The beginning line for the character.\n     * @param {int} startCol The beginning column for the character.\n     * @return {Object} A token object.\n     * @method whitespaceToken\n     */\n    whitespaceToken: function(first, startLine, startCol){\n        var reader  = this._reader,\n            value   = first + this.readWhitespace();\n        return this.createToken(Tokens.S, value, startLine, startCol);\n    },\n\n\n\n\n    //-------------------------------------------------------------------------\n    // Methods to read values from the string stream\n    //-------------------------------------------------------------------------\n\n    readUnicodeRangePart: function(allowQuestionMark){\n        var reader  = this._reader,\n            part = \"\",\n            c       = reader.peek();\n\n        //first read hex digits\n        while(isHexDigit(c) && part.length < 6){\n            reader.read();\n            part += c;\n            c = reader.peek();\n        }\n\n        //then read question marks if allowed\n        if (allowQuestionMark){\n            while(c == \"?\" && part.length < 6){\n                reader.read();\n                part += c;\n                c = reader.peek();\n            }\n        }\n\n        //there can't be any other characters after this point\n\n        return part;\n    },\n\n    readWhitespace: function(){\n        var reader  = this._reader,\n            whitespace = \"\",\n            c       = reader.peek();\n\n        while(isWhitespace(c)){\n            reader.read();\n            whitespace += c;\n            c = reader.peek();\n        }\n\n        return whitespace;\n    },\n    readNumber: function(first){\n        var reader  = this._reader,\n            number  = first,\n            hasDot  = (first == \".\"),\n            c       = reader.peek();\n\n\n        while(c){\n            if (isDigit(c)){\n                number += reader.read();\n            } else if (c == \".\"){\n                if (hasDot){\n                    break;\n                } else {\n                    hasDot = true;\n                    number += reader.read();\n                }\n            } else {\n                break;\n            }\n\n            c = reader.peek();\n        }\n\n        return number;\n    },\n    readString: function(){\n        var reader  = this._reader,\n            delim   = reader.read(),\n            string  = delim,\n            prev    = delim,\n            c       = reader.peek();\n\n        while(c){\n            c = reader.read();\n            string += c;\n\n            //if the delimiter is found with an escapement, we're done.\n            if (c == delim && prev != \"\\\\\"){\n                break;\n            }\n\n            //if there's a newline without an escapement, it's an invalid string\n            if (isNewLine(reader.peek()) && c != \"\\\\\"){\n                string = \"\";\n                break;\n            }\n\n            //save previous and get next\n            prev = c;\n            c = reader.peek();\n        }\n\n        //if c is null, that means we're out of input and the string was never closed\n        if (c === null){\n            string = \"\";\n        }\n\n        return string;\n    },\n    readURI: function(first){\n        var reader  = this._reader,\n            uri     = first,\n            inner   = \"\",\n            c       = reader.peek();\n\n        reader.mark();\n\n        //skip whitespace before\n        while(c && isWhitespace(c)){\n            reader.read();\n            c = reader.peek();\n        }\n\n        //it's a string\n        if (c == \"'\" || c == \"\\\"\"){\n            inner = this.readString();\n        } else {\n            inner = this.readURL();\n        }\n\n        c = reader.peek();\n\n        //skip whitespace after\n        while(c && isWhitespace(c)){\n            reader.read();\n            c = reader.peek();\n        }\n\n        //if there was no inner value or the next character isn't closing paren, it's not a URI\n        if (inner === \"\" || c != \")\"){\n            uri = first;\n            reader.reset();\n        } else {\n            uri += inner + reader.read();\n        }\n\n        return uri;\n    },\n    readURL: function(){\n        var reader  = this._reader,\n            url     = \"\",\n            c       = reader.peek();\n\n        //TODO: Check for escape and nonascii\n        while (/^[!#$%&\\\\*-~]$/.test(c)){\n            url += reader.read();\n            c = reader.peek();\n        }\n\n        return url;\n\n    },\n    readName: function(first){\n        var reader  = this._reader,\n            ident   = first || \"\",\n            c       = reader.peek();\n\n        while(true){\n            if (c == \"\\\\\"){\n                ident += this.readEscape(reader.read());\n                c = reader.peek();\n            } else if(c && isNameChar(c)){\n                ident += reader.read();\n                c = reader.peek();\n            } else {\n                break;\n            }\n        }\n\n        return ident;\n    },\n    \n    readEscape: function(first){\n        var reader  = this._reader,\n            cssEscape = first || \"\",\n            i       = 0,\n            c       = reader.peek();    \n    \n        if (isHexDigit(c)){\n            do {\n                cssEscape += reader.read();\n                c = reader.peek();\n            } while(c && isHexDigit(c) && ++i < 6);\n        }\n        \n        if (cssEscape.length == 3 && /\\s/.test(c) ||\n            cssEscape.length == 7 || cssEscape.length == 1){\n                reader.read();\n        } else {\n            c = \"\";\n        }\n        \n        return cssEscape + c;\n    },\n    \n    readComment: function(first){\n        var reader  = this._reader,\n            comment = first || \"\",\n            c       = reader.read();\n\n        if (c == \"*\"){\n            while(c){\n                comment += c;\n\n                //look for end of comment\n                if (comment.length > 2 && c == \"*\" && reader.peek() == \"/\"){\n                    comment += reader.read();\n                    break;\n                }\n\n                c = reader.read();\n            }\n\n            return comment;\n        } else {\n            return \"\";\n        }\n\n    }\n});\n\n\nvar Tokens  = [\n\n    /*\n     * The following token names are defined in CSS3 Grammar: http://www.w3.org/TR/css3-syntax/#lexical\n     */\n     \n    //HTML-style comments\n    { name: \"CDO\"},\n    { name: \"CDC\"},\n\n    //ignorables\n    { name: \"S\", whitespace: true/*, channel: \"ws\"*/},\n    { name: \"COMMENT\", comment: true, hide: true, channel: \"comment\" },\n        \n    //attribute equality\n    { name: \"INCLUDES\", text: \"~=\"},\n    { name: \"DASHMATCH\", text: \"|=\"},\n    { name: \"PREFIXMATCH\", text: \"^=\"},\n    { name: \"SUFFIXMATCH\", text: \"$=\"},\n    { name: \"SUBSTRINGMATCH\", text: \"*=\"},\n        \n    //identifier types\n    { name: \"STRING\"},     \n    { name: \"IDENT\"},\n    { name: \"HASH\"},\n\n    //at-keywords\n    { name: \"IMPORT_SYM\", text: \"@import\"},\n    { name: \"PAGE_SYM\", text: \"@page\"},\n    { name: \"MEDIA_SYM\", text: \"@media\"},\n    { name: \"FONT_FACE_SYM\", text: \"@font-face\"},\n    { name: \"CHARSET_SYM\", text: \"@charset\"},\n    { name: \"NAMESPACE_SYM\", text: \"@namespace\"},\n    { name: \"UNKNOWN_SYM\" },\n    //{ name: \"ATKEYWORD\"},\n    \n    //CSS3 animations\n    { name: \"KEYFRAMES_SYM\", text: [ \"@keyframes\", \"@-webkit-keyframes\", \"@-moz-keyframes\", \"@-ms-keyframes\" ] },\n\n    //important symbol\n    { name: \"IMPORTANT_SYM\"},\n\n    //measurements\n    { name: \"LENGTH\"},\n    { name: \"ANGLE\"},\n    { name: \"TIME\"},\n    { name: \"FREQ\"},\n    { name: \"DIMENSION\"},\n    { name: \"PERCENTAGE\"},\n    { name: \"NUMBER\"},\n    \n    //functions\n    { name: \"URI\"},\n    { name: \"FUNCTION\"},\n    \n    //Unicode ranges\n    { name: \"UNICODE_RANGE\"},\n    \n    /*\n     * The following token names are defined in CSS3 Selectors: http://www.w3.org/TR/css3-selectors/#selector-syntax\n     */    \n    \n    //invalid string\n    { name: \"INVALID\"},\n    \n    //combinators\n    { name: \"PLUS\", text: \"+\" },\n    { name: \"GREATER\", text: \">\"},\n    { name: \"COMMA\", text: \",\"},\n    { name: \"TILDE\", text: \"~\"},\n    \n    //modifier\n    { name: \"NOT\"},        \n    \n    /*\n     * Defined in CSS3 Paged Media\n     */\n    { name: \"TOPLEFTCORNER_SYM\", text: \"@top-left-corner\"},\n    { name: \"TOPLEFT_SYM\", text: \"@top-left\"},\n    { name: \"TOPCENTER_SYM\", text: \"@top-center\"},\n    { name: \"TOPRIGHT_SYM\", text: \"@top-right\"},\n    { name: \"TOPRIGHTCORNER_SYM\", text: \"@top-right-corner\"},\n    { name: \"BOTTOMLEFTCORNER_SYM\", text: \"@bottom-left-corner\"},\n    { name: \"BOTTOMLEFT_SYM\", text: \"@bottom-left\"},\n    { name: \"BOTTOMCENTER_SYM\", text: \"@bottom-center\"},\n    { name: \"BOTTOMRIGHT_SYM\", text: \"@bottom-right\"},\n    { name: \"BOTTOMRIGHTCORNER_SYM\", text: \"@bottom-right-corner\"},\n    { name: \"LEFTTOP_SYM\", text: \"@left-top\"},\n    { name: \"LEFTMIDDLE_SYM\", text: \"@left-middle\"},\n    { name: \"LEFTBOTTOM_SYM\", text: \"@left-bottom\"},\n    { name: \"RIGHTTOP_SYM\", text: \"@right-top\"},\n    { name: \"RIGHTMIDDLE_SYM\", text: \"@right-middle\"},\n    { name: \"RIGHTBOTTOM_SYM\", text: \"@right-bottom\"},\n\n    /*\n     * The following token names are defined in CSS3 Media Queries: http://www.w3.org/TR/css3-mediaqueries/#syntax\n     */\n    /*{ name: \"MEDIA_ONLY\", state: \"media\"},\n    { name: \"MEDIA_NOT\", state: \"media\"},\n    { name: \"MEDIA_AND\", state: \"media\"},*/\n    { name: \"RESOLUTION\", state: \"media\"},\n\n    /*\n     * The following token names are not defined in any CSS specification but are used by the lexer.\n     */\n    \n    //not a real token, but useful for stupid IE filters\n    { name: \"IE_FUNCTION\" },\n\n    //part of CSS3 grammar but not the Flex code\n    { name: \"CHAR\" },\n    \n    //TODO: Needed?\n    //Not defined as tokens, but might as well be\n    {\n        name: \"PIPE\",\n        text: \"|\"\n    },\n    {\n        name: \"SLASH\",\n        text: \"/\"\n    },\n    {\n        name: \"MINUS\",\n        text: \"-\"\n    },\n    {\n        name: \"STAR\",\n        text: \"*\"\n    },\n\n    {\n        name: \"LBRACE\",\n        text: \"{\"\n    },   \n    {\n        name: \"RBRACE\",\n        text: \"}\"\n    },      \n    {\n        name: \"LBRACKET\",\n        text: \"[\"\n    },   \n    {\n        name: \"RBRACKET\",\n        text: \"]\"\n    },    \n    {\n        name: \"EQUALS\",\n        text: \"=\"\n    },\n    {\n        name: \"COLON\",\n        text: \":\"\n    },    \n    {\n        name: \"SEMICOLON\",\n        text: \";\"\n    },    \n \n    {\n        name: \"LPAREN\",\n        text: \"(\"\n    },   \n    {\n        name: \"RPAREN\",\n        text: \")\"\n    },     \n    {\n        name: \"DOT\",\n        text: \".\"\n    }\n];\n\n(function(){\n\n    var nameMap = [],\n        typeMap = {};\n    \n    Tokens.UNKNOWN = -1;\n    Tokens.unshift({name:\"EOF\"});\n    for (var i=0, len = Tokens.length; i < len; i++){\n        nameMap.push(Tokens[i].name);\n        Tokens[Tokens[i].name] = i;\n        if (Tokens[i].text){\n            if (Tokens[i].text instanceof Array){\n                for (var j=0; j < Tokens[i].text.length; j++){\n                    typeMap[Tokens[i].text[j]] = i;\n                }\n            } else {\n                typeMap[Tokens[i].text] = i;\n            }\n        }\n    }\n    \n    Tokens.name = function(tt){\n        return nameMap[tt];\n    };\n    \n    Tokens.type = function(c){\n        return typeMap[c] || -1;\n    };\n\n})();\n\n\n\n\n//This file will likely change a lot! Very experimental!\n/*global Properties, ValidationTypes, ValidationError, PropertyValueIterator */\nvar Validation = {\n\n    validate: function(property, value){\n    \n        //normalize name\n        var name        = property.toString().toLowerCase(),\n            parts       = value.parts,\n            expression  = new PropertyValueIterator(value),\n            spec        = Properties[name],\n            part,\n            valid,            \n            j, count,\n            msg,\n            types,\n            last,\n            literals,\n            max, multi, group;\n            \n        if (!spec) {\n            if (name.indexOf(\"-\") !== 0){    //vendor prefixed are ok\n                throw new ValidationError(\"Unknown property '\" + property + \"'.\", property.line, property.col);\n            }\n        } else if (typeof spec != \"number\"){\n        \n            //initialization\n            if (typeof spec == \"string\"){\n                if (spec.indexOf(\"||\") > -1) {\n                    this.groupProperty(spec, expression);\n                } else {\n                    this.singleProperty(spec, expression, 1);\n                }\n\n            } else if (spec.multi) {\n                this.multiProperty(spec.multi, expression, spec.comma, spec.max || Infinity);\n            } else if (typeof spec == \"function\") {\n                spec(expression);\n            }\n\n        }\n\n    },\n    \n    singleProperty: function(types, expression, max, partial) {\n\n        var result      = false,\n            value       = expression.value,\n            count       = 0,\n            part;\n         \n        while (expression.hasNext() && count < max) {\n            result = ValidationTypes.isAny(expression, types);\n            if (!result) {\n                break;\n            }\n            count++;\n        }\n        \n        if (!result) {\n            if (expression.hasNext() && !expression.isFirst()) {\n                part = expression.peek();\n                throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            } else {\n                 throw new ValidationError(\"Expected (\" + types + \") but found '\" + value + \"'.\", value.line, value.col);\n            }        \n        } else if (expression.hasNext()) {\n            part = expression.next();\n            throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n        }          \n                 \n    },    \n    \n    multiProperty: function (types, expression, comma, max) {\n\n        var result      = false,\n            value       = expression.value,\n            count       = 0,\n            sep         = false,\n            part;\n            \n        while(expression.hasNext() && !result && count < max) {\n            if (ValidationTypes.isAny(expression, types)) {\n                count++;\n                if (!expression.hasNext()) {\n                    result = true;\n\n                } else if (comma) {\n                    if (expression.peek() == \",\") {\n                        part = expression.next();\n                    } else {\n                        break;\n                    }\n                }\n            } else {\n                break;\n\n            }\n        }\n        \n        if (!result) {\n            if (expression.hasNext() && !expression.isFirst()) {\n                part = expression.peek();\n                throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            } else {\n                part = expression.previous();\n                if (comma && part == \",\") {\n                    throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col); \n                } else {\n                    throw new ValidationError(\"Expected (\" + types + \") but found '\" + value + \"'.\", value.line, value.col);\n                }\n            }\n        \n        } else if (expression.hasNext()) {\n            part = expression.next();\n            throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n        }  \n\n    },\n    \n    groupProperty: function (types, expression, comma) {\n\n        var result      = false,\n            value       = expression.value,\n            typeCount   = types.split(\"||\").length,\n            groups      = { count: 0 },\n            partial     = false,\n            name,\n            part;\n            \n        while(expression.hasNext() && !result) {\n            name = ValidationTypes.isAnyOfGroup(expression, types);\n            if (name) {\n            \n                //no dupes\n                if (groups[name]) {\n                    break;\n                } else {\n                    groups[name] = 1;\n                    groups.count++;\n                    partial = true;\n                    \n                    if (groups.count == typeCount || !expression.hasNext()) {\n                        result = true;\n                    }\n                }\n            } else {\n                break;\n            }\n        }\n        \n        if (!result) {        \n            if (partial && expression.hasNext()) {\n                    part = expression.peek();\n                    throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n            } else {\n                throw new ValidationError(\"Expected (\" + types + \") but found '\" + value + \"'.\", value.line, value.col);\n            }\n        } else if (expression.hasNext()) {\n            part = expression.next();\n            throw new ValidationError(\"Expected end of value but found '\" + part + \"'.\", part.line, part.col);\n        }           \n    }\n\n    \n\n};\n/**\n * Type to use when a validation error occurs.\n * @class ValidationError\n * @namespace parserlib.util\n * @constructor\n * @param {String} message The error message.\n * @param {int} line The line at which the error occurred.\n * @param {int} col The column at which the error occurred.\n */\nfunction ValidationError(message, line, col){\n\n    /**\n     * The column at which the error occurred.\n     * @type int\n     * @property col\n     */\n    this.col = col;\n\n    /**\n     * The line at which the error occurred.\n     * @type int\n     * @property line\n     */\n    this.line = line;\n\n    /**\n     * The text representation of the unit.\n     * @type String\n     * @property text\n     */\n    this.message = message;\n\n}\n\n//inherit from Error\nValidationError.prototype = new Error();\n//This file will likely change a lot! Very experimental!\n/*global Properties, Validation, ValidationError, PropertyValueIterator, console*/\nvar ValidationTypes = {\n\n    isLiteral: function (part, literals) {\n        var text = part.text.toString().toLowerCase(),\n            args = literals.split(\" | \"),\n            i, len, found = false;\n        \n        for (i=0,len=args.length; i < len && !found; i++){\n            if (text == args[i]){\n                found = true;\n            }\n        }\n        \n        return found;    \n    },\n    \n    isSimple: function(type) {\n        return !!this.simple[type];\n    },\n    \n    isComplex: function(type) {\n        return !!this.complex[type];\n    },\n    \n    /**\n     * Determines if the next part(s) of the given expression\n     * are any of the given types.\n     */\n    isAny: function (expression, types) {\n        var args = types.split(\" | \"),\n            i, len, found = false;\n        \n        for (i=0,len=args.length; i < len && !found && expression.hasNext(); i++){\n            found = this.isType(expression, args[i]);\n        }\n        \n        return found;    \n    },\n    \n    /**\n     * Determines if the next part(s) of the given expresion\n     * are one of a group.\n     */\n    isAnyOfGroup: function(expression, types) {\n        var args = types.split(\" || \"),\n            i, len, found = false;\n        \n        for (i=0,len=args.length; i < len && !found; i++){\n            found = this.isType(expression, args[i]);\n        }\n        \n        return found ? args[i-1] : false;\n    },\n    \n    /**\n     * Determines if the next part(s) of the given expression\n     * are of a given type.\n     */\n    isType: function (expression, type) {\n        var part = expression.peek(),\n            result = false;\n            \n        if (type.charAt(0) != \"<\") {\n            result = this.isLiteral(part, type);\n            if (result) {\n                expression.next();\n            }\n        } else if (this.simple[type]) {\n            result = this.simple[type](part);\n            if (result) {\n                expression.next();\n            }\n        } else {\n            result = this.complex[type](expression);\n        }\n        \n        return result;\n    },\n    \n    \n    \n    simple: {\n\n        \"<absolute-size>\": function(part){\n            return ValidationTypes.isLiteral(part, \"xx-small | x-small | small | medium | large | x-large | xx-large\");\n        },\n        \n        \"<attachment>\": function(part){\n            return ValidationTypes.isLiteral(part, \"scroll | fixed | local\");\n        },\n        \n        \"<attr>\": function(part){\n            return part.type == \"function\" && part.name == \"attr\";\n        },\n                \n        \"<bg-image>\": function(part){\n            return this[\"<image>\"](part) || this[\"<gradient>\"](part) ||  part == \"none\";\n        },        \n        \n        \"<gradient>\": function(part) {\n            return part.type == \"function\" && /^(?:\\-(?:ms|moz|o|webkit)\\-)?(?:repeating\\-)?(?:radial|linear)\\-gradient/i.test(part);\n        },\n        \n        \"<box>\": function(part){\n            return ValidationTypes.isLiteral(part, \"padding-box | border-box | content-box\");\n        },\n        \n        \"<content>\": function(part){\n            return part.type == \"function\" && part.name == \"content\";\n        },        \n        \n        \"<relative-size>\": function(part){\n            return ValidationTypes.isLiteral(part, \"smaller | larger\");\n        },\n        \n        //any identifier\n        \"<ident>\": function(part){\n            return part.type == \"identifier\";\n        },\n        \n        \"<length>\": function(part){\n            return part.type == \"length\" || part.type == \"number\" || part.type == \"integer\" || part == \"0\";\n        },\n        \n        \"<color>\": function(part){\n            return part.type == \"color\" || part == \"transparent\";\n        },\n        \n        \"<number>\": function(part){\n            return part.type == \"number\" || this[\"<integer>\"](part);\n        },\n        \n        \"<integer>\": function(part){\n            return part.type == \"integer\";\n        },\n        \n        \"<line>\": function(part){\n            return part.type == \"integer\";\n        },\n        \n        \"<angle>\": function(part){\n            return part.type == \"angle\";\n        },        \n        \n        \"<uri>\": function(part){\n            return part.type == \"uri\";\n        },\n        \n        \"<image>\": function(part){\n            return this[\"<uri>\"](part);\n        },\n        \n        \"<percentage>\": function(part){\n            return part.type == \"percentage\" || part == \"0\";\n        },\n\n        \"<border-width>\": function(part){\n            return this[\"<length>\"](part) || ValidationTypes.isLiteral(part, \"thin | medium | thick\");\n        },\n        \n        \"<border-style>\": function(part){\n            return ValidationTypes.isLiteral(part, \"none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset\");\n        },\n        \n        \"<margin-width>\": function(part){\n            return this[\"<length>\"](part) || this[\"<percentage>\"](part) || ValidationTypes.isLiteral(part, \"auto\");\n        },\n        \n        \"<padding-width>\": function(part){\n            return this[\"<length>\"](part) || this[\"<percentage>\"](part);\n        },\n        \n        \"<shape>\": function(part){\n            return part.type == \"function\" && (part.name == \"rect\" || part.name == \"inset-rect\");\n        },\n        \n        \"<time>\": function(part) {\n            return part.type == \"time\";\n        }\n    },\n    \n    complex: {\n\n        \"<bg-position>\": function(expression){\n            var types   = this,\n                result  = false,\n                numeric = \"<percentage> | <length>\",\n                xDir    = \"left | center | right\",\n                yDir    = \"top | center | bottom\",\n                part,\n                i, len;\n            \n                \n            if (ValidationTypes.isAny(expression, \"top | bottom\")) {\n                result = true;\n            } else {\n                \n                //must be two-part\n                if (ValidationTypes.isAny(expression, numeric)){\n                    if (expression.hasNext()){\n                        result = ValidationTypes.isAny(expression, numeric + \" | \" + yDir);\n                    }\n                } else if (ValidationTypes.isAny(expression, xDir)){\n                    if (expression.hasNext()){\n                        \n                        //two- or three-part\n                        if (ValidationTypes.isAny(expression, yDir)){\n                            result = true;\n                      \n                            ValidationTypes.isAny(expression, numeric);\n                            \n                        } else if (ValidationTypes.isAny(expression, numeric)){\n                        \n                            //could also be two-part, so check the next part\n                            if (ValidationTypes.isAny(expression, yDir)){                                    \n                                ValidationTypes.isAny(expression, numeric);                               \n                            }\n                            \n                            result = true;\n                        }\n                    }\n                }                                 \n            }            \n\n            \n            return result;\n        },\n\n        \"<bg-size>\": function(expression){\n            //<bg-size> = [ <length> | <percentage> | auto ]{1,2} | cover | contain\n            var types   = this,\n                result  = false,\n                numeric = \"<percentage> | <length> | auto\",\n                part,\n                i, len;      \n      \n            if (ValidationTypes.isAny(expression, \"cover | contain\")) {\n                result = true;\n            } else if (ValidationTypes.isAny(expression, numeric)) {\n                result = true;                \n                ValidationTypes.isAny(expression, numeric);\n            }\n            \n            return result;\n        },\n        \n        \"<repeat-style>\": function(expression){\n            //repeat-x | repeat-y | [repeat | space | round | no-repeat]{1,2}\n            var result  = false,\n                values  = \"repeat | space | round | no-repeat\",\n                part;\n            \n            if (expression.hasNext()){\n                part = expression.next();\n                \n                if (ValidationTypes.isLiteral(part, \"repeat-x | repeat-y\")) {\n                    result = true;                    \n                } else if (ValidationTypes.isLiteral(part, values)) {\n                    result = true;\n\n                    if (expression.hasNext() && ValidationTypes.isLiteral(expression.peek(), values)) {\n                        expression.next();\n                    }\n                }\n            }\n            \n            return result;\n            \n        },\n        \n        \"<shadow>\": function(expression) {\n            //inset? && [ <length>{2,4} && <color>? ]\n            var result  = false,\n                count   = 0,\n                inset   = false,\n                color   = false,\n                part;\n                \n            if (expression.hasNext()) {            \n                \n                if (ValidationTypes.isAny(expression, \"inset\")){\n                    inset = true;\n                }\n                \n                if (ValidationTypes.isAny(expression, \"<color>\")) {\n                    color = true;\n                }                \n                \n                while (ValidationTypes.isAny(expression, \"<length>\") && count < 4) {\n                    count++;\n                }\n                \n                \n                if (expression.hasNext()) {\n                    if (!color) {\n                        ValidationTypes.isAny(expression, \"<color>\");\n                    }\n                    \n                    if (!inset) {\n                        ValidationTypes.isAny(expression, \"inset\");\n                    }\n\n                }\n                \n                result = (count >= 2 && count <= 4);\n            \n            }\n            \n            return result;\n        },\n        \n        \"<x-one-radius>\": function(expression) {\n            //[ <length> | <percentage> ] [ <length> | <percentage> ]?\n            var result  = false,\n                count   = 0,\n                numeric = \"<length> | <percentage>\",\n                part;\n                \n            if (ValidationTypes.isAny(expression, numeric)){\n                result = true;\n                \n                ValidationTypes.isAny(expression, numeric);\n            }                \n            \n            return result;\n        }\n    }\n};\n\n\nparserlib.css = {\nColors              :Colors,    \nCombinator          :Combinator,                \nParser              :Parser,\nPropertyName        :PropertyName,\nPropertyValue       :PropertyValue,\nPropertyValuePart   :PropertyValuePart,\nMediaFeature        :MediaFeature,\nMediaQuery          :MediaQuery,\nSelector            :Selector,\nSelectorPart        :SelectorPart,\nSelectorSubPart     :SelectorSubPart,\nSpecificity         :Specificity,\nTokenStream         :TokenStream,\nTokens              :Tokens,\nValidationError     :ValidationError\n};\n})();\n\n\n\n/**\n * Main CSSLint object.\n * @class CSSLint\n * @static\n * @extends parserlib.util.EventTarget\n */\n/*global parserlib, Reporter*/\nvar CSSLint = (function(){\n\n    var rules      = [],\n        formatters = [],\n        api        = new parserlib.util.EventTarget();\n        \n    api.version = \"0.9.7\";\n\n    //-------------------------------------------------------------------------\n    // Rule Management\n    //-------------------------------------------------------------------------\n\n    /**\n     * Adds a new rule to the engine.\n     * @param {Object} rule The rule to add.\n     * @method addRule\n     */\n    api.addRule = function(rule){\n        rules.push(rule);\n        rules[rule.id] = rule;\n    };\n\n    /**\n     * Clears all rule from the engine.\n     * @method clearRules\n     */\n    api.clearRules = function(){\n        rules = [];\n    };\n    \n    /**\n     * Returns the rule objects.\n     * @return An array of rule objects.\n     * @method getRules\n     */\n    api.getRules = function(){\n        return [].concat(rules).sort(function(a,b){ \n            return a.id > b.id ? 1 : 0;\n        });\n    };\n\n    //-------------------------------------------------------------------------\n    // Formatters\n    //-------------------------------------------------------------------------\n\n    /**\n     * Adds a new formatter to the engine.\n     * @param {Object} formatter The formatter to add.\n     * @method addFormatter\n     */\n    api.addFormatter = function(formatter) {\n        // formatters.push(formatter);\n        formatters[formatter.id] = formatter;\n    };\n    \n    /**\n     * Retrieves a formatter for use.\n     * @param {String} formatId The name of the format to retrieve.\n     * @return {Object} The formatter or undefined.\n     * @method getFormatter\n     */\n    api.getFormatter = function(formatId){\n        return formatters[formatId];\n    };\n    \n    /**\n     * Formats the results in a particular format for a single file.\n     * @param {Object} result The results returned from CSSLint.verify().\n     * @param {String} filename The filename for which the results apply.\n     * @param {String} formatId The name of the formatter to use.\n     * @param {Object} options (Optional) for special output handling.\n     * @return {String} A formatted string for the results.\n     * @method format\n     */\n    api.format = function(results, filename, formatId, options) {\n        var formatter = this.getFormatter(formatId),\n            result = null;\n            \n        if (formatter){\n            result = formatter.startFormat();\n            result += formatter.formatResults(results, filename, options || {});\n            result += formatter.endFormat();\n        }\n        \n        return result;\n    };\n    \n    /**\n     * Indicates if the given format is supported.\n     * @param {String} formatId The ID of the format to check.\n     * @return {Boolean} True if the format exists, false if not.\n     * @method hasFormat\n     */\n    api.hasFormat = function(formatId){\n        return formatters.hasOwnProperty(formatId);\n    };\n\n    //-------------------------------------------------------------------------\n    // Verification\n    //-------------------------------------------------------------------------\n\n    /**\n     * Starts the verification process for the given CSS text.\n     * @param {String} text The CSS text to verify.\n     * @param {Object} ruleset (Optional) List of rules to apply. If null, then\n     *      all rules are used. If a rule has a value of 1 then it's a warning,\n     *      a value of 2 means it's an error.\n     * @return {Object} Results of the verification.\n     * @method verify\n     */\n    api.verify = function(text, ruleset){\n\n        var i       = 0,\n            len     = rules.length,\n            reporter,\n            lines,\n            report,\n            parser = new parserlib.css.Parser({ starHack: true, ieFilters: true,\n                                                underscoreHack: true, strict: false });\n\n        lines = text.replace(/\\n\\r?/g, \"$split$\").split('$split$');\n        \n        if (!ruleset){\n            ruleset = {};\n            while (i < len){\n                ruleset[rules[i++].id] = 1;    //by default, everything is a warning\n            }\n        }\n        \n        reporter = new Reporter(lines, ruleset);\n        \n        ruleset.errors = 2;       //always report parsing errors as errors\n        for (i in ruleset){\n            if(ruleset.hasOwnProperty(i)){\n                if (rules[i]){\n                    rules[i].init(parser, reporter);\n                }\n            }\n        }\n\n\n        //capture most horrible error type\n        try {\n            parser.parse(text);\n        } catch (ex) {\n            reporter.error(\"Fatal error, cannot continue: \" + ex.message, ex.line, ex.col, {});\n        }\n\n        report = {\n            messages    : reporter.messages,\n            stats       : reporter.stats\n        };\n        \n        //sort by line numbers, rollups at the bottom\n        report.messages.sort(function (a, b){\n            if (a.rollup && !b.rollup){\n                return 1;\n            } else if (!a.rollup && b.rollup){\n                return -1;\n            } else {\n                return a.line - b.line;\n            }\n        });        \n        \n        return report;\n    };\n\n    //-------------------------------------------------------------------------\n    // Publish the API\n    //-------------------------------------------------------------------------\n\n    return api;\n\n})();\n\n/*global CSSLint*/\n/**\n * An instance of Report is used to report results of the\n * verification back to the main API.\n * @class Reporter\n * @constructor\n * @param {String[]} lines The text lines of the source.\n * @param {Object} ruleset The set of rules to work with, including if\n *      they are errors or warnings.\n */\nfunction Reporter(lines, ruleset){\n\n    /**\n     * List of messages being reported.\n     * @property messages\n     * @type String[]\n     */\n    this.messages = [];\n\n    /**\n     * List of statistics being reported.\n     * @property stats\n     * @type String[]\n     */\n    this.stats = [];\n\n    /**\n     * Lines of code being reported on. Used to provide contextual information\n     * for messages.\n     * @property lines\n     * @type String[]\n     */\n    this.lines = lines;\n    \n    /**\n     * Information about the rules. Used to determine whether an issue is an\n     * error or warning.\n     * @property ruleset\n     * @type Object\n     */\n    this.ruleset = ruleset;\n}\n\nReporter.prototype = {\n\n    //restore constructor\n    constructor: Reporter,\n\n    /**\n     * Report an error.\n     * @param {String} message The message to store.\n     * @param {int} line The line number.\n     * @param {int} col The column number.\n     * @param {Object} rule The rule this message relates to.\n     * @method error\n     */\n    error: function(message, line, col, rule){\n        this.messages.push({\n            type    : \"error\",\n            line    : line,\n            col     : col,\n            message : message,\n            evidence: this.lines[line-1],\n            rule    : rule || {}\n        });\n    },\n\n    /**\n     * Report an warning.\n     * @param {String} message The message to store.\n     * @param {int} line The line number.\n     * @param {int} col The column number.\n     * @param {Object} rule The rule this message relates to.\n     * @method warn\n     * @deprecated Use report instead.\n     */\n    warn: function(message, line, col, rule){\n        this.report(message, line, col, rule);\n    },\n\n    /**\n     * Report an issue.\n     * @param {String} message The message to store.\n     * @param {int} line The line number.\n     * @param {int} col The column number.\n     * @param {Object} rule The rule this message relates to.\n     * @method report\n     */\n    report: function(message, line, col, rule){\n        this.messages.push({\n            type    : this.ruleset[rule.id] == 2 ? \"error\" : \"warning\",\n            line    : line,\n            col     : col,\n            message : message,\n            evidence: this.lines[line-1],\n            rule    : rule\n        });\n    },\n\n    /**\n     * Report some informational text.\n     * @param {String} message The message to store.\n     * @param {int} line The line number.\n     * @param {int} col The column number.\n     * @param {Object} rule The rule this message relates to.\n     * @method info\n     */\n    info: function(message, line, col, rule){\n        this.messages.push({\n            type    : \"info\",\n            line    : line,\n            col     : col,\n            message : message,\n            evidence: this.lines[line-1],\n            rule    : rule\n        });\n    },\n\n    /**\n     * Report some rollup error information.\n     * @param {String} message The message to store.\n     * @param {Object} rule The rule this message relates to.\n     * @method rollupError\n     */\n    rollupError: function(message, rule){\n        this.messages.push({\n            type    : \"error\",\n            rollup  : true,\n            message : message,\n            rule    : rule\n        });\n    },\n\n    /**\n     * Report some rollup warning information.\n     * @param {String} message The message to store.\n     * @param {Object} rule The rule this message relates to.\n     * @method rollupWarn\n     */\n    rollupWarn: function(message, rule){\n        this.messages.push({\n            type    : \"warning\",\n            rollup  : true,\n            message : message,\n            rule    : rule\n        });\n    },\n\n    /**\n     * Report a statistic.\n     * @param {String} name The name of the stat to store.\n     * @param {Variant} value The value of the stat.\n     * @method stat\n     */\n    stat: function(name, value){\n        this.stats[name] = value;\n    }\n};\n\n//expose for testing purposes\nCSSLint._Reporter = Reporter;\n\n/*global CSSLint*/\n\n/*\n * Utility functions that make life easier.\n */\nCSSLint.Util = {\n    /*\n     * Adds all properties from supplier onto receiver,\n     * overwriting if the same name already exists on\n     * reciever.\n     * @param {Object} The object to receive the properties.\n     * @param {Object} The object to provide the properties.\n     * @return {Object} The receiver\n     */\n    mix: function(receiver, supplier){\n        var prop;\n\n        for (prop in supplier){\n            if (supplier.hasOwnProperty(prop)){\n                receiver[prop] = supplier[prop];\n            }\n        }\n\n        return prop;\n    },\n\n    /*\n     * Polyfill for array indexOf() method.\n     * @param {Array} values The array to search.\n     * @param {Variant} value The value to search for.\n     * @return {int} The index of the value if found, -1 if not.\n     */\n    indexOf: function(values, value){\n        if (values.indexOf){\n            return values.indexOf(value);\n        } else {\n            for (var i=0, len=values.length; i < len; i++){\n                if (values[i] === value){\n                    return i;\n                }\n            }\n            return -1;\n        }\n    },\n\n    /*\n     * Polyfill for array forEach() method.\n     * @param {Array} values The array to operate on.\n     * @param {Function} func The function to call on each item.\n     * @return {void}\n     */\n    forEach: function(values, func) {\n        if (values.forEach){\n            return values.forEach(func);\n        } else {\n            for (var i=0, len=values.length; i < len; i++){\n                func(values[i], i, values);\n            }\n        }\n    }\n};\n/*global CSSLint*/\n/*\n * Rule: Don't use adjoining classes (.foo.bar).\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"adjoining-classes\",\n    name: \"Disallow adjoining classes\",\n    desc: \"Don't use adjoining classes.\",\n    browsers: \"IE6\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                classCount,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part.type == parser.SELECTOR_PART_TYPE){\n                        classCount = 0;\n                        for (k=0; k < part.modifiers.length; k++){\n                            modifier = part.modifiers[k];\n                            if (modifier.type == \"class\"){\n                                classCount++;\n                            }\n                            if (classCount > 1){\n                                reporter.report(\"Don't use adjoining classes.\", part.line, part.col, rule);\n                            }\n                        }\n                    }\n                }\n            }\n        });\n    }\n\n});\n/*global CSSLint*/\n\n/*\n * Rule: Don't use width or height when using padding or border. \n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"box-model\",\n    name: \"Beware of broken box size\",\n    desc: \"Don't use width or height when using padding or border.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            widthProperties = {\n                border: 1,\n                \"border-left\": 1,\n                \"border-right\": 1,\n                padding: 1,\n                \"padding-left\": 1,\n                \"padding-right\": 1\n            },\n            heightProperties = {\n                border: 1,\n                \"border-bottom\": 1,\n                \"border-top\": 1,\n                padding: 1,\n                \"padding-bottom\": 1,\n                \"padding-top\": 1\n            },\n            properties;\n\n        function startRule(){\n            properties = {};\n        }\n\n        function endRule(){\n            var prop;\n            if (properties.height){\n                for (prop in heightProperties){\n                    if (heightProperties.hasOwnProperty(prop) && properties[prop]){\n                    \n                        //special case for padding\n                        if (!(prop == \"padding\" && properties[prop].value.parts.length === 2 && properties[prop].value.parts[0].value === 0)){\n                            reporter.report(\"Using height with \" + prop + \" can sometimes make elements larger than you expect.\", properties[prop].line, properties[prop].col, rule);\n                        }\n                    }\n                }\n            }\n\n            if (properties.width){\n                for (prop in widthProperties){\n                    if (widthProperties.hasOwnProperty(prop) && properties[prop]){\n\n                        if (!(prop == \"padding\" && properties[prop].value.parts.length === 2 && properties[prop].value.parts[1].value === 0)){\n                            reporter.report(\"Using width with \" + prop + \" can sometimes make elements larger than you expect.\", properties[prop].line, properties[prop].col, rule);\n                        }\n                    }\n                }\n            }        \n        }\n\n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n        parser.addListener(\"startpage\", startRule);\n        parser.addListener(\"startpagemargin\", startRule);\n        parser.addListener(\"startkeyframerule\", startRule); \n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase();\n            \n            if (heightProperties[name] || widthProperties[name]){\n                if (!/^0\\S*$/.test(event.value) && !(name == \"border\" && event.value == \"none\")){\n                    properties[name] = { line: event.property.line, col: event.property.col, value: event.value };\n                }\n            } else {\n                if (name == \"width\" || name == \"height\"){\n                    properties[name] = 1;\n                }\n            }\n            \n        });\n\n        parser.addListener(\"endrule\", endRule);\n        parser.addListener(\"endfontface\", endRule);\n        parser.addListener(\"endpage\", endRule);\n        parser.addListener(\"endpagemargin\", endRule);\n        parser.addListener(\"endkeyframerule\", endRule);         \n    }\n\n});\n/*global CSSLint*/\n\n/*\n * Rule: box-sizing doesn't work in IE6 and IE7.\n */\nCSSLint.addRule({\n\n    //rule information\n    id: \"box-sizing\",\n    name: \"Disallow use of box-sizing\",\n    desc: \"The box-sizing properties isn't supported in IE6 and IE7.\",\n    browsers: \"IE6, IE7\",\n    tags: [\"Compatibility\"],\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase();\n   \n            if (name == \"box-sizing\"){\n                reporter.report(\"The box-sizing property isn't supported in IE6 and IE7.\", event.line, event.col, rule);\n            }\n        });       \n    }\n\n});\n/*\n * Rule: Include all compatible vendor prefixes to reach a wider\n * range of users.\n */\n/*global CSSLint*/ \nCSSLint.addRule({\n\n    //rule information\n    id: \"compatible-vendor-prefixes\",\n    name: \"Require compatible vendor prefixes\",\n    desc: \"Include all compatible vendor prefixes to reach a wider range of users.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function (parser, reporter) {\n        var rule = this,\n            compatiblePrefixes,\n            properties,\n            prop,\n            variations,\n            prefixed,\n            i,\n            len,\n            arrayPush = Array.prototype.push,\n            applyTo = [];\n\n        // See http://peter.sh/experiments/vendor-prefixed-css-property-overview/ for details\n        compatiblePrefixes = {\n            \"animation\"                  : \"webkit moz ms\",\n            \"animation-delay\"            : \"webkit moz ms\",\n            \"animation-direction\"        : \"webkit moz ms\",\n            \"animation-duration\"         : \"webkit moz ms\",\n            \"animation-fill-mode\"        : \"webkit moz ms\",\n            \"animation-iteration-count\"  : \"webkit moz ms\",\n            \"animation-name\"             : \"webkit moz ms\",\n            \"animation-play-state\"       : \"webkit moz ms\",\n            \"animation-timing-function\"  : \"webkit moz ms\",\n            \"appearance\"                 : \"webkit moz\",\n            \"border-end\"                 : \"webkit moz\",\n            \"border-end-color\"           : \"webkit moz\",\n            \"border-end-style\"           : \"webkit moz\",\n            \"border-end-width\"           : \"webkit moz\",\n            \"border-image\"               : \"webkit moz o\",\n            \"border-radius\"              : \"webkit moz\",\n            \"border-start\"               : \"webkit moz\",\n            \"border-start-color\"         : \"webkit moz\",\n            \"border-start-style\"         : \"webkit moz\",\n            \"border-start-width\"         : \"webkit moz\",\n            \"box-align\"                  : \"webkit moz ms\",\n            \"box-direction\"              : \"webkit moz ms\",\n            \"box-flex\"                   : \"webkit moz ms\",\n            \"box-lines\"                  : \"webkit ms\",\n            \"box-ordinal-group\"          : \"webkit moz ms\",\n            \"box-orient\"                 : \"webkit moz ms\",\n            \"box-pack\"                   : \"webkit moz ms\",\n            \"box-sizing\"                 : \"webkit moz\",\n            \"box-shadow\"                 : \"webkit moz\",\n            \"column-count\"               : \"webkit moz ms\",\n            \"column-gap\"                 : \"webkit moz ms\",\n            \"column-rule\"                : \"webkit moz ms\",\n            \"column-rule-color\"          : \"webkit moz ms\",\n            \"column-rule-style\"          : \"webkit moz ms\",\n            \"column-rule-width\"          : \"webkit moz ms\",\n            \"column-width\"               : \"webkit moz ms\",\n            \"hyphens\"                    : \"epub moz\",\n            \"line-break\"                 : \"webkit ms\",\n            \"margin-end\"                 : \"webkit moz\",\n            \"margin-start\"               : \"webkit moz\",\n            \"marquee-speed\"              : \"webkit wap\",\n            \"marquee-style\"              : \"webkit wap\",\n            \"padding-end\"                : \"webkit moz\",\n            \"padding-start\"              : \"webkit moz\",\n            \"tab-size\"                   : \"moz o\",\n            \"text-size-adjust\"           : \"webkit ms\",\n            \"transform\"                  : \"webkit moz ms o\",\n            \"transform-origin\"           : \"webkit moz ms o\",\n            \"transition\"                 : \"webkit moz o ms\",\n            \"transition-delay\"           : \"webkit moz o ms\",\n            \"transition-duration\"        : \"webkit moz o ms\",\n            \"transition-property\"        : \"webkit moz o ms\",\n            \"transition-timing-function\" : \"webkit moz o ms\",\n            \"user-modify\"                : \"webkit moz\",\n            \"user-select\"                : \"webkit moz ms\",\n            \"word-break\"                 : \"epub ms\",\n            \"writing-mode\"               : \"epub ms\"\n        };\n\n\n        for (prop in compatiblePrefixes) {\n            if (compatiblePrefixes.hasOwnProperty(prop)) {\n                variations = [];\n                prefixed = compatiblePrefixes[prop].split(' ');\n                for (i = 0, len = prefixed.length; i < len; i++) {\n                    variations.push('-' + prefixed[i] + '-' + prop);\n                }\n                compatiblePrefixes[prop] = variations;\n                arrayPush.apply(applyTo, variations);\n            }\n        }\n        parser.addListener(\"startrule\", function () {\n            properties = [];\n        });\n\n        parser.addListener(\"property\", function (event) {\n            var name = event.property;\n            if (CSSLint.Util.indexOf(applyTo, name.text) > -1) {\n                properties.push(name);\n            }\n        });\n\n        parser.addListener(\"endrule\", function (event) {\n            if (!properties.length) {\n                return;\n            }\n\n            var propertyGroups = {},\n                i,\n                len,\n                name,\n                prop,\n                variations,\n                value,\n                full,\n                actual,\n                item,\n                propertiesSpecified;\n\n            for (i = 0, len = properties.length; i < len; i++) {\n                name = properties[i];\n\n                for (prop in compatiblePrefixes) {\n                    if (compatiblePrefixes.hasOwnProperty(prop)) {\n                        variations = compatiblePrefixes[prop];\n                        if (CSSLint.Util.indexOf(variations, name.text) > -1) {\n                            if (!propertyGroups[prop]) {\n                                propertyGroups[prop] = {\n                                    full : variations.slice(0),\n                                    actual : [],\n                                    actualNodes: []\n                                };\n                            }\n                            if (CSSLint.Util.indexOf(propertyGroups[prop].actual, name.text) === -1) {\n                                propertyGroups[prop].actual.push(name.text);\n                                propertyGroups[prop].actualNodes.push(name);\n                            }\n                        }\n                    }\n                }\n            }\n\n            for (prop in propertyGroups) {\n                if (propertyGroups.hasOwnProperty(prop)) {\n                    value = propertyGroups[prop];\n                    full = value.full;\n                    actual = value.actual;\n\n                    if (full.length > actual.length) {\n                        for (i = 0, len = full.length; i < len; i++) {\n                            item = full[i];\n                            if (CSSLint.Util.indexOf(actual, item) === -1) {\n                                propertiesSpecified = (actual.length === 1) ? actual[0] : (actual.length == 2) ? actual.join(\" and \") : actual.join(\", \");\n                                reporter.report(\"The property \" + item + \" is compatible with \" + propertiesSpecified + \" and should be included as well.\", value.actualNodes[0].line, value.actualNodes[0].col, rule); \n                            }\n                        }\n\n                    }\n                }\n            }\n        });\n    }\n});\n/*\n * Rule: Certain properties don't play well with certain display values. \n * - float should not be used with inline-block\n * - height, width, margin-top, margin-bottom, float should not be used with inline\n * - vertical-align should not be used with block\n * - margin, float should not be used with table-*\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"display-property-grouping\",\n    name: \"Require properties appropriate for display\",\n    desc: \"Certain properties shouldn't be used with certain display property values.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        var propertiesToCheck = {\n                display: 1,\n                \"float\": \"none\",\n                height: 1,\n                width: 1,\n                margin: 1,\n                \"margin-left\": 1,\n                \"margin-right\": 1,\n                \"margin-bottom\": 1,\n                \"margin-top\": 1,\n                padding: 1,\n                \"padding-left\": 1,\n                \"padding-right\": 1,\n                \"padding-bottom\": 1,\n                \"padding-top\": 1,\n                \"vertical-align\": 1\n            },\n            properties;\n\n        function reportProperty(name, display, msg){\n            if (properties[name]){\n                if (typeof propertiesToCheck[name] != \"string\" || properties[name].value.toLowerCase() != propertiesToCheck[name]){\n                    reporter.report(msg || name + \" can't be used with display: \" + display + \".\", properties[name].line, properties[name].col, rule);\n                }\n            }\n        }\n        \n        function startRule(){\n            properties = {};\n        }\n\n        function endRule(){\n\n            var display = properties.display ? properties.display.value : null;\n            if (display){\n                switch(display){\n\n                    case \"inline\":\n                        //height, width, margin-top, margin-bottom, float should not be used with inline\n                        reportProperty(\"height\", display);\n                        reportProperty(\"width\", display);\n                        reportProperty(\"margin\", display);\n                        reportProperty(\"margin-top\", display);\n                        reportProperty(\"margin-bottom\", display);              \n                        reportProperty(\"float\", display, \"display:inline has no effect on floated elements (but may be used to fix the IE6 double-margin bug).\");\n                        break;\n\n                    case \"block\":\n                        //vertical-align should not be used with block\n                        reportProperty(\"vertical-align\", display);\n                        break;\n\n                    case \"inline-block\":\n                        //float should not be used with inline-block\n                        reportProperty(\"float\", display);\n                        break;\n\n                    default:\n                        //margin, float should not be used with table\n                        if (display.indexOf(\"table-\") === 0){\n                            reportProperty(\"margin\", display);\n                            reportProperty(\"margin-left\", display);\n                            reportProperty(\"margin-right\", display);\n                            reportProperty(\"margin-top\", display);\n                            reportProperty(\"margin-bottom\", display);\n                            reportProperty(\"float\", display);\n                        }\n\n                        //otherwise do nothing\n                }\n            }\n          \n        }\n\n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n        parser.addListener(\"startkeyframerule\", startRule);\n        parser.addListener(\"startpagemargin\", startRule);\n        parser.addListener(\"startpage\", startRule);\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase();\n\n            if (propertiesToCheck[name]){\n                properties[name] = { value: event.value.text, line: event.property.line, col: event.property.col };                    \n            }\n        });\n\n        parser.addListener(\"endrule\", endRule);\n        parser.addListener(\"endfontface\", endRule);\n        parser.addListener(\"endkeyframerule\", endRule);\n        parser.addListener(\"endpagemargin\", endRule);\n        parser.addListener(\"endpage\", endRule);\n\n    }\n\n});\n/*\n * Rule: Disallow duplicate background-images (using url).\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"duplicate-background-images\",\n    name: \"Disallow duplicate background images\",\n    desc: \"Every background-image should be unique. Use a common class for e.g. sprites.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            stack = {};\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text,\n                value = event.value,\n                i, len;\n\n            if (name.match(/background/i)) {\n                for (i=0, len=value.parts.length; i < len; i++) {\n                    if (value.parts[i].type == 'uri') {\n                        if (typeof stack[value.parts[i].uri] === 'undefined') {\n                            stack[value.parts[i].uri] = event;\n                        }\n                        else {\n                            reporter.report(\"Background image '\" + value.parts[i].uri + \"' was used multiple times, first declared at line \" + stack[value.parts[i].uri].line + \", col \" + stack[value.parts[i].uri].col + \".\", event.line, event.col, rule);\n                        }\n                    }\n                }\n            }\n        });\n    }\n});\n/*\n * Rule: Duplicate properties must appear one after the other. If an already-defined\n * property appears somewhere else in the rule, then it's likely an error.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"duplicate-properties\",\n    name: \"Disallow duplicate properties\",\n    desc: \"Duplicate properties must appear one after the other.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            properties,\n            lastProperty;            \n            \n        function startRule(event){\n            properties = {};        \n        }\n        \n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n        parser.addListener(\"startpage\", startRule);\n        parser.addListener(\"startpagemargin\", startRule);\n        parser.addListener(\"startkeyframerule\", startRule);        \n        \n        parser.addListener(\"property\", function(event){\n            var property = event.property,\n                name = property.text.toLowerCase();\n            \n            if (properties[name] && (lastProperty != name || properties[name] == event.value.text)){\n                reporter.report(\"Duplicate property '\" + event.property + \"' found.\", event.line, event.col, rule);\n            }\n            \n            properties[name] = event.value.text;\n            lastProperty = name;\n                        \n        });\n            \n        \n    }\n\n});\n/*\n * Rule: Style rules without any properties defined should be removed.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"empty-rules\",\n    name: \"Disallow empty rules\",\n    desc: \"Rules without any properties specified should be removed.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n        parser.addListener(\"startrule\", function(){\n            count=0;\n        });\n\n        parser.addListener(\"property\", function(){\n            count++;\n        });\n\n        parser.addListener(\"endrule\", function(event){\n            var selectors = event.selectors;\n            if (count === 0){\n                reporter.report(\"Rule is empty.\", selectors[0].line, selectors[0].col, rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: There should be no syntax errors. (Duh.)\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"errors\",\n    name: \"Parsing Errors\",\n    desc: \"This rule looks for recoverable syntax errors.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"error\", function(event){\n            reporter.error(event.message, event.line, event.col, rule);\n        });\n\n    }\n\n});\n\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"fallback-colors\",\n    name: \"Require fallback colors\",\n    desc: \"For older browsers that don't support RGBA, HSL, or HSLA, provide a fallback color.\",\n    browsers: \"IE6,IE7,IE8\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            lastProperty,\n            propertiesToCheck = {\n                color: 1,\n                background: 1,\n                \"background-color\": 1                \n            },\n            properties;\n        \n        function startRule(event){\n            properties = {};    \n            lastProperty = null;    \n        }\n        \n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n        parser.addListener(\"startpage\", startRule);\n        parser.addListener(\"startpagemargin\", startRule);\n        parser.addListener(\"startkeyframerule\", startRule);        \n        \n        parser.addListener(\"property\", function(event){\n            var property = event.property,\n                name = property.text.toLowerCase(),\n                parts = event.value.parts,\n                i = 0, \n                colorType = \"\",\n                len = parts.length;                \n                        \n            if(propertiesToCheck[name]){\n                while(i < len){\n                    if (parts[i].type == \"color\"){\n                        if (\"alpha\" in parts[i] || \"hue\" in parts[i]){\n                            \n                            if (/([^\\)]+)\\(/.test(parts[i])){\n                                colorType = RegExp.$1.toUpperCase();\n                            }\n                            \n                            if (!lastProperty || (lastProperty.property.text.toLowerCase() != name || lastProperty.colorType != \"compat\")){\n                                reporter.report(\"Fallback \" + name + \" (hex or RGB) should precede \" + colorType + \" \" + name + \".\", event.line, event.col, rule);\n                            }\n                        } else {\n                            event.colorType = \"compat\";\n                        }\n                    }\n                    \n                    i++;\n                }\n            }\n\n            lastProperty = event;\n        });        \n         \n    }\n\n});\n/*\n * Rule: You shouldn't use more than 10 floats. If you do, there's probably\n * room for some abstraction.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"floats\",\n    name: \"Disallow too many floats\",\n    desc: \"This rule tests if the float property is used too many times\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n        var count = 0;\n\n        //count how many times \"float\" is used\n        parser.addListener(\"property\", function(event){\n            if (event.property.text.toLowerCase() == \"float\" &&\n                    event.value.text.toLowerCase() != \"none\"){\n                count++;\n            }\n        });\n\n        //report the results\n        parser.addListener(\"endstylesheet\", function(){\n            reporter.stat(\"floats\", count);\n            if (count >= 10){\n                reporter.rollupWarn(\"Too many floats (\" + count + \"), you're probably using them for layout. Consider using a grid system instead.\", rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: Avoid too many @font-face declarations in the same stylesheet.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"font-faces\",\n    name: \"Don't use too many web fonts\",\n    desc: \"Too many different web fonts in the same stylesheet.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n\n        parser.addListener(\"startfontface\", function(){\n            count++;\n        });\n\n        parser.addListener(\"endstylesheet\", function(){\n            if (count > 5){\n                reporter.rollupWarn(\"Too many @font-face declarations (\" + count + \").\", rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: You shouldn't need more than 9 font-size declarations.\n */\n\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"font-sizes\",\n    name: \"Disallow too many font sizes\",\n    desc: \"Checks the number of font-size declarations.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n        //check for use of \"font-size\"\n        parser.addListener(\"property\", function(event){\n            if (event.property == \"font-size\"){\n                count++;\n            }\n        });\n\n        //report the results\n        parser.addListener(\"endstylesheet\", function(){\n            reporter.stat(\"font-sizes\", count);\n            if (count >= 10){\n                reporter.rollupWarn(\"Too many font-size declarations (\" + count + \"), abstraction needed.\", rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: When using a vendor-prefixed gradient, make sure to use them all.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"gradients\",\n    name: \"Require all gradient definitions\",\n    desc: \"When using a vendor-prefixed gradient, make sure to use them all.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            gradients;\n\n        parser.addListener(\"startrule\", function(){\n            gradients = {\n                moz: 0,\n                webkit: 0,\n                oldWebkit: 0,\n                ms: 0,\n                o: 0\n            };\n        });\n\n        parser.addListener(\"property\", function(event){\n\n            if (/\\-(moz|ms|o|webkit)(?:\\-(?:linear|radial))\\-gradient/i.test(event.value)){\n                gradients[RegExp.$1] = 1;\n            } else if (/\\-webkit\\-gradient/i.test(event.value)){\n                gradients.oldWebkit = 1;\n            }\n\n        });\n\n        parser.addListener(\"endrule\", function(event){\n            var missing = [];\n\n            if (!gradients.moz){\n                missing.push(\"Firefox 3.6+\");\n            }\n\n            if (!gradients.webkit){\n                missing.push(\"Webkit (Safari 5+, Chrome)\");\n            }\n            \n            if (!gradients.oldWebkit){\n                missing.push(\"Old Webkit (Safari 4+, Chrome)\");\n            }\n\n            if (!gradients.ms){\n                missing.push(\"Internet Explorer 10+\");\n            }\n\n            if (!gradients.o){\n                missing.push(\"Opera 11.1+\");\n            }\n\n            if (missing.length && missing.length < 5){            \n                reporter.report(\"Missing vendor-prefixed CSS gradients for \" + missing.join(\", \") + \".\", event.selectors[0].line, event.selectors[0].col, rule); \n            }\n\n        });\n\n    }\n\n});\n/*\n * Rule: Don't use IDs for selectors.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"ids\",\n    name: \"Disallow IDs in selectors\",\n    desc: \"Selectors should not contain IDs.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                idCount,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                idCount = 0;\n\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part.type == parser.SELECTOR_PART_TYPE){\n                        for (k=0; k < part.modifiers.length; k++){\n                            modifier = part.modifiers[k];\n                            if (modifier.type == \"id\"){\n                                idCount++;\n                            }\n                        }\n                    }\n                }\n\n                if (idCount == 1){\n                    reporter.report(\"Don't use IDs in selectors.\", selector.line, selector.col, rule);\n                } else if (idCount > 1){\n                    reporter.report(idCount + \" IDs in the selector, really?\", selector.line, selector.col, rule);\n                }\n            }\n\n        });\n    }\n\n});\n/*\n * Rule: Don't use @import, use <link> instead.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"import\",\n    name: \"Disallow @import\",\n    desc: \"Don't use @import, use <link> instead.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n        \n        parser.addListener(\"import\", function(event){        \n            reporter.report(\"@import prevents parallel downloads, use <link> instead.\", event.line, event.col, rule);\n        });\n\n    }\n\n});\n/*\n * Rule: Make sure !important is not overused, this could lead to specificity\n * war. Display a warning on !important declarations, an error if it's\n * used more at least 10 times.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"important\",\n    name: \"Disallow !important\",\n    desc: \"Be careful when using !important declaration\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n        //warn that important is used and increment the declaration counter\n        parser.addListener(\"property\", function(event){\n            if (event.important === true){\n                count++;\n                reporter.report(\"Use of !important\", event.line, event.col, rule);\n            }\n        });\n\n        //if there are more than 10, show an error\n        parser.addListener(\"endstylesheet\", function(){\n            reporter.stat(\"important\", count);\n            if (count >= 10){\n                reporter.rollupWarn(\"Too many !important declarations (\" + count + \"), try to use less than 10 to avoid specifity issues.\", rule);\n            }\n        });\n    }\n\n});\n/*\n * Rule: Properties should be known (listed in CSS3 specification) or\n * be a vendor-prefixed property.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"known-properties\",\n    name: \"Require use of known properties\",\n    desc: \"Properties should be known (listed in CSS specification) or be a vendor-prefixed property.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            properties = {\n\n                \"alignment-adjust\": 1,\n                \"alignment-baseline\": 1,\n                \"animation\": 1,\n                \"animation-delay\": 1,\n                \"animation-direction\": 1,\n                \"animation-duration\": 1,\n                \"animation-fill-mode\": 1,\n                \"animation-iteration-count\": 1,\n                \"animation-name\": 1,\n                \"animation-play-state\": 1,\n                \"animation-timing-function\": 1,\n                \"appearance\": 1,\n                \"azimuth\": 1,\n                \"backface-visibility\": 1,\n                \"background\": 1,\n                \"background-attachment\": 1,\n                \"background-break\": 1,\n                \"background-clip\": 1,\n                \"background-color\": 1,\n                \"background-image\": 1,\n                \"background-origin\": 1,\n                \"background-position\": 1,\n                \"background-repeat\": 1,\n                \"background-size\": 1,\n                \"baseline-shift\": 1,\n                \"binding\": 1,\n                \"bleed\": 1,\n                \"bookmark-label\": 1,\n                \"bookmark-level\": 1,\n                \"bookmark-state\": 1,\n                \"bookmark-target\": 1,\n                \"border\": 1,\n                \"border-bottom\": 1,\n                \"border-bottom-color\": 1,\n                \"border-bottom-left-radius\": 1,\n                \"border-bottom-right-radius\": 1,\n                \"border-bottom-style\": 1,\n                \"border-bottom-width\": 1,\n                \"border-collapse\": 1,\n                \"border-color\": 1,\n                \"border-image\": 1,\n                \"border-image-outset\": 1,\n                \"border-image-repeat\": 1,\n                \"border-image-slice\": 1,\n                \"border-image-source\": 1,\n                \"border-image-width\": 1,\n                \"border-left\": 1,\n                \"border-left-color\": 1,\n                \"border-left-style\": 1,\n                \"border-left-width\": 1,\n                \"border-radius\": 1,\n                \"border-right\": 1,\n                \"border-right-color\": 1,\n                \"border-right-style\": 1,\n                \"border-right-width\": 1,\n                \"border-spacing\": 1,\n                \"border-style\": 1,\n                \"border-top\": 1,\n                \"border-top-color\": 1,\n                \"border-top-left-radius\": 1,\n                \"border-top-right-radius\": 1,\n                \"border-top-style\": 1,\n                \"border-top-width\": 1,\n                \"border-width\": 1,\n                \"bottom\": 1, \n                \"box-align\": 1,\n                \"box-decoration-break\": 1,\n                \"box-direction\": 1,\n                \"box-flex\": 1,\n                \"box-flex-group\": 1,\n                \"box-lines\": 1,\n                \"box-ordinal-group\": 1,\n                \"box-orient\": 1,\n                \"box-pack\": 1,\n                \"box-shadow\": 1,\n                \"box-sizing\": 1,\n                \"break-after\": 1,\n                \"break-before\": 1,\n                \"break-inside\": 1,\n                \"caption-side\": 1,\n                \"clear\": 1,\n                \"clip\": 1,\n                \"color\": 1,\n                \"color-profile\": 1,\n                \"column-count\": 1,\n                \"column-fill\": 1,\n                \"column-gap\": 1,\n                \"column-rule\": 1,\n                \"column-rule-color\": 1,\n                \"column-rule-style\": 1,\n                \"column-rule-width\": 1,\n                \"column-span\": 1,\n                \"column-width\": 1,\n                \"columns\": 1,\n                \"content\": 1,\n                \"counter-increment\": 1,\n                \"counter-reset\": 1,\n                \"crop\": 1,\n                \"cue\": 1,\n                \"cue-after\": 1,\n                \"cue-before\": 1,\n                \"cursor\": 1,\n                \"direction\": 1,\n                \"display\": 1,\n                \"dominant-baseline\": 1,\n                \"drop-initial-after-adjust\": 1,\n                \"drop-initial-after-align\": 1,\n                \"drop-initial-before-adjust\": 1,\n                \"drop-initial-before-align\": 1,\n                \"drop-initial-size\": 1,\n                \"drop-initial-value\": 1,\n                \"elevation\": 1,\n                \"empty-cells\": 1,\n                \"fit\": 1,\n                \"fit-position\": 1,\n                \"float\": 1,                \n                \"float-offset\": 1,\n                \"font\": 1,\n                \"font-family\": 1,\n                \"font-size\": 1,\n                \"font-size-adjust\": 1,\n                \"font-stretch\": 1,\n                \"font-style\": 1,\n                \"font-variant\": 1,\n                \"font-weight\": 1,\n                \"grid-columns\": 1,\n                \"grid-rows\": 1,\n                \"hanging-punctuation\": 1,\n                \"height\": 1,\n                \"hyphenate-after\": 1,\n                \"hyphenate-before\": 1,\n                \"hyphenate-character\": 1,\n                \"hyphenate-lines\": 1,\n                \"hyphenate-resource\": 1,\n                \"hyphens\": 1,\n                \"icon\": 1,\n                \"image-orientation\": 1,\n                \"image-rendering\": 1,\n                \"image-resolution\": 1,\n                \"inline-box-align\": 1,\n                \"left\": 1,\n                \"letter-spacing\": 1,\n                \"line-height\": 1,\n                \"line-stacking\": 1,\n                \"line-stacking-ruby\": 1,\n                \"line-stacking-shift\": 1,\n                \"line-stacking-strategy\": 1,\n                \"list-style\": 1,\n                \"list-style-image\": 1,\n                \"list-style-position\": 1,\n                \"list-style-type\": 1,\n                \"margin\": 1,\n                \"margin-bottom\": 1,\n                \"margin-left\": 1,\n                \"margin-right\": 1,\n                \"margin-top\": 1,\n                \"mark\": 1,\n                \"mark-after\": 1,\n                \"mark-before\": 1,\n                \"marks\": 1,\n                \"marquee-direction\": 1,\n                \"marquee-play-count\": 1,\n                \"marquee-speed\": 1,\n                \"marquee-style\": 1,\n                \"max-height\": 1,\n                \"max-width\": 1,\n                \"min-height\": 1,\n                \"min-width\": 1,\n                \"move-to\": 1,\n                \"nav-down\": 1,\n                \"nav-index\": 1,\n                \"nav-left\": 1,\n                \"nav-right\": 1,\n                \"nav-up\": 1,\n                \"opacity\": 1,\n                \"orphans\": 1,\n                \"outline\": 1,\n                \"outline-color\": 1,\n                \"outline-offset\": 1,\n                \"outline-style\": 1,\n                \"outline-width\": 1,\n                \"overflow\": 1,\n                \"overflow-style\": 1,\n                \"overflow-x\": 1,\n                \"overflow-y\": 1,\n                \"padding\": 1,\n                \"padding-bottom\": 1,\n                \"padding-left\": 1,\n                \"padding-right\": 1,\n                \"padding-top\": 1,\n                \"page\": 1,\n                \"page-break-after\": 1,\n                \"page-break-before\": 1,\n                \"page-break-inside\": 1,\n                \"page-policy\": 1,\n                \"pause\": 1,\n                \"pause-after\": 1,\n                \"pause-before\": 1,\n                \"perspective\": 1,\n                \"perspective-origin\": 1,\n                \"phonemes\": 1,\n                \"pitch\": 1,\n                \"pitch-range\": 1,\n                \"play-during\": 1,\n                \"position\": 1,\n                \"presentation-level\": 1,\n                \"punctuation-trim\": 1,\n                \"quotes\": 1,\n                \"rendering-intent\": 1,\n                \"resize\": 1,\n                \"rest\": 1,\n                \"rest-after\": 1,\n                \"rest-before\": 1,\n                \"richness\": 1,\n                \"right\": 1,\n                \"rotation\": 1,\n                \"rotation-point\": 1,\n                \"ruby-align\": 1,\n                \"ruby-overhang\": 1,\n                \"ruby-position\": 1,\n                \"ruby-span\": 1,\n                \"size\": 1,\n                \"speak\": 1,\n                \"speak-header\": 1,\n                \"speak-numeral\": 1,\n                \"speak-punctuation\": 1,\n                \"speech-rate\": 1,\n                \"stress\": 1,\n                \"string-set\": 1,\n                \"table-layout\": 1,\n                \"target\": 1,\n                \"target-name\": 1,\n                \"target-new\": 1,\n                \"target-position\": 1,\n                \"text-align\": 1,\n                \"text-align-last\": 1,\n                \"text-decoration\": 1,\n                \"text-emphasis\": 1,\n                \"text-height\": 1,\n                \"text-indent\": 1,\n                \"text-justify\": 1,\n                \"text-outline\": 1,\n                \"text-shadow\": 1,\n                \"text-transform\": 1,\n                \"text-wrap\": 1,\n                \"top\": 1,\n                \"transform\": 1,\n                \"transform-origin\": 1,\n                \"transform-style\": 1,\n                \"transition\": 1,\n                \"transition-delay\": 1,\n                \"transition-duration\": 1,\n                \"transition-property\": 1,\n                \"transition-timing-function\": 1,\n                \"unicode-bidi\": 1,\n                \"user-modify\": 1,\n                \"user-select\": 1,\n                \"vertical-align\": 1,\n                \"visibility\": 1,\n                \"voice-balance\": 1,\n                \"voice-duration\": 1,\n                \"voice-family\": 1,\n                \"voice-pitch\": 1,\n                \"voice-pitch-range\": 1,\n                \"voice-rate\": 1,\n                \"voice-stress\": 1,\n                \"voice-volume\": 1,\n                \"volume\": 1,\n                \"white-space\": 1,\n                \"white-space-collapse\": 1,\n                \"widows\": 1,\n                \"width\": 1,\n                \"word-break\": 1,\n                \"word-spacing\": 1,\n                \"word-wrap\": 1,\n                \"z-index\": 1,\n                \n                //IE\n                \"filter\": 1,\n                \"zoom\": 1,\n                \n                //@font-face\n                \"src\": 1\n            };\n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase();\n\n            if (event.invalid) {\n                reporter.report(event.invalid.message, event.line, event.col, rule);\n            }\n            //if (!properties[name] && name.charAt(0) != \"-\"){\n            //    reporter.error(\"Unknown property '\" + event.property + \"'.\", event.line, event.col, rule);\n            //}\n\n        });\n    }\n\n});\n/*\n * Rule: outline: none or outline: 0 should only be used in a :focus rule\n *       and only if there are other properties in the same rule.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"outline-none\",\n    name: \"Disallow outline: none\",\n    desc: \"Use of outline: none or outline: 0 should be limited to :focus rules.\",\n    browsers: \"All\",\n    tags: [\"Accessibility\"],\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            lastRule;\n\n        function startRule(event){\n            if (event.selectors){\n                lastRule = {\n                    line: event.line,\n                    col: event.col,\n                    selectors: event.selectors,\n                    propCount: 0,\n                    outline: false\n                };\n            } else {\n                lastRule = null;\n            }\n        }\n        \n        function endRule(event){\n            if (lastRule){\n                if (lastRule.outline){\n                    if (lastRule.selectors.toString().toLowerCase().indexOf(\":focus\") == -1){\n                        reporter.report(\"Outlines should only be modified using :focus.\", lastRule.line, lastRule.col, rule);\n                    } else if (lastRule.propCount == 1) {\n                        reporter.report(\"Outlines shouldn't be hidden unless other visual changes are made.\", lastRule.line, lastRule.col, rule);                        \n                    }\n                }\n            }\n        }\n\n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n        parser.addListener(\"startpage\", startRule);\n        parser.addListener(\"startpagemargin\", startRule);\n        parser.addListener(\"startkeyframerule\", startRule); \n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase(),\n                value = event.value;                \n                \n            if (lastRule){\n                lastRule.propCount++;\n                if (name == \"outline\" && (value == \"none\" || value == \"0\")){\n                    lastRule.outline = true;\n                }            \n            }\n            \n        });\n        \n        parser.addListener(\"endrule\", endRule);\n        parser.addListener(\"endfontface\", endRule);\n        parser.addListener(\"endpage\", endRule);\n        parser.addListener(\"endpagemargin\", endRule);\n        parser.addListener(\"endkeyframerule\", endRule); \n\n    }\n\n});\n/*\n * Rule: Don't use classes or IDs with elements (a.foo or a#foo).\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"overqualified-elements\",\n    name: \"Disallow overqualified elements\",\n    desc: \"Don't use classes or IDs with elements (a.foo or a#foo).\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            classes = {};\n            \n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part.type == parser.SELECTOR_PART_TYPE){\n                        for (k=0; k < part.modifiers.length; k++){\n                            modifier = part.modifiers[k];\n                            if (part.elementName && modifier.type == \"id\"){\n                                reporter.report(\"Element (\" + part + \") is overqualified, just use \" + modifier + \" without element name.\", part.line, part.col, rule);\n                            } else if (modifier.type == \"class\"){\n                                \n                                if (!classes[modifier]){\n                                    classes[modifier] = [];\n                                }\n                                classes[modifier].push({ modifier: modifier, part: part });\n                            }\n                        }\n                    }\n                }\n            }\n        });\n        \n        parser.addListener(\"endstylesheet\", function(){\n        \n            var prop;\n            for (prop in classes){\n                if (classes.hasOwnProperty(prop)){\n                \n                    //one use means that this is overqualified\n                    if (classes[prop].length == 1 && classes[prop][0].part.elementName){\n                        reporter.report(\"Element (\" + classes[prop][0].part + \") is overqualified, just use \" + classes[prop][0].modifier + \" without element name.\", classes[prop][0].part.line, classes[prop][0].part.col, rule);\n                    }\n                }\n            }        \n        });\n    }\n\n});\n/*\n * Rule: Headings (h1-h6) should not be qualified (namespaced).\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"qualified-headings\",\n    name: \"Disallow qualified headings\",\n    desc: \"Headings should not be qualified (namespaced).\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                i, j;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part.type == parser.SELECTOR_PART_TYPE){\n                        if (part.elementName && /h[1-6]/.test(part.elementName.toString()) && j > 0){\n                            reporter.report(\"Heading (\" + part.elementName + \") should not be qualified.\", part.line, part.col, rule);\n                        }\n                    }\n                }\n            }\n        });\n    }\n\n});\n/*\n * Rule: Selectors that look like regular expressions are slow and should be avoided.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"regex-selectors\",\n    name: \"Disallow selectors that look like regexs\",\n    desc: \"Selectors that look like regular expressions are slow and should be avoided.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                for (j=0; j < selector.parts.length; j++){\n                    part = selector.parts[j];\n                    if (part.type == parser.SELECTOR_PART_TYPE){\n                        for (k=0; k < part.modifiers.length; k++){\n                            modifier = part.modifiers[k];\n                            if (modifier.type == \"attribute\"){\n                                if (/([\\~\\|\\^\\$\\*]=)/.test(modifier)){\n                                    reporter.report(\"Attribute selectors with \" + RegExp.$1 + \" are slow!\", modifier.line, modifier.col, rule);\n                                }\n                            }\n\n                        }\n                    }\n                }\n            }\n        });\n    }\n\n});\n/*\n * Rule: Total number of rules should not exceed x.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"rules-count\",\n    name: \"Rules Count\",\n    desc: \"Track how many rules there are.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            count = 0;\n\n        //count each rule\n        parser.addListener(\"startrule\", function(){\n            count++;\n        });\n\n        parser.addListener(\"endstylesheet\", function(){\n            reporter.stat(\"rule-count\", count);\n        });\n    }\n\n});\n/*\n * Rule: Use shorthand properties where possible.\n * \n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"shorthand\",\n    name: \"Require shorthand properties\",\n    desc: \"Use shorthand properties where possible.\",\n    browsers: \"All\",\n    \n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            prop, i, len,\n            propertiesToCheck = {},\n            properties,\n            mapping = {\n                \"margin\": [\n                    \"margin-top\",\n                    \"margin-bottom\",\n                    \"margin-left\",\n                    \"margin-right\"\n                ],\n                \"padding\": [\n                    \"padding-top\",\n                    \"padding-bottom\",\n                    \"padding-left\",\n                    \"padding-right\"\n                ]              \n            };\n            \n        //initialize propertiesToCheck \n        for (prop in mapping){\n            if (mapping.hasOwnProperty(prop)){\n                for (i=0, len=mapping[prop].length; i < len; i++){\n                    propertiesToCheck[mapping[prop][i]] = prop;\n                }\n            }\n        }\n            \n        function startRule(event){\n            properties = {};\n        }\n        \n        //event handler for end of rules\n        function endRule(event){\n            \n            var prop, i, len, total;\n            \n            //check which properties this rule has\n            for (prop in mapping){\n                if (mapping.hasOwnProperty(prop)){\n                    total=0;\n                    \n                    for (i=0, len=mapping[prop].length; i < len; i++){\n                        total += properties[mapping[prop][i]] ? 1 : 0;\n                    }\n                    \n                    if (total == mapping[prop].length){\n                        reporter.report(\"The properties \" + mapping[prop].join(\", \") + \" can be replaced by \" + prop + \".\", event.line, event.col, rule);\n                    }\n                }\n            }\n        }        \n        \n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n    \n        //check for use of \"font-size\"\n        parser.addListener(\"property\", function(event){\n            var name = event.property.toString().toLowerCase(),\n                value = event.value.parts[0].value;\n\n            if (propertiesToCheck[name]){\n                properties[name] = 1;\n            }\n        });\n\n        parser.addListener(\"endrule\", endRule);\n        parser.addListener(\"endfontface\", endRule);     \n\n    }\n\n});\n/*\n * Rule: Don't use text-indent for image replacement if you need to support rtl. \n * \n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"text-indent\",\n    name: \"Disallow negative text-indent\",\n    desc: \"Checks for text indent less than -99px\",\n    browsers: \"All\",\n    \n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            textIndent = false;\n            \n            \n        function startRule(event){\n            textIndent = false;\n        }\n        \n        //event handler for end of rules\n        function endRule(event){\n            if (textIndent){\n                reporter.report(\"Negative text-indent doesn't work well with RTL. If you use text-indent for image replacement explicitly set direction for that item to ltr.\", textIndent.line, textIndent.col, rule);\n            }\n        }        \n        \n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n    \n        //check for use of \"font-size\"\n        parser.addListener(\"property\", function(event){\n            var name = event.property.toString().toLowerCase(),\n                value = event.value;\n\n            if (name == \"text-indent\" && value.parts[0].value < -99){\n                textIndent = event.property;\n            } else if (name == \"direction\" && value == \"ltr\"){\n                textIndent = false;\n            }\n        });\n\n        parser.addListener(\"endrule\", endRule);\n        parser.addListener(\"endfontface\", endRule);     \n\n    }\n\n});\n/*\n * Rule: Headings (h1-h6) should be defined only once.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"unique-headings\",\n    name: \"Headings should only be defined once\",\n    desc: \"Headings should be defined only once.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        var headings =  {\n                h1: 0,\n                h2: 0,\n                h3: 0,\n                h4: 0,\n                h5: 0,\n                h6: 0\n            };\n\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                pseudo,\n                i, j;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                part = selector.parts[selector.parts.length-1];\n\n                if (part.elementName && /(h[1-6])/i.test(part.elementName.toString())){\n                    \n                    for (j=0; j < part.modifiers.length; j++){\n                        if (part.modifiers[j].type == \"pseudo\"){\n                            pseudo = true;\n                            break;\n                        }\n                    }\n                \n                    if (!pseudo){\n                        headings[RegExp.$1]++;\n                        if (headings[RegExp.$1] > 1) {\n                            reporter.report(\"Heading (\" + part.elementName + \") has already been defined.\", part.line, part.col, rule);\n                        }\n                    }\n                }\n            }\n        });\n        \n        parser.addListener(\"endstylesheet\", function(event){\n            var prop,\n                messages = [];\n                \n            for (prop in headings){\n                if (headings.hasOwnProperty(prop)){\n                    if (headings[prop] > 1){\n                        messages.push(headings[prop] + \" \" + prop + \"s\");\n                    }\n                }\n            }\n            \n            if (messages.length){\n                reporter.rollupWarn(\"You have \" + messages.join(\", \") + \" defined in this stylesheet.\", rule);\n            }\n        });        \n    }\n\n});\n/*\n * Rule: Don't use universal selector because it's slow.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"universal-selector\",\n    name: \"Disallow universal selector\",\n    desc: \"The universal selector (*) is known to be slow.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"startrule\", function(event){\n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                \n                part = selector.parts[selector.parts.length-1];\n                if (part.elementName == \"*\"){\n                    reporter.report(rule.desc, part.line, part.col, rule);\n                }\n            }\n        });\n    }\n\n});\n/*\n * Rule: Don't use unqualified attribute selectors because they're just like universal selectors.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"unqualified-attributes\",\n    name: \"Disallow unqualified attribute selectors\",\n    desc: \"Unqualified attribute selectors are known to be slow.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        parser.addListener(\"startrule\", function(event){\n            \n            var selectors = event.selectors,\n                selector,\n                part,\n                modifier,\n                i, j, k;\n\n            for (i=0; i < selectors.length; i++){\n                selector = selectors[i];\n                \n                part = selector.parts[selector.parts.length-1];\n                if (part.type == parser.SELECTOR_PART_TYPE){\n                    for (k=0; k < part.modifiers.length; k++){\n                        modifier = part.modifiers[k];\n                        if (modifier.type == \"attribute\" && (!part.elementName || part.elementName == \"*\")){\n                            reporter.report(rule.desc, part.line, part.col, rule);                               \n                        }\n                    }\n                }\n                \n            }            \n        });\n    }\n\n});\n/*\n * Rule: When using a vendor-prefixed property, make sure to\n * include the standard one.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"vendor-prefix\",\n    name: \"Require standard property with vendor prefix\",\n    desc: \"When using a vendor-prefixed property, make sure to include the standard one.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this,\n            properties,\n            num,\n            propertiesToCheck = {\n                \"-webkit-border-radius\": \"border-radius\",\n                \"-webkit-border-top-left-radius\": \"border-top-left-radius\",\n                \"-webkit-border-top-right-radius\": \"border-top-right-radius\",\n                \"-webkit-border-bottom-left-radius\": \"border-bottom-left-radius\",\n                \"-webkit-border-bottom-right-radius\": \"border-bottom-right-radius\",\n                \n                \"-o-border-radius\": \"border-radius\",\n                \"-o-border-top-left-radius\": \"border-top-left-radius\",\n                \"-o-border-top-right-radius\": \"border-top-right-radius\",\n                \"-o-border-bottom-left-radius\": \"border-bottom-left-radius\",\n                \"-o-border-bottom-right-radius\": \"border-bottom-right-radius\",\n                \n                \"-moz-border-radius\": \"border-radius\",\n                \"-moz-border-radius-topleft\": \"border-top-left-radius\",\n                \"-moz-border-radius-topright\": \"border-top-right-radius\",\n                \"-moz-border-radius-bottomleft\": \"border-bottom-left-radius\",\n                \"-moz-border-radius-bottomright\": \"border-bottom-right-radius\",                \n                \n                \"-moz-column-count\": \"column-count\",\n                \"-webkit-column-count\": \"column-count\",\n                \n                \"-moz-column-gap\": \"column-gap\",\n                \"-webkit-column-gap\": \"column-gap\",\n                \n                \"-moz-column-rule\": \"column-rule\",\n                \"-webkit-column-rule\": \"column-rule\",\n                \n                \"-moz-column-rule-style\": \"column-rule-style\",\n                \"-webkit-column-rule-style\": \"column-rule-style\",\n                \n                \"-moz-column-rule-color\": \"column-rule-color\",\n                \"-webkit-column-rule-color\": \"column-rule-color\",\n                \n                \"-moz-column-rule-width\": \"column-rule-width\",\n                \"-webkit-column-rule-width\": \"column-rule-width\",\n                \n                \"-moz-column-width\": \"column-width\",\n                \"-webkit-column-width\": \"column-width\",\n                \n                \"-webkit-column-span\": \"column-span\",\n                \"-webkit-columns\": \"columns\",\n                \n                \"-moz-box-shadow\": \"box-shadow\",\n                \"-webkit-box-shadow\": \"box-shadow\",\n                \n                \"-moz-transform\" : \"transform\",\n                \"-webkit-transform\" : \"transform\",\n                \"-o-transform\" : \"transform\",\n                \"-ms-transform\" : \"transform\",\n                \n                \"-moz-transform-origin\" : \"transform-origin\",\n                \"-webkit-transform-origin\" : \"transform-origin\",\n                \"-o-transform-origin\" : \"transform-origin\",\n                \"-ms-transform-origin\" : \"transform-origin\",\n                \n                \"-moz-box-sizing\" : \"box-sizing\",\n                \"-webkit-box-sizing\" : \"box-sizing\",\n                \n                \"-moz-user-select\" : \"user-select\",\n                \"-khtml-user-select\" : \"user-select\",\n                \"-webkit-user-select\" : \"user-select\"                \n            };\n\n        //event handler for beginning of rules\n        function startRule(){\n            properties = {};\n            num=1;        \n        }\n        \n        //event handler for end of rules\n        function endRule(event){\n            var prop,\n                i, len,\n                standard,\n                needed,\n                actual,\n                needsStandard = [];\n\n            for (prop in properties){\n                if (propertiesToCheck[prop]){\n                    needsStandard.push({ actual: prop, needed: propertiesToCheck[prop]});\n                }\n            }\n\n            for (i=0, len=needsStandard.length; i < len; i++){\n                needed = needsStandard[i].needed;\n                actual = needsStandard[i].actual;\n\n                if (!properties[needed]){               \n                    reporter.report(\"Missing standard property '\" + needed + \"' to go along with '\" + actual + \"'.\", properties[actual][0].name.line, properties[actual][0].name.col, rule);\n                } else {\n                    //make sure standard property is last\n                    if (properties[needed][0].pos < properties[actual][0].pos){\n                        reporter.report(\"Standard property '\" + needed + \"' should come after vendor-prefixed property '\" + actual + \"'.\", properties[actual][0].name.line, properties[actual][0].name.col, rule);\n                    }\n                }\n            }\n\n        }        \n        \n        parser.addListener(\"startrule\", startRule);\n        parser.addListener(\"startfontface\", startRule);\n        parser.addListener(\"startpage\", startRule);\n        parser.addListener(\"startpagemargin\", startRule);\n        parser.addListener(\"startkeyframerule\", startRule);         \n\n        parser.addListener(\"property\", function(event){\n            var name = event.property.text.toLowerCase();\n\n            if (!properties[name]){\n                properties[name] = [];\n            }\n\n            properties[name].push({ name: event.property, value : event.value, pos:num++ });\n        });\n\n        parser.addListener(\"endrule\", endRule);\n        parser.addListener(\"endfontface\", endRule);\n        parser.addListener(\"endpage\", endRule);\n        parser.addListener(\"endpagemargin\", endRule);\n        parser.addListener(\"endkeyframerule\", endRule);         \n    }\n\n});\n/*\n * Rule: You don't need to specify units when a value is 0.\n */\n/*global CSSLint*/\nCSSLint.addRule({\n\n    //rule information\n    id: \"zero-units\",\n    name: \"Disallow units for 0 values\",\n    desc: \"You don't need to specify units when a value is 0.\",\n    browsers: \"All\",\n\n    //initialization\n    init: function(parser, reporter){\n        var rule = this;\n\n        //count how many times \"float\" is used\n        parser.addListener(\"property\", function(event){\n            var parts = event.value.parts,\n                i = 0, \n                len = parts.length;\n\n            while(i < len){\n                if ((parts[i].units || parts[i].type == \"percentage\") && parts[i].value === 0 && parts[i].type != \"time\"){\n                    reporter.report(\"Values of 0 shouldn't have units specified.\", parts[i].line, parts[i].col, rule);\n                }\n                i++;\n            }\n\n        });\n\n    }\n\n});\n/*global CSSLint*/\nCSSLint.addFormatter({\n    //format information\n    id: \"checkstyle-xml\",\n    name: \"Checkstyle XML format\",\n\n    /**\n     * Return opening root XML tag.\n     * @return {String} to prepend before all results\n     */\n    startFormat: function(){\n        return \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><checkstyle>\";\n    },\n\n    /**\n     * Return closing root XML tag.\n     * @return {String} to append after all results\n     */\n    endFormat: function(){\n        return \"</checkstyle>\";\n    },\n\n    /**\n     * Given CSS Lint results for a file, return output for this format.\n     * @param results {Object} with error and warning messages\n     * @param filename {String} relative file path\n     * @param options {Object} (UNUSED for now) specifies special handling of output\n     * @return {String} output for results\n     */\n    formatResults: function(results, filename, options) {\n        var messages = results.messages,\n            output = [];\n\n        /**\n         * Generate a source string for a rule.\n         * Checkstyle source strings usually resemble Java class names e.g\n         * net.csslint.SomeRuleName\n         * @param {Object} rule\n         * @return rule source as {String}\n         */\n        var generateSource = function(rule) {\n            if (!rule || !('name' in rule)) {\n                return \"\";\n            }\n            return 'net.csslint.' + rule.name.replace(/\\s/g,'');\n        };\n\n        /**\n         * Replace special characters before write to output.\n         *\n         * Rules:\n         *  - single quotes is the escape sequence for double-quotes\n         *  - &lt; is the escape sequence for <\n         *  - &gt; is the escape sequence for >\n         *\n         * @param {String} message to escape\n         * @return escaped message as {String}\n         */\n        var escapeSpecialCharacters = function(str) {\n            if (!str || str.constructor !== String) {\n                return \"\";\n            }\n            return str.replace(/\\\"/g, \"'\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n        };\n\n        if (messages.length > 0) {\n            output.push(\"<file name=\\\"\"+filename+\"\\\">\");\n            CSSLint.Util.forEach(messages, function (message, i) {\n                //ignore rollups for now\n                if (!message.rollup) {\n                  output.push(\"<error line=\\\"\" + message.line + \"\\\" column=\\\"\" + message.col + \"\\\" severity=\\\"\" + message.type + \"\\\"\" +\n                      \" message=\\\"\" + escapeSpecialCharacters(message.message) + \"\\\" source=\\\"\" + generateSource(message.rule) +\"\\\"/>\");\n                }\n            });\n            output.push(\"</file>\");\n        }\n\n        return output.join(\"\");\n    }\n});\n/*global CSSLint*/\nCSSLint.addFormatter({\n    //format information\n    id: \"compact\",\n    name: \"Compact, 'porcelain' format\",\n\n    /**\n     * Return content to be printed before all file results.\n     * @return {String} to prepend before all results\n     */\n    startFormat: function() {\n        return \"\";\n    },\n\n    /**\n     * Return content to be printed after all file results.\n     * @return {String} to append after all results\n     */\n    endFormat: function() {\n        return \"\";\n    },\n\n    /**\n     * Given CSS Lint results for a file, return output for this format.\n     * @param results {Object} with error and warning messages\n     * @param filename {String} relative file path\n     * @param options {Object} (Optional) specifies special handling of output\n     * @return {String} output for results\n     */\n    formatResults: function(results, filename, options) {\n        var messages = results.messages,\n            output = \"\";\n        options = options || {};\n\n        /**\n         * Capitalize and return given string.\n         * @param str {String} to capitalize\n         * @return {String} capitalized\n         */\n        var capitalize = function(str) {\n            return str.charAt(0).toUpperCase() + str.slice(1);\n        };\n\n        if (messages.length === 0) {\n            return options.quiet ? \"\" : filename + \": Lint Free!\";\n        }\n\n        CSSLint.Util.forEach(messages, function(message, i) {\n            if (message.rollup) {\n                output += filename + \": \" + capitalize(message.type) + \" - \" + message.message + \"\\n\";\n            } else {\n                output += filename + \": \" + \"line \" + message.line + \n                    \", col \" + message.col + \", \" + capitalize(message.type) + \" - \" + message.message + \"\\n\";\n            }\n        });\n    \n        return output;\n    }\n});\n/*global CSSLint*/\nCSSLint.addFormatter({\n    //format information\n    id: \"csslint-xml\",\n    name: \"CSSLint XML format\",\n\n    /**\n     * Return opening root XML tag.\n     * @return {String} to prepend before all results\n     */\n    startFormat: function(){\n        return \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><csslint>\";\n    },\n\n    /**\n     * Return closing root XML tag.\n     * @return {String} to append after all results\n     */\n    endFormat: function(){\n        return \"</csslint>\";\n    },\n\n    /**\n     * Given CSS Lint results for a file, return output for this format.\n     * @param results {Object} with error and warning messages\n     * @param filename {String} relative file path\n     * @param options {Object} (UNUSED for now) specifies special handling of output\n     * @return {String} output for results\n     */\n    formatResults: function(results, filename, options) {\n        var messages = results.messages,\n            output = [];\n\n        /**\n         * Replace special characters before write to output.\n         *\n         * Rules:\n         *  - single quotes is the escape sequence for double-quotes\n         *  - &lt; is the escape sequence for <\n         *  - &gt; is the escape sequence for >\n         * \n         * @param {String} message to escape\n         * @return escaped message as {String}\n         */\n        var escapeSpecialCharacters = function(str) {\n            if (!str || str.constructor !== String) {\n                return \"\";\n            }\n            return str.replace(/\\\"/g, \"'\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n        };\n\n        if (messages.length > 0) {\n            output.push(\"<file name=\\\"\"+filename+\"\\\">\");\n            CSSLint.Util.forEach(messages, function (message, i) {\n                if (message.rollup) {\n                    output.push(\"<issue severity=\\\"\" + message.type + \"\\\" reason=\\\"\" + escapeSpecialCharacters(message.message) + \"\\\" evidence=\\\"\" + escapeSpecialCharacters(message.evidence) + \"\\\"/>\");\n                } else {\n                    output.push(\"<issue line=\\\"\" + message.line + \"\\\" char=\\\"\" + message.col + \"\\\" severity=\\\"\" + message.type + \"\\\"\" +\n                        \" reason=\\\"\" + escapeSpecialCharacters(message.message) + \"\\\" evidence=\\\"\" + escapeSpecialCharacters(message.evidence) + \"\\\"/>\");\n                }\n            });\n            output.push(\"</file>\");\n        }\n\n        return output.join(\"\");\n    }\n});\n/*global CSSLint*/\nCSSLint.addFormatter({\n    //format information\n    id: \"lint-xml\",\n    name: \"Lint XML format\",\n\n    /**\n     * Return opening root XML tag.\n     * @return {String} to prepend before all results\n     */\n    startFormat: function(){\n        return \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?><lint>\";\n    },\n\n    /**\n     * Return closing root XML tag.\n     * @return {String} to append after all results\n     */\n    endFormat: function(){\n        return \"</lint>\";\n    },\n\n    /**\n     * Given CSS Lint results for a file, return output for this format.\n     * @param results {Object} with error and warning messages\n     * @param filename {String} relative file path\n     * @param options {Object} (UNUSED for now) specifies special handling of output\n     * @return {String} output for results\n     */\n    formatResults: function(results, filename, options) {\n        var messages = results.messages,\n            output = [];\n\n        /**\n         * Replace special characters before write to output.\n         *\n         * Rules:\n         *  - single quotes is the escape sequence for double-quotes\n         *  - &lt; is the escape sequence for <\n         *  - &gt; is the escape sequence for >\n         * \n         * @param {String} message to escape\n         * @return escaped message as {String}\n         */\n        var escapeSpecialCharacters = function(str) {\n            if (!str || str.constructor !== String) {\n                return \"\";\n            }\n            return str.replace(/\\\"/g, \"'\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n        };\n\n        if (messages.length > 0) {\n        \n            output.push(\"<file name=\\\"\"+filename+\"\\\">\");\n            CSSLint.Util.forEach(messages, function (message, i) {\n                if (message.rollup) {\n                    output.push(\"<issue severity=\\\"\" + message.type + \"\\\" reason=\\\"\" + escapeSpecialCharacters(message.message) + \"\\\" evidence=\\\"\" + escapeSpecialCharacters(message.evidence) + \"\\\"/>\");\n                } else {\n                    output.push(\"<issue line=\\\"\" + message.line + \"\\\" char=\\\"\" + message.col + \"\\\" severity=\\\"\" + message.type + \"\\\"\" +\n                        \" reason=\\\"\" + escapeSpecialCharacters(message.message) + \"\\\" evidence=\\\"\" + escapeSpecialCharacters(message.evidence) + \"\\\"/>\");\n                }\n            });\n            output.push(\"</file>\");\n        }\n\n        return output.join(\"\");\n    }\n});\n/*global CSSLint*/\nCSSLint.addFormatter({\n    //format information\n    id: \"text\",\n    name: \"Plain Text\",\n\n    /**\n     * Return content to be printed before all file results.\n     * @return {String} to prepend before all results\n     */\n    startFormat: function() {\n        return \"\";\n    },\n\n    /**\n     * Return content to be printed after all file results.\n     * @return {String} to append after all results\n     */\n    endFormat: function() {\n        return \"\";\n    },\n\n    /**\n     * Given CSS Lint results for a file, return output for this format.\n     * @param results {Object} with error and warning messages\n     * @param filename {String} relative file path\n     * @param options {Object} (Optional) specifies special handling of output\n     * @return {String} output for results\n     */\n    formatResults: function(results, filename, options) {\n        var messages = results.messages,\n            output = \"\";\n        options = options || {};\n\n        if (messages.length === 0) {\n            return options.quiet ? \"\" : \"\\n\\ncsslint: No errors in \" + filename + \".\";\n        }\n\n        output = \"\\n\\ncsslint: There are \" + messages.length  +  \" problems in \" + filename + \".\";\n        var pos = filename.lastIndexOf(\"/\"),\n            shortFilename = filename;\n\n        if (pos === -1){\n            pos = filename.lastIndexOf(\"\\\\\");       \n        }\n        if (pos > -1){\n            shortFilename = filename.substring(pos+1);\n        }\n\n        CSSLint.Util.forEach(messages, function (message, i) {\n            output = output + \"\\n\\n\" + shortFilename;\n            if (message.rollup) {\n                output += \"\\n\" + (i+1) + \": \" + message.type;\n                output += \"\\n\" + message.message;\n            } else {\n                output += \"\\n\" + (i+1) + \": \" + message.type + \" at line \" + message.line + \", col \" + message.col;\n                output += \"\\n\" + message.message;\n                output += \"\\n\" + message.evidence;\n            }\n        });\n    \n        return output;\n    }\n});\n\n\nexports.CSSLint = CSSLint;\n\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/css.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar CssHighlightRules = require(\"./css_highlight_rules\").CssHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar WorkerClient = require(\"../worker/worker_client\").WorkerClient;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new CssHighlightRules().getRules(), \"i\");\n    this.$outdent = new MatchingBraceOutdent();\n    this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.foldingRules = \"cStyle\";\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        // ignore braces in comments\n        var tokens = this.$tokenizer.getLineTokens(line, state).tokens;\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n\n        var match = line.match(/^.*\\{\\s*$/);\n        if (match) {\n            indent += tab;\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n    \n    this.createWorker = function(session) {\n        var worker = new WorkerClient([\"ace\"], \"worker-css.js\", \"ace/mode/css_worker\", \"Worker\");\n        worker.attachToDocument(session.getDocument());\n        \n        worker.on(\"csslint\", function(e) {\n            var errors = [];\n            e.data.forEach(function(message) {\n                errors.push({\n                    row: message.line - 1,\n                    column: message.col - 1,\n                    text: message.message,\n                    type: message.type,\n                    lint: message\n                });\n            });\n            \n            session.setAnnotations(errors);\n        });\n        return worker;\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/css_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar CssHighlightRules = function() {\n\n    var properties = lang.arrayToMap(\n        (\"animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index\").split(\"|\")\n    );\n\n    var functions = lang.arrayToMap(\n        (\"rgb|rgba|url|attr|counter|counters\").split(\"|\")\n    );\n\n    var constants = lang.arrayToMap(\n        (\"absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|font-size|font|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero\").split(\"|\")\n    );\n\n    var colors = lang.arrayToMap(\n        (\"aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|\" +\n        \"purple|red|silver|teal|white|yellow\").split(\"|\")\n    );\n\n    var fonts = lang.arrayToMap(\n        (\"arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|\" +\n        \"symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|\" +\n        \"serif|monospace\").split(\"|\")\n    );\n    \n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    var numRe = \"\\\\-?(?:(?:[0-9]+)|(?:[0-9]*\\\\.[0-9]+))\";\n    var pseudoElements = \"(\\\\:+)\\\\b(after|before|first-letter|first-line|moz-selection|selection)\\\\b\";\n    var pseudoClasses = \"(:)\\\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\\\b\";\n    \n    var base_ruleset = [\n        {\n            token : \"comment\", // multi line comment\n            merge : true,\n            regex : \"\\\\/\\\\*\",\n            next : \"ruleset_comment\"\n        }, {\n            token : \"string\", // single line\n            regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n        }, {\n            token : \"string\", // single line\n            regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n        }, {\n            token : [\"constant.numeric\", \"keyword\"],\n            regex : \"(\" + numRe + \")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)\"\n        }, {\n            token : [\"constant.numeric\"],\n            regex : \"([0-9]+)\"\n        }, {\n            token : \"constant.numeric\",  // hex6 color\n            regex : \"#[a-f0-9]{6}\"\n        }, {\n            token : \"constant.numeric\", // hex3 color\n            regex : \"#[a-f0-9]{3}\"\n        }, {\n            token : [\"punctuation\", \"entity.other.attribute-name.pseudo-element.css\"], \n            regex : pseudoElements\n        }, {\n            token : [\"punctuation\", \"entity.other.attribute-name.pseudo-class.css\"], \n            regex : pseudoClasses\n        }, {\n            token : function(value) {\n                if (properties.hasOwnProperty(value.toLowerCase())) {\n                    return \"support.type\";\n                }\n                else if (functions.hasOwnProperty(value.toLowerCase())) {\n                    return \"support.function\";\n                }\n                else if (constants.hasOwnProperty(value.toLowerCase())) {\n                    return \"support.constant\";\n                }\n                else if (colors.hasOwnProperty(value.toLowerCase())) {\n                    return \"support.constant.color\";\n                }\n                else if (fonts.hasOwnProperty(value.toLowerCase())) {\n                    return \"support.constant.fonts\";\n                }\n                else {\n                    return \"text\";\n                }\n            },\n            regex : \"\\\\-?[a-zA-Z_][a-zA-Z0-9_\\\\-]*\"\n        } \n      ];\n\n    var ruleset = lang.copyArray(base_ruleset);\n    ruleset.unshift({\n        token : \"paren.rparen\",\n        regex : \"\\\\}\",\n        next:   \"start\"\n    });\n\n    var media_ruleset = lang.copyArray( base_ruleset );\n    media_ruleset.unshift({\n        token : \"paren.rparen\",\n        regex : \"\\\\}\",\n        next:   \"media\"\n    });\n\n    var base_comment = [{\n          token : \"comment\", // comment spanning whole line\n          merge : true,\n          regex : \".+\"\n    }];\n\n    var comment = lang.copyArray(base_comment);\n    comment.unshift({\n          token : \"comment\", // closing comment\n          regex : \".*?\\\\*\\\\/\",\n          next : \"start\"\n    });\n\n    var media_comment = lang.copyArray(base_comment);\n    media_comment.unshift({\n          token : \"comment\", // closing comment\n          regex : \".*?\\\\*\\\\/\",\n          next : \"media\"\n    });\n\n    var ruleset_comment = lang.copyArray(base_comment);\n    ruleset_comment.unshift({\n          token : \"comment\", // closing comment\n          regex : \".*?\\\\*\\\\/\",\n          next : \"ruleset\"\n    });\n\n    this.$rules = {\n        \"start\" : [{\n            token : \"comment\", // multi line comment\n            merge : true,\n            regex : \"\\\\/\\\\*\",\n            next : \"comment\"\n        }, {\n            token: \"paren.lparen\",\n            regex: \"\\\\{\",\n            next:  \"ruleset\"\n        }, {\n            token: \"string\",\n            regex: \"@.*?{\",\n            next:  \"media\"\n        },{\n            token: \"keyword\",\n            regex: \"#[a-z0-9-_]+\"\n        },{\n            token: \"variable\",\n            regex: \"\\\\.[a-z0-9-_]+\"\n        },{\n            token: \"string\",\n            regex: \":[a-z0-9-_]+\"\n        },{\n            token: \"constant\",\n            regex: \"[a-z0-9-_]+\"\n        }],\n\n        \"media\" : [ {\n            token : \"comment\", // multi line comment\n            merge : true,\n            regex : \"\\\\/\\\\*\",\n            next : \"media_comment\"\n        }, {\n            token: \"paren.lparen\",\n            regex: \"\\\\{\",\n            next:  \"media_ruleset\"\n        },{\n            token: \"string\",\n            regex: \"\\\\}\",\n            next:  \"start\"\n        },{\n            token: \"keyword\",\n            regex: \"#[a-z0-9-_]+\"\n        },{\n            token: \"variable\",\n            regex: \"\\\\.[a-z0-9-_]+\"\n        },{\n            token: \"string\",\n            regex: \":[a-z0-9-_]+\"\n        },{\n            token: \"constant\",\n            regex: \"[a-z0-9-_]+\"\n        }],\n\n        \"comment\" : comment,\n\n        \"ruleset\" : ruleset,\n        \"ruleset_comment\" : ruleset_comment,\n\n        \"media_ruleset\" : media_ruleset,\n        \"media_comment\" : media_comment\n    };\n};\n\noop.inherits(CssHighlightRules, TextHighlightRules);\n\nexports.CssHighlightRules = CssHighlightRules;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/css_highlight_rules_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar CssMode = require(\"./css\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n    \n    name: \"CSS Tokenizer\",\n    \n    setUp : function() {\n        this.tokenizer = new CssMode().getTokenizer();\n    },\n\n    \"test: tokenize pixel number\" : function() {\n        var line = \"-12px\";\n        var tokens = this.tokenizer.getLineTokens(line, \"ruleset\").tokens;\n\n        assert.equal(2, tokens.length);\n        assert.equal(\"constant.numeric\", tokens[0].type);\n    },\n\n    \"test: tokenize hex3 color\" : function() {\n        var tokens = this.tokenizer.getLineTokens(\"#abc\", \"ruleset\").tokens;\n\n        assert.equal(1, tokens.length);\n        assert.equal(\"constant.numeric\", tokens[0].type);\n    },\n\n    \"test: tokenize hex6 color\" : function() {\n        var tokens = this.tokenizer.getLineTokens(\"#abc012\", \"ruleset\").tokens;\n\n        assert.equal(1, tokens.length);\n        assert.equal(\"constant.numeric\", tokens[0].type);\n    },\n\n    \"test: tokenize parens\" : function() {\n        var tokens = this.tokenizer.getLineTokens(\"{()}\", \"start\").tokens;\n\n        assert.equal(3, tokens.length);\n        assert.equal(\"paren.lparen\", tokens[0].type);\n        assert.equal(\"text\", tokens[1].type);\n        assert.equal(\"paren.rparen\", tokens[2].type);\n    },\n    \n    \"test for last rule in ruleset to catch capturing group bugs\" : function() {\n        var tokens = this.tokenizer.getLineTokens(\"top\", \"ruleset\").tokens;\n        \n        assert.equal(1, tokens.length);\n        assert.equal(\"support.type\", tokens[0].type);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/css_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"../edit_session\").EditSession;\nvar CssMode = require(\"./css\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n    \n    name: \"CSS\",\n    \n    setUp : function() {\n        this.mode = new CssMode();\n    },\n\n    \"test: toggle comment lines should not do anything\" : function() {\n        var session = new EditSession([\"  abc\", \"cde\", \"fg\"].join(\"\\n\"));\n\n        var comment = this.mode.toggleCommentLines(\"start\", session, 0, 1);\n        assert.equal([\"  abc\", \"cde\", \"fg\"].join(\"\\n\"), session.toString());\n    },\n\n\n    \"test: lines should keep indentation\" : function() {\n        assert.equal(\"   \", this.mode.getNextLineIndent(\"start\", \"   abc\", \"  \"));\n        assert.equal(\"\\t\", this.mode.getNextLineIndent(\"start\", \"\\tabc\", \"  \"));\n    },\n\n    \"test: new line after { should increase indent\" : function() {\n        assert.equal(\"     \", this.mode.getNextLineIndent(\"start\", \"   abc{\", \"  \"));\n        assert.equal(\"\\t  \", this.mode.getNextLineIndent(\"start\", \"\\tabc  { \", \"  \"));\n    },\n\n    \"test: no indent increase after { in a comment\" : function() {\n        assert.equal(\"   \", this.mode.getNextLineIndent(\"start\", \"   /*{\", \"  \"));\n        assert.equal(\"   \", this.mode.getNextLineIndent(\"start\", \"   /*{  \", \"  \"));\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/css_worker.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n \ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar Mirror = require(\"../worker/mirror\").Mirror;\nvar CSSLint = require(\"./css/csslint\").CSSLint;\n\nvar Worker = exports.Worker = function(sender) {\n    Mirror.call(this, sender);\n    this.setTimeout(200);\n};\n\noop.inherits(Worker, Mirror);\n\n(function() {\n    \n    this.onUpdate = function() {\n        var value = this.doc.getValue();\n        \n        var result = CSSLint.verify(value);\n        this.sender.emit(\"csslint\", result.messages.map(function(msg) {\n            delete msg.rule;\n            return msg;\n        }));\n    };\n    \n}).call(Worker.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/css_worker_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar assert = require(\"../test/assertions\");\nvar Worker = require(\"./css_worker\").Worker;\n\n\nmodule.exports = {\n    setUp : function() {\n        this.sender = {\n            on: function() {},\n            callback: function(data, id) {\n                this.data = data;\n            },\n            events: [],\n            emit: function(type, e) {\n                this.events.push([type, e]);\n            }\n        };\n    },\n    \n    \"test check for syntax error\": function() {\n        var worker = new Worker(this.sender);\n        worker.setValue(\"Juhu Kinners\");\n        worker.deferredUpdate.call();\n        assert.equal(this.sender.events[0][1][0].type, \"error\");\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/doc_comment_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar DocCommentHighlightRules = function() {\n\n    this.$rules = {\n        \"start\" : [ {\n            token : \"comment.doc.tag\",\n            regex : \"@[\\\\w\\\\d_]+\" // TODO: fix email addresses\n        }, {\n            token : \"comment.doc\",\n            merge : true,\n            regex : \"\\\\s+\"\n        }, {\n            token : \"comment.doc\",\n            merge : true,\n            regex : \"TODO\"\n        }, {\n            token : \"comment.doc\",\n            merge : true,\n            regex : \"[^@\\\\*]+\"\n        }, {\n            token : \"comment.doc\",\n            merge : true,\n            regex : \".\"\n        }]\n    };\n};\n\noop.inherits(DocCommentHighlightRules, TextHighlightRules);\n\nDocCommentHighlightRules.getStartRule = function(start) {\n    return {\n        token : \"comment.doc\", // doc comment\n        merge : true,\n        regex : \"\\\\/\\\\*(?=\\\\*)\",\n        next  : start\n    };\n};\n\nDocCommentHighlightRules.getEndRule = function (start) {\n    return {\n        token : \"comment.doc\", // closing comment\n        merge : true,\n        regex : \"\\\\*\\\\/\",\n        next  : start\n    };\n};\n\n\nexports.DocCommentHighlightRules = DocCommentHighlightRules;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/folding/cstyle.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../../lib/oop\");\nvar Range = require(\"../../range\").Range;\nvar BaseFoldMode = require(\"./fold_mode\").FoldMode;\n\nvar FoldMode = exports.FoldMode = function() {};\noop.inherits(FoldMode, BaseFoldMode);\n\n(function() {\n\n    this.foldingStartMarker = /(\\{|\\[)[^\\}\\]]*$|^\\s*(\\/\\*)/;\n    this.foldingStopMarker = /^[^\\[\\{]*(\\}|\\])|^[\\s\\*]*(\\*\\/)/;\n    \n    this.getFoldWidgetRange = function(session, foldStyle, row) {\n        var line = session.getLine(row);\n        var match = line.match(this.foldingStartMarker);\n        if (match) {\n            var i = match.index;\n\n            if (match[1])\n                return this.openingBracketBlock(session, match[1], row, i);\n\n            var range = session.getCommentFoldRange(row, i + match[0].length);\n            range.end.column -= 2;\n            return range;\n        }\n\n        if (foldStyle !== \"markbeginend\")\n            return;\n            \n        var match = line.match(this.foldingStopMarker);\n        if (match) {\n            var i = match.index + match[0].length;\n\n            if (match[2]) {\n                var range = session.getCommentFoldRange(row, i);\n                range.end.column -= 2;\n                return range;\n            }\n\n            var end = {row: row, column: i};\n            var start = session.$findOpeningBracket(match[1], end);\n            \n            if (!start)\n                return;\n\n            start.column++;\n            end.column--;\n\n            return  Range.fromPoints(start, end);\n        }\n    };\n    \n}).call(FoldMode.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/folding/cstyle_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\")\n    require(\"amd-loader\");\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar JavaScriptMode = require(\"../javascript\").Mode;\nvar EditSession = require(\"../../edit_session\").EditSession;\nvar assert = require(\"../../test/assertions\");\n\nmodule.exports = {\n\n    \"test: fold comments\": function() {\n        var session = new EditSession([\n            '/*',\n            'stuff',\n            '*/'\n        ]);\n        \n        var mode = new JavaScriptMode();\n        session.setFoldStyle(\"markbeginend\");\n        session.setMode(mode);\n        \n        assert.equal(session.getFoldWidget(0), \"start\");\n        assert.equal(session.getFoldWidget(1), \"\");\n        assert.equal(session.getFoldWidget(2), \"end\");\n        \n        assert.range(session.getFoldWidgetRange(0), 0, 2, 2, 0);\n        assert.range(session.getFoldWidgetRange(2), 0, 2, 2, 0);\n    },\n    \n    \"test: fold doc style comments\": function() {\n        var session = new EditSession([\n            '/**',\n            ' * stuff',\n            ' * *** */'\n        ]);\n        \n        var mode = new JavaScriptMode();\n        session.setFoldStyle(\"markbeginend\");\n        session.setMode(mode);\n        \n        assert.equal(session.getFoldWidget(0), \"start\");\n        assert.equal(session.getFoldWidget(1), \"\");\n        assert.equal(session.getFoldWidget(2), \"end\");\n        \n        assert.range(session.getFoldWidgetRange(0), 0, 2, 2, 7);\n        assert.range(session.getFoldWidgetRange(2), 0, 2, 2, 7);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main)\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/folding/fold_mode.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Range = require(\"../../range\").Range;\n\nvar FoldMode = exports.FoldMode = function() {};\n\n(function() {\n\n    this.foldingStartMarker = null;\n    this.foldingStopMarker = null;\n\n    // must return \"\" if there's no fold, to enable caching\n    this.getFoldWidget = function(session, foldStyle, row) {\n        var line = session.getLine(row);\n        if (this.foldingStartMarker.test(line))\n            return \"start\";\n        if (foldStyle == \"markbeginend\"\n                && this.foldingStopMarker\n                && this.foldingStopMarker.test(line))\n            return \"end\";\n        return \"\";\n    };\n    \n    this.getFoldWidgetRange = function(session, foldStyle, row) {\n        return null;\n    };\n\n    this.indentationBlock = function(session, row, column) {\n        var re = /^\\s*/;\n        var startRow = row;\n        var endRow = row;\n        var line = session.getLine(row);\n        var startColumn = column || line.length;\n        var startLevel = line.match(re)[0].length;\n        var maxRow = session.getLength()\n        \n        while (++row < maxRow) {\n            line = session.getLine(row);\n            var level = line.match(re)[0].length;\n\n            if (level == line.length)\n                continue;\n\n            if (level <= startLevel)\n                break;\n\n            endRow = row;\n        }\n\n        if (endRow > startRow) {\n            var endColumn = session.getLine(endRow).length;\n            return new Range(startRow, startColumn, endRow, endColumn);\n        }\n    };\n\n    this.openingBracketBlock = function(session, bracket, row, column) {\n        var start = {row: row, column: column + 1};\n        var end = session.$findClosingBracket(bracket, start);\n        if (!end)\n            return;\n\n        var fw = session.foldWidgets[end.row];\n        if (fw == null)\n            fw = this.getFoldWidget(session, end.row);\n\n        if (fw == \"start\") {\n            end.row --;\n            end.column = session.getLine(end.row).length;\n        }\n        return Range.fromPoints(start, end);\n    };\n\n}).call(FoldMode.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/folding/html.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../../lib/oop\");\nvar MixedFoldMode = require(\"./mixed\").FoldMode;\nvar XmlFoldMode = require(\"./xml\").FoldMode;\nvar CStyleFoldMode = require(\"./cstyle\").FoldMode;\n\nvar FoldMode = exports.FoldMode = function() {\n    MixedFoldMode.call(this, new XmlFoldMode({\n        // void elements\n        \"area\": 1,\n        \"base\": 1,\n        \"br\": 1,\n        \"col\": 1,\n        \"command\": 1,\n        \"embed\": 1,\n        \"hr\": 1,\n        \"img\": 1,\n        \"input\": 1,\n        \"keygen\": 1,\n        \"link\": 1,\n        \"meta\": 1,\n        \"param\": 1,\n        \"source\": 1,\n        \"track\": 1,\n        \"wbr\": 1,\n        \n        // optional tags \n        \"li\": 1,\n        \"dt\": 1,\n        \"dd\": 1,\n        \"p\": 1,\n        \"rt\": 1,\n        \"rp\": 1,\n        \"optgroup\": 1,\n        \"option\": 1,\n        \"colgroup\": 1,\n        \"td\": 1,\n        \"th\": 1\n    }), {\n        \"js-\": new CStyleFoldMode(),\n        \"css-\": new CStyleFoldMode()\n    });\n};\n\noop.inherits(FoldMode, MixedFoldMode);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/folding/html_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\")\n    require(\"amd-loader\");\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar HtmlMode = require(\"../html\").Mode;\nvar EditSession = require(\"../../edit_session\").EditSession;\nvar assert = require(\"../../test/assertions\");\n\nmodule.exports = {\n\n    \"test: fold mixed html and javascript\": function() {\n        var session = new EditSession([\n            '<script type=\"text/javascript\"> ',\n            'function() foo {',\n            '    var bar = 1;',\n            '}',\n            '</script>'\n        ]);\n        \n        var mode = new HtmlMode();\n        session.setMode(mode);\n        session.setFoldStyle(\"markbeginend\");\n        \n        assert.equal(session.getFoldWidget(0), \"start\");\n        assert.equal(session.getFoldWidget(1), \"start\");\n        assert.equal(session.getFoldWidget(2), \"\");\n        assert.equal(session.getFoldWidget(3), \"end\");\n        assert.equal(session.getFoldWidget(4), \"end\");\n        \n        assert.range(session.getFoldWidgetRange(0), 0, 8, 4, 0);\n        assert.range(session.getFoldWidgetRange(4), 0, 8, 4, 0);\n        \n        assert.range(session.getFoldWidgetRange(1), 1, 16, 3, 0);\n        assert.range(session.getFoldWidgetRange(3), 1, 16, 3, 0);\n    },\n    \n    \"test: fold mixed html and css\": function() {\n        var session = new EditSession([\n            '<style type=\"text/css\">',\n            '    .text-layer {',\n            '        font-family: Monaco, \"Courier New\", monospace;',\n            '    }',\n            '</style>'\n        ]);\n        \n        var mode = new HtmlMode();\n        session.setMode(mode);\n        session.setFoldStyle(\"markbeginend\");\n        \n        assert.equal(session.getFoldWidget(0), \"start\");\n        assert.equal(session.getFoldWidget(1), \"start\");\n        assert.equal(session.getFoldWidget(2), \"\");\n        assert.equal(session.getFoldWidget(3), \"end\");\n        assert.equal(session.getFoldWidget(4), \"end\");\n        \n        assert.range(session.getFoldWidgetRange(0), 0, 7, 4, 0);\n        assert.range(session.getFoldWidgetRange(4), 0, 7, 4, 0);\n        \n        assert.range(session.getFoldWidgetRange(1), 1, 17, 3, 4);\n        assert.range(session.getFoldWidgetRange(3), 1, 17, 3, 4);\n    },\n    \n    \"test: fold should skip self closing elements\": function() {\n        var session = new EditSession([\n            '<body>',\n            '<br />',\n            '</body>'\n        ]);\n        \n        var mode = new HtmlMode();\n        session.setMode(mode);\n        session.setFoldStyle(\"markbeginend\");\n        \n        assert.equal(session.getFoldWidget(0), \"start\");\n        assert.equal(session.getFoldWidget(1), \"\");\n        assert.equal(session.getFoldWidget(2), \"end\");\n        \n        assert.range(session.getFoldWidgetRange(0), 0, 6, 2, 0);\n        assert.range(session.getFoldWidgetRange(2), 0, 6, 2, 0);\n    },\n    \n    \"test: fold should skip void elements\": function() {\n        var session = new EditSession([\n            '<body>',\n            '<br>',\n            '</body>'\n        ]);\n        \n        var mode = new HtmlMode();\n        session.setMode(mode);\n        session.setFoldStyle(\"markbeginend\");\n        \n        assert.equal(session.getFoldWidget(0), \"start\");\n        assert.equal(session.getFoldWidget(1), \"\");\n        assert.equal(session.getFoldWidget(2), \"end\");\n        \n        assert.range(session.getFoldWidgetRange(0), 0, 6, 2, 0);\n        assert.range(session.getFoldWidgetRange(2), 0, 6, 2, 0);\n    },\n    \n    \"test: fold multiple unclosed elements\": function() {\n        var session = new EditSession([\n            '<div>',\n            '<p>',\n            'juhu',\n            '<p>',\n            'kinners',\n            '</div>'\n        ]);\n        \n        var mode = new HtmlMode();\n        session.setMode(mode);\n        session.setFoldStyle(\"markbeginend\");\n        \n        assert.equal(session.getFoldWidget(0), \"start\");\n        assert.equal(session.getFoldWidget(1), \"\");\n        assert.equal(session.getFoldWidget(2), \"\");\n        assert.equal(session.getFoldWidget(3), \"\");\n        assert.equal(session.getFoldWidget(4), \"\");\n        assert.equal(session.getFoldWidget(5), \"end\");\n        \n        assert.range(session.getFoldWidgetRange(0), 0, 5, 5, 0);\n        assert.range(session.getFoldWidgetRange(5), 0, 5, 5, 0);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main)\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/folding/mixed.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../../lib/oop\");\nvar BaseFoldMode = require(\"./fold_mode\").FoldMode;\n\nvar FoldMode = exports.FoldMode = function(defaultMode, subModes) {\n    this.defaultMode = defaultMode;\n    this.subModes = subModes;\n};\noop.inherits(FoldMode, BaseFoldMode);\n\n(function() {\n\n\n    this.$getMode = function(state) {\n        for (var key in this.subModes) {\n            if (state.indexOf(key) === 0)\n                return this.subModes[key];\n        }\n        return null;\n    };\n    \n    this.$tryMode = function(state, session, foldStyle, row) {\n        var mode = this.$getMode(state);\n        return (mode ? mode.getFoldWidget(session, foldStyle, row) : \"\");\n    };\n\n    this.getFoldWidget = function(session, foldStyle, row) {\n        return (\n            this.$tryMode(session.getState(row-1), session, foldStyle, row) ||\n            this.$tryMode(session.getState(row), session, foldStyle, row) ||\n            this.defaultMode.getFoldWidget(session, foldStyle, row)\n        );\n    };\n\n    this.getFoldWidgetRange = function(session, foldStyle, row) {\n        var mode = this.$getMode(session.getState(row-1));\n        \n        if (!mode || !mode.getFoldWidget(session, foldStyle, row))\n            mode = this.$getMode(session.getState(row));\n        \n        if (!mode || !mode.getFoldWidget(session, foldStyle, row))\n            mode = this.defaultMode;\n        \n        return mode.getFoldWidgetRange(session, foldStyle, row);\n    };\n\n}).call(FoldMode.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/folding/pythonic.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../../lib/oop\");\nvar BaseFoldMode = require(\"./fold_mode\").FoldMode;\n\nvar FoldMode = exports.FoldMode = function(markers) {\n    this.foldingStartMarker = new RegExp(\"(?:([\\\\[{])|(\" + markers + \"))(?:\\\\s*)(?:#.*)?$\");\n};\noop.inherits(FoldMode, BaseFoldMode);\n\n(function() {\n\n    this.getFoldWidgetRange = function(session, foldStyle, row) {\n        var line = session.getLine(row);\n        var match = line.match(this.foldingStartMarker);\n        if (match) {\n            if (match[1])\n                return this.openingBracketBlock(session, match[1], row, match.index);\n            if (match[2])\n                return this.indentationBlock(session, row, match.index + match[2].length);\n            return this.indentationBlock(session, row);\n        }\n    }\n\n}).call(FoldMode.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/folding/pythonic_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\")\n    require(\"amd-loader\");\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar PythonMode = require(\"../python\").Mode;\nvar EditSession = require(\"../../edit_session\").EditSession;\nvar assert = require(\"../../test/assertions\");\n\nmodule.exports = {\n\n    \"test: bracket folding\": function() {\n        var session = new EditSession([\n            '[  #-',\n            'stuff',\n            ']',\n            '[ ',\n            '{ '\n        ]);\n\n        var mode = new PythonMode();\n        session.setFoldStyle(\"markbeginend\");\n        session.setMode(mode);\n\n        assert.equal(session.getFoldWidget(0), \"start\");\n        assert.equal(session.getFoldWidget(1), \"\");\n        assert.equal(session.getFoldWidget(2), \"\");\n        assert.equal(session.getFoldWidget(3), \"start\");\n        assert.equal(session.getFoldWidget(4), \"start\");\n\n        assert.range(session.getFoldWidgetRange(0), 0, 1, 2, 0);\n        assert.equal(session.getFoldWidgetRange(3), null);\n    },\n\n    \"test: indentation folding\": function() {\n        var session = new EditSession([\n            'def a: #',\n            '',\n            ' b:',\n            '  c',\n            ' ',\n            '  c',\n            '',\n            ' ',\n            ''\n        ]);\n\n        var mode = new PythonMode();\n        session.setFoldStyle(\"markbeginend\");\n        session.setMode(mode);\n\n        assert.equal(session.getFoldWidget(0), \"start\");\n        assert.equal(session.getFoldWidget(1), \"\");\n        assert.equal(session.getFoldWidget(2), \"start\");\n\n        assert.range(session.getFoldWidgetRange(0), 0, 6, 5, 3);\n        assert.range(session.getFoldWidgetRange(2), 2, 3, 5, 3);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main)\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/folding/xml.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../../lib/oop\");\nvar lang = require(\"../../lib/lang\");\nvar Range = require(\"../../range\").Range;\nvar BaseFoldMode = require(\"./fold_mode\").FoldMode;\nvar TokenIterator = require(\"../../token_iterator\").TokenIterator;\n\nvar FoldMode = exports.FoldMode = function(voidElements) {\n    BaseFoldMode.call(this);\n    this.voidElements = voidElements || {};\n};\noop.inherits(FoldMode, BaseFoldMode);\n\n(function() {\n\n    this.getFoldWidget = function(session, foldStyle, row) {\n        var tag = this._getFirstTagInLine(session, row);\n\n        if (tag.closing)\n            return foldStyle == \"markbeginend\" ? \"end\" : \"\";\n\n        if (!tag.tagName || this.voidElements[tag.tagName.toLowerCase()])\n            return \"\";\n\n        if (tag.selfClosing)\n            return \"\";\n\n        if (tag.value.indexOf(\"/\" + tag.tagName) !== -1)\n            return \"\";\n\n        return \"start\";\n    };\n    \n    this._getFirstTagInLine = function(session, row) {\n        var tokens = session.getTokens(row, row)[0].tokens;\n        var value = \"\";\n        for (var i = 0; i < tokens.length; i++) {\n            var token = tokens[i];\n            if (token.type.indexOf(\"meta.tag\") === 0)\n                value += token.value;\n            else\n                value += lang.stringRepeat(\" \", token.value.length);\n        }\n        \n        return this._parseTag(value);\n    };\n\n    this.tagRe = /^(\\s*)(<?(\\/?)([-_a-zA-Z0-9:!]*)\\s*(\\/?)>?)/;\n    this._parseTag = function(tag) {\n        \n        var match = this.tagRe.exec(tag);\n        var column = this.tagRe.lastIndex || 0;\n        this.tagRe.lastIndex = 0;\n\n        return {\n            value: tag,\n            match: match ? match[2] : \"\",\n            closing: match ? !!match[3] : false,\n            selfClosing: match ? !!match[5] || match[2] == \"/>\" : false,\n            tagName: match ? match[4] : \"\",\n            column: match[1] ? column + match[1].length : column\n        };\n    };\n    \n    /**\n     * reads a full tag and places the iterator after the tag\n     */\n    this._readTagForward = function(iterator) {\n        var token = iterator.getCurrentToken();\n        if (!token)\n            return null;\n            \n        var value = \"\";\n        var start;\n        \n        do {\n            if (token.type.indexOf(\"meta.tag\") === 0) {\n                if (!start) {\n                    var start = {\n                        row: iterator.getCurrentTokenRow(),\n                        column: iterator.getCurrentTokenColumn()\n                    };\n                }\n                value += token.value;\n                if (value.indexOf(\">\") !== -1) {\n                    var tag = this._parseTag(value);\n                    tag.start = start;\n                    tag.end = {\n                        row: iterator.getCurrentTokenRow(),\n                        column: iterator.getCurrentTokenColumn() + token.value.length\n                    };\n                    iterator.stepForward();\n                    return tag;\n                }\n            }\n        } while(token = iterator.stepForward());\n        \n        return null;\n    };\n    \n    this._readTagBackward = function(iterator) {\n        var token = iterator.getCurrentToken();\n        if (!token)\n            return null;\n            \n        var value = \"\";\n        var end;\n\n        do {\n            if (token.type.indexOf(\"meta.tag\") === 0) {\n                if (!end) {\n                    end = {\n                        row: iterator.getCurrentTokenRow(),\n                        column: iterator.getCurrentTokenColumn() + token.value.length\n                    };\n                }\n                value = token.value + value;\n                if (value.indexOf(\"<\") !== -1) {\n                    var tag = this._parseTag(value);\n                    tag.end = end;\n                    tag.start = {\n                        row: iterator.getCurrentTokenRow(),\n                        column: iterator.getCurrentTokenColumn()\n                    };\n                    iterator.stepBackward();\n                    return tag;\n                }\n            }\n        } while(token = iterator.stepBackward());\n        \n        return null;\n    };\n    \n    this._pop = function(stack, tag) {\n        while (stack.length) {\n            \n            var top = stack[stack.length-1];\n            if (!tag || top.tagName == tag.tagName) {\n                return stack.pop();\n            }\n            else if (this.voidElements[tag.tagName]) {\n                return;\n            }\n            else if (this.voidElements[top.tagName]) {\n                stack.pop();\n                continue;\n            } else {\n                return null;\n            }\n        }\n    };\n    \n    this.getFoldWidgetRange = function(session, foldStyle, row) {\n        var firstTag = this._getFirstTagInLine(session, row);\n        \n        if (!firstTag.match)\n            return null;\n        \n        var isBackward = firstTag.closing || firstTag.selfClosing;\n        var stack = [];\n        var tag;\n        \n        if (!isBackward) {\n            var iterator = new TokenIterator(session, row, firstTag.column);\n            var start = {\n                row: row,\n                column: firstTag.column + firstTag.tagName.length + 2\n            };\n            while (tag = this._readTagForward(iterator)) {\n                if (tag.selfClosing) {\n                    if (!stack.length) {\n                        tag.start.column += tag.tagName.length + 2;\n                        tag.end.column -= 2;\n                        return Range.fromPoints(tag.start, tag.end);\n                    } else\n                        continue;\n                }\n                \n                if (tag.closing) {\n                    this._pop(stack, tag);\n                    if (stack.length == 0)\n                        return Range.fromPoints(start, tag.start);\n                }\n                else {\n                    stack.push(tag)\n                }\n            }\n        }\n        else {\n            var iterator = new TokenIterator(session, row, firstTag.column + firstTag.match.length);\n            var end = {\n                row: row,\n                column: firstTag.column\n            };\n            \n            while (tag = this._readTagBackward(iterator)) {\n                if (tag.selfClosing) {\n                    if (!stack.length) {\n                        tag.start.column += tag.tagName.length + 2;\n                        tag.end.column -= 2;\n                        return Range.fromPoints(tag.start, tag.end);\n                    } else\n                        continue;\n                }\n                \n                if (!tag.closing) {\n                    this._pop(stack, tag);\n                    if (stack.length == 0) {\n                        tag.start.column += tag.tagName.length + 2;\n                        return Range.fromPoints(tag.start, end);\n                    }\n                }\n                else {\n                    stack.push(tag)\n                }\n            }\n        }\n        \n    };\n\n}).call(FoldMode.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/folding/xml_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\")\n    require(\"amd-loader\");\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar XmlMode = require(\"../xml\").Mode;\nvar EditSession = require(\"../../edit_session\").EditSession;\nvar assert = require(\"../../test/assertions\");\n\nmodule.exports = {\n\n    \"test: fold multi line self closing element\": function() {\n        var session = new EditSession([\n            '<person',\n            '  firstname=\"fabian\"',\n            '  lastname=\"jakobs\"/>'\n        ]);\n        \n        var mode = new XmlMode();\n        session.setFoldStyle(\"markbeginend\");\n        session.setMode(mode);\n        \n        assert.equal(session.getFoldWidget(0), \"start\");\n        assert.equal(session.getFoldWidget(1), \"\");\n        assert.equal(session.getFoldWidget(2), \"end\");\n        \n        assert.range(session.getFoldWidgetRange(0), 0, 8, 2, 19);\n        assert.range(session.getFoldWidgetRange(2), 0, 8, 2, 19);\n    },\n    \n    \"test: fold should skip self closing elements\": function() {\n        var session = new EditSession([\n            '<person>',\n            '  <attrib value=\"fabian\"/>',\n            '</person>'\n        ]);\n        \n        var mode = new XmlMode();\n        session.setFoldStyle(\"markbeginend\");\n        session.setMode(mode);\n        \n        assert.equal(session.getFoldWidget(0), \"start\");\n        assert.equal(session.getFoldWidget(1), \"\");\n        assert.equal(session.getFoldWidget(2), \"end\");\n        \n        assert.range(session.getFoldWidgetRange(0), 0, 8, 2, 0);\n        assert.range(session.getFoldWidgetRange(2), 0, 8, 2, 0);\n    },\n    \n    \"test: fold should skip multi line self closing elements\": function() {\n        var session = new EditSession([\n            '<person>',\n            '  <attib',\n            '     key=\"name\"',\n            '     value=\"fabian\"/>',\n            '</person>'\n        ]);\n        \n        var mode = new XmlMode();\n        session.setMode(mode);\n        session.setFoldStyle(\"markbeginend\");\n        \n        assert.equal(session.getFoldWidget(0), \"start\");\n        assert.equal(session.getFoldWidget(1), \"start\");\n        assert.equal(session.getFoldWidget(2), \"\");\n        assert.equal(session.getFoldWidget(3), \"end\");\n        assert.equal(session.getFoldWidget(4), \"end\");\n        \n        assert.range(session.getFoldWidgetRange(0), 0, 8, 4, 0);\n        assert.range(session.getFoldWidgetRange(1), 1, 9, 3, 19);\n        assert.range(session.getFoldWidgetRange(3), 1, 9, 3, 19);\n        assert.range(session.getFoldWidgetRange(4), 0, 8, 4, 0);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main)\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/golang.js",
    "content": "define(function(require, exports, module) {\n\n    var oop = require(\"../lib/oop\");\n    var TextMode = require(\"./text\").Mode;\n    var Tokenizer = require(\"../tokenizer\").Tokenizer;\n    var GolangHighlightRules = require(\"./golang_highlight_rules\").GolangHighlightRules;\n    var MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\n    \n    var Mode = function() {\n        this.$tokenizer = new Tokenizer(new GolangHighlightRules().getRules());\n        this.$outdent = new MatchingBraceOutdent();\n    };\n    oop.inherits(Mode, TextMode);\n    \n    (function() {\n        \n        this.toggleCommentLines = function(state, doc, startRow, endRow) {\n            var outdent = true;\n            var outentedRows = [];\n            var re = /^(\\s*)\\/\\//;\n\n            for (var i=startRow; i<= endRow; i++) {\n                if (!re.test(doc.getLine(i))) {\n                    outdent = false;\n                    break;\n                }\n            }\n\n            if (outdent) {\n                var deleteRange = new Range(0, 0, 0, 0);\n                for (var i=startRow; i<= endRow; i++)\n                {\n                    var line = doc.getLine(i);\n                    var m = line.match(re);\n                    deleteRange.start.row = i;\n                    deleteRange.end.row = i;\n                    deleteRange.end.column = m[0].length;\n                    doc.replace(deleteRange, m[1]);\n                }\n            }\n            else {\n                doc.indentRows(startRow, endRow, \"//\");\n            }\n        };\n\n        this.getNextLineIndent = function(state, line, tab) {\n            var indent = this.$getIndent(line);\n\n            var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n            var tokens = tokenizedLine.tokens;\n            var endState = tokenizedLine.state;\n\n            if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n                return indent;\n            }\n            \n            if (state == \"start\") {\n                var match = line.match(/^.*[\\{\\(\\[]\\s*$/);\n                if (match) {\n                    indent += tab;\n                }\n            }\n\n            return indent;\n        };//end getNextLineIndent\n\n        this.checkOutdent = function(state, line, input) {\n            return this.$outdent.checkOutdent(line, input);\n        };\n\n        this.autoOutdent = function(state, doc, row) {\n            this.$outdent.autoOutdent(doc, row);\n        };\n\n    }).call(Mode.prototype);\n\n    exports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/golang_highlight_rules.js",
    "content": "define(function(require, exports, module) {\n    var oop = require(\"../lib/oop\");\n    var lang = require(\"../lib/lang\");\n    var DocCommentHighlightRules = require(\"./doc_comment_highlight_rules\").DocCommentHighlightRules;\n    var TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\n    var GolangHighlightRules = function() {\n        var keywords = lang.arrayToMap(\n            (\"true|else|false|break|case|return|goto|if|const|\" +\n             \"continue|struct|default|switch|for|\" +\n             \"func|import|package|chan|defer|fallthrough|go|interface|map|range\" +\n             \"select|type|var\").split(\"|\")\n        );\n\n        var buildinConstants = lang.arrayToMap(\n            (\"nit|true|false|iota\").split(\"|\")\n        );\n\n        this.$rules = {\n            \"start\" : [\n                {\n                    token : \"comment\",\n                    regex : \"\\\\/\\\\/.*$\"\n                },\n                DocCommentHighlightRules.getStartRule(\"doc-start\"),\n                {\n                    token : \"comment\", // multi line comment\n                    merge : true,\n                    regex : \"\\\\/\\\\*\",\n                    next : \"comment\"\n                }, {\n                    token : \"string\", // single line\n                    regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n                }, {\n                    token : \"string\", // multi line string start\n                    merge : true,\n                    regex : '[\"].*\\\\\\\\$',\n                    next : \"qqstring\"\n                }, {\n                    token : \"string\", // single line\n                    regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n                }, {\n                    token : \"string\", // multi line string start\n                    merge : true,\n                    regex : \"['].*\\\\\\\\$\",\n                    next : \"qstring\"\n                }, {\n                    token : \"constant.numeric\", // hex\n                    regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n                }, {\n                    token : \"constant.numeric\", // float\n                    regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n                }, {\n                    token : \"constant\", // <CONSTANT>\n                    regex : \"<[a-zA-Z0-9.]+>\"\n                }, {\n                    token : \"keyword\", // pre-compiler directivs\n                    regex : \"(?:#include|#pragma|#line|#define|#undef|#ifdef|#else|#elif|#endif|#ifndef)\"\n                }, {\n                    token : function(value) {\n                        if (value == \"this\")\n                            return \"variable.language\";\n                        else if (keywords.hasOwnProperty(value))\n                            return \"keyword\";\n                        else if (buildinConstants.hasOwnProperty(value))\n                            return \"constant.language\";\n                        else\n                            return \"identifier\";\n                    },\n                    regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n                }, {\n                    token : \"keyword.operator\",\n                    regex : \"!|\\\\$|%|&|\\\\*|\\\\-\\\\-|\\\\-|\\\\+\\\\+|\\\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\\\|\\\\||\\\\?\\\\:|\\\\*=|%=|\\\\+=|\\\\-=|&=|\\\\^=|\\\\b(?:in|new|delete|typeof|void)\"\n                }, {\n                    token : \"punctuation.operator\",\n                    regex : \"\\\\?|\\\\:|\\\\,|\\\\;|\\\\.\"\n                }, {\n                    token : \"paren.lparen\",\n                    regex : \"[[({]\"\n                }, {\n                    token : \"paren.rparen\",\n                    regex : \"[\\\\])}]\"\n                }, {\n                    token : \"text\",\n                    regex : \"\\\\s+\"\n                }\n            ],\n            \"comment\" : [\n                {\n                    token : \"comment\", // closing comment\n                    regex : \".*?\\\\*\\\\/\",\n                    next : \"start\"\n                }, {\n                    token : \"comment\", // comment spanning whole line\n                    merge : true,\n                    regex : \".+\"\n                }\n            ],\n            \"qqstring\" : [\n                {\n                    token : \"string\",\n                    regex : '(?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?\"',\n                    next : \"start\"\n                }, {\n                    token : \"string\",\n                    merge : true,\n                    regex : '.+'\n                }\n            ],\n            \"qstring\" : [\n                {\n                    token : \"string\",\n                    regex : \"(?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?'\",\n                    next : \"start\"\n                }, {\n                    token : \"string\",\n                    merge : true,\n                    regex : '.+'\n                }\n            ]\n        };\n    }\n    oop.inherits(GolangHighlightRules, TextHighlightRules);\n\n    exports.GolangHighlightRules = GolangHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/groovy.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar JavaScriptMode = require(\"./javascript\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar GroovyHighlightRules = require(\"./groovy_highlight_rules\").GroovyHighlightRules;\n\nvar Mode = function() {\n    JavaScriptMode.call(this);\n    this.$tokenizer = new Tokenizer(new GroovyHighlightRules().getRules());\n};\noop.inherits(Mode, JavaScriptMode);\n\n(function() {\n\n    this.createWorker = function(session) {\n        return null;\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/groovy_highlight_rules.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar DocCommentHighlightRules = require(\"./doc_comment_highlight_rules\").DocCommentHighlightRules;\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar GroovyHighlightRules = function() {\n\n    var keywords = lang.arrayToMap(\n    (\"assert|with|abstract|continue|for|new|switch|\" +\n    \"assert|default|goto|package|synchronized|\" +\n    \"boolean|do|if|private|this|\" +\n    \"break|double|implements|protected|throw|\" +\n    \"byte|else|import|public|throws|\" +\n    \"case|enum|instanceof|return|transient|\" +\n    \"catch|extends|int|short|try|\" +\n    \"char|final|interface|static|void|\" +\n    \"class|finally|long|strictfp|volatile|\" +\n    \"def|float|native|super|while\").split(\"|\")\n    );\n\n    var buildinConstants = lang.arrayToMap(\n        (\"null|Infinity|NaN|undefined\").split(\"|\")\n    );\n\n    var langClasses = lang.arrayToMap(\n        (\"AbstractMethodError|AssertionError|ClassCircularityError|\"+\n        \"ClassFormatError|Deprecated|EnumConstantNotPresentException|\"+\n        \"ExceptionInInitializerError|IllegalAccessError|\"+\n        \"IllegalThreadStateException|InstantiationError|InternalError|\"+\n        \"NegativeArraySizeException|NoSuchFieldError|Override|Process|\"+\n        \"ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|\"+\n        \"SuppressWarnings|TypeNotPresentException|UnknownError|\"+\n        \"UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|\"+\n        \"InstantiationException|IndexOutOfBoundsException|\"+\n        \"ArrayIndexOutOfBoundsException|CloneNotSupportedException|\"+\n        \"NoSuchFieldException|IllegalArgumentException|NumberFormatException|\"+\n        \"SecurityException|Void|InheritableThreadLocal|IllegalStateException|\"+\n        \"InterruptedException|NoSuchMethodException|IllegalAccessException|\"+\n        \"UnsupportedOperationException|Enum|StrictMath|Package|Compiler|\"+\n        \"Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|\"+\n        \"NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|\"+\n        \"NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|\"+\n        \"Character|Boolean|StackTraceElement|Appendable|StringBuffer|\"+\n        \"Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|\"+\n        \"StackOverflowError|OutOfMemoryError|VirtualMachineError|\"+\n        \"ArrayStoreException|ClassCastException|LinkageError|\"+\n        \"NoClassDefFoundError|ClassNotFoundException|RuntimeException|\"+\n        \"Exception|ThreadDeath|Error|Throwable|System|ClassLoader|\"+\n        \"Cloneable|Class|CharSequence|Comparable|String|Object\").split(\"|\")\n    );\n    \n    var importClasses = lang.arrayToMap(\n        (\"\").split(\"|\")\n    );\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \"\\\\/\\\\/.*$\"\n            },\n            DocCommentHighlightRules.getStartRule(\"doc-start\"),\n            {\n                token : \"comment\", // multi line comment\n                merge : true,\n                regex : \"\\\\/\\\\*\",\n                next : \"comment\"\n            }, {\n                token : \"string.regexp\",\n                regex : \"[/](?:(?:\\\\[(?:\\\\\\\\]|[^\\\\]])+\\\\])|(?:\\\\\\\\/|[^\\\\]/]))*[/]\\\\w*\\\\s*(?=[).,;]|$)\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n                token : \"constant.language.boolean\",\n                regex : \"(?:true|false)\\\\b\"\n            }, {\n                token : function(value) {\n                    if (value == \"this\")\n                        return \"variable.language\";\n                    else if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (langClasses.hasOwnProperty(value))\n                        return \"support.function\";\n                    else if (importClasses.hasOwnProperty(value))\n                        return \"support.function\";\n                    else if (buildinConstants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else\n                        return \"identifier\";\n                },\n                // TODO: Unicode escape sequences\n                // TODO: Unicode identifiers\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"\\\\?:|\\\\?\\\\.|\\\\*\\\\.|<=>|=~|==~|\\\\.@|\\\\*\\\\.@|\\\\.&|as|in|is|!|\\\\$|%|&|\\\\*|\\\\-\\\\-|\\\\-|\\\\+\\\\+|\\\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\\\|\\\\||\\\\?\\\\:|\\\\*=|%=|\\\\+=|\\\\-=|&=|\\\\^=|\\\\b(?:in|instanceof|new|delete|typeof|void)\"\n            }, {\n                token : \"lparen\",\n                regex : \"[[({]\"\n            }, {\n                token : \"rparen\",\n                regex : \"[\\\\])}]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ]\n    };\n    \n    this.embedRules(DocCommentHighlightRules, \"doc-\",\n        [ DocCommentHighlightRules.getEndRule(\"start\") ]);\n};\n\noop.inherits(GroovyHighlightRules, TextHighlightRules);\n\nexports.GroovyHighlightRules = GroovyHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/haxe.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar HaxeHighlightRules = require(\"./haxe_highlight_rules\").HaxeHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar CstyleBehaviour = require(\"./behaviour/cstyle\").CstyleBehaviour;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new HaxeHighlightRules().getRules());\n    this.$outdent = new MatchingBraceOutdent();\n    this.$behaviour = new CstyleBehaviour();\n    this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n      this.getNextLineIndent = function(state, line, tab) {\n          var indent = this.$getIndent(line);\n\n          var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n          var tokens = tokenizedLine.tokens;\n\n          if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n              return indent;\n          }\n\n          if (state == \"start\") {\n              var match = line.match(/^.*[\\{\\(\\[]\\s*$/);\n              if (match) {\n                  indent += tab;\n              }\n          }\n\n          return indent;\n      };\n\n      this.checkOutdent = function(state, line, input) {\n          return this.$outdent.checkOutdent(line, input);\n      };\n\n      this.autoOutdent = function(state, doc, row) {\n          this.$outdent.autoOutdent(doc, row);\n      };\n\n\n    this.createWorker = function(session) {\n        return null;\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/haxe_highlight_rules.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar DocCommentHighlightRules = require(\"./doc_comment_highlight_rules\").DocCommentHighlightRules;\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar HaxeHighlightRules = function() {\n\n    var keywords = lang.arrayToMap(\n        (\"break|case|cast|catch|class|continue|default|else|enum|extends|for|function|if|implements|import|in|inline|interface|new|override|package|private|public|return|static|super|switch|this|throw|trace|try|typedef|untyped|var|while|Array|Void|Bool|Int|UInt|Float|Dynamic|String|List|Hash|IntHash|Error|Unknown|Type|Std\").split(\"|\")\n    );\n\n    var buildinConstants = lang.arrayToMap(\n        (\"null|true|false\").split(\"|\")\n    );\n\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \"\\\\/\\\\/.*$\"\n            },\n            DocCommentHighlightRules.getStartRule(\"doc-start\"),\n            {\n                token : \"comment\", // multi line comment\n                regex : \"\\\\/\\\\*\",\n                merge : true,\n                next : \"comment\"\n            }, {\n                token : \"string.regexp\",\n                regex : \"[/](?:(?:\\\\[(?:\\\\\\\\]|[^\\\\]])+\\\\])|(?:\\\\\\\\/|[^\\\\]/]))*[/]\\\\w*\\\\s*(?=[).,;]|$)\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n                token : \"constant.language.boolean\",\n                regex : \"(?:true|false)\\\\b\"\n            }, {\n                token : function(value) {\n                    if (value == \"this\")\n                        return \"variable.language\";\n                    else if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (buildinConstants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else\n                        return \"identifier\";\n                },\n                // TODO: Unicode escape sequences\n                // TODO: Unicode identifiers\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"!|\\\\$|%|&|\\\\*|\\\\-\\\\-|\\\\-|\\\\+\\\\+|\\\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\\\|\\\\||\\\\?\\\\:|\\\\*=|%=|\\\\+=|\\\\-=|&=|\\\\^=|\\\\b(?:in|instanceof|new|delete|typeof|void)\"\n            }, {\n                token : \"punctuation.operator\",\n                regex : \"\\\\?|\\\\:|\\\\,|\\\\;|\\\\.\"\n            }, {\n                token : \"paren.lparen\",\n                regex : \"[[({<]\"\n            }, {\n                token : \"paren.rparen\",\n                regex : \"[\\\\])}>]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ]\n    };\n\n    this.embedRules(DocCommentHighlightRules, \"doc-\",\n        [ DocCommentHighlightRules.getEndRule(\"start\") ]);\n};\n\noop.inherits(HaxeHighlightRules, TextHighlightRules);\n\nexports.HaxeHighlightRules = HaxeHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/html.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar JavaScriptMode = require(\"./javascript\").Mode;\nvar CssMode = require(\"./css\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar HtmlHighlightRules = require(\"./html_highlight_rules\").HtmlHighlightRules;\nvar XmlBehaviour = require(\"./behaviour/xml\").XmlBehaviour;\nvar HtmlFoldMode = require(\"./folding/html\").FoldMode;\n\nvar Mode = function() {\n    var highlighter = new HtmlHighlightRules();\n    this.$tokenizer = new Tokenizer(highlighter.getRules());\n    this.$behaviour = new XmlBehaviour();\n    \n    this.$embeds = highlighter.getEmbeds();\n    this.createModeDelegates({\n        \"js-\": JavaScriptMode,\n        \"css-\": CssMode\n    });\n    \n    this.foldingRules = new HtmlFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    \n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        return 0;\n    };\n\n    this.getNextLineIndent = function(state, line, tab) {\n        return this.$getIndent(line);\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return false;\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/html_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar CssHighlightRules = require(\"./css_highlight_rules\").CssHighlightRules;\nvar JavaScriptHighlightRules = require(\"./javascript_highlight_rules\").JavaScriptHighlightRules;\nvar xmlUtil = require(\"./xml_util\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar HtmlHighlightRules = function() {\n\n    // regexp must not have capturing parentheses\n    // regexps are ordered -> the first match is used\n    this.$rules = {\n        start : [{\n            token : \"text\",\n            merge : true,\n            regex : \"<\\\\!\\\\[CDATA\\\\[\",\n            next : \"cdata\"\n        }, {\n            token : \"xml_pe\",\n            regex : \"<\\\\?.*?\\\\?>\"\n        }, {\n            token : \"comment\",\n            merge : true,\n            regex : \"<\\\\!--\",\n            next : \"comment\"\n        }, {\n            token : \"xml_pe\",\n            regex : \"<\\\\!.*?>\"\n        }, {\n            token : \"meta.tag\",\n            regex : \"<(?=\\s*script\\\\b)\",\n            next : \"script\"\n        }, {\n            token : \"meta.tag\",\n            regex : \"<(?=\\s*style\\\\b)\",\n            next : \"style\"\n        }, {\n            token : \"meta.tag\", // opening tag\n            regex : \"<\\\\/?\",\n            next : \"tag\"\n        }, {\n            token : \"text\",\n            regex : \"\\\\s+\"\n        }, {\n            token : \"constant.character.entity\",\n            regex : \"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\\\.-]+;)\"\n        }, {\n            token : \"text\",\n            regex : \"[^<]+\"\n        } ],\n    \n        cdata : [ {\n            token : \"text\",\n            regex : \"\\\\]\\\\]>\",\n            next : \"start\"\n        }, {\n            token : \"text\",\n            merge : true,\n            regex : \"\\\\s+\"\n        }, {\n            token : \"text\",\n            merge : true,\n            regex : \".+\"\n        } ],\n\n        comment : [ {\n            token : \"comment\",\n            regex : \".*?-->\",\n            next : \"start\"\n        }, {\n            token : \"comment\",\n            merge : true,\n            regex : \".+\"\n        } ]\n    };\n    \n    xmlUtil.tag(this.$rules, \"tag\", \"start\");\n    xmlUtil.tag(this.$rules, \"style\", \"css-start\");\n    xmlUtil.tag(this.$rules, \"script\", \"js-start\");\n    \n    this.embedRules(JavaScriptHighlightRules, \"js-\", [{\n        token: \"comment\",\n        regex: \"\\\\/\\\\/.*(?=<\\\\/script>)\",\n        next: \"tag\"\n    }, {\n        token: \"meta.tag\",\n        regex: \"<\\\\/(?=script)\",\n        next: \"tag\"\n    }]);\n    \n    this.embedRules(CssHighlightRules, \"css-\", [{\n        token: \"meta.tag\",\n        regex: \"<\\\\/(?=style)\",\n        next: \"tag\"\n    }]);\n};\n\noop.inherits(HtmlHighlightRules, TextHighlightRules);\n\nexports.HtmlHighlightRules = HtmlHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/html_highlight_rules_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar HtmlMode = require(\"./html\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n    setUp : function() {\n        this.tokenizer = new HtmlMode().getTokenizer();\n    },\n\n    \"test: tokenize embedded script\" : function() {\n        var line = \"<script a='a'>var</script>'123'\";\n        var tokens = this.tokenizer.getLineTokens(line, \"start\").tokens;\n\n        assert.equal(12, tokens.length);\n        assert.equal(\"meta.tag\", tokens[0].type);\n        assert.equal(\"meta.tag.script\", tokens[1].type);\n        assert.equal(\"text\", tokens[2].type);\n        assert.equal(\"entity.other.attribute-name\", tokens[3].type);\n        assert.equal(\"keyword.operator\", tokens[4].type);\n        assert.equal(\"string\", tokens[5].type);\n        assert.equal(\"meta.tag\", tokens[6].type);\n        assert.equal(\"storage.type\", tokens[7].type);\n        assert.equal(\"meta.tag\", tokens[8].type);\n        assert.equal(\"meta.tag.script\", tokens[9].type);\n        assert.equal(\"meta.tag\", tokens[10].type);\n        assert.equal(\"text\", tokens[11].type);\n    },\n    \n    \"test: tokenize multiline attribute value with double quotes\": function() {\n        var line1 = this.tokenizer.getLineTokens('<a href=\"abc', \"start\");\n        var t1 = line1.tokens;\n        var t2 = this.tokenizer.getLineTokens('def\">', line1.state).tokens;\n        assert.equal(t1[t1.length-1].type, \"string\");\n        assert.equal(t2[0].type, \"string\");\n    },\n    \n    \"test: tokenize multiline attribute value with single quotes\": function() {\n        var line1 = this.tokenizer.getLineTokens(\"<a href='abc\", \"start\");\n        var t1 = line1.tokens;\n        var t2 = this.tokenizer.getLineTokens('def\\'>', line1.state).tokens;\n        assert.equal(t1[t1.length-1].type, \"string\");\n        assert.equal(t2[0].type, \"string\");\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/html_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"../edit_session\").EditSession;\nvar Range = require(\"../range\").Range;\nvar HtmlMode = require(\"./html\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n    setUp : function() {    \n        this.mode = new HtmlMode();\n    },\n\n    \"test: toggle comment lines should not do anything\" : function() {\n        var session = new EditSession([\"  abc\", \"cde\", \"fg\"]);\n\n        var range = new Range(0, 3, 1, 1);\n        var comment = this.mode.toggleCommentLines(\"start\", session, 0, 1);\n        assert.equal([\"  abc\", \"cde\", \"fg\"].join(\"\\n\"), session.toString());\n    },\n\n    \"test: next line indent should be the same as the current line indent\" : function() {\n        assert.equal(\"     \", this.mode.getNextLineIndent(\"start\", \"     abc\"));\n        assert.equal(\"\", this.mode.getNextLineIndent(\"start\", \"abc\"));\n        assert.equal(\"\\t\", this.mode.getNextLineIndent(\"start\", \"\\tabc\"));\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/java.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar JavaScriptMode = require(\"./javascript\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar JavaHighlightRules = require(\"./java_highlight_rules\").JavaHighlightRules;\n\nvar Mode = function() {\n    JavaScriptMode.call(this);\n    \n    this.$tokenizer = new Tokenizer(new JavaHighlightRules().getRules());\n};\noop.inherits(Mode, JavaScriptMode);\n\n(function() {\n    \n    this.createWorker = function(session) {\n        return null;\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/java_highlight_rules.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar DocCommentHighlightRules = require(\"./doc_comment_highlight_rules\").DocCommentHighlightRules;\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar JavaHighlightRules = function() {\n\n    // taken from http://download.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html\n    var keywords = lang.arrayToMap(\n    (\"abstract|continue|for|new|switch|\" +\n    \"assert|default|goto|package|synchronized|\" +\n    \"boolean|do|if|private|this|\" +\n    \"break|double|implements|protected|throw|\" +\n    \"byte|else|import|public|throws|\" +\n    \"case|enum|instanceof|return|transient|\" +\n    \"catch|extends|int|short|try|\" +\n    \"char|final|interface|static|void|\" +\n    \"class|finally|long|strictfp|volatile|\" +\n    \"const|float|native|super|while\").split(\"|\")\n    );\n\n    var buildinConstants = lang.arrayToMap(\n        (\"null|Infinity|NaN|undefined\").split(\"|\")\n    );\n\n    var langClasses = lang.arrayToMap(\n        (\"AbstractMethodError|AssertionError|ClassCircularityError|\"+\n        \"ClassFormatError|Deprecated|EnumConstantNotPresentException|\"+\n        \"ExceptionInInitializerError|IllegalAccessError|\"+\n        \"IllegalThreadStateException|InstantiationError|InternalError|\"+\n        \"NegativeArraySizeException|NoSuchFieldError|Override|Process|\"+\n        \"ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|\"+\n        \"SuppressWarnings|TypeNotPresentException|UnknownError|\"+\n        \"UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|\"+\n        \"InstantiationException|IndexOutOfBoundsException|\"+\n        \"ArrayIndexOutOfBoundsException|CloneNotSupportedException|\"+\n        \"NoSuchFieldException|IllegalArgumentException|NumberFormatException|\"+\n        \"SecurityException|Void|InheritableThreadLocal|IllegalStateException|\"+\n        \"InterruptedException|NoSuchMethodException|IllegalAccessException|\"+\n        \"UnsupportedOperationException|Enum|StrictMath|Package|Compiler|\"+\n        \"Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|\"+\n        \"NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|\"+\n        \"NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|\"+\n        \"Character|Boolean|StackTraceElement|Appendable|StringBuffer|\"+\n        \"Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|\"+\n        \"StackOverflowError|OutOfMemoryError|VirtualMachineError|\"+\n        \"ArrayStoreException|ClassCastException|LinkageError|\"+\n        \"NoClassDefFoundError|ClassNotFoundException|RuntimeException|\"+\n        \"Exception|ThreadDeath|Error|Throwable|System|ClassLoader|\"+\n        \"Cloneable|Class|CharSequence|Comparable|String|Object\").split(\"|\")\n    );\n    \n    var importClasses = lang.arrayToMap(\n        (\"\").split(\"|\")\n    );\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \"\\\\/\\\\/.*$\"\n            },\n            DocCommentHighlightRules.getStartRule(\"doc-start\"),\n            {\n                token : \"comment\", // multi line comment\n                merge : true,\n                regex : \"\\\\/\\\\*\",\n                next : \"comment\"\n            }, {\n                token : \"string.regexp\",\n                regex : \"[/](?:(?:\\\\[(?:\\\\\\\\]|[^\\\\]])+\\\\])|(?:\\\\\\\\/|[^\\\\]/]))*[/]\\\\w*\\\\s*(?=[).,;]|$)\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n                token : \"constant.language.boolean\",\n                regex : \"(?:true|false)\\\\b\"\n            }, {\n                token : function(value) {\n                    if (value == \"this\")\n                        return \"variable.language\";\n                    else if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (langClasses.hasOwnProperty(value))\n                        return \"support.function\";\n                    else if (importClasses.hasOwnProperty(value))\n                        return \"support.function\";\n                    else if (buildinConstants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else\n                        return \"identifier\";\n                },\n                // TODO: Unicode escape sequences\n                // TODO: Unicode identifiers\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"!|\\\\$|%|&|\\\\*|\\\\-\\\\-|\\\\-|\\\\+\\\\+|\\\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\\\|\\\\||\\\\?\\\\:|\\\\*=|%=|\\\\+=|\\\\-=|&=|\\\\^=|\\\\b(?:in|instanceof|new|delete|typeof|void)\"\n            }, {\n                token : \"lparen\",\n                regex : \"[[({]\"\n            }, {\n                token : \"rparen\",\n                regex : \"[\\\\])}]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ]\n    };\n    \n    this.embedRules(DocCommentHighlightRules, \"doc-\",\n        [ DocCommentHighlightRules.getEndRule(\"start\") ]);\n};\n\noop.inherits(JavaHighlightRules, TextHighlightRules);\n\nexports.JavaHighlightRules = JavaHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/javascript.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar JavaScriptHighlightRules = require(\"./javascript_highlight_rules\").JavaScriptHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar Range = require(\"../range\").Range;\nvar WorkerClient = require(\"../worker/worker_client\").WorkerClient;\nvar CstyleBehaviour = require(\"./behaviour/cstyle\").CstyleBehaviour;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new JavaScriptHighlightRules().getRules());\n    this.$outdent = new MatchingBraceOutdent();\n    this.$behaviour = new CstyleBehaviour();\n    this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        var outdent = true;\n        var re = /^(\\s*)\\/\\//;\n\n        for (var i=startRow; i<= endRow; i++) {\n            if (!re.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        if (outdent) {\n            var deleteRange = new Range(0, 0, 0, 0);\n            for (var i=startRow; i<= endRow; i++)\n            {\n                var line = doc.getLine(i);\n                var m = line.match(re);\n                deleteRange.start.row = i;\n                deleteRange.end.row = i;\n                deleteRange.end.column = m[0].length;\n                doc.replace(deleteRange, m[1]);\n            }\n        }\n        else {\n            doc.indentRows(startRow, endRow, \"//\");\n        }\n    };\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n        var endState = tokenizedLine.state;\n\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n        \n        if (state == \"start\" || state == \"regex_allowed\") {\n            var match = line.match(/^.*(?:\\bcase\\b.*\\:|[\\{\\(\\[])\\s*$/);\n            if (match) {\n                indent += tab;\n            }\n        } else if (state == \"doc-start\") {\n            if (endState == \"start\" || state == \"regex_allowed\") {\n                return \"\";\n            }\n            var match = line.match(/^\\s*(\\/?)\\*/);\n            if (match) {\n                if (match[1]) {\n                    indent += \" \";\n                }\n                indent += \"* \";\n            }\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n    \n    this.createWorker = function(session) {\n        var worker = new WorkerClient([\"ace\"], \"worker-javascript.js\", \"ace/mode/javascript_worker\", \"JavaScriptWorker\");\n        worker.attachToDocument(session.getDocument());\n            \n        worker.on(\"jslint\", function(results) {\n            var errors = [];\n            for (var i=0; i<results.data.length; i++) {\n                var error = results.data[i];\n                if (error)\n                    errors.push({\n                        row: error.line-1,\n                        column: error.character-1,\n                        text: error.reason,\n                        type: \"warning\",\n                        lint: error\n                    });\n            }\n            session.setAnnotations(errors);\n        });\n        \n        worker.on(\"narcissus\", function(e) {\n            session.setAnnotations([e.data]);\n        });\n        \n        worker.on(\"terminate\", function() {\n            session.clearAnnotations();\n        });\n        \n        return worker;\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/javascript_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Mihai Sucan <mihai DOT sucan AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar unicode = require(\"../unicode\");\nvar DocCommentHighlightRules = require(\"./doc_comment_highlight_rules\").DocCommentHighlightRules;\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar JavaScriptHighlightRules = function() {\n\n    // see: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects\n    var globals = lang.arrayToMap(\n      // Constructors\n        (\"Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|\" +\n      // E4X\n         \"Namespace|QName|XML|XMLList|\" +\n         \"ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|\" +\n         \"Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|\" +\n      // Errors\n        \"Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|\" +\n        \"SyntaxError|TypeError|URIError|\" +\n      //  Non-constructor functions\n        \"decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|\" +\n        \"isNaN|parseFloat|parseInt|\" +\n      // Other\n        \"JSON|Math|\" +\n      // Pseudo\n        \"this|arguments|prototype|window|document\"\n      ).split(\"|\")\n    );\n\n    var keywords = lang.arrayToMap(\n        (\"break|case|catch|continue|default|delete|do|else|finally|for|function|\" +\n        \"if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|\" +\n        \"const|yield|import|get|set\").split(\"|\")\n    );\n\n    // keywords which can be followed by regular expressions\n    var kwBeforeRe = \"case|do|else|finally|in|instanceof|return|throw|try|typeof|yield\";\n\n    var deprecated = lang.arrayToMap(\n        (\"__parent__|__count__|escape|unescape|with|__proto__\").split(\"|\")\n    );\n\n    var definitions = lang.arrayToMap((\"const|let|var|function\").split(\"|\"));\n\n    var buildinConstants = lang.arrayToMap(\n        (\"null|Infinity|NaN|undefined\").split(\"|\")\n    );\n\n    var futureReserved = lang.arrayToMap(\n        (\"class|enum|extends|super|export|implements|private|\" +\n        \"public|interface|package|protected|static\").split(\"|\")\n    );\n\n    // TODO: Unicode escape sequences\n    var identifierRe = \"[\" + unicode.packages.L + \"\\\\$_][\"\n        + unicode.packages.L\n        + unicode.packages.Mn + unicode.packages.Mc\n        + unicode.packages.Nd\n        + unicode.packages.Pc + \"\\\\$_]*\\\\b\";\n\n    var escapedRe = \"\\\\\\\\(?:x[0-9a-fA-F]{2}|\" + // hex\n        \"u[0-9a-fA-F]{4}|\" + // unicode\n        \"[0-2][0-7]{0,2}|\" + // oct\n        \"3[0-6][0-7]?|\" + // oct\n        \"37[0-7]?|\" + // oct\n        \"[4-7][0-7]?|\" + //oct\n        \".)\";\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : /\\/\\/.*$/\n            },\n            DocCommentHighlightRules.getStartRule(\"doc-start\"),\n            {\n                token : \"comment\", // multi line comment\n                merge : true,\n                regex : /\\/\\*/,\n                next : \"comment\"\n            }, {\n                token : \"string\",\n                regex : \"'(?=.)\",\n                next  : \"qstring\"\n            }, {\n                token : \"string\",\n                regex : '\"(?=.)',\n                next  : \"qqstring\"\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : /0[xX][0-9a-fA-F]+\\b/\n            }, {\n                token : \"constant.numeric\", // float\n                regex : /[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b/\n            }, { // match stuff like: Sound.prototype.play = function() { }\n                token : [\n                    \"storage.type\",\n                    \"punctuation.operator\",\n                    \"support.function\",\n                    \"punctuation.operator\",\n                    \"entity.name.function\",\n                    \"text\",\n                    \"keyword.operator\",\n                    \"text\",\n                    \"storage.type\",\n                    \"text\",\n                    \"paren.lparen\"\n                ],\n                regex : \"(\" + identifierRe + \")(\\\\.)(prototype)(\\\\.)(\" + identifierRe +\")(\\\\s*)(=)(\\\\s*)(function)(\\\\s*)(\\\\()\",\n                next: \"function_arguments\"\n            }, { // match stuff like: Sound.prototype.play = myfunc\n                token : [\n                    \"storage.type\",\n                    \"punctuation.operator\",\n                    \"support.function\",\n                    \"punctuation.operator\",\n                    \"entity.name.function\",\n                    \"text\",\n                    \"keyword.operator\",\n                    \"text\"\n                ],\n                regex : \"(\" + identifierRe + \")(\\\\.)(prototype)(\\\\.)(\" + identifierRe +\")(\\\\s*)(=)(\\\\s*)\",\n                next: \"function_arguments\"\n            }, { // match stuff like: Sound.play = function() {  }\n                token : [\n                    \"storage.type\",\n                    \"punctuation.operator\",\n                    \"entity.name.function\",\n                    \"text\",\n                    \"keyword.operator\",\n                    \"text\",\n                    \"storage.type\",\n                    \"text\",\n                    \"paren.lparen\"\n                ],\n                regex : \"(\" + identifierRe + \")(\\\\.)(\" + identifierRe +\")(\\\\s*)(=)(\\\\s*)(function)(\\\\s*)(\\\\()\",\n                next: \"function_arguments\"\n            }, { // match stuff like: play = function() {  }\n                token : [\n                    \"entity.name.function\",\n                    \"text\",\n                    \"keyword.operator\",\n                    \"text\",\n                    \"storage.type\",\n                    \"text\",\n                    \"paren.lparen\"\n                ],\n                regex : \"(\" + identifierRe +\")(\\\\s*)(=)(\\\\s*)(function)(\\\\s*)(\\\\()\",\n                next: \"function_arguments\"\n            }, { // match regular function like: function myFunc(arg) { }\n                token : [\n                    \"storage.type\",\n                    \"text\",\n                    \"entity.name.function\",\n                    \"text\",\n                    \"paren.lparen\"\n                ],\n                regex : \"(function)(\\\\s+)(\" + identifierRe + \")(\\\\s*)(\\\\()\",\n                next: \"function_arguments\"\n            }, { // match stuff like: foobar: function() { }\n                token : [\n                    \"entity.name.function\",\n                    \"text\",\n                    \"punctuation.operator\",\n                    \"text\",\n                    \"storage.type\",\n                    \"text\",\n                    \"paren.lparen\"\n                ],\n                regex : \"(\" + identifierRe + \")(\\\\s*)(:)(\\\\s*)(function)(\\\\s*)(\\\\()\",\n                next: \"function_arguments\"\n            }, { // Attempt to match : function() { } (this is for issues with 'foo': function() { })\n                token : [\n                    \"text\",\n                    \"text\",\n                    \"storage.type\",\n                    \"text\",\n                    \"paren.lparen\"\n                ],\n                regex : \"(:)(\\\\s*)(function)(\\\\s*)(\\\\()\",\n                next: \"function_arguments\"\n            }, {\n                token : \"constant.language.boolean\",\n                regex : /(?:true|false)\\b/\n            }, {\n                token : \"keyword\",\n                regex : \"(?:\" + kwBeforeRe + \")\\\\b\",\n                next : \"regex_allowed\"\n            }, {\n                token : [\"punctuation.operator\", \"support.function\"],\n                regex : /(\\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:opzzzz|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\\b(?=\\()/\n            }, {\n                token : [\"punctuation.operator\", \"support.function.dom\"],\n                regex : /(\\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\\b(?=\\()/\n            }, {\n                token : [\"punctuation.operator\", \"support.constant\"],\n                regex : /(\\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\\b/\n            }, {\n                token : [\"storage.type\", \"punctuation.operator\", \"support.function.firebug\"],\n                regex : /(console)(\\.)(warn|info|log|error|time|timeEnd|assert)\\b/\n            }, {\n                token : function(value) {\n                    if (globals.hasOwnProperty(value))\n                        return \"variable.language\";\n                    else if (deprecated.hasOwnProperty(value))\n                        return \"invalid.deprecated\";\n                    else if (definitions.hasOwnProperty(value))\n                        return \"storage.type\";\n                    else if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (buildinConstants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else if (futureReserved.hasOwnProperty(value))\n                        return \"invalid.illegal\";\n                    else if (value == \"debugger\")\n                        return \"invalid.deprecated\";\n                    else\n                        return \"identifier\";\n                },\n                regex : identifierRe\n            }, {\n                token : \"keyword.operator\",\n                regex : /!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)/,\n                next  : \"regex_allowed\"\n            }, {\n                token : \"punctuation.operator\",\n                regex : /\\?|\\:|\\,|\\;|\\./,\n                next  : \"regex_allowed\"\n            }, {\n                token : \"paren.lparen\",\n                regex : /[\\[({]/,\n                next  : \"regex_allowed\"\n            }, {\n                token : \"paren.rparen\",\n                regex : /[\\])}]/\n            }, {\n                token : \"keyword.operator\",\n                regex : /\\/=?/,\n                next  : \"regex_allowed\"\n            }, {\n                token: \"comment\",\n                regex: /^#!.*$/\n            }, {\n                token : \"text\",\n                regex : /\\s+/\n            }\n        ],\n        // regular expressions are only allowed after certain tokens. This\n        // makes sure we don't mix up regexps with the divison operator\n        \"regex_allowed\": [\n            DocCommentHighlightRules.getStartRule(\"doc-start\"),\n            {\n                token : \"comment\", // multi line comment\n                merge : true,\n                regex : \"\\\\/\\\\*\",\n                next : \"comment_regex_allowed\"\n            }, {\n                token : \"comment\",\n                regex : \"\\\\/\\\\/.*$\"\n            }, {\n                token: \"string.regexp\",\n                regex: \"\\\\/\",\n                next: \"regex\",\n                merge: true\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }, {\n                // immediately return to the start mode without matching\n                // anything\n                token: \"empty\",\n                regex: \"\",\n                next: \"start\"\n            }\n        ],\n        \"regex\": [\n            {\n                token: \"regexp.keyword.operator\",\n                regex: \"\\\\\\\\(?:u[\\\\da-fA-F]{4}|x[\\\\da-fA-F]{2}|.)\"\n            }, {\n                // flag\n                token: \"string.regexp\",\n                regex: \"/\\\\w*\",\n                next: \"start\",\n                merge: true\n            }, {\n                token: \"string.regexp\",\n                regex: \"[^\\\\\\\\/\\\\[]+\",\n                merge: true\n            }, {\n                token: \"string.regexp.charachterclass\",\n                regex: \"\\\\[\",\n                next: \"regex_character_class\",\n                merge: true\n            }, {\n                token: \"empty\",\n                regex: \"\",\n                next: \"start\"\n            }\n        ],\n        \"regex_character_class\": [\n            {\n                token: \"regexp.keyword.operator\",\n                regex: \"\\\\\\\\(?:u[\\\\da-fA-F]{4}|x[\\\\da-fA-F]{2}|.)\"\n            }, {\n                token: \"string.regexp.charachterclass\",\n                regex: \"]\",\n                next: \"regex\",\n                merge: true\n            }, {\n                token: \"string.regexp.charachterclass\",\n                regex: \"[^\\\\\\\\\\\\]]+\",\n                merge: true\n            }, {\n                token: \"empty\",\n                regex: \"\",\n                next: \"start\"\n            }\n        ],\n        \"function_arguments\": [\n            {\n                token: \"variable.parameter\",\n                regex: identifierRe,\n            }, {\n                token: \"punctuation.operator\",\n                regex: \"[, ]+\",\n                merge: true\n            }, {\n                token: \"punctuation.operator\",\n                regex: \"$\",\n                merge: true\n            }, {\n                token: \"empty\",\n                regex: \"\",\n                next: \"start\"\n            }\n        ],\n        \"comment_regex_allowed\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                merge : true,\n                next : \"regex_allowed\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                merge : true,\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ],\n        \"qqstring\" : [\n            {\n                token : \"constant.language.escape\",\n                regex : escapedRe\n            }, {\n                token : \"string\",\n                regex : '[^\"\\\\\\\\]+',\n                merge : true\n            }, {\n                token : \"string\",\n                regex : \"\\\\\\\\$\",\n                next  : \"qqstring\",\n                merge : true\n            }, {\n                token : \"string\",\n                regex : '\"|$',\n                next  : \"start\",\n                merge : true\n            }\n        ],\n        \"qstring\" : [\n            {\n                token : \"constant.language.escape\",\n                regex : escapedRe\n            }, {\n                token : \"string\",\n                regex : \"[^'\\\\\\\\]+\",\n                merge : true\n            }, {\n                token : \"string\",\n                regex : \"\\\\\\\\$\",\n                next  : \"qstring\",\n                merge : true\n            }, {\n                token : \"string\",\n                regex : \"'|$\",\n                next  : \"start\",\n                merge : true\n            }\n        ]\n    };\n\n    this.embedRules(DocCommentHighlightRules, \"doc-\",\n        [ DocCommentHighlightRules.getEndRule(\"start\") ]);\n};\n\noop.inherits(JavaScriptHighlightRules, TextHighlightRules);\n\nexports.JavaScriptHighlightRules = JavaScriptHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/javascript_highlight_rules_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar JavaScriptMode = require(\"./javascript\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n\n    name: \"JavaScript Tokenizer\",\n\n    setUp : function() {\n        this.tokenizer = new JavaScriptMode().getTokenizer();\n    },\n\n    \"test: tokenize1\" : function() {\n        var line = \"foo = function\";\n\n        var tokens = this.tokenizer.getLineTokens(line, \"start\").tokens;\n\n        assert.equal(5, tokens.length);\n        assert.equal(\"identifier\", tokens[0].type);\n        assert.equal(\"text\", tokens[1].type);\n        assert.equal(\"keyword.operator\", tokens[2].type);\n        assert.equal(\"text\", tokens[3].type);\n        assert.equal(\"storage.type\", tokens[4].type);\n    },\n\n    \"test: tokenize 'standard' functions\" : function() {\n        var line = \"string.charCodeAt(23); document.getElementById('test'); console.log('Here it is');\";\n\n        var tokens = this.tokenizer.getLineTokens(line, \"start\").tokens;\n\n        assert.equal(23, tokens.length);\n        assert.equal(\"support.function\", tokens[2].type); // charCodeAt\n        assert.equal(\"support.function.dom\", tokens[10].type); // getElementById\n        assert.equal(\"support.function.firebug\", tokens[18].type); // log\n    },\n\n    \"test: tokenize doc comment\" : function() {\n        var line = \"abc /** de */ fg\";\n\n        var tokens = this.tokenizer.getLineTokens(line, \"start\").tokens;\n\n        assert.equal(5, tokens.length);\n        assert.equal(\"identifier\", tokens[0].type);\n        assert.equal(\"text\", tokens[1].type);\n        assert.equal(\"comment.doc\", tokens[2].type);\n        assert.equal(\"text\", tokens[3].type);\n        assert.equal(\"identifier\", tokens[4].type);\n    },\n\n    \"test: tokenize doc comment with tag\" : function() {\n        var line = \"/** @param {} */\";\n\n        var tokens = this.tokenizer.getLineTokens(line, \"start\").tokens;\n\n        assert.equal(3, tokens.length);\n        assert.equal(\"comment.doc\", tokens[0].type);\n        assert.equal(\"comment.doc.tag\", tokens[1].type);\n        assert.equal(\"comment.doc\", tokens[2].type);\n    },\n\n    \"test: tokenize parens\" : function() {\n        var line = \"[{( )}]\";\n\n        var tokens = this.tokenizer.getLineTokens(line, \"start\").tokens;\n\n        assert.equal(7, tokens.length);\n        assert.equal(\"paren.lparen\", tokens[0].type);\n        assert.equal(\"paren.lparen\", tokens[1].type);\n        assert.equal(\"paren.lparen\", tokens[2].type);\n        assert.equal(\"text\", tokens[3].type);\n        assert.equal(\"paren.rparen\", tokens[4].type);\n        assert.equal(\"paren.rparen\", tokens[5].type);\n        assert.equal(\"paren.rparen\", tokens[6].type);\n    },\n\n    \"test for last rule in ruleset to catch capturing group bugs\" : function() {\n        var tokens = this.tokenizer.getLineTokens(\"}\", \"start\").tokens;\n\n        assert.equal(1, tokens.length);\n        assert.equal(\"paren.rparen\", tokens[0].type);\n    },\n\n    \"test tokenize arithmetic expression which looks like a regexp\": function() {\n        var tokens = this.tokenizer.getLineTokens(\"a/b/c\", \"start\").tokens;\n        assert.equal(5, tokens.length);\n\n        var tokens = this.tokenizer.getLineTokens(\"a/=b/c\", \"start\").tokens;\n        assert.equal(5, tokens.length);\n    },\n\n    \"test tokenize reg exps\" : function() {\n        var tokens = this.tokenizer.getLineTokens(\"a=/b/g\", \"start\").tokens;\n        assert.equal(3, tokens.length);\n        assert.equal(\"string.regexp\", tokens[2].type);\n\n        var tokens = this.tokenizer.getLineTokens(\"a+/b/g\", \"start\").tokens;\n        assert.equal(3, tokens.length);\n        assert.equal(\"string.regexp\", tokens[2].type);\n\n        var tokens = this.tokenizer.getLineTokens(\"a = 1 + /2 + 1/b\", \"start\").tokens;\n        assert.equal(9, tokens.length);\n        assert.equal(\"string.regexp\", tokens[8].type);\n\n        var tokens = this.tokenizer.getLineTokens(\"a=/a/ / /a/\", \"start\").tokens;\n        assert.equal(7, tokens.length);\n        assert.equal(\"string.regexp\", tokens[2].type);\n        assert.equal(\"string.regexp\", tokens[6].type);\n\n        var tokens = this.tokenizer.getLineTokens(\"case /a/.test(c)\", \"start\").tokens;\n        assert.equal(8, tokens.length);\n        assert.equal(\"string.regexp\", tokens[2].type);\n    },\n\n    \"test tokenize multi-line comment containing a single line comment\" : function() {\n        var tokens = this.tokenizer.getLineTokens(\"/* foo // bar */\", \"start\").tokens;\n        assert.equal(1, tokens.length);\n        assert.equal(\"comment\", tokens[0].type);\n\n        var tokens = this.tokenizer.getLineTokens(\"/* foo // bar */\", \"regex_allowed\").tokens;\n        assert.equal(1, tokens.length);\n        assert.equal(\"comment\", tokens[0].type);\n    },\n\n    \"test tokenize identifier with umlauts\": function() {\n        var tokens = this.tokenizer.getLineTokens(\"füße\", \"start\").tokens;\n        assert.equal(1, tokens.length);\n    },\n\n    \"test // is not a regexp\": function() {\n        var tokens = this.tokenizer.getLineTokens(\"{ // 123\", \"start\").tokens;\n        assert.equal(3, tokens.length);\n        assert.equal(\"paren.lparen\", tokens[0].type);\n        assert.equal(\"text\", tokens[1].type);\n        assert.equal(\"comment\", tokens[2].type);\n    },\n\n    \"test skipping escaped chars\": function() {\n        var line = \"console.log('Meh\\\\nNeh');\"\n        var tokens = this.tokenizer.getLineTokens(line, \"start\").tokens;\n\n        assert.equal(9, tokens.length);\n        assert.equal(\"constant.language.escape\", tokens[5].type);\n\n        line = \"console.log('\\\\u1232Feh');\";\n        tokens = this.tokenizer.getLineTokens(line, \"start\").tokens;\n\n        assert.equal(9, tokens.length);\n        assert.equal(\"constant.language.escape\", tokens[5].type);\n    },\n\n    \"test multiline strings\": function() {\n        var line = \"console.log('Meh\\\\\"\n        var data = this.tokenizer.getLineTokens(line, \"start\")\n\n        assert.equal(5, data.tokens.length);\n        assert.equal(data.state, \"qstring\");\n\n        line = \"console.log('Meh\\\\ \"\n        data = this.tokenizer.getLineTokens(line, \"start\")\n\n        assert.equal(6, data.tokens.length);\n        assert.equal(data.state, \"start\");\n\n        line = 'console.log(\"\\\\'\n        data = this.tokenizer.getLineTokens(line, \"start\")\n\n        assert.equal(5, data.tokens.length);\n        assert.equal(data.state, \"qqstring\");\n\n        line = 'a=\"'\n        data = this.tokenizer.getLineTokens(line, \"start\")\n\n        assert.equal(3, data.tokens.length);\n        assert.equal(data.state, \"start\");\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/javascript_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"../edit_session\").EditSession;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar JavaScriptMode = require(\"./javascript\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n    setUp : function() {    \n        this.mode = new JavaScriptMode();\n    },\n\n    \"test: getTokenizer() (smoke test)\" : function() {\n        var tokenizer = this.mode.getTokenizer();\n\n        assert.ok(tokenizer instanceof Tokenizer);\n\n        var tokens = tokenizer.getLineTokens(\"'juhu'\", \"start\").tokens;\n        assert.equal(\"string\", tokens[0].type);\n    },\n\n    \"test: toggle comment lines should prepend '//' to each line\" : function() {\n        var session = new EditSession([\"  abc\", \"cde\", \"fg\"]);\n\n        this.mode.toggleCommentLines(\"start\", session, 0, 1);\n        assert.equal([\"//  abc\", \"//cde\", \"fg\"].join(\"\\n\"), session.toString());\n    },\n\n    \"test: toggle comment on commented lines should remove leading '//' chars\" : function() {\n        var session = new EditSession([\"//  abc\", \"//cde\", \"fg\"]);\n\n        this.mode.toggleCommentLines(\"start\", session, 0, 1);\n        assert.equal([\"  abc\", \"cde\", \"fg\"].join(\"\\n\"), session.toString());\n    },\n\n    \"test: toggle comment lines twice should return the original text\" : function() {\n        var session = new EditSession([\"  abc\", \"cde\", \"fg\"]);\n\n        this.mode.toggleCommentLines(\"start\", session, 0, 2);\n        this.mode.toggleCommentLines(\"start\", session, 0, 2);\n        assert.equal([\"  abc\", \"cde\", \"fg\"].join(\"\\n\"), session.toString());\n    },\n\n    \"test: toggle comment on multiple lines with one commented line prepend '//' to each line\" : function() {\n        var session = new EditSession([\"//  abc\", \"//cde\", \"fg\"]);\n\n        this.mode.toggleCommentLines(\"start\", session, 0, 2);\n        assert.equal([\"////  abc\", \"////cde\", \"//fg\"].join(\"\\n\"), session.toString());\n    },\n\n    \"test: toggle comment on a comment line with leading white space\": function() {\n        var session = new EditSession([\"//cde\", \"  //fg\"]);\n\n        this.mode.toggleCommentLines(\"start\", session, 0, 1);\n        assert.equal([\"cde\", \"  fg\"].join(\"\\n\"), session.toString());\n    },\n\n    \"test: auto indent after opening brace\" : function() {\n        assert.equal(\"  \", this.mode.getNextLineIndent(\"start\", \"if () {\", \"  \"));\n    },\n    \n    \"test: auto indent after case\" : function() {\n        assert.equal(\"  \", this.mode.getNextLineIndent(\"start\", \"case 'juhu':\", \"  \"));\n    },\n\n    \"test: no auto indent in object literal\" : function() {\n        assert.equal(\"\", this.mode.getNextLineIndent(\"start\", \"{ 'juhu':\", \"  \"));\n    },\n\n    \"test: no auto indent after opening brace in multi line comment\" : function() {\n        assert.equal(\"\", this.mode.getNextLineIndent(\"start\", \"/*if () {\", \"  \"));\n        assert.equal(\"  \", this.mode.getNextLineIndent(\"comment\", \"  abcd\", \"  \"));\n    },\n\n    \"test: no auto indent after opening brace in single line comment\" : function() {\n        assert.equal(\"\", this.mode.getNextLineIndent(\"start\", \"//if () {\", \"  \"));\n        assert.equal(\"  \", this.mode.getNextLineIndent(\"start\", \"  //if () {\", \"  \"));\n    },\n\n    \"test: no auto indent should add to existing indent\" : function() {\n        assert.equal(\"      \", this.mode.getNextLineIndent(\"start\", \"    if () {\", \"  \"));\n        assert.equal(\"    \", this.mode.getNextLineIndent(\"start\", \"    cde\", \"  \"));\n        assert.equal(\"    \", this.mode.getNextLineIndent(\"regex_allowed\", \"function foo(items) {\", \"    \"));\n    },\n\n    \"test: special indent in doc comments\" : function() {\n        assert.equal(\" * \", this.mode.getNextLineIndent(\"doc-start\", \"/**\", \" \"));\n        assert.equal(\"   * \", this.mode.getNextLineIndent(\"doc-start\", \"  /**\", \" \"));\n        assert.equal(\" * \", this.mode.getNextLineIndent(\"doc-start\", \" *\", \" \"));\n        assert.equal(\"    * \", this.mode.getNextLineIndent(\"doc-start\", \"    *\", \" \"));\n        assert.equal(\"  \", this.mode.getNextLineIndent(\"doc-start\", \"  abc\", \" \"));\n    },\n\n    \"test: no indent after doc comments\" : function() {\n        assert.equal(\"\", this.mode.getNextLineIndent(\"doc-start\", \"   */\", \"  \"));\n    },\n\n    \"test: trigger outdent if line is space and new text starts with closing brace\" : function() {\n        assert.ok(this.mode.checkOutdent(\"start\", \"   \", \" }\"));\n        assert.ok(!this.mode.checkOutdent(\"start\", \" a  \", \" }\"));\n        assert.ok(!this.mode.checkOutdent(\"start\", \"\", \"}\"));\n        assert.ok(!this.mode.checkOutdent(\"start\", \"   \", \"a }\"));\n        assert.ok(!this.mode.checkOutdent(\"start\", \"   }\", \"}\"));\n    },\n\n    \"test: auto outdent should indent the line with the same indent as the line with the matching opening brace\" : function() {\n        var session = new EditSession([\"  function foo() {\", \"    bla\", \"    }\"], new JavaScriptMode());\n        this.mode.autoOutdent(\"start\", session, 2);\n        assert.equal(\"  }\", session.getLine(2));\n    },\n\n    \"test: no auto outdent if no matching brace is found\" : function() {\n        var session = new EditSession([\"  function foo()\", \"    bla\", \"    }\"]);\n        this.mode.autoOutdent(\"start\", session, 2);\n        assert.equal(\"    }\", session.getLine(2));\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/javascript_worker.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n \ndefine(function(require, exports, module) {\n\"use strict\";\n    \nvar oop = require(\"../lib/oop\");\nvar Mirror = require(\"../worker/mirror\").Mirror;\nvar lint = require(\"../worker/jshint\").JSHINT;\nvar parser = require(\"../narcissus/parser\");\n    \nvar JavaScriptWorker = exports.JavaScriptWorker = function(sender) {\n    Mirror.call(this, sender);\n    this.setTimeout(500);\n};\n\noop.inherits(JavaScriptWorker, Mirror);\n\n(function() {\n    \n    this.onUpdate = function() {\n        var value = this.doc.getValue();\n        value = value.replace(/^#!.*\\n/, \"\\n\");\n        \n//        var start = new Date();\n        try {\n            parser.parse(value);\n        } catch(e) {\n//            console.log(\"narcissus\")\n//            console.log(e);\n            var chunks = e.message.split(\":\")\n            var message = chunks.pop().trim();\n            var lineNumber = parseInt(chunks.pop().trim()) - 1;\n            this.sender.emit(\"narcissus\", {\n                row: lineNumber,\n                column: null, // TODO convert e.cursor\n                text: message,\n                type: \"error\"\n            });\n            return;\n        } finally {\n//            console.log(\"parse time: \" + (new Date() - start));\n        }\n        \n//        var start = new Date();\n//        console.log(\"jslint\")\n        lint(value, {undef: false, onevar: false, passfail: false});\n        this.sender.emit(\"jslint\", lint.errors);        \n//        console.log(\"lint time: \" + (new Date() - start));\n    }\n    \n}).call(JavaScriptWorker.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/javascript_worker_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar assert = require(\"../test/assertions\");\nvar JavaScriptWorker = require(\"./javascript_worker\").JavaScriptWorker;\n\n\nmodule.exports = {\n    setUp : function() {\n        this.sender = {\n            on: function() {},\n            callback: function(data, id) {\n                this.data = data;\n            },\n            events: [],\n            emit: function(type, e) {\n                this.events.push([type, e]);\n            }\n        };\n    },\n\n    \"test check for syntax error\": function() {\n        var worker = new JavaScriptWorker(this.sender);\n        worker.setValue(\"Juhu Kinners\");\n        worker.deferredUpdate.call();\n\n        var error = this.sender.events[0][1];\n        assert.equal(error.text, \"missing ; before statement\");\n        assert.equal(error.type, \"error\");\n        assert.equal(error.row, 0);\n        assert.equal(error.column, null);\n    },\n\n    \"test invalid multi line string\": function() {\n        var worker = new JavaScriptWorker(this.sender);\n        worker.setValue('\"a\\n\\\\nn\"');\n        worker.deferredUpdate.call();\n\n        var error = this.sender.events[0][1];\n        assert.equal(error.text, \"Unterminated string literal\");\n        assert.equal(error.type, \"error\");\n        assert.equal(error.row, 0);\n        assert.equal(error.column, null);\n    },\n\n    \"test check for narcissus bug\": function() {\n        var worker = new JavaScriptWorker(this.sender);\n        worker.setValue(\"if('\");\n        worker.deferredUpdate.call();\n        assert.equal(this.sender.events[0][1].type, \"error\");\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/json/json_parse.js",
    "content": "/*\n    http://www.JSON.org/json_parse.js\n    2008-09-18\n\n    Public Domain.\n\n    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n\n    This file creates a json_parse function.\n\n        json_parse(text, reviver)\n            This method parses a JSON text to produce an object or array.\n            It can throw a SyntaxError exception.\n\n            The optional reviver parameter is a function that can filter and\n            transform the results. It receives each of the keys and values,\n            and its return value is used instead of the original value.\n            If it returns what it received, then the structure is not modified.\n            If it returns undefined then the member is deleted.\n\n            Example:\n\n            // Parse the text. Values that look like ISO date strings will\n            // be converted to Date objects.\n\n            myData = json_parse(text, function (key, value) {\n                var a;\n                if (typeof value === 'string') {\n                    a =\n/^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2}(?:\\.\\d*)?)Z$/.exec(value);\n                    if (a) {\n                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],\n                            +a[5], +a[6]));\n                    }\n                }\n                return value;\n            });\n\n    This is a reference implementation. You are free to copy, modify, or\n    redistribute.\n\n    This code should be minified before deployment.\n    See http://javascript.crockford.com/jsmin.html\n\n    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO\n    NOT CONTROL.\n*/\n\n/*members \"\", \"\\\"\", \"\\/\", \"\\\\\", at, b, call, charAt, f, fromCharCode,\n    hasOwnProperty, message, n, name, push, r, t, text\n*/\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\n// This is a function that can parse a JSON text, producing a JavaScript\n// data structure. It is a simple, recursive descent parser. It does not use\n// eval or regular expressions, so it can be used as a model for implementing\n// a JSON parser in other languages.\n\n// We are defining the function inside of another function to avoid creating\n// global variables.\n\n    var at,     // The index of the current character\n        ch,     // The current character\n        escapee = {\n            '\"':  '\"',\n            '\\\\': '\\\\',\n            '/':  '/',\n            b:    '\\b',\n            f:    '\\f',\n            n:    '\\n',\n            r:    '\\r',\n            t:    '\\t'\n        },\n        text,\n\n        error = function (m) {\n\n// Call error when something is wrong.\n\n            throw {\n                name:    'SyntaxError',\n                message: m,\n                at:      at,\n                text:    text\n            };\n        },\n\n        next = function (c) {\n\n// If a c parameter is provided, verify that it matches the current character.\n\n            if (c && c !== ch) {\n                error(\"Expected '\" + c + \"' instead of '\" + ch + \"'\");\n            }\n\n// Get the next character. When there are no more characters,\n// return the empty string.\n\n            ch = text.charAt(at);\n            at += 1;\n            return ch;\n        },\n\n        number = function () {\n\n// Parse a number value.\n\n            var number,\n                string = '';\n\n            if (ch === '-') {\n                string = '-';\n                next('-');\n            }\n            while (ch >= '0' && ch <= '9') {\n                string += ch;\n                next();\n            }\n            if (ch === '.') {\n                string += '.';\n                while (next() && ch >= '0' && ch <= '9') {\n                    string += ch;\n                }\n            }\n            if (ch === 'e' || ch === 'E') {\n                string += ch;\n                next();\n                if (ch === '-' || ch === '+') {\n                    string += ch;\n                    next();\n                }\n                while (ch >= '0' && ch <= '9') {\n                    string += ch;\n                    next();\n                }\n            }\n            number = +string;\n            if (isNaN(number)) {\n                error(\"Bad number\");\n            } else {\n                return number;\n            }\n        },\n\n        string = function () {\n\n// Parse a string value.\n\n            var hex,\n                i,\n                string = '',\n                uffff;\n\n// When parsing for string values, we must look for \" and \\ characters.\n\n            if (ch === '\"') {\n                while (next()) {\n                    if (ch === '\"') {\n                        next();\n                        return string;\n                    } else if (ch === '\\\\') {\n                        next();\n                        if (ch === 'u') {\n                            uffff = 0;\n                            for (i = 0; i < 4; i += 1) {\n                                hex = parseInt(next(), 16);\n                                if (!isFinite(hex)) {\n                                    break;\n                                }\n                                uffff = uffff * 16 + hex;\n                            }\n                            string += String.fromCharCode(uffff);\n                        } else if (typeof escapee[ch] === 'string') {\n                            string += escapee[ch];\n                        } else {\n                            break;\n                        }\n                    } else {\n                        string += ch;\n                    }\n                }\n            }\n            error(\"Bad string\");\n        },\n\n        white = function () {\n\n// Skip whitespace.\n\n            while (ch && ch <= ' ') {\n                next();\n            }\n        },\n\n        word = function () {\n\n// true, false, or null.\n\n            switch (ch) {\n            case 't':\n                next('t');\n                next('r');\n                next('u');\n                next('e');\n                return true;\n            case 'f':\n                next('f');\n                next('a');\n                next('l');\n                next('s');\n                next('e');\n                return false;\n            case 'n':\n                next('n');\n                next('u');\n                next('l');\n                next('l');\n                return null;\n            }\n            error(\"Unexpected '\" + ch + \"'\");\n        },\n\n        value,  // Place holder for the value function.\n\n        array = function () {\n\n// Parse an array value.\n\n            var array = [];\n\n            if (ch === '[') {\n                next('[');\n                white();\n                if (ch === ']') {\n                    next(']');\n                    return array;   // empty array\n                }\n                while (ch) {\n                    array.push(value());\n                    white();\n                    if (ch === ']') {\n                        next(']');\n                        return array;\n                    }\n                    next(',');\n                    white();\n                }\n            }\n            error(\"Bad array\");\n        },\n\n        object = function () {\n\n// Parse an object value.\n\n            var key,\n                object = {};\n\n            if (ch === '{') {\n                next('{');\n                white();\n                if (ch === '}') {\n                    next('}');\n                    return object;   // empty object\n                }\n                while (ch) {\n                    key = string();\n                    white();\n                    next(':');\n                    if (Object.hasOwnProperty.call(object, key)) {\n                        error('Duplicate key \"' + key + '\"');\n                    }\n                    object[key] = value();\n                    white();\n                    if (ch === '}') {\n                        next('}');\n                        return object;\n                    }\n                    next(',');\n                    white();\n                }\n            }\n            error(\"Bad object\");\n        };\n\n    value = function () {\n\n// Parse a JSON value. It could be an object, an array, a string, a number,\n// or a word.\n\n        white();\n        switch (ch) {\n        case '{':\n            return object();\n        case '[':\n            return array();\n        case '\"':\n            return string();\n        case '-':\n            return number();\n        default:\n            return ch >= '0' && ch <= '9' ? number() : word();\n        }\n    };\n\n// Return the json_parse function. It will have access to all of the above\n// functions and variables.\n\n    return function (source, reviver) {\n        var result;\n\n        text = source;\n        at = 0;\n        ch = ' ';\n        result = value();\n        white();\n        if (ch) {\n            error(\"Syntax error\");\n        }\n\n// If there is a reviver function, we recursively walk the new structure,\n// passing each name/value pair to the reviver function for possible\n// transformation, starting with a temporary root object that holds the result\n// in an empty key. If there is not a reviver function, we simply return the\n// result.\n\n        return typeof reviver === 'function' ? function walk(holder, key) {\n            var k, v, value = holder[key];\n            if (value && typeof value === 'object') {\n                for (k in value) {\n                    if (Object.hasOwnProperty.call(value, k)) {\n                        v = walk(value, k);\n                        if (v !== undefined) {\n                            value[k] = v;\n                        } else {\n                            delete value[k];\n                        }\n                    }\n                }\n            }\n            return reviver.call(holder, key, value);\n        }({'': result}, '') : result;\n    };\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/json.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar HighlightRules = require(\"./json_highlight_rules\").JsonHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar CstyleBehaviour = require(\"./behaviour/cstyle\").CstyleBehaviour;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\nvar WorkerClient = require(\"../worker/worker_client\").WorkerClient;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new HighlightRules().getRules());\n    this.$outdent = new MatchingBraceOutdent();\n    this.$behaviour = new CstyleBehaviour();\n    this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        if (state == \"start\") {\n            var match = line.match(/^.*[\\{\\(\\[]\\s*$/);\n            if (match) {\n                indent += tab;\n            }\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n    this.createWorker = function(session) {\n        var worker = new WorkerClient([\"ace\"], \"worker-json.js\", \"ace/mode/json_worker\", \"JsonWorker\");\n        worker.attachToDocument(session.getDocument());\n\n        worker.on(\"error\", function(e) {\n            session.setAnnotations([e.data]);\n        });\n\n        worker.on(\"ok\", function() {\n            session.clearAnnotations();\n        });\n\n        return worker;\n    };\n\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/json_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Mihai Sucan <mihai DOT sucan AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar JsonHighlightRules = function() {\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n                token : \"constant.language.boolean\",\n                regex : \"(?:true|false)\\\\b\"\n            }, {\n                token : \"invalid.illegal\", // single quoted strings are not allowed\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"invalid.illegal\", // comments are not allowed\n                regex : \"\\\\/\\\\/.*$\"\n            }, {\n                token : \"paren.lparen\",\n                regex : \"[[({]\"\n            }, {\n                token : \"paren.rparen\",\n                regex : \"[\\\\])}]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ]\n    };\n    \n};\n\noop.inherits(JsonHighlightRules, TextHighlightRules);\n\nexports.JsonHighlightRules = JsonHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/json_worker.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar Mirror = require(\"../worker/mirror\").Mirror;\nvar parse = require(\"./json/json_parse\");\n\nvar JsonWorker = exports.JsonWorker = function(sender) {\n    Mirror.call(this, sender);\n    this.setTimeout(200);\n};\n\noop.inherits(JsonWorker, Mirror);\n\n(function() {\n\n    this.onUpdate = function() {\n        var value = this.doc.getValue();\n\n        try {\n            var result = parse(value);\n        } catch (e) {\n            var pos = this.charToDocumentPosition(e.at-1);\n            this.sender.emit(\"error\", {\n                row: pos.row,\n                column: pos.column,\n                text: e.message,\n                type: \"error\"\n            });\n            return;\n        }\n        this.sender.emit(\"ok\");\n    };\n\n    this.charToDocumentPosition = function(charPos) {\n        var i = 0;\n        var len = this.doc.getLength();\n        var nl = this.doc.getNewLineCharacter().length;\n\n        if (!len) {\n            return { row: 0, column: 0};\n        }\n\n        var lineStart = 0;\n        while (i < len) {\n            var line = this.doc.getLine(i);\n            var lineLength = line.length + nl;\n            if (lineStart + lineLength > charPos)\n                return {\n                    row: i,\n                    column: charPos - lineStart\n                };\n\n            lineStart += lineLength;\n            i += 1;\n        }\n\n        return {\n            row: i-1,\n            column: line.length\n        };\n    };\n\n}).call(JsonWorker.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/json_worker_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar assert = require(\"../test/assertions\");\nvar Worker = require(\"./json_worker\").JsonWorker;\n\n\nmodule.exports = {\n    setUp : function() {\n        this.sender = {\n            on: function() {},\n            callback: function(data, id) {\n                this.data = data;\n            },\n            events: [],\n            emit: function(type, e) {\n                this.events.push([type, e]);\n            }\n        };\n    },\n\n    \"test check valid json\": function() {\n        var worker = new Worker(this.sender);\n        worker.setValue(\"{}\");\n        worker.deferredUpdate.call();\n\n        assert.equal(this.sender.events[0][0], \"ok\");\n    },\n\n    \"test check for syntax error\": function() {\n        var worker = new Worker(this.sender);\n        worker.setValue([\n            \"{\",\n            \"juhu: 12\",\n            \"}\"\n        ].join(\"\\n\"));\n        worker.deferredUpdate.call();\n\n        var event = this.sender.events[0];\n        assert.equal(event[0], \"error\");\n        assert.equal(event[1].type, \"error\");\n        assert.equal(event[1].text, \"Bad string\");\n        assert.equal(event[1].row, 1);\n        assert.equal(event[1].column, 0);\n\n    },\n\n    \"test check for syntax error at first char\": function() {\n        var worker = new Worker(this.sender);\n        worker.setValue(\"x\");\n        worker.deferredUpdate.call();\n\n        var event = this.sender.events[0];\n        assert.equal(event[0], \"error\");\n        assert.equal(event[1].type, \"error\");\n        assert.equal(event[1].text, \"Unexpected 'x'\");\n        assert.equal(event[1].row, 0);\n        assert.equal(event[1].column, 0);\n    }\n\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/latex.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar LatexHighlightRules = require(\"./latex_highlight_rules\").LatexHighlightRules;\nvar Range = require(\"../range\").Range;\n\nvar Mode = function()\n{\n    this.$tokenizer = new Tokenizer(new LatexHighlightRules().getRules());\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        // This code is adapted from ruby.js\n        var outdent = true;\n        \n        // LaTeX comments begin with % and go to the end of the line\n        var commentRegEx = /^(\\s*)\\%/;\n\n        for (var i = startRow; i <= endRow; i++) {\n            if (!commentRegEx.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        if (outdent) {\n            var deleteRange = new Range(0, 0, 0, 0);\n            for (var i = startRow; i <= endRow; i++) {\n                var line = doc.getLine(i);\n                var m = line.match(commentRegEx);\n                deleteRange.start.row = i;\n                deleteRange.end.row = i;\n                deleteRange.end.column = m[0].length;\n                doc.replace(deleteRange, m[1]);\n            }\n        }\n        else {\n            doc.indentRows(startRow, endRow, \"%\");\n        }\n    };\n    \n    // There is no universally accepted way of indenting a tex document\n    // so just maintain the indentation of the previous line\n    this.getNextLineIndent = function(state, line, tab) {\n        return this.$getIndent(line);\n    };\n    \n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/latex_highlight_rules.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar LatexHighlightRules = function() {   \n    this.$rules = {\n        \"start\" : [{\n            // A tex command e.g. \\foo\n            token : \"keyword\",\n            regex : \"\\\\\\\\(?:[^a-zA-Z]|[a-zA-Z]+)\",\n        }, {\n            // Curly and square braces\n            token : \"lparen\",\n            regex : \"[[({]\"\n        }, {\n            // Curly and square braces\n            token : \"rparen\",\n            regex : \"[\\\\])}]\"\n        }, {\n            // Inline math between two $ symbols\n            token : \"string\",\n            regex : \"\\\\$(?:(?:\\\\\\\\.)|(?:[^\\\\$\\\\\\\\]))*?\\\\$\"\n        }, {\n            // A comment. Tex comments start with % and go to \n            // the end of the line\n            token : \"comment\",\n            regex : \"%.*$\"\n        }]\n    };\n};\n\noop.inherits(LatexHighlightRules, TextHighlightRules);\n\nexports.LatexHighlightRules = LatexHighlightRules;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/less.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      John Roepke <john AT justjohn DOT us>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar LessHighlightRules = require(\"./less_highlight_rules\").LessHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new LessHighlightRules().getRules(), \"i\");\n    this.$outdent = new MatchingBraceOutdent();\n    this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n    \n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        // ignore braces in comments\n        var tokens = this.$tokenizer.getLineTokens(line, state).tokens;\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n\n        var match = line.match(/^.*\\{\\s*$/);\n        if (match) {\n            indent += tab;\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/less_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      John Roepke <john AT justjohn DOT us>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar LessHighlightRules = function() {\n    \n    var properties = lang.arrayToMap( (function () {\n\n        var browserPrefix = (\"-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-\").split(\"|\");\n        \n        var prefixProperties = (\"appearance|background-clip|background-inline-policy|background-origin|\" + \n             \"background-size|binding|border-bottom-colors|border-left-colors|\" + \n             \"border-right-colors|border-top-colors|border-end|border-end-color|\" + \n             \"border-end-style|border-end-width|border-image|border-start|\" + \n             \"border-start-color|border-start-style|border-start-width|box-align|\" + \n             \"box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|\" + \n             \"box-pack|box-sizing|column-count|column-gap|column-width|column-rule|\" + \n             \"column-rule-width|column-rule-style|column-rule-color|float-edge|\" + \n             \"font-feature-settings|font-language-override|force-broken-image-icon|\" + \n             \"image-region|margin-end|margin-start|opacity|outline|outline-color|\" + \n             \"outline-offset|outline-radius|outline-radius-bottomleft|\" + \n             \"outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|\" + \n             \"outline-style|outline-width|padding-end|padding-start|stack-sizing|\" + \n             \"tab-size|text-blink|text-decoration-color|text-decoration-line|\" + \n             \"text-decoration-style|transform|transform-origin|transition|\" + \n             \"transition-delay|transition-duration|transition-property|\" + \n             \"transition-timing-function|user-focus|user-input|user-modify|user-select|\" +\n             \"window-shadow|border-radius\").split(\"|\");\n        \n        var properties = (\"azimuth|background-attachment|background-color|background-image|\" +\n            \"background-position|background-repeat|background|border-bottom-color|\" +\n            \"border-bottom-style|border-bottom-width|border-bottom|border-collapse|\" +\n            \"border-color|border-left-color|border-left-style|border-left-width|\" +\n            \"border-left|border-right-color|border-right-style|border-right-width|\" +\n            \"border-right|border-spacing|border-style|border-top-color|\" +\n            \"border-top-style|border-top-width|border-top|border-width|border|\" +\n            \"bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|\" +\n            \"counter-reset|cue-after|cue-before|cue|cursor|direction|display|\" +\n            \"elevation|empty-cells|float|font-family|font-size-adjust|font-size|\" +\n            \"font-stretch|font-style|font-variant|font-weight|font|height|left|\" +\n            \"letter-spacing|line-height|list-style-image|list-style-position|\" +\n            \"list-style-type|list-style|margin-bottom|margin-left|margin-right|\" +\n            \"margin-top|marker-offset|margin|marks|max-height|max-width|min-height|\" +\n            \"min-width|opacity|orphans|outline-color|\" +\n            \"outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|\" +\n            \"padding-left|padding-right|padding-top|padding|page-break-after|\" +\n            \"page-break-before|page-break-inside|page|pause-after|pause-before|\" +\n            \"pause|pitch-range|pitch|play-during|position|quotes|richness|right|\" +\n            \"size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|\" +\n            \"stress|table-layout|text-align|text-decoration|text-indent|\" +\n            \"text-shadow|text-transform|top|unicode-bidi|vertical-align|\" +\n            \"visibility|voice-family|volume|white-space|widows|width|word-spacing|\" +\n            \"z-index\").split(\"|\");\n          \n        //The return array     \n        var ret = [];\n        \n        //All prefixProperties will get the browserPrefix in\n        //the begning by join the prefixProperties array with the value of browserPrefix\n        for (var i=0, ln=browserPrefix.length; i<ln; i++) {\n            Array.prototype.push.apply(\n                ret,\n                (( browserPrefix[i] + prefixProperties.join(\"|\" + browserPrefix[i]) ).split(\"|\"))\n            );\n        }\n        \n        //Add also prefixProperties and properties without any browser prefix\n        Array.prototype.push.apply(ret, prefixProperties);\n        Array.prototype.push.apply(ret, properties);\n        \n        return ret;\n        \n    })() );\n    \n\n\n    var functions = lang.arrayToMap(\n        (\"hsl|hsla|rgb|rgba|url|attr|counter|counters|lighten|darken|saturate|\" +\n        \"desaturate|fadein|fadeout|fade|spin|mix|hue|saturation|lightness|\" +\n        \"alpha|round|ceil|floor|percentage|color|iscolor|isnumber|isstring|\" +\n        \"iskeyword|isurl|ispixel|ispercentage|isem\").split(\"|\")\n    );\n\n    var constants = lang.arrayToMap(\n        (\"absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|\" +\n        \"block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|\" +\n        \"char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|\" +\n        \"decimal-leading-zero|decimal|default|disabled|disc|\" +\n        \"distribute-all-lines|distribute-letter|distribute-space|\" +\n        \"distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|\" +\n        \"hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|\" +\n        \"ideograph-alpha|ideograph-numeric|ideograph-parenthesis|\" +\n        \"ideograph-space|inactive|inherit|inline-block|inline|inset|inside|\" +\n        \"inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|\" +\n        \"keep-all|left|lighter|line-edge|line-through|line|list-item|loose|\" +\n        \"lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|\" +\n        \"medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|\" +\n        \"nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|\" +\n        \"overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|\" +\n        \"ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|\" +\n        \"solid|square|static|strict|super|sw-resize|table-footer-group|\" +\n        \"table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|\" +\n        \"transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|\" +\n        \"vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|\" +\n        \"zero\").split(\"|\")\n    );\n\n    var colors = lang.arrayToMap(\n        (\"aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|\" +\n        \"purple|red|silver|teal|white|yellow\").split(\"|\")\n    );\n    \n    var keywords = lang.arrayToMap(\n        (\"@mixin|@extend|@include|@import|@media|@debug|@warn|@if|@for|@each|\" +\n        \"@while|@else|@font-face|@-webkit-keyframes|if|and|!default|module|\" +\n        \"def|end|declare|when|not|and\").split(\"|\")\n    );\n    \n    var tags = lang.arrayToMap(\n        (\"a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdo|\" + \n         \"big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|\" + \n         \"command|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|\" + \n         \"figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|\" + \n         \"header|hgroup|hr|html|i|iframe|img|input|ins|keygen|kbd|label|legend|li|\" + \n         \"link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|\" + \n         \"option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|\" + \n         \"small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|\" + \n         \"textarea|tfoot|th|thead|time|title|tr|tt|u|ul|var|video|wbr|xmp\").split(\"|\")\n    );\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    var numRe = \"\\\\-?(?:(?:[0-9]+)|(?:[0-9]*\\\\.[0-9]+))\";\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \"\\\\/\\\\/.*$\"\n            },\n            {\n                token : \"comment\", // multi line comment\n                merge : true,\n                regex : \"\\\\/\\\\*\",\n                next : \"comment\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"constant.numeric\",\n                regex : numRe + \"(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)\"\n            }, {\n                token : \"constant.numeric\", // hex6 color\n                regex : \"#[a-f0-9]{6}\"\n            }, {\n                token : \"constant.numeric\", // hex3 color\n                regex : \"#[a-f0-9]{3}\"\n            }, {\n                token : \"constant.numeric\",\n                regex : numRe\n            }, {\n                token : function(value) {\n                    if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else\n                        return \"variable\";\n                },\n                regex : \"@[a-z0-9_\\\\-@]*\\\\b\"\n            }, {\n                token : function(value) {\n                    if (properties.hasOwnProperty(value.toLowerCase()))\n                        return \"support.type\";\n                    else if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (constants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else if (functions.hasOwnProperty(value))\n                        return \"support.function\";\n                    else if (colors.hasOwnProperty(value.toLowerCase()))\n                        return \"support.constant.color\";\n                    else if (tags.hasOwnProperty(value.toLowerCase()))\n                        return \"variable.language\";\n                    else\n                        return \"text\";\n                },\n                regex : \"\\\\-?[@a-z_][@a-z0-9_\\\\-]*\"\n            }, {\n                token: \"variable.language\",\n                regex: \"#[a-z0-9-_]+\"\n            }, {\n                token: \"variable.language\",\n                regex: \"\\\\.[a-z0-9-_]+\"\n            }, {\n                token: \"variable.language\",\n                regex: \":[a-z0-9-_]+\"\n            }, {\n                token: \"constant\",\n                regex: \"[a-z0-9-_]+\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"<|>|<=|>=|==|!=|-|%|#|\\\\+|\\\\$|\\\\+|\\\\*\"\n            }, {\n                token : \"paren.lparen\",\n                regex : \"[[({]\"\n            }, {\n                token : \"paren.rparen\",\n                regex : \"[\\\\])}]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ]\n    };\n};\n\noop.inherits(LessHighlightRules, TextHighlightRules);\n\nexports.LessHighlightRules = LessHighlightRules;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/liquid.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar LiquidHighlightRules = require(\"./liquid_highlight_rules\").LiquidHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar Range = require(\"../range\").Range;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new LiquidHighlightRules().getRules());\n    this.$outdent = new MatchingBraceOutdent();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        var outdent = true;\n        var outentedRows = [];\n        var re = /^(\\s*)#/;\n\n        for (var i=startRow; i<= endRow; i++) {\n            if (!re.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        if (outdent) {\n            var deleteRange = new Range(0, 0, 0, 0);\n            for (var i=startRow; i<= endRow; i++)\n            {\n                var line = doc.getLine(i);\n                var m = line.match(re);\n                deleteRange.start.row = i;\n                deleteRange.end.row = i;\n                deleteRange.end.column = m[0].length;\n                doc.replace(deleteRange, m[1]);\n            }\n        }\n        else {\n            doc.indentRows(startRow, endRow, \"#\");\n        }\n    };\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n        var endState = tokenizedLine.state;\n\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n\n        if (state == \"start\") {\n            var match = line.match(/^.*[\\{\\(\\[]\\s*$/);\n            if (match) {\n                indent += tab;\n            }\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/liquid_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar CssHighlightRules = require(\"./css_highlight_rules\").CssHighlightRules;\nvar JavaScriptHighlightRules = require(\"./javascript_highlight_rules\").JavaScriptHighlightRules;\nvar lang = require(\"../lib/lang\");\nvar xmlUtil = require(\"./xml_util\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar LiquidHighlightRules = function() {\n\n    // see: https://developer.mozilla.org/en/Liquid/Reference/Global_Objects\n    var functions = lang.arrayToMap(\n      // Standard Filters\n        (\"date|capitalize|downcase|upcase|first|last|join|sort|map|size|escape|\" +\n         \"escape_once|strip_html|strip_newlines|newline_to_br|replace|replace_first|\" +\n         \"truncate|truncatewords|prepend|append|minus|plus|times|divided_by|split\"\n      ).split(\"|\")\n    );\n\n    var keywords = lang.arrayToMap(\n      // Standard Tags\n        (\"capture|endcapture|case|endcase|when|comment|endcomment|\" +\n        \"cycle|for|endfor|in|reversed|if|endif|else|elsif|include|endinclude|unless|endunless|\" +\n     // Commonly used tags\n        \"style|text|image|widget|plugin|marker|endmarker|tablerow|endtablerow\").split(\"|\")\n    );\n\n    var builtinVariables = lang.arrayToMap(\n        ['forloop']\n        // (\"forloop\\\\.(length|index|index0|rindex|rindex0|first|last)|limit|offset|range\" +\n        // \"tablerowloop\\\\.(length|index|index0|rindex|rindex0|first|last|col|col0|\"+\n        // \"col_first|col_last)\").split(\"|\")\n    );\n\n    var definitions = lang.arrayToMap((\"assign\").split(\"|\"));\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n            start : [{\n                token : \"variable\",\n                regex : \"{%\",\n                next : \"liquid_start\"\n            }, {\n                token : \"variable\",\n                regex : \"{{\",\n                next : \"liquid_start\"\n            }, {\n                token : \"meta.tag\",\n                merge : true,\n                regex : \"<\\\\!\\\\[CDATA\\\\[\",\n                next : \"cdata\"\n            }, {\n                token : \"xml_pe\",\n                regex : \"<\\\\?.*?\\\\?>\"\n            }, {\n                token : \"comment\",\n                merge : true,\n                regex : \"<\\\\!--\",\n                next : \"comment\"\n            }, {\n                token : \"meta.tag\",\n                regex : \"<(?=\\\\s*script\\\\b)\",\n                next : \"script\"\n            }, {\n                token : \"meta.tag\",\n                regex : \"<(?=\\\\s*style\\\\b)\",\n                next : \"style\"\n            }, {\n                token : \"meta.tag\", // opening tag\n                regex : \"<\\\\/?\",\n                next : \"tag\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }, {\n                token : \"text\",\n                regex : \"[^<]+\"\n            } ],\n\n            cdata : [ {\n                token : \"text\",\n                regex : \"\\\\]\\\\]>\",\n                next : \"start\"\n            }, {\n                token : \"text\",\n                merge : true,\n                regex : \"\\\\s+\"\n            }, {\n                token : \"text\",\n                merge : true,\n                regex : \".+\"\n            } ],\n\n            comment : [ {\n                token : \"comment\",\n                regex : \".*?-->\",\n                next : \"start\"\n            }, {\n                token : \"comment\",\n                merge : true,\n                regex : \".+\"\n            } ] ,\n\n            liquid_start : [{\n                token: \"variable\",\n                regex: \"}}\",\n                next: \"start\"\n            }, {\n                token: \"variable\",\n                regex: \"%}\",\n                next: \"start\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n                token : \"constant.language.boolean\",\n                regex : \"(?:true|false)\\\\b\"\n            }, {\n                token : function(value) {\n                    if (functions.hasOwnProperty(value))\n                        return \"support.function\";\n                    else if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (builtinVariables.hasOwnProperty(value))\n                        return \"variable.language\";\n                    else if (definitions.hasOwnProperty(value))\n                        return \"keyword.definition\";\n                    else\n                        return \"identifier\";\n                },\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"\\/|\\\\*|\\\\-|\\\\+|=|!=|\\\\?\\\\:\"\n            }, {\n                token : \"paren.lparen\",\n                regex : /[\\[\\({]/\n            }, {\n                token : \"paren.rparen\",\n                regex : /[\\])}]/\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }]\n    };\n\n    xmlUtil.tag(this.$rules, \"tag\", \"start\");\n    xmlUtil.tag(this.$rules, \"style\", \"css-start\");\n    xmlUtil.tag(this.$rules, \"script\", \"js-start\");\n\n    this.embedRules(JavaScriptHighlightRules, \"js-\", [{\n        token: \"comment\",\n        regex: \"\\\\/\\\\/.*(?=<\\\\/script>)\",\n        next: \"tag\"\n    }, {\n        token: \"meta.tag\",\n        regex: \"<\\\\/(?=script)\",\n        next: \"tag\"\n    }]);\n\n    this.embedRules(CssHighlightRules, \"css-\", [{\n        token: \"meta.tag\",\n        regex: \"<\\\\/(?=style)\",\n        next: \"tag\"\n    }]);\n};\noop.inherits(LiquidHighlightRules, TextHighlightRules);\n\nexports.LiquidHighlightRules = LiquidHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/liquid_highlight_rules_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\nvar LiquidMode = require(\"./liquid\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n\n    name: \"Liquid Tokenizer\",\n\n    setUp : function() {\n        this.tokenizer = new LiquidMode().getTokenizer();\n    },\n\n    \"test: tokenize tags\" : function() {\n        var line = \"for one in many\";\n\n        var tokens = this.tokenizer.getLineTokens(line, \"liquid_start\").tokens;\n\n        assert.equal(7, tokens.length);\n        assert.equal(\"keyword\", tokens[0].type);\n        assert.equal(\"text\", tokens[1].type);\n        assert.equal(\"identifier\", tokens[2].type);\n        assert.equal(\"text\", tokens[3].type);\n        assert.equal(\"keyword\", tokens[4].type);\n        assert.equal(\"text\", tokens[5].type);\n        assert.equal(\"identifier\", tokens[6].type);\n    },\n\n    \"test: tokenize parens\" : function() {\n        var line = \"[{( )}]\";\n\n        var tokens = this.tokenizer.getLineTokens(line, \"liquid_start\").tokens;\n\n        assert.equal(7, tokens.length);\n        assert.equal(\"paren.lparen\", tokens[0].type);\n        assert.equal(\"paren.lparen\", tokens[1].type);\n        assert.equal(\"paren.lparen\", tokens[2].type);\n        assert.equal(\"text\", tokens[3].type);\n        assert.equal(\"paren.rparen\", tokens[4].type);\n        assert.equal(\"paren.rparen\", tokens[5].type);\n        assert.equal(\"paren.rparen\", tokens[6].type);\n    }\n\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/lua.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n* Version: MPL 1.1/GPL 2.0/LGPL 2.1\n*\n* The contents of this file are subject to the Mozilla Public License Version\n* 1.1 (the \"License\"); you may not use this file except in compliance with\n* the License. You may obtain a copy of the License at\n* http://www.mozilla.org/MPL/\n*\n* Software distributed under the License is distributed on an \"AS IS\" basis,\n* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n* for the specific language governing rights and limitations under the\n* License.\n*\n* The Original Code is Ajax.org Code Editor (ACE).\n*\n* The Initial Developer of the Original Code is\n* Ajax.org B.V.\n* Portions created by the Initial Developer are Copyright (C) 2010\n* the Initial Developer. All Rights Reserved.\n*\n* Contributor(s):\n*      Fabian Jakobs <fabian AT ajax DOT org>\n*      Colin Gourlay <colin DOT j DOT gourlay AT gmail DOT com>\n*      Lee Gao\n*\n* Alternatively, the contents of this file may be used under the terms of\n* either the GNU General Public License Version 2 or later (the \"GPL\"), or\n* the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n* in which case the provisions of the GPL or the LGPL are applicable instead\n* of those above. If you wish to allow use of your version of this file only\n* under the terms of either the GPL or the LGPL, and not to allow others to\n* use your version of this file under the terms of the MPL, indicate your\n* decision by deleting the provisions above and replace them with the notice\n* and other provisions required by the GPL or the LGPL. If you do not delete\n* the provisions above, a recipient may use your version of this file under\n* the terms of any one of the MPL, the GPL or the LGPL.\n*\n* ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar LuaHighlightRules = require(\"./lua_highlight_rules\").LuaHighlightRules;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new LuaHighlightRules().getRules());\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n\t\n        var chunks = [\"function\", \"then\", \"do\", \"repeat\"];\n        \n        if (state == \"start\") {\n            var match = line.match(/^.*[\\{\\(\\[]\\s*$/);\n            if (match) {\n                indent += tab;\n            } else {\n                for (var i in tokens){\n                    var token = tokens[i];\n                    if (token.type != \"keyword\") continue;\n                    var chunk_i = chunks.indexOf(token.value);\n                    if (chunk_i != -1){\n                        indent += tab;\n                        break;\n                    }\n                }\n            }\n        } \n\n        return indent;\n    };\n    \n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n\n\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/lua_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n* Version: MPL 1.1/GPL 2.0/LGPL 2.1\n*\n* The contents of this file are subject to the Mozilla Public License Version\n* 1.1 (the \"License\"); you may not use this file except in compliance with\n* the License. You may obtain a copy of the License at\n* http://www.mozilla.org/MPL/\n*\n* Software distributed under the License is distributed on an \"AS IS\" basis,\n* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n* for the specific language governing rights and limitations under the\n* License.\n*\n* The Original Code is Ajax.org Code Editor (ACE).\n*\n* The Initial Developer of the Original Code is\n* Ajax.org B.V.\n* Portions created by the Initial Developer are Copyright (C) 2010\n* the Initial Developer. All Rights Reserved.\n*\n* Contributor(s):\n*      Fabian Jakobs <fabian AT ajax DOT org>\n*      Colin Gourlay <colin DOT j DOT gourlay AT gmail DOT com>\n*      Lee Gao\n*\n* Alternatively, the contents of this file may be used under the terms of\n* either the GNU General Public License Version 2 or later (the \"GPL\"), or\n* the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n* in which case the provisions of the GPL or the LGPL are applicable instead\n* of those above. If you wish to allow use of your version of this file only\n* under the terms of either the GPL or the LGPL, and not to allow others to\n* use your version of this file under the terms of the MPL, indicate your\n* decision by deleting the provisions above and replace them with the notice\n* and other provisions required by the GPL or the LGPL. If you do not delete\n* the provisions above, a recipient may use your version of this file under\n* the terms of any one of the MPL, the GPL or the LGPL.\n*\n* ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar LuaHighlightRules = function() {\n\n    var keywords = lang.arrayToMap(\n        (\"break|do|else|elseif|end|for|function|if|in|local|repeat|\"+\n         \"return|then|until|while|or|and|not\").split(\"|\")\n    );\n\n    var builtinConstants = lang.arrayToMap(\n        (\"true|false|nil|_G|_VERSION\").split(\"|\")\n    );\n\n    var builtinFunctions = lang.arrayToMap(\n        (\"string|xpcall|package|tostring|print|os|unpack|require|\"+\n        \"getfenv|setmetatable|next|assert|tonumber|io|rawequal|\"+\n        \"collectgarbage|getmetatable|module|rawset|math|debug|\"+\n        \"pcall|table|newproxy|type|coroutine|_G|select|gcinfo|\"+\n        \"pairs|rawget|loadstring|ipairs|_VERSION|dofile|setfenv|\"+\n        \"load|error|loadfile|\"+\n\n        \"sub|upper|len|gfind|rep|find|match|char|dump|gmatch|\"+\n        \"reverse|byte|format|gsub|lower|preload|loadlib|loaded|\"+\n        \"loaders|cpath|config|path|seeall|exit|setlocale|date|\"+\n        \"getenv|difftime|remove|time|clock|tmpname|rename|execute|\"+\n        \"lines|write|close|flush|open|output|type|read|stderr|\"+\n        \"stdin|input|stdout|popen|tmpfile|log|max|acos|huge|\"+\n        \"ldexp|pi|cos|tanh|pow|deg|tan|cosh|sinh|random|randomseed|\"+\n        \"frexp|ceil|floor|rad|abs|sqrt|modf|asin|min|mod|fmod|log10|\"+\n        \"atan2|exp|sin|atan|getupvalue|debug|sethook|getmetatable|\"+\n        \"gethook|setmetatable|setlocal|traceback|setfenv|getinfo|\"+\n        \"setupvalue|getlocal|getregistry|getfenv|setn|insert|getn|\"+\n        \"foreachi|maxn|foreach|concat|sort|remove|resume|yield|\"+\n        \"status|wrap|create|running\").split(\"|\")\n    );\n    \n    var stdLibaries = lang.arrayToMap(\n        (\"string|package|os|io|math|debug|table|coroutine\").split(\"|\")\n    );\n    \n    var metatableMethods = lang.arrayToMap(\n        (\"__add|__sub|__mod|__unm|__concat|__lt|__index|__call|__gc|__metatable|\"+\n         \"__mul|__div|__pow|__len|__eq|__le|__newindex|__tostring|__mode|__tonumber\").split(\"|\")\n    );\n\n    var futureReserved = lang.arrayToMap(\n        (\"\").split(\"|\")\n    );\n    \n    var deprecatedIn5152 = lang.arrayToMap(\n        (\"setn|foreach|foreachi|gcinfo|log10|maxn\").split(\"|\")\n    );\n\n    var strPre = \"\";\n\n    var decimalInteger = \"(?:(?:[1-9]\\\\d*)|(?:0))\";\n    var hexInteger = \"(?:0[xX][\\\\dA-Fa-f]+)\";\n    var integer = \"(?:\" + decimalInteger + \"|\" + hexInteger + \")\";\n\n    var fraction = \"(?:\\\\.\\\\d+)\";\n    var intPart = \"(?:\\\\d+)\";\n    var pointFloat = \"(?:(?:\" + intPart + \"?\" + fraction + \")|(?:\" + intPart + \"\\\\.))\";\n    var floatNumber = \"(?:\" + pointFloat + \")\";\n    \n    var comment_stack = [];\n    \n    this.$rules = {\n        \"start\" : \n\n\t\t\n        // bracketed comments\n        [{\n            token : \"comment\",           // --[[ comment\n            regex : strPre + '\\\\-\\\\-\\\\[\\\\[.*\\\\]\\\\]'\n        }, {\n            token : \"comment\",           // --[=[ comment\n            regex : strPre + '\\\\-\\\\-\\\\[\\\\=\\\\[.*\\\\]\\\\=\\\\]'\n        }, {\n            token : \"comment\",           // --[==[ comment\n            regex : strPre + '\\\\-\\\\-\\\\[\\\\={2}\\\\[.*\\\\]\\\\={2}\\\\]'\n        }, {\n            token : \"comment\",           // --[===[ comment\n            regex : strPre + '\\\\-\\\\-\\\\[\\\\={3}\\\\[.*\\\\]\\\\={3}\\\\]'\n        }, {\n            token : \"comment\",           // --[====[ comment\n            regex : strPre + '\\\\-\\\\-\\\\[\\\\={4}\\\\[.*\\\\]\\\\={4}\\\\]'\n        }, {\n            token : \"comment\",           // --[====+[ comment\n            regex : strPre + '\\\\-\\\\-\\\\[\\\\={5}\\\\=*\\\\[.*\\\\]\\\\={5}\\\\=*\\\\]'\n        },\n\t\t\n\t\t// multiline bracketed comments\n\t\t{\n            token : \"comment\",           // --[[ comment\n            regex : strPre + '\\\\-\\\\-\\\\[\\\\[.*$',\n            merge : true,\n            next  : \"qcomment\"\n        }, {\n            token : \"comment\",           // --[=[ comment\n            regex : strPre + '\\\\-\\\\-\\\\[\\\\=\\\\[.*$',\n            merge : true,\n            next  : \"qcomment1\"\n        }, {\n            token : \"comment\",           // --[==[ comment\n            regex : strPre + '\\\\-\\\\-\\\\[\\\\={2}\\\\[.*$',\n            merge : true,\n            next  : \"qcomment2\"\n        }, {\n            token : \"comment\",           // --[===[ comment\n            regex : strPre + '\\\\-\\\\-\\\\[\\\\={3}\\\\[.*$',\n            merge : true,\n            next  : \"qcomment3\"\n        }, {\n            token : \"comment\",           // --[====[ comment\n            regex : strPre + '\\\\-\\\\-\\\\[\\\\={4}\\\\[.*$',\n            merge : true,\n            next  : \"qcomment4\"\n        }, {\n            token : function(value){     // --[====+[ comment\n                // WARNING: EXTREMELY SLOW, but this is the only way to circumvent the\n                // limits imposed by the current automaton.\n                // I've never personally seen any practical code where 5 or more '='s are\n                // used for string or commenting, so this will rarely be invoked.\n                var pattern = /\\-\\-\\[(\\=+)\\[/, match;\n                // you can never be too paranoid ;)\n                if ((match = pattern.exec(value)) != null && (match = match[1]) != undefined)\n                    comment_stack.push(match.length);\n                \n                return \"comment\";\n            },\n            regex : strPre + '\\\\-\\\\-\\\\[\\\\={5}\\\\=*\\\\[.*$',\n            merge : true,\n            next  : \"qcomment5\"\n        },\n        \n        // single line comments\n        {\n            token : \"comment\",\n            regex : \"\\\\-\\\\-.*$\"\n        }, \n        \n        // bracketed strings\n\t\t{\n            token : \"string\",           // [[ string\n            regex : strPre + '\\\\[\\\\[.*\\\\]\\\\]'\n        }, {\n            token : \"string\",           // [=[ string\n            regex : strPre + '\\\\[\\\\=\\\\[.*\\\\]\\\\=\\\\]'\n        }, {\n            token : \"string\",           // [==[ string\n            regex : strPre + '\\\\[\\\\={2}\\\\[.*\\\\]\\\\={2}\\\\]'\n        }, {\n            token : \"string\",           // [===[ string\n            regex : strPre + '\\\\[\\\\={3}\\\\[.*\\\\]\\\\={3}\\\\]'\n        }, {\n            token : \"string\",           // [====[ string\n            regex : strPre + '\\\\[\\\\={4}\\\\[.*\\\\]\\\\={4}\\\\]'\n        }, {\n            token : \"string\",           // [====+[ string\n            regex : strPre + '\\\\[\\\\={5}\\\\=*\\\\[.*\\\\]\\\\={5}\\\\=*\\\\]'\n        },\n\t\t\n\t\t// multiline bracketed strings\n        {\n            token : \"string\",           // [[ string\n            regex : strPre + '\\\\[\\\\[.*$',\n            merge : true,\n            next  : \"qstring\"\n        }, {\n            token : \"string\",           // [=[ string\n            regex : strPre + '\\\\[\\\\=\\\\[.*$',\n            merge : true,\n            next  : \"qstring1\"\n        }, {\n            token : \"string\",           // [==[ string\n            regex : strPre + '\\\\[\\\\={2}\\\\[.*$',\n            merge : true,\n            next  : \"qstring2\"\n        }, {\n            token : \"string\",           // [===[ string\n            regex : strPre + '\\\\[\\\\={3}\\\\[.*$',\n            merge : true,\n            next  : \"qstring3\"\n        }, {\n            token : \"string\",           // [====[ string\n            regex : strPre + '\\\\[\\\\={4}\\\\[.*$',\n            merge : true,\n            next  : \"qstring4\"\n        }, {\n            token : function(value){     // --[====+[ string\n                // WARNING: EXTREMELY SLOW, see above.\n                var pattern = /\\[(\\=+)\\[/, match;\n                if ((match = pattern.exec(value)) != null && (match = match[1]) != undefined)\n                    comment_stack.push(match.length);\n                \n                return \"string\";\n            },\n            regex : strPre + '\\\\[\\\\={5}\\\\=*\\\\[.*$',\n            merge : true,\n            next  : \"qstring5\"\n        }, \n        \n        {\n            token : \"string\",           // \" string\n            regex : strPre + '\"(?:[^\\\\\\\\]|\\\\\\\\.)*?\"'\n        }, {\n            token : \"string\",           // ' string\n            regex : strPre + \"'(?:[^\\\\\\\\]|\\\\\\\\.)*?'\"\n        }, {\n            token : \"constant.numeric\", // float\n            regex : floatNumber\n        }, {\n            token : \"constant.numeric\", // integer\n            regex : integer + \"\\\\b\"\n        }, {\n            token : function(value) {\n                if (keywords.hasOwnProperty(value))\n                    return \"keyword\";\n                else if (builtinConstants.hasOwnProperty(value))\n                    return \"constant.language\";\n                else if (futureReserved.hasOwnProperty(value))\n                    return \"invalid.illegal\";\n                else if (stdLibaries.hasOwnProperty(value))\n                    return \"constant.library\";\n                else if (deprecatedIn5152.hasOwnProperty(value))\n                    return \"invalid.deprecated\";\n                else if (builtinFunctions.hasOwnProperty(value))\n                    return \"support.function\";\n                else if (metatableMethods.hasOwnProperty(value))\n                    return \"support.function\";\n                else\n                    return \"identifier\";\n            },\n            regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n        }, {\n            token : \"keyword.operator\",\n            regex : \"\\\\+|\\\\-|\\\\*|\\\\/|%|\\\\#|\\\\^|~|<|>|<=|=>|==|~=|=|\\\\:|\\\\.\\\\.\\\\.|\\\\.\\\\.\"\n        }, {\n            token : \"paren.lparen\",\n            regex : \"[\\\\[\\\\(\\\\{]\"\n        }, {\n            token : \"paren.rparen\",\n            regex : \"[\\\\]\\\\)\\\\}]\"\n        }, {\n            token : \"text\",\n            regex : \"\\\\s+\"\n        } ],\n        \n        \"qcomment\": [ {\n            token : \"comment\",\n            regex : \"(?:[^\\\\\\\\]|\\\\\\\\.)*?\\\\]\\\\]\",\n            next  : \"start\"\n        }, {\n            token : \"comment\",\n            merge : true,\n            regex : '.+'\n        } ],\n        \"qcomment1\": [ {\n            token : \"comment\",\n            regex : \"(?:[^\\\\\\\\]|\\\\\\\\.)*?\\\\]\\\\=\\\\]\",\n            next  : \"start\"\n        }, {\n            token : \"comment\",\n            merge : true,\n            regex : '.+'\n        } ],\n        \"qcomment2\": [ {\n            token : \"comment\",\n            regex : \"(?:[^\\\\\\\\]|\\\\\\\\.)*?\\\\]\\\\={2}\\\\]\",\n            next  : \"start\"\n        }, {\n            token : \"comment\",\n            merge : true,\n            regex : '.+'\n        } ],\n        \"qcomment3\": [ {\n            token : \"comment\",\n            regex : \"(?:[^\\\\\\\\]|\\\\\\\\.)*?\\\\]\\\\={3}\\\\]\",\n            next  : \"start\"\n        }, {\n            token : \"comment\",\n            merge : true,\n            regex : '.+'\n        } ],\n        \"qcomment4\": [ {\n            token : \"comment\",\n            regex : \"(?:[^\\\\\\\\]|\\\\\\\\.)*?\\\\]\\\\={4}\\\\]\",\n            next  : \"start\"\n        }, {\n            token : \"comment\",\n            merge : true,\n            regex : '.+'\n        } ],\n        \"qcomment5\": [ {\n            token : function(value){ \n                // very hackish, mutates the qcomment5 field on the fly.\n                var pattern = /\\](\\=+)\\]/, rule = this.rules.qcomment5[0], match;\n                rule.next = \"start\";\n                if ((match = pattern.exec(value)) != null && (match = match[1]) != undefined){\n                    var found = match.length, expected;\n                    if ((expected = comment_stack.pop()) != found){\n                        comment_stack.push(expected);\n                        rule.next = \"qcomment5\";\n                    }\n                }\n                \n                return \"comment\";\n            },\n            regex : \"(?:[^\\\\\\\\]|\\\\\\\\.)*?\\\\]\\\\={5}\\\\=*\\\\]\",\n            next  : \"start\"\n        }, {\n            token : \"comment\",\n            merge : true,\n            regex : '.+'\n        } ],\n        \n        \"qstring\": [ {\n            token : \"string\",\n            regex : \"(?:[^\\\\\\\\]|\\\\\\\\.)*?\\\\]\\\\]\",\n            next  : \"start\"\n        }, {\n            token : \"string\",\n            merge : true,\n            regex : '.+'\n        } ],\n        \"qstring1\": [ {\n            token : \"string\",\n            regex : \"(?:[^\\\\\\\\]|\\\\\\\\.)*?\\\\]\\\\=\\\\]\",\n            next  : \"start\"\n        }, {\n            token : \"string\",\n            merge : true,\n            regex : '.+'\n        } ],\n        \"qstring2\": [ {\n            token : \"string\",\n            regex : \"(?:[^\\\\\\\\]|\\\\\\\\.)*?\\\\]\\\\={2}\\\\]\",\n            next  : \"start\"\n        }, {\n            token : \"string\",\n            merge : true,\n            regex : '.+'\n        } ],\n        \"qstring3\": [ {\n            token : \"string\",\n            regex : \"(?:[^\\\\\\\\]|\\\\\\\\.)*?\\\\]\\\\={3}\\\\]\",\n            next  : \"start\"\n        }, {\n            token : \"string\",\n            merge : true,\n            regex : '.+'\n        } ],\n        \"qstring4\": [ {\n            token : \"string\",\n            regex : \"(?:[^\\\\\\\\]|\\\\\\\\.)*?\\\\]\\\\={4}\\\\]\",\n            next  : \"start\"\n        }, {\n            token : \"string\",\n            merge : true,\n            regex : '.+'\n        } ],\n        \"qstring5\": [ {\n            token : function(value){ \n                // very hackish, mutates the qstring5 field on the fly.\n                var pattern = /\\](\\=+)\\]/, rule = this.rules.qstring5[0], match;\n                rule.next = \"start\";\n                if ((match = pattern.exec(value)) != null && (match = match[1]) != undefined){\n                    var found = match.length, expected;\n                    if ((expected = comment_stack.pop()) != found){\n                        comment_stack.push(expected);\n                        rule.next = \"qstring5\";\n                    }\n                }\n                \n                return \"string\";\n            },\n            regex : \"(?:[^\\\\\\\\]|\\\\\\\\.)*?\\\\]\\\\={5}\\\\=*\\\\]\",\n            next  : \"start\"\n        }, {\n            token : \"string\",\n            merge : true,\n            regex : '.+'\n        } ]\n        \n    };\n\n}\n\noop.inherits(LuaHighlightRules, TextHighlightRules);\n\nexports.LuaHighlightRules = LuaHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/markdown.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Mihai Sucan <mihai DOT sucan AT gmail DOT com>\n *      Chris Spencer <chris.ag.spencer AT googlemail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar JavaScriptMode = require(\"./javascript\").Mode;\nvar XmlMode = require(\"./xml\").Mode;\nvar HtmlMode = require(\"./html\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar MarkdownHighlightRules = require(\"./markdown_highlight_rules\").MarkdownHighlightRules;\n\nvar Mode = function() {\n    var highlighter = new MarkdownHighlightRules();\n    \n    this.$tokenizer = new Tokenizer(highlighter.getRules());\n    this.$embeds = highlighter.getEmbeds();\n    this.createModeDelegates({\n      \"js-\": JavaScriptMode,\n      \"xml-\": XmlMode,\n      \"html-\": HtmlMode\n    });\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n    this.getNextLineIndent = function(state, line, tab) {\n        if (state == \"listblock\") {\n            var match = /^((?:.+)?)([-+*][ ]+)/.exec(line);\n            if (match) {\n                return new Array(match[1].length + 1).join(\" \") + match[2];\n            } else {\n                return \"\";\n            }\n        } else {\n            return this.$getIndent(line);\n        }\n    };\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/markdown_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Chris Spencer <chris.ag.spencer AT googlemail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\nvar JavaScriptHighlightRules = require(\"./javascript_highlight_rules\").JavaScriptHighlightRules;\nvar XmlHighlightRules = require(\"./xml_highlight_rules\").XmlHighlightRules;\nvar HtmlHighlightRules = require(\"./html_highlight_rules\").HtmlHighlightRules;\nvar CssHighlightRules = require(\"./css_highlight_rules\").CssHighlightRules;\n\nfunction github_embed(tag, prefix) {\n    return { // Github style block\n        token : \"support.function\",\n        regex : \"^```\" + tag + \"\\\\s*$\",\n        next  : prefix + \"start\"\n    };\n}\n\nvar MarkdownHighlightRules = function() {\n\n    // regexp must not have capturing parentheses\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [ {\n            token : \"empty_line\",\n            regex : '^$'\n        }, { // code span `\n            token : [\"support.function\", \"support.function\", \"support.function\"],\n            regex : \"(`+)([^\\\\r]*?[^`])(\\\\1)\"\n        }, { // code block\n            token : \"support.function\",\n            regex : \"^[ ]{4}.+\"\n        }, { // h1\n            token: \"markup.heading.1\",\n            regex: \"^=+(?=\\\\s*$)\"\n        }, { // h2\n            token: \"markup.heading.1\",\n            regex: \"^\\\\-+(?=\\\\s*$)\"\n        }, { // header\n            token : function(value) {\n                return \"markup.heading.\" + value.length;\n            },\n            regex : \"^#{1,6}\"\n        }, github_embed(\"javascript\", \"js-\"),\n           github_embed(\"xml\", \"xml-\"),\n           github_embed(\"html\", \"html-\"),\n           github_embed(\"css\", \"css-\"),\n        { // Github style block\n            token : \"support.function\",\n            regex : \"^```[a-zA-Z]+\\\\s*$\",\n            next  : \"githubblock\"\n        }, { // block quote\n            token : \"string\",\n            regex : \"^>[ ].+$\",\n            next  : \"blockquote\"\n        }, { // reference\n            token : [\"text\", \"constant\", \"text\", \"url\", \"string\", \"text\"],\n            regex : \"^([ ]{0,3}\\\\[)([^\\\\]]+)(\\\\]:\\\\s*)([^ ]+)(\\\\s*(?:[\\\"][^\\\"]+[\\\"])?(\\\\s*))$\"\n        }, { // link by reference\n            token : [\"text\", \"string\", \"text\", \"constant\", \"text\"],\n            regex : \"(\\\\[)((?:[[^\\\\]]*\\\\]|[^\\\\[\\\\]])*)(\\\\][ ]?(?:\\\\n[ ]*)?\\\\[)(.*?)(\\\\])\"\n        }, { // link by url\n            token : [\"text\", \"string\", \"text\", \"markup.underline\", \"string\", \"text\"],\n            regex : \"(\\\\[)\"+\n                    \"(\\\\[[^\\\\]]*\\\\]|[^\\\\[\\\\]]*)\"+\n                    \"(\\\\]\\\\([ \\\\t]*)\"+\n                    \"(<?(?:(?:[^\\\\(]*?\\\\([^\\\\)]*?\\\\)\\\\S*?)|(?:.*?))>?)\"+\n                    \"((?:[ \\t]*\\\"(?:.*?)\\\"[ \\\\t]*)?)\"+\n                    \"(\\\\))\"\n        }, { // HR *\n            token : \"constant\",\n            regex : \"^[ ]{0,2}(?:[ ]?\\\\*[ ]?){3,}\\\\s*$\"\n        }, { // HR -\n            token : \"constant\",\n            regex : \"^[ ]{0,2}(?:[ ]?\\\\-[ ]?){3,}\\\\s*$\"\n        }, { // HR _\n            token : \"constant\",\n            regex : \"^[ ]{0,2}(?:[ ]?\\\\_[ ]?){3,}\\\\s*$\"\n        }, { // list\n            token : \"markup.list\",\n            regex : \"^\\\\s{0,3}(?:[*+-]|\\\\d+\\\\.)\\\\s+\",\n            next  : \"listblock\"\n        }, { // strong ** __\n            token : [\"string\", \"string\", \"string\"],\n            regex : \"([*]{2}|[_]{2}(?=\\\\S))([^\\\\r]*?\\\\S[*_]*)(\\\\1)\"\n        }, { // emphasis * _\n            token : [\"string\", \"string\", \"string\"],\n            regex : \"([*]|[_](?=\\\\S))([^\\\\r]*?\\\\S[*_]*)(\\\\1)\"\n        }, { // \n            token : [\"text\", \"url\", \"text\"],\n            regex : \"(<)(\"+\n                      \"(?:https?|ftp|dict):[^'\\\">\\\\s]+\"+\n                      \"|\"+\n                      \"(?:mailto:)?[-.\\\\w]+\\\\@[-a-z0-9]+(?:\\\\.[-a-z0-9]+)*\\\\.[a-z]+\"+\n                    \")(>)\"\n        }, {\n            token : \"text\",\n            regex : \"[^\\\\*_%$`\\\\[#<>]+\"\n        } ],\n        \n        \"listblock\" : [ { // Lists only escape on completely blank lines.\n            token : \"empty_line\",\n            regex : \"^$\",\n            next  : \"start\"\n        }, {\n            token : \"markup.list\",\n            regex : \".+\"\n        } ],\n        \n        \"blockquote\" : [ { // BLockquotes only escape on blank lines.\n            token : \"empty_line\",\n            regex : \"^\\\\s*$\",\n            next  : \"start\"\n        }, {\n            token : \"string\",\n            regex : \".+\"\n        } ],\n        \n        \"githubblock\" : [ {\n            token : \"support.function\",\n            regex : \"^```\",\n            next  : \"start\"\n        }, {\n            token : \"support.function\",\n            regex : \".+\"\n        } ]\n    };\n    \n    this.embedRules(JavaScriptHighlightRules, \"js-\", [{\n       token : \"support.function\",\n       regex : \"^```\",\n       next  : \"start\"\n    }]);\n    \n    this.embedRules(HtmlHighlightRules, \"html-\", [{\n       token : \"support.function\",\n       regex : \"^```\",\n       next  : \"start\"\n    }]);\n    \n    this.embedRules(CssHighlightRules, \"css-\", [{\n       token : \"support.function\",\n       regex : \"^```\",\n       next  : \"start\"\n    }]);\n    \n    this.embedRules(XmlHighlightRules, \"xml-\", [{\n       token : \"support.function\",\n       regex : \"^```\",\n       next  : \"start\"\n    }]);\n};\noop.inherits(MarkdownHighlightRules, TextHighlightRules);\n\nexports.MarkdownHighlightRules = MarkdownHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/matching_brace_outdent.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Range = require(\"../range\").Range;\n\nvar MatchingBraceOutdent = function() {};\n\n(function() {\n\n    this.checkOutdent = function(line, input) {\n        if (! /^\\s+$/.test(line))\n            return false;\n\n        return /^\\s*\\}/.test(input);\n    };\n\n    this.autoOutdent = function(doc, row) {\n        var line = doc.getLine(row);\n        var match = line.match(/^(\\s*\\})/);\n\n        if (!match) return 0;\n\n        var column = match[1].length;\n        var openBracePos = doc.findMatchingBracket({row: row, column: column});\n\n        if (!openBracePos || openBracePos.row == row) return 0;\n\n        var indent = this.$getIndent(doc.getLine(openBracePos.row));\n        doc.replace(new Range(row, 0, row, column-1), indent);\n    };\n\n    this.$getIndent = function(line) {\n        var match = line.match(/^(\\s+)/);\n        if (match) {\n            return match[1];\n        }\n\n        return \"\";\n    };\n\n}).call(MatchingBraceOutdent.prototype);\n\nexports.MatchingBraceOutdent = MatchingBraceOutdent;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/matching_parens_outdent.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Range = require(\"../range\").Range;\n\nvar MatchingParensOutdent = function() {};\n\n(function() {\n\n    this.checkOutdent = function(line, input) {\n        if (! /^\\s+$/.test(line))\n            return false;\n\n        return /^\\s*\\)/.test(input);\n    };\n\n    this.autoOutdent = function(doc, row) {\n        var line = doc.getLine(row);\n        var match = line.match(/^(\\s*\\))/);\n\n        if (!match) return 0;\n\n        var column = match[1].length;\n        var openBracePos = doc.findMatchingBracket({row: row, column: column});\n\n        if (!openBracePos || openBracePos.row == row) return 0;\n\n        var indent = this.$getIndent(doc.getLine(openBracePos.row));\n        doc.replace(new Range(row, 0, row, column-1), indent);\n    };\n\n    this.$getIndent = function(line) {\n        var match = line.match(/^(\\s+)/);\n        if (match) {\n            return match[1];\n        }\n\n        return \"\";\n    };\n\n}).call(MatchingParensOutdent.prototype);\n\nexports.MatchingParensOutdent = MatchingParensOutdent;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/ocaml.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Sergi Mansilla <sergi AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar OcamlHighlightRules = require(\"./ocaml_highlight_rules\").OcamlHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar Range = require(\"../range\").Range;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new OcamlHighlightRules().getRules());\n    this.$outdent   = new MatchingBraceOutdent();\n};\noop.inherits(Mode, TextMode);\n\nvar indenter = /(?:[({[=:]|[-=]>|\\b(?:else|try|with))\\s*$/;\n\n(function() {\n\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        var i, line;\n        var outdent = true;\n        var re = /^\\s*\\(\\*(.*)\\*\\)/;\n\n        for (i=startRow; i<= endRow; i++) {\n            if (!re.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        var range = new Range(0, 0, 0, 0);\n        for (i=startRow; i<= endRow; i++) {\n            line = doc.getLine(i);\n            range.start.row  = i;\n            range.end.row    = i;\n            range.end.column = line.length;\n\n            doc.replace(range, outdent ? line.match(re)[1] : \"(*\" + line + \"*)\");\n        }\n    };\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n        var tokens = this.$tokenizer.getLineTokens(line, state).tokens;\n\n        if (!(tokens.length && tokens[tokens.length - 1].type === 'comment') &&\n            state === 'start' && indenter.test(line))\n            indent += tab;\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/ocaml_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Sergi Mansilla <sergi AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK *****\n *\n */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar OcamlHighlightRules = function() {\n\n    var keywords = lang.arrayToMap((\n        \"and|as|assert|begin|class|constraint|do|done|downto|else|end|\"  +\n        \"exception|external|for|fun|function|functor|if|in|include|\"     +\n        \"inherit|initializer|lazy|let|match|method|module|mutable|new|\"  +\n        \"object|of|open|or|private|rec|sig|struct|then|to|try|type|val|\" +\n        \"virtual|when|while|with\").split(\"|\")\n    );\n\n    var builtinConstants = lang.arrayToMap(\n        (\"true|false\").split(\"|\")\n    );\n\n    var builtinFunctions = lang.arrayToMap((\n        \"abs|abs_big_int|abs_float|abs_num|abstract_tag|accept|access|acos|add|\" +\n        \"add_available_units|add_big_int|add_buffer|add_channel|add_char|\" +\n        \"add_initializer|add_int_big_int|add_interfaces|add_num|add_string|\" +\n        \"add_substitute|add_substring|alarm|allocated_bytes|allow_only|\" +\n        \"allow_unsafe_modules|always|append|appname_get|appname_set|\" +\n        \"approx_num_exp|approx_num_fix|arg|argv|arith_status|array|\" +\n        \"array1_of_genarray|array2_of_genarray|array3_of_genarray|asin|asr|\" +\n        \"assoc|assq|at_exit|atan|atan2|auto_synchronize|background|basename|\" +\n        \"beginning_of_input|big_int_of_int|big_int_of_num|big_int_of_string|bind|\" +\n        \"bind_class|bind_tag|bits|bits_of_float|black|blit|blit_image|blue|bool|\" +\n        \"bool_of_string|bounded_full_split|bounded_split|bounded_split_delim|\" +\n        \"bprintf|break|broadcast|bscanf|button_down|c_layout|capitalize|cardinal|\" +\n        \"cardinal|catch|catch_break|ceil|ceiling_num|channel|char|char_of_int|\" +\n        \"chdir|check|check_suffix|chmod|choose|chop_extension|chop_suffix|chown|\" +\n        \"chown|chr|chroot|classify_float|clear|clear_available_units|\" +\n        \"clear_close_on_exec|clear_graph|clear_nonblock|clear_parser|\" +\n        \"close|close|closeTk|close_box|close_graph|close_in|close_in_noerr|\" +\n        \"close_out|close_out_noerr|close_process|close_process|\" +\n        \"close_process_full|close_process_in|close_process_out|close_subwindow|\" +\n        \"close_tag|close_tbox|closedir|closedir|closure_tag|code|combine|\" +\n        \"combine|combine|command|compact|compare|compare_big_int|compare_num|\" +\n        \"complex32|complex64|concat|conj|connect|contains|contains_from|contents|\" +\n        \"copy|cos|cosh|count|count|counters|create|create_alarm|create_image|\" +\n        \"create_matrix|create_matrix|create_matrix|create_object|\" +\n        \"create_object_and_run_initializers|create_object_opt|create_process|\" +\n        \"create_process|create_process_env|create_process_env|create_table|\" +\n        \"current|current_dir_name|current_point|current_x|current_y|curveto|\" +\n        \"custom_tag|cyan|data_size|decr|decr_num|default_available_units|delay|\" +\n        \"delete_alarm|descr_of_in_channel|descr_of_out_channel|destroy|diff|dim|\" +\n        \"dim1|dim2|dim3|dims|dirname|display_mode|div|div_big_int|div_num|\" +\n        \"double_array_tag|double_tag|draw_arc|draw_char|draw_circle|draw_ellipse|\" +\n        \"draw_image|draw_poly|draw_poly_line|draw_rect|draw_segments|draw_string|\" +\n        \"dummy_pos|dummy_table|dump_image|dup|dup2|elements|empty|end_of_input|\" +\n        \"environment|eprintf|epsilon_float|eq_big_int|eq_num|equal|err_formatter|\" +\n        \"error_message|escaped|establish_server|executable_name|execv|execve|execvp|\" +\n        \"execvpe|exists|exists2|exit|exp|failwith|fast_sort|fchmod|fchown|field|\" +\n        \"file|file_exists|fill|fill_arc|fill_circle|fill_ellipse|fill_poly|fill_rect|\" +\n        \"filter|final_tag|finalise|find|find_all|first_chars|firstkey|flatten|\" +\n        \"float|float32|float64|float_of_big_int|float_of_bits|float_of_int|\" +\n        \"float_of_num|float_of_string|floor|floor_num|flush|flush_all|flush_input|\" +\n        \"flush_str_formatter|fold|fold_left|fold_left2|fold_right|fold_right2|\" +\n        \"for_all|for_all2|force|force_newline|force_val|foreground|fork|\" +\n        \"format_of_string|formatter_of_buffer|formatter_of_out_channel|\" +\n        \"fortran_layout|forward_tag|fprintf|frexp|from|from_channel|from_file|\" +\n        \"from_file_bin|from_function|from_string|fscanf|fst|fstat|ftruncate|\" +\n        \"full_init|full_major|full_split|gcd_big_int|ge_big_int|ge_num|\" +\n        \"genarray_of_array1|genarray_of_array2|genarray_of_array3|get|\" +\n        \"get_all_formatter_output_functions|get_approx_printing|get_copy|\" +\n        \"get_ellipsis_text|get_error_when_null_denominator|get_floating_precision|\" +\n        \"get_formatter_output_functions|get_formatter_tag_functions|get_image|\" +\n        \"get_margin|get_mark_tags|get_max_boxes|get_max_indent|get_method|\" +\n        \"get_method_label|get_normalize_ratio|get_normalize_ratio_when_printing|\" +\n        \"get_print_tags|get_state|get_variable|getcwd|getegid|getegid|getenv|\" +\n        \"getenv|getenv|geteuid|geteuid|getgid|getgid|getgrgid|getgrgid|getgrnam|\" +\n        \"getgrnam|getgroups|gethostbyaddr|gethostbyname|gethostname|getitimer|\" +\n        \"getlogin|getpeername|getpid|getppid|getprotobyname|getprotobynumber|\" +\n        \"getpwnam|getpwuid|getservbyname|getservbyport|getsockname|getsockopt|\" +\n        \"getsockopt_float|getsockopt_int|getsockopt_optint|gettimeofday|getuid|\" +\n        \"global_replace|global_substitute|gmtime|green|grid|group_beginning|\" +\n        \"group_end|gt_big_int|gt_num|guard|handle_unix_error|hash|hash_param|\" +\n        \"hd|header_size|i|id|ignore|in_channel_length|in_channel_of_descr|incr|\" +\n        \"incr_num|index|index_from|inet_addr_any|inet_addr_of_string|infinity|\" +\n        \"infix_tag|init|init_class|input|input_binary_int|input_byte|input_char|\" +\n        \"input_line|input_value|int|int16_signed|int16_unsigned|int32|int64|\" +\n        \"int8_signed|int8_unsigned|int_of_big_int|int_of_char|int_of_float|\" +\n        \"int_of_num|int_of_string|integer_num|inter|interactive|inv|invalid_arg|\" +\n        \"is_block|is_empty|is_implicit|is_int|is_int_big_int|is_integer_num|\" +\n        \"is_relative|iter|iter2|iteri|join|junk|key_pressed|kill|kind|kprintf|\" +\n        \"kscanf|land|last_chars|layout|lazy_from_fun|lazy_from_val|lazy_is_val|\" +\n        \"lazy_tag|ldexp|le_big_int|le_num|length|lexeme|lexeme_char|lexeme_end|\" +\n        \"lexeme_end_p|lexeme_start|lexeme_start_p|lineto|link|list|listen|lnot|\" +\n        \"loadfile|loadfile_private|localtime|lock|lockf|log|log10|logand|lognot|\" +\n        \"logor|logxor|lor|lower_window|lowercase|lseek|lsl|lsr|lstat|lt_big_int|\" +\n        \"lt_num|lxor|magenta|magic|mainLoop|major|major_slice|make|make_formatter|\" +\n        \"make_image|make_lexer|make_matrix|make_self_init|map|map2|map_file|mapi|\" +\n        \"marshal|match_beginning|match_end|matched_group|matched_string|max|\" +\n        \"max_array_length|max_big_int|max_elt|max_float|max_int|max_num|\" +\n        \"max_string_length|mem|mem_assoc|mem_assq|memq|merge|min|min_big_int|\" +\n        \"min_elt|min_float|min_int|min_num|minor|minus_big_int|minus_num|\" +\n        \"minus_one|mkdir|mkfifo|mktime|mod|mod_big_int|mod_float|mod_num|modf|\" +\n        \"mouse_pos|moveto|mul|mult_big_int|mult_int_big_int|mult_num|nan|narrow|\" +\n        \"nat_of_num|nativeint|neg|neg_infinity|new_block|new_channel|new_method|\" +\n        \"new_variable|next|nextkey|nice|nice|no_scan_tag|norm|norm2|not|npeek|\" +\n        \"nth|nth_dim|num_digits_big_int|num_dims|num_of_big_int|num_of_int|\" +\n        \"num_of_nat|num_of_ratio|num_of_string|O|obj|object_tag|ocaml_version|\" +\n        \"of_array|of_channel|of_float|of_int|of_int32|of_list|of_nativeint|\" +\n        \"of_string|one|openTk|open_box|open_connection|open_graph|open_hbox|\" +\n        \"open_hovbox|open_hvbox|open_in|open_in_bin|open_in_gen|open_out|\" +\n        \"open_out_bin|open_out_gen|open_process|open_process_full|open_process_in|\" +\n        \"open_process_out|open_subwindow|open_tag|open_tbox|open_temp_file|\" +\n        \"open_vbox|opendbm|opendir|openfile|or|os_type|out_channel_length|\" +\n        \"out_channel_of_descr|output|output_binary_int|output_buffer|output_byte|\" +\n        \"output_char|output_string|output_value|over_max_boxes|pack|params|\" +\n        \"parent_dir_name|parse|parse_argv|partition|pause|peek|pipe|pixels|\" +\n        \"place|plot|plots|point_color|polar|poll|pop|pos_in|pos_out|pow|\" +\n        \"power_big_int_positive_big_int|power_big_int_positive_int|\" +\n        \"power_int_positive_big_int|power_int_positive_int|power_num|\" +\n        \"pp_close_box|pp_close_tag|pp_close_tbox|pp_force_newline|\" +\n        \"pp_get_all_formatter_output_functions|pp_get_ellipsis_text|\" +\n        \"pp_get_formatter_output_functions|pp_get_formatter_tag_functions|\" +\n        \"pp_get_margin|pp_get_mark_tags|pp_get_max_boxes|pp_get_max_indent|\" +\n        \"pp_get_print_tags|pp_open_box|pp_open_hbox|pp_open_hovbox|pp_open_hvbox|\" +\n        \"pp_open_tag|pp_open_tbox|pp_open_vbox|pp_over_max_boxes|pp_print_as|\" +\n        \"pp_print_bool|pp_print_break|pp_print_char|pp_print_cut|pp_print_float|\" +\n        \"pp_print_flush|pp_print_if_newline|pp_print_int|pp_print_newline|\" +\n        \"pp_print_space|pp_print_string|pp_print_tab|pp_print_tbreak|\" +\n        \"pp_set_all_formatter_output_functions|pp_set_ellipsis_text|\" +\n        \"pp_set_formatter_out_channel|pp_set_formatter_output_functions|\" +\n        \"pp_set_formatter_tag_functions|pp_set_margin|pp_set_mark_tags|\" +\n        \"pp_set_max_boxes|pp_set_max_indent|pp_set_print_tags|pp_set_tab|\" +\n        \"pp_set_tags|pred|pred_big_int|pred_num|prerr_char|prerr_endline|\" +\n        \"prerr_float|prerr_int|prerr_newline|prerr_string|print|print_as|\" +\n        \"print_bool|print_break|print_char|print_cut|print_endline|print_float|\" +\n        \"print_flush|print_if_newline|print_int|print_newline|print_space|\" +\n        \"print_stat|print_string|print_tab|print_tbreak|printf|prohibit|\" +\n        \"public_method_label|push|putenv|quo_num|quomod_big_int|quote|raise|\" +\n        \"raise_window|ratio_of_num|rcontains_from|read|read_float|read_int|\" +\n        \"read_key|read_line|readdir|readdir|readlink|really_input|receive|recv|\" +\n        \"recvfrom|red|ref|regexp|regexp_case_fold|regexp_string|\" +\n        \"regexp_string_case_fold|register|register_exception|rem|remember_mode|\" +\n        \"remove|remove_assoc|remove_assq|rename|replace|replace_first|\" +\n        \"replace_matched|repr|reset|reshape|reshape_1|reshape_2|reshape_3|rev|\" +\n        \"rev_append|rev_map|rev_map2|rewinddir|rgb|rhs_end|rhs_end_pos|rhs_start|\" +\n        \"rhs_start_pos|rindex|rindex_from|rlineto|rmdir|rmoveto|round_num|\" +\n        \"run_initializers|run_initializers_opt|scanf|search_backward|\" +\n        \"search_forward|seek_in|seek_out|select|self|self_init|send|sendto|set|\" +\n        \"set_all_formatter_output_functions|set_approx_printing|\" +\n        \"set_binary_mode_in|set_binary_mode_out|set_close_on_exec|\" +\n        \"set_close_on_exec|set_color|set_ellipsis_text|\" +\n        \"set_error_when_null_denominator|set_field|set_floating_precision|\" +\n        \"set_font|set_formatter_out_channel|set_formatter_output_functions|\" +\n        \"set_formatter_tag_functions|set_line_width|set_margin|set_mark_tags|\" +\n        \"set_max_boxes|set_max_indent|set_method|set_nonblock|set_nonblock|\" +\n        \"set_normalize_ratio|set_normalize_ratio_when_printing|set_print_tags|\" +\n        \"set_signal|set_state|set_tab|set_tag|set_tags|set_text_size|\" +\n        \"set_window_title|setgid|setgid|setitimer|setitimer|setsid|setsid|\" +\n        \"setsockopt|setsockopt|setsockopt_float|setsockopt_float|setsockopt_int|\" +\n        \"setsockopt_int|setsockopt_optint|setsockopt_optint|setuid|setuid|\" +\n        \"shift_left|shift_left|shift_left|shift_right|shift_right|shift_right|\" +\n        \"shift_right_logical|shift_right_logical|shift_right_logical|show_buckets|\" +\n        \"shutdown|shutdown|shutdown_connection|shutdown_connection|sigabrt|\" +\n        \"sigalrm|sigchld|sigcont|sigfpe|sighup|sigill|sigint|sigkill|sign_big_int|\" +\n        \"sign_num|signal|signal|sigpending|sigpending|sigpipe|sigprocmask|\" +\n        \"sigprocmask|sigprof|sigquit|sigsegv|sigstop|sigsuspend|sigsuspend|\" +\n        \"sigterm|sigtstp|sigttin|sigttou|sigusr1|sigusr2|sigvtalrm|sin|singleton|\" +\n        \"sinh|size|size|size_x|size_y|sleep|sleep|sleep|slice_left|slice_left|\" +\n        \"slice_left_1|slice_left_2|slice_right|slice_right|slice_right_1|\" +\n        \"slice_right_2|snd|socket|socket|socket|socketpair|socketpair|sort|sound|\" +\n        \"split|split_delim|sprintf|sprintf|sqrt|sqrt|sqrt_big_int|square_big_int|\" +\n        \"square_num|sscanf|stable_sort|stable_sort|stable_sort|stable_sort|stable_sort|\" +\n        \"stable_sort|stat|stat|stat|stat|stat|stats|stats|std_formatter|stdbuf|\" +\n        \"stderr|stderr|stderr|stdib|stdin|stdin|stdin|stdout|stdout|stdout|\" +\n        \"str_formatter|string|string_after|string_before|string_match|\" +\n        \"string_of_big_int|string_of_bool|string_of_float|string_of_format|\" +\n        \"string_of_inet_addr|string_of_inet_addr|string_of_int|string_of_num|\" +\n        \"string_partial_match|string_tag|sub|sub|sub_big_int|sub_left|sub_num|\" +\n        \"sub_right|subset|subset|substitute_first|substring|succ|succ|\" +\n        \"succ|succ|succ_big_int|succ_num|symbol_end|symbol_end_pos|symbol_start|\" +\n        \"symbol_start_pos|symlink|symlink|sync|synchronize|system|system|system|\" +\n        \"tag|take|tan|tanh|tcdrain|tcdrain|tcflow|tcflow|tcflush|tcflush|\" +\n        \"tcgetattr|tcgetattr|tcsendbreak|tcsendbreak|tcsetattr|tcsetattr|\" +\n        \"temp_file|text_size|time|time|time|timed_read|timed_write|times|times|\" +\n        \"tl|tl|tl|to_buffer|to_channel|to_float|to_hex|to_int|to_int32|to_list|\" +\n        \"to_list|to_list|to_nativeint|to_string|to_string|to_string|to_string|\" +\n        \"to_string|top|top|total_size|transfer|transp|truncate|truncate|truncate|\" +\n        \"truncate|truncate|truncate|try_lock|umask|umask|uncapitalize|uncapitalize|\" +\n        \"uncapitalize|union|union|unit_big_int|unlink|unlink|unlock|unmarshal|\" +\n        \"unsafe_blit|unsafe_fill|unsafe_get|unsafe_get|unsafe_set|unsafe_set|\" +\n        \"update|uppercase|uppercase|uppercase|uppercase|usage|utimes|utimes|wait|\" +\n        \"wait|wait|wait|wait_next_event|wait_pid|wait_read|wait_signal|\" +\n        \"wait_timed_read|wait_timed_write|wait_write|waitpid|white|\" +\n        \"widen|window_id|word_size|wrap|wrap_abort|write|yellow|yield|zero|zero_big_int|\" +\n\n        \"Arg|Arith_status|Array|Array1|Array2|Array3|ArrayLabels|Big_int|Bigarray|\" +\n        \"Buffer|Callback|CamlinternalOO|Char|Complex|Condition|Dbm|Digest|Dynlink|\" +\n        \"Event|Filename|Format|Gc|Genarray|Genlex|Graphics|GraphicsX11|Hashtbl|\" +\n        \"Int32|Int64|LargeFile|Lazy|Lexing|List|ListLabels|Make|Map|Marshal|\" +\n        \"MoreLabels|Mutex|Nativeint|Num|Obj|Oo|Parsing|Pervasives|Printexc|\" +\n        \"Printf|Queue|Random|Scanf|Scanning|Set|Sort|Stack|State|StdLabels|Str|\" +\n        \"Stream|String|StringLabels|Sys|Thread|ThreadUnix|Tk|Unix|UnixLabels|Weak\"\n    ).split(\"|\"));\n\n    var decimalInteger = \"(?:(?:[1-9]\\\\d*)|(?:0))\";\n    var octInteger = \"(?:0[oO]?[0-7]+)\";\n    var hexInteger = \"(?:0[xX][\\\\dA-Fa-f]+)\";\n    var binInteger = \"(?:0[bB][01]+)\";\n    var integer = \"(?:\" + decimalInteger + \"|\" + octInteger + \"|\" + hexInteger + \"|\" + binInteger + \")\";\n\n    var exponent = \"(?:[eE][+-]?\\\\d+)\";\n    var fraction = \"(?:\\\\.\\\\d+)\";\n    var intPart = \"(?:\\\\d+)\";\n    var pointFloat = \"(?:(?:\" + intPart + \"?\" + fraction + \")|(?:\" + intPart + \"\\\\.))\";\n    var exponentFloat = \"(?:(?:\" + pointFloat + \"|\" +  intPart + \")\" + exponent + \")\";\n    var floatNumber = \"(?:\" + exponentFloat + \"|\" + pointFloat + \")\";\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : '\\\\(\\\\*.*?\\\\*\\\\)\\\\s*?$'\n            },\n            {\n                token : \"comment\",\n                merge : true,\n                regex : '\\\\(\\\\*.*',\n                next : \"comment\"\n            },\n            {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            },\n            {\n                token : \"string\", // single char\n                regex : \"'.'\"\n            },\n            {\n                token : \"string\", // \" string\n                merge : true,\n                regex : '\"',\n                next  : \"qstring\"\n            },\n            {\n                token : \"constant.numeric\", // imaginary\n                regex : \"(?:\" + floatNumber + \"|\\\\d+)[jJ]\\\\b\"\n            },\n            {\n                token : \"constant.numeric\", // float\n                regex : floatNumber\n            },\n            {\n                token : \"constant.numeric\", // integer\n                regex : integer + \"\\\\b\"\n            },\n            {\n                token : function(value) {\n                    if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (builtinConstants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else if (builtinFunctions.hasOwnProperty(value))\n                        return \"support.function\";\n                    else\n                        return \"identifier\";\n                },\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n            },\n            {\n                token : \"keyword.operator\",\n                regex : \"\\\\+\\\\.|\\\\-\\\\.|\\\\*\\\\.|\\\\/\\\\.|#|;;|\\\\+|\\\\-|\\\\*|\\\\*\\\\*\\\\/|\\\\/\\\\/|%|<<|>>|&|\\\\||\\\\^|~|<|>|<=|=>|==|!=|<>|<-|=\"\n            },\n            {\n                token : \"paren.lparen\",\n                regex : \"[[({]\"\n            },\n            {\n                token : \"paren.rparen\",\n                regex : \"[\\\\])}]\"\n            },\n            {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\)\",\n                next : \"start\"\n            },\n            {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ],\n\n        \"qstring\" : [\n            {\n                token : \"string\",\n                regex : '\"',\n                next : \"start\"\n            }, {\n                token : \"string\",\n                merge : true,\n                regex : '.+'\n            }\n        ]\n    };\n};\n\noop.inherits(OcamlHighlightRules, TextHighlightRules);\n\nexports.OcamlHighlightRules = OcamlHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/perl.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Panagiotis Astithas <pastith AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar PerlHighlightRules = require(\"./perl_highlight_rules\").PerlHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar Range = require(\"../range\").Range;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new PerlHighlightRules().getRules());\n    this.$outdent = new MatchingBraceOutdent();\n    this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        var outdent = true;\n        var re = /^(\\s*)#/;\n\n        for (var i=startRow; i<= endRow; i++) {\n            if (!re.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        if (outdent) {\n            var deleteRange = new Range(0, 0, 0, 0);\n            for (var i=startRow; i<= endRow; i++)\n            {\n                var line = doc.getLine(i);\n                var m = line.match(re);\n                deleteRange.start.row = i;\n                deleteRange.end.row = i;\n                deleteRange.end.column = m[0].length;\n                doc.replace(deleteRange, m[1]);\n            }\n        }\n        else {\n            doc.indentRows(startRow, endRow, \"#\");\n        }\n    };\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n\n        if (state == \"start\") {\n            var match = line.match(/^.*[\\{\\(\\[\\:]\\s*$/);\n            if (match) {\n                indent += tab;\n            }\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/perl_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Panagiotis Astithas <pastith AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar PerlHighlightRules = function() {\n\n    var keywords = lang.arrayToMap(\n        (\"base|constant|continue|else|elsif|for|foreach|format|goto|if|last|local|my|next|\" +\n         \"no|package|parent|redo|require|scalar|sub|unless|until|while|use|vars\").split(\"|\")\n    );\n\n    var buildinConstants = lang.arrayToMap(\n        (\"ARGV|ENV|INC|SIG\").split(\"|\")\n    );\n\n    var builtinFunctions = lang.arrayToMap(\n        (\"getprotobynumber|getprotobyname|getservbyname|gethostbyaddr|\" +\n         \"gethostbyname|getservbyport|getnetbyaddr|getnetbyname|getsockname|\" +\n         \"getpeername|setpriority|getprotoent|setprotoent|getpriority|\" +\n         \"endprotoent|getservent|setservent|endservent|sethostent|socketpair|\" +\n         \"getsockopt|gethostent|endhostent|setsockopt|setnetent|quotemeta|\" +\n         \"localtime|prototype|getnetent|endnetent|rewinddir|wantarray|getpwuid|\" +\n         \"closedir|getlogin|readlink|endgrent|getgrgid|getgrnam|shmwrite|\" +\n         \"shutdown|readline|endpwent|setgrent|readpipe|formline|truncate|\" +\n         \"dbmclose|syswrite|setpwent|getpwnam|getgrent|getpwent|ucfirst|sysread|\" +\n         \"setpgrp|shmread|sysseek|sysopen|telldir|defined|opendir|connect|\" +\n         \"lcfirst|getppid|binmode|syscall|sprintf|getpgrp|readdir|seekdir|\" +\n         \"waitpid|reverse|unshift|symlink|dbmopen|semget|msgrcv|rename|listen|\" +\n         \"chroot|msgsnd|shmctl|accept|unpack|exists|fileno|shmget|system|\" +\n         \"unlink|printf|gmtime|msgctl|semctl|values|rindex|substr|splice|\" +\n         \"length|msgget|select|socket|return|caller|delete|alarm|ioctl|index|\" +\n         \"undef|lstat|times|srand|chown|fcntl|close|write|umask|rmdir|study|\" +\n         \"sleep|chomp|untie|print|utime|mkdir|atan2|split|crypt|flock|chmod|\" +\n         \"BEGIN|bless|chdir|semop|shift|reset|link|stat|chop|grep|fork|dump|\" +\n         \"join|open|tell|pipe|exit|glob|warn|each|bind|sort|pack|eval|push|\" +\n         \"keys|getc|kill|seek|sqrt|send|wait|rand|tied|read|time|exec|recv|\" +\n         \"eof|chr|int|ord|exp|pos|pop|sin|log|abs|oct|hex|tie|cos|vec|END|ref|\" +\n         \"map|die|uc|lc|do\").split(\"|\")\n    );\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \"#.*$\"\n            }, {\n                token : \"string.regexp\",\n                regex : \"[/](?:(?:\\\\[(?:\\\\\\\\]|[^\\\\]])+\\\\])|(?:\\\\\\\\/|[^\\\\]/]))*[/]\\\\w*\\\\s*(?=[).,;]|$)\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // multi line string start\n                merge : true,\n                regex : '[\"].*\\\\\\\\$',\n                next : \"qqstring\"\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"string\", // multi line string start\n                merge : true,\n                regex : \"['].*\\\\\\\\$\",\n                next : \"qstring\"\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0x[0-9a-fA-F]+\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n                token : function(value) {\n                    if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (buildinConstants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else if (builtinFunctions.hasOwnProperty(value))\n                        return \"support.function\";\n                    else\n                        return \"identifier\";\n                },\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"\\\\.\\\\.\\\\.|\\\\|\\\\|=|>>=|<<=|<=>|&&=|=>|!~|\\\\^=|&=|\\\\|=|\\\\.=|x=|%=|\\\\/=|\\\\*=|\\\\-=|\\\\+=|=~|\\\\*\\\\*|\\\\-\\\\-|\\\\.\\\\.|\\\\|\\\\||&&|\\\\+\\\\+|\\\\->|!=|==|>=|<=|>>|<<|,|=|\\\\?\\\\:|\\\\^|\\\\||x|%|\\\\/|\\\\*|<|&|\\\\\\\\|~|!|>|\\\\.|\\\\-|\\\\+|\\\\-C|\\\\-b|\\\\-S|\\\\-u|\\\\-t|\\\\-p|\\\\-l|\\\\-d|\\\\-f|\\\\-g|\\\\-s|\\\\-z|\\\\-k|\\\\-e|\\\\-O|\\\\-T|\\\\-B|\\\\-M|\\\\-A|\\\\-X|\\\\-W|\\\\-c|\\\\-R|\\\\-o|\\\\-x|\\\\-w|\\\\-r|\\\\b(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|xor)\"\n            }, {\n                token : \"lparen\",\n                regex : \"[[({]\"\n            }, {\n                token : \"rparen\",\n                regex : \"[\\\\])}]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"qqstring\" : [\n            {\n                token : \"string\",\n                regex : '(?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?\"',\n                next : \"start\"\n            }, {\n                token : \"string\",\n                merge : true,\n                regex : '.+'\n            }\n        ],\n        \"qstring\" : [\n            {\n                token : \"string\",\n                regex : \"(?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?'\",\n                next : \"start\"\n            }, {\n                token : \"string\",\n                merge : true,\n                regex : '.+'\n            }\n        ]\n    };\n};\n\noop.inherits(PerlHighlightRules, TextHighlightRules);\n\nexports.PerlHighlightRules = PerlHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/pgsql.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n* The Original Code is Ajax.org Code Editor (ACE).\n*\n* Contributor(s):\n*      Jonathan Camile <jonathan.camile AT gmail DOT com>\n*\n* Alternatively, the contents of this file may be used under the terms of\n* either the GNU General Public License Version 2 or later (the \"GPL\"), or\n* the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n* in which case the provisions of the GPL or the LGPL are applicable instead\n* of those above. If you wish to allow use of your version of this file only\n* under the terms of either the GPL or the LGPL, and not to allow others to\n* use your version of this file under the terms of the MPL, indicate your\n* decision by deleting the provisions above and replace them with the notice\n* and other provisions required by the GPL or the LGPL. If you do not delete\n* the provisions above, a recipient may use your version of this file under\n* the terms of any one of the MPL, the GPL or the LGPL.\n*\n* ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\n    var oop = require(\"ace/lib/oop\");\n    var TextMode = require(\"ace/mode/text\").Mode;\n    var Tokenizer = require(\"ace/tokenizer\").Tokenizer;\n    var PgsqlHighlightRules = require(\"ace/mode/pgsql_highlight_rules\").PgsqlHighlightRules;\n    var Range = require(\"ace/range\").Range;\n    // var EditSession = require(\"ace/edit_session\").EditSession;\n\n    var Mode = function() {\n        this.$tokenizer = new Tokenizer(new PgsqlHighlightRules().getRules());\n    };\n    oop.inherits(Mode, TextMode);\n\n    (function() {\n\n        this.toggleCommentLines = function(state, doc, startRow, endRow) {\n            var outdent = true;\n            // var outentedRows = [];\n            var re = /^(\\s*)--/;\n\n            for (var i=startRow; i<= endRow; i++) {\n                if (!re.test(doc.getLine(i))) {\n                    outdent = false;\n                    break;\n                }\n            }\n\n            if (outdent) {\n                var deleteRange = new Range(0, 0, 0, 0);\n                for (var i=startRow; i<= endRow; i++)\n                {\n                    var line = doc.getLine(i);\n                    var m = line.match(re);\n                    deleteRange.start.row = i;\n                    deleteRange.end.row = i;\n                    deleteRange.end.column = m[0].length;\n                    doc.replace(deleteRange, m[1]);\n                }\n            }\n            else {\n                doc.indentRows(startRow, endRow, \"--\");\n            }\n        };\n\n\n        this.getNextLineIndent = function(state, line, tab) { \n            if (state == \"start\" || state == \"keyword.statementEnd\") {\n                return \"\";\n            } else {\n                return this.$getIndent(line); // Keep whatever indent the previous line has\n            }\n        }\n\n    }).call(Mode.prototype);\n\n    exports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/pgsql_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * Contributor(s):\n *      John DeSoi, Ph.D. <desoi AT pgedit DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK *****\n *\n */\n\n\ndefine(function(require, exports, module) {\n\nvar oop = require(\"ace/lib/oop\");\nvar lang = require(\"ace/lib/lang\");\nvar DocCommentHighlightRules = require(\"./doc_comment_highlight_rules\").DocCommentHighlightRules;\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n// Supporting perl and python for now -- both in pg core and ace\nvar PerlHighlightRules = require(\"./perl_highlight_rules\").PerlHighlightRules;\nvar PythonHighlightRules = require(\"./python_highlight_rules\").PythonHighlightRules;\n\nvar PgsqlHighlightRules = function() {\n    \n    // Keywords, functions, operators last updated for pg 9.1.\n    var keywords = lang.arrayToMap(\n        (\"abort|absolute|abstime|access|aclitem|action|add|admin|after|aggregate|all|also|alter|always|\" +\n        \"analyse|analyze|and|any|anyarray|anyelement|anyenum|anynonarray|array|as|asc|assertion|\" +\n        \"assignment|asymmetric|at|attribute|authorization|backward|before|begin|between|bigint|\" +\n        \"binary|bit|bool|boolean|both|box|bpchar|by|bytea|cache|called|cascade|cascaded|case|cast|\" +\n        \"catalog|chain|char|character|characteristics|check|checkpoint|cid|cidr|circle|class|close|\" +\n        \"cluster|coalesce|collate|collation|column|comment|comments|commit|committed|concurrently|\" +\n        \"configuration|connection|constraint|constraints|content|continue|conversion|copy|cost|\" +\n        \"create|cross|cstring|csv|current|current_catalog|current_date|current_role|\" +\n        \"current_schema|current_time|current_timestamp|current_user|cursor|cycle|data|database|\" +\n        \"date|day|deallocate|dec|decimal|declare|default|defaults|deferrable|deferred|definer|delete|\" +\n        \"delimiter|delimiters|desc|dictionary|disable|discard|distinct|do|document|domain|double|\" +\n        \"drop|each|else|enable|encoding|encrypted|end|enum|escape|except|exclude|excluding|exclusive|\" +\n        \"execute|exists|explain|extension|external|extract|false|family|fdw_handler|fetch|first|\" +\n        \"float|float4|float8|following|for|force|foreign|forward|freeze|from|full|function|functions|\" +\n        \"global|grant|granted|greatest|group|gtsvector|handler|having|header|hold|hour|identity|if|\" +\n        \"ilike|immediate|immutable|implicit|in|including|increment|index|indexes|inet|inherit|\" +\n        \"inherits|initially|inline|inner|inout|input|insensitive|insert|instead|int|int2|int2vector|\" +\n        \"int4|int8|integer|internal|intersect|interval|into|invoker|is|isnull|isolation|join|key|label|\" +\n        \"language|language_handler|large|last|lc_collate|lc_ctype|leading|least|left|level|like|\" +\n        \"limit|line|listen|load|local|localtime|localtimestamp|location|lock|lseg|macaddr|mapping|\" +\n        \"match|maxvalue|minute|minvalue|mode|money|month|move|name|names|national|natural|nchar|next|no|\" +\n        \"none|not|nothing|notify|notnull|nowait|null|nullif|nulls|numeric|object|of|off|offset|oid|oids|\" +\n        \"oidvector|on|only|opaque|operator|option|options|or|order|out|outer|over|overlaps|overlay|\" +\n        \"owned|owner|parser|partial|partition|passing|password|path|pg_attribute|pg_auth_members|\" +\n        \"pg_authid|pg_class|pg_database|pg_node_tree|pg_proc|pg_type|placing|plans|point|polygon|\" +\n        \"position|preceding|precision|prepare|prepared|preserve|primary|prior|privileges|\" +\n        \"procedural|procedure|quote|range|read|real|reassign|recheck|record|recursive|ref|refcursor|\" +\n        \"references|regclass|regconfig|regdictionary|regoper|regoperator|regproc|regprocedure|\" +\n        \"regtype|reindex|relative|release|reltime|rename|repeatable|replace|replica|reset|restart|\" +\n        \"restrict|returning|returns|revoke|right|role|rollback|row|rows|rule|savepoint|schema|scroll|\" +\n        \"search|second|security|select|sequence|sequences|serializable|server|session|session_user|\" +\n        \"set|setof|share|show|similar|simple|smallint|smgr|some|stable|standalone|start|statement|\" +\n        \"statistics|stdin|stdout|storage|strict|strip|substring|symmetric|sysid|system|table|tables|\" +\n        \"tablespace|temp|template|temporary|text|then|tid|time|timestamp|timestamptz|timetz|\" +\n        \"tinterval|to|trailing|transaction|treat|trigger|trim|true|truncate|trusted|tsquery|tsvector|\" +\n        \"txid_snapshot|type|unbounded|uncommitted|unencrypted|union|unique|unknown|unlisten|\" +\n        \"unlogged|until|update|user|using|uuid|vacuum|valid|validate|validator|value|values|varbit|\" +\n        \"varchar|variadic|varying|verbose|version|view|void|volatile|when|where|whitespace|window|\" +\n        \"with|without|work|wrapper|write|xid|xml|xmlattributes|xmlconcat|xmlelement|xmlexists|\" +\n        \"xmlforest|xmlparse|xmlpi|xmlroot|xmlserialize|year|yes|zone\").split(\"|\")\n    );\n    \n    \n    var builtinFunctions = lang.arrayToMap(\n        (\"RI_FKey_cascade_del|RI_FKey_cascade_upd|RI_FKey_check_ins|RI_FKey_check_upd|\" +\n        \"RI_FKey_noaction_del|RI_FKey_noaction_upd|RI_FKey_restrict_del|RI_FKey_restrict_upd|\" +\n        \"RI_FKey_setdefault_del|RI_FKey_setdefault_upd|RI_FKey_setnull_del|\" +\n        \"RI_FKey_setnull_upd|abbrev|abs|abstime|abstimeeq|abstimege|abstimegt|abstimein|abstimele|\" +\n        \"abstimelt|abstimene|abstimeout|abstimerecv|abstimesend|aclcontains|aclexplode|aclinsert|\" +\n        \"aclitemeq|aclitemin|aclitemout|aclremove|acos|age|any_in|any_out|anyarray_in|anyarray_out|\" +\n        \"anyarray_recv|anyarray_send|anyelement_in|anyelement_out|anyenum_in|anyenum_out|\" +\n        \"anynonarray_in|anynonarray_out|anytextcat|area|areajoinsel|areasel|array_agg|\" +\n        \"array_agg_finalfn|array_agg_transfn|array_append|array_cat|array_dims|array_eq|\" +\n        \"array_fill|array_ge|array_gt|array_in|array_larger|array_le|array_length|array_lower|\" +\n        \"array_lt|array_ndims|array_ne|array_out|array_prepend|array_recv|array_send|\" +\n        \"array_smaller|array_to_string|array_upper|arraycontained|arraycontains|arrayoverlap|\" +\n        \"ascii|ascii_to_mic|ascii_to_utf8|asin|atan|atan2|avg|big5_to_euc_tw|big5_to_mic|\" +\n        \"big5_to_utf8|bit_and|bit_in|bit_length|bit_or|bit_out|bit_recv|bit_send|bitand|bitcat|\" +\n        \"bitcmp|biteq|bitge|bitgt|bitle|bitlt|bitne|bitnot|bitor|bitshiftleft|bitshiftright|\" +\n        \"bittypmodin|bittypmodout|bitxor|bool|bool_and|bool_or|booland_statefunc|booleq|boolge|\" +\n        \"boolgt|boolin|boolle|boollt|boolne|boolor_statefunc|boolout|boolrecv|boolsend|box|\" +\n        \"box_above|box_above_eq|box_add|box_below|box_below_eq|box_center|box_contain|\" +\n        \"box_contain_pt|box_contained|box_distance|box_div|box_eq|box_ge|box_gt|box_in|\" +\n        \"box_intersect|box_le|box_left|box_lt|box_mul|box_out|box_overabove|box_overbelow|\" +\n        \"box_overlap|box_overleft|box_overright|box_recv|box_right|box_same|box_send|box_sub|\" +\n        \"bpchar_larger|bpchar_pattern_ge|bpchar_pattern_gt|bpchar_pattern_le|\" +\n        \"bpchar_pattern_lt|bpchar_smaller|bpcharcmp|bpchareq|bpcharge|bpchargt|bpchariclike|\" +\n        \"bpcharicnlike|bpcharicregexeq|bpcharicregexne|bpcharin|bpcharle|bpcharlike|bpcharlt|\" +\n        \"bpcharne|bpcharnlike|bpcharout|bpcharrecv|bpcharregexeq|bpcharregexne|bpcharsend|\" +\n        \"bpchartypmodin|bpchartypmodout|broadcast|btabstimecmp|btarraycmp|btbeginscan|btboolcmp|\" +\n        \"btbpchar_pattern_cmp|btbuild|btbuildempty|btbulkdelete|btcharcmp|btcostestimate|\" +\n        \"btendscan|btfloat48cmp|btfloat4cmp|btfloat84cmp|btfloat8cmp|btgetbitmap|btgettuple|\" +\n        \"btinsert|btint24cmp|btint28cmp|btint2cmp|btint42cmp|btint48cmp|btint4cmp|btint82cmp|\" +\n        \"btint84cmp|btint8cmp|btmarkpos|btnamecmp|btoidcmp|btoidvectorcmp|btoptions|btrecordcmp|\" +\n        \"btreltimecmp|btrescan|btrestrpos|btrim|bttext_pattern_cmp|bttextcmp|bttidcmp|\" +\n        \"bttintervalcmp|btvacuumcleanup|byteacat|byteacmp|byteaeq|byteage|byteagt|byteain|byteale|\" +\n        \"bytealike|bytealt|byteane|byteanlike|byteaout|bytearecv|byteasend|cash_cmp|cash_div_cash|\" +\n        \"cash_div_flt4|cash_div_flt8|cash_div_int2|cash_div_int4|cash_eq|cash_ge|cash_gt|cash_in|\" +\n        \"cash_le|cash_lt|cash_mi|cash_mul_flt4|cash_mul_flt8|cash_mul_int2|cash_mul_int4|cash_ne|\" +\n        \"cash_out|cash_pl|cash_recv|cash_send|cash_words|cashlarger|cashsmaller|cbrt|ceil|ceiling|\" +\n        \"center|char|char_length|character_length|chareq|charge|chargt|charin|charle|charlt|charne|\" +\n        \"charout|charrecv|charsend|chr|cideq|cidin|cidout|cidr|cidr_in|cidr_out|cidr_recv|cidr_send|\" +\n        \"cidrecv|cidsend|circle|circle_above|circle_add_pt|circle_below|circle_center|\" +\n        \"circle_contain|circle_contain_pt|circle_contained|circle_distance|circle_div_pt|\" +\n        \"circle_eq|circle_ge|circle_gt|circle_in|circle_le|circle_left|circle_lt|circle_mul_pt|\" +\n        \"circle_ne|circle_out|circle_overabove|circle_overbelow|circle_overlap|circle_overleft|\" +\n        \"circle_overright|circle_recv|circle_right|circle_same|circle_send|circle_sub_pt|\" +\n        \"clock_timestamp|close_lb|close_ls|close_lseg|close_pb|close_pl|close_ps|close_sb|\" +\n        \"close_sl|col_description|concat|concat_ws|contjoinsel|contsel|convert|convert_from|\" +\n        \"convert_to|corr|cos|cot|count|covar_pop|covar_samp|cstring_in|cstring_out|cstring_recv|\" +\n        \"cstring_send|cume_dist|current_database|current_query|current_schema|current_schemas|\" +\n        \"current_setting|current_user|currtid|currtid2|currval|cursor_to_xml|\" +\n        \"cursor_to_xmlschema|database_to_xml|database_to_xml_and_xmlschema|\" +\n        \"database_to_xmlschema|date|date_cmp|date_cmp_timestamp|date_cmp_timestamptz|date_eq|\" +\n        \"date_eq_timestamp|date_eq_timestamptz|date_ge|date_ge_timestamp|date_ge_timestamptz|\" +\n        \"date_gt|date_gt_timestamp|date_gt_timestamptz|date_in|date_larger|date_le|\" +\n        \"date_le_timestamp|date_le_timestamptz|date_lt|date_lt_timestamp|date_lt_timestamptz|\" +\n        \"date_mi|date_mi_interval|date_mii|date_ne|date_ne_timestamp|date_ne_timestamptz|\" +\n        \"date_out|date_part|date_pl_interval|date_pli|date_recv|date_send|date_smaller|\" +\n        \"date_trunc|datetime_pl|datetimetz_pl|dcbrt|decode|degrees|dense_rank|dexp|diagonal|\" +\n        \"diameter|dispell_init|dispell_lexize|dist_cpoly|dist_lb|dist_pb|dist_pc|dist_pl|\" +\n        \"dist_ppath|dist_ps|dist_sb|dist_sl|div|dlog1|dlog10|domain_in|domain_recv|dpow|dround|\" +\n        \"dsimple_init|dsimple_lexize|dsnowball_init|dsnowball_lexize|dsqrt|dsynonym_init|\" +\n        \"dsynonym_lexize|dtrunc|encode|enum_cmp|enum_eq|enum_first|enum_ge|enum_gt|enum_in|\" +\n        \"enum_larger|enum_last|enum_le|enum_lt|enum_ne|enum_out|enum_range|enum_recv|enum_send|\" +\n        \"enum_smaller|eqjoinsel|eqsel|euc_cn_to_mic|euc_cn_to_utf8|\" +\n        \"euc_jis_2004_to_shift_jis_2004|euc_jis_2004_to_utf8|euc_jp_to_mic|euc_jp_to_sjis|\" +\n        \"euc_jp_to_utf8|euc_kr_to_mic|euc_kr_to_utf8|euc_tw_to_big5|euc_tw_to_mic|\" +\n        \"euc_tw_to_utf8|every|exp|factorial|family|fdw_handler_in|fdw_handler_out|first_value|\" +\n        \"float4|float48div|float48eq|float48ge|float48gt|float48le|float48lt|float48mi|float48mul|\" +\n        \"float48ne|float48pl|float4_accum|float4abs|float4div|float4eq|float4ge|float4gt|float4in|\" +\n        \"float4larger|float4le|float4lt|float4mi|float4mul|float4ne|float4out|float4pl|float4recv|\" +\n        \"float4send|float4smaller|float4um|float4up|float8|float84div|float84eq|float84ge|\" +\n        \"float84gt|float84le|float84lt|float84mi|float84mul|float84ne|float84pl|float8_accum|\" +\n        \"float8_avg|float8_corr|float8_covar_pop|float8_covar_samp|float8_regr_accum|\" +\n        \"float8_regr_avgx|float8_regr_avgy|float8_regr_intercept|float8_regr_r2|\" +\n        \"float8_regr_slope|float8_regr_sxx|float8_regr_sxy|float8_regr_syy|float8_stddev_pop|\" +\n        \"float8_stddev_samp|float8_var_pop|float8_var_samp|float8abs|float8div|float8eq|\" +\n        \"float8ge|float8gt|float8in|float8larger|float8le|float8lt|float8mi|float8mul|float8ne|\" +\n        \"float8out|float8pl|float8recv|float8send|float8smaller|float8um|float8up|floor|\" +\n        \"flt4_mul_cash|flt8_mul_cash|fmgr_c_validator|fmgr_internal_validator|\" +\n        \"fmgr_sql_validator|format|format_type|gb18030_to_utf8|gbk_to_utf8|generate_series|\" +\n        \"generate_subscripts|get_bit|get_byte|get_current_ts_config|getdatabaseencoding|\" +\n        \"getpgusername|gin_cmp_prefix|gin_cmp_tslexeme|gin_extract_tsquery|\" +\n        \"gin_extract_tsvector|gin_tsquery_consistent|ginarrayconsistent|ginarrayextract|\" +\n        \"ginbeginscan|ginbuild|ginbuildempty|ginbulkdelete|gincostestimate|ginendscan|\" +\n        \"gingetbitmap|gininsert|ginmarkpos|ginoptions|ginqueryarrayextract|ginrescan|\" +\n        \"ginrestrpos|ginvacuumcleanup|gist_box_compress|gist_box_consistent|\" +\n        \"gist_box_decompress|gist_box_penalty|gist_box_picksplit|gist_box_same|gist_box_union|\" +\n        \"gist_circle_compress|gist_circle_consistent|gist_point_compress|\" +\n        \"gist_point_consistent|gist_point_distance|gist_poly_compress|gist_poly_consistent|\" +\n        \"gistbeginscan|gistbuild|gistbuildempty|gistbulkdelete|gistcostestimate|gistendscan|\" +\n        \"gistgetbitmap|gistgettuple|gistinsert|gistmarkpos|gistoptions|gistrescan|gistrestrpos|\" +\n        \"gistvacuumcleanup|gtsquery_compress|gtsquery_consistent|gtsquery_decompress|\" +\n        \"gtsquery_penalty|gtsquery_picksplit|gtsquery_same|gtsquery_union|gtsvector_compress|\" +\n        \"gtsvector_consistent|gtsvector_decompress|gtsvector_penalty|gtsvector_picksplit|\" +\n        \"gtsvector_same|gtsvector_union|gtsvectorin|gtsvectorout|has_any_column_privilege|\" +\n        \"has_column_privilege|has_database_privilege|has_foreign_data_wrapper_privilege|\" +\n        \"has_function_privilege|has_language_privilege|has_schema_privilege|\" +\n        \"has_sequence_privilege|has_server_privilege|has_table_privilege|\" +\n        \"has_tablespace_privilege|hash_aclitem|hash_array|hash_numeric|hashbeginscan|\" +\n        \"hashbpchar|hashbuild|hashbuildempty|hashbulkdelete|hashchar|hashcostestimate|\" +\n        \"hashendscan|hashenum|hashfloat4|hashfloat8|hashgetbitmap|hashgettuple|hashinet|\" +\n        \"hashinsert|hashint2|hashint2vector|hashint4|hashint8|hashmacaddr|hashmarkpos|hashname|\" +\n        \"hashoid|hashoidvector|hashoptions|hashrescan|hashrestrpos|hashtext|hashvacuumcleanup|\" +\n        \"hashvarlena|height|host|hostmask|iclikejoinsel|iclikesel|icnlikejoinsel|icnlikesel|\" +\n        \"icregexeqjoinsel|icregexeqsel|icregexnejoinsel|icregexnesel|inet_client_addr|\" +\n        \"inet_client_port|inet_in|inet_out|inet_recv|inet_send|inet_server_addr|\" +\n        \"inet_server_port|inetand|inetmi|inetmi_int8|inetnot|inetor|inetpl|initcap|int2|int24div|\" +\n        \"int24eq|int24ge|int24gt|int24le|int24lt|int24mi|int24mul|int24ne|int24pl|int28div|int28eq|\" +\n        \"int28ge|int28gt|int28le|int28lt|int28mi|int28mul|int28ne|int28pl|int2_accum|\" +\n        \"int2_avg_accum|int2_mul_cash|int2_sum|int2abs|int2and|int2div|int2eq|int2ge|int2gt|int2in|\" +\n        \"int2larger|int2le|int2lt|int2mi|int2mod|int2mul|int2ne|int2not|int2or|int2out|int2pl|\" +\n        \"int2recv|int2send|int2shl|int2shr|int2smaller|int2um|int2up|int2vectoreq|int2vectorin|\" +\n        \"int2vectorout|int2vectorrecv|int2vectorsend|int2xor|int4|int42div|int42eq|int42ge|\" +\n        \"int42gt|int42le|int42lt|int42mi|int42mul|int42ne|int42pl|int48div|int48eq|int48ge|int48gt|\" +\n        \"int48le|int48lt|int48mi|int48mul|int48ne|int48pl|int4_accum|int4_avg_accum|int4_mul_cash|\" +\n        \"int4_sum|int4abs|int4and|int4div|int4eq|int4ge|int4gt|int4in|int4inc|int4larger|int4le|\" +\n        \"int4lt|int4mi|int4mod|int4mul|int4ne|int4not|int4or|int4out|int4pl|int4recv|int4send|\" +\n        \"int4shl|int4shr|int4smaller|int4um|int4up|int4xor|int8|int82div|int82eq|int82ge|int82gt|\" +\n        \"int82le|int82lt|int82mi|int82mul|int82ne|int82pl|int84div|int84eq|int84ge|int84gt|int84le|\" +\n        \"int84lt|int84mi|int84mul|int84ne|int84pl|int8_accum|int8_avg|int8_avg_accum|int8_sum|\" +\n        \"int8abs|int8and|int8div|int8eq|int8ge|int8gt|int8in|int8inc|int8inc_any|\" +\n        \"int8inc_float8_float8|int8larger|int8le|int8lt|int8mi|int8mod|int8mul|int8ne|int8not|\" +\n        \"int8or|int8out|int8pl|int8pl_inet|int8recv|int8send|int8shl|int8shr|int8smaller|int8um|\" +\n        \"int8up|int8xor|integer_pl_date|inter_lb|inter_sb|inter_sl|internal_in|internal_out|\" +\n        \"interval_accum|interval_avg|interval_cmp|interval_div|interval_eq|interval_ge|\" +\n        \"interval_gt|interval_hash|interval_in|interval_larger|interval_le|interval_lt|\" +\n        \"interval_mi|interval_mul|interval_ne|interval_out|interval_pl|interval_pl_date|\" +\n        \"interval_pl_time|interval_pl_timestamp|interval_pl_timestamptz|interval_pl_timetz|\" +\n        \"interval_recv|interval_send|interval_smaller|interval_um|intervaltypmodin|\" +\n        \"intervaltypmodout|intinterval|isclosed|isfinite|ishorizontal|iso8859_1_to_utf8|\" +\n        \"iso8859_to_utf8|iso_to_koi8r|iso_to_mic|iso_to_win1251|iso_to_win866|isopen|isparallel|\" +\n        \"isperp|isvertical|johab_to_utf8|justify_days|justify_hours|justify_interval|\" +\n        \"koi8r_to_iso|koi8r_to_mic|koi8r_to_utf8|koi8r_to_win1251|koi8r_to_win866|\" +\n        \"koi8u_to_utf8|lag|language_handler_in|language_handler_out|last_value|lastval|\" +\n        \"latin1_to_mic|latin2_to_mic|latin2_to_win1250|latin3_to_mic|latin4_to_mic|lead|left|\" +\n        \"length|like|like_escape|likejoinsel|likesel|line|line_distance|line_eq|line_horizontal|\" +\n        \"line_in|line_interpt|line_intersect|line_out|line_parallel|line_perp|line_recv|\" +\n        \"line_send|line_vertical|ln|lo_close|lo_creat|lo_create|lo_export|lo_import|lo_lseek|\" +\n        \"lo_open|lo_tell|lo_truncate|lo_unlink|log|loread|lower|lowrite|lpad|lseg|lseg_center|\" +\n        \"lseg_distance|lseg_eq|lseg_ge|lseg_gt|lseg_horizontal|lseg_in|lseg_interpt|\" +\n        \"lseg_intersect|lseg_le|lseg_length|lseg_lt|lseg_ne|lseg_out|lseg_parallel|lseg_perp|\" +\n        \"lseg_recv|lseg_send|lseg_vertical|ltrim|macaddr_cmp|macaddr_eq|macaddr_ge|macaddr_gt|\" +\n        \"macaddr_in|macaddr_le|macaddr_lt|macaddr_ne|macaddr_out|macaddr_recv|macaddr_send|\" +\n        \"makeaclitem|masklen|max|md5|mic_to_ascii|mic_to_big5|mic_to_euc_cn|mic_to_euc_jp|\" +\n        \"mic_to_euc_kr|mic_to_euc_tw|mic_to_iso|mic_to_koi8r|mic_to_latin1|mic_to_latin2|\" +\n        \"mic_to_latin3|mic_to_latin4|mic_to_sjis|mic_to_win1250|mic_to_win1251|mic_to_win866|\" +\n        \"min|mktinterval|mod|money|mul_d_interval|name|nameeq|namege|namegt|nameiclike|nameicnlike|\" +\n        \"nameicregexeq|nameicregexne|namein|namele|namelike|namelt|namene|namenlike|nameout|\" +\n        \"namerecv|nameregexeq|nameregexne|namesend|neqjoinsel|neqsel|netmask|network|network_cmp|\" +\n        \"network_eq|network_ge|network_gt|network_le|network_lt|network_ne|network_sub|\" +\n        \"network_subeq|network_sup|network_supeq|nextval|nlikejoinsel|nlikesel|notlike|now|\" +\n        \"npoints|nth_value|ntile|numeric_abs|numeric_accum|numeric_add|numeric_avg|\" +\n        \"numeric_avg_accum|numeric_cmp|numeric_div|numeric_div_trunc|numeric_eq|numeric_exp|\" +\n        \"numeric_fac|numeric_ge|numeric_gt|numeric_in|numeric_inc|numeric_larger|numeric_le|\" +\n        \"numeric_ln|numeric_log|numeric_lt|numeric_mod|numeric_mul|numeric_ne|numeric_out|\" +\n        \"numeric_power|numeric_recv|numeric_send|numeric_smaller|numeric_sqrt|\" +\n        \"numeric_stddev_pop|numeric_stddev_samp|numeric_sub|numeric_uminus|numeric_uplus|\" +\n        \"numeric_var_pop|numeric_var_samp|numerictypmodin|numerictypmodout|numnode|\" +\n        \"obj_description|octet_length|oid|oideq|oidge|oidgt|oidin|oidlarger|oidle|oidlt|oidne|oidout|\" +\n        \"oidrecv|oidsend|oidsmaller|oidvectoreq|oidvectorge|oidvectorgt|oidvectorin|oidvectorle|\" +\n        \"oidvectorlt|oidvectorne|oidvectorout|oidvectorrecv|oidvectorsend|oidvectortypes|on_pb|\" +\n        \"on_pl|on_ppath|on_ps|on_sb|on_sl|opaque_in|opaque_out|overlaps|overlay|path|path_add|\" +\n        \"path_add_pt|path_center|path_contain_pt|path_distance|path_div_pt|path_in|path_inter|\" +\n        \"path_length|path_mul_pt|path_n_eq|path_n_ge|path_n_gt|path_n_le|path_n_lt|path_npoints|\" +\n        \"path_out|path_recv|path_send|path_sub_pt|pclose|percent_rank|pg_advisory_lock|\" +\n        \"pg_advisory_lock_shared|pg_advisory_unlock|pg_advisory_unlock_all|\" +\n        \"pg_advisory_unlock_shared|pg_advisory_xact_lock|pg_advisory_xact_lock_shared|\" +\n        \"pg_available_extension_versions|pg_available_extensions|pg_backend_pid|\" +\n        \"pg_cancel_backend|pg_char_to_encoding|pg_client_encoding|pg_collation_is_visible|\" +\n        \"pg_column_size|pg_conf_load_time|pg_conversion_is_visible|pg_create_restore_point|\" +\n        \"pg_current_xlog_insert_location|pg_current_xlog_location|pg_cursor|pg_database_size|\" +\n        \"pg_describe_object|pg_encoding_max_length|pg_encoding_to_char|\" +\n        \"pg_extension_config_dump|pg_extension_update_paths|pg_function_is_visible|\" +\n        \"pg_get_constraintdef|pg_get_expr|pg_get_function_arguments|\" +\n        \"pg_get_function_identity_arguments|pg_get_function_result|pg_get_functiondef|\" +\n        \"pg_get_indexdef|pg_get_keywords|pg_get_ruledef|pg_get_serial_sequence|\" +\n        \"pg_get_triggerdef|pg_get_userbyid|pg_get_viewdef|pg_has_role|pg_indexes_size|\" +\n        \"pg_is_in_recovery|pg_is_other_temp_schema|pg_is_xlog_replay_paused|\" +\n        \"pg_last_xact_replay_timestamp|pg_last_xlog_receive_location|\" +\n        \"pg_last_xlog_replay_location|pg_listening_channels|pg_lock_status|pg_ls_dir|\" +\n        \"pg_my_temp_schema|pg_node_tree_in|pg_node_tree_out|pg_node_tree_recv|\" +\n        \"pg_node_tree_send|pg_notify|pg_opclass_is_visible|pg_operator_is_visible|\" +\n        \"pg_options_to_table|pg_postmaster_start_time|pg_prepared_statement|pg_prepared_xact|\" +\n        \"pg_read_binary_file|pg_read_file|pg_relation_filenode|pg_relation_filepath|\" +\n        \"pg_relation_size|pg_reload_conf|pg_rotate_logfile|pg_sequence_parameters|\" +\n        \"pg_show_all_settings|pg_size_pretty|pg_sleep|pg_start_backup|pg_stat_clear_snapshot|\" +\n        \"pg_stat_file|pg_stat_get_activity|pg_stat_get_analyze_count|\" +\n        \"pg_stat_get_autoanalyze_count|pg_stat_get_autovacuum_count|\" +\n        \"pg_stat_get_backend_activity|pg_stat_get_backend_activity_start|\" +\n        \"pg_stat_get_backend_client_addr|pg_stat_get_backend_client_port|\" +\n        \"pg_stat_get_backend_dbid|pg_stat_get_backend_idset|pg_stat_get_backend_pid|\" +\n        \"pg_stat_get_backend_start|pg_stat_get_backend_userid|pg_stat_get_backend_waiting|\" +\n        \"pg_stat_get_backend_xact_start|pg_stat_get_bgwriter_buf_written_checkpoints|\" +\n        \"pg_stat_get_bgwriter_buf_written_clean|pg_stat_get_bgwriter_maxwritten_clean|\" +\n        \"pg_stat_get_bgwriter_requested_checkpoints|pg_stat_get_bgwriter_stat_reset_time|\" +\n        \"pg_stat_get_bgwriter_timed_checkpoints|pg_stat_get_blocks_fetched|\" +\n        \"pg_stat_get_blocks_hit|pg_stat_get_buf_alloc|pg_stat_get_buf_fsync_backend|\" +\n        \"pg_stat_get_buf_written_backend|pg_stat_get_db_blocks_fetched|\" +\n        \"pg_stat_get_db_blocks_hit|pg_stat_get_db_conflict_all|\" +\n        \"pg_stat_get_db_conflict_bufferpin|pg_stat_get_db_conflict_lock|\" +\n        \"pg_stat_get_db_conflict_snapshot|pg_stat_get_db_conflict_startup_deadlock|\" +\n        \"pg_stat_get_db_conflict_tablespace|pg_stat_get_db_numbackends|\" +\n        \"pg_stat_get_db_stat_reset_time|pg_stat_get_db_tuples_deleted|\" +\n        \"pg_stat_get_db_tuples_fetched|pg_stat_get_db_tuples_inserted|\" +\n        \"pg_stat_get_db_tuples_returned|pg_stat_get_db_tuples_updated|\" +\n        \"pg_stat_get_db_xact_commit|pg_stat_get_db_xact_rollback|pg_stat_get_dead_tuples|\" +\n        \"pg_stat_get_function_calls|pg_stat_get_function_self_time|\" +\n        \"pg_stat_get_function_time|pg_stat_get_last_analyze_time|\" +\n        \"pg_stat_get_last_autoanalyze_time|pg_stat_get_last_autovacuum_time|\" +\n        \"pg_stat_get_last_vacuum_time|pg_stat_get_live_tuples|pg_stat_get_numscans|\" +\n        \"pg_stat_get_tuples_deleted|pg_stat_get_tuples_fetched|\" +\n        \"pg_stat_get_tuples_hot_updated|pg_stat_get_tuples_inserted|\" +\n        \"pg_stat_get_tuples_returned|pg_stat_get_tuples_updated|pg_stat_get_vacuum_count|\" +\n        \"pg_stat_get_wal_senders|pg_stat_get_xact_blocks_fetched|\" +\n        \"pg_stat_get_xact_blocks_hit|pg_stat_get_xact_function_calls|\" +\n        \"pg_stat_get_xact_function_self_time|pg_stat_get_xact_function_time|\" +\n        \"pg_stat_get_xact_numscans|pg_stat_get_xact_tuples_deleted|\" +\n        \"pg_stat_get_xact_tuples_fetched|pg_stat_get_xact_tuples_hot_updated|\" +\n        \"pg_stat_get_xact_tuples_inserted|pg_stat_get_xact_tuples_returned|\" +\n        \"pg_stat_get_xact_tuples_updated|pg_stat_reset|pg_stat_reset_shared|\" +\n        \"pg_stat_reset_single_function_counters|pg_stat_reset_single_table_counters|\" +\n        \"pg_stop_backup|pg_switch_xlog|pg_table_is_visible|pg_table_size|\" +\n        \"pg_tablespace_databases|pg_tablespace_size|pg_terminate_backend|pg_timezone_abbrevs|\" +\n        \"pg_timezone_names|pg_total_relation_size|pg_try_advisory_lock|\" +\n        \"pg_try_advisory_lock_shared|pg_try_advisory_xact_lock|\" +\n        \"pg_try_advisory_xact_lock_shared|pg_ts_config_is_visible|pg_ts_dict_is_visible|\" +\n        \"pg_ts_parser_is_visible|pg_ts_template_is_visible|pg_type_is_visible|pg_typeof|\" +\n        \"pg_xlog_replay_pause|pg_xlog_replay_resume|pg_xlogfile_name|pg_xlogfile_name_offset|\" +\n        \"pi|plainto_tsquery|plpgsql_call_handler|plpgsql_inline_handler|plpgsql_validator|\" +\n        \"point|point_above|point_add|point_below|point_distance|point_div|point_eq|point_horiz|\" +\n        \"point_in|point_left|point_mul|point_ne|point_out|point_recv|point_right|point_send|\" +\n        \"point_sub|point_vert|poly_above|poly_below|poly_center|poly_contain|poly_contain_pt|\" +\n        \"poly_contained|poly_distance|poly_in|poly_left|poly_npoints|poly_out|poly_overabove|\" +\n        \"poly_overbelow|poly_overlap|poly_overleft|poly_overright|poly_recv|poly_right|\" +\n        \"poly_same|poly_send|polygon|popen|position|positionjoinsel|positionsel|\" +\n        \"postgresql_fdw_validator|pow|power|prsd_end|prsd_headline|prsd_lextype|prsd_nexttoken|\" +\n        \"prsd_start|pt_contained_circle|pt_contained_poly|query_to_xml|\" +\n        \"query_to_xml_and_xmlschema|query_to_xmlschema|querytree|quote_ident|quote_literal|\" +\n        \"quote_nullable|radians|radius|random|rank|record_eq|record_ge|record_gt|record_in|\" +\n        \"record_le|record_lt|record_ne|record_out|record_recv|record_send|regclass|regclassin|\" +\n        \"regclassout|regclassrecv|regclasssend|regconfigin|regconfigout|regconfigrecv|\" +\n        \"regconfigsend|regdictionaryin|regdictionaryout|regdictionaryrecv|regdictionarysend|\" +\n        \"regexeqjoinsel|regexeqsel|regexnejoinsel|regexnesel|regexp_matches|regexp_replace|\" +\n        \"regexp_split_to_array|regexp_split_to_table|regoperatorin|regoperatorout|\" +\n        \"regoperatorrecv|regoperatorsend|regoperin|regoperout|regoperrecv|regopersend|\" +\n        \"regprocedurein|regprocedureout|regprocedurerecv|regproceduresend|regprocin|regprocout|\" +\n        \"regprocrecv|regprocsend|regr_avgx|regr_avgy|regr_count|regr_intercept|regr_r2|\" +\n        \"regr_slope|regr_sxx|regr_sxy|regr_syy|regtypein|regtypeout|regtyperecv|regtypesend|\" +\n        \"reltime|reltimeeq|reltimege|reltimegt|reltimein|reltimele|reltimelt|reltimene|reltimeout|\" +\n        \"reltimerecv|reltimesend|repeat|replace|reverse|right|round|row_number|rpad|rtrim|\" +\n        \"scalargtjoinsel|scalargtsel|scalarltjoinsel|scalarltsel|schema_to_xml|\" +\n        \"schema_to_xml_and_xmlschema|schema_to_xmlschema|session_user|set_bit|set_byte|\" +\n        \"set_config|set_masklen|setseed|setval|setweight|shell_in|shell_out|\" +\n        \"shift_jis_2004_to_euc_jis_2004|shift_jis_2004_to_utf8|shobj_description|sign|\" +\n        \"similar_escape|sin|sjis_to_euc_jp|sjis_to_mic|sjis_to_utf8|slope|smgreq|smgrin|smgrne|\" +\n        \"smgrout|split_part|sqrt|statement_timestamp|stddev|stddev_pop|stddev_samp|string_agg|\" +\n        \"string_agg_finalfn|string_agg_transfn|string_to_array|strip|strpos|substr|substring|sum|\" +\n        \"suppress_redundant_updates_trigger|table_to_xml|table_to_xml_and_xmlschema|\" +\n        \"table_to_xmlschema|tan|text|text_ge|text_gt|text_larger|text_le|text_lt|text_pattern_ge|\" +\n        \"text_pattern_gt|text_pattern_le|text_pattern_lt|text_smaller|textanycat|textcat|texteq|\" +\n        \"texticlike|texticnlike|texticregexeq|texticregexne|textin|textlen|textlike|textne|\" +\n        \"textnlike|textout|textrecv|textregexeq|textregexne|textsend|thesaurus_init|\" +\n        \"thesaurus_lexize|tideq|tidge|tidgt|tidin|tidlarger|tidle|tidlt|tidne|tidout|tidrecv|tidsend|\" +\n        \"tidsmaller|time_cmp|time_eq|time_ge|time_gt|time_hash|time_in|time_larger|time_le|time_lt|\" +\n        \"time_mi_interval|time_mi_time|time_ne|time_out|time_pl_interval|time_recv|time_send|\" +\n        \"time_smaller|timedate_pl|timemi|timenow|timeofday|timepl|timestamp_cmp|\" +\n        \"timestamp_cmp_date|timestamp_cmp_timestamptz|timestamp_eq|timestamp_eq_date|\" +\n        \"timestamp_eq_timestamptz|timestamp_ge|timestamp_ge_date|timestamp_ge_timestamptz|\" +\n        \"timestamp_gt|timestamp_gt_date|timestamp_gt_timestamptz|timestamp_hash|timestamp_in|\" +\n        \"timestamp_larger|timestamp_le|timestamp_le_date|timestamp_le_timestamptz|\" +\n        \"timestamp_lt|timestamp_lt_date|timestamp_lt_timestamptz|timestamp_mi|\" +\n        \"timestamp_mi_interval|timestamp_ne|timestamp_ne_date|timestamp_ne_timestamptz|\" +\n        \"timestamp_out|timestamp_pl_interval|timestamp_recv|timestamp_send|timestamp_smaller|\" +\n        \"timestamptypmodin|timestamptypmodout|timestamptz_cmp|timestamptz_cmp_date|\" +\n        \"timestamptz_cmp_timestamp|timestamptz_eq|timestamptz_eq_date|\" +\n        \"timestamptz_eq_timestamp|timestamptz_ge|timestamptz_ge_date|\" +\n        \"timestamptz_ge_timestamp|timestamptz_gt|timestamptz_gt_date|\" +\n        \"timestamptz_gt_timestamp|timestamptz_in|timestamptz_larger|timestamptz_le|\" +\n        \"timestamptz_le_date|timestamptz_le_timestamp|timestamptz_lt|timestamptz_lt_date|\" +\n        \"timestamptz_lt_timestamp|timestamptz_mi|timestamptz_mi_interval|timestamptz_ne|\" +\n        \"timestamptz_ne_date|timestamptz_ne_timestamp|timestamptz_out|\" +\n        \"timestamptz_pl_interval|timestamptz_recv|timestamptz_send|timestamptz_smaller|\" +\n        \"timestamptztypmodin|timestamptztypmodout|timetypmodin|timetypmodout|timetz_cmp|\" +\n        \"timetz_eq|timetz_ge|timetz_gt|timetz_hash|timetz_in|timetz_larger|timetz_le|timetz_lt|\" +\n        \"timetz_mi_interval|timetz_ne|timetz_out|timetz_pl_interval|timetz_recv|timetz_send|\" +\n        \"timetz_smaller|timetzdate_pl|timetztypmodin|timetztypmodout|timezone|tinterval|\" +\n        \"tintervalct|tintervalend|tintervaleq|tintervalge|tintervalgt|tintervalin|tintervalle|\" +\n        \"tintervalleneq|tintervallenge|tintervallengt|tintervallenle|tintervallenlt|\" +\n        \"tintervallenne|tintervallt|tintervalne|tintervalout|tintervalov|tintervalrecv|\" +\n        \"tintervalrel|tintervalsame|tintervalsend|tintervalstart|to_ascii|to_char|to_date|to_hex|\" +\n        \"to_number|to_timestamp|to_tsquery|to_tsvector|transaction_timestamp|translate|\" +\n        \"trigger_in|trigger_out|trunc|ts_debug|ts_headline|ts_lexize|ts_match_qv|ts_match_tq|\" +\n        \"ts_match_tt|ts_match_vq|ts_parse|ts_rank|ts_rank_cd|ts_rewrite|ts_stat|ts_token_type|\" +\n        \"ts_typanalyze|tsmatchjoinsel|tsmatchsel|tsq_mcontained|tsq_mcontains|tsquery_and|\" +\n        \"tsquery_cmp|tsquery_eq|tsquery_ge|tsquery_gt|tsquery_le|tsquery_lt|tsquery_ne|\" +\n        \"tsquery_not|tsquery_or|tsqueryin|tsqueryout|tsqueryrecv|tsquerysend|tsvector_cmp|\" +\n        \"tsvector_concat|tsvector_eq|tsvector_ge|tsvector_gt|tsvector_le|tsvector_lt|\" +\n        \"tsvector_ne|tsvector_update_trigger|tsvector_update_trigger_column|tsvectorin|\" +\n        \"tsvectorout|tsvectorrecv|tsvectorsend|txid_current|txid_current_snapshot|\" +\n        \"txid_snapshot_in|txid_snapshot_out|txid_snapshot_recv|txid_snapshot_send|\" +\n        \"txid_snapshot_xip|txid_snapshot_xmax|txid_snapshot_xmin|txid_visible_in_snapshot|\" +\n        \"uhc_to_utf8|unique_key_recheck|unknownin|unknownout|unknownrecv|unknownsend|unnest|\" +\n        \"upper|utf8_to_ascii|utf8_to_big5|utf8_to_euc_cn|utf8_to_euc_jis_2004|utf8_to_euc_jp|\" +\n        \"utf8_to_euc_kr|utf8_to_euc_tw|utf8_to_gb18030|utf8_to_gbk|utf8_to_iso8859|\" +\n        \"utf8_to_iso8859_1|utf8_to_johab|utf8_to_koi8r|utf8_to_koi8u|utf8_to_shift_jis_2004|\" +\n        \"utf8_to_sjis|utf8_to_uhc|utf8_to_win|uuid_cmp|uuid_eq|uuid_ge|uuid_gt|uuid_hash|uuid_in|\" +\n        \"uuid_le|uuid_lt|uuid_ne|uuid_out|uuid_recv|uuid_send|var_pop|var_samp|varbit_in|\" +\n        \"varbit_out|varbit_recv|varbit_send|varbitcmp|varbiteq|varbitge|varbitgt|varbitle|\" +\n        \"varbitlt|varbitne|varbittypmodin|varbittypmodout|varcharin|varcharout|varcharrecv|\" +\n        \"varcharsend|varchartypmodin|varchartypmodout|variance|version|void_in|void_out|\" +\n        \"void_recv|void_send|width|width_bucket|win1250_to_latin2|win1250_to_mic|win1251_to_iso|\" +\n        \"win1251_to_koi8r|win1251_to_mic|win1251_to_win866|win866_to_iso|win866_to_koi8r|\" +\n        \"win866_to_mic|win866_to_win1251|win_to_utf8|xideq|xideqint4|xidin|xidout|xidrecv|xidsend|\" +\n        \"xml|xml_in|xml_is_well_formed|xml_is_well_formed_content|xml_is_well_formed_document|\" +\n        \"xml_out|xml_recv|xml_send|xmlagg|xmlcomment|xmlconcat2|xmlexists|xmlvalidate|xpath|\" +\n        \"xpath_exists\").split(\"|\")\n    );\n    \n    var sqlRules = [\n        {\n            token : \"string\", // single line string -- assume dollar strings if multi-line for now\n            regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n        }, {\n            token : \"variable.language\", // pg identifier\n            regex : '\".*?\"'\n        }, {\n            token : \"constant.numeric\", // float\n            regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n        }, {\n            token : function(value) {\n                value = value.toLowerCase();\n                if (keywords.hasOwnProperty(value)) {\n                    return \"keyword\";\n                } else if (builtinFunctions.hasOwnProperty(value)) {\n                    return \"support.function\";\n                } else {\n                    return \"identifier\";\n                }\n              },\n              regex : \"[a-zA-Z_][a-zA-Z0-9_$]*\\\\b\" // TODO - Unicode in identifiers\n          }, {\n              token : \"keyword.operator\",\n              regex : \"!|!!|!~|!~\\\\*|!~~|!~~\\\\*|#|##|#<|#<=|#<>|#=|#>|#>=|%|\\\\&|\\\\&\\\\&|\\\\&<|\\\\&<\\\\||\\\\&>|\\\\*|\\\\+|\" +\n                      \"\\\\-|/|<|<#>|<\\\\->|<<|<<=|<<\\\\||<=|<>|<\\\\?>|<@|<\\\\^|=|>|>=|>>|>>=|>\\\\^|\\\\?#|\\\\?\\\\-|\\\\?\\\\-\\\\||\" +\n                      \"\\\\?\\\\||\\\\?\\\\|\\\\||@|@\\\\-@|@>|@@|@@@|\\\\^|\\\\||\\\\|\\\\&>|\\\\|/|\\\\|>>|\\\\|\\\\||\\\\|\\\\|/|~|~\\\\*|~<=~|~<~|\" +\n                      \"~=|~>=~|~>~|~~|~~\\\\*\"\n          }, {\n              token : \"lparen.paren\",\n              regex : \"[\\\\(]\"\n          }, {\n              token : \"paren.rparen\",\n              regex : \"[\\\\)]\"\n          }, {\n              token : \"text\",\n              regex : \"\\\\s+\"\n          }\n    ];\n           \n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \"--.*$\"\n            }, \n            DocCommentHighlightRules.getStartRule(\"doc-start\"),\n            {\n                token : \"comment\", // multi-line comment\n                merge : true,\n                regex : \"\\\\/\\\\*\",\n                next : \"comment\"\n            },{\n                token : \"keyword.statementBegin\",\n                regex : \"^[a-zA-Z]+\", // Could enumerate starting keywords but this allows things to work when new statements are added.\n                next : \"statement\"\n            },{\n                token : \"support.buildin\", // psql directive\n                regex : \"^\\\\\\\\[\\\\S]+.*$\"\n            }\n        ],\n        \n        \"statement\" : [\n            {\n                token : \"comment\",\n                regex : \"--.*$\"\n            }, {\n                token : \"comment\", // multi-line comment\n                merge : true,\n                regex : \"\\\\/\\\\*\",\n                next : \"commentStatement\"\n            }, {\n                token : \"statementEnd\",\n                regex : \";\",\n                next : \"start\"\n            }, {\n                token : \"string\", // perl, python, tcl are in the pg default dist (no tcl highlighter)\n                regex : \"\\\\$perl\\\\$\",\n                next : \"perl-start\"\n            }, {\n                token : \"string\",\n                regex : \"\\\\$python\\\\$\",\n                next : \"python-start\"\n            },{\n                token : \"string\",\n                regex : \"\\\\$[\\\\w_0-9]*\\\\$$\", // dollar quote at the end of a line\n                next : \"dollarSql\"\n            }, {\n                token : \"string\",\n                regex : \"\\\\$[\\\\w_0-9]*\\\\$\",\n                next : \"dollarStatementString\"\n            }\n        ].concat(sqlRules),\n        \n        \"dollarSql\" : [\n            {\n                token : \"comment\",\n                regex : \"--.*$\"\n            }, {\n                token : \"comment\", // multi-line comment\n                merge : true,\n                regex : \"\\\\/\\\\*\",\n                next : \"commentDollarSql\"\n            }, {\n                token : \"string\", // end quoting with dollar at the start of a line\n                regex : \"^\\\\$[\\\\w_0-9]*\\\\$\",\n                next : \"statement\"\n            }, {\n                token : \"string\",\n                regex : \"\\\\$[\\\\w_0-9]*\\\\$\",\n                next : \"dollarSqlString\"\n            }\n        ].concat(sqlRules),\n        \n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ],\n        \n        \"commentStatement\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"statement\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ],\n        \n        \"commentDollarSql\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"dollarSql\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ],\n        \n        \"dollarStatementString\" : [\n            {\n                token : \"string\", // closing dollarstring\n                regex : \".*?\\\\$[\\\\w_0-9]*\\\\$\",\n                next : \"statement\"\n            }, {\n                token : \"string\", // dollarstring spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ],\n        \n        \"dollarSqlString\" : [\n            {\n                token : \"string\", // closing dollarstring\n                regex : \".*?\\\\$[\\\\w_0-9]*\\\\$\",\n                next : \"dollarSql\"\n            }, {\n                token : \"string\", // dollarstring spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ]\n    };\n    \n    this.embedRules(DocCommentHighlightRules, \"doc-\", [ DocCommentHighlightRules.getEndRule(\"start\") ]);\n    this.embedRules(PerlHighlightRules, \"perl-\", [{token : \"string\", regex : \"\\\\$perl\\\\$\", next : \"statement\"}]);\n    this.embedRules(PythonHighlightRules, \"python-\", [{token : \"string\", regex : \"\\\\$python\\\\$\", next : \"statement\"}]);\n};\n\noop.inherits(PgsqlHighlightRules, TextHighlightRules);\n\nexports.PgsqlHighlightRules = PgsqlHighlightRules;\n});\n\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/php.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n* Version: MPL 1.1/GPL 2.0/LGPL 2.1\n*\n* The contents of this file are subject to the Mozilla Public License Version\n* 1.1 (the \"License\"); you may not use this file except in compliance with\n* the License. You may obtain a copy of the License at\n* http://www.mozilla.org/MPL/\n*\n* Software distributed under the License is distributed on an \"AS IS\" basis,\n* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n* for the specific language governing rights and limitations under the\n* License.\n*\n* The Original Code is Ajax.org Code Editor (ACE).\n*\n* The Initial Developer of the Original Code is\n* Ajax.org B.V.\n* Portions created by the Initial Developer are Copyright (C) 2010\n* the Initial Developer. All Rights Reserved.\n*\n* Contributor(s):\n*      André Fiedler <fiedler dot andre a t gmail dot com>\n*\n* Alternatively, the contents of this file may be used under the terms of\n* either the GNU General Public License Version 2 or later (the \"GPL\"), or\n* the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n* in which case the provisions of the GPL or the LGPL are applicable instead\n* of those above. If you wish to allow use of your version of this file only\n* under the terms of either the GPL or the LGPL, and not to allow others to\n* use your version of this file under the terms of the MPL, indicate your\n* decision by deleting the provisions above and replace them with the notice\n* and other provisions required by the GPL or the LGPL. If you do not delete\n* the provisions above, a recipient may use your version of this file under\n* the terms of any one of the MPL, the GPL or the LGPL.\n*\n* ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar PhpHighlightRules = require(\"./php_highlight_rules\").PhpHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar Range = require(\"../range\").Range;\nvar CstyleBehaviour = require(\"./behaviour/cstyle\").CstyleBehaviour;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new PhpHighlightRules().getRules());\n    this.$outdent = new MatchingBraceOutdent();\n    this.$behaviour = new CstyleBehaviour();\n    this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        var outdent = true;\n        var re = /^(\\s*)#/;\n\n        for (var i=startRow; i<= endRow; i++) {\n            if (!re.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        if (outdent) {\n            var deleteRange = new Range(0, 0, 0, 0);\n            for (var i=startRow; i<= endRow; i++)\n            {\n                var line = doc.getLine(i);\n                var m = line.match(re);\n                deleteRange.start.row = i;\n                deleteRange.end.row = i;\n                deleteRange.end.column = m[0].length;\n                doc.replace(deleteRange, m[1]);\n            }\n        }\n        else {\n            doc.indentRows(startRow, endRow, \"#\");\n        }\n    };\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n\n        if (state == \"start\") {\n            var match = line.match(/^.*[\\{\\(\\[\\:]\\s*$/);\n            if (match) {\n                indent += tab;\n            }\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/php_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      André Fiedler <fiedler dot andre a t gmail dot com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK *****\n */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar DocCommentHighlightRules = require(\"./doc_comment_highlight_rules\").DocCommentHighlightRules;\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar PhpHighlightRules = function() {\n    var docComment = DocCommentHighlightRules;\n    // http://php.net/quickref.php\n    var builtinFunctions = lang.arrayToMap(\n        ('abs|acos|acosh|addcslashes|addslashes|aggregate|aggregate_info|aggregate_methods|aggregate_methods_by_list|aggregate_methods_by_regexp|' +\n        'aggregate_properties|aggregate_properties_by_list|aggregate_properties_by_regexp|aggregation_info|amqpconnection|amqpexchange|amqpqueue|' +\n        'apache_child_terminate|apache_get_modules|apache_get_version|apache_getenv|apache_lookup_uri|apache_note|apache_request_headers|' +\n        'apache_reset_timeout|apache_response_headers|apache_setenv|apc_add|apc_bin_dump|apc_bin_dumpfile|apc_bin_load|apc_bin_loadfile|' +\n        'apc_cache_info|apc_cas|apc_clear_cache|apc_compile_file|apc_dec|apc_define_constants|apc_delete|apc_delete_file|apc_exists|apc_fetch|' +\n        'apc_inc|apc_load_constants|apc_sma_info|apc_store|apciterator|apd_breakpoint|apd_callstack|apd_clunk|apd_continue|apd_croak|' +\n        'apd_dump_function_table|apd_dump_persistent_resources|apd_dump_regular_resources|apd_echo|apd_get_active_symbols|apd_set_pprof_trace|' +\n        'apd_set_session|apd_set_session_trace|apd_set_session_trace_socket|appenditerator|array|array_change_key_case|array_chunk|array_combine|' +\n        'array_count_values|array_diff|array_diff_assoc|array_diff_key|array_diff_uassoc|array_diff_ukey|array_fill|array_fill_keys|array_filter|' +\n        'array_flip|array_intersect|array_intersect_assoc|array_intersect_key|array_intersect_uassoc|array_intersect_ukey|array_key_exists|' +\n        'array_keys|array_map|array_merge|array_merge_recursive|array_multisort|array_pad|array_pop|array_product|array_push|array_rand|' +\n        'array_reduce|array_replace|array_replace_recursive|array_reverse|array_search|array_shift|array_slice|array_splice|array_sum|array_udiff|' +\n        'array_udiff_assoc|array_udiff_uassoc|array_uintersect|array_uintersect_assoc|array_uintersect_uassoc|array_unique|array_unshift|' +\n        'array_values|array_walk|array_walk_recursive|arrayaccess|arrayiterator|arrayobject|arsort|asin|asinh|asort|assert|assert_options|atan|' +\n        'atan2|atanh|audioproperties|badfunctioncallexception|badmethodcallexception|base64_decode|base64_encode|base_convert|basename|' +\n        'bbcode_add_element|bbcode_add_smiley|bbcode_create|bbcode_destroy|bbcode_parse|bbcode_set_arg_parser|bbcode_set_flags|bcadd|bccomp|bcdiv|' +\n        'bcmod|bcmul|bcompiler_load|bcompiler_load_exe|bcompiler_parse_class|bcompiler_read|bcompiler_write_class|bcompiler_write_constant|' +\n        'bcompiler_write_exe_footer|bcompiler_write_file|bcompiler_write_footer|bcompiler_write_function|bcompiler_write_functions_from_file|' +\n        'bcompiler_write_header|bcompiler_write_included_filename|bcpow|bcpowmod|bcscale|bcsqrt|bcsub|bin2hex|bind_textdomain_codeset|bindec|' +\n        'bindtextdomain|bson_decode|bson_encode|bumpValue|bzclose|bzcompress|bzdecompress|bzerrno|bzerror|bzerrstr|bzflush|bzopen|bzread|bzwrite|' +\n        'cachingiterator|cairo|cairo_create|cairo_font_face_get_type|cairo_font_face_status|cairo_font_options_create|cairo_font_options_equal|' +\n        'cairo_font_options_get_antialias|cairo_font_options_get_hint_metrics|cairo_font_options_get_hint_style|' +\n        'cairo_font_options_get_subpixel_order|cairo_font_options_hash|cairo_font_options_merge|cairo_font_options_set_antialias|' +\n        'cairo_font_options_set_hint_metrics|cairo_font_options_set_hint_style|cairo_font_options_set_subpixel_order|cairo_font_options_status|' +\n        'cairo_format_stride_for_width|cairo_image_surface_create|cairo_image_surface_create_for_data|cairo_image_surface_create_from_png|' +\n        'cairo_image_surface_get_data|cairo_image_surface_get_format|cairo_image_surface_get_height|cairo_image_surface_get_stride|' +\n        'cairo_image_surface_get_width|cairo_matrix_create_scale|cairo_matrix_create_translate|cairo_matrix_invert|cairo_matrix_multiply|' +\n        'cairo_matrix_rotate|cairo_matrix_transform_distance|cairo_matrix_transform_point|cairo_matrix_translate|cairo_pattern_add_color_stop_rgb|' +\n        'cairo_pattern_add_color_stop_rgba|cairo_pattern_create_for_surface|cairo_pattern_create_linear|cairo_pattern_create_radial|' +\n        'cairo_pattern_create_rgb|cairo_pattern_create_rgba|cairo_pattern_get_color_stop_count|cairo_pattern_get_color_stop_rgba|' +\n        'cairo_pattern_get_extend|cairo_pattern_get_filter|cairo_pattern_get_linear_points|cairo_pattern_get_matrix|' +\n        'cairo_pattern_get_radial_circles|cairo_pattern_get_rgba|cairo_pattern_get_surface|cairo_pattern_get_type|cairo_pattern_set_extend|' +\n        'cairo_pattern_set_filter|cairo_pattern_set_matrix|cairo_pattern_status|cairo_pdf_surface_create|cairo_pdf_surface_set_size|' +\n        'cairo_ps_get_levels|cairo_ps_level_to_string|cairo_ps_surface_create|cairo_ps_surface_dsc_begin_page_setup|' +\n        'cairo_ps_surface_dsc_begin_setup|cairo_ps_surface_dsc_comment|cairo_ps_surface_get_eps|cairo_ps_surface_restrict_to_level|' +\n        'cairo_ps_surface_set_eps|cairo_ps_surface_set_size|cairo_scaled_font_create|cairo_scaled_font_extents|cairo_scaled_font_get_ctm|' +\n        'cairo_scaled_font_get_font_face|cairo_scaled_font_get_font_matrix|cairo_scaled_font_get_font_options|cairo_scaled_font_get_scale_matrix|' +\n        'cairo_scaled_font_get_type|cairo_scaled_font_glyph_extents|cairo_scaled_font_status|cairo_scaled_font_text_extents|' +\n        'cairo_surface_copy_page|cairo_surface_create_similar|cairo_surface_finish|cairo_surface_flush|cairo_surface_get_content|' +\n        'cairo_surface_get_device_offset|cairo_surface_get_font_options|cairo_surface_get_type|cairo_surface_mark_dirty|' +\n        'cairo_surface_mark_dirty_rectangle|cairo_surface_set_device_offset|cairo_surface_set_fallback_resolution|cairo_surface_show_page|' +\n        'cairo_surface_status|cairo_surface_write_to_png|cairo_svg_surface_create|cairo_svg_surface_restrict_to_version|' +\n        'cairo_svg_version_to_string|cairoantialias|cairocontent|cairocontext|cairoexception|cairoextend|cairofillrule|cairofilter|cairofontface|' +\n        'cairofontoptions|cairofontslant|cairofonttype|cairofontweight|cairoformat|cairogradientpattern|cairohintmetrics|cairohintstyle|' +\n        'cairoimagesurface|cairolineargradient|cairolinecap|cairolinejoin|cairomatrix|cairooperator|cairopath|cairopattern|cairopatterntype|' +\n        'cairopdfsurface|cairopslevel|cairopssurface|cairoradialgradient|cairoscaledfont|cairosolidpattern|cairostatus|cairosubpixelorder|' +\n        'cairosurface|cairosurfacepattern|cairosurfacetype|cairosvgsurface|cairosvgversion|cairotoyfontface|cal_days_in_month|cal_from_jd|cal_info|' +\n        'cal_to_jd|calcul_hmac|calculhmac|call_user_func|call_user_func_array|call_user_method|call_user_method_array|callbackfilteriterator|ceil|' +\n        'chdb|chdb_create|chdir|checkdate|checkdnsrr|chgrp|chmod|chop|chown|chr|chroot|chunk_split|class_alias|class_exists|class_implements|' +\n        'class_parents|classkit_import|classkit_method_add|classkit_method_copy|classkit_method_redefine|classkit_method_remove|' +\n        'classkit_method_rename|clearstatcache|clone|closedir|closelog|collator|com|com_addref|com_create_guid|com_event_sink|com_get|' +\n        'com_get_active_object|com_invoke|com_isenum|com_load|com_load_typelib|com_message_pump|com_print_typeinfo|com_propget|com_propput|' +\n        'com_propset|com_release|com_set|compact|connection_aborted|connection_status|connection_timeout|constant|construct|construct|construct|' +\n        'convert_cyr_string|convert_uudecode|convert_uuencode|copy|cos|cosh|count|count_chars|countable|counter_bump|counter_bump_value|' +\n        'counter_create|counter_get|counter_get_meta|counter_get_named|counter_get_value|counter_reset|counter_reset_value|crack_check|' +\n        'crack_closedict|crack_getlastmessage|crack_opendict|crc32|create_function|crypt|ctype_alnum|ctype_alpha|ctype_cntrl|ctype_digit|' +\n        'ctype_graph|ctype_lower|ctype_print|ctype_punct|ctype_space|ctype_upper|ctype_xdigit|cubrid_affected_rows|cubrid_bind|' +\n        'cubrid_client_encoding|cubrid_close|cubrid_close_prepare|cubrid_close_request|cubrid_col_get|cubrid_col_size|cubrid_column_names|' +\n        'cubrid_column_types|cubrid_commit|cubrid_connect|cubrid_connect_with_url|cubrid_current_oid|cubrid_data_seek|cubrid_db_name|' +\n        'cubrid_disconnect|cubrid_drop|cubrid_errno|cubrid_error|cubrid_error_code|cubrid_error_code_facility|cubrid_error_msg|cubrid_execute|' +\n        'cubrid_fetch|cubrid_fetch_array|cubrid_fetch_assoc|cubrid_fetch_field|cubrid_fetch_lengths|cubrid_fetch_object|cubrid_fetch_row|' +\n        'cubrid_field_flags|cubrid_field_len|cubrid_field_name|cubrid_field_seek|cubrid_field_table|cubrid_field_type|cubrid_free_result|' +\n        'cubrid_get|cubrid_get_autocommit|cubrid_get_charset|cubrid_get_class_name|cubrid_get_client_info|cubrid_get_db_parameter|' +\n        'cubrid_get_server_info|cubrid_insert_id|cubrid_is_instance|cubrid_list_dbs|cubrid_load_from_glo|cubrid_lob_close|cubrid_lob_export|' +\n        'cubrid_lob_get|cubrid_lob_send|cubrid_lob_size|cubrid_lock_read|cubrid_lock_write|cubrid_move_cursor|cubrid_new_glo|cubrid_next_result|' +\n        'cubrid_num_cols|cubrid_num_fields|cubrid_num_rows|cubrid_ping|cubrid_prepare|cubrid_put|cubrid_query|cubrid_real_escape_string|' +\n        'cubrid_result|cubrid_rollback|cubrid_save_to_glo|cubrid_schema|cubrid_send_glo|cubrid_seq_drop|cubrid_seq_insert|cubrid_seq_put|' +\n        'cubrid_set_add|cubrid_set_autocommit|cubrid_set_db_parameter|cubrid_set_drop|cubrid_unbuffered_query|cubrid_version|curl_close|' +\n        'curl_copy_handle|curl_errno|curl_error|curl_exec|curl_getinfo|curl_init|curl_multi_add_handle|curl_multi_close|curl_multi_exec|' +\n        'curl_multi_getcontent|curl_multi_info_read|curl_multi_init|curl_multi_remove_handle|curl_multi_select|curl_setopt|curl_setopt_array|' +\n        'curl_version|current|cyrus_authenticate|cyrus_bind|cyrus_close|cyrus_connect|cyrus_query|cyrus_unbind|date|date_add|date_create|' +\n        'date_create_from_format|date_date_set|date_default_timezone_get|date_default_timezone_set|date_diff|date_format|date_get_last_errors|' +\n        'date_interval_create_from_date_string|date_interval_format|date_isodate_set|date_modify|date_offset_get|date_parse|date_parse_from_format|' +\n        'date_sub|date_sun_info|date_sunrise|date_sunset|date_time_set|date_timestamp_get|date_timestamp_set|date_timezone_get|date_timezone_set|' +\n        'dateinterval|dateperiod|datetime|datetimezone|db2_autocommit|db2_bind_param|db2_client_info|db2_close|db2_column_privileges|db2_columns|' +\n        'db2_commit|db2_conn_error|db2_conn_errormsg|db2_connect|db2_cursor_type|db2_escape_string|db2_exec|db2_execute|db2_fetch_array|' +\n        'db2_fetch_assoc|db2_fetch_both|db2_fetch_object|db2_fetch_row|db2_field_display_size|db2_field_name|db2_field_num|db2_field_precision|' +\n        'db2_field_scale|db2_field_type|db2_field_width|db2_foreign_keys|db2_free_result|db2_free_stmt|db2_get_option|db2_last_insert_id|' +\n        'db2_lob_read|db2_next_result|db2_num_fields|db2_num_rows|db2_pclose|db2_pconnect|db2_prepare|db2_primary_keys|db2_procedure_columns|' +\n        'db2_procedures|db2_result|db2_rollback|db2_server_info|db2_set_option|db2_special_columns|db2_statistics|db2_stmt_error|db2_stmt_errormsg|' +\n        'db2_table_privileges|db2_tables|dba_close|dba_delete|dba_exists|dba_fetch|dba_firstkey|dba_handlers|dba_insert|dba_key_split|dba_list|' +\n        'dba_nextkey|dba_open|dba_optimize|dba_popen|dba_replace|dba_sync|dbase_add_record|dbase_close|dbase_create|dbase_delete_record|' +\n        'dbase_get_header_info|dbase_get_record|dbase_get_record_with_names|dbase_numfields|dbase_numrecords|dbase_open|dbase_pack|' +\n        'dbase_replace_record|dbplus_add|dbplus_aql|dbplus_chdir|dbplus_close|dbplus_curr|dbplus_errcode|dbplus_errno|dbplus_find|dbplus_first|' +\n        'dbplus_flush|dbplus_freealllocks|dbplus_freelock|dbplus_freerlocks|dbplus_getlock|dbplus_getunique|dbplus_info|dbplus_last|dbplus_lockrel|' +\n        'dbplus_next|dbplus_open|dbplus_prev|dbplus_rchperm|dbplus_rcreate|dbplus_rcrtexact|dbplus_rcrtlike|dbplus_resolve|dbplus_restorepos|' +\n        'dbplus_rkeys|dbplus_ropen|dbplus_rquery|dbplus_rrename|dbplus_rsecindex|dbplus_runlink|dbplus_rzap|dbplus_savepos|dbplus_setindex|' +\n        'dbplus_setindexbynumber|dbplus_sql|dbplus_tcl|dbplus_tremove|dbplus_undo|dbplus_undoprepare|dbplus_unlockrel|dbplus_unselect|' +\n        'dbplus_update|dbplus_xlockrel|dbplus_xunlockrel|dbx_close|dbx_compare|dbx_connect|dbx_error|dbx_escape_string|dbx_fetch_row|dbx_query|' +\n        'dbx_sort|dcgettext|dcngettext|deaggregate|debug_backtrace|debug_print_backtrace|debug_zval_dump|decbin|dechex|decoct|define|' +\n        'define_syslog_variables|defined|deg2rad|delete|dgettext|die|dio_close|dio_fcntl|dio_open|dio_read|dio_seek|dio_stat|dio_tcsetattr|' +\n        'dio_truncate|dio_write|dir|directoryiterator|dirname|disk_free_space|disk_total_space|diskfreespace|dl|dngettext|dns_check_record|' +\n        'dns_get_mx|dns_get_record|dom_import_simplexml|domainexception|domattr|domattribute_name|domattribute_set_value|domattribute_specified|' +\n        'domattribute_value|domcharacterdata|domcomment|domdocument|domdocument_add_root|domdocument_create_attribute|' +\n        'domdocument_create_cdata_section|domdocument_create_comment|domdocument_create_element|domdocument_create_element_ns|' +\n        'domdocument_create_entity_reference|domdocument_create_processing_instruction|domdocument_create_text_node|domdocument_doctype|' +\n        'domdocument_document_element|domdocument_dump_file|domdocument_dump_mem|domdocument_get_element_by_id|domdocument_get_elements_by_tagname|' +\n        'domdocument_html_dump_mem|domdocument_xinclude|domdocumentfragment|domdocumenttype|domdocumenttype_entities|' +\n        'domdocumenttype_internal_subset|domdocumenttype_name|domdocumenttype_notations|domdocumenttype_public_id|domdocumenttype_system_id|' +\n        'domelement|domelement_get_attribute|domelement_get_attribute_node|domelement_get_elements_by_tagname|domelement_has_attribute|' +\n        'domelement_remove_attribute|domelement_set_attribute|domelement_set_attribute_node|domelement_tagname|domentity|domentityreference|' +\n        'domexception|domimplementation|domnamednodemap|domnode|domnode_add_namespace|domnode_append_child|domnode_append_sibling|' +\n        'domnode_attributes|domnode_child_nodes|domnode_clone_node|domnode_dump_node|domnode_first_child|domnode_get_content|' +\n        'domnode_has_attributes|domnode_has_child_nodes|domnode_insert_before|domnode_is_blank_node|domnode_last_child|domnode_next_sibling|' +\n        'domnode_node_name|domnode_node_type|domnode_node_value|domnode_owner_document|domnode_parent_node|domnode_prefix|domnode_previous_sibling|' +\n        'domnode_remove_child|domnode_replace_child|domnode_replace_node|domnode_set_content|domnode_set_name|domnode_set_namespace|' +\n        'domnode_unlink_node|domnodelist|domnotation|domprocessinginstruction|domprocessinginstruction_data|domprocessinginstruction_target|' +\n        'domtext|domxml_new_doc|domxml_open_file|domxml_open_mem|domxml_version|domxml_xmltree|domxml_xslt_stylesheet|domxml_xslt_stylesheet_doc|' +\n        'domxml_xslt_stylesheet_file|domxml_xslt_version|domxpath|domxsltstylesheet_process|domxsltstylesheet_result_dump_file|' +\n        'domxsltstylesheet_result_dump_mem|dotnet|dotnet_load|doubleval|each|easter_date|easter_days|echo|empty|emptyiterator|' +\n        'enchant_broker_describe|enchant_broker_dict_exists|enchant_broker_free|enchant_broker_free_dict|enchant_broker_get_error|' +\n        'enchant_broker_init|enchant_broker_list_dicts|enchant_broker_request_dict|enchant_broker_request_pwl_dict|enchant_broker_set_ordering|' +\n        'enchant_dict_add_to_personal|enchant_dict_add_to_session|enchant_dict_check|enchant_dict_describe|enchant_dict_get_error|' +\n        'enchant_dict_is_in_session|enchant_dict_quick_check|enchant_dict_store_replacement|enchant_dict_suggest|end|ereg|ereg_replace|eregi|' +\n        'eregi_replace|error_get_last|error_log|error_reporting|errorexception|escapeshellarg|escapeshellcmd|eval|event_add|event_base_free|' +\n        'event_base_loop|event_base_loopbreak|event_base_loopexit|event_base_new|event_base_priority_init|event_base_set|event_buffer_base_set|' +\n        'event_buffer_disable|event_buffer_enable|event_buffer_fd_set|event_buffer_free|event_buffer_new|event_buffer_priority_set|' +\n        'event_buffer_read|event_buffer_set_callback|event_buffer_timeout_set|event_buffer_watermark_set|event_buffer_write|event_del|event_free|' +\n        'event_new|event_set|exception|exec|exif_imagetype|exif_read_data|exif_tagname|exif_thumbnail|exit|exp|expect_expectl|expect_popen|explode|' +\n        'expm1|export|export|extension_loaded|extract|ezmlm_hash|fam_cancel_monitor|fam_close|fam_monitor_collection|fam_monitor_directory|' +\n        'fam_monitor_file|fam_next_event|fam_open|fam_pending|fam_resume_monitor|fam_suspend_monitor|fbsql_affected_rows|fbsql_autocommit|' +\n        'fbsql_blob_size|fbsql_change_user|fbsql_clob_size|fbsql_close|fbsql_commit|fbsql_connect|fbsql_create_blob|fbsql_create_clob|' +\n        'fbsql_create_db|fbsql_data_seek|fbsql_database|fbsql_database_password|fbsql_db_query|fbsql_db_status|fbsql_drop_db|fbsql_errno|' +\n        'fbsql_error|fbsql_fetch_array|fbsql_fetch_assoc|fbsql_fetch_field|fbsql_fetch_lengths|fbsql_fetch_object|fbsql_fetch_row|' +\n        'fbsql_field_flags|fbsql_field_len|fbsql_field_name|fbsql_field_seek|fbsql_field_table|fbsql_field_type|fbsql_free_result|' +\n        'fbsql_get_autostart_info|fbsql_hostname|fbsql_insert_id|fbsql_list_dbs|fbsql_list_fields|fbsql_list_tables|fbsql_next_result|' +\n        'fbsql_num_fields|fbsql_num_rows|fbsql_password|fbsql_pconnect|fbsql_query|fbsql_read_blob|fbsql_read_clob|fbsql_result|fbsql_rollback|' +\n        'fbsql_rows_fetched|fbsql_select_db|fbsql_set_characterset|fbsql_set_lob_mode|fbsql_set_password|fbsql_set_transaction|fbsql_start_db|' +\n        'fbsql_stop_db|fbsql_table_name|fbsql_tablename|fbsql_username|fbsql_warnings|fclose|fdf_add_doc_javascript|fdf_add_template|fdf_close|' +\n        'fdf_create|fdf_enum_values|fdf_errno|fdf_error|fdf_get_ap|fdf_get_attachment|fdf_get_encoding|fdf_get_file|fdf_get_flags|fdf_get_opt|' +\n        'fdf_get_status|fdf_get_value|fdf_get_version|fdf_header|fdf_next_field_name|fdf_open|fdf_open_string|fdf_remove_item|fdf_save|' +\n        'fdf_save_string|fdf_set_ap|fdf_set_encoding|fdf_set_file|fdf_set_flags|fdf_set_javascript_action|fdf_set_on_import_javascript|fdf_set_opt|' +\n        'fdf_set_status|fdf_set_submit_form_action|fdf_set_target_frame|fdf_set_value|fdf_set_version|feof|fflush|fgetc|fgetcsv|fgets|fgetss|file|' +\n        'file_exists|file_get_contents|file_put_contents|fileatime|filectime|filegroup|fileinode|filemtime|fileowner|fileperms|filepro|' +\n        'filepro_fieldcount|filepro_fieldname|filepro_fieldtype|filepro_fieldwidth|filepro_retrieve|filepro_rowcount|filesize|filesystemiterator|' +\n        'filetype|filter_has_var|filter_id|filter_input|filter_input_array|filter_list|filter_var|filter_var_array|filteriterator|finfo_buffer|' +\n        'finfo_close|finfo_file|finfo_open|finfo_set_flags|floatval|flock|floor|flush|fmod|fnmatch|fopen|forward_static_call|' +\n        'forward_static_call_array|fpassthru|fprintf|fputcsv|fputs|fread|frenchtojd|fribidi_log2vis|fscanf|fseek|fsockopen|fstat|ftell|ftok|' +\n        'ftp_alloc|ftp_cdup|ftp_chdir|ftp_chmod|ftp_close|ftp_connect|ftp_delete|ftp_exec|ftp_fget|ftp_fput|ftp_get|ftp_get_option|ftp_login|' +\n        'ftp_mdtm|ftp_mkdir|ftp_nb_continue|ftp_nb_fget|ftp_nb_fput|ftp_nb_get|ftp_nb_put|ftp_nlist|ftp_pasv|ftp_put|ftp_pwd|ftp_quit|ftp_raw|' +\n        'ftp_rawlist|ftp_rename|ftp_rmdir|ftp_set_option|ftp_site|ftp_size|ftp_ssl_connect|ftp_systype|ftruncate|func_get_arg|func_get_args|' +\n        'func_num_args|function_exists|fwrite|gc_collect_cycles|gc_disable|gc_enable|gc_enabled|gd_info|gearmanclient|gearmanjob|gearmantask|' +\n        'gearmanworker|geoip_continent_code_by_name|geoip_country_code3_by_name|geoip_country_code_by_name|geoip_country_name_by_name|' +\n        'geoip_database_info|geoip_db_avail|geoip_db_filename|geoip_db_get_all_info|geoip_id_by_name|geoip_isp_by_name|geoip_org_by_name|' +\n        'geoip_record_by_name|geoip_region_by_name|geoip_region_name_by_code|geoip_time_zone_by_country_and_region|getMeta|getNamed|getValue|' +\n        'get_browser|get_called_class|get_cfg_var|get_class|get_class_methods|get_class_vars|get_current_user|get_declared_classes|' +\n        'get_declared_interfaces|get_defined_constants|get_defined_functions|get_defined_vars|get_extension_funcs|get_headers|' +\n        'get_html_translation_table|get_include_path|get_included_files|get_loaded_extensions|get_magic_quotes_gpc|get_magic_quotes_runtime|' +\n        'get_meta_tags|get_object_vars|get_parent_class|get_required_files|get_resource_type|getallheaders|getconstant|getconstants|getconstructor|' +\n        'getcwd|getdate|getdefaultproperties|getdoccomment|getendline|getenv|getextension|getextensionname|getfilename|gethostbyaddr|gethostbyname|' +\n        'gethostbynamel|gethostname|getimagesize|getinterfacenames|getinterfaces|getlastmod|getmethod|getmethods|getmodifiers|getmxrr|getmygid|' +\n        'getmyinode|getmypid|getmyuid|getname|getnamespacename|getopt|getparentclass|getproperties|getproperty|getprotobyname|getprotobynumber|' +\n        'getrandmax|getrusage|getservbyname|getservbyport|getshortname|getstartline|getstaticproperties|getstaticpropertyvalue|gettext|' +\n        'gettimeofday|gettype|glob|globiterator|gmagick|gmagickdraw|gmagickpixel|gmdate|gmmktime|gmp_abs|gmp_add|gmp_and|gmp_clrbit|gmp_cmp|' +\n        'gmp_com|gmp_div|gmp_div_q|gmp_div_qr|gmp_div_r|gmp_divexact|gmp_fact|gmp_gcd|gmp_gcdext|gmp_hamdist|gmp_init|gmp_intval|gmp_invert|' +\n        'gmp_jacobi|gmp_legendre|gmp_mod|gmp_mul|gmp_neg|gmp_nextprime|gmp_or|gmp_perfect_square|gmp_popcount|gmp_pow|gmp_powm|gmp_prob_prime|' +\n        'gmp_random|gmp_scan0|gmp_scan1|gmp_setbit|gmp_sign|gmp_sqrt|gmp_sqrtrem|gmp_strval|gmp_sub|gmp_testbit|gmp_xor|gmstrftime|' +\n        'gnupg_adddecryptkey|gnupg_addencryptkey|gnupg_addsignkey|gnupg_cleardecryptkeys|gnupg_clearencryptkeys|gnupg_clearsignkeys|gnupg_decrypt|' +\n        'gnupg_decryptverify|gnupg_encrypt|gnupg_encryptsign|gnupg_export|gnupg_geterror|gnupg_getprotocol|gnupg_import|gnupg_init|gnupg_keyinfo|' +\n        'gnupg_setarmor|gnupg_seterrormode|gnupg_setsignmode|gnupg_sign|gnupg_verify|gopher_parsedir|grapheme_extract|grapheme_stripos|' +\n        'grapheme_stristr|grapheme_strlen|grapheme_strpos|grapheme_strripos|grapheme_strrpos|grapheme_strstr|grapheme_substr|gregoriantojd|' +\n        'gupnp_context_get_host_ip|gupnp_context_get_port|gupnp_context_get_subscription_timeout|gupnp_context_host_path|gupnp_context_new|' +\n        'gupnp_context_set_subscription_timeout|gupnp_context_timeout_add|gupnp_context_unhost_path|gupnp_control_point_browse_start|' +\n        'gupnp_control_point_browse_stop|gupnp_control_point_callback_set|gupnp_control_point_new|gupnp_device_action_callback_set|' +\n        'gupnp_device_info_get|gupnp_device_info_get_service|gupnp_root_device_get_available|gupnp_root_device_get_relative_location|' +\n        'gupnp_root_device_new|gupnp_root_device_set_available|gupnp_root_device_start|gupnp_root_device_stop|gupnp_service_action_get|' +\n        'gupnp_service_action_return|gupnp_service_action_return_error|gupnp_service_action_set|gupnp_service_freeze_notify|gupnp_service_info_get|' +\n        'gupnp_service_info_get_introspection|gupnp_service_introspection_get_state_variable|gupnp_service_notify|gupnp_service_proxy_action_get|' +\n        'gupnp_service_proxy_action_set|gupnp_service_proxy_add_notify|gupnp_service_proxy_callback_set|gupnp_service_proxy_get_subscribed|' +\n        'gupnp_service_proxy_remove_notify|gupnp_service_proxy_set_subscribed|gupnp_service_thaw_notify|gzclose|gzcompress|gzdecode|gzdeflate|' +\n        'gzencode|gzeof|gzfile|gzgetc|gzgets|gzgetss|gzinflate|gzopen|gzpassthru|gzputs|gzread|gzrewind|gzseek|gztell|gzuncompress|gzwrite|' +\n        'halt_compiler|haruannotation|haruannotation_setborderstyle|haruannotation_sethighlightmode|haruannotation_seticon|' +\n        'haruannotation_setopened|harudestination|harudestination_setfit|harudestination_setfitb|harudestination_setfitbh|harudestination_setfitbv|' +\n        'harudestination_setfith|harudestination_setfitr|harudestination_setfitv|harudestination_setxyz|harudoc|harudoc_addpage|' +\n        'harudoc_addpagelabel|harudoc_construct|harudoc_createoutline|harudoc_getcurrentencoder|harudoc_getcurrentpage|harudoc_getencoder|' +\n        'harudoc_getfont|harudoc_getinfoattr|harudoc_getpagelayout|harudoc_getpagemode|harudoc_getstreamsize|harudoc_insertpage|harudoc_loadjpeg|' +\n        'harudoc_loadpng|harudoc_loadraw|harudoc_loadttc|harudoc_loadttf|harudoc_loadtype1|harudoc_output|harudoc_readfromstream|' +\n        'harudoc_reseterror|harudoc_resetstream|harudoc_save|harudoc_savetostream|harudoc_setcompressionmode|harudoc_setcurrentencoder|' +\n        'harudoc_setencryptionmode|harudoc_setinfoattr|harudoc_setinfodateattr|harudoc_setopenaction|harudoc_setpagelayout|harudoc_setpagemode|' +\n        'harudoc_setpagesconfiguration|harudoc_setpassword|harudoc_setpermission|harudoc_usecnsencodings|harudoc_usecnsfonts|' +\n        'harudoc_usecntencodings|harudoc_usecntfonts|harudoc_usejpencodings|harudoc_usejpfonts|harudoc_usekrencodings|harudoc_usekrfonts|' +\n        'haruencoder|haruencoder_getbytetype|haruencoder_gettype|haruencoder_getunicode|haruencoder_getwritingmode|haruexception|harufont|' +\n        'harufont_getascent|harufont_getcapheight|harufont_getdescent|harufont_getencodingname|harufont_getfontname|harufont_gettextwidth|' +\n        'harufont_getunicodewidth|harufont_getxheight|harufont_measuretext|haruimage|haruimage_getbitspercomponent|haruimage_getcolorspace|' +\n        'haruimage_getheight|haruimage_getsize|haruimage_getwidth|haruimage_setcolormask|haruimage_setmaskimage|haruoutline|' +\n        'haruoutline_setdestination|haruoutline_setopened|harupage|harupage_arc|harupage_begintext|harupage_circle|harupage_closepath|' +\n        'harupage_concat|harupage_createdestination|harupage_createlinkannotation|harupage_createtextannotation|harupage_createurlannotation|' +\n        'harupage_curveto|harupage_curveto2|harupage_curveto3|harupage_drawimage|harupage_ellipse|harupage_endpath|harupage_endtext|' +\n        'harupage_eofill|harupage_eofillstroke|harupage_fill|harupage_fillstroke|harupage_getcharspace|harupage_getcmykfill|harupage_getcmykstroke|' +\n        'harupage_getcurrentfont|harupage_getcurrentfontsize|harupage_getcurrentpos|harupage_getcurrenttextpos|harupage_getdash|' +\n        'harupage_getfillingcolorspace|harupage_getflatness|harupage_getgmode|harupage_getgrayfill|harupage_getgraystroke|harupage_getheight|' +\n        'harupage_gethorizontalscaling|harupage_getlinecap|harupage_getlinejoin|harupage_getlinewidth|harupage_getmiterlimit|harupage_getrgbfill|' +\n        'harupage_getrgbstroke|harupage_getstrokingcolorspace|harupage_gettextleading|harupage_gettextmatrix|harupage_gettextrenderingmode|' +\n        'harupage_gettextrise|harupage_gettextwidth|harupage_gettransmatrix|harupage_getwidth|harupage_getwordspace|harupage_lineto|' +\n        'harupage_measuretext|harupage_movetextpos|harupage_moveto|harupage_movetonextline|harupage_rectangle|harupage_setcharspace|' +\n        'harupage_setcmykfill|harupage_setcmykstroke|harupage_setdash|harupage_setflatness|harupage_setfontandsize|harupage_setgrayfill|' +\n        'harupage_setgraystroke|harupage_setheight|harupage_sethorizontalscaling|harupage_setlinecap|harupage_setlinejoin|harupage_setlinewidth|' +\n        'harupage_setmiterlimit|harupage_setrgbfill|harupage_setrgbstroke|harupage_setrotate|harupage_setsize|harupage_setslideshow|' +\n        'harupage_settextleading|harupage_settextmatrix|harupage_settextrenderingmode|harupage_settextrise|harupage_setwidth|harupage_setwordspace|' +\n        'harupage_showtext|harupage_showtextnextline|harupage_stroke|harupage_textout|harupage_textrect|hasconstant|hash|hash_algos|hash_copy|' +\n        'hash_file|hash_final|hash_hmac|hash_hmac_file|hash_init|hash_update|hash_update_file|hash_update_stream|hasmethod|hasproperty|header|' +\n        'header_register_callback|header_remove|headers_list|headers_sent|hebrev|hebrevc|hex2bin|hexdec|highlight_file|highlight_string|' +\n        'html_entity_decode|htmlentities|htmlspecialchars|htmlspecialchars_decode|http_build_cookie|http_build_query|http_build_str|http_build_url|' +\n        'http_cache_etag|http_cache_last_modified|http_chunked_decode|http_date|http_deflate|http_get|http_get_request_body|' +\n        'http_get_request_body_stream|http_get_request_headers|http_head|http_inflate|http_match_etag|http_match_modified|' +\n        'http_match_request_header|http_negotiate_charset|http_negotiate_content_type|http_negotiate_language|http_parse_cookie|http_parse_headers|' +\n        'http_parse_message|http_parse_params|http_persistent_handles_clean|http_persistent_handles_count|http_persistent_handles_ident|' +\n        'http_post_data|http_post_fields|http_put_data|http_put_file|http_put_stream|http_redirect|http_request|http_request_body_encode|' +\n        'http_request_method_exists|http_request_method_name|http_request_method_register|http_request_method_unregister|http_response_code|' +\n        'http_send_content_disposition|http_send_content_type|http_send_data|http_send_file|http_send_last_modified|http_send_status|' +\n        'http_send_stream|http_support|http_throttle|httpdeflatestream|httpdeflatestream_construct|httpdeflatestream_factory|' +\n        'httpdeflatestream_finish|httpdeflatestream_flush|httpdeflatestream_update|httpinflatestream|httpinflatestream_construct|' +\n        'httpinflatestream_factory|httpinflatestream_finish|httpinflatestream_flush|httpinflatestream_update|httpmessage|httpmessage_addheaders|' +\n        'httpmessage_construct|httpmessage_detach|httpmessage_factory|httpmessage_fromenv|httpmessage_fromstring|httpmessage_getbody|' +\n        'httpmessage_getheader|httpmessage_getheaders|httpmessage_gethttpversion|httpmessage_getparentmessage|httpmessage_getrequestmethod|' +\n        'httpmessage_getrequesturl|httpmessage_getresponsecode|httpmessage_getresponsestatus|httpmessage_gettype|httpmessage_guesscontenttype|' +\n        'httpmessage_prepend|httpmessage_reverse|httpmessage_send|httpmessage_setbody|httpmessage_setheaders|httpmessage_sethttpversion|' +\n        'httpmessage_setrequestmethod|httpmessage_setrequesturl|httpmessage_setresponsecode|httpmessage_setresponsestatus|httpmessage_settype|' +\n        'httpmessage_tomessagetypeobject|httpmessage_tostring|httpquerystring|httpquerystring_construct|httpquerystring_get|httpquerystring_mod|' +\n        'httpquerystring_set|httpquerystring_singleton|httpquerystring_toarray|httpquerystring_tostring|httpquerystring_xlate|httprequest|' +\n        'httprequest_addcookies|httprequest_addheaders|httprequest_addpostfields|httprequest_addpostfile|httprequest_addputdata|' +\n        'httprequest_addquerydata|httprequest_addrawpostdata|httprequest_addssloptions|httprequest_clearhistory|httprequest_construct|' +\n        'httprequest_enablecookies|httprequest_getcontenttype|httprequest_getcookies|httprequest_getheaders|httprequest_gethistory|' +\n        'httprequest_getmethod|httprequest_getoptions|httprequest_getpostfields|httprequest_getpostfiles|httprequest_getputdata|' +\n        'httprequest_getputfile|httprequest_getquerydata|httprequest_getrawpostdata|httprequest_getrawrequestmessage|' +\n        'httprequest_getrawresponsemessage|httprequest_getrequestmessage|httprequest_getresponsebody|httprequest_getresponsecode|' +\n        'httprequest_getresponsecookies|httprequest_getresponsedata|httprequest_getresponseheader|httprequest_getresponseinfo|' +\n        'httprequest_getresponsemessage|httprequest_getresponsestatus|httprequest_getssloptions|httprequest_geturl|httprequest_resetcookies|' +\n        'httprequest_send|httprequest_setcontenttype|httprequest_setcookies|httprequest_setheaders|httprequest_setmethod|httprequest_setoptions|' +\n        'httprequest_setpostfields|httprequest_setpostfiles|httprequest_setputdata|httprequest_setputfile|httprequest_setquerydata|' +\n        'httprequest_setrawpostdata|httprequest_setssloptions|httprequest_seturl|httprequestpool|httprequestpool_attach|httprequestpool_construct|' +\n        'httprequestpool_destruct|httprequestpool_detach|httprequestpool_getattachedrequests|httprequestpool_getfinishedrequests|' +\n        'httprequestpool_reset|httprequestpool_send|httprequestpool_socketperform|httprequestpool_socketselect|httpresponse|httpresponse_capture|' +\n        'httpresponse_getbuffersize|httpresponse_getcache|httpresponse_getcachecontrol|httpresponse_getcontentdisposition|' +\n        'httpresponse_getcontenttype|httpresponse_getdata|httpresponse_getetag|httpresponse_getfile|httpresponse_getgzip|httpresponse_getheader|' +\n        'httpresponse_getlastmodified|httpresponse_getrequestbody|httpresponse_getrequestbodystream|httpresponse_getrequestheaders|' +\n        'httpresponse_getstream|httpresponse_getthrottledelay|httpresponse_guesscontenttype|httpresponse_redirect|httpresponse_send|' +\n        'httpresponse_setbuffersize|httpresponse_setcache|httpresponse_setcachecontrol|httpresponse_setcontentdisposition|' +\n        'httpresponse_setcontenttype|httpresponse_setdata|httpresponse_setetag|httpresponse_setfile|httpresponse_setgzip|httpresponse_setheader|' +\n        'httpresponse_setlastmodified|httpresponse_setstream|httpresponse_setthrottledelay|httpresponse_status|hw_array2objrec|hw_changeobject|' +\n        'hw_children|hw_childrenobj|hw_close|hw_connect|hw_connection_info|hw_cp|hw_deleteobject|hw_docbyanchor|hw_docbyanchorobj|' +\n        'hw_document_attributes|hw_document_bodytag|hw_document_content|hw_document_setcontent|hw_document_size|hw_dummy|hw_edittext|hw_error|' +\n        'hw_errormsg|hw_free_document|hw_getanchors|hw_getanchorsobj|hw_getandlock|hw_getchildcoll|hw_getchildcollobj|hw_getchilddoccoll|' +\n        'hw_getchilddoccollobj|hw_getobject|hw_getobjectbyquery|hw_getobjectbyquerycoll|hw_getobjectbyquerycollobj|hw_getobjectbyqueryobj|' +\n        'hw_getparents|hw_getparentsobj|hw_getrellink|hw_getremote|hw_getremotechildren|hw_getsrcbydestobj|hw_gettext|hw_getusername|hw_identify|' +\n        'hw_incollections|hw_info|hw_inscoll|hw_insdoc|hw_insertanchors|hw_insertdocument|hw_insertobject|hw_mapid|hw_modifyobject|hw_mv|' +\n        'hw_new_document|hw_objrec2array|hw_output_document|hw_pconnect|hw_pipedocument|hw_root|hw_setlinkroot|hw_stat|hw_unlock|hw_who|' +\n        'hwapi_attribute|hwapi_attribute_key|hwapi_attribute_langdepvalue|hwapi_attribute_value|hwapi_attribute_values|hwapi_checkin|' +\n        'hwapi_checkout|hwapi_children|hwapi_content|hwapi_content_mimetype|hwapi_content_read|hwapi_copy|hwapi_dbstat|hwapi_dcstat|' +\n        'hwapi_dstanchors|hwapi_dstofsrcanchor|hwapi_error_count|hwapi_error_reason|hwapi_find|hwapi_ftstat|hwapi_hgcsp|hwapi_hwstat|' +\n        'hwapi_identify|hwapi_info|hwapi_insert|hwapi_insertanchor|hwapi_insertcollection|hwapi_insertdocument|hwapi_link|hwapi_lock|hwapi_move|' +\n        'hwapi_new_content|hwapi_object|hwapi_object_assign|hwapi_object_attreditable|hwapi_object_count|hwapi_object_insert|hwapi_object_new|' +\n        'hwapi_object_remove|hwapi_object_title|hwapi_object_value|hwapi_objectbyanchor|hwapi_parents|hwapi_reason_description|hwapi_reason_type|' +\n        'hwapi_remove|hwapi_replace|hwapi_setcommittedversion|hwapi_srcanchors|hwapi_srcsofdst|hwapi_unlock|hwapi_user|hwapi_userlist|hypot|' +\n        'ibase_add_user|ibase_affected_rows|ibase_backup|ibase_blob_add|ibase_blob_cancel|ibase_blob_close|ibase_blob_create|ibase_blob_echo|' +\n        'ibase_blob_get|ibase_blob_import|ibase_blob_info|ibase_blob_open|ibase_close|ibase_commit|ibase_commit_ret|ibase_connect|ibase_db_info|' +\n        'ibase_delete_user|ibase_drop_db|ibase_errcode|ibase_errmsg|ibase_execute|ibase_fetch_assoc|ibase_fetch_object|ibase_fetch_row|' +\n        'ibase_field_info|ibase_free_event_handler|ibase_free_query|ibase_free_result|ibase_gen_id|ibase_maintain_db|ibase_modify_user|' +\n        'ibase_name_result|ibase_num_fields|ibase_num_params|ibase_param_info|ibase_pconnect|ibase_prepare|ibase_query|ibase_restore|' +\n        'ibase_rollback|ibase_rollback_ret|ibase_server_info|ibase_service_attach|ibase_service_detach|ibase_set_event_handler|ibase_timefmt|' +\n        'ibase_trans|ibase_wait_event|iconv|iconv_get_encoding|iconv_mime_decode|iconv_mime_decode_headers|iconv_mime_encode|iconv_set_encoding|' +\n        'iconv_strlen|iconv_strpos|iconv_strrpos|iconv_substr|id3_get_frame_long_name|id3_get_frame_short_name|id3_get_genre_id|id3_get_genre_list|' +\n        'id3_get_genre_name|id3_get_tag|id3_get_version|id3_remove_tag|id3_set_tag|id3v2attachedpictureframe|id3v2frame|id3v2tag|idate|' +\n        'idn_to_ascii|idn_to_unicode|idn_to_utf8|ifx_affected_rows|ifx_blobinfile_mode|ifx_byteasvarchar|ifx_close|ifx_connect|ifx_copy_blob|' +\n        'ifx_create_blob|ifx_create_char|ifx_do|ifx_error|ifx_errormsg|ifx_fetch_row|ifx_fieldproperties|ifx_fieldtypes|ifx_free_blob|' +\n        'ifx_free_char|ifx_free_result|ifx_get_blob|ifx_get_char|ifx_getsqlca|ifx_htmltbl_result|ifx_nullformat|ifx_num_fields|ifx_num_rows|' +\n        'ifx_pconnect|ifx_prepare|ifx_query|ifx_textasvarchar|ifx_update_blob|ifx_update_char|ifxus_close_slob|ifxus_create_slob|ifxus_free_slob|' +\n        'ifxus_open_slob|ifxus_read_slob|ifxus_seek_slob|ifxus_tell_slob|ifxus_write_slob|ignore_user_abort|iis_add_server|iis_get_dir_security|' +\n        'iis_get_script_map|iis_get_server_by_comment|iis_get_server_by_path|iis_get_server_rights|iis_get_service_state|iis_remove_server|' +\n        'iis_set_app_settings|iis_set_dir_security|iis_set_script_map|iis_set_server_rights|iis_start_server|iis_start_service|iis_stop_server|' +\n        'iis_stop_service|image2wbmp|image_type_to_extension|image_type_to_mime_type|imagealphablending|imageantialias|imagearc|imagechar|' +\n        'imagecharup|imagecolorallocate|imagecolorallocatealpha|imagecolorat|imagecolorclosest|imagecolorclosestalpha|imagecolorclosesthwb|' +\n        'imagecolordeallocate|imagecolorexact|imagecolorexactalpha|imagecolormatch|imagecolorresolve|imagecolorresolvealpha|imagecolorset|' +\n        'imagecolorsforindex|imagecolorstotal|imagecolortransparent|imageconvolution|imagecopy|imagecopymerge|imagecopymergegray|' +\n        'imagecopyresampled|imagecopyresized|imagecreate|imagecreatefromgd|imagecreatefromgd2|imagecreatefromgd2part|imagecreatefromgif|' +\n        'imagecreatefromjpeg|imagecreatefrompng|imagecreatefromstring|imagecreatefromwbmp|imagecreatefromxbm|imagecreatefromxpm|' +\n        'imagecreatetruecolor|imagedashedline|imagedestroy|imageellipse|imagefill|imagefilledarc|imagefilledellipse|imagefilledpolygon|' +\n        'imagefilledrectangle|imagefilltoborder|imagefilter|imagefontheight|imagefontwidth|imageftbbox|imagefttext|imagegammacorrect|imagegd|' +\n        'imagegd2|imagegif|imagegrabscreen|imagegrabwindow|imageinterlace|imageistruecolor|imagejpeg|imagelayereffect|imageline|imageloadfont|' +\n        'imagepalettecopy|imagepng|imagepolygon|imagepsbbox|imagepsencodefont|imagepsextendfont|imagepsfreefont|imagepsloadfont|imagepsslantfont|' +\n        'imagepstext|imagerectangle|imagerotate|imagesavealpha|imagesetbrush|imagesetpixel|imagesetstyle|imagesetthickness|imagesettile|' +\n        'imagestring|imagestringup|imagesx|imagesy|imagetruecolortopalette|imagettfbbox|imagettftext|imagetypes|imagewbmp|imagexbm|imagick|' +\n        'imagick_adaptiveblurimage|imagick_adaptiveresizeimage|imagick_adaptivesharpenimage|imagick_adaptivethresholdimage|imagick_addimage|' +\n        'imagick_addnoiseimage|imagick_affinetransformimage|imagick_animateimages|imagick_annotateimage|imagick_appendimages|imagick_averageimages|' +\n        'imagick_blackthresholdimage|imagick_blurimage|imagick_borderimage|imagick_charcoalimage|imagick_chopimage|imagick_clear|imagick_clipimage|' +\n        'imagick_clippathimage|imagick_clone|imagick_clutimage|imagick_coalesceimages|imagick_colorfloodfillimage|imagick_colorizeimage|' +\n        'imagick_combineimages|imagick_commentimage|imagick_compareimagechannels|imagick_compareimagelayers|imagick_compareimages|' +\n        'imagick_compositeimage|imagick_construct|imagick_contrastimage|imagick_contraststretchimage|imagick_convolveimage|imagick_cropimage|' +\n        'imagick_cropthumbnailimage|imagick_current|imagick_cyclecolormapimage|imagick_decipherimage|imagick_deconstructimages|' +\n        'imagick_deleteimageartifact|imagick_despeckleimage|imagick_destroy|imagick_displayimage|imagick_displayimages|imagick_distortimage|' +\n        'imagick_drawimage|imagick_edgeimage|imagick_embossimage|imagick_encipherimage|imagick_enhanceimage|imagick_equalizeimage|' +\n        'imagick_evaluateimage|imagick_extentimage|imagick_flattenimages|imagick_flipimage|imagick_floodfillpaintimage|imagick_flopimage|' +\n        'imagick_frameimage|imagick_fximage|imagick_gammaimage|imagick_gaussianblurimage|imagick_getcolorspace|imagick_getcompression|' +\n        'imagick_getcompressionquality|imagick_getcopyright|imagick_getfilename|imagick_getfont|imagick_getformat|imagick_getgravity|' +\n        'imagick_gethomeurl|imagick_getimage|imagick_getimagealphachannel|imagick_getimageartifact|imagick_getimagebackgroundcolor|' +\n        'imagick_getimageblob|imagick_getimageblueprimary|imagick_getimagebordercolor|imagick_getimagechanneldepth|' +\n        'imagick_getimagechanneldistortion|imagick_getimagechanneldistortions|imagick_getimagechannelextrema|imagick_getimagechannelmean|' +\n        'imagick_getimagechannelrange|imagick_getimagechannelstatistics|imagick_getimageclipmask|imagick_getimagecolormapcolor|' +\n        'imagick_getimagecolors|imagick_getimagecolorspace|imagick_getimagecompose|imagick_getimagecompression|imagick_getimagecompressionquality|' +\n        'imagick_getimagedelay|imagick_getimagedepth|imagick_getimagedispose|imagick_getimagedistortion|imagick_getimageextrema|' +\n        'imagick_getimagefilename|imagick_getimageformat|imagick_getimagegamma|imagick_getimagegeometry|imagick_getimagegravity|' +\n        'imagick_getimagegreenprimary|imagick_getimageheight|imagick_getimagehistogram|imagick_getimageindex|imagick_getimageinterlacescheme|' +\n        'imagick_getimageinterpolatemethod|imagick_getimageiterations|imagick_getimagelength|imagick_getimagemagicklicense|imagick_getimagematte|' +\n        'imagick_getimagemattecolor|imagick_getimageorientation|imagick_getimagepage|imagick_getimagepixelcolor|imagick_getimageprofile|' +\n        'imagick_getimageprofiles|imagick_getimageproperties|imagick_getimageproperty|imagick_getimageredprimary|imagick_getimageregion|' +\n        'imagick_getimagerenderingintent|imagick_getimageresolution|imagick_getimagesblob|imagick_getimagescene|imagick_getimagesignature|' +\n        'imagick_getimagesize|imagick_getimagetickspersecond|imagick_getimagetotalinkdensity|imagick_getimagetype|imagick_getimageunits|' +\n        'imagick_getimagevirtualpixelmethod|imagick_getimagewhitepoint|imagick_getimagewidth|imagick_getinterlacescheme|imagick_getiteratorindex|' +\n        'imagick_getnumberimages|imagick_getoption|imagick_getpackagename|imagick_getpage|imagick_getpixeliterator|imagick_getpixelregioniterator|' +\n        'imagick_getpointsize|imagick_getquantumdepth|imagick_getquantumrange|imagick_getreleasedate|imagick_getresource|imagick_getresourcelimit|' +\n        'imagick_getsamplingfactors|imagick_getsize|imagick_getsizeoffset|imagick_getversion|imagick_hasnextimage|imagick_haspreviousimage|' +\n        'imagick_identifyimage|imagick_implodeimage|imagick_labelimage|imagick_levelimage|imagick_linearstretchimage|imagick_liquidrescaleimage|' +\n        'imagick_magnifyimage|imagick_mapimage|imagick_mattefloodfillimage|imagick_medianfilterimage|imagick_mergeimagelayers|imagick_minifyimage|' +\n        'imagick_modulateimage|imagick_montageimage|imagick_morphimages|imagick_mosaicimages|imagick_motionblurimage|imagick_negateimage|' +\n        'imagick_newimage|imagick_newpseudoimage|imagick_nextimage|imagick_normalizeimage|imagick_oilpaintimage|imagick_opaquepaintimage|' +\n        'imagick_optimizeimagelayers|imagick_orderedposterizeimage|imagick_paintfloodfillimage|imagick_paintopaqueimage|' +\n        'imagick_painttransparentimage|imagick_pingimage|imagick_pingimageblob|imagick_pingimagefile|imagick_polaroidimage|imagick_posterizeimage|' +\n        'imagick_previewimages|imagick_previousimage|imagick_profileimage|imagick_quantizeimage|imagick_quantizeimages|imagick_queryfontmetrics|' +\n        'imagick_queryfonts|imagick_queryformats|imagick_radialblurimage|imagick_raiseimage|imagick_randomthresholdimage|imagick_readimage|' +\n        'imagick_readimageblob|imagick_readimagefile|imagick_recolorimage|imagick_reducenoiseimage|imagick_removeimage|imagick_removeimageprofile|' +\n        'imagick_render|imagick_resampleimage|imagick_resetimagepage|imagick_resizeimage|imagick_rollimage|imagick_rotateimage|' +\n        'imagick_roundcorners|imagick_sampleimage|imagick_scaleimage|imagick_separateimagechannel|imagick_sepiatoneimage|' +\n        'imagick_setbackgroundcolor|imagick_setcolorspace|imagick_setcompression|imagick_setcompressionquality|imagick_setfilename|' +\n        'imagick_setfirstiterator|imagick_setfont|imagick_setformat|imagick_setgravity|imagick_setimage|imagick_setimagealphachannel|' +\n        'imagick_setimageartifact|imagick_setimagebackgroundcolor|imagick_setimagebias|imagick_setimageblueprimary|imagick_setimagebordercolor|' +\n        'imagick_setimagechanneldepth|imagick_setimageclipmask|imagick_setimagecolormapcolor|imagick_setimagecolorspace|imagick_setimagecompose|' +\n        'imagick_setimagecompression|imagick_setimagecompressionquality|imagick_setimagedelay|imagick_setimagedepth|imagick_setimagedispose|' +\n        'imagick_setimageextent|imagick_setimagefilename|imagick_setimageformat|imagick_setimagegamma|imagick_setimagegravity|' +\n        'imagick_setimagegreenprimary|imagick_setimageindex|imagick_setimageinterlacescheme|imagick_setimageinterpolatemethod|' +\n        'imagick_setimageiterations|imagick_setimagematte|imagick_setimagemattecolor|imagick_setimageopacity|imagick_setimageorientation|' +\n        'imagick_setimagepage|imagick_setimageprofile|imagick_setimageproperty|imagick_setimageredprimary|imagick_setimagerenderingintent|' +\n        'imagick_setimageresolution|imagick_setimagescene|imagick_setimagetickspersecond|imagick_setimagetype|imagick_setimageunits|' +\n        'imagick_setimagevirtualpixelmethod|imagick_setimagewhitepoint|imagick_setinterlacescheme|imagick_setiteratorindex|imagick_setlastiterator|' +\n        'imagick_setoption|imagick_setpage|imagick_setpointsize|imagick_setresolution|imagick_setresourcelimit|imagick_setsamplingfactors|' +\n        'imagick_setsize|imagick_setsizeoffset|imagick_settype|imagick_shadeimage|imagick_shadowimage|imagick_sharpenimage|imagick_shaveimage|' +\n        'imagick_shearimage|imagick_sigmoidalcontrastimage|imagick_sketchimage|imagick_solarizeimage|imagick_spliceimage|imagick_spreadimage|' +\n        'imagick_steganoimage|imagick_stereoimage|imagick_stripimage|imagick_swirlimage|imagick_textureimage|imagick_thresholdimage|' +\n        'imagick_thumbnailimage|imagick_tintimage|imagick_transformimage|imagick_transparentpaintimage|imagick_transposeimage|' +\n        'imagick_transverseimage|imagick_trimimage|imagick_uniqueimagecolors|imagick_unsharpmaskimage|imagick_valid|imagick_vignetteimage|' +\n        'imagick_waveimage|imagick_whitethresholdimage|imagick_writeimage|imagick_writeimagefile|imagick_writeimages|imagick_writeimagesfile|' +\n        'imagickdraw|imagickdraw_affine|imagickdraw_annotation|imagickdraw_arc|imagickdraw_bezier|imagickdraw_circle|imagickdraw_clear|' +\n        'imagickdraw_clone|imagickdraw_color|imagickdraw_comment|imagickdraw_composite|imagickdraw_construct|imagickdraw_destroy|' +\n        'imagickdraw_ellipse|imagickdraw_getclippath|imagickdraw_getcliprule|imagickdraw_getclipunits|imagickdraw_getfillcolor|' +\n        'imagickdraw_getfillopacity|imagickdraw_getfillrule|imagickdraw_getfont|imagickdraw_getfontfamily|imagickdraw_getfontsize|' +\n        'imagickdraw_getfontstyle|imagickdraw_getfontweight|imagickdraw_getgravity|imagickdraw_getstrokeantialias|imagickdraw_getstrokecolor|' +\n        'imagickdraw_getstrokedasharray|imagickdraw_getstrokedashoffset|imagickdraw_getstrokelinecap|imagickdraw_getstrokelinejoin|' +\n        'imagickdraw_getstrokemiterlimit|imagickdraw_getstrokeopacity|imagickdraw_getstrokewidth|imagickdraw_gettextalignment|' +\n        'imagickdraw_gettextantialias|imagickdraw_gettextdecoration|imagickdraw_gettextencoding|imagickdraw_gettextundercolor|' +\n        'imagickdraw_getvectorgraphics|imagickdraw_line|imagickdraw_matte|imagickdraw_pathclose|imagickdraw_pathcurvetoabsolute|' +\n        'imagickdraw_pathcurvetoquadraticbezierabsolute|imagickdraw_pathcurvetoquadraticbezierrelative|' +\n        'imagickdraw_pathcurvetoquadraticbeziersmoothabsolute|imagickdraw_pathcurvetoquadraticbeziersmoothrelative|imagickdraw_pathcurvetorelative|' +\n        'imagickdraw_pathcurvetosmoothabsolute|imagickdraw_pathcurvetosmoothrelative|imagickdraw_pathellipticarcabsolute|' +\n        'imagickdraw_pathellipticarcrelative|imagickdraw_pathfinish|imagickdraw_pathlinetoabsolute|imagickdraw_pathlinetohorizontalabsolute|' +\n        'imagickdraw_pathlinetohorizontalrelative|imagickdraw_pathlinetorelative|imagickdraw_pathlinetoverticalabsolute|' +\n        'imagickdraw_pathlinetoverticalrelative|imagickdraw_pathmovetoabsolute|imagickdraw_pathmovetorelative|imagickdraw_pathstart|' +\n        'imagickdraw_point|imagickdraw_polygon|imagickdraw_polyline|imagickdraw_pop|imagickdraw_popclippath|imagickdraw_popdefs|' +\n        'imagickdraw_poppattern|imagickdraw_push|imagickdraw_pushclippath|imagickdraw_pushdefs|imagickdraw_pushpattern|imagickdraw_rectangle|' +\n        'imagickdraw_render|imagickdraw_rotate|imagickdraw_roundrectangle|imagickdraw_scale|imagickdraw_setclippath|imagickdraw_setcliprule|' +\n        'imagickdraw_setclipunits|imagickdraw_setfillalpha|imagickdraw_setfillcolor|imagickdraw_setfillopacity|imagickdraw_setfillpatternurl|' +\n        'imagickdraw_setfillrule|imagickdraw_setfont|imagickdraw_setfontfamily|imagickdraw_setfontsize|imagickdraw_setfontstretch|' +\n        'imagickdraw_setfontstyle|imagickdraw_setfontweight|imagickdraw_setgravity|imagickdraw_setstrokealpha|imagickdraw_setstrokeantialias|' +\n        'imagickdraw_setstrokecolor|imagickdraw_setstrokedasharray|imagickdraw_setstrokedashoffset|imagickdraw_setstrokelinecap|' +\n        'imagickdraw_setstrokelinejoin|imagickdraw_setstrokemiterlimit|imagickdraw_setstrokeopacity|imagickdraw_setstrokepatternurl|' +\n        'imagickdraw_setstrokewidth|imagickdraw_settextalignment|imagickdraw_settextantialias|imagickdraw_settextdecoration|' +\n        'imagickdraw_settextencoding|imagickdraw_settextundercolor|imagickdraw_setvectorgraphics|imagickdraw_setviewbox|imagickdraw_skewx|' +\n        'imagickdraw_skewy|imagickdraw_translate|imagickpixel|imagickpixel_clear|imagickpixel_construct|imagickpixel_destroy|imagickpixel_getcolor|' +\n        'imagickpixel_getcolorasstring|imagickpixel_getcolorcount|imagickpixel_getcolorvalue|imagickpixel_gethsl|imagickpixel_issimilar|' +\n        'imagickpixel_setcolor|imagickpixel_setcolorvalue|imagickpixel_sethsl|imagickpixeliterator|imagickpixeliterator_clear|' +\n        'imagickpixeliterator_construct|imagickpixeliterator_destroy|imagickpixeliterator_getcurrentiteratorrow|' +\n        'imagickpixeliterator_getiteratorrow|imagickpixeliterator_getnextiteratorrow|imagickpixeliterator_getpreviousiteratorrow|' +\n        'imagickpixeliterator_newpixeliterator|imagickpixeliterator_newpixelregioniterator|imagickpixeliterator_resetiterator|' +\n        'imagickpixeliterator_setiteratorfirstrow|imagickpixeliterator_setiteratorlastrow|imagickpixeliterator_setiteratorrow|' +\n        'imagickpixeliterator_synciterator|imap_8bit|imap_alerts|imap_append|imap_base64|imap_binary|imap_body|imap_bodystruct|imap_check|' +\n        'imap_clearflag_full|imap_close|imap_create|imap_createmailbox|imap_delete|imap_deletemailbox|imap_errors|imap_expunge|imap_fetch_overview|' +\n        'imap_fetchbody|imap_fetchheader|imap_fetchmime|imap_fetchstructure|imap_fetchtext|imap_gc|imap_get_quota|imap_get_quotaroot|imap_getacl|' +\n        'imap_getmailboxes|imap_getsubscribed|imap_header|imap_headerinfo|imap_headers|imap_last_error|imap_list|imap_listmailbox|imap_listscan|' +\n        'imap_listsubscribed|imap_lsub|imap_mail|imap_mail_compose|imap_mail_copy|imap_mail_move|imap_mailboxmsginfo|imap_mime_header_decode|' +\n        'imap_msgno|imap_num_msg|imap_num_recent|imap_open|imap_ping|imap_qprint|imap_rename|imap_renamemailbox|imap_reopen|' +\n        'imap_rfc822_parse_adrlist|imap_rfc822_parse_headers|imap_rfc822_write_address|imap_savebody|imap_scan|imap_scanmailbox|imap_search|' +\n        'imap_set_quota|imap_setacl|imap_setflag_full|imap_sort|imap_status|imap_subscribe|imap_thread|imap_timeout|imap_uid|imap_undelete|' +\n        'imap_unsubscribe|imap_utf7_decode|imap_utf7_encode|imap_utf8|implementsinterface|implode|import_request_variables|in_array|include|' +\n        'include_once|inclued_get_data|inet_ntop|inet_pton|infiniteiterator|ingres_autocommit|ingres_autocommit_state|ingres_charset|ingres_close|' +\n        'ingres_commit|ingres_connect|ingres_cursor|ingres_errno|ingres_error|ingres_errsqlstate|ingres_escape_string|ingres_execute|' +\n        'ingres_fetch_array|ingres_fetch_assoc|ingres_fetch_object|ingres_fetch_proc_return|ingres_fetch_row|ingres_field_length|ingres_field_name|' +\n        'ingres_field_nullable|ingres_field_precision|ingres_field_scale|ingres_field_type|ingres_free_result|ingres_next_error|ingres_num_fields|' +\n        'ingres_num_rows|ingres_pconnect|ingres_prepare|ingres_query|ingres_result_seek|ingres_rollback|ingres_set_environment|' +\n        'ingres_unbuffered_query|ini_alter|ini_get|ini_get_all|ini_restore|ini_set|innamespace|inotify_add_watch|inotify_init|inotify_queue_len|' +\n        'inotify_read|inotify_rm_watch|interface_exists|intl_error_name|intl_get_error_code|intl_get_error_message|intl_is_failure|' +\n        'intldateformatter|intval|invalidargumentexception|invoke|invokeargs|ip2long|iptcembed|iptcparse|is_a|is_array|is_bool|is_callable|is_dir|' +\n        'is_double|is_executable|is_file|is_finite|is_float|is_infinite|is_int|is_integer|is_link|is_long|is_nan|is_null|is_numeric|is_object|' +\n        'is_readable|is_real|is_resource|is_scalar|is_soap_fault|is_string|is_subclass_of|is_uploaded_file|is_writable|is_writeable|isabstract|' +\n        'iscloneable|isdisabled|isfinal|isinstance|isinstantiable|isinterface|isinternal|isiterateable|isset|issubclassof|isuserdefined|iterator|' +\n        'iterator_apply|iterator_count|iterator_to_array|iteratoraggregate|iteratoriterator|java_last_exception_clear|java_last_exception_get|' +\n        'jddayofweek|jdmonthname|jdtofrench|jdtogregorian|jdtojewish|jdtojulian|jdtounix|jewishtojd|join|jpeg2wbmp|json_decode|json_encode|' +\n        'json_last_error|jsonserializable|judy|judy_type|judy_version|juliantojd|kadm5_chpass_principal|kadm5_create_principal|' +\n        'kadm5_delete_principal|kadm5_destroy|kadm5_flush|kadm5_get_policies|kadm5_get_principal|kadm5_get_principals|kadm5_init_with_password|' +\n        'kadm5_modify_principal|key|krsort|ksort|lcfirst|lcg_value|lchgrp|lchown|ldap_8859_to_t61|ldap_add|ldap_bind|ldap_close|ldap_compare|' +\n        'ldap_connect|ldap_count_entries|ldap_delete|ldap_dn2ufn|ldap_err2str|ldap_errno|ldap_error|ldap_explode_dn|ldap_first_attribute|' +\n        'ldap_first_entry|ldap_first_reference|ldap_free_result|ldap_get_attributes|ldap_get_dn|ldap_get_entries|ldap_get_option|ldap_get_values|' +\n        'ldap_get_values_len|ldap_list|ldap_mod_add|ldap_mod_del|ldap_mod_replace|ldap_modify|ldap_next_attribute|ldap_next_entry|' +\n        'ldap_next_reference|ldap_parse_reference|ldap_parse_result|ldap_read|ldap_rename|ldap_sasl_bind|ldap_search|ldap_set_option|' +\n        'ldap_set_rebind_proc|ldap_sort|ldap_start_tls|ldap_t61_to_8859|ldap_unbind|lengthexception|levenshtein|libxml_clear_errors|' +\n        'libxml_disable_entity_loader|libxml_get_errors|libxml_get_last_error|libxml_set_streams_context|libxml_use_internal_errors|libxmlerror|' +\n        'limititerator|link|linkinfo|list|locale|localeconv|localtime|log|log10|log1p|logicexception|long2ip|lstat|ltrim|lzf_compress|' +\n        'lzf_decompress|lzf_optimized_for|m_checkstatus|m_completeauthorizations|m_connect|m_connectionerror|m_deletetrans|m_destroyconn|' +\n        'm_destroyengine|m_getcell|m_getcellbynum|m_getcommadelimited|m_getheader|m_initconn|m_initengine|m_iscommadelimited|m_maxconntimeout|' +\n        'm_monitor|m_numcolumns|m_numrows|m_parsecommadelimited|m_responsekeys|m_responseparam|m_returnstatus|m_setblocking|m_setdropfile|m_setip|' +\n        'm_setssl|m_setssl_cafile|m_setssl_files|m_settimeout|m_sslcert_gen_hash|m_transactionssent|m_transinqueue|m_transkeyval|m_transnew|' +\n        'm_transsend|m_uwait|m_validateidentifier|m_verifyconnection|m_verifysslcert|magic_quotes_runtime|mail|' +\n        'mailparse_determine_best_xfer_encoding|mailparse_msg_create|mailparse_msg_extract_part|mailparse_msg_extract_part_file|' +\n        'mailparse_msg_extract_whole_part_file|mailparse_msg_free|mailparse_msg_get_part|mailparse_msg_get_part_data|mailparse_msg_get_structure|' +\n        'mailparse_msg_parse|mailparse_msg_parse_file|mailparse_rfc822_parse_addresses|mailparse_stream_encode|mailparse_uudecode_all|main|max|' +\n        'maxdb_affected_rows|maxdb_autocommit|maxdb_bind_param|maxdb_bind_result|maxdb_change_user|maxdb_character_set_name|maxdb_client_encoding|' +\n        'maxdb_close|maxdb_close_long_data|maxdb_commit|maxdb_connect|maxdb_connect_errno|maxdb_connect_error|maxdb_data_seek|maxdb_debug|' +\n        'maxdb_disable_reads_from_master|maxdb_disable_rpl_parse|maxdb_dump_debug_info|maxdb_embedded_connect|maxdb_enable_reads_from_master|' +\n        'maxdb_enable_rpl_parse|maxdb_errno|maxdb_error|maxdb_escape_string|maxdb_execute|maxdb_fetch|maxdb_fetch_array|maxdb_fetch_assoc|' +\n        'maxdb_fetch_field|maxdb_fetch_field_direct|maxdb_fetch_fields|maxdb_fetch_lengths|maxdb_fetch_object|maxdb_fetch_row|maxdb_field_count|' +\n        'maxdb_field_seek|maxdb_field_tell|maxdb_free_result|maxdb_get_client_info|maxdb_get_client_version|maxdb_get_host_info|maxdb_get_metadata|' +\n        'maxdb_get_proto_info|maxdb_get_server_info|maxdb_get_server_version|maxdb_info|maxdb_init|maxdb_insert_id|maxdb_kill|maxdb_master_query|' +\n        'maxdb_more_results|maxdb_multi_query|maxdb_next_result|maxdb_num_fields|maxdb_num_rows|maxdb_options|maxdb_param_count|maxdb_ping|' +\n        'maxdb_prepare|maxdb_query|maxdb_real_connect|maxdb_real_escape_string|maxdb_real_query|maxdb_report|maxdb_rollback|' +\n        'maxdb_rpl_parse_enabled|maxdb_rpl_probe|maxdb_rpl_query_type|maxdb_select_db|maxdb_send_long_data|maxdb_send_query|maxdb_server_end|' +\n        'maxdb_server_init|maxdb_set_opt|maxdb_sqlstate|maxdb_ssl_set|maxdb_stat|maxdb_stmt_affected_rows|maxdb_stmt_bind_param|' +\n        'maxdb_stmt_bind_result|maxdb_stmt_close|maxdb_stmt_close_long_data|maxdb_stmt_data_seek|maxdb_stmt_errno|maxdb_stmt_error|' +\n        'maxdb_stmt_execute|maxdb_stmt_fetch|maxdb_stmt_free_result|maxdb_stmt_init|maxdb_stmt_num_rows|maxdb_stmt_param_count|maxdb_stmt_prepare|' +\n        'maxdb_stmt_reset|maxdb_stmt_result_metadata|maxdb_stmt_send_long_data|maxdb_stmt_sqlstate|maxdb_stmt_store_result|maxdb_store_result|' +\n        'maxdb_thread_id|maxdb_thread_safe|maxdb_use_result|maxdb_warning_count|mb_check_encoding|mb_convert_case|mb_convert_encoding|' +\n        'mb_convert_kana|mb_convert_variables|mb_decode_mimeheader|mb_decode_numericentity|mb_detect_encoding|mb_detect_order|mb_encode_mimeheader|' +\n        'mb_encode_numericentity|mb_encoding_aliases|mb_ereg|mb_ereg_match|mb_ereg_replace|mb_ereg_search|mb_ereg_search_getpos|' +\n        'mb_ereg_search_getregs|mb_ereg_search_init|mb_ereg_search_pos|mb_ereg_search_regs|mb_ereg_search_setpos|mb_eregi|mb_eregi_replace|' +\n        'mb_get_info|mb_http_input|mb_http_output|mb_internal_encoding|mb_language|mb_list_encodings|mb_output_handler|mb_parse_str|' +\n        'mb_preferred_mime_name|mb_regex_encoding|mb_regex_set_options|mb_send_mail|mb_split|mb_strcut|mb_strimwidth|mb_stripos|mb_stristr|' +\n        'mb_strlen|mb_strpos|mb_strrchr|mb_strrichr|mb_strripos|mb_strrpos|mb_strstr|mb_strtolower|mb_strtoupper|mb_strwidth|' +\n        'mb_substitute_character|mb_substr|mb_substr_count|mcrypt_cbc|mcrypt_cfb|mcrypt_create_iv|mcrypt_decrypt|mcrypt_ecb|' +\n        'mcrypt_enc_get_algorithms_name|mcrypt_enc_get_block_size|mcrypt_enc_get_iv_size|mcrypt_enc_get_key_size|mcrypt_enc_get_modes_name|' +\n        'mcrypt_enc_get_supported_key_sizes|mcrypt_enc_is_block_algorithm|mcrypt_enc_is_block_algorithm_mode|mcrypt_enc_is_block_mode|' +\n        'mcrypt_enc_self_test|mcrypt_encrypt|mcrypt_generic|mcrypt_generic_deinit|mcrypt_generic_end|mcrypt_generic_init|mcrypt_get_block_size|' +\n        'mcrypt_get_cipher_name|mcrypt_get_iv_size|mcrypt_get_key_size|mcrypt_list_algorithms|mcrypt_list_modes|mcrypt_module_close|' +\n        'mcrypt_module_get_algo_block_size|mcrypt_module_get_algo_key_size|mcrypt_module_get_supported_key_sizes|mcrypt_module_is_block_algorithm|' +\n        'mcrypt_module_is_block_algorithm_mode|mcrypt_module_is_block_mode|mcrypt_module_open|mcrypt_module_self_test|mcrypt_ofb|md5|md5_file|' +\n        'mdecrypt_generic|memcache|memcache_debug|memcached|memory_get_peak_usage|memory_get_usage|messageformatter|metaphone|method_exists|mhash|' +\n        'mhash_count|mhash_get_block_size|mhash_get_hash_name|mhash_keygen_s2k|microtime|mime_content_type|min|ming_keypress|' +\n        'ming_setcubicthreshold|ming_setscale|ming_setswfcompression|ming_useconstants|ming_useswfversion|mkdir|mktime|money_format|mongo|' +\n        'mongobindata|mongocode|mongocollection|mongoconnectionexception|mongocursor|mongocursorexception|mongocursortimeoutexception|mongodate|' +\n        'mongodb|mongodbref|mongoexception|mongogridfs|mongogridfscursor|mongogridfsexception|mongogridfsfile|mongoid|mongoint32|mongoint64|' +\n        'mongomaxkey|mongominkey|mongoregex|mongotimestamp|move_uploaded_file|mpegfile|mqseries_back|mqseries_begin|mqseries_close|mqseries_cmit|' +\n        'mqseries_conn|mqseries_connx|mqseries_disc|mqseries_get|mqseries_inq|mqseries_open|mqseries_put|mqseries_put1|mqseries_set|' +\n        'mqseries_strerror|msession_connect|msession_count|msession_create|msession_destroy|msession_disconnect|msession_find|msession_get|' +\n        'msession_get_array|msession_get_data|msession_inc|msession_list|msession_listvar|msession_lock|msession_plugin|msession_randstr|' +\n        'msession_set|msession_set_array|msession_set_data|msession_timeout|msession_uniq|msession_unlock|msg_get_queue|msg_queue_exists|' +\n        'msg_receive|msg_remove_queue|msg_send|msg_set_queue|msg_stat_queue|msql|msql_affected_rows|msql_close|msql_connect|msql_create_db|' +\n        'msql_createdb|msql_data_seek|msql_db_query|msql_dbname|msql_drop_db|msql_error|msql_fetch_array|msql_fetch_field|msql_fetch_object|' +\n        'msql_fetch_row|msql_field_flags|msql_field_len|msql_field_name|msql_field_seek|msql_field_table|msql_field_type|msql_fieldflags|' +\n        'msql_fieldlen|msql_fieldname|msql_fieldtable|msql_fieldtype|msql_free_result|msql_list_dbs|msql_list_fields|msql_list_tables|' +\n        'msql_num_fields|msql_num_rows|msql_numfields|msql_numrows|msql_pconnect|msql_query|msql_regcase|msql_result|msql_select_db|msql_tablename|' +\n        'mssql_bind|mssql_close|mssql_connect|mssql_data_seek|mssql_execute|mssql_fetch_array|mssql_fetch_assoc|mssql_fetch_batch|' +\n        'mssql_fetch_field|mssql_fetch_object|mssql_fetch_row|mssql_field_length|mssql_field_name|mssql_field_seek|mssql_field_type|' +\n        'mssql_free_result|mssql_free_statement|mssql_get_last_message|mssql_guid_string|mssql_init|mssql_min_error_severity|' +\n        'mssql_min_message_severity|mssql_next_result|mssql_num_fields|mssql_num_rows|mssql_pconnect|mssql_query|mssql_result|mssql_rows_affected|' +\n        'mssql_select_db|mt_getrandmax|mt_rand|mt_srand|multipleiterator|mysql_affected_rows|mysql_client_encoding|mysql_close|mysql_connect|' +\n        'mysql_create_db|mysql_data_seek|mysql_db_name|mysql_db_query|mysql_drop_db|mysql_errno|mysql_error|mysql_escape_string|mysql_fetch_array|' +\n        'mysql_fetch_assoc|mysql_fetch_field|mysql_fetch_lengths|mysql_fetch_object|mysql_fetch_row|mysql_field_flags|mysql_field_len|' +\n        'mysql_field_name|mysql_field_seek|mysql_field_table|mysql_field_type|mysql_free_result|mysql_get_client_info|mysql_get_host_info|' +\n        'mysql_get_proto_info|mysql_get_server_info|mysql_info|mysql_insert_id|mysql_list_dbs|mysql_list_fields|mysql_list_processes|' +\n        'mysql_list_tables|mysql_num_fields|mysql_num_rows|mysql_pconnect|mysql_ping|mysql_query|mysql_real_escape_string|mysql_result|' +\n        'mysql_select_db|mysql_set_charset|mysql_stat|mysql_tablename|mysql_thread_id|mysql_unbuffered_query|mysqli|mysqli_bind_param|' +\n        'mysqli_bind_result|mysqli_client_encoding|mysqli_connect|mysqli_disable_reads_from_master|mysqli_disable_rpl_parse|mysqli_driver|' +\n        'mysqli_enable_reads_from_master|mysqli_enable_rpl_parse|mysqli_escape_string|mysqli_execute|mysqli_fetch|mysqli_get_metadata|' +\n        'mysqli_master_query|mysqli_param_count|mysqli_report|mysqli_result|mysqli_rpl_parse_enabled|mysqli_rpl_probe|mysqli_rpl_query_type|' +\n        'mysqli_send_long_data|mysqli_send_query|mysqli_set_opt|mysqli_slave_query|mysqli_stmt|mysqli_warning|mysqlnd_ms_get_stats|' +\n        'mysqlnd_ms_query_is_select|mysqlnd_ms_set_user_pick_server|mysqlnd_qc_change_handler|mysqlnd_qc_clear_cache|mysqlnd_qc_get_cache_info|' +\n        'mysqlnd_qc_get_core_stats|mysqlnd_qc_get_handler|mysqlnd_qc_get_query_trace_log|mysqlnd_qc_set_user_handlers|natcasesort|natsort|' +\n        'ncurses_addch|ncurses_addchnstr|ncurses_addchstr|ncurses_addnstr|ncurses_addstr|ncurses_assume_default_colors|ncurses_attroff|' +\n        'ncurses_attron|ncurses_attrset|ncurses_baudrate|ncurses_beep|ncurses_bkgd|ncurses_bkgdset|ncurses_border|ncurses_bottom_panel|' +\n        'ncurses_can_change_color|ncurses_cbreak|ncurses_clear|ncurses_clrtobot|ncurses_clrtoeol|ncurses_color_content|ncurses_color_set|' +\n        'ncurses_curs_set|ncurses_def_prog_mode|ncurses_def_shell_mode|ncurses_define_key|ncurses_del_panel|ncurses_delay_output|ncurses_delch|' +\n        'ncurses_deleteln|ncurses_delwin|ncurses_doupdate|ncurses_echo|ncurses_echochar|ncurses_end|ncurses_erase|ncurses_erasechar|ncurses_filter|' +\n        'ncurses_flash|ncurses_flushinp|ncurses_getch|ncurses_getmaxyx|ncurses_getmouse|ncurses_getyx|ncurses_halfdelay|ncurses_has_colors|' +\n        'ncurses_has_ic|ncurses_has_il|ncurses_has_key|ncurses_hide_panel|ncurses_hline|ncurses_inch|ncurses_init|ncurses_init_color|' +\n        'ncurses_init_pair|ncurses_insch|ncurses_insdelln|ncurses_insertln|ncurses_insstr|ncurses_instr|ncurses_isendwin|ncurses_keyok|' +\n        'ncurses_keypad|ncurses_killchar|ncurses_longname|ncurses_meta|ncurses_mouse_trafo|ncurses_mouseinterval|ncurses_mousemask|ncurses_move|' +\n        'ncurses_move_panel|ncurses_mvaddch|ncurses_mvaddchnstr|ncurses_mvaddchstr|ncurses_mvaddnstr|ncurses_mvaddstr|ncurses_mvcur|' +\n        'ncurses_mvdelch|ncurses_mvgetch|ncurses_mvhline|ncurses_mvinch|ncurses_mvvline|ncurses_mvwaddstr|ncurses_napms|ncurses_new_panel|' +\n        'ncurses_newpad|ncurses_newwin|ncurses_nl|ncurses_nocbreak|ncurses_noecho|ncurses_nonl|ncurses_noqiflush|ncurses_noraw|' +\n        'ncurses_pair_content|ncurses_panel_above|ncurses_panel_below|ncurses_panel_window|ncurses_pnoutrefresh|ncurses_prefresh|ncurses_putp|' +\n        'ncurses_qiflush|ncurses_raw|ncurses_refresh|ncurses_replace_panel|ncurses_reset_prog_mode|ncurses_reset_shell_mode|ncurses_resetty|' +\n        'ncurses_savetty|ncurses_scr_dump|ncurses_scr_init|ncurses_scr_restore|ncurses_scr_set|ncurses_scrl|ncurses_show_panel|ncurses_slk_attr|' +\n        'ncurses_slk_attroff|ncurses_slk_attron|ncurses_slk_attrset|ncurses_slk_clear|ncurses_slk_color|ncurses_slk_init|ncurses_slk_noutrefresh|' +\n        'ncurses_slk_refresh|ncurses_slk_restore|ncurses_slk_set|ncurses_slk_touch|ncurses_standend|ncurses_standout|ncurses_start_color|' +\n        'ncurses_termattrs|ncurses_termname|ncurses_timeout|ncurses_top_panel|ncurses_typeahead|ncurses_ungetch|ncurses_ungetmouse|' +\n        'ncurses_update_panels|ncurses_use_default_colors|ncurses_use_env|ncurses_use_extended_names|ncurses_vidattr|ncurses_vline|ncurses_waddch|' +\n        'ncurses_waddstr|ncurses_wattroff|ncurses_wattron|ncurses_wattrset|ncurses_wborder|ncurses_wclear|ncurses_wcolor_set|ncurses_werase|' +\n        'ncurses_wgetch|ncurses_whline|ncurses_wmouse_trafo|ncurses_wmove|ncurses_wnoutrefresh|ncurses_wrefresh|ncurses_wstandend|' +\n        'ncurses_wstandout|ncurses_wvline|newinstance|newinstanceargs|newt_bell|newt_button|newt_button_bar|newt_centered_window|newt_checkbox|' +\n        'newt_checkbox_get_value|newt_checkbox_set_flags|newt_checkbox_set_value|newt_checkbox_tree|newt_checkbox_tree_add_item|' +\n        'newt_checkbox_tree_find_item|newt_checkbox_tree_get_current|newt_checkbox_tree_get_entry_value|newt_checkbox_tree_get_multi_selection|' +\n        'newt_checkbox_tree_get_selection|newt_checkbox_tree_multi|newt_checkbox_tree_set_current|newt_checkbox_tree_set_entry|' +\n        'newt_checkbox_tree_set_entry_value|newt_checkbox_tree_set_width|newt_clear_key_buffer|newt_cls|newt_compact_button|' +\n        'newt_component_add_callback|newt_component_takes_focus|newt_create_grid|newt_cursor_off|newt_cursor_on|newt_delay|newt_draw_form|' +\n        'newt_draw_root_text|newt_entry|newt_entry_get_value|newt_entry_set|newt_entry_set_filter|newt_entry_set_flags|newt_finished|newt_form|' +\n        'newt_form_add_component|newt_form_add_components|newt_form_add_hot_key|newt_form_destroy|newt_form_get_current|newt_form_run|' +\n        'newt_form_set_background|newt_form_set_height|newt_form_set_size|newt_form_set_timer|newt_form_set_width|newt_form_watch_fd|' +\n        'newt_get_screen_size|newt_grid_add_components_to_form|newt_grid_basic_window|newt_grid_free|newt_grid_get_size|newt_grid_h_close_stacked|' +\n        'newt_grid_h_stacked|newt_grid_place|newt_grid_set_field|newt_grid_simple_window|newt_grid_v_close_stacked|newt_grid_v_stacked|' +\n        'newt_grid_wrapped_window|newt_grid_wrapped_window_at|newt_init|newt_label|newt_label_set_text|newt_listbox|newt_listbox_append_entry|' +\n        'newt_listbox_clear|newt_listbox_clear_selection|newt_listbox_delete_entry|newt_listbox_get_current|newt_listbox_get_selection|' +\n        'newt_listbox_insert_entry|newt_listbox_item_count|newt_listbox_select_item|newt_listbox_set_current|newt_listbox_set_current_by_key|' +\n        'newt_listbox_set_data|newt_listbox_set_entry|newt_listbox_set_width|newt_listitem|newt_listitem_get_data|newt_listitem_set|' +\n        'newt_open_window|newt_pop_help_line|newt_pop_window|newt_push_help_line|newt_radio_get_current|newt_radiobutton|newt_redraw_help_line|' +\n        'newt_reflow_text|newt_refresh|newt_resize_screen|newt_resume|newt_run_form|newt_scale|newt_scale_set|newt_scrollbar_set|' +\n        'newt_set_help_callback|newt_set_suspend_callback|newt_suspend|newt_textbox|newt_textbox_get_num_lines|newt_textbox_reflowed|' +\n        'newt_textbox_set_height|newt_textbox_set_text|newt_vertical_scrollbar|newt_wait_for_key|newt_win_choice|newt_win_entries|newt_win_menu|' +\n        'newt_win_message|newt_win_messagev|newt_win_ternary|next|ngettext|nl2br|nl_langinfo|norewinditerator|normalizer|notes_body|notes_copy_db|' +\n        'notes_create_db|notes_create_note|notes_drop_db|notes_find_note|notes_header_info|notes_list_msgs|notes_mark_read|notes_mark_unread|' +\n        'notes_nav_create|notes_search|notes_unread|notes_version|nsapi_request_headers|nsapi_response_headers|nsapi_virtual|nthmac|number_format|' +\n        'numberformatter|oauth|oauth_get_sbs|oauth_urlencode|oauthexception|oauthprovider|ob_clean|ob_deflatehandler|ob_end_clean|ob_end_flush|' +\n        'ob_etaghandler|ob_flush|ob_get_clean|ob_get_contents|ob_get_flush|ob_get_length|ob_get_level|ob_get_status|ob_gzhandler|ob_iconv_handler|' +\n        'ob_implicit_flush|ob_inflatehandler|ob_list_handlers|ob_start|ob_tidyhandler|oci_bind_array_by_name|oci_bind_by_name|oci_cancel|' +\n        'oci_client_version|oci_close|oci_collection_append|oci_collection_assign|oci_collection_element_assign|oci_collection_element_get|' +\n        'oci_collection_free|oci_collection_max|oci_collection_size|oci_collection_trim|oci_commit|oci_connect|oci_define_by_name|oci_error|' +\n        'oci_execute|oci_fetch|oci_fetch_all|oci_fetch_array|oci_fetch_assoc|oci_fetch_object|oci_fetch_row|oci_field_is_null|oci_field_name|' +\n        'oci_field_precision|oci_field_scale|oci_field_size|oci_field_type|oci_field_type_raw|oci_free_statement|oci_internal_debug|oci_lob_append|' +\n        'oci_lob_close|oci_lob_copy|oci_lob_eof|oci_lob_erase|oci_lob_export|oci_lob_flush|oci_lob_free|oci_lob_getbuffering|oci_lob_import|' +\n        'oci_lob_is_equal|oci_lob_load|oci_lob_read|oci_lob_rewind|oci_lob_save|oci_lob_savefile|oci_lob_seek|oci_lob_setbuffering|oci_lob_size|' +\n        'oci_lob_tell|oci_lob_truncate|oci_lob_write|oci_lob_writetemporary|oci_lob_writetofile|oci_new_collection|oci_new_connect|oci_new_cursor|' +\n        'oci_new_descriptor|oci_num_fields|oci_num_rows|oci_parse|oci_password_change|oci_pconnect|oci_result|oci_rollback|oci_server_version|' +\n        'oci_set_action|oci_set_client_identifier|oci_set_client_info|oci_set_edition|oci_set_module_name|oci_set_prefetch|oci_statement_type|' +\n        'ocibindbyname|ocicancel|ocicloselob|ocicollappend|ocicollassign|ocicollassignelem|ocicollgetelem|ocicollmax|ocicollsize|ocicolltrim|' +\n        'ocicolumnisnull|ocicolumnname|ocicolumnprecision|ocicolumnscale|ocicolumnsize|ocicolumntype|ocicolumntyperaw|ocicommit|ocidefinebyname|' +\n        'ocierror|ociexecute|ocifetch|ocifetchinto|ocifetchstatement|ocifreecollection|ocifreecursor|ocifreedesc|ocifreestatement|ociinternaldebug|' +\n        'ociloadlob|ocilogoff|ocilogon|ocinewcollection|ocinewcursor|ocinewdescriptor|ocinlogon|ocinumcols|ociparse|ociplogon|ociresult|' +\n        'ocirollback|ocirowcount|ocisavelob|ocisavelobfile|ociserverversion|ocisetprefetch|ocistatementtype|ociwritelobtofile|ociwritetemporarylob|' +\n        'octdec|odbc_autocommit|odbc_binmode|odbc_close|odbc_close_all|odbc_columnprivileges|odbc_columns|odbc_commit|odbc_connect|odbc_cursor|' +\n        'odbc_data_source|odbc_do|odbc_error|odbc_errormsg|odbc_exec|odbc_execute|odbc_fetch_array|odbc_fetch_into|odbc_fetch_object|' +\n        'odbc_fetch_row|odbc_field_len|odbc_field_name|odbc_field_num|odbc_field_precision|odbc_field_scale|odbc_field_type|odbc_foreignkeys|' +\n        'odbc_free_result|odbc_gettypeinfo|odbc_longreadlen|odbc_next_result|odbc_num_fields|odbc_num_rows|odbc_pconnect|odbc_prepare|' +\n        'odbc_primarykeys|odbc_procedurecolumns|odbc_procedures|odbc_result|odbc_result_all|odbc_rollback|odbc_setoption|odbc_specialcolumns|' +\n        'odbc_statistics|odbc_tableprivileges|odbc_tables|openal_buffer_create|openal_buffer_data|openal_buffer_destroy|openal_buffer_get|' +\n        'openal_buffer_loadwav|openal_context_create|openal_context_current|openal_context_destroy|openal_context_process|openal_context_suspend|' +\n        'openal_device_close|openal_device_open|openal_listener_get|openal_listener_set|openal_source_create|openal_source_destroy|' +\n        'openal_source_get|openal_source_pause|openal_source_play|openal_source_rewind|openal_source_set|openal_source_stop|openal_stream|opendir|' +\n        'openlog|openssl_cipher_iv_length|openssl_csr_export|openssl_csr_export_to_file|openssl_csr_get_public_key|openssl_csr_get_subject|' +\n        'openssl_csr_new|openssl_csr_sign|openssl_decrypt|openssl_dh_compute_key|openssl_digest|openssl_encrypt|openssl_error_string|' +\n        'openssl_free_key|openssl_get_cipher_methods|openssl_get_md_methods|openssl_get_privatekey|openssl_get_publickey|openssl_open|' +\n        'openssl_pkcs12_export|openssl_pkcs12_export_to_file|openssl_pkcs12_read|openssl_pkcs7_decrypt|openssl_pkcs7_encrypt|openssl_pkcs7_sign|' +\n        'openssl_pkcs7_verify|openssl_pkey_export|openssl_pkey_export_to_file|openssl_pkey_free|openssl_pkey_get_details|openssl_pkey_get_private|' +\n        'openssl_pkey_get_public|openssl_pkey_new|openssl_private_decrypt|openssl_private_encrypt|openssl_public_decrypt|openssl_public_encrypt|' +\n        'openssl_random_pseudo_bytes|openssl_seal|openssl_sign|openssl_verify|openssl_x509_check_private_key|openssl_x509_checkpurpose|' +\n        'openssl_x509_export|openssl_x509_export_to_file|openssl_x509_free|openssl_x509_parse|openssl_x509_read|ord|outeriterator|' +\n        'outofboundsexception|outofrangeexception|output_add_rewrite_var|output_reset_rewrite_vars|overflowexception|overload|override_function|' +\n        'ovrimos_close|ovrimos_commit|ovrimos_connect|ovrimos_cursor|ovrimos_exec|ovrimos_execute|ovrimos_fetch_into|ovrimos_fetch_row|' +\n        'ovrimos_field_len|ovrimos_field_name|ovrimos_field_num|ovrimos_field_type|ovrimos_free_result|ovrimos_longreadlen|ovrimos_num_fields|' +\n        'ovrimos_num_rows|ovrimos_prepare|ovrimos_result|ovrimos_result_all|ovrimos_rollback|pack|parentiterator|parse_ini_file|parse_ini_string|' +\n        'parse_str|parse_url|parsekit_compile_file|parsekit_compile_string|parsekit_func_arginfo|passthru|pathinfo|pclose|pcntl_alarm|pcntl_exec|' +\n        'pcntl_fork|pcntl_getpriority|pcntl_setpriority|pcntl_signal|pcntl_signal_dispatch|pcntl_sigprocmask|pcntl_sigtimedwait|pcntl_sigwaitinfo|' +\n        'pcntl_wait|pcntl_waitpid|pcntl_wexitstatus|pcntl_wifexited|pcntl_wifsignaled|pcntl_wifstopped|pcntl_wstopsig|pcntl_wtermsig|' +\n        'pdf_activate_item|pdf_add_annotation|pdf_add_bookmark|pdf_add_launchlink|pdf_add_locallink|pdf_add_nameddest|pdf_add_note|pdf_add_outline|' +\n        'pdf_add_pdflink|pdf_add_table_cell|pdf_add_textflow|pdf_add_thumbnail|pdf_add_weblink|pdf_arc|pdf_arcn|pdf_attach_file|pdf_begin_document|' +\n        'pdf_begin_font|pdf_begin_glyph|pdf_begin_item|pdf_begin_layer|pdf_begin_page|pdf_begin_page_ext|pdf_begin_pattern|pdf_begin_template|' +\n        'pdf_begin_template_ext|pdf_circle|pdf_clip|pdf_close|pdf_close_image|pdf_close_pdi|pdf_close_pdi_page|pdf_closepath|' +\n        'pdf_closepath_fill_stroke|pdf_closepath_stroke|pdf_concat|pdf_continue_text|pdf_create_3dview|pdf_create_action|pdf_create_annotation|' +\n        'pdf_create_bookmark|pdf_create_field|pdf_create_fieldgroup|pdf_create_gstate|pdf_create_pvf|pdf_create_textflow|pdf_curveto|' +\n        'pdf_define_layer|pdf_delete|pdf_delete_pvf|pdf_delete_table|pdf_delete_textflow|pdf_encoding_set_char|pdf_end_document|pdf_end_font|' +\n        'pdf_end_glyph|pdf_end_item|pdf_end_layer|pdf_end_page|pdf_end_page_ext|pdf_end_pattern|pdf_end_template|pdf_endpath|pdf_fill|' +\n        'pdf_fill_imageblock|pdf_fill_pdfblock|pdf_fill_stroke|pdf_fill_textblock|pdf_findfont|pdf_fit_image|pdf_fit_pdi_page|pdf_fit_table|' +\n        'pdf_fit_textflow|pdf_fit_textline|pdf_get_apiname|pdf_get_buffer|pdf_get_errmsg|pdf_get_errnum|pdf_get_font|pdf_get_fontname|' +\n        'pdf_get_fontsize|pdf_get_image_height|pdf_get_image_width|pdf_get_majorversion|pdf_get_minorversion|pdf_get_parameter|' +\n        'pdf_get_pdi_parameter|pdf_get_pdi_value|pdf_get_value|pdf_info_font|pdf_info_matchbox|pdf_info_table|pdf_info_textflow|pdf_info_textline|' +\n        'pdf_initgraphics|pdf_lineto|pdf_load_3ddata|pdf_load_font|pdf_load_iccprofile|pdf_load_image|pdf_makespotcolor|pdf_moveto|pdf_new|' +\n        'pdf_open_ccitt|pdf_open_file|pdf_open_gif|pdf_open_image|pdf_open_image_file|pdf_open_jpeg|pdf_open_memory_image|pdf_open_pdi|' +\n        'pdf_open_pdi_document|pdf_open_pdi_page|pdf_open_tiff|pdf_pcos_get_number|pdf_pcos_get_stream|pdf_pcos_get_string|pdf_place_image|' +\n        'pdf_place_pdi_page|pdf_process_pdi|pdf_rect|pdf_restore|pdf_resume_page|pdf_rotate|pdf_save|pdf_scale|pdf_set_border_color|' +\n        'pdf_set_border_dash|pdf_set_border_style|pdf_set_char_spacing|pdf_set_duration|pdf_set_gstate|pdf_set_horiz_scaling|pdf_set_info|' +\n        'pdf_set_info_author|pdf_set_info_creator|pdf_set_info_keywords|pdf_set_info_subject|pdf_set_info_title|pdf_set_layer_dependency|' +\n        'pdf_set_leading|pdf_set_parameter|pdf_set_text_matrix|pdf_set_text_pos|pdf_set_text_rendering|pdf_set_text_rise|pdf_set_value|' +\n        'pdf_set_word_spacing|pdf_setcolor|pdf_setdash|pdf_setdashpattern|pdf_setflat|pdf_setfont|pdf_setgray|pdf_setgray_fill|pdf_setgray_stroke|' +\n        'pdf_setlinecap|pdf_setlinejoin|pdf_setlinewidth|pdf_setmatrix|pdf_setmiterlimit|pdf_setpolydash|pdf_setrgbcolor|pdf_setrgbcolor_fill|' +\n        'pdf_setrgbcolor_stroke|pdf_shading|pdf_shading_pattern|pdf_shfill|pdf_show|pdf_show_boxed|pdf_show_xy|pdf_skew|pdf_stringwidth|pdf_stroke|' +\n        'pdf_suspend_page|pdf_translate|pdf_utf16_to_utf8|pdf_utf32_to_utf16|pdf_utf8_to_utf16|pdo|pdo_cubrid_schema|pdo_pgsqllobcreate|' +\n        'pdo_pgsqllobopen|pdo_pgsqllobunlink|pdo_sqlitecreateaggregate|pdo_sqlitecreatefunction|pdoexception|pdostatement|pfsockopen|' +\n        'pg_affected_rows|pg_cancel_query|pg_client_encoding|pg_close|pg_connect|pg_connection_busy|pg_connection_reset|pg_connection_status|' +\n        'pg_convert|pg_copy_from|pg_copy_to|pg_dbname|pg_delete|pg_end_copy|pg_escape_bytea|pg_escape_string|pg_execute|pg_fetch_all|' +\n        'pg_fetch_all_columns|pg_fetch_array|pg_fetch_assoc|pg_fetch_object|pg_fetch_result|pg_fetch_row|pg_field_is_null|pg_field_name|' +\n        'pg_field_num|pg_field_prtlen|pg_field_size|pg_field_table|pg_field_type|pg_field_type_oid|pg_free_result|pg_get_notify|pg_get_pid|' +\n        'pg_get_result|pg_host|pg_insert|pg_last_error|pg_last_notice|pg_last_oid|pg_lo_close|pg_lo_create|pg_lo_export|pg_lo_import|pg_lo_open|' +\n        'pg_lo_read|pg_lo_read_all|pg_lo_seek|pg_lo_tell|pg_lo_unlink|pg_lo_write|pg_meta_data|pg_num_fields|pg_num_rows|pg_options|' +\n        'pg_parameter_status|pg_pconnect|pg_ping|pg_port|pg_prepare|pg_put_line|pg_query|pg_query_params|pg_result_error|pg_result_error_field|' +\n        'pg_result_seek|pg_result_status|pg_select|pg_send_execute|pg_send_prepare|pg_send_query|pg_send_query_params|pg_set_client_encoding|' +\n        'pg_set_error_verbosity|pg_trace|pg_transaction_status|pg_tty|pg_unescape_bytea|pg_untrace|pg_update|pg_version|php_check_syntax|' +\n        'php_ini_loaded_file|php_ini_scanned_files|php_logo_guid|php_sapi_name|php_strip_whitespace|php_uname|phpcredits|phpinfo|phpversion|pi|' +\n        'png2wbmp|popen|pos|posix_access|posix_ctermid|posix_errno|posix_get_last_error|posix_getcwd|posix_getegid|posix_geteuid|posix_getgid|' +\n        'posix_getgrgid|posix_getgrnam|posix_getgroups|posix_getlogin|posix_getpgid|posix_getpgrp|posix_getpid|posix_getppid|posix_getpwnam|' +\n        'posix_getpwuid|posix_getrlimit|posix_getsid|posix_getuid|posix_initgroups|posix_isatty|posix_kill|posix_mkfifo|posix_mknod|posix_setegid|' +\n        'posix_seteuid|posix_setgid|posix_setpgid|posix_setsid|posix_setuid|posix_strerror|posix_times|posix_ttyname|posix_uname|pow|preg_filter|' +\n        'preg_grep|preg_last_error|preg_match|preg_match_all|preg_quote|preg_replace|preg_replace_callback|preg_split|prev|print|print_r|' +\n        'printer_abort|printer_close|printer_create_brush|printer_create_dc|printer_create_font|printer_create_pen|printer_delete_brush|' +\n        'printer_delete_dc|printer_delete_font|printer_delete_pen|printer_draw_bmp|printer_draw_chord|printer_draw_elipse|printer_draw_line|' +\n        'printer_draw_pie|printer_draw_rectangle|printer_draw_roundrect|printer_draw_text|printer_end_doc|printer_end_page|printer_get_option|' +\n        'printer_list|printer_logical_fontheight|printer_open|printer_select_brush|printer_select_font|printer_select_pen|printer_set_option|' +\n        'printer_start_doc|printer_start_page|printer_write|printf|proc_close|proc_get_status|proc_nice|proc_open|proc_terminate|property_exists|' +\n        'ps_add_bookmark|ps_add_launchlink|ps_add_locallink|ps_add_note|ps_add_pdflink|ps_add_weblink|ps_arc|ps_arcn|ps_begin_page|' +\n        'ps_begin_pattern|ps_begin_template|ps_circle|ps_clip|ps_close|ps_close_image|ps_closepath|ps_closepath_stroke|ps_continue_text|ps_curveto|' +\n        'ps_delete|ps_end_page|ps_end_pattern|ps_end_template|ps_fill|ps_fill_stroke|ps_findfont|ps_get_buffer|ps_get_parameter|ps_get_value|' +\n        'ps_hyphenate|ps_include_file|ps_lineto|ps_makespotcolor|ps_moveto|ps_new|ps_open_file|ps_open_image|ps_open_image_file|' +\n        'ps_open_memory_image|ps_place_image|ps_rect|ps_restore|ps_rotate|ps_save|ps_scale|ps_set_border_color|ps_set_border_dash|' +\n        'ps_set_border_style|ps_set_info|ps_set_parameter|ps_set_text_pos|ps_set_value|ps_setcolor|ps_setdash|ps_setflat|ps_setfont|ps_setgray|' +\n        'ps_setlinecap|ps_setlinejoin|ps_setlinewidth|ps_setmiterlimit|ps_setoverprintmode|ps_setpolydash|ps_shading|ps_shading_pattern|ps_shfill|' +\n        'ps_show|ps_show2|ps_show_boxed|ps_show_xy|ps_show_xy2|ps_string_geometry|ps_stringwidth|ps_stroke|ps_symbol|ps_symbol_name|' +\n        'ps_symbol_width|ps_translate|pspell_add_to_personal|pspell_add_to_session|pspell_check|pspell_clear_session|pspell_config_create|' +\n        'pspell_config_data_dir|pspell_config_dict_dir|pspell_config_ignore|pspell_config_mode|pspell_config_personal|pspell_config_repl|' +\n        'pspell_config_runtogether|pspell_config_save_repl|pspell_new|pspell_new_config|pspell_new_personal|pspell_save_wordlist|' +\n        'pspell_store_replacement|pspell_suggest|putenv|px_close|px_create_fp|px_date2string|px_delete|px_delete_record|px_get_field|px_get_info|' +\n        'px_get_parameter|px_get_record|px_get_schema|px_get_value|px_insert_record|px_new|px_numfields|px_numrecords|px_open_fp|px_put_record|' +\n        'px_retrieve_record|px_set_blob_file|px_set_parameter|px_set_tablename|px_set_targetencoding|px_set_value|px_timestamp2string|' +\n        'px_update_record|qdom_error|qdom_tree|quoted_printable_decode|quoted_printable_encode|quotemeta|rad2deg|radius_acct_open|' +\n        'radius_add_server|radius_auth_open|radius_close|radius_config|radius_create_request|radius_cvt_addr|radius_cvt_int|radius_cvt_string|' +\n        'radius_demangle|radius_demangle_mppe_key|radius_get_attr|radius_get_vendor_attr|radius_put_addr|radius_put_attr|radius_put_int|' +\n        'radius_put_string|radius_put_vendor_addr|radius_put_vendor_attr|radius_put_vendor_int|radius_put_vendor_string|' +\n        'radius_request_authenticator|radius_send_request|radius_server_secret|radius_strerror|rand|range|rangeexception|rar_wrapper_cache_stats|' +\n        'rararchive|rarentry|rarexception|rawurldecode|rawurlencode|read_exif_data|readdir|readfile|readgzfile|readline|readline_add_history|' +\n        'readline_callback_handler_install|readline_callback_handler_remove|readline_callback_read_char|readline_clear_history|' +\n        'readline_completion_function|readline_info|readline_list_history|readline_on_new_line|readline_read_history|readline_redisplay|' +\n        'readline_write_history|readlink|realpath|realpath_cache_get|realpath_cache_size|recode|recode_file|recode_string|recursivearrayiterator|' +\n        'recursivecachingiterator|recursivecallbackfilteriterator|recursivedirectoryiterator|recursivefilteriterator|recursiveiterator|' +\n        'recursiveiteratoriterator|recursiveregexiterator|recursivetreeiterator|reflection|reflectionclass|reflectionexception|reflectionextension|' +\n        'reflectionfunction|reflectionfunctionabstract|reflectionmethod|reflectionobject|reflectionparameter|reflectionproperty|reflector|' +\n        'regexiterator|register_shutdown_function|register_tick_function|rename|rename_function|require|require_once|reset|resetValue|' +\n        'resourcebundle|restore_error_handler|restore_exception_handler|restore_include_path|return|rewind|rewinddir|rmdir|round|rpm_close|' +\n        'rpm_get_tag|rpm_is_valid|rpm_open|rpm_version|rrd_create|rrd_error|rrd_fetch|rrd_first|rrd_graph|rrd_info|rrd_last|rrd_lastupdate|' +\n        'rrd_restore|rrd_tune|rrd_update|rrd_xport|rrdcreator|rrdgraph|rrdupdater|rsort|rtrim|runkit_class_adopt|runkit_class_emancipate|' +\n        'runkit_constant_add|runkit_constant_redefine|runkit_constant_remove|runkit_function_add|runkit_function_copy|runkit_function_redefine|' +\n        'runkit_function_remove|runkit_function_rename|runkit_import|runkit_lint|runkit_lint_file|runkit_method_add|runkit_method_copy|' +\n        'runkit_method_redefine|runkit_method_remove|runkit_method_rename|runkit_return_value_used|runkit_sandbox_output_handler|' +\n        'runkit_superglobals|runtimeexception|samconnection_commit|samconnection_connect|samconnection_constructor|samconnection_disconnect|' +\n        'samconnection_errno|samconnection_error|samconnection_isconnected|samconnection_peek|samconnection_peekall|samconnection_receive|' +\n        'samconnection_remove|samconnection_rollback|samconnection_send|samconnection_setDebug|samconnection_subscribe|samconnection_unsubscribe|' +\n        'sammessage_body|sammessage_constructor|sammessage_header|sca_createdataobject|sca_getservice|sca_localproxy_createdataobject|' +\n        'sca_soapproxy_createdataobject|scandir|sdo_das_changesummary_beginlogging|sdo_das_changesummary_endlogging|' +\n        'sdo_das_changesummary_getchangeddataobjects|sdo_das_changesummary_getchangetype|sdo_das_changesummary_getoldcontainer|' +\n        'sdo_das_changesummary_getoldvalues|sdo_das_changesummary_islogging|sdo_das_datafactory_addpropertytotype|sdo_das_datafactory_addtype|' +\n        'sdo_das_datafactory_getdatafactory|sdo_das_dataobject_getchangesummary|sdo_das_relational_applychanges|sdo_das_relational_construct|' +\n        'sdo_das_relational_createrootdataobject|sdo_das_relational_executepreparedquery|sdo_das_relational_executequery|' +\n        'sdo_das_setting_getlistindex|sdo_das_setting_getpropertyindex|sdo_das_setting_getpropertyname|sdo_das_setting_getvalue|' +\n        'sdo_das_setting_isset|sdo_das_xml_addtypes|sdo_das_xml_create|sdo_das_xml_createdataobject|sdo_das_xml_createdocument|' +\n        'sdo_das_xml_document_getrootdataobject|sdo_das_xml_document_getrootelementname|sdo_das_xml_document_getrootelementuri|' +\n        'sdo_das_xml_document_setencoding|sdo_das_xml_document_setxmldeclaration|sdo_das_xml_document_setxmlversion|sdo_das_xml_loadfile|' +\n        'sdo_das_xml_loadstring|sdo_das_xml_savefile|sdo_das_xml_savestring|sdo_datafactory_create|sdo_dataobject_clear|' +\n        'sdo_dataobject_createdataobject|sdo_dataobject_getcontainer|sdo_dataobject_getsequence|sdo_dataobject_gettypename|' +\n        'sdo_dataobject_gettypenamespaceuri|sdo_exception_getcause|sdo_list_insert|sdo_model_property_getcontainingtype|' +\n        'sdo_model_property_getdefault|sdo_model_property_getname|sdo_model_property_gettype|sdo_model_property_iscontainment|' +\n        'sdo_model_property_ismany|sdo_model_reflectiondataobject_construct|sdo_model_reflectiondataobject_export|' +\n        'sdo_model_reflectiondataobject_getcontainmentproperty|sdo_model_reflectiondataobject_getinstanceproperties|' +\n        'sdo_model_reflectiondataobject_gettype|sdo_model_type_getbasetype|sdo_model_type_getname|sdo_model_type_getnamespaceuri|' +\n        'sdo_model_type_getproperties|sdo_model_type_getproperty|sdo_model_type_isabstracttype|sdo_model_type_isdatatype|sdo_model_type_isinstance|' +\n        'sdo_model_type_isopentype|sdo_model_type_issequencedtype|sdo_sequence_getproperty|sdo_sequence_insert|sdo_sequence_move|seekableiterator|' +\n        'sem_acquire|sem_get|sem_release|sem_remove|serializable|serialize|session_cache_expire|session_cache_limiter|session_commit|' +\n        'session_decode|session_destroy|session_encode|session_get_cookie_params|session_id|session_is_registered|session_module_name|session_name|' +\n        'session_pgsql_add_error|session_pgsql_get_error|session_pgsql_get_field|session_pgsql_reset|session_pgsql_set_field|session_pgsql_status|' +\n        'session_regenerate_id|session_register|session_save_path|session_set_cookie_params|session_set_save_handler|session_start|' +\n        'session_unregister|session_unset|session_write_close|setCounterClass|set_error_handler|set_exception_handler|set_file_buffer|' +\n        'set_include_path|set_magic_quotes_runtime|set_socket_blocking|set_time_limit|setcookie|setlocale|setproctitle|setrawcookie|' +\n        'setstaticpropertyvalue|setthreadtitle|settype|sha1|sha1_file|shell_exec|shm_attach|shm_detach|shm_get_var|shm_has_var|shm_put_var|' +\n        'shm_remove|shm_remove_var|shmop_close|shmop_delete|shmop_open|shmop_read|shmop_size|shmop_write|show_source|shuffle|signeurlpaiement|' +\n        'similar_text|simplexml_import_dom|simplexml_load_file|simplexml_load_string|simplexmlelement|simplexmliterator|sin|sinh|sizeof|sleep|snmp|' +\n        'snmp2_get|snmp2_getnext|snmp2_real_walk|snmp2_set|snmp2_walk|snmp3_get|snmp3_getnext|snmp3_real_walk|snmp3_set|snmp3_walk|' +\n        'snmp_get_quick_print|snmp_get_valueretrieval|snmp_read_mib|snmp_set_enum_print|snmp_set_oid_numeric_print|snmp_set_oid_output_format|' +\n        'snmp_set_quick_print|snmp_set_valueretrieval|snmpget|snmpgetnext|snmprealwalk|snmpset|snmpwalk|snmpwalkoid|soapclient|soapfault|' +\n        'soapheader|soapparam|soapserver|soapvar|socket_accept|socket_bind|socket_clear_error|socket_close|socket_connect|socket_create|' +\n        'socket_create_listen|socket_create_pair|socket_get_option|socket_get_status|socket_getpeername|socket_getsockname|socket_last_error|' +\n        'socket_listen|socket_read|socket_recv|socket_recvfrom|socket_select|socket_send|socket_sendto|socket_set_block|socket_set_blocking|' +\n        'socket_set_nonblock|socket_set_option|socket_set_timeout|socket_shutdown|socket_strerror|socket_write|solr_get_version|solrclient|' +\n        'solrclientexception|solrdocument|solrdocumentfield|solrexception|solrgenericresponse|solrillegalargumentexception|' +\n        'solrillegaloperationexception|solrinputdocument|solrmodifiableparams|solrobject|solrparams|solrpingresponse|solrquery|solrqueryresponse|' +\n        'solrresponse|solrupdateresponse|solrutils|sort|soundex|sphinxclient|spl_autoload|spl_autoload_call|spl_autoload_extensions|' +\n        'spl_autoload_functions|spl_autoload_register|spl_autoload_unregister|spl_classes|spl_object_hash|splbool|spldoublylinkedlist|splenum|' +\n        'splfileinfo|splfileobject|splfixedarray|splfloat|splheap|splint|split|spliti|splmaxheap|splminheap|splobjectstorage|splobserver|' +\n        'splpriorityqueue|splqueue|splstack|splstring|splsubject|spltempfileobject|spoofchecker|sprintf|sql_regcase|sqlite3|sqlite3result|' +\n        'sqlite3stmt|sqlite_array_query|sqlite_busy_timeout|sqlite_changes|sqlite_close|sqlite_column|sqlite_create_aggregate|' +\n        'sqlite_create_function|sqlite_current|sqlite_error_string|sqlite_escape_string|sqlite_exec|sqlite_factory|sqlite_fetch_all|' +\n        'sqlite_fetch_array|sqlite_fetch_column_types|sqlite_fetch_object|sqlite_fetch_single|sqlite_fetch_string|sqlite_field_name|' +\n        'sqlite_has_more|sqlite_has_prev|sqlite_key|sqlite_last_error|sqlite_last_insert_rowid|sqlite_libencoding|sqlite_libversion|sqlite_next|' +\n        'sqlite_num_fields|sqlite_num_rows|sqlite_open|sqlite_popen|sqlite_prev|sqlite_query|sqlite_rewind|sqlite_seek|sqlite_single_query|' +\n        'sqlite_udf_decode_binary|sqlite_udf_encode_binary|sqlite_unbuffered_query|sqlite_valid|sqrt|srand|sscanf|ssdeep_fuzzy_compare|' +\n        'ssdeep_fuzzy_hash|ssdeep_fuzzy_hash_filename|ssh2_auth_hostbased_file|ssh2_auth_none|ssh2_auth_password|ssh2_auth_pubkey_file|' +\n        'ssh2_connect|ssh2_exec|ssh2_fetch_stream|ssh2_fingerprint|ssh2_methods_negotiated|ssh2_publickey_add|ssh2_publickey_init|' +\n        'ssh2_publickey_list|ssh2_publickey_remove|ssh2_scp_recv|ssh2_scp_send|ssh2_sftp|ssh2_sftp_lstat|ssh2_sftp_mkdir|ssh2_sftp_readlink|' +\n        'ssh2_sftp_realpath|ssh2_sftp_rename|ssh2_sftp_rmdir|ssh2_sftp_stat|ssh2_sftp_symlink|ssh2_sftp_unlink|ssh2_shell|ssh2_tunnel|stat|' +\n        'stats_absolute_deviation|stats_cdf_beta|stats_cdf_binomial|stats_cdf_cauchy|stats_cdf_chisquare|stats_cdf_exponential|stats_cdf_f|' +\n        'stats_cdf_gamma|stats_cdf_laplace|stats_cdf_logistic|stats_cdf_negative_binomial|stats_cdf_noncentral_chisquare|stats_cdf_noncentral_f|' +\n        'stats_cdf_poisson|stats_cdf_t|stats_cdf_uniform|stats_cdf_weibull|stats_covariance|stats_den_uniform|stats_dens_beta|stats_dens_cauchy|' +\n        'stats_dens_chisquare|stats_dens_exponential|stats_dens_f|stats_dens_gamma|stats_dens_laplace|stats_dens_logistic|' +\n        'stats_dens_negative_binomial|stats_dens_normal|stats_dens_pmf_binomial|stats_dens_pmf_hypergeometric|stats_dens_pmf_poisson|stats_dens_t|' +\n        'stats_dens_weibull|stats_harmonic_mean|stats_kurtosis|stats_rand_gen_beta|stats_rand_gen_chisquare|stats_rand_gen_exponential|' +\n        'stats_rand_gen_f|stats_rand_gen_funiform|stats_rand_gen_gamma|stats_rand_gen_ibinomial|stats_rand_gen_ibinomial_negative|' +\n        'stats_rand_gen_int|stats_rand_gen_ipoisson|stats_rand_gen_iuniform|stats_rand_gen_noncenral_chisquare|stats_rand_gen_noncentral_f|' +\n        'stats_rand_gen_noncentral_t|stats_rand_gen_normal|stats_rand_gen_t|stats_rand_get_seeds|stats_rand_phrase_to_seeds|stats_rand_ranf|' +\n        'stats_rand_setall|stats_skew|stats_standard_deviation|stats_stat_binomial_coef|stats_stat_correlation|stats_stat_gennch|' +\n        'stats_stat_independent_t|stats_stat_innerproduct|stats_stat_noncentral_t|stats_stat_paired_t|stats_stat_percentile|stats_stat_powersum|' +\n        'stats_variance|stomp|stomp_connect_error|stomp_version|stompexception|stompframe|str_getcsv|str_ireplace|str_pad|str_repeat|str_replace|' +\n        'str_rot13|str_shuffle|str_split|str_word_count|strcasecmp|strchr|strcmp|strcoll|strcspn|stream_bucket_append|stream_bucket_make_writeable|' +\n        'stream_bucket_new|stream_bucket_prepend|stream_context_create|stream_context_get_default|stream_context_get_options|' +\n        'stream_context_get_params|stream_context_set_default|stream_context_set_option|stream_context_set_params|stream_copy_to_stream|' +\n        'stream_encoding|stream_filter_append|stream_filter_prepend|stream_filter_register|stream_filter_remove|stream_get_contents|' +\n        'stream_get_filters|stream_get_line|stream_get_meta_data|stream_get_transports|stream_get_wrappers|stream_is_local|' +\n        'stream_notification_callback|stream_register_wrapper|stream_resolve_include_path|stream_select|stream_set_blocking|stream_set_read_buffer|' +\n        'stream_set_timeout|stream_set_write_buffer|stream_socket_accept|stream_socket_client|stream_socket_enable_crypto|stream_socket_get_name|' +\n        'stream_socket_pair|stream_socket_recvfrom|stream_socket_sendto|stream_socket_server|stream_socket_shutdown|stream_supports_lock|' +\n        'stream_wrapper_register|stream_wrapper_restore|stream_wrapper_unregister|streamwrapper|strftime|strip_tags|stripcslashes|stripos|' +\n        'stripslashes|stristr|strlen|strnatcasecmp|strnatcmp|strncasecmp|strncmp|strpbrk|strpos|strptime|strrchr|strrev|strripos|strrpos|strspn|' +\n        'strstr|strtok|strtolower|strtotime|strtoupper|strtr|strval|substr|substr_compare|substr_count|substr_replace|svm|svmmodel|svn_add|' +\n        'svn_auth_get_parameter|svn_auth_set_parameter|svn_blame|svn_cat|svn_checkout|svn_cleanup|svn_client_version|svn_commit|svn_delete|' +\n        'svn_diff|svn_export|svn_fs_abort_txn|svn_fs_apply_text|svn_fs_begin_txn2|svn_fs_change_node_prop|svn_fs_check_path|' +\n        'svn_fs_contents_changed|svn_fs_copy|svn_fs_delete|svn_fs_dir_entries|svn_fs_file_contents|svn_fs_file_length|svn_fs_is_dir|svn_fs_is_file|' +\n        'svn_fs_make_dir|svn_fs_make_file|svn_fs_node_created_rev|svn_fs_node_prop|svn_fs_props_changed|svn_fs_revision_prop|svn_fs_revision_root|' +\n        'svn_fs_txn_root|svn_fs_youngest_rev|svn_import|svn_log|svn_ls|svn_mkdir|svn_repos_create|svn_repos_fs|svn_repos_fs_begin_txn_for_commit|' +\n        'svn_repos_fs_commit_txn|svn_repos_hotcopy|svn_repos_open|svn_repos_recover|svn_revert|svn_status|svn_update|swf_actiongeturl|' +\n        'swf_actiongotoframe|swf_actiongotolabel|swf_actionnextframe|swf_actionplay|swf_actionprevframe|swf_actionsettarget|swf_actionstop|' +\n        'swf_actiontogglequality|swf_actionwaitforframe|swf_addbuttonrecord|swf_addcolor|swf_closefile|swf_definebitmap|swf_definefont|' +\n        'swf_defineline|swf_definepoly|swf_definerect|swf_definetext|swf_endbutton|swf_enddoaction|swf_endshape|swf_endsymbol|swf_fontsize|' +\n        'swf_fontslant|swf_fonttracking|swf_getbitmapinfo|swf_getfontinfo|swf_getframe|swf_labelframe|swf_lookat|swf_modifyobject|swf_mulcolor|' +\n        'swf_nextid|swf_oncondition|swf_openfile|swf_ortho|swf_ortho2|swf_perspective|swf_placeobject|swf_polarview|swf_popmatrix|swf_posround|' +\n        'swf_pushmatrix|swf_removeobject|swf_rotate|swf_scale|swf_setfont|swf_setframe|swf_shapearc|swf_shapecurveto|swf_shapecurveto3|' +\n        'swf_shapefillbitmapclip|swf_shapefillbitmaptile|swf_shapefilloff|swf_shapefillsolid|swf_shapelinesolid|swf_shapelineto|swf_shapemoveto|' +\n        'swf_showframe|swf_startbutton|swf_startdoaction|swf_startshape|swf_startsymbol|swf_textwidth|swf_translate|swf_viewport|swfaction|' +\n        'swfbitmap|swfbutton|swfdisplayitem|swffill|swffont|swffontchar|swfgradient|swfmorph|swfmovie|swfprebuiltclip|swfshape|swfsound|' +\n        'swfsoundinstance|swfsprite|swftext|swftextfield|swfvideostream|swish_construct|swish_getmetalist|swish_getpropertylist|swish_prepare|' +\n        'swish_query|swishresult_getmetalist|swishresult_stem|swishresults_getparsedwords|swishresults_getremovedstopwords|swishresults_nextresult|' +\n        'swishresults_seekresult|swishsearch_execute|swishsearch_resetlimit|swishsearch_setlimit|swishsearch_setphrasedelimiter|' +\n        'swishsearch_setsort|swishsearch_setstructure|sybase_affected_rows|sybase_close|sybase_connect|sybase_data_seek|' +\n        'sybase_deadlock_retry_count|sybase_fetch_array|sybase_fetch_assoc|sybase_fetch_field|sybase_fetch_object|sybase_fetch_row|' +\n        'sybase_field_seek|sybase_free_result|sybase_get_last_message|sybase_min_client_severity|sybase_min_error_severity|' +\n        'sybase_min_message_severity|sybase_min_server_severity|sybase_num_fields|sybase_num_rows|sybase_pconnect|sybase_query|sybase_result|' +\n        'sybase_select_db|sybase_set_message_handler|sybase_unbuffered_query|symlink|sys_get_temp_dir|sys_getloadavg|syslog|system|tag|tan|tanh|' +\n        'tcpwrap_check|tempnam|textdomain|tidy|tidy_access_count|tidy_config_count|tidy_diagnose|tidy_error_count|tidy_get_error_buffer|' +\n        'tidy_get_output|tidy_load_config|tidy_reset_config|tidy_save_config|tidy_set_encoding|tidy_setopt|tidy_warning_count|tidynode|time|' +\n        'time_nanosleep|time_sleep_until|timezone_abbreviations_list|timezone_identifiers_list|timezone_location_get|timezone_name_from_abbr|' +\n        'timezone_name_get|timezone_offset_get|timezone_open|timezone_transitions_get|timezone_version_get|tmpfile|token_get_all|token_name|' +\n        'tokyotyrant|tokyotyrantquery|tokyotyranttable|tostring|tostring|touch|transliterator|traversable|trigger_error|trim|uasort|ucfirst|' +\n        'ucwords|udm_add_search_limit|udm_alloc_agent|udm_alloc_agent_array|udm_api_version|udm_cat_list|udm_cat_path|udm_check_charset|' +\n        'udm_check_stored|udm_clear_search_limits|udm_close_stored|udm_crc32|udm_errno|udm_error|udm_find|udm_free_agent|udm_free_ispell_data|' +\n        'udm_free_res|udm_get_doc_count|udm_get_res_field|udm_get_res_param|udm_hash32|udm_load_ispell_data|udm_open_stored|udm_set_agent_param|' +\n        'uksort|umask|underflowexception|unexpectedvalueexception|uniqid|unixtojd|unlink|unpack|unregister_tick_function|unserialize|unset|' +\n        'urldecode|urlencode|use_soap_error_handler|user_error|usleep|usort|utf8_decode|utf8_encode|v8js|v8jsexception|var_dump|var_export|variant|' +\n        'variant_abs|variant_add|variant_and|variant_cast|variant_cat|variant_cmp|variant_date_from_timestamp|variant_date_to_timestamp|' +\n        'variant_div|variant_eqv|variant_fix|variant_get_type|variant_idiv|variant_imp|variant_int|variant_mod|variant_mul|variant_neg|variant_not|' +\n        'variant_or|variant_pow|variant_round|variant_set|variant_set_type|variant_sub|variant_xor|version_compare|vfprintf|virtual|' +\n        'vpopmail_add_alias_domain|vpopmail_add_alias_domain_ex|vpopmail_add_domain|vpopmail_add_domain_ex|vpopmail_add_user|vpopmail_alias_add|' +\n        'vpopmail_alias_del|vpopmail_alias_del_domain|vpopmail_alias_get|vpopmail_alias_get_all|vpopmail_auth_user|vpopmail_del_domain|' +\n        'vpopmail_del_domain_ex|vpopmail_del_user|vpopmail_error|vpopmail_passwd|vpopmail_set_user_quota|vprintf|vsprintf|w32api_deftype|' +\n        'w32api_init_dtype|w32api_invoke_function|w32api_register_function|w32api_set_call_method|wddx_add_vars|wddx_deserialize|wddx_packet_end|' +\n        'wddx_packet_start|wddx_serialize_value|wddx_serialize_vars|win32_continue_service|win32_create_service|win32_delete_service|' +\n        'win32_get_last_control_message|win32_pause_service|win32_ps_list_procs|win32_ps_stat_mem|win32_ps_stat_proc|win32_query_service_status|' +\n        'win32_set_service_status|win32_start_service|win32_start_service_ctrl_dispatcher|win32_stop_service|wincache_fcache_fileinfo|' +\n        'wincache_fcache_meminfo|wincache_lock|wincache_ocache_fileinfo|wincache_ocache_meminfo|wincache_refresh_if_changed|' +\n        'wincache_rplist_fileinfo|wincache_rplist_meminfo|wincache_scache_info|wincache_scache_meminfo|wincache_ucache_add|wincache_ucache_cas|' +\n        'wincache_ucache_clear|wincache_ucache_dec|wincache_ucache_delete|wincache_ucache_exists|wincache_ucache_get|wincache_ucache_inc|' +\n        'wincache_ucache_info|wincache_ucache_meminfo|wincache_ucache_set|wincache_unlock|wordwrap|xattr_get|xattr_list|xattr_remove|xattr_set|' +\n        'xattr_supported|xdiff_file_bdiff|xdiff_file_bdiff_size|xdiff_file_bpatch|xdiff_file_diff|xdiff_file_diff_binary|xdiff_file_merge3|' +\n        'xdiff_file_patch|xdiff_file_patch_binary|xdiff_file_rabdiff|xdiff_string_bdiff|xdiff_string_bdiff_size|xdiff_string_bpatch|' +\n        'xdiff_string_diff|xdiff_string_diff_binary|xdiff_string_merge3|xdiff_string_patch|xdiff_string_patch_binary|xdiff_string_rabdiff|' +\n        'xhprof_disable|xhprof_enable|xhprof_sample_disable|xhprof_sample_enable|xml_error_string|xml_get_current_byte_index|' +\n        'xml_get_current_column_number|xml_get_current_line_number|xml_get_error_code|xml_parse|xml_parse_into_struct|xml_parser_create|' +\n        'xml_parser_create_ns|xml_parser_free|xml_parser_get_option|xml_parser_set_option|xml_set_character_data_handler|xml_set_default_handler|' +\n        'xml_set_element_handler|xml_set_end_namespace_decl_handler|xml_set_external_entity_ref_handler|xml_set_notation_decl_handler|' +\n        'xml_set_object|xml_set_processing_instruction_handler|xml_set_start_namespace_decl_handler|xml_set_unparsed_entity_decl_handler|xmlreader|' +\n        'xmlrpc_decode|xmlrpc_decode_request|xmlrpc_encode|xmlrpc_encode_request|xmlrpc_get_type|xmlrpc_is_fault|xmlrpc_parse_method_descriptions|' +\n        'xmlrpc_server_add_introspection_data|xmlrpc_server_call_method|xmlrpc_server_create|xmlrpc_server_destroy|' +\n        'xmlrpc_server_register_introspection_callback|xmlrpc_server_register_method|xmlrpc_set_type|xmlwriter_end_attribute|xmlwriter_end_cdata|' +\n        'xmlwriter_end_comment|xmlwriter_end_document|xmlwriter_end_dtd|xmlwriter_end_dtd_attlist|xmlwriter_end_dtd_element|' +\n        'xmlwriter_end_dtd_entity|xmlwriter_end_element|xmlwriter_end_pi|xmlwriter_flush|xmlwriter_full_end_element|xmlwriter_open_memory|' +\n        'xmlwriter_open_uri|xmlwriter_output_memory|xmlwriter_set_indent|xmlwriter_set_indent_string|xmlwriter_start_attribute|' +\n        'xmlwriter_start_attribute_ns|xmlwriter_start_cdata|xmlwriter_start_comment|xmlwriter_start_document|xmlwriter_start_dtd|' +\n        'xmlwriter_start_dtd_attlist|xmlwriter_start_dtd_element|xmlwriter_start_dtd_entity|xmlwriter_start_element|xmlwriter_start_element_ns|' +\n        'xmlwriter_start_pi|xmlwriter_text|xmlwriter_write_attribute|xmlwriter_write_attribute_ns|xmlwriter_write_cdata|xmlwriter_write_comment|' +\n        'xmlwriter_write_dtd|xmlwriter_write_dtd_attlist|xmlwriter_write_dtd_element|xmlwriter_write_dtd_entity|xmlwriter_write_element|' +\n        'xmlwriter_write_element_ns|xmlwriter_write_pi|xmlwriter_write_raw|xpath_eval|xpath_eval_expression|xpath_new_context|xpath_register_ns|' +\n        'xpath_register_ns_auto|xptr_eval|xptr_new_context|xslt_backend_info|xslt_backend_name|xslt_backend_version|xslt_create|xslt_errno|' +\n        'xslt_error|xslt_free|xslt_getopt|xslt_process|xslt_set_base|xslt_set_encoding|xslt_set_error_handler|xslt_set_log|xslt_set_object|' +\n        'xslt_set_sax_handler|xslt_set_sax_handlers|xslt_set_scheme_handler|xslt_set_scheme_handlers|xslt_setopt|xsltprocessor|yaml_emit|' +\n        'yaml_emit_file|yaml_parse|yaml_parse_file|yaml_parse_url|yaz_addinfo|yaz_ccl_conf|yaz_ccl_parse|yaz_close|yaz_connect|yaz_database|' +\n        'yaz_element|yaz_errno|yaz_error|yaz_es|yaz_es_result|yaz_get_option|yaz_hits|yaz_itemorder|yaz_present|yaz_range|yaz_record|yaz_scan|' +\n        'yaz_scan_result|yaz_schema|yaz_search|yaz_set_option|yaz_sort|yaz_syntax|yaz_wait|yp_all|yp_cat|yp_err_string|yp_errno|yp_first|' +\n        'yp_get_default_domain|yp_master|yp_match|yp_next|yp_order|zend_logo_guid|zend_thread_id|zend_version|zip_close|zip_entry_close|' +\n        'zip_entry_compressedsize|zip_entry_compressionmethod|zip_entry_filesize|zip_entry_name|zip_entry_open|zip_entry_read|zip_open|zip_read|' +\n        'ziparchive|ziparchive_addemptydir|ziparchive_addfile|ziparchive_addfromstring|ziparchive_close|ziparchive_deleteindex|' +\n        'ziparchive_deletename|ziparchive_extractto|ziparchive_getarchivecomment|ziparchive_getcommentindex|ziparchive_getcommentname|' +\n        'ziparchive_getfromindex|ziparchive_getfromname|ziparchive_getnameindex|ziparchive_getstatusstring|ziparchive_getstream|' +\n        'ziparchive_locatename|ziparchive_open|ziparchive_renameindex|ziparchive_renamename|ziparchive_setCommentName|ziparchive_setarchivecomment|' +\n        'ziparchive_setcommentindex|ziparchive_statindex|ziparchive_statname|ziparchive_unchangeall|ziparchive_unchangearchive|' +\n        'ziparchive_unchangeindex|ziparchive_unchangename|zlib_get_coding_type').split('|')\n    );\n\n    // http://php.net/manual/en/reserved.keywords.php\n    var keywords = lang.arrayToMap(\n        ('abstract|and|array|as|break|case|catch|class|clone|const|continue|declare|default|do|else|elseif|enddeclare|endfor|endforeach|endif|' +\n        'endswitch|endwhile|extends|final|for|foreach|function|global|goto|if|implements|interface|instanceof|namespace|new|or|private|protected|' +\n        'public|static|switch|throw|try|use|var|while|xor').split('|')\n    );\n\n    // http://php.net/manual/en/reserved.keywords.php\n    var languageConstructs = lang.arrayToMap(\n        ('die|echo|empty|exit|eval|include|include_once|isset|list|require|require_once|return|print|unset').split('|')\n    );\n\n    var builtinConstants = lang.arrayToMap(\n        ('true|false|null|__CLASS__|__DIR__|__FILE__|__LINE__|__METHOD__|__FUNCTION__|__NAMESPACE__').split('|')\n    );\n\n    var builtinVariables = lang.arrayToMap(\n        ('$GLOBALS|$_SERVER|$_GET|$_POST|$_FILES|$_REQUEST|$_SESSION|$_ENV|$_COOKIE|$php_errormsg|$HTTP_RAW_POST_DATA|' +\n        '$http_response_header|$argc|$argv').split('|')\n    );\n\n    // Discovery done by downloading 'Many HTML files' from:  http://php.net/download-docs.php\n    // Then search for files containing 'deprecated' (case-insensitive) and look at each file that turns up.\n    var builtinFunctionsDeprecated = lang.arrayToMap(\n        ('key_exists|cairo_matrix_create_scale|cairo_matrix_create_translate|call_user_method|call_user_method_array|com_addref|com_get|' +\n        'com_invoke|com_isenum|com_load|com_release|com_set|connection_timeout|cubrid_load_from_glo|cubrid_new_glo|cubrid_save_to_glo|' +\n        'cubrid_send_glo|define_syslog_variables|dl|ereg|ereg_replace|eregi|eregi_replace|hw_documentattributes|hw_documentbodytag|' +\n        'hw_documentsize|hw_outputdocument|imagedashedline|maxdb_bind_param|maxdb_bind_result|maxdb_client_encoding|maxdb_close_long_data|' +\n        'maxdb_execute|maxdb_fetch|maxdb_get_metadata|maxdb_param_count|maxdb_send_long_data|mcrypt_ecb|mcrypt_generic_end|mime_content_type|' +\n        'mysql_createdb|mysql_dbname|mysql_db_query|mysql_drop_db|mysql_dropdb|mysql_escape_string|mysql_fieldflags|mysql_fieldflags|' +\n        'mysql_fieldname|mysql_fieldtable|mysql_fieldtype|mysql_freeresult|mysql_listdbs|mysql_list_fields|mysql_listfields|mysql_list_tables|' +\n        'mysql_listtables|mysql_numfields|mysql_numrows|mysql_selectdb|mysql_tablename|mysqli_bind_param|mysqli_bind_result|' +\n        'mysqli_disable_reads_from_master|mysqli_disable_rpl_parse|mysqli_enable_reads_from_master|mysqli_enable_rpl_parse|mysqli_execute|' +\n        'mysqli_fetch|mysqli_get_metadata|mysqli_master_query|mysqli_param_count|mysqli_rpl_parse_enabled|mysqli_rpl_probe|mysqli_rpl_query_type|' +\n        'mysqli_send_long_data|mysqli_send_query|mysqli_slave_query|ocibindbyname|ocicancel|ocicloselob|ocicollappend|ocicollassign|' +\n        'ocicollassignelem|ocicollgetelem|ocicollmax|ocicollsize|ocicolltrim|ocicolumnisnull|ocicolumnname|ocicolumnprecision|ocicolumnscale|' +\n        'ocicolumnsize|ocicolumntype|ocicolumntyperaw|ocicommit|ocidefinebyname|ocierror|ociexecute|ocifetch|ocifetchinto|ocifetchstatement|' +\n        'ocifreecollection|ocifreecursor|ocifreedesc|ocifreestatement|ociinternaldebug|ociloadlob|ocilogoff|ocilogon|ocinewcollection|' +\n        'ocinewcursor|ocinewdescriptor|ocinlogon|ocinumcols|ociparse|ociplogon|ociresult|ocirollback|ocirowcount|ocisavelob|ocisavelobfile|' +\n        'ociserverversion|ocisetprefetch|ocistatementtype|ociwritelobtofile|ociwritetemporarylob|PDF_add_annotation|PDF_add_bookmark|' +\n        'PDF_add_launchlink|PDF_add_locallink|PDF_add_note|PDF_add_outline|PDF_add_pdflink|PDF_add_weblink|PDF_attach_file|PDF_begin_page|' +\n        'PDF_begin_template|PDF_close_pdi|PDF_close|PDF_findfont|PDF_get_font|PDF_get_fontname|PDF_get_fontsize|PDF_get_image_height|' +\n        'PDF_get_image_width|PDF_get_majorversion|PDF_get_minorversion|PDF_get_pdi_parameter|PDF_get_pdi_value|PDF_open_ccitt|PDF_open_file|' +\n        'PDF_open_gif|PDF_open_image_file|PDF_open_image|PDF_open_jpeg|PDF_open_pdi|PDF_open_tiff|PDF_place_image|PDF_place_pdi_page|' +\n        'PDF_set_border_color|PDF_set_border_dash|PDF_set_border_style|PDF_set_char_spacing|PDF_set_duration|PDF_set_horiz_scaling|' +\n        'PDF_set_info_author|PDF_set_info_creator|PDF_set_info_keywords|PDF_set_info_subject|PDF_set_info_title|PDF_set_leading|' +\n        'PDF_set_text_matrix|PDF_set_text_rendering|PDF_set_text_rise|PDF_set_word_spacing|PDF_setgray_fill|PDF_setgray_stroke|PDF_setgray|' +\n        'PDF_setpolydash|PDF_setrgbcolor_fill|PDF_setrgbcolor_stroke|PDF_setrgbcolor|PDF_show_boxed|php_check_syntax|px_set_tablename|' +\n        'px_set_targetencoding|runkit_sandbox_output_handler|session_is_registered|session_register|session_unregister' +\n        'set_magic_quotes_runtime|magic_quotes_runtime|set_socket_blocking|socket_set_blocking|set_socket_timeout|socket_set_timeout|split|spliti|' +\n        'sql_regcase').split('|')\n    );\n\n    var keywordsDeprecated = lang.arrayToMap(\n        ('cfunction|old_function').split('|')\n    );\n\n    var futureReserved = lang.arrayToMap([]);\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"support.php_tag\", // php open tag\n                regex : \"<\\\\?(?:php|\\\\=)\"\n            },\n            {\n                token : \"support.php_tag\", // php close tag\n                regex : \"\\\\?>\"\n            },\n            {\n                token : \"comment\",\n                regex : \"<\\\\!--\",\n                next : \"htmlcomment\"\n            }, \n            {\n                token : \"meta.tag\",\n                regex : \"<style\",\n                next : \"css\"\n            },\n            {\n                token : \"meta.tag\", // opening tag\n                regex : \"<\\\\/?[-_a-zA-Z0-9:]+\",\n                next : \"htmltag\"\n            },\n            {\n                token : 'meta.tag',\n                regex : '<\\!DOCTYPE.*?>'\n            },\n            {\n                token : \"comment\",\n                regex : \"\\\\/\\\\/.*$\"\n            },\n            {\n               token : \"comment\",\n               regex : \"#.*$\"\n            },\n            docComment.getStartRule(\"doc-start\"),\n            {\n                token : \"comment\", // multi line comment\n                regex : \"\\\\/\\\\*\",\n                next : \"comment\"\n            }, {\n                token : \"string.regexp\",\n                regex : \"[/](?:(?:\\\\[(?:\\\\\\\\]|[^\\\\]])+\\\\])|(?:\\\\\\\\/|[^\\\\]/]))*[/][gimy]*\\\\s*(?=[).,;]|$)\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // multi line string start\n                regex : '[\"][\\\\s\\\\S]*',\n                next : \"qqstring\"\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"string\", // multi line string start\n                regex : \"['][\\\\s\\\\S]+\",\n                next : \"qstring\"\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n                token : \"constant.language\", // constants\n                regex : \"\\\\b(?:DEFAULT_INCLUDE_PATH|E_(?:ALL|CO(?:MPILE_(?:ERROR|WARNING)|RE_(?:ERROR|WARNING))|\" +\n                        \"ERROR|NOTICE|PARSE|STRICT|USER_(?:ERROR|NOTICE|WARNING)|WARNING)|P(?:EAR_(?:EXTENSION_DIR|INSTALL_DIR)|\" +\n                        \"HP_(?:BINDIR|CONFIG_FILE_(?:PATH|SCAN_DIR)|DATADIR|E(?:OL|XTENSION_DIR)|INT_(?:MAX|SIZE)|\" +\n                        \"L(?:IBDIR|OCALSTATEDIR)|O(?:S|UTPUT_HANDLER_(?:CONT|END|START))|PREFIX|S(?:API|HLIB_SUFFIX|YSCONFDIR)|\" +\n                        \"VERSION))|__COMPILER_HALT_OFFSET__)\\\\b\"\n            }, {\n                token : \"constant.language\", // constants\n                regex : \"\\\\b(?:A(?:B(?:DAY_(?:1|2|3|4|5|6|7)|MON_(?:1(?:0|1|2|)|2|3|4|5|6|7|8|9))|LT_DIGITS|M_STR|\" +\n                        \"SSERT_(?:ACTIVE|BAIL|CALLBACK|QUIET_EVAL|WARNING))|C(?:ASE_(?:LOWER|UPPER)|HAR_MAX|\" +\n                        \"O(?:DESET|NNECTION_(?:ABORTED|NORMAL|TIMEOUT)|UNT_(?:NORMAL|RECURSIVE))|\" +\n                        \"R(?:EDITS_(?:ALL|DOCS|FULLPAGE|G(?:ENERAL|ROUP)|MODULES|QA|SAPI)|NCYSTR|\" +\n                        \"YPT_(?:BLOWFISH|EXT_DES|MD5|S(?:ALT_LENGTH|TD_DES)))|URRENCY_SYMBOL)|D(?:AY_(?:1|2|3|4|5|6|7)|\" +\n                        \"ECIMAL_POINT|IRECTORY_SEPARATOR|_(?:FMT|T_FMT))|E(?:NT_(?:COMPAT|NOQUOTES|QUOTES)|RA(?:_(?:D_(?:FMT|T_FMT)|\" +\n                        \"T_FMT|YEAR)|)|XTR_(?:IF_EXISTS|OVERWRITE|PREFIX_(?:ALL|I(?:F_EXISTS|NVALID)|SAME)|SKIP))|FRAC_DIGITS|GROUPING|\" +\n                        \"HTML_(?:ENTITIES|SPECIALCHARS)|IN(?:FO_(?:ALL|C(?:ONFIGURATION|REDITS)|ENVIRONMENT|GENERAL|LICENSE|MODULES|VARIABLES)|\" +\n                        \"I_(?:ALL|PERDIR|SYSTEM|USER)|T_(?:CURR_SYMBOL|FRAC_DIGITS))|L(?:C_(?:ALL|C(?:OLLATE|TYPE)|M(?:ESSAGES|ONETARY)|NUMERIC|TIME)|\" +\n                        \"O(?:CK_(?:EX|NB|SH|UN)|G_(?:A(?:LERT|UTH(?:PRIV|))|C(?:ONS|R(?:IT|ON))|D(?:AEMON|EBUG)|E(?:MERG|RR)|INFO|KERN|\" +\n                        \"L(?:OCAL(?:0|1|2|3|4|5|6|7)|PR)|MAIL|N(?:DELAY|EWS|O(?:TICE|WAIT))|ODELAY|P(?:ERROR|ID)|SYSLOG|U(?:SER|UCP)|WARNING)))|\" +\n                        \"M(?:ON_(?:1(?:0|1|2|)|2|3|4|5|6|7|8|9|DECIMAL_POINT|GROUPING|THOUSANDS_SEP)|_(?:1_PI|2_(?:PI|SQRTPI)|E|L(?:N(?:10|2)|\" +\n                        \"OG(?:10E|2E))|PI(?:_(?:2|4)|)|SQRT(?:1_2|2)))|N(?:EGATIVE_SIGN|O(?:EXPR|STR)|_(?:CS_PRECEDES|S(?:EP_BY_SPACE|IGN_POSN)))|\" +\n                        \"P(?:ATH(?:INFO_(?:BASENAME|DIRNAME|EXTENSION)|_SEPARATOR)|M_STR|OSITIVE_SIGN|_(?:CS_PRECEDES|S(?:EP_BY_SPACE|IGN_POSN)))|\" +\n                        \"RADIXCHAR|S(?:EEK_(?:CUR|END|SET)|ORT_(?:ASC|DESC|NUMERIC|REGULAR|STRING)|TR_PAD_(?:BOTH|LEFT|RIGHT))|\" +\n                        \"T(?:HOUS(?:ANDS_SEP|EP)|_FMT(?:_AMPM|))|YES(?:EXPR|STR)|STD(?:IN|OUT|ERR))\\\\b\"\n            }, {\n                token : function(value) {\n                    if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (builtinConstants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else if (builtinVariables.hasOwnProperty(value))\n                        return \"variable.language\";\n                    else if (futureReserved.hasOwnProperty(value))\n                        return \"invalid.illegal\";\n                    else if (builtinFunctions.hasOwnProperty(value))\n                        return \"support.function\";\n                    else if (value == \"debugger\")\n                        return \"invalid.deprecated\";\n                    else\n                        if(value.match(/^(\\$[a-zA-Z][a-zA-Z0-9_]*|self|parent)$/))\n                            return \"variable\";\n                        return \"identifier\";\n                },\n                // TODO: Unicode escape sequences\n                // TODO: Unicode identifiers\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"!|\\\\$|%|&|\\\\*|\\\\-\\\\-|\\\\-|\\\\+\\\\+|\\\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\\\|\\\\||\\\\?\\\\:|\\\\*=|%=|\\\\+=|\\\\-=|&=|\\\\^=|\\\\b(?:in|instanceof|new|delete|typeof|void)\"\n            }, {\n                token : \"lparen\",\n                regex : \"[[({]\"\n            }, {\n                token : \"rparen\",\n                regex : \"[\\\\])}]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                regex : \".+\"\n            }\n        ],\n        \"qqstring\" : [\n            {\n                token : \"string\",\n                regex : '\"',\n                next : \"start\"\n            }, {\n                token : \"string\",\n                regex : '[^\"]+'\n            }\n        ],\n        \"qstring\" : [\n            {\n                token : \"string\",\n                regex : \"'\",\n                next : \"start\"\n            }, {\n                token : \"string\",\n                regex : \"[^']+\"\n            }\n        ],\n        \"htmlcomment\" : [\n             {\n                 token : \"comment\",\n                 regex : \".*?-->\",\n                 next : \"start\"\n             }, {\n                 token : \"comment\",\n                 regex : \".+\"\n             } \n         ],\n         \"htmltag\" : [ \n             {\n                 token : \"meta.tag\",\n                 regex : \">\",\n                 next : \"start\"\n             }, {\n                 token : \"text\",\n                 regex : \"[-_a-zA-Z0-9:]+\"\n             }, {\n                 token : \"text\",\n                 regex : \"\\\\s+\"\n             }, {\n                 token : \"string\",\n                 regex : '\".*?\"'\n             }, {\n                 token : \"string\",\n                 regex : \"'.*?'\"\n             } \n         ],\n        \"css\" : [ \n             {\n                 token : \"meta.tag\",\n                 regex : \"<\\/style>\",\n                 next : \"htmltag\"\n             }, {\n                 token : \"meta.tag\",\n                 regex : \">\"\n             }, {\n                 token : 'text',\n                 regex : \"(?:media|type|href)\"\n             }, {\n                 token : 'string',\n                 regex : '=\".*?\"'\n             }, {\n                 token : \"paren.lparen\",\n                 regex : \"\\{\",\n                 next : \"cssdeclaration\"\n             }, {\n                 token : \"keyword\",\n                 regex : \"#[A-Za-z0-9\\-\\_\\.]+\"\n             }, {\n                 token : \"variable\",\n                 regex : \"\\\\.[A-Za-z0-9\\-\\_\\.]+\"\n             }, {\n                 token : \"constant\",\n                 regex : \"[A-Za-z0-9]+\"\n             }\n         ],\n         \"cssdeclaration\" : [\n             {\n                 token : \"support.type\",\n                 regex : \"[\\-a-zA-Z]+\",\n                 next  : \"cssvalue\"\n             }, \n             {\n                 token : \"paren.rparen\",\n                 regex : '\\}',\n                 next : \"css\"\n             }\n         ],\n         \"cssvalue\" : [\n               {\n                   token : \"text\",\n                   regex : \"\\:\"\n               }, \n               {\n                   token : \"constant\",\n                   regex : \"#[0-9a-zA-Z]+\"\n               },\n               {\n                   token : \"text\",\n                   regex : \"[\\-\\_0-9a-zA-Z\\\"' ,%]+\"\n               },\n               {\n                   token : \"text\",\n                   regex : \";\",\n                   next : \"cssdeclaration\"\n               }\n         ]\n    };\n\n    this.embedRules(DocCommentHighlightRules, \"doc-\",\n        [ DocCommentHighlightRules.getEndRule(\"start\") ]);\n};\n\noop.inherits(PhpHighlightRules, TextHighlightRules);\n\nexports.PhpHighlightRules = PhpHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/powershell.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar PowershellHighlightRules = require(\"./powershell_highlight_rules\").PowershellHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar CstyleBehaviour = require(\"./behaviour/cstyle\").CstyleBehaviour;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new PowershellHighlightRules().getRules());\n    this.$outdent = new MatchingBraceOutdent();\n    this.$behaviour = new CstyleBehaviour();\n    this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n      \n        if (state == \"start\") {\n            var match = line.match(/^.*[\\{\\(\\[]\\s*$/);\n            if (match) {\n                indent += tab;\n            }\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n\n    this.createWorker = function(session) {\n        return null;\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/powershell_highlight_rules.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar PowershellHighlightRules = function() {\n    \n    var keywords = lang.arrayToMap(\n      (\"function|if|else|elseif|switch|while|default|for|do|until|break|continue|\" + \n       \"foreach|return|filter|in|trap|throw|param|begin|process|end\").split(\"|\")\n    );\n\n    var builtinFunctions = lang.arrayToMap(\n      (\"Get-Alias|Import-Alias|New-Alias|Set-Alias|Get-AuthenticodeSignature|Set-AuthenticodeSignature|\" +\n       \"Set-Location|Get-ChildItem|Clear-Item|Get-Command|Measure-Command|Trace-Command|\" +\n       \"Add-Computer|Checkpoint-Computer|Remove-Computer|Restart-Computer|Restore-Computer|Stop-Computer|\" +\n       \"Reset-ComputerMachinePassword|Test-ComputerSecureChannel|Add-Content|Get-Content|Set-Content|Clear-Content|\" +\n       \"Get-Command|Invoke-Command|Enable-ComputerRestore|Disable-ComputerRestore|Get-ComputerRestorePoint|Test-Connection|\" +\n       \"ConvertFrom-CSV|ConvertTo-CSV|ConvertTo-Html|ConvertTo-Xml|ConvertFrom-SecureString|ConvertTo-SecureString|\" +\n       \"Copy-Item|Export-Counter|Get-Counter|Import-Counter|Get-Credential|Get-Culture|\" +\n       \"Get-ChildItem|Get-Date|Set-Date|Remove-Item|Compare-Object|Get-Event|\" +\n       \"Get-WinEvent|New-Event|Remove-Event|Unregister-Event|Wait-Event|Clear-EventLog|\" +\n       \"Get-Eventlog|Limit-EventLog|New-Eventlog|Remove-EventLog|Show-EventLog|Write-EventLog|\" +\n       \"Get-EventSubscriber|Register-EngineEvent|Register-ObjectEvent|Register-WmiEvent|Get-ExecutionPolicy|Set-ExecutionPolicy|\" +\n       \"Export-Alias|Export-Clixml|Export-Console|Export-Csv|ForEach-Object|Format-Custom|\" +\n       \"Format-List|Format-Table|Format-Wide|Export-FormatData|Get-FormatData|Get-Item|\" +\n       \"Get-ChildItem|Get-Help|Add-History|Clear-History|Get-History|Invoke-History|\" +\n       \"Get-Host|Read-Host|Write-Host|Get-HotFix|Import-Clixml|Import-Csv|\" +\n       \"Invoke-Command|Invoke-Expression|Get-Item|Invoke-Item|New-Item|Remove-Item|\" +\n       \"Set-Item|Clear-ItemProperty|Copy-ItemProperty|Get-ItemProperty|Move-ItemProperty|New-ItemProperty|\" +\n       \"Remove-ItemProperty|Rename-ItemProperty|Set-ItemProperty|Get-Job|Receive-Job|Remove-Job|\" +\n       \"Start-Job|Stop-Job|Wait-Job|Stop-Process|Update-List|Get-Location|\" +\n       \"Pop-Location|Push-Location|Set-Location|Send-MailMessage|Add-Member|Get-Member|\" +\n       \"Move-Item|Compare-Object|Group-Object|Measure-Object|New-Object|Select-Object|\" +\n       \"Sort-Object|Where-Object|Out-Default|Out-File|Out-GridView|Out-Host|\" +\n       \"Out-Null|Out-Printer|Out-String|Convert-Path|Join-Path|Resolve-Path|\" +\n       \"Split-Path|Test-Path|Get-Pfxcertificate|Pop-Location|Push-Location|Get-Process|\" +\n       \"Start-Process|Stop-Process|Wait-Process|Enable-PSBreakpoint|Disable-PSBreakpoint|Get-PSBreakpoint|\" +\n       \"Set-PSBreakpoint|Remove-PSBreakpoint|Get-PSDrive|New-PSDrive|Remove-PSDrive|Get-PSProvider|\" +\n       \"Set-PSdebug|Enter-PSSession|Exit-PSSession|Export-PSSession|Get-PSSession|Import-PSSession|\" +\n       \"New-PSSession|Remove-PSSession|Disable-PSSessionConfiguration|Enable-PSSessionConfiguration|Get-PSSessionConfiguration|Register-PSSessionConfiguration|\" +\n       \"Set-PSSessionConfiguration|Unregister-PSSessionConfiguration|New-PSSessionOption|Add-PsSnapIn|Get-PsSnapin|Remove-PSSnapin|\" +\n       \"Get-Random|Read-Host|Remove-Item|Rename-Item|Rename-ItemProperty|Select-Object|\" +\n       \"Select-XML|Send-MailMessage|Get-Service|New-Service|Restart-Service|Resume-Service|\" +\n       \"Set-Service|Start-Service|Stop-Service|Suspend-Service|Sort-Object|Start-Sleep|\" +\n       \"ConvertFrom-StringData|Select-String|Tee-Object|New-Timespan|Trace-Command|Get-Tracesource|\" +\n       \"Set-Tracesource|Start-Transaction|Complete-Transaction|Get-Transaction|Use-Transaction|Undo-Transaction|\" +\n       \"Start-Transcript|Stop-Transcript|Add-Type|Update-TypeData|Get-Uiculture|Get-Unique|\" +\n       \"Update-Formatdata|Update-Typedata|Clear-Variable|Get-Variable|New-Variable|Remove-Variable|\" +\n       \"Set-Variable|New-WebServiceProxy|Where-Object|Write-Debug|Write-Error|Write-Host|\" +\n       \"Write-Output|Write-Progress|Write-Verbose|Write-Warning|Set-WmiInstance|Invoke-WmiMethod|\" +\n       \"Get-WmiObject|Remove-WmiObject|Connect-WSMan|Disconnect-WSMan|Test-WSMan|Invoke-WSManAction|\" +\n       \"Disable-WSManCredSSP|Enable-WSManCredSSP|Get-WSManCredSSP|New-WSManInstance|Get-WSManInstance|Set-WSManInstance|\" +\n       \"Remove-WSManInstance|Set-WSManQuickConfig|New-WSManSessionOption\").split(\"|\"));\n\n    var binaryOperatorsRe = \"eq|ne|ge|gt|lt|le|like|notlike|match|notmatch|replace|contains|notcontains|\" +\n                            \"ieq|ine|ige|igt|ile|ilt|ilike|inotlike|imatch|inotmatch|ireplace|icontains|inotcontains|\" +\n                            \"is|isnot|as|\" +\n                            \"and|or|band|bor|not\"; \n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \"#.*$\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n                token : \"constant.language.boolean\",\n                regex : \"[$](?:[Tt]rue|[Ff]alse)\\\\b\"\n            }, {\n                token : \"constant.language\",\n                regex : \"[$][Nn]ull\\\\b\"\n            }, {\n                token : \"variable.instance\",\n                regex : \"[$][a-zA-Z][a-zA-Z0-9_]*\\\\b\"\n            }, {\n                token : function(value) {\n                    if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (builtinFunctions.hasOwnProperty(value))\n                        return \"support.function\";\n                    else\n                        return \"identifier\";\n                },\n                // TODO: Unicode escape sequences\n                // TODO: Unicode identifiers\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$\\\\-]*\\\\b\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"\\\\-(?:\" + binaryOperatorsRe + \")\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"&|\\\\*|\\\\+|\\\\-|\\\\=|\\\\+=|\\\\-=\"\n            }, {\n                token : \"lparen\",\n                regex : \"[[({]\"\n            }, {\n                token : \"rparen\",\n                regex : \"[\\\\])}]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ]\n    };\n};\n\noop.inherits(PowershellHighlightRules, TextHighlightRules);\n\nexports.PowershellHighlightRules = PowershellHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/python.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n* Version: MPL 1.1/GPL 2.0/LGPL 2.1\n*\n* The contents of this file are subject to the Mozilla Public License Version\n* 1.1 (the \"License\"); you may not use this file except in compliance with\n* the License. You may obtain a copy of the License at\n* http://www.mozilla.org/MPL/\n*\n* Software distributed under the License is distributed on an \"AS IS\" basis,\n* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n* for the specific language governing rights and limitations under the\n* License.\n*\n* The Original Code is Ajax.org Code Editor (ACE).\n*\n* The Initial Developer of the Original Code is\n* Ajax.org B.V.\n* Portions created by the Initial Developer are Copyright (C) 2010\n* the Initial Developer. All Rights Reserved.\n*\n* Contributor(s):\n*      Fabian Jakobs <fabian AT ajax DOT org>\n*      Colin Gourlay <colin DOT j DOT gourlay AT gmail DOT com>\n*\n* Alternatively, the contents of this file may be used under the terms of\n* either the GNU General Public License Version 2 or later (the \"GPL\"), or\n* the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n* in which case the provisions of the GPL or the LGPL are applicable instead\n* of those above. If you wish to allow use of your version of this file only\n* under the terms of either the GPL or the LGPL, and not to allow others to\n* use your version of this file under the terms of the MPL, indicate your\n* decision by deleting the provisions above and replace them with the notice\n* and other provisions required by the GPL or the LGPL. If you do not delete\n* the provisions above, a recipient may use your version of this file under\n* the terms of any one of the MPL, the GPL or the LGPL.\n*\n* ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar PythonHighlightRules = require(\"./python_highlight_rules\").PythonHighlightRules;\nvar PythonFoldMode = require(\"./folding/pythonic\").FoldMode;\nvar Range = require(\"../range\").Range;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new PythonHighlightRules().getRules());\n    this.foldingRules = new PythonFoldMode(\"\\\\:\");\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        var outdent = true;\n        var re = /^(\\s*)#/;\n\n        for (var i=startRow; i<= endRow; i++) {\n            if (!re.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        if (outdent) {\n            var deleteRange = new Range(0, 0, 0, 0);\n            for (var i=startRow; i<= endRow; i++)\n            {\n                var line = doc.getLine(i);\n                var m = line.match(re);\n                deleteRange.start.row = i;\n                deleteRange.end.row = i;\n                deleteRange.end.column = m[0].length;\n                doc.replace(deleteRange, m[1]);\n            }\n        }\n        else {\n            doc.indentRows(startRow, endRow, \"#\");\n        }\n    };\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n\n        if (state == \"start\") {\n            var match = line.match(/^.*[\\{\\(\\[\\:]\\s*$/);\n            if (match) {\n                indent += tab;\n            }\n        }\n\n        return indent;\n    };\n\n    var outdents = {\n        \"pass\": 1,\n        \"return\": 1,\n        \"raise\": 1,\n        \"break\": 1,\n        \"continue\": 1\n    };\n    \n    this.checkOutdent = function(state, line, input) {\n        if (input !== \"\\r\\n\" && input !== \"\\r\" && input !== \"\\n\")\n            return false;\n\n        var tokens = this.$tokenizer.getLineTokens(line.trim(), state).tokens;\n        \n        if (!tokens)\n            return false;\n        \n        // ignore trailing comments\n        do {\n            var last = tokens.pop();\n        } while (last && (last.type == \"comment\" || (last.type == \"text\" && last.value.match(/^\\s+$/))));\n        \n        if (!last)\n            return false;\n        \n        return (last.type == \"keyword\" && outdents[last.value]);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        // outdenting in python is slightly different because it always applies\n        // to the next line and only of a new line is inserted\n        \n        row += 1;\n        var indent = this.$getIndent(doc.getLine(row));\n        var tab = doc.getTabString();\n        if (indent.slice(-tab.length) == tab)\n            doc.remove(new Range(row, indent.length-tab.length, row, indent.length));\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/python_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Colin Gourlay <colin DOT j DOT gourlay AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK *****\n *\n * TODO: python delimiters\n */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar PythonHighlightRules = function() {\n\n    var keywords = lang.arrayToMap(\n        (\"and|as|assert|break|class|continue|def|del|elif|else|except|exec|\" +\n        \"finally|for|from|global|if|import|in|is|lambda|not|or|pass|print|\" +\n        \"raise|return|try|while|with|yield\").split(\"|\")\n    );\n\n    var builtinConstants = lang.arrayToMap(\n        (\"True|False|None|NotImplemented|Ellipsis|__debug__\").split(\"|\")\n    );\n\n    var builtinFunctions = lang.arrayToMap(\n        (\"abs|divmod|input|open|staticmethod|all|enumerate|int|ord|str|any|\" +\n        \"eval|isinstance|pow|sum|basestring|execfile|issubclass|print|super|\" +\n        \"binfile|iter|property|tuple|bool|filter|len|range|type|bytearray|\" +\n        \"float|list|raw_input|unichr|callable|format|locals|reduce|unicode|\" +\n        \"chr|frozenset|long|reload|vars|classmethod|getattr|map|repr|xrange|\" +\n        \"cmp|globals|max|reversed|zip|compile|hasattr|memoryview|round|\" +\n        \"__import__|complex|hash|min|set|apply|delattr|help|next|setattr|\" +\n        \"buffer|dict|hex|object|slice|coerce|dir|id|oct|sorted|intern\").split(\"|\")\n    );\n\n    var futureReserved = lang.arrayToMap(\n        (\"\").split(\"|\")\n    );\n\n    var strPre = \"(?:r|u|ur|R|U|UR|Ur|uR)?\";\n\n    var decimalInteger = \"(?:(?:[1-9]\\\\d*)|(?:0))\";\n    var octInteger = \"(?:0[oO]?[0-7]+)\";\n    var hexInteger = \"(?:0[xX][\\\\dA-Fa-f]+)\";\n    var binInteger = \"(?:0[bB][01]+)\";\n    var integer = \"(?:\" + decimalInteger + \"|\" + octInteger + \"|\" + hexInteger + \"|\" + binInteger + \")\";\n\n    var exponent = \"(?:[eE][+-]?\\\\d+)\";\n    var fraction = \"(?:\\\\.\\\\d+)\";\n    var intPart = \"(?:\\\\d+)\";\n    var pointFloat = \"(?:(?:\" + intPart + \"?\" + fraction + \")|(?:\" + intPart + \"\\\\.))\";\n    var exponentFloat = \"(?:(?:\" + pointFloat + \"|\" +  intPart + \")\" + exponent + \")\";\n    var floatNumber = \"(?:\" + exponentFloat + \"|\" + pointFloat + \")\";\n\n    this.$rules = {\n        \"start\" : [ {\n            token : \"comment\",\n            regex : \"#.*$\"\n        }, {\n            token : \"string\",           // \"\"\" string\n            regex : strPre + '\"{3}(?:[^\\\\\\\\]|\\\\\\\\.)*?\"{3}'\n        }, {\n            token : \"string\",           // multi line \"\"\" string start\n            merge : true,\n            regex : strPre + '\"{3}.*$',\n            next : \"qqstring\"\n        }, {\n            token : \"string\",           // \" string\n            regex : strPre + '\"(?:[^\\\\\\\\]|\\\\\\\\.)*?\"'\n        }, {\n            token : \"string\",           // ''' string\n            regex : strPre + \"'{3}(?:[^\\\\\\\\]|\\\\\\\\.)*?'{3}\"\n        }, {\n            token : \"string\",           // multi line ''' string start\n            merge : true,\n            regex : strPre + \"'{3}.*$\",\n            next : \"qstring\"\n        }, {\n            token : \"string\",           // ' string\n            regex : strPre + \"'(?:[^\\\\\\\\]|\\\\\\\\.)*?'\"\n        }, {\n            token : \"constant.numeric\", // imaginary\n            regex : \"(?:\" + floatNumber + \"|\\\\d+)[jJ]\\\\b\"\n        }, {\n            token : \"constant.numeric\", // float\n            regex : floatNumber\n        }, {\n            token : \"constant.numeric\", // long integer\n            regex : integer + \"[lL]\\\\b\"\n        }, {\n            token : \"constant.numeric\", // integer\n            regex : integer + \"\\\\b\"\n        }, {\n            token : function(value) {\n                if (keywords.hasOwnProperty(value))\n                    return \"keyword\";\n                else if (builtinConstants.hasOwnProperty(value))\n                    return \"constant.language\";\n                else if (futureReserved.hasOwnProperty(value))\n                    return \"invalid.illegal\";\n                else if (builtinFunctions.hasOwnProperty(value))\n                    return \"support.function\";\n                else if (value == \"debugger\")\n                    return \"invalid.deprecated\";\n                else\n                    return \"identifier\";\n            },\n            regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n        }, {\n            token : \"keyword.operator\",\n            regex : \"\\\\+|\\\\-|\\\\*|\\\\*\\\\*|\\\\/|\\\\/\\\\/|%|<<|>>|&|\\\\||\\\\^|~|<|>|<=|=>|==|!=|<>|=\"\n        }, {\n            token : \"lparen.paren\",\n            regex : \"[\\\\[\\\\(\\\\{]\"\n        }, {\n            token : \"paren.rparen\",\n            regex : \"[\\\\]\\\\)\\\\}]\"\n        }, {\n            token : \"text\",\n            regex : \"\\\\s+\"\n        } ],\n        \"qqstring\" : [ {\n            token : \"string\", // multi line \"\"\" string end\n            regex : '(?:[^\\\\\\\\]|\\\\\\\\.)*?\"{3}',\n            next : \"start\"\n        }, {\n            token : \"string\",\n            merge : true,\n            regex : '.+'\n        } ],\n        \"qstring\" : [ {\n            token : \"string\",  // multi line ''' string end\n            regex : \"(?:[^\\\\\\\\]|\\\\\\\\.)*?'{3}\",\n            next : \"start\"\n        }, {\n            token : \"string\",\n            merge : true,\n            regex : '.+'\n        } ]\n    };\n};\n\noop.inherits(PythonHighlightRules, TextHighlightRules);\n\nexports.PythonHighlightRules = PythonHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/python_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"../edit_session\").EditSession;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar Mode = require(\"./python\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n    setUp : function() {    \n        this.mode = new Mode();\n    },\n\n    \"test: getTokenizer() (smoke test)\" : function() {\n        var tokenizer = this.mode.getTokenizer();\n\n        assert.ok(tokenizer instanceof Tokenizer);\n\n        var tokens = tokenizer.getLineTokens(\"'juhu'\", \"start\").tokens;\n        assert.equal(\"string\", tokens[0].type);\n    },\n\n    \"test: auto outdent after 'pass', 'return' and 'raise'\" : function() {\n        assert.ok(this.mode.checkOutdent(\"start\", \"        pass\", \"\\n\"));\n        assert.ok(this.mode.checkOutdent(\"start\", \"        pass  \", \"\\n\"));\n        assert.ok(this.mode.checkOutdent(\"start\", \"        return\", \"\\n\"));\n        assert.ok(this.mode.checkOutdent(\"start\", \"        raise\", \"\\n\"));\n        assert.equal(this.mode.checkOutdent(\"start\", \"        raise\", \" \"), false);\n        assert.ok(this.mode.checkOutdent(\"start\", \"        pass # comment\", \"\\n\"));\n        assert.equal(this.mode.checkOutdent(\"start\", \"'juhu'\", \"\\n\"), false);\n    },\n    \n    \"test: auto outdent\" : function() {\n        var session = new EditSession([\"    if True:\", \"        pass\", \"        \"]);\n        this.mode.autoOutdent(\"start\", session, 1);\n        assert.equal(\"    \", session.getLine(2));\n    }\n\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/ruby.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Shlomo Zalman Heigh <shlomozalmanheigh AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar RubyHighlightRules = require(\"./ruby_highlight_rules\").RubyHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar Range = require(\"../range\").Range;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new RubyHighlightRules().getRules());\n    this.$outdent = new MatchingBraceOutdent();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        var outdent = true;\n        var re = /^(\\s*)#/;\n\n        for (var i=startRow; i<= endRow; i++) {\n            if (!re.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        if (outdent) {\n            var deleteRange = new Range(0, 0, 0, 0);\n            for (var i=startRow; i<= endRow; i++)\n            {\n                var line = doc.getLine(i);\n                var m = line.match(re);\n                deleteRange.start.row = i;\n                deleteRange.end.row = i;\n                deleteRange.end.column = m[0].length;\n                doc.replace(deleteRange, m[1]);\n            }\n        }\n        else {\n            doc.indentRows(startRow, endRow, \"#\");\n        }\n    };\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n        \n        if (state == \"start\") {\n            var match = line.match(/^.*[\\{\\(\\[]\\s*$/);\n            if (match) {\n                indent += tab;\n            }\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/ruby_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Shlomo Zalman Heigh <shlomozalmanheigh AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar RubyHighlightRules = function() {\n\n    var builtinFunctions = lang.arrayToMap(\n        (\"abort|Array|assert|assert_equal|assert_not_equal|assert_same|assert_not_same|\" +\n        \"assert_nil|assert_not_nil|assert_match|assert_no_match|assert_in_delta|assert_throws|\" + \n        \"assert_raise|assert_nothing_raised|assert_instance_of|assert_kind_of|assert_respond_to|\" +\n        \"assert_operator|assert_send|assert_difference|assert_no_difference|assert_recognizes|\" +\n        \"assert_generates|assert_response|assert_redirected_to|assert_template|assert_select|\" +\n        \"assert_select_email|assert_select_rjs|assert_select_encoded|css_select|at_exit|\" +\n        \"attr|attr_writer|attr_reader|attr_accessor|attr_accessible|autoload|binding|block_given?|callcc|\" +\n        \"caller|catch|chomp|chomp!|chop|chop!|defined?|delete_via_redirect|eval|exec|exit|\" +\n        \"exit!|fail|Float|flunk|follow_redirect!|fork|form_for|form_tag|format|gets|global_variables|gsub|\" +\n        \"gsub!|get_via_redirect|h|host!|https?|https!|include|Integer|lambda|link_to|\" +\n        \"link_to_unless_current|link_to_function|link_to_remote|load|local_variables|loop|open|open_session|\" +\n        \"p|print|printf|proc|putc|puts|post_via_redirect|put_via_redirect|raise|rand|\" +\n        \"raw|readline|readlines|redirect?|request_via_redirect|require|scan|select|\" +\n        \"set_trace_func|sleep|split|sprintf|srand|String|stylesheet_link_tag|syscall|system|sub|sub!|test|\" +\n        \"throw|trace_var|trap|untrace_var|atan2|cos|exp|frexp|ldexp|log|log10|sin|sqrt|tan|\" +\n        \"render|javascript_include_tag|csrf_meta_tag|label_tag|text_field_tag|submit_tag|check_box_tag|\" +\n        \"content_tag|radio_button_tag|text_area_tag|password_field_tag|hidden_field_tag|\" +\n        \"fields_for|select_tag|options_for_select|options_from_collection_for_select|collection_select|\" +\n        \"time_zone_select|select_date|select_time|select_datetime|date_select|time_select|datetime_select|\" +\n        \"select_year|select_month|select_day|select_hour|select_minute|select_second|file_field_tag|\" +\n        \"file_field|respond_to|skip_before_filter|around_filter|after_filter|verify|\" +\n        \"protect_from_forgery|rescue_from|helper_method|redirect_to|before_filter|\" +\n        \"send_data|send_file|validates_presence_of|validates_uniqueness_of|validates_length_of|\" +\n        \"validates_format_of|validates_acceptance_of|validates_associated|validates_exclusion_of|\" +\n        \"validates_inclusion_of|validates_numericality_of|validates_with|validates_each|\" +\n        \"authenticate_or_request_with_http_basic|authenticate_or_request_with_http_digest|\" +\n        \"filter_parameter_logging|match|get|post|resources|redirect|scope|assert_routing|\" +\n        \"translate|localize|extract_locale_from_tld|t|l|caches_page|expire_page|caches_action|expire_action|\" +\n        \"cache|expire_fragment|expire_cache_for|observe|cache_sweeper|\" +\n        \"has_many|has_one|belongs_to|has_and_belongs_to_many\").split(\"|\")\n    );\n\n    var keywords = lang.arrayToMap(\n        (\"alias|and|BEGIN|begin|break|case|class|def|defined|do|else|elsif|END|end|ensure|\" +\n        \"__FILE__|finally|for|gem|if|in|__LINE__|module|next|not|or|private|protected|public|\" + \n        \"redo|rescue|retry|return|super|then|undef|unless|until|when|while|yield\").split(\"|\")\n    );\n\n    var buildinConstants = lang.arrayToMap(\n        (\"true|TRUE|false|FALSE|nil|NIL|ARGF|ARGV|DATA|ENV|RUBY_PLATFORM|RUBY_RELEASE_DATE|\" +\n        \"RUBY_VERSION|STDERR|STDIN|STDOUT|TOPLEVEL_BINDING\").split(\"|\")\n    );\n\n    var builtinVariables = lang.arrayToMap(\n        (\"\\$DEBUG|\\$defout|\\$FILENAME|\\$LOAD_PATH|\\$SAFE|\\$stdin|\\$stdout|\\$stderr|\\$VERBOSE|\" +\n        \"$!|root_url|flash|session|cookies|params|request|response|logger\").split(\"|\")\n    );\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \"#.*$\"\n            }, {\n                token : \"comment\", // multi line comment\n                merge : true,\n                regex : \"^\\=begin$\",\n                next : \"comment\"\n            }, {\n                token : \"string.regexp\",\n                regex : \"[/](?:(?:\\\\[(?:\\\\\\\\]|[^\\\\]])+\\\\])|(?:\\\\\\\\/|[^\\\\]/]))*[/]\\\\w*\\\\s*(?=[).,;]|$)\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"string\", // backtick string\n                regex : \"[`](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[`]\"\n            }, {\n                token : \"text\", // namespaces aren't symbols\n                regex : \"::\"\n            }, {\n                token : \"variable.instancce\", // instance variable\n                regex : \"@{1,2}(?:[a-zA-Z_]|\\d)+\"\n            }, {\n                token : \"variable.class\", // class name\n                regex : \"[A-Z](?:[a-zA-Z_]|\\d)+\"\n            }, {\n                token : \"string\", // symbol\n                regex : \"[:](?:[A-Za-z_]|[@$](?=[a-zA-Z0-9_]))[a-zA-Z0-9_]*[!=?]?\"\n           }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0[xX][0-9a-fA-F](?:[0-9a-fA-F]|_(?=[0-9a-fA-F]))*\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d(?:\\\\d|_(?=\\\\d))*(?:(?:\\\\.\\\\d(?:\\\\d|_(?=\\\\d))*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n                token : \"constant.language.boolean\",\n                regex : \"(?:true|false)\\\\b\"\n            }, {\n                token : function(value) {\n                    if (value == \"self\")\n                        return \"variable.language\";\n                    else if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (buildinConstants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else if (builtinVariables.hasOwnProperty(value))\n                        return \"variable.language\";\n                    else if (builtinFunctions.hasOwnProperty(value))\n                        return \"support.function\";\n                    else if (value == \"debugger\")\n                        return \"invalid.deprecated\";\n                    else\n                        return \"identifier\";\n                },\n                // TODO: Unicode escape sequences\n                // TODO: Unicode identifiers\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"!|\\\\$|%|&|\\\\*|\\\\-\\\\-|\\\\-|\\\\+\\\\+|\\\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\\\|\\\\||\\\\?\\\\:|\\\\*=|%=|\\\\+=|\\\\-=|&=|\\\\^=|\\\\b(?:in|instanceof|new|delete|typeof|void)\"\n            }, {\n                token : \"paren.lparen\",\n                regex : \"[[({]\"\n            }, {\n                token : \"paren.rparen\",\n                regex : \"[\\\\])}]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \"^\\=end$\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ]\n    };\n};\n\noop.inherits(RubyHighlightRules, TextHighlightRules);\n\nexports.RubyHighlightRules = RubyHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/ruby_highlight_rules_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Trent Ogren <me AT trentogren DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar RubyMode = require(\"./ruby\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n    \n    name: \"Ruby Tokenizer\",\n    \n    setUp : function() {\n        this.tokenizer = new RubyMode().getTokenizer();\n    },\n\n    \"test: symbol tokenizer\" : function() {\n        // https://gist.github.com/1072693\n        assertValidTokens(this.tokenizer, \"string\",\n          [\":@thing\", \":$thing\", \":_thing\", \":thing\", \":Thing\", \":thing1\", \":thing_a\",\n              \":THING\", \":thing!\", \":thing=\", \":thing?\", \":t?\"]);\n        assertInvalidTokens(this.tokenizer, \"string\",\n          [\":\", \":@\", \":$\", \":1\", \":1thing\", \":th?ing\", \":thi=ng\", \":1thing\",\n            \":th!ing\", \":thing#\"]);\n    },\n\n    \"test: namespaces aren't symbols\" : function() {\n        var line = \"Namespaced::Class\";\n        var tokens = this.tokenizer.getLineTokens(line, \"start\").tokens;\n\n        assert.equal(3, tokens.length);\n        assert.equal(\"variable.class\", tokens[0].type);\n        assert.equal(\"text\", tokens[1].type);\n        assert.equal(\"variable.class\", tokens[2].type);\n    },\n\n    \"test: hex tokenizer\" : function() {\n        assertValidTokens(this.tokenizer, \"constant.numeric\",\n            [\"0x9a\", \"0XA1\", \"0x9_a\"]);\n        assertInvalidTokens(this.tokenizer, \"constant.numeric\",\n            [\"0x\", \"0x_9a\", \"0x9a_\"]);\n    },\n\n    \"test: float tokenizer\" : function() {\n        assertValidTokens(this.tokenizer, \"constant.numeric\",\n            [\"1\", \"+1\", \"-1\", \"12_345\", \"0.000_1\"]);\n        assertInvalidTokens(this.tokenizer, \"constant.numeric\",\n            [\"_\", \"_1\", \"1_\", \"1_.0\", \"0._1\"]);\n    }\n};\n\nfunction assertValidTokens(tokenizer, tokenType, validTokens) {\n    for (var i = 0, length = validTokens.length; i < length; i++) {\n        var validToken = validTokens[i],\n            tokens = tokenizer.getLineTokens(validToken, \"start\").tokens;\n        assert.equal(tokens[0].value, validToken,\n          '\"' + validToken + '\" should be one token');\n        assert.equal(tokens[0].type, tokenType,\n          '\"' + validToken + '\" should be a \"' + tokenType + '\" token');\n    }\n}\n\nfunction assertInvalidTokens(tokenizer, tokenType, invalidTokens) {\n    for (var i = 0, length = invalidTokens.length; i < length; i++) {\n        var invalidToken = invalidTokens[i],\n            tokens = tokenizer.getLineTokens(invalidToken, \"start\").tokens;\n        assert.ok(tokens[0].type !== tokenType || tokens[0].value !== invalidToken,\n          '\"' + invalidToken + '\" is not a valid \"' + tokenType + '\"');\n    }\n}\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/scad.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Gastón Kleiman <gaston.kleiman AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar scadHighlightRules = require(\"./scad_highlight_rules\").scadHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar Range = require(\"../range\").Range;\nvar CstyleBehaviour = require(\"./behaviour/cstyle\").CstyleBehaviour;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new scadHighlightRules().getRules());\n    this.$outdent = new MatchingBraceOutdent();\n    this.$behaviour = new CstyleBehaviour();\n    this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        var outdent = true;\n        var re = /^(\\s*)\\/\\//;\n\n        for (var i=startRow; i<= endRow; i++) {\n            if (!re.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        if (outdent) {\n            var deleteRange = new Range(0, 0, 0, 0);\n            for (var i=startRow; i<= endRow; i++)\n            {\n                var line = doc.getLine(i);\n                var m = line.match(re);\n                deleteRange.start.row = i;\n                deleteRange.end.row = i;\n                deleteRange.end.column = m[0].length;\n                doc.replace(deleteRange, m[1]);\n            }\n        }\n        else {\n            doc.indentRows(startRow, endRow, \"//\");\n        }\n    };\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n        var endState = tokenizedLine.state;\n\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n\n        if (state == \"start\") {\n            var match = line.match(/^.*[\\{\\(\\[]\\s*$/);\n            if (match) {\n                indent += tab;\n            }\n        } else if (state == \"doc-start\") {\n            if (endState == \"start\") {\n                return \"\";\n            }\n            var match = line.match(/^\\s*(\\/?)\\*/);\n            if (match) {\n                if (match[1]) {\n                    indent += \" \";\n                }\n                indent += \"* \";\n            }\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/scad_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Gastón Kleiman <gaston.kleiman AT gmail DOT com>\n *\n * Based on Bespin's C/C++ Syntax Plugin by Marc McIntyre.\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar DocCommentHighlightRules = require(\"./doc_comment_highlight_rules\").DocCommentHighlightRules;\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar scadHighlightRules = function() {\n\n    var keywords = lang.arrayToMap(\n        (\"module|if|else|for\").split(\"|\")\n    );\n\n    var buildinConstants = lang.arrayToMap(\n        (\"NULL\").split(\"|\")\n    );\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \"\\\\/\\\\/.*$\"\n            },\n            DocCommentHighlightRules.getStartRule(\"start\"),\n            {\n                token : \"comment\", // multi line comment\n                merge : true,\n                regex : \"\\\\/\\\\*\",\n                next : \"comment\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // multi line string start\n                regex : '[\"].*\\\\\\\\$',\n                next : \"qqstring\"\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"string\", // multi line string start\n                regex : \"['].*\\\\\\\\$\",\n                next : \"qstring\"\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n              token : \"constant\", // <CONSTANT>\n              regex : \"<[a-zA-Z0-9.]+>\"\n            }, {\n              token : \"keyword\", // pre-compiler directivs\n              regex : \"(?:use|include)\"\n          }, {\n                token : function(value) {\n                    if (value == \"this\")\n                        return \"variable.language\";\n                    else if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (buildinConstants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else\n                        return \"identifier\";\n                },\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"!|\\\\$|%|&|\\\\*|\\\\-\\\\-|\\\\-|\\\\+\\\\+|\\\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\\\|\\\\||\\\\?\\\\:|\\\\*=|%=|\\\\+=|\\\\-=|&=|\\\\^=|\\\\b(?:in|new|delete|typeof|void)\"\n            }, {\n                token : \"paren.lparen\",\n                regex : \"[[({]\"\n            }, {\n                token : \"paren.rparen\",\n                regex : \"[\\\\])}]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ],\n        \"qqstring\" : [\n            {\n                token : \"string\",\n                regex : '(?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?\"',\n                next : \"start\"\n            }, {\n                token : \"string\",\n                merge : true,\n                regex : '.+'\n            }\n        ],\n        \"qstring\" : [\n            {\n                token : \"string\",\n                regex : \"(?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?'\",\n                next : \"start\"\n            }, {\n                token : \"string\",\n                merge : true,\n                regex : '.+'\n            }\n        ]\n    };\n    \n    this.embedRules(DocCommentHighlightRules, \"doc-\",\n        [ DocCommentHighlightRules.getEndRule(\"start\") ]);\n};\n\noop.inherits(scadHighlightRules, TextHighlightRules);\n\nexports.scadHighlightRules = scadHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/scala.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar JavaScriptMode = require(\"./javascript\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar ScalaHighlightRules = require(\"./scala_highlight_rules\").ScalaHighlightRules;\n\nvar Mode = function() {\n    JavaScriptMode.call(this);\n    \n    this.$tokenizer = new Tokenizer(new ScalaHighlightRules().getRules());\n};\noop.inherits(Mode, JavaScriptMode);\n\n(function() {\n\n    this.createWorker = function(session) {\n        return null;\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/scala_highlight_rules.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar DocCommentHighlightRules = require(\"./doc_comment_highlight_rules\").DocCommentHighlightRules;\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar ScalaHighlightRules = function() {\n\n    // taken from http://download.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html\n    var keywords = lang.arrayToMap(\n        (\n            \"case|default|do|else|for|if|match|while|throw|return|try|catch|finally|yield|\" +\n            \"abstract|class|def|extends|final|forSome|implicit|implicits|import|lazy|new|object|\" +\n            \"override|package|private|protected|sealed|super|this|trait|type|val|var|with\"\n        ).split(\"|\")\n    );\n\n    var buildinConstants = lang.arrayToMap(\n        (\"true|false\").split(\"|\")\n    );\n    \n    var langClasses = lang.arrayToMap(\n        (\"AbstractMethodError|AssertionError|ClassCircularityError|\"+\n        \"ClassFormatError|Deprecated|EnumConstantNotPresentException|\"+\n        \"ExceptionInInitializerError|IllegalAccessError|\"+\n        \"IllegalThreadStateException|InstantiationError|InternalError|\"+\n\n        \"NegativeArraySizeException|NoSuchFieldError|Override|Process|\"+\n        \"ProcessBuilder|SecurityManager|StringIndexOutOfBoundsException|\"+\n        \"SuppressWarnings|TypeNotPresentException|UnknownError|\"+\n        \"UnsatisfiedLinkError|UnsupportedClassVersionError|VerifyError|\"+\n        \"InstantiationException|IndexOutOfBoundsException|\"+\n        \"ArrayIndexOutOfBoundsException|CloneNotSupportedException|\"+\n        \"NoSuchFieldException|IllegalArgumentException|NumberFormatException|\"+\n        \"SecurityException|Void|InheritableThreadLocal|IllegalStateException|\"+\n        \"InterruptedException|NoSuchMethodException|IllegalAccessException|\"+\n        \"UnsupportedOperationException|Enum|StrictMath|Package|Compiler|\"+\n        \"Readable|Runtime|StringBuilder|Math|IncompatibleClassChangeError|\"+\n        \"NoSuchMethodError|ThreadLocal|RuntimePermission|ArithmeticException|\"+\n        \"NullPointerException|Long|Integer|Short|Byte|Double|Number|Float|\"+\n        \"Character|Boolean|StackTraceElement|Appendable|StringBuffer|\"+\n        \"Iterable|ThreadGroup|Runnable|Thread|IllegalMonitorStateException|\"+\n        \"StackOverflowError|OutOfMemoryError|VirtualMachineError|\"+\n        \"ArrayStoreException|ClassCastException|LinkageError|\"+\n        \"NoClassDefFoundError|ClassNotFoundException|RuntimeException|\"+\n        \"Exception|ThreadDeath|Error|Throwable|System|ClassLoader|\"+\n        \"Cloneable|Class|CharSequence|Comparable|String|Object|\" +\n        \"Unit|Any|AnyVal|AnyRef|Null|ScalaObject|Singleton|Seq|Iterable|List|\" +\n        \"Option|Array|Char|Byte|Short|Int|Long|Nothing\"\n        \n        ).split(\"|\")\n    );\n    \n    var importClasses = lang.arrayToMap(\n        (\"\").split(\"|\")\n    );\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \"\\\\/\\\\/.*$\"\n            },\n            DocCommentHighlightRules.getStartRule(\"doc-start\"),\n            {\n                token : \"comment\", // multi line comment\n                merge : true,\n                regex : \"\\\\/\\\\*\",\n                next : \"comment\"\n            }, {\n                token : \"string.regexp\",\n                regex : \"[/](?:(?:\\\\[(?:\\\\\\\\]|[^\\\\]])+\\\\])|(?:\\\\\\\\/|[^\\\\]/]))*[/]\\\\w*\\\\s*(?=[).,;]|$)\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"constant.numeric\", // hex\n                regex : \"0[xX][0-9a-fA-F]+\\\\b\"\n            }, {\n                token : \"constant.numeric\", // float\n                regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n            }, {\n                token : \"constant.language.boolean\",\n                regex : \"(?:true|false)\\\\b\"\n            }, {\n                token : function(value) {\n                    if (value == \"this\")\n                        return \"variable.language\";\n                    else if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (langClasses.hasOwnProperty(value))\n                        return \"support.function\";\n                    else if (importClasses.hasOwnProperty(value))\n                        return \"support.function\";\n                    else if (buildinConstants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else\n                        return \"identifier\";\n                },\n                // TODO: Unicode escape sequences\n                // TODO: Unicode identifiers\n                regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"!|\\\\$|%|&|\\\\*|\\\\-\\\\-|\\\\-|\\\\+\\\\+|\\\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\\\|\\\\||\\\\?\\\\:|\\\\*=|%=|\\\\+=|\\\\-=|&=|\\\\^=|\\\\b(?:in|instanceof|new|delete|typeof|void)\"\n            }, {\n                token : \"paren.lparen\",\n                regex : \"[[({]\"\n            }, {\n                token : \"paren.rparen\",\n                regex : \"[\\\\])}]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ]\n    };\n    \n    this.embedRules(DocCommentHighlightRules, \"doc-\",\n        [ DocCommentHighlightRules.getEndRule(\"start\") ]);\n};\n\noop.inherits(ScalaHighlightRules, TextHighlightRules);\n\nexports.ScalaHighlightRules = ScalaHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/scss.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar ScssHighlightRules = require(\"./scss_highlight_rules\").ScssHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new ScssHighlightRules().getRules(), \"i\");\n    this.$outdent = new MatchingBraceOutdent();\n    this.foldingRules = new CStyleFoldMode();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n    \n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        // ignore braces in comments\n        var tokens = this.$tokenizer.getLineTokens(line, state).tokens;\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n\n        var match = line.match(/^.*\\{\\s*$/);\n        if (match) {\n            indent += tab;\n        }\n\n        return indent;\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/scss_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar ScssHighlightRules = function() {\n    \n    var properties = lang.arrayToMap( (function () {\n\n        var browserPrefix = (\"-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-\").split(\"|\");\n        \n        var prefixProperties = (\"appearance|background-clip|background-inline-policy|background-origin|\" + \n             \"background-size|binding|border-bottom-colors|border-left-colors|\" + \n             \"border-right-colors|border-top-colors|border-end|border-end-color|\" + \n             \"border-end-style|border-end-width|border-image|border-start|\" + \n             \"border-start-color|border-start-style|border-start-width|box-align|\" + \n             \"box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|\" + \n             \"box-pack|box-sizing|column-count|column-gap|column-width|column-rule|\" + \n             \"column-rule-width|column-rule-style|column-rule-color|float-edge|\" + \n             \"font-feature-settings|font-language-override|force-broken-image-icon|\" + \n             \"image-region|margin-end|margin-start|opacity|outline|outline-color|\" + \n             \"outline-offset|outline-radius|outline-radius-bottomleft|\" + \n             \"outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|\" + \n             \"outline-style|outline-width|padding-end|padding-start|stack-sizing|\" + \n             \"tab-size|text-blink|text-decoration-color|text-decoration-line|\" + \n             \"text-decoration-style|transform|transform-origin|transition|\" + \n             \"transition-delay|transition-duration|transition-property|\" + \n             \"transition-timing-function|user-focus|user-input|user-modify|user-select|\" +\n             \"window-shadow|border-radius\").split(\"|\");\n        \n        var properties = (\"azimuth|background-attachment|background-color|background-image|\" +\n            \"background-position|background-repeat|background|border-bottom-color|\" +\n            \"border-bottom-style|border-bottom-width|border-bottom|border-collapse|\" +\n            \"border-color|border-left-color|border-left-style|border-left-width|\" +\n            \"border-left|border-right-color|border-right-style|border-right-width|\" +\n            \"border-right|border-spacing|border-style|border-top-color|\" +\n            \"border-top-style|border-top-width|border-top|border-width|border|\" +\n            \"bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|\" +\n            \"counter-reset|cue-after|cue-before|cue|cursor|direction|display|\" +\n            \"elevation|empty-cells|float|font-family|font-size-adjust|font-size|\" +\n            \"font-stretch|font-style|font-variant|font-weight|font|height|left|\" +\n            \"letter-spacing|line-height|list-style-image|list-style-position|\" +\n            \"list-style-type|list-style|margin-bottom|margin-left|margin-right|\" +\n            \"margin-top|marker-offset|margin|marks|max-height|max-width|min-height|\" +\n            \"min-width|opacity|orphans|outline-color|\" +\n            \"outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|\" +\n            \"padding-left|padding-right|padding-top|padding|page-break-after|\" +\n            \"page-break-before|page-break-inside|page|pause-after|pause-before|\" +\n            \"pause|pitch-range|pitch|play-during|position|quotes|richness|right|\" +\n            \"size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|\" +\n            \"stress|table-layout|text-align|text-decoration|text-indent|\" +\n            \"text-shadow|text-transform|top|unicode-bidi|vertical-align|\" +\n            \"visibility|voice-family|volume|white-space|widows|width|word-spacing|\" +\n            \"z-index\").split(\"|\");\n          \n        //The return array     \n        var ret = [];\n        \n        //All prefixProperties will get the browserPrefix in\n        //the begning by join the prefixProperties array with the value of browserPrefix\n        for (var i=0, ln=browserPrefix.length; i<ln; i++) {\n            Array.prototype.push.apply(\n                ret,\n                (( browserPrefix[i] + prefixProperties.join(\"|\" + browserPrefix[i]) ).split(\"|\"))\n            );\n        }\n        \n        //Add also prefixProperties and properties without any browser prefix\n        Array.prototype.push.apply(ret, prefixProperties);\n        Array.prototype.push.apply(ret, properties);\n        \n        return ret;\n        \n    })() );\n    \n\n\n    var functions = lang.arrayToMap(\n        (\"hsl|hsla|rgb|rgba|url|attr|counter|counters|abs|adjust_color|adjust_hue|\" +\n         \"alpha|join|blue|ceil|change_color|comparable|complement|darken|desaturate|\" + \n         \"floor|grayscale|green|hue|if|invert|join|length|lighten|lightness|mix|\" + \n         \"nth|opacify|opacity|percentage|quote|red|round|saturate|saturation|\" +\n         \"scale_color|transparentize|type_of|unit|unitless|unqoute\").split(\"|\")\n    );\n\n    var constants = lang.arrayToMap(\n        (\"absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|\" +\n        \"block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|\" +\n        \"char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|\" +\n        \"decimal-leading-zero|decimal|default|disabled|disc|\" +\n        \"distribute-all-lines|distribute-letter|distribute-space|\" +\n        \"distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|\" +\n        \"hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|\" +\n        \"ideograph-alpha|ideograph-numeric|ideograph-parenthesis|\" +\n        \"ideograph-space|inactive|inherit|inline-block|inline|inset|inside|\" +\n        \"inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|\" +\n        \"keep-all|left|lighter|line-edge|line-through|line|list-item|loose|\" +\n        \"lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|\" +\n        \"medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|\" +\n        \"nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|\" +\n        \"overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|\" +\n        \"ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|\" +\n        \"solid|square|static|strict|super|sw-resize|table-footer-group|\" +\n        \"table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|\" +\n        \"transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|\" +\n        \"vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|\" +\n        \"zero\").split(\"|\")\n    );\n\n    var colors = lang.arrayToMap(\n        (\"aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|\" +\n        \"purple|red|silver|teal|white|yellow\").split(\"|\")\n    );\n    \n    var keywords = lang.arrayToMap(\n        (\"@mixin|@extend|@include|@import|@media|@debug|@warn|@if|@for|@each|@while|@else|@font-face|@-webkit-keyframes|if|and|!default|module|def|end|declare\").split(\"|\")\n    )\n    \n    var tags = lang.arrayToMap(\n        (\"a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdo|\" + \n         \"big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|\" + \n         \"command|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|\" + \n         \"figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|\" + \n         \"header|hgroup|hr|html|i|iframe|img|input|ins|keygen|kbd|label|legend|li|\" + \n         \"link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|\" + \n         \"option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|\" + \n         \"small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|\" + \n         \"textarea|tfoot|th|thead|time|title|tr|tt|u|ul|var|video|wbr|xmp\").split(\"|\")\n    );\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    var numRe = \"\\\\-?(?:(?:[0-9]+)|(?:[0-9]*\\\\.[0-9]+))\";\n\n    // regexp must not have capturing parentheses. Use (?:) instead.\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [\n            {\n                token : \"comment\",\n                regex : \"\\\\/\\\\/.*$\"\n            },\n            {\n                token : \"comment\", // multi line comment\n                merge : true,\n                regex : \"\\\\/\\\\*\",\n                next : \"comment\"\n            }, {\n                token : \"string\", // single line\n                regex : '[\"](?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?[\"]'\n            }, {\n                token : \"string\", // multi line string start\n                merge : true,\n                regex : '[\"].*\\\\\\\\$',\n                next : \"qqstring\"\n            }, {\n                token : \"string\", // single line\n                regex : \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"\n            }, {\n                token : \"string\", // multi line string start\n                merge : true,\n                regex : \"['].*\\\\\\\\$\",\n                next : \"qstring\"\n            }, {\n                token : \"constant.numeric\",\n                regex : numRe + \"(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)\"\n            }, {\n                token : \"constant.numeric\", // hex6 color\n                regex : \"#[a-f0-9]{6}\"\n            }, {\n                token : \"constant.numeric\", // hex3 color\n                regex : \"#[a-f0-9]{3}\"\n            }, {\n                token : \"constant.numeric\",\n                regex : numRe\n            }, {\n                token : function(value) {\n                    if (properties.hasOwnProperty(value.toLowerCase()))\n                        return \"support.type\";\n                    if (keywords.hasOwnProperty(value))\n                        return \"keyword\";\n                    else if (constants.hasOwnProperty(value))\n                        return \"constant.language\";\n                    else if (functions.hasOwnProperty(value))\n                        return \"support.function\";\n                    else if (colors.hasOwnProperty(value.toLowerCase()))\n                        return \"support.constant.color\";\n                    else if (tags.hasOwnProperty(value.toLowerCase()))\n                        return \"variable.language\";\n                    else\n                        return \"text\";\n                },\n                regex : \"\\\\-?[@a-z_][@a-z0-9_\\\\-]*\"\n            }, {\n                token : \"variable\",\n                regex : \"[a-z_\\\\-$][a-z0-9_\\\\-$]*\\\\b\"\n            }, {\n                token: \"variable.language\",\n                regex: \"#[a-z0-9-_]+\"\n            }, {\n                token: \"variable.language\",\n                regex: \"\\\\.[a-z0-9-_]+\"\n            }, {\n                token: \"variable.language\",\n                regex: \":[a-z0-9-_]+\"\n            }, {\n                token: \"constant\",\n                regex: \"[a-z0-9-_]+\"\n            }, {\n                token : \"keyword.operator\",\n                regex : \"<|>|<=|>=|==|!=|-|%|#|\\\\+|\\\\$|\\\\+|\\\\*\"\n            }, {\n                token : \"paren.lparen\",\n                regex : \"[[({]\"\n            }, {\n                token : \"paren.rparen\",\n                regex : \"[\\\\])}]\"\n            }, {\n                token : \"text\",\n                regex : \"\\\\s+\"\n            }\n        ],\n        \"comment\" : [\n            {\n                token : \"comment\", // closing comment\n                regex : \".*?\\\\*\\\\/\",\n                next : \"start\"\n            }, {\n                token : \"comment\", // comment spanning whole line\n                merge : true,\n                regex : \".+\"\n            }\n        ],\n        \"qqstring\" : [\n            {\n                token : \"string\",\n                regex : '(?:(?:\\\\\\\\.)|(?:[^\"\\\\\\\\]))*?\"',\n                next : \"start\"\n            }, {\n                token : \"string\",\n                merge : true,\n                regex : '.+'\n            }\n        ],\n        \"qstring\" : [\n            {\n                token : \"string\",\n                regex : \"(?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?'\",\n                next : \"start\"\n            }, {\n                token : \"string\",\n                merge : true,\n                regex : '.+'\n            }\n        ]\n    };\n};\n\noop.inherits(ScssHighlightRules, TextHighlightRules);\n\nexports.ScssHighlightRules = ScssHighlightRules;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/sh.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n* Version: MPL 1.1/GPL 2.0/LGPL 2.1\n*\n* The contents of this file are subject to the Mozilla Public License Version\n* 1.1 (the \"License\"); you may not use this file except in compliance with\n* the License. You may obtain a copy of the License at\n* http://www.mozilla.org/MPL/\n*\n* Software distributed under the License is distributed on an \"AS IS\" basis,\n* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n* for the specific language governing rights and limitations under the\n* License.\n*\n* The Original Code is Ajax.org Code Editor (ACE).\n*\n* The Initial Developer of the Original Code is\n* Ajax.org B.V.\n* Portions created by the Initial Developer are Copyright (C) 2010\n* the Initial Developer. All Rights Reserved.\n*\n* Contributor(s):\n*      Rich Healey <richo AT psych0tik DOT net>\n*\n* Alternatively, the contents of this file may be used under the terms of\n* either the GNU General Public License Version 2 or later (the \"GPL\"), or\n* the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n* in which case the provisions of the GPL or the LGPL are applicable instead\n* of those above. If you wish to allow use of your version of this file only\n* under the terms of either the GPL or the LGPL, and not to allow others to\n* use your version of this file under the terms of the MPL, indicate your\n* decision by deleting the provisions above and replace them with the notice\n* and other provisions required by the GPL or the LGPL. If you do not delete\n* the provisions above, a recipient may use your version of this file under\n* the terms of any one of the MPL, the GPL or the LGPL.\n*\n* ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar ShHighlightRules = require(\"./sh_highlight_rules\").ShHighlightRules;\nvar Range = require(\"../range\").Range;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new ShHighlightRules().getRules());\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        var outdent = true;\n        var re = /^(\\s*)#/;\n\n        for (var i=startRow; i<= endRow; i++) {\n            if (!re.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        if (outdent) {\n            var deleteRange = new Range(0, 0, 0, 0);\n            for (var i=startRow; i<= endRow; i++)\n            {\n                var line = doc.getLine(i);\n                var m = line.match(re);\n                deleteRange.start.row = i;\n                deleteRange.end.row = i;\n                deleteRange.end.column = m[0].length;\n                doc.replace(deleteRange, m[1]);\n            }\n        }\n        else {\n            doc.indentRows(startRow, endRow, \"#\");\n        }\n    };\n\n    this.getNextLineIndent = function(state, line, tab) {\n        var indent = this.$getIndent(line);\n\n        var tokenizedLine = this.$tokenizer.getLineTokens(line, state);\n        var tokens = tokenizedLine.tokens;\n\n        if (tokens.length && tokens[tokens.length-1].type == \"comment\") {\n            return indent;\n        }\n\n        if (state == \"start\") {\n            var match = line.match(/^.*[\\{\\(\\[\\:]\\s*$/);\n            if (match) {\n                indent += tab;\n            }\n        }\n\n        return indent;\n    };\n\n    var outdents = {\n        \"pass\": 1,\n        \"return\": 1,\n        \"raise\": 1,\n        \"break\": 1,\n        \"continue\": 1\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        if (input !== \"\\r\\n\" && input !== \"\\r\" && input !== \"\\n\")\n            return false;\n\n        var tokens = this.$tokenizer.getLineTokens(line.trim(), state).tokens;\n\n        if (!tokens)\n            return false;\n\n        // ignore trailing comments\n        do {\n            var last = tokens.pop();\n        } while (last && (last.type == \"comment\" || (last.type == \"text\" && last.value.match(/^\\s+$/))));\n\n        if (!last)\n            return false;\n\n        return (last.type == \"keyword\" && outdents[last.value]);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        // outdenting in sh is slightly different because it always applies\n        // to the next line and only of a new line is inserted\n\n        row += 1;\n        var indent = this.$getIndent(doc.getLine(row));\n        var tab = doc.getTabString();\n        if (indent.slice(-tab.length) == tab)\n            doc.remove(new Range(row, indent.length-tab.length, row, indent.length));\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/sh_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Rich Healey <richo AT psych0tik DOT net>\n *      Javier Perez-Griffo <javier AT besol DOT es>\n *      James Tan   <jamestyj AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK *****\n */\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar ShHighlightRules = function() {\n\n    var reservedKeywords = lang.arrayToMap(\n        ('!|{|}|case|do|done|elif|else|'+\n        'esac|fi|for|if|in|then|until|while|'+\n        '&|;|export|local|read|typeset|unset|'+\n        'elif|select|set'\n        ).split('|')\n    );\n\n    var languageConstructs = lang.arrayToMap(\n        ('[|]|alias|bg|bind|break|builtin|'+\n         'cd|command|compgen|complete|continue|'+\n         'dirs|disown|echo|enable|eval|exec|'+\n         'exit|fc|fg|getopts|hash|help|history|'+\n         'jobs|kill|let|logout|popd|printf|pushd|'+\n         'pwd|return|set|shift|shopt|source|'+\n         'suspend|test|times|trap|type|ulimit|'+\n         'umask|unalias|wait'\n         ).split('|')\n    );\n\n    var integer = \"(?:(?:[1-9]\\\\d*)|(?:0))\";\n    // var integer = \"(?:\" + decimalInteger + \")\";\n\n    var fraction = \"(?:\\\\.\\\\d+)\";\n    var intPart = \"(?:\\\\d+)\";\n    var pointFloat = \"(?:(?:\" + intPart + \"?\" + fraction + \")|(?:\" + intPart + \"\\\\.))\";\n    var exponentFloat = \"(?:(?:\" + pointFloat + \"|\" +  intPart + \")\" + \")\";\n    var floatNumber = \"(?:\" + exponentFloat + \"|\" + pointFloat + \")\";\n    var fileDescriptor = \"(?:&\" + intPart + \")\";\n\n    var variableName = \"[a-zA-Z][a-zA-Z0-9_]*\";\n    var variable = \"(?:(?:\\\\$\" + variableName + \")|(?:\" + variableName + \"=))\";\n\n    var builtinVariable = \"(?:\\\\$(?:SHLVL|\\\\$|\\\\!|\\\\?))\";\n\n    var func = \"(?:\" + variableName + \"\\\\s*\\\\(\\\\))\";\n\n    this.$rules = {\n        \"start\" : [ {\n            token : \"comment\",\n            regex : \"#.*$\"\n        }, {\n            token : \"string\",           // \" string\n            regex : '\"(?:[^\\\\\\\\]|\\\\\\\\.)*?\"'\n        }, {\n            token : \"variable.language\",\n            regex : builtinVariable\n        }, {\n            token : \"variable\",\n            regex : variable\n        }, {\n            token : \"support.function\",\n            regex : func,\n        }, {\n            token : \"support.function\",\n            regex : fileDescriptor\n        }, {\n            token : \"string\",           // ' string\n            regex : \"'(?:[^\\\\\\\\]|\\\\\\\\.)*?'\"\n        }, {\n            token : \"constant.numeric\", // float\n            regex : floatNumber\n        }, {\n            token : \"constant.numeric\", // integer\n            regex : integer + \"\\\\b\"\n        }, {\n            token : function(value) {\n                if (reservedKeywords.hasOwnProperty(value))\n                    return \"keyword\";\n                else if (languageConstructs.hasOwnProperty(value))\n                    return \"constant.language\";\n                else if (value == \"debugger\")\n                    return \"invalid.deprecated\";\n                else\n                    return \"identifier\";\n            },\n            regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n        }, {\n            token : \"keyword.operator\",\n            regex : \"\\\\+|\\\\-|\\\\*|\\\\*\\\\*|\\\\/|\\\\/\\\\/|~|<|>|<=|=>|=|!=\"\n        }, {\n            token : \"lparen.paren\",\n            regex : \"[\\\\[\\\\(\\\\{]\"\n        }, {\n            token : \"paren.rparen\",\n            regex : \"[\\\\]\\\\)\\\\}]\"\n        }, {\n            token : \"text\",\n            regex : \"\\\\s+\"\n        } ]\n    };\n};\n\noop.inherits(ShHighlightRules, TextHighlightRules);\n\nexports.ShHighlightRules = ShHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/sql.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n* The Original Code is Ajax.org Code Editor (ACE).\n*\n* Contributor(s):\n*      Jonathan Camile <jonathan.camile AT gmail DOT com>\n*\n* Alternatively, the contents of this file may be used under the terms of\n* either the GNU General Public License Version 2 or later (the \"GPL\"), or\n* the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n* in which case the provisions of the GPL or the LGPL are applicable instead\n* of those above. If you wish to allow use of your version of this file only\n* under the terms of either the GPL or the LGPL, and not to allow others to\n* use your version of this file under the terms of the MPL, indicate your\n* decision by deleting the provisions above and replace them with the notice\n* and other provisions required by the GPL or the LGPL. If you do not delete\n* the provisions above, a recipient may use your version of this file under\n* the terms of any one of the MPL, the GPL or the LGPL.\n*\n* ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar SqlHighlightRules = require(\"./sql_highlight_rules\").SqlHighlightRules;\nvar Range = require(\"../range\").Range;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new SqlHighlightRules().getRules());\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        var outdent = true;\n        var outentedRows = [];\n        var re = /^(\\s*)--/;\n\n        for (var i=startRow; i<= endRow; i++) {\n            if (!re.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        if (outdent) {\n            var deleteRange = new Range(0, 0, 0, 0);\n            for (var i=startRow; i<= endRow; i++)\n            {\n                var line = doc.getLine(i);\n                var m = line.match(re);\n                deleteRange.start.row = i;\n                deleteRange.end.row = i;\n                deleteRange.end.column = m[0].length;\n                doc.replace(deleteRange, m[1]);\n            }\n        }\n        else {\n            doc.indentRows(startRow, endRow, \"--\");\n        }\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/sql_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * Contributor(s):\n *      Jonathan Camile <jonathan.camile AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar SqlHighlightRules = function() {\n\n    var keywords = lang.arrayToMap(\n        (\"select|from|where|and|or|group|by|order|limit|offset|having|as|case|\" +\n        \"when|else|end|type|left|right|join|on|outer|desc|asc\").split(\"|\")\n    );\n\n    var builtinConstants = lang.arrayToMap(\n        (\"true|false|null\").split(\"|\")\n    );\n\n    var builtinFunctions = lang.arrayToMap(\n        (\"count|min|max|avg|sum|rank|now|coalesce\").split(\"|\")\n    );\n\n    this.$rules = {\n        \"start\" : [ {\n            token : \"comment\",\n            regex : \"--.*$\"\n        }, {\n            token : \"string\",           // \" string\n            regex : '\".*\"'\n        }, {\n            token : \"string\",           // ' string\n            regex : \"'.*'\"\n        }, {\n            token : \"constant.numeric\", // float\n            regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n        }, {\n            token : function(value) {\n                value = value.toLowerCase();\n                if (keywords.hasOwnProperty(value))\n                    return \"keyword\";\n                else if (builtinConstants.hasOwnProperty(value))\n                    return \"constant.language\";\n                else if (builtinFunctions.hasOwnProperty(value))\n                    return \"support.function\";\n                else\n                    return \"identifier\";\n            },\n            regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n        }, {\n            token : \"keyword.operator\",\n            regex : \"\\\\+|\\\\-|\\\\/|\\\\/\\\\/|%|<@>|@>|<@|&|\\\\^|~|<|>|<=|=>|==|!=|<>|=\"\n        }, {\n            token : \"lparen.paren\",\n            regex : \"[\\\\(]\"\n        }, {\n            token : \"paren.rparen\",\n            regex : \"[\\\\)]\"\n        }, {\n            token : \"text\",\n            regex : \"\\\\s+\"\n        } ]\n    };\n};\n\noop.inherits(SqlHighlightRules, TextHighlightRules);\n\nexports.SqlHighlightRules = SqlHighlightRules;\n});\n\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/svg.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar XmlMode = require(\"./xml\").Mode;\nvar JavaScriptMode = require(\"./javascript\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar SvgHighlightRules = require(\"./svg_highlight_rules\").SvgHighlightRules;\nvar MixedFoldMode = require(\"./folding/mixed\").FoldMode;\nvar XmlFoldMode = require(\"./folding/xml\").FoldMode;\nvar CStyleFoldMode = require(\"./folding/cstyle\").FoldMode;\n\nvar Mode = function() {\n    XmlMode.call(this);\n    \n    this.highlighter = new SvgHighlightRules();\n    this.$tokenizer = new Tokenizer(this.highlighter.getRules());\n    \n    this.$embeds = this.highlighter.getEmbeds();\n    this.createModeDelegates({\n        \"js-\": JavaScriptMode\n    });\n    \n    this.foldingRules = new MixedFoldMode(new XmlFoldMode({}), {\n        \"js-\": new CStyleFoldMode()\n    });\n};\n\noop.inherits(Mode, XmlMode);\n\n(function() {\n\n    this.getNextLineIndent = function(state, line, tab) {\n        return this.$getIndent(line);\n    };\n    \n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/svg_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar JavaScriptHighlightRules = require(\"./javascript_highlight_rules\").JavaScriptHighlightRules;\nvar XmlHighlightRules = require(\"./xml_highlight_rules\").XmlHighlightRules;\nvar xmlUtil = require(\"./xml_util\");\n\nvar SvgHighlightRules = function() {\n    XmlHighlightRules.call(this);\n\n    this.$rules.start.splice(3, 0, {\n        token : \"meta.tag\",\n        regex : \"<(?=\\s*script)\",\n        next : \"script\"\n    });\n    \n    xmlUtil.tag(this.$rules, \"script\", \"js-start\");\n    \n    this.embedRules(JavaScriptHighlightRules, \"js-\", [{\n        token: \"comment\",\n        regex: \"\\\\/\\\\/.*(?=<\\\\/script>)\",\n        next: \"tag\"\n    }, {\n        token: \"meta.tag\",\n        regex: \"<\\\\/(?=script)\",\n        next: \"tag\"\n    }]);\n};\n\noop.inherits(SvgHighlightRules, XmlHighlightRules);\n\nexports.SvgHighlightRules = SvgHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/text.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Mihai Sucan <mihai DOT sucan AT gmail DOT com>\n *      Chris Spencer <chris.ag.spencer AT googlemail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\nvar Behaviour = require(\"./behaviour\").Behaviour;\nvar unicode = require(\"../unicode\");\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new TextHighlightRules().getRules());\n    this.$behaviour = new Behaviour();\n};\n\n(function() {\n\n    this.tokenRe = new RegExp(\"^[\"\n        + unicode.packages.L\n        + unicode.packages.Mn + unicode.packages.Mc\n        + unicode.packages.Nd\n        + unicode.packages.Pc + \"\\\\$_]+\", \"g\"\n    );\n    \n    this.nonTokenRe = new RegExp(\"^(?:[^\"\n        + unicode.packages.L\n        + unicode.packages.Mn + unicode.packages.Mc\n        + unicode.packages.Nd\n        + unicode.packages.Pc + \"\\\\$_]|\\s])+\", \"g\"\n    );\n\n    this.getTokenizer = function() {\n        return this.$tokenizer;\n    };\n\n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n    };\n\n    this.getNextLineIndent = function(state, line, tab) {\n        return \"\";\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return false;\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n    };\n\n    this.$getIndent = function(line) {\n        var match = line.match(/^(\\s+)/);\n        if (match) {\n            return match[1];\n        }\n\n        return \"\";\n    };\n    \n    this.createWorker = function(session) {\n        return null;\n    };\n\n    this.highlightSelection = function(editor) {\n        var session = editor.session;\n        if (!session.$selectionOccurrences)\n            session.$selectionOccurrences = [];\n\n        if (session.$selectionOccurrences.length)\n            this.clearSelectionHighlight(editor);\n\n        var selection = editor.getSelectionRange();\n        if (selection.isEmpty() || selection.isMultiLine())\n            return;\n\n        var startOuter = selection.start.column - 1;\n        var endOuter = selection.end.column + 1;\n        var line = session.getLine(selection.start.row);\n        var lineCols = line.length;\n        var needle = line.substring(Math.max(startOuter, 0),\n                                    Math.min(endOuter, lineCols));\n\n        // Make sure the outer characters are not part of the word.\n        if ((startOuter >= 0 && /^[\\w\\d]/.test(needle)) ||\n            (endOuter <= lineCols && /[\\w\\d]$/.test(needle)))\n            return;\n\n        needle = line.substring(selection.start.column, selection.end.column);\n        if (!/^[\\w\\d]+$/.test(needle))\n            return;\n\n        var cursor = editor.getCursorPosition();\n\n        var newOptions = {\n            wrap: true,\n            wholeWord: true,\n            caseSensitive: true,\n            needle: needle\n        };\n\n        var currentOptions = editor.$search.getOptions();\n        editor.$search.set(newOptions);\n\n        var ranges = editor.$search.findAll(session);\n        ranges.forEach(function(range) {\n            if (!range.contains(cursor.row, cursor.column)) {\n                var marker = session.addMarker(range, \"ace_selected_word\", \"text\");\n                session.$selectionOccurrences.push(marker);\n            }\n        });\n\n        editor.$search.set(currentOptions);\n    };\n\n    this.clearSelectionHighlight = function(editor) {\n        if (!editor.session.$selectionOccurrences)\n            return;\n\n        editor.session.$selectionOccurrences.forEach(function(marker) {\n            editor.session.removeMarker(marker);\n        });\n\n        editor.session.$selectionOccurrences = [];\n    };\n    \n    this.createModeDelegates = function (mapping) {\n        if (!this.$embeds) {\n            return;\n        }\n        this.$modes = {};\n        for (var i = 0; i < this.$embeds.length; i++) {\n            if (mapping[this.$embeds[i]]) {\n                this.$modes[this.$embeds[i]] = new mapping[this.$embeds[i]]();\n            }\n        }\n        \n        var delegations = ['toggleCommentLines', 'getNextLineIndent', 'checkOutdent', 'autoOutdent', 'transformAction'];\n\n        for (var i = 0; i < delegations.length; i++) {\n            (function(scope) {\n              var functionName = delegations[i];\n              var defaultHandler = scope[functionName];\n              scope[delegations[i]] = function() {\n                  return this.$delegator(functionName, arguments, defaultHandler);\n              }\n            } (this));\n        }\n    }\n    \n    this.$delegator = function(method, args, defaultHandler) {\n        var state = args[0];\n        \n        for (var i = 0; i < this.$embeds.length; i++) {\n            if (!this.$modes[this.$embeds[i]]) continue;\n            \n            var split = state.split(this.$embeds[i]);\n            if (!split[0] && split[1]) {\n                args[0] = split[1];\n                var mode = this.$modes[this.$embeds[i]];\n                return mode[method].apply(mode, args);\n            }\n        }\n        var ret = defaultHandler.apply(this, args);\n        return defaultHandler ? ret : undefined;\n    };\n    \n    this.transformAction = function(state, action, editor, session, param) {\n        if (this.$behaviour) {\n            var behaviours = this.$behaviour.getBehaviours();\n            for (var key in behaviours) {\n                if (behaviours[key][action]) {\n                    var ret = behaviours[key][action].apply(this, arguments);\n                    if (ret) {\n                        return ret;\n                    }\n                }\n            }\n        }\n    }\n    \n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/text_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar lang = require(\"../lib/lang\");\n\nvar TextHighlightRules = function() {\n\n    // regexp must not have capturing parentheses\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        \"start\" : [{\n            token : \"empty_line\",\n            regex : '^$'\n        }, {\n            token : \"text\",\n            regex : \".+\"\n        }]\n    };\n};\n\n(function() {\n\n    this.addRules = function(rules, prefix) {\n        for (var key in rules) {\n            var state = rules[key];\n            for (var i=0; i<state.length; i++) {\n                var rule = state[i];\n                if (rule.next) {\n                    rule.next = prefix + rule.next;\n                }\n            }\n            this.$rules[prefix + key] = state;\n        }\n    };\n\n    this.getRules = function() {\n        return this.$rules;\n    };\n    \n    this.embedRules = function (HighlightRules, prefix, escapeRules, states) {\n        var embedRules = new HighlightRules().getRules();\n        if (states) {\n            for (var i = 0; i < states.length; i++) {\n                states[i] = prefix + states[i];\n            }\n        } else {\n            states = [];\n            for (var key in embedRules) {\n                states.push(prefix + key);\n            }\n        }\n        this.addRules(embedRules, prefix);\n        \n        for (var i = 0; i < states.length; i++) {\n            Array.prototype.unshift.apply(this.$rules[states[i]], lang.deepCopy(escapeRules));\n        }\n        \n        if (!this.$embeds) {\n            this.$embeds = [];\n        }\n        this.$embeds.push(prefix);\n    }\n    \n    this.getEmbeds = function() {\n        return this.$embeds;\n    }\n\n}).call(TextHighlightRules.prototype);\n\nexports.TextHighlightRules = TextHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/text_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"../edit_session\").EditSession;\nvar TextMode = require(\"./text\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n    setUp : function() {\n        this.mode = new TextMode();\n    },\n\n    \"test: toggle comment lines should not do anything\" : function() {\n        var session = new EditSession([\"  abc\", \"cde\", \"fg\"]);\n\n        this.mode.toggleCommentLines(\"start\", session, 0, 1);\n        assert.equal([\"  abc\", \"cde\", \"fg\"].join(\"\\n\"), session.toString());\n    },\n\n\n    \"text: lines should not be indented\" : function() {\n        assert.equal(\"\", this.mode.getNextLineIndent(\"start\", \"   abc\", \"  \"));\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/textile.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Kelley van Evert <kelley.vanevert@gmail.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar TextileHighlightRules = require(\"./textile_highlight_rules\").TextileHighlightRules;\nvar MatchingBraceOutdent = require(\"./matching_brace_outdent\").MatchingBraceOutdent;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new TextileHighlightRules().getRules());\n    this.$outdent = new MatchingBraceOutdent();\n};\noop.inherits(Mode, TextMode);\n\n(function() {\n    this.getNextLineIndent = function(state, line, tab) {\n        if (state == \"intag\")\n            return tab;\n        \n        return \"\";\n    };\n\n    this.checkOutdent = function(state, line, input) {\n        return this.$outdent.checkOutdent(line, input);\n    };\n\n    this.autoOutdent = function(state, doc, row) {\n        this.$outdent.autoOutdent(doc, row);\n    };\n    \n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/textile_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Kelley van Evert <kelley.vanevert@gmail.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar TextileHighlightRules = function() {\n    this.$rules = {\n        \"start\" : [\n            {\n                token : function(value) {\n                    if (value.match(/^h\\d$/))\n                        return \"markup.heading.\" + value.charAt(1);\n                    else\n                        return \"markup.heading\";\n                },\n                regex : \"h1|h2|h3|h4|h5|h6|bq|p|bc|pre\",\n                next  : \"blocktag\"\n            },\n            {\n                token : \"keyword\",\n                regex : \"[\\\\*]+|[#]+\"\n            },\n            {\n                token : \"text\",\n                regex : \".+\"\n            }\n        ],\n        \"blocktag\" : [\n            {\n                token : \"keyword\",\n                regex : \"\\\\. \",\n                next  : \"start\"\n            },\n            {\n                token : \"keyword\",\n                regex : \"\\\\(\",\n                next  : \"blocktagproperties\"\n            }\n        ],\n        \"blocktagproperties\" : [\n            {\n                token : \"keyword\",\n                regex : \"\\\\)\",\n                next  : \"blocktag\"\n            },\n            {\n                token : \"string\",\n                regex : \"[a-zA-Z0-9\\\\-_]+\"\n            },\n            {\n                token : \"keyword\",\n                regex : \"#\"\n            }\n        ]\n    };\n};\n\noop.inherits(TextileHighlightRules, TextHighlightRules);\n\nexports.TextileHighlightRules = TextileHighlightRules;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/xml.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar XmlHighlightRules = require(\"./xml_highlight_rules\").XmlHighlightRules;\nvar XmlBehaviour = require(\"./behaviour/xml\").XmlBehaviour;\nvar XmlFoldMode = require(\"./folding/xml\").FoldMode;\n\nvar Mode = function() {\n    this.$tokenizer = new Tokenizer(new XmlHighlightRules().getRules());\n    this.$behaviour = new XmlBehaviour();\n    this.foldingRules = new XmlFoldMode();\n};\n\noop.inherits(Mode, TextMode);\n\n(function() {\n    \n    this.getNextLineIndent = function(state, line, tab) {\n        return this.$getIndent(line);\n    };\n\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/xml_highlight_rules.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar xmlUtil = require(\"./xml_util\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar XmlHighlightRules = function() {\n\n    // regexp must not have capturing parentheses\n    // regexps are ordered -> the first match is used\n    this.$rules = {\n        start : [{\n            token : \"text\",\n            regex : \"<\\\\!\\\\[CDATA\\\\[\",\n            next : \"cdata\"\n        }, {\n            token : \"xml_pe\",\n            regex : \"<\\\\?.*?\\\\?>\"\n        }, {\n            token : \"comment\",\n            merge : true,\n            regex : \"<\\\\!--\",\n            next : \"comment\"\n        }, {\n            token : \"xml_pe\",\n            regex : \"<\\\\!.*?>\"\n        }, {\n            token : \"meta.tag\", // opening tag\n            regex : \"<\\\\/?\",\n            next : \"tag\"\n        }, {\n            token : \"text\",\n            regex : \"\\\\s+\"\n        }, {\n            token : \"constant.character.entity\",\n            regex : \"(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\\\.-]+;)\"\n        }, {\n            token : \"text\",\n            regex : \"[^<]+\"\n        }],\n        \n        cdata : [{\n            token : \"text\",\n            regex : \"\\\\]\\\\]>\",\n            next : \"start\"\n        }, {\n            token : \"text\",\n            regex : \"\\\\s+\"\n        }, {\n            token : \"text\",\n            regex : \"(?:[^\\\\]]|\\\\](?!\\\\]>))+\"\n        }],\n\n        comment : [{\n            token : \"comment\",\n            regex : \".*?-->\",\n            next : \"start\"\n        }, {\n            token : \"comment\",\n            merge : true,\n            regex : \".+\"\n        }]\n    };\n    \n    xmlUtil.tag(this.$rules, \"tag\", \"start\");\n};\n\noop.inherits(XmlHighlightRules, TextHighlightRules);\n\nexports.XmlHighlightRules = XmlHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/xml_highlight_rules_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar XmlMode = require(\"./xml\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n    \n    name: \"XML Tokenizer\",\n    \n    setUp : function() {\n        this.tokenizer = new XmlMode().getTokenizer();\n    },\n\n    \"test: tokenize1\" : function() {\n        var line = \"<Juhu>//Juhu Kinners</Kinners>\";\n        var tokens = this.tokenizer.getLineTokens(line, \"start\").tokens;\n\n        assert.equal(3, tokens.length);\n        assert.equal(\"meta.tag\", tokens[0].type);\n        assert.equal(\"text\", tokens[1].type);\n        assert.equal(\"meta.tag\", tokens[2].type);\n    },\n    \n    \"test: two tags in the same lines should be in separate tokens\" : function() {\n        var line = \"<Juhu><Kinners>\";\n        var tokens = this.tokenizer.getLineTokens(line, \"start\").tokens;\n\n        assert.equal(2, tokens.length);\n        assert.equal(\"meta.tag\", tokens[0].type);\n        assert.equal(\"meta.tag\", tokens[1].type);\n        \n        assert.equal(\"<Juhu>\", tokens[0].value);\n        assert.equal(\"<Kinners>\", tokens[1].value);\n    },\n    \n    \"test: multiline attributes\": function() {\n        var multiLine = ['<copy set=\"{', '}\" undo=\"{', '}\"/>'];\n        \n        var state = \"start\";\n        var multiLineTokens = multiLine.map(function(line) {\n            var tokens = this.tokenizer.getLineTokens(line, state);\n            state = tokens.state;\n            return tokens.tokens;\n        }, this);\n        \n        assert.equal(multiLineTokens[0].length, 5);\n        assert.equal(multiLineTokens[1].length, 5);\n        assert.equal(multiLineTokens[2].length, 2);\n        \n        assert.equal(multiLineTokens[0][4].type, \"string\");\n        assert.equal(multiLineTokens[1][0].type, \"string\");\n        assert.equal(multiLineTokens[1][4].type, \"string\");\n        assert.equal(multiLineTokens[2][0].type, \"string\");\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/xml_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"../edit_session\").EditSession;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar XmlMode = require(\"./xml\").Mode;\nvar assert = require(\"../test/assertions\");\n\nmodule.exports = {\n    setUp : function() {\n        this.mode = new XmlMode();\n    },\n\n    \"test: getTokenizer() (smoke test)\" : function() {\n        var tokenizer = this.mode.getTokenizer();\n\n        assert.ok(tokenizer instanceof Tokenizer);\n\n        var tokens = tokenizer.getLineTokens(\"<juhu>\", \"start\").tokens;\n        assert.equal(\"meta.tag\", tokens[0].type);\n    },\n\n    \"test: toggle comment lines should not do anything\" : function() {\n        var session = new EditSession([\"  abc\", \"cde\", \"fg\"]);\n\n        this.mode.toggleCommentLines(\"start\", session, 0, 1);\n        assert.equal([\"  abc\", \"cde\", \"fg\"].join(\"\\n\"), session.toString());\n    },\n\n    \"test: next line indent should be the same as the current line indent\" : function() {\n        assert.equal(\"     \", this.mode.getNextLineIndent(\"start\", \"     abc\"));\n        assert.equal(\"\", this.mode.getNextLineIndent(\"start\", \"abc\"));\n        assert.equal(\"\\t\", this.mode.getNextLineIndent(\"start\", \"\\tabc\"));\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/xml_util.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar lang = require(\"../lib/lang\");\n\nvar formTags = lang.arrayToMap(\n    (\"button|form|input|label|select|textarea\").split(\"|\")\n);\n\nvar tableTags = lang.arrayToMap(\n    (\"table|tbody|td|tfoot|th|tr\").split(\"|\")\n);\n\nfunction string(state) {\n    return [{\n        token : \"string\",\n        regex : '\".*?\"'\n    }, {\n        token : \"string\", // multi line string start\n        merge : true,\n        regex : '[\"].*',\n        next : state + \"_qqstring\"\n    }, {\n        token : \"string\",\n        regex : \"'.*?'\"\n    }, {\n        token : \"string\", // multi line string start\n        merge : true,\n        regex : \"['].*\",\n        next : state + \"_qstring\"\n    }];\n}\n\nfunction multiLineString(quote, state) {\n    return [{\n        token : \"string\",\n        merge : true,\n        regex : \".*?\" + quote,\n        next : state\n    }, {\n        token : \"string\",\n        merge : true,\n        regex : '.+'\n    }];\n}\n\nexports.tag = function(states, name, nextState) {\n    states[name] = [{\n        token : \"text\",\n        regex : \"\\\\s+\"\n    }, {\n        //token : \"meta.tag\",\n        \n    token : function(value) {\n            if ( value==='a' ) {\n                return \"meta.tag.anchor\";\n            }\n            else if ( value==='img' ) {\n                return \"meta.tag.image\";\n            }\n            else if ( value==='script' ) {\n                return \"meta.tag.script\";\n            }\n            else if ( value==='style' ) {\n                return \"meta.tag.style\";\n            }\n            else if (formTags.hasOwnProperty(value.toLowerCase())) {\n                return \"meta.tag.form\";\n            }\n            else if (tableTags.hasOwnProperty(value.toLowerCase())) {\n                return \"meta.tag.table\";\n            }\n            else {\n                return \"meta.tag\";\n            }\n        },        \n        merge : true,\n        regex : \"[-_a-zA-Z0-9:]+\",\n        next : name + \"_embed_attribute_list\" \n    }, {\n        token: \"empty\",\n        regex: \"\",\n        next : name + \"_embed_attribute_list\"\n    }];\n\n    states[name + \"_qstring\"] = multiLineString(\"'\", name + \"_embed_attribute_list\");\n    states[name + \"_qqstring\"] = multiLineString(\"\\\"\", name + \"_embed_attribute_list\");\n    \n    states[name + \"_embed_attribute_list\"] = [{\n        token : \"meta.tag\",\n        merge : true,\n        regex : \"\\/?>\",\n        next : nextState\n    }, {\n        token : \"keyword.operator\",\n        regex : \"=\"\n    }, {\n        token : \"entity.other.attribute-name\",\n        regex : \"[-_a-zA-Z0-9:]+\"\n    }, {\n        token : \"constant.numeric\", // float\n        regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n    }, {\n        token : \"text\",\n        regex : \"\\\\s+\"\n    }].concat(string(name));\n};\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/xquery.js",
    "content": "/*\n *  eXide - web-based XQuery IDE\n *  \n *  Copyright (C) 2011 Wolfgang Meier\n *\n *  This program is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  This program is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar TextMode = require(\"./text\").Mode;\nvar Tokenizer = require(\"../tokenizer\").Tokenizer;\nvar XQueryHighlightRules = require(\"./xquery_highlight_rules\").XQueryHighlightRules;\nvar XQueryBehaviour = require(\"./behaviour/xquery\").XQueryBehaviour;\nvar Range = require(\"../range\").Range;\n\nvar Mode = function(parent) {\n    this.$tokenizer = new Tokenizer(new XQueryHighlightRules().getRules());\n    this.$behaviour = new XQueryBehaviour(parent);\n};\n\noop.inherits(Mode, TextMode);\n\n(function() {\n\n    this.getNextLineIndent = function(state, line, tab) {\n      var indent = this.$getIndent(line);\n      var match = line.match(/\\s*(?:then|else|return|[{\\(]|<\\w+>)\\s*$/);\n      if (match)\n        indent += tab;\n        return indent;\n    };\n    \n    this.checkOutdent = function(state, line, input) {\n      if (! /^\\s+$/.test(line))\n            return false;\n\n        return /^\\s*[\\}\\)]/.test(input);\n    };\n    \n    this.autoOutdent = function(state, doc, row) {\n      var line = doc.getLine(row);\n        var match = line.match(/^(\\s*[\\}\\)])/);\n\n        if (!match) return 0;\n\n        var column = match[1].length;\n        var openBracePos = doc.findMatchingBracket({row: row, column: column});\n\n        if (!openBracePos || openBracePos.row == row) return 0;\n\n        var indent = this.$getIndent(doc.getLine(openBracePos.row));\n        doc.replace(new Range(row, 0, row, column-1), indent);\n    };\n\n    this.$getIndent = function(line) {\n        var match = line.match(/^(\\s+)/);\n        if (match) {\n            return match[1];\n        }\n\n        return \"\";\n    };\n    \n    this.toggleCommentLines = function(state, doc, startRow, endRow) {\n        var i, line;\n        var outdent = true;\n        var re = /^\\s*\\(:(.*):\\)/;\n\n        for (i=startRow; i<= endRow; i++) {\n            if (!re.test(doc.getLine(i))) {\n                outdent = false;\n                break;\n            }\n        }\n\n        var range = new Range(0, 0, 0, 0);\n        for (i=startRow; i<= endRow; i++) {\n            line = doc.getLine(i);\n            range.start.row  = i;\n            range.end.row    = i;\n            range.end.column = line.length;\n\n            doc.replace(range, outdent ? line.match(re)[1] : \"(:\" + line + \":)\");\n        }\n    };\n}).call(Mode.prototype);\n\nexports.Mode = Mode;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mode/xquery_highlight_rules.js",
    "content": "/*\n *  eXide - web-based XQuery IDE\n *  \n *  Copyright (C) 2011 Wolfgang Meier\n *\n *  This program is free software: you can redistribute it and/or modify\n *  it under the terms of the GNU General Public License as published by\n *  the Free Software Foundation, either version 3 of the License, or\n *  (at your option) any later version.\n *\n *  This program is distributed in the hope that it will be useful,\n *  but WITHOUT ANY WARRANTY; without even the implied warranty of\n *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n *  GNU General Public License for more details.\n *\n *  You should have received a copy of the GNU General Public License\n *  along with this program.  If not, see <http://www.gnu.org/licenses/>.\n */\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar lang = require(\"../lib/lang\");\nvar TextHighlightRules = require(\"./text_highlight_rules\").TextHighlightRules;\n\nvar XQueryHighlightRules = function() {\n\n  var keywords = lang.arrayToMap(\n    (\"return|for|let|where|order|by|declare|function|variable|xquery|version|option|namespace|import|module|when|encoding|\" +\n     \"switch|default|try|catch|group|tumbling|sliding|window|start|end|at|only|\" +\n     \"using|stemming|\" +\n     \"while|\" + \n     \"external|\" +\n     \"if|then|else|as|and|or|typeswitch|case|ascending|descending|empty|in|count|updating|insert|delete|replace|value|node|attribute|text|element|into|of|with|contains\").split(\"|\")\n    );\n\n    // regexp must not have capturing parentheses\n    // regexps are ordered -> the first match is used\n\n    this.$rules = {\n        start : [ {\n            token : \"text\",\n            regex : \"<\\\\!\\\\[CDATA\\\\[\",\n            next : \"cdata\"\n        }, {\n            token : \"xml_pe\",\n            regex : \"<\\\\?.*?\\\\?>\"\n        }, {\n            token : \"comment\",\n            regex : \"<\\\\!--\",\n            next : \"comment\"\n    }, {\n      token : \"comment\",\n      regex : \"\\\\(:\",\n      next : \"comment\"\n        }, {\n            token : \"text\", // opening tag\n            regex : \"<\\\\/?\",\n            next : \"tag\"\n        }, {\n            token : \"constant\", // number\n            regex : \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"\n    }, {\n            token : \"variable\", // variable\n            regex : \"\\\\$[a-zA-Z_][a-zA-Z0-9_\\\\-:]*\\\\b\"\n    }, {\n      token: \"string\",\n      regex : '\".*?\"'\n    }, {\n      token: \"string\",\n      regex : \"'.*?'\"\n        }, {\n            token : \"text\",\n            regex : \"\\\\s+\"\n        }, {\n            token: \"support.function\",\n            regex: \"\\\\w[\\\\w+_\\\\-:]+(?=\\\\()\"\n        }, {\n      token : function(value) {\n            if (keywords[value])\n                return \"keyword\";\n            else\n                return \"identifier\";\n      },\n      regex : \"[a-zA-Z_$][a-zA-Z0-9_$]*\\\\b\"\n    }, {\n            token: \"keyword.operator\",\n            regex: \"\\\\*|=|<|>|\\\\-|\\\\+|and|or|eq|ne|lt|gt\"\n        }, {\n            token: \"lparen\",\n            regex: \"[[({]\"\n        }, {\n            token: \"rparen\",\n            regex: \"[\\\\])}]\"\n        } ],\n\n        tag : [ {\n            token : \"text\",\n            regex : \">\",\n            next : \"start\"\n        }, {\n            token : \"meta.tag\",\n            regex : \"[-_a-zA-Z0-9:]+\"\n        }, {\n            token : \"text\",\n            regex : \"\\\\s+\"\n        }, {\n            token : \"string\",\n            regex : '\".*?\"'\n        }, {\n            token : \"string\",\n            regex : \"'.*?'\"\n        } ],\n\n        cdata : [ {\n            token : \"text\",\n            regex : \"\\\\]\\\\]>\",\n            next : \"start\"\n        }, {\n            token : \"text\",\n            regex : \"\\\\s+\"\n        }, {\n            token : \"text\",\n            regex : \"(?:[^\\\\]]|\\\\](?!\\\\]>))+\"\n        } ],\n\n        comment : [ {\n            token : \"comment\",\n            regex : \".*?-->\",\n            next : \"start\"\n        }, {\n      token: \"comment\",\n      regex : \".*:\\\\)\",\n      next : \"start\"\n        }, {\n            token : \"comment\",\n            regex : \".+\"\n    } ]\n    };\n};\n\noop.inherits(XQueryHighlightRules, TextHighlightRules);\n\nexports.XQueryHighlightRules = XQueryHighlightRules;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/model/editor.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2011\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"ace/lib/oop\");\nvar EventEmitter = require(\"ace/lib/event_emitter\").EventEmitter;\n\nvar Editor = exports.Editor = function() {\n    this._buffers = [];\n    this._windows = [];\n};\n\n(function() {\n\n    oop.implement(this, EventEmitter);\n    \n    this.addBuffer = function(buffer) {\n        this._buffers.push(buffer);\n        return this._buffers.length-1;\n    };\n    \n    this.addWindow = function(win) {\n        this._windows.push(win);\n        return this._windows.length-1;\n    };\n    \n    this.openInWindow = function(bufferId, winId) {\n        this._windows[winId || 0].setBuffer(this._buffers[bufferId]);\n    };\n    \n}).call(Editor.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mouse/default_gutter_handler.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nfunction GutterHandler(editor) {\n    editor.setDefaultHandler(\"gutterclick\", function(e) {\n        var row = e.getDocumentPosition().row;\n        var selection = editor.session.selection;\n        \n        selection.moveCursorTo(row, 0);\n        selection.selectLine();\n    });\n}\n\nexports.GutterHandler = GutterHandler;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mouse/default_handlers.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Mike de Boer <mike AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar event = require(\"../lib/event\");\nvar dom = require(\"../lib/dom\");\nvar BrowserFocus = require(\"../lib/browser_focus\").BrowserFocus;\n\nvar STATE_UNKNOWN = 0;\nvar STATE_SELECT = 1;\nvar STATE_DRAG = 2;\n\nvar DRAG_OFFSET = 5; // pixels\n\nfunction DefaultHandlers(editor) {\n    this.editor = editor;\n    this.$clickSelection = null;\n    this.browserFocus = new BrowserFocus();\n\n    editor.setDefaultHandler(\"mousedown\", this.onMouseDown.bind(this));\n    editor.setDefaultHandler(\"dblclick\", this.onDoubleClick.bind(this));\n    editor.setDefaultHandler(\"tripleclick\", this.onTripleClick.bind(this));\n    editor.setDefaultHandler(\"quadclick\", this.onQuadClick.bind(this));\n    editor.setDefaultHandler(\"mousewheel\", this.onScroll.bind(this));\n}\n\n(function() {\n    \n    this.onMouseDown = function(ev) {\n        var inSelection = ev.inSelection();\n        var pageX = ev.pageX;\n        var pageY = ev.pageY;\n        var pos = ev.getDocumentPosition();\n        var editor = this.editor;\n        var _self = this;\n        \n        var selectionRange = editor.getSelectionRange();\n        var selectionEmpty = selectionRange.isEmpty();\n        var state = STATE_UNKNOWN;\n        \n        // if this click caused the editor to be focused should not clear the\n        // selection\n        if (\n            inSelection && (\n                !this.browserFocus.isFocused()\n                || new Date().getTime() - this.browserFocus.lastFocus < 20\n                || !editor.isFocused()\n            )\n        ) {\n            editor.focus();\n            return;\n        }\n\n        var button = ev.getButton();\n        if (button !== 0) {\n            if (selectionEmpty) {\n                editor.moveCursorToPosition(pos);\n            }\n            if (button == 2) {\n                editor.textInput.onContextMenu({x: ev.clientX, y: ev.clientY}, selectionEmpty);\n                event.capture(editor.container, function(){}, editor.textInput.onContextMenuClose);\n            }\n            return;\n        }\n\n        if (!inSelection) {\n            // Directly pick STATE_SELECT, since the user is not clicking inside\n            // a selection.\n            onStartSelect(pos);\n        }\n\n        var mousePageX = pageX, mousePageY = pageY;\n        var mousedownTime = (new Date()).getTime();\n        var dragCursor, dragRange, dragSelectionMarker;\n\n        var onMouseSelection = function(e) {\n            mousePageX = event.getDocumentX(e);\n            mousePageY = event.getDocumentY(e);\n        };\n\n        var onMouseSelectionEnd = function(e) {\n            clearInterval(timerId);\n            if (state == STATE_UNKNOWN)\n                onStartSelect(pos);\n            else if (state == STATE_DRAG)\n                onMouseDragSelectionEnd(e);\n\n            _self.$clickSelection = null;\n            state = STATE_UNKNOWN;\n        };\n\n        var onMouseDragSelectionEnd = function(e) {\n            dom.removeCssClass(editor.container, \"ace_dragging\");\n            editor.session.removeMarker(dragSelectionMarker);\n\n            if (!editor.$mouseHandler.$clickSelection) {\n                if (!dragCursor) {\n                    editor.moveCursorToPosition(pos);\n                    editor.selection.clearSelection();\n                }\n            }\n\n            if (!dragCursor)\n                return;\n\n            if (dragRange.contains(dragCursor.row, dragCursor.column)) {\n                dragCursor = null;\n                return;\n            }\n\n            editor.clearSelection();\n            if (e && (e.ctrlKey || e.altKey)) {\n                var session = editor.session;\n                var newRange = session.insert(dragCursor, session.getTextRange(dragRange));\n            } else {\n                var newRange = editor.moveText(dragRange, dragCursor);\n            }\n            if (!newRange) {\n                dragCursor = null;\n                return;\n            }\n\n            editor.selection.setSelectionRange(newRange);\n        };\n\n        var onSelectionInterval = function() {\n            if (state == STATE_UNKNOWN) {\n                var distance = calcDistance(pageX, pageY, mousePageX, mousePageY);\n                var time = (new Date()).getTime();\n\n                if (distance > DRAG_OFFSET) {\n                    state = STATE_SELECT;\n                    var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);\n                    onStartSelect(cursor);\n                }\n                else if ((time - mousedownTime) > editor.getDragDelay()) {\n                    state = STATE_DRAG;\n                    dragRange = editor.getSelectionRange();\n                    var style = editor.getSelectionStyle();\n                    dragSelectionMarker = editor.session.addMarker(dragRange, \"ace_selection\", style);\n                    editor.clearSelection();\n                    dom.addCssClass(editor.container, \"ace_dragging\");\n                }\n\n            }\n\n            if (state == STATE_DRAG)\n                onDragSelectionInterval();\n            else if (state == STATE_SELECT)\n                onUpdateSelectionInterval();\n        };\n\n        function onStartSelect(pos) {\n            if (ev.getShiftKey()) {\n                editor.selection.selectToPosition(pos);\n            }\n            else {\n                if (!_self.$clickSelection) {\n                    editor.moveCursorToPosition(pos);\n                    editor.selection.clearSelection();\n                }\n            }\n            state = STATE_SELECT;\n        }\n\n        var onUpdateSelectionInterval = function() {\n            var anchor;\n            var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);\n\n            if (_self.$clickSelection) {\n                if (_self.$clickSelection.contains(cursor.row, cursor.column)) {\n                    editor.selection.setSelectionRange(_self.$clickSelection);\n                }\n                else {\n                    if (_self.$clickSelection.compare(cursor.row, cursor.column) == -1) {\n                        anchor = _self.$clickSelection.end;\n                    }\n                    else {\n                        anchor = _self.$clickSelection.start;\n                    }\n                    editor.selection.setSelectionAnchor(anchor.row, anchor.column);\n                    editor.selection.selectToPosition(cursor);\n                }\n            }\n            else {\n                editor.selection.selectToPosition(cursor);\n            }\n\n            editor.renderer.scrollCursorIntoView();\n        };\n\n        var onDragSelectionInterval = function() {\n            dragCursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);\n            editor.moveCursorToPosition(dragCursor);\n        };\n\n        event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);\n        var timerId = setInterval(onSelectionInterval, 20);\n\n        return ev.preventDefault();\n    };\n    \n    this.onDoubleClick = function(ev) {\n        var pos = ev.getDocumentPosition();\n        var editor = this.editor;\n        \n        editor.moveCursorToPosition(pos);\n        editor.selection.selectWord();\n        this.$clickSelection = editor.getSelectionRange();\n    };\n    \n    this.onTripleClick = function(ev) {\n        var pos = ev.getDocumentPosition();\n        var editor = this.editor;\n        \n        editor.moveCursorToPosition(pos);\n        editor.selection.selectLine();\n        this.$clickSelection = editor.getSelectionRange();\n    };\n    \n    this.onQuadClick = function(ev) {\n        var editor = this.editor;\n        \n        editor.selectAll();\n        this.$clickSelection = editor.getSelectionRange();\n    };\n    \n    this.onScroll = function(ev) {\n        var editor = this.editor;\n        \n        editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed);\n        if (editor.renderer.isScrollableBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed))\n            return ev.preventDefault();\n    };\n    \n}).call(DefaultHandlers.prototype);\n\nexports.DefaultHandlers = DefaultHandlers;\n\nfunction calcDistance(ax, ay, bx, by) {\n    return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));\n}\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mouse/dragdrop.js",
    "content": ""
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mouse/fold_handler.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nfunction FoldHandler(editor) {\n    \n    editor.on(\"click\", function(e) {\n        var position = e.getDocumentPosition();\n        var session = editor.session;\n        \n        // If the user clicked on a fold, then expand it.\n        var fold = session.getFoldAt(position.row, position.column, 1);\n        if (fold) {\n            if (e.getAccelKey())\n                session.removeFold(fold);\n            else\n                session.expandFold(fold);\n                \n            e.stop();\n        }\n    });\n    \n    editor.on(\"gutterclick\", function(e) {\n        if (e.domEvent.target.className.indexOf(\"ace_fold-widget\") != -1) {\n            var row = e.getDocumentPosition().row;\n            editor.session.onFoldWidgetClick(row, e.domEvent);\n            e.stop();\n        }\n    });\n}\n\nexports.FoldHandler = FoldHandler;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mouse/mouse_event.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar event = require(\"../lib/event\");\n\n/**\n * Custom Ace mouse event\n */\nvar MouseEvent = exports.MouseEvent = function(domEvent, editor) {\n    this.domEvent = domEvent;\n    this.editor = editor;\n    \n    this.pageX = event.getDocumentX(domEvent);\n    this.pageY = event.getDocumentY(domEvent);\n    \n    this.clientX = domEvent.clientX;\n    this.clientY = domEvent.clientY;\n\n    this.$pos = null;\n    this.$inSelection = null;\n    \n    this.propagationStopped = false;\n    this.defaultPrevented = false;\n};\n\n(function() {  \n    \n    this.stopPropagation = function() {\n        event.stopPropagation(this.domEvent);\n        this.propagationStopped = true;\n    };\n    \n    this.preventDefault = function() {\n        event.preventDefault(this.domEvent);\n        this.defaultPrevented = true;\n    };\n    \n    this.stop = function() {\n        this.stopPropagation();\n        this.preventDefault();\n    };\n\n    /**\n     * Get the document position below the mouse cursor\n     * \n     * @return {Object} 'row' and 'column' of the document position\n     */\n    this.getDocumentPosition = function() {\n        if (this.$pos)\n            return this.$pos;\n            \n        var pageX = event.getDocumentX(this.domEvent);\n        var pageY = event.getDocumentY(this.domEvent);\n        this.$pos = this.editor.renderer.screenToTextCoordinates(pageX, pageY);\n        return this.$pos;\n    };\n    \n    /**\n     * Check if the mouse cursor is inside of the text selection\n     * \n     * @return {Boolean} whether the mouse cursor is inside of the selection\n     */\n    this.inSelection = function() {\n        if (this.$inSelection !== null)\n            return this.$inSelection;\n            \n        var editor = this.editor;\n        \n        if (editor.getReadOnly()) {\n            this.$inSelection = false;\n        }\n        else {\n            var selectionRange = editor.getSelectionRange();\n            if (selectionRange.isEmpty())\n                this.$inSelection = false;\n            else {\n                var pos = this.getDocumentPosition();\n                this.$inSelection = selectionRange.contains(pos.row, pos.column);\n            }\n        }\n        return this.$inSelection;\n    };\n    \n    /**\n     * Get the clicked mouse button\n     * \n     * @return {Number} 0 for left button, 1 for middle button, 2 for right button\n     */\n    this.getButton = function() {\n        return event.getButton(this.domEvent);\n    };\n    \n    /**\n     * @return {Boolean} whether the shift key was pressed when the event was emitted\n     */\n    this.getShiftKey = function() {\n        return this.domEvent.shiftKey;\n    };\n    \n    this.getAccelKey = function() {\n        return this.domEvent.ctrlKey || this.domEvent.metaKey ;\n    };\n    \n}).call(MouseEvent.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mouse/mouse_handler.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Mihai Sucan <mihai DOT sucan AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar event = require(\"../lib/event\");\nvar DefaultHandlers = require(\"./default_handlers\").DefaultHandlers;\nvar DefaultGutterHandler = require(\"./default_gutter_handler\").GutterHandler;\nvar MouseEvent = require(\"./mouse_event\").MouseEvent;\n\nvar MouseHandler = function(editor) {\n    this.editor = editor;\n    \n    new DefaultHandlers(editor);\n    new DefaultGutterHandler(editor);\n    \n    event.addListener(editor.container, \"mousedown\", function(e) {\n        editor.focus();\n        return event.preventDefault(e);\n    });\n    event.addListener(editor.container, \"selectstart\", function(e) {\n        return event.preventDefault(e);\n    });\n\n    var mouseTarget = editor.renderer.getMouseEventTarget();\n    event.addListener(mouseTarget, \"mousedown\", this.onMouseEvent.bind(this, \"mousedown\"));\n    event.addListener(mouseTarget, \"click\", this.onMouseEvent.bind(this, \"click\"));\n    event.addListener(mouseTarget, \"mousemove\", this.onMouseMove.bind(this, \"mousemove\"));\n    event.addMultiMouseDownListener(mouseTarget, 0, 2, 500, this.onMouseEvent.bind(this, \"dblclick\"));\n    event.addMultiMouseDownListener(mouseTarget, 0, 3, 600, this.onMouseEvent.bind(this, \"tripleclick\"));\n    event.addMultiMouseDownListener(mouseTarget, 0, 4, 600, this.onMouseEvent.bind(this, \"quadclick\"));\n    event.addMouseWheelListener(editor.container, this.onMouseWheel.bind(this, \"mousewheel\"));\n    \n    var gutterEl = editor.renderer.$gutter;\n    event.addListener(gutterEl, \"mousedown\", this.onMouseEvent.bind(this, \"guttermousedown\"));\n    event.addListener(gutterEl, \"click\", this.onMouseEvent.bind(this, \"gutterclick\"));\n    event.addListener(gutterEl, \"dblclick\", this.onMouseEvent.bind(this, \"gutterdblclick\"));\n    event.addListener(gutterEl, \"mousemove\", this.onMouseMove.bind(this, \"gutter\"));\n};\n\n(function() {\n\n    this.$scrollSpeed = 1;\n    this.setScrollSpeed = function(speed) {\n        this.$scrollSpeed = speed;\n    };\n\n    this.getScrollSpeed = function() {\n        return this.$scrollSpeed;\n    };\n\n    this.onMouseEvent = function(name, e) {\n        this.editor._emit(name, new MouseEvent(e, this.editor));\n    };\n    \n    this.$dragDelay = 250;\n    this.setDragDelay = function(dragDelay) {\n        this.$dragDelay = dragDelay;\n    };\n\n    this.getDragDelay = function() {\n        return this.$dragDelay;\n    };\n\n    this.onMouseMove = function(name, e) {\n        // optimization, because mousemove doesn't have a default handler.\n        var listeners = this.editor._eventRegistry && this.editor._eventRegistry.mousemove;\n        if (!listeners || !listeners.length)\n            return;\n\n        this.editor._emit(name, new MouseEvent(e, this.editor));\n    };\n\n    this.onMouseWheel = function(name, e) {\n        var mouseEvent = new MouseEvent(e, this.editor);\n        mouseEvent.speed = this.$scrollSpeed * 2;\n        mouseEvent.wheelX = e.wheelX;\n        mouseEvent.wheelY = e.wheelY;\n        \n        this.editor._emit(name, mouseEvent);\n    };\n\n}).call(MouseHandler.prototype);\n\nexports.MouseHandler = MouseHandler;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/mouse/multi_select_handler.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Harutyun Amirjanyan <amirjanyan AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nvar event = require(\"../lib/event\");\n\n\n// mouse\nfunction isSamePoint(p1, p2) {\n    return p1.row == p2.row && p1.column == p2.column;\n}\n\nfunction onMouseDown(e) {\n    var ev = e.domEvent;\n    var alt = ev.altKey;\n    var shift = ev.shiftKey;\n    var ctrl = e.getAccelKey();\n    var button = e.getButton();\n\n    if (!ctrl && !alt) {\n        if (e.editor.inMultiSelectMode) {\n            if (button == 0) {\n                e.editor.exitMultiSelectMode();\n            } else if (button == 2) {\n                var editor = e.editor;\n                var selectionEmpty = editor.selection.isEmpty();\n                editor.textInput.onContextMenu({x: e.clientX, y: e.clientY}, selectionEmpty);\n                event.capture(editor.container, function(){}, editor.textInput.onContextMenuClose);\n                e.stop();\n            }\n        }\n        return;\n    }\n\n    var editor = e.editor;\n    var selection = editor.selection;\n    var isMultiSelect = editor.inMultiSelectMode;\n    var pos = e.getDocumentPosition();\n    var cursor = selection.getCursor();\n    var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor));\n\n\n    var mouseX = e.pageX, mouseY = e.pageY;\n    var onMouseSelection = function(e) {\n        mouseX = event.getDocumentX(e);\n        mouseY = event.getDocumentY(e);\n    };\n\n    var blockSelect = function() {\n        var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);\n        var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column);\n\n        if (isSamePoint(screenCursor, newCursor)\n            && isSamePoint(cursor, selection.selectionLead))\n            return;\n        screenCursor = newCursor;\n\n        editor.selection.moveCursorToPosition(cursor);\n        editor.selection.clearSelection();\n        editor.renderer.scrollCursorIntoView();\n\n        editor.removeSelectionMarkers(rectSel);\n        rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor);\n        rectSel.forEach(editor.addSelectionMarker, editor);\n        editor.updateSelectionMarkers();\n    };\n    \n    var session = editor.session;\n    var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY);\n    var screenCursor = screenAnchor;\n\n    \n\n    if (ctrl && !shift && !alt && button == 0) {\n        if (!isMultiSelect && inSelection)\n            return; // dragging\n\n        if (!isMultiSelect) {\n            var range = selection.toOrientedRange();\n            editor.addSelectionMarker(range);\n        }\n\n        var oldRange = selection.rangeList.rangeAtPoint(pos);\n\n        event.capture(editor.container, function(){}, function() {\n            var tmpSel = selection.toOrientedRange();\n\n            if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor))\n                selection.substractPoint(tmpSel.cursor);\n            else {\n                if (range) {\n                    editor.removeSelectionMarker(range);\n                    selection.addRange(range);\n                }\n                selection.addRange(tmpSel);\n            }\n        });\n\n    } else if (!shift && alt && button == 0) {\n        e.stop();\n\n        if (isMultiSelect && !ctrl)\n            selection.toSingleRange();\n        else if (!isMultiSelect && ctrl)\n            selection.addRange();\n\n        selection.moveCursorToPosition(pos);\n        selection.clearSelection();\n\n        var rectSel = [];\n\n        var onMouseSelectionEnd = function(e) {\n            clearInterval(timerId);\n            editor.removeSelectionMarkers(rectSel);\n            for (var i = 0; i < rectSel.length; i++)\n                selection.addRange(rectSel[i]);\n        };\n\n        var onSelectionInterval = blockSelect;\n\n        event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);\n        var timerId = setInterval(function() {onSelectionInterval();}, 20);\n\n        return e.preventDefault();\n    }\n}\n\n\nexports.onMouseDown = onMouseDown;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/multi_select.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Harutyun Amirjanyan <amirjanyan AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nvar RangeList = require(\"./range_list\").RangeList;\nvar Range = require(\"./range\").Range;\nvar Selection = require(\"./selection\").Selection;\nvar onMouseDown = require(\"./mouse/multi_select_handler\").onMouseDown;\nexports.commands = require(\"./commands/multi_select_commands\");\n\n// Todo: session.find or editor.findVolatile that returns range\nvar Search = require(\"./search\").Search;\nvar search = new Search();\n\nfunction find(session, needle, dir) {\n    search.$options.wrap = true;\n    search.$options.needle = needle;\n    search.$options.backwards = dir == -1;\n    return search.find(session);\n}\n\n// extend EditSession\nvar EditSession = require(\"./edit_session\").EditSession;\n(function() {\n    this.getSelectionMarkers = function() {\n        return this.$selectionMarkers;\n    };\n}).call(EditSession.prototype);\n\n// extend Selection\n(function() {\n    // list of ranges in reverse addition order\n    this.ranges = null;\n\n    // automatically sorted list of ranges\n    this.rangeList = null;\n\n    /**\n     * Selection.addRange(Range) -> Void\n     *\n     * adds a range to selection entering multiselect mode if necessary\n     **/\n    this.addRange = function(range, $blockChangeEvents) {\n        if (!range)\n            return;\n\n        if (!this.inMultiSelectMode && this.rangeCount == 0) {\n            var oldRange = this.toOrientedRange();\n            if (range.intersects(oldRange))\n                return $blockChangeEvents || this.fromOrientedRange(range);\n\n            this.rangeList.add(oldRange);\n            this.$onAddRange(oldRange);\n        }\n\n        if (!range.cursor)\n            range.cursor = range.end;\n\n        var removed = this.rangeList.add(range);\n\n        this.$onAddRange(range);\n\n        if (removed.length)\n            this.$onRemoveRange(removed);\n\n        if (this.rangeCount > 1 && !this.inMultiSelectMode) {\n            this._emit(\"multiSelect\");\n            this.inMultiSelectMode = true;\n            this.session.$undoSelect = false;\n            this.rangeList.attach(this.session);\n        }\n\n        return $blockChangeEvents || this.fromOrientedRange(range);\n    };\n\n    this.toSingleRange = function(range) {\n        range = range || this.ranges[0];\n        var removed = this.rangeList.removeAll();\n        if (removed.length)\n            this.$onRemoveRange(removed);\n\n        range && this.fromOrientedRange(range);\n    };\n    \n    /**\n     * Selection.addRange(pos) -> Range\n     * pos: {row, column}\n     *\n     * removes range containing pos (if exists)\n     **/\n    this.substractPoint = function(pos) {\n        var removed = this.rangeList.substractPoint(pos);\n        if (removed) {\n            this.$onRemoveRange(removed);\n            return removed[0];\n        }\n    };\n\n    /**\n     * Selection.mergeOverlappingRanges() -> Void\n     *\n     * merges overlapping ranges ensuring consistency after changes\n     **/\n    this.mergeOverlappingRanges = function() {\n        var removed = this.rangeList.merge();\n        if (removed.length)\n            this.$onRemoveRange(removed);\n        else if(this.ranges[0])\n            this.fromOrientedRange(this.ranges[0]);\n    };\n\n    this.$onAddRange = function(range) {\n        this.rangeCount = this.rangeList.ranges.length;\n        this.ranges.unshift(range);\n        this._emit(\"addRange\", {range: range});\n    };\n\n    this.$onRemoveRange = function(removed) {\n        this.rangeCount = this.rangeList.ranges.length;\n        if (this.rangeCount == 1 && this.inMultiSelectMode) {\n            var lastRange = this.rangeList.ranges.pop();\n            removed.push(lastRange);\n            this.rangeCount = 0;\n        }\n\n        for (var i = removed.length; i--; ) {\n            var index = this.ranges.indexOf(removed[i]);\n            this.ranges.splice(index, 1);\n        }\n\n        this._emit(\"removeRange\", {ranges: removed});\n\n        if (this.rangeCount == 0 && this.inMultiSelectMode) {\n            this.inMultiSelectMode = false;\n            this._emit(\"singleSelect\");\n            this.session.$undoSelect = true;\n            this.rangeList.detach(this.session);\n        }\n\n        lastRange = lastRange || this.ranges[0];\n        if (lastRange && !lastRange.isEqual(this.getRange()))\n            this.fromOrientedRange(lastRange);\n    };\n\n    // adds multicursor support to selection\n    this.$initRangeList = function() {\n        if (this.rangeList)\n            return;\n\n        this.rangeList = new RangeList();\n        this.ranges = [];\n        this.rangeCount = 0;\n    };\n\n    this.getAllRanges = function() {\n        return this.rangeList.ranges.concat();\n    };\n\n    this.splitIntoLines = function () {\n        if (this.rangeCount > 1) {\n            var ranges = this.rangeList.ranges;\n            var lastRange = ranges[ranges.length - 1];\n            var range = Range.fromPoints(ranges[0].start, lastRange.end);\n\n            this.toSingleRange();\n            this.setSelectionRange(range, lastRange.cursor == lastRange.start);\n        } else {\n            var cursor = this.session.documentToScreenPosition(this.selectionLead);\n            var anchor = this.session.documentToScreenPosition(this.selectionAnchor);\n\n            var rectSel = this.rectangularRangeBlock(cursor, anchor);\n            rectSel.forEach(this.addRange, this);\n        }\n    };\n\n    /**\n     *   Selection.rectangularRangeBlock(screenCursor, screenAnchor, includeEmptyLines) -> [Range]\n     *   gets list of ranges composing rectangular block on the screen\n     *   @includeEmptyLines if true includes ranges inside the block which\n     *         are empty becuase of the clipping\n     */\n    this.rectangularRangeBlock = function(screenCursor, screenAnchor, includeEmptyLines) {\n        var rectSel = [];\n\n        var xBackwards = screenCursor.column < screenAnchor.column;\n        if (xBackwards) {\n            var startColumn = screenCursor.column;\n            var endColumn = screenAnchor.column;\n        } else {\n            var startColumn = screenAnchor.column;\n            var endColumn = screenCursor.column;\n        }\n\n        var yBackwards = screenCursor.row < screenAnchor.row;\n        if (yBackwards) {\n            var startRow = screenCursor.row;\n            var endRow = screenAnchor.row;\n        } else {\n            var startRow = screenAnchor.row;\n            var endRow = screenCursor.row;\n        }\n\n        if (startColumn < 0)\n            startColumn = 0;\n        if (startRow < 0)\n            startRow = 0;\n\n        if (startRow == endRow)\n            includeEmptyLines = true;\n\n        for (var row = startRow; row <= endRow; row++) {\n            var range = Range.fromPoints(\n                this.session.screenToDocumentPosition(row, startColumn),\n                this.session.screenToDocumentPosition(row, endColumn)\n            );\n            if (range.isEmpty()) {\n                if (docEnd && isSamePoint(range.end, docEnd))\n                    break;\n                var docEnd = range.end;\n            }\n            range.cursor = xBackwards ? range.start : range.end;\n            rectSel.push(range);\n        }\n\n        if (yBackwards)\n            rectSel.reverse();\n\n        if (!includeEmptyLines) {\n            var end = rectSel.length - 1;\n            while (rectSel[end].isEmpty() && end > 0)\n                end--;\n            if (end > 0) {\n                var start = 0;\n                while (rectSel[start].isEmpty())\n                    start++;\n            }\n            for (var i = end; i >= start; i--) {\n                if (rectSel[i].isEmpty())\n                    rectSel.splice(i, 1);\n            }\n        }\n\n        return rectSel;\n    };\n}).call(Selection.prototype);\n\n// extend Editor\nvar Editor = require(\"./editor\").Editor;\n(function() {\n    /**\n     * Editor.updateSelectionMarkers() -> Void\n     *\n     * updates cursor and marker layers\n     **/\n    this.updateSelectionMarkers = function() {\n        this.renderer.updateCursor();\n        this.renderer.updateBackMarkers();\n    };\n\n    /**\n     * Editor.addSelectionMarker(orientedRange) -> Range\n     * - orientedRange: range with cursor\n     *\n     * adds selection and cursor\n     **/\n    this.addSelectionMarker = function(orientedRange) {\n        if (!orientedRange.cursor)\n            orientedRange.cursor = orientedRange.end;\n\n        var style = this.getSelectionStyle();\n        orientedRange.marker = this.session.addMarker(orientedRange, \"ace_selection\", style);\n\n        this.session.$selectionMarkers.push(orientedRange);\n        this.session.selectionMarkerCount = this.session.$selectionMarkers.length;\n        return orientedRange;\n    };\n\n    /**\n     * Editor.removeSelectionMarker(range) -> Void\n     * - range: selection range added with addSelectionMarker\n     *\n     * removes selection marker\n     **/\n    this.removeSelectionMarker = function(range) {\n        if (!range.marker)\n            return;\n        this.session.removeMarker(range.marker);\n        var index = this.session.$selectionMarkers.indexOf(range);\n        if (index != -1)\n            this.session.$selectionMarkers.splice(index, 1);\n        this.session.selectionMarkerCount = this.session.$selectionMarkers.length;\n    };\n\n    this.removeSelectionMarkers = function(ranges) {\n        var markerList = this.session.$selectionMarkers;\n        for (var i = ranges.length; i--; ) {\n            var range = ranges[i];\n            if (!range.marker)\n                continue;\n            this.session.removeMarker(range.marker);\n            var index = markerList.indexOf(range);\n            if (index != -1)\n                markerList.splice(index, 1);\n        }\n        this.session.selectionMarkerCount = markerList.length;\n    };\n\n    this.$onAddRange = function(e) {\n        this.addSelectionMarker(e.range);\n        this.renderer.updateCursor();\n        this.renderer.updateBackMarkers();\n    };\n    \n    this.$onRemoveRange = function(e) {\n        this.removeSelectionMarkers(e.ranges);\n        this.renderer.updateCursor();\n        this.renderer.updateBackMarkers();\n    };\n    \n    this.$onMultiSelect = function(e) {\n        if (this.inMultiSelectMode)\n            return;\n        this.inMultiSelectMode = true;\n\n        this.setStyle(\"multiselect\");\n        this.keyBinding.addKeyboardHandler(exports.commands.keyboardHandler);\n        this.commands.on(\"exec\", this.$onMultiSelectExec);\n\n        this.renderer.updateCursor();\n        this.renderer.updateBackMarkers();\n    };\n    \n    this.$onSingleSelect = function(e) {\n        if (this.session.multiSelect.inVirtualMode)\n            return;\n        this.inMultiSelectMode = false;\n\n        this.unsetStyle(\"multiselect\");\n        this.keyBinding.removeKeyboardHandler(exports.commands.keyboardHandler);\n\n        this.commands.removeEventListener(\"exec\", this.$onMultiSelectExec);\n        this.renderer.updateCursor();\n        this.renderer.updateBackMarkers();\n    };\n\n    this.$onMultiSelectExec = function(e) {\n        var command = e.command;\n        var editor = e.editor;\n        if (!command.multiSelectAction) {\n            command.exec(editor, e.args || {});\n            editor.multiSelect.addRange(editor.multiSelect.toOrientedRange());\n            editor.multiSelect.mergeOverlappingRanges();\n        } else if (command.multiSelectAction == \"forEach\") {\n            editor.forEachSelection(command, e.args);\n        } else if (command.multiSelectAction == \"single\") {\n            editor.exitMultiSelectMode();\n            command.exec(editor, e.args || {});\n        } else {\n            command.multiSelectAction(editor, e.args || {});\n        }\n        e.preventDefault();\n    };\n\n    /**\n     * Editor.forEachSelection(cmd, args) -> Void\n     * - cmd: command to execute\n     * - args: arguments to the command\n     *\n     * executes command for each selection range\n     **/\n    this.forEachSelection = function(cmd, args) {\n        if (this.inVirtualSelectionMode)\n            return;\n\n        var session = this.session;\n        var selection = this.selection;\n        var rangeList = selection.rangeList;\n\n        var reg = selection._eventRegistry;\n        selection._eventRegistry = {};\n\n        var tmpSel = new Selection(session);\n        this.inVirtualSelectionMode = true;\n        for (var i = rangeList.ranges.length; i--;) {\n            tmpSel.fromOrientedRange(rangeList.ranges[i]);\n            this.selection = session.selection = tmpSel;\n            cmd.exec(this, args || {});\n            tmpSel.toOrientedRange(rangeList.ranges[i]);\n        }\n        tmpSel.detach();\n\n        this.selection = session.selection = selection;\n        this.inVirtualSelectionMode = false;\n        selection._eventRegistry = reg;\n        selection.mergeOverlappingRanges();\n\n        this.onCursorChange();\n        this.onSelectionChange();\n    };\n    \n    /**\n    * Editor.exitMultiSelectMode() -> Void\n    *\n    * removes all selections except the last added one.\n    **/\n    this.exitMultiSelectMode = function() {\n        if (this.inVirtualSelectionMode)\n            return;\n        this.multiSelect.toSingleRange();\n    };\n\n    this.getCopyText = function() {\n        var text = \"\";\n        if (this.inMultiSelectMode) {\n            var ranges = this.multiSelect.rangeList.ranges;\n            text = [];\n            for (var i = 0; i < ranges.length; i++) {\n                text.push(this.session.getTextRange(ranges[i]));\n            }\n            text = text.join(this.session.getDocument().getNewLineCharacter());\n        } else if (!this.selection.isEmpty()) {\n            text = this.session.getTextRange(this.getSelectionRange());\n        }\n\n        return text;\n    };\n\n    /**\n     * Editor.findAll(dir, options) -> Number\n     * - needle: text to find\n     * - options: search options\n     * - additive: keeps \n     *\n     * finds and selects all the occurencies of needle\n     * returns number of found ranges\n     **/\n    this.findAll = function(needle, options, additive) {\n        options = options || {};\n        options.needle = needle || options.needle;\n        this.$search.set(options);\n\n        var ranges = this.$search.findAll(this.session);\n        if (!ranges.length)\n            return 0;\n\n        this.$blockScrolling += 1;\n        var selection = this.multiSelect;\n        \n        if (!additive)\n            selection.toSingleRange(ranges[0]);\n        \n        for (var i = ranges.length; i--; )\n            selection.addRange(ranges[i], true);\n\n        this.$blockScrolling -= 1;\n\n        return ranges.length;\n    };\n\n    // commands\n    /**\n     * Editor.selectMoreLines(dir, skip) -> Void\n     * - dir: -1 up, 1 down\n     * - skip: remove active selection range if true\n     *\n     * adds cursor above or bellow active cursor\n     **/\n    this.selectMoreLines = function(dir, skip) {\n        var range = this.selection.toOrientedRange();\n        var isBackwards = range.cursor == range.end;\n\n        var screenLead = this.session.documentToScreenPosition(range.cursor);\n        if (this.selection.$desiredColumn)\n            screenLead.column = this.selection.$desiredColumn;\n\n        var lead = this.session.screenToDocumentPosition(screenLead.row + dir, screenLead.column);\n\n        if (!range.isEmpty()) {\n            var screenAnchor = this.session.documentToScreenPosition(isBackwards ? range.end : range.start);\n            var anchor = this.session.screenToDocumentPosition(screenAnchor.row + dir, screenAnchor.column);\n        } else {\n            var anchor = lead;\n        }\n\n        if (isBackwards) {\n            var newRange = Range.fromPoints(lead, anchor);\n            newRange.cursor = newRange.start;\n        } else {\n            var newRange = Range.fromPoints(anchor, lead);\n            newRange.cursor = newRange.end;\n        }\n\n        newRange.desiredColumn = screenLead.column;\n        if (!this.selection.inMultiSelectMode) {\n            this.selection.addRange(range);\n        } else {\n            if (skip)\n                var toRemove = range.cursor;\n        }\n\n        this.selection.addRange(newRange);\n        if (toRemove)\n            this.selection.substractPoint(toRemove);\n    };\n\n    /**\n     * Editor.transposeSelections(dir) -> Void\n     * - dir: direction to rotate selections\n     *\n     * contents \n     * empty ranges are expanded to word\n     **/\n    this.transposeSelections = function(dir) {\n        var session = this.session;\n        var sel = session.multiSelect;\n        var all = sel.ranges;\n\n        for (var i = all.length; i--; ) {\n            var range = all[i];\n            if (range.isEmpty()) {\n                var tmp = session.getWordRange(range.start.row, range.start.column);\n                range.start.row = tmp.start.row;\n                range.start.column = tmp.start.column;\n                range.end.row = tmp.end.row;\n                range.end.column = tmp.end.column;\n            }\n        }\n        sel.mergeOverlappingRanges();\n        \n        var words = [];\n        for (var i = all.length; i--; ) {\n            var range = all[i];\n            words.unshift(session.getTextRange(range));\n        }\n\n        if (dir < 0)\n            words.unshift(words.pop());\n        else\n            words.push(words.shift());\n\n        for (var i = all.length; i--; ) {\n            var range = all[i];\n            var tmp = range.clone();\n            session.replace(range, words[i]);\n            range.start.row = tmp.start.row;\n            range.start.column = tmp.start.column;\n        }\n    }\n\n    /**\n     * Editor.selectMore(dir, skip) -> Void\n     * - dir: 1 next, -1 previous\n     * - skip: remove active selection range if true\n     *\n     * finds next occurence of text in active selection\n     * and adds it to the selections\n     **/\n    this.selectMore = function (dir, skip) {\n        var session = this.session;\n        var sel = session.multiSelect;\n\n        var range = sel.toOrientedRange();\n        if (range.isEmpty()) {\n            var range = session.getWordRange(range.start.row, range.start.column);\n            range.cursor = range.end;\n            this.multiSelect.addRange(range);\n        }\n        var needle = session.getTextRange(range);\n\n        var newRange = find(session, needle, dir);\n        if (newRange) {\n            newRange.cursor = dir == -1 ? newRange.start : newRange.end;\n            this.multiSelect.addRange(newRange);\n        }\n        if (skip)\n            this.multiSelect.substractPoint(range.cursor);\n    };\n}).call(Editor.prototype);\n\n\nfunction isSamePoint(p1, p2) {\n    return p1.row == p2.row && p1.column == p2.column;\n}\n\n// patch\n// adds multicursor support to a session\nexports.onSessionChange = function(e) {\n    var session = e.session;\n    if (!session.multiSelect) {\n        session.$selectionMarkers = [];\n        session.selection.$initRangeList();\n        session.multiSelect = session.selection;\n    }\n    this.multiSelect = session.multiSelect;\n\n    var oldSession = e.oldSession;\n    if (oldSession) {\n        // todo use events\n        if (oldSession.multiSelect && oldSession.multiSelect.editor == this)\n            oldSession.multiSelect.editor = null;\n\n        session.multiSelect.removeEventListener(\"addRange\", this.$onAddRange);\n        session.multiSelect.removeEventListener(\"removeRange\", this.$onRemoveRange);\n        session.multiSelect.removeEventListener(\"multiSelect\", this.$onMultiSelect);\n        session.multiSelect.removeEventListener(\"singleSelect\", this.$onSingleSelect);\n    }\n\n    session.multiSelect.on(\"addRange\", this.$onAddRange);\n    session.multiSelect.on(\"removeRange\", this.$onRemoveRange);\n    session.multiSelect.on(\"multiSelect\", this.$onMultiSelect);\n    session.multiSelect.on(\"singleSelect\", this.$onSingleSelect);\n\n    // this.$onSelectionChange = this.onSelectionChange.bind(this);\n\n    if (this.inMultiSelectMode != session.selection.inMultiSelectMode) {\n        if (session.selection.inMultiSelectMode)\n            this.$onMultiSelect();\n        else\n            this.$onSingleSelect();\n    }\n};\n\n/**\n * MultiSelect(editor) -> Void\n *\n * adds multiple selection support to the editor\n * (note: should be called only once for each editor instance)\n **/\nfunction MultiSelect(editor) {\n    editor.$onAddRange = editor.$onAddRange.bind(editor);\n    editor.$onRemoveRange = editor.$onRemoveRange.bind(editor);\n    editor.$onMultiSelect = editor.$onMultiSelect.bind(editor);\n    editor.$onSingleSelect = editor.$onSingleSelect.bind(editor);\n\n    exports.onSessionChange.call(editor, editor);\n    editor.on(\"changeSession\", exports.onSessionChange.bind(editor));\n\n    editor.on(\"mousedown\", onMouseDown);\n    editor.commands.addCommands(exports.commands.defaultCommands);\n    \n    addAltCursorListeners(editor);\n}\n\nfunction addAltCursorListeners(editor){\n    var el = editor.textInput.getElement();\n    var altCursor = false;\n    var contentEl = editor.renderer.content;\n    el.addEventListener(\"keydown\", function(e) {\n        if (e.keyCode == 18 && !(e.ctrlKey || e.shiftKey || e.metaKey)) {\n            if (!altCursor) {\n                contentEl.style.cursor = \"crosshair\";\n                altCursor = true;\n            }\n        } else if (altCursor) {\n            contentEl.style.cursor = \"\";\n        }\n    });\n    \n    el.addEventListener(\"keyup\", reset);\n    el.addEventListener(\"blur\", reset);\n    function reset() {\n        if (altCursor) {\n            contentEl.style.cursor = \"\";\n            altCursor = false;\n        }\n    }\n}\n\nexports.MultiSelect = MultiSelect;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/multi_select_test.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Harutyun Amirjanyan <amirjanyan AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"./edit_session\").EditSession;\nvar Editor = require(\"./editor\").Editor;\nvar MockRenderer = require(\"./test/mockrenderer\").MockRenderer;\nvar Range = require(\"./range\").Range;\nvar assert = require(\"./test/assertions\");\nvar MultiSelect = require(\"./multi_select\").MultiSelect;\n\nvar editor\nvar exec = function(name, times, args) {\n    do {\n        editor.commands.exec(name, editor, args);\n    } while(times --> 1)\n};\nvar testRanges = function(str) {\n    assert.equal(editor.selection.getAllRanges() + \"\", str + \"\");\n}\n\nmodule.exports = {\n\n    name: \"ACE multi_select.js\",\n\n    \"test: multiselect editing\": function() {\n        var doc = new EditSession([\n            \"w1.w2\",\n            \"    wtt.w\",\n            \"    wtt.w\"\n        ]);\n        editor = new Editor(new MockRenderer(), doc);\n        MultiSelect(editor);\n\n        editor.navigateFileEnd();\n        exec(\"selectMoreBefore\", 3);\n        assert.ok(editor.inMultiSelectMode);\n        assert.equal(editor.selection.getAllRanges().length, 4);\n\n        var newLine = editor.session.getDocument().getNewLineCharacter();\n        var copyText = \"wwww\".split(\"\").join(newLine);\n        assert.equal(editor.getCopyText(), copyText);\n        exec(\"insertstring\", 1, \"a\");\n        exec(\"backspace\", 2);\n        assert.equal(editor.session.getValue(), \"w1.w2\\ntt\\ntt\");\n        assert.equal(editor.selection.getAllRanges().length, 4);\n\n        exec(\"selectall\");\n        assert.ok(!editor.inMultiSelectMode);\n        //assert.equal(editor.selection.getAllRanges().length, 1);\n    },\n\n    \"test: multiselect navigation\": function() {\n        var doc = new EditSession([\n            \"w1.w2\",\n            \"    wtt.w\",\n            \"    wtt.we\"\n        ]);\n        editor = new Editor(new MockRenderer(), doc);\n        MultiSelect(editor);\n\n        editor.selectMoreLines(1);\n        testRanges(\"Range: [0/0] -> [0/0],Range: [1/0] -> [1/0]\");\n        assert.ok(editor.inMultiSelectMode);\n\n        exec(\"golinedown\");\n        exec(\"gotolineend\");\n        testRanges(\"Range: [1/9] -> [1/9],Range: [2/10] -> [2/10]\");\n        exec(\"selectwordleft\");\n\n        testRanges(\"Range: [1/8] -> [1/9],Range: [2/8] -> [2/10]\");\n        exec(\"golinedown\", 2);\n        assert.ok(!editor.inMultiSelectMode);\n    },\n\n    \"test: multiselect session change\": function() {\n        var doc = new EditSession([\n            \"w1.w2\",\n            \"    wtt.w\",\n            \"    wtt.w\"\n        ]);\n        editor = new Editor(new MockRenderer(), doc);\n        MultiSelect(editor);\n\n        editor.selectMoreLines(1)\n        testRanges(\"Range: [0/0] -> [0/0],Range: [1/0] -> [1/0]\");\n        assert.ok(editor.inMultiSelectMode);\n\n        var doc2 = new EditSession([\"w1\"]);\n        editor.setSession(doc2);\n        assert.ok(!editor.inMultiSelectMode);\n\n        editor.setSession(doc);\n        assert.ok(editor.inMultiSelectMode);\n    },\n    \n    \"test: multiselect addRange\": function() {\n        var doc = new EditSession([\n            \"w1.w2\",\n            \"    wtt.w\",\n            \"    wtt.w\"\n        ]);\n        editor = new Editor(new MockRenderer(), doc);\n        MultiSelect(editor);\n\t\tvar selection = editor.selection;\n\n        var range1 = new Range(0, 2, 0, 4);\n        editor.selection.fromOrientedRange(range1);\n        \n        var range2 = new Range(0, 3, 0, 4);\n        selection.addRange(range2);\n        assert.ok(!editor.inMultiSelectMode);\n        assert.ok(range2.isEqual(editor.selection.getRange()));\n        \n        var range3 = new Range(0, 1, 0, 1);\n        selection.addRange(range3);\n        assert.ok(editor.inMultiSelectMode);\n        testRanges([range3, range2]);\n        \n        var range4 = new Range(0, 0, 4, 0);\n        selection.addRange(range4);\n        assert.ok(!editor.inMultiSelectMode);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/narcissus/definitions.js",
    "content": "/* vim: set sw=4 ts=4 et tw=78: */\n/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is the Narcissus JavaScript engine.\n *\n * The Initial Developer of the Original Code is\n * Brendan Eich <brendan@mozilla.org>.\n * Portions created by the Initial Developer are Copyright (C) 2004\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *   Tom Austin <taustin@ucsc.edu>\n *   Brendan Eich <brendan@mozilla.org>\n *   Shu-Yu Guo <shu@rfrn.org>\n *   Dave Herman <dherman@mozilla.com>\n *   Dimitris Vardoulakis <dimvar@ccs.neu.edu>\n *   Patrick Walton <pcwalton@mozilla.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\n/*\n * Narcissus - JS implemented in JS.\n *\n * Well-known constants and lookup tables.  Many consts are generated from the\n * tokens table via eval to minimize redundancy, so consumers must be compiled\n * separately to take advantage of the simple switch-case constant propagation\n * done by SpiderMonkey.\n */\n\ndefine(function(require, exports, module) {\n\nvar tokens = [\n    // End of source.\n    \"END\",\n\n    // Operators and punctuators.  Some pair-wise order matters, e.g. (+, -)\n    // and (UNARY_PLUS, UNARY_MINUS).\n    \"\\n\", \";\",\n    \",\",\n    \"=\",\n    \"?\", \":\", \"CONDITIONAL\",\n    \"||\",\n    \"&&\",\n    \"|\",\n    \"^\",\n    \"&\",\n    \"==\", \"!=\", \"===\", \"!==\",\n    \"<\", \"<=\", \">=\", \">\",\n    \"<<\", \">>\", \">>>\",\n    \"+\", \"-\",\n    \"*\", \"/\", \"%\",\n    \"!\", \"~\", \"UNARY_PLUS\", \"UNARY_MINUS\",\n    \"++\", \"--\",\n    \".\",\n    \"[\", \"]\",\n    \"{\", \"}\",\n    \"(\", \")\",\n\n    // Nonterminal tree node type codes.\n    \"SCRIPT\", \"BLOCK\", \"LABEL\", \"FOR_IN\", \"CALL\", \"NEW_WITH_ARGS\", \"INDEX\",\n    \"ARRAY_INIT\", \"OBJECT_INIT\", \"PROPERTY_INIT\", \"GETTER\", \"SETTER\",\n    \"GROUP\", \"LIST\", \"LET_BLOCK\", \"ARRAY_COMP\", \"GENERATOR\", \"COMP_TAIL\",\n\n    // Contextual keywords.\n    \"IMPLEMENTS\", \"INTERFACE\", \"LET\", \"MODULE\", \"PACKAGE\", \"PRIVATE\",\n    \"PROTECTED\", \"PUBLIC\", \"STATIC\", \"USE\", \"YIELD\",\n\n    // Terminals.\n    \"IDENTIFIER\", \"NUMBER\", \"STRING\", \"REGEXP\",\n\n    // Keywords.\n    \"break\",\n    \"case\", \"catch\", \"const\", \"continue\",\n    \"debugger\", \"default\", \"delete\", \"do\",\n    \"else\", \"export\",\n    \"false\", \"finally\", \"for\", \"function\",\n    \"if\", \"import\", \"in\", \"instanceof\",\n    \"new\", \"null\",\n    \"return\",\n    \"switch\",\n    \"this\", \"throw\", \"true\", \"try\", \"typeof\",\n    \"var\", \"void\",\n    \"while\", \"with\",\n];\n\nvar strictKeywords = {\n    __proto__: null,\n    \"implements\": true,\n    \"interface\": true,\n    \"let\": true,\n    //\"module\": true,\n    \"package\": true,\n    \"private\": true,\n    \"protected\": true,\n    \"public\": true,\n    \"static\": true,\n    \"use\": true,\n    \"yield\": true\n};\n\nvar statementStartTokens = [\n    \"break\",\n    \"const\", \"continue\",\n    \"debugger\", \"do\",\n    \"for\",\n    \"if\",\n    \"let\",\n    \"return\",\n    \"switch\",\n    \"throw\", \"try\",\n    \"var\",\n    \"yield\",\n    \"while\", \"with\",\n];\n\n// Whitespace characters (see ECMA-262 7.2)\nvar whitespaceChars = [\n    // normal whitespace:\n    \"\\u0009\", \"\\u000B\", \"\\u000C\", \"\\u0020\", \"\\u00A0\", \"\\uFEFF\",\n\n    // high-Unicode whitespace:\n    \"\\u1680\", \"\\u180E\",\n    \"\\u2000\", \"\\u2001\", \"\\u2002\", \"\\u2003\", \"\\u2004\", \"\\u2005\", \"\\u2006\",\n    \"\\u2007\", \"\\u2008\", \"\\u2009\", \"\\u200A\",\n    \"\\u202F\", \"\\u205F\", \"\\u3000\"\n];\n\nvar whitespace = {};\nfor (var i = 0; i < whitespaceChars.length; i++) {\n    whitespace[whitespaceChars[i]] = true;\n}\n\n// Operator and punctuator mapping from token to tree node type name.\n// NB: because the lexer doesn't backtrack, all token prefixes must themselves\n// be valid tokens (e.g. !== is acceptable because its prefixes are the valid\n// tokens != and !).\nvar opTypeNames = {\n    '\\n':   \"NEWLINE\",\n    ';':    \"SEMICOLON\",\n    ',':    \"COMMA\",\n    '?':    \"HOOK\",\n    ':':    \"COLON\",\n    '||':   \"OR\",\n    '&&':   \"AND\",\n    '|':    \"BITWISE_OR\",\n    '^':    \"BITWISE_XOR\",\n    '&':    \"BITWISE_AND\",\n    '===':  \"STRICT_EQ\",\n    '==':   \"EQ\",\n    '=':    \"ASSIGN\",\n    '!==':  \"STRICT_NE\",\n    '!=':   \"NE\",\n    '<<':   \"LSH\",\n    '<=':   \"LE\",\n    '<':    \"LT\",\n    '>>>':  \"URSH\",\n    '>>':   \"RSH\",\n    '>=':   \"GE\",\n    '>':    \"GT\",\n    '++':   \"INCREMENT\",\n    '--':   \"DECREMENT\",\n    '+':    \"PLUS\",\n    '-':    \"MINUS\",\n    '*':    \"MUL\",\n    '/':    \"DIV\",\n    '%':    \"MOD\",\n    '!':    \"NOT\",\n    '~':    \"BITWISE_NOT\",\n    '.':    \"DOT\",\n    '[':    \"LEFT_BRACKET\",\n    ']':    \"RIGHT_BRACKET\",\n    '{':    \"LEFT_CURLY\",\n    '}':    \"RIGHT_CURLY\",\n    '(':    \"LEFT_PAREN\",\n    ')':    \"RIGHT_PAREN\"\n};\n\n// Hash of keyword identifier to tokens index.  NB: we must null __proto__ to\n// avoid toString, etc. namespace pollution.\nvar keywords = {__proto__: null};\nvar mozillaKeywords = {__proto__: null};\n\n// Define const END, etc., based on the token names.  Also map name to index.\nvar tokenIds = {};\n\nvar hostSupportsEvalConst = (function() {\n    try {\n        return eval(\"(function(s) { eval(s); return x })('const x = true;')\");\n    } catch (e) {\n        return false;\n    }\n})();\n\n// Building up a string to be eval'd in different contexts.\nvar consts = hostSupportsEvalConst ? \"const \" : \"var \";\nfor (var i = 0, j = tokens.length; i < j; i++) {\n    if (i > 0)\n        consts += \", \";\n    var t = tokens[i];\n    var name;\n    if (/^[a-z]/.test(t)) {\n        name = t.toUpperCase();\n        if (name === \"LET\" || name === \"YIELD\")\n            mozillaKeywords[name] = i;\n        if (strictKeywords[name])\n            strictKeywords[name] = i;\n        keywords[t] = i;\n    } else {\n        name = (/^\\W/.test(t) ? opTypeNames[t] : t);\n    }\n    consts += name + \" = \" + i;\n    tokenIds[name] = i;\n    tokens[t] = i;\n}\nconsts += \";\";\n\nvar isStatementStartCode = {__proto__: null};\nfor (i = 0, j = statementStartTokens.length; i < j; i++)\n    isStatementStartCode[keywords[statementStartTokens[i]]] = true;\n\n// Map assignment operators to their indexes in the tokens array.\nvar assignOps = ['|', '^', '&', '<<', '>>', '>>>', '+', '-', '*', '/', '%'];\n\nfor (i = 0, j = assignOps.length; i < j; i++) {\n    t = assignOps[i];\n    assignOps[t] = tokens[t];\n}\n\nfunction defineGetter(obj, prop, fn, dontDelete, dontEnum) {\n    Object.defineProperty(obj, prop,\n                          { get: fn, configurable: !dontDelete, enumerable: !dontEnum });\n}\n\nfunction defineGetterSetter(obj, prop, getter, setter, dontDelete, dontEnum) {\n    Object.defineProperty(obj, prop, {\n        get: getter,\n        set: setter,\n        configurable: !dontDelete,\n        enumerable: !dontEnum\n    });\n}\n\nfunction defineMemoGetter(obj, prop, fn, dontDelete, dontEnum) {\n    Object.defineProperty(obj, prop, {\n        get: function() {\n            var val = fn();\n            defineProperty(obj, prop, val, dontDelete, true, dontEnum);\n            return val;\n        },\n        configurable: true,\n        enumerable: !dontEnum\n    });\n}\n\nfunction defineProperty(obj, prop, val, dontDelete, readOnly, dontEnum) {\n    Object.defineProperty(obj, prop,\n                          { value: val, writable: !readOnly, configurable: !dontDelete,\n                            enumerable: !dontEnum });\n}\n\n// Returns true if fn is a native function.  (Note: SpiderMonkey specific.)\nfunction isNativeCode(fn) {\n    // Relies on the toString method to identify native code.\n    return ((typeof fn) === \"function\") && fn.toString().match(/\\[native code\\]/);\n}\n\nvar Fpapply = Function.prototype.apply;\n\nfunction apply(f, o, a) {\n    return Fpapply.call(f, [o].concat(a));\n}\n\nvar applyNew;\n\n// ES5's bind is a simpler way to implement applyNew\nif (Function.prototype.bind) {\n    applyNew = function applyNew(f, a) {\n        return new (f.bind.apply(f, [,].concat(Array.prototype.slice.call(a))))();\n    };\n} else {\n    applyNew = function applyNew(f, a) {\n        switch (a.length) {\n          case 0:\n            return new f();\n          case 1:\n            return new f(a[0]);\n          case 2:\n            return new f(a[0], a[1]);\n          case 3:\n            return new f(a[0], a[1], a[2]);\n          default:\n            var argStr = \"a[0]\";\n            for (var i = 1, n = a.length; i < n; i++)\n                argStr += \",a[\" + i + \"]\";\n            return eval(\"new f(\" + argStr + \")\");\n        }\n    };\n}\n\nfunction getPropertyDescriptor(obj, name) {\n    while (obj) {\n        if (({}).hasOwnProperty.call(obj, name))\n            return Object.getOwnPropertyDescriptor(obj, name);\n        obj = Object.getPrototypeOf(obj);\n    }\n}\n\nfunction getPropertyNames(obj) {\n    var table = Object.create(null, {});\n    while (obj) {\n        var names = Object.getOwnPropertyNames(obj);\n        for (var i = 0, n = names.length; i < n; i++)\n            table[names[i]] = true;\n        obj = Object.getPrototypeOf(obj);\n    }\n    return Object.keys(table);\n}\n\nfunction getOwnProperties(obj) {\n    var map = {};\n    for (var name in Object.getOwnPropertyNames(obj))\n        map[name] = Object.getOwnPropertyDescriptor(obj, name);\n    return map;\n}\n\n/*\n * Mixin proxies break the single-inheritance model of prototypes, so\n * the handler treats all properties as own-properties:\n *\n *                  X\n *                  |\n *     +------------+------------+\n *     |                 O       |\n *     |                 |       |\n *     |  O         O    O       |\n *     |  |         |    |       |\n *     |  O    O    O    O       |\n *     |  |    |    |    |       |\n *     |  O    O    O    O    O  |\n *     |  |    |    |    |    |  |\n *     +-(*)--(w)--(x)--(y)--(z)-+\n */\n\nfunction mixinHandler(redirect, catchall) {\n    function targetFor(name) {\n        return hasOwn(redirect, name) ? redirect[name] : catchall;\n    }\n\n    function getMuxPropertyDescriptor(name) {\n        var desc = getPropertyDescriptor(targetFor(name), name);\n        if (desc)\n            desc.configurable = true;\n        return desc;\n    }\n\n    function getMuxPropertyNames() {\n        var names1 = Object.getOwnPropertyNames(redirect).filter(function(name) {\n            return name in redirect[name];\n        });\n        var names2 = getPropertyNames(catchall).filter(function(name) {\n            return !hasOwn(redirect, name);\n        });\n        return names1.concat(names2);\n    }\n\n    function enumerateMux() {\n        var result = Object.getOwnPropertyNames(redirect).filter(function(name) {\n            return name in redirect[name];\n        });\n        for (name in catchall) {\n            if (!hasOwn(redirect, name))\n                result.push(name);\n        };\n        return result;\n    }\n\n    function hasMux(name) {\n        return name in targetFor(name);\n    }\n\n    return {\n        getOwnPropertyDescriptor: getMuxPropertyDescriptor,\n        getPropertyDescriptor: getMuxPropertyDescriptor,\n        getOwnPropertyNames: getMuxPropertyNames,\n        defineProperty: function(name, desc) {\n            Object.defineProperty(targetFor(name), name, desc);\n        },\n        \"delete\": function(name) {\n            var target = targetFor(name);\n            return delete target[name];\n        },\n        // FIXME: ha ha ha\n        fix: function() { },\n        has: hasMux,\n        hasOwn: hasMux,\n        get: function(receiver, name) {\n            var target = targetFor(name);\n            return target[name];\n        },\n        set: function(receiver, name, val) {\n            var target = targetFor(name);\n            target[name] = val;\n            return true;\n        },\n        enumerate: enumerateMux,\n        keys: enumerateMux\n    };\n}\n\nfunction makePassthruHandler(obj) {\n    // Handler copied from\n    // http://wiki.ecmascript.org/doku.php?id=harmony:proxies&s=proxy%20object#examplea_no-op_forwarding_proxy\n    return {\n        getOwnPropertyDescriptor: function(name) {\n            var desc = Object.getOwnPropertyDescriptor(obj, name);\n\n            // a trapping proxy's properties must always be configurable\n            desc.configurable = true;\n            return desc;\n        },\n        getPropertyDescriptor: function(name) {\n            var desc = getPropertyDescriptor(obj, name);\n\n            // a trapping proxy's properties must always be configurable\n            desc.configurable = true;\n            return desc;\n        },\n        getOwnPropertyNames: function() {\n            return Object.getOwnPropertyNames(obj);\n        },\n        defineProperty: function(name, desc) {\n            Object.defineProperty(obj, name, desc);\n        },\n        \"delete\": function(name) { return delete obj[name]; },\n        fix: function() {\n            if (Object.isFrozen(obj)) {\n                return getOwnProperties(obj);\n            }\n\n            // As long as obj is not frozen, the proxy won't allow itself to be fixed.\n            return undefined; // will cause a TypeError to be thrown\n        },\n\n        has: function(name) { return name in obj; },\n        hasOwn: function(name) { return ({}).hasOwnProperty.call(obj, name); },\n        get: function(receiver, name) { return obj[name]; },\n\n        // bad behavior when set fails in non-strict mode\n        set: function(receiver, name, val) { obj[name] = val; return true; },\n        enumerate: function() {\n            var result = [];\n            for (name in obj) { result.push(name); };\n            return result;\n        },\n        keys: function() { return Object.keys(obj); }\n    };\n}\n\nvar hasOwnProperty = ({}).hasOwnProperty;\n\nfunction hasOwn(obj, name) {\n    return hasOwnProperty.call(obj, name);\n}\n\nfunction Dict(table, size) {\n    this.table = table || Object.create(null, {});\n    this.size = size || 0;\n}\n\nDict.create = function(table) {\n    var init = Object.create(null, {});\n    var size = 0;\n    var names = Object.getOwnPropertyNames(table);\n    for (var i = 0, n = names.length; i < n; i++) {\n        var name = names[i];\n        init[name] = table[name];\n        size++;\n    }\n    return new Dict(init, size);\n};\n\nDict.prototype = {\n    has: function(x) { return hasOwnProperty.call(this.table, x); },\n    set: function(x, v) {\n        if (!hasOwnProperty.call(this.table, x))\n            this.size++;\n        this.table[x] = v;\n    },\n    get: function(x) { return this.table[x]; },\n    getDef: function(x, thunk) {\n        if (!hasOwnProperty.call(this.table, x)) {\n            this.size++;\n            this.table[x] = thunk();\n        }\n        return this.table[x];\n    },\n    forEach: function(f) {\n        var table = this.table;\n        for (var key in table)\n            f.call(this, key, table[key]);\n    },\n    map: function(f) {\n        var table1 = this.table;\n        var table2 = Object.create(null, {});\n        this.forEach(function(key, val) {\n            table2[key] = f.call(this, val, key);\n        });\n        return new Dict(table2, this.size);\n    },\n    mapObject: function(f) {\n        var table1 = this.table;\n        var table2 = Object.create(null, {});\n        this.forEach(function(key, val) {\n            table2[key] = f.call(this, val, key);\n        });\n        return table2;\n    },\n    toObject: function() {\n        return this.mapObject(function(val) { return val; });\n    },\n    choose: function() {\n        return Object.getOwnPropertyNames(this.table)[0];\n    },\n    remove: function(x) {\n        if (hasOwnProperty.call(this.table, x)) {\n            this.size--;\n            delete this.table[x];\n        }\n    },\n    copy: function() {\n        var table = Object.create(null, {});\n        for (var key in this.table)\n            table[key] = this.table[key];\n        return new Dict(table, this.size);\n    },\n    keys: function() {\n        return Object.keys(this.table);\n    },\n    toString: function() { return \"[object Dict]\" }\n};\n\nvar _WeakMap = typeof WeakMap === \"function\" ? WeakMap : (function() {\n    // shim for ES6 WeakMap with poor asymptotics\n    function WeakMap(array) {\n        this.array = array || [];\n    }\n\n    function searchMap(map, key, found, notFound) {\n        var a = map.array;\n        for (var i = 0, n = a.length; i < n; i++) {\n            var pair = a[i];\n            if (pair.key === key)\n                return found(pair, i);\n        }\n        return notFound();\n    }\n\n    WeakMap.prototype = {\n        has: function(x) {\n            return searchMap(this, x, function() { return true }, function() { return false });\n        },\n        set: function(x, v) {\n            var a = this.array;\n            searchMap(this, x,\n                      function(pair) { pair.value = v },\n                      function() { a.push({ key: x, value: v }) });\n        },\n        get: function(x) {\n            return searchMap(this, x,\n                             function(pair) { return pair.value },\n                             function() { return null });\n        },\n        \"delete\": function(x) {\n            var a = this.array;\n            searchMap(this, x,\n                      function(pair, i) { a.splice(i, 1) },\n                      function() { });\n        },\n        toString: function() { return \"[object WeakMap]\" }\n    };\n\n    return WeakMap;\n})();\n\n// non-destructive stack\nfunction Stack(elts) {\n    this.elts = elts || null;\n}\n\nStack.prototype = {\n    push: function(x) {\n        return new Stack({ top: x, rest: this.elts });\n    },\n    top: function() {\n        if (!this.elts)\n            throw new Error(\"empty stack\");\n        return this.elts.top;\n    },\n    isEmpty: function() {\n        return this.top === null;\n    },\n    find: function(test) {\n        for (var elts = this.elts; elts; elts = elts.rest) {\n            if (test(elts.top))\n                return elts.top;\n        }\n        return null;\n    },\n    has: function(x) {\n        return Boolean(this.find(function(elt) { return elt === x }));\n    },\n    forEach: function(f) {\n        for (var elts = this.elts; elts; elts = elts.rest) {\n            f(elts.top);\n        }\n    }\n};\n\nif (!Array.prototype.copy) {\n    defineProperty(Array.prototype, \"copy\",\n                   function() {\n                       var result = [];\n                       for (var i = 0, n = this.length; i < n; i++)\n                           result[i] = this[i];\n                       return result;\n                   }, false, false, true);\n}\n\nif (!Array.prototype.top) {\n    defineProperty(Array.prototype, \"top\",\n                   function() {\n                       return this.length && this[this.length-1];\n                   }, false, false, true);\n}\n\nexports.tokens = tokens;\nexports.whitespace = whitespace;\nexports.opTypeNames = opTypeNames;\nexports.keywords = keywords;\nexports.mozillaKeywords = mozillaKeywords;\nexports.strictKeywords = strictKeywords;\nexports.isStatementStartCode = isStatementStartCode;\nexports.tokenIds = tokenIds;\nexports.consts = consts;\nexports.assignOps = assignOps;\nexports.defineGetter = defineGetter;\nexports.defineGetterSetter = defineGetterSetter;\nexports.defineMemoGetter = defineMemoGetter;\nexports.defineProperty = defineProperty;\nexports.isNativeCode = isNativeCode;\nexports.apply = apply;\nexports.applyNew = applyNew;\nexports.mixinHandler = mixinHandler;\nexports.makePassthruHandler = makePassthruHandler;\nexports.Dict = Dict;\nexports.WeakMap = _WeakMap;\nexports.Stack = Stack;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/narcissus/lexer.js",
    "content": "/* vim: set sw=4 ts=4 et tw=78: */\n/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is the Narcissus JavaScript engine.\n *\n * The Initial Developer of the Original Code is\n * Brendan Eich <brendan@mozilla.org>.\n * Portions created by the Initial Developer are Copyright (C) 2004\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *   Tom Austin <taustin@ucsc.edu>\n *   Brendan Eich <brendan@mozilla.org>\n *   Shu-Yu Guo <shu@rfrn.org>\n *   Stephan Herhut <stephan.a.herhut@intel.com>\n *   Dave Herman <dherman@mozilla.com>\n *   Dimitris Vardoulakis <dimvar@ccs.neu.edu>\n *   Patrick Walton <pcwalton@mozilla.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\n/*\n * Narcissus - JS implemented in JS.\n *\n * Lexical scanner.\n */\n\n define(function(require, exports, module) {\n\nvar definitions = require('./definitions');\n\n// Set constants in the local scope.\neval(definitions.consts);\n\n// Build up a trie of operator tokens.\nvar opTokens = {};\nfor (var op in definitions.opTypeNames) {\n    if (op === '\\n' || op === '.')\n        continue;\n\n    var node = opTokens;\n    for (var i = 0; i < op.length; i++) {\n        var ch = op[i];\n        if (!(ch in node))\n            node[ch] = {};\n        node = node[ch];\n        node.op = op;\n    }\n}\n\n/*\n * Since JavaScript provides no convenient way to determine if a\n * character is in a particular Unicode category, we use\n * metacircularity to accomplish this (oh yeaaaah!)\n */\nfunction isValidIdentifierChar(ch, first) {\n    // check directly for ASCII\n    if (ch <= \"\\u007F\") {\n        if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch === '$' || ch === '_' ||\n            (!first && (ch >= '0' && ch <= '9'))) {\n            return true;\n        }\n        return false;\n    }\n\n    // create an object to test this in\n    var x = {};\n    x[\"x\"+ch] = true;\n    x[ch] = true;\n\n    // then use eval to determine if it's a valid character\n    var valid = false;\n    try {\n        valid = (Function(\"x\", \"return (x.\" + (first?\"\":\"x\") + ch + \");\")(x) === true);\n    } catch (ex) {}\n\n    return valid;\n}\n\nfunction isIdentifier(str) {\n    if (typeof str !== \"string\")\n        return false;\n\n    if (str.length === 0)\n        return false;\n\n    if (!isValidIdentifierChar(str[0], true))\n        return false;\n\n    for (var i = 1; i < str.length; i++) {\n        if (!isValidIdentifierChar(str[i], false))\n            return false;\n    }\n\n    return true;\n}\n\n/*\n * Tokenizer :: (source, filename, line number, boolean) -> Tokenizer\n */\nfunction Tokenizer(s, f, l, allowHTMLComments) {\n    this.cursor = 0;\n    this.source = String(s);\n    this.tokens = [];\n    this.tokenIndex = 0;\n    this.lookahead = 0;\n    this.scanNewlines = false;\n    this.filename = f || \"\";\n    this.lineno = l || 1;\n    this.allowHTMLComments = allowHTMLComments;\n    this.blockComments = null;\n}\n\nTokenizer.prototype = {\n    get done() {\n        // We need to set scanOperand to true here because the first thing\n        // might be a regexp.\n        return this.peek(true) === END;\n    },\n\n    get token() {\n        return this.tokens[this.tokenIndex];\n    },\n\n    match: function (tt, scanOperand, keywordIsName) {\n        return this.get(scanOperand, keywordIsName) === tt || this.unget();\n    },\n\n    mustMatch: function (tt, keywordIsName) {\n        if (!this.match(tt, false, keywordIsName)) {\n            throw this.newSyntaxError(\"Missing \" +\n                                      definitions.tokens[tt].toLowerCase());\n        }\n        return this.token;\n    },\n\n    peek: function (scanOperand) {\n        var tt, next;\n        if (this.lookahead) {\n            next = this.tokens[(this.tokenIndex + this.lookahead) & 3];\n            tt = (this.scanNewlines && next.lineno !== this.lineno)\n                ? NEWLINE\n                : next.type;\n        } else {\n            tt = this.get(scanOperand);\n            this.unget();\n        }\n        return tt;\n    },\n\n    peekOnSameLine: function (scanOperand) {\n        this.scanNewlines = true;\n        var tt = this.peek(scanOperand);\n        this.scanNewlines = false;\n        return tt;\n    },\n\n    lastBlockComment: function() {\n        var length = this.blockComments.length;\n        return length ? this.blockComments[length - 1] : null;\n    },\n\n    // Eat comments and whitespace.\n    skip: function () {\n        var input = this.source;\n        this.blockComments = [];\n        for (;;) {\n            var ch = input[this.cursor++];\n            var next = input[this.cursor];\n            // handle \\r, \\r\\n and (always preferable) \\n\n            if (ch === '\\r') {\n                // if the next character is \\n, we don't care about this at all\n                if (next === '\\n') continue;\n\n                // otherwise, we want to consider this as a newline\n                ch = '\\n';\n            }\n\n            if (ch === '\\n' && !this.scanNewlines) {\n                this.lineno++;\n            } else if (ch === '/' && next === '*') {\n                var commentStart = ++this.cursor;\n                for (;;) {\n                    ch = input[this.cursor++];\n                    if (ch === undefined)\n                        throw this.newSyntaxError(\"Unterminated comment\");\n\n                    if (ch === '*') {\n                        next = input[this.cursor];\n                        if (next === '/') {\n                            var commentEnd = this.cursor - 1;\n                            this.cursor++;\n                            break;\n                        }\n                    } else if (ch === '\\n') {\n                        this.lineno++;\n                    }\n                }\n                this.blockComments.push(input.substring(commentStart, commentEnd));\n            } else if ((ch === '/' && next === '/') ||\n                       (this.allowHTMLComments && ch === '<' && next === '!' &&\n                        input[this.cursor + 1] === '-' && input[this.cursor + 2] === '-' &&\n                        (this.cursor += 2))) {\n                this.cursor++;\n                for (;;) {\n                    ch = input[this.cursor++];\n                    next = input[this.cursor];\n                    if (ch === undefined)\n                        return;\n\n                    if (ch === '\\r') {\n                        // check for \\r\\n\n                        if (next !== '\\n') ch = '\\n';\n                    }\n\n                    if (ch === '\\n') {\n                        if (this.scanNewlines) {\n                            this.cursor--;\n                        } else {\n                            this.lineno++;\n                        }\n                        break;\n                    }\n                }\n            } else if (!(ch in definitions.whitespace)) {\n                this.cursor--;\n                return;\n            }\n        }\n    },\n\n    // Lex the exponential part of a number, if present. Return true iff an\n    // exponential part was found.\n    lexExponent: function() {\n        var input = this.source;\n        var next = input[this.cursor];\n        if (next === 'e' || next === 'E') {\n            this.cursor++;\n            ch = input[this.cursor++];\n            if (ch === '+' || ch === '-')\n                ch = input[this.cursor++];\n\n            if (ch < '0' || ch > '9')\n                throw this.newSyntaxError(\"Missing exponent\");\n\n            do {\n                ch = input[this.cursor++];\n            } while (ch >= '0' && ch <= '9');\n            this.cursor--;\n\n            return true;\n        }\n\n        return false;\n    },\n\n    lexZeroNumber: function (ch) {\n        var token = this.token, input = this.source;\n        token.type = NUMBER;\n\n        ch = input[this.cursor++];\n        if (ch === '.') {\n            do {\n                ch = input[this.cursor++];\n            } while (ch >= '0' && ch <= '9');\n            this.cursor--;\n\n            this.lexExponent();\n            token.value = parseFloat(\n                input.substring(token.start, this.cursor));\n        } else if (ch === 'x' || ch === 'X') {\n            do {\n                ch = input[this.cursor++];\n            } while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') ||\n                     (ch >= 'A' && ch <= 'F'));\n            this.cursor--;\n\n            token.value = parseInt(input.substring(token.start, this.cursor));\n        } else if (ch >= '0' && ch <= '7') {\n            do {\n                ch = input[this.cursor++];\n            } while (ch >= '0' && ch <= '7');\n            this.cursor--;\n\n            token.value = parseInt(input.substring(token.start, this.cursor));\n        } else {\n            this.cursor--;\n            this.lexExponent();     // 0E1, &c.\n            token.value = 0;\n        }\n    },\n\n    lexNumber: function (ch) {\n        var token = this.token, input = this.source;\n        token.type = NUMBER;\n\n        var floating = false;\n        do {\n            ch = input[this.cursor++];\n            if (ch === '.' && !floating) {\n                floating = true;\n                ch = input[this.cursor++];\n            }\n        } while (ch >= '0' && ch <= '9');\n\n        this.cursor--;\n\n        var exponent = this.lexExponent();\n        floating = floating || exponent;\n\n        var str = input.substring(token.start, this.cursor);\n        token.value = floating ? parseFloat(str) : parseInt(str);\n    },\n\n    lexDot: function (ch) {\n        var token = this.token, input = this.source;\n        var next = input[this.cursor];\n        if (next >= '0' && next <= '9') {\n            do {\n                ch = input[this.cursor++];\n            } while (ch >= '0' && ch <= '9');\n            this.cursor--;\n\n            this.lexExponent();\n\n            token.type = NUMBER;\n            token.value = parseFloat(\n                input.substring(token.start, this.cursor));\n        } else {\n            token.type = DOT;\n            token.assignOp = null;\n            token.value = '.';\n        }\n    },\n\n    lexString: function (ch) {\n        var token = this.token, input = this.source;\n        token.type = STRING;\n\n        var hasEscapes = false;\n        var delim = ch;\n        if (input.length <= this.cursor)\n            throw this.newSyntaxError(\"Unterminated string literal\");\n        while ((ch = input[this.cursor++]) !== delim) {\n            if (ch == '\\n' || ch == '\\r')\n                throw this.newSyntaxError(\"Unterminated string literal\");\n            if (this.cursor == input.length)\n                throw this.newSyntaxError(\"Unterminated string literal\");\n            if (ch === '\\\\') {\n                hasEscapes = true;\n                if (++this.cursor == input.length)\n                    throw this.newSyntaxError(\"Unterminated string literal\");\n            }\n        }\n\n        token.value = hasEscapes\n            ? eval(input.substring(token.start, this.cursor))\n            : input.substring(token.start + 1, this.cursor - 1);\n    },\n\n    lexRegExp: function (ch) {\n        var token = this.token, input = this.source;\n        token.type = REGEXP;\n\n        do {\n            ch = input[this.cursor++];\n            if (ch === '\\\\') {\n                this.cursor++;\n            } else if (ch === '[') {\n                do {\n                    if (ch === undefined)\n                        throw this.newSyntaxError(\"Unterminated character class\");\n\n                    if (ch === '\\\\')\n                        this.cursor++;\n\n                    ch = input[this.cursor++];\n                } while (ch !== ']');\n            } else if (ch === undefined) {\n                throw this.newSyntaxError(\"Unterminated regex\");\n            }\n        } while (ch !== '/');\n\n        do {\n            ch = input[this.cursor++];\n        } while (ch >= 'a' && ch <= 'z');\n\n        this.cursor--;\n\n        token.value = eval(input.substring(token.start, this.cursor));\n    },\n\n    lexOp: function (ch) {\n        var token = this.token, input = this.source;\n\n        // A bit ugly, but it seems wasteful to write a trie lookup routine\n        // for only 3 characters...\n        var node = opTokens[ch];\n        var next = input[this.cursor];\n        if (next in node) {\n            node = node[next];\n            this.cursor++;\n            next = input[this.cursor];\n            if (next in node) {\n                node = node[next];\n                this.cursor++;\n                next = input[this.cursor];\n            }\n        }\n\n        var op = node.op;\n        if (definitions.assignOps[op] && input[this.cursor] === '=') {\n            this.cursor++;\n            token.type = ASSIGN;\n            token.assignOp = definitions.tokenIds[definitions.opTypeNames[op]];\n            op += '=';\n        } else {\n            token.type = definitions.tokenIds[definitions.opTypeNames[op]];\n            token.assignOp = null;\n        }\n\n        token.value = op;\n    },\n\n    // FIXME: Unicode escape sequences\n    lexIdent: function (ch, keywordIsName) {\n        var token = this.token;\n        var id = ch;\n\n        while ((ch = this.getValidIdentifierChar(false)) !== null) {\n            id += ch;\n        }\n\n        token.type = IDENTIFIER;\n        token.value = id;\n\n        if (keywordIsName)\n            return;\n\n        var kw;\n\n        if (this.parser.mozillaMode) {\n            kw = definitions.mozillaKeywords[id];\n            if (kw) {\n                token.type = kw;\n                return;\n            }\n        }\n\n        if (this.parser.x.strictMode) {\n            kw = definitions.strictKeywords[id];\n            if (kw) {\n                token.type = kw;\n                return;\n            }\n        }\n\n        kw = definitions.keywords[id];\n        if (kw)\n            token.type = kw;\n    },\n\n    /*\n     * Tokenizer.get :: ([boolean[, boolean]]) -> token type\n     *\n     * Consume input *only* if there is no lookahead.\n     * Dispatch to the appropriate lexing function depending on the input.\n     */\n    get: function (scanOperand, keywordIsName) {\n        var token;\n        while (this.lookahead) {\n            --this.lookahead;\n            this.tokenIndex = (this.tokenIndex + 1) & 3;\n            token = this.tokens[this.tokenIndex];\n            if (token.type !== NEWLINE || this.scanNewlines)\n                return token.type;\n        }\n\n        this.skip();\n\n        this.tokenIndex = (this.tokenIndex + 1) & 3;\n        token = this.tokens[this.tokenIndex];\n        if (!token)\n            this.tokens[this.tokenIndex] = token = {};\n\n        var input = this.source;\n        if (this.cursor >= input.length)\n            return token.type = END;\n\n        token.start = this.cursor;\n        token.lineno = this.lineno;\n\n        var ich = this.getValidIdentifierChar(true);\n        var ch = (ich === null) ? input[this.cursor++] : null;\n        if (ich !== null) {\n            this.lexIdent(ich, keywordIsName);\n        } else if (scanOperand && ch === '/') {\n            this.lexRegExp(ch);\n        } else if (ch in opTokens) {\n            this.lexOp(ch);\n        } else if (ch === '.') {\n            this.lexDot(ch);\n        } else if (ch >= '1' && ch <= '9') {\n            this.lexNumber(ch);\n        } else if (ch === '0') {\n            this.lexZeroNumber(ch);\n        } else if (ch === '\"' || ch === \"'\") {\n            this.lexString(ch);\n        } else if (this.scanNewlines && (ch === '\\n' || ch === '\\r')) {\n            // if this was a \\r, look for \\r\\n\n            if (ch === '\\r' && input[this.cursor] === '\\n') this.cursor++;\n            token.type = NEWLINE;\n            token.value = '\\n';\n            this.lineno++;\n        } else {\n            throw this.newSyntaxError(\"Illegal token\");\n        }\n\n        token.end = this.cursor;\n        return token.type;\n    },\n\n    /*\n     * Tokenizer.unget :: void -> undefined\n     *\n     * Match depends on unget returning undefined.\n     */\n    unget: function () {\n        if (++this.lookahead === 4) throw \"PANIC: too much lookahead!\";\n        this.tokenIndex = (this.tokenIndex - 1) & 3;\n    },\n\n    newSyntaxError: function (m) {\n        m = (this.filename ? this.filename + \":\" : \"\") + this.lineno + \": \" + m;\n        var e = new SyntaxError(m, this.filename, this.lineno);\n        e.source = this.source;\n        e.cursor = this.lookahead\n            ? this.tokens[(this.tokenIndex + this.lookahead) & 3].start\n            : this.cursor;\n        return e;\n    },\n\n\n    /* Gets a single valid identifier char from the input stream, or null\n     * if there is none.\n     */\n    getValidIdentifierChar: function(first) {\n        var input = this.source;\n        if (this.cursor >= input.length) return null;\n        var ch = input[this.cursor];\n\n        // first check for \\u escapes\n        if (ch === '\\\\' && input[this.cursor+1] === 'u') {\n            // get the character value\n            try {\n                ch = String.fromCharCode(parseInt(\n                    input.substring(this.cursor + 2, this.cursor + 6),\n                    16));\n            } catch (ex) {\n                return null;\n            }\n            this.cursor += 5;\n        }\n\n        var valid = isValidIdentifierChar(ch, first);\n        if (valid) this.cursor++;\n        return (valid ? ch : null);\n    },\n};\n\n\nexports.isIdentifier = isIdentifier;\nexports.Tokenizer = Tokenizer;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/narcissus/options.js",
    "content": "/* vim: set sw=4 ts=4 et tw=78: */\n/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is the Narcissus JavaScript engine.\n *\n * The Initial Developer of the Original Code is\n * Brendan Eich <brendan@mozilla.org>.\n * Portions created by the Initial Developer are Copyright (C) 2004\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *   Tom Austin <taustin@ucsc.edu>\n *   Brendan Eich <brendan@mozilla.org>\n *   Shu-Yu Guo <shu@rfrn.org>\n *   Dave Herman <dherman@mozilla.com>\n *   Dimitris Vardoulakis <dimvar@ccs.neu.edu>\n *   Patrick Walton <pcwalton@mozilla.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\n// Global variables to hide from the interpreter\nexports.hiddenHostGlobals = { Narcissus: true };\n\n// Desugar SpiderMonkey language extensions?\nexports.desugarExtensions = false;\n\n// Allow HTML comments?\nexports.allowHTMLComments = false;\n\n// Allow non-standard Mozilla extensions?\nexports.mozillaMode = true;\n\n// Allow experimental paren-free mode?\nexports.parenFreeMode = false;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/narcissus/parser.js",
    "content": "/* -*- Mode: JS; tab-width: 4; indent-tabs-mode: nil; -*-\n * vim: set sw=4 ts=4 et tw=78:\n * ***** BEGIN LICENSE BLOCK *****\n *\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is the Narcissus JavaScript engine.\n *\n * The Initial Developer of the Original Code is\n * Brendan Eich <brendan@mozilla.org>.\n * Portions created by the Initial Developer are Copyright (C) 2004\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *   Tom Austin <taustin@ucsc.edu>\n *   Brendan Eich <brendan@mozilla.org>\n *   Shu-Yu Guo <shu@rfrn.org>\n *   Dave Herman <dherman@mozilla.com>\n *   Dimitris Vardoulakis <dimvar@ccs.neu.edu>\n *   Patrick Walton <pcwalton@mozilla.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\n/*\n * Narcissus - JS implemented in JS.\n *\n * Parser.\n */\n\ndefine(function(require, exports, module) {\n\nvar lexer = require('./lexer');\nvar definitions = require('./definitions');\nvar options = require('./options');\nvar Tokenizer = lexer.Tokenizer;\n\nvar Dict = definitions.Dict;\nvar Stack = definitions.Stack;\n\n// Set constants in the local scope.\neval(definitions.consts);\n\n/*\n * pushDestructuringVarDecls :: (node, hoisting node) -> void\n *\n * Recursively add all destructured declarations to varDecls.\n */\nfunction pushDestructuringVarDecls(n, s) {\n    for (var i in n) {\n        var sub = n[i];\n        if (sub.type === IDENTIFIER) {\n            s.varDecls.push(sub);\n        } else {\n            pushDestructuringVarDecls(sub, s);\n        }\n    }\n}\n\nfunction Parser(tokenizer) {\n    tokenizer.parser = this;\n    this.t = tokenizer;\n    this.x = null;\n    this.unexpectedEOF = false;\n    options.mozillaMode && (this.mozillaMode = true);\n    options.parenFreeMode && (this.parenFreeMode = true);\n}\n\nfunction StaticContext(parentScript, parentBlock, inModule, inFunction, strictMode) {\n    this.parentScript = parentScript;\n    this.parentBlock = parentBlock || parentScript;\n    this.inModule = inModule || false;\n    this.inFunction = inFunction || false;\n    this.inForLoopInit = false;\n    this.topLevel = true;\n    this.allLabels = new Stack();\n    this.currentLabels = new Stack();\n    this.labeledTargets = new Stack();\n    this.defaultLoopTarget = null;\n    this.defaultTarget = null;\n    this.strictMode = strictMode;\n}\n\nStaticContext.prototype = {\n    // non-destructive update via prototype extension\n    update: function(ext) {\n        var desc = {};\n        for (var key in ext) {\n            desc[key] = {\n                value: ext[key],\n                writable: true,\n                enumerable: true,\n                configurable: true\n            }\n        }\n        return Object.create(this, desc);\n    },\n    pushLabel: function(label) {\n        return this.update({ currentLabels: this.currentLabels.push(label),\n                             allLabels: this.allLabels.push(label) });\n    },\n    pushTarget: function(target) {\n        var isDefaultLoopTarget = target.isLoop;\n        var isDefaultTarget = isDefaultLoopTarget || target.type === SWITCH;\n\n        if (this.currentLabels.isEmpty()) {\n            if (isDefaultLoopTarget) this.update({ defaultLoopTarget: target });\n            if (isDefaultTarget) this.update({ defaultTarget: target });\n            return this;\n        }\n\n        target.labels = new Dict();\n        this.currentLabels.forEach(function(label) {\n            target.labels.set(label, true);\n        });\n        return this.update({ currentLabels: new Stack(),\n                             labeledTargets: this.labeledTargets.push(target),\n                             defaultLoopTarget: isDefaultLoopTarget\n                             ? target\n                             : this.defaultLoopTarget,\n                             defaultTarget: isDefaultTarget\n                             ? target\n                             : this.defaultTarget });\n    },\n    nest: function() {\n        return this.topLevel ? this.update({ topLevel: false }) : this;\n    },\n    canImport: function() {\n        return this.topLevel && !this.inFunction;\n    },\n    canExport: function() {\n        return this.inModule && this.topLevel && !this.inFunction;\n    },\n    banWith: function() {\n        return this.strictMode || this.inModule;\n    },\n    modulesAllowed: function() {\n        return this.topLevel && !this.inFunction;\n    }\n};\n\nvar Pp = Parser.prototype;\n\nPp.mozillaMode = false;\n\nPp.parenFreeMode = false;\n\nPp.withContext = function(x, f) {\n    var x0 = this.x;\n    this.x = x;\n    var result = f.call(this);\n    // NB: we don't bother with finally, since exceptions trash the parser\n    this.x = x0;\n    return result;\n};\n\nPp.newNode = function newNode(opts) {\n    return new Node(this.t, opts);\n};\n\nPp.fail = function fail(msg) {\n    throw this.t.newSyntaxError(msg);\n};\n\nPp.match = function match(tt, scanOperand, keywordIsName) {\n    return this.t.match(tt, scanOperand, keywordIsName);\n};\n\nPp.mustMatch = function mustMatch(tt, keywordIsName) {\n    return this.t.mustMatch(tt, keywordIsName);\n};\n\nPp.peek = function peek(scanOperand) {\n    return this.t.peek(scanOperand);\n};\n\nPp.peekOnSameLine = function peekOnSameLine(scanOperand) {\n    return this.t.peekOnSameLine(scanOperand);\n};\n\nPp.done = function done() {\n    return this.t.done;\n};\n\n/*\n * Script :: (boolean, boolean, boolean) -> node\n *\n * Parses the toplevel and module/function bodies.\n */\nPp.Script = function Script(inModule, inFunction, expectEnd) {\n    var node = this.newNode(scriptInit());\n    var x2 = new StaticContext(node, node, inModule, inFunction);\n    this.withContext(x2, function() {\n        this.Statements(node, true);\n    });\n    if (expectEnd && !this.done())\n        this.fail(\"expected end of input\");\n    return node;\n};\n\n/*\n * Pragma :: (expression statement node) -> boolean\n *\n * Checks whether a node is a pragma and annotates it.\n */\nfunction Pragma(n) {\n    if (n.type === SEMICOLON) {\n        var e = n.expression;\n        if (e.type === STRING && e.value === \"use strict\") {\n            n.pragma = \"strict\";\n            return true;\n        }\n    }\n    return false;\n}\n\n/*\n * Node :: (tokenizer, optional init object) -> node\n */\nfunction Node(t, init) {\n    var token = t.token;\n    if (token) {\n        // If init.type exists it will override token.type.\n        this.type = token.type;\n        this.value = token.value;\n        this.lineno = token.lineno;\n\n        // Start and end are file positions for error handling.\n        this.start = token.start;\n        this.end = token.end;\n    } else {\n        this.lineno = t.lineno;\n    }\n\n    this.filename = t.filename;\n    this.children = [];\n\n    for (var prop in init)\n        this[prop] = init[prop];\n}\n\n/*\n * SyntheticNode :: (optional init object) -> node\n */\nfunction SyntheticNode(init) {\n    this.children = [];\n    for (var prop in init)\n        this[prop] = init[prop];\n    this.synthetic = true;\n}\n\nvar Np = Node.prototype = SyntheticNode.prototype = {};\nNp.constructor = Node;\n\nvar TO_SOURCE_SKIP = {\n    type: true,\n    value: true,\n    lineno: true,\n    start: true,\n    end: true,\n    tokenizer: true,\n    assignOp: true\n};\nfunction unevalableConst(code) {\n    var token = definitions.tokens[code];\n    var constName = definitions.opTypeNames.hasOwnProperty(token)\n        ? definitions.opTypeNames[token]\n        : token in definitions.keywords\n        ? token.toUpperCase()\n        : token;\n    return { toSource: function() { return constName } };\n}\nNp.toSource = function toSource() {\n    var mock = {};\n    var self = this;\n    mock.type = unevalableConst(this.type);\n    // avoid infinite recursion in case of back-links\n    if (this.generatingSource)\n        return mock.toSource();\n    this.generatingSource = true;\n    if (\"value\" in this)\n        mock.value = this.value;\n    if (\"lineno\" in this)\n        mock.lineno = this.lineno;\n    if (\"start\" in this)\n        mock.start = this.start;\n    if (\"end\" in this)\n        mock.end = this.end;\n    if (this.assignOp)\n        mock.assignOp = unevalableConst(this.assignOp);\n    for (var key in this) {\n        if (this.hasOwnProperty(key) && !(key in TO_SOURCE_SKIP))\n            mock[key] = this[key];\n    }\n    try {\n        return mock.toSource();\n    } finally {\n        delete this.generatingSource;\n    }\n};\n\n// Always use push to add operands to an expression, to update start and end.\nNp.push = function (kid) {\n    // kid can be null e.g. [1, , 2].\n    if (kid !== null) {\n        if (kid.start < this.start)\n            this.start = kid.start;\n        if (this.end < kid.end)\n            this.end = kid.end;\n    }\n    return this.children.push(kid);\n}\n\nNode.indentLevel = 0;\n\nfunction tokenString(tt) {\n    var t = definitions.tokens[tt];\n    return /^\\W/.test(t) ? definitions.opTypeNames[t] : t.toUpperCase();\n}\n\nNp.toString = function () {\n    var a = [];\n    for (var i in this) {\n        if (this.hasOwnProperty(i) && i !== 'type' && i !== 'target')\n            a.push({id: i, value: this[i]});\n    }\n    a.sort(function (a,b) { return (a.id < b.id) ? -1 : 1; });\n    var INDENTATION = \"    \";\n    var n = ++Node.indentLevel;\n    var s = \"{\\n\" + INDENTATION.repeat(n) + \"type: \" + tokenString(this.type);\n    for (i = 0; i < a.length; i++)\n        s += \",\\n\" + INDENTATION.repeat(n) + a[i].id + \": \" + a[i].value;\n    n = --Node.indentLevel;\n    s += \"\\n\" + INDENTATION.repeat(n) + \"}\";\n    return s;\n}\n\nNp.synth = function(init) {\n    var node = new SyntheticNode(init);\n    node.filename = this.filename;\n    node.lineno = this.lineno;\n    node.start = this.start;\n    node.end = this.end;\n    return node;\n};\n\n/*\n * Helper init objects for common nodes.\n */\n\nvar LOOP_INIT = { isLoop: true };\n\nfunction blockInit() {\n    return { type: BLOCK, varDecls: [] };\n}\n\nfunction scriptInit() {\n    return { type: SCRIPT,\n             funDecls: [],\n             varDecls: [],\n             modDefns: new Dict(),\n             modAssns: new Dict(),\n             modDecls: new Dict(),\n             modLoads: new Dict(),\n             impDecls: [],\n             expDecls: [],\n             exports: new Dict(),\n             hasEmptyReturn: false,\n             hasReturnWithValue: false,\n             hasYield: false };\n}\n\ndefinitions.defineGetter(Np, \"length\",\n                         function() {\n                             throw new Error(\"Node.prototype.length is gone; \" +\n                                             \"use n.children.length instead\");\n                         });\n\ndefinitions.defineProperty(String.prototype, \"repeat\",\n                           function(n) {\n                               var s = \"\", t = this + s;\n                               while (--n >= 0)\n                                   s += t;\n                               return s;\n                           }, false, false, true);\n\nPp.MaybeLeftParen = function MaybeLeftParen() {\n    if (this.parenFreeMode)\n        return this.match(LEFT_PAREN) ? LEFT_PAREN : END;\n    return this.mustMatch(LEFT_PAREN).type;\n};\n\nPp.MaybeRightParen = function MaybeRightParen(p) {\n    if (p === LEFT_PAREN)\n        this.mustMatch(RIGHT_PAREN);\n}\n\n/*\n * Statements :: (node[, boolean]) -> void\n *\n * Parses a sequence of Statements.\n */\nPp.Statements = function Statements(n, topLevel) {\n    var prologue = !!topLevel;\n    try {\n        while (!this.done() && this.peek(true) !== RIGHT_CURLY) {\n            var n2 = this.Statement();\n            n.push(n2);\n            if (prologue && Pragma(n2)) {\n                this.x.strictMode = true;\n                n.strict = true;\n            } else {\n                prologue = false;\n            }\n        }\n    } catch (e) {\n        try {\n            if (this.done())\n                this.unexpectedEOF = true;\n        } catch(e) {}\n        throw e;\n    }\n}\n\nPp.Block = function Block() {\n    this.mustMatch(LEFT_CURLY);\n    var n = this.newNode(blockInit());\n    var x2 = this.x.update({ parentBlock: n }).pushTarget(n);\n    this.withContext(x2, function() {\n        this.Statements(n);\n    });\n    this.mustMatch(RIGHT_CURLY);\n    return n;\n}\n\nvar DECLARED_FORM = 0, EXPRESSED_FORM = 1, STATEMENT_FORM = 2;\n\n/*\n * Export :: (binding node, boolean) -> Export\n *\n * Static semantic representation of a module export.\n */\nfunction Export(node, isDefinition) {\n    this.node = node;                 // the AST node declaring this individual export\n    this.isDefinition = isDefinition; // is the node an 'export'-annotated definition?\n    this.resolved = null;             // resolved pointer to the target of this export\n}\n\n/*\n * registerExport :: (Dict, EXPORT node) -> void\n */\nfunction registerExport(exports, decl) {\n    function register(name, exp) {\n        if (exports.has(name))\n            throw new SyntaxError(\"multiple exports of \" + name);\n        exports.set(name, exp);\n    }\n\n    switch (decl.type) {\n      case MODULE:\n      case FUNCTION:\n        register(decl.name, new Export(decl, true));\n        break;\n\n      case VAR:\n        for (var i = 0; i < decl.children.length; i++)\n            register(decl.children[i].name, new Export(decl.children[i], true));\n        break;\n\n      case LET:\n      case CONST:\n        throw new Error(\"NYI: \" + definitions.tokens[decl.type]);\n\n      case EXPORT:\n        for (var i = 0; i < decl.pathList.length; i++) {\n            var path = decl.pathList[i];\n            switch (path.type) {\n              case OBJECT_INIT:\n                for (var j = 0; j < path.children.length; j++) {\n                    // init :: IDENTIFIER | PROPERTY_INIT\n                    var init = path.children[j];\n                    if (init.type === IDENTIFIER)\n                        register(init.value, new Export(init, false));\n                    else\n                        register(init.children[0].value, new Export(init.children[1], false));\n                }\n                break;\n\n              case DOT:\n                register(path.children[1].value, new Export(path, false));\n                break;\n\n              case IDENTIFIER:\n                register(path.value, new Export(path, false));\n                break;\n\n              default:\n                throw new Error(\"unexpected export path: \" + definitions.tokens[path.type]);\n            }\n        }\n        break;\n\n      default:\n        throw new Error(\"unexpected export decl: \" + definitions.tokens[exp.type]);\n    }\n}\n\n/*\n * Module :: (node) -> Module\n *\n * Static semantic representation of a module.\n */\nfunction Module(node) {\n    var exports = node.body.exports;\n    var modDefns = node.body.modDefns;\n\n    var exportedModules = new Dict();\n\n    exports.forEach(function(name, exp) {\n        var node = exp.node;\n        if (node.type === MODULE) {\n            exportedModules.set(name, node);\n        } else if (!exp.isDefinition && node.type === IDENTIFIER && modDefns.has(node.value)) {\n            var mod = modDefns.get(node.value);\n            exportedModules.set(name, mod);\n        }\n    });\n\n    this.node = node;\n    this.exports = exports;\n    this.exportedModules = exportedModules;\n}\n\n/*\n * Statement :: () -> node\n *\n * Parses a Statement.\n */\nPp.Statement = function Statement() {\n    var i, label, n, n2, p, c, ss, tt = this.t.get(true), tt2, x0, x2, x3;\n\n    var comments = this.t.blockComments;\n\n    // Cases for statements ending in a right curly return early, avoiding the\n    // common semicolon insertion magic after this switch.\n    switch (tt) {\n      case IMPORT:\n        if (!this.x.canImport())\n            this.fail(\"illegal context for import statement\");\n        n = this.newNode();\n        n.pathList = this.ImportPathList();\n        this.x.parentScript.impDecls.push(n);\n        break;\n\n      case EXPORT:\n        if (!this.x.canExport())\n            this.fail(\"export statement not in module top level\");\n        switch (this.peek()) {\n          case MODULE:\n          case FUNCTION:\n          case LET:\n          case VAR:\n          case CONST:\n            n = this.Statement();\n            n.blockComments = comments;\n            n.exported = true;\n            this.x.parentScript.expDecls.push(n);\n            registerExport(this.x.parentScript.exports, n);\n            return n;\n        }\n        n = this.newNode();\n        n.pathList = this.ExportPathList();\n        this.x.parentScript.expDecls.push(n);\n        registerExport(this.x.parentScript.exports, n);\n        break;\n\n      case FUNCTION:\n        // DECLARED_FORM extends funDecls of x, STATEMENT_FORM doesn't.\n        return this.FunctionDefinition(true, this.x.topLevel ? DECLARED_FORM : STATEMENT_FORM, comments);\n\n      case LEFT_CURLY:\n        n = this.newNode(blockInit());\n        x2 = this.x.update({ parentBlock: n }).pushTarget(n).nest();\n        this.withContext(x2, function() {\n            this.Statements(n);\n        });\n        this.mustMatch(RIGHT_CURLY);\n        return n;\n\n      case IF:\n        n = this.newNode();\n        n.condition = this.HeadExpression();\n        x2 = this.x.pushTarget(n).nest();\n        this.withContext(x2, function() {\n            n.thenPart = this.Statement();\n            n.elsePart = this.match(ELSE, true) ? this.Statement() : null;\n        });\n        return n;\n\n      case SWITCH:\n        // This allows CASEs after a DEFAULT, which is in the standard.\n        n = this.newNode({ cases: [], defaultIndex: -1 });\n        n.discriminant = this.HeadExpression();\n        x2 = this.x.pushTarget(n).nest();\n        this.withContext(x2, function() {\n            this.mustMatch(LEFT_CURLY);\n            while ((tt = this.t.get()) !== RIGHT_CURLY) {\n                switch (tt) {\n                  case DEFAULT:\n                    if (n.defaultIndex >= 0)\n                        this.fail(\"More than one switch default\");\n                    // FALL THROUGH\n                  case CASE:\n                    n2 = this.newNode();\n                    if (tt === DEFAULT)\n                        n.defaultIndex = n.cases.length;\n                    else\n                        n2.caseLabel = this.Expression(COLON);\n                    break;\n\n                  default:\n                    this.fail(\"Invalid switch case\");\n                }\n                this.mustMatch(COLON);\n                n2.statements = this.newNode(blockInit());\n                while ((tt=this.peek(true)) !== CASE && tt !== DEFAULT &&\n                       tt !== RIGHT_CURLY)\n                    n2.statements.push(this.Statement());\n                n.cases.push(n2);\n            }\n        });\n        return n;\n\n      case FOR:\n        n = this.newNode(LOOP_INIT);\n        n.blockComments = comments;\n        if (this.match(IDENTIFIER)) {\n            if (this.t.token.value === \"each\")\n                n.isEach = true;\n            else\n                this.t.unget();\n        }\n        if (!this.parenFreeMode)\n            this.mustMatch(LEFT_PAREN);\n        x2 = this.x.pushTarget(n).nest();\n        x3 = this.x.update({ inForLoopInit: true });\n        n2 = null;\n        if ((tt = this.peek(true)) !== SEMICOLON) {\n            this.withContext(x3, function() {\n                if (tt === VAR || tt === CONST) {\n                    this.t.get();\n                    n2 = this.Variables();\n                } else if (tt === LET) {\n                    this.t.get();\n                    if (this.peek() === LEFT_PAREN) {\n                        n2 = this.LetBlock(false);\n                    } else {\n                        // Let in for head, we need to add an implicit block\n                        // around the rest of the for.\n                        this.x.parentBlock = n;\n                        n.varDecls = [];\n                        n2 = this.Variables();\n                    }\n                } else {\n                    n2 = this.Expression();\n                }\n            });\n        }\n        if (n2 && this.match(IN)) {\n            n.type = FOR_IN;\n            this.withContext(x3, function() {\n                n.object = this.Expression();\n                if (n2.type === VAR || n2.type === LET) {\n                    c = n2.children;\n\n                    // Destructuring turns one decl into multiples, so either\n                    // there must be only one destructuring or only one\n                    // decl.\n                    if (c.length !== 1 && n2.destructurings.length !== 1) {\n                        // FIXME: this.fail ?\n                        throw new SyntaxError(\"Invalid for..in left-hand side\",\n                                              this.filename, n2.lineno);\n                    }\n                    if (n2.destructurings.length > 0) {\n                        n.iterator = n2.destructurings[0];\n                    } else {\n                        n.iterator = c[0];\n                    }\n                    n.varDecl = n2;\n                } else {\n                    if (n2.type === ARRAY_INIT || n2.type === OBJECT_INIT) {\n                        n2.destructuredNames = this.checkDestructuring(n2);\n                    }\n                    n.iterator = n2;\n                }\n            });\n        } else {\n            x3.inForLoopInit = false;\n            n.setup = n2;\n            this.mustMatch(SEMICOLON);\n            if (n.isEach)\n                this.fail(\"Invalid for each..in loop\");\n            this.withContext(x3, function() {\n                n.condition = (this.peek(true) === SEMICOLON)\n                    ? null\n                    : this.Expression();\n                this.mustMatch(SEMICOLON);\n                tt2 = this.peek(true);\n                n.update = (this.parenFreeMode\n                            ? tt2 === LEFT_CURLY || definitions.isStatementStartCode[tt2]\n                            : tt2 === RIGHT_PAREN)\n                    ? null\n                    : this.Expression();\n            });\n        }\n        if (!this.parenFreeMode)\n            this.mustMatch(RIGHT_PAREN);\n        this.withContext(x2, function() {\n            n.body = this.Statement();\n        });\n        return n;\n\n      case WHILE:\n        n = this.newNode({ isLoop: true });\n        n.blockComments = comments;\n        n.condition = this.HeadExpression();\n        x2 = this.x.pushTarget(n).nest();\n        this.withContext(x2, function() {\n            n.body = this.Statement();\n        });\n        return n;\n\n      case DO:\n        n = this.newNode({ isLoop: true });\n        n.blockComments = comments;\n        x2 = this.x.pushTarget(n).next();\n        this.withContext(x2, function() {\n            n.body = this.Statement();\n        });\n        this.mustMatch(WHILE);\n        n.condition = this.HeadExpression();\n        // <script language=\"JavaScript\"> (without version hints) may need\n        // automatic semicolon insertion without a newline after do-while.\n        // See http://bugzilla.mozilla.org/show_bug.cgi?id=238945.\n        this.match(SEMICOLON);\n        return n;\n\n      case BREAK:\n      case CONTINUE:\n        n = this.newNode();\n        n.blockComments = comments;\n\n        // handle the |foo: break foo;| corner case\n        x2 = this.x.pushTarget(n);\n\n        if (this.peekOnSameLine() === IDENTIFIER) {\n            this.t.get();\n            n.label = this.t.token.value;\n        }\n\n        if (n.label) {\n            n.target = x2.labeledTargets.find(function(target) {\n                return target.labels.has(n.label)\n            });\n        } else if (tt === CONTINUE) {\n            n.target = x2.defaultLoopTarget;\n        } else {\n            n.target = x2.defaultTarget;\n        }\n\n        if (!n.target)\n            this.fail(\"Invalid \" + ((tt === BREAK) ? \"break\" : \"continue\"));\n        if (!n.target.isLoop && tt === CONTINUE)\n            this.fail(\"Invalid continue\");\n\n        break;\n\n      case TRY:\n        n = this.newNode({ catchClauses: [] });\n        n.blockComments = comments;\n        n.tryBlock = this.Block();\n        while (this.match(CATCH)) {\n            n2 = this.newNode();\n            p = this.MaybeLeftParen();\n            switch (this.t.get()) {\n              case LEFT_BRACKET:\n              case LEFT_CURLY:\n                // Destructured catch identifiers.\n                this.t.unget();\n                n2.varName = this.DestructuringExpression(true);\n                break;\n              case IDENTIFIER:\n                n2.varName = this.t.token.value;\n                break;\n              default:\n                this.fail(\"missing identifier in catch\");\n                break;\n            }\n            if (this.match(IF)) {\n                if (!this.mozillaMode)\n                    this.fail(\"Illegal catch guard\");\n                if (n.catchClauses.length && !n.catchClauses.top().guard)\n                    this.fail(\"Guarded catch after unguarded\");\n                n2.guard = this.Expression();\n            }\n            this.MaybeRightParen(p);\n            n2.block = this.Block();\n            n.catchClauses.push(n2);\n        }\n        if (this.match(FINALLY))\n            n.finallyBlock = this.Block();\n        if (!n.catchClauses.length && !n.finallyBlock)\n            this.fail(\"Invalid try statement\");\n        return n;\n\n      case CATCH:\n      case FINALLY:\n        this.fail(definitions.tokens[tt] + \" without preceding try\");\n\n      case THROW:\n        n = this.newNode();\n        n.exception = this.Expression();\n        break;\n\n      case RETURN:\n        n = this.ReturnOrYield();\n        break;\n\n      case WITH:\n        if (this.x.banWith())\n            this.fail(\"with statements not allowed in strict code or modules\");\n        n = this.newNode();\n        n.blockComments = comments;\n        n.object = this.HeadExpression();\n        x2 = this.x.pushTarget(n).next();\n        this.withContext(x2, function() {\n            n.body = this.Statement();\n        });\n        return n;\n\n      case VAR:\n      case CONST:\n        n = this.Variables();\n        break;\n\n      case LET:\n        if (this.peek() === LEFT_PAREN) {\n            n = this.LetBlock(true);\n            return n;\n        }\n        n = this.Variables();\n        break;\n\n      case DEBUGGER:\n        n = this.newNode();\n        break;\n\n      case NEWLINE:\n      case SEMICOLON:\n        n = this.newNode({ type: SEMICOLON });\n        n.blockComments = comments;\n        n.expression = null;\n        return n;\n\n      case IDENTIFIER:\n      case USE:\n      case MODULE:\n        switch (this.t.token.value) {\n          case \"use\":\n            if (!isPragmaToken(this.peekOnSameLine())) {\n                this.t.unget();\n                break;\n            }\n            return this.newNode({ type: USE, params: this.Pragmas() });\n\n          case \"module\":\n            if (!this.x.modulesAllowed())\n                this.fail(\"module declaration not at top level\");\n            this.x.parentScript.hasModules = true;\n            tt = this.peekOnSameLine();\n            if (tt !== IDENTIFIER && tt !== LEFT_CURLY) {\n                this.t.unget();\n                break;\n            }\n            n = this.newNode({ type: MODULE });\n            n.blockComments = comments;\n            this.mustMatch(IDENTIFIER);\n            label = this.t.token.value;\n\n            if (this.match(LEFT_CURLY)) {\n                n.name = label;\n                n.body = this.Script(true, false);\n                n.module = new Module(n);\n                this.mustMatch(RIGHT_CURLY);\n                this.x.parentScript.modDefns.set(n.name, n);\n                return n;\n            }\n\n            this.t.unget();\n            this.ModuleVariables(n);\n            return n;\n\n          default:\n            tt = this.peek();\n            // Labeled statement.\n            if (tt === COLON) {\n                label = this.t.token.value;\n                if (this.x.allLabels.has(label))\n                    this.fail(\"Duplicate label: \" + label);\n                this.t.get();\n                n = this.newNode({ type: LABEL, label: label });\n                n.blockComments = comments;\n                x2 = this.x.pushLabel(label).nest();\n                this.withContext(x2, function() {\n                    n.statement = this.Statement();\n                });\n                n.target = (n.statement.type === LABEL) ? n.statement.target : n.statement;\n                return n;\n            }\n            // FALL THROUGH\n        }\n        // FALL THROUGH\n\n      default:\n        // Expression statement.\n        // We unget the current token to parse the expression as a whole.\n        n = this.newNode({ type: SEMICOLON });\n        this.t.unget();\n        n.blockComments = comments;\n        n.expression = this.Expression();\n        n.end = n.expression.end;\n        break;\n    }\n\n    n.blockComments = comments;\n    this.MagicalSemicolon();\n    return n;\n}\n\n/*\n * isPragmaToken :: (number) -> boolean\n */\nfunction isPragmaToken(tt) {\n    switch (tt) {\n      case IDENTIFIER:\n      case STRING:\n      case NUMBER:\n      case NULL:\n      case TRUE:\n      case FALSE:\n        return true;\n    }\n    return false;\n}\n\n/*\n * Pragmas :: () -> Array[Array[token]]\n */\nPp.Pragmas = function Pragmas() {\n    var pragmas = [];\n    do {\n        pragmas.push(this.Pragma());\n    } while (this.match(COMMA));\n    this.MagicalSemicolon();\n    return pragmas;\n}\n\n/*\n * Pragmas :: () -> Array[token]\n */\nPp.Pragma = function Pragma() {\n    var items = [];\n    var tt;\n    do {\n        tt = this.t.get(true);\n        items.push(this.t.token);\n    } while (isPragmaToken(this.peek()));\n    return items;\n}\n\n/*\n * MagicalSemicolon :: () -> void\n */\nPp.MagicalSemicolon = function MagicalSemicolon() {\n    var tt;\n    if (this.t.lineno === this.t.token.lineno) {\n        tt = this.peekOnSameLine();\n        if (tt !== END && tt !== NEWLINE && tt !== SEMICOLON && tt !== RIGHT_CURLY)\n            this.fail(\"missing ; before statement\");\n    }\n    this.match(SEMICOLON);\n}\n\n/*\n * ReturnOrYield :: () -> (RETURN | YIELD) node\n */\nPp.ReturnOrYield = function ReturnOrYield() {\n    var n, b, tt = this.t.token.type, tt2;\n\n    var parentScript = this.x.parentScript;\n\n    if (tt === RETURN) {\n        if (!this.x.inFunction)\n            this.fail(\"Return not in function\");\n    } else /* if (tt === YIELD) */ {\n        if (!this.x.inFunction)\n            this.fail(\"Yield not in function\");\n        parentScript.hasYield = true;\n    }\n    n = this.newNode({ value: undefined });\n\n    tt2 = (tt === RETURN) ? this.peekOnSameLine(true) : this.peek(true);\n    if (tt2 !== END && tt2 !== NEWLINE &&\n        tt2 !== SEMICOLON && tt2 !== RIGHT_CURLY\n        && (tt !== YIELD ||\n            (tt2 !== tt && tt2 !== RIGHT_BRACKET && tt2 !== RIGHT_PAREN &&\n             tt2 !== COLON && tt2 !== COMMA))) {\n        if (tt === RETURN) {\n            n.value = this.Expression();\n            parentScript.hasReturnWithValue = true;\n        } else {\n            n.value = this.AssignExpression();\n        }\n    } else if (tt === RETURN) {\n        parentScript.hasEmptyReturn = true;\n    }\n\n    return n;\n}\n\n/*\n * ModuleExpression :: () -> (STRING | IDENTIFIER | DOT) node\n */\nPp.ModuleExpression = function ModuleExpression() {\n    return this.match(STRING) ? this.newNode() : this.QualifiedPath();\n}\n\n/*\n * ImportPathList :: () -> Array[DOT node]\n */\nPp.ImportPathList = function ImportPathList() {\n    var a = [];\n    do {\n        a.push(this.ImportPath());\n    } while (this.match(COMMA));\n    return a;\n}\n\n/*\n * ImportPath :: () -> DOT node\n */\nPp.ImportPath = function ImportPath() {\n    var n = this.QualifiedPath();\n    if (!this.match(DOT)) {\n        if (n.type === IDENTIFIER)\n            this.fail(\"cannot import local variable\");\n        return n;\n    }\n\n    var n2 = this.newNode();\n    n2.push(n);\n    n2.push(this.ImportSpecifierSet());\n    return n2;\n}\n\n/*\n * ExplicitSpecifierSet :: (() -> node) -> OBJECT_INIT node\n */\nPp.ExplicitSpecifierSet = function ExplicitSpecifierSet(SpecifierRHS) {\n    var n, n2, id, tt;\n\n    n = this.newNode({ type: OBJECT_INIT });\n    this.mustMatch(LEFT_CURLY);\n\n    if (!this.match(RIGHT_CURLY)) {\n        do {\n            id = this.Identifier();\n            if (this.match(COLON)) {\n                n2 = this.newNode({ type: PROPERTY_INIT });\n                n2.push(id);\n                n2.push(SpecifierRHS());\n                n.push(n2);\n            } else {\n                n.push(id);\n            }\n        } while (!this.match(RIGHT_CURLY) && this.mustMatch(COMMA));\n    }\n\n    return n;\n}\n\n/*\n * ImportSpecifierSet :: () -> (IDENTIFIER | OBJECT_INIT) node\n */\nPp.ImportSpecifierSet = function ImportSpecifierSet() {\n    var self = this;\n    return this.match(MUL)\n        ? this.newNode({ type: IDENTIFIER, name: \"*\" })\n    : ExplicitSpecifierSet(function() { return self.Identifier() });\n}\n\n/*\n * Identifier :: () -> IDENTIFIER node\n */\nPp.Identifier = function Identifier() {\n    this.mustMatch(IDENTIFIER);\n    return this.newNode({ type: IDENTIFIER });\n}\n\n/*\n * IdentifierName :: () -> IDENTIFIER node\n */\nPp.IdentifierName = function IdentifierName() {\n    this.mustMatch(IDENTIFIER, true);\n    return this.newNode({ type: IDENTIFIER });\n}\n\n/*\n * QualifiedPath :: () -> (IDENTIFIER | DOT) node\n */\nPp.QualifiedPath = function QualifiedPath() {\n    var n, n2;\n\n    n = this.Identifier();\n\n    while (this.match(DOT)) {\n        if (this.peek() !== IDENTIFIER) {\n            // Unget the '.' token, which isn't part of the QualifiedPath.\n            this.t.unget();\n            break;\n        }\n        n2 = this.newNode();\n        n2.push(n);\n        n2.push(this.Identifier());\n        n = n2;\n    }\n\n    return n;\n}\n\n/*\n * ExportPath :: () -> (IDENTIFIER | DOT | OBJECT_INIT) node\n */\nPp.ExportPath = function ExportPath() {\n    var self = this;\n    if (this.peek() === LEFT_CURLY)\n        return this.ExplicitSpecifierSet(function() { return self.QualifiedPath() });\n    return this.QualifiedPath();\n}\n\n/*\n * ExportPathList :: () -> Array[(IDENTIFIER | DOT | OBJECT_INIT) node]\n */\nPp.ExportPathList = function ExportPathList() {\n    var a = [];\n    do {\n        a.push(this.ExportPath());\n    } while (this.match(COMMA));\n    return a;\n}\n\n/*\n * FunctionDefinition :: (boolean,\n *                        DECLARED_FORM or EXPRESSED_FORM or STATEMENT_FORM,\n *                        [string] or null or undefined)\n *                    -> node\n */\nPp.FunctionDefinition = function FunctionDefinition(requireName, functionForm, comments) {\n    var tt;\n    var f = this.newNode({ params: [], paramComments: [] });\n    if (typeof comments === \"undefined\")\n        comments = null;\n    f.blockComments = comments;\n    if (f.type !== FUNCTION)\n        f.type = (f.value === \"get\") ? GETTER : SETTER;\n    if (this.match(MUL))\n        f.isExplicitGenerator = true;\n    if (this.match(IDENTIFIER, false, true))\n        f.name = this.t.token.value;\n    else if (requireName)\n        this.fail(\"missing function identifier\");\n\n    var inModule = this.x.inModule;\n    x2 = new StaticContext(null, null, inModule, true, this.x.strictMode);\n    this.withContext(x2, function() {\n        this.mustMatch(LEFT_PAREN);\n        if (!this.match(RIGHT_PAREN)) {\n            do {\n                tt = this.t.get();\n                f.paramComments.push(this.t.lastBlockComment());\n                switch (tt) {\n                  case LEFT_BRACKET:\n                  case LEFT_CURLY:\n                    // Destructured formal parameters.\n                    this.t.unget();\n                    f.params.push(this.DestructuringExpression());\n                    break;\n                  case IDENTIFIER:\n                    f.params.push(this.t.token.value);\n                    break;\n                  default:\n                    this.fail(\"missing formal parameter\");\n                }\n            } while (this.match(COMMA));\n            this.mustMatch(RIGHT_PAREN);\n        }\n\n        // Do we have an expression closure or a normal body?\n        tt = this.t.get(true);\n        if (tt !== LEFT_CURLY)\n            this.t.unget();\n\n        if (tt !== LEFT_CURLY) {\n            f.body = this.AssignExpression();\n        } else {\n            f.body = this.Script(inModule, true);\n        }\n    });\n\n    if (tt === LEFT_CURLY)\n        this.mustMatch(RIGHT_CURLY);\n\n    f.end = this.t.token.end;\n    f.functionForm = functionForm;\n    if (functionForm === DECLARED_FORM)\n        this.x.parentScript.funDecls.push(f);\n\n    if (this.x.inModule && !f.isExplicitGenerator && f.body.hasYield)\n        this.fail(\"yield in non-generator function\");\n\n    if (f.isExplicitGenerator || f.body.hasYield)\n        f.body = this.newNode({ type: GENERATOR, body: f.body });\n\n    return f;\n}\n\n/*\n * ModuleVariables :: (MODULE node) -> void\n *\n * Parses a comma-separated list of module declarations (and maybe\n * initializations).\n */\nPp.ModuleVariables = function ModuleVariables(n) {\n    var n1, n2;\n    do {\n        n1 = this.Identifier();\n        if (this.match(ASSIGN)) {\n            n2 = this.ModuleExpression();\n            n1.initializer = n2;\n            if (n2.type === STRING)\n                this.x.parentScript.modLoads.set(n1.value, n2.value);\n            else\n                this.x.parentScript.modAssns.set(n1.value, n1);\n        }\n        n.push(n1);\n    } while (this.match(COMMA));\n}\n\n/*\n * Variables :: () -> node\n *\n * Parses a comma-separated list of var declarations (and maybe\n * initializations).\n */\nPp.Variables = function Variables(letBlock) {\n    var n, n2, ss, i, s, tt;\n\n    tt = this.t.token.type;\n    switch (tt) {\n      case VAR:\n      case CONST:\n        s = this.x.parentScript;\n        break;\n      case LET:\n        s = this.x.parentBlock;\n        break;\n      case LEFT_PAREN:\n        tt = LET;\n        s = letBlock;\n        break;\n    }\n\n    n = this.newNode({ type: tt, destructurings: [] });\n\n    do {\n        tt = this.t.get();\n        if (tt === LEFT_BRACKET || tt === LEFT_CURLY) {\n            // Need to unget to parse the full destructured expression.\n            this.t.unget();\n\n            var dexp = this.DestructuringExpression(true);\n\n            n2 = this.newNode({ type: IDENTIFIER,\n                                name: dexp,\n                                readOnly: n.type === CONST });\n            n.push(n2);\n            pushDestructuringVarDecls(n2.name.destructuredNames, s);\n            n.destructurings.push({ exp: dexp, decl: n2 });\n\n            if (this.x.inForLoopInit && this.peek() === IN) {\n                continue;\n            }\n\n            this.mustMatch(ASSIGN);\n            if (this.t.token.assignOp)\n                this.fail(\"Invalid variable initialization\");\n\n            n2.blockComment = this.t.lastBlockComment();\n            n2.initializer = this.AssignExpression();\n\n            continue;\n        }\n\n        if (tt !== IDENTIFIER)\n            this.fail(\"missing variable name\");\n\n        n2 = this.newNode({ type: IDENTIFIER,\n                            name: this.t.token.value,\n                            readOnly: n.type === CONST });\n        n.push(n2);\n        s.varDecls.push(n2);\n\n        if (this.match(ASSIGN)) {\n            var comment = this.t.lastBlockComment();\n            if (this.t.token.assignOp)\n                this.fail(\"Invalid variable initialization\");\n\n            n2.initializer = this.AssignExpression();\n        } else {\n            var comment = this.t.lastBlockComment();\n        }\n        n2.blockComment = comment;\n    } while (this.match(COMMA));\n\n    return n;\n}\n\n/*\n * LetBlock :: (boolean) -> node\n *\n * Does not handle let inside of for loop init.\n */\nPp.LetBlock = function LetBlock(isStatement) {\n    var n, n2;\n\n    // t.token.type must be LET\n    n = this.newNode({ type: LET_BLOCK, varDecls: [] });\n    this.mustMatch(LEFT_PAREN);\n    n.variables = this.Variables(n);\n    this.mustMatch(RIGHT_PAREN);\n\n    if (isStatement && this.peek() !== LEFT_CURLY) {\n        /*\n         * If this is really an expression in let statement guise, then we\n         * need to wrap the LET_BLOCK node in a SEMICOLON node so that we pop\n         * the return value of the expression.\n         */\n        n2 = this.newNode({ type: SEMICOLON, expression: n });\n        isStatement = false;\n    }\n\n    if (isStatement)\n        n.block = this.Block();\n    else\n        n.expression = this.AssignExpression();\n\n    return n;\n}\n\nPp.checkDestructuring = function checkDestructuring(n, simpleNamesOnly) {\n    if (n.type === ARRAY_COMP)\n        this.fail(\"Invalid array comprehension left-hand side\");\n    if (n.type !== ARRAY_INIT && n.type !== OBJECT_INIT)\n        return;\n\n    var lhss = {};\n    var nn, n2, idx, sub, cc, c = n.children;\n    for (var i = 0, j = c.length; i < j; i++) {\n        if (!(nn = c[i]))\n            continue;\n        if (nn.type === PROPERTY_INIT) {\n            cc = nn.children;\n            sub = cc[1];\n            idx = cc[0].value;\n        } else if (n.type === OBJECT_INIT) {\n            // Do we have destructuring shorthand {foo, bar}?\n            sub = nn;\n            idx = nn.value;\n        } else {\n            sub = nn;\n            idx = i;\n        }\n\n        if (sub.type === ARRAY_INIT || sub.type === OBJECT_INIT) {\n            lhss[idx] = this.checkDestructuring(sub, simpleNamesOnly);\n        } else {\n            if (simpleNamesOnly && sub.type !== IDENTIFIER) {\n                // In declarations, lhs must be simple names\n                this.fail(\"missing name in pattern\");\n            }\n\n            lhss[idx] = sub;\n        }\n    }\n\n    return lhss;\n}\n\nPp.DestructuringExpression = function DestructuringExpression(simpleNamesOnly) {\n    var n = this.PrimaryExpression();\n    // Keep the list of lefthand sides for varDecls\n    n.destructuredNames = this.checkDestructuring(n, simpleNamesOnly);\n    return n;\n}\n\nPp.GeneratorExpression = function GeneratorExpression(e) {\n    return this.newNode({ type: GENERATOR,\n                          expression: e,\n                          tail: this.ComprehensionTail() });\n}\n\nPp.ComprehensionTail = function ComprehensionTail() {\n    var body, n, n2, n3, p;\n\n    // t.token.type must be FOR\n    body = this.newNode({ type: COMP_TAIL });\n\n    do {\n        // Comprehension tails are always for..in loops.\n        n = this.newNode({ type: FOR_IN, isLoop: true });\n        if (this.match(IDENTIFIER)) {\n            // But sometimes they're for each..in.\n            if (this.mozillaMode && this.t.token.value === \"each\")\n                n.isEach = true;\n            else\n                this.t.unget();\n        }\n        p = this.MaybeLeftParen();\n        switch(this.t.get()) {\n          case LEFT_BRACKET:\n          case LEFT_CURLY:\n            this.t.unget();\n            // Destructured left side of for in comprehension tails.\n            n.iterator = this.DestructuringExpression();\n            break;\n\n          case IDENTIFIER:\n            n.iterator = n3 = this.newNode({ type: IDENTIFIER });\n            n3.name = n3.value;\n            n.varDecl = n2 = this.newNode({ type: VAR });\n            n2.push(n3);\n            this.x.parentScript.varDecls.push(n3);\n            // Don't add to varDecls since the semantics of comprehensions is\n            // such that the variables are in their own function when\n            // desugared.\n            break;\n\n          default:\n            this.fail(\"missing identifier\");\n        }\n        this.mustMatch(IN);\n        n.object = this.Expression();\n        this.MaybeRightParen(p);\n        body.push(n);\n    } while (this.match(FOR));\n\n    // Optional guard.\n    if (this.match(IF))\n        body.guard = this.HeadExpression();\n\n    return body;\n}\n\nPp.HeadExpression = function HeadExpression() {\n    var p = this.MaybeLeftParen();\n    var n = this.ParenExpression();\n    this.MaybeRightParen(p);\n    if (p === END && !n.parenthesized) {\n        var tt = this.peek();\n        if (tt !== LEFT_CURLY && !definitions.isStatementStartCode[tt])\n            this.fail(\"Unparenthesized head followed by unbraced body\");\n    }\n    return n;\n}\n\nPp.ParenExpression = function ParenExpression() {\n    // Always accept the 'in' operator in a parenthesized expression,\n    // where it's unambiguous, even if we might be parsing the init of a\n    // for statement.\n    var x2 = this.x.update({\n        inForLoopInit: this.x.inForLoopInit && (this.t.token.type === LEFT_PAREN)\n    });\n    var n = this.withContext(x2, function() {\n        return this.Expression();\n    });\n    if (this.match(FOR)) {\n        if (n.type === YIELD && !n.parenthesized)\n            this.fail(\"Yield expression must be parenthesized\");\n        if (n.type === COMMA && !n.parenthesized)\n            this.fail(\"Generator expression must be parenthesized\");\n        n = this.GeneratorExpression(n);\n    }\n\n    return n;\n}\n\n/*\n * Expression :: () -> node\n *\n * Top-down expression parser matched against SpiderMonkey.\n */\nPp.Expression = function Expression() {\n    var n, n2;\n\n    n = this.AssignExpression();\n    if (this.match(COMMA)) {\n        n2 = this.newNode({ type: COMMA });\n        n2.push(n);\n        n = n2;\n        do {\n            n2 = n.children[n.children.length-1];\n            if (n2.type === YIELD && !n2.parenthesized)\n                this.fail(\"Yield expression must be parenthesized\");\n            n.push(this.AssignExpression());\n        } while (this.match(COMMA));\n    }\n\n    return n;\n}\n\nPp.AssignExpression = function AssignExpression() {\n    var n, lhs;\n\n    // Have to treat yield like an operand because it could be the leftmost\n    // operand of the expression.\n    if (this.match(YIELD, true))\n        return this.ReturnOrYield();\n\n    n = this.newNode({ type: ASSIGN });\n    lhs = this.ConditionalExpression();\n\n    if (!this.match(ASSIGN)) {\n        return lhs;\n    }\n\n    n.blockComment = this.t.lastBlockComment();\n\n    switch (lhs.type) {\n      case OBJECT_INIT:\n      case ARRAY_INIT:\n        lhs.destructuredNames = this.checkDestructuring(lhs);\n        // FALL THROUGH\n      case IDENTIFIER: case DOT: case INDEX: case CALL:\n        break;\n      default:\n        this.fail(\"Bad left-hand side of assignment\");\n        break;\n    }\n\n    n.assignOp = lhs.assignOp = this.t.token.assignOp;\n    n.push(lhs);\n    n.push(this.AssignExpression());\n\n    return n;\n}\n\nPp.ConditionalExpression = function ConditionalExpression() {\n    var n, n2;\n\n    n = this.OrExpression();\n    if (this.match(HOOK)) {\n        n2 = n;\n        n = this.newNode({ type: HOOK });\n        n.push(n2);\n        /*\n         * Always accept the 'in' operator in the middle clause of a ternary,\n         * where it's unambiguous, even if we might be parsing the init of a\n         * for statement.\n         */\n        var x2 = this.x.update({ inForLoopInit: false });\n        this.withContext(x2, function() {\n            n.push(this.AssignExpression());\n        });\n        if (!this.match(COLON))\n            this.fail(\"missing : after ?\");\n        n.push(this.AssignExpression());\n    }\n\n    return n;\n}\n\nPp.OrExpression = function OrExpression() {\n    var n, n2;\n\n    n = this.AndExpression();\n    while (this.match(OR)) {\n        n2 = this.newNode();\n        n2.push(n);\n        n2.push(this.AndExpression());\n        n = n2;\n    }\n\n    return n;\n}\n\nPp.AndExpression = function AndExpression() {\n    var n, n2;\n\n    n = this.BitwiseOrExpression();\n    while (this.match(AND)) {\n        n2 = this.newNode();\n        n2.push(n);\n        n2.push(this.BitwiseOrExpression());\n        n = n2;\n    }\n\n    return n;\n}\n\nPp.BitwiseOrExpression = function BitwiseOrExpression() {\n    var n, n2;\n\n    n = this.BitwiseXorExpression();\n    while (this.match(BITWISE_OR)) {\n        n2 = this.newNode();\n        n2.push(n);\n        n2.push(this.BitwiseXorExpression());\n        n = n2;\n    }\n\n    return n;\n}\n\nPp.BitwiseXorExpression = function BitwiseXorExpression() {\n    var n, n2;\n\n    n = this.BitwiseAndExpression();\n    while (this.match(BITWISE_XOR)) {\n        n2 = this.newNode();\n        n2.push(n);\n        n2.push(this.BitwiseAndExpression());\n        n = n2;\n    }\n\n    return n;\n}\n\nPp.BitwiseAndExpression = function BitwiseAndExpression() {\n    var n, n2;\n\n    n = this.EqualityExpression();\n    while (this.match(BITWISE_AND)) {\n        n2 = this.newNode();\n        n2.push(n);\n        n2.push(this.EqualityExpression());\n        n = n2;\n    }\n\n    return n;\n}\n\nPp.EqualityExpression = function EqualityExpression() {\n    var n, n2;\n\n    n = this.RelationalExpression();\n    while (this.match(EQ) || this.match(NE) ||\n           this.match(STRICT_EQ) || this.match(STRICT_NE)) {\n        n2 = this.newNode();\n        n2.push(n);\n        n2.push(this.RelationalExpression());\n        n = n2;\n    }\n\n    return n;\n}\n\nPp.RelationalExpression = function RelationalExpression() {\n    var n, n2;\n\n    /*\n     * Uses of the in operator in shiftExprs are always unambiguous,\n     * so unset the flag that prohibits recognizing it.\n     */\n    var x2 = this.x.update({ inForLoopInit: false });\n    this.withContext(x2, function() {\n        n = this.ShiftExpression();\n        while ((this.match(LT) || this.match(LE) || this.match(GE) || this.match(GT) ||\n                (!this.x.inForLoopInit && this.match(IN)) ||\n                this.match(INSTANCEOF))) {\n            n2 = this.newNode();\n            n2.push(n);\n            n2.push(this.ShiftExpression());\n            n = n2;\n        }\n    });\n\n    return n;\n}\n\nPp.ShiftExpression = function ShiftExpression() {\n    var n, n2;\n\n    n = this.AddExpression();\n    while (this.match(LSH) || this.match(RSH) || this.match(URSH)) {\n        n2 = this.newNode();\n        n2.push(n);\n        n2.push(this.AddExpression());\n        n = n2;\n    }\n\n    return n;\n}\n\nPp.AddExpression = function AddExpression() {\n    var n, n2;\n\n    n = this.MultiplyExpression();\n    while (this.match(PLUS) || this.match(MINUS)) {\n        n2 = this.newNode();\n        n2.push(n);\n        n2.push(this.MultiplyExpression());\n        n = n2;\n    }\n\n    return n;\n}\n\nPp.MultiplyExpression = function MultiplyExpression() {\n    var n, n2;\n\n    n = this.UnaryExpression();\n    while (this.match(MUL) || this.match(DIV) || this.match(MOD)) {\n        n2 = this.newNode();\n        n2.push(n);\n        n2.push(this.UnaryExpression());\n        n = n2;\n    }\n\n    return n;\n}\n\nPp.UnaryExpression = function UnaryExpression() {\n    var n, n2, tt;\n\n    switch (tt = this.t.get(true)) {\n      case DELETE: case VOID: case TYPEOF:\n      case NOT: case BITWISE_NOT: case PLUS: case MINUS:\n        if (tt === PLUS)\n            n = this.newNode({ type: UNARY_PLUS });\n        else if (tt === MINUS)\n            n = this.newNode({ type: UNARY_MINUS });\n        else\n            n = this.newNode();\n        n.push(this.UnaryExpression());\n        break;\n\n      case INCREMENT:\n      case DECREMENT:\n        // Prefix increment/decrement.\n        n = this.newNode();\n        n.push(this.MemberExpression(true));\n        break;\n\n      default:\n        this.t.unget();\n        n = this.MemberExpression(true);\n\n        // Don't look across a newline boundary for a postfix {in,de}crement.\n        if (this.t.tokens[(this.t.tokenIndex + this.t.lookahead - 1) & 3].lineno ===\n            this.t.lineno) {\n            if (this.match(INCREMENT) || this.match(DECREMENT)) {\n                n2 = this.newNode({ postfix: true });\n                n2.push(n);\n                n = n2;\n            }\n        }\n        break;\n    }\n\n    return n;\n}\n\nPp.MemberExpression = function MemberExpression(allowCallSyntax) {\n    var n, n2, name, tt;\n\n    if (this.match(NEW)) {\n        n = this.newNode();\n        n.push(this.MemberExpression(false));\n        if (this.match(LEFT_PAREN)) {\n            n.type = NEW_WITH_ARGS;\n            n.push(this.ArgumentList());\n        }\n    } else {\n        n = this.PrimaryExpression();\n    }\n\n    while ((tt = this.t.get()) !== END) {\n        switch (tt) {\n          case DOT:\n            n2 = this.newNode();\n            n2.push(n);\n            n2.push(this.IdentifierName());\n            break;\n\n          case LEFT_BRACKET:\n            n2 = this.newNode({ type: INDEX });\n            n2.push(n);\n            n2.push(this.Expression());\n            this.mustMatch(RIGHT_BRACKET);\n            break;\n\n          case LEFT_PAREN:\n            if (allowCallSyntax) {\n                n2 = this.newNode({ type: CALL });\n                n2.push(n);\n                n2.push(this.ArgumentList());\n                break;\n            }\n\n            // FALL THROUGH\n          default:\n            this.t.unget();\n            return n;\n        }\n\n        n = n2;\n    }\n\n    return n;\n}\n\nPp.ArgumentList = function ArgumentList() {\n    var n, n2;\n\n    n = this.newNode({ type: LIST });\n    if (this.match(RIGHT_PAREN, true))\n        return n;\n    do {\n        n2 = this.AssignExpression();\n        if (n2.type === YIELD && !n2.parenthesized && this.peek() === COMMA)\n            this.fail(\"Yield expression must be parenthesized\");\n        if (this.match(FOR)) {\n            n2 = this.GeneratorExpression(n2);\n            if (n.children.length > 1 || this.peek(true) === COMMA)\n                this.fail(\"Generator expression must be parenthesized\");\n        }\n        n.push(n2);\n    } while (this.match(COMMA));\n    this.mustMatch(RIGHT_PAREN);\n\n    return n;\n}\n\nPp.PrimaryExpression = function PrimaryExpression() {\n    var n, n2, tt = this.t.get(true);\n\n    switch (tt) {\n      case FUNCTION:\n        n = this.FunctionDefinition(false, EXPRESSED_FORM);\n        break;\n\n      case LEFT_BRACKET:\n        n = this.newNode({ type: ARRAY_INIT });\n        while ((tt = this.peek(true)) !== RIGHT_BRACKET) {\n            if (tt === COMMA) {\n                this.t.get();\n                n.push(null);\n                continue;\n            }\n            n.push(this.AssignExpression());\n            if (tt !== COMMA && !this.match(COMMA))\n                break;\n        }\n\n        // If we matched exactly one element and got a FOR, we have an\n        // array comprehension.\n        if (n.children.length === 1 && this.match(FOR)) {\n            n2 = this.newNode({ type: ARRAY_COMP,\n                                expression: n.children[0],\n                                tail: this.ComprehensionTail() });\n            n = n2;\n        }\n        this.mustMatch(RIGHT_BRACKET);\n        break;\n\n      case LEFT_CURLY:\n        var id, fd;\n        n = this.newNode({ type: OBJECT_INIT });\n\n        object_init:\n        if (!this.match(RIGHT_CURLY)) {\n            do {\n                tt = this.t.get();\n                if ((this.t.token.value === \"get\" || this.t.token.value === \"set\") &&\n                    this.peek() === IDENTIFIER) {\n                    n.push(this.FunctionDefinition(true, EXPRESSED_FORM));\n                } else {\n                    var comments = this.t.blockComments;\n                    switch (tt) {\n                      case IDENTIFIER: case NUMBER: case STRING:\n                        id = this.newNode({ type: IDENTIFIER });\n                        break;\n                      case RIGHT_CURLY:\n                        break object_init;\n                      default:\n                        if (this.t.token.value in definitions.keywords) {\n                            id = this.newNode({ type: IDENTIFIER });\n                            break;\n                        }\n                        this.fail(\"Invalid property name\");\n                    }\n                    if (this.match(COLON)) {\n                        n2 = this.newNode({ type: PROPERTY_INIT });\n                        n2.push(id);\n                        n2.push(this.AssignExpression());\n                        n2.blockComments = comments;\n                        n.push(n2);\n                    } else {\n                        // Support, e.g., |var {x, y} = o| as destructuring shorthand\n                        // for |var {x: x, y: y} = o|, per proposed JS2/ES4 for JS1.8.\n                        if (this.peek() !== COMMA && this.peek() !== RIGHT_CURLY)\n                            this.fail(\"missing : after property\");\n                        n.push(id);\n                    }\n                }\n            } while (this.match(COMMA));\n            this.mustMatch(RIGHT_CURLY);\n        }\n        break;\n\n      case LEFT_PAREN:\n        n = this.ParenExpression();\n        this.mustMatch(RIGHT_PAREN);\n        n.parenthesized = true;\n        break;\n\n      case LET:\n        n = this.LetBlock(false);\n        break;\n\n      case NULL: case THIS: case TRUE: case FALSE:\n      case IDENTIFIER: case NUMBER: case STRING: case REGEXP:\n        n = this.newNode();\n        break;\n\n      default:\n        this.fail(\"missing operand; found \" + definitions.tokens[tt]);\n        break;\n    }\n\n    return n;\n}\n\n/*\n * parse :: (source, filename, line number) -> node\n */\nfunction parse(s, f, l) {\n    var t = new Tokenizer(s, f, l, options.allowHTMLComments);\n    var p = new Parser(t);\n    return p.Script(false, false, true);\n}\n\n/*\n * parseFunction :: (source, boolean,\n *                   DECLARED_FORM or EXPRESSED_FORM or STATEMENT_FORM,\n *                   filename, line number)\n *               -> node\n */\nfunction parseFunction(s, requireName, form, f, l) {\n    var t = new Tokenizer(s, f, l);\n    var p = new Parser(t);\n    p.x = new StaticContext(null, null, false, false, false);\n    return p.FunctionDefinition(requireName, form);\n}\n\n/*\n * parseStdin :: (source, {line number}, string, (string) -> boolean) -> program node\n */\nfunction parseStdin(s, ln, prefix, isCommand) {\n    // the special .begin command is only recognized at the beginning\n    if (s.match(/^[\\s]*\\.begin[\\s]*$/)) {\n        ++ln.value;\n        return parseMultiline(ln, prefix);\n    }\n\n    // commands at the beginning are treated as the entire input\n    if (isCommand(s.trim()))\n        s = \"\";\n\n    for (;;) {\n        try {\n            var t = new Tokenizer(s, \"stdin\", ln.value, false);\n            var p = new Parser(t);\n            var n = p.Script(false, false);\n            ln.value = t.lineno;\n            return n;\n        } catch (e) {\n            if (!p.unexpectedEOF)\n                throw e;\n\n            // commands in the middle are not treated as part of the input\n            var more;\n            do {\n                if (prefix)\n                    putstr(prefix);\n                more = readline();\n                if (!more)\n                    throw e;\n            } while (isCommand(more.trim()));\n\n            s += \"\\n\" + more;\n        }\n    }\n}\n\n/*\n * parseMultiline :: ({line number}, string | null) -> program node\n */\nfunction parseMultiline(ln, prefix) {\n    var s = \"\";\n    for (;;) {\n        if (prefix)\n            putstr(prefix);\n        var more = readline();\n        if (more === null)\n            return null;\n        // the only command recognized in multiline mode is .end\n        if (more.match(/^[\\s]*\\.end[\\s]*$/))\n            break;\n        s += \"\\n\" + more;\n    }\n    var t = new Tokenizer(s, \"stdin\", ln.value, false);\n    var p = new Parser(t);\n    var n = p.Script(false, false);\n    ln.value = t.lineno;\n    return n;\n}\n\nexports.parse = parse;\nexports.parseStdin = parseStdin;\nexports.parseFunction = parseFunction;\nexports.Node = Node;\nexports.DECLARED_FORM = DECLARED_FORM;\nexports.EXPRESSED_FORM = EXPRESSED_FORM;\nexports.STATEMENT_FORM = STATEMENT_FORM;\nexports.Tokenizer = Tokenizer;\nexports.Parser = Parser;\nexports.Module = Module;\nexports.Export = Export;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/placeholder.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Zef Hemel <zef@c9.io>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Range = require('./range').Range;\nvar EventEmitter = require(\"./lib/event_emitter\").EventEmitter;\nvar oop = require(\"./lib/oop\");\n\nvar PlaceHolder = function(session, length, pos, others, mainClass, othersClass) {\n    var _self = this;\n    this.length = length;\n    this.session = session;\n    this.doc = session.getDocument();\n    this.mainClass = mainClass;\n    this.othersClass = othersClass;\n    this.$onUpdate = this.onUpdate.bind(this);\n    this.doc.on(\"change\", this.$onUpdate);\n    this.$others = others;\n    \n    this.$onCursorChange = function() {\n        setTimeout(function() {\n            _self.onCursorChange();\n        });\n    };\n    \n    this.$pos = pos;\n    // Used for reset\n    var undoStack = session.getUndoManager().$undoStack || session.getUndoManager().$undostack || {length: -1};\n    this.$undoStackDepth =  undoStack.length;\n    this.setup();\n\n    session.selection.on(\"changeCursor\", this.$onCursorChange);\n};\n\n(function() {\n\n    oop.implement(this, EventEmitter);\n\n    this.setup = function() {\n        var _self = this;\n        var doc = this.doc;\n        var session = this.session;\n        var pos = this.$pos;\n\n        this.pos = doc.createAnchor(pos.row, pos.column);\n        this.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column + this.length), this.mainClass, null, false);\n        this.pos.on(\"change\", function(event) {\n            session.removeMarker(_self.markerId);\n            _self.markerId = session.addMarker(new Range(event.value.row, event.value.column, event.value.row, event.value.column+_self.length), _self.mainClass, null, false);\n        });\n        this.others = [];\n        this.$others.forEach(function(other) {\n            var anchor = doc.createAnchor(other.row, other.column);\n            _self.others.push(anchor);\n        });\n        session.setUndoSelect(false);\n    };\n    \n    this.showOtherMarkers = function() {\n        if(this.othersActive) return;\n        var session = this.session;\n        var _self = this;\n        this.othersActive = true;\n        this.others.forEach(function(anchor) {\n            anchor.markerId = session.addMarker(new Range(anchor.row, anchor.column, anchor.row, anchor.column+_self.length), _self.othersClass, null, false);\n            anchor.on(\"change\", function(event) {\n                session.removeMarker(anchor.markerId);\n                anchor.markerId = session.addMarker(new Range(event.value.row, event.value.column, event.value.row, event.value.column+_self.length), _self.othersClass, null, false);\n            });\n        });\n    };\n    \n    this.hideOtherMarkers = function() {\n        if(!this.othersActive) return;\n        this.othersActive = false;\n        for (var i = 0; i < this.others.length; i++) {\n            this.session.removeMarker(this.others[i].markerId);\n        }\n    };\n\n    this.onUpdate = function(event) {\n        var delta = event.data;\n        var range = delta.range;\n        if(range.start.row !== range.end.row) return;\n        if(range.start.row !== this.pos.row) return;\n        if (this.$updating) return;\n        this.$updating = true;\n        var lengthDiff = delta.action === \"insertText\" ? range.end.column - range.start.column : range.start.column - range.end.column;\n        \n        if(range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1) {\n            var distanceFromStart = range.start.column - this.pos.column;\n            this.length += lengthDiff;\n            if(!this.session.$fromUndo) {\n                if(delta.action === \"insertText\") {\n                    for (var i = this.others.length - 1; i >= 0; i--) {\n                        var otherPos = this.others[i];\n                        var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};\n                        if(otherPos.row === range.start.row && range.start.column < otherPos.column)\n                            newPos.column += lengthDiff;\n                        this.doc.insert(newPos, delta.text);\n                    }\n                } else if(delta.action === \"removeText\") {\n                    for (var i = this.others.length - 1; i >= 0; i--) {\n                        var otherPos = this.others[i];\n                        var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart};\n                        if(otherPos.row === range.start.row && range.start.column < otherPos.column)\n                            newPos.column += lengthDiff;\n                        this.doc.remove(new Range(newPos.row, newPos.column, newPos.row, newPos.column - lengthDiff));\n                    }\n                }\n                // Special case: insert in beginning\n                if(range.start.column === this.pos.column && delta.action === \"insertText\") {\n                    setTimeout(function() {\n                        this.pos.setPosition(this.pos.row, this.pos.column - lengthDiff);\n                        for (var i = 0; i < this.others.length; i++) {\n                            var other = this.others[i];\n                            var newPos = {row: other.row, column: other.column - lengthDiff};\n                            if(other.row === range.start.row && range.start.column < other.column)\n                                newPos.column += lengthDiff;\n                            other.setPosition(newPos.row, newPos.column);\n                        }\n                    }.bind(this), 0);\n                }\n                else if(range.start.column === this.pos.column && delta.action === \"removeText\") {\n                    setTimeout(function() {\n                        for (var i = 0; i < this.others.length; i++) {\n                            var other = this.others[i];\n                            if(other.row === range.start.row && range.start.column < other.column) {\n                                other.setPosition(other.row, other.column - lengthDiff);\n                            }\n                        }\n                    }.bind(this), 0);\n                }\n            }\n            this.pos._emit(\"change\", {value: this.pos});\n            for (var i = 0; i < this.others.length; i++) {\n                this.others[i]._emit(\"change\", {value: this.others[i]});\n            }\n        }\n        this.$updating = false;\n    };\n    \n    this.onCursorChange = function(event) {\n        if (this.$updating) return;\n        var pos = this.session.selection.getCursor();\n        if(pos.row === this.pos.row && pos.column >= this.pos.column && pos.column <= this.pos.column + this.length) {\n            this.showOtherMarkers();\n            this._emit(\"cursorEnter\", event);\n        } else {\n            this.hideOtherMarkers();\n            this._emit(\"cursorLeave\", event);\n        }\n    };\n    \n    this.detach = function() {\n        this.session.removeMarker(this.markerId);\n        this.hideOtherMarkers();\n        this.doc.removeEventListener(\"change\", this.$onUpdate);\n        this.session.selection.removeEventListener(\"changeCursor\", this.$onCursorChange);\n        this.pos.detach();\n        for (var i = 0; i < this.others.length; i++) {\n            this.others[i].detach();\n        }\n        this.session.setUndoSelect(true);\n    };\n    \n    this.cancel = function() {\n        if(this.$undoStackDepth === -1)\n            throw Error(\"Canceling placeholders only supported with undo manager attached to session.\");\n        var undoManager = this.session.getUndoManager();\n        var undosRequired = (undoManager.$undoStack || undoManager.$undostack).length - this.$undoStackDepth;\n        for (var i = 0; i < undosRequired; i++) {\n            undoManager.undo(true);\n        }\n    };\n}).call(PlaceHolder.prototype);\n\n\nexports.PlaceHolder = PlaceHolder;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/placeholder_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Julian Viereck <julian DOT viereck AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n    require(\"./test/mockdom\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"./edit_session\").EditSession;\nvar Editor = require(\"./editor\").Editor;\nvar MockRenderer = require(\"./test/mockrenderer\").MockRenderer;\nvar assert = require(\"./test/assertions\");\nvar JavaScriptMode = require(\"./mode/javascript\").Mode;\nvar PlaceHolder = require('./placeholder').PlaceHolder;\nvar UndoManager = require('./undomanager').UndoManager;\n\nmodule.exports = {\n\n   \"test: simple at the end appending of text\" : function() {\n        var session = new EditSession(\"var a = 10;\\nconsole.log(a, a);\", new JavaScriptMode());\n        var editor = new Editor(new MockRenderer(), session);\n        \n        new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]);\n        \n        editor.moveCursorTo(0, 5);\n        editor.insert('b');\n        assert.equal(session.doc.getValue(), \"var ab = 10;\\nconsole.log(ab, ab);\");\n        editor.insert('cd');\n        assert.equal(session.doc.getValue(), \"var abcd = 10;\\nconsole.log(abcd, abcd);\");\n        editor.remove('left');\n        editor.remove('left');\n        editor.remove('left');\n        assert.equal(session.doc.getValue(), \"var a = 10;\\nconsole.log(a, a);\");\n    },\n\n    \"test: inserting text outside placeholder\" : function() {\n        var session = new EditSession(\"var a = 10;\\nconsole.log(a, a);\\n\", new JavaScriptMode());\n        var editor = new Editor(new MockRenderer(), session);\n        \n        new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]);\n        \n        editor.moveCursorTo(2, 0);\n        editor.insert('b');\n        assert.equal(session.doc.getValue(), \"var a = 10;\\nconsole.log(a, a);\\nb\");\n    },\n    \n   \"test: insertion at the beginning\" : function(next) {\n        var session = new EditSession(\"var a = 10;\\nconsole.log(a, a);\", new JavaScriptMode());\n        var editor = new Editor(new MockRenderer(), session);\n        \n        var p = new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]);\n        \n        editor.moveCursorTo(0, 4);\n        editor.insert('$');\n        assert.equal(session.doc.getValue(), \"var $a = 10;\\nconsole.log($a, $a);\");\n        editor.moveCursorTo(0, 4);\n        // Have to put this in a setTimeout because the anchor is only fixed later.\n        setTimeout(function() {\n            editor.insert('v');\n            assert.equal(session.doc.getValue(), \"var v$a = 10;\\nconsole.log(v$a, v$a);\");\n            next();\n        }, 10);\n    },\n\n   \"test: detaching placeholder\" : function() {\n        var session = new EditSession(\"var a = 10;\\nconsole.log(a, a);\", new JavaScriptMode());\n        var editor = new Editor(new MockRenderer(), session);\n        \n        var p = new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]);\n        \n        editor.moveCursorTo(0, 5);\n        editor.insert('b');\n        assert.equal(session.doc.getValue(), \"var ab = 10;\\nconsole.log(ab, ab);\");\n        p.detach();\n        editor.insert('cd');\n        assert.equal(session.doc.getValue(), \"var abcd = 10;\\nconsole.log(ab, ab);\");\n    },\n\n   \"test: events\" : function() {\n        var session = new EditSession(\"var a = 10;\\nconsole.log(a, a);\", new JavaScriptMode());\n        var editor = new Editor(new MockRenderer(), session);\n        \n        var p = new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]);\n        var entered = false;\n        var left = false;\n        p.on(\"cursorEnter\", function() {\n            entered = true;\n        });\n        p.on(\"cursorLeave\", function() {\n            left = true;\n        });\n        \n        editor.moveCursorTo(0, 0);\n        editor.moveCursorTo(0, 4);\n        p.onCursorChange(); // Have to do this by hand because moveCursorTo doesn't trigger the event\n        assert.ok(entered);\n        editor.moveCursorTo(1, 0);\n        p.onCursorChange(); // Have to do this by hand because moveCursorTo doesn't trigger the event\n        assert.ok(left);\n    },\n    \n    \"test: cancel\": function(next) {\n        var session = new EditSession(\"var a = 10;\\nconsole.log(a, a);\", new JavaScriptMode());\n        session.setUndoManager(new UndoManager());\n        var editor = new Editor(new MockRenderer(), session);\n        var p = new PlaceHolder(session, 1, {row: 0, column: 4}, [{row: 1, column: 12}, {row: 1, column: 15}]);\n        \n        editor.moveCursorTo(0, 5);\n        editor.insert('b');\n        editor.insert('cd');\n        editor.remove('left');\n        assert.equal(session.doc.getValue(), \"var abc = 10;\\nconsole.log(abc, abc);\");\n        // Wait a little for the changes to enter the undo stack\n        setTimeout(function() {\n            p.cancel();\n            assert.equal(session.doc.getValue(), \"var a = 10;\\nconsole.log(a, a);\");\n            next();\n        }, 80);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/range.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Range = function(startRow, startColumn, endRow, endColumn) {\n    this.start = {\n        row: startRow,\n        column: startColumn\n    };\n\n    this.end = {\n        row: endRow,\n        column: endColumn\n    };\n};\n\n(function() {\n    this.isEqual = function(range) {\n        return this.start.row == range.start.row &&\n            this.end.row == range.end.row &&\n            this.start.column == range.start.column &&\n            this.end.column == range.end.column\n    };\n\n    this.toString = function() {\n        return (\"Range: [\" + this.start.row + \"/\" + this.start.column +\n            \"] -> [\" + this.end.row + \"/\" + this.end.column + \"]\");\n    };\n\n    this.contains = function(row, column) {\n        return this.compare(row, column) == 0;\n    };\n\n    /**\n     * Compares this range (A) with another range (B), where B is the passed in\n     * range.\n     *\n     * Return values:\n     *  -2: (B) is infront of (A) and doesn't intersect with (A)\n     *  -1: (B) begins before (A) but ends inside of (A)\n     *   0: (B) is completly inside of (A) OR (A) is complety inside of (B)\n     *  +1: (B) begins inside of (A) but ends outside of (A)\n     *  +2: (B) is after (A) and doesn't intersect with (A)\n     *\n     *  42: FTW state: (B) ends in (A) but starts outside of (A)\n     */\n    this.compareRange = function(range) {\n        var cmp,\n            end = range.end,\n            start = range.start;\n\n        cmp = this.compare(end.row, end.column);\n        if (cmp == 1) {\n            cmp = this.compare(start.row, start.column);\n            if (cmp == 1) {\n                return 2;\n            } else if (cmp == 0) {\n                return 1;\n            } else {\n                return 0;\n            }\n        } else if (cmp == -1) {\n            return -2;\n        } else {\n            cmp = this.compare(start.row, start.column);\n            if (cmp == -1) {\n                return -1;\n            } else if (cmp == 1) {\n                return 42;\n            } else {\n                return 0;\n            }\n        }\n    }\n\n    this.comparePoint = function(p) {\n        return this.compare(p.row, p.column);\n    }\n\n    this.containsRange = function(range) {\n        return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0;\n    }\n\n    this.intersects = function(range) {\n        var cmp = this.compareRange(range);\n        return (cmp == -1 || cmp == 0 || cmp == 1);\n    }\n\n    this.isEnd = function(row, column) {\n        return this.end.row == row && this.end.column == column;\n    }\n\n    this.isStart = function(row, column) {\n        return this.start.row == row && this.start.column == column;\n    }\n\n    this.setStart = function(row, column) {\n        if (typeof row == \"object\") {\n            this.start.column = row.column;\n            this.start.row = row.row;\n        } else {\n            this.start.row = row;\n            this.start.column = column;\n        }\n    }\n\n    this.setEnd = function(row, column) {\n        if (typeof row == \"object\") {\n            this.end.column = row.column;\n            this.end.row = row.row;\n        } else {\n            this.end.row = row;\n            this.end.column = column;\n        }\n    }\n\n    this.inside = function(row, column) {\n        if (this.compare(row, column) == 0) {\n            if (this.isEnd(row, column) || this.isStart(row, column)) {\n                return false;\n            } else {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    this.insideStart = function(row, column) {\n        if (this.compare(row, column) == 0) {\n            if (this.isEnd(row, column)) {\n                return false;\n            } else {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    this.insideEnd = function(row, column) {\n        if (this.compare(row, column) == 0) {\n            if (this.isStart(row, column)) {\n                return false;\n            } else {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    this.compare = function(row, column) {\n        if (!this.isMultiLine()) {\n            if (row === this.start.row) {\n                return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0);\n            };\n        }\n\n        if (row < this.start.row)\n            return -1;\n\n        if (row > this.end.row)\n            return 1;\n\n        if (this.start.row === row)\n            return column >= this.start.column ? 0 : -1;\n\n        if (this.end.row === row)\n            return column <= this.end.column ? 0 : 1;\n\n        return 0;\n    };\n\n    /**\n     * Like .compare(), but if isStart is true, return -1;\n     */\n    this.compareStart = function(row, column) {\n        if (this.start.row == row && this.start.column == column) {\n            return -1;\n        } else {\n            return this.compare(row, column);\n        }\n    }\n\n    /**\n     * Like .compare(), but if isEnd is true, return 1;\n     */\n    this.compareEnd = function(row, column) {\n        if (this.end.row == row && this.end.column == column) {\n            return 1;\n        } else {\n            return this.compare(row, column);\n        }\n    }\n\n    this.compareInside = function(row, column) {\n        if (this.end.row == row && this.end.column == column) {\n            return 1;\n        } else if (this.start.row == row && this.start.column == column) {\n            return -1;\n        } else {\n            return this.compare(row, column);\n        }\n    }\n\n    this.clipRows = function(firstRow, lastRow) {\n        if (this.end.row > lastRow) {\n            var end = {\n                row: lastRow+1,\n                column: 0\n            };\n        }\n\n        if (this.start.row > lastRow) {\n            var start = {\n                row: lastRow+1,\n                column: 0\n            };\n        }\n\n        if (this.start.row < firstRow) {\n            var start = {\n                row: firstRow,\n                column: 0\n            };\n        }\n\n        if (this.end.row < firstRow) {\n            var end = {\n                row: firstRow,\n                column: 0\n            };\n        }\n        return Range.fromPoints(start || this.start, end || this.end);\n    };\n\n    this.extend = function(row, column) {\n        var cmp = this.compare(row, column);\n\n        if (cmp == 0)\n            return this;\n        else if (cmp == -1)\n            var start = {row: row, column: column};\n        else\n            var end = {row: row, column: column};\n\n        return Range.fromPoints(start || this.start, end || this.end);\n    };\n\n    this.fixOrientation = function() {\n        if (\n            this.start.row < this.end.row \n            || (this.start.row == this.end.row && this.start.column < this.end.column)\n        ) {\n            return false;\n        }\n        \n        var temp = this.start;\n        this.end = this.start;\n        this.start = temp;\n        return true;\n    };\n\n\n    this.isEmpty = function() {\n        return (this.start.row == this.end.row && this.start.column == this.end.column);\n    };\n\n    this.isMultiLine = function() {\n        return (this.start.row !== this.end.row);\n    };\n\n    this.clone = function() {\n        return Range.fromPoints(this.start, this.end);\n    };\n\n    this.collapseRows = function() {\n        if (this.end.column == 0)\n            return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0)\n        else\n            return new Range(this.start.row, 0, this.end.row, 0)\n    };\n\n    this.toScreenRange = function(session) {\n        var screenPosStart =\n            session.documentToScreenPosition(this.start);\n        var screenPosEnd =\n            session.documentToScreenPosition(this.end);\n\n        return new Range(\n            screenPosStart.row, screenPosStart.column,\n            screenPosEnd.row, screenPosEnd.column\n        );\n    };\n\n}).call(Range.prototype);\n\n\nRange.fromPoints = function(start, end) {\n    return new Range(start.row, start.column, end.row, end.column);\n};\n\nexports.Range = Range;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/range_list.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Harutyun Amirjanyan <amirjanyan AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\n\nvar RangeList = function() {\n    this.ranges = [];\n};\n\n(function() {\n    this.comparePoints = function(p1, p2) {\n        return p1.row - p2.row || p1.column - p2.column;\n    };\n\n    this.pointIndex = function(pos, startIndex) {\n        var list = this.ranges;\n\n        for (var i = startIndex || 0; i < list.length; i++) {\n            var range = list[i];\n            var cmp = this.comparePoints(pos, range.end);\n\n            if (cmp > 0)\n                continue;\n            if (cmp == 0)\n                return i;\n            cmp = this.comparePoints(pos, range.start);\n            if (cmp >= 0)\n                return i;\n\n            return -i-1;\n        }\n        return -i - 1;\n    };\n\n    this.add = function(range) {\n        var startIndex = this.pointIndex(range.start);\n        if (startIndex < 0)\n            startIndex = -startIndex - 1;\n\n        var endIndex = this.pointIndex(range.end, startIndex);\n\n        if (endIndex < 0)\n            endIndex = -endIndex - 1;\n        else\n            endIndex++;\n\n        return this.ranges.splice(startIndex, endIndex - startIndex, range);\n    };\n\n    this.addList = function(list) {\n        var removed = [];\n        for (var i = list.length; i--; ) {\n            removed.push.call(removed, this.add(list[i]));\n        }\n        return removed;\n    };\n\n    this.substractPoint = function(pos) {\n        var i = this.pointIndex(pos);\n\n        if (i >= 0)\n            return this.ranges.splice(i, 1);\n    };\n\n    // merge overlapping ranges\n    this.merge = function() {\n        var removed = [];\n        var list = this.ranges;\n        var next = list[0], range;\n        for (var i = 1; i < list.length; i++) {\n            range = next;\n            next = list[i];\n            var cmp = this.comparePoints(range.end, next.start);\n            if (cmp < 0)\n                continue;\n\n            if (cmp == 0 && !(range.isEmpty() || next.isEmpty()))\n                continue;\n\n            if (this.comparePoints(range.end, next.end) < 0) {\n                range.end.row = next.end.row;\n                range.end.column = next.end.column;\n            }\n\n            list.splice(i, 1);\n            removed.push(next);\n            next = range;\n            i--;\n        }\n\n        return removed;\n    };\n\n    this.contains = function(row, column) {\n        return this.pointIndex({row: row, column: column}) >= 0;\n    };\n\n    this.containsPoint = function(pos) {\n        return this.pointIndex(pos) >= 0;\n    };\n\n    this.rangeAtPoint = function(pos) {\n        var i = this.pointIndex(pos);\n        if (i >= 0)\n            return this.ranges[i];\n    };\n\n\n    this.clipRows = function(startRow, endRow) {\n        var list = this.ranges;\n        if (list[0].start.row > endRow || list[list.length - 1].start.row < startRow)\n            return [];\n\n        var startIndex = this.pointIndex({row: startRow, column: 0});\n        if (startIndex < 0)\n            startIndex = -startIndex - 1;\n        var endIndex = this.pointIndex({row: endRow, column: 0}, startIndex);\n        if (endIndex < 0)\n            endIndex = -endIndex - 1;\n\n        var clipped = [];\n        for (var i = startIndex; i < endIndex; i++) {\n            clipped.push(list[i]);\n        }\n        return clipped;\n    };\n\n    this.removeAll = function() {\n        return this.ranges.splice(0, this.ranges.length);\n    };\n\n    this.attach = function(session) {\n        if (this.session)\n            this.detach();\n\n        this.session = session;\n        this.onChange = this.$onChange.bind(this);\n\n        this.session.on('change', this.onChange);\n    };\n\n    this.detach = function() {\n        if (!this.session)\n            return;\n        this.session.removeListener('change', this.onChange);\n        this.session = null;\n    };\n\n    this.$onChange = function(e) {\n        var changeRange = e.data.range;\n        if (e.data.action[0] == \"i\"){\n            var start = changeRange.start;\n            var end = changeRange.end;\n        } else {\n            var end = changeRange.start;\n            var start = changeRange.end;\n        }\n        var startRow = start.row;\n        var endRow = end.row;\n        var lineDif = endRow - startRow;\n\n        var colDiff = -start.column + end.column;\n\n        var ranges = this.ranges;\n\n        for (var i=0, n = ranges.length; i < n; i++) {\n            var r = ranges[i];\n            if (r.end.row < startRow)\n                continue;\n            if (r.start.row > startRow)\n                break;\n\n            if (r.start.row == startRow && r.start.column >= start.column ) {\n                r.start.column += colDiff;\n                r.start.row += lineDif;\n            }\n            if (r.end.row == startRow && r.end.column >=  start.column) {\n                r.end.column += colDiff;\n                r.end.row += lineDif;\n            }\n        }\n\n        if (lineDif != 0 && i < n) {\n            for (; i < n; i++) {\n                var r = ranges[i];\n                r.start.row += lineDif;\n                r.end.row += lineDif;\n            }\n        }\n    };\n\n}).call(RangeList.prototype);\n\nexports.RangeList = RangeList;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/range_list_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Range = require(\"./range\").Range;\nvar RangeList = require(\"./range_list\").RangeList;\nvar EditSession = require(\"./edit_session\").EditSession;\nvar assert = require(\"./test/assertions\");\n\nfunction flatten(rangeList) {\n    var points = [];\n    rangeList.ranges.forEach(function(r) {\n        points.push(r.start.row, r.start.column, r.end.row, r.end.column)\n    })\n    return points;\n}\nfunction testRangeList(rangeList, points) {\n    assert.equal(\"\" + flatten(rangeList), \"\" + points);\n}\n\nmodule.exports = {\n\n    name: \"ACE range_list.js\",\n\n    \"test: rangeList pointIndex\": function() {\n        var rangeList = new RangeList();\n        rangeList.ranges = [\n            new Range(1,2,3,4),\n            new Range(4,2,5,4),\n            new Range(8,8,9,9)\n        ];\n\n        assert.equal(rangeList.pointIndex({row: 0, column: 1}), -1);\n        assert.equal(rangeList.pointIndex({row: 1, column: 2}), 0);\n        assert.equal(rangeList.pointIndex({row: 1, column: 3}), 0);\n        assert.equal(rangeList.pointIndex({row: 3, column: 4}), 0);\n        assert.equal(rangeList.pointIndex({row: 4, column: 1}), -2);\n        assert.equal(rangeList.pointIndex({row: 5, column: 1}), 1);\n        assert.equal(rangeList.pointIndex({row: 8, column: 9}), 2);\n        assert.equal(rangeList.pointIndex({row: 18, column: 9}), -4);\n    },\n\n    \"test: rangeList add\": function() {\n        var rangeList = new RangeList();\n        rangeList.addList([\n            new Range(9,0,9,1),\n            new Range(1,2,3,4),\n            new Range(8,8,9,9),\n            new Range(4,2,5,4),\n            new Range(3,20,3,24),\n            new Range(6,6,7,7)\n        ]);\n        assert.equal(rangeList.ranges.length, 5);\n\n        rangeList.add(new Range(1,2,3,5));\n        assert.range(rangeList.ranges[0], 1,2,3,5);\n        assert.equal(rangeList.ranges.length, 5);\n\n        rangeList.add(new Range(7,7,7,7));\n        assert.range(rangeList.ranges[3], 7,7,7,7);\n        rangeList.add(new Range(7,8,7,8));\n        assert.range(rangeList.ranges[4], 7,8,7,8);\n    },\n\n    \"test: rangeList add empty\": function() {\n        var rangeList = new RangeList();\n        rangeList.addList([\n            new Range(7,10,7,10),\n            new Range(9,10,9,10),\n            new Range(8,10,8,10)\n        ]);\n        assert.equal(rangeList.ranges.length, 3);\n\n        rangeList.add(new Range(9,10,9,10));\n        testRangeList(rangeList, [7,10,7,10,8,10,8,10,9,10,9,10]);\n    },\n\n    \"test: rangeList merge\": function() {\n        var rangeList = new RangeList();\n        rangeList.addList([\n            new Range(1,2,3,4),\n            new Range(4,2,5,4),\n            new Range(6,6,7,7),\n            new Range(8,8,9,9)\n        ]);\n        var removed = [];\n\n        assert.equal(rangeList.ranges.length, 4);\n\n        rangeList.ranges[1].end.row = 7;\n        removed = rangeList.merge();\n        assert.equal(removed.length, 1);\n        assert.range(rangeList.ranges[1], 4,2,7,7);\n        assert.equal(rangeList.ranges.length, 3);\n\n        rangeList.ranges[0].end.row = 10;\n        removed = rangeList.merge();\n        assert.range(rangeList.ranges[0], 1,2,10,4);\n        assert.equal(removed.length, 2);\n        assert.equal(rangeList.ranges.length, 1);\n\n        rangeList.ranges.push(new Range(10,10,10,10));\n        rangeList.ranges.push(new Range(10,10,10,10));\n        removed = rangeList.merge();\n        assert.equal(rangeList.ranges.length, 2);\n    },\n\n    \"test: rangeList remove\": function() {\n        var rangeList = new RangeList();\n        var list = [\n            new Range(1,2,3,4),\n            new Range(4,2,5,4),\n            new Range(6,6,7,7),\n            new Range(8,8,9,9)\n        ];\n        rangeList.addList(list);\n        assert.equal(rangeList.ranges.length, 4);\n        rangeList.substractPoint({row: 1, column: 2});\n        assert.equal(rangeList.ranges.length, 3);\n        rangeList.substractPoint({row: 6, column: 7});\n        assert.equal(rangeList.ranges.length, 2);\n    }\n\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/range_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Range = require(\"./range\").Range;\nvar EditSession = require(\"./edit_session\").EditSession;\nvar assert = require(\"./test/assertions\");\n\nmodule.exports = {\n    \n    name: \"ACE range.js\",\n    \n    \"test: create range\": function() {\n        var range = new Range(1,2,3,4);\n\n        assert.equal(range.start.row, 1);\n        assert.equal(range.start.column, 2);\n        assert.equal(range.end.row, 3);\n        assert.equal(range.end.column, 4);\n    },\n\n    \"test: create from points\": function() {\n        var range = Range.fromPoints({row: 1, column: 2}, {row:3, column:4});\n\n        assert.equal(range.start.row, 1);\n        assert.equal(range.start.column, 2);\n        assert.equal(range.end.row, 3);\n        assert.equal(range.end.column, 4);\n    },\n\n    \"test: clip to rows\": function() {\n        assert.range(new Range(0, 20, 100, 30).clipRows(10, 30), 10, 0, 31, 0);\n        assert.range(new Range(0, 20, 30, 10).clipRows(10, 30), 10, 0, 30, 10);\n\n        var range = new Range(0, 20, 3, 10);\n        var range = range.clipRows(10, 30);\n\n        assert.ok(range.isEmpty());\n        assert.range(range, 10, 0, 10, 0);\n    },\n\n    \"test: isEmpty\": function() {\n        var range = new Range(1, 2, 1, 2);\n        assert.ok(range.isEmpty());\n\n        var range = new Range(1, 2, 1, 6);\n        assert.notOk(range.isEmpty());\n    },\n\n    \"test: is multi line\": function() {\n        var range = new Range(1, 2, 1, 6);\n        assert.notOk(range.isMultiLine());\n\n        var range = new Range(1, 2, 2, 6);\n        assert.ok(range.isMultiLine());\n    },\n\n    \"test: clone\": function() {\n        var range = new Range(1, 2, 3, 4);\n        var clone = range.clone();\n\n        assert.position(clone.start, 1, 2);\n        assert.position(clone.end, 3, 4);\n\n        clone.start.column = 20;\n        assert.position(range.start, 1, 2);\n\n        clone.end.column = 20;\n        assert.position(range.end, 3, 4);\n    },\n\n    \"test: contains for multi line ranges\": function() {\n        var range = new Range(1, 10, 5, 20);\n\n        assert.ok(range.contains(1, 10));\n        assert.ok(range.contains(2, 0));\n        assert.ok(range.contains(3, 100));\n        assert.ok(range.contains(5, 19));\n        assert.ok(range.contains(5, 20));\n\n        assert.notOk(range.contains(1, 9));\n        assert.notOk(range.contains(0, 0));\n        assert.notOk(range.contains(5, 21));\n    },\n\n    \"test: contains for single line ranges\": function() {\n        var range = new Range(1, 10, 1, 20);\n\n        assert.ok(range.contains(1, 10));\n        assert.ok(range.contains(1, 15));\n        assert.ok(range.contains(1, 20));\n\n        assert.notOk(range.contains(0, 9));\n        assert.notOk(range.contains(2, 9));\n        assert.notOk(range.contains(1, 9));\n        assert.notOk(range.contains(1, 21));\n    },\n\n    \"test: extend range\": function() {\n        var range = new Range(2, 10, 2, 30);\n\n        var range = range.extend(2, 5);\n        assert.range(range, 2, 5, 2, 30);\n\n        var range = range.extend(2, 35);\n        assert.range(range, 2, 5, 2, 35);\n\n        var range = range.extend(2, 15);\n        assert.range(range, 2, 5, 2, 35);\n\n        var range = range.extend(1, 4);\n        assert.range(range, 1, 4, 2, 35);\n\n        var range = range.extend(6, 10);\n        assert.range(range, 1, 4, 6, 10);\n    },\n\n    \"test: collapse rows\" : function() {\n        var range = new Range(0, 2, 1, 2);\n        assert.range(range.collapseRows(), 0, 0, 1, 0);\n\n        var range = new Range(2, 2, 3, 1);\n        assert.range(range.collapseRows(), 2, 0, 3, 0);\n\n        var range = new Range(2, 2, 3, 0);\n        assert.range(range.collapseRows(), 2, 0, 2, 0);\n\n        var range = new Range(2, 0, 2, 0);\n        assert.range(range.collapseRows(), 2, 0, 2, 0);\n    },\n    \n    \"test: to screen range\" : function() {\n        var session = new EditSession([\n            \"juhu\",\n            \"12\\t\\t34\",\n            \"ぁぁa\",\n            \"\\t\\t34\",\n        ]);\n        \n        var range = new Range(0, 0, 0, 3);\n        assert.range(range.toScreenRange(session), 0, 0, 0, 3);\n        \n        var range = new Range(1, 1, 1, 3);\n        assert.range(range.toScreenRange(session), 1, 1, 1, 4);\n        \n        var range = new Range(2, 1, 2, 2);\n        assert.range(range.toScreenRange(session), 2, 2, 2, 4);\n\n        var range = new Range(3, 0, 3, 4);\n        assert.range(range.toScreenRange(session), 3, 0, 3, 10);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/renderloop.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar event = require(\"./lib/event\");\n\nvar RenderLoop = function(onRender, win) {\n    this.onRender = onRender;\n    this.pending = false;\n    this.changes = 0;\n    this.window = win || window;\n};\n\n(function() {\n\n    this.schedule = function(change) {\n        //this.onRender(change);\n        //return;\n        this.changes = this.changes | change;\n        if (!this.pending) {\n            this.pending = true;\n            var _self = this;\n            event.nextTick(function() {\n                _self.pending = false;\n                var changes;\n                while (changes = _self.changes) {\n                    _self.changes = 0;\n                    _self.onRender(changes);\n                }\n            }, this.window);\n        }\n    };\n\n}).call(RenderLoop.prototype);\n\nexports.RenderLoop = RenderLoop;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/requirejs/text.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\n/**\n * Extremely simplified version of the requireJS text plugin\n */\n \n(function() {\n    \nvar globalRequire = require;\n \ndefine(function (require, exports, module) {\n    \"use strict\";\n    \n    exports.load = function (name, req, onLoad, config) {\n        if (req.isBrowser)\n            require(\"ace/lib/net\").get(req.toUrl(name), onLoad);\n        else\n            //Using special require.nodeRequire, something added by r.js.\n            onLoad(globalRequire.nodeRequire('fs').readFileSync(req.toUrl(name), 'utf8'));\n    };\n});\n\n})();\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/scrollbar.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"./lib/oop\");\nvar dom = require(\"./lib/dom\");\nvar event = require(\"./lib/event\");\nvar EventEmitter = require(\"./lib/event_emitter\").EventEmitter;\n\nvar ScrollBar = function(parent) {\n    this.element = dom.createElement(\"div\");\n    this.element.className = \"ace_sb\";\n\n    this.inner = dom.createElement(\"div\");\n    this.element.appendChild(this.inner);\n\n    parent.appendChild(this.element);\n\n    // in OSX lion the scrollbars appear to have no width. In this case resize\n    // the to show the scrollbar but still pretend that the scrollbar has a width\n    // of 0px\n    // in Firefox 6+ scrollbar is hidden if element has the same width as scrollbar\n    // make element a little bit wider to retain scrollbar when page is zoomed \n    this.width = dom.scrollbarWidth(parent.ownerDocument);\n    this.element.style.width = (this.width || 15) + 5 + \"px\";\n\n    event.addListener(this.element, \"scroll\", this.onScroll.bind(this));\n};\n\n(function() {\n    oop.implement(this, EventEmitter);\n\n    this.onScroll = function() {\n        this._emit(\"scroll\", {data: this.element.scrollTop});\n    };\n\n    this.getWidth = function() {\n        return this.width;\n    };\n\n    this.setHeight = function(height) {\n        this.element.style.height = height + \"px\";\n    };\n\n    this.setInnerHeight = function(height) {\n        this.inner.style.height = height + \"px\";\n    };\n\n    // TODO: on chrome 17+ after for small zoom levels after this function\n    // this.element.scrollTop != scrollTop which makes page to scroll up.\n    this.setScrollTop = function(scrollTop) {\n        this.element.scrollTop = scrollTop;\n    };\n\n}).call(ScrollBar.prototype);\n\nexports.ScrollBar = ScrollBar;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/search.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Mihai Sucan <mihai DOT sucan AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar lang = require(\"./lib/lang\");\nvar oop = require(\"./lib/oop\");\nvar Range = require(\"./range\").Range;\n\nvar Search = function() {\n    this.$options = {\n        needle: \"\",\n        backwards: false,\n        wrap: false,\n        caseSensitive: false,\n        wholeWord: false,\n        scope: Search.ALL,\n        regExp: false\n    };\n};\n\nSearch.ALL = 1;\nSearch.SELECTION = 2;\n\n(function() {\n\n    this.set = function(options) {\n        oop.mixin(this.$options, options);\n        return this;\n    };\n    \n    this.getOptions = function() {\n        return lang.copyObject(this.$options);\n    };\n\n    this.find = function(session) {\n        if (!this.$options.needle)\n            return null;\n\n        if (this.$options.backwards) {\n            var iterator = this.$backwardMatchIterator(session);\n        } else {\n            iterator = this.$forwardMatchIterator(session);\n        }\n\n        var firstRange = null;\n        iterator.forEach(function(range) {\n            firstRange = range;\n            return true;\n        });\n\n        return firstRange;\n    };\n\n    this.findAll = function(session) {\n        var options = this.$options;\n        if (!options.needle)\n            return [];\n\n        if (options.backwards) {\n            var iterator = this.$backwardMatchIterator(session);\n        } else {\n            iterator = this.$forwardMatchIterator(session);\n        }\n\n        var ignoreCursor = !options.start && options.wrap && options.scope == Search.ALL;\n        if (ignoreCursor)\n            options.start = {row: 0, column: 0};\n\n        var ranges = [];\n        iterator.forEach(function(range) {\n            ranges.push(range);\n        });\n\n        if (ignoreCursor)\n            options.start = null;\n\n        return ranges;\n    };\n\n    this.replace = function(input, replacement) {\n        var re = this.$assembleRegExp();\n        var match = re.exec(input);\n        if (match && match[0].length == input.length) {\n            if (this.$options.regExp) {\n                return input.replace(re, replacement);\n            } else {\n                return replacement;\n            }\n        } else {\n            return null;\n        }\n    };\n\n    this.$forwardMatchIterator = function(session) {\n        var re = this.$assembleRegExp();\n        var self = this;\n\n        return {\n            forEach: function(callback) {\n                self.$forwardLineIterator(session).forEach(function(line, startIndex, row) {\n                    if (startIndex) {\n                        line = line.substring(startIndex);\n                    }\n\n                    var matches = [];\n\n                    line.replace(re, function(str) {\n                        var offset = arguments[arguments.length-2];\n                        matches.push({\n                            str: str,\n                            offset: startIndex + offset\n                        });\n                        return str;\n                    });\n\n                    for (var i=0; i<matches.length; i++) {\n                        var match = matches[i];\n                        var range = self.$rangeFromMatch(row, match.offset, match.str.length);\n                        if (callback(range))\n                            return true;\n                    }\n\n                });\n            }\n        };\n    };\n\n    this.$backwardMatchIterator = function(session) {\n        var re = this.$assembleRegExp();\n        var self = this;\n\n        return {\n            forEach: function(callback) {\n                self.$backwardLineIterator(session).forEach(function(line, startIndex, row) {\n                    if (startIndex) {\n                        line = line.substring(startIndex);\n                    }\n\n                    var matches = [];\n\n                    line.replace(re, function(str, offset) {\n                        matches.push({\n                            str: str,\n                            offset: startIndex + offset\n                        });\n                        return str;\n                    });\n\n                    for (var i=matches.length-1; i>= 0; i--) {\n                        var match = matches[i];\n                        var range = self.$rangeFromMatch(row, match.offset, match.str.length);\n                        if (callback(range))\n                            return true;\n                    }\n                });\n            }\n        };\n    };\n\n    this.$rangeFromMatch = function(row, column, length) {\n        return new Range(row, column, row, column+length);\n    };\n\n    this.$assembleRegExp = function() {\n        if (this.$options.regExp) {\n            var needle = this.$options.needle;\n        } else {\n            needle = lang.escapeRegExp(this.$options.needle);\n        }\n\n        if (this.$options.wholeWord) {\n            needle = \"\\\\b\" + needle + \"\\\\b\";\n        }\n\n        var modifier = \"g\";\n        if (!this.$options.caseSensitive) {\n            modifier += \"i\";\n        }\n\n        var re = new RegExp(needle, modifier);\n        return re;\n    };\n\n    this.$forwardLineIterator = function(session) {\n        var searchSelection = this.$options.scope == Search.SELECTION;\n\n        var range = this.$options.range || session.getSelection().getRange();\n        var start = this.$options.start || range[searchSelection ? \"start\" : \"end\"];\n\n        var firstRow = searchSelection ? range.start.row : 0;\n        var firstColumn = searchSelection ? range.start.column : 0;\n        var lastRow = searchSelection ? range.end.row : session.getLength() - 1;\n\n        var wrap = this.$options.wrap;\n        var inWrap = false;\n\n        function getLine(row) {\n            var line = session.getLine(row);\n            if (searchSelection && row == range.end.row) {\n                line = line.substring(0, range.end.column);\n            }\n            if (inWrap && row == start.row) {\n                line = line.substring(0, start.column);\n            }\n            return line;\n        }\n\n        return {\n            forEach: function(callback) {\n                var row = start.row;\n\n                var line = getLine(row);\n                var startIndex = start.column;\n\n                var stop = false;\n                inWrap = false;\n\n                while (!callback(line, startIndex, row)) {\n\n                    if (stop) {\n                        return;\n                    }\n\n                    row++;\n                    startIndex = 0;\n\n                    if (row > lastRow) {\n                        if (wrap) {\n                            row = firstRow;\n                            startIndex = firstColumn;\n                            inWrap = true;\n                        } else {\n                            return;\n                        }\n                    }\n\n                    if (row == start.row)\n                        stop = true;\n\n                    line = getLine(row);\n                }\n            }\n        };\n    };\n\n    this.$backwardLineIterator = function(session) {\n        var searchSelection = this.$options.scope == Search.SELECTION;\n\n        var range = this.$options.range || session.getSelection().getRange();\n        var start = this.$options.start || range[searchSelection ? \"end\" : \"start\"];\n\n        var firstRow = searchSelection ? range.start.row : 0;\n        var firstColumn = searchSelection ? range.start.column : 0;\n        var lastRow = searchSelection ? range.end.row : session.getLength() - 1;\n\n        var wrap = this.$options.wrap;\n\n        return {\n            forEach : function(callback) {\n                var row = start.row;\n\n                var line = session.getLine(row).substring(0, start.column);\n                var startIndex = 0;\n                var stop = false;\n                var inWrap = false;\n\n                while (!callback(line, startIndex, row)) {\n\n                    if (stop)\n                        return;\n\n                    row--;\n                    startIndex = 0;\n\n                    if (row < firstRow) {\n                        if (wrap) {\n                            row = lastRow;\n                            inWrap = true;\n                        } else {\n                            return;\n                        }\n                    }\n\n                    if (row == start.row)\n                        stop = true;\n\n                    line = session.getLine(row);\n                    if (searchSelection) {\n                        if (row == firstRow)\n                            startIndex = firstColumn;\n                        else if (row == lastRow)\n                            line = line.substring(0, range.end.column);\n                    }\n\n                    if (inWrap && row == start.row)\n                        startIndex = start.column;\n                }\n            }\n        };\n    };\n\n}).call(Search.prototype);\n\nexports.Search = Search;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/search_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Mihai Sucan <mihai DOT sucan AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"./edit_session\").EditSession;\nvar Search = require(\"./search\").Search;\nvar assert = require(\"./test/assertions\");\n\nmodule.exports = {\n    \"test: configure the search object\" : function() {\n        var search = new Search();\n        search.set({\n            needle: \"juhu\",\n            scope: Search.ALL\n        });\n    },\n\n    \"test: find simple text in document\" : function() {\n        var session = new EditSession([\"juhu kinners 123\", \"456\"]);\n        var search = new Search().set({\n            needle: \"kinners\"\n        });\n\n        var range = search.find(session);\n        assert.position(range.start, 0, 5);\n        assert.position(range.end, 0, 12);\n    },\n\n    \"test: find simple text in next line\" : function() {\n        var session = new EditSession([\"abc\", \"juhu kinners 123\", \"456\"]);\n        var search = new Search().set({\n            needle: \"kinners\"\n        });\n\n        var range = search.find(session);\n        assert.position(range.start, 1, 5);\n        assert.position(range.end, 1, 12);\n    },\n\n    \"test: find text starting at cursor position\" : function() {\n        var session = new EditSession([\"juhu kinners\", \"juhu kinners 123\"]);\n        session.getSelection().moveCursorTo(0, 6);\n        var search = new Search().set({\n            needle: \"kinners\"\n        });\n\n        var range = search.find(session);\n        assert.position(range.start, 1, 5);\n        assert.position(range.end, 1, 12);\n    },\n\n    \"test: wrap search is off by default\" : function() {\n        var session = new EditSession([\"abc\", \"juhu kinners 123\", \"456\"]);\n        session.getSelection().moveCursorTo(2, 1);\n\n        var search = new Search().set({\n            needle: \"kinners\"\n        });\n\n        assert.equal(search.find(session), null);\n    },\n\n    \"test: wrap search should wrap at file end\" : function() {\n        var session = new EditSession([\"abc\", \"juhu kinners 123\", \"456\"]);\n        session.getSelection().moveCursorTo(2, 1);\n\n        var search = new Search().set({\n            needle: \"kinners\",\n            wrap: true\n        });\n\n        var range = search.find(session);\n        assert.position(range.start, 1, 5);\n        assert.position(range.end, 1, 12);\n    },\n\n    \"test: wrap search with no match should return 'null'\": function() {\n        var session = new EditSession([\"abc\", \"juhu kinners 123\", \"456\"]);\n        session.getSelection().moveCursorTo(2, 1);\n\n        var search = new Search().set({\n            needle: \"xyz\",\n            wrap: true\n        });\n\n        assert.equal(search.find(session), null);\n    },\n\n    \"test: case sensitive is by default off\": function() {\n        var session = new EditSession([\"abc\", \"juhu kinners 123\", \"456\"]);\n\n        var search = new Search().set({\n            needle: \"JUHU\"\n        });\n\n        assert.range(search.find(session), 1, 0, 1, 4);\n    },\n\n    \"test: case sensitive search\": function() {\n        var session = new EditSession([\"abc\", \"juhu kinners 123\", \"456\"]);\n\n        var search = new Search().set({\n            needle: \"KINNERS\",\n            caseSensitive: true\n        });\n\n        var range = search.find(session);\n        assert.equal(range, null);\n    },\n\n    \"test: whole word search should not match inside of words\": function() {\n        var session = new EditSession([\"juhukinners\", \"juhu kinners 123\", \"456\"]);\n\n        var search = new Search().set({\n            needle: \"kinners\",\n            wholeWord: true\n        });\n\n        var range = search.find(session);\n        assert.position(range.start, 1, 5);\n        assert.position(range.end, 1, 12);\n    },\n\n    \"test: find backwards\": function() {\n        var session = new EditSession([\"juhu juhu juhu juhu\"]);\n        session.getSelection().moveCursorTo(0, 10);\n        var search = new Search().set({\n            needle: \"juhu\",\n            backwards: true\n        });\n\n        var range = search.find(session);\n        assert.position(range.start, 0, 5);\n        assert.position(range.end, 0, 9);\n    },\n\n    \"test: find in selection\": function() {\n        var session = new EditSession([\"juhu\", \"juhu\", \"juhu\", \"juhu\"]);\n        session.getSelection().setSelectionAnchor(1, 0);\n        session.getSelection().selectTo(3, 5);\n\n        var search = new Search().set({\n            needle: \"juhu\",\n            wrap: true,\n            scope: Search.SELECTION\n        });\n\n        var range = search.find(session);\n        assert.position(range.start, 1, 0);\n        assert.position(range.end, 1, 4);\n\n        session.getSelection().setSelectionAnchor(0, 2);\n        session.getSelection().selectTo(3, 2);\n\n        var range = search.find(session);\n        assert.position(range.start, 1, 0);\n        assert.position(range.end, 1, 4);\n    },\n\n    \"test: find backwards in selection\": function() {\n        var session = new EditSession([\"juhu\", \"juhu\", \"juhu\", \"juhu\"]);\n\n        var search = new Search().set({\n            needle: \"juhu\",\n            wrap: true,\n            backwards: true,\n            scope: Search.SELECTION\n        });\n\n        session.getSelection().setSelectionAnchor(0, 2);\n        session.getSelection().selectTo(3, 2);\n\n        var range = search.find(session);\n        assert.position(range.start, 2, 0);\n        assert.position(range.end, 2, 4);\n\n        session.getSelection().setSelectionAnchor(0, 2);\n        session.getSelection().selectTo(1, 2);\n\n        assert.equal(search.find(session), null);\n    },\n\n    \"test: edge case - match directly before the cursor\" : function() {\n        var session = new EditSession([\"123\", \"123\", \"juhu\"]);\n\n        var search = new Search().set({\n            needle: \"juhu\",\n            wrap: true\n        });\n\n        session.getSelection().moveCursorTo(2, 5);\n\n        var range = search.find(session);\n        assert.position(range.start, 2, 0);\n        assert.position(range.end, 2, 4);\n    },\n\n    \"test: edge case - match backwards directly after the cursor\" : function() {\n        var session = new EditSession([\"123\", \"123\", \"juhu\"]);\n\n        var search = new Search().set({\n            needle: \"juhu\",\n            wrap: true,\n            backwards: true\n        });\n\n        session.getSelection().moveCursorTo(2, 0);\n\n        var range = search.find(session);\n        assert.position(range.start, 2, 0);\n        assert.position(range.end, 2, 4);\n    },\n\n    \"test: find using a regular expression\" : function() {\n        var session = new EditSession([\"abc123 123 cd\", \"abc\"]);\n\n        var search = new Search().set({\n            needle: \"\\\\d+\",\n            regExp: true\n        });\n\n        var range = search.find(session);\n        assert.position(range.start, 0, 3);\n        assert.position(range.end, 0, 6);\n    },\n\n    \"test: find using a regular expression and whole word\" : function() {\n        var session = new EditSession([\"abc123 123 cd\", \"abc\"]);\n\n        var search = new Search().set({\n            needle: \"\\\\d+\\\\b\",\n            regExp: true,\n            wholeWord: true\n        });\n\n        var range = search.find(session);\n        assert.position(range.start, 0, 7);\n        assert.position(range.end, 0, 10);\n    },\n\n    \"test: use regular expressions with capture groups\": function() {\n        var session = new EditSession([\"  ab: 12px\", \"  <h1 abc\"]);\n\n        var search = new Search().set({\n            needle: \"(\\\\d+)\",\n            regExp: true\n        });\n\n        var range = search.find(session);\n        assert.position(range.start, 0, 6);\n        assert.position(range.end, 0, 8);\n    },\n\n    \"test: find all matches in selection\" : function() {\n        var session = new EditSession([\"juhu\", \"juhu\", \"juhu\", \"juhu\"]);\n\n        var search = new Search().set({\n            needle: \"uh\",\n            wrap: true,\n            scope: Search.SELECTION\n        });\n\n        session.getSelection().setSelectionAnchor(0, 2);\n        session.getSelection().selectTo(3, 2);\n\n        var ranges = search.findAll(session);\n\n        assert.equal(ranges.length, 2);\n        assert.position(ranges[0].start, 1, 1);\n        assert.position(ranges[0].end, 1, 3);\n        assert.position(ranges[1].start, 2, 1);\n        assert.position(ranges[1].end, 2, 3);\n    },\n\n    \"test: replace() should return the replacement if the input matches the needle\" : function() {\n        var search = new Search().set({\n            needle: \"juhu\"\n        });\n\n        assert.equal(search.replace(\"juhu\", \"kinners\"), \"kinners\");\n        assert.equal(search.replace(\"\", \"kinners\"), null);\n        assert.equal(search.replace(\" juhu\", \"kinners\"), null);\n\n        // regexp replacement\n    },\n\n    \"test: replace with a RegExp search\" : function() {\n        var search = new Search().set({\n            needle: \"\\\\d+\",\n            regExp: true\n        });\n\n        assert.equal(search.replace(\"123\", \"kinners\"), \"kinners\");\n        assert.equal(search.replace(\"01234\", \"kinners\"), \"kinners\");\n        assert.equal(search.replace(\"\", \"kinners\"), null);\n        assert.equal(search.replace(\"a12\", \"kinners\"), null);\n        assert.equal(search.replace(\"12a\", \"kinners\"), null);\n    },\n\n    \"test: replace with RegExp match and capture groups\" : function() {\n        var search = new Search().set({\n            needle: \"ab(\\\\d\\\\d)\",\n            regExp: true\n        });\n\n        assert.equal(search.replace(\"ab12\", \"cd$1\"), \"cd12\");\n        assert.equal(search.replace(\"ab12\", \"-$&-\"), \"-ab12-\");\n        assert.equal(search.replace(\"ab12\", \"$$\"), \"$\");\n    },\n\n    \"test: find all using regular expresion containing $\" : function() {\n        var session = new EditSession([\"a\", \"     b\", \"c \", \"d\"]);\n\n        var search = new Search().set({\n            needle: \"[ ]+$\",\n            regExp: true,\n            wrap: true,\n            scope: Search.ALL\n        });\n\n        session.getSelection().moveCursorTo(1, 2);\n        var ranges = search.findAll(session);\n\n        assert.equal(ranges.length, 1);\n        assert.position(ranges[0].start, 2, 1);\n        assert.position(ranges[0].end, 2, 2);\n    },\n\n    \"test: find all matches in a line\" : function() {\n        var session = new EditSession(\"foo bar foo baz foobar foo\");\n\n        var search = new Search().set({\n            needle: \"foo\",\n            wrap: true,\n            wholeWord: true,\n        });\n\n        session.getSelection().moveCursorTo(0, 4);\n\n        var ranges = search.findAll(session);\n\n        assert.equal(ranges.length, 3);\n        assert.position(ranges[0].start, 0, 0);\n        assert.position(ranges[0].end, 0, 3);\n        assert.position(ranges[1].start, 0, 8);\n        assert.position(ranges[1].end, 0, 11);\n        assert.position(ranges[2].start, 0, 23);\n        assert.position(ranges[2].end, 0, 26);\n    },\n\n    \"test: find all matches in a line backwards\" : function() {\n        var session = new EditSession(\"foo bar foo baz foobar foo\");\n\n        var search = new Search().set({\n            needle: \"foo\",\n            wrap: true,\n            wholeWord: true,\n            backwards: true,\n        });\n\n        session.getSelection().moveCursorTo(0, 13);\n\n        var ranges = search.findAll(session);\n\n        assert.equal(ranges.length, 3);\n        assert.position(ranges[0].start, 0, 23);\n        assert.position(ranges[0].end, 0, 26);\n        assert.position(ranges[1].start, 0, 8);\n        assert.position(ranges[1].end, 0, 11);\n        assert.position(ranges[2].start, 0, 0);\n        assert.position(ranges[2].end, 0, 3);\n    },\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/selection.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Julian Viereck <julian.viereck@gmail.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"./lib/oop\");\nvar lang = require(\"./lib/lang\");\nvar EventEmitter = require(\"./lib/event_emitter\").EventEmitter;\nvar Range = require(\"./range\").Range;\n\n/**\n * Keeps cursor position and the text selection of an edit session.\n *\n * The row/columns used in the selection are in document coordinates\n * representing ths coordinates as thez appear in the document\n * before applying soft wrap and folding.\n */\nvar Selection = function(session) {\n    this.session = session;\n    this.doc = session.getDocument();\n\n    this.clearSelection();\n    this.selectionLead = this.doc.createAnchor(0, 0);\n    this.selectionAnchor = this.doc.createAnchor(0, 0);\n\n    var self = this;\n    this.selectionLead.on(\"change\", function(e) {\n        self._emit(\"changeCursor\");\n        if (!self.$isEmpty)\n            self._emit(\"changeSelection\");\n        if (!self.$keepDesiredColumnOnChange && e.old.column != e.value.column)\n            self.$desiredColumn = null;\n    });\n\n    this.selectionAnchor.on(\"change\", function() {\n        if (!self.$isEmpty)\n            self._emit(\"changeSelection\");\n    });\n};\n\n(function() {\n\n    oop.implement(this, EventEmitter);\n\n    this.isEmpty = function() {\n        return (this.$isEmpty || (\n            this.selectionAnchor.row == this.selectionLead.row &&\n            this.selectionAnchor.column == this.selectionLead.column\n        ));\n    };\n\n    this.isMultiLine = function() {\n        if (this.isEmpty()) {\n            return false;\n        }\n\n        return this.getRange().isMultiLine();\n    };\n\n    this.getCursor = function() {\n        return this.selectionLead.getPosition();\n    };\n\n    this.setSelectionAnchor = function(row, column) {\n        this.selectionAnchor.setPosition(row, column);\n\n        if (this.$isEmpty) {\n            this.$isEmpty = false;\n            this._emit(\"changeSelection\");\n        }\n    };\n\n    this.getSelectionAnchor = function() {\n        if (this.$isEmpty)\n            return this.getSelectionLead()\n        else\n            return this.selectionAnchor.getPosition();\n    };\n\n    this.getSelectionLead = function() {\n        return this.selectionLead.getPosition();\n    };\n\n    this.shiftSelection = function(columns) {\n        if (this.$isEmpty) {\n            this.moveCursorTo(this.selectionLead.row, this.selectionLead.column + columns);\n            return;\n        };\n\n        var anchor = this.getSelectionAnchor();\n        var lead = this.getSelectionLead();\n\n        var isBackwards = this.isBackwards();\n\n        if (!isBackwards || anchor.column !== 0)\n            this.setSelectionAnchor(anchor.row, anchor.column + columns);\n\n        if (isBackwards || lead.column !== 0) {\n            this.$moveSelection(function() {\n                this.moveCursorTo(lead.row, lead.column + columns);\n            });\n        }\n    };\n\n    this.isBackwards = function() {\n        var anchor = this.selectionAnchor;\n        var lead = this.selectionLead;\n        return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column));\n    };\n\n    this.getRange = function() {\n        var anchor = this.selectionAnchor;\n        var lead = this.selectionLead;\n\n        if (this.isEmpty())\n            return Range.fromPoints(lead, lead);\n\n        if (this.isBackwards()) {\n            return Range.fromPoints(lead, anchor);\n        }\n        else {\n            return Range.fromPoints(anchor, lead);\n        }\n    };\n\n    this.clearSelection = function() {\n        if (!this.$isEmpty) {\n            this.$isEmpty = true;\n            this._emit(\"changeSelection\");\n        }\n    };\n\n    this.selectAll = function() {\n        var lastRow = this.doc.getLength() - 1;\n        this.setSelectionAnchor(lastRow, this.doc.getLine(lastRow).length);\n        this.moveCursorTo(0, 0);\n    };\n\n    this.setSelectionRange = function(range, reverse) {\n        if (reverse) {\n            this.setSelectionAnchor(range.end.row, range.end.column);\n            this.selectTo(range.start.row, range.start.column);\n        } else {\n            this.setSelectionAnchor(range.start.row, range.start.column);\n            this.selectTo(range.end.row, range.end.column);\n        }\n        this.$desiredColumn = null;\n    };\n\n    this.$moveSelection = function(mover) {\n        var lead = this.selectionLead;\n        if (this.$isEmpty)\n            this.setSelectionAnchor(lead.row, lead.column);\n\n        mover.call(this);\n    };\n\n    this.selectTo = function(row, column) {\n        this.$moveSelection(function() {\n            this.moveCursorTo(row, column);\n        });\n    };\n\n    this.selectToPosition = function(pos) {\n        this.$moveSelection(function() {\n            this.moveCursorToPosition(pos);\n        });\n    };\n\n    this.selectUp = function() {\n        this.$moveSelection(this.moveCursorUp);\n    };\n\n    this.selectDown = function() {\n        this.$moveSelection(this.moveCursorDown);\n    };\n\n    this.selectRight = function() {\n        this.$moveSelection(this.moveCursorRight);\n    };\n\n    this.selectLeft = function() {\n        this.$moveSelection(this.moveCursorLeft);\n    };\n\n    this.selectLineStart = function() {\n        this.$moveSelection(this.moveCursorLineStart);\n    };\n\n    this.selectLineEnd = function() {\n        this.$moveSelection(this.moveCursorLineEnd);\n    };\n\n    this.selectFileEnd = function() {\n        this.$moveSelection(this.moveCursorFileEnd);\n    };\n\n    this.selectFileStart = function() {\n        this.$moveSelection(this.moveCursorFileStart);\n    };\n\n    this.selectWordRight = function() {\n        this.$moveSelection(this.moveCursorWordRight);\n    };\n\n    this.selectWordLeft = function() {\n        this.$moveSelection(this.moveCursorWordLeft);\n    };\n\n    this.selectWord = function() {\n        var cursor = this.getCursor();\n        var range  = this.session.getWordRange(cursor.row, cursor.column);\n        this.setSelectionRange(range);\n    };\n\n    // Selects a word including its right whitespace\n    this.selectAWord = function() {\n        var cursor = this.getCursor();\n        var range = this.session.getAWordRange(cursor.row, cursor.column);\n        this.setSelectionRange(range);\n    };\n\n    this.selectLine = function() {\n        var rowStart = this.selectionLead.row;\n        var rowEnd;\n\n        var foldLine = this.session.getFoldLine(rowStart);\n        if (foldLine) {\n            rowStart = foldLine.start.row;\n            rowEnd = foldLine.end.row;\n        } else {\n            rowEnd = rowStart;\n        }\n        this.setSelectionAnchor(rowStart, 0);\n        this.$moveSelection(function() {\n            this.moveCursorTo(rowEnd + 1, 0);\n        });\n    };\n\n    this.moveCursorUp = function() {\n        this.moveCursorBy(-1, 0);\n    };\n\n    this.moveCursorDown = function() {\n        this.moveCursorBy(1, 0);\n    };\n\n    this.moveCursorLeft = function() {\n        var cursor = this.selectionLead.getPosition(),\n            fold;\n\n        if (fold = this.session.getFoldAt(cursor.row, cursor.column, -1)) {\n            this.moveCursorTo(fold.start.row, fold.start.column);\n        } else if (cursor.column == 0) {\n            // cursor is a line (start\n            if (cursor.row > 0) {\n                this.moveCursorTo(cursor.row - 1, this.doc.getLine(cursor.row - 1).length);\n            }\n        }\n        else {\n            var tabSize = this.session.getTabSize();\n            if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column-tabSize, cursor.column).split(\" \").length-1 == tabSize)\n                this.moveCursorBy(0, -tabSize);\n            else\n                this.moveCursorBy(0, -1);\n        }\n    };\n\n    this.moveCursorRight = function() {\n        var cursor = this.selectionLead.getPosition(),\n            fold;\n        if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) {\n            this.moveCursorTo(fold.end.row, fold.end.column);\n        }\n        else if (this.selectionLead.column == this.doc.getLine(this.selectionLead.row).length) {\n            if (this.selectionLead.row < this.doc.getLength() - 1) {\n                this.moveCursorTo(this.selectionLead.row + 1, 0);\n            }\n        }\n        else {\n            var tabSize = this.session.getTabSize();\n            var cursor = this.selectionLead;\n            if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column, cursor.column+tabSize).split(\" \").length-1 == tabSize)\n                this.moveCursorBy(0, tabSize);\n            else\n                this.moveCursorBy(0, 1);\n        }\n    };\n\n    this.moveCursorLineStart = function() {\n        var row = this.selectionLead.row;\n        var column = this.selectionLead.column;\n        var screenRow = this.session.documentToScreenRow(row, column);\n\n        // Determ the doc-position of the first character at the screen line.\n        var firstColumnPosition = this.session.screenToDocumentPosition(screenRow, 0);\n\n        // Determ the line\n        var beforeCursor = this.session.getDisplayLine(\n            row, null,\n            firstColumnPosition.row, firstColumnPosition.column\n        );\n\n        var leadingSpace = beforeCursor.match(/^\\s*/);\n        if (leadingSpace[0].length == column) {\n            this.moveCursorTo(\n                firstColumnPosition.row, firstColumnPosition.column\n            );\n        }\n        else {\n            this.moveCursorTo(\n                firstColumnPosition.row,\n                firstColumnPosition.column + leadingSpace[0].length\n            );\n        }\n    };\n\n    this.moveCursorLineEnd = function() {\n        var lead = this.selectionLead;\n        var lastRowColumnPosition =\n            this.session.getDocumentLastRowColumnPosition(lead.row, lead.column);\n        this.moveCursorTo(\n            lastRowColumnPosition.row,\n            lastRowColumnPosition.column\n        );\n    };\n\n    this.moveCursorFileEnd = function() {\n        var row = this.doc.getLength() - 1;\n        var column = this.doc.getLine(row).length;\n        this.moveCursorTo(row, column);\n    };\n\n    this.moveCursorFileStart = function() {\n        this.moveCursorTo(0, 0);\n    };\n\n    this.moveCursorWordRight = function() {\n        var row = this.selectionLead.row;\n        var column = this.selectionLead.column;\n        var line = this.doc.getLine(row);\n        var rightOfCursor = line.substring(column);\n\n        var match;\n        this.session.nonTokenRe.lastIndex = 0;\n        this.session.tokenRe.lastIndex = 0;\n\n        // skip folds\n        var fold = this.session.getFoldAt(row, column, 1);\n        if (fold) {\n            this.moveCursorTo(fold.end.row, fold.end.column);\n            return;\n        }\n\n        // first skip space\n        if (match = this.session.nonTokenRe.exec(rightOfCursor)) {\n            column += this.session.nonTokenRe.lastIndex;\n            this.session.nonTokenRe.lastIndex = 0;\n            rightOfCursor = line.substring(column);\n        }\n\n        // if at line end proceed with next line\n        if (column >= line.length) {\n            this.moveCursorTo(row, line.length);\n            this.moveCursorRight();\n            if (row < this.doc.getLength() - 1)\n                this.moveCursorWordRight();\n            return;\n        }\n\n        // advance to the end of the next token\n        if (match = this.session.tokenRe.exec(rightOfCursor)) {\n            column += this.session.tokenRe.lastIndex;\n            this.session.tokenRe.lastIndex = 0;\n        }\n\n        this.moveCursorTo(row, column);\n    };\n\n    this.moveCursorWordLeft = function() {\n        var row = this.selectionLead.row;\n        var column = this.selectionLead.column;\n\n        // skip folds\n        var fold;\n        if (fold = this.session.getFoldAt(row, column, -1)) {\n            this.moveCursorTo(fold.start.row, fold.start.column);\n            return;\n        }\n\n        var str = this.session.getFoldStringAt(row, column, -1);\n        if (str == null) {\n            str = this.doc.getLine(row).substring(0, column)\n        }\n\n        var leftOfCursor = lang.stringReverse(str);\n        var match;\n        this.session.nonTokenRe.lastIndex = 0;\n        this.session.tokenRe.lastIndex = 0;\n\n        // skip whitespace\n        if (match = this.session.nonTokenRe.exec(leftOfCursor)) {\n            column -= this.session.nonTokenRe.lastIndex;\n            leftOfCursor = leftOfCursor.slice(this.session.nonTokenRe.lastIndex);\n            this.session.nonTokenRe.lastIndex = 0;\n        }\n\n        // if at begin of the line proceed in line above\n        if (column <= 0) {\n            this.moveCursorTo(row, 0);\n            this.moveCursorLeft();\n            if (row > 0)\n                this.moveCursorWordLeft();\n            return;\n        }\n\n        // move to the begin of the word\n        if (match = this.session.tokenRe.exec(leftOfCursor)) {\n            column -= this.session.tokenRe.lastIndex;\n            this.session.tokenRe.lastIndex = 0;\n        }\n\n        this.moveCursorTo(row, column);\n    };\n\n    this.moveCursorBy = function(rows, chars) {\n        var screenPos = this.session.documentToScreenPosition(\n            this.selectionLead.row,\n            this.selectionLead.column\n        );\n\n        if (chars === 0) {\n            if (this.$desiredColumn)\n                screenPos.column = this.$desiredColumn;\n            else\n                this.$desiredColumn = screenPos.column;\n        }\n\n        var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenPos.column);\n\n        // move the cursor and update the desired column\n        this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0);\n    };\n\n    this.moveCursorToPosition = function(position) {\n        this.moveCursorTo(position.row, position.column);\n    };\n\n    this.moveCursorTo = function(row, column, keepDesiredColumn) {\n        // Ensure the row/column is not inside of a fold.\n        var fold = this.session.getFoldAt(row, column, 1);\n        if (fold) {\n            row = fold.start.row;\n            column = fold.start.column;\n        }\n\n        this.$keepDesiredColumnOnChange = true;\n        this.selectionLead.setPosition(row, column);\n        this.$keepDesiredColumnOnChange = false;\n\n        if (!keepDesiredColumn)\n            this.$desiredColumn = null;\n    };\n\n    this.moveCursorToScreen = function(row, column, keepDesiredColumn) {\n        var pos = this.session.screenToDocumentPosition(row, column);\n        this.moveCursorTo(pos.row, pos.column, keepDesiredColumn);\n    };\n\n    // remove listeners from document\n    this.detach = function() {\n        this.selectionLead.detach();\n        this.selectionAnchor.detach();\n        this.session = this.doc = null;\n    }\n\n    this.fromOrientedRange = function(range) {\n        this.setSelectionRange(range, range.cursor == range.start);\n        this.$desiredColumn = range.desiredColumn || this.$desiredColumn;\n    }\n\n    this.toOrientedRange = function(range) {\n        var r = this.getRange();\n        if (range) {\n            range.start.column = r.start.column;\n            range.start.row = r.start.row;\n            range.end.column = r.end.column;\n            range.end.row = r.end.row;\n        } else {\n            range = r;\n        }\n\n        range.cursor = this.isBackwards() ? range.start : range.end;\n        range.desiredColumn = this.$desiredColumn;\n        return range;\n    }\n\n}).call(Selection.prototype);\n\nexports.Selection = Selection;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/selection_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"./edit_session\").EditSession;\nvar assert = require(\"./test/assertions\");\n\nmodule.exports = {\n    createSession : function(rows, cols) {\n        var line = new Array(cols + 1).join(\"a\");\n        var text = new Array(rows).join(line + \"\\n\") + line;\n        return new EditSession(text);\n    },\n\n    \"test: move cursor to end of file should place the cursor on last row and column\" : function() {\n        var session = this.createSession(200, 10);\n        var selection = session.getSelection();\n\n        selection.moveCursorFileEnd();\n        assert.position(selection.getCursor(), 199, 10);\n    },\n\n    \"test: moveCursor to start of file should place the cursor on the first row and column\" : function() {\n        var session = this.createSession(200, 10);\n        var selection = session.getSelection();\n\n        selection.moveCursorFileStart();\n        assert.position(selection.getCursor(), 0, 0);\n    },\n\n    \"test: move selection lead to end of file\" : function() {\n        var session = this.createSession(200, 10);\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(100, 5);\n        selection.selectFileEnd();\n\n        var range = selection.getRange();\n\n        assert.position(range.start, 100, 5);\n        assert.position(range.end, 199, 10);\n    },\n\n    \"test: move selection lead to start of file\" : function() {\n        var session = this.createSession(200, 10);\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(100, 5);\n        selection.selectFileStart();\n\n        var range = selection.getRange();\n\n        assert.position(range.start, 0, 0);\n        assert.position(range.end, 100, 5);\n    },\n\n    \"test: move cursor word right\" : function() {\n        var session = new EditSession([\n            \"ab\",\n            \" Juhu Kinners (abc, 12)\",\n            \" cde\"\n        ].join(\"\\n\"));\n        \n        var selection = session.getSelection();\n\n        selection.moveCursorDown();\n        assert.position(selection.getCursor(), 1, 0);\n\n        selection.moveCursorWordRight();\n        assert.position(selection.getCursor(), 1, 5);\n\n        selection.moveCursorWordRight();\n        assert.position(selection.getCursor(), 1, 13);\n\n        selection.moveCursorWordRight();\n        assert.position(selection.getCursor(), 1, 18);\n\n        selection.moveCursorWordRight();\n        assert.position(selection.getCursor(), 1, 22);\n\n        // wrap line\n        selection.moveCursorWordRight();\n        assert.position(selection.getCursor(), 2, 4);\n        \n        selection.moveCursorWordRight();\n        assert.position(selection.getCursor(), 2, 4);\n    },\n\n    \"test: select word right if cursor in word\" : function() {\n        var session = new EditSession(\"Juhu Kinners\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 2);\n        selection.moveCursorWordRight();\n\n        assert.position(selection.getCursor(), 0, 4);\n    },\n\n    \"test: moveCursor word left\" : function() {\n        var session = new EditSession([\n            \"ab\",\n            \" Juhu Kinners (abc, 12)\",\n            \" cde\"\n        ].join(\"\\n\"));\n\n        var selection = session.getSelection();\n\n        selection.moveCursorDown();\n        selection.moveCursorLineEnd();\n        assert.position(selection.getCursor(), 1, 23);\n\n        selection.moveCursorWordLeft();\n        assert.position(selection.getCursor(), 1, 20);\n\n        selection.moveCursorWordLeft();\n        assert.position(selection.getCursor(), 1, 15);\n\n        selection.moveCursorWordLeft();\n        assert.position(selection.getCursor(), 1, 6);\n\n        selection.moveCursorWordLeft();\n        assert.position(selection.getCursor(), 1, 1);\n\n        // wrap line\n        selection.moveCursorWordLeft();\n        assert.position(selection.getCursor(), 0, 0);\n\n        selection.moveCursorWordLeft();\n        assert.position(selection.getCursor(), 0, 0);\n    },\n\n    \"test: moveCursor word left with umlauts\" : function() {\n        var session = new EditSession(\" Fuß Füße\");\n\n        var selection = session.getSelection();\n        selection.moveCursorTo(0, 9)\n        selection.moveCursorWordLeft();\n        assert.position(selection.getCursor(), 0, 5);\n\n        selection.moveCursorWordLeft();\n        assert.position(selection.getCursor(), 0, 1);\n    },\n\n    \"test: select word left if cursor in word\" : function() {\n        var session = new EditSession(\"Juhu Kinners\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 8);\n\n        selection.moveCursorWordLeft();\n        assert.position(selection.getCursor(), 0, 5);\n    },\n\n    \"test: select word right and select\" : function() {\n        var session = new EditSession(\"Juhu Kinners\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 0);\n        selection.selectWordRight();\n\n        var range = selection.getRange();\n\n        assert.position(range.start, 0, 0);\n        assert.position(range.end, 0, 4);\n    },\n\n    \"test: select word left and select\" : function() {\n        var session = new EditSession(\"Juhu Kinners\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 3);\n        selection.selectWordLeft();\n\n        var range = selection.getRange();\n\n        assert.position(range.start, 0, 0);\n        assert.position(range.end, 0, 3);\n    },\n\n    \"test: select word with cursor in word should select the word\" : function() {\n        var session = new EditSession(\"Juhu Kinners 123\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 8);\n        selection.selectWord();\n\n        var range = selection.getRange();\n        assert.position(range.start, 0, 5);\n        assert.position(range.end, 0, 12);\n    },\n\n    \"test: select word with cursor in word including right whitespace should select the word\" : function() {\n        var session = new EditSession(\"Juhu Kinners      123\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 8);\n        selection.selectAWord();\n\n        var range = selection.getRange();\n        assert.position(range.start, 0, 5);\n        assert.position(range.end, 0, 18);\n    },\n\n    \"test: select word with cursor betwen white space and word should select the word\" : function() {\n        var session = new EditSession(\"Juhu Kinners\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 4);\n        selection.selectWord();\n\n        var range = selection.getRange();\n        assert.position(range.start, 0, 0);\n        assert.position(range.end, 0, 4);\n\n        selection.moveCursorTo(0, 5);\n        selection.selectWord();\n\n        var range = selection.getRange();\n        assert.position(range.start, 0, 5);\n        assert.position(range.end, 0, 12);\n    },\n\n    \"test: select word with cursor in white space should select white space\" : function() {\n        var session = new EditSession(\"Juhu  Kinners\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 5);\n        selection.selectWord();\n\n        var range = selection.getRange();\n        assert.position(range.start, 0, 4);\n        assert.position(range.end, 0, 6);\n    },\n\n    \"test: moving cursor should fire a 'changeCursor' event\" : function() {\n        var session = new EditSession(\"Juhu  Kinners\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 5);\n\n        var called = false;\n        selection.addEventListener(\"changeCursor\", function() {\n           called = true;\n        });\n\n        selection.moveCursorTo(0, 6);\n        assert.ok(called);\n    },\n\n    \"test: calling setCursor with the same position should not fire an event\": function() {\n        var session = new EditSession(\"Juhu  Kinners\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 5);\n\n        var called = false;\n        selection.addEventListener(\"changeCursor\", function() {\n           called = true;\n        });\n\n        selection.moveCursorTo(0, 5);\n        assert.notOk(called);\n    },\n\n    \"test: moveWordright should move past || and [\": function() {\n        var session = new EditSession(\"||foo[\");\n        var selection = session.getSelection();\n\n        // Move behind ||foo\n        selection.moveCursorWordRight();\n        assert.position(selection.getCursor(), 0, 5);\n\n        // Move behind [\n        selection.moveCursorWordRight();\n        assert.position(selection.getCursor(), 0, 6);\n    },\n\n    \"test: moveWordLeft should move past || and [\": function() {\n        var session = new EditSession(\"||foo[\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 6);\n\n        // Move behind [foo\n        selection.moveCursorWordLeft();\n        assert.position(selection.getCursor(), 0, 2);\n\n        // Move behind ||\n        selection.moveCursorWordLeft();\n        assert.position(selection.getCursor(), 0, 0);\n    },\n\n    \"test: move cursor to line start should move cursor to end of the indentation first\": function() {\n        var session = new EditSession(\"12\\n    Juhu\\n12\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(1, 6);\n        selection.moveCursorLineStart();\n\n        assert.position(selection.getCursor(), 1, 4);\n    },\n\n    \"test: move cursor to line start when the cursor is at the end of the indentation should move cursor to column 0\": function() {\n        var session = new EditSession(\"12\\n    Juhu\\n12\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(1, 4);\n        selection.moveCursorLineStart();\n\n        assert.position(selection.getCursor(), 1, 0);\n    },\n\n    \"test: move cursor to line start when the cursor is at column 0 should move cursor to the end of the indentation\": function() {\n        var session = new EditSession(\"12\\n    Juhu\\n12\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(1, 0);\n        selection.moveCursorLineStart();\n\n        assert.position(selection.getCursor(), 1, 4);\n    },\n\n    // Eclipse style\n    \"test: move cursor to line start when the cursor is before the initial indentation should move cursor to the end of the indentation\": function() {\n        var session = new EditSession(\"12\\n    Juhu\\n12\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(1, 2);\n        selection.moveCursorLineStart();\n\n        assert.position(selection.getCursor(), 1, 4);\n    },\n\n    \"test go line up when in the middle of the first line should go to document start\": function() {\n        var session = new EditSession(\"juhu kinners\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 4);\n        selection.moveCursorUp();\n\n        assert.position(selection.getCursor(), 0, 0);\n    },\n\n    \"test: (wrap) go line up when in the middle of the first line should go to document start\": function() {\n        var session = new EditSession(\"juhu kinners\");\n        session.setWrapLimitRange(5, 5);\n        session.adjustWrapLimit(80);\n\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 4);\n        selection.moveCursorUp();\n\n        assert.position(selection.getCursor(), 0, 0);\n    },\n\n\n    \"test go line down when in the middle of the last line should go to document end\": function() {\n        var session = new EditSession(\"juhu kinners\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 4);\n        selection.moveCursorDown();\n\n        assert.position(selection.getCursor(), 0, 12);\n    },\n\n    \"test (wrap) go line down when in the middle of the last line should go to document end\": function() {\n        var session = new EditSession(\"juhu kinners\");\n        session.setWrapLimitRange(8, 8);\n        session.adjustWrapLimit(80);\n\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 10);\n        selection.moveCursorDown();\n\n        assert.position(selection.getCursor(), 0, 12);\n    },\n\n    \"test go line up twice and then once down when in the second should go back to the previous column\": function() {\n        var session = new EditSession(\"juhu\\nkinners\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(1, 4);\n        selection.moveCursorUp();\n        selection.moveCursorUp();\n        selection.moveCursorDown();\n\n        assert.position(selection.getCursor(), 1, 4);\n    },\n\n    \"test (keyboard navigation) when curLine is not EOL and targetLine is all whitespace new column should be current column\": function() {\n        var session = new EditSession(\"function (a) {\\n\\\n    \\n\\\n}\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(2, 0);\n        selection.moveCursorUp();\n\n        assert.position(selection.getCursor(), 1, 0);\n    },\n\n    \"test (keyboard navigation) when curLine is EOL and targetLine is shorter dan current column, new column should be targetLine's EOL\": function() {\n        var session = new EditSession(\"function (a) {\\n\\\n    \\n\\\n}\");\n        var selection = session.getSelection();\n\n        selection.moveCursorTo(0, 14);\n        selection.moveCursorDown();\n\n        assert.position(selection.getCursor(), 1, 4);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/split.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n *  Julian Viereck <julian.viereck@gmail.com>\n *\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"./lib/oop\");\nvar lang = require(\"./lib/lang\");\nvar EventEmitter = require(\"./lib/event_emitter\").EventEmitter;\n\nvar Editor = require(\"./editor\").Editor;\nvar Renderer = require(\"./virtual_renderer\").VirtualRenderer;\nvar EditSession = require(\"./edit_session\").EditSession;\n\nvar Split = function(container, theme, splits) {\n    this.BELOW = 1;\n    this.BESIDE = 0;\n\n    this.$container = container;\n    this.$theme = theme;\n    this.$splits = 0;\n    this.$editorCSS = \"\";\n    this.$editors = [];\n    this.$orientation = this.BESIDE;\n\n    this.setSplits(splits || 1);\n    this.$cEditor = this.$editors[0];\n\n\n    this.on(\"focus\", function(editor) {\n        this.$cEditor = editor;\n    }.bind(this));\n};\n\n(function(){\n\n    oop.implement(this, EventEmitter);\n\n    this.$createEditor = function() {\n        var el = document.createElement(\"div\");\n        el.className = this.$editorCSS;\n        el.style.cssText = \"position: absolute; top:0px; bottom:0px\";\n        this.$container.appendChild(el);\n        var editor = new Editor(new Renderer(el, this.$theme));\n\n        editor.on(\"focus\", function() {\n            this._emit(\"focus\", editor);\n        }.bind(this));\n\n        this.$editors.push(editor);\n        editor.setFontSize(this.$fontSize);\n        return editor;\n    };\n\n    this.setSplits = function(splits) {\n        var editor;\n        if (splits < 1) {\n            throw \"The number of splits have to be > 0!\";\n        }\n\n        if (splits == this.$splits) {\n            return;\n        } else if (splits > this.$splits) {\n            while (this.$splits < this.$editors.length && this.$splits < splits) {\n                editor = this.$editors[this.$splits];\n                this.$container.appendChild(editor.container);\n                editor.setFontSize(this.$fontSize);\n                this.$splits ++;\n            }\n            while (this.$splits < splits) {\n                this.$createEditor();\n                this.$splits ++;\n            }\n        } else {\n            while (this.$splits > splits) {\n                editor = this.$editors[this.$splits - 1];\n                this.$container.removeChild(editor.container);\n                this.$splits --;\n            }\n        }\n        this.resize();\n    };\n\n    this.getSplits = function() {\n        return this.$splits;\n    };\n\n    this.getEditor = function(idx) {\n        return this.$editors[idx];\n    };\n\n    this.getCurrentEditor = function() {\n        return this.$cEditor;\n    };\n\n    this.focus = function() {\n        this.$cEditor.focus();\n    };\n\n    this.blur = function() {\n        this.$cEditor.blur();\n    };\n\n    this.setTheme = function(theme) {\n        this.$editors.forEach(function(editor) {\n            editor.setTheme(theme);\n        });\n    };\n\n    this.setKeyboardHandler = function(keybinding) {\n        this.$editors.forEach(function(editor) {\n            editor.setKeyboardHandler(keybinding);\n        });\n    };\n\n    this.forEach = function(callback, scope) {\n        this.$editors.forEach(callback, scope);\n    };\n\n    this.$fontSize = \"\";\n    this.setFontSize = function(size) {\n        this.$fontSize = size;\n        this.forEach(function(editor) {\n           editor.setFontSize(size);\n        });\n    };\n\n    this.$cloneSession = function(session) {\n        var s = new EditSession(session.getDocument(), session.getMode());\n\n        var undoManager = session.getUndoManager();\n        if (undoManager) {\n            var undoManagerProxy = new UndoManagerProxy(undoManager, s);\n            s.setUndoManager(undoManagerProxy);\n        }\n\n        // Overwrite the default $informUndoManager function such that new delas\n        // aren't added to the undo manager from the new and the old session.\n        s.$informUndoManager = lang.deferredCall(function() { s.$deltas = []; });\n\n        // Copy over 'settings' from the session.\n        s.setTabSize(session.getTabSize());\n        s.setUseSoftTabs(session.getUseSoftTabs());\n        s.setOverwrite(session.getOverwrite());\n        s.setBreakpoints(session.getBreakpoints());\n        s.setUseWrapMode(session.getUseWrapMode());\n        s.setUseWorker(session.getUseWorker());\n        s.setWrapLimitRange(session.$wrapLimitRange.min,\n                            session.$wrapLimitRange.max);\n        s.$foldData = session.$cloneFoldData();\n\n        return s;\n    };\n\n    this.setSession = function(session, idx) {\n        var editor;\n        if (idx == null) {\n            editor = this.$cEditor;\n        } else {\n            editor = this.$editors[idx];\n        }\n\n        // Check if the session is used already by any of the editors in the\n        // split. If it is, we have to clone the session as two editors using\n        // the same session can cause terrible side effects (e.g. UndoQueue goes\n        // wrong). This also gives the user of Split the possibility to treat\n        // each session on each split editor different.\n        var isUsed = this.$editors.some(function(editor) {\n           return editor.session === session;\n        });\n\n        if (isUsed) {\n            session = this.$cloneSession(session);\n        }\n        editor.setSession(session);\n\n        // Return the session set on the editor. This might be a cloned one.\n        return session;\n    };\n\n    this.getOrientation = function() {\n        return this.$orientation;\n    };\n\n    this.setOrientation = function(orientation) {\n        if (this.$orientation == orientation) {\n            return;\n        }\n        this.$orientation = orientation;\n        this.resize();\n    };\n\n    this.resize = function() {\n        var width = this.$container.clientWidth;\n        var height = this.$container.clientHeight;\n        var editor;\n\n        if (this.$orientation == this.BESIDE) {\n            var editorWidth = width / this.$splits;\n            for (var i = 0; i < this.$splits; i++) {\n                editor = this.$editors[i];\n                editor.container.style.width = editorWidth + \"px\";\n                editor.container.style.top = \"0px\";\n                editor.container.style.left = i * editorWidth + \"px\";\n                editor.container.style.height = height + \"px\";\n                editor.resize();\n            }\n        } else {\n            var editorHeight = height / this.$splits;\n            for (var i = 0; i < this.$splits; i++) {\n                editor = this.$editors[i];\n                editor.container.style.width = width + \"px\";\n                editor.container.style.top = i * editorHeight + \"px\";\n                editor.container.style.left = \"0px\";\n                editor.container.style.height = editorHeight + \"px\";\n                editor.resize();\n            }\n        }\n    };\n\n}).call(Split.prototype);\n\nfunction UndoManagerProxy(undoManager, session) {\n    this.$u = undoManager;\n    this.$doc = session;\n}\n\n(function() {\n    this.execute = function(options) {\n        this.$u.execute(options);\n    };\n\n    this.undo = function() {\n        var selectionRange = this.$u.undo(true);\n        if (selectionRange) {\n            this.$doc.selection.setSelectionRange(selectionRange);\n        }\n    };\n\n    this.redo = function() {\n        var selectionRange = this.$u.redo(true);\n        if (selectionRange) {\n            this.$doc.selection.setSelectionRange(selectionRange);\n        }\n    };\n\n    this.reset = function() {\n        this.$u.reset();\n    };\n\n    this.hasUndo = function() {\n        return this.$u.hasUndo();\n    };\n\n    this.hasRedo = function() {\n        return this.$u.hasRedo();\n    };\n}).call(UndoManagerProxy.prototype);\n\nexports.Split = Split;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/test/all.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\n\"use strict\";\n\nrequire(\"amd-loader\");\nvar test = require(\"asyncjs\").test;\ntest.walkTestCases(__dirname + \"/..\").exec();\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/test/all_browser.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nrequire(\"ace/lib/fixoldbrowsers\");\nvar AsyncTest = require(\"asyncjs\").test;\nvar async = require(\"asyncjs\");\n\nvar passed = 0\nvar failed = 0\nvar log = document.getElementById(\"log\")\n\nvar testNames = [\n    \"ace/anchor_test\",\n    \"ace/commands/command_manager_test\",\n    \"ace/document_test\",\n    \"ace/edit_session_test\",\n    \"ace/editor_change_document_test\",\n    \"ace/editor_highlight_selected_word_test\",\n    \"ace/editor_navigation_test\",\n    \"ace/editor_text_edit_test\",\n    \"ace/ext/static_highlight_test\",\n    \"ace/layer/text_test\",\n    \"ace/lib/event_emitter_test\",\n    \"ace/mode/coffee/parser_test\",\n    \"ace/mode/coffee_highlight_rules_test\",\n    \"ace/mode/coldfusion_test\",\n    \"ace/mode/css_test\",\n    \"ace/mode/css_highlight_rules_test\",\n    \"ace/mode/css_worker\",\n    \"ace/mode/html_test\",\n    \"ace/mode/html_highlight_rules_test\",\n    \"ace/mode/javascript_test\",\n    \"ace/mode/javascript_highlight_rules_test\",\n    \"ace/mode/javascript_worker_test\",\n    \"ace/mode/python_test\",\n    \"ace/mode/ruby_highlight_rules_test\",\n    \"ace/mode/text_test\",\n    \"ace/mode/xml_test\",\n    \"ace/mode/xml_highlight_rules_test\",\n    \"ace/mode/folding/cstyle_test\",\n    \"ace/mode/folding/html_test\",\n    \"ace/mode/folding/pythonic_test\",\n    \"ace/mode/folding/xml_test\",\n    \"ace/multi_select_test\",\n    \"ace/range_test\",\n    \"ace/range_list_test\",\n    \"ace/search_test\",\n    \"ace/selection_test\",\n    \"ace/token_iterator_test\",\n    \"ace/virtual_renderer_test\"\n];\n\nvar html = [\"<a href='?'>all tests</a><br>\"];\nfor (var i in testNames) {\n    var href = testNames[i];\n    html.push(\"<a href='?\", href, \"'>\", href.replace(/^ace\\//, \"\") ,\"</a><br>\");\n}\n\nvar nav = document.createElement(\"div\");\nnav.innerHTML = html.join(\"\");\nnav.style.cssText = \"position:absolute;right:0;top:0\"; \ndocument.body.appendChild(nav);\n\nif (location.search)\n    testNames = location.search.substr(1).split(\",\")\n\nrequire(testNames, function() {\n    var tests = testNames.map(require);\n    \n    async.list(tests)\n        .expand(function(test) {\n            return AsyncTest.testcase(test)\n        }, AsyncTest.TestGenerator)\n        .run()\n        .each(function(test, next) {\n            var node = document.createElement(\"div\");\n            node.className = test.passed ? \"passed\" : \"failed\";\n\n            var name = test.name\n            if (test.suiteName)\n                name = test.suiteName + \": \" + test.name\n\n            var msg = \"[\" + test.count + \"/\" + test.index + \"] \" + name + \" \" + (test.passed ? \"OK\" : \"FAIL\")\n            if (!test.passed) {\n                if (test.err.stack)\n                    var err = test.err.stack\n                else\n                    var err = test.err\n\n                console.error(msg);\n                console.error(err);\n                msg += \"<pre class='error'>\" + err + \"</pre>\";\n            } else {\n                console.log(msg);\n            }\n\n            node.innerHTML = msg;\n            log.appendChild(node);\n\n            next()\n        })\n        .each(function(test) {\n            if (test.passed)\n                passed += 1\n            else\n                failed += 1\n        })\n        .end(function() {\n            log.innerHTML += [\n                \"<div class='summary'>\",\n                \"<br>\",\n                \"Summary: <br>\",\n                \"<br>\",\n                \"Total number of tests: \" + (passed + failed) + \"<br>\",\n                (passed ? \"Passed tests: \" + passed + \"<br>\" : \"\"),\n                (failed ? \"Failed tests: \" + failed + \"<br>\" : \"\")\n            ].join(\"\")\n            console.log(\"Total number of tests: \" + (passed + failed));\n            console.log(\"Passed tests: \" + passed);\n            console.log(\"Failed tests: \" + failed);\n        })\n});\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/test/assertions.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar assert = require(\"assert\");\n    \nassert.position = function(cursor, row, column) {\n    assert.equal(cursor.row, row);\n    assert.equal(cursor.column, column);\n};\n\nassert.range = function(range, startRow, startColumn, endRow, endColumn) {\n    assert.position(range.start, startRow, startColumn);\n    assert.position(range.end, endRow, endColumn);\n};\n\nassert.notOk = function(value) {\n    assert.equal(value, false);   \n};\n\nexports.jsonEquals = function(foundJson, expectedJson) {\n    assert.equal(JSON.stringify(foundJson), JSON.stringify(expectedJson));\n};\n\nmodule.exports = assert;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/test/asyncjs/assert.js",
    "content": "define(function(require, exports, module) {\n    \n// http://wiki.commonjs.org/wiki/Unit_Testing/1.0\n//\n// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!\n//\n// Originally from narwhal.js (http://narwhaljs.org)\n// Copyright (c) 2009 Thomas Robinson <280north.com>\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the 'Software'), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n// UTILITY\nvar oop = require(\"ace/lib/oop\");\nvar pSlice = Array.prototype.slice;\n\n// 1. The assert module provides functions that throw\n// AssertionError's when particular conditions are not met. The\n// assert module must conform to the following interface.\n\nvar assert = exports;\n\n// 2. The AssertionError is defined in assert.\n// new assert.AssertionError({ message: message,\n//                             actual: actual,\n//                             expected: expected })\n\nassert.AssertionError = function AssertionError(options) {\n  this.name = 'AssertionError';\n  this.message = options.message;\n  this.actual = options.actual;\n  this.expected = options.expected;\n  this.operator = options.operator;\n  var stackStartFunction = options.stackStartFunction || fail;\n\n  if (Error.captureStackTrace) {\n    Error.captureStackTrace(this, stackStartFunction);\n  }\n};\noop.inherits(assert.AssertionError, Error);\n\ntoJSON = function(obj) {\n    if (typeof JSON !== \"undefined\")\n        return JSON.stringify(obj);\n    else\n        return obj.toString();\n}\n\nassert.AssertionError.prototype.toString = function() {\n  if (this.message) {\n    return [this.name + ':', this.message].join(' ');\n  } else {\n    return [this.name + ':',\n            toJSON(this.expected),\n            this.operator,\n            toJSON(this.actual)].join(' ');\n  }\n};\n\n// assert.AssertionError instanceof Error\n\nassert.AssertionError.__proto__ = Error.prototype;\n\n// At present only the three keys mentioned above are used and\n// understood by the spec. Implementations or sub modules can pass\n// other keys to the AssertionError's constructor - they will be\n// ignored.\n\n// 3. All of the following functions must throw an AssertionError\n// when a corresponding condition is not met, with a message that\n// may be undefined if not provided.  All assertion methods provide\n// both the actual and expected values to the assertion error for\n// display purposes.\n\nfunction fail(actual, expected, message, operator, stackStartFunction) {\n  throw new assert.AssertionError({\n    message: message,\n    actual: actual,\n    expected: expected,\n    operator: operator,\n    stackStartFunction: stackStartFunction\n  });\n}\n\n// EXTENSION! allows for well behaved errors defined elsewhere.\nassert.fail = fail;\n\n// 4. Pure assertion tests whether a value is truthy, as determined\n// by !!guard.\n// assert.ok(guard, message_opt);\n// This statement is equivalent to assert.equal(true, guard,\n// message_opt);. To test strictly for the value true, use\n// assert.strictEqual(true, guard, message_opt);.\n\nassert.ok = function ok(value, message) {\n  if (!!!value) fail(value, true, message, '==', assert.ok);\n};\n\n// 5. The equality assertion tests shallow, coercive equality with\n// ==.\n// assert.equal(actual, expected, message_opt);\n\nassert.equal = function equal(actual, expected, message) {\n  if (actual != expected) fail(actual, expected, message, '==', assert.equal);\n};\n\n// 6. The non-equality assertion tests for whether two objects are not equal\n// with != assert.notEqual(actual, expected, message_opt);\n\nassert.notEqual = function notEqual(actual, expected, message) {\n  if (actual == expected) {\n    fail(actual, expected, message, '!=', assert.notEqual);\n  }\n};\n\n// 7. The equivalence assertion tests a deep equality relation.\n// assert.deepEqual(actual, expected, message_opt);\n\nassert.deepEqual = function deepEqual(actual, expected, message) {\n  if (!_deepEqual(actual, expected)) {\n    fail(actual, expected, message, 'deepEqual', assert.deepEqual);\n  }\n};\n\nfunction _deepEqual(actual, expected) {\n  // 7.1. All identical values are equivalent, as determined by ===.\n  if (actual === expected) {\n    return true;\n\n  } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {\n    if (actual.length != expected.length) return false;\n\n    for (var i = 0; i < actual.length; i++) {\n      if (actual[i] !== expected[i]) return false;\n    }\n\n    return true;\n\n  // 7.2. If the expected value is a Date object, the actual value is\n  // equivalent if it is also a Date object that refers to the same time.\n  } else if (actual instanceof Date && expected instanceof Date) {\n    return actual.getTime() === expected.getTime();\n\n  // 7.3. Other pairs that do not both pass typeof value == 'object',\n  // equivalence is determined by ==.\n  } else if (typeof actual != 'object' && typeof expected != 'object') {\n    return actual == expected;\n\n  // 7.4. For all other Object pairs, including Array objects, equivalence is\n  // determined by having the same number of owned properties (as verified\n  // with Object.prototype.hasOwnProperty.call), the same set of keys\n  // (although not necessarily the same order), equivalent values for every\n  // corresponding key, and an identical 'prototype' property. Note: this\n  // accounts for both named and indexed properties on Arrays.\n  } else {\n    return objEquiv(actual, expected);\n  }\n}\n\nfunction isUndefinedOrNull(value) {\n  return value === null || value === undefined;\n}\n\nfunction isArguments(object) {\n  return Object.prototype.toString.call(object) == '[object Arguments]';\n}\n\nfunction objEquiv(a, b) {\n  if (isUndefinedOrNull(a) || isUndefinedOrNull(b))\n    return false;\n  // an identical 'prototype' property.\n  if (a.prototype !== b.prototype) return false;\n  //~~~I've managed to break Object.keys through screwy arguments passing.\n  //   Converting to array solves the problem.\n  if (isArguments(a)) {\n    if (!isArguments(b)) {\n      return false;\n    }\n    a = pSlice.call(a);\n    b = pSlice.call(b);\n    return _deepEqual(a, b);\n  }\n  try {\n    var ka = Object.keys(a),\n        kb = Object.keys(b),\n        key, i;\n  } catch (e) {//happens when one is a string literal and the other isn't\n    return false;\n  }\n  // having the same number of owned properties (keys incorporates\n  // hasOwnProperty)\n  if (ka.length != kb.length)\n    return false;\n  //the same set of keys (although not necessarily the same order),\n  ka.sort();\n  kb.sort();\n  //~~~cheap key test\n  for (i = ka.length - 1; i >= 0; i--) {\n    if (ka[i] != kb[i])\n      return false;\n  }\n  //equivalent values for every corresponding key, and\n  //~~~possibly expensive deep test\n  for (i = ka.length - 1; i >= 0; i--) {\n    key = ka[i];\n    if (!_deepEqual(a[key], b[key])) return false;\n  }\n  return true;\n}\n\n// 8. The non-equivalence assertion tests for any deep inequality.\n// assert.notDeepEqual(actual, expected, message_opt);\n\nassert.notDeepEqual = function notDeepEqual(actual, expected, message) {\n  if (_deepEqual(actual, expected)) {\n    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);\n  }\n};\n\n// 9. The strict equality assertion tests strict equality, as determined by ===.\n// assert.strictEqual(actual, expected, message_opt);\n\nassert.strictEqual = function strictEqual(actual, expected, message) {\n  if (actual !== expected) {\n    fail(actual, expected, message, '===', assert.strictEqual);\n  }\n};\n\n// 10. The strict non-equality assertion tests for strict inequality, as\n// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);\n\nassert.notStrictEqual = function notStrictEqual(actual, expected, message) {\n  if (actual === expected) {\n    fail(actual, expected, message, '!==', assert.notStrictEqual);\n  }\n};\n\nfunction expectedException(actual, expected) {\n  if (!actual || !expected) {\n    return false;\n  }\n\n  if (expected instanceof RegExp) {\n    return expected.test(actual);\n  } else if (actual instanceof expected) {\n    return true;\n  } else if (expected.call({}, actual) === true) {\n    return true;\n  }\n\n  return false;\n}\n\nfunction _throws(shouldThrow, block, expected, message) {\n  var actual;\n\n  if (typeof expected === 'string') {\n    message = expected;\n    expected = null;\n  }\n\n  try {\n    block();\n  } catch (e) {\n    actual = e;\n  }\n\n  message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +\n            (message ? ' ' + message : '.');\n\n  if (shouldThrow && !actual) {\n    fail('Missing expected exception' + message);\n  }\n\n  if (!shouldThrow && expectedException(actual, expected)) {\n    fail('Got unwanted exception' + message);\n  }\n\n  if ((shouldThrow && actual && expected &&\n      !expectedException(actual, expected)) || (!shouldThrow && actual)) {\n    throw actual;\n  }\n}\n\n// 11. Expected to throw an error:\n// assert.throws(block, Error_opt, message_opt);\n\nassert.throws = function(block, /*optional*/error, /*optional*/message) {\n  _throws.apply(this, [true].concat(pSlice.call(arguments)));\n};\n\n// EXTENSION! This is annoying to write outside this module.\nassert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {\n  _throws.apply(this, [false].concat(pSlice.call(arguments)));\n};\n\nassert.ifError = function(err) { if (err) {throw err;}};\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/test/asyncjs/async.js",
    "content": "/*!\n * async.js\n * Copyright(c) 2010 Fabian Jakobs <fabian.jakobs@web.de>\n * MIT Licensed\n */\n\ndefine(function(require, exports, module) {\n\nvar STOP = exports.STOP = {}\n\nexports.Generator = function(source) {\n    if (typeof source == \"function\")\n        this.source = {\n            next: source\n        }\n    else\n        this.source = source\n}\n\n;(function() {\n    this.next = function(callback) {\n        this.source.next(callback)\n    }\n\n    this.map = function(mapper) {\n        if (!mapper)\n            return this\n            \n        mapper = makeAsync(1, mapper)\n        \n        var source = this.source\n        this.next = function(callback) {\n            source.next(function(err, value) {\n                if (err)\n                    callback(err)\n                else {\n                    mapper(value, function(err, value) {\n                        if (err)\n                            callback(err)\n                        else\n                            callback(null, value)\n                    })\n                }\n            })\n        }\n        return new this.constructor(this)\n    }\n    \n    this.filter = function(filter) {\n        if (!filter)\n            return this\n            \n        filter = makeAsync(1, filter)\n        \n        var source = this.source\n        this.next = function(callback) {\n            source.next(function handler(err, value) {\n                if (err)\n                    callback(err)\n                else {\n                    filter(value, function(err, takeIt) {\n                        if (err)\n                            callback(err)\n                        else if (takeIt)\n                            callback(null, value)\n                        else\n                            source.next(handler)\n                    })\n                }\n            })\n        }\n        return new this.constructor(this)\n    }\n\n    this.slice = function(begin, end) {\n        var count = -1\n        if (!end || end < 0)\n            var end = Infinity\n        \n        var source = this.source\n        this.next = function(callback) {\n            source.next(function handler(err, value) {\n                count++\n                if (err)\n                    callback(err)\n                else if (count >= begin && count < end)\n                    callback(null, value)\n                else if (count >= end)\n                    callback(STOP)\n                else\n                    source.next(handler)\n            })\n        }\n        return new this.constructor(this)\n    }\n    \n    this.reduce = function(reduce, initialValue) {\n        reduce = makeAsync(3, reduce)\n\n        var index = 0\n        var done = false\n        var previousValue = initialValue\n        \n        var source = this.source\n        this.next = function(callback) {\n            if (done)\n                return callback(STOP)\n\n            if (initialValue === undefined) {\n                source.next(function(err, currentValue) {\n                    if (err)\n                        return callback(err, previousValue)\n                    \n                    previousValue = currentValue\n                    reduceAll()\n                })\n            }\n            else\n                reduceAll()\n\n            function reduceAll() {\n                source.next(function handler(err, currentValue) {                    \n                    if (err) {\n                        done = true\n                        if (err == STOP)                            \n                            return callback(null, previousValue)\n                        else\n                            return(err)\n                    }\n                    reduce(previousValue, currentValue, index++, function(err, value) {\n                        previousValue = value\n                        source.next(handler)\n                    })\n                })\n            }            \n        }\n        return new this.constructor(this)\n    }\n    \n    this.forEach =\n    this.each = function(fn) {\n        fn = makeAsync(1, fn)\n            \n        var source = this.source\n        this.next = function(callback) {\n            source.next(function handler(err, value) {\n                if (err) \n                    callback(err)\n                else {\n                    fn(value, function(err) {\n                        callback(err, value)\n                    })\n                }\n            })\n        }\n        return new this.constructor(this)\n    }\n    \n    this.some = function(condition) {\n        condition = makeAsync(1, condition)\n        \n        var source = this.source\n        var done = false\n        this.next = function(callback) {\n            if (done)\n                return callback(STOP)\n            \n            source.next(function handler(err, value) {\n                if (err)\n                    return callback(err)\n                    \n                condition(value, function(err, result) {\n                    if (err) {\n                        done = true\n                        if (err == STOP)\n                            callback(null, false)\n                        else\n                            callback(err)\n                    }                        \n                    else if (result) {\n                        done = true\n                        callback(null, true)\n                    }\n                    else \n                        source.next(handler)\n                })\n            })\n        }\n        return new this.constructor(this)\n    }\n    \n    this.every = function(condition) {\n        condition = makeAsync(1, condition)\n        \n        var source = this.source\n        var done = false\n        this.next = function(callback) {\n            if (done)\n                return callback(STOP)\n            \n            source.next(function handler(err, value) {\n                if (err)\n                    return callback(err)\n                    \n                condition(value, function(err, result) {\n                    if (err) {\n                        done = true\n                        if (err == STOP)\n                            callback(null, true)\n                        else\n                            callback(err)\n                    }                        \n                    else if (!result) {\n                        done = true\n                        callback(null, false)\n                    }\n                    else \n                        source.next(handler)\n                })\n            })\n        }\n        return new this.constructor(this)\n    }\n    \n    this.call = function(context) {\n        var source = this.source\n        return this.map(function(fn, next) {\n            fn = makeAsync(0, fn, context)\n            fn.call(context, function(err, value) {\n                next(err, value)\n            })\n        })\n    }\n    \n    this.concat = function(generator) {\n        var generators = [this]\n        generators.push.apply(generators, arguments)\n        var index = 0\n        var source = generators[index++]\n        \n        return new this.constructor(function(callback) {            \n            source.next(function handler(err, value) {\n                if (err) {\n                    if (err == STOP) {\n                        source = generators[index++]\n                        if (!source)\n                            return callback(STOP)\n                        else\n                            return source.next(handler)\n                    }\n                    else\n                        return callback(err)\n                }\n                else\n                    return callback(null, value)\n            })\n        })\n    }\n    \n    this.zip = function(generator) {\n        var generators = [this]\n        generators.push.apply(generators, arguments)\n        \n        return new this.constructor(function(callback) {\n            exports.list(generators)\n                .map(function(gen, next) {                    \n                    gen.next(next)\n                })\n                .toArray(callback)\n        })\n    }\n    \n    this.expand = function(inserter, constructor) {\n       if (!inserter)\n            return this\n            \n        var inserter = makeAsync(1, inserter)\n        var constructor = constructor || this.constructor\n        var source = this.source;\n        var spliced = null;\n        \n        return new constructor(function next(callback) {\n            if (!spliced) {\n                source.next(function(err, value) {\n                    if (err)\n                        return callback(err)\n                        \n                    inserter(value, function(err, toInsert) {\n                        if (err)\n                            return callback(err)\n                            \n                        spliced = toInsert                        \n                        next(callback)\n                    })\n\n                })\n            } \n            else {\n                spliced.next(function(err, value) {\n                    if (err == STOP) {\n                        spliced = null\n                        return next(callback)\n                    }\n                    else if (err)\n                        return callback(err)\n                    \n                    callback(err, value)\n                })\n            }\n        })\n    }\n\n    this.sort = function(compare) {\n        var self = this\n        var arrGen\n        this.next = function(callback) {\n            if (arrGen)\n                return arrGen.next(callback)\n\n            self.toArray(function(err, arr) {\n                if (err)\n                    callback(err)\n                else {\n                    arrGen = exports.list(arr.sort(compare))\n                    arrGen.next(callback)\n                }\n            })            \n        }\n        return new this.constructor(this)\n    }\n\n    this.join = function(separator) {\n        return this.$arrayOp(Array.prototype.join, separator !== undefined ? [separator] : null)\n    }\n    \n    this.reverse = function() {\n        return this.$arrayOp(Array.prototype.reverse)\n    }\n    \n    this.$arrayOp = function(arrayMethod, args) {\n        var self = this\n        var i = 0\n        this.next = function(callback) {\n            if (i++ > 0)\n                return callback(STOP)\n                \n            self.toArray(function(err, arr) {\n                if (err)\n                    callback(err, \"\")\n                else {\n                    if (args)\n                        callback(null, arrayMethod.apply(arr, args))\n                    else\n                        callback(null, arrayMethod.call(arr))\n                }\n            })\n        }\n        return new this.constructor(this)\n        \n    }\n    \n    this.end = function(breakOnError, callback) {\n    \tif (!callback) {\n            callback = arguments[0]\n            breakOnError = true\n        }\n\n        var source = this.source\n        var last\n        var lastError\n        source.next(function handler(err, value) {\n            if (err) {\n                if (err == STOP)\n                    callback && callback(lastError, last)\n                else if (!breakOnError) {\n                    lastError = err\n                    source.next(handler)\n                }\n                else\n                    callback && callback(err, value)\n            }\n            else  {\n                last = value\n                source.next(handler)\n            }\n        })\n    }\n\n    this.toArray = function(breakOnError, callback) {\n        if (!callback) {\n            callback = arguments[0]\n            breakOnError = true\n        }\n        \n        var values = []\n        var errors = []\n        var source = this.source\n        \n        source.next(function handler(err, value) {\n            if (err) {\n                if (err == STOP) {\n                    if (breakOnError)\n                        return callback(null, values)\n                    else {\n                        errors.length = values.length\n                        return callback(errors, values)\n                    }\n                }\n                else {\n                    if (breakOnError)\n                        return callback(err)\n                    else\n                        errors[values.length] = err\n                }\n            }\n\n            values.push(value)\n            source.next(handler)\n        })\n    }\n\n}).call(exports.Generator.prototype)\n\nvar makeAsync = exports.makeAsync = function(args, fn, context) {\n    if (fn.length > args) \n        return fn\n    else {\n        return function() {\n            var value\n            var next = arguments[args]\n            try {\n                value = fn.apply(context || this, arguments)\n            } catch(e) {\n                return next(e)\n            }\n            next(null, value)\n        }\n    }\n}\n\nexports.list = function(arr, construct) {\n    var construct = construct || exports.Generator\n    var i = 0\n    var len = arr.length\n    \n    return new construct(function(callback) {\n        if (i < len)\n            callback(null, arr[i++])\n        else\n            callback(STOP)\n    })\n}\n\nexports.values = function(map, construct) {\n    var values = []\n    for (var key in map) \n        values.push(map[key])\n        \n    return exports.list(values, construct)\n}\n\nexports.keys = function(map, construct) {\n    var keys = []\n    for (var key in map) \n        keys.push(key)\n        \n    return exports.list(keys, construct)\n}\n\n/**\n * range([start,] stop[, step]) -> generator of integers\n *\n * Return a generator containing an arithmetic progression of integers.\n * range(i, j) returns [i, i+1, i+2, ..., j-1] start (!) defaults to 0.\n * When step is given, it specifies the increment (or decrement).\n */ \nexports.range = function(start, stop, step, construct) {\n    var construct = construct || exports.Generator\n    start = start || 0\n    step = step || 1\n    \n    if (stop === undefined || stop === null)\n        stop = step > 0 ? Infinity : -Infinity\n        \n    var value = start\n    \n    return new construct(function(callback) {\n        if (step > 0 && value >= stop || step < 0 && value <= stop)\n            callback(STOP)\n        else {\n            var current = value\n            value += step\n            callback(null, current)\n        }\n    })\n}\n\nexports.concat = function(first, varargs) {\n    if (arguments.length > 1)\n        return first.concat.apply(first, Array.prototype.slice.call(arguments, 1))\n    else\n        return first\n}\n\nexports.zip = function(first, varargs) {\n    if (arguments.length > 1)\n        return first.zip.apply(first, Array.prototype.slice.call(arguments, 1))\n    else\n        return first.map(function(item, next) {\n            next(null, [item])\n        })\n}\n\n\nexports.plugin = function(members, constructors) {\n    if (members) {\n        for (var key in members) {\n            exports.Generator.prototype[key] = members[key]\n        }\n    }\n\n    if (constructors) {\n        for (var key in constructors) {\n            exports[key] = constructors[key]\n        }\n    }    \n}\n\n})\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/test/asyncjs/index.js",
    "content": "/*!\n * async.js\n * Copyright(c) 2010 Fabian Jakobs <fabian.jakobs@web.de>\n * MIT Licensed\n */\n\ndefine(function(require, exports, module) {\n    \nmodule.exports = require(\"./async\")\nmodule.exports.test = require(\"./test\")\nrequire(\"./utils\")\n\n})\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/test/asyncjs/test.js",
    "content": "/*!\n * async.js\n * Copyright(c) 2010 Fabian Jakobs <fabian.jakobs@web.de>\n * MIT Licensed\n */\n\ndefine(function(require, exports, module) {\n\nvar oop = require(\"ace/lib/oop\")\nvar async = require(\"asyncjs/async\")\nrequire(\"asyncjs/utils\")\n\nexports.TestGenerator = function(source) {\n    async.Generator.call(this, source)\n}\n\noop.inherits(exports.TestGenerator, async.Generator)\n\n;(function() {\n    \n    this.exec = function() {\n        this.run().report().summary(function(err, passed) {\n            console.log(\"DONE\")\n        })\n    }\n    \n    this.run = function() {\n        return this.setupTest()\n            .each(function(test, next) {\n                if (test.setUpSuite)\n                    test.setUpSuite(next)\n                else\n                    next()\n            })\n            .each(function(test, next) {\n                test.test(function(err, passed) {\n                    test.err = err\n                    test.passed = passed\n                    next()\n                })\n            })\n            .each(function(test, next) {\n                if (test.tearDownSuite)\n                    test.tearDownSuite(next)\n                else\n                    next()\n            })\n    }\n    \n    this.report = function() {\n        return this.each(function(test, next) {\n            var color = test.passed ? \"\\x1b[32m\" : \"\\x1b[31m\"\n            var name = test.name\n            if (test.suiteName)\n                name = test.suiteName + \": \" + test.name\n            console.log(color + \"[\" + test.count + \"/\" + test.index + \"] \" + name + \" \" + (test.passed ? \"OK\" : \"FAIL\") + \"\\x1b[0m\")\n            if (!test.passed)                \n                if (test.err.stack)\n                    console.log(test.err.stack)\n                else\n                    console.log(test.err)\n                    \n            next()\n        })\n    }\n    \n    this.summary = function(callback) {\n        var passed = 0\n        var failed = 0\n        \n        this.each(function(test) {\n            if (test.passed)\n                passed += 1\n            else\n                failed += 1\n        }).end(function() {\n            console.log(\"\")\n            console.log(\"Summary:\")\n            console.log(\"\")\n            console.log(                  \"Total number of tests: \" + (passed + failed))\n            passed && console.log(\"\\x1b[32mPassed tests:          \" + passed + \"\\x1b[0m\")\n            failed && console.log(\"\\x1b[31mFailed tests:          \" + failed + \"\\x1b[0m\")\n            console.log(\"\")            \n            callback(null, failed == 0)\n        })\n    }\n    \n    this.setupTest = function() {\n        return this.each(function(test, next) {\n            var empty = function(next) { next() }\n            var context = test.context || this\n            \n            if (test.setUp)\n                var setUp = async.makeAsync(0, test.setUp, context)\n            else \n                setUp = empty\n\n            tearDownCalled = false\n            if (test.tearDown)\n                var tearDownInner = async.makeAsync(0, test.tearDown, context)\n            else\n                tearDownInner = empty\n                \n            function tearDown(next) {\n                tearDownCalled = true\n                tearDownInner.call(test.context, next)\n            }\n\n            var testFn = async.makeAsync(0, test.fn, context)\n                \n            test.test = function(callback) {    \n                var called            \n                function errorListener(e) {\n                    if (called)\n                        return\n                    called = true\n                    //process.removeListener('uncaughtException', errorListener)\n                    if (!tearDownCalled) {\n                        async.list([tearDown])\n                            .call()\n                            .timeout(test.timeout)\n                            .end(function() {\n                                callback(e, false)\n                            })                    }\n                    else\n                        callback(e, false)\n                }\n                //process.addListener('uncaughtException', errorListener)\n                \n                async.list([setUp, testFn, tearDown])\n                    .delay(0)\n                    .call(context)\n                    .timeout(test.timeout)\n                    .toArray(false, function(errors, values) {\n                        if (called)\n                            return\n                        called = true\n                        var err = errors[1]\n                        //process.removeListener('uncaughtException', errorListener)                            \n                        callback(err, !err)                        \n                    })\n            }\n            \n            next()\n        })\n    }\n    \n}).call(exports.TestGenerator.prototype)\n\nexports.testcase = function(testcase, suiteName, timeout) {\n    var methods = []\n    for (var method in testcase)\n        methods.push(method)\n        \n    var setUp = testcase.setUp || null\n    var tearDown = testcase.tearDown || null\n    \n    var single\n    methods.forEach(function(name) {\n        if (name.charAt(0) == '>')\n           single = name\n    })\n    if (single)\n        methods = [single]\n    \n    var testNames = methods.filter(function(method) { \n        return method.match(/^>?test/) && typeof(testcase[method]) == \"function\"\n    })\n    var count = testNames.length\n    var i=1\n    tests = testNames.map(function(name) {\n        return {\n            suiteName: suiteName || testcase.name || \"\",\n            name: name,\n            setUp: setUp,\n            tearDown: tearDown,\n            context: testcase,\n            timeout: timeout === undefined ? 3000 : timeout,\n            fn: testcase[name],\n            count: count,\n            index: i++\n        }\n    })\n\n    if (testcase.setUpSuite) {\n        tests[0].setUpSuite = async.makeAsync(0, testcase.setUpSuite, testcase)\n    }\n    if (testcase.tearDownSuite) {\n        tests[tests.length-1].tearDownSuite = async.makeAsync(0, testcase.tearDownSuite, testcase)\n    }\n\n    return async.list(tests, exports.TestGenerator)\n}\n\n})\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/test/asyncjs/utils.js",
    "content": "/*!\n * async.js\n * Copyright(c) 2010 Fabian Jakobs <fabian.jakobs@web.de>\n * MIT Licensed\n */\n\ndefine(function(require, exports, module) {\n\nvar async = require(\"asyncjs/async\")\n\nasync.plugin({\n    delay: function(delay) {\n        return this.each(function(item, next) {\n            setTimeout(function() {\n                next();\n            }, delay)\n        })\n    },\n    \n    timeout: function(timeout) {\n        timeout = timeout || 0\n        var source = this.source\n        \n        this.next = function(callback) {\n            var called            \n            var id = setTimeout(function() {\n                called = true\n                callback(\"Source did not respond after \" + timeout + \"ms!\")\n            }, timeout)\n            \n            source.next(function(err, value) {\n                if (called)\n                    return\n\n                called = true\n                clearTimeout(id)\n                \n                callback(err, value)\n            })\n        }\n        return new this.constructor(this)\n    },\n    \n    get: function(key) {\n        return this.map(function(value, next) {\n            next(null, value[key])\n        })\n    },\n    \n    inspect: function() {\n        return this.each(function(item, next) {\n            console.log(JSON.stringify(item))\n            next()\n        })\n    },\n    \n    print: function() {\n        return this.each(function(item, next) {\n            console.log(item)\n            next()\n        })\n    }    \n})\n\n})\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/test/benchmark.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"../edit_session\").EditSession;\n\nmodule.exports = {\n    setUp : function() {\n        this.start = Date.now();\n    },\n    \n    tearDown : function() {\n        console.log(\"took: \", Date.now() - this.start + \"ms\");\n    },\n    \n    \"test: document to screen position\": function() {\n        var s = new EditSession(Array(6000).join('someText\\n'));\n\n        for (var i=0; i<6000; i++)\n            s.documentToScreenPosition(i, 0);\n\n        for (var i=0; i<6000; i++)\n            s.documentToScreenPosition(i, 0);\n\n        console.log(s.$rowCache.length);\n    },\n    \n    \"test: screen to document position\": function() {\n        var s = new EditSession(Array(6000).join('someText\\n'));\n\n        for (var i=0; i<6000; i++)\n            s.screenToDocumentPosition(i, 0);\n\n        for (var i=0; i<6000; i++)\n            s.documentToScreenPosition(i, 0);\n\n        console.log(s.$rowCache.length);\n    }\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec();\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/test/mockdom.js",
    "content": "\"use strict\";\n\nvar dom     = require('jsdom/lib/jsdom/level2/html').dom.level2.html;\nvar browser = require('jsdom/lib/jsdom/browser/index').windowAugmentation(dom);\n\nglobal.document     = browser.document;\nglobal.window       = browser.window;\nglobal.self         = browser.self;\nglobal.navigator    = browser.navigator;\nglobal.location     = browser.location;\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/test/mockrenderer.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar MockRenderer = exports.MockRenderer = function(visibleRowCount) {\n    this.container = document.createElement(\"div\");\n    this.visibleRowCount = visibleRowCount || 20;\n\n    this.layerConfig = {\n        firstVisibleRow : 0,\n        lastVisibleRow : this.visibleRowCount\n    };\n\n    this.isMockRenderer = true;\n\n    this.$gutter = {};\n};\n\n\nMockRenderer.prototype.getFirstVisibleRow = function() {\n    return this.layerConfig.firstVisibleRow;\n};\n\nMockRenderer.prototype.getLastVisibleRow = function() {\n    return this.layerConfig.lastVisibleRow;\n};\n\nMockRenderer.prototype.getFirstFullyVisibleRow = function() {\n    return this.layerConfig.firstVisibleRow;\n};\n\nMockRenderer.prototype.getLastFullyVisibleRow = function() {\n    return this.layerConfig.lastVisibleRow;\n};\n\nMockRenderer.prototype.getContainerElement = function() {\n    return this.container;\n};\n\nMockRenderer.prototype.getMouseEventTarget = function() {\n    return this.container;\n};\n\nMockRenderer.prototype.getTextAreaContainer = function() {\n    return this.container;\n};\n\nMockRenderer.prototype.addGutterDecoration = function() {\n};\n\nMockRenderer.prototype.removeGutterDecoration = function() {\n};\n\nMockRenderer.prototype.moveTextAreaToCursor = function() {\n};\n\nMockRenderer.prototype.setSession = function(session) {\n    this.session = session;\n};\n\nMockRenderer.prototype.getSession = function(session) {\n    return this.session;\n};\n\nMockRenderer.prototype.setTokenizer = function() {\n};\n\nMockRenderer.prototype.on = function() {\n};\n\nMockRenderer.prototype.updateCursor = function() {\n};\n\nMockRenderer.prototype.scrollToX = function(scrollTop) {};\nMockRenderer.prototype.scrollToY = function(scrollLeft) {};\n\nMockRenderer.prototype.scrollToLine = function(line, center) {\n    var lineHeight = { lineHeight: 16 };\n    var row = 0;\n    for (var l = 1; l < line; l++) {\n        row += this.session.getRowHeight(lineHeight, l-1) / lineHeight.lineHeight;\n    }\n\n    if (center) {\n        row -= this.visibleRowCount / 2;\n    }\n    this.scrollToRow(row);\n};\n\nMockRenderer.prototype.scrollSelectionIntoView = function() {\n};\n\nMockRenderer.prototype.scrollCursorIntoView = function() {\n    var cursor = this.session.getSelection().getCursor();\n    if (cursor.row < this.layerConfig.firstVisibleRow) {\n        this.scrollToRow(cursor.row);\n    }\n    else if (cursor.row > this.layerConfig.lastVisibleRow) {\n        this.scrollToRow(cursor.row);\n    }\n};\n\nMockRenderer.prototype.scrollToRow = function(row) {\n    var row = Math.min(this.session.getLength() - this.visibleRowCount, Math.max(0,\n                                                                          row));\n    this.layerConfig.firstVisibleRow = row;\n    this.layerConfig.lastVisibleRow = row + this.visibleRowCount;\n};\n\nMockRenderer.prototype.getScrollTopRow = function() {\n  return this.layerConfig.firstVisibleRow;\n};\n\nMockRenderer.prototype.draw = function() {\n};\n\nMockRenderer.prototype.updateLines = function(startRow, endRow) {\n};\n\nMockRenderer.prototype.updateBackMarkers = function() {\n};\n\nMockRenderer.prototype.updateFrontMarkers = function() {\n};\n\nMockRenderer.prototype.setBreakpoints = function() {\n};\n\nMockRenderer.prototype.onResize = function() {\n};\n\nMockRenderer.prototype.updateFull = function() {\n};\n\nMockRenderer.prototype.updateText = function() {\n};\n\nMockRenderer.prototype.showCursor = function() {\n};\n\nMockRenderer.prototype.visualizeFocus = function() {\n};\n\nMockRenderer.prototype.setAnnotations = function() {\n};\n\nMockRenderer.prototype.setStyle = function() {\n};\n\nMockRenderer.prototype.unsetStyle = function() {\n};\n\nMockRenderer.prototype.textToScreenCoordinates = function() {\n    return {\n        pageX: 0,\n        pageY: 0\n    }\n};\n\nMockRenderer.prototype.adjustWrapLimit = function () {\n\n};\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/test/tests.html",
    "content": "\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n  <title>Ace Unit Tests</title>\n  <style type=\"text/css\" media=\"screen\">\n\n    #log .passed {\n        color: green;\n    }\n    \n    #log .failed {\n        color: red;\n    }\n    \n    #log pre.error {\n        color: black;\n    }\n  </style>\n</head>\n<body>\n    \n<div id=\"log\"></div>\n\n<script type=\"text/javascript\">\n    var require = {\n        paths: {\n            ace: \"../\"\n        },\n        packages : [{\n            name: \"asyncjs\",\n            location: \"./asyncjs\",\n            main: \"index\"\n        }, {\n            name: \"assert\",\n            location: \"./asyncjs\",\n            main: \"assert\"\n        }]\n    };\n</script>\n<script src=\"../../../demo/kitchen-sink/require.js\" data-main=\"all_browser\" type=\"text/javascript\" charset=\"utf-8\"></script>\n\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/chrome.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.cssClass = \"ace-chrome\";\nexports.cssText = \".ace-chrome .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-chrome .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-chrome .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n  overflow : hidden;\\\n}\\\n\\\n.ace-chrome .ace_gutter-layer {\\\n  width: 100%;\\\n  text-align: right;\\\n}\\\n\\\n.ace-chrome .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-chrome .ace_text-layer {\\\n  cursor: text;\\\n}\\\n\\\n.ace-chrome .ace_cursor {\\\n  border-left: 2px solid black;\\\n}\\\n\\\n.ace-chrome .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid black;\\\n}\\\n\\\n.ace-chrome .ace_line .ace_invisible {\\\n  color: rgb(191, 191, 191);\\\n}\\\n\\\n.ace-chrome .ace_line .ace_constant.ace_buildin {\\\n  color: rgb(88, 72, 246);\\\n}\\\n\\\n.ace-chrome .ace_line .ace_constant.ace_language {\\\n  color: rgb(88, 92, 246);\\\n}\\\n\\\n.ace-chrome .ace_line .ace_constant.ace_library {\\\n  color: rgb(6, 150, 14);\\\n}\\\n\\\n.ace-chrome .ace_line .ace_invalid {\\\n  background-color: rgb(153, 0, 0);\\\n  color: white;\\\n}\\\n\\\n.ace-chrome .ace_line .ace_fold {\\\n}\\\n\\\n.ace-chrome .ace_line .ace_support.ace_function {\\\n  color: rgb(60, 76, 114);\\\n}\\\n\\\n.ace-chrome .ace_line .ace_support.ace_constant {\\\n  color: rgb(6, 150, 14);\\\n}\\\n\\\n.ace-chrome .ace_line .ace_support.ace_type,\\\n.ace-chrome .ace_line .ace_support.ace_class {\\\n  color: rgb(109, 121, 222);\\\n}\\\n\\\n.ace-chrome .ace_variable.ace_parameter {\\\n  font-style:italic;\\\ncolor:#FD971F;\\\n}\\\n.ace-chrome .ace_line .ace_keyword.ace_operator {\\\n  color: rgb(104, 118, 135);\\\n}\\\n\\\n.ace-chrome .ace_line .ace_comment {\\\n  color: #236e24;\\\n}\\\n\\\n.ace-chrome .ace_line .ace_comment.ace_doc {\\\n  color: #236e24;\\\n}\\\n\\\n.ace-chrome .ace_line .ace_comment.ace_doc.ace_tag {\\\n  color: #236e24;\\\n}\\\n\\\n.ace-chrome .ace_line .ace_constant.ace_numeric {\\\n  color: rgb(0, 0, 205);\\\n}\\\n\\\n.ace-chrome .ace_line .ace_variable {\\\n  color: rgb(49, 132, 149);\\\n}\\\n\\\n.ace-chrome .ace_line .ace_xml_pe {\\\n  color: rgb(104, 104, 91);\\\n}\\\n\\\n.ace-chrome .ace_entity.ace_name.ace_function {\\\n  color: #0000A2;\\\n}\\\n\\\n.ace-chrome .ace_markup.ace_markupine {\\\n    text-decoration:underline;\\\n}\\\n\\\n.ace-chrome .ace_markup.ace_heading {\\\n  color: rgb(12, 7, 255);\\\n}\\\n\\\n.ace-chrome .ace_markup.ace_list {\\\n  color:rgb(185, 6, 144);\\\n}\\\n\\\n.ace-chrome .ace_marker-layer .ace_selection {\\\n  background: rgb(181, 213, 255);\\\n}\\\n\\\n.ace-chrome .ace_marker-layer .ace_step {\\\n  background: rgb(252, 255, 0);\\\n}\\\n\\\n.ace-chrome .ace_marker-layer .ace_stack {\\\n  background: rgb(164, 229, 101);\\\n}\\\n\\\n.ace-chrome .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid rgb(192, 192, 192);\\\n}\\\n\\\n.ace-chrome .ace_marker-layer .ace_active_line {\\\n  background: rgba(0, 0, 0, 0.07);\\\n}\\\n\\\n.ace-chrome .ace_marker-layer .ace_selected_word {\\\n  background: rgb(250, 250, 255);\\\n  border: 1px solid rgb(200, 200, 250);\\\n}\\\n\\\n.ace-chrome .ace_storage,\\\n.ace-chrome .ace_line .ace_keyword,\\\n.ace-chrome .ace_meta.ace_tag {\\\n  color: rgb(147, 15, 128);\\\n}\\\n\\\n.ace-chrome .ace_string.ace_regex {\\\n  color: rgb(255, 0, 0)\\\n}\\\n\\\n.ace-chrome .ace_line .ace_string,\\\n.ace-chrome .ace_entity.ace_other.ace_attribute-name{\\\n  color: #994409;\\\n}\";\n\nvar dom = require(\"../lib/dom\");\ndom.importCssString(exports.cssText, exports.cssClass);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/clouds.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = false;\nexports.cssClass = \"ace-clouds\";\nexports.cssText = \"\\\n.ace-clouds .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-clouds .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-clouds .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-clouds .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-clouds .ace_scroller {\\\n  background-color: #FFFFFF;\\\n}\\\n\\\n.ace-clouds .ace_text-layer {\\\n  cursor: text;\\\n  color: #000000;\\\n}\\\n\\\n.ace-clouds .ace_cursor {\\\n  border-left: 2px solid #000000;\\\n}\\\n\\\n.ace-clouds .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #000000;\\\n}\\\n\\\n.ace-clouds .ace_marker-layer .ace_selection {\\\n  background: #BDD5FC;\\\n}\\\n\\\n.ace-clouds.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #FFFFFF;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-clouds .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-clouds .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid #BFBFBF;\\\n}\\\n\\\n.ace-clouds .ace_marker-layer .ace_active_line {\\\n  background: #FFFBD1;\\\n}\\\n\\\n.ace-clouds .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid #BDD5FC;\\\n}\\\n\\\n.ace-clouds .ace_invisible {\\\n  color: #BFBFBF;\\\n}\\\n\\\n.ace-clouds .ace_keyword, .ace-clouds .ace_meta {\\\n  color:#AF956F;\\\n}\\\n\\\n.ace-clouds .ace_keyword.ace_operator {\\\n  color:#484848;\\\n}\\\n\\\n.ace-clouds .ace_constant.ace_language {\\\n  color:#39946A;\\\n}\\\n\\\n.ace-clouds .ace_constant.ace_numeric {\\\n  color:#46A609;\\\n}\\\n\\\n.ace-clouds .ace_invalid {\\\n  background-color:#FF002A;\\\n}\\\n\\\n.ace-clouds .ace_fold {\\\n    background-color: #AF956F;\\\n    border-color: #000000;\\\n}\\\n\\\n.ace-clouds .ace_support.ace_function {\\\n  color:#C52727;\\\n}\\\n\\\n.ace-clouds .ace_storage {\\\n  color:#C52727;\\\n}\\\n\\\n.ace-clouds .ace_string {\\\n  color:#5D90CD;\\\n}\\\n\\\n.ace-clouds .ace_comment {\\\n  color:#BCC8BA;\\\n}\\\n\\\n.ace-clouds .ace_entity.ace_other.ace_attribute-name {\\\n  color:#606060;\\\n}\\\n\\\n.ace-clouds .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/clouds_midnight.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-clouds-midnight\";\nexports.cssText = \"\\\n.ace-clouds-midnight .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-clouds-midnight .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-clouds-midnight .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-clouds-midnight .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-clouds-midnight .ace_scroller {\\\n  background-color: #191919;\\\n}\\\n\\\n.ace-clouds-midnight .ace_text-layer {\\\n  cursor: text;\\\n  color: #929292;\\\n}\\\n\\\n.ace-clouds-midnight .ace_cursor {\\\n  border-left: 2px solid #7DA5DC;\\\n}\\\n\\\n.ace-clouds-midnight .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #7DA5DC;\\\n}\\\n\\\n.ace-clouds-midnight .ace_marker-layer .ace_selection {\\\n  background: #000000;\\\n}\\\n\\\n.ace-clouds-midnight.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #191919;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-clouds-midnight .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-clouds-midnight .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid #BFBFBF;\\\n}\\\n\\\n.ace-clouds-midnight .ace_marker-layer .ace_active_line {\\\n  background: rgba(215, 215, 215, 0.031);\\\n}\\\n\\\n.ace-clouds-midnight .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid #000000;\\\n}\\\n\\\n.ace-clouds-midnight .ace_invisible {\\\n  color: #BFBFBF;\\\n}\\\n\\\n.ace-clouds-midnight .ace_keyword, .ace-clouds-midnight .ace_meta {\\\n  color:#927C5D;\\\n}\\\n\\\n.ace-clouds-midnight .ace_keyword.ace_operator {\\\n  color:#4B4B4B;\\\n}\\\n\\\n.ace-clouds-midnight .ace_constant.ace_language {\\\n  color:#39946A;\\\n}\\\n\\\n.ace-clouds-midnight .ace_constant.ace_numeric {\\\n  color:#46A609;\\\n}\\\n\\\n.ace-clouds-midnight .ace_invalid {\\\n  color:#FFFFFF;\\\nbackground-color:#E92E2E;\\\n}\\\n\\\n.ace-clouds-midnight .ace_fold {\\\n    background-color: #927C5D;\\\n    border-color: #929292;\\\n}\\\n\\\n.ace-clouds-midnight .ace_support.ace_function {\\\n  color:#E92E2E;\\\n}\\\n\\\n.ace-clouds-midnight .ace_storage {\\\n  color:#E92E2E;\\\n}\\\n\\\n.ace-clouds-midnight .ace_string {\\\n  color:#5D90CD;\\\n}\\\n\\\n.ace-clouds-midnight .ace_comment {\\\n  color:#3C403B;\\\n}\\\n\\\n.ace-clouds-midnight .ace_entity.ace_other.ace_attribute-name {\\\n  color:#606060;\\\n}\\\n\\\n.ace-clouds-midnight .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/cobalt.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-cobalt\";\nexports.cssText = \"\\\n.ace-cobalt .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-cobalt .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-cobalt .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-cobalt .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-cobalt .ace_scroller {\\\n  background-color: #002240;\\\n}\\\n\\\n.ace-cobalt .ace_text-layer {\\\n  cursor: text;\\\n  color: #FFFFFF;\\\n}\\\n\\\n.ace-cobalt .ace_cursor {\\\n  border-left: 2px solid #FFFFFF;\\\n}\\\n\\\n.ace-cobalt .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #FFFFFF;\\\n}\\\n\\\n.ace-cobalt .ace_marker-layer .ace_selection {\\\n  background: rgba(179, 101, 57, 0.75);\\\n}\\\n\\\n.ace-cobalt.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #002240;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-cobalt .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-cobalt .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid rgba(255, 255, 255, 0.15);\\\n}\\\n\\\n.ace-cobalt .ace_marker-layer .ace_active_line {\\\n  background: rgba(0, 0, 0, 0.35);\\\n}\\\n\\\n.ace-cobalt .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid rgba(179, 101, 57, 0.75);\\\n}\\\n\\\n.ace-cobalt .ace_invisible {\\\n  color: rgba(255, 255, 255, 0.15);\\\n}\\\n\\\n.ace-cobalt .ace_keyword, .ace-cobalt .ace_meta {\\\n  color:#FF9D00;\\\n}\\\n\\\n.ace-cobalt .ace_constant, .ace-cobalt .ace_constant.ace_other {\\\n  color:#FF628C;\\\n}\\\n\\\n.ace-cobalt .ace_constant.ace_character,  {\\\n  color:#FF628C;\\\n}\\\n\\\n.ace-cobalt .ace_constant.ace_character.ace_escape,  {\\\n  color:#FF628C;\\\n}\\\n\\\n.ace-cobalt .ace_invalid {\\\n  color:#F8F8F8;\\\nbackground-color:#800F00;\\\n}\\\n\\\n.ace-cobalt .ace_support {\\\n  color:#80FFBB;\\\n}\\\n\\\n.ace-cobalt .ace_support.ace_constant {\\\n  color:#EB939A;\\\n}\\\n\\\n.ace-cobalt .ace_fold {\\\n    background-color: #FF9D00;\\\n    border-color: #FFFFFF;\\\n}\\\n\\\n.ace-cobalt .ace_support.ace_function {\\\n  color:#FFB054;\\\n}\\\n\\\n.ace-cobalt .ace_storage {\\\n  color:#FFEE80;\\\n}\\\n\\\n.ace-cobalt .ace_string.ace_regexp {\\\n  color:#80FFC2;\\\n}\\\n\\\n.ace-cobalt .ace_comment {\\\n  font-style:italic;\\\ncolor:#0088FF;\\\n}\\\n\\\n.ace-cobalt .ace_variable {\\\n  color:#CCCCCC;\\\n}\\\n\\\n.ace-cobalt .ace_variable.ace_language {\\\n  color:#FF80E1;\\\n}\\\n\\\n.ace-cobalt .ace_meta.ace_tag {\\\n  color:#9EFFFF;\\\n}\\\n\\\n.ace-cobalt .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\\\n\\\n.ace-cobalt .ace_markup.ace_heading {\\\n  color:#C8E4FD;\\\nbackground-color:#001221;\\\n}\\\n\\\n.ace-cobalt .ace_markup.ace_list {\\\n  background-color:#130D26;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/crimson_editor.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\nexports.isDark = false;\nexports.cssText = \".ace-crimson-editor .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-crimson-editor .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-crimson-editor .ace_gutter {\\\n  width: 50px;\\\n  background: #e8e8e8;\\\n  color: #333;\\\n  overflow : hidden;\\\n}\\\n\\\n.ace-crimson-editor .ace_gutter-layer {\\\n  width: 100%;\\\n  text-align: right;\\\n}\\\n\\\n.ace-crimson-editor .ace_gutter-layer .ace_gutter-cell {\\\n  padding-right: 6px;\\\n}\\\n\\\n.ace-crimson-editor .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-crimson-editor .ace_text-layer {\\\n  cursor: text;\\\n  color: rgb(64, 64, 64);\\\n}\\\n\\\n.ace-crimson-editor .ace_cursor {\\\n  border-left: 2px solid black;\\\n}\\\n\\\n.ace-crimson-editor .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid black;\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_invisible {\\\n  color: rgb(191, 191, 191);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_identifier {\\\n  color: black;\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_keyword {\\\n  color: blue;\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_constant.ace_buildin {\\\n  color: rgb(88, 72, 246);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_constant.ace_language {\\\n  color: rgb(255, 156, 0);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_constant.ace_library {\\\n  color: rgb(6, 150, 14);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_invalid {\\\n  text-decoration: line-through;\\\n  color: rgb(224, 0, 0);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_fold {\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_support.ace_function {\\\n  color: rgb(192, 0, 0);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_support.ace_constant {\\\n  color: rgb(6, 150, 14);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_support.ace_type,\\\n.ace-crimson-editor .ace_line .ace_support.ace_class {\\\n  color: rgb(109, 121, 222);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_keyword.ace_operator {\\\n  color: rgb(49, 132, 149);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_string {\\\n  color: rgb(128, 0, 128);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_comment {\\\n  color: rgb(76, 136, 107);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_comment.ace_doc {\\\n  color: rgb(0, 102, 255);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_comment.ace_doc.ace_tag {\\\n  color: rgb(128, 159, 191);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_constant.ace_numeric {\\\n  color: rgb(0, 0, 64);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_variable {\\\n  color: rgb(0, 64, 128);\\\n}\\\n\\\n.ace-crimson-editor .ace_line .ace_xml_pe {\\\n  color: rgb(104, 104, 91);\\\n}\\\n\\\n.ace-crimson-editor .ace_marker-layer .ace_selection {\\\n  background: rgb(181, 213, 255);\\\n}\\\n\\\n.ace-crimson-editor .ace_marker-layer .ace_step {\\\n  background: rgb(252, 255, 0);\\\n}\\\n\\\n.ace-crimson-editor .ace_marker-layer .ace_stack {\\\n  background: rgb(164, 229, 101);\\\n}\\\n\\\n.ace-crimson-editor .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid rgb(192, 192, 192);\\\n}\\\n\\\n.ace-crimson-editor .ace_marker-layer .ace_active_line {\\\n  background: rgb(232, 242, 254);\\\n}\\\n\\\n.ace-crimson-editor .ace_meta.ace_tag {\\\n  color:rgb(28, 2, 255);\\\n}\\\n\\\n.ace-crimson-editor .ace_marker-layer .ace_selected_word {\\\n  background: rgb(250, 250, 255);\\\n  border: 1px solid rgb(200, 200, 250);\\\n}\\\n\\\n.ace-crimson-editor .ace_string.ace_regex {\\\n  color: rgb(192, 0, 192);\\\n}\";\n\nexports.cssClass = \"ace-crimson-editor\";\n\nvar dom = require(\"../lib/dom\");\ndom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/dawn.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = false;\nexports.cssClass = \"ace-dawn\";\nexports.cssText = \"\\\n.ace-dawn .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-dawn .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-dawn .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-dawn .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-dawn .ace_scroller {\\\n  background-color: #F9F9F9;\\\n}\\\n\\\n.ace-dawn .ace_text-layer {\\\n  cursor: text;\\\n  color: #080808;\\\n}\\\n\\\n.ace-dawn .ace_cursor {\\\n  border-left: 2px solid #000000;\\\n}\\\n\\\n.ace-dawn .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #000000;\\\n}\\\n\\\n.ace-dawn .ace_marker-layer .ace_selection {\\\n  background: rgba(39, 95, 255, 0.30);\\\n}\\\n\\\n.ace-dawn.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #F9F9F9;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-dawn .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-dawn .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid rgba(75, 75, 126, 0.50);\\\n}\\\n\\\n.ace-dawn .ace_marker-layer .ace_active_line {\\\n  background: rgba(36, 99, 180, 0.12);\\\n}\\\n\\\n.ace-dawn .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid rgba(39, 95, 255, 0.30);\\\n}\\\n\\\n.ace-dawn .ace_invisible {\\\n  color: rgba(75, 75, 126, 0.50);\\\n}\\\n\\\n.ace-dawn .ace_keyword, .ace-dawn .ace_meta {\\\n  color:#794938;\\\n}\\\n\\\n.ace-dawn .ace_constant, .ace-dawn .ace_constant.ace_other {\\\n  color:#811F24;\\\n}\\\n\\\n.ace-dawn .ace_constant.ace_character,  {\\\n  color:#811F24;\\\n}\\\n\\\n.ace-dawn .ace_constant.ace_character.ace_escape,  {\\\n  color:#811F24;\\\n}\\\n\\\n.ace-dawn .ace_invalid.ace_illegal {\\\n  text-decoration:underline;\\\nfont-style:italic;\\\ncolor:#F8F8F8;\\\nbackground-color:#B52A1D;\\\n}\\\n\\\n.ace-dawn .ace_invalid.ace_deprecated {\\\n  text-decoration:underline;\\\nfont-style:italic;\\\ncolor:#B52A1D;\\\n}\\\n\\\n.ace-dawn .ace_support {\\\n  color:#691C97;\\\n}\\\n\\\n.ace-dawn .ace_support.ace_constant {\\\n  color:#B4371F;\\\n}\\\n\\\n.ace-dawn .ace_fold {\\\n    background-color: #794938;\\\n    border-color: #080808;\\\n}\\\n\\\n.ace-dawn .ace_support.ace_function {\\\n  color:#693A17;\\\n}\\\n\\\n.ace-dawn .ace_storage {\\\n  font-style:italic;\\\ncolor:#A71D5D;\\\n}\\\n\\\n.ace-dawn .ace_string {\\\n  color:#0B6125;\\\n}\\\n\\\n.ace-dawn .ace_string.ace_regexp {\\\n  color:#CF5628;\\\n}\\\n\\\n.ace-dawn .ace_comment {\\\n  font-style:italic;\\\ncolor:#5A525F;\\\n}\\\n\\\n.ace-dawn .ace_variable {\\\n  color:#234A97;\\\n}\\\n\\\n.ace-dawn .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\\\n\\\n.ace-dawn .ace_markup.ace_heading {\\\n  color:#19356D;\\\n}\\\n\\\n.ace-dawn .ace_markup.ace_list {\\\n  color:#693A17;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/dreamweaver.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Adam Jimenez <adam AT shiftcreate DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\nexports.isDark = false;\nexports.cssClass = \"ace-dreamweaver\";\nexports.cssText = \".ace-dreamweaver .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-dreamweaver .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-dreamweaver .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-dreamweaver .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-dreamweaver .ace_fold {\\\n    background-color: #00F;\\\n}\\\n\\\n.ace-dreamweaver .ace_text-layer {\\\n  cursor: text;\\\n}\\\n\\\n.ace-dreamweaver .ace_cursor {\\\n  border-left: 2px solid black;\\\n}\\\n\\\n.ace-dreamweaver .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid black;\\\n}\\\n        \\\n.ace-dreamweaver .ace_line .ace_invisible {\\\n  color: rgb(191, 191, 191);\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_storage,\\\n.ace-dreamweaver .ace_line .ace_keyword {\\\n  color: blue;\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_constant.ace_buildin {\\\n  color: rgb(88, 72, 246);\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_constant.ace_language {\\\n  color: rgb(88, 92, 246);\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_constant.ace_library {\\\n  color: rgb(6, 150, 14);\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_invalid {\\\n  background-color: rgb(153, 0, 0);\\\n  color: white;\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_support.ace_function {\\\n  color: rgb(60, 76, 114);\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_support.ace_constant {\\\n  color: rgb(6, 150, 14);\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_support.ace_type,\\\n.ace-dreamweaver .ace_line .ace_support.ace_class {\\\n  color: #009;\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_support.ace_php_tag {\\\n  color: #f00;\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_keyword.ace_operator {\\\n  color: rgb(104, 118, 135);\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_string {\\\n  color: #00F;\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_comment {\\\n  color: rgb(76, 136, 107);\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_comment.ace_doc {\\\n  color: rgb(0, 102, 255);\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_comment.ace_doc.ace_tag {\\\n  color: rgb(128, 159, 191);\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_constant.ace_numeric {\\\n  color: rgb(0, 0, 205);\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_variable {\\\n  color: #06F\\\n}\\\n\\\n.ace-dreamweaver .ace_line .ace_xml_pe {\\\n  color: rgb(104, 104, 91);\\\n}\\\n\\\n.ace-dreamweaver .ace_entity.ace_name.ace_function {\\\n  color: #00F;\\\n}\\\n\\\n.ace-dreamweaver .ace_markup.ace_markupine {\\\n    text-decoration:underline;\\\n}\\\n\\\n.ace-dreamweaver .ace_markup.ace_heading {\\\n  color: rgb(12, 7, 255);\\\n}\\\n\\\n.ace-dreamweaver .ace_markup.ace_list {\\\n  color:rgb(185, 6, 144);\\\n}\\\n\\\n.ace-dreamweaver .ace_marker-layer .ace_selection {\\\n  background: rgb(181, 213, 255);\\\n}\\\n\\\n.ace-dreamweaver .ace_marker-layer .ace_step {\\\n  background: rgb(252, 255, 0);\\\n}\\\n\\\n.ace-dreamweaver .ace_marker-layer .ace_stack {\\\n  background: rgb(164, 229, 101);\\\n}\\\n\\\n.ace-dreamweaver .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid rgb(192, 192, 192);\\\n}\\\n\\\n.ace-dreamweaver .ace_marker-layer .ace_active_line {\\\n  background: rgba(0, 0, 0, 0.07);\\\n}\\\n\\\n.ace-dreamweaver .ace_marker-layer .ace_selected_word {\\\n  background: rgb(250, 250, 255);\\\n  border: 1px solid rgb(200, 200, 250);\\\n}\\\n\\\n.ace-dreamweaver .ace_meta.ace_tag {\\\n  color:#009;\\\n}\\\n\\\n.ace-dreamweaver .ace_meta.ace_tag.ace_anchor {\\\n  color:#060;\\\n}\\\n\\\n.ace-dreamweaver .ace_meta.ace_tag.ace_form {\\\n  color:#F90;\\\n}\\\n\\\n.ace-dreamweaver .ace_meta.ace_tag.ace_image {\\\n  color:#909;\\\n}\\\n\\\n.ace-dreamweaver .ace_meta.ace_tag.ace_script {\\\n  color:#900;\\\n}\\\n\\\n.ace-dreamweaver .ace_meta.ace_tag.ace_style {\\\n  color:#909;\\\n}\\\n\\\n.ace-dreamweaver .ace_meta.ace_tag.ace_table {\\\n  color:#099;\\\n}\\\n\\\n.ace-dreamweaver .ace_string.ace_regex {\\\n  color: rgb(255, 0, 0)\\\n}\";\n\nvar dom = require(\"../lib/dom\");\ndom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/eclipse.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nexports.isDark = false;\nexports.cssText = \".ace-eclipse .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-eclipse .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-eclipse .ace_gutter {\\\n  background: rgb(227, 227, 227);\\\n  border-right: 1px solid rgb(159, 159, 159);\\\n  color: rgb(136, 136, 136);\\\n}\\\n\\\n.ace-eclipse .ace_print_margin {\\\n  width: 1px;\\\n  background: #b1b4ba;\\\n}\\\n\\\n.ace-eclipse .ace_fold {\\\n    background-color: rgb(60, 76, 114);\\\n}\\\n\\\n.ace-eclipse .ace_text-layer {\\\n  cursor: text;\\\n}\\\n\\\n.ace-eclipse .ace_cursor {\\\n  border-left: 2px solid black;\\\n}\\\n\\\n.ace-eclipse .ace_line .ace_storage,\\\n.ace-eclipse .ace_line .ace_keyword,\\\n.ace-eclipse .ace_line .ace_variable {\\\n  color: rgb(127, 0, 85);\\\n}\\\n\\\n.ace-eclipse .ace_line .ace_constant.ace_buildin {\\\n  color: rgb(88, 72, 246);\\\n}\\\n\\\n.ace-eclipse .ace_line .ace_constant.ace_library {\\\n  color: rgb(6, 150, 14);\\\n}\\\n\\\n.ace-eclipse .ace_line .ace_function {\\\n  color: rgb(60, 76, 114);\\\n}\\\n\\\n.ace-eclipse .ace_line .ace_string {\\\n  color: rgb(42, 0, 255);\\\n}\\\n\\\n.ace-eclipse .ace_line .ace_comment {\\\n  color: rgb(63, 127, 95);\\\n}\\\n\\\n.ace-eclipse .ace_line .ace_comment.ace_doc {\\\n  color: rgb(63, 95, 191);\\\n}\\\n\\\n.ace-eclipse .ace_line .ace_comment.ace_doc.ace_tag {\\\n  color: rgb(127, 159, 191);\\\n}\\\n\\\n.ace-eclipse .ace_line .ace_constant.ace_numeric {\\\n}\\\n\\\n.ace-eclipse .ace_line .ace_tag {\\\n  color: rgb(63, 127, 127);\\\n}\\\n\\\n.ace-eclipse .ace_line .ace_type {\\\n  color: rgb(127, 0, 127);\\\n}\\\n\\\n.ace-eclipse .ace_line .ace_xml_pe {\\\n  color: rgb(104, 104, 91);\\\n}\\\n\\\n.ace-eclipse .ace_marker-layer .ace_selection {\\\n  background: rgb(181, 213, 255);\\\n}\\\n\\\n.ace-eclipse .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid rgb(192, 192, 192);\\\n}\\\n\\\n.ace-eclipse .ace_line .ace_meta.ace_tag {\\\n  color:rgb(63, 127, 127);\\\n}\\\n\\\n.ace-eclipse .ace_entity.ace_other.ace_attribute-name {\\\n  color:rgb(127, 0, 127);\\\n}\\\n\\\n.ace-eclipse .ace_marker-layer .ace_active_line {\\\n  background: rgb(232, 242, 254);\\\n}\";\n\nexports.cssClass = \"ace-eclipse\";\n\nvar dom = require(\"../lib/dom\");\ndom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/idle_fingers.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-idle-fingers\";\nexports.cssText = \"\\\n.ace-idle-fingers .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-idle-fingers .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-idle-fingers .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-idle-fingers .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-idle-fingers .ace_scroller {\\\n  background-color: #323232;\\\n}\\\n\\\n.ace-idle-fingers .ace_text-layer {\\\n  cursor: text;\\\n  color: #FFFFFF;\\\n}\\\n\\\n.ace-idle-fingers .ace_cursor {\\\n  border-left: 2px solid #91FF00;\\\n}\\\n\\\n.ace-idle-fingers .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #91FF00;\\\n}\\\n\\\n.ace-idle-fingers .ace_marker-layer .ace_selection {\\\n  background: rgba(90, 100, 126, 0.88);\\\n}\\\n\\\n.ace-idle-fingers.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #323232;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-idle-fingers .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-idle-fingers .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid #404040;\\\n}\\\n\\\n.ace-idle-fingers .ace_marker-layer .ace_active_line {\\\n  background: #353637;\\\n}\\\n\\\n.ace-idle-fingers .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid rgba(90, 100, 126, 0.88);\\\n}\\\n\\\n.ace-idle-fingers .ace_invisible {\\\n  color: #404040;\\\n}\\\n\\\n.ace-idle-fingers .ace_keyword, .ace-idle-fingers .ace_meta {\\\n  color:#CC7833;\\\n}\\\n\\\n.ace-idle-fingers .ace_constant, .ace-idle-fingers .ace_constant.ace_other {\\\n  color:#6C99BB;\\\n}\\\n\\\n.ace-idle-fingers .ace_constant.ace_character,  {\\\n  color:#6C99BB;\\\n}\\\n\\\n.ace-idle-fingers .ace_constant.ace_character.ace_escape,  {\\\n  color:#6C99BB;\\\n}\\\n\\\n.ace-idle-fingers .ace_invalid {\\\n  color:#FFFFFF;\\\nbackground-color:#FF0000;\\\n}\\\n\\\n.ace-idle-fingers .ace_support.ace_constant {\\\n  color:#6C99BB;\\\n}\\\n\\\n.ace-idle-fingers .ace_fold {\\\n    background-color: #CC7833;\\\n    border-color: #FFFFFF;\\\n}\\\n\\\n.ace-idle-fingers .ace_support.ace_function {\\\n  color:#B83426;\\\n}\\\n\\\n.ace-idle-fingers .ace_variable.ace_parameter {\\\n  font-style:italic;\\\n}\\\n\\\n.ace-idle-fingers .ace_string {\\\n  color:#A5C261;\\\n}\\\n\\\n.ace-idle-fingers .ace_string.ace_regexp {\\\n  color:#CCCC33;\\\n}\\\n\\\n.ace-idle-fingers .ace_comment {\\\n  font-style:italic;\\\ncolor:#BC9458;\\\n}\\\n\\\n.ace-idle-fingers .ace_meta.ace_tag {\\\n  color:#FFE5BB;\\\n}\\\n\\\n.ace-idle-fingers .ace_entity.ace_name {\\\n  color:#FFC66D;\\\n}\\\n\\\n.ace-idle-fingers .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\\\n\\\n.ace-idle-fingers .ace_collab.ace_user1 {\\\n  color:#323232;\\\nbackground-color:#FFF980;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/kr_theme.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-kr-theme\";\nexports.cssText = \"\\\n.ace-kr-theme .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-kr-theme .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-kr-theme .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-kr-theme .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-kr-theme .ace_scroller {\\\n  background-color: #0B0A09;\\\n}\\\n\\\n.ace-kr-theme .ace_text-layer {\\\n  cursor: text;\\\n  color: #FCFFE0;\\\n}\\\n\\\n.ace-kr-theme .ace_cursor {\\\n  border-left: 2px solid #FF9900;\\\n}\\\n\\\n.ace-kr-theme .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #FF9900;\\\n}\\\n\\\n.ace-kr-theme .ace_marker-layer .ace_selection {\\\n  background: rgba(170, 0, 255, 0.45);\\\n}\\\n\\\n.ace-kr-theme.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #0B0A09;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-kr-theme .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-kr-theme .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid rgba(255, 177, 111, 0.32);\\\n}\\\n\\\n.ace-kr-theme .ace_marker-layer .ace_active_line {\\\n  background: #38403D;\\\n}\\\n\\\n.ace-kr-theme .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid rgba(170, 0, 255, 0.45);\\\n}\\\n\\\n.ace-kr-theme .ace_invisible {\\\n  color: rgba(255, 177, 111, 0.32);\\\n}\\\n\\\n.ace-kr-theme .ace_keyword, .ace-kr-theme .ace_meta {\\\n  color:#949C8B;\\\n}\\\n\\\n.ace-kr-theme .ace_constant, .ace-kr-theme .ace_constant.ace_other {\\\n  color:rgba(210, 117, 24, 0.76);\\\n}\\\n\\\n.ace-kr-theme .ace_constant.ace_character,  {\\\n  color:rgba(210, 117, 24, 0.76);\\\n}\\\n\\\n.ace-kr-theme .ace_constant.ace_character.ace_escape,  {\\\n  color:rgba(210, 117, 24, 0.76);\\\n}\\\n\\\n.ace-kr-theme .ace_invalid {\\\n  color:#F8F8F8;\\\nbackground-color:#A41300;\\\n}\\\n\\\n.ace-kr-theme .ace_support {\\\n  color:#9FC28A;\\\n}\\\n\\\n.ace-kr-theme .ace_support.ace_constant {\\\n  color:#C27E66;\\\n}\\\n\\\n.ace-kr-theme .ace_fold {\\\n    background-color: #949C8B;\\\n    border-color: #FCFFE0;\\\n}\\\n\\\n.ace-kr-theme .ace_support.ace_function {\\\n  color:#85873A;\\\n}\\\n\\\n.ace-kr-theme .ace_storage {\\\n  color:#FFEE80;\\\n}\\\n\\\n.ace-kr-theme .ace_string.ace_regexp {\\\n  color:rgba(125, 255, 192, 0.65);\\\n}\\\n\\\n.ace-kr-theme .ace_comment {\\\n  font-style:italic;\\\ncolor:#706D5B;\\\n}\\\n\\\n.ace-kr-theme .ace_variable {\\\n  color:#D1A796;\\\n}\\\n\\\n.ace-kr-theme .ace_variable.ace_language {\\\n  color:#FF80E1;\\\n}\\\n\\\n.ace-kr-theme .ace_meta.ace_tag {\\\n  color:#BABD9C;\\\n}\\\n\\\n.ace-kr-theme .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\\\n\\\n.ace-kr-theme .ace_markup.ace_list {\\\n  background-color:#0F0040;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/merbivore.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-merbivore\";\nexports.cssText = \"\\\n.ace-merbivore .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-merbivore .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-merbivore .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-merbivore .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-merbivore .ace_scroller {\\\n  background-color: #161616;\\\n}\\\n\\\n.ace-merbivore .ace_text-layer {\\\n  cursor: text;\\\n  color: #E6E1DC;\\\n}\\\n\\\n.ace-merbivore .ace_cursor {\\\n  border-left: 2px solid #FFFFFF;\\\n}\\\n\\\n.ace-merbivore .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #FFFFFF;\\\n}\\\n\\\n.ace-merbivore .ace_marker-layer .ace_selection {\\\n  background: #454545;\\\n}\\\n\\\n.ace-merbivore.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #161616;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-merbivore .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-merbivore .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid #404040;\\\n}\\\n\\\n.ace-merbivore .ace_marker-layer .ace_active_line {\\\n  background: #333435;\\\n}\\\n\\\n.ace-merbivore .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid #454545;\\\n}\\\n\\\n.ace-merbivore .ace_invisible {\\\n  color: #404040;\\\n}\\\n\\\n.ace-merbivore .ace_keyword, .ace-merbivore .ace_meta {\\\n  color:#FC6F09;\\\n}\\\n\\\n.ace-merbivore .ace_constant, .ace-merbivore .ace_constant.ace_other {\\\n  color:#1EDAFB;\\\n}\\\n\\\n.ace-merbivore .ace_constant.ace_character,  {\\\n  color:#1EDAFB;\\\n}\\\n\\\n.ace-merbivore .ace_constant.ace_character.ace_escape,  {\\\n  color:#1EDAFB;\\\n}\\\n\\\n.ace-merbivore .ace_constant.ace_language {\\\n  color:#FDC251;\\\n}\\\n\\\n.ace-merbivore .ace_constant.ace_library {\\\n  color:#8DFF0A;\\\n}\\\n\\\n.ace-merbivore .ace_constant.ace_numeric {\\\n  color:#58C554;\\\n}\\\n\\\n.ace-merbivore .ace_invalid {\\\n  color:#FFFFFF;\\\nbackground-color:#990000;\\\n}\\\n\\\n.ace-merbivore .ace_support.ace_constant {\\\n  color:#8DFF0A;\\\n}\\\n\\\n.ace-merbivore .ace_fold {\\\n    background-color: #FC6F09;\\\n    border-color: #E6E1DC;\\\n}\\\n\\\n.ace-merbivore .ace_support.ace_function {\\\n  color:#FC6F09;\\\n}\\\n\\\n.ace-merbivore .ace_storage {\\\n  color:#FC6F09;\\\n}\\\n\\\n.ace-merbivore .ace_string {\\\n  color:#8DFF0A;\\\n}\\\n\\\n.ace-merbivore .ace_comment {\\\n  font-style:italic;\\\ncolor:#AD2EA4;\\\n}\\\n\\\n.ace-merbivore .ace_meta.ace_tag {\\\n  color:#FC6F09;\\\n}\\\n\\\n.ace-merbivore .ace_entity.ace_other.ace_attribute-name {\\\n  color:#FFFF89;\\\n}\\\n\\\n.ace-merbivore .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/merbivore_soft.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-merbivore-soft\";\nexports.cssText = \"\\\n.ace-merbivore-soft .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-merbivore-soft .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-merbivore-soft .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-merbivore-soft .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-merbivore-soft .ace_scroller {\\\n  background-color: #1C1C1C;\\\n}\\\n\\\n.ace-merbivore-soft .ace_text-layer {\\\n  cursor: text;\\\n  color: #E6E1DC;\\\n}\\\n\\\n.ace-merbivore-soft .ace_cursor {\\\n  border-left: 2px solid #FFFFFF;\\\n}\\\n\\\n.ace-merbivore-soft .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #FFFFFF;\\\n}\\\n\\\n.ace-merbivore-soft .ace_marker-layer .ace_selection {\\\n  background: #494949;\\\n}\\\n\\\n.ace-merbivore-soft.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #1C1C1C;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-merbivore-soft .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-merbivore-soft .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid #404040;\\\n}\\\n\\\n.ace-merbivore-soft .ace_marker-layer .ace_active_line {\\\n  background: #333435;\\\n}\\\n\\\n.ace-merbivore-soft .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid #494949;\\\n}\\\n\\\n.ace-merbivore-soft .ace_invisible {\\\n  color: #404040;\\\n}\\\n\\\n.ace-merbivore-soft .ace_keyword, .ace-merbivore-soft .ace_meta {\\\n  color:#FC803A;\\\n}\\\n\\\n.ace-merbivore-soft .ace_constant, .ace-merbivore-soft .ace_constant.ace_other {\\\n  color:#68C1D8;\\\n}\\\n\\\n.ace-merbivore-soft .ace_constant.ace_character,  {\\\n  color:#68C1D8;\\\n}\\\n\\\n.ace-merbivore-soft .ace_constant.ace_character.ace_escape,  {\\\n  color:#68C1D8;\\\n}\\\n\\\n.ace-merbivore-soft .ace_constant.ace_language {\\\n  color:#E1C582;\\\n}\\\n\\\n.ace-merbivore-soft .ace_constant.ace_library {\\\n  color:#8EC65F;\\\n}\\\n\\\n.ace-merbivore-soft .ace_constant.ace_numeric {\\\n  color:#7FC578;\\\n}\\\n\\\n.ace-merbivore-soft .ace_invalid {\\\n  color:#FFFFFF;\\\nbackground-color:#FE3838;\\\n}\\\n\\\n.ace-merbivore-soft .ace_invalid.ace_deprecated {\\\n  color:#FFFFFF;\\\nbackground-color:#FE3838;\\\n}\\\n\\\n.ace-merbivore-soft .ace_support.ace_constant {\\\n  color:#8EC65F;\\\n}\\\n\\\n.ace-merbivore-soft .ace_fold {\\\n    background-color: #FC803A;\\\n    border-color: #E6E1DC;\\\n}\\\n\\\n.ace-merbivore-soft .ace_storage {\\\n  color:#FC803A;\\\n}\\\n\\\n.ace-merbivore-soft .ace_string {\\\n  color:#8EC65F;\\\n}\\\n\\\n.ace-merbivore-soft .ace_comment {\\\n  font-style:italic;\\\ncolor:#AC4BB8;\\\n}\\\n\\\n.ace-merbivore-soft .ace_meta {\\\n  font-style:italic;\\\ncolor:#AC4BB8;\\\n}\\\n\\\n.ace-merbivore-soft .ace_meta.ace_tag {\\\n  color:#FC803A;\\\n}\\\n\\\n.ace-merbivore-soft .ace_entity.ace_other.ace_attribute-name {\\\n  color:#EAF1A3;\\\n}\\\n\\\n.ace-merbivore-soft .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/mono_industrial.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-mono-industrial\";\nexports.cssText = \"\\\n.ace-mono-industrial .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-mono-industrial .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-mono-industrial .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-mono-industrial .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-mono-industrial .ace_scroller {\\\n  background-color: #222C28;\\\n}\\\n\\\n.ace-mono-industrial .ace_text-layer {\\\n  cursor: text;\\\n  color: #FFFFFF;\\\n}\\\n\\\n.ace-mono-industrial .ace_cursor {\\\n  border-left: 2px solid #FFFFFF;\\\n}\\\n\\\n.ace-mono-industrial .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #FFFFFF;\\\n}\\\n\\\n.ace-mono-industrial .ace_marker-layer .ace_selection {\\\n  background: rgba(145, 153, 148, 0.40);\\\n}\\\n\\\n.ace-mono-industrial.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #222C28;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-mono-industrial .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-mono-industrial .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid rgba(102, 108, 104, 0.50);\\\n}\\\n\\\n.ace-mono-industrial .ace_marker-layer .ace_active_line {\\\n  background: rgba(12, 13, 12, 0.25);\\\n}\\\n\\\n.ace-mono-industrial .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid rgba(145, 153, 148, 0.40);\\\n}\\\n\\\n.ace-mono-industrial .ace_invisible {\\\n  color: rgba(102, 108, 104, 0.50);\\\n}\\\n\\\n.ace-mono-industrial .ace_keyword, .ace-mono-industrial .ace_meta {\\\n  color:#A39E64;\\\n}\\\n\\\n.ace-mono-industrial .ace_keyword.ace_operator {\\\n  color:#A8B3AB;\\\n}\\\n\\\n.ace-mono-industrial .ace_constant, .ace-mono-industrial .ace_constant.ace_other {\\\n  color:#E98800;\\\n}\\\n\\\n.ace-mono-industrial .ace_constant.ace_character,  {\\\n  color:#E98800;\\\n}\\\n\\\n.ace-mono-industrial .ace_constant.ace_character.ace_escape,  {\\\n  color:#E98800;\\\n}\\\n\\\n.ace-mono-industrial .ace_constant.ace_numeric {\\\n  color:#E98800;\\\n}\\\n\\\n.ace-mono-industrial .ace_invalid {\\\n  color:#FFFFFF;\\\nbackground-color:rgba(153, 0, 0, 0.68);\\\n}\\\n\\\n.ace-mono-industrial .ace_support.ace_constant {\\\n  color:#C87500;\\\n}\\\n\\\n.ace-mono-industrial .ace_fold {\\\n    background-color: #A8B3AB;\\\n    border-color: #FFFFFF;\\\n}\\\n\\\n.ace-mono-industrial .ace_support.ace_function {\\\n  color:#588E60;\\\n}\\\n\\\n.ace-mono-industrial .ace_storage {\\\n  color:#C23B00;\\\n}\\\n\\\n.ace-mono-industrial .ace_variable {\\\n  color:#A8B3AB;\\\n}\\\n\\\n.ace-mono-industrial .ace_variable.ace_parameter {\\\n  color:#648BD2;\\\n}\\\n\\\n.ace-mono-industrial .ace_comment {\\\n  color:#666C68;\\\nbackground-color:#151C19;\\\n}\\\n\\\n.ace-mono-industrial .ace_variable.ace_language {\\\n  color:#648BD2;\\\n}\\\n\\\n.ace-mono-industrial .ace_entity.ace_other.ace_attribute-name {\\\n  color:#909993;\\\n}\\\n\\\n.ace-mono-industrial .ace_entity.ace_name {\\\n  color:#5778B6;\\\n}\\\n\\\n.ace-mono-industrial .ace_entity.ace_name.ace_function {\\\n  color:#A8B3AB;\\\n}\\\n\\\n.ace-mono-industrial .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/monokai.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-monokai\";\nexports.cssText = \"\\\n.ace-monokai .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-monokai .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-monokai .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-monokai .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-monokai .ace_scroller {\\\n  background-color: #272822;\\\n}\\\n\\\n.ace-monokai .ace_text-layer {\\\n  cursor: text;\\\n  color: #F8F8F2;\\\n}\\\n\\\n.ace-monokai .ace_cursor {\\\n  border-left: 2px solid #F8F8F0;\\\n}\\\n\\\n.ace-monokai .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #F8F8F0;\\\n}\\\n\\\n.ace-monokai .ace_marker-layer .ace_selection {\\\n  background: #49483E;\\\n}\\\n\\\n.ace-monokai.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #272822;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-monokai .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-monokai .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid #49483E;\\\n}\\\n\\\n.ace-monokai .ace_marker-layer .ace_active_line {\\\n  background: #49483E;\\\n}\\\n\\\n.ace-monokai .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid #49483E;\\\n}\\\n\\\n.ace-monokai .ace_invisible {\\\n  color: #49483E;\\\n}\\\n\\\n.ace-monokai .ace_keyword, .ace-monokai .ace_meta {\\\n  color:#F92672;\\\n}\\\n\\\n.ace-monokai .ace_constant.ace_language {\\\n  color:#AE81FF;\\\n}\\\n\\\n.ace-monokai .ace_constant.ace_numeric {\\\n  color:#AE81FF;\\\n}\\\n\\\n.ace-monokai .ace_constant.ace_other {\\\n  color:#AE81FF;\\\n}\\\n\\\n.ace-monokai .ace_invalid {\\\n  color:#F8F8F0;\\\nbackground-color:#F92672;\\\n}\\\n\\\n.ace-monokai .ace_invalid.ace_deprecated {\\\n  color:#F8F8F0;\\\nbackground-color:#AE81FF;\\\n}\\\n\\\n.ace-monokai .ace_support.ace_constant {\\\n  color:#66D9EF;\\\n}\\\n\\\n.ace-monokai .ace_fold {\\\n    background-color: #A6E22E;\\\n    border-color: #F8F8F2;\\\n}\\\n\\\n.ace-monokai .ace_support.ace_function {\\\n  color:#66D9EF;\\\n}\\\n\\\n.ace-monokai .ace_storage {\\\n  color:#F92672;\\\n}\\\n\\\n.ace-monokai .ace_storage.ace_type,  .ace-monokai .ace_support.ace_type{\\\n  font-style:italic;\\\ncolor:#66D9EF;\\\n}\\\n\\\n.ace-monokai .ace_variable {\\\n  color:#A6E22E;\\\n}\\\n\\\n.ace-monokai .ace_variable.ace_parameter {\\\n  font-style:italic;\\\ncolor:#FD971F;\\\n}\\\n\\\n.ace-monokai .ace_string {\\\n  color:#E6DB74;\\\n}\\\n\\\n.ace-monokai .ace_comment {\\\n  color:#75715E;\\\n}\\\n\\\n.ace-monokai .ace_entity.ace_other.ace_attribute-name {\\\n  color:#A6E22E;\\\n}\\\n\\\n.ace-monokai .ace_entity.ace_name.ace_function {\\\n  color:#A6E22E;\\\n}\\\n\\\n.ace-monokai .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/pastel_on_dark.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-pastel-on-dark\";\nexports.cssText = \"\\\n.ace-pastel-on-dark .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-pastel-on-dark .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_scroller {\\\n  background-color: #2C2828;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_text-layer {\\\n  cursor: text;\\\n  color: #8F938F;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_cursor {\\\n  border-left: 2px solid #A7A7A7;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #A7A7A7;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_marker-layer .ace_selection {\\\n  background: rgba(221, 240, 255, 0.20);\\\n}\\\n\\\n.ace-pastel-on-dark.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #2C2828;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-pastel-on-dark .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid rgba(255, 255, 255, 0.25);\\\n}\\\n\\\n.ace-pastel-on-dark .ace_marker-layer .ace_active_line {\\\n  background: rgba(255, 255, 255, 0.031);\\\n}\\\n\\\n.ace-pastel-on-dark .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid rgba(221, 240, 255, 0.20);\\\n}\\\n\\\n.ace-pastel-on-dark .ace_invisible {\\\n  color: rgba(255, 255, 255, 0.25);\\\n}\\\n\\\n.ace-pastel-on-dark .ace_keyword, .ace-pastel-on-dark .ace_meta {\\\n  color:#757aD8;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_keyword.ace_operator {\\\n  color:#797878;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_constant, .ace-pastel-on-dark .ace_constant.ace_other {\\\n  color:#4FB7C5;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_constant.ace_character,  {\\\n  color:#4FB7C5;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_constant.ace_character.ace_escape,  {\\\n  color:#4FB7C5;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_constant.ace_language {\\\n  color:#DE8E30;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_constant.ace_numeric {\\\n  color:#CCCCCC;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_invalid {\\\n  color:#F8F8F8;\\\nbackground-color:rgba(86, 45, 86, 0.75);\\\n}\\\n\\\n.ace-pastel-on-dark .ace_invalid.ace_illegal {\\\n  color:#F8F8F8;\\\nbackground-color:rgba(86, 45, 86, 0.75);\\\n}\\\n\\\n.ace-pastel-on-dark .ace_invalid.ace_deprecated {\\\n  text-decoration:underline;\\\nfont-style:italic;\\\ncolor:#D2A8A1;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_fold {\\\n    background-color: #757aD8;\\\n    border-color: #8F938F;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_support.ace_function {\\\n  color:#AEB2F8;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_string {\\\n  color:#66A968;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_string.ace_regexp {\\\n  color:#E9C062;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_comment {\\\n  color:#A6C6FF;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_variable {\\\n  color:#BEBF55;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_variable.ace_language {\\\n  color:#C1C144;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_xml_pe {\\\n  color:#494949;\\\n}\\\n\\\n.ace-pastel-on-dark .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/solarized_dark.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-solarized-dark\";\nexports.cssText = \"\\\n.ace-solarized-dark .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-solarized-dark .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-solarized-dark .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-solarized-dark .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-solarized-dark .ace_scroller {\\\n  background-color: #002B36;\\\n}\\\n\\\n.ace-solarized-dark .ace_text-layer {\\\n  cursor: text;\\\n  color: #93A1A1;\\\n}\\\n\\\n.ace-solarized-dark .ace_cursor {\\\n  border-left: 2px solid #D30102;\\\n}\\\n\\\n.ace-solarized-dark .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #D30102;\\\n}\\\n\\\n.ace-solarized-dark .ace_marker-layer .ace_selection {\\\n  background: #073642;\\\n}\\\n\\\n.ace-solarized-dark.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #002B36;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-solarized-dark .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-solarized-dark .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid rgba(147, 161, 161, 0.50);\\\n}\\\n\\\n.ace-solarized-dark .ace_marker-layer .ace_active_line {\\\n  background: #073642;\\\n}\\\n\\\n.ace-solarized-dark .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid #073642;\\\n}\\\n\\\n.ace-solarized-dark .ace_invisible {\\\n  color: rgba(147, 161, 161, 0.50);\\\n}\\\n\\\n.ace-solarized-dark .ace_keyword, .ace-solarized-dark .ace_meta {\\\n  color:#859900;\\\n}\\\n\\\n.ace-solarized-dark .ace_constant.ace_language {\\\n  color:#B58900;\\\n}\\\n\\\n.ace-solarized-dark .ace_constant.ace_numeric {\\\n  color:#D33682;\\\n}\\\n\\\n.ace-solarized-dark .ace_constant.ace_other {\\\n  color:#CB4B16;\\\n}\\\n\\\n.ace-solarized-dark .ace_fold {\\\n    background-color: #268BD2;\\\n    border-color: #93A1A1;\\\n}\\\n\\\n.ace-solarized-dark .ace_support.ace_function {\\\n  color:#268BD2;\\\n}\\\n\\\n.ace-solarized-dark .ace_storage {\\\n  color:#93A1A1;\\\n}\\\n\\\n.ace-solarized-dark .ace_variable {\\\n  color:#268BD2;\\\n}\\\n\\\n.ace-solarized-dark .ace_string {\\\n  color:#2AA198;\\\n}\\\n\\\n.ace-solarized-dark .ace_string.ace_regexp {\\\n  color:#D30102;\\\n}\\\n\\\n.ace-solarized-dark .ace_comment {\\\n  font-style:italic;\\\ncolor:#657B83;\\\n}\\\n\\\n.ace-solarized-dark .ace_variable.ace_language {\\\n  color:#268BD2;\\\n}\\\n\\\n.ace-solarized-dark .ace_entity.ace_other.ace_attribute-name {\\\n  color:#93A1A1;\\\n}\\\n\\\n.ace-solarized-dark .ace_entity.ace_name.ace_function {\\\n  color:#268BD2;\\\n}\\\n\\\n.ace-solarized-dark .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/solarized_light.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = false;\nexports.cssClass = \"ace-solarized-light\";\nexports.cssText = \"\\\n.ace-solarized-light .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-solarized-light .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-solarized-light .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-solarized-light .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-solarized-light .ace_scroller {\\\n  background-color: #FDF6E3;\\\n}\\\n\\\n.ace-solarized-light .ace_text-layer {\\\n  cursor: text;\\\n  color: #586E75;\\\n}\\\n\\\n.ace-solarized-light .ace_cursor {\\\n  border-left: 2px solid #000000;\\\n}\\\n\\\n.ace-solarized-light .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #000000;\\\n}\\\n\\\n.ace-solarized-light .ace_marker-layer .ace_selection {\\\n  background: #073642;\\\n}\\\n\\\n.ace-solarized-light.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #FDF6E3;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-solarized-light .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-solarized-light .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid rgba(147, 161, 161, 0.50);\\\n}\\\n\\\n.ace-solarized-light .ace_marker-layer .ace_active_line {\\\n  background: #EEE8D5;\\\n}\\\n\\\n.ace-solarized-light .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid #073642;\\\n}\\\n\\\n.ace-solarized-light .ace_invisible {\\\n  color: rgba(147, 161, 161, 0.50);\\\n}\\\n\\\n.ace-solarized-light .ace_keyword, .ace-solarized-light .ace_meta {\\\n  color:#859900;\\\n}\\\n\\\n.ace-solarized-light .ace_constant.ace_language {\\\n  color:#B58900;\\\n}\\\n\\\n.ace-solarized-light .ace_constant.ace_numeric {\\\n  color:#D33682;\\\n}\\\n\\\n.ace-solarized-light .ace_constant.ace_other {\\\n  color:#CB4B16;\\\n}\\\n\\\n.ace-solarized-light .ace_fold {\\\n    background-color: #268BD2;\\\n    border-color: #586E75;\\\n}\\\n\\\n.ace-solarized-light .ace_support.ace_function {\\\n  color:#268BD2;\\\n}\\\n\\\n.ace-solarized-light .ace_storage {\\\n  color:#073642;\\\n}\\\n\\\n.ace-solarized-light .ace_variable {\\\n  color:#268BD2;\\\n}\\\n\\\n.ace-solarized-light .ace_string {\\\n  color:#2AA198;\\\n}\\\n\\\n.ace-solarized-light .ace_string.ace_regexp {\\\n  color:#D30102;\\\n}\\\n\\\n.ace-solarized-light .ace_comment {\\\n  color:#93A1A1;\\\n}\\\n\\\n.ace-solarized-light .ace_variable.ace_language {\\\n  color:#268BD2;\\\n}\\\n\\\n.ace-solarized-light .ace_entity.ace_other.ace_attribute-name {\\\n  color:#93A1A1;\\\n}\\\n\\\n.ace-solarized-light .ace_entity.ace_name.ace_function {\\\n  color:#268BD2;\\\n}\\\n\\\n.ace-solarized-light .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/textmate.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nexports.isDark = false;\nexports.cssClass = \"ace-tm\";\nexports.cssText = \".ace-tm .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-tm .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-tm .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-tm .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-tm .ace_fold {\\\n    background-color: #6B72E6;\\\n}\\\n\\\n.ace-tm .ace_text-layer {\\\n  cursor: text;\\\n}\\\n\\\n.ace-tm .ace_cursor {\\\n  border-left: 2px solid black;\\\n}\\\n\\\n.ace-tm .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid black;\\\n}\\\n        \\\n.ace-tm .ace_line .ace_invisible {\\\n  color: rgb(191, 191, 191);\\\n}\\\n\\\n.ace-tm .ace_line .ace_storage,\\\n.ace-tm .ace_line .ace_keyword {\\\n  color: blue;\\\n}\\\n\\\n.ace-tm .ace_line .ace_constant {\\\n  color: rgb(197, 6, 11);\\\n}\\\n\\\n.ace-tm .ace_line .ace_constant.ace_buildin {\\\n  color: rgb(88, 72, 246);\\\n}\\\n\\\n.ace-tm .ace_line .ace_constant.ace_language {\\\n  color: rgb(88, 92, 246);\\\n}\\\n\\\n.ace-tm .ace_line .ace_constant.ace_library {\\\n  color: rgb(6, 150, 14);\\\n}\\\n\\\n.ace-tm .ace_line .ace_invalid {\\\n  background-color: rgb(153, 0, 0);\\\n  color: white;\\\n}\\\n\\\n.ace-tm .ace_line .ace_support.ace_function {\\\n  color: rgb(60, 76, 114);\\\n}\\\n\\\n.ace-tm .ace_line .ace_support.ace_constant {\\\n  color: rgb(6, 150, 14);\\\n}\\\n\\\n.ace-tm .ace_line .ace_support.ace_type,\\\n.ace-tm .ace_line .ace_support.ace_class {\\\n  color: rgb(109, 121, 222);\\\n}\\\n\\\n.ace-tm .ace_line .ace_keyword.ace_operator {\\\n  color: rgb(104, 118, 135);\\\n}\\\n\\\n.ace-tm .ace_line .ace_string {\\\n  color: rgb(3, 106, 7);\\\n}\\\n\\\n.ace-tm .ace_line .ace_comment {\\\n  color: rgb(76, 136, 107);\\\n}\\\n\\\n.ace-tm .ace_line .ace_comment.ace_doc {\\\n  color: rgb(0, 102, 255);\\\n}\\\n\\\n.ace-tm .ace_line .ace_comment.ace_doc.ace_tag {\\\n  color: rgb(128, 159, 191);\\\n}\\\n\\\n.ace-tm .ace_line .ace_constant.ace_numeric {\\\n  color: rgb(0, 0, 205);\\\n}\\\n\\\n.ace-tm .ace_line .ace_variable {\\\n  color: rgb(49, 132, 149);\\\n}\\\n\\\n.ace-tm .ace_line .ace_xml_pe {\\\n  color: rgb(104, 104, 91);\\\n}\\\n\\\n.ace-tm .ace_entity.ace_name.ace_function {\\\n  color: #0000A2;\\\n}\\\n\\\n.ace-tm .ace_markup.ace_markupine {\\\n    text-decoration:underline;\\\n}\\\n\\\n.ace-tm .ace_markup.ace_heading {\\\n  color: rgb(12, 7, 255);\\\n}\\\n\\\n.ace-tm .ace_markup.ace_list {\\\n  color:rgb(185, 6, 144);\\\n}\\\n\\\n.ace-tm .ace_marker-layer .ace_selection {\\\n  background: rgb(181, 213, 255);\\\n}\\\n.ace-tm.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px white;\\\n  border-radius: 2px;\\\n}\\\n.ace-tm .ace_marker-layer .ace_step {\\\n  background: rgb(252, 255, 0);\\\n}\\\n\\\n.ace-tm .ace_marker-layer .ace_stack {\\\n  background: rgb(164, 229, 101);\\\n}\\\n\\\n.ace-tm .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid rgb(192, 192, 192);\\\n}\\\n\\\n.ace-tm .ace_marker-layer .ace_active_line {\\\n  background: rgba(0, 0, 0, 0.07);\\\n}\\\n\\\n.ace-tm .ace_marker-layer .ace_selected_word {\\\n  background: rgb(250, 250, 255);\\\n  border: 1px solid rgb(200, 200, 250);\\\n}\\\n\\\n.ace-tm .ace_meta.ace_tag {\\\n  color:rgb(28, 2, 255);\\\n}\\\n\\\n.ace-tm .ace_string.ace_regex {\\\n  color: rgb(255, 0, 0)\\\n}\";\n\nvar dom = require(\"../lib/dom\");\ndom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/tomorrow.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = false;\nexports.cssClass = \"ace-tomorrow\";\nexports.cssText = \"\\\n.ace-tomorrow .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-tomorrow .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-tomorrow .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-tomorrow .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-tomorrow .ace_scroller {\\\n  background-color: #FFFFFF;\\\n}\\\n\\\n.ace-tomorrow .ace_text-layer {\\\n  cursor: text;\\\n  color: #4D4D4C;\\\n}\\\n\\\n.ace-tomorrow .ace_cursor {\\\n  border-left: 2px solid #AEAFAD;\\\n}\\\n\\\n.ace-tomorrow .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #AEAFAD;\\\n}\\\n\\\n.ace-tomorrow .ace_marker-layer .ace_selection {\\\n  background: #D6D6D6;\\\n}\\\n\\\n.ace-tomorrow.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #FFFFFF;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-tomorrow .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-tomorrow .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid #D1D1D1;\\\n}\\\n\\\n.ace-tomorrow .ace_marker-layer .ace_active_line {\\\n  background: #EFEFEF;\\\n}\\\n\\\n.ace-tomorrow .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid #D6D6D6;\\\n}\\\n\\\n.ace-tomorrow .ace_invisible {\\\n  color: #D1D1D1;\\\n}\\\n\\\n.ace-tomorrow .ace_keyword, .ace-tomorrow .ace_meta {\\\n  color:#8959A8;\\\n}\\\n\\\n.ace-tomorrow .ace_keyword.ace_operator {\\\n  color:#3E999F;\\\n}\\\n\\\n.ace-tomorrow .ace_constant.ace_language {\\\n  color:#F5871F;\\\n}\\\n\\\n.ace-tomorrow .ace_constant.ace_numeric {\\\n  color:#F5871F;\\\n}\\\n\\\n.ace-tomorrow .ace_constant.ace_other {\\\n  color:#666969;\\\n}\\\n\\\n.ace-tomorrow .ace_invalid {\\\n  color:#FFFFFF;\\\nbackground-color:#C82829;\\\n}\\\n\\\n.ace-tomorrow .ace_invalid.ace_deprecated {\\\n  color:#FFFFFF;\\\nbackground-color:#8959A8;\\\n}\\\n\\\n.ace-tomorrow .ace_support.ace_constant {\\\n  color:#F5871F;\\\n}\\\n\\\n.ace-tomorrow .ace_fold {\\\n    background-color: #4271AE;\\\n    border-color: #4D4D4C;\\\n}\\\n\\\n.ace-tomorrow .ace_support.ace_function {\\\n  color:#4271AE;\\\n}\\\n\\\n.ace-tomorrow .ace_storage {\\\n  color:#8959A8;\\\n}\\\n\\\n.ace-tomorrow .ace_storage.ace_type,  .ace-tomorrow .ace_support.ace_type{\\\n  color:#8959A8;\\\n}\\\n\\\n.ace-tomorrow .ace_variable {\\\n  color:#4271AE;\\\n}\\\n\\\n.ace-tomorrow .ace_variable.ace_parameter {\\\n  color:#F5871F;\\\n}\\\n\\\n.ace-tomorrow .ace_string {\\\n  color:#718C00;\\\n}\\\n\\\n.ace-tomorrow .ace_string.ace_regexp {\\\n  color:#C82829;\\\n}\\\n\\\n.ace-tomorrow .ace_comment {\\\n  color:#8E908C;\\\n}\\\n\\\n.ace-tomorrow .ace_variable {\\\n  color:#C82829;\\\n}\\\n\\\n.ace-tomorrow .ace_meta.ace_tag {\\\n  color:#C82829;\\\n}\\\n\\\n.ace-tomorrow .ace_entity.ace_other.ace_attribute-name {\\\n  color:#C82829;\\\n}\\\n\\\n.ace-tomorrow .ace_entity.ace_name.ace_function {\\\n  color:#4271AE;\\\n}\\\n\\\n.ace-tomorrow .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\\\n\\\n.ace-tomorrow .ace_markup.ace_heading {\\\n  color:#718C00;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/tomorrow_night.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-tomorrow-night\";\nexports.cssText = \"\\\n.ace-tomorrow-night .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-tomorrow-night .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-tomorrow-night .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-tomorrow-night .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-tomorrow-night .ace_scroller {\\\n  background-color: #1D1F21;\\\n}\\\n\\\n.ace-tomorrow-night .ace_text-layer {\\\n  cursor: text;\\\n  color: #C5C8C6;\\\n}\\\n\\\n.ace-tomorrow-night .ace_cursor {\\\n  border-left: 2px solid #AEAFAD;\\\n}\\\n\\\n.ace-tomorrow-night .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #AEAFAD;\\\n}\\\n\\\n.ace-tomorrow-night .ace_marker-layer .ace_selection {\\\n  background: #373B41;\\\n}\\\n\\\n.ace-tomorrow-night.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #1D1F21;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-tomorrow-night .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-tomorrow-night .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid #4B4E55;\\\n}\\\n\\\n.ace-tomorrow-night .ace_marker-layer .ace_active_line {\\\n  background: #282A2E;\\\n}\\\n\\\n.ace-tomorrow-night .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid #373B41;\\\n}\\\n\\\n.ace-tomorrow-night .ace_invisible {\\\n  color: #4B4E55;\\\n}\\\n\\\n.ace-tomorrow-night .ace_keyword, .ace-tomorrow-night .ace_meta {\\\n  color:#B294BB;\\\n}\\\n\\\n.ace-tomorrow-night .ace_keyword.ace_operator {\\\n  color:#8ABEB7;\\\n}\\\n\\\n.ace-tomorrow-night .ace_constant.ace_language {\\\n  color:#DE935F;\\\n}\\\n\\\n.ace-tomorrow-night .ace_constant.ace_numeric {\\\n  color:#DE935F;\\\n}\\\n\\\n.ace-tomorrow-night .ace_constant.ace_other {\\\n  color:#CED1CF;\\\n}\\\n\\\n.ace-tomorrow-night .ace_invalid {\\\n  color:#CED2CF;\\\nbackground-color:#DF5F5F;\\\n}\\\n\\\n.ace-tomorrow-night .ace_invalid.ace_deprecated {\\\n  color:#CED2CF;\\\nbackground-color:#B798BF;\\\n}\\\n\\\n.ace-tomorrow-night .ace_support.ace_constant {\\\n  color:#DE935F;\\\n}\\\n\\\n.ace-tomorrow-night .ace_fold {\\\n    background-color: #81A2BE;\\\n    border-color: #C5C8C6;\\\n}\\\n\\\n.ace-tomorrow-night .ace_support.ace_function {\\\n  color:#81A2BE;\\\n}\\\n\\\n.ace-tomorrow-night .ace_storage {\\\n  color:#B294BB;\\\n}\\\n\\\n.ace-tomorrow-night .ace_storage.ace_type,  .ace-tomorrow-night .ace_support.ace_type{\\\n  color:#B294BB;\\\n}\\\n\\\n.ace-tomorrow-night .ace_variable {\\\n  color:#81A2BE;\\\n}\\\n\\\n.ace-tomorrow-night .ace_variable.ace_parameter {\\\n  color:#DE935F;\\\n}\\\n\\\n.ace-tomorrow-night .ace_string {\\\n  color:#B5BD68;\\\n}\\\n\\\n.ace-tomorrow-night .ace_string.ace_regexp {\\\n  color:#CC6666;\\\n}\\\n\\\n.ace-tomorrow-night .ace_comment {\\\n  color:#969896;\\\n}\\\n\\\n.ace-tomorrow-night .ace_variable {\\\n  color:#CC6666;\\\n}\\\n\\\n.ace-tomorrow-night .ace_meta.ace_tag {\\\n  color:#CC6666;\\\n}\\\n\\\n.ace-tomorrow-night .ace_entity.ace_other.ace_attribute-name {\\\n  color:#CC6666;\\\n}\\\n\\\n.ace-tomorrow-night .ace_entity.ace_name.ace_function {\\\n  color:#81A2BE;\\\n}\\\n\\\n.ace-tomorrow-night .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\\\n\\\n.ace-tomorrow-night .ace_markup.ace_heading {\\\n  color:#B5BD68;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/tomorrow_night_blue.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-tomorrow-night-blue\";\nexports.cssText = \"\\\n.ace-tomorrow-night-blue .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_scroller {\\\n  background-color: #002451;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_text-layer {\\\n  cursor: text;\\\n  color: #FFFFFF;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_cursor {\\\n  border-left: 2px solid #FFFFFF;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #FFFFFF;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_marker-layer .ace_selection {\\\n  background: #003F8E;\\\n}\\\n\\\n.ace-tomorrow-night-blue.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #002451;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid #404F7D;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_marker-layer .ace_active_line {\\\n  background: #00346E;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid #003F8E;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_invisible {\\\n  color: #404F7D;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_keyword, .ace-tomorrow-night-blue .ace_meta {\\\n  color:#EBBBFF;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_keyword.ace_operator {\\\n  color:#99FFFF;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_constant.ace_language {\\\n  color:#FFC58F;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_constant.ace_numeric {\\\n  color:#FFC58F;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_constant.ace_other {\\\n  color:#FFFFFF;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_invalid {\\\n  color:#FFFFFF;\\\nbackground-color:#F99DA5;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_invalid.ace_deprecated {\\\n  color:#FFFFFF;\\\nbackground-color:#EBBBFF;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_support.ace_constant {\\\n  color:#FFC58F;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_fold {\\\n    background-color: #BBDAFF;\\\n    border-color: #FFFFFF;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_support.ace_function {\\\n  color:#BBDAFF;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_storage {\\\n  color:#EBBBFF;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_storage.ace_type,  .ace-tomorrow-night-blue .ace_support.ace_type{\\\n  color:#EBBBFF;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_variable {\\\n  color:#BBDAFF;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_variable.ace_parameter {\\\n  color:#FFC58F;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_string {\\\n  color:#D1F1A9;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_string.ace_regexp {\\\n  color:#FF9DA4;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_comment {\\\n  color:#7285B7;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_variable {\\\n  color:#FF9DA4;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_meta.ace_tag {\\\n  color:#FF9DA4;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_entity.ace_other.ace_attribute-name {\\\n  color:#FF9DA4;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_entity.ace_name.ace_function {\\\n  color:#BBDAFF;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\\\n\\\n.ace-tomorrow-night-blue .ace_markup.ace_heading {\\\n  color:#D1F1A9;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/tomorrow_night_bright.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-tomorrow-night-bright\";\nexports.cssText = \"\\\n.ace-tomorrow-night-bright .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_scroller {\\\n  background-color: #000000;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_text-layer {\\\n  cursor: text;\\\n  color: #DEDEDE;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_cursor {\\\n  border-left: 2px solid #9F9F9F;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #9F9F9F;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_marker-layer .ace_selection {\\\n  background: #424242;\\\n}\\\n\\\n.ace-tomorrow-night-bright.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #000000;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid #343434;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_marker-layer .ace_active_line {\\\n  background: #2A2A2A;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid #424242;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_invisible {\\\n  color: #343434;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_keyword, .ace-tomorrow-night-bright .ace_meta {\\\n  color:#C397D8;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_keyword.ace_operator {\\\n  color:#70C0B1;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_constant.ace_language {\\\n  color:#E78C45;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_constant.ace_numeric {\\\n  color:#E78C45;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_constant.ace_other {\\\n  color:#EEEEEE;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_invalid {\\\n  color:#CED2CF;\\\nbackground-color:#DF5F5F;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_invalid.ace_deprecated {\\\n  color:#CED2CF;\\\nbackground-color:#B798BF;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_support.ace_constant {\\\n  color:#E78C45;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_fold {\\\n    background-color: #7AA6DA;\\\n    border-color: #DEDEDE;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_support.ace_function {\\\n  color:#7AA6DA;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_storage {\\\n  color:#C397D8;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_storage.ace_type,  .ace-tomorrow-night-bright .ace_support.ace_type{\\\n  color:#C397D8;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_variable {\\\n  color:#7AA6DA;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_variable.ace_parameter {\\\n  color:#E78C45;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_string {\\\n  color:#B9CA4A;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_string.ace_regexp {\\\n  color:#D54E53;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_comment {\\\n  color:#969896;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_variable {\\\n  color:#D54E53;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_meta.ace_tag {\\\n  color:#D54E53;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_entity.ace_other.ace_attribute-name {\\\n  color:#D54E53;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_entity.ace_name.ace_function {\\\n  color:#7AA6DA;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\\\n\\\n.ace-tomorrow-night-bright .ace_markup.ace_heading {\\\n  color:#B9CA4A;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/tomorrow_night_eighties.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-tomorrow-night-eighties\";\nexports.cssText = \"\\\n.ace-tomorrow-night-eighties .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_scroller {\\\n  background-color: #2D2D2D;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_text-layer {\\\n  cursor: text;\\\n  color: #CCCCCC;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_cursor {\\\n  border-left: 2px solid #CCCCCC;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #CCCCCC;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_marker-layer .ace_selection {\\\n  background: #515151;\\\n}\\\n\\\n.ace-tomorrow-night-eighties.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #2D2D2D;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid #6A6A6A;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_marker-layer .ace_active_line {\\\n  background: #393939;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid #515151;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_invisible {\\\n  color: #6A6A6A;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_keyword, .ace-tomorrow-night-eighties .ace_meta {\\\n  color:#CC99CC;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_keyword.ace_operator {\\\n  color:#66CCCC;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_constant.ace_language {\\\n  color:#F99157;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_constant.ace_numeric {\\\n  color:#F99157;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_constant.ace_other {\\\n  color:#CCCCCC;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_invalid {\\\n  color:#CDCDCD;\\\nbackground-color:#F2777A;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_invalid.ace_deprecated {\\\n  color:#CDCDCD;\\\nbackground-color:#CC99CC;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_support.ace_constant {\\\n  color:#F99157;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_fold {\\\n    background-color: #6699CC;\\\n    border-color: #CCCCCC;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_support.ace_function {\\\n  color:#6699CC;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_storage {\\\n  color:#CC99CC;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_storage.ace_type,  .ace-tomorrow-night-eighties .ace_support.ace_type{\\\n  color:#CC99CC;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_variable {\\\n  color:#6699CC;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_variable.ace_parameter {\\\n  color:#F99157;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_string {\\\n  color:#99CC99;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_comment {\\\n  color:#999999;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_variable {\\\n  color:#F2777A;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_meta.ace_tag {\\\n  color:#F2777A;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_entity.ace_other.ace_attribute-name {\\\n  color:#F2777A;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_entity.ace_name.ace_function {\\\n  color:#6699CC;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\\\n\\\n.ace-tomorrow-night-eighties .ace_markup.ace_heading {\\\n  color:#99CC99;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/twilight.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-twilight\";\nexports.cssText = \"\\\n.ace-twilight .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-twilight .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-twilight .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-twilight .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-twilight .ace_scroller {\\\n  background-color: #141414;\\\n}\\\n\\\n.ace-twilight .ace_text-layer {\\\n  cursor: text;\\\n  color: #F8F8F8;\\\n}\\\n\\\n.ace-twilight .ace_cursor {\\\n  border-left: 2px solid #A7A7A7;\\\n}\\\n\\\n.ace-twilight .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #A7A7A7;\\\n}\\\n\\\n.ace-twilight .ace_marker-layer .ace_selection {\\\n  background: rgba(221, 240, 255, 0.20);\\\n}\\\n\\\n.ace-twilight.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #141414;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-twilight .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-twilight .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid rgba(255, 255, 255, 0.25);\\\n}\\\n\\\n.ace-twilight .ace_marker-layer .ace_active_line {\\\n  background: rgba(255, 255, 255, 0.031);\\\n}\\\n\\\n.ace-twilight .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid rgba(221, 240, 255, 0.20);\\\n}\\\n\\\n.ace-twilight .ace_invisible {\\\n  color: rgba(255, 255, 255, 0.25);\\\n}\\\n\\\n.ace-twilight .ace_keyword, .ace-twilight .ace_meta {\\\n  color:#CDA869;\\\n}\\\n\\\n.ace-twilight .ace_constant, .ace-twilight .ace_constant.ace_other {\\\n  color:#CF6A4C;\\\n}\\\n\\\n.ace-twilight .ace_constant.ace_character,  {\\\n  color:#CF6A4C;\\\n}\\\n\\\n.ace-twilight .ace_constant.ace_character.ace_escape,  {\\\n  color:#CF6A4C;\\\n}\\\n\\\n.ace-twilight .ace_invalid.ace_illegal {\\\n  color:#F8F8F8;\\\nbackground-color:rgba(86, 45, 86, 0.75);\\\n}\\\n\\\n.ace-twilight .ace_invalid.ace_deprecated {\\\n  text-decoration:underline;\\\nfont-style:italic;\\\ncolor:#D2A8A1;\\\n}\\\n\\\n.ace-twilight .ace_support {\\\n  color:#9B859D;\\\n}\\\n\\\n.ace-twilight .ace_support.ace_constant {\\\n  color:#CF6A4C;\\\n}\\\n\\\n.ace-twilight .ace_fold {\\\n    background-color: #AC885B;\\\n    border-color: #F8F8F8;\\\n}\\\n\\\n.ace-twilight .ace_support.ace_function {\\\n  color:#DAD085;\\\n}\\\n\\\n.ace-twilight .ace_storage {\\\n  color:#F9EE98;\\\n}\\\n\\\n.ace-twilight .ace_variable {\\\n  color:#AC885B;\\\n}\\\n\\\n.ace-twilight .ace_string {\\\n  color:#8F9D6A;\\\n}\\\n\\\n.ace-twilight .ace_string.ace_regexp {\\\n  color:#E9C062;\\\n}\\\n\\\n.ace-twilight .ace_comment {\\\n  font-style:italic;\\\ncolor:#5F5A60;\\\n}\\\n\\\n.ace-twilight .ace_variable {\\\n  color:#7587A6;\\\n}\\\n\\\n.ace-twilight .ace_xml_pe {\\\n  color:#494949;\\\n}\\\n\\\n.ace-twilight .ace_meta.ace_tag {\\\n  color:#AC885B;\\\n}\\\n\\\n.ace-twilight .ace_entity.ace_name.ace_function {\\\n  color:#AC885B;\\\n}\\\n\\\n.ace-twilight .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\\\n\\\n.ace-twilight .ace_markup.ace_heading {\\\n  color:#CF6A4C;\\\n}\\\n\\\n.ace-twilight .ace_markup.ace_list {\\\n  color:#F9EE98;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/theme/vibrant_ink.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\nexports.isDark = true;\nexports.cssClass = \"ace-vibrant-ink\";\nexports.cssText = \"\\\n.ace-vibrant-ink .ace_editor {\\\n  border: 2px solid rgb(159, 159, 159);\\\n}\\\n\\\n.ace-vibrant-ink .ace_editor.ace_focus {\\\n  border: 2px solid #327fbd;\\\n}\\\n\\\n.ace-vibrant-ink .ace_gutter {\\\n  background: #e8e8e8;\\\n  color: #333;\\\n}\\\n\\\n.ace-vibrant-ink .ace_print_margin {\\\n  width: 1px;\\\n  background: #e8e8e8;\\\n}\\\n\\\n.ace-vibrant-ink .ace_scroller {\\\n  background-color: #0F0F0F;\\\n}\\\n\\\n.ace-vibrant-ink .ace_text-layer {\\\n  cursor: text;\\\n  color: #FFFFFF;\\\n}\\\n\\\n.ace-vibrant-ink .ace_cursor {\\\n  border-left: 2px solid #FFFFFF;\\\n}\\\n\\\n.ace-vibrant-ink .ace_cursor.ace_overwrite {\\\n  border-left: 0px;\\\n  border-bottom: 1px solid #FFFFFF;\\\n}\\\n\\\n.ace-vibrant-ink .ace_marker-layer .ace_selection {\\\n  background: #6699CC;\\\n}\\\n\\\n.ace-vibrant-ink.multiselect .ace_selection.start {\\\n  box-shadow: 0 0 3px 0px #0F0F0F;\\\n  border-radius: 2px;\\\n}\\\n\\\n.ace-vibrant-ink .ace_marker-layer .ace_step {\\\n  background: rgb(198, 219, 174);\\\n}\\\n\\\n.ace-vibrant-ink .ace_marker-layer .ace_bracket {\\\n  margin: -1px 0 0 -1px;\\\n  border: 1px solid #404040;\\\n}\\\n\\\n.ace-vibrant-ink .ace_marker-layer .ace_active_line {\\\n  background: #333333;\\\n}\\\n\\\n.ace-vibrant-ink .ace_marker-layer .ace_selected_word {\\\n  border: 1px solid #6699CC;\\\n}\\\n\\\n.ace-vibrant-ink .ace_invisible {\\\n  color: #404040;\\\n}\\\n\\\n.ace-vibrant-ink .ace_keyword, .ace-vibrant-ink .ace_meta {\\\n  color:#FF6600;\\\n}\\\n\\\n.ace-vibrant-ink .ace_constant, .ace-vibrant-ink .ace_constant.ace_other {\\\n  color:#339999;\\\n}\\\n\\\n.ace-vibrant-ink .ace_constant.ace_character,  {\\\n  color:#339999;\\\n}\\\n\\\n.ace-vibrant-ink .ace_constant.ace_character.ace_escape,  {\\\n  color:#339999;\\\n}\\\n\\\n.ace-vibrant-ink .ace_constant.ace_numeric {\\\n  color:#99CC99;\\\n}\\\n\\\n.ace-vibrant-ink .ace_invalid {\\\n  color:#CCFF33;\\\nbackground-color:#000000;\\\n}\\\n\\\n.ace-vibrant-ink .ace_invalid.ace_deprecated {\\\n  color:#CCFF33;\\\nbackground-color:#000000;\\\n}\\\n\\\n.ace-vibrant-ink .ace_fold {\\\n    background-color: #FFCC00;\\\n    border-color: #FFFFFF;\\\n}\\\n\\\n.ace-vibrant-ink .ace_support.ace_function {\\\n  color:#FFCC00;\\\n}\\\n\\\n.ace-vibrant-ink .ace_variable {\\\n  color:#FFCC00;\\\n}\\\n\\\n.ace-vibrant-ink .ace_variable.ace_parameter {\\\n  font-style:italic;\\\n}\\\n\\\n.ace-vibrant-ink .ace_string {\\\n  color:#66FF00;\\\n}\\\n\\\n.ace-vibrant-ink .ace_string.ace_regexp {\\\n  color:#44B4CC;\\\n}\\\n\\\n.ace-vibrant-ink .ace_comment {\\\n  color:#9933CC;\\\n}\\\n\\\n.ace-vibrant-ink .ace_entity.ace_other.ace_attribute-name {\\\n  font-style:italic;\\\ncolor:#99CC99;\\\n}\\\n\\\n.ace-vibrant-ink .ace_entity.ace_name.ace_function {\\\n  color:#FFCC00;\\\n}\\\n\\\n.ace-vibrant-ink .ace_markup.ace_underline {\\\n    text-decoration:underline;\\\n}\";\n\n    var dom = require(\"../lib/dom\");\n    dom.importCssString(exports.cssText, exports.cssClass);\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/token_iterator.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar TokenIterator = function(session, initialRow, initialColumn) {\n    this.$session = session;\n    this.$row = initialRow;\n    this.$rowTokens = session.getTokens(initialRow, initialRow)[0].tokens;\n\n    var token = session.getTokenAt(initialRow, initialColumn);\n    this.$tokenIndex = token ? token.index : -1;\n};\n\n(function() {\n    \n    this.stepBackward = function() {\n        this.$tokenIndex -= 1;\n        \n        while (this.$tokenIndex < 0) {\n            this.$row -= 1;\n            if (this.$row < 0) {\n                this.$row = 0;\n                return null;\n            }\n                \n            this.$rowTokens = this.$session.getTokens(this.$row, this.$row)[0].tokens;\n            this.$tokenIndex = this.$rowTokens.length - 1;\n        }\n            \n        return this.$rowTokens[this.$tokenIndex];\n    };\n    \n    this.stepForward = function() {\n        var rowCount = this.$session.getLength();\n        this.$tokenIndex += 1;\n        \n        while (this.$tokenIndex >= this.$rowTokens.length) {\n            this.$row += 1;\n            if (this.$row >= rowCount) {\n                this.$row = rowCount - 1;\n                return null;\n            }\n\n            this.$rowTokens = this.$session.getTokens(this.$row, this.$row)[0].tokens;\n            this.$tokenIndex = 0;\n        }\n            \n        return this.$rowTokens[this.$tokenIndex];\n    };\n    \n    this.getCurrentToken = function () {\n        return this.$rowTokens[this.$tokenIndex];\n    };\n    \n    this.getCurrentTokenRow = function () {\n        return this.$row;\n    };\n    \n    this.getCurrentTokenColumn = function() {\n        var rowTokens = this.$rowTokens;\n        var tokenIndex = this.$tokenIndex;\n        \n        // If a column was cached by EditSession.getTokenAt, then use it\n        var column = rowTokens[tokenIndex].start;\n        if (column !== undefined)\n            return column;\n            \n        column = 0;\n        while (tokenIndex > 0) {\n            tokenIndex -= 1;\n            column += rowTokens[tokenIndex].value.length;\n        }\n        \n        return column;  \n    };\n            \n}).call(TokenIterator.prototype);\n\nexports.TokenIterator = TokenIterator;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/token_iterator_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\n if (typeof process !== \"undefined\") {\n     require(\"amd-loader\");\n }\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"./edit_session\").EditSession;\nvar JavaScriptMode = require(\"./mode/javascript\").Mode;\nvar TokenIterator = require(\"./token_iterator\").TokenIterator;\nvar assert = require(\"./test/assertions\");\n\nmodule.exports = {\n    \"test: token iterator initialization in JavaScript document\" : function() {\n        var lines = [\n            \"function foo(items) {\",\n            \"    for (var i=0; i<items.length; i++) {\",\n            \"        alert(items[i] + \\\"juhu\\\");\",\n            \"    } // Real Tab.\",\n            \"}\"\n        ];\n        var session = new EditSession(lines.join(\"\\n\"), new JavaScriptMode());\n\n        var iterator = new TokenIterator(session, 0, 0);\n        assert.equal(iterator.getCurrentToken().value, \"function\");\n        assert.equal(iterator.getCurrentTokenRow(), 0);\n        assert.equal(iterator.getCurrentTokenColumn(), 0);\n\n        iterator.stepForward();\n        assert.equal(iterator.getCurrentToken().value, \" \");\n        assert.equal(iterator.getCurrentTokenRow(), 0);\n        assert.equal(iterator.getCurrentTokenColumn(), 8);\n\n        var iterator = new TokenIterator(session, 0, 4);\n        assert.equal(iterator.getCurrentToken().value, \"function\");\n        assert.equal(iterator.getCurrentTokenRow(), 0);\n        assert.equal(iterator.getCurrentTokenColumn(), 0);\n\n        iterator.stepForward();\n        assert.equal(iterator.getCurrentToken().value, \" \");\n        assert.equal(iterator.getCurrentTokenRow(), 0);\n        assert.equal(iterator.getCurrentTokenColumn(), 8);\n\n        var iterator = new TokenIterator(session, 2, 18);\n        assert.equal(iterator.getCurrentToken().value, \"items\");\n        assert.equal(iterator.getCurrentTokenRow(), 2);\n        assert.equal(iterator.getCurrentTokenColumn(), 14);\n\n        iterator.stepForward();\n        assert.equal(iterator.getCurrentToken().value, \"[\");\n        assert.equal(iterator.getCurrentTokenRow(), 2);\n        assert.equal(iterator.getCurrentTokenColumn(), 19);\n\n        var iterator = new TokenIterator(session, 4, 0);\n        assert.equal(iterator.getCurrentToken().value, \"}\");\n        assert.equal(iterator.getCurrentTokenRow(), 4);\n        assert.equal(iterator.getCurrentTokenColumn(), 0);\n\n        iterator.stepBackward();\n        assert.equal(iterator.getCurrentToken().value, \"// Real Tab.\");\n        assert.equal(iterator.getCurrentTokenRow(), 3);\n        assert.equal(iterator.getCurrentTokenColumn(), 6);\n\n        var iterator = new TokenIterator(session, 5, 0);\n        assert.equal(iterator.getCurrentToken(), null);\n    },\n\n    \"test: token iterator initialization in text document\" : function() {\n        var lines = [\n            \"Lorem ipsum dolor sit amet, consectetur adipisicing elit,\",\n            \"sed do eiusmod tempor incididunt ut labore et dolore magna\",\n            \"aliqua. Ut enim ad minim veniam, quis nostrud exercitation\",\n            \"ullamco laboris nisi ut aliquip ex ea commodo consequat.\"\n        ];\n        var session = new EditSession(lines.join(\"\\n\"));\n\n        var iterator = new TokenIterator(session, 0, 0);\n        assert.equal(iterator.getCurrentToken().value, lines[0]);\n        assert.equal(iterator.getCurrentTokenRow(), 0);\n        assert.equal(iterator.getCurrentTokenColumn(), 0);\n\n        var iterator = new TokenIterator(session, 0, 4);\n        assert.equal(iterator.getCurrentToken().value, lines[0]);\n        assert.equal(iterator.getCurrentTokenRow(), 0);\n        assert.equal(iterator.getCurrentTokenColumn(), 0);\n\n        var iterator = new TokenIterator(session, 2, 18);\n        assert.equal(iterator.getCurrentToken().value, lines[2]);\n        assert.equal(iterator.getCurrentTokenRow(), 2);\n        assert.equal(iterator.getCurrentTokenColumn(), 0);\n\n        var iterator = new TokenIterator(session, 3, lines[3].length-1);\n        assert.equal(iterator.getCurrentToken().value, lines[3]);\n        assert.equal(iterator.getCurrentTokenRow(), 3);\n        assert.equal(iterator.getCurrentTokenColumn(), 0);\n\n        var iterator = new TokenIterator(session, 4, 0);\n        assert.equal(iterator.getCurrentToken(), null);\n    },\n\n    \"test: token iterator step forward in JavaScript document\" : function() {\n        var lines = [\n            \"function foo(items) {\",\n            \"    for (var i=0; i<items.length; i++) {\",\n            \"        alert(items[i] + \\\"juhu\\\");\",\n            \"    } // Real Tab.\",\n            \"}\"\n        ];\n        var session = new EditSession(lines.join(\"\\n\"), new JavaScriptMode());\n\n        var rows = session.getTokens(0, lines.length-1);\n        var tokens = [];\n        for (var i = 0; i < rows.length; i++)\n            tokens = tokens.concat(rows[i].tokens);\n\n        var iterator = new TokenIterator(session, 0, 0);\n        for (var i = 1; i < tokens.length; i++)\n            assert.equal(iterator.stepForward(), tokens[i]);\n        assert.equal(iterator.stepForward(), null);\n        assert.equal(iterator.getCurrentToken(), null);\n    },\n\n    \"test: token iterator step backward in JavaScript document\" : function() {\n        var lines = [\n            \"function foo(items) {\",\n            \"     for (var i=0; i<items.length; i++) {\",\n            \"         alert(items[i] + \\\"juhu\\\");\",\n            \"     } // Real Tab.\",\n            \"}\"\n        ];\n        var session = new EditSession(lines.join(\"\\n\"), new JavaScriptMode());\n\n        var rows = session.getTokens(0, lines.length-1);\n        var tokens = [];\n        for (var i = 0; i < rows.length; i++)\n            tokens = tokens.concat(rows[i].tokens);\n\n        var iterator = new TokenIterator(session, 4, 0);\n        for (var i = tokens.length-2; i >= 0; i--)\n            assert.equal(iterator.stepBackward(), tokens[i]);\n        assert.equal(iterator.stepBackward(), null);\n        assert.equal(iterator.getCurrentToken(), null);\n    },\n\n    \"test: token iterator reports correct row and column\" : function() {\n        var lines = [\n            \"function foo(items) {\",\n            \"    for (var i=0; i<items.length; i++) {\",\n            \"        alert(items[i] + \\\"juhu\\\");\",\n            \"    } // Real Tab.\",\n            \"}\"\n        ];\n        var session = new EditSession(lines.join(\"\\n\"), new JavaScriptMode());\n\n        var iterator = new TokenIterator(session, 0, 0);\n\n        iterator.stepForward();\n        iterator.stepForward();\n\n        assert.equal(iterator.getCurrentToken().value, \"foo\");\n        assert.equal(iterator.getCurrentTokenRow(), 0);\n        assert.equal(iterator.getCurrentTokenColumn(), 9);\n\n        iterator.stepForward();\n        iterator.stepForward();\n        iterator.stepForward();\n        iterator.stepForward();\n        iterator.stepForward();\n        iterator.stepForward();\n        iterator.stepForward();\n\n        assert.equal(iterator.getCurrentToken().value, \"for\");\n        assert.equal(iterator.getCurrentTokenRow(), 1);\n        assert.equal(iterator.getCurrentTokenColumn(), 4);\n    },\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/tokenizer.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar Tokenizer = function(rules, flag) {\n    flag = flag ? \"g\" + flag : \"g\";\n    this.rules = rules;\n\n    this.regExps = {};\n    this.matchMappings = {};\n    for ( var key in this.rules) {\n        var rule = this.rules[key];\n        var state = rule;\n        var ruleRegExps = [];\n        var matchTotal = 0;\n        var mapping = this.matchMappings[key] = {};\n\n        for ( var i = 0; i < state.length; i++) {\n\n            if (state[i].regex instanceof RegExp)\n                state[i].regex = state[i].regex.toString().slice(1, -1);\n\n            // Count number of matching groups. 2 extra groups from the full match\n            // And the catch-all on the end (used to force a match);\n            var matchcount = new RegExp(\"(?:(\" + state[i].regex + \")|(.))\").exec(\"a\").length - 2;\n\n            // Replace any backreferences and offset appropriately.\n            var adjustedregex = state[i].regex.replace(/\\\\([0-9]+)/g, function (match, digit) {\n                return \"\\\\\" + (parseInt(digit, 10) + matchTotal + 1);\n            });\n\n            if (matchcount > 1 && state[i].token.length !== matchcount-1)\n                throw new Error(\"Matching groups and length of the token array don't match in rule #\" + i + \" of state \" + key);\n\n            mapping[matchTotal] = {\n                rule: i,\n                len: matchcount\n            };\n            matchTotal += matchcount;\n\n            ruleRegExps.push(adjustedregex);\n        }\n\n        this.regExps[key] = new RegExp(\"(?:(\" + ruleRegExps.join(\")|(\") + \")|(.))\", flag);\n    }\n};\n\n(function() {\n\n    this.getLineTokens = function(line, startState) {\n        var currentState = startState;\n        var state = this.rules[currentState];\n        var mapping = this.matchMappings[currentState];\n        var re = this.regExps[currentState];\n        re.lastIndex = 0;\n\n        var match, tokens = [];\n\n        var lastIndex = 0;\n\n        var token = {\n            type: null,\n            value: \"\"\n        };\n\n        while (match = re.exec(line)) {\n            var type = \"text\";\n            var rule = null;\n            var value = [match[0]];\n\n            for (var i = 0; i < match.length-2; i++) {\n                if (match[i + 1] === undefined)\n                    continue;\n\n                rule = state[mapping[i].rule];\n\n                if (mapping[i].len > 1)\n                    value = match.slice(i+2, i+1+mapping[i].len);\n\n                // compute token type\n                if (typeof rule.token == \"function\")\n                    type = rule.token.apply(this, value);\n                else\n                    type = rule.token;\n\n                if (rule.next) {\n                    currentState = rule.next;\n                    state = this.rules[currentState];\n                    mapping = this.matchMappings[currentState];\n                    lastIndex = re.lastIndex;\n\n                    re = this.regExps[currentState];\n                    re.lastIndex = lastIndex;\n                }\n                break;\n            }\n\n            if (value[0]) {\n                if (typeof type == \"string\") {\n                    value = [value.join(\"\")];\n                    type = [type];\n                }\n                for (var i = 0; i < value.length; i++) {\n                    if (!value[i])\n                        continue;\n\n                    if ((!rule || rule.merge || type[i] === \"text\") && token.type === type[i]) {\n                        token.value += value[i];\n                    } else {\n                        if (token.type)\n                            tokens.push(token);\n\n                        token = {\n                            type: type[i],\n                            value: value[i]\n                        };\n                    }\n                }\n            }\n\n            if (lastIndex == line.length)\n                break;\n\n            lastIndex = re.lastIndex;\n        }\n\n        if (token.type)\n            tokens.push(token);\n\n        return {\n            tokens : tokens,\n            state : currentState\n        };\n    };\n\n}).call(Tokenizer.prototype);\n\nexports.Tokenizer = Tokenizer;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/undomanager.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *      Mihai Sucan <mihai DOT sucan AT gmail DOT com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar UndoManager = function() {\n    this.reset();\n};\n\n(function() {\n\n    this.execute = function(options) {\n        var deltas = options.args[0];\n        this.$doc  = options.args[1];\n        this.$undoStack.push(deltas);\n        this.$redoStack = [];\n    };\n\n    this.undo = function(dontSelect) {\n        var deltas = this.$undoStack.pop();\n        var undoSelectionRange = null;\n        if (deltas) {\n            undoSelectionRange =\n                this.$doc.undoChanges(deltas, dontSelect);\n            this.$redoStack.push(deltas);\n        }\n        return undoSelectionRange;\n    };\n\n    this.redo = function(dontSelect) {\n        var deltas = this.$redoStack.pop();\n        var redoSelectionRange = null;\n        if (deltas) {\n            redoSelectionRange =\n                this.$doc.redoChanges(deltas, dontSelect);\n            this.$undoStack.push(deltas);\n        }\n        return redoSelectionRange;\n    };\n\n    this.reset = function() {\n        this.$undoStack = [];\n        this.$redoStack = [];\n    };\n\n    this.hasUndo = function() {\n        return this.$undoStack.length > 0;\n    };\n\n    this.hasRedo = function() {\n        return this.$redoStack.length > 0;\n    };\n\n}).call(UndoManager.prototype);\n\nexports.UndoManager = UndoManager;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/unicode.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\n/*\nXRegExp Unicode plugin pack: Categories 1.0\n(c) 2010 Steven Levithan\nMIT License\n<http://xregexp.com>\nUses the Unicode 5.2 character database\n\nThis package for the XRegExp Unicode plugin enables the following Unicode categories (aka properties):\n\nL - Letter (the top-level Letter category is included in the Unicode plugin base script)\n    Ll - Lowercase letter\n    Lu - Uppercase letter\n    Lt - Titlecase letter\n    Lm - Modifier letter\n    Lo - Letter without case\nM - Mark\n    Mn - Non-spacing mark\n    Mc - Spacing combining mark\n    Me - Enclosing mark\nN - Number\n    Nd - Decimal digit\n    Nl - Letter number\n    No -  Other number\nP - Punctuation\n    Pd - Dash punctuation\n    Ps - Open punctuation\n    Pe - Close punctuation\n    Pi - Initial punctuation\n    Pf - Final punctuation\n    Pc - Connector punctuation\n    Po - Other punctuation\nS - Symbol\n    Sm - Math symbol\n    Sc - Currency symbol\n    Sk - Modifier symbol\n    So - Other symbol\nZ - Separator\n    Zs - Space separator\n    Zl - Line separator\n    Zp - Paragraph separator\nC - Other\n    Cc - Control\n    Cf - Format\n    Co - Private use\n    Cs - Surrogate\n    Cn - Unassigned\n\nExample usage:\n\n    \\p{N}\n    \\p{Cn}\n*/\n\n\n// will be populated by addUnicodePackage\nexports.packages = {};\n\naddUnicodePackage({\n    L:  \"0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC\",\n    Ll: \"0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A\",\n    Lu: \"0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A\",\n    Lt: \"01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC\",\n    Lm: \"02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F\",\n    Lo: \"01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317DC1820-18421844-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541B05-1B331B45-1B4B1B83-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF66-FF6FFF71-FF9DFFA0-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC\",\n    M:  \"0300-036F0483-04890591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-098309BC09BE-09C409C709C809CB-09CD09D709E209E30A01-0A030A3C0A3E-0A420A470A480A4B-0A4D0A510A700A710A750A81-0A830ABC0ABE-0AC50AC7-0AC90ACB-0ACD0AE20AE30B01-0B030B3C0B3E-0B440B470B480B4B-0B4D0B560B570B620B630B820BBE-0BC20BC6-0BC80BCA-0BCD0BD70C01-0C030C3E-0C440C46-0C480C4A-0C4D0C550C560C620C630C820C830CBC0CBE-0CC40CC6-0CC80CCA-0CCD0CD50CD60CE20CE30D020D030D3E-0D440D46-0D480D4A-0D4D0D570D620D630D820D830DCA0DCF-0DD40DD60DD8-0DDF0DF20DF30E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F3E0F3F0F71-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26\",\n    Mn: \"0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26\",\n    Mc: \"0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC\",\n    Me: \"0488048906DE20DD-20E020E2-20E4A670-A672\",\n    N:  \"0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BF20C66-0C6F0C78-0C7E0CE6-0CEF0D66-0D750E50-0E590ED0-0ED90F20-0F331040-10491090-10991369-137C16EE-16F017E0-17E917F0-17F91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C5920702074-20792080-20892150-21822185-21892460-249B24EA-24FF2776-27932CFD30073021-30293038-303A3192-31953220-32293251-325F3280-328932B1-32BFA620-A629A6E6-A6EFA830-A835A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19\",\n    Nd: \"0030-00390660-066906F0-06F907C0-07C90966-096F09E6-09EF0A66-0A6F0AE6-0AEF0B66-0B6F0BE6-0BEF0C66-0C6F0CE6-0CEF0D66-0D6F0E50-0E590ED0-0ED90F20-0F291040-10491090-109917E0-17E91810-18191946-194F19D0-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19\",\n    Nl: \"16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF\",\n    No: \"00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835\",\n    P:  \"0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65\",\n    Pd: \"002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D\",\n    Ps: \"0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62\",\n    Pe: \"0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63\",\n    Pi: \"00AB2018201B201C201F20392E022E042E092E0C2E1C2E20\",\n    Pf: \"00BB2019201D203A2E032E052E0A2E0D2E1D2E21\",\n    Pc: \"005F203F20402054FE33FE34FE4D-FE4FFF3F\",\n    Po: \"0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65\",\n    S:  \"0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD\",\n    Sm: \"002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC\",\n    Sc: \"002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6\",\n    Sk: \"005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3\",\n    So: \"00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD\",\n    Z:  \"002000A01680180E2000-200A20282029202F205F3000\",\n    Zs: \"002000A01680180E2000-200A202F205F3000\",\n    Zl: \"2028\",\n    Zp: \"2029\",\n    C:  \"0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF\",\n    Cc: \"0000-001F007F-009F\",\n    Cf: \"00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB\",\n    Co: \"E000-F8FF\",\n    Cs: \"D800-DFFF\",\n    Cn: \"03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF\"\n});\n\nfunction addUnicodePackage (pack) {\n    var codePoint = /\\w{4}/g;\n    for (var name in pack)\n        exports.packages[name] = pack[name].replace(codePoint, \"\\\\u$&\");\n};\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/virtual_renderer.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian@ajax.org>\n *      Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)\n *      Julian Viereck <julian.viereck@gmail.com>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"./lib/oop\");\nvar dom = require(\"./lib/dom\");\nvar event = require(\"./lib/event\");\nvar useragent = require(\"./lib/useragent\");\nvar config = require(\"./config\");\nvar net = require(\"./lib/net\");\nvar GutterLayer = require(\"./layer/gutter\").Gutter;\nvar MarkerLayer = require(\"./layer/marker\").Marker;\nvar TextLayer = require(\"./layer/text\").Text;\nvar CursorLayer = require(\"./layer/cursor\").Cursor;\nvar ScrollBar = require(\"./scrollbar\").ScrollBar;\nvar RenderLoop = require(\"./renderloop\").RenderLoop;\nvar EventEmitter = require(\"./lib/event_emitter\").EventEmitter;\nvar editorCss = require(\"ace/requirejs/text!./css/editor.css\");\n\ndom.importCssString(editorCss, \"ace_editor\");\n\nvar VirtualRenderer = function(container, theme) {\n    var _self = this;\n\n    this.container = container;\n\n    // TODO: this breaks rendering in Cloud9 with multiple ace instances\n//    // Imports CSS once per DOM document ('ace_editor' serves as an identifier).\n//    dom.importCssString(editorCss, \"ace_editor\", container.ownerDocument);\n\n    dom.addCssClass(container, \"ace_editor\");\n\n    this.setTheme(theme);\n\n    this.$gutter = dom.createElement(\"div\");\n    this.$gutter.className = \"ace_gutter\";\n    this.container.appendChild(this.$gutter);\n\n    this.scroller = dom.createElement(\"div\");\n    this.scroller.className = \"ace_scroller\";\n    this.container.appendChild(this.scroller);\n\n    this.content = dom.createElement(\"div\");\n    this.content.className = \"ace_content\";\n    this.scroller.appendChild(this.content);\n\n    this.$gutterLayer = new GutterLayer(this.$gutter);\n    this.$gutterLayer.on(\"changeGutterWidth\", this.onResize.bind(this, true));\n\n    this.$markerBack = new MarkerLayer(this.content);\n\n    var textLayer = this.$textLayer = new TextLayer(this.content);\n    this.canvas = textLayer.element;\n\n    this.$markerFront = new MarkerLayer(this.content);\n\n    this.characterWidth = textLayer.getCharacterWidth();\n    this.lineHeight = textLayer.getLineHeight();\n\n    this.$cursorLayer = new CursorLayer(this.content);\n    this.$cursorPadding = 8;\n\n    // Indicates whether the horizontal scrollbar is visible\n    this.$horizScroll = true;\n    this.$horizScrollAlwaysVisible = true;\n\n    this.$animatedScroll = false;\n\n    this.scrollBar = new ScrollBar(container);\n    this.scrollBar.addEventListener(\"scroll\", function(e) {\n        _self.session.setScrollTop(e.data);\n    });\n\n    this.scrollTop = 0;\n    this.scrollLeft = 0;\n\n    event.addListener(this.scroller, \"scroll\", function() {\n        var scrollLeft = _self.scroller.scrollLeft;\n        _self.scrollLeft = scrollLeft;\n        _self.session.setScrollLeft(scrollLeft);\n\n        if (scrollLeft == 0) {\n            _self.$gutter.className = \"ace_gutter\";\n        }\n        else {\n            _self.$gutter.className = \"ace_gutter horscroll\";\n        }\n    });\n\n    this.cursorPos = {\n        row : 0,\n        column : 0\n    };\n\n    this.$textLayer.addEventListener(\"changeCharacterSize\", function() {\n        _self.characterWidth = textLayer.getCharacterWidth();\n        _self.lineHeight = textLayer.getLineHeight();\n        _self.$updatePrintMargin();\n        _self.onResize(true);\n\n        _self.$loop.schedule(_self.CHANGE_FULL);\n    });\n\n    this.$size = {\n        width: 0,\n        height: 0,\n        scrollerHeight: 0,\n        scrollerWidth: 0\n    };\n\n    this.layerConfig = {\n        width : 1,\n        padding : 0,\n        firstRow : 0,\n        firstRowScreen: 0,\n        lastRow : 0,\n        lineHeight : 1,\n        characterWidth : 1,\n        minHeight : 1,\n        maxHeight : 1,\n        offset : 0,\n        height : 1\n    };\n\n    this.$loop = new RenderLoop(\n        this.$renderChanges.bind(this),\n        this.container.ownerDocument.defaultView\n    );\n    this.$loop.schedule(this.CHANGE_FULL);\n\n    this.setPadding(4);\n    this.$updatePrintMargin();\n};\n\n(function() {\n    this.showGutter = true;\n\n    this.CHANGE_CURSOR = 1;\n    this.CHANGE_MARKER = 2;\n    this.CHANGE_GUTTER = 4;\n    this.CHANGE_SCROLL = 8;\n    this.CHANGE_LINES = 16;\n    this.CHANGE_TEXT = 32;\n    this.CHANGE_SIZE = 64;\n    this.CHANGE_MARKER_BACK = 128;\n    this.CHANGE_MARKER_FRONT = 256;\n    this.CHANGE_FULL = 512;\n    this.CHANGE_H_SCROLL = 1024;\n\n    oop.implement(this, EventEmitter);\n\n    this.setSession = function(session) {\n        this.session = session;\n        this.$cursorLayer.setSession(session);\n        this.$markerBack.setSession(session);\n        this.$markerFront.setSession(session);\n        this.$gutterLayer.setSession(session);\n        this.$textLayer.setSession(session);\n        this.$loop.schedule(this.CHANGE_FULL);\n    };\n\n    /**\n     * Triggers partial update of the text layer\n     */\n    this.updateLines = function(firstRow, lastRow) {\n        if (lastRow === undefined)\n            lastRow = Infinity;\n\n        if (!this.$changedLines) {\n            this.$changedLines = {\n                firstRow: firstRow,\n                lastRow: lastRow\n            };\n        }\n        else {\n            if (this.$changedLines.firstRow > firstRow)\n                this.$changedLines.firstRow = firstRow;\n\n            if (this.$changedLines.lastRow < lastRow)\n                this.$changedLines.lastRow = lastRow;\n        }\n\n        this.$loop.schedule(this.CHANGE_LINES);\n    };\n\n    /**\n     * Triggers full update of the text layer\n     */\n    this.updateText = function() {\n        this.$loop.schedule(this.CHANGE_TEXT);\n    };\n\n    /**\n     * Triggers a full update of all layers\n     */\n    this.updateFull = function() {\n        this.$loop.schedule(this.CHANGE_FULL);\n    };\n\n    this.updateFontSize = function() {\n        this.$textLayer.checkForSizeChanges();\n    };\n\n    /**\n     * Triggers resize of the editor\n     */\n    this.onResize = function(force) {\n        var changes = this.CHANGE_SIZE;\n        var size = this.$size;\n\n        var height = dom.getInnerHeight(this.container);\n        if (force || size.height != height) {\n            size.height = height;\n\n            this.scroller.style.height = height + \"px\";\n            size.scrollerHeight = this.scroller.clientHeight;\n            this.scrollBar.setHeight(size.scrollerHeight);\n\n            if (this.session) {\n                this.session.setScrollTop(this.getScrollTop());\n                changes = changes | this.CHANGE_FULL;\n            }\n        }\n\n        var width = dom.getInnerWidth(this.container);\n        if (force || size.width != width) {\n            size.width = width;\n\n            var gutterWidth = this.showGutter ? this.$gutter.offsetWidth : 0;\n            this.scroller.style.left = gutterWidth + \"px\";\n            size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBar.getWidth());\n            this.scroller.style.width = size.scrollerWidth + \"px\";\n\n            if (this.session.getUseWrapMode() && this.adjustWrapLimit() || force)\n                changes = changes | this.CHANGE_FULL;\n        }\n\n        this.$loop.schedule(changes);\n    };\n\n    this.adjustWrapLimit = function() {\n        var availableWidth = this.$size.scrollerWidth - this.$padding * 2;\n        var limit = Math.floor(availableWidth / this.characterWidth);\n        return this.session.adjustWrapLimit(limit);\n    };\n\n    this.setAnimatedScroll = function(shouldAnimate){\n        this.$animatedScroll = shouldAnimate;\n    };\n\n    this.getAnimatedScroll = function() {\n        return this.$animatedScroll;\n    };\n\n    this.setShowInvisibles = function(showInvisibles) {\n        if (this.$textLayer.setShowInvisibles(showInvisibles))\n            this.$loop.schedule(this.CHANGE_TEXT);\n    };\n\n    this.getShowInvisibles = function() {\n        return this.$textLayer.showInvisibles;\n    };\n\n    this.$showPrintMargin = true;\n    this.setShowPrintMargin = function(showPrintMargin) {\n        this.$showPrintMargin = showPrintMargin;\n        this.$updatePrintMargin();\n    };\n\n    this.getShowPrintMargin = function() {\n        return this.$showPrintMargin;\n    };\n\n    this.$printMarginColumn = 80;\n    this.setPrintMarginColumn = function(showPrintMargin) {\n        this.$printMarginColumn = showPrintMargin;\n        this.$updatePrintMargin();\n    };\n\n    this.getPrintMarginColumn = function() {\n        return this.$printMarginColumn;\n    };\n\n    this.getShowGutter = function(){\n        return this.showGutter;\n    };\n\n    this.setShowGutter = function(show){\n        if(this.showGutter === show)\n            return;\n        this.$gutter.style.display = show ? \"block\" : \"none\";\n        this.showGutter = show;\n        this.onResize(true);\n    };\n\n    this.$updatePrintMargin = function() {\n        var containerEl;\n\n        if (!this.$showPrintMargin && !this.$printMarginEl)\n            return;\n\n        if (!this.$printMarginEl) {\n            containerEl = dom.createElement(\"div\");\n            containerEl.className = \"ace_print_margin_layer\";\n            this.$printMarginEl = dom.createElement(\"div\");\n            this.$printMarginEl.className = \"ace_print_margin\";\n            containerEl.appendChild(this.$printMarginEl);\n            this.content.insertBefore(containerEl, this.$textLayer.element);\n        }\n\n        var style = this.$printMarginEl.style;\n        style.left = ((this.characterWidth * this.$printMarginColumn) + this.$padding) + \"px\";\n        style.visibility = this.$showPrintMargin ? \"visible\" : \"hidden\";\n    };\n\n    this.getContainerElement = function() {\n        return this.container;\n    };\n\n    this.getMouseEventTarget = function() {\n        return this.content;\n    };\n\n    this.getTextAreaContainer = function() {\n        return this.container;\n    };\n\n    this.moveTextAreaToCursor = function(textarea) {\n        // in IE the native cursor always shines through\n        // this persists in IE9\n        if (useragent.isIE)\n            return;\n\n        if (this.layerConfig.lastRow === 0)\n            return;\n\n        var pos = this.$cursorLayer.getPixelPosition();\n        if (!pos)\n            return;\n\n        var bounds = this.content.getBoundingClientRect();\n        var offset = this.layerConfig.offset;\n\n        textarea.style.left = (bounds.left + pos.left) + \"px\";\n        textarea.style.top = (bounds.top + pos.top - this.scrollTop + offset) + \"px\";\n    };\n\n    this.getFirstVisibleRow = function() {\n        return this.layerConfig.firstRow;\n    };\n\n    this.getFirstFullyVisibleRow = function() {\n        return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1);\n    };\n\n    this.getLastFullyVisibleRow = function() {\n        var flint = Math.floor((this.layerConfig.height + this.layerConfig.offset) / this.layerConfig.lineHeight);\n        return this.layerConfig.firstRow - 1 + flint;\n    };\n\n    this.getLastVisibleRow = function() {\n        return this.layerConfig.lastRow;\n    };\n\n    this.$padding = null;\n    this.setPadding = function(padding) {\n        this.$padding = padding;\n        this.$textLayer.setPadding(padding);\n        this.$cursorLayer.setPadding(padding);\n        this.$markerFront.setPadding(padding);\n        this.$markerBack.setPadding(padding);\n        this.$loop.schedule(this.CHANGE_FULL);\n        this.$updatePrintMargin();\n    };\n\n    this.getHScrollBarAlwaysVisible = function() {\n        return this.$horizScrollAlwaysVisible;\n    };\n\n    this.setHScrollBarAlwaysVisible = function(alwaysVisible) {\n        if (this.$horizScrollAlwaysVisible != alwaysVisible) {\n            this.$horizScrollAlwaysVisible = alwaysVisible;\n            if (!this.$horizScrollAlwaysVisible || !this.$horizScroll)\n                this.$loop.schedule(this.CHANGE_SCROLL);\n        }\n    };\n\n    this.$updateScrollBar = function() {\n        this.scrollBar.setInnerHeight(this.layerConfig.maxHeight);\n        this.scrollBar.setScrollTop(this.scrollTop);\n    };\n\n    this.$renderChanges = function(changes) {\n        if (!changes || !this.session || !this.container.offsetWidth)\n            return;\n\n        // text, scrolling and resize changes can cause the view port size to change\n        if (changes & this.CHANGE_FULL ||\n            changes & this.CHANGE_SIZE ||\n            changes & this.CHANGE_TEXT ||\n            changes & this.CHANGE_LINES ||\n            changes & this.CHANGE_SCROLL\n        )\n            this.$computeLayerConfig();\n\n        // horizontal scrolling\n        if (changes & this.CHANGE_H_SCROLL) {\n            this.scroller.scrollLeft = this.scrollLeft;\n\n            // read the value after writing it since the value might get clipped\n            var scrollLeft = this.scroller.scrollLeft;\n            this.scrollLeft = scrollLeft;\n            this.session.setScrollLeft(scrollLeft);\n        }\n\n        // full\n        if (changes & this.CHANGE_FULL) {\n            this.$textLayer.checkForSizeChanges();\n            // update scrollbar first to not lose scroll position when gutter calls resize\n            this.$updateScrollBar();\n            this.$textLayer.update(this.layerConfig);\n            if (this.showGutter)\n                this.$gutterLayer.update(this.layerConfig);\n            this.$markerBack.update(this.layerConfig);\n            this.$markerFront.update(this.layerConfig);\n            this.$cursorLayer.update(this.layerConfig);\n            return;\n        }\n\n        // scrolling\n        if (changes & this.CHANGE_SCROLL) {\n            this.$updateScrollBar();\n            if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES)\n                this.$textLayer.update(this.layerConfig);\n            else\n                this.$textLayer.scrollLines(this.layerConfig);\n\n            if (this.showGutter)\n                this.$gutterLayer.update(this.layerConfig);\n            this.$markerBack.update(this.layerConfig);\n            this.$markerFront.update(this.layerConfig);\n            this.$cursorLayer.update(this.layerConfig);\n            return;\n        }\n\n        if (changes & this.CHANGE_TEXT) {\n            this.$textLayer.update(this.layerConfig);\n            if (this.showGutter)\n                this.$gutterLayer.update(this.layerConfig);\n        }\n        else if (changes & this.CHANGE_LINES) {\n            if (this.$updateLines()) {\n                this.$updateScrollBar();\n                if (this.showGutter)\n                    this.$gutterLayer.update(this.layerConfig);\n            }\n        } else if (changes & this.CHANGE_GUTTER) {\n            if (this.showGutter)\n                this.$gutterLayer.update(this.layerConfig);\n        }\n\n        if (changes & this.CHANGE_CURSOR)\n            this.$cursorLayer.update(this.layerConfig);\n\n        if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) {\n            this.$markerFront.update(this.layerConfig);\n        }\n\n        if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_BACK)) {\n            this.$markerBack.update(this.layerConfig);\n        }\n\n        if (changes & this.CHANGE_SIZE)\n            this.$updateScrollBar();\n    };\n\n    this.$computeLayerConfig = function() {\n        var session = this.session;\n\n        var offset = this.scrollTop % this.lineHeight;\n        var minHeight = this.$size.scrollerHeight + this.lineHeight;\n\n        var longestLine = this.$getLongestLine();\n\n        var horizScroll = this.$horizScrollAlwaysVisible || this.$size.scrollerWidth - longestLine < 0;\n        var horizScrollChanged = this.$horizScroll !== horizScroll;\n        this.$horizScroll = horizScroll;\n        if (horizScrollChanged) {\n            this.scroller.style.overflowX = horizScroll ? \"scroll\" : \"hidden\";\n            // when we hide scrollbar scroll event isn't emited\n            // leaving session with wrong scrollLeft value\n            if (!horizScroll)\n                this.session.setScrollLeft(0);\n        }\n        var maxHeight = this.session.getScreenLength() * this.lineHeight;\n        this.session.setScrollTop(Math.max(0, Math.min(this.scrollTop, maxHeight - this.$size.scrollerHeight)));\n\n        var lineCount = Math.ceil(minHeight / this.lineHeight) - 1;\n        var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight));\n        var lastRow = firstRow + lineCount;\n\n        // Map lines on the screen to lines in the document.\n        var firstRowScreen, firstRowHeight;\n        var lineHeight = { lineHeight: this.lineHeight };\n        firstRow = session.screenToDocumentRow(firstRow, 0);\n\n        // Check if firstRow is inside of a foldLine. If true, then use the first\n        // row of the foldLine.\n        var foldLine = session.getFoldLine(firstRow);\n        if (foldLine) {\n            firstRow = foldLine.start.row;\n        }\n\n        firstRowScreen = session.documentToScreenRow(firstRow, 0);\n        firstRowHeight = session.getRowHeight(lineHeight, firstRow);\n\n        lastRow = Math.min(session.screenToDocumentRow(lastRow, 0), session.getLength() - 1);\n        minHeight = this.$size.scrollerHeight + session.getRowHeight(lineHeight, lastRow)+\n                                                firstRowHeight;\n\n        offset = this.scrollTop - firstRowScreen * this.lineHeight;\n\n        this.layerConfig = {\n            width : longestLine,\n            padding : this.$padding,\n            firstRow : firstRow,\n            firstRowScreen: firstRowScreen,\n            lastRow : lastRow,\n            lineHeight : this.lineHeight,\n            characterWidth : this.characterWidth,\n            minHeight : minHeight,\n            maxHeight : maxHeight,\n            offset : offset,\n            height : this.$size.scrollerHeight\n        };\n\n        // For debugging.\n        // console.log(JSON.stringify(this.layerConfig));\n\n        this.$gutterLayer.element.style.marginTop = (-offset) + \"px\";\n        this.content.style.marginTop = (-offset) + \"px\";\n        this.content.style.width = longestLine + 2 * this.$padding + \"px\";\n        this.content.style.height = minHeight + \"px\";\n\n        // Horizontal scrollbar visibility may have changed, which changes\n        // the client height of the scroller\n        if (horizScrollChanged)\n            this.onResize(true);\n    };\n\n    this.$updateLines = function() {\n        var firstRow = this.$changedLines.firstRow;\n        var lastRow = this.$changedLines.lastRow;\n        this.$changedLines = null;\n\n        var layerConfig = this.layerConfig;\n\n        // if the update changes the width of the document do a full redraw\n        if (layerConfig.width != this.$getLongestLine())\n            return this.$textLayer.update(layerConfig);\n\n        if (firstRow > layerConfig.lastRow + 1) { return; }\n        if (lastRow < layerConfig.firstRow) { return; }\n\n        // if the last row is unknown -> redraw everything\n        if (lastRow === Infinity) {\n            if (this.showGutter)\n                this.$gutterLayer.update(layerConfig);\n            this.$textLayer.update(layerConfig);\n            return;\n        }\n\n        // else update only the changed rows\n        this.$textLayer.updateLines(layerConfig, firstRow, lastRow);\n        return true;\n    };\n\n    this.$getLongestLine = function() {\n        var charCount = this.session.getScreenWidth();\n        if (this.$textLayer.showInvisibles)\n            charCount += 1;\n\n        return Math.max(this.$size.scrollerWidth - 2 * this.$padding, Math.round(charCount * this.characterWidth));\n    };\n\n    this.updateFrontMarkers = function() {\n        this.$markerFront.setMarkers(this.session.getMarkers(true));\n        this.$loop.schedule(this.CHANGE_MARKER_FRONT);\n    };\n\n    this.updateBackMarkers = function() {\n        this.$markerBack.setMarkers(this.session.getMarkers());\n        this.$loop.schedule(this.CHANGE_MARKER_BACK);\n    };\n\n    this.addGutterDecoration = function(row, className){\n        this.$gutterLayer.addGutterDecoration(row, className);\n        this.$loop.schedule(this.CHANGE_GUTTER);\n    };\n\n    this.removeGutterDecoration = function(row, className){\n        this.$gutterLayer.removeGutterDecoration(row, className);\n        this.$loop.schedule(this.CHANGE_GUTTER);\n    };\n\n    this.setBreakpoints = function(rows) {\n        this.$gutterLayer.setBreakpoints(rows);\n        this.$loop.schedule(this.CHANGE_GUTTER);\n    };\n\n    this.setAnnotations = function(annotations) {\n        this.$gutterLayer.setAnnotations(annotations);\n        this.$loop.schedule(this.CHANGE_GUTTER);\n    };\n\n    this.updateCursor = function() {\n        this.$loop.schedule(this.CHANGE_CURSOR);\n    };\n\n    this.hideCursor = function() {\n        this.$cursorLayer.hideCursor();\n    };\n\n    this.showCursor = function() {\n        this.$cursorLayer.showCursor();\n    };\n\n    this.scrollSelectionIntoView = function(anchor, lead) {\n        // first scroll anchor into view then scroll lead into view\n        this.scrollCursorIntoView(anchor);\n        this.scrollCursorIntoView(lead);\n    };\n\n    this.scrollCursorIntoView = function(cursor) {\n        // the editor is not visible\n        if (this.$size.scrollerHeight === 0)\n            return;\n\n        var pos = this.$cursorLayer.getPixelPosition(cursor);\n\n        var left = pos.left;\n        var top = pos.top;\n\n        if (this.scrollTop > top) {\n            this.session.setScrollTop(top);\n        }\n\n        if (this.scrollTop + this.$size.scrollerHeight < top + this.lineHeight) {\n            this.session.setScrollTop(top + this.lineHeight - this.$size.scrollerHeight);\n        }\n\n        var scrollLeft = this.scrollLeft;\n\n        if (scrollLeft > left) {\n            if (left < this.$padding + 2 * this.layerConfig.characterWidth)\n                left = 0;\n            this.session.setScrollLeft(left);\n        }\n\n        if (scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) {\n            this.session.setScrollLeft(Math.round(left + this.characterWidth - this.$size.scrollerWidth));\n        }\n    };\n\n    this.getScrollTop = function() {\n        return this.session.getScrollTop();\n    };\n\n    this.getScrollLeft = function() {\n        return this.session.getScrollLeft();\n    };\n\n    this.getScrollTopRow = function() {\n        return this.scrollTop / this.lineHeight;\n    };\n\n    this.getScrollBottomRow = function() {\n        return Math.max(0, Math.floor((this.scrollTop + this.$size.scrollerHeight) / this.lineHeight) - 1);\n    };\n\n    this.scrollToRow = function(row) {\n        this.session.setScrollTop(row * this.lineHeight);\n    };\n\n    this.STEPS = 10;\n    this.$calcSteps = function(fromValue, toValue){\n        var i = 0;\n        var l = this.STEPS;\n        var steps = [];\n\n        var func  = function(t, x_min, dx) {\n            if ((t /= .5) < 1)\n                return dx / 2 * Math.pow(t, 3) + x_min;\n            return dx / 2 * (Math.pow(t - 2, 3) + 2) + x_min;\n        };\n\n        for (i = 0; i < l; ++i)\n            steps.push(func(i / this.STEPS, fromValue, toValue - fromValue));\n        steps.push(toValue);\n\n        return steps;\n    };\n\n    this.scrollToLine = function(line, center) {\n        var pos = this.$cursorLayer.getPixelPosition({row: line, column: 0});\n        var offset = pos.top;\n        if (center)\n            offset -= this.$size.scrollerHeight / 2;\n\n        if (this.$animatedScroll && Math.abs(offset - this.scrollTop) < 10000) {\n            var _self = this;\n            var steps = _self.$calcSteps(this.scrollTop, offset);\n\n            clearInterval(this.$timer);\n            this.$timer = setInterval(function() {\n                _self.session.setScrollTop(steps.shift());\n                \n                if (!steps.length)\n                    clearInterval(_self.$timer);\n            }, 10);\n        }\n        else {\n            this.session.setScrollTop(offset);\n        }\n    };\n\n    this.scrollToY = function(scrollTop) {\n        // after calling scrollBar.setScrollTop\n        // scrollbar sends us event with same scrollTop. ignore it\n        if (this.scrollTop !== scrollTop) {\n            this.$loop.schedule(this.CHANGE_SCROLL);\n            this.scrollTop = scrollTop;\n        }\n    };\n\n    this.scrollToX = function(scrollLeft) {\n        if (scrollLeft <= this.$padding)\n            scrollLeft = 0;\n\n        if (this.scrollLeft !== scrollLeft)\n            this.scrollLeft = scrollLeft;\n        this.$loop.schedule(this.CHANGE_H_SCROLL);\n    };\n\n    this.scrollBy = function(deltaX, deltaY) {\n        deltaY && this.session.setScrollTop(this.session.getScrollTop() + deltaY);\n        deltaX && this.session.setScrollLeft(this.session.getScrollLeft() + deltaX);\n    };\n\n    this.isScrollableBy = function(deltaX, deltaY) {\n        if (deltaY < 0 && this.session.getScrollTop() > 0)\n           return true;\n        if (deltaY > 0 && this.session.getScrollTop() + this.$size.scrollerHeight < this.layerConfig.maxHeight)\n           return true;\n        // todo: handle horizontal scrolling\n    };\n\n    this.pixelToScreenCoordinates = function(pageX, pageY) {\n        var canvasPos = this.scroller.getBoundingClientRect();\n\n        var col = Math.round(\n            (pageX + this.scrollLeft - canvasPos.left - this.$padding - dom.getPageScrollLeft()) / this.characterWidth\n        );\n        var row = Math.floor(\n            (pageY + this.scrollTop - canvasPos.top - dom.getPageScrollTop()) / this.lineHeight\n        );\n\n        return {row: row, column: col};\n    };\n\n    this.screenToTextCoordinates = function(pageX, pageY) {\n        var canvasPos = this.scroller.getBoundingClientRect();\n\n        var col = Math.round(\n            (pageX + this.scrollLeft - canvasPos.left - this.$padding - dom.getPageScrollLeft()) / this.characterWidth\n        );\n        var row = Math.floor(\n            (pageY + this.scrollTop - canvasPos.top - dom.getPageScrollTop()) / this.lineHeight\n        );\n\n        return this.session.screenToDocumentPosition(row, Math.max(col, 0));\n    };\n\n    this.textToScreenCoordinates = function(row, column) {\n        var canvasPos = this.scroller.getBoundingClientRect();\n        var pos = this.session.documentToScreenPosition(row, column);\n\n        var x = this.$padding + Math.round(pos.column * this.characterWidth);\n        var y = pos.row * this.lineHeight;\n\n        return {\n            pageX: canvasPos.left + x - this.scrollLeft,\n            pageY: canvasPos.top + y - this.scrollTop\n        };\n    };\n\n    this.visualizeFocus = function() {\n        dom.addCssClass(this.container, \"ace_focus\");\n    };\n\n    this.visualizeBlur = function() {\n        dom.removeCssClass(this.container, \"ace_focus\");\n    };\n\n    this.showComposition = function(position) {\n        if (!this.$composition) {\n            this.$composition = dom.createElement(\"div\");\n            this.$composition.className = \"ace_composition\";\n            this.content.appendChild(this.$composition);\n        }\n\n        this.$composition.innerHTML = \"&#160;\";\n\n        var pos = this.$cursorLayer.getPixelPosition();\n        var style = this.$composition.style;\n        style.top = pos.top + \"px\";\n        style.left = (pos.left + this.$padding) + \"px\";\n        style.height = this.lineHeight + \"px\";\n\n        this.hideCursor();\n    };\n\n    this.setCompositionText = function(text) {\n        dom.setInnerText(this.$composition, text);\n    };\n\n    this.hideComposition = function() {\n        this.showCursor();\n\n        if (!this.$composition)\n            return;\n\n        var style = this.$composition.style;\n        style.top = \"-10000px\";\n        style.left = \"-10000px\";\n    };\n\n    this._loadTheme = function(name, callback) {\n        if (!config.get(\"packaged\"))\n            return callback();\n\n        var base = name.split(\"/\").pop();\n        var filename = config.get(\"themePath\") + \"/theme-\" + base + config.get(\"suffix\");\n        net.loadScript(filename, callback);\n    };\n\n    this.setTheme = function(theme) {\n        var _self = this;\n\n        this.$themeValue = theme;\n        if (!theme || typeof theme == \"string\") {\n            var moduleName = theme || \"ace/theme/textmate\";\n\n            var module;\n            try {\n                module = require(moduleName);\n            } catch (e) {};\n            if (module)\n                return afterLoad(module);\n\n            _self._loadTheme(moduleName, function() {\n                require([moduleName], function(module) {\n                    if (_self.$themeValue !== theme)\n                        return;\n\n                    afterLoad(module);\n                });\n            });\n        } else {\n            afterLoad(theme);\n        }\n\n        function afterLoad(theme) {\n            dom.importCssString(\n                theme.cssText,\n                theme.cssClass,\n                _self.container.ownerDocument\n            );\n\n            if (_self.$theme)\n                dom.removeCssClass(_self.container, _self.$theme);\n\n            _self.$theme = theme ? theme.cssClass : null;\n\n            if (_self.$theme)\n                dom.addCssClass(_self.container, _self.$theme);\n\n            if (theme && theme.isDark)\n                dom.addCssClass(_self.container, \"ace_dark\");\n            else\n                dom.removeCssClass(_self.container, \"ace_dark\");\n\n            // force re-measure of the gutter width\n            if (_self.$size) {\n                _self.$size.width = 0;\n                _self.onResize();\n            }\n        }\n    };\n\n    this.getTheme = function() {\n        return this.$themeValue;\n    };\n\n    // Methods allows to add / remove CSS classnames to the editor element.\n    // This feature can be used by plug-ins to provide a visual indication of\n    // a certain mode that editor is in.\n\n    this.setStyle = function setStyle(style) {\n      dom.addCssClass(this.container, style);\n    };\n\n    this.unsetStyle = function unsetStyle(style) {\n      dom.removeCssClass(this.container, style);\n    };\n\n    this.destroy = function() {\n        this.$textLayer.destroy();\n        this.$cursorLayer.destroy();\n    };\n\n}).call(VirtualRenderer.prototype);\n\nexports.VirtualRenderer = VirtualRenderer;\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/virtual_renderer_test.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\nif (typeof process !== \"undefined\") {\n    require(\"amd-loader\");\n    require(\"./test/mockdom\");\n}\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar EditSession = require(\"./edit_session\").EditSession;\nvar VirtualRenderer = require(\"./virtual_renderer\").VirtualRenderer;\nvar assert = require(\"./test/assertions\");\n\nmodule.exports = {\n    \"test: screen2text the column should be rounded to the next character edge\" : function() {\n        var el = document.createElement(\"div\");\n        \n        if (!el.getBoundingClientRect) {\n            console.log(\"Skipping test: This test only runs in the browser\");\n            return;\n        }\n        \n        el.style.left = \"0px\";\n        el.style.top = \"0px\";\n        el.style.width = \"100px\";\n        el.style.height = \"100px\";\n        document.body.style.margin = \"0px\";\n        document.body.style.padding = \"0px\";\n        document.body.appendChild(el);\n\n        var renderer = new VirtualRenderer(el);\n        renderer.setPadding(0);\n        renderer.setSession(new EditSession(\"1234\"));\n\n        renderer.characterWidth = 10;\n        renderer.lineHeight = 15;\n\n        assert.position(renderer.screenToTextCoordinates(0, 0), 0, 0);\n        assert.position(renderer.screenToTextCoordinates(4, 0), 0, 0);\n        assert.position(renderer.screenToTextCoordinates(5, 0), 0, 1);\n        assert.position(renderer.screenToTextCoordinates(9, 0), 0, 1);\n        assert.position(renderer.screenToTextCoordinates(10, 0), 0, 1);\n        assert.position(renderer.screenToTextCoordinates(14, 0), 0, 1);\n        assert.position(renderer.screenToTextCoordinates(15, 0), 0, 2);\n        document.body.removeChild(el);\n    }\n\n    // change tab size after setDocument (for text layer)\n};\n\n});\n\nif (typeof module !== \"undefined\" && module === require.main) {\n    require(\"asyncjs\").test.testcase(module.exports).exec()\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/worker/jshint.js",
    "content": "define(function(require, exports, module) {\n/*!\n * JSHint, by JSHint Community.\n *\n * Licensed under the same slightly modified MIT license that JSLint is.\n * It stops evil-doers everywhere.\n *\n * JSHint is a derivative work of JSLint:\n *\n *   Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)\n *\n *   Permission is hereby granted, free of charge, to any person obtaining\n *   a copy of this software and associated documentation files (the \"Software\"),\n *   to deal in the Software without restriction, including without limitation\n *   the rights to use, copy, modify, merge, publish, distribute, sublicense,\n *   and/or sell copies of the Software, and to permit persons to whom\n *   the Software is furnished to do so, subject to the following conditions:\n *\n *   The above copyright notice and this permission notice shall be included\n *   in all copies or substantial portions of the Software.\n *\n *   The Software shall be used for Good, not Evil.\n *\n *   THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n *   DEALINGS IN THE SOFTWARE.\n *\n * JSHint was forked from 2010-12-16 edition of JSLint.\n *\n */\n\n/*\n JSHINT is a global function. It takes two parameters.\n\n     var myResult = JSHINT(source, option);\n\n The first parameter is either a string or an array of strings. If it is a\n string, it will be split on '\\n' or '\\r'. If it is an array of strings, it\n is assumed that each string represents one line. The source can be a\n JavaScript text or a JSON text.\n\n The second parameter is an optional object of options which control the\n operation of JSHINT. Most of the options are booleans: They are all\n optional and have a default value of false. One of the options, predef,\n can be an array of names, which will be used to declare global variables,\n or an object whose keys are used as global names, with a boolean value\n that determines if they are assignable.\n\n If it checks out, JSHINT returns true. Otherwise, it returns false.\n\n If false, you can inspect JSHINT.errors to find out the problems.\n JSHINT.errors is an array of objects containing these members:\n\n {\n     line      : The line (relative to 0) at which the lint was found\n     character : The character (relative to 0) at which the lint was found\n     reason    : The problem\n     evidence  : The text line in which the problem occurred\n     raw       : The raw message before the details were inserted\n     a         : The first detail\n     b         : The second detail\n     c         : The third detail\n     d         : The fourth detail\n }\n\n If a fatal error was found, a null will be the last element of the\n JSHINT.errors array.\n\n You can request a Function Report, which shows all of the functions\n and the parameters and vars that they use. This can be used to find\n implied global variables and other problems. The report is in HTML and\n can be inserted in an HTML <body>.\n\n     var myReport = JSHINT.report(limited);\n\n If limited is true, then the report will be limited to only errors.\n\n You can request a data structure which contains JSHint's results.\n\n     var myData = JSHINT.data();\n\n It returns a structure with this form:\n\n {\n     errors: [\n         {\n             line: NUMBER,\n             character: NUMBER,\n             reason: STRING,\n             evidence: STRING\n         }\n     ],\n     functions: [\n         name: STRING,\n         line: NUMBER,\n         last: NUMBER,\n         param: [\n             STRING\n         ],\n         closure: [\n             STRING\n         ],\n         var: [\n             STRING\n         ],\n         exception: [\n             STRING\n         ],\n         outer: [\n             STRING\n         ],\n         unused: [\n             STRING\n         ],\n         global: [\n             STRING\n         ],\n         label: [\n             STRING\n         ]\n     ],\n     globals: [\n         STRING\n     ],\n     member: {\n         STRING: NUMBER\n     },\n     unused: [\n         {\n             name: STRING,\n             line: NUMBER\n         }\n     ],\n     implieds: [\n         {\n             name: STRING,\n             line: NUMBER\n         }\n     ],\n     urls: [\n         STRING\n     ],\n     json: BOOLEAN\n }\n\n Empty arrays will not be included.\n\n*/\n\n/*jshint\n evil: true, nomen: false, onevar: false, regexp: false, strict: true, boss: true,\n undef: true, maxlen: 100, indent:4\n*/\n\n/*members \"\\b\", \"\\t\", \"\\n\", \"\\f\", \"\\r\", \"!=\", \"!==\", \"\\\"\", \"%\", \"(begin)\",\n \"(breakage)\", \"(context)\", \"(error)\", \"(global)\", \"(identifier)\", \"(last)\",\n \"(line)\", \"(loopage)\", \"(name)\", \"(onevar)\", \"(params)\", \"(scope)\",\n \"(statement)\", \"(verb)\", \"*\", \"+\", \"++\", \"-\", \"--\", \"\\/\", \"<\", \"<=\", \"==\",\n \"===\", \">\", \">=\", $, $$, $A, $F, $H, $R, $break, $continue, $w, Abstract, Ajax,\n __filename, __dirname, ActiveXObject, Array, ArrayBuffer, ArrayBufferView, Audio,\n Autocompleter, Assets, Boolean, Builder, Buffer, Browser, COM, CScript, Canvas,\n CustomAnimation, Class, Control, Chain, Color, Cookie, Core, DataView, Date,\n Debug, Draggable, Draggables, Droppables, Document, DomReady, DOMReady, DOMParser, Drag,\n E, Enumerator, Enumerable, Element, Elements, Error, Effect, EvalError, Event,\n Events, FadeAnimation, Field, Flash, Float32Array, Float64Array, Form,\n FormField, Frame, FormData, Function, Fx, GetObject, Group, Hash, HotKey,\n HTMLElement, HTMLAnchorElement, HTMLBaseElement, HTMLBlockquoteElement,\n HTMLBodyElement, HTMLBRElement, HTMLButtonElement, HTMLCanvasElement, HTMLDirectoryElement,\n HTMLDivElement, HTMLDListElement, HTMLFieldSetElement,\n HTMLFontElement, HTMLFormElement, HTMLFrameElement, HTMLFrameSetElement,\n HTMLHeadElement, HTMLHeadingElement, HTMLHRElement, HTMLHtmlElement,\n HTMLIFrameElement, HTMLImageElement, HTMLInputElement, HTMLIsIndexElement,\n HTMLLabelElement, HTMLLayerElement, HTMLLegendElement, HTMLLIElement,\n HTMLLinkElement, HTMLMapElement, HTMLMenuElement, HTMLMetaElement,\n HTMLModElement, HTMLObjectElement, HTMLOListElement, HTMLOptGroupElement,\n HTMLOptionElement, HTMLParagraphElement, HTMLParamElement, HTMLPreElement,\n HTMLQuoteElement, HTMLScriptElement, HTMLSelectElement, HTMLStyleElement,\n HtmlTable, HTMLTableCaptionElement, HTMLTableCellElement, HTMLTableColElement,\n HTMLTableElement, HTMLTableRowElement, HTMLTableSectionElement,\n HTMLTextAreaElement, HTMLTitleElement, HTMLUListElement, HTMLVideoElement,\n Iframe, IframeShim, Image, Int16Array, Int32Array, Int8Array,\n Insertion, InputValidator, JSON, Keyboard, Locale, LN10, LN2, LOG10E, LOG2E,\n MAX_VALUE, MIN_VALUE, Mask, Math, MenuItem, MessageChannel, MessageEvent, MessagePort,\n MoveAnimation, MooTools, Native, NEGATIVE_INFINITY, Number, Object, ObjectRange, Option,\n Options, OverText, PI, POSITIVE_INFINITY, PeriodicalExecuter, Point, Position, Prototype,\n RangeError, Rectangle, ReferenceError, RegExp, ResizeAnimation, Request, RotateAnimation,\n SQRT1_2, SQRT2, ScrollBar, ScriptEngine, ScriptEngineBuildVersion,\n ScriptEngineMajorVersion, ScriptEngineMinorVersion, Scriptaculous, Scroller,\n Slick, Slider, Selector, SharedWorker, String, Style, SyntaxError, Sortable, Sortables,\n SortableObserver, Sound, Spinner, System, Swiff, Text, TextArea, Template,\n Timer, Tips, Type, TypeError, Toggle, Try, \"use strict\", unescape, URI, URIError, URL,\n VBArray, WSH, WScript, XDomainRequest, Web, Window, XMLDOM, XMLHttpRequest, XMLSerializer,\n XPathEvaluator, XPathException, XPathExpression, XPathNamespace, XPathNSResolver, XPathResult,\n \"\\\\\", a, addEventListener, address, alert, apply, applicationCache, arguments, arity, asi, atob,\n b, basic, basicToken, bitwise, block, blur, boolOptions, boss, browser, btoa, c, call, callee,\n caller, cases, charAt, charCodeAt, character, clearInterval, clearTimeout,\n close, closed, closure, comment, condition, confirm, console, constructor,\n content, couch, create, css, curly, d, data, datalist, dd, debug, decodeURI,\n decodeURIComponent, defaultStatus, defineClass, deserialize, devel, document,\n dojo, dijit, dojox, define, else, emit, encodeURI, encodeURIComponent,\n entityify, eqeqeq, eqnull, errors, es5, escape, esnext, eval, event, evidence, evil,\n ex, exception, exec, exps, expr, exports, FileReader, first, floor, focus,\n forin, fragment, frames, from, fromCharCode, fud, funcscope, funct, function, functions,\n g, gc, getComputedStyle, getRow, getter, getterToken, GLOBAL, global, globals, globalstrict,\n hasOwnProperty, help, history, i, id, identifier, immed, implieds, importPackage, include,\n indent, indexOf, init, ins, instanceOf, isAlpha, isApplicationRunning, isArray,\n isDigit, isFinite, isNaN, iterator, java, join, jshint,\n JSHINT, json, jquery, jQuery, keys, label, labelled, last, lastsemic, laxbreak, laxcomma,\n latedef, lbp, led, left, length, line, load, loadClass, localStorage, location,\n log, loopfunc, m, match, maxerr, maxlen, member,message, meta, module, moveBy,\n moveTo, mootools, multistr, name, navigator, new, newcap, noarg, node, noempty, nomen,\n nonew, nonstandard, nud, onbeforeunload, onblur, onerror, onevar, onecase, onfocus,\n onload, onresize, onunload, open, openDatabase, openURL, opener, opera, options, outer, param,\n parent, parseFloat, parseInt, passfail, plusplus, predef, print, process, prompt,\n proto, prototype, prototypejs, provides, push, quit, range, raw, reach, reason, regexp,\n readFile, readUrl, regexdash, removeEventListener, replace, report, require,\n reserved, resizeBy, resizeTo, resolvePath, resumeUpdates, respond, rhino, right,\n runCommand, scroll, screen, scripturl, scrollBy, scrollTo, scrollbar, search, seal,\n send, serialize, sessionStorage, setInterval, setTimeout, setter, setterToken, shift, slice,\n smarttabs, sort, spawn, split, stack, status, start, strict, sub, substr, supernew, shadow,\n supplant, sum, sync, test, toLowerCase, toString, toUpperCase, toint32, token, top, trailing,\n type, typeOf, Uint16Array, Uint32Array, Uint8Array, undef, undefs, unused, urls, validthis,\n value, valueOf, var, version, WebSocket, withstmt, white, window, Worker, wsh*/\n\n/*global exports: false */\n\n// We build the application inside a function so that we produce only a single\n// global variable. That function will be invoked immediately, and its return\n// value is the JSHINT function itself.\n\nvar JSHINT = (function () {\n    \"use strict\";\n\n    var anonname,       // The guessed name for anonymous functions.\n\n// These are operators that should not be used with the ! operator.\n\n        bang = {\n            '<'  : true,\n            '<=' : true,\n            '==' : true,\n            '===': true,\n            '!==': true,\n            '!=' : true,\n            '>'  : true,\n            '>=' : true,\n            '+'  : true,\n            '-'  : true,\n            '*'  : true,\n            '/'  : true,\n            '%'  : true\n        },\n\n        // These are the JSHint boolean options.\n        boolOptions = {\n            asi         : true, // if automatic semicolon insertion should be tolerated\n            bitwise     : true, // if bitwise operators should not be allowed\n            boss        : true, // if advanced usage of assignments should be allowed\n            browser     : true, // if the standard browser globals should be predefined\n            couch       : true, // if CouchDB globals should be predefined\n            curly       : true, // if curly braces around all blocks should be required\n            debug       : true, // if debugger statements should be allowed\n            devel       : true, // if logging globals should be predefined (console,\n                                // alert, etc.)\n            dojo        : true, // if Dojo Toolkit globals should be predefined\n            eqeqeq      : true, // if === should be required\n            eqnull      : true, // if == null comparisons should be tolerated\n            es5         : true, // if ES5 syntax should be allowed\n            esnext      : true, // if es.next specific syntax should be allowed\n            evil        : true, // if eval should be allowed\n            expr        : true, // if ExpressionStatement should be allowed as Programs\n            forin       : true, // if for in statements must filter\n            funcscope   : true, // if only function scope should be used for scope tests\n            globalstrict: true, // if global \"use strict\"; should be allowed (also\n                                // enables 'strict')\n            immed       : true, // if immediate invocations must be wrapped in parens\n            iterator    : true, // if the `__iterator__` property should be allowed\n            jquery      : true, // if jQuery globals should be predefined\n            lastsemic   : true, // if semicolons may be ommitted for the trailing\n                                // statements inside of a one-line blocks.\n            latedef     : true, // if the use before definition should not be tolerated\n            laxbreak    : true, // if line breaks should not be checked\n            laxcomma    : true, // if line breaks should not be checked around commas\n            loopfunc    : true, // if functions should be allowed to be defined within\n                                // loops\n            mootools    : true, // if MooTools globals should be predefined\n            multistr    : true, // allow multiline strings\n            newcap      : true, // if constructor names must be capitalized\n            noarg       : true, // if arguments.caller and arguments.callee should be\n                                // disallowed\n            node        : true, // if the Node.js environment globals should be\n                                // predefined\n            noempty     : true, // if empty blocks should be disallowed\n            nonew       : true, // if using `new` for side-effects should be disallowed\n            nonstandard : true, // if non-standard (but widely adopted) globals should\n                                // be predefined\n            nomen       : true, // if names should be checked\n            onevar      : true, // if only one var statement per function should be\n                                // allowed\n            onecase     : true, // if one case switch statements should be allowed\n            passfail    : true, // if the scan should stop on first error\n            plusplus    : true, // if increment/decrement should not be allowed\n            proto       : true, // if the `__proto__` property should be allowed\n            prototypejs : true, // if Prototype and Scriptaculous globals should be\n                                // predefined\n            regexdash   : true, // if unescaped first/last dash (-) inside brackets\n                                // should be tolerated\n            regexp      : true, // if the . should not be allowed in regexp literals\n            rhino       : true, // if the Rhino environment globals should be predefined\n            undef       : true, // if variables should be declared before used\n            scripturl   : true, // if script-targeted URLs should be tolerated\n            shadow      : true, // if variable shadowing should be tolerated\n            smarttabs   : true, // if smarttabs should be tolerated\n                                // (http://www.emacswiki.org/emacs/SmartTabs)\n            strict      : true, // require the \"use strict\"; pragma\n            sub         : true, // if all forms of subscript notation are tolerated\n            supernew    : true, // if `new function () { ... };` and `new Object;`\n                                // should be tolerated\n            trailing    : true, // if trailing whitespace rules apply\n            validthis   : true, // if 'this' inside a non-constructor function is valid.\n                                // This is a function scoped option only.\n            withstmt    : true, // if with statements should be allowed\n            white       : true, // if strict whitespace rules apply\n            wsh         : true  // if the Windows Scripting Host environment globals\n                                // should be predefined\n        },\n\n        // These are the JSHint options that can take any value\n        // (we use this object to detect invalid options)\n        valOptions = {\n            maxlen: false,\n            indent: false,\n            maxerr: false,\n            predef: false\n        },\n\n\n        // browser contains a set of global names which are commonly provided by a\n        // web browser environment.\n        browser = {\n            ArrayBuffer              :  false,\n            ArrayBufferView          :  false,\n            Audio                    :  false,\n            addEventListener         :  false,\n            applicationCache         :  false,\n            atob                     :  false,\n            blur                     :  false,\n            btoa                     :  false,\n            clearInterval            :  false,\n            clearTimeout             :  false,\n            close                    :  false,\n            closed                   :  false,\n            DataView                 :  false,\n            DOMParser                :  false,\n            defaultStatus            :  false,\n            document                 :  false,\n            event                    :  false,\n            FileReader               :  false,\n            Float32Array             :  false,\n            Float64Array             :  false,\n            FormData                 :  false,\n            focus                    :  false,\n            frames                   :  false,\n            getComputedStyle         :  false,\n            HTMLElement              :  false,\n            HTMLAnchorElement        :  false,\n            HTMLBaseElement          :  false,\n            HTMLBlockquoteElement    :  false,\n            HTMLBodyElement          :  false,\n            HTMLBRElement            :  false,\n            HTMLButtonElement        :  false,\n            HTMLCanvasElement        :  false,\n            HTMLDirectoryElement     :  false,\n            HTMLDivElement           :  false,\n            HTMLDListElement         :  false,\n            HTMLFieldSetElement      :  false,\n            HTMLFontElement          :  false,\n            HTMLFormElement          :  false,\n            HTMLFrameElement         :  false,\n            HTMLFrameSetElement      :  false,\n            HTMLHeadElement          :  false,\n            HTMLHeadingElement       :  false,\n            HTMLHRElement            :  false,\n            HTMLHtmlElement          :  false,\n            HTMLIFrameElement        :  false,\n            HTMLImageElement         :  false,\n            HTMLInputElement         :  false,\n            HTMLIsIndexElement       :  false,\n            HTMLLabelElement         :  false,\n            HTMLLayerElement         :  false,\n            HTMLLegendElement        :  false,\n            HTMLLIElement            :  false,\n            HTMLLinkElement          :  false,\n            HTMLMapElement           :  false,\n            HTMLMenuElement          :  false,\n            HTMLMetaElement          :  false,\n            HTMLModElement           :  false,\n            HTMLObjectElement        :  false,\n            HTMLOListElement         :  false,\n            HTMLOptGroupElement      :  false,\n            HTMLOptionElement        :  false,\n            HTMLParagraphElement     :  false,\n            HTMLParamElement         :  false,\n            HTMLPreElement           :  false,\n            HTMLQuoteElement         :  false,\n            HTMLScriptElement        :  false,\n            HTMLSelectElement        :  false,\n            HTMLStyleElement         :  false,\n            HTMLTableCaptionElement  :  false,\n            HTMLTableCellElement     :  false,\n            HTMLTableColElement      :  false,\n            HTMLTableElement         :  false,\n            HTMLTableRowElement      :  false,\n            HTMLTableSectionElement  :  false,\n            HTMLTextAreaElement      :  false,\n            HTMLTitleElement         :  false,\n            HTMLUListElement         :  false,\n            HTMLVideoElement         :  false,\n            history                  :  false,\n            Int16Array               :  false,\n            Int32Array               :  false,\n            Int8Array                :  false,\n            Image                    :  false,\n            length                   :  false,\n            localStorage             :  false,\n            location                 :  false,\n            MessageChannel           :  false,\n            MessageEvent             :  false,\n            MessagePort              :  false,\n            moveBy                   :  false,\n            moveTo                   :  false,\n            name                     :  false,\n            navigator                :  false,\n            onbeforeunload           :  true,\n            onblur                   :  true,\n            onerror                  :  true,\n            onfocus                  :  true,\n            onload                   :  true,\n            onresize                 :  true,\n            onunload                 :  true,\n            open                     :  false,\n            openDatabase             :  false,\n            opener                   :  false,\n            Option                   :  false,\n            parent                   :  false,\n            print                    :  false,\n            removeEventListener      :  false,\n            resizeBy                 :  false,\n            resizeTo                 :  false,\n            screen                   :  false,\n            scroll                   :  false,\n            scrollBy                 :  false,\n            scrollTo                 :  false,\n            sessionStorage           :  false,\n            setInterval              :  false,\n            setTimeout               :  false,\n            SharedWorker             :  false,\n            status                   :  false,\n            top                      :  false,\n            Uint16Array              :  false,\n            Uint32Array              :  false,\n            Uint8Array               :  false,\n            WebSocket                :  false,\n            window                   :  false,\n            Worker                   :  false,\n            XMLHttpRequest           :  false,\n            XMLSerializer            :  false,\n            XPathEvaluator           :  false,\n            XPathException           :  false,\n            XPathExpression          :  false,\n            XPathNamespace           :  false,\n            XPathNSResolver          :  false,\n            XPathResult              :  false\n        },\n\n        couch = {\n            \"require\" : false,\n            respond   : false,\n            getRow    : false,\n            emit      : false,\n            send      : false,\n            start     : false,\n            sum       : false,\n            log       : false,\n            exports   : false,\n            module    : false,\n            provides  : false\n        },\n\n        devel = {\n            alert   : false,\n            confirm : false,\n            console : false,\n            Debug   : false,\n            opera   : false,\n            prompt  : false\n        },\n\n        dojo = {\n            dojo      : false,\n            dijit     : false,\n            dojox     : false,\n            define    : false,\n            \"require\" : false\n        },\n\n        escapes = {\n            '\\b': '\\\\b',\n            '\\t': '\\\\t',\n            '\\n': '\\\\n',\n            '\\f': '\\\\f',\n            '\\r': '\\\\r',\n            '\"' : '\\\\\"',\n            '/' : '\\\\/',\n            '\\\\': '\\\\\\\\'\n        },\n\n        funct,          // The current function\n\n        functionicity = [\n            'closure', 'exception', 'global', 'label',\n            'outer', 'unused', 'var'\n        ],\n\n        functions,      // All of the functions\n\n        global,         // The global scope\n        implied,        // Implied globals\n        inblock,\n        indent,\n        jsonmode,\n\n        jquery = {\n            '$'    : false,\n            jQuery : false\n        },\n\n        lines,\n        lookahead,\n        member,\n        membersOnly,\n\n        mootools = {\n            '$'             : false,\n            '$$'            : false,\n            Assets          : false,\n            Browser         : false,\n            Chain           : false,\n            Class           : false,\n            Color           : false,\n            Cookie          : false,\n            Core            : false,\n            Document        : false,\n            DomReady        : false,\n            DOMReady        : false,\n            Drag            : false,\n            Element         : false,\n            Elements        : false,\n            Event           : false,\n            Events          : false,\n            Fx              : false,\n            Group           : false,\n            Hash            : false,\n            HtmlTable       : false,\n            Iframe          : false,\n            IframeShim      : false,\n            InputValidator  : false,\n            instanceOf      : false,\n            Keyboard        : false,\n            Locale          : false,\n            Mask            : false,\n            MooTools        : false,\n            Native          : false,\n            Options         : false,\n            OverText        : false,\n            Request         : false,\n            Scroller        : false,\n            Slick           : false,\n            Slider          : false,\n            Sortables       : false,\n            Spinner         : false,\n            Swiff           : false,\n            Tips            : false,\n            Type            : false,\n            typeOf          : false,\n            URI             : false,\n            Window          : false\n        },\n\n        nexttoken,\n\n        node = {\n            __filename    : false,\n            __dirname     : false,\n            Buffer        : false,\n            console       : false,\n            exports       : false,\n            GLOBAL        : false,\n            global        : false,\n            module        : false,\n            process       : false,\n            require       : false,\n            setTimeout    : false,\n            clearTimeout  : false,\n            setInterval   : false,\n            clearInterval : false\n        },\n\n        noreach,\n        option,\n        predefined,     // Global variables defined by option\n        prereg,\n        prevtoken,\n\n        prototypejs = {\n            '$'               : false,\n            '$$'              : false,\n            '$A'              : false,\n            '$F'              : false,\n            '$H'              : false,\n            '$R'              : false,\n            '$break'          : false,\n            '$continue'       : false,\n            '$w'              : false,\n            Abstract          : false,\n            Ajax              : false,\n            Class             : false,\n            Enumerable        : false,\n            Element           : false,\n            Event             : false,\n            Field             : false,\n            Form              : false,\n            Hash              : false,\n            Insertion         : false,\n            ObjectRange       : false,\n            PeriodicalExecuter: false,\n            Position          : false,\n            Prototype         : false,\n            Selector          : false,\n            Template          : false,\n            Toggle            : false,\n            Try               : false,\n            Autocompleter     : false,\n            Builder           : false,\n            Control           : false,\n            Draggable         : false,\n            Draggables        : false,\n            Droppables        : false,\n            Effect            : false,\n            Sortable          : false,\n            SortableObserver  : false,\n            Sound             : false,\n            Scriptaculous     : false\n        },\n\n        rhino = {\n            defineClass  : false,\n            deserialize  : false,\n            gc           : false,\n            help         : false,\n            importPackage: false,\n            \"java\"       : false,\n            load         : false,\n            loadClass    : false,\n            print        : false,\n            quit         : false,\n            readFile     : false,\n            readUrl      : false,\n            runCommand   : false,\n            seal         : false,\n            serialize    : false,\n            spawn        : false,\n            sync         : false,\n            toint32      : false,\n            version      : false\n        },\n\n        scope,      // The current scope\n        stack,\n\n        // standard contains the global names that are provided by the\n        // ECMAScript standard.\n        standard = {\n            Array               : false,\n            Boolean             : false,\n            Date                : false,\n            decodeURI           : false,\n            decodeURIComponent  : false,\n            encodeURI           : false,\n            encodeURIComponent  : false,\n            Error               : false,\n            'eval'              : false,\n            EvalError           : false,\n            Function            : false,\n            hasOwnProperty      : false,\n            isFinite            : false,\n            isNaN               : false,\n            JSON                : false,\n            Math                : false,\n            Number              : false,\n            Object              : false,\n            parseInt            : false,\n            parseFloat          : false,\n            RangeError          : false,\n            ReferenceError      : false,\n            RegExp              : false,\n            String              : false,\n            SyntaxError         : false,\n            TypeError           : false,\n            URIError            : false\n        },\n\n        // widely adopted global names that are not part of ECMAScript standard\n        nonstandard = {\n            escape              : false,\n            unescape            : false\n        },\n\n        standard_member = {\n            E                   : true,\n            LN2                 : true,\n            LN10                : true,\n            LOG2E               : true,\n            LOG10E              : true,\n            MAX_VALUE           : true,\n            MIN_VALUE           : true,\n            NEGATIVE_INFINITY   : true,\n            PI                  : true,\n            POSITIVE_INFINITY   : true,\n            SQRT1_2             : true,\n            SQRT2               : true\n        },\n\n        directive,\n        syntax = {},\n        tab,\n        token,\n        urls,\n        useESNextSyntax,\n        warnings,\n\n        wsh = {\n            ActiveXObject             : true,\n            Enumerator                : true,\n            GetObject                 : true,\n            ScriptEngine              : true,\n            ScriptEngineBuildVersion  : true,\n            ScriptEngineMajorVersion  : true,\n            ScriptEngineMinorVersion  : true,\n            VBArray                   : true,\n            WSH                       : true,\n            WScript                   : true,\n            XDomainRequest            : true\n        };\n\n    // Regular expressions. Some of these are stupidly long.\n    var ax, cx, tx, nx, nxg, lx, ix, jx, ft;\n    (function () {\n        /*jshint maxlen:300 */\n\n        // unsafe comment or string\n        ax = /@cc|<\\/?|script|\\]\\s*\\]|<\\s*!|&lt/i;\n\n        // unsafe characters that are silently deleted by one or more browsers\n        cx = /[\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/;\n\n        // token\n        tx = /^\\s*([(){}\\[.,:;'\"~\\?\\]#@]|==?=?|\\/(\\*(jshint|jslint|members?|global)?|=|\\/)?|\\*[\\/=]?|\\+(?:=|\\++)?|-(?:=|-+)?|%=?|&[&=]?|\\|[|=]?|>>?>?=?|<([\\/=!]|\\!(\\[|--)?|<=?)?|\\^=?|\\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\\.[0-9]*)?([eE][+\\-]?[0-9]+)?)/;\n\n        // characters in strings that need escapement\n        nx = /[\\u0000-\\u001f&<\"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/;\n        nxg = /[\\u0000-\\u001f&<\"\\/\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g;\n\n        // star slash\n        lx = /\\*\\/|\\/\\*/;\n\n        // identifier\n        ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;\n\n        // javascript url\n        jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\\s*:/i;\n\n        // catches /* falls through */ comments\n        ft = /^\\s*\\/\\*\\s*falls\\sthrough\\s*\\*\\/\\s*$/;\n    }());\n\n    function F() {}     // Used by Object.create\n\n    function is_own(object, name) {\n\n// The object.hasOwnProperty method fails when the property under consideration\n// is named 'hasOwnProperty'. So we have to use this more convoluted form.\n\n        return Object.prototype.hasOwnProperty.call(object, name);\n    }\n\n    function checkOption(name, t) {\n        if (valOptions[name] === undefined && boolOptions[name] === undefined) {\n            warning(\"Bad option: '\" + name + \"'.\", t);\n        }\n    }\n\n// Provide critical ES5 functions to ES3.\n\n    if (typeof Array.isArray !== 'function') {\n        Array.isArray = function (o) {\n            return Object.prototype.toString.apply(o) === '[object Array]';\n        };\n    }\n\n    if (typeof Object.create !== 'function') {\n        Object.create = function (o) {\n            F.prototype = o;\n            return new F();\n        };\n    }\n\n    if (typeof Object.keys !== 'function') {\n        Object.keys = function (o) {\n            var a = [], k;\n            for (k in o) {\n                if (is_own(o, k)) {\n                    a.push(k);\n                }\n            }\n            return a;\n        };\n    }\n\n// Non standard methods\n\n    if (typeof String.prototype.entityify !== 'function') {\n        String.prototype.entityify = function () {\n            return this\n                .replace(/&/g, '&amp;')\n                .replace(/</g, '&lt;')\n                .replace(/>/g, '&gt;');\n        };\n    }\n\n    if (typeof String.prototype.isAlpha !== 'function') {\n        String.prototype.isAlpha = function () {\n            return (this >= 'a' && this <= 'z\\uffff') ||\n                (this >= 'A' && this <= 'Z\\uffff');\n        };\n    }\n\n    if (typeof String.prototype.isDigit !== 'function') {\n        String.prototype.isDigit = function () {\n            return (this >= '0' && this <= '9');\n        };\n    }\n\n    if (typeof String.prototype.supplant !== 'function') {\n        String.prototype.supplant = function (o) {\n            return this.replace(/\\{([^{}]*)\\}/g, function (a, b) {\n                var r = o[b];\n                return typeof r === 'string' || typeof r === 'number' ? r : a;\n            });\n        };\n    }\n\n    if (typeof String.prototype.name !== 'function') {\n        String.prototype.name = function () {\n\n// If the string looks like an identifier, then we can return it as is.\n// If the string contains no control characters, no quote characters, and no\n// backslash characters, then we can simply slap some quotes around it.\n// Otherwise we must also replace the offending characters with safe\n// sequences.\n\n            if (ix.test(this)) {\n                return this;\n            }\n            if (nx.test(this)) {\n                return '\"' + this.replace(nxg, function (a) {\n                    var c = escapes[a];\n                    if (c) {\n                        return c;\n                    }\n                    return '\\\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);\n                }) + '\"';\n            }\n            return '\"' + this + '\"';\n        };\n    }\n\n\n    function combine(t, o) {\n        var n;\n        for (n in o) {\n            if (is_own(o, n)) {\n                t[n] = o[n];\n            }\n        }\n    }\n\n    function assume() {\n        if (option.couch) {\n            combine(predefined, couch);\n        }\n\n        if (option.rhino) {\n            combine(predefined, rhino);\n        }\n\n        if (option.prototypejs) {\n            combine(predefined, prototypejs);\n        }\n\n        if (option.node) {\n            combine(predefined, node);\n            option.globalstrict = true;\n        }\n\n        if (option.devel) {\n            combine(predefined, devel);\n        }\n\n        if (option.dojo) {\n            combine(predefined, dojo);\n        }\n\n        if (option.browser) {\n            combine(predefined, browser);\n        }\n\n        if (option.nonstandard) {\n            combine(predefined, nonstandard);\n        }\n\n        if (option.jquery) {\n            combine(predefined, jquery);\n        }\n\n        if (option.mootools) {\n            combine(predefined, mootools);\n        }\n\n        if (option.wsh) {\n            combine(predefined, wsh);\n        }\n\n        if (option.esnext) {\n            useESNextSyntax();\n        }\n\n        if (option.globalstrict && option.strict !== false) {\n            option.strict = true;\n        }\n    }\n\n\n    // Produce an error warning.\n    function quit(message, line, chr) {\n        var percentage = Math.floor((line / lines.length) * 100);\n\n        throw {\n            name: 'JSHintError',\n            line: line,\n            character: chr,\n            message: message + \" (\" + percentage + \"% scanned).\",\n            raw: message\n        };\n    }\n\n    function isundef(scope, m, t, a) {\n        return JSHINT.undefs.push([scope, m, t, a]);\n    }\n\n    function warning(m, t, a, b, c, d) {\n        var ch, l, w;\n        t = t || nexttoken;\n        if (t.id === '(end)') {  // `~\n            t = token;\n        }\n        l = t.line || 0;\n        ch = t.from || 0;\n        w = {\n            id: '(error)',\n            raw: m,\n            evidence: lines[l - 1] || '',\n            line: l,\n            character: ch,\n            a: a,\n            b: b,\n            c: c,\n            d: d\n        };\n        w.reason = m.supplant(w);\n        JSHINT.errors.push(w);\n        if (option.passfail) {\n            quit('Stopping. ', l, ch);\n        }\n        warnings += 1;\n        if (warnings >= option.maxerr) {\n            quit(\"Too many errors.\", l, ch);\n        }\n        return w;\n    }\n\n    function warningAt(m, l, ch, a, b, c, d) {\n        return warning(m, {\n            line: l,\n            from: ch\n        }, a, b, c, d);\n    }\n\n    function error(m, t, a, b, c, d) {\n        var w = warning(m, t, a, b, c, d);\n    }\n\n    function errorAt(m, l, ch, a, b, c, d) {\n        return error(m, {\n            line: l,\n            from: ch\n        }, a, b, c, d);\n    }\n\n\n\n// lexical analysis and token construction\n\n    var lex = (function lex() {\n        var character, from, line, s;\n\n// Private lex methods\n\n        function nextLine() {\n            var at,\n                tw; // trailing whitespace check\n\n            if (line >= lines.length)\n                return false;\n\n            character = 1;\n            s = lines[line];\n            line += 1;\n\n            // If smarttabs option is used check for spaces followed by tabs only.\n            // Otherwise check for any occurence of mixed tabs and spaces.\n            if (option.smarttabs)\n                at = s.search(/ \\t/);\n            else\n                at = s.search(/ \\t|\\t /);\n\n            if (at >= 0)\n                warningAt(\"Mixed spaces and tabs.\", line, at + 1);\n\n            s = s.replace(/\\t/g, tab);\n            at = s.search(cx);\n\n            if (at >= 0)\n                warningAt(\"Unsafe character.\", line, at);\n\n            if (option.maxlen && option.maxlen < s.length)\n                warningAt(\"Line too long.\", line, s.length);\n\n            // Check for trailing whitespaces\n            tw = option.trailing && s.match(/^(.*?)\\s+$/);\n            if (tw && !/^\\s+$/.test(s)) {\n                warningAt(\"Trailing whitespace.\", line, tw[1].length + 1);\n            }\n            return true;\n        }\n\n// Produce a token object.  The token inherits from a syntax symbol.\n\n        function it(type, value) {\n            var i, t;\n            if (type === '(color)' || type === '(range)') {\n                t = {type: type};\n            } else if (type === '(punctuator)' ||\n                    (type === '(identifier)' && is_own(syntax, value))) {\n                t = syntax[value] || syntax['(error)'];\n            } else {\n                t = syntax[type];\n            }\n            t = Object.create(t);\n            if (type === '(string)' || type === '(range)') {\n                if (!option.scripturl && jx.test(value)) {\n                    warningAt(\"Script URL.\", line, from);\n                }\n            }\n            if (type === '(identifier)') {\n                t.identifier = true;\n                if (value === '__proto__' && !option.proto) {\n                    warningAt(\"The '{a}' property is deprecated.\",\n                        line, from, value);\n                } else if (value === '__iterator__' && !option.iterator) {\n                    warningAt(\"'{a}' is only available in JavaScript 1.7.\",\n                        line, from, value);\n                } else if (option.nomen && (value.charAt(0) === '_' ||\n                         value.charAt(value.length - 1) === '_')) {\n                    if (!option.node || token.id === '.' ||\n                            (value !== '__dirname' && value !== '__filename')) {\n                        warningAt(\"Unexpected {a} in '{b}'.\", line, from, \"dangling '_'\", value);\n                    }\n                }\n            }\n            t.value = value;\n            t.line = line;\n            t.character = character;\n            t.from = from;\n            i = t.id;\n            if (i !== '(endline)') {\n                prereg = i &&\n                    (('(,=:[!&|?{};'.indexOf(i.charAt(i.length - 1)) >= 0) ||\n                    i === 'return' ||\n                    i === 'case');\n            }\n            return t;\n        }\n\n        // Public lex methods\n        return {\n            init: function (source) {\n                if (typeof source === 'string') {\n                    lines = source\n                        .replace(/\\r\\n/g, '\\n')\n                        .replace(/\\r/g, '\\n')\n                        .split('\\n');\n                } else {\n                    lines = source;\n                }\n\n                // If the first line is a shebang (#!), make it a blank and move on.\n                // Shebangs are used by Node scripts.\n                if (lines[0] && lines[0].substr(0, 2) === '#!')\n                    lines[0] = '';\n\n                line = 0;\n                nextLine();\n                from = 1;\n            },\n\n            range: function (begin, end) {\n                var c, value = '';\n                from = character;\n                if (s.charAt(0) !== begin) {\n                    errorAt(\"Expected '{a}' and instead saw '{b}'.\",\n                            line, character, begin, s.charAt(0));\n                }\n                for (;;) {\n                    s = s.slice(1);\n                    character += 1;\n                    c = s.charAt(0);\n                    switch (c) {\n                    case '':\n                        errorAt(\"Missing '{a}'.\", line, character, c);\n                        break;\n                    case end:\n                        s = s.slice(1);\n                        character += 1;\n                        return it('(range)', value);\n                    case '\\\\':\n                        warningAt(\"Unexpected '{a}'.\", line, character, c);\n                    }\n                    value += c;\n                }\n\n            },\n\n\n            // token -- this is called by advance to get the next token\n            token: function () {\n                var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange, n;\n\n                function match(x) {\n                    var r = x.exec(s), r1;\n                    if (r) {\n                        l = r[0].length;\n                        r1 = r[1];\n                        c = r1.charAt(0);\n                        s = s.substr(l);\n                        from = character + l - r1.length;\n                        character += l;\n                        return r1;\n                    }\n                }\n\n                function string(x) {\n                    var c, j, r = '', allowNewLine = false;\n\n                    if (jsonmode && x !== '\"') {\n                        warningAt(\"Strings must use doublequote.\",\n                                line, character);\n                    }\n\n                    function esc(n) {\n                        var i = parseInt(s.substr(j + 1, n), 16);\n                        j += n;\n                        if (i >= 32 && i <= 126 &&\n                                i !== 34 && i !== 92 && i !== 39) {\n                            warningAt(\"Unnecessary escapement.\", line, character);\n                        }\n                        character += n;\n                        c = String.fromCharCode(i);\n                    }\n                    j = 0;\nunclosedString:     for (;;) {\n                        while (j >= s.length) {\n                            j = 0;\n\n                            var cl = line, cf = from;\n                            if (!nextLine()) {\n                                errorAt(\"Unclosed string.\", cl, cf);\n                                break unclosedString;\n                            }\n\n                            if (allowNewLine) {\n                                allowNewLine = false;\n                            } else {\n                                warningAt(\"Unclosed string.\", cl, cf);\n                            }\n                        }\n                        c = s.charAt(j);\n                        if (c === x) {\n                            character += 1;\n                            s = s.substr(j + 1);\n                            return it('(string)', r, x);\n                        }\n                        if (c < ' ') {\n                            if (c === '\\n' || c === '\\r') {\n                                break;\n                            }\n                            warningAt(\"Control character in string: {a}.\",\n                                    line, character + j, s.slice(0, j));\n                        } else if (c === '\\\\') {\n                            j += 1;\n                            character += 1;\n                            c = s.charAt(j);\n                            n = s.charAt(j + 1);\n                            switch (c) {\n                            case '\\\\':\n                            case '\"':\n                            case '/':\n                                break;\n                            case '\\'':\n                                if (jsonmode) {\n                                    warningAt(\"Avoid \\\\'.\", line, character);\n                                }\n                                break;\n                            case 'b':\n                                c = '\\b';\n                                break;\n                            case 'f':\n                                c = '\\f';\n                                break;\n                            case 'n':\n                                c = '\\n';\n                                break;\n                            case 'r':\n                                c = '\\r';\n                                break;\n                            case 't':\n                                c = '\\t';\n                                break;\n                            case '0':\n                                c = '\\0';\n                                // Octal literals fail in strict mode\n                                // check if the number is between 00 and 07\n                                // where 'n' is the token next to 'c'\n                                if (n >= 0 && n <= 7 && directive[\"use strict\"]) {\n                                    warningAt(\n                                    \"Octal literals are not allowed in strict mode.\",\n                                    line, character);\n                                }\n                                break;\n                            case 'u':\n                                esc(4);\n                                break;\n                            case 'v':\n                                if (jsonmode) {\n                                    warningAt(\"Avoid \\\\v.\", line, character);\n                                }\n                                c = '\\v';\n                                break;\n                            case 'x':\n                                if (jsonmode) {\n                                    warningAt(\"Avoid \\\\x-.\", line, character);\n                                }\n                                esc(2);\n                                break;\n                            case '':\n                                // last character is escape character\n                                // always allow new line if escaped, but show\n                                // warning if option is not set\n                                allowNewLine = true;\n                                if (option.multistr) {\n                                    if (jsonmode) {\n                                        warningAt(\"Avoid EOL escapement.\", line, character);\n                                    }\n                                    c = '';\n                                    character -= 1;\n                                    break;\n                                }\n                                warningAt(\"Bad escapement of EOL. Use option multistr if needed.\",\n                                    line, character);\n                                break;\n                            default:\n                                warningAt(\"Bad escapement.\", line, character);\n                            }\n                        }\n                        r += c;\n                        character += 1;\n                        j += 1;\n                    }\n                }\n\n                for (;;) {\n                    if (!s) {\n                        return it(nextLine() ? '(endline)' : '(end)', '');\n                    }\n                    t = match(tx);\n                    if (!t) {\n                        t = '';\n                        c = '';\n                        while (s && s < '!') {\n                            s = s.substr(1);\n                        }\n                        if (s) {\n                            errorAt(\"Unexpected '{a}'.\", line, character, s.substr(0, 1));\n                            s = '';\n                        }\n                    } else {\n\n    //      identifier\n\n                        if (c.isAlpha() || c === '_' || c === '$') {\n                            return it('(identifier)', t);\n                        }\n\n    //      number\n\n                        if (c.isDigit()) {\n                            if (!isFinite(Number(t))) {\n                                warningAt(\"Bad number '{a}'.\",\n                                    line, character, t);\n                            }\n                            if (s.substr(0, 1).isAlpha()) {\n                                warningAt(\"Missing space after '{a}'.\",\n                                        line, character, t);\n                            }\n                            if (c === '0') {\n                                d = t.substr(1, 1);\n                                if (d.isDigit()) {\n                                    if (token.id !== '.') {\n                                        warningAt(\"Don't use extra leading zeros '{a}'.\",\n                                            line, character, t);\n                                    }\n                                } else if (jsonmode && (d === 'x' || d === 'X')) {\n                                    warningAt(\"Avoid 0x-. '{a}'.\",\n                                            line, character, t);\n                                }\n                            }\n                            if (t.substr(t.length - 1) === '.') {\n                                warningAt(\n\"A trailing decimal point can be confused with a dot '{a}'.\", line, character, t);\n                            }\n                            return it('(number)', t);\n                        }\n                        switch (t) {\n\n    //      string\n\n                        case '\"':\n                        case \"'\":\n                            return string(t);\n\n    //      // comment\n\n                        case '//':\n                            s = '';\n                            token.comment = true;\n                            break;\n\n    //      /* comment\n\n                        case '/*':\n                            for (;;) {\n                                i = s.search(lx);\n                                if (i >= 0) {\n                                    break;\n                                }\n                                if (!nextLine()) {\n                                    errorAt(\"Unclosed comment.\", line, character);\n                                }\n                            }\n                            character += i + 2;\n                            if (s.substr(i, 1) === '/') {\n                                errorAt(\"Nested comment.\", line, character);\n                            }\n                            s = s.substr(i + 2);\n                            token.comment = true;\n                            break;\n\n    //      /*members /*jshint /*global\n\n                        case '/*members':\n                        case '/*member':\n                        case '/*jshint':\n                        case '/*jslint':\n                        case '/*global':\n                        case '*/':\n                            return {\n                                value: t,\n                                type: 'special',\n                                line: line,\n                                character: character,\n                                from: from\n                            };\n\n                        case '':\n                            break;\n    //      /\n                        case '/':\n                            if (token.id === '/=') {\n                                errorAt(\"A regular expression literal can be confused with '/='.\",\n                                    line, from);\n                            }\n                            if (prereg) {\n                                depth = 0;\n                                captures = 0;\n                                l = 0;\n                                for (;;) {\n                                    b = true;\n                                    c = s.charAt(l);\n                                    l += 1;\n                                    switch (c) {\n                                    case '':\n                                        errorAt(\"Unclosed regular expression.\", line, from);\n                                        return quit('Stopping.', line, from);\n                                    case '/':\n                                        if (depth > 0) {\n                                            warningAt(\"{a} unterminated regular expression \" +\n                                                \"group(s).\", line, from + l, depth);\n                                        }\n                                        c = s.substr(0, l - 1);\n                                        q = {\n                                            g: true,\n                                            i: true,\n                                            m: true\n                                        };\n                                        while (q[s.charAt(l)] === true) {\n                                            q[s.charAt(l)] = false;\n                                            l += 1;\n                                        }\n                                        character += l;\n                                        s = s.substr(l);\n                                        q = s.charAt(0);\n                                        if (q === '/' || q === '*') {\n                                            errorAt(\"Confusing regular expression.\",\n                                                    line, from);\n                                        }\n                                        return it('(regexp)', c);\n                                    case '\\\\':\n                                        c = s.charAt(l);\n                                        if (c < ' ') {\n                                            warningAt(\n\"Unexpected control character in regular expression.\", line, from + l);\n                                        } else if (c === '<') {\n                                            warningAt(\n\"Unexpected escaped character '{a}' in regular expression.\", line, from + l, c);\n                                        }\n                                        l += 1;\n                                        break;\n                                    case '(':\n                                        depth += 1;\n                                        b = false;\n                                        if (s.charAt(l) === '?') {\n                                            l += 1;\n                                            switch (s.charAt(l)) {\n                                            case ':':\n                                            case '=':\n                                            case '!':\n                                                l += 1;\n                                                break;\n                                            default:\n                                                warningAt(\n\"Expected '{a}' and instead saw '{b}'.\", line, from + l, ':', s.charAt(l));\n                                            }\n                                        } else {\n                                            captures += 1;\n                                        }\n                                        break;\n                                    case '|':\n                                        b = false;\n                                        break;\n                                    case ')':\n                                        if (depth === 0) {\n                                            warningAt(\"Unescaped '{a}'.\",\n                                                    line, from + l, ')');\n                                        } else {\n                                            depth -= 1;\n                                        }\n                                        break;\n                                    case ' ':\n                                        q = 1;\n                                        while (s.charAt(l) === ' ') {\n                                            l += 1;\n                                            q += 1;\n                                        }\n                                        if (q > 1) {\n                                            warningAt(\n\"Spaces are hard to count. Use {{a}}.\", line, from + l, q);\n                                        }\n                                        break;\n                                    case '[':\n                                        c = s.charAt(l);\n                                        if (c === '^') {\n                                            l += 1;\n                                            if (option.regexp) {\n                                                warningAt(\"Insecure '{a}'.\",\n                                                        line, from + l, c);\n                                            } else if (s.charAt(l) === ']') {\n                                                errorAt(\"Unescaped '{a}'.\",\n                                                    line, from + l, '^');\n                                            }\n                                        }\n                                        if (c === ']') {\n                                            warningAt(\"Empty class.\", line,\n                                                    from + l - 1);\n                                        }\n                                        isLiteral = false;\n                                        isInRange = false;\nklass:                                  do {\n                                            c = s.charAt(l);\n                                            l += 1;\n                                            switch (c) {\n                                            case '[':\n                                            case '^':\n                                                warningAt(\"Unescaped '{a}'.\",\n                                                        line, from + l, c);\n                                                if (isInRange) {\n                                                    isInRange = false;\n                                                } else {\n                                                    isLiteral = true;\n                                                }\n                                                break;\n                                            case '-':\n                                                if (isLiteral && !isInRange) {\n                                                    isLiteral = false;\n                                                    isInRange = true;\n                                                } else if (isInRange) {\n                                                    isInRange = false;\n                                                } else if (s.charAt(l) === ']') {\n                                                    isInRange = true;\n                                                } else {\n                                                    if (option.regexdash !== (l === 2 || (l === 3 &&\n                                                        s.charAt(1) === '^'))) {\n                                                        warningAt(\"Unescaped '{a}'.\",\n                                                            line, from + l - 1, '-');\n                                                    }\n                                                    isLiteral = true;\n                                                }\n                                                break;\n                                            case ']':\n                                                if (isInRange && !option.regexdash) {\n                                                    warningAt(\"Unescaped '{a}'.\",\n                                                            line, from + l - 1, '-');\n                                                }\n                                                break klass;\n                                            case '\\\\':\n                                                c = s.charAt(l);\n                                                if (c < ' ') {\n                                                    warningAt(\n\"Unexpected control character in regular expression.\", line, from + l);\n                                                } else if (c === '<') {\n                                                    warningAt(\n\"Unexpected escaped character '{a}' in regular expression.\", line, from + l, c);\n                                                }\n                                                l += 1;\n\n                                                // \\w, \\s and \\d are never part of a character range\n                                                if (/[wsd]/i.test(c)) {\n                                                    if (isInRange) {\n                                                        warningAt(\"Unescaped '{a}'.\",\n                                                            line, from + l, '-');\n                                                        isInRange = false;\n                                                    }\n                                                    isLiteral = false;\n                                                } else if (isInRange) {\n                                                    isInRange = false;\n                                                } else {\n                                                    isLiteral = true;\n                                                }\n                                                break;\n                                            case '/':\n                                                warningAt(\"Unescaped '{a}'.\",\n                                                        line, from + l - 1, '/');\n\n                                                if (isInRange) {\n                                                    isInRange = false;\n                                                } else {\n                                                    isLiteral = true;\n                                                }\n                                                break;\n                                            case '<':\n                                                if (isInRange) {\n                                                    isInRange = false;\n                                                } else {\n                                                    isLiteral = true;\n                                                }\n                                                break;\n                                            default:\n                                                if (isInRange) {\n                                                    isInRange = false;\n                                                } else {\n                                                    isLiteral = true;\n                                                }\n                                            }\n                                        } while (c);\n                                        break;\n                                    case '.':\n                                        if (option.regexp) {\n                                            warningAt(\"Insecure '{a}'.\", line,\n                                                    from + l, c);\n                                        }\n                                        break;\n                                    case ']':\n                                    case '?':\n                                    case '{':\n                                    case '}':\n                                    case '+':\n                                    case '*':\n                                        warningAt(\"Unescaped '{a}'.\", line,\n                                                from + l, c);\n                                    }\n                                    if (b) {\n                                        switch (s.charAt(l)) {\n                                        case '?':\n                                        case '+':\n                                        case '*':\n                                            l += 1;\n                                            if (s.charAt(l) === '?') {\n                                                l += 1;\n                                            }\n                                            break;\n                                        case '{':\n                                            l += 1;\n                                            c = s.charAt(l);\n                                            if (c < '0' || c > '9') {\n                                                warningAt(\n\"Expected a number and instead saw '{a}'.\", line, from + l, c);\n                                            }\n                                            l += 1;\n                                            low = +c;\n                                            for (;;) {\n                                                c = s.charAt(l);\n                                                if (c < '0' || c > '9') {\n                                                    break;\n                                                }\n                                                l += 1;\n                                                low = +c + (low * 10);\n                                            }\n                                            high = low;\n                                            if (c === ',') {\n                                                l += 1;\n                                                high = Infinity;\n                                                c = s.charAt(l);\n                                                if (c >= '0' && c <= '9') {\n                                                    l += 1;\n                                                    high = +c;\n                                                    for (;;) {\n                                                        c = s.charAt(l);\n                                                        if (c < '0' || c > '9') {\n                                                            break;\n                                                        }\n                                                        l += 1;\n                                                        high = +c + (high * 10);\n                                                    }\n                                                }\n                                            }\n                                            if (s.charAt(l) !== '}') {\n                                                warningAt(\n\"Expected '{a}' and instead saw '{b}'.\", line, from + l, '}', c);\n                                            } else {\n                                                l += 1;\n                                            }\n                                            if (s.charAt(l) === '?') {\n                                                l += 1;\n                                            }\n                                            if (low > high) {\n                                                warningAt(\n\"'{a}' should not be greater than '{b}'.\", line, from + l, low, high);\n                                            }\n                                        }\n                                    }\n                                }\n                                c = s.substr(0, l - 1);\n                                character += l;\n                                s = s.substr(l);\n                                return it('(regexp)', c);\n                            }\n                            return it('(punctuator)', t);\n\n    //      punctuator\n\n                        case '#':\n                            return it('(punctuator)', t);\n                        default:\n                            return it('(punctuator)', t);\n                        }\n                    }\n                }\n            }\n        };\n    }());\n\n\n    function addlabel(t, type) {\n\n        if (t === 'hasOwnProperty') {\n            warning(\"'hasOwnProperty' is a really bad name.\");\n        }\n\n// Define t in the current function in the current scope.\n        if (is_own(funct, t) && !funct['(global)']) {\n            if (funct[t] === true) {\n                if (option.latedef)\n                    warning(\"'{a}' was used before it was defined.\", nexttoken, t);\n            } else {\n                if (!option.shadow && type !== \"exception\")\n                    warning(\"'{a}' is already defined.\", nexttoken, t);\n            }\n        }\n\n        funct[t] = type;\n        if (funct['(global)']) {\n            global[t] = funct;\n            if (is_own(implied, t)) {\n                if (option.latedef)\n                    warning(\"'{a}' was used before it was defined.\", nexttoken, t);\n                delete implied[t];\n            }\n        } else {\n            scope[t] = funct;\n        }\n    }\n\n\n    function doOption() {\n        var b, obj, filter, o = nexttoken.value, t, v;\n\n        switch (o) {\n        case '*/':\n            error(\"Unbegun comment.\");\n            break;\n        case '/*members':\n        case '/*member':\n            o = '/*members';\n            if (!membersOnly) {\n                membersOnly = {};\n            }\n            obj = membersOnly;\n            break;\n        case '/*jshint':\n        case '/*jslint':\n            obj = option;\n            filter = boolOptions;\n            break;\n        case '/*global':\n            obj = predefined;\n            break;\n        default:\n            error(\"What?\");\n        }\n\n        t = lex.token();\nloop:   for (;;) {\n            for (;;) {\n                if (t.type === 'special' && t.value === '*/') {\n                    break loop;\n                }\n                if (t.id !== '(endline)' && t.id !== ',') {\n                    break;\n                }\n                t = lex.token();\n            }\n            if (t.type !== '(string)' && t.type !== '(identifier)' &&\n                    o !== '/*members') {\n                error(\"Bad option.\", t);\n            }\n\n            v = lex.token();\n            if (v.id === ':') {\n                v = lex.token();\n\n                if (obj === membersOnly) {\n                    error(\"Expected '{a}' and instead saw '{b}'.\",\n                            t, '*/', ':');\n                }\n\n                if (o === '/*jshint') {\n                    checkOption(t.value, t);\n                }\n\n                if (t.value === 'indent' && (o === '/*jshint' || o === '/*jslint')) {\n                    b = +v.value;\n                    if (typeof b !== 'number' || !isFinite(b) || b <= 0 ||\n                            Math.floor(b) !== b) {\n                        error(\"Expected a small integer and instead saw '{a}'.\",\n                                v, v.value);\n                    }\n                    obj.white = true;\n                    obj.indent = b;\n                } else if (t.value === 'maxerr' && (o === '/*jshint' || o === '/*jslint')) {\n                    b = +v.value;\n                    if (typeof b !== 'number' || !isFinite(b) || b <= 0 ||\n                            Math.floor(b) !== b) {\n                        error(\"Expected a small integer and instead saw '{a}'.\",\n                                v, v.value);\n                    }\n                    obj.maxerr = b;\n                } else if (t.value === 'maxlen' && (o === '/*jshint' || o === '/*jslint')) {\n                    b = +v.value;\n                    if (typeof b !== 'number' || !isFinite(b) || b <= 0 ||\n                            Math.floor(b) !== b) {\n                        error(\"Expected a small integer and instead saw '{a}'.\",\n                                v, v.value);\n                    }\n                    obj.maxlen = b;\n                } else if (t.value === 'validthis') {\n                    if (funct['(global)']) {\n                        error(\"Option 'validthis' can't be used in a global scope.\");\n                    } else {\n                        if (v.value === 'true' || v.value === 'false')\n                            obj[t.value] = v.value === 'true';\n                        else\n                            error(\"Bad option value.\", v);\n                    }\n                } else if (v.value === 'true') {\n                    obj[t.value] = true;\n                } else if (v.value === 'false') {\n                    obj[t.value] = false;\n                } else {\n                    error(\"Bad option value.\", v);\n                }\n                t = lex.token();\n            } else {\n                if (o === '/*jshint' || o === '/*jslint') {\n                    error(\"Missing option value.\", t);\n                }\n                obj[t.value] = false;\n                t = v;\n            }\n        }\n        if (filter) {\n            assume();\n        }\n    }\n\n\n// We need a peek function. If it has an argument, it peeks that much farther\n// ahead. It is used to distinguish\n//     for ( var i in ...\n// from\n//     for ( var i = ...\n\n    function peek(p) {\n        var i = p || 0, j = 0, t;\n\n        while (j <= i) {\n            t = lookahead[j];\n            if (!t) {\n                t = lookahead[j] = lex.token();\n            }\n            j += 1;\n        }\n        return t;\n    }\n\n\n\n// Produce the next token. It looks for programming errors.\n\n    function advance(id, t) {\n        switch (token.id) {\n        case '(number)':\n            if (nexttoken.id === '.') {\n                warning(\"A dot following a number can be confused with a decimal point.\", token);\n            }\n            break;\n        case '-':\n            if (nexttoken.id === '-' || nexttoken.id === '--') {\n                warning(\"Confusing minusses.\");\n            }\n            break;\n        case '+':\n            if (nexttoken.id === '+' || nexttoken.id === '++') {\n                warning(\"Confusing plusses.\");\n            }\n            break;\n        }\n\n        if (token.type === '(string)' || token.identifier) {\n            anonname = token.value;\n        }\n\n        if (id && nexttoken.id !== id) {\n            if (t) {\n                if (nexttoken.id === '(end)') {\n                    warning(\"Unmatched '{a}'.\", t, t.id);\n                } else {\n                    warning(\"Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.\",\n                            nexttoken, id, t.id, t.line, nexttoken.value);\n                }\n            } else if (nexttoken.type !== '(identifier)' ||\n                            nexttoken.value !== id) {\n                warning(\"Expected '{a}' and instead saw '{b}'.\",\n                        nexttoken, id, nexttoken.value);\n            }\n        }\n\n        prevtoken = token;\n        token = nexttoken;\n        for (;;) {\n            nexttoken = lookahead.shift() || lex.token();\n            if (nexttoken.id === '(end)' || nexttoken.id === '(error)') {\n                return;\n            }\n            if (nexttoken.type === 'special') {\n                doOption();\n            } else {\n                if (nexttoken.id !== '(endline)') {\n                    break;\n                }\n            }\n        }\n    }\n\n\n// This is the heart of JSHINT, the Pratt parser. In addition to parsing, it\n// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is\n// like .nud except that it is only used on the first token of a statement.\n// Having .fud makes it much easier to define statement-oriented languages like\n// JavaScript. I retained Pratt's nomenclature.\n\n// .nud     Null denotation\n// .fud     First null denotation\n// .led     Left denotation\n//  lbp     Left binding power\n//  rbp     Right binding power\n\n// They are elements of the parsing method called Top Down Operator Precedence.\n\n    function expression(rbp, initial) {\n        var left, isArray = false, isObject = false;\n\n        if (nexttoken.id === '(end)')\n            error(\"Unexpected early end of program.\", token);\n\n        advance();\n        if (initial) {\n            anonname = 'anonymous';\n            funct['(verb)'] = token.value;\n        }\n        if (initial === true && token.fud) {\n            left = token.fud();\n        } else {\n            if (token.nud) {\n                left = token.nud();\n            } else {\n                if (nexttoken.type === '(number)' && token.id === '.') {\n                    warning(\"A leading decimal point can be confused with a dot: '.{a}'.\",\n                            token, nexttoken.value);\n                    advance();\n                    return token;\n                } else {\n                    error(\"Expected an identifier and instead saw '{a}'.\",\n                            token, token.id);\n                }\n            }\n            while (rbp < nexttoken.lbp) {\n                isArray = token.value === 'Array';\n                isObject = token.value === 'Object';\n                advance();\n                if (isArray && token.id === '(' && nexttoken.id === ')')\n                    warning(\"Use the array literal notation [].\", token);\n                if (isObject && token.id === '(' && nexttoken.id === ')')\n                    warning(\"Use the object literal notation {}.\", token);\n                if (token.led) {\n                    left = token.led(left);\n                } else {\n                    error(\"Expected an operator and instead saw '{a}'.\",\n                        token, token.id);\n                }\n            }\n        }\n        return left;\n    }\n\n\n// Functions for conformance of style.\n\n    function adjacent(left, right) {\n        left = left || token;\n        right = right || nexttoken;\n        if (option.white) {\n            if (left.character !== right.from && left.line === right.line) {\n                left.from += (left.character - left.from);\n                warning(\"Unexpected space after '{a}'.\", left, left.value);\n            }\n        }\n    }\n\n    function nobreak(left, right) {\n        left = left || token;\n        right = right || nexttoken;\n        if (option.white && (left.character !== right.from || left.line !== right.line)) {\n            warning(\"Unexpected space before '{a}'.\", right, right.value);\n        }\n    }\n\n    function nospace(left, right) {\n        left = left || token;\n        right = right || nexttoken;\n        if (option.white && !left.comment) {\n            if (left.line === right.line) {\n                adjacent(left, right);\n            }\n        }\n    }\n\n    function nonadjacent(left, right) {\n        if (option.white) {\n            left = left || token;\n            right = right || nexttoken;\n            if (left.line === right.line && left.character === right.from) {\n                left.from += (left.character - left.from);\n                warning(\"Missing space after '{a}'.\",\n                        left, left.value);\n            }\n        }\n    }\n\n    function nobreaknonadjacent(left, right) {\n        left = left || token;\n        right = right || nexttoken;\n        if (!option.laxbreak && left.line !== right.line) {\n            warning(\"Bad line breaking before '{a}'.\", right, right.id);\n        } else if (option.white) {\n            left = left || token;\n            right = right || nexttoken;\n            if (left.character === right.from) {\n                left.from += (left.character - left.from);\n                warning(\"Missing space after '{a}'.\",\n                        left, left.value);\n            }\n        }\n    }\n\n    function indentation(bias) {\n        var i;\n        if (option.white && nexttoken.id !== '(end)') {\n            i = indent + (bias || 0);\n            if (nexttoken.from !== i) {\n                warning(\n\"Expected '{a}' to have an indentation at {b} instead at {c}.\",\n                        nexttoken, nexttoken.value, i, nexttoken.from);\n            }\n        }\n    }\n\n    function nolinebreak(t) {\n        t = t || token;\n        if (t.line !== nexttoken.line) {\n            warning(\"Line breaking error '{a}'.\", t, t.value);\n        }\n    }\n\n\n    function comma() {\n        if (token.line !== nexttoken.line) {\n            if (!option.laxcomma) {\n                if (comma.first) {\n                    warning(\"Comma warnings can be turned off with 'laxcomma'\");\n                    comma.first = false;\n                }\n                warning(\"Bad line breaking before '{a}'.\", token, nexttoken.id);\n            }\n        } else if (!token.comment && token.character !== nexttoken.from && option.white) {\n            token.from += (token.character - token.from);\n            warning(\"Unexpected space after '{a}'.\", token, token.value);\n        }\n        advance(',');\n        nonadjacent(token, nexttoken);\n    }\n\n\n// Functional constructors for making the symbols that will be inherited by\n// tokens.\n\n    function symbol(s, p) {\n        var x = syntax[s];\n        if (!x || typeof x !== 'object') {\n            syntax[s] = x = {\n                id: s,\n                lbp: p,\n                value: s\n            };\n        }\n        return x;\n    }\n\n\n    function delim(s) {\n        return symbol(s, 0);\n    }\n\n\n    function stmt(s, f) {\n        var x = delim(s);\n        x.identifier = x.reserved = true;\n        x.fud = f;\n        return x;\n    }\n\n\n    function blockstmt(s, f) {\n        var x = stmt(s, f);\n        x.block = true;\n        return x;\n    }\n\n\n    function reserveName(x) {\n        var c = x.id.charAt(0);\n        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {\n            x.identifier = x.reserved = true;\n        }\n        return x;\n    }\n\n\n    function prefix(s, f) {\n        var x = symbol(s, 150);\n        reserveName(x);\n        x.nud = (typeof f === 'function') ? f : function () {\n            this.right = expression(150);\n            this.arity = 'unary';\n            if (this.id === '++' || this.id === '--') {\n                if (option.plusplus) {\n                    warning(\"Unexpected use of '{a}'.\", this, this.id);\n                } else if ((!this.right.identifier || this.right.reserved) &&\n                        this.right.id !== '.' && this.right.id !== '[') {\n                    warning(\"Bad operand.\", this);\n                }\n            }\n            return this;\n        };\n        return x;\n    }\n\n\n    function type(s, f) {\n        var x = delim(s);\n        x.type = s;\n        x.nud = f;\n        return x;\n    }\n\n\n    function reserve(s, f) {\n        var x = type(s, f);\n        x.identifier = x.reserved = true;\n        return x;\n    }\n\n\n    function reservevar(s, v) {\n        return reserve(s, function () {\n            if (typeof v === 'function') {\n                v(this);\n            }\n            return this;\n        });\n    }\n\n\n    function infix(s, f, p, w) {\n        var x = symbol(s, p);\n        reserveName(x);\n        x.led = function (left) {\n            if (!w) {\n                nobreaknonadjacent(prevtoken, token);\n                nonadjacent(token, nexttoken);\n            }\n            if (s === \"in\" && left.id === \"!\") {\n                warning(\"Confusing use of '{a}'.\", left, '!');\n            }\n            if (typeof f === 'function') {\n                return f(left, this);\n            } else {\n                this.left = left;\n                this.right = expression(p);\n                return this;\n            }\n        };\n        return x;\n    }\n\n\n    function relation(s, f) {\n        var x = symbol(s, 100);\n        x.led = function (left) {\n            nobreaknonadjacent(prevtoken, token);\n            nonadjacent(token, nexttoken);\n            var right = expression(100);\n            if ((left && left.id === 'NaN') || (right && right.id === 'NaN')) {\n                warning(\"Use the isNaN function to compare with NaN.\", this);\n            } else if (f) {\n                f.apply(this, [left, right]);\n            }\n            if (left.id === '!') {\n                warning(\"Confusing use of '{a}'.\", left, '!');\n            }\n            if (right.id === '!') {\n                warning(\"Confusing use of '{a}'.\", right, '!');\n            }\n            this.left = left;\n            this.right = right;\n            return this;\n        };\n        return x;\n    }\n\n\n    function isPoorRelation(node) {\n        return node &&\n              ((node.type === '(number)' && +node.value === 0) ||\n               (node.type === '(string)' && node.value === '') ||\n               (node.type === 'null' && !option.eqnull) ||\n                node.type === 'true' ||\n                node.type === 'false' ||\n                node.type === 'undefined');\n    }\n\n\n    function assignop(s, f) {\n        symbol(s, 20).exps = true;\n        return infix(s, function (left, that) {\n            var l;\n            that.left = left;\n            if (predefined[left.value] === false &&\n                    scope[left.value]['(global)'] === true) {\n                warning(\"Read only.\", left);\n            } else if (left['function']) {\n                warning(\"'{a}' is a function.\", left, left.value);\n            }\n            if (left) {\n                if (option.esnext && funct[left.value] === 'const') {\n                    warning(\"Attempting to override '{a}' which is a constant\", left, left.value);\n                }\n                if (left.id === '.' || left.id === '[') {\n                    if (!left.left || left.left.value === 'arguments') {\n                        warning('Bad assignment.', that);\n                    }\n                    that.right = expression(19);\n                    return that;\n                } else if (left.identifier && !left.reserved) {\n                    if (funct[left.value] === 'exception') {\n                        warning(\"Do not assign to the exception parameter.\", left);\n                    }\n                    that.right = expression(19);\n                    return that;\n                }\n                if (left === syntax['function']) {\n                    warning(\n\"Expected an identifier in an assignment and instead saw a function invocation.\",\n                                token);\n                }\n            }\n            error(\"Bad assignment.\", that);\n        }, 20);\n    }\n\n\n    function bitwise(s, f, p) {\n        var x = symbol(s, p);\n        reserveName(x);\n        x.led = (typeof f === 'function') ? f : function (left) {\n            if (option.bitwise) {\n                warning(\"Unexpected use of '{a}'.\", this, this.id);\n            }\n            this.left = left;\n            this.right = expression(p);\n            return this;\n        };\n        return x;\n    }\n\n\n    function bitwiseassignop(s) {\n        symbol(s, 20).exps = true;\n        return infix(s, function (left, that) {\n            if (option.bitwise) {\n                warning(\"Unexpected use of '{a}'.\", that, that.id);\n            }\n            nonadjacent(prevtoken, token);\n            nonadjacent(token, nexttoken);\n            if (left) {\n                if (left.id === '.' || left.id === '[' ||\n                        (left.identifier && !left.reserved)) {\n                    expression(19);\n                    return that;\n                }\n                if (left === syntax['function']) {\n                    warning(\n\"Expected an identifier in an assignment, and instead saw a function invocation.\",\n                                token);\n                }\n                return that;\n            }\n            error(\"Bad assignment.\", that);\n        }, 20);\n    }\n\n\n    function suffix(s, f) {\n        var x = symbol(s, 150);\n        x.led = function (left) {\n            if (option.plusplus) {\n                warning(\"Unexpected use of '{a}'.\", this, this.id);\n            } else if ((!left.identifier || left.reserved) &&\n                    left.id !== '.' && left.id !== '[') {\n                warning(\"Bad operand.\", this);\n            }\n            this.left = left;\n            return this;\n        };\n        return x;\n    }\n\n\n    // fnparam means that this identifier is being defined as a function\n    // argument (see identifier())\n    function optionalidentifier(fnparam) {\n        if (nexttoken.identifier) {\n            advance();\n            if (token.reserved && !option.es5) {\n                // `undefined` as a function param is a common pattern to protect\n                // against the case when somebody does `undefined = true` and\n                // help with minification. More info: https://gist.github.com/315916\n                if (!fnparam || token.value !== 'undefined') {\n                    warning(\"Expected an identifier and instead saw '{a}' (a reserved word).\",\n                            token, token.id);\n                }\n            }\n            return token.value;\n        }\n    }\n\n    // fnparam means that this identifier is being defined as a function\n    // argument\n    function identifier(fnparam) {\n        var i = optionalidentifier(fnparam);\n        if (i) {\n            return i;\n        }\n        if (token.id === 'function' && nexttoken.id === '(') {\n            warning(\"Missing name in function declaration.\");\n        } else {\n            error(\"Expected an identifier and instead saw '{a}'.\",\n                    nexttoken, nexttoken.value);\n        }\n    }\n\n\n    function reachable(s) {\n        var i = 0, t;\n        if (nexttoken.id !== ';' || noreach) {\n            return;\n        }\n        for (;;) {\n            t = peek(i);\n            if (t.reach) {\n                return;\n            }\n            if (t.id !== '(endline)') {\n                if (t.id === 'function') {\n                    if (!option.latedef) {\n                        break;\n                    }\n                    warning(\n\"Inner functions should be listed at the top of the outer function.\", t);\n                    break;\n                }\n                warning(\"Unreachable '{a}' after '{b}'.\", t, t.value, s);\n                break;\n            }\n            i += 1;\n        }\n    }\n\n\n    function statement(noindent) {\n        var i = indent, r, s = scope, t = nexttoken;\n\n        if (t.id === \";\") {\n            advance(\";\");\n            return;\n        }\n\n// Is this a labelled statement?\n\n        if (t.identifier && !t.reserved && peek().id === ':') {\n            advance();\n            advance(':');\n            scope = Object.create(s);\n            addlabel(t.value, 'label');\n            if (!nexttoken.labelled) {\n                warning(\"Label '{a}' on {b} statement.\",\n                        nexttoken, t.value, nexttoken.value);\n            }\n            if (jx.test(t.value + ':')) {\n                warning(\"Label '{a}' looks like a javascript url.\",\n                        t, t.value);\n            }\n            nexttoken.label = t.value;\n            t = nexttoken;\n        }\n\n// Parse the statement.\n\n        if (!noindent) {\n            indentation();\n        }\n        r = expression(0, true);\n\n        // Look for the final semicolon.\n        if (!t.block) {\n            if (!option.expr && (!r || !r.exps)) {\n                warning(\"Expected an assignment or function call and instead saw an expression.\",\n                    token);\n            } else if (option.nonew && r.id === '(' && r.left.id === 'new') {\n                warning(\"Do not use 'new' for side effects.\");\n            }\n\n            if (nexttoken.id === ',') {\n                return comma();\n            }\n\n            if (nexttoken.id !== ';') {\n                if (!option.asi) {\n                    // If this is the last statement in a block that ends on\n                    // the same line *and* option lastsemic is on, ignore the warning.\n                    // Otherwise, complain about missing semicolon.\n                    if (!option.lastsemic || nexttoken.id !== '}' ||\n                            nexttoken.line !== token.line) {\n                        warningAt(\"Missing semicolon.\", token.line, token.character);\n                    }\n                }\n            } else {\n                adjacent(token, nexttoken);\n                advance(';');\n                nonadjacent(token, nexttoken);\n            }\n        }\n\n// Restore the indentation.\n\n        indent = i;\n        scope = s;\n        return r;\n    }\n\n\n    function statements(startLine) {\n        var a = [], f, p;\n\n        while (!nexttoken.reach && nexttoken.id !== '(end)') {\n            if (nexttoken.id === ';') {\n                p = peek();\n                if (!p || p.id !== \"(\") {\n                    warning(\"Unnecessary semicolon.\");\n                }\n                advance(';');\n            } else {\n                a.push(statement(startLine === nexttoken.line));\n            }\n        }\n        return a;\n    }\n\n\n    /*\n     * read all directives\n     * recognizes a simple form of asi, but always\n     * warns, if it is used\n     */\n    function directives() {\n        var i, p, pn;\n\n        for (;;) {\n            if (nexttoken.id === \"(string)\") {\n                p = peek(0);\n                if (p.id === \"(endline)\") {\n                    i = 1;\n                    do {\n                        pn = peek(i);\n                        i = i + 1;\n                    } while (pn.id === \"(endline)\");\n\n                    if (pn.id !== \";\") {\n                        if (pn.id !== \"(string)\" && pn.id !== \"(number)\" &&\n                            pn.id !== \"(regexp)\" && pn.identifier !== true &&\n                            pn.id !== \"}\") {\n                            break;\n                        }\n                        warning(\"Missing semicolon.\", nexttoken);\n                    } else {\n                        p = pn;\n                    }\n                } else if (p.id === \"}\") {\n                    // directive with no other statements, warn about missing semicolon\n                    warning(\"Missing semicolon.\", p);\n                } else if (p.id !== \";\") {\n                    break;\n                }\n\n                indentation();\n                advance();\n                if (directive[token.value]) {\n                    warning(\"Unnecessary directive \\\"{a}\\\".\", token, token.value);\n                }\n\n                if (token.value === \"use strict\") {\n                    option.newcap = true;\n                    option.undef = true;\n                }\n\n                // there's no directive negation, so always set to true\n                directive[token.value] = true;\n\n                if (p.id === \";\") {\n                    advance(\";\");\n                }\n                continue;\n            }\n            break;\n        }\n    }\n\n\n    /*\n     * Parses a single block. A block is a sequence of statements wrapped in\n     * braces.\n     *\n     * ordinary - true for everything but function bodies and try blocks.\n     * stmt     - true if block can be a single statement (e.g. in if/for/while).\n     * isfunc   - true if block is a function body\n     */\n    function block(ordinary, stmt, isfunc) {\n        var a,\n            b = inblock,\n            old_indent = indent,\n            m,\n            s = scope,\n            t,\n            line,\n            d;\n\n        inblock = ordinary;\n        if (!ordinary || !option.funcscope) scope = Object.create(scope);\n        nonadjacent(token, nexttoken);\n        t = nexttoken;\n\n        if (nexttoken.id === '{') {\n            advance('{');\n            line = token.line;\n            if (nexttoken.id !== '}') {\n                indent += option.indent;\n                while (!ordinary && nexttoken.from > indent) {\n                    indent += option.indent;\n                }\n\n                if (isfunc) {\n                    m = {};\n                    for (d in directive) {\n                        if (is_own(directive, d)) {\n                            m[d] = directive[d];\n                        }\n                    }\n                    directives();\n\n                    if (option.strict && funct['(context)']['(global)']) {\n                        if (!m[\"use strict\"] && !directive[\"use strict\"]) {\n                            warning(\"Missing \\\"use strict\\\" statement.\");\n                        }\n                    }\n                }\n\n                a = statements(line);\n\n                if (isfunc) {\n                    directive = m;\n                }\n\n                indent -= option.indent;\n                if (line !== nexttoken.line) {\n                    indentation();\n                }\n            } else if (line !== nexttoken.line) {\n                indentation();\n            }\n            advance('}', t);\n            indent = old_indent;\n        } else if (!ordinary) {\n            error(\"Expected '{a}' and instead saw '{b}'.\",\n                  nexttoken, '{', nexttoken.value);\n        } else {\n            if (!stmt || option.curly)\n                warning(\"Expected '{a}' and instead saw '{b}'.\",\n                        nexttoken, '{', nexttoken.value);\n\n            noreach = true;\n            indent += option.indent;\n            // test indentation only if statement is in new line\n            a = [statement(nexttoken.line === token.line)];\n            indent -= option.indent;\n            noreach = false;\n        }\n        funct['(verb)'] = null;\n        if (!ordinary || !option.funcscope) scope = s;\n        inblock = b;\n        if (ordinary && option.noempty && (!a || a.length === 0)) {\n            warning(\"Empty block.\");\n        }\n        return a;\n    }\n\n\n    function countMember(m) {\n        if (membersOnly && typeof membersOnly[m] !== 'boolean') {\n            warning(\"Unexpected /*member '{a}'.\", token, m);\n        }\n        if (typeof member[m] === 'number') {\n            member[m] += 1;\n        } else {\n            member[m] = 1;\n        }\n    }\n\n\n    function note_implied(token) {\n        var name = token.value, line = token.line, a = implied[name];\n        if (typeof a === 'function') {\n            a = false;\n        }\n\n        if (!a) {\n            a = [line];\n            implied[name] = a;\n        } else if (a[a.length - 1] !== line) {\n            a.push(line);\n        }\n    }\n\n\n    // Build the syntax table by declaring the syntactic elements of the language.\n\n    type('(number)', function () {\n        return this;\n    });\n\n    type('(string)', function () {\n        return this;\n    });\n\n    syntax['(identifier)'] = {\n        type: '(identifier)',\n        lbp: 0,\n        identifier: true,\n        nud: function () {\n            var v = this.value,\n                s = scope[v],\n                f;\n\n            if (typeof s === 'function') {\n                // Protection against accidental inheritance.\n                s = undefined;\n            } else if (typeof s === 'boolean') {\n                f = funct;\n                funct = functions[0];\n                addlabel(v, 'var');\n                s = funct;\n                funct = f;\n            }\n\n            // The name is in scope and defined in the current function.\n            if (funct === s) {\n                // Change 'unused' to 'var', and reject labels.\n                switch (funct[v]) {\n                case 'unused':\n                    funct[v] = 'var';\n                    break;\n                case 'unction':\n                    funct[v] = 'function';\n                    this['function'] = true;\n                    break;\n                case 'function':\n                    this['function'] = true;\n                    break;\n                case 'label':\n                    warning(\"'{a}' is a statement label.\", token, v);\n                    break;\n                }\n            } else if (funct['(global)']) {\n                // The name is not defined in the function.  If we are in the global\n                // scope, then we have an undefined variable.\n                //\n                // Operators typeof and delete do not raise runtime errors even if\n                // the base object of a reference is null so no need to display warning\n                // if we're inside of typeof or delete.\n\n                if (option.undef && typeof predefined[v] !== 'boolean') {\n                    // Attempting to subscript a null reference will throw an\n                    // error, even within the typeof and delete operators\n                    if (!(anonname === 'typeof' || anonname === 'delete') ||\n                        (nexttoken && (nexttoken.value === '.' || nexttoken.value === '['))) {\n\n                        isundef(funct, \"'{a}' is not defined.\", token, v);\n                    }\n                }\n                note_implied(token);\n            } else {\n                // If the name is already defined in the current\n                // function, but not as outer, then there is a scope error.\n\n                switch (funct[v]) {\n                case 'closure':\n                case 'function':\n                case 'var':\n                case 'unused':\n                    warning(\"'{a}' used out of scope.\", token, v);\n                    break;\n                case 'label':\n                    warning(\"'{a}' is a statement label.\", token, v);\n                    break;\n                case 'outer':\n                case 'global':\n                    break;\n                default:\n                    // If the name is defined in an outer function, make an outer entry,\n                    // and if it was unused, make it var.\n                    if (s === true) {\n                        funct[v] = true;\n                    } else if (s === null) {\n                        warning(\"'{a}' is not allowed.\", token, v);\n                        note_implied(token);\n                    } else if (typeof s !== 'object') {\n                        // Operators typeof and delete do not raise runtime errors even\n                        // if the base object of a reference is null so no need to\n                        // display warning if we're inside of typeof or delete.\n                        if (option.undef) {\n                            // Attempting to subscript a null reference will throw an\n                            // error, even within the typeof and delete operators\n                            if (!(anonname === 'typeof' || anonname === 'delete') ||\n                                (nexttoken &&\n                                    (nexttoken.value === '.' || nexttoken.value === '['))) {\n\n                                isundef(funct, \"'{a}' is not defined.\", token, v);\n                            }\n                        }\n                        funct[v] = true;\n                        note_implied(token);\n                    } else {\n                        switch (s[v]) {\n                        case 'function':\n                        case 'unction':\n                            this['function'] = true;\n                            s[v] = 'closure';\n                            funct[v] = s['(global)'] ? 'global' : 'outer';\n                            break;\n                        case 'var':\n                        case 'unused':\n                            s[v] = 'closure';\n                            funct[v] = s['(global)'] ? 'global' : 'outer';\n                            break;\n                        case 'closure':\n                        case 'parameter':\n                            funct[v] = s['(global)'] ? 'global' : 'outer';\n                            break;\n                        case 'label':\n                            warning(\"'{a}' is a statement label.\", token, v);\n                        }\n                    }\n                }\n            }\n            return this;\n        },\n        led: function () {\n            error(\"Expected an operator and instead saw '{a}'.\",\n                nexttoken, nexttoken.value);\n        }\n    };\n\n    type('(regexp)', function () {\n        return this;\n    });\n\n\n// ECMAScript parser\n\n    delim('(endline)');\n    delim('(begin)');\n    delim('(end)').reach = true;\n    delim('</').reach = true;\n    delim('<!');\n    delim('<!--');\n    delim('-->');\n    delim('(error)').reach = true;\n    delim('}').reach = true;\n    delim(')');\n    delim(']');\n    delim('\"').reach = true;\n    delim(\"'\").reach = true;\n    delim(';');\n    delim(':').reach = true;\n    delim(',');\n    delim('#');\n    delim('@');\n    reserve('else');\n    reserve('case').reach = true;\n    reserve('catch');\n    reserve('default').reach = true;\n    reserve('finally');\n    reservevar('arguments', function (x) {\n        if (directive['use strict'] && funct['(global)']) {\n            warning(\"Strict violation.\", x);\n        }\n    });\n    reservevar('eval');\n    reservevar('false');\n    reservevar('Infinity');\n    reservevar('NaN');\n    reservevar('null');\n    reservevar('this', function (x) {\n        if (directive['use strict'] && !option.validthis && ((funct['(statement)'] &&\n                funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) {\n            warning(\"Possible strict violation.\", x);\n        }\n    });\n    reservevar('true');\n    reservevar('undefined');\n    assignop('=', 'assign', 20);\n    assignop('+=', 'assignadd', 20);\n    assignop('-=', 'assignsub', 20);\n    assignop('*=', 'assignmult', 20);\n    assignop('/=', 'assigndiv', 20).nud = function () {\n        error(\"A regular expression literal can be confused with '/='.\");\n    };\n    assignop('%=', 'assignmod', 20);\n    bitwiseassignop('&=', 'assignbitand', 20);\n    bitwiseassignop('|=', 'assignbitor', 20);\n    bitwiseassignop('^=', 'assignbitxor', 20);\n    bitwiseassignop('<<=', 'assignshiftleft', 20);\n    bitwiseassignop('>>=', 'assignshiftright', 20);\n    bitwiseassignop('>>>=', 'assignshiftrightunsigned', 20);\n    infix('?', function (left, that) {\n        that.left = left;\n        that.right = expression(10);\n        advance(':');\n        that['else'] = expression(10);\n        return that;\n    }, 30);\n\n    infix('||', 'or', 40);\n    infix('&&', 'and', 50);\n    bitwise('|', 'bitor', 70);\n    bitwise('^', 'bitxor', 80);\n    bitwise('&', 'bitand', 90);\n    relation('==', function (left, right) {\n        var eqnull = option.eqnull && (left.value === 'null' || right.value === 'null');\n\n        if (!eqnull && option.eqeqeq)\n            warning(\"Expected '{a}' and instead saw '{b}'.\", this, '===', '==');\n        else if (isPoorRelation(left))\n            warning(\"Use '{a}' to compare with '{b}'.\", this, '===', left.value);\n        else if (isPoorRelation(right))\n            warning(\"Use '{a}' to compare with '{b}'.\", this, '===', right.value);\n\n        return this;\n    });\n    relation('===');\n    relation('!=', function (left, right) {\n        var eqnull = option.eqnull &&\n                (left.value === 'null' || right.value === 'null');\n\n        if (!eqnull && option.eqeqeq) {\n            warning(\"Expected '{a}' and instead saw '{b}'.\",\n                    this, '!==', '!=');\n        } else if (isPoorRelation(left)) {\n            warning(\"Use '{a}' to compare with '{b}'.\",\n                    this, '!==', left.value);\n        } else if (isPoorRelation(right)) {\n            warning(\"Use '{a}' to compare with '{b}'.\",\n                    this, '!==', right.value);\n        }\n        return this;\n    });\n    relation('!==');\n    relation('<');\n    relation('>');\n    relation('<=');\n    relation('>=');\n    bitwise('<<', 'shiftleft', 120);\n    bitwise('>>', 'shiftright', 120);\n    bitwise('>>>', 'shiftrightunsigned', 120);\n    infix('in', 'in', 120);\n    infix('instanceof', 'instanceof', 120);\n    infix('+', function (left, that) {\n        var right = expression(130);\n        if (left && right && left.id === '(string)' && right.id === '(string)') {\n            left.value += right.value;\n            left.character = right.character;\n            if (!option.scripturl && jx.test(left.value)) {\n                warning(\"JavaScript URL.\", left);\n            }\n            return left;\n        }\n        that.left = left;\n        that.right = right;\n        return that;\n    }, 130);\n    prefix('+', 'num');\n    prefix('+++', function () {\n        warning(\"Confusing pluses.\");\n        this.right = expression(150);\n        this.arity = 'unary';\n        return this;\n    });\n    infix('+++', function (left) {\n        warning(\"Confusing pluses.\");\n        this.left = left;\n        this.right = expression(130);\n        return this;\n    }, 130);\n    infix('-', 'sub', 130);\n    prefix('-', 'neg');\n    prefix('---', function () {\n        warning(\"Confusing minuses.\");\n        this.right = expression(150);\n        this.arity = 'unary';\n        return this;\n    });\n    infix('---', function (left) {\n        warning(\"Confusing minuses.\");\n        this.left = left;\n        this.right = expression(130);\n        return this;\n    }, 130);\n    infix('*', 'mult', 140);\n    infix('/', 'div', 140);\n    infix('%', 'mod', 140);\n\n    suffix('++', 'postinc');\n    prefix('++', 'preinc');\n    syntax['++'].exps = true;\n\n    suffix('--', 'postdec');\n    prefix('--', 'predec');\n    syntax['--'].exps = true;\n    prefix('delete', function () {\n        var p = expression(0);\n        if (!p || (p.id !== '.' && p.id !== '[')) {\n            warning(\"Variables should not be deleted.\");\n        }\n        this.first = p;\n        return this;\n    }).exps = true;\n\n    prefix('~', function () {\n        if (option.bitwise) {\n            warning(\"Unexpected '{a}'.\", this, '~');\n        }\n        expression(150);\n        return this;\n    });\n\n    prefix('!', function () {\n        this.right = expression(150);\n        this.arity = 'unary';\n        if (bang[this.right.id] === true) {\n            warning(\"Confusing use of '{a}'.\", this, '!');\n        }\n        return this;\n    });\n    prefix('typeof', 'typeof');\n    prefix('new', function () {\n        var c = expression(155), i;\n        if (c && c.id !== 'function') {\n            if (c.identifier) {\n                c['new'] = true;\n                switch (c.value) {\n                case 'Number':\n                case 'String':\n                case 'Boolean':\n                case 'Math':\n                case 'JSON':\n                    warning(\"Do not use {a} as a constructor.\", token, c.value);\n                    break;\n                case 'Function':\n                    if (!option.evil) {\n                        warning(\"The Function constructor is eval.\");\n                    }\n                    break;\n                case 'Date':\n                case 'RegExp':\n                    break;\n                default:\n                    if (c.id !== 'function') {\n                        i = c.value.substr(0, 1);\n                        if (option.newcap && (i < 'A' || i > 'Z')) {\n                            warning(\"A constructor name should start with an uppercase letter.\",\n                                token);\n                        }\n                    }\n                }\n            } else {\n                if (c.id !== '.' && c.id !== '[' && c.id !== '(') {\n                    warning(\"Bad constructor.\", token);\n                }\n            }\n        } else {\n            if (!option.supernew)\n                warning(\"Weird construction. Delete 'new'.\", this);\n        }\n        adjacent(token, nexttoken);\n        if (nexttoken.id !== '(' && !option.supernew) {\n            warning(\"Missing '()' invoking a constructor.\");\n        }\n        this.first = c;\n        return this;\n    });\n    syntax['new'].exps = true;\n\n    prefix('void').exps = true;\n\n    infix('.', function (left, that) {\n        adjacent(prevtoken, token);\n        nobreak();\n        var m = identifier();\n        if (typeof m === 'string') {\n            countMember(m);\n        }\n        that.left = left;\n        that.right = m;\n        if (left && left.value === 'arguments' && (m === 'callee' || m === 'caller')) {\n            if (option.noarg)\n                warning(\"Avoid arguments.{a}.\", left, m);\n            else if (directive['use strict'])\n                error('Strict violation.');\n        } else if (!option.evil && left && left.value === 'document' &&\n                (m === 'write' || m === 'writeln')) {\n            warning(\"document.write can be a form of eval.\", left);\n        }\n        if (!option.evil && (m === 'eval' || m === 'execScript')) {\n            warning('eval is evil.');\n        }\n        return that;\n    }, 160, true);\n\n    infix('(', function (left, that) {\n        if (prevtoken.id !== '}' && prevtoken.id !== ')') {\n            nobreak(prevtoken, token);\n        }\n        nospace();\n        if (option.immed && !left.immed && left.id === 'function') {\n            warning(\"Wrap an immediate function invocation in parentheses \" +\n                \"to assist the reader in understanding that the expression \" +\n                \"is the result of a function, and not the function itself.\");\n        }\n        var n = 0,\n            p = [];\n        if (left) {\n            if (left.type === '(identifier)') {\n                if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {\n                    if (left.value !== 'Number' && left.value !== 'String' &&\n                            left.value !== 'Boolean' &&\n                            left.value !== 'Date') {\n                        if (left.value === 'Math') {\n                            warning(\"Math is not a function.\", left);\n                        } else if (option.newcap) {\n                            warning(\n\"Missing 'new' prefix when invoking a constructor.\", left);\n                        }\n                    }\n                }\n            }\n        }\n        if (nexttoken.id !== ')') {\n            for (;;) {\n                p[p.length] = expression(10);\n                n += 1;\n                if (nexttoken.id !== ',') {\n                    break;\n                }\n                comma();\n            }\n        }\n        advance(')');\n        nospace(prevtoken, token);\n        if (typeof left === 'object') {\n            if (left.value === 'parseInt' && n === 1) {\n                warning(\"Missing radix parameter.\", left);\n            }\n            if (!option.evil) {\n                if (left.value === 'eval' || left.value === 'Function' ||\n                        left.value === 'execScript') {\n                    warning(\"eval is evil.\", left);\n                } else if (p[0] && p[0].id === '(string)' &&\n                       (left.value === 'setTimeout' ||\n                        left.value === 'setInterval')) {\n                    warning(\n    \"Implied eval is evil. Pass a function instead of a string.\", left);\n                }\n            }\n            if (!left.identifier && left.id !== '.' && left.id !== '[' &&\n                    left.id !== '(' && left.id !== '&&' && left.id !== '||' &&\n                    left.id !== '?') {\n                warning(\"Bad invocation.\", left);\n            }\n        }\n        that.left = left;\n        return that;\n    }, 155, true).exps = true;\n\n    prefix('(', function () {\n        nospace();\n        if (nexttoken.id === 'function') {\n            nexttoken.immed = true;\n        }\n        var v = expression(0);\n        advance(')', this);\n        nospace(prevtoken, token);\n        if (option.immed && v.id === 'function') {\n            if (nexttoken.id === '(' ||\n              (nexttoken.id === '.' && (peek().value === 'call' || peek().value === 'apply'))) {\n                warning(\n\"Move the invocation into the parens that contain the function.\", nexttoken);\n            } else {\n                warning(\n\"Do not wrap function literals in parens unless they are to be immediately invoked.\",\n                        this);\n            }\n        }\n        return v;\n    });\n\n    infix('[', function (left, that) {\n        nobreak(prevtoken, token);\n        nospace();\n        var e = expression(0), s;\n        if (e && e.type === '(string)') {\n            if (!option.evil && (e.value === 'eval' || e.value === 'execScript')) {\n                warning(\"eval is evil.\", that);\n            }\n            countMember(e.value);\n            if (!option.sub && ix.test(e.value)) {\n                s = syntax[e.value];\n                if (!s || !s.reserved) {\n                    warning(\"['{a}'] is better written in dot notation.\",\n                            e, e.value);\n                }\n            }\n        }\n        advance(']', that);\n        nospace(prevtoken, token);\n        that.left = left;\n        that.right = e;\n        return that;\n    }, 160, true);\n\n    prefix('[', function () {\n        var b = token.line !== nexttoken.line;\n        this.first = [];\n        if (b) {\n            indent += option.indent;\n            if (nexttoken.from === indent + option.indent) {\n                indent += option.indent;\n            }\n        }\n        while (nexttoken.id !== '(end)') {\n            while (nexttoken.id === ',') {\n                warning(\"Extra comma.\");\n                advance(',');\n            }\n            if (nexttoken.id === ']') {\n                break;\n            }\n            if (b && token.line !== nexttoken.line) {\n                indentation();\n            }\n            this.first.push(expression(10));\n            if (nexttoken.id === ',') {\n                comma();\n                if (nexttoken.id === ']' && !option.es5) {\n                    warning(\"Extra comma.\", token);\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n        if (b) {\n            indent -= option.indent;\n            indentation();\n        }\n        advance(']', this);\n        return this;\n    }, 160);\n\n\n    function property_name() {\n        var id = optionalidentifier(true);\n        if (!id) {\n            if (nexttoken.id === '(string)') {\n                id = nexttoken.value;\n                advance();\n            } else if (nexttoken.id === '(number)') {\n                id = nexttoken.value.toString();\n                advance();\n            }\n        }\n        return id;\n    }\n\n\n    function functionparams() {\n        var i, t = nexttoken, p = [];\n        advance('(');\n        nospace();\n        if (nexttoken.id === ')') {\n            advance(')');\n            return;\n        }\n        for (;;) {\n            i = identifier(true);\n            p.push(i);\n            addlabel(i, 'parameter');\n            if (nexttoken.id === ',') {\n                comma();\n            } else {\n                advance(')', t);\n                nospace(prevtoken, token);\n                return p;\n            }\n        }\n    }\n\n\n    function doFunction(i, statement) {\n        var f,\n            oldOption = option,\n            oldScope  = scope;\n\n        option = Object.create(option);\n        scope = Object.create(scope);\n\n        funct = {\n            '(name)'     : i || '\"' + anonname + '\"',\n            '(line)'     : nexttoken.line,\n            '(context)'  : funct,\n            '(breakage)' : 0,\n            '(loopage)'  : 0,\n            '(scope)'    : scope,\n            '(statement)': statement\n        };\n        f = funct;\n        token.funct = funct;\n        functions.push(funct);\n        if (i) {\n            addlabel(i, 'function');\n        }\n        funct['(params)'] = functionparams();\n\n        block(false, false, true);\n        scope = oldScope;\n        option = oldOption;\n        funct['(last)'] = token.line;\n        funct = funct['(context)'];\n        return f;\n    }\n\n\n    (function (x) {\n        x.nud = function () {\n            var b, f, i, j, p, t;\n            var props = {}; // All properties, including accessors\n\n            function saveProperty(name, token) {\n                if (props[name] && is_own(props, name))\n                    warning(\"Duplicate member '{a}'.\", nexttoken, i);\n                else\n                    props[name] = {};\n\n                props[name].basic = true;\n                props[name].basicToken = token;\n            }\n\n            function saveSetter(name, token) {\n                if (props[name] && is_own(props, name)) {\n                    if (props[name].basic || props[name].setter)\n                        warning(\"Duplicate member '{a}'.\", nexttoken, i);\n                } else {\n                    props[name] = {};\n                }\n\n                props[name].setter = true;\n                props[name].setterToken = token;\n            }\n\n            function saveGetter(name) {\n                if (props[name] && is_own(props, name)) {\n                    if (props[name].basic || props[name].getter)\n                        warning(\"Duplicate member '{a}'.\", nexttoken, i);\n                } else {\n                    props[name] = {};\n                }\n\n                props[name].getter = true;\n                props[name].getterToken = token;\n            }\n\n            b = token.line !== nexttoken.line;\n            if (b) {\n                indent += option.indent;\n                if (nexttoken.from === indent + option.indent) {\n                    indent += option.indent;\n                }\n            }\n            for (;;) {\n                if (nexttoken.id === '}') {\n                    break;\n                }\n                if (b) {\n                    indentation();\n                }\n                if (nexttoken.value === 'get' && peek().id !== ':') {\n                    advance('get');\n                    if (!option.es5) {\n                        error(\"get/set are ES5 features.\");\n                    }\n                    i = property_name();\n                    if (!i) {\n                        error(\"Missing property name.\");\n                    }\n                    saveGetter(i);\n                    t = nexttoken;\n                    adjacent(token, nexttoken);\n                    f = doFunction();\n                    p = f['(params)'];\n                    if (p) {\n                        warning(\"Unexpected parameter '{a}' in get {b} function.\", t, p[0], i);\n                    }\n                    adjacent(token, nexttoken);\n                } else if (nexttoken.value === 'set' && peek().id !== ':') {\n                    advance('set');\n                    if (!option.es5) {\n                        error(\"get/set are ES5 features.\");\n                    }\n                    i = property_name();\n                    if (!i) {\n                        error(\"Missing property name.\");\n                    }\n                    saveSetter(i, nexttoken);\n                    t = nexttoken;\n                    adjacent(token, nexttoken);\n                    f = doFunction();\n                    p = f['(params)'];\n                    if (!p || p.length !== 1) {\n                        warning(\"Expected a single parameter in set {a} function.\", t, i);\n                    }\n                } else {\n                    i = property_name();\n                    saveProperty(i, nexttoken);\n                    if (typeof i !== 'string') {\n                        break;\n                    }\n                    advance(':');\n                    nonadjacent(token, nexttoken);\n                    expression(10);\n                }\n\n                countMember(i);\n                if (nexttoken.id === ',') {\n                    comma();\n                    if (nexttoken.id === ',') {\n                        warning(\"Extra comma.\", token);\n                    } else if (nexttoken.id === '}' && !option.es5) {\n                        warning(\"Extra comma.\", token);\n                    }\n                } else {\n                    break;\n                }\n            }\n            if (b) {\n                indent -= option.indent;\n                indentation();\n            }\n            advance('}', this);\n\n            // Check for lonely setters if in the ES5 mode.\n            if (option.es5) {\n                for (var name in props) {\n                    if (is_own(props, name) && props[name].setter && !props[name].getter) {\n                        warning(\"Setter is defined without getter.\", props[name].setterToken);\n                    }\n                }\n            }\n            return this;\n        };\n        x.fud = function () {\n            error(\"Expected to see a statement and instead saw a block.\", token);\n        };\n    }(delim('{')));\n\n// This Function is called when esnext option is set to true\n// it adds the `const` statement to JSHINT\n\n    useESNextSyntax = function () {\n        var conststatement = stmt('const', function (prefix) {\n            var id, name, value;\n\n            this.first = [];\n            for (;;) {\n                nonadjacent(token, nexttoken);\n                id = identifier();\n                if (funct[id] === \"const\") {\n                    warning(\"const '\" + id + \"' has already been declared\");\n                }\n                if (funct['(global)'] && predefined[id] === false) {\n                    warning(\"Redefinition of '{a}'.\", token, id);\n                }\n                addlabel(id, 'const');\n                if (prefix) {\n                    break;\n                }\n                name = token;\n                this.first.push(token);\n\n                if (nexttoken.id !== \"=\") {\n                    warning(\"const \" +\n                      \"'{a}' is initialized to 'undefined'.\", token, id);\n                }\n\n                if (nexttoken.id === '=') {\n                    nonadjacent(token, nexttoken);\n                    advance('=');\n                    nonadjacent(token, nexttoken);\n                    if (nexttoken.id === 'undefined') {\n                        warning(\"It is not necessary to initialize \" +\n                          \"'{a}' to 'undefined'.\", token, id);\n                    }\n                    if (peek(0).id === '=' && nexttoken.identifier) {\n                        error(\"Constant {a} was not declared correctly.\",\n                                nexttoken, nexttoken.value);\n                    }\n                    value = expression(0);\n                    name.first = value;\n                }\n\n                if (nexttoken.id !== ',') {\n                    break;\n                }\n                comma();\n            }\n            return this;\n        });\n        conststatement.exps = true;\n    };\n\n    var varstatement = stmt('var', function (prefix) {\n        // JavaScript does not have block scope. It only has function scope. So,\n        // declaring a variable in a block can have unexpected consequences.\n        var id, name, value;\n\n        if (funct['(onevar)'] && option.onevar) {\n            warning(\"Too many var statements.\");\n        } else if (!funct['(global)']) {\n            funct['(onevar)'] = true;\n        }\n        this.first = [];\n        for (;;) {\n            nonadjacent(token, nexttoken);\n            id = identifier();\n            if (option.esnext && funct[id] === \"const\") {\n                warning(\"const '\" + id + \"' has already been declared\");\n            }\n            if (funct['(global)'] && predefined[id] === false) {\n                warning(\"Redefinition of '{a}'.\", token, id);\n            }\n            addlabel(id, 'unused');\n            if (prefix) {\n                break;\n            }\n            name = token;\n            this.first.push(token);\n            if (nexttoken.id === '=') {\n                nonadjacent(token, nexttoken);\n                advance('=');\n                nonadjacent(token, nexttoken);\n                if (nexttoken.id === 'undefined') {\n                    warning(\"It is not necessary to initialize '{a}' to 'undefined'.\", token, id);\n                }\n                if (peek(0).id === '=' && nexttoken.identifier) {\n                    error(\"Variable {a} was not declared correctly.\",\n                            nexttoken, nexttoken.value);\n                }\n                value = expression(0);\n                name.first = value;\n            }\n            if (nexttoken.id !== ',') {\n                break;\n            }\n            comma();\n        }\n        return this;\n    });\n    varstatement.exps = true;\n\n    blockstmt('function', function () {\n        if (inblock) {\n            warning(\"Function declarations should not be placed in blocks. \" +\n                \"Use a function expression or move the statement to the top of \" +\n                \"the outer function.\", token);\n\n        }\n        var i = identifier();\n        if (option.esnext && funct[i] === \"const\") {\n            warning(\"const '\" + i + \"' has already been declared\");\n        }\n        adjacent(token, nexttoken);\n        addlabel(i, 'unction');\n        doFunction(i, true);\n        if (nexttoken.id === '(' && nexttoken.line === token.line) {\n            error(\n\"Function declarations are not invocable. Wrap the whole function invocation in parens.\");\n        }\n        return this;\n    });\n\n    prefix('function', function () {\n        var i = optionalidentifier();\n        if (i) {\n            adjacent(token, nexttoken);\n        } else {\n            nonadjacent(token, nexttoken);\n        }\n        doFunction(i);\n        if (!option.loopfunc && funct['(loopage)']) {\n            warning(\"Don't make functions within a loop.\");\n        }\n        return this;\n    });\n\n    blockstmt('if', function () {\n        var t = nexttoken;\n        advance('(');\n        nonadjacent(this, t);\n        nospace();\n        expression(20);\n        if (nexttoken.id === '=') {\n            if (!option.boss)\n                warning(\"Expected a conditional expression and instead saw an assignment.\");\n            advance('=');\n            expression(20);\n        }\n        advance(')', t);\n        nospace(prevtoken, token);\n        block(true, true);\n        if (nexttoken.id === 'else') {\n            nonadjacent(token, nexttoken);\n            advance('else');\n            if (nexttoken.id === 'if' || nexttoken.id === 'switch') {\n                statement(true);\n            } else {\n                block(true, true);\n            }\n        }\n        return this;\n    });\n\n    blockstmt('try', function () {\n        var b, e, s;\n\n        block(false);\n        if (nexttoken.id === 'catch') {\n            advance('catch');\n            nonadjacent(token, nexttoken);\n            advance('(');\n            s = scope;\n            scope = Object.create(s);\n            e = nexttoken.value;\n            if (nexttoken.type !== '(identifier)') {\n                warning(\"Expected an identifier and instead saw '{a}'.\",\n                    nexttoken, e);\n            } else {\n                addlabel(e, 'exception');\n            }\n            advance();\n            advance(')');\n            block(false);\n            b = true;\n            scope = s;\n        }\n        if (nexttoken.id === 'finally') {\n            advance('finally');\n            block(false);\n            return;\n        } else if (!b) {\n            error(\"Expected '{a}' and instead saw '{b}'.\",\n                    nexttoken, 'catch', nexttoken.value);\n        }\n        return this;\n    });\n\n    blockstmt('while', function () {\n        var t = nexttoken;\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        nonadjacent(this, t);\n        nospace();\n        expression(20);\n        if (nexttoken.id === '=') {\n            if (!option.boss)\n                warning(\"Expected a conditional expression and instead saw an assignment.\");\n            advance('=');\n            expression(20);\n        }\n        advance(')', t);\n        nospace(prevtoken, token);\n        block(true, true);\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    }).labelled = true;\n\n    blockstmt('with', function () {\n        var t = nexttoken;\n        if (directive['use strict']) {\n            error(\"'with' is not allowed in strict mode.\", token);\n        } else if (!option.withstmt) {\n            warning(\"Don't use 'with'.\", token);\n        }\n\n        advance('(');\n        nonadjacent(this, t);\n        nospace();\n        expression(0);\n        advance(')', t);\n        nospace(prevtoken, token);\n        block(true, true);\n\n        return this;\n    });\n\n    blockstmt('switch', function () {\n        var t = nexttoken,\n            g = false;\n        funct['(breakage)'] += 1;\n        advance('(');\n        nonadjacent(this, t);\n        nospace();\n        this.condition = expression(20);\n        advance(')', t);\n        nospace(prevtoken, token);\n        nonadjacent(token, nexttoken);\n        t = nexttoken;\n        advance('{');\n        nonadjacent(token, nexttoken);\n        indent += option.indent;\n        this.cases = [];\n        for (;;) {\n            switch (nexttoken.id) {\n            case 'case':\n                switch (funct['(verb)']) {\n                case 'break':\n                case 'case':\n                case 'continue':\n                case 'return':\n                case 'switch':\n                case 'throw':\n                    break;\n                default:\n                    // You can tell JSHint that you don't use break intentionally by\n                    // adding a comment /* falls through */ on a line just before\n                    // the next `case`.\n                    if (!ft.test(lines[nexttoken.line - 2])) {\n                        warning(\n                            \"Expected a 'break' statement before 'case'.\",\n                            token);\n                    }\n                }\n                indentation(-option.indent);\n                advance('case');\n                this.cases.push(expression(20));\n                g = true;\n                advance(':');\n                funct['(verb)'] = 'case';\n                break;\n            case 'default':\n                switch (funct['(verb)']) {\n                case 'break':\n                case 'continue':\n                case 'return':\n                case 'throw':\n                    break;\n                default:\n                    if (!ft.test(lines[nexttoken.line - 2])) {\n                        warning(\n                            \"Expected a 'break' statement before 'default'.\",\n                            token);\n                    }\n                }\n                indentation(-option.indent);\n                advance('default');\n                g = true;\n                advance(':');\n                break;\n            case '}':\n                indent -= option.indent;\n                indentation();\n                advance('}', t);\n                if (this.cases.length === 1 || this.condition.id === 'true' ||\n                        this.condition.id === 'false') {\n                    if (!option.onecase)\n                        warning(\"This 'switch' should be an 'if'.\", this);\n                }\n                funct['(breakage)'] -= 1;\n                funct['(verb)'] = undefined;\n                return;\n            case '(end)':\n                error(\"Missing '{a}'.\", nexttoken, '}');\n                return;\n            default:\n                if (g) {\n                    switch (token.id) {\n                    case ',':\n                        error(\"Each value should have its own case label.\");\n                        return;\n                    case ':':\n                        g = false;\n                        statements();\n                        break;\n                    default:\n                        error(\"Missing ':' on a case clause.\", token);\n                        return;\n                    }\n                } else {\n                    if (token.id === ':') {\n                        advance(':');\n                        error(\"Unexpected '{a}'.\", token, ':');\n                        statements();\n                    } else {\n                        error(\"Expected '{a}' and instead saw '{b}'.\",\n                            nexttoken, 'case', nexttoken.value);\n                        return;\n                    }\n                }\n            }\n        }\n    }).labelled = true;\n\n    stmt('debugger', function () {\n        if (!option.debug) {\n            warning(\"All 'debugger' statements should be removed.\");\n        }\n        return this;\n    }).exps = true;\n\n    (function () {\n        var x = stmt('do', function () {\n            funct['(breakage)'] += 1;\n            funct['(loopage)'] += 1;\n            this.first = block(true);\n            advance('while');\n            var t = nexttoken;\n            nonadjacent(token, t);\n            advance('(');\n            nospace();\n            expression(20);\n            if (nexttoken.id === '=') {\n                if (!option.boss)\n                    warning(\"Expected a conditional expression and instead saw an assignment.\");\n                advance('=');\n                expression(20);\n            }\n            advance(')', t);\n            nospace(prevtoken, token);\n            funct['(breakage)'] -= 1;\n            funct['(loopage)'] -= 1;\n            return this;\n        });\n        x.labelled = true;\n        x.exps = true;\n    }());\n\n    blockstmt('for', function () {\n        var s, t = nexttoken;\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        nonadjacent(this, t);\n        nospace();\n        if (peek(nexttoken.id === 'var' ? 1 : 0).id === 'in') {\n            if (nexttoken.id === 'var') {\n                advance('var');\n                varstatement.fud.call(varstatement, true);\n            } else {\n                switch (funct[nexttoken.value]) {\n                case 'unused':\n                    funct[nexttoken.value] = 'var';\n                    break;\n                case 'var':\n                    break;\n                default:\n                    warning(\"Bad for in variable '{a}'.\",\n                            nexttoken, nexttoken.value);\n                }\n                advance();\n            }\n            advance('in');\n            expression(20);\n            advance(')', t);\n            s = block(true, true);\n            if (option.forin && s && (s.length > 1 || typeof s[0] !== 'object' ||\n                    s[0].value !== 'if')) {\n                warning(\"The body of a for in should be wrapped in an if statement to filter \" +\n                        \"unwanted properties from the prototype.\", this);\n            }\n            funct['(breakage)'] -= 1;\n            funct['(loopage)'] -= 1;\n            return this;\n        } else {\n            if (nexttoken.id !== ';') {\n                if (nexttoken.id === 'var') {\n                    advance('var');\n                    varstatement.fud.call(varstatement);\n                } else {\n                    for (;;) {\n                        expression(0, 'for');\n                        if (nexttoken.id !== ',') {\n                            break;\n                        }\n                        comma();\n                    }\n                }\n            }\n            nolinebreak(token);\n            advance(';');\n            if (nexttoken.id !== ';') {\n                expression(20);\n                if (nexttoken.id === '=') {\n                    if (!option.boss)\n                        warning(\"Expected a conditional expression and instead saw an assignment.\");\n                    advance('=');\n                    expression(20);\n                }\n            }\n            nolinebreak(token);\n            advance(';');\n            if (nexttoken.id === ';') {\n                error(\"Expected '{a}' and instead saw '{b}'.\",\n                        nexttoken, ')', ';');\n            }\n            if (nexttoken.id !== ')') {\n                for (;;) {\n                    expression(0, 'for');\n                    if (nexttoken.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n            }\n            advance(')', t);\n            nospace(prevtoken, token);\n            block(true, true);\n            funct['(breakage)'] -= 1;\n            funct['(loopage)'] -= 1;\n            return this;\n        }\n    }).labelled = true;\n\n\n    stmt('break', function () {\n        var v = nexttoken.value;\n\n        if (funct['(breakage)'] === 0)\n            warning(\"Unexpected '{a}'.\", nexttoken, this.value);\n\n        if (!option.asi)\n            nolinebreak(this);\n\n        if (nexttoken.id !== ';') {\n            if (token.line === nexttoken.line) {\n                if (funct[v] !== 'label') {\n                    warning(\"'{a}' is not a statement label.\", nexttoken, v);\n                } else if (scope[v] !== funct) {\n                    warning(\"'{a}' is out of scope.\", nexttoken, v);\n                }\n                this.first = nexttoken;\n                advance();\n            }\n        }\n        reachable('break');\n        return this;\n    }).exps = true;\n\n\n    stmt('continue', function () {\n        var v = nexttoken.value;\n\n        if (funct['(breakage)'] === 0)\n            warning(\"Unexpected '{a}'.\", nexttoken, this.value);\n\n        if (!option.asi)\n            nolinebreak(this);\n\n        if (nexttoken.id !== ';') {\n            if (token.line === nexttoken.line) {\n                if (funct[v] !== 'label') {\n                    warning(\"'{a}' is not a statement label.\", nexttoken, v);\n                } else if (scope[v] !== funct) {\n                    warning(\"'{a}' is out of scope.\", nexttoken, v);\n                }\n                this.first = nexttoken;\n                advance();\n            }\n        } else if (!funct['(loopage)']) {\n            warning(\"Unexpected '{a}'.\", nexttoken, this.value);\n        }\n        reachable('continue');\n        return this;\n    }).exps = true;\n\n\n    stmt('return', function () {\n        if (this.line === nexttoken.line) {\n            if (nexttoken.id === '(regexp)')\n                warning(\"Wrap the /regexp/ literal in parens to disambiguate the slash operator.\");\n\n            if (nexttoken.id !== ';' && !nexttoken.reach) {\n                nonadjacent(token, nexttoken);\n                if (peek().value === \"=\" && !option.boss) {\n                    warningAt(\"Did you mean to return a conditional instead of an assignment?\",\n                              token.line, token.character + 1);\n                }\n                this.first = expression(0);\n            }\n        } else if (!option.asi) {\n            nolinebreak(this); // always warn (Line breaking error)\n        }\n        reachable('return');\n        return this;\n    }).exps = true;\n\n\n    stmt('throw', function () {\n        nolinebreak(this);\n        nonadjacent(token, nexttoken);\n        this.first = expression(20);\n        reachable('throw');\n        return this;\n    }).exps = true;\n\n//  Superfluous reserved words\n\n    reserve('class');\n    reserve('const');\n    reserve('enum');\n    reserve('export');\n    reserve('extends');\n    reserve('import');\n    reserve('super');\n\n    reserve('let');\n    reserve('yield');\n    reserve('implements');\n    reserve('interface');\n    reserve('package');\n    reserve('private');\n    reserve('protected');\n    reserve('public');\n    reserve('static');\n\n\n// Parse JSON\n\n    function jsonValue() {\n\n        function jsonObject() {\n            var o = {}, t = nexttoken;\n            advance('{');\n            if (nexttoken.id !== '}') {\n                for (;;) {\n                    if (nexttoken.id === '(end)') {\n                        error(\"Missing '}' to match '{' from line {a}.\",\n                                nexttoken, t.line);\n                    } else if (nexttoken.id === '}') {\n                        warning(\"Unexpected comma.\", token);\n                        break;\n                    } else if (nexttoken.id === ',') {\n                        error(\"Unexpected comma.\", nexttoken);\n                    } else if (nexttoken.id !== '(string)') {\n                        warning(\"Expected a string and instead saw {a}.\",\n                                nexttoken, nexttoken.value);\n                    }\n                    if (o[nexttoken.value] === true) {\n                        warning(\"Duplicate key '{a}'.\",\n                                nexttoken, nexttoken.value);\n                    } else if ((nexttoken.value === '__proto__' &&\n                        !option.proto) || (nexttoken.value === '__iterator__' &&\n                        !option.iterator)) {\n                        warning(\"The '{a}' key may produce unexpected results.\",\n                            nexttoken, nexttoken.value);\n                    } else {\n                        o[nexttoken.value] = true;\n                    }\n                    advance();\n                    advance(':');\n                    jsonValue();\n                    if (nexttoken.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                }\n            }\n            advance('}');\n        }\n\n        function jsonArray() {\n            var t = nexttoken;\n            advance('[');\n            if (nexttoken.id !== ']') {\n                for (;;) {\n                    if (nexttoken.id === '(end)') {\n                        error(\"Missing ']' to match '[' from line {a}.\",\n                                nexttoken, t.line);\n                    } else if (nexttoken.id === ']') {\n                        warning(\"Unexpected comma.\", token);\n                        break;\n                    } else if (nexttoken.id === ',') {\n                        error(\"Unexpected comma.\", nexttoken);\n                    }\n                    jsonValue();\n                    if (nexttoken.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                }\n            }\n            advance(']');\n        }\n\n        switch (nexttoken.id) {\n        case '{':\n            jsonObject();\n            break;\n        case '[':\n            jsonArray();\n            break;\n        case 'true':\n        case 'false':\n        case 'null':\n        case '(number)':\n        case '(string)':\n            advance();\n            break;\n        case '-':\n            advance('-');\n            if (token.character !== nexttoken.from) {\n                warning(\"Unexpected space after '-'.\", token);\n            }\n            adjacent(token, nexttoken);\n            advance('(number)');\n            break;\n        default:\n            error(\"Expected a JSON value.\", nexttoken);\n        }\n    }\n\n\n// The actual JSHINT function itself.\n\n    var itself = function (s, o, g) {\n        var a, i, k;\n        JSHINT.errors = [];\n        JSHINT.undefs = [];\n        predefined = Object.create(standard);\n        combine(predefined, g || {});\n        if (o) {\n            a = o.predef;\n            if (a) {\n                if (Array.isArray(a)) {\n                    for (i = 0; i < a.length; i += 1) {\n                        predefined[a[i]] = true;\n                    }\n                } else if (typeof a === 'object') {\n                    k = Object.keys(a);\n                    for (i = 0; i < k.length; i += 1) {\n                        predefined[k[i]] = !!a[k[i]];\n                    }\n                }\n            }\n            option = o;\n        } else {\n            option = {};\n        }\n        option.indent = option.indent || 4;\n        option.maxerr = option.maxerr || 50;\n\n        tab = '';\n        for (i = 0; i < option.indent; i += 1) {\n            tab += ' ';\n        }\n        indent = 1;\n        global = Object.create(predefined);\n        scope = global;\n        funct = {\n            '(global)': true,\n            '(name)': '(global)',\n            '(scope)': scope,\n            '(breakage)': 0,\n            '(loopage)': 0\n        };\n        functions = [funct];\n        urls = [];\n        stack = null;\n        member = {};\n        membersOnly = null;\n        implied = {};\n        inblock = false;\n        lookahead = [];\n        jsonmode = false;\n        warnings = 0;\n        lex.init(s);\n        prereg = true;\n        directive = {};\n\n        prevtoken = token = nexttoken = syntax['(begin)'];\n\n        // Check options\n        for (var name in o) {\n            if (is_own(o, name)) {\n                checkOption(name, token);\n            }\n        }\n\n        assume();\n\n        // combine the passed globals after we've assumed all our options\n        combine(predefined, g || {});\n\n        //reset values\n        comma.first = true;\n\n        try {\n            advance();\n            switch (nexttoken.id) {\n            case '{':\n            case '[':\n                option.laxbreak = true;\n                jsonmode = true;\n                jsonValue();\n                break;\n            default:\n                directives();\n                if (directive[\"use strict\"] && !option.globalstrict) {\n                    warning(\"Use the function form of \\\"use strict\\\".\", prevtoken);\n                }\n\n                statements();\n            }\n            advance('(end)');\n\n            var markDefined = function (name, context) {\n                do {\n                    if (typeof context[name] === 'string') {\n                        // JSHINT marks unused variables as 'unused' and\n                        // unused function declaration as 'unction'. This\n                        // code changes such instances back 'var' and\n                        // 'closure' so that the code in JSHINT.data()\n                        // doesn't think they're unused.\n\n                        if (context[name] === 'unused')\n                            context[name] = 'var';\n                        else if (context[name] === 'unction')\n                            context[name] = 'closure';\n\n                        return true;\n                    }\n\n                    context = context['(context)'];\n                } while (context);\n\n                return false;\n            };\n\n            var clearImplied = function (name, line) {\n                if (!implied[name])\n                    return;\n\n                var newImplied = [];\n                for (var i = 0; i < implied[name].length; i += 1) {\n                    if (implied[name][i] !== line)\n                        newImplied.push(implied[name][i]);\n                }\n\n                if (newImplied.length === 0)\n                    delete implied[name];\n                else\n                    implied[name] = newImplied;\n            };\n\n            // Check queued 'x is not defined' instances to see if they're still undefined.\n            for (i = 0; i < JSHINT.undefs.length; i += 1) {\n                k = JSHINT.undefs[i].slice(0);\n\n                if (markDefined(k[2].value, k[0])) {\n                    clearImplied(k[2].value, k[2].line);\n                } else {\n                    warning.apply(warning, k.slice(1));\n                }\n            }\n        } catch (e) {\n            if (e) {\n                var nt = nexttoken || {};\n                JSHINT.errors.push({\n                    raw       : e.raw,\n                    reason    : e.message,\n                    line      : e.line || nt.line,\n                    character : e.character || nt.from\n                }, null);\n            }\n        }\n\n        return JSHINT.errors.length === 0;\n    };\n\n    // Data summary.\n    itself.data = function () {\n\n        var data = { functions: [], options: option }, fu, globals, implieds = [], f, i, j,\n            members = [], n, unused = [], v;\n        if (itself.errors.length) {\n            data.errors = itself.errors;\n        }\n\n        if (jsonmode) {\n            data.json = true;\n        }\n\n        for (n in implied) {\n            if (is_own(implied, n)) {\n                implieds.push({\n                    name: n,\n                    line: implied[n]\n                });\n            }\n        }\n        if (implieds.length > 0) {\n            data.implieds = implieds;\n        }\n\n        if (urls.length > 0) {\n            data.urls = urls;\n        }\n\n        globals = Object.keys(scope);\n        if (globals.length > 0) {\n            data.globals = globals;\n        }\n        for (i = 1; i < functions.length; i += 1) {\n            f = functions[i];\n            fu = {};\n            for (j = 0; j < functionicity.length; j += 1) {\n                fu[functionicity[j]] = [];\n            }\n            for (n in f) {\n                if (is_own(f, n) && n.charAt(0) !== '(') {\n                    v = f[n];\n                    if (v === 'unction') {\n                        v = 'unused';\n                    }\n                    if (Array.isArray(fu[v])) {\n                        fu[v].push(n);\n                        if (v === 'unused') {\n                            unused.push({\n                                name: n,\n                                line: f['(line)'],\n                                'function': f['(name)']\n                            });\n                        }\n                    }\n                }\n            }\n            for (j = 0; j < functionicity.length; j += 1) {\n                if (fu[functionicity[j]].length === 0) {\n                    delete fu[functionicity[j]];\n                }\n            }\n            fu.name = f['(name)'];\n            fu.param = f['(params)'];\n            fu.line = f['(line)'];\n            fu.last = f['(last)'];\n            data.functions.push(fu);\n        }\n\n        if (unused.length > 0) {\n            data.unused = unused;\n        }\n\n        members = [];\n        for (n in member) {\n            if (typeof member[n] === 'number') {\n                data.member = member;\n                break;\n            }\n        }\n\n        return data;\n    };\n\n    itself.report = function (option) {\n        var data = itself.data();\n\n        var a = [], c, e, err, f, i, k, l, m = '', n, o = [], s;\n\n        function detail(h, array) {\n            var b, i, singularity;\n            if (array) {\n                o.push('<div><i>' + h + '</i> ');\n                array = array.sort();\n                for (i = 0; i < array.length; i += 1) {\n                    if (array[i] !== singularity) {\n                        singularity = array[i];\n                        o.push((b ? ', ' : '') + singularity);\n                        b = true;\n                    }\n                }\n                o.push('</div>');\n            }\n        }\n\n\n        if (data.errors || data.implieds || data.unused) {\n            err = true;\n            o.push('<div id=errors><i>Error:</i>');\n            if (data.errors) {\n                for (i = 0; i < data.errors.length; i += 1) {\n                    c = data.errors[i];\n                    if (c) {\n                        e = c.evidence || '';\n                        o.push('<p>Problem' + (isFinite(c.line) ? ' at line ' +\n                                c.line + ' character ' + c.character : '') +\n                                ': ' + c.reason.entityify() +\n                                '</p><p class=evidence>' +\n                                (e && (e.length > 80 ? e.slice(0, 77) + '...' :\n                                e).entityify()) + '</p>');\n                    }\n                }\n            }\n\n            if (data.implieds) {\n                s = [];\n                for (i = 0; i < data.implieds.length; i += 1) {\n                    s[i] = '<code>' + data.implieds[i].name + '</code>&nbsp;<i>' +\n                        data.implieds[i].line + '</i>';\n                }\n                o.push('<p><i>Implied global:</i> ' + s.join(', ') + '</p>');\n            }\n\n            if (data.unused) {\n                s = [];\n                for (i = 0; i < data.unused.length; i += 1) {\n                    s[i] = '<code><u>' + data.unused[i].name + '</u></code>&nbsp;<i>' +\n                        data.unused[i].line + '</i> <code>' +\n                        data.unused[i]['function'] + '</code>';\n                }\n                o.push('<p><i>Unused variable:</i> ' + s.join(', ') + '</p>');\n            }\n            if (data.json) {\n                o.push('<p>JSON: bad.</p>');\n            }\n            o.push('</div>');\n        }\n\n        if (!option) {\n\n            o.push('<br><div id=functions>');\n\n            if (data.urls) {\n                detail(\"URLs<br>\", data.urls, '<br>');\n            }\n\n            if (data.json && !err) {\n                o.push('<p>JSON: good.</p>');\n            } else if (data.globals) {\n                o.push('<div><i>Global</i> ' +\n                        data.globals.sort().join(', ') + '</div>');\n            } else {\n                o.push('<div><i>No new global variables introduced.</i></div>');\n            }\n\n            for (i = 0; i < data.functions.length; i += 1) {\n                f = data.functions[i];\n\n                o.push('<br><div class=function><i>' + f.line + '-' +\n                        f.last + '</i> ' + (f.name || '') + '(' +\n                        (f.param ? f.param.join(', ') : '') + ')</div>');\n                detail('<big><b>Unused</b></big>', f.unused);\n                detail('Closure', f.closure);\n                detail('Variable', f['var']);\n                detail('Exception', f.exception);\n                detail('Outer', f.outer);\n                detail('Global', f.global);\n                detail('Label', f.label);\n            }\n\n            if (data.member) {\n                a = Object.keys(data.member);\n                if (a.length) {\n                    a = a.sort();\n                    m = '<br><pre id=members>/*members ';\n                    l = 10;\n                    for (i = 0; i < a.length; i += 1) {\n                        k = a[i];\n                        n = k.name();\n                        if (l + n.length > 72) {\n                            o.push(m + '<br>');\n                            m = '    ';\n                            l = 1;\n                        }\n                        l += n.length + 2;\n                        if (data.member[k] === 1) {\n                            n = '<i>' + n + '</i>';\n                        }\n                        if (i < a.length - 1) {\n                            n += ', ';\n                        }\n                        m += n;\n                    }\n                    o.push(m + '<br>*/</pre>');\n                }\n                o.push('</div>');\n            }\n        }\n        return o.join('');\n    };\n\n    itself.jshint = itself;\n\n    return itself;\n}());\n\n// Make JSHINT a Node module, if possible.\nif (typeof exports === 'object' && exports)\n    exports.JSHINT = JSHINT;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/worker/jslint.js",
    "content": "define(function(require, exports, module) {\n// jslint.js\n// 2012-03-15\n\n// Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)\n\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n\n// The Software shall be used for Good, not Evil.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\n// WARNING: JSLint will hurt your feelings.\n\n// JSLINT is a global function. It takes two parameters.\n\n//     var myResult = JSLINT(source, option);\n\n// The first parameter is either a string or an array of strings. If it is a\n// string, it will be split on '\\n' or '\\r'. If it is an array of strings, it\n// is assumed that each string represents one line. The source can be a\n// JavaScript text, or HTML text, or a JSON text, or a CSS text.\n\n// The second parameter is an optional object of options that control the\n// operation of JSLINT. Most of the options are booleans: They are all\n// optional and have a default value of false. One of the options, predef,\n// can be an array of names, which will be used to declare global variables,\n// or an object whose keys are used as global names, with a boolean value\n// that determines if they are assignable.\n\n// If it checks out, JSLINT returns true. Otherwise, it returns false.\n\n// If false, you can inspect JSLINT.errors to find out the problems.\n// JSLINT.errors is an array of objects containing these properties:\n\n//  {\n//      line      : The line (relative to 0) at which the lint was found\n//      character : The character (relative to 0) at which the lint was found\n//      reason    : The problem\n//      evidence  : The text line in which the problem occurred\n//      raw       : The raw message before the details were inserted\n//      a         : The first detail\n//      b         : The second detail\n//      c         : The third detail\n//      d         : The fourth detail\n//  }\n\n// If a stopping error was found, a null will be the last element of the\n// JSLINT.errors array. A stopping error means that JSLint was not confident\n// enough to continue. It does not necessarily mean that the error was\n// especially heinous.\n\n// You can request a Function Report, which shows all of the functions\n// and the parameters and vars that they use. This can be used to find\n// implied global variables and other problems. The report is in HTML and\n// can be inserted in an HTML <body>.\n\n//     var myReport = JSLINT.report(errors_only);\n\n// If errors_only is true, then the report will be limited to only errors.\n\n// You can request a data structure that contains JSLint's results.\n\n//     var myData = JSLINT.data();\n\n// It returns a structure with this form:\n\n//     {\n//         errors: [\n//             {\n//                 line: NUMBER,\n//                 character: NUMBER,\n//                 reason: STRING,\n//                 evidence: STRING\n//             }\n//         ],\n//         functions: [\n//             {\n//                 name: STRING,\n//                 line: NUMBER,\n//                 last: NUMBER,\n//                 params: [\n//                     {\n//                         string: STRING\n//                     }\n//                 ],\n//                 closure: [\n//                     STRING\n//                 ],\n//                 var: [\n//                     STRING\n//                 ],\n//                 exception: [\n//                     STRING\n//                 ],\n//                 outer: [\n//                     STRING\n//                 ],\n//                 unused: [\n//                     STRING\n//                 ],\n//                 undef: [\n//                     STRING\n//                 ],\n//                 global: [\n//                     STRING\n//                 ],\n//                 label: [\n//                     STRING\n//                 ]\n//             }\n//         ],\n//         globals: [\n//             STRING\n//         ],\n//         member: {\n//             STRING: NUMBER\n//         },\n//         urls: [\n//             STRING\n//         ],\n//         json: BOOLEAN\n//     }\n\n// Empty arrays will not be included.\n\n// You can obtain the parse tree that JSLint constructed while parsing. The\n// latest tree is kept in JSLINT.tree. A nice stringication can be produced\n// with\n\n//     JSON.stringify(JSLINT.tree, [\n//         'string',  'arity', 'name',  'first',\n//         'second', 'third', 'block', 'else'\n//     ], 4));\n\n// JSLint provides three directives. They look like slashstar comments, and\n// allow for setting options, declaring global variables, and establishing a\n// set of allowed property names.\n\n// These directives respect function scope.\n\n// The jslint directive is a special comment that can set one or more options.\n// The current option set is\n\n//     anon       true, if the space may be omitted in anonymous function declarations\n//     bitwise    true, if bitwise operators should be allowed\n//     browser    true, if the standard browser globals should be predefined\n//     cap        true, if upper case HTML should be allowed\n//     'continue' true, if the continuation statement should be tolerated\n//     css        true, if CSS workarounds should be tolerated\n//     debug      true, if debugger statements should be allowed\n//     devel      true, if logging should be allowed (console, alert, etc.)\n//     eqeq       true, if == should be allowed\n//     es5        true, if ES5 syntax should be allowed\n//     evil       true, if eval should be allowed\n//     forin      true, if for in statements need not filter\n//     fragment   true, if HTML fragments should be allowed\n//     indent     the indentation factor\n//     maxerr     the maximum number of errors to allow\n//     maxlen     the maximum length of a source line\n//     newcap     true, if constructor names capitalization is ignored\n//     node       true, if Node.js globals should be predefined\n//     nomen      true, if names may have dangling _\n//     on         true, if HTML event handlers should be allowed\n//     passfail   true, if the scan should stop on first error\n//     plusplus   true, if increment/decrement should be allowed\n//     properties true, if all property names must be declared with /*properties*/\n//     regexp     true, if the . should be allowed in regexp literals\n//     rhino      true, if the Rhino environment globals should be predefined\n//     undef      true, if variables can be declared out of order\n//     unparam    true, if unused parameters should be tolerated\n//     sloppy     true, if the 'use strict'; pragma is optional\n//     sub        true, if all forms of subscript notation are tolerated\n//     vars       true, if multiple var statements per function should be allowed\n//     white      true, if sloppy whitespace is tolerated\n//     widget     true  if the Yahoo Widgets globals should be predefined\n//     windows    true, if MS Windows-specific globals should be predefined\n\n// For example:\n\n/*jslint\n    evil: true, nomen: true, regexp: true\n*/\n\n// The properties directive declares an exclusive list of property names.\n// Any properties named in the program that are not in the list will\n// produce a warning.\n\n// For example:\n\n/*properties\n    '\\b', '\\t', '\\n', '\\f', '\\r', '!=', '!==', '\"', '%', '\\'', '(arguments)',\n    '(begin)', '(breakage)', '(context)', '(error)', '(identifier)', '(line)',\n    '(loopage)', '(name)', '(params)', '(scope)', '(token)', '(vars)', '(verb)',\n    '*', '+', '-', '/', '<', '<=', '==', '===', '>', '>=', ADSAFE,\n    Array, Date, Function, Object, '\\\\', a, a_label, a_not_allowed,\n    a_not_defined, a_scope, abbr, acronym, address, adsafe, adsafe_a,\n    adsafe_autocomplete, adsafe_bad_id, adsafe_div, adsafe_fragment, adsafe_go,\n    adsafe_html, adsafe_id, adsafe_id_go, adsafe_lib, adsafe_lib_second,\n    adsafe_missing_id, adsafe_name_a, adsafe_placement, adsafe_prefix_a,\n    adsafe_script, adsafe_source, adsafe_subscript_a, adsafe_tag, all,\n    already_defined, and, anon, applet, apply, approved, area, arity, article,\n    aside, assign, assign_exception, assignment_function_expression, at,\n    attribute_case_a, audio, autocomplete, avoid_a, b, background,\n    'background-attachment', 'background-color', 'background-image',\n    'background-position', 'background-repeat', bad_assignment, bad_color_a,\n    bad_constructor, bad_entity, bad_html, bad_id_a, bad_in_a, bad_invocation,\n    bad_name_a, bad_new, bad_number, bad_operand, bad_style, bad_type, bad_url_a,\n    bad_wrap, base, bdo, big, bitwise, block, blockquote, body, border,\n    'border-bottom', 'border-bottom-color', 'border-bottom-left-radius',\n    'border-bottom-right-radius', 'border-bottom-style', 'border-bottom-width',\n    'border-collapse', 'border-color', 'border-left', 'border-left-color',\n    'border-left-style', 'border-left-width', 'border-radius', 'border-right',\n    'border-right-color', 'border-right-style', 'border-right-width',\n    'border-spacing', 'border-style', 'border-top', 'border-top-color',\n    'border-top-left-radius', 'border-top-right-radius', 'border-top-style',\n    'border-top-width', 'border-width', bottom, br, braille, browser, button, c,\n    call, canvas, cap, caption, 'caption-side', center, charAt, charCodeAt,\n    character, cite, clear, clip, closure, cm, code, col, colgroup, color,\n    combine_var, command, conditional_assignment, confusing_a, confusing_regexp,\n    constructor_name_a, content, continue, control_a, 'counter-increment',\n    'counter-reset', create, css, cursor, d, dangerous_comment, dangling_a, data,\n    datalist, dd, debug, del, deleted, details, devel, dfn, dialog, dir,\n    direction, display, disrupt, div, dl, dt, duplicate_a, edge, edition, else,\n    em, embed, embossed, empty, 'empty-cells', empty_block, empty_case,\n    empty_class, entityify, eqeq, errors, es5, eval, evidence, evil, ex,\n    exception, exec, expected_a, expected_a_at_b_c, expected_a_b,\n    expected_a_b_from_c_d, expected_at_a, expected_attribute_a,\n    expected_attribute_value_a, expected_class_a, expected_fraction_a,\n    expected_id_a, expected_identifier_a, expected_identifier_a_reserved,\n    expected_lang_a, expected_linear_a, expected_media_a, expected_name_a,\n    expected_nonstandard_style_attribute, expected_number_a, expected_operator_a,\n    expected_percent_a, expected_positive_a, expected_pseudo_a,\n    expected_selector_a, expected_small_a, expected_space_a_b, expected_string_a,\n    expected_style_attribute, expected_style_pattern, expected_tagname_a,\n    expected_type_a, f, fieldset, figure, filter, first, flag, float, floor,\n    font, 'font-family', 'font-size', 'font-size-adjust', 'font-stretch',\n    'font-style', 'font-variant', 'font-weight', footer, forEach, for_if, forin,\n    form, fragment, frame, frameset, from, fromCharCode, fud, funct, function,\n    function_block, function_eval, function_loop, function_statement,\n    function_strict, functions, global, globals, h1, h2, h3, h4, h5, h6,\n    handheld, hasOwnProperty, head, header, height, hgroup, hr,\n    'hta:application', html, html_confusion_a, html_handlers, i, id, identifier,\n    identifier_function, iframe, img, immed, implied_evil, in, indent, indexOf,\n    infix_in, init, input, ins, insecure_a, isAlpha, isArray, isDigit, isNaN,\n    join, jslint, json, kbd, keygen, keys, label, labeled, lang, lbp,\n    leading_decimal_a, led, left, legend, length, 'letter-spacing', li, lib,\n    line, 'line-height', link, 'list-style', 'list-style-image',\n    'list-style-position', 'list-style-type', map, margin, 'margin-bottom',\n    'margin-left', 'margin-right', 'margin-top', mark, 'marker-offset', match,\n    'max-height', 'max-width', maxerr, maxlen, member, menu, message, meta,\n    meter, 'min-height', 'min-width', missing_a, missing_a_after_b,\n    missing_option, missing_property, missing_space_a_b, missing_url,\n    missing_use_strict, mixed, mm, mode, move_invocation, move_var, n, name,\n    name_function, nav, nested_comment, newcap, node, noframes, nomen, noscript,\n    not, not_a_constructor, not_a_defined, not_a_function, not_a_label,\n    not_a_scope, not_greater, nud, number, object, octal_a, ol, on, opacity,\n    open, optgroup, option, outer, outline, 'outline-color', 'outline-style',\n    'outline-width', output, overflow, 'overflow-x', 'overflow-y', p, padding,\n    'padding-bottom', 'padding-left', 'padding-right', 'padding-top',\n    'page-break-after', 'page-break-before', param, parameter_a_get_b,\n    parameter_arguments_a, parameter_set_a, params, paren, parent, passfail, pc,\n    plusplus, pop, position, postscript, pre, predef, print, progress,\n    projection, properties, prototype, pt, push, px, q, quote, quotes, r, radix,\n    range, raw, read_only, reason, redefinition_a, regexp, replace, report,\n    reserved, reserved_a, rhino, right, rp, rt, ruby, safe, samp, scanned_a_b,\n    screen, script, search, second, section, select, shift, slash_equal, slice,\n    sloppy, small, sort, source, span, speech, split, src, statement_block,\n    stopping, strange_loop, strict, string, strong, style, styleproperty, sub,\n    subscript, substr, sup, supplant, t, table, 'table-layout', tag_a_in_b,\n    tbody, td, test, 'text-align', 'text-decoration', 'text-indent',\n    'text-shadow', 'text-transform', textarea, tfoot, th, thead, third, thru,\n    time, title, toLowerCase, toString, toUpperCase, token, too_long, too_many,\n    top, tr, trailing_decimal_a, tree, tt, tty, tv, type, u, ul, unclosed,\n    unclosed_comment, unclosed_regexp, undef, undefined, unescaped_a,\n    unexpected_a, unexpected_char_a_b, unexpected_comment, unexpected_else,\n    unexpected_label_a, unexpected_property_a, unexpected_space_a_b,\n    'unicode-bidi', unnecessary_initialize, unnecessary_use, unparam,\n    unreachable_a_b, unrecognized_style_attribute_a, unrecognized_tag_a, unsafe,\n    unused, url, urls, use_array, use_braces, use_charAt, use_object, use_or,\n    use_param, used_before_a, var, var_a_not, vars, 'vertical-align', video,\n    visibility, was, weird_assignment, weird_condition, weird_new,\n    weird_program, weird_relation, weird_ternary, white, 'white-space', widget,\n    width, windows, 'word-spacing', 'word-wrap', wrap, wrap_immediate,\n    wrap_regexp, write_is_wrong, writeable, 'z-index'\n*/\n\n// The global directive is used to declare global variables that can\n// be accessed by the program. If a declaration is true, then the variable\n// is writeable. Otherwise, it is read-only.\n\n// We build the application inside a function so that we produce only a single\n// global variable. That function will be invoked immediately, and its return\n// value is the JSLINT function itself. That function is also an object that\n// can contain data and other functions.\n\nvar JSLINT = (function () {\n    'use strict';\n\n    function array_to_object(array, value) {\n\n// Make an object from an array of keys and a common value.\n\n        var i, length = array.length, object = {};\n        for (i = 0; i < length; i += 1) {\n            object[array[i]] = value;\n        }\n        return object;\n    }\n\n\n    var adsafe_id,      // The widget's ADsafe id.\n        adsafe_may,     // The widget may load approved scripts.\n        adsafe_top,     // At the top of the widget script.\n        adsafe_went,    // ADSAFE.go has been called.\n        allowed_option = {\n            anon      : true,\n            bitwise   : true,\n            browser   : true,\n            cap       : true,\n            'continue': true,\n            css       : true,\n            debug     : true,\n            devel     : true,\n            eqeq      : true,\n            es5       : true,\n            evil      : true,\n            forin     : true,\n            fragment  : true,\n            indent    :   10,\n            maxerr    : 1000,\n            maxlen    :  256,\n            newcap    : true,\n            node      : true,\n            nomen     : true,\n            on        : true,\n            passfail  : true,\n            plusplus  : true,\n            properties: true,\n            regexp    : true,\n            rhino     : true,\n            undef     : true,\n            unparam   : true,\n            sloppy    : true,\n            sub       : true,\n            vars      : true,\n            white     : true,\n            widget    : true,\n            windows   : true\n        },\n        anonname,       // The guessed name for anonymous functions.\n        approved,       // ADsafe approved urls.\n\n// These are operators that should not be used with the ! operator.\n\n        bang = {\n            '<'  : true,\n            '<=' : true,\n            '==' : true,\n            '===': true,\n            '!==': true,\n            '!=' : true,\n            '>'  : true,\n            '>=' : true,\n            '+'  : true,\n            '-'  : true,\n            '*'  : true,\n            '/'  : true,\n            '%'  : true\n        },\n\n// These are property names that should not be permitted in the safe subset.\n\n        banned = array_to_object([\n            'arguments', 'callee', 'caller', 'constructor', 'eval', 'prototype',\n            'stack', 'unwatch', 'valueOf', 'watch'\n        ], true),\n        begin,          // The root token\n\n// browser contains a set of global names that are commonly provided by a\n// web browser environment.\n\n        browser = array_to_object([\n            'clearInterval', 'clearTimeout', 'document', 'event', 'FormData',\n            'frames', 'history', 'Image', 'localStorage', 'location', 'name',\n            'navigator', 'Option', 'parent', 'screen', 'sessionStorage',\n            'setInterval', 'setTimeout', 'Storage', 'window', 'XMLHttpRequest'\n        ], false),\n\n// bundle contains the text messages.\n\n        bundle = {\n            a_label: \"'{a}' is a statement label.\",\n            a_not_allowed: \"'{a}' is not allowed.\",\n            a_not_defined: \"'{a}' is not defined.\",\n            a_scope: \"'{a}' used out of scope.\",\n            adsafe_a: \"ADsafe violation: '{a}'.\",\n            adsafe_autocomplete: \"ADsafe autocomplete violation.\",\n            adsafe_bad_id: \"ADSAFE violation: bad id.\",\n            adsafe_div: \"ADsafe violation: Wrap the widget in a div.\",\n            adsafe_fragment: \"ADSAFE: Use the fragment option.\",\n            adsafe_go: \"ADsafe violation: Misformed ADSAFE.go.\",\n            adsafe_html: \"Currently, ADsafe does not operate on whole HTML \" +\n                \"documents. It operates on <div> fragments and .js files.\",\n            adsafe_id: \"ADsafe violation: id does not match.\",\n            adsafe_id_go: \"ADsafe violation: Missing ADSAFE.id or ADSAFE.go.\",\n            adsafe_lib: \"ADsafe lib violation.\",\n            adsafe_lib_second: \"ADsafe: The second argument to lib must be a function.\",\n            adsafe_missing_id: \"ADSAFE violation: missing ID_.\",\n            adsafe_name_a: \"ADsafe name violation: '{a}'.\",\n            adsafe_placement: \"ADsafe script placement violation.\",\n            adsafe_prefix_a: \"ADsafe violation: An id must have a '{a}' prefix\",\n            adsafe_script: \"ADsafe script violation.\",\n            adsafe_source: \"ADsafe unapproved script source.\",\n            adsafe_subscript_a: \"ADsafe subscript '{a}'.\",\n            adsafe_tag: \"ADsafe violation: Disallowed tag '{a}'.\",\n            already_defined: \"'{a}' is already defined.\",\n            and: \"The '&&' subexpression should be wrapped in parens.\",\n            assign_exception: \"Do not assign to the exception parameter.\",\n            assignment_function_expression: \"Expected an assignment or \" +\n                \"function call and instead saw an expression.\",\n            attribute_case_a: \"Attribute '{a}' not all lower case.\",\n            avoid_a: \"Avoid '{a}'.\",\n            bad_assignment: \"Bad assignment.\",\n            bad_color_a: \"Bad hex color '{a}'.\",\n            bad_constructor: \"Bad constructor.\",\n            bad_entity: \"Bad entity.\",\n            bad_html: \"Bad HTML string\",\n            bad_id_a: \"Bad id: '{a}'.\",\n            bad_in_a: \"Bad for in variable '{a}'.\",\n            bad_invocation: \"Bad invocation.\",\n            bad_name_a: \"Bad name: '{a}'.\",\n            bad_new: \"Do not use 'new' for side effects.\",\n            bad_number: \"Bad number '{a}'.\",\n            bad_operand: \"Bad operand.\",\n            bad_style: \"Bad style.\",\n            bad_type: \"Bad type.\",\n            bad_url_a: \"Bad url '{a}'.\",\n            bad_wrap: \"Do not wrap function literals in parens unless they \" +\n                \"are to be immediately invoked.\",\n            combine_var: \"Combine this with the previous 'var' statement.\",\n            conditional_assignment: \"Expected a conditional expression and \" +\n                \"instead saw an assignment.\",\n            confusing_a: \"Confusing use of '{a}'.\",\n            confusing_regexp: \"Confusing regular expression.\",\n            constructor_name_a: \"A constructor name '{a}' should start with \" +\n                \"an uppercase letter.\",\n            control_a: \"Unexpected control character '{a}'.\",\n            css: \"A css file should begin with @charset 'UTF-8';\",\n            dangling_a: \"Unexpected dangling '_' in '{a}'.\",\n            dangerous_comment: \"Dangerous comment.\",\n            deleted: \"Only properties should be deleted.\",\n            duplicate_a: \"Duplicate '{a}'.\",\n            empty_block: \"Empty block.\",\n            empty_case: \"Empty case.\",\n            empty_class: \"Empty class.\",\n            es5: \"This is an ES5 feature.\",\n            evil: \"eval is evil.\",\n            expected_a: \"Expected '{a}'.\",\n            expected_a_b: \"Expected '{a}' and instead saw '{b}'.\",\n            expected_a_b_from_c_d: \"Expected '{a}' to match '{b}' from line \" +\n                \"{c} and instead saw '{d}'.\",\n            expected_at_a: \"Expected an at-rule, and instead saw @{a}.\",\n            expected_a_at_b_c: \"Expected '{a}' at column {b}, not column {c}.\",\n            expected_attribute_a: \"Expected an attribute, and instead saw [{a}].\",\n            expected_attribute_value_a: \"Expected an attribute value and \" +\n                \"instead saw '{a}'.\",\n            expected_class_a: \"Expected a class, and instead saw .{a}.\",\n            expected_fraction_a: \"Expected a number between 0 and 1 and \" +\n                \"instead saw '{a}'\",\n            expected_id_a: \"Expected an id, and instead saw #{a}.\",\n            expected_identifier_a: \"Expected an identifier and instead saw '{a}'.\",\n            expected_identifier_a_reserved: \"Expected an identifier and \" +\n                \"instead saw '{a}' (a reserved word).\",\n            expected_linear_a: \"Expected a linear unit and instead saw '{a}'.\",\n            expected_lang_a: \"Expected a lang code, and instead saw :{a}.\",\n            expected_media_a: \"Expected a CSS media type, and instead saw '{a}'.\",\n            expected_name_a: \"Expected a name and instead saw '{a}'.\",\n            expected_nonstandard_style_attribute: \"Expected a non-standard \" +\n                \"style attribute and instead saw '{a}'.\",\n            expected_number_a: \"Expected a number and instead saw '{a}'.\",\n            expected_operator_a: \"Expected an operator and instead saw '{a}'.\",\n            expected_percent_a: \"Expected a percentage and instead saw '{a}'\",\n            expected_positive_a: \"Expected a positive number and instead saw '{a}'\",\n            expected_pseudo_a: \"Expected a pseudo, and instead saw :{a}.\",\n            expected_selector_a: \"Expected a CSS selector, and instead saw {a}.\",\n            expected_small_a: \"Expected a small positive integer and instead saw '{a}'\",\n            expected_space_a_b: \"Expected exactly one space between '{a}' and '{b}'.\",\n            expected_string_a: \"Expected a string and instead saw {a}.\",\n            expected_style_attribute: \"Excepted a style attribute, and instead saw '{a}'.\",\n            expected_style_pattern: \"Expected a style pattern, and instead saw '{a}'.\",\n            expected_tagname_a: \"Expected a tagName, and instead saw {a}.\",\n            expected_type_a: \"Expected a type, and instead saw {a}.\",\n            for_if: \"The body of a for in should be wrapped in an if \" +\n                \"statement to filter unwanted properties from the prototype.\",\n            function_block: \"Function statements should not be placed in blocks. \" +\n                \"Use a function expression or move the statement to the top of \" +\n                \"the outer function.\",\n            function_eval: \"The Function constructor is eval.\",\n            function_loop: \"Don't make functions within a loop.\",\n            function_statement: \"Function statements are not invocable. \" +\n                \"Wrap the whole function invocation in parens.\",\n            function_strict: \"Use the function form of 'use strict'.\",\n            html_confusion_a: \"HTML confusion in regular expression '<{a}'.\",\n            html_handlers: \"Avoid HTML event handlers.\",\n            identifier_function: \"Expected an identifier in an assignment \" +\n                \"and instead saw a function invocation.\",\n            implied_evil: \"Implied eval is evil. Pass a function instead of a string.\",\n            infix_in: \"Unexpected 'in'. Compare with undefined, or use the \" +\n                \"hasOwnProperty method instead.\",\n            insecure_a: \"Insecure '{a}'.\",\n            isNaN: \"Use the isNaN function to compare with NaN.\",\n            lang: \"lang is deprecated.\",\n            leading_decimal_a: \"A leading decimal point can be confused with a dot: '.{a}'.\",\n            missing_a: \"Missing '{a}'.\",\n            missing_a_after_b: \"Missing '{a}' after '{b}'.\",\n            missing_option: \"Missing option value.\",\n            missing_property: \"Missing property name.\",\n            missing_space_a_b: \"Missing space between '{a}' and '{b}'.\",\n            missing_url: \"Missing url.\",\n            missing_use_strict: \"Missing 'use strict' statement.\",\n            mixed: \"Mixed spaces and tabs.\",\n            move_invocation: \"Move the invocation into the parens that \" +\n                \"contain the function.\",\n            move_var: \"Move 'var' declarations to the top of the function.\",\n            name_function: \"Missing name in function statement.\",\n            nested_comment: \"Nested comment.\",\n            not: \"Nested not.\",\n            not_a_constructor: \"Do not use {a} as a constructor.\",\n            not_a_defined: \"'{a}' has not been fully defined yet.\",\n            not_a_function: \"'{a}' is not a function.\",\n            not_a_label: \"'{a}' is not a label.\",\n            not_a_scope: \"'{a}' is out of scope.\",\n            not_greater: \"'{a}' should not be greater than '{b}'.\",\n            octal_a: \"Don't use octal: '{a}'. Use '\\\\u....' instead.\",\n            parameter_arguments_a: \"Do not mutate parameter '{a}' when using 'arguments'.\",\n            parameter_a_get_b: \"Unexpected parameter '{a}' in get {b} function.\",\n            parameter_set_a: \"Expected parameter (value) in set {a} function.\",\n            radix: \"Missing radix parameter.\",\n            read_only: \"Read only.\",\n            redefinition_a: \"Redefinition of '{a}'.\",\n            reserved_a: \"Reserved name '{a}'.\",\n            scanned_a_b: \"{a} ({b}% scanned).\",\n            slash_equal: \"A regular expression literal can be confused with '/='.\",\n            statement_block: \"Expected to see a statement and instead saw a block.\",\n            stopping: \"Stopping. \",\n            strange_loop: \"Strange loop.\",\n            strict: \"Strict violation.\",\n            subscript: \"['{a}'] is better written in dot notation.\",\n            tag_a_in_b: \"A '<{a}>' must be within '<{b}>'.\",\n            too_long: \"Line too long.\",\n            too_many: \"Too many errors.\",\n            trailing_decimal_a: \"A trailing decimal point can be confused \" +\n                \"with a dot: '.{a}'.\",\n            type: \"type is unnecessary.\",\n            unclosed: \"Unclosed string.\",\n            unclosed_comment: \"Unclosed comment.\",\n            unclosed_regexp: \"Unclosed regular expression.\",\n            unescaped_a: \"Unescaped '{a}'.\",\n            unexpected_a: \"Unexpected '{a}'.\",\n            unexpected_char_a_b: \"Unexpected character '{a}' in {b}.\",\n            unexpected_comment: \"Unexpected comment.\",\n            unexpected_else: \"Unexpected 'else' after 'return'.\",\n            unexpected_label_a: \"Unexpected label '{a}'.\",\n            unexpected_property_a: \"Unexpected /*property*/ '{a}'.\",\n            unexpected_space_a_b: \"Unexpected space between '{a}' and '{b}'.\",\n            unnecessary_initialize: \"It is not necessary to initialize '{a}' \" +\n                \"to 'undefined'.\",\n            unnecessary_use: \"Unnecessary 'use strict'.\",\n            unreachable_a_b: \"Unreachable '{a}' after '{b}'.\",\n            unrecognized_style_attribute_a: \"Unrecognized style attribute '{a}'.\",\n            unrecognized_tag_a: \"Unrecognized tag '<{a}>'.\",\n            unsafe: \"Unsafe character.\",\n            url: \"JavaScript URL.\",\n            use_array: \"Use the array literal notation [].\",\n            use_braces: \"Spaces are hard to count. Use {{a}}.\",\n            use_charAt: \"Use the charAt method.\",\n            use_object: \"Use the object literal notation {}.\",\n            use_or: \"Use the || operator.\",\n            use_param: \"Use a named parameter.\",\n            used_before_a: \"'{a}' was used before it was defined.\",\n            var_a_not: \"Variable {a} was not declared correctly.\",\n            weird_assignment: \"Weird assignment.\",\n            weird_condition: \"Weird condition.\",\n            weird_new: \"Weird construction. Delete 'new'.\",\n            weird_program: \"Weird program.\",\n            weird_relation: \"Weird relation.\",\n            weird_ternary: \"Weird ternary.\",\n            wrap_immediate: \"Wrap an immediate function invocation in parentheses \" +\n                \"to assist the reader in understanding that the expression \" +\n                \"is the result of a function, and not the function itself.\",\n            wrap_regexp: \"Wrap the /regexp/ literal in parens to \" +\n                \"disambiguate the slash operator.\",\n            write_is_wrong: \"document.write can be a form of eval.\"\n        },\n        comments_off,\n        css_attribute_data,\n        css_any,\n\n        css_colorData = array_to_object([\n            \"aliceblue\", \"antiquewhite\", \"aqua\", \"aquamarine\", \"azure\", \"beige\",\n            \"bisque\", \"black\", \"blanchedalmond\", \"blue\", \"blueviolet\", \"brown\",\n            \"burlywood\", \"cadetblue\", \"chartreuse\", \"chocolate\", \"coral\",\n            \"cornflowerblue\", \"cornsilk\", \"crimson\", \"cyan\", \"darkblue\",\n            \"darkcyan\", \"darkgoldenrod\", \"darkgray\", \"darkgreen\", \"darkkhaki\",\n            \"darkmagenta\", \"darkolivegreen\", \"darkorange\", \"darkorchid\",\n            \"darkred\", \"darksalmon\", \"darkseagreen\", \"darkslateblue\",\n            \"darkslategray\", \"darkturquoise\", \"darkviolet\", \"deeppink\",\n            \"deepskyblue\", \"dimgray\", \"dodgerblue\", \"firebrick\", \"floralwhite\",\n            \"forestgreen\", \"fuchsia\", \"gainsboro\", \"ghostwhite\", \"gold\",\n            \"goldenrod\", \"gray\", \"green\", \"greenyellow\", \"honeydew\", \"hotpink\",\n            \"indianred\", \"indigo\", \"ivory\", \"khaki\", \"lavender\",\n            \"lavenderblush\", \"lawngreen\", \"lemonchiffon\", \"lightblue\",\n            \"lightcoral\", \"lightcyan\", \"lightgoldenrodyellow\", \"lightgreen\",\n            \"lightpink\", \"lightsalmon\", \"lightseagreen\", \"lightskyblue\",\n            \"lightslategray\", \"lightsteelblue\", \"lightyellow\", \"lime\",\n            \"limegreen\", \"linen\", \"magenta\", \"maroon\", \"mediumaquamarine\",\n            \"mediumblue\", \"mediumorchid\", \"mediumpurple\", \"mediumseagreen\",\n            \"mediumslateblue\", \"mediumspringgreen\", \"mediumturquoise\",\n            \"mediumvioletred\", \"midnightblue\", \"mintcream\", \"mistyrose\",\n            \"moccasin\", \"navajowhite\", \"navy\", \"oldlace\", \"olive\", \"olivedrab\",\n            \"orange\", \"orangered\", \"orchid\", \"palegoldenrod\", \"palegreen\",\n            \"paleturquoise\", \"palevioletred\", \"papayawhip\", \"peachpuff\",\n            \"peru\", \"pink\", \"plum\", \"powderblue\", \"purple\", \"red\", \"rosybrown\",\n            \"royalblue\", \"saddlebrown\", \"salmon\", \"sandybrown\", \"seagreen\",\n            \"seashell\", \"sienna\", \"silver\", \"skyblue\", \"slateblue\", \"slategray\",\n            \"snow\", \"springgreen\", \"steelblue\", \"tan\", \"teal\", \"thistle\",\n            \"tomato\", \"turquoise\", \"violet\", \"wheat\", \"white\", \"whitesmoke\",\n            \"yellow\", \"yellowgreen\",\n\n            \"activeborder\", \"activecaption\", \"appworkspace\", \"background\",\n            \"buttonface\", \"buttonhighlight\", \"buttonshadow\", \"buttontext\",\n            \"captiontext\", \"graytext\", \"highlight\", \"highlighttext\",\n            \"inactiveborder\", \"inactivecaption\", \"inactivecaptiontext\",\n            \"infobackground\", \"infotext\", \"menu\", \"menutext\", \"scrollbar\",\n            \"threeddarkshadow\", \"threedface\", \"threedhighlight\",\n            \"threedlightshadow\", \"threedshadow\", \"window\", \"windowframe\",\n            \"windowtext\"\n        ], true),\n\n        css_border_style,\n        css_break,\n\n        css_lengthData = {\n            '%': true,\n            'cm': true,\n            'em': true,\n            'ex': true,\n            'in': true,\n            'mm': true,\n            'pc': true,\n            'pt': true,\n            'px': true\n        },\n\n        css_media,\n        css_overflow,\n\n        descapes = {\n            'b': '\\b',\n            't': '\\t',\n            'n': '\\n',\n            'f': '\\f',\n            'r': '\\r',\n            '\"': '\"',\n            '/': '/',\n            '\\\\': '\\\\'\n        },\n\n        devel = array_to_object([\n            'alert', 'confirm', 'console', 'Debug', 'opera', 'prompt', 'WSH'\n        ], false),\n        directive,\n        escapes = {\n            '\\b': '\\\\b',\n            '\\t': '\\\\t',\n            '\\n': '\\\\n',\n            '\\f': '\\\\f',\n            '\\r': '\\\\r',\n            '\\'': '\\\\\\'',\n            '\"' : '\\\\\"',\n            '/' : '\\\\/',\n            '\\\\': '\\\\\\\\'\n        },\n\n        funct,          // The current function, including the labels used in\n                        // the function, as well as (breakage),\n                        // (context), (loopage), (name), (params), (token),\n                        // (vars), (verb)\n\n        functionicity = [\n            'closure', 'exception', 'global', 'label', 'outer', 'undef',\n            'unused', 'var'\n        ],\n\n        functions,      // All of the functions\n        global_funct,   // The global body\n        global_scope,   // The global scope\n        html_tag = {\n            a:        {},\n            abbr:     {},\n            acronym:  {},\n            address:  {},\n            applet:   {},\n            area:     {empty: true, parent: ' map '},\n            article:  {},\n            aside:    {},\n            audio:    {},\n            b:        {},\n            base:     {empty: true, parent: ' head '},\n            bdo:      {},\n            big:      {},\n            blockquote: {},\n            body:     {parent: ' html noframes '},\n            br:       {empty: true},\n            button:   {},\n            canvas:   {parent: ' body p div th td '},\n            caption:  {parent: ' table '},\n            center:   {},\n            cite:     {},\n            code:     {},\n            col:      {empty: true, parent: ' table colgroup '},\n            colgroup: {parent: ' table '},\n            command:  {parent: ' menu '},\n            datalist: {},\n            dd:       {parent: ' dl '},\n            del:      {},\n            details:  {},\n            dialog:   {},\n            dfn:      {},\n            dir:      {},\n            div:      {},\n            dl:       {},\n            dt:       {parent: ' dl '},\n            em:       {},\n            embed:    {},\n            fieldset: {},\n            figure:   {},\n            font:     {},\n            footer:   {},\n            form:     {},\n            frame:    {empty: true, parent: ' frameset '},\n            frameset: {parent: ' html frameset '},\n            h1:       {},\n            h2:       {},\n            h3:       {},\n            h4:       {},\n            h5:       {},\n            h6:       {},\n            head:     {parent: ' html '},\n            header:   {},\n            hgroup:   {},\n            hr:       {empty: true},\n            'hta:application':\n                      {empty: true, parent: ' head '},\n            html:     {parent: '*'},\n            i:        {},\n            iframe:   {},\n            img:      {empty: true},\n            input:    {empty: true},\n            ins:      {},\n            kbd:      {},\n            keygen:   {},\n            label:    {},\n            legend:   {parent: ' details fieldset figure '},\n            li:       {parent: ' dir menu ol ul '},\n            link:     {empty: true, parent: ' head '},\n            map:      {},\n            mark:     {},\n            menu:     {},\n            meta:     {empty: true, parent: ' head noframes noscript '},\n            meter:    {},\n            nav:      {},\n            noframes: {parent: ' html body '},\n            noscript: {parent: ' body head noframes '},\n            object:   {},\n            ol:       {},\n            optgroup: {parent: ' select '},\n            option:   {parent: ' optgroup select '},\n            output:   {},\n            p:        {},\n            param:    {empty: true, parent: ' applet object '},\n            pre:      {},\n            progress: {},\n            q:        {},\n            rp:       {},\n            rt:       {},\n            ruby:     {},\n            samp:     {},\n            script:   {empty: true, parent: ' body div frame head iframe p pre span '},\n            section:  {},\n            select:   {},\n            small:    {},\n            span:     {},\n            source:   {},\n            strong:   {},\n            style:    {parent: ' head ', empty: true},\n            sub:      {},\n            sup:      {},\n            table:    {},\n            tbody:    {parent: ' table '},\n            td:       {parent: ' tr '},\n            textarea: {},\n            tfoot:    {parent: ' table '},\n            th:       {parent: ' tr '},\n            thead:    {parent: ' table '},\n            time:     {},\n            title:    {parent: ' head '},\n            tr:       {parent: ' table tbody thead tfoot '},\n            tt:       {},\n            u:        {},\n            ul:       {},\n            'var':    {},\n            video:    {}\n        },\n\n        ids,            // HTML ids\n        in_block,\n        indent,\n        itself,         // JSLint itself\n        json_mode,\n        lex,            // the tokenizer\n        lines,\n        lookahead,\n        node = array_to_object([\n            'Buffer', 'clearInterval', 'clearTimeout', 'console', 'exports',\n            'global', 'module', 'process', 'querystring', 'require',\n            'setInterval', 'setTimeout', '__dirname', '__filename'\n        ], false),\n        node_js,\n        numbery = array_to_object(['indexOf', 'lastIndexOf', 'search'], true),\n        next_token,\n        option,\n        predefined,     // Global variables defined by option\n        prereg,\n        prev_token,\n        property,\n        regexp_flag = array_to_object(['g', 'i', 'm'], true),\n        return_this = function return_this() {\n            return this;\n        },\n        rhino = array_to_object([\n            'defineClass', 'deserialize', 'gc', 'help', 'load', 'loadClass',\n            'print', 'quit', 'readFile', 'readUrl', 'runCommand', 'seal',\n            'serialize', 'spawn', 'sync', 'toint32', 'version'\n        ], false),\n\n        scope,      // An object containing an object for each variable in scope\n        semicolon_coda = array_to_object([';', '\"', '\\'', ')'], true),\n        src,\n        stack,\n\n// standard contains the global names that are provided by the\n// ECMAScript standard.\n\n        standard = array_to_object([\n            'Array', 'Boolean', 'Date', 'decodeURI', 'decodeURIComponent',\n            'encodeURI', 'encodeURIComponent', 'Error', 'eval', 'EvalError',\n            'Function', 'isFinite', 'isNaN', 'JSON', 'Math', 'Number',\n            'Object', 'parseInt', 'parseFloat', 'RangeError', 'ReferenceError',\n            'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError'\n        ], false),\n\n        strict_mode,\n        syntax = {},\n        tab,\n        token,\n        urls,\n        var_mode,\n        warnings,\n\n// widget contains the global names which are provided to a Yahoo\n// (fna Konfabulator) widget.\n\n        widget = array_to_object([\n            'alert', 'animator', 'appleScript', 'beep', 'bytesToUIString',\n            'Canvas', 'chooseColor', 'chooseFile', 'chooseFolder',\n            'closeWidget', 'COM', 'convertPathToHFS', 'convertPathToPlatform',\n            'CustomAnimation', 'escape', 'FadeAnimation', 'filesystem', 'Flash',\n            'focusWidget', 'form', 'FormField', 'Frame', 'HotKey', 'Image',\n            'include', 'isApplicationRunning', 'iTunes', 'konfabulatorVersion',\n            'log', 'md5', 'MenuItem', 'MoveAnimation', 'openURL', 'play',\n            'Point', 'popupMenu', 'preferenceGroups', 'preferences', 'print',\n            'prompt', 'random', 'Rectangle', 'reloadWidget', 'ResizeAnimation',\n            'resolvePath', 'resumeUpdates', 'RotateAnimation', 'runCommand',\n            'runCommandInBg', 'saveAs', 'savePreferences', 'screen',\n            'ScrollBar', 'showWidgetPreferences', 'sleep', 'speak', 'Style',\n            'suppressUpdates', 'system', 'tellWidget', 'Text', 'TextArea',\n            'Timer', 'unescape', 'updateNow', 'URL', 'Web', 'widget', 'Window',\n            'XMLDOM', 'XMLHttpRequest', 'yahooCheckLogin', 'yahooLogin',\n            'yahooLogout'\n        ], true),\n\n        windows = array_to_object([\n            'ActiveXObject', 'CScript', 'Debug', 'Enumerator', 'System',\n            'VBArray', 'WScript', 'WSH'\n        ], false),\n\n//  xmode is used to adapt to the exceptions in html parsing.\n//  It can have these states:\n//      ''      .js script file\n//      'html'\n//      'outer'\n//      'script'\n//      'style'\n//      'scriptstring'\n//      'styleproperty'\n\n        xmode,\n        xquote,\n\n// Regular expressions. Some of these are stupidly long.\n\n// unsafe comment or string\n        ax = /@cc|<\\/?|script|\\]\\s*\\]|<\\s*!|&lt/i,\n// carriage return, carriage return linefeed, or linefeed\n        crlfx = /\\r\\n?|\\n/,\n// unsafe characters that are silently deleted by one or more browsers\n        cx = /[\\u0000-\\u001f\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/,\n// query characters for ids\n        dx = /[\\[\\]\\/\\\\\"'*<>.&:(){}+=#]/,\n// html token\n        hx = /^\\s*(['\"=>\\/&#]|<(?:\\/|\\!(?:--)?)?|[a-zA-Z][a-zA-Z0-9_\\-:]*|[0-9]+|--)/,\n// identifier\n        ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/,\n// javascript url\n        jx = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\\s*:/i,\n// star slash\n        lx = /\\*\\/|\\/\\*/,\n// characters in strings that need escapement\n        nx = /[\\u0000-\\u001f'\\\\\\u007f-\\u009f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n// outer html token\n        ox = /[>&]|<[\\/!]?|--/,\n// attributes characters\n        qx = /[^a-zA-Z0-9+\\-_\\/. ]/,\n// style\n        sx = /^\\s*([{}:#%.=,>+\\[\\]@()\"';]|[*$\\^~]=|[a-zA-Z_][a-zA-Z0-9_\\-]*|[0-9]+|<\\/|\\/\\*)/,\n        ssx = /^\\s*([@#!\"'};:\\-%.=,+\\[\\]()*_]|[a-zA-Z][a-zA-Z0-9._\\-]*|\\/\\*?|\\d+(?:\\.\\d+)?|<\\/)/,\n// token\n        tx = /^\\s*([(){}\\[\\]\\?.,:;'\"~#@`]|={1,3}|\\/(\\*(jslint|properties|property|members?|globals?)?|=|\\/)?|\\*[\\/=]?|\\+(?:=|\\++)?|-(?:=|-+)?|[\\^%]=?|&[&=]?|\\|[|=]?|>{1,3}=?|<(?:[\\/=!]|\\!(\\[|--)?|<=?)?|\\!={0,2}|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+(?:[xX][0-9a-fA-F]+|\\.[0-9]*)?(?:[eE][+\\-]?[0-9]+)?)/,\n// url badness\n        ux = /&|\\+|\\u00AD|\\.\\.|\\/\\*|%[^;]|base64|url|expression|data|mailto|script/i,\n\n        rx = {\n            outer: hx,\n            html: hx,\n            style: sx,\n            styleproperty: ssx\n        };\n\n\n    function F() {}     // Used by Object.create\n\n// Provide critical ES5 functions to ES3.\n\n    if (typeof Array.prototype.filter !== 'function') {\n        Array.prototype.filter = function (f) {\n            var i, length = this.length, result = [], value;\n            for (i = 0; i < length; i += 1) {\n                try {\n                    value = this[i];\n                    if (f(value)) {\n                        result.push(value);\n                    }\n                } catch (ignore) {\n                }\n            }\n            return result;\n        };\n    }\n\n    if (typeof Array.prototype.forEach !== 'function') {\n        Array.prototype.forEach = function (f) {\n            var i, length = this.length;\n            for (i = 0; i < length; i += 1) {\n                try {\n                    f(this[i]);\n                } catch (ignore) {\n                }\n            }\n        };\n    }\n\n    if (typeof Array.isArray !== 'function') {\n        Array.isArray = function (o) {\n            return Object.prototype.toString.apply(o) === '[object Array]';\n        };\n    }\n\n    if (!Object.prototype.hasOwnProperty.call(Object, 'create')) {\n        Object.create = function (o) {\n            F.prototype = o;\n            return new F();\n        };\n    }\n\n    if (typeof Object.keys !== 'function') {\n        Object.keys = function (o) {\n            var array = [], key;\n            for (key in o) {\n                if (Object.prototype.hasOwnProperty.call(o, key)) {\n                    array.push(key);\n                }\n            }\n            return array;\n        };\n    }\n\n    if (typeof String.prototype.entityify !== 'function') {\n        String.prototype.entityify = function () {\n            return this\n                .replace(/&/g, '&amp;')\n                .replace(/</g, '&lt;')\n                .replace(/>/g, '&gt;');\n        };\n    }\n\n    if (typeof String.prototype.isAlpha !== 'function') {\n        String.prototype.isAlpha = function () {\n            return (this >= 'a' && this <= 'z\\uffff') ||\n                (this >= 'A' && this <= 'Z\\uffff');\n        };\n    }\n\n    if (typeof String.prototype.isDigit !== 'function') {\n        String.prototype.isDigit = function () {\n            return (this >= '0' && this <= '9');\n        };\n    }\n\n    if (typeof String.prototype.supplant !== 'function') {\n        String.prototype.supplant = function (o) {\n            return this.replace(/\\{([^{}]*)\\}/g, function (a, b) {\n                var replacement = o[b];\n                return typeof replacement === 'string' ||\n                    typeof replacement === 'number' ? replacement : a;\n            });\n        };\n    }\n\n\n    function sanitize(a) {\n\n//  Escapify a troublesome character.\n\n        return escapes[a] ||\n            '\\\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);\n    }\n\n\n    function add_to_predefined(group) {\n        Object.keys(group).forEach(function (name) {\n            predefined[name] = group[name];\n        });\n    }\n\n\n    function assume() {\n        if (!option.safe) {\n            if (option.rhino) {\n                add_to_predefined(rhino);\n                option.rhino = false;\n            }\n            if (option.devel) {\n                add_to_predefined(devel);\n                option.devel = false;\n            }\n            if (option.browser) {\n                add_to_predefined(browser);\n                option.browser = false;\n            }\n            if (option.windows) {\n                add_to_predefined(windows);\n                option.windows = false;\n            }\n            if (option.node) {\n                add_to_predefined(node);\n                option.node = false;\n                node_js = true;\n            }\n            if (option.widget) {\n                add_to_predefined(widget);\n                option.widget = false;\n            }\n        }\n    }\n\n\n// Produce an error warning.\n\n    function artifact(tok) {\n        if (!tok) {\n            tok = next_token;\n        }\n        return tok.number || tok.string;\n    }\n\n    function quit(message, line, character) {\n        throw {\n            name: 'JSLintError',\n            line: line,\n            character: character,\n            message: bundle.scanned_a_b.supplant({\n                a: message,\n                b: Math.floor((line / lines.length) * 100)\n            })\n        };\n    }\n\n    function warn(message, offender, a, b, c, d) {\n        var character, line, warning;\n        offender = offender || next_token;  // ~~\n        line = offender.line || 0;\n        character = offender.from || 0;\n        warning = {\n            id: '(error)',\n            raw: bundle[message] || message,\n            evidence: lines[line - 1] || '',\n            line: line,\n            character: character,\n            a: a || (offender.id === '(number)'\n                ? String(offender.number)\n                : offender.string),\n            b: b,\n            c: c,\n            d: d\n        };\n        warning.reason = warning.raw.supplant(warning);\n        JSLINT.errors.push(warning);\n        if (option.passfail) {\n            quit(bundle.stopping, line, character);\n        }\n        warnings += 1;\n        if (warnings >= option.maxerr) {\n            quit(bundle.too_many, line, character);\n        }\n        return warning;\n    }\n\n    function warn_at(message, line, character, a, b, c, d) {\n        return warn(message, {\n            line: line,\n            from: character\n        }, a, b, c, d);\n    }\n\n    function stop(message, offender, a, b, c, d) {\n        var warning = warn(message, offender, a, b, c, d);\n        quit(bundle.stopping, warning.line, warning.character);\n    }\n\n    function stop_at(message, line, character, a, b, c, d) {\n        return stop(message, {\n            line: line,\n            from: character\n        }, a, b, c, d);\n    }\n\n    function expected_at(at) {\n        if (!option.white && next_token.from !== at) {\n            warn('expected_a_at_b_c', next_token, '', at,\n                next_token.from);\n        }\n    }\n\n    function aint(it, name, expected) {\n        if (it[name] !== expected) {\n            warn('expected_a_b', it, expected, it[name]);\n            return true;\n        }\n        return false;\n    }\n\n\n// lexical analysis and token construction\n\n    lex = (function lex() {\n        var character, c, from, length, line, pos, source_row;\n\n// Private lex methods\n\n        function next_line() {\n            var at;\n            if (line >= lines.length) {\n                return false;\n            }\n            character = 1;\n            source_row = lines[line];\n            line += 1;\n            at = source_row.search(/ \\t/);\n            if (at >= 0) {\n                warn_at('mixed', line, at + 1);\n            }\n            source_row = source_row.replace(/\\t/g, tab);\n            at = source_row.search(cx);\n            if (at >= 0) {\n                warn_at('unsafe', line, at);\n            }\n            if (option.maxlen && option.maxlen < source_row.length) {\n                warn_at('too_long', line, source_row.length);\n            }\n            return true;\n        }\n\n// Produce a token object.  The token inherits from a syntax symbol.\n\n        function it(type, value) {\n            var id, the_token;\n            if (type === '(string)' || type === '(range)') {\n                if (jx.test(value)) {\n                    warn_at('url', line, from);\n                }\n            }\n            the_token = Object.create(syntax[(\n                type === '(punctuator)' || (type === '(identifier)' &&\n                        Object.prototype.hasOwnProperty.call(syntax, value))\n                    ? value\n                    : type\n            )] || syntax['(error)']);\n            if (type === '(identifier)') {\n                the_token.identifier = true;\n                if (value === '__iterator__' || value === '__proto__') {\n                    stop_at('reserved_a', line, from, value);\n                } else if (!option.nomen &&\n                        (value.charAt(0) === '_' ||\n                        value.charAt(value.length - 1) === '_')) {\n                    warn_at('dangling_a', line, from, value);\n                }\n            }\n            if (type === '(number)') {\n                the_token.number = +value;\n            } else if (value !== undefined) {\n                the_token.string = String(value);\n            }\n            the_token.line = line;\n            the_token.from = from;\n            the_token.thru = character;\n            id = the_token.id;\n            prereg = id && (\n                ('(,=:[!&|?{};'.indexOf(id.charAt(id.length - 1)) >= 0) ||\n                id === 'return' || id === 'case'\n            );\n            return the_token;\n        }\n\n        function match(x) {\n            var exec = x.exec(source_row), first;\n            if (exec) {\n                length = exec[0].length;\n                first = exec[1];\n                c = first.charAt(0);\n                source_row = source_row.slice(length);\n                from = character + length - first.length;\n                character += length;\n                return first;\n            }\n        }\n\n        function string(x) {\n            var c, pos = 0, r = '', result;\n\n            function hex(n) {\n                var i = parseInt(source_row.substr(pos + 1, n), 16);\n                pos += n;\n                if (i >= 32 && i <= 126 &&\n                        i !== 34 && i !== 92 && i !== 39) {\n                    warn_at('unexpected_a', line, character, '\\\\');\n                }\n                character += n;\n                c = String.fromCharCode(i);\n            }\n\n            if (json_mode && x !== '\"') {\n                warn_at('expected_a', line, character, '\"');\n            }\n\n            if (xquote === x || (xmode === 'scriptstring' && !xquote)) {\n                return it('(punctuator)', x);\n            }\n\n            for (;;) {\n                while (pos >= source_row.length) {\n                    pos = 0;\n                    if (xmode !== 'html' || !next_line()) {\n                        stop_at('unclosed', line, from);\n                    }\n                }\n                c = source_row.charAt(pos);\n                if (c === x) {\n                    character += 1;\n                    source_row = source_row.slice(pos + 1);\n                    result = it('(string)', r);\n                    result.quote = x;\n                    return result;\n                }\n                if (c < ' ') {\n                    if (c === '\\n' || c === '\\r') {\n                        break;\n                    }\n                    warn_at('control_a', line, character + pos,\n                        source_row.slice(0, pos));\n                } else if (c === xquote) {\n                    warn_at('bad_html', line, character + pos);\n                } else if (c === '<') {\n                    if (option.safe && xmode === 'html') {\n                        warn_at('adsafe_a', line, character + pos, c);\n                    } else if (source_row.charAt(pos + 1) === '/' && (xmode || option.safe)) {\n                        warn_at('expected_a_b', line, character,\n                            '<\\\\/', '</');\n                    } else if (source_row.charAt(pos + 1) === '!' && (xmode || option.safe)) {\n                        warn_at('unexpected_a', line, character, '<!');\n                    }\n                } else if (c === '\\\\') {\n                    if (xmode === 'html') {\n                        if (option.safe) {\n                            warn_at('adsafe_a', line, character + pos, c);\n                        }\n                    } else if (xmode === 'styleproperty') {\n                        pos += 1;\n                        character += 1;\n                        c = source_row.charAt(pos);\n                        if (c !== x) {\n                            warn_at('unexpected_a', line, character, '\\\\');\n                        }\n                    } else {\n                        pos += 1;\n                        character += 1;\n                        c = source_row.charAt(pos);\n                        switch (c) {\n                        case '':\n                            if (!option.es5) {\n                                warn_at('es5', line, character);\n                            }\n                            next_line();\n                            pos = -1;\n                            break;\n                        case xquote:\n                            warn_at('bad_html', line, character + pos);\n                            break;\n                        case '\\'':\n                            if (json_mode) {\n                                warn_at('unexpected_a', line, character, '\\\\\\'');\n                            }\n                            break;\n                        case 'u':\n                            hex(4);\n                            break;\n                        case 'v':\n                            if (json_mode) {\n                                warn_at('unexpected_a', line, character, '\\\\v');\n                            }\n                            c = '\\v';\n                            break;\n                        case 'x':\n                            if (json_mode) {\n                                warn_at('unexpected_a', line, character, '\\\\x');\n                            }\n                            hex(2);\n                            break;\n                        default:\n                            if (typeof descapes[c] !== 'string') {\n                                warn_at(c >= '0' && c <= '7' ? 'octal_a' : 'unexpected_a',\n                                    line, character, '\\\\' + c);\n                            } else {\n                                c = descapes[c];\n                            }\n                        }\n                    }\n                }\n                r += c;\n                character += 1;\n                pos += 1;\n            }\n        }\n\n        function number(snippet) {\n            var digit;\n            if (xmode !== 'style' && xmode !== 'styleproperty' &&\n                    source_row.charAt(0).isAlpha()) {\n                warn_at('expected_space_a_b',\n                    line, character, c, source_row.charAt(0));\n            }\n            if (c === '0') {\n                digit = snippet.charAt(1);\n                if (digit.isDigit()) {\n                    if (token.id !== '.' && xmode !== 'styleproperty') {\n                        warn_at('unexpected_a', line, character, snippet);\n                    }\n                } else if (json_mode && (digit === 'x' || digit === 'X')) {\n                    warn_at('unexpected_a', line, character, '0x');\n                }\n            }\n            if (snippet.slice(snippet.length - 1) === '.') {\n                warn_at('trailing_decimal_a', line, character, snippet);\n            }\n            if (xmode !== 'style') {\n                digit = +snippet;\n                if (!isFinite(digit)) {\n                    warn_at('bad_number', line, character, snippet);\n                }\n                snippet = digit;\n            }\n            return it('(number)', snippet);\n        }\n\n        function comment(snippet) {\n            if (comments_off || src || (xmode && xmode !== 'script' &&\n                    xmode !== 'style' && xmode !== 'styleproperty')) {\n                warn_at('unexpected_comment', line, character);\n            } else if (xmode === 'script' && /<\\//i.test(source_row)) {\n                warn_at('unexpected_a', line, character, '<\\/');\n            } else if (option.safe && ax.test(snippet)) {\n                warn_at('dangerous_comment', line, character);\n            }\n        }\n\n        function regexp() {\n            var b,\n                bit,\n                captures = 0,\n                depth = 0,\n                flag = '',\n                high,\n                letter,\n                length = 0,\n                low,\n                potential,\n                quote,\n                result;\n            for (;;) {\n                b = true;\n                c = source_row.charAt(length);\n                length += 1;\n                switch (c) {\n                case '':\n                    stop_at('unclosed_regexp', line, from);\n                    return;\n                case '/':\n                    if (depth > 0) {\n                        warn_at('unescaped_a', line, from + length, '/');\n                    }\n                    c = source_row.slice(0, length - 1);\n                    potential = Object.create(regexp_flag);\n                    for (;;) {\n                        letter = source_row.charAt(length);\n                        if (potential[letter] !== true) {\n                            break;\n                        }\n                        potential[letter] = false;\n                        length += 1;\n                        flag += letter;\n                    }\n                    if (source_row.charAt(length).isAlpha()) {\n                        stop_at('unexpected_a', line, from, source_row.charAt(length));\n                    }\n                    character += length;\n                    source_row = source_row.slice(length);\n                    quote = source_row.charAt(0);\n                    if (quote === '/' || quote === '*') {\n                        stop_at('confusing_regexp', line, from);\n                    }\n                    result = it('(regexp)', c);\n                    result.flag = flag;\n                    return result;\n                case '\\\\':\n                    c = source_row.charAt(length);\n                    if (c < ' ') {\n                        warn_at('control_a', line, from + length, String(c));\n                    } else if (c === '<') {\n                        warn_at(bundle.unexpected_a, line, from + length, '\\\\');\n                    }\n                    length += 1;\n                    break;\n                case '(':\n                    depth += 1;\n                    b = false;\n                    if (source_row.charAt(length) === '?') {\n                        length += 1;\n                        switch (source_row.charAt(length)) {\n                        case ':':\n                        case '=':\n                        case '!':\n                            length += 1;\n                            break;\n                        default:\n                            warn_at(bundle.expected_a_b, line, from + length,\n                                ':', source_row.charAt(length));\n                        }\n                    } else {\n                        captures += 1;\n                    }\n                    break;\n                case '|':\n                    b = false;\n                    break;\n                case ')':\n                    if (depth === 0) {\n                        warn_at('unescaped_a', line, from + length, ')');\n                    } else {\n                        depth -= 1;\n                    }\n                    break;\n                case ' ':\n                    pos = 1;\n                    while (source_row.charAt(length) === ' ') {\n                        length += 1;\n                        pos += 1;\n                    }\n                    if (pos > 1) {\n                        warn_at('use_braces', line, from + length, pos);\n                    }\n                    break;\n                case '[':\n                    c = source_row.charAt(length);\n                    if (c === '^') {\n                        length += 1;\n                        if (!option.regexp) {\n                            warn_at('insecure_a', line, from + length, c);\n                        } else if (source_row.charAt(length) === ']') {\n                            stop_at('unescaped_a', line, from + length, '^');\n                        }\n                    }\n                    bit = false;\n                    if (c === ']') {\n                        warn_at('empty_class', line, from + length - 1);\n                        bit = true;\n                    }\nklass:              do {\n                        c = source_row.charAt(length);\n                        length += 1;\n                        switch (c) {\n                        case '[':\n                        case '^':\n                            warn_at('unescaped_a', line, from + length, c);\n                            bit = true;\n                            break;\n                        case '-':\n                            if (bit) {\n                                bit = false;\n                            } else {\n                                warn_at('unescaped_a', line, from + length, '-');\n                                bit = true;\n                            }\n                            break;\n                        case ']':\n                            if (!bit) {\n                                warn_at('unescaped_a', line, from + length - 1, '-');\n                            }\n                            break klass;\n                        case '\\\\':\n                            c = source_row.charAt(length);\n                            if (c < ' ') {\n                                warn_at(bundle.control_a, line, from + length, String(c));\n                            } else if (c === '<') {\n                                warn_at(bundle.unexpected_a, line, from + length, '\\\\');\n                            }\n                            length += 1;\n                            bit = true;\n                            break;\n                        case '/':\n                            warn_at('unescaped_a', line, from + length - 1, '/');\n                            bit = true;\n                            break;\n                        case '<':\n                            if (xmode === 'script') {\n                                c = source_row.charAt(length);\n                                if (c === '!' || c === '/') {\n                                    warn_at(bundle.html_confusion_a, line,\n                                        from + length, c);\n                                }\n                            }\n                            bit = true;\n                            break;\n                        default:\n                            bit = true;\n                        }\n                    } while (c);\n                    break;\n                case '.':\n                    if (!option.regexp) {\n                        warn_at('insecure_a', line, from + length, c);\n                    }\n                    break;\n                case ']':\n                case '?':\n                case '{':\n                case '}':\n                case '+':\n                case '*':\n                    warn_at('unescaped_a', line, from + length, c);\n                    break;\n                case '<':\n                    if (xmode === 'script') {\n                        c = source_row.charAt(length);\n                        if (c === '!' || c === '/') {\n                            warn_at(bundle.html_confusion_a, line, from + length, c);\n                        }\n                    }\n                    break;\n                }\n                if (b) {\n                    switch (source_row.charAt(length)) {\n                    case '?':\n                    case '+':\n                    case '*':\n                        length += 1;\n                        if (source_row.charAt(length) === '?') {\n                            length += 1;\n                        }\n                        break;\n                    case '{':\n                        length += 1;\n                        c = source_row.charAt(length);\n                        if (c < '0' || c > '9') {\n                            warn_at(bundle.expected_number_a, line,\n                                from + length, c);\n                        }\n                        length += 1;\n                        low = +c;\n                        for (;;) {\n                            c = source_row.charAt(length);\n                            if (c < '0' || c > '9') {\n                                break;\n                            }\n                            length += 1;\n                            low = +c + (low * 10);\n                        }\n                        high = low;\n                        if (c === ',') {\n                            length += 1;\n                            high = Infinity;\n                            c = source_row.charAt(length);\n                            if (c >= '0' && c <= '9') {\n                                length += 1;\n                                high = +c;\n                                for (;;) {\n                                    c = source_row.charAt(length);\n                                    if (c < '0' || c > '9') {\n                                        break;\n                                    }\n                                    length += 1;\n                                    high = +c + (high * 10);\n                                }\n                            }\n                        }\n                        if (source_row.charAt(length) !== '}') {\n                            warn_at(bundle.expected_a_b, line, from + length,\n                                '}', c);\n                        } else {\n                            length += 1;\n                        }\n                        if (source_row.charAt(length) === '?') {\n                            length += 1;\n                        }\n                        if (low > high) {\n                            warn_at(bundle.not_greater, line, from + length,\n                                low, high);\n                        }\n                        break;\n                    }\n                }\n            }\n            c = source_row.slice(0, length - 1);\n            character += length;\n            source_row = source_row.slice(length);\n            return it('(regexp)', c);\n        }\n\n// Public lex methods\n\n        return {\n            init: function (source) {\n                if (typeof source === 'string') {\n                    lines = source.split(crlfx);\n                } else {\n                    lines = source;\n                }\n                line = 0;\n                next_line();\n                from = 1;\n            },\n\n            range: function (begin, end) {\n                var c, value = '';\n                from = character;\n                if (source_row.charAt(0) !== begin) {\n                    stop_at('expected_a_b', line, character, begin,\n                        source_row.charAt(0));\n                }\n                for (;;) {\n                    source_row = source_row.slice(1);\n                    character += 1;\n                    c = source_row.charAt(0);\n                    switch (c) {\n                    case '':\n                        stop_at('missing_a', line, character, c);\n                        break;\n                    case end:\n                        source_row = source_row.slice(1);\n                        character += 1;\n                        return it('(range)', value);\n                    case xquote:\n                    case '\\\\':\n                        warn_at('unexpected_a', line, character, c);\n                        break;\n                    }\n                    value += c;\n                }\n            },\n\n// token -- this is called by advance to get the next token.\n\n            token: function () {\n                var c, i, snippet;\n\n                for (;;) {\n                    while (!source_row) {\n                        if (!next_line()) {\n                            return it('(end)');\n                        }\n                    }\n                    while (xmode === 'outer') {\n                        i = source_row.search(ox);\n                        if (i === 0) {\n                            break;\n                        } else if (i > 0) {\n                            character += 1;\n                            source_row = source_row.slice(i);\n                            break;\n                        } else {\n                            if (!next_line()) {\n                                return it('(end)', '');\n                            }\n                        }\n                    }\n                    snippet = match(rx[xmode] || tx);\n                    if (!snippet) {\n                        if (source_row) {\n                            if (source_row.charAt(0) === ' ') {\n                                if (!option.white) {\n                                    warn_at('unexpected_a', line, character,\n                                        '(space)');\n                                }\n                                character += 1;\n                                source_row = '';\n                            } else {\n                                stop_at('unexpected_a', line, character,\n                                    source_row.charAt(0));\n                            }\n                        }\n                    } else {\n\n//      identifier\n\n                        c = snippet.charAt(0);\n                        if (c.isAlpha() || c === '_' || c === '$') {\n                            return it('(identifier)', snippet);\n                        }\n\n//      number\n\n                        if (c.isDigit()) {\n                            return number(snippet);\n                        }\n                        switch (snippet) {\n\n//      string\n\n                        case '\"':\n                        case \"'\":\n                            return string(snippet);\n\n//      // comment\n\n                        case '//':\n                            comment(source_row);\n                            source_row = '';\n                            break;\n\n//      /* comment\n\n                        case '/*':\n                            for (;;) {\n                                i = source_row.search(lx);\n                                if (i >= 0) {\n                                    break;\n                                }\n                                comment(source_row);\n                                if (!next_line()) {\n                                    stop_at('unclosed_comment', line, character);\n                                }\n                            }\n                            comment(source_row.slice(0, i));\n                            character += i + 2;\n                            if (source_row.charAt(i) === '/') {\n                                stop_at('nested_comment', line, character);\n                            }\n                            source_row = source_row.slice(i + 2);\n                            break;\n\n                        case '':\n                            break;\n//      /\n                        case '/':\n                            if (token.id === '/=') {\n                                stop_at(\n                                    bundle.slash_equal,\n                                    line,\n                                    from\n                                );\n                            }\n                            return prereg\n                                ? regexp()\n                                : it('(punctuator)', snippet);\n\n//      punctuator\n\n                        case '<!--':\n                            length = line;\n//                            c = character;\n                            for (;;) {\n                                i = source_row.indexOf('--');\n                                if (i >= 0) {\n                                    break;\n                                }\n                                i = source_row.indexOf('<!');\n                                if (i >= 0) {\n                                    stop_at('nested_comment',\n                                        line, character + i);\n                                }\n                                if (!next_line()) {\n                                    stop_at('unclosed_comment', length, c);\n                                }\n                            }\n                            length = source_row.indexOf('<!');\n                            if (length >= 0 && length < i) {\n                                stop_at('nested_comment',\n                                    line, character + length);\n                            }\n                            character += i;\n                            if (source_row.charAt(i + 2) !== '>') {\n                                stop_at('expected_a', line, character, '-->');\n                            }\n                            character += 3;\n                            source_row = source_row.slice(i + 3);\n                            break;\n                        case '#':\n                            if (xmode === 'html' || xmode === 'styleproperty') {\n                                for (;;) {\n                                    c = source_row.charAt(0);\n                                    if ((c < '0' || c > '9') &&\n                                            (c < 'a' || c > 'f') &&\n                                            (c < 'A' || c > 'F')) {\n                                        break;\n                                    }\n                                    character += 1;\n                                    source_row = source_row.slice(1);\n                                    snippet += c;\n                                }\n                                if (snippet.length !== 4 && snippet.length !== 7) {\n                                    warn_at('bad_color_a', line,\n                                        from + length, snippet);\n                                }\n                                return it('(color)', snippet);\n                            }\n                            return it('(punctuator)', snippet);\n\n                        default:\n                            if (xmode === 'outer' && c === '&') {\n                                character += 1;\n                                source_row = source_row.slice(1);\n                                for (;;) {\n                                    c = source_row.charAt(0);\n                                    character += 1;\n                                    source_row = source_row.slice(1);\n                                    if (c === ';') {\n                                        break;\n                                    }\n                                    if (!((c >= '0' && c <= '9') ||\n                                            (c >= 'a' && c <= 'z') ||\n                                            c === '#')) {\n                                        stop_at('bad_entity', line, from + length,\n                                            character);\n                                    }\n                                }\n                                break;\n                            }\n                            return it('(punctuator)', snippet);\n                        }\n                    }\n                }\n            }\n        };\n    }());\n\n\n    function add_label(token, kind, name) {\n\n// Define the symbol in the current function in the current scope.\n\n        name = name || token.string;\n\n// Global variables cannot be created in the safe subset. If a global variable\n// already exists, do nothing. If it is predefined, define it.\n\n        if (funct === global_funct) {\n            if (option.safe) {\n                warn('adsafe_a', token, name);\n            }\n            if (typeof global_funct[name] !== 'string') {\n                token.writeable = typeof predefined[name] === 'boolean'\n                    ? predefined[name]\n                    : true;\n                token.funct = funct;\n                global_scope[name] = token;\n            }\n            if (kind === 'becoming') {\n                kind = 'var';\n            }\n\n// Ordinary variables.\n\n        } else {\n\n// Warn if the variable already exists.\n\n            if (typeof funct[name] === 'string') {\n                if (funct[name] === 'undef') {\n                    if (!option.undef) {\n                        warn('used_before_a', token, name);\n                    }\n                    kind = 'var';\n                } else {\n                    warn('already_defined', token, name);\n                }\n            } else {\n\n// Add the symbol to the current function.\n\n                token.funct = funct;\n                token.writeable = true;\n                scope[name] = token;\n            }\n        }\n        funct[name] = kind;\n    }\n\n\n    function peek(distance) {\n\n// Peek ahead to a future token. The distance is how far ahead to look. The\n// default is the next token.\n\n        var found, slot = 0;\n\n        distance = distance || 0;\n        while (slot <= distance) {\n            found = lookahead[slot];\n            if (!found) {\n                found = lookahead[slot] = lex.token();\n            }\n            slot += 1;\n        }\n        return found;\n    }\n\n\n    function advance(id, match) {\n\n// Produce the next token, also looking for programming errors.\n\n        if (indent) {\n\n// If indentation checking was requested, then inspect all of the line breakings.\n// The var statement is tricky because the names might be aligned or not. We\n// look at the first line break after the var to determine the programmer's\n// intention.\n\n            if (var_mode && next_token.line !== token.line) {\n                if ((var_mode !== indent || !next_token.edge) &&\n                        next_token.from === indent.at -\n                        (next_token.edge ? option.indent : 0)) {\n                    var dent = indent;\n                    for (;;) {\n                        dent.at -= option.indent;\n                        if (dent === var_mode) {\n                            break;\n                        }\n                        dent = dent.was;\n                    }\n                    dent.open = false;\n                }\n                var_mode = null;\n            }\n            if (next_token.id === '?' && indent.mode === ':' &&\n                    token.line !== next_token.line) {\n                indent.at -= option.indent;\n            }\n            if (indent.open) {\n\n// If the token is an edge.\n\n                if (next_token.edge) {\n                    if (next_token.edge === 'label') {\n                        expected_at(1);\n                    } else if (next_token.edge === 'case' || indent.mode === 'statement') {\n                        expected_at(indent.at - option.indent);\n                    } else if (indent.mode !== 'array' || next_token.line !== token.line) {\n                        expected_at(indent.at);\n                    }\n\n// If the token is not an edge, but is the first token on the line.\n\n                } else if (next_token.line !== token.line) {\n                    if (next_token.from < indent.at + (indent.mode ===\n                            'expression' ? 0 : option.indent)) {\n                        expected_at(indent.at + option.indent);\n                    }\n                    indent.wrap = true;\n                }\n            } else if (next_token.line !== token.line) {\n                if (next_token.edge) {\n                    expected_at(indent.at);\n                } else {\n                    indent.wrap = true;\n                    if (indent.mode === 'statement' || indent.mode === 'var') {\n                        expected_at(indent.at + option.indent);\n                    } else if (next_token.from < indent.at + (indent.mode ===\n                            'expression' ? 0 : option.indent)) {\n                        expected_at(indent.at + option.indent);\n                    }\n                }\n            }\n        }\n\n        switch (token.id) {\n        case '(number)':\n            if (next_token.id === '.') {\n                warn('trailing_decimal_a');\n            }\n            break;\n        case '-':\n            if (next_token.id === '-' || next_token.id === '--') {\n                warn('confusing_a');\n            }\n            break;\n        case '+':\n            if (next_token.id === '+' || next_token.id === '++') {\n                warn('confusing_a');\n            }\n            break;\n        }\n        if (token.id === '(string)' || token.identifier) {\n            anonname = token.string;\n        }\n\n        if (id && next_token.id !== id) {\n            if (match) {\n                warn('expected_a_b_from_c_d', next_token, id,\n                    match.id, match.line, artifact());\n            } else if (!next_token.identifier || next_token.string !== id) {\n                warn('expected_a_b', next_token, id, artifact());\n            }\n        }\n        prev_token = token;\n        token = next_token;\n        next_token = lookahead.shift() || lex.token();\n    }\n\n\n    function advance_identifier(string) {\n        if (next_token.identifier && next_token.string === string) {\n            advance();\n        } else {\n            warn('expected_a_b', next_token, string, artifact());\n        }\n    }\n\n\n    function do_safe() {\n        if (option.adsafe) {\n            option.safe = true;\n        }\n        if (option.safe) {\n            option.browser     =\n                option['continue'] =\n                option.css     =\n                option.debug   =\n                option.devel   =\n                option.evil    =\n                option.forin   =\n                option.newcap  =\n                option.nomen   =\n                option.on      =\n                option.rhino   =\n                option.sloppy  =\n                option.sub     =\n                option.undef   =\n                option.widget  =\n                option.windows = false;\n\n\n            delete predefined.Array;\n            delete predefined.Date;\n            delete predefined.Function;\n            delete predefined.Object;\n            delete predefined['eval'];\n\n            add_to_predefined({\n                ADSAFE: false,\n                lib: false\n            });\n        }\n    }\n\n\n    function do_globals() {\n        var name, writeable;\n        for (;;) {\n            if (next_token.id !== '(string)' && !next_token.identifier) {\n                return;\n            }\n            name = next_token.string;\n            advance();\n            writeable = false;\n            if (next_token.id === ':') {\n                advance(':');\n                switch (next_token.id) {\n                case 'true':\n                    writeable = predefined[name] !== false;\n                    advance('true');\n                    break;\n                case 'false':\n                    advance('false');\n                    break;\n                default:\n                    stop('unexpected_a');\n                }\n            }\n            predefined[name] = writeable;\n            if (next_token.id !== ',') {\n                return;\n            }\n            advance(',');\n        }\n    }\n\n\n    function do_jslint() {\n        var name, value;\n        while (next_token.id === '(string)' || next_token.identifier) {\n            name = next_token.string;\n            if (!allowed_option[name]) {\n                stop('unexpected_a');\n            }\n            advance();\n            if (next_token.id !== ':') {\n                stop('expected_a_b', next_token, ':', artifact());\n            }\n            advance(':');\n            if (typeof allowed_option[name] === 'number') {\n                value = next_token.number;\n                if (value > allowed_option[name] || value <= 0 ||\n                        Math.floor(value) !== value) {\n                    stop('expected_small_a');\n                }\n                option[name] = value;\n            } else {\n                if (next_token.id === 'true') {\n                    option[name] = true;\n                } else if (next_token.id === 'false') {\n                    option[name] = false;\n                } else {\n                    stop('unexpected_a');\n                }\n            }\n            advance();\n            if (next_token.id === ',') {\n                advance(',');\n            }\n        }\n        assume();\n    }\n\n\n    function do_properties() {\n        var name;\n        option.properties = true;\n        for (;;) {\n            if (next_token.id !== '(string)' && !next_token.identifier) {\n                return;\n            }\n            name = next_token.string;\n            advance();\n            if (next_token.id === ':') {\n                for (;;) {\n                    advance();\n                    if (next_token.id !== '(string)' && !next_token.identifier) {\n                        break;\n                    }\n                }\n            }\n            property[name] = 0;\n            if (next_token.id !== ',') {\n                return;\n            }\n            advance(',');\n        }\n    }\n\n\n    directive = function directive() {\n        var command = this.id,\n            old_comments_off = comments_off,\n            old_indent = indent;\n        comments_off = true;\n        indent = null;\n        if (next_token.line === token.line && next_token.from === token.thru) {\n            warn('missing_space_a_b', next_token, artifact(token), artifact());\n        }\n        if (lookahead.length > 0) {\n            warn('unexpected_a', this);\n        }\n        switch (command) {\n        case '/*properties':\n        case '/*property':\n        case '/*members':\n        case '/*member':\n            do_properties();\n            break;\n        case '/*jslint':\n            if (option.safe) {\n                warn('adsafe_a', this);\n            }\n            do_jslint();\n            break;\n        case '/*globals':\n        case '/*global':\n            if (option.safe) {\n                warn('adsafe_a', this);\n            }\n            do_globals();\n            break;\n        default:\n            stop('unexpected_a', this);\n        }\n        comments_off = old_comments_off;\n        advance('*/');\n        indent = old_indent;\n    };\n\n\n// Indentation intention\n\n    function edge(mode) {\n        next_token.edge = indent ? indent.open && (mode || 'edge') : '';\n    }\n\n\n    function step_in(mode) {\n        var open;\n        if (typeof mode === 'number') {\n            indent = {\n                at: +mode,\n                open: true,\n                was: indent\n            };\n        } else if (!indent) {\n            indent = {\n                at: 1,\n                mode: 'statement',\n                open: true\n            };\n        } else if (mode === 'statement') {\n            indent = {\n                at: indent.at,\n                open: true,\n                was: indent\n            };\n        } else {\n            open = mode === 'var' || next_token.line !== token.line;\n            indent = {\n                at: (open || mode === 'control'\n                    ? indent.at + option.indent\n                    : indent.at) + (indent.wrap ? option.indent : 0),\n                mode: mode,\n                open: open,\n                was: indent\n            };\n            if (mode === 'var' && open) {\n                var_mode = indent;\n            }\n        }\n    }\n\n    function step_out(id, symbol) {\n        if (id) {\n            if (indent && indent.open) {\n                indent.at -= option.indent;\n                edge();\n            }\n            advance(id, symbol);\n        }\n        if (indent) {\n            indent = indent.was;\n        }\n    }\n\n// Functions for conformance of whitespace.\n\n    function one_space(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && !option.white &&\n                (token.line !== right.line ||\n                token.thru + 1 !== right.from)) {\n            warn('expected_space_a_b', right, artifact(token), artifact(right));\n        }\n    }\n\n    function one_space_only(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && (left.line !== right.line ||\n                (!option.white && left.thru + 1 !== right.from))) {\n            warn('expected_space_a_b', right, artifact(left), artifact(right));\n        }\n    }\n\n    function no_space(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if ((!option.white || xmode === 'styleproperty' || xmode === 'style') &&\n                left.thru !== right.from && left.line === right.line) {\n            warn('unexpected_space_a_b', right, artifact(left), artifact(right));\n        }\n    }\n\n    function no_space_only(left, right) {\n        left = left || token;\n        right = right || next_token;\n        if (right.id !== '(end)' && (left.line !== right.line ||\n                (!option.white && left.thru !== right.from))) {\n            warn('unexpected_space_a_b', right, artifact(left), artifact(right));\n        }\n    }\n\n    function spaces(left, right) {\n        if (!option.white) {\n            left = left || token;\n            right = right || next_token;\n            if (left.thru === right.from && left.line === right.line) {\n                warn('missing_space_a_b', right, artifact(left), artifact(right));\n            }\n        }\n    }\n\n    function comma() {\n        if (next_token.id !== ',') {\n            warn_at('expected_a_b', token.line, token.thru, ',', artifact());\n        } else {\n            if (!option.white) {\n                no_space_only();\n            }\n            advance(',');\n            spaces();\n        }\n    }\n\n\n    function semicolon() {\n        if (next_token.id !== ';') {\n            warn_at('expected_a_b', token.line, token.thru, ';', artifact());\n        } else {\n            if (!option.white) {\n                no_space_only();\n            }\n            advance(';');\n            if (semicolon_coda[next_token.id] !== true) {\n                spaces();\n            }\n        }\n    }\n\n    function use_strict() {\n        if (next_token.string === 'use strict') {\n            if (strict_mode) {\n                warn('unnecessary_use');\n            }\n            edge();\n            advance();\n            semicolon();\n            strict_mode = true;\n            option.newcap = false;\n            option.undef = false;\n            return true;\n        }\n        return false;\n    }\n\n\n    function are_similar(a, b) {\n        if (a === b) {\n            return true;\n        }\n        if (Array.isArray(a)) {\n            if (Array.isArray(b) && a.length === b.length) {\n                var i;\n                for (i = 0; i < a.length; i += 1) {\n                    if (!are_similar(a[i], b[i])) {\n                        return false;\n                    }\n                }\n                return true;\n            }\n            return false;\n        }\n        if (Array.isArray(b)) {\n            return false;\n        }\n        if (a.id === '(number)' && b.id === '(number)') {\n            return a.number === b.number;\n        }\n        if (a.arity === b.arity && a.string === b.string) {\n            switch (a.arity) {\n            case 'prefix':\n            case 'suffix':\n            case undefined:\n                return a.id === b.id && are_similar(a.first, b.first);\n            case 'infix':\n                return are_similar(a.first, b.first) &&\n                    are_similar(a.second, b.second);\n            case 'ternary':\n                return are_similar(a.first, b.first) &&\n                    are_similar(a.second, b.second) &&\n                    are_similar(a.third, b.third);\n            case 'function':\n            case 'regexp':\n                return false;\n            default:\n                return true;\n            }\n        } else {\n            if (a.id === '.' && b.id === '[' && b.arity === 'infix') {\n                return a.second.string === b.second.string && b.second.id === '(string)';\n            }\n            if (a.id === '[' && a.arity === 'infix' && b.id === '.') {\n                return a.second.string === b.second.string && a.second.id === '(string)';\n            }\n        }\n        return false;\n    }\n\n\n// This is the heart of JSLINT, the Pratt parser. In addition to parsing, it\n// is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is\n// like .nud except that it is only used on the first token of a statement.\n// Having .fud makes it much easier to define statement-oriented languages like\n// JavaScript. I retained Pratt's nomenclature.\n\n// .nud     Null denotation\n// .fud     First null denotation\n// .led     Left denotation\n//  lbp     Left binding power\n//  rbp     Right binding power\n\n// They are elements of the parsing method called Top Down Operator Precedence.\n\n    function expression(rbp, initial) {\n\n// rbp is the right binding power.\n// initial indicates that this is the first expression of a statement.\n\n        var left;\n        if (next_token.id === '(end)') {\n            stop('unexpected_a', token, next_token.id);\n        }\n        advance();\n        if (option.safe && scope[token.string] &&\n                scope[token.string] === global_scope[token.string] &&\n                (next_token.id !== '(' && next_token.id !== '.')) {\n            warn('adsafe_a', token);\n        }\n        if (initial) {\n            anonname = 'anonymous';\n            funct['(verb)'] = token.string;\n        }\n        if (initial === true && token.fud) {\n            left = token.fud();\n        } else {\n            if (token.nud) {\n                left = token.nud();\n            } else {\n                if (next_token.id === '(number)' && token.id === '.') {\n                    warn('leading_decimal_a', token, artifact());\n                    advance();\n                    return token;\n                }\n                stop('expected_identifier_a', token, token.id);\n            }\n            while (rbp < next_token.lbp) {\n                advance();\n                if (token.led) {\n                    left = token.led(left);\n                } else {\n                    stop('expected_operator_a', token, token.id);\n                }\n            }\n        }\n        return left;\n    }\n\n\n// Functional constructors for making the symbols that will be inherited by\n// tokens.\n\n    function symbol(s, p) {\n        var x = syntax[s];\n        if (!x || typeof x !== 'object') {\n            syntax[s] = x = {\n                id: s,\n                lbp: p || 0,\n                string: s\n            };\n        }\n        return x;\n    }\n\n    function postscript(x) {\n        x.postscript = true;\n        return x;\n    }\n\n    function ultimate(s) {\n        var x = symbol(s, 0);\n        x.from = 1;\n        x.thru = 1;\n        x.line = 0;\n        x.edge = 'edge';\n        s.string = s;\n        return postscript(x);\n    }\n\n\n    function stmt(s, f) {\n        var x = symbol(s);\n        x.identifier = x.reserved = true;\n        x.fud = f;\n        return x;\n    }\n\n    function labeled_stmt(s, f) {\n        var x = stmt(s, f);\n        x.labeled = true;\n    }\n\n    function disrupt_stmt(s, f) {\n        var x = stmt(s, f);\n        x.disrupt = true;\n    }\n\n\n    function reserve_name(x) {\n        var c = x.id.charAt(0);\n        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {\n            x.identifier = x.reserved = true;\n        }\n        return x;\n    }\n\n\n    function prefix(s, f) {\n        var x = symbol(s, 150);\n        reserve_name(x);\n        x.nud = typeof f === 'function'\n            ? f\n            : function () {\n                if (s === 'typeof') {\n                    one_space();\n                } else {\n                    no_space_only();\n                }\n                this.first = expression(150);\n                this.arity = 'prefix';\n                if (this.id === '++' || this.id === '--') {\n                    if (!option.plusplus) {\n                        warn('unexpected_a', this);\n                    } else if ((!this.first.identifier || this.first.reserved) &&\n                            this.first.id !== '.' && this.first.id !== '[') {\n                        warn('bad_operand', this);\n                    }\n                }\n                return this;\n            };\n        return x;\n    }\n\n\n    function type(s, t, nud) {\n        var x = symbol(s);\n        x.arity = t;\n        if (nud) {\n            x.nud = nud;\n        }\n        return x;\n    }\n\n\n    function reserve(s, f) {\n        var x = symbol(s);\n        x.identifier = x.reserved = true;\n        if (typeof f === 'function') {\n            x.nud = f;\n        }\n        return x;\n    }\n\n\n    function constant(name) {\n        var x = reserve(name);\n        x.string = name;\n        x.nud = return_this;\n        return x;\n    }\n\n\n    function reservevar(s, v) {\n        return reserve(s, function () {\n            if (typeof v === 'function') {\n                v(this);\n            }\n            return this;\n        });\n    }\n\n\n    function infix(s, p, f, w) {\n        var x = symbol(s, p);\n        reserve_name(x);\n        x.led = function (left) {\n            this.arity = 'infix';\n            if (!w) {\n                spaces(prev_token, token);\n                spaces();\n            }\n            if (!option.bitwise && this.bitwise) {\n                warn('unexpected_a', this);\n            }\n            if (typeof f === 'function') {\n                return f(left, this);\n            }\n            this.first = left;\n            this.second = expression(p);\n            return this;\n        };\n        return x;\n    }\n\n    function expected_relation(node, message) {\n        if (node.assign) {\n            warn(message || bundle.conditional_assignment, node);\n        }\n        return node;\n    }\n\n    function expected_condition(node, message) {\n        switch (node.id) {\n        case '[':\n        case '-':\n            if (node.arity !== 'infix') {\n                warn(message || bundle.weird_condition, node);\n            }\n            break;\n        case 'false':\n        case 'function':\n        case 'Infinity':\n        case 'NaN':\n        case 'null':\n        case 'true':\n        case 'undefined':\n        case 'void':\n        case '(number)':\n        case '(regexp)':\n        case '(string)':\n        case '{':\n            warn(message || bundle.weird_condition, node);\n            break;\n        case '(':\n            if (node.first.id === '.' && numbery[node.first.second.string] === true) {\n                warn(message || bundle.weird_condition, node);\n            }\n            break;\n        }\n        return node;\n    }\n\n    function check_relation(node) {\n        switch (node.arity) {\n        case 'prefix':\n            switch (node.id) {\n            case '{':\n            case '[':\n                warn('unexpected_a', node);\n                break;\n            case '!':\n                warn('confusing_a', node);\n                break;\n            }\n            break;\n        case 'function':\n        case 'regexp':\n            warn('unexpected_a', node);\n            break;\n        default:\n            if (node.id  === 'NaN') {\n                warn('isNaN', node);\n            }\n        }\n        return node;\n    }\n\n\n    function relation(s, eqeq) {\n        return infix(s, 100, function (left, that) {\n            check_relation(left);\n            if (eqeq && !option.eqeq) {\n                warn('expected_a_b', that, eqeq, that.id);\n            }\n            var right = expression(100);\n            if (are_similar(left, right) ||\n                    ((left.id === '(string)' || left.id === '(number)') &&\n                    (right.id === '(string)' || right.id === '(number)'))) {\n                warn('weird_relation', that);\n            }\n            that.first = left;\n            that.second = check_relation(right);\n            return that;\n        });\n    }\n\n\n    function assignop(s, op) {\n        var x = infix(s, 20, function (left, that) {\n            var l;\n            that.first = left;\n            if (left.identifier) {\n                if (scope[left.string]) {\n                    if (scope[left.string].writeable === false) {\n                        warn('read_only', left);\n                    }\n                } else {\n                    stop('read_only');\n                }\n                if (funct['(params)']) {\n                    funct['(params)'].forEach(function (value) {\n                        if (value.string === left.string) {\n                            value.assign = true;\n                        }\n                    });\n                }\n            } else if (option.safe) {\n                l = left;\n                do {\n                    if (typeof predefined[l.string] === 'boolean') {\n                        warn('adsafe_a', l);\n                    }\n                    l = l.first;\n                } while (l);\n            }\n            if (left === syntax['function']) {\n                warn('identifier_function', token);\n            }\n            if (left.id === '.' || left.id === '[') {\n                if (!left.first || left.first.string === 'arguments') {\n                    warn('bad_assignment', that);\n                }\n            } else if (left.identifier) {\n                if (!left.reserved && funct[left.string] === 'exception') {\n                    warn('assign_exception', left);\n                }\n            } else {\n                warn('bad_assignment', that);\n            }\n            that.second = expression(19);\n            if (that.id === '=' && are_similar(that.first, that.second)) {\n                warn('weird_assignment', that);\n            }\n            return that;\n        });\n        x.assign = true;\n        if (op) {\n            if (syntax[op].bitwise) {\n                x.bitwise = true;\n            }\n        }\n        return x;\n    }\n\n\n    function bitwise(s, p) {\n        var x = infix(s, p, 'number');\n        x.bitwise = true;\n        return x;\n    }\n\n\n    function suffix(s) {\n        var x = symbol(s, 150);\n        x.led = function (left) {\n            no_space_only(prev_token, token);\n            if (!option.plusplus) {\n                warn('unexpected_a', this);\n            } else if ((!left.identifier || left.reserved) &&\n                    left.id !== '.' && left.id !== '[') {\n                warn('bad_operand', this);\n            }\n            this.first = left;\n            this.arity = 'suffix';\n            return this;\n        };\n        return x;\n    }\n\n\n    function optional_identifier() {\n        if (next_token.identifier) {\n            advance();\n            if (option.safe && banned[token.string]) {\n                warn('adsafe_a', token);\n            } else if (token.reserved && !option.es5) {\n                warn('expected_identifier_a_reserved', token);\n            }\n            return token.string;\n        }\n    }\n\n\n    function identifier() {\n        var i = optional_identifier();\n        if (!i) {\n            stop(token.id === 'function' && next_token.id === '('\n                ? 'name_function'\n                : 'expected_identifier_a');\n        }\n        return i;\n    }\n\n\n    function statement() {\n\n        var label, old_scope = scope, the_statement;\n\n// We don't like the empty statement.\n\n        if (next_token.id === ';') {\n            warn('unexpected_a');\n            semicolon();\n            return;\n        }\n\n// Is this a labeled statement?\n\n        if (next_token.identifier && !next_token.reserved && peek().id === ':') {\n            edge('label');\n            label = next_token;\n            advance();\n            advance(':');\n            scope = Object.create(old_scope);\n            add_label(label, 'label');\n            if (next_token.labeled !== true || funct === global_funct) {\n                stop('unexpected_label_a', label);\n            } else if (jx.test(label.string + ':')) {\n                warn('url', label);\n            }\n            next_token.label = label;\n        }\n\n// Parse the statement.\n\n        if (token.id !== 'else') {\n            edge();\n        }\n        step_in('statement');\n        the_statement = expression(0, true);\n        if (the_statement) {\n\n// Look for the final semicolon.\n\n            if (the_statement.arity === 'statement') {\n                if (the_statement.id === 'switch' ||\n                        (the_statement.block && the_statement.id !== 'do')) {\n                    spaces();\n                } else {\n                    semicolon();\n                }\n            } else {\n\n// If this is an expression statement, determine if it is acceptable.\n// We do not like\n//      new Blah();\n// statments. If it is to be used at all, new should only be used to make\n// objects, not side effects. The expression statements we do like do\n// assignment or invocation or delete.\n\n                if (the_statement.id === '(') {\n                    if (the_statement.first.id === 'new') {\n                        warn('bad_new');\n                    }\n                } else if (!the_statement.assign &&\n                        the_statement.id !== 'delete' &&\n                        the_statement.id !== '++' &&\n                        the_statement.id !== '--') {\n                    warn('assignment_function_expression', token);\n                }\n                semicolon();\n            }\n        }\n        step_out();\n        scope = old_scope;\n        return the_statement;\n    }\n\n\n    function statements() {\n        var array = [], disruptor, the_statement;\n\n// A disrupt statement may not be followed by any other statement.\n// If the last statement is disrupt, then the sequence is disrupt.\n\n        while (next_token.postscript !== true) {\n            if (next_token.id === ';') {\n                warn('unexpected_a', next_token);\n                semicolon();\n            } else {\n                if (next_token.string === 'use strict') {\n                    if ((!node_js && xmode !== 'script') || funct !== global_funct || array.length > 0) {\n                        warn('function_strict');\n                    }\n                    use_strict();\n                }\n                if (disruptor) {\n                    warn('unreachable_a_b', next_token, next_token.string,\n                        disruptor.string);\n                    disruptor = null;\n                }\n                the_statement = statement();\n                if (the_statement) {\n                    array.push(the_statement);\n                    if (the_statement.disrupt) {\n                        disruptor = the_statement;\n                        array.disrupt = true;\n                    }\n                }\n            }\n        }\n        return array;\n    }\n\n\n    function block(ordinary) {\n\n// array block is array sequence of statements wrapped in braces.\n// ordinary is false for function bodies and try blocks.\n// ordinary is true for if statements, while, etc.\n\n        var array,\n            curly = next_token,\n            old_in_block = in_block,\n            old_scope = scope,\n            old_strict_mode = strict_mode;\n\n        in_block = ordinary;\n        scope = Object.create(scope);\n        spaces();\n        if (next_token.id === '{') {\n            advance('{');\n            step_in();\n            if (!ordinary && !use_strict() && !old_strict_mode &&\n                    !option.sloppy && funct['(context)'] === global_funct) {\n                warn('missing_use_strict');\n            }\n            array = statements();\n            strict_mode = old_strict_mode;\n            step_out('}', curly);\n        } else if (!ordinary) {\n            stop('expected_a_b', next_token, '{', artifact());\n        } else {\n            warn('expected_a_b', next_token, '{', artifact());\n            array = [statement()];\n            array.disrupt = array[0].disrupt;\n        }\n        funct['(verb)'] = null;\n        scope = old_scope;\n        in_block = old_in_block;\n        if (ordinary && array.length === 0) {\n            warn('empty_block');\n        }\n        return array;\n    }\n\n\n    function tally_property(name) {\n        if (option.properties && typeof property[name] !== 'number') {\n            warn('unexpected_property_a', token, name);\n        }\n        if (typeof property[name] === 'number') {\n            property[name] += 1;\n        } else {\n            property[name] = 1;\n        }\n    }\n\n\n// ECMAScript parser\n\n    syntax['(identifier)'] = {\n        id: '(identifier)',\n        lbp: 0,\n        identifier: true,\n        nud: function () {\n            var name = this.string,\n                variable = scope[name],\n                site,\n                writeable;\n\n// If the variable is not in scope, then we may have an undeclared variable.\n// Check the predefined list. If it was predefined, create the global\n// variable.\n\n            if (typeof variable !== 'object') {\n                writeable = predefined[name];\n                if (typeof writeable === 'boolean') {\n                    global_scope[name] = variable = {\n                        string:    name,\n                        writeable: writeable,\n                        funct:     global_funct\n                    };\n                    global_funct[name] = 'var';\n\n// But if the variable is not in scope, and is not predefined, and if we are not\n// in the global scope, then we have an undefined variable error.\n\n                } else {\n                    if (!option.undef) {\n                        warn('used_before_a', token);\n                    }\n                    scope[name] = variable = {\n                        string: name,\n                        writeable: true,\n                        funct: funct\n                    };\n                    funct[name] = 'undef';\n                }\n\n            }\n            site = variable.funct;\n\n// The name is in scope and defined in the current function.\n\n            if (funct === site) {\n\n//      Change 'unused' to 'var', and reject labels.\n\n                switch (funct[name]) {\n                case 'becoming':\n                    warn('unexpected_a', token);\n                    funct[name] = 'var';\n                    break;\n                case 'unused':\n                    funct[name] = 'var';\n                    break;\n                case 'unparam':\n                    funct[name] = 'parameter';\n                    break;\n                case 'unction':\n                    funct[name] = 'function';\n                    break;\n                case 'label':\n                    warn('a_label', token, name);\n                    break;\n                }\n\n// If the name is already defined in the current\n// function, but not as outer, then there is a scope error.\n\n            } else {\n                switch (funct[name]) {\n                case 'closure':\n                case 'function':\n                case 'var':\n                case 'unused':\n                    warn('a_scope', token, name);\n                    break;\n                case 'label':\n                    warn('a_label', token, name);\n                    break;\n                case 'outer':\n                case 'global':\n                    break;\n                default:\n\n// If the name is defined in an outer function, make an outer entry, and if\n// it was unused, make it var.\n\n                    switch (site[name]) {\n                    case 'becoming':\n                    case 'closure':\n                    case 'function':\n                    case 'parameter':\n                    case 'unction':\n                    case 'unused':\n                    case 'var':\n                        site[name] = 'closure';\n                        funct[name] = site === global_funct\n                            ? 'global'\n                            : 'outer';\n                        break;\n                    case 'unparam':\n                        site[name] = 'parameter';\n                        funct[name] = 'outer';\n                        break;\n                    case 'undef':\n                        funct[name] = 'undef';\n                        break;\n                    case 'label':\n                        warn('a_label', token, name);\n                        break;\n                    }\n                }\n            }\n            return this;\n        },\n        led: function () {\n            stop('expected_operator_a');\n        }\n    };\n\n// Build the syntax table by declaring the syntactic elements.\n\n    type('(array)', 'array');\n    type('(color)', 'color');\n    type('(function)', 'function');\n    type('(number)', 'number', return_this);\n    type('(object)', 'object');\n    type('(string)', 'string', return_this);\n    type('(boolean)', 'boolean', return_this);\n    type('(range)', 'range');\n    type('(regexp)', 'regexp', return_this);\n\n    ultimate('(begin)');\n    ultimate('(end)');\n    ultimate('(error)');\n    postscript(symbol('</'));\n    symbol('<!');\n    symbol('<!--');\n    symbol('-->');\n    postscript(symbol('}'));\n    symbol(')');\n    symbol(']');\n    postscript(symbol('\"'));\n    postscript(symbol('\\''));\n    symbol(';');\n    symbol(':');\n    symbol(',');\n    symbol('#');\n    symbol('@');\n    symbol('*/');\n    postscript(reserve('case'));\n    reserve('catch');\n    postscript(reserve('default'));\n    reserve('else');\n    reserve('finally');\n\n    reservevar('arguments', function (x) {\n        if (strict_mode && funct === global_funct) {\n            warn('strict', x);\n        } else if (option.safe) {\n            warn('adsafe_a', x);\n        }\n        funct['(arguments)'] = true;\n    });\n    reservevar('eval', function (x) {\n        if (option.safe) {\n            warn('adsafe_a', x);\n        }\n    });\n    constant('false', 'boolean');\n    constant('Infinity', 'number');\n    constant('NaN', 'number');\n    constant('null', '');\n    reservevar('this', function (x) {\n        if (option.safe) {\n            warn('adsafe_a', x);\n        } else if (strict_mode && funct['(token)'].arity === 'statement' &&\n                funct['(name)'].charAt(0) > 'Z') {\n            warn('strict', x);\n        }\n    });\n    constant('true', 'boolean');\n    constant('undefined', '');\n\n    infix('?', 30, function (left, that) {\n        step_in('?');\n        that.first = expected_condition(expected_relation(left));\n        that.second = expression(0);\n        spaces();\n        step_out();\n        var colon = next_token;\n        advance(':');\n        step_in(':');\n        spaces();\n        that.third = expression(10);\n        that.arity = 'ternary';\n        if (are_similar(that.second, that.third)) {\n            warn('weird_ternary', colon);\n        } else if (are_similar(that.first, that.second)) {\n            warn('use_or', that);\n        }\n        step_out();\n        return that;\n    });\n\n    infix('||', 40, function (left, that) {\n        function paren_check(that) {\n            if (that.id === '&&' && !that.paren) {\n                warn('and', that);\n            }\n            return that;\n        }\n\n        that.first = paren_check(expected_condition(expected_relation(left)));\n        that.second = paren_check(expected_relation(expression(40)));\n        if (are_similar(that.first, that.second)) {\n            warn('weird_condition', that);\n        }\n        return that;\n    });\n\n    infix('&&', 50, function (left, that) {\n        that.first = expected_condition(expected_relation(left));\n        that.second = expected_relation(expression(50));\n        if (are_similar(that.first, that.second)) {\n            warn('weird_condition', that);\n        }\n        return that;\n    });\n\n    prefix('void', function () {\n        this.first = expression(0);\n        this.arity = 'prefix';\n        if (option.es5) {\n            warn('expected_a_b', this, 'undefined', 'void');\n        } else if (this.first.number !== 0) {\n            warn('expected_a_b', this.first, '0', artifact(this.first));\n        }\n        return this;\n    });\n\n    bitwise('|', 70);\n    bitwise('^', 80);\n    bitwise('&', 90);\n\n    relation('==', '===');\n    relation('===');\n    relation('!=', '!==');\n    relation('!==');\n    relation('<');\n    relation('>');\n    relation('<=');\n    relation('>=');\n\n    bitwise('<<', 120);\n    bitwise('>>', 120);\n    bitwise('>>>', 120);\n\n    infix('in', 120, function (left, that) {\n        warn('infix_in', that);\n        that.left = left;\n        that.right = expression(130);\n        return that;\n    });\n    infix('instanceof', 120);\n    infix('+', 130, function (left, that) {\n        if (left.id === '(number)') {\n            if (left.number === 0) {\n                warn('unexpected_a', left, '0');\n            }\n        } else if (left.id === '(string)') {\n            if (left.string === '') {\n                warn('expected_a_b', left, 'String', '\\'\\'');\n            }\n        }\n        var right = expression(130);\n        if (right.id === '(number)') {\n            if (right.number === 0) {\n                warn('unexpected_a', right, '0');\n            }\n        } else if (right.id === '(string)') {\n            if (right.string === '') {\n                warn('expected_a_b', right, 'String', '\\'\\'');\n            }\n        }\n        if (left.id === right.id) {\n            if (left.id === '(string)' || left.id === '(number)') {\n                if (left.id === '(string)') {\n                    left.string += right.string;\n                    if (jx.test(left.string)) {\n                        warn('url', left);\n                    }\n                } else {\n                    left.number += right.number;\n                }\n                left.thru = right.thru;\n                return left;\n            }\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    prefix('+', 'num');\n    prefix('+++', function () {\n        warn('confusing_a', token);\n        this.first = expression(150);\n        this.arity = 'prefix';\n        return this;\n    });\n    infix('+++', 130, function (left) {\n        warn('confusing_a', token);\n        this.first = left;\n        this.second = expression(130);\n        return this;\n    });\n    infix('-', 130, function (left, that) {\n        if ((left.id === '(number)' && left.number === 0) || left.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(130);\n        if ((right.id === '(number)' && right.number === 0) || right.id === '(string)') {\n            warn('unexpected_a', right);\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number -= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    prefix('-');\n    prefix('---', function () {\n        warn('confusing_a', token);\n        this.first = expression(150);\n        this.arity = 'prefix';\n        return this;\n    });\n    infix('---', 130, function (left) {\n        warn('confusing_a', token);\n        this.first = left;\n        this.second = expression(130);\n        return this;\n    });\n    infix('*', 140, function (left, that) {\n        if ((left.id === '(number)' && (left.number === 0 || left.number === 1)) || left.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(140);\n        if ((right.id === '(number)' && (right.number === 0 || right.number === 1)) || right.id === '(string)') {\n            warn('unexpected_a', right);\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number *= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    infix('/', 140, function (left, that) {\n        if ((left.id === '(number)' && left.number === 0) || left.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(140);\n        if ((right.id === '(number)' && (right.number === 0 || right.number === 1)) || right.id === '(string)') {\n            warn('unexpected_a', right);\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number /= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n    infix('%', 140, function (left, that) {\n        if ((left.id === '(number)' && (left.number === 0 || left.number === 1)) || left.id === '(string)') {\n            warn('unexpected_a', left);\n        }\n        var right = expression(140);\n        if ((right.id === '(number)' && right.number === 0) || right.id === '(string)') {\n            warn('unexpected_a', right);\n        }\n        if (left.id === right.id && left.id === '(number)') {\n            left.number %= right.number;\n            left.thru = right.thru;\n            return left;\n        }\n        that.first = left;\n        that.second = right;\n        return that;\n    });\n\n    suffix('++');\n    prefix('++');\n\n    suffix('--');\n    prefix('--');\n    prefix('delete', function () {\n        one_space();\n        var p = expression(0);\n        if (!p || (p.id !== '.' && p.id !== '[')) {\n            warn('deleted');\n        }\n        this.first = p;\n        return this;\n    });\n\n\n    prefix('~', function () {\n        no_space_only();\n        if (!option.bitwise) {\n            warn('unexpected_a', this);\n        }\n        expression(150);\n        return this;\n    });\n    prefix('!', function () {\n        no_space_only();\n        this.first = expected_condition(expression(150));\n        this.arity = 'prefix';\n        if (bang[this.first.id] === true || this.first.assign) {\n            warn('confusing_a', this);\n        }\n        return this;\n    });\n    prefix('typeof', null);\n    prefix('new', function () {\n        one_space();\n        var c = expression(160), n, p, v;\n        this.first = c;\n        if (c.id !== 'function') {\n            if (c.identifier) {\n                switch (c.string) {\n                case 'Object':\n                    warn('use_object', token);\n                    break;\n                case 'Array':\n                    if (next_token.id === '(') {\n                        p = next_token;\n                        p.first = this;\n                        advance('(');\n                        if (next_token.id !== ')') {\n                            n = expression(0);\n                            p.second = [n];\n                            if (n.id !== '(number)' || next_token.id === ',') {\n                                warn('use_array', p);\n                            }\n                            while (next_token.id === ',') {\n                                advance(',');\n                                p.second.push(expression(0));\n                            }\n                        } else {\n                            warn('use_array', token);\n                        }\n                        advance(')', p);\n                        return p;\n                    }\n                    warn('use_array', token);\n                    break;\n                case 'Number':\n                case 'String':\n                case 'Boolean':\n                case 'Math':\n                case 'JSON':\n                    warn('not_a_constructor', c);\n                    break;\n                case 'Function':\n                    if (!option.evil) {\n                        warn('function_eval');\n                    }\n                    break;\n                case 'Date':\n                case 'RegExp':\n                case 'this':\n                    break;\n                default:\n                    if (c.id !== 'function') {\n                        v = c.string.charAt(0);\n                        if (!option.newcap && (v < 'A' || v > 'Z')) {\n                            warn('constructor_name_a', token);\n                        }\n                    }\n                }\n            } else {\n                if (c.id !== '.' && c.id !== '[' && c.id !== '(') {\n                    warn('bad_constructor', token);\n                }\n            }\n        } else {\n            warn('weird_new', this);\n        }\n        if (next_token.id !== '(') {\n            warn('missing_a', next_token, '()');\n        }\n        return this;\n    });\n\n    infix('(', 160, function (left, that) {\n        var p;\n        if (indent && indent.mode === 'expression') {\n            no_space(prev_token, token);\n        } else {\n            no_space_only(prev_token, token);\n        }\n        if (!left.immed && left.id === 'function') {\n            warn('wrap_immediate');\n        }\n        p = [];\n        if (left.identifier) {\n            if (left.string.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {\n                if (left.string !== 'Number' && left.string !== 'String' &&\n                        left.string !== 'Boolean' && left.string !== 'Date') {\n                    if (left.string === 'Math' || left.string === 'JSON') {\n                        warn('not_a_function', left);\n                    } else if (left.string === 'Object') {\n                        warn('use_object', token);\n                    } else if (left.string === 'Array' || !option.newcap) {\n                        warn('missing_a', left, 'new');\n                    }\n                }\n            }\n        } else if (left.id === '.') {\n            if (option.safe && left.first.string === 'Math' &&\n                    left.second === 'random') {\n                warn('adsafe_a', left);\n            } else if (left.second.string === 'split' &&\n                    left.first.id === '(string)') {\n                warn('use_array', left.second);\n            }\n        }\n        step_in();\n        if (next_token.id !== ')') {\n            no_space();\n            for (;;) {\n                edge();\n                p.push(expression(10));\n                if (next_token.id !== ',') {\n                    break;\n                }\n                comma();\n            }\n        }\n        no_space();\n        step_out(')', that);\n        if (typeof left === 'object') {\n            if (left.string === 'parseInt' && p.length === 1) {\n                warn('radix', left);\n            }\n            if (!option.evil) {\n                if (left.string === 'eval' || left.string === 'Function' ||\n                        left.string === 'execScript') {\n                    warn('evil', left);\n                } else if (p[0] && p[0].id === '(string)' &&\n                        (left.string === 'setTimeout' ||\n                        left.string === 'setInterval')) {\n                    warn('implied_evil', left);\n                }\n            }\n            if (!left.identifier && left.id !== '.' && left.id !== '[' &&\n                    left.id !== '(' && left.id !== '&&' && left.id !== '||' &&\n                    left.id !== '?') {\n                warn('bad_invocation', left);\n            }\n        }\n        that.first = left;\n        that.second = p;\n        return that;\n    }, true);\n\n    prefix('(', function () {\n        step_in('expression');\n        no_space();\n        edge();\n        if (next_token.id === 'function') {\n            next_token.immed = true;\n        }\n        var value = expression(0);\n        value.paren = true;\n        no_space();\n        step_out(')', this);\n        if (value.id === 'function') {\n            switch (next_token.id) {\n            case '(':\n                warn('move_invocation');\n                break;\n            case '.':\n            case '[':\n                warn('unexpected_a');\n                break;\n            default:\n                warn('bad_wrap', this);\n            }\n        }\n        return value;\n    });\n\n    infix('.', 170, function (left, that) {\n        no_space(prev_token, token);\n        no_space();\n        var name = identifier();\n        if (typeof name === 'string') {\n            tally_property(name);\n        }\n        that.first = left;\n        that.second = token;\n        if (left && left.string === 'arguments' &&\n                (name === 'callee' || name === 'caller')) {\n            warn('avoid_a', left, 'arguments.' + name);\n        } else if (!option.evil && left && left.string === 'document' &&\n                (name === 'write' || name === 'writeln')) {\n            warn('write_is_wrong', left);\n        } else if (option.adsafe) {\n            if (!adsafe_top && left.string === 'ADSAFE') {\n                if (name === 'id' || name === 'lib') {\n                    warn('adsafe_a', that);\n                } else if (name === 'go') {\n                    if (xmode !== 'script') {\n                        warn('adsafe_a', that);\n                    } else if (adsafe_went || next_token.id !== '(' ||\n                            peek(0).id !== '(string)' ||\n                            peek(0).string !== adsafe_id ||\n                            peek(1).id !== ',') {\n                        stop('adsafe_a', that, 'go');\n                    }\n                    adsafe_went = true;\n                    adsafe_may = false;\n                }\n            }\n            adsafe_top = false;\n        }\n        if (!option.evil && (name === 'eval' || name === 'execScript')) {\n            warn('evil');\n        } else if (option.safe) {\n            for (;;) {\n                if (banned[name] === true) {\n                    warn('adsafe_a', token, name);\n                }\n                if (typeof predefined[left.string] !== 'boolean' ||    //// check for writeable\n                        next_token.id === '(') {\n                    break;\n                }\n                if (next_token.id !== '.') {\n                    warn('adsafe_a', that);\n                    break;\n                }\n                advance('.');\n                token.first = that;\n                token.second = name;\n                that = token;\n                name = identifier();\n                if (typeof name === 'string') {\n                    tally_property(name);\n                }\n            }\n        }\n        return that;\n    }, true);\n\n    infix('[', 170, function (left, that) {\n        var e, s;\n        no_space_only(prev_token, token);\n        no_space();\n        step_in();\n        edge();\n        e = expression(0);\n        switch (e.id) {\n        case '(number)':\n            if (e.id === '(number)' && left.id === 'arguments') {\n                warn('use_param', left);\n            }\n            break;\n        case '(string)':\n            if (option.safe && (banned[e.string] ||\n                    e.string.charAt(0) === '_' || e.string.slice(-1) === '_')) {\n                warn('adsafe_subscript_a', e);\n            } else if (!option.evil &&\n                    (e.string === 'eval' || e.string === 'execScript')) {\n                warn('evil', e);\n            } else if (!option.sub && ix.test(e.string)) {\n                s = syntax[e.string];\n                if (!s || !s.reserved) {\n                    warn('subscript', e);\n                }\n            }\n            tally_property(e.string);\n            break;\n        default:\n            if (option.safe) {\n                warn('adsafe_subscript_a', e);\n            }\n        }\n        step_out(']', that);\n        no_space(prev_token, token);\n        that.first = left;\n        that.second = e;\n        return that;\n    }, true);\n\n    prefix('[', function () {\n        this.arity = 'prefix';\n        this.first = [];\n        step_in('array');\n        while (next_token.id !== '(end)') {\n            while (next_token.id === ',') {\n                warn('unexpected_a', next_token);\n                advance(',');\n            }\n            if (next_token.id === ']') {\n                break;\n            }\n            indent.wrap = false;\n            edge();\n            this.first.push(expression(10));\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id === ']' && !option.es5) {\n                    warn('unexpected_a', token);\n                    break;\n                }\n            } else {\n                break;\n            }\n        }\n        step_out(']', this);\n        return this;\n    }, 170);\n\n\n    function property_name() {\n        var id = optional_identifier(true);\n        if (!id) {\n            if (next_token.id === '(string)') {\n                id = next_token.string;\n                if (option.safe) {\n                    if (banned[id]) {\n                        warn('adsafe_a');\n                    } else if (id.charAt(0) === '_' ||\n                            id.charAt(id.length - 1) === '_') {\n                        warn('dangling_a');\n                    }\n                }\n                advance();\n            } else if (next_token.id === '(number)') {\n                id = next_token.number.toString();\n                advance();\n            }\n        }\n        return id;\n    }\n\n\n    function function_params() {\n        var id, paren = next_token, params = [];\n        advance('(');\n        step_in();\n        no_space();\n        if (next_token.id === ')') {\n            no_space();\n            step_out(')', paren);\n            return params;\n        }\n        for (;;) {\n            edge();\n            id = identifier();\n            params.push(token);\n            add_label(token, option.unparam ? 'parameter' : 'unparam');\n            if (next_token.id === ',') {\n                comma();\n            } else {\n                no_space();\n                step_out(')', paren);\n                return params;\n            }\n        }\n    }\n\n\n\n    function do_function(func, name) {\n        var old_funct      = funct,\n            old_option     = option,\n            old_scope      = scope;\n        funct = {\n            '(name)'     : name || '\\'' + (anonname || '').replace(nx, sanitize) + '\\'',\n            '(line)'     : next_token.line,\n            '(context)'  : old_funct,\n            '(breakage)' : 0,\n            '(loopage)'  : 0,\n            '(scope)'    : scope,\n            '(token)'    : func\n        };\n        option = Object.create(old_option);\n        scope = Object.create(old_scope);\n        functions.push(funct);\n        func.name = name;\n        if (name) {\n            add_label(func, 'function', name);\n        }\n        func.writeable = false;\n        func.first = funct['(params)'] = function_params();\n        one_space();\n        func.block = block(false);\n        if (funct['(arguments)']) {\n            func.first.forEach(function (value) {\n                if (value.assign) {\n                    warn('parameter_arguments_a', value, value.string);\n                }\n            });\n        }\n        funct      = old_funct;\n        option     = old_option;\n        scope      = old_scope;\n    }\n\n\n    assignop('=');\n    assignop('+=', '+');\n    assignop('-=', '-');\n    assignop('*=', '*');\n    assignop('/=', '/').nud = function () {\n        stop('slash_equal');\n    };\n    assignop('%=', '%');\n    assignop('&=', '&');\n    assignop('|=', '|');\n    assignop('^=', '^');\n    assignop('<<=', '<<');\n    assignop('>>=', '>>');\n    assignop('>>>=', '>>>');\n\n\n    prefix('{', function () {\n        var get, i, j, name, p, set, seen = {};\n        this.arity = 'prefix';\n        this.first = [];\n        step_in();\n        while (next_token.id !== '}') {\n            indent.wrap = false;\n\n// JSLint recognizes the ES5 extension for get/set in object literals,\n// but requires that they be used in pairs.\n\n            edge();\n            if (next_token.string === 'get' && peek().id !== ':') {\n                if (!option.es5) {\n                    warn('es5');\n                }\n                get = next_token;\n                advance('get');\n                one_space_only();\n                name = next_token;\n                i = property_name();\n                if (!i) {\n                    stop('missing_property');\n                }\n                get.string = '';\n                do_function(get);\n                if (funct['(loopage)']) {\n                    warn('function_loop', get);\n                }\n                p = get.first;\n                if (p && p.length) {\n                    warn('parameter_a_get_b', p[0], p[0].string, i);\n                }\n                comma();\n                set = next_token;\n                spaces();\n                edge();\n                advance('set');\n                set.string = '';\n                one_space_only();\n                j = property_name();\n                if (i !== j) {\n                    stop('expected_a_b', token, i, j || next_token.string);\n                }\n                do_function(set);\n                if (set.block.length === 0) {\n                    warn('missing_a', token, 'throw');\n                }\n                p = set.first;\n                if (!p || p.length !== 1) {\n                    stop('parameter_set_a', set, 'value');\n                } else if (p[0].string !== 'value') {\n                    stop('expected_a_b', p[0], 'value', p[0].string);\n                }\n                name.first = [get, set];\n            } else {\n                name = next_token;\n                i = property_name();\n                if (typeof i !== 'string') {\n                    stop('missing_property');\n                }\n                advance(':');\n                spaces();\n                name.first = expression(10);\n            }\n            this.first.push(name);\n            if (seen[i] === true) {\n                warn('duplicate_a', next_token, i);\n            }\n            seen[i] = true;\n            tally_property(i);\n            if (next_token.id !== ',') {\n                break;\n            }\n            for (;;) {\n                comma();\n                if (next_token.id !== ',') {\n                    break;\n                }\n                warn('unexpected_a', next_token);\n            }\n            if (next_token.id === '}' && !option.es5) {\n                warn('unexpected_a', token);\n            }\n        }\n        step_out('}', this);\n        return this;\n    });\n\n    stmt('{', function () {\n        warn('statement_block');\n        this.arity = 'statement';\n        this.block = statements();\n        this.disrupt = this.block.disrupt;\n        advance('}', this);\n        return this;\n    });\n\n    stmt('/*global', directive);\n    stmt('/*globals', directive);\n    stmt('/*jslint', directive);\n    stmt('/*member', directive);\n    stmt('/*members', directive);\n    stmt('/*property', directive);\n    stmt('/*properties', directive);\n\n    stmt('var', function () {\n\n// JavaScript does not have block scope. It only has function scope. So,\n// declaring a variable in a block can have unexpected consequences.\n\n// var.first will contain an array, the array containing name tokens\n// and assignment tokens.\n\n        var assign, id, name;\n\n        if (funct['(vars)'] && !option.vars) {\n            warn('combine_var');\n        } else if (funct !== global_funct) {\n            funct['(vars)'] = true;\n        }\n        this.arity = 'statement';\n        this.first = [];\n        step_in('var');\n        for (;;) {\n            name = next_token;\n            id = identifier();\n            add_label(name, 'becoming');\n\n            if (next_token.id === '=') {\n                assign = next_token;\n                assign.first = name;\n                spaces();\n                advance('=');\n                spaces();\n                if (next_token.id === 'undefined') {\n                    warn('unnecessary_initialize', token, id);\n                }\n                if (peek(0).id === '=' && next_token.identifier) {\n                    stop('var_a_not');\n                }\n                assign.second = expression(0);\n                assign.arity = 'infix';\n                this.first.push(assign);\n            } else {\n                this.first.push(name);\n            }\n            if (funct[id] === 'becoming') {\n                funct[id] = 'unused';\n            }\n            if (next_token.id !== ',') {\n                break;\n            }\n            comma();\n            indent.wrap = false;\n            if (var_mode && next_token.line === token.line &&\n                    this.first.length === 1) {\n                var_mode = null;\n                indent.open = false;\n                indent.at -= option.indent;\n            }\n            spaces();\n            edge();\n        }\n        var_mode = null;\n        step_out();\n        return this;\n    });\n\n    stmt('function', function () {\n        one_space();\n        if (in_block) {\n            warn('function_block', token);\n        }\n        var name = next_token, id = identifier();\n        add_label(name, 'unction');\n        no_space();\n        this.arity = 'statement';\n        do_function(this, id);\n        if (next_token.id === '(' && next_token.line === token.line) {\n            stop('function_statement');\n        }\n        return this;\n    });\n\n    prefix('function', function () {\n        if (!option.anon) {\n            one_space();\n        }\n        var id = optional_identifier();\n        if (id) {\n            no_space();\n        } else {\n            id = '';\n        }\n        do_function(this, id);\n        if (funct['(loopage)']) {\n            warn('function_loop');\n        }\n        switch (next_token.id) {\n        case ';':\n        case '(':\n        case ')':\n        case ',':\n        case ']':\n        case '}':\n        case ':':\n            break;\n        case '.':\n            if (peek().string !== 'bind' || peek(1).id !== '(') {\n                warn('unexpected_a');\n            }\n            break;\n        default:\n            stop('unexpected_a');\n        }\n        this.arity = 'function';\n        return this;\n    });\n\n    stmt('if', function () {\n        var paren = next_token;\n        one_space();\n        advance('(');\n        step_in('control');\n        no_space();\n        edge();\n        this.arity = 'statement';\n        this.first = expected_condition(expected_relation(expression(0)));\n        no_space();\n        step_out(')', paren);\n        one_space();\n        this.block = block(true);\n        if (next_token.id === 'else') {\n            one_space();\n            advance('else');\n            one_space();\n            this['else'] = next_token.id === 'if' || next_token.id === 'switch'\n                ? statement(true)\n                : block(true);\n            if (this['else'].disrupt && this.block.disrupt) {\n                this.disrupt = true;\n            }\n        }\n        return this;\n    });\n\n    stmt('try', function () {\n\n// try.first    The catch variable\n// try.second   The catch clause\n// try.third    The finally clause\n// try.block    The try block\n\n        var exception_variable, old_scope, paren;\n        if (option.adsafe) {\n            warn('adsafe_a', this);\n        }\n        one_space();\n        this.arity = 'statement';\n        this.block = block(false);\n        if (next_token.id === 'catch') {\n            one_space();\n            advance('catch');\n            one_space();\n            paren = next_token;\n            advance('(');\n            step_in('control');\n            no_space();\n            edge();\n            old_scope = scope;\n            scope = Object.create(old_scope);\n            exception_variable = next_token.string;\n            this.first = exception_variable;\n            if (!next_token.identifier) {\n                warn('expected_identifier_a', next_token);\n            } else {\n                add_label(next_token, 'exception');\n            }\n            advance();\n            no_space();\n            step_out(')', paren);\n            one_space();\n            this.second = block(false);\n            scope = old_scope;\n        }\n        if (next_token.id === 'finally') {\n            one_space();\n            advance('finally');\n            one_space();\n            this.third = block(false);\n        } else if (!this.second) {\n            stop('expected_a_b', next_token, 'catch', artifact());\n        }\n        return this;\n    });\n\n    labeled_stmt('while', function () {\n        one_space();\n        var paren = next_token;\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        step_in('control');\n        no_space();\n        edge();\n        this.arity = 'statement';\n        this.first = expected_relation(expression(0));\n        if (this.first.id !== 'true') {\n            expected_condition(this.first, bundle.unexpected_a);\n        }\n        no_space();\n        step_out(')', paren);\n        one_space();\n        this.block = block(true);\n        if (this.block.disrupt) {\n            warn('strange_loop', prev_token);\n        }\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    });\n\n    reserve('with');\n\n    labeled_stmt('switch', function () {\n\n// switch.first         the switch expression\n// switch.second        the array of cases. A case is 'case' or 'default' token:\n//    case.first        the array of case expressions\n//    case.second       the array of statements\n// If all of the arrays of statements are disrupt, then the switch is disrupt.\n\n        var cases = [],\n            old_in_block = in_block,\n            particular,\n            the_case = next_token,\n            unbroken = true;\n\n        function find_duplicate_case(value) {\n            if (are_similar(particular, value)) {\n                warn('duplicate_a', value);\n            }\n        }\n\n        funct['(breakage)'] += 1;\n        one_space();\n        advance('(');\n        no_space();\n        step_in();\n        this.arity = 'statement';\n        this.first = expected_condition(expected_relation(expression(0)));\n        no_space();\n        step_out(')', the_case);\n        one_space();\n        advance('{');\n        step_in();\n        in_block = true;\n        this.second = [];\n        while (next_token.id === 'case') {\n            the_case = next_token;\n            cases.forEach(find_duplicate_case);\n            the_case.first = [];\n            the_case.arity = 'case';\n            spaces();\n            edge('case');\n            advance('case');\n            for (;;) {\n                one_space();\n                particular = expression(0);\n                cases.forEach(find_duplicate_case);\n                cases.push(particular);\n                the_case.first.push(particular);\n                if (particular.id === 'NaN') {\n                    warn('unexpected_a', particular);\n                }\n                no_space_only();\n                advance(':');\n                if (next_token.id !== 'case') {\n                    break;\n                }\n                spaces();\n                edge('case');\n                advance('case');\n            }\n            spaces();\n            the_case.second = statements();\n            if (the_case.second && the_case.second.length > 0) {\n                particular = the_case.second[the_case.second.length - 1];\n                if (particular.disrupt) {\n                    if (particular.id === 'break') {\n                        unbroken = false;\n                    }\n                } else {\n                    warn('missing_a_after_b', next_token, 'break', 'case');\n                }\n            } else {\n                warn('empty_case');\n            }\n            this.second.push(the_case);\n        }\n        if (this.second.length === 0) {\n            warn('missing_a', next_token, 'case');\n        }\n        if (next_token.id === 'default') {\n            spaces();\n            the_case = next_token;\n            the_case.arity = 'case';\n            edge('case');\n            advance('default');\n            no_space_only();\n            advance(':');\n            spaces();\n            the_case.second = statements();\n            if (the_case.second && the_case.second.length > 0) {\n                particular = the_case.second[the_case.second.length - 1];\n                if (unbroken && particular.disrupt && particular.id !== 'break') {\n                    this.disrupt = true;\n                }\n            }\n            this.second.push(the_case);\n        }\n        funct['(breakage)'] -= 1;\n        spaces();\n        step_out('}', this);\n        in_block = old_in_block;\n        return this;\n    });\n\n    stmt('debugger', function () {\n        if (!option.debug) {\n            warn('unexpected_a', this);\n        }\n        this.arity = 'statement';\n        return this;\n    });\n\n    labeled_stmt('do', function () {\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        one_space();\n        this.arity = 'statement';\n        this.block = block(true);\n        if (this.block.disrupt) {\n            warn('strange_loop', prev_token);\n        }\n        one_space();\n        advance('while');\n        var paren = next_token;\n        one_space();\n        advance('(');\n        step_in();\n        no_space();\n        edge();\n        this.first = expected_condition(expected_relation(expression(0)), bundle.unexpected_a);\n        no_space();\n        step_out(')', paren);\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    });\n\n    labeled_stmt('for', function () {\n\n        var blok, filter, ok = false, paren = next_token, value;\n        this.arity = 'statement';\n        funct['(breakage)'] += 1;\n        funct['(loopage)'] += 1;\n        advance('(');\n        if (next_token.id === ';') {\n            no_space();\n            advance(';');\n            no_space();\n            advance(';');\n            no_space();\n            advance(')');\n            blok = block(true);\n        } else {\n            step_in('control');\n            spaces(this, paren);\n            no_space();\n            if (next_token.id === 'var') {\n                stop('move_var');\n            }\n            edge();\n            if (peek(0).id === 'in') {\n                this.forin = true;\n                value = next_token;\n                switch (funct[value.string]) {\n                case 'unused':\n                    funct[value.string] = 'var';\n                    break;\n                case 'closure':\n                case 'var':\n                    break;\n                default:\n                    warn('bad_in_a', value);\n                }\n                advance();\n                advance('in');\n                this.first = value;\n                this.second = expression(20);\n                step_out(')', paren);\n                blok = block(true);\n                if (!option.forin) {\n                    if (blok.length === 1 && typeof blok[0] === 'object' &&\n                            blok[0].string === 'if' && !blok[0]['else']) {\n                        filter = blok[0].first;\n                        while (filter.id === '&&') {\n                            filter = filter.first;\n                        }\n                        switch (filter.id) {\n                        case '===':\n                        case '!==':\n                            ok = filter.first.id === '['\n                                ? filter.first.first.string === this.second.string &&\n                                    filter.first.second.string === this.first.string\n                                : filter.first.id === 'typeof' &&\n                                    filter.first.first.id === '[' &&\n                                    filter.first.first.first.string === this.second.string &&\n                                    filter.first.first.second.string === this.first.string;\n                            break;\n                        case '(':\n                            ok = filter.first.id === '.' && ((\n                                filter.first.first.string === this.second.string &&\n                                filter.first.second.string === 'hasOwnProperty' &&\n                                filter.second[0].string === this.first.string\n                            ) || (\n                                filter.first.first.string === 'ADSAFE' &&\n                                filter.first.second.string === 'has' &&\n                                filter.second[0].string === this.second.string &&\n                                filter.second[1].string === this.first.string\n                            ) || (\n                                filter.first.first.id === '.' &&\n                                filter.first.first.first.id === '.' &&\n                                filter.first.first.first.first.string === 'Object' &&\n                                filter.first.first.first.second.string === 'prototype' &&\n                                filter.first.first.second.string === 'hasOwnProperty' &&\n                                filter.first.second.string === 'call' &&\n                                filter.second[0].string === this.second.string &&\n                                filter.second[1].string === this.first.string\n                            ));\n                            break;\n                        }\n                    }\n                    if (!ok) {\n                        warn('for_if', this);\n                    }\n                }\n            } else {\n                edge();\n                this.first = [];\n                for (;;) {\n                    this.first.push(expression(0, 'for'));\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n                semicolon();\n                edge();\n                this.second = expected_relation(expression(0));\n                if (this.second.id !== 'true') {\n                    expected_condition(this.second, bundle.unexpected_a);\n                }\n                semicolon(token);\n                if (next_token.id === ';') {\n                    stop('expected_a_b', next_token, ')', ';');\n                }\n                this.third = [];\n                edge();\n                for (;;) {\n                    this.third.push(expression(0, 'for'));\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n                no_space();\n                step_out(')', paren);\n                one_space();\n                blok = block(true);\n            }\n        }\n        if (blok.disrupt) {\n            warn('strange_loop', prev_token);\n        }\n        this.block = blok;\n        funct['(breakage)'] -= 1;\n        funct['(loopage)'] -= 1;\n        return this;\n    });\n\n    disrupt_stmt('break', function () {\n        var label = next_token.string;\n        this.arity = 'statement';\n        if (funct['(breakage)'] === 0) {\n            warn('unexpected_a', this);\n        }\n        if (next_token.identifier && token.line === next_token.line) {\n            one_space_only();\n            if (funct[label] !== 'label') {\n                warn('not_a_label', next_token);\n            } else if (scope[label].funct !== funct) {\n                warn('not_a_scope', next_token);\n            }\n            this.first = next_token;\n            advance();\n        }\n        return this;\n    });\n\n    disrupt_stmt('continue', function () {\n        if (!option['continue']) {\n            warn('unexpected_a', this);\n        }\n        var label = next_token.string;\n        this.arity = 'statement';\n        if (funct['(breakage)'] === 0) {\n            warn('unexpected_a', this);\n        }\n        if (next_token.identifier && token.line === next_token.line) {\n            one_space_only();\n            if (funct[label] !== 'label') {\n                warn('not_a_label', next_token);\n            } else if (scope[label].funct !== funct) {\n                warn('not_a_scope', next_token);\n            }\n            this.first = next_token;\n            advance();\n        }\n        return this;\n    });\n\n    disrupt_stmt('return', function () {\n        if (funct === global_funct && xmode !== 'scriptstring') {\n            warn('unexpected_a', this);\n        }\n        this.arity = 'statement';\n        if (next_token.id !== ';' && next_token.line === token.line) {\n            one_space_only();\n            if (next_token.id === '/' || next_token.id === '(regexp)') {\n                warn('wrap_regexp');\n            }\n            this.first = expression(20);\n        }\n        if (peek(0).id === '}' && peek(1).id === 'else') {\n            warn('unexpected_else', this);\n        }\n        return this;\n    });\n\n    disrupt_stmt('throw', function () {\n        this.arity = 'statement';\n        one_space_only();\n        this.first = expression(20);\n        return this;\n    });\n\n\n//  Superfluous reserved words\n\n    reserve('class');\n    reserve('const');\n    reserve('enum');\n    reserve('export');\n    reserve('extends');\n    reserve('import');\n    reserve('super');\n\n// Harmony reserved words\n\n    reserve('implements');\n    reserve('interface');\n    reserve('let');\n    reserve('package');\n    reserve('private');\n    reserve('protected');\n    reserve('public');\n    reserve('static');\n    reserve('yield');\n\n\n// Parse JSON\n\n    function json_value() {\n\n        function json_object() {\n            var brace = next_token, object = {};\n            advance('{');\n            if (next_token.id !== '}') {\n                while (next_token.id !== '(end)') {\n                    while (next_token.id === ',') {\n                        warn('unexpected_a', next_token);\n                        advance(',');\n                    }\n                    if (next_token.id !== '(string)') {\n                        warn('expected_string_a');\n                    }\n                    if (object[next_token.string] === true) {\n                        warn('duplicate_a');\n                    } else if (next_token.string === '__proto__') {\n                        warn('dangling_a');\n                    } else {\n                        object[next_token.string] = true;\n                    }\n                    advance();\n                    advance(':');\n                    json_value();\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                    if (next_token.id === '}') {\n                        warn('unexpected_a', token);\n                        break;\n                    }\n                }\n            }\n            advance('}', brace);\n        }\n\n        function json_array() {\n            var bracket = next_token;\n            advance('[');\n            if (next_token.id !== ']') {\n                while (next_token.id !== '(end)') {\n                    while (next_token.id === ',') {\n                        warn('unexpected_a', next_token);\n                        advance(',');\n                    }\n                    json_value();\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    advance(',');\n                    if (next_token.id === ']') {\n                        warn('unexpected_a', token);\n                        break;\n                    }\n                }\n            }\n            advance(']', bracket);\n        }\n\n        switch (next_token.id) {\n        case '{':\n            json_object();\n            break;\n        case '[':\n            json_array();\n            break;\n        case 'true':\n        case 'false':\n        case 'null':\n        case '(number)':\n        case '(string)':\n            advance();\n            break;\n        case '-':\n            advance('-');\n            no_space_only();\n            advance('(number)');\n            break;\n        default:\n            stop('unexpected_a');\n        }\n    }\n\n\n// CSS parsing.\n\n    function css_name() {\n        if (next_token.identifier) {\n            advance();\n            return true;\n        }\n    }\n\n\n    function css_number() {\n        if (next_token.id === '-') {\n            advance('-');\n            no_space_only();\n        }\n        if (next_token.id === '(number)') {\n            advance('(number)');\n            return true;\n        }\n    }\n\n\n    function css_string() {\n        if (next_token.id === '(string)') {\n            advance();\n            return true;\n        }\n    }\n\n    function css_color() {\n        var i, number, paren, value;\n        if (next_token.identifier) {\n            value = next_token.string;\n            if (value === 'rgb' || value === 'rgba') {\n                advance();\n                paren = next_token;\n                advance('(');\n                for (i = 0; i < 3; i += 1) {\n                    if (i) {\n                        comma();\n                    }\n                    number = next_token.number;\n                    if (next_token.id !== '(number)' || number < 0) {\n                        warn('expected_positive_a', next_token);\n                        advance();\n                    } else {\n                        advance();\n                        if (next_token.id === '%') {\n                            advance('%');\n                            if (number > 100) {\n                                warn('expected_percent_a', token, number);\n                            }\n                        } else {\n                            if (number > 255) {\n                                warn('expected_small_a', token, number);\n                            }\n                        }\n                    }\n                }\n                if (value === 'rgba') {\n                    comma();\n                    number = next_token.number;\n                    if (next_token.id !== '(number)' || number < 0 || number > 1) {\n                        warn('expected_fraction_a', next_token);\n                    }\n                    advance();\n                    if (next_token.id === '%') {\n                        warn('unexpected_a');\n                        advance('%');\n                    }\n                }\n                advance(')', paren);\n                return true;\n            }\n            if (css_colorData[next_token.string] === true) {\n                advance();\n                return true;\n            }\n        } else if (next_token.id === '(color)') {\n            advance();\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_length() {\n        if (next_token.id === '-') {\n            advance('-');\n            no_space_only();\n        }\n        if (next_token.id === '(number)') {\n            advance();\n            if (next_token.id !== '(string)' &&\n                    css_lengthData[next_token.string] === true) {\n                no_space_only();\n                advance();\n            } else if (+token.number !== 0) {\n                warn('expected_linear_a');\n            }\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_line_height() {\n        if (next_token.id === '-') {\n            advance('-');\n            no_space_only();\n        }\n        if (next_token.id === '(number)') {\n            advance();\n            if (next_token.id !== '(string)' &&\n                    css_lengthData[next_token.string] === true) {\n                no_space_only();\n                advance();\n            }\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_width() {\n        if (next_token.identifier) {\n            switch (next_token.string) {\n            case 'thin':\n            case 'medium':\n            case 'thick':\n                advance();\n                return true;\n            }\n        } else {\n            return css_length();\n        }\n    }\n\n\n    function css_margin() {\n        if (next_token.identifier) {\n            if (next_token.string === 'auto') {\n                advance();\n                return true;\n            }\n        } else {\n            return css_length();\n        }\n    }\n\n    function css_attr() {\n        if (next_token.identifier && next_token.string === 'attr') {\n            advance();\n            advance('(');\n            if (!next_token.identifier) {\n                warn('expected_name_a');\n            }\n            advance();\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_comma_list() {\n        while (next_token.id !== ';') {\n            if (!css_name() && !css_string()) {\n                warn('expected_name_a');\n            }\n            if (next_token.id !== ',') {\n                return true;\n            }\n            comma();\n        }\n    }\n\n\n    function css_counter() {\n        if (next_token.identifier && next_token.string === 'counter') {\n            advance();\n            advance('(');\n            advance();\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id !== '(string)') {\n                    warn('expected_string_a');\n                }\n                advance();\n            }\n            advance(')');\n            return true;\n        }\n        if (next_token.identifier && next_token.string === 'counters') {\n            advance();\n            advance('(');\n            if (!next_token.identifier) {\n                warn('expected_name_a');\n            }\n            advance();\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id !== '(string)') {\n                    warn('expected_string_a');\n                }\n                advance();\n            }\n            if (next_token.id === ',') {\n                comma();\n                if (next_token.id !== '(string)') {\n                    warn('expected_string_a');\n                }\n                advance();\n            }\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_radius() {\n        return css_length() && (next_token.id !== '(number)' || css_length());\n    }\n\n\n    function css_shape() {\n        var i;\n        if (next_token.identifier && next_token.string === 'rect') {\n            advance();\n            advance('(');\n            for (i = 0; i < 4; i += 1) {\n                if (!css_length()) {\n                    warn('expected_number_a');\n                    break;\n                }\n            }\n            advance(')');\n            return true;\n        }\n        return false;\n    }\n\n\n    function css_url() {\n        var c, url;\n        if (next_token.identifier && next_token.string === 'url') {\n            next_token = lex.range('(', ')');\n            url = next_token.string;\n            c = url.charAt(0);\n            if (c === '\"' || c === '\\'') {\n                if (url.slice(-1) !== c) {\n                    warn('bad_url_a');\n                } else {\n                    url = url.slice(1, -1);\n                    if (url.indexOf(c) >= 0) {\n                        warn('bad_url_a');\n                    }\n                }\n            }\n            if (!url) {\n                warn('missing_url');\n            }\n            if (ux.test(url)) {\n                stop('bad_url_a');\n            }\n            urls.push(url);\n            advance();\n            return true;\n        }\n        return false;\n    }\n\n\n    css_any = [css_url, function () {\n        for (;;) {\n            if (next_token.identifier) {\n                switch (next_token.string.toLowerCase()) {\n                case 'url':\n                    css_url();\n                    break;\n                case 'expression':\n                    warn('unexpected_a');\n                    advance();\n                    break;\n                default:\n                    advance();\n                }\n            } else {\n                if (next_token.id === ';' || next_token.id === '!'  ||\n                        next_token.id === '(end)' || next_token.id === '}') {\n                    return true;\n                }\n                advance();\n            }\n        }\n    }];\n\n\n    function font_face() {\n        advance_identifier('font-family');\n        advance(':');\n        if (!css_name() && !css_string()) {\n            stop('expected_name_a');\n        }\n        semicolon();\n        advance_identifier('src');\n        advance(':');\n        while (true) {\n            if (next_token.string === 'local') {\n                advance_identifier('local');\n                advance('(');\n                if (ux.test(next_token.string)) {\n                    stop('bad_url_a');\n                }\n\n                if (!css_name() && !css_string()) {\n                    stop('expected_name_a');\n                }\n                advance(')');\n            } else if (!css_url()) {\n                stop('expected_a_b', next_token, 'url', artifact());\n            }\n            if (next_token.id !== ',') {\n                break;\n            }\n            comma();\n        }\n        semicolon();\n    }\n\n\n    css_border_style = [\n        'none', 'dashed', 'dotted', 'double', 'groove',\n        'hidden', 'inset', 'outset', 'ridge', 'solid'\n    ];\n\n    css_break = [\n        'auto', 'always', 'avoid', 'left', 'right'\n    ];\n\n    css_media = {\n        'all': true,\n        'braille': true,\n        'embossed': true,\n        'handheld': true,\n        'print': true,\n        'projection': true,\n        'screen': true,\n        'speech': true,\n        'tty': true,\n        'tv': true\n    };\n\n    css_overflow = [\n        'auto', 'hidden', 'scroll', 'visible'\n    ];\n\n    css_attribute_data = {\n        background: [\n            true, 'background-attachment', 'background-color',\n            'background-image', 'background-position', 'background-repeat'\n        ],\n        'background-attachment': ['scroll', 'fixed'],\n        'background-color': ['transparent', css_color],\n        'background-image': ['none', css_url],\n        'background-position': [\n            2, [css_length, 'top', 'bottom', 'left', 'right', 'center']\n        ],\n        'background-repeat': [\n            'repeat', 'repeat-x', 'repeat-y', 'no-repeat'\n        ],\n        'border': [true, 'border-color', 'border-style', 'border-width'],\n        'border-bottom': [\n            true, 'border-bottom-color', 'border-bottom-style',\n            'border-bottom-width'\n        ],\n        'border-bottom-color': css_color,\n        'border-bottom-left-radius': css_radius,\n        'border-bottom-right-radius': css_radius,\n        'border-bottom-style': css_border_style,\n        'border-bottom-width': css_width,\n        'border-collapse': ['collapse', 'separate'],\n        'border-color': ['transparent', 4, css_color],\n        'border-left': [\n            true, 'border-left-color', 'border-left-style', 'border-left-width'\n        ],\n        'border-left-color': css_color,\n        'border-left-style': css_border_style,\n        'border-left-width': css_width,\n        'border-radius': function () {\n            function count(separator) {\n                var n = 1;\n                if (separator) {\n                    advance(separator);\n                }\n                if (!css_length()) {\n                    return false;\n                }\n                while (next_token.id === '(number)') {\n                    if (!css_length()) {\n                        return false;\n                    }\n                    n += 1;\n                }\n                if (n > 4) {\n                    warn('bad_style');\n                }\n                return true;\n            }\n\n            return count() && (next_token.id !== '/' || count('/'));\n        },\n        'border-right': [\n            true, 'border-right-color', 'border-right-style',\n            'border-right-width'\n        ],\n        'border-right-color': css_color,\n        'border-right-style': css_border_style,\n        'border-right-width': css_width,\n        'border-spacing': [2, css_length],\n        'border-style': [4, css_border_style],\n        'border-top': [\n            true, 'border-top-color', 'border-top-style', 'border-top-width'\n        ],\n        'border-top-color': css_color,\n        'border-top-left-radius': css_radius,\n        'border-top-right-radius': css_radius,\n        'border-top-style': css_border_style,\n        'border-top-width': css_width,\n        'border-width': [4, css_width],\n        bottom: [css_length, 'auto'],\n        'caption-side' : ['bottom', 'left', 'right', 'top'],\n        clear: ['both', 'left', 'none', 'right'],\n        clip: [css_shape, 'auto'],\n        color: css_color,\n        content: [\n            'open-quote', 'close-quote', 'no-open-quote', 'no-close-quote',\n            css_string, css_url, css_counter, css_attr\n        ],\n        'counter-increment': [\n            css_name, 'none'\n        ],\n        'counter-reset': [\n            css_name, 'none'\n        ],\n        cursor: [\n            css_url, 'auto', 'crosshair', 'default', 'e-resize', 'help', 'move',\n            'n-resize', 'ne-resize', 'nw-resize', 'pointer', 's-resize',\n            'se-resize', 'sw-resize', 'w-resize', 'text', 'wait'\n        ],\n        direction: ['ltr', 'rtl'],\n        display: [\n            'block', 'compact', 'inline', 'inline-block', 'inline-table',\n            'list-item', 'marker', 'none', 'run-in', 'table', 'table-caption',\n            'table-cell', 'table-column', 'table-column-group',\n            'table-footer-group', 'table-header-group', 'table-row',\n            'table-row-group'\n        ],\n        'empty-cells': ['show', 'hide'],\n        'float': ['left', 'none', 'right'],\n        font: [\n            'caption', 'icon', 'menu', 'message-box', 'small-caption',\n            'status-bar', true, 'font-size', 'font-style', 'font-weight',\n            'font-family'\n        ],\n        'font-family': css_comma_list,\n        'font-size': [\n            'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large',\n            'xx-large', 'larger', 'smaller', css_length\n        ],\n        'font-size-adjust': ['none', css_number],\n        'font-stretch': [\n            'normal', 'wider', 'narrower', 'ultra-condensed',\n            'extra-condensed', 'condensed', 'semi-condensed',\n            'semi-expanded', 'expanded', 'extra-expanded'\n        ],\n        'font-style': [\n            'normal', 'italic', 'oblique'\n        ],\n        'font-variant': [\n            'normal', 'small-caps'\n        ],\n        'font-weight': [\n            'normal', 'bold', 'bolder', 'lighter', css_number\n        ],\n        height: [css_length, 'auto'],\n        left: [css_length, 'auto'],\n        'letter-spacing': ['normal', css_length],\n        'line-height': ['normal', css_line_height],\n        'list-style': [\n            true, 'list-style-image', 'list-style-position', 'list-style-type'\n        ],\n        'list-style-image': ['none', css_url],\n        'list-style-position': ['inside', 'outside'],\n        'list-style-type': [\n            'circle', 'disc', 'square', 'decimal', 'decimal-leading-zero',\n            'lower-roman', 'upper-roman', 'lower-greek', 'lower-alpha',\n            'lower-latin', 'upper-alpha', 'upper-latin', 'hebrew', 'katakana',\n            'hiragana-iroha', 'katakana-oroha', 'none'\n        ],\n        margin: [4, css_margin],\n        'margin-bottom': css_margin,\n        'margin-left': css_margin,\n        'margin-right': css_margin,\n        'margin-top': css_margin,\n        'marker-offset': [css_length, 'auto'],\n        'max-height': [css_length, 'none'],\n        'max-width': [css_length, 'none'],\n        'min-height': css_length,\n        'min-width': css_length,\n        opacity: css_number,\n        outline: [true, 'outline-color', 'outline-style', 'outline-width'],\n        'outline-color': ['invert', css_color],\n        'outline-style': [\n            'dashed', 'dotted', 'double', 'groove', 'inset', 'none',\n            'outset', 'ridge', 'solid'\n        ],\n        'outline-width': css_width,\n        overflow: css_overflow,\n        'overflow-x': css_overflow,\n        'overflow-y': css_overflow,\n        padding: [4, css_length],\n        'padding-bottom': css_length,\n        'padding-left': css_length,\n        'padding-right': css_length,\n        'padding-top': css_length,\n        'page-break-after': css_break,\n        'page-break-before': css_break,\n        position: ['absolute', 'fixed', 'relative', 'static'],\n        quotes: [8, css_string],\n        right: [css_length, 'auto'],\n        'table-layout': ['auto', 'fixed'],\n        'text-align': ['center', 'justify', 'left', 'right'],\n        'text-decoration': [\n            'none', 'underline', 'overline', 'line-through', 'blink'\n        ],\n        'text-indent': css_length,\n        'text-shadow': ['none', 4, [css_color, css_length]],\n        'text-transform': ['capitalize', 'uppercase', 'lowercase', 'none'],\n        top: [css_length, 'auto'],\n        'unicode-bidi': ['normal', 'embed', 'bidi-override'],\n        'vertical-align': [\n            'baseline', 'bottom', 'sub', 'super', 'top', 'text-top', 'middle',\n            'text-bottom', css_length\n        ],\n        visibility: ['visible', 'hidden', 'collapse'],\n        'white-space': [\n            'normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap', 'inherit'\n        ],\n        width: [css_length, 'auto'],\n        'word-spacing': ['normal', css_length],\n        'word-wrap': ['break-word', 'normal'],\n        'z-index': ['auto', css_number]\n    };\n\n    function style_attribute() {\n        var v;\n        while (next_token.id === '*' || next_token.id === '#' ||\n                next_token.string === '_') {\n            if (!option.css) {\n                warn('unexpected_a');\n            }\n            advance();\n        }\n        if (next_token.id === '-') {\n            if (!option.css) {\n                warn('unexpected_a');\n            }\n            advance('-');\n            if (!next_token.identifier) {\n                warn('expected_nonstandard_style_attribute');\n            }\n            advance();\n            return css_any;\n        }\n        if (!next_token.identifier) {\n            warn('expected_style_attribute');\n        } else {\n            if (Object.prototype.hasOwnProperty.call(css_attribute_data,\n                    next_token.string)) {\n                v = css_attribute_data[next_token.string];\n            } else {\n                v = css_any;\n                if (!option.css) {\n                    warn('unrecognized_style_attribute_a');\n                }\n            }\n        }\n        advance();\n        return v;\n    }\n\n\n    function style_value(v) {\n        var i = 0,\n            n,\n            once,\n            match,\n            round,\n            start = 0,\n            vi;\n        switch (typeof v) {\n        case 'function':\n            return v();\n        case 'string':\n            if (next_token.identifier && next_token.string === v) {\n                advance();\n                return true;\n            }\n            return false;\n        }\n        for (;;) {\n            if (i >= v.length) {\n                return false;\n            }\n            vi = v[i];\n            i += 1;\n            if (typeof vi === 'boolean') {\n                break;\n            } else if (typeof vi === 'number') {\n                n = vi;\n                vi = v[i];\n                i += 1;\n            } else {\n                n = 1;\n            }\n            match = false;\n            while (n > 0) {\n                if (style_value(vi)) {\n                    match = true;\n                    n -= 1;\n                } else {\n                    break;\n                }\n            }\n            if (match) {\n                return true;\n            }\n        }\n        start = i;\n        once = [];\n        for (;;) {\n            round = false;\n            for (i = start; i < v.length; i += 1) {\n                if (!once[i]) {\n                    if (style_value(css_attribute_data[v[i]])) {\n                        match = true;\n                        round = true;\n                        once[i] = true;\n                        break;\n                    }\n                }\n            }\n            if (!round) {\n                return match;\n            }\n        }\n    }\n\n    function style_child() {\n        if (next_token.id === '(number)') {\n            advance();\n            if (next_token.string === 'n' && next_token.identifier) {\n                no_space_only();\n                advance();\n                if (next_token.id === '+') {\n                    no_space_only();\n                    advance('+');\n                    no_space_only();\n                    advance('(number)');\n                }\n            }\n            return;\n        }\n        if (next_token.identifier &&\n                (next_token.string === 'odd' || next_token.string === 'even')) {\n            advance();\n            return;\n        }\n        warn('unexpected_a');\n    }\n\n    function substyle() {\n        var v;\n        for (;;) {\n            if (next_token.id === '}' || next_token.id === '(end)' ||\n                    (xquote && next_token.id === xquote)) {\n                return;\n            }\n            v = style_attribute();\n            advance(':');\n            if (next_token.identifier && next_token.string === 'inherit') {\n                advance();\n            } else {\n                if (!style_value(v)) {\n                    warn('unexpected_a');\n                    advance();\n                }\n            }\n            if (next_token.id === '!') {\n                advance('!');\n                no_space_only();\n                if (next_token.identifier && next_token.string === 'important') {\n                    advance();\n                } else {\n                    warn('expected_a_b',\n                        next_token, 'important', artifact());\n                }\n            }\n            if (next_token.id === '}' || next_token.id === xquote) {\n                warn('expected_a_b', next_token, ';', artifact());\n            } else {\n                semicolon();\n            }\n        }\n    }\n\n    function style_selector() {\n        if (next_token.identifier) {\n            if (!Object.prototype.hasOwnProperty.call(html_tag, option.cap\n                    ? next_token.string.toLowerCase()\n                    : next_token.string)) {\n                warn('expected_tagname_a');\n            }\n            advance();\n        } else {\n            switch (next_token.id) {\n            case '>':\n            case '+':\n                advance();\n                style_selector();\n                break;\n            case ':':\n                advance(':');\n                switch (next_token.string) {\n                case 'active':\n                case 'after':\n                case 'before':\n                case 'checked':\n                case 'disabled':\n                case 'empty':\n                case 'enabled':\n                case 'first-child':\n                case 'first-letter':\n                case 'first-line':\n                case 'first-of-type':\n                case 'focus':\n                case 'hover':\n                case 'last-child':\n                case 'last-of-type':\n                case 'link':\n                case 'only-of-type':\n                case 'root':\n                case 'target':\n                case 'visited':\n                    advance_identifier(next_token.string);\n                    break;\n                case 'lang':\n                    advance_identifier('lang');\n                    advance('(');\n                    if (!next_token.identifier) {\n                        warn('expected_lang_a');\n                    }\n                    advance(')');\n                    break;\n                case 'nth-child':\n                case 'nth-last-child':\n                case 'nth-last-of-type':\n                case 'nth-of-type':\n                    advance_identifier(next_token.string);\n                    advance('(');\n                    style_child();\n                    advance(')');\n                    break;\n                case 'not':\n                    advance_identifier('not');\n                    advance('(');\n                    if (next_token.id === ':' && peek(0).string === 'not') {\n                        warn('not');\n                    }\n                    style_selector();\n                    advance(')');\n                    break;\n                default:\n                    warn('expected_pseudo_a');\n                }\n                break;\n            case '#':\n                advance('#');\n                if (!next_token.identifier) {\n                    warn('expected_id_a');\n                }\n                advance();\n                break;\n            case '*':\n                advance('*');\n                break;\n            case '.':\n                advance('.');\n                if (!next_token.identifier) {\n                    warn('expected_class_a');\n                }\n                advance();\n                break;\n            case '[':\n                advance('[');\n                if (!next_token.identifier) {\n                    warn('expected_attribute_a');\n                }\n                advance();\n                if (next_token.id === '=' || next_token.string === '~=' ||\n                        next_token.string === '$=' ||\n                        next_token.string === '|=' ||\n                        next_token.id === '*=' ||\n                        next_token.id === '^=') {\n                    advance();\n                    if (next_token.id !== '(string)') {\n                        warn('expected_string_a');\n                    }\n                    advance();\n                }\n                advance(']');\n                break;\n            default:\n                stop('expected_selector_a');\n            }\n        }\n    }\n\n    function style_pattern() {\n        if (next_token.id === '{') {\n            warn('expected_style_pattern');\n        }\n        for (;;) {\n            style_selector();\n            if (next_token.id === '</' || next_token.id === '{' ||\n                    next_token.id === '}' || next_token.id === '(end)') {\n                return '';\n            }\n            if (next_token.id === ',') {\n                comma();\n            }\n        }\n    }\n\n    function style_list() {\n        while (next_token.id !== '}' && next_token.id !== '</' &&\n                next_token.id !== '(end)') {\n            style_pattern();\n            xmode = 'styleproperty';\n            if (next_token.id === ';') {\n                semicolon();\n            } else {\n                advance('{');\n                substyle();\n                xmode = 'style';\n                advance('}');\n            }\n        }\n    }\n\n    function styles() {\n        var i;\n        while (next_token.id === '@') {\n            i = peek();\n            advance('@');\n            switch (next_token.string) {\n            case 'import':\n                advance_identifier('import');\n                if (!css_url()) {\n                    warn('expected_a_b',\n                        next_token, 'url', artifact());\n                    advance();\n                }\n                semicolon();\n                break;\n            case 'media':\n                advance_identifier('media');\n                for (;;) {\n                    if (!next_token.identifier || css_media[next_token.string] !== true) {\n                        stop('expected_media_a');\n                    }\n                    advance();\n                    if (next_token.id !== ',') {\n                        break;\n                    }\n                    comma();\n                }\n                advance('{');\n                style_list();\n                advance('}');\n                break;\n            case 'font-face':\n                advance_identifier('font-face');\n                advance('{');\n                font_face();\n                advance('}');\n                break;\n            default:\n                stop('expected_at_a');\n            }\n        }\n        style_list();\n    }\n\n\n// Parse HTML\n\n    function do_begin(n) {\n        if (n !== 'html' && !option.fragment) {\n            if (n === 'div' && option.adsafe) {\n                stop('adsafe_fragment');\n            } else {\n                stop('expected_a_b', token, 'html', n);\n            }\n        }\n        if (option.adsafe) {\n            if (n === 'html') {\n                stop('adsafe_html', token);\n            }\n            if (option.fragment) {\n                if (n !== 'div') {\n                    stop('adsafe_div', token);\n                }\n            } else {\n                stop('adsafe_fragment', token);\n            }\n        }\n        option.browser = true;\n    }\n\n    function do_attribute(a, v) {\n        var u, x;\n        if (a === 'id') {\n            u = typeof v === 'string' ? v.toUpperCase() : '';\n            if (ids[u] === true) {\n                warn('duplicate_a', next_token, v);\n            }\n            if (!/^[A-Za-z][A-Za-z0-9._:\\-]*$/.test(v)) {\n                warn('bad_id_a', next_token, v);\n            } else if (option.adsafe) {\n                if (adsafe_id) {\n                    if (v.slice(0, adsafe_id.length) !== adsafe_id) {\n                        warn('adsafe_prefix_a', next_token, adsafe_id);\n                    } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {\n                        warn('adsafe_bad_id');\n                    }\n                } else {\n                    adsafe_id = v;\n                    if (!/^[A-Z]+_$/.test(v)) {\n                        warn('adsafe_bad_id');\n                    }\n                }\n            }\n            x = v.search(dx);\n            if (x >= 0) {\n                warn('unexpected_char_a_b', token, v.charAt(x), a);\n            }\n            ids[u] = true;\n        } else if (a === 'class' || a === 'type' || a === 'name') {\n            x = v.search(qx);\n            if (x >= 0) {\n                warn('unexpected_char_a_b', token, v.charAt(x), a);\n            }\n            ids[u] = true;\n        } else if (a === 'href' || a === 'background' ||\n                a === 'content' || a === 'data' ||\n                a.indexOf('src') >= 0 || a.indexOf('url') >= 0) {\n            if (option.safe && ux.test(v)) {\n                stop('bad_url_a', next_token, v);\n            }\n            urls.push(v);\n        } else if (a === 'for') {\n            if (option.adsafe) {\n                if (adsafe_id) {\n                    if (v.slice(0, adsafe_id.length) !== adsafe_id) {\n                        warn('adsafe_prefix_a', next_token, adsafe_id);\n                    } else if (!/^[A-Z]+_[A-Z]+$/.test(v)) {\n                        warn('adsafe_bad_id');\n                    }\n                } else {\n                    warn('adsafe_bad_id');\n                }\n            }\n        } else if (a === 'name') {\n            if (option.adsafe && v.indexOf('_') >= 0) {\n                warn('adsafe_name_a', next_token, v);\n            }\n        }\n    }\n\n    function do_tag(name, attribute) {\n        var i, tag = html_tag[name], script, x;\n        src = false;\n        if (!tag) {\n            stop(\n                bundle.unrecognized_tag_a,\n                next_token,\n                name === name.toLowerCase()\n                    ? name\n                    : name + ' (capitalization error)'\n            );\n        }\n        if (stack.length > 0) {\n            if (name === 'html') {\n                stop('unexpected_a', token, name);\n            }\n            x = tag.parent;\n            if (x) {\n                if (x.indexOf(' ' + stack[stack.length - 1].name + ' ') < 0) {\n                    stop('tag_a_in_b', token, name, x);\n                }\n            } else if (!option.adsafe && !option.fragment) {\n                i = stack.length;\n                do {\n                    if (i <= 0) {\n                        stop('tag_a_in_b', token, name, 'body');\n                    }\n                    i -= 1;\n                } while (stack[i].name !== 'body');\n            }\n        }\n        switch (name) {\n        case 'div':\n            if (option.adsafe && stack.length === 1 && !adsafe_id) {\n                warn('adsafe_missing_id');\n            }\n            break;\n        case 'script':\n            xmode = 'script';\n            advance('>');\n            if (attribute.lang) {\n                warn('lang', token);\n            }\n            if (option.adsafe && stack.length !== 1) {\n                warn('adsafe_placement', token);\n            }\n            if (attribute.src) {\n                if (option.adsafe && (!adsafe_may || !approved[attribute.src])) {\n                    warn('adsafe_source', token);\n                }\n            } else {\n                step_in(next_token.from);\n                edge();\n                use_strict();\n                adsafe_top = true;\n                script = statements();\n\n// JSLint is also the static analyzer for ADsafe. See www.ADsafe.org.\n\n                if (option.adsafe) {\n                    if (adsafe_went) {\n                        stop('adsafe_script', token);\n                    }\n                    if (script.length !== 1 ||\n                            aint(script[0],             'id',     '(') ||\n                            aint(script[0].first,       'id',     '.') ||\n                            aint(script[0].first.first, 'string', 'ADSAFE') ||\n                            aint(script[0].second[0],   'string', adsafe_id)) {\n                        stop('adsafe_id_go');\n                    }\n                    switch (script[0].first.second.string) {\n                    case 'id':\n                        if (adsafe_may || adsafe_went ||\n                                script[0].second.length !== 1) {\n                            stop('adsafe_id', next_token);\n                        }\n                        adsafe_may = true;\n                        break;\n                    case 'go':\n                        if (adsafe_went) {\n                            stop('adsafe_go');\n                        }\n                        if (script[0].second.length !== 2 ||\n                                aint(script[0].second[1], 'id', 'function') ||\n                                !script[0].second[1].first ||\n                                aint(script[0].second[1].first[0], 'string', 'dom') ||\n                                script[0].second[1].first.length > 2 ||\n                                (script[0].second[1].first.length === 2 &&\n                                aint(script[0].second[1].first[1], 'string', 'lib'))) {\n                            stop('adsafe_go', next_token);\n                        }\n                        adsafe_went = true;\n                        break;\n                    default:\n                        stop('adsafe_id_go');\n                    }\n                }\n                indent = null;\n            }\n            xmode = 'html';\n            advance('</');\n            advance_identifier('script');\n            xmode = 'outer';\n            break;\n        case 'style':\n            xmode = 'style';\n            advance('>');\n            styles();\n            xmode = 'html';\n            advance('</');\n            advance_identifier('style');\n            break;\n        case 'input':\n            switch (attribute.type) {\n            case 'button':\n            case 'checkbox':\n            case 'radio':\n            case 'reset':\n            case 'submit':\n                break;\n            case 'file':\n            case 'hidden':\n            case 'image':\n            case 'password':\n            case 'text':\n                if (option.adsafe && attribute.autocomplete !== 'off') {\n                    warn('adsafe_autocomplete');\n                }\n                break;\n            default:\n                warn('bad_type');\n            }\n            break;\n        case 'applet':\n        case 'body':\n        case 'embed':\n        case 'frame':\n        case 'frameset':\n        case 'head':\n        case 'iframe':\n        case 'noembed':\n        case 'noframes':\n        case 'object':\n        case 'param':\n            if (option.adsafe) {\n                warn('adsafe_tag', next_token, name);\n            }\n            break;\n        }\n    }\n\n\n    function closetag(name) {\n        return '</' + name + '>';\n    }\n\n    function html() {\n        var attribute, attributes, is_empty, name, old_white = option.white,\n            quote, tag_name, tag, wmode;\n        xmode = 'html';\n        xquote = '';\n        stack = null;\n        for (;;) {\n            switch (next_token.string) {\n            case '<':\n                xmode = 'html';\n                advance('<');\n                attributes = {};\n                tag_name = next_token;\n                name = tag_name.string;\n                advance_identifier(name);\n                if (option.cap) {\n                    name = name.toLowerCase();\n                }\n                tag_name.name = name;\n                if (!stack) {\n                    stack = [];\n                    do_begin(name);\n                }\n                tag = html_tag[name];\n                if (typeof tag !== 'object') {\n                    stop('unrecognized_tag_a', tag_name, name);\n                }\n                is_empty = tag.empty;\n                tag_name.type = name;\n                for (;;) {\n                    if (next_token.id === '/') {\n                        advance('/');\n                        if (next_token.id !== '>') {\n                            warn('expected_a_b', next_token, '>', artifact());\n                        }\n                        break;\n                    }\n                    if (next_token.id && next_token.id.charAt(0) === '>') {\n                        break;\n                    }\n                    if (!next_token.identifier) {\n                        if (next_token.id === '(end)' || next_token.id === '(error)') {\n                            warn('expected_a_b', next_token, '>', artifact());\n                        }\n                        warn('bad_name_a');\n                    }\n                    option.white = false;\n                    spaces();\n                    attribute = next_token.string;\n                    option.white = old_white;\n                    advance();\n                    if (!option.cap && attribute !== attribute.toLowerCase()) {\n                        warn('attribute_case_a', token);\n                    }\n                    attribute = attribute.toLowerCase();\n                    xquote = '';\n                    if (Object.prototype.hasOwnProperty.call(attributes, attribute)) {\n                        warn('duplicate_a', token, attribute);\n                    }\n                    if (attribute.slice(0, 2) === 'on') {\n                        if (!option.on) {\n                            warn('html_handlers');\n                        }\n                        xmode = 'scriptstring';\n                        advance('=');\n                        quote = next_token.id;\n                        if (quote !== '\"' && quote !== '\\'') {\n                            stop('expected_a_b', next_token, '\"', artifact());\n                        }\n                        xquote = quote;\n                        wmode = option.white;\n                        option.white = true;\n                        advance(quote);\n                        use_strict();\n                        statements();\n                        option.white = wmode;\n                        if (next_token.id !== quote) {\n                            stop('expected_a_b', next_token, quote, artifact());\n                        }\n                        xmode = 'html';\n                        xquote = '';\n                        advance(quote);\n                        tag = false;\n                    } else if (attribute === 'style') {\n                        xmode = 'scriptstring';\n                        advance('=');\n                        quote = next_token.id;\n                        if (quote !== '\"' && quote !== '\\'') {\n                            stop('expected_a_b', next_token, '\"', artifact());\n                        }\n                        xmode = 'styleproperty';\n                        xquote = quote;\n                        advance(quote);\n                        substyle();\n                        xmode = 'html';\n                        xquote = '';\n                        advance(quote);\n                        tag = false;\n                    } else {\n                        if (next_token.id === '=') {\n                            advance('=');\n                            tag = next_token.string;\n                            if (!next_token.identifier &&\n                                    next_token.id !== '\"' &&\n                                    next_token.id !== '\\'' &&\n                                    next_token.id !== '(string)' &&\n                                    next_token.id !== '(string)' &&\n                                    next_token.id !== '(color)') {\n                                warn('expected_attribute_value_a', token, attribute);\n                            }\n                            advance();\n                        } else {\n                            tag = true;\n                        }\n                    }\n                    attributes[attribute] = tag;\n                    do_attribute(attribute, tag);\n                }\n                do_tag(name, attributes);\n                if (!is_empty) {\n                    stack.push(tag_name);\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '</':\n                xmode = 'html';\n                advance('</');\n                if (!next_token.identifier) {\n                    warn('bad_name_a');\n                }\n                name = next_token.string;\n                if (option.cap) {\n                    name = name.toLowerCase();\n                }\n                advance();\n                if (!stack) {\n                    stop('unexpected_a', next_token, closetag(name));\n                }\n                tag_name = stack.pop();\n                if (!tag_name) {\n                    stop('unexpected_a', next_token, closetag(name));\n                }\n                if (tag_name.name !== name) {\n                    stop('expected_a_b',\n                        next_token, closetag(tag_name.name), closetag(name));\n                }\n                if (next_token.id !== '>') {\n                    stop('expected_a_b', next_token, '>', artifact());\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '<!':\n                if (option.safe) {\n                    warn('adsafe_a');\n                }\n                xmode = 'html';\n                for (;;) {\n                    advance();\n                    if (next_token.id === '>' || next_token.id === '(end)') {\n                        break;\n                    }\n                    if (next_token.string.indexOf('--') >= 0) {\n                        stop('unexpected_a', next_token, '--');\n                    }\n                    if (next_token.string.indexOf('<') >= 0) {\n                        stop('unexpected_a', next_token, '<');\n                    }\n                    if (next_token.string.indexOf('>') >= 0) {\n                        stop('unexpected_a', next_token, '>');\n                    }\n                }\n                xmode = 'outer';\n                advance('>');\n                break;\n            case '(end)':\n                if (stack.length !== 0) {\n                    warn('missing_a', next_token, '</' + stack.pop().string + '>');\n                }\n                return;\n            default:\n                if (next_token.id === '(end)') {\n                    stop('missing_a', next_token,\n                        '</' + stack[stack.length - 1].string + '>');\n                } else {\n                    advance();\n                }\n            }\n            if (stack && stack.length === 0 && (option.adsafe ||\n                    !option.fragment || next_token.id === '(end)')) {\n                break;\n            }\n        }\n        if (next_token.id !== '(end)') {\n            stop('unexpected_a');\n        }\n    }\n\n\n// The actual JSLINT function itself.\n\n    itself = function JSLint(the_source, the_option) {\n\n        var i, predef, tree;\n        JSLINT.errors = [];\n        JSLINT.tree = '';\n        begin = prev_token = token = next_token =\n            Object.create(syntax['(begin)']);\n        predefined = {};\n        add_to_predefined(standard);\n        property = {};\n        if (the_option) {\n            option = Object.create(the_option);\n            predef = option.predef;\n            if (predef) {\n                if (Array.isArray(predef)) {\n                    for (i = 0; i < predef.length; i += 1) {\n                        predefined[predef[i]] = true;\n                    }\n                } else if (typeof predef === 'object') {\n                    add_to_predefined(predef);\n                }\n            }\n            do_safe();\n        } else {\n            option = {};\n        }\n        option.indent = +option.indent || 4;\n        option.maxerr = +option.maxerr || 50;\n        adsafe_id = '';\n        adsafe_may = adsafe_top = adsafe_went = false;\n        approved = {};\n        if (option.approved) {\n            for (i = 0; i < option.approved.length; i += 1) {\n                approved[option.approved[i]] = option.approved[i];\n            }\n        } else {\n            approved.test = 'test';\n        }\n        tab = '';\n        for (i = 0; i < option.indent; i += 1) {\n            tab += ' ';\n        }\n        global_scope = scope = {};\n        global_funct = funct = {\n            '(scope)': scope,\n            '(breakage)': 0,\n            '(loopage)': 0\n        };\n        functions = [funct];\n\n        comments_off = false;\n        ids = {};\n        in_block = false;\n        indent = null;\n        json_mode = false;\n        lookahead = [];\n        node_js = false;\n        prereg = true;\n        src = false;\n        stack = null;\n        strict_mode = false;\n        urls = [];\n        var_mode = null;\n        warnings = 0;\n        xmode = '';\n        lex.init(the_source);\n\n        assume();\n\n        try {\n            advance();\n            if (next_token.id === '(number)') {\n                stop('unexpected_a');\n            } else if (next_token.string.charAt(0) === '<') {\n                html();\n                if (option.adsafe && !adsafe_went) {\n                    warn('adsafe_go', this);\n                }\n            } else {\n                switch (next_token.id) {\n                case '{':\n                case '[':\n                    json_mode = true;\n                    json_value();\n                    break;\n                case '@':\n                case '*':\n                case '#':\n                case '.':\n                case ':':\n                    xmode = 'style';\n                    advance();\n                    if (token.id !== '@' || !next_token.identifier ||\n                            next_token.string !== 'charset' || token.line !== 1 ||\n                            token.from !== 1) {\n                        stop('css');\n                    }\n                    advance();\n                    if (next_token.id !== '(string)' &&\n                            next_token.string !== 'UTF-8') {\n                        stop('css');\n                    }\n                    advance();\n                    semicolon();\n                    styles();\n                    break;\n\n                default:\n                    if (option.adsafe && option.fragment) {\n                        stop('expected_a_b',\n                            next_token, '<div>', artifact());\n                    }\n\n// If the first token is a semicolon, ignore it. This is sometimes used when\n// files are intended to be appended to files that may be sloppy. A sloppy\n// file may be depending on semicolon insertion on its last line.\n\n                    step_in(1);\n                    if (next_token.id === ';' && !node_js) {\n                        semicolon();\n                    }\n                    adsafe_top = true;\n                    tree = statements();\n                    begin.first = tree;\n                    JSLINT.tree = begin;\n                    // infer_types(tree);\n                    if (option.adsafe && (tree.length !== 1 ||\n                            aint(tree[0], 'id', '(') ||\n                            aint(tree[0].first, 'id', '.') ||\n                            aint(tree[0].first.first, 'string', 'ADSAFE') ||\n                            aint(tree[0].first.second, 'string', 'lib') ||\n                            tree[0].second.length !== 2 ||\n                            tree[0].second[0].id !== '(string)' ||\n                            aint(tree[0].second[1], 'id', 'function'))) {\n                        stop('adsafe_lib');\n                    }\n                    if (tree.disrupt) {\n                        warn('weird_program', prev_token);\n                    }\n                }\n            }\n            indent = null;\n            advance('(end)');\n        } catch (e) {\n            if (e) {        // ~~\n                JSLINT.errors.push({\n                    reason    : e.message,\n                    line      : e.line || next_token.line,\n                    character : e.character || next_token.from\n                }, null);\n            }\n        }\n        return JSLINT.errors.length === 0;\n    };\n\n\n// Data summary.\n\n    itself.data = function () {\n        var data = {functions: []},\n            function_data,\n            globals,\n            i,\n            j,\n            kind,\n            members = [],\n            name,\n            the_function,\n            undef = [],\n            unused = [];\n        if (itself.errors.length) {\n            data.errors = itself.errors;\n        }\n\n        if (json_mode) {\n            data.json = true;\n        }\n\n        if (urls.length > 0) {\n            data.urls = urls;\n        }\n\n        globals = Object.keys(global_scope).filter(function (value) {\n            return value.charAt(0) !== '(' && typeof standard[value] !== 'boolean';\n        });\n        if (globals.length > 0) {\n            data.globals = globals;\n        }\n\n        for (i = 1; i < functions.length; i += 1) {\n            the_function = functions[i];\n            function_data = {};\n            for (j = 0; j < functionicity.length; j += 1) {\n                function_data[functionicity[j]] = [];\n            }\n            for (name in the_function) {\n                if (Object.prototype.hasOwnProperty.call(the_function, name)) {\n                    if (name.charAt(0) !== '(') {\n                        kind = the_function[name];\n                        if (kind === 'unction' || kind === 'unparam') {\n                            kind = 'unused';\n                        }\n                        if (Array.isArray(function_data[kind])) {\n                            function_data[kind].push(name);\n                            if (kind === 'unused') {\n                                unused.push({\n                                    name: name,\n                                    line: the_function['(line)'],\n                                    'function': the_function['(name)']\n                                });\n                            } else if (kind === 'undef') {\n                                undef.push({\n                                    name: name,\n                                    line: the_function['(line)'],\n                                    'function': the_function['(name)']\n                                });\n                            }\n                        }\n                    }\n                }\n            }\n            for (j = 0; j < functionicity.length; j += 1) {\n                if (function_data[functionicity[j]].length === 0) {\n                    delete function_data[functionicity[j]];\n                }\n            }\n            function_data.name = the_function['(name)'];\n            function_data.params = the_function['(params)'];\n            function_data.line = the_function['(line)'];\n            data.functions.push(function_data);\n        }\n\n        if (unused.length > 0) {\n            data.unused = unused;\n        }\n        if (undef.length > 0) {\n            data['undefined'] = undef;\n        }\n\n        members = [];\n        for (name in property) {\n            if (typeof property[name] === 'number') {\n                data.member = property;\n                break;\n            }\n        }\n\n        return data;\n    };\n\n\n    itself.report = function (errors_only) {\n        var data = itself.data(), err, evidence, i, italics, j, key, keys,\n            length, mem = '', name, names, not_first, output = [], snippets,\n            the_function, warning;\n\n        function detail(h, value) {\n            var comma_needed, singularity;\n            if (Array.isArray(value)) {\n                output.push('<div><i>' + h + '</i> ');\n                value.sort().forEach(function (item) {\n                    if (item !== singularity) {\n                        singularity = item;\n                        output.push((comma_needed ? ', ' : '') + singularity);\n                        comma_needed = true;\n                    }\n                });\n                output.push('</div>');\n            } else if (value) {\n                output.push('<div><i>' + h + '</i> ' + value + '</div>');\n            }\n        }\n\n        if (data.errors || data.unused || data['undefined']) {\n            err = true;\n            output.push('<div id=errors><i>Error:</i>');\n            if (data.errors) {\n                for (i = 0; i < data.errors.length; i += 1) {\n                    warning = data.errors[i];\n                    if (warning) {\n                        evidence = warning.evidence || '';\n                        output.push('<p>Problem' + (isFinite(warning.line)\n                            ? ' at line ' + String(warning.line) +\n                                ' character ' + String(warning.character)\n                            : '') +\n                            ': ' + warning.reason.entityify() +\n                            '</p><p class=evidence>' +\n                            (evidence && (evidence.length > 80\n                                ? evidence.slice(0, 77) + '...'\n                                : evidence).entityify()) + '</p>');\n                    }\n                }\n            }\n\n            if (data['undefined']) {\n                snippets = [];\n                for (i = 0; i < data['undefined'].length; i += 1) {\n                    snippets[i] = '<code><u>' + data['undefined'][i].name + '</u></code>&nbsp;<i>' +\n                        String(data['undefined'][i].line) + ' </i> <small>' +\n                        data['undefined'][i]['function'] + '</small>';\n                }\n                output.push('<p><i>Undefined variable:</i> ' + snippets.join(', ') + '</p>');\n            }\n            if (data.unused) {\n                snippets = [];\n                for (i = 0; i < data.unused.length; i += 1) {\n                    snippets[i] = '<code><u>' + data.unused[i].name + '</u></code>&nbsp;<i>' +\n                        String(data.unused[i].line) + ' </i> <small>' +\n                        data.unused[i]['function'] + '</small>';\n                }\n                output.push('<p><i>Unused variable:</i> ' + snippets.join(', ') + '</p>');\n            }\n            if (data.json) {\n                output.push('<p>JSON: bad.</p>');\n            }\n            output.push('</div>');\n        }\n\n        if (!errors_only) {\n\n            output.push('<br><div id=functions>');\n\n            if (data.urls) {\n                detail(\"URLs<br>\", data.urls, '<br>');\n            }\n\n            if (xmode === 'style') {\n                output.push('<p>CSS.</p>');\n            } else if (data.json && !err) {\n                output.push('<p>JSON: good.</p>');\n            } else if (data.globals) {\n                output.push('<div><i>Global</i> ' +\n                    data.globals.sort().join(', ') + '</div>');\n            } else {\n                output.push('<div><i>No new global variables introduced.</i></div>');\n            }\n\n            for (i = 0; i < data.functions.length; i += 1) {\n                the_function = data.functions[i];\n                names = [];\n                if (the_function.params) {\n                    for (j = 0; j < the_function.params.length; j += 1) {\n                        names[j] = the_function.params[j].string;\n                    }\n                }\n                output.push('<br><div class=function><i>' +\n                    String(the_function.line) + '</i> ' +\n                    the_function.name.entityify() +\n                    '(' + names.join(', ') + ')</div>');\n                detail('<big><b>Undefined</b></big>', the_function['undefined']);\n                detail('<big><b>Unused</b></big>', the_function.unused);\n                detail('Closure', the_function.closure);\n                detail('Variable', the_function['var']);\n                detail('Exception', the_function.exception);\n                detail('Outer', the_function.outer);\n                detail('Global', the_function.global);\n                detail('Label', the_function.label);\n            }\n\n            if (data.member) {\n                keys = Object.keys(data.member);\n                if (keys.length) {\n                    keys = keys.sort();\n                    output.push('<br><pre id=properties>/*properties<br>');\n                    mem = '    ';\n                    italics = 0;\n                    j = 0;\n                    not_first = false;\n                    for (i = 0; i < keys.length; i += 1) {\n                        key = keys[i];\n                        if (data.member[key] > 0) {\n                            if (not_first) {\n                                mem += ', ';\n                            }\n                            name = ix.test(key)\n                                ? key\n                                : '\\'' + key.entityify().replace(nx, sanitize) + '\\'';\n                            length += name.length + 2;\n                            if (data.member[key] === 1) {\n                                name = '<i>' + name + '</i>';\n                                italics += 1;\n                                j = 1;\n                            }\n                            if (mem.length + name.length - (italics * 7) > 80) {\n                                output.push(mem + '<br>');\n                                mem = '    ';\n                                italics = j;\n                            }\n                            mem += name;\n                            j = 0;\n                            not_first = true;\n                        }\n                    }\n                    output.push(mem + '<br>*/</pre>');\n                }\n                output.push('</div>');\n            }\n        }\n        return output.join('');\n    };\n    itself.jslint = itself;\n\n    itself.edition = '2012-03-15';\n\n    return itself;\n}());\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/worker/mirror.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar Document = require(\"../document\").Document;\nvar lang = require(\"../lib/lang\");\n    \nvar Mirror = exports.Mirror = function(sender) {\n    this.sender = sender;\n    var doc = this.doc = new Document(\"\");\n    \n    var deferredUpdate = this.deferredUpdate = lang.deferredCall(this.onUpdate.bind(this));\n    \n    var _self = this;\n    sender.on(\"change\", function(e) {\n        doc.applyDeltas([e.data]);        \n        deferredUpdate.schedule(_self.$timeout);\n    });\n};\n\n(function() {\n    \n    this.$timeout = 500;\n    \n    this.setTimeout = function(timeout) {\n        this.$timeout = timeout;\n    };\n    \n    this.setValue = function(value) {\n        this.doc.setValue(value);\n        this.deferredUpdate.schedule(this.$timeout);\n    };\n    \n    this.getValue = function(callbackId) {\n        this.sender.callback(this.doc.getValue(), callbackId);\n    };\n    \n    this.onUpdate = function() {\n        // abstract method\n    };\n    \n}).call(Mirror.prototype);\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/worker/worker.js",
    "content": "\"no use strict\";\n\nvar console = {\n    log: function(msg) {\n        postMessage({type: \"log\", data: msg});\n    }\n};\nvar window = {\n    console: console\n};\n\nvar normalizeModule = function(parentId, moduleName) {\n    // normalize plugin requires\n    if (moduleName.indexOf(\"!\") !== -1) {\n        var chunks = moduleName.split(\"!\");\n        return normalizeModule(parentId, chunks[0]) + \"!\" + normalizeModule(parentId, chunks[1]);\n    }\n    // normalize relative requires\n    if (moduleName.charAt(0) == \".\") {\n        var base = parentId.split(\"/\").slice(0, -1).join(\"/\");\n        var moduleName = base + \"/\" + moduleName;\n        \n        while(moduleName.indexOf(\".\") !== -1 && previous != moduleName) {\n            var previous = moduleName;\n            var moduleName = moduleName.replace(/\\/\\.\\//, \"/\").replace(/[^\\/]+\\/\\.\\.\\//, \"\");\n        }\n    }\n    \n    return moduleName;\n};\n\nvar require = function(parentId, id) {\n    var id = normalizeModule(parentId, id);\n    \n    var module = require.modules[id];\n    if (module) {\n        if (!module.initialized) {\n            module.exports = module.factory().exports;\n            module.initialized = true;\n        }\n        return module.exports;\n    }\n    \n    var chunks = id.split(\"/\");\n    chunks[0] = require.tlns[chunks[0]] || chunks[0];\n    var path = chunks.join(\"/\") + \".js\";\n    \n    require.id = id;\n    importScripts(path);\n    return require(parentId, id);    \n};\n\nrequire.modules = {};\nrequire.tlns = {};\n\nvar define = function(id, deps, factory) {\n    if (arguments.length == 2) {\n        factory = deps;\n    } else if (arguments.length == 1) {\n        factory = id;\n        id = require.id;\n    }\n\n    if (id.indexOf(\"text!\") === 0) \n        return;\n    \n    var req = function(deps, factory) {\n        return require(id, deps, factory);\n    };\n\n    require.modules[id] = {\n        factory: function() {\n            var module = {\n                exports: {}\n            };\n            var returnExports = factory(req, module.exports, module);\n            if (returnExports)\n                module.exports = returnExports;\n            return module;\n        }\n    };\n};\n\nfunction initBaseUrls(topLevelNamespaces) {\n    require.tlns = topLevelNamespaces;\n}\n\nfunction initSender() {\n\n    var EventEmitter = require(null, \"ace/lib/event_emitter\").EventEmitter;\n    var oop = require(null, \"ace/lib/oop\");\n    \n    var Sender = function() {};\n    \n    (function() {\n        \n        oop.implement(this, EventEmitter);\n                \n        this.callback = function(data, callbackId) {\n            postMessage({\n                type: \"call\",\n                id: callbackId,\n                data: data\n            });\n        };\n    \n        this.emit = function(name, data) {\n            postMessage({\n                type: \"event\",\n                name: name,\n                data: data\n            });\n        };\n        \n    }).call(Sender.prototype);\n    \n    return new Sender();\n}\n\nvar main;\nvar sender;\n\nonmessage = function(e) {\n    var msg = e.data;\n    if (msg.command) {\n        main[msg.command].apply(main, msg.args);\n    }\n    else if (msg.init) {        \n        initBaseUrls(msg.tlns);\n        require(null, \"ace/lib/fixoldbrowsers\");\n        sender = initSender();\n        var clazz = require(null, msg.module)[msg.classname];\n        main = new clazz(sender);\n    } \n    else if (msg.event && sender) {\n        sender._emit(msg.event, msg.data);\n    }\n};\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/ace/worker/worker_client.js",
    "content": "/* ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n\"use strict\";\n\nvar oop = require(\"../lib/oop\");\nvar EventEmitter = require(\"../lib/event_emitter\").EventEmitter;\nvar config = require(\"../config\");\n\nvar WorkerClient = function(topLevelNamespaces, packagedJs, mod, classname) {\n\n    this.changeListener = this.changeListener.bind(this);\n\n    if (config.get(\"packaged\")) {\n        this.$worker = new Worker(config.get(\"workerPath\") + \"/\" + packagedJs);\n    }\n    else {\n        var workerUrl = this.$normalizePath(require.nameToUrl(\"ace/worker/worker\", null, \"_\"));\n        this.$worker = new Worker(workerUrl);\n\n        var tlns = {};\n        for (var i=0; i<topLevelNamespaces.length; i++) {\n            var ns = topLevelNamespaces[i];\n            var path = this.$normalizePath(require.nameToUrl(ns, null, \"_\").replace(/.js$/, \"\"));\n\n            tlns[ns] = path;\n        }\n    }\n\n    this.$worker.postMessage({\n        init : true,\n        tlns: tlns,\n        module: mod,\n        classname: classname\n    });\n\n    this.callbackId = 1;\n    this.callbacks = {};\n\n    var _self = this;\n    this.$worker.onerror = function(e) {\n        window.console && console.log && console.log(e);\n        throw e;\n    };\n    this.$worker.onmessage = function(e) {\n        var msg = e.data;\n        switch(msg.type) {\n            case \"log\":\n                window.console && console.log && console.log(msg.data);\n                break;\n\n            case \"event\":\n                _self._emit(msg.name, {data: msg.data});\n                break;\n\n            case \"call\":\n                var callback = _self.callbacks[msg.id];\n                if (callback) {\n                    callback(msg.data);\n                    delete _self.callbacks[msg.id];\n                }\n                break;\n        }\n    };\n};\n\n(function(){\n\n    oop.implement(this, EventEmitter);\n\n    this.$normalizePath = function(path) {\n        path = path.replace(/^[a-z]+:\\/\\/[^\\/]+/, \"\"); // Remove domain name and rebuild it\n        path = location.protocol + \"//\" + location.host\n            // paths starting with a slash are relative to the root (host)\n            + (path.charAt(0) == \"/\" ? \"\" : location.pathname.replace(/\\/[^\\/]*$/, \"\"))\n            + \"/\" + path.replace(/^[\\/]+/, \"\");\n        return path;\n    };\n\n    this.terminate = function() {\n        this._emit(\"terminate\", {});\n        this.$worker.terminate();\n        this.$worker = null;\n        this.$doc.removeEventListener(\"change\", this.changeListener);\n        this.$doc = null;\n    };\n\n    this.send = function(cmd, args) {\n        this.$worker.postMessage({command: cmd, args: args});\n    };\n\n    this.call = function(cmd, args, callback) {\n        if (callback) {\n            var id = this.callbackId++;\n            this.callbacks[id] = callback;\n            args.push(id);\n        }\n        this.send(cmd, args);\n    };\n\n    this.emit = function(event, data) {\n        try {\n            // firefox refuses to clone objects which have function properties\n            // TODO: cleanup event\n            this.$worker.postMessage({event: event, data: {data: data.data}});\n        }\n        catch(ex) {}\n    };\n\n    this.attachToDocument = function(doc) {\n        if(this.$doc)\n            this.terminate();\n\n        this.$doc = doc;\n        this.call(\"setValue\", [doc.getValue()]);\n        doc.on(\"change\", this.changeListener);\n    };\n\n    this.changeListener = function(e) {\n        e.range = {\n            start: e.data.range.start,\n            end: e.data.range.end\n        };\n        this.emit(\"change\", e);\n    };\n\n}).call(WorkerClient.prototype);\n\nexports.WorkerClient = WorkerClient;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/pilot/browser_focus.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n    console.warn(\"DEPRECATED: 'pilot/browser_focus' is deprecated. Use 'ace/lib/browser_focus' instead\");\n    module.exports = require(\"ace/lib/browser_focus\");\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/pilot/canon.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n    console.warn(\"DEPRECATED: 'pilot/canon' is deprecated.\");\n    //return require(\"ace/lib/dom\");\n    \n    exports.addCommand = function() {\n        console.warn(\"DEPRECATED: 'canon.addCommand()' is deprecated. Use 'editor.commands.addCommand(command)' instead.\");\n        console.trace();\n    }\n    \n    exports.removeCommand = function() {\n        console.warn(\"DEPRECATED: 'canon.removeCommand()' is deprecated. Use 'editor.commands.removeCommand(command)' instead.\");\n        console.trace();\n    }\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/pilot/dom.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n    console.warn(\"DEPRECATED: 'pilot/dom' is deprecated. Use 'ace/lib/dom' instead\");\n    module.exports = require(\"ace/lib/dom\");\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/pilot/event.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n    console.warn(\"DEPRECATED: 'pilot/event' is deprecated. Use 'ace/lib/event' instead\");\n    module.exports = require(\"ace/lib/event\");\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/pilot/event_emitter.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n    console.warn(\"DEPRECATED: 'pilot/event_emitter' is deprecated. Use 'ace/lib/event_emitter' instead\");\n    module.exports = require(\"ace/lib/event_emitter\");\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/pilot/fixoldbrowsers.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n    console.warn(\"DEPRECATED: 'pilot/fixoldbrowsers' is deprecated. Use 'ace/lib/fixoldbrowsers' instead\");\n    module.exports = require(\"ace/lib/fixoldbrowsers\");\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/pilot/index.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n    require(\"pilot/browser_focus\");\n    require(\"pilot/dom\");\n    require(\"pilot/event\");\n    require(\"pilot/event_emitter\");\n    require(\"pilot/fixoldbrowsers\");\n    require(\"pilot/keys\");\n    require(\"pilot/lang\");\n    require(\"pilot/oop\");\n    require(\"pilot/useragent\");\n    require(\"pilot/canon\");\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/pilot/keys.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n    console.warn(\"DEPRECATED: 'pilot/keys' is deprecated. Use 'ace/lib/keys' instead\");\n    module.exports = require(\"ace/lib/keys\");\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/pilot/lang.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n    console.warn(\"DEPRECATED: 'pilot/lang' is deprecated. Use 'ace/lib/lang' instead\");\n    module.exports = require(\"ace/lib/lang\");\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/pilot/oop.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n    console.warn(\"DEPRECATED: 'pilot/oop' is deprecated. Use 'ace/lib/oop' instead\");\n    module.exports = require(\"ace/lib/oop\");\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/lib/pilot/useragent.js",
    "content": "/* vim:ts=4:sts=4:sw=4:\n * ***** BEGIN LICENSE BLOCK *****\n * Version: MPL 1.1/GPL 2.0/LGPL 2.1\n *\n * The contents of this file are subject to the Mozilla Public License Version\n * 1.1 (the \"License\"); you may not use this file except in compliance with\n * the License. You may obtain a copy of the License at\n * http://www.mozilla.org/MPL/\n *\n * Software distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\n * for the specific language governing rights and limitations under the\n * License.\n *\n * The Original Code is Ajax.org Code Editor (ACE).\n *\n * The Initial Developer of the Original Code is\n * Ajax.org B.V.\n * Portions created by the Initial Developer are Copyright (C) 2010\n * the Initial Developer. All Rights Reserved.\n *\n * Contributor(s):\n *      Fabian Jakobs <fabian AT ajax DOT org>\n *\n * Alternatively, the contents of this file may be used under the terms of\n * either the GNU General Public License Version 2 or later (the \"GPL\"), or\n * the GNU Lesser General Public License Version 2.1 or later (the \"LGPL\"),\n * in which case the provisions of the GPL or the LGPL are applicable instead\n * of those above. If you wish to allow use of your version of this file only\n * under the terms of either the GPL or the LGPL, and not to allow others to\n * use your version of this file under the terms of the MPL, indicate your\n * decision by deleting the provisions above and replace them with the notice\n * and other provisions required by the GPL or the LGPL. If you do not delete\n * the provisions above, a recipient may use your version of this file under\n * the terms of any one of the MPL, the GPL or the LGPL.\n *\n * ***** END LICENSE BLOCK ***** */\n\ndefine(function(require, exports, module) {\n    console.warn(\"DEPRECATED: 'pilot/useragent' is deprecated. Use 'ace/lib/useragent' instead\");\n    module.exports = require(\"ace/lib/useragent\");\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/manifest.json",
    "content": "{\n  \"name\": \"Simple Text Editor\",\n  \"description\": \"Syntax highlighting text editor\",\n  \"version\": \"0.21\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"23\",\n  \"icons\": {\n    \"16\": \"icons/texteditor_16.png\",\n    \"24\": \"icons/texteditor_24.png\",\n    \"48\": \"icons/texteditor_48.png\",\n    \"128\": \"icons/texteditor_128.png\"\n  },\n  \"permissions\": [\n    \"clipboardRead\",\n    \"clipboardWrite\",\n    {\"fileSystem\": [\"write\"]}\n  ],\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/modes.js",
    "content": "define(function(require, exports, module) {\n\"use strict\";\n\nvar Mode = function(name, desc, extensions) {\n    this.desc = desc;\n    this.mode = \"ace/mode/\" + name;\n    this.extRe = new RegExp(\"^.*\\\\.(\" + extensions.join(\"|\") + \")$\", \"g\");\n};\n\nMode.prototype.supportsFile = function(filename) {\n    return filename.match(this.extRe);\n};\n\nvar modes = [\n    new Mode(\"c_cpp\", \"C/C++\", [\"c\", \"cpp\", \"cc\", \"cxx\", \"h\", \"hpp\"]),\n    new Mode(\"clojure\", \"Clojure\", [\"clj\"]),\n    new Mode(\"coffee\", \"CoffeeScript\", [\"coffee\"]),\n    new Mode(\"coldfusion\", \"ColdFusion\", [\"cfm\"]),\n    new Mode(\"csharp\", \"C#\", [\"cs\"]),\n    new Mode(\"css\", \"CSS\", [\"css\"]),\n    new Mode(\"golang\", \"Go\", [\"go\"]),\n    new Mode(\"groovy\", \"Groovy\", [\"groovy\"]),\n    new Mode(\"haxe\", \"haXe\", [\"hx\"]),\n    new Mode(\"html\", \"HTML\", [\"html\", \"htm\"]),\n    new Mode(\"java\", \"Java\", [\"java\"]),\n    new Mode(\"javascript\", \"JavaScript\", [\"js\"]),\n    new Mode(\"json\", \"JSON\", [\"json\"]),\n    new Mode(\"latex\", \"LaTeX\", [\"tex\"]),\n    new Mode(\"less\", \"LESS\", [\"less\"]),\n    new Mode(\"lua\", \"Lua\", [\"lua\"]),\n    new Mode(\"liquid\", \"Liquid\", [\"liquid\"]),\n    new Mode(\"markdown\", \"Markdown\", [\"md\", \"markdown\"]),\n    new Mode(\"ocaml\", \"OCaml\", [\"ml\", \"mli\"]),\n    new Mode(\"perl\", \"Perl\", [\"pl\", \"pm\"]),\n    new Mode(\"pgsql\", \"pgSQL\", [\"pgsql\", \"sql\"]),\n    new Mode(\"php\", \"PHP\", [\"php\"]),\n    new Mode(\"powershell\", \"Powershell\", [\"ps1\"]),\n    new Mode(\"python\", \"Python\", [\"py\"]),\n    new Mode(\"scala\", \"Scala\", [\"scala\"]),\n    new Mode(\"scss\", \"SCSS\", [\"scss\"]),\n    new Mode(\"ruby\", \"Ruby\", [\"rb\"]),\n    new Mode(\"sql\", \"SQL\", [\"sql\"]),\n    new Mode(\"svg\", \"SVG\", [\"svg\"]),\n    new Mode(\"text\", \"Text\", [\"txt\"]),\n    new Mode(\"textile\", \"Textile\", [\"textile\"]),\n    new Mode(\"xml\", \"XML\", [\"xml\"]),\n    new Mode(\"sh\", \"SH\", [\"sh\"]),\n    new Mode(\"xquery\", \"XQuery\", [\"xq\"])\n];\n\nfunction getModeFromBaseName(aBaseName) {\n  var mode = null;\n  for (var i = 0; i < modes.length; i++) {\n    if (modes[i].supportsFile(aBaseName)) {\n      mode = modes[i];\n      break;\n    }\n  }\n  return mode;\n}\n\nexports.getModeFromBaseName = getModeFromBaseName;\n\n});\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/require.js",
    "content": "/** vim: et:ts=4:sw=4:sts=4\n * @license RequireJS 1.0.3 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/jrburke/requirejs for details\n */\n/*jslint strict: false, plusplus: false, sub: true */\n/*global window: false, navigator: false, document: false, importScripts: false,\n  jQuery: false, clearInterval: false, setInterval: false, self: false,\n  setTimeout: false, opera: false */\n\nvar requirejs, require, define;\n(function () {\n    //Change this version number for each release.\n    var version = \"1.0.3\",\n        commentRegExp = /(\\/\\*([\\s\\S]*?)\\*\\/|([^:]|^)\\/\\/(.*)$)/mg,\n        cjsRequireRegExp = /require\\(\\s*[\"']([^'\"\\s]+)[\"']\\s*\\)/g,\n        currDirRegExp = /^\\.\\//,\n        jsSuffixRegExp = /\\.js$/,\n        ostring = Object.prototype.toString,\n        ap = Array.prototype,\n        aps = ap.slice,\n        apsp = ap.splice,\n        isBrowser = !!(typeof window !== \"undefined\" && navigator && document),\n        isWebWorker = !isBrowser && typeof importScripts !== \"undefined\",\n        //PS3 indicates loaded and complete, but need to wait for complete\n        //specifically. Sequence is \"loading\", \"loaded\", execution,\n        // then \"complete\". The UA check is unfortunate, but not sure how\n        //to feature test w/o causing perf issues.\n        readyRegExp = isBrowser && navigator.platform === 'PLAYSTATION 3' ?\n                      /^complete$/ : /^(complete|loaded)$/,\n        defContextName = \"_\",\n        //Oh the tragedy, detecting opera. See the usage of isOpera for reason.\n        isOpera = typeof opera !== \"undefined\" && opera.toString() === \"[object Opera]\",\n        empty = {},\n        contexts = {},\n        globalDefQueue = [],\n        interactiveScript = null,\n        checkLoadedDepth = 0,\n        useInteractive = false,\n        req, cfg = {}, currentlyAddingScript, s, head, baseElement, scripts, script,\n        src, subPath, mainScript, dataMain, i, ctx, jQueryCheck, checkLoadedTimeoutId;\n\n    function isFunction(it) {\n        return ostring.call(it) === \"[object Function]\";\n    }\n\n    function isArray(it) {\n        return ostring.call(it) === \"[object Array]\";\n    }\n\n    /**\n     * Simple function to mix in properties from source into target,\n     * but only if target does not already have a property of the same name.\n     * This is not robust in IE for transferring methods that match\n     * Object.prototype names, but the uses of mixin here seem unlikely to\n     * trigger a problem related to that.\n     */\n    function mixin(target, source, force) {\n        for (var prop in source) {\n            if (!(prop in empty) && (!(prop in target) || force)) {\n                target[prop] = source[prop];\n            }\n        }\n        return req;\n    }\n\n    /**\n     * Constructs an error with a pointer to an URL with more information.\n     * @param {String} id the error ID that maps to an ID on a web page.\n     * @param {String} message human readable error.\n     * @param {Error} [err] the original error, if there is one.\n     *\n     * @returns {Error}\n     */\n    function makeError(id, msg, err) {\n        var e = new Error(msg + '\\nhttp://requirejs.org/docs/errors.html#' + id);\n        if (err) {\n            e.originalError = err;\n        }\n        return e;\n    }\n\n    /**\n     * Used to set up package paths from a packagePaths or packages config object.\n     * @param {Object} pkgs the object to store the new package config\n     * @param {Array} currentPackages an array of packages to configure\n     * @param {String} [dir] a prefix dir to use.\n     */\n    function configurePackageDir(pkgs, currentPackages, dir) {\n        var i, location, pkgObj;\n\n        for (i = 0; (pkgObj = currentPackages[i]); i++) {\n            pkgObj = typeof pkgObj === \"string\" ? { name: pkgObj } : pkgObj;\n            location = pkgObj.location;\n\n            //Add dir to the path, but avoid paths that start with a slash\n            //or have a colon (indicates a protocol)\n            if (dir && (!location || (location.indexOf(\"/\") !== 0 && location.indexOf(\":\") === -1))) {\n                location = dir + \"/\" + (location || pkgObj.name);\n            }\n\n            //Create a brand new object on pkgs, since currentPackages can\n            //be passed in again, and config.pkgs is the internal transformed\n            //state for all package configs.\n            pkgs[pkgObj.name] = {\n                name: pkgObj.name,\n                location: location || pkgObj.name,\n                //Remove leading dot in main, so main paths are normalized,\n                //and remove any trailing .js, since different package\n                //envs have different conventions: some use a module name,\n                //some use a file name.\n                main: (pkgObj.main || \"main\")\n                      .replace(currDirRegExp, '')\n                      .replace(jsSuffixRegExp, '')\n            };\n        }\n    }\n\n    /**\n     * jQuery 1.4.3-1.5.x use a readyWait/ready() pairing to hold DOM\n     * ready callbacks, but jQuery 1.6 supports a holdReady() API instead.\n     * At some point remove the readyWait/ready() support and just stick\n     * with using holdReady.\n     */\n    function jQueryHoldReady($, shouldHold) {\n        if ($.holdReady) {\n            $.holdReady(shouldHold);\n        } else if (shouldHold) {\n            $.readyWait += 1;\n        } else {\n            $.ready(true);\n        }\n    }\n\n    if (typeof define !== \"undefined\") {\n        //If a define is already in play via another AMD loader,\n        //do not overwrite.\n        return;\n    }\n\n    if (typeof requirejs !== \"undefined\") {\n        if (isFunction(requirejs)) {\n            //Do not overwrite and existing requirejs instance.\n            return;\n        } else {\n            cfg = requirejs;\n            requirejs = undefined;\n        }\n    }\n\n    //Allow for a require config object\n    if (typeof require !== \"undefined\" && !isFunction(require)) {\n        //assume it is a config object.\n        cfg = require;\n        require = undefined;\n    }\n\n    /**\n     * Creates a new context for use in require and define calls.\n     * Handle most of the heavy lifting. Do not want to use an object\n     * with prototype here to avoid using \"this\" in require, in case it\n     * needs to be used in more super secure envs that do not want this.\n     * Also there should not be that many contexts in the page. Usually just\n     * one for the default context, but could be extra for multiversion cases\n     * or if a package needs a special context for a dependency that conflicts\n     * with the standard context.\n     */\n    function newContext(contextName) {\n        var context, resume,\n            config = {\n                waitSeconds: 7,\n                baseUrl: \"./\",\n                paths: {},\n                pkgs: {},\n                catchError: {}\n            },\n            defQueue = [],\n            specified = {\n                \"require\": true,\n                \"exports\": true,\n                \"module\": true\n            },\n            urlMap = {},\n            defined = {},\n            loaded = {},\n            waiting = {},\n            waitAry = [],\n            urlFetched = {},\n            managerCounter = 0,\n            managerCallbacks = {},\n            plugins = {},\n            //Used to indicate which modules in a build scenario\n            //need to be full executed.\n            needFullExec = {},\n            fullExec = {},\n            resumeDepth = 0;\n\n        /**\n         * Trims the . and .. from an array of path segments.\n         * It will keep a leading path segment if a .. will become\n         * the first path segment, to help with module name lookups,\n         * which act like paths, but can be remapped. But the end result,\n         * all paths that use this function should look normalized.\n         * NOTE: this method MODIFIES the input array.\n         * @param {Array} ary the array of path segments.\n         */\n        function trimDots(ary) {\n            var i, part;\n            for (i = 0; (part = ary[i]); i++) {\n                if (part === \".\") {\n                    ary.splice(i, 1);\n                    i -= 1;\n                } else if (part === \"..\") {\n                    if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {\n                        //End of the line. Keep at least one non-dot\n                        //path segment at the front so it can be mapped\n                        //correctly to disk. Otherwise, there is likely\n                        //no path mapping for a path starting with '..'.\n                        //This can still fail, but catches the most reasonable\n                        //uses of ..\n                        break;\n                    } else if (i > 0) {\n                        ary.splice(i - 1, 2);\n                        i -= 2;\n                    }\n                }\n            }\n        }\n\n        /**\n         * Given a relative module name, like ./something, normalize it to\n         * a real name that can be mapped to a path.\n         * @param {String} name the relative name\n         * @param {String} baseName a real name that the name arg is relative\n         * to.\n         * @returns {String} normalized name\n         */\n        function normalize(name, baseName) {\n            var pkgName, pkgConfig;\n\n            //Adjust any relative paths.\n            if (name && name.charAt(0) === \".\") {\n                //If have a base name, try to normalize against it,\n                //otherwise, assume it is a top-level require that will\n                //be relative to baseUrl in the end.\n                if (baseName) {\n                    if (config.pkgs[baseName]) {\n                        //If the baseName is a package name, then just treat it as one\n                        //name to concat the name with.\n                        baseName = [baseName];\n                    } else {\n                        //Convert baseName to array, and lop off the last part,\n                        //so that . matches that \"directory\" and not name of the baseName's\n                        //module. For instance, baseName of \"one/two/three\", maps to\n                        //\"one/two/three.js\", but we want the directory, \"one/two\" for\n                        //this normalization.\n                        baseName = baseName.split(\"/\");\n                        baseName = baseName.slice(0, baseName.length - 1);\n                    }\n\n                    name = baseName.concat(name.split(\"/\"));\n                    trimDots(name);\n\n                    //Some use of packages may use a . path to reference the\n                    //\"main\" module name, so normalize for that.\n                    pkgConfig = config.pkgs[(pkgName = name[0])];\n                    name = name.join(\"/\");\n                    if (pkgConfig && name === pkgName + '/' + pkgConfig.main) {\n                        name = pkgName;\n                    }\n                } else if (name.indexOf(\"./\") === 0) {\n                    // No baseName, so this is ID is resolved relative\n                    // to baseUrl, pull off the leading dot.\n                    name = name.substring(2);\n                }\n            }\n            return name;\n        }\n\n        /**\n         * Creates a module mapping that includes plugin prefix, module\n         * name, and path. If parentModuleMap is provided it will\n         * also normalize the name via require.normalize()\n         *\n         * @param {String} name the module name\n         * @param {String} [parentModuleMap] parent module map\n         * for the module name, used to resolve relative names.\n         *\n         * @returns {Object}\n         */\n        function makeModuleMap(name, parentModuleMap) {\n            var index = name ? name.indexOf(\"!\") : -1,\n                prefix = null,\n                parentName = parentModuleMap ? parentModuleMap.name : null,\n                originalName = name,\n                normalizedName, url, pluginModule;\n\n            if (index !== -1) {\n                prefix = name.substring(0, index);\n                name = name.substring(index + 1, name.length);\n            }\n\n            if (prefix) {\n                prefix = normalize(prefix, parentName);\n            }\n\n            //Account for relative paths if there is a base name.\n            if (name) {\n                if (prefix) {\n                    pluginModule = defined[prefix];\n                    if (pluginModule && pluginModule.normalize) {\n                        //Plugin is loaded, use its normalize method.\n                        normalizedName = pluginModule.normalize(name, function (name) {\n                            return normalize(name, parentName);\n                        });\n                    } else {\n                        normalizedName = normalize(name, parentName);\n                    }\n                } else {\n                    //A regular module.\n                    normalizedName = normalize(name, parentName);\n\n                    url = urlMap[normalizedName];\n                    if (!url) {\n                        //Calculate url for the module, if it has a name.\n                        url = context.nameToUrl(normalizedName, null, parentModuleMap);\n\n                        //Store the URL mapping for later.\n                        urlMap[normalizedName] = url;\n                    }\n                }\n            }\n\n            return {\n                prefix: prefix,\n                name: normalizedName,\n                parentMap: parentModuleMap,\n                url: url,\n                originalName: originalName,\n                fullName: prefix ? prefix + \"!\" + (normalizedName || '') : normalizedName\n            };\n        }\n\n        /**\n         * Determine if priority loading is done. If so clear the priorityWait\n         */\n        function isPriorityDone() {\n            var priorityDone = true,\n                priorityWait = config.priorityWait,\n                priorityName, i;\n            if (priorityWait) {\n                for (i = 0; (priorityName = priorityWait[i]); i++) {\n                    if (!loaded[priorityName]) {\n                        priorityDone = false;\n                        break;\n                    }\n                }\n                if (priorityDone) {\n                    delete config.priorityWait;\n                }\n            }\n            return priorityDone;\n        }\n\n        function makeContextModuleFunc(func, relModuleMap, enableBuildCallback) {\n            return function () {\n                //A version of a require function that passes a moduleName\n                //value for items that may need to\n                //look up paths relative to the moduleName\n                var args = aps.call(arguments, 0), lastArg;\n                if (enableBuildCallback &&\n                    isFunction((lastArg = args[args.length - 1]))) {\n                    lastArg.__requireJsBuild = true;\n                }\n                args.push(relModuleMap);\n                return func.apply(null, args);\n            };\n        }\n\n        /**\n         * Helper function that creates a require function object to give to\n         * modules that ask for it as a dependency. It needs to be specific\n         * per module because of the implication of path mappings that may\n         * need to be relative to the module name.\n         */\n        function makeRequire(relModuleMap, enableBuildCallback) {\n            var modRequire = makeContextModuleFunc(context.require, relModuleMap, enableBuildCallback);\n\n            mixin(modRequire, {\n                nameToUrl: makeContextModuleFunc(context.nameToUrl, relModuleMap),\n                toUrl: makeContextModuleFunc(context.toUrl, relModuleMap),\n                defined: makeContextModuleFunc(context.requireDefined, relModuleMap),\n                specified: makeContextModuleFunc(context.requireSpecified, relModuleMap),\n                isBrowser: req.isBrowser\n            });\n            return modRequire;\n        }\n\n        /*\n         * Queues a dependency for checking after the loader is out of a\n         * \"paused\" state, for example while a script file is being loaded\n         * in the browser, where it may have many modules defined in it.\n         */\n        function queueDependency(manager) {\n            context.paused.push(manager);\n        }\n\n        function execManager(manager) {\n            var i, ret, err, errFile, errModuleTree,\n                cb = manager.callback,\n                map = manager.map,\n                fullName = map.fullName,\n                args = manager.deps,\n                listeners = manager.listeners,\n                cjsModule;\n\n            //Call the callback to define the module, if necessary.\n            if (cb && isFunction(cb)) {\n                if (config.catchError.define) {\n                    try {\n                        ret = req.execCb(fullName, manager.callback, args, defined[fullName]);\n                    } catch (e) {\n                        err = e;\n                    }\n                } else {\n                    ret = req.execCb(fullName, manager.callback, args, defined[fullName]);\n                }\n\n                if (fullName) {\n                    //If setting exports via \"module\" is in play,\n                    //favor that over return value and exports. After that,\n                    //favor a non-undefined return value over exports use.\n                    cjsModule = manager.cjsModule;\n                    if (cjsModule &&\n                        cjsModule.exports !== undefined &&\n                        //Make sure it is not already the exports value\n                        cjsModule.exports !== defined[fullName]) {\n                        ret = defined[fullName] = manager.cjsModule.exports;\n                    } else if (ret === undefined && manager.usingExports) {\n                        //exports already set the defined value.\n                        ret = defined[fullName];\n                    } else {\n                        //Use the return value from the function.\n                        defined[fullName] = ret;\n                        //If this module needed full execution in a build\n                        //environment, mark that now.\n                        if (needFullExec[fullName]) {\n                            fullExec[fullName] = true;\n                        }\n                    }\n                }\n            } else if (fullName) {\n                //May just be an object definition for the module. Only\n                //worry about defining if have a module name.\n                ret = defined[fullName] = cb;\n\n                //If this module needed full execution in a build\n                //environment, mark that now.\n                if (needFullExec[fullName]) {\n                    fullExec[fullName] = true;\n                }\n            }\n\n            //Clean up waiting. Do this before error calls, and before\n            //calling back listeners, so that bookkeeping is correct\n            //in the event of an error and error is reported in correct order,\n            //since the listeners will likely have errors if the\n            //onError function does not throw.\n            if (waiting[manager.id]) {\n                delete waiting[manager.id];\n                manager.isDone = true;\n                context.waitCount -= 1;\n                if (context.waitCount === 0) {\n                    //Clear the wait array used for cycles.\n                    waitAry = [];\n                }\n            }\n\n            //Do not need to track manager callback now that it is defined.\n            delete managerCallbacks[fullName];\n\n            //Allow instrumentation like the optimizer to know the order\n            //of modules executed and their dependencies.\n            if (req.onResourceLoad && !manager.placeholder) {\n                req.onResourceLoad(context, map, manager.depArray);\n            }\n\n            if (err) {\n                errFile = (fullName ? makeModuleMap(fullName).url : '') ||\n                           err.fileName || err.sourceURL;\n                errModuleTree = err.moduleTree;\n                err = makeError('defineerror', 'Error evaluating ' +\n                                'module \"' + fullName + '\" at location \"' +\n                                errFile + '\":\\n' +\n                                err + '\\nfileName:' + errFile +\n                                '\\nlineNumber: ' + (err.lineNumber || err.line), err);\n                err.moduleName = fullName;\n                err.moduleTree = errModuleTree;\n                return req.onError(err);\n            }\n\n            //Let listeners know of this manager's value.\n            for (i = 0; (cb = listeners[i]); i++) {\n                cb(ret);\n            }\n\n            return undefined;\n        }\n\n        /**\n         * Helper that creates a callack function that is called when a dependency\n         * is ready, and sets the i-th dependency for the manager as the\n         * value passed to the callback generated by this function.\n         */\n        function makeArgCallback(manager, i) {\n            return function (value) {\n                //Only do the work if it has not been done\n                //already for a dependency. Cycle breaking\n                //logic in forceExec could mean this function\n                //is called more than once for a given dependency.\n                if (!manager.depDone[i]) {\n                    manager.depDone[i] = true;\n                    manager.deps[i] = value;\n                    manager.depCount -= 1;\n                    if (!manager.depCount) {\n                        //All done, execute!\n                        execManager(manager);\n                    }\n                }\n            };\n        }\n\n        function callPlugin(pluginName, depManager) {\n            var map = depManager.map,\n                fullName = map.fullName,\n                name = map.name,\n                plugin = plugins[pluginName] ||\n                        (plugins[pluginName] = defined[pluginName]),\n                load;\n\n            //No need to continue if the manager is already\n            //in the process of loading.\n            if (depManager.loading) {\n                return;\n            }\n            depManager.loading = true;\n\n            load = function (ret) {\n                depManager.callback = function () {\n                    return ret;\n                };\n                execManager(depManager);\n\n                loaded[depManager.id] = true;\n\n                //The loading of this plugin\n                //might have placed other things\n                //in the paused queue. In particular,\n                //a loader plugin that depends on\n                //a different plugin loaded resource.\n                resume();\n            };\n\n            //Allow plugins to load other code without having to know the\n            //context or how to \"complete\" the load.\n            load.fromText = function (moduleName, text) {\n                /*jslint evil: true */\n                var hasInteractive = useInteractive;\n\n                //Indicate a the module is in process of loading.\n                loaded[moduleName] = false;\n                context.scriptCount += 1;\n\n                //Indicate this is not a \"real\" module, so do not track it\n                //for builds, it does not map to a real file.\n                context.fake[moduleName] = true;\n\n                //Turn off interactive script matching for IE for any define\n                //calls in the text, then turn it back on at the end.\n                if (hasInteractive) {\n                    useInteractive = false;\n                }\n\n                req.exec(text);\n\n                if (hasInteractive) {\n                    useInteractive = true;\n                }\n\n                //Support anonymous modules.\n                context.completeLoad(moduleName);\n            };\n\n            //No need to continue if the plugin value has already been\n            //defined by a build.\n            if (fullName in defined) {\n                load(defined[fullName]);\n            } else {\n                //Use parentName here since the plugin's name is not reliable,\n                //could be some weird string with no path that actually wants to\n                //reference the parentName's path.\n                plugin.load(name, makeRequire(map.parentMap, true), load, config);\n            }\n        }\n\n        /**\n         * Adds the manager to the waiting queue. Only fully\n         * resolved items should be in the waiting queue.\n         */\n        function addWait(manager) {\n            if (!waiting[manager.id]) {\n                waiting[manager.id] = manager;\n                waitAry.push(manager);\n                context.waitCount += 1;\n            }\n        }\n\n        /**\n         * Function added to every manager object. Created out here\n         * to avoid new function creation for each manager instance.\n         */\n        function managerAdd(cb) {\n            this.listeners.push(cb);\n        }\n\n        function getManager(map, shouldQueue) {\n            var fullName = map.fullName,\n                prefix = map.prefix,\n                plugin = prefix ? plugins[prefix] ||\n                                (plugins[prefix] = defined[prefix]) : null,\n                manager, created, pluginManager;\n\n            if (fullName) {\n                manager = managerCallbacks[fullName];\n            }\n\n            if (!manager) {\n                created = true;\n                manager = {\n                    //ID is just the full name, but if it is a plugin resource\n                    //for a plugin that has not been loaded,\n                    //then add an ID counter to it.\n                    id: (prefix && !plugin ?\n                        (managerCounter++) + '__p@:' : '') +\n                        (fullName || '__r@' + (managerCounter++)),\n                    map: map,\n                    depCount: 0,\n                    depDone: [],\n                    depCallbacks: [],\n                    deps: [],\n                    listeners: [],\n                    add: managerAdd\n                };\n\n                specified[manager.id] = true;\n\n                //Only track the manager/reuse it if this is a non-plugin\n                //resource. Also only track plugin resources once\n                //the plugin has been loaded, and so the fullName is the\n                //true normalized value.\n                if (fullName && (!prefix || plugins[prefix])) {\n                    managerCallbacks[fullName] = manager;\n                }\n            }\n\n            //If there is a plugin needed, but it is not loaded,\n            //first load the plugin, then continue on.\n            if (prefix && !plugin) {\n                pluginManager = getManager(makeModuleMap(prefix), true);\n                pluginManager.add(function (plugin) {\n                    //Create a new manager for the normalized\n                    //resource ID and have it call this manager when\n                    //done.\n                    var newMap = makeModuleMap(map.originalName, map.parentMap),\n                        normalizedManager = getManager(newMap, true);\n\n                    //Indicate this manager is a placeholder for the real,\n                    //normalized thing. Important for when trying to map\n                    //modules and dependencies, for instance, in a build.\n                    manager.placeholder = true;\n\n                    normalizedManager.add(function (resource) {\n                        manager.callback = function () {\n                            return resource;\n                        };\n                        execManager(manager);\n                    });\n                });\n            } else if (created && shouldQueue) {\n                //Indicate the resource is not loaded yet if it is to be\n                //queued.\n                loaded[manager.id] = false;\n                queueDependency(manager);\n                addWait(manager);\n            }\n\n            return manager;\n        }\n\n        function main(inName, depArray, callback, relModuleMap) {\n            var moduleMap = makeModuleMap(inName, relModuleMap),\n                name = moduleMap.name,\n                fullName = moduleMap.fullName,\n                manager = getManager(moduleMap),\n                id = manager.id,\n                deps = manager.deps,\n                i, depArg, depName, depPrefix, cjsMod;\n\n            if (fullName) {\n                //If module already defined for context, or already loaded,\n                //then leave. Also leave if jQuery is registering but it does\n                //not match the desired version number in the config.\n                if (fullName in defined || loaded[id] === true ||\n                    (fullName === \"jquery\" && config.jQuery &&\n                     config.jQuery !== callback().fn.jquery)) {\n                    return;\n                }\n\n                //Set specified/loaded here for modules that are also loaded\n                //as part of a layer, where onScriptLoad is not fired\n                //for those cases. Do this after the inline define and\n                //dependency tracing is done.\n                specified[id] = true;\n                loaded[id] = true;\n\n                //If module is jQuery set up delaying its dom ready listeners.\n                if (fullName === \"jquery\" && callback) {\n                    jQueryCheck(callback());\n                }\n            }\n\n            //Attach real depArray and callback to the manager. Do this\n            //only if the module has not been defined already, so do this after\n            //the fullName checks above. IE can call main() more than once\n            //for a module.\n            manager.depArray = depArray;\n            manager.callback = callback;\n\n            //Add the dependencies to the deps field, and register for callbacks\n            //on the dependencies.\n            for (i = 0; i < depArray.length; i++) {\n                depArg = depArray[i];\n                //There could be cases like in IE, where a trailing comma will\n                //introduce a null dependency, so only treat a real dependency\n                //value as a dependency.\n                if (depArg) {\n                    //Split the dependency name into plugin and name parts\n                    depArg = makeModuleMap(depArg, (name ? moduleMap : relModuleMap));\n                    depName = depArg.fullName;\n                    depPrefix = depArg.prefix;\n\n                    //Fix the name in depArray to be just the name, since\n                    //that is how it will be called back later.\n                    depArray[i] = depName;\n\n                    //Fast path CommonJS standard dependencies.\n                    if (depName === \"require\") {\n                        deps[i] = makeRequire(moduleMap);\n                    } else if (depName === \"exports\") {\n                        //CommonJS module spec 1.1\n                        deps[i] = defined[fullName] = {};\n                        manager.usingExports = true;\n                    } else if (depName === \"module\") {\n                        //CommonJS module spec 1.1\n                        manager.cjsModule = cjsMod = deps[i] = {\n                            id: name,\n                            uri: name ? context.nameToUrl(name, null, relModuleMap) : undefined,\n                            exports: defined[fullName]\n                        };\n                    } else if (depName in defined && !(depName in waiting) &&\n                               (!(fullName in needFullExec) ||\n                                (fullName in needFullExec && fullExec[depName]))) {\n                        //Module already defined, and not in a build situation\n                        //where the module is a something that needs full\n                        //execution and this dependency has not been fully\n                        //executed. See r.js's requirePatch.js for more info\n                        //on fullExec.\n                        deps[i] = defined[depName];\n                    } else {\n                        //Mark this dependency as needing full exec if\n                        //the current module needs full exec.\n                        if (fullName in needFullExec) {\n                            needFullExec[depName] = true;\n                            //Reset state so fully executed code will get\n                            //picked up correctly.\n                            delete defined[depName];\n                            urlFetched[depArg.url] = false;\n                        }\n\n                        //Either a resource that is not loaded yet, or a plugin\n                        //resource for either a plugin that has not\n                        //loaded yet.\n                        manager.depCount += 1;\n                        manager.depCallbacks[i] = makeArgCallback(manager, i);\n                        getManager(depArg, true).add(manager.depCallbacks[i]);\n                    }\n                }\n            }\n\n            //Do not bother tracking the manager if it is all done.\n            if (!manager.depCount) {\n                //All done, execute!\n                execManager(manager);\n            } else {\n                addWait(manager);\n            }\n        }\n\n        /**\n         * Convenience method to call main for a define call that was put on\n         * hold in the defQueue.\n         */\n        function callDefMain(args) {\n            main.apply(null, args);\n        }\n\n        /**\n         * jQuery 1.4.3+ supports ways to hold off calling\n         * calling jQuery ready callbacks until all scripts are loaded. Be sure\n         * to track it if the capability exists.. Also, since jQuery 1.4.3 does\n         * not register as a module, need to do some global inference checking.\n         * Even if it does register as a module, not guaranteed to be the precise\n         * name of the global. If a jQuery is tracked for this context, then go\n         * ahead and register it as a module too, if not already in process.\n         */\n        jQueryCheck = function (jqCandidate) {\n            if (!context.jQuery) {\n                var $ = jqCandidate || (typeof jQuery !== \"undefined\" ? jQuery : null);\n\n                if ($) {\n                    //If a specific version of jQuery is wanted, make sure to only\n                    //use this jQuery if it matches.\n                    if (config.jQuery && $.fn.jquery !== config.jQuery) {\n                        return;\n                    }\n\n                    if (\"holdReady\" in $ || \"readyWait\" in $) {\n                        context.jQuery = $;\n\n                        //Manually create a \"jquery\" module entry if not one already\n                        //or in process. Note this could trigger an attempt at\n                        //a second jQuery registration, but does no harm since\n                        //the first one wins, and it is the same value anyway.\n                        callDefMain([\"jquery\", [], function () {\n                            return jQuery;\n                        }]);\n\n                        //Ask jQuery to hold DOM ready callbacks.\n                        if (context.scriptCount) {\n                            jQueryHoldReady($, true);\n                            context.jQueryIncremented = true;\n                        }\n                    }\n                }\n            }\n        };\n\n        function forceExec(manager, traced) {\n            if (manager.isDone) {\n                return undefined;\n            }\n\n            var fullName = manager.map.fullName,\n                depArray = manager.depArray,\n                i, depName, depManager, prefix, prefixManager, value;\n\n            if (fullName) {\n                if (traced[fullName]) {\n                    return defined[fullName];\n                }\n\n                traced[fullName] = true;\n            }\n\n            //Trace through the dependencies.\n            if (depArray) {\n                for (i = 0; i < depArray.length; i++) {\n                    //Some array members may be null, like if a trailing comma\n                    //IE, so do the explicit [i] access and check if it has a value.\n                    depName = depArray[i];\n                    if (depName) {\n                        //First, make sure if it is a plugin resource that the\n                        //plugin is not blocked.\n                        prefix = makeModuleMap(depName).prefix;\n                        if (prefix && (prefixManager = waiting[prefix])) {\n                            forceExec(prefixManager, traced);\n                        }\n                        depManager = waiting[depName];\n                        if (depManager && !depManager.isDone && loaded[depName]) {\n                            value = forceExec(depManager, traced);\n                            manager.depCallbacks[i](value);\n                        }\n                    }\n                }\n            }\n\n            return fullName ? defined[fullName] : undefined;\n        }\n\n        /**\n         * Checks if all modules for a context are loaded, and if so, evaluates the\n         * new ones in right dependency order.\n         *\n         * @private\n         */\n        function checkLoaded() {\n            var waitInterval = config.waitSeconds * 1000,\n                //It is possible to disable the wait interval by using waitSeconds of 0.\n                expired = waitInterval && (context.startTime + waitInterval) < new Date().getTime(),\n                noLoads = \"\", hasLoadedProp = false, stillLoading = false, prop,\n                err, manager;\n\n            //If there are items still in the paused queue processing wait.\n            //This is particularly important in the sync case where each paused\n            //item is processed right away but there may be more waiting.\n            if (context.pausedCount > 0) {\n                return undefined;\n            }\n\n            //Determine if priority loading is done. If so clear the priority. If\n            //not, then do not check\n            if (config.priorityWait) {\n                if (isPriorityDone()) {\n                    //Call resume, since it could have\n                    //some waiting dependencies to trace.\n                    resume();\n                } else {\n                    return undefined;\n                }\n            }\n\n            //See if anything is still in flight.\n            for (prop in loaded) {\n                if (!(prop in empty)) {\n                    hasLoadedProp = true;\n                    if (!loaded[prop]) {\n                        if (expired) {\n                            noLoads += prop + \" \";\n                        } else {\n                            stillLoading = true;\n                            break;\n                        }\n                    }\n                }\n            }\n\n            //Check for exit conditions.\n            if (!hasLoadedProp && !context.waitCount) {\n                //If the loaded object had no items, then the rest of\n                //the work below does not need to be done.\n                return undefined;\n            }\n            if (expired && noLoads) {\n                //If wait time expired, throw error of unloaded modules.\n                err = makeError(\"timeout\", \"Load timeout for modules: \" + noLoads);\n                err.requireType = \"timeout\";\n                err.requireModules = noLoads;\n                return req.onError(err);\n            }\n            if (stillLoading || context.scriptCount) {\n                //Something is still waiting to load. Wait for it, but only\n                //if a timeout is not already in effect.\n                if ((isBrowser || isWebWorker) && !checkLoadedTimeoutId) {\n                    checkLoadedTimeoutId = setTimeout(function () {\n                        checkLoadedTimeoutId = 0;\n                        checkLoaded();\n                    }, 50);\n                }\n                return undefined;\n            }\n\n            //If still have items in the waiting cue, but all modules have\n            //been loaded, then it means there are some circular dependencies\n            //that need to be broken.\n            //However, as a waiting thing is fired, then it can add items to\n            //the waiting cue, and those items should not be fired yet, so\n            //make sure to redo the checkLoaded call after breaking a single\n            //cycle, if nothing else loaded then this logic will pick it up\n            //again.\n            if (context.waitCount) {\n                //Cycle through the waitAry, and call items in sequence.\n                for (i = 0; (manager = waitAry[i]); i++) {\n                    forceExec(manager, {});\n                }\n\n                //If anything got placed in the paused queue, run it down.\n                if (context.paused.length) {\n                    resume();\n                }\n\n                //Only allow this recursion to a certain depth. Only\n                //triggered by errors in calling a module in which its\n                //modules waiting on it cannot finish loading, or some circular\n                //dependencies that then may add more dependencies.\n                //The value of 5 is a bit arbitrary. Hopefully just one extra\n                //pass, or two for the case of circular dependencies generating\n                //more work that gets resolved in the sync node case.\n                if (checkLoadedDepth < 5) {\n                    checkLoadedDepth += 1;\n                    checkLoaded();\n                }\n            }\n\n            checkLoadedDepth = 0;\n\n            //Check for DOM ready, and nothing is waiting across contexts.\n            req.checkReadyState();\n\n            return undefined;\n        }\n\n        /**\n         * Resumes tracing of dependencies and then checks if everything is loaded.\n         */\n        resume = function () {\n            var manager, map, url, i, p, args, fullName;\n\n            resumeDepth += 1;\n\n            if (context.scriptCount <= 0) {\n                //Synchronous envs will push the number below zero with the\n                //decrement above, be sure to set it back to zero for good measure.\n                //require() calls that also do not end up loading scripts could\n                //push the number negative too.\n                context.scriptCount = 0;\n            }\n\n            //Make sure any remaining defQueue items get properly processed.\n            while (defQueue.length) {\n                args = defQueue.shift();\n                if (args[0] === null) {\n                    return req.onError(makeError('mismatch', 'Mismatched anonymous define() module: ' + args[args.length - 1]));\n                } else {\n                    callDefMain(args);\n                }\n            }\n\n            //Skip the resume of paused dependencies\n            //if current context is in priority wait.\n            if (!config.priorityWait || isPriorityDone()) {\n                while (context.paused.length) {\n                    p = context.paused;\n                    context.pausedCount += p.length;\n                    //Reset paused list\n                    context.paused = [];\n\n                    for (i = 0; (manager = p[i]); i++) {\n                        map = manager.map;\n                        url = map.url;\n                        fullName = map.fullName;\n\n                        //If the manager is for a plugin managed resource,\n                        //ask the plugin to load it now.\n                        if (map.prefix) {\n                            callPlugin(map.prefix, manager);\n                        } else {\n                            //Regular dependency.\n                            if (!urlFetched[url] && !loaded[fullName]) {\n                                req.load(context, fullName, url);\n\n                                //Mark the URL as fetched, but only if it is\n                                //not an empty: URL, used by the optimizer.\n                                //In that case we need to be sure to call\n                                //load() for each module that is mapped to\n                                //empty: so that dependencies are satisfied\n                                //correctly.\n                                if (url.indexOf('empty:') !== 0) {\n                                    urlFetched[url] = true;\n                                }\n                            }\n                        }\n                    }\n\n                    //Move the start time for timeout forward.\n                    context.startTime = (new Date()).getTime();\n                    context.pausedCount -= p.length;\n                }\n            }\n\n            //Only check if loaded when resume depth is 1. It is likely that\n            //it is only greater than 1 in sync environments where a factory\n            //function also then calls the callback-style require. In those\n            //cases, the checkLoaded should not occur until the resume\n            //depth is back at the top level.\n            if (resumeDepth === 1) {\n                checkLoaded();\n            }\n\n            resumeDepth -= 1;\n\n            return undefined;\n        };\n\n        //Define the context object. Many of these fields are on here\n        //just to make debugging easier.\n        context = {\n            contextName: contextName,\n            config: config,\n            defQueue: defQueue,\n            waiting: waiting,\n            waitCount: 0,\n            specified: specified,\n            loaded: loaded,\n            urlMap: urlMap,\n            urlFetched: urlFetched,\n            scriptCount: 0,\n            defined: defined,\n            paused: [],\n            pausedCount: 0,\n            plugins: plugins,\n            needFullExec: needFullExec,\n            fake: {},\n            fullExec: fullExec,\n            managerCallbacks: managerCallbacks,\n            makeModuleMap: makeModuleMap,\n            normalize: normalize,\n            /**\n             * Set a configuration for the context.\n             * @param {Object} cfg config object to integrate.\n             */\n            configure: function (cfg) {\n                var paths, prop, packages, pkgs, packagePaths, requireWait;\n\n                //Make sure the baseUrl ends in a slash.\n                if (cfg.baseUrl) {\n                    if (cfg.baseUrl.charAt(cfg.baseUrl.length - 1) !== \"/\") {\n                        cfg.baseUrl += \"/\";\n                    }\n                }\n\n                //Save off the paths and packages since they require special processing,\n                //they are additive.\n                paths = config.paths;\n                packages = config.packages;\n                pkgs = config.pkgs;\n\n                //Mix in the config values, favoring the new values over\n                //existing ones in context.config.\n                mixin(config, cfg, true);\n\n                //Adjust paths if necessary.\n                if (cfg.paths) {\n                    for (prop in cfg.paths) {\n                        if (!(prop in empty)) {\n                            paths[prop] = cfg.paths[prop];\n                        }\n                    }\n                    config.paths = paths;\n                }\n\n                packagePaths = cfg.packagePaths;\n                if (packagePaths || cfg.packages) {\n                    //Convert packagePaths into a packages config.\n                    if (packagePaths) {\n                        for (prop in packagePaths) {\n                            if (!(prop in empty)) {\n                                configurePackageDir(pkgs, packagePaths[prop], prop);\n                            }\n                        }\n                    }\n\n                    //Adjust packages if necessary.\n                    if (cfg.packages) {\n                        configurePackageDir(pkgs, cfg.packages);\n                    }\n\n                    //Done with modifications, assing packages back to context config\n                    config.pkgs = pkgs;\n                }\n\n                //If priority loading is in effect, trigger the loads now\n                if (cfg.priority) {\n                    //Hold on to requireWait value, and reset it after done\n                    requireWait = context.requireWait;\n\n                    //Allow tracing some require calls to allow the fetching\n                    //of the priority config.\n                    context.requireWait = false;\n                    //But first, call resume to register any defined modules that may\n                    //be in a data-main built file before the priority config\n                    //call. Also grab any waiting define calls for this context.\n                    context.takeGlobalQueue();\n                    resume();\n\n                    context.require(cfg.priority);\n\n                    //Trigger a resume right away, for the case when\n                    //the script with the priority load is done as part\n                    //of a data-main call. In that case the normal resume\n                    //call will not happen because the scriptCount will be\n                    //at 1, since the script for data-main is being processed.\n                    resume();\n\n                    //Restore previous state.\n                    context.requireWait = requireWait;\n                    config.priorityWait = cfg.priority;\n                }\n\n                //If a deps array or a config callback is specified, then call\n                //require with those args. This is useful when require is defined as a\n                //config object before require.js is loaded.\n                if (cfg.deps || cfg.callback) {\n                    context.require(cfg.deps || [], cfg.callback);\n                }\n            },\n\n            requireDefined: function (moduleName, relModuleMap) {\n                return makeModuleMap(moduleName, relModuleMap).fullName in defined;\n            },\n\n            requireSpecified: function (moduleName, relModuleMap) {\n                return makeModuleMap(moduleName, relModuleMap).fullName in specified;\n            },\n\n            require: function (deps, callback, relModuleMap) {\n                var moduleName, fullName, moduleMap;\n                if (typeof deps === \"string\") {\n                    if (isFunction(callback)) {\n                        //Invalid call\n                        return req.onError(makeError(\"requireargs\", \"Invalid require call\"));\n                    }\n\n                    //Synchronous access to one module. If require.get is\n                    //available (as in the Node adapter), prefer that.\n                    //In this case deps is the moduleName and callback is\n                    //the relModuleMap\n                    if (req.get) {\n                        return req.get(context, deps, callback);\n                    }\n\n                    //Just return the module wanted. In this scenario, the\n                    //second arg (if passed) is just the relModuleMap.\n                    moduleName = deps;\n                    relModuleMap = callback;\n\n                    //Normalize module name, if it contains . or ..\n                    moduleMap = makeModuleMap(moduleName, relModuleMap);\n                    fullName = moduleMap.fullName;\n\n                    if (!(fullName in defined)) {\n                        return req.onError(makeError(\"notloaded\", \"Module name '\" +\n                                    moduleMap.fullName +\n                                    \"' has not been loaded yet for context: \" +\n                                    contextName));\n                    }\n                    return defined[fullName];\n                }\n\n                //Call main but only if there are dependencies or\n                //a callback to call.\n                if (deps && deps.length || callback) {\n                    main(null, deps, callback, relModuleMap);\n                }\n\n                //If the require call does not trigger anything new to load,\n                //then resume the dependency processing.\n                if (!context.requireWait) {\n                    while (!context.scriptCount && context.paused.length) {\n                        //For built layers, there can be some defined\n                        //modules waiting for intake into the context,\n                        //in particular module plugins. Take them.\n                        context.takeGlobalQueue();\n                        resume();\n                    }\n                }\n                return context.require;\n            },\n\n            /**\n             * Internal method to transfer globalQueue items to this context's\n             * defQueue.\n             */\n            takeGlobalQueue: function () {\n                //Push all the globalDefQueue items into the context's defQueue\n                if (globalDefQueue.length) {\n                    //Array splice in the values since the context code has a\n                    //local var ref to defQueue, so cannot just reassign the one\n                    //on context.\n                    apsp.apply(context.defQueue,\n                               [context.defQueue.length - 1, 0].concat(globalDefQueue));\n                    globalDefQueue = [];\n                }\n            },\n\n            /**\n             * Internal method used by environment adapters to complete a load event.\n             * A load event could be a script load or just a load pass from a synchronous\n             * load call.\n             * @param {String} moduleName the name of the module to potentially complete.\n             */\n            completeLoad: function (moduleName) {\n                var args;\n\n                context.takeGlobalQueue();\n\n                while (defQueue.length) {\n                    args = defQueue.shift();\n\n                    if (args[0] === null) {\n                        args[0] = moduleName;\n                        break;\n                    } else if (args[0] === moduleName) {\n                        //Found matching define call for this script!\n                        break;\n                    } else {\n                        //Some other named define call, most likely the result\n                        //of a build layer that included many define calls.\n                        callDefMain(args);\n                        args = null;\n                    }\n                }\n                if (args) {\n                    callDefMain(args);\n                } else {\n                    //A script that does not call define(), so just simulate\n                    //the call for it. Special exception for jQuery dynamic load.\n                    callDefMain([moduleName, [],\n                                moduleName === \"jquery\" && typeof jQuery !== \"undefined\" ?\n                                function () {\n                                    return jQuery;\n                                } : null]);\n                }\n\n                //Doing this scriptCount decrement branching because sync envs\n                //need to decrement after resume, otherwise it looks like\n                //loading is complete after the first dependency is fetched.\n                //For browsers, it works fine to decrement after, but it means\n                //the checkLoaded setTimeout 50 ms cost is taken. To avoid\n                //that cost, decrement beforehand.\n                if (req.isAsync) {\n                    context.scriptCount -= 1;\n                }\n                resume();\n                if (!req.isAsync) {\n                    context.scriptCount -= 1;\n                }\n            },\n\n            /**\n             * Converts a module name + .extension into an URL path.\n             * *Requires* the use of a module name. It does not support using\n             * plain URLs like nameToUrl.\n             */\n            toUrl: function (moduleNamePlusExt, relModuleMap) {\n                var index = moduleNamePlusExt.lastIndexOf(\".\"),\n                    ext = null;\n\n                if (index !== -1) {\n                    ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);\n                    moduleNamePlusExt = moduleNamePlusExt.substring(0, index);\n                }\n\n                return context.nameToUrl(moduleNamePlusExt, ext, relModuleMap);\n            },\n\n            /**\n             * Converts a module name to a file path. Supports cases where\n             * moduleName may actually be just an URL.\n             */\n            nameToUrl: function (moduleName, ext, relModuleMap) {\n                var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,\n                    config = context.config;\n\n                //Normalize module name if have a base relative module name to work from.\n                moduleName = normalize(moduleName, relModuleMap && relModuleMap.fullName);\n\n                //If a colon is in the URL, it indicates a protocol is used and it is just\n                //an URL to a file, or if it starts with a slash or ends with .js, it is just a plain file.\n                //The slash is important for protocol-less URLs as well as full paths.\n                if (req.jsExtRegExp.test(moduleName)) {\n                    //Just a plain path, not module name lookup, so just return it.\n                    //Add extension if it is included. This is a bit wonky, only non-.js things pass\n                    //an extension, this method probably needs to be reworked.\n                    url = moduleName + (ext ? ext : \"\");\n                } else {\n                    //A module that needs to be converted to a path.\n                    paths = config.paths;\n                    pkgs = config.pkgs;\n\n                    syms = moduleName.split(\"/\");\n                    //For each module name segment, see if there is a path\n                    //registered for it. Start with most specific name\n                    //and work up from it.\n                    for (i = syms.length; i > 0; i--) {\n                        parentModule = syms.slice(0, i).join(\"/\");\n                        if (paths[parentModule]) {\n                            syms.splice(0, i, paths[parentModule]);\n                            break;\n                        } else if ((pkg = pkgs[parentModule])) {\n                            //If module name is just the package name, then looking\n                            //for the main module.\n                            if (moduleName === pkg.name) {\n                                pkgPath = pkg.location + '/' + pkg.main;\n                            } else {\n                                pkgPath = pkg.location;\n                            }\n                            syms.splice(0, i, pkgPath);\n                            break;\n                        }\n                    }\n\n                    //Join the path parts together, then figure out if baseUrl is needed.\n                    url = syms.join(\"/\") + (ext || \".js\");\n                    url = (url.charAt(0) === '/' || url.match(/^\\w+:/) ? \"\" : config.baseUrl) + url;\n                }\n\n                return config.urlArgs ? url +\n                                        ((url.indexOf('?') === -1 ? '?' : '&') +\n                                         config.urlArgs) : url;\n            }\n        };\n\n        //Make these visible on the context so can be called at the very\n        //end of the file to bootstrap\n        context.jQueryCheck = jQueryCheck;\n        context.resume = resume;\n\n        return context;\n    }\n\n    /**\n     * Main entry point.\n     *\n     * If the only argument to require is a string, then the module that\n     * is represented by that string is fetched for the appropriate context.\n     *\n     * If the first argument is an array, then it will be treated as an array\n     * of dependency string names to fetch. An optional function callback can\n     * be specified to execute when all of those dependencies are available.\n     *\n     * Make a local req variable to help Caja compliance (it assumes things\n     * on a require that are not standardized), and to give a short\n     * name for minification/local scope use.\n     */\n    req = requirejs = function (deps, callback) {\n\n        //Find the right context, use default\n        var contextName = defContextName,\n            context, config;\n\n        // Determine if have config object in the call.\n        if (!isArray(deps) && typeof deps !== \"string\") {\n            // deps is a config object\n            config = deps;\n            if (isArray(callback)) {\n                // Adjust args if there are dependencies\n                deps = callback;\n                callback = arguments[2];\n            } else {\n                deps = [];\n            }\n        }\n\n        if (config && config.context) {\n            contextName = config.context;\n        }\n\n        context = contexts[contextName] ||\n                  (contexts[contextName] = newContext(contextName));\n\n        if (config) {\n            context.configure(config);\n        }\n\n        return context.require(deps, callback);\n    };\n\n    /**\n     * Support require.config() to make it easier to cooperate with other\n     * AMD loaders on globally agreed names.\n     */\n    req.config = function (config) {\n        return req(config);\n    };\n\n    /**\n     * Export require as a global, but only if it does not already exist.\n     */\n    if (!require) {\n        require = req;\n    }\n\n    /**\n     * Global require.toUrl(), to match global require, mostly useful\n     * for debugging/work in the global space.\n     */\n    req.toUrl = function (moduleNamePlusExt) {\n        return contexts[defContextName].toUrl(moduleNamePlusExt);\n    };\n\n    req.version = version;\n\n    //Used to filter out dependencies that are already paths.\n    req.jsExtRegExp = /^\\/|:|\\?|\\.js$/;\n    s = req.s = {\n        contexts: contexts,\n        //Stores a list of URLs that should not get async script tag treatment.\n        skipAsync: {}\n    };\n\n    req.isAsync = req.isBrowser = isBrowser;\n    if (isBrowser) {\n        head = s.head = document.getElementsByTagName(\"head\")[0];\n        //If BASE tag is in play, using appendChild is a problem for IE6.\n        //When that browser dies, this can be removed. Details in this jQuery bug:\n        //http://dev.jquery.com/ticket/2709\n        baseElement = document.getElementsByTagName(\"base\")[0];\n        if (baseElement) {\n            head = s.head = baseElement.parentNode;\n        }\n    }\n\n    /**\n     * Any errors that require explicitly generates will be passed to this\n     * function. Intercept/override it if you want custom error handling.\n     * @param {Error} err the error object.\n     */\n    req.onError = function (err) {\n        throw err;\n    };\n\n    /**\n     * Does the request to load a module for the browser case.\n     * Make this a separate function to allow other environments\n     * to override it.\n     *\n     * @param {Object} context the require context to find state.\n     * @param {String} moduleName the name of the module.\n     * @param {Object} url the URL to the module.\n     */\n    req.load = function (context, moduleName, url) {\n        req.resourcesReady(false);\n\n        context.scriptCount += 1;\n        req.attach(url, context, moduleName);\n\n        //If tracking a jQuery, then make sure its ready callbacks\n        //are put on hold to prevent its ready callbacks from\n        //triggering too soon.\n        if (context.jQuery && !context.jQueryIncremented) {\n            jQueryHoldReady(context.jQuery, true);\n            context.jQueryIncremented = true;\n        }\n    };\n\n    function getInteractiveScript() {\n        var scripts, i, script;\n        if (interactiveScript && interactiveScript.readyState === 'interactive') {\n            return interactiveScript;\n        }\n\n        scripts = document.getElementsByTagName('script');\n        for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) {\n            if (script.readyState === 'interactive') {\n                return (interactiveScript = script);\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * The function that handles definitions of modules. Differs from\n     * require() in that a string for the module should be the first argument,\n     * and the function to execute after dependencies are loaded should\n     * return a value to define the module corresponding to the first argument's\n     * name.\n     */\n    define = function (name, deps, callback) {\n        var node, context;\n\n        //Allow for anonymous functions\n        if (typeof name !== 'string') {\n            //Adjust args appropriately\n            callback = deps;\n            deps = name;\n            name = null;\n        }\n\n        //This module may not have dependencies\n        if (!isArray(deps)) {\n            callback = deps;\n            deps = [];\n        }\n\n        //If no name, and callback is a function, then figure out if it a\n        //CommonJS thing with dependencies.\n        if (!deps.length && isFunction(callback)) {\n            //Remove comments from the callback string,\n            //look for require calls, and pull them into the dependencies,\n            //but only if there are function args.\n            if (callback.length) {\n                callback\n                    .toString()\n                    .replace(commentRegExp, \"\")\n                    .replace(cjsRequireRegExp, function (match, dep) {\n                        deps.push(dep);\n                    });\n\n                //May be a CommonJS thing even without require calls, but still\n                //could use exports, and module. Avoid doing exports and module\n                //work though if it just needs require.\n                //REQUIRES the function to expect the CommonJS variables in the\n                //order listed below.\n                deps = (callback.length === 1 ? [\"require\"] : [\"require\", \"exports\", \"module\"]).concat(deps);\n            }\n        }\n\n        //If in IE 6-8 and hit an anonymous define() call, do the interactive\n        //work.\n        if (useInteractive) {\n            node = currentlyAddingScript || getInteractiveScript();\n            if (node) {\n                if (!name) {\n                    name = node.getAttribute(\"data-requiremodule\");\n                }\n                context = contexts[node.getAttribute(\"data-requirecontext\")];\n            }\n        }\n\n        //Always save off evaluating the def call until the script onload handler.\n        //This allows multiple modules to be in a file without prematurely\n        //tracing dependencies, and allows for anonymous module support,\n        //where the module name is not known until the script onload event\n        //occurs. If no context, use the global queue, and get it processed\n        //in the onscript load callback.\n        (context ? context.defQueue : globalDefQueue).push([name, deps, callback]);\n\n        return undefined;\n    };\n\n    define.amd = {\n        multiversion: true,\n        plugins: true,\n        jQuery: true\n    };\n\n    /**\n     * Executes the text. Normally just uses eval, but can be modified\n     * to use a more environment specific call.\n     * @param {String} text the text to execute/evaluate.\n     */\n    req.exec = function (text) {\n        return eval(text);\n    };\n\n    /**\n     * Executes a module callack function. Broken out as a separate function\n     * solely to allow the build system to sequence the files in the built\n     * layer in the right sequence.\n     *\n     * @private\n     */\n    req.execCb = function (name, callback, args, exports) {\n        return callback.apply(exports, args);\n    };\n\n\n    /**\n     * Adds a node to the DOM. Public function since used by the order plugin.\n     * This method should not normally be called by outside code.\n     */\n    req.addScriptToDom = function (node) {\n        //For some cache cases in IE 6-8, the script executes before the end\n        //of the appendChild execution, so to tie an anonymous define\n        //call to the module name (which is stored on the node), hold on\n        //to a reference to this node, but clear after the DOM insertion.\n        currentlyAddingScript = node;\n        if (baseElement) {\n            head.insertBefore(node, baseElement);\n        } else {\n            head.appendChild(node);\n        }\n        currentlyAddingScript = null;\n    };\n\n    /**\n     * callback for script loads, used to check status of loading.\n     *\n     * @param {Event} evt the event from the browser for the script\n     * that was loaded.\n     *\n     * @private\n     */\n    req.onScriptLoad = function (evt) {\n        //Using currentTarget instead of target for Firefox 2.0's sake. Not\n        //all old browsers will be supported, but this one was easy enough\n        //to support and still makes sense.\n        var node = evt.currentTarget || evt.srcElement, contextName, moduleName,\n            context;\n\n        if (evt.type === \"load\" || (node && readyRegExp.test(node.readyState))) {\n            //Reset interactive script so a script node is not held onto for\n            //to long.\n            interactiveScript = null;\n\n            //Pull out the name of the module and the context.\n            contextName = node.getAttribute(\"data-requirecontext\");\n            moduleName = node.getAttribute(\"data-requiremodule\");\n            context = contexts[contextName];\n\n            contexts[contextName].completeLoad(moduleName);\n\n            //Clean up script binding. Favor detachEvent because of IE9\n            //issue, see attachEvent/addEventListener comment elsewhere\n            //in this file.\n            if (node.detachEvent && !isOpera) {\n                //Probably IE. If not it will throw an error, which will be\n                //useful to know.\n                node.detachEvent(\"onreadystatechange\", req.onScriptLoad);\n            } else {\n                node.removeEventListener(\"load\", req.onScriptLoad, false);\n            }\n        }\n    };\n\n    /**\n     * Attaches the script represented by the URL to the current\n     * environment. Right now only supports browser loading,\n     * but can be redefined in other environments to do the right thing.\n     * @param {String} url the url of the script to attach.\n     * @param {Object} context the context that wants the script.\n     * @param {moduleName} the name of the module that is associated with the script.\n     * @param {Function} [callback] optional callback, defaults to require.onScriptLoad\n     * @param {String} [type] optional type, defaults to text/javascript\n     * @param {Function} [fetchOnlyFunction] optional function to indicate the script node\n     * should be set up to fetch the script but do not attach it to the DOM\n     * so that it can later be attached to execute it. This is a way for the\n     * order plugin to support ordered loading in IE. Once the script is fetched,\n     * but not executed, the fetchOnlyFunction will be called.\n     */\n    req.attach = function (url, context, moduleName, callback, type, fetchOnlyFunction) {\n        var node;\n        if (isBrowser) {\n            //In the browser so use a script tag\n            callback = callback || req.onScriptLoad;\n            node = context && context.config && context.config.xhtml ?\n                    document.createElementNS(\"http://www.w3.org/1999/xhtml\", \"html:script\") :\n                    document.createElement(\"script\");\n            node.type = type || \"text/javascript\";\n            node.charset = \"utf-8\";\n            //Use async so Gecko does not block on executing the script if something\n            //like a long-polling comet tag is being run first. Gecko likes\n            //to evaluate scripts in DOM order, even for dynamic scripts.\n            //It will fetch them async, but only evaluate the contents in DOM\n            //order, so a long-polling script tag can delay execution of scripts\n            //after it. But telling Gecko we expect async gets us the behavior\n            //we want -- execute it whenever it is finished downloading. Only\n            //Helps Firefox 3.6+\n            //Allow some URLs to not be fetched async. Mostly helps the order!\n            //plugin\n            node.async = !s.skipAsync[url];\n\n            if (context) {\n                node.setAttribute(\"data-requirecontext\", context.contextName);\n            }\n            node.setAttribute(\"data-requiremodule\", moduleName);\n\n            //Set up load listener. Test attachEvent first because IE9 has\n            //a subtle issue in its addEventListener and script onload firings\n            //that do not match the behavior of all other browsers with\n            //addEventListener support, which fire the onload event for a\n            //script right after the script execution. See:\n            //https://connect.microsoft.com/IE/feedback/details/648057/script-onload-event-is-not-fired-immediately-after-script-execution\n            //UNFORTUNATELY Opera implements attachEvent but does not follow the script\n            //script execution mode.\n            if (node.attachEvent && !isOpera) {\n                //Probably IE. IE (at least 6-8) do not fire\n                //script onload right after executing the script, so\n                //we cannot tie the anonymous define call to a name.\n                //However, IE reports the script as being in \"interactive\"\n                //readyState at the time of the define call.\n                useInteractive = true;\n\n\n                if (fetchOnlyFunction) {\n                    //Need to use old school onreadystate here since\n                    //when the event fires and the node is not attached\n                    //to the DOM, the evt.srcElement is null, so use\n                    //a closure to remember the node.\n                    node.onreadystatechange = function (evt) {\n                        //Script loaded but not executed.\n                        //Clear loaded handler, set the real one that\n                        //waits for script execution.\n                        if (node.readyState === 'loaded') {\n                            node.onreadystatechange = null;\n                            node.attachEvent(\"onreadystatechange\", callback);\n                            fetchOnlyFunction(node);\n                        }\n                    };\n                } else {\n                    node.attachEvent(\"onreadystatechange\", callback);\n                }\n            } else {\n                node.addEventListener(\"load\", callback, false);\n            }\n            node.src = url;\n\n            //Fetch only means waiting to attach to DOM after loaded.\n            if (!fetchOnlyFunction) {\n                req.addScriptToDom(node);\n            }\n\n            return node;\n        } else if (isWebWorker) {\n            //In a web worker, use importScripts. This is not a very\n            //efficient use of importScripts, importScripts will block until\n            //its script is downloaded and evaluated. However, if web workers\n            //are in play, the expectation that a build has been done so that\n            //only one script needs to be loaded anyway. This may need to be\n            //reevaluated if other use cases become common.\n            importScripts(url);\n\n            //Account for anonymous modules\n            context.completeLoad(moduleName);\n        }\n        return null;\n    };\n\n    //Look for a data-main script attribute, which could also adjust the baseUrl.\n    if (isBrowser) {\n        //Figure out baseUrl. Get it from the script tag with require.js in it.\n        scripts = document.getElementsByTagName(\"script\");\n\n        for (i = scripts.length - 1; i > -1 && (script = scripts[i]); i--) {\n            //Set the \"head\" where we can append children by\n            //using the script's parent.\n            if (!head) {\n                head = script.parentNode;\n            }\n\n            //Look for a data-main attribute to set main script for the page\n            //to load. If it is there, the path to data main becomes the\n            //baseUrl, if it is not already set.\n            if ((dataMain = script.getAttribute('data-main'))) {\n                if (!cfg.baseUrl) {\n                    //Pull off the directory of data-main for use as the\n                    //baseUrl.\n                    src = dataMain.split('/');\n                    mainScript = src.pop();\n                    subPath = src.length ? src.join('/')  + '/' : './';\n\n                    //Set final config.\n                    cfg.baseUrl = subPath;\n                    //Strip off any trailing .js since dataMain is now\n                    //like a module name.\n                    dataMain = mainScript.replace(jsSuffixRegExp, '');\n                }\n\n                //Put the data-main script in the files to load.\n                cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain];\n\n                break;\n            }\n        }\n    }\n\n    //See if there is nothing waiting across contexts, and if not, trigger\n    //resourcesReady.\n    req.checkReadyState = function () {\n        var contexts = s.contexts, prop;\n        for (prop in contexts) {\n            if (!(prop in empty)) {\n                if (contexts[prop].waitCount) {\n                    return;\n                }\n            }\n        }\n        req.resourcesReady(true);\n    };\n\n    /**\n     * Internal function that is triggered whenever all scripts/resources\n     * have been loaded by the loader. Can be overridden by other, for\n     * instance the domReady plugin, which wants to know when all resources\n     * are loaded.\n     */\n    req.resourcesReady = function (isReady) {\n        var contexts, context, prop;\n\n        //First, set the public variable indicating that resources are loading.\n        req.resourcesDone = isReady;\n\n        if (req.resourcesDone) {\n            //If jQuery with DOM ready delayed, release it now.\n            contexts = s.contexts;\n            for (prop in contexts) {\n                if (!(prop in empty)) {\n                    context = contexts[prop];\n                    if (context.jQueryIncremented) {\n                        jQueryHoldReady(context.jQuery, false);\n                        context.jQueryIncremented = false;\n                    }\n                }\n            }\n        }\n    };\n\n    //FF < 3.6 readyState fix. Needed so that domReady plugin\n    //works well in that environment, since require.js is normally\n    //loaded via an HTML script tag so it will be there before window load,\n    //where the domReady plugin is more likely to be loaded after window load.\n    req.pageLoaded = function () {\n        if (document.readyState !== \"complete\") {\n            document.readyState = \"complete\";\n        }\n    };\n    if (isBrowser) {\n        if (document.addEventListener) {\n            if (!document.readyState) {\n                document.readyState = \"loading\";\n                window.addEventListener(\"load\", req.pageLoaded, false);\n            }\n        }\n    }\n\n    //Set up default context. If require was a configuration object, use that as base config.\n    req(cfg);\n\n    //If modules are built into require.js, then need to make sure dependencies are\n    //traced. Use a setTimeout in the browser world, to allow all the modules to register\n    //themselves. In a non-browser env, assume that modules are not built into require.js,\n    //which seems odd to do on the server.\n    if (req.isAsync && typeof setTimeout !== \"undefined\") {\n        ctx = s.contexts[(cfg.context || defContextName)];\n        //Indicate that the script that includes require() is still loading,\n        //so that require()'d dependencies are not traced until the end of the\n        //file is parsed (approximated via the setTimeout call).\n        ctx.requireWait = true;\n        setTimeout(function () {\n            ctx.requireWait = false;\n\n            //Any modules included with the require.js file will be in the\n            //global queue, assign them to this context.\n            ctx.takeGlobalQueue();\n\n            if (!ctx.scriptCount) {\n                ctx.resume();\n            }\n            req.checkReadyState();\n        }, 0);\n    }\n}());\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/require_config.js",
    "content": "      var require = {\n          baseUrl: window.location.protocol + \"//\" + window.location.host + window.location.pathname.split(\"/\").slice(0, -1).join(\"/\"),\n          paths: {\n              ace: \"lib/ace\"\n          }\n      };\n"
  },
  {
    "path": "_archive/apps/samples/text-editor/styles.css",
    "content": "html {\n    height: 100%;\n    width: 100%;\n    overflow: hidden;\n}\n\nbody {\n    overflow: hidden;\n    margin: 0;\n    padding: 0;\n    height: 100%;\n    width: 100%;\n    font-family: Arial, Helvetica, sans-serif, Tahoma, Verdana, sans-serif;\n    font-size: 12px;\n    background: white;\n    color: black;\n}\n\n.hidden {\n    display: none;\n}\n\n#toolbar {\n    position: absolute;\n    left: 0px;\n    top: 0px;\n    width: 58px;\n    height: 100%;\n    background: #EEE;\n    z-index: 100001;\n}\n\n.toolbarbutton {\n    padding: 5px;\n    height: 48px;\n    width: 48px;\n    background-repeat: no-repeat;\n    background-position: center;\n}\n\n.enabled:hover {\n    background: white;\n    background-repeat: no-repeat;\n    background-position: center;\n}\n\n#openfile {\n    background-image: url(\"icons/openfile.png\");\n}\n\n#openweb {\n    background-image: url(\"icons/openweb.png\");\n}\n\n#save {\n    background-image: url(\"icons/save.png\");\n}\n\n#saveas {\n    background-image: url(\"icons/saveas.png\");\n}\n\n#new {\n    background-image: url(\"icons/new.png\");\n}\n\n#editarea {\n    position: absolute;\n    top:  0px;\n    left: 58px;\n    bottom: 0px;\n    right: 0px;\n    background: white;\n}\n\n#status {\n    border-bottom: 1px solid #CCC;\n    background-color: #EEE;\n}\n\n#path {\n    padding: 5px;\n    color: #777;\n}\n\n#error {\n    padding: 5px;\n    padding-top: 0px;\n    color: #C66;\n}"
  },
  {
    "path": "_archive/apps/samples/todomvc/background.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\n\nvar dbName = 'todos-vanillajs';\n\nfunction launch() {\n  chrome.app.window.create('index.html', {\n    id: 'main',\n    innerBounds: { width: 620, height: 500 }\n  });\n}\n\nfunction showNotification(storedData) {\n\n  var openTodos = 0;\n\n  if ( storedData[dbName].todos ) {\n    storedData[dbName].todos.forEach(function(todo) {\n      if ( !todo.completed ) {\n        openTodos++;\n      }\n    });\n  }\n\n  if (openTodos>0) {\n    // Now create the notification\n    chrome.notifications.create('reminder', {\n        type: 'basic',\n        iconUrl: 'icon_128.png',\n        title: 'Don\\'t forget!',\n        message: 'You have '+openTodos+' things to do. Wake up, dude!'\n     }, function(notificationId) {})\n  }\n}\n\n// When the user clicks on the notification, we want to open the To Do list\nchrome.notifications.onClicked.addListener(function( notificationId ) {\n  launch();\n  chrome.notifications.clear(notificationId, function() {});\n});\n\nchrome.app.runtime.onLaunched.addListener(launch);\n\nchrome.alarms.onAlarm.addListener(function( alarm ) {\n  chrome.storage.local.get(dbName, showNotification);\n});\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/bower.json",
    "content": "{\n  \"name\": \"todomvc-vanillajs\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"todomvc-common\": \"~0.1.4\",\n    \"director\": \"~1.2.0\"\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/bower_components/director/build/director.js",
    "content": "\n\n//\n// Generated on Sun Dec 16 2012 22:47:05 GMT-0500 (EST) by Nodejitsu, Inc (Using Codesurgeon).\n// Version 1.1.9\n//\n\n(function (exports) {\n\n\n/*\n * browser.js: Browser specific functionality for director.\n *\n * (C) 2011, Nodejitsu Inc.\n * MIT LICENSE\n *\n */\n\nif (!Array.prototype.filter) {\n  Array.prototype.filter = function(filter, that) {\n    var other = [], v;\n    for (var i = 0, n = this.length; i < n; i++) {\n      if (i in this && filter.call(that, v = this[i], i, this)) {\n        other.push(v);\n      }\n    }\n    return other;\n  };\n}\n\nif (!Array.isArray){\n  Array.isArray = function(obj) {\n    return Object.prototype.toString.call(obj) === '[object Array]';\n  };\n}\n\nvar dloc = document.location;\n\nfunction dlocHashEmpty() {\n  // Non-IE browsers return '' when the address bar shows '#'; Director's logic\n  // assumes both mean empty.\n  return dloc.hash === '' || dloc.hash === '#';\n}\n\nvar listener = {\n  mode: 'modern',\n  hash: dloc.hash,\n  history: false,\n\n  check: function () {\n    var h = dloc.hash;\n    if (h != this.hash) {\n      this.hash = h;\n      this.onHashChanged();\n    }\n  },\n\n  fire: function () {\n    if (this.mode === 'modern') {\n      this.history === true ? window.onpopstate() : window.onhashchange();\n    }\n    else {\n      this.onHashChanged();\n    }\n  },\n\n  init: function (fn, history) {\n    var self = this;\n    this.history = history;\n\n    if (!Router.listeners) {\n      Router.listeners = [];\n    }\n\n    function onchange(onChangeEvent) {\n      for (var i = 0, l = Router.listeners.length; i < l; i++) {\n        Router.listeners[i](onChangeEvent);\n      }\n    }\n\n    //note IE8 is being counted as 'modern' because it has the hashchange event\n    if ('onhashchange' in window && (document.documentMode === undefined\n      || document.documentMode > 7)) {\n      // At least for now HTML5 history is available for 'modern' browsers only\n      if (this.history === true) {\n        // There is an old bug in Chrome that causes onpopstate to fire even\n        // upon initial page load. Since the handler is run manually in init(),\n        // this would cause Chrome to run it twise. Currently the only\n        // workaround seems to be to set the handler after the initial page load\n        // http://code.google.com/p/chromium/issues/detail?id=63040\n        setTimeout(function() {\n          window.onpopstate = onchange;\n        }, 500);\n      }\n      else {\n        window.onhashchange = onchange;\n      }\n      this.mode = 'modern';\n    }\n    else {\n      //\n      // IE support, based on a concept by Erik Arvidson ...\n      //\n      var frame = document.createElement('iframe');\n      frame.id = 'state-frame';\n      frame.style.display = 'none';\n      document.body.appendChild(frame);\n      this.writeFrame('');\n\n      if ('onpropertychange' in document && 'attachEvent' in document) {\n        document.attachEvent('onpropertychange', function () {\n          if (event.propertyName === 'location') {\n            self.check();\n          }\n        });\n      }\n\n      window.setInterval(function () { self.check(); }, 50);\n\n      this.onHashChanged = onchange;\n      this.mode = 'legacy';\n    }\n\n    Router.listeners.push(fn);\n\n    return this.mode;\n  },\n\n  destroy: function (fn) {\n    if (!Router || !Router.listeners) {\n      return;\n    }\n\n    var listeners = Router.listeners;\n\n    for (var i = listeners.length - 1; i >= 0; i--) {\n      if (listeners[i] === fn) {\n        listeners.splice(i, 1);\n      }\n    }\n  },\n\n  setHash: function (s) {\n    // Mozilla always adds an entry to the history\n    if (this.mode === 'legacy') {\n      this.writeFrame(s);\n    }\n\n    if (this.history === true) {\n      window.history.pushState({}, document.title, s);\n      // Fire an onpopstate event manually since pushing does not obviously\n      // trigger the pop event.\n      this.fire();\n    } else {\n      dloc.hash = (s[0] === '/') ? s : '/' + s;\n    }\n    return this;\n  },\n\n  writeFrame: function (s) {\n    // IE support...\n    var f = document.getElementById('state-frame');\n    var d = f.contentDocument || f.contentWindow.document;\n    d.open();\n    d.write(\"<script>_hash = '\" + s + \"'; onload = parent.listener.syncHash;<script>\");\n    d.close();\n  },\n\n  syncHash: function () {\n    // IE support...\n    var s = this._hash;\n    if (s != dloc.hash) {\n      dloc.hash = s;\n    }\n    return this;\n  },\n\n  onHashChanged: function () {}\n};\n\nvar Router = exports.Router = function (routes) {\n  if (!(this instanceof Router)) return new Router(routes);\n\n  this.params   = {};\n  this.routes   = {};\n  this.methods  = ['on', 'once', 'after', 'before'];\n  this.scope    = [];\n  this._methods = {};\n\n  this._insert = this.insert;\n  this.insert = this.insertEx;\n\n  this.historySupport = (window.history != null ? window.history.pushState : null) != null\n\n  this.configure();\n  this.mount(routes || {});\n};\n\nRouter.prototype.init = function (r) {\n  var self = this;\n  this.handler = function(onChangeEvent) {\n    var newURL = onChangeEvent && onChangeEvent.newURL || window.location.hash;\n    var url = self.history === true ? self.getPath() : newURL.replace(/.*#/, '');\n    self.dispatch('on', url);\n  };\n\n  listener.init(this.handler, this.history);\n\n  if (this.history === false) {\n    if (dlocHashEmpty() && r) {\n      dloc.hash = r;\n    } else if (!dlocHashEmpty()) {\n      self.dispatch('on', dloc.hash.replace(/^#/, ''));\n    }\n  }\n  else {\n    var routeTo = dlocHashEmpty() && r ? r : !dlocHashEmpty() ? dloc.hash.replace(/^#/, '') : null;\n    if (routeTo) {\n      window.history.replaceState({}, document.title, routeTo);\n    }\n\n    // Router has been initialized, but due to the chrome bug it will not\n    // yet actually route HTML5 history state changes. Thus, decide if should route.\n    if (routeTo || this.run_in_init === true) {\n      this.handler();\n    }\n  }\n\n  return this;\n};\n\nRouter.prototype.explode = function () {\n  var v = this.history === true ? this.getPath() : dloc.hash;\n  if (v.charAt(1) === '/') { v=v.slice(1) }\n  return v.slice(1, v.length).split(\"/\");\n};\n\nRouter.prototype.setRoute = function (i, v, val) {\n  var url = this.explode();\n\n  if (typeof i === 'number' && typeof v === 'string') {\n    url[i] = v;\n  }\n  else if (typeof val === 'string') {\n    url.splice(i, v, s);\n  }\n  else {\n    url = [i];\n  }\n\n  listener.setHash(url.join('/'));\n  return url;\n};\n\n//\n// ### function insertEx(method, path, route, parent)\n// #### @method {string} Method to insert the specific `route`.\n// #### @path {Array} Parsed path to insert the `route` at.\n// #### @route {Array|function} Route handlers to insert.\n// #### @parent {Object} **Optional** Parent \"routes\" to insert into.\n// insert a callback that will only occur once per the matched route.\n//\nRouter.prototype.insertEx = function(method, path, route, parent) {\n  if (method === \"once\") {\n    method = \"on\";\n    route = function(route) {\n      var once = false;\n      return function() {\n        if (once) return;\n        once = true;\n        return route.apply(this, arguments);\n      };\n    }(route);\n  }\n  return this._insert(method, path, route, parent);\n};\n\nRouter.prototype.getRoute = function (v) {\n  var ret = v;\n\n  if (typeof v === \"number\") {\n    ret = this.explode()[v];\n  }\n  else if (typeof v === \"string\"){\n    var h = this.explode();\n    ret = h.indexOf(v);\n  }\n  else {\n    ret = this.explode();\n  }\n\n  return ret;\n};\n\nRouter.prototype.destroy = function () {\n  listener.destroy(this.handler);\n  return this;\n};\n\nRouter.prototype.getPath = function () {\n  var path = window.location.pathname;\n  if (path.substr(0, 1) !== '/') {\n    path = '/' + path;\n  }\n  return path;\n};\nfunction _every(arr, iterator) {\n  for (var i = 0; i < arr.length; i += 1) {\n    if (iterator(arr[i], i, arr) === false) {\n      return;\n    }\n  }\n}\n\nfunction _flatten(arr) {\n  var flat = [];\n  for (var i = 0, n = arr.length; i < n; i++) {\n    flat = flat.concat(arr[i]);\n  }\n  return flat;\n}\n\nfunction _asyncEverySeries(arr, iterator, callback) {\n  if (!arr.length) {\n    return callback();\n  }\n  var completed = 0;\n  (function iterate() {\n    iterator(arr[completed], function(err) {\n      if (err || err === false) {\n        callback(err);\n        callback = function() {};\n      } else {\n        completed += 1;\n        if (completed === arr.length) {\n          callback();\n        } else {\n          iterate();\n        }\n      }\n    });\n  })();\n}\n\nfunction paramifyString(str, params, mod) {\n  mod = str;\n  for (var param in params) {\n    if (params.hasOwnProperty(param)) {\n      mod = params[param](str);\n      if (mod !== str) {\n        break;\n      }\n    }\n  }\n  return mod === str ? \"([._a-zA-Z0-9-]+)\" : mod;\n}\n\nfunction regifyString(str, params) {\n  var matches, last = 0, out = \"\";\n  while (matches = str.substr(last).match(/[^\\w\\d\\- %@&]*\\*[^\\w\\d\\- %@&]*/)) {\n    last = matches.index + matches[0].length;\n    matches[0] = matches[0].replace(/^\\*/, \"([_.()!\\\\ %@&a-zA-Z0-9-]+)\");\n    out += str.substr(0, matches.index) + matches[0];\n  }\n  str = out += str.substr(last);\n  var captures = str.match(/:([^\\/]+)/ig), length;\n  if (captures) {\n    length = captures.length;\n    for (var i = 0; i < length; i++) {\n      str = str.replace(captures[i], paramifyString(captures[i], params));\n    }\n  }\n  return str;\n}\n\nfunction terminator(routes, delimiter, start, stop) {\n  var last = 0, left = 0, right = 0, start = (start || \"(\").toString(), stop = (stop || \")\").toString(), i;\n  for (i = 0; i < routes.length; i++) {\n    var chunk = routes[i];\n    if (chunk.indexOf(start, last) > chunk.indexOf(stop, last) || ~chunk.indexOf(start, last) && !~chunk.indexOf(stop, last) || !~chunk.indexOf(start, last) && ~chunk.indexOf(stop, last)) {\n      left = chunk.indexOf(start, last);\n      right = chunk.indexOf(stop, last);\n      if (~left && !~right || !~left && ~right) {\n        var tmp = routes.slice(0, (i || 1) + 1).join(delimiter);\n        routes = [ tmp ].concat(routes.slice((i || 1) + 1));\n      }\n      last = (right > left ? right : left) + 1;\n      i = 0;\n    } else {\n      last = 0;\n    }\n  }\n  return routes;\n}\n\nRouter.prototype.configure = function(options) {\n  options = options || {};\n  for (var i = 0; i < this.methods.length; i++) {\n    this._methods[this.methods[i]] = true;\n  }\n  this.recurse = options.recurse || this.recurse || false;\n  this.async = options.async || false;\n  this.delimiter = options.delimiter || \"/\";\n  this.strict = typeof options.strict === \"undefined\" ? true : options.strict;\n  this.notfound = options.notfound;\n  this.resource = options.resource;\n  this.history = options.html5history && this.historySupport || false;\n  this.run_in_init = this.history === true && options.run_handler_in_init !== false;\n  this.every = {\n    after: options.after || null,\n    before: options.before || null,\n    on: options.on || null\n  };\n  return this;\n};\n\nRouter.prototype.param = function(token, matcher) {\n  if (token[0] !== \":\") {\n    token = \":\" + token;\n  }\n  var compiled = new RegExp(token, \"g\");\n  this.params[token] = function(str) {\n    return str.replace(compiled, matcher.source || matcher);\n  };\n};\n\nRouter.prototype.on = Router.prototype.route = function(method, path, route) {\n  var self = this;\n  if (!route && typeof path == \"function\") {\n    route = path;\n    path = method;\n    method = \"on\";\n  }\n  if (Array.isArray(path)) {\n    return path.forEach(function(p) {\n      self.on(method, p, route);\n    });\n  }\n  if (path.source) {\n    path = path.source.replace(/\\\\\\//ig, \"/\");\n  }\n  if (Array.isArray(method)) {\n    return method.forEach(function(m) {\n      self.on(m.toLowerCase(), path, route);\n    });\n  }\n  path = path.split(new RegExp(this.delimiter));\n  path = terminator(path, this.delimiter);\n  this.insert(method, this.scope.concat(path), route);\n};\n\nRouter.prototype.dispatch = function(method, path, callback) {\n  var self = this, fns = this.traverse(method, path, this.routes, \"\"), invoked = this._invoked, after;\n  this._invoked = true;\n  if (!fns || fns.length === 0) {\n    this.last = [];\n    if (typeof this.notfound === \"function\") {\n      this.invoke([ this.notfound ], {\n        method: method,\n        path: path\n      }, callback);\n    }\n    return false;\n  }\n  if (this.recurse === \"forward\") {\n    fns = fns.reverse();\n  }\n  function updateAndInvoke() {\n    self.last = fns.after;\n    self.invoke(self.runlist(fns), self, callback);\n  }\n  after = this.every && this.every.after ? [ this.every.after ].concat(this.last) : [ this.last ];\n  if (after && after.length > 0 && invoked) {\n    if (this.async) {\n      this.invoke(after, this, updateAndInvoke);\n    } else {\n      this.invoke(after, this);\n      updateAndInvoke();\n    }\n    return true;\n  }\n  updateAndInvoke();\n  return true;\n};\n\nRouter.prototype.invoke = function(fns, thisArg, callback) {\n  var self = this;\n  if (this.async) {\n    _asyncEverySeries(fns, function apply(fn, next) {\n      if (Array.isArray(fn)) {\n        return _asyncEverySeries(fn, apply, next);\n      } else if (typeof fn == \"function\") {\n        fn.apply(thisArg, fns.captures.concat(next));\n      }\n    }, function() {\n      if (callback) {\n        callback.apply(thisArg, arguments);\n      }\n    });\n  } else {\n    _every(fns, function apply(fn) {\n      if (Array.isArray(fn)) {\n        return _every(fn, apply);\n      } else if (typeof fn === \"function\") {\n        return fn.apply(thisArg, fns.captures || []);\n      } else if (typeof fn === \"string\" && self.resource) {\n        self.resource[fn].apply(thisArg, fns.captures || []);\n      }\n    });\n  }\n};\n\nRouter.prototype.traverse = function(method, path, routes, regexp, filter) {\n  var fns = [], current, exact, match, next, that;\n  function filterRoutes(routes) {\n    if (!filter) {\n      return routes;\n    }\n    function deepCopy(source) {\n      var result = [];\n      for (var i = 0; i < source.length; i++) {\n        result[i] = Array.isArray(source[i]) ? deepCopy(source[i]) : source[i];\n      }\n      return result;\n    }\n    function applyFilter(fns) {\n      for (var i = fns.length - 1; i >= 0; i--) {\n        if (Array.isArray(fns[i])) {\n          applyFilter(fns[i]);\n          if (fns[i].length === 0) {\n            fns.splice(i, 1);\n          }\n        } else {\n          if (!filter(fns[i])) {\n            fns.splice(i, 1);\n          }\n        }\n      }\n    }\n    var newRoutes = deepCopy(routes);\n    newRoutes.matched = routes.matched;\n    newRoutes.captures = routes.captures;\n    newRoutes.after = routes.after.filter(filter);\n    applyFilter(newRoutes);\n    return newRoutes;\n  }\n  if (path === this.delimiter && routes[method]) {\n    next = [ [ routes.before, routes[method] ].filter(Boolean) ];\n    next.after = [ routes.after ].filter(Boolean);\n    next.matched = true;\n    next.captures = [];\n    return filterRoutes(next);\n  }\n  for (var r in routes) {\n    if (routes.hasOwnProperty(r) && (!this._methods[r] || this._methods[r] && typeof routes[r] === \"object\" && !Array.isArray(routes[r]))) {\n      current = exact = regexp + this.delimiter + r;\n      if (!this.strict) {\n        exact += \"[\" + this.delimiter + \"]?\";\n      }\n      match = path.match(new RegExp(\"^\" + exact));\n      if (!match) {\n        continue;\n      }\n      if (match[0] && match[0] == path && routes[r][method]) {\n        next = [ [ routes[r].before, routes[r][method] ].filter(Boolean) ];\n        next.after = [ routes[r].after ].filter(Boolean);\n        next.matched = true;\n        next.captures = match.slice(1);\n        if (this.recurse && routes === this.routes) {\n          next.push([ routes.before, routes.on ].filter(Boolean));\n          next.after = next.after.concat([ routes.after ].filter(Boolean));\n        }\n        return filterRoutes(next);\n      }\n      next = this.traverse(method, path, routes[r], current);\n      if (next.matched) {\n        if (next.length > 0) {\n          fns = fns.concat(next);\n        }\n        if (this.recurse) {\n          fns.push([ routes[r].before, routes[r].on ].filter(Boolean));\n          next.after = next.after.concat([ routes[r].after ].filter(Boolean));\n          if (routes === this.routes) {\n            fns.push([ routes[\"before\"], routes[\"on\"] ].filter(Boolean));\n            next.after = next.after.concat([ routes[\"after\"] ].filter(Boolean));\n          }\n        }\n        fns.matched = true;\n        fns.captures = next.captures;\n        fns.after = next.after;\n        return filterRoutes(fns);\n      }\n    }\n  }\n  return false;\n};\n\nRouter.prototype.insert = function(method, path, route, parent) {\n  var methodType, parentType, isArray, nested, part;\n  path = path.filter(function(p) {\n    return p && p.length > 0;\n  });\n  parent = parent || this.routes;\n  part = path.shift();\n  if (/\\:|\\*/.test(part) && !/\\\\d|\\\\w/.test(part)) {\n    part = regifyString(part, this.params);\n  }\n  if (path.length > 0) {\n    parent[part] = parent[part] || {};\n    return this.insert(method, path, route, parent[part]);\n  }\n  if (!part && !path.length && parent === this.routes) {\n    methodType = typeof parent[method];\n    switch (methodType) {\n     case \"function\":\n      parent[method] = [ parent[method], route ];\n      return;\n     case \"object\":\n      parent[method].push(route);\n      return;\n     case \"undefined\":\n      parent[method] = route;\n      return;\n    }\n    return;\n  }\n  parentType = typeof parent[part];\n  isArray = Array.isArray(parent[part]);\n  if (parent[part] && !isArray && parentType == \"object\") {\n    methodType = typeof parent[part][method];\n    switch (methodType) {\n     case \"function\":\n      parent[part][method] = [ parent[part][method], route ];\n      return;\n     case \"object\":\n      parent[part][method].push(route);\n      return;\n     case \"undefined\":\n      parent[part][method] = route;\n      return;\n    }\n  } else if (parentType == \"undefined\") {\n    nested = {};\n    nested[method] = route;\n    parent[part] = nested;\n    return;\n  }\n  throw new Error(\"Invalid route context: \" + parentType);\n};\n\n\n\nRouter.prototype.extend = function(methods) {\n  var self = this, len = methods.length, i;\n  function extend(method) {\n    self._methods[method] = true;\n    self[method] = function() {\n      var extra = arguments.length === 1 ? [ method, \"\" ] : [ method ];\n      self.on.apply(self, extra.concat(Array.prototype.slice.call(arguments)));\n    };\n  }\n  for (i = 0; i < len; i++) {\n    extend(methods[i]);\n  }\n};\n\nRouter.prototype.runlist = function(fns) {\n  var runlist = this.every && this.every.before ? [ this.every.before ].concat(_flatten(fns)) : _flatten(fns);\n  if (this.every && this.every.on) {\n    runlist.push(this.every.on);\n  }\n  runlist.captures = fns.captures;\n  runlist.source = fns.source;\n  return runlist;\n};\n\nRouter.prototype.mount = function(routes, path) {\n  if (!routes || typeof routes !== \"object\" || Array.isArray(routes)) {\n    return;\n  }\n  var self = this;\n  path = path || [];\n  if (!Array.isArray(path)) {\n    path = path.split(self.delimiter);\n  }\n  function insertOrMount(route, local) {\n    var rename = route, parts = route.split(self.delimiter), routeType = typeof routes[route], isRoute = parts[0] === \"\" || !self._methods[parts[0]], event = isRoute ? \"on\" : rename;\n    if (isRoute) {\n      rename = rename.slice((rename.match(new RegExp(self.delimiter)) || [ \"\" ])[0].length);\n      parts.shift();\n    }\n    if (isRoute && routeType === \"object\" && !Array.isArray(routes[route])) {\n      local = local.concat(parts);\n      self.mount(routes[route], local);\n      return;\n    }\n    if (isRoute) {\n      local = local.concat(rename.split(self.delimiter));\n      local = terminator(local, self.delimiter);\n    }\n    self.insert(event, local, routes[route]);\n  }\n  for (var route in routes) {\n    if (routes.hasOwnProperty(route)) {\n      insertOrMount(route, path.slice(0));\n    }\n  }\n};\n\n\n\n}(typeof exports === \"object\" ? exports : window));"
  },
  {
    "path": "_archive/apps/samples/todomvc/bower_components/todomvc-common/base.css",
    "content": "html,\nbody {\n\tmargin: 0;\n\tpadding: 0;\n}\n\nbutton {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tbackground: none;\n\tfont-size: 100%;\n\tvertical-align: baseline;\n\tfont-family: inherit;\n\tcolor: inherit;\n\t-webkit-appearance: none;\n\t/*-moz-appearance: none;*/\n\t-ms-appearance: none;\n\t-o-appearance: none;\n\tappearance: none;\n}\n\nbody {\n\tfont: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;\n\tline-height: 1.4em;\n\tbackground: #eaeaea url('bg.png');\n\tcolor: #4d4d4d;\n\twidth: 550px;\n\tmargin: 0 auto;\n\t-webkit-font-smoothing: antialiased;\n\t-moz-font-smoothing: antialiased;\n\t-ms-font-smoothing: antialiased;\n\t-o-font-smoothing: antialiased;\n\tfont-smoothing: antialiased;\n}\n\n#todoapp {\n\tbackground: #fff;\n\tbackground: rgba(255, 255, 255, 0.9);\n\tmargin: 130px 0 40px 0;\n\tborder: 1px solid #ccc;\n\tposition: relative;\n\tborder-top-left-radius: 2px;\n\tborder-top-right-radius: 2px;\n\tbox-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),\n\t\t\t\t0 25px 50px 0 rgba(0, 0, 0, 0.15);\n}\n\n#todoapp:before {\n\tcontent: '';\n\tborder-left: 1px solid #f5d6d6;\n\tborder-right: 1px solid #f5d6d6;\n\twidth: 2px;\n\tposition: absolute;\n\ttop: 0;\n\tleft: 40px;\n\theight: 100%;\n}\n\n#todoapp input::-webkit-input-placeholder {\n\tfont-style: italic;\n}\n\n#todoapp input:-moz-placeholder {\n\tfont-style: italic;\n\tcolor: #a9a9a9;\n}\n\n#todoapp h1 {\n\tposition: absolute;\n\ttop: -120px;\n\twidth: 100%;\n\tfont-size: 70px;\n\tfont-weight: bold;\n\ttext-align: center;\n\tcolor: #b3b3b3;\n\tcolor: rgba(255, 255, 255, 0.3);\n\ttext-shadow: -1px -1px rgba(0, 0, 0, 0.2);\n\t-webkit-text-rendering: optimizeLegibility;\n\t-moz-text-rendering: optimizeLegibility;\n\t-ms-text-rendering: optimizeLegibility;\n\t-o-text-rendering: optimizeLegibility;\n\ttext-rendering: optimizeLegibility;\n}\n\n#header {\n\tpadding-top: 15px;\n\tborder-radius: inherit;\n}\n\n#header:before {\n\tcontent: '';\n\tposition: absolute;\n\ttop: 0;\n\tright: 0;\n\tleft: 0;\n\theight: 15px;\n\tz-index: 2;\n\tborder-bottom: 1px solid #6c615c;\n\tbackground: #8d7d77;\n\tbackground: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8)));\n\tbackground: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));\n\tbackground: -moz-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));\n\tbackground: -o-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));\n\tbackground: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));\n\tbackground: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));\n\tfilter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');\n\tborder-top-left-radius: 1px;\n\tborder-top-right-radius: 1px;\n}\n\n#new-todo,\n.edit {\n\tposition: relative;\n\tmargin: 0;\n\twidth: 100%;\n\tfont-size: 24px;\n\tfont-family: inherit;\n\tline-height: 1.4em;\n\tborder: 0;\n\toutline: none;\n\tcolor: inherit;\n\tpadding: 6px;\n\tborder: 1px solid #999;\n\tbox-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);\n\t-webkit-box-sizing: border-box;\n\t-moz-box-sizing: border-box;\n\t-ms-box-sizing: border-box;\n\t-o-box-sizing: border-box;\n\tbox-sizing: border-box;\n\t-webkit-font-smoothing: antialiased;\n\t-moz-font-smoothing: antialiased;\n\t-ms-font-smoothing: antialiased;\n\t-o-font-smoothing: antialiased;\n\tfont-smoothing: antialiased;\n}\n\n#new-todo {\n\tpadding: 16px 16px 16px 60px;\n\tborder: none;\n\tbackground: rgba(0, 0, 0, 0.02);\n\tz-index: 2;\n\tbox-shadow: none;\n}\n\n#main {\n\tposition: relative;\n\tz-index: 2;\n\tborder-top: 1px dotted #adadad;\n}\n\nlabel[for='toggle-all'] {\n\tdisplay: none;\n}\n\n#toggle-all {\n\tposition: absolute;\n\ttop: -42px;\n\tleft: -4px;\n\twidth: 40px;\n\ttext-align: center;\n\tborder: none; /* Mobile Safari */\n}\n\n#toggle-all:before {\n\tcontent: '»';\n\tfont-size: 28px;\n\tcolor: #d9d9d9;\n\tpadding: 0 25px 7px;\n}\n\n#toggle-all:checked:before {\n\tcolor: #737373;\n}\n\n#todo-list {\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n\n#todo-list li {\n\tposition: relative;\n\tfont-size: 24px;\n\tborder-bottom: 1px dotted #ccc;\n}\n\n#todo-list li:last-child {\n\tborder-bottom: none;\n}\n\n#todo-list li.editing {\n\tborder-bottom: none;\n\tpadding: 0;\n}\n\n#todo-list li.editing .edit {\n\tdisplay: block;\n\twidth: 506px;\n\tpadding: 13px 17px 12px 17px;\n\tmargin: 0 0 0 43px;\n}\n\n#todo-list li.editing .view {\n\tdisplay: none;\n}\n\n#todo-list li .toggle {\n\ttext-align: center;\n\twidth: 40px;\n\t/* auto, since non-WebKit browsers doesn't support input styling */\n\theight: auto;\n\tposition: absolute;\n\ttop: 0;\n\tbottom: 0;\n\tmargin: auto 0;\n\tborder: none; /* Mobile Safari */\n\t-webkit-appearance: none;\n\t/*-moz-appearance: none;*/\n\t-ms-appearance: none;\n\t-o-appearance: none;\n\tappearance: none;\n}\n\n#todo-list li .toggle:after {\n\tcontent: '✔';\n\tline-height: 43px; /* 40 + a couple of pixels visual adjustment */\n\tfont-size: 20px;\n\tcolor: #d9d9d9;\n\ttext-shadow: 0 -1px 0 #bfbfbf;\n}\n\n#todo-list li .toggle:checked:after {\n\tcolor: #85ada7;\n\ttext-shadow: 0 1px 0 #669991;\n\tbottom: 1px;\n\tposition: relative;\n}\n\n#todo-list li label {\n\tword-break: break-word;\n\tpadding: 15px;\n\tmargin-left: 45px;\n\tdisplay: block;\n\tline-height: 1.2;\n\t-webkit-transition: color 0.4s;\n\t-moz-transition: color 0.4s;\n\t-ms-transition: color 0.4s;\n\t-o-transition: color 0.4s;\n\ttransition: color 0.4s;\n}\n\n#todo-list li.completed label {\n\tcolor: #a9a9a9;\n\ttext-decoration: line-through;\n}\n\n#todo-list li .destroy {\n\tdisplay: none;\n\tposition: absolute;\n\ttop: 0;\n\tright: 10px;\n\tbottom: 0;\n\twidth: 40px;\n\theight: 40px;\n\tmargin: auto 0;\n\tfont-size: 22px;\n\tcolor: #a88a8a;\n\t-webkit-transition: all 0.2s;\n\t-moz-transition: all 0.2s;\n\t-ms-transition: all 0.2s;\n\t-o-transition: all 0.2s;\n\ttransition: all 0.2s;\n}\n\n#todo-list li .destroy:hover {\n\ttext-shadow: 0 0 1px #000,\n\t\t\t\t 0 0 10px rgba(199, 107, 107, 0.8);\n\t-webkit-transform: scale(1.3);\n\t-moz-transform: scale(1.3);\n\t-ms-transform: scale(1.3);\n\t-o-transform: scale(1.3);\n\ttransform: scale(1.3);\n}\n\n#todo-list li .destroy:after {\n\tcontent: '✖';\n}\n\n#todo-list li:hover .destroy {\n\tdisplay: block;\n}\n\n#todo-list li .edit {\n\tdisplay: none;\n}\n\n#todo-list li.editing:last-child {\n\tmargin-bottom: -1px;\n}\n\n#footer {\n\tcolor: #777;\n\tpadding: 0 15px;\n\tposition: absolute;\n\tright: 0;\n\tbottom: -31px;\n\tleft: 0;\n\theight: 20px;\n\tz-index: 1;\n\ttext-align: center;\n}\n\n#footer:before {\n\tcontent: '';\n\tposition: absolute;\n\tright: 0;\n\tbottom: 31px;\n\tleft: 0;\n\theight: 50px;\n\tz-index: -1;\n\tbox-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),\n\t\t\t\t0 6px 0 -3px rgba(255, 255, 255, 0.8),\n\t\t\t\t0 7px 1px -3px rgba(0, 0, 0, 0.3),\n\t\t\t\t0 43px 0 -6px rgba(255, 255, 255, 0.8),\n\t\t\t\t0 44px 2px -6px rgba(0, 0, 0, 0.2);\n}\n\n#todo-count {\n\tfloat: left;\n\ttext-align: left;\n}\n\n#filters {\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n\tposition: absolute;\n\tright: 0;\n\tleft: 0;\n}\n\n#filters li {\n\tdisplay: inline;\n}\n\n#filters li a {\n\tcolor: #83756f;\n\tmargin: 2px;\n\ttext-decoration: none;\n}\n\n#filters li a.selected {\n\tfont-weight: bold;\n}\n\n#clear-completed {\n\tfloat: right;\n\tposition: relative;\n\tline-height: 20px;\n\ttext-decoration: none;\n\tbackground: rgba(0, 0, 0, 0.1);\n\tfont-size: 11px;\n\tpadding: 0 10px;\n\tborder-radius: 3px;\n\tbox-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);\n}\n\n#clear-completed:hover {\n\tbackground: rgba(0, 0, 0, 0.15);\n\tbox-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);\n}\n\n#info {\n\tmargin: 65px auto 0;\n\tcolor: #a6a6a6;\n\tfont-size: 12px;\n\ttext-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);\n\ttext-align: center;\n}\n\n#info a {\n\tcolor: inherit;\n}\n\n/*\n\tHack to remove background from Mobile Safari.\n\tCan't use it globally since it destroys checkboxes in Firefox and Opera\n*/\n@media screen and (-webkit-min-device-pixel-ratio:0) {\n\t#toggle-all,\n\t#todo-list li .toggle {\n\t\tbackground: none;\n\t}\n\n\t#todo-list li .toggle {\n\t\theight: 40px;\n\t}\n\n\t#toggle-all {\n\t\ttop: -56px;\n\t\tleft: -15px;\n\t\twidth: 65px;\n\t\theight: 41px;\n\t\t-webkit-transform: rotate(90deg);\n\t\ttransform: rotate(90deg);\n\t\t-webkit-appearance: none;\n\t\tappearance: none;\n\t}\n}\n\n.hidden{\n\tdisplay:none;\n}\n\n.thumbnail img[data-src] {\n  max-width: 100px;\n  max-height: 28px;\n}"
  },
  {
    "path": "_archive/apps/samples/todomvc/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n  <title>ToDoMVC Chrome App</title>\n  <link rel=\"stylesheet\" href=\"bower_components/todomvc-common/base.css\">\n  <link rel=\"stylesheet\" href=\"styles.css\">\n</head>\n<body>\n  <section id=\"todoapp\">\n    <header id=\"header\">\n      <h1>todos</h1>\n      <input id=\"new-todo\" placeholder=\"What needs to be done?\" autofocus>\n    </header>\n    <section id=\"main\">\n      <input id=\"toggle-all\" type=\"checkbox\">\n      <label for=\"toggle-all\">Mark all as complete</label>\n      <ul id=\"todo-list\"></ul>\n    </section>\n    <footer id=\"footer\">\n      <span id=\"todo-count\"></span>\n      <ul id=\"filters\">\n        <li>\n          <a href=\"#/\">All</a>\n        </li>\n        <li>\n          <a href=\"#/active\">Active</a>\n        </li>\n        <li>\n          <a href=\"#/completed\">Completed</a>\n        </li>\n      </ul>\n      <button id=\"clear-completed\">Clear completed</button>\n    </footer>\n  </section>\n  <footer id=\"info\">\n    <button id=\"toggleAlarm\">Activate alarm</button>\n    <button id=\"exportToDisk\">Export to Google Drive</button>\n    <div id=\"status\"></div>\n    <p>Based on <a target=\"_blank\" href=\"http://todomvc.com/\">TODO MVC app</a></p>\n  </footer>\n  <script src=\"bower_components/director/build/director.js\"></script>\n  <script src=\"js/bootstrap.js\"></script>\n  <script src=\"js/helpers.js\"></script>\n  <script src=\"js/store.js\"></script>\n  <script src=\"js/model.js\"></script>\n  <script src=\"js/view.js\"></script>\n  <script src=\"js/controller.js\"></script>\n  <script src=\"js/app.js\"></script>\n  <script src=\"js/alarms.js\"></script>\n  <script src=\"js/export.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/js/alarms.js",
    "content": "(function () {\n  'use strict';\n   var alarmName = 'remindme';\n\n   function checkAlarm(callback) {\n     chrome.alarms.getAll(function(alarms) {\n\n       var hasAlarm = alarms.some(function(a) {\n         return a.name == alarmName;\n       });\n\n       var newLabel;\n       if (hasAlarm) {\n         newLabel = 'Cancel alarm';\n       } else {\n         newLabel = 'Activate alarm';\n       }\n       document.getElementById('toggleAlarm').innerText = newLabel;\n\n       if (callback) callback(hasAlarm);\n     })\n   }\n\n   function createAlarm() {\n     chrome.alarms.create(alarmName, {\n       delayInMinutes: 0.1, periodInMinutes: 0.1});\n   }\n\n   function cancelAlarm() {\n     chrome.alarms.clear(alarmName);\n   }\n\n   function doToggleAlarm() {\n     checkAlarm( function(hasAlarm) {\n       if (hasAlarm) {\n         cancelAlarm();\n       } else {\n         createAlarm();\n       }\n       checkAlarm();\n     });\n   }\n\n  $$('#toggleAlarm').addEventListener('click', doToggleAlarm);\n\n  checkAlarm();\n\n})();\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/js/app.js",
    "content": "/*global Store, Model, View, Controller, $$ */\n(function () {\n\t'use strict';\n\n\t/**\n\t * Sets up a brand new Todo list.\n\t *\n\t * @param {string} name The name of your new to do list.\n\t */\n\tfunction Todo(name) {\n\t\tthis.storage = new app.Store(name);\n\t\tthis.model = new app.Model(this.storage);\n\t\tthis.view = new app.View();\n\t\tthis.controller = new app.Controller(this.model, this.view);\n\t}\n\n\tvar todo = new Todo('todos-vanillajs');\n\n\t/**\n\t * Finds the model ID of the clicked DOM element\n\t *\n\t * @param {object} target The starting point in the DOM for it to try to find\n\t * the ID of the model.\n\t */\n\tfunction lookupId(target) {\n\t\tvar lookup = target;\n\n\t\twhile (lookup.nodeName !== 'LI') {\n\t\t\tlookup = lookup.parentNode;\n\t\t}\n\n\t\treturn lookup.dataset.id;\n\t}\n\n\t// When the enter key is pressed fire the addItem method.\n\t$$('#new-todo').addEventListener('keypress', function (e) {\n\t\ttodo.controller.addItem(e);\n\t});\n\n\t// A delegation event. Will check what item was clicked whenever you click on any\n\t// part of a list item.\n\t$$('#todo-list').addEventListener('click', function (e) {\n\t\tvar target = e.target;\n\n\t\t// If you click a destroy button\n\t\tif (target.className.indexOf('destroy') > -1) {\n\t\t\ttodo.controller.removeItem(lookupId(target));\n\t\t} else if (target.className.indexOf('toggle') > -1) {\n      // If you click the checkmark\n\t\t\ttodo.controller.toggleComplete(lookupId(target), target);\n\t\t}\n\t});\n\n\t// For touch devices, a single touch should start item edit\n\t$$('#todo-list').addEventListener('touchend', function (e) {\n\t\tvar target = e.target;\n\n\t\tif (target.nodeName === 'LABEL') {\n\t\t\ttodo.controller.editItem(lookupId(target), target);\n\t\t}\n  });\n\n\t$$('#todo-list').addEventListener('dblclick', function (e) {\n\t\tvar target = e.target;\n\n\t\tif (target.nodeName === 'LABEL') {\n\t\t\ttodo.controller.editItem(lookupId(target), target);\n\t\t}\n\t});\n\n\n\t$$('#toggle-all').addEventListener('click', function (e) {\n\t\ttodo.controller.toggleAll(e);\n\t});\n\n\t$$('#clear-completed').addEventListener('click', function () {\n\t\ttodo.controller.removeCompletedItems();\n\t});\n})();\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/js/bootstrap.js",
    "content": "    // Bootstrap app data\n    window.app = {};\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/js/controller.js",
    "content": "/*global Router, $$, $ */\n(function (window) {\n  'use strict';\n\n  /**\n   * Takes a model and view and acts as the controller between them\n   *\n   * @constructor\n   * @param {object} model The model constructor\n   * @param {object} view The view constructor\n   */\n  function Controller(model, view) {\n    this.model = model;\n    this.view = view;\n\n    this.ENTER_KEY = 13;\n    this.ESCAPE_KEY = 27;\n\n    this.$main = $$('#main');\n    this.$toggleAll = $$('#toggle-all');\n    this.$todoList = $$('#todo-list');\n    this.$todoItemCounter = $$('#todo-count');\n    this.$clearCompleted = $$('#clear-completed');\n    this.$footer = $$('#footer');\n\n    this.router = new Router();\n    this.router.init();\n\n    window.addEventListener('load', function () {\n      this._updateFilterState();\n    }.bind(this));\n\n    // Couldn't figure out how to get flatiron to run some code on all pages. I\n    // tried '*', but then it overwrites ALL handlers for all the other pages\n    // and only runs this.\n    window.addEventListener('hashchange', function () {\n      this._updateFilterState();\n    }.bind(this));\n\n    // Make sure on page load we start with a hash to trigger the flatiron and\n    // onhashchange routes\n    if (window.location.href.indexOf('#') === -1) {\n      window.location.hash = '#/';\n    }\n  }\n\n  /**\n   * An event to fire on load. Will get all items and display them in the\n   * todo-list\n   */\n  Controller.prototype.showAll = function () {\n    this.model.read(function (data) {\n      this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));\n      this._parseForImageURLs();\n    }.bind(this));\n  };\n\n  /**\n   * Renders all active tasks\n   */\n  Controller.prototype.showActive = function () {\n    this.model.read({ completed: 0 }, function (data) {\n      this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));\n      this._parseForImageURLs();\n    }.bind(this));\n  };\n\n  /**\n   * Renders all completed tasks\n   */\n  Controller.prototype.showCompleted = function () {\n    this.model.read({ completed: 1 }, function (data) {\n      this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));\n      this._parseForImageURLs();\n    }.bind(this));\n  };\n\n  /**\n   * An event to fire whenever you want to add an item. Simply pass in the event\n   * object and it'll handle the DOM insertion and saving of the new item.\n   *\n   * @param {object} e The event object\n   */\n  Controller.prototype.addItem = function (e) {\n    var input = $$('#new-todo');\n    var title = title || '';\n\n    if (e.keyCode === this.ENTER_KEY) {\n      if (e.target.value.trim() === '') {\n        return;\n      }\n\n      this.model.create(e.target.value, function (data) {\n        input.value = '';\n        this._filter(true);\n      }.bind(this));\n    }\n\n  };\n\n\n  /**\n   * Hides the label text and creates an input to edit the title of the item.\n   * When you hit enter or blur out of the input it saves it and updates the UI\n   * with the new name.\n   *\n   * @param {number} id The id of the item to edit\n   * @param {object} label The label you want to edit the text of\n   */\n  Controller.prototype.editItem = function (id, label) {\n    var li =  label;\n\n    // This finds the <label>'s parent <li>\n    while (li.nodeName !== 'LI') {\n      li = li.parentNode;\n    }\n\n    var onSaveHandler = function () {\n      var value = input.value.trim();\n      var discarding = input.dataset.discard;\n\n      if (value.length && !discarding) {\n        this.model.update(id, { title: input.value });\n\n        // Instead of re-rendering the whole view just update\n        // this piece of it\n        label.innerHTML = this._parseForURLs(value);\n        this._parseForImageURLs();\n\n      } else if (value.length === 0) {\n        // No value was entered in the input. We'll remove the todo item.\n        this.removeItem(id);\n      }\n\n      // Remove the input since we no longer need it\n      // Less DOM means faster rendering\n      li.removeChild(input);\n\n      // Remove the editing class\n      li.className = li.className.replace('editing', '');\n\n    }.bind(this);\n\n    // Append the editing class\n    li.className = li.className + ' editing';\n\n    var input = document.createElement('input');\n    input.className = 'edit';\n\n    // Get the innerHTML of the label instead of requesting the data from the\n    // ORM. If this were a real DB this would save a lot of time and would avoid\n    // a spinner gif.\n    input.value = label.innerText;\n\n    li.appendChild(input);\n\n    input.addEventListener('blur', onSaveHandler);\n\n    input.addEventListener('keypress', function (e) {\n      if (e.keyCode === this.ENTER_KEY) {\n        // Remove the cursor from the input when you hit enter just like if it\n        // were a real form\n        input.blur();\n      }\n\n      if (e.keyCode === this.ESCAPE_KEY) {\n        // Discard the changes\n        input.dataset.discard = true;\n        input.blur();\n      }\n    }.bind(this));\n\n    input.focus();\n  };\n\n  /**\n   * By giving it an ID it'll find the DOM element matching that ID,\n   * remove it from the DOM and also remove it from storage.\n   *\n   * @param {number} id The ID of the item to remove from the DOM and\n   * storage\n   */\n  Controller.prototype.removeItem = function (id) {\n    this.model.remove(id, function () {\n      var ids = [].concat(id);\n      ids.forEach( function(id) {\n        this.$todoList.removeChild($$('[data-id=\"' + id + '\"]'));\n      }.bind(this));\n      this._filter();\n    }.bind(this));\n  };\n\n  /**\n   * Will remove all completed items from the DOM and storage.\n   */\n  Controller.prototype.removeCompletedItems = function () {\n    this.model.read({ completed: 1 }, function (data) {\n      var ids = [];\n      data.forEach(function (item) {\n        ids.push(item.id);\n      }.bind(this));\n      this.removeItem(ids);\n    }.bind(this));\n\n    this._filter();\n  };\n\n  /**\n   * Give it an ID of a model and a checkbox and it will update the item\n   * in storage based on the checkbox's state.\n   *\n   * @param {number} id The ID of the element to complete or uncomplete\n   * @param {object} checkbox The checkbox to check the state of complete\n   *                          or not\n   * @param {boolean|undefined} silent Prevent re-filtering the todo items\n   */\n  Controller.prototype.toggleComplete = function (ids, checkbox, silent) {\n    var completed = checkbox.checked ? 1 : 0;\n\n    this.model.update(ids, { completed: completed }, function () {\n      if ( ids.constructor != Array ) {\n        ids = [ ids ];\n      }\n\n      ids.forEach( function(id) {\n        var listItem = $$('[data-id=\"' + id + '\"]');\n\n        if (!listItem) {\n          return;\n        }\n\n        listItem.className = completed ? 'completed' : '';\n\n        // In case it was toggled from an event and not by clicking the checkbox\n        listItem.querySelector('input').checked = completed;\n      });\n\n      if (!silent) {\n        this._filter();\n      }\n\n    }.bind(this));\n  };\n\n  /**\n   * Will toggle ALL checkboxe's on/off state and completeness of models.\n   * Just pass in the event object.\n   *\n   * @param {object} e The event object\n   */\n  Controller.prototype.toggleAll = function (e) {\n    var completed = e.target.checked ? 1 : 0;\n    var query = 0;\n\n    if (completed === 0) {\n      query = 1;\n    }\n\n    this.model.read({ completed: query }, function (data) {\n      var ids = [];\n      data.forEach(function (item) {\n        ids.push(item.id);\n      }.bind(this));\n      this.toggleComplete(ids, e.target, false);\n    }.bind(this));\n\n  };\n\n  /**\n   * Updates the pieces of the page which change depending on the remaining\n   * number of todos.\n   */\n  Controller.prototype._updateCount = function () {\n    this.model.getCount(function(todos) {\n      this.$todoItemCounter.innerHTML = this.view.itemCounter(todos.active);\n\n      this.$clearCompleted.innerHTML = this.view.clearCompletedButton(todos.completed);\n      this.$clearCompleted.style.display = todos.completed > 0 ? 'block' : 'none';\n\n      this.$toggleAll.checked = todos.completed === todos.total;\n\n      this._toggleFrame(todos);\n    }.bind(this));\n\n  };\n\n  /**\n   * The main body and footer elements should not be visible when there are no\n   * todos left.\n   *\n   * @param {object} todos Contains a count of all todos, and their statuses.\n   */\n  Controller.prototype._toggleFrame = function (todos) {\n    var frameDisplay = this.$main.style.display;\n    var frameVisible = frameDisplay === 'block' || frameDisplay === '';\n\n    if (todos.total === 0 && frameVisible) {\n      this.$main.style.display = 'none';\n      this.$footer.style.display = 'none';\n    }\n\n    if (todos.total > 0 && !frameVisible) {\n      this.$main.style.display = 'block';\n      this.$footer.style.display = 'block';\n    }\n  };\n\n  /**\n   * Re-filters the todo items, based on the active route.\n   * @param {boolean|undefined} force  forces a re-painting of todo items.\n   */\n  Controller.prototype._filter = function (force) {\n    var activeRoute = this._activeRoute.charAt(0).toUpperCase() + this._activeRoute.substr(1);\n\n    // Update the elements on the page, which change with each completed todo\n    this._updateCount();\n\n    // If the last active route isn't \"All\", or we're switching routes, we\n    // re-create the todo item elements, calling:\n    //   this.show[All|Active|Completed]();\n    if (force || this._lastActiveRoute !== 'All' || this._lastActiveRoute !== activeRoute) {\n      this['show' + activeRoute]();\n    }\n\n    this._lastActiveRoute = activeRoute;\n  };\n\n  /**\n   * Simply updates the filter nav's selected states\n   */\n  Controller.prototype._updateFilterState = function () {\n    var currentPage = this._getCurrentPage() || '';\n\n    // Store a reference to the active route, allowing us to re-filter todo\n    // items as they are marked complete or incomplete.\n    this._activeRoute = currentPage;\n\n    if (currentPage === '') {\n      this._activeRoute = 'All';\n    }\n\n    this._filter();\n\n    // Remove all other selected states. We loop through all of them in case the\n    // UI gets in a funky state with two selected.\n    $('#filters .selected').each(function (item) {\n      item.className = '';\n    });\n\n    $$('#filters [href=\"#/' + currentPage + '\"]').className = 'selected';\n  };\n\n   /**\n    * A getter for getting the current page\n    */\n  Controller.prototype._getCurrentPage = function () {\n    return document.location.hash.split('/')[1];\n  };\n\n  Controller.prototype._parseForURLs = function (text) {\n    var re = /(https?:\\/\\/[^\\s\"<>,]+)/g;\n    return text.replace(re, '<a href=\"$1\" target=\"_blank\" data-src=\"$1\">$1</a>');\n  };\n\n  Controller.prototype._parseForImageURLs = function () {\n    // remove old blobs to avoid memory leak:\n    this._clearObjectURL();\n\n    var links = this.$todoList.querySelectorAll('a[data-src]:not(.thumbnail)');\n    var re = /\\.(png|jpg|jpeg|svg|gif)$/;\n\n    for (var i = 0; i<links.length; i++) {\n      var url = links[i].getAttribute('data-src');\n      if (re.test(url)) {\n        links[i].classList.add('thumbnail');\n        this._requestRemoteImageAndAppend(url, links[i]);\n      }\n    }\n  };\n\n  Controller.prototype._requestRemoteImageAndAppend = function(imageUrl, element) {\n    var xhr = new XMLHttpRequest();\n    xhr.open('GET', imageUrl);\n    xhr.responseType = 'blob';\n    xhr.onload = function() {\n      var img = document.createElement('img');\n      img.setAttribute('data-src', imageUrl);\n      img.className = 'icon';\n      var objURL = this._createObjectURL(xhr.response);\n      img.setAttribute('src', objURL);\n      element.appendChild(img);\n    }.bind(this);\n    xhr.send();\n  };\n\n  Controller.prototype._clearObjectURL = function() {\n    if (this.objectURLs) {\n      this.objectURLs.forEach(function(objURL) {\n        URL.revokeObjectURL(objURL);\n      });\n      this.objectURLs = null;\n    }\n  };\n\n  Controller.prototype._createObjectURL = function(blob) {\n    var objURL = URL.createObjectURL(blob);\n    this.objectURLs = this.objectURLs || [];\n    this.objectURLs.push(objURL);\n    return objURL;\n  };\n\n  // Export to window\n  window.app.Controller = Controller;\n})(window);\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/js/export.js",
    "content": "(function() {\n\n  var dbName = 'todos-vanillajs';\n\n  var fileSystem;\n\n  var savedFileEntry, fileDisplayPath;\n\n  function getTodosAsText(callback) {\n    chrome.storage.local.get(dbName, function(storedData) {\n      var text = '';\n\n      if ( storedData[dbName].todos ) {\n        storedData[dbName].todos.forEach(function(todo) {\n            text += '- ';\n            if ( todo.completed ) {\n              text += '[DONE] ';\n            }\n            text += todo.title;\n            text += '\\n';\n          }, '');\n      }\n\n      callback(text);\n\n    }.bind(this));\n  }\n\n  // Given a FileEntry,\n  function exportToFileEntry(fileEntry) {\n    savedFileEntry = fileEntry;\n\n    var status = document.getElementById('status'),\n        fileDisplayPath = fileEntry.fullPath;\n\n    status.innerText = 'Exporting to '+fileDisplayPath;\n\n    getTodosAsText( function(contents) {\n\n      fileEntry.createWriter(function(fileWriter) {\n\n        fileWriter.onwriteend = function(e) {\n          status.innerText = 'Export to '+\n               fileDisplayPath+' completed';\n          // You need to explicitly set the file size to truncate\n          // any content that could be there before\n          this.onwriteend = null;\n          this.truncate(e.total);\n        };\n\n        fileWriter.onerror = function(e) {\n          status.innerText = 'Export failed: '+e.toString();\n        };\n\n        var blob = new Blob([contents]);\n        fileWriter.write(blob);\n\n      });\n    });\n\n  }\n\n  function exportToFileSystem(fs) {\n    if (fs) {\n      fileSystem = fs;\n    }\n\n    fs.root.getFile('todomvc.txt', {create: true}, exportToFileEntry);\n\n  }\n\n  function doExportToDisk() {\n\n    if (fileSystem) {\n      exportToFileSystem(fileSystem);\n    }\n      \n    chrome.syncFileSystem.requestFileSystem( exportToFileSystem );\n\n  }\n\n document.getElementById('exportToDisk').\n   addEventListener('click', doExportToDisk);\n\n})()\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/js/helpers.js",
    "content": "(function (window) {\n\t'use strict';\n\n\t// Cache the querySelector/All for easier and faster reuse\n\twindow.$ = document.querySelectorAll.bind(document);\n\twindow.$$ = document.querySelector.bind(document);\n\n\t// Allow for looping on Objects by chaining:\n\t// $('.foo').each(function () {})\n\tObject.prototype.each = function (callback) {\n\t\tfor (var x in this) {\n\t\t\tif (this.hasOwnProperty(x)) {\n\t\t\t\tcallback.call(this, this[x]);\n\t\t\t}\n\t\t}\n\t};\n\n})(window);\n\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/js/model.js",
    "content": "(function (window) {\n  'use strict';\n\n  /**\n   * Creates a new Model instance and hooks up the storage.\n   *\n   * @constructor\n   * @param {object} storage A reference to the client side storage class\n   */\n  function Model(storage) {\n    this.storage = storage;\n  }\n\n  /**\n   * Creates a new todo model\n   *\n   * @param {string} [title] The title of the task\n   * @param {function} [callback] The callback to fire after the model is created\n   */\n  Model.prototype.create = function (title, callback) {\n    title = title || '';\n    callback = callback || function () {};\n\n    var newItem = {\n      title: title.trim(),\n      completed: 0\n    };\n\n    this.storage.save(newItem, callback);\n  };\n\n  /**\n   * Finds and returns a model in storage. If no query is given it'll simply\n   * return everything. If you pass in a string or number it'll look that up as\n   * the ID of the model to find. Lastly, you can pass it an object to match\n   * against.\n   *\n   * @param {string|number|object} [query] A query to match models against\n   * @param {function} [callback] The callback to fire after the model is found\n   *\n   * @example\n   * model.read(1, func); // Will find the model with an ID of 1\n   * model.read('1'); // Same as above\n   * //Below will find a model with foo equalling bar and hello equalling world.\n   * model.read({ foo: 'bar', hello: 'world' });\n   */\n  Model.prototype.read = function (query, callback) {\n    var queryType = typeof query;\n    callback = callback || function () {};\n\n    if (queryType === 'function') {\n      callback = query;\n      return this.storage.findAll(callback);\n    } else if (queryType === 'string' || queryType === 'number') {\n      this.storage.find({ id: query }, callback);\n    } else {\n      this.storage.find(query, callback);\n    }\n  };\n\n  /**\n   * Updates a model by giving it an ID, data to update, and a callback to fire when\n   * the update is complete.\n   *\n   * @param {number} id The id of the model to update\n   * @param {object} data The properties to update and their new value\n   * @param {function} callback The callback to fire when the update is complete.\n   */\n  Model.prototype.update = function (id, data, callback) {\n    this.storage.save(id, data, callback);\n  };\n\n  /**\n   * Removes a model from storage\n   *\n   * @param {number} id The ID of the model to remove\n   * @param {function} callback The callback to fire when the removal is complete.\n   */\n  Model.prototype.remove = function (id, callback) {\n    this.storage.remove(id, callback);\n  };\n\n  /**\n   * WARNING: Will remove ALL data from storage.\n   *\n   * @param {function} callback The callback to fire when the storage is wiped.\n   */\n  Model.prototype.removeAll = function (callback) {\n    this.storage.drop(callback);\n  };\n\n  /**\n   * Returns a count of all todos\n   */\n  Model.prototype.getCount = function (callback) {\n    var todos = {\n      active: 0,\n      completed: 0,\n      total: 0\n    };\n\n    this.storage.findAll(function (data) {\n      data.each(function (todo) {\n        if (todo.completed === 1) {\n          todos.completed++;\n        } else {\n          todos.active++;\n        }\n\n        todos.total++;\n      });\n      if (callback) callback(todos);\n    });\n\n  };\n\n  // Export to window\n  window.app.Model = Model;\n})(window);\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/js/store.js",
    "content": "/*jshint eqeqeq:false */\n(function (window) {\n  'use strict';\n\n  /**\n   * Creates a new client side storage object and will create an empty\n   * collection if no collection already exists.\n   *\n   * @param {string} name The name of our DB we want to use\n   * @param {function} callback Our fake DB uses callbacks because in\n   * real life you probably would be making AJAX calls\n   */\n  function Store(name, callback) {\n    var data;\n    var dbName;\n\n    callback = callback || function () {};\n\n    dbName = this._dbName = name;\n\n    chrome.storage.local.get(dbName, function(storage) {\n      if ( dbName in storage ) {\n        callback.call(this, storage[dbName].todos);\n      } else {\n        storage = {};\n        storage[dbName] = { todos: [] };\n        chrome.storage.local.set( storage, function() {\n          callback.call(this, storage[dbName].todos);\n        }.bind(this));\n      }\n    }.bind(this));\n  }\n\n  /**\n   * Finds items based on a query given as a JS object\n   *\n   * @param {object} query The query to match against (i.e. {foo: 'bar'})\n   * @param {function} callback  The callback to fire when the query has\n   * completed running\n   *\n   * @example\n   * db.find({foo: 'bar', hello: 'world'}, function (data) {\n   *   // data will return any items that have foo: bar and\n   *   // hello: world in their properties\n   * });\n   */\n  Store.prototype.find = function (query, callback) {\n    if (!callback) {\n      return;\n    }\n\n    chrome.storage.local.get(this._dbName, function(storage) {\n      var todos = storage[this._dbName].todos.filter(function (todo) {\n        for (var q in query) {\n          return query[q] === todo[q];\n        }\n      });\n      callback.call(this, todos);\n    }.bind(this));\n  };\n\n  /**\n   * Will retrieve all data from the collection\n   *\n   * @param {function} callback The callback to fire upon retrieving data\n   */\n  Store.prototype.findAll = function (callback) {\n    callback = callback || function () {};\n    chrome.storage.local.get(this._dbName, function(storage) {\n      callback.call(this, storage[this._dbName].todos);\n    }.bind(this));\n  };\n\n  /**\n   * Will save the given data to the DB. If no item exists it will create a new\n   * item, otherwise it'll simply update an existing item's properties\n   *\n   * @param {number} id An optional param to enter an ID of an item to update\n   * @param {object} data The data to save back into the DB\n   * @param {function} callback The callback to fire after saving\n   */\nStore.prototype.save = function (id, updateData, callback) {\n  chrome.storage.local.get(this._dbName, function(storage) {\n    var data = storage[this._dbName];\n    var todos = data.todos;\n\n    callback = callback || function () {};\n\n    // If an ID was actually given, find the item and update each property\n    if (typeof id !== 'object'  || Array.isArray(id) ) {\n      var ids = [].concat( id );\n      ids.forEach(function(id) {\n        for (var i = 0; i < todos.length; i++) {\n          if (todos[i].id == id) {\n            for (var x in updateData) {\n              todos[i][x] = updateData[x];\n            }\n          }\n        }\n      });\n\n      chrome.storage.local.set(storage, function() {\n        chrome.storage.local.get(this._dbName, function(storage) {\n          callback.call(this, storage[this._dbName].todos);\n        }.bind(this));\n      }.bind(this));\n\n    } else {\n      callback = updateData;\n\n      updateData = id;\n\n      // Generate an ID\n      updateData.id = new Date().getTime();\n\n      todos.push(updateData);\n      chrome.storage.local.set(storage, function() {\n        callback.call(this, [updateData]);\n      }.bind(this));\n\n    }\n  }.bind(this));\n};\n\n  /**\n   * Will remove an item from the Store based on its ID\n   *\n   * @param {number} id The ID of the item you want to remove\n   * @param {function} callback The callback to fire after saving\n   */\n  Store.prototype.remove = function (id, callback) {\n    chrome.storage.local.get(this._dbName, function(storage) {\n      var data = storage[this._dbName];\n      var todos = data.todos;\n\n      var ids = [].concat(id);\n      ids.forEach( function(id) {\n        for (var i = 0; i < todos.length; i++) {\n          if (todos[i].id == id) {\n            todos.splice(i, 1);\n            break;\n          }\n        }\n      });\n\n      chrome.storage.local.set(storage, function() {\n        callback.call(this, todos);\n      }.bind(this));\n    }.bind(this));\n  };\n\n  /**\n   * Will drop all storage and start fresh\n   *\n   * @param {function} callback The callback to fire after dropping the data\n   */\n  Store.prototype.drop = function (callback) {\n    localStorage[this._dbName] = JSON.stringify({todos: []});\n    callback.call(this, JSON.parse(localStorage[this._dbName]).todos);\n  };\n\n  // Export to window\n  window.app.Store = Store;\n})(window);\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/js/view.js",
    "content": "/*jshint laxbreak:true */\n(function (window) {\n\t'use strict';\n\n\t/**\n\t * Sets up defaults for all the View methods such as a default template\n\t *\n\t * @constructor\n\t */\n\tfunction View() {\n\t\tthis.defaultTemplate\n\t\t=\t'<li data-id=\"{{id}}\" class=\"{{completed}}\">'\n\t\t+\t\t'<div class=\"view\">'\n\t\t+\t\t\t'<input class=\"toggle\" type=\"checkbox\" {{checked}}>'\n\t\t+\t\t\t'<label>{{title}}</label>'\n\t\t+\t\t\t'<button class=\"destroy\"></button>'\n\t\t+\t\t'</div>'\n\t\t+\t'</li>';\n\t}\n\n\t/**\n\t * Creates an <li> HTML string and returns it for placement in your app.\n\t *\n\t * NOTE: In real life you should be using a templating engine such as Mustache\n\t * or Handlebars, however, this is a vanilla JS example.\n\t *\n\t * @param {object} data The object containing keys you want to find in the\n\t *                      template to replace.\n\t * @returns {string} HTML String of an <li> element\n\t *\n\t * @example\n\t * view.show({\n\t *\tid: 1,\n\t *\ttitle: \"Hello World\",\n\t *\tcompleted: 0,\n\t * });\n\t */\n\tView.prototype.show = function (data) {\n\t\tvar i, l;\n\t\tvar view = '';\n\n\t\tfor (i = 0, l = data.length; i < l; i++) {\n\t\t\tvar template = this.defaultTemplate;\n\t\t\tvar completed = '';\n\t\t\tvar checked = '';\n\n\t\t\tif (data[i].completed === 1) {\n\t\t\t\tcompleted = 'completed';\n\t\t\t\tchecked = 'checked';\n\t\t\t}\n\n\t\t\ttemplate = template.replace('{{id}}', data[i].id);\n\t\t\ttemplate = template.replace('{{title}}', data[i].title);\n\t\t\ttemplate = template.replace('{{completed}}', completed);\n\t\t\ttemplate = template.replace('{{checked}}', checked);\n\n\t\t\tview = view + template;\n\t\t}\n\n\t\treturn view;\n\t};\n\n\t/**\n\t * Displays a counter of how many to dos are left to complete\n\t *\n\t * @param {number} activeTodos The number of active todos.\n\t * @returns {string} String containing the count\n\t */\n\tView.prototype.itemCounter = function (activeTodos) {\n\t\tvar plural = activeTodos === 1 ? '' : 's';\n\n\t\treturn '<strong>' + activeTodos + '</strong> item' + plural + ' left';\n\t};\n\n\t/**\n\t * Updates the text within the \"Clear completed\" button\n\t *\n\t * @param  {[type]} completedTodos The number of completed todos.\n\t * @returns {string} String containing the count\n\t */\n\tView.prototype.clearCompletedButton = function (completedTodos) {\n\t\tif (completedTodos > 0) {\n\t\t\treturn 'Clear completed (' + completedTodos + ')';\n\t\t} else {\n\t\t\treturn '';\n\t\t}\n\t};\n\n\t// Export to window\n\twindow.app.View = View;\n})(window);\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"ToDoMVC\",\n  \"version\": \"1\",\n  \"icons\": {\n    \"128\": \"icon_128.png\"\n  },\n  \"permissions\": [\"storage\", \"alarms\", \"notifications\",\n                  \"<all_urls>\", { \"fileSystem\": [\"write\"]} , \"syncFileSystem\" ],\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"minimum_chrome_version\": \"28\"\n}\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"todomvc\",\n  \"files_with_snippets\": [ ],\n  \"android\": {\"works\": true}\n}\n"
  },
  {
    "path": "_archive/apps/samples/todomvc/styles.css",
    "content": "\nhtml, body {\n  height: 100%;\n}\n\n#todoapp {\n  height: calc( 100% - 200px );\n}\n\n#main {\n  overflow-y: auto;\n  max-height: calc( 100% - 82px );\n}\n\nbutton {\n  cursor: pointer;\n}\n\n#toggleAlarm, #exportToDisk {\n  background: rgba(0, 0, 0, 0.1);\n  font-size: 11px;\n  border-radius: 3px;\n  box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);\n  border: 1px solid;\n  padding: 5px 10px;\n  color: #777;\n}\n\n#toggleAlarm:hover, #exportToDisk:hover {\n  background: rgba(0, 0, 0, 0.15);\n  box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);\n}\n\n#todoapp {\n  margin-top: 70px;\n}\n#todoapp h1 {\n  top: -95px;\n  font-size: 60px;\n}\n\n/* small height, hide status bar and \"based on todomvc\" lines */\n@media (max-height: 460px) {\n  #info > p, #status {\n    display: none;\n  }\n}\n\n/* smaller height, make header and padding smaller */ \n@media (max-height: 390px) {\n  #todoapp {\n    margin-top: 50px;\n  }\n  #todoapp h1 {\n    top: -70px;\n    font-size: 40px;\n  }\n  #todoapp {\n    height: calc( 100% - 145px );\n  }\n\n  #main {\n    overflow-y: auto;\n    max-height: calc( 100% - 82px );\n  }\n  #new-todo {\n    padding: 8px 16px 8px 60px;\n  }\n  #todo-list li.editing .edit {\n    width: auto;\n    padding: 4px 17px 3px 8px;\n    height: auto;\n  }\n  #todo-list li label {\n    padding: 7px;\n  }\n  #todo-list li .destroy:hover {\n    -webkit-transform: none;\n    transform: none;\n  }\n}\n\n/* small width, allow width to adapt */\n@media (max-width: 550px) {\n  body {\n    width: inherit;\n  }\n}\n\n/* small height but not too small width, minimize empty space at the bottom */\n/*@media (min-width: 413px) and (max-height: 460px) {*/\n@media (max-height: 460px) {\n  #todoapp {\n    height: calc( 100% - 170px );\n  }\n\n  #info {\n    margin-top: 60px;\n  }\n}\n\n/* narrow window, make footer actions and indicators vertical */\n@media (max-width: 412px) {\n  #todoapp {\n    margin-bottom: 94px;\n  }\n\n  #footer {\n    height: 65px;\n    bottom: -77px;\n    display: flex !important;\n    flex-direction: column;\n    align-items: center;\n  }\n\n  #filters {\n    position: relative;\n    order: 0;\n  }\n\n  #todo-count {\n    float: none;\n    text-align: center;\n    order: 1;\n  }\n\n  #clear-completed {\n    order: 2;\n  }\n\n  #clear-completed, #todo-count, #filters {\n    flex: 1 1 auto;\n  }\n\n  #footer::before {\n    bottom: 77px;\n    height: 85px;\n    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3), 0 6px 0 -3px rgba(255, 255, 255, 0.8), 0 7px 1px -3px rgba(0, 0, 0, 0.3), 0 87px 0 -6px rgba(255, 255, 255, 0.8), 0 88px 2px -6px rgba(0, 0, 0, 0.2)\n  }\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/tts/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  // Center window on screen.\n  var screenWidth = screen.availWidth;\n  var screenHeight = screen.availHeight;\n  var width = 1024;\n  var height = 768;\n\n  chrome.app.window.create('ttsdemo.html', {\n    id: 'ttsID',\n    outerBounds: {\n      width: width,\n      height: height,\n      left: Math.round((screenWidth-width)/2),\n      top: Math.round((screenHeight-height)/2)\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/tts/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Text-to-Speech Sample\",\n  \"version\": \"1\",\n  \"icons\": {\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\"tts\"]\n}\n"
  },
  {
    "path": "_archive/apps/samples/tts/ttsdemo.css",
    "content": ".banner {\n  width: 100%;\n  float: left;\n}\n\n.banner_left {\n  padding: 8px;\n  float: left;\n}\n\n.banner_right {\n  padding: 8px;\n}\n\nbody {\n  font-family: arial, helvetica, sans-serif;\n}\n\n.body_inner {\n  padding: 0 32px;\n}\n\n.body_left {\n  border: 0;\n  padding: 0;\n  margin: 0;\n  width: 50%;\n  float: left;\n}\n\n.body_right {\n  border: 0;\n  padding: 0;\n  margin: 0;\n  width: 46%;\n  float: left;\n}\n\n.body_wrapper {\n  width: 100%;\n  float: left;\n}\n\n.box {\n  margin: 10px;\n  padding: 10px;\n  border: 1px solid #999;\n}\n\n.busy {\n  background-color: #ffc;\n}\n\n#help {\n  text-align: left;\n}\n\n.large_button {\n  font-size: 166%;\n  padding: 6pt 12pt 6pt 12pt;\n}\n\n#srctext {\n  width: 100%;\n  font-size: 133%;\n}\n\n.tabbable {\n  padding: 10px;\n  border: 1px solid #00C;\n}\n\ntable {\n  margin-left: auto;\n  margin-right: auto;\n}\n\n#voiceInfo {\n  text-align: left;\n  padding: 4px;\n  border: 1px solid #aaa;\n  width: 100%;\n  min-height: 100px;\n  overflow: auto;\n}\n"
  },
  {
    "path": "_archive/apps/samples/tts/ttsdemo.html",
    "content": "<!DOCTYPE html>\r\n<html>\r\n<head>\r\n  <title>Text-to-Speech Sample</title>\r\n  <link href=\"ttsdemo.css\" rel=\"stylesheet\" type=\"text/css\"/>\r\n</head>\r\n\r\n<body>\r\n\r\n<div class=\"banner\">\r\n  <div class=\"banner_left\">\r\n    <img src=\"icon_128.png\" class=\"logo\" alt=\"\">\r\n  </div>\r\n  <div class=\"banner_right\">\r\n    <h1>Text-to-Speech Sample</h1>\r\n    <p>\r\n      Use this application to try out all of the text-to-speech voices in Chrome.\r\n    </p>\r\n  </div>\r\n</div>\r\n\r\n<div class=\"body_wrapper\">\r\n  <div class=\"body_left\">\r\n    <div class=\"body_inner\">\r\n\r\n      Enter text here:\r\n      <textarea id=\"srctext\" rows=\"6\" cols=\"40\">This is a demo of text-to-speech.</textarea>\r\n\r\n      <p>\r\n        <button id=\"speak\" class=\"large_button\">Speak</button>\r\n        <button id=\"stop\" class=\"large_button\" >Stop</button>\r\n      </p>\r\n\r\n      <div class=\"box\" id=\"ttsStatusBox\">\r\n        TTS status: <b><span id=\"ttsStatus\"></span></b>\r\n      </div>\r\n\r\n      <p>\r\n\r\n        Click on or tab to these boxes:\r\n\r\n      <p>\r\n\r\n      <span id=\"alpha\" tabindex=\"0\" class=\"tabbable\">Alpha</span>\r\n      <span id=\"bravo\" tabindex=\"0\" class=\"tabbable\" >Bravo</span>\r\n      <span id=\"charlie\" tabindex=\"0\" class=\"tabbable\" >Charlie</span>\r\n      <span id=\"delta\" tabindex=\"0\" class=\"tabbable\" >Delta</span>\r\n      <span id=\"echo\" tabindex=\"0\" class=\"tabbable\" >Echo</span>\r\n      <span id=\"foxtrot\" tabindex=\"0\" class=\"tabbable\" >Foxtrot</span>\r\n\r\n    </div>\r\n  </div>\r\n  <div class=\"body_right\">\r\n    <div class=\"body_inner\">\r\n\r\n      <table border=\"0\">\r\n        <tr>\r\n        <td>Voice:</td>\r\n        <td><select id=\"voices\">\r\n              <option value=\"\">Unspecified</option>\r\n            </select></td>\r\n        </td>\r\n        </tr>\r\n        <tr>\r\n        <td>Lang:</td>\r\n        <td><select id=\"lang\">\r\n          <option value=\"\">Unspecified</option>\r\n          <option value=\"de\">de (German)</option>\r\n          <option value=\"en-GB\">en-GB (British English)</option>\r\n          <option value=\"en-US\" selected>en-US (American English)</option>\r\n          <option value=\"es\">es (Spanish)</option>\r\n          <option value=\"fr\">fr (French)</option>\r\n          <option value=\"it\">it (Italian)</option>\r\n        </select></td></tr>\r\n        <tr>\r\n        <td>Queuing mode:</td>\r\n        <td><select id=\"enqueue\">\r\n          <option value=\"\">Interrupt</option>\r\n          <option value=\"true\">Enqueue</option>\r\n        </select></td></tr>\r\n        <tr>\r\n        <td>Rate:</td>\r\n        <td><input id=\"rate\" type=\"range\" min=\"0.1\" max=\"10.0\" value=\"1.0\" step=\"0.1\">\r\n        </td></tr>\r\n        <tr>\r\n        <td>Pitch:</td>\r\n        <td><input id=\"pitch\" type=\"range\" min=\"0.0\" max=\"2.0\" value=\"1.0\" step=\"0.1\">\r\n        </td></tr>\r\n        <tr>\r\n        <td>Volume:</td>\r\n        <td><input id=\"volume\" type=\"range\" min=\"0.0\" max=\"1.0\" value=\"1.0\" step=\"0.1\">\r\n        </td></tr>\r\n      </table>\r\n\r\n      <pre id=\"voiceInfo\"></pre>\r\n    </div>\r\n  </div>\r\n</div>\r\n\r\n<script src=\"ttsdemo.js\"></script>\r\n</body>\r\n</html>\r\n"
  },
  {
    "path": "_archive/apps/samples/tts/ttsdemo.js",
    "content": "var voices;\r\nvar utteranceIndex = 0;\r\n\r\nvar enqueue = document.getElementById('enqueue');\r\nvar lang = document.getElementById('lang');\r\nvar pitch = document.getElementById('pitch');\r\nvar rate = document.getElementById('rate');\r\nvar text = document.getElementById('srctext');\r\nvar ttsStatusBox = document.getElementById('ttsStatusBox');\r\nvar ttsStatus = document.getElementById('ttsStatus');\r\nvar voiceInfo = document.getElementById('voiceInfo');\r\nvar voicesSelect = document.getElementById('voices');\r\nvar volume = document.getElementById('volume');\r\n\r\nfunction speak(utterance, highlightText) {\r\n  var options = {\r\n    'enqueue' : Boolean(enqueue.value),\r\n    'lang': lang.value,\r\n    'pitch': Number(pitch.value),\r\n    'rate': Number(rate.value),\r\n    'volume': Number(volume.value),\r\n    'voiceName': voicesSelect.value,\r\n    'onEvent': function(event) {\r\n        console.debug(utteranceIndex, event);\r\n        if (event.type == 'error') {\r\n          console.error(event);\r\n        }\r\n        if (highlightText) {\r\n          text.setSelectionRange(0, event.charIndex);\r\n        }\r\n        if (event.type == 'end' ||\r\n            event.type == 'interrupted' ||\r\n            event.type == 'cancelled' ||\r\n            event.type == 'error') {\r\n          chrome.tts.isSpeaking(function(isSpeaking) {\r\n            if (!isSpeaking) {\r\n              ttsStatus.textContent = 'Idle';\r\n              ttsStatusBox.classList.remove('busy');\r\n            }\r\n          });\r\n        }\r\n    }\r\n  };\r\n  console.debug(++utteranceIndex, options);\r\n  \r\n  chrome.tts.speak(utterance, options);\r\n\r\n  ttsStatus.textContent = 'Busy';\r\n  ttsStatusBox.classList.add('busy');\r\n}\r\n\r\ndocument.getElementById('speak').addEventListener('click', function() {\r\n  speak(text.value, true);\r\n});\r\n\r\ndocument.getElementById('alpha').addEventListener('focus', function() {\r\n  speak('Alpha');\r\n});\r\n\r\ndocument.getElementById('bravo').addEventListener('focus', function() {\r\n  speak('Bravo');\r\n});\r\n\r\ndocument.getElementById('charlie').addEventListener('focus', function() {\r\n  speak('Charlie');\r\n});\r\n\r\ndocument.getElementById('delta').addEventListener('focus', function() {\r\n  speak('Delta');\r\n});\r\n\r\ndocument.getElementById('echo').addEventListener('focus', function() {\r\n  speak('Echo');\r\n});\r\n\r\ndocument.getElementById('foxtrot').addEventListener('focus', function() {\r\n  speak('Foxtrot');\r\n});\r\n\r\ndocument.getElementById('stop').addEventListener('click', function() {\r\n  chrome.tts.stop();\r\n});\r\n\r\nvoicesSelect.addEventListener('change', function() {\r\n  voiceInfo.textContent = '';\r\n  for (var i = 0; i < voices.length; i++) {\r\n    if (voices[i].voiceName === this.value) {\r\n      voiceInfo.textContent = JSON.stringify(voices[i], null, 2);\r\n      break;\r\n    }\r\n  }\r\n});\r\n\r\nchrome.tts.getVoices(function(availableVoices) {\r\n  voices = availableVoices;\r\n  for (var i = 0; i < voices.length; i++) {\r\n    voicesSelect.add(new Option(voices[i].voiceName, voices[i].voiceName));\r\n  }\r\n});\r\n\r\n"
  },
  {
    "path": "_archive/apps/samples/udp/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/okhdmjejphblookgnkabaoaalhcoobec\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# A simple UDP echo client\n\n    ------------------------------\n\n    [127.0.0.1:3007    ] [Connect]\n\n                   **o\n                      ..\n                        .\n\n\n\n    ------------------------------\n\nConnects to a UDP echo server at the given address.\n\nEach little dot represents a echo request.\nWhen the request receives a reply, it shoots away and blows up.\nWhen a request doesn't receive a reply, it grows into a big ball and blows up.\n\nThe dots gravitate towards each other for extra spiffiness.\n\n### Server side\n\nIn the `server` directory, you will find a Node echo server that intentionally drops some packets to simulate a real network. Run this server before, so you can connect the client (Chrome Packaged App) to it.\n\n## APIs\n\n* [UDP Network](http://developer.chrome.com/apps/app_network#udp)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/udp/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/udp/demo.js",
    "content": "var demo = null;\nconsole.debug = function() {};\n\nwindow.addEventListener(\"load\", function() {\n  var connect = document.getElementById(\"connect\");\n  var address = document.getElementById(\"address\");\n\n  var echoClient = newEchoClient(address.value);\n  connect.onclick = function(ev) {\n    echoClient.disconnect();\n    echoClient = newEchoClient(address.value);\n  };\n  address.onkeydown = function(ev) {\n    if (ev.which == 13) {\n      echoClient.disconnect();\n      echoClient = newEchoClient(address.value);\n    }\n  };\n\n  demo = new MCO();\n  demo.init();\n  demo.canvas.style.zIndex = 1;\n\n  setInterval(function(){ \n    if (demo.objects.length < 100) {\n      echoClient.sender();\n    }\n  }, 100);\n\n  setInterval(function(){\n    for (var i = 0; i < demo.objects.length; i++) {\n      demo.objects[i].age += 0.5;\n      demo.objects[i].size += 1;\n      demo.objects[i].mass *= 1.1;\n    }\n  }, 500);\n});\n\nvar newEchoClient = function(address) {\n  var ec = new chromeNetworking.clients.echoClient();\n  ec.sender = attachSend(ec);\n  var hostnamePort = address.split(\":\");\n  var hostname = hostnamePort[0];\n  var port = (hostnamePort[1] || 7) | 0;\n  ec.connect(\n    hostname, port,\n    function() {\n      console.log(\"Connected\");\n    }\n  );\n  return ec;\n};\n\nvar attachSend = function(client) {\n  var i = 1;\n  return function(e) {\n    var data = i;\n    var obj = demo.addObject();\n    i++;\n    client.echo(data, function() {\n      obj.age = 0;\n      obj.size = 2;\n      var d = Math.sqrt(obj.vx*obj.vx+obj.vy*obj.vy);\n      if (d == 0) {\n        obj.vy = -12;\n      } else {\n        obj.vx = obj.vx*12 / d;\n        obj.vy = obj.vy*12 / d;\n      }\n      setTimeout(function() {obj.age = 10;},200);\n    });\n  };\n};\n\n"
  },
  {
    "path": "_archive/apps/samples/udp/echo_mco.html",
    "content": "<html>\n  <head>\n    <title>Echo!</title>\n    <script src=\"networking.js\"></script>\n    <script src=\"raf.js\"></script>\n    <script src=\"mco.js\"></script>\n    <script src=\"demo.js\"></script>\n  </head>\n  <body>\n    <div style=\"position:absolute;z-index:8;top:10px;left:10px;\">\n      <input type=\"text\" id=\"address\" value=\"127.0.0.1:3007\"/>\n      <input type=\"button\" id=\"connect\" value=\"Connect\" />\n      <br>\n      Instructions: now run <code>node dropping-server.js</code> in the <code>server</code> directory\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/udp/main.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('echo_mco.html', {\n  \tid: \"mainwin\",\n    innerBounds: {\n      width: 680,\n      height: 480\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/udp/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Sample of UDP Network Access\",\n  \"description\": \"Echo..... Echo.\",\n  \"version\": \"2.2\",\n  \"minimum_chrome_version\": \"33\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"sockets\": {\n    \"udp\": {\n      \"send\": [\"*\"],\n      \"bind\": [\"*\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/udp/mco.js",
    "content": "MCO = function() {};\n\nMCO.prototype = {\n  intToColor: function(i) {\n    var r = (i >> 16) & 0xff;\n    var g = (i >> 8) & 0xff;\n    var b = (i >> 0) & 0xff;\n    return 'rgb('+r+','+b+','+g+')';\n  },\n  \n  rainbow: function(hue) {\n    return 'hsl('+hue+', 80%, 50%)';\n  },\n  \n  gravity: function(objects, dt) {\n    var minD = 1.5;\n    for (var step=0; step<3; step++) {\n      for (var i=0; i<objects.length; i++) {\n        var o = objects[i];\n        for (var j=i+1; j<objects.length; j++) {\n          var k = objects[j];\n          var dx = k.x-o.x;\n          var dy = k.y-o.y;\n          var dz = k.z-o.z;\n          var d = Math.sqrt(dx*dx+dy*dy+dz*dz);\n          if (d < minD) {\n            var ox = 0.5-Math.random();\n            var oy = 0.5-Math.random();\n            var oz = 0.5-Math.random();\n            var od = Math.sqrt(ox*ox+oy*oy+oz*oz);\n            k.x += minD*ox/od;\n            k.y += minD*oy/od;\n            k.z += minD*oz/od;\n            d = minD;\n          }\n          var F = (o.mass*k.mass*0.1)/(0.5*d*d);\n          var Fx = F * dx/d;\n          var Fy = F * dy/d;\n          var Fz = F * dz/d;\n          o.vx += Fx/o.mass * dt;\n          o.vy += Fy/o.mass * dt;\n          o.vz += Fz/o.mass * dt;\n          k.vx += -Fx/k.mass * dt;\n          k.vy += -Fy/k.mass * dt;\n          k.vz += -Fz/k.mass * dt;\n        }\n      }\n    }\n  },\n  \n  drawRibbon: function(ctx, o) {\n    var d = Math.max(o.size, 6*Math.sqrt(o.vx*o.vx+o.vy*o.vy));\n    var s = o.element.style;\n    s.backgroundColor = o.color;\n    s.webkitTransform = new WebKitCSSMatrix()\n      .translate(o.x, o.y)\n      .rotate(Math.atan2(o.vy, o.vx)*180/Math.PI)\n      .scale(d/10, o.size/10);\n  },\n\n  drawObjects: function(objects, ctx) {\n    for (var i=0; i<objects.length; i++) {\n      var o = objects[i];\n      this.drawRibbon(ctx, o);\n    }\n  },\n\n  drawExplosions: function(explosions, ctx) {\n    for (var i=0; i<explosions.length; i++) {\n      var o = explosions[i];\n      if (!o.element) {\n        o.size = 50;\n        o.vx = o.vy = 0;\n        o.element = this.createElement(o);\n        this.canvas.appendChild(o.element);\n      }\n      this.drawRibbon(ctx, o);\n    }\n  },\n  \n  updateObjects: function(objects, t, dt, explosions, newExplosions, w, h) {\n    for (var i=0; i<objects.length; i++) {\n      var o = objects[i];\n      if (o.age >= 10) {\n        newExplosions.push({x: o.x, y: o.y, color: o.color});\n        this.removeObjectAt(objects, i);\n        i--;\n        continue;\n      }\n      var sz = o.size/2;\n      \n      o.vx *= 0.99;\n      o.vy *= 0.99;\n      o.vz *= 0.99;\n      o.x += o.vx * dt;\n      o.y += o.vy * dt;\n      o.z += o.vz * dt;\n      for (var j=0; j<explosions.length; j++) {\n        var e = explosions[j];\n        var ex = e.x-o.x;\n        var ey = e.y-o.y;\n        var de = Math.sqrt(ex*ex+ey*ey);\n        if (de < 80) {\n          var f = -3;\n          o.vx = f * ex/de;\n          o.vy = f * ey/de;\n        }\n      }\n    }\n  },\n  \n  newObject: function(a,cx,cy) {\n    var obj = {\n      x: Math.cos(a)*100+cx,\n      y: Math.sin(a)*100+cy,\n      z: Math.random()*5,\n      mass: 1,\n      vx: 0,//Math.cos(a)*0.5,\n      vy: 0,//Math.sin(a)*0.5,\n      vz: 0,\n      size: 2,\n      age: 0,\n      sendTime: new Date,\n      color: this.rainbow(360*Math.random())\n    };\n    return obj;\n  },\n\n  createElement: function(obj) {\n    var e = document.createElement('div');\n    e.style.position = 'absolute';\n    e.style.left = '0px';\n    e.style.top = '0px';\n    e.style.borderRadius = '5px';\n    e.style.width = e.style.height = '10px';\n    e.style.backgroundColor = obj.color;\n    return e;\n  },\n\n  addObject: function() {\n    var obj = this.newObject(this.angleC, this.canvas.width/2, this.canvas.height/2);\n    this.angleC += 0.01*2*Math.PI;\n    obj.element = this.createElement(obj);\n    this.drawRibbon(this.ctx, obj);\n    this.canvas.appendChild(obj.element);\n    this.objects.push(obj);\n    return obj;\n  },\n\n  removeObjectAt: function(objects, idx) {\n    var o = objects[idx];\n    o.element.parentNode.removeChild(o.element);\n    objects.splice(idx,1);\n  },\n\n  removeObject: function(obj) {\n    var idx = this.objects.indexOf(obj);\n    if (idx > -1) {\n      this.removeObjectAt(this.objects, idx);\n    }\n    return idx > -1;\n  },\n  \n  init: function() {\n    var c = document.createElement('div');\n    c.style.backgroundColor = 'rgb(255,250,245)';\n    c.width = window.innerWidth;\n    c.height = window.innerHeight;\n    c.style.width = c.width + 'px';\n    c.style.height = c.height + 'px';\n    c.style.position = 'absolute';\n    c.style.overflow = 'hidden';\n    c.style.left = c.style.top = '0px';\n    this.canvas = c;\n    \n    document.body.appendChild(c);\n    \n    this.objects = [];\n    \n    this.angleC = -0.5*Math.PI;\n    \n    this.explosions = [];\n    this.newExplosions = [];\n    \n    this.pt = 0;\n    this.mx = c.width/2;\n    this.my = c.height/2;\n    this.t = 0;\n    this.n = 30;\n\n    var self = this;\n    \n    this.ticker = function(T) { \n      self.tick(T); \n      requestAnimationFrame(self.ticker, self.canvas);\n    };\n    \n    requestAnimationFrame(this.ticker, c);\n  },\n  \n  tick: function(T) {\n    this.t+=16;\n    var dt = Math.min(60, (this.t - this.pt)) / 8;\n    var ctx = this.ctx;\n    var c = this.canvas;\n    this.pt = this.t;\n    while (this.explosions.length > 0) {\n      this.removeObjectAt(this.explosions, 0);\n    }\n    this.explosions.push.apply(this.explosions, this.newExplosions);\n    this.newExplosions.splice(0);\n\n    this.gravity(this.objects, dt);\n    this.updateObjects(this.objects, this.t, dt, this.explosions,this.newExplosions, c.width, c.height);\n\n    this.drawObjects(this.objects, ctx);\n    this.drawExplosions(this.explosions, ctx);\n  }\n\n};\n\n"
  },
  {
    "path": "_archive/apps/samples/udp/networking.js",
    "content": "(function(root) {\n  // Set-up the NameSpace\n  root.chromeNetworking = new (function() {\n    var NoAddressException = \"No Address\";\n    var NotConnectedException = \"Not Connected\";\n\n    var socket = chrome.sockets.udp;\n\n    var baseClient = function() {\n      var address, port;\n      var socketInfo;\n      var connected = false;\n      var callbacks = [];\n      var self = this;\n\n      this.connect = function(inAddress, inPort, callback, responseHandler) {\n        if(!!inAddress == false) throw NoAddressException;\n\n        address = inAddress;\n        port = inPort || this.defaultPort;\n\n        console.debug('creating socket', address, port);\n\n        socket.create({}, function(_socketInfo) {\n          socketInfo = _socketInfo;\n\n          socket.bind(socketInfo.socketId, address, 0, function(connectResult) {\n            connected = (connectResult == 0);\n\n            socket.onReceive.addListener(function(result) {\n              if (callbacks.length > 0) {\n                callbacks.shift()(result);\n              }\n            });\n\n            callback(connected);\n          });\n        });\n      };\n\n      this.send = function(data, callback) {\n        callback = callback || function() {};\n        if(!!address == false) throw NoAddressException;\n        if(connected == false) throw NotConnectedException;\n\n        socket.send(socketInfo.socketId, data, address, port, function(sendResult) {\n          callback(sendResult);\n        });\n      };\n\n      this.receive = function(callback) {\n        if(!!address == false) throw NoAddressException;\n        if(connected == false) throw NotConnectedException;\n        callbacks.push(callback);\n      };\n\n      this.disconnect = function() {\n        if(!!address == false) throw NoAddressException;\n        if(connected == false) throw NotConnectedException;\n\n        socket.close(socketInfo.socketId, function() {\n          connected = false;\n        });\n      };\n    };\n\n    var _EchoClient = function(defaultPort) {\n      return function() {\n        var client = new baseClient();\n        this.defaultPort = defaultPort;\n\n        this.connect = client.connect;\n        this.disconnect = client.disconnect;\n\n        this.callbacks = {};\n        this.echo = function(data, callback) {\n          if (!this.callbacks[data]) {\n            this.callbacks[data] = [];\n          }\n          this.callbacks[data].push(callback);\n          var self = this;\n          client.send(new Uint32Array([data]).buffer, function(sendResult) {\n            console.debug('send', sendResult);\n            client.receive(function(receiveResult) {\n              var u32 = new Uint32Array(receiveResult.data);\n              var m = u32[0];\n              var cbs = self.callbacks[m];\n              if (cbs) {\n                cb = cbs.shift();\n                if (cb) {\n                  cb(receiveResult);\n                }\n              }\n            });\n          });\n        };\n      };\n    };\n\n    return {\n      // Clients\n      clients: {\n        echoClient: _EchoClient(7)\n      },\n      // Exceptions\n      exceptions: {\n        NoAddressException: NoAddressException,\n        NotConnectedException: NotConnectedException\n      }\n    };\n  })();\n})(this);\n"
  },
  {
    "path": "_archive/apps/samples/udp/raf.js",
    "content": "/**\n *  * Provides requestAnimationFrame in a cross browser way.\n *  * http://paulirish.com/2011/requestanimationframe-for-smart-animating/\n *  */\n\nif ( !window.requestAnimationFrame ) {\n\n        window.requestAnimationFrame = ( function() {\n\n                return window.webkitRequestAnimationFrame ||\n                window.mozRequestAnimationFrame || // comment out if FF4 is slow (it caps framerate at ~30fps: https://bugzilla.mozilla.org/show_bug.cgi?id=630127)\n                window.oRequestAnimationFrame ||\n                window.msRequestAnimationFrame ||\n                function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {\n\n                        window.setTimeout( callback, 1000 / 60 );\n\n                };\n\n        } )();\n\n}\n"
  },
  {
    "path": "_archive/apps/samples/udp/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"udp\",\n  \"files_with_snippets\": [ ],\n  \"ios\": {\"works\": true}\n}\n"
  },
  {
    "path": "_archive/apps/samples/udp/server/dropping-server.js",
    "content": "/*\n *  Node.js UDP echo server\n *\n *  This demonstration shows a basic echo server that has randomly drops responses.\n *  The drop factor is `threshold` 0.9 = 90% chance of succes, 10% dropped packets\n * \n *  Additionally each response is delayed by 2-3 seconds.\n * \n *  Listens on port 3007 by default. Pass in a desired port as cmdline argument.\n */\n\nvar dgram = require('dgram');\nvar server = dgram.createSocket('udp4');\n\nvar threshold = 0.99;\n\nserver.on(\"listening\", function() {\n  var address = server.address();\n  console.log(\"Listening on \" + address.address);\n});\n\nserver.on(\"message\", function(message, rinfo) {\n  var delay = 2000+Math.random()*1000;\n  // Echo the message back to the client.\n  var dropped = Math.random();\n  if(dropped > threshold) {\n    console.log(\"Recieved message from: \" + rinfo.address + \", DROPPED\");\n    return;\n  }\n  console.log(\"Recieved message from: \" + rinfo.address);\n  setTimeout(function() {\n    server.send(message, 0, message.length, rinfo.port, rinfo.address, function(err, bytes) {\n      console.log(err, bytes); \n    });\n  }, delay);\n});\n\nserver.on(\"close\", function() {\n  console.log(\"Socket closed\");\n});\n\nvar port = process.argv[2];\nserver.bind(port ? parseInt(port) : 3007);\n"
  },
  {
    "path": "_archive/apps/samples/url-handler/README.md",
    "content": "# URL Handler Sample App\n\nThis is a basic Wikipedia viewer implemented as a packaged app.\n\nChrome 31 introduces a new mechanism to allow apps to intercept navigations to URLs that match a given pattern or patterns.\n\nUsing that mechanism, this sample app intercepts Wikipedia desktop and mobile URLs, normalizes them to the mobile version, and loads the result into a webview.\n\nNote that at least in this initial version of the feature in Chrome 31 stable channel, the Chrome Web Store will reject any apps that attempt to claim URLs not owned by the app's developer (per the Store's definition of ownership and the corresponding verification procedure). That means that this app is for sample purposes only: it can't be uploaded to the Store, however it can be installed locally in developer's mode as unpackaged app.\n\n## Resources\n\n* [url_handlers in manifest](http://developer.chrome.com/apps/manifest/url_handlers)\n* [chrome.app.runtime.onLaunched](https://developer.chrome.com/docs/extensions/reference/app_runtime#event-onLaunched)\n* [webview](https://developer.chrome.com/apps/tags/webview)\n* [chrome.storage](http://developer.chrome.com/apps/storage)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/url-handler/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/url-handler/main.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <title>Wikipedia Viewer Window</title>\n</head>\n<body>\n  <webview id='webview'></webview>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/url-handler/main.js",
    "content": "// Global app's settings.\nvar App = function() {\n  this.defaultSettings = null;\n};\n\nApp.prototype.getSettings_ = function(callback) {\n  if (this.defaultSettings !== null) {\n    callback(this.defaultSettings);\n  } else {\n    chrome.storage.local.get(\n      { width: 600, height: 800 },\n      function(settings) {\n        this.defaultSettings = settings;\n        callback(settings);\n      }.bind(this)\n    );\n  }\n};\n\nApp.prototype.updateSettings_ = function(settings) {\n  this.defaultSettings = settings;\n  // NOTE: The method is asynchronous, but there's no need to wait since\n  // the stored value is used only on app's startup -- the rest of the code uses\n  // the cached value.\n  chrome.storage.local.set(settings);\n};\n\nvar app = new App();\n\n// The app is multi-windowed. This is an object that incapsulates a single\n// window's state.\nvar AppWindow = function(startUrl) {\n  this.startUrl_ = startUrl;\n  this.win_ = null;\n  this.bounds_ = { width: -1, height: -1 };\n  this.webview_ = null;\n\n  app.getSettings_(this.createWindow_.bind(this));\n};\n\n// Create a new window. Defer navigating the webview until the DOM is loaded.\nAppWindow.prototype.createWindow_ = function(settings) {\n  chrome.app.window.create(\n    'main.html',\n    {\n      id: \"mainwin\",\n      innerBounds: { width: settings.width, height: settings.height },\n      frame: 'chrome'\n    },\n    function(win) {\n      this.win_ = win;\n      this.win_.contentWindow.addEventListener('DOMContentLoaded',\n                                               this.onLoad_.bind(this));\n      this.win_.onBoundsChanged.addListener(this.onBoundsChanged_.bind(this));\n    }.bind(this)\n  );\n}\n\n// Resize the window's webview to the window's size and load the start URL.\nAppWindow.prototype.onLoad_ = function() {\n  this.webview_ = this.win_.contentWindow.document.getElementById('webview');\n  this.onBoundsChanged_();\n  this.loadArticle(this.startUrl_);\n}\n\n// Update this window's cached bounds and, if the window has been resized as\n// opposed to just moved, also update the global app's default window size.\nAppWindow.prototype.onBoundsChanged_ = function() {\n  var bounds = this.win_.innerBounds;\n  if (bounds.width !== this.bounds_.width ||\n      bounds.height !== this.bounds_.height) {\n      app.updateSettings_({ width: bounds.width, height: bounds.height });\n  }\n  this.bounds_ = bounds;\n  this.webview_.style.height = bounds.height + 'px';\n  this.webview_.style.width = bounds.width + 'px';\n}\n\n// Navigate the window's webview to an article's URL.\nAppWindow.prototype.loadArticle = function(url) {\n  this.webview_.src = url;\n};\n\n// Create a new app window and load the requested Wikipedia article.\nchrome.app.runtime.onLaunched.addListener(function(launchData) {\n  var articleUrl = null;\n\n  if (launchData.id) {\n    // We are called to handle a URL that matches one of our url_handlers.\n    if (launchData.id === 'wiki_article') {\n      // Convert the desktop URL to a mobile one.\n      articleUrl = launchData.url.replace(\"en.wikipedia\", \"en.m.wikipedia\");\n    } else if (launchData.id === 'mobile_wiki_article') {\n      articleUrl = launchData.url;\n    } else {\n      console.error(\"Unexpected URL handler ID: \" + launchData.id);\n    }\n  } else {\n    articleUrl = \"http://en.m.wikipedia.org\";\n  }\n\n  if (articleUrl)\n    new AppWindow(articleUrl);\n});\n"
  },
  {
    "path": "_archive/apps/samples/url-handler/manifest.json",
    "content": "{\n  \"name\": \"Wikipedia Viewer\",\n  \"version\": \"1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"31.0.1650.4\",\n\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\n        \"main.js\"\n      ]\n    }\n  },\n\n  \"permissions\": [\n    \"webview\",\n    \"storage\"\n  ],\n\n  \"url_handlers\": {\n    \"wiki_article\": {\n      \"title\": \"View Wikipedia article\",\n      \"matches\": [\n        \"*://en.wikipedia.org/wiki/*\"\n      ]\n    },\n    \"mobile_wiki_article\": {\n      \"title\": \"View Wikipedia article\",\n      \"matches\": [\n        \"*://en.m.wikipedia.org/wiki/*\"\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/usb/device-info/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/igkmggljimacfdfalpeelenjeicmfnll\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# USB Device Info Demo\n\nThis app displays information about any device available to Chrome. The\nnew `chrome.usb.getUserSelectedDevices` API is used to request permission\nfor arbitrary devices.\n\n## APIs\n\n* [USB raw access](https://developer.chrome.com/apps/usb)\n* [Runtime](https://developer.chrome.com/apps/runtime)\n* [Window](https://developer.chrome.com/apps/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/usb/device-info/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/usb/device-info/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n    innerBounds: {\n      width: 670,\n      height: 350,\n      minWidth: 670,\n      minHeight: 350\n    },\n    id: \"ChromeApps-Sample-USB-DeviceInfo\"\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/usb/device-info/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>USB Device Info</title>\n    <link rel=\"stylesheet\" href=\"style.css\">\n  </head>\n  <body>\n    <div class=\"left-panel\">\n      <p>Devices:</p>\n      <p>\n        <select id=\"device-selector\" size=\"20\">\n        </select>\n      </p>\n      <p>\n        <button id=\"add-device\">Add Device</button>\n      </p>\n    </div>\n    <p id=\"device-info\">\n      <em>No device selected.</em>\n    </p>\n    <script src=\"script.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/usb/device-info/manifest.json",
    "content": "{\n  \"name\": \"USB Device Info\",\n  \"version\": \"0.6\",\n  \"description\": \"This application displays detailed technical information about USB devices that are connected to your computer.\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"40.0.2213.0\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [\"usb\"],\n  \"icons\": {\n    \"128\": \"assets/icon_128.png\"\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/usb/device-info/script.js",
    "content": "var device_selector = document.getElementById('device-selector');\nvar add_device = document.getElementById('add-device');\nvar device_info = document.getElementById('device-info');\n\nvar devices = {};\n\nfunction appendToDeviceSelector(device) {\n  var el = document.createElement('option');\n  el.setAttribute('value', device.device);\n  el.textContent =\n      'Product 0x' + ('0000' + device.productId.toString(16)).slice(-4) +\n      ' Vendor 0x' + ('0000' + device.vendorId.toString(16)).slice(-4);\n  device_selector.add(el);\n};\n\nfunction appendDeviceInfo(name, value) {\n  var el = document.createElement('b');\n  el.textContent = name + ': '\n  device_info.appendChild(el);\n  device_info.appendChild(document.createTextNode(value));\n  device_info.appendChild(document.createElement('br'));\n}\n\nfunction populateDeviceInfo(handle, callback) {\n  chrome.usb.getConfiguration(handle, function(config) {\n    if (chrome.runtime.lastError != undefined) {\n      var el = document.createElement('em');\n      el.textContent = 'Failed to read device configuration: ' +\n          chrome.runtime.lastError.message;\n      device_info.appendChild(el);\n    } else {\n      var el = document.createElement('h2');\n      el.textContent = 'Configuration ' + config.configurationValue;\n      device_info.appendChild(el);\n\n      for (var iface of config.interfaces) {\n        el = document.createElement('h3');\n        el.textContent = 'Interface ' + iface.interfaceNumber;\n        device_info.appendChild(el);\n\n        appendDeviceInfo('Alternate Setting', iface.alternateSetting);\n        appendDeviceInfo('Inteface Class', iface.interfaceClass);\n        appendDeviceInfo('Interface Subclass', iface.interfaceSubclass);\n        appendDeviceInfo('Interface Protocol', iface.interfaceProtocol);\n\n        for (var endpoint of iface.endpoints) {\n          el = document.createElement('h4');\n          el.textContent = 'Endpoint ' + endpoint.address;\n          device_info.appendChild(el);\n\n          appendDeviceInfo('Type', endpoint.type);\n          appendDeviceInfo('Direction', endpoint.direction);\n          appendDeviceInfo('Maximum Packet Size', endpoint.maximumPacketSize);\n        }\n      }\n    }\n\n    callback();\n  });\n}\n\nfunction deviceSelectionChanged() {\n  device_info.innerHTML = \"\";\n\n  var index = device_selector.selectedIndex;\n  if (index == -1) {\n    var el = document.createElement('em');\n    el.textContent = 'No device selected.';\n    device_info.appendChild(el);\n  } else {\n    var device = devices[device_selector.options.item(index).value];\n\n    appendDeviceInfo(\n        'Product ID',\n        '0x' + ('0000' + device.productId.toString(16)).slice(-4));\n    appendDeviceInfo(\n        'Vendor ID',\n        '0x' + ('0000' + device.vendorId.toString(16)).slice(-4));\n\n    chrome.usb.openDevice(device, function(handle) {\n      if (chrome.runtime.lastError != undefined) {\n        var el = document.createElement('em');\n        el.textContent = 'Failed to open device: ' +\n            chrome.runtime.lastError.message;\n        device_info.appendChild(el);\n      } else {\n        populateDeviceInfo(handle, function () {\n          chrome.usb.closeDevice(handle);\n        });\n      }\n    });\n  }\n}\n\nchrome.usb.getDevices({}, function(found_devices) {\n  if (chrome.runtime.lastError != undefined) {\n    console.warn('chrome.usb.getDevices error: ' +\n                 chrome.runtime.lastError.message);\n    return;\n  }\n\n  for (var device of found_devices) {\n    devices[device.device] = device;\n    appendToDeviceSelector(device);\n  }\n});\n\nif (chrome.usb.onDeviceAdded) {\n  chrome.usb.onDeviceAdded.addListener(function (device) {\n    devices[device.device] = device;\n    appendToDeviceSelector(device);\n  });\n}\n\nif (chrome.usb.onDeviceRemoved) {\n  chrome.usb.onDeviceRemoved.addListener(function (device) {\n    delete devices[device.device];\n    for (var i = 0; i < device_selector.length; ++i) {\n      if (device_selector.options.item(i).value == device.device) {\n        device_selector.remove(i);\n        deviceSelectionChanged();\n        break;\n      }\n    }\n  });\n}\n\nadd_device.addEventListener('click', function() {\n  chrome.usb.getUserSelectedDevices({\n    'multiple': false\n  }, function(selected_devices) {\n    if (chrome.runtime.lastError != undefined) {\n      console.warn('chrome.usb.getUserSelectedDevices error: ' +\n                   chrome.runtime.lastError.message);\n      return;\n    }\n\n    for (var device of selected_devices) {\n      var deviceInfo = { 'device': device, 'index': undefined };\n      if (device.device in devices) {\n        for (var i = 0; i < device_selector.length; ++i) {\n          if (device_selector.options.item(i).value == device.device) {\n            device_selector.selectedIndex = i;\n            break;\n          }\n        }\n      } else {\n        devices[device.device] = device;\n        appendToDeviceSelector(device);\n        device_selector.selectedIndex = device_selector.options.length - 1;\n      }\n      deviceSelectionChanged();\n    }\n  });\n});\n\ndevice_selector.addEventListener('input', deviceSelectionChanged);\n"
  },
  {
    "path": "_archive/apps/samples/usb/device-info/style.css",
    "content": "html {\n  height: 100%;\n}\n\nbody {\n  margin: 0px auto;\n  overflow-y: scroll;\n  height: 100%;\n}\n\nh3 {\n  border-bottom: 1px solid;\n}\n\np {\n  margin: 8px;\n}\n\n#device-info {\n  margin-left: 216px;\n}\n\n.left-panel {\n  position: absolute;\n}\n\n#device-selector {\n  width: 200px;\n  height: 283px;\n}\n"
  },
  {
    "path": "_archive/apps/samples/usb/knob/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/npiachjbcianljljdlckbnkilpnddnfn\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Griffin PowerMate knob\n\nThis demo interfaces with a [Griffin PowerMate](http://en.wikipedia.org/wiki/Griffin_PowerMate) device, reading its position and displaying it via a Chrome logo. It does not currently work on Mac OS X, since on that platform the OS claims the PowerMate is an HID device, and does not allow raw USB access to it.\n\n## APIs\n\n* [USB raw access](https://developer.chrome.com/apps/usb)\n* [Runtime](https://developer.chrome.com/apps/runtime)\n* [Window](https://developer.chrome.com/apps/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/usb/knob/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/usb/knob/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('knob.html', {\n    innerBounds: {\n      width: 400,\n      height: 400\n    },\n    id: \"ChromeApps-Sample-USB-Knob\"\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/usb/knob/knob.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Knob Control</title>\n    <style>\n      #knob {\n        background-image: url(chrome-logo.svg);\n        background-size: contain;\n        background-repeat: no-repeat;\n        background-position: center;\n        width: 100%;\n        height: 100%;\n        position: fixed;\n      }\n    </style>\n  </head>\n  <body>\n    <button id=\"requestPermission\">Request permissions</button>\n    <div id=\"knob\" style=\"display: none;\"></div>\n    <script src=\"knob.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/usb/knob/knob.js",
    "content": "var POWERMATE_VENDOR_ID = 1917; //0x077d;\nvar POWERMATE_PRODUCT_ID = 1040; //0x0410;\nvar DEVICE_INFO = {\"vendorId\": POWERMATE_VENDOR_ID, \"productId\": POWERMATE_PRODUCT_ID};\n\nvar powerMateDevice;\nvar knob = document.getElementById('knob');\nvar requestButton = document.getElementById(\"requestPermission\");\n\nvar amount = 0;\nvar ROTATE_DEGREE = 4;\n\nvar transfer = {\n  direction: 'in',\n  endpoint: 1,\n  length: 6\n};\n\nvar onEvent = function(usbEvent) {\n    \n    if (usbEvent.resultCode) {\n      console.log(\"Error: \" + usbEvent.error);\n      return;\n    }\n\n    var dv = new DataView(usbEvent.data);\n    var knobState = {\n      _ledStatus: dv.getUint8(4),\n      buttonState: dv.getUint8(0),\n      knobDisplacement: dv.getInt8(1),\n      ledBrightness: dv.getUint8(3),\n      pulseEnabled: (dv.getUint8(4) & 1) == 1,\n      pulseWhileAsleep: (dv.getUint8(4) & 4) == 4,\n      pulseSpeed: null,\n      pulseStyle: null,\n      ledMultiplier: dv.getUint8(5)\n    };\n\n    knobState.pulseSpeed = pulseDescriptionFromStatusByte(\n      knobState, [\"slower\", \"normal\", \"faster\"], 4);\n\n    knobState.pulseStyle = pulseDescriptionFromStatusByte(\n      knobState, [\"style1\", \"style2\", \"style3\"], 6);\n\n    var transform = '';\n    if (knobState.buttonState == 1) {\n      transform = 'scale(0.5) ';\n    }\n\n    amount += (knobState.knobDisplacement * ROTATE_DEGREE);\n    transform += 'rotate(' + amount + 'deg)';\n    knob.style.webkitTransform = transform;\n    \n    console.log(\"RotateEvent\", knobState);\n\n    chrome.usb.interruptTransfer(powerMateDevice, transfer, onEvent);\n  };\n\nvar pulseDescriptionFromStatusByte = function(knobState, descriptions, offset) {\n    if(descriptions && offset >= 0 && offset < 8) {\n      var index = (knobState._ledStatus >> offset) & 3;\n      if(descriptions.length > index) {\n        return descriptions[index];\n      }\n    }\n\n    return \"unknown\";\n  };\n\nvar gotPermission = function(result) {\n    requestButton.style.display = 'none';\n    knob.style.display = 'block';\n    console.log('App was granted the \"usbDevices\" permission.');\n    chrome.usb.findDevices( DEVICE_INFO,\n      function(devices) {\n        if (!devices || !devices.length) {\n          console.log('device not found');\n          return;\n        }\n        console.log('Found device: ' + devices[0].handle);\n        powerMateDevice = devices[0];\n        chrome.usb.interruptTransfer(powerMateDevice, transfer, onEvent);\n    });\n  };\n\nvar permissionObj = {permissions: [{'usbDevices': [DEVICE_INFO] }]};\n\nrequestButton.addEventListener('click', function() {\n  chrome.permissions.request( permissionObj, function(result) {\n    if (result) {\n      gotPermission();\n    } else {\n      console.log('App was not granted the \"usbDevices\" permission.');\n      console.log(chrome.runtime.lastError);\n    }\n  });\n});\n\nchrome.permissions.contains(permissionObj, function(result) {\n  if (result) {\n    gotPermission();\n  }\n});\n\nfunction setLEDBrightness(brightness) {\n  if ((brightness >= 0) && (brightness <= 255)) {\n    var info = {\n      \"direction\": \"out\",\n      \"endpoint\": 2,\n      \"data\": new Uint8Array([brightness]).buffer\n    };\n    chrome.usb.interruptTransfer(powerMateDevice, info, sendCompleted);\n  } else {\n    console.error(\"Invalid brightness setting (0-255)\", brightness);\n  }\n}\n\nfunction enablePulse(val) {\n  if (val === true) {\n    sendCommand(1, 3, 1);\n  } else {\n    sendCommand(1, 3, 0);\n  }\n}\n\nfunction enablePulseDuringSleep(val) {\n  if (val === true) {\n    sendCommand(1, 2, 1);\n  } else {\n    sendCommand(1, 2, 0);\n  }\n}\n\nfunction sendCommand(request, val, idx) {\n  var ti = {\n    \"requestType\": \"vendor\",\n    \"recipient\": \"interface\",\n    \"direction\": \"out\",\n    \"request\": request,\n    \"value\": val,\n    \"index\": idx,\n    \"data\": new ArrayBuffer(0)\n  };\n  chrome.usb.controlTransfer(powerMateDevice, ti, sendCompleted);\n}\n\nfunction sendCompleted(usbEvent) {\n  if (chrome.runtime.lastError) {\n    console.error(\"sendCompleted Error:\", chrome.runtime.lastError);\n  }\n\n  if (usbEvent) {\n    if (usbEvent.data) {\n      var buf = new Uint8Array(usbEvent.data);\n      console.log(\"sendCompleted Buffer:\", usbEvent.data.byteLength, buf);\n    }\n    if (usbEvent.resultCode !== 0) {\n      console.error(\"Error writing to device\", usbEvent.resultCode);\n    }\n  }\n}\n\n\n/* some fun commands to try:\n *   sendCommand(1, 0x0104, 0x3002) // fast flashing\n *   sendCommand(1, 0x0104, 0xff02) // fastest flashing possible\n *   sendCommand(1, 0x0104, 0xff01) // normal speed flashing\n *   sendCommand(1, 0x0104, 0x0f00) // super slow flashing\n */"
  },
  {
    "path": "_archive/apps/samples/usb/knob/manifest.json",
    "content": "{\n  \"name\": \"USB Spinner Sample\",\n  \"version\": \"0.3\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"23\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [\"usb\"],\n  \"optional_permissions\": [ {\"usbDevices\": [{\"vendorId\": 1917, \"productId\": 1040}]}]\n}\n"
  },
  {
    "path": "_archive/apps/samples/usb-label-printer/LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "_archive/apps/samples/usb-label-printer/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/fgnncpfphbgfchijmoopegkdhihegfla\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\nlabel-printer-app\n=================\n\nChrome packaged app for a simple label generator with printer support for Dymo 450 LabelWriter.\n\nCode originally created by Marjin Kruisselbrink (@mkruisselbrink).\n\n### Other printers\n\nIf you want to reuse this code for other LabelWriter printers, you might be able to do it if they use the same protocol.\n\nFor example, for Dymo 450 Turbo, you need to change:\n\n- index.js\n<pre>\nvar productId = 0x0021; // changed from 0x0020\n</pre>\n\n- manifest.json\n<pre>\n\"optional_permissions\": [ {\"usbDevices\": [{\"vendorId\": 2338, \"productId\": 33}]}] // changed from 32\n</pre>\n\n(thanks @kjantzer for the [information](https://github.com/GoogleChrome/chrome-app-samples/issues/126#issuecomment-29547981))\n\n### Windows issues\n\nSome Windows device drivers take ownership of the device and don't allow Chrome to connect to them. If openDevice or findDevice doesn't work for you, you can try to use a generic low level driver instead.\nFor more info, check this [chrome-app-samples issue](https://github.com/GoogleChrome/chrome-app-samples/issues/203).\n\nLICENSE\n=======\n\nCopyright 2013 Google Inc. All Rights Reserved.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n## Screenshot\n![screenshot](/_archive/apps/samples/usb-label-printer/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/usb-label-printer/dettach_kernel_driver.py",
    "content": "# not required for ChromeOS. May be required for other operational systems, like Linux or Mac\nimport usb\n\ndev = usb.core.find(idVendor=0x0922, idProduct=0x0020)\n\ndev.detach_kernel_driver(0)\n\n"
  },
  {
    "path": "_archive/apps/samples/usb-label-printer/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <link href=\"styles/main.css\" rel=\"stylesheet\">\n</head>\n<body>\n<h1>Label maker</h1>\n<div class=\"settings\">\n  <div>Page width: <input type=\"text\" id=\"pageWidth\" value=\"900\"> Page height: <input type=\"text\" id=\"pageHeight\" value=\"304\"></div>\n</div>\n<div class=\"controls\">\n  <button id=\"print\">Print</button>\n  <button id=\"previewBtn\">Preview dithering</button>\n</div>\n<div class=\"preview\">\n  <div class=\"photooverlay\">\n    <div>\n      <button id=\"camera\"><img src='camera.svg' width='64px'></img></button>\n      <button id=\"setImage\"><img src='upload.svg' width='64px'></img></button>\n    </div>\n    <video id=\"video\"></video>\n  </div>\n  <div class=\"content\">\n     <input type=\"text\" id=\"name\" value=\"Your name here\">\n     <input type=\"text\" id=\"nick\" value=\"nick\">\n  </div>\n  <canvas id=\"previewCanvas\" width=900 height=304></canvas>\n  <canvas id=\"ditheredCanvas\" width=900 height=304></canvas>\n  <canvas id=\"tempCanvas\" style=\"display:none;\" width=500 height=300></canvas>\n</div>\n<script src=\"index.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/usb-label-printer/index.js",
    "content": "var vendorId = 0x0922;\nvar productId = 0x0020;\n\nvar ESC = 0x1B;\nvar SYN = 0x16;\n\nvar pageWidth = 304;  // pixels (must be multiple of 8)\nvar pageHeight = 900; // pixels\n\n\nvar $ = function(id) { return document.getElementById(id); };\nvar $$ = function(selector) { return document.querySelector(selector); };\n\nvar resetSequence = // 156 times ESC\n   [ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC,\n    ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC,\n    ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC,\n    ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC,\n    ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC,\n    ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC,\n    ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC,\n    ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC,\n    ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC,\n    ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC,\n    ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC,\n    ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC,\n    ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC];\n\n// should set the resolution to 204x204ppi, but the resolution I get is more\n// like 290x580, not sure what's up with that.\nvar setResolution = [ESC, 0x79];\n// some more seemingly required setup stuff\nvar tabData = [ESC, 0x51, 0, 0, ESC, 42, 0];\nvar qualityData = [ESC, 0x69]; // images\nvar densityData = [ESC, 0x65]; // normal\nvar lengthData = [ESC, 0x4C,  0x40, 0x00]; // not sure what this is about...\n\nvar startDoc = resetSequence.concat(setResolution, tabData, qualityData,\n                                    densityData, lengthData);\nvar endDoc = [ESC, 0x45]; // Form feed\n\nvar logoImg = new Image();\nlogoImg.src = \"chrome_logo.png\";\n\n\nfunction requestPermission(callback) {\n  chrome.permissions.request(\n    {permissions: [{'usbDevices': [{\"vendorId\": vendorId, \"productId\": productId}] }]}\n    , function(result) {\n    if (result) {\n      callback();\n    } else {\n      console.log('App was not granted the \"usbDevices\" permission.');\n      console.log(chrome.runtime.lastError);\n    }\n  });\n}\n\n\nfunction printCanvas() {\n  var onDeviceFound = function(devices) {\n    if (devices && devices.length>0) {\n      device = devices[0];\n      console.log(\"Device found: \" + device.handle);\n\n      var ctx = document.getElementById('ditheredCanvas').getContext('2d');\n      var img = ctx.getImageData(0, 0, pageHeight, pageWidth);\n\n      var dataBytesPerLine = pageWidth / 8;\n\n      // every row of the image results in 2 rows of pixels to be printed, both\n      // with one extra byte in front of it\n      var bytesPerRow = (dataBytesPerLine + 1) * 2;\n\n      var bytesForImage = bytesPerRow * pageHeight;\n      // Total size is the size of all the data + the prefix and suffix\n      // and 3 bytes to set the line size\n      var totalDataSize = bytesForImage + startDoc.length + endDoc.length + 3;\n\n      var data = new ArrayBuffer(totalDataSize);\n      var dataView = new Uint8Array(data, 0, totalDataSize);\n\n      // Set beginning data\n      dataView.set(startDoc, 0);\n      var offset = startDoc.length;\n      // Set Bytes Per Line\n      dataView.set([ESC, 0x44, dataBytesPerLine], offset);\n      offset += 3;\n\n      for (var x = 0; x < img.width; x++) {\n        var off1 = offset;\n        var off2 = offset + dataBytesPerLine + 1;\n        dataView[off1++] = SYN;\n        dataView[off2++] = SYN;\n        for (var y = 0; y < img.height; y += 8) {\n          var cur1 = 0;\n          var cur2 = 0;\n          for (var bit = 0; bit < 8; bit++) {\n            cur1 = cur1 << 1;\n            cur2 = cur2 << 1;\n            var i = ((img.height - (y+bit) - 1) * img.width + x) * 4;\n            // convert color to greyscale\n            var color = (0.2126 * img.data[i] + 0.7152 * img.data[i+1] + 0.0722 * img.data[i+2]);\n            // we want higher numbers to be darker colors\n            color = 255 - color;\n            // multiple color by alpha channel\n            color = color * img.data[i+3] / 255;\n            // set 0 1 or both bits depending on color\n            if (color > 170) {\n              cur1 |= 1; cur2 |= 1;\n            } else if (color > 85) {\n              // for grey, alternate which of the two bits we set\n              if (bit & 1) cur1 |= 1; else cur2 |= 1;\n            }\n          }\n          dataView[off1++] = cur1;\n          dataView[off2++] = cur2;\n        }\n        offset = off2;\n      }\n\n      // Set end data\n      dataView.set(endDoc, offset);\n\n      var info = {\n        \"direction\": \"out\",\n        \"endpoint\": 2, // 2 is the Bulk OUT Endpoint. You may use chrome.usb.listInterfaces to figure which address to use for Outputing data.\n        \"data\": data\n      };\n      chrome.usb.claimInterface(device, 0, function() {\n        if (chrome.runtime.lastError) {\n          console.error(chrome.runtime.lastError);\n          return;\n        }\n        chrome.usb.bulkTransfer(device, info, function(transferResult) {\n          console.log(\"Send data\", transferResult);\n          chrome.usb.releaseInterface(device, 0, function() {\n            if (chrome.runtime.lastError)\n              console.error(chrome.runtime.lastError);\n          });\n        });\n      });\n    } else {\n      console.log(\"Device not found\");\n    }\n  }\n\n  // var onUsbEvent = function(event) {\n  //   console.log(\"USB event! \" + event.resultCode + \" \" + event.data + \" \" + event.data.byteLength);\n  //   var dataView = new Uint8Array(event.data, 0, 7);\n  //   console.log(\"Data: \" + dataView[0] + \", \" + dataView[1] + \", \" + dataView[2] + \", \" + dataView[3] + \", \" + dataView[4] + \", \" + dataView[5] + \", \" + dataView[6]);\n  // }\n\n  chrome.usb.findDevices( {\"vendorId\": vendorId, \"productId\": productId}, onDeviceFound);\n\n}\n\nfunction toGreyScale(imgData) {\n  for (var y = 0; y < imgData.height; y++) {\n    for (var x = 0; x < imgData.width; x++) {\n      var i = (y * imgData.width + x) * 4;\n      var color = (0.2126 * imgData.data[i] + 0.7152 * imgData.data[i+1] + 0.0722 * imgData.data[i+2]);\n      imgData.data[i] = color;\n      imgData.data[i+1] = color;\n      imgData.data[i+2] = color;\n      imgData.data[i+3] = 255;\n    }\n  }\n}\n\nfunction ditherImg(imgData) {\n  var offsets = [1, 2, imgData.width-1, imgData.width, imgData.width+1, 2*imgData.width];\n  var imgSize = 4* imgData.width * imgData.height;\n  for (var y = 0; y < imgData.height; y++) {\n    for (var x = 0; x < imgData.width; x++) {\n      var i = (y * imgData.width + x) * 4;\n      var color = imgData.data[i];\n      var ocolor;\n      if (color > 170) {\n        ocolor = 255;\n      } else if (color > 85) {\n        ocolor = 128;\n      } else {\n        ocolor = 0;\n      }\n      imgData.data[i] = ocolor;\n      imgData.data[i+1] = ocolor;\n      imgData.data[i+2] = ocolor;\n      var diff = ocolor - color;\n      // if diff > 0, ocolor is higher than color, so subtract it from neighbours\n      var delta = Math.round(diff / 8);\n      for (o in offsets) {\n        var j = i + 4*o;\n        // should make sure this didn't wrap around\n        if (j < imgSize) {\n          var c = imgData.data[j] - delta;\n          if (c < 0) c = 0;\n          if (c > 255) c = 255;\n          imgData.data[j] = c;\n        }\n      }\n    }\n  }\n}\n\n  var dither = function() {\n    var ictx = $(\"previewCanvas\").getContext('2d');\n    var octx = $(\"ditheredCanvas\").getContext('2d');\n    var img = ictx.getImageData(0, 0, pageHeight, pageWidth);\n    toGreyScale(img);\n    ditherImg(img);\n    octx.putImageData(img, 0, 0);\n  };\n\n  var print = function() {\n    updateCanvas();\n    dither();\n    requestPermission(printCanvas);\n  }\n\n  var preview = function() {\n    updateCanvas();\n    var ictx = $(\"previewCanvas\").getContext('2d');\n    var img = ictx.getImageData(0, 0, pageHeight, pageWidth);\n    toGreyScale(img);\n    ditherImg(img);\n    ictx.putImageData(img, 0, 0);\n  }\n\n  var updateCanvas = function(e) {\n    var canvas = $(\"previewCanvas\");\n    var ctx = canvas.getContext('2d');\n    ctx.fillStyle = \"#fff\";\n    ctx.fillRect(0, 0, pageHeight, pageWidth);\n    ctx.fillStyle = \"#000\";\n    var img = logoImg;\n    var scale = 1;\n    if (img.height > pageWidth) {\n      scale = pageWidth / img.height;\n    }\n    var y = 0;\n    if (img.height < pageWidth) {\n      y = (pageWidth - img.height) / 2;\n    }\n    ctx.font = \"64px sans-serif\";\n    var nameSize = ctx.measureText($(\"name\").value);\n    ctx.font = \"48px sans-serif\";\n    var nickSize = ctx.measureText($(\"nick\").value);\n    var textX;\n    if (img.width * scale > 2*(pageHeight / 5)) {\n      textX = (pageHeight - nameSize.width) / 2;\n\n      ctx.globalAlpha = 0.6;\n      ctx.drawImage(img, 0, 0, img.width, img.height, (pageHeight - (scale * img.width)) / 2, y, img.width*scale, img.height*scale);\n      ctx.globalAlpha = 1.0;\n      ctx.font = \"64px sans-serif\";\n      ctx.fillText($(\"name\").value, textX, pageWidth / 2);\n      ctx.font = \"48px sans-serif\";\n      ctx.fillText($(\"nick\").value, textX, pageWidth / 2 + 64);\n    } else {\n      textX = img.width * scale + 16;\n      ctx.drawImage(img, 0, 0, img.width, img.height, 0, y, img.width*scale, img.height*scale);\n      ctx.font = \"64px sans-serif\";\n      ctx.fillText($(\"name\").value, textX, pageWidth / 2);\n      ctx.font = \"48px sans-serif\";\n      ctx.fillText($(\"nick\").value, textX, pageWidth / 2 + 64);\n    }\n      $(\"name\").style.left = (Math.round(textX)+24)+'px';\n      $(\"nick\").style.left = (Math.round(textX)+24)+'px';\n      $$(\".photooverlay\").style.width = (img.width*scale)+'px';\n  };\n\n  logoImg.onload = updateCanvas;\n\n  var selectImage = function(e) {\n    chrome.fileSystem.chooseEntry({'acceptsAllTypes': false,\n                                  'accepts': [{'mimeTypes': ['image/*']}],\n                                  'type': 'openFile'}, function(fileEntry) {\n      if (!fileEntry || !fileEntry.file) return;\n      fileEntry.file(function(file) {\n        console.log(\"Success: \" + file);\n        var reader = new FileReader();\n        reader.onload = function(e) {\n          logoImg.src = e.target.result;\n        };\n        reader.readAsDataURL(file);\n      }, function(error) {\n        console.log(\"Error: \" + error.code);\n      });\n    });\n  };\n\n  var stream;\n  var width = 280, height = 0;\n  var tempCanvas = $('tempCanvas');\n  var video = $('video');\n  var startTakePicture = function(e) {\n    navigator.webkitGetUserMedia({audio: false, video: true}, function(videoStream) {\n      stream = videoStream;\n      video.src = webkitURL.createObjectURL(stream);\n      video.style.display = 'block';\n      video.play();\n    }, function(e) {\n      console.error(e);\n    });\n  };\n\n  $('camera').addEventListener('click', startTakePicture);\n\n  video.addEventListener('loadedmetadata', function(ev){\n    height = video.videoHeight / (video.videoWidth/width);\n    video.setAttribute('width', width);\n    video.setAttribute('height', height);\n    tempCanvas.setAttribute('width', width);\n    tempCanvas.setAttribute('height', height);\n  }, false);\n\n\n  var takePicture = function() {\n    stream.stop();\n    video.style.display = 'none';\n    tempCanvas.width = width;\n    tempCanvas.height = height;\n    tempCanvas.getContext('2d').drawImage(video, 0, 0, width, height);\n    var data = tempCanvas.toDataURL('image/png');\n    logoImg.src=data;\n  };\n\n  video.addEventListener('click', takePicture);\n\n\n\n  var updateCanvasSize = function(e) {\n    var curWindow = chrome.app.window.current();\n    var canvas = $(\"previewCanvas\");\n    pageHeight = parseInt($('pageWidth').value, 10);\n    pageWidth = parseInt($('pageHeight').value, 10);\n    if (pageWidth % 8 != 0) {\n      pageWidth = pageWidth + 8 - pageWidth % 8;\n    }\n    $('pageWidth').value=pageHeight;\n    $('pageHeight').value=pageWidth;\n    canvas.setAttribute('width', pageHeight);\n    canvas.setAttribute('height', pageWidth);\n    updateCanvas();\n\n    curWindow.outerBounds.width = Math.max(1030, pageHeight + 130);\n    curWindow.outerBounds.height = pageWidth + 400;\n  };\n\n\nwindow.addEventListener('DOMContentLoaded', function() {\n  $('name').addEventListener('change', updateCanvas);\n  $('nick').addEventListener('change', updateCanvas);\n  $('print').addEventListener('click', print);\n  $('previewBtn').addEventListener('click', preview);\n  $('setImage').addEventListener('click', selectImage);\n  $('pageHeight').addEventListener('change', updateCanvasSize);\n  $('pageWidth').addEventListener('change', updateCanvasSize);\n  updateCanvas();\n});\n"
  },
  {
    "path": "_archive/apps/samples/usb-label-printer/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see http://developer.chrome.com/apps/experimental.app.html\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function(data) {\n  // App Launched\n  chrome.app.window.create('index.html',\n    { id: 'main',\n      innerBounds: {width: 1030, height: 704}\n    });\n});\n"
  },
  {
    "path": "_archive/apps/samples/usb-label-printer/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Label USB Printer Sample\",\n  \"version\": \"2.2\",\n  \"minimum_chrome_version\": \"25\",\n  \"icons\": {\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\"usb\", \"fileSystem\", \"videoCapture\"],\n  \"optional_permissions\": [ {\"usbDevices\": [{\"vendorId\": 2338, \"productId\": 32}]}]\n\n}\n"
  },
  {
    "path": "_archive/apps/samples/usb-label-printer/styles/main.css",
    "content": "\nbody {\n  font-family: Arial, sans-serif;\n}\n\nh1 {\n  text-align: center;\n  width: 100%;\n  line-height: 120%;\n  color: rgb(66,66,66);\n  letter-spacing: -0.05em;\n}\n\n.controls {\n  text-align: center;\n  margin-top: 25px;\n}\n\n.preview, .settings {\n  border: 1px solid #999;\n  margin-left: 32px; margin-right: 32px;\n  margin-top: 32px;\n  padding: 25px;\n  position: relative;\n}\n\n.preview:hover .content input {\n  visibility: visible;\n}\n\n.content input:focus {\n  z-index: 20;\n}\n.content input {\n  visibility: hidden;\n  position: absolute;\n  width: 570px;\n  font-size: 50px;\n  z-index: 10;\n  border-color: transparent;\n}\n\n.photooverlay {\n  position: absolute;\n  width: 310px;\n  height: 300px;\n  z-index: 10;\n}\n\n#video {\n  display: none;\n  width: 100%;\n  height: 100%; \n  position: absolute;\n  top: 0;\n  left: 0;\n  cursor: pointer;\n  margin: 1px;\n  background: white;\n}\n\n.photooverlay > div {\n  visibility: hidden;\n  width: 100%;\n  text-align: center;\n  bottom: 0;\n  position: absolute;\n  padding: 20px 0;\n}\n.photooverlay:hover > div {\n  background-color: rgba(255,255,255,0.7);\n  visibility: visible;\n}\n\nbutton {\n  cursor: pointer;\n}\n\n.photooverlay button {\n  border: none;\n  background: none;\n  margin: 0 10px;\n}\n\n#name {\n  font-size: 64px;\n  top: 114px;\n  left: 345px;\n}\n\n#nick {\n  font-size: 48px;\n  top: 191px;\n  left: 345px;\n}\n\n#previewCanvas {\n  border: 1px solid #999;\n}\n\n#ditheredCanvas {\n  display: none;\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/weather/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hfgmgghdkhgcklddhfefhdhcpkpmikhi\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Weather\n\nA basic 5-day weather forecast. Uses geolocation (if available) to locate the\nuser and retrieve the conditions nearest to them. Also allows the user to add\nother cities and choose the temperature format.\n\nMakes use of the Chrome Storage API to save and load the cities and settings\nthat the user has chosen\n\n## Resources\n\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n* [Storage](http://developer.chrome.com/apps/storage)\n* [Geolocation](http://developer.chrome.com/apps/manifest#permissions)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/weather/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/weather/lib/iscroll.js",
    "content": "/*!\n * iScroll v4.2.5 ~ Copyright (c) 2012 Matteo Spinelli, http://cubiq.org\n * Released under MIT license, http://cubiq.org/license\n */\n(function(window, doc){\nvar m = Math,\n\tdummyStyle = doc.createElement('div').style,\n\tvendor = (function () {\n\t\tvar vendors = 't,webkitT,MozT,msT,OT'.split(','),\n\t\t\tt,\n\t\t\ti = 0,\n\t\t\tl = vendors.length;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tt = vendors[i] + 'ransform';\n\t\t\tif ( t in dummyStyle ) {\n\t\t\t\treturn vendors[i].substr(0, vendors[i].length - 1);\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t})(),\n\tcssVendor = vendor ? '-' + vendor.toLowerCase() + '-' : '',\n\n\t// Style properties\n\ttransform = prefixStyle('transform'),\n\ttransitionProperty = prefixStyle('transitionProperty'),\n\ttransitionDuration = prefixStyle('transitionDuration'),\n\ttransformOrigin = prefixStyle('transformOrigin'),\n\ttransitionTimingFunction = prefixStyle('transitionTimingFunction'),\n\ttransitionDelay = prefixStyle('transitionDelay'),\n\n    // Browser capabilities\n\tisAndroid = (/android/gi).test(navigator.appVersion),\n\tisIDevice = (/iphone|ipad/gi).test(navigator.appVersion),\n\tisTouchPad = (/hp-tablet/gi).test(navigator.appVersion),\n\n    has3d = prefixStyle('perspective') in dummyStyle,\n    hasTouch = 'ontouchstart' in window && !isTouchPad,\n    hasTransform = vendor !== false,\n    hasTransitionEnd = prefixStyle('transition') in dummyStyle,\n\n\tRESIZE_EV = 'onorientationchange' in window ? 'orientationchange' : 'resize',\n\tSTART_EV = hasTouch ? 'touchstart' : 'mousedown',\n\tMOVE_EV = hasTouch ? 'touchmove' : 'mousemove',\n\tEND_EV = hasTouch ? 'touchend' : 'mouseup',\n\tCANCEL_EV = hasTouch ? 'touchcancel' : 'mouseup',\n\tTRNEND_EV = (function () {\n\t\tif ( vendor === false ) return false;\n\n\t\tvar transitionEnd = {\n\t\t\t\t''\t\t\t: 'transitionend',\n\t\t\t\t'webkit'\t: 'webkitTransitionEnd',\n\t\t\t\t'Moz'\t\t: 'transitionend',\n\t\t\t\t'O'\t\t\t: 'otransitionend',\n\t\t\t\t'ms'\t\t: 'MSTransitionEnd'\n\t\t\t};\n\n\t\treturn transitionEnd[vendor];\n\t})(),\n\n\tnextFrame = (function() {\n\t\treturn window.requestAnimationFrame ||\n\t\t\twindow.webkitRequestAnimationFrame ||\n\t\t\twindow.mozRequestAnimationFrame ||\n\t\t\twindow.oRequestAnimationFrame ||\n\t\t\twindow.msRequestAnimationFrame ||\n\t\t\tfunction(callback) { return setTimeout(callback, 1); };\n\t})(),\n\tcancelFrame = (function () {\n\t\treturn window.cancelRequestAnimationFrame ||\n\t\t\twindow.webkitCancelAnimationFrame ||\n\t\t\twindow.webkitCancelRequestAnimationFrame ||\n\t\t\twindow.mozCancelRequestAnimationFrame ||\n\t\t\twindow.oCancelRequestAnimationFrame ||\n\t\t\twindow.msCancelRequestAnimationFrame ||\n\t\t\tclearTimeout;\n\t})(),\n\n\t// Helpers\n\ttranslateZ = has3d ? ' translateZ(0)' : '',\n\n\t// Constructor\n\tiScroll = function (el, options) {\n\t\tvar that = this,\n\t\t\ti;\n\n\t\tthat.wrapper = typeof el == 'object' ? el : doc.getElementById(el);\n\t\tthat.wrapper.style.overflow = 'hidden';\n\t\tthat.scroller = that.wrapper.children[0];\n\n\t\t// Default options\n\t\tthat.options = {\n\t\t\thScroll: true,\n\t\t\tvScroll: true,\n\t\t\tx: 0,\n\t\t\ty: 0,\n\t\t\tbounce: true,\n\t\t\tbounceLock: false,\n\t\t\tmomentum: true,\n\t\t\tlockDirection: true,\n\t\t\tuseTransform: true,\n\t\t\tuseTransition: false,\n\t\t\ttopOffset: 0,\n\t\t\tcheckDOMChanges: false,\t\t// Experimental\n\t\t\thandleClick: true,\n\n\t\t\t// Scrollbar\n\t\t\thScrollbar: true,\n\t\t\tvScrollbar: true,\n\t\t\tfixedScrollbar: isAndroid,\n\t\t\thideScrollbar: isIDevice,\n\t\t\tfadeScrollbar: isIDevice && has3d,\n\t\t\tscrollbarClass: '',\n\n\t\t\t// Zoom\n\t\t\tzoom: false,\n\t\t\tzoomMin: 1,\n\t\t\tzoomMax: 4,\n\t\t\tdoubleTapZoom: 2,\n\t\t\twheelAction: 'scroll',\n\n\t\t\t// Snap\n\t\t\tsnap: false,\n\t\t\tsnapThreshold: 1,\n\n\t\t\t// Events\n\t\t\tonRefresh: null,\n\t\t\tonBeforeScrollStart: function (e) { e.preventDefault(); },\n\t\t\tonScrollStart: null,\n\t\t\tonBeforeScrollMove: null,\n\t\t\tonScrollMove: null,\n\t\t\tonBeforeScrollEnd: null,\n\t\t\tonScrollEnd: null,\n\t\t\tonTouchEnd: null,\n\t\t\tonDestroy: null,\n\t\t\tonZoomStart: null,\n\t\t\tonZoom: null,\n\t\t\tonZoomEnd: null\n\t\t};\n\n\t\t// User defined options\n\t\tfor (i in options) that.options[i] = options[i];\n\t\t\n\t\t// Set starting position\n\t\tthat.x = that.options.x;\n\t\tthat.y = that.options.y;\n\n\t\t// Normalize options\n\t\tthat.options.useTransform = hasTransform && that.options.useTransform;\n\t\tthat.options.hScrollbar = that.options.hScroll && that.options.hScrollbar;\n\t\tthat.options.vScrollbar = that.options.vScroll && that.options.vScrollbar;\n\t\tthat.options.zoom = that.options.useTransform && that.options.zoom;\n\t\tthat.options.useTransition = hasTransitionEnd && that.options.useTransition;\n\n\t\t// Helpers FIX ANDROID BUG!\n\t\t// translate3d and scale doesn't work together!\n\t\t// Ignoring 3d ONLY WHEN YOU SET that.options.zoom\n\t\tif ( that.options.zoom && isAndroid ){\n\t\t\ttranslateZ = '';\n\t\t}\n\t\t\n\t\t// Set some default styles\n\t\tthat.scroller.style[transitionProperty] = that.options.useTransform ? cssVendor + 'transform' : 'top left';\n\t\tthat.scroller.style[transitionDuration] = '0';\n\t\tthat.scroller.style[transformOrigin] = '0 0';\n\t\tif (that.options.useTransition) that.scroller.style[transitionTimingFunction] = 'cubic-bezier(0.33,0.66,0.66,1)';\n\t\t\n\t\tif (that.options.useTransform) that.scroller.style[transform] = 'translate(' + that.x + 'px,' + that.y + 'px)' + translateZ;\n\t\telse that.scroller.style.cssText += ';position:absolute;top:' + that.y + 'px;left:' + that.x + 'px';\n\n\t\tif (that.options.useTransition) that.options.fixedScrollbar = true;\n\n\t\tthat.refresh();\n\n\t\tthat._bind(RESIZE_EV, window);\n\t\tthat._bind(START_EV);\n\t\tif (!hasTouch) {\n\t\t\tif (that.options.wheelAction != 'none') {\n\t\t\t\tthat._bind('DOMMouseScroll');\n\t\t\t\tthat._bind('mousewheel');\n\t\t\t}\n\t\t}\n\n\t\tif (that.options.checkDOMChanges) that.checkDOMTime = setInterval(function () {\n\t\t\tthat._checkDOMChanges();\n\t\t}, 500);\n\t};\n\n// Prototype\niScroll.prototype = {\n\tenabled: true,\n\tx: 0,\n\ty: 0,\n\tsteps: [],\n\tscale: 1,\n\tcurrPageX: 0, currPageY: 0,\n\tpagesX: [], pagesY: [],\n\taniTime: null,\n\twheelZoomCount: 0,\n\t\n\thandleEvent: function (e) {\n\t\tvar that = this;\n\t\tswitch(e.type) {\n\t\t\tcase START_EV:\n\t\t\t\tif (!hasTouch && e.button !== 0) return;\n\t\t\t\tthat._start(e);\n\t\t\t\tbreak;\n\t\t\tcase MOVE_EV: that._move(e); break;\n\t\t\tcase END_EV:\n\t\t\tcase CANCEL_EV: that._end(e); break;\n\t\t\tcase RESIZE_EV: that._resize(); break;\n\t\t\tcase 'DOMMouseScroll': case 'mousewheel': that._wheel(e); break;\n\t\t\tcase TRNEND_EV: that._transitionEnd(e); break;\n\t\t}\n\t},\n\t\n\t_checkDOMChanges: function () {\n\t\tif (this.moved || this.zoomed || this.animating ||\n\t\t\t(this.scrollerW == this.scroller.offsetWidth * this.scale && this.scrollerH == this.scroller.offsetHeight * this.scale)) return;\n\n\t\tthis.refresh();\n\t},\n\t\n\t_scrollbar: function (dir) {\n\t\tvar that = this,\n\t\t\tbar;\n\n\t\tif (!that[dir + 'Scrollbar']) {\n\t\t\tif (that[dir + 'ScrollbarWrapper']) {\n\t\t\t\tif (hasTransform) that[dir + 'ScrollbarIndicator'].style[transform] = '';\n\t\t\t\tthat[dir + 'ScrollbarWrapper'].parentNode.removeChild(that[dir + 'ScrollbarWrapper']);\n\t\t\t\tthat[dir + 'ScrollbarWrapper'] = null;\n\t\t\t\tthat[dir + 'ScrollbarIndicator'] = null;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (!that[dir + 'ScrollbarWrapper']) {\n\t\t\t// Create the scrollbar wrapper\n\t\t\tbar = doc.createElement('div');\n\n\t\t\tif (that.options.scrollbarClass) bar.className = that.options.scrollbarClass + dir.toUpperCase();\n\t\t\telse bar.style.cssText = 'position:absolute;z-index:100;' + (dir == 'h' ? 'height:7px;bottom:1px;left:2px;right:' + (that.vScrollbar ? '7' : '2') + 'px' : 'width:7px;bottom:' + (that.hScrollbar ? '7' : '2') + 'px;top:2px;right:1px');\n\n\t\t\tbar.style.cssText += ';pointer-events:none;' + cssVendor + 'transition-property:opacity;' + cssVendor + 'transition-duration:' + (that.options.fadeScrollbar ? '350ms' : '0') + ';overflow:hidden;opacity:' + (that.options.hideScrollbar ? '0' : '1');\n\n\t\t\tthat.wrapper.appendChild(bar);\n\t\t\tthat[dir + 'ScrollbarWrapper'] = bar;\n\n\t\t\t// Create the scrollbar indicator\n\t\t\tbar = doc.createElement('div');\n\t\t\tif (!that.options.scrollbarClass) {\n\t\t\t\tbar.style.cssText = 'position:absolute;z-index:100;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);' + cssVendor + 'background-clip:padding-box;' + cssVendor + 'box-sizing:border-box;' + (dir == 'h' ? 'height:100%' : 'width:100%') + ';' + cssVendor + 'border-radius:3px;border-radius:3px';\n\t\t\t}\n\t\t\tbar.style.cssText += ';pointer-events:none;' + cssVendor + 'transition-property:' + cssVendor + 'transform;' + cssVendor + 'transition-timing-function:cubic-bezier(0.33,0.66,0.66,1);' + cssVendor + 'transition-duration:0;' + cssVendor + 'transform: translate(0,0)' + translateZ;\n\t\t\tif (that.options.useTransition) bar.style.cssText += ';' + cssVendor + 'transition-timing-function:cubic-bezier(0.33,0.66,0.66,1)';\n\n\t\t\tthat[dir + 'ScrollbarWrapper'].appendChild(bar);\n\t\t\tthat[dir + 'ScrollbarIndicator'] = bar;\n\t\t}\n\n\t\tif (dir == 'h') {\n\t\t\tthat.hScrollbarSize = that.hScrollbarWrapper.clientWidth;\n\t\t\tthat.hScrollbarIndicatorSize = m.max(m.round(that.hScrollbarSize * that.hScrollbarSize / that.scrollerW), 8);\n\t\t\tthat.hScrollbarIndicator.style.width = that.hScrollbarIndicatorSize + 'px';\n\t\t\tthat.hScrollbarMaxScroll = that.hScrollbarSize - that.hScrollbarIndicatorSize;\n\t\t\tthat.hScrollbarProp = that.hScrollbarMaxScroll / that.maxScrollX;\n\t\t} else {\n\t\t\tthat.vScrollbarSize = that.vScrollbarWrapper.clientHeight;\n\t\t\tthat.vScrollbarIndicatorSize = m.max(m.round(that.vScrollbarSize * that.vScrollbarSize / that.scrollerH), 8);\n\t\t\tthat.vScrollbarIndicator.style.height = that.vScrollbarIndicatorSize + 'px';\n\t\t\tthat.vScrollbarMaxScroll = that.vScrollbarSize - that.vScrollbarIndicatorSize;\n\t\t\tthat.vScrollbarProp = that.vScrollbarMaxScroll / that.maxScrollY;\n\t\t}\n\n\t\t// Reset position\n\t\tthat._scrollbarPos(dir, true);\n\t},\n\t\n\t_resize: function () {\n\t\tvar that = this;\n\t\tsetTimeout(function () { that.refresh(); }, isAndroid ? 200 : 0);\n\t},\n\t\n\t_pos: function (x, y) {\n\t\tif (this.zoomed) return;\n\n\t\tx = this.hScroll ? x : 0;\n\t\ty = this.vScroll ? y : 0;\n\n\t\tif (this.options.useTransform) {\n\t\t\tthis.scroller.style[transform] = 'translate(' + x + 'px,' + y + 'px) scale(' + this.scale + ')' + translateZ;\n\t\t} else {\n\t\t\tx = m.round(x);\n\t\t\ty = m.round(y);\n\t\t\tthis.scroller.style.left = x + 'px';\n\t\t\tthis.scroller.style.top = y + 'px';\n\t\t}\n\n\t\tthis.x = x;\n\t\tthis.y = y;\n\n\t\tthis._scrollbarPos('h');\n\t\tthis._scrollbarPos('v');\n\t},\n\n\t_scrollbarPos: function (dir, hidden) {\n\t\tvar that = this,\n\t\t\tpos = dir == 'h' ? that.x : that.y,\n\t\t\tsize;\n\n\t\tif (!that[dir + 'Scrollbar']) return;\n\n\t\tpos = that[dir + 'ScrollbarProp'] * pos;\n\n\t\tif (pos < 0) {\n\t\t\tif (!that.options.fixedScrollbar) {\n\t\t\t\tsize = that[dir + 'ScrollbarIndicatorSize'] + m.round(pos * 3);\n\t\t\t\tif (size < 8) size = 8;\n\t\t\t\tthat[dir + 'ScrollbarIndicator'].style[dir == 'h' ? 'width' : 'height'] = size + 'px';\n\t\t\t}\n\t\t\tpos = 0;\n\t\t} else if (pos > that[dir + 'ScrollbarMaxScroll']) {\n\t\t\tif (!that.options.fixedScrollbar) {\n\t\t\t\tsize = that[dir + 'ScrollbarIndicatorSize'] - m.round((pos - that[dir + 'ScrollbarMaxScroll']) * 3);\n\t\t\t\tif (size < 8) size = 8;\n\t\t\t\tthat[dir + 'ScrollbarIndicator'].style[dir == 'h' ? 'width' : 'height'] = size + 'px';\n\t\t\t\tpos = that[dir + 'ScrollbarMaxScroll'] + (that[dir + 'ScrollbarIndicatorSize'] - size);\n\t\t\t} else {\n\t\t\t\tpos = that[dir + 'ScrollbarMaxScroll'];\n\t\t\t}\n\t\t}\n\n\t\tthat[dir + 'ScrollbarWrapper'].style[transitionDelay] = '0';\n\t\tthat[dir + 'ScrollbarWrapper'].style.opacity = hidden && that.options.hideScrollbar ? '0' : '1';\n\t\tthat[dir + 'ScrollbarIndicator'].style[transform] = 'translate(' + (dir == 'h' ? pos + 'px,0)' : '0,' + pos + 'px)') + translateZ;\n\t},\n\t\n\t_start: function (e) {\n\t\tvar that = this,\n\t\t\tpoint = hasTouch ? e.touches[0] : e,\n\t\t\tmatrix, x, y,\n\t\t\tc1, c2;\n\n\t\tif (!that.enabled) return;\n\n\t\tif (that.options.onBeforeScrollStart) that.options.onBeforeScrollStart.call(that, e);\n\n\t\tif (that.options.useTransition || that.options.zoom) that._transitionTime(0);\n\n\t\tthat.moved = false;\n\t\tthat.animating = false;\n\t\tthat.zoomed = false;\n\t\tthat.distX = 0;\n\t\tthat.distY = 0;\n\t\tthat.absDistX = 0;\n\t\tthat.absDistY = 0;\n\t\tthat.dirX = 0;\n\t\tthat.dirY = 0;\n\n\t\t// Gesture start\n\t\tif (that.options.zoom && hasTouch && e.touches.length > 1) {\n\t\t\tc1 = m.abs(e.touches[0].pageX-e.touches[1].pageX);\n\t\t\tc2 = m.abs(e.touches[0].pageY-e.touches[1].pageY);\n\t\t\tthat.touchesDistStart = m.sqrt(c1 * c1 + c2 * c2);\n\n\t\t\tthat.originX = m.abs(e.touches[0].pageX + e.touches[1].pageX - that.wrapperOffsetLeft * 2) / 2 - that.x;\n\t\t\tthat.originY = m.abs(e.touches[0].pageY + e.touches[1].pageY - that.wrapperOffsetTop * 2) / 2 - that.y;\n\n\t\t\tif (that.options.onZoomStart) that.options.onZoomStart.call(that, e);\n\t\t}\n\n\t\tif (that.options.momentum) {\n\t\t\tif (that.options.useTransform) {\n\t\t\t\t// Very lame general purpose alternative to CSSMatrix\n\t\t\t\tmatrix = getComputedStyle(that.scroller, null)[transform].replace(/[^0-9\\-.,]/g, '').split(',');\n\t\t\t\tx = +(matrix[12] || matrix[4]);\n\t\t\t\ty = +(matrix[13] || matrix[5]);\n\t\t\t} else {\n\t\t\t\tx = +getComputedStyle(that.scroller, null).left.replace(/[^0-9-]/g, '');\n\t\t\t\ty = +getComputedStyle(that.scroller, null).top.replace(/[^0-9-]/g, '');\n\t\t\t}\n\t\t\t\n\t\t\tif (x != that.x || y != that.y) {\n\t\t\t\tif (that.options.useTransition) that._unbind(TRNEND_EV);\n\t\t\t\telse cancelFrame(that.aniTime);\n\t\t\t\tthat.steps = [];\n\t\t\t\tthat._pos(x, y);\n\t\t\t\tif (that.options.onScrollEnd) that.options.onScrollEnd.call(that);\n\t\t\t}\n\t\t}\n\n\t\tthat.absStartX = that.x;\t// Needed by snap threshold\n\t\tthat.absStartY = that.y;\n\n\t\tthat.startX = that.x;\n\t\tthat.startY = that.y;\n\t\tthat.pointX = point.pageX;\n\t\tthat.pointY = point.pageY;\n\n\t\tthat.startTime = e.timeStamp || Date.now();\n\n\t\tif (that.options.onScrollStart) that.options.onScrollStart.call(that, e);\n\n\t\tthat._bind(MOVE_EV, window);\n\t\tthat._bind(END_EV, window);\n\t\tthat._bind(CANCEL_EV, window);\n\t},\n\t\n\t_move: function (e) {\n\t\tvar that = this,\n\t\t\tpoint = hasTouch ? e.touches[0] : e,\n\t\t\tdeltaX = point.pageX - that.pointX,\n\t\t\tdeltaY = point.pageY - that.pointY,\n\t\t\tnewX = that.x + deltaX,\n\t\t\tnewY = that.y + deltaY,\n\t\t\tc1, c2, scale,\n\t\t\ttimestamp = e.timeStamp || Date.now();\n\n\t\tif (that.options.onBeforeScrollMove) that.options.onBeforeScrollMove.call(that, e);\n\n\t\t// Zoom\n\t\tif (that.options.zoom && hasTouch && e.touches.length > 1) {\n\t\t\tc1 = m.abs(e.touches[0].pageX - e.touches[1].pageX);\n\t\t\tc2 = m.abs(e.touches[0].pageY - e.touches[1].pageY);\n\t\t\tthat.touchesDist = m.sqrt(c1*c1+c2*c2);\n\n\t\t\tthat.zoomed = true;\n\n\t\t\tscale = 1 / that.touchesDistStart * that.touchesDist * this.scale;\n\n\t\t\tif (scale < that.options.zoomMin) scale = 0.5 * that.options.zoomMin * Math.pow(2.0, scale / that.options.zoomMin);\n\t\t\telse if (scale > that.options.zoomMax) scale = 2.0 * that.options.zoomMax * Math.pow(0.5, that.options.zoomMax / scale);\n\n\t\t\tthat.lastScale = scale / this.scale;\n\n\t\t\tnewX = this.originX - this.originX * that.lastScale + this.x,\n\t\t\tnewY = this.originY - this.originY * that.lastScale + this.y;\n\n\t\t\tthis.scroller.style[transform] = 'translate(' + newX + 'px,' + newY + 'px) scale(' + scale + ')' + translateZ;\n\n\t\t\tif (that.options.onZoom) that.options.onZoom.call(that, e);\n\t\t\treturn;\n\t\t}\n\n\t\tthat.pointX = point.pageX;\n\t\tthat.pointY = point.pageY;\n\n\t\t// Slow down if outside of the boundaries\n\t\tif (newX > 0 || newX < that.maxScrollX) {\n\t\t\tnewX = that.options.bounce ? that.x + (deltaX / 2) : newX >= 0 || that.maxScrollX >= 0 ? 0 : that.maxScrollX;\n\t\t}\n\t\tif (newY > that.minScrollY || newY < that.maxScrollY) {\n\t\t\tnewY = that.options.bounce ? that.y + (deltaY / 2) : newY >= that.minScrollY || that.maxScrollY >= 0 ? that.minScrollY : that.maxScrollY;\n\t\t}\n\n\t\tthat.distX += deltaX;\n\t\tthat.distY += deltaY;\n\t\tthat.absDistX = m.abs(that.distX);\n\t\tthat.absDistY = m.abs(that.distY);\n\n\t\tif (that.absDistX < 6 && that.absDistY < 6) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Lock direction\n\t\tif (that.options.lockDirection) {\n\t\t\tif (that.absDistX > that.absDistY + 5) {\n\t\t\t\tnewY = that.y;\n\t\t\t\tdeltaY = 0;\n\t\t\t} else if (that.absDistY > that.absDistX + 5) {\n\t\t\t\tnewX = that.x;\n\t\t\t\tdeltaX = 0;\n\t\t\t}\n\t\t}\n\n\t\tthat.moved = true;\n\t\tthat._pos(newX, newY);\n\t\tthat.dirX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;\n\t\tthat.dirY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;\n\n\t\tif (timestamp - that.startTime > 300) {\n\t\t\tthat.startTime = timestamp;\n\t\t\tthat.startX = that.x;\n\t\t\tthat.startY = that.y;\n\t\t}\n\t\t\n\t\tif (that.options.onScrollMove) that.options.onScrollMove.call(that, e);\n\t},\n\t\n\t_end: function (e) {\n\t\tif (hasTouch && e.touches.length !== 0) return;\n\n\t\tvar that = this,\n\t\t\tpoint = hasTouch ? e.changedTouches[0] : e,\n\t\t\ttarget, ev,\n\t\t\tmomentumX = { dist:0, time:0 },\n\t\t\tmomentumY = { dist:0, time:0 },\n\t\t\tduration = (e.timeStamp || Date.now()) - that.startTime,\n\t\t\tnewPosX = that.x,\n\t\t\tnewPosY = that.y,\n\t\t\tdistX, distY,\n\t\t\tnewDuration,\n\t\t\tsnap,\n\t\t\tscale;\n\n\t\tthat._unbind(MOVE_EV, window);\n\t\tthat._unbind(END_EV, window);\n\t\tthat._unbind(CANCEL_EV, window);\n\n\t\tif (that.options.onBeforeScrollEnd) that.options.onBeforeScrollEnd.call(that, e);\n\n\t\tif (that.zoomed) {\n\t\t\tscale = that.scale * that.lastScale;\n\t\t\tscale = Math.max(that.options.zoomMin, scale);\n\t\t\tscale = Math.min(that.options.zoomMax, scale);\n\t\t\tthat.lastScale = scale / that.scale;\n\t\t\tthat.scale = scale;\n\n\t\t\tthat.x = that.originX - that.originX * that.lastScale + that.x;\n\t\t\tthat.y = that.originY - that.originY * that.lastScale + that.y;\n\t\t\t\n\t\t\tthat.scroller.style[transitionDuration] = '200ms';\n\t\t\tthat.scroller.style[transform] = 'translate(' + that.x + 'px,' + that.y + 'px) scale(' + that.scale + ')' + translateZ;\n\t\t\t\n\t\t\tthat.zoomed = false;\n\t\t\tthat.refresh();\n\n\t\t\tif (that.options.onZoomEnd) that.options.onZoomEnd.call(that, e);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!that.moved) {\n\t\t\tif (hasTouch) {\n\t\t\t\tif (that.doubleTapTimer && that.options.zoom) {\n\t\t\t\t\t// Double tapped\n\t\t\t\t\tclearTimeout(that.doubleTapTimer);\n\t\t\t\t\tthat.doubleTapTimer = null;\n\t\t\t\t\tif (that.options.onZoomStart) that.options.onZoomStart.call(that, e);\n\t\t\t\t\tthat.zoom(that.pointX, that.pointY, that.scale == 1 ? that.options.doubleTapZoom : 1);\n\t\t\t\t\tif (that.options.onZoomEnd) {\n\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\tthat.options.onZoomEnd.call(that, e);\n\t\t\t\t\t\t}, 200); // 200 is default zoom duration\n\t\t\t\t\t}\n\t\t\t\t} else if (this.options.handleClick) {\n\t\t\t\t\tthat.doubleTapTimer = setTimeout(function () {\n\t\t\t\t\t\tthat.doubleTapTimer = null;\n\n\t\t\t\t\t\t// Find the last touched element\n\t\t\t\t\t\ttarget = point.target;\n\t\t\t\t\t\twhile (target.nodeType != 1) target = target.parentNode;\n\n\t\t\t\t\t\tif (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') {\n\t\t\t\t\t\t\tev = doc.createEvent('MouseEvents');\n\t\t\t\t\t\t\tev.initMouseEvent('click', true, true, e.view, 1,\n\t\t\t\t\t\t\t\tpoint.screenX, point.screenY, point.clientX, point.clientY,\n\t\t\t\t\t\t\t\te.ctrlKey, e.altKey, e.shiftKey, e.metaKey,\n\t\t\t\t\t\t\t\t0, null);\n\t\t\t\t\t\t\tev._fake = true;\n\t\t\t\t\t\t\ttarget.dispatchEvent(ev);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, that.options.zoom ? 250 : 0);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthat._resetPos(400);\n\n\t\t\tif (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);\n\t\t\treturn;\n\t\t}\n\n\t\tif (duration < 300 && that.options.momentum) {\n\t\t\tmomentumX = newPosX ? that._momentum(newPosX - that.startX, duration, -that.x, that.scrollerW - that.wrapperW + that.x, that.options.bounce ? that.wrapperW : 0) : momentumX;\n\t\t\tmomentumY = newPosY ? that._momentum(newPosY - that.startY, duration, -that.y, (that.maxScrollY < 0 ? that.scrollerH - that.wrapperH + that.y - that.minScrollY : 0), that.options.bounce ? that.wrapperH : 0) : momentumY;\n\n\t\t\tnewPosX = that.x + momentumX.dist;\n\t\t\tnewPosY = that.y + momentumY.dist;\n\n\t\t\tif ((that.x > 0 && newPosX > 0) || (that.x < that.maxScrollX && newPosX < that.maxScrollX)) momentumX = { dist:0, time:0 };\n\t\t\tif ((that.y > that.minScrollY && newPosY > that.minScrollY) || (that.y < that.maxScrollY && newPosY < that.maxScrollY)) momentumY = { dist:0, time:0 };\n\t\t}\n\n\t\tif (momentumX.dist || momentumY.dist) {\n\t\t\tnewDuration = m.max(m.max(momentumX.time, momentumY.time), 10);\n\n\t\t\t// Do we need to snap?\n\t\t\tif (that.options.snap) {\n\t\t\t\tdistX = newPosX - that.absStartX;\n\t\t\t\tdistY = newPosY - that.absStartY;\n\t\t\t\tif (m.abs(distX) < that.options.snapThreshold && m.abs(distY) < that.options.snapThreshold) { that.scrollTo(that.absStartX, that.absStartY, 200); }\n\t\t\t\telse {\n\t\t\t\t\tsnap = that._snap(newPosX, newPosY);\n\t\t\t\t\tnewPosX = snap.x;\n\t\t\t\t\tnewPosY = snap.y;\n\t\t\t\t\tnewDuration = m.max(snap.time, newDuration);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthat.scrollTo(m.round(newPosX), m.round(newPosY), newDuration);\n\n\t\t\tif (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);\n\t\t\treturn;\n\t\t}\n\n\t\t// Do we need to snap?\n\t\tif (that.options.snap) {\n\t\t\tdistX = newPosX - that.absStartX;\n\t\t\tdistY = newPosY - that.absStartY;\n\t\t\tif (m.abs(distX) < that.options.snapThreshold && m.abs(distY) < that.options.snapThreshold) that.scrollTo(that.absStartX, that.absStartY, 200);\n\t\t\telse {\n\t\t\t\tsnap = that._snap(that.x, that.y);\n\t\t\t\tif (snap.x != that.x || snap.y != that.y) that.scrollTo(snap.x, snap.y, snap.time);\n\t\t\t}\n\n\t\t\tif (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);\n\t\t\treturn;\n\t\t}\n\n\t\tthat._resetPos(200);\n\t\tif (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);\n\t},\n\t\n\t_resetPos: function (time) {\n\t\tvar that = this,\n\t\t\tresetX = that.x >= 0 ? 0 : that.x < that.maxScrollX ? that.maxScrollX : that.x,\n\t\t\tresetY = that.y >= that.minScrollY || that.maxScrollY > 0 ? that.minScrollY : that.y < that.maxScrollY ? that.maxScrollY : that.y;\n\n\t\tif (resetX == that.x && resetY == that.y) {\n\t\t\tif (that.moved) {\n\t\t\t\tthat.moved = false;\n\t\t\t\tif (that.options.onScrollEnd) that.options.onScrollEnd.call(that);\t\t// Execute custom code on scroll end\n\t\t\t}\n\n\t\t\tif (that.hScrollbar && that.options.hideScrollbar) {\n\t\t\t\tif (vendor == 'webkit') that.hScrollbarWrapper.style[transitionDelay] = '300ms';\n\t\t\t\tthat.hScrollbarWrapper.style.opacity = '0';\n\t\t\t}\n\t\t\tif (that.vScrollbar && that.options.hideScrollbar) {\n\t\t\t\tif (vendor == 'webkit') that.vScrollbarWrapper.style[transitionDelay] = '300ms';\n\t\t\t\tthat.vScrollbarWrapper.style.opacity = '0';\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tthat.scrollTo(resetX, resetY, time || 0);\n\t},\n\n\t_wheel: function (e) {\n\t\tvar that = this,\n\t\t\twheelDeltaX, wheelDeltaY,\n\t\t\tdeltaX, deltaY,\n\t\t\tdeltaScale;\n\n\t\tif ('wheelDeltaX' in e) {\n\t\t\twheelDeltaX = e.wheelDeltaX / 12;\n\t\t\twheelDeltaY = e.wheelDeltaY / 12;\n\t\t} else if('wheelDelta' in e) {\n\t\t\twheelDeltaX = wheelDeltaY = e.wheelDelta / 12;\n\t\t} else if ('detail' in e) {\n\t\t\twheelDeltaX = wheelDeltaY = -e.detail * 3;\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tif (that.options.wheelAction == 'zoom') {\n\t\t\tdeltaScale = that.scale * Math.pow(2, 1/3 * (wheelDeltaY ? wheelDeltaY / Math.abs(wheelDeltaY) : 0));\n\t\t\tif (deltaScale < that.options.zoomMin) deltaScale = that.options.zoomMin;\n\t\t\tif (deltaScale > that.options.zoomMax) deltaScale = that.options.zoomMax;\n\t\t\t\n\t\t\tif (deltaScale != that.scale) {\n\t\t\t\tif (!that.wheelZoomCount && that.options.onZoomStart) that.options.onZoomStart.call(that, e);\n\t\t\t\tthat.wheelZoomCount++;\n\t\t\t\t\n\t\t\t\tthat.zoom(e.pageX, e.pageY, deltaScale, 400);\n\t\t\t\t\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tthat.wheelZoomCount--;\n\t\t\t\t\tif (!that.wheelZoomCount && that.options.onZoomEnd) that.options.onZoomEnd.call(that, e);\n\t\t\t\t}, 400);\n\t\t\t}\n\t\t\t\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tdeltaX = that.x + wheelDeltaX;\n\t\tdeltaY = that.y + wheelDeltaY;\n\n\t\tif (deltaX > 0) deltaX = 0;\n\t\telse if (deltaX < that.maxScrollX) deltaX = that.maxScrollX;\n\n\t\tif (deltaY > that.minScrollY) deltaY = that.minScrollY;\n\t\telse if (deltaY < that.maxScrollY) deltaY = that.maxScrollY;\n    \n\t\tif (that.maxScrollY < 0) {\n\t\t\tthat.scrollTo(deltaX, deltaY, 0);\n\t\t}\n\t},\n\t\n\t_transitionEnd: function (e) {\n\t\tvar that = this;\n\n\t\tif (e.target != that.scroller) return;\n\n\t\tthat._unbind(TRNEND_EV);\n\t\t\n\t\tthat._startAni();\n\t},\n\n\n\t/**\n\t*\n\t* Utilities\n\t*\n\t*/\n\t_startAni: function () {\n\t\tvar that = this,\n\t\t\tstartX = that.x, startY = that.y,\n\t\t\tstartTime = Date.now(),\n\t\t\tstep, easeOut,\n\t\t\tanimate;\n\n\t\tif (that.animating) return;\n\t\t\n\t\tif (!that.steps.length) {\n\t\t\tthat._resetPos(400);\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tstep = that.steps.shift();\n\t\t\n\t\tif (step.x == startX && step.y == startY) step.time = 0;\n\n\t\tthat.animating = true;\n\t\tthat.moved = true;\n\t\t\n\t\tif (that.options.useTransition) {\n\t\t\tthat._transitionTime(step.time);\n\t\t\tthat._pos(step.x, step.y);\n\t\t\tthat.animating = false;\n\t\t\tif (step.time) that._bind(TRNEND_EV);\n\t\t\telse that._resetPos(0);\n\t\t\treturn;\n\t\t}\n\n\t\tanimate = function () {\n\t\t\tvar now = Date.now(),\n\t\t\t\tnewX, newY;\n\n\t\t\tif (now >= startTime + step.time) {\n\t\t\t\tthat._pos(step.x, step.y);\n\t\t\t\tthat.animating = false;\n\t\t\t\tif (that.options.onAnimationEnd) that.options.onAnimationEnd.call(that);\t\t\t// Execute custom code on animation end\n\t\t\t\tthat._startAni();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tnow = (now - startTime) / step.time - 1;\n\t\t\teaseOut = m.sqrt(1 - now * now);\n\t\t\tnewX = (step.x - startX) * easeOut + startX;\n\t\t\tnewY = (step.y - startY) * easeOut + startY;\n\t\t\tthat._pos(newX, newY);\n\t\t\tif (that.animating) that.aniTime = nextFrame(animate);\n\t\t};\n\n\t\tanimate();\n\t},\n\n\t_transitionTime: function (time) {\n\t\ttime += 'ms';\n\t\tthis.scroller.style[transitionDuration] = time;\n\t\tif (this.hScrollbar) this.hScrollbarIndicator.style[transitionDuration] = time;\n\t\tif (this.vScrollbar) this.vScrollbarIndicator.style[transitionDuration] = time;\n\t},\n\n\t_momentum: function (dist, time, maxDistUpper, maxDistLower, size) {\n\t\tvar deceleration = 0.0006,\n\t\t\tspeed = m.abs(dist) / time,\n\t\t\tnewDist = (speed * speed) / (2 * deceleration),\n\t\t\tnewTime = 0, outsideDist = 0;\n\n\t\t// Proportinally reduce speed if we are outside of the boundaries\n\t\tif (dist > 0 && newDist > maxDistUpper) {\n\t\t\toutsideDist = size / (6 / (newDist / speed * deceleration));\n\t\t\tmaxDistUpper = maxDistUpper + outsideDist;\n\t\t\tspeed = speed * maxDistUpper / newDist;\n\t\t\tnewDist = maxDistUpper;\n\t\t} else if (dist < 0 && newDist > maxDistLower) {\n\t\t\toutsideDist = size / (6 / (newDist / speed * deceleration));\n\t\t\tmaxDistLower = maxDistLower + outsideDist;\n\t\t\tspeed = speed * maxDistLower / newDist;\n\t\t\tnewDist = maxDistLower;\n\t\t}\n\n\t\tnewDist = newDist * (dist < 0 ? -1 : 1);\n\t\tnewTime = speed / deceleration;\n\n\t\treturn { dist: newDist, time: m.round(newTime) };\n\t},\n\n\t_offset: function (el) {\n\t\tvar left = -el.offsetLeft,\n\t\t\ttop = -el.offsetTop;\n\t\t\t\n\t\twhile (el = el.offsetParent) {\n\t\t\tleft -= el.offsetLeft;\n\t\t\ttop -= el.offsetTop;\n\t\t}\n\t\t\n\t\tif (el != this.wrapper) {\n\t\t\tleft *= this.scale;\n\t\t\ttop *= this.scale;\n\t\t}\n\n\t\treturn { left: left, top: top };\n\t},\n\n\t_snap: function (x, y) {\n\t\tvar that = this,\n\t\t\ti, l,\n\t\t\tpage, time,\n\t\t\tsizeX, sizeY;\n\n\t\t// Check page X\n\t\tpage = that.pagesX.length - 1;\n\t\tfor (i=0, l=that.pagesX.length; i<l; i++) {\n\t\t\tif (x >= that.pagesX[i]) {\n\t\t\t\tpage = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (page == that.currPageX && page > 0 && that.dirX < 0) page--;\n\t\tx = that.pagesX[page];\n\t\tsizeX = m.abs(x - that.pagesX[that.currPageX]);\n\t\tsizeX = sizeX ? m.abs(that.x - x) / sizeX * 500 : 0;\n\t\tthat.currPageX = page;\n\n\t\t// Check page Y\n\t\tpage = that.pagesY.length-1;\n\t\tfor (i=0; i<page; i++) {\n\t\t\tif (y >= that.pagesY[i]) {\n\t\t\t\tpage = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (page == that.currPageY && page > 0 && that.dirY < 0) page--;\n\t\ty = that.pagesY[page];\n\t\tsizeY = m.abs(y - that.pagesY[that.currPageY]);\n\t\tsizeY = sizeY ? m.abs(that.y - y) / sizeY * 500 : 0;\n\t\tthat.currPageY = page;\n\n\t\t// Snap with constant speed (proportional duration)\n\t\ttime = m.round(m.max(sizeX, sizeY)) || 200;\n\n\t\treturn { x: x, y: y, time: time };\n\t},\n\n\t_bind: function (type, el, bubble) {\n\t\t(el || this.scroller).addEventListener(type, this, !!bubble);\n\t},\n\n\t_unbind: function (type, el, bubble) {\n\t\t(el || this.scroller).removeEventListener(type, this, !!bubble);\n\t},\n\n\n\t/**\n\t*\n\t* Public methods\n\t*\n\t*/\n\tdestroy: function () {\n\t\tvar that = this;\n\n\t\tthat.scroller.style[transform] = '';\n\n\t\t// Remove the scrollbars\n\t\tthat.hScrollbar = false;\n\t\tthat.vScrollbar = false;\n\t\tthat._scrollbar('h');\n\t\tthat._scrollbar('v');\n\n\t\t// Remove the event listeners\n\t\tthat._unbind(RESIZE_EV, window);\n\t\tthat._unbind(START_EV);\n\t\tthat._unbind(MOVE_EV, window);\n\t\tthat._unbind(END_EV, window);\n\t\tthat._unbind(CANCEL_EV, window);\n\t\t\n\t\tif (!that.options.hasTouch) {\n\t\t\tthat._unbind('DOMMouseScroll');\n\t\t\tthat._unbind('mousewheel');\n\t\t}\n\t\t\n\t\tif (that.options.useTransition) that._unbind(TRNEND_EV);\n\t\t\n\t\tif (that.options.checkDOMChanges) clearInterval(that.checkDOMTime);\n\t\t\n\t\tif (that.options.onDestroy) that.options.onDestroy.call(that);\n\t},\n\n\trefresh: function () {\n\t\tvar that = this,\n\t\t\toffset,\n\t\t\ti, l,\n\t\t\tels,\n\t\t\tpos = 0,\n\t\t\tpage = 0;\n\n\t\tif (that.scale < that.options.zoomMin) that.scale = that.options.zoomMin;\n\t\tthat.wrapperW = that.wrapper.clientWidth || 1;\n\t\tthat.wrapperH = that.wrapper.clientHeight || 1;\n\n\t\tthat.minScrollY = -that.options.topOffset || 0;\n\t\t//that.scrollerW = m.round(that.scroller.offsetWidth * that.scale);\n\t\tthat.scrollerW = (!that.scroller.children.length) ? 0 : m.round(that.scroller.children.length * that.scroller.children[0].offsetWidth * that.scale);\n\t\tthat.scrollerH = m.round((that.scroller.offsetHeight + that.minScrollY) * that.scale);\n\t\tthat.maxScrollX = that.wrapperW - that.scrollerW;\n\t\tthat.maxScrollY = that.wrapperH - that.scrollerH + that.minScrollY;\n\t\tthat.dirX = 0;\n\t\tthat.dirY = 0;\n\n\t\tif (that.options.onRefresh) that.options.onRefresh.call(that);\n\n\t\tthat.hScroll = that.options.hScroll && that.maxScrollX < 0;\n\t\tthat.vScroll = that.options.vScroll && (!that.options.bounceLock && !that.hScroll || that.scrollerH > that.wrapperH);\n\n\t\tthat.hScrollbar = that.hScroll && that.options.hScrollbar;\n\t\tthat.vScrollbar = that.vScroll && that.options.vScrollbar && that.scrollerH > that.wrapperH;\n\n\t\toffset = that._offset(that.wrapper);\n\t\tthat.wrapperOffsetLeft = -offset.left;\n\t\tthat.wrapperOffsetTop = -offset.top;\n\n\t\t// Prepare snap\n\t\tif (typeof that.options.snap == 'string') {\n\t\t\tthat.pagesX = [];\n\t\t\tthat.pagesY = [];\n\t\t\tels = that.scroller.querySelectorAll(that.options.snap);\n\t\t\tfor (i=0, l=els.length; i<l; i++) {\n\t\t\t\tpos = that._offset(els[i]);\n\t\t\t\tpos.left += that.wrapperOffsetLeft;\n\t\t\t\tpos.top += that.wrapperOffsetTop;\n\t\t\t\tthat.pagesX[i] = pos.left < that.maxScrollX ? that.maxScrollX : pos.left * that.scale;\n\t\t\t\tthat.pagesY[i] = pos.top < that.maxScrollY ? that.maxScrollY : pos.top * that.scale;\n\t\t\t}\n\t\t} else if (that.options.snap) {\n\t\t\tthat.pagesX = [];\n\t\t\twhile (pos >= that.maxScrollX) {\n\t\t\t\tthat.pagesX[page] = pos;\n\t\t\t\tpos = pos - that.wrapperW;\n\t\t\t\tpage++;\n\t\t\t}\n\t\t\tif (that.maxScrollX%that.wrapperW) that.pagesX[that.pagesX.length] = that.maxScrollX - that.pagesX[that.pagesX.length-1] + that.pagesX[that.pagesX.length-1];\n\n\t\t\tpos = 0;\n\t\t\tpage = 0;\n\t\t\tthat.pagesY = [];\n\t\t\twhile (pos >= that.maxScrollY) {\n\t\t\t\tthat.pagesY[page] = pos;\n\t\t\t\tpos = pos - that.wrapperH;\n\t\t\t\tpage++;\n\t\t\t}\n\t\t\tif (that.maxScrollY%that.wrapperH) that.pagesY[that.pagesY.length] = that.maxScrollY - that.pagesY[that.pagesY.length-1] + that.pagesY[that.pagesY.length-1];\n\t\t}\n\n\t\t// Prepare the scrollbars\n\t\tthat._scrollbar('h');\n\t\tthat._scrollbar('v');\n\n\t\tif (!that.zoomed) {\n\t\t\tthat.scroller.style[transitionDuration] = '0';\n\t\t\tthat._resetPos(400);\n\t\t}\n\t},\n\n\tscrollTo: function (x, y, time, relative) {\n\t\tvar that = this,\n\t\t\tstep = x,\n\t\t\ti, l;\n\n\t\tthat.stop();\n\n\t\tif (!step.length) step = [{ x: x, y: y, time: time, relative: relative }];\n\t\t\n\t\tfor (i=0, l=step.length; i<l; i++) {\n\t\t\tif (step[i].relative) { step[i].x = that.x - step[i].x; step[i].y = that.y - step[i].y; }\n\t\t\tthat.steps.push({ x: step[i].x, y: step[i].y, time: step[i].time || 0 });\n\t\t}\n\n\t\tthat._startAni();\n\t},\n\n\tscrollToElement: function (el, time) {\n\t\tvar that = this, pos;\n\t\tel = el.nodeType ? el : that.scroller.querySelector(el);\n\t\tif (!el) return;\n\n\t\tpos = that._offset(el);\n\t\tpos.left += that.wrapperOffsetLeft;\n\t\tpos.top += that.wrapperOffsetTop;\n\n\t\tpos.left = pos.left > 0 ? 0 : pos.left < that.maxScrollX ? that.maxScrollX : pos.left;\n\t\tpos.top = pos.top > that.minScrollY ? that.minScrollY : pos.top < that.maxScrollY ? that.maxScrollY : pos.top;\n\t\ttime = time === undefined ? m.max(m.abs(pos.left)*2, m.abs(pos.top)*2) : time;\n\n\t\tthat.scrollTo(pos.left, pos.top, time);\n\t},\n\n\tscrollToPage: function (pageX, pageY, time) {\n\t\tvar that = this, x, y;\n\t\t\n\t\ttime = time === undefined ? 400 : time;\n\n\t\tif (that.options.onScrollStart) that.options.onScrollStart.call(that);\n\n\t\tif (that.options.snap) {\n\t\t\tpageX = pageX == 'next' ? that.currPageX+1 : pageX == 'prev' ? that.currPageX-1 : pageX;\n\t\t\tpageY = pageY == 'next' ? that.currPageY+1 : pageY == 'prev' ? that.currPageY-1 : pageY;\n\n\t\t\tpageX = pageX < 0 ? 0 : pageX > that.pagesX.length-1 ? that.pagesX.length-1 : pageX;\n\t\t\tpageY = pageY < 0 ? 0 : pageY > that.pagesY.length-1 ? that.pagesY.length-1 : pageY;\n\n\t\t\tthat.currPageX = pageX;\n\t\t\tthat.currPageY = pageY;\n\t\t\tx = that.pagesX[pageX];\n\t\t\ty = that.pagesY[pageY];\n\t\t} else {\n\t\t\tx = -that.wrapperW * pageX;\n\t\t\ty = -that.wrapperH * pageY;\n\t\t\tif (x < that.maxScrollX) x = that.maxScrollX;\n\t\t\tif (y < that.maxScrollY) y = that.maxScrollY;\n\t\t}\n\n\t\tthat.scrollTo(x, y, time);\n\t},\n\n\tdisable: function () {\n\t\tthis.stop();\n\t\tthis._resetPos(0);\n\t\tthis.enabled = false;\n\n\t\t// If disabled after touchstart we make sure that there are no left over events\n\t\tthis._unbind(MOVE_EV, window);\n\t\tthis._unbind(END_EV, window);\n\t\tthis._unbind(CANCEL_EV, window);\n\t},\n\t\n\tenable: function () {\n\t\tthis.enabled = true;\n\t},\n\t\n\tstop: function () {\n\t\tif (this.options.useTransition) this._unbind(TRNEND_EV);\n\t\telse cancelFrame(this.aniTime);\n\t\tthis.steps = [];\n\t\tthis.moved = false;\n\t\tthis.animating = false;\n\t},\n\t\n\tzoom: function (x, y, scale, time) {\n\t\tvar that = this,\n\t\t\trelScale = scale / that.scale;\n\n\t\tif (!that.options.useTransform) return;\n\n\t\tthat.zoomed = true;\n\t\ttime = time === undefined ? 200 : time;\n\t\tx = x - that.wrapperOffsetLeft - that.x;\n\t\ty = y - that.wrapperOffsetTop - that.y;\n\t\tthat.x = x - x * relScale + that.x;\n\t\tthat.y = y - y * relScale + that.y;\n\n\t\tthat.scale = scale;\n\t\tthat.refresh();\n\n\t\tthat.x = that.x > 0 ? 0 : that.x < that.maxScrollX ? that.maxScrollX : that.x;\n\t\tthat.y = that.y > that.minScrollY ? that.minScrollY : that.y < that.maxScrollY ? that.maxScrollY : that.y;\n\n\t\tthat.scroller.style[transitionDuration] = time + 'ms';\n\t\tthat.scroller.style[transform] = 'translate(' + that.x + 'px,' + that.y + 'px) scale(' + scale + ')' + translateZ;\n\t\tthat.zoomed = false;\n\t},\n\t\n\tisReady: function () {\n\t\treturn !this.moved && !this.zoomed && !this.animating;\n\t}\n};\n\nfunction prefixStyle (style) {\n\tif ( vendor === '' ) return style;\n\n\tstyle = style.charAt(0).toUpperCase() + style.substr(1);\n\treturn vendor + style;\n}\n\ndummyStyle = null;\t// for the sake of it\n\nif (typeof exports !== 'undefined') exports.iScroll = iScroll;\nelse window.iScroll = iScroll;\n\n})(window, document);\n"
  },
  {
    "path": "_archive/apps/samples/weather/main.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('weather.html', {\n    id: 'weather',\n    innerBounds: {\n      height: 450,\n      width: 300,\n    },\n    resizable: false\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/weather/manifest.json",
    "content": "{\n  \"name\": \"Weather\",\n  \"description\": \"A simple weather application.\",\n  \"manifest_version\": 2,\n  \"version\": \"1.0.7\",\n  \"minimum_chrome_version\": \"23\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"icons\": {\n    \"16\": \"img/icon.png\",\n    \"64\": \"img/icon.png\",\n    \"128\": \"img/icon.png\"\n  },\n  \"permissions\": [\n    \"geolocation\",\n    \"storage\",\n    \"<all_urls>\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/weather/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"weather\",\n  \"files_with_snippets\": [ ],\n  \"ios\": {\"works\": true}\n}\n"
  },
  {
    "path": "_archive/apps/samples/weather/style.css",
    "content": "html, body {\n  width: 100%;\n  height: 100%;\n  margin: 0px;\n  padding: 0px;\n  -webkit-app-region: drag;\n  color: #fff;\n  font-family: \"Quicksand\", \"Open Sans\", sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 18px;\n  text-align: center;\n  -webkit-user-select:none;\n  background-color: #444;\n}\n\na, #dots div {\n  -webkit-app-region: no-drag;\n}\n\n::-webkit-scrollbar {\n  width: 10px;\n  height: 10px;\n  border: 1px solid #fff;\n  -webkit-app-region: no-drag;\n}\n\n::-webkit-scrollbar-thumb {\n  background: #eee;\n  -webkit-app-region: no-drag;\n}\n\n.mobile #close {\n  display: none;\n}\n\n.not-mobile #close {\n  background: url('img/x.png') center no-repeat;\n  background-size: 10px 10px;\n  position: absolute;\n  top: 0px;\n  left: 0px;\n  height: 30px;\n  width: 30px;\n  cursor: pointer;\n  -webkit-app-region: no-drag;\n  z-index: 100;\n  visibility: hidden;\n}\n\nbody:hover.not-mobile #close {\n  visibility: visible;\n}\n\n#close {\n  display: none;\n}\n\n.button {\n  background-color: #f5f5f5;\n  background-image: linear-gradient(top, #f5f5f5, #f1f1f1);\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f1f1f1);\n  border: 1px solid rgba(0, 0, 0, 0.1);\n  border-radius: 2px;\n  -webkit-border-radius: 2px;\n  color: #444;\n  cursor: default;\n  display: inline-block;\n  font-size: 11px;\n  font-weight: bold;\n  height: 27px;\n  line-height: 27px;\n  margin-left: 0px;\n  margin-right: 10px;\n  margin-top: 0px;\n  margin-bottom: 10px;\n  min-width: 50px;\n  padding: 0 8px;\n  text-align: center;\n  transition: all 0.218s;\n  -webkit-transition: all 0.218s;\n  white-space: nowrap;\n  -webkit-app-region: no-drag;\n}\n\n.button:hover {\n  background-color: #f8f8f8;\n  background-image: -webkit-linear-gradient(top, #f8f8f8, #f1f1f1);\n  background-image: linear-gradient(top, #f8f8f8, #f1f1f1);\n  border: 1px solid #c6c6Cc;\n  box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);\n  -webkit-box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);\n  color: #222;\n  transition: all 0.0s;\n  -webkit-transition: all 0.0s;\n}\n\n.button:active {\n  background-color: #f6f6f6;\n  background-image: -webkit-linear-gradient(top, #f6f6f6, #f1f1f1);\n  background-image: linear-gradient(top, #f6f6f6, #f1f1f1);\n  border: 1px solid #c6c6c6;\n  box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);\n  -webkit-box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);\n  color: #333;\n}\n\n.button.blue {\n  background-color: #4d90fe;\n  background-image: -webkit-linear-gradient(top, #4d90fe, #4787ed);\n  background-image: linear-gradient(top, #4d90fe, #4787ed);\n  border: 1px solid #3079ed;\n  color: #fff;\n}\n\n.button.blue:hover {\n  background-color: #5093ff;\n  background-image: -webkit-linear-gradient(top, #5093ff, #4a8af0);\n  background-image: linear-gradient(top, #5093ff, #4a8af0);\n  border: 1px solid #337cf3;\n  box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.1);\n}\n\ninput[type=checkbox],\ninput[type=radio] {\n  -webkit-appearance: none;\n  width: 13px;\n  height: 13px;\n  border: 1px solid #c6c6c6;\n  background: #f5f5f5;\n  margin: 0;\n  margin-right: 10px;\n  margin-bottom: -2px;\n  margin-top: 2px;\n  -webkit-border-radius: 1px;\n  border-radius: 1px;\n  -webkit-box-sizing: border-box;\n  box-sizing: border-box;\n  cursor: default;\n  position: relative;\n  -webkit-app-region: no-drag;\n}\n\ninput[type=checkbox]:active,\ninput[type=radio]:active {\n  background: #fff;\n  border-color: #666;\n}\n\ninput[type=checkbox]:hover,\ninput[type=radio]:hover {\n  border-color: #666;\n  -webkit-box-shadow: inset 0px 1px 1px rgba(0,0,0,0.1);\n  box-shadow: inset 0px 1px 1px rgba(0,0,0,0.1);\n}\n\ninput[type=radio] {\n  border-radius: 50%;\n  width: 15px;\n  height: 15px;\n}\n\ninput[type=checkbox].disabled,\ninput[type=radio].disabled {\n  border-color:#f1f1f1;\n  background: #fff;\n  -webkit-box-shadow: none;\n  -moz-box-shadow: none;\n  box-shadow: none;\n}\n\n.disabledtext{\n  color: #b8b8b8;\n}\n\ninput[type=radio]:checked::after {\n  content: '';\n  display: block;\n  position: relative;\n  top: 3px;\n  left: 3px;\n  width: 7px;\n  height: 7px;\n  background: #666;\n  border-radius: 50%;\n}\n\ninput[type=checkbox]:focus {\n  outline: none;\n  border-color: #4d90fe;\n}\n\ninput[type=text] {\n  background-color: #fff;\n  border: 1px solid #d9d9d9;\n  border-top: 1px solid #c0c0c0;\n  box-sizing: border-box;\n  -webkit-box-sizing: border-box;\n  border-radius: 1 px;\n  -webkit-border-radius: 1px;\n  color: #333;\n  display: inline-block;\n  font-family: \"Quicksand\", \"Open Sans\", sans-serif;\n  font-size: 16px;\n  height: 32px;\n  line-height: 30px;\n  padding-left: 8px;\n  vertical-align: middle;\n  margin-bottom: 15px;\n  width: 270px;\n  -webkit-app-region: no-drag;\n}\n\ninput[type=text]:hover {\n  border: 1px solid #b9b9b9;\n  border-top: 1px solid #a0a0a0;\n  box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);\n  -webkit-box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.1);\n}\n\ninput[type=text]:focus {\n  border: 1px solid #4d90fe;\n  box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.3);\n  -webkit-box-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.3);\n  outline: none;\n}\n\ninput[type=text].form-error{\n  border: 1px solid #ff3f3f;\n}\n\n#error-message {\n  color: #ff3f3f;\n  padding: 0px;\n  margin-top: -5px;\n  margin-bottom: 5px;\n}\n\n#settings {\n  position: absolute;\n  top: 0px;\n  left: 0px;\n  bottom: 0px;\n  right: 0px;\n  background: #444;\n  text-align: left;\n  padding: 15px;\n  z-index: 1;\n}\n\n#settings #source,\n#settings #source a {\n  color: #fff;\n  font-size: 11px;\n  margin-bottom: 10px;\n  margin-top: 5px;\n  text-align: center;\n}\n\n#settings #new {\n  margin-bottom: 10px;\n}\n\n#settings #cities-list {\n  margin-top: 10px;\n  overflow: auto;\n}\n\n.not-mobile #settings #cities-list {\n  height: 180px;\n}\n\n.mobile #settings #cities-list {\n}\n\n#settings #cities-list .delete {\n  background: url('img/x.png') center no-repeat;\n  background-size: 12px 12px;\n  display: inline-block;\n  height: 30px;\n  opacity: 0.7;\n  width: 30px;\n  vertical-align: middle;\n}\n\n#settings #cities-list .delete:hover {\n  opacity: 1;\n}\n\n#settingsToggle {\n  background: url('img/settings.png') center no-repeat;\n  background-size: 14px 14px;\n  position: absolute;\n  top: 0px;\n  right: 0px;\n  cursor: pointer;\n  height: 40px;\n  width: 40px;\n  -webkit-app-region: no-drag;\n  z-index: 100;\n}\n\n#loading {\n  height: 100%;\n  width: 100%;\n  position: absolute;\n  white-space: nowrap;\n  overflow: hidden;\n  -webkit-box-sizing: border-box;\n  background-color: pink;\n  z-index: 10000;\n  -webkit-transition: opacity 0.5s ease-in;\n}\n\n#loading > div\n{\n  position: absolute;\n  width: 100%;\n  top: 50%;\n  margin-top: -100px;\n  text-align: center;\n}\n\n#loading > div > p\n{\n  font-size: 2em;\n}\n\n#loading > div > img {\n  -webkit-animation-name: spinnerRotate;\n  -webkit-animation-duration: 5s;\n  -webkit-animation-iteration-count: infinite;\n  -webkit-animation-timing-function: linear;\n}\n\n@-webkit-keyframes spinnerRotate {\n  from {\n    -webkit-transform:rotate(0deg);\n  }\n  to {\n    -webkit-transform:rotate(360deg);\n  }\n}\n\n#wrapper {\n  height: 100%;\n  width: 100%;\n  position: absolute;\n  white-space: nowrap;\n  overflow: hidden;\n  -webkit-box-sizing: border-box;\n}\n\n#weather {\n  height: 100%;\n  width: 100%;\n}\n\n#searchterm {\n  margin-top: 10px;\n}\n\n.forecast {\n  display: inline-block;\n  -webkit-box-sizing: border-box;\n  height: 100%;\n  width: 100%;\n  text-align: center;\n}\n\n\n.forecast.selected {\n}\n\n.city {\n  bottom: 45px;\n  font-size: 12px;\n  position: absolute;\n  text-align: center;\n  width: 100%;\n}\n\n.current {\n  text-align: center;\n  margin-top: 150px;\n}\n\n.current-icon {\n  height: 34px;\n  width: 34px;\n  display: inline-block;\n  margin-bottom: 10px;\n  margin-right: -34px;\n}\n\n.current-temp {\n  display: inline-block;\n  font-size: 72px;\n  font-weight: normal;\n}\n\n.high_low {\n  margin-top: 45px;\n  font-size: 21px;\n  display: block;\n  font-weight: normal;\n}\n\n#dots {\n  width: 200px;\n  text-align: center;\n  white-space: nowrap;\n  position: absolute;\n  bottom: 15px;\n  left: 50%;\n  margin-left: -100px;\n  overflow: auto;\n}\n\n#dots #prev,\n#dots #next {\n  width: 0;\n  height: 0;\n  border-top: 6px solid transparent;\n  border-bottom: 6px solid transparent;\n  display: inline-block;\n  margin-bottom: 4px;\n  opacity: 0;\n}\n\n#dots #prev {\n  border-right: 8px solid #fff;\n  margin-right: 5px;\n}\n\n#dots #next {\n  border-left: 8px solid #fff;\n  margin-left: 5px;\n}\n\n#dots #prev.disabled,\n#dots #next.disabled {\n  opacity: 0.4;\n}\n\n#dots #prev.shown,\n#dots #next.shown {\n  opacity: 1;\n}\n\n#dots .dot {\n    border: 2px solid #fff;\n  border-radius: 8px;\n  height: 10px;\n  margin: 3px;\n  width: 10px;\n  display: none;\n}\n\n#dots .dot.shown {\n  display: inline-block;\n}\n\n#dots .dot.selected {\n  background-color: #fff;\n}\n\n.current-icon.cloudy {\n  background: url('img/cloudy.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.hail {\n  background: url('img/hail.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.light-rain {\n  background: url('img/light-rain.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.light-snow {\n  background: url('img/light-snow.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.mostly-sunny {\n  background: url('img/mostly-sunny.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.partly-cloudy {\n  background: url('img/partly-cloudy.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.rain-snow {\n  background: url('img/rain-snow.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.rain {\n  background: url('img/rain.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.scattered-light-rain {\n  background: url('img/scattered-light-rain.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.scattered-rain {\n  background: url('img/scattered-rain.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.scattered-snow {\n  background: url('img/scattered-snow.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.scattered-tstorm {\n  background: url('img/scattered-tstorm.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.snow {\n  background: url('img/snow.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.sunny {\n  background: url('img/sunny.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.current-icon.tstorm {\n  background: url('img/tstorm.png') center no-repeat;\n  background-size: 34px 34px;\n}\n\n.forecast.cloudy {\n  background-color: #75d6ff;\n  background-image: linear-gradient(top, #75d6ff, #45a6dd);\n  background-image: -webkit-linear-gradient(top, #75d6ff, #45a6dd);\n}\n\n.forecast.hail {\n  background-color: #6f9fba;\n  background-image: linear-gradient(top, #6f9fba, #3f6f8a);\n  background-image: -webkit-linear-gradient(top, #6f9fba, #3f6f8a);\n}\n\n.forecast.light-rain {\n  background-color: #82bddf;\n  background-image: linear-gradient(top, #82bddf, #528daf);\n  background-image: -webkit-linear-gradient(top, #82bddf, #528daf);\n}\n\n.forecast.light-snow {\n  background-color: #c0e5ff;\n  background-image: linear-gradient(top, #c0e5ff, #90b5d7);\n  background-image: -webkit-linear-gradient(top, #c0e5ff, #90b5d7);\n}\n\n.forecast.mostly-sunny {\n  background-color: #a1d0ed;\n  background-image: linear-gradient(top, #a1d0ed, #71a0bd);\n  background-image: -webkit-linear-gradient(top, #a1d0ed, #71a0bd);\n }\n\n.forecast.partly-cloudy {\n  background-color: #f6b955;\n  background-image: linear-gradient(top, #f6b955, #d68925);\n  background-image: -webkit-linear-gradient(top, #f6b955, #d68925);\n}\n\n.forecast.rain-snow {\n  background-color: #6f9fba;\n  background-image: linear-gradient(top, #6f9fba, #3f6f8a);\n  background-image: -webkit-linear-gradient(top, #6f9fba, #3f6f8a);\n}\n\n.forecast.rain {\n  background-color: #78afce;\n  background-image: linear-gradient(top, #78afce, #487f9e);\n  background-image: -webkit-linear-gradient(top, #78afce, #487f9e);\n}\n\n.forecast.scattered-light-rain {\n  background-color: #8fd6fe;\n  background-image: linear-gradient(top, #8fd6fe, #5fa6ce);\n  background-image: -webkit-linear-gradient(top, #8fd6fe, #5fa6ce);\n}\n\n.forecast.scattered-rain {\n  background-color: #84c4e8;\n  background-image: linear-gradient(top, #84c4e8, #5494b8);\n  background-image: -webkit-linear-gradient(top, #84c4e8, #5494b8);\n}\n\n.forecast.scattered-snow {\n  background-color: #8ee5ff;\n  background-image: linear-gradient(top, #8ee5ff, #5eb5d7);\n  background-image: -webkit-linear-gradient(top, #8ee5ff, #5eb5d7);\n}\n\n.forecast.scattered-tstorm {\n  background-color: #3f4d55;\n  background-image: linear-gradient(top, #3f4d55, #0f1d25);\n  background-image: -webkit-linear-gradient(top, #3f4d55, #0f1d25);\n}\n\n.forecast.snow {\n  background-color: #c0e5ff;\n  background-image: linear-gradient(top, #c0e5ff, #90b5d7);\n  background-image: -webkit-linear-gradient(top, #c0e5ff, #90b5d7);\n }\n\n.forecast.sunny {\n  background-color: #ffc33b;\n  background-image: linear-gradient(top, #ffc33b, #ea930b);\n  background-image: -webkit-linear-gradient(top, #ffc33b, #ea930b);\n}\n\n.forecast.tstorm {\n  background-color: #3f4d55;\n  background-image: linear-gradient(top, #3f4d55, #0f1d25);\n  background-image: -webkit-linear-gradient(top, #3f4d55, #0f1d25);\n}\n\n.hidden {\n  /*display: none;*/\n  visibility: hidden;\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/weather/weather.html",
    "content": "<html>\n    <head>\n        <title>Weather</title>\n        <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\" />\n        <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />\n\n        <script type=\"text/javascript\" src=\"lib/jquery-1.7.2.min.js\"></script>\n        <script type=\"text/javascript\" src=\"lib/iscroll.js\"></script>\n        <script type=\"text/javascript\" src=\"weather.js\"></script>\n    </head>\n\n    <body>\n        <div id=\"close\"></div>\n        <div id=\"settingsToggle\"></div>\n\n        <div id=\"settings\" class=\"hidden\">\n            <div id=\"source\">\n                Powered by <a href=\"http://www.worldweatheronline.com/\" title=\"Free local weather content provider\" target=\"blank\">World Weather Online</a>\n            </div>\n\n            <div id=\"new\">\n                <input id=\"searchterm\" type=\"text\" /><br>\n                <div id=\"error-message\" class=\"hidden\"></div>\n                <div id=\"add\" class=\"button blue\">ADD</div>\n                <div id=\"cancel\" class=\"button\">CANCEL</div>\n            </div>\n\n            <input type=\"radio\" name=\"temp-type\" class=\"F\" value=\"F\">FAHRENHEIT</input>\n            <input type=\"radio\" name=\"temp-type\" class=\"C\" value=\"C\">CELSIUS</input>\n\n            <div id=\"cities-list\"></div>\n        </div>\n\n        <div id=\"loading\">\n          <div>\n            <img src=\"img/sunny.png\" />\n            <p>Checking the Weather</p>\n          </div>\n        </div>\n\n        <div id=\"wrapper\">\n          <div id=\"weather\"></div>\n        </div>\n\n        <div id=\"dots\">\n            <div id=\"prev\"></div>\n            <div id=\"next\"></div>\n        </div>\n    </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/weather/weather.js",
    "content": "/**\n * Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\n\n/* TODO: Bugs to fix:\n * \n * * Some formatter_address's are not formatted well for wether query\n *  * ie, search for dublin returns formatted_address: \"Dublin, Co. Dublin, Ireland\"\n *  and doing a weather search on that fails, so we dont add the city.\n\n/******************************************************************************/\n/******************************************************************************/\n/******************************************************************************/\n// consts\n\nconst num_dots_at_bottom = 4;\nconst base_weather_url = 'https://api.worldweatheronline.com/free/v1/weather.ashx?format=json&num_of_days=5&key=vfc3k7q22tjedr2rxse7xzke&q=';\nconst base_geolocation_url = 'http://maps.googleapis.com/maps/api/geocode/json?sensor=true&language=EN&latlng=';\nconst base_searchterm_url = 'http://maps.googleapis.com/maps/api/geocode/json?sensor=false&language=EN&address=';\n// Samples:\n// http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=kingston\n// http://maps.googleapis.com/maps/api/geocode/json?sensor=true&latlng=43.480926,-80.53766399999999\n\nconst days = {\n  0 : 'Sun',\n  1 : 'Mon',\n  2 : 'Tues',\n  3 : 'Wed',\n  4 : 'Thur',\n  5 : 'Fri',\n  6 : 'Sat'\n};\n\nconst condition_codes = {\n  113 : 'sunny',\n  116 : 'partly-cloudy',\n  119 : 'cloudy',\n  122 : 'cloudy',\n  143 : 'mostly-sunny',\n  176 : 'scattered-light-rain',\n  179 : 'light-snow',\n  182 : 'rain-snow',\n  185 : 'rain-snow',\n  200 : 'tstorm',\n  227 : 'snow',\n  230 : 'snow',\n  248 : 'cloudy',\n  260 : 'cloudy',\n  263 : 'scattered-light-rain',\n  266 : 'light-rain',\n  281 : 'rain-snow',\n  284 : 'rain-snow',\n  293 : 'scattered-light-rain',\n  296 : 'light-rain',\n  299 : 'light-rain',\n  302 : 'rain',\n  305 : 'rain',\n  308 : 'rain',\n  311 : 'rain',\n  314 : 'hail',\n  317 : 'rain-snow',\n  320 : 'rain-snow',\n  323 : 'light-snow',\n  326 : 'light-snow',\n  329 : 'scattered-snow',\n  332 : 'snow',\n  335 : 'scattered-snow',\n  338 : 'snow',\n  350 : 'hail',\n  353 : 'light-rain',\n  356 : 'rain',\n  359 : 'rain',\n  362 : 'rain-snow',\n  365 : 'rain-snow',\n  368 : 'light-snow',\n  371 : 'snow',\n  374 : 'hail',\n  377 : 'hail',\n  386 : 'scattered-light-rain',\n  389 : 'rain',\n  392 : 'light-snow',\n  395 : 'snow',\n};\n\n/******************************************************************************/\n/******************************************************************************/\n/******************************************************************************/\n// \"model\"\n\nfunction City(address) {\n  // TODO: this doesn't really need to be a member, can just be a method, and then we don't need to worry about changing id format & sync issues\n  this.id = City.ConvertAddressDomFriendly(address);\n  this.address = address;\n  this.date = new Date();\n}\n\nCity.ConvertAddressDomFriendly = function(address) {\n  // TODO: improve this\n  if (!address)\n    return;\n  return address.toLowerCase().replace(/,/g , \"-\").split(' ').join('-');\n}\n\nfunction Cities() {\n  this.cities = [];\n  this.version = Cities.CurrentVersion;\n}\n\nCities.CurrentVersion = 2;\n\nCities.prototype.sync = function() {\n  this.cities.forEach(function(city) {\n    city.date = city.date.toJSON();\n  });\n  chrome.storage.sync.set({ 'cities': this });\n  this.cities.forEach(function(city) {\n    city.date = new Date(city.date);\n  });\n}\n\nCities.prototype.add = function(city) {\n  this.cities.push(city);\n  this.sync();\n}\n\nCities.prototype.remove = function(city) {\n  this.cities.splice(this.cities.indexOf(city), 1);\n  this.sync();\n}\n\nCities.prototype.length = function() {\n  return this.cities.length;\n}\n\nCities.prototype.findByKey = function(key, value) {\n  for (var i = 0; i < this.cities.length; ++i) {\n    var city = this.cities[i];\n    if (city[key] === value)\n      return city;\n  }\n  return null;\n}\n\nCities.prototype.findById = function(value) {\n  return this.findByKey(\"id\", value);\n}\n\nCities.prototype.sortedByKey = function(key) {\n  return this.cities.slice(0).sort(function(a,b){\n    var ret = (typeof a[key] === 'string') ? a[key].localeCompare(b[key]) : a[key] - b[key];\n    return ret;\n  });\n}\n\nCities.prototype.ordered = function() {\n  return this.sortedByKey('date');\n}\n\nCities.prototype.asArray = function(key) {\n  return this.cities;\n}\n\nfunction WeatherData(city, current_condition, forecast) {\n  this.city = city;\n  this.current_condition = current_condition;\n  this.forecast = forecast;\n}\n\n/******************************************************************************/\n/******************************************************************************/\n/******************************************************************************/\n// globals\n\nvar temp = 'F';\nvar cities = null;\nvar current_city = null;\nvar weather_data = {}; // map city.id->WeatherData\nvar myScroll = null;\n\n/******************************************************************************/\n/******************************************************************************/\n/******************************************************************************/\n// \"controller\"\n\nfunction selectCity(city) {\n  if (!city)\n    return;\n  current_city = city.id;\n\n  $('.forecast').removeClass('selected');\n  $('.dot').removeClass('selected');\n  $('.forecast[city=' + city.id + ']').addClass('selected');\n  $('.dot[city=' + city.id + ']').addClass('selected');\n\n  refreshIScroll();\n  var index = cities.ordered().indexOf(getCurrentCity());\n  if (myScroll && myScroll.currPageX != index)\n    myScroll.scrollToPage(index);\n\n  setDots();\n}\n\nfunction deleteCity(city) {\n  if (!city)\n    return;\n  $('[city=' + city.id +']').remove();\n  delete weather_data[city.id];\n  cities.remove(city);\n  selectCity(getCurrentCity()); // in case we removed the previously selected city\n}\n\nfunction addCity(address) {\n  var id = City.ConvertAddressDomFriendly(address);\n  var city = cities.findById(id);\n  if (city != null)\n    return city;\n  city = new City(address);\n  cities.add(city);\n  return city;\n}\n\nfunction getCurrentCity() {\n  // TODO: do we need to use current_city global for this?  Can we just walk the DOM?\n  // we set the city we want to be current, before we add it to the dom?\n  var city = cities.findById(current_city);\n  if (!city && cities.length() > 0)\n    city = cities.asArray()[0];\n  return city;\n}\n\nfunction addWeatherData(city, current_condition, forecast) {\n  weather_data[city.id] = new WeatherData(city, current_condition, forecast);\n  refresh();\n}\n\nfunction currentlyOnSettingsPage() {\n  return !$('#settings').hasClass('hidden');\n}\n\nfunction refreshIScroll() {\n  if (!myScroll)\n    return;\n  setTimeout(function() {\n    myScroll.refresh();\n  }, 0);\n}\n\nfunction hideLoading() {\n  if ($('#loading').hasClass('fadeOut')) {\n    return;\n  }\n  $('#loading').css('opacity', 0);\n  setTimeout(function() {\n    $('#loading').addClass('hidden');\n  }, 500); // 500 comes from the fade out time in css\n}\n\nfunction hideSettings() {\n  $('#weather').removeClass('hidden');\n  $('#settings').addClass('hidden');\n  $('#dots').removeClass('hidden');\n  $('#searchterm').val('');\n  hideInputError();\n  selectCity(getCurrentCity());\n}\n\nfunction showSettings() {\n  $('#weather').addClass('hidden');\n  $('#settings').removeClass('hidden');\n  $('#dots').addClass('hidden');\n  $('#searchterm').focus();\n  hideInputError();\n}\n\nfunction showInputError(searchterm) {\n  $('#searchterm').addClass('form-error');\n  $('#new #error-message').text('Could not find weather for \\'' + searchterm + '\\'');\n  $('#new #error-message').removeClass('hidden');\n}\n\nfunction hideInputError() {\n  $('#searchterm').removeClass('form-error');\n  $('#searchterm').val('');\n  $('#new #error-message').addClass('hidden');\n  $('#new').removeClass('selected');\n}\n\nfunction adjustnext(n) {\n  var c = cities.ordered();\n  var index = c.indexOf(getCurrentCity());\n  var newCity = c[Math.min(c.length-1, index+n)];\n  selectCity(newCity);\n}\n\nfunction adjustprev(n) {\n  var c = cities.ordered();\n  var index = c.indexOf(getCurrentCity());\n  var newCity = c[Math.max(0, index-n)];\n  selectCity(newCity);\n}\n\nfunction attemptAddCity(searchurl, onsuccess, onerror) {\n  // TODO: figure out how to resolve conflicts when multiple cities returned\n  // Idea: seems to be duplication at the google api level, so maybe create a set of unique canonical id's, and then ask user to resolve?\n  $.get(searchurl, function(data) {\n    var formatted_address = null;\n    for (var i = 0; i < data.results.length; i++) {\n      if (data.results[i].types.indexOf('locality') != -1 || data.results[i].types.indexOf('administrative_area_level_1') != -1) {\n        formatted_address = data.results[i].formatted_address;\n        break;\n      }\n    }\n\n    if (!formatted_address) {\n      onerror && onerror();\n      return;\n    }\n\n    getWeatherData(formatted_address, function(current_condition, forecast) {\n      var city = addCity(formatted_address);\n      addWeatherData(city, current_condition, forecast);\n      onsuccess && onsuccess(city);\n    }, onerror);\n  }, 'json');\n}\n\nfunction getWeatherData(address, onsuccess, onerror) {\n  var url = encodeURI(base_weather_url + address);\n  $.get(url, function(data) {\n    if (!data.data.error) {\n      var current_condition = data.data.current_condition[0];\n      var forecast = data.data.weather;\n      onsuccess && onsuccess(current_condition, forecast);\n    } else {\n      onerror && onerror();\n    }\n  }, 'json');\n};\n\nfunction updateAllWeatherData(onfirstsuccessfulupdate) {\n  cities.asArray().forEach(function(city) {\n    getWeatherData(city.address,\n      function(current_condition, forecast) {\n        addWeatherData(city, current_condition, forecast);\n        onfirstsuccessfulupdate && onfirstsuccessfulupdate();\n      }, null); // TODO: handle error?\n  });\n}\n\nfunction attemptAddCurrentLocation() {\n  // TODO: we always permanentally add your current location.  Should keep a history of all places, but only display \"pinned\" places\n  // and the current location\n  var onfail = function(reason) {\n    console.warn(reason);\n    if (cities.length() != 0) {\n      return;\n    }\n    showSettings();\n    hideLoading();\n  };\n  navigator.geolocation.getCurrentPosition(\n    function(position) {\n      var searchurl = base_geolocation_url + position.coords.latitude + ',' + position.coords.longitude;\n      attemptAddCity(searchurl,\n        function(city) {\n          selectCity(city);\n          hideLoading();\n        },\n        onfail.bind(null, \"Could not find current location\")\n      );\n    },\n    onfail.bind(null, \"Geocoder failed\")\n  );\n}\n\n/******************************************************************************/\n/******************************************************************************/\n/******************************************************************************/\n// \"view\"\n\nfunction refresh() {\n  cities.sortedByKey('date').forEach(function(city) {\n    if (weather_data.hasOwnProperty(city.id)) {\n      var w = weather_data[city.id];\n      updateCityDisplay(city, w.current_condition, w.forecast);\n    }\n  });\n  refreshIScroll();\n}\n\nfunction updateCityDisplay(city, current_condition, forecast) {\n  // remove old city elements\n  $('[city=' + city.id + ']').remove();\n\n  var forecast_div = document.createElement('div');\n  var description = condition_codes[current_condition.weatherCode];\n  forecast_div.className = 'forecast ' + description;\n  forecast_div.setAttribute('city', city.id);\n  $('#weather').append(forecast_div);\n\n  forecast_div.appendChild(currentDisplay(current_condition));\n\n  var tempMax = forecast[0]['tempMax' + temp];\n  var tempMin = forecast[0]['tempMin' + temp];\n  var high_low_div = document.createElement('div');\n  high_low_div.className = 'high_low';\n  high_low_div.appendChild(document.createTextNode(tempMax + '\\u00B0 / ' + tempMin + '\\u00B0')); // &deg;\n  forecast_div.appendChild(high_low_div);\n\n  var city_div = document.createElement('div');\n  city_div.className = 'city';\n  city_div.appendChild(document.createTextNode(city.address));\n  forecast_div.appendChild(city_div);\n\n  /*\n  var day_html = '';\n  forecast.splice(1,4).forEach(function(forecast_day, i) {\n    day_html += dayDisplay(forecast_day, i);\n  });\n  $(forecast_div).append(day_html);\n  */\n\n  var city_list_div = document.createElement('div');\n  city_list_div.className = 'city-list';\n  city_list_div.setAttribute('city', city.id);\n  var delete_div = document.createElement('div');\n  delete_div.className = 'delete';\n  city_list_div.appendChild(delete_div);\n  city_list_div.appendChild(document.createTextNode(city.address));\n  $('#settings #cities-list').append(city_list_div);\n\n  var dot = document.createElement('div');\n  dot.className = 'dot';\n  dot.setAttribute('city', city.id);\n  dot.setAttribute('title', city.id);\n  $('#dots #next').before(dot);\n\n  // TODO: find a way to remove the need for this\n  if (city === getCurrentCity()) {\n    selectCity(city);\n  }\n\n  setDots();\n\n  // TODO\n  // What follows is a workaround for broken jquery \"live\" onclick functionality on mobile.\n  // Need to 'poke' elements so they are clickable.\n  Array.prototype.forEach.call(document.querySelectorAll('#dots .dot'), function(e,i) {\n    e.onclick = function(){};\n  });\n  Array.prototype.forEach.call(document.querySelectorAll('.city-list .delete'), function(e,i) {\n    e.onclick = function(){};\n  });\n}\n\nfunction setDots() {\n  if (cities.length() <= num_dots_at_bottom) {\n    $('.dot').addClass('shown');\n    $('#dots #prev').removeClass('disabled').removeClass('shown');\n    $('#dots #next').removeClass('disabled').removeClass('shown');\n  } else {\n    $('.dot').removeClass('shown');\n\n    var c = cities.ordered();\n    var index = c.indexOf(getCurrentCity());\n    var i = index % num_dots_at_bottom;\n    var first = index - i;\n    for (var l = first; l < first + num_dots_at_bottom && l < c.length; l++)\n      $('#dots .dot[city=' + c[l].id + ']').addClass('shown');\n\n    if (first === 0)\n      $('#dots #prev').removeClass('shown').addClass('disabled');\n    else\n      $('#dots #prev').addClass('shown').removeClass('disabled');\n\n    if ((first + num_dots_at_bottom) >= c.length)\n      $('#dots #next').removeClass('shown').addClass('disabled');\n    else\n      $('#dots #next').addClass('shown').removeClass('disabled');\n\n  }\n}\n\nfunction currentDisplay(current_condition) {\n  var current_temp = current_condition['temp_' + temp];\n  var current_description = current_condition.weatherDesc[0].value;\n  var current_icon = condition_codes[current_condition.weatherCode];\n  var current_div = document.createElement('div');\n  current_div.className = 'current';\n  var current_temp_div = document.createElement('div');\n  current_temp_div.className = 'current-temp';\n  current_temp_div.appendChild(document.createTextNode(current_temp));\n  var current_icon_div = document.createElement('div');\n  current_icon_div.className = 'current-icon ' + current_icon;\n  current_icon_div.setAttribute('title', current_description);\n  current_div.appendChild(current_temp_div);\n  current_div.appendChild(current_icon_div);\n  return current_div;\n}\n\nfunction dayDisplay(forecast_day, i) {\n  var day_condition = condition_codes[forecast_day.weatherCode];\n  var day_description = forecast_day.weatherDesc[0].value;\n  var date = forecast_day.date.split('-');\n  var day = days[((new Date().getDay() + i) % 7)];\n  var html = '<div class=\"day' + i + '\">' +\n                '<div class=\"date\">' + day + '</div>' +\n                '<div class=\"icon ' + day_condition + '\"' +\n                    ' title=\"' + day_description + '\"></div>' +\n                '<div class=\"high\">' + forecast_day['tempMax' + temp] + '&deg;</div>' +\n                '<div class=\"low\">' + forecast_day['tempMin' + temp] + '&deg;</div>' +\n              '</div>';\n  return html;\n}\n\n/******************************************************************************/\n/******************************************************************************/\n/******************************************************************************/\n// init\n\nfunction initHandlers() {\n  $('#close').click(function() {\n    window.close();\n  });\n\n  $('input[name=\"temp-type\"]').change(function() {\n    // TODO: this is firing twice per change!\n    temp = $('input[name=\"temp-type\"]:checked').val();\n    chrome.storage.sync.set({ 'temp' : temp });\n    updateAllWeatherData();\n  });\n\n  // TODO: remove the use of jQuery live()\n  $('#dots .dot').live('click', function() {\n    var id = this.getAttribute('city');\n    selectCity(cities.findById(id));\n  });\n\n  $('.delete').live('click', function() {\n    var id = this.parentElement.getAttribute('city');\n    deleteCity(cities.findById(id));\n  });\n\n  $('#new #add').click(function() {\n    var searchterm = $('#searchterm').val();\n    var searchurl = base_searchterm_url + searchterm;\n    // TODO: this will call onerror asyncronously -- should disable textbox during that time?\n    attemptAddCity(searchurl,\n      function(city) {\n        hideInputError();\n        selectCity(city);\n      }, showInputError.bind(null, searchterm));\n  });\n\n  $('#searchterm').keyup(function(e) {\n    if (event.which == 13) // enter\n      $('#new #add').click();\n    if (event.which == 27) // esc\n      $('#new #cancel').click();\n  });\n\n  $('#new #cancel').click(function() {\n    hideSettings();\n  });\n\n  $('#settingsToggle').click(function() {\n    if (currentlyOnSettingsPage())\n      hideSettings();\n    else\n      showSettings();\n  });\n\n\n  $('#dots #next.shown').live('click', function() {\n    adjustnext(num_dots_at_bottom);\n  });\n\n  $('#dots #prev.shown').live('click', function() {\n    adjustprev(num_dots_at_bottom);\n  });\n\n  $(document).keyup(function(event) {\n    if (currentlyOnSettingsPage())\n      return;\n    if (event.which == 39) // right-arrow\n      adjustnext(1);\n    else if (event.which == 37) // left-arrow\n      adjustprev(1);\n  });\n\n  // disable page scrolling only on main page\n  document.ontouchmove = function(e) {\n    if (!currentlyOnSettingsPage())\n      e.preventDefault();\n  };\n\n  document.addEventListener(\"backbutton\" , function(e) {\n    if (currentlyOnSettingsPage())\n      hideSettings();\n    else\n      window.navigator.app.exitApp();\n  }, false);\n}\n\nfunction init() {\n  $(document.body).addClass((window.cordova !== undefined) ? 'mobile' : 'not-mobile');\n\n  chrome.storage.sync.get(function(items) {\n    if (items.cities !== undefined && items.cities.version === Cities.CurrentVersion) {\n      cities = items.cities;\n      cities.__proto__ = Cities.prototype;\n      cities.asArray().forEach(function(city) {\n        city.__proto__ = City.prototype;\n        city.date = new Date(city.date);\n      });\n    } else {\n      cities = new Cities();\n    }\n    temp = items.temp;\n    if (!temp) temp = 'F';\n    $('input[name=\"temp-type\"].' + temp).attr('checked', true);\n    updateAllWeatherData(function() {\n      setTimeout(hideLoading, 300); // 300ms comes from the amount of time we want to give other cities to load weather\n    });\n  });\n\n  attemptAddCurrentLocation();\n\n  initHandlers();\n\n  setInterval(function() {\n    updateAllWeatherData();\n  }, 1000 * 60 * 5);\n\n  myScroll = new iScroll('wrapper', {\n    snap: true,\n    bounce: true,\n    momentum: false,\n    hScroll: true,\n    vScroll: false,\n    hScrollbar: false,\n    vScrollbar: false,\n    onScrollEnd: function () {\n      var city = cities.ordered()[this.currPageX];\n      selectCity(city);\n    },\n    onTouchEnd: function () {\n      var city = cities.ordered()[this.currPageX];\n      selectCity(city);\n    }\n  });\n}\n\n$(document).ready(function() {\n  if (typeof cordova !== 'undefined') {\n    document.addEventListener(\"deviceready\", init);\n  } else {\n    init();\n  }\n});\n\n/******************************************************************************/\n/******************************************************************************/\n/******************************************************************************/\n"
  },
  {
    "path": "_archive/apps/samples/web-store/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ndgidogppopohjpghapeojgoehfmflab\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n# Web Store API Sample App\n\nLets you upload and publish Chrome Apps and Extensions folders stored locally on your hard drive. The `chrome.identity` API is used to retrieve a valid token to authenticate against the [Chrome Web Store Publish API](http://developer.chrome.com/webstore/using_webstore_api). The zip process is handled by the external library [zip.js](http://gildas-lormeau.github.io/zip.js/) and the `chrome.fileSystem` API.\n\n## APIs\n\n* [runtime](http://developer.chrome.com/apps/app_runtime)\n* [window](http://developer.chrome.com/apps/app_window)\n* [identity](http://developer.chrome.com/apps/app_identity)\n* [fileSystem](http://developer.chrome.com/apps/fileSystem)\n* [storage](http://developer.chrome.com/apps/storage)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/web-store/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/web-store/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html',\n    { \n      \"id\": \"mainWindow\",\n      \"resizable\": false,\n      \"innerBounds\": { \"width\": 360, \"height\": 540 }\n    });\n});\n"
  },
  {
    "path": "_archive/apps/samples/web-store/css/index.css",
    "content": "html,body {\n    height: 100%;\n}\n\nbody {\n    background-color: #EEE;\n    margin: 0 auto;\n}\n\n.header {\n    background: url(../images/add.png) 50% no-repeat;\n    border-radius: 50%;\n    cursor: hand;\n    height: 50px;\n    margin: 4px auto 0;\n    width: 50px;\n}\n\n#projects {\n    height: 482px;\n    margin-left: 7px;\n    margin-top: 4px;\n    overflow-x: hidden;\n    overflow-y: overlay;\n}\n\n#console {\n    background: #FEFA8E;\n    border-top: 2px solid #ddd;\n    bottom: 0;\n    height: 80px;\n    padding-top: 4px;\n    position: fixed;\n    transition: all .4s ease-in-out;\n}\n\n#console.hidden {\n    height: 0px;\n    padding-top: 0px;\n}\n\n.failure {\n    background-color: #FF4500!important;\n}\n\n.success {\n    background-color: #ADE7AE!important;\n}\n\n.working {\n    background-color: #FE9375!important;\n}\n\n.project {\n    background: #FFF;\n    background-position: 0 100%;\n    background-repeat: no-repeat;\n    border-radius: 1px;\n    box-shadow: 0 2px 1px rgba(0,0,0,0.08);\n    height: 156px;\n    margin: 0 8px 16px;\n    width: 328px;\n}\n\n.project button {\n    background: #BEBEBE;\n    border: 0;\n    border-radius: 1px;\n    color: #FFF;\n    cursor: hand;\n    float: right;\n    font-weight: 700;\n    height: 30px;\n    margin-right: 8px;\n    margin-top: 24px;\n    outline: none;\n    text-transform: uppercase;\n    width: 92px;\n}\n\n.project button:disabled {\n    cursor: default;\n    opacity: .3;\n}\n\n.project input {\n    border: 1px solid #EEE;\n    border-radius: 3px;\n    float: left;\n    font-size: 100%;\n    height: 30px;\n    margin-left: 128px;\n    outline: none;\n    padding-left: 4px;\n    width: 192px;\n}\n\n.project .title {\n    float: left;\n    font-weight: 700;\n    line-height: 36px;\n    overflow: hidden;\n    padding-left: 16px;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n    width: 100%;\n}\n\n.project .webstore-link {\n    color: dodgerblue;\n    cursor: hand;\n    line-height: 36px;\n    position: absolute;\n    right: 26px;\n    text-decoration: underline;\n}\n\n.project .webstore-link.disabled {\n    cursor: default;\n    opacity: .3;\n}\n\n.project .path {\n    float: left;\n    margin-bottom: 8px;\n    margin-left: 132px;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n    width: 180px;\n}\n\n::-webkit-scrollbar {\n    height: 16px;\n    overflow: visible;\n    width: 16px;\n}\n\n::-webkit-scrollbar-thumb {\n    background-clip: padding-box;\n    background-color: rgba(0,0,0,0.2);\n    border: solid rgba(0,0,0,0);\n    border-width: 1px 1px 1px 6px;\n    box-shadow: inset 1px 1px 0 rgba(0,0,0,0.1),inset 0 -1px 0 rgba(0,0,0,0.07);\n    min-height: 28px;\n    padding: 100px 0 0;\n}\n\n::-webkit-scrollbar-button {\n    height: 0;\n    width: 0;\n}\n\n::-webkit-scrollbar-track {\n    background-clip: padding-box;\n    border: solid rgba(0,0,0,0);\n    border-width: 0 0 0 4px;\n}\n\n::-webkit-scrollbar-corner {\n    background: rgba(0,0,0,0);\n}\n"
  },
  {
    "path": "_archive/apps/samples/web-store/index.html",
    "content": "<html>\n  <head>\n    <link rel=\"stylesheet\" href=\"css/index.css\">\n  </head>\n  <body>\n    <div id=\"add-project\" class=\"header\"></div>\n    <div id=\"projects\"></div>\n    <div id=\"console\" class=\"hidden\"></div>\n    \n    <script src=\"js/zip/zip.js\"></script>\n    <script src=\"js/webstore.js\"></script>\n    <script src=\"js/index.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/web-store/js/index.js",
    "content": "function updateIdInput(button, itemId) {\n  var input = button.parentNode.querySelector('input');\n  input.value = itemId;\n  updateVisibleButtons(input);\n}\n\nfunction updateVisibleButtons(input) {\n  var enabled = (input.value && input.value.length === 32);\n  var webStoreLink = input.parentNode.querySelector('.webstore-link');\n  input.parentNode.querySelector('.publish').disabled = !enabled; \n  if (enabled)\n    webStoreLink.classList.remove('disabled');\n  else\n    webStoreLink.classList.add('disabled');\n}\n\nfunction setSuccessButton(button) {\n  button.textContent = 'success';\n  button.classList.add('success');\n}\n\nfunction setFailureButton(button) {\n  button.textContent = 'failure';\n  button.classList.add('failure');\n}\n\nfunction resetButton(button) {\n  setTimeout(function() {\n    button.classList.remove('success', 'failure');\n    if (button.classList.contains('publish'))\n      button.textContent = 'publish';\n    else if (button.classList.contains('upload'))\n      button.textContent = 'upload';\n  }, 2000);\n}\n\nfunction onWebStoreLinkClicked() {\n  var input = this.parentNode.querySelector('input');\n  var url = 'https://chrome.google.com/webstore/developer/edit/' + input.value;\n  window.open(url);\n}\n\nvar console = document.querySelector('#console');\nfunction showError(response) {\n  console.textContent = JSON.stringify(response, null, 2);\n  console.classList.remove('hidden');\n  setTimeout(function() {\n    console.classList.add('hidden');\n  }, 5000);\n}\n\n// Handles click on Upload button.\nfunction onUploadButtonClicked() {\n  var directoryEntryId = this.parentNode.dataset.directoryEntryId;\n  var itemId = this.parentNode.querySelector('input').value;\n\n  var button = this;\n  button.classList.add('working');\n  button.textContent = 'packing';\n  chrome.fileSystem.restoreEntry(directoryEntryId, function(directoryEntry) {\n    var directories = [];\n    var files = [];\n    var reader = directoryEntry.createReader();\n\n    function scan(entries) {\n      // when the size of the entries array is 0, we've processed all the\n      // directory contents\n      if (entries.length == 0) {\n        if (directories.length > 0) {\n          reader = directories.shift().createReader();\n          reader.readEntries(scan);\n        } else {\n          zip.workerScriptsPath = chrome.runtime.getURL('js/zip/');\n          zip.createWriter(new zip.BlobWriter('application/zip'),\n              function(zipWriter) {\n\n            (function writeToZip(index) {\n              if (index == files.length) {\n                zipWriter.close(function(blob) {\n                  button.textContent = 'uploading';\n                  webstore.upload(itemId, blob, function(error, status, response) {\n                    button.classList.remove('working');\n                    if (response.uploadState === 'SUCCESS') {\n                      setSuccessButton(button);\n                      updateIdInput(button, response.id);\n                    } else {\n                      setFailureButton(button);\n                      showError(error || response);\n                    }\n                    resetButton(button);\n                  });\n                });\n                return;\n              }\n              var entry = files[index];\n              entry.file(function(file) {\n                zipWriter.add(entry.fullPath, new zip.BlobReader(file),\n                    function() {\n                  writeToZip(++index);\n                });\n              });\n            })(0);\n          });\n        }\n        return;\n      }\n      for (var i = 0; i < entries.length; i++) {\n         if (entries[i].isDirectory) {\n           // Skip .git folder.\n           if (entries[i].name !== '.git')\n             directories.push(entries[i]);\n         } else {\n           files.push(entries[i]);\n         }\n      }\n      // readEntries has to be called until it returns an empty array.\n      // According to the spec, the function might not return all of the\n      // directory's contents during a given call.\n      reader.readEntries(scan);\n    }\n    reader.readEntries(scan);\n  });\n}\n\n// Handles click on Publish button.\nfunction onPublishButtonClicked() {\n  var button = this;\n  var directoryEntryId = button.parentNode.dataset.directoryEntryId;\n  var itemId = button.parentNode.querySelector('input').value;\n\n  if (!itemId)\n    return;\n         \n  // Save item Id before publishing to the webstore.\n  var id = {};\n  id[directoryEntryId] = itemId; \n  chrome.storage.local.set(id, function() {  \n    button.classList.add('working');\n    button.textContent = 'uploading';\n    webstore.publish(itemId, function(error, status, response) {\n      button.classList.remove('working');\n      if (response.status && response.status[0] === 'OK') {\n        setSuccessButton(button);\n      } else {\n        setFailureButton(button);\n        showError(error || response);\n      }\n      resetButton(button);\n    });\n  });\n}\n\n// Get Project 128x128 icon Data URL defined in manifest.\nfunction getProjectIcon(directoryEntry, manifest, callback) {\n  // If it doesn't exist, return a default image URL.\n  if (!manifest.icons || !manifest.icons[128]) {\n    callback(chrome.runtime.getURL('images/extension_icon.png'));\n    return;\n  }\n  directoryEntry.getFile(manifest.icons[128], {}, function(fileEntry) {\n    fileEntry.file(function(file) {\n      var reader = new FileReader();\n      reader.onloadend = function() {\n        callback(this.result);\n      };\n      reader.readAsDataURL(file);\n    });\n  });\n}\n\n// Get Project manifest from directory Entry.\nfunction getProjectManifest(directoryEntry, callback) {\n  directoryEntry.getFile('manifest.json', {}, function(fileEntry) {\n    fileEntry.file(function(file) {\n      var reader = new FileReader();\n      reader.onloadend = function() {\n        try {\n          var manifest = JSON.parse(this.result);\n          callback(manifest);          \n        } catch(e) {\n          console.error(e);\n        }\n      };\n      reader.readAsText(file);\n    });\n  });\n}\n\nvar projectsContainer = document.querySelector('#projects');\n// Create project div.\nfunction createProjectDiv(directoryEntry, directoryEntryId, callback) {\n  getProjectManifest(directoryEntry, function(manifest) {\n    getProjectIcon(directoryEntry, manifest, function(iconUrl) {\n      var projectDiv = document.createElement('div');\n      projectDiv.classList.add('project');\n      projectDiv.dataset.directoryEntryId = directoryEntryId;\n      projectDiv.style.backgroundImage = 'url(' + iconUrl + ')';\n\n      var title = document.createElement('div');\n      title.classList.add('title');\n      title.textContent = manifest.name;\n      projectDiv.appendChild(title);\n\n      var webstoreLink = document.createElement('div');\n      webstoreLink.classList.add('webstore-link');\n      webstoreLink.textContent = 'Web Store';\n      webstoreLink.addEventListener('click', onWebStoreLinkClicked);\n      projectDiv.appendChild(webstoreLink);\n\n      var path = document.createElement('div');\n      path.classList.add('path');\n      chrome.fileSystem.getDisplayPath(directoryEntry,\n          function(displayPath) {\n        path.textContent = displayPath;\n      });\n      projectDiv.appendChild(path);\n\n      var idInput = document.createElement('input');\n      idInput.placeholder = 'Enter ID or leave empty';\n      idInput.addEventListener('input', function() {\n          updateVisibleButtons(this);\n      });\n      chrome.storage.local.get(directoryEntryId, function(results) {\n        var id = results[directoryEntryId];\n        idInput.value = id || '';        \n        updateVisibleButtons(idInput);\n      });\n      projectDiv.appendChild(idInput);\n\n      var publishButton = document.createElement('button');\n      publishButton.textContent = 'Publish';\n      publishButton.classList.add('publish');\n      publishButton.addEventListener('click', onPublishButtonClicked);\n      projectDiv.appendChild(publishButton);\n\n      var uploadButton = document.createElement('button');\n      uploadButton.textContent = 'Upload';\n      uploadButton.classList.add('upload');\n      uploadButton.addEventListener('click', onUploadButtonClicked);\n      projectDiv.appendChild(uploadButton);\n      \n      projectsContainer.insertBefore(projectDiv, projectsContainer.firstChild);\n      callback();\n    });\n  });\n}\n\n// Insert project backed up by its retained entry Id.\nfunction insertProject(directoryEntryId, callback) {\n  chrome.fileSystem.restoreEntry(directoryEntryId, function(directoryEntry) {\n    if (chrome.runtime.lastError)\n      return;\n    createProjectDiv(directoryEntry, directoryEntryId, callback);\n  });\n}\n\nvar addProjectButton = document.querySelector('#add-project');\n// Open directory picker.\naddProjectButton.addEventListener('click', function() {\n  chrome.fileSystem.chooseEntry({ type: 'openDirectory' },\n      function(directoryEntry) {\n    if (!directoryEntry)\n      return;\n    // Retain directory entry id.\n    var directoryEntryId = chrome.fileSystem.retainEntry(directoryEntry);\n    insertProject(directoryEntryId, function() {      \n      getDirectoryEntryIds(function(directoryEntryIds) {\n        directoryEntryIds.splice(0, 0, directoryEntryId);\n\tchrome.storage.local.set({'directoryEntryIds' : directoryEntryIds });\n      });\n    });\n  });\n});\n\n// Get retained directory entry Ids from local storage.\nfunction getDirectoryEntryIds(callback) {\n  chrome.storage.local.get('directoryEntryIds', function(results) {\n    var directoryEntryIds = results.directoryEntryIds || [];\n    callback(directoryEntryIds);\n  });\n}\n\n// Restore retained directories on load.\ngetDirectoryEntryIds(function(directoryEntryIds) {\n  var i = directoryEntryIds.length - 1;\n  if (i < 0)\n    return;\n  insertProject(directoryEntryIds[i], function callback() {\n    if (--i >= 0)\n      insertProject(directoryEntryIds[i], callback);\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/web-store/js/webstore.js",
    "content": "var webstore = (function() {\n    \n  function send(method, pathName, data, callback) {\n    var token;\n    var retry = true;\n\n    getToken();\n\n    function getToken() {\n      chrome.identity.getAuthToken({ interactive: true }, function(authToken) {\n        if (chrome.runtime.lastError) {\n          callback(chrome.runtime.lastError);\n          return;\n        }\n\n        token = authToken;\n        start();\n      });\n    }\n\n    function start() {\n      var xhr = new XMLHttpRequest();\n      xhr.open(method, 'https://www.googleapis.com' + pathName);\n      xhr.setRequestHeader('Authorization', 'Bearer ' + token);\n      xhr.responseType = 'json';\n      xhr.onload = onLoad;\n      xhr.send(data);\n    }\n\n    function onLoad() {\n      if (this.status == 401 && retry) {\n        retry = false;\n\tchrome.identity.removeCachedAuthToken({ token: token }, getToken);\n      } else {\n        callback(null, this.status, this.response);\n      }\n    }\n  }\n  \n  function publish(itemId, callback) {\n    send('POST', '/chromewebstore/v1.1/items/' + itemId + '/publish', null, callback);\n  }\n  \n  function upload(itemId, data, callback) {\n    var pathName = '/upload/chromewebstore/v1.1/items/';\n    if (!itemId)\n      send('POST', pathName, data, callback);\n    else \n      send('PUT', pathName + itemId, data, callback);\n  }\n  \n  return {\n    publish: publish,\n    upload: upload,\n  }\n\n})();\n"
  },
  {
    "path": "_archive/apps/samples/web-store/js/zip/deflate.js",
    "content": "/*\n Copyright (c) 2012 Gildas Lormeau. All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n\n 1. Redistributions of source code must retain the above copyright notice,\n this list of conditions and the following disclaimer.\n\n 2. Redistributions in binary form must reproduce the above copyright \n notice, this list of conditions and the following disclaimer in \n the documentation and/or other materials provided with the distribution.\n\n 3. The names of the authors may not be used to endorse or promote products\n derived from this software without specific prior written permission.\n\n THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\n INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\n INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\n INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\n OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc.\n * JZlib is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\n(function(obj) {\n\n\t// Global\n\n\tvar MAX_BITS = 15;\n\tvar D_CODES = 30;\n\tvar BL_CODES = 19;\n\n\tvar LENGTH_CODES = 29;\n\tvar LITERALS = 256;\n\tvar L_CODES = (LITERALS + 1 + LENGTH_CODES);\n\tvar HEAP_SIZE = (2 * L_CODES + 1);\n\n\tvar END_BLOCK = 256;\n\n\t// Bit length codes must not exceed MAX_BL_BITS bits\n\tvar MAX_BL_BITS = 7;\n\n\t// repeat previous bit length 3-6 times (2 bits of repeat count)\n\tvar REP_3_6 = 16;\n\n\t// repeat a zero length 3-10 times (3 bits of repeat count)\n\tvar REPZ_3_10 = 17;\n\n\t// repeat a zero length 11-138 times (7 bits of repeat count)\n\tvar REPZ_11_138 = 18;\n\n\t// The lengths of the bit length codes are sent in order of decreasing\n\t// probability, to avoid transmitting the lengths for unused bit\n\t// length codes.\n\n\tvar Buf_size = 8 * 2;\n\n\t// JZlib version : \"1.0.2\"\n\tvar Z_DEFAULT_COMPRESSION = -1;\n\n\t// compression strategy\n\tvar Z_FILTERED = 1;\n\tvar Z_HUFFMAN_ONLY = 2;\n\tvar Z_DEFAULT_STRATEGY = 0;\n\n\tvar Z_NO_FLUSH = 0;\n\tvar Z_PARTIAL_FLUSH = 1;\n\tvar Z_FULL_FLUSH = 3;\n\tvar Z_FINISH = 4;\n\n\tvar Z_OK = 0;\n\tvar Z_STREAM_END = 1;\n\tvar Z_NEED_DICT = 2;\n\tvar Z_STREAM_ERROR = -2;\n\tvar Z_DATA_ERROR = -3;\n\tvar Z_BUF_ERROR = -5;\n\n\t// Tree\n\n\t// see definition of array dist_code below\n\tvar _dist_code = [ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,\n\t\t\t10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\n\t\t\t12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,\n\t\t\t13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n\t\t\t14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n\t\t\t14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\n\t\t\t15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19,\n\t\t\t20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n\t\t\t24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n\t\t\t26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,\n\t\t\t27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n\t\t\t28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29,\n\t\t\t29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,\n\t\t\t29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 ];\n\n\tfunction Tree() {\n\t\tvar that = this;\n\n\t\t// dyn_tree; // the dynamic tree\n\t\t// max_code; // largest code with non zero frequency\n\t\t// stat_desc; // the corresponding static tree\n\n\t\t// Compute the optimal bit lengths for a tree and update the total bit\n\t\t// length\n\t\t// for the current block.\n\t\t// IN assertion: the fields freq and dad are set, heap[heap_max] and\n\t\t// above are the tree nodes sorted by increasing frequency.\n\t\t// OUT assertions: the field len is set to the optimal bit length, the\n\t\t// array bl_count contains the frequencies for each bit length.\n\t\t// The length opt_len is updated; static_len is also updated if stree is\n\t\t// not null.\n\t\tfunction gen_bitlen(s) {\n\t\t\tvar tree = that.dyn_tree;\n\t\t\tvar stree = that.stat_desc.static_tree;\n\t\t\tvar extra = that.stat_desc.extra_bits;\n\t\t\tvar base = that.stat_desc.extra_base;\n\t\t\tvar max_length = that.stat_desc.max_length;\n\t\t\tvar h; // heap index\n\t\t\tvar n, m; // iterate over the tree elements\n\t\t\tvar bits; // bit length\n\t\t\tvar xbits; // extra bits\n\t\t\tvar f; // frequency\n\t\t\tvar overflow = 0; // number of elements with bit length too large\n\n\t\t\tfor (bits = 0; bits <= MAX_BITS; bits++)\n\t\t\t\ts.bl_count[bits] = 0;\n\n\t\t\t// In a first pass, compute the optimal bit lengths (which may\n\t\t\t// overflow in the case of the bit length tree).\n\t\t\ttree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap\n\n\t\t\tfor (h = s.heap_max + 1; h < HEAP_SIZE; h++) {\n\t\t\t\tn = s.heap[h];\n\t\t\t\tbits = tree[tree[n * 2 + 1] * 2 + 1] + 1;\n\t\t\t\tif (bits > max_length) {\n\t\t\t\t\tbits = max_length;\n\t\t\t\t\toverflow++;\n\t\t\t\t}\n\t\t\t\ttree[n * 2 + 1] = bits;\n\t\t\t\t// We overwrite tree[n*2+1] which is no longer needed\n\n\t\t\t\tif (n > that.max_code)\n\t\t\t\t\tcontinue; // not a leaf node\n\n\t\t\t\ts.bl_count[bits]++;\n\t\t\t\txbits = 0;\n\t\t\t\tif (n >= base)\n\t\t\t\t\txbits = extra[n - base];\n\t\t\t\tf = tree[n * 2];\n\t\t\t\ts.opt_len += f * (bits + xbits);\n\t\t\t\tif (stree)\n\t\t\t\t\ts.static_len += f * (stree[n * 2 + 1] + xbits);\n\t\t\t}\n\t\t\tif (overflow === 0)\n\t\t\t\treturn;\n\n\t\t\t// This happens for example on obj2 and pic of the Calgary corpus\n\t\t\t// Find the first bit length which could increase:\n\t\t\tdo {\n\t\t\t\tbits = max_length - 1;\n\t\t\t\twhile (s.bl_count[bits] === 0)\n\t\t\t\t\tbits--;\n\t\t\t\ts.bl_count[bits]--; // move one leaf down the tree\n\t\t\t\ts.bl_count[bits + 1] += 2; // move one overflow item as its brother\n\t\t\t\ts.bl_count[max_length]--;\n\t\t\t\t// The brother of the overflow item also moves one step up,\n\t\t\t\t// but this does not affect bl_count[max_length]\n\t\t\t\toverflow -= 2;\n\t\t\t} while (overflow > 0);\n\n\t\t\tfor (bits = max_length; bits !== 0; bits--) {\n\t\t\t\tn = s.bl_count[bits];\n\t\t\t\twhile (n !== 0) {\n\t\t\t\t\tm = s.heap[--h];\n\t\t\t\t\tif (m > that.max_code)\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\tif (tree[m * 2 + 1] != bits) {\n\t\t\t\t\t\ts.opt_len += (bits - tree[m * 2 + 1]) * tree[m * 2];\n\t\t\t\t\t\ttree[m * 2 + 1] = bits;\n\t\t\t\t\t}\n\t\t\t\t\tn--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Reverse the first len bits of a code, using straightforward code (a\n\t\t// faster\n\t\t// method would use a table)\n\t\t// IN assertion: 1 <= len <= 15\n\t\tfunction bi_reverse(code, // the value to invert\n\t\tlen // its bit length\n\t\t) {\n\t\t\tvar res = 0;\n\t\t\tdo {\n\t\t\t\tres |= code & 1;\n\t\t\t\tcode >>>= 1;\n\t\t\t\tres <<= 1;\n\t\t\t} while (--len > 0);\n\t\t\treturn res >>> 1;\n\t\t}\n\n\t\t// Generate the codes for a given tree and bit counts (which need not be\n\t\t// optimal).\n\t\t// IN assertion: the array bl_count contains the bit length statistics for\n\t\t// the given tree and the field len is set for all tree elements.\n\t\t// OUT assertion: the field code is set for all tree elements of non\n\t\t// zero code length.\n\t\tfunction gen_codes(tree, // the tree to decorate\n\t\tmax_code, // largest code with non zero frequency\n\t\tbl_count // number of codes at each bit length\n\t\t) {\n\t\t\tvar next_code = []; // next code value for each\n\t\t\t// bit length\n\t\t\tvar code = 0; // running code value\n\t\t\tvar bits; // bit index\n\t\t\tvar n; // code index\n\t\t\tvar len;\n\n\t\t\t// The distribution counts are first used to generate the code values\n\t\t\t// without bit reversal.\n\t\t\tfor (bits = 1; bits <= MAX_BITS; bits++) {\n\t\t\t\tnext_code[bits] = code = ((code + bl_count[bits - 1]) << 1);\n\t\t\t}\n\n\t\t\t// Check that the bit counts in bl_count are consistent. The last code\n\t\t\t// must be all ones.\n\t\t\t// Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,\n\t\t\t// \"inconsistent bit counts\");\n\t\t\t// Tracev((stderr,\"\\ngen_codes: max_code %d \", max_code));\n\n\t\t\tfor (n = 0; n <= max_code; n++) {\n\t\t\t\tlen = tree[n * 2 + 1];\n\t\t\t\tif (len === 0)\n\t\t\t\t\tcontinue;\n\t\t\t\t// Now reverse the bits\n\t\t\t\ttree[n * 2] = bi_reverse(next_code[len]++, len);\n\t\t\t}\n\t\t}\n\n\t\t// Construct one Huffman tree and assigns the code bit strings and lengths.\n\t\t// Update the total bit length for the current block.\n\t\t// IN assertion: the field freq is set for all tree elements.\n\t\t// OUT assertions: the fields len and code are set to the optimal bit length\n\t\t// and corresponding code. The length opt_len is updated; static_len is\n\t\t// also updated if stree is not null. The field max_code is set.\n\t\tthat.build_tree = function(s) {\n\t\t\tvar tree = that.dyn_tree;\n\t\t\tvar stree = that.stat_desc.static_tree;\n\t\t\tvar elems = that.stat_desc.elems;\n\t\t\tvar n, m; // iterate over heap elements\n\t\t\tvar max_code = -1; // largest code with non zero frequency\n\t\t\tvar node; // new node being created\n\n\t\t\t// Construct the initial heap, with least frequent element in\n\t\t\t// heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].\n\t\t\t// heap[0] is not used.\n\t\t\ts.heap_len = 0;\n\t\t\ts.heap_max = HEAP_SIZE;\n\n\t\t\tfor (n = 0; n < elems; n++) {\n\t\t\t\tif (tree[n * 2] !== 0) {\n\t\t\t\t\ts.heap[++s.heap_len] = max_code = n;\n\t\t\t\t\ts.depth[n] = 0;\n\t\t\t\t} else {\n\t\t\t\t\ttree[n * 2 + 1] = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// The pkzip format requires that at least one distance code exists,\n\t\t\t// and that at least one bit should be sent even if there is only one\n\t\t\t// possible code. So to avoid special checks later on we force at least\n\t\t\t// two codes of non zero frequency.\n\t\t\twhile (s.heap_len < 2) {\n\t\t\t\tnode = s.heap[++s.heap_len] = max_code < 2 ? ++max_code : 0;\n\t\t\t\ttree[node * 2] = 1;\n\t\t\t\ts.depth[node] = 0;\n\t\t\t\ts.opt_len--;\n\t\t\t\tif (stree)\n\t\t\t\t\ts.static_len -= stree[node * 2 + 1];\n\t\t\t\t// node is 0 or 1 so it does not have extra bits\n\t\t\t}\n\t\t\tthat.max_code = max_code;\n\n\t\t\t// The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,\n\t\t\t// establish sub-heaps of increasing lengths:\n\n\t\t\tfor (n = Math.floor(s.heap_len / 2); n >= 1; n--)\n\t\t\t\ts.pqdownheap(tree, n);\n\n\t\t\t// Construct the Huffman tree by repeatedly combining the least two\n\t\t\t// frequent nodes.\n\n\t\t\tnode = elems; // next internal node of the tree\n\t\t\tdo {\n\t\t\t\t// n = node of least frequency\n\t\t\t\tn = s.heap[1];\n\t\t\t\ts.heap[1] = s.heap[s.heap_len--];\n\t\t\t\ts.pqdownheap(tree, 1);\n\t\t\t\tm = s.heap[1]; // m = node of next least frequency\n\n\t\t\t\ts.heap[--s.heap_max] = n; // keep the nodes sorted by frequency\n\t\t\t\ts.heap[--s.heap_max] = m;\n\n\t\t\t\t// Create a new node father of n and m\n\t\t\t\ttree[node * 2] = (tree[n * 2] + tree[m * 2]);\n\t\t\t\ts.depth[node] = Math.max(s.depth[n], s.depth[m]) + 1;\n\t\t\t\ttree[n * 2 + 1] = tree[m * 2 + 1] = node;\n\n\t\t\t\t// and insert the new node in the heap\n\t\t\t\ts.heap[1] = node++;\n\t\t\t\ts.pqdownheap(tree, 1);\n\t\t\t} while (s.heap_len >= 2);\n\n\t\t\ts.heap[--s.heap_max] = s.heap[1];\n\n\t\t\t// At this point, the fields freq and dad are set. We can now\n\t\t\t// generate the bit lengths.\n\n\t\t\tgen_bitlen(s);\n\n\t\t\t// The field len is now set, we can generate the bit codes\n\t\t\tgen_codes(tree, that.max_code, s.bl_count);\n\t\t};\n\n\t}\n\n\tTree._length_code = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16,\n\t\t\t16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t\t\t20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t\t\t22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n\t\t\t24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,\n\t\t\t25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,\n\t\t\t26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 ];\n\n\tTree.base_length = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0 ];\n\n\tTree.base_dist = [ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384,\n\t\t\t24576 ];\n\n\t// Mapping from a distance to a distance code. dist is the distance - 1 and\n\t// must not have side effects. _dist_code[256] and _dist_code[257] are never\n\t// used.\n\tTree.d_code = function(dist) {\n\t\treturn ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >>> 7)]);\n\t};\n\n\t// extra bits for each length code\n\tTree.extra_lbits = [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 ];\n\n\t// extra bits for each distance code\n\tTree.extra_dbits = [ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 ];\n\n\t// extra bits for each bit length code\n\tTree.extra_blbits = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 ];\n\n\tTree.bl_order = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];\n\n\t// StaticTree\n\n\tfunction StaticTree(static_tree, extra_bits, extra_base, elems, max_length) {\n\t\tvar that = this;\n\t\tthat.static_tree = static_tree;\n\t\tthat.extra_bits = extra_bits;\n\t\tthat.extra_base = extra_base;\n\t\tthat.elems = elems;\n\t\tthat.max_length = max_length;\n\t}\n\n\tStaticTree.static_ltree = [ 12, 8, 140, 8, 76, 8, 204, 8, 44, 8, 172, 8, 108, 8, 236, 8, 28, 8, 156, 8, 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, 252, 8, 2, 8,\n\t\t\t130, 8, 66, 8, 194, 8, 34, 8, 162, 8, 98, 8, 226, 8, 18, 8, 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, 114, 8, 242, 8, 10, 8, 138, 8, 74, 8, 202, 8, 42,\n\t\t\t8, 170, 8, 106, 8, 234, 8, 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, 186, 8, 122, 8, 250, 8, 6, 8, 134, 8, 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, 230, 8,\n\t\t\t22, 8, 150, 8, 86, 8, 214, 8, 54, 8, 182, 8, 118, 8, 246, 8, 14, 8, 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,\n\t\t\t222, 8, 62, 8, 190, 8, 126, 8, 254, 8, 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, 161, 8, 97, 8, 225, 8, 17, 8, 145, 8, 81, 8, 209, 8, 49, 8, 177, 8, 113,\n\t\t\t8, 241, 8, 9, 8, 137, 8, 73, 8, 201, 8, 41, 8, 169, 8, 105, 8, 233, 8, 25, 8, 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, 121, 8, 249, 8, 5, 8, 133, 8,\n\t\t\t69, 8, 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, 181, 8, 117, 8, 245, 8, 13, 8, 141, 8, 77, 8, 205, 8, 45, 8,\n\t\t\t173, 8, 109, 8, 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, 211, 9, 467, 9,\n\t\t\t51, 9, 307, 9, 179, 9, 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, 331, 9, 203, 9, 459, 9, 43, 9, 299, 9, 171, 9,\n\t\t\t427, 9, 107, 9, 363, 9, 235, 9, 491, 9, 27, 9, 283, 9, 155, 9, 411, 9, 91, 9, 347, 9, 219, 9, 475, 9, 59, 9, 315, 9, 187, 9, 443, 9, 123, 9, 379,\n\t\t\t9, 251, 9, 507, 9, 7, 9, 263, 9, 135, 9, 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, 359, 9, 231, 9, 487, 9, 23,\n\t\t\t9, 279, 9, 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, 471, 9, 55, 9, 311, 9, 183, 9, 439, 9, 119, 9, 375, 9, 247, 9, 503, 9, 15, 9, 271, 9, 143, 9,\n\t\t\t399, 9, 79, 9, 335, 9, 207, 9, 463, 9, 47, 9, 303, 9, 175, 9, 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, 351, 9,\n\t\t\t223, 9, 479, 9, 63, 9, 319, 9, 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, 511, 9, 0, 7, 64, 7, 32, 7, 96, 7, 16, 7, 80, 7, 48, 7, 112, 7, 8, 7, 72, 7,\n\t\t\t40, 7, 104, 7, 24, 7, 88, 7, 56, 7, 120, 7, 4, 7, 68, 7, 36, 7, 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, 163, 8,\n\t\t\t99, 8, 227, 8 ];\n\n\tStaticTree.static_dtree = [ 0, 5, 16, 5, 8, 5, 24, 5, 4, 5, 20, 5, 12, 5, 28, 5, 2, 5, 18, 5, 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, 30, 5, 1, 5, 17, 5, 9, 5,\n\t\t\t25, 5, 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5 ];\n\n\tStaticTree.static_l_desc = new StaticTree(StaticTree.static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);\n\n\tStaticTree.static_d_desc = new StaticTree(StaticTree.static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS);\n\n\tStaticTree.static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS);\n\n\t// Deflate\n\n\tvar MAX_MEM_LEVEL = 9;\n\tvar DEF_MEM_LEVEL = 8;\n\n\tfunction Config(good_length, max_lazy, nice_length, max_chain, func) {\n\t\tvar that = this;\n\t\tthat.good_length = good_length;\n\t\tthat.max_lazy = max_lazy;\n\t\tthat.nice_length = nice_length;\n\t\tthat.max_chain = max_chain;\n\t\tthat.func = func;\n\t}\n\n\tvar STORED = 0;\n\tvar FAST = 1;\n\tvar SLOW = 2;\n\tvar config_table = [ new Config(0, 0, 0, 0, STORED), new Config(4, 4, 8, 4, FAST), new Config(4, 5, 16, 8, FAST), new Config(4, 6, 32, 32, FAST),\n\t\t\tnew Config(4, 4, 16, 16, SLOW), new Config(8, 16, 32, 32, SLOW), new Config(8, 16, 128, 128, SLOW), new Config(8, 32, 128, 256, SLOW),\n\t\t\tnew Config(32, 128, 258, 1024, SLOW), new Config(32, 258, 258, 4096, SLOW) ];\n\n\tvar z_errmsg = [ \"need dictionary\", // Z_NEED_DICT\n\t// 2\n\t\"stream end\", // Z_STREAM_END 1\n\t\"\", // Z_OK 0\n\t\"\", // Z_ERRNO (-1)\n\t\"stream error\", // Z_STREAM_ERROR (-2)\n\t\"data error\", // Z_DATA_ERROR (-3)\n\t\"\", // Z_MEM_ERROR (-4)\n\t\"buffer error\", // Z_BUF_ERROR (-5)\n\t\"\",// Z_VERSION_ERROR (-6)\n\t\"\" ];\n\n\t// block not completed, need more input or more output\n\tvar NeedMore = 0;\n\n\t// block flush performed\n\tvar BlockDone = 1;\n\n\t// finish started, need only more output at next deflate\n\tvar FinishStarted = 2;\n\n\t// finish done, accept no more input or output\n\tvar FinishDone = 3;\n\n\t// preset dictionary flag in zlib header\n\tvar PRESET_DICT = 0x20;\n\n\tvar INIT_STATE = 42;\n\tvar BUSY_STATE = 113;\n\tvar FINISH_STATE = 666;\n\n\t// The deflate compression method\n\tvar Z_DEFLATED = 8;\n\n\tvar STORED_BLOCK = 0;\n\tvar STATIC_TREES = 1;\n\tvar DYN_TREES = 2;\n\n\t// The three kinds of block type\n\tvar Z_BINARY = 0;\n\tvar Z_ASCII = 1;\n\tvar Z_UNKNOWN = 2;\n\n\tvar MIN_MATCH = 3;\n\tvar MAX_MATCH = 258;\n\tvar MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);\n\n\tfunction smaller(tree, n, m, depth) {\n\t\tvar tn2 = tree[n * 2];\n\t\tvar tm2 = tree[m * 2];\n\t\treturn (tn2 < tm2 || (tn2 == tm2 && depth[n] <= depth[m]));\n\t}\n\n\tfunction Deflate() {\n\n\t\tvar that = this;\n\t\tvar strm; // pointer back to this zlib stream\n\t\tvar status; // as the name implies\n\t\t// pending_buf; // output still pending\n\t\tvar pending_buf_size; // size of pending_buf\n\t\t// pending_out; // next pending byte to output to the stream\n\t\t// pending; // nb of bytes in the pending buffer\n\t\t// data_type; // UNKNOWN, BINARY or ASCII\n\t\tvar method; // STORED (for zip only) or DEFLATED\n\t\tvar last_flush; // value of flush param for previous deflate call\n\n\t\tvar w_size; // LZ77 window size (32K by default)\n\t\tvar w_bits; // log2(w_size) (8..16)\n\t\tvar w_mask; // w_size - 1\n\n\t\tvar window;\n\t\t// Sliding window. Input bytes are read into the second half of the window,\n\t\t// and move to the first half later to keep a dictionary of at least wSize\n\t\t// bytes. With this organization, matches are limited to a distance of\n\t\t// wSize-MAX_MATCH bytes, but this ensures that IO is always\n\t\t// performed with a length multiple of the block size. Also, it limits\n\t\t// the window size to 64K, which is quite useful on MSDOS.\n\t\t// To do: use the user input buffer as sliding window.\n\n\t\tvar window_size;\n\t\t// Actual size of window: 2*wSize, except when the user input buffer\n\t\t// is directly used as sliding window.\n\n\t\tvar prev;\n\t\t// Link to older string with same hash index. To limit the size of this\n\t\t// array to 64K, this link is maintained only for the last 32K strings.\n\t\t// An index in this array is thus a window index modulo 32K.\n\n\t\tvar head; // Heads of the hash chains or NIL.\n\n\t\tvar ins_h; // hash index of string to be inserted\n\t\tvar hash_size; // number of elements in hash table\n\t\tvar hash_bits; // log2(hash_size)\n\t\tvar hash_mask; // hash_size-1\n\n\t\t// Number of bits by which ins_h must be shifted at each input\n\t\t// step. It must be such that after MIN_MATCH steps, the oldest\n\t\t// byte no longer takes part in the hash key, that is:\n\t\t// hash_shift * MIN_MATCH >= hash_bits\n\t\tvar hash_shift;\n\n\t\t// Window position at the beginning of the current output block. Gets\n\t\t// negative when the window is moved backwards.\n\n\t\tvar block_start;\n\n\t\tvar match_length; // length of best match\n\t\tvar prev_match; // previous match\n\t\tvar match_available; // set if previous match exists\n\t\tvar strstart; // start of string to insert\n\t\tvar match_start; // start of matching string\n\t\tvar lookahead; // number of valid bytes ahead in window\n\n\t\t// Length of the best match at previous step. Matches not greater than this\n\t\t// are discarded. This is used in the lazy match evaluation.\n\t\tvar prev_length;\n\n\t\t// To speed up deflation, hash chains are never searched beyond this\n\t\t// length. A higher limit improves compression ratio but degrades the speed.\n\t\tvar max_chain_length;\n\n\t\t// Attempt to find a better match only when the current match is strictly\n\t\t// smaller than this value. This mechanism is used only for compression\n\t\t// levels >= 4.\n\t\tvar max_lazy_match;\n\n\t\t// Insert new strings in the hash table only if the match length is not\n\t\t// greater than this length. This saves time but degrades compression.\n\t\t// max_insert_length is used only for compression levels <= 3.\n\n\t\tvar level; // compression level (1..9)\n\t\tvar strategy; // favor or force Huffman coding\n\n\t\t// Use a faster search when the previous match is longer than this\n\t\tvar good_match;\n\n\t\t// Stop searching when current match exceeds this\n\t\tvar nice_match;\n\n\t\tvar dyn_ltree; // literal and length tree\n\t\tvar dyn_dtree; // distance tree\n\t\tvar bl_tree; // Huffman tree for bit lengths\n\n\t\tvar l_desc = new Tree(); // desc for literal tree\n\t\tvar d_desc = new Tree(); // desc for distance tree\n\t\tvar bl_desc = new Tree(); // desc for bit length tree\n\n\t\t// that.heap_len; // number of elements in the heap\n\t\t// that.heap_max; // element of largest frequency\n\t\t// The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.\n\t\t// The same heap array is used to build all trees.\n\n\t\t// Depth of each subtree used as tie breaker for trees of equal frequency\n\t\tthat.depth = [];\n\n\t\tvar l_buf; // index for literals or lengths */\n\n\t\t// Size of match buffer for literals/lengths. There are 4 reasons for\n\t\t// limiting lit_bufsize to 64K:\n\t\t// - frequencies can be kept in 16 bit counters\n\t\t// - if compression is not successful for the first block, all input\n\t\t// data is still in the window so we can still emit a stored block even\n\t\t// when input comes from standard input. (This can also be done for\n\t\t// all blocks if lit_bufsize is not greater than 32K.)\n\t\t// - if compression is not successful for a file smaller than 64K, we can\n\t\t// even emit a stored file instead of a stored block (saving 5 bytes).\n\t\t// This is applicable only for zip (not gzip or zlib).\n\t\t// - creating new Huffman trees less frequently may not provide fast\n\t\t// adaptation to changes in the input data statistics. (Take for\n\t\t// example a binary file with poorly compressible code followed by\n\t\t// a highly compressible string table.) Smaller buffer sizes give\n\t\t// fast adaptation but have of course the overhead of transmitting\n\t\t// trees more frequently.\n\t\t// - I can't count above 4\n\t\tvar lit_bufsize;\n\n\t\tvar last_lit; // running index in l_buf\n\n\t\t// Buffer for distances. To simplify the code, d_buf and l_buf have\n\t\t// the same number of elements. To use different lengths, an extra flag\n\t\t// array would be necessary.\n\n\t\tvar d_buf; // index of pendig_buf\n\n\t\t// that.opt_len; // bit length of current block with optimal trees\n\t\t// that.static_len; // bit length of current block with static trees\n\t\tvar matches; // number of string matches in current block\n\t\tvar last_eob_len; // bit length of EOB code for last block\n\n\t\t// Output buffer. bits are inserted starting at the bottom (least\n\t\t// significant bits).\n\t\tvar bi_buf;\n\n\t\t// Number of valid bits in bi_buf. All bits above the last valid bit\n\t\t// are always zero.\n\t\tvar bi_valid;\n\n\t\t// number of codes at each bit length for an optimal tree\n\t\tthat.bl_count = [];\n\n\t\t// heap used to build the Huffman trees\n\t\tthat.heap = [];\n\n\t\tdyn_ltree = [];\n\t\tdyn_dtree = [];\n\t\tbl_tree = [];\n\n\t\tfunction lm_init() {\n\t\t\tvar i;\n\t\t\twindow_size = 2 * w_size;\n\n\t\t\thead[hash_size - 1] = 0;\n\t\t\tfor (i = 0; i < hash_size - 1; i++) {\n\t\t\t\thead[i] = 0;\n\t\t\t}\n\n\t\t\t// Set the default configuration parameters:\n\t\t\tmax_lazy_match = config_table[level].max_lazy;\n\t\t\tgood_match = config_table[level].good_length;\n\t\t\tnice_match = config_table[level].nice_length;\n\t\t\tmax_chain_length = config_table[level].max_chain;\n\n\t\t\tstrstart = 0;\n\t\t\tblock_start = 0;\n\t\t\tlookahead = 0;\n\t\t\tmatch_length = prev_length = MIN_MATCH - 1;\n\t\t\tmatch_available = 0;\n\t\t\tins_h = 0;\n\t\t}\n\n\t\tfunction init_block() {\n\t\t\tvar i;\n\t\t\t// Initialize the trees.\n\t\t\tfor (i = 0; i < L_CODES; i++)\n\t\t\t\tdyn_ltree[i * 2] = 0;\n\t\t\tfor (i = 0; i < D_CODES; i++)\n\t\t\t\tdyn_dtree[i * 2] = 0;\n\t\t\tfor (i = 0; i < BL_CODES; i++)\n\t\t\t\tbl_tree[i * 2] = 0;\n\n\t\t\tdyn_ltree[END_BLOCK * 2] = 1;\n\t\t\tthat.opt_len = that.static_len = 0;\n\t\t\tlast_lit = matches = 0;\n\t\t}\n\n\t\t// Initialize the tree data structures for a new zlib stream.\n\t\tfunction tr_init() {\n\n\t\t\tl_desc.dyn_tree = dyn_ltree;\n\t\t\tl_desc.stat_desc = StaticTree.static_l_desc;\n\n\t\t\td_desc.dyn_tree = dyn_dtree;\n\t\t\td_desc.stat_desc = StaticTree.static_d_desc;\n\n\t\t\tbl_desc.dyn_tree = bl_tree;\n\t\t\tbl_desc.stat_desc = StaticTree.static_bl_desc;\n\n\t\t\tbi_buf = 0;\n\t\t\tbi_valid = 0;\n\t\t\tlast_eob_len = 8; // enough lookahead for inflate\n\n\t\t\t// Initialize the first block of the first file:\n\t\t\tinit_block();\n\t\t}\n\n\t\t// Restore the heap property by moving down the tree starting at node k,\n\t\t// exchanging a node with the smallest of its two sons if necessary,\n\t\t// stopping\n\t\t// when the heap property is re-established (each father smaller than its\n\t\t// two sons).\n\t\tthat.pqdownheap = function(tree, // the tree to restore\n\t\tk // node to move down\n\t\t) {\n\t\t\tvar heap = that.heap;\n\t\t\tvar v = heap[k];\n\t\t\tvar j = k << 1; // left son of k\n\t\t\twhile (j <= that.heap_len) {\n\t\t\t\t// Set j to the smallest of the two sons:\n\t\t\t\tif (j < that.heap_len && smaller(tree, heap[j + 1], heap[j], that.depth)) {\n\t\t\t\t\tj++;\n\t\t\t\t}\n\t\t\t\t// Exit if v is smaller than both sons\n\t\t\t\tif (smaller(tree, v, heap[j], that.depth))\n\t\t\t\t\tbreak;\n\n\t\t\t\t// Exchange v with the smallest son\n\t\t\t\theap[k] = heap[j];\n\t\t\t\tk = j;\n\t\t\t\t// And continue down the tree, setting j to the left son of k\n\t\t\t\tj <<= 1;\n\t\t\t}\n\t\t\theap[k] = v;\n\t\t};\n\n\t\t// Scan a literal or distance tree to determine the frequencies of the codes\n\t\t// in the bit length tree.\n\t\tfunction scan_tree(tree,// the tree to be scanned\n\t\tmax_code // and its largest code of non zero frequency\n\t\t) {\n\t\t\tvar n; // iterates over all tree elements\n\t\t\tvar prevlen = -1; // last emitted length\n\t\t\tvar curlen; // length of current code\n\t\t\tvar nextlen = tree[0 * 2 + 1]; // length of next code\n\t\t\tvar count = 0; // repeat count of the current code\n\t\t\tvar max_count = 7; // max repeat count\n\t\t\tvar min_count = 4; // min repeat count\n\n\t\t\tif (nextlen === 0) {\n\t\t\t\tmax_count = 138;\n\t\t\t\tmin_count = 3;\n\t\t\t}\n\t\t\ttree[(max_code + 1) * 2 + 1] = 0xffff; // guard\n\n\t\t\tfor (n = 0; n <= max_code; n++) {\n\t\t\t\tcurlen = nextlen;\n\t\t\t\tnextlen = tree[(n + 1) * 2 + 1];\n\t\t\t\tif (++count < max_count && curlen == nextlen) {\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (count < min_count) {\n\t\t\t\t\tbl_tree[curlen * 2] += count;\n\t\t\t\t} else if (curlen !== 0) {\n\t\t\t\t\tif (curlen != prevlen)\n\t\t\t\t\t\tbl_tree[curlen * 2]++;\n\t\t\t\t\tbl_tree[REP_3_6 * 2]++;\n\t\t\t\t} else if (count <= 10) {\n\t\t\t\t\tbl_tree[REPZ_3_10 * 2]++;\n\t\t\t\t} else {\n\t\t\t\t\tbl_tree[REPZ_11_138 * 2]++;\n\t\t\t\t}\n\t\t\t\tcount = 0;\n\t\t\t\tprevlen = curlen;\n\t\t\t\tif (nextlen === 0) {\n\t\t\t\t\tmax_count = 138;\n\t\t\t\t\tmin_count = 3;\n\t\t\t\t} else if (curlen == nextlen) {\n\t\t\t\t\tmax_count = 6;\n\t\t\t\t\tmin_count = 3;\n\t\t\t\t} else {\n\t\t\t\t\tmax_count = 7;\n\t\t\t\t\tmin_count = 4;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Construct the Huffman tree for the bit lengths and return the index in\n\t\t// bl_order of the last bit length code to send.\n\t\tfunction build_bl_tree() {\n\t\t\tvar max_blindex; // index of last bit length code of non zero freq\n\n\t\t\t// Determine the bit length frequencies for literal and distance trees\n\t\t\tscan_tree(dyn_ltree, l_desc.max_code);\n\t\t\tscan_tree(dyn_dtree, d_desc.max_code);\n\n\t\t\t// Build the bit length tree:\n\t\t\tbl_desc.build_tree(that);\n\t\t\t// opt_len now includes the length of the tree representations, except\n\t\t\t// the lengths of the bit lengths codes and the 5+5+4 bits for the\n\t\t\t// counts.\n\n\t\t\t// Determine the number of bit length codes to send. The pkzip format\n\t\t\t// requires that at least 4 bit length codes be sent. (appnote.txt says\n\t\t\t// 3 but the actual value used is 4.)\n\t\t\tfor (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) {\n\t\t\t\tif (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] !== 0)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// Update opt_len to include the bit length tree and counts\n\t\t\tthat.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;\n\n\t\t\treturn max_blindex;\n\t\t}\n\n\t\t// Output a byte on the stream.\n\t\t// IN assertion: there is enough room in pending_buf.\n\t\tfunction put_byte(p) {\n\t\t\tthat.pending_buf[that.pending++] = p;\n\t\t}\n\n\t\tfunction put_short(w) {\n\t\t\tput_byte(w & 0xff);\n\t\t\tput_byte((w >>> 8) & 0xff);\n\t\t}\n\n\t\tfunction putShortMSB(b) {\n\t\t\tput_byte((b >> 8) & 0xff);\n\t\t\tput_byte((b & 0xff) & 0xff);\n\t\t}\n\n\t\tfunction send_bits(value, length) {\n\t\t\tvar val, len = length;\n\t\t\tif (bi_valid > Buf_size - len) {\n\t\t\t\tval = value;\n\t\t\t\t// bi_buf |= (val << bi_valid);\n\t\t\t\tbi_buf |= ((val << bi_valid) & 0xffff);\n\t\t\t\tput_short(bi_buf);\n\t\t\t\tbi_buf = val >>> (Buf_size - bi_valid);\n\t\t\t\tbi_valid += len - Buf_size;\n\t\t\t} else {\n\t\t\t\t// bi_buf |= (value) << bi_valid;\n\t\t\t\tbi_buf |= (((value) << bi_valid) & 0xffff);\n\t\t\t\tbi_valid += len;\n\t\t\t}\n\t\t}\n\n\t\tfunction send_code(c, tree) {\n\t\t\tvar c2 = c * 2;\n\t\t\tsend_bits(tree[c2] & 0xffff, tree[c2 + 1] & 0xffff);\n\t\t}\n\n\t\t// Send a literal or distance tree in compressed form, using the codes in\n\t\t// bl_tree.\n\t\tfunction send_tree(tree,// the tree to be sent\n\t\tmax_code // and its largest code of non zero frequency\n\t\t) {\n\t\t\tvar n; // iterates over all tree elements\n\t\t\tvar prevlen = -1; // last emitted length\n\t\t\tvar curlen; // length of current code\n\t\t\tvar nextlen = tree[0 * 2 + 1]; // length of next code\n\t\t\tvar count = 0; // repeat count of the current code\n\t\t\tvar max_count = 7; // max repeat count\n\t\t\tvar min_count = 4; // min repeat count\n\n\t\t\tif (nextlen === 0) {\n\t\t\t\tmax_count = 138;\n\t\t\t\tmin_count = 3;\n\t\t\t}\n\n\t\t\tfor (n = 0; n <= max_code; n++) {\n\t\t\t\tcurlen = nextlen;\n\t\t\t\tnextlen = tree[(n + 1) * 2 + 1];\n\t\t\t\tif (++count < max_count && curlen == nextlen) {\n\t\t\t\t\tcontinue;\n\t\t\t\t} else if (count < min_count) {\n\t\t\t\t\tdo {\n\t\t\t\t\t\tsend_code(curlen, bl_tree);\n\t\t\t\t\t} while (--count !== 0);\n\t\t\t\t} else if (curlen !== 0) {\n\t\t\t\t\tif (curlen != prevlen) {\n\t\t\t\t\t\tsend_code(curlen, bl_tree);\n\t\t\t\t\t\tcount--;\n\t\t\t\t\t}\n\t\t\t\t\tsend_code(REP_3_6, bl_tree);\n\t\t\t\t\tsend_bits(count - 3, 2);\n\t\t\t\t} else if (count <= 10) {\n\t\t\t\t\tsend_code(REPZ_3_10, bl_tree);\n\t\t\t\t\tsend_bits(count - 3, 3);\n\t\t\t\t} else {\n\t\t\t\t\tsend_code(REPZ_11_138, bl_tree);\n\t\t\t\t\tsend_bits(count - 11, 7);\n\t\t\t\t}\n\t\t\t\tcount = 0;\n\t\t\t\tprevlen = curlen;\n\t\t\t\tif (nextlen === 0) {\n\t\t\t\t\tmax_count = 138;\n\t\t\t\t\tmin_count = 3;\n\t\t\t\t} else if (curlen == nextlen) {\n\t\t\t\t\tmax_count = 6;\n\t\t\t\t\tmin_count = 3;\n\t\t\t\t} else {\n\t\t\t\t\tmax_count = 7;\n\t\t\t\t\tmin_count = 4;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Send the header for a block using dynamic Huffman trees: the counts, the\n\t\t// lengths of the bit length codes, the literal tree and the distance tree.\n\t\t// IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.\n\t\tfunction send_all_trees(lcodes, dcodes, blcodes) {\n\t\t\tvar rank; // index in bl_order\n\n\t\t\tsend_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt\n\t\t\tsend_bits(dcodes - 1, 5);\n\t\t\tsend_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt\n\t\t\tfor (rank = 0; rank < blcodes; rank++) {\n\t\t\t\tsend_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3);\n\t\t\t}\n\t\t\tsend_tree(dyn_ltree, lcodes - 1); // literal tree\n\t\t\tsend_tree(dyn_dtree, dcodes - 1); // distance tree\n\t\t}\n\n\t\t// Flush the bit buffer, keeping at most 7 bits in it.\n\t\tfunction bi_flush() {\n\t\t\tif (bi_valid == 16) {\n\t\t\t\tput_short(bi_buf);\n\t\t\t\tbi_buf = 0;\n\t\t\t\tbi_valid = 0;\n\t\t\t} else if (bi_valid >= 8) {\n\t\t\t\tput_byte(bi_buf & 0xff);\n\t\t\t\tbi_buf >>>= 8;\n\t\t\t\tbi_valid -= 8;\n\t\t\t}\n\t\t}\n\n\t\t// Send one empty static block to give enough lookahead for inflate.\n\t\t// This takes 10 bits, of which 7 may remain in the bit buffer.\n\t\t// The current inflate code requires 9 bits of lookahead. If the\n\t\t// last two codes for the previous block (real code plus EOB) were coded\n\t\t// on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode\n\t\t// the last real code. In this case we send two empty static blocks instead\n\t\t// of one. (There are no problems if the previous block is stored or fixed.)\n\t\t// To simplify the code, we assume the worst case of last real code encoded\n\t\t// on one bit only.\n\t\tfunction _tr_align() {\n\t\t\tsend_bits(STATIC_TREES << 1, 3);\n\t\t\tsend_code(END_BLOCK, StaticTree.static_ltree);\n\n\t\t\tbi_flush();\n\n\t\t\t// Of the 10 bits for the empty block, we have already sent\n\t\t\t// (10 - bi_valid) bits. The lookahead for the last real code (before\n\t\t\t// the EOB of the previous block) was thus at least one plus the length\n\t\t\t// of the EOB plus what we have just sent of the empty static block.\n\t\t\tif (1 + last_eob_len + 10 - bi_valid < 9) {\n\t\t\t\tsend_bits(STATIC_TREES << 1, 3);\n\t\t\t\tsend_code(END_BLOCK, StaticTree.static_ltree);\n\t\t\t\tbi_flush();\n\t\t\t}\n\t\t\tlast_eob_len = 7;\n\t\t}\n\n\t\t// Save the match info and tally the frequency counts. Return true if\n\t\t// the current block must be flushed.\n\t\tfunction _tr_tally(dist, // distance of matched string\n\t\tlc // match length-MIN_MATCH or unmatched char (if dist==0)\n\t\t) {\n\t\t\tvar out_length, in_length, dcode;\n\t\t\tthat.pending_buf[d_buf + last_lit * 2] = (dist >>> 8) & 0xff;\n\t\t\tthat.pending_buf[d_buf + last_lit * 2 + 1] = dist & 0xff;\n\n\t\t\tthat.pending_buf[l_buf + last_lit] = lc & 0xff;\n\t\t\tlast_lit++;\n\n\t\t\tif (dist === 0) {\n\t\t\t\t// lc is the unmatched char\n\t\t\t\tdyn_ltree[lc * 2]++;\n\t\t\t} else {\n\t\t\t\tmatches++;\n\t\t\t\t// Here, lc is the match length - MIN_MATCH\n\t\t\t\tdist--; // dist = match distance - 1\n\t\t\t\tdyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++;\n\t\t\t\tdyn_dtree[Tree.d_code(dist) * 2]++;\n\t\t\t}\n\n\t\t\tif ((last_lit & 0x1fff) === 0 && level > 2) {\n\t\t\t\t// Compute an upper bound for the compressed length\n\t\t\t\tout_length = last_lit * 8;\n\t\t\t\tin_length = strstart - block_start;\n\t\t\t\tfor (dcode = 0; dcode < D_CODES; dcode++) {\n\t\t\t\t\tout_length += dyn_dtree[dcode * 2] * (5 + Tree.extra_dbits[dcode]);\n\t\t\t\t}\n\t\t\t\tout_length >>>= 3;\n\t\t\t\tif ((matches < Math.floor(last_lit / 2)) && out_length < Math.floor(in_length / 2))\n\t\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn (last_lit == lit_bufsize - 1);\n\t\t\t// We avoid equality with lit_bufsize because of wraparound at 64K\n\t\t\t// on 16 bit machines and because stored blocks are restricted to\n\t\t\t// 64K-1 bytes.\n\t\t}\n\n\t\t// Send the block data compressed using the given Huffman trees\n\t\tfunction compress_block(ltree, dtree) {\n\t\t\tvar dist; // distance of matched string\n\t\t\tvar lc; // match length or unmatched char (if dist === 0)\n\t\t\tvar lx = 0; // running index in l_buf\n\t\t\tvar code; // the code to send\n\t\t\tvar extra; // number of extra bits to send\n\n\t\t\tif (last_lit !== 0) {\n\t\t\t\tdo {\n\t\t\t\t\tdist = ((that.pending_buf[d_buf + lx * 2] << 8) & 0xff00) | (that.pending_buf[d_buf + lx * 2 + 1] & 0xff);\n\t\t\t\t\tlc = (that.pending_buf[l_buf + lx]) & 0xff;\n\t\t\t\t\tlx++;\n\n\t\t\t\t\tif (dist === 0) {\n\t\t\t\t\t\tsend_code(lc, ltree); // send a literal byte\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Here, lc is the match length - MIN_MATCH\n\t\t\t\t\t\tcode = Tree._length_code[lc];\n\n\t\t\t\t\t\tsend_code(code + LITERALS + 1, ltree); // send the length\n\t\t\t\t\t\t// code\n\t\t\t\t\t\textra = Tree.extra_lbits[code];\n\t\t\t\t\t\tif (extra !== 0) {\n\t\t\t\t\t\t\tlc -= Tree.base_length[code];\n\t\t\t\t\t\t\tsend_bits(lc, extra); // send the extra length bits\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdist--; // dist is now the match distance - 1\n\t\t\t\t\t\tcode = Tree.d_code(dist);\n\n\t\t\t\t\t\tsend_code(code, dtree); // send the distance code\n\t\t\t\t\t\textra = Tree.extra_dbits[code];\n\t\t\t\t\t\tif (extra !== 0) {\n\t\t\t\t\t\t\tdist -= Tree.base_dist[code];\n\t\t\t\t\t\t\tsend_bits(dist, extra); // send the extra distance bits\n\t\t\t\t\t\t}\n\t\t\t\t\t} // literal or match pair ?\n\n\t\t\t\t\t// Check that the overlay between pending_buf and d_buf+l_buf is\n\t\t\t\t\t// ok:\n\t\t\t\t} while (lx < last_lit);\n\t\t\t}\n\n\t\t\tsend_code(END_BLOCK, ltree);\n\t\t\tlast_eob_len = ltree[END_BLOCK * 2 + 1];\n\t\t}\n\n\t\t// Set the data type to ASCII or BINARY, using a crude approximation:\n\t\t// binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.\n\t\t// IN assertion: the fields freq of dyn_ltree are set and the total of all\n\t\t// frequencies does not exceed 64K (to fit in an int on 16 bit machines).\n\t\tfunction set_data_type() {\n\t\t\tvar n = 0;\n\t\t\tvar ascii_freq = 0;\n\t\t\tvar bin_freq = 0;\n\t\t\twhile (n < 7) {\n\t\t\t\tbin_freq += dyn_ltree[n * 2];\n\t\t\t\tn++;\n\t\t\t}\n\t\t\twhile (n < 128) {\n\t\t\t\tascii_freq += dyn_ltree[n * 2];\n\t\t\t\tn++;\n\t\t\t}\n\t\t\twhile (n < LITERALS) {\n\t\t\t\tbin_freq += dyn_ltree[n * 2];\n\t\t\t\tn++;\n\t\t\t}\n\t\t\tthat.data_type = (bin_freq > (ascii_freq >>> 2) ? Z_BINARY : Z_ASCII) & 0xff;\n\t\t}\n\n\t\t// Flush the bit buffer and align the output on a byte boundary\n\t\tfunction bi_windup() {\n\t\t\tif (bi_valid > 8) {\n\t\t\t\tput_short(bi_buf);\n\t\t\t} else if (bi_valid > 0) {\n\t\t\t\tput_byte(bi_buf & 0xff);\n\t\t\t}\n\t\t\tbi_buf = 0;\n\t\t\tbi_valid = 0;\n\t\t}\n\n\t\t// Copy a stored block, storing first the length and its\n\t\t// one's complement if requested.\n\t\tfunction copy_block(buf, // the input data\n\t\tlen, // its length\n\t\theader // true if block header must be written\n\t\t) {\n\t\t\tbi_windup(); // align on byte boundary\n\t\t\tlast_eob_len = 8; // enough lookahead for inflate\n\n\t\t\tif (header) {\n\t\t\t\tput_short(len);\n\t\t\t\tput_short(~len);\n\t\t\t}\n\n\t\t\tthat.pending_buf.set(window.subarray(buf, buf + len), that.pending);\n\t\t\tthat.pending += len;\n\t\t}\n\n\t\t// Send a stored block\n\t\tfunction _tr_stored_block(buf, // input block\n\t\tstored_len, // length of input block\n\t\teof // true if this is the last block for a file\n\t\t) {\n\t\t\tsend_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type\n\t\t\tcopy_block(buf, stored_len, true); // with header\n\t\t}\n\n\t\t// Determine the best encoding for the current block: dynamic trees, static\n\t\t// trees or store, and output the encoded block to the zip file.\n\t\tfunction _tr_flush_block(buf, // input block, or NULL if too old\n\t\tstored_len, // length of input block\n\t\teof // true if this is the last block for a file\n\t\t) {\n\t\t\tvar opt_lenb, static_lenb;// opt_len and static_len in bytes\n\t\t\tvar max_blindex = 0; // index of last bit length code of non zero freq\n\n\t\t\t// Build the Huffman trees unless a stored block is forced\n\t\t\tif (level > 0) {\n\t\t\t\t// Check if the file is ascii or binary\n\t\t\t\tif (that.data_type == Z_UNKNOWN)\n\t\t\t\t\tset_data_type();\n\n\t\t\t\t// Construct the literal and distance trees\n\t\t\t\tl_desc.build_tree(that);\n\n\t\t\t\td_desc.build_tree(that);\n\n\t\t\t\t// At this point, opt_len and static_len are the total bit lengths\n\t\t\t\t// of\n\t\t\t\t// the compressed block data, excluding the tree representations.\n\n\t\t\t\t// Build the bit length tree for the above two trees, and get the\n\t\t\t\t// index\n\t\t\t\t// in bl_order of the last bit length code to send.\n\t\t\t\tmax_blindex = build_bl_tree();\n\n\t\t\t\t// Determine the best encoding. Compute first the block length in\n\t\t\t\t// bytes\n\t\t\t\topt_lenb = (that.opt_len + 3 + 7) >>> 3;\n\t\t\t\tstatic_lenb = (that.static_len + 3 + 7) >>> 3;\n\n\t\t\t\tif (static_lenb <= opt_lenb)\n\t\t\t\t\topt_lenb = static_lenb;\n\t\t\t} else {\n\t\t\t\topt_lenb = static_lenb = stored_len + 5; // force a stored block\n\t\t\t}\n\n\t\t\tif ((stored_len + 4 <= opt_lenb) && buf != -1) {\n\t\t\t\t// 4: two words for the lengths\n\t\t\t\t// The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.\n\t\t\t\t// Otherwise we can't have processed more than WSIZE input bytes\n\t\t\t\t// since\n\t\t\t\t// the last block flush, because compression would have been\n\t\t\t\t// successful. If LIT_BUFSIZE <= WSIZE, it is never too late to\n\t\t\t\t// transform a block into a stored block.\n\t\t\t\t_tr_stored_block(buf, stored_len, eof);\n\t\t\t} else if (static_lenb == opt_lenb) {\n\t\t\t\tsend_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);\n\t\t\t\tcompress_block(StaticTree.static_ltree, StaticTree.static_dtree);\n\t\t\t} else {\n\t\t\t\tsend_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);\n\t\t\t\tsend_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1);\n\t\t\t\tcompress_block(dyn_ltree, dyn_dtree);\n\t\t\t}\n\n\t\t\t// The above check is made mod 2^32, for files larger than 512 MB\n\t\t\t// and uLong implemented on 32 bits.\n\n\t\t\tinit_block();\n\n\t\t\tif (eof) {\n\t\t\t\tbi_windup();\n\t\t\t}\n\t\t}\n\n\t\tfunction flush_block_only(eof) {\n\t\t\t_tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof);\n\t\t\tblock_start = strstart;\n\t\t\tstrm.flush_pending();\n\t\t}\n\n\t\t// Fill the window when the lookahead becomes insufficient.\n\t\t// Updates strstart and lookahead.\n\t\t//\n\t\t// IN assertion: lookahead < MIN_LOOKAHEAD\n\t\t// OUT assertions: strstart <= window_size-MIN_LOOKAHEAD\n\t\t// At least one byte has been read, or avail_in === 0; reads are\n\t\t// performed for at least two bytes (required for the zip translate_eol\n\t\t// option -- not supported here).\n\t\tfunction fill_window() {\n\t\t\tvar n, m;\n\t\t\tvar p;\n\t\t\tvar more; // Amount of free space at the end of the window.\n\n\t\t\tdo {\n\t\t\t\tmore = (window_size - lookahead - strstart);\n\n\t\t\t\t// Deal with !@#$% 64K limit:\n\t\t\t\tif (more === 0 && strstart === 0 && lookahead === 0) {\n\t\t\t\t\tmore = w_size;\n\t\t\t\t} else if (more == -1) {\n\t\t\t\t\t// Very unlikely, but possible on 16 bit machine if strstart ==\n\t\t\t\t\t// 0\n\t\t\t\t\t// and lookahead == 1 (input done one byte at time)\n\t\t\t\t\tmore--;\n\n\t\t\t\t\t// If the window is almost full and there is insufficient\n\t\t\t\t\t// lookahead,\n\t\t\t\t\t// move the upper half to the lower one to make room in the\n\t\t\t\t\t// upper half.\n\t\t\t\t} else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) {\n\t\t\t\t\twindow.set(window.subarray(w_size, w_size + w_size), 0);\n\n\t\t\t\t\tmatch_start -= w_size;\n\t\t\t\t\tstrstart -= w_size; // we now have strstart >= MAX_DIST\n\t\t\t\t\tblock_start -= w_size;\n\n\t\t\t\t\t// Slide the hash table (could be avoided with 32 bit values\n\t\t\t\t\t// at the expense of memory usage). We slide even when level ==\n\t\t\t\t\t// 0\n\t\t\t\t\t// to keep the hash table consistent if we switch back to level\n\t\t\t\t\t// > 0\n\t\t\t\t\t// later. (Using level 0 permanently is not an optimal usage of\n\t\t\t\t\t// zlib, so we don't care about this pathological case.)\n\n\t\t\t\t\tn = hash_size;\n\t\t\t\t\tp = n;\n\t\t\t\t\tdo {\n\t\t\t\t\t\tm = (head[--p] & 0xffff);\n\t\t\t\t\t\thead[p] = (m >= w_size ? m - w_size : 0);\n\t\t\t\t\t} while (--n !== 0);\n\n\t\t\t\t\tn = w_size;\n\t\t\t\t\tp = n;\n\t\t\t\t\tdo {\n\t\t\t\t\t\tm = (prev[--p] & 0xffff);\n\t\t\t\t\t\tprev[p] = (m >= w_size ? m - w_size : 0);\n\t\t\t\t\t\t// If n is not on any hash chain, prev[n] is garbage but\n\t\t\t\t\t\t// its value will never be used.\n\t\t\t\t\t} while (--n !== 0);\n\t\t\t\t\tmore += w_size;\n\t\t\t\t}\n\n\t\t\t\tif (strm.avail_in === 0)\n\t\t\t\t\treturn;\n\n\t\t\t\t// If there was no sliding:\n\t\t\t\t// strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&\n\t\t\t\t// more == window_size - lookahead - strstart\n\t\t\t\t// => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)\n\t\t\t\t// => more >= window_size - 2*WSIZE + 2\n\t\t\t\t// In the BIG_MEM or MMAP case (not yet supported),\n\t\t\t\t// window_size == input_size + MIN_LOOKAHEAD &&\n\t\t\t\t// strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.\n\t\t\t\t// Otherwise, window_size == 2*WSIZE so more >= 2.\n\t\t\t\t// If there was sliding, more >= WSIZE. So in all cases, more >= 2.\n\n\t\t\t\tn = strm.read_buf(window, strstart + lookahead, more);\n\t\t\t\tlookahead += n;\n\n\t\t\t\t// Initialize the hash value now that we have some input:\n\t\t\t\tif (lookahead >= MIN_MATCH) {\n\t\t\t\t\tins_h = window[strstart] & 0xff;\n\t\t\t\t\tins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;\n\t\t\t\t}\n\t\t\t\t// If the whole input has less than MIN_MATCH bytes, ins_h is\n\t\t\t\t// garbage,\n\t\t\t\t// but this is not important since only literal bytes will be\n\t\t\t\t// emitted.\n\t\t\t} while (lookahead < MIN_LOOKAHEAD && strm.avail_in !== 0);\n\t\t}\n\n\t\t// Copy without compression as much as possible from the input stream,\n\t\t// return\n\t\t// the current block state.\n\t\t// This function does not insert new strings in the dictionary since\n\t\t// uncompressible data is probably not useful. This function is used\n\t\t// only for the level=0 compression option.\n\t\t// NOTE: this function should be optimized to avoid extra copying from\n\t\t// window to pending_buf.\n\t\tfunction deflate_stored(flush) {\n\t\t\t// Stored blocks are limited to 0xffff bytes, pending_buf is limited\n\t\t\t// to pending_buf_size, and each stored block has a 5 byte header:\n\n\t\t\tvar max_block_size = 0xffff;\n\t\t\tvar max_start;\n\n\t\t\tif (max_block_size > pending_buf_size - 5) {\n\t\t\t\tmax_block_size = pending_buf_size - 5;\n\t\t\t}\n\n\t\t\t// Copy as much as possible from input to output:\n\t\t\twhile (true) {\n\t\t\t\t// Fill the window as much as possible:\n\t\t\t\tif (lookahead <= 1) {\n\t\t\t\t\tfill_window();\n\t\t\t\t\tif (lookahead === 0 && flush == Z_NO_FLUSH)\n\t\t\t\t\t\treturn NeedMore;\n\t\t\t\t\tif (lookahead === 0)\n\t\t\t\t\t\tbreak; // flush the current block\n\t\t\t\t}\n\n\t\t\t\tstrstart += lookahead;\n\t\t\t\tlookahead = 0;\n\n\t\t\t\t// Emit a stored block if pending_buf will be full:\n\t\t\t\tmax_start = block_start + max_block_size;\n\t\t\t\tif (strstart === 0 || strstart >= max_start) {\n\t\t\t\t\t// strstart === 0 is possible when wraparound on 16-bit machine\n\t\t\t\t\tlookahead = (strstart - max_start);\n\t\t\t\t\tstrstart = max_start;\n\n\t\t\t\t\tflush_block_only(false);\n\t\t\t\t\tif (strm.avail_out === 0)\n\t\t\t\t\t\treturn NeedMore;\n\n\t\t\t\t}\n\n\t\t\t\t// Flush if we may have to slide, otherwise block_start may become\n\t\t\t\t// negative and the data will be gone:\n\t\t\t\tif (strstart - block_start >= w_size - MIN_LOOKAHEAD) {\n\t\t\t\t\tflush_block_only(false);\n\t\t\t\t\tif (strm.avail_out === 0)\n\t\t\t\t\t\treturn NeedMore;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tflush_block_only(flush == Z_FINISH);\n\t\t\tif (strm.avail_out === 0)\n\t\t\t\treturn (flush == Z_FINISH) ? FinishStarted : NeedMore;\n\n\t\t\treturn flush == Z_FINISH ? FinishDone : BlockDone;\n\t\t}\n\n\t\tfunction longest_match(cur_match) {\n\t\t\tvar chain_length = max_chain_length; // max hash chain length\n\t\t\tvar scan = strstart; // current string\n\t\t\tvar match; // matched string\n\t\t\tvar len; // length of current match\n\t\t\tvar best_len = prev_length; // best match length so far\n\t\t\tvar limit = strstart > (w_size - MIN_LOOKAHEAD) ? strstart - (w_size - MIN_LOOKAHEAD) : 0;\n\t\t\tvar _nice_match = nice_match;\n\n\t\t\t// Stop when cur_match becomes <= limit. To simplify the code,\n\t\t\t// we prevent matches with the string of window index 0.\n\n\t\t\tvar wmask = w_mask;\n\n\t\t\tvar strend = strstart + MAX_MATCH;\n\t\t\tvar scan_end1 = window[scan + best_len - 1];\n\t\t\tvar scan_end = window[scan + best_len];\n\n\t\t\t// The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of\n\t\t\t// 16.\n\t\t\t// It is easy to get rid of this optimization if necessary.\n\n\t\t\t// Do not waste too much time if we already have a good match:\n\t\t\tif (prev_length >= good_match) {\n\t\t\t\tchain_length >>= 2;\n\t\t\t}\n\n\t\t\t// Do not look for matches beyond the end of the input. This is\n\t\t\t// necessary\n\t\t\t// to make deflate deterministic.\n\t\t\tif (_nice_match > lookahead)\n\t\t\t\t_nice_match = lookahead;\n\n\t\t\tdo {\n\t\t\t\tmatch = cur_match;\n\n\t\t\t\t// Skip to next match if the match length cannot increase\n\t\t\t\t// or if the match length is less than 2:\n\t\t\t\tif (window[match + best_len] != scan_end || window[match + best_len - 1] != scan_end1 || window[match] != window[scan]\n\t\t\t\t\t\t|| window[++match] != window[scan + 1])\n\t\t\t\t\tcontinue;\n\n\t\t\t\t// The check at best_len-1 can be removed because it will be made\n\t\t\t\t// again later. (This heuristic is not always a win.)\n\t\t\t\t// It is not necessary to compare scan[2] and match[2] since they\n\t\t\t\t// are always equal when the other bytes match, given that\n\t\t\t\t// the hash keys are equal and that HASH_BITS >= 8.\n\t\t\t\tscan += 2;\n\t\t\t\tmatch++;\n\n\t\t\t\t// We check for insufficient lookahead only every 8th comparison;\n\t\t\t\t// the 256th check will be made at strstart+258.\n\t\t\t\tdo {\n\t\t\t\t} while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]\n\t\t\t\t\t\t&& window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match]\n\t\t\t\t\t\t&& window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend);\n\n\t\t\t\tlen = MAX_MATCH - (strend - scan);\n\t\t\t\tscan = strend - MAX_MATCH;\n\n\t\t\t\tif (len > best_len) {\n\t\t\t\t\tmatch_start = cur_match;\n\t\t\t\t\tbest_len = len;\n\t\t\t\t\tif (len >= _nice_match)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tscan_end1 = window[scan + best_len - 1];\n\t\t\t\t\tscan_end = window[scan + best_len];\n\t\t\t\t}\n\n\t\t\t} while ((cur_match = (prev[cur_match & wmask] & 0xffff)) > limit && --chain_length !== 0);\n\n\t\t\tif (best_len <= lookahead)\n\t\t\t\treturn best_len;\n\t\t\treturn lookahead;\n\t\t}\n\n\t\t// Compress as much as possible from the input stream, return the current\n\t\t// block state.\n\t\t// This function does not perform lazy evaluation of matches and inserts\n\t\t// new strings in the dictionary only for unmatched strings or for short\n\t\t// matches. It is used only for the fast compression options.\n\t\tfunction deflate_fast(flush) {\n\t\t\t// short hash_head = 0; // head of the hash chain\n\t\t\tvar hash_head = 0; // head of the hash chain\n\t\t\tvar bflush; // set if current block must be flushed\n\n\t\t\twhile (true) {\n\t\t\t\t// Make sure that we always have enough lookahead, except\n\t\t\t\t// at the end of the input file. We need MAX_MATCH bytes\n\t\t\t\t// for the next match, plus MIN_MATCH bytes to insert the\n\t\t\t\t// string following the next match.\n\t\t\t\tif (lookahead < MIN_LOOKAHEAD) {\n\t\t\t\t\tfill_window();\n\t\t\t\t\tif (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {\n\t\t\t\t\t\treturn NeedMore;\n\t\t\t\t\t}\n\t\t\t\t\tif (lookahead === 0)\n\t\t\t\t\t\tbreak; // flush the current block\n\t\t\t\t}\n\n\t\t\t\t// Insert the string window[strstart .. strstart+2] in the\n\t\t\t\t// dictionary, and set hash_head to the head of the hash chain:\n\t\t\t\tif (lookahead >= MIN_MATCH) {\n\t\t\t\t\tins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;\n\n\t\t\t\t\t// prev[strstart&w_mask]=hash_head=head[ins_h];\n\t\t\t\t\thash_head = (head[ins_h] & 0xffff);\n\t\t\t\t\tprev[strstart & w_mask] = head[ins_h];\n\t\t\t\t\thead[ins_h] = strstart;\n\t\t\t\t}\n\n\t\t\t\t// Find the longest match, discarding those <= prev_length.\n\t\t\t\t// At this point we have always match_length < MIN_MATCH\n\n\t\t\t\tif (hash_head !== 0 && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {\n\t\t\t\t\t// To simplify the code, we prevent matches with the string\n\t\t\t\t\t// of window index 0 (in particular we have to avoid a match\n\t\t\t\t\t// of the string with itself at the start of the input file).\n\t\t\t\t\tif (strategy != Z_HUFFMAN_ONLY) {\n\t\t\t\t\t\tmatch_length = longest_match(hash_head);\n\t\t\t\t\t}\n\t\t\t\t\t// longest_match() sets match_start\n\t\t\t\t}\n\t\t\t\tif (match_length >= MIN_MATCH) {\n\t\t\t\t\t// check_match(strstart, match_start, match_length);\n\n\t\t\t\t\tbflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH);\n\n\t\t\t\t\tlookahead -= match_length;\n\n\t\t\t\t\t// Insert new strings in the hash table only if the match length\n\t\t\t\t\t// is not too large. This saves time but degrades compression.\n\t\t\t\t\tif (match_length <= max_lazy_match && lookahead >= MIN_MATCH) {\n\t\t\t\t\t\tmatch_length--; // string at strstart already in hash table\n\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\tstrstart++;\n\n\t\t\t\t\t\t\tins_h = ((ins_h << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;\n\t\t\t\t\t\t\t// prev[strstart&w_mask]=hash_head=head[ins_h];\n\t\t\t\t\t\t\thash_head = (head[ins_h] & 0xffff);\n\t\t\t\t\t\t\tprev[strstart & w_mask] = head[ins_h];\n\t\t\t\t\t\t\thead[ins_h] = strstart;\n\n\t\t\t\t\t\t\t// strstart never exceeds WSIZE-MAX_MATCH, so there are\n\t\t\t\t\t\t\t// always MIN_MATCH bytes ahead.\n\t\t\t\t\t\t} while (--match_length !== 0);\n\t\t\t\t\t\tstrstart++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstrstart += match_length;\n\t\t\t\t\t\tmatch_length = 0;\n\t\t\t\t\t\tins_h = window[strstart] & 0xff;\n\n\t\t\t\t\t\tins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;\n\t\t\t\t\t\t// If lookahead < MIN_MATCH, ins_h is garbage, but it does\n\t\t\t\t\t\t// not\n\t\t\t\t\t\t// matter since it will be recomputed at next deflate call.\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// No match, output a literal byte\n\n\t\t\t\t\tbflush = _tr_tally(0, window[strstart] & 0xff);\n\t\t\t\t\tlookahead--;\n\t\t\t\t\tstrstart++;\n\t\t\t\t}\n\t\t\t\tif (bflush) {\n\n\t\t\t\t\tflush_block_only(false);\n\t\t\t\t\tif (strm.avail_out === 0)\n\t\t\t\t\t\treturn NeedMore;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tflush_block_only(flush == Z_FINISH);\n\t\t\tif (strm.avail_out === 0) {\n\t\t\t\tif (flush == Z_FINISH)\n\t\t\t\t\treturn FinishStarted;\n\t\t\t\telse\n\t\t\t\t\treturn NeedMore;\n\t\t\t}\n\t\t\treturn flush == Z_FINISH ? FinishDone : BlockDone;\n\t\t}\n\n\t\t// Same as above, but achieves better compression. We use a lazy\n\t\t// evaluation for matches: a match is finally adopted only if there is\n\t\t// no better match at the next window position.\n\t\tfunction deflate_slow(flush) {\n\t\t\t// short hash_head = 0; // head of hash chain\n\t\t\tvar hash_head = 0; // head of hash chain\n\t\t\tvar bflush; // set if current block must be flushed\n\t\t\tvar max_insert;\n\n\t\t\t// Process the input block.\n\t\t\twhile (true) {\n\t\t\t\t// Make sure that we always have enough lookahead, except\n\t\t\t\t// at the end of the input file. We need MAX_MATCH bytes\n\t\t\t\t// for the next match, plus MIN_MATCH bytes to insert the\n\t\t\t\t// string following the next match.\n\n\t\t\t\tif (lookahead < MIN_LOOKAHEAD) {\n\t\t\t\t\tfill_window();\n\t\t\t\t\tif (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {\n\t\t\t\t\t\treturn NeedMore;\n\t\t\t\t\t}\n\t\t\t\t\tif (lookahead === 0)\n\t\t\t\t\t\tbreak; // flush the current block\n\t\t\t\t}\n\n\t\t\t\t// Insert the string window[strstart .. strstart+2] in the\n\t\t\t\t// dictionary, and set hash_head to the head of the hash chain:\n\n\t\t\t\tif (lookahead >= MIN_MATCH) {\n\t\t\t\t\tins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;\n\t\t\t\t\t// prev[strstart&w_mask]=hash_head=head[ins_h];\n\t\t\t\t\thash_head = (head[ins_h] & 0xffff);\n\t\t\t\t\tprev[strstart & w_mask] = head[ins_h];\n\t\t\t\t\thead[ins_h] = strstart;\n\t\t\t\t}\n\n\t\t\t\t// Find the longest match, discarding those <= prev_length.\n\t\t\t\tprev_length = match_length;\n\t\t\t\tprev_match = match_start;\n\t\t\t\tmatch_length = MIN_MATCH - 1;\n\n\t\t\t\tif (hash_head !== 0 && prev_length < max_lazy_match && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) {\n\t\t\t\t\t// To simplify the code, we prevent matches with the string\n\t\t\t\t\t// of window index 0 (in particular we have to avoid a match\n\t\t\t\t\t// of the string with itself at the start of the input file).\n\n\t\t\t\t\tif (strategy != Z_HUFFMAN_ONLY) {\n\t\t\t\t\t\tmatch_length = longest_match(hash_head);\n\t\t\t\t\t}\n\t\t\t\t\t// longest_match() sets match_start\n\n\t\t\t\t\tif (match_length <= 5 && (strategy == Z_FILTERED || (match_length == MIN_MATCH && strstart - match_start > 4096))) {\n\n\t\t\t\t\t\t// If prev_match is also MIN_MATCH, match_start is garbage\n\t\t\t\t\t\t// but we will ignore the current match anyway.\n\t\t\t\t\t\tmatch_length = MIN_MATCH - 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If there was a match at the previous step and the current\n\t\t\t\t// match is not better, output the previous match:\n\t\t\t\tif (prev_length >= MIN_MATCH && match_length <= prev_length) {\n\t\t\t\t\tmax_insert = strstart + lookahead - MIN_MATCH;\n\t\t\t\t\t// Do not insert strings in hash table beyond this.\n\n\t\t\t\t\t// check_match(strstart-1, prev_match, prev_length);\n\n\t\t\t\t\tbflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);\n\n\t\t\t\t\t// Insert in hash table all strings up to the end of the match.\n\t\t\t\t\t// strstart-1 and strstart are already inserted. If there is not\n\t\t\t\t\t// enough lookahead, the last two strings are not inserted in\n\t\t\t\t\t// the hash table.\n\t\t\t\t\tlookahead -= prev_length - 1;\n\t\t\t\t\tprev_length -= 2;\n\t\t\t\t\tdo {\n\t\t\t\t\t\tif (++strstart <= max_insert) {\n\t\t\t\t\t\t\tins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;\n\t\t\t\t\t\t\t// prev[strstart&w_mask]=hash_head=head[ins_h];\n\t\t\t\t\t\t\thash_head = (head[ins_h] & 0xffff);\n\t\t\t\t\t\t\tprev[strstart & w_mask] = head[ins_h];\n\t\t\t\t\t\t\thead[ins_h] = strstart;\n\t\t\t\t\t\t}\n\t\t\t\t\t} while (--prev_length !== 0);\n\t\t\t\t\tmatch_available = 0;\n\t\t\t\t\tmatch_length = MIN_MATCH - 1;\n\t\t\t\t\tstrstart++;\n\n\t\t\t\t\tif (bflush) {\n\t\t\t\t\t\tflush_block_only(false);\n\t\t\t\t\t\tif (strm.avail_out === 0)\n\t\t\t\t\t\t\treturn NeedMore;\n\t\t\t\t\t}\n\t\t\t\t} else if (match_available !== 0) {\n\n\t\t\t\t\t// If there was no match at the previous position, output a\n\t\t\t\t\t// single literal. If there was a match but the current match\n\t\t\t\t\t// is longer, truncate the previous match to a single literal.\n\n\t\t\t\t\tbflush = _tr_tally(0, window[strstart - 1] & 0xff);\n\n\t\t\t\t\tif (bflush) {\n\t\t\t\t\t\tflush_block_only(false);\n\t\t\t\t\t}\n\t\t\t\t\tstrstart++;\n\t\t\t\t\tlookahead--;\n\t\t\t\t\tif (strm.avail_out === 0)\n\t\t\t\t\t\treturn NeedMore;\n\t\t\t\t} else {\n\t\t\t\t\t// There is no previous match to compare with, wait for\n\t\t\t\t\t// the next step to decide.\n\n\t\t\t\t\tmatch_available = 1;\n\t\t\t\t\tstrstart++;\n\t\t\t\t\tlookahead--;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (match_available !== 0) {\n\t\t\t\tbflush = _tr_tally(0, window[strstart - 1] & 0xff);\n\t\t\t\tmatch_available = 0;\n\t\t\t}\n\t\t\tflush_block_only(flush == Z_FINISH);\n\n\t\t\tif (strm.avail_out === 0) {\n\t\t\t\tif (flush == Z_FINISH)\n\t\t\t\t\treturn FinishStarted;\n\t\t\t\telse\n\t\t\t\t\treturn NeedMore;\n\t\t\t}\n\n\t\t\treturn flush == Z_FINISH ? FinishDone : BlockDone;\n\t\t}\n\n\t\tfunction deflateReset(strm) {\n\t\t\tstrm.total_in = strm.total_out = 0;\n\t\t\tstrm.msg = null; //\n\t\t\tstrm.data_type = Z_UNKNOWN;\n\n\t\t\tthat.pending = 0;\n\t\t\tthat.pending_out = 0;\n\n\t\t\tstatus = BUSY_STATE;\n\n\t\t\tlast_flush = Z_NO_FLUSH;\n\n\t\t\ttr_init();\n\t\t\tlm_init();\n\t\t\treturn Z_OK;\n\t\t}\n\n\t\tthat.deflateInit = function(strm, _level, bits, _method, memLevel, _strategy) {\n\t\t\tif (!_method)\n\t\t\t\t_method = Z_DEFLATED;\n\t\t\tif (!memLevel)\n\t\t\t\tmemLevel = DEF_MEM_LEVEL;\n\t\t\tif (!_strategy)\n\t\t\t\t_strategy = Z_DEFAULT_STRATEGY;\n\n\t\t\t// byte[] my_version=ZLIB_VERSION;\n\n\t\t\t//\n\t\t\t// if (!version || version[0] != my_version[0]\n\t\t\t// || stream_size != sizeof(z_stream)) {\n\t\t\t// return Z_VERSION_ERROR;\n\t\t\t// }\n\n\t\t\tstrm.msg = null;\n\n\t\t\tif (_level == Z_DEFAULT_COMPRESSION)\n\t\t\t\t_level = 6;\n\n\t\t\tif (memLevel < 1 || memLevel > MAX_MEM_LEVEL || _method != Z_DEFLATED || bits < 9 || bits > 15 || _level < 0 || _level > 9 || _strategy < 0\n\t\t\t\t\t|| _strategy > Z_HUFFMAN_ONLY) {\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\t}\n\n\t\t\tstrm.dstate = that;\n\n\t\t\tw_bits = bits;\n\t\t\tw_size = 1 << w_bits;\n\t\t\tw_mask = w_size - 1;\n\n\t\t\thash_bits = memLevel + 7;\n\t\t\thash_size = 1 << hash_bits;\n\t\t\thash_mask = hash_size - 1;\n\t\t\thash_shift = Math.floor((hash_bits + MIN_MATCH - 1) / MIN_MATCH);\n\n\t\t\twindow = new Uint8Array(w_size * 2);\n\t\t\tprev = [];\n\t\t\thead = [];\n\n\t\t\tlit_bufsize = 1 << (memLevel + 6); // 16K elements by default\n\n\t\t\t// We overlay pending_buf and d_buf+l_buf. This works since the average\n\t\t\t// output size for (length,distance) codes is <= 24 bits.\n\t\t\tthat.pending_buf = new Uint8Array(lit_bufsize * 4);\n\t\t\tpending_buf_size = lit_bufsize * 4;\n\n\t\t\td_buf = Math.floor(lit_bufsize / 2);\n\t\t\tl_buf = (1 + 2) * lit_bufsize;\n\n\t\t\tlevel = _level;\n\n\t\t\tstrategy = _strategy;\n\t\t\tmethod = _method & 0xff;\n\n\t\t\treturn deflateReset(strm);\n\t\t};\n\n\t\tthat.deflateEnd = function() {\n\t\t\tif (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) {\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\t}\n\t\t\t// Deallocate in reverse order of allocations:\n\t\t\tthat.pending_buf = null;\n\t\t\thead = null;\n\t\t\tprev = null;\n\t\t\twindow = null;\n\t\t\t// free\n\t\t\tthat.dstate = null;\n\t\t\treturn status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;\n\t\t};\n\n\t\tthat.deflateParams = function(strm, _level, _strategy) {\n\t\t\tvar err = Z_OK;\n\n\t\t\tif (_level == Z_DEFAULT_COMPRESSION) {\n\t\t\t\t_level = 6;\n\t\t\t}\n\t\t\tif (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\t}\n\n\t\t\tif (config_table[level].func != config_table[_level].func && strm.total_in !== 0) {\n\t\t\t\t// Flush the last buffer:\n\t\t\t\terr = strm.deflate(Z_PARTIAL_FLUSH);\n\t\t\t}\n\n\t\t\tif (level != _level) {\n\t\t\t\tlevel = _level;\n\t\t\t\tmax_lazy_match = config_table[level].max_lazy;\n\t\t\t\tgood_match = config_table[level].good_length;\n\t\t\t\tnice_match = config_table[level].nice_length;\n\t\t\t\tmax_chain_length = config_table[level].max_chain;\n\t\t\t}\n\t\t\tstrategy = _strategy;\n\t\t\treturn err;\n\t\t};\n\n\t\tthat.deflateSetDictionary = function(strm, dictionary, dictLength) {\n\t\t\tvar length = dictLength;\n\t\t\tvar n, index = 0;\n\n\t\t\tif (!dictionary || status != INIT_STATE)\n\t\t\t\treturn Z_STREAM_ERROR;\n\n\t\t\tif (length < MIN_MATCH)\n\t\t\t\treturn Z_OK;\n\t\t\tif (length > w_size - MIN_LOOKAHEAD) {\n\t\t\t\tlength = w_size - MIN_LOOKAHEAD;\n\t\t\t\tindex = dictLength - length; // use the tail of the dictionary\n\t\t\t}\n\t\t\twindow.set(dictionary.subarray(index, index + length), 0);\n\n\t\t\tstrstart = length;\n\t\t\tblock_start = length;\n\n\t\t\t// Insert all strings in the hash table (except for the last two bytes).\n\t\t\t// s->lookahead stays null, so s->ins_h will be recomputed at the next\n\t\t\t// call of fill_window.\n\n\t\t\tins_h = window[0] & 0xff;\n\t\t\tins_h = (((ins_h) << hash_shift) ^ (window[1] & 0xff)) & hash_mask;\n\n\t\t\tfor (n = 0; n <= length - MIN_MATCH; n++) {\n\t\t\t\tins_h = (((ins_h) << hash_shift) ^ (window[(n) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;\n\t\t\t\tprev[n & w_mask] = head[ins_h];\n\t\t\t\thead[ins_h] = n;\n\t\t\t}\n\t\t\treturn Z_OK;\n\t\t};\n\n\t\tthat.deflate = function(_strm, flush) {\n\t\t\tvar i, header, level_flags, old_flush, bstate;\n\n\t\t\tif (flush > Z_FINISH || flush < 0) {\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\t}\n\n\t\t\tif (!_strm.next_out || (!_strm.next_in && _strm.avail_in !== 0) || (status == FINISH_STATE && flush != Z_FINISH)) {\n\t\t\t\t_strm.msg = z_errmsg[Z_NEED_DICT - (Z_STREAM_ERROR)];\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\t}\n\t\t\tif (_strm.avail_out === 0) {\n\t\t\t\t_strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];\n\t\t\t\treturn Z_BUF_ERROR;\n\t\t\t}\n\n\t\t\tstrm = _strm; // just in case\n\t\t\told_flush = last_flush;\n\t\t\tlast_flush = flush;\n\n\t\t\t// Write the zlib header\n\t\t\tif (status == INIT_STATE) {\n\t\t\t\theader = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8;\n\t\t\t\tlevel_flags = ((level - 1) & 0xff) >> 1;\n\n\t\t\t\tif (level_flags > 3)\n\t\t\t\t\tlevel_flags = 3;\n\t\t\t\theader |= (level_flags << 6);\n\t\t\t\tif (strstart !== 0)\n\t\t\t\t\theader |= PRESET_DICT;\n\t\t\t\theader += 31 - (header % 31);\n\n\t\t\t\tstatus = BUSY_STATE;\n\t\t\t\tputShortMSB(header);\n\t\t\t}\n\n\t\t\t// Flush as much pending output as possible\n\t\t\tif (that.pending !== 0) {\n\t\t\t\tstrm.flush_pending();\n\t\t\t\tif (strm.avail_out === 0) {\n\t\t\t\t\t// console.log(\" avail_out==0\");\n\t\t\t\t\t// Since avail_out is 0, deflate will be called again with\n\t\t\t\t\t// more output space, but possibly with both pending and\n\t\t\t\t\t// avail_in equal to zero. There won't be anything to do,\n\t\t\t\t\t// but this is not an error situation so make sure we\n\t\t\t\t\t// return OK instead of BUF_ERROR at next call of deflate:\n\t\t\t\t\tlast_flush = -1;\n\t\t\t\t\treturn Z_OK;\n\t\t\t\t}\n\n\t\t\t\t// Make sure there is something to do and avoid duplicate\n\t\t\t\t// consecutive\n\t\t\t\t// flushes. For repeated and useless calls with Z_FINISH, we keep\n\t\t\t\t// returning Z_STREAM_END instead of Z_BUFF_ERROR.\n\t\t\t} else if (strm.avail_in === 0 && flush <= old_flush && flush != Z_FINISH) {\n\t\t\t\tstrm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];\n\t\t\t\treturn Z_BUF_ERROR;\n\t\t\t}\n\n\t\t\t// User must not provide more input after the first FINISH:\n\t\t\tif (status == FINISH_STATE && strm.avail_in !== 0) {\n\t\t\t\t_strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)];\n\t\t\t\treturn Z_BUF_ERROR;\n\t\t\t}\n\n\t\t\t// Start a new block or continue the current one.\n\t\t\tif (strm.avail_in !== 0 || lookahead !== 0 || (flush != Z_NO_FLUSH && status != FINISH_STATE)) {\n\t\t\t\tbstate = -1;\n\t\t\t\tswitch (config_table[level].func) {\n\t\t\t\tcase STORED:\n\t\t\t\t\tbstate = deflate_stored(flush);\n\t\t\t\t\tbreak;\n\t\t\t\tcase FAST:\n\t\t\t\t\tbstate = deflate_fast(flush);\n\t\t\t\t\tbreak;\n\t\t\t\tcase SLOW:\n\t\t\t\t\tbstate = deflate_slow(flush);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t}\n\n\t\t\t\tif (bstate == FinishStarted || bstate == FinishDone) {\n\t\t\t\t\tstatus = FINISH_STATE;\n\t\t\t\t}\n\t\t\t\tif (bstate == NeedMore || bstate == FinishStarted) {\n\t\t\t\t\tif (strm.avail_out === 0) {\n\t\t\t\t\t\tlast_flush = -1; // avoid BUF_ERROR next call, see above\n\t\t\t\t\t}\n\t\t\t\t\treturn Z_OK;\n\t\t\t\t\t// If flush != Z_NO_FLUSH && avail_out === 0, the next call\n\t\t\t\t\t// of deflate should use the same flush parameter to make sure\n\t\t\t\t\t// that the flush is complete. So we don't have to output an\n\t\t\t\t\t// empty block here, this will be done at next call. This also\n\t\t\t\t\t// ensures that for a very small output buffer, we emit at most\n\t\t\t\t\t// one empty block.\n\t\t\t\t}\n\n\t\t\t\tif (bstate == BlockDone) {\n\t\t\t\t\tif (flush == Z_PARTIAL_FLUSH) {\n\t\t\t\t\t\t_tr_align();\n\t\t\t\t\t} else { // FULL_FLUSH or SYNC_FLUSH\n\t\t\t\t\t\t_tr_stored_block(0, 0, false);\n\t\t\t\t\t\t// For a full flush, this empty block will be recognized\n\t\t\t\t\t\t// as a special marker by inflate_sync().\n\t\t\t\t\t\tif (flush == Z_FULL_FLUSH) {\n\t\t\t\t\t\t\t// state.head[s.hash_size-1]=0;\n\t\t\t\t\t\t\tfor (i = 0; i < hash_size/*-1*/; i++)\n\t\t\t\t\t\t\t\t// forget history\n\t\t\t\t\t\t\t\thead[i] = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tstrm.flush_pending();\n\t\t\t\t\tif (strm.avail_out === 0) {\n\t\t\t\t\t\tlast_flush = -1; // avoid BUF_ERROR at next call, see above\n\t\t\t\t\t\treturn Z_OK;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (flush != Z_FINISH)\n\t\t\t\treturn Z_OK;\n\t\t\treturn Z_STREAM_END;\n\t\t};\n\t}\n\n\t// ZStream\n\n\tfunction ZStream() {\n\t\tvar that = this;\n\t\tthat.next_in_index = 0;\n\t\tthat.next_out_index = 0;\n\t\t// that.next_in; // next input byte\n\t\tthat.avail_in = 0; // number of bytes available at next_in\n\t\tthat.total_in = 0; // total nb of input bytes read so far\n\t\t// that.next_out; // next output byte should be put there\n\t\tthat.avail_out = 0; // remaining free space at next_out\n\t\tthat.total_out = 0; // total nb of bytes output so far\n\t\t// that.msg;\n\t\t// that.dstate;\n\t\t// that.data_type; // best guess about the data type: ascii or binary\n\n\t}\n\n\tZStream.prototype = {\n\t\tdeflateInit : function(level, bits) {\n\t\t\tvar that = this;\n\t\t\tthat.dstate = new Deflate();\n\t\t\tif (!bits)\n\t\t\t\tbits = MAX_BITS;\n\t\t\treturn that.dstate.deflateInit(that, level, bits);\n\t\t},\n\n\t\tdeflate : function(flush) {\n\t\t\tvar that = this;\n\t\t\tif (!that.dstate) {\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\t}\n\t\t\treturn that.dstate.deflate(that, flush);\n\t\t},\n\n\t\tdeflateEnd : function() {\n\t\t\tvar that = this;\n\t\t\tif (!that.dstate)\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\tvar ret = that.dstate.deflateEnd();\n\t\t\tthat.dstate = null;\n\t\t\treturn ret;\n\t\t},\n\n\t\tdeflateParams : function(level, strategy) {\n\t\t\tvar that = this;\n\t\t\tif (!that.dstate)\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\treturn that.dstate.deflateParams(that, level, strategy);\n\t\t},\n\n\t\tdeflateSetDictionary : function(dictionary, dictLength) {\n\t\t\tvar that = this;\n\t\t\tif (!that.dstate)\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\treturn that.dstate.deflateSetDictionary(that, dictionary, dictLength);\n\t\t},\n\n\t\t// Read a new buffer from the current input stream, update the\n\t\t// total number of bytes read. All deflate() input goes through\n\t\t// this function so some applications may wish to modify it to avoid\n\t\t// allocating a large strm->next_in buffer and copying from it.\n\t\t// (See also flush_pending()).\n\t\tread_buf : function(buf, start, size) {\n\t\t\tvar that = this;\n\t\t\tvar len = that.avail_in;\n\t\t\tif (len > size)\n\t\t\t\tlen = size;\n\t\t\tif (len === 0)\n\t\t\t\treturn 0;\n\t\t\tthat.avail_in -= len;\n\t\t\tbuf.set(that.next_in.subarray(that.next_in_index, that.next_in_index + len), start);\n\t\t\tthat.next_in_index += len;\n\t\t\tthat.total_in += len;\n\t\t\treturn len;\n\t\t},\n\n\t\t// Flush as much pending output as possible. All deflate() output goes\n\t\t// through this function so some applications may wish to modify it\n\t\t// to avoid allocating a large strm->next_out buffer and copying into it.\n\t\t// (See also read_buf()).\n\t\tflush_pending : function() {\n\t\t\tvar that = this;\n\t\t\tvar len = that.dstate.pending;\n\n\t\t\tif (len > that.avail_out)\n\t\t\t\tlen = that.avail_out;\n\t\t\tif (len === 0)\n\t\t\t\treturn;\n\n\t\t\t// if (that.dstate.pending_buf.length <= that.dstate.pending_out || that.next_out.length <= that.next_out_index\n\t\t\t// || that.dstate.pending_buf.length < (that.dstate.pending_out + len) || that.next_out.length < (that.next_out_index +\n\t\t\t// len)) {\n\t\t\t// console.log(that.dstate.pending_buf.length + \", \" + that.dstate.pending_out + \", \" + that.next_out.length + \", \" +\n\t\t\t// that.next_out_index + \", \" + len);\n\t\t\t// console.log(\"avail_out=\" + that.avail_out);\n\t\t\t// }\n\n\t\t\tthat.next_out.set(that.dstate.pending_buf.subarray(that.dstate.pending_out, that.dstate.pending_out + len), that.next_out_index);\n\n\t\t\tthat.next_out_index += len;\n\t\t\tthat.dstate.pending_out += len;\n\t\t\tthat.total_out += len;\n\t\t\tthat.avail_out -= len;\n\t\t\tthat.dstate.pending -= len;\n\t\t\tif (that.dstate.pending === 0) {\n\t\t\t\tthat.dstate.pending_out = 0;\n\t\t\t}\n\t\t}\n\t};\n\n\t// Deflater\n\n\tfunction Deflater(level) {\n\t\tvar that = this;\n\t\tvar z = new ZStream();\n\t\tvar bufsize = 512;\n\t\tvar flush = Z_NO_FLUSH;\n\t\tvar buf = new Uint8Array(bufsize);\n\n\t\tif (typeof level == \"undefined\")\n\t\t\tlevel = Z_DEFAULT_COMPRESSION;\n\t\tz.deflateInit(level);\n\t\tz.next_out = buf;\n\n\t\tthat.append = function(data, onprogress) {\n\t\t\tvar err, buffers = [], lastIndex = 0, bufferIndex = 0, bufferSize = 0, array;\n\t\t\tif (!data.length)\n\t\t\t\treturn;\n\t\t\tz.next_in_index = 0;\n\t\t\tz.next_in = data;\n\t\t\tz.avail_in = data.length;\n\t\t\tdo {\n\t\t\t\tz.next_out_index = 0;\n\t\t\t\tz.avail_out = bufsize;\n\t\t\t\terr = z.deflate(flush);\n\t\t\t\tif (err != Z_OK)\n\t\t\t\t\tthrow \"deflating: \" + z.msg;\n\t\t\t\tif (z.next_out_index)\n\t\t\t\t\tif (z.next_out_index == bufsize)\n\t\t\t\t\t\tbuffers.push(new Uint8Array(buf));\n\t\t\t\t\telse\n\t\t\t\t\t\tbuffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));\n\t\t\t\tbufferSize += z.next_out_index;\n\t\t\t\tif (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {\n\t\t\t\t\tonprogress(z.next_in_index);\n\t\t\t\t\tlastIndex = z.next_in_index;\n\t\t\t\t}\n\t\t\t} while (z.avail_in > 0 || z.avail_out === 0);\n\t\t\tarray = new Uint8Array(bufferSize);\n\t\t\tbuffers.forEach(function(chunk) {\n\t\t\t\tarray.set(chunk, bufferIndex);\n\t\t\t\tbufferIndex += chunk.length;\n\t\t\t});\n\t\t\treturn array;\n\t\t};\n\t\tthat.flush = function() {\n\t\t\tvar err, buffers = [], bufferIndex = 0, bufferSize = 0, array;\n\t\t\tdo {\n\t\t\t\tz.next_out_index = 0;\n\t\t\t\tz.avail_out = bufsize;\n\t\t\t\terr = z.deflate(Z_FINISH);\n\t\t\t\tif (err != Z_STREAM_END && err != Z_OK)\n\t\t\t\t\tthrow \"deflating: \" + z.msg;\n\t\t\t\tif (bufsize - z.avail_out > 0)\n\t\t\t\t\tbuffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));\n\t\t\t\tbufferSize += z.next_out_index;\n\t\t\t} while (z.avail_in > 0 || z.avail_out === 0);\n\t\t\tz.deflateEnd();\n\t\t\tarray = new Uint8Array(bufferSize);\n\t\t\tbuffers.forEach(function(chunk) {\n\t\t\t\tarray.set(chunk, bufferIndex);\n\t\t\t\tbufferIndex += chunk.length;\n\t\t\t});\n\t\t\treturn array;\n\t\t};\n\t}\n\n\tvar deflater;\n\n\tif (obj.zip)\n\t\tobj.zip.Deflater = Deflater;\n\telse {\n\t\tdeflater = new Deflater();\n\t\tobj.addEventListener(\"message\", function(event) {\n\t\t\tvar message = event.data;\n\t\t\tif (message.init) {\n\t\t\t\tdeflater = new Deflater(message.level);\n\t\t\t\tobj.postMessage({\n\t\t\t\t\toninit : true\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (message.append)\n\t\t\t\tobj.postMessage({\n\t\t\t\t\tonappend : true,\n\t\t\t\t\tdata : deflater.append(message.data, function(current) {\n\t\t\t\t\t\tobj.postMessage({\n\t\t\t\t\t\t\tprogress : true,\n\t\t\t\t\t\t\tcurrent : current\n\t\t\t\t\t\t});\n\t\t\t\t\t})\n\t\t\t\t});\n\t\t\tif (message.flush)\n\t\t\t\tobj.postMessage({\n\t\t\t\t\tonflush : true,\n\t\t\t\t\tdata : deflater.flush()\n\t\t\t\t});\n\t\t}, false);\n\t}\n\n})(this);\n"
  },
  {
    "path": "_archive/apps/samples/web-store/js/zip/inflate.js",
    "content": "/*\n Copyright (c) 2012 Gildas Lormeau. All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n\n 1. Redistributions of source code must retain the above copyright notice,\n this list of conditions and the following disclaimer.\n\n 2. Redistributions in binary form must reproduce the above copyright \n notice, this list of conditions and the following disclaimer in \n the documentation and/or other materials provided with the distribution.\n\n 3. The names of the authors may not be used to endorse or promote products\n derived from this software without specific prior written permission.\n\n THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\n INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\n INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\n INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\n OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * This program is based on JZlib 1.0.2 ymnk, JCraft,Inc.\n * JZlib is based on zlib-1.1.3, so all credit should go authors\n * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)\n * and contributors of zlib.\n */\n\n(function(obj) {\n\n\t// Global\n\tvar MAX_BITS = 15;\n\n\tvar Z_OK = 0;\n\tvar Z_STREAM_END = 1;\n\tvar Z_NEED_DICT = 2;\n\tvar Z_STREAM_ERROR = -2;\n\tvar Z_DATA_ERROR = -3;\n\tvar Z_MEM_ERROR = -4;\n\tvar Z_BUF_ERROR = -5;\n\n\tvar inflate_mask = [ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff,\n\t\t\t0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff ];\n\n\tvar MANY = 1440;\n\n\t// JZlib version : \"1.0.2\"\n\tvar Z_NO_FLUSH = 0;\n\tvar Z_FINISH = 4;\n\n\t// InfTree\n\tvar fixed_bl = 9;\n\tvar fixed_bd = 5;\n\n\tvar fixed_tl = [ 96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 192, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 160, 0, 8, 0,\n\t\t\t0, 8, 128, 0, 8, 64, 0, 9, 224, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 144, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 208, 81, 7, 17, 0, 8, 104, 0, 8, 40,\n\t\t\t0, 9, 176, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 240, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 200, 81, 7, 13,\n\t\t\t0, 8, 100, 0, 8, 36, 0, 9, 168, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 232, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 152, 84, 7, 83, 0, 8, 124, 0, 8, 60,\n\t\t\t0, 9, 216, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 184, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 248, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7,\n\t\t\t35, 0, 8, 114, 0, 8, 50, 0, 9, 196, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 164, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 228, 80, 7, 7, 0, 8, 90, 0, 8,\n\t\t\t26, 0, 9, 148, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 212, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 180, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 244, 80,\n\t\t\t7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 204, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 172, 0, 8, 6, 0, 8, 134, 0,\n\t\t\t8, 70, 0, 9, 236, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 156, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 220, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 188, 0,\n\t\t\t8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 252, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 194, 80, 7, 10, 0, 8, 97,\n\t\t\t0, 8, 33, 0, 9, 162, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 226, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 146, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 210,\n\t\t\t81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 178, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 242, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117,\n\t\t\t0, 8, 53, 0, 9, 202, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 170, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 234, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 154,\n\t\t\t84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 218, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 186, 0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 250, 80, 7, 3, 0, 8, 83,\n\t\t\t0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 198, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 166, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 230,\n\t\t\t80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 150, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 214, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 182, 0, 8, 11, 0, 8, 139,\n\t\t\t0, 8, 75, 0, 9, 246, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 206, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 174,\n\t\t\t0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 238, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 158, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 222, 82, 7, 27, 0, 8, 111,\n\t\t\t0, 8, 47, 0, 9, 190, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 254, 96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9,\n\t\t\t193, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 161, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 225, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 145, 83, 7, 59, 0, 8,\n\t\t\t120, 0, 8, 56, 0, 9, 209, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 177, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 241, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8,\n\t\t\t227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 201, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 169, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 233, 80, 7, 8, 0, 8,\n\t\t\t92, 0, 8, 28, 0, 9, 153, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 217, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 185, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9,\n\t\t\t249, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 197, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 165, 0, 8, 2, 0, 8,\n\t\t\t130, 0, 8, 66, 0, 9, 229, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 149, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 213, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9,\n\t\t\t181, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 245, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 205, 81, 7, 15, 0, 8,\n\t\t\t102, 0, 8, 38, 0, 9, 173, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 237, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 157, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9,\n\t\t\t221, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 189, 0, 8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 253, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0,\n\t\t\t8, 113, 0, 8, 49, 0, 9, 195, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 163, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 227, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9,\n\t\t\t147, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 211, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 179, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 243, 80, 7, 4, 0, 8,\n\t\t\t85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 203, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 171, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9,\n\t\t\t235, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 155, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 219, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 187, 0, 8, 13, 0, 8,\n\t\t\t141, 0, 8, 77, 0, 9, 251, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 199, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9,\n\t\t\t167, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 231, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 151, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 215, 82, 7, 19, 0, 8,\n\t\t\t107, 0, 8, 43, 0, 9, 183, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 247, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9,\n\t\t\t207, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 175, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 239, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 159, 84, 7, 99, 0, 8,\n\t\t\t127, 0, 8, 63, 0, 9, 223, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 191, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 255 ];\n\tvar fixed_td = [ 80, 5, 1, 87, 5, 257, 83, 5, 17, 91, 5, 4097, 81, 5, 5, 89, 5, 1025, 85, 5, 65, 93, 5, 16385, 80, 5, 3, 88, 5, 513, 84, 5, 33, 92, 5,\n\t\t\t8193, 82, 5, 9, 90, 5, 2049, 86, 5, 129, 192, 5, 24577, 80, 5, 2, 87, 5, 385, 83, 5, 25, 91, 5, 6145, 81, 5, 7, 89, 5, 1537, 85, 5, 97, 93, 5,\n\t\t\t24577, 80, 5, 4, 88, 5, 769, 84, 5, 49, 92, 5, 12289, 82, 5, 13, 90, 5, 3073, 86, 5, 193, 192, 5, 24577 ];\n\n\t// Tables for deflate from PKZIP's appnote.txt.\n\tvar cplens = [ // Copy lengths for literal codes 257..285\n\t3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 ];\n\n\t// see note #13 above about 258\n\tvar cplext = [ // Extra bits for literal codes 257..285\n\t0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid\n\t];\n\n\tvar cpdist = [ // Copy offsets for distance codes 0..29\n\t1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 ];\n\n\tvar cpdext = [ // Extra bits for distance codes\n\t0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 ];\n\n\t// If BMAX needs to be larger than 16, then h and x[] should be uLong.\n\tvar BMAX = 15; // maximum bit length of any code\n\n\tfunction InfTree() {\n\t\tvar that = this;\n\n\t\tvar hn; // hufts used in space\n\t\tvar v; // work area for huft_build\n\t\tvar c; // bit length count table\n\t\tvar r; // table entry for structure assignment\n\t\tvar u; // table stack\n\t\tvar x; // bit offsets, then code stack\n\n\t\tfunction huft_build(b, // code lengths in bits (all assumed <=\n\t\t// BMAX)\n\t\tbindex, n, // number of codes (assumed <= 288)\n\t\ts, // number of simple-valued codes (0..s-1)\n\t\td, // list of base values for non-simple codes\n\t\te, // list of extra bits for non-simple codes\n\t\tt, // result: starting table\n\t\tm, // maximum lookup bits, returns actual\n\t\thp,// space for trees\n\t\thn,// hufts used in space\n\t\tv // working area: values in order of bit length\n\t\t) {\n\t\t\t// Given a list of code lengths and a maximum table size, make a set of\n\t\t\t// tables to decode that set of codes. Return Z_OK on success,\n\t\t\t// Z_BUF_ERROR\n\t\t\t// if the given code set is incomplete (the tables are still built in\n\t\t\t// this\n\t\t\t// case), Z_DATA_ERROR if the input is invalid (an over-subscribed set\n\t\t\t// of\n\t\t\t// lengths), or Z_MEM_ERROR if not enough memory.\n\n\t\t\tvar a; // counter for codes of length k\n\t\t\tvar f; // i repeats in table every f entries\n\t\t\tvar g; // maximum code length\n\t\t\tvar h; // table level\n\t\t\tvar i; // counter, current code\n\t\t\tvar j; // counter\n\t\t\tvar k; // number of bits in current code\n\t\t\tvar l; // bits per table (returned in m)\n\t\t\tvar mask; // (1 << w) - 1, to avoid cc -O bug on HP\n\t\t\tvar p; // pointer into c[], b[], or v[]\n\t\t\tvar q; // points to current table\n\t\t\tvar w; // bits before this table == (l * h)\n\t\t\tvar xp; // pointer into x\n\t\t\tvar y; // number of dummy codes added\n\t\t\tvar z; // number of entries in current table\n\n\t\t\t// Generate counts for each bit length\n\n\t\t\tp = 0;\n\t\t\ti = n;\n\t\t\tdo {\n\t\t\t\tc[b[bindex + p]]++;\n\t\t\t\tp++;\n\t\t\t\ti--; // assume all entries <= BMAX\n\t\t\t} while (i !== 0);\n\n\t\t\tif (c[0] == n) { // null input--all zero length codes\n\t\t\t\tt[0] = -1;\n\t\t\t\tm[0] = 0;\n\t\t\t\treturn Z_OK;\n\t\t\t}\n\n\t\t\t// Find minimum and maximum length, bound *m by those\n\t\t\tl = m[0];\n\t\t\tfor (j = 1; j <= BMAX; j++)\n\t\t\t\tif (c[j] !== 0)\n\t\t\t\t\tbreak;\n\t\t\tk = j; // minimum code length\n\t\t\tif (l < j) {\n\t\t\t\tl = j;\n\t\t\t}\n\t\t\tfor (i = BMAX; i !== 0; i--) {\n\t\t\t\tif (c[i] !== 0)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tg = i; // maximum code length\n\t\t\tif (l > i) {\n\t\t\t\tl = i;\n\t\t\t}\n\t\t\tm[0] = l;\n\n\t\t\t// Adjust last length count to fill out codes, if needed\n\t\t\tfor (y = 1 << j; j < i; j++, y <<= 1) {\n\t\t\t\tif ((y -= c[j]) < 0) {\n\t\t\t\t\treturn Z_DATA_ERROR;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ((y -= c[i]) < 0) {\n\t\t\t\treturn Z_DATA_ERROR;\n\t\t\t}\n\t\t\tc[i] += y;\n\n\t\t\t// Generate starting offsets into the value table for each length\n\t\t\tx[1] = j = 0;\n\t\t\tp = 1;\n\t\t\txp = 2;\n\t\t\twhile (--i !== 0) { // note that i == g from above\n\t\t\t\tx[xp] = (j += c[p]);\n\t\t\t\txp++;\n\t\t\t\tp++;\n\t\t\t}\n\n\t\t\t// Make a table of values in order of bit lengths\n\t\t\ti = 0;\n\t\t\tp = 0;\n\t\t\tdo {\n\t\t\t\tif ((j = b[bindex + p]) !== 0) {\n\t\t\t\t\tv[x[j]++] = i;\n\t\t\t\t}\n\t\t\t\tp++;\n\t\t\t} while (++i < n);\n\t\t\tn = x[g]; // set n to length of v\n\n\t\t\t// Generate the Huffman codes and for each, make the table entries\n\t\t\tx[0] = i = 0; // first Huffman code is zero\n\t\t\tp = 0; // grab values in bit order\n\t\t\th = -1; // no tables yet--level -1\n\t\t\tw = -l; // bits decoded == (l * h)\n\t\t\tu[0] = 0; // just to keep compilers happy\n\t\t\tq = 0; // ditto\n\t\t\tz = 0; // ditto\n\n\t\t\t// go through the bit lengths (k already is bits in shortest code)\n\t\t\tfor (; k <= g; k++) {\n\t\t\t\ta = c[k];\n\t\t\t\twhile (a-- !== 0) {\n\t\t\t\t\t// here i is the Huffman code of length k bits for value *p\n\t\t\t\t\t// make tables up to required level\n\t\t\t\t\twhile (k > w + l) {\n\t\t\t\t\t\th++;\n\t\t\t\t\t\tw += l; // previous table always l bits\n\t\t\t\t\t\t// compute minimum size table less than or equal to l bits\n\t\t\t\t\t\tz = g - w;\n\t\t\t\t\t\tz = (z > l) ? l : z; // table size upper limit\n\t\t\t\t\t\tif ((f = 1 << (j = k - w)) > a + 1) { // try a k-w bit table\n\t\t\t\t\t\t\t// too few codes for\n\t\t\t\t\t\t\t// k-w bit table\n\t\t\t\t\t\t\tf -= a + 1; // deduct codes from patterns left\n\t\t\t\t\t\t\txp = k;\n\t\t\t\t\t\t\tif (j < z) {\n\t\t\t\t\t\t\t\twhile (++j < z) { // try smaller tables up to z bits\n\t\t\t\t\t\t\t\t\tif ((f <<= 1) <= c[++xp])\n\t\t\t\t\t\t\t\t\t\tbreak; // enough codes to use up j bits\n\t\t\t\t\t\t\t\t\tf -= c[xp]; // else deduct codes from patterns\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tz = 1 << j; // table entries for j-bit table\n\n\t\t\t\t\t\t// allocate new table\n\t\t\t\t\t\tif (hn[0] + z > MANY) { // (note: doesn't matter for fixed)\n\t\t\t\t\t\t\treturn Z_DATA_ERROR; // overflow of MANY\n\t\t\t\t\t\t}\n\t\t\t\t\t\tu[h] = q = /* hp+ */hn[0]; // DEBUG\n\t\t\t\t\t\thn[0] += z;\n\n\t\t\t\t\t\t// connect to last table, if there is one\n\t\t\t\t\t\tif (h !== 0) {\n\t\t\t\t\t\t\tx[h] = i; // save pattern for backing up\n\t\t\t\t\t\t\tr[0] = /* (byte) */j; // bits in this table\n\t\t\t\t\t\t\tr[1] = /* (byte) */l; // bits to dump before this table\n\t\t\t\t\t\t\tj = i >>> (w - l);\n\t\t\t\t\t\t\tr[2] = /* (int) */(q - u[h - 1] - j); // offset to this table\n\t\t\t\t\t\t\thp.set(r, (u[h - 1] + j) * 3);\n\t\t\t\t\t\t\t// to\n\t\t\t\t\t\t\t// last\n\t\t\t\t\t\t\t// table\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tt[0] = q; // first table is returned result\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// set up table entry in r\n\t\t\t\t\tr[1] = /* (byte) */(k - w);\n\t\t\t\t\tif (p >= n) {\n\t\t\t\t\t\tr[0] = 128 + 64; // out of values--invalid code\n\t\t\t\t\t} else if (v[p] < s) {\n\t\t\t\t\t\tr[0] = /* (byte) */(v[p] < 256 ? 0 : 32 + 64); // 256 is\n\t\t\t\t\t\t// end-of-block\n\t\t\t\t\t\tr[2] = v[p++]; // simple code is just the value\n\t\t\t\t\t} else {\n\t\t\t\t\t\tr[0] = /* (byte) */(e[v[p] - s] + 16 + 64); // non-simple--look\n\t\t\t\t\t\t// up in lists\n\t\t\t\t\t\tr[2] = d[v[p++] - s];\n\t\t\t\t\t}\n\n\t\t\t\t\t// fill code-like entries with r\n\t\t\t\t\tf = 1 << (k - w);\n\t\t\t\t\tfor (j = i >>> w; j < z; j += f) {\n\t\t\t\t\t\thp.set(r, (q + j) * 3);\n\t\t\t\t\t}\n\n\t\t\t\t\t// backwards increment the k-bit code i\n\t\t\t\t\tfor (j = 1 << (k - 1); (i & j) !== 0; j >>>= 1) {\n\t\t\t\t\t\ti ^= j;\n\t\t\t\t\t}\n\t\t\t\t\ti ^= j;\n\n\t\t\t\t\t// backup over finished tables\n\t\t\t\t\tmask = (1 << w) - 1; // needed on HP, cc -O bug\n\t\t\t\t\twhile ((i & mask) != x[h]) {\n\t\t\t\t\t\th--; // don't need to update q\n\t\t\t\t\t\tw -= l;\n\t\t\t\t\t\tmask = (1 << w) - 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Return Z_BUF_ERROR if we were given an incomplete table\n\t\t\treturn y !== 0 && g != 1 ? Z_BUF_ERROR : Z_OK;\n\t\t}\n\n\t\tfunction initWorkArea(vsize) {\n\t\t\tvar i;\n\t\t\tif (!hn) {\n\t\t\t\thn = []; // []; //new Array(1);\n\t\t\t\tv = []; // new Array(vsize);\n\t\t\t\tc = new Int32Array(BMAX + 1); // new Array(BMAX + 1);\n\t\t\t\tr = []; // new Array(3);\n\t\t\t\tu = new Int32Array(BMAX); // new Array(BMAX);\n\t\t\t\tx = new Int32Array(BMAX + 1); // new Array(BMAX + 1);\n\t\t\t}\n\t\t\tif (v.length < vsize) {\n\t\t\t\tv = []; // new Array(vsize);\n\t\t\t}\n\t\t\tfor (i = 0; i < vsize; i++) {\n\t\t\t\tv[i] = 0;\n\t\t\t}\n\t\t\tfor (i = 0; i < BMAX + 1; i++) {\n\t\t\t\tc[i] = 0;\n\t\t\t}\n\t\t\tfor (i = 0; i < 3; i++) {\n\t\t\t\tr[i] = 0;\n\t\t\t}\n\t\t\t// for(int i=0; i<BMAX; i++){u[i]=0;}\n\t\t\tu.set(c.subarray(0, BMAX), 0);\n\t\t\t// for(int i=0; i<BMAX+1; i++){x[i]=0;}\n\t\t\tx.set(c.subarray(0, BMAX + 1), 0);\n\t\t}\n\n\t\tthat.inflate_trees_bits = function(c, // 19 code lengths\n\t\tbb, // bits tree desired/actual depth\n\t\ttb, // bits tree result\n\t\thp, // space for trees\n\t\tz // for messages\n\t\t) {\n\t\t\tvar result;\n\t\t\tinitWorkArea(19);\n\t\t\thn[0] = 0;\n\t\t\tresult = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);\n\n\t\t\tif (result == Z_DATA_ERROR) {\n\t\t\t\tz.msg = \"oversubscribed dynamic bit lengths tree\";\n\t\t\t} else if (result == Z_BUF_ERROR || bb[0] === 0) {\n\t\t\t\tz.msg = \"incomplete dynamic bit lengths tree\";\n\t\t\t\tresult = Z_DATA_ERROR;\n\t\t\t}\n\t\t\treturn result;\n\t\t};\n\n\t\tthat.inflate_trees_dynamic = function(nl, // number of literal/length codes\n\t\tnd, // number of distance codes\n\t\tc, // that many (total) code lengths\n\t\tbl, // literal desired/actual bit depth\n\t\tbd, // distance desired/actual bit depth\n\t\ttl, // literal/length tree result\n\t\ttd, // distance tree result\n\t\thp, // space for trees\n\t\tz // for messages\n\t\t) {\n\t\t\tvar result;\n\n\t\t\t// build literal/length tree\n\t\t\tinitWorkArea(288);\n\t\t\thn[0] = 0;\n\t\t\tresult = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);\n\t\t\tif (result != Z_OK || bl[0] === 0) {\n\t\t\t\tif (result == Z_DATA_ERROR) {\n\t\t\t\t\tz.msg = \"oversubscribed literal/length tree\";\n\t\t\t\t} else if (result != Z_MEM_ERROR) {\n\t\t\t\t\tz.msg = \"incomplete literal/length tree\";\n\t\t\t\t\tresult = Z_DATA_ERROR;\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\t// build distance tree\n\t\t\tinitWorkArea(288);\n\t\t\tresult = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);\n\n\t\t\tif (result != Z_OK || (bd[0] === 0 && nl > 257)) {\n\t\t\t\tif (result == Z_DATA_ERROR) {\n\t\t\t\t\tz.msg = \"oversubscribed distance tree\";\n\t\t\t\t} else if (result == Z_BUF_ERROR) {\n\t\t\t\t\tz.msg = \"incomplete distance tree\";\n\t\t\t\t\tresult = Z_DATA_ERROR;\n\t\t\t\t} else if (result != Z_MEM_ERROR) {\n\t\t\t\t\tz.msg = \"empty distance tree with lengths\";\n\t\t\t\t\tresult = Z_DATA_ERROR;\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\treturn Z_OK;\n\t\t};\n\n\t}\n\n\tInfTree.inflate_trees_fixed = function(bl, // literal desired/actual bit depth\n\tbd, // distance desired/actual bit depth\n\ttl,// literal/length tree result\n\ttd// distance tree result\n\t) {\n\t\tbl[0] = fixed_bl;\n\t\tbd[0] = fixed_bd;\n\t\ttl[0] = fixed_tl;\n\t\ttd[0] = fixed_td;\n\t\treturn Z_OK;\n\t};\n\n\t// InfCodes\n\n\t// waiting for \"i:\"=input,\n\t// \"o:\"=output,\n\t// \"x:\"=nothing\n\tvar START = 0; // x: set up for LEN\n\tvar LEN = 1; // i: get length/literal/eob next\n\tvar LENEXT = 2; // i: getting length extra (have base)\n\tvar DIST = 3; // i: get distance next\n\tvar DISTEXT = 4;// i: getting distance extra\n\tvar COPY = 5; // o: copying bytes in window, waiting\n\t// for space\n\tvar LIT = 6; // o: got literal, waiting for output\n\t// space\n\tvar WASH = 7; // o: got eob, possibly still output\n\t// waiting\n\tvar END = 8; // x: got eob and all data flushed\n\tvar BADCODE = 9;// x: got error\n\n\tfunction InfCodes() {\n\t\tvar that = this;\n\n\t\tvar mode; // current inflate_codes mode\n\n\t\t// mode dependent information\n\t\tvar len = 0;\n\n\t\tvar tree; // pointer into tree\n\t\tvar tree_index = 0;\n\t\tvar need = 0; // bits needed\n\n\t\tvar lit = 0;\n\n\t\t// if EXT or COPY, where and how much\n\t\tvar get = 0; // bits to get for extra\n\t\tvar dist = 0; // distance back to copy from\n\n\t\tvar lbits = 0; // ltree bits decoded per branch\n\t\tvar dbits = 0; // dtree bits decoder per branch\n\t\tvar ltree; // literal/length/eob tree\n\t\tvar ltree_index = 0; // literal/length/eob tree\n\t\tvar dtree; // distance tree\n\t\tvar dtree_index = 0; // distance tree\n\n\t\t// Called with number of bytes left to write in window at least 258\n\t\t// (the maximum string length) and number of input bytes available\n\t\t// at least ten. The ten bytes are six bytes for the longest length/\n\t\t// distance pair plus four bytes for overloading the bit buffer.\n\n\t\tfunction inflate_fast(bl, bd, tl, tl_index, td, td_index, s, z) {\n\t\t\tvar t; // temporary pointer\n\t\t\tvar tp; // temporary pointer\n\t\t\tvar tp_index; // temporary pointer\n\t\t\tvar e; // extra bits or operation\n\t\t\tvar b; // bit buffer\n\t\t\tvar k; // bits in bit buffer\n\t\t\tvar p; // input data pointer\n\t\t\tvar n; // bytes available there\n\t\t\tvar q; // output window write pointer\n\t\t\tvar m; // bytes to end of window or read pointer\n\t\t\tvar ml; // mask for literal/length tree\n\t\t\tvar md; // mask for distance tree\n\t\t\tvar c; // bytes to copy\n\t\t\tvar d; // distance back to copy from\n\t\t\tvar r; // copy source pointer\n\n\t\t\tvar tp_index_t_3; // (tp_index+t)*3\n\n\t\t\t// load input, output, bit values\n\t\t\tp = z.next_in_index;\n\t\t\tn = z.avail_in;\n\t\t\tb = s.bitb;\n\t\t\tk = s.bitk;\n\t\t\tq = s.write;\n\t\t\tm = q < s.read ? s.read - q - 1 : s.end - q;\n\n\t\t\t// initialize masks\n\t\t\tml = inflate_mask[bl];\n\t\t\tmd = inflate_mask[bd];\n\n\t\t\t// do until not enough input or output space for fast loop\n\t\t\tdo { // assume called with m >= 258 && n >= 10\n\t\t\t\t// get literal/length code\n\t\t\t\twhile (k < (20)) { // max bits for literal/length code\n\t\t\t\t\tn--;\n\t\t\t\t\tb |= (z.read_byte(p++) & 0xff) << k;\n\t\t\t\t\tk += 8;\n\t\t\t\t}\n\n\t\t\t\tt = b & ml;\n\t\t\t\ttp = tl;\n\t\t\t\ttp_index = tl_index;\n\t\t\t\ttp_index_t_3 = (tp_index + t) * 3;\n\t\t\t\tif ((e = tp[tp_index_t_3]) === 0) {\n\t\t\t\t\tb >>= (tp[tp_index_t_3 + 1]);\n\t\t\t\t\tk -= (tp[tp_index_t_3 + 1]);\n\n\t\t\t\t\ts.window[q++] = /* (byte) */tp[tp_index_t_3 + 2];\n\t\t\t\t\tm--;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tdo {\n\n\t\t\t\t\tb >>= (tp[tp_index_t_3 + 1]);\n\t\t\t\t\tk -= (tp[tp_index_t_3 + 1]);\n\n\t\t\t\t\tif ((e & 16) !== 0) {\n\t\t\t\t\t\te &= 15;\n\t\t\t\t\t\tc = tp[tp_index_t_3 + 2] + (/* (int) */b & inflate_mask[e]);\n\n\t\t\t\t\t\tb >>= e;\n\t\t\t\t\t\tk -= e;\n\n\t\t\t\t\t\t// decode distance base of block to copy\n\t\t\t\t\t\twhile (k < (15)) { // max bits for distance code\n\t\t\t\t\t\t\tn--;\n\t\t\t\t\t\t\tb |= (z.read_byte(p++) & 0xff) << k;\n\t\t\t\t\t\t\tk += 8;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tt = b & md;\n\t\t\t\t\t\ttp = td;\n\t\t\t\t\t\ttp_index = td_index;\n\t\t\t\t\t\ttp_index_t_3 = (tp_index + t) * 3;\n\t\t\t\t\t\te = tp[tp_index_t_3];\n\n\t\t\t\t\t\tdo {\n\n\t\t\t\t\t\t\tb >>= (tp[tp_index_t_3 + 1]);\n\t\t\t\t\t\t\tk -= (tp[tp_index_t_3 + 1]);\n\n\t\t\t\t\t\t\tif ((e & 16) !== 0) {\n\t\t\t\t\t\t\t\t// get extra bits to add to distance base\n\t\t\t\t\t\t\t\te &= 15;\n\t\t\t\t\t\t\t\twhile (k < (e)) { // get extra bits (up to 13)\n\t\t\t\t\t\t\t\t\tn--;\n\t\t\t\t\t\t\t\t\tb |= (z.read_byte(p++) & 0xff) << k;\n\t\t\t\t\t\t\t\t\tk += 8;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\td = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);\n\n\t\t\t\t\t\t\t\tb >>= (e);\n\t\t\t\t\t\t\t\tk -= (e);\n\n\t\t\t\t\t\t\t\t// do the copy\n\t\t\t\t\t\t\t\tm -= c;\n\t\t\t\t\t\t\t\tif (q >= d) { // offset before dest\n\t\t\t\t\t\t\t\t\t// just copy\n\t\t\t\t\t\t\t\t\tr = q - d;\n\t\t\t\t\t\t\t\t\tif (q - r > 0 && 2 > (q - r)) {\n\t\t\t\t\t\t\t\t\t\ts.window[q++] = s.window[r++]; // minimum\n\t\t\t\t\t\t\t\t\t\t// count is\n\t\t\t\t\t\t\t\t\t\t// three,\n\t\t\t\t\t\t\t\t\t\ts.window[q++] = s.window[r++]; // so unroll\n\t\t\t\t\t\t\t\t\t\t// loop a\n\t\t\t\t\t\t\t\t\t\t// little\n\t\t\t\t\t\t\t\t\t\tc -= 2;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\ts.window.set(s.window.subarray(r, r + 2), q);\n\t\t\t\t\t\t\t\t\t\tq += 2;\n\t\t\t\t\t\t\t\t\t\tr += 2;\n\t\t\t\t\t\t\t\t\t\tc -= 2;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else { // else offset after destination\n\t\t\t\t\t\t\t\t\tr = q - d;\n\t\t\t\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\t\t\t\tr += s.end; // force pointer in window\n\t\t\t\t\t\t\t\t\t} while (r < 0); // covers invalid distances\n\t\t\t\t\t\t\t\t\te = s.end - r;\n\t\t\t\t\t\t\t\t\tif (c > e) { // if source crosses,\n\t\t\t\t\t\t\t\t\t\tc -= e; // wrapped copy\n\t\t\t\t\t\t\t\t\t\tif (q - r > 0 && e > (q - r)) {\n\t\t\t\t\t\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\t\t\t\t\t\ts.window[q++] = s.window[r++];\n\t\t\t\t\t\t\t\t\t\t\t} while (--e !== 0);\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\ts.window.set(s.window.subarray(r, r + e), q);\n\t\t\t\t\t\t\t\t\t\t\tq += e;\n\t\t\t\t\t\t\t\t\t\t\tr += e;\n\t\t\t\t\t\t\t\t\t\t\te = 0;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tr = 0; // copy rest from start of window\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// copy all or what's left\n\t\t\t\t\t\t\t\tif (q - r > 0 && c > (q - r)) {\n\t\t\t\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\t\t\t\ts.window[q++] = s.window[r++];\n\t\t\t\t\t\t\t\t\t} while (--c !== 0);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\ts.window.set(s.window.subarray(r, r + c), q);\n\t\t\t\t\t\t\t\t\tq += c;\n\t\t\t\t\t\t\t\t\tr += c;\n\t\t\t\t\t\t\t\t\tc = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} else if ((e & 64) === 0) {\n\t\t\t\t\t\t\t\tt += tp[tp_index_t_3 + 2];\n\t\t\t\t\t\t\t\tt += (b & inflate_mask[e]);\n\t\t\t\t\t\t\t\ttp_index_t_3 = (tp_index + t) * 3;\n\t\t\t\t\t\t\t\te = tp[tp_index_t_3];\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tz.msg = \"invalid distance code\";\n\n\t\t\t\t\t\t\t\tc = z.avail_in - n;\n\t\t\t\t\t\t\t\tc = (k >> 3) < c ? k >> 3 : c;\n\t\t\t\t\t\t\t\tn += c;\n\t\t\t\t\t\t\t\tp -= c;\n\t\t\t\t\t\t\t\tk -= c << 3;\n\n\t\t\t\t\t\t\t\ts.bitb = b;\n\t\t\t\t\t\t\t\ts.bitk = k;\n\t\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\t\ts.write = q;\n\n\t\t\t\t\t\t\t\treturn Z_DATA_ERROR;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} while (true);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ((e & 64) === 0) {\n\t\t\t\t\t\tt += tp[tp_index_t_3 + 2];\n\t\t\t\t\t\tt += (b & inflate_mask[e]);\n\t\t\t\t\t\ttp_index_t_3 = (tp_index + t) * 3;\n\t\t\t\t\t\tif ((e = tp[tp_index_t_3]) === 0) {\n\n\t\t\t\t\t\t\tb >>= (tp[tp_index_t_3 + 1]);\n\t\t\t\t\t\t\tk -= (tp[tp_index_t_3 + 1]);\n\n\t\t\t\t\t\t\ts.window[q++] = /* (byte) */tp[tp_index_t_3 + 2];\n\t\t\t\t\t\t\tm--;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ((e & 32) !== 0) {\n\n\t\t\t\t\t\tc = z.avail_in - n;\n\t\t\t\t\t\tc = (k >> 3) < c ? k >> 3 : c;\n\t\t\t\t\t\tn += c;\n\t\t\t\t\t\tp -= c;\n\t\t\t\t\t\tk -= c << 3;\n\n\t\t\t\t\t\ts.bitb = b;\n\t\t\t\t\t\ts.bitk = k;\n\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\ts.write = q;\n\n\t\t\t\t\t\treturn Z_STREAM_END;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tz.msg = \"invalid literal/length code\";\n\n\t\t\t\t\t\tc = z.avail_in - n;\n\t\t\t\t\t\tc = (k >> 3) < c ? k >> 3 : c;\n\t\t\t\t\t\tn += c;\n\t\t\t\t\t\tp -= c;\n\t\t\t\t\t\tk -= c << 3;\n\n\t\t\t\t\t\ts.bitb = b;\n\t\t\t\t\t\ts.bitk = k;\n\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\ts.write = q;\n\n\t\t\t\t\t\treturn Z_DATA_ERROR;\n\t\t\t\t\t}\n\t\t\t\t} while (true);\n\t\t\t} while (m >= 258 && n >= 10);\n\n\t\t\t// not enough input or output--restore pointers and return\n\t\t\tc = z.avail_in - n;\n\t\t\tc = (k >> 3) < c ? k >> 3 : c;\n\t\t\tn += c;\n\t\t\tp -= c;\n\t\t\tk -= c << 3;\n\n\t\t\ts.bitb = b;\n\t\t\ts.bitk = k;\n\t\t\tz.avail_in = n;\n\t\t\tz.total_in += p - z.next_in_index;\n\t\t\tz.next_in_index = p;\n\t\t\ts.write = q;\n\n\t\t\treturn Z_OK;\n\t\t}\n\n\t\tthat.init = function(bl, bd, tl, tl_index, td, td_index) {\n\t\t\tmode = START;\n\t\t\tlbits = /* (byte) */bl;\n\t\t\tdbits = /* (byte) */bd;\n\t\t\tltree = tl;\n\t\t\tltree_index = tl_index;\n\t\t\tdtree = td;\n\t\t\tdtree_index = td_index;\n\t\t\ttree = null;\n\t\t};\n\n\t\tthat.proc = function(s, z, r) {\n\t\t\tvar j; // temporary storage\n\t\t\tvar tindex; // temporary pointer\n\t\t\tvar e; // extra bits or operation\n\t\t\tvar b = 0; // bit buffer\n\t\t\tvar k = 0; // bits in bit buffer\n\t\t\tvar p = 0; // input data pointer\n\t\t\tvar n; // bytes available there\n\t\t\tvar q; // output window write pointer\n\t\t\tvar m; // bytes to end of window or read pointer\n\t\t\tvar f; // pointer to copy strings from\n\n\t\t\t// copy input/output information to locals (UPDATE macro restores)\n\t\t\tp = z.next_in_index;\n\t\t\tn = z.avail_in;\n\t\t\tb = s.bitb;\n\t\t\tk = s.bitk;\n\t\t\tq = s.write;\n\t\t\tm = q < s.read ? s.read - q - 1 : s.end - q;\n\n\t\t\t// process input and output based on current state\n\t\t\twhile (true) {\n\t\t\t\tswitch (mode) {\n\t\t\t\t// waiting for \"i:\"=input, \"o:\"=output, \"x:\"=nothing\n\t\t\t\tcase START: // x: set up for LEN\n\t\t\t\t\tif (m >= 258 && n >= 10) {\n\n\t\t\t\t\t\ts.bitb = b;\n\t\t\t\t\t\ts.bitk = k;\n\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\ts.write = q;\n\t\t\t\t\t\tr = inflate_fast(lbits, dbits, ltree, ltree_index, dtree, dtree_index, s, z);\n\n\t\t\t\t\t\tp = z.next_in_index;\n\t\t\t\t\t\tn = z.avail_in;\n\t\t\t\t\t\tb = s.bitb;\n\t\t\t\t\t\tk = s.bitk;\n\t\t\t\t\t\tq = s.write;\n\t\t\t\t\t\tm = q < s.read ? s.read - q - 1 : s.end - q;\n\n\t\t\t\t\t\tif (r != Z_OK) {\n\t\t\t\t\t\t\tmode = r == Z_STREAM_END ? WASH : BADCODE;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tneed = lbits;\n\t\t\t\t\ttree = ltree;\n\t\t\t\t\ttree_index = ltree_index;\n\n\t\t\t\t\tmode = LEN;\n\t\t\t\tcase LEN: // i: get length/literal/eob next\n\t\t\t\t\tj = need;\n\n\t\t\t\t\twhile (k < (j)) {\n\t\t\t\t\t\tif (n !== 0)\n\t\t\t\t\t\t\tr = Z_OK;\n\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\ts.bitb = b;\n\t\t\t\t\t\t\ts.bitk = k;\n\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\ts.write = q;\n\t\t\t\t\t\t\treturn s.inflate_flush(z, r);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tn--;\n\t\t\t\t\t\tb |= (z.read_byte(p++) & 0xff) << k;\n\t\t\t\t\t\tk += 8;\n\t\t\t\t\t}\n\n\t\t\t\t\ttindex = (tree_index + (b & inflate_mask[j])) * 3;\n\n\t\t\t\t\tb >>>= (tree[tindex + 1]);\n\t\t\t\t\tk -= (tree[tindex + 1]);\n\n\t\t\t\t\te = tree[tindex];\n\n\t\t\t\t\tif (e === 0) { // literal\n\t\t\t\t\t\tlit = tree[tindex + 2];\n\t\t\t\t\t\tmode = LIT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif ((e & 16) !== 0) { // length\n\t\t\t\t\t\tget = e & 15;\n\t\t\t\t\t\tlen = tree[tindex + 2];\n\t\t\t\t\t\tmode = LENEXT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif ((e & 64) === 0) { // next table\n\t\t\t\t\t\tneed = e;\n\t\t\t\t\t\ttree_index = tindex / 3 + tree[tindex + 2];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif ((e & 32) !== 0) { // end of block\n\t\t\t\t\t\tmode = WASH;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tmode = BADCODE; // invalid code\n\t\t\t\t\tz.msg = \"invalid literal/length code\";\n\t\t\t\t\tr = Z_DATA_ERROR;\n\n\t\t\t\t\ts.bitb = b;\n\t\t\t\t\ts.bitk = k;\n\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\ts.write = q;\n\t\t\t\t\treturn s.inflate_flush(z, r);\n\n\t\t\t\tcase LENEXT: // i: getting length extra (have base)\n\t\t\t\t\tj = get;\n\n\t\t\t\t\twhile (k < (j)) {\n\t\t\t\t\t\tif (n !== 0)\n\t\t\t\t\t\t\tr = Z_OK;\n\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\ts.bitb = b;\n\t\t\t\t\t\t\ts.bitk = k;\n\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\ts.write = q;\n\t\t\t\t\t\t\treturn s.inflate_flush(z, r);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tn--;\n\t\t\t\t\t\tb |= (z.read_byte(p++) & 0xff) << k;\n\t\t\t\t\t\tk += 8;\n\t\t\t\t\t}\n\n\t\t\t\t\tlen += (b & inflate_mask[j]);\n\n\t\t\t\t\tb >>= j;\n\t\t\t\t\tk -= j;\n\n\t\t\t\t\tneed = dbits;\n\t\t\t\t\ttree = dtree;\n\t\t\t\t\ttree_index = dtree_index;\n\t\t\t\t\tmode = DIST;\n\t\t\t\tcase DIST: // i: get distance next\n\t\t\t\t\tj = need;\n\n\t\t\t\t\twhile (k < (j)) {\n\t\t\t\t\t\tif (n !== 0)\n\t\t\t\t\t\t\tr = Z_OK;\n\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\ts.bitb = b;\n\t\t\t\t\t\t\ts.bitk = k;\n\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\ts.write = q;\n\t\t\t\t\t\t\treturn s.inflate_flush(z, r);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tn--;\n\t\t\t\t\t\tb |= (z.read_byte(p++) & 0xff) << k;\n\t\t\t\t\t\tk += 8;\n\t\t\t\t\t}\n\n\t\t\t\t\ttindex = (tree_index + (b & inflate_mask[j])) * 3;\n\n\t\t\t\t\tb >>= tree[tindex + 1];\n\t\t\t\t\tk -= tree[tindex + 1];\n\n\t\t\t\t\te = (tree[tindex]);\n\t\t\t\t\tif ((e & 16) !== 0) { // distance\n\t\t\t\t\t\tget = e & 15;\n\t\t\t\t\t\tdist = tree[tindex + 2];\n\t\t\t\t\t\tmode = DISTEXT;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif ((e & 64) === 0) { // next table\n\t\t\t\t\t\tneed = e;\n\t\t\t\t\t\ttree_index = tindex / 3 + tree[tindex + 2];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tmode = BADCODE; // invalid code\n\t\t\t\t\tz.msg = \"invalid distance code\";\n\t\t\t\t\tr = Z_DATA_ERROR;\n\n\t\t\t\t\ts.bitb = b;\n\t\t\t\t\ts.bitk = k;\n\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\ts.write = q;\n\t\t\t\t\treturn s.inflate_flush(z, r);\n\n\t\t\t\tcase DISTEXT: // i: getting distance extra\n\t\t\t\t\tj = get;\n\n\t\t\t\t\twhile (k < (j)) {\n\t\t\t\t\t\tif (n !== 0)\n\t\t\t\t\t\t\tr = Z_OK;\n\t\t\t\t\t\telse {\n\n\t\t\t\t\t\t\ts.bitb = b;\n\t\t\t\t\t\t\ts.bitk = k;\n\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\ts.write = q;\n\t\t\t\t\t\t\treturn s.inflate_flush(z, r);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tn--;\n\t\t\t\t\t\tb |= (z.read_byte(p++) & 0xff) << k;\n\t\t\t\t\t\tk += 8;\n\t\t\t\t\t}\n\n\t\t\t\t\tdist += (b & inflate_mask[j]);\n\n\t\t\t\t\tb >>= j;\n\t\t\t\t\tk -= j;\n\n\t\t\t\t\tmode = COPY;\n\t\t\t\tcase COPY: // o: copying bytes in window, waiting for space\n\t\t\t\t\tf = q - dist;\n\t\t\t\t\twhile (f < 0) { // modulo window size-\"while\" instead\n\t\t\t\t\t\tf += s.end; // of \"if\" handles invalid distances\n\t\t\t\t\t}\n\t\t\t\t\twhile (len !== 0) {\n\n\t\t\t\t\t\tif (m === 0) {\n\t\t\t\t\t\t\tif (q == s.end && s.read !== 0) {\n\t\t\t\t\t\t\t\tq = 0;\n\t\t\t\t\t\t\t\tm = q < s.read ? s.read - q - 1 : s.end - q;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (m === 0) {\n\t\t\t\t\t\t\t\ts.write = q;\n\t\t\t\t\t\t\t\tr = s.inflate_flush(z, r);\n\t\t\t\t\t\t\t\tq = s.write;\n\t\t\t\t\t\t\t\tm = q < s.read ? s.read - q - 1 : s.end - q;\n\n\t\t\t\t\t\t\t\tif (q == s.end && s.read !== 0) {\n\t\t\t\t\t\t\t\t\tq = 0;\n\t\t\t\t\t\t\t\t\tm = q < s.read ? s.read - q - 1 : s.end - q;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (m === 0) {\n\t\t\t\t\t\t\t\t\ts.bitb = b;\n\t\t\t\t\t\t\t\t\ts.bitk = k;\n\t\t\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\t\t\ts.write = q;\n\t\t\t\t\t\t\t\t\treturn s.inflate_flush(z, r);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ts.window[q++] = s.window[f++];\n\t\t\t\t\t\tm--;\n\n\t\t\t\t\t\tif (f == s.end)\n\t\t\t\t\t\t\tf = 0;\n\t\t\t\t\t\tlen--;\n\t\t\t\t\t}\n\t\t\t\t\tmode = START;\n\t\t\t\t\tbreak;\n\t\t\t\tcase LIT: // o: got literal, waiting for output space\n\t\t\t\t\tif (m === 0) {\n\t\t\t\t\t\tif (q == s.end && s.read !== 0) {\n\t\t\t\t\t\t\tq = 0;\n\t\t\t\t\t\t\tm = q < s.read ? s.read - q - 1 : s.end - q;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (m === 0) {\n\t\t\t\t\t\t\ts.write = q;\n\t\t\t\t\t\t\tr = s.inflate_flush(z, r);\n\t\t\t\t\t\t\tq = s.write;\n\t\t\t\t\t\t\tm = q < s.read ? s.read - q - 1 : s.end - q;\n\n\t\t\t\t\t\t\tif (q == s.end && s.read !== 0) {\n\t\t\t\t\t\t\t\tq = 0;\n\t\t\t\t\t\t\t\tm = q < s.read ? s.read - q - 1 : s.end - q;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (m === 0) {\n\t\t\t\t\t\t\t\ts.bitb = b;\n\t\t\t\t\t\t\t\ts.bitk = k;\n\t\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\t\ts.write = q;\n\t\t\t\t\t\t\t\treturn s.inflate_flush(z, r);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tr = Z_OK;\n\n\t\t\t\t\ts.window[q++] = /* (byte) */lit;\n\t\t\t\t\tm--;\n\n\t\t\t\t\tmode = START;\n\t\t\t\t\tbreak;\n\t\t\t\tcase WASH: // o: got eob, possibly more output\n\t\t\t\t\tif (k > 7) { // return unused byte, if any\n\t\t\t\t\t\tk -= 8;\n\t\t\t\t\t\tn++;\n\t\t\t\t\t\tp--; // can always return one\n\t\t\t\t\t}\n\n\t\t\t\t\ts.write = q;\n\t\t\t\t\tr = s.inflate_flush(z, r);\n\t\t\t\t\tq = s.write;\n\t\t\t\t\tm = q < s.read ? s.read - q - 1 : s.end - q;\n\n\t\t\t\t\tif (s.read != s.write) {\n\t\t\t\t\t\ts.bitb = b;\n\t\t\t\t\t\ts.bitk = k;\n\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\ts.write = q;\n\t\t\t\t\t\treturn s.inflate_flush(z, r);\n\t\t\t\t\t}\n\t\t\t\t\tmode = END;\n\t\t\t\tcase END:\n\t\t\t\t\tr = Z_STREAM_END;\n\t\t\t\t\ts.bitb = b;\n\t\t\t\t\ts.bitk = k;\n\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\ts.write = q;\n\t\t\t\t\treturn s.inflate_flush(z, r);\n\n\t\t\t\tcase BADCODE: // x: got error\n\n\t\t\t\t\tr = Z_DATA_ERROR;\n\n\t\t\t\t\ts.bitb = b;\n\t\t\t\t\ts.bitk = k;\n\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\ts.write = q;\n\t\t\t\t\treturn s.inflate_flush(z, r);\n\n\t\t\t\tdefault:\n\t\t\t\t\tr = Z_STREAM_ERROR;\n\n\t\t\t\t\ts.bitb = b;\n\t\t\t\t\ts.bitk = k;\n\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\ts.write = q;\n\t\t\t\t\treturn s.inflate_flush(z, r);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tthat.free = function() {\n\t\t\t// ZFREE(z, c);\n\t\t};\n\n\t}\n\n\t// InfBlocks\n\n\t// Table for deflate from PKZIP's appnote.txt.\n\tvar border = [ // Order of the bit length code lengths\n\t16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];\n\n\tvar TYPE = 0; // get type bits (3, including end bit)\n\tvar LENS = 1; // get lengths for stored\n\tvar STORED = 2;// processing stored block\n\tvar TABLE = 3; // get table lengths\n\tvar BTREE = 4; // get bit lengths tree for a dynamic\n\t// block\n\tvar DTREE = 5; // get length, distance trees for a\n\t// dynamic block\n\tvar CODES = 6; // processing fixed or dynamic block\n\tvar DRY = 7; // output remaining window bytes\n\tvar DONELOCKS = 8; // finished last block, done\n\tvar BADBLOCKS = 9; // ot a data error--stuck here\n\n\tfunction InfBlocks(z, w) {\n\t\tvar that = this;\n\n\t\tvar mode = TYPE; // current inflate_block mode\n\n\t\tvar left = 0; // if STORED, bytes left to copy\n\n\t\tvar table = 0; // table lengths (14 bits)\n\t\tvar index = 0; // index into blens (or border)\n\t\tvar blens; // bit lengths of codes\n\t\tvar bb = [ 0 ]; // bit length tree depth\n\t\tvar tb = [ 0 ]; // bit length decoding tree\n\n\t\tvar codes = new InfCodes(); // if CODES, current state\n\n\t\tvar last = 0; // true if this block is the last block\n\n\t\tvar hufts = new Int32Array(MANY * 3); // single malloc for tree space\n\t\tvar check = 0; // check on output\n\t\tvar inftree = new InfTree();\n\n\t\tthat.bitk = 0; // bits in bit buffer\n\t\tthat.bitb = 0; // bit buffer\n\t\tthat.window = new Uint8Array(w); // sliding window\n\t\tthat.end = w; // one byte after sliding window\n\t\tthat.read = 0; // window read pointer\n\t\tthat.write = 0; // window write pointer\n\n\t\tthat.reset = function(z, c) {\n\t\t\tif (c)\n\t\t\t\tc[0] = check;\n\t\t\t// if (mode == BTREE || mode == DTREE) {\n\t\t\t// }\n\t\t\tif (mode == CODES) {\n\t\t\t\tcodes.free(z);\n\t\t\t}\n\t\t\tmode = TYPE;\n\t\t\tthat.bitk = 0;\n\t\t\tthat.bitb = 0;\n\t\t\tthat.read = that.write = 0;\n\t\t};\n\n\t\tthat.reset(z, null);\n\n\t\t// copy as much as possible from the sliding window to the output area\n\t\tthat.inflate_flush = function(z, r) {\n\t\t\tvar n;\n\t\t\tvar p;\n\t\t\tvar q;\n\n\t\t\t// local copies of source and destination pointers\n\t\t\tp = z.next_out_index;\n\t\t\tq = that.read;\n\n\t\t\t// compute number of bytes to copy as far as end of window\n\t\t\tn = /* (int) */((q <= that.write ? that.write : that.end) - q);\n\t\t\tif (n > z.avail_out)\n\t\t\t\tn = z.avail_out;\n\t\t\tif (n !== 0 && r == Z_BUF_ERROR)\n\t\t\t\tr = Z_OK;\n\n\t\t\t// update counters\n\t\t\tz.avail_out -= n;\n\t\t\tz.total_out += n;\n\n\t\t\t// copy as far as end of window\n\t\t\tz.next_out.set(that.window.subarray(q, q + n), p);\n\t\t\tp += n;\n\t\t\tq += n;\n\n\t\t\t// see if more to copy at beginning of window\n\t\t\tif (q == that.end) {\n\t\t\t\t// wrap pointers\n\t\t\t\tq = 0;\n\t\t\t\tif (that.write == that.end)\n\t\t\t\t\tthat.write = 0;\n\n\t\t\t\t// compute bytes to copy\n\t\t\t\tn = that.write - q;\n\t\t\t\tif (n > z.avail_out)\n\t\t\t\t\tn = z.avail_out;\n\t\t\t\tif (n !== 0 && r == Z_BUF_ERROR)\n\t\t\t\t\tr = Z_OK;\n\n\t\t\t\t// update counters\n\t\t\t\tz.avail_out -= n;\n\t\t\t\tz.total_out += n;\n\n\t\t\t\t// copy\n\t\t\t\tz.next_out.set(that.window.subarray(q, q + n), p);\n\t\t\t\tp += n;\n\t\t\t\tq += n;\n\t\t\t}\n\n\t\t\t// update pointers\n\t\t\tz.next_out_index = p;\n\t\t\tthat.read = q;\n\n\t\t\t// done\n\t\t\treturn r;\n\t\t};\n\n\t\tthat.proc = function(z, r) {\n\t\t\tvar t; // temporary storage\n\t\t\tvar b; // bit buffer\n\t\t\tvar k; // bits in bit buffer\n\t\t\tvar p; // input data pointer\n\t\t\tvar n; // bytes available there\n\t\t\tvar q; // output window write pointer\n\t\t\tvar m; // bytes to end of window or read pointer\n\n\t\t\tvar i;\n\n\t\t\t// copy input/output information to locals (UPDATE macro restores)\n\t\t\t// {\n\t\t\tp = z.next_in_index;\n\t\t\tn = z.avail_in;\n\t\t\tb = that.bitb;\n\t\t\tk = that.bitk;\n\t\t\t// }\n\t\t\t// {\n\t\t\tq = that.write;\n\t\t\tm = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);\n\t\t\t// }\n\n\t\t\t// process input based on current state\n\t\t\t// DEBUG dtree\n\t\t\twhile (true) {\n\t\t\t\tswitch (mode) {\n\t\t\t\tcase TYPE:\n\n\t\t\t\t\twhile (k < (3)) {\n\t\t\t\t\t\tif (n !== 0) {\n\t\t\t\t\t\t\tr = Z_OK;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tn--;\n\t\t\t\t\t\tb |= (z.read_byte(p++) & 0xff) << k;\n\t\t\t\t\t\tk += 8;\n\t\t\t\t\t}\n\t\t\t\t\tt = /* (int) */(b & 7);\n\t\t\t\t\tlast = t & 1;\n\n\t\t\t\t\tswitch (t >>> 1) {\n\t\t\t\t\tcase 0: // stored\n\t\t\t\t\t\t// {\n\t\t\t\t\t\tb >>>= (3);\n\t\t\t\t\t\tk -= (3);\n\t\t\t\t\t\t// }\n\t\t\t\t\t\tt = k & 7; // go to byte boundary\n\n\t\t\t\t\t\t// {\n\t\t\t\t\t\tb >>>= (t);\n\t\t\t\t\t\tk -= (t);\n\t\t\t\t\t\t// }\n\t\t\t\t\t\tmode = LENS; // get length of stored block\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1: // fixed\n\t\t\t\t\t\t// {\n\t\t\t\t\t\tvar bl = []; // new Array(1);\n\t\t\t\t\t\tvar bd = []; // new Array(1);\n\t\t\t\t\t\tvar tl = [ [] ]; // new Array(1);\n\t\t\t\t\t\tvar td = [ [] ]; // new Array(1);\n\n\t\t\t\t\t\tInfTree.inflate_trees_fixed(bl, bd, tl, td);\n\t\t\t\t\t\tcodes.init(bl[0], bd[0], tl[0], 0, td[0], 0);\n\t\t\t\t\t\t// }\n\n\t\t\t\t\t\t// {\n\t\t\t\t\t\tb >>>= (3);\n\t\t\t\t\t\tk -= (3);\n\t\t\t\t\t\t// }\n\n\t\t\t\t\t\tmode = CODES;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2: // dynamic\n\n\t\t\t\t\t\t// {\n\t\t\t\t\t\tb >>>= (3);\n\t\t\t\t\t\tk -= (3);\n\t\t\t\t\t\t// }\n\n\t\t\t\t\t\tmode = TABLE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3: // illegal\n\n\t\t\t\t\t\t// {\n\t\t\t\t\t\tb >>>= (3);\n\t\t\t\t\t\tk -= (3);\n\t\t\t\t\t\t// }\n\t\t\t\t\t\tmode = BADBLOCKS;\n\t\t\t\t\t\tz.msg = \"invalid block type\";\n\t\t\t\t\t\tr = Z_DATA_ERROR;\n\n\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase LENS:\n\n\t\t\t\t\twhile (k < (32)) {\n\t\t\t\t\t\tif (n !== 0) {\n\t\t\t\t\t\t\tr = Z_OK;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tn--;\n\t\t\t\t\t\tb |= (z.read_byte(p++) & 0xff) << k;\n\t\t\t\t\t\tk += 8;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ((((~b) >>> 16) & 0xffff) != (b & 0xffff)) {\n\t\t\t\t\t\tmode = BADBLOCKS;\n\t\t\t\t\t\tz.msg = \"invalid stored block lengths\";\n\t\t\t\t\t\tr = Z_DATA_ERROR;\n\n\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t}\n\t\t\t\t\tleft = (b & 0xffff);\n\t\t\t\t\tb = k = 0; // dump bits\n\t\t\t\t\tmode = left !== 0 ? STORED : (last !== 0 ? DRY : TYPE);\n\t\t\t\t\tbreak;\n\t\t\t\tcase STORED:\n\t\t\t\t\tif (n === 0) {\n\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (m === 0) {\n\t\t\t\t\t\tif (q == that.end && that.read !== 0) {\n\t\t\t\t\t\t\tq = 0;\n\t\t\t\t\t\t\tm = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (m === 0) {\n\t\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\t\tr = that.inflate_flush(z, r);\n\t\t\t\t\t\t\tq = that.write;\n\t\t\t\t\t\t\tm = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);\n\t\t\t\t\t\t\tif (q == that.end && that.read !== 0) {\n\t\t\t\t\t\t\t\tq = 0;\n\t\t\t\t\t\t\t\tm = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (m === 0) {\n\t\t\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tr = Z_OK;\n\n\t\t\t\t\tt = left;\n\t\t\t\t\tif (t > n)\n\t\t\t\t\t\tt = n;\n\t\t\t\t\tif (t > m)\n\t\t\t\t\t\tt = m;\n\t\t\t\t\tthat.window.set(z.read_buf(p, t), q);\n\t\t\t\t\tp += t;\n\t\t\t\t\tn -= t;\n\t\t\t\t\tq += t;\n\t\t\t\t\tm -= t;\n\t\t\t\t\tif ((left -= t) !== 0)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tmode = last !== 0 ? DRY : TYPE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase TABLE:\n\n\t\t\t\t\twhile (k < (14)) {\n\t\t\t\t\t\tif (n !== 0) {\n\t\t\t\t\t\t\tr = Z_OK;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tn--;\n\t\t\t\t\t\tb |= (z.read_byte(p++) & 0xff) << k;\n\t\t\t\t\t\tk += 8;\n\t\t\t\t\t}\n\n\t\t\t\t\ttable = t = (b & 0x3fff);\n\t\t\t\t\tif ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) {\n\t\t\t\t\t\tmode = BADBLOCKS;\n\t\t\t\t\t\tz.msg = \"too many length or distance symbols\";\n\t\t\t\t\t\tr = Z_DATA_ERROR;\n\n\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t}\n\t\t\t\t\tt = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);\n\t\t\t\t\tif (!blens || blens.length < t) {\n\t\t\t\t\t\tblens = []; // new Array(t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfor (i = 0; i < t; i++) {\n\t\t\t\t\t\t\tblens[i] = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// {\n\t\t\t\t\tb >>>= (14);\n\t\t\t\t\tk -= (14);\n\t\t\t\t\t// }\n\n\t\t\t\t\tindex = 0;\n\t\t\t\t\tmode = BTREE;\n\t\t\t\tcase BTREE:\n\t\t\t\t\twhile (index < 4 + (table >>> 10)) {\n\t\t\t\t\t\twhile (k < (3)) {\n\t\t\t\t\t\t\tif (n !== 0) {\n\t\t\t\t\t\t\t\tr = Z_OK;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tn--;\n\t\t\t\t\t\t\tb |= (z.read_byte(p++) & 0xff) << k;\n\t\t\t\t\t\t\tk += 8;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tblens[border[index++]] = b & 7;\n\n\t\t\t\t\t\t// {\n\t\t\t\t\t\tb >>>= (3);\n\t\t\t\t\t\tk -= (3);\n\t\t\t\t\t\t// }\n\t\t\t\t\t}\n\n\t\t\t\t\twhile (index < 19) {\n\t\t\t\t\t\tblens[border[index++]] = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tbb[0] = 7;\n\t\t\t\t\tt = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);\n\t\t\t\t\tif (t != Z_OK) {\n\t\t\t\t\t\tr = t;\n\t\t\t\t\t\tif (r == Z_DATA_ERROR) {\n\t\t\t\t\t\t\tblens = null;\n\t\t\t\t\t\t\tmode = BADBLOCKS;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t}\n\n\t\t\t\t\tindex = 0;\n\t\t\t\t\tmode = DTREE;\n\t\t\t\tcase DTREE:\n\t\t\t\t\twhile (true) {\n\t\t\t\t\t\tt = table;\n\t\t\t\t\t\tif (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar j, c;\n\n\t\t\t\t\t\tt = bb[0];\n\n\t\t\t\t\t\twhile (k < (t)) {\n\t\t\t\t\t\t\tif (n !== 0) {\n\t\t\t\t\t\t\t\tr = Z_OK;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tn--;\n\t\t\t\t\t\t\tb |= (z.read_byte(p++) & 0xff) << k;\n\t\t\t\t\t\t\tk += 8;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// if (tb[0] == -1) {\n\t\t\t\t\t\t// System.err.println(\"null...\");\n\t\t\t\t\t\t// }\n\n\t\t\t\t\t\tt = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];\n\t\t\t\t\t\tc = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];\n\n\t\t\t\t\t\tif (c < 16) {\n\t\t\t\t\t\t\tb >>>= (t);\n\t\t\t\t\t\t\tk -= (t);\n\t\t\t\t\t\t\tblens[index++] = c;\n\t\t\t\t\t\t} else { // c == 16..18\n\t\t\t\t\t\t\ti = c == 18 ? 7 : c - 14;\n\t\t\t\t\t\t\tj = c == 18 ? 11 : 3;\n\n\t\t\t\t\t\t\twhile (k < (t + i)) {\n\t\t\t\t\t\t\t\tif (n !== 0) {\n\t\t\t\t\t\t\t\t\tr = Z_OK;\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tn--;\n\t\t\t\t\t\t\t\tb |= (z.read_byte(p++) & 0xff) << k;\n\t\t\t\t\t\t\t\tk += 8;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tb >>>= (t);\n\t\t\t\t\t\t\tk -= (t);\n\n\t\t\t\t\t\t\tj += (b & inflate_mask[i]);\n\n\t\t\t\t\t\t\tb >>>= (i);\n\t\t\t\t\t\t\tk -= (i);\n\n\t\t\t\t\t\t\ti = index;\n\t\t\t\t\t\t\tt = table;\n\t\t\t\t\t\t\tif (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1)) {\n\t\t\t\t\t\t\t\tblens = null;\n\t\t\t\t\t\t\t\tmode = BADBLOCKS;\n\t\t\t\t\t\t\t\tz.msg = \"invalid bit length repeat\";\n\t\t\t\t\t\t\t\tr = Z_DATA_ERROR;\n\n\t\t\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tc = c == 16 ? blens[i - 1] : 0;\n\t\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\t\tblens[i++] = c;\n\t\t\t\t\t\t\t} while (--j !== 0);\n\t\t\t\t\t\t\tindex = i;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\ttb[0] = -1;\n\t\t\t\t\t// {\n\t\t\t\t\tvar bl_ = []; // new Array(1);\n\t\t\t\t\tvar bd_ = []; // new Array(1);\n\t\t\t\t\tvar tl_ = []; // new Array(1);\n\t\t\t\t\tvar td_ = []; // new Array(1);\n\t\t\t\t\tbl_[0] = 9; // must be <= 9 for lookahead assumptions\n\t\t\t\t\tbd_[0] = 6; // must be <= 9 for lookahead assumptions\n\n\t\t\t\t\tt = table;\n\t\t\t\t\tt = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl_, bd_, tl_, td_, hufts, z);\n\n\t\t\t\t\tif (t != Z_OK) {\n\t\t\t\t\t\tif (t == Z_DATA_ERROR) {\n\t\t\t\t\t\t\tblens = null;\n\t\t\t\t\t\t\tmode = BADBLOCKS;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tr = t;\n\n\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t}\n\t\t\t\t\tcodes.init(bl_[0], bd_[0], hufts, tl_[0], hufts, td_[0]);\n\t\t\t\t\t// }\n\t\t\t\t\tmode = CODES;\n\t\t\t\tcase CODES:\n\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\tthat.write = q;\n\n\t\t\t\t\tif ((r = codes.proc(that, z, r)) != Z_STREAM_END) {\n\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t}\n\t\t\t\t\tr = Z_OK;\n\t\t\t\t\tcodes.free(z);\n\n\t\t\t\t\tp = z.next_in_index;\n\t\t\t\t\tn = z.avail_in;\n\t\t\t\t\tb = that.bitb;\n\t\t\t\t\tk = that.bitk;\n\t\t\t\t\tq = that.write;\n\t\t\t\t\tm = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);\n\n\t\t\t\t\tif (last === 0) {\n\t\t\t\t\t\tmode = TYPE;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tmode = DRY;\n\t\t\t\tcase DRY:\n\t\t\t\t\tthat.write = q;\n\t\t\t\t\tr = that.inflate_flush(z, r);\n\t\t\t\t\tq = that.write;\n\t\t\t\t\tm = /* (int) */(q < that.read ? that.read - q - 1 : that.end - q);\n\t\t\t\t\tif (that.read != that.write) {\n\t\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\t\tthat.write = q;\n\t\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t\t}\n\t\t\t\t\tmode = DONELOCKS;\n\t\t\t\tcase DONELOCKS:\n\t\t\t\t\tr = Z_STREAM_END;\n\n\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\tthat.write = q;\n\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\tcase BADBLOCKS:\n\t\t\t\t\tr = Z_DATA_ERROR;\n\n\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\tthat.write = q;\n\t\t\t\t\treturn that.inflate_flush(z, r);\n\n\t\t\t\tdefault:\n\t\t\t\t\tr = Z_STREAM_ERROR;\n\n\t\t\t\t\tthat.bitb = b;\n\t\t\t\t\tthat.bitk = k;\n\t\t\t\t\tz.avail_in = n;\n\t\t\t\t\tz.total_in += p - z.next_in_index;\n\t\t\t\t\tz.next_in_index = p;\n\t\t\t\t\tthat.write = q;\n\t\t\t\t\treturn that.inflate_flush(z, r);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tthat.free = function(z) {\n\t\t\tthat.reset(z, null);\n\t\t\tthat.window = null;\n\t\t\thufts = null;\n\t\t\t// ZFREE(z, s);\n\t\t};\n\n\t\tthat.set_dictionary = function(d, start, n) {\n\t\t\tthat.window.set(d.subarray(start, start + n), 0);\n\t\t\tthat.read = that.write = n;\n\t\t};\n\n\t\t// Returns true if inflate is currently at the end of a block generated\n\t\t// by Z_SYNC_FLUSH or Z_FULL_FLUSH.\n\t\tthat.sync_point = function() {\n\t\t\treturn mode == LENS ? 1 : 0;\n\t\t};\n\n\t}\n\n\t// Inflate\n\n\t// preset dictionary flag in zlib header\n\tvar PRESET_DICT = 0x20;\n\n\tvar Z_DEFLATED = 8;\n\n\tvar METHOD = 0; // waiting for method byte\n\tvar FLAG = 1; // waiting for flag byte\n\tvar DICT4 = 2; // four dictionary check bytes to go\n\tvar DICT3 = 3; // three dictionary check bytes to go\n\tvar DICT2 = 4; // two dictionary check bytes to go\n\tvar DICT1 = 5; // one dictionary check byte to go\n\tvar DICT0 = 6; // waiting for inflateSetDictionary\n\tvar BLOCKS = 7; // decompressing blocks\n\tvar DONE = 12; // finished check, done\n\tvar BAD = 13; // got an error--stay here\n\n\tvar mark = [ 0, 0, 0xff, 0xff ];\n\n\tfunction Inflate() {\n\t\tvar that = this;\n\n\t\tthat.mode = 0; // current inflate mode\n\n\t\t// mode dependent information\n\t\tthat.method = 0; // if FLAGS, method byte\n\n\t\t// if CHECK, check values to compare\n\t\tthat.was = [ 0 ]; // new Array(1); // computed check value\n\t\tthat.need = 0; // stream check value\n\n\t\t// if BAD, inflateSync's marker bytes count\n\t\tthat.marker = 0;\n\n\t\t// mode independent information\n\t\tthat.wbits = 0; // log2(window size) (8..15, defaults to 15)\n\n\t\t// this.blocks; // current inflate_blocks state\n\n\t\tfunction inflateReset(z) {\n\t\t\tif (!z || !z.istate)\n\t\t\t\treturn Z_STREAM_ERROR;\n\n\t\t\tz.total_in = z.total_out = 0;\n\t\t\tz.msg = null;\n\t\t\tz.istate.mode = BLOCKS;\n\t\t\tz.istate.blocks.reset(z, null);\n\t\t\treturn Z_OK;\n\t\t}\n\n\t\tthat.inflateEnd = function(z) {\n\t\t\tif (that.blocks)\n\t\t\t\tthat.blocks.free(z);\n\t\t\tthat.blocks = null;\n\t\t\t// ZFREE(z, z->state);\n\t\t\treturn Z_OK;\n\t\t};\n\n\t\tthat.inflateInit = function(z, w) {\n\t\t\tz.msg = null;\n\t\t\tthat.blocks = null;\n\n\t\t\t// set window size\n\t\t\tif (w < 8 || w > 15) {\n\t\t\t\tthat.inflateEnd(z);\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\t}\n\t\t\tthat.wbits = w;\n\n\t\t\tz.istate.blocks = new InfBlocks(z, 1 << w);\n\n\t\t\t// reset state\n\t\t\tinflateReset(z);\n\t\t\treturn Z_OK;\n\t\t};\n\n\t\tthat.inflate = function(z, f) {\n\t\t\tvar r;\n\t\t\tvar b;\n\n\t\t\tif (!z || !z.istate || !z.next_in)\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\tf = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;\n\t\t\tr = Z_BUF_ERROR;\n\t\t\twhile (true) {\n\t\t\t\t// System.out.println(\"mode: \"+z.istate.mode);\n\t\t\t\tswitch (z.istate.mode) {\n\t\t\t\tcase METHOD:\n\n\t\t\t\t\tif (z.avail_in === 0)\n\t\t\t\t\t\treturn r;\n\t\t\t\t\tr = f;\n\n\t\t\t\t\tz.avail_in--;\n\t\t\t\t\tz.total_in++;\n\t\t\t\t\tif (((z.istate.method = z.read_byte(z.next_in_index++)) & 0xf) != Z_DEFLATED) {\n\t\t\t\t\t\tz.istate.mode = BAD;\n\t\t\t\t\t\tz.msg = \"unknown compression method\";\n\t\t\t\t\t\tz.istate.marker = 5; // can't try inflateSync\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif ((z.istate.method >> 4) + 8 > z.istate.wbits) {\n\t\t\t\t\t\tz.istate.mode = BAD;\n\t\t\t\t\t\tz.msg = \"invalid window size\";\n\t\t\t\t\t\tz.istate.marker = 5; // can't try inflateSync\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tz.istate.mode = FLAG;\n\t\t\t\tcase FLAG:\n\n\t\t\t\t\tif (z.avail_in === 0)\n\t\t\t\t\t\treturn r;\n\t\t\t\t\tr = f;\n\n\t\t\t\t\tz.avail_in--;\n\t\t\t\t\tz.total_in++;\n\t\t\t\t\tb = (z.read_byte(z.next_in_index++)) & 0xff;\n\n\t\t\t\t\tif ((((z.istate.method << 8) + b) % 31) !== 0) {\n\t\t\t\t\t\tz.istate.mode = BAD;\n\t\t\t\t\t\tz.msg = \"incorrect header check\";\n\t\t\t\t\t\tz.istate.marker = 5; // can't try inflateSync\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ((b & PRESET_DICT) === 0) {\n\t\t\t\t\t\tz.istate.mode = BLOCKS;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tz.istate.mode = DICT4;\n\t\t\t\tcase DICT4:\n\n\t\t\t\t\tif (z.avail_in === 0)\n\t\t\t\t\t\treturn r;\n\t\t\t\t\tr = f;\n\n\t\t\t\t\tz.avail_in--;\n\t\t\t\t\tz.total_in++;\n\t\t\t\t\tz.istate.need = ((z.read_byte(z.next_in_index++) & 0xff) << 24) & 0xff000000;\n\t\t\t\t\tz.istate.mode = DICT3;\n\t\t\t\tcase DICT3:\n\n\t\t\t\t\tif (z.avail_in === 0)\n\t\t\t\t\t\treturn r;\n\t\t\t\t\tr = f;\n\n\t\t\t\t\tz.avail_in--;\n\t\t\t\t\tz.total_in++;\n\t\t\t\t\tz.istate.need += ((z.read_byte(z.next_in_index++) & 0xff) << 16) & 0xff0000;\n\t\t\t\t\tz.istate.mode = DICT2;\n\t\t\t\tcase DICT2:\n\n\t\t\t\t\tif (z.avail_in === 0)\n\t\t\t\t\t\treturn r;\n\t\t\t\t\tr = f;\n\n\t\t\t\t\tz.avail_in--;\n\t\t\t\t\tz.total_in++;\n\t\t\t\t\tz.istate.need += ((z.read_byte(z.next_in_index++) & 0xff) << 8) & 0xff00;\n\t\t\t\t\tz.istate.mode = DICT1;\n\t\t\t\tcase DICT1:\n\n\t\t\t\t\tif (z.avail_in === 0)\n\t\t\t\t\t\treturn r;\n\t\t\t\t\tr = f;\n\n\t\t\t\t\tz.avail_in--;\n\t\t\t\t\tz.total_in++;\n\t\t\t\t\tz.istate.need += (z.read_byte(z.next_in_index++) & 0xff);\n\t\t\t\t\tz.istate.mode = DICT0;\n\t\t\t\t\treturn Z_NEED_DICT;\n\t\t\t\tcase DICT0:\n\t\t\t\t\tz.istate.mode = BAD;\n\t\t\t\t\tz.msg = \"need dictionary\";\n\t\t\t\t\tz.istate.marker = 0; // can try inflateSync\n\t\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\t\tcase BLOCKS:\n\n\t\t\t\t\tr = z.istate.blocks.proc(z, r);\n\t\t\t\t\tif (r == Z_DATA_ERROR) {\n\t\t\t\t\t\tz.istate.mode = BAD;\n\t\t\t\t\t\tz.istate.marker = 0; // can try inflateSync\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (r == Z_OK) {\n\t\t\t\t\t\tr = f;\n\t\t\t\t\t}\n\t\t\t\t\tif (r != Z_STREAM_END) {\n\t\t\t\t\t\treturn r;\n\t\t\t\t\t}\n\t\t\t\t\tr = f;\n\t\t\t\t\tz.istate.blocks.reset(z, z.istate.was);\n\t\t\t\t\tz.istate.mode = DONE;\n\t\t\t\tcase DONE:\n\t\t\t\t\treturn Z_STREAM_END;\n\t\t\t\tcase BAD:\n\t\t\t\t\treturn Z_DATA_ERROR;\n\t\t\t\tdefault:\n\t\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tthat.inflateSetDictionary = function(z, dictionary, dictLength) {\n\t\t\tvar index = 0;\n\t\t\tvar length = dictLength;\n\t\t\tif (!z || !z.istate || z.istate.mode != DICT0)\n\t\t\t\treturn Z_STREAM_ERROR;\n\n\t\t\tif (length >= (1 << z.istate.wbits)) {\n\t\t\t\tlength = (1 << z.istate.wbits) - 1;\n\t\t\t\tindex = dictLength - length;\n\t\t\t}\n\t\t\tz.istate.blocks.set_dictionary(dictionary, index, length);\n\t\t\tz.istate.mode = BLOCKS;\n\t\t\treturn Z_OK;\n\t\t};\n\n\t\tthat.inflateSync = function(z) {\n\t\t\tvar n; // number of bytes to look at\n\t\t\tvar p; // pointer to bytes\n\t\t\tvar m; // number of marker bytes found in a row\n\t\t\tvar r, w; // temporaries to save total_in and total_out\n\n\t\t\t// set up\n\t\t\tif (!z || !z.istate)\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\tif (z.istate.mode != BAD) {\n\t\t\t\tz.istate.mode = BAD;\n\t\t\t\tz.istate.marker = 0;\n\t\t\t}\n\t\t\tif ((n = z.avail_in) === 0)\n\t\t\t\treturn Z_BUF_ERROR;\n\t\t\tp = z.next_in_index;\n\t\t\tm = z.istate.marker;\n\n\t\t\t// search\n\t\t\twhile (n !== 0 && m < 4) {\n\t\t\t\tif (z.read_byte(p) == mark[m]) {\n\t\t\t\t\tm++;\n\t\t\t\t} else if (z.read_byte(p) !== 0) {\n\t\t\t\t\tm = 0;\n\t\t\t\t} else {\n\t\t\t\t\tm = 4 - m;\n\t\t\t\t}\n\t\t\t\tp++;\n\t\t\t\tn--;\n\t\t\t}\n\n\t\t\t// restore\n\t\t\tz.total_in += p - z.next_in_index;\n\t\t\tz.next_in_index = p;\n\t\t\tz.avail_in = n;\n\t\t\tz.istate.marker = m;\n\n\t\t\t// return no joy or set up to restart on a new block\n\t\t\tif (m != 4) {\n\t\t\t\treturn Z_DATA_ERROR;\n\t\t\t}\n\t\t\tr = z.total_in;\n\t\t\tw = z.total_out;\n\t\t\tinflateReset(z);\n\t\t\tz.total_in = r;\n\t\t\tz.total_out = w;\n\t\t\tz.istate.mode = BLOCKS;\n\t\t\treturn Z_OK;\n\t\t};\n\n\t\t// Returns true if inflate is currently at the end of a block generated\n\t\t// by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP\n\t\t// implementation to provide an additional safety check. PPP uses\n\t\t// Z_SYNC_FLUSH\n\t\t// but removes the length bytes of the resulting empty stored block. When\n\t\t// decompressing, PPP checks that at the end of input packet, inflate is\n\t\t// waiting for these length bytes.\n\t\tthat.inflateSyncPoint = function(z) {\n\t\t\tif (!z || !z.istate || !z.istate.blocks)\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\treturn z.istate.blocks.sync_point();\n\t\t};\n\t}\n\n\t// ZStream\n\n\tfunction ZStream() {\n\t}\n\n\tZStream.prototype = {\n\t\tinflateInit : function(bits) {\n\t\t\tvar that = this;\n\t\t\tthat.istate = new Inflate();\n\t\t\tif (!bits)\n\t\t\t\tbits = MAX_BITS;\n\t\t\treturn that.istate.inflateInit(that, bits);\n\t\t},\n\n\t\tinflate : function(f) {\n\t\t\tvar that = this;\n\t\t\tif (!that.istate)\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\treturn that.istate.inflate(that, f);\n\t\t},\n\n\t\tinflateEnd : function() {\n\t\t\tvar that = this;\n\t\t\tif (!that.istate)\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\tvar ret = that.istate.inflateEnd(that);\n\t\t\tthat.istate = null;\n\t\t\treturn ret;\n\t\t},\n\n\t\tinflateSync : function() {\n\t\t\tvar that = this;\n\t\t\tif (!that.istate)\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\treturn that.istate.inflateSync(that);\n\t\t},\n\t\tinflateSetDictionary : function(dictionary, dictLength) {\n\t\t\tvar that = this;\n\t\t\tif (!that.istate)\n\t\t\t\treturn Z_STREAM_ERROR;\n\t\t\treturn that.istate.inflateSetDictionary(that, dictionary, dictLength);\n\t\t},\n\t\tread_byte : function(start) {\n\t\t\tvar that = this;\n\t\t\treturn that.next_in.subarray(start, start + 1)[0];\n\t\t},\n\t\tread_buf : function(start, size) {\n\t\t\tvar that = this;\n\t\t\treturn that.next_in.subarray(start, start + size);\n\t\t}\n\t};\n\n\t// Inflater\n\n\tfunction Inflater() {\n\t\tvar that = this;\n\t\tvar z = new ZStream();\n\t\tvar bufsize = 512;\n\t\tvar flush = Z_NO_FLUSH;\n\t\tvar buf = new Uint8Array(bufsize);\n\t\tvar nomoreinput = false;\n\n\t\tz.inflateInit();\n\t\tz.next_out = buf;\n\n\t\tthat.append = function(data, onprogress) {\n\t\t\tvar err, buffers = [], lastIndex = 0, bufferIndex = 0, bufferSize = 0, array;\n\t\t\tif (data.length === 0)\n\t\t\t\treturn;\n\t\t\tz.next_in_index = 0;\n\t\t\tz.next_in = data;\n\t\t\tz.avail_in = data.length;\n\t\t\tdo {\n\t\t\t\tz.next_out_index = 0;\n\t\t\t\tz.avail_out = bufsize;\n\t\t\t\tif ((z.avail_in === 0) && (!nomoreinput)) { // if buffer is empty and more input is available, refill it\n\t\t\t\t\tz.next_in_index = 0;\n\t\t\t\t\tnomoreinput = true;\n\t\t\t\t}\n\t\t\t\terr = z.inflate(flush);\n\t\t\t\tif (nomoreinput && (err == Z_BUF_ERROR))\n\t\t\t\t\treturn -1;\n\t\t\t\tif (err != Z_OK && err != Z_STREAM_END)\n\t\t\t\t\tthrow \"inflating: \" + z.msg;\n\t\t\t\tif ((nomoreinput || err == Z_STREAM_END) && (z.avail_in == data.length))\n\t\t\t\t\treturn -1;\n\t\t\t\tif (z.next_out_index)\n\t\t\t\t\tif (z.next_out_index == bufsize)\n\t\t\t\t\t\tbuffers.push(new Uint8Array(buf));\n\t\t\t\t\telse\n\t\t\t\t\t\tbuffers.push(new Uint8Array(buf.subarray(0, z.next_out_index)));\n\t\t\t\tbufferSize += z.next_out_index;\n\t\t\t\tif (onprogress && z.next_in_index > 0 && z.next_in_index != lastIndex) {\n\t\t\t\t\tonprogress(z.next_in_index);\n\t\t\t\t\tlastIndex = z.next_in_index;\n\t\t\t\t}\n\t\t\t} while (z.avail_in > 0 || z.avail_out === 0);\n\t\t\tarray = new Uint8Array(bufferSize);\n\t\t\tbuffers.forEach(function(chunk) {\n\t\t\t\tarray.set(chunk, bufferIndex);\n\t\t\t\tbufferIndex += chunk.length;\n\t\t\t});\n\t\t\treturn array;\n\t\t};\n\t\tthat.flush = function() {\n\t\t\tz.inflateEnd();\n\t\t};\n\t}\n\n\tvar inflater;\n\n\tif (obj.zip)\n\t\tobj.zip.Inflater = Inflater;\n\telse {\n\t\tinflater = new Inflater();\n\t\tobj.addEventListener(\"message\", function(event) {\n\t\t\tvar message = event.data;\n\n\t\t\tif (message.append)\n\t\t\t\tobj.postMessage({\n\t\t\t\t\tonappend : true,\n\t\t\t\t\tdata : inflater.append(message.data, function(current) {\n\t\t\t\t\t\tobj.postMessage({\n\t\t\t\t\t\t\tprogress : true,\n\t\t\t\t\t\t\tcurrent : current\n\t\t\t\t\t\t});\n\t\t\t\t\t})\n\t\t\t\t});\n\t\t\tif (message.flush) {\n\t\t\t\tinflater.flush();\n\t\t\t\tobj.postMessage({\n\t\t\t\t\tonflush : true\n\t\t\t\t});\n\t\t\t}\n\t\t}, false);\n\t}\n\n})(this);\n"
  },
  {
    "path": "_archive/apps/samples/web-store/js/zip/zip.js",
    "content": "/*\n Copyright (c) 2012 Gildas Lormeau. All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n\n 1. Redistributions of source code must retain the above copyright notice,\n this list of conditions and the following disclaimer.\n\n 2. Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the distribution.\n\n 3. The names of the authors may not be used to endorse or promote products\n derived from this software without specific prior written permission.\n\n THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\n INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\n FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\n INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\n INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\n OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n(function(obj) {\n\n\tvar ERR_BAD_FORMAT = \"File format is not recognized.\";\n\tvar ERR_ENCRYPTED = \"File contains encrypted entry.\";\n\tvar ERR_ZIP64 = \"File is using Zip64 (4gb+ file size).\";\n\tvar ERR_READ = \"Error while reading zip file.\";\n\tvar ERR_WRITE = \"Error while writing zip file.\";\n\tvar ERR_WRITE_DATA = \"Error while writing file data.\";\n\tvar ERR_READ_DATA = \"Error while reading file data.\";\n\tvar ERR_DUPLICATED_NAME = \"File already exists.\";\n\tvar ERR_HTTP_RANGE = \"HTTP Range not supported.\";\n\tvar CHUNK_SIZE = 512 * 1024;\n\n\tvar INFLATE_JS = \"inflate.js\";\n\tvar DEFLATE_JS = \"deflate.js\";\n\n\tvar appendABViewSupported;\n\ttry {\n\t\tappendABViewSupported = new Blob([ getDataHelper(0).view ]).size == 0;\n\t} catch (e) {\n\t}\t\n\n\tfunction Crc32() {\n\t\tvar crc = -1, that = this;\n\t\tthat.append = function(data) {\n\t\t\tvar offset, table = that.table;\n\t\t\tfor (offset = 0; offset < data.length; offset++)\n\t\t\t\tcrc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xFF];\n\t\t};\n\t\tthat.get = function() {\n\t\t\treturn ~crc;\n\t\t};\n\t}\n\tCrc32.prototype.table = (function() {\n\t\tvar i, j, t, table = [];\n\t\tfor (i = 0; i < 256; i++) {\n\t\t\tt = i;\n\t\t\tfor (j = 0; j < 8; j++)\n\t\t\t\tif (t & 1)\n\t\t\t\t\tt = (t >>> 1) ^ 0xEDB88320;\n\t\t\t\telse\n\t\t\t\t\tt = t >>> 1;\n\t\t\ttable[i] = t;\n\t\t}\n\t\treturn table;\n\t})();\n\n\tfunction blobSlice(blob, index, length) {\n\t\tif (blob.slice)\n\t\t\treturn blob.slice(index, index + length);\n\t\telse if (blob.webkitSlice)\n\t\t\treturn blob.webkitSlice(index, index + length);\n\t\telse if (blob.mozSlice)\n\t\t\treturn blob.mozSlice(index, index + length);\n\t\telse if (blob.msSlice)\n\t\t\treturn blob.msSlice(index, index + length);\n\t}\n\n\tfunction getDataHelper(byteLength, bytes) {\n\t\tvar dataBuffer, dataArray;\n\t\tdataBuffer = new ArrayBuffer(byteLength);\n\t\tdataArray = new Uint8Array(dataBuffer);\n\t\tif (bytes)\n\t\t\tdataArray.set(bytes, 0);\n\t\treturn {\n\t\t\tbuffer : dataBuffer,\n\t\t\tarray : dataArray,\n\t\t\tview : new DataView(dataBuffer)\n\t\t};\n\t}\n\n\t// Readers\n\tfunction Reader() {\n\t}\n\n\tfunction TextReader(text) {\n\t\tvar that = this, blobReader;\n\n\t\tfunction init(callback, onerror) {\n\t\t\tvar blob = new Blob([ text ], {\n\t\t\t\ttype : \"text/plain\"\n\t\t\t});\n\t\t\tblobReader = new BlobReader(blob);\n\t\t\tblobReader.init(function() {\n\t\t\t\tthat.size = blobReader.size;\n\t\t\t\tcallback();\n\t\t\t}, onerror);\n\t\t}\n\n\t\tfunction readUint8Array(index, length, callback, onerror) {\n\t\t\tblobReader.readUint8Array(index, length, callback, onerror);\n\t\t}\n\n\t\tthat.size = 0;\n\t\tthat.init = init;\n\t\tthat.readUint8Array = readUint8Array;\n\t}\n\tTextReader.prototype = new Reader();\n\tTextReader.prototype.constructor = TextReader;\n\n\tfunction Data64URIReader(dataURI) {\n\t\tvar that = this, dataStart;\n\n\t\tfunction init(callback) {\n\t\t\tvar dataEnd = dataURI.length;\n\t\t\twhile (dataURI.charAt(dataEnd - 1) == \"=\")\n\t\t\t\tdataEnd--;\n\t\t\tdataStart = dataURI.indexOf(\",\") + 1;\n\t\t\tthat.size = Math.floor((dataEnd - dataStart) * 0.75);\n\t\t\tcallback();\n\t\t}\n\n\t\tfunction readUint8Array(index, length, callback) {\n\t\t\tvar i, data = getDataHelper(length);\n\t\t\tvar start = Math.floor(index / 3) * 4;\n\t\t\tvar end = Math.ceil((index + length) / 3) * 4;\n\t\t\tvar bytes = obj.atob(dataURI.substring(start + dataStart, end + dataStart));\n\t\t\tvar delta = index - Math.floor(start / 4) * 3;\n\t\t\tfor (i = delta; i < delta + length; i++)\n\t\t\t\tdata.array[i - delta] = bytes.charCodeAt(i);\n\t\t\tcallback(data.array);\n\t\t}\n\n\t\tthat.size = 0;\n\t\tthat.init = init;\n\t\tthat.readUint8Array = readUint8Array;\n\t}\n\tData64URIReader.prototype = new Reader();\n\tData64URIReader.prototype.constructor = Data64URIReader;\n\n\tfunction BlobReader(blob) {\n\t\tvar that = this;\n\n\t\tfunction init(callback) {\n\t\t\tthis.size = blob.size;\n\t\t\tcallback();\n\t\t}\n\n\t\tfunction readUint8Array(index, length, callback, onerror) {\n\t\t\tvar reader = new FileReader();\n\t\t\treader.onload = function(e) {\n\t\t\t\tcallback(new Uint8Array(e.target.result));\n\t\t\t};\n\t\t\treader.onerror = onerror;\n\t\t\treader.readAsArrayBuffer(blobSlice(blob, index, length));\n\t\t}\n\n\t\tthat.size = 0;\n\t\tthat.init = init;\n\t\tthat.readUint8Array = readUint8Array;\n\t}\n\tBlobReader.prototype = new Reader();\n\tBlobReader.prototype.constructor = BlobReader;\n\n\tfunction HttpReader(url) {\n\t\tvar that = this;\n\n\t\tfunction getData(callback, onerror) {\n\t\t\tvar request;\n\t\t\tif (!that.data) {\n\t\t\t\trequest = new XMLHttpRequest();\n\t\t\t\trequest.addEventListener(\"load\", function() {\n\t\t\t\t\tif (!that.size)\n\t\t\t\t\t\tthat.size = Number(request.getResponseHeader(\"Content-Length\"));\n\t\t\t\t\tthat.data = new Uint8Array(request.response);\n\t\t\t\t\tcallback();\n\t\t\t\t}, false);\n\t\t\t\trequest.addEventListener(\"error\", onerror, false);\n\t\t\t\trequest.open(\"GET\", url);\n\t\t\t\trequest.responseType = \"arraybuffer\";\n\t\t\t\trequest.send();\n\t\t\t} else\n\t\t\t\tcallback();\n\t\t}\n\n\t\tfunction init(callback, onerror) {\n\t\t\tvar request = new XMLHttpRequest();\n\t\t\trequest.addEventListener(\"load\", function() {\n\t\t\t\tthat.size = Number(request.getResponseHeader(\"Content-Length\"));\n\t\t\t\tcallback();\n\t\t\t}, false);\n\t\t\trequest.addEventListener(\"error\", onerror, false);\n\t\t\trequest.open(\"HEAD\", url);\n\t\t\trequest.send();\n\t\t}\n\n\t\tfunction readUint8Array(index, length, callback, onerror) {\n\t\t\tgetData(function() {\n\t\t\t\tcallback(new Uint8Array(that.data.subarray(index, index + length)));\n\t\t\t}, onerror);\n\t\t}\n\n\t\tthat.size = 0;\n\t\tthat.init = init;\n\t\tthat.readUint8Array = readUint8Array;\n\t}\n\tHttpReader.prototype = new Reader();\n\tHttpReader.prototype.constructor = HttpReader;\n\n\tfunction HttpRangeReader(url) {\n\t\tvar that = this;\n\n\t\tfunction init(callback, onerror) {\n\t\t\tvar request = new XMLHttpRequest();\n\t\t\trequest.addEventListener(\"load\", function() {\n\t\t\t\tthat.size = Number(request.getResponseHeader(\"Content-Length\"));\n\t\t\t\tif (request.getResponseHeader(\"Accept-Ranges\") == \"bytes\")\n\t\t\t\t\tcallback();\n\t\t\t\telse\n\t\t\t\t\tonerror(ERR_HTTP_RANGE);\n\t\t\t}, false);\n\t\t\trequest.addEventListener(\"error\", onerror, false);\n\t\t\trequest.open(\"HEAD\", url);\n\t\t\trequest.send();\n\t\t}\n\n\t\tfunction readArrayBuffer(index, length, callback, onerror) {\n\t\t\tvar request = new XMLHttpRequest();\n\t\t\trequest.open(\"GET\", url);\n\t\t\trequest.responseType = \"arraybuffer\";\n\t\t\trequest.setRequestHeader(\"Range\", \"bytes=\" + index + \"-\" + (index + length - 1));\n\t\t\trequest.addEventListener(\"load\", function() {\n\t\t\t\tcallback(request.response);\n\t\t\t}, false);\n\t\t\trequest.addEventListener(\"error\", onerror, false);\n\t\t\trequest.send();\n\t\t}\n\n\t\tfunction readUint8Array(index, length, callback, onerror) {\n\t\t\treadArrayBuffer(index, length, function(arraybuffer) {\n\t\t\t\tcallback(new Uint8Array(arraybuffer));\n\t\t\t}, onerror);\n\t\t}\n\n\t\tthat.size = 0;\n\t\tthat.init = init;\n\t\tthat.readUint8Array = readUint8Array;\n\t}\n\tHttpRangeReader.prototype = new Reader();\n\tHttpRangeReader.prototype.constructor = HttpRangeReader;\n\n\t// Writers\n\n\tfunction Writer() {\n\t}\n\tWriter.prototype.getData = function(callback) {\n\t\tcallback(this.data);\n\t};\n\n\tfunction TextWriter() {\n\t\tvar that = this, blob;\n\n\t\tfunction init(callback) {\n\t\t\tblob = new Blob([], {\n\t\t\t\ttype : \"text/plain\"\n\t\t\t});\n\t\t\tcallback();\n\t\t}\n\n\t\tfunction writeUint8Array(array, callback) {\n\t\t\tblob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {\n\t\t\t\ttype : \"text/plain\"\n\t\t\t});\n\t\t\tcallback();\n\t\t}\n\n\t\tfunction getData(callback, onerror) {\n\t\t\tvar reader = new FileReader();\n\t\t\treader.onload = function(e) {\n\t\t\t\tcallback(e.target.result);\n\t\t\t};\n\t\t\treader.onerror = onerror;\n\t\t\treader.readAsText(blob);\n\t\t}\n\n\t\tthat.init = init;\n\t\tthat.writeUint8Array = writeUint8Array;\n\t\tthat.getData = getData;\n\t}\n\tTextWriter.prototype = new Writer();\n\tTextWriter.prototype.constructor = TextWriter;\n\n\tfunction Data64URIWriter(contentType) {\n\t\tvar that = this, data = \"\", pending = \"\";\n\n\t\tfunction init(callback) {\n\t\t\tdata += \"data:\" + (contentType || \"\") + \";base64,\";\n\t\t\tcallback();\n\t\t}\n\n\t\tfunction writeUint8Array(array, callback) {\n\t\t\tvar i, delta = pending.length, dataString = pending;\n\t\t\tpending = \"\";\n\t\t\tfor (i = 0; i < (Math.floor((delta + array.length) / 3) * 3) - delta; i++)\n\t\t\t\tdataString += String.fromCharCode(array[i]);\n\t\t\tfor (; i < array.length; i++)\n\t\t\t\tpending += String.fromCharCode(array[i]);\n\t\t\tif (dataString.length > 2)\n\t\t\t\tdata += obj.btoa(dataString);\n\t\t\telse\n\t\t\t\tpending = dataString;\n\t\t\tcallback();\n\t\t}\n\n\t\tfunction getData(callback) {\n\t\t\tcallback(data + obj.btoa(pending));\n\t\t}\n\n\t\tthat.init = init;\n\t\tthat.writeUint8Array = writeUint8Array;\n\t\tthat.getData = getData;\n\t}\n\tData64URIWriter.prototype = new Writer();\n\tData64URIWriter.prototype.constructor = Data64URIWriter;\n\n\tfunction FileWriter(fileEntry, contentType) {\n\t\tvar writer, that = this;\n\n\t\tfunction init(callback, onerror) {\n\t\t\tfileEntry.createWriter(function(fileWriter) {\n\t\t\t\twriter = fileWriter;\n\t\t\t\tcallback();\n\t\t\t}, onerror);\n\t\t}\n\n\t\tfunction writeUint8Array(array, callback, onerror) {\n\t\t\tvar blob = new Blob([ appendABViewSupported ? array : array.buffer ], {\n\t\t\t\ttype : contentType\n\t\t\t});\n\t\t\twriter.onwrite = function() {\n\t\t\t\twriter.onwrite = null;\n\t\t\t\tcallback();\n\t\t\t};\n\t\t\twriter.onerror = onerror;\n\t\t\twriter.write(blob);\n\t\t}\n\n\t\tfunction getData(callback) {\n\t\t\tfileEntry.file(callback);\n\t\t}\n\n\t\tthat.init = init;\n\t\tthat.writeUint8Array = writeUint8Array;\n\t\tthat.getData = getData;\n\t}\n\tFileWriter.prototype = new Writer();\n\tFileWriter.prototype.constructor = FileWriter;\n\n\tfunction BlobWriter(contentType) {\n\t\tvar blob, that = this;\n\n\t\tfunction init(callback) {\n\t\t\tblob = new Blob([], {\n\t\t\t\ttype : contentType\n\t\t\t});\n\t\t\tcallback();\n\t\t}\n\n\t\tfunction writeUint8Array(array, callback) {\n\t\t\tblob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {\n\t\t\t\ttype : contentType\n\t\t\t});\n\t\t\tcallback();\n\t\t}\n\n\t\tfunction getData(callback) {\n\t\t\tcallback(blob);\n\t\t}\n\n\t\tthat.init = init;\n\t\tthat.writeUint8Array = writeUint8Array;\n\t\tthat.getData = getData;\n\t}\n\tBlobWriter.prototype = new Writer();\n\tBlobWriter.prototype.constructor = BlobWriter;\n\n\t// inflate/deflate core functions\n\n\tfunction launchWorkerProcess(worker, reader, writer, offset, size, onappend, onprogress, onend, onreaderror, onwriteerror) {\n\t\tvar chunkIndex = 0, index, outputSize;\n\n\t\tfunction onflush() {\n\t\t\tworker.removeEventListener(\"message\", onmessage, false);\n\t\t\tonend(outputSize);\n\t\t}\n\n\t\tfunction onmessage(event) {\n\t\t\tvar message = event.data, data = message.data;\n\n\t\t\tif (message.onappend) {\n\t\t\t\toutputSize += data.length;\n\t\t\t\twriter.writeUint8Array(data, function() {\n\t\t\t\t\tonappend(false, data);\n\t\t\t\t\tstep();\n\t\t\t\t}, onwriteerror);\n\t\t\t}\n\t\t\tif (message.onflush)\n\t\t\t\tif (data) {\n\t\t\t\t\toutputSize += data.length;\n\t\t\t\t\twriter.writeUint8Array(data, function() {\n\t\t\t\t\t\tonappend(false, data);\n\t\t\t\t\t\tonflush();\n\t\t\t\t\t}, onwriteerror);\n\t\t\t\t} else\n\t\t\t\t\tonflush();\n\t\t\tif (message.progress && onprogress)\n\t\t\t\tonprogress(index + message.current, size);\n\t\t}\n\n\t\tfunction step() {\n\t\t\tindex = chunkIndex * CHUNK_SIZE;\n\t\t\tif (index < size)\n\t\t\t\treader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(array) {\n\t\t\t\t\tworker.postMessage({\n\t\t\t\t\t\tappend : true,\n\t\t\t\t\t\tdata : array\n\t\t\t\t\t});\n\t\t\t\t\tchunkIndex++;\n\t\t\t\t\tif (onprogress)\n\t\t\t\t\t\tonprogress(index, size);\n\t\t\t\t\tonappend(true, array);\n\t\t\t\t}, onreaderror);\n\t\t\telse\n\t\t\t\tworker.postMessage({\n\t\t\t\t\tflush : true\n\t\t\t\t});\n\t\t}\n\n\t\toutputSize = 0;\n\t\tworker.addEventListener(\"message\", onmessage, false);\n\t\tstep();\n\t}\n\n\tfunction launchProcess(process, reader, writer, offset, size, onappend, onprogress, onend, onreaderror, onwriteerror) {\n\t\tvar chunkIndex = 0, index, outputSize = 0;\n\n\t\tfunction step() {\n\t\t\tvar outputData;\n\t\t\tindex = chunkIndex * CHUNK_SIZE;\n\t\t\tif (index < size)\n\t\t\t\treader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(inputData) {\n\t\t\t\t\tvar outputData = process.append(inputData, function() {\n\t\t\t\t\t\tif (onprogress)\n\t\t\t\t\t\t\tonprogress(offset + index, size);\n\t\t\t\t\t});\n\t\t\t\t\toutputSize += outputData.length;\n\t\t\t\t\tonappend(true, inputData);\n\t\t\t\t\twriter.writeUint8Array(outputData, function() {\n\t\t\t\t\t\tonappend(false, outputData);\n\t\t\t\t\t\tchunkIndex++;\n\t\t\t\t\t\tsetTimeout(step, 1);\n\t\t\t\t\t}, onwriteerror);\n\t\t\t\t\tif (onprogress)\n\t\t\t\t\t\tonprogress(index, size);\n\t\t\t\t}, onreaderror);\n\t\t\telse {\n\t\t\t\toutputData = process.flush();\n\t\t\t\tif (outputData) {\n\t\t\t\t\toutputSize += outputData.length;\n\t\t\t\t\twriter.writeUint8Array(outputData, function() {\n\t\t\t\t\t\tonappend(false, outputData);\n\t\t\t\t\t\tonend(outputSize);\n\t\t\t\t\t}, onwriteerror);\n\t\t\t\t} else\n\t\t\t\t\tonend(outputSize);\n\t\t\t}\n\t\t}\n\n\t\tstep();\n\t}\n\n\tfunction inflate(reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {\n\t\tvar worker, crc32 = new Crc32();\n\n\t\tfunction oninflateappend(sending, array) {\n\t\t\tif (computeCrc32 && !sending)\n\t\t\t\tcrc32.append(array);\n\t\t}\n\n\t\tfunction oninflateend(outputSize) {\n\t\t\tonend(outputSize, crc32.get());\n\t\t}\n\n\t\tif (obj.zip.useWebWorkers) {\n\t\t\tworker = new Worker(obj.zip.workerScriptsPath + INFLATE_JS);\n\t\t\tlaunchWorkerProcess(worker, reader, writer, offset, size, oninflateappend, onprogress, oninflateend, onreaderror, onwriteerror);\n\t\t} else\n\t\t\tlaunchProcess(new obj.zip.Inflater(), reader, writer, offset, size, oninflateappend, onprogress, oninflateend, onreaderror, onwriteerror);\n\t\treturn worker;\n\t}\n\n\tfunction deflate(reader, writer, level, onend, onprogress, onreaderror, onwriteerror) {\n\t\tvar worker, crc32 = new Crc32();\n\n\t\tfunction ondeflateappend(sending, array) {\n\t\t\tif (sending)\n\t\t\t\tcrc32.append(array);\n\t\t}\n\n\t\tfunction ondeflateend(outputSize) {\n\t\t\tonend(outputSize, crc32.get());\n\t\t}\n\n\t\tfunction onmessage() {\n\t\t\tworker.removeEventListener(\"message\", onmessage, false);\n\t\t\tlaunchWorkerProcess(worker, reader, writer, 0, reader.size, ondeflateappend, onprogress, ondeflateend, onreaderror, onwriteerror);\n\t\t}\n\n\t\tif (obj.zip.useWebWorkers) {\n\t\t\tworker = new Worker(obj.zip.workerScriptsPath + DEFLATE_JS);\n\t\t\tworker.addEventListener(\"message\", onmessage, false);\n\t\t\tworker.postMessage({\n\t\t\t\tinit : true,\n\t\t\t\tlevel : level\n\t\t\t});\n\t\t} else\n\t\t\tlaunchProcess(new obj.zip.Deflater(), reader, writer, 0, reader.size, ondeflateappend, onprogress, ondeflateend, onreaderror, onwriteerror);\n\t\treturn worker;\n\t}\n\n\tfunction copy(reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {\n\t\tvar chunkIndex = 0, crc32 = new Crc32();\n\n\t\tfunction step() {\n\t\t\tvar index = chunkIndex * CHUNK_SIZE;\n\t\t\tif (index < size)\n\t\t\t\treader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(array) {\n\t\t\t\t\tif (computeCrc32)\n\t\t\t\t\t\tcrc32.append(array);\n\t\t\t\t\tif (onprogress)\n\t\t\t\t\t\tonprogress(index, size, array);\n\t\t\t\t\twriter.writeUint8Array(array, function() {\n\t\t\t\t\t\tchunkIndex++;\n\t\t\t\t\t\tstep();\n\t\t\t\t\t}, onwriteerror);\n\t\t\t\t}, onreaderror);\n\t\t\telse\n\t\t\t\tonend(size, crc32.get());\n\t\t}\n\n\t\tstep();\n\t}\n\n\t// ZipReader\n\n\tfunction decodeASCII(str) {\n\t\tvar i, out = \"\", charCode, extendedASCII = [ '\\u00C7', '\\u00FC', '\\u00E9', '\\u00E2', '\\u00E4', '\\u00E0', '\\u00E5', '\\u00E7', '\\u00EA', '\\u00EB',\n\t\t\t\t'\\u00E8', '\\u00EF', '\\u00EE', '\\u00EC', '\\u00C4', '\\u00C5', '\\u00C9', '\\u00E6', '\\u00C6', '\\u00F4', '\\u00F6', '\\u00F2', '\\u00FB', '\\u00F9',\n\t\t\t\t'\\u00FF', '\\u00D6', '\\u00DC', '\\u00F8', '\\u00A3', '\\u00D8', '\\u00D7', '\\u0192', '\\u00E1', '\\u00ED', '\\u00F3', '\\u00FA', '\\u00F1', '\\u00D1',\n\t\t\t\t'\\u00AA', '\\u00BA', '\\u00BF', '\\u00AE', '\\u00AC', '\\u00BD', '\\u00BC', '\\u00A1', '\\u00AB', '\\u00BB', '_', '_', '_', '\\u00A6', '\\u00A6',\n\t\t\t\t'\\u00C1', '\\u00C2', '\\u00C0', '\\u00A9', '\\u00A6', '\\u00A6', '+', '+', '\\u00A2', '\\u00A5', '+', '+', '-', '-', '+', '-', '+', '\\u00E3',\n\t\t\t\t'\\u00C3', '+', '+', '-', '-', '\\u00A6', '-', '+', '\\u00A4', '\\u00F0', '\\u00D0', '\\u00CA', '\\u00CB', '\\u00C8', 'i', '\\u00CD', '\\u00CE',\n\t\t\t\t'\\u00CF', '+', '+', '_', '_', '\\u00A6', '\\u00CC', '_', '\\u00D3', '\\u00DF', '\\u00D4', '\\u00D2', '\\u00F5', '\\u00D5', '\\u00B5', '\\u00FE',\n\t\t\t\t'\\u00DE', '\\u00DA', '\\u00DB', '\\u00D9', '\\u00FD', '\\u00DD', '\\u00AF', '\\u00B4', '\\u00AD', '\\u00B1', '_', '\\u00BE', '\\u00B6', '\\u00A7',\n\t\t\t\t'\\u00F7', '\\u00B8', '\\u00B0', '\\u00A8', '\\u00B7', '\\u00B9', '\\u00B3', '\\u00B2', '_', ' ' ];\n\t\tfor (i = 0; i < str.length; i++) {\n\t\t\tcharCode = str.charCodeAt(i) & 0xFF;\n\t\t\tif (charCode > 127)\n\t\t\t\tout += extendedASCII[charCode - 128];\n\t\t\telse\n\t\t\t\tout += String.fromCharCode(charCode);\n\t\t}\n\t\treturn out;\n\t}\n\n\tfunction decodeUTF8(str_data) {\n\t\tvar tmp_arr = [], i = 0, ac = 0, c1 = 0, c2 = 0, c3 = 0;\n\n\t\tstr_data += '';\n\n\t\twhile (i < str_data.length) {\n\t\t\tc1 = str_data.charCodeAt(i);\n\t\t\tif (c1 < 128) {\n\t\t\t\ttmp_arr[ac++] = String.fromCharCode(c1);\n\t\t\t\ti++;\n\t\t\t} else if (c1 > 191 && c1 < 224) {\n\t\t\t\tc2 = str_data.charCodeAt(i + 1);\n\t\t\t\ttmp_arr[ac++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));\n\t\t\t\ti += 2;\n\t\t\t} else {\n\t\t\t\tc2 = str_data.charCodeAt(i + 1);\n\t\t\t\tc3 = str_data.charCodeAt(i + 2);\n\t\t\t\ttmp_arr[ac++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));\n\t\t\t\ti += 3;\n\t\t\t}\n\t\t}\n\n\t\treturn tmp_arr.join('');\n\t}\n\n\tfunction getString(bytes) {\n\t\tvar i, str = \"\";\n\t\tfor (i = 0; i < bytes.length; i++)\n\t\t\tstr += String.fromCharCode(bytes[i]);\n\t\treturn str;\n\t}\n\n\tfunction getDate(timeRaw) {\n\t\tvar date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & 0x0000ffff;\n\t\ttry {\n\t\t\treturn new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5,\n\t\t\t\t\t(time & 0x001F) * 2, 0);\n\t\t} catch (e) {\n\t\t}\n\t}\n\n\tfunction readCommonHeader(entry, data, index, centralDirectory, onerror) {\n\t\tentry.version = data.view.getUint16(index, true);\n\t\tentry.bitFlag = data.view.getUint16(index + 2, true);\n\t\tentry.compressionMethod = data.view.getUint16(index + 4, true);\n\t\tentry.lastModDateRaw = data.view.getUint32(index + 6, true);\n\t\tentry.lastModDate = getDate(entry.lastModDateRaw);\n\t\tif ((entry.bitFlag & 0x01) === 0x01) {\n\t\t\tonerror(ERR_ENCRYPTED);\n\t\t\treturn;\n\t\t}\n\t\tif (centralDirectory || (entry.bitFlag & 0x0008) != 0x0008) {\n\t\t\tentry.crc32 = data.view.getUint32(index + 10, true);\n\t\t\tentry.compressedSize = data.view.getUint32(index + 14, true);\n\t\t\tentry.uncompressedSize = data.view.getUint32(index + 18, true);\n\t\t}\n\t\tif (entry.compressedSize === 0xFFFFFFFF || entry.uncompressedSize === 0xFFFFFFFF) {\n\t\t\tonerror(ERR_ZIP64);\n\t\t\treturn;\n\t\t}\n\t\tentry.filenameLength = data.view.getUint16(index + 22, true);\n\t\tentry.extraFieldLength = data.view.getUint16(index + 24, true);\n\t}\n\n\tfunction createZipReader(reader, onerror) {\n\t\tfunction Entry() {\n\t\t}\n\n\t\tEntry.prototype.getData = function(writer, onend, onprogress, checkCrc32) {\n\t\t\tvar that = this, worker;\n\n\t\t\tfunction terminate(callback, param) {\n\t\t\t\tif (worker)\n\t\t\t\t\tworker.terminate();\n\t\t\t\tworker = null;\n\t\t\t\tif (callback)\n\t\t\t\t\tcallback(param);\n\t\t\t}\n\n\t\t\tfunction testCrc32(crc32) {\n\t\t\t\tvar dataCrc32 = getDataHelper(4);\n\t\t\t\tdataCrc32.view.setUint32(0, crc32);\n\t\t\t\treturn that.crc32 == dataCrc32.view.getUint32(0);\n\t\t\t}\n\n\t\t\tfunction getWriterData(uncompressedSize, crc32) {\n\t\t\t\tif (checkCrc32 && !testCrc32(crc32))\n\t\t\t\t\tonreaderror();\n\t\t\t\telse\n\t\t\t\t\twriter.getData(function(data) {\n\t\t\t\t\t\tterminate(onend, data);\n\t\t\t\t\t});\n\t\t\t}\n\n\t\t\tfunction onreaderror() {\n\t\t\t\tterminate(onerror, ERR_READ_DATA);\n\t\t\t}\n\n\t\t\tfunction onwriteerror() {\n\t\t\t\tterminate(onerror, ERR_WRITE_DATA);\n\t\t\t}\n\n\t\t\treader.readUint8Array(that.offset, 30, function(bytes) {\n\t\t\t\tvar data = getDataHelper(bytes.length, bytes), dataOffset;\n\t\t\t\tif (data.view.getUint32(0) != 0x504b0304) {\n\t\t\t\t\tonerror(ERR_BAD_FORMAT);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treadCommonHeader(that, data, 4, false, function(error) {\n\t\t\t\t\tonerror(error);\n\t\t\t\t\treturn;\n\t\t\t\t});\n\t\t\t\tdataOffset = that.offset + 30 + that.filenameLength + that.extraFieldLength;\n\t\t\t\twriter.init(function() {\n\t\t\t\t\tif (that.compressionMethod === 0)\n\t\t\t\t\t\tcopy(reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);\n\t\t\t\t\telse\n\t\t\t\t\t\tworker = inflate(reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);\n\t\t\t\t}, onwriteerror);\n\t\t\t}, onreaderror);\n\t\t};\n\n\t\tfunction seekEOCDR(offset, entriesCallback) {\n\t\t\treader.readUint8Array(reader.size - offset, offset, function(bytes) {\n\t\t\t\tvar dataView = getDataHelper(bytes.length, bytes).view;\n\t\t\t\tif (dataView.getUint32(0) != 0x504b0506) {\n\t\t\t\t\tseekEOCDR(offset + 1, entriesCallback);\n\t\t\t\t} else {\n\t\t\t\t\tentriesCallback(dataView);\n\t\t\t\t}\n\t\t\t}, function() {\n\t\t\t\tonerror(ERR_READ);\n\t\t\t});\n\t\t}\n\n\t\treturn {\n\t\t\tgetEntries : function(callback) {\n\t\t\t\tif (reader.size < 22) {\n\t\t\t\t\tonerror(ERR_BAD_FORMAT);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// look for End of central directory record\n\t\t\t\tseekEOCDR(22, function(dataView) {\n\t\t\t\t\tvar datalength, fileslength;\n\t\t\t\t\tdatalength = dataView.getUint32(16, true);\n\t\t\t\t\tfileslength = dataView.getUint16(8, true);\n\t\t\t\t\treader.readUint8Array(datalength, reader.size - datalength, function(bytes) {\n\t\t\t\t\t\tvar i, index = 0, entries = [], entry, filename, comment, data = getDataHelper(bytes.length, bytes);\n\t\t\t\t\t\tfor (i = 0; i < fileslength; i++) {\n\t\t\t\t\t\t\tentry = new Entry();\n\t\t\t\t\t\t\tif (data.view.getUint32(index) != 0x504b0102) {\n\t\t\t\t\t\t\t\tonerror(ERR_BAD_FORMAT);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treadCommonHeader(entry, data, index + 6, true, function(error) {\n\t\t\t\t\t\t\t\tonerror(error);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tentry.commentLength = data.view.getUint16(index + 32, true);\n\t\t\t\t\t\t\tentry.directory = ((data.view.getUint8(index + 38) & 0x10) == 0x10);\n\t\t\t\t\t\t\tentry.offset = data.view.getUint32(index + 42, true);\n\t\t\t\t\t\t\tfilename = getString(data.array.subarray(index + 46, index + 46 + entry.filenameLength));\n\t\t\t\t\t\t\tentry.filename = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(filename) : decodeASCII(filename);\n\t\t\t\t\t\t\tif (!entry.directory && entry.filename.charAt(entry.filename.length - 1) == \"/\")\n\t\t\t\t\t\t\t\tentry.directory = true;\n\t\t\t\t\t\t\tcomment = getString(data.array.subarray(index + 46 + entry.filenameLength + entry.extraFieldLength, index + 46\n\t\t\t\t\t\t\t\t\t+ entry.filenameLength + entry.extraFieldLength + entry.commentLength));\n\t\t\t\t\t\t\tentry.comment = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(comment) : decodeASCII(comment);\n\t\t\t\t\t\t\tentries.push(entry);\n\t\t\t\t\t\t\tindex += 46 + entry.filenameLength + entry.extraFieldLength + entry.commentLength;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcallback(entries);\n\t\t\t\t\t}, function() {\n\t\t\t\t\t\tonerror(ERR_READ);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\tclose : function(callback) {\n\t\t\t\tif (callback)\n\t\t\t\t\tcallback();\n\t\t\t}\n\t\t};\n\t}\n\n\t// ZipWriter\n\n\tfunction encodeUTF8(string) {\n\t\tvar n, c1, enc, utftext = [], start = 0, end = 0, stringl = string.length;\n\t\tfor (n = 0; n < stringl; n++) {\n\t\t\tc1 = string.charCodeAt(n);\n\t\t\tenc = null;\n\t\t\tif (c1 < 128)\n\t\t\t\tend++;\n\t\t\telse if (c1 > 127 && c1 < 2048)\n\t\t\t\tenc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);\n\t\t\telse\n\t\t\t\tenc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);\n\t\t\tif (enc != null) {\n\t\t\t\tif (end > start)\n\t\t\t\t\tutftext += string.slice(start, end);\n\t\t\t\tutftext += enc;\n\t\t\t\tstart = end = n + 1;\n\t\t\t}\n\t\t}\n\t\tif (end > start)\n\t\t\tutftext += string.slice(start, stringl);\n\t\treturn utftext;\n\t}\n\n\tfunction getBytes(str) {\n\t\tvar i, array = [];\n\t\tfor (i = 0; i < str.length; i++)\n\t\t\tarray.push(str.charCodeAt(i));\n\t\treturn array;\n\t}\n\n\tfunction createZipWriter(writer, onerror, dontDeflate) {\n\t\tvar worker, files = [], filenames = [], datalength = 0;\n\n\t\tfunction terminate(callback, message) {\n\t\t\tif (worker)\n\t\t\t\tworker.terminate();\n\t\t\tworker = null;\n\t\t\tif (callback)\n\t\t\t\tcallback(message);\n\t\t}\n\n\t\tfunction onwriteerror() {\n\t\t\tterminate(onerror, ERR_WRITE);\n\t\t}\n\n\t\tfunction onreaderror() {\n\t\t\tterminate(onerror, ERR_READ_DATA);\n\t\t}\n\n\t\treturn {\n\t\t\tadd : function(name, reader, onend, onprogress, options) {\n\t\t\t\tvar header, filename, date;\n\n\t\t\t\tfunction writeHeader(callback) {\n\t\t\t\t\tvar data;\n\t\t\t\t\tdate = options.lastModDate || new Date();\n\t\t\t\t\theader = getDataHelper(26);\n\t\t\t\t\tfiles[name] = {\n\t\t\t\t\t\theaderArray : header.array,\n\t\t\t\t\t\tdirectory : options.directory,\n\t\t\t\t\t\tfilename : filename,\n\t\t\t\t\t\toffset : datalength,\n\t\t\t\t\t\tcomment : getBytes(encodeUTF8(options.comment || \"\"))\n\t\t\t\t\t};\n\t\t\t\t\theader.view.setUint32(0, 0x14000808);\n\t\t\t\t\tif (options.version)\n\t\t\t\t\t\theader.view.setUint8(0, options.version);\n\t\t\t\t\tif (!dontDeflate && options.level != 0 && !options.directory)\n\t\t\t\t\t\theader.view.setUint16(4, 0x0800);\n\t\t\t\t\theader.view.setUint16(6, (((date.getHours() << 6) | date.getMinutes()) << 5) | date.getSeconds() / 2, true);\n\t\t\t\t\theader.view.setUint16(8, ((((date.getFullYear() - 1980) << 4) | (date.getMonth() + 1)) << 5) | date.getDate(), true);\n\t\t\t\t\theader.view.setUint16(22, filename.length, true);\n\t\t\t\t\tdata = getDataHelper(30 + filename.length);\n\t\t\t\t\tdata.view.setUint32(0, 0x504b0304);\n\t\t\t\t\tdata.array.set(header.array, 4);\n\t\t\t\t\tdata.array.set(filename, 30);\n\t\t\t\t\tdatalength += data.array.length;\n\t\t\t\t\twriter.writeUint8Array(data.array, callback, onwriteerror);\n\t\t\t\t}\n\n\t\t\t\tfunction writeFooter(compressedLength, crc32) {\n\t\t\t\t\tvar footer = getDataHelper(16);\n\t\t\t\t\tdatalength += compressedLength || 0;\n\t\t\t\t\tfooter.view.setUint32(0, 0x504b0708);\n\t\t\t\t\tif (typeof crc32 != \"undefined\") {\n\t\t\t\t\t\theader.view.setUint32(10, crc32, true);\n\t\t\t\t\t\tfooter.view.setUint32(4, crc32, true);\n\t\t\t\t\t}\n\t\t\t\t\tif (reader) {\n\t\t\t\t\t\tfooter.view.setUint32(8, compressedLength, true);\n\t\t\t\t\t\theader.view.setUint32(14, compressedLength, true);\n\t\t\t\t\t\tfooter.view.setUint32(12, reader.size, true);\n\t\t\t\t\t\theader.view.setUint32(18, reader.size, true);\n\t\t\t\t\t}\n\t\t\t\t\twriter.writeUint8Array(footer.array, function() {\n\t\t\t\t\t\tdatalength += 16;\n\t\t\t\t\t\tterminate(onend);\n\t\t\t\t\t}, onwriteerror);\n\t\t\t\t}\n\n\t\t\t\tfunction writeFile() {\n\t\t\t\t\toptions = options || {};\n\t\t\t\t\tname = name.trim();\n\t\t\t\t\tif (options.directory && name.charAt(name.length - 1) != \"/\")\n\t\t\t\t\t\tname += \"/\";\n\t\t\t\t\tif (files[name])\n\t\t\t\t\t\tthrow ERR_DUPLICATED_NAME;\n\t\t\t\t\tfilename = getBytes(encodeUTF8(name));\n\t\t\t\t\tfilenames.push(name);\n\t\t\t\t\twriteHeader(function() {\n\t\t\t\t\t\tif (reader)\n\t\t\t\t\t\t\tif (dontDeflate || options.level == 0)\n\t\t\t\t\t\t\t\tcopy(reader, writer, 0, reader.size, true, writeFooter, onprogress, onreaderror, onwriteerror);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tworker = deflate(reader, writer, options.level, writeFooter, onprogress, onreaderror, onwriteerror);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\twriteFooter();\n\t\t\t\t\t}, onwriteerror);\n\t\t\t\t}\n\n\t\t\t\tif (reader)\n\t\t\t\t\treader.init(writeFile, onreaderror);\n\t\t\t\telse\n\t\t\t\t\twriteFile();\n\t\t\t},\n\t\t\tclose : function(callback) {\n\t\t\t\tvar data, length = 0, index = 0;\n\t\t\t\tfilenames.forEach(function(name) {\n\t\t\t\t\tvar file = files[name];\n\t\t\t\t\tlength += 46 + file.filename.length + file.comment.length;\n\t\t\t\t});\n\t\t\t\tdata = getDataHelper(length + 22);\n\t\t\t\tfilenames.forEach(function(name) {\n\t\t\t\t\tvar file = files[name];\n\t\t\t\t\tdata.view.setUint32(index, 0x504b0102);\n\t\t\t\t\tdata.view.setUint16(index + 4, 0x1400);\n\t\t\t\t\tdata.array.set(file.headerArray, index + 6);\n\t\t\t\t\tdata.view.setUint16(index + 32, file.comment.length, true);\n\t\t\t\t\tif (file.directory)\n\t\t\t\t\t\tdata.view.setUint8(index + 38, 0x10);\n\t\t\t\t\tdata.view.setUint32(index + 42, file.offset, true);\n\t\t\t\t\tdata.array.set(file.filename, index + 46);\n\t\t\t\t\tdata.array.set(file.comment, index + 46 + file.filename.length);\n\t\t\t\t\tindex += 46 + file.filename.length + file.comment.length;\n\t\t\t\t});\n\t\t\t\tdata.view.setUint32(index, 0x504b0506);\n\t\t\t\tdata.view.setUint16(index + 8, filenames.length, true);\n\t\t\t\tdata.view.setUint16(index + 10, filenames.length, true);\n\t\t\t\tdata.view.setUint32(index + 12, length, true);\n\t\t\t\tdata.view.setUint32(index + 16, datalength, true);\n\t\t\t\twriter.writeUint8Array(data.array, function() {\n\t\t\t\t\tterminate(function() {\n\t\t\t\t\t\twriter.getData(callback);\n\t\t\t\t\t});\n\t\t\t\t}, onwriteerror);\n\t\t\t}\n\t\t};\n\t}\n\n\tobj.zip = {\n\t\tReader : Reader,\n\t\tWriter : Writer,\n\t\tBlobReader : BlobReader,\n\t\tHttpReader : HttpReader,\n\t\tHttpRangeReader : HttpRangeReader,\n\t\tData64URIReader : Data64URIReader,\n\t\tTextReader : TextReader,\n\t\tBlobWriter : BlobWriter,\n\t\tFileWriter : FileWriter,\n\t\tData64URIWriter : Data64URIWriter,\n\t\tTextWriter : TextWriter,\n\t\tcreateReader : function(reader, callback, onerror) {\n\t\t\treader.init(function() {\n\t\t\t\tcallback(createZipReader(reader, onerror));\n\t\t\t}, onerror);\n\t\t},\n\t\tcreateWriter : function(writer, callback, onerror, dontDeflate) {\n\t\t\twriter.init(function() {\n\t\t\t\tcallback(createZipWriter(writer, onerror, dontDeflate));\n\t\t\t}, onerror);\n\t\t},\n\t\tworkerScriptsPath : \"\",\n\t\tuseWebWorkers : true\n\t};\n\n})(this);\n"
  },
  {
    "path": "_archive/apps/samples/web-store/manifest.json",
    "content": "{\n  \"name\": \"Web Store API Sample App\",\n  \"description\": \"An example app to upload and publish Chrome Apps to the Web Store\",\n  \"version\": \"1\",\n  \"manifest_version\": 2,\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"key\": \"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvTWT4REnE8g8VuWDWF96d1bOfpDMt9nWL2+m92a9kzmiciabfetpTk+zXsjuBNObK0Hm+KPxYfZjxIU7jCSq6UBf2W0SRmCWUtz7OSCAhpBKHTI7D4ybTbcRh41RKPjrHH7WTjNKi/x9LUjwdgROxVNdV5f1CCe2CHSUU1lZciu1FDHKz8cA+2+mAB+j4FvQT8rrbidbAs1O75w6k8d3g0Rp7SrlUXbvvemPIFnaBDGIpfdBLRJRIMk4dS5MAzsHJb4WVCW3hGdMR65x2lHMMLYVe8G8A+4lWrr/hnV4CBCs4FzudaMMXKYoEW5Atr+ES9XKPW8qxSTVM0FfZ4/q7QIDAQAB\",\n  \"icons\": {\n    \"16\": \"images/icon_16.png\",\n    \"128\": \"images/icon_128.png\"\n  },\n  \"permissions\": [\n    { \"fileSystem\": [\"directory\", \"retainEntries\"] },\n    \"identity\", \n    \"storage\"\n  ],\n  \"oauth2\": {\n    \"client_id\": \"313416032683-3ob52hbv8u7gl4hi8l3sa6eh5ru4rb6u.apps.googleusercontent.com\",\n    \"scopes\": [\"https://www.googleapis.com/auth/chromewebstore\"]\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/webgl-pointer-lock/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/pjfconokbhkicolnaaphhfhjpcgnnfpj\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Hello 3D World\n\nA basic application using WebGL capabilities. It loads a 3D model from a JSON file and allows for model rotation and camera zooming, based on mouse movements. Dragging the mouse enters pointer lock, allowing movement unlimited by window or screen boundaries.\n\nThis sample uses the frameless window:\n\n    chrome.app.runtime.onLaunched.addListener(function() {\n      chrome.app.window.create('index.html',\n        {frame: 'none', innerBounds: {width: 500, height: 400}});\n    });\n\n## APIs\n\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Pointer Lock](http://www.w3.org/TR/pointerlock/)\n\n## External libs\n\n* [Three.js](https://github.com/mrdoob/three.js/)\n"
  },
  {
    "path": "_archive/apps/samples/webgl-pointer-lock/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <title>Hello 3D World</title>\n  <link href=\"styles/main.css\" rel=\"stylesheet\">\n  <script src=\"js/Detector.js\"></script>\n  <script src=\"js/three.min.js\"></script>\n</head>\n<body>\n  <div class=\"close\"></close>\n  <script src=\"js/showlogo3d.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webgl-pointer-lock/js/Detector.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n * @author mr.doob / http://mrdoob.com/\n */\n\nDetector = {\n\n\tcanvas: !! window.CanvasRenderingContext2D,\n\twebgl: ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(),\n\tworkers: !! window.Worker,\n\tfileapi: window.File && window.FileReader && window.FileList && window.Blob,\n\n\tgetWebGLErrorMessage: function () {\n\n\t\tvar element = document.createElement( 'div' );\n\t\telement.id = 'webgl-error-message';\n\t\telement.style.fontFamily = 'monospace';\n\t\telement.style.fontSize = '13px';\n\t\telement.style.fontWeight = 'normal';\n\t\telement.style.textAlign = 'center';\n\t\telement.style.background = '#fff';\n\t\telement.style.color = '#000';\n\t\telement.style.padding = '1.5em';\n\t\telement.style.width = '400px';\n\t\telement.style.margin = '5em auto 0';\n\n\t\tif ( ! this.webgl ) {\n\n\t\t\telement.innerHTML = window.WebGLRenderingContext ? [\n\t\t\t\t'Your graphics card does not seem to support <a href=\"http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation\" style=\"color:#000\">WebGL</a>.<br />',\n\t\t\t\t'Find out how to get it <a href=\"http://get.webgl.org/\" style=\"color:#000\">here</a>.'\n\t\t\t].join( '\\n' ) : [\n\t\t\t\t'Your browser does not seem to support <a href=\"http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation\" style=\"color:#000\">WebGL</a>.<br/>',\n\t\t\t\t'Find out how to get it <a href=\"http://get.webgl.org/\" style=\"color:#000\">here</a>.'\n\t\t\t].join( '\\n' );\n\n\t\t}\n\n\t\treturn element;\n\n\t},\n\n\taddGetWebGLMessage: function ( parameters ) {\n\n\t\tvar parent, id, element;\n\n\t\tparameters = parameters || {};\n\n\t\tparent = parameters.parent !== undefined ? parameters.parent : document.body;\n\t\tid = parameters.id !== undefined ? parameters.id : 'oldie';\n\n\t\telement = Detector.getWebGLErrorMessage();\n\t\telement.id = id;\n\n\t\tparent.appendChild( element );\n\n\t}\n\n};\n"
  },
  {
    "path": "_archive/apps/samples/webgl-pointer-lock/js/showlogo3d.js",
    "content": "\n// 3D code partially grabbed from http://dev.opera.com/articles/view/porting-3d-graphics-to-the-web-webgl-intro-part-2/\n\n// Cribbed from three.js's class of the same name and updated to use pointer\n// lock.\nOrbitControls = function(object, domElement) {\n  THREE.EventTarget.call(this);\n  this.object = object;\n  this.domElement = domElement;\n\n  // API\n  this.center = new THREE.Vector3();\n\n  this.userZoom = true;\n  this.userZoomSpeed = 1.0;\n\n  this.userRotate = true;\n  this.userRotateSpeed = 1.0;\n\n  this.autoRotate = false;\n  this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60\n\n  // internals\n\n  var scope = this;\n\n  var EPS = 0.000001;\n  var PIXELS_PER_ROUND = 1800;\n\n  var rotateStart = new THREE.Vector2();\n  var rotateEnd = new THREE.Vector2();\n  var rotateDelta = new THREE.Vector2();\n\n  var zoomStart = new THREE.Vector2();\n  var zoomEnd = new THREE.Vector2();\n  var zoomDelta = new THREE.Vector2();\n\n  var phiDelta = 0;\n  var thetaDelta = 0;\n  var scale = 1;\n\n  var lastPosition = new THREE.Vector3();\n\n  var STATE = { NONE : -1, ROTATE : 0, ZOOM : 1 };\n  var state = STATE.NONE;\n\n  // events\n\n  var changeEvent = { type: 'change' };\n\n  this.rotateLeft = function(angle) {\n    if (angle === undefined) {\n      angle = getAutoRotationAngle();\n    }\n\n    thetaDelta -= angle;\n  };\n\n  this.rotateRight = function(angle) {\n    if (angle === undefined) {\n      angle = getAutoRotationAngle();\n    }\n\n    thetaDelta += angle;\n  };\n\n  this.rotateUp = function(angle) {\n    if (angle === undefined) {\n      angle = getAutoRotationAngle();\n    }\n\n    phiDelta -= angle;\n  };\n\n  this.rotateDown = function(angle) {\n    if (angle === undefined) {\n      angle = getAutoRotationAngle();\n    }\n\n    phiDelta += angle;\n  };\n\n  this.zoomIn = function(zoomScale) {\n    if (zoomScale === undefined) {\n      zoomScale = getZoomScale();\n    }\n\n    scale /= zoomScale;\n  };\n\n  this.zoomOut = function(zoomScale) {\n    if (zoomScale === undefined) {\n      zoomScale = getZoomScale();\n    }\n\n    scale *= zoomScale;\n  };\n\n  this.update = function() {\n    var position = this.object.position;\n    var offset = position.clone().subSelf(this.center)\n\n    // angle from z-axis around y-axis\n\n    var theta = Math.atan2(offset.x, offset.z);\n\n    // angle from y-axis\n\n    var phi = Math.atan2(Math.sqrt(offset.x * offset.x + offset.z * offset.z), offset.y);\n\n    if (this.autoRotate) {\n      this.rotateLeft(getAutoRotationAngle());\n    }\n\n    theta += thetaDelta;\n    phi += phiDelta;\n\n    // restrict phi to be betwee EPS and PI-EPS\n\n    phi = Math.max(EPS, Math.min(Math.PI - EPS, phi));\n\n    var radius = offset.length();\n    offset.x = radius * Math.sin(phi) * Math.sin(theta);\n    offset.y = radius * Math.cos(phi);\n    offset.z = radius * Math.sin(phi) * Math.cos(theta);\n    offset.multiplyScalar(scale);\n\n    position.copy(this.center).addSelf(offset);\n\n    this.object.lookAt(this.center);\n\n    thetaDelta = 0;\n    phiDelta = 0;\n    scale = 1;\n\n    if (lastPosition.distanceTo(this.object.position) > 0) {\n      this.dispatchEvent(changeEvent);\n      lastPosition.copy(this.object.position);\n    }\n  };\n\n\n  function getAutoRotationAngle() {\n    return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\n  }\n\n  function getZoomScale() {\n    return Math.pow(0.95, scope.userZoomSpeed);\n  }\n\n  function onMouseDown(event) {\n    if (!scope.userRotate) return;\n\n    event.preventDefault();\n\n    if (event.button === 0 || event.button === 2) {\n      state = STATE.ROTATE;\n      rotateStart.set(event.clientX, event.clientY);\n      rotateEnd.set(event.clientX, event.clientY);\n    } else if (event.button === 1) {\n      state = STATE.ZOOM;\n      zoomStart.set(event.clientX, event.clientY);\n      zoomEnd.set(event.clientX, event.clientY);\n    }\n\n    scope.domElement.requestPointerLock =\n      scope.domElement.requestPointerLock ||\n      scope.domElement.mozRequestPointerLock ||\n      scope.domElement.webkitRequestPointerLock;\n    scope.domElement.requestPointerLock();\n\n    document.addEventListener('mousemove', onMouseMove, false);\n    document.addEventListener('mouseup', onMouseUp, false);\n  }\n\n  function onMouseMove(event) {\n    event.preventDefault();\n\n    if (state === STATE.ROTATE) {\n      rotateEnd.addSelf({\n        x: event.movementX || event.webkitMovementX || 0,\n        y: event.movementY || event.webkitMovementY || 0\n      });\n      rotateDelta.sub(rotateEnd, rotateStart);\n\n      scope.rotateLeft(2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed);\n      scope.rotateUp(2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed);\n\n      rotateStart.copy(rotateEnd);\n    } else if (state === STATE.ZOOM) {\n      zoomEnd.addSelf({\n        x: event.movementX || event.webkitMovementX || 0,\n        y: event.movementY || event.webkitMovementY || 0\n      });\n      zoomDelta.sub(zoomEnd, zoomStart);\n\n      if (zoomDelta.y > 0) {\n        scope.zoomIn();\n      } else {\n        scope.zoomOut();\n      }\n\n      zoomStart.copy(zoomEnd);\n    }\n  }\n\n  function onMouseUp(event) {\n    if (!scope.userRotate) return;\n\n    document.removeEventListener('mousemove', onMouseMove, false);\n    document.removeEventListener('mouseup', onMouseUp, false);\n\n    state = STATE.NONE;\n\n    document.exitPointerLock =\n      document.exitPointerLock ||\n      document.mozExitPointerLock ||\n      document.webkitExitPointerLock;\n    document.exitPointerLock();\n  }\n\n  function onMouseWheel(event) {\n    if (!scope.userZoom) return;\n\n    if (event.wheelDelta > 0) {\n      scope.zoomOut();\n    } else {\n      scope.zoomIn();\n    }\n  }\n\n  this.domElement.addEventListener('contextmenu', function(event) { event.preventDefault(); }, false);\n  this.domElement.addEventListener('mousedown', onMouseDown, false);\n  this.domElement.addEventListener('mousewheel', onMouseWheel, false);\n};\n\ndocument.addEventListener('DOMContentLoaded', function() {\n    if (!Detector.webgl) Detector.addGetWebGLMessage();\n\n    var SCREEN_WIDTH = window.innerWidth;\n    var SCREEN_HEIGHT = window.innerHeight;\n    var FLOOR = 0;\n\n    var container;\n\n    //var camera, scene, controls;\n    var webglRenderer;\n\n    var zmesh, geometry;\n\n    var mouseX = 0, mouseY = 0;\n\n    var windowHalfX = window.innerWidth / 2;\n    var windowHalfY = window.innerHeight / 2;\n\n    init();\n    animate();\n\n    function init() {\n\n      var closeEl=document.querySelector(\".close\");\n      console.log(closeEl);\n      if (closeEl) {\n        closeEl.addEventListener('click', function() {\n          window.close();\n        });\n        closeEl.addEventListener('mousedown', function(e) {\n          e.stopPropagation();\n        });\n      };\n\n      container = document.createElement('div');\n      document.body.appendChild(container);\n\n      // camera\n      camera = new THREE.PerspectiveCamera(75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 100000);\n      camera.position.z = 75;\n\n      //scene\n      scene = new THREE.Scene();\n\n      // lights\n      var ambient = new THREE.AmbientLight(0xffffff);\n      scene.add(ambient);\n\n      // more lights\n      var directionalLight = new THREE.DirectionalLight(0xffeedd);\n      directionalLight.position.set(0, -70, 100).normalize();\n      scene.add(directionalLight);\n\n      // renderer\n      webglRenderer = new THREE.WebGLRenderer();\n      webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);\n      webglRenderer.domElement.style.position = \"relative\";\n      container.appendChild(webglRenderer.domElement);\n\n      // load ascii model\n      var jsonLoader = new THREE.JSONLoader();\n      jsonLoader.load(\"obj/html5rocks.js\", function(geometry) { createScene(geometry) });\n\n      controls = new OrbitControls(camera, container);\n      controls.autoRotate = true;\n    }\n\n    function createScene(geometry) {\n      zmesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial());\n      zmesh.position.set(-10, -10, 0);\n      zmesh.scale.set(1, 1, 1);\n      scene.add(zmesh);\n    }\n\n    function onDocumentMouseDown(event) {\n      if (event.button !== 0)\n        return;\n      document.body.requestPointerLock =\n        document.body.requestPointerLock ||\n        document.body.mozRequestPointerLock ||\n        document.body.webkitRequestPointerLock;\n      document.body.requestPointerLock();\n    }\n\n    function onDocumentMouseUp(event) {\n      document.exitPointerLock =\n        document.exitPointerLock ||\n        document.mozExitPointerLock ||\n        document.webkitExitPointerLock;\n      document.exitPointerLock();\n    }\n\n    function onDocumentMouseWheel(event) {\n      camera.position.z -= event.wheelDelta/120*3;\n    }\n\n    function onDocumentMouseMove(event) {\n      if (!event.which) return;\n      document.pointerLockElement =\n        document.pointerLockElement ||\n        document.mozPointerLockElement ||\n        document.webkitPointerLockElement;\n      if (document.pointerLockElement) {\n        mouseX += event.movementX || event.mozMovementX || event.webkitMovementX || 0;\n        mouseY += event.movementY || event.mozMovementY || event.webkitMovementY || 0;\n      }\n    }\n\n    function animate() {\n      requestAnimationFrame(animate);\n      render();\n    }\n\n    function render() {\n      controls.update();\n\n      webglRenderer.render(scene, camera);\n    }\n\n});\n\n"
  },
  {
    "path": "_archive/apps/samples/webgl-pointer-lock/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html',\n    {\n    \tid: \"mainwin\",\n    \tframe:\"none\", \n    \tinnerBounds: {width: 500, height: 400}\n    });\n});\n"
  },
  {
    "path": "_archive/apps/samples/webgl-pointer-lock/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Sample of WebGL\",\n  \"version\": \"2\",\n  \"minimum_chrome_version\": \"23\",\n  \"icons\": {\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"pointerLock\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/webgl-pointer-lock/obj/html5rocks.js",
    "content": "{\n    \"metadata\" :\n    {\n        \"formatVersion\" : 3.1,\n        \"sourceFile\"    : \"estatua_hang-loose_cartoon_.obj\",\n        \"generatedBy\"   : \"OBJConverter\",\n        \"vertices\"      : 9638,\n        \"faces\"         : 19260,\n        \"normals\"       : 0,\n        \"colors\"        : 0,\n        \"uvs\"           : 10505,\n        \"materials\"     : 1\n    },\n\n    \"scale\" : 1.000000,\n\n    \"materials\": [\t{\n\t\"DbgColor\" : 15658734,\n\t\"DbgIndex\" : 0,\n\t\"DbgName\" : \"JPG_TorrioneLato_part\",\n\t\"colorAmbient\" : [0.0, 0.0, 0.0],\n\t\"colorDiffuse\" : [0.705882, 0.694118, 0.666667],\n\t\"colorSpecular\" : [0.33, 0.33, 0.33]\n\t}],\n\n    \"vertices\": [16.641403,36.050453,13.327883,19.742035,36.050453,13.327883,16.641403,36.401821,10.578089,19.742033,36.401821,10.578089,16.114893,39.370655,13.784882,20.268545,39.370655,13.784882,20.268545,39.398991,9.460533,16.114893,39.398991,9.460533,20.268545,42.003139,13.397568,16.114893,41.230740,9.518074,16.114893,42.003139,13.394184,20.268545,41.230740,9.518072,18.191719,35.403179,11.991080,15.454481,37.474556,11.934597,18.191719,37.320366,14.437613,18.191719,37.549301,9.294214,20.928957,37.474556,11.934597,15.342120,40.437431,11.623327,18.178978,47.388481,8.389557,18.193913,40.450493,8.766558,21.005672,44.060535,8.326774,15.345330,44.176907,8.311184,18.191719,40.452950,14.496783,18.191719,40.344582,8.435482,21.041317,40.437431,11.623503,18.191719,35.756012,13.659493,20.185114,37.374664,13.735245,18.191719,36.175537,10.234926,16.198324,37.567749,10.027802,20.101681,35.943523,11.990064,16.281757,35.943523,11.990063,16.198324,37.374664,13.735245,20.268545,40.453377,13.717873,20.185114,37.567749,10.027802,16.114893,40.361919,9.273144,18.191719,39.364826,14.549973,18.191719,39.398537,8.648470,21.041317,39.393459,11.702559,15.342120,39.393459,11.702559,16.090826,46.666988,8.359789,20.256676,41.395077,8.626534,20.245068,46.282043,8.364445,16.103823,41.395496,8.622797,16.114893,40.453377,13.717104,20.268545,40.361923,9.273143,15.342120,41.789955,11.535536,18.191719,42.053757,14.191496,18.191719,41.087883,8.755094,21.041317,41.789955,11.536304,16.114893,45.308929,11.940770,18.191719,45.956860,12.564547,20.268545,45.281200,11.940666,20.268545,41.244057,8.740726,18.191719,40.512341,8.491041,16.114893,41.244057,8.740987,21.041317,43.531391,10.263846,15.342120,43.537693,10.264034,18.191719,43.686493,13.684443,20.268545,43.354992,12.948171,18.191719,40.552376,8.747618,16.114893,40.982944,9.335222,21.041317,42.441177,11.052772,16.114893,43.354992,12.947402,20.268545,40.982944,9.335222,15.342120,42.441177,11.052597,16.114893,46.301876,9.946912,20.268545,41.314926,8.309004,15.342120,43.950813,9.033460,18.191719,47.068024,10.288746,20.268545,46.117897,9.946452,18.191719,40.366028,8.336493,16.114893,41.314926,8.310179,21.041317,43.909000,9.032497,21.768913,54.196747,2.614700,24.869545,54.196747,2.614701,21.768913,54.196747,5.715332,24.869545,54.196747,5.715332,21.261555,50.241081,2.081614,25.494305,50.183758,2.128567,25.495596,50.158657,6.291623,21.260317,50.215897,6.228301,23.319229,55.024487,4.165016,20.575747,52.860622,4.141340,23.322069,52.860649,1.427786,23.322052,52.860649,6.902254,26.074532,52.860641,4.165015,23.319229,54.473660,2.255052,25.327866,52.834797,2.171618,23.319229,54.473660,6.074979,21.324411,52.834797,6.153027,25.229191,54.473660,4.165016,21.409266,54.473660,4.165016,21.324495,52.834797,2.166284,25.327866,52.834797,6.158411,23.341387,50.204720,1.338990,23.343298,50.169548,7.060791,26.283466,50.156330,4.218988,20.474649,50.249149,4.020133,17.554789,33.814087,8.799238,20.088314,33.870144,9.469117,19.407812,30.711727,9.417116,17.446987,30.717049,8.484209,15.679900,30.280327,9.176313,14.745571,33.442089,9.267974,13.464590,36.499039,9.300364,17.488024,36.469810,9.032684,20.432421,36.413799,9.132643,20.167929,41.970753,0.026967,20.177900,43.225380,0.960329,19.941080,43.924812,1.181310,18.087969,42.948048,0.094355,20.020899,44.868488,2.038604,20.111053,45.879368,4.404027,18.056732,46.407009,3.802715,18.106661,44.907505,1.540094,15.754895,44.285030,1.150802,15.936067,45.215076,2.150713,15.140106,43.729908,0.730247,15.103419,42.327309,-0.392162,3.390004,42.871494,4.997637,3.392763,45.758049,4.398319,4.239798,45.752808,6.543943,4.353976,42.858681,7.488483,4.549840,40.991074,8.313766,3.359155,40.998260,5.610103,4.063556,41.135990,2.619805,4.192435,43.102505,2.324712,4.225183,45.811069,2.123022,25.131229,30.795273,4.763364,24.350306,30.470226,6.926511,25.023617,33.325092,7.348320,25.891321,33.255470,4.882966,25.466103,35.895164,7.411461,26.276449,35.923019,5.104357,25.506905,36.077450,2.268959,24.864639,32.876648,1.946726,23.652630,28.653019,2.314134,20.301308,41.017052,9.346592,20.350430,42.311680,9.465361,20.979349,42.713650,9.284279,22.445278,41.353931,9.171185,21.349653,43.320969,8.514824,21.357107,44.289207,7.028204,23.386040,43.836029,7.731021,23.124115,42.693779,8.532862,25.602055,40.897011,7.795481,25.694229,42.363914,7.460166,9.409750,41.929077,0.172657,9.611314,43.194702,0.837131,8.749145,43.436462,1.032222,6.774537,41.874424,0.683467,8.476739,44.178329,1.544436,8.850641,45.800503,2.534525,6.438601,45.890144,1.317175,6.423025,43.545059,1.027998,14.509761,44.422642,1.198188,12.183472,42.997578,0.402852,12.178839,45.870777,1.723199,14.351413,46.039818,2.048748,10.312719,44.042572,1.324485,10.227236,45.668369,2.276392,23.214529,36.634808,-0.159538,21.899523,33.182312,-1.057005,20.809690,37.173286,-1.517969,20.402075,35.268509,-1.981152,3.945579,28.993652,6.731921,6.342696,27.630436,6.293505,6.163786,29.285851,1.198049,3.464254,30.788326,3.331007,1.338848,32.479755,6.336014,5.581024,29.480576,10.243374,8.099658,43.485302,8.512098,8.956647,43.280663,8.510280,9.057632,42.670677,9.281703,8.521521,42.487381,9.659775,9.117075,44.159954,7.356660,9.914556,43.452801,8.520782,10.022098,42.881302,8.980339,9.942124,42.229786,9.569644,9.370812,42.009182,10.001351,15.134304,42.093102,9.440177,14.387882,42.471207,9.410965,15.171021,42.756046,9.188321,15.922336,42.454304,9.260571,14.291126,43.054817,9.146950,15.163970,43.100239,8.753696,16.016615,42.923134,8.836382,15.200027,43.790550,8.073415,15.829412,43.443306,8.382787,20.624073,43.161572,9.105728,20.802483,43.496231,8.483589,19.908230,42.752525,9.295874,19.979214,43.137562,8.790290,21.179781,43.964096,1.985341,21.419081,44.678547,2.819633,20.692398,44.912537,4.065842,20.698273,44.560291,2.564911,20.551888,44.122517,1.900337,20.679087,43.452496,1.425149,15.096082,46.359104,4.283350,14.370894,46.863148,4.068720,15.164320,45.553528,2.675919,15.126204,44.803699,1.776985,15.685823,46.383793,4.398052,9.415887,45.137848,3.679012,9.530736,44.719231,2.284747,9.600285,44.127499,1.652371,9.146831,44.701492,5.592675,9.228874,44.806225,6.392028,8.427194,45.634892,6.677935,9.171459,46.057098,4.579768,9.840028,46.386486,4.184544,15.111487,45.220764,6.421625,15.334659,45.387959,6.496698,14.526147,43.524315,8.767260,14.936706,45.272228,6.559089,20.819218,44.646954,6.014454,20.661507,44.949554,6.595640,20.880468,44.865456,5.058719,20.869555,43.988991,7.599807,20.243906,43.508228,8.377787,18.187477,42.574409,8.910583,12.079569,47.086853,3.725282,23.374477,44.260109,1.615456,25.682211,43.957302,2.585875,26.489252,43.660370,4.861056,25.698055,43.659355,6.924173,14.569901,39.045750,9.292404,17.680470,38.910503,9.163155,20.567404,38.696495,9.077148,14.579780,36.977009,-2.403368,14.273384,34.259434,-2.816847,17.820778,34.745197,-2.663809,17.876354,37.152195,-2.186249,13.963810,30.925550,-2.720890,17.898161,31.678459,-2.625872,25.636402,38.477085,7.571956,26.422905,38.571774,5.326321,25.631039,38.825432,2.600293,7.509877,38.871658,9.777608,5.087964,39.433441,8.889061,10.534670,38.209156,9.590168,12.471426,39.494137,9.452972,23.042797,36.242794,8.745680,22.635843,33.699162,9.032579,22.126825,30.599434,9.099345,4.227679,34.028828,1.234534,4.869411,37.046757,0.540800,7.268015,33.643375,-0.877840,8.073478,36.809208,-1.241564,10.665771,33.890480,-2.224016,11.272703,36.871658,-2.060862,10.119993,30.189079,-1.559706,23.208015,39.185551,0.400586,20.800259,39.438560,-0.852280,21.295887,27.105906,8.047331,18.772892,27.090797,8.475763,23.296041,27.617611,5.593077,13.640282,27.521879,-2.120310,17.300322,27.632465,-2.232962,10.290840,27.351061,-0.730001,8.005838,26.995007,1.340794,7.881689,26.610336,4.373246,10.342911,27.992636,9.338223,10.136003,26.527800,7.325953,13.525179,29.289242,9.805340,13.060810,26.812967,8.576186,15.433518,27.121002,8.180026,17.021749,27.355066,7.643191,17.993605,39.602966,-1.262928,14.852346,39.526501,-1.592901,3.315180,39.863258,6.037643,3.427480,39.524639,2.906029,23.173668,38.603973,8.781794,5.577664,39.303471,0.421090,8.686111,39.364182,-0.797068,11.736773,39.527954,-1.189819,15.005508,41.070789,9.416479,17.839493,41.533096,9.290857,18.034786,42.608624,8.984064,26.493185,40.923836,5.468141,26.516514,42.381710,5.225249,25.647190,42.697170,2.741247,25.468126,41.246685,2.815219,7.182427,41.314468,9.754662,6.424438,43.108315,8.662846,6.307978,45.795990,7.449553,9.744529,40.954704,10.018959,12.302345,41.530029,9.583488,12.239944,42.797985,9.273614,21.804770,41.955315,0.974688,22.948654,43.200829,1.481548,12.260656,42.975819,9.167521,8.002187,36.246353,10.707651,10.098858,36.172592,10.321278,12.233822,35.077797,10.201479,13.354960,32.377285,10.181287,10.767703,30.246899,10.724348,10.627337,32.827007,11.035929,8.928242,32.305416,11.360986,7.505074,31.968317,11.621004,7.650098,29.100325,10.323163,20.827526,27.994570,-0.710585,16.422197,25.529619,-1.728355,19.312330,25.684122,-0.622551,21.869705,26.267088,1.359137,9.961075,25.596695,5.899326,12.786579,25.683430,7.127923,8.588577,25.489107,3.707689,18.985529,17.062880,-0.836391,15.759809,17.059116,-1.867243,21.503588,17.075041,0.945327,8.872824,17.053808,2.113360,8.678974,17.054417,3.893244,10.295196,17.054976,0.095808,14.806417,25.749647,7.216353,12.922199,17.063547,7.073422,14.940153,17.067007,7.583995,10.048281,17.059328,5.795955,16.737556,17.064751,7.708737,16.558949,25.640188,7.146163,18.225084,25.541855,7.257401,18.691275,17.064339,7.282313,22.008366,26.121586,4.368635,20.037382,25.631338,6.454726,13.462507,25.538822,-1.435225,10.382483,25.535931,-0.019753,13.044678,17.057060,-1.346640,8.749629,25.501326,1.791185,21.830109,17.074678,3.410662,20.238194,17.066284,5.927027,4.738553,58.362854,2.614700,7.839186,58.362854,2.614701,4.738553,58.362854,5.715331,7.839186,58.362854,5.715331,4.212043,54.291206,2.088189,8.365697,54.291206,2.088190,8.365696,54.291206,6.241842,4.212045,54.291206,6.241842,6.288870,59.190594,4.165016,3.551632,57.026756,4.165016,6.288870,57.026756,1.427777,6.288869,57.026756,6.902254,9.026110,57.026756,4.165015,3.430220,49.942783,4.188568,6.320290,49.947720,1.327636,6.291111,49.944317,7.052760,9.147076,49.950531,4.202928,6.288871,58.639767,2.255052,8.282265,57.000912,2.171618,6.288871,58.639767,6.074979,4.295475,57.000912,6.158411,8.198833,58.639767,4.165016,4.378906,58.639767,4.165016,4.295476,57.000912,2.171620,8.432631,49.950974,2.164508,8.282265,57.000912,6.158411,4.213673,49.943008,6.264811,6.288871,54.289200,1.315415,6.288869,54.289200,7.014617,9.138471,54.289200,4.165015,3.439273,54.289200,4.165015,4.215776,49.945549,2.088596,8.361197,49.946930,6.256989,21.410135,46.776218,2.280177,20.678959,46.834373,4.104882,21.385612,46.615040,6.368768,23.382584,46.557716,1.475410,25.595661,46.411324,2.346613,25.603920,46.250683,6.560437,23.391037,46.332623,7.314590,26.393833,46.248272,4.510440,11.056482,41.847813,19.294094,10.096521,43.836731,17.117727,12.369826,40.362034,17.356993,11.409865,42.350956,15.180626,8.315140,39.586281,19.186621,7.029160,42.250668,16.271124,9.493032,40.235123,13.343232,10.779423,37.569397,16.258656,3.216904,39.399868,14.312715,8.085762,35.034203,14.462288,4.978256,36.770203,17.081661,6.875467,38.003014,11.615137,6.647142,36.221252,10.636936,2.155750,38.342415,4.195006,11.835215,42.621201,17.448685,11.141682,39.567734,18.863804,8.972998,42.574364,18.668358,11.754573,40.057922,15.141747,9.446774,43.079372,15.021206,8.428783,36.958767,17.692564,4.312377,30.378920,11.247246,5.772224,40.120266,17.679523,9.460240,37.299286,13.561360,6.631604,40.628731,13.706677,2.260362,30.740210,8.731430,10.609234,43.175892,18.496361,8.718431,43.495461,16.782455,3.590176,38.643867,7.179515,12.258520,41.336563,16.087978,11.936502,39.107044,17.032473,10.834767,43.514793,15.985506,12.017424,41.064476,18.666756,9.952749,40.938107,19.580828,5.548511,41.091908,15.704193,10.702185,41.664394,14.234099,9.605797,36.355656,15.576456,7.236441,41.275066,18.246937,10.603447,38.524544,14.252131,7.969440,41.770737,14.316831,9.734018,38.114643,18.317148,1.565763,35.230194,4.600419,6.451230,31.800060,12.342048,6.918190,38.433075,18.603262,8.320122,39.063290,12.668394,6.758489,35.427429,16.256882,3.528469,38.360352,16.209948,8.065103,36.089821,12.580495,4.802545,39.310608,12.306630,1.730812,32.879078,12.046486,0.297583,34.202763,10.289080,0.404438,36.200855,8.449080,4.576043,37.641415,8.736993,6.655129,35.097988,11.233162,6.197171,32.599602,12.874135,2.189323,38.181309,7.397979,4.129261,32.135151,13.040577,1.182024,36.034462,13.863922,0.999399,37.504108,12.168008,7.186284,35.304951,11.723192,6.780647,33.841454,13.345825,3.167920,38.528095,10.279415,2.842915,34.810661,14.877496,5.755158,37.507278,10.397800,5.185740,33.763828,14.605365,10.450357,35.186325,13.327882,13.550987,35.186325,13.327882,10.450357,35.537697,10.578089,13.550986,35.537697,10.578089,9.923845,38.506626,13.784882,14.077498,38.506622,13.784882,14.077499,38.534973,9.460531,9.923847,38.534973,9.460531,14.077499,41.280045,13.477845,9.923844,40.506046,9.518072,9.923845,41.280045,13.477845,14.077498,40.506046,9.518072,12.000672,34.539055,11.991080,9.263436,36.610428,11.934597,12.000671,36.456242,14.437613,12.000672,36.685173,9.294215,14.737909,36.610428,11.934597,9.151072,39.575020,11.627849,12.012102,47.684345,7.150929,12.052097,40.782219,8.826370,14.861292,44.327942,8.143458,9.170312,44.244328,8.133732,12.000671,39.590591,14.501760,12.000672,39.481853,8.435479,14.850271,39.575020,11.627849,12.000673,34.891884,13.659492,13.994066,36.510540,13.735244,12.000673,35.311409,10.234928,10.007278,36.703621,10.027802,13.910633,35.079395,11.990064,10.090711,35.079395,11.990063,10.007278,36.510540,13.735244,14.077499,39.591022,13.736116,13.994066,36.703621,10.027802,9.923845,39.499252,9.273142,12.000672,38.500797,14.549973,12.000672,38.534519,8.648468,14.850271,38.529434,11.702559,9.151073,38.529434,11.702559,9.923397,46.829483,7.336849,14.133482,41.641453,8.699834,14.100113,46.894310,7.310285,9.950153,41.620209,8.666710,9.923845,39.591019,13.736116,14.077499,39.499252,9.273141,9.151072,41.066566,11.555433,12.000672,41.330666,14.213403,12.000671,40.362896,8.755093,14.850271,41.066563,11.555432,9.923845,45.348640,11.993540,12.000671,46.010227,12.626451,14.077497,45.348640,11.993363,14.077497,41.244057,8.741523,12.000671,40.512341,8.491310,9.923845,41.244057,8.741524,14.850269,43.545048,10.274147,9.151073,43.545048,10.274188,12.000671,43.552818,13.689421,14.077497,43.221317,12.966413,12.000671,40.418266,8.747617,9.923844,40.848904,9.335220,14.850269,42.307434,11.057117,9.923845,43.221317,12.966413,14.077497,40.848904,9.335220,9.151072,42.307434,11.057117,9.923847,46.514065,10.013801,14.077497,41.314922,8.322428,9.151073,43.990105,9.089344,12.000673,47.361317,10.353624,14.077498,46.514065,10.012886,12.000671,40.366028,8.337685,9.923846,41.314922,8.322467,14.850270,43.990105,9.088991,20.192572,42.425991,8.520422,18.205755,41.508308,8.860454,16.044043,42.428680,8.493790,15.362660,44.849834,7.499453,15.960866,46.721329,6.367357,18.110172,47.156933,6.000805,20.118290,46.229187,6.398079,20.813181,44.553116,7.604331,18.905565,23.691742,-0.645952,21.402662,23.988091,1.119466,12.883198,23.771187,6.898215,10.101403,23.726400,5.691478,8.826480,23.638632,3.751289,8.998137,23.619196,2.027554,10.449265,23.617064,0.164200,14.808486,23.795984,7.238482,16.561420,23.704803,7.312755,18.324514,23.682308,7.079845,21.643616,23.963575,3.787188,19.891924,23.733683,5.985257,15.987513,23.619730,-1.643965,13.284235,23.617804,-1.232370,18.954315,19.867538,-0.767868,12.892725,19.908937,7.017492,8.911561,19.825632,2.056930,14.865093,19.923429,7.440622,16.645174,19.875196,7.539196,18.511890,19.863377,7.209062,21.759832,20.013813,3.614588,13.158110,19.826483,-1.318419,21.474323,20.026661,1.018013,10.058620,19.883738,5.770820,8.727594,19.835974,3.828487,10.356169,19.825092,0.105424,20.075781,19.890882,5.978356,15.877319,19.828476,-1.784967,15.623264,16.877340,0.341383,18.212959,16.878120,1.110964,20.193148,16.878445,2.229185,20.644865,16.878759,3.375543,19.638765,16.879248,5.072898,18.583061,16.879309,5.583260,16.942411,16.879047,5.645343,15.206474,16.877945,5.407784,13.308384,16.875574,5.079582,10.827990,16.873308,4.369802,9.783607,16.872122,3.596771,9.903769,16.872265,2.509836,11.006862,16.873405,1.515726,13.396418,16.875406,0.638642,15.732248,16.877132,-1.322676,18.742275,16.877985,-0.362395,21.030886,16.878494,1.217498,21.313299,16.879005,3.292273,19.889227,16.879599,5.599811,18.468029,16.879734,6.804078,16.703886,16.879366,7.181118,15.030458,16.878109,7.057922,13.104929,16.875574,6.565329,10.414518,16.873117,5.393981,9.206625,16.871698,3.784928,9.376821,16.871883,2.295980,10.666405,16.873137,0.495298,13.224916,16.875189,-0.841703,18.999050,18.060926,-0.859556,12.890165,18.078762,7.105497,8.834087,18.037954,2.070193,14.899314,18.086885,7.581875,16.703024,18.065239,7.695966,18.641371,18.060030,7.303984,21.857199,18.129482,3.507825,13.071989,18.040211,-1.389826,21.542841,18.135103,0.945808,10.012770,18.065683,5.829231,8.641753,18.042677,3.878240,10.280075,18.038408,0.056387,20.208963,18.072767,5.983792,15.811380,18.042252,-1.892391,21.487160,25.393953,1.170491,10.016922,24.996634,5.664968,8.769790,24.863192,3.676781,10.428385,24.829475,0.144152,19.815533,25.004255,6.059919,16.128824,24.831432,-1.621716,18.950151,24.941053,-0.618525,12.814125,25.063833,6.859687,8.932547,24.833395,1.960216,14.738281,25.100456,7.118892,16.507238,24.960320,7.168732,18.203655,24.925659,7.035248,21.686033,25.356140,3.984578,13.372715,24.829535,-1.259056,19.177628,35.548180,12.846576,17.205811,35.548183,12.846576,17.205811,35.812298,11.103799,19.177628,35.812298,11.103799,15.901735,36.551426,12.848299,15.545857,38.461151,12.908218,15.545857,38.513863,10.685572,15.901736,36.734550,11.081800,17.061300,38.411079,14.348694,17.201220,36.454262,13.999976,19.182219,36.454262,13.999976,19.322138,38.411079,14.348694,19.322138,38.518322,9.134588,19.182219,36.820133,9.850221,17.201220,36.820133,9.850222,17.061300,38.518318,9.134588,20.837582,38.461151,12.908218,20.481703,36.551426,12.848299,20.481701,36.734550,11.081800,20.837580,38.513863,10.685572,15.535314,39.947311,12.827888,15.535314,41.193550,12.700999,15.535314,41.009632,10.421375,15.535314,39.944195,10.374254,17.054630,47.161354,9.289335,19.326729,42.767220,13.768440,19.326672,40.542145,8.493248,17.056709,40.926949,8.978058,20.844835,45.227222,8.881756,20.848125,41.627056,10.333172,15.535313,42.458786,12.342426,15.535067,42.537148,8.479824,17.056709,41.207169,14.160527,17.056709,39.944817,14.350922,19.326729,39.944817,14.350974,19.326729,41.207169,14.162152,19.326729,40.828857,8.779441,19.326729,39.938557,8.663347,17.056709,39.938557,8.663347,17.056709,40.828857,8.779442,20.848125,41.193550,12.702679,20.848125,39.947311,12.827942,20.848125,39.944195,10.374255,20.848125,41.009632,10.421430,17.056709,44.711197,13.095601,19.326729,46.433743,11.342216,19.326729,40.595543,8.716471,17.056709,40.660587,8.321803,20.848125,43.778011,11.719252,20.848125,42.484840,8.930696,15.535314,45.022453,10.365782,15.535314,41.968910,9.774929,19.326729,44.709309,13.095648,17.056709,40.595543,8.716488,20.848125,41.968849,9.774906,15.535314,43.779968,11.719212,17.056709,42.767220,13.766815,19.326729,40.926949,8.978058,20.848125,42.458786,12.344106,15.535313,41.627056,10.333117,17.056709,46.496574,11.342385,19.326729,40.660587,8.321302,20.848125,44.957527,10.365335,15.535314,42.486935,8.931477,19.325262,46.966408,9.289326,17.056133,40.541748,8.493687,20.845490,42.528873,8.479901,15.534319,45.430840,8.881246,24.305138,54.758736,3.179108,22.333321,54.758736,3.179109,22.333321,54.758736,5.150924,24.305136,54.758736,5.150924,21.028811,53.745491,3.172851,20.662985,51.698215,2.981336,20.662720,51.696850,5.241288,21.028805,53.745491,5.153847,22.190882,51.695518,1.520131,22.328749,53.745491,1.874983,24.310631,53.745491,1.875032,24.479534,51.692585,1.522119,24.479733,51.689331,6.815812,24.310631,53.745491,6.454999,22.328743,53.745491,6.454946,22.190754,51.692261,6.812626,26.023739,51.690056,3.039541,25.610991,53.745491,3.174518,25.610991,53.745491,5.155515,26.023800,51.688698,5.300696,20.753113,48.508533,2.942355,20.748770,48.463425,5.184855,22.233299,48.418186,1.594431,24.543472,48.321777,1.606426,24.550125,48.214409,6.984290,22.233631,48.310631,6.934351,26.145372,48.238914,3.193201,26.147352,48.193993,5.473647,18.636971,32.404770,9.074467,16.376188,32.186584,8.843417,15.727245,35.102921,8.986838,19.000874,35.210129,9.110662,19.652338,43.086422,0.531118,19.184822,45.605434,2.738800,16.895943,44.359596,1.070831,15.981345,43.392769,0.361590,16.534216,41.066914,-0.924400,19.355003,40.963615,-0.612793,3.639777,44.134853,5.920639,3.817101,40.372875,7.312723,3.324638,40.315384,4.197595,3.585385,44.218235,3.347118,25.365749,31.950527,6.043601,25.924685,34.592331,6.286140,25.924139,34.571522,3.554149,25.172302,31.392506,3.449844,20.923660,41.933197,9.431765,22.199686,43.453106,8.050827,24.328583,41.874275,8.446329,24.374645,39.849094,8.485490,21.636562,39.906246,9.158533,8.710921,42.683472,0.612247,7.621956,44.696972,1.441670,5.221850,44.404003,1.448474,4.801250,40.355244,1.470530,7.582601,40.603672,-0.036109,14.309141,43.382782,0.463187,13.417071,44.956059,1.218999,11.136164,44.786297,1.386002,10.391443,43.063438,0.688610,10.510473,40.913063,-0.424807,13.470739,41.038200,-0.821938,24.119791,34.790966,0.661142,21.722111,35.720856,-1.300774,4.609509,28.858812,4.168057,2.502909,30.499889,6.006476,3.817699,29.598148,9.151240,8.654212,42.980255,9.020784,9.417565,43.469284,8.385565,9.196018,42.362057,9.717140,15.169633,42.496185,9.374279,14.811451,42.873493,9.135054,15.461407,43.308304,8.501404,20.901630,43.243069,8.892934,20.474005,42.834675,9.376417,20.427694,43.219006,8.931873,20.940338,44.507927,2.880301,20.428297,44.420670,1.921980,20.357460,43.741806,1.459164,14.857429,46.378151,3.145224,15.121124,44.327347,1.277593,15.376033,45.937466,3.343720,9.186234,44.816750,2.505777,9.613709,43.713306,1.240052,9.896523,44.689678,1.932997,9.271010,44.282093,6.990232,9.020747,44.943485,6.026285,9.245756,45.186619,4.122787,9.312288,45.255104,4.880955,15.309000,44.483871,7.353007,15.024277,44.487125,7.463449,14.936273,46.100616,5.196392,15.230033,46.003265,5.371095,20.603348,45.195866,5.295019,20.908539,44.701904,4.568311,20.946033,44.376118,6.491854,20.721663,44.344212,7.219947,15.778305,37.744228,9.162167,16.277533,40.134243,9.291404,19.153067,40.024265,9.215727,19.142372,37.629044,9.082109,16.158464,35.822681,-2.649612,16.028042,32.986443,-2.897707,19.349323,36.132870,-2.198488,26.189301,37.183468,6.449512,26.285995,39.764744,6.679629,26.270004,39.955318,4.063074,26.200058,37.340355,3.835012,5.907312,40.181042,9.324844,8.675956,39.819576,9.851395,11.247345,40.026413,9.676135,13.592762,40.270119,9.432932,24.170151,34.806232,8.253614,23.679630,32.072273,8.325788,21.052652,32.359516,9.579142,21.559284,35.144451,9.227540,3.038743,36.202400,2.371482,2.484451,33.018967,3.580737,5.131736,31.828352,0.920474,6.152965,35.391411,-0.397745,9.339619,35.408878,-1.817001,8.431721,31.727547,-1.116013,12.224746,32.348972,-2.529594,12.694196,35.572834,-2.531681,24.612703,37.686359,1.186119,24.145309,40.336964,1.601249,21.459702,40.643291,-0.016140,22.162260,38.122040,-0.657642,20.397100,28.727934,9.161972,22.993778,28.793436,7.692471,15.723521,29.340591,-2.657234,11.937710,28.901690,-1.943720,8.484262,28.311823,-0.106343,6.779028,27.453493,3.111143,8.533222,27.032415,6.941748,11.837704,27.510199,9.078629,14.614011,28.265347,9.145103,16.523064,28.817101,8.274223,18.069559,28.892893,8.504900,16.340534,38.267014,-1.963892,19.472052,38.319069,-1.538601,4.518171,38.780716,8.200706,2.780499,39.290993,4.924208,24.507029,37.274754,8.219031,21.872675,37.486652,8.958099,3.785339,38.546600,1.782764,6.748656,38.084949,-0.512537,9.947130,38.131706,-1.458376,13.103838,38.188179,-1.930614,15.951391,41.830639,9.381996,16.889874,42.424000,9.102205,19.028152,42.562313,9.111189,19.642809,41.976730,9.411666,26.333092,41.694584,6.639504,26.327515,43.081482,3.792095,5.504274,41.958656,8.792840,7.347798,44.372292,7.906316,8.709717,41.794144,10.049509,10.275284,41.736523,9.907425,11.033854,42.342022,9.367052,13.377811,42.506977,9.379248,14.254447,41.837273,9.489464,24.039204,42.328423,1.858445,22.158985,43.950130,1.807408,20.517336,42.727493,0.802418,19.178379,44.200027,1.022982,16.869183,45.787598,2.778233,3.702962,41.785156,6.760511,3.532026,41.906448,3.839122,21.829031,42.589985,9.024361,24.585873,43.016945,7.826727,7.627068,43.248543,0.914963,5.244207,42.338631,1.466793,13.326985,46.680557,2.573720,10.971622,46.486965,2.752482,8.674153,44.070572,7.739083,9.381322,42.719597,9.076485,14.898561,43.395615,8.722820,15.509964,42.844757,9.000991,21.057430,43.761692,7.921137,20.577295,43.574684,8.349038,20.748726,44.075409,2.033368,20.458515,45.114853,3.223298,14.901451,45.228760,1.929090,15.389853,44.931385,1.953307,9.148496,44.088188,1.625882,9.691490,45.564919,3.045094,16.948677,42.856930,8.850634,19.214125,42.937054,8.839369,26.336576,42.905743,6.220609,26.313284,41.877377,4.042703,5.247642,44.189331,7.688189,7.561880,42.590927,9.313634,11.056667,43.159363,9.082541,13.439856,43.243221,9.210249,24.548891,43.441082,1.889585,21.434433,43.193420,1.363935,6.810998,37.870289,10.090435,9.006160,37.556618,10.009308,11.608252,36.674183,9.750625,14.461701,31.474083,9.726006,13.464899,34.539425,9.710725,12.669313,38.263420,9.351788,12.244402,29.898466,10.298521,11.948799,32.825737,10.669153,10.536947,34.376850,10.815229,8.697083,34.285072,11.107603,7.365722,33.890316,11.602808,5.971167,30.509975,11.595707,7.379906,30.379738,11.176011,9.442577,30.952545,11.162054,5.642332,28.450190,8.451833,8.716584,28.385054,9.480860,24.384850,29.258661,4.923893,19.639774,33.857788,-2.257301,23.051905,30.535717,0.485292,19.627186,29.948368,-1.853336,18.440351,26.348196,-1.459663,20.458391,25.497444,0.156416,11.337755,25.319181,6.425010,9.112247,25.196522,4.689526,9.432670,25.094761,1.009853,13.850128,25.392689,7.059331,15.794596,17.496792,7.738206,17.736759,17.488543,7.632228,22.893539,26.997591,3.312141,20.883610,25.484203,5.275519,18.940117,25.202658,6.721929,14.392673,17.476892,-1.838358,11.574842,17.474710,-0.780100,8.180226,26.086823,2.675013,14.086191,26.181408,7.809783,17.565865,26.190626,7.560880,22.011137,25.812244,2.630022,11.859081,26.326958,-1.128983,17.375153,17.479456,-1.561142,21.473343,26.849041,0.405292,8.965528,25.998219,5.265844,21.744772,26.391611,6.225070,19.490084,26.046711,7.703404,8.639051,25.096888,2.756497,9.224627,26.241894,0.562008,15.955209,26.295012,7.383237,15.194336,26.313751,-2.037136,11.437361,26.052446,7.323575,7.274779,58.924847,3.179108,5.302960,58.924847,3.179109,5.302960,58.924847,5.150924,7.274779,58.924847,5.150924,3.998887,57.911602,3.174517,3.643009,55.851738,3.034595,3.643009,55.851738,5.295435,3.998887,57.911598,5.155515,5.158450,55.851738,1.519154,5.298369,57.911598,1.875032,7.279369,57.911602,1.875032,7.419290,55.851738,1.519154,7.419290,55.851738,6.810878,7.279369,57.911602,6.454999,5.298369,57.911602,6.454999,5.158450,55.851738,6.810878,8.934732,55.851738,3.034595,8.578854,57.911602,3.174518,8.578854,57.911602,5.155515,8.934732,55.851738,5.295434,3.631946,52.232254,3.031311,3.615490,47.731865,3.078831,3.618338,47.724873,5.389040,3.631986,52.232109,5.302357,5.199051,47.745274,1.497859,5.155294,52.232513,1.508316,7.429556,52.232800,1.513508,7.603024,47.760201,1.656425,7.419795,47.737785,6.936042,7.423768,52.232395,6.824149,5.154235,52.232208,6.824666,5.167885,47.729450,6.945454,9.081119,47.778713,3.259274,8.949479,52.232986,3.036574,8.944792,52.232738,5.301911,8.932367,47.764133,5.381154,20.985931,45.614414,3.459317,20.940250,45.480022,5.606457,22.329248,45.359600,1.854093,24.603243,45.078907,1.792924,24.621342,44.769497,7.303060,22.295229,45.047077,7.225978,26.256113,44.839191,3.503879,26.261852,44.709785,5.807554,1.043470,32.463959,9.301449,5.446695,36.973961,9.467166,1.250158,37.126423,5.964483,10.928643,43.560108,17.301991,11.539122,42.295273,18.686031,12.340069,41.328209,17.448978,11.729589,42.593048,16.064938,11.180668,40.844398,19.376122,9.789659,39.458450,19.230112,11.026962,38.399399,17.716619,12.056702,39.916046,18.141321,8.530491,41.126442,19.150816,10.190417,42.269634,19.264036,9.577096,43.540359,17.873550,7.830531,42.576675,17.563908,10.745502,40.102211,14.017082,11.683762,41.398911,14.987329,12.297081,40.128185,16.377813,11.445490,38.651890,15.603985,8.151330,42.852863,15.515790,9.762702,43.782249,16.161390,10.638737,42.853897,14.926591,9.388606,41.793903,14.002302,8.352434,38.213882,18.726952,6.816943,36.883846,17.710957,8.365986,35.805515,16.130232,9.768825,37.075142,17.067131,1.873100,37.855576,14.376666,7.638938,34.871517,12.943440,5.168882,38.451073,10.993448,5.243996,31.357975,12.617258,4.908603,35.115887,15.905409,5.305984,38.533390,17.708267,7.001680,39.894852,18.691116,6.293373,41.350510,17.098751,4.425842,39.972408,16.151148,8.286153,37.557480,12.435341,9.583463,38.713917,13.251810,10.286791,37.252502,14.844656,8.973915,36.014782,14.014539,4.953972,40.300930,14.038047,6.700830,41.621948,14.999548,8.122199,40.488964,13.339247,6.695390,39.326275,12.435244,1.141699,34.418869,12.973587,0.538633,34.444187,7.298905,6.240433,36.350941,10.486206,6.754831,33.588383,12.078051,1.351583,37.710026,9.489221,2.842505,38.510593,6.680871,2.857583,31.375097,11.316751,5.590723,32.893509,13.573164,0.224136,35.858727,11.353081,6.876017,33.989555,12.338572,3.918142,38.185066,8.983435,3.306141,33.339996,13.847090,2.954785,36.498306,15.771214,7.103849,36.653214,11.445950,2.751418,38.797001,12.300148,6.779470,34.345528,14.701653,12.986581,34.684055,12.846575,11.014765,34.684055,12.846575,11.014765,34.948174,11.103799,12.986580,34.948170,11.103800,9.710690,35.687302,12.848297,9.354812,37.597034,12.908216,9.354813,37.649750,10.685571,9.710690,35.870422,11.081800,10.870254,37.546967,14.348694,11.010174,35.590137,13.999975,12.991171,35.590137,13.999975,13.131091,37.546967,14.348694,13.131092,37.654205,9.134586,12.991171,35.956009,9.850222,11.010174,35.956009,9.850222,10.870255,37.654205,9.134587,14.646533,37.597038,12.908217,14.290655,35.687302,12.848297,14.290654,35.870426,11.081800,14.646533,37.649750,10.685572,9.344265,39.083618,12.829280,9.344265,40.347370,12.744184,9.344265,40.162823,10.422775,9.344266,39.080505,10.374298,10.865870,47.442520,8.811403,13.135681,42.339333,13.803123,13.141752,40.572422,8.504747,10.865661,40.497738,8.978058,14.658400,45.578842,8.719080,14.657077,41.198498,10.334517,9.344265,42.030880,12.385611,9.346547,42.553795,8.558364,10.865662,40.361012,14.196836,10.865662,39.081123,14.352092,13.135681,39.081123,14.352092,13.135681,40.361012,14.196836,13.135681,39.981422,8.779439,13.135681,39.074867,8.663344,10.865664,39.074867,8.663345,10.865662,39.981422,8.779439,14.657078,40.347370,12.744184,14.657078,39.083618,12.829280,14.657078,39.080505,10.374298,14.657078,40.162823,10.422775,10.865662,44.702526,13.102887,13.135681,46.646667,11.511313,13.135681,40.582134,8.716522,10.865662,40.660583,8.323018,14.657076,43.768951,11.723741,14.657076,42.489281,8.938841,9.344267,45.097630,10.456156,9.344264,41.955597,9.775123,13.135681,44.702526,13.102876,10.865662,40.582130,8.716522,14.657076,41.955597,9.775122,9.344266,43.768951,11.723753,10.865662,42.339333,13.803123,13.135681,40.497738,8.978056,14.657077,42.030880,12.385611,9.344264,41.198498,10.334517,10.865664,46.646667,11.511694,13.135681,40.660583,8.323015,14.657076,45.097630,10.455751,9.344267,42.489281,8.938867,13.137759,47.445995,8.808912,10.869411,40.571918,8.502621,14.660285,42.559292,8.560830,9.345113,45.570374,8.721229,13.329808,42.059944,9.017334,14.764982,43.595028,8.129411,14.705503,46.021530,6.411304,13.205901,47.380157,5.385569,10.873232,47.268181,5.447838,9.368658,45.741112,6.440056,9.410848,43.422943,8.030836,10.982435,42.042747,8.948253,19.324810,41.121655,8.796227,17.037706,41.108589,8.793915,15.527177,43.048519,8.307582,15.502482,45.761047,7.638565,16.988077,47.263443,7.263326,19.278307,46.961964,7.267157,20.739586,45.377872,7.678252,20.761154,42.979889,8.345749,19.319759,42.387100,8.772545,16.998760,42.348213,8.766518,15.505630,44.090820,7.737069,15.434960,46.058620,6.108462,16.859215,46.877235,5.014728,19.190132,46.606930,5.023943,20.540840,45.564888,6.216631,20.603973,43.916637,7.840076,20.356384,21.935303,0.079631,11.460922,21.865475,6.462011,9.209770,21.811413,4.781453,9.500175,21.764174,1.085005,13.971968,21.897491,7.215889,15.640819,24.686058,7.212909,17.419924,24.597246,7.206676,20.933134,21.936081,4.947014,19.179688,21.818645,6.697162,14.719165,24.515427,-1.594475,11.816390,24.514036,-0.629112,21.879139,22.070061,2.334231,17.462406,24.526873,-1.252726,8.721462,21.766535,2.913206,15.703133,21.868137,7.409086,17.537027,21.815708,7.358860,14.579163,21.765621,-1.654602,11.742198,21.763897,-0.657730,17.401079,21.773043,-1.344719,20.437250,18.772350,-0.014598,11.432573,18.735153,6.549742,9.122615,18.706902,4.851295,9.407022,18.683216,1.060418,13.996494,18.752613,7.362582,21.081324,18.773380,4.866317,19.359726,18.714571,6.767576,21.978432,18.840353,2.208685,8.614991,18.684006,2.961240,16.480072,16.878244,3.084507,17.293669,16.895899,-1.288616,20.291500,16.897415,0.139323,21.753170,16.898680,2.137090,20.953724,16.898592,4.643325,19.355940,16.898348,6.584766,17.692438,16.898169,7.373841,15.832581,16.897655,7.480178,14.098608,16.895819,7.183511,11.566457,16.892948,6.342673,9.320601,16.890553,4.753181,8.839743,16.889658,3.033017,9.589805,16.890430,1.221766,11.712492,16.892170,-0.527458,14.407377,16.894384,-1.553297,10.247737,16.872633,3.012594,12.121304,16.874378,2.895618,14.438999,16.876669,2.824519,18.545700,16.878746,3.650945,19.836700,16.878904,4.081058,17.125908,16.877686,-0.566061,19.826540,16.878176,0.695425,21.106300,16.878574,2.292359,20.422674,16.879137,4.369406,19.038282,16.879557,6.051779,17.563087,16.879507,6.677150,15.889748,16.878843,6.742825,14.249690,16.876921,6.462040,11.877981,16.874313,5.705248,9.866133,16.872374,4.399299,9.479528,16.871828,3.075833,10.110312,16.872578,1.610288,12.042936,16.874247,0.094013,14.503995,16.876343,-0.819168,15.757514,18.738888,7.611740,17.657904,18.712984,7.527865,14.466406,18.685968,-1.769737,11.639355,18.683969,-0.735420,17.386421,18.690475,-1.479416,20.486277,17.507824,-0.071147,11.417179,17.492353,6.600452,9.070891,17.481277,4.893283,9.351133,17.473269,1.048778,14.014738,17.500122,7.451940,21.173944,17.509022,4.808823,19.475687,17.489231,6.808097,22.037354,17.531395,2.126247,8.551604,17.473011,2.993782,20.344948,24.799458,0.143988,11.430448,24.684771,6.401713,9.216089,24.595253,4.713896,9.519883,24.515690,1.075019,13.917432,24.736816,7.090843,20.842503,24.799911,5.083506,19.014040,24.602037,6.664341,21.871321,25.025837,2.482183,8.744521,24.520197,2.840145,15.600572,25.325880,7.099741,17.353725,25.200829,7.140421,14.857493,25.094193,-1.637787,11.829719,25.094046,-0.686926,17.589914,25.109741,-1.252993,19.111567,35.849396,13.544410,18.191719,35.420341,12.903393,19.234911,35.540119,11.990978,19.983116,35.923756,12.782813,17.271872,35.849396,13.544410,16.400322,35.923756,12.782813,17.148525,35.540119,11.990978,17.271872,36.260334,10.351431,18.191719,35.687813,11.047059,16.400322,36.160915,11.165913,19.111567,36.260330,10.351431,19.983116,36.160915,11.165913,16.391979,36.533813,13.551985,15.640757,37.421074,12.923223,15.734962,36.599945,11.982726,16.123236,38.427185,13.793436,15.535314,39.382088,12.856033,15.353356,38.495823,11.820838,16.123236,38.519039,9.722998,15.640757,37.531906,10.905386,15.535314,39.398335,10.488022,16.391979,36.846035,10.321903,17.102617,37.336750,14.255486,18.191719,38.407879,14.538737,17.056709,39.365612,14.357549,18.191719,36.405762,14.162046,19.991459,36.533813,13.551985,19.280821,37.336750,14.255486,20.260202,38.427185,13.793436,19.326729,39.365612,14.357549,20.260202,38.519039,9.722998,19.280821,37.562069,9.479464,18.191719,38.516869,8.940861,19.326729,39.398746,8.845592,19.991459,36.846031,10.321903,18.191719,36.777836,9.685539,17.102617,37.562069,9.479464,17.056709,39.398746,8.845592,20.742682,37.421078,12.923223,21.030081,38.495827,11.820838,20.848125,39.382088,12.856033,20.648476,36.599945,11.982726,20.742682,37.531906,10.905386,20.848125,39.398335,10.488022,16.114893,39.945763,13.771959,15.535314,40.452309,12.790545,15.342120,39.947365,11.642111,16.114893,41.203743,13.579041,15.535313,41.941357,12.552052,15.342120,41.137985,11.611138,16.114893,40.882072,9.394773,15.535314,40.399803,10.356503,15.535313,41.505383,10.451000,16.114893,39.940353,9.298003,17.035912,47.277157,8.385750,16.112486,46.530819,9.139420,17.056709,42.039692,13.973067,18.191719,42.813759,13.972836,20.268545,42.645542,13.200865,19.312056,47.018940,8.386906,19.326729,42.039692,13.975374,19.326147,40.672096,8.732490,20.267359,41.277660,8.445422,19.326729,41.108227,8.944662,18.191719,40.879517,8.803053,16.114893,41.153965,9.497336,17.050951,40.668137,8.731960,17.056709,41.108227,8.944662,20.815235,45.290882,8.317923,20.848125,41.941357,12.554434,21.041317,42.133865,11.337413,20.821770,42.641518,8.458622,20.848125,41.505383,10.451077,15.525365,45.579418,8.306328,15.342442,44.029270,8.624664,15.532848,42.667873,8.447657,17.056709,40.453033,14.297426,18.191719,41.208546,14.372641,18.191719,39.944565,14.544655,20.268545,39.945763,13.772036,19.326729,40.453033,14.297951,20.268545,41.203743,13.581426,20.268545,40.882072,9.394774,19.326729,40.346348,8.635162,18.191719,40.822269,8.582569,20.268545,39.940353,9.298003,18.191719,39.938236,8.464033,17.056709,40.346352,8.635164,20.848125,40.452309,12.791087,21.041317,41.137985,11.611680,21.041317,39.947365,11.642128,20.848125,40.399803,10.356520,16.114893,44.342308,12.572349,18.191719,46.667400,11.465978,20.268545,45.844791,10.970308,20.268545,41.063507,9.063543,18.191719,40.461708,8.351713,16.114893,41.324883,8.442030,21.041317,43.810848,9.639263,15.342120,42.987026,10.718575,17.056709,45.790794,12.409409,19.326729,45.771889,12.409353,19.326729,40.668285,8.507093,17.056709,40.668285,8.507254,20.848125,44.534904,11.176061,20.848125,42.313648,9.380499,15.535314,44.554440,11.176202,15.535314,42.314278,9.380748,18.191719,44.846687,13.268427,20.268545,44.339539,12.572414,18.191719,40.478363,8.635054,16.114893,41.063507,9.063569,21.041317,42.986397,10.718573,16.114893,42.645542,13.198481,20.268545,41.153965,9.497336,15.342120,42.133865,11.336872,19.326729,43.595711,13.498241,17.056709,40.634193,8.889254,20.848125,41.677258,10.093628,15.535313,42.991386,12.070600,17.056709,43.595711,13.497718,19.326729,40.634193,8.889255,20.848125,42.991386,12.071141,15.535313,41.677258,10.093611,16.114893,45.936947,10.970628,20.268545,41.324883,8.441223,15.342120,43.831791,9.639856,18.190445,47.301392,9.333878,20.266197,46.244278,9.139559,18.191938,40.313358,8.534178,16.113787,41.277702,8.445915,21.037754,43.961258,8.625288,17.056709,46.909267,10.204490,19.326729,40.594177,8.286865,20.848125,45.139332,9.523804,15.535314,42.528965,8.586712,19.326729,46.783825,10.204264,17.056709,40.594177,8.287579,20.848125,42.524784,8.585518,15.535314,45.268955,9.524509,24.239077,54.382538,2.373620,23.319229,54.886497,3.121822,24.362421,54.886497,4.165015,25.110626,54.382538,3.245169,22.399382,54.382538,2.373619,21.527832,54.382538,3.245169,22.276035,54.886497,4.165015,22.399382,54.382538,5.956413,23.319229,54.886497,5.208209,21.527832,54.382538,5.084864,24.239077,54.382538,5.956413,25.110626,54.382542,5.084864,21.519354,53.693615,2.364742,20.763912,52.847706,3.059258,20.861847,53.790577,4.162648,21.249098,51.696789,2.081678,20.674793,50.250458,2.940423,20.464760,51.698589,4.087549,21.248751,51.694267,6.217825,20.763855,52.847706,5.237430,20.673670,50.236786,5.202442,21.519346,53.693615,5.964218,22.230326,52.847725,1.613546,23.329002,51.694218,1.329037,22.199638,50.222973,1.531838,23.319513,53.790581,1.708261,25.120493,53.693615,2.365275,24.417364,52.847721,1.614054,25.438080,51.691048,2.100569,24.512810,50.193737,1.538224,25.438208,51.688538,6.238477,24.417360,52.847721,6.715980,23.329144,51.690701,7.007997,24.514833,50.161201,6.870763,25.120493,53.693615,5.964757,23.319511,53.790581,6.621773,22.230267,52.847725,6.715441,22.199938,50.190380,6.853216,25.887974,52.847717,3.075914,26.217106,51.689354,4.170413,26.089144,50.168610,3.079460,25.777792,53.790581,4.165015,25.887974,52.847717,5.254117,26.089745,50.154995,5.352638,21.321777,48.475178,2.136343,20.800713,45.603359,4.509366,21.429585,45.271347,6.579948,23.359774,48.360641,1.394032,25.544701,48.286228,2.221438,25.657463,44.734886,6.724250,23.365866,48.244576,7.167438,26.339039,48.201057,4.343124,18.875042,33.871147,9.120334,19.768240,32.403183,9.536522,18.345964,30.746292,8.890167,17.541786,32.342308,8.690907,16.578119,30.566181,8.683220,15.304139,31.908722,9.292963,16.042351,33.680710,8.892563,14.189455,34.925529,9.276173,15.568882,36.465328,9.093781,17.508007,35.182549,8.920240,20.294790,35.196877,9.301270,19.070362,36.452477,9.086901,20.104628,42.791420,0.577681,20.036896,43.526527,1.058300,19.265669,43.571903,0.659410,19.343452,42.275845,-0.057437,20.019974,45.421886,3.028676,19.175989,46.225121,3.946450,18.078575,45.709652,2.605100,19.196337,44.882835,1.685485,16.657610,43.774109,0.634901,18.108410,44.105488,0.819012,16.916897,45.039989,1.749426,15.906406,44.691719,1.527119,15.464121,43.959949,0.913273,15.144241,43.241425,0.279191,16.457815,42.465542,-0.290684,18.032698,41.134064,-0.697588,14.993956,40.991642,-1.034718,20.478870,40.763428,-0.452255,3.389414,44.158978,4.663870,3.618115,45.748989,5.570063,4.285882,44.145420,6.970190,3.671995,42.835373,6.352323,4.712657,40.284855,8.551924,3.324966,40.394356,5.788345,3.742052,40.976151,7.086371,3.824152,40.261921,2.709553,3.460637,41.028038,4.055423,4.212529,44.302662,2.200943,3.600349,45.780319,3.171161,3.565593,42.962051,3.582203,24.936283,30.597111,5.683071,24.721972,31.941702,7.235352,25.688593,33.296711,6.194411,25.533989,31.862644,4.793197,26.087320,35.874332,6.362533,26.129501,34.606285,4.991213,25.274326,34.626839,7.386949,26.102797,35.968845,3.698805,25.258768,34.593613,2.073620,25.621437,33.058712,3.445497,24.314751,30.825848,1.987291,24.705051,29.966974,3.830026,20.293507,41.844727,9.446563,20.660421,42.489391,9.438536,21.475254,42.191185,9.306491,21.281910,41.083885,9.336077,21.430523,43.694820,7.886481,22.272318,44.069572,7.532277,23.293331,43.182491,8.111282,22.052437,43.016380,8.596215,24.235613,41.038918,8.586093,22.869686,42.153870,8.894066,24.483322,42.477421,8.161065,25.640656,41.731518,7.690297,25.619728,39.767353,7.720154,22.908085,39.934753,8.967115,20.439102,39.906765,9.198441,9.577999,42.758091,0.579149,9.192568,43.279724,0.912129,7.973061,42.826664,0.742129,8.143831,41.804947,0.310023,8.607332,44.807529,1.983389,7.694664,45.929417,1.672755,6.427093,44.534744,1.184988,7.549326,43.868351,1.142976,5.223820,45.846169,1.479102,5.222655,43.291370,1.436917,6.121223,40.516167,0.541895,5.166497,41.399937,1.483019,9.072658,40.718033,-0.330175,14.805387,43.956726,0.947405,13.642221,43.922604,0.803087,13.767563,42.445076,-0.143671,12.216135,44.698929,1.120617,14.387233,45.207699,1.539000,13.370416,45.995766,1.767550,10.997043,43.711636,0.947088,11.062299,45.825310,1.970976,10.344847,44.861031,1.733459,10.008719,43.503441,1.025593,10.643039,42.240303,0.205030,11.965343,41.090950,-0.518196,24.456833,36.317196,0.945202,22.815397,35.168457,-0.527044,23.620777,32.902107,0.451882,22.032202,36.953125,-0.959841,20.649965,36.106712,-1.800602,21.012646,34.587795,-1.718079,4.978706,28.299118,6.318358,5.738618,28.146751,3.609865,4.673028,30.058168,2.284859,3.527547,29.629072,4.916024,2.326924,31.609034,4.674740,3.012593,29.801413,7.525293,4.841736,29.843573,10.605217,4.653027,28.972685,8.621450,8.585666,43.448738,8.442003,8.982916,42.904572,8.959615,8.861362,42.640682,9.451617,8.225171,42.890968,9.176709,9.413201,43.869144,7.876321,10.034971,43.268196,8.794219,9.373075,43.067535,8.723679,9.032157,43.737427,7.995955,9.359035,42.477882,9.423197,9.671122,42.087204,9.856417,8.950419,42.198891,9.934868,14.744575,42.251617,9.453815,14.898930,42.673862,9.301453,15.442292,42.666008,9.229023,15.553685,42.250195,9.388505,14.833572,43.109619,8.930006,15.163683,42.899006,9.009723,14.262037,42.746632,9.287180,15.484536,43.050518,8.744184,15.188663,43.367794,8.488741,15.411626,43.742237,8.100508,15.974624,43.146614,8.669818,21.204372,42.994835,8.978666,20.734758,43.033447,9.203416,20.716419,43.317383,8.853078,21.004307,43.482243,8.457790,20.103416,42.524174,9.436575,20.390089,43.051762,9.215410,20.510572,43.378208,8.616904,19.893873,42.954830,9.044175,21.377295,44.252888,2.346261,20.966549,44.668537,3.593447,20.693790,44.785202,3.212491,20.858122,44.295452,2.378093,19.966780,44.368088,1.459415,20.361124,44.094299,1.657123,20.646448,44.327209,2.171221,20.478094,44.758656,2.399970,20.406992,43.308659,1.193012,20.590895,43.882195,1.754434,14.854101,46.556343,4.075883,14.312721,46.622704,2.814949,14.890806,45.838356,2.440076,15.135514,46.102436,3.388431,15.293470,44.614742,1.562021,14.950200,44.696003,1.562791,15.870486,45.856663,3.105525,15.294436,46.279518,4.330134,15.420296,45.363422,2.529984,9.256587,45.148815,3.225742,9.121899,44.412567,1.969477,9.490784,45.014702,2.884538,9.871583,44.143234,1.576435,9.300085,43.858669,1.404687,9.802517,45.220139,2.392237,9.578428,44.390129,1.906105,9.190154,44.741856,5.930165,9.401670,44.044743,7.479988,9.125471,44.452854,6.535304,8.947513,45.990421,5.600882,9.152154,45.070019,5.081038,8.846419,44.660877,6.924278,9.184897,46.070305,3.584209,9.271124,44.982342,4.610575,9.533460,45.613747,3.896913,9.363036,45.633236,5.343843,15.162799,44.440556,7.365264,15.235123,45.316410,6.398436,15.444337,44.430660,7.474728,14.971936,43.812706,8.309229,14.882080,44.303013,7.719369,15.010372,45.305580,6.366236,14.789614,46.187500,5.388405,15.086724,45.974773,5.342422,15.360712,46.079437,5.521375,20.720598,44.834194,6.292734,20.512402,45.502068,5.594425,20.470364,45.325954,4.255356,20.747450,44.858345,5.036515,20.882217,44.597569,5.589725,21.022114,44.895424,3.978747,21.040661,44.078247,7.267324,20.860214,44.327435,6.892231,20.981594,44.689415,6.051043,20.600670,44.246506,7.530590,20.644081,43.872669,7.950486,16.965237,42.780350,8.797026,16.821774,46.448120,3.950610,13.277872,47.094959,3.762330,24.605307,44.099026,1.863038,26.308552,43.629101,5.997924,24.628727,43.711849,7.520837,16.087605,38.959831,9.221620,17.568443,37.697327,9.103731,14.036032,37.878624,9.252407,14.867569,40.140892,9.357334,17.751545,40.155121,9.240513,19.178335,38.805183,9.120506,20.546482,37.551586,9.052776,14.429100,35.682274,-2.665607,16.083496,34.483017,-2.831200,17.821783,35.983963,-2.490379,16.248453,37.061745,-2.358364,14.121518,32.661255,-2.837864,15.927664,31.272106,-2.840887,17.895203,33.366730,-2.701088,19.378292,35.039108,-2.333160,19.414890,37.217117,-1.913898,26.249332,38.496006,6.557117,26.366547,37.252781,5.215496,25.587790,37.177727,7.467243,26.464128,39.833263,5.430820,25.535812,40.125793,2.736303,26.246700,38.680595,3.958066,25.628710,37.475426,2.445673,7.276455,40.042198,9.721989,6.247694,39.153526,9.553357,10.028954,39.740528,9.803137,8.895260,38.560188,9.769471,12.404553,40.326324,9.534595,11.714146,38.936031,9.484641,13.311237,39.256973,9.370465,24.369871,36.052475,8.206547,23.935108,33.493080,8.314014,22.851545,35.019577,8.871225,23.378307,30.500862,8.156354,22.400114,32.251816,9.158916,21.339222,33.821484,9.439924,20.730190,30.667311,9.521723,21.733717,36.356133,9.039493,2.782625,34.598953,2.798466,4.579616,35.636448,0.764430,3.331252,37.595200,2.118001,1.359806,33.758568,5.344462,3.777120,32.334480,2.090909,6.647886,31.579399,-0.096021,5.716334,33.720566,0.041116,7.733484,35.364285,-1.213509,6.469623,36.828201,-0.536423,8.925309,33.726448,-1.635994,10.989293,35.484566,-2.249109,9.666884,36.833778,-1.725534,8.170670,29.776659,-0.489979,10.328640,32.034599,-1.957790,12.457150,34.066849,-2.616737,12.039768,30.569494,-2.293806,12.914169,36.916245,-2.294998,24.516850,39.006992,1.397154,23.381802,37.921700,0.133351,22.595528,40.540077,0.682212,22.002537,39.323730,-0.355410,20.889782,38.260059,-1.202435,21.786095,28.732948,8.717813,19.995081,27.033680,8.526789,19.083479,28.783363,9.046204,23.884375,28.946438,6.329932,22.457222,27.311937,7.007578,13.793531,29.131544,-2.467134,15.459247,27.565708,-2.374491,17.685703,29.594215,-2.464762,10.156918,28.632109,-1.145252,11.889273,27.457142,-1.534290,7.215286,27.924133,1.287426,8.945047,27.191730,0.200193,7.217382,27.114252,5.109770,7.624425,26.785276,2.772189,8.396526,27.619564,8.125460,10.211266,27.180983,8.339682,8.801503,26.517502,5.975291,12.069988,28.610746,9.818596,13.319473,27.907505,9.287832,11.610470,26.646732,8.195745,14.696961,29.854477,9.573535,15.685308,28.570786,8.760146,14.354069,26.966389,8.515387,17.264614,28.940311,8.086042,16.279821,27.284746,7.777730,17.809416,27.246920,8.019768,16.440052,39.572971,-1.481592,14.716867,38.214920,-2.047503,17.939236,38.313904,-1.765297,19.460096,39.546192,-1.099857,4.045441,39.717964,7.626573,3.377058,39.267742,6.521693,5.800233,38.157677,9.549750,3.095849,39.746845,4.430873,2.871609,38.973602,3.372006,24.520552,38.531387,8.313488,23.186920,37.402466,8.708410,21.870481,38.644009,9.000509,4.301625,39.372093,1.533991,5.177743,38.208649,0.424342,8.367355,38.093735,-1.101498,7.093079,39.305817,-0.342302,10.222964,39.457283,-1.021776,11.513420,38.167648,-1.704208,13.279824,39.530743,-1.438425,16.270111,41.152435,9.351803,15.091225,41.730564,9.445066,16.647537,42.083157,9.275387,17.952614,42.284904,9.128217,16.040228,42.687031,9.051563,16.926876,42.706898,8.937922,19.128256,42.242641,9.305588,19.110878,42.811367,8.926743,19.236399,41.149677,9.327429,26.311180,40.866020,6.732684,26.344429,42.332092,6.447494,26.510460,41.747719,5.384691,26.301121,43.790592,3.654202,25.692238,43.261147,2.671056,26.331623,42.511909,3.922163,26.511131,42.947178,5.044782,26.288113,41.052650,4.104238,5.711077,41.086761,9.163919,5.345649,42.946938,8.273311,6.646924,42.211174,9.249277,4.440015,41.823315,7.956400,7.369191,43.331470,8.665202,6.333752,44.270241,8.004358,7.404769,45.813511,7.245297,8.165598,44.351578,7.692427,8.561223,41.018833,10.017677,7.991364,42.079388,9.792011,9.515255,41.683968,10.080179,10.885203,41.103325,9.845394,10.863742,41.953163,9.629997,12.241312,42.299587,9.407255,10.025349,42.507690,9.251697,11.040872,42.784515,9.173298,13.594412,42.107525,9.483077,13.384200,42.919933,9.266783,13.795835,41.190510,9.486115,23.847914,41.512779,1.765273,22.431791,42.690998,1.338636,25.536533,42.072109,2.803706,24.368189,42.916496,1.885303,22.304367,44.481934,1.933883,21.865088,43.573879,1.594221,23.247494,43.658951,1.578501,20.853693,41.864193,0.373790,20.958477,42.861931,1.099420,3.381548,41.819324,5.335313,4.164127,42.070072,2.481911,25.713308,42.936478,7.184658,8.510762,43.729626,1.233114,6.510849,42.730129,0.912569,12.128891,46.610538,2.541742,10.091254,46.169128,3.002729,10.894349,46.905891,3.881809,14.374894,43.353626,9.034544,20.852283,43.713245,8.096820,20.074589,43.311981,8.621523,20.940559,43.685558,1.682908,15.148148,45.102985,2.139313,18.120951,42.721119,8.926603,19.298254,42.838409,8.797062,5.194198,45.768501,7.198839,11.043324,43.034592,9.022094,12.268542,43.163265,9.218060,13.452645,43.074520,9.141044,7.304992,36.136101,10.845129,7.803468,37.733246,10.136074,8.967599,36.290035,10.500805,10.332819,37.239334,9.845808,11.242750,35.813160,10.228612,11.978357,37.360794,9.448692,12.704027,35.805725,9.710804,13.547070,30.812994,10.078577,14.014053,33.052635,9.725785,12.931320,33.870636,10.202738,12.239711,31.333862,10.559049,10.591520,28.994595,10.154968,11.389588,33.960777,10.717386,10.707598,31.723412,11.007269,9.820823,32.641808,11.219601,9.584343,34.380093,10.947639,8.165901,32.102787,11.455596,7.943089,34.120583,11.321966,6.908387,31.813606,11.955835,6.628537,30.436886,11.268208,6.484479,29.170958,10.174368,8.296200,30.494547,11.190926,9.151044,29.467581,10.580984,6.949115,28.183672,8.707483,23.671944,28.004915,4.011963,19.843040,32.236004,-2.048979,21.461384,30.326265,-0.853115,22.344427,28.320753,0.550805,19.117746,27.766773,-1.657143,16.827293,26.310062,-1.955563,17.855516,25.549225,-1.310507,20.009932,26.512579,-0.642714,19.013174,17.487980,-0.888962,21.574253,25.753536,1.204295,20.764969,25.993904,0.229691,11.342638,25.642136,6.677053,12.892483,17.495953,7.132735,9.965412,25.274031,5.683319,9.050217,25.536165,4.837748,8.713796,25.124695,3.650927,17.350298,17.060022,-1.504547,20.443743,17.069136,-0.025982,8.616555,17.053640,3.011778,8.811159,17.472950,2.079098,9.404182,17.054272,1.093643,10.404146,25.094122,0.111973,13.899402,25.730690,7.260096,14.915236,17.501400,7.630952,14.041799,17.065777,7.398164,11.454706,17.061508,6.541011,16.726492,17.490894,7.751478,15.813255,17.066181,7.695531,15.690286,25.709053,7.150330,17.397141,25.580492,7.240785,18.691154,17.488451,7.334654,17.742125,17.064255,7.584542,22.548197,27.107134,1.732160,22.285990,26.291468,2.847310,22.593653,26.710938,4.895365,21.888174,17.523979,3.461174,19.818569,25.284508,6.135491,21.133667,25.860064,5.581452,19.077175,25.539207,7.008371,16.216705,25.094971,-1.635595,14.981012,25.532698,-1.758879,13.039465,17.475794,-1.410210,11.840092,25.541082,-0.821751,11.598265,17.055946,-0.720728,8.493941,25.483198,2.710521,8.492786,26.164209,1.551419,8.327722,26.026545,3.927063,9.359232,25.521366,0.870436,9.127893,17.056633,4.864182,12.877970,26.116903,7.768610,15.087298,26.243109,7.615479,18.455978,26.079042,7.800764,16.758373,26.289309,7.319993,21.972494,17.076715,2.110902,10.359335,26.301203,-0.325572,13.533218,26.326807,-1.739668,21.134119,17.070362,4.750649,14.380322,17.058172,-1.775415,19.468609,17.064604,6.755840,10.036417,26.006784,6.471746,20.618797,26.142811,7.186136,7.208718,58.548649,2.373620,6.288871,59.052605,3.121822,7.332064,59.052605,4.165015,8.080268,58.548649,3.245169,5.369023,58.548645,2.373619,4.497472,58.548649,3.245169,5.245677,59.052605,4.165015,5.369023,58.548649,5.956412,6.288870,59.052605,5.208209,4.497472,58.548645,5.084863,7.208718,58.548649,5.956412,8.080267,58.548649,5.084863,4.489129,57.859726,2.365277,3.737906,57.013832,3.075914,3.832115,57.956688,4.165015,4.220387,55.851315,2.096533,3.632465,54.290203,3.030006,3.450507,55.852165,4.165015,4.220387,55.851315,6.233499,3.737907,57.013832,5.254117,3.632466,54.290203,5.300025,4.489129,57.859726,5.964756,5.199768,57.013832,1.614054,6.288869,55.852165,1.326653,5.153859,54.290203,1.508610,6.288869,57.956688,1.708261,8.088611,57.859726,2.365275,7.377971,57.013832,1.614054,8.357354,55.851315,2.096532,7.423881,54.290203,1.508610,8.357354,55.851315,6.233499,7.377973,57.013836,6.715980,6.288870,55.852165,7.003379,7.423881,54.290203,6.821423,8.088610,57.859726,5.964756,6.288869,57.956688,6.621772,5.199769,57.013836,6.715980,5.153859,54.290203,6.821423,8.839834,57.013832,3.075914,9.127234,55.852165,4.165015,8.945276,54.290203,3.030006,8.745625,57.956688,4.165015,8.839834,57.013832,5.254117,8.945276,54.290203,5.300025,4.212416,52.233040,2.088230,3.627290,49.944027,3.043055,3.438367,52.231499,4.167371,3.627692,49.942577,5.323339,4.212207,52.232784,6.244139,5.168217,49.946594,1.505676,6.292009,52.231995,1.316638,8.372391,52.233582,2.095821,7.480637,49.949463,1.557598,7.422767,49.945412,6.848693,8.365247,52.233177,6.243357,6.289093,52.231651,7.018430,5.157617,49.943565,6.853862,8.987308,49.951321,3.095686,9.139330,52.232273,4.168807,8.940441,49.948849,5.318882,9.164660,47.777367,4.307336,8.590138,47.756321,2.336234,6.387420,47.753197,1.348097,4.223290,47.738449,2.092757,3.410544,47.726856,4.250995,4.219153,47.725868,6.333145,6.296741,47.734730,7.159575,8.358445,47.731014,6.321867,21.493906,45.518398,2.538444,20.558258,48.506721,3.979689,21.316763,48.392071,6.265371,23.401960,45.194599,1.566182,25.645140,44.973515,2.473907,25.548960,48.203396,6.406117,23.408291,44.859566,7.482282,26.447136,44.732353,4.683672,20.868395,46.838795,3.086727,20.849884,46.751308,5.291579,22.282188,46.668106,1.704926,24.574862,46.481304,1.699065,24.587433,46.273079,7.137646,22.272404,46.459518,7.058118,26.201366,46.320629,3.346508,26.205208,46.233509,5.636748,1.635231,31.455126,7.475845,1.804434,31.803974,10.338355,6.959061,33.702713,11.860501,5.063929,37.743168,8.897758,4.016105,38.063637,7.924103,1.826599,36.811543,4.201970,2.605949,38.879154,5.677646,10.319792,43.655571,17.751904,11.298140,43.032246,18.061222,11.408506,43.206440,16.685514,10.431080,43.817165,16.608812,10.889366,42.475487,19.043207,11.540320,41.518959,19.123615,12.054456,41.868114,18.149971,12.412128,40.748428,16.793234,12.161770,42.010654,16.746685,12.289411,40.626587,17.977694,11.842556,41.928516,15.501931,11.180172,42.924797,15.462891,10.638065,41.494854,19.511448,10.556636,40.176792,19.413078,11.692709,40.307716,18.897406,9.127988,40.258537,19.430555,9.019840,38.778557,18.963381,10.447770,38.811375,18.622766,11.397459,38.321854,16.659870,11.631979,39.176693,18.024801,10.368683,37.673870,17.359879,12.257060,39.811199,17.258690,9.402512,41.781658,19.306099,8.073578,41.941181,18.486431,7.697996,40.457783,18.913486,9.827355,43.009544,18.689213,9.523658,43.803764,16.984930,8.728136,43.178883,17.777193,7.847176,42.912220,16.526772,6.995194,41.913902,17.320133,10.116605,40.975674,13.756093,11.301387,40.834385,14.499609,11.207761,39.288216,14.679920,10.138397,39.345051,13.588716,11.142656,42.120110,14.732173,12.117028,40.713318,15.580824,11.975761,39.437164,16.028515,10.841481,37.888016,15.182018,8.977069,43.449455,15.831978,8.690236,42.452778,14.638207,7.374975,42.186527,15.234259,10.171476,43.459518,15.448554,10.052413,42.449356,14.443700,8.723535,41.082752,13.630806,7.628269,39.023079,18.960327,7.662292,37.629013,18.363373,9.096390,37.539921,18.059309,6.024049,37.670769,17.958887,5.870421,36.022461,16.854111,7.622815,36.240059,17.058453,8.868757,35.698132,15.068370,9.133861,36.490974,16.703741,7.546943,35.068653,15.425198,10.211407,36.945862,15.934110,4.168529,37.584637,16.833416,2.265388,37.192738,15.173405,1.982996,38.418724,13.402159,3.156446,38.992588,15.339802,7.608171,37.031719,11.923724,7.560580,35.634689,12.106702,7.365899,34.432007,13.845615,8.244535,35.392532,13.470661,3.831851,39.512741,13.230539,3.917874,38.847858,11.394219,5.884092,38.790169,11.748303,3.190530,30.381670,10.055662,4.059358,31.205290,12.119967,5.480928,30.762796,12.080939,6.265476,39.303688,18.340076,4.743705,39.344551,17.061262,6.536301,40.712105,18.025492,6.333921,41.686909,16.046473,5.507632,40.755188,16.756596,4.467891,40.316895,15.101749,7.594754,38.496323,12.178852,8.993194,38.143436,12.900979,8.749182,36.674255,13.094795,8.924361,39.618141,13.019550,10.050558,37.887768,13.913485,9.693762,36.658661,14.490592,5.950207,41.037392,14.651419,5.753031,39.953648,13.101408,7.328388,41.197937,14.060464,7.479052,39.932625,12.985655,2.099380,33.861332,13.558422,0.616486,33.346684,8.268393,0.767035,35.731422,6.491117,5.174391,37.473679,9.596972,6.567209,35.413559,10.971935,6.214268,32.089821,12.647699,1.945452,38.209156,5.944568,4.542839,32.971207,13.844051,0.847200,33.466415,11.222641,0.130142,35.119968,9.342730,5.813436,36.508232,9.979670,6.731462,33.681931,12.227583,1.148451,37.362976,7.702090,3.344707,38.252075,7.796564,2.883570,32.415112,12.666870,5.280798,32.131454,13.129345,0.498098,35.063633,12.201614,0.472757,36.772327,10.434320,6.875102,35.096634,11.456600,6.387446,33.211105,13.061136,2.598854,38.296761,8.891235,3.860703,35.795406,16.050240,6.289865,37.677814,11.046551,5.935740,34.588867,15.419040,0.820280,36.751980,13.096207,7.180863,34.415516,12.539801,4.526953,38.267117,10.094158,4.021949,34.212807,14.900347,1.875816,35.404976,14.495268,6.683070,36.425507,10.978102,1.878448,38.189754,11.096096,6.112705,33.627186,14.061048,12.920520,34.985268,13.544409,12.000672,34.556217,12.903392,13.043864,34.675991,11.990979,13.792068,35.059631,12.782812,11.080826,34.985268,13.544409,10.209277,35.059631,12.782812,10.957479,34.675991,11.990978,11.080826,35.396206,10.351431,12.000672,34.823685,11.047060,10.209276,35.296791,11.165913,12.920520,35.396206,10.351432,13.792068,35.296791,11.165913,10.200933,35.669685,13.551984,9.449711,36.556950,12.923222,9.543919,35.735817,11.982725,9.932189,37.563065,13.793435,9.344266,38.518059,12.856033,9.162312,37.631710,11.820837,9.932189,37.654922,9.722996,9.449711,36.667782,10.905385,9.344267,38.534313,10.488020,10.200933,35.981907,10.321902,10.911572,36.472622,14.255485,12.000671,37.543762,14.538737,10.865662,38.501583,14.357548,12.000672,35.541634,14.162046,13.800411,35.669689,13.551984,13.089773,36.472622,14.255485,14.069155,37.563068,13.793435,13.135682,38.501583,14.357548,14.069155,37.654922,9.722998,13.089773,36.697945,9.479465,12.000671,37.652756,8.940861,13.135683,38.534733,8.845589,13.800411,35.981907,10.321901,12.000672,35.913708,9.685539,10.911572,36.697945,9.479464,10.865662,38.534733,8.845591,14.551635,36.556950,12.923222,14.839035,37.631710,11.820838,14.657078,38.518059,12.856033,14.457427,35.735817,11.982725,14.551634,36.667782,10.905385,14.657078,38.534313,10.488021,9.923845,39.082069,13.773860,9.344266,39.589947,12.804476,9.151073,39.083672,11.642562,9.923845,40.357582,13.637983,9.344266,41.218231,12.613345,9.151072,40.291626,11.625156,9.923845,40.034821,9.394773,9.344266,39.537262,10.356954,9.344264,40.781338,10.452988,9.923846,39.076664,9.298001,10.867714,47.480286,7.179679,9.923804,46.765823,8.755726,10.865662,41.316597,14.024602,12.000671,42.385872,13.988270,14.077497,42.217655,13.257422,13.156437,47.515038,7.160353,13.135683,41.316597,14.024603,13.196390,40.974892,8.805475,14.083096,41.302296,8.481531,13.135681,40.383270,8.944662,12.000671,40.450287,8.803052,9.923843,40.724945,9.497335,10.903156,40.969852,8.784106,10.865661,40.383270,8.944662,14.670298,45.763115,7.692564,14.657078,41.218231,12.613345,14.850270,41.705769,11.350889,14.689166,42.848808,8.484054,14.657078,40.781338,10.452989,9.352713,45.678440,7.705573,9.152998,44.076523,8.667166,9.367073,42.793850,8.456367,10.865662,39.590675,14.309137,12.000671,40.362389,14.388074,12.000671,39.080872,14.545151,14.077499,39.082069,13.773860,13.135683,39.590675,14.309137,14.077499,40.357582,13.637983,14.077499,40.034821,9.394773,13.135683,39.483627,8.635160,12.000671,39.974812,8.582567,14.077499,39.076664,9.298000,12.000671,39.074547,8.464031,10.865662,39.483627,8.635160,14.657078,39.589947,12.804476,14.850271,40.291626,11.625156,14.850271,39.083675,11.642562,14.657078,39.537262,10.356954,9.923845,44.332912,12.579525,12.000671,46.838688,11.637138,14.077497,46.063801,11.117127,14.077497,41.050102,9.063622,12.000671,40.461708,8.352552,9.923845,41.324883,8.444689,14.850269,43.855282,9.672317,9.151073,42.974388,10.720041,10.865662,45.837757,12.470581,13.135681,45.837757,12.470461,13.135681,40.668282,8.507614,10.865662,40.668282,8.507614,14.657076,44.577972,11.207586,14.657076,42.315014,9.382236,9.344266,44.577972,11.207712,9.344266,42.315014,9.382242,12.000671,44.838654,13.275113,14.077497,44.332912,12.579507,12.000671,40.464951,8.635079,9.923845,41.050102,9.063622,14.850269,42.974388,10.720036,9.923845,42.217655,13.257422,14.077497,40.724945,9.497335,9.151072,41.705769,11.350889,13.135681,43.462036,13.509428,10.865661,40.500092,8.889254,14.657076,41.543365,10.094061,9.344266,42.857704,12.084528,10.865662,43.462036,13.509428,13.135681,40.500092,8.889253,14.657076,42.857704,12.084528,9.344264,41.543365,10.094061,9.923846,46.063801,11.117689,14.077497,41.324883,8.444681,9.151073,43.855282,9.672461,12.001817,47.646618,8.843751,14.079762,46.772308,8.752174,12.005813,40.346531,8.540970,9.926476,41.300171,8.478312,14.851372,44.084885,8.667555,10.865664,47.160999,10.270333,13.135681,40.594177,8.290149,14.657078,45.394695,9.589322,9.344267,42.532894,8.620808,13.135683,47.160999,10.269730,10.865662,40.594177,8.290156,14.657076,42.532894,8.620678,9.344267,45.394695,9.590050,12.163465,41.921936,9.041628,14.269116,42.586639,8.756330,14.888233,44.838898,7.294356,14.164498,46.925713,5.686264,12.038959,47.467449,5.349647,9.915398,46.707241,5.767210,9.210026,44.569885,7.250165,9.995214,42.522408,8.643644,20.229372,41.821426,8.625198,18.198957,40.892803,8.852510,16.078362,41.822815,8.611645,15.352712,44.474102,7.956368,16.035473,46.733955,7.397505,18.149672,47.333015,7.224235,20.191071,46.271240,7.413288,20.923685,44.273617,8.010027,20.165478,43.035252,8.427762,18.209543,42.124641,8.883219,15.996268,43.033184,8.392982,15.368076,45.201458,6.933306,15.873714,46.612888,5.404764,18.072210,46.871624,4.898759,20.055717,46.149109,5.445770,20.706758,44.823006,7.079834,19.323006,41.753891,8.771074,17.019854,41.728554,8.766459,15.519533,43.572712,8.056651,15.471641,45.937870,6.886113,16.923603,47.129822,6.081027,19.232819,46.821442,6.088429,20.637627,45.480267,6.963595,20.679455,43.448826,8.131346,18.918823,24.607183,-0.622524,21.427158,22.043354,1.070309,12.854106,24.708105,6.870529,10.089665,21.845648,5.728786,8.787594,21.779432,3.791720,8.980127,24.517258,1.997173,10.409899,21.763617,0.139929,14.774199,24.738756,7.169447,16.530931,24.623318,7.231325,18.256449,24.594793,7.048689,21.649208,24.949989,3.884941,19.979645,21.852842,5.975874,15.926832,21.766657,-1.708158,13.332956,24.514633,-1.234587,20.329304,23.844131,0.125067,11.461037,23.752430,6.419604,9.237327,23.681074,4.742376,9.533150,23.618061,1.089578,13.949863,23.794207,7.138393,15.670063,23.754404,7.295655,17.469345,23.684216,7.267368,20.864555,23.844746,5.008060,19.081264,23.688055,6.667361,14.650666,23.618658,-1.604120,11.792863,23.617105,-0.626913,21.847580,24.023598,2.411689,17.422104,23.628035,-1.279770,8.759296,23.621473,2.879095,18.923323,21.820921,-0.702150,12.893267,21.879879,6.954190,8.965446,21.764893,2.046245,14.839455,21.899120,7.337948,16.603025,21.831068,7.425031,18.417564,21.814322,7.140727,21.691370,22.025120,3.694175,13.220997,21.764702,-1.268127,21.512287,18.826784,0.978006,10.033217,18.724583,5.803184,8.680033,18.690540,3.856052,10.314009,18.683325,0.078254,20.149570,18.731701,5.981368,15.840785,18.686964,-1.844484,15.734155,19.901531,7.524189,17.605682,19.864319,7.454692,14.514690,19.827461,-1.719282,11.684139,19.825579,-0.701208,17.392097,19.833210,-1.420687,20.401384,19.949364,0.026486,11.445627,19.898254,6.511497,9.161355,19.858995,4.821122,9.448247,19.825270,1.071512,13.986326,19.921921,7.298971,21.016567,19.950285,4.900367,19.281826,19.866474,6.736664,21.934305,20.045832,2.262559,8.662103,19.826729,2.940857,16.905573,16.877855,0.627214,19.358471,16.878304,1.654525,20.601116,16.878592,2.823874,20.151592,16.878984,4.231959,19.184994,16.879299,5.380640,17.809891,16.879242,5.665607,16.068895,16.878653,5.543797,14.337659,16.876850,5.272657,12.018510,16.874357,4.768855,10.101599,16.872522,3.937157,9.820956,16.872135,3.067203,10.272310,16.872686,2.081716,12.141081,16.874348,1.024452,14.508259,16.876471,0.374790,15.743845,16.895294,-1.642181,18.884787,16.896511,-0.640379,21.306641,16.898268,1.056626,21.616224,16.898741,3.353398,20.098093,16.898413,5.788005,18.604483,16.898302,7.084702,16.726921,16.897959,7.494055,14.980809,16.897011,7.368978,12.999865,16.894356,6.862650,10.201334,16.891666,5.628486,8.898214,16.889824,3.850296,9.082525,16.889915,2.191993,10.448427,16.891184,0.262820,13.115929,16.893282,-1.136148,10.973272,16.873392,2.942486,13.380175,16.875507,2.858712,15.419835,16.877649,2.875615,17.556145,16.878569,3.373529,19.334570,16.878839,3.890730,15.712509,16.877184,-0.891226,18.571156,16.877962,0.015524,20.718626,16.878368,1.452322,20.991087,16.878820,3.254981,19.691795,16.879419,5.386839,18.365400,16.879580,6.449198,16.708069,16.879286,6.767366,15.088680,16.878078,6.634462,13.212067,16.875584,6.170243,10.632429,16.873215,5.097256,9.521948,16.871895,3.710539,9.674919,16.872086,2.403258,10.881305,16.873308,0.789869,13.333032,16.875299,-0.449718,17.218882,16.877663,-0.981636,20.076565,16.878250,0.373275,21.445581,16.878735,2.187011,20.693001,16.879328,4.507912,19.182936,16.879732,6.345794,17.611290,16.879623,7.069986,15.852285,16.878901,7.166148,14.172419,16.876930,6.876926,11.720620,16.874268,6.064963,9.590854,16.872229,4.595380,9.153350,16.871614,3.056114,9.851180,16.872395,1.397468,11.878607,16.874104,-0.257676,14.456953,16.876257,-1.240221,18.979101,18.714731,-0.818668,12.891307,18.743073,7.066253,8.868635,18.683315,2.064279,14.884054,18.754032,7.518885,16.677227,18.720535,7.626055,18.583630,18.712376,7.261655,21.813780,18.817944,3.555434,13.110394,18.684944,-1.357983,21.562618,17.526567,0.920780,10.000459,17.487947,5.846111,8.615779,17.475315,3.896952,10.255263,17.473820,0.043362,20.257961,17.494995,5.979996,15.783411,17.477854,-1.927036,15.776317,18.077171,7.682208,17.699934,18.060373,7.586761,14.427544,18.041277,-1.810349,11.603310,18.039181,-0.762960,17.381853,18.044781,-1.526688,20.466118,18.099072,-0.047665,11.422066,18.073074,6.580524,9.091434,18.053677,4.875583,9.373840,18.038071,1.051488,14.004677,18.085537,7.413782,21.133444,18.100183,4.838910,19.422428,18.061495,6.792458,22.013947,18.144165,2.165325,8.577072,18.038322,2.977643,21.429873,24.981096,1.150450,10.071295,24.652222,5.672702,8.813333,24.541824,3.713180,10.450121,24.514235,0.161942,19.842323,24.659655,6.016362,16.056150,24.516541,-1.620724,19.013237,25.224298,-0.617670,12.778297,25.352253,6.879520,8.873234,25.094908,1.913086,14.716198,25.396626,7.090042,16.494133,25.239758,7.118283,18.165092,25.193811,7.048481,21.750851,25.699577,4.102883,13.412606,25.094189,-1.298471,20.385506,25.173944,0.147182,11.382132,25.035833,6.398365,9.166435,24.927807,4.691895,9.479620,24.831394,1.049374,13.879240,25.098343,7.061291,20.847939,25.174240,5.166707,18.965729,24.934425,6.677054,21.927279,25.448097,2.547946,8.699028,24.837008,2.798712,15.614086,25.036440,7.148917,17.381668,24.928667,7.164601,14.785273,24.830269,-1.608866,11.823786,24.829033,-0.650648,17.513643,24.843828,-1.248163,19.489737,35.949944,13.432768,18.667994,35.781670,13.626121,18.191719,35.548172,13.308344,18.191719,35.372139,12.459389,18.724342,35.437725,11.991081,19.701376,35.709129,11.990674,20.068308,35.908863,12.402634,19.861029,35.980175,13.108173,17.715445,35.781670,13.626121,16.893702,35.949944,13.432768,16.522409,35.980175,13.108173,16.315128,35.908863,12.402634,16.682062,35.709129,11.990674,17.659096,35.437725,11.991080,16.893702,36.335133,10.467337,17.715445,36.201191,10.268299,18.191719,35.913311,10.613874,18.191719,35.513088,11.513216,16.315128,36.035763,11.567530,16.522409,36.294315,10.816093,18.667994,36.201191,10.268299,19.489735,36.335133,10.467337,19.861029,36.294312,10.816093,20.068308,36.035763,11.567530,16.522409,36.235035,13.432768,16.281755,36.917728,13.656422,15.873234,37.397018,13.359224,15.501102,37.446899,12.443069,15.566841,37.012375,11.966208,15.969663,36.242062,11.989046,16.148266,37.892513,13.777623,16.114893,38.934593,13.792562,15.776805,39.375885,13.357878,15.390419,39.388275,12.298033,15.342120,38.979061,11.757549,15.387064,37.981678,11.882998,16.114893,38.989697,9.582666,16.148266,38.030544,9.873915,15.873234,37.554333,10.435041,15.501102,37.504101,11.413637,15.390419,39.396660,11.088297,15.776805,39.398956,9.934509,16.281757,37.174183,10.177049,16.522409,36.579483,10.462615,16.615820,37.353951,14.035451,17.635618,37.324928,14.390992,18.191719,37.859276,14.505030,18.191719,38.923843,14.549973,17.612139,39.364910,14.501676,16.549578,39.367378,14.118361,18.191719,36.044235,13.942094,18.191719,36.833500,14.325253,19.861029,36.235035,13.432768,20.101683,36.917728,13.656422,19.767618,37.353951,14.035451,18.747820,37.324928,14.390992,20.235172,37.892513,13.777623,20.268545,38.934593,13.792562,19.833860,39.367378,14.118361,18.771299,39.364910,14.501676,20.268545,38.989697,9.582666,20.235172,38.030544,9.873915,19.767618,37.568512,9.708864,18.747820,37.553852,9.340836,18.191719,38.022980,9.112844,18.191719,38.989285,8.784118,18.771299,39.398605,8.696768,19.833860,39.398899,9.098870,20.101681,37.174183,10.177049,19.861029,36.579483,10.462614,18.191719,36.460442,9.931479,18.191719,37.137520,9.479115,16.615820,37.568512,9.708865,17.635618,37.553852,9.340836,16.549578,39.398899,9.098870,17.612139,39.398605,8.696768,20.510204,37.397018,13.359224,20.882336,37.446899,12.443069,20.996374,37.981682,11.882998,21.041317,38.979061,11.757549,20.993019,39.388275,12.298033,20.606634,39.375885,13.357878,20.413776,36.242058,11.989046,20.816597,37.012375,11.966208,20.510204,37.554333,10.435042,20.882336,37.504101,11.413637,20.606634,39.398956,9.934509,20.993019,39.396660,11.088297,16.114893,39.691284,13.780273,16.114893,40.183369,13.753162,15.776805,40.453682,13.291245,15.390419,40.447483,12.229683,15.342120,40.177677,11.629338,15.342120,39.701092,11.665298,16.114893,40.805073,13.657007,16.114893,41.614670,13.489378,15.776804,41.978783,13.000383,15.390418,41.881527,12.060123,15.342120,41.491791,11.586003,15.342120,40.772034,11.620420,16.114893,41.099812,9.466867,16.114893,40.621464,9.323099,15.776805,40.379158,9.772718,15.390419,40.420383,10.986153,15.390418,41.657318,10.989223,15.776804,41.355930,9.950680,16.114893,40.147377,9.266213,16.114893,39.703384,9.364210,17.595882,47.395046,8.389137,16.525436,47.034557,8.376822,16.105267,46.608673,8.762667,16.114893,46.429771,9.523138,16.549578,42.023758,13.722521,17.612139,42.050007,14.133500,18.191719,42.435921,14.088330,18.191719,43.219780,13.839909,20.268545,42.334442,13.302710,20.268545,42.973404,13.085022,19.815264,46.688320,8.379290,18.758831,47.257721,8.389571,18.771299,42.050007,14.134730,19.833860,42.023754,13.725596,18.773470,40.503887,8.758213,19.828400,40.965649,8.688794,20.263798,41.304424,8.547775,20.268545,41.289566,8.354240,19.833860,41.151588,9.182995,18.771299,41.090408,8.802290,18.191719,41.027176,8.795105,18.191719,40.702164,8.785154,16.114893,41.230927,9.527089,16.114893,41.053440,9.432240,16.539835,40.962318,8.687162,17.611025,40.501389,8.758116,17.612139,41.090408,8.802290,16.549578,41.151588,9.182995,20.957455,44.705688,8.309589,20.578083,45.816284,8.340098,20.606634,41.978783,13.003459,20.993019,41.881527,12.061661,21.041317,41.988983,11.450956,21.041317,42.269600,11.202433,20.587429,41.970909,8.545113,20.960814,43.355267,8.381146,20.993019,41.657314,10.989532,20.606634,41.355930,9.950678,15.758448,46.174194,8.332081,15.388638,44.905907,8.295153,15.343404,44.087841,8.465340,15.342120,43.987995,8.807816,15.392503,43.415661,8.367045,15.769057,41.979252,8.537934,16.549578,40.453167,14.053453,17.612139,40.452965,14.446157,18.191719,40.804733,14.443593,18.191719,41.634762,14.287436,18.191719,39.688484,14.549973,18.191719,40.182808,14.528697,20.268545,39.691284,13.780273,20.268545,40.183369,13.753469,19.833860,40.453167,14.054152,18.771299,40.452965,14.446438,20.268545,40.805077,13.658545,20.268545,41.614670,13.492454,20.268545,41.099812,9.466866,20.268545,40.621464,9.323098,19.833860,40.351555,8.896122,18.771299,40.344593,8.483780,18.191719,40.587135,8.494688,18.191719,41.004383,8.676809,20.268545,40.147377,9.266212,20.268545,39.703384,9.364210,18.191719,39.702934,8.539772,18.191719,40.140198,8.427267,16.549578,40.351555,8.896123,17.612139,40.344593,8.483780,20.606634,40.453682,13.291944,20.993019,40.447483,12.230032,21.041317,40.772034,11.620770,21.041317,41.491791,11.586702,21.041317,39.701092,11.665298,21.041317,40.177677,11.629409,20.606634,40.379158,9.772718,20.993019,40.420383,10.986223,16.114893,44.852173,12.297575,16.114893,43.827271,12.782990,18.191719,46.361053,12.049251,18.191719,46.896267,10.863038,20.268545,45.609184,11.483825,20.268545,46.007778,10.443418,20.268545,41.155941,8.904600,20.268545,40.996071,9.209703,18.191719,40.497547,8.414195,18.191719,40.414608,8.320258,16.114893,41.298550,8.580305,16.114893,41.328518,8.345531,21.041317,43.702686,9.963526,21.041317,43.873680,9.319454,15.342120,43.281666,10.511902,15.342120,42.693592,10.895117,16.549578,45.586296,12.214540,17.612139,45.916344,12.525901,19.833860,45.561089,12.214460,18.771299,45.906261,12.525872,19.833860,40.894695,8.581271,18.771299,40.546829,8.487311,16.549578,40.894695,8.581493,17.612141,40.546829,8.487396,20.606634,44.939568,11.587446,20.993019,44.065941,10.727774,20.606634,41.734360,9.016349,20.993019,42.929977,9.805544,15.776805,44.964771,11.587568,15.390419,44.078545,10.727936,15.776805,41.734360,9.016613,15.390419,42.932495,9.805762,18.191719,44.246414,13.501337,18.191719,45.434452,12.963551,20.268545,43.827271,12.783298,20.268545,44.841084,12.297534,18.191719,40.487415,8.696657,18.191719,40.496311,8.565587,16.114893,40.996071,9.209703,16.114893,41.155937,8.904703,21.041317,42.693592,10.895185,21.041317,43.279144,10.511827,16.114893,42.973404,13.083485,16.114893,42.334442,13.299633,20.268545,41.053440,9.432240,20.268545,41.230927,9.527088,15.342120,42.269600,11.202084,15.342120,41.988983,11.450257,19.833860,43.491455,13.267932,18.771299,43.662479,13.637585,16.549578,40.766594,9.072442,17.612139,40.568527,8.782150,20.606634,41.300461,9.681104,20.993019,42.071457,10.556337,15.776804,43.191586,12.539774,15.390418,42.744534,11.566124,16.549578,43.491459,13.267233,17.612139,43.662479,13.637304,19.833860,40.766594,9.072442,18.771299,40.568527,8.782150,20.606634,43.191586,12.540474,20.993019,42.744534,11.566473,15.776804,41.300461,9.681105,15.390418,42.071457,10.556269,16.114893,46.143478,10.443832,16.114893,45.664642,11.484031,20.268545,41.328518,8.344479,20.268545,41.298550,8.579787,15.342120,43.904522,9.320258,15.342120,43.715290,9.963900,18.191719,47.203037,9.791412,18.186623,47.363178,8.878979,20.268545,46.194904,9.522713,20.259155,46.271496,8.764350,18.191719,40.325752,8.417078,18.192596,40.348412,8.659950,16.114893,41.289566,8.355347,16.110466,41.304592,8.546772,21.041317,43.934616,8.806787,21.027060,43.999657,8.470963,16.549578,46.661430,10.097750,17.612141,47.044949,10.267900,19.833860,40.889954,8.274775,18.771299,40.421555,8.316896,20.606632,45.663803,9.750635,20.993019,44.551918,9.279808,15.776805,41.875145,8.419165,15.390419,43.234737,8.796814,19.833860,46.494175,10.097406,18.771299,46.978046,10.267788,16.549578,40.889954,8.275766,17.612141,40.421555,8.317270,20.606634,41.875145,8.417931,20.993019,43.218010,8.795719,15.776805,45.831059,9.751216,15.390419,44.635544,9.280642,24.617245,54.288517,2.495706,23.795504,54.448040,2.288425,23.319229,54.714340,2.655359,23.319229,54.989944,3.632394,23.851852,54.989944,4.165015,24.828884,54.714340,4.165015,25.195818,54.448040,3.688740,24.988539,54.288517,2.867000,22.842953,54.448036,2.288425,22.021212,54.288517,2.495706,21.649920,54.288517,2.867000,21.442638,54.448036,3.688740,21.809572,54.714340,4.165015,22.786606,54.989944,4.165015,22.021212,54.288517,5.834326,22.842953,54.448036,6.041606,23.319229,54.714340,5.674673,23.319229,54.989944,4.697639,21.442638,54.448036,4.641291,21.649920,54.288517,5.463033,23.795504,54.448040,6.041606,24.617245,54.288517,5.834326,24.988539,54.288517,5.463033,25.195820,54.448040,4.641291,21.649920,54.002068,2.495706,21.408730,53.301575,2.252918,20.997972,52.839100,2.578392,20.622955,52.856316,3.587403,20.691853,53.354805,4.155546,21.097172,54.164631,4.165015,21.273096,52.302124,2.110888,21.247063,51.012028,2.073604,20.920883,50.247051,2.477477,20.525360,50.251190,3.458593,20.457651,51.013985,4.054028,20.502087,52.311340,4.117663,21.246380,51.001953,6.224367,21.272928,52.302124,6.197703,20.997896,52.839100,5.730149,20.622925,52.856316,4.699588,20.524734,50.244221,4.613187,20.919512,50.227222,5.752585,21.408697,53.301575,6.072825,21.649920,54.002068,5.834326,21.742836,52.839108,1.844418,22.764294,52.856342,1.474419,23.324911,52.311398,1.360381,23.334457,50.996273,1.324868,22.755455,50.213257,1.388226,21.694740,50.232651,1.764683,23.319229,54.164631,1.942958,23.320366,53.354813,1.540141,24.988539,54.002068,2.495706,25.235289,53.301575,2.255053,24.907547,52.839104,1.846531,23.880981,52.856339,1.474401,25.393166,52.302120,2.121560,25.469496,50.989094,2.104341,25.041500,50.189156,1.784945,23.936640,50.198570,1.389281,25.470013,50.979053,6.261755,25.393166,52.302120,6.208469,24.907547,52.839104,6.483502,23.880974,52.856339,6.855634,23.324873,52.311398,6.969671,23.335178,50.982204,7.033085,23.938776,50.164082,7.014829,25.043198,50.159775,6.629418,25.235289,53.301575,6.074980,24.988539,54.002068,5.834326,23.319229,54.164635,6.387073,23.320358,53.354813,6.789894,21.742760,52.839108,6.481348,22.764256,52.856342,6.855634,21.694138,50.203190,6.594277,22.756670,50.178741,7.007820,25.654650,52.839104,2.589115,26.027910,52.856331,3.608914,26.160011,52.311378,4.165015,26.255146,50.976898,4.186604,26.235332,50.161461,3.637861,25.842829,50.176476,2.568217,25.541286,54.164635,4.165015,25.951332,53.354813,4.165015,25.654650,52.839104,5.740915,26.027910,52.856331,4.721117,25.843756,50.156723,5.858204,26.235626,50.154522,4.798408,21.287136,49.377182,2.100651,21.363453,47.589909,2.194312,20.848604,45.172863,4.776919,20.742323,46.157135,4.278030,21.418922,44.751629,6.754478,21.415051,45.887482,6.455611,23.349907,49.306721,1.362514,23.370747,47.424850,1.432134,25.519398,49.262547,2.168947,25.570145,47.315563,2.282008,25.680187,44.146370,6.817441,25.631500,45.433472,6.640086,23.353819,49.236378,7.106966,23.378563,47.256031,7.238036,26.311398,49.209984,4.272961,26.366486,47.192753,4.424084,19.484591,33.876873,9.320843,18.238750,33.850903,8.926746,19.587263,31.591347,9.505428,19.939129,33.158897,9.520911,17.885178,30.743725,8.633536,18.847467,30.732910,9.177046,17.557810,33.093956,8.749050,17.505316,31.552290,8.608171,16.135632,30.440498,8.920715,17.013269,30.658117,8.519244,15.032852,32.684746,9.285250,15.529724,31.108942,9.265267,16.802238,33.758633,8.796961,15.336378,33.576473,9.058685,13.875231,35.670765,9.289439,14.472004,34.185829,9.266983,16.559664,36.467705,9.046734,14.551997,36.469955,9.173480,17.534132,34.509556,8.858104,17.488583,35.835236,8.980238,20.204184,34.548576,9.391659,20.368185,35.817726,9.210686,19.768009,36.435249,9.119697,18.317644,36.464363,9.051985,20.138674,43.059460,0.806066,20.107964,42.431271,0.306175,19.975876,43.718590,1.110331,20.113665,43.353313,1.004761,18.797058,43.313831,0.396749,19.641567,43.773777,0.921665,19.785480,42.093723,-0.045218,18.823273,42.529480,-0.019391,20.036057,45.674854,3.651081,20.021626,45.146114,2.485939,18.638031,46.334267,3.838363,19.662392,46.079838,4.125072,18.094259,45.311794,2.037824,18.064453,46.081314,3.205526,19.650570,44.882160,1.848492,18.675823,44.886093,1.574409,17.265944,43.428425,0.369678,16.151237,44.056442,0.899611,18.110941,44.516563,1.148303,18.100378,43.640804,0.508787,16.379551,45.127979,1.939476,17.506475,44.962650,1.607367,15.847885,44.476311,1.314736,15.934466,44.936295,1.801319,15.287575,43.826599,0.809911,15.623434,44.112835,1.021939,15.131739,42.839241,-0.046498,15.144634,43.542362,0.549635,17.187084,42.637070,-0.139626,15.769173,42.364250,-0.380690,18.054043,41.970295,-0.359819,18.013823,40.340733,-0.993399,14.924297,40.253784,-1.325806,15.055577,41.697128,-0.722534,20.303776,41.401596,-0.224524,20.656574,40.095875,-0.660187,3.389701,44.914047,4.518575,3.390113,43.481804,4.826220,3.882247,45.749363,6.089681,3.453064,45.751835,5.000979,4.317534,43.466518,7.227589,4.259731,44.904484,6.735803,3.476735,42.846321,5.693069,3.967252,42.839283,6.956944,4.862425,39.896271,8.692122,4.616014,40.637138,8.436472,3.341627,40.676826,5.702914,3.314404,40.130089,5.891541,4.096997,40.976109,7.741550,3.493332,40.985451,6.368973,3.962863,40.687855,2.662931,3.646124,39.870186,2.782856,3.347841,41.008823,4.830503,3.698795,41.066795,3.310109,4.220398,45.008808,2.155893,4.202803,43.673576,2.257452,3.442874,45.767776,3.777974,3.862135,45.794983,2.609102,3.823669,43.026321,2.919412,3.420332,42.910255,4.284481,24.693949,30.516718,6.288914,25.075905,30.699268,5.144535,24.880072,32.644440,7.308086,24.546364,31.216942,7.113650,25.848345,33.289871,5.556758,25.413280,33.300335,6.792682,25.317057,31.240458,4.768984,25.726683,32.548862,4.833286,26.230221,35.895950,5.756371,25.836395,35.870098,6.916383,26.024082,33.938820,4.935956,26.212112,35.265228,5.047693,25.378363,35.261730,7.397843,25.155558,33.983593,7.372524,25.862690,36.009758,2.978590,26.237347,35.943626,4.412949,25.081314,33.774612,1.995306,25.399723,35.354328,2.169047,25.816309,33.169151,4.176286,25.304838,32.951946,2.699384,24.000141,29.761177,2.097696,24.606018,31.879034,1.940513,24.985350,30.453985,4.382212,24.284115,29.389263,3.165035,20.322348,42.131752,9.464952,20.282717,41.471378,9.405580,20.827768,42.595787,9.379440,20.488806,42.389992,9.463711,21.864168,41.836700,9.271120,21.186729,42.480782,9.307206,20.790440,41.026588,9.350626,21.801544,41.186047,9.287919,21.426229,43.939598,7.507102,21.401554,43.495018,8.221874,22.805277,43.945080,7.676636,21.793833,44.190956,7.316229,23.218403,42.931664,8.324009,23.349129,43.474525,7.908883,21.653540,43.180019,8.561890,22.543556,42.848236,8.594353,23.394182,41.162579,8.893511,24.986897,40.951992,8.222973,23.010223,42.440575,8.723633,22.695454,41.815491,9.041903,25.138245,42.409351,7.851554,23.791325,42.571201,8.388300,25.615875,41.347713,7.763681,25.669178,42.064796,7.585677,25.632797,39.131516,7.646737,25.606409,40.363037,7.775355,22.705185,40.621716,9.073009,23.069008,39.257088,8.865406,20.360619,40.487068,9.274191,20.515211,39.301464,9.129404,9.605985,43.028805,0.732156,9.514772,42.393494,0.391521,8.955847,43.345066,0.964855,9.429539,43.230133,0.867745,7.464935,42.422035,0.668005,8.395243,43.160477,0.868124,8.783578,41.846008,0.217526,7.493428,41.807713,0.455670,8.712986,45.224564,2.238945,8.525487,44.464161,1.749841,7.071829,45.917328,1.433584,8.286854,45.907604,2.023663,6.418530,44.006371,1.103498,6.437519,45.154545,1.260277,8.044451,44.031101,1.325679,7.004479,43.702274,1.031898,4.686440,45.827881,1.744139,5.815236,45.866673,1.334566,5.818079,43.408901,1.166842,4.669769,43.190048,1.826710,6.427353,41.160801,0.617041,5.834405,39.894508,0.471370,4.556170,41.246513,2.009761,5.884399,41.597816,1.042621,9.256382,41.358917,-0.074044,8.876570,40.041447,-0.577318,14.640387,44.151943,1.067256,14.987984,43.817364,0.826575,13.037357,43.551323,0.609922,14.132759,44.207664,1.000674,14.442812,42.348820,-0.307616,13.057885,42.632359,0.083056,12.217417,43.967793,0.823667,12.201358,45.337418,1.409412,14.365852,45.638710,1.767982,14.430288,44.788452,1.352252,12.782274,45.929699,1.709294,13.905912,46.041599,1.885017,11.469999,43.431740,0.714049,10.616846,43.911598,1.150393,10.597506,45.776371,2.134153,11.597462,45.846378,1.822207,10.357828,44.431259,1.513817,10.294432,45.288025,1.986596,9.794737,43.319778,0.912709,10.188865,43.738834,1.162301,11.310970,42.517509,0.273818,10.019436,42.052334,0.169901,12.075228,41.948875,-0.115475,11.851308,40.282852,-0.875029,23.840275,36.470867,0.358577,25.025331,36.182995,1.586580,22.468052,34.300613,-0.754318,23.053492,35.937031,-0.330863,24.298969,32.860615,1.196311,22.843006,32.999393,-0.282801,21.435900,37.081879,-1.263746,22.618458,36.799831,-0.595390,20.526613,35.624287,-1.909847,20.741356,36.630627,-1.666786,21.401949,34.018581,-1.461935,20.665689,35.007504,-1.888716,5.579902,27.977943,6.249157,4.442203,28.635208,6.478784,5.803269,28.604258,2.437780,5.891953,27.818979,4.842933,4.053597,30.415976,2.785627,5.343539,29.701536,1.788003,3.696266,29.238382,5.803024,3.447511,30.150717,4.086745,1.807175,32.041992,5.467166,2.883990,31.188576,3.961699,3.464022,29.381893,7.079259,2.606352,30.253691,8.074518,5.189496,29.651136,10.387568,4.546457,30.079092,10.892913,4.267392,28.909874,7.686893,5.093799,29.167707,9.489107,8.775783,43.375584,8.457292,8.366793,43.489014,8.461308,9.021777,42.763435,9.148293,8.958406,43.078671,8.744556,8.711621,42.588242,9.558588,8.979068,42.663052,9.353062,8.139335,43.159084,8.865305,8.353718,42.670544,9.442728,9.615103,43.714672,8.173094,9.253112,44.005043,7.605630,10.031973,43.085323,8.884407,10.010694,43.399788,8.686047,9.147761,43.175083,8.604074,9.656539,42.966713,8.854098,9.080637,43.960815,7.696724,8.986029,43.505478,8.263944,9.612401,42.357136,9.502604,9.173062,42.588245,9.343473,9.504719,42.042561,9.952079,9.824155,42.145390,9.723810,8.725127,42.331062,9.824265,9.183280,42.088161,9.990255,14.545242,42.354595,9.442131,14.960052,42.160679,9.450293,15.066378,42.727352,9.239012,14.674799,42.590405,9.360172,15.655343,42.578217,9.246917,15.277884,42.723801,9.207387,15.323415,42.160801,9.422735,15.762005,42.348122,9.335202,15.012838,43.110825,8.826895,14.601295,43.092369,9.043278,15.167884,42.816078,9.116407,15.161280,42.993336,8.884706,14.264482,42.898392,9.214209,14.298326,42.603062,9.356039,15.311848,43.082115,8.730167,15.710104,42.999504,8.783630,15.198942,43.553509,8.310858,15.175053,43.220882,8.629030,15.568148,43.655968,8.205650,15.296683,43.776691,8.054832,16.000063,43.033539,8.754030,15.928130,43.271317,8.561382,21.103662,42.847446,9.150914,21.285149,43.153458,8.766863,20.666492,43.119831,9.151215,20.833868,42.897964,9.248727,20.762966,43.404049,8.674309,20.665880,43.231628,9.004566,21.143560,43.421032,8.478455,20.900932,43.506630,8.457832,19.987793,42.640553,9.381652,20.238239,42.406662,9.461733,20.537258,43.127094,9.157209,20.182634,42.928089,9.263344,20.678001,43.453072,8.540062,20.283281,43.272686,8.703764,19.931080,43.047947,8.909656,19.881590,42.856823,9.178148,21.432117,44.429626,2.558352,21.288797,44.102600,2.156700,20.816401,44.765366,3.866171,21.153334,44.629967,3.255512,20.699949,44.678570,2.857678,20.688404,44.867443,3.618747,20.984369,44.138325,2.195208,20.772327,44.435955,2.509496,19.942980,44.140511,1.291694,19.997684,44.609947,1.702409,20.484108,44.120461,1.815228,20.180523,44.030369,1.436139,20.680149,44.443115,2.344803,20.598034,44.212749,2.018034,20.289694,44.826248,2.230994,20.607241,44.668930,2.519841,20.542261,43.370838,1.309632,20.278601,43.259811,1.065736,20.568857,44.030254,1.854830,20.622173,43.687740,1.602194,14.667027,46.685867,4.008091,14.990829,46.445602,4.184526,14.329172,46.369347,2.390850,14.315645,46.795296,3.341709,15.045578,45.692825,2.595478,14.669564,45.963043,2.245799,15.114201,46.295555,3.812921,15.154171,45.836258,3.009543,15.182306,44.725815,1.698874,15.476653,44.469471,1.375467,14.774017,44.583675,1.391127,15.062981,44.764854,1.696475,15.800468,46.152020,3.691622,15.915213,45.533108,2.588669,15.188727,46.302303,4.321684,15.438871,46.295052,4.339305,15.628072,45.289749,2.356336,15.277468,45.447536,2.645300,9.109711,45.365009,2.918903,9.352036,45.075584,3.482701,9.351640,44.545391,2.147818,8.833076,44.297852,1.763693,9.461190,45.107162,3.260737,9.511641,44.879158,2.557010,9.712510,44.138687,1.633898,10.067975,44.115486,1.469900,9.052427,43.667629,1.220647,9.487115,44.014271,1.555628,9.667619,44.956997,2.366296,9.975647,45.470112,2.362345,9.594760,44.236534,1.760312,9.555041,44.553627,2.074348,9.214334,44.796921,6.121861,9.164824,44.692791,5.769562,9.600839,43.722904,8.006012,9.277287,44.410042,6.935973,9.127111,44.575489,6.074121,9.127072,44.319157,6.966167,9.087321,46.037971,5.087586,8.742931,45.884426,6.116715,9.144661,44.819714,5.352124,9.163140,45.474960,4.812544,8.676887,45.049446,6.767850,8.987329,44.371471,7.125046,9.083962,46.004757,3.086137,9.209023,46.077812,4.080364,9.199469,44.845299,5.101019,9.347898,45.088051,4.132766,9.637589,45.962017,3.997572,9.467959,45.328129,3.803905,9.257614,45.220722,5.866214,9.544672,46.023476,4.810223,15.136021,44.822208,6.917217,15.186057,44.091450,7.754440,15.291251,45.373226,6.414395,15.172970,45.253571,6.412839,15.579510,43.931232,7.937673,15.368530,44.928009,6.989343,14.800974,43.746128,8.509497,15.098367,43.815033,8.161041,14.937604,44.779449,7.146244,14.759996,43.875061,8.259224,15.057373,45.254036,6.388815,14.970234,45.327583,6.405718,14.630535,46.564270,4.780859,14.889523,45.749199,5.977145,15.094970,45.620560,5.889820,15.087008,46.236565,4.800057,15.325289,45.775211,6.011981,15.461219,46.290321,5.011066,20.680935,44.914284,6.428217,20.770142,44.736134,6.163409,20.356491,45.714127,5.053313,20.613209,45.247131,6.105649,20.584055,45.102154,4.184608,20.330313,45.575687,4.310962,20.784697,44.769650,5.531679,20.714382,44.907738,4.543164,20.857470,44.593502,5.820085,20.890779,44.680958,5.332795,20.921640,44.901814,4.527384,21.180109,44.835533,3.420792,20.952244,44.028618,7.428336,21.157362,44.152466,7.127021,20.844103,44.495552,6.470630,20.868412,44.154587,7.271282,21.124350,44.535019,6.523068,20.900377,44.797108,5.564765,20.659889,44.609566,7.073049,20.476160,43.879711,7.960979,20.482069,43.749310,8.143919,20.770039,43.944786,7.771486,17.577869,42.620438,8.883623,16.380510,43.044147,8.644926,16.234112,46.427803,4.126443,17.440313,46.443073,3.841415,12.686144,47.113796,3.716529,13.836578,47.020206,3.868060,25.185455,44.029617,2.172356,23.986679,44.173275,1.672533,26.062119,43.639915,6.495458,26.447536,43.633663,5.447735,24.007935,43.760963,7.677148,25.206177,43.680656,7.267905,16.886906,38.937893,9.190420,15.307094,38.990917,9.255900,17.518499,37.088451,9.072174,17.626289,38.302620,9.132381,14.322472,38.473721,9.266421,13.742458,37.248688,9.256857,14.948765,40.633999,9.389360,14.746440,39.606476,9.323862,17.719418,39.527149,9.201075,17.785265,40.796978,9.275839,18.443769,38.863068,9.140677,19.885704,38.746460,9.100159,20.495550,36.987770,9.079876,20.574131,38.117180,9.051737,14.351123,34.990707,-2.756422,14.505817,36.341816,-2.547043,16.965782,34.608879,-2.770000,15.183003,34.366798,-2.846962,17.845497,36.573624,-2.354010,17.811460,35.376667,-2.594076,15.416236,37.017250,-2.398956,17.070477,37.107666,-2.285992,14.044193,31.807343,-2.796993,14.197382,33.480785,-2.844238,16.914871,31.462910,-2.777292,14.942118,31.096251,-2.820730,17.855984,34.083008,-2.698292,17.916553,32.573006,-2.675760,19.994106,35.171738,-2.139492,18.639399,34.892769,-2.513063,18.660130,37.192505,-2.063540,20.133717,37.214535,-1.733366,26.383572,38.528549,5.964531,26.005255,38.477673,7.095714,26.327042,36.587021,5.160162,26.397617,37.915852,5.270752,25.621332,37.825615,7.512668,25.535978,36.534035,7.434051,26.445061,39.216103,5.382593,26.480156,40.407700,5.462251,25.588875,39.488598,2.672594,25.489634,40.718121,2.785740,26.382263,38.622147,4.650852,26.001274,38.748047,3.267900,25.583038,36.783665,2.360732,25.644512,38.155193,2.525090,7.380607,39.447952,9.721760,7.203778,40.649258,9.746320,5.655979,39.291752,9.290578,6.865021,39.014809,9.706127,10.230059,39.020557,9.684391,9.873477,40.397133,9.922201,8.184174,38.720119,9.796528,9.650482,38.391857,9.703027,12.442450,39.840595,9.487923,12.360588,40.872871,9.574892,11.189226,38.586800,9.522910,12.159898,39.258003,9.461590,12.814143,39.386436,9.413901,13.900553,39.138920,9.330280,24.965094,35.961452,7.841308,23.716938,36.151752,8.507797,23.296707,33.600349,8.708164,24.520819,33.395332,7.858083,22.950733,35.641979,8.800384,22.746246,34.372871,8.951019,22.779993,30.548923,8.680685,23.906752,30.469788,7.560309,22.521349,32.995735,9.108722,22.269489,31.456640,9.162634,21.982737,33.771538,9.279308,20.707136,33.853016,9.506002,20.045120,30.690897,9.533322,21.433825,30.637857,9.378378,22.383947,36.309120,8.920815,21.085432,36.389225,9.108006,3.490290,34.291294,1.976085,2.132008,34.921894,3.680350,4.727160,36.371883,0.632027,4.416537,34.851685,0.958453,2.672872,37.949291,3.068673,4.076998,37.286179,1.270184,1.316671,33.091164,5.816196,1.449190,34.474178,4.934605,4.002799,33.179108,1.613112,3.585863,31.526897,2.664634,6.962992,32.644905,-0.543985,6.364174,30.476431,0.462733,4.967467,33.841476,0.595134,6.480957,33.657425,-0.444284,7.914118,36.114342,-1.255856,7.521482,34.545231,-1.094259,5.667796,36.901474,-0.054571,7.272360,36.804821,-0.925253,9.787225,33.803391,-1.953135,8.084186,33.669746,-1.276320,11.136464,36.197155,-2.178488,10.832094,34.720230,-2.266396,8.870442,36.819248,-1.505846,10.466429,36.851631,-1.908062,9.147022,29.987930,-1.076099,7.198235,29.552681,0.223266,10.491230,32.981659,-2.115643,10.198172,31.090128,-1.766972,11.556789,33.977634,-2.444912,13.363724,34.160118,-2.740410,12.998318,30.750206,-2.545439,11.082285,30.382694,-1.965420,12.089338,36.892693,-2.191364,13.745036,36.943848,-2.367191,23.863991,39.099548,0.870763,25.121048,38.913681,1.975188,23.330698,37.290276,-0.006834,23.347639,38.547367,0.267124,22.942726,39.854530,0.539840,22.210165,41.227978,0.825025,22.594469,39.259190,-0.008803,21.411406,39.382431,-0.637234,20.863876,37.711941,-1.363722,20.873285,38.831112,-1.032492,21.565346,27.856331,8.414865,21.969475,29.669426,8.948523,19.360165,27.046751,8.563480,20.649652,27.052942,8.357477,19.241501,29.752668,9.261065,18.928894,27.873007,8.781460,23.607307,28.239994,5.967331,24.130840,29.701620,6.657465,21.905794,27.193930,7.588138,22.928022,27.454857,6.333331,13.712549,28.286802,-2.302181,13.878771,30.022371,-2.608822,16.379482,27.593239,-2.356667,14.544538,27.543913,-2.293388,17.818146,30.659729,-2.554985,17.510029,28.559328,-2.356865,10.223807,27.960911,-0.937796,10.114277,29.372284,-1.352514,12.751398,27.493645,-1.862200,11.065292,27.410301,-1.151815,7.644349,27.435282,1.302249,6.733980,28.498634,1.268099,9.577304,27.277349,-0.284082,8.414437,27.096762,0.737067,7.574628,26.869783,4.700637,6.817749,27.357050,5.610297,7.739620,26.889025,2.025614,7.668900,26.690228,3.561180,9.386540,27.768164,8.815408,7.399898,27.558056,7.302674,10.172976,26.836279,7.823249,10.263650,27.565304,8.852317,8.271439,26.552069,5.189047,9.435239,26.508718,6.698689,12.833395,28.954836,9.854166,11.238609,28.281755,9.659617,13.187534,27.314806,8.951854,13.438173,28.572002,9.575277,10.867148,26.576824,7.823789,12.347759,26.728464,8.445363,15.205021,30.084921,9.394592,14.141691,29.589186,9.711123,15.581360,27.788712,8.479052,15.724958,29.417799,9.000254,13.731414,26.891174,8.591759,14.923271,27.041899,8.370373,17.148708,28.098764,7.858529,17.365396,29.829731,8.302384,15.879309,27.206989,7.967651,16.654242,27.339144,7.654749,17.401527,27.317390,7.787539,18.261257,27.164454,8.271851,17.224546,39.595528,-1.372339,15.647020,39.546295,-1.564005,14.649487,37.595528,-2.237225,14.783844,38.852726,-1.833097,17.968239,38.933418,-1.521854,17.908104,37.726227,-1.988386,18.740330,39.584286,-1.180044,20.148281,39.495380,-0.998543,3.627208,39.818569,6.851451,4.541740,39.582550,8.320086,3.332522,39.573105,6.251796,3.459401,38.955292,6.835033,6.218775,37.317657,10.014658,5.411932,38.858425,9.174746,3.137492,39.830921,5.228078,3.191945,39.636322,3.654150,3.166914,39.237282,3.102260,2.548738,38.699081,3.715730,23.855501,38.569572,8.581190,25.127844,38.497772,7.977479,23.207767,37.990658,8.730185,23.126728,36.824738,8.714298,22.516020,38.626247,8.916504,21.224968,38.664883,9.048994,4.899574,39.328079,0.938132,3.804149,39.437092,2.194633,5.361769,38.750687,0.406674,5.016614,37.649841,0.470311,8.519273,38.721252,-0.971008,8.221657,37.462700,-1.190897,6.315568,39.296684,-0.003107,7.889993,39.328949,-0.604342,10.978939,39.499367,-1.101055,9.461228,39.409588,-0.928329,11.625393,38.829636,-1.466419,11.397106,37.521736,-1.902561,12.504087,39.535133,-1.311720,14.062929,39.524590,-1.541595,16.965317,41.280025,9.320177,15.621828,41.084248,9.383837,15.118501,41.953880,9.445451,15.053278,41.436256,9.435228,17.132729,41.842705,9.279984,16.248571,42.288155,9.269489,17.905117,42.011791,9.212521,17.994362,42.478279,9.048410,16.036446,42.806446,8.939234,16.008635,42.568462,9.162350,17.471024,42.627819,8.971676,16.432138,42.815468,8.890318,18.602045,41.923458,9.295343,19.560209,42.521523,9.307861,19.581453,42.973888,8.866133,18.588364,42.679710,8.967569,18.628241,41.291401,9.311469,19.788691,41.058151,9.338998,26.455488,40.885067,6.119980,26.035091,40.869179,7.294951,26.479916,42.346516,5.855296,26.089411,42.338024,6.987298,26.503262,41.366112,5.439738,26.514851,42.081852,5.310646,26.050665,43.874332,3.088982,26.443882,43.715977,4.254052,25.678490,42.975277,2.707047,25.692217,43.580059,2.631318,26.474854,42.438076,4.571897,26.063507,42.599510,3.302970,26.502621,43.270805,4.952604,26.515518,42.660480,5.136147,25.973055,41.141754,3.438729,26.449442,40.979855,4.788467,6.393088,41.174458,9.475557,5.092264,41.026794,8.782271,5.889445,43.017948,8.519312,4.823634,42.894207,7.928487,6.845910,41.798363,9.507448,6.512023,42.638454,8.967966,4.394490,42.312813,7.733356,4.491486,41.384598,8.151806,6.920053,43.219116,8.700268,7.764760,43.426495,8.591272,6.316332,44.982571,7.701395,6.367401,43.648865,8.333242,7.919312,45.772141,7.008202,6.864757,45.814182,7.398589,8.109596,43.880047,8.120682,8.264110,44.908146,7.228719,7.925718,41.128597,9.932617,9.164744,40.960590,10.044231,8.282736,42.319756,9.740986,7.643497,41.760307,9.802644,9.623014,41.377571,10.070789,9.427570,41.892120,10.049622,11.501256,41.259514,9.721931,10.308821,41.002003,9.948542,11.468044,41.777000,9.622370,10.357169,42.099609,9.612265,12.260047,41.992954,9.492908,12.235134,42.563107,9.331846,10.025748,42.686268,9.105738,10.003332,42.353043,9.409302,11.633112,42.776604,9.236033,10.493704,42.819992,9.087402,13.061924,41.861523,9.518281,14.032076,42.310501,9.449618,13.878189,42.992706,9.221268,12.830879,42.850395,9.284048,13.146414,41.316620,9.526973,14.406189,41.107388,9.449927,22.868015,41.694263,1.341325,24.737181,41.366974,2.256986,22.130600,42.376457,1.210824,22.711151,42.960991,1.422461,25.594555,42.401543,2.775618,25.489075,41.692585,2.819057,23.641893,43.048061,1.619739,25.059353,42.801182,2.263916,21.847008,44.591209,2.286335,22.813614,44.367279,1.706413,22.356667,43.379742,1.485055,21.473074,43.772305,1.772997,23.327740,43.928768,1.606855,23.124285,43.424892,1.535145,21.244791,41.878647,0.635290,20.509369,41.894569,0.168825,20.778027,43.182060,1.250338,21.259920,42.477596,0.994047,3.387295,42.317009,5.170135,3.372313,41.379417,5.484769,4.182652,42.570400,2.402009,4.127539,41.594330,2.556990,25.708588,42.645248,7.324110,25.709446,43.265285,7.048963,8.470381,43.933907,1.373305,8.602233,43.564232,1.120530,6.606266,42.335735,0.834696,6.451784,43.126442,0.970679,12.154325,46.286526,2.095123,12.103616,46.868690,3.079609,10.163916,45.958210,2.606026,9.996036,46.312714,3.493737,10.351576,46.711575,4.012556,11.476326,47.024269,3.783212,14.434982,43.461086,8.940411,14.327436,43.212383,9.095226,20.864500,43.842640,7.869829,20.831934,43.598537,8.296249,20.138494,43.399811,8.526932,20.024273,43.225071,8.701777,21.063402,43.822708,1.827862,20.812153,43.559776,1.549123,15.160108,45.310760,2.387216,15.135048,44.925236,1.928091,18.078318,42.692650,8.946138,18.158672,42.684784,8.917427,19.786316,43.117329,8.644354,18.763124,42.652252,8.883766,5.743142,45.780766,7.379670,4.685098,45.759186,6.916964,11.646518,42.978535,9.121592,10.469318,43.171078,8.847826,12.254169,43.018711,9.239494,12.273794,43.169640,9.197878,14.001738,43.226627,9.026159,12.867491,42.999367,9.181084,7.000522,36.126431,10.814748,7.628914,36.186592,10.798500,7.925306,37.060913,10.403917,7.657911,38.318459,9.921509,8.454714,36.283836,10.605377,9.521945,36.255955,10.403062,10.240641,36.771927,10.057301,10.411085,37.666294,9.689274,10.679438,36.030941,10.264578,11.767857,35.501396,10.209030,12.662395,36.978165,9.386553,11.304882,37.739193,9.511088,12.489798,35.477203,9.947464,12.970717,36.113220,9.495967,13.478602,31.595959,10.145349,13.562037,30.040163,9.969173,14.331182,33.273727,9.493071,13.715032,32.760071,9.957922,12.619707,34.524521,10.201608,13.174469,33.145199,10.198191,12.854685,31.885536,10.387688,11.535547,30.771301,10.677294,10.703106,29.585407,10.473623,10.461828,28.466368,9.774471,11.841891,34.557648,10.468387,10.952496,33.331207,10.917679,10.659524,32.372917,11.046543,10.756430,30.987152,10.901051,9.365029,32.472935,11.298124,10.275213,32.763824,11.125742,9.871775,35.349831,10.635268,9.261516,33.339806,11.206757,7.826308,32.035156,11.521029,8.530872,32.187454,11.407862,8.012869,35.234459,11.029888,7.778579,33.000084,11.535225,6.656482,31.776497,12.152154,7.195176,31.886007,11.772363,6.106023,29.896915,10.837762,7.108307,31.120634,11.530643,6.007603,29.310667,10.176043,7.026895,29.091000,10.227143,7.979412,29.739897,10.848732,8.609474,31.353359,11.358692,8.369332,29.228491,10.451219,9.961684,29.809687,10.682137,6.621945,27.875595,7.642261,7.299250,28.586752,9.605265,23.539129,27.795120,4.814497,23.709139,28.264536,3.199847,20.818192,32.623657,-1.626774,18.871958,31.928547,-2.382555,21.171314,29.074505,-0.773737,21.702019,31.683208,-0.943951,23.013214,28.489796,1.326785,21.613810,28.150656,-0.123454,19.991739,27.867558,-1.225170,18.216841,27.689360,-1.996429,16.605799,25.864578,-1.828962,17.065771,26.891033,-2.094713,18.579424,25.595713,-0.991400,17.137484,25.531559,-1.562086,20.425732,27.153109,-0.668421,19.624130,26.035433,-0.628935,19.007183,17.247709,-0.878046,19.008722,17.765213,-0.879381,21.682911,25.981443,1.259021,21.517683,25.564121,1.179829,20.057362,25.827545,-0.221745,21.385599,26.151112,0.750427,12.086809,25.662209,6.944238,10.614061,25.621029,6.328156,12.902204,17.251547,7.119307,12.889611,17.777958,7.124525,9.954399,25.426876,5.754263,9.988219,25.132504,5.661790,9.443674,25.566942,5.392353,8.769066,25.508759,4.266022,8.664165,25.287607,3.663816,8.746119,24.987513,3.658690,16.535595,17.059469,-1.736170,18.176186,17.061064,-1.196556,19.750601,17.065763,-0.448238,21.037291,17.072418,0.436502,8.603869,17.053864,3.445528,8.708914,17.053652,2.573789,8.826130,17.236031,2.091476,8.817335,17.746338,2.073061,9.100167,17.054008,1.612293,9.798112,17.054590,0.580463,10.392832,25.281809,0.064775,10.416103,24.950726,0.134285,14.365399,25.746311,7.249888,13.381952,25.707994,7.226325,14.926008,17.255875,7.625480,14.906713,17.784698,7.612415,14.505136,17.066610,7.503482,13.523149,17.064697,7.258119,12.211958,17.062508,6.834150,10.712721,17.060471,6.194710,16.734348,17.250036,7.748530,16.715532,17.768806,7.729864,16.265474,17.065424,7.716851,15.373837,17.066786,7.649629,16.127842,25.675549,7.135980,15.248929,25.735489,7.180144,17.810760,25.558065,7.272120,16.980959,25.608185,7.189948,18.700527,17.248743,7.324048,18.669367,17.765022,7.324507,18.233824,17.064268,7.458238,17.236572,17.064388,7.666338,22.160679,26.629713,1.519771,23.024616,27.737165,1.987537,22.230766,26.224625,3.628418,22.167736,26.309748,2.074491,22.946978,27.114597,5.230593,22.269604,26.386608,4.602882,21.875835,17.270037,3.436641,21.878252,17.816969,3.484739,19.887518,25.445438,6.249421,19.803566,25.140221,6.082476,21.625086,25.994730,5.018783,20.586853,25.733599,6.059237,19.538000,25.569296,6.770514,18.643379,25.532816,7.170076,16.297400,25.280212,-1.667185,16.165415,24.952509,-1.623726,14.236162,25.535845,-1.637684,15.706532,25.530310,-1.791525,13.034996,17.239111,-1.394165,13.053368,17.748896,-1.405264,11.070816,25.539621,-0.437603,12.650570,25.540691,-1.158770,10.908672,17.055431,-0.337269,12.323692,17.056496,-1.056530,8.578356,25.490795,2.247234,8.497108,25.481615,3.193264,8.284421,26.566236,1.431294,8.643626,25.804159,1.678828,8.478376,25.742067,3.792872,8.130774,26.322615,4.117953,9.007043,25.511721,1.330148,9.814834,25.529640,0.418365,9.523664,17.057995,5.345453,8.849990,17.055387,4.373120,12.957756,26.421043,8.169679,12.821045,25.878412,7.409266,14.928737,25.965242,7.386183,15.262196,26.617081,7.886132,18.322836,25.770800,7.496395,18.610626,26.505924,8.138042,16.887810,26.759190,7.463375,16.644924,25.923584,7.213951,21.814974,17.076420,1.506613,21.977190,17.076082,2.748736,10.373421,25.878637,-0.154056,10.333912,26.794918,-0.521742,13.581184,26.870510,-1.927868,13.494339,25.884872,-1.570517,21.532293,17.072660,4.087222,20.685961,17.068125,5.373174,13.720940,17.057631,-1.593018,15.050664,17.058680,-1.873571,19.841194,17.065172,6.384439,19.094086,17.064390,7.051656,9.991335,25.789148,6.143217,10.087563,26.252151,6.870720,20.966375,26.548002,7.622857,20.295139,25.850527,6.781862,7.586887,58.454628,2.495706,6.765145,58.614147,2.288425,6.288871,58.880451,2.655359,6.288871,59.156052,3.632394,6.821493,59.156052,4.165015,7.798528,58.880451,4.165015,8.165460,58.614147,3.688740,7.958180,58.454628,2.867000,5.812596,58.614147,2.288425,4.990852,58.454628,2.495706,4.619559,58.454628,2.867000,4.412278,58.614147,3.688740,4.779212,58.880451,4.165015,5.756247,59.156052,4.165015,4.990852,58.454628,5.834325,5.812596,58.614147,6.041606,6.288871,58.880451,5.674673,6.288871,59.156052,4.697639,4.412278,58.614147,4.641291,4.619559,58.454628,5.463032,6.765145,58.614147,6.041606,7.586886,58.454628,5.834325,7.958179,58.454628,5.463032,8.165460,58.614147,4.641291,4.619559,58.168175,2.495706,4.378907,57.467686,2.255053,3.970384,57.005219,2.589115,3.598252,57.022449,3.608914,3.663992,57.520924,4.165015,4.066812,58.330742,4.165015,4.245417,56.468243,2.121560,4.212043,55.131756,2.088189,3.873954,54.290871,2.522874,3.487570,54.289532,3.585436,3.439272,55.129730,4.165015,3.484215,56.477509,4.165015,4.212045,55.131756,6.241842,4.245417,56.468243,6.208469,3.970384,57.005219,5.740915,3.598253,57.022449,4.721117,3.487571,54.289532,4.744595,3.873957,54.290871,5.807158,4.378907,57.467686,6.074978,4.619559,58.168175,5.834325,4.712970,57.005219,1.846531,5.732768,57.022449,1.474398,6.288869,56.477505,1.360360,6.288869,55.129730,1.315415,5.709290,54.289532,1.363713,4.646729,54.290871,1.750101,6.288870,58.330742,1.942958,6.288869,57.520924,1.540137,7.958179,58.168175,2.495706,8.198833,57.467686,2.255053,7.864770,57.005219,1.846531,6.844971,57.022449,1.474398,8.332324,56.468243,2.121560,8.365696,55.131756,2.088189,7.931012,54.290871,1.750101,6.868450,54.289532,1.363713,8.365696,55.131756,6.241843,8.332324,56.468243,6.208469,7.864770,57.005219,6.483502,6.844971,57.022449,6.855634,6.288869,56.477509,6.969671,6.288869,55.129730,7.014616,6.868449,54.289532,6.966317,7.931012,54.290871,6.579931,8.198833,57.467690,6.074978,7.958179,58.168175,5.834325,6.288870,58.330742,6.387073,6.288869,57.520924,6.789894,4.712969,57.005219,6.483501,5.732769,57.022449,6.855634,4.646729,54.290871,6.579930,5.709290,54.289532,6.966317,8.607356,57.005219,2.589115,8.979488,57.022449,3.608914,9.093526,56.477509,4.165015,9.138470,55.129730,4.165015,9.090172,54.289532,3.585436,8.703785,54.290871,2.522874,8.510927,58.330742,4.165015,8.913749,57.520924,4.165015,8.607356,57.005219,5.740915,8.979488,57.022449,4.721117,8.703785,54.290871,5.807158,9.090172,54.289532,4.744595,4.212043,53.311295,2.088189,4.213536,51.097450,2.088352,3.872896,49.944813,2.529132,3.479536,49.943310,3.604742,3.435650,51.095680,4.174438,3.439271,53.309563,4.165015,3.872593,49.942749,5.829446,3.479919,49.942562,4.768907,4.212694,51.096436,6.251029,4.212045,53.311295,6.241841,4.655348,49.946110,1.747078,5.730996,49.947098,1.365496,6.288869,53.309563,1.315415,6.301438,51.097656,1.320305,8.365696,53.311295,2.088189,8.392471,51.099621,2.118715,7.996482,49.950314,1.816231,6.912706,49.948555,1.393201,7.928096,49.946114,6.600044,6.869128,49.944813,7.000433,8.363896,51.098003,6.247900,8.365696,53.311295,6.241843,6.288869,53.309563,7.014616,6.289765,51.096294,7.029874,4.649988,49.943272,6.607011,5.712630,49.943905,7.003175,8.761477,49.951302,2.597831,9.114411,49.951057,3.637559,9.138470,53.309563,4.165015,9.141912,51.098782,4.180180,8.698145,49.947872,5.822027,9.089584,49.949764,4.771276,9.170941,46.838989,4.415838,9.155681,48.828972,4.240839,8.701222,46.754391,2.439303,8.499563,48.829193,2.240824,6.419143,46.765915,1.343493,6.351710,48.823349,1.339856,4.225663,46.728489,2.103036,4.219511,48.818340,2.089005,3.400393,46.702015,4.311093,3.421168,48.813477,4.212120,4.226795,46.699493,6.414129,4.215302,48.813263,6.287776,6.301532,46.720627,7.274035,6.293350,48.816544,7.090905,8.374496,46.687111,6.434714,8.356696,48.821110,6.272134,21.459795,46.088951,2.399560,21.493944,45.054848,2.682800,20.616152,47.635254,4.011894,20.509638,49.395706,3.988894,21.351564,47.469025,6.306725,21.285063,49.326817,6.240601,23.395044,45.817612,1.522448,23.397160,44.678741,1.599540,25.621176,45.634270,2.411218,25.666000,44.418156,2.532765,25.576340,47.195084,6.480788,25.521978,49.212349,6.341403,23.402409,45.536243,7.392924,23.404297,44.295269,7.591900,26.421185,45.430809,4.596796,26.470291,44.144878,4.771585,21.095768,46.814766,2.656757,20.729099,46.846073,3.569597,20.719061,46.801468,4.692093,21.071907,46.687847,5.863688,22.811050,46.610268,1.538812,21.810413,46.725380,1.957472,25.124479,46.447895,1.973107,23.982376,46.516319,1.530996,23.994537,46.295605,7.278573,25.135349,46.259842,6.896651,21.791477,46.536839,6.767168,22.811291,46.389355,7.240848,26.346582,46.279026,3.920956,25.952841,46.366814,2.813069,25.958782,46.240383,6.133850,26.348467,46.234619,5.088990,1.445400,31.932137,6.890121,1.907249,31.055546,8.090506,1.989676,31.262453,9.500523,1.714767,32.348331,11.201490,6.780280,32.659363,12.191339,6.952267,34.874298,11.365784,5.858297,37.084229,9.765899,4.287798,38.269356,8.023004,3.780002,38.341591,7.542830,4.285712,37.825188,8.322451,1.977486,37.579834,4.140771,1.690462,36.018822,4.355698,3.031346,38.847786,6.405169,2.308625,38.736019,4.974618,10.190611,43.784958,17.388357,10.461512,43.450275,18.133728,10.968587,43.141029,18.305994,11.589734,42.856613,17.772099,11.644137,42.941704,17.067045,11.136118,43.401955,16.319775,10.634377,43.705257,16.295502,10.239201,43.854618,16.901611,10.756423,42.839256,18.802334,10.994348,42.119717,19.210543,11.272843,41.713039,19.245028,11.796369,41.297756,18.929901,12.070904,41.465199,18.439066,11.973939,42.258392,17.814753,12.405921,40.513577,17.120117,12.367371,41.030766,16.439047,12.239666,41.672348,16.403156,12.026423,42.333076,17.101038,12.179918,40.834160,18.337055,12.351458,40.461552,17.625568,12.072458,41.641788,15.770442,11.602184,42.178822,15.297934,11.317814,42.603130,15.282155,11.017927,43.241661,15.702656,10.893060,41.706795,19.406837,10.320240,41.236469,19.572535,10.252460,40.542137,19.549917,10.856100,39.849510,19.180861,11.440683,39.938835,18.910982,11.888157,40.680790,18.817766,9.548750,40.606239,19.527061,8.710203,39.912659,19.310635,8.661321,39.169048,19.134298,9.380729,38.424019,18.686716,10.085272,38.449669,18.468204,10.805309,39.187988,18.761183,11.087996,37.933525,16.454020,11.687174,38.718369,16.858568,11.813308,39.094841,17.538813,11.404205,39.338890,18.472458,10.069737,37.859642,17.867525,10.611647,37.572170,16.816246,12.124803,39.471855,17.163942,12.338259,40.123459,17.322416,9.666675,41.357262,19.495270,9.168529,42.193340,19.026175,8.523045,42.273186,18.591589,7.639684,41.600941,18.366880,7.443623,40.880974,18.621117,7.991266,40.021038,19.107502,10.228235,43.129768,18.622259,9.408355,42.822113,18.702740,9.859416,43.848373,17.063421,9.137584,43.686783,16.891285,8.690872,43.379005,17.282986,8.824188,42.906773,18.245506,8.283436,43.227814,16.658413,7.424225,42.577049,16.395138,6.974447,42.127766,16.802225,7.084745,41.624523,17.807489,9.801852,40.598450,13.538551,10.421860,41.339943,13.989921,11.014065,41.248741,14.311478,11.552204,40.433414,14.781897,11.497223,39.681942,14.911666,10.903923,38.895992,14.456683,10.396105,38.919151,13.877978,9.835611,39.788338,13.403936,10.942148,41.922173,14.482695,11.304616,42.265038,14.979002,12.216743,41.021717,15.818676,11.962072,40.396881,15.359990,11.989866,39.226997,16.523762,11.896544,39.719986,15.562565,10.852806,37.680393,15.709146,10.755133,38.175117,14.691579,8.816844,43.516552,16.295174,9.190060,43.301342,15.403709,9.068656,42.786118,14.823943,8.320751,42.105579,14.467877,7.646115,42.017967,14.754191,7.165996,42.267174,15.744185,10.512252,43.531494,15.698392,9.815349,43.306328,15.226117,10.377693,42.069260,14.284068,9.738166,42.790718,14.695308,9.115947,40.671513,13.426199,8.334973,41.454079,13.935026,7.962540,39.297062,19.077839,7.288198,38.742390,18.810122,7.283121,38.017967,18.543545,8.047061,37.273514,18.075472,8.775070,37.260162,17.902145,9.410215,37.818069,18.189247,6.494116,38.073204,18.315781,5.516069,37.233768,17.543779,5.419450,36.382416,17.022881,6.320370,35.700684,16.592922,7.190985,35.840939,16.669662,8.040057,36.615700,17.405376,8.475795,35.361477,14.772533,9.250232,36.033188,15.339708,9.410620,36.372990,16.145491,8.798816,36.692078,17.227377,7.173976,35.213051,15.863562,7.857502,35.005333,14.954027,9.921034,36.654568,15.768522,10.492382,37.245491,16.091421,4.557642,37.175468,17.012880,3.821831,37.984123,16.560146,2.889611,37.789169,15.718900,1.686094,36.598640,14.559674,2.583714,38.909691,13.882474,1.444857,37.944382,12.840944,3.299363,38.699738,15.799697,3.121646,39.229195,14.840672,7.276799,37.528404,11.718912,7.870603,36.542385,12.215582,7.791376,35.845371,12.335023,7.362339,35.455353,11.900951,7.713080,34.727287,14.147725,7.052371,34.139637,13.572725,8.192685,35.703445,13.004471,8.211834,35.166359,13.962216,3.464147,39.494900,13.766340,4.288493,39.451828,12.734305,4.346961,39.057098,11.868794,3.522469,38.674370,10.869045,5.342484,39.087524,11.976506,6.403158,38.426132,11.626390,2.693466,30.515936,9.395940,3.735513,30.336349,10.682222,4.148207,30.764256,11.664806,4.051240,31.672195,12.587100,4.905082,30.508310,11.722357,6.007211,31.180624,12.296375,6.576145,38.867043,18.529799,5.994673,39.726822,18.051012,5.289062,39.758286,17.403925,4.151671,38.878693,16.660336,6.878933,40.986153,18.140596,6.177684,40.430840,17.879257,6.676560,41.961449,16.162342,5.968739,41.404556,15.901196,5.485006,40.967995,16.238295,5.606625,40.467834,17.242529,5.040736,40.726471,15.433145,3.852455,39.871815,14.723706,7.224181,38.233437,11.900429,7.966845,38.777626,12.438732,8.681323,38.601826,12.720791,9.253560,37.703976,13.188116,9.112978,36.988205,13.339960,8.392130,36.370453,12.837696,8.634252,39.339256,12.856163,9.205578,39.912560,13.176069,10.324067,38.193130,14.076435,9.767693,37.594479,13.747164,9.696093,36.456512,15.020472,9.611060,36.945217,13.999870,5.707906,41.112591,15.170861,6.262434,40.873657,14.158983,6.210631,40.298382,13.433855,5.277452,39.616924,12.721583,7.645543,41.474468,14.188946,6.997299,40.922306,13.907627,7.911774,39.511978,12.764631,7.044736,40.309967,13.307619,1.862701,33.379776,12.829903,2.429804,34.334656,14.238726,0.397770,33.776035,9.280542,0.936066,32.914619,7.278319,0.531885,35.960960,7.461702,1.111217,35.493935,5.537349,4.874328,37.527500,9.166851,5.470059,37.470192,10.012304,6.593083,35.209667,11.109346,6.579888,35.723534,10.819167,6.179101,32.324970,12.769347,6.304400,31.909676,12.506248,2.034197,38.179893,6.677003,1.957748,38.260540,5.163441,4.298831,32.564339,13.454770,4.844179,33.367218,14.222792,1.250151,33.156624,11.654663,0.527748,33.813461,10.763189,0.208231,35.641537,8.885551,0.162487,34.639320,9.813083,5.215635,37.125702,9.338225,6.312311,35.821503,10.623818,6.525512,33.077118,12.598005,6.784757,34.370174,11.770192,0.726440,36.794754,8.040846,1.644674,37.845245,7.474054,3.951793,38.022892,8.213483,2.756610,38.310898,7.515105,2.283401,32.628784,12.385338,3.506973,32.247440,12.886734,5.776711,32.293247,13.048644,4.726091,32.087624,13.124052,0.783470,35.527798,13.072359,0.333582,34.626957,11.268312,0.676735,37.115326,11.352524,0.383360,36.469406,9.453230,7.022039,35.181057,11.578846,6.750967,35.064625,11.345142,6.558875,33.528740,13.181685,6.266750,32.898190,12.965009,2.861406,38.400513,9.611473,2.376184,38.221981,8.144732,3.327663,35.300259,15.481413,4.418684,36.288071,16.583735,6.023516,37.575176,10.738407,6.568936,37.819115,11.334652,5.550415,34.172489,15.006141,6.339252,35.008625,15.837980,0.827620,37.128166,12.655100,0.948158,36.384449,13.497192,7.020928,34.085732,12.949151,7.242099,34.824142,12.127805,5.168469,37.939606,10.199177,3.852727,38.469913,10.111363,3.418411,34.504642,14.932828,4.621677,33.958191,14.788407,2.327312,35.107834,14.725994,1.492651,35.710915,14.202263,6.264896,36.990044,10.661406,6.995071,35.851273,11.335995,1.364855,37.870918,11.629063,2.494649,38.421761,10.626936,6.478365,33.689346,13.719794,5.682291,33.652752,14.359574,13.298688,35.085815,13.432767,12.476948,34.917542,13.626120,12.000672,34.684048,13.308343,12.000672,34.508011,12.459389,12.533295,34.573597,11.991080,13.510328,34.845001,11.990674,13.877261,35.044739,12.402634,13.669981,35.116051,13.108171,11.524398,34.917542,13.626120,10.702656,35.085815,13.432767,10.331364,35.116051,13.108171,10.124084,35.044739,12.402634,10.491016,34.845001,11.990673,11.468050,34.573597,11.991080,10.702656,35.471008,10.467337,11.524398,35.337067,10.268300,12.000672,35.049183,10.613876,12.000672,34.648960,11.513216,10.124084,35.171638,11.567529,10.331364,35.430191,10.816093,12.476948,35.337067,10.268300,13.298688,35.471008,10.467337,13.669981,35.430191,10.816093,13.877260,35.171635,11.567530,10.331364,35.370911,13.432767,10.090711,36.053600,13.656421,9.682188,36.532890,13.359224,9.310057,36.582775,12.443069,9.375796,36.148251,11.966208,9.778617,35.377937,11.989045,9.957219,37.028385,13.777622,9.923846,38.070503,13.792562,9.585758,38.511856,13.357878,9.199370,38.524246,12.298033,9.151073,38.114975,11.757548,9.196019,37.117554,11.882997,9.923847,38.125614,9.582664,9.957219,37.166416,9.873914,9.682188,36.690208,10.435041,9.310057,36.639977,11.413635,9.199371,38.532631,11.088297,9.585759,38.534939,9.934507,10.090711,36.310059,10.177048,10.331364,35.715359,10.462614,10.424774,36.489826,14.035450,11.444572,36.460804,14.390991,12.000672,36.995148,14.505029,12.000672,38.059757,14.549973,11.421093,38.500881,14.501675,10.358530,38.503349,14.118361,12.000672,35.180111,13.942093,12.000672,35.969376,14.325252,13.669981,35.370911,13.432767,13.910635,36.053604,13.656421,13.576571,36.489826,14.035450,12.556773,36.460804,14.390991,14.044125,37.028385,13.777622,14.077498,38.070503,13.792562,13.642814,38.503349,14.118361,12.580252,38.500881,14.501675,14.077498,38.125614,9.582664,14.044125,37.166416,9.873914,13.576571,36.704388,9.708864,12.556773,36.689724,9.340836,12.000672,37.158852,9.112844,12.000672,38.125202,8.784117,12.580252,38.534592,8.696766,13.642815,38.534882,9.098868,13.910633,36.310059,10.177048,13.669981,35.715359,10.462614,12.000672,35.596317,9.931479,12.000672,36.273392,9.479115,10.424774,36.704388,9.708864,11.444572,36.689724,9.340836,10.358532,38.534882,9.098868,11.421093,38.534592,8.696766,14.319157,36.532894,13.359224,14.691288,36.582775,12.443069,14.805326,37.117554,11.882997,14.850270,38.114975,11.757548,14.801972,38.524246,12.298033,14.415586,38.511856,13.357878,14.222728,35.377934,11.989046,14.625549,36.148251,11.966208,14.319157,36.690208,10.435041,14.691288,36.639977,11.413636,14.415586,38.534939,9.934507,14.801972,38.532631,11.088297,9.923845,38.827351,13.780272,9.923845,39.320168,13.760767,9.585756,39.591324,13.308978,9.199370,39.585106,12.238726,9.151073,39.314457,11.631146,9.151073,38.837166,11.665298,9.923845,39.944023,13.695034,9.923845,40.810120,13.565433,9.585756,41.255692,13.078419,9.199370,41.158314,12.099918,9.151072,40.686977,11.604092,9.151073,39.910854,11.629463,9.923844,40.293823,9.466866,9.923845,39.759731,9.323097,9.585756,39.516548,9.772717,9.199370,39.557911,10.987961,9.199369,40.933628,10.997182,9.585755,40.631531,9.950678,9.923845,39.284077,9.266211,9.923847,38.839478,9.364208,11.427401,47.631996,7.156898,10.358044,47.216892,7.234565,9.923668,46.821102,8.067640,9.923849,46.663525,9.403612,10.358530,41.300659,13.794331,11.421093,41.326912,14.165384,12.000672,41.847252,14.108246,12.000671,42.952427,13.849865,14.077498,41.745773,13.375689,14.077497,42.706051,13.121511,13.665901,47.267559,7.209353,12.596809,47.649666,7.146479,12.580252,41.326912,14.165384,13.642815,41.300663,13.794332,12.637463,40.827003,8.824818,13.703516,41.241257,8.764946,14.099892,41.402973,8.600594,14.077497,41.289566,8.377268,13.642814,40.426720,9.182993,12.580251,40.365421,8.802288,12.000671,40.436775,8.795101,12.000671,40.433945,8.785152,9.923843,40.640797,9.527087,9.923843,40.785355,9.432240,10.389647,41.230206,8.735897,11.465651,40.825180,8.813532,11.421092,40.365421,8.802288,10.358528,40.426720,9.182993,14.811810,45.067852,7.922329,14.433990,46.382381,7.479952,14.415586,41.255688,13.078419,14.801972,41.158314,12.099918,14.850270,41.400040,11.468346,14.850269,42.002113,11.211126,14.460926,42.190845,8.606740,14.821516,43.574715,8.330164,14.801972,40.933628,10.997182,14.415586,40.631531,9.950678,9.588779,46.305740,7.501822,9.213716,44.980373,7.924181,9.158770,44.142109,8.435686,9.151074,44.031284,8.870831,9.221019,43.503082,8.310311,9.609706,42.153824,8.574350,10.358530,39.590809,14.069773,11.421093,39.590607,14.453403,12.000672,39.943684,14.453550,12.000672,40.830212,14.307352,12.000672,38.824554,14.549973,12.000672,39.319603,14.530687,14.077498,38.827351,13.780272,14.077498,39.320168,13.760767,13.642815,39.590809,14.069773,12.580252,39.590607,14.453403,14.077498,39.944023,13.695034,14.077498,40.810120,13.565433,14.077498,40.293823,9.466866,14.077498,39.759731,9.323097,13.642815,39.488850,8.896120,12.580252,39.481869,8.483778,12.000672,39.725273,8.494686,12.000671,40.198132,8.676807,14.077498,39.284077,9.266211,14.077499,38.839478,9.364208,12.000672,38.839027,8.539770,12.000672,39.276882,8.427265,10.358530,39.488850,8.896120,11.421093,39.481869,8.483778,14.415586,39.591328,13.308978,14.801972,39.585106,12.238726,14.850271,39.910854,11.629463,14.850271,40.686977,11.604092,14.850271,38.837166,11.665298,14.850271,39.314457,11.631146,14.415586,39.516548,9.772717,14.801972,39.557911,10.987961,9.923845,44.868057,12.318682,9.923845,43.773800,12.790594,12.000671,46.467789,12.173064,12.000673,47.133129,11.027662,14.077497,45.744064,11.589220,14.077497,46.317310,10.588035,14.077497,41.155937,8.904917,14.077497,40.942455,9.209702,12.000671,40.497547,8.414736,12.000671,40.414608,8.321341,9.923845,41.298550,8.581381,9.923845,41.328518,8.351650,14.850269,43.730000,9.984130,14.850269,43.936710,9.365129,9.151073,43.284607,10.515963,9.151073,42.640095,10.896923,10.358530,45.630421,12.272982,11.421092,45.965931,12.587888,13.642813,45.630421,12.272821,12.580251,45.965931,12.587824,13.642813,40.894695,8.581950,12.580251,40.546829,8.487677,10.358530,40.894695,8.581951,11.421092,40.546829,8.487679,14.415585,44.997131,11.630545,14.801971,44.093254,10.747713,14.415585,41.734360,9.017162,14.801971,42.935440,9.810110,9.585758,44.997131,11.630705,9.199370,44.093254,10.747795,9.585758,41.734360,9.017164,9.199371,42.935440,9.810127,12.000671,44.192944,13.503326,12.000671,45.455799,12.988312,14.077497,43.773800,12.790594,14.077497,44.868057,12.318611,12.000671,40.433769,8.696656,12.000671,40.496307,8.565695,9.923844,40.942455,9.209702,9.923845,41.155937,8.904917,14.850269,42.640095,10.896923,14.850269,43.284607,10.515946,9.923845,42.706051,13.121511,9.923845,41.745773,13.375689,14.077497,40.785355,9.432240,14.077497,40.640797,9.527087,9.151072,42.002113,11.211126,9.151072,41.400040,11.468346,13.642813,43.357780,13.283552,12.580251,43.528805,13.644548,10.358528,40.632511,9.072441,11.421091,40.434418,8.782148,14.415586,41.166485,9.681102,14.801971,41.937645,10.558074,9.585756,43.057911,12.557508,9.199370,42.610832,11.575167,10.358530,43.357780,13.283552,11.421092,43.528805,13.644548,13.642813,40.632511,9.072441,12.580251,40.434418,8.782148,14.415586,43.057911,12.557508,14.801971,42.610832,11.575167,9.585755,41.166485,9.681102,9.199369,41.937645,10.558075,9.923847,46.317310,10.588797,9.923846,45.744064,11.589573,14.077497,41.328518,8.351631,14.077497,41.298550,8.581378,9.151073,43.936710,9.365362,9.151073,43.730000,9.984213,12.000673,47.533455,9.624016,12.005245,47.697891,8.017750,14.077499,46.663525,9.402631,14.086545,46.847031,8.056423,12.000671,40.325752,8.418160,12.021241,40.481102,8.684308,9.923845,41.289566,8.377340,9.934368,41.394474,8.587421,14.850269,44.031284,8.870321,14.854679,44.175556,8.439123,10.358532,46.897190,10.164224,11.421095,47.313156,10.333133,13.642813,40.889950,8.281738,12.580251,40.421551,8.318512,14.415586,46.003952,9.817194,14.801971,44.714134,9.342257,9.585758,41.875145,8.441435,9.199372,43.250454,8.842729,13.642815,46.897190,10.163409,12.580254,47.313152,10.332811,10.358530,40.889950,8.281757,11.421092,40.421551,8.318514,14.415585,41.875145,8.441362,14.801971,43.250454,8.842508,9.585759,46.003952,9.818064,9.199372,44.714134,9.342796,12.219860,42.519794,9.115561,12.103523,41.302620,8.945354,14.373699,43.103855,8.756279,14.189466,42.067589,8.744630,14.909534,45.091705,6.878179,14.872314,44.566681,7.738994,14.235539,46.908504,4.877782,14.122727,46.920757,6.508665,12.057828,47.290909,4.495317,12.023529,47.603062,6.248205,9.893847,46.579147,4.983500,9.922944,46.791111,6.560849,9.225286,44.718010,6.788045,9.189548,44.399456,7.718643,9.988335,43.025402,8.584677,9.976460,42.025097,8.678220,20.244804,41.574837,8.646922,20.211565,42.112572,8.577614,18.196106,40.639175,8.826160,18.202246,41.189728,8.859358,16.092752,41.575680,8.638877,16.061756,42.114590,8.557737,15.348539,44.309673,8.143532,15.357525,44.658165,7.743680,16.066759,46.709419,7.897691,15.999372,46.738594,6.880351,18.166235,47.377388,7.828449,18.130560,47.258492,6.605494,20.221590,46.281391,7.907204,20.155853,46.253273,6.903358,20.970026,44.154621,8.175684,20.870214,44.409218,7.822131,20.173578,42.739410,8.469879,20.179167,43.295944,8.395851,18.209265,41.826881,8.869549,18.203358,42.380756,8.898037,16.026329,42.742775,8.436439,15.941507,43.276222,8.370718,15.367796,45.037071,7.217671,15.358648,45.324562,6.681325,15.922359,46.680153,5.879650,15.804794,46.517368,4.930233,18.089785,47.031464,5.438748,18.060255,46.666958,4.360270,20.080725,46.200676,5.918111,20.055822,46.055866,4.963375,20.756147,44.697021,7.348956,20.672663,44.913155,6.820786,18.785191,41.575066,8.837584,19.798901,42.039345,8.664248,16.487226,42.018021,8.651886,17.605003,41.559059,8.836363,15.403755,44.216927,7.789968,15.727221,42.961773,8.293318,15.659321,46.372738,6.604588,15.379021,45.426861,7.191285,17.508085,47.190784,6.018506,16.395079,46.973515,6.195074,19.714838,46.549885,6.211152,18.691507,47.028805,6.021213,20.765404,45.041588,7.288085,20.423904,45.874393,6.657909,20.483717,42.908379,8.342924,20.786903,44.009632,7.885283,18.908806,24.258509,-0.630594,18.933357,24.810467,-0.619308,21.409733,23.092737,1.096452,21.450251,20.975979,1.043380,12.870693,24.348619,6.881215,12.834797,24.922293,6.864056,10.099773,22.863771,5.708456,10.074730,20.807236,5.750298,8.812157,22.787027,3.771521,8.757753,20.750772,3.811006,8.994676,24.177334,2.013597,8.958184,24.711697,1.979105,10.433304,22.768396,0.154646,10.382904,20.737562,0.122654,14.791649,24.376320,7.200500,14.756342,24.955921,7.143015,16.544901,24.273094,7.268509,16.518660,24.828163,7.198852,18.287617,24.247606,7.060945,18.229097,24.796576,7.040860,21.640554,24.565582,3.835710,21.665668,25.189331,3.934641,19.932407,22.871004,5.978267,20.028988,20.814400,5.976447,15.955970,22.771254,-1.672243,15.900487,20.740788,-1.747227,13.310276,24.175331,-1.229307,13.353395,24.708452,-1.245430,20.929842,23.924593,0.586682,19.641169,23.761562,-0.280703,10.741388,23.741432,6.086514,12.196318,23.761614,6.690316,8.982846,23.657751,4.239326,9.605112,23.705120,5.234928,9.937273,23.617477,0.616978,9.224300,23.618683,1.565328,13.457642,23.783373,7.042871,14.390075,23.799732,7.198893,16.112261,23.727800,7.310019,15.235310,23.779003,7.271272,17.908442,23.682068,7.196949,17.017061,23.691036,7.302255,20.375385,23.783773,5.531132,21.305334,23.907660,4.424067,18.707733,23.682659,6.904912,19.468271,23.703421,6.362405,13.980943,23.618214,-1.453072,15.312994,23.619154,-1.672190,11.081714,23.616962,-0.252085,12.540956,23.617411,-0.955330,21.825302,24.003544,3.105448,21.707638,24.019772,1.738750,16.693810,23.620398,-1.506123,18.162617,23.649523,-0.986010,8.842067,23.619465,2.459584,8.753032,23.627199,3.303772,18.938597,20.787012,-0.735653,18.911358,22.834187,-0.671026,12.893625,20.836691,6.986572,12.890257,22.903160,6.923640,8.938781,20.738453,2.052267,8.986812,22.770096,2.038221,14.853070,20.853422,7.390994,14.824508,22.925112,7.285704,16.624847,20.795843,7.484115,16.581341,22.845758,7.366421,18.466396,20.781700,7.175712,18.369051,22.826202,7.107606,21.725624,20.960596,3.652099,21.662294,23.071432,3.739606,13.188368,20.738813,-1.293331,13.253715,22.769312,-1.246559,21.494694,19.331434,0.996545,21.528027,18.449181,0.961419,10.044989,19.210363,5.788186,10.022683,18.363863,5.816603,8.702074,19.169962,3.843278,8.660313,18.335512,3.867482,10.333546,19.161043,0.090845,10.296528,18.329809,0.066988,20.115376,19.217495,5.979972,20.180168,18.370966,5.982616,15.857716,19.164570,-1.816904,15.825637,18.333557,-1.869164,16.182789,19.887411,7.541878,15.296010,19.914543,7.489361,18.073221,19.863214,7.356188,17.124569,19.867905,7.512914,13.847388,19.826969,-1.552364,15.183505,19.827967,-1.802406,10.981413,19.825262,-0.320843,12.423366,19.826004,-1.034216,16.619621,19.828993,-1.650194,18.176434,19.844828,-1.119047,21.001812,19.992558,0.492014,19.707424,19.905037,-0.389750,10.713011,19.892067,6.170353,12.193266,19.903484,6.793972,8.892925,19.846334,4.318328,9.545661,19.872091,5.313181,9.849389,19.825117,0.576146,9.139915,19.825462,1.571710,13.480800,19.915796,7.181781,14.438146,19.925177,7.381207,20.544476,19.917677,5.473846,21.439278,19.983925,4.274941,18.906397,19.863583,7.004972,19.663260,19.874699,6.396876,21.925455,20.035156,2.936331,21.784542,20.043709,1.615656,8.750360,19.825699,2.507360,8.652583,19.829796,3.375282,16.249205,16.877636,0.449790,17.568213,16.878004,0.854120,18.815655,16.878218,1.378201,19.823578,16.878374,1.938622,20.449352,16.878513,2.524900,20.657362,16.878677,3.124206,20.443699,16.878849,3.734678,19.853165,16.879133,4.724432,19.439766,16.879274,5.227656,18.902988,16.879311,5.498269,18.214523,16.879288,5.638328,17.381681,16.879164,5.667233,16.504595,16.878881,5.602070,15.635968,16.878344,5.476909,14.781073,16.877434,5.342806,13.854130,16.876215,5.188022,12.678318,16.874949,4.938019,11.383540,16.873808,4.577610,10.406437,16.872873,4.150952,9.896188,16.872263,3.744510,9.793042,16.872107,3.374342,9.863536,16.872196,2.750770,10.042998,16.872429,2.329513,10.589280,16.873013,1.800548,11.538011,16.873854,1.256980,12.774432,16.874872,0.818293,13.965393,16.875956,0.485649,15.051917,16.876942,0.321544,15.751008,16.949892,-1.772419,15.737774,16.877108,-1.488331,18.942989,16.951975,-0.753754,18.816141,16.878006,-0.506510,21.419891,16.957216,0.991682,21.173689,16.878569,1.133964,21.739861,16.957418,3.382754,21.470325,16.879110,3.323078,20.181036,16.954401,5.866735,19.997957,16.879690,5.696981,18.657190,16.953669,7.199072,18.539360,16.879801,6.949578,16.734564,16.953566,7.619818,16.716179,16.879398,7.343727,14.958795,16.953680,7.494493,15.005072,16.878115,7.219452,12.955894,16.950750,6.984264,13.050684,16.875563,6.719398,10.113532,16.947533,5.724790,10.304169,16.873070,5.515423,8.771875,16.944654,3.875973,9.046846,16.871609,3.819014,8.961813,16.944511,2.147922,9.224385,16.871784,2.242401,10.359673,16.945753,0.167038,10.553370,16.873055,0.374968,13.073227,16.947855,-1.257135,13.168064,16.875128,-0.994173,10.910405,16.873354,3.709950,11.008216,16.873409,2.175162,13.349104,16.875546,4.056044,13.397360,16.875463,1.661579,15.306329,16.877808,4.242231,15.530859,16.877481,1.508485,17.905245,16.878323,2.151979,17.217815,16.878824,4.597392,19.783819,16.878613,2.990265,18.912088,16.879084,4.798941,15.726723,16.877151,-1.157022,15.680919,16.877245,-0.425138,18.668407,16.877960,-0.218281,18.427135,16.878010,0.428708,20.888083,16.878420,1.301032,20.495865,16.878368,1.739121,21.156273,16.878906,3.261471,20.809587,16.878771,3.297127,19.780497,16.879509,5.502640,19.643152,16.879324,5.233778,18.396696,16.879665,6.658579,18.414177,16.879465,6.112051,16.691591,16.879333,7.018510,16.782085,16.879194,6.339156,15.055846,16.878098,6.896395,15.136407,16.878029,6.171726,13.159174,16.875578,6.411260,13.262255,16.875584,5.755332,10.524871,16.873165,5.272538,10.734400,16.873262,4.814290,9.366404,16.871792,3.750842,9.669021,16.872011,3.657802,9.529255,16.871986,2.349559,9.807042,16.872185,2.457204,10.779438,16.873226,0.615628,10.960835,16.873369,1.071933,13.281771,16.875244,-0.689236,13.373112,16.875357,-0.036109,17.990465,16.877838,-0.695076,16.456490,16.877434,-1.198645,20.612787,16.878374,0.780704,19.445351,16.878120,-0.007019,21.446686,16.878864,2.722084,21.307734,16.878613,1.685873,20.292458,16.879477,5.086135,21.047676,16.879166,3.898753,18.837223,16.879745,6.604340,19.526495,16.879681,6.015325,17.155888,16.879515,7.143151,18.054028,16.879692,6.958128,15.440658,16.878551,7.121597,16.271357,16.879166,7.187387,13.676800,16.876257,6.741883,14.615675,16.877556,6.979320,11.027870,16.873667,5.748870,12.432921,16.874903,6.338403,9.351154,16.871914,4.183642,9.940411,16.872633,5.004155,9.233315,16.871714,2.689173,9.142571,16.871607,3.415224,10.209354,16.872738,0.935900,9.578221,16.872112,1.858118,12.554751,16.874638,-0.570656,11.235991,16.873600,0.097542,15.075119,16.876730,-1.330305,13.849602,16.875734,-1.071123,18.989378,18.356638,-0.839731,18.967615,19.197567,-0.795126,12.890718,18.379568,7.086470,12.891964,19.231962,7.043656,8.850838,18.329576,2.067326,8.888528,19.161291,2.060872,14.891914,18.389069,7.551334,14.875267,19.244560,7.482616,16.690516,18.361675,7.662070,16.662373,19.204233,7.585804,18.613375,18.355036,7.283461,18.550385,19.194378,7.237282,21.836147,18.441999,3.530908,21.788780,19.320736,3.582847,13.090609,18.331526,-1.374386,13.132505,19.162561,-1.339647,21.557655,17.821022,0.930196,21.547880,17.271366,0.923759,10.002855,17.767490,5.841862,10.013095,17.245676,5.833602,8.623194,17.749842,3.888999,8.630658,17.237400,3.899302,10.263623,17.747002,0.045783,10.263090,17.237068,0.057310,20.237761,17.774565,5.984966,20.260971,17.252693,5.962731,15.797123,17.750950,-1.915615,15.770791,17.241175,-1.914846,16.230654,18.070782,7.702036,15.334405,18.083010,7.640737,18.186964,18.059914,7.470380,17.199036,18.061956,7.659749,13.759235,18.040751,-1.632906,15.102922,18.041780,-1.903170,10.903185,18.038746,-0.377712,12.339796,18.039679,-1.100086,16.578924,18.042677,-1.759024,18.196463,18.050287,-1.218992,21.068739,18.119194,0.422059,19.765913,18.078417,-0.471991,10.678605,18.069857,6.233073,12.180227,18.075859,6.871395,8.813296,18.047611,4.371054,9.487486,18.059990,5.369188,9.774635,18.038193,0.540066,9.064665,18.038004,1.568810,13.488951,18.082323,7.282641,14.465435,18.087391,7.509874,20.670219,18.085136,5.445971,21.546486,18.115709,4.185298,19.044401,18.060146,7.080951,19.801825,18.065294,6.429679,22.013433,18.139297,2.829181,21.857496,18.143097,1.532217,8.669080,18.037893,2.533792,8.565487,18.039749,3.419782,21.456636,25.223785,1.161156,21.410627,24.593374,1.137010,10.045625,24.860765,5.668145,10.090899,24.298325,5.680019,8.793461,24.738874,3.694874,8.825605,24.199320,3.731914,10.440664,24.708227,0.154018,10.453929,24.174761,0.165985,19.827503,24.868292,6.037362,19.862846,24.305676,5.998475,16.092236,24.710356,-1.619705,16.021074,24.177242,-1.627800,18.966944,25.071638,-0.617739,19.118532,25.421101,-0.619036,12.793455,25.205372,6.855318,12.774168,25.509825,6.960865,8.906908,24.955093,1.941324,8.823486,25.270948,1.866157,14.720221,25.244986,7.094769,14.740250,25.562475,7.124105,16.495815,25.092478,7.138613,16.511932,25.417288,7.117537,18.178215,25.054741,7.029634,18.176609,25.352854,7.116249,21.706398,25.522947,4.034514,21.843477,25.895849,4.208111,13.392035,24.950611,-1.272682,13.435680,25.282757,-1.348598,21.001743,25.296921,0.616525,19.685843,25.047747,-0.257760,10.657883,25.019331,6.065372,12.123076,25.049536,6.663340,8.920488,24.892313,4.175520,9.525843,24.964354,5.197760,9.897460,24.830317,0.589210,9.162201,24.832489,1.510942,13.388685,25.082113,6.986797,14.318278,25.106470,7.099783,20.327553,25.080917,5.648670,21.319746,25.270544,4.612515,18.584570,24.926178,6.887403,19.368822,24.957939,6.401970,21.889856,25.417349,3.281379,21.794359,25.442324,1.829308,8.777993,24.833893,2.383489,8.696131,24.845766,3.223827,16.060772,24.995604,7.160048,15.171737,25.074251,7.135234,17.801300,24.925325,7.122819,16.948925,24.939171,7.175078,14.095551,24.829868,-1.471119,15.457743,24.830776,-1.662373,11.085052,24.829084,-0.272099,12.600899,24.829218,-0.982599,16.814384,24.832279,-1.476967,18.225824,24.876581,-0.955336,19.134317,35.661316,13.221988,18.696167,35.452759,12.885029,19.216549,35.507477,12.431174,19.613110,35.704777,12.804670,17.249119,35.661316,13.221988,16.770329,35.704777,12.804670,17.166889,35.507477,12.431174,17.687271,35.452759,12.885029,17.249119,36.020058,10.700817,17.687269,35.720230,11.065423,17.166889,35.647018,11.541187,16.770329,35.958832,11.145473,19.134317,36.020058,10.700817,19.613108,35.958828,11.145473,19.216549,35.647018,11.541187,18.696167,35.720230,11.065424,16.105640,36.546173,13.227076,15.746199,36.958000,12.892734,15.777308,36.566299,12.428500,16.115284,36.206326,12.804507,15.786448,38.442776,13.385049,15.535314,38.956841,12.881964,15.401487,38.479702,12.380847,15.577490,37.935677,12.925178,15.786448,38.517605,10.168222,15.577490,38.014900,10.797054,15.401487,38.506908,11.246096,15.535314,38.988457,10.579656,16.105640,36.802650,10.673491,16.115284,36.419636,11.140589,15.777308,36.661507,11.526019,15.746199,37.105213,11.001850,16.556202,38.416977,14.115478,17.075073,37.867088,14.317984,17.614487,38.408409,14.490607,17.056709,38.925125,14.358316,16.763704,36.497631,13.810178,17.249119,36.114941,13.800842,17.684923,36.420353,14.119702,17.148525,36.863670,14.150503,19.619734,36.497627,13.810178,19.234913,36.863670,14.150503,18.698515,36.420353,14.119702,19.134319,36.114941,13.800842,19.827236,38.416977,14.115478,19.326729,38.925125,14.358316,18.768951,38.408409,14.490607,19.308365,37.867088,14.317984,19.827236,38.519073,9.378855,19.308365,38.028191,9.303257,18.768951,38.517384,8.988991,19.326729,38.989494,8.979888,19.619732,36.844933,10.047853,19.134317,36.523148,10.074837,18.698515,36.792419,9.727884,19.234911,37.162910,9.656775,16.763704,36.844933,10.047854,17.148525,37.162910,9.656775,17.684923,36.792419,9.727884,17.249119,36.523148,10.074837,16.556202,38.519073,9.378855,17.056709,38.989494,8.979888,17.614487,38.517384,8.988991,17.075073,38.028191,9.303257,20.596991,38.442776,13.385049,20.805948,37.935677,12.925178,20.981951,38.479702,12.380847,20.848125,38.956841,12.881964,20.277798,36.546169,13.227076,20.268154,36.206326,12.804508,20.606131,36.566299,12.428500,20.637239,36.958000,12.892734,20.277796,36.802650,10.673490,20.637239,37.105213,11.001850,20.606131,36.661507,11.526019,20.268154,36.419636,11.140589,20.596991,38.517605,10.168222,20.848125,38.988457,10.579656,20.981951,38.506908,11.246096,20.805948,38.014900,10.797054,15.776805,39.946571,13.338925,15.535314,40.183331,12.813427,15.390419,39.947678,12.256424,15.535314,39.696239,12.840050,15.776805,41.201553,13.171919,15.535313,41.586468,12.634027,15.390419,41.174206,12.177126,15.535314,40.802273,12.753121,15.776805,40.940102,9.869663,15.535314,40.696865,10.384890,15.390419,41.079361,11.013878,15.535313,41.293877,10.449049,15.776805,39.942158,9.793884,15.535314,39.703171,10.419387,15.390419,39.946068,11.002525,15.535314,40.162659,10.353125,16.547163,46.907612,9.228904,17.056709,47.052742,9.727010,17.610514,47.292473,9.323422,17.048391,47.235897,8.854552,19.833860,42.714279,13.526105,19.326729,43.151917,13.644714,18.771299,42.801376,13.919981,19.326729,42.407764,13.876350,19.833315,40.842422,8.463990,19.326729,40.556873,8.369853,18.771515,40.368546,8.520781,19.326496,40.572910,8.624856,16.549578,41.010948,9.195141,17.056709,40.766361,8.946638,17.612139,40.887844,8.847044,17.056709,41.059666,8.978929,20.603779,45.769257,9.018495,20.848125,45.189857,9.181762,20.989464,44.622959,8.745351,20.834969,45.258530,8.601304,20.606634,41.370117,9.883690,20.848125,41.636318,10.225545,20.993019,41.892422,10.824755,20.848125,41.599926,10.410389,15.776804,42.564003,12.798443,15.535313,42.702820,12.214387,15.390418,42.319031,11.849035,15.535313,42.218548,12.454916,15.776030,41.856968,8.450209,15.535314,42.528133,8.510641,15.390627,43.275497,8.537170,15.534328,42.576797,8.467686,16.549578,41.205654,13.911529,17.056709,40.804787,14.238071,17.612139,41.208172,14.317182,17.056709,41.629150,14.070342,16.549578,39.945190,14.109413,17.056709,39.688942,14.357088,17.612139,39.944622,14.496123,17.056709,40.182945,14.333038,19.833860,39.945190,14.109483,19.326729,40.182945,14.333248,18.771299,39.944622,14.496151,19.326729,39.688942,14.357088,19.833860,41.205654,13.913696,19.326729,41.629150,14.072439,18.771299,41.208172,14.318048,19.326729,40.804787,14.239120,19.833860,40.846851,9.032740,19.326729,40.590584,8.693444,18.771299,40.822521,8.630757,19.326729,41.016350,8.870672,19.833860,39.939201,8.923197,19.326729,39.703125,8.738131,18.771299,39.938282,8.512333,19.326729,40.140987,8.627078,16.549578,39.939201,8.923197,17.056709,40.140987,8.627078,17.612139,39.938282,8.512333,17.056709,39.703125,8.738131,16.549578,40.846851,9.032740,17.056709,41.016350,8.870672,17.612139,40.822521,8.630757,17.056709,40.590584,8.693445,20.606634,41.201553,13.174086,20.848125,40.802273,12.754205,20.993019,41.174206,12.178209,20.848125,41.586468,12.636194,20.606634,39.946571,13.338995,20.848125,39.696236,12.840050,20.993019,39.947678,12.256458,20.848125,40.183331,12.813644,20.606634,39.942158,9.793884,20.848125,40.162659,10.353131,20.993019,39.946068,11.002531,20.848125,39.703171,10.419387,20.606634,40.940102,9.869663,20.848125,41.293877,10.449120,20.993019,41.079361,11.014093,20.848125,40.696865,10.384924,16.549578,44.552628,12.878180,17.056709,44.132458,13.321885,17.612139,44.811417,13.225415,17.056709,45.280964,12.798298,19.833860,46.179932,11.187347,19.326729,46.637627,10.758474,18.771299,46.598732,11.435049,19.326729,46.151917,11.908255,19.833860,40.775974,8.848234,19.326729,40.586731,8.810493,18.771299,40.502808,8.651121,19.326729,40.632202,8.613299,16.549578,40.928917,8.345609,17.056709,40.631138,8.277122,17.612141,40.508610,8.335531,17.056709,40.675358,8.404291,20.606634,44.084320,12.177360,20.848125,43.365238,11.911084,20.993019,43.414185,11.224264,20.848125,44.183357,11.479593,20.606634,41.859756,8.645319,20.848125,42.515766,8.733574,20.993019,43.151436,9.270849,20.848125,42.421101,9.153977,15.776805,45.519608,10.691351,15.535314,45.164154,9.930964,15.390419,44.456261,10.009944,15.535314,44.825378,10.792887,15.776805,41.477539,9.379562,15.535313,41.799423,9.943533,15.390419,42.488461,10.228368,15.535314,42.151829,9.587450,19.833860,44.550110,12.878242,19.326729,45.273403,12.798276,18.771299,44.810410,13.225441,19.326729,44.132458,13.322095,16.549578,40.775974,8.848255,17.056709,40.632202,8.613363,17.612139,40.502808,8.651131,17.056709,40.586731,8.810493,20.606634,41.477539,9.379536,20.848125,42.151577,9.587351,20.993019,42.488209,10.228354,20.848125,41.799423,9.943541,15.776805,44.086838,12.177302,15.535314,44.191170,11.479650,15.390419,43.415443,11.224245,15.535313,43.365238,11.910868,16.549578,42.714279,13.523938,17.056709,42.407764,13.874254,17.612139,42.801376,13.919114,17.056709,43.151917,13.643665,19.833860,41.010948,9.195141,19.326729,41.059666,8.978929,18.771299,40.887844,8.847044,19.326729,40.766361,8.946638,20.606634,42.564003,12.800610,20.848125,42.218548,12.457083,20.993019,42.319031,11.850119,20.848125,42.702820,12.215470,15.776804,41.370117,9.883690,15.535313,41.599926,10.410318,15.390418,41.892422,10.824539,15.535313,41.636318,10.225510,16.549578,46.263706,11.187594,17.056709,46.189728,11.908364,17.612139,46.632244,11.435135,17.056709,46.730152,10.758688,19.833860,40.928917,8.344918,19.326729,40.675358,8.403969,18.771299,40.508610,8.335269,19.326729,40.631138,8.276475,20.606634,45.435829,10.690967,20.848125,44.786308,10.792604,20.993019,44.414371,10.009431,20.848125,45.068546,9.930365,15.776805,41.859756,8.646147,15.535314,42.422363,9.154473,15.390419,43.159813,9.271541,15.535314,42.518848,8.734607,19.832001,46.647491,9.228939,19.320860,47.007702,8.854960,18.770052,47.188541,9.323408,19.326729,46.892601,9.726820,16.548603,40.842087,8.464530,17.054405,40.571327,8.624910,17.612028,40.368298,8.521025,17.056709,40.556873,8.370506,20.604713,41.856133,8.449955,20.837584,42.562088,8.471445,20.989799,43.246906,8.537576,20.848125,42.522797,8.509443,15.774969,46.030548,9.018173,15.531334,45.503017,8.597082,15.390241,44.755733,8.744715,15.535314,45.355331,9.182496,24.261827,54.602348,2.743626,23.823677,54.854084,3.140187,24.344059,54.854084,3.660566,24.740618,54.602348,3.222417,22.376629,54.602348,2.743626,21.897839,54.602348,3.222417,22.294399,54.854084,3.660566,22.814779,54.854084,3.140187,22.376629,54.602348,5.586406,22.814779,54.854084,5.189845,22.294399,54.854084,4.669464,21.897839,54.602348,5.107615,24.261827,54.602348,5.586406,24.740618,54.602348,5.107615,24.344059,54.854084,4.669464,23.823677,54.854084,5.189845,21.232874,53.711472,2.735930,20.871967,53.328190,3.115161,20.904251,53.776115,3.656068,21.242794,54.096931,3.222417,20.908245,51.697544,2.496432,20.657860,51.015137,2.956865,20.514696,51.698624,3.517878,20.696293,52.306728,3.015059,20.907904,51.695560,5.766437,20.696178,52.306728,5.248287,20.514553,51.697926,4.671840,20.657282,51.009670,5.223613,21.232866,53.711472,5.591953,21.242794,54.096931,5.107615,20.904247,53.776115,4.669659,20.871944,53.328190,5.201533,21.684166,51.696129,1.755586,22.202980,52.306767,1.549774,22.746681,51.694897,1.377290,22.190832,51.004185,1.516768,21.891165,53.711472,2.078727,22.376629,54.096931,2.088581,22.812550,53.776115,1.750607,22.276115,53.328197,1.719292,24.748486,53.711472,2.078938,24.366035,53.328194,1.719496,23.826591,53.776115,1.750606,24.261827,54.096931,2.088581,24.995792,51.691769,1.763228,24.497904,50.992481,1.520457,23.915279,51.693420,1.377350,24.453943,52.306759,1.550789,24.995964,51.688831,6.575236,24.453938,52.306759,6.779245,23.915472,51.689972,6.960100,24.498707,50.979469,6.841158,24.748486,53.711472,6.251095,24.261827,54.096931,6.241451,23.826590,53.776115,6.579428,24.366034,53.328194,6.610537,21.891157,53.711472,6.250879,22.276093,53.328197,6.610321,22.812546,53.776115,6.579428,22.376629,54.096931,6.241451,21.683901,51.693184,6.565994,22.190819,50.991150,6.832933,22.746702,51.691444,6.959399,22.202862,52.306767,6.778169,25.780415,51.690495,2.534033,25.969021,52.306747,3.048369,26.168991,51.689693,3.593027,26.060869,50.982422,3.049787,25.407001,53.711472,2.737001,25.395664,54.096931,3.222417,25.735447,53.776115,3.658218,25.771862,53.328194,3.121822,25.407001,53.711472,5.593030,25.771862,53.328194,5.208208,25.735447,53.776115,4.671812,25.395664,54.096931,5.107615,25.780508,51.688519,5.805637,26.061110,50.976974,5.321071,26.169020,51.688999,4.747628,25.969021,52.306747,5.281662,20.991644,48.495651,2.508850,20.807806,47.637970,2.989534,20.608034,48.512623,3.433689,20.707659,49.397144,2.930784,20.705687,49.369804,5.184958,20.605633,48.489624,4.577189,20.798357,47.572357,5.215831,20.986277,48.430210,5.761360,22.214104,49.342079,1.557495,22.778671,48.387920,1.446239,22.256304,47.507969,1.643343,21.741665,48.448315,1.828003,25.082729,48.304909,1.865089,24.559105,47.367794,1.651125,23.958595,48.339474,1.448419,24.528019,49.283630,1.567837,24.532076,49.218559,6.920103,23.965561,48.225666,7.126584,24.568680,47.211628,7.058434,25.088335,48.207943,6.743239,21.738838,48.351097,6.655560,22.253548,47.351528,6.991765,22.782265,48.274010,7.104169,22.214985,49.276894,6.887596,26.117302,49.233398,3.128913,26.291279,48.217098,3.758438,26.173384,47.247280,3.267383,25.897713,48.263092,2.672506,25.900778,48.197903,5.975608,26.176266,47.181942,5.552567,26.292252,48.194199,4.922173,26.118502,49.206173,5.405251,18.094341,32.383373,8.837021,18.493177,31.603941,9.005234,19.188620,32.410152,9.331537,18.767530,33.157570,9.109093,16.960360,32.277912,8.707836,16.215921,32.945656,8.870148,15.815405,32.064720,9.053257,16.503479,31.395937,8.788924,16.628141,35.151108,8.920589,15.611549,35.793186,9.042789,14.881084,35.033310,9.108450,15.875153,34.399277,8.934111,19.037966,35.841812,9.098384,18.291075,35.201908,8.996330,18.949696,34.554283,9.119417,19.660934,35.208141,9.225040,19.469601,42.740662,0.238309,19.433117,43.307892,0.570284,19.846607,43.343006,0.807461,19.880371,42.911831,0.531960,19.193474,45.246544,2.173964,18.656208,45.663681,2.639260,19.178385,45.938690,3.344779,19.647182,45.527817,2.880816,16.352318,44.530106,1.289220,16.922035,44.689426,1.370468,17.498732,44.201405,0.899389,16.821938,44.048290,0.829121,16.360548,43.555676,0.477745,16.251591,42.986015,0.040127,15.570593,43.285175,0.290377,15.710213,43.711391,0.657481,16.495224,40.309246,-1.212780,15.764177,41.018623,-1.012020,16.536884,41.805759,-0.614613,17.297455,41.119381,-0.804895,19.318949,41.662094,-0.342587,19.940855,40.857334,-0.557285,19.410534,40.244621,-0.863710,18.718750,41.069000,-0.646557,3.655526,43.450466,6.133356,3.917210,44.135937,6.479650,3.626668,44.897907,5.728198,3.461280,44.142445,5.309822,3.768682,40.662571,7.202424,3.514244,40.395718,6.571988,3.903845,40.070271,7.444897,4.220815,40.333397,7.982163,3.223619,40.014561,4.290448,3.261986,40.361221,4.990182,3.402462,40.652237,4.127518,3.512251,40.275925,3.430686,3.576496,43.559341,3.459339,3.431870,44.184731,3.999451,3.593069,44.953606,3.249681,3.846694,44.258034,2.737432,25.513506,31.941513,5.427284,25.539309,32.627705,6.133866,25.099325,31.939240,6.647770,25.164959,31.273289,5.904872,25.658295,34.595341,6.863572,25.816559,33.949440,6.243979,26.079689,34.601437,5.660179,26.014446,35.231815,6.324469,26.080318,34.590508,4.284768,25.791082,33.836147,3.492131,25.652956,34.566750,2.812664,26.026184,35.278023,3.625170,25.409628,32.226025,3.420637,25.418591,31.664379,4.135720,24.926109,30.612577,3.565418,24.800117,31.092829,2.730567,21.095810,41.550377,9.395765,21.217785,42.042343,9.386616,20.780640,42.242786,9.444677,20.614496,41.863655,9.448486,22.135332,43.224674,8.330988,22.711649,43.311230,8.112276,22.243822,43.726406,7.774492,21.767233,43.588741,7.959635,25.039377,41.788101,8.106493,24.407448,42.194660,8.315289,23.577057,41.993641,8.710601,24.260429,41.496807,8.542780,24.286749,40.477272,8.557722,23.638054,39.900978,8.763420,24.460104,39.191612,8.397221,25.052561,39.801479,8.138063,21.466780,40.523262,9.252094,21.040358,39.894894,9.188156,21.777393,39.270557,9.070107,22.250029,39.928017,9.091836,8.433331,42.285133,0.465114,8.306506,42.723179,0.669014,8.960808,43.010067,0.759800,9.141642,42.694466,0.580149,7.575225,44.246544,1.289817,7.037836,44.616119,1.259727,7.671263,45.246346,1.579921,8.156136,44.765438,1.697293,5.219538,43.817398,1.438046,4.679628,44.350655,1.768208,5.224856,45.072990,1.463671,5.813050,44.464703,1.250985,5.013192,40.882874,1.475165,5.431332,40.438061,0.963858,4.559555,39.845592,1.484119,4.259669,40.292446,2.054298,7.858221,41.232800,0.138597,8.330652,40.652237,-0.214231,7.323075,39.952538,-0.201047,6.842218,40.564842,0.212251,14.023061,42.970959,0.172709,13.933476,43.591370,0.620364,14.574996,43.704578,0.723812,14.718243,43.270046,0.343127,13.385616,45.503719,1.469335,13.950175,45.101673,1.360498,13.486347,44.403259,0.999772,12.822418,44.800400,1.129361,10.697933,44.845253,1.566337,11.110674,45.337769,1.658890,11.648140,44.715874,1.221796,11.113666,44.219994,1.146105,10.740158,43.334007,0.796836,10.552725,42.712234,0.466968,9.999329,42.876274,0.615676,10.206808,43.321373,0.874237,10.614775,41.620201,-0.101484,11.232458,41.020901,-0.453686,10.372677,40.180008,-0.737173,9.794902,40.808540,-0.392002,13.593451,41.781094,-0.482006,14.230164,41.003105,-0.959452,13.369435,40.275574,-1.143116,12.713617,41.082100,-0.657902,23.884071,33.906704,0.533629,23.459845,34.954391,0.024438,24.310223,35.585381,0.803387,24.733574,34.669525,1.350325,22.248114,35.441807,-0.960556,21.439005,35.119511,-1.494635,21.201498,35.952019,-1.572369,21.909153,36.339092,-1.123604,4.061588,29.233429,4.507588,4.585844,29.379642,3.174604,5.175663,28.498646,3.875855,4.747612,28.493187,5.226663,3.003036,30.052305,5.414947,2.718033,30.092667,6.745422,2.042023,30.968580,6.692735,2.371209,31.009777,5.314301,3.472492,29.964668,9.555144,3.382601,29.639421,8.340245,4.214945,29.271139,8.840994,4.307529,29.669044,9.919243,8.462001,42.960587,9.093489,8.741601,42.798592,9.256361,8.820696,42.959652,8.971132,8.600669,43.194782,8.748241,9.209240,43.594486,8.180479,9.393130,43.265755,8.561733,9.682656,43.359184,8.596958,9.430107,43.669327,8.169058,9.012018,42.497421,9.603197,9.077862,42.299221,9.836958,9.415810,42.227829,9.799488,9.293324,42.413048,9.578432,15.354053,42.388538,9.385880,15.330161,42.584461,9.311609,15.014091,42.587063,9.348255,14.970492,42.389507,9.420719,14.572369,42.824829,9.214210,14.835648,42.769268,9.227509,15.000443,42.897060,9.061989,14.813541,42.986752,9.032713,15.669405,43.245281,8.575179,15.442738,43.491783,8.335672,15.311912,43.345310,8.467144,15.473270,43.166641,8.629207,20.959618,43.358330,8.689161,20.808865,43.301968,8.861237,20.828083,43.134743,9.065055,21.024246,43.140606,8.935154,20.556675,42.683250,9.417372,20.617443,42.939270,9.305910,20.417009,42.953968,9.310896,20.302317,42.702133,9.418815,20.198975,43.107208,8.989729,20.397640,43.138687,9.084557,20.594770,43.289398,8.881474,20.468285,43.296967,8.770901,20.903751,44.404907,2.606201,20.804258,44.640457,3.081818,20.963671,44.599712,3.204902,21.123446,44.382942,2.627662,20.460377,44.586121,2.123620,20.560736,44.393219,2.087887,20.391041,44.258202,1.772337,20.234556,44.412006,1.702012,20.207691,43.653095,1.274592,20.351059,43.924568,1.558777,20.484673,43.811752,1.614829,20.376944,43.538818,1.340144,15.015850,46.233414,3.292839,14.874924,46.133213,2.765807,14.633363,46.516048,2.978833,14.846977,46.534985,3.583008,14.985077,44.159592,1.126777,15.016789,44.498688,1.419383,15.220592,44.474155,1.415512,15.268996,44.156521,1.114431,15.405750,45.651459,2.909639,15.243308,46.005806,3.398753,15.336630,46.167473,3.822838,15.570489,45.891361,3.243246,9.363096,44.876186,2.718860,9.147366,44.611732,2.213562,8.942506,44.809250,2.256751,9.226868,45.008484,2.842308,9.415782,43.507248,1.073583,9.440451,43.783318,1.321778,9.769610,43.918571,1.407425,9.807076,43.627052,1.144428,10.088305,44.801922,1.858036,9.907726,44.407478,1.747816,9.737715,44.546059,1.951278,9.856454,44.968201,2.143403,9.195217,44.349812,6.765765,9.349293,44.071995,7.471464,9.346082,44.198658,7.226388,9.210985,44.503651,6.468379,8.937008,44.835564,6.483410,9.068547,44.642273,6.281172,9.091391,45.013824,5.557676,8.978373,45.381920,5.793559,9.259549,45.011059,4.389821,9.262708,45.199619,3.658662,9.221248,45.529541,3.840469,9.206257,45.135517,4.599826,9.229460,45.001892,5.399853,9.340238,45.458984,5.051987,9.422031,45.472828,4.376982,9.288978,45.079956,4.754051,15.382416,44.484573,7.395391,15.265144,44.903740,6.891968,15.235215,44.457664,7.346303,15.362437,44.084820,7.764403,15.026039,44.887463,6.933871,14.952132,44.450195,7.569295,15.003832,44.122303,7.932838,15.093493,44.467144,7.399877,15.012382,46.027069,5.263702,14.889330,46.394852,4.620569,14.858572,46.165916,5.208954,14.978535,45.723747,5.782679,15.256342,46.211628,4.848751,15.159126,45.973221,5.364085,15.223189,45.693890,5.889566,15.299891,46.045761,5.405854,20.671314,45.016815,5.180271,20.528385,45.299400,4.779078,20.546347,45.368958,5.417351,20.672052,45.037308,5.800066,20.978893,44.742256,4.276071,20.941772,44.702679,4.059376,20.828959,44.746986,4.827159,20.886044,44.665997,5.085864,20.971882,44.484562,6.275035,20.904987,44.499241,6.057581,20.909779,44.331738,6.699851,20.997040,44.233318,6.894967,20.686502,44.094345,7.621376,20.794441,44.339233,7.062197,20.735081,44.596996,6.771547,20.651087,44.319450,7.375676,14.877958,37.789177,9.205044,15.640059,37.114601,9.131628,16.687731,37.718468,9.127989,15.936840,38.357426,9.191240,17.015436,40.155277,9.263128,16.308487,40.676365,9.324368,15.558273,40.124519,9.323111,16.202538,39.557087,9.256082,19.165674,39.415321,9.163006,19.810482,39.954659,9.207121,19.163275,40.613155,9.272415,18.465422,40.101265,9.225784,19.168285,38.212723,9.094489,18.382648,37.666245,9.090616,19.107447,37.045258,9.080528,19.859640,37.589546,9.071675,16.202579,36.451317,-2.517387,17.002420,35.901550,-2.587400,16.118103,35.168896,-2.754423,15.297996,35.749031,-2.676016,16.056639,33.758099,-2.879324,16.970219,33.166779,-2.832197,15.988213,32.160347,-2.885258,15.076024,32.819881,-2.899101,19.378056,36.675148,-2.070744,20.031197,36.156342,-2.010738,19.339941,35.589020,-2.289509,18.608467,36.068237,-2.359554,25.948086,37.169041,6.989071,26.144785,36.526321,6.403907,26.324450,37.213787,5.855883,26.223331,37.841465,6.500275,26.269772,39.142784,6.620964,26.425880,39.791344,6.076410,26.299347,40.344841,6.720931,26.024075,39.755928,7.230777,26.260040,39.332329,4.015261,25.983860,40.034695,3.383836,26.278669,40.533958,4.094924,26.421131,39.888050,4.752553,26.328613,37.293236,4.535668,26.159555,36.657173,3.768674,25.970285,37.399345,3.132144,26.227905,38.015713,3.898064,6.050307,39.689785,9.411827,6.579609,40.121273,9.563194,5.802719,40.643883,9.256547,5.279909,40.234821,8.993620,8.787542,39.169136,9.782139,9.365001,39.742748,9.843073,8.591672,40.454014,9.940115,7.977506,39.930511,9.814545,11.438626,39.449734,9.577003,11.827394,40.204502,9.603134,11.081974,40.599670,9.769644,10.652134,39.853416,9.745148,13.677517,40.754696,9.463804,12.991091,40.330517,9.478968,13.485975,39.766552,9.399684,14.215326,40.198166,9.393166,23.520111,34.917755,8.594223,24.055695,34.160545,8.285286,24.766584,34.703201,7.850743,24.275776,35.435192,8.225278,24.241423,31.991974,7.801909,23.811092,32.798794,8.333530,23.058544,32.164814,8.785341,23.536707,31.308102,8.272743,20.893457,31.548555,9.582999,21.726290,32.315498,9.424864,21.202873,33.112915,9.526125,20.394777,32.387524,9.617708,20.925970,35.177277,9.301153,21.456799,34.497948,9.336514,22.199539,35.093513,9.083281,21.650362,35.763130,9.124651,3.170561,36.944672,2.242609,3.789839,35.891861,1.522196,2.914148,35.410774,2.548569,2.367860,36.527760,3.279791,3.118523,32.661419,2.796576,2.374046,32.284355,4.093640,1.892385,33.390297,4.433372,2.630018,33.796093,3.145767,4.442765,32.054974,1.473752,5.428372,32.785187,0.422447,5.860311,31.660051,0.406439,4.867472,30.896875,1.537380,5.954578,34.587685,-0.225703,5.366552,35.476456,0.130687,6.321359,36.136627,-0.494741,6.941171,35.360847,-0.839575,9.511656,36.145607,-1.798338,10.157898,35.444275,-2.052896,9.145819,34.607761,-1.767550,8.532224,35.381252,-1.538265,8.673141,32.749107,-1.408348,9.374967,31.873360,-1.567135,8.243456,30.713562,-0.790382,7.513859,31.615730,-0.614573,12.123435,31.455462,-2.428349,11.277783,32.192703,-2.277817,12.337914,33.227081,-2.593678,13.171874,32.504723,-2.715487,12.576669,34.845325,-2.594908,11.836033,35.526875,-2.408813,12.807455,36.259701,-2.430546,13.559858,35.624088,-2.617388,24.006947,37.805027,0.629715,24.601387,38.346935,1.293342,25.164738,37.573795,1.794218,24.561089,37.013653,1.071424,23.346769,40.446892,1.114778,23.954428,40.960026,1.690548,24.898975,40.228241,2.141932,24.348804,39.678143,1.501620,21.763357,39.978733,-0.191605,20.971613,40.695164,-0.269921,21.140066,41.285282,0.172500,21.983757,40.598572,0.303238,21.539684,38.200211,-0.959106,22.128752,38.710411,-0.509066,22.771603,38.028286,-0.294628,22.123323,37.541859,-0.806211,20.567747,29.703054,9.379339,19.713566,28.747345,9.169988,20.209221,27.814093,8.875747,21.099480,28.723633,9.013975,22.749130,27.998205,7.371118,23.485937,28.855621,7.035340,23.200417,29.645149,7.958573,22.422346,28.754379,8.265304,15.836904,30.314020,-2.763508,16.703640,29.457262,-2.611807,15.595106,28.406321,-2.526192,14.751451,29.235065,-2.607021,11.909294,28.145176,-1.742775,11.038309,28.772562,-1.575136,11.979530,29.714016,-2.129831,12.855867,29.020884,-2.243544,8.275687,28.986349,-0.273320,9.292785,28.478928,-0.661549,8.722139,27.722273,0.045016,7.769694,28.129597,0.538040,6.276937,27.796942,3.348970,6.887235,27.687315,2.157648,7.233301,27.120678,2.914352,6.884157,27.257023,4.110354,7.793470,27.041533,6.063880,8.669847,26.772163,6.429321,9.357441,27.080448,7.712440,8.422405,27.310688,7.505586,11.039839,27.329372,8.787195,11.720129,27.045601,8.646088,12.599401,27.708048,9.237627,11.956539,28.034065,9.475441,13.992464,28.093153,9.252893,14.494763,27.561405,8.848677,15.179747,28.424440,8.976757,14.689010,29.041834,9.391209,16.126335,28.704735,8.507568,16.418648,27.998621,8.023718,16.895744,28.898691,8.115314,16.580435,29.689760,8.502854,17.649918,28.932774,8.241610,17.938038,28.014610,8.266794,18.541445,28.837482,8.798803,18.205147,29.823032,8.718040,16.388840,38.898300,-1.732666,17.145477,38.293541,-1.871784,16.294088,37.660904,-2.173162,15.529349,38.239189,-2.027254,19.448578,37.760033,-1.735584,18.716867,38.323250,-1.658794,19.478247,38.909397,-1.325756,20.198463,38.298843,-1.391041,5.173747,38.451378,8.953617,4.258423,39.279160,7.885384,3.901154,39.068012,7.370953,4.800067,38.249489,8.551922,2.727554,39.160549,4.151076,2.655098,39.080856,5.267880,3.000254,39.334396,5.710262,2.937779,39.509323,4.643666,23.858828,37.340439,8.495749,24.449736,36.663124,8.203696,25.095394,37.216740,7.876713,24.533415,37.894970,8.254860,21.897034,38.054417,8.963435,21.214926,37.518982,9.018875,21.813028,36.925598,8.983713,22.527439,37.449509,8.858568,4.040973,38.952930,1.638199,4.443141,38.356213,1.059176,3.542474,38.111599,1.953709,3.242851,38.760674,2.568137,6.607620,37.471008,-0.542522,5.950641,38.123032,-0.094771,6.906041,38.689919,-0.445963,7.558620,38.079987,-0.843321,9.810247,37.489201,-1.612583,9.161686,38.111774,-1.301437,10.082908,38.781124,-1.261806,10.729202,38.151131,-1.587553,13.012064,37.552799,-2.128527,12.305301,38.178852,-1.823578,13.192192,38.841217,-1.700752,13.908029,38.199059,-2.010273,16.137110,41.531448,9.370537,16.342218,41.941055,9.336552,15.754856,42.067223,9.387598,15.527685,41.757278,9.416822,16.919069,42.578121,9.013409,16.428835,42.557938,9.078739,16.814726,42.251575,9.193401,17.406322,42.315426,9.119555,19.497658,42.762707,9.084352,19.059422,42.699379,9.010694,18.503181,42.385124,9.125620,19.036484,42.403786,9.214436,19.347311,42.097713,9.369802,19.412537,41.601524,9.375134,19.963911,41.887405,9.435772,19.878342,42.283325,9.433168,26.473776,41.710762,6.031061,26.340698,42.030167,6.551597,26.063639,41.700924,7.196942,26.322838,41.311237,6.702703,26.468021,43.004982,4.415781,26.332531,42.792862,3.857716,26.074093,43.169323,3.201322,26.316929,43.404987,3.724519,4.944405,41.877808,8.421568,5.606923,41.518143,9.003946,6.087198,42.067497,9.071077,5.417143,42.428928,8.546814,7.790746,44.389404,7.786697,7.375212,45.034897,7.544454,6.857864,44.325974,7.992612,7.342098,43.808517,8.288912,9.111296,41.718472,10.092569,8.825257,42.035419,10.007848,8.325294,41.911476,9.949333,8.611139,41.460411,10.053463,10.599716,41.471176,9.891254,10.609966,41.822643,9.773834,9.961682,41.932648,9.894104,9.906816,41.690140,10.014002,11.043484,42.561680,9.258295,10.490797,42.415329,9.318902,10.989489,42.132736,9.492678,11.629772,42.294712,9.396162,13.859297,42.634460,9.341690,13.366020,42.715950,9.318364,12.831238,42.382847,9.401361,13.440112,42.298096,9.439035,13.882198,41.953499,9.496727,14.003317,41.547787,9.493675,14.662134,41.760094,9.470761,14.503714,42.069710,9.476454,24.208920,42.640694,1.877277,24.848749,42.190403,2.286074,23.897520,41.960682,1.821175,23.196686,42.492393,1.534485,22.668079,43.798183,1.636215,22.030933,43.754745,1.705641,21.725599,44.105160,2.058467,22.248869,44.183720,1.891002,20.732418,42.768963,0.949525,20.649826,42.339512,0.587212,20.312511,42.732475,0.673152,20.445089,43.044380,1.009061,19.192944,43.874115,0.808451,18.672699,44.121811,0.873826,19.185408,44.535130,1.308574,19.612230,44.289772,1.225624,16.319838,45.822536,2.938763,16.839031,46.139885,3.365532,17.469166,45.750465,2.659218,16.897209,45.413506,2.229106,3.720684,41.350410,6.936933,4.023534,41.793537,7.396476,3.687268,42.280209,6.563507,3.486298,41.794857,6.067219,3.502722,41.445702,3.956515,3.396708,41.855244,4.583507,3.551877,42.411491,3.711574,3.787750,41.976780,3.129482,21.674446,42.379807,9.184841,22.291359,42.362629,8.991476,21.952682,42.803497,8.827745,21.469669,42.806007,9.014248,25.195530,42.968887,7.548939,24.614319,43.330719,7.665503,23.934938,43.086269,8.015136,24.542501,42.742012,7.995062,7.755248,43.006996,0.823261,7.095841,42.982708,0.856092,7.562517,43.535675,1.019780,8.099459,43.501415,1.050629,5.232281,41.877876,1.479077,4.661405,42.190166,1.923735,5.235939,42.804123,1.449620,5.877163,42.517025,1.122937,13.304550,46.911190,3.113286,13.864573,46.673706,2.674852,13.349907,46.381729,2.130410,12.738029,46.654766,2.526729,10.928169,46.712395,3.264158,11.530765,46.562080,2.626621,11.016140,46.199821,2.328464,10.479442,46.362770,2.890440,8.860793,43.900738,7.846249,8.755232,44.390255,7.344118,8.451245,44.233074,7.682184,8.613896,43.748699,8.105330,9.373676,42.883423,8.897520,9.162333,42.820808,9.001308,9.382404,42.582241,9.253796,9.662260,42.612171,9.165419,14.935827,43.578049,8.559816,14.680539,43.384766,8.883882,14.863194,43.242691,8.836464,15.059408,43.387260,8.582537,15.496241,42.752491,9.122834,15.741070,42.781067,9.023086,15.501415,42.943665,8.871445,15.325512,42.882824,8.992964,21.205786,43.748028,7.879139,21.059561,43.918320,7.609335,20.949860,43.749130,7.995998,21.037960,43.616512,8.202868,20.608881,43.704453,8.181928,20.364994,43.460999,8.487205,20.545717,43.468361,8.485157,20.733910,43.656933,8.216705,20.819942,43.895969,1.869650,20.677692,43.972385,1.890818,20.700003,44.220215,2.143469,20.807659,44.184361,2.191471,20.279875,45.278717,3.145747,20.452477,45.253571,3.726965,20.587513,44.946842,3.252598,20.472263,44.942390,2.773749,14.915565,44.944771,1.730799,14.693748,45.244598,1.739642,14.896423,45.531746,2.163341,15.042075,45.176571,2.074013,15.596754,44.823227,1.757098,15.349753,44.763840,1.738608,15.252195,45.022945,2.089896,15.414182,45.127323,2.214154,9.205400,43.960953,1.503860,8.858727,43.921478,1.432443,9.121469,44.238388,1.777335,9.385209,44.240955,1.790706,9.621344,45.636543,3.449723,9.844092,45.885662,3.051585,9.749704,45.422581,2.692699,9.586985,45.259438,2.991346,16.956043,42.857441,8.820900,16.415777,43.002682,8.766665,16.937851,42.803291,8.886652,17.529137,42.752804,8.906631,19.683657,43.123741,8.742311,19.261957,42.926361,8.814993,18.687918,42.792690,8.902491,19.163105,42.894657,8.873127,26.472366,42.915436,5.651503,26.325068,43.234463,6.106559,26.088608,42.914093,6.736772,26.343040,42.614452,6.335709,26.467903,41.803719,4.713474,26.300411,41.495789,4.084436,26.013769,41.967304,3.397681,26.324448,42.211418,3.986218,5.788269,44.224880,7.900330,5.216504,44.932198,7.420547,4.738104,44.163033,7.375588,5.289921,43.530659,7.979772,7.137196,42.396526,9.320444,7.741253,42.306789,9.577517,7.924834,42.761745,9.257906,7.440155,42.929047,9.008154,11.654080,43.149033,9.168669,11.055611,43.193821,9.051364,10.504971,43.200336,8.956902,11.048511,43.003334,9.118950,13.951178,43.301109,9.143635,13.459326,43.253513,9.180355,12.871388,43.195965,9.233488,13.411813,43.113857,9.234901,24.478539,43.174824,1.890163,23.891838,43.542061,1.667872,24.588171,43.740681,1.881301,25.166431,43.349586,2.228896,21.855122,42.932907,1.295346,21.196234,43.011436,1.237040,21.137484,43.447838,1.503730,21.661819,43.383835,1.481658,7.291254,37.796696,10.152121,6.515455,38.555683,9.785301,6.329988,37.977295,9.909168,7.091729,37.071381,10.451539,9.665130,37.422703,9.924484,8.967931,38.050213,9.850516,8.380354,37.656677,10.084154,9.010545,36.996807,10.229880,12.190481,36.285877,9.724829,11.765453,37.008949,9.574726,10.984778,36.990917,9.789404,11.453276,36.297295,9.969658,14.868521,31.714993,9.518146,14.255239,32.271004,9.735215,14.036833,31.176563,9.913748,14.615067,30.666901,9.678622,13.223431,34.249500,9.954575,13.756520,33.813965,9.717247,13.752151,34.762833,9.480761,13.121450,35.213459,9.707340,13.022634,38.754349,9.351679,12.132223,38.551697,9.411444,12.300432,37.788925,9.379252,13.301867,38.037884,9.300049,11.455690,29.425661,10.288473,12.171398,29.233788,10.090166,12.945560,30.373934,10.217695,12.272629,30.600061,10.452026,11.344166,32.253578,10.859165,12.129278,32.095139,10.627954,12.492147,33.380402,10.445638,11.705737,33.467484,10.693054,10.061322,34.406925,10.878132,10.152146,33.522877,11.060076,10.989847,34.246017,10.759880,10.918894,35.156643,10.524273,8.300102,34.212585,11.205999,8.465163,33.170250,11.339855,9.127379,34.340191,11.022806,8.863836,35.355564,10.810649,7.138988,33.789528,11.736265,7.202330,32.784668,11.853859,7.632690,34.006916,11.459472,7.398132,35.041603,11.247725,5.699085,30.600351,11.825598,5.409961,30.113178,11.170126,6.285032,30.464533,11.405249,6.484322,31.066080,11.863697,7.811504,30.402567,11.180235,7.797123,31.174360,11.403013,6.989538,30.399899,11.198565,6.935330,29.713684,10.768495,8.845860,30.681845,11.187771,9.305579,30.170282,10.938971,10.068446,31.294735,11.105061,9.599314,31.780708,11.254596,5.281353,28.292953,7.411096,6.242042,28.269466,8.514221,6.048426,28.746328,9.387535,5.120740,28.691814,8.489653,7.792795,28.226849,9.062288,8.514724,27.971609,8.805993,9.663989,28.644346,9.865426,8.941702,28.878107,10.083736,24.679064,29.923122,5.343585,24.174637,29.071390,5.612272,24.045185,28.611065,4.461472,24.543144,29.536430,4.306330,19.775768,33.126724,-2.159569,18.795641,33.592144,-2.502895,19.492760,34.478642,-2.318794,20.395840,34.178448,-1.983997,23.347612,31.746683,0.446938,23.728918,30.652060,1.229431,22.720976,29.364489,0.533448,22.292992,30.441065,-0.216819,19.401745,28.793558,-1.756178,18.663607,29.760599,-2.210127,19.783899,31.136202,-1.948917,20.566280,30.149479,-1.399809,18.785360,26.963005,-1.555929,19.232382,26.408791,-1.084152,18.118483,25.888290,-1.375481,17.637453,26.319166,-1.754913,20.567863,25.713243,0.181046,21.082792,25.641041,0.635099,20.407343,25.324883,0.147796,19.751669,25.349583,-0.253818,10.609504,25.299990,6.089664,11.356866,25.175032,6.397600,12.083057,25.335354,6.688560,11.330961,25.473232,6.508770,8.865580,25.156914,4.161077,9.139832,25.057734,4.681299,9.472592,25.237553,5.206773,9.082703,25.353046,4.735400,9.400917,25.277456,0.958876,9.860744,25.094423,0.554338,9.457800,24.952873,1.035858,9.107605,25.094976,1.466708,13.356366,25.373632,6.997090,13.859785,25.242788,7.047640,14.292450,25.402620,7.084295,13.860067,25.553503,7.121702,15.803855,17.253407,7.735370,16.250694,17.493639,7.758923,15.785433,17.777622,7.716374,15.351631,17.499626,7.693994,17.745340,17.248734,7.625851,18.230999,17.488356,7.508670,17.720312,17.765234,7.615316,17.228552,17.489292,7.711205,23.277004,27.464796,3.631004,22.819227,26.865833,4.120916,22.554726,26.610193,3.048915,22.810558,27.090425,2.503948,20.968441,25.659777,5.391525,20.346920,25.374479,5.741878,20.852375,25.325106,5.208794,21.370850,25.597847,4.730995,18.978146,25.358122,6.819857,18.549744,25.193443,6.917104,18.942757,25.064272,6.684394,19.356346,25.230124,6.461783,14.382276,17.240221,-1.823940,13.724909,17.476353,-1.656780,14.408701,17.749981,-1.830038,15.069819,17.477400,-1.935068,11.576825,17.238007,-0.764759,10.876672,17.474226,-0.393341,11.585834,17.747839,-0.776312,12.309275,17.475241,-1.118519,8.193665,26.053516,3.285735,7.937076,26.434074,2.698253,8.281802,26.124407,2.096404,8.362856,25.763281,2.684943,14.607957,26.212618,7.729817,14.214724,26.516678,8.158690,13.512646,26.149492,7.830878,13.977930,25.929699,7.499854,17.682529,26.648554,7.779867,17.156780,26.247787,7.416904,17.467905,25.844234,7.376590,17.995604,26.130238,7.704603,22.112751,26.030281,2.713313,21.965824,25.773560,3.385759,21.957270,25.622980,2.580533,21.882156,25.808088,1.886068,11.872632,26.850245,-1.325567,12.687859,26.329403,-1.466516,11.848332,25.889748,-0.956919,11.073902,26.318035,-0.743269,17.366129,17.242384,-1.549915,16.560513,17.478241,-1.794386,17.379639,17.752998,-1.549604,18.201365,17.482401,-1.251326,21.078918,26.361042,0.310352,20.769390,26.671196,-0.149687,21.911863,27.492275,0.496765,22.084368,27.010513,1.032591,8.897411,26.255995,5.586638,8.588002,26.007977,4.597485,9.013812,25.754749,5.015388,9.451325,25.997683,5.900985,21.197430,26.252150,6.757412,21.406086,26.093302,5.869941,22.222839,26.548702,5.600569,22.108793,26.787115,6.614923,18.956964,26.049450,7.802048,19.257540,25.754456,7.317671,20.046856,26.076084,7.499784,19.745649,26.458836,8.121226,8.582459,25.266336,2.734214,8.717240,25.094395,2.337176,8.674360,24.959044,2.777841,8.638095,25.105837,3.188573,9.742395,26.275032,0.107907,9.304302,25.846893,0.732046,8.807577,26.204163,1.041567,9.108710,26.694223,0.378624,15.533568,26.272846,7.491265,15.806113,25.965078,7.244213,16.360662,26.302774,7.317457,16.119228,26.725887,7.562656,15.323531,26.873259,-2.206253,16.013487,26.309246,-2.047274,15.078038,25.871971,-1.882792,14.368145,26.320597,-1.932238,12.172807,26.083664,7.598483,11.515375,26.320045,7.745525,10.711830,26.025928,6.946969,11.378942,25.830845,6.958036,7.231470,58.768456,2.743626,6.793320,59.020195,3.140187,7.313700,59.020195,3.660566,7.710260,58.768456,3.222417,5.346270,58.768456,2.743626,4.867479,58.768456,3.222417,5.264040,59.020195,3.660566,5.784420,59.020195,3.140187,5.346270,58.768456,5.586405,5.784420,59.020195,5.189845,5.264040,59.020195,4.669464,4.867479,58.768456,5.107615,7.231470,58.768456,5.586405,7.710260,58.768456,5.107615,7.313700,59.020195,4.669464,6.793320,59.020195,5.189845,4.202791,57.877583,2.737001,3.843350,57.494305,3.121822,3.874458,57.942226,3.658218,4.212435,58.263039,3.222417,3.883598,55.851456,2.529496,3.632464,55.130745,3.030006,3.498637,55.852024,3.587784,3.674642,56.472874,3.048369,3.883599,55.851456,5.800533,3.674642,56.472874,5.281662,3.498637,55.852024,4.742247,3.632465,55.130745,5.300026,4.202791,57.877583,5.593029,4.212435,58.263039,5.107615,3.874458,57.942223,4.671812,3.843350,57.494305,5.208208,4.653353,55.851456,1.759744,5.172224,56.472874,1.550786,5.711637,55.852024,1.374782,5.153859,55.130745,1.508610,4.860855,57.877583,2.078938,5.346270,58.263039,2.088581,5.782072,57.942223,1.750606,5.245676,57.494305,1.719496,7.716884,57.877583,2.078938,7.332063,57.494305,1.719494,6.795665,57.942226,1.750606,7.231470,58.263039,2.088581,7.924387,55.851456,1.759744,7.423881,55.130745,1.508610,6.866100,55.852024,1.374782,7.405517,56.472874,1.550786,7.924387,55.851456,6.570288,7.405517,56.472874,6.779245,6.866100,55.852024,6.955249,7.423881,55.130745,6.821423,7.716884,57.877583,6.251094,7.231470,58.263039,6.241451,6.795665,57.942226,6.579427,7.332063,57.494305,6.610537,4.860855,57.877583,6.251094,5.245676,57.494305,6.610537,5.782072,57.942226,6.579428,5.346270,58.263039,6.241451,4.653353,55.851456,6.570287,5.153859,55.130745,6.821423,5.711637,55.852024,6.955249,5.172224,56.472874,6.779245,8.694141,55.851456,2.529496,8.903099,56.472874,3.048369,9.079103,55.852024,3.587784,8.945276,55.130745,3.030006,8.374949,57.877583,2.737001,8.365305,58.263039,3.222417,8.703282,57.942226,3.658218,8.734391,57.494305,3.121822,8.374949,57.877583,5.593029,8.734390,57.494305,5.208208,8.703281,57.942226,4.671812,8.365305,58.263039,5.107615,8.694141,55.851456,5.800533,8.945276,55.130745,5.300026,9.079103,55.852024,4.742247,8.903099,56.472874,5.281662,3.873849,52.232754,2.523499,3.630394,51.096512,3.035227,3.486765,52.231762,3.587367,3.632463,53.310429,3.030006,3.869959,47.735065,2.548141,3.608027,46.713249,3.115697,3.461733,47.729057,3.656043,3.622114,48.815636,3.056104,3.622921,48.812733,5.346651,3.463772,47.725475,4.834900,3.616037,46.697468,5.460260,3.871159,47.725018,5.894696,3.873819,52.232548,5.809386,3.632465,53.310429,5.300025,3.486805,52.231689,4.747026,3.630556,51.095932,5.309350,5.182577,48.820766,1.502745,5.777623,47.749023,1.365537,5.214008,46.745335,1.490239,4.673630,47.741802,1.741466,4.647590,52.232883,1.749799,5.153859,53.310429,1.508610,5.711460,52.232143,1.363893,5.159602,51.097538,1.507436,7.937559,52.233307,1.756714,7.446584,51.098686,1.528206,6.872874,52.232288,1.366662,7.423881,53.310429,1.508610,8.145096,47.756836,1.957729,7.663682,46.780937,1.688370,7.006509,47.757957,1.449137,7.537397,48.826508,1.606586,7.421651,48.818401,6.875964,6.869889,47.737698,7.100292,7.416899,46.725315,7.050823,7.925242,47.731934,6.675024,7.930720,52.232883,6.581942,7.423881,53.310429,6.821423,6.868517,52.231915,6.969728,7.423434,51.097065,6.832331,4.647054,52.232601,6.582638,5.155362,51.096325,6.834397,5.709624,52.231823,6.970003,5.153859,53.310429,6.821423,4.659238,47.727386,6.685667,5.178409,46.707481,7.045053,5.721562,47.731937,7.105692,5.161371,48.814709,6.886301,9.029340,48.830219,3.161368,9.166536,47.780663,3.773575,9.135579,46.839386,3.395349,8.895566,47.767105,2.775121,8.709554,52.233402,2.530369,8.945276,53.310429,3.030006,9.092595,52.232536,3.590649,8.962089,51.099430,3.056278,8.703220,52.233063,5.808644,8.943342,51.098438,5.307569,9.090113,52.232407,4.747262,8.945276,53.310429,5.300026,8.691614,47.745903,5.881199,8.934257,46.801838,5.466141,9.088326,47.773239,4.849865,8.935606,48.825272,5.337740,21.198435,45.577431,2.976879,21.020292,45.188793,3.704643,20.853231,45.623161,3.972754,20.931536,46.164345,3.248334,20.828754,45.554703,5.061335,20.969452,45.023033,5.821527,21.138092,45.382145,6.122525,20.898788,46.054989,5.425797,22.841118,45.273544,1.651151,22.329260,44.871189,1.913504,21.875511,45.443504,2.157019,22.310032,45.955276,1.779870,25.164028,45.028370,2.082236,24.609224,44.541523,1.832526,24.002611,45.132015,1.617172,24.590681,45.721920,1.747384,24.018223,44.803852,7.445757,24.629980,44.188835,7.402175,25.180229,44.749008,7.060466,24.606071,45.461639,7.217035,21.822031,45.157902,6.949138,22.289749,44.507607,7.354473,22.828970,44.944138,7.406357,22.287872,45.694542,7.131691,26.400490,44.777813,4.088473,26.280445,44.265511,3.580360,26.006748,44.907440,2.956738,26.229349,45.521080,3.425632,26.015621,44.719639,6.300688,26.287066,44.118149,5.899071,26.403305,44.711849,5.262624,26.234150,45.412182,5.720928,1.383757,32.105804,9.822752,0.888418,32.970039,10.268865,0.786680,32.877800,8.781107,1.297396,31.956287,8.357928,5.624967,36.702408,9.726112,6.092364,36.243530,10.248869,5.269578,37.319435,9.196943,4.728096,37.588711,8.677346,0.979654,36.437477,6.180526,1.152905,37.240086,6.828802,1.573006,37.740707,5.870984,1.464378,36.997337,5.092871,10.640613,43.636467,17.560520,11.127945,43.327492,17.687429,11.186071,43.418060,17.003183,10.699156,43.724133,16.932692,11.224274,42.427193,18.883764,11.579287,41.900612,18.928070,11.820650,42.103294,18.441862,11.440302,42.680328,18.395586,12.400656,41.042503,17.099457,12.282837,41.675709,17.105865,12.226131,41.606583,17.809080,12.339856,40.978340,17.749758,11.816995,42.251778,15.776215,11.459726,42.801861,15.754379,11.591554,42.921349,16.370401,11.970480,42.322872,16.397709,10.903972,41.153465,19.490114,10.894164,40.515339,19.423365,11.449034,40.561470,19.176458,11.401751,41.172913,19.274586,9.455125,39.844318,19.387535,9.396127,39.106689,19.097260,10.123302,39.110836,18.970963,10.182481,39.819824,19.342024,11.246976,38.312435,17.197390,11.345247,38.788216,17.886389,10.754776,38.569969,18.198198,10.695362,38.023521,17.534710,12.176579,39.816517,17.706989,12.195946,40.273441,18.102278,11.895339,40.086178,18.545242,11.868922,39.551552,18.112637,8.816532,40.691200,19.346497,8.970442,41.465820,19.247282,8.279595,41.548393,18.858974,8.100421,40.783710,19.033836,10.402067,41.874756,19.433128,10.547653,42.416584,19.172514,9.997547,42.655968,19.013046,9.808937,42.053795,19.310123,9.517836,43.706772,17.428450,9.162987,43.392120,17.845665,9.683737,43.306145,18.301594,9.963991,43.625854,17.849272,7.803814,42.789429,17.050518,7.397619,42.239830,17.440485,7.922172,42.288933,18.048643,8.279011,42.898380,17.679708,10.448299,40.538788,13.827451,11.038297,40.483112,14.255392,11.001045,39.680496,14.307176,10.439902,39.715061,13.792311,11.416005,41.755707,14.808179,11.795067,41.654213,15.239788,11.924763,41.049057,15.250425,11.517871,41.132645,14.742095,12.300236,39.923691,16.812857,12.163819,39.794319,16.206553,12.238573,40.398880,15.961878,12.378728,40.444939,16.563030,11.461056,38.440437,16.123421,11.142817,38.258575,15.385644,11.358484,38.939911,15.117504,11.729729,39.050552,15.822967,7.965772,42.930073,16.010960,8.563741,43.173653,15.672108,8.395577,42.690475,15.053970,7.751266,42.514641,15.368136,9.612264,43.829723,16.561630,10.116014,43.836800,16.359638,9.954021,43.658951,15.787051,9.379888,43.652729,15.990288,10.884872,42.492775,14.778506,10.354647,42.688942,14.679560,10.400327,43.183655,15.155837,10.910210,42.937328,15.187331,9.757586,41.398312,13.820820,9.050390,41.431839,13.805606,9.027035,42.149658,14.281208,9.726507,42.142044,14.216474,7.982870,38.605656,18.904011,8.020428,37.934647,18.573725,8.726948,37.855923,18.441326,8.678758,38.488071,18.848392,6.415208,37.263008,17.893410,6.351010,36.463009,17.300249,7.221926,36.540470,17.427361,7.257586,37.275627,18.070557,8.659591,35.703018,15.606989,8.763299,36.159515,16.440611,8.012281,35.989803,16.620064,7.955882,35.438667,15.786971,10.029442,36.960129,16.505974,10.065160,37.363720,17.211346,9.450746,37.274033,17.593077,9.463715,36.790207,16.905254,1.851162,38.154335,13.911339,1.301859,37.286118,13.788735,2.020586,37.531895,14.797551,2.501973,38.433388,14.885265,7.544156,34.608921,13.393520,7.391117,34.638863,12.719256,7.645870,35.215027,12.509720,7.923638,35.120426,13.198520,5.758008,38.105057,10.970224,4.841707,38.344074,10.568152,4.547251,38.702965,11.130140,5.514376,38.596855,11.382637,5.768581,31.633450,12.701207,5.227588,31.736084,12.880713,4.665818,31.227291,12.416597,5.328837,31.024441,12.347746,4.376160,35.445667,16.027613,4.450179,34.661102,15.408507,5.435857,34.824230,15.697820,5.385818,35.571545,16.388222,5.650802,38.099941,17.891554,5.813190,38.942467,18.058887,5.000113,38.953972,17.425884,4.754285,38.079700,17.296886,7.298654,39.457996,18.883728,7.340979,40.168839,18.806902,6.745008,40.318077,18.399403,6.652411,39.613808,18.543165,6.274401,41.564144,16.579828,5.927588,41.068081,16.953760,6.383213,41.061375,17.586290,6.638178,41.624954,17.213549,4.394379,40.185997,15.636218,3.804479,39.506207,15.765542,4.547284,39.687977,16.631256,5.000304,40.389351,16.485279,7.969231,38.030968,12.247637,8.647523,37.849243,12.679977,8.545982,37.097893,12.723786,7.932048,37.280762,12.179211,9.275920,39.163059,13.071501,9.857889,39.015560,13.413931,9.843003,38.284290,13.539473,9.300202,38.427437,13.086208,10.293535,37.049232,15.376041,10.002743,36.957806,14.677954,10.202143,37.537926,14.352841,10.561255,37.557613,15.007184,8.969149,35.806671,14.532410,8.600944,35.694771,13.746031,8.896210,36.308594,13.530190,9.344504,36.340199,14.266089,4.661377,40.353256,14.563022,5.478317,40.684303,14.375766,5.324811,40.165775,13.544838,4.398154,39.904621,13.651794,6.479555,41.703430,15.515640,7.033881,41.896072,15.119270,6.987267,41.450703,14.510417,6.348659,41.342831,14.851472,8.532766,40.065578,13.116962,7.814225,40.213745,13.180660,7.713718,40.871887,13.661910,8.419720,40.773548,13.482324,7.162262,38.931503,12.247163,6.283937,39.039764,12.103039,6.217770,39.670403,12.725767,7.099934,39.630352,12.733315,1.583738,34.134129,13.297394,1.458529,34.901161,13.764620,0.778181,34.725414,12.602996,0.934774,33.944988,12.125237,0.617838,35.065830,6.868267,0.904186,34.106964,6.303988,0.535994,33.869976,7.769970,0.276251,34.778950,8.316168,5.745071,36.947197,10.019817,6.463628,36.364956,10.735023,6.627949,35.721794,10.972883,6.021145,36.394890,10.233728,6.555745,32.763199,12.435990,6.832501,33.628059,11.976168,6.773343,34.500172,11.585847,6.721571,33.606506,12.160928,0.845905,37.258682,9.945154,1.571474,37.933483,10.332764,1.949369,38.073631,9.120066,1.212626,37.519737,8.600613,3.390265,38.374603,7.252129,2.677424,38.686119,6.156467,2.364761,38.460617,6.229774,3.074168,38.361435,7.227386,2.302397,31.559103,10.841593,2.983011,30.860111,10.655750,3.449924,31.255857,11.748114,2.821887,31.901730,12.000010,6.022746,32.996738,13.345593,5.829654,33.263153,13.802948,5.095910,32.889099,13.740449,5.404807,32.516769,13.354397,0.272551,36.303692,10.903170,0.113411,35.475948,10.365543,0.306368,35.443390,11.785437,0.460400,36.280128,12.273812,6.680289,33.548927,12.723189,6.783247,33.814148,12.280797,6.949374,34.512337,11.914103,7.008860,34.194546,12.418906,4.560906,37.893517,9.240921,3.626421,38.195946,8.388956,3.259617,38.326694,8.856283,4.218707,38.211452,9.558878,2.683717,33.590611,13.740681,3.050273,32.890343,13.278679,3.936049,33.127518,13.880572,3.635318,33.776627,14.383759,3.384420,36.146938,15.959093,3.559141,37.051441,16.326529,2.579281,36.847557,15.503638,2.384123,35.943420,15.162463,6.739693,37.182220,11.208508,7.337489,36.822968,11.681021,7.378692,36.125729,11.748730,6.891093,36.521160,11.213360,2.296830,38.639282,12.849714,3.276044,39.142647,12.787815,3.305515,38.872868,11.799603,2.278658,38.478481,11.744066,7.108541,34.345539,14.285381,7.153131,34.705158,15.059278,6.386074,34.427967,15.083261,6.430987,33.987091,14.364763,12.943272,34.797188,13.221987,12.505121,34.588634,12.885029,13.025501,34.643353,12.431173,13.422062,34.840652,12.804669,11.058073,34.797188,13.221987,10.579283,34.840652,12.804669,10.975843,34.643353,12.431173,11.496223,34.588634,12.885029,11.058073,35.155933,10.700817,11.496223,34.856102,11.065424,10.975843,34.782894,11.541187,10.579283,35.094704,11.145473,12.943272,35.155933,10.700817,13.422061,35.094704,11.145473,13.025501,34.782894,11.541187,12.505121,34.856102,11.065424,9.914596,35.682045,13.227076,9.555154,36.093876,12.892733,9.586263,35.702175,12.428499,9.924238,35.342201,12.804506,9.595402,37.578659,13.385048,9.344267,38.092751,12.881963,9.210442,37.615585,12.380846,9.386445,37.071552,12.925177,9.595402,37.653488,10.168221,9.386445,37.150776,10.797053,9.210442,37.642792,11.246094,9.344268,38.124371,10.579655,9.914596,35.938522,10.673490,9.924238,35.555511,11.140588,9.586263,35.797379,11.526018,9.555154,36.241089,11.001850,10.365155,37.552864,14.115477,10.884026,37.002960,14.317983,11.423441,37.544292,14.490606,10.865664,38.061039,14.358316,10.572659,35.633503,13.810177,11.058073,35.250816,13.800841,11.493876,35.556229,14.119701,10.957480,35.999546,14.150503,13.428686,35.633503,13.810177,13.043865,35.999546,14.150502,12.507469,35.556229,14.119701,12.943272,35.250816,13.800841,13.636189,37.552864,14.115477,13.135681,38.061039,14.358316,12.577904,37.544292,14.490606,13.117319,37.002960,14.317983,13.636189,37.654961,9.378854,13.117319,37.164066,9.303257,12.577904,37.653271,8.988990,13.135682,38.125412,8.979887,13.428686,35.980808,10.047853,12.943272,35.659023,10.074837,12.507469,35.928291,9.727884,13.043865,36.298782,9.656775,10.572659,35.980808,10.047853,10.957480,36.298782,9.656775,11.493876,35.928291,9.727884,11.058073,35.659023,10.074837,10.365156,37.654961,9.378854,10.865664,38.125412,8.979887,11.423441,37.653271,8.988990,10.884026,37.164066,9.303257,14.405943,37.578659,13.385048,14.614900,37.071552,12.925177,14.790903,37.615585,12.380846,14.657078,38.092754,12.881963,14.086750,35.682045,13.227076,14.077106,35.342201,12.804506,14.415083,35.702175,12.428500,14.446192,36.093876,12.892733,14.086749,35.938522,10.673490,14.446191,36.241089,11.001850,14.415082,35.797379,11.526018,14.077106,35.555511,11.140588,14.405943,37.653488,10.168221,14.657078,38.124371,10.579655,14.790904,37.642792,11.246094,14.614900,37.150776,10.797053,9.585756,39.082878,13.340698,9.344265,39.320126,12.818998,9.199370,39.083984,12.257327,9.344266,38.832306,12.840049,9.585756,40.355392,13.226897,9.344265,40.781891,12.689749,9.199369,40.327965,12.205163,9.344265,39.941208,12.780981,9.585756,40.093048,9.869661,9.344265,39.835411,10.385792,9.199369,40.232796,11.019484,9.344264,40.488476,10.450856,9.585758,39.078465,9.793882,9.344266,38.839252,10.419386,9.199370,39.082378,11.002705,9.344266,39.299400,10.353304,10.358484,47.168907,8.782812,10.865664,47.330788,9.565056,11.421726,47.597984,8.834164,10.866486,47.493313,8.014552,13.642813,42.286392,13.574532,13.135681,42.884567,13.667089,12.580252,42.373489,13.941577,13.135681,41.819092,13.921103,13.648883,40.869980,8.484203,13.135681,40.556873,8.373920,12.585972,40.400860,8.528542,13.159964,40.694031,8.657106,10.358528,40.581802,9.195140,10.865661,40.498158,8.946636,11.421092,40.458614,8.847042,10.865661,40.469292,8.978927,14.417427,46.229610,8.734388,14.657078,45.493851,9.161464,14.802956,44.852947,8.699162,14.662366,45.663860,8.237626,14.415586,40.941307,9.883688,14.657076,41.368534,10.226413,14.801971,41.464119,10.830145,14.657077,41.010391,10.412126,9.585756,42.136116,12.853422,9.344265,42.435452,12.242247,9.199369,41.891060,11.877072,9.344265,41.629852,12.510638,9.588153,41.874424,8.508289,9.344267,42.532463,8.571650,9.201536,43.300442,8.615625,9.353389,42.629917,8.535189,10.358530,40.359497,13.962122,10.865662,39.943737,14.261496,11.421093,40.362015,14.339645,10.865662,40.824600,14.117191,10.358530,39.081497,14.111044,10.865662,38.825008,14.357087,11.421093,39.080929,14.496847,10.865662,39.319744,14.337722,13.642814,39.081497,14.111044,13.135682,39.319744,14.337722,12.580252,39.080929,14.496847,13.135681,38.825008,14.357086,13.642815,40.359497,13.962122,13.135683,40.824600,14.117191,12.580252,40.362015,14.339645,13.135682,39.943737,14.261496,13.642814,39.999474,9.032739,13.135682,39.728733,8.693442,12.580252,39.975067,8.630755,13.135681,40.210121,8.870672,13.642815,39.075512,8.923195,13.135683,38.839218,8.738129,12.580252,39.074593,8.512331,13.135682,39.277672,8.627075,10.358530,39.075512,8.923195,10.865663,39.277672,8.627075,11.421093,39.074593,8.512331,10.865664,38.839218,8.738129,10.358530,39.999474,9.032739,10.865662,40.210121,8.870672,11.421092,39.975067,8.630755,10.865662,39.728733,8.693442,14.415586,40.355392,13.226897,14.657078,39.941208,12.780981,14.801972,40.327965,12.205163,14.657078,40.781891,12.689749,14.415586,39.082878,13.340698,14.657078,38.832306,12.840049,14.801972,39.083984,12.257327,14.657078,39.320126,12.818998,14.415586,39.078465,9.793882,14.657078,39.299400,10.353304,14.801972,39.082378,11.002705,14.657078,38.839252,10.419386,14.415586,40.093048,9.869661,14.657078,40.488476,10.450856,14.801972,40.232796,11.019484,14.657078,39.835411,10.385792,10.358530,44.543674,12.885654,10.865662,44.078987,13.326568,11.421092,44.803005,13.232336,10.865662,45.299747,12.822765,13.642813,46.404655,11.349192,13.135682,46.936039,10.921545,12.580252,46.790966,11.606344,13.135681,46.283649,12.030472,13.642813,40.762566,8.848300,13.135681,40.533089,8.810493,12.580251,40.489395,8.651157,13.135681,40.632202,8.613506,10.358530,40.928917,8.347429,10.865662,40.631138,8.278959,11.421092,40.508606,8.336408,10.865662,40.675358,8.405010,14.415585,44.076706,12.183372,14.657076,43.311764,11.916437,14.801970,43.403545,11.227125,14.657076,44.200581,11.492203,14.415585,41.859756,8.649830,14.657076,42.522068,8.751534,14.801971,43.169209,9.287680,14.657076,42.423832,9.157454,9.585759,45.622971,10.812782,9.344268,45.267166,10.027765,9.199372,44.503242,10.068990,9.344267,44.872444,10.855909,9.585756,41.464142,9.379616,9.344264,41.745865,9.943712,9.199370,42.475372,10.228983,9.344266,42.152122,9.588047,13.642813,44.543674,12.885638,13.135681,45.299747,12.822718,12.580251,44.803005,13.232330,13.135681,44.078987,13.326568,10.358530,40.762566,8.848300,10.865662,40.632202,8.613506,11.421092,40.489395,8.651157,10.865661,40.533089,8.810493,14.415585,41.464142,9.379614,14.657076,42.152122,9.588044,14.801970,42.475372,10.228981,14.657076,41.745865,9.943712,9.585756,44.076706,12.183388,9.344266,44.200584,11.492252,9.199370,43.403545,11.227135,9.344265,43.311764,11.916438,10.358530,42.286392,13.574532,10.865662,41.819092,13.921103,11.421092,42.373489,13.941577,10.865662,42.884567,13.667089,13.642813,40.581802,9.195140,13.135681,40.469292,8.978927,12.580251,40.458614,8.847042,13.135681,40.498158,8.946636,14.415586,42.136116,12.853422,14.657078,41.629852,12.510638,14.801971,41.891060,11.877072,14.657076,42.435452,12.242247,9.585755,40.941307,9.883688,9.344264,41.010391,10.412126,9.199369,41.464115,10.830145,9.344264,41.368530,10.226413,10.358530,46.404655,11.349701,10.865662,46.283649,12.030713,11.421093,46.790966,11.606547,10.865664,46.936039,10.922056,13.642813,40.928917,8.347425,13.135681,40.675358,8.405008,12.580251,40.508606,8.336407,13.135681,40.631138,8.278955,14.415586,45.622971,10.812267,14.657076,44.872444,10.855659,14.801971,44.503242,10.068722,14.657076,45.267166,10.027195,9.585758,41.859756,8.649841,9.344267,42.423832,9.157465,9.199372,43.169209,9.287746,9.344267,42.522068,8.751596,13.645124,47.173973,8.779522,13.143986,47.507214,8.006462,12.581909,47.599751,8.832828,13.135683,47.330788,9.564426,10.361642,40.868877,8.481338,10.880659,40.692013,8.648567,11.425547,40.400677,8.527414,10.865662,40.556873,8.373930,14.420119,41.878128,8.511345,14.669912,42.651901,8.546015,14.803926,43.307606,8.617172,14.657076,42.532463,8.571415,9.586062,46.221947,8.737489,9.347647,45.629990,8.243429,9.200808,44.844200,8.700077,9.344268,45.493855,9.162319,13.402231,42.636024,9.088137,13.843952,42.265190,8.927354,13.257099,41.468216,8.924333,12.761162,41.952751,9.049210,14.819143,43.992241,7.915632,14.867524,44.206844,7.727680,14.721256,43.188538,8.332035,14.570819,43.042439,8.481321,14.739729,46.129902,5.821756,14.486055,46.521713,6.008965,14.683518,45.890800,7.059349,14.836894,45.452190,6.847668,13.242226,47.253204,4.534075,12.634879,47.462841,5.345449,13.177191,47.470062,6.273857,13.726777,47.206486,5.488819,10.878733,47.097221,4.623746,10.353540,47.038342,5.568450,10.869761,47.400555,6.311962,11.443390,47.406887,5.379339,9.370897,45.719494,5.833216,9.243350,45.166649,6.839699,9.361156,45.721455,7.084311,9.589890,46.264736,6.070152,9.419018,43.765579,7.756795,9.651672,42.928501,8.369083,9.389878,43.078613,8.276138,9.264745,43.979362,7.652536,11.017797,42.609566,8.991407,11.562162,41.945824,9.013240,10.940653,41.458138,8.881577,10.449461,42.231049,8.830877,19.325565,40.862621,8.783956,18.778461,40.950840,8.838630,19.323936,41.426353,8.786276,19.815834,41.410198,8.725138,17.045193,40.854706,8.782622,16.517427,41.399200,8.718879,17.029068,41.407352,8.782855,17.608459,40.942589,8.838032,15.530382,42.831169,8.393164,15.397295,43.759182,8.132446,15.523479,43.301754,8.194286,15.751238,42.387825,8.470930,15.515415,45.667591,7.985306,15.716228,46.296017,7.506121,15.487558,45.853302,7.270651,15.384542,45.147564,7.790195,17.015114,47.285919,7.846012,17.558487,47.355572,7.233068,16.956881,47.210987,6.665669,16.469913,47.056335,7.317355,19.297382,47.002571,7.848345,19.772490,46.647942,7.325640,19.256296,46.900467,6.671225,18.730156,47.196068,7.234476,20.782345,45.331379,8.009128,20.875656,44.853928,7.839745,20.690250,45.428219,7.328630,20.512413,45.849098,7.533463,20.795416,42.786221,8.415985,20.543255,42.360294,8.496243,20.721622,43.206196,8.250131,20.886742,43.633301,8.181185,18.788540,42.199890,8.856282,19.314671,42.649040,8.782640,19.786526,42.671715,8.630753,19.322075,42.081429,8.767593,16.448059,42.636097,8.615016,16.981550,42.601173,8.778588,17.599436,42.175903,8.854607,17.010641,42.049759,8.761744,15.405568,44.661400,7.345426,15.483644,44.293022,7.592291,15.692327,43.533089,8.093293,15.515589,43.843227,7.898050,15.592047,46.373077,5.727751,15.404513,46.083035,5.770666,15.369089,45.667637,6.515650,15.455722,46.008270,6.489497,17.459688,46.907883,4.925709,16.832434,46.690060,4.493073,16.313332,46.779922,5.170751,16.890327,47.021198,5.537379,19.664225,46.397022,5.191458,19.179461,46.443546,4.498357,18.654243,46.768219,4.928941,19.209343,46.728245,5.546652,20.659138,45.216209,6.651112,20.513603,45.561165,5.873399,20.343811,45.873795,5.801173,20.585003,45.531876,6.586479,20.433254,43.459221,8.160431,20.588366,44.106945,7.685897,20.691757,44.380524,7.478016,20.637287,43.691452,7.991610,20.955544,21.995689,0.542318,20.378639,20.884184,0.052538,19.666655,21.873331,-0.330833,20.338610,22.967140,0.104796,10.735933,21.857067,6.125354,11.453905,20.824253,6.487245,12.201183,21.872526,6.738407,11.464145,22.886629,6.438548,8.948403,21.793833,4.279647,9.185922,20.778019,4.801987,9.585568,21.829556,5.272659,9.228405,22.824120,4.761068,9.901817,21.763821,0.601291,9.474391,20.737923,1.078545,9.192281,21.764566,1.572762,9.521221,22.769171,1.089234,13.473724,21.889194,7.109008,13.979879,20.851856,7.258632,14.417406,21.901793,7.287860,13.962120,22.923412,7.174541,16.084198,24.652401,7.225621,15.627295,24.897579,7.179741,15.203313,24.717203,7.193935,15.654970,24.329220,7.250765,17.848232,24.594507,7.150743,17.400099,24.799309,7.184474,16.978498,24.605892,7.229274,17.442541,24.249783,7.233531,20.454159,21.890385,5.495848,20.975502,20.885040,4.921961,21.363297,21.983227,4.342185,20.894482,22.967838,4.975667,18.805965,21.814596,6.950612,19.232424,20.785378,6.717060,19.562868,21.830162,6.374280,19.127880,22.831224,6.679688,14.041052,24.515005,-1.450439,14.752368,24.709219,-1.600168,15.384971,24.515928,-1.655098,14.685364,24.176153,-1.594790,11.093159,24.513990,-0.253325,11.821096,24.707905,-0.638672,12.577195,24.514280,-0.958506,11.807652,24.174683,-0.624388,21.864080,22.055059,3.015793,21.906322,20.998705,2.296720,21.734262,22.067152,1.676674,21.857857,23.123743,2.373190,16.750380,24.517298,-1.479759,17.487341,24.721718,-1.249039,18.186974,24.553942,-0.960138,17.440205,24.186554,-1.262032,8.806979,21.765053,2.487150,8.691978,20.739805,2.927934,8.713474,21.770830,3.342152,8.745564,22.772047,2.896865,16.147793,21.848255,7.425194,15.686411,22.888948,7.349921,15.267525,21.886497,7.379180,15.719341,20.827240,7.468669,17.990341,21.814125,7.273601,17.501730,22.827845,7.310515,17.070347,21.820787,7.406129,17.572567,20.782852,7.408289,13.912206,21.765154,-1.495417,14.614774,22.770201,-1.625469,15.243496,21.766123,-1.730562,14.545310,20.739763,-1.687286,11.037110,21.763660,-0.280770,11.770009,22.768560,-0.639114,12.483911,21.764265,-0.987873,11.712538,20.737955,-0.679512,16.650799,21.767246,-1.572258,17.409473,22.778576,-1.308744,18.163361,21.789209,-1.047398,17.395699,20.746300,-1.383448,21.038893,18.802763,0.453255,20.452122,18.404226,-0.031631,19.739830,18.741140,-0.435316,20.420630,19.266405,0.004441,10.693949,18.730612,6.205103,11.427160,18.372797,6.565599,12.186043,18.739031,6.836868,11.438623,19.222763,6.532020,8.848806,18.697893,4.347542,9.106552,18.349110,4.863808,9.513429,18.716240,5.344213,9.140568,19.189413,4.837313,9.807972,18.683216,0.556155,9.389928,18.329588,1.055817,9.098221,18.683266,1.570105,9.426126,19.161070,1.065558,13.485315,18.748102,7.237662,14.000710,18.387684,7.388958,14.453265,18.755093,7.452497,13.991782,19.243099,7.333105,20.614145,18.750500,5.458403,21.108173,18.405302,4.852198,21.498676,18.796982,4.225272,21.051313,19.267385,4.882096,18.982859,18.712532,7.047069,19.392027,18.356857,6.780394,19.740032,18.720339,6.415051,19.323626,19.196993,6.753250,21.974199,18.832897,2.876965,21.996727,18.460428,2.186349,21.824963,18.838814,1.569426,21.957983,19.347601,2.233651,8.705326,18.683310,2.522005,8.595456,18.330101,2.969690,8.604328,18.686165,3.399938,8.636823,19.162172,2.951796,17.022402,16.878435,3.225420,16.255877,16.878464,4.410990,15.941699,16.877991,2.963627,16.707846,16.878031,1.758523,17.325388,16.950607,-1.413651,18.098364,16.896177,-0.989367,17.257410,16.877661,-1.140816,16.499294,16.895618,-1.514194,20.379375,16.954674,0.043800,20.860771,16.897879,0.578627,20.187950,16.878300,0.252007,19.624334,16.896942,-0.265580,21.879381,16.958055,2.119545,21.756870,16.898745,2.730521,21.604893,16.878826,2.160567,21.603601,16.898529,1.577619,21.058983,16.955883,4.702253,20.526413,16.898495,5.249130,20.828382,16.879427,4.577373,21.332750,16.898680,4.001206,19.423588,16.953796,6.683033,18.993523,16.898329,6.866000,19.273209,16.879808,6.469523,19.716032,16.898367,6.229325,17.723179,16.953547,7.496658,17.206976,16.898071,7.452907,17.653830,16.879677,7.227736,18.164530,16.898247,7.252543,15.822847,16.953840,7.606355,15.404757,16.897396,7.434424,15.842409,16.878918,7.329330,16.271046,16.897831,7.501599,14.067017,16.952473,7.308075,13.589115,16.895096,7.044703,14.134451,16.876930,7.035965,14.553967,16.896471,7.288470,11.502629,16.949125,6.456723,10.844748,16.892288,6.008834,11.640888,16.874239,6.208778,12.305237,16.893637,6.627959,9.209707,16.945889,4.817457,9.058348,16.890129,4.295794,9.450881,16.872158,4.677206,9.697440,16.891075,5.203673,8.711195,16.944286,3.022049,8.927062,16.889748,2.624625,8.990895,16.871515,3.044449,8.827737,16.889675,3.435472,9.482788,16.945011,1.148784,9.968482,16.890778,0.729541,9.715757,16.872301,1.306643,9.298962,16.890142,1.716811,11.645649,16.946735,-0.638439,12.416752,16.892717,-0.853804,11.792306,16.874031,-0.397348,11.043074,16.891657,-0.155714,14.389627,16.948967,-1.681408,15.055918,16.894875,-1.648636,14.430758,16.876215,-1.402443,13.770093,16.893845,-1.375889,10.187481,16.872583,3.511150,10.011410,16.872356,3.044319,10.280354,16.872675,2.511909,10.560522,16.872982,2.976597,12.077200,16.874372,3.904194,11.509493,16.873859,2.916419,12.144654,16.874372,1.887563,12.760825,16.874931,2.877309,14.388997,16.876770,4.145499,13.931475,16.876097,2.837051,14.480982,16.876568,1.503141,14.927028,16.877195,2.833310,18.974531,16.878496,2.571977,18.972479,16.878801,3.776483,18.136108,16.879009,4.734473,18.068748,16.878674,3.515999,20.233328,16.878717,3.394365,20.007851,16.878939,4.159844,19.466291,16.879107,4.777339,19.617458,16.878874,3.991803,17.858910,16.877838,-0.296015,17.039619,16.877741,-0.115242,16.400866,16.877472,-0.772001,17.180355,16.877663,-0.822454,20.328331,16.878273,1.064157,19.633389,16.878201,1.055547,19.233923,16.878073,0.345942,19.965181,16.878201,0.494539,21.110870,16.878687,2.753935,20.885012,16.878546,2.476185,20.976751,16.878469,1.860106,21.286270,16.878641,2.213454,20.058704,16.879288,4.909665,20.288599,16.879051,4.301194,20.747578,16.878973,3.805657,20.557619,16.879227,4.438450,18.713186,16.879581,6.276804,19.055693,16.879444,5.788379,19.358070,16.879505,5.761333,19.092663,16.879648,6.222066,17.135445,16.879419,6.738122,17.631176,16.879398,6.287386,17.977554,16.879560,6.581743,17.568752,16.879574,6.912237,15.489407,16.878508,6.697104,15.952755,16.878773,6.288755,16.294403,16.879097,6.767590,15.862162,16.878880,7.002968,13.766851,16.876261,6.335301,14.291668,16.876896,6.012567,14.682870,16.877539,6.558934,14.210385,16.876930,6.717890,11.215048,16.873737,5.416366,11.951403,16.874338,5.345180,12.563049,16.874933,5.958383,11.800353,16.874289,5.921148,9.649339,16.872086,4.049175,9.992103,16.872450,4.220185,10.188310,16.872755,4.753446,9.730826,16.872301,4.513554,9.548716,16.871925,2.751204,9.645786,16.871964,3.076674,9.467975,16.871815,3.390851,9.315805,16.871717,3.067777,10.447095,16.872915,1.193178,10.210588,16.872650,1.794638,9.857518,16.872303,2.018301,9.986603,16.872496,1.488290,12.691612,16.874767,-0.197202,12.104418,16.874306,0.450717,11.426376,16.873755,0.423261,11.964908,16.874178,-0.118003,15.089554,16.876802,-0.901115,14.514148,16.876402,-0.367108,13.927824,16.875835,-0.662872,14.483148,16.876295,-1.078001,16.209309,18.729052,7.630613,15.746689,19.226286,7.571168,15.317283,18.747923,7.573232,15.767200,18.376722,7.648042,18.136240,18.712238,7.419456,17.633703,19.195141,7.493956,17.165829,18.715462,7.594269,17.679556,18.355509,7.558206,13.798547,18.685459,-1.596989,14.488782,19.163567,-1.746355,15.138858,18.686472,-1.858236,14.446386,18.332573,-1.790659,10.938070,18.683586,-0.352352,11.660109,19.161619,-0.719566,12.377064,18.684435,-1.070711,11.620787,18.330524,-0.749607,16.597073,18.687428,-1.710491,17.389053,19.168648,-1.452200,18.187531,18.698708,-1.174421,17.384068,18.336561,-1.503767,21.088747,17.518286,0.399302,20.476763,17.259874,-0.061435,19.784615,17.497087,-0.498068,20.480116,17.793915,-0.063696,10.670115,17.490385,6.250935,11.427990,17.248829,6.585613,12.178890,17.494118,6.894455,11.416971,17.773346,6.595448,8.789417,17.477976,4.389501,9.084852,17.241251,4.887507,9.470978,17.484753,5.386189,9.076316,17.758242,4.887358,9.751122,17.473505,0.531624,9.363454,17.236431,1.062290,9.042183,17.473089,1.572158,9.357752,17.746557,1.047159,13.495192,17.498131,7.315082,14.025082,17.254625,7.442288,14.478847,17.501390,7.553748,14.008645,17.783384,7.438605,20.715294,17.501324,5.429049,21.169092,17.261097,4.785003,21.582155,17.516951,4.144478,21.158714,17.795073,4.825622,19.097111,17.488531,7.104305,19.483461,17.249233,6.794699,19.853697,17.491175,6.436502,19.452827,17.766136,6.804520,22.040245,17.528963,2.784069,22.021473,17.274414,2.114124,21.878483,17.530767,1.500791,22.031166,17.827898,2.144303,8.644945,17.472837,2.546937,8.567126,17.235962,3.002432,8.539195,17.473751,3.437750,8.558686,17.746548,2.985597,20.951891,24.900984,0.608355,20.332453,24.430702,0.137475,19.652702,24.695274,-0.260392,20.363670,25.023005,0.146567,10.710230,24.671049,6.069473,11.449066,24.327595,6.407932,12.166794,24.696194,6.668906,11.407397,24.896633,6.399131,8.966489,24.565901,4.205394,9.232037,24.247219,4.726922,9.578803,24.625492,5.211922,9.193039,24.797882,4.702491,9.929894,24.514862,0.609774,9.531578,24.175989,1.084377,9.207493,24.516548,1.542535,9.501439,24.709911,1.062890,13.427227,24.723310,7.006065,13.934728,24.374466,7.111243,14.355997,24.743629,7.140193,13.898697,24.953897,7.074942,20.338902,24.722910,5.584766,20.848375,24.431236,5.044329,21.297735,24.879370,4.515818,20.843502,25.023378,5.124622,18.637592,24.595230,6.887719,19.044106,24.254095,6.662900,19.408159,24.621439,6.375054,18.988703,24.804581,6.669715,21.841526,25.000483,3.194111,21.853411,24.633465,2.447822,21.735226,25.021048,1.788011,21.897285,25.273218,2.515360,8.825191,24.517639,2.423786,8.757668,24.179943,2.860086,8.739956,24.527424,3.264020,8.723694,24.714972,2.819584,16.049202,25.280020,7.107064,15.626073,25.499891,7.106329,15.154237,25.367895,7.094628,15.600877,25.175303,7.118093,17.766027,25.195095,7.117237,17.362053,25.370502,7.167252,16.929367,25.214537,7.135087,17.363237,25.058029,7.144728,14.152651,25.094164,-1.506651,14.909635,25.280712,-1.681049,15.540918,25.094416,-1.683546,14.818177,24.951321,-1.617565,11.075190,25.094021,-0.305427,11.834073,25.283434,-0.735859,12.623577,25.094124,-1.021584,11.826475,24.950163,-0.662628,16.898642,25.096003,-1.485601,17.687216,25.296940,-1.271872,18.293716,25.148430,-0.957207,17.539946,24.965937,-1.247286,19.533785,35.793198,13.148399,18.677385,35.577820,13.281847,18.714951,35.406166,12.449998,19.674879,35.675301,12.412270,17.706053,35.577820,13.281847,16.849653,35.793198,13.148399,16.708559,35.675301,12.412270,17.668488,35.406166,12.449997,16.849653,36.132767,10.776161,17.706053,35.942959,10.640371,17.668488,35.547115,11.522608,16.708559,35.810631,11.559360,18.677385,35.942959,10.640372,19.533785,36.132767,10.776161,19.674879,35.810627,11.559360,18.714951,35.547115,11.522608,16.282148,36.228943,13.148399,15.969662,36.938526,13.302199,15.611786,36.980999,12.442558,16.008234,36.207394,12.411618,15.815376,37.912651,13.383610,15.776805,38.944740,13.373240,15.390419,38.968933,12.337234,15.434692,37.959412,12.419312,15.776805,38.989624,10.043127,15.815376,38.025108,10.301592,15.434692,38.000301,11.333217,15.390419,38.985252,11.161409,15.969662,37.147480,10.560373,16.282148,36.517937,10.770300,16.008234,36.320244,11.556103,15.611786,37.056980,11.478217,16.549578,38.928368,14.121434,16.576075,37.877434,14.090236,17.621531,37.861145,14.457402,17.612139,38.923931,14.501676,16.682062,36.890751,13.940866,16.849653,36.184391,13.647086,17.706053,36.064617,13.903522,17.659096,36.842560,14.280309,19.533785,36.184391,13.647086,19.701376,36.890751,13.940866,18.724342,36.842560,14.280309,18.677385,36.064617,13.903522,19.807364,37.877434,14.090236,19.833860,38.928368,14.121434,18.771299,38.923927,14.501676,18.761908,37.861145,14.457402,19.833860,38.989632,9.229113,19.807364,38.030834,9.541103,18.761908,38.024834,9.160472,18.771299,38.989353,8.832416,19.701376,37.175720,9.875143,19.533785,36.568626,10.234909,18.677385,36.480820,9.970051,18.724342,37.146572,9.524059,16.849653,36.568630,10.234909,16.682062,37.175720,9.875144,17.659096,37.146572,9.524059,17.706053,36.480820,9.970051,16.576075,38.030834,9.541104,16.549578,38.989632,9.229113,17.612139,38.989353,8.832416,17.621531,38.024834,9.160472,20.606634,38.944740,13.373240,20.568062,37.912651,13.383610,20.948746,37.959412,12.419312,20.993019,38.968933,12.337234,20.413776,36.938526,13.302199,20.101290,36.228943,13.148399,20.375204,36.207390,12.411618,20.771652,36.980999,12.442558,20.101290,36.517933,10.770300,20.413776,37.147480,10.560373,20.771652,37.056980,11.478217,20.375204,36.320244,11.556103,20.568062,38.025108,10.301593,20.606634,38.989624,10.043127,20.993019,38.985252,11.161409,20.948746,38.000301,11.333217,15.776805,39.693569,13.348661,15.776805,40.183681,13.322007,15.390419,40.181572,12.243759,15.390419,39.698883,12.272806,15.776805,40.805363,13.239971,15.776804,41.605080,13.090813,15.390418,41.551235,12.129074,15.390418,40.792324,12.209067,15.776804,41.188171,9.921923,15.776805,40.655754,9.813422,15.390419,40.737923,10.999791,15.390418,41.400543,11.014869,15.776805,40.154350,9.767071,15.776805,39.703415,9.850561,15.390419,39.702457,11.035896,15.390419,40.170906,10.986504,16.539921,46.984970,8.818617,16.549578,46.800446,9.643381,17.612141,47.186867,9.775772,17.605637,47.361839,8.873623,19.833860,42.375820,13.629360,19.833860,43.074402,13.408179,18.771299,43.201767,13.790124,18.771299,42.428417,14.032927,19.831676,40.870289,8.589231,19.833860,40.857246,8.347646,18.771299,40.381893,8.399962,18.772167,40.402287,8.649986,16.549578,41.121799,9.207743,16.549578,40.874168,9.148829,17.612139,40.714275,8.825478,17.612139,41.032223,8.841198,20.595213,45.796921,8.686466,20.606634,45.726990,9.363960,20.993019,44.590176,8.991057,20.978794,44.658669,8.524318,20.606634,41.399349,9.936415,20.606634,41.319923,9.797066,20.993019,41.965313,10.699921,20.993019,41.805515,10.923679,15.776804,42.285492,12.904358,15.776804,42.853100,12.678347,15.390418,42.511875,11.714626,15.390418,42.123188,11.965489,15.773706,41.888660,8.502862,15.776805,41.860394,8.411728,15.390419,43.251198,8.645025,15.391253,43.324646,8.451694,16.549578,41.622822,13.819670,16.549578,40.804890,13.991617,17.612139,40.804741,14.390640,17.612139,41.633259,14.230046,16.549578,40.183121,14.090554,16.549578,39.689796,14.116518,17.612139,39.688560,14.501676,17.612139,40.182842,14.479468,19.833860,39.689796,14.116518,19.833860,40.183121,14.090835,18.771299,40.182842,14.479580,18.771299,39.688560,14.501676,19.833860,40.804890,13.993015,19.833860,41.622822,13.822466,18.771299,41.633259,14.231165,18.771299,40.804741,14.391200,19.833860,41.045177,9.117262,19.833860,40.600883,8.951628,18.771299,40.587139,8.542986,18.771299,41.005394,8.724667,19.833860,40.143147,8.888420,19.833860,39.703270,8.995123,18.771299,39.702995,8.588070,18.771299,40.140228,8.475566,16.549578,39.703270,8.995123,16.549578,40.143147,8.888422,17.612139,40.140228,8.475567,17.612139,39.702995,8.588070,16.549578,40.600883,8.951628,16.549578,41.045177,9.117262,17.612139,41.005394,8.724667,17.612139,40.587139,8.542986,20.606634,41.605080,13.093609,20.606634,40.805363,13.241369,20.993019,40.792324,12.209766,20.993019,41.551235,12.130471,20.606634,40.183681,13.322288,20.606634,39.693569,13.348661,20.993019,39.698883,12.272806,20.993019,40.181572,12.243898,20.606634,39.703415,9.850561,20.606634,40.154350,9.767071,20.993019,40.170906,10.986532,20.993019,39.702457,11.035896,20.606634,40.655754,9.813422,20.606634,41.188171,9.921922,20.993019,41.400543,11.015148,20.993019,40.737923,10.999931,16.549578,45.097672,12.590281,16.549578,44.000713,13.097431,17.612139,44.216396,13.456478,17.612139,45.395432,12.922446,19.833860,45.918556,11.731599,19.833860,46.365154,10.627390,18.771299,46.817295,10.836937,18.771299,46.301880,12.014052,19.833860,40.835922,8.716160,19.833860,40.743366,8.969619,18.771299,40.507603,8.722713,18.771299,40.525448,8.571336,16.549578,40.923798,8.451887,16.549578,40.915741,8.280842,17.612141,40.466747,8.301289,17.612141,40.538261,8.403174,20.606634,44.541016,11.919306,20.606634,43.618248,12.378714,20.993019,43.059822,11.407534,20.993019,43.764076,11.002424,20.606634,41.814568,8.823364,20.606634,41.877441,8.503183,20.993019,43.196758,9.013159,20.993019,43.067394,9.543430,15.776805,45.281609,11.164921,15.776805,45.696758,10.206802,15.390419,44.561474,9.630667,15.390419,44.301437,10.386394,15.776805,41.611603,9.203407,15.776805,41.363411,9.540365,15.390418,42.258137,10.401140,15.390419,42.725544,10.031919,19.833860,44.000713,13.097712,19.833860,45.087585,12.590250,18.771299,45.391399,12.922435,18.771299,44.216396,13.456590,16.549578,40.743366,8.969619,16.549578,40.835922,8.716248,17.612141,40.525448,8.571369,17.612139,40.507603,8.722713,20.606634,41.363411,9.540365,20.606634,41.611603,9.203301,20.993019,42.724537,10.031832,20.993019,42.258137,10.401168,15.776804,43.618252,12.378434,15.776805,44.551098,11.919355,15.390419,43.769115,11.002489,15.390418,43.059822,11.407394,16.549578,43.074402,13.406782,16.549578,42.375820,13.626564,17.612139,42.428417,14.031808,17.612139,43.201767,13.789565,19.833860,40.874168,9.148829,19.833860,41.121799,9.207743,18.771299,41.032223,8.841198,18.771299,40.714275,8.825478,20.606634,42.853100,12.679745,20.606634,42.285492,12.907154,20.993019,42.123188,11.966887,20.993019,42.511875,11.715324,15.776804,41.319923,9.797066,15.776804,41.399349,9.936415,15.390418,41.805519,10.923400,15.390418,41.965313,10.699781,16.549578,46.488522,10.627706,16.549578,45.968971,11.731759,17.612139,46.322044,12.014109,17.612139,46.866642,10.837044,19.833860,40.915741,8.279947,19.833860,40.923801,8.451442,18.771299,40.538258,8.403006,18.771299,40.466747,8.300949,20.606634,45.573391,10.206295,20.606634,45.231197,11.164675,20.993019,44.276230,10.386070,20.993019,44.499794,9.629971,15.776805,41.877441,8.504271,15.776805,41.814568,8.823894,15.390419,43.072433,9.543867,15.390419,43.209095,9.014088,19.833860,46.586929,9.643082,19.826422,46.679932,8.819501,18.766312,47.240292,8.873773,18.771299,47.101460,9.775680,16.549578,40.857246,8.348564,16.545681,40.868954,8.588964,17.611694,40.401287,8.650082,17.612141,40.381893,8.400302,20.606634,41.860394,8.410534,20.598951,41.885323,8.505159,20.980137,43.283833,8.456692,20.993019,43.229847,8.643888,15.776805,45.940506,9.364534,15.769463,46.106628,8.683550,15.389707,44.822029,8.519073,15.390419,44.696934,8.991947,24.661295,54.473801,2.822949,23.804895,54.684708,2.681856,23.842461,54.955914,3.641784,24.802389,54.684708,3.679350,22.833563,54.684708,2.681856,21.977161,54.473801,2.822949,21.836069,54.684708,3.679350,22.795998,54.955914,3.641784,21.977161,54.473801,5.507082,22.833561,54.684708,5.648175,22.795998,54.955914,4.688248,21.836069,54.684708,4.650682,23.804895,54.684708,5.648176,24.661295,54.473801,5.507082,24.802389,54.684708,4.650682,23.842461,54.955914,4.688247,21.409657,54.035954,2.822949,21.096064,53.310448,2.651069,20.737032,53.345932,3.623788,21.135744,54.144329,3.679350,20.937346,52.303654,2.527923,20.904736,51.014198,2.480694,20.508232,51.015011,3.486512,20.550892,52.309803,3.551804,20.904016,51.006268,5.761211,20.937191,52.303654,5.759129,20.550829,52.309803,4.692145,20.507914,51.012222,4.643807,21.096033,53.310448,5.670366,21.409657,54.035954,5.507082,21.135742,54.144329,4.650682,20.737020,53.345932,4.689027,21.683044,51.008461,1.751204,21.702599,52.303673,1.784449,22.751375,52.309853,1.408031,22.748585,50.999893,1.373565,21.809374,53.310452,1.942114,21.977161,54.035954,2.255445,22.833563,54.144329,1.981530,22.787073,53.345943,1.585091,24.661295,54.035954,2.255445,24.833855,53.310448,1.942958,23.854113,53.345940,1.585084,23.804895,54.144329,1.981530,24.959711,52.303665,1.788672,25.021240,50.991055,1.764039,23.926601,50.994011,1.373950,23.900723,52.309849,1.407996,25.021919,50.979301,6.599726,24.959711,52.303665,6.541359,23.900707,52.309849,6.922044,23.927441,50.980217,6.985722,24.833855,53.310448,6.387074,24.661295,54.035954,6.074588,23.804895,54.144329,6.348501,23.854111,53.345940,6.744949,21.977161,54.035954,6.074588,21.809343,53.310452,6.386211,22.787056,53.345943,6.744949,22.833563,54.144329,6.348501,21.702444,52.303673,6.537052,21.682632,50.996677,6.580846,22.748987,50.986084,6.982918,22.751299,52.309853,6.922044,25.815552,50.985977,2.541012,25.729441,52.303661,2.549370,26.112385,52.309834,3.594828,26.206913,50.979153,3.606405,25.548061,53.310448,2.655359,25.228802,54.035954,2.822949,25.502714,54.144329,3.679350,25.906389,53.345940,3.632394,25.228802,54.035954,5.507082,25.548061,53.310448,5.674673,25.906389,53.345940,4.697639,25.502714,54.144329,4.650682,25.729441,52.303661,5.780661,25.815922,50.978073,5.827576,26.207031,50.976376,4.766120,26.112385,52.309834,4.735204,20.950748,49.389538,2.483557,21.040880,47.619392,2.563277,20.665730,47.643852,3.472575,20.559935,49.399399,3.435007,20.948374,49.349876,5.749692,20.558830,49.385460,4.585118,20.660568,47.610397,4.606985,21.028896,47.524204,5.796416,21.714758,49.360683,1.789399,22.765656,49.323410,1.412636,22.793976,47.464352,1.488483,21.774029,47.551292,1.883143,25.062017,49.273716,1.819791,25.103573,47.342907,1.917357,23.970310,47.393887,1.487866,23.947338,49.294044,1.414830,25.065414,49.214951,6.678906,23.951649,49.225071,7.063340,23.980022,47.228348,7.199885,25.111725,47.201870,6.817472,21.713923,49.301765,6.618961,21.765739,47.409889,6.704741,22.797113,47.298664,7.169096,22.768272,49.254375,7.049324,25.870226,49.248367,2.613560,26.263428,49.219864,3.690287,26.318972,47.215908,3.837076,25.925262,47.282093,2.740521,25.872082,49.208858,5.909248,25.929718,47.187271,6.052176,26.320385,47.182602,5.002892,26.264015,49.205986,4.852218,18.177324,33.134892,8.889341,17.995171,31.588827,8.756260,19.017738,31.602995,9.279991,19.348206,33.164680,9.341786,17.005205,31.488976,8.636076,16.889210,33.032078,8.754730,15.582337,32.831085,9.059065,16.008774,31.270241,9.015671,16.709925,34.464729,8.854733,16.572763,35.818520,8.987076,14.661487,35.759834,9.143240,15.104338,34.308033,9.077705,19.718683,35.833214,9.168886,18.302458,35.842743,9.026421,18.273252,34.538937,8.962757,19.585869,34.557026,9.278811,19.805819,42.555973,0.245478,19.095982,42.992489,0.282079,19.725931,43.545280,0.848109,19.987534,43.173389,0.785828,19.650805,45.206146,2.320683,18.668377,45.278149,2.071203,18.644398,46.022461,3.240879,19.654388,45.826443,3.504170,16.279577,44.277683,1.069572,16.381598,44.813580,1.574029,17.512808,44.583771,1.219080,17.454124,43.795269,0.613297,15.955160,43.866508,0.763859,16.821140,43.163925,0.177412,15.689169,42.878956,-0.038546,15.435265,43.594593,0.575640,17.265837,40.336323,-1.100386,15.711531,40.276176,-1.298588,15.788784,41.729393,-0.705618,17.308529,41.920925,-0.475851,18.723745,41.849270,-0.337009,19.840960,41.512997,-0.311726,20.053762,40.170280,-0.785143,18.729637,40.305801,-0.923817,3.469095,43.460201,5.497575,3.941104,43.452579,6.715913,3.897084,44.898487,6.265221,3.455275,44.903004,5.140671,4.144621,40.648201,7.864510,3.497810,40.674145,6.473973,3.553690,40.120438,6.689116,4.346284,39.991558,8.124145,3.370992,39.934658,3.517357,3.204568,40.087250,5.086914,3.309745,40.664516,4.913003,3.620070,40.655010,3.369736,3.836099,43.612553,2.822979,3.426874,43.515305,4.136947,3.436735,44.931297,3.877842,3.855392,44.979824,2.665296,25.304482,31.304937,5.333323,25.694540,32.611599,5.498794,25.266111,32.628281,6.737349,24.909683,31.234840,6.504705,25.755796,35.231857,6.889616,25.544065,33.953758,6.833009,25.975683,33.951004,5.610080,26.163490,35.247604,5.708471,26.169493,35.270699,4.348208,25.964401,33.893257,4.226251,25.498571,33.789322,2.744760,25.772743,35.301228,2.893730,25.067001,32.037621,2.685907,25.630619,32.408390,4.138498,25.191488,30.990526,4.190781,24.519249,30.164049,2.859602,20.692066,41.485519,9.409875,21.505611,41.662674,9.351482,20.995392,42.349804,9.393710,20.554001,42.160812,9.464581,21.721043,43.371975,8.276139,22.636944,43.071705,8.356813,22.767738,43.593472,7.879349,21.785393,43.853603,7.621312,25.000977,41.405842,8.187939,25.089375,42.116646,7.990434,23.691648,42.301685,8.559827,23.451397,41.626102,8.833670,25.009867,40.408676,8.199800,23.484936,40.566593,8.854599,23.767948,39.228584,8.666460,25.097660,39.155983,8.057408,22.048264,40.587715,9.195532,20.913347,40.487041,9.272623,21.151041,39.278168,9.109516,22.411102,39.267303,8.994347,8.975927,42.314766,0.409416,7.899654,42.308281,0.559493,8.654875,43.063896,0.805471,9.281988,42.992062,0.729839,8.085790,44.363613,1.504012,7.013052,44.123837,1.144047,7.062778,45.205242,1.361913,8.241462,45.261189,1.892447,5.810915,43.905029,1.204965,4.673725,43.741051,1.792341,4.684771,45.039410,1.752684,5.816991,45.110916,1.296865,4.431132,40.765793,2.030383,5.697351,41.033150,1.000357,5.161014,39.865788,0.937573,4.048452,39.843777,2.102162,7.146936,41.210003,0.336306,8.563325,41.281223,0.004362,8.101047,39.990875,-0.422413,6.561311,39.921921,0.094356,14.577161,42.863377,0.028385,13.467062,43.181583,0.373075,14.327417,43.907501,0.853565,14.852640,43.580944,0.610763,12.799173,45.407787,1.401971,13.921053,45.591820,1.596379,14.013878,44.623001,1.165792,12.862144,44.136253,0.863680,10.692327,44.352844,1.340084,10.658159,45.337025,1.830557,11.631800,45.325989,1.506780,11.628309,44.043671,0.945888,10.446987,43.573303,0.995853,11.070898,43.002434,0.561273,10.037193,42.517616,0.410543,9.920366,43.139225,0.783314,9.931528,41.469517,-0.104268,11.332136,41.818146,-0.080873,11.109995,40.242313,-0.795506,9.630992,40.108772,-0.673342,12.835661,41.897911,-0.278336,14.328611,41.714264,-0.639034,14.143069,40.258751,-1.262444,12.604984,40.288773,-1.002438,24.533754,33.813850,1.254934,23.160452,34.052830,-0.158622,23.680956,35.749573,0.198350,24.897680,35.451340,1.466276,22.471436,36.140873,-0.766279,21.912035,34.698433,-1.185955,20.995565,35.437061,-1.721447,21.341005,36.509678,-1.418537,4.209832,28.855173,5.473520,4.006500,29.757769,3.603967,5.196748,29.005062,2.764693,5.322638,28.143938,5.051879,2.897669,30.569765,4.656910,3.193888,29.651310,6.225751,2.284041,30.561174,7.365766,1.882374,31.465614,6.058758,3.990062,29.973785,10.258913,3.006879,30.056414,8.815662,3.807238,29.259171,7.965413,4.678559,29.405794,9.662785,8.392833,43.200401,8.796813,8.569772,42.759789,9.348393,8.883932,42.800461,9.181362,8.782606,43.151207,8.728016,9.240860,43.805687,7.921389,9.173218,43.381073,8.401756,9.670978,43.165260,8.727930,9.672197,43.531807,8.434078,9.112859,42.536827,9.480585,8.883024,42.436172,9.721128,9.290020,42.173019,9.907021,9.528486,42.282970,9.661101,15.154708,42.287521,9.425303,15.526956,42.483669,9.327299,15.173956,42.659485,9.285534,14.804179,42.488194,9.400551,14.576193,42.954979,9.127216,14.601383,42.702961,9.294960,15.015461,42.806679,9.161982,15.000560,42.998077,8.946581,15.692623,43.113541,8.683714,15.630474,43.409367,8.432774,15.308939,43.532639,8.291105,15.311060,43.200027,8.605861,21.091232,43.276138,8.724421,20.860222,43.400734,8.669613,20.746881,43.207031,9.022560,20.939495,43.014519,9.110104,20.397141,42.564194,9.451437,20.704256,42.791023,9.350476,20.559914,43.044273,9.244831,20.227650,42.822529,9.356899,20.238171,43.189472,8.840566,20.176769,43.021530,9.135804,20.555073,43.208786,9.033021,20.637770,43.368977,8.711776,21.060736,44.259232,2.394816,20.792080,44.543427,2.768080,20.811491,44.717590,3.448563,21.161850,44.514187,2.900419,20.268084,44.613049,1.923585,20.591940,44.529396,2.273649,20.518675,44.258072,1.936796,20.201305,44.219120,1.546218,20.245129,43.464272,1.186430,20.184404,43.841743,1.351714,20.475386,43.976883,1.718037,20.504131,43.609497,1.475208,14.999457,46.405479,3.713415,15.033419,45.979248,2.920843,14.649801,46.271973,2.577965,14.632514,46.673527,3.461720,15.131908,44.000587,0.985849,14.863890,44.346653,1.256016,15.117949,44.615089,1.556900,15.383832,44.311058,1.238174,15.609913,45.589115,2.765637,15.266059,45.730415,2.998374,15.215452,46.215752,3.841502,15.511149,46.152130,3.780604,9.365292,45.003403,3.079373,9.355272,44.716122,2.406547,8.875058,44.537308,1.990509,9.025443,45.111267,2.558866,9.616867,43.431259,1.003117,9.220507,43.581326,1.143152,9.607271,43.961681,1.482146,9.963274,43.849106,1.300151,10.039666,45.155033,2.091820,10.103697,44.444248,1.653296,9.747707,44.336605,1.786672,9.707382,44.757683,2.138521,9.166281,44.516266,6.278096,9.231029,44.182907,7.214350,9.486874,43.939320,7.747809,9.251297,44.485596,6.676997,8.830811,45.268986,6.284245,9.032413,44.527828,6.716620,9.103407,44.733376,5.824430,9.087287,45.440723,5.302510,9.199987,44.919861,4.869983,9.313511,45.070549,3.923454,9.181145,45.492123,3.358920,9.211520,45.514191,4.325104,9.211453,44.889912,5.258383,9.247007,45.129433,5.583203,9.484948,45.761440,4.519168,9.380210,45.235252,4.266062,15.474746,44.035263,7.842961,15.323302,44.941242,6.913630,15.200552,44.851921,6.900961,15.269684,44.092144,7.735413,15.078044,44.851032,6.917344,14.979421,44.880577,6.999328,14.883088,44.061161,8.094091,15.101130,44.116951,7.819934,15.034070,45.661575,5.830768,14.996552,46.303940,4.708122,14.756671,46.494522,4.599411,14.929855,45.766483,5.809992,15.360632,46.243771,4.880939,15.169370,46.207508,4.834363,15.159744,45.641289,5.895395,15.280106,45.748489,5.914405,20.725830,44.896358,5.677547,20.619692,45.088436,4.679863,20.431313,45.523621,4.877305,20.631725,45.163795,5.931883,20.915354,44.730988,4.813749,21.075285,44.707287,3.735360,20.821608,44.774323,4.332491,20.840298,44.685875,5.329813,21.067596,44.333260,6.711909,20.911282,44.599636,5.817610,20.882320,44.472389,6.277610,20.934776,44.180748,7.084273,20.571598,44.011734,7.801672,20.785547,44.133877,7.447448,20.791159,44.545208,6.629571,20.687462,44.626568,6.913669,15.103927,38.400536,9.227398,14.659068,37.146027,9.190577,16.604715,37.099415,9.092110,16.788525,38.329685,9.159163,16.962690,39.547905,9.226547,17.044708,40.755554,9.295744,15.612061,40.634441,9.355791,15.457581,39.571129,9.288809,18.454103,39.478367,9.180529,19.853067,39.351768,9.146599,19.781254,40.531376,9.273872,18.494699,40.725601,9.270566,19.885084,38.162502,9.075652,18.417448,38.261532,9.112112,18.346878,37.069695,9.071979,19.817804,37.017246,9.086825,15.357422,36.393822,-2.549948,17.034277,36.512012,-2.451397,16.978420,35.269447,-2.693705,15.239382,35.075737,-2.775557,15.130282,33.615082,-2.888624,16.968018,33.913013,-2.815994,16.957472,32.355103,-2.819124,15.015034,31.980503,-2.876949,18.629227,36.633858,-2.227261,20.084568,36.679928,-1.884054,19.977049,35.654392,-2.103291,18.608355,35.489819,-2.456224,25.982624,37.823666,7.037517,25.899918,36.516838,6.949114,26.283014,36.552906,5.805300,26.357109,37.873898,5.908751,26.017698,39.128029,7.164923,26.406424,39.173050,6.023855,26.442162,40.367367,6.111889,26.028500,40.342579,7.278909,26.403088,39.269199,4.706175,25.995457,39.405468,3.330514,25.973913,40.619019,3.421899,26.436539,40.463375,4.782485,26.358519,37.962204,4.594090,26.289305,36.619087,4.475363,25.927547,36.709347,3.057872,25.993872,38.079124,3.201964,5.433685,39.796387,9.114087,6.702534,39.574345,9.607122,6.490877,40.663002,9.540241,5.173239,40.635479,8.894554,8.074767,39.308487,9.777519,9.521458,39.043091,9.743354,9.245963,40.395664,9.952679,7.907495,40.559071,9.875469,10.866886,39.191734,9.628479,11.951959,39.687672,9.531351,11.711917,40.762310,9.668347,10.477322,40.471542,9.857725,14.311940,40.679260,9.424422,13.021427,40.844784,9.510336,12.945668,39.843559,9.443117,14.087736,39.679569,9.360377,23.622974,35.543293,8.544395,23.410603,34.271362,8.650930,24.648390,34.058571,7.857883,24.872965,35.335426,7.843079,24.082716,31.246956,7.712537,24.386311,32.707283,7.844924,23.180683,32.900951,8.759573,22.926308,31.383589,8.765650,20.220154,31.574358,9.606441,21.584221,31.510471,9.435074,21.859356,33.065125,9.366644,20.560074,33.142906,9.579952,21.010046,35.796120,9.196544,20.827051,34.530357,9.408688,22.095753,34.446926,9.181752,22.295227,35.713505,8.993200,2.495690,37.295280,3.186569,3.928422,36.625763,1.383195,3.648157,35.106400,1.711666,2.249816,35.727394,3.439726,3.303147,33.468472,2.339933,2.968206,31.893623,3.339376,1.818499,32.687424,4.921291,2.004877,34.138988,4.015646,4.211907,31.195843,2.075547,4.707506,32.950981,0.980271,6.176498,32.682800,-0.079318,5.573693,30.626413,1.015399,6.732386,34.546692,-0.690874,5.183986,34.684067,0.318368,5.524658,36.216354,0.012804,7.117699,36.110138,-0.910872,8.711054,36.126675,-1.549961,10.319077,36.169613,-2.006130,9.981183,34.660553,-2.038515,8.325939,34.567455,-1.452974,7.798953,32.672592,-0.990519,9.574314,32.857712,-1.786911,9.221698,30.900156,-1.321100,7.272521,30.538900,-0.167483,13.081947,31.632631,-2.648180,11.163797,31.274927,-2.135332,11.412647,33.104206,-2.383976,13.266375,33.352032,-2.746511,13.462194,34.914536,-2.696339,11.698612,34.781189,-2.451725,11.966969,36.226704,-2.320560,13.654783,36.297592,-2.506641,23.954288,37.150772,0.500582,23.982197,38.449375,0.751325,25.167923,38.246670,1.886739,25.115778,36.888191,1.695029,23.636276,39.771297,0.993378,23.043186,41.108616,1.230568,24.793190,40.830826,2.208781,25.019831,39.581699,2.062161,22.328640,39.921211,0.143411,21.216221,40.034489,-0.460905,20.721392,41.327507,-0.061078,21.606058,41.269485,0.470100,21.507996,37.640457,-1.111794,21.513357,38.775936,-0.802111,22.735003,38.634300,-0.152829,22.725636,37.422882,-0.440161,21.275782,29.685469,9.235882,19.878584,29.724636,9.385523,19.543087,27.830793,8.893659,20.894306,27.822681,8.719044,22.189348,27.914814,7.954533,23.227512,28.106575,6.697693,23.710089,29.658016,7.328729,22.615616,29.652468,8.510629,14.852079,30.166426,-2.728998,16.827505,30.475130,-2.707214,16.551544,28.474798,-2.493984,14.646760,28.346216,-2.460064,12.798516,28.220400,-2.059122,11.049515,28.059292,-1.365038,11.044844,29.547800,-1.776976,12.922712,29.871887,-2.408106,7.414292,28.767660,0.430187,9.183455,29.186512,-0.859425,9.436804,27.848198,-0.472942,8.113443,27.584261,0.631579,6.412601,27.529875,4.493589,6.369462,28.147461,2.257417,7.348493,27.276459,2.072515,7.306204,26.980824,3.799735,7.533679,27.289251,6.618114,8.046004,26.800440,5.589028,9.395667,26.784321,7.185925,9.345938,27.405569,8.261259,11.134911,27.781298,9.245943,10.951286,26.927406,8.305703,12.469035,27.178768,8.857204,12.725354,28.304129,9.574118,14.091816,28.818203,9.512226,13.865158,27.441618,8.942835,15.069212,27.676369,8.687906,15.232481,29.241997,9.218470,16.169170,29.568344,8.742804,16.024065,27.900633,8.240640,16.786423,28.069170,7.879332,16.974070,29.778179,8.337137,17.769732,29.840546,8.455328,17.526821,28.073895,8.012354,18.399635,27.940964,8.547834,18.689713,29.789602,9.012595,15.586822,38.873219,-1.806967,17.184458,38.920769,-1.630770,17.107513,37.695339,-2.091490,15.473017,37.626453,-2.224655,20.175192,37.749569,-1.568806,18.690670,37.750019,-1.872599,18.734747,38.929054,-1.426491,20.193005,38.876175,-1.200731,5.548297,37.746681,9.372955,4.827894,39.066246,8.599619,3.745853,39.460377,7.085092,4.084626,38.663620,7.689951,2.970764,39.386032,3.865464,2.482427,38.936646,4.510761,2.981825,39.090721,6.035157,3.060765,39.580551,5.438549,23.881603,37.944092,8.525084,23.799747,36.746895,8.490784,25.040531,36.587486,7.851848,25.125793,37.852428,7.917918,22.549316,38.025524,8.871753,21.241709,38.083061,9.018881,21.158279,36.958942,9.048683,22.466833,36.882584,8.875430,3.533430,39.089687,2.352366,4.660199,38.836700,0.982163,4.248656,37.851185,1.158680,2.938961,38.409145,2.834718,7.415542,37.455132,-0.903210,5.805457,37.529514,-0.090720,6.116343,38.704571,-0.065859,7.712978,38.698292,-0.744171,10.601660,37.505402,-1.768543,9.018402,37.474510,-1.423695,9.307043,38.750362,-1.137005,10.853485,38.809048,-1.365065,13.828689,37.571667,-2.202122,12.201056,37.536846,-2.025614,12.405252,38.838390,-1.585524,13.985346,38.844028,-1.790485,15.590466,41.457291,9.404232,16.692076,41.659988,9.332209,16.032976,42.168842,9.337918,15.443205,41.987915,9.421450,17.445518,42.496094,9.038350,16.440788,42.692272,8.978674,16.372643,42.420544,9.179387,17.336433,42.079407,9.204599,19.501234,42.644073,9.202971,19.530670,42.873840,8.967054,18.539824,42.556786,9.038502,18.488121,42.156471,9.216709,19.693401,42.398640,9.383970,18.952351,41.738705,9.345091,19.856098,41.511230,9.394648,20.092560,42.183475,9.457321,26.466076,41.328381,6.090372,26.478439,42.045654,5.950038,26.078617,42.036259,7.101438,26.047966,41.316929,7.264539,26.458347,43.328312,4.335509,26.473368,42.717670,4.494648,26.073929,42.880562,3.252723,26.065754,43.491882,3.147248,4.880011,42.359768,8.187889,5.015570,41.437195,8.622152,6.242990,41.630562,9.306438,5.972332,42.521439,8.807663,7.757196,43.864613,8.200321,7.858433,45.014076,7.364654,6.857797,45.016895,7.667105,6.875202,43.730389,8.346527,9.121740,41.396286,10.089796,9.127757,41.942871,10.055748,8.537583,42.160080,9.902493,8.093163,41.573524,9.958305,10.113007,41.400696,9.999927,11.091138,41.594536,9.758822,10.186143,41.999107,9.761776,9.707185,41.892849,9.992896,11.632895,42.543518,9.305494,10.497553,42.611343,9.191345,10.451363,42.241550,9.461924,11.611206,42.024799,9.501635,13.912136,42.464874,9.402454,13.854376,42.812618,9.277803,12.819557,42.626678,9.336258,12.879549,42.112419,9.470613,14.238299,42.177982,9.472710,13.475788,41.676285,9.518625,14.526688,41.467098,9.465460,14.801226,41.988079,9.465576,23.433203,42.788239,1.586924,24.956604,42.513435,2.278511,24.765656,41.814209,2.280825,22.963736,42.141632,1.447624,22.758722,44.051273,1.685391,22.535967,43.582760,1.566798,21.613705,43.931232,1.914625,21.800562,44.314655,2.201934,20.607563,43.096493,1.128553,20.949203,42.370743,0.790102,20.379356,42.359402,0.422995,20.289993,43.024246,0.891021,19.609577,44.022057,1.042015,18.684931,43.707058,0.602274,18.673464,44.507736,1.186578,19.631804,44.576588,1.488961,16.358318,45.473171,2.401036,16.266045,46.149445,3.532706,17.450583,46.118816,3.251775,17.489862,45.358315,2.099247,3.489749,41.359371,6.230891,4.057227,41.357246,7.583652,3.994135,42.286907,7.185686,3.482215,42.290859,5.885448,3.752775,41.506168,3.227406,3.376269,41.405823,4.717807,3.410835,42.356812,4.436198,3.809466,42.482277,3.024199,21.343126,42.634628,9.180693,22.114180,42.086746,9.148769,22.431423,42.614166,8.806289,21.571445,42.989586,8.807953,25.173264,42.684097,7.701653,25.206135,43.291737,7.401620,23.979986,43.389297,7.836096,23.872234,42.823151,8.202971,8.212964,43.306728,0.949030,7.219214,42.664230,0.766100,7.028169,43.325310,0.940302,8.046147,43.743286,1.175364,5.917809,42.078819,1.086204,4.628116,41.717308,1.971776,4.670475,42.677082,1.872943,5.842041,42.953308,1.144658,12.712570,46.905613,3.067434,13.855949,46.874466,3.215137,13.884156,46.399155,2.237993,12.761578,46.337410,2.079114,10.406820,46.550522,3.396620,11.501292,46.811367,3.151835,11.563303,46.249413,2.189450,10.540468,46.111504,2.478533,8.806346,43.633244,8.164238,8.925622,44.154625,7.500720,8.548884,44.670818,7.237662,8.388406,43.836189,8.089914,9.658718,42.780212,9.002567,9.147835,42.986160,8.806289,9.180147,42.685539,9.182042,9.651906,42.469006,9.334738,15.082611,43.575974,8.406717,14.734475,43.537739,8.751289,14.636111,43.235970,8.971688,15.034302,43.236382,8.714071,15.319983,42.798351,9.108816,15.721146,42.677486,9.142089,15.731821,42.888542,8.900177,15.319733,42.976894,8.862974,21.184340,43.575195,8.197800,21.200109,43.948921,7.519156,20.957111,43.884548,7.729505,20.930973,43.622963,8.236034,20.753473,43.787628,8.020474,20.415571,43.578049,8.354675,20.323227,43.361202,8.594772,20.709400,43.547237,8.382470,20.904991,44.015495,2.022158,20.726557,43.784973,1.731668,20.642946,44.116249,1.994491,20.742384,44.327499,2.308214,20.287191,45.055626,2.644308,20.287041,45.473061,3.717538,20.577497,45.048901,3.702790,20.601597,44.814133,2.852221,15.042755,44.954441,1.868377,14.721130,44.892574,1.549672,14.680386,45.611004,1.969021,15.045740,45.423985,2.314790,15.623615,45.037628,2.023900,15.547697,44.637020,1.544698,15.224792,44.860806,1.875620,15.271300,45.215118,2.344465,9.420001,44.112171,1.659188,8.932929,43.780304,1.314890,8.826538,44.093285,1.579856,9.362020,44.386181,1.948059,9.535039,45.330914,3.377074,9.754610,45.985931,3.500026,9.914113,45.713688,2.677313,9.629333,45.129524,2.652496,17.556089,42.724243,8.893551,16.391687,43.063572,8.700466,16.426533,42.919460,8.824799,17.499838,42.717026,8.930222,19.631195,43.059258,8.796635,19.742599,43.161125,8.686914,18.730639,42.759869,8.891536,18.639111,42.762157,8.925034,26.478056,42.626789,5.754828,26.462358,43.241409,5.548182,26.078260,43.244308,6.612047,26.092533,42.621319,6.863798,26.472946,42.137890,4.647305,26.459984,41.422173,4.762995,25.988718,41.586185,3.428359,26.041077,42.300083,3.353588,5.829594,43.582573,8.209132,5.760955,44.954426,7.616108,4.707817,44.915638,7.124012,4.776521,43.492260,7.650733,7.002662,42.781124,9.025253,7.337824,42.045448,9.584799,8.078714,42.517349,9.524631,7.820411,43.061832,8.945293,11.642969,42.999336,9.194181,11.658058,43.162998,9.148228,10.489161,43.279938,8.894556,10.501331,43.031670,9.015220,13.911552,43.168087,9.182558,13.993774,43.354126,9.086455,12.880108,43.195915,9.213041,12.851567,43.060474,9.253474,25.127136,43.071510,2.248065,23.791365,43.290764,1.647728,23.953535,43.827660,1.677148,25.183712,43.660572,2.204348,22.124462,43.163879,1.398896,21.564417,42.684563,1.161429,20.957096,43.302551,1.375258,21.311905,43.607800,1.636170,7.487924,37.060139,10.460032,7.072441,38.435257,9.894304,5.968203,38.692486,9.557711,6.700966,37.124889,10.338633,9.617668,36.909958,10.137117,9.687221,37.884201,9.771595,8.290619,38.192539,9.903700,8.439635,37.043465,10.323008,12.003429,35.936485,9.952671,12.406187,36.607018,9.529080,11.102125,37.368294,9.625887,10.859095,36.571743,10.003008,15.074970,30.909101,9.486670,14.611860,32.503044,9.512465,13.898861,31.973633,9.948009,14.120570,30.378527,9.839875,12.892626,34.907352,9.949455,13.493727,33.526215,9.958754,14.052671,34.027485,9.483410,13.405436,35.478287,9.482403,13.625166,38.591675,9.307095,12.525499,38.961674,9.402438,11.686800,38.138931,9.443634,12.970949,37.477585,9.318371,11.524032,30.072432,10.511041,11.353043,28.829323,10.005897,12.910021,29.647991,10.065264,12.930339,31.123003,10.321741,11.188513,32.883503,10.889245,11.467718,31.523930,10.790926,12.708924,32.651871,10.425817,12.203440,34.029530,10.456657,10.400169,35.288673,10.571991,9.702931,33.447685,11.135881,10.587853,33.514194,10.980982,11.406589,34.923164,10.490332,8.411844,35.308720,10.916380,8.108565,33.089909,11.424221,8.849203,33.250439,11.271057,9.355071,35.370697,10.715883,7.148039,34.973087,11.306154,6.968837,32.700417,12.028492,7.474372,32.891449,11.683937,7.680687,35.137074,11.147985,6.220815,31.088511,12.076571,5.128549,30.275913,11.423094,5.739167,29.995159,10.972126,6.784549,31.085926,11.675731,7.423977,29.686228,10.798658,8.182721,31.237234,11.380445,7.442408,31.142803,11.446408,6.500379,29.793501,10.775707,9.087649,31.544664,11.317741,8.614732,29.903461,10.901251,10.027596,30.533724,10.944651,10.126532,32.031055,11.166262,4.749677,28.585745,7.500409,5.889687,28.037674,7.424085,6.627014,28.619659,9.457119,5.543887,28.938446,9.397778,8.084730,28.675915,9.830711,7.525393,27.862408,8.168504,9.504628,28.176697,9.357910,9.828411,29.184284,10.314615,24.836212,30.121899,4.788542,24.448887,29.786509,5.981155,23.871336,28.398535,5.213105,24.154434,28.906456,3.738887,20.656605,33.510082,-1.807947,18.859201,32.822289,-2.452374,18.712101,34.271255,-2.525873,20.154356,34.706043,-2.097118,22.567738,31.748598,-0.280070,24.029964,31.786106,1.190661,23.398016,29.520197,1.304067,21.977118,29.217428,-0.159427,20.308434,28.931204,-1.308664,18.464520,28.667589,-2.108255,18.803089,30.877785,-2.301683,20.762142,31.441875,-1.498285,17.931580,26.916508,-1.875025,19.619339,27.039036,-1.149652,18.872026,25.939966,-1.030718,17.363182,25.867472,-1.646976,19.859539,25.555538,-0.243057,21.192616,25.864962,0.674622,21.028408,25.458609,0.619765,19.703764,25.187656,-0.257547,10.601857,25.452940,6.168747,10.630384,25.157137,6.064131,12.100331,25.189880,6.661547,12.076727,25.491087,6.773190,8.825125,25.316479,4.191163,8.895635,25.019161,4.160836,9.497697,25.097443,5.191232,9.453571,25.391710,5.266458,9.065942,25.274426,1.415739,9.839514,25.279949,0.505309,9.879677,24.951675,0.578093,9.137776,24.954092,1.494596,13.358302,25.532780,7.070657,13.368906,25.225197,6.978261,14.299191,25.251574,7.080722,14.310404,25.565554,7.133140,15.361801,17.254976,7.690115,16.259071,17.251608,7.756442,16.241003,17.772903,7.736665,15.342707,17.781908,7.673467,17.236591,17.249132,7.706832,18.240137,17.248663,7.500089,18.211557,17.764919,7.495070,17.215137,17.766390,7.691497,23.246307,27.643232,2.802845,23.178156,27.288317,4.447289,22.493160,26.515366,3.844814,22.446501,26.654005,2.259220,21.459881,25.783243,4.843143,20.425529,25.541746,5.858528,20.323452,25.223600,5.681264,21.332602,25.429848,4.661174,19.410774,25.387148,6.569476,18.572475,25.349609,7.001726,18.559128,25.055302,6.888299,19.350451,25.089846,6.416319,15.057627,17.240728,-1.921831,13.717234,17.239676,-1.641331,13.740175,17.749443,-1.650320,15.085499,17.750484,-1.924957,12.308058,17.238550,-1.102604,10.881701,17.237507,-0.378750,10.886271,17.747379,-0.390008,12.321727,17.748354,-1.114330,8.369588,25.749050,3.223071,7.962412,26.374184,3.394142,8.047000,26.499142,2.040547,8.455196,25.782427,2.172271,14.469784,25.950836,7.457178,14.764319,26.565144,8.042613,13.612755,26.469404,8.209375,13.434557,25.904627,7.491465,18.123280,26.572363,7.983017,17.275124,26.716747,7.587138,17.055668,25.886326,7.282590,17.888130,25.803625,7.459881,21.987862,26.033440,1.955592,22.062862,25.981306,3.481160,21.916029,25.589525,3.324926,21.825895,25.616713,1.849458,11.072476,26.827904,-0.940609,12.715246,26.863819,-1.660145,12.667034,25.888868,-1.294872,11.072405,25.886629,-0.571650,18.194414,17.244255,-1.240273,16.549274,17.241543,-1.782824,16.570126,17.751354,-1.782553,18.200794,17.757185,-1.240602,21.689463,26.520235,0.874607,20.375118,26.187616,-0.186368,21.196760,27.313728,-0.124464,22.550476,27.660133,1.209805,9.450775,26.245169,6.267707,8.449924,26.282515,4.859420,8.692204,25.744658,4.400573,9.445942,25.770269,5.606531,21.560848,26.651880,7.175941,20.858459,25.958227,6.372021,21.891857,26.241007,5.279077,22.580679,26.944443,5.959805,19.157820,26.466986,8.186399,18.778513,25.752077,7.450062,19.762291,25.784937,7.096007,20.354906,26.484749,7.935666,8.583154,25.272030,3.183429,8.662448,25.267113,2.300385,8.752501,24.955650,2.363060,8.672297,24.968571,3.203704,9.676073,26.749407,-0.085437,9.785555,25.864889,0.280869,8.925160,25.826149,1.198393,8.641576,26.632215,0.880759,15.709005,26.674765,7.714236,15.373405,25.970127,7.309610,16.229179,25.949699,7.206742,16.507338,26.758133,7.467125,14.451317,26.872196,-2.112263,16.195719,26.878077,-2.202765,15.846015,25.866680,-1.905195,14.296077,25.878637,-1.768860,12.118776,25.853848,7.230514,12.249076,26.369316,8.014610,10.785316,26.279049,7.363778,10.652731,25.809309,6.594662,7.630938,58.639912,2.822949,6.774536,58.850815,2.681856,6.812102,59.122021,3.641784,7.772031,58.850815,3.679350,5.803204,58.850815,2.681856,4.946803,58.639908,2.822949,4.805710,58.850815,3.679350,5.765638,59.122021,3.641784,4.946803,58.639908,5.507081,5.803204,58.850815,5.648175,5.765638,59.122021,4.688248,4.805710,58.850815,4.650681,6.774537,58.850815,5.648175,7.630938,58.639908,5.507081,7.772030,58.850815,4.650681,6.812101,59.122021,4.688247,4.379298,58.202061,2.822949,4.066814,57.476559,2.655359,3.708935,57.512051,3.632394,4.105384,58.310436,3.679350,3.912527,56.469788,2.549370,3.873955,55.131420,2.522874,3.487570,55.130070,3.585436,3.531843,56.475964,3.594828,3.873957,55.131420,5.807158,3.912527,56.469788,5.780661,3.531843,56.475964,4.735204,3.487571,55.130070,4.744595,4.066812,57.476559,5.674672,4.379298,58.202061,5.507081,4.105384,58.310436,4.650681,3.708938,57.512051,4.697639,4.646729,55.131420,1.750101,4.673225,56.469788,1.788672,5.718681,56.475964,1.407987,5.709290,55.130070,1.363713,4.779212,57.476559,1.942960,4.946803,58.202061,2.255445,5.803204,58.310436,1.981530,5.756247,57.512051,1.585082,7.630938,58.202061,2.255445,7.798528,57.476559,1.942958,6.821492,57.512051,1.585082,6.774536,58.310436,1.981530,7.904514,56.469788,1.788672,7.931012,55.131420,1.750101,6.868449,55.130070,1.363713,6.859057,56.475960,1.407989,7.931012,55.131420,6.579930,7.904514,56.469788,6.541359,6.859057,56.475964,6.922044,6.868449,55.130070,6.966317,7.798528,57.476559,6.387074,7.630936,58.202061,6.074587,6.774536,58.310436,6.348501,6.821492,57.512051,6.744949,4.946803,58.202061,6.074587,4.779212,57.476559,6.387074,5.756247,57.512051,6.744949,5.803204,58.310436,6.348501,4.673224,56.469788,6.541359,4.646729,55.131420,6.579930,5.709290,55.130070,6.966317,5.718681,56.475964,6.922044,8.703785,55.131420,2.522874,8.665214,56.469788,2.549370,9.045898,56.475964,3.594828,9.090172,55.130070,3.585436,8.510927,57.476559,2.655359,8.198442,58.202061,2.822949,8.472355,58.310436,3.679350,8.868805,57.512051,3.632394,8.198442,58.202061,5.507081,8.510927,57.476559,5.674672,8.868804,57.512051,4.697639,8.472355,58.310436,4.650681,8.665214,56.469788,5.780661,8.703785,55.131420,5.807158,9.090172,55.130070,4.744595,9.045898,56.475964,4.735204,3.873954,53.311008,2.522874,3.873532,51.097046,2.525377,3.484355,51.096004,3.593160,3.487570,53.309853,3.585436,3.871839,48.816986,2.535389,3.866858,46.720566,2.571382,3.451697,46.706936,3.705696,3.471503,48.814423,3.624048,3.871229,48.812859,5.851733,3.472271,48.812927,4.793217,3.456635,46.698883,4.901606,3.874219,46.697693,5.970092,3.873410,51.096222,5.816072,3.873957,53.311008,5.807158,3.487571,53.309853,4.744595,3.484509,51.095703,4.754320,4.663968,48.819576,1.744056,5.752702,48.821999,1.367277,5.800291,46.754978,1.356045,4.681923,46.736626,1.740946,4.650175,51.097565,1.748892,4.646727,53.311008,1.750101,5.709290,53.309853,1.363713,5.717972,51.097519,1.364427,7.931012,53.311008,1.750101,7.957201,51.099247,1.776553,6.886151,51.098099,1.375508,6.868449,53.309853,1.363713,8.061953,48.827988,1.882360,8.237397,46.761433,2.025126,7.048935,46.778500,1.457713,6.956963,48.824905,1.422689,7.925179,48.819588,6.620158,6.869809,48.817429,7.034549,6.868496,46.728867,7.215645,7.932434,46.697105,6.791348,7.929845,51.097569,6.587976,7.931012,53.311008,6.579930,6.868449,53.309853,6.966317,6.868722,51.096603,6.979963,4.646729,53.311008,6.579930,4.648032,51.096432,6.590762,5.710626,51.096241,6.981059,5.709290,53.309853,6.966317,4.653249,48.813900,6.634091,4.669380,46.702793,6.775404,5.730315,46.713463,7.214217,5.715972,48.815613,7.040031,8.819168,48.829960,2.672788,9.138652,48.829914,3.689682,9.192012,46.848301,3.900162,8.986300,46.794228,2.902221,8.726862,51.099640,2.552856,8.703785,53.311008,2.522874,9.090172,53.309853,3.585436,9.099867,51.099102,3.606286,8.703785,53.311008,5.807158,8.701530,51.098270,5.813106,9.089937,51.098583,4.755267,9.090172,53.309853,4.744595,8.692506,48.823105,5.836897,8.702477,46.738205,5.978419,9.087718,46.829468,4.941556,9.088999,48.827328,4.797956,21.153620,46.135765,2.799209,21.214212,45.134804,3.176020,20.898321,45.199440,4.240685,20.794212,46.172272,3.742692,20.776541,46.116516,4.850102,20.871450,45.115181,5.306115,21.145199,44.893044,6.316410,21.110983,45.977119,5.972005,22.829370,45.883240,1.596667,22.838472,44.771465,1.691366,21.873356,44.966312,2.252974,21.849384,46.026321,2.053641,25.145386,45.680042,2.028860,25.178139,44.481892,2.130860,24.001488,44.604614,1.651006,23.994692,45.765808,1.575632,24.008614,45.489910,7.357973,24.019337,44.230011,7.549592,25.196754,44.163654,7.156006,25.158972,45.444981,6.975831,21.812906,45.790646,6.843507,21.810860,44.625198,7.099442,22.824329,44.392719,7.522744,22.823267,45.607098,7.316164,26.374195,45.469196,4.004835,26.424158,44.196274,4.171625,26.030581,44.342751,3.025002,25.980419,45.578693,2.885618,25.987848,45.420658,6.215523,26.040808,44.128876,6.392836,26.427410,44.121162,5.353027,26.376551,45.413685,5.175090,1.602999,31.574497,8.923369,1.261986,32.637257,10.747051,0.598778,33.348892,9.776753,1.074528,32.404205,7.808233,4.965814,37.324471,9.005303,6.191335,35.987862,10.441814,6.010502,36.596081,10.040716,4.502190,37.907364,8.351025,1.271389,36.247639,5.267049,0.802319,36.611969,7.102876,1.568558,37.783371,6.675004,1.689619,37.700584,5.030908,10.459212,43.777893,17.200666,10.810980,43.422165,17.940516,11.407351,43.167068,17.390821,10.927785,43.600494,16.630854,11.111707,42.799099,18.622305,11.290225,42.056137,19.084690,11.846165,41.697727,18.712948,11.731337,42.495808,18.125345,12.395597,40.752022,17.405334,12.352345,41.354904,16.755272,12.157236,41.980949,17.466974,12.233545,41.220734,18.106169,12.051619,41.977970,16.073483,11.564585,42.473778,15.521313,11.315168,43.123501,16.024075,11.833250,42.652210,16.732450,11.135411,41.425007,19.384718,10.604565,40.859844,19.547571,11.176912,40.206989,19.208355,11.659756,40.922031,19.084023,9.862928,40.198341,19.489975,9.048203,39.495934,19.262381,9.744854,38.754684,18.828218,10.499308,39.479954,19.095119,10.928097,37.929680,17.002457,11.548606,38.705723,17.382391,11.092384,38.953190,18.352129,10.408264,38.201401,18.030163,12.021404,39.465088,17.648001,12.282524,40.149193,17.712816,12.065689,40.457615,18.480556,11.673351,39.714912,18.539686,8.391237,40.347115,19.229074,9.248045,41.034264,19.441362,8.725566,41.884323,18.959223,7.846865,41.206848,18.741060,10.053318,41.641174,19.489811,10.707020,42.046761,19.333364,10.385324,42.787941,18.932503,9.592237,42.454163,19.044191,9.876006,43.768517,17.449341,9.118532,43.577934,17.370520,9.262433,43.137474,18.296484,10.084597,43.411007,18.250713,8.247632,43.106995,17.173283,7.374418,42.453842,16.923798,7.487988,41.950397,17.927433,8.372503,42.615822,18.158781,10.139619,40.155907,13.604761,10.745249,40.911545,14.065268,11.291967,40.068596,14.543218,10.696678,39.290291,14.082514,11.238343,41.524948,14.559343,11.544971,41.956566,15.057299,12.028791,41.338604,15.499253,11.764519,40.753780,15.014470,12.375984,40.234810,16.941322,12.173128,39.588188,16.678635,12.094320,40.070473,15.762177,12.329517,40.715534,16.181042,11.745662,38.838814,16.333347,11.156590,38.048695,15.910011,11.055614,38.546547,14.896131,11.645029,39.337097,15.343660,7.552880,42.594059,15.872268,8.391488,43.246983,16.154011,8.792146,43.016979,15.224741,8.010262,42.348557,14.895690,9.228658,43.710548,16.428198,9.952997,43.874821,16.704018,10.307734,43.723255,16.018795,9.579407,43.516823,15.586584,11.100111,42.599010,15.032118,10.645498,42.315792,14.528625,10.075847,43.024742,14.917916,10.713667,43.258839,15.415330,10.077166,41.754364,14.046427,9.432623,41.028294,13.612370,8.673614,41.795467,14.097645,9.385223,42.490215,14.481750,8.313628,38.879528,19.023075,7.646786,38.325706,18.752399,8.399673,37.576904,18.286253,9.047697,38.131363,18.566282,6.869615,37.660717,18.252739,5.928839,36.833893,17.478983,6.774440,36.129299,17.024752,7.650306,36.924953,17.783386,8.258016,35.352501,15.288850,9.048401,36.046608,15.896513,8.419119,36.354881,16.950676,7.592502,35.606102,16.252155,9.732424,36.671875,16.341990,10.317307,37.254604,16.657404,9.756083,37.556866,17.729780,9.137174,36.992115,17.433559,2.471458,38.697247,14.402164,1.292603,37.623596,13.338786,1.442926,36.941338,14.194471,2.649834,38.127552,15.326077,7.862686,34.879047,13.670412,7.261739,34.347355,13.147709,7.428614,35.009682,12.299595,7.898887,35.444756,12.748055,6.068090,38.242916,11.306164,5.461827,38.006107,10.605564,4.187231,38.572392,10.648527,4.932448,38.871418,11.568651,5.856701,31.369827,12.505138,5.742152,31.948814,12.882927,4.656815,31.654606,12.777253,4.749705,30.835316,12.059244,4.895979,35.917637,16.538528,3.877725,34.972630,15.491817,5.017062,34.387207,15.242831,5.872232,35.263859,16.149231,5.120843,37.654465,17.477463,6.138805,38.506077,18.245537,5.526774,39.365494,17.772722,4.427521,38.493202,17.018894,6.954112,39.177013,18.734732,7.635722,39.732002,19.000187,7.086114,40.592056,18.514776,6.390972,40.037006,18.252361,6.618901,41.838726,16.694908,5.907563,41.281429,16.434963,6.020426,40.779541,17.440790,6.727237,41.335609,17.701149,4.973349,40.601250,15.967804,3.769883,39.727047,15.256266,3.937867,39.219891,16.238058,5.109557,40.103970,16.969381,7.609695,37.764702,11.984261,8.333680,38.314308,12.497122,8.907560,37.401016,12.967517,8.192454,36.807419,12.469088,8.990435,38.880619,12.906723,9.552679,39.461510,13.231710,10.116567,38.588253,13.702311,9.560354,37.993965,13.373421,10.570250,37.352348,15.536855,10.007277,36.755730,15.209612,9.919018,37.243240,14.186239,10.475746,37.843727,14.515885,9.344597,36.136257,14.791525,8.586108,35.479469,14.252761,8.532289,35.995670,13.268844,9.262962,36.629391,13.777527,4.070568,39.929916,14.181345,5.214510,40.751839,14.897488,5.815808,40.530830,13.882911,4.809139,39.799202,13.157669,6.119506,41.422432,15.369259,6.818305,41.977654,15.632963,7.313046,41.725433,14.633764,6.644992,41.173531,14.360154,8.821231,40.355167,13.267425,8.234849,39.789074,12.955727,7.394376,40.596931,13.506212,8.021131,41.151909,13.797315,7.547833,39.220615,12.524590,6.774294,38.661171,11.943910,5.777021,39.361065,12.366152,6.646437,39.993912,13.043530,1.360720,33.651688,12.503984,1.909252,34.615620,14.037271,1.081858,35.201736,13.437430,0.590515,34.267479,11.708426,0.356688,35.349003,7.869758,0.984425,34.778675,5.887681,0.883677,33.483910,6.772220,0.290104,34.253677,8.790056,5.477855,37.003479,9.679447,6.009886,36.946251,10.350187,6.808581,35.763996,11.150135,6.460187,35.736889,10.799143,6.517027,32.896736,12.525421,6.643040,32.682182,12.325901,6.832670,34.688019,11.469121,6.758376,34.396683,11.685643,0.739077,37.009468,9.001184,1.052607,37.544975,10.834026,2.189140,38.234207,9.906119,1.769747,37.942986,8.299226,3.656495,38.175720,7.720621,3.174687,38.603851,6.812237,2.279398,38.580368,5.572747,2.534735,38.367702,6.870321,2.242060,32.101051,11.622357,2.455751,31.023783,10.085352,3.553236,30.773062,11.189604,3.432272,31.756672,12.324804,5.871559,32.644073,13.196705,6.226331,33.346684,13.513796,5.368915,33.272034,14.041746,4.877047,32.496712,13.439835,0.488058,36.691174,11.830875,0.179731,35.956787,9.909042,0.169621,35.031227,10.819660,0.567595,35.889797,12.686064,6.827218,33.815437,12.814016,6.579826,33.298668,12.657557,6.849474,34.413254,11.841177,7.081300,34.653831,12.004477,4.866850,37.899094,9.738056,4.254575,37.931801,8.726490,2.997684,38.299484,8.184838,3.544077,38.385761,9.506204,3.015953,34.047821,14.352331,2.435077,33.121449,13.088231,3.680717,32.700096,13.400955,4.255520,33.542587,14.338688,2.827961,35.622444,15.365944,3.969907,36.668785,16.507414,3.195876,37.427685,16.058037,2.001665,36.267410,14.888022,6.502702,37.067974,10.944324,6.992261,37.334972,11.463515,7.604053,36.315605,11.975434,7.180403,35.971401,11.535555,1.788328,38.239090,12.291532,2.864169,39.061287,13.331890,3.782567,39.144379,12.287649,2.871491,38.633320,11.252064,6.774903,34.020176,13.982077,7.471876,34.671803,14.614451,6.770904,34.819916,15.470892,6.022274,34.038490,14.709785,13.342738,34.929073,13.148398,12.486339,34.713696,13.281845,12.523903,34.542038,12.449997,13.483831,34.811172,12.412270,11.515007,34.713696,13.281845,10.658607,34.929073,13.148398,10.517513,34.811172,12.412269,11.477442,34.542042,12.449997,10.658607,35.268639,10.776161,11.515007,35.078831,10.640372,11.477442,34.682991,11.522608,10.517513,34.946503,11.559359,12.486339,35.078831,10.640373,13.342737,35.268639,10.776161,13.483831,34.946503,11.559360,12.523904,34.682991,11.522608,10.091102,35.364819,13.148398,9.778617,36.074402,13.302198,9.420740,36.116875,12.442557,9.817188,35.343269,12.411617,9.624331,37.048527,13.383609,9.585758,38.080650,13.373239,9.199372,38.104851,12.337233,9.243647,37.095287,12.419312,9.585759,38.125538,10.043127,9.624331,37.160980,10.301592,9.243647,37.136177,11.333216,9.199372,38.121166,11.161408,9.778617,36.283356,10.560372,10.091102,35.653809,10.770300,9.817188,35.456116,11.556103,9.420740,36.192856,11.478216,10.358530,38.064278,14.121433,10.385028,37.013306,14.090235,11.430485,36.997017,14.457401,11.421093,38.059841,14.501675,10.491016,36.026627,13.940865,10.658607,35.320267,13.647085,11.515007,35.200493,13.903522,11.468050,35.978436,14.280308,13.342738,35.320263,13.647085,13.510328,36.026627,13.940865,12.533295,35.978436,14.280308,12.486339,35.200493,13.903522,13.616317,37.013309,14.090235,13.642814,38.064278,14.121433,12.580252,38.059841,14.501675,12.570860,36.997017,14.457401,13.642815,38.125549,9.229111,13.616317,37.166706,9.541103,12.570860,37.160709,9.160471,12.580252,38.125275,8.832415,13.510328,36.311592,9.875143,13.342738,35.704506,10.234909,12.486339,35.616692,9.970051,12.533295,36.282448,9.524059,10.658607,35.704506,10.234909,10.491016,36.311592,9.875143,11.468050,36.282448,9.524059,11.515007,35.616692,9.970051,10.385028,37.166706,9.541103,10.358532,38.125549,9.229111,11.421093,38.125275,8.832415,11.430485,37.160709,9.160471,14.415586,38.080650,13.373239,14.377014,37.048527,13.383609,14.757698,37.095287,12.419312,14.801972,38.104851,12.337233,14.222728,36.074402,13.302198,13.910243,35.364819,13.148398,14.184156,35.343266,12.411618,14.580605,36.116875,12.442557,13.910242,35.653809,10.770300,14.222728,36.283356,10.560372,14.580605,36.192856,11.478216,14.184156,35.456116,11.556103,14.377014,37.160980,10.301592,14.415586,38.125538,10.043127,14.801972,38.121166,11.161409,14.757698,37.136177,11.333216,9.585757,38.829636,13.348660,9.585756,39.320480,13.329101,9.199370,39.318363,12.247375,9.199370,38.834953,12.272804,9.585756,39.944309,13.275441,9.585756,40.800533,13.161754,9.199370,40.746582,12.165251,9.199370,39.931221,12.227156,9.585756,40.382450,9.921921,9.585756,39.794147,9.813421,9.199370,39.876617,11.003408,9.199369,40.595463,11.022103,9.585757,39.291069,9.767069,9.585758,38.839500,9.850561,9.199370,38.838535,11.035894,9.199370,39.307667,10.987226,10.358337,47.221714,8.028111,10.358534,47.060169,9.495804,11.421095,47.485256,9.608688,11.423618,47.648006,8.015064,13.642814,41.787148,13.691846,13.642813,42.807053,13.439422,12.580251,42.934418,13.804056,12.580252,41.839748,14.060793,13.667093,40.980530,8.629669,13.642813,40.857243,8.358307,12.580250,40.381893,8.401431,12.603136,40.531532,8.677214,10.358528,40.531506,9.207741,10.358528,40.606003,9.148827,11.421091,40.446056,8.825476,11.421092,40.441822,8.841196,14.422948,46.310028,8.135670,14.415586,46.130970,9.290199,14.801971,44.783508,9.020234,14.805906,44.941406,8.344657,14.415586,40.809490,9.936413,14.415586,41.051979,9.797064,14.801971,41.697689,10.703396,14.801971,41.216305,10.930634,9.585756,41.696823,12.975299,9.585756,42.585751,12.713816,9.199370,42.244469,11.732714,9.199370,41.534409,12.001666,9.595337,41.958488,8.562759,9.585758,41.860390,8.453621,9.199372,43.268513,8.715897,9.208031,43.370533,8.495801,10.358530,40.818275,13.884952,10.358530,39.943840,14.024258,11.421093,39.943691,14.405132,11.421093,40.828712,14.259032,10.358530,39.319920,14.097081,10.358530,38.825863,14.116517,11.421093,38.824627,14.501675,11.421093,39.319637,14.482366,13.642814,38.825863,14.116517,13.642815,39.319920,14.097081,12.580252,39.319637,14.482366,12.580252,38.824627,14.501675,13.642815,39.943840,14.024258,13.642815,40.818275,13.884952,12.580253,40.828712,14.259032,12.580252,39.943691,14.405132,13.642814,40.239033,9.117260,13.642815,39.739071,8.951626,12.580252,39.725281,8.542984,12.580252,40.199139,8.724665,13.642815,39.279835,8.888418,13.642815,38.839363,8.995121,12.580253,38.839088,8.588068,12.580252,39.276909,8.475563,10.358532,38.839363,8.995121,10.358530,39.279835,8.888418,11.421093,39.276909,8.475564,11.421093,38.839088,8.588068,10.358530,39.739071,8.951626,10.358530,40.239033,9.117260,11.421092,40.199139,8.724666,11.421093,39.725281,8.542984,14.415586,40.800533,13.161754,14.415586,39.944309,13.275441,14.801972,39.931221,12.227156,14.801972,40.746582,12.165251,14.415586,39.320480,13.329101,14.415586,38.829636,13.348660,14.801972,38.834953,12.272805,14.801972,39.318363,12.247375,14.415586,38.839500,9.850561,14.415586,39.291069,9.767069,14.801972,39.307667,10.987226,14.801972,38.838535,11.035894,14.415586,39.794144,9.813421,14.415586,40.382450,9.921921,14.801972,40.595463,11.022103,14.801972,39.876617,11.003408,10.358530,45.115318,12.613657,10.358530,43.947243,13.103958,11.421092,44.162926,13.459374,11.421092,45.415268,12.947240,13.642813,46.057220,11.848323,13.642814,46.681667,10.784523,12.580253,47.084999,11.001719,12.580252,46.421219,12.137957,13.642813,40.835918,8.716431,13.642813,40.689732,8.969618,12.580251,40.453957,8.722712,12.580251,40.525448,8.571482,10.358530,40.923798,8.452805,10.358530,40.915737,8.284267,11.421092,40.466747,8.302420,11.421092,40.538258,8.403740,14.415585,44.564041,11.936544,14.415585,43.564781,12.385527,14.801971,43.006340,11.411009,14.801971,43.774998,11.010399,14.415585,41.814568,8.824993,14.415585,41.877438,8.514382,14.801971,43.221970,9.042109,14.801971,43.078316,9.552565,9.585758,45.346329,11.251195,9.585759,45.838398,10.330170,9.199372,44.625858,9.700018,9.199371,44.330853,10.426115,9.585757,41.611603,9.203627,9.585756,41.309822,9.540363,9.199370,42.204613,10.401862,9.199370,42.726719,10.033664,13.642813,43.947243,13.103958,13.642813,45.115318,12.613593,12.580251,45.415268,12.947214,12.580251,44.162926,13.459374,10.358528,40.689732,8.969618,10.358530,40.835918,8.716431,11.421092,40.525448,8.571482,11.421091,40.453957,8.722712,14.415585,41.309822,9.540363,14.415585,41.611603,9.203626,14.801971,42.726719,10.033656,14.801971,42.204613,10.401861,9.585756,43.564777,12.385527,9.585756,44.564041,11.936608,9.199370,43.774998,11.010431,9.199370,43.006340,11.411010,10.358530,42.807053,13.439422,10.358530,41.787148,13.691846,11.421093,41.839748,14.060793,11.421092,42.934418,13.804056,13.642813,40.606003,9.148827,13.642813,40.531506,9.207741,12.580251,40.441822,8.841196,12.580251,40.446056,8.825476,14.415586,42.585751,12.713816,14.415586,41.696823,12.975299,14.801971,41.534409,12.001666,14.801971,42.244469,11.732713,9.585755,41.051979,9.797064,9.585755,40.809490,9.936413,9.199369,41.216305,10.930634,9.199369,41.697689,10.703397,10.358532,46.681667,10.785208,10.358530,46.057220,11.848644,11.421093,46.421219,12.138084,11.421094,47.084999,11.001991,13.642813,40.915737,8.284258,13.642813,40.923798,8.452803,12.580251,40.538258,8.403739,12.580251,40.466747,8.302417,14.415586,45.838398,10.329462,14.415585,45.346329,11.250874,14.801971,44.330856,10.425953,14.801971,44.625858,9.699621,9.585758,41.877438,8.514414,9.585758,41.814568,8.824997,9.199372,43.078316,9.552599,9.199372,43.221970,9.042234,13.642815,47.060169,9.494946,13.652050,47.241978,8.017529,12.586876,47.655071,8.010709,12.580254,47.485256,9.608355,10.358530,40.857243,8.358337,10.370977,40.976109,8.618082,11.438915,40.530804,8.672701,11.421091,40.381893,8.401432,14.415585,41.860390,8.453480,14.433722,41.973297,8.575562,14.809790,43.399185,8.503389,14.801971,43.268513,8.715538,9.585760,46.130970,9.291166,9.586968,46.279373,8.145038,9.205111,44.906418,8.345937,9.199373,44.783508,9.020924,12.823305,42.545368,9.126569,13.937462,42.818104,8.977888,13.764219,41.704525,8.860273,12.694676,41.340355,8.948721,14.655651,43.505516,8.383768,14.900005,44.533161,7.407149,14.841062,43.865650,8.053473,14.506269,42.575722,8.565486,14.859028,45.631306,6.348577,14.542883,46.565434,5.301124,14.452393,46.456818,6.753145,14.821646,45.251244,7.397792,13.784748,47.129704,4.642833,12.659693,47.303162,4.489310,12.613364,47.581963,6.244616,13.688986,47.254082,6.355389,11.457312,47.227772,4.538868,10.342682,46.882732,4.753728,10.357553,47.152748,6.405037,11.433706,47.546627,6.265169,9.576916,46.181313,5.367746,9.254798,45.223961,6.306660,9.228060,45.076286,7.400487,9.591799,46.303535,6.795853,9.279028,44.224937,7.277333,9.648253,43.360771,8.208700,9.633655,42.501671,8.500380,9.242666,43.722385,8.013043,10.460865,42.774357,8.836357,11.611076,42.532951,9.077492,11.510211,41.336708,8.926149,10.420765,41.682426,8.802110,19.822937,41.153313,8.728106,18.775640,40.694126,8.816099,18.781717,41.251873,8.840796,19.807640,41.713234,8.697861,17.609909,40.689125,8.815767,16.530092,41.146645,8.724424,16.502815,41.697239,8.688656,17.606789,41.239868,8.839900,15.761310,42.152531,8.523678,15.394587,43.565563,8.261670,15.400421,43.981358,7.976253,15.739616,42.664463,8.390532,15.386857,45.017464,8.053083,15.740091,46.238693,7.935182,15.688692,46.342068,7.058167,15.381870,45.287075,7.503819,16.501297,47.058414,7.867816,17.579622,47.392162,7.832737,17.534100,47.287651,6.618775,16.433702,47.028103,6.751190,18.746365,47.241825,7.833601,19.796667,46.676731,7.872829,19.744593,46.604733,6.763241,18.711454,47.123909,6.620809,20.549530,45.833656,7.951616,20.921890,44.772415,8.082796,20.822308,44.945293,7.576239,20.469585,45.862656,7.098080,20.928608,43.475853,8.290850,20.568222,42.135845,8.538778,20.514446,42.624416,8.427597,20.838432,43.815323,8.047535,18.788664,41.898254,8.843981,18.781225,42.458408,8.870779,19.793100,42.938267,8.628540,19.790161,42.365459,8.642265,16.471640,42.338799,8.626698,16.408491,42.886436,8.618768,17.591652,42.430477,8.869493,17.603220,41.878250,8.842415,15.407090,44.450722,7.570472,15.394334,44.827610,7.142495,15.649630,43.760490,8.015129,15.714824,43.259079,8.190132,15.629950,46.383926,6.158651,15.537080,46.337650,5.319281,15.353539,45.744186,6.224365,15.376171,45.557789,6.849926,17.482073,47.067345,5.460908,17.444559,46.702946,4.392635,16.261211,46.631519,4.663551,16.356453,46.892353,5.674759,19.685081,46.486183,5.694892,19.661165,46.265804,4.677842,18.642189,46.578876,4.394005,18.671560,46.914219,5.464300,20.708500,45.137878,6.971089,20.624861,45.258614,6.354012,20.331945,45.823952,5.385875,20.378222,45.884354,6.225396,20.452988,43.192341,8.252314,20.435513,43.691940,8.071942,20.663958,44.521641,7.266796,20.735374,44.203945,7.689810,20.937931,23.037338,0.566561,20.978296,20.935484,0.516593,19.686874,20.831541,-0.360854,19.650255,22.895105,-0.303008,10.742401,22.876957,6.103930,10.725099,20.817019,6.148315,12.197847,20.830339,6.766769,12.201324,22.894722,6.711915,8.970645,22.803734,4.259083,8.920902,20.763037,4.299804,9.566101,20.793493,5.293503,9.599944,22.845146,5.252514,9.923738,22.768707,0.611396,9.875653,20.737675,0.588822,9.166353,20.738211,1.572726,9.213122,22.769676,1.570674,13.467262,22.913876,7.073333,13.477936,20.844707,7.146342,14.428556,20.855604,7.335999,14.404608,22.928310,7.240816,16.097359,24.299114,7.264291,16.072195,24.860340,7.191658,15.187498,24.932049,7.163420,15.219233,24.357069,7.229109,17.875849,24.247341,7.170419,17.823936,24.796267,7.135638,16.963150,24.808880,7.201001,16.996094,24.257509,7.262241,20.410908,22.914679,5.511375,20.500296,20.846260,5.483640,21.401609,20.925047,4.306437,21.329487,23.022690,4.381593,18.754574,22.826515,6.925111,18.857908,20.781940,6.978278,19.614574,20.795153,6.385351,19.512611,22.844620,6.365890,14.012050,24.175720,-1.447384,14.068653,24.708807,-1.459322,15.421307,24.709724,-1.657213,15.348833,24.176651,-1.659075,11.091103,24.174589,-0.249416,11.090328,24.707907,-0.261617,12.589830,24.708118,-0.969244,12.561426,24.174957,-0.952995,21.839266,23.106272,3.060158,21.894545,20.985991,2.973978,21.758909,20.996210,1.644971,21.715528,23.120388,1.708641,16.720701,24.177954,-1.488522,16.781918,24.711157,-1.476889,18.205492,24.751623,-0.956423,18.172077,24.210815,-0.969124,8.829659,22.770309,2.474389,8.778916,20.738562,2.498071,8.683185,20.743452,3.359647,8.738430,22.777042,3.323345,16.165972,20.810402,7.485605,16.129480,22.865784,7.365158,15.251598,22.910360,7.322754,15.282519,20.842773,7.436174,18.033257,20.781523,7.316067,17.947670,22.825983,7.232618,17.042521,22.833773,7.351662,17.098406,20.787144,7.461324,13.878361,20.739279,-1.524065,13.947031,22.769745,-1.470417,15.277552,22.770697,-1.697487,15.211818,20.740263,-1.767004,11.008898,20.737675,-0.300863,11.062550,22.768372,-0.263522,12.514219,22.768898,-0.968124,12.452728,20.738354,-1.011072,16.633921,20.741335,-1.611959,16.670635,22.771879,-1.535507,18.160406,22.797342,-1.013428,18.169397,20.760059,-1.083931,21.021709,19.302742,0.471217,21.054268,18.429340,0.437183,19.753267,18.378454,-0.454208,19.724813,19.229118,-0.414198,10.702783,19.217459,6.188999,10.686045,18.368940,6.219512,12.183047,18.376116,6.854655,12.189391,19.227266,6.816990,8.869251,19.178709,4.334003,8.830513,18.341619,4.359653,9.500064,18.356890,5.357079,9.528365,19.200489,5.329832,9.827166,19.161001,0.565419,9.790799,18.329649,0.547867,9.080935,18.329576,1.569438,9.117542,19.161190,1.570849,13.483223,19.237843,7.211766,13.487188,18.383842,7.260834,14.459535,18.389843,7.482055,14.446259,19.245939,7.419459,20.581860,19.239998,5.465559,20.643032,18.386456,5.451999,21.523306,18.424742,4.204679,21.471151,19.295641,4.248289,18.947426,19.194559,7.027561,19.014563,18.355173,7.064523,19.771864,18.361610,6.422586,19.704454,19.203899,6.406629,21.951611,19.338654,2.904476,21.994411,18.454308,2.852348,21.841722,18.459129,1.550257,21.806231,19.345791,1.590849,8.726195,19.161320,2.515219,8.686654,18.329540,2.528078,8.584319,18.331881,3.410160,8.626691,19.164751,3.388511,17.313450,16.878199,1.945552,16.738356,16.878674,4.506626,15.776496,16.878181,4.319765,16.107346,16.877798,1.607349,16.518665,16.950230,-1.642727,18.142916,16.951143,-1.109291,18.046295,16.877850,-0.847666,16.478298,16.877422,-1.362270,19.697351,16.953228,-0.371142,20.962431,16.956079,0.496323,20.741245,16.878435,0.675920,19.538137,16.878157,-0.141045,21.725130,16.957853,1.535132,21.883881,16.957890,2.737795,21.607395,16.878965,2.725691,21.460947,16.878696,1.629417,21.448559,16.956707,4.047296,20.620138,16.955072,5.318456,20.414085,16.879570,5.170068,21.195560,16.879269,3.951007,19.790684,16.954000,6.317924,19.054255,16.953707,6.973078,18.918856,16.879820,6.739920,19.625288,16.879770,6.126005,18.206903,16.953608,7.372026,17.225803,16.953524,7.577683,17.182775,16.879560,7.304049,18.111855,16.879753,7.110881,16.269245,16.953705,7.627780,15.388364,16.953865,7.560330,15.422396,16.878563,7.284112,16.271530,16.879192,7.350677,14.527136,16.953186,7.413627,13.552059,16.951632,7.168174,13.631599,16.876255,6.898881,14.584016,16.877562,7.139779,12.252147,16.949923,6.746686,10.769154,16.948336,6.115663,10.933115,16.873631,5.883482,12.366930,16.874887,6.488391,9.597578,16.946695,5.285390,8.938334,16.945187,4.340986,9.199473,16.871830,4.241895,9.814601,16.872576,5.107523,8.698747,16.944372,3.442410,8.801469,16.944349,2.596637,9.074682,16.871614,2.656041,8.979469,16.871510,3.425985,9.184477,16.944733,1.657654,9.870077,16.945353,0.644261,10.084512,16.872646,0.829141,9.433563,16.872013,1.785166,10.964901,16.946220,-0.259936,12.361796,16.947287,-0.970247,12.482943,16.874571,-0.717255,11.135876,16.873520,-0.033567,13.739824,16.948425,-1.500887,15.050675,16.949467,-1.778616,15.064647,16.876698,-1.495308,13.807950,16.875685,-1.228985,10.495033,16.872932,3.607854,9.966399,16.872314,3.427096,10.046520,16.872406,2.655691,10.594678,16.873011,2.344917,12.725735,16.874945,3.987602,11.454942,16.873838,3.810186,11.539686,16.873867,2.023089,12.778690,16.874908,1.767441,14.851491,16.877325,4.187669,13.895863,16.876163,4.105150,13.956230,16.876024,1.568843,14.997298,16.877060,1.478386,18.464317,16.878420,2.361349,19.419744,16.878557,2.782177,18.548500,16.879055,4.776785,17.688141,16.878935,4.674008,20.050619,16.878662,3.194558,20.345131,16.878784,3.588997,19.683096,16.879110,4.734706,19.213654,16.879101,4.798938,17.934633,16.877827,-0.542488,17.743401,16.877893,0.138227,16.343042,16.877533,-0.310196,16.434681,16.877445,-1.035021,20.484327,16.878311,0.885491,20.117260,16.878286,1.390574,19.063572,16.878109,0.734704,19.352566,16.878084,0.127005,21.285976,16.878765,2.718477,20.906969,16.878653,2.867514,20.749880,16.878454,2.100524,21.154518,16.878527,1.742330,20.170828,16.879383,5.002203,19.965591,16.879200,4.799912,20.586697,16.878906,3.787642,20.899794,16.879065,3.846500,18.755589,16.879671,6.468760,18.749241,16.879465,5.972099,19.346758,16.879402,5.552769,19.427704,16.879595,5.904643,17.128998,16.879477,6.982253,17.208561,16.879318,6.327527,18.037268,16.879450,6.216354,17.996201,16.879635,6.805375,15.458919,16.878536,6.959082,15.544348,16.878447,6.236201,16.364408,16.879017,6.324653,16.271183,16.879139,7.024096,13.721998,16.876261,6.584886,13.811010,16.876245,5.900542,14.726157,16.877501,6.100072,14.647335,16.877552,6.818861,11.122627,16.873701,5.614258,11.302797,16.873774,5.091910,12.623470,16.874945,5.568265,12.498914,16.874920,6.188415,9.502837,16.871996,4.125389,9.785479,16.872179,3.937043,10.302956,16.872816,4.518158,10.066220,16.872694,4.900786,9.391948,16.871815,2.722301,9.701757,16.872044,2.771649,9.628665,16.871944,3.371535,9.305675,16.871702,3.404464,10.334196,16.872833,1.042658,10.536104,16.872976,1.431221,9.972110,16.872385,2.134082,9.722880,16.872213,1.931072,12.626559,16.874704,-0.424057,12.743155,16.874826,0.190163,11.496959,16.873816,0.744870,11.336105,16.873680,0.228651,15.085591,16.876760,-1.165302,15.080500,16.876860,-0.438562,13.954231,16.875891,-0.227412,13.891253,16.875784,-0.913265,16.220304,18.368660,7.667407,16.197020,19.214462,7.589493,15.307425,19.237164,7.534365,15.326103,18.384111,7.608006,18.162371,18.354914,7.445689,18.107037,19.194229,7.390137,17.146708,19.198133,7.556567,17.182936,18.357527,7.628001,13.778296,18.332052,-1.615492,13.821180,19.163063,-1.576309,15.159548,19.164070,-1.832363,15.120346,18.333076,-1.881384,10.920099,18.330114,-0.365417,10.958155,19.161264,-0.337751,12.398520,19.162067,-1.053799,12.357864,18.331005,-1.085844,16.587725,18.334002,-1.735493,16.607523,19.165056,-1.682549,18.182388,19.178450,-1.148760,18.192133,18.343391,-1.197384,21.083210,17.809052,0.406933,21.076420,17.266279,0.406661,19.777493,17.253302,-0.487387,19.778559,17.778376,-0.489773,10.671165,17.770775,6.246634,10.681837,17.247387,6.236713,12.188972,17.250162,6.879933,12.177408,17.775604,6.888135,8.796079,17.753601,4.382455,8.803869,17.239111,4.387840,9.484347,17.243536,5.376648,9.474907,17.763092,5.381298,9.758472,17.746737,0.532265,9.761397,17.236713,0.545303,9.056088,17.236204,1.585328,9.048395,17.746431,1.568185,13.490713,17.780804,7.304449,13.505098,17.253147,7.303363,14.489576,17.255644,7.546267,14.471335,17.784937,7.537695,20.697409,17.783815,5.439945,20.714581,17.256485,5.408415,21.573261,17.265842,4.118933,21.569668,17.806677,4.165915,19.074240,17.765121,7.097378,19.106049,17.248806,7.092232,19.859516,17.250401,6.421513,19.831783,17.768978,6.436770,22.032455,17.824289,2.806014,22.025566,17.272999,2.764568,21.862572,17.273973,1.496717,21.873270,17.827057,1.514174,8.651505,17.746250,2.539508,8.660411,17.235891,2.557793,8.554476,17.236410,3.443550,8.546656,17.747618,3.429403,20.975080,25.135229,0.613284,20.935654,24.521626,0.600051,19.642885,24.337400,-0.267233,19.667923,24.907839,-0.257971,10.685380,24.881523,6.066613,10.729781,24.315243,6.075567,12.184217,24.337885,6.676641,12.145823,24.909191,6.665133,8.945340,24.765465,4.190204,8.980226,24.220903,4.221600,9.596955,24.274340,5.221766,9.553988,24.831268,5.204288,9.915243,24.708960,0.600327,9.938282,24.175280,0.615881,9.221237,24.176725,1.555581,9.186627,24.710890,1.527288,13.408464,24.939034,6.995335,13.443958,24.362305,7.021180,14.373719,24.380630,7.166114,14.337365,24.961365,7.118845,20.331657,24.938236,5.616076,20.352430,24.362305,5.556024,21.295982,24.502365,4.469015,21.306890,25.111238,4.563858,18.610012,24.797054,6.886507,18.669455,24.247999,6.893152,19.434320,24.271463,6.366055,19.387192,24.826035,6.387621,21.863684,25.245169,3.237831,21.827393,24.610777,3.150041,21.715517,24.629158,1.764874,21.762821,25.267935,1.809157,8.803487,24.712135,2.403919,8.839314,24.177662,2.442529,8.752259,24.186415,3.283978,8.719966,24.722963,3.243951,16.049349,25.130867,7.128437,16.071608,25.456951,7.106166,15.180547,25.537827,7.113739,15.155975,25.216452,7.107049,17.778664,25.054386,7.110000,17.773392,25.359106,7.164591,16.941824,25.389183,7.144733,16.934700,25.069462,7.149155,14.122450,24.950930,-1.482918,14.189455,25.281744,-1.554260,15.608268,25.280066,-1.721258,15.494178,24.951830,-1.667534,11.079779,24.950260,-0.282586,11.071974,25.282946,-0.352981,12.636264,25.283346,-1.071764,12.611969,24.950315,-0.995956,16.846851,24.953402,-1.477045,16.989079,25.281561,-1.511120,18.395731,25.339178,-0.968243,18.246157,25.001541,-0.954252,18.534342,14.961010,14.920060,11.031338,14.961010,14.920060,11.367298,10.482590,14.920061,16.540981,10.482590,14.920061,16.540981,8.579273,14.920061,14.746568,7.907505,14.920061,12.890285,8.601658,14.920061,12.912683,9.810837,14.920061,11.412037,9.810837,14.920061,11.546465,7.504452,14.920061,14.746568,6.362461,14.920061,17.951981,7.594025,14.920061,18.243252,11.848526,14.920061,12.621523,11.848526,14.920061,12.509596,13.415955,14.920060,18.422312,13.415955,14.920060,18.534342,14.961010,15.707462,11.031338,14.961010,15.707462,11.367298,10.482590,15.707462,16.540981,10.482590,15.707462,16.540981,8.579273,15.707462,14.746568,7.907505,15.707462,12.890285,8.601658,15.707462,12.912683,9.810837,15.707462,11.412037,9.810837,15.707462,11.546465,7.504452,15.707462,14.746568,6.362461,15.707462,17.951981,7.594025,15.707462,18.243252,11.848526,15.707462,12.621523,11.848526,15.707462,12.509596,13.415955,15.707462,18.422312,13.415955,15.707462,14.751186,17.334011,14.197391,8.842903,17.334011,14.197391,9.978224,5.557796,14.197392,14.748644,3.988644,14.197392,19.527683,5.557796,14.197392,20.663010,17.334011,14.197391,14.751186,17.334011,14.984793,8.842903,17.334011,14.984793,9.978224,5.557796,14.984793,14.748644,3.988644,14.984794,19.527683,5.557796,14.984793,20.663010,17.334011,14.984793,5.166041,0.858387,14.259264,24.851080,0.858387,14.259264,5.166041,0.858387,-5.425776,24.851080,0.858387,-5.425776,5.166041,20.543427,14.259264,24.851080,20.543427,14.259264,5.166041,20.543427,-5.425776,24.851080,20.543427,-5.425776],\n\n    \"morphTargets\": [],\n\n    \"morphColors\": [],\n\n    \"normals\": [],\n\n    \"colors\": [],\n\n    \"uvs\": [[1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,0,0,1,1,1,0,0,0,1,1,0.5,0.5,0,0,0.5,0.5,0,1,0.5,0.5,1,0,0.5,0.5,1,0,0.375,0.375,0,0,0.375,0.625,1,1,0.375,0.625,0,1,0.375,0.375,1,0.5,0.5,0.24496,0.5,0.5,0.75504,0.5,0.75504,0.75504,0.5,0.55746,0.5,0.47543,0.3362,0.4716,0.32454,0.30036,0.497,0.64343,0.5009,0.5,0.44254,0.5,0.44254,0.44254,0.5,0.5,1,0,0.75,0.5,1,0,0.75,1,0.5,1,0.5,1,0.75,0,0.4375,1,0.75,0,0.4375,0.5,0.55145,0.5,0.55145,0.55145,0.5,0.44855,0.5,1,0.3125,1,0.3125,0,0.3125,0,0.3125,1,0.4375,1,0.4375,0.61768,0.5,0.5,0.38232,0.5,0.38232,0.38232,0.5,0.5,0,0.75,0,0.5,1,0.25,1,0,0.5,0,0.5,0.25,0,0.4375,0,0.75,1,0.5625,1,0.6875,0,0.3125,1,0.3125,0,0.6875,1,0.5625,0,0.4375,1,1,0.34375,0.65625,0,0.5,0.34375,0,0.34375,0.34375,0,1,0.34375,0.34375,1,0.5,0.34375,0,0.34375,0.65625,1,0.34375,0.5,0.65625,0.5,0.5,0.35938,0,0.35938,0.35938,0,0.5,0.35938,0,0.35938,0.64062,1,0.35938,0.5,1,0.35938,0.64062,0,1,0.35938,0.35938,1,0.64062,0.5,1,0.32812,0.67188,0,1,0.32812,0.32812,1,0.67188,0.5,0.5,0.32812,0,0.32812,0.32812,0,0.5,0.32812,0,0.32812,0.67188,1,0.32812,0.5,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,0,0,1,1,1,0,0,0,1,1,0.5,0.5,0,0,0.5,0.5,0,1,0.5,0.5,1,0,0.5,0.5,1,0.5,0.5,0.24496,0.5,0.5,0.75504,0.5,0.75504,0.75504,0.5,0.5,1,0,0.75,0.5,1,0,0.75,1,0.5,1,0.5,1,0.75,1,0.75,0.47499,0.56671,0.47363,0.56255,0.53832,0.50075,0.40792,0.49823,0.5,0,0.75,0,0.5,1,0.25,1,0,0.5,0,0.5,0.25,0,0.75,1,0.24247,0.41769,0.24446,0.43294,0.27457,0.42506,0.27272,0.41103,0.27307,0.39723,0.2448,0.40317,0.21657,0.40231,0.21712,0.42152,0.22064,0.43924,0.20954,0.55247,0.1986,0.55578,0.19566,0.5633,0.21021,0.57492,0.18923,0.56735,0.18065,0.56979,0.21174,0.56278,0.19614,0.58079,0.2069,0.59345,0.19952,0.59506,0.21438,0.59716,0.22559,0.5914,0.16702,0.32091,0.15983,0.31747,0.18544,0.38315,0.16368,0.33714,0.17306,0.3409,0.17347,0.32399,0.2764,0.64514,0.28873,0.65964,0.26968,0.65136,0.33706,0.5983,0.27827,0.66472,0.28333,0.66073,0.27967,0.46853,0.28014,0.45515,0.25256,0.46172,0.25612,0.47712,0.22883,0.46998,0.23223,0.48496,0.23715,0.50116,0.2641,0.49064,0.30382,0.47421,0.17571,0.4511,0.16363,0.4558,0.16231,0.46379,0.17922,0.46829,0.15773,0.46912,0.1594,0.48576,0.18989,0.48726,0.16941,0.47716,0.18929,0.48312,0.17829,0.48934,0.24987,0.62427,0.24106,0.63149,0.24263,0.63819,0.25996,0.63632,0.24059,0.64477,0.24099,0.61181,0.2906,0.62059,0.25483,0.6467,0.21367,0.60537,0.23241,0.6122,0.21955,0.62099,0.20818,0.61137,0.23357,0.62997,0.22707,0.63291,0.24266,0.51636,0.27524,0.50779,0.24827,0.53272,0.26519,0.52663,0.27074,0.31004,0.28403,0.3261,0.29635,0.30088,0.28104,0.28884,0.26794,0.28261,0.26012,0.29942,0.25031,0.31386,0.25285,0.32597,0.1458,0.35907,0.14135,0.3671,0.14657,0.36813,0.15219,0.3632,0.13335,0.36548,0.15751,0.39814,0.1399,0.37613,0.14902,0.37488,0.15471,0.3693,0.15308,0.41075,0.14804,0.40392,0.14459,0.41107,0.14902,0.41792,0.13848,0.40152,0.13912,0.41086,0.1416,0.41984,0.13093,0.41053,0.14732,0.42848,0.15522,0.45967,0.1514,0.46136,0.15642,0.45093,0.14821,0.45071,0.18715,0.54966,0.18057,0.55083,0.18451,0.55783,0.18695,0.5579,0.19054,0.55724,0.19321,0.55047,0.19698,0.60741,0.20197,0.57362,0.20269,0.60384,0.20653,0.60149,0.22394,0.57856,0.23012,0.64391,0.23308,0.64,0.23541,0.63719,0.12539,0.3635,0.12174,0.36444,0.1917,0.38903,0.11794,0.35835,0.22533,0.65073,0.22135,0.65918,0.28191,0.59275,0.22126,0.65328,0.12338,0.41046,0.1186,0.41188,0.17517,0.42251,0.11466,0.40963,0.19097,0.61111,0.18279,0.61771,0.18598,0.61285,0.1353,0.46871,0.14221,0.46565,0.1201,0.47399,0.12545,0.47467,0.16304,0.47775,0.12497,0.47629,0.14613,0.46364,0.16379,0.46038,0.1667,0.42565,0.25676,0.57763,0.20637,0.53752,0.19028,0.50771,0.20401,0.50809,0.21287,0.51092,0.19277,0.40682,0.19624,0.42537,0.20139,0.44415,0.27082,0.56905,0.29311,0.55924,0.27903,0.54043,0.25933,0.55074,0.32338,0.54655,0.30409,0.52603,0.21055,0.4762,0.2145,0.49114,0.21924,0.5086,0.18844,0.35537,0.18638,0.34057,0.19499,0.37916,0.18555,0.3918,0.22544,0.45555,0.2487,0.44698,0.27848,0.43955,0.31109,0.63533,0.32997,0.62939,0.32458,0.61473,0.30164,0.6198,0.35051,0.62807,0.35132,0.61225,0.35761,0.59202,0.3177,0.59794,0.29178,0.60474,0.30585,0.57895,0.28132,0.58757,0.33941,0.56817,0.22444,0.52461,0.23086,0.54113,0.19911,0.33634,0.22567,0.33056,0.31051,0.65311,0.19039,0.32312,0.30347,0.43572,0.30076,0.41854,0.30562,0.45373,0.35291,0.53833,0.3361,0.51658,0.37041,0.5593,0.37912,0.57716,0.3057,0.33098,0.31,0.31855,0.28019,0.35545,0.30283,0.35056,0.2745,0.38069,0.3,0.37284,0.29924,0.38922,0.29928,0.40327,0.23921,0.56105,0.24996,0.57907,0.18195,0.32842,0.29043,0.6399,0.29864,0.65941,0.20631,0.46158,0.28082,0.6263,0.27064,0.61296,0.25995,0.59709,0.16576,0.40979,0.16382,0.43208,0.14789,0.43442,0.19509,0.49962,0.18381,0.50479,0.18781,0.52177,0.19944,0.51789,0.1667,0.35617,0.15576,0.3496,0.20289,0.35899,0.16675,0.3715,0.15869,0.38939,0.14048,0.38875,0.20178,0.53691,0.18944,0.53724,0.18502,0.37628,0.20215,0.35093,0.21017,0.37039,0.22719,0.38563,0.25055,0.38607,0.25754,0.36166,0.23713,0.36782,0.22972,0.35438,0.22464,0.34096,0.25755,0.33947,0.31788,0.49389,0.35744,0.51187,0.3444,0.48977,0.33476,0.46865,0.32104,0.34872,0.32085,0.3694,0.32163,0.33228,0.41916,0.46985,0.42771,0.49322,0.4121,0.44921,0.38013,0.30313,0.38477,0.31573,0.37431,0.28856,0.32079,0.38656,0.39112,0.35403,0.39342,0.37272,0.38808,0.33213,0.39589,0.38739,0.32097,0.40079,0.3219,0.41534,0.39865,0.40066,0.32843,0.44929,0.32385,0.43062,0.37053,0.53291,0.38168,0.55238,0.44678,0.53897,0.43589,0.51333,0.32239,0.3191,0.32243,0.30485,0.40655,0.43133,0.40182,0.4142,0.31063,0.30117,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,0,0,1,1,1,0,0,0,1,1,0.5,0.5,0,0,0.5,0.5,0,1,0.5,0.5,1,0,0.5,0.5,1,0.5,0.5,0.24496,0.5,0.5,0.75504,0.5,0.75504,0.75504,0.5,0.49372,0.49874,0.46112,0.48649,0.44469,0.43757,0.41105,0.50122,0.5,1,0,0.75,0.5,1,0,0.75,1,0.5,1,0.5,1,0.75,0,0.4375,1,0.75,0,0.4375,0.5,0.55145,0.5,0.55145,0.55145,0.5,0.44855,0.5,1,0.4375,1,0.4375,0.5,0,0.75,0,0.5,1,0.25,1,0,0.5,0,0.5,0.25,0,0.4375,0,0.75,1,0.5625,1,0.5625,0,0.4375,1,0.31249,0.23814,0.59028,0.52541,0.30252,0.4887,0.32556,0.73717,0.07556,0.48717,0.33993,0.53517,0.08918,0.51243,0.33918,0.26243,0.58569,0.49817,0.3357,0.74816,0.33123,0.5085,0.35344,0.50481,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,0,0,1,1,1,0,0,0,1,1,0.5,0.5,0,0,0.5,0.5,0,1,0.5,0.5,1,0,0.5,0.5,1,0,0.375,0.375,0,0,0.375,0.625,1,1,0.375,0.625,0,1,0.375,0.375,1,0.5,0.125,0.5,0.125,0.125,0.5,0.5,0.5,0.24496,0.5,0.5,0.75504,0.5,0.75504,0.75504,0.5,0.55746,0.5,0.875,0.5,0.5,0.44254,0.5,0.44254,0.44254,0.5,1,0.125,0.5,1,0,0.75,1,0.125,0.5,1,0,0.75,1,0.5,1,0.5,1,0.75,0,0.4375,1,0.75,0,0.4375,0.5,0.55145,0.5,0.55145,0.55145,0.5,0.44855,0.5,0,0.125,0,0.125,1,0.4375,1,0.4375,0.61768,0.5,0.5,0.38232,0.5,0.38232,0.38232,0.5,0.875,0,0.5,0,0.75,0,0.125,1,0.5,1,0.25,1,0,0.5,0,0.5,0.25,0,0.4375,0,0.75,1,0.5625,1,0.125,0,0.875,1,0.5625,0,0.4375,1,1,0.34375,0.65625,0,0.5,0.31201,0,0.34375,0.34375,0,1,0.34375,0.34375,1,0.5,0.31201,0,0.34375,0.65625,1,0.31201,0.5,0.68799,0.5,0.5,0.35938,0,0.35938,0.35938,0,0.5,0.35938,0,0.35938,0.64062,1,0.35938,0.5,1,0.35938,0.64062,0,1,0.35938,0.35938,1,0.64062,0.5,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,0,0,1,1,1,0,0,0,1,1,0.5,0.5,0,0,0.5,0.5,0,1,0.5,0.5,1,0,0.5,0.5,1,0,0.375,0.375,0,0,0.375,0.625,1,1,0.375,0.625,0,1,0.375,0.375,1,0.5,0.5,0.24496,0.5,0.5,0.75504,0.5,0.75504,0.75504,0.5,0.55746,0.5,0.45467,0.36425,0.44116,0.32673,0.28982,0.50197,0.60451,0.50128,0.5,0.44254,0.5,0.44254,0.44254,0.5,0.5,1,0,0.75,0.5,1,0,0.75,1,0.5,1,0.5,1,0.75,0,0.4375,1,0.75,0,0.4375,0.5,0.55145,0.5,0.55145,0.55145,0.5,0.44855,0.5,1,0.3125,1,0.3125,0,0.3125,0,0.3125,1,0.4375,1,0.4375,0.61768,0.5,0.5,0.38232,0.5,0.38232,0.38232,0.5,0.5,0,0.75,0,0.5,1,0.25,1,0,0.5,0,0.5,0.25,0,0.4375,0,0.75,1,0.5625,1,0.6875,0,0.3125,1,0.3125,0,0.6875,1,0.5625,0,0.4375,1,1,0.34375,0.65625,0,0.5,0.34375,0,0.34375,0.34375,0,1,0.34375,0.34375,1,0.5,0.34375,0,0.34375,0.65625,1,0.34375,0.5,0.65625,0.5,0.5,0.35938,0,0.35938,0.35938,0,0.5,0.35938,0,0.35938,0.64062,1,0.35938,0.5,1,0.35938,0.64062,0,1,0.35938,0.35938,1,0.64062,0.5,1,0.32812,0.67188,0,1,0.32812,0.32812,1,0.67188,0.5,0.5,0.32812,0,0.32812,0.32812,0,0.5,0.32812,0,0.32812,0.67188,1,0.32812,0.5,0.2257,0.72625,0.56946,0.3825,0.31827,0.37395,0.06643,0.36569,0.41018,0.70944,0.40305,0.45594,0.43674,0.55642,0.43976,0.29926,0.59601,0.45551,0.34274,0.44856,0.090325,0.44115,0.2163,0.237,0.2192,0.4808,0.38292,0.47989,0.37476,0.45876,0.35685,0.36172,0.35523,0.34057,0.35373,0.32431,0.35166,0.31148,0.34837,0.2967,0.41423,0.54568,0.35803,0.37972,0.35934,0.39418,0.36111,0.40798,0.36851,0.44005,0.36359,0.42211,0.39333,0.50244,0.40411,0.5244,0.4003,0.47507,0.37329,0.35803,0.36531,0.30747,0.37501,0.37636,0.37687,0.39092,0.37912,0.40447,0.38676,0.43587,0.41978,0.52056,0.39267,0.45418,0.37098,0.33652,0.36862,0.32019,0.36134,0.29263,0.43051,0.54232,0.38193,0.41832,0.40982,0.49802,0.42375,0.47403,0.417,0.45658,0.41152,0.44125,0.4078,0.42972,0.40389,0.41555,0.40228,0.40794,0.40101,0.39998,0.40021,0.39125,0.39787,0.37297,0.38879,0.33095,0.3855,0.31457,0.38144,0.30369,0.38739,0.33188,0.42231,0.46074,0.4291,0.49285,0.42064,0.46944,0.41362,0.44882,0.40809,0.43098,0.40338,0.41388,0.40018,0.40037,0.39738,0.38711,0.39486,0.37243,0.39251,0.35371,0.38941,0.33178,0.38603,0.31538,0.38128,0.3028,0.37431,0.28856,0.41054,0.41376,0.43244,0.4965,0.41121,0.47205,0.3836,0.35572,0.37388,0.30497,0.38565,0.37425,0.38787,0.38888,0.39041,0.40227,0.3982,0.43325,0.4296,0.51815,0.4039,0.45131,0.38087,0.33398,0.37796,0.31761,0.36783,0.2906,0.43864,0.54065,0.39343,0.41594,0.42016,0.49525,0.35533,0.46373,0.33813,0.34496,0.33758,0.32877,0.3354,0.30078,0.39796,0.54903,0.34369,0.42622,0.37544,0.50724,0.36405,0.48512,0.33903,0.36573,0.33684,0.31582,0.33962,0.38336,0.34032,0.39771,0.34158,0.41178,0.34872,0.44458,0.38712,0.52857,0.25,0.25,0.75,0.25,0.75,0.75,0.25,0.75,0.12466,0.25,0.36179,0.25,0.36179,0.75,0.12466,0.75,0.75,0.63821,0.75,0.87534,0.25,0.87534,0.25,0.63821,0.75,0.63821,0.75,0.87534,0.25,0.87534,0.25,0.63821,0.63821,0.25,0.87534,0.25,0.87534,0.75,0.63821,0.75,0.51804,0.25,0.59277,0.25,0.59277,0.75,0.51804,0.75,0.7464,0.32243,0.25,0.36783,0.74606,0.32142,0.25,0.36783,0.31923,0.25124,0.36783,0.75,0.63217,0.25,0.67566,0.74805,0.75,0.40723,0.75,0.48196,0.25,0.48196,0.25,0.40723,0.75,0.40723,0.75,0.48196,0.25,0.48196,0.25,0.40723,0.40723,0.25,0.48196,0.25,0.48196,0.75,0.40723,0.75,0.75,0.35156,0.25,0.33594,0.75,0.35156,0.25,0.33594,0.35156,0.25,0.33594,0.75,0.66406,0.25,0.64844,0.75,0.25,0.35156,0.25,0.35156,0.35156,0.75,0.64844,0.25,0.75,0.36783,0.75,0.36783,0.36783,0.25,0.63217,0.75,0.75,0.33594,0.75,0.33594,0.33594,0.25,0.66406,0.75,0.2493,0.32234,0.24897,0.32132,0.31928,0.74824,0.67603,0.2521,0.25,0.25,0.75,0.25,0.75,0.75,0.25,0.75,0.12466,0.25,0.35825,0.25131,0.35833,0.74838,0.12466,0.75,0.74635,0.63953,0.75,0.87534,0.25,0.87534,0.24927,0.63945,0.74626,0.63916,0.75,0.87534,0.25,0.87534,0.24913,0.6391,0.63702,0.25157,0.87534,0.25,0.87534,0.75,0.637,0.74856,0.38584,0.30812,0.38919,0.67994,0.60392,0.53081,0.23157,0.52749,0.60054,0.51692,0.22588,0.51411,0.43628,0.31834,0.43539,0.68676,0.25804,0.42191,0.25793,0.40781,0.22942,0.41189,0.22967,0.42813,0.20276,0.56173,0.18868,0.57363,0.20292,0.58664,0.21359,0.58981,0.23144,0.57675,0.2226,0.55719,0.16699,0.33257,0.17896,0.33384,0.2882,0.6504,0.27845,0.65294,0.26723,0.46546,0.24147,0.47365,0.24571,0.48905,0.27548,0.47777,0.16925,0.46021,0.16126,0.47641,0.17862,0.4793,0.19657,0.47241,0.19099,0.45649,0.24761,0.63308,0.24623,0.64658,0.26742,0.64897,0.27655,0.63625,0.26509,0.62496,0.22068,0.60168,0.21787,0.61237,0.22807,0.62447,0.23874,0.62517,0.2533,0.61167,0.24213,0.59469,0.25256,0.50393,0.25596,0.52048,0.28343,0.30628,0.27011,0.29535,0.25907,0.3124,0.1461,0.36433,0.13605,0.37107,0.15013,0.36871,0.14826,0.411,0.14258,0.40707,0.13646,0.41498,0.15598,0.46383,0.1588,0.458,0.15215,0.45623,0.1846,0.55418,0.18996,0.56125,0.19395,0.55662,0.202,0.60917,0.20987,0.59959,0.19842,0.60114,0.23515,0.64461,0.23774,0.63474,0.23206,0.63558,0.13404,0.37173,0.13248,0.36603,0.23108,0.64599,0.23096,0.64088,0.13018,0.41495,0.12615,0.41233,0.19433,0.60835,0.19498,0.60519,0.12807,0.46831,0.13331,0.47296,0.14549,0.47256,0.13869,0.46321,0.20625,0.41417,0.18014,0.41828,0.18483,0.4382,0.20905,0.43241,0.2752,0.55512,0.29952,0.5428,0.26222,0.53737,0.22137,0.48029,0.20207,0.48722,0.20674,0.50439,0.22551,0.4963,0.17915,0.34835,0.17921,0.36498,0.17721,0.38257,0.17664,0.39921,0.23806,0.45868,0.26514,0.45016,0.26137,0.4359,0.23373,0.44411,0.31662,0.62473,0.33897,0.62107,0.33728,0.60422,0.30833,0.60935,0.29817,0.59262,0.32943,0.58426,0.31498,0.56311,0.28686,0.57401,0.2306,0.51269,0.21119,0.52203,0.21678,0.53841,0.23626,0.52807,0.29014,0.4293,0.29277,0.44588,0.3304,0.53121,0.34737,0.55258,0.36175,0.57393,0.29949,0.31876,0.29388,0.34034,0.28938,0.36521,0.28672,0.3855,0.28659,0.39984,0.28726,0.41392,0.25548,0.56472,0.2446,0.54591,0.18965,0.33221,0.30245,0.64662,0.21815,0.46615,0.21402,0.45045,0.29577,0.62985,0.28624,0.61577,0.27607,0.60047,0.266,0.58282,0.15693,0.41754,0.15005,0.42582,0.1537,0.44248,0.16411,0.44806,0.18592,0.49405,0.1839,0.51328,0.16499,0.34653,0.15436,0.35382,0.15915,0.36467,0.15643,0.37561,0.14688,0.38203,0.14633,0.39606,0.1556,0.40365,0.19422,0.52889,0.18815,0.54409,0.20007,0.54923,0.19722,0.57155,0.19754,0.58783,0.1695,0.33127,0.27937,0.65367,0.16652,0.46971,0.17503,0.4868,0.24882,0.64172,0.26499,0.64428,0.21066,0.61437,0.22723,0.62498,0.13973,0.36244,0.14405,0.37141,0.13395,0.40646,0.14313,0.4148,0.15187,0.46713,0.1467,0.45735,0.1889,0.55394,0.18506,0.56305,0.20713,0.60554,0.20362,0.59888,0.23727,0.64046,0.22887,0.63794,0.14124,0.42616,0.14752,0.4426,0.18013,0.50122,0.19088,0.51146,0.15806,0.34268,0.1547,0.3571,0.13559,0.38117,0.14043,0.39407,0.18519,0.53036,0.19243,0.54391,0.1939,0.34561,0.19831,0.36415,0.212,0.38612,0.26022,0.39319,0.2345,0.39618,0.19901,0.39535,0.26568,0.37187,0.24289,0.37642,0.22459,0.37073,0.21433,0.35457,0.21169,0.33975,0.23823,0.32796,0.24103,0.33964,0.24547,0.35514,0.26737,0.32475,0.27073,0.34503,0.29302,0.46267,0.27987,0.52459,0.29021,0.49061,0.30911,0.5096,0.34015,0.50249,0.34965,0.47672,0.32982,0.3573,0.32951,0.33833,0.32924,0.31056,0.33025,0.37697,0.39124,0.38102,0.39379,0.39478,0.31935,0.46138,0.33593,0.43727,0.33249,0.42066,0.42911,0.50567,0.43799,0.52774,0.31492,0.32544,0.31068,0.37973,0.31103,0.40902,0.34193,0.45639,0.36941,0.54571,0.41999,0.4823,0.32666,0.48092,0.31311,0.34021,0.31554,0.4424,0.3127,0.42477,0.32954,0.3244,0.31629,0.31118,0.31047,0.39462,0.35553,0.5249,0.31162,0.36023,0.25,0.25,0.75,0.25,0.75,0.75,0.25,0.75,0.12466,0.25,0.36179,0.25,0.36179,0.75,0.12466,0.75,0.75,0.63821,0.75,0.87534,0.25,0.87534,0.25,0.63821,0.75,0.63821,0.75,0.87534,0.25,0.87534,0.25,0.63821,0.63821,0.25,0.87534,0.25,0.87534,0.75,0.63821,0.75,0.51311,0.25481,0.41615,0.45495,0.35879,0.53779,0.51177,0.74499,0.50502,0.54781,0.74375,0.48582,0.24944,0.48579,0.24711,0.54672,0.4461,0.39525,0.74217,0.4816,0.24815,0.48145,0.20105,0.3892,0.33401,0.45246,0.47985,0.25477,0.47865,0.74541,0.28336,0.55414,0.22008,0.41902,0.22989,0.5463,0.32648,0.53876,0.1979,0.52887,0.31721,0.49865,0.18131,0.49043,0.26551,0.44845,0.26326,0.56613,0.75,0.2316,0.75,0.2316,0.2316,0.25,0.25,0.25,0.75,0.25,0.75,0.75,0.25,0.75,0.12466,0.25,0.36179,0.25,0.36179,0.75,0.12466,0.75,0.75,0.63821,0.75,0.87534,0.25,0.87534,0.25,0.63821,0.75,0.63821,0.75,0.87534,0.25,0.87534,0.25,0.63821,0.63821,0.25,0.87534,0.25,0.87534,0.75,0.63821,0.75,0.51804,0.25,0.59277,0.25,0.59277,0.75,0.51804,0.75,0.25,0.36783,0.25,0.36783,0.36783,0.75,0.7684,0.75,0.63217,0.25,0.75,0.40723,0.75,0.48196,0.25,0.48196,0.25,0.40723,0.75,0.40723,0.75,0.48196,0.25,0.48196,0.25,0.40723,0.40723,0.25,0.48196,0.25,0.48196,0.75,0.40723,0.75,0.75,0.34879,0.25,0.2316,0.75,0.34879,0.25,0.2316,0.34879,0.25,0.2316,0.75,0.7684,0.25,0.65121,0.75,0.25,0.34879,0.25,0.34879,0.34879,0.75,0.65121,0.25,0.75,0.36783,0.75,0.36783,0.36783,0.25,0.63217,0.75,0.25,0.25,0.75,0.25,0.75,0.75,0.25,0.75,0.12466,0.25,0.36179,0.25,0.36179,0.75,0.12466,0.75,0.75,0.63821,0.75,0.87534,0.25,0.87534,0.25,0.63821,0.75,0.63821,0.75,0.87534,0.25,0.87534,0.25,0.63821,0.63821,0.25,0.87534,0.25,0.87534,0.75,0.63821,0.75,0.51804,0.25,0.59277,0.25,0.59277,0.75,0.51804,0.75,0.74317,0.3249,0.25,0.36783,0.74191,0.32163,0.25,0.36783,0.3188,0.25433,0.36783,0.75,0.63217,0.25,0.67186,0.74556,0.75,0.40723,0.75,0.48196,0.25,0.48196,0.25,0.40723,0.75,0.40723,0.75,0.48196,0.25,0.48196,0.25,0.40723,0.40723,0.25,0.48196,0.25,0.48196,0.75,0.40723,0.75,0.75,0.35156,0.25,0.33594,0.75,0.35156,0.25,0.33594,0.35156,0.25,0.33594,0.75,0.66406,0.25,0.64844,0.75,0.25,0.35156,0.25,0.35156,0.35156,0.75,0.64844,0.25,0.75,0.36783,0.75,0.36783,0.36783,0.25,0.63217,0.75,0.75,0.33594,0.75,0.33594,0.33594,0.25,0.66406,0.75,0.24891,0.32478,0.24779,0.32148,0.31794,0.74599,0.673,0.25465,0.4372,0.35394,0.2161,0.57798,0.25201,0.43317,0.22766,0.46727,0.48345,0.47226,0.45385,0.44714,0.40496,0.56008,0.18793,0.34747,0.59302,0.34645,0.22017,0.34215,0.54303,0.6644,0.55922,0.34102,0.60605,0.3844,0.23253,0.38073,0.26388,0.30561,0.26628,0.67493,0.29526,0.41023,0.16495,0.39775,0.26966,0.50105,0.31698,0.51449,0.33305,0.51969,0.20052,0.50922,0.17131,0.41195,0.17862,0.53203,0.38798,0.46648,0.36467,0.34894,0.36268,0.32952,0.35698,0.30225,0.3664,0.36943,0.34928,0.38896,0.35054,0.40295,0.37558,0.42864,0.37185,0.41278,0.39007,0.51578,0.40092,0.53697,0.38113,0.44691,0.37874,0.49367,0.36048,0.31569,0.36785,0.38544,0.36967,0.39933,0.40735,0.51132,0.41743,0.53322,0.39699,0.48864,0.40238,0.4626,0.37778,0.34577,0.37517,0.32617,0.36743,0.29908,0.38,0.36658,0.39051,0.42541,0.38667,0.40981,0.39585,0.44335,0.37215,0.31237,0.4104,0.43055,0.42459,0.48103,0.41677,0.45873,0.41057,0.43978,0.40543,0.42218,0.40149,0.40685,0.39861,0.39387,0.39592,0.38013,0.39359,0.36372,0.39089,0.34261,0.38767,0.32282,0.38381,0.30906,0.37788,0.29592,0.4328,0.49451,0.43318,0.50356,0.38347,0.31132,0.39887,0.37324,0.41311,0.43219,0.40784,0.42627,0.40619,0.42329,0.42429,0.47941,0.41663,0.45768,0.41059,0.43925,0.4056,0.42218,0.40178,0.40732,0.39904,0.39485,0.39652,0.38168,0.39434,0.36583,0.39127,0.34351,0.38766,0.32244,0.3839,0.30903,0.37827,0.2968,0.4146,0.43109,0.43216,0.49949,0.38188,0.38279,0.38414,0.3966,0.42041,0.50794,0.4299,0.53039,0.41079,0.48483,0.41197,0.46003,0.38652,0.34366,0.3835,0.32393,0.3744,0.29697,0.38906,0.36468,0.40045,0.42325,0.39655,0.40784,0.40567,0.44097,0.37992,0.31016,0.36895,0.4716,0.34732,0.35313,0.34616,0.33395,0.34315,0.30644,0.34842,0.37321,0.35584,0.43292,0.35225,0.4167,0.36165,0.45163,0.34506,0.32008,0.33052,0.39245,0.33122,0.40655,0.37267,0.52029,0.38435,0.54078,0.36029,0.4987,0.25,0,0.5,0.25,0.25,0.5,0,0.25,0.75,0,1,0.25,0.75,0.5,0.75,1,0.5,0.75,1,0.75,0.25,1,0,0.75,0.125,0,0.24657,0.25,0.1245,0.5,0.375,0,0.45779,0.25,0.35646,0.5,0.375,1,0.24657,0.75,0.45779,0.75,0.125,1,0.75,0.75343,0.5,0.64354,0.75,0.54221,0.5,0.8755,0,0.875,0.25,0.75343,0,0.625,0.25,0.54221,1,0.625,0.75,0.75343,0.5,0.64354,0.75,0.54221,1,0.875,0.5,0.8755,0.25,0.75343,0.25,0.54221,0.75343,0.25,0.64354,0.5,0.54221,0.25,0.8755,0.5,0.75343,0.75,0.54221,0.75,0.53125,0,0.55907,0.25,0.51271,0.5,0.59375,0,0.61823,0.25,0.59251,0.5,0.59375,1,0.55907,0.75,0.61823,0.75,0.53125,1,0.71087,0.33489,1,0.32031,0.75,0.38177,0.5,0.36792,0,0.36719,0.2437,0.33394,0.25,0.38177,0.70722,0.3242,1,0.32031,0.75,0.38177,0.5,0.36792,0,0.36719,0.24022,0.32309,0.25,0.38177,0.30103,0.26421,0.38177,0.25,0.36792,0.5,0.30165,0.7303,0.38177,0.75,0.64902,0.27369,0.67529,0.50009,0.64482,0.72785,0.75,0.44093,0.5,0.40749,0.5,0.48729,0,0.46875,0.25,0.44093,0,0.40625,1,0.40625,0.75,0.44093,0.5,0.40749,1,0.46875,0.5,0.48729,0.25,0.44093,0.44093,0.25,0.40749,0.5,0.48729,0.5,0.44093,0.75,1,0.35156,0.5,0.33594,0,0.33594,1,0.35156,0.5,0.33594,0,0.33594,0.33594,0.5,0.64844,0.5,0.75,0.34375,0.25,0.34375,0.75,0.34375,0.25,0.34375,0.34375,0.25,0.34375,0.75,0.65625,0.25,0.65625,0.75,0.5,0.35156,0,0.35156,0.5,0.35156,0,0.35156,0.35156,0.5,1,0.36719,1,0.36719,0.63208,0.5,0.25,0.35938,0.25,0.35938,0.35938,0.75,0.64062,0.25,0.75,0.35938,0.75,0.35938,0.35938,0.25,0.64062,0.75,1,0.33594,1,0.33594,0.66406,0.5,0.49754,0.32268,0,0.32031,0.49716,0.32152,0,0.32031,0.3191,0.4997,0.75,0.32812,0.75,0.32812,0.32812,0.25,0.67188,0.75,0.25,0.32812,0.25,0.32812,0.32812,0.75,0.67188,0.25,0.25,0,0.5,0.25,0.25,0.5,0,0.25,0.75,0,1,0.25,0.75,0.5,0.75,1,0.5,0.75,1,0.75,0.25,1,0,0.75,0.125,0,0.24657,0.25,0.1245,0.5,0.375,0,0.42041,0.26496,0.3524,0.49982,0.375,1,0.24657,0.75,0.42128,0.73169,0.125,1,0.75,0.75343,0.4975,0.64507,0.71029,0.55614,0.5,0.8755,0,0.875,0.25,0.75343,0,0.625,0.24342,0.55527,1,0.625,0.75,0.75343,0.49736,0.64465,0.70932,0.55223,1,0.875,0.5,0.8755,0.25,0.75343,0.24185,0.5515,0.75343,0.25,0.64223,0.50008,0.52956,0.26779,0.8755,0.5,0.75343,0.75,0.52933,0.73364,0.40624,0.11907,0.22246,0.48309,0.23834,0.60576,0.41746,0.53715,0.04459,0.50621,0.37854,0.49725,0.41298,0.5234,0.44344,0.50248,0.24301,0.42535,0.25937,0.42904,0.27328,0.41799,0.25755,0.41475,0.27278,0.40418,0.2589,0.4008,0.24313,0.41041,0.23123,0.40403,0.21707,0.41278,0.22884,0.41983,0.23149,0.43637,0.21843,0.4304,0.20242,0.555,0.19755,0.5594,0.2011,0.56803,0.21087,0.56188,0.18559,0.56851,0.19065,0.55758,0.19348,0.58056,0.19262,0.57364,0.20806,0.58639,0.20154,0.5786,0.19821,0.58832,0.20315,0.59374,0.21097,0.59503,0.21813,0.59522,0.21969,0.5835,0.22589,0.5676,0.23721,0.58549,0.2199,0.54716,0.16342,0.31919,0.21491,0.38535,0.16272,0.33905,0.16568,0.32931,0.17957,0.34128,0.17771,0.32621,0.17377,0.33278,0.28251,0.6424,0.28298,0.65191,0.27418,0.64932,0.31628,0.60163,0.27662,0.65582,0.28024,0.46275,0.2663,0.45781,0.25406,0.46955,0.26957,0.47232,0.2304,0.47729,0.24331,0.48141,0.23984,0.46601,0.23451,0.49308,0.24882,0.49654,0.25954,0.48397,0.28326,0.48335,0.28857,0.47067,0.16765,0.45403,0.16329,0.4597,0.16897,0.46578,0.17823,0.45932,0.15571,0.47242,0.16666,0.48242,0.16863,0.48113,0.16336,0.47282,0.18539,0.47585,0.17329,0.47358,0.17439,0.48272,0.18266,0.48624,0.1995,0.47964,0.19348,0.46488,0.18824,0.44754,0.24391,0.6288,0.24208,0.63464,0.24951,0.63752,0.25524,0.6299,0.23957,0.64501,0.24848,0.61913,0.25688,0.64784,0.24715,0.64581,0.33234,0.61986,0.26241,0.64839,0.27053,0.63088,0.2692,0.64025,0.25949,0.61859,0.21446,0.60107,0.22087,0.60802,0.22977,0.6002,0.2245,0.61747,0.21136,0.60863,0.21371,0.61576,0.23296,0.62313,0.22382,0.62715,0.23015,0.63101,0.23758,0.63054,0.24316,0.61857,0.24703,0.60386,0.23998,0.50879,0.25554,0.51182,0.26942,0.49791,0.24506,0.5243,0.25732,0.52905,0.26823,0.51936,0.27678,0.31666,0.29107,0.31284,0.28869,0.29486,0.27648,0.30024,0.27449,0.28573,0.26519,0.30438,0.25054,0.32008,0.2632,0.31832,0.14295,0.36314,0.14439,0.3677,0.14848,0.36601,0.14948,0.36089,0.13421,0.37195,0.13622,0.37731,0.14028,0.37126,0.13764,0.36639,0.14719,0.37076,0.1523,0.37207,0.15378,0.36631,0.15104,0.4073,0.14571,0.4083,0.14594,0.41377,0.1515,0.41442,0.1385,0.40656,0.14233,0.41102,0.14392,0.40221,0.13986,0.41493,0.13528,0.41067,0.1336,0.4153,0.13863,0.42046,0.1603,0.46674,0.15769,0.46162,0.15338,0.46051,0.15395,0.4654,0.16046,0.4533,0.15522,0.45643,0.14932,0.4567,0.1523,0.45033,0.18466,0.54986,0.18254,0.55433,0.18521,0.5582,0.18673,0.55403,0.19274,0.56577,0.19217,0.55962,0.1888,0.55754,0.18752,0.5622,0.19622,0.55295,0.19126,0.55456,0.1986,0.60801,0.20497,0.61064,0.20475,0.6075,0.20014,0.60544,0.2064,0.59852,0.20893,0.60316,0.19854,0.59481,0.19759,0.60187,0.20098,0.6,0.23363,0.64428,0.23621,0.64271,0.23187,0.64154,0.23445,0.63465,0.23795,0.63795,0.2301,0.63698,0.23427,0.63853,0.12356,0.36397,0.20187,0.42113,0.12874,0.3643,0.1722,0.41272,0.12166,0.36092,0.13874,0.36431,0.25697,0.59798,0.22747,0.64763,0.23144,0.63719,0.28825,0.58982,0.12636,0.4105,0.12099,0.41117,0.16436,0.43762,0.13187,0.40864,0.1492,0.45327,0.11902,0.41004,0.20816,0.56452,0.19329,0.6097,0.22505,0.58113,0.13291,0.46542,0.1374,0.45389,0.12277,0.47433,0.12986,0.47171,0.13953,0.47295,0.15592,0.46138,0.14938,0.46989,0.14112,0.46589,0.1685,0.49382,0.14817,0.47825,0.14445,0.45937,0.1471,0.41933,0.23137,0.56967,0.21581,0.57381,0.18812,0.52943,0.20261,0.51934,0.21194,0.49281,0.19463,0.41602,0.20722,0.4232,0.20432,0.4049,0.1788,0.40851,0.18156,0.4284,0.19863,0.43481,0.21149,0.44159,0.28116,0.56449,0.28638,0.54961,0.26883,0.54604,0.26523,0.55986,0.30751,0.55281,0.31442,0.53615,0.29045,0.53323,0.27111,0.53213,0.25333,0.54162,0.21248,0.48338,0.22324,0.4879,0.21975,0.47318,0.20443,0.49543,0.20899,0.51346,0.21679,0.49979,0.22803,0.50479,0.17859,0.35601,0.18737,0.34737,0.17939,0.37433,0.19071,0.36576,0.17513,0.39052,0.19018,0.38723,0.18959,0.39806,0.22727,0.46287,0.25078,0.45418,0.23603,0.45147,0.27962,0.44728,0.26348,0.44282,0.24648,0.44004,0.27655,0.43219,0.22312,0.44767,0.32739,0.62246,0.31261,0.61707,0.30624,0.62734,0.34024,0.62873,0.33791,0.61303,0.33521,0.59468,0.32161,0.6066,0.30357,0.60129,0.29682,0.61241,0.3122,0.58866,0.29248,0.58347,0.28657,0.59643,0.34722,0.57946,0.32225,0.57363,0.29951,0.56908,0.3316,0.55722,0.27613,0.57835,0.22175,0.51679,0.2333,0.52029,0.21359,0.53034,0.22746,0.5325,0.23992,0.53651,0.29179,0.4375,0.30208,0.42695,0.28842,0.42141,0.29325,0.45431,0.30463,0.44467,0.33924,0.54184,0.34486,0.52765,0.32042,0.52048,0.35502,0.56333,0.36058,0.5489,0.36836,0.58459,0.37477,0.56823,0.29613,0.32881,0.30762,0.32337,0.28251,0.34159,0.2918,0.35266,0.30421,0.34011,0.27712,0.36887,0.28743,0.37656,0.30128,0.36199,0.27338,0.38981,0.28666,0.39288,0.29941,0.38172,0.28669,0.40677,0.29916,0.39625,0.29981,0.41067,0.2445,0.57024,0.2609,0.57369,0.24995,0.55555,0.2347,0.551,0.18445,0.33389,0.18617,0.32577,0.19244,0.3388,0.29476,0.64879,0.29976,0.63766,0.2085,0.46911,0.21631,0.4587,0.20395,0.45318,0.28574,0.63268,0.29114,0.62274,0.28118,0.60846,0.27582,0.61986,0.26525,0.60538,0.27099,0.59186,0.25499,0.58815,0.16615,0.41949,0.15729,0.41048,0.15457,0.42343,0.15395,0.43372,0.14558,0.41947,0.14497,0.42648,0.15917,0.4435,0.14839,0.44292,0.17162,0.44255,0.19242,0.49103,0.18133,0.49674,0.1886,0.50254,0.20386,0.49743,0.18433,0.52159,0.18599,0.51328,0.18216,0.50699,0.1974,0.50873,0.17091,0.34824,0.16032,0.34386,0.16051,0.35249,0.16797,0.33947,0.15048,0.35461,0.15664,0.34807,0.23111,0.36547,0.14646,0.35987,0.16748,0.36406,0.15793,0.36022,0.15867,0.36992,0.16429,0.37938,0.15249,0.3804,0.14816,0.38901,0.14495,0.37605,0.14031,0.38211,0.15195,0.39819,0.13952,0.39542,0.1637,0.40049,0.20113,0.52676,0.19437,0.53688,0.19278,0.52039,0.18913,0.5298,0.22119,0.54298,0.18842,0.54399,0.18732,0.53761,0.20665,0.54445,0.1965,0.54517,0.17025,0.32245,0.27241,0.64808,0.17847,0.49411,0.24192,0.6415,0.25701,0.64218,0.21944,0.61944,0.22927,0.63112,0.2952,0.58261,0.13645,0.40235,0.1493,0.46225,0.14638,0.45161,0.19017,0.5496,0.20479,0.60254,0.14521,0.43396,0.18389,0.43486,0.17198,0.35639,0.15033,0.37312,0.13835,0.38721,0.21667,0.3843,0.20108,0.34311,0.19533,0.35376,0.20504,0.36039,0.20364,0.37559,0.21762,0.37947,0.20617,0.39126,0.2224,0.39371,0.26237,0.38385,0.24727,0.39541,0.23851,0.38728,0.25445,0.37436,0.26892,0.35842,0.23248,0.37597,0.24587,0.36519,0.23364,0.36194,0.21863,0.36285,0.22651,0.34738,0.21198,0.3467,0.22454,0.33497,0.23917,0.33376,0.25544,0.33198,0.24336,0.34649,0.25846,0.34963,0.27048,0.33321,0.30621,0.46303,0.29167,0.51631,0.29816,0.49942,0.31061,0.48423,0.32672,0.50497,0.34796,0.51396,0.35069,0.50084,0.33282,0.49124,0.41577,0.47079,0.34551,0.46621,0.33909,0.47898,0.32091,0.35902,0.38792,0.35474,0.32959,0.34709,0.32128,0.33983,0.32953,0.33091,0.4233,0.48139,0.41542,0.4591,0.38271,0.30937,0.37746,0.30391,0.37697,0.2962,0.32892,0.30281,0.32081,0.37854,0.39011,0.37337,0.39232,0.36399,0.38966,0.34291,0.39247,0.38803,0.3946,0.38038,0.32081,0.39379,0.32135,0.40801,0.39515,0.40135,0.39725,0.39413,0.32197,0.4711,0.33131,0.45887,0.31737,0.45186,0.40299,0.43215,0.33375,0.42831,0.32586,0.43968,0.32263,0.42268,0.36649,0.50962,0.36412,0.52255,0.43363,0.51683,0.37653,0.54295,0.43878,0.51919,0.32204,0.32569,0.31584,0.31888,0.31393,0.33225,0.32254,0.31173,0.38649,0.32313,0.31101,0.37076,0.31053,0.38749,0.31174,0.41674,0.31059,0.40165,0.40919,0.44011,0.37605,0.55584,0.36268,0.53542,0.40403,0.42248,0.43216,0.50458,0.4001,0.40713,0.31237,0.34956,0.31395,0.43328,0.25,0,0.5,0.25,0.25,0.5,0,0.25,0.75,0,1,0.25,0.75,0.5,0.75,1,0.5,0.75,1,0.75,0.25,1,0,0.75,0.125,0,0.24657,0.25,0.1245,0.5,0.375,0,0.45779,0.25,0.35646,0.5,0.375,1,0.24657,0.75,0.45779,0.75,0.125,1,0.75,0.75343,0.5,0.64354,0.75,0.54221,0.5,0.8755,0,0.875,0.25,0.75343,0,0.625,0.25,0.54221,1,0.625,0.75,0.75343,0.5,0.64354,0.75,0.54221,1,0.875,0.5,0.8755,0.25,0.75343,0.25,0.54221,0.75343,0.25,0.64354,0.5,0.54221,0.25,0.8755,0.5,0.75343,0.75,0.54221,0.75,0.53125,0,0.50735,0.30457,0.50633,0.49988,0.49225,0.69335,0.53125,1,0.68176,0.48175,0.49611,0.49168,0,0.46875,0.24629,0.48139,0.66492,0.4372,1,0.46875,0.49447,0.48679,0.23272,0.43551,0.41919,0.30402,0.48416,0.50012,0.40556,0.69794,0.27772,0.42917,0.33714,0.32648,0.37564,0.54823,0.6325,0.54797,0.42039,0.58236,0.35922,0.66546,0.32317,0.39195,0.56748,0.39691,0.21873,0.35722,0.37916,0.49417,0.41278,0.86859,0.26254,0.53659,0.13377,0.51865,0.79285,0.49908,0.24959,0.49689,0.26698,0.50706,0.3045,0.36361,0.31104,0.61313,0.46514,0.53325,0.21459,0.52676,0.45857,0.50621,0.2035,0.50072,0.34922,0.38353,0.34747,0.6264,0.75,0.125,1,0.23438,0.25,0.125,0.75,0.125,1,0.23438,0.125,0.25,0.125,0.75,0.25,0,0.5,0.25,0.25,0.5,0,0.25,0.75,0,1,0.25,0.75,0.5,0.75,1,0.5,0.75,1,0.75,0.25,1,0,0.75,0.125,0,0.24657,0.25,0.1245,0.5,0.375,0,0.45779,0.25,0.35646,0.5,0.375,1,0.24657,0.75,0.45779,0.75,0.125,1,0.75,0.75343,0.5,0.64354,0.75,0.54221,0.5,0.8755,0,0.875,0.25,0.75343,0,0.625,0.25,0.54221,1,0.625,0.75,0.75343,0.5,0.64354,0.75,0.54221,1,0.875,0.5,0.8755,0.25,0.75343,0.25,0.54221,0.75343,0.25,0.64354,0.5,0.54221,0.25,0.8755,0.5,0.75343,0.75,0.54221,0.75,0.53125,0,0.55907,0.25,0.51271,0.5,0.59375,0,0.61823,0.25,0.59251,0.5,0.59375,1,0.55907,0.75,0.61823,0.75,0.53125,1,0.75,0.38177,0.5,0.36792,0,0.36719,0.25,0.38177,0.75,0.38177,0.5,0.36792,0,0.36719,0.25,0.38177,0.38177,0.25,0.36792,0.5,0.38177,0.75,0.875,0.25,0.7688,0.5,0.875,0.75,0.75,0.44093,0.5,0.40749,0.5,0.48729,0,0.46875,0.25,0.44093,0,0.40625,1,0.40625,0.75,0.44093,0.5,0.40749,1,0.46875,0.5,0.48729,0.25,0.44093,0.44093,0.25,0.40749,0.5,0.48729,0.5,0.44093,0.75,1,0.35156,0.5,0.2312,0,0.23438,1,0.35156,0.5,0.2312,0,0.23438,0.2312,0.5,0.65161,0.5,0.75,0.31439,0.25,0.31439,0.75,0.31439,0.25,0.31439,0.31439,0.25,0.31439,0.75,0.68561,0.25,0.68561,0.75,0.5,0.34839,0,0.35156,0.5,0.34839,0,0.35156,0.34839,0.5,1,0.36719,1,0.36719,0.63208,0.5,0.25,0.35938,0.25,0.35938,0.35938,0.75,0.64062,0.25,0.75,0.35938,0.75,0.35938,0.35938,0.25,0.64062,0.75,0.25,0,0.5,0.25,0.25,0.5,0,0.25,0.75,0,1,0.25,0.75,0.5,0.75,1,0.5,0.75,1,0.75,0.25,1,0,0.75,0.125,0,0.24657,0.25,0.1245,0.5,0.375,0,0.45779,0.25,0.35646,0.5,0.375,1,0.24657,0.75,0.45779,0.75,0.125,1,0.75,0.75343,0.5,0.64354,0.75,0.54221,0.5,0.8755,0,0.875,0.25,0.75343,0,0.625,0.25,0.54221,1,0.625,0.75,0.75343,0.5,0.64354,0.75,0.54221,1,0.875,0.5,0.8755,0.25,0.75343,0.25,0.54221,0.75343,0.25,0.64354,0.5,0.54221,0.25,0.8755,0.5,0.75343,0.75,0.54221,0.75,0.53125,0,0.55907,0.25,0.51271,0.5,0.59375,0,0.61823,0.25,0.59251,0.5,0.59375,1,0.55907,0.75,0.61823,0.75,0.53125,1,0.67558,0.361,1,0.32031,0.75,0.38177,0.5,0.36792,0,0.36719,0.24063,0.35967,0.25,0.38177,0.66227,0.32652,1,0.32031,0.75,0.38177,0.5,0.36792,0,0.36719,0.22894,0.3248,0.25,0.38177,0.29682,0.29896,0.38177,0.25,0.36792,0.5,0.2871,0.70436,0.38177,0.75,0.61725,0.30259,0.67139,0.50013,0.60436,0.69959,0.75,0.44093,0.5,0.40749,0.5,0.48729,0,0.46875,0.25,0.44093,0,0.40625,1,0.40625,0.75,0.44093,0.5,0.40749,1,0.46875,0.5,0.48729,0.25,0.44093,0.44093,0.25,0.40749,0.5,0.48729,0.5,0.44093,0.75,1,0.35156,0.5,0.33594,0,0.33594,1,0.35156,0.5,0.33594,0,0.33594,0.33594,0.5,0.64844,0.5,0.75,0.34375,0.25,0.34375,0.75,0.34375,0.25,0.34375,0.34375,0.25,0.34375,0.75,0.65625,0.25,0.65625,0.75,0.5,0.35156,0,0.35156,0.5,0.35156,0,0.35156,0.35156,0.5,1,0.36719,1,0.36719,0.63208,0.5,0.25,0.35938,0.25,0.35938,0.35938,0.75,0.64062,0.25,0.75,0.35938,0.75,0.35938,0.35938,0.25,0.64062,0.75,1,0.33594,1,0.33594,0.66406,0.5,0.49547,0.32549,0,0.32031,0.49412,0.32173,0,0.32031,0.31806,0.50019,0.75,0.32812,0.75,0.32812,0.32812,0.25,0.67188,0.75,0.25,0.32812,0.25,0.32812,0.32812,0.75,0.67188,0.25,0.31198,0.35047,0.56112,0.35672,0.21358,0.45482,0.25646,0.30865,0.35511,0.47041,0.61042,0.47486,0.45438,0.57664,0.40686,0.68749,0.2691,0.86313,0.40629,0.34443,0.033215,0.3391,0.54527,0.47797,0.56363,0.14963,0.41891,0.3829,0.045162,0.37682,0.26464,0.4901,0.18231,0.58938,0.23042,0.40369,0.099645,0.39229,0.26082,0.43391,0.31588,0.44889,0.26674,0.51441,0.13549,0.50547,0.17418,0.4716,0.44392,0.3782,0.19241,0.36979,0.40662,0.58269,0.43825,0.42784,0.4693,0.45208,0.21646,0.44489,0.21742,0.35875,0.22212,0.60338,0.37348,0.48251,0.38432,0.45631,0.34794,0.36372,0.36364,0.33841,0.36168,0.32211,0.34425,0.31365,0.35485,0.29467,0.34883,0.38154,0.34983,0.39594,0.35134,0.40988,0.35861,0.44231,0.37338,0.42008,0.40213,0.50008,0.39561,0.52648,0.37854,0.46902,0.35606,0.35102,0.35448,0.33172,0.35012,0.30433,0.35748,0.3713,0.35863,0.38719,0.36018,0.40113,0.36579,0.43077,0.36213,0.41473,0.39877,0.51353,0.40923,0.53509,0.37147,0.44925,0.38794,0.49114,0.35283,0.31787,0.3922,0.47732,0.36563,0.35975,0.35895,0.30934,0.3671,0.37793,0.3687,0.39244,0.37073,0.4061,0.37825,0.43782,0.41247,0.52235,0.39889,0.45259,0.37646,0.33511,0.37379,0.31876,0.36458,0.29161,0.3883,0.417,0.41555,0.49648,0.37589,0.38392,0.37796,0.39777,0.41483,0.50939,0.42465,0.53158,0.4049,0.48646,0.39623,0.46426,0.37218,0.34713,0.36984,0.3276,0.36303,0.30041,0.37419,0.3678,0.38413,0.42679,0.38034,0.41108,0.38956,0.44487,0.36717,0.31379,0.42026,0.46523,0.41408,0.44856,0.40935,0.43472,0.40576,0.42248,0.40305,0.41189,0.4016,0.40397,0.40055,0.39587,0.39979,0.38509,0.3934,0.35189,0.38645,0.31928,0.38361,0.3091,0.38042,0.30327,0.40636,0.40158,0.42651,0.47953,0.42896,0.49289,0.42049,0.46948,0.41346,0.44886,0.40794,0.43101,0.40322,0.41391,0.40003,0.4004,0.39723,0.38714,0.39471,0.37246,0.39237,0.35374,0.38928,0.33182,0.38591,0.31541,0.38117,0.30283,0.37431,0.28856,0.43505,0.50601,0.38763,0.32977,0.40973,0.41563,0.41198,0.43264,0.40901,0.42828,0.4069,0.42459,0.42857,0.49097,0.42027,0.46815,0.41341,0.44806,0.40806,0.43083,0.40344,0.41408,0.40039,0.40112,0.39774,0.3884,0.39539,0.37431,0.39305,0.35564,0.38935,0.3317,0.38597,0.31529,0.3813,0.3029,0.37431,0.28856,0.42916,0.4851,0.42474,0.48099,0.41692,0.45869,0.41073,0.43974,0.40558,0.42214,0.40164,0.40682,0.39876,0.39384,0.39607,0.38011,0.39373,0.36369,0.39103,0.34258,0.3878,0.32278,0.38393,0.30902,0.37798,0.29589,0.42379,0.46297,0.43304,0.50258,0.40634,0.4734,0.379,0.35675,0.37006,0.30608,0.3809,0.37519,0.38296,0.38979,0.38538,0.40325,0.3931,0.43441,0.42522,0.51922,0.40861,0.4501,0.385,0.33292,0.38187,0.31653,0.37107,0.28958,0.39825,0.41494,0.42449,0.49409,0.38671,0.38188,0.38911,0.39566,0.4249,0.50679,0.43417,0.52942,0.41554,0.48353,0.40732,0.46127,0.38229,0.34469,0.37947,0.32502,0.37101,0.298,0.38467,0.3656,0.39564,0.4243,0.39176,0.40879,0.40091,0.44212,0.37615,0.31123,0.36505,0.46124,0.34668,0.34276,0.34566,0.32654,0.34188,0.29874,0.35364,0.42417,0.38438,0.50484,0.35454,0.48768,0.33008,0.36769,0.32947,0.31788,0.33037,0.38514,0.33078,0.39943,0.33179,0.41366,0.33877,0.44687,0.37866,0.53067,0.35935,0.47418,0.33858,0.35524,0.33783,0.33618,0.33618,0.30854,0.33936,0.37511,0.3459,0.43508,0.34237,0.41868,0.35184,0.45401,0.33729,0.32229,0.33992,0.39073,0.34089,0.40477,0.38136,0.51803,0.39261,0.53886,0.36954,0.49621,0.25,1,1,0.25,0.75,1,0,0.25,0.25,1,0,0.75,0.75,1,1,0.75,1,0.875,1,0.625,0,0.625,0,0.875,0.875,0,0.625,0,0.625,1,0.875,1,1,0.46875,1,0.40625,0,0.40625,0,0.46875,0.67969,0,0.36719,0,0.32031,1,0.63281,1,0.46875,0,0.40625,0,0.40625,1,0.46875,1,0.64844,0,0.33594,0,0.35156,1,0.66406,1,0.35156,0,0.64844,1,0.63281,0,0.36719,1,0.66406,0,0.33594,1,0.32031,0,0.67969,1,0.25,1,1,0.25,0.75,1,0,0.25,0.25,1,0,0.75,0.75,1,1,0.75,1,0.875,1,0.625,0,0.625,0,0.875,0.875,0,0.625,0,0.625,1,0.875,1,0.79514,0.51271,0.11334,0.48075,0.41959,0.13121,0.25354,0.62225,0.2808,0.66273,0.29368,0.65953,0.35446,0.60213,0.35091,0.62016,0.12521,0.47548,0.22329,0.652,0.22334,0.65495,0.18848,0.61198,0.18688,0.61441,0.18258,0.56381,0.25,0.125,0.30317,0.30972,0.31032,0.30986,0.30457,0.65626,0.28603,0.66019,0.38982,0.5507,0.31653,0.30301,0.25,1,1,0.25,0.75,1,0,0.25,0.25,1,0,0.75,0.75,1,1,0.75,1,0.875,1,0.625,0,0.625,0,0.875,0.875,0,0.625,0,0.625,1,0.875,1,1,0.46875,0,0.46875,0.46875,0,0.46875,1,0.32943,0.57959,0.11839,0.54522,0.41375,0.32921,0.36117,0.40874,0.07797,0.38421,0.28623,0.67815,0.38543,0.53812,0.03778,0.49358,0.25877,0.39365,0.41785,0.87408,0.26403,0.29102,0.76562,0,0.21239,0.33345,0.19475,0.32973,0.23438,1,0.32053,0.63236,0.3108,0.64422,0.25,1,1,0.25,0.75,1,0,0.25,0.25,1,0,0.75,0.75,1,1,0.75,1,0.875,1,0.625,0,0.625,0,0.875,0.875,0,0.625,0,0.625,1,0.875,1,1,0.46875,1,0.40625,0,0.40625,0,0.46875,0.36719,0,0.63281,1,0.25522,0.30664,0.23799,0.32221,0.46875,0,0.40625,0,0.40625,1,0.46875,1,0.64844,0,0.23438,0,0.35156,1,0.76562,1,0.35156,0,0.64844,1,0.63281,0,0.36719,1,0.25,1,1,0.25,0.75,1,0,0.25,0.25,1,0,0.75,0.75,1,1,0.75,1,0.875,1,0.625,0,0.625,0,0.875,0.875,0,0.625,0,0.625,1,0.875,1,1,0.46875,1,0.40625,0,0.40625,0,0.46875,0.67969,0,0.36719,0,0.32031,1,0.63281,1,0.46875,0,0.40625,0,0.40625,1,0.46875,1,0.64844,0,0.33594,0,0.35156,1,0.66406,1,0.35156,0,0.64844,1,0.63281,0,0.36719,1,0.66406,0,0.33594,1,0.32031,0,0.67969,1,0.21738,0.70047,0.24765,0.55885,0.10021,0.4649,0.45416,0.31861,0.40462,0.43222,0.063115,0.34375,0.78473,0.3475,0.54884,0.85472,0.56212,0.52821,0.798,0.384,0.2644,0.1185,0.35418,0.41751,0.27152,0.56417,0.31136,0.58464,0.39401,0.52702,0.1682,0.35549,0.42237,0.544,0.43457,0.54148,0.42866,0.47637,0.39243,0.35116,0.44271,0.53981,0.40609,0.54735,0.125,0,0.375,0,0.5,0.125,0.5,0.375,0.375,0.5,0.125,0.5,0,0.375,0,0.125,0.625,0,0.875,0,1,0.125,1,0.375,0.875,0.5,0.625,0.5,0.875,1,0.625,1,0.5,0.875,0.5,0.625,1,0.625,1,0.875,0.375,1,0.125,1,0,0.875,0,0.625,0.0625,0,0.1875,0,0.24817,0.125,0.24542,0.375,0.18549,0.5,0.0625,0.5,0.3125,0,0.4375,0,0.47144,0.125,0.45056,0.375,0.40564,0.5,0.30243,0.5,0.4375,1,0.3125,1,0.24817,0.875,0.24542,0.625,0.45056,0.625,0.47144,0.875,0.1875,1,0.0625,1,0.875,0.75183,0.625,0.75458,0.5,0.69757,0.5,0.59436,0.625,0.54944,0.875,0.52856,0.5,0.9375,0.5,0.81451,0,0.9375,0,0.8125,0.125,0.75183,0.375,0.75458,0,0.6875,0,0.5625,0.125,0.52856,0.375,0.54944,1,0.5625,1,0.6875,0.875,0.75183,0.625,0.75458,0.5,0.69757,0.5,0.59436,0.625,0.54944,0.875,0.52856,1,0.8125,1,0.9375,0.5,0.9375,0.5,0.81451,0.125,0.75183,0.375,0.75458,0.125,0.52856,0.375,0.54944,0.75183,0.125,0.75458,0.375,0.69757,0.5,0.59436,0.5,0.54944,0.375,0.52856,0.125,0.9375,0.5,0.81451,0.5,0.75183,0.875,0.75458,0.625,0.52856,0.875,0.54944,0.625,0.51562,0,0.54688,0,0.56067,0.125,0.55792,0.375,0.5368,0.5,0.48377,0.5,0.57812,0,0.60938,0,0.61987,0.125,0.61768,0.375,0.60645,0.5,0.57611,0.5,0.60938,1,0.57812,1,0.56067,0.875,0.55792,0.625,0.61768,0.625,0.61987,0.875,0.54688,1,0.51562,1,0.59078,0.33648,0.84044,0.32958,1,0.31641,1,0.32422,0.875,0.38013,0.625,0.38232,0.5,0.37402,0.5,0.36328,0,0.37109,0,0.36328,0.1252,0.32857,0.36009,0.33592,0.375,0.38232,0.125,0.38013,0.58689,0.32487,0.83763,0.32153,1,0.31641,1,0.32422,0.875,0.38013,0.625,0.38232,0.5,0.37402,0.5,0.36328,0,0.37109,0,0.36328,0.12258,0.32035,0.35631,0.32422,0.375,0.38232,0.125,0.38013,0.3002,0.38199,0.30377,0.1409,0.38013,0.125,0.38232,0.375,0.37402,0.5,0.36328,0.5,0.30443,0.85499,0.30057,0.61204,0.38232,0.625,0.38013,0.875,0.65858,0.14825,0.64526,0.39093,0.66599,0.50035,0.67578,0.5,0.64174,0.61082,0.65518,0.85285,0.875,0.43933,0.625,0.44208,0.5,0.42389,0.5,0.39355,0.5,0.51623,0.5,0.4632,0,0.48438,0,0.45312,0.125,0.43933,0.375,0.44208,0,0.42188,0,0.39062,1,0.39062,1,0.42188,0.875,0.43933,0.625,0.44208,0.5,0.42389,0.5,0.39355,1,0.45312,1,0.48438,0.5,0.51623,0.5,0.4632,0.125,0.43933,0.375,0.44208,0.43933,0.125,0.44208,0.375,0.42389,0.5,0.39355,0.5,0.51623,0.5,0.4632,0.5,0.43933,0.875,0.44208,0.625,1,0.34766,1,0.35547,0.5,0.33984,0.5,0.33203,0,0.33984,0,0.33203,1,0.34766,1,0.35547,0.5,0.33984,0.5,0.33203,0,0.33984,0,0.33203,0.33984,0.5,0.33203,0.5,0.65234,0.5,0.64453,0.5,0.875,0.34375,0.625,0.34375,0.125,0.34375,0.375,0.34375,0.875,0.34375,0.625,0.34375,0.125,0.34375,0.375,0.34375,0.34375,0.125,0.34375,0.375,0.34375,0.875,0.34375,0.625,0.65625,0.125,0.65625,0.375,0.65625,0.875,0.65625,0.625,0.5,0.35547,0.5,0.34766,0,0.35547,0,0.34766,0.5,0.35547,0.5,0.34766,0,0.35547,0,0.34766,0.35547,0.5,0.34766,0.5,1,0.36328,1,0.37109,1,0.36328,1,0.37109,0.63672,0.5,0.62598,0.5,0.125,0.35938,0.375,0.35938,0.125,0.35938,0.375,0.35938,0.35938,0.875,0.35938,0.625,0.64062,0.125,0.64062,0.375,0.875,0.35938,0.625,0.35938,0.875,0.35938,0.625,0.35938,0.35938,0.125,0.35938,0.375,0.64062,0.875,0.64062,0.625,1,0.33203,1,0.33984,1,0.33203,1,0.33984,0.66797,0.5,0.66016,0.5,0.5,0.32422,0.49017,0.32589,0,0.32422,0,0.31641,0.5,0.32422,0.48864,0.32122,0,0.32422,0,0.31641,0.32422,0.5,0.31155,0.4988,0.875,0.32812,0.625,0.32812,0.875,0.32812,0.625,0.32812,0.32812,0.125,0.32812,0.375,0.67188,0.875,0.67188,0.625,0.125,0.32812,0.375,0.32812,0.125,0.32812,0.375,0.32812,0.32812,0.875,0.32812,0.625,0.67188,0.125,0.67188,0.375,0.125,0,0.375,0,0.5,0.125,0.5,0.375,0.375,0.5,0.125,0.5,0,0.375,0,0.125,0.625,0,0.875,0,1,0.125,1,0.375,0.875,0.5,0.625,0.5,0.875,1,0.625,1,0.5,0.875,0.5,0.625,1,0.625,1,0.875,0.375,1,0.125,1,0,0.875,0,0.625,0.0625,0,0.1875,0,0.24817,0.125,0.24542,0.375,0.18549,0.5,0.0625,0.5,0.3125,0,0.4375,0,0.44341,0.14132,0.40992,0.383,0.38939,0.49929,0.30243,0.5,0.4375,1,0.3125,1,0.24817,0.875,0.24542,0.625,0.41043,0.61343,0.44433,0.8561,0.1875,1,0.0625,1,0.875,0.75183,0.625,0.75458,0.5,0.69757,0.49,0.60047,0.59024,0.56472,0.83994,0.53885,0.5,0.9375,0.5,0.81451,0,0.9375,0,0.8125,0.125,0.75183,0.375,0.75458,0,0.6875,0,0.5625,0.12502,0.53794,0.35973,0.56422,1,0.5625,1,0.6875,0.875,0.75183,0.625,0.75458,0.5,0.69757,0.48945,0.5988,0.58905,0.56052,0.83929,0.53588,1,0.8125,1,0.9375,0.5,0.9375,0.5,0.81451,0.125,0.75183,0.375,0.75458,0.12373,0.53511,0.35819,0.56009,0.75183,0.125,0.75458,0.375,0.69757,0.5,0.58911,0.5003,0.53614,0.3858,0.51865,0.14363,0.9375,0.5,0.81451,0.5,0.75183,0.875,0.75458,0.625,0.51841,0.85747,0.53601,0.61571,0.45312,0.059536,0.35936,0.17861,0.18888,0.48037,0.2612,0.48588,0.19787,0.5443,0.28195,0.67146,0.44998,0.54676,0.37994,0.53444,0.022295,0.50311,0.066885,0.50932,0.29144,0.50254,0.48212,0.49771,0.44726,0.53842,0.37342,0.51443,0.48996,0.5015,0.39813,0.50361,0.24364,0.42919,0.2426,0.42149,0.26705,0.42703,0.25176,0.43103,0.27292,0.4145,0.27383,0.42152,0.24991,0.41632,0.26522,0.41298,0.27292,0.40073,0.27269,0.4076,0.25179,0.40215,0.26602,0.39915,0.24266,0.41402,0.24385,0.40681,0.22436,0.40364,0.23799,0.40383,0.21701,0.4172,0.21706,0.40807,0.23544,0.41884,0.22272,0.4207,0.2377,0.43472,0.2258,0.43788,0.21946,0.43485,0.21762,0.42594,0.20007,0.55553,0.20555,0.55405,0.19672,0.56146,0.19818,0.55734,0.20482,0.5709,0.19809,0.56552,0.21041,0.55693,0.2109,0.56746,0.18372,0.56834,0.18742,0.56808,0.20068,0.55942,0.18262,0.55883,0.19351,0.58178,0.19867,0.57495,0.19079,0.57037,0.19449,0.57713,0.20897,0.58172,0.20739,0.59024,0.19872,0.57976,0.20488,0.5772,0.19889,0.59187,0.19733,0.58458,0.20499,0.5934,0.20134,0.59435,0.21291,0.59619,0.20894,0.59406,0.22134,0.59357,0.2158,0.59642,0.2158,0.57957,0.22291,0.5874,0.21859,0.57107,0.23282,0.56423,0.24367,0.58223,0.23103,0.58863,0.21445,0.55006,0.2255,0.54407,0.16163,0.31833,0.16522,0.32005,0.21106,0.39789,0.2039,0.36034,0.16155,0.33569,0.17054,0.35223,0.16637,0.32513,0.16482,0.33334,0.18303,0.34106,0.17619,0.34123,0.17559,0.3251,0.17983,0.32731,0.17356,0.33694,0.17374,0.32847,0.27919,0.64375,0.28627,0.64111,0.28604,0.65574,0.27976,0.64833,0.29377,0.63396,0.26845,0.65319,0.3071,0.62523,0.32233,0.58869,0.27318,0.65345,0.28,0.65833,0.28026,0.45905,0.28004,0.46609,0.25936,0.45966,0.27327,0.45626,0.25496,0.47341,0.2533,0.46563,0.27551,0.47012,0.26295,0.47471,0.23127,0.48107,0.22959,0.4736,0.24954,0.47935,0.23751,0.48328,0.23408,0.46807,0.24603,0.46386,0.2358,0.49716,0.23332,0.48899,0.25596,0.49375,0.24259,0.499,0.25766,0.48062,0.26171,0.48729,0.29335,0.4792,0.27336,0.48717,0.2833,0.4694,0.29508,0.47221,0.16514,0.45511,0.17111,0.45268,0.16292,0.46184,0.16351,0.45753,0.17334,0.46686,0.16534,0.46478,0.17715,0.45521,0.17895,0.4635,0.15612,0.47623,0.15643,0.47033,0.17764,0.48461,0.15843,0.48149,0.16763,0.47899,0.17514,0.48381,0.16038,0.47093,0.16644,0.47487,0.18283,0.47226,0.18749,0.47944,0.17124,0.47542,0.17575,0.47141,0.17647,0.48591,0.17205,0.47979,0.18557,0.48471,0.18033,0.48776,0.20513,0.47788,0.19407,0.48141,0.18657,0.46658,0.20017,0.46319,0.18161,0.44936,0.19503,0.44577,0.24212,0.63045,0.24645,0.62672,0.24248,0.63643,0.24153,0.63289,0.254,0.63696,0.24575,0.63795,0.25268,0.62706,0.2576,0.63285,0.23962,0.63716,0.23996,0.64647,0.26802,0.62,0.23509,0.61772,0.25386,0.64902,0.26782,0.63956,0.24365,0.64538,0.25094,0.64621,0.34491,0.61503,0.31314,0.62113,0.25866,0.64741,0.26609,0.64969,0.26543,0.63344,0.27566,0.62848,0.27292,0.6425,0.26509,0.63827,0.25433,0.6215,0.26504,0.61569,0.21423,0.6033,0.21446,0.59887,0.22567,0.60968,0.21691,0.60661,0.22788,0.59561,0.23128,0.60534,0.22755,0.61538,0.22191,0.61929,0.20983,0.61001,0.21268,0.60711,0.21674,0.61825,0.21077,0.61348,0.23274,0.61863,0.23323,0.62687,0.22552,0.63018,0.22187,0.62402,0.23179,0.63032,0.2286,0.63191,0.23955,0.63108,0.23554,0.63011,0.23881,0.61561,0.24677,0.62145,0.24015,0.60768,0.25369,0.6003,0.24136,0.51255,0.23856,0.50502,0.26394,0.50965,0.24852,0.51411,0.26669,0.49412,0.27224,0.50221,0.24648,0.52845,0.24384,0.52027,0.26175,0.52756,0.25276,0.53082,0.27104,0.51432,0.26627,0.52361,0.28008,0.32073,0.27368,0.31315,0.29374,0.30699,0.28806,0.3189,0.28487,0.29185,0.29252,0.29787,0.27379,0.30533,0.2789,0.29481,0.27121,0.28417,0.27776,0.28728,0.26791,0.30712,0.26257,0.30179,0.25159,0.32304,0.24987,0.31705,0.26725,0.31433,0.25844,0.32216,0.14205,0.36511,0.14417,0.36114,0.14565,0.36795,0.14295,0.36741,0.1501,0.36464,0.1473,0.36724,0.14775,0.35994,0.15097,0.36195,0.1423,0.38129,0.13234,0.3675,0.13696,0.37603,0.1402,0.38139,0.14075,0.36912,0.13999,0.37357,0.13556,0.36597,0.13957,0.36676,0.14793,0.37266,0.14677,0.36919,0.15367,0.3705,0.15075,0.37361,0.1531,0.36469,0.15432,0.36796,0.14966,0.40546,0.15222,0.40922,0.14501,0.40996,0.14671,0.40628,0.14722,0.41569,0.14509,0.41218,0.15242,0.41238,0.15038,0.41634,0.13878,0.40877,0.13837,0.40416,0.14365,0.41106,0.14081,0.41095,0.14138,0.4018,0.14613,0.40288,0.13944,0.41286,0.14054,0.41721,0.13316,0.41059,0.13728,0.41076,0.13859,0.42033,0.13165,0.4124,0.13957,0.41993,0.13988,0.42189,0.16142,0.46539,0.15905,0.46795,0.15616,0.46052,0.15975,0.46272,0.15238,0.46094,0.1544,0.46005,0.15563,0.46728,0.15258,0.46343,0.15848,0.45196,0.16228,0.45471,0.15513,0.45839,0.15564,0.45392,0.15028,0.45914,0.1486,0.45392,0.15025,0.45047,0.15436,0.45043,0.18474,0.55006,0.18563,0.54974,0.18352,0.55608,0.18155,0.55258,0.18603,0.55808,0.18457,0.5582,0.18683,0.55197,0.18679,0.55597,0.19431,0.5647,0.19102,0.56662,0.19113,0.5582,0.19368,0.56133,0.18787,0.55772,0.18977,0.55737,0.18818,0.56464,0.18715,0.55997,0.19474,0.55155,0.19758,0.55449,0.19077,0.55614,0.19207,0.55266,0.20046,0.59922,0.19764,0.60949,0.20651,0.61281,0.2037,0.60117,0.20363,0.60567,0.20622,0.60939,0.19865,0.60637,0.20149,0.6046,0.20642,0.60032,0.20657,0.59622,0.21101,0.60422,0.20743,0.6022,0.205,0.59069,0.19765,0.59574,0.19604,0.60552,0.2044,0.59454,0.20022,0.59773,0.20181,0.60199,0.23734,0.63563,0.23155,0.64579,0.23457,0.6414,0.23817,0.64386,0.2311,0.64257,0.23251,0.64072,0.23497,0.63622,0.23398,0.63257,0.24003,0.63818,0.23639,0.63757,0.2316,0.63856,0.2286,0.63513,0.2349,0.63778,0.23367,0.63927,0.12265,0.36421,0.12448,0.36373,0.19631,0.42726,0.18517,0.40059,0.12667,0.36375,0.13102,0.3649,0.15701,0.39367,0.18052,0.41756,0.12353,0.36221,0.1198,0.35964,0.1527,0.37115,0.13388,0.36341,0.25646,0.58986,0.24833,0.6199,0.22614,0.64954,0.22886,0.64568,0.24456,0.62409,0.22836,0.64242,0.27288,0.6136,0.28992,0.57839,0.12438,0.4105,0.1286,0.41051,0.11979,0.41152,0.12219,0.41081,0.16412,0.44129,0.15333,0.42766,0.14182,0.41275,0.12962,0.40859,0.13893,0.43765,0.15731,0.45548,0.1212,0.41025,0.11684,0.40984,0.20955,0.55624,0.20118,0.58434,0.19166,0.6107,0.19513,0.60857,0.21538,0.59381,0.22721,0.57388,0.1352,0.46491,0.13354,0.46681,0.13245,0.45514,0.14021,0.4583,0.12411,0.4745,0.12144,0.47416,0.1325,0.4702,0.12742,0.47322,0.13638,0.47075,0.1475,0.47528,0.16037,0.46826,0.14735,0.45997,0.14739,0.46622,0.15322,0.47571,0.13823,0.46725,0.14381,0.46467,0.16812,0.49624,0.16628,0.48696,0.14471,0.47325,0.15304,0.47782,0.14827,0.45912,0.14444,0.46112,0.15611,0.42181,0.14142,0.4195,0.23472,0.57382,0.22284,0.56609,0.23507,0.57543,0.20139,0.5734,0.18349,0.52219,0.19637,0.53422,0.20421,0.52066,0.20294,0.51455,0.20193,0.48958,0.21812,0.49818,0.19538,0.42068,0.19381,0.4114,0.2121,0.42233,0.20207,0.42419,0.19876,0.4059,0.20989,0.40378,0.17189,0.40922,0.18594,0.4077,0.1893,0.42679,0.1733,0.43012,0.19734,0.43009,0.2,0.4395,0.21599,0.44044,0.20675,0.44279,0.28686,0.562,0.27586,0.5668,0.2828,0.54495,0.2898,0.55439,0.26402,0.54844,0.27382,0.54341,0.26806,0.56444,0.26231,0.5553,0.31535,0.54955,0.30005,0.55611,0.30947,0.53106,0.31902,0.54131,0.28453,0.53695,0.29693,0.52951,0.26763,0.52882,0.27502,0.53607,0.25629,0.54617,0.25061,0.53712,0.21347,0.48716,0.21152,0.47975,0.22757,0.48646,0.21897,0.48942,0.21532,0.47467,0.22415,0.47165,0.20954,0.49321,0.1995,0.49763,0.2142,0.51096,0.20395,0.51585,0.21561,0.49539,0.218,0.50423,0.2324,0.50304,0.22375,0.50659,0.18384,0.35579,0.17296,0.35611,0.18694,0.3439,0.18782,0.35113,0.18673,0.37635,0.17262,0.37274,0.18938,0.36026,0.19247,0.37186,0.18136,0.39118,0.16773,0.38995,0.19255,0.38388,0.18767,0.38993,0.18746,0.39436,0.19136,0.4023,0.22806,0.46642,0.22641,0.45927,0.24977,0.45054,0.25171,0.45791,0.2305,0.45361,0.24208,0.44922,0.27915,0.44338,0.27994,0.45121,0.25593,0.44482,0.27109,0.44104,0.24759,0.4435,0.24542,0.43654,0.27551,0.42861,0.27757,0.43583,0.22433,0.45169,0.22187,0.44352,0.326,0.61865,0.32874,0.62611,0.30704,0.61841,0.31843,0.61584,0.30854,0.63126,0.30396,0.62353,0.34537,0.6284,0.3351,0.62906,0.33113,0.61379,0.34477,0.61246,0.32601,0.59628,0.34535,0.59317,0.32315,0.61072,0.31983,0.60235,0.29746,0.603,0.31027,0.59961,0.29926,0.61611,0.29433,0.60864,0.30906,0.58384,0.31512,0.59337,0.28671,0.58553,0.29881,0.5813,0.28919,0.60067,0.28395,0.59206,0.34323,0.57374,0.35159,0.58539,0.31378,0.57636,0.33091,0.57086,0.30267,0.57402,0.29633,0.56415,0.32756,0.55185,0.33554,0.56267,0.27873,0.58299,0.2735,0.57369,0.22306,0.52072,0.22048,0.51277,0.23772,0.51836,0.229,0.52232,0.21921,0.52733,0.20782,0.53348,0.2259,0.5285,0.22911,0.53667,0.24407,0.53458,0.23559,0.53865,0.29781,0.43665,0.28536,0.43842,0.30139,0.42269,0.30279,0.4313,0.28169,0.42316,0.29477,0.41985,0.29951,0.45411,0.2868,0.45458,0.30408,0.44018,0.30514,0.44919,0.34649,0.53998,0.33144,0.544,0.34057,0.52219,0.34897,0.53302,0.31209,0.52303,0.32858,0.51834,0.36245,0.56118,0.34739,0.56566,0.3567,0.54363,0.36481,0.55414,0.37374,0.58088,0.36299,0.5883,0.37259,0.56376,0.37694,0.57269,0.30112,0.32998,0.29067,0.32752,0.30873,0.32031,0.30661,0.32695,0.28145,0.34859,0.28336,0.33439,0.29746,0.35149,0.28599,0.35401,0.30492,0.33537,0.30353,0.34518,0.27567,0.37507,0.27869,0.36228,0.29385,0.37456,0.28092,0.37868,0.30206,0.35624,0.30057,0.3676,0.27319,0.39365,0.27377,0.38554,0.2931,0.39087,0.27997,0.39508,0.29963,0.37751,0.2993,0.38558,0.29315,0.40483,0.27988,0.40889,0.29919,0.39276,0.29918,0.39974,0.29949,0.40691,0.30023,0.41454,0.24179,0.56573,0.24726,0.57465,0.2659,0.57132,0.25565,0.57625,0.24485,0.55818,0.25471,0.55309,0.23685,0.55608,0.23272,0.54596,0.18324,0.3308,0.18552,0.33719,0.18406,0.3271,0.18828,0.32444,0.19556,0.33762,0.18945,0.3398,0.29679,0.65382,0.29264,0.64413,0.29491,0.63876,0.305,0.63655,0.20742,0.46543,0.20955,0.47268,0.21158,0.46012,0.22082,0.45722,0.20515,0.45748,0.2027,0.44872,0.2833,0.62945,0.28812,0.63612,0.28597,0.62441,0.29635,0.62123,0.27598,0.61058,0.28641,0.60654,0.27833,0.62312,0.27326,0.61648,0.26257,0.60132,0.26796,0.60926,0.26565,0.59431,0.27615,0.58964,0.25745,0.59267,0.25252,0.58359,0.16556,0.42494,0.16619,0.4145,0.15466,0.41066,0.16094,0.4102,0.15843,0.42697,0.15146,0.42046,0.15775,0.43315,0.15076,0.43412,0.14362,0.41973,0.1474,0.41891,0.14665,0.43033,0.14318,0.42296,0.16116,0.43876,0.1576,0.44751,0.14824,0.44699,0.14837,0.43867,0.16861,0.4379,0.17393,0.44692,0.19381,0.49524,0.19092,0.48699,0.18262,0.5007,0.1799,0.49295,0.19152,0.50121,0.1861,0.50369,0.20068,0.49683,0.20465,0.50178,0.18539,0.52243,0.18603,0.51772,0.18493,0.50901,0.18695,0.51756,0.18868,0.50776,0.18152,0.50595,0.19845,0.51334,0.19628,0.50413,0.1692,0.35194,0.17218,0.34462,0.15817,0.34683,0.16217,0.34063,0.16317,0.35406,0.15809,0.35103,0.16579,0.33841,0.17036,0.34031,0.15314,0.35219,0.14797,0.3569,0.17125,0.35118,0.15338,0.34808,0.22942,0.37193,0.22018,0.36159,0.14369,0.35822,0.15919,0.36653,0.1673,0.36034,0.16731,0.36776,0.15477,0.36176,0.16173,0.35849,0.16215,0.37057,0.15618,0.3695,0.1622,0.38377,0.16578,0.37533,0.15504,0.38405,0.15052,0.37741,0.15242,0.38915,0.14429,0.38888,0.14256,0.37617,0.1471,0.37566,0.1405,0.38539,0.14006,0.379,0.15473,0.39456,0.14976,0.40127,0.13892,0.39858,0.1401,0.39211,0.16186,0.39557,0.16496,0.40518,0.20167,0.53141,0.20036,0.52231,0.19743,0.5368,0.19179,0.53704,0.1902,0.52114,0.19579,0.51935,0.18945,0.5336,0.18856,0.52586,0.21635,0.54598,0.21626,0.5403,0.18904,0.54072,0.18773,0.54698,0.19287,0.53766,0.18707,0.53746,0.20459,0.54076,0.20829,0.54833,0.19467,0.54803,0.19874,0.5417,0.16863,0.32168,0.17186,0.32322,0.27096,0.64967,0.27418,0.64658,0.17631,0.49103,0.18884,0.49988,0.24128,0.64312,0.24241,0.63987,0.2583,0.63966,0.25587,0.64447,0.21716,0.62272,0.23107,0.60609,0.22552,0.63386,0.24366,0.62105,0.30206,0.58691,0.27845,0.57977,0.14715,0.40622,0.1352,0.40124,0.14791,0.46286,0.15041,0.46177,0.15107,0.45327,0.14617,0.45092,0.18866,0.54957,0.19169,0.54986,0.20378,0.60316,0.20577,0.60195,0.14504,0.43469,0.15143,0.43127,0.18379,0.44289,0.17707,0.42956,0.18549,0.35641,0.16633,0.36145,0.16588,0.37353,0.14188,0.37738,0.13643,0.38857,0.15247,0.38349,0.21559,0.39457,0.20421,0.37904,0.20055,0.33964,0.20151,0.34684,0.19852,0.35251,0.19212,0.35471,0.20332,0.35551,0.20732,0.3654,0.20685,0.37326,0.20006,0.37747,0.21362,0.37516,0.22215,0.38305,0.21109,0.39667,0.20108,0.38561,0.22478,0.38981,0.21986,0.39762,0.25647,0.38506,0.26835,0.3824,0.24593,0.39941,0.24881,0.39101,0.23269,0.38695,0.24452,0.3869,0.2525,0.38045,0.2562,0.36803,0.26329,0.36,0.27452,0.35692,0.2298,0.38088,0.2351,0.37132,0.24075,0.36675,0.2516,0.36345,0.23164,0.35819,0.2356,0.36536,0.21409,0.36684,0.22383,0.35863,0.22537,0.34412,0.22798,0.35079,0.20666,0.349,0.218,0.34403,0.22498,0.33235,0.2244,0.33787,0.2463,0.32988,0.23182,0.3375,0.25416,0.32888,0.2566,0.33544,0.25053,0.34286,0.23632,0.35033,0.25819,0.34424,0.25827,0.35548,0.27683,0.32997,0.26412,0.33631,0.30608,0.4583,0.30572,0.46808,0.28438,0.5119,0.2982,0.52107,0.30851,0.4963,0.28721,0.50314,0.30735,0.47954,0.31408,0.48894,0.32215,0.49928,0.33143,0.51079,0.35286,0.51289,0.34247,0.51515,0.34745,0.49528,0.35405,0.50638,0.3259,0.49229,0.3389,0.49049,0.41769,0.47025,0.41356,0.4714,0.3403,0.46743,0.35048,0.46497,0.34162,0.48432,0.3368,0.47375,0.32087,0.36429,0.32096,0.35376,0.38973,0.35434,0.38583,0.35521,0.32531,0.348,0.33386,0.34606,0.32115,0.34409,0.32144,0.33591,0.32555,0.33174,0.33354,0.32989,0.42548,0.4873,0.42119,0.47554,0.41724,0.46437,0.4137,0.45404,0.3838,0.31247,0.3815,0.3063,0.37897,0.30347,0.37573,0.30442,0.37858,0.29976,0.37542,0.29248,0.32567,0.30383,0.33216,0.3018,0.3208,0.38267,0.32083,0.37413,0.39198,0.373,0.38795,0.3738,0.39287,0.3685,0.39174,0.35917,0.39042,0.34853,0.38887,0.33737,0.39441,0.38767,0.39025,0.38844,0.39524,0.38394,0.394,0.37666,0.32087,0.39729,0.32079,0.39024,0.32161,0.41167,0.32113,0.40437,0.39713,0.40096,0.39286,0.40179,0.39795,0.39742,0.39657,0.39078,0.32875,0.46985,0.3141,0.47249,0.32982,0.45408,0.33294,0.46371,0.31157,0.45294,0.32299,0.4506,0.405,0.43169,0.40067,0.43268,0.32879,0.42942,0.33872,0.42725,0.3271,0.44446,0.32477,0.43503,0.32315,0.42653,0.32223,0.41898,0.36198,0.51077,0.37097,0.50844,0.36736,0.52777,0.3608,0.51726,0.43509,0.51549,0.43173,0.51763,0.3793,0.54781,0.3736,0.53798,0.44118,0.52465,0.43722,0.516,0.32223,0.32246,0.32184,0.32892,0.31276,0.3185,0.31905,0.31912,0.31779,0.33244,0.30994,0.33175,0.32249,0.31547,0.32254,0.30803,0.38729,0.3274,0.38566,0.31926,0.30569,0.37163,0.31604,0.37006,0.31577,0.38702,0.30504,0.38816,0.31689,0.41604,0.30639,0.41754,0.30508,0.40228,0.31587,0.40122,0.4106,0.44459,0.40785,0.43572,0.37886,0.55411,0.37323,0.55757,0.3582,0.53682,0.36669,0.53412,0.40526,0.42689,0.40287,0.41822,0.43416,0.50943,0.42997,0.49908,0.40091,0.41054,0.39936,0.40387,0.31676,0.3492,0.30776,0.34997,0.30883,0.43457,0.31893,0.43194,0.125,0,0.375,0,0.5,0.125,0.5,0.375,0.375,0.5,0.125,0.5,0,0.375,0,0.125,0.625,0,0.875,0,1,0.125,1,0.375,0.875,0.5,0.625,0.5,0.875,1,0.625,1,0.5,0.875,0.5,0.625,1,0.625,1,0.875,0.375,1,0.125,1,0,0.875,0,0.625,0.0625,0,0.1875,0,0.24817,0.125,0.24542,0.375,0.18549,0.5,0.0625,0.5,0.3125,0,0.4375,0,0.47144,0.125,0.45056,0.375,0.40564,0.5,0.30243,0.5,0.4375,1,0.3125,1,0.24817,0.875,0.24542,0.625,0.45056,0.625,0.47144,0.875,0.1875,1,0.0625,1,0.875,0.75183,0.625,0.75458,0.5,0.69757,0.5,0.59436,0.625,0.54944,0.875,0.52856,0.5,0.9375,0.5,0.81451,0,0.9375,0,0.8125,0.125,0.75183,0.375,0.75458,0,0.6875,0,0.5625,0.125,0.52856,0.375,0.54944,1,0.5625,1,0.6875,0.875,0.75183,0.625,0.75458,0.5,0.69757,0.5,0.59436,0.625,0.54944,0.875,0.52856,1,0.8125,1,0.9375,0.5,0.9375,0.5,0.81451,0.125,0.75183,0.375,0.75458,0.125,0.52856,0.375,0.54944,0.75183,0.125,0.75458,0.375,0.69757,0.5,0.59436,0.5,0.54944,0.375,0.52856,0.125,0.9375,0.5,0.81451,0.5,0.75183,0.875,0.75458,0.625,0.52856,0.875,0.54944,0.625,0.51562,0,0.54688,0,0.52181,0.17773,0.50035,0.41193,0.51126,0.49951,0.48377,0.5,0.50952,0.82083,0.48776,0.58565,0.54688,1,0.51562,1,0.81361,0.47026,0.56714,0.48613,0.5,0.51623,0.48445,0.48078,0,0.48438,0,0.45312,0.13193,0.46987,0.3551,0.48592,0.80036,0.43677,0.54974,0.43761,1,0.45312,1,0.48438,0.5,0.51623,0.47788,0.46121,0.12215,0.43498,0.33963,0.43662,0.42361,0.17713,0.41644,0.41206,0.51623,0.5,0.45068,0.50047,0.41241,0.82421,0.40519,0.59026,0.19783,0.39376,0.34723,0.46507,0.28863,0.47447,0.38732,0.16324,0.32915,0.58732,0.42224,0.5118,0.47738,0.57936,0.81625,0.49273,0.34933,0.62354,0.46374,0.54068,0.26955,0.51889,0.46086,0.83273,0.25727,0.3731,0.38939,0.41396,0.3723,0.3887,0.78374,0.4172,0.26561,0.29768,0.17185,0.41675,0.34383,0.49153,0.40252,0.49647,0.36917,0.80288,0.45639,0.93429,0.29991,0.53591,0.23048,0.53715,0.11148,0.51554,0.16093,0.51499,0.68927,0.49862,0.89642,0.49954,0.28903,0.50257,0.21562,0.4917,0.30874,0.50601,0.23109,0.5078,0.30812,0.3009,0.30238,0.42623,0.30565,0.55098,0.31792,0.67517,0.40255,0.53532,0.52772,0.5297,0.15189,0.51996,0.27727,0.53207,0.39494,0.50844,0.52215,0.50255,0.13955,0.4943,0.26741,0.50569,0.35242,0.44414,0.34456,0.32297,0.34195,0.68727,0.35155,0.56557,0.625,0.125,0.875,0.125,1,0.17969,1,0.28906,0.125,0.125,0.375,0.125,0.625,0.125,0.875,0.125,1,0.17969,1,0.28906,0.125,0.375,0.125,0.125,0.125,0.875,0.125,0.625,0.125,0,0.375,0,0.5,0.125,0.5,0.375,0.375,0.5,0.125,0.5,0,0.375,0,0.125,0.625,0,0.875,0,1,0.125,1,0.375,0.875,0.5,0.625,0.5,0.875,1,0.625,1,0.5,0.875,0.5,0.625,1,0.625,1,0.875,0.375,1,0.125,1,0,0.875,0,0.625,0.0625,0,0.1875,0,0.24817,0.125,0.24542,0.375,0.18549,0.5,0.0625,0.5,0.3125,0,0.4375,0,0.47144,0.125,0.45056,0.375,0.40564,0.5,0.30243,0.5,0.4375,1,0.3125,1,0.24817,0.875,0.24542,0.625,0.45056,0.625,0.47144,0.875,0.1875,1,0.0625,1,0.875,0.75183,0.625,0.75458,0.5,0.69757,0.5,0.59436,0.625,0.54944,0.875,0.52856,0.5,0.9375,0.5,0.81451,0,0.9375,0,0.8125,0.125,0.75183,0.375,0.75458,0,0.6875,0,0.5625,0.125,0.52856,0.375,0.54944,1,0.5625,1,0.6875,0.875,0.75183,0.625,0.75458,0.5,0.69757,0.5,0.59436,0.625,0.54944,0.875,0.52856,1,0.8125,1,0.9375,0.5,0.9375,0.5,0.81451,0.125,0.75183,0.375,0.75458,0.125,0.52856,0.375,0.54944,0.75183,0.125,0.75458,0.375,0.69757,0.5,0.59436,0.5,0.54944,0.375,0.52856,0.125,0.9375,0.5,0.81451,0.5,0.75183,0.875,0.75458,0.625,0.52856,0.875,0.54944,0.625,0.51562,0,0.54688,0,0.56067,0.125,0.55792,0.375,0.5368,0.5,0.48377,0.5,0.57812,0,0.60938,0,0.61987,0.125,0.61768,0.375,0.60645,0.5,0.57611,0.5,0.60938,1,0.57812,1,0.56067,0.875,0.55792,0.625,0.61768,0.625,0.61987,0.875,0.54688,1,0.51562,1,0.875,0.38013,0.625,0.38232,0.5,0.37402,0.5,0.36328,0,0.37109,0,0.36328,0.375,0.38232,0.125,0.38013,0.875,0.38013,0.625,0.38232,0.5,0.37402,0.5,0.36328,0,0.37109,0,0.36328,0.375,0.38232,0.125,0.38013,0.38013,0.125,0.38232,0.375,0.37402,0.5,0.36328,0.5,0.38232,0.625,0.38013,0.875,0.875,0.125,0.875,0.375,0.82031,0.5,0.72363,0.5,0.875,0.625,0.875,0.875,0.875,0.43933,0.625,0.44208,0.5,0.42389,0.5,0.39355,0.5,0.51623,0.5,0.4632,0,0.48438,0,0.45312,0.125,0.43933,0.375,0.44208,0,0.42188,0,0.39062,1,0.39062,1,0.42188,0.875,0.43933,0.625,0.44208,0.5,0.42389,0.5,0.39355,1,0.45312,1,0.48438,0.5,0.51623,0.5,0.4632,0.125,0.43933,0.375,0.44208,0.43933,0.125,0.44208,0.375,0.42389,0.5,0.39355,0.5,0.51623,0.5,0.4632,0.5,0.43933,0.875,0.44208,0.625,1,0.34766,1,0.35547,0.5,0.27637,0.5,0.17969,0,0.28906,0,0.17969,1,0.34766,1,0.35547,0.5,0.27637,0.5,0.17969,0,0.28906,0,0.17969,0.27637,0.5,0.17969,0.5,0.66504,0.5,0.64453,0.5,0.875,0.32153,0.625,0.31201,0.125,0.32153,0.375,0.31201,0.875,0.32153,0.625,0.31201,0.125,0.32153,0.375,0.31201,0.32153,0.125,0.31201,0.375,0.32153,0.875,0.31201,0.625,0.67847,0.125,0.68799,0.375,0.67847,0.875,0.68799,0.625,0.5,0.35547,0.5,0.33496,0,0.35547,0,0.34766,0.5,0.35547,0.5,0.33496,0,0.35547,0,0.34766,0.35547,0.5,0.33496,0.5,1,0.36328,1,0.37109,1,0.36328,1,0.37109,0.63672,0.5,0.62598,0.5,0.125,0.35938,0.375,0.35938,0.125,0.35938,0.375,0.35938,0.35938,0.875,0.35938,0.625,0.64062,0.125,0.64062,0.375,0.875,0.35938,0.625,0.35938,0.875,0.35938,0.625,0.35938,0.35938,0.125,0.35938,0.375,0.64062,0.875,0.64062,0.625,0.125,0,0.375,0,0.5,0.125,0.5,0.375,0.375,0.5,0.125,0.5,0,0.375,0,0.125,0.625,0,0.875,0,1,0.125,1,0.375,0.875,0.5,0.625,0.5,0.875,1,0.625,1,0.5,0.875,0.5,0.625,1,0.625,1,0.875,0.375,1,0.125,1,0,0.875,0,0.625,0.0625,0,0.1875,0,0.24817,0.125,0.24542,0.375,0.18549,0.5,0.0625,0.5,0.3125,0,0.4375,0,0.47144,0.125,0.45056,0.375,0.40564,0.5,0.30243,0.5,0.4375,1,0.3125,1,0.24817,0.875,0.24542,0.625,0.45056,0.625,0.47144,0.875,0.1875,1,0.0625,1,0.875,0.75183,0.625,0.75458,0.5,0.69757,0.5,0.59436,0.625,0.54944,0.875,0.52856,0.5,0.9375,0.5,0.81451,0,0.9375,0,0.8125,0.125,0.75183,0.375,0.75458,0,0.6875,0,0.5625,0.125,0.52856,0.375,0.54944,1,0.5625,1,0.6875,0.875,0.75183,0.625,0.75458,0.5,0.69757,0.5,0.59436,0.625,0.54944,0.875,0.52856,1,0.8125,1,0.9375,0.5,0.9375,0.5,0.81451,0.125,0.75183,0.375,0.75458,0.125,0.52856,0.375,0.54944,0.75183,0.125,0.75458,0.375,0.69757,0.5,0.59436,0.5,0.54944,0.375,0.52856,0.125,0.9375,0.5,0.81451,0.5,0.75183,0.875,0.75458,0.625,0.52856,0.875,0.54944,0.625,0.51562,0,0.54688,0,0.56067,0.125,0.55792,0.375,0.5368,0.5,0.48377,0.5,0.57812,0,0.60938,0,0.61987,0.125,0.61768,0.375,0.60645,0.5,0.57611,0.5,0.60938,1,0.57812,1,0.56067,0.875,0.55792,0.625,0.61768,0.625,0.61987,0.875,0.54688,1,0.51562,1,0.56055,0.36462,0.80887,0.34938,1,0.31641,1,0.32422,0.875,0.38013,0.625,0.38232,0.5,0.37402,0.5,0.36328,0,0.37109,0,0.36328,0.12775,0.34798,0.34882,0.36385,0.375,0.38232,0.125,0.38013,0.54656,0.32723,0.79856,0.32337,1,0.31641,1,0.32422,0.875,0.38013,0.625,0.38232,0.5,0.37402,0.5,0.36328,0,0.37109,0,0.36328,0.11915,0.32155,0.33578,0.32622,0.375,0.38232,0.125,0.38013,0.29391,0.40798,0.30126,0.173,0.38013,0.125,0.38232,0.375,0.37402,0.5,0.36328,0.5,0.2931,0.82935,0.28607,0.59583,0.38232,0.625,0.38013,0.875,0.63477,0.17579,0.60988,0.41105,0.65041,0.5005,0.67578,0.5,0.59919,0.59144,0.62423,0.82576,0.875,0.43933,0.625,0.44208,0.5,0.42389,0.5,0.39355,0.5,0.51623,0.5,0.4632,0,0.48438,0,0.45312,0.125,0.43933,0.375,0.44208,0,0.42188,0,0.39062,1,0.39062,1,0.42188,0.875,0.43933,0.625,0.44208,0.5,0.42389,0.5,0.39355,1,0.45312,1,0.48438,0.5,0.51623,0.5,0.4632,0.125,0.43933,0.375,0.44208,0.43933,0.125,0.44208,0.375,0.42389,0.5,0.39355,0.5,0.51623,0.5,0.4632,0.5,0.43933,0.875,0.44208,0.625,1,0.34766,1,0.35547,0.5,0.33984,0.5,0.33203,0,0.33984,0,0.33203,1,0.34766,1,0.35547,0.5,0.33984,0.5,0.33203,0,0.33984,0,0.33203,0.33984,0.5,0.33203,0.5,0.65234,0.5,0.64453,0.5,0.875,0.34375,0.625,0.34375,0.125,0.34375,0.375,0.34375,0.875,0.34375,0.625,0.34375,0.125,0.34375,0.375,0.34375,0.34375,0.125,0.34375,0.375,0.34375,0.875,0.34375,0.625,0.65625,0.125,0.65625,0.375,0.65625,0.875,0.65625,0.625,0.5,0.35547,0.5,0.34766,0,0.35547,0,0.34766,0.5,0.35547,0.5,0.34766,0,0.35547,0,0.34766,0.35547,0.5,0.34766,0.5,1,0.36328,1,0.37109,1,0.36328,1,0.37109,0.63672,0.5,0.62598,0.5,0.125,0.35938,0.375,0.35938,0.125,0.35938,0.375,0.35938,0.35938,0.875,0.35938,0.625,0.64062,0.125,0.64062,0.375,0.875,0.35938,0.625,0.35938,0.875,0.35938,0.625,0.35938,0.35938,0.125,0.35938,0.375,0.64062,0.875,0.64062,0.625,1,0.33203,1,0.33984,1,0.33203,1,0.33984,0.66797,0.5,0.66016,0.5,0.5,0.32422,0.48187,0.3371,0,0.32422,0,0.31641,0.5,0.32422,0.47646,0.3221,0,0.32422,0,0.31641,0.32422,0.5,0.30739,0.50077,0.875,0.32812,0.625,0.32812,0.875,0.32812,0.625,0.32812,0.32812,0.125,0.32812,0.375,0.67188,0.875,0.67188,0.625,0.125,0.32812,0.375,0.32812,0.125,0.32812,0.375,0.32812,0.32812,0.875,0.32812,0.625,0.67188,0.125,0.67188,0.375,0.2422,0.36441,0.38232,0.33705,0.36135,0.38677,0.78056,0.33461,0.16412,0.43222,0.25398,0.47819,0.2291,0.44678,0.28448,0.15432,0.30117,0.52899,0.40935,0.41209,0.43832,0.53956,0.80521,0.39368,0.33782,0.61496,0.53775,0.53883,0.27835,0.53977,0.54718,0.84375,0.2908,0.93156,0.2474,0.79469,0.44321,0.33268,0.3637,0.35858,0.016608,0.3258,0.049823,0.3524,0.59876,0.48934,0.47416,0.46696,0.62556,0.074815,0.50169,0.22445,0.45086,0.356,0.38206,0.41454,0.022581,0.34466,0.067744,0.40898,0.28432,0.494,0.24252,0.4856,0.20401,0.65782,0.16981,0.52381,0.27283,0.38931,0.19403,0.41613,0.083038,0.37899,0.12168,0.40913,0.33194,0.44493,0.18971,0.4229,0.37782,0.37407,0.26579,0.51632,0.30343,0.48257,0.2353,0.54187,0.11291,0.47331,0.15807,0.53763,0.19587,0.476,0.15575,0.46802,0.38112,0.37606,0.5067,0.38035,0.12943,0.36774,0.25536,0.37186,0.40483,0.51932,0.4084,0.64607,0.439,0.36355,0.43749,0.49213,0.40599,0.45033,0.53264,0.4538,0.15338,0.44303,0.27957,0.44674,0.21819,0.41972,0.21682,0.29785,0.22387,0.6648,0.22054,0.54203,0.3782,0.4812,0.36877,0.48381,0.37962,0.45752,0.38872,0.45519,0.3524,0.36272,0.34348,0.36472,0.3595,0.33947,0.36751,0.33741,0.35777,0.32319,0.36534,0.3211,0.34795,0.31256,0.34055,0.31473,0.35161,0.29569,0.3581,0.29365,0.35343,0.38063,0.34423,0.38245,0.35459,0.39506,0.34508,0.39683,0.35623,0.40893,0.34646,0.41083,0.36356,0.44118,0.35366,0.44345,0.36856,0.42108,0.37789,0.41915,0.3978,0.50124,0.40619,0.499,0.39986,0.52544,0.39136,0.52753,0.37658,0.4638,0.38065,0.47439,0.35564,0.34566,0.35647,0.35644,0.35412,0.32786,0.35485,0.33593,0.34925,0.30055,0.35092,0.30799,0.35719,0.36667,0.35776,0.37565,0.35897,0.39071,0.35832,0.38355,0.36064,0.40457,0.35975,0.39766,0.3646,0.42631,0.36711,0.43538,0.36159,0.41133,0.36278,0.41829,0.40146,0.51899,0.39606,0.50802,0.41174,0.54039,0.40669,0.52976,0.36995,0.44465,0.37306,0.45393,0.39061,0.4968,0.38536,0.48549,0.35229,0.31473,0.35331,0.32102,0.39647,0.47614,0.38763,0.47859,0.36967,0.35884,0.36131,0.36072,0.3623,0.30836,0.35536,0.31039,0.37127,0.3771,0.36264,0.37881,0.37301,0.39164,0.3641,0.3933,0.37515,0.40524,0.36599,0.40703,0.38273,0.43679,0.37346,0.43891,0.41633,0.52141,0.40836,0.52336,0.39601,0.45332,0.40147,0.45193,0.37392,0.33576,0.37873,0.33453,0.3714,0.31942,0.37594,0.31817,0.36296,0.29212,0.3662,0.29111,0.38535,0.41761,0.39094,0.41645,0.41289,0.4972,0.41792,0.49585,0.37637,0.38746,0.37544,0.38024,0.37854,0.40114,0.37741,0.39436,0.41732,0.51499,0.41232,0.50373,0.42728,0.53702,0.42218,0.52609,0.40734,0.49224,0.40255,0.48072,0.39439,0.45912,0.3982,0.46958,0.37158,0.34168,0.37276,0.35264,0.36925,0.32373,0.37041,0.33184,0.36196,0.29663,0.36419,0.30404,0.37376,0.36307,0.3746,0.37222,0.38296,0.42243,0.38541,0.43131,0.37971,0.40775,0.38107,0.41457,0.38813,0.44037,0.39107,0.44945,0.3663,0.31068,0.36793,0.31692,0.42198,0.46964,0.41859,0.46085,0.4155,0.45248,0.41275,0.44482,0.41037,0.43786,0.40846,0.4319,0.40693,0.42666,0.40465,0.4184,0.40348,0.41385,0.40265,0.40991,0.40193,0.40596,0.40129,0.40198,0.40076,0.39796,0.40036,0.39365,0.40008,0.3886,0.39911,0.38009,0.39584,0.36311,0.39093,0.34071,0.38736,0.32398,0.38587,0.31629,0.38474,0.31226,0.38239,0.30596,0.38061,0.30208,0.38195,0.31078,0.39666,0.36602,0.41538,0.43477,0.42572,0.47467,0.42556,0.47833,0.42855,0.493,0.4291,0.49285,0.42005,0.4696,0.42064,0.46944,0.41301,0.44898,0.41362,0.44882,0.40747,0.43112,0.40809,0.43098,0.40275,0.41401,0.40338,0.41388,0.39957,0.40048,0.40018,0.40037,0.39678,0.38722,0.39738,0.38711,0.39428,0.37255,0.39486,0.37243,0.39196,0.35384,0.39251,0.35371,0.38888,0.33192,0.38941,0.33178,0.38553,0.31552,0.38603,0.31538,0.38082,0.30293,0.38128,0.3028,0.37431,0.28856,0.37431,0.28856,0.4358,0.51008,0.43385,0.50139,0.38817,0.33011,0.38747,0.33079,0.40322,0.39222,0.41642,0.43965,0.40556,0.41006,0.4184,0.45522,0.41337,0.44371,0.40465,0.41284,0.40942,0.43368,0.40438,0.41551,0.4291,0.49285,0.42696,0.48532,0.42064,0.46944,0.41918,0.46429,0.41362,0.44882,0.41278,0.44579,0.40809,0.43098,0.40796,0.43039,0.40338,0.41388,0.40362,0.41467,0.40018,0.40037,0.40102,0.40339,0.39738,0.38711,0.39883,0.39226,0.39486,0.37243,0.397,0.37996,0.39251,0.35371,0.39465,0.36141,0.38941,0.33178,0.38916,0.33145,0.38603,0.31538,0.38578,0.31502,0.38128,0.3028,0.38135,0.3032,0.37431,0.28856,0.38,0.30743,0.43102,0.49161,0.4264,0.47535,0.42265,0.47514,0.4269,0.48692,0.41521,0.45365,0.41873,0.46396,0.40939,0.43536,0.41213,0.44421,0.40443,0.41789,0.40681,0.42654,0.4009,0.40356,0.40246,0.41022,0.39806,0.3905,0.39947,0.39713,0.39545,0.37638,0.39671,0.38367,0.39315,0.35887,0.39429,0.36821,0.39022,0.33703,0.3918,0.34821,0.38695,0.31891,0.38861,0.32705,0.38268,0.30595,0.38504,0.31212,0.37617,0.29225,0.3797,0.29942,0.42898,0.48268,0.41746,0.43935,0.43135,0.49872,0.4336,0.50249,0.40885,0.4727,0.40354,0.47418,0.38137,0.35622,0.37636,0.35734,0.37202,0.30551,0.36786,0.30673,0.38335,0.37471,0.37817,0.37573,0.38549,0.38932,0.38014,0.39032,0.38797,0.40274,0.38248,0.40381,0.39572,0.43381,0.39016,0.43509,0.42748,0.51867,0.4227,0.51984,0.40633,0.45068,0.41058,0.4496,0.383,0.33343,0.38674,0.33247,0.37998,0.31705,0.38351,0.31607,0.36945,0.29009,0.37269,0.28907,0.39592,0.41542,0.40027,0.41452,0.4224,0.49465,0.42631,0.4936,0.38728,0.38543,0.38617,0.37817,0.38976,0.39899,0.38848,0.39229,0.42726,0.51248,0.42252,0.50104,0.43641,0.53504,0.4319,0.52379,0.41782,0.48939,0.41332,0.47773,0.40555,0.45619,0.40921,0.46657,0.38158,0.33919,0.38297,0.35027,0.37874,0.32115,0.38017,0.32927,0.36944,0.29433,0.37251,0.30157,0.38416,0.36082,0.38516,0.37007,0.39447,0.41999,0.39689,0.42875,0.39107,0.4055,0.39254,0.41224,0.39953,0.43768,0.40236,0.44664,0.37509,0.30815,0.3771,0.31435,0.36019,0.46248,0.3699,0.46,0.34241,0.34386,0.35095,0.34166,0.34162,0.32766,0.34969,0.32543,0.33864,0.29976,0.34513,0.29772,0.34866,0.42519,0.35861,0.42314,0.37991,0.50604,0.38886,0.50364,0.35934,0.48643,0.34959,0.48881,0.33457,0.36673,0.32551,0.3686,0.33314,0.3169,0.32588,0.31865,0.33502,0.38427,0.32565,0.38592,0.33557,0.39859,0.32593,0.40018,0.33669,0.41274,0.32687,0.41454,0.34377,0.44571,0.33367,0.44805,0.38287,0.52961,0.37453,0.53176,0.35727,0.46887,0.36161,0.47961,0.33834,0.34997,0.33881,0.36055,0.3377,0.33233,0.33797,0.34037,0.3358,0.30469,0.33653,0.31227,0.3392,0.37057,0.33949,0.37937,0.34469,0.43051,0.34725,0.43981,0.34194,0.41521,0.34294,0.42231,0.35024,0.44929,0.35353,0.4588,0.33709,0.31912,0.33744,0.32547,0.3401,0.39423,0.33976,0.38713,0.34122,0.4083,0.34059,0.40123,0.38427,0.52333,0.37841,0.51267,0.39529,0.54395,0.38989,0.53374,0.37246,0.50175,0.36672,0.49066,0.375,1,0.125,1,1,0.125,1,0.375,0.875,1,0.625,1,0,0.375,0,0.125,0.375,1,0.125,1,0,0.875,0,0.625,0.875,1,0.625,1,1,0.625,1,0.875,1,0.8125,1,0.9375,1,0.5625,1,0.6875,0,0.6875,0,0.5625,0,0.9375,0,0.8125,0.8125,0,0.9375,0,0.5625,0,0.6875,0,0.6875,1,0.5625,1,0.9375,1,0.8125,1,1,0.45312,1,0.48438,1,0.39062,1,0.42188,0,0.42188,0,0.39062,0,0.48438,0,0.45312,0.67578,0,0.68359,0,0.36328,0,0.37109,0,0.32422,1,0.31641,1,0.63672,1,0.62891,1,0.45312,0,0.48438,0,0.39062,0,0.42188,0,0.42188,1,0.39062,1,0.48438,1,0.45312,1,0.64453,0,0.65234,0,0.33203,0,0.33984,0,0.35547,1,0.34766,1,0.66797,1,0.66016,1,0.34766,0,0.35547,0,0.65234,1,0.64453,1,0.62891,0,0.63672,0,0.37109,1,0.36328,1,0.66016,0,0.66797,0,0.33984,1,0.33203,1,0.31641,0,0.32422,0,0.68359,1,0.67578,1,0.375,1,0.125,1,1,0.125,1,0.375,0.875,1,0.625,1,0,0.375,0,0.125,0.375,1,0.125,1,0,0.875,0,0.625,0.875,1,0.625,1,1,0.625,1,0.875,1,0.8125,1,0.9375,1,0.5625,1,0.6875,0,0.6875,0,0.5625,0,0.9375,0,0.8125,0.8125,0,0.9375,0,0.5625,0,0.6875,0,0.6875,1,0.5625,1,0.9375,1,0.8125,1,0.69271,0.51906,0.89757,0.50635,0.09445,0.48396,0.13537,0.4818,0.37938,0.19682,0.4598,0.065608,0.29462,0.68521,0.22894,0.56504,0.28207,0.66173,0.27953,0.66372,0.29616,0.65947,0.29121,0.65958,0.35604,0.59708,0.35289,0.60719,0.35112,0.61621,0.35071,0.62411,0.12509,0.47589,0.12533,0.47508,0.22431,0.65137,0.22228,0.65264,0.22234,0.65707,0.22434,0.65284,0.18972,0.61155,0.18723,0.61242,0.18483,0.61606,0.18893,0.61276,0.18161,0.5668,0.18355,0.56082,0.125,0.125,0.375,0.125,0.29976,0.3053,0.30659,0.31413,0.31016,0.31421,0.31047,0.30551,0.30754,0.65468,0.30161,0.65783,0.28738,0.65991,0.28468,0.66046,0.39389,0.54987,0.38575,0.55154,0.31358,0.30209,0.31948,0.30393,0.375,1,0.125,1,1,0.125,1,0.375,0.875,1,0.625,1,0,0.375,0,0.125,0.375,1,0.125,1,0,0.875,0,0.625,0.875,1,0.625,1,1,0.625,1,0.875,1,0.8125,1,0.9375,1,0.5625,1,0.6875,0,0.6875,0,0.5625,0,0.9375,0,0.8125,0.8125,0,0.9375,0,0.5625,0,0.6875,0,0.6875,1,0.5625,1,0.9375,1,0.8125,1,1,0.45312,1,0.48438,0,0.48438,0,0.45312,0.45312,0,0.48438,0,0.48438,1,0.45312,1,0.37308,0.54028,0.27539,0.61938,0.059193,0.49136,0.17926,0.58384,0.48812,0.16461,0.368,0.46998,0.43413,0.45387,0.2605,0.3631,0.038985,0.41085,0.12893,0.37826,0.36186,0.83908,0.23167,0.52932,0.283,0.54448,0.48786,0.53177,0.01889,0.49679,0.05667,0.49038,0.22343,0.45249,0.29897,0.32804,0.45892,0.93704,0.37677,0.81112,0.26208,0.29522,0.26599,0.28681,0.71094,0,0.82031,0,0.20575,0.33489,0.21903,0.332,0.19257,0.32643,0.19693,0.33304,0.28906,1,0.17969,1,0.32525,0.63087,0.31581,0.63384,0.31095,0.63977,0.31066,0.64867,0.375,1,0.125,1,1,0.125,1,0.375,0.875,1,0.625,1,0,0.375,0,0.125,0.375,1,0.125,1,0,0.875,0,0.625,0.875,1,0.625,1,1,0.625,1,0.875,1,0.8125,1,0.9375,1,0.5625,1,0.6875,0,0.6875,0,0.5625,0,0.9375,0,0.8125,0.8125,0,0.9375,0,0.5625,0,0.6875,0,0.6875,1,0.5625,1,0.9375,1,0.8125,1,1,0.45312,1,0.48438,1,0.39062,1,0.42188,0,0.42188,0,0.39062,0,0.48438,0,0.45312,0.36328,0,0.37109,0,0.63672,1,0.62891,1,0.25276,0.31025,0.25767,0.30303,0.23183,0.32638,0.24415,0.31804,0.45312,0,0.48438,0,0.39062,0,0.42188,0,0.42188,1,0.39062,1,0.48438,1,0.45312,1,0.64453,0,0.65234,0,0.17969,0,0.28906,0,0.35547,1,0.34766,1,0.82031,1,0.71094,1,0.34766,0,0.35547,0,0.65234,1,0.64453,1,0.62891,0,0.63672,0,0.37109,1,0.36328,1,0.375,1,0.125,1,1,0.125,1,0.375,0.875,1,0.625,1,0,0.375,0,0.125,0.375,1,0.125,1,0,0.875,0,0.625,0.875,1,0.625,1,1,0.625,1,0.875,1,0.8125,1,0.9375,1,0.5625,1,0.6875,0,0.6875,0,0.5625,0,0.9375,0,0.8125,0.8125,0,0.9375,0,0.5625,0,0.6875,0,0.6875,1,0.5625,1,0.9375,1,0.8125,1,1,0.45312,1,0.48438,1,0.39062,1,0.42188,0,0.42188,0,0.39062,0,0.48438,0,0.45312,0.67578,0,0.68359,0,0.36328,0,0.37109,0,0.32422,1,0.31641,1,0.63672,1,0.62891,1,0.45312,0,0.48438,0,0.39062,0,0.42188,0,0.42188,1,0.39062,1,0.48438,1,0.45312,1,0.64453,0,0.65234,0,0.33203,0,0.33984,0,0.35547,1,0.34766,1,0.66797,1,0.66016,1,0.34766,0,0.35547,0,0.65234,1,0.64453,1,0.62891,0,0.63672,0,0.37109,1,0.36328,1,0.66016,0,0.66797,0,0.33984,1,0.33203,1,0.31641,0,0.32422,0,0.68359,1,0.67578,1,0.26494,0.85023,0.18947,0.55865,0.27101,0.53021,0.21522,0.58828,0.050105,0.3887,0.15097,0.52491,0.57083,0.1593,0.36019,0.46144,0.51287,0.46662,0.26318,0.39833,0.031558,0.32812,0.10647,0.3679,0.67709,0.365,0.89236,0.33,0.47951,0.78208,0.61817,0.92736,0.49943,0.54232,0.60719,0.51446,0.697,0.41976,0.899,0.34825,0.24035,0.17775,0.28845,0.059249,0.25574,0.43787,0.46182,0.40001,0.20761,0.49507,0.34085,0.63681,0.24867,0.59874,0.37405,0.57053,0.30485,0.55538,0.49501,0.49126,0.14415,0.41474,0.19225,0.29624,0.42644,0.54316,0.4183,0.54484,0.43661,0.54107,0.43254,0.5419,0.4196,0.44507,0.43772,0.50767,0.38906,0.33873,0.40149,0.38246,0.44475,0.53939,0.44068,0.54023,0.41016,0.54651,0.40202,0.54819,0.25,0.125,0.375,0.25,0.25,0.375,0.125,0.25,0.75,0.125,0.875,0.25,0.75,0.375,0.625,0.25,0.75,0.875,0.625,0.75,0.75,0.625,0.875,0.75,0.25,0.875,0.125,0.75,0.25,0.625,0.375,0.75,0.12482,0.125,0.18613,0.25,0.12454,0.375,0.0625,0.25,0.36786,0.125,0.41351,0.25,0.35788,0.375,0.30563,0.25,0.36786,0.875,0.30563,0.75,0.35788,0.625,0.41351,0.75,0.12482,0.875,0.0625,0.75,0.12454,0.625,0.18613,0.75,0.875,0.63214,0.75,0.69437,0.625,0.64212,0.75,0.58649,0.875,0.87518,0.75,0.9375,0.625,0.87546,0.75,0.81387,0.125,0.87518,0.25,0.81387,0.375,0.87546,0.25,0.9375,0.125,0.63214,0.25,0.58649,0.375,0.64212,0.25,0.69437,0.875,0.63214,0.75,0.69437,0.625,0.64212,0.75,0.58649,0.875,0.87518,0.75,0.9375,0.625,0.87546,0.75,0.81387,0.125,0.87518,0.25,0.81387,0.375,0.87546,0.25,0.9375,0.125,0.63214,0.25,0.58649,0.375,0.64212,0.25,0.69437,0.63214,0.125,0.69437,0.25,0.64212,0.375,0.58649,0.25,0.87518,0.125,0.9375,0.25,0.87546,0.375,0.81387,0.25,0.87518,0.875,0.81387,0.75,0.87546,0.625,0.9375,0.75,0.63214,0.875,0.58649,0.75,0.64212,0.625,0.69437,0.75,0.52411,0.125,0.54001,0.25,0.51413,0.375,0.49164,0.25,0.5932,0.125,0.60681,0.25,0.59256,0.375,0.57675,0.25,0.5932,0.875,0.57675,0.75,0.59256,0.625,0.60681,0.75,0.52411,0.875,0.49164,0.75,0.51413,0.625,0.54001,0.75,0.87281,0.32153,0.75,0.32422,0.62158,0.32271,0.73561,0.32487,0.125,0.36755,0.25,0.36328,0.375,0.36792,0.25,0.37366,0.87261,0.32095,0.75,0.32422,0.62119,0.32155,0.73423,0.32082,0.125,0.36755,0.25,0.36328,0.375,0.36792,0.25,0.37366,0.31969,0.12585,0.32422,0.25,0.31908,0.3757,0.31207,0.25494,0.36755,0.875,0.36328,0.75,0.36792,0.625,0.37366,0.75,0.63245,0.125,0.63672,0.25,0.63208,0.375,0.62634,0.25,0.67737,0.87369,0.67578,0.75,0.67517,0.62374,0.66749,0.7422,0.875,0.4068,0.75,0.42325,0.625,0.40744,0.75,0.39319,0.875,0.47589,0.75,0.50836,0.625,0.48587,0.75,0.45999,0.125,0.47589,0.25,0.45999,0.375,0.48587,0.25,0.50836,0.125,0.4068,0.25,0.39319,0.375,0.40744,0.25,0.42325,0.875,0.4068,0.75,0.42325,0.625,0.40744,0.75,0.39319,0.875,0.47589,0.75,0.50836,0.625,0.48587,0.75,0.45999,0.125,0.47589,0.25,0.45999,0.375,0.48587,0.25,0.50836,0.125,0.4068,0.25,0.39319,0.375,0.40744,0.25,0.42325,0.4068,0.125,0.42325,0.25,0.40744,0.375,0.39319,0.25,0.47589,0.125,0.50836,0.25,0.48587,0.375,0.45999,0.25,0.47589,0.875,0.45999,0.75,0.48587,0.625,0.50836,0.75,0.4068,0.875,0.39319,0.75,0.40744,0.625,0.42325,0.75,0.875,0.35156,0.75,0.35547,0.625,0.35156,0.75,0.34766,0.125,0.33594,0.25,0.33203,0.375,0.33594,0.25,0.33984,0.875,0.35156,0.75,0.35547,0.625,0.35156,0.75,0.34766,0.125,0.33594,0.25,0.33203,0.375,0.33594,0.25,0.33984,0.35156,0.125,0.35547,0.25,0.35156,0.375,0.34766,0.25,0.33594,0.875,0.33203,0.75,0.33594,0.625,0.33984,0.75,0.66406,0.125,0.66797,0.25,0.66406,0.375,0.66016,0.25,0.64844,0.875,0.64453,0.75,0.64844,0.625,0.65234,0.75,0.125,0.35156,0.25,0.34766,0.375,0.35156,0.25,0.35547,0.125,0.35156,0.25,0.34766,0.375,0.35156,0.25,0.35547,0.35156,0.875,0.34766,0.75,0.35156,0.625,0.35547,0.75,0.64844,0.125,0.65234,0.25,0.64844,0.375,0.64453,0.25,0.875,0.36755,0.75,0.37366,0.625,0.36792,0.75,0.36328,0.875,0.36755,0.75,0.37366,0.625,0.36792,0.75,0.36328,0.36755,0.125,0.37366,0.25,0.36792,0.375,0.36328,0.25,0.63245,0.875,0.62634,0.75,0.63208,0.625,0.63672,0.75,0.875,0.33594,0.75,0.33984,0.625,0.33594,0.75,0.33203,0.875,0.33594,0.75,0.33984,0.625,0.33594,0.75,0.33203,0.33594,0.125,0.33984,0.25,0.33594,0.375,0.33203,0.25,0.66406,0.875,0.66016,0.75,0.66406,0.625,0.66797,0.75,0.12474,0.32147,0.2472,0.32453,0.37351,0.32265,0.25,0.32422,0.12455,0.32088,0.24588,0.32043,0.37313,0.32148,0.25,0.32422,0.31973,0.87385,0.31229,0.74298,0.31912,0.6237,0.32422,0.75,0.67762,0.12639,0.66897,0.25838,0.67541,0.37643,0.67578,0.25,0.25,0.125,0.375,0.25,0.25,0.375,0.125,0.25,0.75,0.125,0.875,0.25,0.75,0.375,0.625,0.25,0.75,0.875,0.625,0.75,0.75,0.625,0.875,0.75,0.25,0.875,0.125,0.75,0.25,0.625,0.375,0.75,0.12482,0.125,0.18613,0.25,0.12454,0.375,0.0625,0.25,0.36584,0.12589,0.39934,0.25524,0.35381,0.3758,0.30563,0.25,0.36589,0.87393,0.30563,0.75,0.35387,0.62384,0.39965,0.7435,0.12482,0.875,0.0625,0.75,0.12454,0.625,0.18613,0.75,0.87277,0.63289,0.75,0.69437,0.62152,0.64365,0.7354,0.59178,0.875,0.87518,0.75,0.9375,0.625,0.87546,0.75,0.81387,0.125,0.87518,0.25,0.81387,0.375,0.87546,0.25,0.9375,0.12472,0.63284,0.24709,0.59148,0.37347,0.6436,0.25,0.69437,0.87272,0.63268,0.75,0.69437,0.6214,0.64323,0.73502,0.59031,0.875,0.87518,0.75,0.9375,0.625,0.87546,0.75,0.81387,0.125,0.87518,0.25,0.81387,0.375,0.87546,0.25,0.9375,0.12464,0.63264,0.2465,0.59005,0.37332,0.64319,0.25,0.69437,0.63146,0.12604,0.69437,0.25,0.64079,0.37608,0.58174,0.25629,0.87518,0.125,0.9375,0.25,0.87546,0.375,0.81387,0.25,0.87518,0.875,0.81387,0.75,0.87546,0.625,0.9375,0.75,0.63144,0.87403,0.58166,0.74424,0.64078,0.62407,0.69437,0.75,0.39508,0.21384,0.34788,0.33521,0.38046,0.40141,0.41297,0.28364,0.41491,0.70928,0.38215,0.58684,0.35278,0.64734,0.40003,0.77402,0.66418,0.5376,0.5103,0.53585,0.53636,0.53043,0.69913,0.52256,0.13817,0.51764,0.22344,0.52556,0.32461,0.53418,0.23824,0.53567,0.66217,0.52936,0.50638,0.52199,0.53143,0.51015,0.6963,0.50877,0.13191,0.50461,0.21513,0.50603,0.31952,0.52057,0.23488,0.52773,0.48154,0.28968,0.44154,0.41065,0.39241,0.35015,0.42856,0.22503,0.42723,0.78017,0.3911,0.6573,0.44109,0.59436,0.48102,0.71334,0.25769,0.41831,0.26574,0.42,0.25861,0.4255,0.2504,0.4237,0.25765,0.41127,0.25045,0.40925,0.25836,0.40434,0.26543,0.40612,0.22896,0.41583,0.22304,0.41233,0.23015,0.40795,0.23611,0.41127,0.22378,0.42932,0.2291,0.42395,0.23609,0.42681,0.23049,0.43229,0.20636,0.56229,0.20221,0.56511,0.19988,0.56071,0.20285,0.55831,0.19025,0.57458,0.19101,0.57693,0.18874,0.56893,0.18683,0.57098,0.20307,0.5904,0.20054,0.58742,0.20253,0.58261,0.20542,0.58617,0.21085,0.58772,0.21601,0.58676,0.21605,0.59234,0.21199,0.59254,0.23808,0.57341,0.2344,0.58111,0.22507,0.58014,0.22848,0.57231,0.21645,0.55999,0.22127,0.55205,0.22881,0.55408,0.22404,0.56247,0.16374,0.32813,0.16548,0.33653,0.18067,0.34835,0.16587,0.32642,0.17628,0.33339,0.17838,0.33003,0.18171,0.33405,0.17938,0.3376,0.29133,0.64964,0.29096,0.65489,0.2854,0.65114,0.28538,0.64619,0.27534,0.65714,0.27976,0.65735,0.2903,0.6375,0.27659,0.65044,0.26806,0.46905,0.26063,0.46743,0.26672,0.46168,0.27378,0.46382,0.24066,0.4698,0.24763,0.47164,0.24234,0.47753,0.23569,0.47554,0.24443,0.48525,0.25229,0.48665,0.24717,0.49282,0.2398,0.49119,0.26749,0.481,0.27213,0.47514,0.28284,0.47434,0.27934,0.48043,0.17327,0.45998,0.16938,0.46315,0.166,0.46012,0.16869,0.45714,0.16178,0.47441,0.16487,0.47865,0.16284,0.47913,0.15824,0.47447,0.18077,0.48264,0.17634,0.48099,0.17615,0.47623,0.18152,0.47758,0.1906,0.47412,0.19498,0.46873,0.20269,0.47072,0.19808,0.47602,0.18432,0.45807,0.18969,0.45207,0.1977,0.45481,0.1922,0.46078,0.25114,0.63171,0.24885,0.63531,0.24464,0.63406,0.24596,0.63089,0.24635,0.64795,0.25125,0.64724,0.2474,0.63813,0.24246,0.6457,0.26129,0.65058,0.27122,0.64904,0.28797,0.63963,0.26245,0.64849,0.27254,0.63822,0.2735,0.63356,0.28099,0.63438,0.27956,0.63914,0.25996,0.62757,0.26235,0.62184,0.27043,0.62234,0.26777,0.628,0.2248,0.60136,0.22114,0.60501,0.21729,0.60155,0.21967,0.59838,0.21585,0.61411,0.21443,0.61038,0.21965,0.61041,0.2214,0.61469,0.2292,0.62792,0.22591,0.62575,0.22661,0.62086,0.2304,0.62348,0.23582,0.62381,0.24033,0.62197,0.24147,0.62686,0.23789,0.62801,0.2477,0.6151,0.25006,0.60792,0.25929,0.60839,0.25646,0.61521,0.23569,0.5978,0.23975,0.59004,0.24869,0.59137,0.24447,0.59937,0.26043,0.50109,0.2543,0.50778,0.24578,0.5065,0.25068,0.50021,0.2559,0.5161,0.26205,0.51929,0.2563,0.5248,0.25025,0.52228,0.27988,0.30314,0.28615,0.30063,0.28715,0.30957,0.28038,0.3117,0.27324,0.29768,0.26775,0.29997,0.26705,0.29315,0.27233,0.29058,0.25712,0.30951,0.26234,0.30848,0.2611,0.31533,0.25522,0.31623,0.14756,0.36263,0.14739,0.36507,0.14505,0.366,0.14461,0.3637,0.13672,0.36855,0.13806,0.37108,0.13611,0.37428,0.13471,0.37142,0.14933,0.36724,0.15181,0.36747,0.15106,0.37035,0.14864,0.36986,0.1497,0.41269,0.14711,0.41257,0.14699,0.4095,0.14952,0.4092,0.1431,0.40479,0.14425,0.40754,0.14233,0.40912,0.14068,0.40677,0.13745,0.41764,0.13496,0.41513,0.13586,0.41274,0.13813,0.41493,0.15498,0.46465,0.15449,0.46226,0.1569,0.46286,0.1579,0.46531,0.16091,0.45893,0.15827,0.45997,0.15693,0.4571,0.15948,0.45574,0.15204,0.45352,0.15364,0.45619,0.1526,0.45854,0.15072,0.45643,0.18566,0.55411,0.18497,0.55614,0.18357,0.55426,0.18427,0.55215,0.18876,0.56176,0.18921,0.55934,0.19112,0.56058,0.19113,0.56338,0.1956,0.55799,0.19307,0.55827,0.19253,0.55544,0.19495,0.55481,0.20103,0.60752,0.20344,0.60857,0.20324,0.60992,0.20037,0.60875,0.212,0.60036,0.20946,0.60152,0.20802,0.59892,0.21032,0.5974,0.19956,0.60063,0.19914,0.60344,0.19796,0.60138,0.19839,0.59817,0.23347,0.64328,0.23571,0.64386,0.23716,0.64492,0.23444,0.64454,0.23978,0.63481,0.23791,0.63646,0.23597,0.63463,0.23758,0.63278,0.23109,0.63353,0.23317,0.63501,0.23311,0.63722,0.23106,0.63626,0.12812,0.36573,0.13476,0.37247,0.15374,0.38705,0.1297,0.36848,0.13635,0.36569,0.12867,0.36269,0.12738,0.36406,0.14474,0.37943,0.22819,0.64927,0.2328,0.64444,0.23881,0.63225,0.22764,0.64989,0.22769,0.64587,0.24798,0.62505,0.23198,0.63816,0.22626,0.64662,0.14024,0.42222,0.12607,0.41334,0.12681,0.41172,0.13235,0.41542,0.12265,0.41172,0.1329,0.42405,0.12941,0.41083,0.12505,0.40926,0.19327,0.61135,0.19675,0.60763,0.19816,0.59569,0.19087,0.61092,0.19672,0.60308,0.19267,0.60846,0.19203,0.60833,0.20379,0.59745,0.12847,0.47056,0.12548,0.47107,0.13026,0.46377,0.13046,0.46657,0.14042,0.47019,0.12942,0.47401,0.13063,0.47299,0.13655,0.47277,0.15307,0.48003,0.14264,0.47297,0.14235,0.46837,0.14768,0.4714,0.14185,0.4613,0.13928,0.46353,0.13568,0.46444,0.14118,0.46685,0.20557,0.40959,0.21158,0.4134,0.20671,0.41869,0.20072,0.41503,0.1807,0.42334,0.17277,0.41919,0.17955,0.41334,0.1876,0.41717,0.19198,0.43638,0.1866,0.44293,0.17777,0.44023,0.18305,0.43336,0.20417,0.43351,0.20802,0.42779,0.21366,0.4314,0.21023,0.43702,0.27012,0.55753,0.27208,0.55053,0.28058,0.55252,0.27822,0.55978,0.29271,0.5463,0.29516,0.53795,0.30677,0.53934,0.30362,0.54776,0.25775,0.53954,0.2594,0.5332,0.26671,0.53497,0.26546,0.54165,0.22055,0.4767,0.22572,0.47883,0.22226,0.484,0.21706,0.48177,0.20736,0.48524,0.20326,0.49123,0.19697,0.48919,0.20082,0.48336,0.21184,0.50201,0.20787,0.50896,0.20182,0.5067,0.20559,0.49985,0.22433,0.49204,0.22984,0.49473,0.22676,0.50059,0.22125,0.49794,0.18342,0.34797,0.17878,0.35205,0.17485,0.34848,0.17945,0.34481,0.18528,0.36555,0.17952,0.36972,0.17311,0.36441,0.17882,0.36037,0.18402,0.38455,0.17588,0.3865,0.17037,0.38096,0.1785,0.37857,0.16982,0.39969,0.17557,0.39477,0.1834,0.39875,0.17778,0.40379,0.23708,0.45507,0.24418,0.45642,0.23898,0.46231,0.23242,0.46086,0.26578,0.45396,0.25783,0.45207,0.26437,0.44644,0.27247,0.44854,0.26906,0.43396,0.26245,0.43932,0.25376,0.43794,0.26032,0.43249,0.23258,0.4403,0.23982,0.44211,0.2349,0.44782,0.22818,0.44598,0.31143,0.62603,0.31464,0.62091,0.32192,0.62351,0.31858,0.62855,0.33838,0.61713,0.34492,0.62059,0.33959,0.62492,0.3331,0.62167,0.33763,0.60872,0.32918,0.60536,0.33661,0.59955,0.34577,0.60315,0.3147,0.60793,0.31051,0.61323,0.30241,0.61085,0.30603,0.60538,0.29215,0.59452,0.29534,0.58809,0.3048,0.59068,0.30094,0.59703,0.32053,0.58651,0.3259,0.57895,0.33854,0.58193,0.33267,0.58954,0.32328,0.56007,0.31862,0.56834,0.30697,0.56617,0.31129,0.55793,0.29286,0.57167,0.28967,0.57876,0.28133,0.57621,0.28403,0.56925,0.23193,0.5165,0.22629,0.51463,0.22931,0.50881,0.23504,0.5108,0.21232,0.52622,0.20589,0.52462,0.21009,0.5178,0.21659,0.51934,0.22226,0.53533,0.21839,0.54265,0.21142,0.54152,0.21513,0.53436,0.23798,0.53218,0.23202,0.53013,0.23472,0.52413,0.2405,0.52618,0.28356,0.43066,0.28924,0.42531,0.2963,0.42809,0.29102,0.43337,0.29884,0.44535,0.29305,0.45009,0.28638,0.44645,0.29236,0.44167,0.32242,0.53347,0.32558,0.52587,0.338,0.52929,0.33493,0.53652,0.35445,0.55066,0.35129,0.55797,0.33969,0.55475,0.34337,0.5472,0.35483,0.57676,0.35845,0.56864,0.36834,0.57109,0.36506,0.57925,0.29524,0.31592,0.30132,0.31417,0.30364,0.32131,0.29771,0.32361,0.29491,0.33443,0.29922,0.34015,0.29287,0.34643,0.28828,0.34075,0.29059,0.35898,0.29547,0.36346,0.28829,0.37113,0.28321,0.36707,0.28694,0.3813,0.29321,0.38344,0.28666,0.38931,0.28007,0.38769,0.28662,0.39638,0.29303,0.39785,0.28659,0.40329,0.27983,0.40202,0.28691,0.41031,0.29371,0.41212,0.28776,0.41762,0.28045,0.41592,0.25024,0.56736,0.25271,0.56018,0.26041,0.56224,0.25822,0.5692,0.24901,0.54371,0.24722,0.55075,0.2399,0.54831,0.24215,0.54112,0.19119,0.33549,0.18708,0.33322,0.18795,0.32898,0.1922,0.33102,0.30123,0.64202,0.30658,0.64543,0.30354,0.6514,0.29849,0.64776,0.21728,0.46251,0.22262,0.4646,0.21897,0.46969,0.21355,0.46762,0.20928,0.45177,0.21277,0.44608,0.21852,0.44912,0.21521,0.45467,0.29067,0.63119,0.2935,0.62624,0.30099,0.62859,0.29789,0.63363,0.29146,0.61403,0.28871,0.61926,0.28105,0.61769,0.28373,0.61218,0.28127,0.59838,0.27863,0.60455,0.27079,0.60277,0.27352,0.59623,0.27108,0.58053,0.26849,0.58737,0.2607,0.58534,0.26348,0.57825,0.16095,0.41882,0.15603,0.42081,0.15385,0.41606,0.15736,0.41405,0.14753,0.42625,0.14768,0.42244,0.15249,0.42499,0.15235,0.4296,0.15296,0.4466,0.15102,0.44264,0.15421,0.4381,0.15645,0.44264,0.16176,0.44544,0.1672,0.44525,0.16609,0.45096,0.16193,0.45074,0.18732,0.49822,0.1835,0.4954,0.18437,0.49005,0.18882,0.49262,0.18316,0.50994,0.18361,0.51419,0.18419,0.51725,0.18952,0.50872,0.16667,0.34314,0.16769,0.34755,0.16294,0.34967,0.16259,0.34529,0.15078,0.35709,0.17771,0.35758,0.15602,0.35088,0.14816,0.35339,0.15912,0.36722,0.15617,0.36538,0.15878,0.3623,0.16287,0.36419,0.15975,0.37754,0.15468,0.37829,0.15401,0.37381,0.15777,0.37277,0.14371,0.38217,0.14586,0.37889,0.14985,0.38155,0.1478,0.38545,0.14507,0.39929,0.14307,0.39566,0.14752,0.39259,0.14934,0.39679,0.15403,0.4006,0.15906,0.4019,0.15669,0.40698,0.153,0.40545,0.19157,0.52941,0.1936,0.5247,0.19732,0.52809,0.19453,0.53297,0.18821,0.54092,0.18641,0.5441,0.18646,0.54712,0.1974,0.54384,0.19839,0.54689,0.20293,0.54701,0.20146,0.55195,0.19788,0.55114,0.19935,0.57009,0.19961,0.57492,0.19496,0.57268,0.19485,0.5685,0.19836,0.59137,0.20744,0.58213,0.19578,0.58421,0.19584,0.58918,0.17154,0.33208,0.16888,0.33549,0.16758,0.33035,0.16992,0.3269,0.28101,0.65275,0.28272,0.65687,0.27793,0.65467,0.27594,0.65069,0.16793,0.46792,0.16997,0.47146,0.16496,0.4713,0.16323,0.46817,0.17709,0.49034,0.18632,0.4897,0.17212,0.48379,0.17251,0.48456,0.2494,0.63965,0.25285,0.64182,0.24802,0.64376,0.24513,0.64166,0.26677,0.64227,0.26877,0.64596,0.26359,0.64631,0.26106,0.64301,0.21218,0.60158,0.2074,0.61222,0.21158,0.61747,0.21486,0.61681,0.24807,0.6115,0.22382,0.62216,0.22171,0.62855,0.22887,0.62792,0.13836,0.36425,0.1394,0.36312,0.14261,0.36132,0.14112,0.36258,0.14227,0.37139,0.14406,0.36947,0.14568,0.37123,0.14435,0.37358,0.13298,0.4072,0.13473,0.40472,0.13602,0.40635,0.13439,0.40851,0.14461,0.41447,0.1441,0.41697,0.14154,0.41492,0.14257,0.41287,0.15359,0.46985,0.15073,0.46842,0.15054,0.46464,0.15293,0.46617,0.1458,0.45811,0.14622,0.45478,0.14792,0.45694,0.14787,0.45983,0.1894,0.55191,0.19005,0.5541,0.18871,0.55578,0.1878,0.55394,0.1851,0.56579,0.18382,0.56344,0.18516,0.56051,0.18629,0.56263,0.20813,0.60446,0.20896,0.60704,0.20599,0.60652,0.20577,0.60407,0.20332,0.59654,0.20496,0.59855,0.20409,0.60084,0.20232,0.59939,0.2377,0.63927,0.23934,0.6411,0.23675,0.6416,0.23562,0.63961,0.23002,0.63745,0.22893,0.63472,0.22914,0.63766,0.2301,0.63998,0.14272,0.42422,0.13981,0.42317,0.14244,0.42668,0.14321,0.42986,0.1471,0.44731,0.158,0.4404,0.14677,0.43818,0.14577,0.44317,0.18111,0.50418,0.18717,0.50737,0.17937,0.4978,0.1792,0.49818,0.18979,0.50697,0.19383,0.51028,0.19188,0.51596,0.18834,0.51242,0.15712,0.34521,0.16281,0.34724,0.16009,0.34087,0.15802,0.34227,0.15766,0.35494,0.15651,0.35852,0.15192,0.35906,0.15267,0.35582,0.13668,0.38396,0.13997,0.37895,0.13574,0.37928,0.13665,0.382,0.13881,0.39842,0.16291,0.39129,0.13994,0.39045,0.13564,0.39517,0.18666,0.53021,0.18621,0.53415,0.18575,0.52995,0.18462,0.52607,0.19357,0.54055,0.19448,0.54426,0.19124,0.54693,0.19042,0.54387,0.19451,0.34944,0.19074,0.34658,0.19327,0.34212,0.1972,0.34446,0.20062,0.36986,0.19487,0.36526,0.19657,0.35872,0.20154,0.36253,0.21697,0.39046,0.20919,0.38884,0.2075,0.38109,0.21473,0.38304,0.25949,0.39713,0.25372,0.39445,0.26115,0.38882,0.26676,0.39164,0.23643,0.39194,0.24085,0.39606,0.23272,0.40015,0.2283,0.3955,0.1947,0.39691,0.19511,0.39095,0.20281,0.39345,0.20211,0.40008,0.2674,0.36523,0.27132,0.37046,0.26394,0.37814,0.2601,0.37315,0.24471,0.37074,0.24864,0.37555,0.24074,0.38202,0.23743,0.37669,0.2214,0.36696,0.22879,0.36618,0.22824,0.37386,0.22089,0.37526,0.21289,0.35054,0.22007,0.35109,0.21626,0.35869,0.20932,0.3577,0.21198,0.33656,0.21792,0.3376,0.21163,0.34312,0.206,0.34156,0.23806,0.32508,0.24474,0.32404,0.23858,0.33086,0.2314,0.33167,0.24217,0.34288,0.23361,0.34354,0.24001,0.33665,0.24843,0.33576,0.24452,0.3506,0.25196,0.35226,0.24602,0.36,0.23928,0.35831,0.27242,0.32093,0.26919,0.32861,0.26174,0.32837,0.26533,0.32139,0.27093,0.33879,0.27666,0.34309,0.27004,0.35163,0.26469,0.34722,0.28662,0.46248,0.29339,0.45851,0.29958,0.46298,0.29169,0.46675,0.28515,0.52038,0.28533,0.52867,0.27535,0.52858,0.27417,0.5213,0.27955,0.49431,0.28678,0.48676,0.30076,0.48713,0.29388,0.49483,0.31824,0.50701,0.31486,0.51501,0.29996,0.51271,0.30339,0.50437,0.33394,0.50353,0.33638,0.49678,0.34565,0.50165,0.34405,0.50825,0.34453,0.47791,0.34749,0.47139,0.35455,0.47547,0.35199,0.48217,0.32969,0.35208,0.3342,0.35629,0.32995,0.36257,0.32539,0.35823,0.32951,0.33448,0.33366,0.3373,0.32953,0.34252,0.32538,0.3392,0.32585,0.31132,0.32909,0.30671,0.3327,0.3096,0.32938,0.31431,0.33017,0.37249,0.33482,0.37606,0.33031,0.38118,0.32559,0.37782,0.39314,0.38066,0.39185,0.38458,0.38905,0.38143,0.39066,0.3773,0.39575,0.39441,0.39446,0.39809,0.39153,0.39521,0.39312,0.39143,0.31286,0.46241,0.31833,0.4566,0.3255,0.46016,0.32048,0.46622,0.33092,0.43843,0.33474,0.43265,0.34092,0.43616,0.3373,0.44204,0.32756,0.42167,0.33211,0.41714,0.33743,0.41967,0.33302,0.42435,0.43085,0.50512,0.43139,0.51131,0.42707,0.50622,0.4268,0.49992,0.43906,0.52505,0.44031,0.53367,0.43624,0.52895,0.43579,0.52222,0.31442,0.32874,0.31134,0.32469,0.31542,0.32223,0.31846,0.32577,0.31059,0.38372,0.30522,0.38054,0.31082,0.37544,0.31586,0.37913,0.30556,0.40968,0.31077,0.40529,0.31627,0.40852,0.31135,0.41284,0.33676,0.45761,0.34031,0.45163,0.34693,0.4552,0.34366,0.46123,0.36542,0.54725,0.36608,0.54059,0.373,0.54426,0.37273,0.55078,0.42186,0.48178,0.42222,0.48819,0.41784,0.48289,0.41784,0.47647,0.33321,0.47991,0.32958,0.48598,0.31919,0.48226,0.32408,0.47598,0.30881,0.34017,0.3135,0.33606,0.31723,0.34013,0.31274,0.3447,0.31471,0.43778,0.32076,0.44104,0.31644,0.44711,0.31019,0.44365,0.31219,0.4207,0.31771,0.42371,0.31328,0.42895,0.30752,0.42584,0.32575,0.3252,0.32952,0.32121,0.3334,0.3234,0.32954,0.3276,0.31642,0.30712,0.31937,0.31162,0.31612,0.31515,0.31329,0.31056,0.31049,0.3911,0.31574,0.39421,0.3105,0.39812,0.30495,0.39524,0.3506,0.5262,0.35179,0.5195,0.35994,0.5237,0.35916,0.5302,0.31129,0.36562,0.30663,0.36097,0.31199,0.35481,0.31635,0.35963,0.25,0.125,0.375,0.25,0.25,0.375,0.125,0.25,0.75,0.125,0.875,0.25,0.75,0.375,0.625,0.25,0.75,0.875,0.625,0.75,0.75,0.625,0.875,0.75,0.25,0.875,0.125,0.75,0.25,0.625,0.375,0.75,0.12482,0.125,0.18613,0.25,0.12454,0.375,0.0625,0.25,0.36786,0.125,0.41351,0.25,0.35788,0.375,0.30563,0.25,0.36786,0.875,0.30563,0.75,0.35788,0.625,0.41351,0.75,0.12482,0.875,0.0625,0.75,0.12454,0.625,0.18613,0.75,0.875,0.63214,0.75,0.69437,0.625,0.64212,0.75,0.58649,0.875,0.87518,0.75,0.9375,0.625,0.87546,0.75,0.81387,0.125,0.87518,0.25,0.81387,0.375,0.87546,0.25,0.9375,0.125,0.63214,0.25,0.58649,0.375,0.64212,0.25,0.69437,0.875,0.63214,0.75,0.69437,0.625,0.64212,0.75,0.58649,0.875,0.87518,0.75,0.9375,0.625,0.87546,0.75,0.81387,0.125,0.87518,0.25,0.81387,0.375,0.87546,0.25,0.9375,0.125,0.63214,0.25,0.58649,0.375,0.64212,0.25,0.69437,0.63214,0.125,0.69437,0.25,0.64212,0.375,0.58649,0.25,0.87518,0.125,0.9375,0.25,0.87546,0.375,0.81387,0.25,0.87518,0.875,0.81387,0.75,0.87546,0.625,0.9375,0.75,0.63214,0.875,0.58649,0.75,0.64212,0.625,0.69437,0.75,0.52135,0.12821,0.52026,0.26923,0.50818,0.37815,0.49164,0.25,0.41835,0.38947,0.36179,0.53612,0.41463,0.51896,0.46866,0.37212,0.43489,0.62352,0.35661,0.4729,0.27987,0.45345,0.36059,0.60391,0.52046,0.87167,0.49164,0.75,0.50729,0.62161,0.51492,0.72998,0.60204,0.50931,0.4399,0.5485,0.40991,0.58696,0.5719,0.54535,0.87116,0.4781,0.75,0.50836,0.61921,0.49028,0.725,0.47543,0.12495,0.47808,0.24778,0.4753,0.37301,0.49025,0.25,0.50836,0.18293,0.54438,0.24811,0.58613,0.31136,0.54782,0.24628,0.5085,0.56632,0.41549,0.38434,0.3935,0.32747,0.3783,0.50911,0.39747,0.87024,0.47569,0.75,0.50836,0.61747,0.48542,0.71867,0.45856,0.12423,0.47559,0.2426,0.45796,0.37146,0.48533,0.25,0.50836,0.14084,0.38904,0.18524,0.37056,0.26196,0.39034,0.21788,0.41172,0.37835,0.37061,0.33072,0.51629,0.29113,0.53315,0.33609,0.38777,0.47475,0.12817,0.50836,0.25,0.48316,0.37823,0.45158,0.26909,0.47395,0.87193,0.44677,0.73165,0.48236,0.62199,0.50836,0.75,0.28744,0.61748,0.2216,0.47576,0.27925,0.49154,0.34789,0.63349,0.21939,0.38792,0.18374,0.44323,0.22085,0.45092,0.26112,0.39202,0.22569,0.51497,0.1952,0.51692,0.23443,0.57677,0.26929,0.57891,0.29494,0.53823,0.26656,0.54117,0.35637,0.53861,0.39393,0.53607,0.1663,0.52319,0.1921,0.52921,0.23009,0.5334,0.20574,0.52795,0.28361,0.49821,0.25743,0.49564,0.35011,0.49875,0.38571,0.50227,0.14762,0.48624,0.17286,0.48615,0.21539,0.49414,0.19188,0.4954,0.26689,0.47755,0.23032,0.47632,0.26302,0.42003,0.30603,0.41691,0.26056,0.59504,0.22875,0.53984,0.26559,0.53669,0.30385,0.5955,0.875,0.23279,0.75,0.27795,0.625,0.2312,0.75,0.17969,0.75,0.27795,0.625,0.2312,0.75,0.17969,0.875,0.23279,0.23279,0.125,0.27795,0.25,0.2312,0.375,0.17969,0.25,0.25,0.125,0.375,0.25,0.25,0.375,0.125,0.25,0.75,0.125,0.875,0.25,0.75,0.375,0.625,0.25,0.75,0.875,0.625,0.75,0.75,0.625,0.875,0.75,0.25,0.875,0.125,0.75,0.25,0.625,0.375,0.75,0.12482,0.125,0.18613,0.25,0.12454,0.375,0.0625,0.25,0.36786,0.125,0.41351,0.25,0.35788,0.375,0.30563,0.25,0.36786,0.875,0.30563,0.75,0.35788,0.625,0.41351,0.75,0.12482,0.875,0.0625,0.75,0.12454,0.625,0.18613,0.75,0.875,0.63214,0.75,0.69437,0.625,0.64212,0.75,0.58649,0.875,0.87518,0.75,0.9375,0.625,0.87546,0.75,0.81387,0.125,0.87518,0.25,0.81387,0.375,0.87546,0.25,0.9375,0.125,0.63214,0.25,0.58649,0.375,0.64212,0.25,0.69437,0.875,0.63214,0.75,0.69437,0.625,0.64212,0.75,0.58649,0.875,0.87518,0.75,0.9375,0.625,0.87546,0.75,0.81387,0.125,0.87518,0.25,0.81387,0.375,0.87546,0.25,0.9375,0.125,0.63214,0.25,0.58649,0.375,0.64212,0.25,0.69437,0.63214,0.125,0.69437,0.25,0.64212,0.375,0.58649,0.25,0.87518,0.125,0.9375,0.25,0.87546,0.375,0.81387,0.25,0.87518,0.875,0.81387,0.75,0.87546,0.625,0.9375,0.75,0.63214,0.875,0.58649,0.75,0.64212,0.625,0.69437,0.75,0.52411,0.125,0.54001,0.25,0.51413,0.375,0.49164,0.25,0.5932,0.125,0.60681,0.25,0.59256,0.375,0.57675,0.25,0.5932,0.875,0.57675,0.75,0.59256,0.625,0.60681,0.75,0.52411,0.875,0.49164,0.75,0.51413,0.625,0.54001,0.75,0.125,0.36755,0.25,0.36328,0.375,0.36792,0.25,0.37366,0.125,0.36755,0.25,0.36328,0.375,0.36792,0.25,0.37366,0.36755,0.875,0.36328,0.75,0.36792,0.625,0.37366,0.75,0.76721,0.875,0.72205,0.75,0.7688,0.625,0.82031,0.75,0.63245,0.125,0.63672,0.25,0.63208,0.375,0.62634,0.25,0.875,0.4068,0.75,0.42325,0.625,0.40744,0.75,0.39319,0.875,0.47589,0.75,0.50836,0.625,0.48587,0.75,0.45999,0.125,0.47589,0.25,0.45999,0.375,0.48587,0.25,0.50836,0.125,0.4068,0.25,0.39319,0.375,0.40744,0.25,0.42325,0.875,0.4068,0.75,0.42325,0.625,0.40744,0.75,0.39319,0.875,0.47589,0.75,0.50836,0.625,0.48587,0.75,0.45999,0.125,0.47589,0.25,0.45999,0.375,0.48587,0.25,0.50836,0.125,0.4068,0.25,0.39319,0.375,0.40744,0.25,0.42325,0.4068,0.125,0.42325,0.25,0.40744,0.375,0.39319,0.25,0.47589,0.125,0.50836,0.25,0.48587,0.375,0.45999,0.25,0.47589,0.875,0.45999,0.75,0.48587,0.625,0.50836,0.75,0.4068,0.875,0.39319,0.75,0.40744,0.625,0.42325,0.75,0.875,0.34998,0.75,0.35547,0.625,0.34839,0.75,0.33655,0.125,0.23279,0.25,0.17969,0.375,0.2312,0.25,0.27795,0.875,0.34998,0.75,0.35547,0.625,0.34839,0.75,0.33655,0.125,0.23279,0.25,0.17969,0.375,0.2312,0.25,0.27795,0.34998,0.125,0.35547,0.25,0.34839,0.375,0.33655,0.25,0.23279,0.875,0.17969,0.75,0.2312,0.625,0.27795,0.75,0.76721,0.125,0.82031,0.25,0.7688,0.375,0.72205,0.25,0.65002,0.875,0.64453,0.75,0.65161,0.625,0.66345,0.75,0.125,0.34998,0.25,0.33655,0.375,0.34839,0.25,0.35547,0.125,0.34998,0.25,0.33655,0.375,0.34839,0.25,0.35547,0.34998,0.875,0.33655,0.75,0.34839,0.625,0.35547,0.75,0.65002,0.125,0.66345,0.25,0.65161,0.375,0.64453,0.25,0.875,0.36755,0.75,0.37366,0.625,0.36792,0.75,0.36328,0.875,0.36755,0.75,0.37366,0.625,0.36792,0.75,0.36328,0.36755,0.125,0.37366,0.25,0.36792,0.375,0.36328,0.25,0.63245,0.875,0.62634,0.75,0.63208,0.625,0.63672,0.75,0.25,0.125,0.375,0.25,0.25,0.375,0.125,0.25,0.75,0.125,0.875,0.25,0.75,0.375,0.625,0.25,0.75,0.875,0.625,0.75,0.75,0.625,0.875,0.75,0.25,0.875,0.125,0.75,0.25,0.625,0.375,0.75,0.12482,0.125,0.18613,0.25,0.12454,0.375,0.0625,0.25,0.36786,0.125,0.41351,0.25,0.35788,0.375,0.30563,0.25,0.36786,0.875,0.30563,0.75,0.35788,0.625,0.41351,0.75,0.12482,0.875,0.0625,0.75,0.12454,0.625,0.18613,0.75,0.875,0.63214,0.75,0.69437,0.625,0.64212,0.75,0.58649,0.875,0.87518,0.75,0.9375,0.625,0.87546,0.75,0.81387,0.125,0.87518,0.25,0.81387,0.375,0.87546,0.25,0.9375,0.125,0.63214,0.25,0.58649,0.375,0.64212,0.25,0.69437,0.875,0.63214,0.75,0.69437,0.625,0.64212,0.75,0.58649,0.875,0.87518,0.75,0.9375,0.625,0.87546,0.75,0.81387,0.125,0.87518,0.25,0.81387,0.375,0.87546,0.25,0.9375,0.125,0.63214,0.25,0.58649,0.375,0.64212,0.25,0.69437,0.63214,0.125,0.69437,0.25,0.64212,0.375,0.58649,0.25,0.87518,0.125,0.9375,0.25,0.87546,0.375,0.81387,0.25,0.87518,0.875,0.81387,0.75,0.87546,0.625,0.9375,0.75,0.63214,0.875,0.58649,0.75,0.64212,0.625,0.69437,0.75,0.52411,0.125,0.54001,0.25,0.51413,0.375,0.49164,0.25,0.5932,0.125,0.60681,0.25,0.59256,0.375,0.57675,0.25,0.5932,0.875,0.57675,0.75,0.59256,0.625,0.60681,0.75,0.52411,0.875,0.49164,0.75,0.51413,0.625,0.54001,0.75,0.87082,0.32294,0.75,0.32422,0.61855,0.32553,0.72267,0.33474,0.125,0.36755,0.25,0.36328,0.375,0.36792,0.25,0.37366,0.8701,0.32107,0.75,0.32422,0.61716,0.32179,0.71765,0.32169,0.125,0.36755,0.25,0.36328,0.375,0.36792,0.25,0.37366,0.31949,0.12787,0.32422,0.25,0.31836,0.37797,0.31034,0.26732,0.36755,0.875,0.36328,0.75,0.36792,0.625,0.37366,0.75,0.63245,0.125,0.63672,0.25,0.63208,0.375,0.62634,0.25,0.67516,0.87203,0.67578,0.75,0.67101,0.62209,0.6523,0.73224,0.875,0.4068,0.75,0.42325,0.625,0.40744,0.75,0.39319,0.875,0.47589,0.75,0.50836,0.625,0.48587,0.75,0.45999,0.125,0.47589,0.25,0.45999,0.375,0.48587,0.25,0.50836,0.125,0.4068,0.25,0.39319,0.375,0.40744,0.25,0.42325,0.875,0.4068,0.75,0.42325,0.625,0.40744,0.75,0.39319,0.875,0.47589,0.75,0.50836,0.625,0.48587,0.75,0.45999,0.125,0.47589,0.25,0.45999,0.375,0.48587,0.25,0.50836,0.125,0.4068,0.25,0.39319,0.375,0.40744,0.25,0.42325,0.4068,0.125,0.42325,0.25,0.40744,0.375,0.39319,0.25,0.47589,0.125,0.50836,0.25,0.48587,0.375,0.45999,0.25,0.47589,0.875,0.45999,0.75,0.48587,0.625,0.50836,0.75,0.4068,0.875,0.39319,0.75,0.40744,0.625,0.42325,0.75,0.875,0.35156,0.75,0.35547,0.625,0.35156,0.75,0.34766,0.125,0.33594,0.25,0.33203,0.375,0.33594,0.25,0.33984,0.875,0.35156,0.75,0.35547,0.625,0.35156,0.75,0.34766,0.125,0.33594,0.25,0.33203,0.375,0.33594,0.25,0.33984,0.35156,0.125,0.35547,0.25,0.35156,0.375,0.34766,0.25,0.33594,0.875,0.33203,0.75,0.33594,0.625,0.33984,0.75,0.66406,0.125,0.66797,0.25,0.66406,0.375,0.66016,0.25,0.64844,0.875,0.64453,0.75,0.64844,0.625,0.65234,0.75,0.125,0.35156,0.25,0.34766,0.375,0.35156,0.25,0.35547,0.125,0.35156,0.25,0.34766,0.375,0.35156,0.25,0.35547,0.35156,0.875,0.34766,0.75,0.35156,0.625,0.35547,0.75,0.64844,0.125,0.65234,0.25,0.64844,0.375,0.64453,0.25,0.875,0.36755,0.75,0.37366,0.625,0.36792,0.75,0.36328,0.875,0.36755,0.75,0.37366,0.625,0.36792,0.75,0.36328,0.36755,0.125,0.37366,0.25,0.36792,0.375,0.36328,0.25,0.63245,0.875,0.62634,0.75,0.63208,0.625,0.63672,0.75,0.875,0.33594,0.75,0.33984,0.625,0.33594,0.75,0.33203,0.875,0.33594,0.75,0.33984,0.625,0.33594,0.75,0.33203,0.33594,0.125,0.33984,0.25,0.33594,0.375,0.33203,0.25,0.66406,0.875,0.66016,0.75,0.66406,0.625,0.66797,0.75,0.12465,0.32286,0.24562,0.33427,0.37238,0.32545,0.25,0.32422,0.12402,0.32097,0.24118,0.32108,0.37108,0.32168,0.25,0.32422,0.31892,0.87231,0.30691,0.73394,0.31779,0.6224,0.32422,0.75,0.67592,0.12809,0.65685,0.26859,0.67177,0.37815,0.67578,0.25,0.31529,0.37056,0.50132,0.35621,0.56082,0.33826,0.37427,0.35209,0.17897,0.50886,0.21359,0.51637,0.25449,0.64776,0.21908,0.64009,0.22771,0.50598,0.25448,0.36911,0.27621,0.3592,0.24886,0.49634,0.22122,0.5258,0.29136,0.46912,0.23438,0.40795,0.16401,0.46433,0.3796,0.53285,0.54942,0.47177,0.58898,0.4109,0.41891,0.47163,0.36271,0.5259,0.45011,0.5122,0.54414,0.3674,0.45699,0.38106,0.29304,0.48344,0.4077,0.6247,0.51533,0.63717,0.40096,0.49606,0.1672,0.3615,0.24976,0.34885,0.20985,0.33441,0.12682,0.34655,0.65771,0.33334,0.49925,0.34552,0.52044,0.36177,0.68846,0.34706,0.23148,0.33084,0.12676,0.34069,0.20681,0.35547,0.31331,0.34335,0.60118,0.70037,0.54165,0.5709,0.47684,0.62452,0.54563,0.75923,0.61057,0.30284,0.56118,0.24566,0.50056,0.38338,0.55822,0.435,0.66544,0.35585,0.51207,0.38382,0.53947,0.41718,0.70163,0.38436,0.23881,0.35372,0.13893,0.37892,0.22484,0.4118,0.32579,0.38196,0.28439,0.28213,0.26411,0.39806,0.24119,0.33156,0.26404,0.21228,0.28579,0.70632,0.2676,0.76875,0.24472,0.64003,0.26533,0.58222,0.26316,0.40683,0.23186,0.42423,0.32617,0.41411,0.3674,0.39462,0.13285,0.39535,0.15458,0.41,0.19758,0.4006,0.17801,0.38411,0.26571,0.46774,0.20991,0.46527,0.27174,0.53332,0.33639,0.54087,0.31822,0.48054,0.26473,0.55212,0.31448,0.54934,0.37593,0.4723,0.30007,0.51704,0.27519,0.54805,0.36521,0.52241,0.39912,0.48697,0.16791,0.50722,0.19465,0.53672,0.23351,0.51171,0.20807,0.47799,0.17267,0.44146,0.15182,0.4356,0.16979,0.38346,0.19365,0.38593,0.1815,0.56127,0.16108,0.50126,0.17617,0.50197,0.19953,0.56672,0.38609,0.4613,0.39233,0.46531,0.39002,0.47182,0.38334,0.46773,0.36415,0.34354,0.36863,0.34798,0.36517,0.35441,0.36043,0.34996,0.3622,0.32566,0.36646,0.32851,0.36316,0.33375,0.35865,0.3306,0.35593,0.29849,0.36018,0.30128,0.35801,0.30588,0.3536,0.30327,0.36604,0.36475,0.37051,0.36857,0.36675,0.37382,0.36201,0.37035,0.34954,0.39247,0.3446,0.38984,0.34904,0.38534,0.35396,0.38807,0.35093,0.40643,0.34571,0.40386,0.35017,0.39944,0.35536,0.40204,0.3744,0.42423,0.38009,0.42767,0.37688,0.43321,0.37077,0.42969,0.37126,0.40942,0.37633,0.41188,0.37254,0.4163,0.36707,0.41374,0.39287,0.52116,0.38571,0.51691,0.38723,0.51034,0.39442,0.51466,0.40352,0.54217,0.39677,0.53792,0.39829,0.53175,0.40508,0.53603,0.37966,0.44236,0.38558,0.44583,0.38268,0.45154,0.37637,0.44806,0.38154,0.49928,0.37414,0.49494,0.37604,0.48807,0.38334,0.49241,0.35977,0.31257,0.36401,0.31469,0.36112,0.31883,0.35672,0.31676,0.36826,0.38898,0.36331,0.3863,0.36746,0.38178,0.37209,0.38464,0.37019,0.40274,0.365,0.40021,0.36918,0.3959,0.37405,0.39851,0.40993,0.51686,0.40313,0.51241,0.40474,0.50573,0.41129,0.5103,0.4199,0.53862,0.41339,0.53414,0.41496,0.5278,0.42124,0.53236,0.39954,0.49437,0.39254,0.48987,0.39454,0.48294,0.40116,0.48749,0.40058,0.45749,0.40492,0.46192,0.4043,0.46791,0.39953,0.46337,0.37712,0.3403,0.3801,0.34521,0.37841,0.35133,0.37518,0.3464,0.37451,0.3223,0.37739,0.32558,0.37582,0.33042,0.3727,0.32683,0.36602,0.29538,0.36927,0.29853,0.3688,0.30267,0.3654,0.2997,0.37952,0.36182,0.3824,0.36607,0.38045,0.37103,0.37731,0.36714,0.38934,0.42108,0.39315,0.42484,0.39177,0.42989,0.38755,0.42605,0.386,0.40651,0.3893,0.40929,0.38742,0.41328,0.38374,0.4104,0.39445,0.43888,0.39846,0.44272,0.39733,0.44789,0.39294,0.44405,0.37117,0.30928,0.37421,0.31179,0.37301,0.31549,0.36984,0.31303,0.40968,0.4294,0.40503,0.41163,0.41117,0.43165,0.41578,0.44946,0.42416,0.48115,0.4225,0.47518,0.42474,0.48099,0.42675,0.48695,0.41632,0.45886,0.41506,0.45369,0.41692,0.45869,0.41858,0.464,0.41011,0.43989,0.40924,0.43539,0.41073,0.43974,0.41197,0.44425,0.40496,0.42228,0.40427,0.41792,0.40558,0.42214,0.40666,0.42657,0.40103,0.40694,0.40074,0.40359,0.40164,0.40682,0.4023,0.41025,0.39816,0.39395,0.39791,0.39053,0.39876,0.39384,0.39932,0.39715,0.39548,0.38022,0.3953,0.37641,0.39607,0.38011,0.39656,0.38369,0.39317,0.36381,0.39301,0.3589,0.39373,0.36369,0.39415,0.36824,0.39048,0.34271,0.39009,0.33706,0.39103,0.34258,0.39166,0.34824,0.38728,0.32292,0.38682,0.31895,0.3878,0.32278,0.38848,0.32709,0.38344,0.30916,0.38257,0.30599,0.38393,0.30902,0.38491,0.31216,0.3776,0.29601,0.37611,0.29227,0.37798,0.29589,0.37959,0.29946,0.43646,0.50844,0.43433,0.50166,0.42846,0.47911,0.43084,0.48583,0.43288,0.50406,0.43121,0.49875,0.43318,0.50307,0.43456,0.50631,0.38509,0.31563,0.3833,0.30917,0.38188,0.3072,0.38472,0.31759,0.39578,0.36121,0.39273,0.34967,0.40247,0.38699,0.4049,0.39649,0.40584,0.40648,0.41228,0.42689,0.4204,0.45796,0.41282,0.43346,0.41124,0.43843,0.40734,0.42539,0.40443,0.41411,0.40839,0.42723,0.40791,0.42953,0.40594,0.42282,0.40447,0.41706,0.40651,0.42389,0.42224,0.47371,0.42295,0.47468,0.4264,0.48519,0.42474,0.48099,0.41497,0.45277,0.41578,0.45464,0.4184,0.46281,0.41692,0.45869,0.40931,0.43504,0.41018,0.43776,0.41195,0.44357,0.41073,0.43974,0.40446,0.41799,0.40565,0.42228,0.40681,0.4265,0.40558,0.42214,0.40107,0.4042,0.4022,0.40882,0.40256,0.41057,0.40164,0.40682,0.39838,0.39165,0.3999,0.39789,0.39971,0.39801,0.39876,0.39384,0.39594,0.37811,0.39786,0.38641,0.39712,0.3851,0.39607,0.38011,0.39375,0.36099,0.39615,0.37225,0.39487,0.37025,0.39373,0.36369,0.3903,0.3374,0.39198,0.3463,0.3922,0.3497,0.39103,0.34258,0.38684,0.31868,0.38726,0.32141,0.38849,0.32675,0.3878,0.32278,0.38267,0.30599,0.3838,0.30905,0.38499,0.3121,0.38393,0.30902,0.37696,0.29482,0.37915,0.29953,0.37978,0.29966,0.37798,0.29589,0.42309,0.46224,0.41038,0.41614,0.4046,0.39478,0.41912,0.44683,0.43077,0.49668,0.43023,0.49268,0.4319,0.49658,0.4329,0.50209,0.38241,0.38634,0.37911,0.38332,0.38138,0.3791,0.38437,0.38232,0.38476,0.39995,0.38128,0.39714,0.38354,0.39321,0.3867,0.39612,0.42283,0.5136,0.41782,0.50861,0.41797,0.50224,0.42272,0.50735,0.43223,0.53594,0.42748,0.53094,0.42757,0.52482,0.43209,0.52989,0.41315,0.49066,0.40806,0.48559,0.40852,0.47906,0.41324,0.48416,0.41023,0.45496,0.41392,0.4595,0.41382,0.4653,0.40972,0.46063,0.38577,0.33814,0.3883,0.34324,0.38725,0.34927,0.38447,0.34416,0.38271,0.32006,0.38519,0.32348,0.38426,0.3282,0.38155,0.32446,0.37275,0.29331,0.37585,0.29653,0.37599,0.30053,0.37276,0.29747,0.38851,0.35987,0.3909,0.36429,0.38958,0.36917,0.38694,0.36512,0.39929,0.41897,0.40247,0.42282,0.4017,0.42768,0.39812,0.42376,0.39583,0.40456,0.39856,0.40743,0.39734,0.41126,0.39424,0.4083,0.40431,0.43655,0.40766,0.44049,0.40709,0.44546,0.40337,0.44153,0.37877,0.30708,0.3815,0.30971,0.38095,0.31327,0.3781,0.31068,0.36693,0.46633,0.37374,0.47031,0.37113,0.477,0.36415,0.47289,0.34699,0.34782,0.35169,0.35207,0.34764,0.35849,0.34295,0.35418,0.34591,0.33009,0.35032,0.33283,0.34641,0.33815,0.34199,0.33507,0.34253,0.30262,0.34663,0.30538,0.34373,0.31013,0.33966,0.30749,0.34819,0.36862,0.35295,0.37226,0.34862,0.37751,0.34389,0.37416,0.35465,0.42841,0.36082,0.43185,0.35718,0.4376,0.35087,0.434,0.35176,0.41327,0.35719,0.41572,0.35286,0.4203,0.34731,0.41769,0.3601,0.44697,0.36656,0.45044,0.3633,0.45636,0.35674,0.45282,0.34469,0.31692,0.34895,0.31898,0.34538,0.32325,0.34117,0.32119,0.33063,0.39595,0.32573,0.39319,0.33044,0.38887,0.33524,0.39161,0.3315,0.41012,0.32632,0.40734,0.33098,0.40298,0.33607,0.40568,0.3757,0.52551,0.36837,0.52142,0.36959,0.51499,0.377,0.51916,0.3871,0.54575,0.38035,0.54181,0.38154,0.53575,0.38845,0.53981,0.36337,0.50419,0.35556,0.49984,0.35733,0.49319,0.36494,0.49748,0.125,0.125,0.375,0.125,0.375,0.375,0.125,0.375,0.625,0.125,0.875,0.125,0.875,0.375,0.625,0.375,0.875,0.875,0.625,0.875,0.625,0.625,0.875,0.625,0.375,0.875,0.125,0.875,0.125,0.625,0.375,0.625,0.0625,0.125,0.18677,0.125,0.18567,0.375,0.0625,0.375,0.30884,0.125,0.42432,0.125,0.40747,0.375,0.30334,0.375,0.42432,0.875,0.30884,0.875,0.30334,0.625,0.40747,0.625,0.18677,0.875,0.0625,0.875,0.0625,0.625,0.18567,0.625,0.875,0.57568,0.875,0.69116,0.625,0.69666,0.625,0.59253,0.875,0.81323,0.875,0.9375,0.625,0.9375,0.625,0.81433,0.125,0.9375,0.125,0.81323,0.375,0.81433,0.375,0.9375,0.125,0.69116,0.125,0.57568,0.375,0.59253,0.375,0.69666,0.875,0.57568,0.875,0.69116,0.625,0.69666,0.625,0.59253,0.875,0.81323,0.875,0.9375,0.625,0.9375,0.625,0.81433,0.125,0.9375,0.125,0.81323,0.375,0.81433,0.375,0.9375,0.125,0.69116,0.125,0.57568,0.375,0.59253,0.375,0.69666,0.57568,0.125,0.69116,0.125,0.69666,0.375,0.59253,0.375,0.81323,0.125,0.9375,0.125,0.9375,0.375,0.81433,0.375,0.9375,0.875,0.81323,0.875,0.81433,0.625,0.9375,0.625,0.69116,0.875,0.57568,0.875,0.59253,0.625,0.69666,0.625,0.50244,0.125,0.54321,0.125,0.53772,0.375,0.4856,0.375,0.57739,0.125,0.60791,0.125,0.60645,0.375,0.57629,0.375,0.60791,0.875,0.57739,0.875,0.57629,0.625,0.60645,0.625,0.54321,0.875,0.50244,0.875,0.4856,0.625,0.53772,0.625,0.86623,0.32126,0.875,0.32422,0.625,0.32422,0.61131,0.326,0.125,0.37256,0.125,0.36328,0.375,0.36328,0.375,0.37402,0.86543,0.31895,0.875,0.32422,0.625,0.32422,0.60976,0.32136,0.125,0.37256,0.125,0.36328,0.375,0.36328,0.375,0.37402,0.31392,0.1284,0.32422,0.125,0.32422,0.375,0.31149,0.37779,0.37256,0.875,0.36328,0.875,0.36328,0.625,0.37402,0.625,0.62744,0.125,0.63672,0.125,0.63672,0.375,0.62598,0.375,0.67433,0.86977,0.67578,0.875,0.67578,0.625,0.66552,0.61995,0.875,0.39209,0.875,0.42261,0.625,0.42371,0.625,0.39355,0.875,0.45679,0.875,0.49756,0.625,0.5144,0.625,0.46228,0.125,0.49756,0.125,0.45679,0.375,0.46228,0.375,0.5144,0.125,0.42261,0.125,0.39209,0.375,0.39355,0.375,0.42371,0.875,0.39209,0.875,0.42261,0.625,0.42371,0.625,0.39355,0.875,0.45679,0.875,0.49756,0.625,0.5144,0.625,0.46228,0.125,0.49756,0.125,0.45679,0.375,0.46228,0.375,0.5144,0.125,0.42261,0.125,0.39209,0.375,0.39355,0.375,0.42371,0.39209,0.125,0.42261,0.125,0.42371,0.375,0.39355,0.375,0.45679,0.125,0.49756,0.125,0.5144,0.375,0.46228,0.375,0.49756,0.875,0.45679,0.875,0.46228,0.625,0.5144,0.625,0.42261,0.875,0.39209,0.875,0.39355,0.625,0.42371,0.625,0.875,0.34766,0.875,0.35547,0.625,0.35547,0.625,0.34766,0.125,0.33984,0.125,0.33203,0.375,0.33203,0.375,0.33984,0.875,0.34766,0.875,0.35547,0.625,0.35547,0.625,0.34766,0.125,0.33984,0.125,0.33203,0.375,0.33203,0.375,0.33984,0.34766,0.125,0.35547,0.125,0.35547,0.375,0.34766,0.375,0.33984,0.875,0.33203,0.875,0.33203,0.625,0.33984,0.625,0.66016,0.125,0.66797,0.125,0.66797,0.375,0.66016,0.375,0.65234,0.875,0.64453,0.875,0.64453,0.625,0.65234,0.625,0.125,0.35547,0.125,0.34766,0.375,0.34766,0.375,0.35547,0.125,0.35547,0.125,0.34766,0.375,0.34766,0.375,0.35547,0.35547,0.875,0.34766,0.875,0.34766,0.625,0.35547,0.625,0.64453,0.125,0.65234,0.125,0.65234,0.375,0.64453,0.375,0.875,0.36328,0.875,0.37256,0.625,0.37402,0.625,0.36328,0.875,0.36328,0.875,0.37256,0.625,0.37402,0.625,0.36328,0.36328,0.125,0.37256,0.125,0.37402,0.375,0.36328,0.375,0.63672,0.875,0.62744,0.875,0.62598,0.625,0.63672,0.625,0.875,0.33203,0.875,0.33984,0.625,0.33984,0.625,0.33203,0.875,0.33203,0.875,0.33984,0.625,0.33984,0.625,0.33203,0.33203,0.125,0.33984,0.125,0.33984,0.375,0.33203,0.375,0.66797,0.875,0.66016,0.875,0.66016,0.625,0.66797,0.625,0.125,0.32422,0.12395,0.32103,0.36904,0.32577,0.375,0.32422,0.125,0.32422,0.1232,0.31868,0.36752,0.32109,0.375,0.32422,0.32422,0.875,0.31407,0.87042,0.31163,0.61982,0.32422,0.625,0.67578,0.125,0.67532,0.13056,0.66651,0.38074,0.67578,0.375,0.125,0.125,0.375,0.125,0.375,0.375,0.125,0.375,0.625,0.125,0.875,0.125,0.875,0.375,0.625,0.375,0.875,0.875,0.625,0.875,0.625,0.625,0.875,0.625,0.375,0.875,0.125,0.875,0.125,0.625,0.375,0.625,0.0625,0.125,0.18677,0.125,0.18567,0.375,0.0625,0.375,0.30884,0.125,0.41623,0.12855,0.39121,0.3782,0.30334,0.375,0.41643,0.87072,0.30884,0.875,0.30334,0.625,0.39142,0.62037,0.18677,0.875,0.0625,0.875,0.0625,0.625,0.18567,0.625,0.8661,0.5787,0.875,0.69116,0.625,0.69666,0.6111,0.59864,0.875,0.81323,0.875,0.9375,0.625,0.9375,0.625,0.81433,0.125,0.9375,0.125,0.81323,0.375,0.81433,0.375,0.9375,0.125,0.69116,0.12389,0.5785,0.36889,0.59844,0.375,0.69666,0.86589,0.57785,0.875,0.69116,0.625,0.69666,0.61062,0.59696,0.875,0.81323,0.875,0.9375,0.625,0.9375,0.625,0.81433,0.125,0.9375,0.125,0.81323,0.375,0.81433,0.375,0.9375,0.125,0.69116,0.12355,0.57768,0.36828,0.59679,0.375,0.69666,0.57295,0.12917,0.69116,0.125,0.69666,0.375,0.58721,0.37932,0.81323,0.125,0.9375,0.125,0.9375,0.375,0.81433,0.375,0.9375,0.875,0.81323,0.875,0.81433,0.625,0.9375,0.625,0.69116,0.875,0.57289,0.87114,0.58716,0.62129,0.69666,0.625,0.43076,0.17253,0.35316,0.25693,0.34446,0.41342,0.40431,0.39101,0.43342,0.82077,0.40533,0.60187,0.34691,0.56949,0.36051,0.72513,0.77928,0.52362,0.55548,0.54497,0.45816,0.53382,0.61454,0.52521,0.13062,0.52099,0.14517,0.5179,0.3017,0.53138,0.34446,0.54396,0.77768,0.51599,0.55311,0.53657,0.45245,0.51365,0.61036,0.50484,0.12718,0.51376,0.13591,0.49866,0.2943,0.51159,0.34138,0.53571,0.47159,0.17866,0.48782,0.3966,0.39664,0.42685,0.38635,0.27348,0.47088,0.8242,0.38439,0.7342,0.39598,0.58043,0.48754,0.60643,0.25003,0.41999,0.26538,0.41648,0.2663,0.42353,0.25098,0.4274,0.26525,0.40954,0.25006,0.41276,0.25104,0.40573,0.2657,0.40266,0.23561,0.41501,0.22275,0.41653,0.22346,0.40797,0.23692,0.40756,0.22471,0.43364,0.22309,0.42499,0.23562,0.4228,0.23681,0.43081,0.2062,0.55801,0.20602,0.5669,0.19917,0.56327,0.20024,0.55807,0.18868,0.57122,0.19193,0.57812,0.19337,0.57141,0.18552,0.56855,0.20519,0.59006,0.20098,0.59106,0.19984,0.58359,0.20559,0.58167,0.2097,0.59113,0.21256,0.5837,0.21892,0.59005,0.2141,0.5943,0.23534,0.56892,0.2409,0.57781,0.22823,0.58436,0.22154,0.57581,0.21718,0.5656,0.21556,0.55482,0.22712,0.54897,0.23068,0.55922,0.16453,0.32412,0.16278,0.33201,0.1777,0.35291,0.17365,0.33543,0.17637,0.33739,0.17598,0.32927,0.18081,0.33065,0.18248,0.33755,0.28883,0.64516,0.29376,0.65447,0.28833,0.6553,0.28235,0.64724,0.27192,0.65503,0.27871,0.6594,0.28544,0.64882,0.29306,0.63337,0.27419,0.46722,0.26156,0.47118,0.25995,0.46356,0.27351,0.46012,0.23488,0.47177,0.24683,0.46773,0.24851,0.47553,0.23655,0.47938,0.23859,0.48723,0.2508,0.48305,0.25401,0.49021,0.24113,0.49512,0.27034,0.48403,0.26498,0.47794,0.27851,0.47236,0.28815,0.47648,0.17241,0.45634,0.17369,0.4636,0.16585,0.46257,0.16583,0.45759,0.15893,0.47235,0.16475,0.4766,0.16858,0.48124,0.15901,0.47794,0.18369,0.48106,0.17845,0.48425,0.17395,0.47803,0.17891,0.47425,0.19244,0.47774,0.18849,0.47044,0.20142,0.46704,0.20393,0.47431,0.18533,0.4624,0.18309,0.45374,0.19641,0.45035,0.19894,0.4591,0.24896,0.62918,0.25297,0.63434,0.2454,0.63601,0.24358,0.63216,0.24293,0.64732,0.25005,0.64847,0.25657,0.63895,0.24244,0.63688,0.25761,0.6497,0.26491,0.65172,0.29248,0.6368,0.27902,0.64017,0.27595,0.64079,0.2689,0.63588,0.27832,0.6314,0.28365,0.63757,0.26257,0.6306,0.25723,0.62455,0.26778,0.61908,0.27305,0.62546,0.22331,0.59733,0.22578,0.60572,0.21735,0.60418,0.21682,0.5989,0.21904,0.61653,0.21267,0.61195,0.21589,0.60864,0.22391,0.61254,0.23114,0.62716,0.22734,0.62898,0.22415,0.62244,0.22945,0.61929,0.23553,0.62721,0.23654,0.6198,0.2436,0.6243,0.24015,0.62908,0.25119,0.61837,0.24376,0.61165,0.25643,0.60445,0.26219,0.61213,0.23768,0.60287,0.2335,0.59308,0.24623,0.58678,0.25114,0.59591,0.25815,0.49733,0.26267,0.50519,0.24727,0.51026,0.24418,0.50277,0.24943,0.51813,0.26333,0.51449,0.26136,0.52361,0.25127,0.52652,0.27699,0.30836,0.28245,0.29758,0.28993,0.30372,0.284,0.31542,0.27555,0.29255,0.27071,0.30255,0.26489,0.29756,0.26915,0.28868,0.25393,0.31325,0.25999,0.30573,0.26476,0.31134,0.25676,0.3192,0.14596,0.36185,0.14894,0.36355,0.1463,0.36651,0.14364,0.36554,0.13454,0.36811,0.1388,0.36888,0.13742,0.37345,0.13757,0.37708,0.14799,0.36838,0.15102,0.36598,0.1526,0.36904,0.14952,0.37162,0.15085,0.41088,0.14852,0.41435,0.14603,0.41107,0.14817,0.40761,0.1409,0.40442,0.14503,0.40537,0.14378,0.40939,0.14067,0.40892,0.1387,0.41726,0.13741,0.41873,0.13385,0.41261,0.13771,0.41282,0.15679,0.46633,0.15354,0.46287,0.15541,0.46153,0.1589,0.46414,0.16143,0.4568,0.16039,0.46094,0.15656,0.45904,0.15754,0.45472,0.15031,0.45367,0.15381,0.45356,0.15382,0.45831,0.15142,0.45883,0.18556,0.55204,0.18584,0.55607,0.18421,0.55613,0.18293,0.55234,0.18968,0.56406,0.18818,0.55967,0.19022,0.55891,0.19248,0.5625,0.19647,0.55616,0.1947,0.55977,0.19182,0.55701,0.19349,0.5536,0.19946,0.6085,0.2024,0.60656,0.20476,0.61065,0.20166,0.60514,0.21232,0.59825,0.2116,0.60239,0.20778,0.60076,0.20839,0.59667,0.19859,0.59837,0.20053,0.60266,0.19764,0.60437,0.20113,0.59631,0.23267,0.64442,0.23407,0.6423,0.23761,0.64528,0.23685,0.64092,0.23952,0.63299,0.23999,0.63655,0.23627,0.63626,0.2357,0.63258,0.22983,0.63431,0.23246,0.63292,0.23395,0.6366,0.23233,0.63788,0.12625,0.36474,0.13018,0.36668,0.15078,0.38638,0.1419,0.37805,0.1514,0.37751,0.13132,0.36303,0.12608,0.36243,0.13343,0.37189,0.22628,0.65106,0.23,0.64746,0.23927,0.63137,0.23214,0.64235,0.22527,0.64897,0.23741,0.63676,0.24943,0.6217,0.22732,0.64436,0.141,0.42225,0.13191,0.41793,0.12447,0.41128,0.12926,0.4121,0.12307,0.40974,0.12522,0.41916,0.13917,0.42006,0.12727,0.40886,0.19109,0.61209,0.19552,0.61046,0.20006,0.5951,0.19245,0.60396,0.20581,0.5946,0.19434,0.60692,0.19116,0.61,0.19676,0.604,0.1309,0.46864,0.12624,0.47252,0.12619,0.46802,0.13297,0.46334,0.14459,0.47188,0.13346,0.47213,0.12795,0.47404,0.13345,0.4719,0.15354,0.47866,0.15069,0.47845,0.1394,0.46956,0.14507,0.46724,0.14539,0.46347,0.14203,0.46219,0.1364,0.46509,0.13786,0.4667,0.19992,0.41048,0.21119,0.4087,0.2118,0.4179,0.20137,0.4196,0.18837,0.42197,0.17276,0.42464,0.17248,0.41409,0.18684,0.4124,0.19054,0.4316,0.19351,0.44111,0.17986,0.44488,0.17528,0.43532,0.20544,0.43817,0.20303,0.42884,0.21274,0.42685,0.21477,0.43595,0.27303,0.56214,0.26712,0.55296,0.27727,0.5479,0.28377,0.55722,0.29646,0.55116,0.28875,0.54155,0.30205,0.53437,0.31118,0.5444,0.26083,0.54397,0.25499,0.53516,0.26371,0.53124,0.27019,0.53907,0.21618,0.47818,0.22492,0.4752,0.2266,0.48257,0.21798,0.48549,0.20627,0.48151,0.20844,0.48912,0.19827,0.49332,0.19557,0.48522,0.21067,0.49754,0.21302,0.50653,0.20291,0.51131,0.20068,0.50211,0.22007,0.4936,0.22866,0.49055,0.2311,0.49892,0.22249,0.50231,0.18329,0.34448,0.18355,0.35169,0.17378,0.35221,0.17567,0.34487,0.18444,0.36043,0.18631,0.37107,0.17305,0.36859,0.1729,0.36021,0.18573,0.38078,0.1823,0.38789,0.16871,0.38534,0.1717,0.37681,0.17099,0.40446,0.16841,0.39479,0.182,0.39478,0.18476,0.4031,0.2315,0.45726,0.24316,0.4528,0.24514,0.4601,0.23327,0.46445,0.27293,0.45239,0.25865,0.45583,0.25692,0.44839,0.27187,0.44474,0.26801,0.4305,0.27012,0.43746,0.25485,0.44136,0.25271,0.43452,0.22697,0.44199,0.23872,0.43848,0.24095,0.44568,0.22937,0.44985,0.31362,0.62992,0.30924,0.6222,0.3202,0.61971,0.3236,0.62721,0.3321,0.6178,0.34473,0.61662,0.34514,0.6245,0.3341,0.6254,0.34521,0.60792,0.33021,0.60965,0.32784,0.60091,0.34614,0.59829,0.3126,0.60384,0.31662,0.61192,0.30476,0.61464,0.29998,0.60698,0.29484,0.59884,0.28943,0.59008,0.30183,0.58603,0.30764,0.59521,0.32351,0.59147,0.31722,0.58146,0.3347,0.57635,0.34245,0.58763,0.31937,0.55477,0.32712,0.56543,0.31038,0.57126,0.30354,0.56112,0.28988,0.56683,0.29583,0.5765,0.28402,0.5809,0.27862,0.5715,0.23638,0.51458,0.22762,0.51849,0.22501,0.51068,0.23371,0.50697,0.21786,0.52336,0.20673,0.52911,0.20496,0.52024,0.21538,0.51522,0.22069,0.53129,0.22387,0.53956,0.21307,0.54566,0.20953,0.53754,0.24214,0.53029,0.23372,0.53426,0.23046,0.52617,0.23906,0.52222,0.28452,0.4345,0.28258,0.42688,0.2955,0.42391,0.29709,0.43234,0.29838,0.44099,0.29921,0.44972,0.28664,0.45052,0.28596,0.44241,0.32705,0.53872,0.31745,0.52824,0.33342,0.52387,0.34235,0.53465,0.35047,0.54532,0.35859,0.55597,0.3436,0.56019,0.33565,0.54935,0.35885,0.58249,0.35107,0.57117,0.36558,0.56619,0.37105,0.57598,0.2928,0.32153,0.29754,0.31055,0.30509,0.31761,0.30231,0.32544,0.2893,0.33403,0.30012,0.3349,0.29835,0.34569,0.2872,0.3474,0.28461,0.36063,0.29646,0.35748,0.29456,0.36922,0.28192,0.37315,0.28034,0.38347,0.29342,0.37925,0.29313,0.38726,0.27998,0.3915,0.2799,0.39857,0.29306,0.39438,0.29305,0.40132,0.27981,0.40545,0.28009,0.41238,0.29337,0.40843,0.29418,0.41592,0.28098,0.41951,0.25297,0.5718,0.24751,0.56284,0.25758,0.55769,0.26319,0.56677,0.2464,0.53907,0.25182,0.54841,0.2423,0.55329,0.23766,0.54338,0.19405,0.33431,0.18839,0.33648,0.18561,0.33012,0.19027,0.32773,0.29678,0.64309,0.30601,0.6409,0.30708,0.65004,0.30008,0.65272,0.2126,0.46396,0.22178,0.46098,0.2234,0.46814,0.21445,0.47117,0.21047,0.45604,0.20803,0.44734,0.21726,0.44484,0.21972,0.45326,0.29287,0.63483,0.28836,0.62775,0.2987,0.62486,0.30321,0.63247,0.28895,0.61035,0.29394,0.61763,0.28354,0.62107,0.27853,0.6142,0.2787,0.59407,0.28384,0.60255,0.27339,0.60676,0.2682,0.59862,0.26852,0.57591,0.27362,0.58512,0.26317,0.58986,0.25821,0.58078,0.1612,0.41446,0.16012,0.42331,0.15283,0.41849,0.15452,0.4134,0.14942,0.43006,0.14547,0.42279,0.14971,0.42172,0.1556,0.42882,0.1553,0.44681,0.1506,0.44673,0.15118,0.43837,0.15765,0.43793,0.15984,0.44889,0.16439,0.44153,0.16941,0.44897,0.16377,0.45282,0.19023,0.49685,0.18485,0.49947,0.182,0.49149,0.18727,0.48857,0.18954,0.50758,0.1826,0.51003,0.18455,0.51834,0.18793,0.51236,0.16437,0.34199,0.16923,0.34403,0.16572,0.35098,0.16049,0.34829,0.14574,0.35586,0.17051,0.36286,0.17659,0.35396,0.15077,0.35079,0.16271,0.36732,0.15641,0.36739,0.15565,0.36347,0.16263,0.36115,0.16119,0.37399,0.15773,0.38118,0.15241,0.3758,0.15533,0.37167,0.14417,0.38548,0.1431,0.37904,0.14833,0.37839,0.15157,0.38522,0.14759,0.40004,0.14217,0.39885,0.14385,0.39231,0.15132,0.39308,0.15155,0.40314,0.15726,0.39779,0.16026,0.40603,0.15409,0.40798,0.19187,0.53331,0.19098,0.52535,0.19665,0.52374,0.1977,0.53252,0.19681,0.54077,0.18682,0.54087,0.18596,0.54707,0.19147,0.54708,0.19634,0.54937,0.20101,0.54395,0.20445,0.55038,0.19921,0.55321,0.19662,0.56722,0.20245,0.57338,0.197,0.57612,0.19288,0.56951,0.19676,0.59264,0.20745,0.58608,0.20394,0.57847,0.19478,0.58551,0.17175,0.32769,0.1711,0.33631,0.16682,0.3345,0.16815,0.32605,0.27766,0.64947,0.28423,0.65627,0.28132,0.65752,0.27448,0.65201,0.16443,0.46661,0.1719,0.46941,0.16817,0.47321,0.16185,0.46958,0.17454,0.4877,0.18854,0.4946,0.18146,0.48637,0.17021,0.48165,0.24562,0.63983,0.25376,0.63946,0.25189,0.64403,0.24443,0.6435,0.26266,0.64067,0.27058,0.64421,0.26732,0.64778,0.25977,0.64522,0.22082,0.60362,0.20684,0.60037,0.20886,0.61508,0.21442,0.62001,0.24824,0.61534,0.24125,0.60857,0.21956,0.62562,0.22366,0.63135,0.14029,0.36468,0.13623,0.36382,0.14794,0.36532,0.1422,0.36044,0.14228,0.37365,0.14249,0.36933,0.14547,0.36949,0.14622,0.37328,0.13202,0.40848,0.13859,0.40765,0.13549,0.40391,0.13667,0.40862,0.14392,0.4127,0.14573,0.41652,0.14235,0.41716,0.14106,0.4129,0.15448,0.46827,0.1532,0.47255,0.14917,0.46536,0.15163,0.46401,0.14635,0.46036,0.14762,0.45633,0.14689,0.45413,0.14914,0.45945,0.1881,0.55189,0.19071,0.55213,0.18972,0.5558,0.18773,0.55585,0.18667,0.56523,0.18339,0.56631,0.18432,0.56068,0.18613,0.56026,0.20671,0.60325,0.2101,0.60574,0.20764,0.60822,0.20474,0.60486,0.20178,0.59708,0.2049,0.59622,0.20522,0.60042,0.20298,0.60138,0.23611,0.63866,0.23978,0.63968,0.23877,0.64248,0.2351,0.64052,0.22927,0.64101,0.2362,0.6296,0.22735,0.63592,0.23086,0.63921,0.1466,0.42725,0.14107,0.42307,0.1409,0.4231,0.1439,0.43057,0.14588,0.44722,0.15546,0.44717,0.15594,0.43538,0.14557,0.43894,0.1804,0.50199,0.18765,0.50809,0.18797,0.50438,0.17785,0.49452,0.18726,0.50803,0.19272,0.50571,0.19485,0.51485,0.18932,0.51681,0.15582,0.34525,0.16578,0.34838,0.16499,0.34943,0.15995,0.3391,0.15541,0.35353,0.15992,0.3565,0.15351,0.36031,0.15005,0.35795,0.13659,0.38525,0.14503,0.38043,0.13968,0.38064,0.13674,0.37891,0.1353,0.39831,0.15696,0.3993,0.15993,0.38657,0.13606,0.3919,0.18611,0.52639,0.187,0.5339,0.18877,0.53428,0.18507,0.52401,0.19124,0.54058,0.19616,0.54074,0.19297,0.54727,0.18949,0.54689,0.19776,0.34826,0.19133,0.35039,0.19017,0.34311,0.19654,0.34095,0.20388,0.36791,0.19703,0.37131,0.19327,0.35969,0.19976,0.35733,0.21952,0.38694,0.2143,0.39382,0.20428,0.38335,0.21049,0.3784,0.26634,0.39553,0.25268,0.39843,0.25498,0.39004,0.2674,0.38732,0.23046,0.39139,0.24259,0.39173,0.2393,0.40005,0.22612,0.39954,0.19704,0.40129,0.19169,0.39303,0.19813,0.38831,0.20691,0.39865,0.26184,0.36663,0.27298,0.36379,0.26971,0.37672,0.25824,0.37936,0.23953,0.37157,0.25038,0.36948,0.24661,0.38143,0.23508,0.38193,0.21723,0.37127,0.22618,0.36252,0.23164,0.36932,0.22507,0.37856,0.20772,0.35323,0.21879,0.34749,0.22177,0.35481,0.21144,0.36228,0.20586,0.33818,0.2184,0.33474,0.21775,0.34071,0.20618,0.34514,0.23156,0.32899,0.24437,0.32105,0.24541,0.32698,0.23146,0.33454,0.24951,0.33908,0.23489,0.3468,0.23256,0.34047,0.24733,0.33275,0.23784,0.35423,0.25139,0.34729,0.25208,0.35767,0.24046,0.3624,0.26982,0.31744,0.275,0.32499,0.26311,0.33202,0.26014,0.32515,0.26465,0.34144,0.27721,0.33621,0.27576,0.35,0.26424,0.35347,0.28572,0.46609,0.28688,0.4586,0.29979,0.4585,0.29845,0.46763,0.27835,0.51659,0.29132,0.52477,0.27998,0.53253,0.27086,0.52544,0.2829,0.49857,0.2764,0.49055,0.2973,0.48288,0.30443,0.49155,0.31319,0.5015,0.32345,0.51267,0.30625,0.51781,0.29326,0.50783,0.3382,0.50936,0.32979,0.49779,0.34217,0.49602,0.34924,0.5073,0.34695,0.48332,0.34232,0.4726,0.35244,0.47014,0.35685,0.48091,0.32534,0.353,0.33402,0.35105,0.33439,0.36158,0.32545,0.36349,0.32545,0.33533,0.3336,0.33345,0.33375,0.34148,0.32533,0.34342,0.32588,0.31505,0.32577,0.30758,0.33243,0.30573,0.33294,0.31334,0.32556,0.37336,0.33471,0.37155,0.33492,0.38029,0.32562,0.38199,0.39255,0.37694,0.39376,0.38422,0.38964,0.38499,0.38849,0.37772,0.39507,0.39106,0.39643,0.39771,0.39219,0.39852,0.39088,0.39184,0.31322,0.46743,0.31227,0.45762,0.32419,0.45538,0.327,0.46497,0.33224,0.44322,0.32975,0.43379,0.33971,0.43157,0.34229,0.44091,0.32808,0.42541,0.32718,0.41807,0.33703,0.41618,0.33798,0.42332,0.42859,0.49944,0.43303,0.5105,0.42941,0.51194,0.42473,0.50046,0.43697,0.51998,0.44175,0.5318,0.43846,0.53459,0.434,0.5233,0.31812,0.32903,0.31061,0.32805,0.31212,0.32167,0.31878,0.32252,0.31581,0.38319,0.30511,0.38446,0.3054,0.37629,0.31594,0.37477,0.30593,0.41355,0.30528,0.40593,0.31604,0.40483,0.31655,0.41226,0.33846,0.46246,0.33517,0.45283,0.34531,0.45045,0.34865,0.46001,0.36927,0.55242,0.36179,0.54205,0.3699,0.53923,0.37596,0.54921,0.41973,0.47595,0.42406,0.48769,0.42009,0.48877,0.41565,0.47708,0.33082,0.47482,0.33591,0.48512,0.32238,0.48717,0.31626,0.4774,0.30829,0.3449,0.30934,0.33579,0.3175,0.33613,0.31699,0.34448,0.3095,0.43907,0.31978,0.4364,0.32184,0.4458,0.31088,0.44828,0.30692,0.42164,0.31726,0.41984,0.31825,0.42773,0.30816,0.43016,0.32565,0.32841,0.32583,0.32199,0.33329,0.32021,0.33348,0.32658,0.31344,0.30635,0.31944,0.30778,0.31924,0.31545,0.31311,0.31471,0.30498,0.39173,0.31574,0.39067,0.31578,0.3977,0.30498,0.39873,0.35447,0.53155,0.3466,0.52075,0.35643,0.51836,0.36336,0.52895,0.31618,0.36495,0.30612,0.36645,0.3072,0.3554,0.31655,0.35432,0.125,0.125,0.375,0.125,0.375,0.375,0.125,0.375,0.625,0.125,0.875,0.125,0.875,0.375,0.625,0.375,0.875,0.875,0.625,0.875,0.625,0.625,0.875,0.625,0.375,0.875,0.125,0.875,0.125,0.625,0.375,0.625,0.0625,0.125,0.18677,0.125,0.18567,0.375,0.0625,0.375,0.30884,0.125,0.42432,0.125,0.40747,0.375,0.30334,0.375,0.42432,0.875,0.30884,0.875,0.30334,0.625,0.40747,0.625,0.18677,0.875,0.0625,0.875,0.0625,0.625,0.18567,0.625,0.875,0.57568,0.875,0.69116,0.625,0.69666,0.625,0.59253,0.875,0.81323,0.875,0.9375,0.625,0.9375,0.625,0.81433,0.125,0.9375,0.125,0.81323,0.375,0.81433,0.375,0.9375,0.125,0.69116,0.125,0.57568,0.375,0.59253,0.375,0.69666,0.875,0.57568,0.875,0.69116,0.625,0.69666,0.625,0.59253,0.875,0.81323,0.875,0.9375,0.625,0.9375,0.625,0.81433,0.125,0.9375,0.125,0.81323,0.375,0.81433,0.375,0.9375,0.125,0.69116,0.125,0.57568,0.375,0.59253,0.375,0.69666,0.57568,0.125,0.69116,0.125,0.69666,0.375,0.59253,0.375,0.81323,0.125,0.9375,0.125,0.9375,0.375,0.81433,0.375,0.9375,0.875,0.81323,0.875,0.81433,0.625,0.9375,0.625,0.69116,0.875,0.57568,0.875,0.59253,0.625,0.69666,0.625,0.50244,0.125,0.53217,0.13786,0.51392,0.38761,0.4856,0.375,0.47718,0.27161,0.36542,0.50128,0.35608,0.57805,0.46499,0.45965,0.44577,0.72483,0.43241,0.5354,0.27266,0.41035,0.27719,0.48824,0.52862,0.86169,0.50244,0.875,0.4856,0.625,0.51037,0.61144,0.70627,0.50218,0.50928,0.51181,0.37064,0.58776,0.44475,0.58376,0.85963,0.46562,0.875,0.49756,0.625,0.5144,0.60186,0.4799,0.125,0.49756,0.12481,0.46553,0.36704,0.47982,0.375,0.5144,0.15366,0.50107,0.21267,0.58508,0.28763,0.58683,0.33519,0.51138,0.67166,0.41632,0.47449,0.41478,0.2945,0.37526,0.35199,0.38307,0.85596,0.456,0.875,0.49756,0.625,0.5144,0.5949,0.46049,0.125,0.49756,0.12191,0.4556,0.36085,0.4601,0.375,0.5144,0.12904,0.41116,0.15577,0.37356,0.21996,0.37097,0.30425,0.4128,0.38253,0.27007,0.37541,0.45859,0.28478,0.57397,0.2914,0.50151,0.45223,0.13769,0.49756,0.125,0.5144,0.375,0.45143,0.38793,0.49756,0.875,0.44902,0.86273,0.44822,0.61297,0.5144,0.625,0.35377,0.73318,0.22778,0.50491,0.21086,0.43713,0.34645,0.54618,0.26308,0.34488,0.1784,0.42909,0.18666,0.46097,0.2603,0.43904,0.26439,0.53248,0.19213,0.49947,0.19688,0.53136,0.27533,0.62521,0.34693,0.53683,0.25017,0.53942,0.27641,0.54285,0.4409,0.5342,0.15861,0.52202,0.17591,0.52258,0.21071,0.5339,0.25284,0.53277,0.33742,0.50322,0.23721,0.4936,0.27507,0.49881,0.43393,0.50026,0.14318,0.48995,0.15367,0.48384,0.19384,0.489,0.24051,0.49979,0.3082,0.46142,0.2314,0.49139,0.22735,0.46377,0.30277,0.37246,0.29951,0.64034,0.22859,0.55301,0.22989,0.52436,0.30711,0.55071,0.875,0.17969,0.875,0.28271,0.625,0.27637,0.625,0.17969,0.875,0.28271,0.625,0.27637,0.625,0.17969,0.875,0.17969,0.17969,0.125,0.28271,0.125,0.27637,0.375,0.17969,0.375,0.125,0.125,0.375,0.125,0.375,0.375,0.125,0.375,0.625,0.125,0.875,0.125,0.875,0.375,0.625,0.375,0.875,0.875,0.625,0.875,0.625,0.625,0.875,0.625,0.375,0.875,0.125,0.875,0.125,0.625,0.375,0.625,0.0625,0.125,0.18677,0.125,0.18567,0.375,0.0625,0.375,0.30884,0.125,0.42432,0.125,0.40747,0.375,0.30334,0.375,0.42432,0.875,0.30884,0.875,0.30334,0.625,0.40747,0.625,0.18677,0.875,0.0625,0.875,0.0625,0.625,0.18567,0.625,0.875,0.57568,0.875,0.69116,0.625,0.69666,0.625,0.59253,0.875,0.81323,0.875,0.9375,0.625,0.9375,0.625,0.81433,0.125,0.9375,0.125,0.81323,0.375,0.81433,0.375,0.9375,0.125,0.69116,0.125,0.57568,0.375,0.59253,0.375,0.69666,0.875,0.57568,0.875,0.69116,0.625,0.69666,0.625,0.59253,0.875,0.81323,0.875,0.9375,0.625,0.9375,0.625,0.81433,0.125,0.9375,0.125,0.81323,0.375,0.81433,0.375,0.9375,0.125,0.69116,0.125,0.57568,0.375,0.59253,0.375,0.69666,0.57568,0.125,0.69116,0.125,0.69666,0.375,0.59253,0.375,0.81323,0.125,0.9375,0.125,0.9375,0.375,0.81433,0.375,0.9375,0.875,0.81323,0.875,0.81433,0.625,0.9375,0.625,0.69116,0.875,0.57568,0.875,0.59253,0.625,0.69666,0.625,0.50244,0.125,0.54321,0.125,0.53772,0.375,0.4856,0.375,0.57739,0.125,0.60791,0.125,0.60645,0.375,0.57629,0.375,0.60791,0.875,0.57739,0.875,0.57629,0.625,0.60645,0.625,0.54321,0.875,0.50244,0.875,0.4856,0.625,0.53772,0.625,0.125,0.37256,0.125,0.36328,0.375,0.36328,0.375,0.37402,0.125,0.37256,0.125,0.36328,0.375,0.36328,0.375,0.37402,0.37256,0.875,0.36328,0.875,0.36328,0.625,0.37402,0.625,0.82031,0.875,0.71728,0.875,0.72363,0.625,0.82031,0.625,0.62744,0.125,0.63672,0.125,0.63672,0.375,0.62598,0.375,0.875,0.39209,0.875,0.42261,0.625,0.42371,0.625,0.39355,0.875,0.45679,0.875,0.49756,0.625,0.5144,0.625,0.46228,0.125,0.49756,0.125,0.45679,0.375,0.46228,0.375,0.5144,0.125,0.42261,0.125,0.39209,0.375,0.39355,0.375,0.42371,0.875,0.39209,0.875,0.42261,0.625,0.42371,0.625,0.39355,0.875,0.45679,0.875,0.49756,0.625,0.5144,0.625,0.46228,0.125,0.49756,0.125,0.45679,0.375,0.46228,0.375,0.5144,0.125,0.42261,0.125,0.39209,0.375,0.39355,0.375,0.42371,0.39209,0.125,0.42261,0.125,0.42371,0.375,0.39355,0.375,0.45679,0.125,0.49756,0.125,0.5144,0.375,0.46228,0.375,0.49756,0.875,0.45679,0.875,0.46228,0.625,0.5144,0.625,0.42261,0.875,0.39209,0.875,0.39355,0.625,0.42371,0.625,0.875,0.34131,0.875,0.35547,0.625,0.35547,0.625,0.33496,0.125,0.28271,0.125,0.17969,0.375,0.17969,0.375,0.27637,0.875,0.34131,0.875,0.35547,0.625,0.35547,0.625,0.33496,0.125,0.28271,0.125,0.17969,0.375,0.17969,0.375,0.27637,0.34131,0.125,0.35547,0.125,0.35547,0.375,0.33496,0.375,0.28271,0.875,0.17969,0.875,0.17969,0.625,0.27637,0.625,0.71728,0.125,0.82031,0.125,0.82031,0.375,0.72363,0.375,0.65869,0.875,0.64453,0.875,0.64453,0.625,0.66504,0.625,0.125,0.35547,0.125,0.34131,0.375,0.33496,0.375,0.35547,0.125,0.35547,0.125,0.34131,0.375,0.33496,0.375,0.35547,0.35547,0.875,0.34131,0.875,0.33496,0.625,0.35547,0.625,0.64453,0.125,0.65869,0.125,0.66504,0.375,0.64453,0.375,0.875,0.36328,0.875,0.37256,0.625,0.37402,0.625,0.36328,0.875,0.36328,0.875,0.37256,0.625,0.37402,0.625,0.36328,0.36328,0.125,0.37256,0.125,0.37402,0.375,0.36328,0.375,0.63672,0.875,0.62744,0.875,0.62598,0.625,0.63672,0.625,0.125,0.125,0.375,0.125,0.375,0.375,0.125,0.375,0.625,0.125,0.875,0.125,0.875,0.375,0.625,0.375,0.875,0.875,0.625,0.875,0.625,0.625,0.875,0.625,0.375,0.875,0.125,0.875,0.125,0.625,0.375,0.625,0.0625,0.125,0.18677,0.125,0.18567,0.375,0.0625,0.375,0.30884,0.125,0.42432,0.125,0.40747,0.375,0.30334,0.375,0.42432,0.875,0.30884,0.875,0.30334,0.625,0.40747,0.625,0.18677,0.875,0.0625,0.875,0.0625,0.625,0.18567,0.625,0.875,0.57568,0.875,0.69116,0.625,0.69666,0.625,0.59253,0.875,0.81323,0.875,0.9375,0.625,0.9375,0.625,0.81433,0.125,0.9375,0.125,0.81323,0.375,0.81433,0.375,0.9375,0.125,0.69116,0.125,0.57568,0.375,0.59253,0.375,0.69666,0.875,0.57568,0.875,0.69116,0.625,0.69666,0.625,0.59253,0.875,0.81323,0.875,0.9375,0.625,0.9375,0.625,0.81433,0.125,0.9375,0.125,0.81323,0.375,0.81433,0.375,0.9375,0.125,0.69116,0.125,0.57568,0.375,0.59253,0.375,0.69666,0.57568,0.125,0.69116,0.125,0.69666,0.375,0.59253,0.375,0.81323,0.125,0.9375,0.125,0.9375,0.375,0.81433,0.375,0.9375,0.875,0.81323,0.875,0.81433,0.625,0.9375,0.625,0.69116,0.875,0.57568,0.875,0.59253,0.625,0.69666,0.625,0.50244,0.125,0.54321,0.125,0.53772,0.375,0.4856,0.375,0.57739,0.125,0.60791,0.125,0.60645,0.375,0.57629,0.375,0.60791,0.875,0.57739,0.875,0.57629,0.625,0.60645,0.625,0.54321,0.875,0.50244,0.875,0.4856,0.625,0.53772,0.625,0.85829,0.3269,0.875,0.32422,0.625,0.32422,0.59922,0.33726,0.125,0.37256,0.125,0.36328,0.375,0.36328,0.375,0.37402,0.8554,0.31945,0.875,0.32422,0.625,0.32422,0.59362,0.3223,0.125,0.37256,0.125,0.36328,0.375,0.36328,0.375,0.37402,0.31312,0.13648,0.32422,0.125,0.32422,0.375,0.30858,0.38688,0.37256,0.875,0.36328,0.875,0.36328,0.625,0.37402,0.625,0.62744,0.125,0.63672,0.125,0.63672,0.375,0.62598,0.375,0.6655,0.86312,0.67578,0.875,0.67578,0.625,0.6489,0.61337,0.875,0.39209,0.875,0.42261,0.625,0.42371,0.625,0.39355,0.875,0.45679,0.875,0.49756,0.625,0.5144,0.625,0.46228,0.125,0.49756,0.125,0.45679,0.375,0.46228,0.375,0.5144,0.125,0.42261,0.125,0.39209,0.375,0.39355,0.375,0.42371,0.875,0.39209,0.875,0.42261,0.625,0.42371,0.625,0.39355,0.875,0.45679,0.875,0.49756,0.625,0.5144,0.625,0.46228,0.125,0.49756,0.125,0.45679,0.375,0.46228,0.375,0.5144,0.125,0.42261,0.125,0.39209,0.375,0.39355,0.375,0.42371,0.39209,0.125,0.42261,0.125,0.42371,0.375,0.39355,0.375,0.45679,0.125,0.49756,0.125,0.5144,0.375,0.46228,0.375,0.49756,0.875,0.45679,0.875,0.46228,0.625,0.5144,0.625,0.42261,0.875,0.39209,0.875,0.39355,0.625,0.42371,0.625,0.875,0.34766,0.875,0.35547,0.625,0.35547,0.625,0.34766,0.125,0.33984,0.125,0.33203,0.375,0.33203,0.375,0.33984,0.875,0.34766,0.875,0.35547,0.625,0.35547,0.625,0.34766,0.125,0.33984,0.125,0.33203,0.375,0.33203,0.375,0.33984,0.34766,0.125,0.35547,0.125,0.35547,0.375,0.34766,0.375,0.33984,0.875,0.33203,0.875,0.33203,0.625,0.33984,0.625,0.66016,0.125,0.66797,0.125,0.66797,0.375,0.66016,0.375,0.65234,0.875,0.64453,0.875,0.64453,0.625,0.65234,0.625,0.125,0.35547,0.125,0.34766,0.375,0.34766,0.375,0.35547,0.125,0.35547,0.125,0.34766,0.375,0.34766,0.375,0.35547,0.35547,0.875,0.34766,0.875,0.34766,0.625,0.35547,0.625,0.64453,0.125,0.65234,0.125,0.65234,0.375,0.64453,0.375,0.875,0.36328,0.875,0.37256,0.625,0.37402,0.625,0.36328,0.875,0.36328,0.875,0.37256,0.625,0.37402,0.625,0.36328,0.36328,0.125,0.37256,0.125,0.37402,0.375,0.36328,0.375,0.63672,0.875,0.62744,0.875,0.62598,0.625,0.63672,0.625,0.875,0.33203,0.875,0.33984,0.625,0.33984,0.625,0.33203,0.875,0.33203,0.875,0.33984,0.625,0.33984,0.625,0.33203,0.33203,0.125,0.33984,0.125,0.33984,0.375,0.33203,0.375,0.66797,0.875,0.66016,0.875,0.66016,0.625,0.66797,0.625,0.125,0.32422,0.12359,0.32659,0.36453,0.33694,0.375,0.32422,0.125,0.32422,0.12108,0.31905,0.35931,0.32189,0.375,0.32422,0.32422,0.875,0.31083,0.86423,0.3063,0.61462,0.32422,0.625,0.67578,0.125,0.66853,0.13735,0.65193,0.38761,0.67578,0.375,0.28098,0.36665,0.34057,0.37783,0.66726,0.33684,0.46812,0.33806,0.18458,0.53599,0.17191,0.47278,0.25341,0.56023,0.25889,0.74625,0.22239,0.5452,0.22933,0.47446,0.28009,0.25959,0.27335,0.44753,0.18529,0.52516,0.26038,0.52722,0.32263,0.41129,0.14302,0.39958,0.34202,0.5307,0.4106,0.53596,0.69404,0.40363,0.4961,0.41284,0.36374,0.49162,0.35255,0.56838,0.53925,0.45617,0.55579,0.26641,0.28183,0.44328,0.28941,0.514,0.5288,0.73745,0.51165,0.54889,0.13565,0.36392,0.2035,0.36218,0.29656,0.33603,0.12119,0.33157,0.77336,0.332,0.54879,0.33334,0.44209,0.36017,0.59877,0.36339,0.33761,0.33203,0.12431,0.32859,0.12832,0.35393,0.28527,0.35702,0.60846,0.81254,0.59876,0.59353,0.4755,0.54574,0.47817,0.7033,0.60791,0.41002,0.6171,0.1902,0.50113,0.30391,0.5,0.46285,0.78064,0.35268,0.55656,0.35655,0.46074,0.41588,0.61823,0.41847,0.34518,0.35543,0.13105,0.34976,0.14629,0.41039,0.30343,0.41318,0.28609,0.17161,0.284,0.38897,0.24177,0.40854,0.24074,0.25464,0.28474,0.59907,0.28801,0.81787,0.24603,0.71735,0.24353,0.56277,0.32015,0.39195,0.21414,0.4197,0.24496,0.43059,0.41462,0.39731,0.13053,0.38155,0.13757,0.40913,0.17379,0.41262,0.22545,0.3867,0.33417,0.4929,0.20168,0.44513,0.21063,0.48122,0.33862,0.58884,0.37688,0.42319,0.26651,0.53331,0.25795,0.57453,0.37499,0.52142,0.35124,0.48479,0.25607,0.54488,0.29087,0.55162,0.44705,0.48912,0.16048,0.47566,0.17602,0.53666,0.21462,0.5388,0.25571,0.4803,0.19461,0.4309,0.15399,0.4508,0.14832,0.42422,0.1929,0.34107,0.20172,0.61225,0.16518,0.51344,0.15802,0.48548,0.19755,0.52129,0.38141,0.46253,0.39047,0.46015,0.39433,0.47064,0.38541,0.47309,0.35996,0.34458,0.36807,0.34256,0.36917,0.35348,0.36089,0.35541,0.35822,0.32674,0.36592,0.32464,0.36698,0.33274,0.35907,0.33482,0.35262,0.29951,0.35913,0.2975,0.36127,0.30491,0.35452,0.30692,0.36168,0.36569,0.37011,0.36387,0.37089,0.37297,0.36233,0.37472,0.35425,0.39159,0.34482,0.39335,0.3444,0.38623,0.35368,0.38444,0.35578,0.4055,0.34608,0.40736,0.34538,0.40034,0.35496,0.39855,0.36958,0.42525,0.37892,0.42328,0.38138,0.43221,0.37207,0.43428,0.3665,0.41036,0.37572,0.40854,0.37704,0.41539,0.36774,0.41728,0.39716,0.52008,0.38857,0.52225,0.38282,0.51151,0.39165,0.50918,0.40763,0.54128,0.3994,0.54306,0.39409,0.53275,0.40249,0.53076,0.37489,0.44349,0.38413,0.44131,0.3871,0.45044,0.37795,0.45272,0.38607,0.49804,0.377,0.50051,0.37138,0.48937,0.3807,0.48678,0.35609,0.31363,0.36321,0.31157,0.36471,0.31782,0.35728,0.31991,0.37254,0.38818,0.36369,0.38983,0.36296,0.38265,0.37167,0.38097,0.37459,0.4019,0.36549,0.40364,0.36454,0.39676,0.37352,0.39509,0.41383,0.51587,0.40576,0.51791,0.40047,0.50686,0.40874,0.50468,0.42381,0.53777,0.41585,0.53949,0.4109,0.52877,0.41877,0.5269,0.40365,0.49325,0.39515,0.49557,0.39002,0.48419,0.39876,0.48177,0.39771,0.45825,0.40314,0.45682,0.40683,0.46722,0.40147,0.46869,0.37455,0.34094,0.37942,0.33973,0.38076,0.35078,0.37579,0.35194,0.37207,0.32297,0.37669,0.32171,0.37806,0.32983,0.37331,0.33108,0.36418,0.29595,0.36776,0.29484,0.37071,0.3021,0.36666,0.3033,0.37685,0.3624,0.38191,0.36131,0.38288,0.37053,0.37774,0.37158,0.38638,0.4217,0.39198,0.42052,0.39441,0.4293,0.38882,0.43055,0.38309,0.40708,0.38861,0.40599,0.39006,0.41274,0.38448,0.41388,0.39152,0.43957,0.39707,0.43826,0.39992,0.44725,0.39443,0.44861,0.36891,0.30993,0.37319,0.3087,0.37512,0.3149,0.37066,0.31615,0.41454,0.44655,0.40482,0.41225,0.40527,0.41092,0.41707,0.45237,0.42633,0.48707,0.42206,0.4753,0.42265,0.47514,0.4269,0.48692,0.41813,0.46412,0.41461,0.45381,0.41521,0.45365,0.41873,0.46396,0.41152,0.44436,0.40877,0.4355,0.40939,0.43536,0.41213,0.44421,0.40619,0.42668,0.40381,0.41802,0.40443,0.41789,0.40681,0.42654,0.40184,0.41035,0.40028,0.40368,0.4009,0.40356,0.40246,0.41022,0.39886,0.39724,0.39746,0.39062,0.39806,0.3905,0.39947,0.39713,0.39612,0.38378,0.39487,0.37649,0.39545,0.37638,0.39671,0.38367,0.39372,0.36833,0.39259,0.35899,0.39315,0.35887,0.39429,0.36821,0.39125,0.34834,0.38969,0.33716,0.39022,0.33703,0.3918,0.34821,0.38808,0.32719,0.38643,0.31905,0.38695,0.31891,0.38861,0.32705,0.38454,0.31226,0.38221,0.30609,0.38268,0.30595,0.38504,0.31212,0.37925,0.29956,0.37595,0.29232,0.37617,0.29225,0.3797,0.29942,0.43701,0.50788,0.43624,0.5097,0.43181,0.49246,0.42425,0.46282,0.43462,0.508,0.43079,0.49886,0.43135,0.49872,0.43416,0.50445,0.38611,0.32091,0.38472,0.3131,0.38182,0.30526,0.38355,0.31501,0.39988,0.378,0.39164,0.34439,0.39432,0.35665,0.41028,0.4162,0.40587,0.40899,0.40508,0.4013,0.41954,0.45272,0.41977,0.45793,0.41227,0.441,0.41029,0.43599,0.40439,0.41479,0.40452,0.41346,0.40862,0.43151,0.40732,0.42781,0.40458,0.41788,0.40441,0.41626,0.42265,0.47514,0.42102,0.46942,0.42493,0.48001,0.4269,0.48692,0.41521,0.45365,0.41423,0.45012,0.41744,0.45937,0.41873,0.46396,0.40939,0.43536,0.40906,0.4341,0.41143,0.44167,0.41213,0.44421,0.40443,0.41789,0.40457,0.4183,0.4068,0.42638,0.40681,0.42654,0.4009,0.40356,0.4016,0.4061,0.40285,0.4116,0.40246,0.41022,0.39806,0.3905,0.39935,0.39509,0.40045,0.40066,0.39947,0.39713,0.39545,0.37638,0.39741,0.38329,0.39833,0.38938,0.39671,0.38367,0.39315,0.35887,0.39554,0.36735,0.39661,0.37637,0.39429,0.36821,0.39022,0.33703,0.39051,0.3385,0.39342,0.35417,0.3918,0.34821,0.38695,0.31891,0.38653,0.31798,0.38811,0.32583,0.38861,0.32705,0.38268,0.30595,0.38262,0.3061,0.38486,0.31203,0.38504,0.31212,0.37617,0.29225,0.37932,0.30252,0.38001,0.30039,0.3797,0.29942,0.42615,0.4729,0.41958,0.44982,0.40001,0.37844,0.41066,0.41587,0.43135,0.49872,0.42903,0.49056,0.42965,0.48862,0.43303,0.50053,0.38492,0.38587,0.37961,0.38686,0.37863,0.37963,0.38385,0.37862,0.38733,0.39945,0.38187,0.4005,0.3807,0.39375,0.38609,0.39274,0.42511,0.51303,0.42028,0.51425,0.41535,0.50293,0.42032,0.50162,0.43435,0.53548,0.42998,0.53643,0.42507,0.52541,0.4298,0.52429,0.41556,0.49001,0.41045,0.4914,0.40575,0.47983,0.41099,0.47837,0.40797,0.45555,0.41219,0.45444,0.41575,0.46477,0.41159,0.46591,0.38374,0.33865,0.38752,0.3377,0.38904,0.34885,0.38517,0.34975,0.38079,0.32059,0.38438,0.31961,0.38597,0.32775,0.38228,0.32872,0.37112,0.29381,0.37427,0.29284,0.37745,0.30009,0.3743,0.30103,0.38641,0.36033,0.39034,0.35948,0.39144,0.36879,0.38744,0.3696,0.39696,0.41947,0.40132,0.41855,0.40371,0.42723,0.39937,0.4282,0.39353,0.40502,0.39782,0.40417,0.39936,0.41085,0.39502,0.41174,0.402,0.4371,0.40631,0.43608,0.40908,0.44497,0.4048,0.44603,0.37699,0.3076,0.38031,0.30664,0.38256,0.31282,0.37909,0.31379,0.3621,0.4676,0.37175,0.46506,0.37589,0.4757,0.36637,0.47831,0.34267,0.3489,0.35131,0.34674,0.35206,0.35746,0.34323,0.35952,0.34181,0.33121,0.35001,0.32898,0.35063,0.33704,0.34219,0.33926,0.33916,0.30366,0.34589,0.30158,0.34733,0.30906,0.34013,0.3112,0.3437,0.3696,0.35269,0.36764,0.35319,0.37658,0.34406,0.37844,0.34967,0.42946,0.35963,0.42736,0.36214,0.43649,0.35222,0.4387,0.34685,0.41424,0.35668,0.4123,0.35782,0.41929,0.3479,0.42131,0.35517,0.44813,0.36503,0.44581,0.36818,0.45515,0.35841,0.45758,0.34089,0.31802,0.34849,0.31583,0.34934,0.32213,0.34141,0.32436,0.33539,0.39511,0.3258,0.39669,0.32568,0.38963,0.33512,0.38803,0.33637,0.40923,0.32658,0.41095,0.3261,0.40374,0.3358,0.40213,0.37997,0.52442,0.37149,0.52663,0.36519,0.51613,0.374,0.51383,0.39118,0.54485,0.38308,0.5467,0.37749,0.53683,0.38569,0.53473,0.36793,0.50298,0.35875,0.50533,0.35249,0.49432,0.36206,0.49195,3.5556,4.185,-3.9475,4.185,-3.6115,-0.29342,1.5622,-0.29342,1.5622,-2.1967,-0.23222,-2.8685,-2.0885,-2.1744,-2.0661,-0.96517,-3.5668,-0.96517,-3.4323,-3.2716,-0.23222,-4.4135,2.9732,-3.182,3.2645,1.0725,-2.3573,1.0725,-2.4692,2.6399,3.4435,2.6399,3.5556,4.185,-3.9475,4.185,-3.6115,-0.29342,1.5622,-0.29342,1.5622,-2.1967,-0.23222,-2.8685,-2.0885,-2.1744,-2.0661,-0.96517,-3.5668,-0.96517,-3.4323,-3.2716,-0.23222,-4.4135,2.9732,-3.182,3.2645,1.0725,-2.3573,1.0725,-2.4692,2.6399,3.4435,2.6399,-0.22761,6.558,-6.1359,6.558,-5.0006,-5.2182,-0.23015,-6.7874,4.5489,-5.2182,5.6842,6.558,-0.22761,6.558,-6.1359,6.558,-5.0006,-5.2182,-0.23015,-6.7874,4.5489,-5.2182,5.6842,6.558,1,0,0,0,1,1,0,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1]],\n\n    \"faces\": [10,1,2398,7190,0,6,2825,8041,10,2398,1200,4794,0,2825,1415,5645,10,2405,7190,4797,0,2832,8041,5648,10,7190,4794,601,0,8041,5645,816,10,2399,25,2400,0,2826,65,2827,10,7191,2400,1201,0,8042,2827,1416,10,1200,2399,7191,0,1415,2826,8042,10,4794,7191,4795,0,5645,8042,5646,10,12,2402,7192,0,28,2829,8043,10,2402,1202,4796,0,2829,1417,5647,10,2401,7192,4795,0,2828,8043,5646,10,7192,4796,601,0,8043,5647,816,10,2403,29,2404,0,2830,69,2831,10,7193,2404,1203,0,8044,2831,1418,10,1202,2403,7193,0,1417,2830,8044,10,4796,7193,4797,0,5647,8044,5648,10,25,2406,7194,0,65,2833,8045,10,2406,1204,4798,0,2833,1419,5649,10,2400,7194,4801,0,2827,8045,5652,10,7194,4798,602,0,8045,5649,817,10,2407,0,2408,0,2834,7,2835,10,7195,2408,1205,0,8046,2835,1420,10,1204,2407,7195,0,1419,2834,8046,10,4798,7195,4799,0,5649,8046,5650,10,30,2410,7196,0,46,2837,8047,10,2410,1206,4800,0,2837,1421,5651,10,2409,7196,4799,0,2836,8047,5650,10,7196,4800,602,0,8047,5651,817,10,2411,12,2401,0,2838,28,2828,10,7197,2401,1201,0,8048,2828,1416,10,1206,2411,7197,0,1421,2838,8048,10,4800,7197,4801,0,5651,8048,5652,10,2,2412,7198,0,9,2839,8049,10,2412,1207,4802,0,2839,1422,5653,10,2417,7198,4805,0,2844,8049,5656,10,7198,4802,603,0,8049,5653,818,10,2413,27,2414,0,2840,67,2841,10,7199,2414,1208,0,8050,2841,1423,10,1207,2413,7199,0,1422,2840,8050,10,4802,7199,4803,0,5653,8050,5654,10,12,2411,7200,0,28,2838,8051,10,2411,1206,4804,0,2838,1421,5655,10,2415,7200,4803,0,2842,8051,5654,10,7200,4804,603,0,8051,5655,818,10,2410,30,2416,0,2837,46,2843,10,7201,2416,1209,0,8052,2843,1424,10,1206,2410,7201,0,1421,2837,8052,10,4804,7201,4805,0,5655,8052,5656,10,27,2418,7202,0,67,2845,8053,10,2418,1210,4806,0,2845,1425,5657,10,2414,7202,4809,0,2841,8053,5660,10,7202,4806,604,0,8053,5657,819,10,2419,3,2420,0,2846,8,2847,10,7203,2420,1211,0,8054,2847,1426,10,1210,2419,7203,0,1425,2846,8054,10,4806,7203,4807,0,5657,8054,5658,10,29,2403,7204,0,69,2830,8055,10,2403,1202,4808,0,2830,1417,5659,10,2421,7204,4807,0,2848,8055,5658,10,7204,4808,604,0,8055,5659,819,10,2402,12,2415,0,2829,28,2842,10,7205,2415,1208,0,8056,2842,1423,10,1202,2402,7205,0,1417,2829,8056,10,4808,7205,4809,0,5659,8056,5660,10,0,2422,7206,0,10,2849,8057,10,2422,1212,4810,0,2849,1427,5661,10,2408,7206,4813,0,5228,8057,5664,10,7206,4810,605,0,8057,5661,820,10,2423,31,2424,0,2850,71,2851,10,7207,2424,1213,0,8058,2851,1428,10,1212,2423,7207,0,1427,2850,8058,10,4810,7207,4811,0,5661,8058,5662,10,13,2426,7208,0,29,2853,8059,10,2426,1214,4812,0,2853,1429,5663,10,2425,7208,4811,0,2852,8059,5662,10,7208,4812,605,0,8059,5663,820,10,2427,30,2409,0,2854,70,5227,10,7209,2409,1205,0,8060,5227,2616,10,1214,2427,7209,0,1429,2854,8060,10,4812,7209,4813,0,5663,8060,5664,10,31,2428,7210,0,71,2855,8061,10,2428,1215,4814,0,2855,1430,5665,10,2424,7210,4817,0,2851,8061,5668,10,7210,4814,606,0,8061,5665,821,10,2429,4,2430,0,2856,13,2857,10,7211,2430,1216,0,8062,2857,1431,10,1215,2429,7211,0,1430,2856,8062,10,4814,7211,4815,0,5665,8062,5666,10,38,2432,7212,0,54,2859,8063,10,2432,1217,4816,0,2859,1432,5667,10,2431,7212,4815,0,2858,8063,5666,10,7212,4816,606,0,8063,5667,821,10,2433,13,2425,0,2860,29,2852,10,7213,2425,1213,0,8064,2852,1428,10,1217,2433,7213,0,1432,2860,8064,10,4816,7213,4817,0,5667,8064,5668,10,7,2434,7214,0,19,2861,8065,10,2434,1218,4818,0,2861,1433,5669,10,2439,7214,4821,0,2866,8065,5672,10,7214,4818,607,0,8065,5669,822,10,2435,28,2436,0,2862,68,2863,10,7215,2436,1219,0,8066,2863,1434,10,1218,2435,7215,0,1433,2862,8066,10,4818,7215,4819,0,5669,8066,5670,10,13,2433,7216,0,29,2860,8067,10,2433,1217,4820,0,2860,1432,5671,10,2437,7216,4819,0,2864,8067,5670,10,7216,4820,607,0,8067,5671,822,10,2432,38,2438,0,2859,54,2865,10,7217,2438,1220,0,8068,2865,1435,10,1217,2432,7217,0,1432,2859,8068,10,4820,7217,4821,0,5671,8068,5672,10,28,2440,7218,0,68,2867,8069,10,2440,1221,4822,0,2867,1436,5673,10,2436,7218,4825,0,2863,8069,5676,10,7218,4822,608,0,8069,5673,823,10,2441,2,2417,0,2868,11,5231,10,7219,2417,1209,0,8070,5231,2618,10,1221,2441,7219,0,1436,2868,8070,10,4822,7219,4823,0,5673,8070,5674,10,30,2427,7220,0,70,2854,8071,10,2427,1214,4824,0,2854,1429,5675,10,2416,7220,4823,0,5232,8071,5674,10,7220,4824,608,0,8071,5675,823,10,2426,13,2437,0,2853,29,2864,10,7221,2437,1219,0,8072,2864,1434,10,1214,2426,7221,0,1429,2853,8072,10,4824,7221,4825,0,5675,8072,5676,10,4,2429,7222,0,12,5239,8073,10,2429,1215,4826,0,5239,2622,5677,10,2447,7222,4829,0,2874,8073,5680,10,7222,4826,609,0,8073,5677,824,10,2428,31,2442,0,5240,47,2869,10,7223,2442,1222,0,8074,2869,1437,10,1215,2428,7223,0,2622,5240,8074,10,4826,7223,4827,0,5677,8074,5678,10,14,2444,7224,0,30,2871,8075,10,2444,1223,4828,0,2871,1438,5679,10,2443,7224,4827,0,2870,8075,5678,10,7224,4828,609,0,8075,5679,824,10,2445,35,2446,0,2872,51,2873,10,7225,2446,1224,0,8076,2873,1439,10,1223,2445,7225,0,1438,2872,8076,10,4828,7225,4829,0,5679,8076,5680,10,31,2423,7226,0,47,5237,8077,10,2423,1212,4830,0,5237,2621,5681,10,2442,7226,4833,0,2869,8077,5684,10,7226,4830,610,0,8077,5681,825,10,2422,0,2407,0,5238,0,5225,10,7227,2407,1204,0,8078,5225,2615,10,1212,2422,7227,0,2621,5238,8078,10,4830,7227,4831,0,5681,8078,5682,10,25,2448,7228,0,41,2875,8079,10,2448,1225,4832,0,2875,1440,5683,10,2406,7228,4831,0,5226,8079,5682,10,7228,4832,610,0,8079,5683,825,10,2449,14,2443,0,2876,30,2870,10,7229,2443,1222,0,8080,2870,1437,10,1225,2449,7229,0,1440,2876,8080,10,4832,7229,4833,0,5683,8080,5684,10,1,2450,7230,0,1,2877,8081,10,2450,1226,4834,0,2877,1441,5685,10,2398,7230,4837,0,5222,8081,5688,10,7230,4834,611,0,8081,5685,826,10,2451,26,2452,0,2878,42,2879,10,7231,2452,1227,0,8082,2879,1442,10,1226,2451,7231,0,1441,2878,8082,10,4834,7231,4835,0,5685,8082,5686,10,14,2449,7232,0,30,2876,8083,10,2449,1225,4836,0,2876,1440,5687,10,2453,7232,4835,0,2880,8083,5686,10,7232,4836,611,0,8083,5687,826,10,2448,25,2399,0,2875,41,5221,10,7233,2399,1200,0,8084,5221,2613,10,1225,2448,7233,0,1440,2875,8084,10,4836,7233,4837,0,5687,8084,5688,10,26,2454,7234,0,42,2881,8085,10,2454,1228,4838,0,2881,1443,5689,10,2452,7234,4841,0,2879,8085,5692,10,7234,4838,612,0,8085,5689,827,10,2455,5,2456,0,2882,14,2883,10,7235,2456,1229,0,8086,2883,1444,10,1228,2455,7235,0,1443,2882,8086,10,4838,7235,4839,0,5689,8086,5690,10,35,2445,7236,0,51,2872,8087,10,2445,1223,4840,0,2872,1438,5691,10,2457,7236,4839,0,2884,8087,5690,10,7236,4840,612,0,8087,5691,827,10,2444,14,2453,0,2871,30,2880,10,7237,2453,1227,0,8088,2880,1442,10,1223,2444,7237,0,1438,2871,8088,10,4840,7237,4841,0,5691,8088,5692,10,6,2458,7238,0,16,2885,8089,10,2458,1230,4842,0,2885,1445,5693,10,2465,7238,4845,0,2892,8089,5696,10,7238,4842,613,0,8089,5693,828,10,2459,33,2460,0,2886,49,2887,10,7239,2460,1231,0,8090,2887,1446,10,1230,2459,7239,0,1445,2886,8090,10,4842,7239,4843,0,5693,8090,5694,10,15,2462,7240,0,31,2889,8091,10,2462,1232,4844,0,2889,1447,5695,10,2461,7240,4843,0,2888,8091,5694,10,7240,4844,613,0,8091,5695,828,10,2463,36,2464,0,2890,52,2891,10,7241,2464,1233,0,8092,2891,1448,10,1232,2463,7241,0,1447,2890,8092,10,4844,7241,4845,0,5695,8092,5696,10,33,2466,7242,0,49,2893,8093,10,2466,1234,4846,0,2893,1449,5697,10,2460,7242,4849,0,2887,8093,5700,10,7242,4846,614,0,8093,5697,829,10,2467,3,2419,0,2894,3,5233,10,7243,2419,1210,0,8094,5233,2619,10,1234,2467,7243,0,1449,2894,8094,10,4846,7243,4847,0,5697,8094,5698,10,27,2468,7244,0,43,2895,8095,10,2468,1235,4848,0,2895,1450,5699,10,2418,7244,4847,0,5234,8095,5698,10,7244,4848,614,0,8095,5699,829,10,2469,15,2461,0,2896,31,2888,10,7245,2461,1231,0,8096,2888,1446,10,1235,2469,7245,0,1450,2896,8096,10,4848,7245,4849,0,5699,8096,5700,10,2,2441,7246,0,2,5243,8097,10,2441,1221,4850,0,5243,2624,5701,10,2412,7246,4853,0,5230,8097,5704,10,7246,4850,615,0,8097,5701,830,10,2440,28,2470,0,5244,44,2897,10,7247,2470,1236,0,8098,2897,1451,10,1221,2440,7247,0,2624,5244,8098,10,4850,7247,4851,0,5701,8098,5702,10,15,2469,7248,0,31,2896,8099,10,2469,1235,4852,0,2896,1450,5703,10,2471,7248,4851,0,2898,8099,5702,10,7248,4852,615,0,8099,5703,830,10,2468,27,2413,0,2895,43,5229,10,7249,2413,1207,0,8100,5229,2617,10,1235,2468,7249,0,1450,2895,8100,10,4852,7249,4853,0,5703,8100,5704,10,28,2435,7250,0,44,5241,8101,10,2435,1218,4854,0,5241,2623,5705,10,2470,7250,4857,0,2897,8101,5708,10,7250,4854,616,0,8101,5705,831,10,2434,7,2472,0,5242,18,2899,10,7251,2472,1237,0,8102,2899,1452,10,1218,2434,7251,0,2623,5242,8102,10,4854,7251,4855,0,5705,8102,5706,10,36,2463,7252,0,52,2890,8103,10,2463,1232,4856,0,2890,1447,5707,10,2473,7252,4855,0,2900,8103,5706,10,7252,4856,616,0,8103,5707,831,10,2462,15,2471,0,2889,31,2898,10,7253,2471,1236,0,8104,2898,1451,10,1232,2462,7253,0,1447,2889,8104,10,4856,7253,4857,0,5707,8104,5708,10,5,2455,7254,0,15,5247,8105,10,2455,1228,4858,0,5247,2626,5709,10,2479,7254,4861,0,2906,8105,5712,10,7254,4858,617,0,8105,5709,832,10,2454,26,2474,0,5248,66,2901,10,7255,2474,1238,0,8106,2901,1453,10,1228,2454,7255,0,2626,5248,8106,10,4858,7255,4859,0,5709,8106,5710,10,16,2476,7256,0,32,2903,8107,10,2476,1239,4860,0,2903,1454,5711,10,2475,7256,4859,0,2902,8107,5710,10,7256,4860,617,0,8107,5711,832,10,2477,37,2478,0,2904,53,2905,10,7257,2478,1240,0,8108,2905,1455,10,1239,2477,7257,0,1454,2904,8108,10,4860,7257,4861,0,5711,8108,5712,10,26,2451,7258,0,66,5245,8109,10,2451,1226,4862,0,5245,2625,5713,10,2474,7258,4865,0,2901,8109,5716,10,7258,4862,618,0,8109,5713,833,10,2450,1,2405,0,5246,4,5223,10,7259,2405,1203,0,8110,5223,2614,10,1226,2450,7259,0,2625,5246,8110,10,4862,7259,4863,0,5713,8110,5714,10,29,2480,7260,0,45,2907,8111,10,2480,1241,4864,0,2907,1456,5715,10,2404,7260,4863,0,5224,8111,5714,10,7260,4864,618,0,8111,5715,833,10,2481,16,2475,0,2908,32,2902,10,7261,2475,1238,0,8112,2902,1453,10,1241,2481,7261,0,1456,2908,8112,10,4864,7261,4865,0,5715,8112,5716,10,3,2467,7262,0,5,5251,8113,10,2467,1234,4866,0,5251,2628,5717,10,2420,7262,4869,0,5236,8113,5720,10,7262,4866,619,0,8113,5717,834,10,2466,33,2482,0,5252,73,2909,10,7263,2482,1242,0,8114,2909,1457,10,1234,2466,7263,0,2628,5252,8114,10,4866,7263,4867,0,5717,8114,5718,10,16,2481,7264,0,32,2908,8115,10,2481,1241,4868,0,2908,1456,5719,10,2483,7264,4867,0,2910,8115,5718,10,7264,4868,619,0,8115,5719,834,10,2480,29,2421,0,2907,45,5235,10,7265,2421,1211,0,8116,5235,2620,10,1241,2480,7265,0,1456,2907,8116,10,4868,7265,4869,0,5719,8116,5720,10,33,2459,7266,0,73,5249,8117,10,2459,1230,4870,0,5249,2627,5721,10,2482,7266,4873,0,2909,8117,5724,10,7266,4870,620,0,8117,5721,835,10,2458,6,2484,0,5250,17,2911,10,7267,2484,1243,0,8118,2911,1458,10,1230,2458,7267,0,2627,5250,8118,10,4870,7267,4871,0,5721,8118,5722,10,37,2477,7268,0,53,2904,8119,10,2477,1239,4872,0,2904,1454,5723,10,2485,7268,4871,0,2912,8119,5722,10,7268,4872,620,0,8119,5723,835,10,2476,16,2483,0,2903,32,2910,10,7269,2483,1242,0,8120,2910,1457,10,1239,2476,7269,0,1454,2903,8120,10,4872,7269,4873,0,5723,8120,5724,10,4,2486,7270,0,13,2913,8121,10,2486,1244,4874,0,2913,1459,5725,10,2430,7270,4877,0,2857,8121,5728,10,7270,4874,621,0,8121,5725,836,10,2487,43,2488,0,2914,79,2915,10,7271,2488,1245,0,8122,2915,1460,10,1244,2487,7271,0,1459,2914,8122,10,4874,7271,4875,0,5725,8122,5726,10,17,2490,7272,0,33,2917,8123,10,2490,1246,4876,0,2917,1461,5727,10,2489,7272,4875,0,2916,8123,5726,10,7272,4876,621,0,8123,5727,836,10,2491,38,2431,0,2918,54,2858,10,7273,2431,1216,0,8124,2858,1431,10,1246,2491,7273,0,1461,2918,8124,10,4876,7273,4877,0,5727,8124,5728,10,43,2492,7274,0,79,2919,8125,10,2492,1247,4878,0,2919,1462,5729,10,2488,7274,4881,0,2915,8125,5732,10,7274,4878,622,0,8125,5729,837,10,2493,10,2494,0,2920,25,2921,10,7275,2494,1248,0,8126,2921,1463,10,1247,2493,7275,0,1462,2920,8126,10,4878,7275,4879,0,5729,8126,5730,10,45,2496,7276,0,61,2923,8127,10,2496,1249,4880,0,2923,1464,5731,10,2495,7276,4879,0,2922,8127,5730,10,7276,4880,622,0,8127,5731,837,10,2497,17,2489,0,2924,33,2916,10,7277,2489,1245,0,8128,2916,1460,10,1249,2497,7277,0,1464,2924,8128,10,4880,7277,4881,0,5731,8128,5732,10,9,2498,7278,0,23,2925,8129,10,2498,1250,4882,0,2925,1465,5733,10,2503,7278,4885,0,2930,8129,5736,10,7278,4882,623,0,8129,5733,838,10,2499,34,2500,0,2926,74,2927,10,7279,2500,1251,0,8130,2927,1466,10,1250,2499,7279,0,1465,2926,8130,10,4882,7279,4883,0,5733,8130,5734,10,17,2497,7280,0,33,2924,8131,10,2497,1249,4884,0,2924,1464,5735,10,2501,7280,4883,0,2928,8131,5734,10,7280,4884,623,0,8131,5735,838,10,2496,45,2502,0,2923,61,2929,10,7281,2502,1252,0,8132,2929,1467,10,1249,2496,7281,0,1464,2923,8132,10,4884,7281,4885,0,5735,8132,5736,10,34,2504,7282,0,74,2931,8133,10,2504,1253,4886,0,2931,1468,5737,10,2500,7282,4889,0,2927,8133,5740,10,7282,4886,624,0,8133,5737,839,10,2505,7,2439,0,2932,19,2866,10,7283,2439,1220,0,8134,2866,1435,10,1253,2505,7283,0,1468,2932,8134,10,4886,7283,4887,0,5737,8134,5738,10,38,2491,7284,0,54,2918,8135,10,2491,1246,4888,0,2918,1461,5739,10,2438,7284,4887,0,2865,8135,5738,10,7284,4888,624,0,8135,5739,839,10,2490,17,2501,0,2917,33,2928,10,7285,2501,1251,0,8136,2928,1466,10,1246,2490,7285,0,1461,2917,8136,10,4888,7285,4889,0,5739,8136,5740,10,39,2508,7286,0,55,2935,8137,10,2508,1255,4890,0,2935,1470,5741,10,2507,7286,4893,0,2934,8137,5744,10,7286,4890,625,0,8137,5741,840,10,2509,65,2662,0,2936,105,3089,10,7287,2662,1332,0,8138,3089,1547,10,1255,2509,7287,0,1470,2936,8138,10,4890,7287,4891,0,5741,8138,5742,10,68,2652,7288,0,110,3079,8139,10,2652,1327,4892,0,3079,1542,5743,10,2663,7288,4891,0,3090,8139,5742,10,7288,4892,625,0,8139,5743,840,10,2653,18,2506,0,3080,34,2933,10,7289,2506,1254,0,8140,2933,1469,10,1327,2653,7289,0,1542,3080,8140,10,4892,7289,4893,0,5743,8140,5744,10,8,2514,7290,0,20,2941,8141,10,2514,1258,4894,0,2941,1473,5745,10,2519,7290,4897,0,2946,8141,5748,10,7290,4894,626,0,8141,5745,841,10,2515,58,2630,0,2942,94,3057,10,7291,2630,1316,0,8142,3057,1531,10,1258,2515,7291,0,1473,2942,8142,10,4894,7291,4895,0,5745,8142,5746,10,57,2513,7292,0,93,2940,8143,10,2513,1257,4896,0,2940,1472,5747,10,2631,7292,4895,0,3058,8143,5746,10,7292,4896,626,0,8143,5747,841,10,2512,46,2518,0,2939,62,2945,10,7293,2518,1260,0,8144,2945,1475,10,1257,2512,7293,0,1472,2939,8144,10,4896,7293,4897,0,5747,8144,5748,10,40,2522,7294,0,56,2949,8145,10,2522,1262,4898,0,2949,1477,5749,10,2521,7294,4901,0,2948,8145,5752,10,7294,4898,627,0,8145,5749,842,10,2523,66,2664,0,2950,107,3091,10,7295,2664,1333,0,8146,3091,1548,10,1262,2523,7295,0,1477,2950,8146,10,4898,7295,4899,0,5749,8146,5750,10,70,2656,7296,0,113,3083,8147,10,2656,1329,4900,0,3083,1544,5751,10,2665,7296,4899,0,3092,8147,5750,10,7296,4900,627,0,8147,5751,842,10,2657,19,2520,0,3084,35,2947,10,7297,2520,1261,0,8148,2947,1476,10,1329,2657,7297,0,1544,3084,8148,10,4900,7297,4901,0,5751,8148,5752,10,9,2528,7298,0,22,2955,8149,10,2528,1265,4902,0,2955,1480,5753,10,2533,7298,4905,0,2960,8149,5756,10,7298,4902,628,0,8149,5753,843,10,2529,60,2632,0,2956,97,3059,10,7299,2632,1317,0,8150,3059,1532,10,1265,2529,7299,0,1480,2956,8150,10,4902,7299,4903,0,5753,8150,5754,10,59,2527,7300,0,96,2954,8151,10,2527,1264,4904,0,2954,1479,5755,10,2633,7300,4903,0,3060,8151,5754,10,7300,4904,628,0,8151,5755,843,10,2526,47,2532,0,2953,63,2959,10,7301,2532,1267,0,8152,2959,1482,10,1264,2526,7301,0,1479,2953,8152,10,4904,7301,4905,0,5755,8152,5756,10,41,2655,7302,0,77,5297,8153,10,2655,1328,4906,0,5297,2651,5757,10,2535,7302,4909,0,2962,8153,5760,10,7302,4906,629,0,8153,5757,844,10,2654,69,2666,0,5298,112,3093,10,7303,2666,1334,0,8154,3093,1549,10,1328,2654,7303,0,2651,5298,8154,10,4906,7303,4907,0,5757,8154,5758,10,72,2660,7304,0,116,3087,8155,10,2660,1331,4908,0,3087,1546,5759,10,2667,7304,4907,0,3094,8155,5758,10,7304,4908,629,0,8155,5759,844,10,2661,20,2534,0,3088,36,2961,10,7305,2534,1268,0,8156,2961,1483,10,1331,2661,7305,0,1546,3088,8156,10,4908,7305,4909,0,5759,8156,5760,10,11,2627,7306,0,27,5291,8157,10,2627,1314,4910,0,5291,2648,5761,10,2543,7306,4913,0,2970,8157,5764,10,7306,4910,630,0,8157,5761,845,10,2626,63,2634,0,5292,103,3061,10,7307,2634,1318,0,8158,3061,1533,10,1314,2626,7307,0,2648,5292,8158,10,4910,7307,4911,0,5761,8158,5762,10,61,2539,7308,0,99,2966,8159,10,2539,1270,4912,0,2966,1485,5763,10,2635,7308,4911,0,3062,8159,5762,10,7308,4912,630,0,8159,5763,845,10,2538,48,2542,0,2965,64,2969,10,7309,2542,1272,0,8160,2969,1487,10,1270,2538,7309,0,1485,2965,8160,10,4912,7309,4913,0,5763,8160,5764,10,10,2625,7310,0,25,5289,8161,10,2625,1313,4914,0,5289,2647,5765,10,2494,7310,4917,0,2921,8161,5768,10,7310,4914,631,0,8161,5765,846,10,2624,62,2636,0,5290,101,3063,10,7311,2636,1319,0,8162,3063,1534,10,1313,2624,7311,0,2647,5290,8162,10,4914,7311,4915,0,5765,8162,5766,10,64,2628,7312,0,104,3055,8163,10,2628,1315,4916,0,3055,1530,5767,10,2637,7312,4915,0,3064,8163,5766,10,7312,4916,631,0,8163,5767,846,10,2629,45,2495,0,3056,61,2922,10,7313,2495,1248,0,8164,2922,1463,10,1315,2629,7313,0,1530,3056,8164,10,4916,7313,4917,0,5767,8164,5768,10,42,2659,7314,0,78,5299,8165,10,2659,1330,4918,0,5299,2652,5769,10,2549,7314,4921,0,2976,8165,5772,10,7314,4918,632,0,8165,5769,847,10,2658,71,2668,0,5300,115,3095,10,7315,2668,1335,0,8166,3095,1550,10,1330,2658,7315,0,2652,5300,8166,10,4918,7315,4919,0,5769,8166,5770,10,67,2547,7316,0,109,2974,8167,10,2547,1274,4920,0,2974,1489,5771,10,2669,7316,4919,0,3096,8167,5770,10,7316,4920,632,0,8167,5771,847,10,2546,21,2548,0,2973,37,2975,10,7317,2548,1275,0,8168,2975,1490,10,1274,2546,7317,0,1489,2973,8168,10,4920,7317,4921,0,5771,8168,5772,10,10,2493,7318,0,24,5255,8169,10,2493,1247,4922,0,5255,2630,5773,10,2510,7318,4925,0,2937,8169,5776,10,7318,4922,633,0,8169,5773,848,10,2492,43,2550,0,5256,59,2977,10,7319,2550,1276,0,8170,2977,1491,10,1247,2492,7319,0,2630,5256,8170,10,4922,7319,4923,0,5773,8170,5774,10,22,2552,7320,0,38,2979,8171,10,2552,1277,4924,0,2979,1492,5775,10,2551,7320,4923,0,2978,8171,5774,10,7320,4924,633,0,8171,5775,848,10,2553,46,2511,0,2980,62,2938,10,7321,2511,1256,0,8172,2938,1471,10,1277,2553,7321,0,1492,2980,8172,10,4924,7321,4925,0,5775,8172,5776,10,43,2487,7322,0,59,5253,8173,10,2487,1244,4926,0,5253,2629,5777,10,2550,7322,4929,0,2977,8173,5780,10,7322,4926,634,0,8173,5777,849,10,2486,4,2447,0,5254,12,2874,10,7323,2447,1224,0,8174,2874,1439,10,1244,2486,7323,0,2629,5254,8174,10,4926,7323,4927,0,5777,8174,5778,10,35,2554,7324,0,51,2981,8175,10,2554,1278,4928,0,2981,1493,5779,10,2446,7324,4927,0,2873,8175,5778,10,7324,4928,634,0,8175,5779,849,10,2555,22,2551,0,2982,38,2978,10,7325,2551,1276,0,8176,2978,1491,10,1278,2555,7325,0,1493,2982,8176,10,4928,7325,4929,0,5779,8176,5780,10,5,2556,7326,0,14,2983,8177,10,2556,1279,4930,0,2983,1494,5781,10,2456,7326,4933,0,2883,8177,5784,10,7326,4930,635,0,8177,5781,850,10,2557,32,2558,0,2984,48,2985,10,7327,2558,1280,0,8178,2985,1495,10,1279,2557,7327,0,1494,2984,8178,10,4930,7327,4931,0,5781,8178,5782,10,22,2555,7328,0,38,2982,8179,10,2555,1278,4932,0,2982,1493,5783,10,2559,7328,4931,0,2986,8179,5782,10,7328,4932,635,0,8179,5783,850,10,2554,35,2457,0,2981,51,2884,10,7329,2457,1229,0,8180,2884,1444,10,1278,2554,7329,0,1493,2981,8180,10,4932,7329,4933,0,5783,8180,5784,10,32,2560,7330,0,48,2987,8181,10,2560,1281,4934,0,2987,1496,5785,10,2558,7330,4937,0,2985,8181,5788,10,7330,4934,636,0,8181,5785,851,10,2561,8,2519,0,2988,20,2946,10,7331,2519,1260,0,8182,2946,1475,10,1281,2561,7331,0,1496,2988,8182,10,4934,7331,4935,0,5785,8182,5786,10,46,2553,7332,0,62,2980,8183,10,2553,1277,4936,0,2980,1492,5787,10,2518,7332,4935,0,2945,8183,5786,10,7332,4936,636,0,8183,5787,851,10,2552,22,2559,0,2979,38,2986,10,7333,2559,1280,0,8184,2986,1495,10,1277,2552,7333,0,1492,2979,8184,10,4936,7333,4937,0,5787,8184,5788,10,11,2562,7334,0,26,2989,8185,10,2562,1282,4938,0,2989,1497,5789,10,2524,7334,4941,0,2951,8185,5792,10,7334,4938,637,0,8185,5789,852,10,2563,44,2564,0,2990,60,2991,10,7335,2564,1283,0,8186,2991,1498,10,1282,2563,7335,0,1497,2990,8186,10,4938,7335,4939,0,5789,8186,5790,10,23,2566,7336,0,39,2993,8187,10,2566,1284,4940,0,2993,1499,5791,10,2565,7336,4939,0,2992,8187,5790,10,7336,4940,637,0,8187,5791,852,10,2567,47,2525,0,2994,63,2952,10,7337,2525,1263,0,8188,2952,1478,10,1284,2567,7337,0,1499,2994,8188,10,4940,7337,4941,0,5791,8188,5792,10,44,2568,7338,0,60,2995,8189,10,2568,1285,4942,0,2995,1500,5793,10,2564,7338,4945,0,2991,8189,5796,10,7338,4942,638,0,8189,5793,853,10,2569,6,2465,0,2996,16,2892,10,7339,2465,1233,0,8190,2892,1448,10,1285,2569,7339,0,1500,2996,8190,10,4942,7339,4943,0,5793,8190,5794,10,36,2570,7340,0,52,2997,8191,10,2570,1286,4944,0,2997,1501,5795,10,2464,7340,4943,0,2891,8191,5794,10,7340,4944,638,0,8191,5795,853,10,2571,23,2565,0,2998,39,2992,10,7341,2565,1283,0,8192,2992,1498,10,1286,2571,7341,0,1501,2998,8192,10,4944,7341,4945,0,5795,8192,5796,10,7,2505,7342,0,18,5259,8193,10,2505,1253,4946,0,5259,2632,5797,10,2472,7342,4949,0,2899,8193,5800,10,7342,4946,639,0,8193,5797,854,10,2504,34,2572,0,5260,50,2999,10,7343,2572,1287,0,8194,2999,1502,10,1253,2504,7343,0,2632,5260,8194,10,4946,7343,4947,0,5797,8194,5798,10,23,2571,7344,0,39,2998,8195,10,2571,1286,4948,0,2998,1501,5799,10,2573,7344,4947,0,3000,8195,5798,10,7344,4948,639,0,8195,5799,854,10,2570,36,2473,0,2997,52,2900,10,7345,2473,1237,0,8196,2900,1452,10,1286,2570,7345,0,1501,2997,8196,10,4948,7345,4949,0,5799,8196,5800,10,34,2499,7346,0,50,5257,8197,10,2499,1250,4950,0,5257,2631,5801,10,2572,7346,4953,0,2999,8197,5804,10,7346,4950,640,0,8197,5801,855,10,2498,9,2533,0,5258,22,2960,10,7347,2533,1267,0,8198,2960,1482,10,1250,2498,7347,0,2631,5258,8198,10,4950,7347,4951,0,5801,8198,5802,10,47,2567,7348,0,63,2994,8199,10,2567,1284,4952,0,2994,1499,5803,10,2532,7348,4951,0,2959,8199,5802,10,7348,4952,640,0,8199,5803,855,10,2566,23,2573,0,2993,39,3000,10,7349,2573,1287,0,8200,3000,1502,10,1284,2566,7349,0,1499,2993,8200,10,4952,7349,4953,0,5803,8200,5804,10,8,2561,7350,0,21,5271,8201,10,2561,1281,4954,0,5271,2638,5805,10,2536,7350,4957,0,2963,8201,5808,10,7350,4954,641,0,8201,5805,856,10,2560,32,2574,0,5272,72,3001,10,7351,2574,1288,0,8202,3001,1503,10,1281,2560,7351,0,2638,5272,8202,10,4954,7351,4955,0,5805,8202,5806,10,24,2576,7352,0,40,3003,8203,10,2576,1289,4956,0,3003,1504,5807,10,2575,7352,4955,0,3002,8203,5806,10,7352,4956,641,0,8203,5807,856,10,2577,48,2537,0,3004,64,2964,10,7353,2537,1269,0,8204,2964,1484,10,1289,2577,7353,0,1504,3004,8204,10,4956,7353,4957,0,5807,8204,5808,10,32,2557,7354,0,72,5269,8205,10,2557,1279,4958,0,5269,2637,5809,10,2574,7354,4961,0,3001,8205,5812,10,7354,4958,642,0,8205,5809,857,10,2556,5,2479,0,5270,15,2906,10,7355,2479,1240,0,8206,2906,1455,10,1279,2556,7355,0,2637,5270,8206,10,4958,7355,4959,0,5809,8206,5810,10,37,2578,7356,0,53,3005,8207,10,2578,1290,4960,0,3005,1505,5811,10,2478,7356,4959,0,2905,8207,5810,10,7356,4960,642,0,8207,5811,857,10,2579,24,2575,0,3006,40,3002,10,7357,2575,1288,0,8208,3002,1503,10,1290,2579,7357,0,1505,3006,8208,10,4960,7357,4961,0,5811,8208,5812,10,6,2569,7358,0,17,5275,8209,10,2569,1285,4962,0,5275,2640,5813,10,2484,7358,4965,0,2911,8209,5816,10,7358,4962,643,0,8209,5813,858,10,2568,44,2580,0,5276,80,3007,10,7359,2580,1291,0,8210,3007,1506,10,1285,2568,7359,0,2640,5276,8210,10,4962,7359,4963,0,5813,8210,5814,10,24,2579,7360,0,40,3006,8211,10,2579,1290,4964,0,3006,1505,5815,10,2581,7360,4963,0,3008,8211,5814,10,7360,4964,643,0,8211,5815,858,10,2578,37,2485,0,3005,53,2912,10,7361,2485,1243,0,8212,2912,1458,10,1290,2578,7361,0,1505,3005,8212,10,4964,7361,4965,0,5815,8212,5816,10,44,2563,7362,0,80,5273,8213,10,2563,1282,4966,0,5273,2639,5817,10,2580,7362,4969,0,3007,8213,5820,10,7362,4966,644,0,8213,5817,859,10,2562,11,2543,0,5274,27,2970,10,7363,2543,1272,0,8214,2970,1487,10,1282,2562,7363,0,2639,5274,8214,10,4966,7363,4967,0,5817,8214,5818,10,48,2577,7364,0,64,3004,8215,10,2577,1289,4968,0,3004,1504,5819,10,2542,7364,4967,0,2969,8215,5818,10,7364,4968,644,0,8215,5819,859,10,2576,24,2581,0,3003,40,3008,10,7365,2581,1291,0,8216,3008,1506,10,1289,2576,7365,0,1504,3003,8216,10,4968,7365,4969,0,5819,8216,5820,10,49,2582,7366,0,81,3009,8217,10,2582,1292,4970,0,3009,1507,5821,10,2598,7366,4973,0,3025,8217,5824,10,7366,4970,645,0,8217,5821,860,10,2583,62,2638,0,3010,100,3065,10,7367,2638,1320,0,8218,3065,1535,10,1292,2583,7367,0,1507,3010,8218,10,4970,7367,4971,0,5821,8218,5822,10,57,2614,7368,0,93,3041,8219,10,2614,1308,4972,0,3041,1523,5823,10,2639,7368,4971,0,3066,8219,5822,10,7368,4972,645,0,8219,5823,860,10,2615,50,2599,0,3042,83,3026,10,7369,2599,1300,0,8220,3026,1515,10,1308,2615,7369,0,1523,3042,8220,10,4972,7369,4973,0,5823,8220,5824,10,51,2586,7370,0,84,3013,8221,10,2586,1294,4974,0,3013,1509,5825,10,2600,7370,4977,0,3027,8221,5828,10,7370,4974,646,0,8221,5825,861,10,2587,69,2670,0,3014,111,3097,10,7371,2670,1336,0,8222,3097,1551,10,1294,2587,7371,0,1509,3014,8222,10,4974,7371,4975,0,5825,8222,5826,10,68,2585,7372,0,110,3012,8223,10,2585,1293,4976,0,3012,1508,5827,10,2671,7372,4975,0,3098,8223,5826,10,7372,4976,646,0,8223,5827,861,10,2584,50,2601,0,3011,83,3028,10,7373,2601,1301,0,8224,3028,1516,10,1293,2584,7373,0,1508,3011,8224,10,4976,7373,4977,0,5827,8224,5828,10,52,2588,7374,0,86,3015,8225,10,2588,1295,4978,0,3015,1510,5829,10,2602,7374,4981,0,3029,8225,5832,10,7374,4978,647,0,8225,5829,862,10,2589,63,2640,0,3016,102,3067,10,7375,2640,1321,0,8226,3067,1536,10,1295,2589,7375,0,1510,3016,8226,10,4978,7375,4979,0,5829,8226,5830,10,59,2618,7376,0,96,3045,8227,10,2618,1310,4980,0,3045,1525,5831,10,2641,7376,4979,0,3068,8227,5830,10,7376,4980,647,0,8227,5831,862,10,2619,53,2603,0,3046,88,3030,10,7377,2603,1302,0,8228,3030,1517,10,1310,2619,7377,0,1525,3046,8228,10,4980,7377,4981,0,5831,8228,5832,10,54,2592,7378,0,89,3019,8229,10,2592,1297,4982,0,3019,1512,5833,10,2604,7378,4985,0,3031,8229,5836,10,7378,4982,648,0,8229,5833,863,10,2593,71,2672,0,3020,114,3099,10,7379,2672,1337,0,8230,3099,1552,10,1297,2593,7379,0,1512,3020,8230,10,4982,7379,4983,0,5833,8230,5834,10,70,2591,7380,0,113,3018,8231,10,2591,1296,4984,0,3018,1511,5835,10,2673,7380,4983,0,3100,8231,5834,10,7380,4984,648,0,8231,5835,863,10,2590,53,2605,0,3017,88,3032,10,7381,2605,1303,0,8232,3032,1518,10,1296,2590,7381,0,1511,3017,8232,10,4984,7381,4985,0,5835,8232,5836,10,51,2617,7382,0,85,5285,8233,10,2617,1309,4986,0,5285,2645,5837,10,2606,7382,4989,0,3033,8233,5840,10,7382,4986,649,0,8233,5837,864,10,2616,58,2642,0,5286,95,3069,10,7383,2642,1322,0,8234,3069,1537,10,1309,2616,7383,0,2645,5286,8234,10,4986,7383,4987,0,5837,8234,5838,10,61,2622,7384,0,99,3049,8235,10,2622,1312,4988,0,3049,1527,5839,10,2643,7384,4987,0,3070,8235,5838,10,7384,4988,649,0,8235,5839,864,10,2623,55,2607,0,3050,91,3034,10,7385,2607,1304,0,8236,3034,1519,10,1312,2623,7385,0,1527,3050,8236,10,4988,7385,4989,0,5839,8236,5840,10,52,2649,7386,0,87,5295,8237,10,2649,1325,4990,0,5295,2650,5841,10,2608,7386,4993,0,3035,8237,5844,10,7386,4990,650,0,8237,5841,865,10,2648,66,2674,0,5296,108,3101,10,7387,2674,1338,0,8238,3101,1553,10,1325,2648,7387,0,2650,5296,8238,10,4990,7387,4991,0,5841,8238,5842,10,72,2595,7388,0,116,3022,8239,10,2595,1298,4992,0,3022,1513,5843,10,2675,7388,4991,0,3102,8239,5842,10,7388,4992,650,0,8239,5843,865,10,2594,55,2609,0,3021,91,3036,10,7389,2609,1305,0,8240,3036,1520,10,1298,2594,7389,0,1513,3021,8240,10,4992,7389,4993,0,5843,8240,5844,10,49,2647,7390,0,82,5293,8241,10,2647,1324,4994,0,5293,2649,5845,10,2610,7390,4997,0,3037,8241,5848,10,7390,4994,651,0,8241,5845,866,10,2646,65,2676,0,5294,106,3103,10,7391,2676,1339,0,8242,3103,1554,10,1324,2646,7391,0,2649,5294,8242,10,4994,7391,4995,0,5845,8242,5846,10,67,2650,7392,0,109,3077,8243,10,2650,1326,4996,0,3077,1541,5847,10,2677,7392,4995,0,3104,8243,5846,10,7392,4996,651,0,8243,5847,866,10,2651,56,2611,0,3078,92,3038,10,7393,2611,1306,0,8244,3038,1521,10,1326,2651,7393,0,1541,3078,8244,10,4996,7393,4997,0,5847,8244,5848,10,54,2621,7394,0,90,5287,8245,10,2621,1311,4998,0,5287,2646,5849,10,2612,7394,5001,0,3039,8245,5852,10,7394,4998,652,0,8245,5849,867,10,2620,60,2644,0,5288,98,3071,10,7395,2644,1323,0,8246,3071,1538,10,1311,2620,7395,0,2646,5288,8246,10,4998,7395,4999,0,5849,8246,5850,10,64,2597,7396,0,104,3024,8247,10,2597,1299,5000,0,3024,1514,5851,10,2645,7396,4999,0,3072,8247,5850,10,7396,5000,652,0,8247,5851,867,10,2596,56,2613,0,3023,92,3040,10,7397,2613,1307,0,8248,3040,1522,10,1299,2596,7397,0,1514,3023,8248,10,5000,7397,5001,0,5851,8248,5852,10,58,2616,7398,0,94,3043,8249,10,2616,1309,5002,0,3043,1524,5853,10,2630,7398,5005,0,3057,8249,5856,10,7398,5002,653,0,8249,5853,868,10,2617,51,2600,0,3044,84,3027,10,7399,2600,1301,0,8250,3027,1516,10,1309,2617,7399,0,1524,3044,8250,10,5002,7399,5003,0,5853,8250,5854,10,50,2615,7400,0,83,3042,8251,10,2615,1308,5004,0,3042,1523,5855,10,2601,7400,5003,0,3028,8251,5854,10,7400,5004,653,0,8251,5855,868,10,2614,57,2631,0,3041,93,3058,10,7401,2631,1316,0,8252,3058,1531,10,1308,2614,7401,0,1523,3041,8252,10,5004,7401,5005,0,5855,8252,5856,10,60,2620,7402,0,97,3047,8253,10,2620,1311,5006,0,3047,1526,5857,10,2632,7402,5009,0,3059,8253,5860,10,7402,5006,654,0,8253,5857,869,10,2621,54,2604,0,3048,89,3031,10,7403,2604,1303,0,8254,3031,1518,10,1311,2621,7403,0,1526,3048,8254,10,5006,7403,5007,0,5857,8254,5858,10,53,2619,7404,0,88,3046,8255,10,2619,1310,5008,0,3046,1525,5859,10,2605,7404,5007,0,3032,8255,5858,10,7404,5008,654,0,8255,5859,869,10,2618,59,2633,0,3045,96,3060,10,7405,2633,1317,0,8256,3060,1532,10,1310,2618,7405,0,1525,3045,8256,10,5008,7405,5009,0,5859,8256,5860,10,63,2589,7406,0,103,5281,8257,10,2589,1295,5010,0,5281,2643,5861,10,2634,7406,5013,0,3061,8257,5864,10,7406,5010,655,0,8257,5861,870,10,2588,52,2608,0,5282,87,3035,10,7407,2608,1305,0,8258,3035,1520,10,1295,2588,7407,0,2643,5282,8258,10,5010,7407,5011,0,5861,8258,5862,10,55,2623,7408,0,91,3050,8259,10,2623,1312,5012,0,3050,1527,5863,10,2609,7408,5011,0,3036,8259,5862,10,7408,5012,655,0,8259,5863,870,10,2622,61,2635,0,3049,99,3062,10,7409,2635,1318,0,8260,3062,1533,10,1312,2622,7409,0,1527,3049,8260,10,5012,7409,5013,0,5863,8260,5864,10,62,2583,7410,0,101,5277,8261,10,2583,1292,5014,0,5277,2641,5865,10,2636,7410,5017,0,3063,8261,5868,10,7410,5014,656,0,8261,5865,871,10,2582,49,2610,0,5278,82,3037,10,7411,2610,1306,0,8262,3037,1521,10,1292,2582,7411,0,2641,5278,8262,10,5014,7411,5015,0,5865,8262,5866,10,56,2596,7412,0,92,3023,8263,10,2596,1299,5016,0,3023,1514,5867,10,2611,7412,5015,0,3038,8263,5866,10,7412,5016,656,0,8263,5867,871,10,2597,64,2637,0,3024,104,3064,10,7413,2637,1319,0,8264,3064,1534,10,1299,2597,7413,0,1514,3024,8264,10,5016,7413,5017,0,5867,8264,5868,10,62,2624,7414,0,100,3051,8265,10,2624,1313,5018,0,3051,1528,5869,10,2638,7414,5021,0,3065,8265,5872,10,7414,5018,657,0,8265,5869,872,10,2625,10,2510,0,3052,24,2937,10,7415,2510,1256,0,8266,2937,1471,10,1313,2625,7415,0,1528,3052,8266,10,5018,7415,5019,0,5869,8266,5870,10,46,2512,7416,0,62,2939,8267,10,2512,1257,5020,0,2939,1472,5871,10,2511,7416,5019,0,2938,8267,5870,10,7416,5020,657,0,8267,5871,872,10,2513,57,2639,0,2940,93,3066,10,7417,2639,1320,0,8268,3066,1535,10,1257,2513,7417,0,1472,2940,8268,10,5020,7417,5021,0,5871,8268,5872,10,63,2626,7418,0,102,3053,8269,10,2626,1314,5022,0,3053,1529,5873,10,2640,7418,5025,0,3067,8269,5876,10,7418,5022,658,0,8269,5873,873,10,2627,11,2524,0,3054,26,2951,10,7419,2524,1263,0,8270,2951,1478,10,1314,2627,7419,0,1529,3054,8270,10,5022,7419,5023,0,5873,8270,5874,10,47,2526,7420,0,63,2953,8271,10,2526,1264,5024,0,2953,1479,5875,10,2525,7420,5023,0,2952,8271,5874,10,7420,5024,658,0,8271,5875,873,10,2527,59,2641,0,2954,96,3068,10,7421,2641,1321,0,8272,3068,1536,10,1264,2527,7421,0,1479,2954,8272,10,5024,7421,5025,0,5875,8272,5876,10,58,2515,7422,0,95,5263,8273,10,2515,1258,5026,0,5263,2634,5877,10,2642,7422,5029,0,3069,8273,5880,10,7422,5026,659,0,8273,5877,874,10,2514,8,2536,0,5264,21,2963,10,7423,2536,1269,0,8274,2963,1484,10,1258,2514,7423,0,2634,5264,8274,10,5026,7423,5027,0,5877,8274,5878,10,48,2538,7424,0,64,2965,8275,10,2538,1270,5028,0,2965,1485,5879,10,2537,7424,5027,0,2964,8275,5878,10,7424,5028,659,0,8275,5879,874,10,2539,61,2643,0,2966,99,3070,10,7425,2643,1322,0,8276,3070,1537,10,1270,2539,7425,0,1485,2966,8276,10,5028,7425,5029,0,5879,8276,5880,10,60,2529,7426,0,98,5267,8277,10,2529,1265,5030,0,5267,2636,5881,10,2644,7426,5033,0,3071,8277,5884,10,7426,5030,660,0,8277,5881,875,10,2528,9,2503,0,5268,23,2930,10,7427,2503,1252,0,8278,2930,1467,10,1265,2528,7427,0,2636,5268,8278,10,5030,7427,5031,0,5881,8278,5882,10,45,2629,7428,0,61,3056,8279,10,2629,1315,5032,0,3056,1530,5883,10,2502,7428,5031,0,2929,8279,5882,10,7428,5032,660,0,8279,5883,875,10,2628,64,2645,0,3055,104,3072,10,7429,2645,1323,0,8280,3072,1538,10,1315,2628,7429,0,1530,3055,8280,10,5032,7429,5033,0,5883,8280,5884,10,65,2646,7430,0,105,3073,8281,10,2646,1324,5034,0,3073,1539,5885,10,2662,7430,5037,0,3089,8281,5888,10,7430,5034,661,0,8281,5885,876,10,2647,49,2598,0,3074,81,3025,10,7431,2598,1300,0,8282,3025,1515,10,1324,2647,7431,0,1539,3074,8282,10,5034,7431,5035,0,5885,8282,5886,10,50,2584,7432,0,83,3011,8283,10,2584,1293,5036,0,3011,1508,5887,10,2599,7432,5035,0,3026,8283,5886,10,7432,5036,661,0,8283,5887,876,10,2585,68,2663,0,3012,110,3090,10,7433,2663,1332,0,8284,3090,1547,10,1293,2585,7433,0,1508,3012,8284,10,5036,7433,5037,0,5887,8284,5888,10,66,2648,7434,0,107,3075,8285,10,2648,1325,5038,0,3075,1540,5889,10,2664,7434,5041,0,3091,8285,5892,10,7434,5038,662,0,8285,5889,877,10,2649,52,2602,0,3076,86,3029,10,7435,2602,1302,0,8286,3029,1517,10,1325,2649,7435,0,1540,3076,8286,10,5038,7435,5039,0,5889,8286,5890,10,53,2590,7436,0,88,3017,8287,10,2590,1296,5040,0,3017,1511,5891,10,2603,7436,5039,0,3030,8287,5890,10,7436,5040,662,0,8287,5891,877,10,2591,70,2665,0,3018,113,3092,10,7437,2665,1333,0,8288,3092,1548,10,1296,2591,7437,0,1511,3018,8288,10,5040,7437,5041,0,5891,8288,5892,10,69,2587,7438,0,112,5279,8289,10,2587,1294,5042,0,5279,2642,5893,10,2666,7438,5045,0,3093,8289,5896,10,7438,5042,663,0,8289,5893,878,10,2586,51,2606,0,5280,85,3033,10,7439,2606,1304,0,8290,3033,1519,10,1294,2586,7439,0,2642,5280,8290,10,5042,7439,5043,0,5893,8290,5894,10,55,2594,7440,0,91,3021,8291,10,2594,1298,5044,0,3021,1513,5895,10,2607,7440,5043,0,3034,8291,5894,10,7440,5044,663,0,8291,5895,878,10,2595,72,2667,0,3022,116,3094,10,7441,2667,1334,0,8292,3094,1549,10,1298,2595,7441,0,1513,3022,8292,10,5044,7441,5045,0,5895,8292,5896,10,71,2593,7442,0,115,5283,8293,10,2593,1297,5046,0,5283,2644,5897,10,2668,7442,5049,0,3095,8293,5900,10,7442,5046,664,0,8293,5897,879,10,2592,54,2612,0,5284,90,3039,10,7443,2612,1307,0,8294,3039,1522,10,1297,2592,7443,0,2644,5284,8294,10,5046,7443,5047,0,5897,8294,5898,10,56,2651,7444,0,92,3078,8295,10,2651,1326,5048,0,3078,1541,5899,10,2613,7444,5047,0,3040,8295,5898,10,7444,5048,664,0,8295,5899,879,10,2650,67,2669,0,3077,109,3096,10,7445,2669,1335,0,8296,3096,1550,10,1326,2650,7445,0,1541,3077,8296,10,5048,7445,5049,0,5899,8296,5900,10,69,2654,7446,0,111,3081,8297,10,2654,1328,5050,0,3081,1543,5901,10,2670,7446,5053,0,3097,8297,5904,10,7446,5050,665,0,8297,5901,880,10,2655,41,2516,0,3082,57,2943,10,7447,2516,1259,0,8298,2943,1474,10,1328,2655,7447,0,1543,3082,8298,10,5050,7447,5051,0,5901,8298,5902,10,18,2653,7448,0,34,3080,8299,10,2653,1327,5052,0,3080,1542,5903,10,2517,7448,5051,0,2944,8299,5902,10,7448,5052,665,0,8299,5903,880,10,2652,68,2671,0,3079,110,3098,10,7449,2671,1336,0,8300,3098,1551,10,1327,2652,7449,0,1542,3079,8300,10,5052,7449,5053,0,5903,8300,5904,10,71,2658,7450,0,114,3085,8301,10,2658,1330,5054,0,3085,1545,5905,10,2672,7450,5057,0,3099,8301,5908,10,7450,5054,666,0,8301,5905,881,10,2659,42,2530,0,3086,58,2957,10,7451,2530,1266,0,8302,2957,1481,10,1330,2659,7451,0,1545,3086,8302,10,5054,7451,5055,0,5905,8302,5906,10,19,2657,7452,0,35,3084,8303,10,2657,1329,5056,0,3084,1544,5907,10,2531,7452,5055,0,2958,8303,5906,10,7452,5056,666,0,8303,5907,881,10,2656,70,2673,0,3083,113,3100,10,7453,2673,1337,0,8304,3100,1552,10,1329,2656,7453,0,1544,3083,8304,10,5056,7453,5057,0,5907,8304,5908,10,66,2523,7454,0,108,5265,8305,10,2523,1262,5058,0,5265,2635,5909,10,2674,7454,5061,0,3101,8305,5912,10,7454,5058,667,0,8305,5909,882,10,2522,40,2540,0,5266,76,2967,10,7455,2540,1271,0,8306,2967,1486,10,1262,2522,7455,0,2635,5266,8306,10,5058,7455,5059,0,5909,8306,5910,10,20,2661,7456,0,36,3088,8307,10,2661,1331,5060,0,3088,1546,5911,10,2541,7456,5059,0,2968,8307,5910,10,7456,5060,667,0,8307,5911,882,10,2660,72,2675,0,3087,116,3102,10,7457,2675,1338,0,8308,3102,1553,10,1331,2660,7457,0,1546,3087,8308,10,5060,7457,5061,0,5911,8308,5912,10,65,2509,7458,0,106,5261,8309,10,2509,1255,5062,0,5261,2633,5913,10,2676,7458,5065,0,3103,8309,5916,10,7458,5062,668,0,8309,5913,883,10,2508,39,2544,0,5262,75,2971,10,7459,2544,1273,0,8310,2971,1488,10,1255,2508,7459,0,2633,5262,8310,10,5062,7459,5063,0,5913,8310,5914,10,21,2546,7460,0,37,2973,8311,10,2546,1274,5064,0,2973,1489,5915,10,2545,7460,5063,0,2972,8311,5914,10,7460,5064,668,0,8311,5915,883,10,2547,67,2677,0,2974,109,3104,10,7461,2677,1339,0,8312,3104,1554,10,1274,2547,7461,0,1489,2974,8312,10,5064,7461,5065,0,5915,8312,5916,10,74,2678,7462,0,123,3105,8313,10,2678,1340,5066,0,3105,1555,5917,10,2685,7462,5069,0,3112,8313,5920,10,7462,5066,669,0,8313,5917,884,10,2679,86,2680,0,3106,154,3107,10,7463,2680,1341,0,8314,3107,1556,10,1340,2679,7463,0,1555,3106,8314,10,5066,7463,5067,0,5917,8314,5918,10,81,2682,7464,0,137,3109,8315,10,2682,1342,5068,0,3109,1557,5919,10,2681,7464,5067,0,3108,8315,5918,10,7464,5068,669,0,8315,5919,884,10,2683,90,2684,0,3110,158,3111,10,7465,2684,1343,0,8316,3111,1558,10,1342,2683,7465,0,1557,3110,8316,10,5068,7465,5069,0,5919,8316,5920,10,86,2686,7466,0,154,3113,8317,10,2686,1344,5070,0,3113,1559,5921,10,2680,7466,5073,0,3107,8317,5924,10,7466,5070,670,0,8317,5921,885,10,2687,73,2688,0,3114,124,3115,10,7467,2688,1345,0,8318,3115,1560,10,1344,2687,7467,0,1559,3114,8318,10,5070,7467,5071,0,5921,8318,5922,10,91,2690,7468,0,147,3117,8319,10,2690,1346,5072,0,3117,1561,5923,10,2689,7468,5071,0,3116,8319,5922,10,7468,5072,670,0,8319,5923,885,10,2691,81,2681,0,3118,137,3108,10,7469,2681,1341,0,8320,3108,1556,10,1346,2691,7469,0,1561,3118,8320,10,5072,7469,5073,0,5923,8320,5924,10,75,2692,7470,0,126,3119,8321,10,2692,1347,5074,0,3119,1562,5925,10,2697,7470,5077,0,3124,8321,5928,10,7470,5074,671,0,8321,5925,886,10,2693,88,2694,0,3120,156,3121,10,7471,2694,1348,0,8322,3121,1563,10,1347,2693,7471,0,1562,3120,8322,10,5074,7471,5075,0,5925,8322,5926,10,81,2691,7472,0,137,3118,8323,10,2691,1346,5076,0,3118,1561,5927,10,2695,7472,5075,0,3122,8323,5926,10,7472,5076,671,0,8323,5927,886,10,2690,91,2696,0,3117,147,3123,10,7473,2696,1349,0,8324,3123,1564,10,1346,2690,7473,0,1561,3117,8324,10,5076,7473,5077,0,5927,8324,5928,10,88,2698,7474,0,156,3125,8325,10,2698,1350,5078,0,3125,1565,5929,10,2694,7474,5081,0,3121,8325,5932,10,7474,5078,672,0,8325,5929,887,10,2699,76,2700,0,3126,125,3127,10,7475,2700,1351,0,8326,3127,1566,10,1350,2699,7475,0,1565,3126,8326,10,5078,7475,5079,0,5929,8326,5930,10,90,2683,7476,0,158,3110,8327,10,2683,1342,5080,0,3110,1557,5931,10,2701,7476,5079,0,3128,8327,5930,10,7476,5080,672,0,8327,5931,887,10,2682,81,2695,0,3109,137,3122,10,7477,2695,1348,0,8328,3122,1563,10,1342,2682,7477,0,1557,3109,8328,10,5080,7477,5081,0,5931,8328,5932,10,73,2702,7478,0,127,3129,8329,10,2702,1352,5082,0,3129,1567,5933,10,2688,7478,5085,0,5308,8329,5936,10,7478,5082,673,0,8329,5933,888,10,2703,92,2704,0,3130,160,3131,10,7479,2704,1353,0,8330,3131,1568,10,1352,2703,7479,0,1567,3130,8330,10,5082,7479,5083,0,5933,8330,5934,10,82,2706,7480,0,138,3133,8331,10,2706,1354,5084,0,3133,1569,5935,10,2705,7480,5083,0,3132,8331,5934,10,7480,5084,673,0,8331,5935,888,10,2707,91,2689,0,3134,159,5307,10,7481,2689,1345,0,8332,5307,2656,10,1354,2707,7481,0,1569,3134,8332,10,5084,7481,5085,0,5935,8332,5936,10,92,2708,7482,0,160,3135,8333,10,2708,1355,5086,0,3135,1570,5937,10,2704,7482,5089,0,3131,8333,5940,10,7482,5086,674,0,8333,5937,889,10,2709,77,2710,0,3136,130,3137,10,7483,2710,1356,0,8334,3137,1571,10,1355,2709,7483,0,1570,3136,8334,10,5086,7483,5087,0,5937,8334,5938,10,97,2712,7484,0,153,3139,8335,10,2712,1357,5088,0,3139,1572,5939,10,2711,7484,5087,0,3138,8335,5938,10,7484,5088,674,0,8335,5939,889,10,2713,82,2705,0,3140,138,3132,10,7485,2705,1353,0,8336,3132,1568,10,1357,2713,7485,0,1572,3140,8336,10,5088,7485,5089,0,5939,8336,5940,10,80,2714,7486,0,136,3141,8337,10,2714,1358,5090,0,3141,1573,5941,10,2719,7486,5093,0,3146,8337,5944,10,7486,5090,675,0,8337,5941,890,10,2715,89,2716,0,3142,157,3143,10,7487,2716,1359,0,8338,3143,1574,10,1358,2715,7487,0,1573,3142,8338,10,5090,7487,5091,0,5941,8338,5942,10,82,2713,7488,0,138,3140,8339,10,2713,1357,5092,0,3140,1572,5943,10,2717,7488,5091,0,3144,8339,5942,10,7488,5092,675,0,8339,5943,890,10,2712,97,2718,0,3139,153,3145,10,7489,2718,1360,0,8340,3145,1575,10,1357,2712,7489,0,1572,3139,8340,10,5092,7489,5093,0,5943,8340,5944,10,89,2720,7490,0,157,3147,8341,10,2720,1361,5094,0,3147,1576,5945,10,2716,7490,5097,0,3143,8341,5948,10,7490,5094,676,0,8341,5945,891,10,2721,75,2697,0,3148,128,5311,10,7491,2697,1349,0,8342,5311,2658,10,1361,2721,7491,0,1576,3148,8342,10,5094,7491,5095,0,5945,8342,5946,10,91,2707,7492,0,159,3134,8343,10,2707,1354,5096,0,3134,1569,5947,10,2696,7492,5095,0,5312,8343,5946,10,7492,5096,676,0,8343,5947,891,10,2706,82,2717,0,3133,138,3144,10,7493,2717,1359,0,8344,3144,1574,10,1354,2706,7493,0,1569,3133,8344,10,5096,7493,5097,0,5947,8344,5948,10,77,2709,7494,0,129,5319,8345,10,2709,1355,5098,0,5319,2662,5949,10,2727,7494,5101,0,3154,8345,5952,10,7494,5098,677,0,8345,5949,892,10,2708,92,2722,0,5320,148,3149,10,7495,2722,1362,0,8346,3149,1577,10,1355,2708,7495,0,2662,5320,8346,10,5098,7495,5099,0,5949,8346,5950,10,83,2724,7496,0,139,3151,8347,10,2724,1363,5100,0,3151,1578,5951,10,2723,7496,5099,0,3150,8347,5950,10,7496,5100,677,0,8347,5951,892,10,2725,94,2726,0,3152,150,3153,10,7497,2726,1364,0,8348,3153,1579,10,1363,2725,7497,0,1578,3152,8348,10,5100,7497,5101,0,5951,8348,5952,10,92,2703,7498,0,148,5317,8349,10,2703,1352,5102,0,5317,2661,5953,10,2722,7498,5105,0,3149,8349,5956,10,7498,5102,678,0,8349,5953,893,10,2702,73,2687,0,5318,117,5305,10,7499,2687,1344,0,8350,5305,2655,10,1352,2702,7499,0,2661,5318,8350,10,5102,7499,5103,0,5953,8350,5954,10,86,2728,7500,0,142,3155,8351,10,2728,1365,5104,0,3155,1580,5955,10,2686,7500,5103,0,5306,8351,5954,10,7500,5104,678,0,8351,5955,893,10,2729,83,2723,0,3156,139,3150,10,7501,2723,1362,0,8352,3150,1577,10,1365,2729,7501,0,1580,3156,8352,10,5104,7501,5105,0,5955,8352,5956,10,74,2730,7502,0,118,3157,8353,10,2730,1366,5106,0,3157,1581,5957,10,2678,7502,5109,0,5302,8353,5960,10,7502,5106,679,0,8353,5957,894,10,2731,87,2732,0,3158,143,3159,10,7503,2732,1367,0,8354,3159,1582,10,1366,2731,7503,0,1581,3158,8354,10,5106,7503,5107,0,5957,8354,5958,10,83,2729,7504,0,139,3156,8355,10,2729,1365,5108,0,3156,1580,5959,10,2733,7504,5107,0,3160,8355,5958,10,7504,5108,679,0,8355,5959,894,10,2728,86,2679,0,3155,142,5301,10,7505,2679,1340,0,8356,5301,2653,10,1365,2728,7505,0,1580,3155,8356,10,5108,7505,5109,0,5959,8356,5960,10,87,2734,7506,0,143,3161,8357,10,2734,1368,5110,0,3161,1583,5961,10,2732,7506,5113,0,3159,8357,5964,10,7506,5110,680,0,8357,5961,895,10,2735,78,2736,0,3162,131,3163,10,7507,2736,1369,0,8358,3163,1584,10,1368,2735,7507,0,1583,3162,8358,10,5110,7507,5111,0,5961,8358,5962,10,94,2725,7508,0,150,3152,8359,10,2725,1363,5112,0,3152,1578,5963,10,2737,7508,5111,0,3164,8359,5962,10,7508,5112,680,0,8359,5963,895,10,2724,83,2733,0,3151,139,3160,10,7509,2733,1367,0,8360,3160,1582,10,1363,2724,7509,0,1578,3151,8360,10,5112,7509,5113,0,5963,8360,5964,10,79,2738,7510,0,133,3165,8361,10,2738,1370,5114,0,3165,1585,5965,10,2745,7510,5117,0,3172,8361,5968,10,7510,5114,681,0,8361,5965,896,10,2739,93,2740,0,3166,149,3167,10,7511,2740,1371,0,8362,3167,1586,10,1370,2739,7511,0,1585,3166,8362,10,5114,7511,5115,0,5965,8362,5966,10,84,2742,7512,0,140,3169,8363,10,2742,1372,5116,0,3169,1587,5967,10,2741,7512,5115,0,3168,8363,5966,10,7512,5116,681,0,8363,5967,896,10,2743,95,2744,0,3170,151,3171,10,7513,2744,1373,0,8364,3171,1588,10,1372,2743,7513,0,1587,3170,8364,10,5116,7513,5117,0,5967,8364,5968,10,93,2746,7514,0,149,3173,8365,10,2746,1374,5118,0,3173,1589,5969,10,2740,7514,5121,0,3167,8365,5972,10,7514,5118,682,0,8365,5969,897,10,2747,76,2699,0,3174,120,5313,10,7515,2699,1350,0,8366,5313,2659,10,1374,2747,7515,0,1589,3174,8366,10,5118,7515,5119,0,5969,8366,5970,10,88,2748,7516,0,144,3175,8367,10,2748,1375,5120,0,3175,1590,5971,10,2698,7516,5119,0,5314,8367,5970,10,7516,5120,682,0,8367,5971,897,10,2749,84,2741,0,3176,140,3168,10,7517,2741,1371,0,8368,3168,1586,10,1375,2749,7517,0,1590,3176,8368,10,5120,7517,5121,0,5971,8368,5972,10,75,2721,7518,0,119,5323,8369,10,2721,1361,5122,0,5323,2664,5973,10,2692,7518,5125,0,5310,8369,5976,10,7518,5122,683,0,8369,5973,898,10,2720,89,2750,0,5324,145,3177,10,7519,2750,1376,0,8370,3177,1591,10,1361,2720,7519,0,2664,5324,8370,10,5122,7519,5123,0,5973,8370,5974,10,84,2749,7520,0,140,3176,8371,10,2749,1375,5124,0,3176,1590,5975,10,2751,7520,5123,0,3178,8371,5974,10,7520,5124,683,0,8371,5975,898,10,2748,88,2693,0,3175,144,5309,10,7521,2693,1347,0,8372,5309,2657,10,1375,2748,7521,0,1590,3175,8372,10,5124,7521,5125,0,5975,8372,5976,10,89,2715,7522,0,145,5321,8373,10,2715,1358,5126,0,5321,2663,5977,10,2750,7522,5129,0,3177,8373,5980,10,7522,5126,684,0,8373,5977,899,10,2714,80,2752,0,5322,135,3179,10,7523,2752,1377,0,8374,3179,1592,10,1358,2714,7523,0,2663,5322,8374,10,5126,7523,5127,0,5977,8374,5978,10,95,2743,7524,0,151,3170,8375,10,2743,1372,5128,0,3170,1587,5979,10,2753,7524,5127,0,3180,8375,5978,10,7524,5128,684,0,8375,5979,899,10,2742,84,2751,0,3169,140,3178,10,7525,2751,1376,0,8376,3178,1591,10,1372,2742,7525,0,1587,3169,8376,10,5128,7525,5129,0,5979,8376,5980,10,78,2735,7526,0,132,5327,8377,10,2735,1368,5130,0,5327,2666,5981,10,2759,7526,5133,0,3186,8377,5984,10,7526,5130,685,0,8377,5981,900,10,2734,87,2754,0,5328,155,3181,10,7527,2754,1378,0,8378,3181,1593,10,1368,2734,7527,0,2666,5328,8378,10,5130,7527,5131,0,5981,8378,5982,10,85,2756,7528,0,141,3183,8379,10,2756,1379,5132,0,3183,1594,5983,10,2755,7528,5131,0,3182,8379,5982,10,7528,5132,685,0,8379,5983,900,10,2757,96,2758,0,3184,152,3185,10,7529,2758,1380,0,8380,3185,1595,10,1379,2757,7529,0,1594,3184,8380,10,5132,7529,5133,0,5983,8380,5984,10,87,2731,7530,0,155,5325,8381,10,2731,1366,5134,0,5325,2665,5985,10,2754,7530,5137,0,3181,8381,5988,10,7530,5134,686,0,8381,5985,901,10,2730,74,2685,0,5326,121,5303,10,7531,2685,1343,0,8382,5303,2654,10,1366,2730,7531,0,2665,5326,8382,10,5134,7531,5135,0,5985,8382,5986,10,90,2760,7532,0,146,3187,8383,10,2760,1381,5136,0,3187,1596,5987,10,2684,7532,5135,0,5304,8383,5986,10,7532,5136,686,0,8383,5987,901,10,2761,85,2755,0,3188,141,3182,10,7533,2755,1378,0,8384,3182,1593,10,1381,2761,7533,0,1596,3188,8384,10,5136,7533,5137,0,5987,8384,5988,10,76,2747,7534,0,122,5331,8385,10,2747,1374,5138,0,5331,2668,5989,10,2700,7534,5141,0,5316,8385,5992,10,7534,5138,687,0,8385,5989,902,10,2746,93,2762,0,5332,161,3189,10,7535,2762,1382,0,8386,3189,1597,10,1374,2746,7535,0,2668,5332,8386,10,5138,7535,5139,0,5989,8386,5990,10,85,2761,7536,0,141,3188,8387,10,2761,1381,5140,0,3188,1596,5991,10,2763,7536,5139,0,3190,8387,5990,10,7536,5140,687,0,8387,5991,902,10,2760,90,2701,0,3187,146,5315,10,7537,2701,1351,0,8388,5315,2660,10,1381,2760,7537,0,1596,3187,8388,10,5140,7537,5141,0,5991,8388,5992,10,93,2739,7538,0,161,5329,8389,10,2739,1370,5142,0,5329,2667,5993,10,2762,7538,5145,0,3189,8389,5996,10,7538,5142,688,0,8389,5993,903,10,2738,79,2764,0,5330,134,3191,10,7539,2764,1383,0,8390,3191,1598,10,1370,2738,7539,0,2667,5330,8390,10,5142,7539,5143,0,5993,8390,5994,10,96,2757,7540,0,152,3184,8391,10,2757,1379,5144,0,3184,1594,5995,10,2765,7540,5143,0,3192,8391,5994,10,7540,5144,688,0,8391,5995,903,10,2756,85,2763,0,3183,141,3190,10,7541,2763,1382,0,8392,3190,1597,10,1379,2756,7541,0,1594,3183,8392,10,5144,7541,5145,0,5995,8392,5996,10,77,2766,7542,0,130,3193,8393,10,2766,1384,5146,0,3193,1599,5997,10,2710,7542,5149,0,3137,8393,6000,10,7542,5146,689,0,8393,5997,904,10,2767,364,3842,0,3194,480,4269,10,7543,3842,1922,0,8394,4269,2137,10,1384,2767,7543,0,1599,3194,8394,10,5146,7543,5147,0,5997,8394,5998,10,365,3828,7544,0,482,4255,8395,10,3828,1915,5148,0,4255,2130,5999,10,3843,7544,5147,0,4270,8395,5998,10,7544,5148,689,0,8395,5999,904,10,3829,97,2711,0,4256,153,3138,10,7545,2711,1356,0,8396,3138,1571,10,1915,3829,7545,0,2130,4256,8396,10,5148,7545,5149,0,5999,8396,6000,10,80,2719,7546,0,136,3146,8397,10,2719,1360,5150,0,3146,1575,6001,10,3831,7546,5153,0,4258,8397,6004,10,7546,5150,690,0,8397,6001,905,10,2718,97,3829,0,3145,153,4256,10,7547,3829,1915,0,8398,4256,2130,10,1360,2718,7547,0,1575,3145,8398,10,5150,7547,5151,0,6001,8398,6002,10,365,3844,7548,0,482,4271,8399,10,3844,1923,5152,0,4271,2138,6003,10,3828,7548,5151,0,4255,8399,6002,10,7548,5152,690,0,8399,6003,905,10,3845,366,3830,0,4272,483,4257,10,7549,3830,1916,0,8400,4257,2131,10,1923,3845,7549,0,2138,4272,8400,10,5152,7549,5153,0,6003,8400,6004,10,77,2727,7550,0,129,3154,8401,10,2727,1364,5154,0,3154,1579,6005,10,2766,7550,5157,0,5334,8401,6008,10,7550,5154,691,0,8401,6005,906,10,2726,94,2772,0,3153,150,3199,10,7551,2772,1387,0,8402,3199,1602,10,1364,2726,7551,0,1579,3153,8402,10,5154,7551,5155,0,6005,8402,6006,10,367,3846,7552,0,485,4273,8403,10,3846,1924,5156,0,4273,2139,6007,10,2773,7552,5155,0,3200,8403,6006,10,7552,5156,691,0,8403,6007,906,10,3847,364,2767,0,4274,481,5333,10,7553,2767,1384,0,8404,5333,2669,10,1924,3847,7553,0,2139,4274,8404,10,5156,7553,5157,0,6007,8404,6008,10,78,2774,7554,0,131,3201,8405,10,2774,1388,5158,0,3201,1603,6009,10,2736,7554,5161,0,3163,8405,6012,10,7554,5158,692,0,8405,6009,907,10,2775,368,3848,0,3202,486,4275,10,7555,3848,1925,0,8406,4275,2140,10,1388,2775,7555,0,1603,3202,8406,10,5158,7555,5159,0,6009,8406,6010,10,367,2773,7556,0,485,3200,8407,10,2773,1387,5160,0,3200,1602,6011,10,3849,7556,5159,0,4276,8407,6010,10,7556,5160,692,0,8407,6011,907,10,2772,94,2737,0,3199,150,3164,10,7557,2737,1369,0,8408,3164,1584,10,1387,2772,7557,0,1602,3199,8408,10,5160,7557,5161,0,6011,8408,6012,10,79,2745,7558,0,133,3172,8409,10,2745,1373,5162,0,3172,1588,6013,10,3837,7558,5165,0,4264,8409,6016,10,7558,5162,693,0,8409,6013,908,10,2744,95,2778,0,3171,151,3205,10,7559,2778,1390,0,8410,3205,1605,10,1373,2744,7559,0,1588,3171,8410,10,5162,7559,5163,0,6013,8410,6014,10,370,3850,7560,0,490,4277,8411,10,3850,1926,5164,0,4277,2141,6015,10,2779,7560,5163,0,3206,8411,6014,10,7560,5164,693,0,8411,6015,908,10,3851,369,3836,0,4278,488,4263,10,7561,3836,1919,0,8412,4263,2134,10,1926,3851,7561,0,2141,4278,8412,10,5164,7561,5165,0,6015,8412,6016,10,80,3831,7562,0,135,5429,8413,10,3831,1916,5166,0,5429,2717,6017,10,2752,7562,5169,0,3179,8413,6020,10,7562,5166,694,0,8413,6017,909,10,3830,366,3852,0,5430,484,4279,10,7563,3852,1927,0,8414,4279,2142,10,1916,3830,7563,0,2717,5430,8414,10,5166,7563,5167,0,6017,8414,6018,10,370,2779,7564,0,490,3206,8415,10,2779,1390,5168,0,3206,1605,6019,10,3853,7564,5167,0,4280,8415,6018,10,7564,5168,694,0,8415,6019,909,10,2778,95,2753,0,3205,151,3180,10,7565,2753,1377,0,8416,3180,1592,10,1390,2778,7565,0,1605,3205,8416,10,5168,7565,5169,0,6019,8416,6020,10,78,2759,7566,0,132,3186,8417,10,2759,1380,5170,0,3186,1595,6021,10,2774,7566,5173,0,5338,8417,6024,10,7566,5170,695,0,8417,6021,910,10,2758,96,2780,0,3185,152,3207,10,7567,2780,1391,0,8418,3207,1606,10,1380,2758,7567,0,1595,3185,8418,10,5170,7567,5171,0,6021,8418,6022,10,371,3854,7568,0,491,4281,8419,10,3854,1928,5172,0,4281,2143,6023,10,2781,7568,5171,0,3208,8419,6022,10,7568,5172,695,0,8419,6023,910,10,3855,368,2775,0,4282,487,5337,10,7569,2775,1388,0,8420,5337,2671,10,1928,3855,7569,0,2143,4282,8420,10,5172,7569,5173,0,6023,8420,6024,10,79,3837,7570,0,134,5433,8421,10,3837,1919,5174,0,5433,2719,6025,10,2764,7570,5177,0,3191,8421,6028,10,7570,5174,696,0,8421,6025,911,10,3836,369,3856,0,5434,489,4283,10,7571,3856,1929,0,8422,4283,2144,10,1919,3836,7571,0,2719,5434,8422,10,5174,7571,5175,0,6025,8422,6026,10,371,2781,7572,0,491,3208,8423,10,2781,1391,5176,0,3208,1606,6027,10,3857,7572,5175,0,4284,8423,6026,10,7572,5176,696,0,8423,6027,911,10,2780,96,2765,0,3207,152,3192,10,7573,2765,1383,0,8424,3192,1598,10,1391,2780,7573,0,1606,3207,8424,10,5176,7573,5177,0,6027,8424,6028,10,98,2788,7574,0,162,3215,8425,10,2788,1395,5178,0,3215,1610,6029,10,2783,7574,5181,0,3210,8425,6032,10,7574,5178,697,0,8425,6029,912,10,2789,101,2786,0,3216,165,3213,10,7575,2786,1394,0,8426,3213,1609,10,1395,2789,7575,0,1610,3216,8426,10,5178,7575,5179,0,6029,8426,6030,10,100,2784,7576,0,164,3211,8427,10,2784,1393,5180,0,3211,1608,6031,10,2787,7576,5179,0,3214,8427,6030,10,7576,5180,697,0,8427,6031,912,10,2785,99,2782,0,3212,163,3209,10,7577,2782,1392,0,8428,3209,1607,10,1393,2785,7577,0,1608,3212,8428,10,5180,7577,5181,0,6031,8428,6032,10,101,2789,7578,0,165,3216,8429,10,2789,1395,5182,0,3216,1610,6033,10,2791,7578,5185,0,3218,8429,6036,10,7578,5182,698,0,8429,6033,913,10,2788,98,2794,0,3215,162,3221,10,7579,2794,1398,0,8430,3221,1613,10,1395,2788,7579,0,1610,3215,8430,10,5182,7579,5183,0,6033,8430,6034,10,103,2792,7580,0,167,3219,8431,10,2792,1397,5184,0,3219,1612,6035,10,2795,7580,5183,0,3222,8431,6034,10,7580,5184,698,0,8431,6035,913,10,2793,102,2790,0,3220,166,3217,10,7581,2790,1396,0,8432,3217,1611,10,1397,2793,7581,0,1612,3220,8432,10,5184,7581,5185,0,6035,8432,6036,10,98,2800,7582,0,162,3227,8433,10,2800,1401,5186,0,3227,1616,6037,10,2794,7582,5189,0,3221,8433,6040,10,7582,5186,699,0,8433,6037,914,10,2801,105,2798,0,3228,169,3225,10,7583,2798,1400,0,8434,3225,1615,10,1401,2801,7583,0,1616,3228,8434,10,5186,7583,5187,0,6037,8434,6038,10,104,2796,7584,0,168,3223,8435,10,2796,1399,5188,0,3223,1614,6039,10,2799,7584,5187,0,3226,8435,6038,10,7584,5188,699,0,8435,6039,914,10,2797,103,2795,0,3224,167,3222,10,7585,2795,1398,0,8436,3222,1613,10,1399,2797,7585,0,1614,3224,8436,10,5188,7585,5189,0,6039,8436,6040,10,106,2804,7586,0,170,3231,8437,10,2804,1403,5190,0,3231,1618,6041,10,2803,7586,5193,0,3230,8437,6044,10,7586,5190,700,0,8437,6041,915,10,2805,105,2801,0,3232,169,3228,10,7587,2801,1401,0,8438,3228,1616,10,1403,2805,7587,0,1618,3232,8438,10,5190,7587,5191,0,6041,8438,6042,10,98,2783,7588,0,162,3210,8439,10,2783,1392,5192,0,3210,1607,6043,10,2800,7588,5191,0,3227,8439,6042,10,7588,5192,700,0,8439,6043,915,10,2782,99,2802,0,3209,163,3229,10,7589,2802,1402,0,8440,3229,1617,10,1392,2782,7589,0,1607,3209,8440,10,5192,7589,5193,0,6043,8440,6044,10,107,2812,7590,0,171,3239,8441,10,2812,1407,5194,0,3239,1622,6045,10,2807,7590,5197,0,3234,8441,6048,10,7590,5194,701,0,8441,6045,916,10,2813,110,2810,0,3240,174,3237,10,7591,2810,1406,0,8442,3237,1621,10,1407,2813,7591,0,1622,3240,8442,10,5194,7591,5195,0,6045,8442,6046,10,109,2808,7592,0,173,3235,8443,10,2808,1405,5196,0,3235,1620,6047,10,2811,7592,5195,0,3238,8443,6046,10,7592,5196,701,0,8443,6047,916,10,2809,108,2806,0,3236,172,3233,10,7593,2806,1404,0,8444,3233,1619,10,1405,2809,7593,0,1620,3236,8444,10,5196,7593,5197,0,6047,8444,6048,10,111,2820,7594,0,175,3247,8445,10,2820,1411,5198,0,3247,1626,6049,10,2815,7594,5201,0,3242,8445,6052,10,7594,5198,702,0,8445,6049,917,10,2821,114,2818,0,3248,178,3245,10,7595,2818,1410,0,8446,3245,1625,10,1411,2821,7595,0,1626,3248,8446,10,5198,7595,5199,0,6049,8446,6050,10,113,2816,7596,0,177,3243,8447,10,2816,1409,5200,0,3243,1624,6051,10,2819,7596,5199,0,3246,8447,6050,10,7596,5200,702,0,8447,6051,917,10,2817,112,2814,0,3244,176,3241,10,7597,2814,1408,0,8448,3241,1623,10,1409,2817,7597,0,1624,3244,8448,10,5200,7597,5201,0,6051,8448,6052,10,115,2828,7598,0,179,3255,8449,10,2828,1415,5202,0,3255,1630,6053,10,2823,7598,5205,0,3250,8449,6056,10,7598,5202,703,0,8449,6053,918,10,2829,116,2826,0,3256,180,3253,10,7599,2826,1414,0,8450,3253,1629,10,1415,2829,7599,0,1630,3256,8450,10,5202,7599,5203,0,6053,8450,6054,10,114,2824,7600,0,178,3251,8451,10,2824,1413,5204,0,3251,1628,6055,10,2827,7600,5203,0,3254,8451,6054,10,7600,5204,703,0,8451,6055,918,10,2825,110,2822,0,3252,174,3249,10,7601,2822,1412,0,8452,3249,1627,10,1413,2825,7601,0,1628,3252,8452,10,5204,7601,5205,0,6055,8452,6056,10,115,2823,7602,0,179,3250,8453,10,2823,1412,5206,0,3250,1627,6057,10,2831,7602,5209,0,3258,8453,6060,10,7602,5206,704,0,8453,6057,919,10,2822,110,2834,0,3249,174,3261,10,7603,2834,1418,0,8454,3261,1633,10,1412,2822,7603,0,1627,3249,8454,10,5206,7603,5207,0,6057,8454,6058,10,118,2832,7604,0,182,3259,8455,10,2832,1417,5208,0,3259,1632,6059,10,2835,7604,5207,0,3262,8455,6058,10,7604,5208,704,0,8455,6059,919,10,2833,117,2830,0,3260,181,3257,10,7605,2830,1416,0,8456,3257,1631,10,1417,2833,7605,0,1632,3260,8456,10,5208,7605,5209,0,6059,8456,6060,10,269,3354,7606,0,357,3781,8457,10,3354,1678,5210,0,3781,1893,6061,10,2837,7606,5213,0,3264,8457,6064,10,7606,5210,705,0,8457,6061,920,10,3355,270,2838,0,3782,358,3265,10,7607,2838,1420,0,8458,3265,1635,10,1678,3355,7607,0,1893,3782,8458,10,5210,7607,5211,0,6061,8458,6062,10,118,2835,7608,0,182,3262,8459,10,2835,1418,5212,0,3262,1633,6063,10,2839,7608,5211,0,3266,8459,6062,10,7608,5212,705,0,8459,6063,920,10,2834,110,2836,0,3261,174,3263,10,7609,2836,1419,0,8460,3263,1634,10,1418,2834,7609,0,1633,3261,8460,10,5212,7609,5213,0,6063,8460,6064,10,110,2813,7610,0,174,3240,8461,10,2813,1407,5214,0,3240,1622,6065,10,2836,7610,5217,0,3263,8461,6068,10,7610,5214,706,0,8461,6065,921,10,2812,107,2840,0,3239,171,3267,10,7611,2840,1421,0,8462,3267,1636,10,1407,2812,7611,0,1622,3239,8462,10,5214,7611,5215,0,6065,8462,6066,10,254,3361,7612,0,337,3788,8463,10,3361,1681,5216,0,3788,1896,6067,10,2841,7612,5215,0,3268,8463,6066,10,7612,5216,706,0,8463,6067,921,10,3360,269,2837,0,3787,357,3264,10,7613,2837,1419,0,8464,3264,1634,10,1681,3360,7613,0,1896,3787,8464,10,5216,7613,5217,0,6067,8464,6068,10,119,2848,7614,0,183,3275,8465,10,2848,1425,5218,0,3275,1640,6069,10,2843,7614,5221,0,3270,8465,6072,10,7614,5218,707,0,8465,6069,922,10,2849,122,2846,0,3276,186,3273,10,7615,2846,1424,0,8466,3273,1639,10,1425,2849,7615,0,1640,3276,8466,10,5218,7615,5219,0,6069,8466,6070,10,121,2844,7616,0,185,3271,8467,10,2844,1423,5220,0,3271,1638,6071,10,2847,7616,5219,0,3274,8467,6070,10,7616,5220,707,0,8467,6071,922,10,2845,120,2842,0,3272,184,3269,10,7617,2842,1422,0,8468,3269,1637,10,1423,2845,7617,0,1638,3272,8468,10,5220,7617,5221,0,6071,8468,6072,10,123,2854,7618,0,187,3281,8469,10,2854,1428,5222,0,3281,1643,6073,10,2851,7618,5225,0,3278,8469,6076,10,7618,5222,708,0,8469,6073,923,10,2855,124,2852,0,3282,188,3279,10,7619,2852,1427,0,8470,3279,1642,10,1428,2855,7619,0,1643,3282,8470,10,5222,7619,5223,0,6073,8470,6074,10,271,3362,7620,0,359,3789,8471,10,3362,1682,5224,0,3789,1897,6075,10,2853,7620,5223,0,3280,8471,6074,10,7620,5224,708,0,8471,6075,923,10,3363,240,2850,0,3790,318,3277,10,7621,2850,1426,0,8472,3277,1641,10,1682,3363,7621,0,1897,3790,8472,10,5224,7621,5225,0,6075,8472,6076,10,272,3369,7622,0,360,3796,8473,10,3369,1685,5226,0,3796,1900,6077,10,2857,7622,5229,0,3284,8473,6080,10,7622,5226,709,0,8473,6077,924,10,3368,271,2853,0,3795,361,5343,10,7623,2853,1427,0,8474,5343,2674,10,1685,3368,7623,0,1900,3795,8474,10,5226,7623,5227,0,6077,8474,6078,10,124,2858,7624,0,190,3285,8475,10,2858,1430,5228,0,3285,1645,6079,10,2852,7624,5227,0,5344,8475,6078,10,7624,5228,709,0,8475,6079,924,10,2859,125,2856,0,3286,189,3283,10,7625,2856,1429,0,8476,3283,1644,10,1430,2859,7625,0,1645,3286,8476,10,5228,7625,5229,0,6079,8476,6080,10,126,2864,7626,0,191,3291,8477,10,2864,1433,5230,0,3291,1648,6081,10,2861,7626,5233,0,3288,8477,6084,10,7626,5230,710,0,8477,6081,925,10,2865,119,2843,0,3292,194,5341,10,7627,2843,1422,0,8478,5341,2673,10,1433,2865,7627,0,1648,3292,8478,10,5230,7627,5231,0,6081,8478,6082,10,120,2862,7628,0,193,3289,8479,10,2862,1432,5232,0,3289,1647,6083,10,2842,7628,5231,0,5342,8479,6082,10,7628,5232,710,0,8479,6083,925,10,2863,127,2860,0,3290,192,3287,10,7629,2860,1431,0,8480,3287,1646,10,1432,2863,7629,0,1647,3290,8480,10,5232,7629,5233,0,6083,8480,6084,10,128,2872,7630,0,195,3299,8481,10,2872,1437,5234,0,3299,1652,6085,10,2867,7630,5237,0,3294,8481,6088,10,7630,5234,711,0,8481,6085,926,10,2873,131,2870,0,3300,198,3297,10,7631,2870,1436,0,8482,3297,1651,10,1437,2873,7631,0,1652,3300,8482,10,5234,7631,5235,0,6085,8482,6086,10,130,2868,7632,0,197,3295,8483,10,2868,1435,5236,0,3295,1650,6087,10,2871,7632,5235,0,3298,8483,6086,10,7632,5236,711,0,8483,6087,926,10,2869,129,2866,0,3296,196,3293,10,7633,2866,1434,0,8484,3293,1649,10,1435,2869,7633,0,1650,3296,8484,10,5236,7633,5237,0,6087,8484,6088,10,132,2878,7634,0,199,3305,8485,10,2878,1440,5238,0,3305,1655,6089,10,2875,7634,5241,0,3302,8485,6092,10,7634,5238,712,0,8485,6089,927,10,2879,130,2871,0,3306,197,3298,10,7635,2871,1436,0,8486,3298,1651,10,1440,2879,7635,0,1655,3306,8486,10,5238,7635,5239,0,6089,8486,6090,10,131,2876,7636,0,198,3303,8487,10,2876,1439,5240,0,3303,1654,6091,10,2870,7636,5239,0,3297,8487,6090,10,7636,5240,712,0,8487,6091,927,10,2877,133,2874,0,3304,200,3301,10,7637,2874,1438,0,8488,3301,1653,10,1439,2877,7637,0,1654,3304,8488,10,5240,7637,5241,0,6091,8488,6092,10,133,2877,7638,0,200,3304,8489,10,2877,1439,5242,0,3304,1654,6093,10,2881,7638,5245,0,3308,8489,6096,10,7638,5242,713,0,8489,6093,928,10,2876,131,2884,0,3303,198,3311,10,7639,2884,1443,0,8490,3311,1658,10,1439,2876,7639,0,1654,3303,8490,10,5242,7639,5243,0,6093,8490,6094,10,135,2882,7640,0,202,3309,8491,10,2882,1442,5244,0,3309,1657,6095,10,2885,7640,5243,0,3312,8491,6094,10,7640,5244,713,0,8491,6095,928,10,2883,134,2880,0,3310,201,3307,10,7641,2880,1441,0,8492,3307,1656,10,1442,2883,7641,0,1657,3310,8492,10,5244,7641,5245,0,6095,8492,6096,10,135,2885,7642,0,202,3312,8493,10,2885,1443,5246,0,3312,1658,6097,10,2887,7642,5249,0,3314,8493,6100,10,7642,5246,714,0,8493,6097,929,10,2884,131,2873,0,3311,198,3300,10,7643,2873,1437,0,8494,3300,1652,10,1443,2884,7643,0,1658,3311,8494,10,5246,7643,5247,0,6097,8494,6098,10,128,2888,7644,0,195,3315,8495,10,2888,1445,5248,0,3315,1660,6099,10,2872,7644,5247,0,3299,8495,6098,10,7644,5248,714,0,8495,6099,929,10,2889,136,2886,0,3316,203,3313,10,7645,2886,1444,0,8496,3313,1659,10,1445,2889,7645,0,1660,3316,8496,10,5248,7645,5249,0,6099,8496,6100,10,137,2896,7646,0,204,3323,8497,10,2896,1449,5250,0,3323,1664,6101,10,2891,7646,5253,0,3318,8497,6104,10,7646,5250,715,0,8497,6101,930,10,2897,140,2894,0,3324,207,3321,10,7647,2894,1448,0,8498,3321,1663,10,1449,2897,7647,0,1664,3324,8498,10,5250,7647,5251,0,6101,8498,6102,10,139,2892,7648,0,206,3319,8499,10,2892,1447,5252,0,3319,1662,6103,10,2895,7648,5251,0,3322,8499,6102,10,7648,5252,715,0,8499,6103,930,10,2893,138,2890,0,3320,205,3317,10,7649,2890,1446,0,8500,3317,1661,10,1447,2893,7649,0,1662,3320,8500,10,5252,7649,5253,0,6103,8500,6104,10,141,2904,7650,0,208,3331,8501,10,2904,1453,5254,0,3331,1668,6105,10,2899,7650,5257,0,3326,8501,6108,10,7650,5254,716,0,8501,6105,931,10,2905,144,2902,0,3332,211,3329,10,7651,2902,1452,0,8502,3329,1667,10,1453,2905,7651,0,1668,3332,8502,10,5254,7651,5255,0,6105,8502,6106,10,143,2900,7652,0,210,3327,8503,10,2900,1451,5256,0,3327,1666,6107,10,2903,7652,5255,0,3330,8503,6106,10,7652,5256,716,0,8503,6107,931,10,2901,142,2898,0,3328,209,3325,10,7653,2898,1450,0,8504,3325,1665,10,1451,2901,7653,0,1666,3328,8504,10,5256,7653,5257,0,6107,8504,6108,10,145,2912,7654,0,212,3339,8505,10,2912,1457,5258,0,3339,1672,6109,10,2907,7654,5261,0,3334,8505,6112,10,7654,5258,717,0,8505,6109,932,10,2913,146,2910,0,3340,213,3337,10,7655,2910,1456,0,8506,3337,1671,10,1457,2913,7655,0,1672,3340,8506,10,5258,7655,5259,0,6109,8506,6110,10,144,2908,7656,0,211,3335,8507,10,2908,1455,5260,0,3335,1670,6111,10,2911,7656,5259,0,3338,8507,6110,10,7656,5260,717,0,8507,6111,932,10,2909,140,2906,0,3336,207,3333,10,7657,2906,1454,0,8508,3333,1669,10,1455,2909,7657,0,1670,3336,8508,10,5260,7657,5261,0,6111,8508,6112,10,145,2907,7658,0,212,3334,8509,10,2907,1454,5262,0,3334,1669,6113,10,2915,7658,5265,0,3342,8509,6116,10,7658,5262,718,0,8509,6113,933,10,2906,140,2916,0,3333,207,3343,10,7659,2916,1459,0,8510,3343,1674,10,1454,2906,7659,0,1669,3333,8510,10,5262,7659,5263,0,6113,8510,6114,10,273,3372,7660,0,362,3799,8511,10,3372,1687,5264,0,3799,1902,6115,10,2917,7660,5263,0,3344,8511,6114,10,7660,5264,718,0,8511,6115,933,10,3373,236,2914,0,3800,314,3341,10,7661,2914,1458,0,8512,3341,1673,10,1687,3373,7661,0,1902,3800,8512,10,5264,7661,5265,0,6115,8512,6116,10,140,2897,7662,0,207,3324,8513,10,2897,1449,5266,0,3324,1664,6117,10,2916,7662,5269,0,3343,8513,6120,10,7662,5266,719,0,8513,6117,934,10,2896,137,2918,0,3323,204,3345,10,7663,2918,1460,0,8514,3345,1675,10,1449,2896,7663,0,1664,3323,8514,10,5266,7663,5267,0,6117,8514,6118,10,229,3377,7664,0,307,3804,8515,10,3377,1689,5268,0,3804,1904,6119,10,2919,7664,5267,0,3346,8515,6118,10,7664,5268,719,0,8515,6119,934,10,3376,273,2917,0,3803,362,3344,10,7665,2917,1459,0,8516,3344,1674,10,1689,3376,7665,0,1904,3803,8516,10,5268,7665,5269,0,6119,8516,6120,10,147,2926,7666,0,214,3353,8517,10,2926,1464,5270,0,3353,1679,6121,10,2921,7666,5273,0,3348,8517,6124,10,7666,5270,720,0,8517,6121,935,10,2927,150,2924,0,3354,217,3351,10,7667,2924,1463,0,8518,3351,1678,10,1464,2927,7667,0,1679,3354,8518,10,5270,7667,5271,0,6121,8518,6122,10,149,2922,7668,0,216,3349,8519,10,2922,1462,5272,0,3349,1677,6123,10,2925,7668,5271,0,3352,8519,6122,10,7668,5272,720,0,8519,6123,935,10,2923,148,2920,0,3350,215,3347,10,7669,2920,1461,0,8520,3347,1676,10,1462,2923,7669,0,1677,3350,8520,10,5272,7669,5273,0,6123,8520,6124,10,151,2934,7670,0,218,3361,8521,10,2934,1468,5274,0,3361,1683,6125,10,2929,7670,5277,0,3356,8521,6128,10,7670,5274,721,0,8521,6125,936,10,2935,154,2932,0,3362,221,3359,10,7671,2932,1467,0,8522,3359,1682,10,1468,2935,7671,0,1683,3362,8522,10,5274,7671,5275,0,6125,8522,6126,10,153,2930,7672,0,220,3357,8523,10,2930,1466,5276,0,3357,1681,6127,10,2933,7672,5275,0,3360,8523,6126,10,7672,5276,721,0,8523,6127,936,10,2931,152,2928,0,3358,219,3355,10,7673,2928,1465,0,8524,3355,1680,10,1466,2931,7673,0,1681,3358,8524,10,5276,7673,5277,0,6127,8524,6128,10,154,2938,7674,0,221,3365,8525,10,2938,1470,5278,0,3365,1685,6129,10,2932,7674,5281,0,3359,8525,6132,10,7674,5278,722,0,8525,6129,937,10,2939,126,2861,0,3366,191,3288,10,7675,2861,1431,0,8526,3288,1646,10,1470,2939,7675,0,1685,3366,8526,10,5278,7675,5279,0,6129,8526,6130,10,127,2936,7676,0,192,3363,8527,10,2936,1469,5280,0,3363,1684,6131,10,2860,7676,5279,0,3287,8527,6130,10,7676,5280,722,0,8527,6131,937,10,2937,153,2933,0,3364,220,3360,10,7677,2933,1467,0,8528,3360,1682,10,1469,2937,7677,0,1684,3364,8528,10,5280,7677,5281,0,6131,8528,6132,10,125,2942,7678,0,189,3369,8529,10,2942,1472,5282,0,3369,1687,6133,10,2856,7678,5285,0,3283,8529,6136,10,7678,5282,723,0,8529,6133,938,10,2943,150,2940,0,3370,217,3367,10,7679,2940,1471,0,8530,3367,1686,10,1472,2943,7679,0,1687,3370,8530,10,5282,7679,5283,0,6133,8530,6134,10,274,3378,7680,0,363,3805,8531,10,3378,1690,5284,0,3805,1905,6135,10,2941,7680,5283,0,3368,8531,6134,10,7680,5284,723,0,8531,6135,938,10,3379,272,2857,0,3806,360,3284,10,7681,2857,1429,0,8532,3284,1644,10,1690,3379,7681,0,1905,3806,8532,10,5284,7681,5285,0,6135,8532,6136,10,150,2927,7682,0,217,3354,8533,10,2927,1464,5286,0,3354,1679,6137,10,2940,7682,5289,0,3367,8533,6140,10,7682,5286,724,0,8533,6137,939,10,2926,147,2944,0,3353,214,3371,10,7683,2944,1473,0,8534,3371,1688,10,1464,2926,7683,0,1679,3353,8534,10,5286,7683,5287,0,6137,8534,6138,10,275,3385,7684,0,364,3812,8535,10,3385,1693,5288,0,3812,1908,6139,10,2945,7684,5287,0,3372,8535,6138,10,7684,5288,724,0,8535,6139,939,10,3384,274,2941,0,3811,363,3368,10,7685,2941,1471,0,8536,3368,1686,10,1693,3384,7685,0,1908,3811,8536,10,5288,7685,5289,0,6139,8536,6140,10,118,2950,7686,0,182,3377,8537,10,2950,1476,5290,0,3377,1691,6141,10,2832,7686,5293,0,3259,8537,6144,10,7686,5290,725,0,8537,6141,940,10,2951,156,2948,0,3378,223,3375,10,7687,2948,1475,0,8538,3375,1690,10,1476,2951,7687,0,1691,3378,8538,10,5290,7687,5291,0,6141,8538,6142,10,155,2946,7688,0,222,3373,8539,10,2946,1474,5292,0,3373,1689,6143,10,2949,7688,5291,0,3376,8539,6142,10,7688,5292,725,0,8539,6143,940,10,2947,117,2833,0,3374,181,3260,10,7689,2833,1417,0,8540,3260,1632,10,1474,2947,7689,0,1689,3374,8540,10,5292,7689,5293,0,6143,8540,6144,10,157,2956,7690,0,224,3383,8541,10,2956,1479,5294,0,3383,1694,6145,10,2953,7690,5297,0,3380,8541,6148,10,7690,5294,726,0,8541,6145,941,10,2957,158,2954,0,3384,225,3381,10,7691,2954,1478,0,8542,3381,1693,10,1479,2957,7691,0,1694,3384,8542,10,5294,7691,5295,0,6145,8542,6146,10,155,2949,7692,0,222,3376,8543,10,2949,1475,5296,0,3376,1690,6147,10,2955,7692,5295,0,3382,8543,6146,10,7692,5296,726,0,8543,6147,941,10,2948,156,2952,0,3375,223,3379,10,7693,2952,1477,0,8544,3379,1692,10,1475,2948,7693,0,1690,3375,8544,10,5296,7693,5297,0,6147,8544,6148,10,159,2962,7694,0,226,3389,8545,10,2962,1482,5298,0,3389,1697,6149,10,2959,7694,5301,0,3386,8545,6152,10,7694,5298,727,0,8545,6149,942,10,2963,160,2960,0,3390,227,3387,10,7695,2960,1481,0,8546,3387,1696,10,1482,2963,7695,0,1697,3390,8546,10,5298,7695,5299,0,6149,8546,6150,10,157,2953,7696,0,224,3380,8547,10,2953,1477,5300,0,3380,1692,6151,10,2961,7696,5299,0,3388,8547,6150,10,7696,5300,727,0,8547,6151,942,10,2952,156,2958,0,3379,223,3385,10,7697,2958,1480,0,8548,3385,1695,10,1477,2952,7697,0,1692,3379,8548,10,5300,7697,5301,0,6151,8548,6152,10,159,2959,7698,0,226,3386,8549,10,2959,1480,5302,0,3386,1695,6153,10,2965,7698,5305,0,3392,8549,6156,10,7698,5302,728,0,8549,6153,943,10,2958,156,2966,0,3385,223,3393,10,7699,2966,1484,0,8550,3393,1699,10,1480,2958,7699,0,1695,3385,8550,10,5302,7699,5303,0,6153,8550,6154,10,147,2921,7700,0,214,3348,8551,10,2921,1461,5304,0,3348,1676,6155,10,2967,7700,5303,0,3394,8551,6154,10,7700,5304,728,0,8551,6155,943,10,2920,148,2964,0,3347,215,3391,10,7701,2964,1483,0,8552,3391,1698,10,1461,2920,7701,0,1676,3347,8552,10,5304,7701,5305,0,6155,8552,6156,10,147,2967,7702,0,214,3394,8553,10,2967,1484,5306,0,3394,1699,6157,10,2944,7702,5309,0,3371,8553,6160,10,7702,5306,729,0,8553,6157,944,10,2966,156,2968,0,3393,223,3395,10,7703,2968,1485,0,8554,3395,1700,10,1484,2966,7703,0,1699,3393,8554,10,5306,7703,5307,0,6157,8554,6158,10,276,3386,7704,0,365,3813,8555,10,3386,1694,5308,0,3813,1909,6159,10,2969,7704,5307,0,3396,8555,6158,10,7704,5308,729,0,8555,6159,944,10,3387,275,2945,0,3814,364,3372,10,7705,2945,1473,0,8556,3372,1688,10,1694,3387,7705,0,1909,3814,8556,10,5308,7705,5309,0,6159,8556,6160,10,156,2951,7706,0,223,3378,8557,10,2951,1476,5310,0,3378,1691,6161,10,2968,7706,5313,0,3395,8557,6164,10,7706,5310,730,0,8557,6161,945,10,2950,118,2839,0,3377,182,3266,10,7707,2839,1420,0,8558,3266,1635,10,1476,2950,7707,0,1691,3377,8558,10,5310,7707,5311,0,6161,8558,6162,10,270,3391,7708,0,358,3818,8559,10,3391,1696,5312,0,3818,1911,6163,10,2838,7708,5311,0,3265,8559,6162,10,7708,5312,730,0,8559,6163,945,10,3390,276,2969,0,3817,365,3396,10,7709,2969,1485,0,8560,3396,1700,10,1696,3390,7709,0,1911,3817,8560,10,5312,7709,5313,0,6163,8560,6164,10,135,2974,7710,0,202,3401,8561,10,2974,1488,5314,0,3401,1703,6165,10,2882,7710,5317,0,3309,8561,6168,10,7710,5314,731,0,8561,6165,946,10,2975,162,2972,0,3402,229,3399,10,7711,2972,1487,0,8562,3399,1702,10,1488,2975,7711,0,1703,3402,8562,10,5314,7711,5315,0,6165,8562,6166,10,161,2970,7712,0,228,3397,8563,10,2970,1486,5316,0,3397,1701,6167,10,2973,7712,5315,0,3400,8563,6166,10,7712,5316,731,0,8563,6167,946,10,2971,134,2883,0,3398,201,3310,10,7713,2883,1442,0,8564,3310,1657,10,1486,2971,7713,0,1701,3398,8564,10,5316,7713,5317,0,6167,8564,6168,10,161,2973,7714,0,228,3400,8565,10,2973,1487,5318,0,3400,1702,6169,10,2977,7714,5321,0,3404,8565,6172,10,7714,5318,732,0,8565,6169,947,10,2972,162,2980,0,3399,229,3407,10,7715,2980,1491,0,8566,3407,1706,10,1487,2972,7715,0,1702,3399,8566,10,5318,7715,5319,0,6169,8566,6170,10,164,2978,7716,0,231,3405,8567,10,2978,1490,5320,0,3405,1705,6171,10,2981,7716,5319,0,3408,8567,6170,10,7716,5320,732,0,8567,6171,947,10,2979,163,2976,0,3406,230,3403,10,7717,2976,1489,0,8568,3403,1704,10,1490,2979,7717,0,1705,3406,8568,10,5320,7717,5321,0,6171,8568,6172,10,165,2988,7718,0,232,3415,8569,10,2988,1495,5322,0,3415,1710,6173,10,2983,7718,5325,0,3410,8569,6176,10,7718,5322,733,0,8569,6173,948,10,2989,168,2986,0,3416,235,3413,10,7719,2986,1494,0,8570,3413,1709,10,1495,2989,7719,0,1710,3416,8570,10,5322,7719,5323,0,6173,8570,6174,10,167,2984,7720,0,234,3411,8571,10,2984,1493,5324,0,3411,1708,6175,10,2987,7720,5323,0,3414,8571,6174,10,7720,5324,733,0,8571,6175,948,10,2985,166,2982,0,3412,233,3409,10,7721,2982,1492,0,8572,3409,1707,10,1493,2985,7721,0,1708,3412,8572,10,5324,7721,5325,0,6175,8572,6176,10,168,2989,7722,0,235,3416,8573,10,2989,1495,5326,0,3416,1710,6177,10,2991,7722,5329,0,3418,8573,6180,10,7722,5326,734,0,8573,6177,949,10,2988,165,2992,0,3415,232,3419,10,7723,2992,1497,0,8574,3419,1712,10,1495,2988,7723,0,1710,3415,8574,10,5326,7723,5327,0,6177,8574,6178,10,396,3859,7724,0,237,5435,8575,10,3859,1930,5328,0,5435,2720,6179,10,2993,7724,5327,0,3420,8575,6178,10,7724,5328,734,0,8575,6179,949,10,3858,169,2990,0,5436,236,3417,10,7725,2990,1496,0,8576,3417,1711,10,1930,3858,7725,0,2720,5436,8576,10,5328,7725,5329,0,6179,8576,6180,10,392,4003,7726,0,238,5493,8577,10,4003,2002,5330,0,5493,2749,6181,10,2995,7726,5333,0,3422,8577,6184,10,7726,5330,735,0,8577,6181,950,10,4002,396,2993,0,5494,237,3420,10,7727,2993,1497,0,8578,3420,1712,10,2002,4002,7727,0,2749,5494,8578,10,5330,7727,5331,0,6181,8578,6182,10,165,2996,7728,0,232,3423,8579,10,2996,1499,5332,0,3423,1714,6183,10,2992,7728,5331,0,3419,8579,6182,10,7728,5332,735,0,8579,6183,950,10,2997,170,2994,0,3424,239,3421,10,7729,2994,1498,0,8580,3421,1713,10,1499,2997,7729,0,1714,3424,8580,10,5332,7729,5333,0,6183,8580,6184,10,171,3004,7730,0,240,3431,8581,10,3004,1503,5334,0,3431,1718,6185,10,2999,7730,5337,0,3426,8581,6188,10,7730,5334,736,0,8581,6185,951,10,3005,174,3002,0,3432,243,3429,10,7731,3002,1502,0,8582,3429,1717,10,1503,3005,7731,0,1718,3432,8582,10,5334,7731,5335,0,6185,8582,6186,10,173,3000,7732,0,242,3427,8583,10,3000,1501,5336,0,3427,1716,6187,10,3003,7732,5335,0,3430,8583,6186,10,7732,5336,736,0,8583,6187,951,10,3001,172,2998,0,3428,241,3425,10,7733,2998,1500,0,8584,3425,1715,10,1501,3001,7733,0,1716,3428,8584,10,5336,7733,5337,0,6187,8584,6188,10,175,3012,7734,0,244,3439,8585,10,3012,1507,5338,0,3439,1722,6189,10,3007,7734,5341,0,3434,8585,6192,10,7734,5338,737,0,8585,6189,952,10,3013,172,3010,0,3440,241,3437,10,7735,3010,1506,0,8586,3437,1721,10,1507,3013,7735,0,1722,3440,8586,10,5338,7735,5339,0,6189,8586,6190,10,177,3008,7736,0,246,3435,8587,10,3008,1505,5340,0,3435,1720,6191,10,3011,7736,5339,0,3438,8587,6190,10,7736,5340,737,0,8587,6191,952,10,3009,176,3006,0,3436,245,3433,10,7737,3006,1504,0,8588,3433,1719,10,1505,3009,7737,0,1720,3436,8588,10,5340,7737,5341,0,6191,8588,6192,10,173,3003,7738,0,242,3430,8589,10,3003,1502,5342,0,3430,1717,6193,10,3015,7738,5345,0,3442,8589,6196,10,7738,5342,738,0,8589,6193,953,10,3002,174,3018,0,3429,243,3445,10,7739,3018,1510,0,8590,3445,1725,10,1502,3002,7739,0,1717,3429,8590,10,5342,7739,5343,0,6193,8590,6194,10,179,3016,7740,0,248,3443,8591,10,3016,1509,5344,0,3443,1724,6195,10,3019,7740,5343,0,3446,8591,6194,10,7740,5344,738,0,8591,6195,953,10,3017,178,3014,0,3444,247,3441,10,7741,3014,1508,0,8592,3441,1723,10,1509,3017,7741,0,1724,3444,8592,10,5344,7741,5345,0,6195,8592,6196,10,180,3026,7742,0,249,3453,8593,10,3026,1514,5346,0,3453,1729,6197,10,3021,7742,5349,0,3448,8593,6200,10,7742,5346,739,0,8593,6197,954,10,3027,183,3024,0,3454,252,3451,10,7743,3024,1513,0,8594,3451,1728,10,1514,3027,7743,0,1729,3454,8594,10,5346,7743,5347,0,6197,8594,6198,10,182,3022,7744,0,251,3449,8595,10,3022,1512,5348,0,3449,1727,6199,10,3025,7744,5347,0,3452,8595,6198,10,7744,5348,739,0,8595,6199,954,10,3023,181,3020,0,3450,250,3447,10,7745,3020,1511,0,8596,3447,1726,10,1512,3023,7745,0,1727,3450,8596,10,5348,7745,5349,0,6199,8596,6200,10,184,3032,7746,0,253,3459,8597,10,3032,1517,5350,0,3459,1732,6201,10,3029,7746,5353,0,3456,8597,6204,10,7746,5350,740,0,8597,6201,955,10,3033,181,3023,0,3460,250,3450,10,7747,3023,1512,0,8598,3450,1727,10,1517,3033,7747,0,1732,3460,8598,10,5350,7747,5351,0,6201,8598,6202,10,182,3030,7748,0,251,3457,8599,10,3030,1516,5352,0,3457,1731,6203,10,3022,7748,5351,0,3449,8599,6202,10,7748,5352,740,0,8599,6203,955,10,3031,185,3028,0,3458,254,3455,10,7749,3028,1515,0,8600,3455,1730,10,1516,3031,7749,0,1731,3458,8600,10,5352,7749,5353,0,6203,8600,6204,10,186,3040,7750,0,255,3467,8601,10,3040,1521,5354,0,3467,1736,6205,10,3035,7750,5357,0,3462,8601,6208,10,7750,5354,741,0,8601,6205,956,10,3041,188,3038,0,3468,257,3465,10,7751,3038,1520,0,8602,3465,1735,10,1521,3041,7751,0,1736,3468,8602,10,5354,7751,5355,0,6205,8602,6206,10,187,3036,7752,0,256,3463,8603,10,3036,1519,5356,0,3463,1734,6207,10,3039,7752,5355,0,3466,8603,6206,10,7752,5356,741,0,8603,6207,956,10,3037,185,3034,0,3464,254,3461,10,7753,3034,1518,0,8604,3461,1733,10,1519,3037,7753,0,1734,3464,8604,10,5356,7753,5357,0,6207,8604,6208,10,141,3048,7754,0,208,3475,8605,10,3048,1525,5358,0,3475,1740,6209,10,3043,7754,5361,0,3470,8605,6212,10,7754,5358,742,0,8605,6209,957,10,3049,190,3046,0,3476,259,3473,10,7755,3046,1524,0,8606,3473,1739,10,1525,3049,7755,0,1740,3476,8606,10,5358,7755,5359,0,6209,8606,6210,10,189,3044,7756,0,258,3471,8607,10,3044,1523,5360,0,3471,1738,6211,10,3047,7756,5359,0,3474,8607,6210,10,7756,5360,742,0,8607,6211,957,10,3045,139,3042,0,3472,206,3469,10,7757,3042,1522,0,8608,3469,1737,10,1523,3045,7757,0,1738,3472,8608,10,5360,7757,5361,0,6211,8608,6212,10,138,2893,7758,0,205,3320,8609,10,2893,1447,5362,0,3320,1662,6213,10,3051,7758,5365,0,3478,8609,6216,10,7758,5362,743,0,8609,6213,958,10,2892,139,3045,0,3319,206,3472,10,7759,3045,1523,0,8610,3472,1738,10,1447,2892,7759,0,1662,3319,8610,10,5362,7759,5363,0,6213,8610,6214,10,189,3052,7760,0,258,3479,8611,10,3052,1527,5364,0,3479,1742,6215,10,3044,7760,5363,0,3471,8611,6214,10,7760,5364,743,0,8611,6215,958,10,3053,191,3050,0,3480,260,3477,10,7761,3050,1526,0,8612,3477,1741,10,1527,3053,7761,0,1742,3480,8612,10,5364,7761,5365,0,6215,8612,6216,10,192,3056,7762,0,261,3483,8613,10,3056,1529,5366,0,3483,1744,6217,10,3055,7762,5369,0,3482,8613,6220,10,7762,5366,744,0,8613,6217,959,10,3057,191,3053,0,3484,260,3480,10,7763,3053,1527,0,8614,3480,1742,10,1529,3057,7763,0,1744,3484,8614,10,5366,7763,5367,0,6217,8614,6218,10,189,3047,7764,0,258,3474,8615,10,3047,1524,5368,0,3474,1739,6219,10,3052,7764,5367,0,3479,8615,6218,10,7764,5368,744,0,8615,6219,959,10,3046,190,3054,0,3473,259,3481,10,7765,3054,1528,0,8616,3481,1743,10,1524,3046,7765,0,1739,3473,8616,10,5368,7765,5369,0,6219,8616,6220,10,193,3064,7766,0,262,3491,8617,10,3064,1533,5370,0,3491,1748,6221,10,3059,7766,5373,0,3486,8617,6224,10,7766,5370,745,0,8617,6221,960,10,3065,196,3062,0,3492,265,3489,10,7767,3062,1532,0,8618,3489,1747,10,1533,3065,7767,0,1748,3492,8618,10,5370,7767,5371,0,6221,8618,6222,10,195,3060,7768,0,264,3487,8619,10,3060,1531,5372,0,3487,1746,6223,10,3063,7768,5371,0,3490,8619,6222,10,7768,5372,745,0,8619,6223,960,10,3061,194,3058,0,3488,263,3485,10,7769,3058,1530,0,8620,3485,1745,10,1531,3061,7769,0,1746,3488,8620,10,5372,7769,5373,0,6223,8620,6224,10,111,3072,7770,0,175,3499,8621,10,3072,1537,5374,0,3499,1752,6225,10,3067,7770,5377,0,3494,8621,6228,10,7770,5374,746,0,8621,6225,961,10,3073,196,3070,0,3500,265,3497,10,7771,3070,1536,0,8622,3497,1751,10,1537,3073,7771,0,1752,3500,8622,10,5374,7771,5375,0,6225,8622,6226,10,197,3068,7772,0,266,3495,8623,10,3068,1535,5376,0,3495,1750,6227,10,3071,7772,5375,0,3498,8623,6226,10,7772,5376,746,0,8623,6227,961,10,3069,109,3066,0,3496,173,3493,10,7773,3066,1534,0,8624,3493,1749,10,1535,3069,7773,0,1750,3496,8624,10,5376,7773,5377,0,6227,8624,6228,10,108,2809,7774,0,172,3236,8625,10,2809,1405,5378,0,3236,1620,6229,10,3075,7774,5381,0,3502,8625,6232,10,7774,5378,747,0,8625,6229,962,10,2808,109,3069,0,3235,173,3496,10,7775,3069,1535,0,8626,3496,1750,10,1405,2808,7775,0,1620,3235,8626,10,5378,7775,5379,0,6229,8626,6230,10,197,3076,7776,0,266,3503,8627,10,3076,1539,5380,0,3503,1754,6231,10,3068,7776,5379,0,3495,8627,6230,10,7776,5380,747,0,8627,6231,962,10,3077,198,3074,0,3504,267,3501,10,7777,3074,1538,0,8628,3501,1753,10,1539,3077,7777,0,1754,3504,8628,10,5380,7777,5381,0,6231,8628,6232,10,199,3084,7778,0,268,3511,8629,10,3084,1543,5382,0,3511,1758,6233,10,3079,7778,5385,0,3506,8629,6236,10,7778,5382,748,0,8629,6233,963,10,3085,201,3082,0,3512,270,3509,10,7779,3082,1542,0,8630,3509,1757,10,1543,3085,7779,0,1758,3512,8630,10,5382,7779,5383,0,6233,8630,6234,10,158,3080,7780,0,225,3507,8631,10,3080,1541,5384,0,3507,1756,6235,10,3083,7780,5383,0,3510,8631,6234,10,7780,5384,748,0,8631,6235,963,10,3081,200,3078,0,3508,269,3505,10,7781,3078,1540,0,8632,3505,1755,10,1541,3081,7781,0,1756,3508,8632,10,5384,7781,5385,0,6235,8632,6236,10,117,2947,7782,0,181,3374,8633,10,2947,1474,5386,0,3374,1689,6237,10,2830,7782,5389,0,3257,8633,6240,10,7782,5386,749,0,8633,6237,964,10,2946,155,3088,0,3373,222,3515,10,7783,3088,1545,0,8634,3515,1760,10,1474,2946,7783,0,1689,3373,8634,10,5386,7783,5387,0,6237,8634,6238,10,202,3086,7784,0,271,3513,8635,10,3086,1544,5388,0,3513,1759,6239,10,3089,7784,5387,0,3516,8635,6238,10,7784,5388,749,0,8635,6239,964,10,3087,115,2831,0,3514,179,3258,10,7785,2831,1416,0,8636,3258,1631,10,1544,3087,7785,0,1759,3514,8636,10,5388,7785,5389,0,6239,8636,6240,10,116,3094,7786,0,180,3521,8637,10,3094,1548,5390,0,3521,1763,6241,10,3091,7786,5393,0,3518,8637,6244,10,7786,5390,750,0,8637,6241,965,10,3095,201,3085,0,3522,270,3512,10,7787,3085,1543,0,8638,3512,1758,10,1548,3095,7787,0,1763,3522,8638,10,5390,7787,5391,0,6241,8638,6242,10,199,3092,7788,0,268,3519,8639,10,3092,1547,5392,0,3519,1762,6243,10,3084,7788,5391,0,3511,8639,6242,10,7788,5392,750,0,8639,6243,965,10,3093,203,3090,0,3520,272,3517,10,7789,3090,1546,0,8640,3517,1761,10,1547,3093,7789,0,1762,3520,8640,10,5392,7789,5393,0,6243,8640,6244,10,204,3100,7790,0,273,3527,8641,10,3100,1551,5394,0,3527,1766,6245,10,3097,7790,5397,0,3524,8641,6248,10,7790,5394,751,0,8641,6245,966,10,3101,205,3098,0,3528,274,3525,10,7791,3098,1550,0,8642,3525,1765,10,1551,3101,7791,0,1766,3528,8642,10,5394,7791,5395,0,6245,8642,6246,10,151,2929,7792,0,218,3356,8643,10,2929,1465,5396,0,3356,1680,6247,10,3099,7792,5395,0,3526,8643,6246,10,7792,5396,751,0,8643,6247,966,10,2928,152,3096,0,3355,219,3523,10,7793,3096,1549,0,8644,3523,1764,10,1465,2928,7793,0,1680,3355,8644,10,5396,7793,5397,0,6247,8644,6248,10,148,2923,7794,0,215,3350,8645,10,2923,1462,5398,0,3350,1677,6249,10,2964,7794,5401,0,3391,8645,6252,10,7794,5398,752,0,8645,6249,967,10,2922,149,3104,0,3349,216,3531,10,7795,3104,1553,0,8646,3531,1768,10,1462,2922,7795,0,1677,3349,8646,10,5398,7795,5399,0,6249,8646,6250,10,206,3102,7796,0,275,3529,8647,10,3102,1552,5400,0,3529,1767,6251,10,3105,7796,5399,0,3532,8647,6250,10,7796,5400,752,0,8647,6251,967,10,3103,159,2965,0,3530,226,3392,10,7797,2965,1483,0,8648,3392,1698,10,1552,3103,7797,0,1767,3530,8648,10,5400,7797,5401,0,6251,8648,6252,10,160,2963,7798,0,227,3390,8649,10,2963,1482,5402,0,3390,1697,6253,10,3107,7798,5405,0,3534,8649,6256,10,7798,5402,753,0,8649,6253,968,10,2962,159,3103,0,3389,226,3530,10,7799,3103,1552,0,8650,3530,1767,10,1482,2962,7799,0,1697,3389,8650,10,5402,7799,5403,0,6253,8650,6254,10,206,3108,7800,0,275,3535,8651,10,3108,1555,5404,0,3535,1770,6255,10,3102,7800,5403,0,3529,8651,6254,10,7800,5404,753,0,8651,6255,968,10,3109,205,3106,0,3536,274,3533,10,7801,3106,1554,0,8652,3533,1769,10,1555,3109,7801,0,1770,3536,8652,10,5404,7801,5405,0,6255,8652,6256,10,207,3114,7802,0,276,3541,8653,10,3114,1558,5406,0,3541,1773,6257,10,3111,7802,5409,0,3538,8653,6260,10,7802,5406,754,0,8653,6257,969,10,3115,175,3007,0,3542,244,3434,10,7803,3007,1504,0,8654,3434,1719,10,1558,3115,7803,0,1773,3542,8654,10,5406,7803,5407,0,6257,8654,6258,10,176,3112,7804,0,245,3539,8655,10,3112,1557,5408,0,3539,1772,6259,10,3006,7804,5407,0,3433,8655,6258,10,7804,5408,754,0,8655,6259,969,10,3113,208,3110,0,3540,277,3537,10,7805,3110,1556,0,8656,3537,1771,10,1557,3113,7805,0,1772,3540,8656,10,5408,7805,5409,0,6259,8656,6260,10,209,3120,7806,0,278,3547,8657,10,3120,1561,5410,0,3547,1776,6261,10,3117,7806,5413,0,3544,8657,6264,10,7806,5410,755,0,8657,6261,970,10,3121,175,3115,0,3548,244,3542,10,7807,3115,1558,0,8658,3542,1773,10,1561,3121,7807,0,1776,3548,8658,10,5410,7807,5411,0,6261,8658,6262,10,207,3118,7808,0,276,3545,8659,10,3118,1560,5412,0,3545,1775,6263,10,3114,7808,5411,0,3541,8659,6262,10,7808,5412,755,0,8659,6263,970,10,3119,210,3116,0,3546,279,3543,10,7809,3116,1559,0,8660,3543,1774,10,1560,3119,7809,0,1775,3546,8660,10,5412,7809,5413,0,6263,8660,6264,10,207,3124,7810,0,280,3551,8661,10,3124,1563,5414,0,3551,1778,6265,10,3118,7810,5417,0,5354,8661,6268,10,7810,5414,756,0,8661,6265,971,10,3125,204,3097,0,3552,273,3524,10,7811,3097,1549,0,8662,3524,1764,10,1563,3125,7811,0,1778,3552,8662,10,5414,7811,5415,0,6265,8662,6266,10,152,3122,7812,0,219,3549,8663,10,3122,1562,5416,0,3549,1777,6267,10,3096,7812,5415,0,3523,8663,6266,10,7812,5416,756,0,8663,6267,971,10,3123,210,3119,0,3550,281,5353,10,7813,3119,1560,0,8664,5353,2679,10,1562,3123,7813,0,1777,3550,8664,10,5416,7813,5417,0,6267,8664,6268,10,207,3111,7814,0,280,5351,8665,10,3111,1556,5418,0,5351,2678,6269,10,3124,7814,5421,0,3551,8665,6272,10,7814,5418,757,0,8665,6269,972,10,3110,208,3128,0,5352,283,3555,10,7815,3128,1565,0,8666,3555,1780,10,1556,3110,7815,0,2678,5352,8666,10,5418,7815,5419,0,6269,8666,6270,10,211,3126,7816,0,282,3553,8667,10,3126,1564,5420,0,3553,1779,6271,10,3129,7816,5419,0,3556,8667,6270,10,7816,5420,757,0,8667,6271,972,10,3127,204,3125,0,3554,273,3552,10,7817,3125,1563,0,8668,3552,1778,10,1564,3127,7817,0,1779,3554,8668,10,5420,7817,5421,0,6271,8668,6272,10,188,3134,7818,0,257,3561,8669,10,3134,1568,5422,0,3561,1783,6273,10,3038,7818,5425,0,3465,8669,6276,10,7818,5422,758,0,8669,6273,973,10,3135,213,3132,0,3562,285,3559,10,7819,3132,1567,0,8670,3559,1782,10,1568,3135,7819,0,1783,3562,8670,10,5422,7819,5423,0,6273,8670,6274,10,212,3130,7820,0,284,3557,8671,10,3130,1566,5424,0,3557,1781,6275,10,3133,7820,5423,0,3560,8671,6274,10,7820,5424,758,0,8671,6275,973,10,3131,187,3039,0,3558,256,3466,10,7821,3039,1520,0,8672,3466,1735,10,1566,3131,7821,0,1781,3558,8672,10,5424,7821,5425,0,6275,8672,6276,10,212,3140,7822,0,284,3567,8673,10,3140,1571,5426,0,3567,1786,6277,10,3130,7822,5429,0,3557,8673,6280,10,7822,5426,759,0,8673,6277,974,10,3141,215,3138,0,3568,287,3565,10,7823,3138,1570,0,8674,3565,1785,10,1571,3141,7823,0,1786,3568,8674,10,5426,7823,5427,0,6277,8674,6278,10,214,3136,7824,0,286,3563,8675,10,3136,1569,5428,0,3563,1784,6279,10,3139,7824,5427,0,3566,8675,6278,10,7824,5428,759,0,8675,6279,974,10,3137,187,3131,0,3564,256,3558,10,7825,3131,1566,0,8676,3558,1781,10,1569,3137,7825,0,1784,3564,8676,10,5428,7825,5429,0,6279,8676,6280,10,212,3144,7826,0,288,3571,8677,10,3144,1573,5430,0,3571,1788,6281,10,3140,7826,5433,0,5358,8677,6284,10,7826,5430,760,0,8677,6281,975,10,3145,199,3079,0,3572,268,3506,10,7827,3079,1540,0,8678,3506,1755,10,1573,3145,7827,0,1788,3572,8678,10,5430,7827,5431,0,6281,8678,6282,10,200,3142,7828,0,269,3569,8679,10,3142,1572,5432,0,3569,1787,6283,10,3078,7828,5431,0,3505,8679,6282,10,7828,5432,760,0,8679,6283,975,10,3143,215,3141,0,3570,289,5357,10,7829,3141,1571,0,8680,5357,2681,10,1572,3143,7829,0,1787,3570,8680,10,5432,7829,5433,0,6283,8680,6284,10,203,3093,7830,0,272,3520,8681,10,3093,1547,5434,0,3520,1762,6285,10,3147,7830,5437,0,3574,8681,6288,10,7830,5434,761,0,8681,6285,976,10,3092,199,3145,0,3519,268,3572,10,7831,3145,1573,0,8682,3572,1788,10,1547,3092,7831,0,1762,3519,8682,10,5434,7831,5435,0,6285,8682,6286,10,212,3133,7832,0,288,5355,8683,10,3133,1567,5436,0,5355,2680,6287,10,3144,7832,5435,0,3571,8683,6286,10,7832,5436,761,0,8683,6287,976,10,3132,213,3146,0,5356,290,3573,10,7833,3146,1574,0,8684,3573,1789,10,1567,3132,7833,0,2680,5356,8684,10,5436,7833,5437,0,6287,8684,6288,10,216,3154,7834,0,291,3581,8685,10,3154,1578,5438,0,3581,1793,6289,10,3149,7834,5441,0,3576,8685,6292,10,7834,5438,762,0,8685,6289,977,10,3155,195,3152,0,3582,294,3579,10,7835,3152,1577,0,8686,3579,1792,10,1578,3155,7835,0,1793,3582,8686,10,5438,7835,5439,0,6289,8686,6290,10,112,3150,7836,0,293,3577,8687,10,3150,1576,5440,0,3577,1791,6291,10,3153,7836,5439,0,3580,8687,6290,10,7836,5440,762,0,8687,6291,977,10,3151,217,3148,0,3578,292,3575,10,7837,3148,1575,0,8688,3575,1790,10,1576,3151,7837,0,1791,3578,8688,10,5440,7837,5441,0,6291,8688,6292,10,218,3158,7838,0,295,3585,8689,10,3158,1580,5442,0,3585,1795,6293,10,3157,7838,5445,0,3584,8689,6296,10,7838,5442,763,0,8689,6293,978,10,3159,194,3061,0,3586,296,5349,10,7839,3061,1531,0,8690,5349,2677,10,1580,3159,7839,0,1795,3586,8690,10,5442,7839,5443,0,6293,8690,6294,10,195,3155,7840,0,294,3582,8691,10,3155,1578,5444,0,3582,1793,6295,10,3060,7840,5443,0,5350,8691,6294,10,7840,5444,763,0,8691,6295,978,10,3154,216,3156,0,3581,291,3583,10,7841,3156,1579,0,8692,3583,1794,10,1578,3154,7841,0,1793,3581,8692,10,5444,7841,5445,0,6295,8692,6296,10,142,3164,7842,0,209,3591,8693,10,3164,1583,5446,0,3591,1798,6297,10,3161,7842,5449,0,3588,8693,6300,10,7842,5446,764,0,8693,6297,979,10,3165,218,3157,0,3592,295,3584,10,7843,3157,1579,0,8694,3584,1794,10,1583,3165,7843,0,1798,3592,8694,10,5446,7843,5447,0,6297,8694,6298,10,216,3162,7844,0,291,3589,8695,10,3162,1582,5448,0,3589,1797,6299,10,3156,7844,5447,0,3583,8695,6298,10,7844,5448,764,0,8695,6299,979,10,3163,219,3160,0,3590,297,3587,10,7845,3160,1581,0,8696,3587,1796,10,1582,3163,7845,0,1797,3590,8696,10,5448,7845,5449,0,6299,8696,6300,10,220,3168,7846,0,298,3595,8697,10,3168,1585,5450,0,3595,1800,6301,10,3167,7846,5453,0,3594,8697,6304,10,7846,5450,765,0,8697,6301,980,10,3169,219,3163,0,3596,297,3590,10,7847,3163,1582,0,8698,3590,1797,10,1585,3169,7847,0,1800,3596,8698,10,5450,7847,5451,0,6301,8698,6302,10,216,3149,7848,0,291,3576,8699,10,3149,1575,5452,0,3576,1790,6303,10,3162,7848,5451,0,3589,8699,6302,10,7848,5452,765,0,8699,6303,980,10,3148,217,3166,0,3575,292,3593,10,7849,3166,1584,0,8700,3593,1799,10,1575,3148,7849,0,1790,3575,8700,10,5452,7849,5453,0,6303,8700,6304,10,227,3186,7850,0,305,3613,8701,10,3186,1594,5454,0,3613,1809,6305,10,3183,7850,5457,0,3610,8701,6308,10,7850,5454,766,0,8701,6305,981,10,3187,104,2799,0,3614,168,3226,10,7851,2799,1400,0,8702,3226,1615,10,1594,3187,7851,0,1809,3614,8702,10,5454,7851,5455,0,6305,8702,6306,10,105,3184,7852,0,169,3611,8703,10,3184,1593,5456,0,3611,1808,6307,10,2798,7852,5455,0,3225,8703,6306,10,7852,5456,766,0,8703,6307,981,10,3185,228,3182,0,3612,306,3609,10,7853,3182,1592,0,8704,3609,1807,10,1593,3185,7853,0,1808,3612,8704,10,5456,7853,5457,0,6307,8704,6308,10,228,3190,7854,0,306,3617,8705,10,3190,1596,5458,0,3617,1811,6309,10,3182,7854,5461,0,3609,8705,6312,10,7854,5458,767,0,8705,6309,982,10,3191,278,3392,0,3618,367,3819,10,7855,3392,1697,0,8706,3819,1912,10,1596,3191,7855,0,1811,3618,8706,10,5458,7855,5459,0,6309,8706,6310,10,277,3188,7856,0,366,3615,8707,10,3188,1595,5460,0,3615,1810,6311,10,3393,7856,5459,0,3820,8707,6310,10,7856,5460,767,0,8707,6311,982,10,3189,227,3183,0,3616,305,3610,10,7857,3183,1592,0,8708,3610,1807,10,1595,3189,7857,0,1810,3616,8708,10,5460,7857,5461,0,6311,8708,6312,10,228,3192,7858,0,306,3619,8709,10,3192,1597,5462,0,3619,1812,6313,10,3190,7858,5465,0,3617,8709,6316,10,7858,5462,768,0,8709,6313,983,10,3193,229,2919,0,3620,307,3346,10,7859,2919,1460,0,8710,3346,1675,10,1597,3193,7859,0,1812,3620,8710,10,5462,7859,5463,0,6313,8710,6314,10,137,3409,7860,0,204,3836,8711,10,3409,1705,5464,0,3836,1920,6315,10,2918,7860,5463,0,3345,8711,6314,10,7860,5464,768,0,8711,6315,983,10,3408,278,3191,0,3835,367,3618,10,7861,3191,1596,0,8712,3618,1811,10,1705,3408,7861,0,1920,3835,8712,10,5464,7861,5465,0,6315,8712,6316,10,229,3193,7862,0,307,3620,8713,10,3193,1597,5466,0,3620,1812,6317,10,3195,7862,5469,0,3622,8713,6320,10,7862,5466,769,0,8713,6317,984,10,3192,228,3185,0,3619,306,3612,10,7863,3185,1593,0,8714,3612,1808,10,1597,3192,7863,0,1812,3619,8714,10,5466,7863,5467,0,6317,8714,6318,10,105,2805,7864,0,169,3232,8715,10,2805,1403,5468,0,3232,1618,6319,10,3184,7864,5467,0,3611,8715,6318,10,7864,5468,769,0,8715,6319,984,10,2804,106,3194,0,3231,170,3621,10,7865,3194,1598,0,8716,3621,1813,10,1403,2804,7865,0,1618,3231,8716,10,5468,7865,5469,0,6319,8716,6320,10,230,3202,7866,0,308,3629,8717,10,3202,1602,5470,0,3629,1817,6321,10,3197,7866,5473,0,3624,8717,6324,10,7866,5470,770,0,8717,6321,985,10,3203,233,3200,0,3630,311,3627,10,7867,3200,1601,0,8718,3627,1816,10,1602,3203,7867,0,1817,3630,8718,10,5470,7867,5471,0,6321,8718,6322,10,232,3198,7868,0,310,3625,8719,10,3198,1600,5472,0,3625,1815,6323,10,3201,7868,5471,0,3628,8719,6322,10,7868,5472,770,0,8719,6323,985,10,3199,231,3196,0,3626,309,3623,10,7869,3196,1599,0,8720,3623,1814,10,1600,3199,7869,0,1815,3626,8720,10,5472,7869,5473,0,6323,8720,6324,10,231,3199,7870,0,309,3626,8721,10,3199,1600,5474,0,3626,1815,6325,10,3205,7870,5477,0,3632,8721,6328,10,7870,5474,771,0,8721,6325,986,10,3198,232,3208,0,3625,310,3635,10,7871,3208,1605,0,8722,3635,1820,10,1600,3198,7871,0,1815,3625,8722,10,5474,7871,5475,0,6325,8722,6326,10,235,3206,7872,0,313,3633,8723,10,3206,1604,5476,0,3633,1819,6327,10,3209,7872,5475,0,3636,8723,6326,10,7872,5476,771,0,8723,6327,986,10,3207,234,3204,0,3634,312,3631,10,7873,3204,1603,0,8724,3631,1818,10,1604,3207,7873,0,1819,3634,8724,10,5476,7873,5477,0,6327,8724,6328,10,233,3212,7874,0,311,3639,8725,10,3212,1607,5478,0,3639,1822,6329,10,3200,7874,5481,0,3627,8725,6332,10,7874,5478,772,0,8725,6329,987,10,3213,163,2979,0,3640,230,3406,10,7875,2979,1490,0,8726,3406,1705,10,1607,3213,7875,0,1822,3640,8726,10,5478,7875,5479,0,6329,8726,6330,10,164,3210,7876,0,231,3637,8727,10,3210,1606,5480,0,3637,1821,6331,10,2978,7876,5479,0,3405,8727,6330,10,7876,5480,772,0,8727,6331,987,10,3211,232,3201,0,3638,310,3628,10,7877,3201,1601,0,8728,3628,1816,10,1606,3211,7877,0,1821,3638,8728,10,5480,7877,5481,0,6331,8728,6332,10,236,3218,7878,0,314,3645,8729,10,3218,1610,5482,0,3645,1825,6333,10,3215,7878,5485,0,3642,8729,6336,10,7878,5482,773,0,8729,6333,988,10,3219,132,2875,0,3646,199,3302,10,7879,2875,1438,0,8730,3302,1653,10,1610,3219,7879,0,1825,3646,8730,10,5482,7879,5483,0,6333,8730,6334,10,133,3216,7880,0,200,3643,8731,10,3216,1609,5484,0,3643,1824,6335,10,2874,7880,5483,0,3301,8731,6334,10,7880,5484,773,0,8731,6335,988,10,3217,237,3214,0,3644,315,3641,10,7881,3214,1608,0,8732,3641,1823,10,1609,3217,7881,0,1824,3644,8732,10,5484,7881,5485,0,6335,8732,6336,10,236,3215,7882,0,314,3642,8733,10,3215,1608,5486,0,3642,1823,6337,10,2914,7882,5489,0,3341,8733,6340,10,7882,5486,774,0,8733,6337,989,10,3214,237,3220,0,3641,315,3647,10,7883,3220,1611,0,8734,3647,1826,10,1608,3214,7883,0,1823,3641,8734,10,5486,7883,5487,0,6337,8734,6338,10,280,3410,7884,0,369,3837,8735,10,3410,1706,5488,0,3837,1921,6339,10,3221,7884,5487,0,3648,8735,6338,10,7884,5488,774,0,8735,6339,989,10,3411,145,2915,0,3838,212,3342,10,7885,2915,1458,0,8736,3342,1673,10,1706,3411,7885,0,1921,3838,8736,10,5488,7885,5489,0,6339,8736,6340,10,237,3224,7886,0,315,3651,8737,10,3224,1613,5490,0,3651,1828,6341,10,3220,7886,5493,0,3647,8737,6344,10,7886,5490,775,0,8737,6341,990,10,3225,238,3222,0,3652,316,3649,10,7887,3222,1612,0,8738,3649,1827,10,1613,3225,7887,0,1828,3652,8738,10,5490,7887,5491,0,6341,8738,6342,10,283,3424,7888,0,372,3851,8739,10,3424,1713,5492,0,3851,1928,6343,10,3223,7888,5491,0,3650,8739,6342,10,7888,5492,775,0,8739,6343,990,10,3425,280,3221,0,3852,369,3648,10,7889,3221,1611,0,8740,3648,1826,10,1713,3425,7889,0,1928,3852,8740,10,5492,7889,5493,0,6343,8740,6344,10,237,3217,7890,0,315,3644,8741,10,3217,1609,5494,0,3644,1824,6345,10,3224,7890,5497,0,3651,8741,6348,10,7890,5494,776,0,8741,6345,991,10,3216,133,2881,0,3643,200,3308,10,7891,2881,1441,0,8742,3308,1656,10,1609,3216,7891,0,1824,3643,8742,10,5494,7891,5495,0,6345,8742,6346,10,134,3226,7892,0,201,3653,8743,10,3226,1614,5496,0,3653,1829,6347,10,2880,7892,5495,0,3307,8743,6346,10,7892,5496,776,0,8743,6347,991,10,3227,238,3225,0,3654,316,3652,10,7893,3225,1613,0,8744,3652,1828,10,1614,3227,7893,0,1829,3654,8744,10,5496,7893,5497,0,6347,8744,6348,10,240,3230,7894,0,318,3657,8745,10,3230,1616,5498,0,3657,1831,6349,10,2850,7894,5501,0,3277,8745,6352,10,7894,5498,777,0,8745,6349,992,10,3231,239,3228,0,3658,317,3655,10,7895,3228,1615,0,8746,3655,1830,10,1616,3231,7895,0,1831,3658,8746,10,5498,7895,5499,0,6349,8746,6350,10,284,3426,7896,0,373,3853,8747,10,3426,1714,5500,0,3853,1929,6351,10,3229,7896,5499,0,3656,8747,6350,10,7896,5500,777,0,8747,6351,992,10,3427,123,2851,0,3854,187,3278,10,7897,2851,1426,0,8748,3278,1641,10,1714,3427,7897,0,1929,3854,8748,10,5500,7897,5501,0,6351,8748,6352,10,239,3234,7898,0,317,3661,8749,10,3234,1618,5502,0,3661,1833,6353,10,3228,7898,5505,0,3655,8749,6356,10,7898,5502,778,0,8749,6353,993,10,3235,241,3232,0,3662,319,3659,10,7899,3232,1617,0,8750,3659,1832,10,1618,3235,7899,0,1833,3662,8750,10,5502,7899,5503,0,6353,8750,6354,10,287,3443,7900,0,376,3870,8751,10,3443,1722,5504,0,3870,1937,6355,10,3233,7900,5503,0,3660,8751,6354,10,7900,5504,778,0,8751,6355,993,10,3442,284,3229,0,3869,373,3656,10,7901,3229,1615,0,8752,3656,1830,10,1722,3442,7901,0,1937,3869,8752,10,5504,7901,5505,0,6355,8752,6356,10,241,3238,7902,0,319,3665,8753,10,3238,1620,5506,0,3665,1835,6357,10,3232,7902,5509,0,3659,8753,6360,10,7902,5506,779,0,8753,6357,994,10,3239,242,3236,0,3666,320,3663,10,7903,3236,1619,0,8754,3663,1834,10,1620,3239,7903,0,1835,3666,8754,10,5506,7903,5507,0,6357,8754,6358,10,288,3448,7904,0,377,3875,8755,10,3448,1725,5508,0,3875,1940,6359,10,3237,7904,5507,0,3664,8755,6358,10,7904,5508,779,0,8755,6359,994,10,3449,287,3233,0,3876,376,3660,10,7905,3233,1617,0,8756,3660,1832,10,1725,3449,7905,0,1940,3876,8756,10,5508,7905,5509,0,6359,8756,6360,10,277,3463,7906,0,366,3890,8757,10,3463,1732,5510,0,3890,1947,6361,10,3188,7906,5513,0,3615,8757,6364,10,7906,5510,780,0,8757,6361,995,10,3462,288,3237,0,3889,377,3664,10,7907,3237,1619,0,8758,3664,1834,10,1732,3462,7907,0,1947,3889,8758,10,5510,7907,5511,0,6361,8758,6362,10,242,3240,7908,0,320,3667,8759,10,3240,1621,5512,0,3667,1836,6363,10,3236,7908,5511,0,3663,8759,6362,10,7908,5512,780,0,8759,6363,995,10,3241,227,3189,0,3668,305,3616,10,7909,3189,1595,0,8760,3616,1810,10,1621,3241,7909,0,1836,3668,8760,10,5512,7909,5513,0,6363,8760,6364,10,243,3246,7910,0,321,3673,8761,10,3246,1624,5514,0,3673,1839,6365,10,3243,7910,5517,0,3670,8761,6368,10,7910,5514,781,0,8761,6365,996,10,3247,244,3244,0,3674,322,3671,10,7911,3244,1623,0,8762,3671,1838,10,1624,3247,7911,0,1839,3674,8762,10,5514,7911,5515,0,6365,8762,6366,10,130,2879,7912,0,197,3306,8763,10,2879,1440,5516,0,3306,1655,6367,10,3245,7912,5515,0,3672,8763,6366,10,7912,5516,781,0,8763,6367,996,10,2878,132,3242,0,3305,199,3669,10,7913,3242,1622,0,8764,3669,1837,10,1440,2878,7913,0,1655,3305,8764,10,5516,7913,5517,0,6367,8764,6368,10,129,2869,7914,0,196,3296,8765,10,2869,1435,5518,0,3296,1650,6369,10,3249,7914,5521,0,3676,8765,6372,10,7914,5518,782,0,8765,6369,997,10,2868,130,3245,0,3295,197,3672,10,7915,3245,1623,0,8766,3672,1838,10,1435,2868,7915,0,1650,3295,8766,10,5518,7915,5519,0,6369,8766,6370,10,244,3250,7916,0,322,3677,8767,10,3250,1626,5520,0,3677,1841,6371,10,3244,7916,5519,0,3671,8767,6370,10,7916,5520,782,0,8767,6371,997,10,3251,245,3248,0,3678,323,3675,10,7917,3248,1625,0,8768,3675,1840,10,1626,3251,7917,0,1841,3678,8768,10,5520,7917,5521,0,6371,8768,6372,10,100,3254,7918,0,164,3681,8769,10,3254,1628,5522,0,3681,1843,6373,10,2784,7918,5525,0,3211,8769,6376,10,7918,5522,783,0,8769,6373,998,10,3255,245,3251,0,3682,323,3678,10,7919,3251,1626,0,8770,3678,1841,10,1628,3255,7919,0,1843,3682,8770,10,5522,7919,5523,0,6373,8770,6374,10,244,3252,7920,0,322,3679,8771,10,3252,1627,5524,0,3679,1842,6375,10,3250,7920,5523,0,3677,8771,6374,10,7920,5524,783,0,8771,6375,998,10,3253,99,2785,0,3680,163,3212,10,7921,2785,1393,0,8772,3212,1608,10,1627,3253,7921,0,1842,3680,8772,10,5524,7921,5525,0,6375,8772,6376,10,106,2803,7922,0,170,3230,8773,10,2803,1402,5526,0,3230,1617,6377,10,3257,7922,5529,0,3684,8773,6380,10,7922,5526,784,0,8773,6377,999,10,2802,99,3253,0,3229,163,3680,10,7923,3253,1627,0,8774,3680,1842,10,1402,2802,7923,0,1617,3229,8774,10,5526,7923,5527,0,6377,8774,6378,10,244,3247,7924,0,322,3674,8775,10,3247,1624,5528,0,3674,1839,6379,10,3252,7924,5527,0,3679,8775,6378,10,7924,5528,784,0,8775,6379,999,10,3246,243,3256,0,3673,321,3683,10,7925,3256,1629,0,8776,3683,1844,10,1624,3246,7925,0,1839,3673,8776,10,5528,7925,5529,0,6379,8776,6380,10,385,3262,7926,0,324,3689,8777,10,3262,1632,5530,0,3689,1847,6381,10,3868,7926,5533,0,5446,8777,6384,10,7926,5530,785,0,8777,6381,1000,10,3263,247,3260,0,3690,327,3687,10,7927,3260,1631,0,8778,3687,1846,10,1632,3263,7927,0,1847,3690,8778,10,5530,7927,5531,0,6381,8778,6382,10,246,3258,7928,0,326,3685,8779,10,3258,1630,5532,0,3685,1845,6383,10,3261,7928,5531,0,3688,8779,6382,10,7928,5532,785,0,8779,6383,1000,10,3259,412,3869,0,3686,325,5445,10,7929,3869,1935,0,8780,5445,2725,10,1630,3259,7929,0,1845,3686,8780,10,5532,7929,5533,0,6383,8780,6384,10,246,3266,7930,0,326,3693,8781,10,3266,1634,5534,0,3693,1849,6385,10,3258,7930,5537,0,3685,8781,6388,10,7930,5534,786,0,8781,6385,1001,10,3267,168,2991,0,3694,329,5347,10,7931,2991,1496,0,8782,5347,2676,10,1634,3267,7931,0,1849,3694,8782,10,5534,7931,5535,0,6385,8782,6386,10,169,3264,7932,0,328,3691,8783,10,3264,1633,5536,0,3691,1848,6387,10,2990,7932,5535,0,5348,8783,6386,10,7932,5536,786,0,8783,6387,1001,10,3265,412,3259,0,3692,325,3686,10,7933,3259,1630,0,8784,3686,1845,10,1633,3265,7933,0,1848,3692,8784,10,5536,7933,5537,0,6387,8784,6388,10,168,3267,7934,0,329,3694,8785,10,3267,1634,5538,0,3694,1849,6389,10,2986,7934,5541,0,5346,8785,6392,10,7934,5538,787,0,8785,6389,1002,10,3266,246,3270,0,3693,326,3697,10,7935,3270,1636,0,8786,3697,1851,10,1634,3266,7935,0,1849,3693,8786,10,5538,7935,5539,0,6389,8786,6390,10,248,3268,7936,0,331,3695,8787,10,3268,1635,5540,0,3695,1850,6391,10,3271,7936,5539,0,3698,8787,6390,10,7936,5540,787,0,8787,6391,1002,10,3269,167,2987,0,3696,330,5345,10,7937,2987,1494,0,8788,5345,2675,10,1635,3269,7937,0,1850,3696,8788,10,5540,7937,5541,0,6391,8788,6392,10,248,3271,7938,0,331,3698,8789,10,3271,1636,5542,0,3698,1851,6393,10,3273,7938,5545,0,3700,8789,6396,10,7938,5542,788,0,8789,6393,1003,10,3270,246,3261,0,3697,326,3688,10,7939,3261,1631,0,8790,3688,1846,10,1636,3270,7939,0,1851,3697,8790,10,5542,7939,5543,0,6393,8790,6394,10,247,3274,7940,0,327,3701,8791,10,3274,1638,5544,0,3701,1853,6395,10,3260,7940,5543,0,3687,8791,6394,10,7940,5544,788,0,8791,6395,1003,10,3275,249,3272,0,3702,332,3699,10,7941,3272,1637,0,8792,3699,1852,10,1638,3275,7941,0,1853,3702,8792,10,5544,7941,5545,0,6395,8792,6396,10,249,3280,7942,0,332,3707,8793,10,3280,1641,5546,0,3707,1856,6397,10,3272,7942,5549,0,3699,8793,6400,10,7942,5546,789,0,8793,6397,1004,10,3281,251,3278,0,3708,334,3705,10,7943,3278,1640,0,8794,3705,1855,10,1641,3281,7943,0,1856,3708,8794,10,5546,7943,5547,0,6397,8794,6398,10,250,3276,7944,0,333,3703,8795,10,3276,1639,5548,0,3703,1854,6399,10,3279,7944,5547,0,3706,8795,6398,10,7944,5548,789,0,8795,6399,1004,10,3277,248,3273,0,3704,331,3700,10,7945,3273,1637,0,8796,3700,1852,10,1639,3277,7945,0,1854,3704,8796,10,5548,7945,5549,0,6399,8796,6400,10,248,3277,7946,0,331,3704,8797,10,3277,1639,5550,0,3704,1854,6401,10,3268,7946,5553,0,3695,8797,6404,10,7946,5550,790,0,8797,6401,1005,10,3276,250,3284,0,3703,333,3711,10,7947,3284,1643,0,8798,3711,1858,10,1639,3276,7947,0,1854,3703,8798,10,5550,7947,5551,0,6401,8798,6402,10,252,3282,7948,0,335,3709,8799,10,3282,1642,5552,0,3709,1857,6403,10,3285,7948,5551,0,3712,8799,6402,10,7948,5552,790,0,8799,6403,1005,10,3283,167,3269,0,3710,330,3696,10,7949,3269,1635,0,8800,3696,1850,10,1642,3283,7949,0,1857,3710,8800,10,5552,7949,5553,0,6403,8800,6404,10,234,3288,7950,0,312,3715,8801,10,3288,1645,5554,0,3715,1860,6405,10,3204,7950,5557,0,3631,8801,6408,10,7950,5554,791,0,8801,6405,1006,10,3289,252,3285,0,3716,335,3712,10,7951,3285,1643,0,8802,3712,1858,10,1645,3289,7951,0,1860,3716,8802,10,5554,7951,5555,0,6405,8802,6406,10,250,3286,7952,0,333,3713,8803,10,3286,1644,5556,0,3713,1859,6407,10,3284,7952,5555,0,3711,8803,6406,10,7952,5556,791,0,8803,6407,1006,10,3287,231,3205,0,3714,309,3632,10,7953,3205,1603,0,8804,3632,1818,10,1644,3287,7953,0,1859,3714,8804,10,5556,7953,5557,0,6407,8804,6408,10,231,3287,7954,0,309,3714,8805,10,3287,1644,5558,0,3714,1859,6409,10,3196,7954,5561,0,3623,8805,6412,10,7954,5558,792,0,8805,6409,1007,10,3286,250,3279,0,3713,333,3706,10,7955,3279,1640,0,8806,3706,1855,10,1644,3286,7955,0,1859,3713,8806,10,5558,7955,5559,0,6409,8806,6410,10,251,3290,7956,0,334,3717,8807,10,3290,1646,5560,0,3717,1861,6411,10,3278,7956,5559,0,3705,8807,6410,10,7956,5560,792,0,8807,6411,1007,10,3291,230,3197,0,3718,308,3624,10,7957,3197,1599,0,8808,3624,1814,10,1646,3291,7957,0,1861,3718,8808,10,5560,7957,5561,0,6411,8808,6412,10,161,3294,7958,0,228,3721,8809,10,3294,1648,5562,0,3721,1863,6413,10,2970,7958,5565,0,3397,8809,6416,10,7958,5562,793,0,8809,6413,1008,10,3295,253,3292,0,3722,336,3719,10,7959,3292,1647,0,8810,3719,1862,10,1648,3295,7959,0,1863,3722,8810,10,5562,7959,5563,0,6413,8810,6414,10,238,3227,7960,0,316,3654,8811,10,3227,1614,5564,0,3654,1829,6415,10,3293,7960,5563,0,3720,8811,6414,10,7960,5564,793,0,8811,6415,1008,10,3226,134,2971,0,3653,201,3398,10,7961,2971,1486,0,8812,3398,1701,10,1614,3226,7961,0,1829,3653,8812,10,5564,7961,5565,0,6415,8812,6416,10,253,3296,7962,0,336,3723,8813,10,3296,1649,5566,0,3723,1864,6417,10,3292,7962,5569,0,3719,8813,6420,10,7962,5566,794,0,8813,6417,1009,10,3297,290,3464,0,3724,379,3891,10,7963,3464,1733,0,8814,3891,1948,10,1649,3297,7963,0,1864,3724,8814,10,5566,7963,5567,0,6417,8814,6418,10,283,3223,7964,0,372,3650,8815,10,3223,1612,5568,0,3650,1827,6419,10,3465,7964,5567,0,3892,8815,6418,10,7964,5568,794,0,8815,6419,1009,10,3222,238,3293,0,3649,316,3720,10,7965,3293,1647,0,8816,3720,1862,10,1612,3222,7965,0,1827,3649,8816,10,5568,7965,5569,0,6419,8816,6420,10,253,3298,7966,0,336,3725,8817,10,3298,1650,5570,0,3725,1865,6421,10,3296,7966,5573,0,3723,8817,6424,10,7966,5570,795,0,8817,6421,1010,10,3299,254,2841,0,3726,337,3268,10,7967,2841,1421,0,8818,3268,1636,10,1650,3299,7967,0,1865,3726,8818,10,5570,7967,5571,0,6421,8818,6422,10,107,3479,7968,0,171,3906,8819,10,3479,1740,5572,0,3906,1955,6423,10,2840,7968,5571,0,3267,8819,6422,10,7968,5572,795,0,8819,6423,1010,10,3478,290,3297,0,3905,379,3724,10,7969,3297,1649,0,8820,3724,1864,10,1740,3478,7969,0,1955,3905,8820,10,5572,7969,5573,0,6423,8820,6424,10,163,3300,7970,0,230,3727,8821,10,3300,1651,5574,0,3727,1866,6425,10,2976,7970,5577,0,3403,8821,6428,10,7970,5574,796,0,8821,6425,1011,10,3301,254,3299,0,3728,337,3726,10,7971,3299,1650,0,8822,3726,1865,10,1651,3301,7971,0,1866,3728,8822,10,5574,7971,5575,0,6425,8822,6426,10,253,3295,7972,0,336,3722,8823,10,3295,1648,5576,0,3722,1863,6427,10,3298,7972,5575,0,3725,8823,6426,10,7972,5576,796,0,8823,6427,1011,10,3294,161,2977,0,3721,228,3404,10,7973,2977,1489,0,8824,3404,1704,10,1648,3294,7973,0,1863,3721,8824,10,5576,7973,5577,0,6427,8824,6428,10,245,3255,7974,0,323,3682,8825,10,3255,1628,5578,0,3682,1843,6429,10,3303,7974,5581,0,3730,8825,6432,10,7974,5578,797,0,8825,6429,1012,10,3254,100,3306,0,3681,164,3733,10,7975,3306,1654,0,8826,3733,1869,10,1628,3254,7975,0,1843,3681,8826,10,5578,7975,5579,0,6429,8826,6430,10,256,3304,7976,0,343,3731,8827,10,3304,1653,5580,0,3731,1868,6431,10,3307,7976,5579,0,3734,8827,6430,10,7976,5580,797,0,8827,6431,1012,10,3305,255,3302,0,3732,342,3729,10,7977,3302,1652,0,8828,3729,1867,10,1653,3305,7977,0,1868,3732,8828,10,5580,7977,5581,0,6431,8828,6432,10,255,3310,7978,0,342,3737,8829,10,3310,1656,5582,0,3737,1871,6433,10,3302,7978,5585,0,3729,8829,6436,10,7978,5582,798,0,8829,6433,1013,10,3311,257,3308,0,3738,344,3735,10,7979,3308,1655,0,8830,3735,1870,10,1656,3311,7979,0,1871,3738,8830,10,5582,7979,5583,0,6433,8830,6434,10,129,3249,7980,0,196,3676,8831,10,3249,1625,5584,0,3676,1840,6435,10,3309,7980,5583,0,3736,8831,6434,10,7980,5584,798,0,8831,6435,1013,10,3248,245,3303,0,3675,323,3730,10,7981,3303,1652,0,8832,3730,1867,10,1625,3248,7981,0,1840,3675,8832,10,5584,7981,5585,0,6435,8832,6436,10,234,3207,7982,0,312,3634,8833,10,3207,1604,5586,0,3634,1819,6437,10,3313,7982,5589,0,3740,8833,6440,10,7982,5586,799,0,8833,6437,1014,10,3206,235,3316,0,3633,313,3743,10,7983,3316,1659,0,8834,3743,1874,10,1604,3206,7983,0,1819,3633,8834,10,5586,7983,5587,0,6437,8834,6438,10,259,3314,7984,0,346,3741,8835,10,3314,1658,5588,0,3741,1873,6439,10,3317,7984,5587,0,3744,8835,6438,10,7984,5588,799,0,8835,6439,1014,10,3315,258,3312,0,3742,345,3739,10,7985,3312,1657,0,8836,3739,1872,10,1658,3315,7985,0,1873,3742,8836,10,5588,7985,5589,0,6439,8836,6440,10,258,3320,7986,0,345,3747,8837,10,3320,1661,5590,0,3747,1876,6441,10,3312,7986,5593,0,3739,8837,6444,10,7986,5590,800,0,8837,6441,1015,10,3321,260,3318,0,3748,347,3745,10,7987,3318,1660,0,8838,3745,1875,10,1661,3321,7987,0,1876,3748,8838,10,5590,7987,5591,0,6441,8838,6442,10,252,3289,7988,0,335,3716,8839,10,3289,1645,5592,0,3716,1860,6443,10,3319,7988,5591,0,3746,8839,6442,10,7988,5592,800,0,8839,6443,1015,10,3288,234,3313,0,3715,312,3740,10,7989,3313,1657,0,8840,3740,1872,10,1645,3288,7989,0,1860,3715,8840,10,5592,7989,5593,0,6443,8840,6444,10,167,3283,7990,0,330,3710,8841,10,3283,1642,5594,0,3710,1857,6445,10,3323,7990,5597,0,3750,8841,6448,10,7990,5594,801,0,8841,6445,1016,10,3282,252,3319,0,3709,335,3746,10,7991,3319,1660,0,8842,3746,1875,10,1642,3282,7991,0,1857,3709,8842,10,5594,7991,5595,0,6445,8842,6446,10,260,3324,7992,0,347,3751,8843,10,3324,1663,5596,0,3751,1878,6447,10,3318,7992,5595,0,3745,8843,6446,10,7992,5596,801,0,8843,6447,1016,10,3325,261,3322,0,3752,348,3749,10,7993,3322,1662,0,8844,3749,1877,10,1663,3325,7993,0,1878,3752,8844,10,5596,7993,5597,0,6447,8844,6448,10,166,2985,7994,0,233,3412,8845,10,2985,1493,5598,0,3412,1708,6449,10,3327,7994,5601,0,3754,8845,6452,10,7994,5598,802,0,8845,6449,1017,10,2984,167,3323,0,3411,234,5363,10,7995,3323,1662,0,8846,5363,2684,10,1493,2984,7995,0,1708,3411,8846,10,5598,7995,5599,0,6449,8846,6450,10,261,3328,7996,0,350,3755,8847,10,3328,1665,5600,0,3755,1880,6451,10,3322,7996,5599,0,5364,8847,6450,10,7996,5600,802,0,8847,6451,1017,10,3329,262,3326,0,3756,349,3753,10,7997,3326,1664,0,8848,3753,1879,10,1665,3329,7997,0,1880,3756,8848,10,5600,7997,5601,0,6451,8848,6452,10,166,3327,7998,0,233,3754,8849,10,3327,1664,5602,0,3754,1879,6453,10,3331,7998,5605,0,3758,8849,6456,10,7998,5602,803,0,8849,6453,1018,10,3326,262,3334,0,3753,349,3761,10,7999,3334,1668,0,8850,3761,1883,10,1664,3326,7999,0,1879,3753,8850,10,5602,7999,5603,0,6453,8850,6454,10,264,3332,8000,0,352,3759,8851,10,3332,1667,5604,0,3759,1882,6455,10,3335,8000,5603,0,3762,8851,6454,10,8000,5604,803,0,8851,6455,1018,10,3333,263,3330,0,3760,351,3757,10,8001,3330,1666,0,8852,3757,1881,10,1667,3333,8001,0,1882,3760,8852,10,5604,8001,5605,0,6455,8852,6456,10,263,3333,8002,0,351,3760,8853,10,3333,1667,5606,0,3760,1882,6457,10,3337,8002,5609,0,3764,8853,6460,10,8002,5606,804,0,8853,6457,1019,10,3332,264,3340,0,3759,352,3767,10,8003,3340,1671,0,8854,3767,1886,10,1667,3332,8003,0,1882,3759,8854,10,5606,8003,5607,0,6457,8854,6458,10,266,3338,8004,0,354,3765,8855,10,3338,1670,5608,0,3765,1885,6459,10,3341,8004,5607,0,3768,8855,6458,10,8004,5608,804,0,8855,6459,1019,10,3339,265,3336,0,3766,353,3763,10,8005,3336,1669,0,8856,3763,1884,10,1670,3339,8005,0,1885,3766,8856,10,5608,8005,5609,0,6459,8856,6460,10,265,3339,8006,0,353,3766,8857,10,3339,1670,5610,0,3766,1885,6461,10,3343,8006,5613,0,3770,8857,6464,10,8006,5610,805,0,8857,6461,1020,10,3338,266,3346,0,3765,354,3773,10,8007,3346,1674,0,8858,3773,1889,10,1670,3338,8007,0,1885,3765,8858,10,5610,8007,5611,0,6461,8858,6462,10,267,3344,8008,0,355,3771,8859,10,3344,1673,5612,0,3771,1888,6463,10,3347,8008,5611,0,3774,8859,6462,10,8008,5612,805,0,8859,6463,1020,10,3345,102,3342,0,3772,166,3769,10,8009,3342,1672,0,8860,3769,1887,10,1673,3345,8009,0,1888,3772,8860,10,5612,8009,5613,0,6463,8860,6464,10,102,3345,8010,0,166,3772,8861,10,3345,1673,5614,0,3772,1888,6465,10,2790,8010,5617,0,3217,8861,6468,10,8010,5614,806,0,8861,6465,1021,10,3344,267,3350,0,3771,355,3777,10,8011,3350,1676,0,8862,3777,1891,10,1673,3344,8011,0,1888,3771,8862,10,5614,8011,5615,0,6465,8862,6466,10,268,3348,8012,0,356,3775,8863,10,3348,1675,5616,0,3775,1890,6467,10,3351,8012,5615,0,3778,8863,6466,10,8012,5616,806,0,8863,6467,1021,10,3349,101,2791,0,3776,165,3218,10,8013,2791,1396,0,8864,3218,1611,10,1675,3349,8013,0,1890,3776,8864,10,5616,8013,5617,0,6467,8864,6468,10,101,3349,8014,0,165,3776,8865,10,3349,1675,5618,0,3776,1890,6469,10,2786,8014,5621,0,3213,8865,6472,10,8014,5618,807,0,8865,6469,1022,10,3348,268,3352,0,3775,356,3779,10,8015,3352,1677,0,8866,3779,1892,10,1675,3348,8015,0,1890,3775,8866,10,5618,8015,5619,0,6469,8866,6470,10,256,3307,8016,0,343,3734,8867,10,3307,1654,5620,0,3734,1869,6471,10,3353,8016,5619,0,3780,8867,6470,10,8016,5620,807,0,8867,6471,1022,10,3306,100,2787,0,3733,164,3214,10,8017,2787,1394,0,8868,3214,1609,10,1654,3306,8017,0,1869,3733,8868,10,5620,8017,5621,0,6471,8868,6472,10,270,3355,8018,0,358,3782,8869,10,3355,1678,5622,0,3782,1893,6473,10,3357,8018,5625,0,3784,8869,6476,10,8018,5622,808,0,8869,6473,1023,10,3354,269,3358,0,3781,357,3785,10,8019,3358,1680,0,8870,3785,1895,10,1678,3354,8019,0,1893,3781,8870,10,5622,8019,5623,0,6473,8870,6474,10,233,3203,8020,0,311,3630,8871,10,3203,1602,5624,0,3630,1817,6475,10,3359,8020,5623,0,3786,8871,6474,10,8020,5624,808,0,8871,6475,1023,10,3202,230,3356,0,3629,308,3783,10,8021,3356,1679,0,8872,3783,1894,10,1602,3202,8021,0,1817,3629,8872,10,5624,8021,5625,0,6475,8872,6476,10,163,3213,8022,0,230,3640,8873,10,3213,1607,5626,0,3640,1822,6477,10,3300,8022,5629,0,3727,8873,6480,10,8022,5626,809,0,8873,6477,1024,10,3212,233,3359,0,3639,311,3786,10,8023,3359,1680,0,8874,3786,1895,10,1607,3212,8023,0,1822,3639,8874,10,5626,8023,5627,0,6477,8874,6478,10,269,3360,8024,0,357,3787,8875,10,3360,1681,5628,0,3787,1896,6479,10,3358,8024,5627,0,3785,8875,6478,10,8024,5628,809,0,8875,6479,1024,10,3361,254,3301,0,3788,337,3728,10,8025,3301,1651,0,8876,3728,1866,10,1681,3361,8025,0,1896,3788,8876,10,5628,8025,5629,0,6479,8876,6480,10,384,3366,8026,0,338,3793,8877,10,3366,1684,5630,0,3793,1899,6481,10,3864,8026,5633,0,5442,8877,6484,10,8026,5630,810,0,8877,6481,1025,10,3367,240,3363,0,3794,318,3790,10,8027,3363,1682,0,8878,3790,1897,10,1684,3367,8027,0,1899,3794,8878,10,5630,8027,5631,0,6481,8878,6482,10,271,3364,8028,0,359,3791,8879,10,3364,1683,5632,0,3791,1898,6483,10,3362,8028,5631,0,3789,8879,6482,10,8028,5632,810,0,8879,6483,1025,10,3365,399,3865,0,3792,341,5441,10,8029,3865,1933,0,8880,5441,2723,10,1683,3365,8029,0,1898,3792,8880,10,5632,8029,5633,0,6483,8880,6484,10,272,3370,8030,0,360,3797,8881,10,3370,1686,5634,0,3797,1901,6485,10,3369,8030,5637,0,3796,8881,6488,10,8030,5634,811,0,8881,6485,1026,10,3371,385,3871,0,3798,324,5447,10,8031,3871,1936,0,8882,5447,2726,10,1686,3371,8031,0,1901,3798,8882,10,5634,8031,5635,0,6485,8882,6486,10,399,3365,8032,0,340,5367,8883,10,3365,1683,5636,0,5367,2686,6487,10,3870,8032,5635,0,5448,8883,6486,10,8032,5636,811,0,8883,6487,1026,10,3364,271,3368,0,5368,361,3795,10,8033,3368,1685,0,8884,3795,1900,10,1683,3364,8033,0,2686,5368,8884,10,5636,8033,5637,0,6487,8884,6488,10,273,3374,8034,0,362,3801,8885,10,3374,1688,5638,0,3801,1903,6489,10,3372,8034,5641,0,3799,8885,6492,10,8034,5638,812,0,8885,6489,1027,10,3375,243,3243,0,3802,321,3670,10,8035,3243,1622,0,8886,3670,1837,10,1688,3375,8035,0,1903,3802,8886,10,5638,8035,5639,0,6489,8886,6490,10,132,3219,8036,0,199,3646,8887,10,3219,1610,5640,0,3646,1825,6491,10,3242,8036,5639,0,3669,8887,6490,10,8036,5640,812,0,8887,6491,1027,10,3218,236,3373,0,3645,314,3800,10,8037,3373,1687,0,8888,3800,1902,10,1610,3218,8037,0,1825,3645,8888,10,5640,8037,5641,0,6491,8888,6492,10,273,3376,8038,0,362,3803,8889,10,3376,1689,5642,0,3803,1904,6493,10,3374,8038,5645,0,3801,8889,6496,10,8038,5642,813,0,8889,6493,1028,10,3377,229,3195,0,3804,307,3622,10,8039,3195,1598,0,8890,3622,1813,10,1689,3377,8039,0,1904,3804,8890,10,5642,8039,5643,0,6493,8890,6494,10,106,3257,8040,0,170,3684,8891,10,3257,1629,5644,0,3684,1844,6495,10,3194,8040,5643,0,3621,8891,6494,10,8040,5644,813,0,8891,6495,1028,10,3256,243,3375,0,3683,321,3802,10,8041,3375,1688,0,8892,3802,1903,10,1629,3256,8041,0,1844,3683,8892,10,5644,8041,5645,0,6495,8892,6496,10,272,3379,8042,0,360,3806,8893,10,3379,1690,5646,0,3806,1905,6497,10,3370,8042,5649,0,3797,8893,6500,10,8042,5646,814,0,8893,6497,1029,10,3378,274,3380,0,3805,363,3807,10,8043,3380,1691,0,8894,3807,1906,10,1690,3378,8043,0,1905,3805,8894,10,5646,8043,5647,0,6497,8894,6498,10,247,3263,8044,0,327,3690,8895,10,3263,1632,5648,0,3690,1847,6499,10,3381,8044,5647,0,3808,8895,6498,10,8044,5648,814,0,8895,6499,1029,10,3262,385,3371,0,3689,324,3798,10,8045,3371,1686,0,8896,3798,1901,10,1632,3262,8045,0,1847,3689,8896,10,5648,8045,5649,0,6499,8896,6500,10,249,3275,8046,0,332,3702,8897,10,3275,1638,5650,0,3702,1853,6501,10,3383,8046,5653,0,3810,8897,6504,10,8046,5650,815,0,8897,6501,1030,10,3274,247,3381,0,3701,327,3808,10,8047,3381,1691,0,8898,3808,1906,10,1638,3274,8047,0,1853,3701,8898,10,5650,8047,5651,0,6501,8898,6502,10,274,3384,8048,0,363,3811,8899,10,3384,1693,5652,0,3811,1908,6503,10,3380,8048,5651,0,3807,8899,6502,10,8048,5652,815,0,8899,6503,1030,10,3385,275,3382,0,3812,364,3809,10,8049,3382,1692,0,8900,3809,1907,10,1693,3385,8049,0,1908,3812,8900,10,5652,8049,5653,0,6503,8900,6504,10,251,3281,8050,0,334,3708,8901,10,3281,1641,5654,0,3708,1856,6505,10,3389,8050,5657,0,3816,8901,6508,10,8050,5654,816,0,8901,6505,1031,10,3280,249,3383,0,3707,332,3810,10,8051,3383,1692,0,8902,3810,1907,10,1641,3280,8051,0,1856,3707,8902,10,5654,8051,5655,0,6505,8902,6506,10,275,3387,8052,0,364,3814,8903,10,3387,1694,5656,0,3814,1909,6507,10,3382,8052,5655,0,3809,8903,6506,10,8052,5656,816,0,8903,6507,1031,10,3386,276,3388,0,3813,365,3815,10,8053,3388,1695,0,8904,3815,1910,10,1694,3386,8053,0,1909,3813,8904,10,5656,8053,5657,0,6507,8904,6508,10,230,3291,8054,0,308,3718,8905,10,3291,1646,5658,0,3718,1861,6509,10,3356,8054,5661,0,3783,8905,6512,10,8054,5658,817,0,8905,6509,1032,10,3290,251,3389,0,3717,334,3816,10,8055,3389,1695,0,8906,3816,1910,10,1646,3290,8055,0,1861,3717,8906,10,5658,8055,5659,0,6509,8906,6510,10,276,3390,8056,0,365,3817,8907,10,3390,1696,5660,0,3817,1911,6511,10,3388,8056,5659,0,3815,8907,6510,10,8056,5660,817,0,8907,6511,1032,10,3391,270,3357,0,3818,358,3784,10,8057,3357,1679,0,8908,3784,1894,10,1696,3391,8057,0,1911,3818,8908,10,5660,8057,5661,0,6511,8908,6512,10,277,3393,8058,0,366,3820,8909,10,3393,1697,5662,0,3820,1912,6513,10,3395,8058,5665,0,3822,8909,6516,10,8058,5662,818,0,8909,6513,1033,10,3392,278,3396,0,3819,367,3823,10,8059,3396,1699,0,8910,3823,1914,10,1697,3392,8059,0,1912,3819,8910,10,5662,8059,5663,0,6513,8910,6514,10,183,3027,8060,0,252,3454,8911,10,3027,1514,5664,0,3454,1729,6515,10,3397,8060,5663,0,3824,8911,6514,10,8060,5664,818,0,8911,6515,1033,10,3026,180,3394,0,3453,249,3821,10,8061,3394,1698,0,8912,3821,1913,10,1514,3026,8061,0,1729,3453,8912,10,5664,8061,5665,0,6515,8912,6516,10,279,3402,8062,0,368,3829,8913,10,3402,1702,5666,0,3829,1917,6517,10,3399,8062,5669,0,3826,8913,6520,10,8062,5666,819,0,8913,6517,1034,10,3403,186,3400,0,3830,255,3827,10,8063,3400,1701,0,8914,3827,1916,10,1702,3403,8063,0,1917,3830,8914,10,5666,8063,5667,0,6517,8914,6518,10,183,3397,8064,0,252,3824,8915,10,3397,1699,5668,0,3824,1914,6519,10,3401,8064,5667,0,3828,8915,6518,10,8064,5668,819,0,8915,6519,1034,10,3396,278,3398,0,3823,367,3825,10,8065,3398,1700,0,8916,3825,1915,10,1699,3396,8065,0,1914,3823,8916,10,5668,8065,5669,0,6519,8916,6520,10,191,3057,8066,0,260,3484,8917,10,3057,1529,5670,0,3484,1744,6521,10,3405,8066,5673,0,3832,8917,6524,10,8066,5670,820,0,8917,6521,1035,10,3056,192,3406,0,3483,261,3833,10,8067,3406,1704,0,8918,3833,1919,10,1529,3056,8067,0,1744,3483,8918,10,5670,8067,5671,0,6521,8918,6522,10,279,3399,8068,0,368,3826,8919,10,3399,1700,5672,0,3826,1915,6523,10,3407,8068,5671,0,3834,8919,6522,10,8068,5672,820,0,8919,6523,1035,10,3398,278,3404,0,3825,367,3831,10,8069,3404,1703,0,8920,3831,1918,10,1700,3398,8069,0,1915,3825,8920,10,5672,8069,5673,0,6523,8920,6524,10,191,3405,8070,0,260,3832,8921,10,3405,1703,5674,0,3832,1918,6525,10,3050,8070,5677,0,3477,8921,6528,10,8070,5674,821,0,8921,6525,1036,10,3404,278,3408,0,3831,367,3835,10,8071,3408,1705,0,8922,3835,1920,10,1703,3404,8071,0,1918,3831,8922,10,5674,8071,5675,0,6525,8922,6526,10,137,2891,8072,0,204,3318,8923,10,2891,1446,5676,0,3318,1661,6527,10,3409,8072,5675,0,3836,8923,6526,10,8072,5676,821,0,8923,6527,1036,10,2890,138,3051,0,3317,205,3478,10,8073,3051,1526,0,8924,3478,1741,10,1446,2890,8073,0,1661,3317,8924,10,5676,8073,5677,0,6527,8924,6528,10,280,3414,8074,0,369,3841,8925,10,3414,1708,5678,0,3841,1923,6529,10,3410,8074,5681,0,3837,8925,6532,10,8074,5678,822,0,8925,6529,1037,10,3415,281,3412,0,3842,370,3839,10,8075,3412,1707,0,8926,3839,1922,10,1708,3415,8075,0,1923,3842,8926,10,5678,8075,5679,0,6529,8926,6530,10,146,2913,8076,0,213,3340,8927,10,2913,1457,5680,0,3340,1672,6531,10,3413,8076,5679,0,3840,8927,6530,10,8076,5680,822,0,8927,6531,1037,10,2912,145,3411,0,3339,212,3838,10,8077,3411,1706,0,8928,3838,1921,10,1457,2912,8077,0,1672,3339,8928,10,5680,8077,5681,0,6531,8928,6532,10,225,3422,8078,0,303,3849,8929,10,3422,1712,5682,0,3849,1927,6533,10,3417,8078,5685,0,3844,8929,6536,10,8078,5682,823,0,8929,6533,1038,10,3423,281,3420,0,3850,370,3847,10,8079,3420,1711,0,8930,3847,1926,10,1712,3423,8079,0,1927,3850,8930,10,5682,8079,5683,0,6533,8930,6534,10,282,3418,8080,0,371,3845,8931,10,3418,1710,5684,0,3845,1925,6535,10,3421,8080,5683,0,3848,8931,6534,10,8080,5684,823,0,8931,6535,1038,10,3419,224,3416,0,3846,302,3843,10,8081,3416,1709,0,8932,3843,1924,10,1710,3419,8081,0,1925,3846,8932,10,5684,8081,5685,0,6535,8932,6536,10,122,3432,8082,0,186,3859,8933,10,3432,1717,5686,0,3859,1932,6537,10,3429,8082,5689,0,3856,8933,6540,10,8082,5686,824,0,8933,6537,1039,10,3433,123,3427,0,3860,187,3854,10,8083,3427,1714,0,8934,3854,1929,10,1717,3433,8083,0,1932,3860,8934,10,5686,8083,5687,0,6537,8934,6538,10,284,3430,8084,0,373,3857,8935,10,3430,1716,5688,0,3857,1931,6539,10,3426,8084,5687,0,3853,8935,6538,10,8084,5688,824,0,8935,6539,1039,10,3431,285,3428,0,3858,374,3855,10,8085,3428,1715,0,8936,3855,1930,10,1716,3431,8085,0,1931,3858,8936,10,5688,8085,5689,0,6539,8936,6540,10,171,3440,8086,0,240,3867,8937,10,3440,1721,5690,0,3867,1936,6541,10,3435,8086,5693,0,3862,8937,6544,10,8086,5690,825,0,8937,6541,1040,10,3441,209,3438,0,3868,278,3865,10,8087,3438,1720,0,8938,3865,1935,10,1721,3441,8087,0,1936,3868,8938,10,5690,8087,5691,0,6541,8938,6542,10,286,3436,8088,0,375,3863,8939,10,3436,1719,5692,0,3863,1934,6543,10,3439,8088,5691,0,3866,8939,6542,10,8088,5692,825,0,8939,6543,1040,10,3437,285,3434,0,3864,374,3861,10,8089,3434,1718,0,8940,3861,1933,10,1719,3437,8089,0,1934,3864,8940,10,5692,8089,5693,0,6543,8940,6544,10,287,3446,8090,0,376,3873,8941,10,3446,1724,5694,0,3873,1939,6545,10,3443,8090,5697,0,3870,8941,6548,10,8090,5694,826,0,8941,6545,1041,10,3447,179,3019,0,3874,248,3446,10,8091,3019,1510,0,8942,3446,1725,10,1724,3447,8091,0,1939,3874,8942,10,5694,8091,5695,0,6545,8942,6546,10,174,3444,8092,0,243,3871,8943,10,3444,1723,5696,0,3871,1938,6547,10,3018,8092,5695,0,3445,8943,6546,10,8092,5696,826,0,8943,6547,1041,10,3445,284,3442,0,3872,373,3869,10,8093,3442,1722,0,8944,3869,1937,10,1723,3445,8093,0,1938,3872,8944,10,5696,8093,5697,0,6547,8944,6548,10,287,3449,8094,0,376,3876,8945,10,3449,1725,5698,0,3876,1940,6549,10,3446,8094,5701,0,3873,8945,6552,10,8094,5698,827,0,8945,6549,1042,10,3448,288,3450,0,3875,377,3877,10,8095,3450,1726,0,8946,3877,1941,10,1725,3448,8095,0,1940,3875,8946,10,5698,8095,5699,0,6549,8946,6550,10,178,3017,8096,0,247,3444,8947,10,3017,1509,5700,0,3444,1724,6551,10,3451,8096,5699,0,3878,8947,6550,10,8096,5700,827,0,8947,6551,1042,10,3016,179,3447,0,3443,248,3874,10,8097,3447,1724,0,8948,3874,1939,10,1509,3016,8097,0,1724,3443,8948,10,5700,8097,5701,0,6551,8948,6552,10,289,3456,8098,0,378,3883,8949,10,3456,1729,5702,0,3883,1944,6553,10,3453,8098,5705,0,3880,8949,6556,10,8098,5702,828,0,8949,6553,1043,10,3457,177,3454,0,3884,246,3881,10,8099,3454,1728,0,8950,3881,1943,10,1729,3457,8099,0,1944,3884,8950,10,5702,8099,5703,0,6553,8950,6554,10,178,3451,8100,0,247,3878,8951,10,3451,1726,5704,0,3878,1941,6555,10,3455,8100,5703,0,3882,8951,6554,10,8100,5704,828,0,8951,6555,1043,10,3450,288,3452,0,3877,377,3879,10,8101,3452,1727,0,8952,3879,1942,10,1726,3450,8101,0,1941,3877,8952,10,5704,8101,5705,0,6555,8952,6556,10,181,3033,8102,0,250,3460,8953,10,3033,1517,5706,0,3460,1732,6557,10,3459,8102,5709,0,3886,8953,6560,10,8102,5706,829,0,8953,6557,1044,10,3032,184,3460,0,3459,253,3887,10,8103,3460,1731,0,8954,3887,1946,10,1517,3032,8103,0,1732,3459,8954,10,5706,8103,5707,0,6557,8954,6558,10,289,3453,8104,0,378,3880,8955,10,3453,1727,5708,0,3880,1942,6559,10,3461,8104,5707,0,3888,8955,6558,10,8104,5708,829,0,8955,6559,1044,10,3452,288,3458,0,3879,377,3885,10,8105,3458,1730,0,8956,3885,1945,10,1727,3452,8105,0,1942,3879,8956,10,5708,8105,5709,0,6559,8956,6560,10,181,3459,8106,0,250,3886,8957,10,3459,1730,5710,0,3886,1945,6561,10,3020,8106,5713,0,3447,8957,6564,10,8106,5710,830,0,8957,6561,1045,10,3458,288,3462,0,3885,377,3889,10,8107,3462,1732,0,8958,3889,1947,10,1730,3458,8107,0,1945,3885,8958,10,5710,8107,5711,0,6561,8958,6562,10,277,3395,8108,0,366,3822,8959,10,3395,1698,5712,0,3822,1913,6563,10,3463,8108,5711,0,3890,8959,6562,10,8108,5712,830,0,8959,6563,1045,10,3394,180,3021,0,3821,249,3448,10,8109,3021,1511,0,8960,3448,1726,10,1698,3394,8109,0,1913,3821,8960,10,5712,8109,5713,0,6563,8960,6564,10,291,3470,8110,0,380,3897,8961,10,3470,1736,5714,0,3897,1951,6565,10,3467,8110,5717,0,3894,8961,6568,10,8110,5714,831,0,8961,6565,1046,10,3471,282,3468,0,3898,371,3895,10,8111,3468,1735,0,8962,3895,1950,10,1736,3471,8111,0,1951,3898,8962,10,5714,8111,5715,0,6565,8962,6566,10,283,3465,8112,0,372,3892,8963,10,3465,1733,5716,0,3892,1948,6567,10,3469,8112,5715,0,3896,8963,6566,10,8112,5716,831,0,8963,6567,1046,10,3464,290,3466,0,3891,379,3893,10,8113,3466,1734,0,8964,3893,1949,10,1733,3464,8113,0,1948,3891,8964,10,5716,8113,5717,0,6567,8964,6568,10,223,3476,8114,0,301,3903,8965,10,3476,1739,5718,0,3903,1954,6569,10,3473,8114,5721,0,3900,8965,6572,10,8114,5718,832,0,8965,6569,1047,10,3477,291,3474,0,3904,380,3901,10,8115,3474,1738,0,8966,3901,1953,10,1739,3477,8115,0,1954,3904,8966,10,5718,8115,5719,0,6569,8966,6570,10,193,3059,8116,0,262,3486,8967,10,3059,1530,5720,0,3486,1745,6571,10,3475,8116,5719,0,3902,8967,6570,10,8116,5720,832,0,8967,6571,1047,10,3058,194,3472,0,3485,263,3899,10,8117,3472,1737,0,8968,3899,1952,10,1530,3058,8117,0,1745,3485,8968,10,5720,8117,5721,0,6571,8968,6572,10,198,3480,8118,0,267,3907,8969,10,3480,1741,5722,0,3907,1956,6573,10,3074,8118,5725,0,3501,8969,6576,10,8118,5722,833,0,8969,6573,1048,10,3481,290,3478,0,3908,379,3905,10,8119,3478,1740,0,8970,3905,1955,10,1741,3481,8119,0,1956,3908,8970,10,5722,8119,5723,0,6573,8970,6574,10,107,2807,8120,0,171,3234,8971,10,2807,1404,5724,0,3234,1619,6575,10,3479,8120,5723,0,3906,8971,6574,10,8120,5724,833,0,8971,6575,1048,10,2806,108,3075,0,3233,172,3502,10,8121,3075,1538,0,8972,3502,1753,10,1404,2806,8121,0,1619,3233,8972,10,5724,8121,5725,0,6575,8972,6576,10,109,2811,8122,0,173,3238,8973,10,2811,1406,5726,0,3238,1621,6577,10,3066,8122,5729,0,3493,8973,6580,10,8122,5726,834,0,8973,6577,1049,10,2810,110,2825,0,3237,174,3252,10,8123,2825,1413,0,8974,3252,1628,10,1406,2810,8123,0,1621,3237,8974,10,5726,8123,5727,0,6577,8974,6578,10,114,2821,8124,0,178,3248,8975,10,2821,1411,5728,0,3248,1626,6579,10,2824,8124,5727,0,3251,8975,6578,10,8124,5728,834,0,8975,6579,1049,10,2820,111,3067,0,3247,175,3494,10,8125,3067,1534,0,8976,3494,1749,10,1411,2820,8125,0,1626,3247,8976,10,5728,8125,5729,0,6579,8976,6580,10,116,3091,8126,0,180,3518,8977,10,3091,1546,5730,0,3518,1761,6581,10,2826,8126,5733,0,3253,8977,6584,10,8126,5730,835,0,8977,6581,1050,10,3090,203,3172,0,3517,272,3599,10,8127,3172,1587,0,8978,3599,1802,10,1546,3090,8127,0,1761,3517,8978,10,5730,8127,5731,0,6581,8978,6582,10,113,2819,8128,0,177,3246,8979,10,2819,1410,5732,0,3246,1625,6583,10,3173,8128,5731,0,3600,8979,6582,10,8128,5732,835,0,8979,6583,1050,10,2818,114,2827,0,3245,178,3254,10,8129,2827,1414,0,8980,3254,1629,10,1410,2818,8129,0,1625,3245,8980,10,5732,8129,5733,0,6583,8980,6584,10,124,2855,8130,0,188,3282,8981,10,2855,1428,5734,0,3282,1643,6585,10,3483,8130,5737,0,3910,8981,6588,10,8130,5734,836,0,8981,6585,1051,10,2854,123,3433,0,3281,187,3860,10,8131,3433,1717,0,8982,3860,1932,10,1428,2854,8131,0,1643,3281,8982,10,5734,8131,5735,0,6585,8982,6586,10,122,2849,8132,0,186,3276,8983,10,2849,1425,5736,0,3276,1640,6587,10,3432,8132,5735,0,3859,8983,6586,10,8132,5736,836,0,8983,6587,1051,10,2848,119,3482,0,3275,183,3909,10,8133,3482,1742,0,8984,3909,1957,10,1425,2848,8133,0,1640,3275,8984,10,5736,8133,5737,0,6587,8984,6588,10,125,2859,8134,0,189,3286,8985,10,2859,1430,5738,0,3286,1645,6589,10,3485,8134,5741,0,3912,8985,6592,10,8134,5738,837,0,8985,6589,1052,10,2858,124,3483,0,3285,190,5369,10,8135,3483,1742,0,8986,5369,2687,10,1430,2858,8135,0,1645,3285,8986,10,5738,8135,5739,0,6589,8986,6590,10,119,2865,8136,0,194,3292,8987,10,2865,1433,5740,0,3292,1648,6591,10,3482,8136,5739,0,5370,8987,6590,10,8136,5740,837,0,8987,6591,1052,10,2864,126,3484,0,3291,191,3911,10,8137,3484,1743,0,8988,3911,1958,10,1433,2864,8137,0,1648,3291,8988,10,5740,8137,5741,0,6591,8988,6592,10,139,2895,8138,0,206,3322,8989,10,2895,1448,5742,0,3322,1663,6593,10,3042,8138,5745,0,3469,8989,6596,10,8138,5742,838,0,8989,6593,1053,10,2894,140,2909,0,3321,207,3336,10,8139,2909,1455,0,8990,3336,1670,10,1448,2894,8139,0,1663,3321,8990,10,5742,8139,5743,0,6593,8990,6594,10,144,2905,8140,0,211,3332,8991,10,2905,1453,5744,0,3332,1668,6595,10,2908,8140,5743,0,3335,8991,6594,10,8140,5744,838,0,8991,6595,1053,10,2904,141,3043,0,3331,208,3470,10,8141,3043,1522,0,8992,3470,1737,10,1453,2904,8141,0,1668,3331,8992,10,5744,8141,5745,0,6595,8992,6596,10,146,3486,8142,0,213,3913,8993,10,3486,1744,5746,0,3913,1959,6597,10,2910,8142,5749,0,3337,8993,6600,10,8142,5746,839,0,8993,6597,1054,10,3487,226,3181,0,3914,304,3608,10,8143,3181,1591,0,8994,3608,1806,10,1744,3487,8143,0,1959,3914,8994,10,5746,8143,5747,0,6597,8994,6598,10,143,2903,8144,0,210,3330,8995,10,2903,1452,5748,0,3330,1667,6599,10,3180,8144,5747,0,3607,8995,6598,10,8144,5748,839,0,8995,6599,1054,10,2902,144,2911,0,3329,211,3338,10,8145,2911,1456,0,8996,3338,1671,10,1452,2902,8145,0,1667,3329,8996,10,5748,8145,5749,0,6599,8996,6600,10,149,2925,8146,0,216,3352,8997,10,2925,1463,5750,0,3352,1678,6601,10,3489,8146,5753,0,3916,8997,6604,10,8146,5750,840,0,8997,6601,1055,10,2924,150,3490,0,3351,217,3917,10,8147,3490,1746,0,8998,3917,1961,10,1463,2924,8147,0,1678,3351,8998,10,5750,8147,5751,0,6601,8998,6602,10,154,2935,8148,0,221,3362,8999,10,2935,1468,5752,0,3362,1683,6603,10,3491,8148,5751,0,3918,8999,6602,10,8148,5752,840,0,8999,6603,1055,10,2934,151,3488,0,3361,218,3915,10,8149,3488,1745,0,9000,3915,1960,10,1468,2934,8149,0,1683,3361,9000,10,5752,8149,5753,0,6603,9000,6604,10,150,2943,8150,0,217,3370,9001,10,2943,1472,5754,0,3370,1687,6605,10,3490,8150,5757,0,3917,9001,6608,10,8150,5754,841,0,9001,6605,1056,10,2942,125,3485,0,3369,189,3912,10,8151,3485,1743,0,9002,3912,1958,10,1472,2942,8151,0,1687,3369,9002,10,5754,8151,5755,0,6605,9002,6606,10,126,2939,8152,0,191,3366,9003,10,2939,1470,5756,0,3366,1685,6607,10,3484,8152,5755,0,3911,9003,6606,10,8152,5756,841,0,9003,6607,1056,10,2938,154,3491,0,3365,221,3918,10,8153,3491,1746,0,9004,3918,1961,10,1470,2938,8153,0,1685,3365,9004,10,5756,8153,5757,0,6607,9004,6608,10,222,3174,8154,0,300,3601,9005,10,3174,1588,5758,0,3601,1803,6609,10,3493,8154,5761,0,3920,9005,6612,10,8154,5758,842,0,9005,6609,1057,10,3175,200,3081,0,3602,269,3508,10,8155,3081,1541,0,9006,3508,1756,10,1588,3175,8155,0,1803,3602,9006,10,5758,8155,5759,0,6609,9006,6610,10,158,2957,8156,0,225,3384,9007,10,2957,1479,5760,0,3384,1694,6611,10,3080,8156,5759,0,3507,9007,6610,10,8156,5760,842,0,9007,6611,1057,10,2956,157,3492,0,3383,224,3919,10,8157,3492,1747,0,9008,3919,1962,10,1479,2956,8157,0,1694,3383,9008,10,5760,8157,5761,0,6611,9008,6612,10,211,3496,8158,0,282,3923,9009,10,3496,1749,5762,0,3923,1964,6613,10,3495,8158,5765,0,3922,9009,6616,10,8158,5762,843,0,9009,6613,1058,10,3497,222,3493,0,3924,300,3920,10,8159,3493,1747,0,9010,3920,1962,10,1749,3497,8159,0,1964,3924,9010,10,5762,8159,5763,0,6613,9010,6614,10,157,2961,8160,0,224,3388,9011,10,2961,1481,5764,0,3388,1696,6615,10,3492,8160,5763,0,3919,9011,6614,10,8160,5764,843,0,9011,6615,1058,10,2960,160,3494,0,3387,227,3921,10,8161,3494,1748,0,9012,3921,1963,10,1481,2960,8161,0,1696,3387,9012,10,5764,8161,5765,0,6615,9012,6616,10,172,3013,8162,0,241,3440,9013,10,3013,1507,5766,0,3440,1722,6617,10,2998,8162,5769,0,3425,9013,6620,10,8162,5766,844,0,9013,6617,1059,10,3012,175,3121,0,3439,244,3548,10,8163,3121,1561,0,9014,3548,1776,10,1507,3012,8163,0,1722,3439,9014,10,5766,8163,5767,0,6617,9014,6618,10,209,3441,8164,0,278,3868,9015,10,3441,1721,5768,0,3868,1936,6619,10,3120,8164,5767,0,3547,9015,6618,10,8164,5768,844,0,9015,6619,1059,10,3440,171,2999,0,3867,240,3426,10,8165,2999,1500,0,9016,3426,1715,10,1721,3440,8165,0,1936,3867,9016,10,5768,8165,5769,0,6619,9016,6620,10,177,3011,8166,0,246,3438,9017,10,3011,1506,5770,0,3438,1721,6621,10,3454,8166,5773,0,3881,9017,6624,10,8166,5770,845,0,9017,6621,1060,10,3010,172,3001,0,3437,241,3428,10,8167,3001,1501,0,9018,3428,1716,10,1506,3010,8167,0,1721,3437,9018,10,5770,8167,5771,0,6621,9018,6622,10,173,3015,8168,0,242,3442,9019,10,3015,1508,5772,0,3442,1723,6623,10,3000,8168,5771,0,3427,9019,6622,10,8168,5772,845,0,9019,6623,1060,10,3014,178,3455,0,3441,247,3882,10,8169,3455,1728,0,9020,3882,1943,10,1508,3014,8169,0,1723,3441,9020,10,5772,8169,5773,0,6623,9020,6624,10,187,3137,8170,0,256,3564,9021,10,3137,1569,5774,0,3564,1784,6625,10,3036,8170,5777,0,3463,9021,6628,10,8170,5774,846,0,9021,6625,1061,10,3136,214,3498,0,3563,286,3925,10,8171,3498,1750,0,9022,3925,1965,10,1569,3136,8171,0,1784,3563,9022,10,5774,8171,5775,0,6625,9022,6626,10,184,3029,8172,0,253,3456,9023,10,3029,1515,5776,0,3456,1730,6627,10,3499,8172,5775,0,3926,9023,6626,10,8172,5776,846,0,9023,6627,1061,10,3028,185,3037,0,3455,254,3464,10,8173,3037,1519,0,9024,3464,1734,10,1515,3028,8173,0,1730,3455,9024,10,5776,8173,5777,0,6627,9024,6628,10,182,3025,8174,0,251,3452,9025,10,3025,1513,5778,0,3452,1728,6629,10,3030,8174,5781,0,3457,9025,6632,10,8174,5778,847,0,9025,6629,1062,10,3024,183,3401,0,3451,252,3828,10,8175,3401,1701,0,9026,3828,1916,10,1513,3024,8175,0,1728,3451,9026,10,5778,8175,5779,0,6629,9026,6630,10,186,3035,8176,0,255,3462,9027,10,3035,1518,5780,0,3462,1733,6631,10,3400,8176,5779,0,3827,9027,6630,10,8176,5780,847,0,9027,6631,1062,10,3034,185,3031,0,3461,254,3458,10,8177,3031,1516,0,9028,3458,1731,10,1518,3034,8177,0,1733,3461,9028,10,5780,8177,5781,0,6631,9028,6632,10,141,2899,8178,0,208,3326,9029,10,2899,1450,5782,0,3326,1665,6633,10,3048,8178,5785,0,3475,9029,6636,10,8178,5782,848,0,9029,6633,1063,10,2898,142,3161,0,3325,209,3588,10,8179,3161,1581,0,9030,3588,1796,10,1450,2898,8179,0,1665,3325,9030,10,5782,8179,5783,0,6633,9030,6634,10,219,3500,8180,0,297,3927,9031,10,3500,1751,5784,0,3927,1966,6635,10,3160,8180,5783,0,3587,9031,6634,10,8180,5784,848,0,9031,6635,1063,10,3501,190,3049,0,3928,259,3476,10,8181,3049,1525,0,9032,3476,1740,10,1751,3501,8181,0,1966,3928,9032,10,5784,8181,5785,0,6635,9032,6636,10,219,3169,8182,0,297,3596,9033,10,3169,1585,5786,0,3596,1800,6637,10,3500,8182,5789,0,3927,9033,6640,10,8182,5786,849,0,9033,6637,1064,10,3168,220,3502,0,3595,298,3929,10,8183,3502,1752,0,9034,3929,1967,10,1585,3168,8183,0,1800,3595,9034,10,5786,8183,5787,0,6637,9034,6638,10,192,3055,8184,0,261,3482,9035,10,3055,1528,5788,0,3482,1743,6639,10,3503,8184,5787,0,3930,9035,6638,10,8184,5788,849,0,9035,6639,1064,10,3054,190,3501,0,3481,259,3928,10,8185,3501,1751,0,9036,3928,1966,10,1528,3054,8185,0,1743,3481,9036,10,5788,8185,5789,0,6639,9036,6640,10,193,3504,8186,0,262,3931,9037,10,3504,1753,5790,0,3931,1968,6641,10,3064,8186,5793,0,3491,9037,6644,10,8186,5790,850,0,9037,6641,1065,10,3505,198,3077,0,3932,267,3504,10,8187,3077,1539,0,9038,3504,1754,10,1753,3505,8187,0,1968,3932,9038,10,5790,8187,5791,0,6641,9038,6642,10,197,3071,8188,0,266,3498,9039,10,3071,1536,5792,0,3498,1751,6643,10,3076,8188,5791,0,3503,9039,6642,10,8188,5792,850,0,9039,6643,1065,10,3070,196,3065,0,3497,265,3492,10,8189,3065,1533,0,9040,3492,1748,10,1536,3070,8189,0,1751,3497,9040,10,5792,8189,5793,0,6643,9040,6644,10,111,2815,8190,0,175,3242,9041,10,2815,1408,5794,0,3242,1623,6645,10,3072,8190,5797,0,3499,9041,6648,10,8190,5794,851,0,9041,6645,1066,10,2814,112,3153,0,3241,176,5359,10,8191,3153,1577,0,9042,5359,2682,10,1408,2814,8191,0,1623,3241,9042,10,5794,8191,5795,0,6645,9042,6646,10,195,3063,8192,0,264,3490,9043,10,3063,1532,5796,0,3490,1747,6647,10,3152,8192,5795,0,5360,9043,6646,10,8192,5796,851,0,9043,6647,1066,10,3062,196,3073,0,3489,265,3500,10,8193,3073,1537,0,9044,3500,1752,10,1532,3062,8193,0,1747,3489,9044,10,5796,8193,5797,0,6647,9044,6648,10,202,3089,8194,0,271,3516,9045,10,3089,1545,5798,0,3516,1760,6649,10,3507,8194,5801,0,3934,9045,6652,10,8194,5798,852,0,9045,6649,1067,10,3088,155,2955,0,3515,222,3382,10,8195,2955,1478,0,9046,3382,1693,10,1545,3088,8195,0,1760,3515,9046,10,5798,8195,5799,0,6649,9046,6650,10,158,3083,8196,0,225,3510,9047,10,3083,1542,5800,0,3510,1757,6651,10,2954,8196,5799,0,3381,9047,6650,10,8196,5800,852,0,9047,6651,1067,10,3082,201,3506,0,3509,270,3933,10,8197,3506,1754,0,9048,3933,1969,10,1542,3082,8197,0,1757,3509,9048,10,5800,8197,5801,0,6651,9048,6652,10,116,2829,8198,0,180,3256,9049,10,2829,1415,5802,0,3256,1630,6653,10,3094,8198,5805,0,3521,9049,6656,10,8198,5802,853,0,9049,6653,1068,10,2828,115,3087,0,3255,179,3514,10,8199,3087,1544,0,9050,3514,1759,10,1415,2828,8199,0,1630,3255,9050,10,5802,8199,5803,0,6653,9050,6654,10,202,3507,8200,0,271,3934,9051,10,3507,1754,5804,0,3934,1969,6655,10,3086,8200,5803,0,3513,9051,6654,10,8200,5804,853,0,9051,6655,1068,10,3506,201,3095,0,3933,270,3522,10,8201,3095,1548,0,9052,3522,1763,10,1754,3506,8201,0,1969,3933,9052,10,5804,8201,5805,0,6655,9052,6656,10,206,3105,8202,0,275,3532,9053,10,3105,1553,5806,0,3532,1768,6657,10,3108,8202,5809,0,3535,9053,6660,10,8202,5806,854,0,9053,6657,1069,10,3104,149,3489,0,3531,216,3916,10,8203,3489,1745,0,9054,3916,1960,10,1553,3104,8203,0,1768,3531,9054,10,5806,8203,5807,0,6657,9054,6658,10,151,3099,8204,0,218,3526,9055,10,3099,1550,5808,0,3526,1765,6659,10,3488,8204,5807,0,3915,9055,6658,10,8204,5808,854,0,9055,6659,1069,10,3098,205,3109,0,3525,274,3536,10,8205,3109,1555,0,9056,3536,1770,10,1550,3098,8205,0,1765,3525,9056,10,5808,8205,5809,0,6659,9056,6660,10,204,3127,8206,0,273,3554,9057,10,3127,1564,5810,0,3554,1779,6661,10,3100,8206,5813,0,3527,9057,6664,10,8206,5810,855,0,9057,6661,1070,10,3126,211,3495,0,3553,282,3922,10,8207,3495,1748,0,9058,3922,1963,10,1564,3126,8207,0,1779,3553,9058,10,5810,8207,5811,0,6661,9058,6662,10,160,3107,8208,0,227,3534,9059,10,3107,1554,5812,0,3534,1769,6663,10,3494,8208,5811,0,3921,9059,6662,10,8208,5812,855,0,9059,6663,1070,10,3106,205,3101,0,3533,274,3528,10,8209,3101,1551,0,9060,3528,1766,10,1554,3106,8209,0,1769,3533,9060,10,5812,8209,5813,0,6663,9060,6664,10,221,3170,8210,0,299,3597,9061,10,3170,1586,5814,0,3597,1801,6665,10,3509,8210,5817,0,3936,9061,6668,10,8210,5814,856,0,9061,6665,1071,10,3171,188,3041,0,3598,257,3468,10,8211,3041,1521,0,9062,3468,1736,10,1586,3171,8211,0,1801,3598,9062,10,5814,8211,5815,0,6665,9062,6666,10,186,3403,8212,0,255,3830,9063,10,3403,1702,5816,0,3830,1917,6667,10,3040,8212,5815,0,3467,9063,6666,10,8212,5816,856,0,9063,6667,1071,10,3402,279,3508,0,3829,368,3935,10,8213,3508,1755,0,9064,3935,1970,10,1702,3402,8213,0,1917,3829,9064,10,5816,8213,5817,0,6667,9064,6668,10,192,3503,8214,0,261,3930,9065,10,3503,1752,5818,0,3930,1967,6669,10,3406,8214,5821,0,3833,9065,6672,10,8214,5818,857,0,9065,6669,1072,10,3502,220,3510,0,3929,298,3937,10,8215,3510,1756,0,9066,3937,1971,10,1752,3502,8215,0,1967,3929,9066,10,5818,8215,5819,0,6669,9066,6670,10,221,3509,8216,0,299,3936,9067,10,3509,1755,5820,0,3936,1970,6671,10,3511,8216,5819,0,3938,9067,6670,10,8216,5820,857,0,9067,6671,1072,10,3508,279,3407,0,3935,368,3834,10,8217,3407,1704,0,9068,3834,1919,10,1755,3508,8217,0,1970,3935,9068,10,5820,8217,5821,0,6671,9068,6672,10,281,3423,8218,0,370,3850,9069,10,3423,1712,5822,0,3850,1927,6673,10,3412,8218,5825,0,3839,9069,6676,10,8218,5822,858,0,9069,6673,1073,10,3422,225,3179,0,3849,303,3606,10,8219,3179,1590,0,9070,3606,1805,10,1712,3422,8219,0,1927,3849,9070,10,5822,8219,5823,0,6673,9070,6674,10,226,3487,8220,0,304,3914,9071,10,3487,1744,5824,0,3914,1959,6675,10,3178,8220,5823,0,3605,9071,6674,10,8220,5824,858,0,9071,6675,1073,10,3486,146,3413,0,3913,213,3840,10,8221,3413,1707,0,9072,3840,1922,10,1744,3486,8221,0,1959,3913,9072,10,5824,8221,5825,0,6675,9072,6676,10,281,3415,8222,0,370,3842,9073,10,3415,1708,5826,0,3842,1923,6677,10,3420,8222,5829,0,3847,9073,6680,10,8222,5826,859,0,9073,6677,1074,10,3414,280,3425,0,3841,369,3852,10,8223,3425,1713,0,9074,3852,1928,10,1708,3414,8223,0,1923,3841,9074,10,5826,8223,5827,0,6677,9074,6678,10,283,3469,8224,0,372,3896,9075,10,3469,1735,5828,0,3896,1950,6679,10,3424,8224,5827,0,3851,9075,6678,10,8224,5828,859,0,9075,6679,1074,10,3468,282,3421,0,3895,371,3848,10,8225,3421,1711,0,9076,3848,1926,10,1735,3468,8225,0,1950,3895,9076,10,5828,8225,5829,0,6679,9076,6680,10,285,3437,8226,0,374,3864,9077,10,3437,1719,5830,0,3864,1934,6681,10,3428,8226,5833,0,3855,9077,6684,10,8226,5830,860,0,9077,6681,1075,10,3436,286,3512,0,3863,375,3939,10,8227,3512,1757,0,9078,3939,1972,10,1719,3436,8227,0,1934,3863,9078,10,5830,8227,5831,0,6681,9078,6682,10,121,2847,8228,0,185,3274,9079,10,2847,1424,5832,0,3274,1639,6683,10,3513,8228,5831,0,3940,9079,6682,10,8228,5832,860,0,9079,6683,1075,10,2846,122,3429,0,3273,186,3856,10,8229,3429,1715,0,9080,3856,1930,10,1424,2846,8229,0,1639,3273,9080,10,5832,8229,5833,0,6683,9080,6684,10,285,3431,8230,0,374,3858,9081,10,3431,1716,5834,0,3858,1931,6685,10,3434,8230,5837,0,3861,9081,6688,10,8230,5834,861,0,9081,6685,1076,10,3430,284,3445,0,3857,373,3872,10,8231,3445,1723,0,9082,3872,1938,10,1716,3430,8231,0,1931,3857,9082,10,5834,8231,5835,0,6685,9082,6686,10,174,3005,8232,0,243,3432,9083,10,3005,1503,5836,0,3432,1718,6687,10,3444,8232,5835,0,3871,9083,6686,10,8232,5836,861,0,9083,6687,1076,10,3004,171,3435,0,3431,240,3862,10,8233,3435,1718,0,9084,3862,1933,10,1503,3004,8233,0,1718,3431,9084,10,5836,8233,5837,0,6687,9084,6688,10,289,3516,8234,0,378,3943,9085,10,3516,1759,5838,0,3943,1974,6689,10,3456,8234,5841,0,3883,9085,6692,10,8234,5838,862,0,9085,6689,1077,10,3517,292,3514,0,3944,381,3941,10,8235,3514,1758,0,9086,3941,1973,10,1759,3517,8235,0,1974,3944,9086,10,5838,8235,5839,0,6689,9086,6690,10,176,3009,8236,0,245,3436,9087,10,3009,1505,5840,0,3436,1720,6691,10,3515,8236,5839,0,3942,9087,6690,10,8236,5840,862,0,9087,6691,1077,10,3008,177,3457,0,3435,246,3884,10,8237,3457,1729,0,9088,3884,1944,10,1505,3008,8237,0,1720,3435,9088,10,5840,8237,5841,0,6691,9088,6692,10,184,3499,8238,0,253,3926,9089,10,3499,1750,5842,0,3926,1965,6693,10,3460,8238,5845,0,3887,9089,6696,10,8238,5842,863,0,9089,6693,1078,10,3498,214,3518,0,3925,286,3945,10,8239,3518,1760,0,9090,3945,1975,10,1750,3498,8239,0,1965,3925,9090,10,5842,8239,5843,0,6693,9090,6694,10,292,3517,8240,0,381,3944,9091,10,3517,1759,5844,0,3944,1974,6695,10,3519,8240,5843,0,3946,9091,6694,10,8240,5844,863,0,9091,6695,1078,10,3516,289,3461,0,3943,378,3888,10,8241,3461,1731,0,9092,3888,1946,10,1759,3516,8241,0,1974,3943,9092,10,5844,8241,5845,0,6695,9092,6696,10,282,3471,8242,0,371,3898,9093,10,3471,1736,5846,0,3898,1951,6697,10,3418,8242,5849,0,3845,9093,6700,10,8242,5846,864,0,9093,6697,1079,10,3470,291,3477,0,3897,380,3904,10,8243,3477,1739,0,9094,3904,1954,10,1736,3470,8243,0,1951,3897,9094,10,5846,8243,5847,0,6697,9094,6698,10,223,3177,8244,0,301,3604,9095,10,3177,1589,5848,0,3604,1804,6699,10,3476,8244,5847,0,3903,9095,6698,10,8244,5848,864,0,9095,6699,1079,10,3176,224,3419,0,3603,302,3846,10,8245,3419,1710,0,9096,3846,1925,10,1589,3176,8245,0,1804,3603,9096,10,5848,8245,5849,0,6699,9096,6700,10,291,3467,8246,0,380,3894,9097,10,3467,1734,5850,0,3894,1949,6701,10,3474,8246,5853,0,3901,9097,6704,10,8246,5850,865,0,9097,6701,1080,10,3466,290,3481,0,3893,379,3908,10,8247,3481,1741,0,9098,3908,1956,10,1734,3466,8247,0,1949,3893,9098,10,5850,8247,5851,0,6701,9098,6702,10,198,3505,8248,0,267,3932,9099,10,3505,1753,5852,0,3932,1968,6703,10,3480,8248,5851,0,3907,9099,6702,10,8248,5852,865,0,9099,6703,1080,10,3504,193,3475,0,3931,262,3902,10,8249,3475,1738,0,9100,3902,1953,10,1753,3504,8249,0,1968,3931,9100,10,5852,8249,5853,0,6703,9100,6704,10,293,3522,8250,0,382,3949,9101,10,3522,1762,5854,0,3949,1977,6705,10,3521,8250,5857,0,3948,9101,6708,10,8250,5854,866,0,9101,6705,1081,10,3523,239,3231,0,3950,317,3658,10,8251,3231,1616,0,9102,3658,1831,10,1762,3523,8251,0,1977,3950,9102,10,5854,8251,5855,0,6705,9102,6706,10,240,3367,8252,0,318,3794,9103,10,3367,1684,5856,0,3794,1899,6707,10,3230,8252,5855,0,3657,9103,6706,10,8252,5856,866,0,9103,6707,1081,10,3366,384,3520,0,3793,338,3947,10,8253,3520,1761,0,9104,3947,1976,10,1684,3366,8253,0,1899,3793,9104,10,5856,8253,5857,0,6707,9104,6708,10,294,3526,8254,0,383,3953,9105,10,3526,1764,5858,0,3953,1979,6709,10,3525,8254,5861,0,3952,9105,6712,10,8254,5858,867,0,9105,6709,1082,10,3527,241,3235,0,3954,319,3662,10,8255,3235,1618,0,9106,3662,1833,10,1764,3527,8255,0,1979,3954,9106,10,5858,8255,5859,0,6709,9106,6710,10,239,3523,8256,0,317,3950,9107,10,3523,1762,5860,0,3950,1977,6711,10,3234,8256,5859,0,3661,9107,6710,10,8256,5860,867,0,9107,6711,1082,10,3522,293,3524,0,3949,382,3951,10,8257,3524,1763,0,9108,3951,1978,10,1762,3522,8257,0,1977,3949,9108,10,5860,8257,5861,0,6711,9108,6712,10,295,3532,8258,0,384,3959,9109,10,3532,1767,5862,0,3959,1982,6713,10,3529,8258,5865,0,3956,9109,6716,10,8258,5862,868,0,9109,6713,1083,10,3533,104,3530,0,3960,168,3957,10,8259,3530,1766,0,9110,3957,1981,10,1767,3533,8259,0,1982,3960,9110,10,5862,8259,5863,0,6713,9110,6714,10,241,3527,8260,0,319,3954,9111,10,3527,1764,5864,0,3954,1979,6715,10,3531,8260,5863,0,3958,9111,6714,10,8260,5864,868,0,9111,6715,1083,10,3526,294,3528,0,3953,383,3955,10,8261,3528,1765,0,9112,3955,1980,10,1764,3526,8261,0,1979,3953,9112,10,5864,8261,5865,0,6715,9112,6716,10,102,2793,8262,0,166,3220,9113,10,2793,1397,5866,0,3220,1612,6717,10,3342,8262,5869,0,3769,9113,6720,10,8262,5866,869,0,9113,6717,1084,10,2792,103,3536,0,3219,167,3963,10,8263,3536,1769,0,9114,3963,1984,10,1397,2792,8263,0,1612,3219,9114,10,5866,8263,5867,0,6717,9114,6718,10,296,3534,8264,0,385,3961,9115,10,3534,1768,5868,0,3961,1983,6719,10,3537,8264,5867,0,3964,9115,6718,10,8264,5868,869,0,9115,6719,1084,10,3535,265,3343,0,3962,353,3770,10,8265,3343,1672,0,9116,3770,1887,10,1768,3535,8265,0,1983,3962,9116,10,5868,8265,5869,0,6719,9116,6720,10,295,3538,8266,0,384,3965,9117,10,3538,1770,5870,0,3965,1985,6721,10,3532,8266,5873,0,3959,9117,6724,10,8266,5870,870,0,9117,6721,1085,10,3539,296,3537,0,3966,385,3964,10,8267,3537,1769,0,9118,3964,1984,10,1770,3539,8267,0,1985,3966,9118,10,5870,8267,5871,0,6721,9118,6722,10,103,2797,8268,0,167,3224,9119,10,2797,1399,5872,0,3224,1614,6723,10,3536,8268,5871,0,3963,9119,6722,10,8268,5872,870,0,9119,6723,1085,10,2796,104,3533,0,3223,168,3960,10,8269,3533,1767,0,9120,3960,1982,10,1399,2796,8269,0,1614,3223,9120,10,5872,8269,5873,0,6723,9120,6724,10,227,3241,8270,0,305,3668,9121,10,3241,1621,5874,0,3668,1836,6725,10,3186,8270,5877,0,3613,9121,6728,10,8270,5874,871,0,9121,6725,1086,10,3240,242,3239,0,3667,320,3666,10,8271,3239,1620,0,9122,3666,1835,10,1621,3240,8271,0,1836,3667,9122,10,5874,8271,5875,0,6725,9122,6726,10,241,3531,8272,0,319,3958,9123,10,3531,1766,5876,0,3958,1981,6727,10,3238,8272,5875,0,3665,9123,6726,10,8272,5876,871,0,9123,6727,1086,10,3530,104,3187,0,3957,168,3614,10,8273,3187,1594,0,9124,3614,1809,10,1766,3530,8273,0,1981,3957,9124,10,5876,8273,5877,0,6727,9124,6728,10,297,3542,8274,0,386,3969,9125,10,3542,1772,5878,0,3969,1987,6729,10,3541,8274,5881,0,3968,9125,6732,10,8274,5878,872,0,9125,6729,1087,10,3543,263,3337,0,3970,351,3764,10,8275,3337,1669,0,9126,3764,1884,10,1772,3543,8275,0,1987,3970,9126,10,5878,8275,5879,0,6729,9126,6730,10,265,3535,8276,0,353,3962,9127,10,3535,1768,5880,0,3962,1983,6731,10,3336,8276,5879,0,3763,9127,6730,10,8276,5880,872,0,9127,6731,1087,10,3534,296,3540,0,3961,385,3967,10,8277,3540,1771,0,9128,3967,1986,10,1768,3534,8277,0,1983,3961,9128,10,5880,8277,5881,0,6731,9128,6732,10,298,3546,8278,0,387,3973,9129,10,3546,1774,5882,0,3973,1989,6733,10,3545,8278,5885,0,3972,9129,6736,10,8278,5882,873,0,9129,6733,1088,10,3547,297,3541,0,3974,386,3968,10,8279,3541,1771,0,9130,3968,1986,10,1774,3547,8279,0,1989,3974,9130,10,5882,8279,5883,0,6733,9130,6734,10,296,3539,8280,0,385,3966,9131,10,3539,1770,5884,0,3966,1985,6735,10,3540,8280,5883,0,3967,9131,6734,10,8280,5884,873,0,9131,6735,1088,10,3538,295,3544,0,3965,384,3971,10,8281,3544,1773,0,9132,3971,1988,10,1770,3538,8281,0,1985,3965,9132,10,5884,8281,5885,0,6735,9132,6736,10,294,3550,8282,0,383,3977,9133,10,3550,1776,5886,0,3977,1991,6737,10,3528,8282,5889,0,3955,9133,6740,10,8282,5886,874,0,9133,6737,1089,10,3551,299,3548,0,3978,388,3975,10,8283,3548,1775,0,9134,3975,1990,10,1776,3551,8283,0,1991,3978,9134,10,5886,8283,5887,0,6737,9134,6738,10,298,3545,8284,0,387,3972,9135,10,3545,1773,5888,0,3972,1988,6739,10,3549,8284,5887,0,3976,9135,6738,10,8284,5888,874,0,9135,6739,1089,10,3544,295,3529,0,3971,384,3956,10,8285,3529,1765,0,9136,3956,1980,10,1773,3544,8285,0,1988,3971,9136,10,5888,8285,5889,0,6739,9136,6740,10,293,3554,8286,0,382,3981,9137,10,3554,1778,5890,0,3981,1993,6741,10,3524,8286,5893,0,3951,9137,6744,10,8286,5890,875,0,9137,6741,1090,10,3555,300,3552,0,3982,389,3979,10,8287,3552,1777,0,9138,3979,1992,10,1778,3555,8287,0,1993,3982,9138,10,5890,8287,5891,0,6741,9138,6742,10,299,3551,8288,0,388,3978,9139,10,3551,1776,5892,0,3978,1991,6743,10,3553,8288,5891,0,3980,9139,6742,10,8288,5892,875,0,9139,6743,1090,10,3550,294,3525,0,3977,383,3952,10,8289,3525,1763,0,9140,3952,1978,10,1776,3550,8289,0,1991,3977,9140,10,5892,8289,5893,0,6743,9140,6744,10,384,3863,8290,0,338,5439,9141,10,3863,1932,5894,0,5439,2722,6745,10,3520,8290,5897,0,3947,9141,6748,10,8290,5894,876,0,9141,6745,1091,10,3862,413,3556,0,5440,339,3983,10,8291,3556,1779,0,9142,3983,1994,10,1932,3862,8291,0,2722,5440,9142,10,5894,8291,5895,0,6745,9142,6746,10,300,3555,8292,0,389,3982,9143,10,3555,1778,5896,0,3982,1993,6747,10,3557,8292,5895,0,3984,9143,6746,10,8292,5896,876,0,9143,6747,1091,10,3554,293,3521,0,3981,382,3948,10,8293,3521,1761,0,9144,3948,1976,10,1778,3554,8293,0,1993,3981,9144,10,5896,8293,5897,0,6747,9144,6748,10,413,4007,8294,0,339,5495,9145,10,4007,2004,5898,0,5495,2750,6749,10,3556,8294,5901,0,3983,9145,6752,10,8294,5898,877,0,9145,6749,1092,10,4006,392,2995,0,5496,238,3422,10,8295,2995,1498,0,9146,3422,1713,10,2004,4006,8295,0,2750,5496,9146,10,5898,8295,5899,0,6749,9146,6750,10,170,3558,8296,0,239,3985,9147,10,3558,1780,5900,0,3985,1995,6751,10,2994,8296,5899,0,3421,9147,6750,10,8296,5900,877,0,9147,6751,1092,10,3559,300,3557,0,3986,389,3984,10,8297,3557,1779,0,9148,3984,1994,10,1780,3559,8297,0,1995,3986,9148,10,5900,8297,5901,0,6751,9148,6752,10,301,3562,8298,0,390,3989,9149,10,3562,1782,5902,0,3989,1997,6753,10,3561,8298,5905,0,3988,9149,6756,10,8298,5902,878,0,9149,6753,1093,10,3563,299,3553,0,3990,388,3980,10,8299,3553,1777,0,9150,3980,1992,10,1782,3563,8299,0,1997,3990,9150,10,5902,8299,5903,0,6753,9150,6754,10,300,3559,8300,0,389,3986,9151,10,3559,1780,5904,0,3986,1995,6755,10,3552,8300,5903,0,3979,9151,6754,10,8300,5904,878,0,9151,6755,1093,10,3558,170,3560,0,3985,239,3987,10,8301,3560,1781,0,9152,3987,1996,10,1780,3558,8301,0,1995,3985,9152,10,5904,8301,5905,0,6755,9152,6756,10,299,3563,8302,0,388,3990,9153,10,3563,1782,5906,0,3990,1997,6757,10,3548,8302,5909,0,3975,9153,6760,10,8302,5906,879,0,9153,6757,1094,10,3562,301,3564,0,3989,390,3991,10,8303,3564,1783,0,9154,3991,1998,10,1782,3562,8303,0,1997,3989,9154,10,5906,8303,5907,0,6757,9154,6758,10,297,3547,8304,0,386,3974,9155,10,3547,1774,5908,0,3974,1989,6759,10,3565,8304,5907,0,3992,9155,6758,10,8304,5908,879,0,9155,6759,1094,10,3546,298,3549,0,3973,387,3976,10,8305,3549,1775,0,9156,3976,1990,10,1774,3546,8305,0,1989,3973,9156,10,5908,8305,5909,0,6759,9156,6760,10,165,2983,8306,0,232,3410,9157,10,2983,1492,5910,0,3410,1707,6761,10,2996,8306,5913,0,3423,9157,6764,10,8306,5910,880,0,9157,6761,1095,10,2982,166,3566,0,3409,233,3993,10,8307,3566,1784,0,9158,3993,1999,10,1492,2982,8307,0,1707,3409,9158,10,5910,8307,5911,0,6761,9158,6762,10,301,3561,8308,0,390,3988,9159,10,3561,1781,5912,0,3988,1996,6763,10,3567,8308,5911,0,3994,9159,6762,10,8308,5912,880,0,9159,6763,1095,10,3560,170,2997,0,3987,239,3424,10,8309,2997,1499,0,9160,3424,1714,10,1781,3560,8309,0,1996,3987,9160,10,5912,8309,5913,0,6763,9160,6764,10,301,3567,8310,0,390,3994,9161,10,3567,1784,5914,0,3994,1999,6765,10,3564,8310,5917,0,3991,9161,6768,10,8310,5914,881,0,9161,6765,1096,10,3566,166,3331,0,3993,233,3758,10,8311,3331,1666,0,9162,3758,1881,10,1784,3566,8311,0,1999,3993,9162,10,5914,8311,5915,0,6765,9162,6766,10,263,3543,8312,0,351,3970,9163,10,3543,1772,5916,0,3970,1987,6767,10,3330,8312,5915,0,3757,9163,6766,10,8312,5916,881,0,9163,6767,1096,10,3542,297,3565,0,3969,386,3992,10,8313,3565,1783,0,9164,3992,1998,10,1772,3542,8313,0,1987,3969,9164,10,5916,8313,5917,0,6767,9164,6768,10,128,2867,8314,0,195,3294,9165,10,2867,1434,5918,0,3294,1649,6769,10,2888,8314,5921,0,3315,9165,6772,10,8314,5918,882,0,9165,6769,1097,10,2866,129,3309,0,3293,196,3736,10,8315,3309,1655,0,9166,3736,1870,10,1434,2866,8315,0,1649,3293,9166,10,5918,8315,5919,0,6769,9166,6770,10,257,3568,8316,0,344,3995,9167,10,3568,1785,5920,0,3995,2000,6771,10,3308,8316,5919,0,3735,9167,6770,10,8316,5920,882,0,9167,6771,1097,10,3569,136,2889,0,3996,203,3316,10,8317,2889,1445,0,9168,3316,1660,10,1785,3569,8317,0,2000,3996,9168,10,5920,8317,5921,0,6771,9168,6772,10,162,3570,8318,0,229,3997,9169,10,3570,1786,5922,0,3997,2001,6773,10,2980,8318,5925,0,3407,9169,6776,10,8318,5922,883,0,9169,6773,1098,10,3571,235,3209,0,3998,313,3636,10,8319,3209,1605,0,9170,3636,1820,10,1786,3571,8319,0,2001,3998,9170,10,5922,8319,5923,0,6773,9170,6774,10,232,3211,8320,0,310,3638,9171,10,3211,1606,5924,0,3638,1821,6775,10,3208,8320,5923,0,3635,9171,6774,10,8320,5924,883,0,9171,6775,1098,10,3210,164,2981,0,3637,231,3408,10,8321,2981,1491,0,9172,3408,1706,10,1606,3210,8321,0,1821,3637,9172,10,5924,8321,5925,0,6775,9172,6776,10,162,2975,8322,0,229,3402,9173,10,2975,1488,5926,0,3402,1703,6777,10,3573,8322,5929,0,4000,9173,6780,10,8322,5926,884,0,9173,6777,1099,10,2974,135,2887,0,3401,202,3314,10,8323,2887,1444,0,9174,3314,1659,10,1488,2974,8323,0,1703,3401,9174,10,5926,8323,5927,0,6777,9174,6778,10,136,3574,8324,0,203,4001,9175,10,3574,1788,5928,0,4001,2003,6779,10,2886,8324,5927,0,3313,9175,6778,10,8324,5928,884,0,9175,6779,1099,10,3575,302,3572,0,4002,391,3999,10,8325,3572,1787,0,9176,3999,2002,10,1788,3575,8325,0,2003,4002,9176,10,5928,8325,5929,0,6779,9176,6780,10,302,3576,8326,0,391,4003,9177,10,3576,1789,5930,0,4003,2004,6781,10,3572,8326,5933,0,3999,9177,6784,10,8326,5930,885,0,9177,6781,1100,10,3577,259,3317,0,4004,346,3744,10,8327,3317,1659,0,9178,3744,1874,10,1789,3577,8327,0,2004,4004,9178,10,5930,8327,5931,0,6781,9178,6782,10,235,3571,8328,0,313,3998,9179,10,3571,1786,5932,0,3998,2001,6783,10,3316,8328,5931,0,3743,9179,6782,10,8328,5932,885,0,9179,6783,1100,10,3570,162,3573,0,3997,229,4000,10,8329,3573,1787,0,9180,4000,2002,10,1786,3570,8329,0,2001,3997,9180,10,5932,8329,5933,0,6783,9180,6784,10,259,3577,8330,0,346,4004,9181,10,3577,1789,5934,0,4004,2004,6785,10,3579,8330,5937,0,4006,9181,6788,10,8330,5934,886,0,9181,6785,1101,10,3576,302,3582,0,4003,391,4009,10,8331,3582,1792,0,9182,4009,2007,10,1789,3576,8331,0,2004,4003,9182,10,5934,8331,5935,0,6785,9182,6786,10,304,3580,8332,0,393,4007,9183,10,3580,1791,5936,0,4007,2006,6787,10,3583,8332,5935,0,4010,9183,6786,10,8332,5936,886,0,9183,6787,1101,10,3581,303,3578,0,4008,392,4005,10,8333,3578,1790,0,9184,4005,2005,10,1791,3581,8333,0,2006,4008,9184,10,5936,8333,5937,0,6787,9184,6788,10,304,3588,8334,0,393,4015,9185,10,3588,1795,5938,0,4015,2010,6789,10,4751,8334,5941,0,5178,9185,6792,10,8334,5938,887,0,9185,6789,1102,10,3589,305,3586,0,4016,394,4013,10,8335,3586,1794,0,9186,4013,2009,10,1795,3589,8335,0,2010,4016,9186,10,5938,8335,5939,0,6789,9186,6790,10,587,4766,8336,0,801,5193,9187,10,4766,2384,5940,0,5193,2599,6791,10,3587,8336,5939,0,4014,9187,6790,10,8336,5940,887,0,9187,6791,1102,10,4767,593,4750,0,5194,808,5177,10,8337,4750,2376,0,9188,5177,2591,10,2384,4767,8337,0,2599,5194,9188,10,5940,8337,5941,0,6791,9188,6792,10,306,3594,8338,0,395,4021,9189,10,3594,1798,5942,0,4021,2013,6793,10,3591,8338,5945,0,4018,9189,6796,10,8338,5942,888,0,9189,6793,1103,10,3595,588,4768,0,4022,802,5195,10,8339,4768,2385,0,9190,5195,2600,10,1798,3595,8339,0,2013,4022,9190,10,5942,8339,5943,0,6793,9190,6794,10,594,4752,8340,0,809,5179,9191,10,4752,2377,5944,0,5179,2592,6795,10,4769,8340,5943,0,5196,9191,6794,10,8340,5944,888,0,9191,6795,1103,10,4753,307,3590,0,5180,396,4017,10,8341,3590,1796,0,9192,4017,2011,10,2377,4753,8341,0,2592,5180,9192,10,5944,8341,5945,0,6795,9192,6796,10,308,3598,8342,0,397,4025,9193,10,3598,1800,5946,0,4025,2015,6797,10,3597,8342,5949,0,4024,9193,6800,10,8342,5946,889,0,9193,6797,1104,10,3599,589,4770,0,4026,803,5197,10,8343,4770,2386,0,9194,5197,2601,10,1800,3599,8343,0,2015,4026,9194,10,5946,8343,5947,0,6797,9194,6798,10,588,3595,8344,0,802,4022,9195,10,3595,1798,5948,0,4022,2013,6799,10,4771,8344,5947,0,5198,9195,6798,10,8344,5948,889,0,9195,6799,1104,10,3594,306,3596,0,4021,395,4023,10,8345,3596,1799,0,9196,4023,2014,10,1798,3594,8345,0,2013,4021,9196,10,5948,8345,5949,0,6799,9196,6800,10,328,3662,8346,0,418,4089,9197,10,3662,1832,5950,0,4089,2047,6801,10,4755,8346,5953,0,5182,9197,6804,10,8346,5950,890,0,9197,6801,1105,10,3663,326,3610,0,4090,419,4037,10,8347,3610,1806,0,9198,4037,2021,10,1832,3663,8347,0,2047,4090,9198,10,5950,8347,5951,0,6801,9198,6802,10,590,4772,8348,0,804,5199,9199,10,4772,2387,5952,0,5199,2602,6803,10,3611,8348,5951,0,4038,9199,6802,10,8348,5952,890,0,9199,6803,1105,10,4773,595,4754,0,5200,810,5181,10,8349,4754,2378,0,9200,5181,2593,10,2387,4773,8349,0,2602,5200,9200,10,5952,8349,5953,0,6803,9200,6804,10,307,4753,8350,0,396,5180,9201,10,4753,2377,5954,0,5180,2592,6805,10,3613,8350,5957,0,4040,9201,6808,10,8350,5954,891,0,9201,6805,1106,10,4752,594,4774,0,5179,809,5201,10,8351,4774,2388,0,9202,5201,2603,10,2377,4752,8351,0,2592,5179,9202,10,5954,8351,5955,0,6805,9202,6806,10,596,4756,8352,0,811,5183,9203,10,4756,2379,5956,0,5183,2594,6807,10,4775,8352,5955,0,5202,9203,6806,10,8352,5956,891,0,9203,6807,1106,10,4757,315,3612,0,5184,404,4039,10,8353,3612,1807,0,9204,4039,2022,10,2379,4757,8353,0,2594,5184,9204,10,5956,8353,5957,0,6807,9204,6808,10,317,3623,8354,0,406,4050,9205,10,3623,1812,5958,0,4050,2027,6809,10,3614,8354,5961,0,4041,9205,6812,10,8354,5958,892,0,9205,6809,1107,10,3622,319,3620,0,4049,408,4047,10,8355,3620,1811,0,9206,4047,2026,10,1812,3622,8355,0,2027,4049,9206,10,5958,8355,5959,0,6809,9206,6810,10,577,4710,8356,0,790,5137,9207,10,4710,2356,5960,0,5137,2571,6811,10,3621,8356,5959,0,4048,9207,6810,10,8356,5960,892,0,9207,6811,1107,10,4711,576,3615,0,5138,789,4042,10,8357,3615,1808,0,9208,4042,2023,10,2356,4711,8357,0,2571,5138,9208,10,5960,8357,5961,0,6811,9208,6812,10,319,3631,8358,0,408,4058,9209,10,3631,1816,5962,0,4058,2031,6813,10,3620,8358,5965,0,4047,9209,6816,10,8358,5962,893,0,9209,6813,1108,10,3630,322,3628,0,4057,411,4055,10,8359,3628,1815,0,9210,4055,2030,10,1816,3630,8359,0,2031,4057,9210,10,5962,8359,5963,0,6813,9210,6814,10,578,4712,8360,0,791,5139,9211,10,4712,2357,5964,0,5139,2572,6815,10,3629,8360,5963,0,4056,9211,6814,10,8360,5964,893,0,9211,6815,1108,10,4713,577,3621,0,5140,790,4048,10,8361,3621,1811,0,9212,4048,2026,10,2357,4713,8361,0,2572,5140,9212,10,5964,8361,5965,0,6815,9212,6816,10,136,3569,8362,0,203,3996,9213,10,3569,1785,5966,0,3996,2000,6817,10,3633,8362,5969,0,4060,9213,6820,10,8362,5966,894,0,9213,6817,1109,10,3568,257,3636,0,3995,344,4063,10,8363,3636,1819,0,9214,4063,2034,10,1785,3568,8363,0,2000,3995,9214,10,5966,8363,5967,0,6817,9214,6818,10,323,3634,8364,0,412,4061,9215,10,3634,1818,5968,0,4061,2033,6819,10,3637,8364,5967,0,4064,9215,6818,10,8364,5968,894,0,9215,6819,1109,10,3635,305,3632,0,4062,394,4059,10,8365,3632,1817,0,9216,4059,2032,10,1818,3635,8365,0,2033,4062,9216,10,5968,8365,5969,0,6819,9216,6820,10,323,3642,8366,0,412,4069,9217,10,3642,1822,5970,0,4069,2037,6821,10,4763,8366,5973,0,5190,9217,6824,10,8366,5970,895,0,9217,6821,1110,10,3643,324,3640,0,4070,413,4067,10,8367,3640,1821,0,9218,4067,2036,10,1822,3643,8367,0,2037,4070,9218,10,5970,8367,5971,0,6821,9218,6822,10,591,4776,8368,0,806,5203,9219,10,4776,2389,5972,0,5203,2604,6823,10,3641,8368,5971,0,4068,9219,6822,10,8368,5972,895,0,9219,6823,1110,10,4777,599,4762,0,5204,814,5189,10,8369,4762,2382,0,9220,5189,2597,10,2389,4777,8369,0,2604,5204,9220,10,5972,8369,5973,0,6823,9220,6824,10,324,3644,8370,0,413,4071,9221,10,3644,1823,5974,0,4071,2038,6825,10,3640,8370,5977,0,4067,9221,6828,10,8370,5974,896,0,9221,6825,1111,10,3645,321,4761,0,4072,410,5188,10,8371,4761,2381,0,9222,5188,2596,10,1823,3645,8371,0,2038,4072,9222,10,5974,8371,5975,0,6825,9222,6826,10,598,4778,8372,0,813,5205,9223,10,4778,2390,5976,0,5205,2605,6827,10,4760,8372,5975,0,5187,9223,6826,10,8372,5976,896,0,9223,6827,1111,10,4779,591,3641,0,5206,806,4068,10,8373,3641,1821,0,9224,4068,2036,10,2390,4779,8373,0,2605,5206,9224,10,5976,8373,5977,0,6827,9224,6828,10,310,3683,8374,0,399,4110,9225,10,3683,1842,5978,0,4110,2057,6829,10,4709,8374,5981,0,5136,9225,6832,10,8374,5978,897,0,9225,6829,1112,10,3682,327,3650,0,4109,417,4077,10,8375,3650,1826,0,9226,4077,2041,10,1842,3682,8375,0,2057,4109,9226,10,5978,8375,5979,0,6829,9226,6830,10,580,4714,8376,0,793,5141,9227,10,4714,2358,5980,0,5141,2573,6831,10,3651,8376,5979,0,4078,9227,6830,10,8376,5980,897,0,9227,6831,1112,10,4715,586,4708,0,5142,800,5135,10,8377,4708,2355,0,9228,5135,2570,10,2358,4715,8377,0,2573,5142,9228,10,5980,8377,5981,0,6831,9228,6832,10,327,3655,8378,0,417,4082,9229,10,3655,1828,5982,0,4082,2043,6833,10,3650,8378,5985,0,4077,9229,6836,10,8378,5982,898,0,9229,6833,1113,10,3654,314,4705,0,4081,416,5641,10,8379,4705,2353,0,9230,5641,2823,10,1828,3654,8379,0,2043,4081,9230,10,5982,8379,5983,0,6833,9230,6834,10,584,4716,8380,0,798,5143,9231,10,4716,2359,5984,0,5143,2574,6835,10,4704,8380,5983,0,5642,9231,6834,10,8380,5984,898,0,9231,6835,1113,10,4717,580,3651,0,5144,793,4078,10,8381,3651,1826,0,9232,4078,2041,10,2359,4717,8381,0,2574,5144,9232,10,5984,8381,5985,0,6835,9232,6836,10,308,3660,8382,0,397,4087,9233,10,3660,1831,5986,0,4087,2046,6837,10,3657,8382,5989,0,4084,9233,6840,10,8382,5986,899,0,9233,6837,1114,10,3661,262,3329,0,4088,349,3756,10,8383,3329,1665,0,9234,3756,1880,10,1831,3661,8383,0,2046,4088,9234,10,5986,8383,5987,0,6837,9234,6838,10,261,3658,8384,0,350,4085,9235,10,3658,1830,5988,0,4085,2045,6839,10,3328,8384,5987,0,3755,9235,6838,10,8384,5988,899,0,9235,6839,1114,10,3659,328,3656,0,4086,418,4083,10,8385,3656,1829,0,9236,4083,2044,10,1830,3659,8385,0,2045,4086,9236,10,5988,8385,5989,0,6839,9236,6840,10,315,3668,8386,0,404,4095,9237,10,3668,1835,5990,0,4095,2050,6841,10,3612,8386,5993,0,4039,9237,6844,10,8386,5990,900,0,9237,6841,1115,10,3669,267,3347,0,4096,355,3774,10,8387,3347,1674,0,9238,3774,1889,10,1835,3669,8387,0,2050,4096,9238,10,5990,8387,5991,0,6841,9238,6842,10,266,3666,8388,0,354,4093,9239,10,3666,1834,5992,0,4093,2049,6843,10,3346,8388,5991,0,3773,9239,6842,10,8388,5992,900,0,9239,6843,1115,10,3667,307,3613,0,4094,396,4040,10,8389,3613,1807,0,9240,4040,2022,10,1834,3667,8389,0,2049,4094,9240,10,5992,8389,5993,0,6843,9240,6844,10,256,3353,8390,0,343,3780,9241,10,3353,1677,5994,0,3780,1892,6845,10,3671,8390,5997,0,4098,9241,6848,10,8390,5994,901,0,9241,6845,1116,10,3352,268,3672,0,3779,356,4099,10,8391,3672,1837,0,9242,4099,2052,10,1677,3352,8391,0,1892,3779,9242,10,5994,8391,5995,0,6845,9242,6846,10,320,3627,8392,0,409,4054,9243,10,3627,1814,5996,0,4054,2029,6847,10,3673,8392,5995,0,4100,9243,6846,10,8392,5996,901,0,9243,6847,1116,10,3626,321,3670,0,4053,410,4097,10,8393,3670,1836,0,9244,4097,2051,10,1814,3626,8393,0,2029,4053,9244,10,5996,8393,5997,0,6847,9244,6848,10,305,3635,8394,0,394,4062,9245,10,3635,1818,5998,0,4062,2033,6849,10,3586,8394,6001,0,4013,9245,6852,10,8394,5998,902,0,9245,6849,1117,10,3634,323,4763,0,4061,412,5190,10,8395,4763,2382,0,9246,5190,2597,10,1818,3634,8395,0,2033,4061,9246,10,5998,8395,5999,0,6849,9246,6850,10,599,4780,8396,0,814,5207,9247,10,4780,2391,6000,0,5207,2606,6851,10,4762,8396,5999,0,5189,9247,6850,10,8396,6000,902,0,9247,6851,1117,10,4781,587,3587,0,5208,801,4014,10,8397,3587,1794,0,9248,4014,2009,10,2391,4781,8397,0,2606,5208,9248,10,6000,8397,6001,0,6851,9248,6852,10,260,3321,8398,0,347,3748,9249,10,3321,1661,6002,0,3748,1876,6853,10,3677,8398,6005,0,4104,9249,6856,10,8398,6002,903,0,9249,6853,1118,10,3320,258,3678,0,3747,345,4105,10,8399,3678,1840,0,9250,4105,2055,10,1661,3320,8399,0,1876,3747,9250,10,6002,8399,6003,0,6853,9250,6854,10,325,3653,8400,0,414,4080,9251,10,3653,1827,6004,0,4080,2042,6855,10,3679,8400,6003,0,4106,9251,6854,10,8400,6004,903,0,9251,6855,1118,10,3652,326,3676,0,4079,415,4103,10,8401,3676,1839,0,9252,4103,2054,10,1827,3652,8401,0,2042,4079,9252,10,6004,8401,6005,0,6855,9252,6856,10,309,3601,8402,0,398,4028,9253,10,3601,1801,6006,0,4028,2016,6857,10,3584,8402,6009,0,4011,9253,6860,10,8402,6006,904,0,9253,6857,1119,10,3600,310,4709,0,4027,399,5136,10,8403,4709,2355,0,9254,5136,2570,10,1801,3600,8403,0,2016,4027,9254,10,6006,8403,6007,0,6857,9254,6858,10,586,4718,8404,0,800,5145,9255,10,4718,2360,6008,0,5145,2575,6859,10,4708,8404,6007,0,5135,9255,6858,10,8404,6008,904,0,9255,6859,1119,10,4719,573,3585,0,5146,786,4012,10,8405,3585,1793,0,9256,4012,2008,10,2360,4719,8405,0,2575,5146,9256,10,6008,8405,6009,0,6859,9256,6860,10,305,3589,8406,0,394,4016,9257,10,3589,1795,6010,0,4016,2010,6861,10,3632,8406,6013,0,4059,9257,6864,10,8406,6010,905,0,9257,6861,1120,10,3588,304,3583,0,4015,393,4010,10,8407,3583,1792,0,9258,4010,2007,10,1795,3588,8407,0,2010,4015,9258,10,6010,8407,6011,0,6861,9258,6862,10,302,3575,8408,0,391,4002,9259,10,3575,1788,6012,0,4002,2003,6863,10,3582,8408,6011,0,4009,9259,6862,10,8408,6012,905,0,9259,6863,1120,10,3574,136,3633,0,4001,203,4060,10,8409,3633,1817,0,9260,4060,2032,10,1788,3574,8409,0,2003,4001,9260,10,6012,8409,6013,0,6863,9260,6864,10,264,3335,8410,0,352,3762,9261,10,3335,1668,6014,0,3762,1883,6865,10,3687,8410,6017,0,4114,9261,6868,10,8410,6014,906,0,9261,6865,1121,10,3334,262,3661,0,3761,349,4088,10,8411,3661,1831,0,9262,4088,2046,10,1668,3334,8411,0,1883,3761,9262,10,6014,8411,6015,0,6865,9262,6866,10,308,3597,8412,0,397,4024,9263,10,3597,1799,6016,0,4024,2014,6867,10,3660,8412,6015,0,4087,9263,6866,10,8412,6016,906,0,9263,6867,1121,10,3596,306,3686,0,4023,395,4113,10,8413,3686,1844,0,9264,4113,2059,10,1799,3596,8413,0,2014,4023,9264,10,6016,8413,6017,0,6867,9264,6868,10,255,3688,8414,0,342,4115,9265,10,3688,1845,6018,0,4115,2060,6869,10,3310,8414,6021,0,3737,9265,6872,10,8414,6018,907,0,9265,6869,1122,10,3689,324,3643,0,4116,413,4070,10,8415,3643,1822,0,9266,4070,2037,10,1845,3689,8415,0,2060,4116,9266,10,6018,8415,6019,0,6869,9266,6870,10,323,3637,8416,0,412,4064,9267,10,3637,1819,6020,0,4064,2034,6871,10,3642,8416,6019,0,4069,9267,6870,10,8416,6020,907,0,9267,6871,1122,10,3636,257,3311,0,4063,344,3738,10,8417,3311,1656,0,9268,3738,1871,10,1819,3636,8417,0,2034,4063,9268,10,6020,8417,6021,0,6871,9268,6872,10,256,3671,8418,0,343,4098,9269,10,3671,1836,6022,0,4098,2051,6873,10,3304,8418,6025,0,3731,9269,6876,10,8418,6022,908,0,9269,6873,1123,10,3670,321,3645,0,4097,410,4072,10,8419,3645,1823,0,9270,4072,2038,10,1836,3670,8419,0,2051,4097,9270,10,6022,8419,6023,0,6873,9270,6874,10,324,3689,8420,0,413,4116,9271,10,3689,1845,6024,0,4116,2060,6875,10,3644,8420,6023,0,4071,9271,6874,10,8420,6024,908,0,9271,6875,1123,10,3688,255,3305,0,4115,342,3732,10,8421,3305,1653,0,9272,3732,1868,10,1845,3688,8421,0,2060,4115,9272,10,6024,8421,6025,0,6875,9272,6876,10,308,3657,8422,0,397,4084,9273,10,3657,1829,6026,0,4084,2044,6877,10,3598,8422,6029,0,4025,9273,6880,10,8422,6026,909,0,9273,6877,1124,10,3656,328,4755,0,4083,418,5182,10,8423,4755,2378,0,9274,5182,2593,10,1829,3656,8423,0,2044,4083,9274,10,6026,8423,6027,0,6877,9274,6878,10,595,4782,8424,0,810,5209,9275,10,4782,2392,6028,0,5209,2607,6879,10,4754,8424,6027,0,5181,9275,6878,10,8424,6028,909,0,9275,6879,1124,10,4783,589,3599,0,5210,803,4026,10,8425,3599,1800,0,9276,4026,2015,10,2392,4783,8425,0,2607,5210,9276,10,6028,8425,6029,0,6879,9276,6880,10,260,3677,8426,0,422,5373,9277,10,3677,1839,6030,0,5373,2689,6881,10,3324,8426,6033,0,5366,9277,6884,10,8426,6030,910,0,9277,6881,1125,10,3676,326,3663,0,5374,419,4090,10,8427,3663,1832,0,9278,4090,2047,10,1839,3676,8427,0,2689,5374,9278,10,6030,8427,6031,0,6881,9278,6882,10,328,3659,8428,0,418,4086,9279,10,3659,1830,6032,0,4086,2045,6883,10,3662,8428,6031,0,4089,9279,6882,10,8428,6032,910,0,9279,6883,1125,10,3658,261,3325,0,4085,350,5365,10,8429,3325,1663,0,9280,5365,2685,10,1830,3658,8429,0,2045,4085,9280,10,6032,8429,6033,0,6883,9280,6884,10,267,3669,8430,0,355,4096,9281,10,3669,1835,6034,0,4096,2050,6885,10,3350,8430,6037,0,3777,9281,6888,10,8430,6034,911,0,9281,6885,1126,10,3668,315,3625,0,4095,404,4052,10,8431,3625,1813,0,9282,4052,2028,10,1835,3668,8431,0,2050,4095,9282,10,6034,8431,6035,0,6885,9282,6886,10,320,3673,8432,0,409,4100,9283,10,3673,1837,6036,0,4100,2052,6887,10,3624,8432,6035,0,4051,9283,6886,10,8432,6036,911,0,9283,6887,1126,10,3672,268,3351,0,4099,356,3778,10,8433,3351,1676,0,9284,3778,1891,10,1837,3672,8433,0,2052,4099,9284,10,6036,8433,6037,0,6887,9284,6888,10,258,3315,8434,0,345,3742,9285,10,3315,1658,6038,0,3742,1873,6889,10,3678,8434,6041,0,4105,9285,6892,10,8434,6038,912,0,9285,6889,1127,10,3314,259,3579,0,3741,346,4006,10,8435,3579,1790,0,9286,4006,2005,10,1658,3314,8435,0,1873,3741,9286,10,6038,8435,6039,0,6889,9286,6890,10,303,3649,8436,0,392,4076,9287,10,3649,1825,6040,0,4076,2040,6891,10,3578,8436,6039,0,4005,9287,6890,10,8436,6040,912,0,9287,6891,1127,10,3648,325,3679,0,4075,414,4106,10,8437,3679,1840,0,9288,4106,2055,10,1825,3648,8437,0,2040,4075,9288,10,6040,8437,6041,0,6891,9288,6892,10,307,3667,8438,0,396,4094,9289,10,3667,1834,6042,0,4094,2049,6893,10,3590,8438,6045,0,4017,9289,6896,10,8438,6042,913,0,9289,6893,1128,10,3666,266,3341,0,4093,354,3768,10,8439,3341,1671,0,9290,3768,1886,10,1834,3666,8439,0,2049,4093,9290,10,6042,8439,6043,0,6893,9290,6894,10,264,3687,8440,0,352,4114,9291,10,3687,1844,6044,0,4114,2059,6895,10,3340,8440,6043,0,3767,9291,6894,10,8440,6044,913,0,9291,6895,1128,10,3686,306,3591,0,4113,395,4018,10,8441,3591,1796,0,9292,4018,2011,10,1844,3686,8441,0,2059,4113,9292,10,6044,8441,6045,0,6895,9292,6896,10,332,3690,8442,0,429,4117,9293,10,3690,1846,6046,0,4117,2061,6897,10,3697,8442,6049,0,4124,9293,6900,10,8442,6046,914,0,9293,6897,1129,10,3691,348,3692,0,4118,468,4119,10,8443,3692,1847,0,9294,4119,2062,10,1846,3691,8443,0,2061,4118,9294,10,6046,8443,6047,0,6897,9294,6898,10,339,3694,8444,0,443,4121,9295,10,3694,1848,6048,0,4121,2063,6899,10,3693,8444,6047,0,4120,9295,6898,10,8444,6048,914,0,9295,6899,1129,10,3695,352,3696,0,4122,472,4123,10,8445,3696,1849,0,9296,4123,2064,10,1848,3695,8445,0,2063,4122,9296,10,6048,8445,6049,0,6899,9296,6900,10,348,3698,8446,0,468,4125,9297,10,3698,1850,6050,0,4125,2065,6901,10,3692,8446,6053,0,4119,9297,6904,10,8446,6050,915,0,9297,6901,1130,10,3699,331,3700,0,4126,430,4127,10,8447,3700,1851,0,9298,4127,2066,10,1850,3699,8447,0,2065,4126,9298,10,6050,8447,6051,0,6901,9298,6902,10,353,3702,8448,0,457,4129,9299,10,3702,1852,6052,0,4129,2067,6903,10,3701,8448,6051,0,4128,9299,6902,10,8448,6052,915,0,9299,6903,1130,10,3703,339,3693,0,4130,443,4120,10,8449,3693,1847,0,9300,4120,2062,10,1852,3703,8449,0,2067,4130,9300,10,6052,8449,6053,0,6903,9300,6904,10,333,3704,8450,0,432,4131,9301,10,3704,1853,6054,0,4131,2068,6905,10,3709,8450,6057,0,4136,9301,6908,10,8450,6054,916,0,9301,6905,1131,10,3705,350,3706,0,4132,470,4133,10,8451,3706,1854,0,9302,4133,2069,10,1853,3705,8451,0,2068,4132,9302,10,6054,8451,6055,0,6905,9302,6906,10,339,3703,8452,0,443,4130,9303,10,3703,1852,6056,0,4130,2067,6907,10,3707,8452,6055,0,4134,9303,6906,10,8452,6056,916,0,9303,6907,1131,10,3702,353,3708,0,4129,457,4135,10,8453,3708,1855,0,9304,4135,2070,10,1852,3702,8453,0,2067,4129,9304,10,6056,8453,6057,0,6907,9304,6908,10,350,3710,8454,0,470,4137,9305,10,3710,1856,6058,0,4137,2071,6909,10,3706,8454,6061,0,4133,9305,6912,10,8454,6058,917,0,9305,6909,1132,10,3711,334,3712,0,4138,431,4139,10,8455,3712,1857,0,9306,4139,2072,10,1856,3711,8455,0,2071,4138,9306,10,6058,8455,6059,0,6909,9306,6910,10,352,3695,8456,0,472,4122,9307,10,3695,1848,6060,0,4122,2063,6911,10,3713,8456,6059,0,4140,9307,6910,10,8456,6060,917,0,9307,6911,1132,10,3694,339,3707,0,4121,443,4134,10,8457,3707,1854,0,9308,4134,2069,10,1848,3694,8457,0,2063,4121,9308,10,6060,8457,6061,0,6911,9308,6912,10,331,3714,8458,0,433,4141,9309,10,3714,1858,6062,0,4141,2073,6913,10,3700,8458,6065,0,5382,9309,6916,10,8458,6062,918,0,9309,6913,1133,10,3715,354,3716,0,4142,474,4143,10,8459,3716,1859,0,9310,4143,2074,10,1858,3715,8459,0,2073,4142,9310,10,6062,8459,6063,0,6913,9310,6914,10,340,3718,8460,0,444,4145,9311,10,3718,1860,6064,0,4145,2075,6915,10,3717,8460,6063,0,4144,9311,6914,10,8460,6064,918,0,9311,6915,1133,10,3719,353,3701,0,4146,473,5381,10,8461,3701,1851,0,9312,5381,2693,10,1860,3719,8461,0,2075,4146,9312,10,6064,8461,6065,0,6915,9312,6916,10,354,3720,8462,0,474,4147,9313,10,3720,1861,6066,0,4147,2076,6917,10,3716,8462,6069,0,4143,9313,6920,10,8462,6066,919,0,9313,6917,1134,10,3721,335,3722,0,4148,436,4149,10,8463,3722,1862,0,9314,4149,2077,10,1861,3721,8463,0,2076,4148,9314,10,6066,8463,6067,0,6917,9314,6918,10,361,3724,8464,0,465,4151,9315,10,3724,1863,6068,0,4151,2078,6919,10,3723,8464,6067,0,4150,9315,6918,10,8464,6068,919,0,9315,6919,1134,10,3725,340,3717,0,4152,444,4144,10,8465,3717,1859,0,9316,4144,2074,10,1863,3725,8465,0,2078,4152,9316,10,6068,8465,6069,0,6919,9316,6920,10,338,3726,8466,0,442,4153,9317,10,3726,1864,6070,0,4153,2079,6921,10,3731,8466,6073,0,4158,9317,6924,10,8466,6070,920,0,9317,6921,1135,10,3727,351,3728,0,4154,471,4155,10,8467,3728,1865,0,9318,4155,2080,10,1864,3727,8467,0,2079,4154,9318,10,6070,8467,6071,0,6921,9318,6922,10,340,3725,8468,0,444,4152,9319,10,3725,1863,6072,0,4152,2078,6923,10,3729,8468,6071,0,4156,9319,6922,10,8468,6072,920,0,9319,6923,1135,10,3724,361,3730,0,4151,465,4157,10,8469,3730,1866,0,9320,4157,2081,10,1863,3724,8469,0,2078,4151,9320,10,6072,8469,6073,0,6923,9320,6924,10,351,3732,8470,0,471,4159,9321,10,3732,1867,6074,0,4159,2082,6925,10,3728,8470,6077,0,4155,9321,6928,10,8470,6074,921,0,9321,6925,1136,10,3733,333,3709,0,4160,434,5385,10,8471,3709,1855,0,9322,5385,2695,10,1867,3733,8471,0,2082,4160,9322,10,6074,8471,6075,0,6925,9322,6926,10,353,3719,8472,0,473,4146,9323,10,3719,1860,6076,0,4146,2075,6927,10,3708,8472,6075,0,5386,9323,6926,10,8472,6076,921,0,9323,6927,1136,10,3718,340,3729,0,4145,444,4156,10,8473,3729,1865,0,9324,4156,2080,10,1860,3718,8473,0,2075,4145,9324,10,6076,8473,6077,0,6927,9324,6928,10,335,3721,8474,0,435,5393,9325,10,3721,1861,6078,0,5393,2699,6929,10,3739,8474,6081,0,4166,9325,6932,10,8474,6078,922,0,9325,6929,1137,10,3720,354,3734,0,5394,458,4161,10,8475,3734,1868,0,9326,4161,2083,10,1861,3720,8475,0,2699,5394,9326,10,6078,8475,6079,0,6929,9326,6930,10,341,3736,8476,0,445,4163,9327,10,3736,1869,6080,0,4163,2084,6931,10,3735,8476,6079,0,4162,9327,6930,10,8476,6080,922,0,9327,6931,1137,10,3737,358,3738,0,4164,462,4165,10,8477,3738,1870,0,9328,4165,2085,10,1869,3737,8477,0,2084,4164,9328,10,6080,8477,6081,0,6931,9328,6932,10,354,3715,8478,0,458,5391,9329,10,3715,1858,6082,0,5391,2698,6933,10,3734,8478,6085,0,4161,9329,6936,10,8478,6082,923,0,9329,6933,1138,10,3714,331,3699,0,5392,423,5379,10,8479,3699,1850,0,9330,5379,2692,10,1858,3714,8479,0,2698,5392,9330,10,6082,8479,6083,0,6933,9330,6934,10,348,3740,8480,0,452,4167,9331,10,3740,1871,6084,0,4167,2086,6935,10,3698,8480,6083,0,5380,9331,6934,10,8480,6084,923,0,9331,6935,1138,10,3741,341,3735,0,4168,445,4162,10,8481,3735,1868,0,9332,4162,2083,10,1871,3741,8481,0,2086,4168,9332,10,6084,8481,6085,0,6935,9332,6936,10,332,3742,8482,0,424,4169,9333,10,3742,1872,6086,0,4169,2087,6937,10,3690,8482,6089,0,5376,9333,6940,10,8482,6086,924,0,9333,6937,1139,10,3743,349,3744,0,4170,453,4171,10,8483,3744,1873,0,9334,4171,2088,10,1872,3743,8483,0,2087,4170,9334,10,6086,8483,6087,0,6937,9334,6938,10,341,3741,8484,0,445,4168,9335,10,3741,1871,6088,0,4168,2086,6939,10,3745,8484,6087,0,4172,9335,6938,10,8484,6088,924,0,9335,6939,1139,10,3740,348,3691,0,4167,452,5375,10,8485,3691,1846,0,9336,5375,2690,10,1871,3740,8485,0,2086,4167,9336,10,6088,8485,6089,0,6939,9336,6940,10,349,3746,8486,0,453,4173,9337,10,3746,1874,6090,0,4173,2089,6941,10,3744,8486,6093,0,4171,9337,6944,10,8486,6090,925,0,9337,6941,1140,10,3747,336,3748,0,4174,437,4175,10,8487,3748,1875,0,9338,4175,2090,10,1874,3747,8487,0,2089,4174,9338,10,6090,8487,6091,0,6941,9338,6942,10,358,3737,8488,0,462,4164,9339,10,3737,1869,6092,0,4164,2084,6943,10,3749,8488,6091,0,4176,9339,6942,10,8488,6092,925,0,9339,6943,1140,10,3736,341,3745,0,4163,445,4172,10,8489,3745,1873,0,9340,4172,2088,10,1869,3736,8489,0,2084,4163,9340,10,6092,8489,6093,0,6943,9340,6944,10,337,3750,8490,0,439,4177,9341,10,3750,1876,6094,0,4177,2091,6945,10,3757,8490,6097,0,4184,9341,6948,10,8490,6094,926,0,9341,6945,1141,10,3751,356,3752,0,4178,460,4179,10,8491,3752,1877,0,9342,4179,2092,10,1876,3751,8491,0,2091,4178,9342,10,6094,8491,6095,0,6945,9342,6946,10,342,3754,8492,0,446,4181,9343,10,3754,1878,6096,0,4181,2093,6947,10,3753,8492,6095,0,4180,9343,6946,10,8492,6096,926,0,9343,6947,1141,10,3755,359,3756,0,4182,463,4183,10,8493,3756,1879,0,9344,4183,2094,10,1878,3755,8493,0,2093,4182,9344,10,6096,8493,6097,0,6947,9344,6948,10,356,3758,8494,0,460,4185,9345,10,3758,1880,6098,0,4185,2095,6949,10,3752,8494,6101,0,4179,9345,6952,10,8494,6098,927,0,9345,6949,1142,10,3759,334,3711,0,4186,426,5387,10,8495,3711,1856,0,9346,5387,2696,10,1880,3759,8495,0,2095,4186,9346,10,6098,8495,6099,0,6949,9346,6950,10,350,3760,8496,0,454,4187,9347,10,3760,1881,6100,0,4187,2096,6951,10,3710,8496,6099,0,5388,9347,6950,10,8496,6100,927,0,9347,6951,1142,10,3761,342,3753,0,4188,446,4180,10,8497,3753,1877,0,9348,4180,2092,10,1881,3761,8497,0,2096,4188,9348,10,6100,8497,6101,0,6951,9348,6952,10,333,3733,8498,0,425,5397,9349,10,3733,1867,6102,0,5397,2701,6953,10,3704,8498,6105,0,5384,9349,6956,10,8498,6102,928,0,9349,6953,1143,10,3732,351,3762,0,5398,455,4189,10,8499,3762,1882,0,9350,4189,2097,10,1867,3732,8499,0,2701,5398,9350,10,6102,8499,6103,0,6953,9350,6954,10,342,3761,8500,0,446,4188,9351,10,3761,1881,6104,0,4188,2096,6955,10,3763,8500,6103,0,4190,9351,6954,10,8500,6104,928,0,9351,6955,1143,10,3760,350,3705,0,4187,454,5383,10,8501,3705,1853,0,9352,5383,2694,10,1881,3760,8501,0,2096,4187,9352,10,6104,8501,6105,0,6955,9352,6956,10,351,3727,8502,0,455,5395,9353,10,3727,1864,6106,0,5395,2700,6957,10,3762,8502,6109,0,4189,9353,6960,10,8502,6106,929,0,9353,6957,1144,10,3726,338,3764,0,5396,441,4191,10,8503,3764,1883,0,9354,4191,2098,10,1864,3726,8503,0,2700,5396,9354,10,6106,8503,6107,0,6957,9354,6958,10,359,3755,8504,0,463,4182,9355,10,3755,1878,6108,0,4182,2093,6959,10,3765,8504,6107,0,4192,9355,6958,10,8504,6108,929,0,9355,6959,1144,10,3754,342,3763,0,4181,446,4190,10,8505,3763,1882,0,9356,4190,2097,10,1878,3754,8505,0,2093,4181,9356,10,6108,8505,6109,0,6959,9356,6960,10,336,3747,8506,0,438,5401,9357,10,3747,1874,6110,0,5401,2703,6961,10,3771,8506,6113,0,4198,9357,6964,10,8506,6110,930,0,9357,6961,1145,10,3746,349,3766,0,5402,469,4193,10,8507,3766,1884,0,9358,4193,2099,10,1874,3746,8507,0,2703,5402,9358,10,6110,8507,6111,0,6961,9358,6962,10,343,3768,8508,0,447,4195,9359,10,3768,1885,6112,0,4195,2100,6963,10,3767,8508,6111,0,4194,9359,6962,10,8508,6112,930,0,9359,6963,1145,10,3769,360,3770,0,4196,464,4197,10,8509,3770,1886,0,9360,4197,2101,10,1885,3769,8509,0,2100,4196,9360,10,6112,8509,6113,0,6963,9360,6964,10,349,3743,8510,0,469,5399,9361,10,3743,1872,6114,0,5399,2702,6965,10,3766,8510,6117,0,4193,9361,6968,10,8510,6114,931,0,9361,6965,1146,10,3742,332,3697,0,5400,427,5377,10,8511,3697,1849,0,9362,5377,2691,10,1872,3742,8511,0,2702,5400,9362,10,6114,8511,6115,0,6965,9362,6966,10,352,3772,8512,0,456,4199,9363,10,3772,1887,6116,0,4199,2102,6967,10,3696,8512,6115,0,5378,9363,6966,10,8512,6116,931,0,9363,6967,1146,10,3773,343,3767,0,4200,447,4194,10,8513,3767,1884,0,9364,4194,2099,10,1887,3773,8513,0,2102,4200,9364,10,6116,8513,6117,0,6967,9364,6968,10,334,3759,8514,0,428,5405,9365,10,3759,1880,6118,0,5405,2705,6969,10,3712,8514,6121,0,5390,9365,6972,10,8514,6118,932,0,9365,6969,1147,10,3758,356,3774,0,5406,476,4201,10,8515,3774,1888,0,9366,4201,2103,10,1880,3758,8515,0,2705,5406,9366,10,6118,8515,6119,0,6969,9366,6970,10,343,3773,8516,0,447,4200,9367,10,3773,1887,6120,0,4200,2102,6971,10,3775,8516,6119,0,4202,9367,6970,10,8516,6120,932,0,9367,6971,1147,10,3772,352,3713,0,4199,456,5389,10,8517,3713,1857,0,9368,5389,2697,10,1887,3772,8517,0,2102,4199,9368,10,6120,8517,6121,0,6971,9368,6972,10,356,3751,8518,0,476,5403,9369,10,3751,1876,6122,0,5403,2704,6973,10,3774,8518,6125,0,4201,9369,6976,10,8518,6122,933,0,9369,6973,1148,10,3750,337,3776,0,5404,440,4203,10,8519,3776,1889,0,9370,4203,2104,10,1876,3750,8519,0,2704,5404,9370,10,6122,8519,6123,0,6973,9370,6974,10,360,3769,8520,0,464,4196,9371,10,3769,1885,6124,0,4196,2100,6975,10,3777,8520,6123,0,4204,9371,6974,10,8520,6124,933,0,9371,6975,1148,10,3768,343,3775,0,4195,447,4202,10,8521,3775,1888,0,9372,4202,2103,10,1885,3768,8521,0,2100,4195,9372,10,6124,8521,6125,0,6975,9372,6976,10,335,3778,8522,0,436,4205,9373,10,3778,1890,6126,0,4205,2105,6977,10,3722,8522,6129,0,4149,9373,6980,10,8522,6126,934,0,9373,6977,1149,10,3779,362,3780,0,4206,478,4207,10,8523,3780,1891,0,9374,4207,2106,10,1890,3779,8523,0,2105,4206,9374,10,6126,8523,6127,0,6977,9374,6978,10,344,3782,8524,0,448,4209,9375,10,3782,1892,6128,0,4209,2107,6979,10,3781,8524,6127,0,4208,9375,6978,10,8524,6128,934,0,9375,6979,1149,10,3783,361,3723,0,4210,465,4150,10,8525,3723,1862,0,9376,4150,2077,10,1892,3783,8525,0,2107,4210,9376,10,6128,8525,6129,0,6979,9376,6980,10,362,3817,8526,0,478,5419,9377,10,3817,1909,6130,0,5419,2712,6981,10,3780,8526,6133,0,4207,9377,6984,10,8526,6130,935,0,9377,6981,1150,10,3816,127,2863,0,5420,192,3290,10,8527,2863,1432,0,9378,3290,1647,10,1909,3816,8527,0,2712,5420,9378,10,6130,8527,6131,0,6981,9378,6982,10,120,3818,8528,0,193,4245,9379,10,3818,1910,6132,0,4245,2125,6983,10,2862,8528,6131,0,3289,9379,6982,10,8528,6132,935,0,9379,6983,1150,10,3819,344,3781,0,4246,448,4208,10,8529,3781,1891,0,9380,4208,2106,10,1910,3819,8529,0,2125,4246,9380,10,6132,8529,6133,0,6983,9380,6984,10,357,3784,8530,0,477,4211,9381,10,3784,1893,6134,0,4211,2108,6985,10,3821,8530,6137,0,4248,9381,6988,10,8530,6134,936,0,9381,6985,1151,10,3785,344,3819,0,4212,448,5421,10,8531,3819,1910,0,9382,5421,2713,10,1893,3785,8531,0,2108,4212,9382,10,6134,8531,6135,0,6985,9382,6986,10,120,2845,8532,0,184,3272,9383,10,2845,1423,6136,0,3272,1638,6987,10,3818,8532,6135,0,5422,9383,6986,10,8532,6136,936,0,9383,6987,1151,10,2844,121,3820,0,3271,185,4247,10,8533,3820,1911,0,9384,4247,2126,10,1423,2844,8533,0,1638,3271,9384,10,6136,8533,6137,0,6987,9384,6988,10,357,3786,8534,0,477,4213,9385,10,3786,1894,6138,0,4213,2109,6989,10,3784,8534,6141,0,4211,9385,6992,10,8534,6138,937,0,9385,6989,1152,10,3787,338,3731,0,4214,442,4158,10,8535,3731,1866,0,9386,4158,2081,10,1894,3787,8535,0,2109,4214,9386,10,6138,8535,6139,0,6989,9386,6990,10,361,3783,8536,0,465,4210,9387,10,3783,1892,6140,0,4210,2107,6991,10,3730,8536,6139,0,4157,9387,6990,10,8536,6140,937,0,9387,6991,1152,10,3782,344,3785,0,4209,448,4212,10,8537,3785,1893,0,9388,4212,2108,10,1892,3782,8537,0,2107,4209,9388,10,6140,8537,6141,0,6991,9388,6992,10,362,3788,8538,0,466,4215,9389,10,3788,1895,6142,0,4215,2110,6993,10,3817,8538,6145,0,4244,9389,6996,10,8538,6142,938,0,9389,6993,1153,10,3789,345,3815,0,4216,449,4242,10,8539,3815,1908,0,9390,4242,2123,10,1895,3789,8539,0,2110,4216,9390,10,6142,8539,6143,0,6993,9390,6994,10,153,2937,8540,0,220,3364,9391,10,2937,1469,6144,0,3364,1684,6995,10,3814,8540,6143,0,4241,9391,6994,10,8540,6144,938,0,9391,6995,1153,10,2936,127,3816,0,3363,192,4243,10,8541,3816,1909,0,9392,4243,2124,10,1469,2936,8541,0,1684,3363,9392,10,6144,8541,6145,0,6995,9392,6996,10,362,3779,8542,0,466,5407,9393,10,3779,1890,6146,0,5407,2706,6997,10,3788,8542,6149,0,4215,9393,7000,10,8542,6146,939,0,9393,6997,1154,10,3778,335,3739,0,5408,435,4166,10,8543,3739,1870,0,9394,4166,2085,10,1890,3778,8543,0,2706,5408,9394,10,6146,8543,6147,0,6997,9394,6998,10,358,3790,8544,0,462,4217,9395,10,3790,1896,6148,0,4217,2111,6999,10,3738,8544,6147,0,4165,9395,6998,10,8544,6148,939,0,9395,6999,1154,10,3791,345,3789,0,4218,449,4216,10,8545,3789,1895,0,9396,4216,2110,10,1896,3791,8545,0,2111,4218,9396,10,6148,8545,6149,0,6999,9396,7000,10,336,3792,8546,0,437,4219,9397,10,3792,1897,6150,0,4219,2112,7001,10,3748,8546,6153,0,4175,9397,7004,10,8546,6150,940,0,9397,7001,1155,10,3793,355,3794,0,4220,459,4221,10,8547,3794,1898,0,9398,4221,2113,10,1897,3793,8547,0,2112,4220,9398,10,6150,8547,6151,0,7001,9398,7002,10,345,3791,8548,0,449,4218,9399,10,3791,1896,6152,0,4218,2111,7003,10,3795,8548,6151,0,4222,9399,7002,10,8548,6152,940,0,9399,7003,1155,10,3790,358,3749,0,4217,462,4176,10,8549,3749,1875,0,9400,4176,2090,10,1896,3790,8549,0,2111,4217,9400,10,6152,8549,6153,0,7003,9400,7004,10,355,3813,8550,0,459,5417,9401,10,3813,1907,6154,0,5417,2711,7005,10,3794,8550,6157,0,4221,9401,7008,10,8550,6154,941,0,9401,7005,1156,10,3812,152,2931,0,5418,219,3358,10,8551,2931,1466,0,9402,3358,1681,10,1907,3812,8551,0,2711,5418,9402,10,6154,8551,6155,0,7005,9402,7006,10,153,3814,8552,0,220,4241,9403,10,3814,1908,6156,0,4241,2123,7007,10,2930,8552,6155,0,3357,9403,7006,10,8552,6156,941,0,9403,7007,1156,10,3815,345,3795,0,4242,449,4222,10,8553,3795,1898,0,9404,4222,2113,10,1908,3815,8553,0,2123,4242,9404,10,6156,8553,6157,0,7007,9404,7008,10,363,3796,8554,0,467,4223,9405,10,3796,1899,6158,0,4223,2114,7009,10,3825,8554,6161,0,4252,9405,7012,10,8554,6158,942,0,9405,7009,1157,10,3797,346,3823,0,4224,450,4250,10,8555,3823,1912,0,9406,4250,2127,10,1899,3797,8555,0,2114,4224,9406,10,6158,8555,6159,0,7009,9406,7010,10,286,3439,8556,0,375,3866,9407,10,3439,1720,6160,0,3866,1935,7011,10,3822,8556,6159,0,4249,9407,7010,10,8556,6160,942,0,9407,7011,1157,10,3438,209,3824,0,3865,278,4251,10,8557,3824,1913,0,9408,4251,2128,10,1720,3438,8557,0,1935,3865,9408,10,6160,8557,6161,0,7011,9408,7012,10,363,3798,8558,0,467,4225,9409,10,3798,1900,6162,0,4225,2115,7013,10,3796,8558,6165,0,4223,9409,7016,10,8558,6162,943,0,9409,7013,1158,10,3799,337,3757,0,4226,439,4184,10,8559,3757,1879,0,9410,4184,2094,10,1900,3799,8559,0,2115,4226,9410,10,6162,8559,6163,0,7013,9410,7014,10,359,3800,8560,0,463,4227,9411,10,3800,1901,6164,0,4227,2116,7015,10,3756,8560,6163,0,4183,9411,7014,10,8560,6164,943,0,9411,7015,1158,10,3801,346,3797,0,4228,450,4224,10,8561,3797,1899,0,9412,4224,2114,10,1901,3801,8561,0,2116,4228,9412,10,6164,8561,6165,0,7015,9412,7016,10,338,3787,8562,0,441,5409,9413,10,3787,1894,6166,0,5409,2707,7017,10,3764,8562,6169,0,4191,9413,7020,10,8562,6166,944,0,9413,7017,1159,10,3786,357,3802,0,5410,461,4229,10,8563,3802,1902,0,9414,4229,2117,10,1894,3786,8563,0,2707,5410,9414,10,6166,8563,6167,0,7017,9414,7018,10,346,3801,8564,0,450,4228,9415,10,3801,1901,6168,0,4228,2116,7019,10,3803,8564,6167,0,4230,9415,7018,10,8564,6168,944,0,9415,7019,1159,10,3800,359,3765,0,4227,463,4192,10,8565,3765,1883,0,9416,4192,2098,10,1901,3800,8565,0,2116,4227,9416,10,6168,8565,6169,0,7019,9416,7020,10,357,3821,8566,0,461,5423,9417,10,3821,1911,6170,0,5423,2714,7021,10,3802,8566,6173,0,4229,9417,7024,10,8566,6170,945,0,9417,7021,1160,10,3820,121,3513,0,5424,185,3940,10,8567,3513,1757,0,9418,3940,1972,10,1911,3820,8567,0,2714,5424,9418,10,6170,8567,6171,0,7021,9418,7022,10,286,3822,8568,0,375,4249,9419,10,3822,1912,6172,0,4249,2127,7023,10,3512,8568,6171,0,3939,9419,7022,10,8568,6172,945,0,9419,7023,1160,10,3823,346,3803,0,4250,450,4230,10,8569,3803,1902,0,9420,4230,2117,10,1912,3823,8569,0,2127,4250,9420,10,6172,8569,6173,0,7023,9420,7024,10,355,3804,8570,0,475,4231,9421,10,3804,1903,6174,0,4231,2118,7025,10,3813,8570,6177,0,4240,9421,7028,10,8570,6174,946,0,9421,7025,1161,10,3805,347,3811,0,4232,451,5415,10,8571,3811,1906,0,9422,5415,2710,10,1903,3805,8571,0,2118,4232,9422,10,6174,8571,6175,0,7025,9422,7026,10,210,3123,8572,0,281,3550,9423,10,3123,1562,6176,0,3550,1777,7027,10,3810,8572,6175,0,5416,9423,7026,10,8572,6176,946,0,9423,7027,1161,10,3122,152,3812,0,3549,219,4239,10,8573,3812,1907,0,9424,4239,2122,10,1562,3122,8573,0,1777,3549,9424,10,6176,8573,6177,0,7027,9424,7028,10,355,3793,8574,0,475,5411,9425,10,3793,1897,6178,0,5411,2708,7029,10,3804,8574,6181,0,4231,9425,7032,10,8574,6178,947,0,9425,7029,1162,10,3792,336,3771,0,5412,438,4198,10,8575,3771,1886,0,9426,4198,2101,10,1897,3792,8575,0,2708,5412,9426,10,6178,8575,6179,0,7029,9426,7030,10,360,3806,8576,0,464,4233,9427,10,3806,1904,6180,0,4233,2119,7031,10,3770,8576,6179,0,4197,9427,7030,10,8576,6180,947,0,9427,7031,1162,10,3807,347,3805,0,4234,451,4232,10,8577,3805,1903,0,9428,4232,2118,10,1904,3807,8577,0,2119,4234,9428,10,6180,8577,6181,0,7031,9428,7032,10,337,3799,8578,0,440,5413,9429,10,3799,1900,6182,0,5413,2709,7033,10,3776,8578,6185,0,4203,9429,7036,10,8578,6182,948,0,9429,7033,1163,10,3798,363,3808,0,5414,479,4235,10,8579,3808,1905,0,9430,4235,2120,10,1900,3798,8579,0,2709,5414,9430,10,6182,8579,6183,0,7033,9430,7034,10,347,3807,8580,0,451,4234,9431,10,3807,1904,6184,0,4234,2119,7035,10,3809,8580,6183,0,4236,9431,7034,10,8580,6184,948,0,9431,7035,1163,10,3806,360,3777,0,4233,464,4204,10,8581,3777,1889,0,9432,4204,2104,10,1904,3806,8581,0,2119,4233,9432,10,6184,8581,6185,0,7035,9432,7036,10,363,3825,8582,0,479,5425,9433,10,3825,1913,6186,0,5425,2715,7037,10,3808,8582,6189,0,4235,9433,7040,10,8582,6186,949,0,9433,7037,1164,10,3824,209,3117,0,5426,278,3544,10,8583,3117,1559,0,9434,3544,1774,10,1913,3824,8583,0,2715,5426,9434,10,6186,8583,6187,0,7037,9434,7038,10,210,3810,8584,0,279,4237,9435,10,3810,1906,6188,0,4237,2121,7039,10,3116,8584,6187,0,3543,9435,7038,10,8584,6188,949,0,9435,7039,1164,10,3811,347,3809,0,4238,451,4236,10,8585,3809,1905,0,9436,4236,2120,10,1906,3811,8585,0,2121,4238,9436,10,6188,8585,6189,0,7039,9436,7040,10,364,3826,8586,0,480,4253,9437,10,3826,1914,6190,0,4253,2129,7041,10,3842,8586,6193,0,4269,9437,7044,10,8586,6190,950,0,9437,7041,1165,10,3827,194,3159,0,4254,296,3586,10,8587,3159,1580,0,9438,3586,1795,10,1914,3827,8587,0,2129,4254,9438,10,6190,8587,6191,0,7041,9438,7042,10,218,2768,8588,0,295,3195,9439,10,2768,1385,6192,0,3195,1600,7043,10,3158,8588,6191,0,3585,9439,7042,10,8588,6192,950,0,9439,7043,1165,10,2769,365,3843,0,3196,482,4270,10,8589,3843,1922,0,9440,4270,2137,10,1385,2769,8589,0,1600,3196,9440,10,6192,8589,6193,0,7043,9440,7044,10,365,2769,8590,0,482,3196,9441,10,2769,1385,6194,0,3196,1600,7045,10,3844,8590,6197,0,4271,9441,7048,10,8590,6194,951,0,9441,7045,1166,10,2768,218,3165,0,3195,295,3592,10,8591,3165,1583,0,9442,3592,1798,10,1385,2768,8591,0,1600,3195,9442,10,6194,8591,6195,0,7045,9442,7046,10,142,2770,8592,0,209,3197,9443,10,2770,1386,6196,0,3197,1601,7047,10,3164,8592,6195,0,3591,9443,7046,10,8592,6196,951,0,9443,7047,1166,10,2771,366,3845,0,3198,483,4272,10,8593,3845,1923,0,9444,4272,2138,10,1386,2771,8593,0,1601,3198,9444,10,6196,8593,6197,0,7047,9444,7048,10,367,3832,8594,0,485,4259,9445,10,3832,1917,6198,0,4259,2132,7049,10,3846,8594,6201,0,4273,9445,7052,10,8594,6198,952,0,9445,7049,1167,10,3833,223,3473,0,4260,301,3900,10,8595,3473,1737,0,9446,3900,1952,10,1917,3833,8595,0,2132,4260,9446,10,6198,8595,6199,0,7049,9446,7050,10,194,3827,8596,0,263,5427,9447,10,3827,1914,6200,0,5427,2716,7051,10,3472,8596,6199,0,3899,9447,7050,10,8596,6200,952,0,9447,7051,1167,10,3826,364,3847,0,5428,481,4274,10,8597,3847,1924,0,9448,4274,2139,10,1914,3826,8597,0,2716,5428,9448,10,6200,8597,6201,0,7051,9448,7052,10,368,3834,8598,0,486,4261,9449,10,3834,1918,6202,0,4261,2133,7053,10,3848,8598,6205,0,4275,9449,7056,10,8598,6202,953,0,9449,7053,1168,10,3835,224,3176,0,4262,302,3603,10,8599,3176,1589,0,9450,3603,1804,10,1918,3835,8599,0,2133,4262,9450,10,6202,8599,6203,0,7053,9450,7054,10,223,3833,8600,0,301,4260,9451,10,3833,1917,6204,0,4260,2132,7055,10,3177,8600,6203,0,3604,9451,7054,10,8600,6204,953,0,9451,7055,1168,10,3832,367,3849,0,4259,485,4276,10,8601,3849,1925,0,9452,4276,2140,10,1917,3832,8601,0,2132,4259,9452,10,6204,8601,6205,0,7055,9452,7056,10,370,3838,8602,0,490,4265,9453,10,3838,1920,6206,0,4265,2135,7057,10,3850,8602,6209,0,4277,9453,7060,10,8602,6206,954,0,9453,7057,1169,10,3839,143,3180,0,4266,210,3607,10,8603,3180,1591,0,9454,3607,1806,10,1920,3839,8603,0,2135,4266,9454,10,6206,8603,6207,0,7057,9454,7058,10,226,2776,8604,0,304,3203,9455,10,2776,1389,6208,0,3203,1604,7059,10,3181,8604,6207,0,3608,9455,7058,10,8604,6208,954,0,9455,7059,1169,10,2777,369,3851,0,3204,488,4278,10,8605,3851,1926,0,9456,4278,2141,10,1389,2777,8605,0,1604,3204,9456,10,6208,8605,6209,0,7059,9456,7060,10,366,2771,8606,0,484,5335,9457,10,2771,1386,6210,0,5335,2670,7061,10,3852,8606,6213,0,4279,9457,7064,10,8606,6210,955,0,9457,7061,1170,10,2770,142,2901,0,5336,209,3328,10,8607,2901,1451,0,9458,3328,1666,10,1386,2770,8607,0,2670,5336,9458,10,6210,8607,6211,0,7061,9458,7062,10,143,3839,8608,0,210,4266,9459,10,3839,1920,6212,0,4266,2135,7063,10,2900,8608,6211,0,3327,9459,7062,10,8608,6212,955,0,9459,7063,1170,10,3838,370,3853,0,4265,490,4280,10,8609,3853,1927,0,9460,4280,2142,10,1920,3838,8609,0,2135,4265,9460,10,6212,8609,6213,0,7063,9460,7064,10,371,3840,8610,0,491,4267,9461,10,3840,1921,6214,0,4267,2136,7065,10,3854,8610,6217,0,4281,9461,7068,10,8610,6214,956,0,9461,7065,1171,10,3841,225,3417,0,4268,303,3844,10,8611,3417,1709,0,9462,3844,1924,10,1921,3841,8611,0,2136,4268,9462,10,6214,8611,6215,0,7065,9462,7066,10,224,3835,8612,0,302,5431,9463,10,3835,1918,6216,0,5431,2718,7067,10,3416,8612,6215,0,3843,9463,7066,10,8612,6216,956,0,9463,7067,1171,10,3834,368,3855,0,5432,487,4282,10,8613,3855,1928,0,9464,4282,2143,10,1918,3834,8613,0,2718,5432,9464,10,6216,8613,6217,0,7067,9464,7068,10,369,2777,8614,0,489,5339,9465,10,2777,1389,6218,0,5339,2672,7069,10,3856,8614,6221,0,4283,9465,7072,10,8614,6218,957,0,9465,7069,1172,10,2776,226,3178,0,5340,304,3605,10,8615,3178,1590,0,9466,3605,1805,10,1389,2776,8615,0,2672,5340,9466,10,6218,8615,6219,0,7069,9466,7070,10,225,3841,8616,0,303,4268,9467,10,3841,1921,6220,0,4268,2136,7071,10,3179,8616,6219,0,3606,9467,7070,10,8616,6220,957,0,9467,7071,1172,10,3840,371,3857,0,4267,491,4284,10,8617,3857,1929,0,9468,4284,2144,10,1921,3840,8617,0,2136,4267,9468,10,6220,8617,6221,0,7071,9468,7072,10,396,3860,8618,0,533,4287,9469,10,3860,1931,6222,0,4287,2146,7073,10,3859,8618,6225,0,4286,9469,7076,10,8618,6222,958,0,9469,7073,1173,10,3861,420,4056,0,4288,573,4483,10,8619,4056,2029,0,9470,4483,2244,10,1931,3861,8619,0,2146,4288,9470,10,6222,8619,6223,0,7073,9470,7074,10,421,4042,8620,0,575,4469,9471,10,4042,2022,6224,0,4469,2237,7075,10,4057,8620,6223,0,4484,9471,7074,10,8620,6224,958,0,9471,7075,1173,10,4043,169,3858,0,4470,520,4285,10,8621,3858,1930,0,9472,4285,2145,10,2022,4043,8621,0,2237,4470,9472,10,6224,8621,6225,0,7075,9472,7076,10,423,4060,8622,0,578,4487,9473,10,4060,2031,6226,0,4487,2246,7077,10,3867,8622,6229,0,4294,9473,7080,10,8622,6226,959,0,9473,7077,1174,10,4061,424,4048,0,4488,580,4475,10,8623,4048,2025,0,9474,4475,2240,10,2031,4061,8623,0,2246,4488,9474,10,6226,8623,6227,0,7077,9474,7078,10,384,3864,8624,0,521,4291,9475,10,3864,1933,6228,0,4291,2148,7079,10,4049,8624,6227,0,4476,9475,7078,10,8624,6228,959,0,9475,7079,1174,10,3865,399,3866,0,4292,536,4293,10,8625,3866,1934,0,9476,4293,2149,10,1933,3865,8625,0,2148,4292,9476,10,6228,8625,6229,0,7079,9476,7080,10,412,4045,8626,0,569,5507,9477,10,4045,2023,6230,0,5507,2756,7081,10,3869,8626,6233,0,4296,9477,7084,10,8626,6230,960,0,9477,7081,1175,10,4044,422,4064,0,5508,577,4491,10,8627,4064,2033,0,9478,4491,2248,10,2023,4044,8627,0,2756,5508,9478,10,6230,8627,6231,0,7081,9478,7082,10,426,4052,8628,0,583,4479,9479,10,4052,2027,6232,0,4479,2242,7083,10,4065,8628,6231,0,4492,9479,7082,10,8628,6232,960,0,9479,7083,1175,10,4053,385,3868,0,4480,522,4295,10,8629,3868,1935,0,9480,4295,2150,10,2027,4053,8629,0,2242,4480,9480,10,6232,8629,6233,0,7083,9480,7084,10,373,3872,8630,0,498,4299,9481,10,3872,1937,6234,0,4299,2152,7085,10,3879,8630,6237,0,4306,9481,7088,10,8630,6234,961,0,9481,7085,1176,10,3873,397,3874,0,4300,558,4301,10,8631,3874,1938,0,9482,4301,2153,10,1937,3873,8631,0,2152,4300,9482,10,6234,8631,6235,0,7085,9482,7086,10,386,3876,8632,0,523,4303,9483,10,3876,1939,6236,0,4303,2154,7087,10,3875,8632,6235,0,4302,9483,7086,10,8632,6236,961,0,9483,7087,1176,10,3877,402,3878,0,4304,563,4305,10,8633,3878,1940,0,9484,4305,2155,10,1939,3877,8633,0,2154,4304,9484,10,6236,8633,6237,0,7087,9484,7088,10,397,3880,8634,0,558,4307,9485,10,3880,1941,6238,0,4307,2156,7089,10,3874,8634,6241,0,4301,9485,7092,10,8634,6238,962,0,9485,7089,1177,10,3881,372,3882,0,4308,499,4309,10,8635,3882,1942,0,9486,4309,2157,10,1941,3881,8635,0,2156,4308,9486,10,6238,8635,6239,0,7089,9486,7090,10,403,3884,8636,0,540,4311,9487,10,3884,1943,6240,0,4311,2158,7091,10,3883,8636,6239,0,4310,9487,7090,10,8636,6240,962,0,9487,7091,1177,10,3885,386,3875,0,4312,523,4302,10,8637,3875,1938,0,9488,4302,2153,10,1943,3885,8637,0,2158,4312,9488,10,6240,8637,6241,0,7091,9488,7092,10,374,3886,8638,0,501,4313,9489,10,3886,1944,6242,0,4313,2159,7093,10,3891,8638,6245,0,4318,9489,7096,10,8638,6242,963,0,9489,7093,1178,10,3887,400,3888,0,4314,561,4315,10,8639,3888,1945,0,9490,4315,2160,10,1944,3887,8639,0,2159,4314,9490,10,6242,8639,6243,0,7093,9490,7094,10,386,3885,8640,0,523,4312,9491,10,3885,1943,6244,0,4312,2158,7095,10,3889,8640,6243,0,4316,9491,7094,10,8640,6244,963,0,9491,7095,1178,10,3884,403,3890,0,4311,540,4317,10,8641,3890,1946,0,9492,4317,2161,10,1943,3884,8641,0,2158,4311,9492,10,6244,8641,6245,0,7095,9492,7096,10,400,3892,8642,0,561,4319,9493,10,3892,1947,6246,0,4319,2162,7097,10,3888,8642,6249,0,4315,9493,7100,10,8642,6246,964,0,9493,7097,1179,10,3893,375,3894,0,4320,500,4321,10,8643,3894,1948,0,9494,4321,2163,10,1947,3893,8643,0,2162,4320,9494,10,6246,8643,6247,0,7097,9494,7098,10,402,3877,8644,0,563,4304,9495,10,3877,1939,6248,0,4304,2154,7099,10,3895,8644,6247,0,4322,9495,7098,10,8644,6248,964,0,9495,7099,1179,10,3876,386,3889,0,4303,523,4316,10,8645,3889,1945,0,9496,4316,2160,10,1939,3876,8645,0,2154,4303,9496,10,6248,8645,6249,0,7099,9496,7100,10,372,3896,8646,0,502,4323,9497,10,3896,1949,6250,0,4323,2164,7101,10,3882,8646,6253,0,5456,9497,7104,10,8646,6250,965,0,9497,7101,1180,10,3897,404,3898,0,4324,565,4325,10,8647,3898,1950,0,9498,4325,2165,10,1949,3897,8647,0,2164,4324,9498,10,6250,8647,6251,0,7101,9498,7102,10,387,3900,8648,0,524,4327,9499,10,3900,1951,6252,0,4327,2166,7103,10,3899,8648,6251,0,4326,9499,7102,10,8648,6252,965,0,9499,7103,1180,10,3901,403,3883,0,4328,564,5455,10,8649,3883,1942,0,9500,5455,2730,10,1951,3901,8649,0,2166,4328,9500,10,6252,8649,6253,0,7103,9500,7104,10,404,3902,8650,0,565,4329,9501,10,3902,1952,6254,0,4329,2167,7105,10,3898,8650,6257,0,4325,9501,7108,10,8650,6254,966,0,9501,7105,1181,10,3903,376,3904,0,4330,505,4331,10,8651,3904,1953,0,9502,4331,2168,10,1952,3903,8651,0,2167,4330,9502,10,6254,8651,6255,0,7105,9502,7106,10,411,3906,8652,0,548,4333,9503,10,3906,1954,6256,0,4333,2169,7107,10,3905,8652,6255,0,4332,9503,7106,10,8652,6256,966,0,9503,7107,1181,10,3907,387,3899,0,4334,524,4326,10,8653,3899,1950,0,9504,4326,2165,10,1954,3907,8653,0,2169,4334,9504,10,6256,8653,6257,0,7107,9504,7108,10,379,3908,8654,0,511,4335,9505,10,3908,1955,6258,0,4335,2170,7109,10,3913,8654,6261,0,4340,9505,7112,10,8654,6258,967,0,9505,7109,1182,10,3909,401,3910,0,4336,562,4337,10,8655,3910,1956,0,9506,4337,2171,10,1955,3909,8655,0,2170,4336,9506,10,6258,8655,6259,0,7109,9506,7110,10,387,3907,8656,0,524,4334,9507,10,3907,1954,6260,0,4334,2169,7111,10,3911,8656,6259,0,4338,9507,7110,10,8656,6260,967,0,9507,7111,1182,10,3906,411,3912,0,4333,548,4339,10,8657,3912,1957,0,9508,4339,2172,10,1954,3906,8657,0,2169,4333,9508,10,6260,8657,6261,0,7111,9508,7112,10,401,3914,8658,0,562,4341,9509,10,3914,1958,6262,0,4341,2173,7113,10,3910,8658,6265,0,4337,9509,7116,10,8658,6262,968,0,9509,7113,1183,10,3915,374,3891,0,4342,503,5459,10,8659,3891,1946,0,9510,5459,2732,10,1958,3915,8659,0,2173,4342,9510,10,6262,8659,6263,0,7113,9510,7114,10,403,3901,8660,0,564,4328,9511,10,3901,1951,6264,0,4328,2166,7115,10,3890,8660,6263,0,5460,9511,7114,10,8660,6264,968,0,9511,7115,1183,10,3900,387,3911,0,4327,524,4338,10,8661,3911,1956,0,9512,4338,2171,10,1951,3900,8661,0,2166,4327,9512,10,6264,8661,6265,0,7115,9512,7116,10,376,3903,8662,0,504,5467,9513,10,3903,1952,6266,0,5467,2736,7117,10,3921,8662,6269,0,4348,9513,7120,10,8662,6266,969,0,9513,7117,1184,10,3902,404,3916,0,5468,541,4343,10,8663,3916,1959,0,9514,4343,2174,10,1952,3902,8663,0,2736,5468,9514,10,6266,8663,6267,0,7117,9514,7118,10,388,3918,8664,0,525,4345,9515,10,3918,1960,6268,0,4345,2175,7119,10,3917,8664,6267,0,4344,9515,7118,10,8664,6268,969,0,9515,7119,1184,10,3919,408,3920,0,4346,545,4347,10,8665,3920,1961,0,9516,4347,2176,10,1960,3919,8665,0,2175,4346,9516,10,6268,8665,6269,0,7119,9516,7120,10,404,3897,8666,0,541,5465,9517,10,3897,1949,6270,0,5465,2735,7121,10,3916,8666,6273,0,4343,9517,7124,10,8666,6270,970,0,9517,7121,1185,10,3896,372,3881,0,5466,492,5453,10,8667,3881,1941,0,9518,5453,2729,10,1949,3896,8667,0,2735,5466,9518,10,6270,8667,6271,0,7121,9518,7122,10,397,3922,8668,0,534,4349,9519,10,3922,1962,6272,0,4349,2177,7123,10,3880,8668,6271,0,5454,9519,7122,10,8668,6272,970,0,9519,7123,1185,10,3923,388,3917,0,4350,525,4344,10,8669,3917,1959,0,9520,4344,2174,10,1962,3923,8669,0,2177,4350,9520,10,6272,8669,6273,0,7123,9520,7124,10,373,3924,8670,0,493,4351,9521,10,3924,1963,6274,0,4351,2178,7125,10,3872,8670,6277,0,5450,9521,7128,10,8670,6274,971,0,9521,7125,1186,10,3925,398,3926,0,4352,535,4353,10,8671,3926,1964,0,9522,4353,2179,10,1963,3925,8671,0,2178,4352,9522,10,6274,8671,6275,0,7125,9522,7126,10,388,3923,8672,0,525,4350,9523,10,3923,1962,6276,0,4350,2177,7127,10,3927,8672,6275,0,4354,9523,7126,10,8672,6276,971,0,9523,7127,1186,10,3922,397,3873,0,4349,534,5449,10,8673,3873,1937,0,9524,5449,2727,10,1962,3922,8673,0,2177,4349,9524,10,6276,8673,6277,0,7127,9524,7128,10,398,3928,8674,0,535,4355,9525,10,3928,1965,6278,0,4355,2180,7129,10,3926,8674,6281,0,4353,9525,7132,10,8674,6278,972,0,9525,7129,1187,10,3929,377,3930,0,4356,506,4357,10,8675,3930,1966,0,9526,4357,2181,10,1965,3929,8675,0,2180,4356,9526,10,6278,8675,6279,0,7129,9526,7130,10,408,3919,8676,0,545,4346,9527,10,3919,1960,6280,0,4346,2175,7131,10,3931,8676,6279,0,4358,9527,7130,10,8676,6280,972,0,9527,7131,1187,10,3918,388,3927,0,4345,525,4354,10,8677,3927,1964,0,9528,4354,2179,10,1960,3918,8677,0,2175,4345,9528,10,6280,8677,6281,0,7131,9528,7132,10,378,3932,8678,0,508,4359,9529,10,3932,1967,6282,0,4359,2182,7133,10,3939,8678,6285,0,4366,9529,7136,10,8678,6282,973,0,9529,7133,1188,10,3933,406,3934,0,4360,543,4361,10,8679,3934,1968,0,9530,4361,2183,10,1967,3933,8679,0,2182,4360,9530,10,6282,8679,6283,0,7133,9530,7134,10,389,3936,8680,0,526,4363,9531,10,3936,1969,6284,0,4363,2184,7135,10,3935,8680,6283,0,4362,9531,7134,10,8680,6284,973,0,9531,7135,1188,10,3937,409,3938,0,4364,546,4365,10,8681,3938,1970,0,9532,4365,2185,10,1969,3937,8681,0,2184,4364,9532,10,6284,8681,6285,0,7135,9532,7136,10,406,3940,8682,0,543,4367,9533,10,3940,1971,6286,0,4367,2186,7137,10,3934,8682,6289,0,4361,9533,7140,10,8682,6286,974,0,9533,7137,1189,10,3941,375,3893,0,4368,495,5461,10,8683,3893,1947,0,9534,5461,2733,10,1971,3941,8683,0,2186,4368,9534,10,6286,8683,6287,0,7137,9534,7138,10,400,3942,8684,0,537,4369,9535,10,3942,1972,6288,0,4369,2187,7139,10,3892,8684,6287,0,5462,9535,7138,10,8684,6288,974,0,9535,7139,1189,10,3943,389,3935,0,4370,526,4362,10,8685,3935,1968,0,9536,4362,2183,10,1972,3943,8685,0,2187,4370,9536,10,6288,8685,6289,0,7139,9536,7140,10,374,3915,8686,0,494,5471,9537,10,3915,1958,6290,0,5471,2738,7141,10,3886,8686,6293,0,5458,9537,7144,10,8686,6290,975,0,9537,7141,1190,10,3914,401,3944,0,5472,538,4371,10,8687,3944,1973,0,9538,4371,2188,10,1958,3914,8687,0,2738,5472,9538,10,6290,8687,6291,0,7141,9538,7142,10,389,3943,8688,0,526,4370,9539,10,3943,1972,6292,0,4370,2187,7143,10,3945,8688,6291,0,4372,9539,7142,10,8688,6292,975,0,9539,7143,1190,10,3942,400,3887,0,4369,537,5457,10,8689,3887,1944,0,9540,5457,2731,10,1972,3942,8689,0,2187,4369,9540,10,6292,8689,6293,0,7143,9540,7144,10,401,3909,8690,0,538,5469,9541,10,3909,1955,6294,0,5469,2737,7145,10,3944,8690,6297,0,4371,9541,7148,10,8690,6294,976,0,9541,7145,1191,10,3908,379,3946,0,5470,510,4373,10,8691,3946,1974,0,9542,4373,2189,10,1955,3908,8691,0,2737,5470,9542,10,6294,8691,6295,0,7145,9542,7146,10,409,3937,8692,0,546,4364,9543,10,3937,1969,6296,0,4364,2184,7147,10,3947,8692,6295,0,4374,9543,7146,10,8692,6296,976,0,9543,7147,1191,10,3936,389,3945,0,4363,526,4372,10,8693,3945,1973,0,9544,4372,2188,10,1969,3936,8693,0,2184,4363,9544,10,6296,8693,6297,0,7147,9544,7148,10,377,3929,8694,0,507,5475,9545,10,3929,1965,6298,0,5475,2740,7149,10,3953,8694,6301,0,4380,9545,7152,10,8694,6298,977,0,9545,7149,1192,10,3928,398,3948,0,5476,559,4375,10,8695,3948,1975,0,9546,4375,2190,10,1965,3928,8695,0,2740,5476,9546,10,6298,8695,6299,0,7149,9546,7150,10,390,3950,8696,0,527,4377,9547,10,3950,1976,6300,0,4377,2191,7151,10,3949,8696,6299,0,4376,9547,7150,10,8696,6300,977,0,9547,7151,1192,10,3951,410,3952,0,4378,547,4379,10,8697,3952,1977,0,9548,4379,2192,10,1976,3951,8697,0,2191,4378,9548,10,6300,8697,6301,0,7151,9548,7152,10,398,3925,8698,0,559,5473,9549,10,3925,1963,6302,0,5473,2739,7153,10,3948,8698,6305,0,4375,9549,7156,10,8698,6302,978,0,9549,7153,1193,10,3924,373,3879,0,5474,496,5451,10,8699,3879,1940,0,9550,5451,2728,10,1963,3924,8699,0,2739,5474,9550,10,6302,8699,6303,0,7153,9550,7154,10,402,3954,8700,0,539,4381,9551,10,3954,1978,6304,0,4381,2193,7155,10,3878,8700,6303,0,5452,9551,7154,10,8700,6304,978,0,9551,7155,1193,10,3955,390,3949,0,4382,527,4376,10,8701,3949,1975,0,9552,4376,2190,10,1978,3955,8701,0,2193,4382,9552,10,6304,8701,6305,0,7155,9552,7156,10,375,3941,8702,0,497,5479,9553,10,3941,1971,6306,0,5479,2742,7157,10,3894,8702,6309,0,5464,9553,7160,10,8702,6306,979,0,9553,7157,1194,10,3940,406,3956,0,5480,567,4383,10,8703,3956,1979,0,9554,4383,2194,10,1971,3940,8703,0,2742,5480,9554,10,6306,8703,6307,0,7157,9554,7158,10,390,3955,8704,0,527,4382,9555,10,3955,1978,6308,0,4382,2193,7159,10,3957,8704,6307,0,4384,9555,7158,10,8704,6308,979,0,9555,7159,1194,10,3954,402,3895,0,4381,539,5463,10,8705,3895,1948,0,9556,5463,2734,10,1978,3954,8705,0,2193,4381,9556,10,6308,8705,6309,0,7159,9556,7160,10,406,3933,8706,0,567,5477,9557,10,3933,1967,6310,0,5477,2741,7161,10,3956,8706,6313,0,4383,9557,7164,10,8706,6310,980,0,9557,7161,1195,10,3932,378,3958,0,5478,509,4385,10,8707,3958,1980,0,9558,4385,2195,10,1967,3932,8707,0,2741,5478,9558,10,6310,8707,6311,0,7161,9558,7162,10,410,3951,8708,0,547,4378,9559,10,3951,1976,6312,0,4378,2191,7163,10,3959,8708,6311,0,4386,9559,7162,10,8708,6312,980,0,9559,7163,1195,10,3950,390,3957,0,4377,527,4384,10,8709,3957,1979,0,9560,4384,2194,10,1976,3950,8709,0,2191,4377,9560,10,6312,8709,6313,0,7163,9560,7164,10,376,3960,8710,0,505,4387,9561,10,3960,1981,6314,0,4387,2196,7165,10,3904,8710,6317,0,4331,9561,7168,10,8710,6314,981,0,9561,7165,1196,10,3961,414,3962,0,4388,571,4389,10,8711,3962,1982,0,9562,4389,2197,10,1981,3961,8711,0,2196,4388,9562,10,6314,8711,6315,0,7165,9562,7166,10,391,3964,8712,0,528,4391,9563,10,3964,1983,6316,0,4391,2198,7167,10,3963,8712,6315,0,4390,9563,7166,10,8712,6316,981,0,9563,7167,1196,10,3965,411,3905,0,4392,548,4332,10,8713,3905,1953,0,9564,4332,2168,10,1983,3965,8713,0,2198,4392,9564,10,6316,8713,6317,0,7167,9564,7168,10,414,3966,8714,0,571,4393,9565,10,3966,1984,6318,0,4393,2199,7169,10,3962,8714,6321,0,4389,9565,7172,10,8714,6318,982,0,9565,7169,1197,10,3967,382,3968,0,4394,517,4395,10,8715,3968,1985,0,9566,4395,2200,10,1984,3967,8715,0,2199,4394,9566,10,6318,8715,6319,0,7169,9566,7170,10,416,3970,8716,0,553,4397,9567,10,3970,1986,6320,0,4397,2201,7171,10,3969,8716,6319,0,4396,9567,7170,10,8716,6320,982,0,9567,7171,1197,10,3971,391,3963,0,4398,528,4390,10,8717,3963,1982,0,9568,4390,2197,10,1986,3971,8717,0,2201,4398,9568,10,6320,8717,6321,0,7171,9568,7172,10,381,3972,8718,0,515,4399,9569,10,3972,1987,6322,0,4399,2202,7173,10,3977,8718,6325,0,4404,9569,7176,10,8718,6322,983,0,9569,7173,1198,10,3973,407,3974,0,4400,568,4401,10,8719,3974,1988,0,9570,4401,2203,10,1987,3973,8719,0,2202,4400,9570,10,6322,8719,6323,0,7173,9570,7174,10,391,3971,8720,0,528,4398,9571,10,3971,1986,6324,0,4398,2201,7175,10,3975,8720,6323,0,4402,9571,7174,10,8720,6324,983,0,9571,7175,1198,10,3970,416,3976,0,4397,553,4403,10,8721,3976,1989,0,9572,4403,2204,10,1986,3970,8721,0,2201,4397,9572,10,6324,8721,6325,0,7175,9572,7176,10,407,3978,8722,0,568,4405,9573,10,3978,1990,6326,0,4405,2205,7177,10,3974,8722,6329,0,4401,9573,7180,10,8722,6326,984,0,9573,7177,1199,10,3979,379,3913,0,4406,511,4340,10,8723,3913,1957,0,9574,4340,2172,10,1990,3979,8723,0,2205,4406,9574,10,6326,8723,6327,0,7177,9574,7178,10,411,3965,8724,0,548,4392,9575,10,3965,1983,6328,0,4392,2198,7179,10,3912,8724,6327,0,4339,9575,7178,10,8724,6328,984,0,9575,7179,1199,10,3964,391,3975,0,4391,528,4402,10,8725,3975,1988,0,9576,4402,2203,10,1983,3964,8725,0,2198,4391,9576,10,6328,8725,6329,0,7179,9576,7180,10,380,3984,8726,0,512,4411,9577,10,3984,1993,6330,0,4411,2208,7181,10,3987,8726,6333,0,4414,9577,7184,10,8726,6330,985,0,9577,7181,1200,10,3985,429,4088,0,4412,586,4515,10,8727,4088,2045,0,9578,4515,2260,10,1993,3985,8727,0,2208,4412,9578,10,6330,8727,6331,0,7181,9578,7182,10,428,3983,8728,0,585,4410,9579,10,3983,1992,6332,0,4410,2207,7183,10,4089,8728,6331,0,4516,9579,7182,10,8728,6332,985,0,9579,7183,1200,10,3982,417,3986,0,4409,554,4413,10,8729,3986,1994,0,9580,4413,2209,10,1992,3982,8729,0,2207,4409,9580,10,6332,8729,6333,0,7183,9580,7184,10,381,3992,8730,0,514,4419,9581,10,3992,1997,6334,0,4419,2212,7185,10,3995,8730,6337,0,4422,9581,7188,10,8730,6334,986,0,9581,7185,1201,10,3993,431,4090,0,4420,589,4517,10,8731,4090,2046,0,9582,4517,2261,10,1997,3993,8731,0,2212,4420,9582,10,6334,8731,6335,0,7185,9582,7186,10,430,3991,8732,0,588,4418,9583,10,3991,1996,6336,0,4418,2211,7187,10,4091,8732,6335,0,4518,9583,7186,10,8732,6336,986,0,9583,7187,1201,10,3990,418,3994,0,4417,555,4421,10,8733,3994,1998,0,9584,4421,2213,10,1996,3990,8733,0,2211,4417,9584,10,6336,8733,6337,0,7187,9584,7188,10,383,4085,8734,0,519,5519,9585,10,4085,2043,6338,0,5519,2762,7189,10,4001,8734,6341,0,4428,9585,7192,10,8734,6338,987,0,9585,7189,1202,10,4084,434,4092,0,5520,595,4519,10,8735,4092,2047,0,9586,4519,2262,10,2043,4084,8735,0,2762,5520,9586,10,6338,8735,6339,0,7189,9586,7190,10,432,3999,8736,0,591,4426,9587,10,3999,2000,6340,0,4426,2215,7191,10,4093,8736,6339,0,4520,9587,7190,10,8736,6340,987,0,9587,7191,1202,10,3998,419,4000,0,4425,556,4427,10,8737,4000,2001,0,9588,4427,2216,10,2000,3998,8737,0,2215,4425,9588,10,6340,8737,6341,0,7191,9588,7192,10,413,4051,8738,0,570,5511,9589,10,4051,2026,6342,0,5511,2758,7193,10,4007,8738,6345,0,4434,9589,7196,10,8738,6342,988,0,9589,7193,1203,10,4050,425,4070,0,5512,582,4497,10,8739,4070,2036,0,9590,4497,2251,10,2026,4050,8739,0,2758,5512,9590,10,6342,8739,6343,0,7193,9590,7194,10,427,4005,8740,0,584,4432,9591,10,4005,2003,6344,0,4432,2218,7195,10,4071,8740,6343,0,4498,9591,7194,10,8740,6344,988,0,9591,7195,1203,10,4004,392,4006,0,4431,529,4433,10,8741,4006,2004,0,9592,4433,2219,10,2003,4004,8741,0,2218,4431,9592,10,6344,8741,6345,0,7195,9592,7196,10,382,4083,8742,0,517,5517,9593,10,4083,2042,6346,0,5517,2761,7197,10,3968,8742,6349,0,4395,9593,7200,10,8742,6346,989,0,9593,7197,1204,10,4082,433,4094,0,5518,593,4521,10,8743,4094,2048,0,9594,4521,2263,10,2042,4082,8743,0,2761,5518,9594,10,6346,8743,6347,0,7197,9594,7198,10,435,4086,8744,0,596,4513,9595,10,4086,2044,6348,0,4513,2259,7199,10,4095,8744,6347,0,4522,9595,7198,10,8744,6348,989,0,9595,7199,1204,10,4087,416,3969,0,4514,553,4396,10,8745,3969,1985,0,9596,4396,2200,10,2044,4087,8745,0,2259,4514,9596,10,6348,8745,6349,0,7199,9596,7200,10,382,3967,8746,0,516,5483,9597,10,3967,1984,6350,0,5483,2744,7201,10,3980,8746,6353,0,4407,9597,7204,10,8746,6350,990,0,9597,7201,1205,10,3966,414,4008,0,5484,551,4435,10,8747,4008,2005,0,9598,4435,2220,10,1984,3966,8747,0,2744,5484,9598,10,6350,8747,6351,0,7201,9598,7202,10,393,4010,8748,0,530,4437,9599,10,4010,2006,6352,0,4437,2221,7203,10,4009,8748,6351,0,4436,9599,7202,10,8748,6352,990,0,9599,7203,1205,10,4011,417,3981,0,4438,554,4408,10,8749,3981,1991,0,9600,4408,2206,10,2006,4011,8749,0,2221,4438,9600,10,6352,8749,6353,0,7203,9600,7204,10,414,3961,8750,0,551,5481,9601,10,3961,1981,6354,0,5481,2743,7205,10,4008,8750,6357,0,4435,9601,7208,10,8750,6354,991,0,9601,7205,1206,10,3960,376,3921,0,5482,504,4348,10,8751,3921,1961,0,9602,4348,2176,10,1981,3960,8751,0,2743,5482,9602,10,6354,8751,6355,0,7205,9602,7206,10,408,4012,8752,0,545,4439,9603,10,4012,2007,6356,0,4439,2222,7207,10,3920,8752,6355,0,4347,9603,7206,10,8752,6356,991,0,9603,7207,1206,10,4013,393,4009,0,4440,530,4436,10,8753,4009,2005,0,9604,4436,2220,10,2007,4013,8753,0,2222,4440,9604,10,6356,8753,6357,0,7207,9604,7208,10,377,4014,8754,0,506,4441,9605,10,4014,2008,6358,0,4441,2223,7209,10,3930,8754,6361,0,4357,9605,7212,10,8754,6358,992,0,9605,7209,1207,10,4015,405,4016,0,4442,542,4443,10,8755,4016,2009,0,9606,4443,2224,10,2008,4015,8755,0,2223,4442,9606,10,6358,8755,6359,0,7209,9606,7210,10,393,4013,8756,0,530,4440,9607,10,4013,2007,6360,0,4440,2222,7211,10,4017,8756,6359,0,4444,9607,7210,10,8756,6360,992,0,9607,7211,1207,10,4012,408,3931,0,4439,545,4358,10,8757,3931,1966,0,9608,4358,2181,10,2007,4012,8757,0,2222,4439,9608,10,6360,8757,6361,0,7211,9608,7212,10,405,4018,8758,0,542,4445,9609,10,4018,2010,6362,0,4445,2225,7213,10,4016,8758,6365,0,4443,9609,7216,10,8758,6362,993,0,9609,7213,1208,10,4019,380,3987,0,4446,512,4414,10,8759,3987,1994,0,9610,4414,2209,10,2010,4019,8759,0,2225,4446,9610,10,6362,8759,6363,0,7213,9610,7214,10,417,4011,8760,0,554,4438,9611,10,4011,2006,6364,0,4438,2221,7215,10,3986,8760,6363,0,4413,9611,7214,10,8760,6364,993,0,9611,7215,1208,10,4010,393,4017,0,4437,530,4444,10,8761,4017,2009,0,9612,4444,2224,10,2006,4010,8761,0,2221,4437,9612,10,6364,8761,6365,0,7215,9612,7216,10,383,4020,8762,0,518,4447,9613,10,4020,2011,6366,0,4447,2226,7217,10,3988,8762,6369,0,4415,9613,7220,10,8762,6366,994,0,9613,7217,1209,10,4021,415,4022,0,4448,552,4449,10,8763,4022,2012,0,9614,4449,2227,10,2011,4021,8763,0,2226,4448,9614,10,6366,8763,6367,0,7217,9614,7218,10,394,4024,8764,0,531,4451,9615,10,4024,2013,6368,0,4451,2228,7219,10,4023,8764,6367,0,4450,9615,7218,10,8764,6368,994,0,9615,7219,1209,10,4025,418,3989,0,4452,555,4416,10,8765,3989,1995,0,9616,4416,2210,10,2013,4025,8765,0,2228,4452,9616,10,6368,8765,6369,0,7219,9616,7220,10,415,4026,8766,0,552,4453,9617,10,4026,2014,6370,0,4453,2229,7221,10,4022,8766,6373,0,4449,9617,7224,10,8766,6370,995,0,9617,7221,1210,10,4027,378,3939,0,4454,508,4366,10,8767,3939,1970,0,9618,4366,2185,10,2014,4027,8767,0,2229,4454,9618,10,6370,8767,6371,0,7221,9618,7222,10,409,4028,8768,0,546,4455,9619,10,4028,2015,6372,0,4455,2230,7223,10,3938,8768,6371,0,4365,9619,7222,10,8768,6372,995,0,9619,7223,1210,10,4029,394,4023,0,4456,531,4450,10,8769,4023,2012,0,9620,4450,2227,10,2015,4029,8769,0,2230,4456,9620,10,6372,8769,6373,0,7223,9620,7224,10,379,3979,8770,0,510,5487,9621,10,3979,1990,6374,0,5487,2746,7225,10,3946,8770,6377,0,4373,9621,7228,10,8770,6374,996,0,9621,7225,1211,10,3978,407,4030,0,5488,544,4457,10,8771,4030,2016,0,9622,4457,2231,10,1990,3978,8771,0,2746,5488,9622,10,6374,8771,6375,0,7225,9622,7226,10,394,4029,8772,0,531,4456,9623,10,4029,2015,6376,0,4456,2230,7227,10,4031,8772,6375,0,4458,9623,7226,10,8772,6376,996,0,9623,7227,1211,10,4028,409,3947,0,4455,546,4374,10,8773,3947,1974,0,9624,4374,2189,10,2015,4028,8773,0,2230,4455,9624,10,6376,8773,6377,0,7227,9624,7228,10,407,3973,8774,0,544,5485,9625,10,3973,1987,6378,0,5485,2745,7229,10,4030,8774,6381,0,4457,9625,7232,10,8774,6378,997,0,9625,7229,1212,10,3972,381,3995,0,5486,514,4422,10,8775,3995,1998,0,9626,4422,2213,10,1987,3972,8775,0,2745,5486,9626,10,6378,8775,6379,0,7229,9626,7230,10,418,4025,8776,0,555,4452,9627,10,4025,2013,6380,0,4452,2228,7231,10,3994,8776,6379,0,4421,9627,7230,10,8776,6380,997,0,9627,7231,1212,10,4024,394,4031,0,4451,531,4458,10,8777,4031,2016,0,9628,4458,2231,10,2013,4024,8777,0,2228,4451,9628,10,6380,8777,6381,0,7231,9628,7232,10,380,4019,8778,0,513,5499,9629,10,4019,2010,6382,0,5499,2752,7233,10,3996,8778,6385,0,4423,9629,7236,10,8778,6382,998,0,9629,7233,1213,10,4018,405,4032,0,5500,566,4459,10,8779,4032,2017,0,9630,4459,2232,10,2010,4018,8779,0,2752,5500,9630,10,6382,8779,6383,0,7233,9630,7234,10,395,4034,8780,0,532,4461,9631,10,4034,2018,6384,0,4461,2233,7235,10,4033,8780,6383,0,4460,9631,7234,10,8780,6384,998,0,9631,7235,1213,10,4035,419,3997,0,4462,556,4424,10,8781,3997,1999,0,9632,4424,2214,10,2018,4035,8781,0,2233,4462,9632,10,6384,8781,6385,0,7235,9632,7236,10,405,4015,8782,0,566,5497,9633,10,4015,2008,6386,0,5497,2751,7237,10,4032,8782,6389,0,4459,9633,7240,10,8782,6386,999,0,9633,7237,1214,10,4014,377,3953,0,5498,507,4380,10,8783,3953,1977,0,9634,4380,2192,10,2008,4014,8783,0,2751,5498,9634,10,6386,8783,6387,0,7237,9634,7238,10,410,4036,8784,0,547,4463,9635,10,4036,2019,6388,0,4463,2234,7239,10,3952,8784,6387,0,4379,9635,7238,10,8784,6388,999,0,9635,7239,1214,10,4037,395,4033,0,4464,532,4460,10,8785,4033,2017,0,9636,4460,2232,10,2019,4037,8785,0,2234,4464,9636,10,6388,8785,6389,0,7239,9636,7240,10,378,4027,8786,0,509,5503,9637,10,4027,2014,6390,0,5503,2754,7241,10,3958,8786,6393,0,4385,9637,7244,10,8786,6390,1000,0,9637,7241,1215,10,4026,415,4038,0,5504,572,4465,10,8787,4038,2020,0,9638,4465,2235,10,2014,4026,8787,0,2754,5504,9638,10,6390,8787,6391,0,7241,9638,7242,10,395,4037,8788,0,532,4464,9639,10,4037,2019,6392,0,4464,2234,7243,10,4039,8788,6391,0,4466,9639,7242,10,8788,6392,1000,0,9639,7243,1215,10,4036,410,3959,0,4463,547,4386,10,8789,3959,1980,0,9640,4386,2195,10,2019,4036,8789,0,2234,4463,9640,10,6392,8789,6393,0,7243,9640,7244,10,415,4021,8790,0,572,5501,9641,10,4021,2011,6394,0,5501,2753,7245,10,4038,8790,6397,0,4465,9641,7248,10,8790,6394,1001,0,9641,7245,1216,10,4020,383,4001,0,5502,519,4428,10,8791,4001,2001,0,9642,4428,2216,10,2011,4020,8791,0,2753,5502,9642,10,6394,8791,6395,0,7245,9642,7246,10,419,4035,8792,0,556,4462,9643,10,4035,2018,6396,0,4462,2233,7247,10,4000,8792,6395,0,4427,9643,7246,10,8792,6396,1001,0,9643,7247,1216,10,4034,395,4039,0,4461,532,4466,10,8793,4039,2020,0,9644,4466,2235,10,2018,4034,8793,0,2233,4461,9644,10,6396,8793,6397,0,7247,9644,7248,10,420,4040,8794,0,573,4467,9645,10,4040,2021,6398,0,4467,2236,7249,10,4056,8794,6401,0,4483,9645,7252,10,8794,6398,1002,0,9645,7249,1217,10,4041,433,4096,0,4468,592,4523,10,8795,4096,2049,0,9646,4523,2264,10,2021,4041,8795,0,2236,4468,9646,10,6398,8795,6399,0,7249,9646,7250,10,428,4072,8796,0,585,4499,9647,10,4072,2037,6400,0,4499,2252,7251,10,4097,8796,6399,0,4524,9647,7250,10,8796,6400,1002,0,9647,7251,1217,10,4073,421,4057,0,4500,575,4484,10,8797,4057,2029,0,9648,4484,2244,10,2037,4073,8797,0,2252,4500,9648,10,6400,8797,6401,0,7251,9648,7252,10,422,4044,8798,0,576,4471,9649,10,4044,2023,6402,0,4471,2238,7253,10,4058,8798,6405,0,4485,9649,7256,10,8798,6402,1003,0,9649,7253,1218,10,4045,412,3265,0,4472,549,5361,10,8799,3265,1633,0,9650,5361,2683,10,2023,4045,8799,0,2238,4472,9650,10,6402,8799,6403,0,7253,9650,7254,10,169,4043,8800,0,520,4470,9651,10,4043,2022,6404,0,4470,2237,7255,10,3264,8800,6403,0,5362,9651,7254,10,8800,6404,1003,0,9651,7255,1218,10,4042,421,4059,0,4469,575,4486,10,8801,4059,2030,0,9652,4486,2245,10,2022,4042,8801,0,2237,4469,9652,10,6404,8801,6405,0,7255,9652,7256,10,423,4046,8802,0,578,4473,9653,10,4046,2024,6406,0,4473,2239,7257,10,4060,8802,6409,0,4487,9653,7260,10,8802,6406,1004,0,9653,7257,1219,10,4047,434,4098,0,4474,594,4525,10,8803,4098,2050,0,9654,4525,2265,10,2024,4047,8803,0,2239,4474,9654,10,6406,8803,6407,0,7257,9654,7258,10,430,4076,8804,0,588,4503,9655,10,4076,2039,6408,0,4503,2254,7259,10,4099,8804,6407,0,4526,9655,7258,10,8804,6408,1004,0,9655,7259,1219,10,4077,424,4061,0,4504,580,4488,10,8805,4061,2031,0,9656,4488,2246,10,2039,4077,8805,0,2254,4504,9656,10,6408,8805,6409,0,7259,9656,7260,10,425,4050,8806,0,581,4477,9657,10,4050,2026,6410,0,4477,2241,7261,10,4062,8806,6413,0,4489,9657,7264,10,8806,6410,1005,0,9657,7261,1220,10,4051,413,3862,0,4478,550,4289,10,8807,3862,1932,0,9658,4289,2147,10,2026,4051,8807,0,2241,4478,9658,10,6410,8807,6411,0,7261,9658,7262,10,384,4049,8808,0,521,4476,9659,10,4049,2025,6412,0,4476,2240,7263,10,3863,8808,6411,0,4290,9659,7262,10,8808,6412,1005,0,9659,7263,1220,10,4048,424,4063,0,4475,580,4490,10,8809,4063,2032,0,9660,4490,2247,10,2025,4048,8809,0,2240,4475,9660,10,6412,8809,6413,0,7263,9660,7264,10,422,4075,8810,0,577,5513,9661,10,4075,2038,6414,0,5513,2759,7265,10,4064,8810,6417,0,4491,9661,7268,10,8810,6414,1006,0,9661,7265,1221,10,4074,429,4100,0,5514,587,4527,10,8811,4100,2051,0,9662,4527,2266,10,2038,4074,8811,0,2759,5514,9662,10,6414,8811,6415,0,7265,9662,7266,10,432,4080,8812,0,591,4507,9663,10,4080,2041,6416,0,4507,2256,7267,10,4101,8812,6415,0,4528,9663,7266,10,8812,6416,1006,0,9663,7267,1221,10,4081,426,4065,0,4508,583,4492,10,8813,4065,2033,0,9664,4492,2248,10,2041,4081,8813,0,2256,4508,9664,10,6416,8813,6417,0,7267,9664,7268,10,423,3867,8814,0,579,5443,9665,10,3867,1934,6418,0,5443,2724,7269,10,4066,8814,6421,0,4493,9665,7272,10,8814,6418,1007,0,9665,7269,1222,10,3866,399,3870,0,5444,560,4297,10,8815,3870,1936,0,9666,4297,2151,10,1934,3866,8815,0,2724,5444,9666,10,6418,8815,6419,0,7269,9666,7270,10,385,4053,8816,0,522,4480,9667,10,4053,2027,6420,0,4480,2242,7271,10,3871,8816,6419,0,4298,9667,7270,10,8816,6420,1007,0,9667,7271,1222,10,4052,426,4067,0,4479,583,4494,10,8817,4067,2034,0,9668,4494,2249,10,2027,4052,8817,0,2242,4479,9668,10,6420,8817,6421,0,7271,9668,7272,10,420,3861,8818,0,574,5437,9669,10,3861,1931,6422,0,5437,2721,7273,10,4068,8818,6425,0,4495,9669,7276,10,8818,6422,1008,0,9669,7273,1223,10,3860,396,4002,0,5438,557,4429,10,8819,4002,2002,0,9670,4429,2217,10,1931,3860,8819,0,2721,5438,9670,10,6422,8819,6423,0,7273,9670,7274,10,392,4004,8820,0,529,4431,9671,10,4004,2003,6424,0,4431,2218,7275,10,4003,8820,6423,0,4430,9671,7274,10,8820,6424,1008,0,9671,7275,1223,10,4005,427,4069,0,4432,584,4496,10,8821,4069,2035,0,9672,4496,2250,10,2003,4005,8821,0,2218,4432,9672,10,6424,8821,6425,0,7275,9672,7276,10,425,4079,8822,0,582,5515,9673,10,4079,2040,6426,0,5515,2760,7277,10,4070,8822,6429,0,4497,9673,7280,10,8822,6426,1009,0,9673,7277,1224,10,4078,431,4102,0,5516,590,4529,10,8823,4102,2052,0,9674,4529,2267,10,2040,4078,8823,0,2760,5516,9674,10,6426,8823,6427,0,7277,9674,7278,10,435,4055,8824,0,596,4482,9675,10,4055,2028,6428,0,4482,2243,7279,10,4103,8824,6427,0,4530,9675,7278,10,8824,6428,1009,0,9675,7279,1224,10,4054,427,4071,0,4481,584,4498,10,8825,4071,2036,0,9676,4498,2251,10,2028,4054,8825,0,2243,4481,9676,10,6428,8825,6429,0,7279,9676,7280,10,429,4074,8826,0,586,4501,9677,10,4074,2038,6430,0,4501,2253,7281,10,4088,8826,6433,0,4515,9677,7284,10,8826,6430,1010,0,9677,7281,1225,10,4075,422,4058,0,4502,576,4485,10,8827,4058,2030,0,9678,4485,2245,10,2038,4075,8827,0,2253,4502,9678,10,6430,8827,6431,0,7281,9678,7282,10,421,4073,8828,0,575,4500,9679,10,4073,2037,6432,0,4500,2252,7283,10,4059,8828,6431,0,4486,9679,7282,10,8828,6432,1010,0,9679,7283,1225,10,4072,428,4089,0,4499,585,4516,10,8829,4089,2045,0,9680,4516,2260,10,2037,4072,8829,0,2252,4499,9680,10,6432,8829,6433,0,7283,9680,7284,10,431,4078,8830,0,589,4505,9681,10,4078,2040,6434,0,4505,2255,7285,10,4090,8830,6437,0,4517,9681,7288,10,8830,6434,1011,0,9681,7285,1226,10,4079,425,4062,0,4506,581,4489,10,8831,4062,2032,0,9682,4489,2247,10,2040,4079,8831,0,2255,4506,9682,10,6434,8831,6435,0,7285,9682,7286,10,424,4077,8832,0,580,4504,9683,10,4077,2039,6436,0,4504,2254,7287,10,4063,8832,6435,0,4490,9683,7286,10,8832,6436,1011,0,9683,7287,1226,10,4076,430,4091,0,4503,588,4518,10,8833,4091,2046,0,9684,4518,2261,10,2039,4076,8833,0,2254,4503,9684,10,6436,8833,6437,0,7287,9684,7288,10,434,4047,8834,0,595,5509,9685,10,4047,2024,6438,0,5509,2757,7289,10,4092,8834,6441,0,4519,9685,7292,10,8834,6438,1012,0,9685,7289,1227,10,4046,423,4066,0,5510,579,4493,10,8835,4066,2034,0,9686,4493,2249,10,2024,4046,8835,0,2757,5510,9686,10,6438,8835,6439,0,7289,9686,7290,10,426,4081,8836,0,583,4508,9687,10,4081,2041,6440,0,4508,2256,7291,10,4067,8836,6439,0,4494,9687,7290,10,8836,6440,1012,0,9687,7291,1227,10,4080,432,4093,0,4507,591,4520,10,8837,4093,2047,0,9688,4520,2262,10,2041,4080,8837,0,2256,4507,9688,10,6440,8837,6441,0,7291,9688,7292,10,433,4041,8838,0,593,5505,9689,10,4041,2021,6442,0,5505,2755,7293,10,4094,8838,6445,0,4521,9689,7296,10,8838,6442,1013,0,9689,7293,1228,10,4040,420,4068,0,5506,574,4495,10,8839,4068,2035,0,9690,4495,2250,10,2021,4040,8839,0,2755,5506,9690,10,6442,8839,6443,0,7293,9690,7294,10,427,4054,8840,0,584,4481,9691,10,4054,2028,6444,0,4481,2243,7295,10,4069,8840,6443,0,4496,9691,7294,10,8840,6444,1013,0,9691,7295,1228,10,4055,435,4095,0,4482,596,4522,10,8841,4095,2048,0,9692,4522,2263,10,2028,4055,8841,0,2243,4482,9692,10,6444,8841,6445,0,7295,9692,7296,10,433,4082,8842,0,592,4509,9693,10,4082,2042,6446,0,4509,2257,7297,10,4096,8842,6449,0,4523,9693,7300,10,8842,6446,1014,0,9693,7297,1229,10,4083,382,3980,0,4510,516,4407,10,8843,3980,1991,0,9694,4407,2206,10,2042,4083,8843,0,2257,4510,9694,10,6446,8843,6447,0,7297,9694,7298,10,417,3982,8844,0,554,4409,9695,10,3982,1992,6448,0,4409,2207,7299,10,3981,8844,6447,0,4408,9695,7298,10,8844,6448,1014,0,9695,7299,1229,10,3983,428,4097,0,4410,585,4524,10,8845,4097,2049,0,9696,4524,2264,10,1992,3983,8845,0,2207,4410,9696,10,6448,8845,6449,0,7299,9696,7300,10,434,4084,8846,0,594,4511,9697,10,4084,2043,6450,0,4511,2258,7301,10,4098,8846,6453,0,4525,9697,7304,10,8846,6450,1015,0,9697,7301,1230,10,4085,383,3988,0,4512,518,4415,10,8847,3988,1995,0,9698,4415,2210,10,2043,4085,8847,0,2258,4512,9698,10,6450,8847,6451,0,7301,9698,7302,10,418,3990,8848,0,555,4417,9699,10,3990,1996,6452,0,4417,2211,7303,10,3989,8848,6451,0,4416,9699,7302,10,8848,6452,1015,0,9699,7303,1230,10,3991,430,4099,0,4418,588,4526,10,8849,4099,2050,0,9700,4526,2265,10,1996,3991,8849,0,2211,4418,9700,10,6452,8849,6453,0,7303,9700,7304,10,429,3985,8850,0,587,5489,9701,10,3985,1993,6454,0,5489,2747,7305,10,4100,8850,6457,0,4527,9701,7308,10,8850,6454,1016,0,9701,7305,1231,10,3984,380,3996,0,5490,513,4423,10,8851,3996,1999,0,9702,4423,2214,10,1993,3984,8851,0,2747,5490,9702,10,6454,8851,6455,0,7305,9702,7306,10,419,3998,8852,0,556,4425,9703,10,3998,2000,6456,0,4425,2215,7307,10,3997,8852,6455,0,4424,9703,7306,10,8852,6456,1016,0,9703,7307,1231,10,3999,432,4101,0,4426,591,4528,10,8853,4101,2051,0,9704,4528,2266,10,2000,3999,8853,0,2215,4426,9704,10,6456,8853,6457,0,7307,9704,7308,10,431,3993,8854,0,590,5491,9705,10,3993,1997,6458,0,5491,2748,7309,10,4102,8854,6461,0,4529,9705,7312,10,8854,6458,1017,0,9705,7309,1232,10,3992,381,3977,0,5492,515,4404,10,8855,3977,1989,0,9706,4404,2204,10,1997,3992,8855,0,2748,5492,9706,10,6458,8855,6459,0,7309,9706,7310,10,416,4087,8856,0,553,4514,9707,10,4087,2044,6460,0,4514,2259,7311,10,3976,8856,6459,0,4403,9707,7310,10,8856,6460,1017,0,9707,7311,1232,10,4086,435,4103,0,4513,596,4530,10,8857,4103,2052,0,9708,4530,2267,10,2044,4086,8857,0,2259,4513,9708,10,6460,8857,6461,0,7311,9708,7312,10,437,4104,8858,0,603,4531,9709,10,4104,2053,6462,0,4531,2268,7313,10,4111,8858,6465,0,4538,9709,7316,10,8858,6462,1018,0,9709,7313,1233,10,4105,461,4106,0,4532,662,4533,10,8859,4106,2054,0,9710,4533,2269,10,2053,4105,8859,0,2268,4532,9710,10,6462,8859,6463,0,7313,9710,7314,10,448,4108,8860,0,625,4535,9711,10,4108,2055,6464,0,4535,2270,7315,10,4107,8860,6463,0,4534,9711,7314,10,8860,6464,1018,0,9711,7315,1233,10,4109,465,4110,0,4536,666,4537,10,8861,4110,2056,0,9712,4537,2271,10,2055,4109,8861,0,2270,4536,9712,10,6464,8861,6465,0,7315,9712,7316,10,461,4112,8862,0,662,4539,9713,10,4112,2057,6466,0,4539,2272,7317,10,4106,8862,6469,0,4533,9713,7320,10,8862,6466,1019,0,9713,7317,1234,10,4113,436,4114,0,4540,604,4541,10,8863,4114,2058,0,9714,4541,2273,10,2057,4113,8863,0,2272,4540,9714,10,6466,8863,6467,0,7317,9714,7318,10,466,4116,8864,0,643,4543,9715,10,4116,2059,6468,0,4543,2274,7319,10,4115,8864,6467,0,4542,9715,7318,10,8864,6468,1019,0,9715,7319,1234,10,4117,448,4107,0,4544,625,4534,10,8865,4107,2054,0,9716,4534,2269,10,2059,4117,8865,0,2274,4544,9716,10,6468,8865,6469,0,7319,9716,7320,10,438,4118,8866,0,606,4545,9717,10,4118,2060,6470,0,4545,2275,7321,10,4123,8866,6473,0,4550,9717,7324,10,8866,6470,1020,0,9717,7321,1235,10,4119,463,4120,0,4546,664,4547,10,8867,4120,2061,0,9718,4547,2276,10,2060,4119,8867,0,2275,4546,9718,10,6470,8867,6471,0,7321,9718,7322,10,448,4117,8868,0,625,4544,9719,10,4117,2059,6472,0,4544,2274,7323,10,4121,8868,6471,0,4548,9719,7322,10,8868,6472,1020,0,9719,7323,1235,10,4116,466,4122,0,4543,643,4549,10,8869,4122,2062,0,9720,4549,2277,10,2059,4116,8869,0,2274,4543,9720,10,6472,8869,6473,0,7323,9720,7324,10,463,4124,8870,0,664,4551,9721,10,4124,2063,6474,0,4551,2278,7325,10,4120,8870,6477,0,4547,9721,7328,10,8870,6474,1021,0,9721,7325,1236,10,4125,439,4126,0,4552,605,4553,10,8871,4126,2064,0,9722,4553,2279,10,2063,4125,8871,0,2278,4552,9722,10,6474,8871,6475,0,7325,9722,7326,10,465,4109,8872,0,666,4536,9723,10,4109,2055,6476,0,4536,2270,7327,10,4127,8872,6475,0,4554,9723,7326,10,8872,6476,1021,0,9723,7327,1236,10,4108,448,4121,0,4535,625,4548,10,8873,4121,2061,0,9724,4548,2276,10,2055,4108,8873,0,2270,4535,9724,10,6476,8873,6477,0,7327,9724,7328,10,436,4128,8874,0,607,4555,9725,10,4128,2065,6478,0,4555,2280,7329,10,4114,8874,6481,0,5528,9725,7332,10,8874,6478,1022,0,9725,7329,1237,10,4129,467,4130,0,4556,668,4557,10,8875,4130,2066,0,9726,4557,2281,10,2065,4129,8875,0,2280,4556,9726,10,6478,8875,6479,0,7329,9726,7330,10,449,4132,8876,0,626,4559,9727,10,4132,2067,6480,0,4559,2282,7331,10,4131,8876,6479,0,4558,9727,7330,10,8876,6480,1022,0,9727,7331,1237,10,4133,466,4115,0,4560,667,5527,10,8877,4115,2058,0,9728,5527,2766,10,2067,4133,8877,0,2282,4560,9728,10,6480,8877,6481,0,7331,9728,7332,10,467,4134,8878,0,668,4561,9729,10,4134,2068,6482,0,4561,2283,7333,10,4130,8878,6485,0,4557,9729,7336,10,8878,6482,1023,0,9729,7333,1238,10,4135,440,4136,0,4562,610,4563,10,8879,4136,2069,0,9730,4563,2284,10,2068,4135,8879,0,2283,4562,9730,10,6482,8879,6483,0,7333,9730,7334,10,474,4138,8880,0,651,4565,9731,10,4138,2070,6484,0,4565,2285,7335,10,4137,8880,6483,0,4564,9731,7334,10,8880,6484,1023,0,9731,7335,1238,10,4139,449,4131,0,4566,626,4558,10,8881,4131,2066,0,9732,4558,2281,10,2070,4139,8881,0,2285,4566,9732,10,6484,8881,6485,0,7335,9732,7336,10,443,4140,8882,0,616,4567,9733,10,4140,2071,6486,0,4567,2286,7337,10,4145,8882,6489,0,4572,9733,7340,10,8882,6486,1024,0,9733,7337,1239,10,4141,464,4142,0,4568,665,4569,10,8883,4142,2072,0,9734,4569,2287,10,2071,4141,8883,0,2286,4568,9734,10,6486,8883,6487,0,7337,9734,7338,10,449,4139,8884,0,626,4566,9735,10,4139,2070,6488,0,4566,2285,7339,10,4143,8884,6487,0,4570,9735,7338,10,8884,6488,1024,0,9735,7339,1239,10,4138,474,4144,0,4565,651,4571,10,8885,4144,2073,0,9736,4571,2288,10,2070,4138,8885,0,2285,4565,9736,10,6488,8885,6489,0,7339,9736,7340,10,464,4146,8886,0,665,4573,9737,10,4146,2074,6490,0,4573,2289,7341,10,4142,8886,6493,0,4569,9737,7344,10,8886,6490,1025,0,9737,7341,1240,10,4147,438,4123,0,4574,608,5531,10,8887,4123,2062,0,9738,5531,2768,10,2074,4147,8887,0,2289,4574,9738,10,6490,8887,6491,0,7341,9738,7342,10,466,4133,8888,0,667,4560,9739,10,4133,2067,6492,0,4560,2282,7343,10,4122,8888,6491,0,5532,9739,7342,10,8888,6492,1025,0,9739,7343,1240,10,4132,449,4143,0,4559,626,4570,10,8889,4143,2072,0,9740,4570,2287,10,2067,4132,8889,0,2282,4559,9740,10,6492,8889,6493,0,7343,9740,7344,10,440,4135,8890,0,609,5539,9741,10,4135,2068,6494,0,5539,2772,7345,10,4153,8890,6497,0,4580,9741,7348,10,8890,6494,1026,0,9741,7345,1241,10,4134,467,4148,0,5540,644,4575,10,8891,4148,2075,0,9742,4575,2290,10,2068,4134,8891,0,2772,5540,9742,10,6494,8891,6495,0,7345,9742,7346,10,450,4150,8892,0,627,4577,9743,10,4150,2076,6496,0,4577,2291,7347,10,4149,8892,6495,0,4576,9743,7346,10,8892,6496,1026,0,9743,7347,1241,10,4151,471,4152,0,4578,648,4579,10,8893,4152,2077,0,9744,4579,2292,10,2076,4151,8893,0,2291,4578,9744,10,6496,8893,6497,0,7347,9744,7348,10,467,4129,8894,0,644,5537,9745,10,4129,2065,6498,0,5537,2771,7349,10,4148,8894,6501,0,4575,9745,7352,10,8894,6498,1027,0,9745,7349,1242,10,4128,436,4113,0,5538,597,5525,10,8895,4113,2057,0,9746,5525,2765,10,2065,4128,8895,0,2771,5538,9746,10,6498,8895,6499,0,7349,9746,7350,10,461,4154,8896,0,638,4581,9747,10,4154,2078,6500,0,4581,2293,7351,10,4112,8896,6499,0,5526,9747,7350,10,8896,6500,1027,0,9747,7351,1242,10,4155,450,4149,0,4582,627,4576,10,8897,4149,2075,0,9748,4576,2290,10,2078,4155,8897,0,2293,4582,9748,10,6500,8897,6501,0,7351,9748,7352,10,437,4156,8898,0,598,4583,9749,10,4156,2079,6502,0,4583,2294,7353,10,4104,8898,6505,0,5522,9749,7356,10,8898,6502,1028,0,9749,7353,1243,10,4157,462,4158,0,4584,639,4585,10,8899,4158,2080,0,9750,4585,2295,10,2079,4157,8899,0,2294,4584,9750,10,6502,8899,6503,0,7353,9750,7354,10,450,4155,8900,0,627,4582,9751,10,4155,2078,6504,0,4582,2293,7355,10,4159,8900,6503,0,4586,9751,7354,10,8900,6504,1028,0,9751,7355,1243,10,4154,461,4105,0,4581,638,5521,10,8901,4105,2053,0,9752,5521,2763,10,2078,4154,8901,0,2293,4581,9752,10,6504,8901,6505,0,7355,9752,7356,10,462,4160,8902,0,639,4587,9753,10,4160,2081,6506,0,4587,2296,7357,10,4158,8902,6509,0,4585,9753,7360,10,8902,6506,1029,0,9753,7357,1244,10,4161,441,4162,0,4588,611,4589,10,8903,4162,2082,0,9754,4589,2297,10,2081,4161,8903,0,2296,4588,9754,10,6506,8903,6507,0,7357,9754,7358,10,471,4151,8904,0,648,4578,9755,10,4151,2076,6508,0,4578,2291,7359,10,4163,8904,6507,0,4590,9755,7358,10,8904,6508,1029,0,9755,7359,1244,10,4150,450,4159,0,4577,627,4586,10,8905,4159,2080,0,9756,4586,2295,10,2076,4150,8905,0,2291,4577,9756,10,6508,8905,6509,0,7359,9756,7360,10,442,4164,8906,0,613,4591,9757,10,4164,2083,6510,0,4591,2298,7361,10,4171,8906,6513,0,4598,9757,7364,10,8906,6510,1030,0,9757,7361,1245,10,4165,469,4166,0,4592,646,4593,10,8907,4166,2084,0,9758,4593,2299,10,2083,4165,8907,0,2298,4592,9758,10,6510,8907,6511,0,7361,9758,7362,10,451,4168,8908,0,628,4595,9759,10,4168,2085,6512,0,4595,2300,7363,10,4167,8908,6511,0,4594,9759,7362,10,8908,6512,1030,0,9759,7363,1245,10,4169,472,4170,0,4596,649,4597,10,8909,4170,2086,0,9760,4597,2301,10,2085,4169,8909,0,2300,4596,9760,10,6512,8909,6513,0,7363,9760,7364,10,469,4172,8910,0,646,4599,9761,10,4172,2087,6514,0,4599,2302,7365,10,4166,8910,6517,0,4593,9761,7368,10,8910,6514,1031,0,9761,7365,1246,10,4173,439,4125,0,4600,600,5533,10,8911,4125,2063,0,9762,5533,2769,10,2087,4173,8911,0,2302,4600,9762,10,6514,8911,6515,0,7365,9762,7366,10,463,4174,8912,0,640,4601,9763,10,4174,2088,6516,0,4601,2303,7367,10,4124,8912,6515,0,5534,9763,7366,10,8912,6516,1031,0,9763,7367,1246,10,4175,451,4167,0,4602,628,4594,10,8913,4167,2084,0,9764,4594,2299,10,2088,4175,8913,0,2303,4602,9764,10,6516,8913,6517,0,7367,9764,7368,10,438,4147,8914,0,599,5543,9765,10,4147,2074,6518,0,5543,2774,7369,10,4118,8914,6521,0,5530,9765,7372,10,8914,6518,1032,0,9765,7369,1247,10,4146,464,4176,0,5544,641,4603,10,8915,4176,2089,0,9766,4603,2304,10,2074,4146,8915,0,2774,5544,9766,10,6518,8915,6519,0,7369,9766,7370,10,451,4175,8916,0,628,4602,9767,10,4175,2088,6520,0,4602,2303,7371,10,4177,8916,6519,0,4604,9767,7370,10,8916,6520,1032,0,9767,7371,1247,10,4174,463,4119,0,4601,640,5529,10,8917,4119,2060,0,9768,5529,2767,10,2088,4174,8917,0,2303,4601,9768,10,6520,8917,6521,0,7371,9768,7372,10,464,4141,8918,0,641,5541,9769,10,4141,2071,6522,0,5541,2773,7373,10,4176,8918,6525,0,4603,9769,7376,10,8918,6522,1033,0,9769,7373,1248,10,4140,443,4178,0,5542,615,4605,10,8919,4178,2090,0,9770,4605,2305,10,2071,4140,8919,0,2773,5542,9770,10,6522,8919,6523,0,7373,9770,7374,10,472,4169,8920,0,649,4596,9771,10,4169,2085,6524,0,4596,2300,7375,10,4179,8920,6523,0,4606,9771,7374,10,8920,6524,1033,0,9771,7375,1248,10,4168,451,4177,0,4595,628,4604,10,8921,4177,2089,0,9772,4604,2304,10,2085,4168,8921,0,2300,4595,9772,10,6524,8921,6525,0,7375,9772,7376,10,441,4161,8922,0,612,5547,9773,10,4161,2081,6526,0,5547,2776,7377,10,4185,8922,6529,0,4612,9773,7380,10,8922,6526,1034,0,9773,7377,1249,10,4160,462,4180,0,5548,663,4607,10,8923,4180,2091,0,9774,4607,2306,10,2081,4160,8923,0,2776,5548,9774,10,6526,8923,6527,0,7377,9774,7378,10,452,4182,8924,0,629,4609,9775,10,4182,2092,6528,0,4609,2307,7379,10,4181,8924,6527,0,4608,9775,7378,10,8924,6528,1034,0,9775,7379,1249,10,4183,473,4184,0,4610,650,4611,10,8925,4184,2093,0,9776,4611,2308,10,2092,4183,8925,0,2307,4610,9776,10,6528,8925,6529,0,7379,9776,7380,10,462,4157,8926,0,663,5545,9777,10,4157,2079,6530,0,5545,2775,7381,10,4180,8926,6533,0,4607,9777,7384,10,8926,6530,1035,0,9777,7381,1250,10,4156,437,4111,0,5546,601,5523,10,8927,4111,2056,0,9778,5523,2764,10,2079,4156,8927,0,2775,5546,9778,10,6530,8927,6531,0,7381,9778,7382,10,465,4186,8928,0,642,4613,9779,10,4186,2094,6532,0,4613,2309,7383,10,4110,8928,6531,0,5524,9779,7382,10,8928,6532,1035,0,9779,7383,1250,10,4187,452,4181,0,4614,629,4608,10,8929,4181,2091,0,9780,4608,2306,10,2094,4187,8929,0,2309,4614,9780,10,6532,8929,6533,0,7383,9780,7384,10,439,4173,8930,0,602,5551,9781,10,4173,2087,6534,0,5551,2778,7385,10,4126,8930,6537,0,5536,9781,7388,10,8930,6534,1036,0,9781,7385,1251,10,4172,469,4188,0,5552,670,4615,10,8931,4188,2095,0,9782,4615,2310,10,2087,4172,8931,0,2778,5552,9782,10,6534,8931,6535,0,7385,9782,7386,10,452,4187,8932,0,629,4614,9783,10,4187,2094,6536,0,4614,2309,7387,10,4189,8932,6535,0,4616,9783,7386,10,8932,6536,1036,0,9783,7387,1251,10,4186,465,4127,0,4613,642,5535,10,8933,4127,2064,0,9784,5535,2770,10,2094,4186,8933,0,2309,4613,9784,10,6536,8933,6537,0,7387,9784,7388,10,469,4165,8934,0,670,5549,9785,10,4165,2083,6538,0,5549,2777,7389,10,4188,8934,6541,0,4615,9785,7392,10,8934,6538,1037,0,9785,7389,1252,10,4164,442,4190,0,5550,614,4617,10,8935,4190,2096,0,9786,4617,2311,10,2083,4164,8935,0,2777,5550,9786,10,6538,8935,6539,0,7389,9786,7390,10,473,4183,8936,0,650,4610,9787,10,4183,2092,6540,0,4610,2307,7391,10,4191,8936,6539,0,4618,9787,7390,10,8936,6540,1037,0,9787,7391,1252,10,4182,452,4189,0,4609,629,4616,10,8937,4189,2095,0,9788,4616,2310,10,2092,4182,8937,0,2307,4609,9788,10,6540,8937,6541,0,7391,9788,7392,10,440,4192,8938,0,610,4619,9789,10,4192,2097,6542,0,4619,2312,7393,10,4136,8938,6545,0,4563,9789,7396,10,8938,6542,1038,0,9789,7393,1253,10,4193,479,4194,0,4620,676,4621,10,8939,4194,2098,0,9790,4621,2313,10,2097,4193,8939,0,2312,4620,9790,10,6542,8939,6543,0,7393,9790,7394,10,453,4196,8940,0,630,4623,9791,10,4196,2099,6544,0,4623,2314,7395,10,4195,8940,6543,0,4622,9791,7394,10,8940,6544,1038,0,9791,7395,1253,10,4197,474,4137,0,4624,651,4564,10,8941,4137,2069,0,9792,4564,2284,10,2099,4197,8941,0,2314,4624,9792,10,6544,8941,6545,0,7395,9792,7396,10,479,4198,8942,0,676,4625,9793,10,4198,2100,6546,0,4625,2315,7397,10,4194,8942,6549,0,4621,9793,7400,10,8942,6546,1039,0,9793,7397,1254,10,4199,446,4200,0,4626,622,4627,10,8943,4200,2101,0,9794,4627,2316,10,2100,4199,8943,0,2315,4626,9794,10,6546,8943,6547,0,7397,9794,7398,10,481,4202,8944,0,658,4629,9795,10,4202,2102,6548,0,4629,2317,7399,10,4201,8944,6547,0,4628,9795,7398,10,8944,6548,1039,0,9795,7399,1254,10,4203,453,4195,0,4630,630,4622,10,8945,4195,2098,0,9796,4622,2313,10,2102,4203,8945,0,2317,4630,9796,10,6548,8945,6549,0,7399,9796,7400,10,445,4204,8946,0,620,4631,9797,10,4204,2103,6550,0,4631,2318,7401,10,4209,8946,6553,0,4636,9797,7404,10,8946,6550,1040,0,9797,7401,1255,10,4205,470,4206,0,4632,671,4633,10,8947,4206,2104,0,9798,4633,2319,10,2103,4205,8947,0,2318,4632,9798,10,6550,8947,6551,0,7401,9798,7402,10,453,4203,8948,0,630,4630,9799,10,4203,2102,6552,0,4630,2317,7403,10,4207,8948,6551,0,4634,9799,7402,10,8948,6552,1040,0,9799,7403,1255,10,4202,481,4208,0,4629,658,4635,10,8949,4208,2105,0,9800,4635,2320,10,2102,4202,8949,0,2317,4629,9800,10,6552,8949,6553,0,7403,9800,7404,10,470,4210,8950,0,671,4637,9801,10,4210,2106,6554,0,4637,2321,7405,10,4206,8950,6557,0,4633,9801,7408,10,8950,6554,1041,0,9801,7405,1256,10,4211,443,4145,0,4638,616,4572,10,8951,4145,2073,0,9802,4572,2288,10,2106,4211,8951,0,2321,4638,9802,10,6554,8951,6555,0,7405,9802,7406,10,474,4197,8952,0,651,4624,9803,10,4197,2099,6556,0,4624,2314,7407,10,4144,8952,6555,0,4571,9803,7406,10,8952,6556,1041,0,9803,7407,1256,10,4196,453,4207,0,4623,630,4634,10,8953,4207,2104,0,9804,4634,2319,10,2099,4196,8953,0,2314,4623,9804,10,6556,8953,6557,0,7407,9804,7408,10,475,4214,8954,0,652,4641,9805,10,4214,2108,6558,0,4641,2323,7409,10,4213,8954,6561,0,4640,9805,7412,10,8954,6558,1042,0,9805,7409,1257,10,4215,501,4368,0,4642,702,4795,10,8955,4368,2185,0,9806,4795,2400,10,2108,4215,8955,0,2323,4642,9806,10,6558,8955,6559,0,7409,9806,7410,10,504,4358,8956,0,707,4785,9807,10,4358,2180,6560,0,4785,2395,7411,10,4369,8956,6559,0,4796,9807,7410,10,8956,6560,1042,0,9807,7411,1257,10,4359,454,4212,0,4786,631,4639,10,8957,4212,2107,0,9808,4639,2322,10,2180,4359,8957,0,2395,4786,9808,10,6560,8957,6561,0,7411,9808,7412,10,444,4220,8958,0,617,4647,9809,10,4220,2111,6562,0,4647,2326,7413,10,4225,8958,6565,0,4652,9809,7416,10,8958,6562,1043,0,9809,7413,1258,10,4221,494,4336,0,4648,691,4763,10,8959,4336,2169,0,9810,4763,2384,10,2111,4221,8959,0,2326,4648,9810,10,6562,8959,6563,0,7413,9810,7414,10,493,4219,8960,0,690,4646,9811,10,4219,2110,6564,0,4646,2325,7415,10,4337,8960,6563,0,4764,9811,7414,10,8960,6564,1043,0,9811,7415,1258,10,4218,482,4224,0,4645,659,4651,10,8961,4224,2113,0,9812,4651,2328,10,2110,4218,8961,0,2325,4645,9812,10,6564,8961,6565,0,7415,9812,7416,10,476,4228,8962,0,653,4655,9813,10,4228,2115,6566,0,4655,2330,7417,10,4227,8962,6569,0,4654,9813,7420,10,8962,6566,1044,0,9813,7417,1259,10,4229,502,4370,0,4656,704,4797,10,8963,4370,2186,0,9814,4797,2401,10,2115,4229,8963,0,2330,4656,9814,10,6566,8963,6567,0,7417,9814,7418,10,506,4362,8964,0,710,4789,9815,10,4362,2182,6568,0,4789,2397,7419,10,4371,8964,6567,0,4798,9815,7418,10,8964,6568,1044,0,9815,7419,1259,10,4363,455,4226,0,4790,632,4653,10,8965,4226,2114,0,9816,4653,2329,10,2182,4363,8965,0,2397,4790,9816,10,6568,8965,6569,0,7419,9816,7420,10,445,4234,8966,0,619,4661,9817,10,4234,2118,6570,0,4661,2333,7421,10,4239,8966,6573,0,4666,9817,7424,10,8966,6570,1045,0,9817,7421,1260,10,4235,496,4338,0,4662,694,4765,10,8967,4338,2170,0,9818,4765,2385,10,2118,4235,8967,0,2333,4662,9818,10,6570,8967,6571,0,7421,9818,7422,10,495,4233,8968,0,693,4660,9819,10,4233,2117,6572,0,4660,2332,7423,10,4339,8968,6571,0,4766,9819,7422,10,8968,6572,1045,0,9819,7423,1260,10,4232,483,4238,0,4659,660,4665,10,8969,4238,2120,0,9820,4665,2335,10,2117,4232,8969,0,2332,4659,9820,10,6572,8969,6573,0,7423,9820,7424,10,477,4361,8970,0,674,5597,9821,10,4361,2181,6574,0,5597,2801,7425,10,4241,8970,6577,0,4668,9821,7428,10,8970,6574,1046,0,9821,7425,1261,10,4360,505,4372,0,5598,709,4799,10,8971,4372,2187,0,9822,4799,2402,10,2181,4360,8971,0,2801,5598,9822,10,6574,8971,6575,0,7425,9822,7426,10,508,4366,8972,0,713,4793,9823,10,4366,2184,6576,0,4793,2399,7427,10,4373,8972,6575,0,4800,9823,7426,10,8972,6576,1046,0,9823,7427,1261,10,4367,456,4240,0,4794,633,4667,10,8973,4240,2121,0,9824,4667,2336,10,2184,4367,8973,0,2399,4794,9824,10,6576,8973,6577,0,7427,9824,7428,10,447,4333,8974,0,624,5591,9825,10,4333,2167,6578,0,5591,2798,7429,10,4249,8974,6581,0,4676,9825,7432,10,8974,6578,1047,0,9825,7429,1262,10,4332,499,4340,0,5592,700,4767,10,8975,4340,2171,0,9826,4767,2386,10,2167,4332,8975,0,2798,5592,9826,10,6578,8975,6579,0,7429,9826,7430,10,497,4245,8976,0,696,4672,9827,10,4245,2123,6580,0,4672,2338,7431,10,4341,8976,6579,0,4768,9827,7430,10,8976,6580,1047,0,9827,7431,1262,10,4244,484,4248,0,4671,661,4675,10,8977,4248,2125,0,9828,4675,2340,10,2123,4244,8977,0,2338,4671,9828,10,6580,8977,6581,0,7431,9828,7432,10,446,4331,8978,0,622,5589,9829,10,4331,2166,6582,0,5589,2797,7433,10,4200,8978,6585,0,4627,9829,7436,10,8978,6582,1048,0,9829,7433,1263,10,4330,498,4342,0,5590,698,4769,10,8979,4342,2172,0,9830,4769,2387,10,2166,4330,8979,0,2797,5590,9830,10,6582,8979,6583,0,7433,9830,7434,10,500,4334,8980,0,701,4761,9831,10,4334,2168,6584,0,4761,2383,7435,10,4343,8980,6583,0,4770,9831,7434,10,8980,6584,1048,0,9831,7435,1263,10,4335,481,4201,0,4762,658,4628,10,8981,4201,2101,0,9832,4628,2316,10,2168,4335,8981,0,2383,4762,9832,10,6584,8981,6585,0,7435,9832,7436,10,478,4365,8982,0,675,5599,9833,10,4365,2183,6586,0,5599,2802,7437,10,4255,8982,6589,0,4682,9833,7440,10,8982,6586,1049,0,9833,7437,1264,10,4364,507,4374,0,5600,712,4801,10,8983,4374,2188,0,9834,4801,2403,10,2183,4364,8983,0,2802,5600,9834,10,6586,8983,6587,0,7437,9834,7438,10,503,4253,8984,0,706,4680,9835,10,4253,2127,6588,0,4680,2342,7439,10,4375,8984,6587,0,4802,9835,7438,10,8984,6588,1049,0,9835,7439,1264,10,4252,457,4254,0,4679,634,4681,10,8985,4254,2128,0,9836,4681,2343,10,2127,4252,8985,0,2342,4679,9836,10,6588,8985,6589,0,7439,9836,7440,10,446,4199,8986,0,621,5555,9837,10,4199,2100,6590,0,5555,2780,7441,10,4216,8986,6593,0,4643,9837,7444,10,8986,6590,1050,0,9837,7441,1265,10,4198,479,4256,0,5556,656,4683,10,8987,4256,2129,0,9838,4683,2344,10,2100,4198,8987,0,2780,5556,9838,10,6590,8987,6591,0,7441,9838,7442,10,458,4258,8988,0,635,4685,9839,10,4258,2130,6592,0,4685,2345,7443,10,4257,8988,6591,0,4684,9839,7442,10,8988,6592,1050,0,9839,7443,1265,10,4259,482,4217,0,4686,659,4644,10,8989,4217,2109,0,9840,4644,2324,10,2130,4259,8989,0,2345,4686,9840,10,6592,8989,6593,0,7443,9840,7444,10,479,4193,8990,0,656,5553,9841,10,4193,2097,6594,0,5553,2779,7445,10,4256,8990,6597,0,4683,9841,7448,10,8990,6594,1051,0,9841,7445,1266,10,4192,440,4153,0,5554,609,4580,10,8991,4153,2077,0,9842,4580,2292,10,2097,4192,8991,0,2779,5554,9842,10,6594,8991,6595,0,7445,9842,7446,10,471,4260,8992,0,648,4687,9843,10,4260,2131,6596,0,4687,2346,7447,10,4152,8992,6595,0,4579,9843,7446,10,8992,6596,1051,0,9843,7447,1266,10,4261,458,4257,0,4688,635,4684,10,8993,4257,2129,0,9844,4684,2344,10,2131,4261,8993,0,2346,4688,9844,10,6596,8993,6597,0,7447,9844,7448,10,441,4262,8994,0,611,4689,9845,10,4262,2132,6598,0,4689,2347,7449,10,4162,8994,6601,0,4589,9845,7452,10,8994,6598,1052,0,9845,7449,1267,10,4263,468,4264,0,4690,645,4691,10,8995,4264,2133,0,9846,4691,2348,10,2132,4263,8995,0,2347,4690,9846,10,6598,8995,6599,0,7449,9846,7450,10,458,4261,8996,0,635,4688,9847,10,4261,2131,6600,0,4688,2346,7451,10,4265,8996,6599,0,4692,9847,7450,10,8996,6600,1052,0,9847,7451,1267,10,4260,471,4163,0,4687,648,4590,10,8997,4163,2082,0,9848,4590,2297,10,2131,4260,8997,0,2346,4687,9848,10,6600,8997,6601,0,7451,9848,7452,10,468,4266,8998,0,645,4693,9849,10,4266,2134,6602,0,4693,2349,7453,10,4264,8998,6605,0,4691,9849,7456,10,8998,6602,1053,0,9849,7453,1268,10,4267,444,4225,0,4694,617,4652,10,8999,4225,2113,0,9850,4652,2328,10,2134,4267,8999,0,2349,4694,9850,10,6602,8999,6603,0,7453,9850,7454,10,482,4259,9000,0,659,4686,9851,10,4259,2130,6604,0,4686,2345,7455,10,4224,9000,6603,0,4651,9851,7454,10,9000,6604,1053,0,9851,7455,1268,10,4258,458,4265,0,4685,635,4692,10,9001,4265,2133,0,9852,4692,2348,10,2130,4258,9001,0,2345,4685,9852,10,6604,9001,6605,0,7455,9852,7456,10,447,4268,9002,0,623,4695,9853,10,4268,2135,6606,0,4695,2350,7457,10,4230,9002,6609,0,4657,9853,7460,10,9002,6606,1054,0,9853,7457,1269,10,4269,480,4270,0,4696,657,4697,10,9003,4270,2136,0,9854,4697,2351,10,2135,4269,9003,0,2350,4696,9854,10,6606,9003,6607,0,7457,9854,7458,10,459,4272,9004,0,636,4699,9855,10,4272,2137,6608,0,4699,2352,7459,10,4271,9004,6607,0,4698,9855,7458,10,9004,6608,1054,0,9855,7459,1269,10,4273,483,4231,0,4700,660,4658,10,9005,4231,2116,0,9856,4658,2331,10,2137,4273,9005,0,2352,4700,9856,10,6608,9005,6609,0,7459,9856,7460,10,480,4274,9006,0,657,4701,9857,10,4274,2138,6610,0,4701,2353,7461,10,4270,9006,6613,0,4697,9857,7464,10,9006,6610,1055,0,9857,7461,1270,10,4275,442,4171,0,4702,613,4598,10,9007,4171,2086,0,9858,4598,2301,10,2138,4275,9007,0,2353,4702,9858,10,6610,9007,6611,0,7461,9858,7462,10,472,4276,9008,0,649,4703,9859,10,4276,2139,6612,0,4703,2354,7463,10,4170,9008,6611,0,4597,9859,7462,10,9008,6612,1055,0,9859,7463,1270,10,4277,459,4271,0,4704,636,4698,10,9009,4271,2136,0,9860,4698,2351,10,2139,4277,9009,0,2354,4704,9860,10,6612,9009,6613,0,7463,9860,7464,10,443,4211,9010,0,615,5559,9861,10,4211,2106,6614,0,5559,2782,7465,10,4178,9010,6617,0,4605,9861,7468,10,9010,6614,1056,0,9861,7465,1271,10,4210,470,4278,0,5560,647,4705,10,9011,4278,2140,0,9862,4705,2355,10,2106,4210,9011,0,2782,5560,9862,10,6614,9011,6615,0,7465,9862,7466,10,459,4277,9012,0,636,4704,9863,10,4277,2139,6616,0,4704,2354,7467,10,4279,9012,6615,0,4706,9863,7466,10,9012,6616,1056,0,9863,7467,1271,10,4276,472,4179,0,4703,649,4606,10,9013,4179,2090,0,9864,4606,2305,10,2139,4276,9013,0,2354,4703,9864,10,6616,9013,6617,0,7467,9864,7468,10,470,4205,9014,0,647,5557,9865,10,4205,2103,6618,0,5557,2781,7469,10,4278,9014,6621,0,4705,9865,7472,10,9014,6618,1057,0,9865,7469,1272,10,4204,445,4239,0,5558,619,4666,10,9015,4239,2120,0,9866,4666,2335,10,2103,4204,9015,0,2781,5558,9866,10,6618,9015,6619,0,7469,9866,7470,10,483,4273,9016,0,660,4700,9867,10,4273,2137,6620,0,4700,2352,7471,10,4238,9016,6619,0,4665,9867,7470,10,9016,6620,1057,0,9867,7471,1272,10,4272,459,4279,0,4699,636,4706,10,9017,4279,2140,0,9868,4706,2355,10,2137,4272,9017,0,2352,4699,9868,10,6620,9017,6621,0,7471,9868,7472,10,444,4267,9018,0,618,5571,9869,10,4267,2134,6622,0,5571,2788,7473,10,4242,9018,6625,0,4669,9869,7476,10,9018,6622,1058,0,9869,7473,1273,10,4266,468,4280,0,5572,669,4707,10,9019,4280,2141,0,9870,4707,2356,10,2134,4266,9019,0,2788,5572,9870,10,6622,9019,6623,0,7473,9870,7474,10,460,4282,9020,0,637,4709,9871,10,4282,2142,6624,0,4709,2357,7475,10,4281,9020,6623,0,4708,9871,7474,10,9020,6624,1058,0,9871,7475,1273,10,4283,484,4243,0,4710,661,4670,10,9021,4243,2122,0,9872,4670,2337,10,2142,4283,9021,0,2357,4710,9872,10,6624,9021,6625,0,7475,9872,7476,10,468,4263,9022,0,669,5569,9873,10,4263,2132,6626,0,5569,2787,7477,10,4280,9022,6629,0,4707,9873,7480,10,9022,6626,1059,0,9873,7477,1274,10,4262,441,4185,0,5570,612,4612,10,9023,4185,2093,0,9874,4612,2308,10,2132,4262,9023,0,2787,5570,9874,10,6626,9023,6627,0,7477,9874,7478,10,473,4284,9024,0,650,4711,9875,10,4284,2143,6628,0,4711,2358,7479,10,4184,9024,6627,0,4611,9875,7478,10,9024,6628,1059,0,9875,7479,1274,10,4285,460,4281,0,4712,637,4708,10,9025,4281,2141,0,9876,4708,2356,10,2143,4285,9025,0,2358,4712,9876,10,6628,9025,6629,0,7479,9876,7480,10,442,4275,9026,0,614,5575,9877,10,4275,2138,6630,0,5575,2790,7481,10,4190,9026,6633,0,4617,9877,7484,10,9026,6630,1060,0,9877,7481,1275,10,4274,480,4286,0,5576,677,4713,10,9027,4286,2144,0,9878,4713,2359,10,2138,4274,9027,0,2790,5576,9878,10,6630,9027,6631,0,7481,9878,7482,10,460,4285,9028,0,637,4712,9879,10,4285,2143,6632,0,4712,2358,7483,10,4287,9028,6631,0,4714,9879,7482,10,9028,6632,1060,0,9879,7483,1275,10,4284,473,4191,0,4711,650,4618,10,9029,4191,2096,0,9880,4618,2311,10,2143,4284,9029,0,2358,4711,9880,10,6632,9029,6633,0,7483,9880,7484,10,480,4269,9030,0,677,5573,9881,10,4269,2135,6634,0,5573,2789,7485,10,4286,9030,6637,0,4713,9881,7488,10,9030,6634,1061,0,9881,7485,1276,10,4268,447,4249,0,5574,624,4676,10,9031,4249,2125,0,9882,4676,2340,10,2135,4268,9031,0,2789,5574,9882,10,6634,9031,6635,0,7485,9882,7486,10,484,4283,9032,0,661,4710,9883,10,4283,2142,6636,0,4710,2357,7487,10,4248,9032,6635,0,4675,9883,7486,10,9032,6636,1061,0,9883,7487,1276,10,4282,460,4287,0,4709,637,4714,10,9033,4287,2144,0,9884,4714,2359,10,2142,4282,9033,0,2357,4709,9884,10,6636,9033,6637,0,7487,9884,7488,10,485,4288,9034,0,678,4715,9885,10,4288,2145,6638,0,4715,2360,7489,10,4304,9034,6641,0,4731,9885,7492,10,9034,6638,1062,0,9885,7489,1277,10,4289,498,4344,0,4716,697,4771,10,9035,4344,2173,0,9886,4771,2388,10,2145,4289,9035,0,2360,4716,9886,10,6638,9035,6639,0,7489,9886,7490,10,493,4320,9036,0,690,4747,9887,10,4320,2161,6640,0,4747,2376,7491,10,4345,9036,6639,0,4772,9887,7490,10,9036,6640,1062,0,9887,7491,1277,10,4321,486,4305,0,4748,680,4732,10,9037,4305,2153,0,9888,4732,2368,10,2161,4321,9037,0,2376,4748,9888,10,6640,9037,6641,0,7491,9888,7492,10,487,4292,9038,0,681,4719,9889,10,4292,2147,6642,0,4719,2362,7493,10,4306,9038,6645,0,4733,9889,7496,10,9038,6642,1063,0,9889,7493,1278,10,4293,505,4376,0,4720,708,4803,10,9039,4376,2189,0,9890,4803,2404,10,2147,4293,9039,0,2362,4720,9890,10,6642,9039,6643,0,7493,9890,7494,10,504,4291,9040,0,707,4718,9891,10,4291,2146,6644,0,4718,2361,7495,10,4377,9040,6643,0,4804,9891,7494,10,9040,6644,1063,0,9891,7495,1278,10,4290,486,4307,0,4717,680,4734,10,9041,4307,2154,0,9892,4734,2369,10,2146,4290,9041,0,2361,4717,9892,10,6644,9041,6645,0,7495,9892,7496,10,488,4294,9042,0,683,4721,9893,10,4294,2148,6646,0,4721,2363,7497,10,4308,9042,6649,0,4735,9893,7500,10,9042,6646,1064,0,9893,7497,1279,10,4295,499,4346,0,4722,699,4773,10,9043,4346,2174,0,9894,4773,2389,10,2148,4295,9043,0,2363,4722,9894,10,6646,9043,6647,0,7497,9894,7498,10,495,4324,9044,0,693,4751,9895,10,4324,2163,6648,0,4751,2378,7499,10,4347,9044,6647,0,4774,9895,7498,10,9044,6648,1064,0,9895,7499,1279,10,4325,489,4309,0,4752,685,4736,10,9045,4309,2155,0,9896,4736,2370,10,2163,4325,9045,0,2378,4752,9896,10,6648,9045,6649,0,7499,9896,7500,10,490,4298,9046,0,686,4725,9897,10,4298,2150,6650,0,4725,2365,7501,10,4310,9046,6653,0,4737,9897,7504,10,9046,6650,1065,0,9897,7501,1280,10,4299,507,4378,0,4726,711,4805,10,9047,4378,2190,0,9898,4805,2405,10,2150,4299,9047,0,2365,4726,9898,10,6650,9047,6651,0,7501,9898,7502,10,506,4297,9048,0,710,4724,9899,10,4297,2149,6652,0,4724,2364,7503,10,4379,9048,6651,0,4806,9899,7502,10,9048,6652,1065,0,9899,7503,1280,10,4296,489,4311,0,4723,685,4738,10,9049,4311,2156,0,9900,4738,2371,10,2149,4296,9049,0,2364,4723,9900,10,6652,9049,6653,0,7503,9900,7504,10,487,4323,9050,0,682,5585,9901,10,4323,2162,6654,0,5585,2795,7505,10,4312,9050,6657,0,4739,9901,7508,10,9050,6654,1066,0,9901,7505,1281,10,4322,494,4348,0,5586,692,4775,10,9051,4348,2175,0,9902,4775,2390,10,2162,4322,9051,0,2795,5586,9902,10,6654,9051,6655,0,7505,9902,7506,10,497,4328,9052,0,696,4755,9903,10,4328,2165,6656,0,4755,2380,7507,10,4349,9052,6655,0,4776,9903,7506,10,9052,6656,1066,0,9903,7507,1281,10,4329,491,4313,0,4756,688,4740,10,9053,4313,2157,0,9904,4740,2372,10,2165,4329,9053,0,2380,4756,9904,10,6656,9053,6657,0,7507,9904,7508,10,488,4355,9054,0,684,5595,9905,10,4355,2178,6658,0,5595,2800,7509,10,4314,9054,6661,0,4741,9905,7512,10,9054,6658,1067,0,9905,7509,1282,10,4354,502,4380,0,5596,705,4807,10,9055,4380,2191,0,9906,4807,2406,10,2178,4354,9055,0,2800,5596,9906,10,6658,9055,6659,0,7509,9906,7510,10,508,4301,9056,0,713,4728,9907,10,4301,2151,6660,0,4728,2366,7511,10,4381,9056,6659,0,4808,9907,7510,10,9056,6660,1067,0,9907,7511,1282,10,4300,491,4315,0,4727,688,4742,10,9057,4315,2158,0,9908,4742,2373,10,2151,4300,9057,0,2366,4727,9908,10,6660,9057,6661,0,7511,9908,7512,10,485,4353,9058,0,679,5593,9909,10,4353,2177,6662,0,5593,2799,7513,10,4316,9058,6665,0,4743,9909,7516,10,9058,6662,1068,0,9909,7513,1283,10,4352,501,4382,0,5594,703,4809,10,9059,4382,2192,0,9910,4809,2407,10,2177,4352,9059,0,2799,5594,9910,10,6662,9059,6663,0,7513,9910,7514,10,503,4356,9060,0,706,4783,9911,10,4356,2179,6664,0,4783,2394,7515,10,4383,9060,6663,0,4810,9911,7514,10,9060,6664,1068,0,9911,7515,1283,10,4357,492,4317,0,4784,689,4744,10,9061,4317,2159,0,9912,4744,2374,10,2179,4357,9061,0,2394,4784,9912,10,6664,9061,6665,0,7515,9912,7516,10,490,4327,9062,0,687,5587,9913,10,4327,2164,6666,0,5587,2796,7517,10,4318,9062,6669,0,4745,9913,7520,10,9062,6666,1069,0,9913,7517,1284,10,4326,496,4350,0,5588,695,4777,10,9063,4350,2176,0,9914,4777,2391,10,2164,4326,9063,0,2796,5588,9914,10,6666,9063,6667,0,7517,9914,7518,10,500,4303,9064,0,701,4730,9915,10,4303,2152,6668,0,4730,2367,7519,10,4351,9064,6667,0,4778,9915,7518,10,9064,6668,1069,0,9915,7519,1284,10,4302,492,4319,0,4729,689,4746,10,9065,4319,2160,0,9916,4746,2375,10,2152,4302,9065,0,2367,4729,9916,10,6668,9065,6669,0,7519,9916,7520,10,494,4322,9066,0,691,4749,9917,10,4322,2162,6670,0,4749,2377,7521,10,4336,9066,6673,0,4763,9917,7524,10,9066,6670,1070,0,9917,7521,1285,10,4323,487,4306,0,4750,681,4733,10,9067,4306,2154,0,9918,4733,2369,10,2162,4323,9067,0,2377,4750,9918,10,6670,9067,6671,0,7521,9918,7522,10,486,4321,9068,0,680,4748,9919,10,4321,2161,6672,0,4748,2376,7523,10,4307,9068,6671,0,4734,9919,7522,10,9068,6672,1070,0,9919,7523,1285,10,4320,493,4337,0,4747,690,4764,10,9069,4337,2169,0,9920,4764,2384,10,2161,4320,9069,0,2376,4747,9920,10,6672,9069,6673,0,7523,9920,7524,10,496,4326,9070,0,694,4753,9921,10,4326,2164,6674,0,4753,2379,7525,10,4338,9070,6677,0,4765,9921,7528,10,9070,6674,1071,0,9921,7525,1286,10,4327,490,4310,0,4754,686,4737,10,9071,4310,2156,0,9922,4737,2371,10,2164,4327,9071,0,2379,4754,9922,10,6674,9071,6675,0,7525,9922,7526,10,489,4325,9072,0,685,4752,9923,10,4325,2163,6676,0,4752,2378,7527,10,4311,9072,6675,0,4738,9923,7526,10,9072,6676,1071,0,9923,7527,1286,10,4324,495,4339,0,4751,693,4766,10,9073,4339,2170,0,9924,4766,2385,10,2163,4324,9073,0,2378,4751,9924,10,6676,9073,6677,0,7527,9924,7528,10,499,4295,9074,0,700,5581,9925,10,4295,2148,6678,0,5581,2793,7529,10,4340,9074,6681,0,4767,9925,7532,10,9074,6678,1072,0,9925,7529,1287,10,4294,488,4314,0,5582,684,4741,10,9075,4314,2158,0,9926,4741,2373,10,2148,4294,9075,0,2793,5582,9926,10,6678,9075,6679,0,7529,9926,7530,10,491,4329,9076,0,688,4756,9927,10,4329,2165,6680,0,4756,2380,7531,10,4315,9076,6679,0,4742,9927,7530,10,9076,6680,1072,0,9927,7531,1287,10,4328,497,4341,0,4755,696,4768,10,9077,4341,2171,0,9928,4768,2386,10,2165,4328,9077,0,2380,4755,9928,10,6680,9077,6681,0,7531,9928,7532,10,498,4289,9078,0,698,5577,9929,10,4289,2145,6682,0,5577,2791,7533,10,4342,9078,6685,0,4769,9929,7536,10,9078,6682,1073,0,9929,7533,1288,10,4288,485,4316,0,5578,679,4743,10,9079,4316,2159,0,9930,4743,2374,10,2145,4288,9079,0,2791,5578,9930,10,6682,9079,6683,0,7533,9930,7534,10,492,4302,9080,0,689,4729,9931,10,4302,2152,6684,0,4729,2367,7535,10,4317,9080,6683,0,4744,9931,7534,10,9080,6684,1073,0,9931,7535,1288,10,4303,500,4343,0,4730,701,4770,10,9081,4343,2172,0,9932,4770,2387,10,2152,4303,9081,0,2367,4730,9932,10,6684,9081,6685,0,7535,9932,7536,10,498,4330,9082,0,697,4757,9933,10,4330,2166,6686,0,4757,2381,7537,10,4344,9082,6689,0,4771,9933,7540,10,9082,6686,1074,0,9933,7537,1289,10,4331,446,4216,0,4758,621,4643,10,9083,4216,2109,0,9934,4643,2324,10,2166,4331,9083,0,2381,4758,9934,10,6686,9083,6687,0,7537,9934,7538,10,482,4218,9084,0,659,4645,9935,10,4218,2110,6688,0,4645,2325,7539,10,4217,9084,6687,0,4644,9935,7538,10,9084,6688,1074,0,9935,7539,1289,10,4219,493,4345,0,4646,690,4772,10,9085,4345,2173,0,9936,4772,2388,10,2110,4219,9085,0,2325,4646,9936,10,6688,9085,6689,0,7539,9936,7540,10,499,4332,9086,0,699,4759,9937,10,4332,2167,6690,0,4759,2382,7541,10,4346,9086,6693,0,4773,9937,7544,10,9086,6690,1075,0,9937,7541,1290,10,4333,447,4230,0,4760,623,4657,10,9087,4230,2116,0,9938,4657,2331,10,2167,4333,9087,0,2382,4760,9938,10,6690,9087,6691,0,7541,9938,7542,10,483,4232,9088,0,660,4659,9939,10,4232,2117,6692,0,4659,2332,7543,10,4231,9088,6691,0,4658,9939,7542,10,9088,6692,1075,0,9939,7543,1290,10,4233,495,4347,0,4660,693,4774,10,9089,4347,2174,0,9940,4774,2389,10,2117,4233,9089,0,2332,4660,9940,10,6692,9089,6693,0,7543,9940,7544,10,494,4221,9090,0,692,5563,9941,10,4221,2111,6694,0,5563,2784,7545,10,4348,9090,6697,0,4775,9941,7548,10,9090,6694,1076,0,9941,7545,1291,10,4220,444,4242,0,5564,618,4669,10,9091,4242,2122,0,9942,4669,2337,10,2111,4220,9091,0,2784,5564,9942,10,6694,9091,6695,0,7545,9942,7546,10,484,4244,9092,0,661,4671,9943,10,4244,2123,6696,0,4671,2338,7547,10,4243,9092,6695,0,4670,9943,7546,10,9092,6696,1076,0,9943,7547,1291,10,4245,497,4349,0,4672,696,4776,10,9093,4349,2175,0,9944,4776,2390,10,2123,4245,9093,0,2338,4672,9944,10,6696,9093,6697,0,7547,9944,7548,10,496,4235,9094,0,695,5567,9945,10,4235,2118,6698,0,5567,2786,7549,10,4350,9094,6701,0,4777,9945,7552,10,9094,6698,1077,0,9945,7549,1292,10,4234,445,4209,0,5568,620,4636,10,9095,4209,2105,0,9946,4636,2320,10,2118,4234,9095,0,2786,5568,9946,10,6698,9095,6699,0,7549,9946,7550,10,481,4335,9096,0,658,4762,9947,10,4335,2168,6700,0,4762,2383,7551,10,4208,9096,6699,0,4635,9947,7550,10,9096,6700,1077,0,9947,7551,1292,10,4334,500,4351,0,4761,701,4778,10,9097,4351,2176,0,9948,4778,2391,10,2168,4334,9097,0,2383,4761,9948,10,6700,9097,6701,0,7551,9948,7552,10,501,4352,9098,0,702,4779,9949,10,4352,2177,6702,0,4779,2392,7553,10,4368,9098,6705,0,4795,9949,7556,10,9098,6702,1078,0,9949,7553,1293,10,4353,485,4304,0,4780,678,4731,10,9099,4304,2153,0,9950,4731,2368,10,2177,4353,9099,0,2392,4780,9950,10,6702,9099,6703,0,7553,9950,7554,10,486,4290,9100,0,680,4717,9951,10,4290,2146,6704,0,4717,2361,7555,10,4305,9100,6703,0,4732,9951,7554,10,9100,6704,1078,0,9951,7555,1293,10,4291,504,4369,0,4718,707,4796,10,9101,4369,2185,0,9952,4796,2400,10,2146,4291,9101,0,2361,4718,9952,10,6704,9101,6705,0,7555,9952,7556,10,502,4354,9102,0,704,4781,9953,10,4354,2178,6706,0,4781,2393,7557,10,4370,9102,6709,0,4797,9953,7560,10,9102,6706,1079,0,9953,7557,1294,10,4355,488,4308,0,4782,683,4735,10,9103,4308,2155,0,9954,4735,2370,10,2178,4355,9103,0,2393,4782,9954,10,6706,9103,6707,0,7557,9954,7558,10,489,4296,9104,0,685,4723,9955,10,4296,2149,6708,0,4723,2364,7559,10,4309,9104,6707,0,4736,9955,7558,10,9104,6708,1079,0,9955,7559,1294,10,4297,506,4371,0,4724,710,4798,10,9105,4371,2186,0,9956,4798,2401,10,2149,4297,9105,0,2364,4724,9956,10,6708,9105,6709,0,7559,9956,7560,10,505,4293,9106,0,709,5579,9957,10,4293,2147,6710,0,5579,2792,7561,10,4372,9106,6713,0,4799,9957,7564,10,9106,6710,1080,0,9957,7561,1295,10,4292,487,4312,0,5580,682,4739,10,9107,4312,2157,0,9958,4739,2372,10,2147,4292,9107,0,2792,5580,9958,10,6710,9107,6711,0,7561,9958,7562,10,491,4300,9108,0,688,4727,9959,10,4300,2151,6712,0,4727,2366,7563,10,4313,9108,6711,0,4740,9959,7562,10,9108,6712,1080,0,9959,7563,1295,10,4301,508,4373,0,4728,713,4800,10,9109,4373,2187,0,9960,4800,2402,10,2151,4301,9109,0,2366,4728,9960,10,6712,9109,6713,0,7563,9960,7564,10,507,4299,9110,0,712,5583,9961,10,4299,2150,6714,0,5583,2794,7565,10,4374,9110,6717,0,4801,9961,7568,10,9110,6714,1081,0,9961,7565,1296,10,4298,490,4318,0,5584,687,4745,10,9111,4318,2160,0,9962,4745,2375,10,2150,4298,9111,0,2794,5584,9962,10,6714,9111,6715,0,7565,9962,7566,10,492,4357,9112,0,689,4784,9963,10,4357,2179,6716,0,4784,2394,7567,10,4319,9112,6715,0,4746,9963,7566,10,9112,6716,1081,0,9963,7567,1296,10,4356,503,4375,0,4783,706,4802,10,9113,4375,2188,0,9964,4802,2403,10,2179,4356,9113,0,2394,4783,9964,10,6716,9113,6717,0,7567,9964,7568,10,505,4360,9114,0,708,4787,9965,10,4360,2181,6718,0,4787,2396,7569,10,4376,9114,6721,0,4803,9965,7572,10,9114,6718,1082,0,9965,7569,1297,10,4361,477,4222,0,4788,654,4649,10,9115,4222,2112,0,9966,4649,2327,10,2181,4361,9115,0,2396,4788,9966,10,6718,9115,6719,0,7569,9966,7570,10,454,4359,9116,0,631,4786,9967,10,4359,2180,6720,0,4786,2395,7571,10,4223,9116,6719,0,4650,9967,7570,10,9116,6720,1082,0,9967,7571,1297,10,4358,504,4377,0,4785,707,4804,10,9117,4377,2189,0,9968,4804,2404,10,2180,4358,9117,0,2395,4785,9968,10,6720,9117,6721,0,7571,9968,7572,10,507,4364,9118,0,711,4791,9969,10,4364,2183,6722,0,4791,2398,7573,10,4378,9118,6725,0,4805,9969,7576,10,9118,6722,1083,0,9969,7573,1298,10,4365,478,4236,0,4792,655,4663,10,9119,4236,2119,0,9970,4663,2334,10,2183,4365,9119,0,2398,4792,9970,10,6722,9119,6723,0,7573,9970,7574,10,455,4363,9120,0,632,4790,9971,10,4363,2182,6724,0,4790,2397,7575,10,4237,9120,6723,0,4664,9971,7574,10,9120,6724,1083,0,9971,7575,1298,10,4362,506,4379,0,4789,710,4806,10,9121,4379,2190,0,9972,4806,2405,10,2182,4362,9121,0,2397,4789,9972,10,6724,9121,6725,0,7575,9972,7576,10,502,4229,9122,0,705,5565,9973,10,4229,2115,6726,0,5565,2785,7577,10,4380,9122,6729,0,4807,9973,7580,10,9122,6726,1084,0,9973,7577,1299,10,4228,476,4246,0,5566,673,4673,10,9123,4246,2124,0,9974,4673,2339,10,2115,4228,9123,0,2785,5566,9974,10,6726,9123,6727,0,7577,9974,7578,10,456,4367,9124,0,633,4794,9975,10,4367,2184,6728,0,4794,2399,7579,10,4247,9124,6727,0,4674,9975,7578,10,9124,6728,1084,0,9975,7579,1299,10,4366,508,4381,0,4793,713,4808,10,9125,4381,2191,0,9976,4808,2406,10,2184,4366,9125,0,2399,4793,9976,10,6728,9125,6729,0,7579,9976,7580,10,501,4215,9126,0,703,5561,9977,10,4215,2108,6730,0,5561,2783,7581,10,4382,9126,6733,0,4809,9977,7584,10,9126,6730,1085,0,9977,7581,1300,10,4214,475,4250,0,5562,672,4677,10,9127,4250,2126,0,9978,4677,2341,10,2108,4214,9127,0,2783,5562,9978,10,6730,9127,6731,0,7581,9978,7582,10,457,4252,9128,0,634,4679,9979,10,4252,2127,6732,0,4679,2342,7583,10,4251,9128,6731,0,4678,9979,7582,10,9128,6732,1085,0,9979,7583,1300,10,4253,503,4383,0,4680,706,4810,10,9129,4383,2192,0,9980,4810,2407,10,2127,4253,9129,0,2342,4680,9980,10,6732,9129,6733,0,7583,9980,7584,10,292,3519,9130,0,381,3946,9981,10,3519,1760,6734,0,3946,1975,7585,10,4384,9130,6737,0,4811,9981,7588,10,9130,6734,1086,0,9981,7585,1301,10,3518,214,4386,0,3945,286,4813,10,9131,4386,2194,0,9982,4813,2409,10,1760,3518,9131,0,1975,3945,9982,10,6734,9131,6735,0,7585,9982,7586,10,476,4227,9132,0,653,4654,9983,10,4227,2114,6736,0,4654,2329,7587,10,4387,9132,6735,0,4814,9983,7586,10,9132,6736,1086,0,9983,7587,1301,10,4226,455,4385,0,4653,632,4812,10,9133,4385,2193,0,9984,4812,2408,10,2114,4226,9133,0,2329,4653,9984,10,6736,9133,6737,0,7587,9984,7588,10,214,3139,9134,0,286,3566,9985,10,3139,1570,6738,0,3566,1785,7589,10,4386,9134,6741,0,5602,9985,7592,10,9134,6738,1087,0,9985,7589,1302,10,3138,215,4388,0,3565,287,4815,10,9135,4388,2195,0,9986,4815,2410,10,1570,3138,9135,0,1785,3565,9986,10,6738,9135,6739,0,7589,9986,7590,10,456,4247,9136,0,633,4674,9987,10,4247,2124,6740,0,4674,2339,7591,10,4389,9136,6739,0,4816,9987,7590,10,9136,6740,1087,0,9987,7591,1302,10,4246,476,4387,0,4673,673,5601,10,9137,4387,2194,0,9988,5601,2803,10,2124,4246,9137,0,2339,4673,9988,10,6740,9137,6741,0,7591,9988,7592,10,215,3143,9138,0,289,3570,9989,10,3143,1572,6742,0,3570,1787,7593,10,4388,9138,6745,0,5604,9989,7596,10,9138,6742,1088,0,9989,7593,1303,10,3142,200,4390,0,3569,269,4817,10,9139,4390,2196,0,9990,4817,2411,10,1572,3142,9139,0,1787,3569,9990,10,6742,9139,6743,0,7593,9990,7594,10,477,4241,9140,0,674,4668,9991,10,4241,2121,6744,0,4668,2336,7595,10,4391,9140,6743,0,4818,9991,7594,10,9140,6744,1088,0,9991,7595,1303,10,4240,456,4389,0,4667,633,5603,10,9141,4389,2195,0,9992,5603,2804,10,2121,4240,9141,0,2336,4667,9992,10,6744,9141,6745,0,7595,9992,7596,10,200,3175,9142,0,269,3602,9993,10,3175,1588,6746,0,3602,1803,7597,10,4390,9142,6749,0,5606,9993,7600,10,9142,6746,1089,0,9993,7597,1304,10,3174,222,4392,0,3601,300,4819,10,9143,4392,2197,0,9994,4819,2412,10,1588,3174,9143,0,1803,3601,9994,10,6746,9143,6747,0,7597,9994,7598,10,454,4223,9144,0,631,4650,9995,10,4223,2112,6748,0,4650,2327,7599,10,4393,9144,6747,0,4820,9995,7598,10,9144,6748,1089,0,9995,7599,1304,10,4222,477,4391,0,4649,654,5605,10,9145,4391,2196,0,9996,5605,2805,10,2112,4222,9145,0,2327,4649,9996,10,6748,9145,6749,0,7599,9996,7600,10,222,3497,9146,0,300,3924,9997,10,3497,1749,6750,0,3924,1964,7601,10,4392,9146,6753,0,4819,9997,7604,10,9146,6750,1090,0,9997,7601,1305,10,3496,211,4394,0,3923,282,4821,10,9147,4394,2198,0,9998,4821,2413,10,1749,3496,9147,0,1964,3923,9998,10,6750,9147,6751,0,7601,9998,7602,10,475,4213,9148,0,652,4640,9999,10,4213,2107,6752,0,4640,2322,7603,10,4395,9148,6751,0,4822,9999,7602,10,9148,6752,1090,0,9999,7603,1305,10,4212,454,4393,0,4639,631,4820,10,9149,4393,2197,0,10000,4820,2412,10,2107,4212,9149,0,2322,4639,10000,10,6752,9149,6753,0,7603,10000,7604,10,211,3129,9150,0,282,3556,10001,10,3129,1565,6754,0,3556,1780,7605,10,4394,9150,6757,0,5608,10001,7608,10,9150,6754,1091,0,10001,7605,1306,10,3128,208,4396,0,3555,283,4823,10,9151,4396,2199,0,10002,4823,2414,10,1565,3128,9151,0,1780,3555,10002,10,6754,9151,6755,0,7605,10002,7606,10,457,4251,9152,0,634,4678,10003,10,4251,2126,6756,0,4678,2341,7607,10,4397,9152,6755,0,4824,10003,7606,10,9152,6756,1091,0,10003,7607,1306,10,4250,475,4395,0,4677,672,5607,10,9153,4395,2198,0,10004,5607,2806,10,2126,4250,9153,0,2341,4677,10004,10,6756,9153,6757,0,7607,10004,7608,10,208,3113,9154,0,277,3540,10005,10,3113,1557,6758,0,3540,1772,7609,10,4396,9154,6761,0,5610,10005,7612,10,9154,6758,1092,0,10005,7609,1307,10,3112,176,4398,0,3539,245,4825,10,9155,4398,2200,0,10006,4825,2415,10,1557,3112,9155,0,1772,3539,10006,10,6758,9155,6759,0,7609,10006,7610,10,478,4255,9156,0,675,4682,10007,10,4255,2128,6760,0,4682,2343,7611,10,4399,9156,6759,0,4826,10007,7610,10,9156,6760,1092,0,10007,7611,1307,10,4254,457,4397,0,4681,634,5609,10,9157,4397,2199,0,10008,5609,2807,10,2128,4254,9157,0,2343,4681,10008,10,6760,9157,6761,0,7611,10008,7612,10,176,3515,9158,0,245,3942,10009,10,3515,1758,6762,0,3942,1973,7613,10,4398,9158,6765,0,5612,10009,7616,10,9158,6762,1093,0,10009,7613,1308,10,3514,292,4384,0,3941,381,4811,10,9159,4384,2193,0,10010,4811,2408,10,1758,3514,9159,0,1973,3941,10010,10,6762,9159,6763,0,7613,10010,7614,10,455,4237,9160,0,632,4664,10011,10,4237,2119,6764,0,4664,2334,7615,10,4385,9160,6763,0,4812,10011,7614,10,9160,6764,1093,0,10011,7615,1308,10,4236,478,4399,0,4663,655,5611,10,9161,4399,2200,0,10012,5611,2808,10,2119,4236,9161,0,2334,4663,10012,10,6764,9161,6765,0,7615,10012,7616,10,40,2521,9162,0,56,2948,10013,10,2521,1261,6766,0,2948,1476,7617,10,4400,9162,6769,0,5614,10013,7620,10,9162,6766,1094,0,10013,7617,1309,10,2520,19,4402,0,2947,35,4829,10,9163,4402,2202,0,10014,4829,2417,10,1261,2520,9163,0,1476,2947,10014,10,6766,9163,6767,0,7617,10014,7618,10,510,4432,9164,0,716,4859,10015,10,4432,2217,6768,0,4859,2432,7619,10,4403,9164,6767,0,4830,10015,7618,10,9164,6768,1094,0,10015,7619,1309,10,4433,509,4401,0,4860,715,5613,10,9165,4401,2201,0,10016,5613,2809,10,2217,4433,9165,0,2432,4860,10016,10,6768,9165,6769,0,7619,10016,7620,10,19,2531,9166,0,35,2958,10017,10,2531,1266,6770,0,2958,1481,7621,10,4402,9166,6773,0,4829,10017,7624,10,9166,6770,1095,0,10017,7621,1310,10,2530,42,4404,0,2957,58,4831,10,9167,4404,2203,0,10018,4831,2418,10,1266,2530,9167,0,1481,2957,10018,10,6770,9167,6771,0,7621,10018,7622,10,511,4434,9168,0,717,4861,10019,10,4434,2218,6772,0,4861,2433,7623,10,4405,9168,6771,0,4832,10019,7622,10,9168,6772,1095,0,10019,7623,1310,10,4435,510,4403,0,4862,716,4830,10,9169,4403,2202,0,10020,4830,2417,10,2218,4435,9169,0,2433,4862,10020,10,6772,9169,6773,0,7623,10020,7624,10,42,2549,9170,0,78,2976,10021,10,2549,1275,6774,0,2976,1490,7625,10,4404,9170,6777,0,5616,10021,7628,10,9170,6774,1096,0,10021,7625,1311,10,2548,21,4406,0,2975,37,4833,10,9171,4406,2204,0,10022,4833,2419,10,1275,2548,9171,0,1490,2975,10022,10,6774,9171,6775,0,7625,10022,7626,10,512,4436,9172,0,719,4863,10023,10,4436,2219,6776,0,4863,2434,7627,10,4407,9172,6775,0,4834,10023,7626,10,9172,6776,1096,0,10023,7627,1311,10,4437,511,4405,0,4864,718,5615,10,9173,4405,2203,0,10024,5615,2810,10,2219,4437,9173,0,2434,4864,10024,10,6776,9173,6777,0,7627,10024,7628,10,21,2545,9174,0,37,2972,10025,10,2545,1273,6778,0,2972,1488,7629,10,4406,9174,6781,0,5618,10025,7632,10,9174,6778,1097,0,10025,7629,1312,10,2544,39,4408,0,2971,75,4835,10,9175,4408,2205,0,10026,4835,2420,10,1273,2544,9175,0,1488,2971,10026,10,6778,9175,6779,0,7629,10026,7630,10,513,4438,9176,0,721,4865,10027,10,4438,2220,6780,0,4865,2435,7631,10,4409,9176,6779,0,4836,10027,7630,10,9176,6780,1097,0,10027,7631,1312,10,4439,512,4407,0,4866,720,5617,10,9177,4407,2204,0,10028,5617,2811,10,2220,4439,9177,0,2435,4866,10028,10,6780,9177,6781,0,7631,10028,7632,10,39,2507,9178,0,55,2934,10029,10,2507,1254,6782,0,2934,1469,7633,10,4408,9178,6785,0,5620,10029,7636,10,9178,6782,1098,0,10029,7633,1313,10,2506,18,4410,0,2933,34,4837,10,9179,4410,2206,0,10030,4837,2421,10,1254,2506,9179,0,1469,2933,10030,10,6782,9179,6783,0,7633,10030,7634,10,514,4440,9180,0,723,4867,10031,10,4440,2221,6784,0,4867,2436,7635,10,4411,9180,6783,0,4838,10031,7634,10,9180,6784,1098,0,10031,7635,1313,10,4441,513,4409,0,4868,722,5619,10,9181,4409,2205,0,10032,5619,2812,10,2221,4441,9181,0,2436,4868,10032,10,6784,9181,6785,0,7635,10032,7636,10,18,2517,9182,0,34,2944,10033,10,2517,1259,6786,0,2944,1474,7637,10,4410,9182,6789,0,4837,10033,7640,10,9182,6786,1099,0,10033,7637,1314,10,2516,41,4412,0,2943,57,4839,10,9183,4412,2207,0,10034,4839,2422,10,1259,2516,9183,0,1474,2943,10034,10,6786,9183,6787,0,7637,10034,7638,10,515,4442,9184,0,724,4869,10035,10,4442,2222,6788,0,4869,2437,7639,10,4413,9184,6787,0,4840,10035,7638,10,9184,6788,1099,0,10035,7639,1314,10,4443,514,4411,0,4870,723,4838,10,9185,4411,2206,0,10036,4838,2421,10,2222,4443,9185,0,2437,4870,10036,10,6788,9185,6789,0,7639,10036,7640,10,41,2535,9186,0,77,2962,10037,10,2535,1268,6790,0,2962,1483,7641,10,4412,9186,6793,0,5622,10037,7644,10,9186,6790,1100,0,10037,7641,1315,10,2534,20,4414,0,2961,36,4841,10,9187,4414,2208,0,10038,4841,2423,10,1268,2534,9187,0,1483,2961,10038,10,6790,9187,6791,0,7641,10038,7642,10,516,4444,9188,0,726,4871,10039,10,4444,2223,6792,0,4871,2438,7643,10,4415,9188,6791,0,4842,10039,7642,10,9188,6792,1100,0,10039,7643,1315,10,4445,515,4413,0,4872,725,5621,10,9189,4413,2207,0,10040,5621,2813,10,2223,4445,9189,0,2438,4872,10040,10,6792,9189,6793,0,7643,10040,7644,10,20,2541,9190,0,36,2968,10041,10,2541,1271,6794,0,2968,1486,7645,10,4414,9190,6797,0,4841,10041,7648,10,9190,6794,1101,0,10041,7645,1316,10,2540,40,4400,0,2967,76,4827,10,9191,4400,2201,0,10042,4827,2416,10,1271,2540,9191,0,1486,2967,10042,10,6794,9191,6795,0,7645,10042,7646,10,509,4446,9192,0,714,4873,10043,10,4446,2224,6796,0,4873,2439,7647,10,4401,9192,6795,0,4828,10043,7646,10,9192,6796,1101,0,10043,7647,1316,10,4447,516,4415,0,4874,726,4842,10,9193,4415,2208,0,10044,4842,2423,10,2224,4447,9193,0,2439,4874,10044,10,6796,9193,6797,0,7647,10044,7648,10,510,4418,9194,0,716,4845,10045,10,4418,2210,6798,0,4845,2425,7649,10,4432,9194,6801,0,4859,10045,7652,10,9194,6798,1102,0,10045,7649,1317,10,4419,221,3511,0,4846,299,3938,10,9195,3511,1756,0,10046,3938,1971,10,2210,4419,9195,0,2425,4846,10046,10,6798,9195,6799,0,7649,10046,7650,10,220,4417,9196,0,298,5623,10047,10,4417,2209,6800,0,5623,2814,7651,10,3510,9196,6799,0,3937,10047,7650,10,9196,6800,1102,0,10047,7651,1317,10,4416,509,4433,0,5624,715,4860,10,9197,4433,2217,0,10048,4860,2432,10,2209,4416,9197,0,2814,5624,10048,10,6800,9197,6801,0,7651,10048,7652,10,511,4420,9198,0,717,4847,10049,10,4420,2211,6802,0,4847,2426,7653,10,4434,9198,6805,0,4861,10049,7656,10,9198,6802,1103,0,10049,7653,1318,10,4421,188,3171,0,4848,257,3598,10,9199,3171,1586,0,10050,3598,1801,10,2211,4421,9199,0,2426,4848,10050,10,6802,9199,6803,0,7653,10050,7654,10,221,4419,9200,0,299,4846,10051,10,4419,2210,6804,0,4846,2425,7655,10,3170,9200,6803,0,3597,10051,7654,10,9200,6804,1103,0,10051,7655,1318,10,4418,510,4435,0,4845,716,4862,10,9201,4435,2218,0,10052,4862,2433,10,2210,4418,9201,0,2425,4845,10052,10,6804,9201,6805,0,7655,10052,7656,10,512,4422,9202,0,719,4849,10053,10,4422,2212,6806,0,4849,2427,7657,10,4436,9202,6809,0,4863,10053,7660,10,9202,6806,1104,0,10053,7657,1319,10,4423,213,3135,0,4850,285,3562,10,9203,3135,1568,0,10054,3562,1783,10,2212,4423,9203,0,2427,4850,10054,10,6806,9203,6807,0,7657,10054,7658,10,188,4421,9204,0,257,5625,10055,10,4421,2211,6808,0,5625,2815,7659,10,3134,9204,6807,0,3561,10055,7658,10,9204,6808,1104,0,10055,7659,1319,10,4420,511,4437,0,5626,718,4864,10,9205,4437,2219,0,10056,4864,2434,10,2211,4420,9205,0,2815,5626,10056,10,6808,9205,6809,0,7659,10056,7660,10,513,4424,9206,0,721,4851,10057,10,4424,2213,6810,0,4851,2428,7661,10,4438,9206,6813,0,4865,10057,7664,10,9206,6810,1105,0,10057,7661,1320,10,4425,203,3147,0,4852,272,3574,10,9207,3147,1574,0,10058,3574,1789,10,2213,4425,9207,0,2428,4852,10058,10,6810,9207,6811,0,7661,10058,7662,10,213,4423,9208,0,290,5627,10059,10,4423,2212,6812,0,5627,2816,7663,10,3146,9208,6811,0,3573,10059,7662,10,9208,6812,1105,0,10059,7663,1320,10,4422,512,4439,0,5628,720,4866,10,9209,4439,2220,0,10060,4866,2435,10,2212,4422,9209,0,2816,5628,10060,10,6812,9209,6813,0,7663,10060,7664,10,514,4426,9210,0,723,4853,10061,10,4426,2214,6814,0,4853,2429,7665,10,4440,9210,6817,0,4867,10061,7668,10,9210,6814,1106,0,10061,7665,1321,10,4427,113,3173,0,4854,177,3600,10,9211,3173,1587,0,10062,3600,1802,10,2214,4427,9211,0,2429,4854,10062,10,6814,9211,6815,0,7665,10062,7666,10,203,4425,9212,0,272,5629,10063,10,4425,2213,6816,0,5629,2817,7667,10,3172,9212,6815,0,3599,10063,7666,10,9212,6816,1106,0,10063,7667,1321,10,4424,513,4441,0,5630,722,4868,10,9213,4441,2221,0,10064,4868,2436,10,2213,4424,9213,0,2817,5630,10064,10,6816,9213,6817,0,7667,10064,7668,10,515,4428,9214,0,724,4855,10065,10,4428,2215,6818,0,4855,2430,7669,10,4442,9214,6821,0,4869,10065,7672,10,9214,6818,1107,0,10065,7669,1322,10,4429,112,2817,0,4856,176,3244,10,9215,2817,1409,0,10066,3244,1624,10,2215,4429,9215,0,2430,4856,10066,10,6818,9215,6819,0,7669,10066,7670,10,113,4427,9216,0,177,4854,10067,10,4427,2214,6820,0,4854,2429,7671,10,2816,9216,6819,0,3243,10067,7670,10,9216,6820,1107,0,10067,7671,1322,10,4426,514,4443,0,4853,723,4870,10,9217,4443,2222,0,10068,4870,2437,10,2214,4426,9217,0,2429,4853,10068,10,6820,9217,6821,0,7671,10068,7672,10,516,4430,9218,0,726,4857,10069,10,4430,2216,6822,0,4857,2431,7673,10,4444,9218,6825,0,4871,10069,7676,10,9218,6822,1108,0,10069,7673,1323,10,4431,217,3151,0,4858,292,3578,10,9219,3151,1576,0,10070,3578,1791,10,2216,4431,9219,0,2431,4858,10070,10,6822,9219,6823,0,7673,10070,7674,10,112,4429,9220,0,293,5631,10071,10,4429,2215,6824,0,5631,2818,7675,10,3150,9220,6823,0,3577,10071,7674,10,9220,6824,1108,0,10071,7675,1323,10,4428,515,4445,0,5632,725,4872,10,9221,4445,2223,0,10072,4872,2438,10,2215,4428,9221,0,2818,5632,10072,10,6824,9221,6825,0,7675,10072,7676,10,509,4416,9222,0,714,4843,10073,10,4416,2209,6826,0,4843,2424,7677,10,4446,9222,6829,0,4873,10073,7680,10,9222,6826,1109,0,10073,7677,1324,10,4417,220,3167,0,4844,298,3594,10,9223,3167,1584,0,10074,3594,1799,10,2209,4417,9223,0,2424,4844,10074,10,6826,9223,6827,0,7677,10074,7678,10,217,4431,9224,0,292,4858,10075,10,4431,2216,6828,0,4858,2431,7679,10,3166,9224,6827,0,3593,10075,7678,10,9224,6828,1109,0,10075,7679,1324,10,4430,516,4447,0,4857,726,4874,10,9225,4447,2224,0,10076,4874,2439,10,2216,4430,9225,0,2431,4857,10076,10,6828,9225,6829,0,7679,10076,7680,10,518,4450,9226,0,728,4877,10077,10,4450,2226,6830,0,4877,2441,7681,10,4476,9226,6833,0,4903,10077,7684,10,9226,6830,1110,0,10077,7681,1325,10,4451,539,4542,0,4878,750,4969,10,9227,4542,2272,0,10078,4969,2487,10,2226,4451,9227,0,2441,4878,10078,10,6830,9227,6831,0,7681,10078,7682,10,531,4504,9228,0,742,4931,10079,10,4504,2253,6832,0,4931,2468,7683,10,4543,9228,6831,0,4970,10079,7682,10,9228,6832,1110,0,10079,7683,1325,10,4505,517,4477,0,4932,727,4904,10,9229,4477,2239,0,10080,4904,2454,10,2253,4505,9229,0,2468,4932,10080,10,6832,9229,6833,0,7683,10080,7684,10,520,4454,9230,0,730,4881,10081,10,4454,2228,6834,0,4881,2443,7685,10,4478,9230,6837,0,4905,10081,7688,10,9230,6834,1111,0,10081,7685,1326,10,4455,540,4544,0,4882,751,4971,10,9231,4544,2273,0,10082,4971,2488,10,2228,4455,9231,0,2443,4882,10082,10,6834,9231,6835,0,7685,10082,7686,10,532,4506,9232,0,743,4933,10083,10,4506,2254,6836,0,4933,2469,7687,10,4545,9232,6835,0,4972,10083,7686,10,9232,6836,1111,0,10083,7687,1326,10,4507,519,4479,0,4934,729,4906,10,9233,4479,2240,0,10084,4906,2455,10,2254,4507,9233,0,2469,4934,10084,10,6836,9233,6837,0,7687,10084,7688,10,521,4456,9234,0,731,4883,10085,10,4456,2229,6838,0,4883,2444,7689,10,4480,9234,6841,0,4907,10085,7692,10,9234,6838,1112,0,10085,7689,1327,10,4457,541,4546,0,4884,752,4973,10,9235,4546,2274,0,10086,4973,2489,10,2229,4457,9235,0,2444,4884,10086,10,6838,9235,6839,0,7689,10086,7690,10,540,4455,9236,0,751,4882,10087,10,4455,2228,6840,0,4882,2443,7691,10,4547,9236,6839,0,4974,10087,7690,10,9236,6840,1112,0,10087,7691,1327,10,4454,520,4481,0,4881,730,4908,10,9237,4481,2241,0,10088,4908,2456,10,2228,4454,9237,0,2443,4881,10088,10,6840,9237,6841,0,7691,10088,7692,10,523,4460,9238,0,733,4887,10089,10,4460,2231,6842,0,4887,2446,7693,10,4482,9238,6845,0,4909,10089,7696,10,9238,6842,1113,0,10089,7693,1328,10,4461,542,4548,0,4888,753,4975,10,9239,4548,2275,0,10090,4975,2490,10,2231,4461,9239,0,2446,4888,10090,10,6842,9239,6843,0,7693,10090,7694,10,533,4508,9240,0,744,4935,10091,10,4508,2255,6844,0,4935,2470,7695,10,4549,9240,6843,0,4976,10091,7694,10,9240,6844,1113,0,10091,7695,1328,10,4509,522,4483,0,4936,732,4910,10,9241,4483,2242,0,10092,4910,2457,10,2255,4509,9241,0,2470,4936,10092,10,6844,9241,6845,0,7695,10092,7696,10,519,4507,9242,0,729,4934,10093,10,4507,2254,6846,0,4934,2469,7697,10,4484,9242,6849,0,4911,10093,7700,10,9242,6846,1114,0,10093,7697,1329,10,4506,532,4550,0,4933,743,4977,10,9243,4550,2276,0,10094,4977,2491,10,2254,4506,9243,0,2469,4933,10094,10,6846,9243,6847,0,7697,10094,7698,10,534,4510,9244,0,745,4937,10095,10,4510,2256,6848,0,4937,2471,7699,10,4551,9244,6847,0,4978,10095,7698,10,9244,6848,1114,0,10095,7699,1329,10,4511,524,4485,0,4938,735,4912,10,9245,4485,2243,0,10096,4912,2458,10,2256,4511,9245,0,2471,4938,10096,10,6848,9245,6849,0,7699,10096,7700,10,525,4464,9246,0,736,4891,10097,10,4464,2233,6850,0,4891,2448,7701,10,4486,9246,6853,0,4913,10097,7704,10,9246,6850,1115,0,10097,7701,1330,10,4465,597,4784,0,4892,812,5211,10,9247,4784,2393,0,10098,5211,2608,10,2233,4465,9247,0,2448,4892,10098,10,6850,9247,6851,0,7701,10098,7702,10,596,4463,9248,0,811,4890,10099,10,4463,2232,6852,0,4890,2447,7703,10,4785,9248,6851,0,5212,10099,7702,10,9248,6852,1115,0,10099,7703,1330,10,4462,524,4487,0,4889,735,4914,10,9249,4487,2244,0,10100,4914,2459,10,2232,4462,9249,0,2447,4889,10100,10,6852,9249,6853,0,7703,10100,7704,10,526,4466,9250,0,737,4893,10101,10,4466,2234,6854,0,4893,2449,7705,10,4488,9250,6857,0,4915,10101,7708,10,9250,6854,1116,0,10101,7705,1331,10,4467,598,4786,0,4894,813,5213,10,9251,4786,2394,0,10102,5213,2609,10,2234,4467,9251,0,2449,4894,10102,10,6854,9251,6855,0,7705,10102,7706,10,597,4465,9252,0,812,4892,10103,10,4465,2233,6856,0,4892,2448,7707,10,4787,9252,6855,0,5214,10103,7706,10,9252,6856,1116,0,10103,7707,1331,10,4464,525,4489,0,4891,736,4916,10,9253,4489,2245,0,10104,4916,2460,10,2233,4464,9253,0,2448,4891,10104,10,6856,9253,6857,0,7707,10104,7708,10,528,4470,9254,0,739,4897,10105,10,4470,2236,6858,0,4897,2451,7709,10,4490,9254,6861,0,4917,10105,7712,10,9254,6858,1117,0,10105,7709,1332,10,4471,543,4552,0,4898,755,4979,10,9255,4552,2277,0,10106,4979,2492,10,2236,4471,9255,0,2451,4898,10106,10,6858,9255,6859,0,7709,10106,7710,10,537,4516,9256,0,748,4943,10107,10,4516,2259,6860,0,4943,2474,7711,10,4553,9256,6859,0,4980,10107,7710,10,9256,6860,1117,0,10107,7711,1332,10,4517,527,4491,0,4944,738,4918,10,9257,4491,2246,0,10108,4918,2461,10,2259,4517,9257,0,2474,4944,10108,10,6860,9257,6861,0,7711,10108,7712,10,526,4515,9258,0,737,4942,10109,10,4515,2258,6862,0,4942,2473,7713,10,4492,9258,6865,0,4919,10109,7716,10,9258,6862,1118,0,10109,7713,1333,10,4514,536,4554,0,4941,747,4981,10,9259,4554,2278,0,10110,4981,2493,10,2258,4514,9259,0,2473,4941,10110,10,6862,9259,6863,0,7713,10110,7714,10,543,4471,9260,0,755,4898,10111,10,4471,2236,6864,0,4898,2451,7715,10,4555,9260,6863,0,4982,10111,7714,10,9260,6864,1118,0,10111,7715,1333,10,4470,528,4493,0,4897,739,4920,10,9261,4493,2247,0,10112,4920,2462,10,2236,4470,9261,0,2451,4897,10112,10,6864,9261,6865,0,7715,10112,7716,10,530,4474,9262,0,741,4901,10113,10,4474,2238,6866,0,4901,2453,7717,10,4494,9262,6869,0,4921,10113,7720,10,9262,6866,1119,0,10113,7717,1334,10,4475,600,4788,0,4902,815,5215,10,9263,4788,2395,0,10114,5215,2610,10,2238,4475,9263,0,2453,4902,10114,10,6866,9263,6867,0,7717,10114,7718,10,592,4748,9264,0,807,5175,10115,10,4748,2375,6868,0,5175,2590,7719,10,4789,9264,6867,0,5216,10115,7718,10,9264,6868,1119,0,10115,7719,1334,10,4749,529,4495,0,5176,740,4922,10,9265,4495,2248,0,10116,4922,2463,10,2375,4749,9265,0,2590,5176,10116,10,6868,9265,6869,0,7719,10116,7720,10,523,4745,9266,0,734,5643,10117,10,4745,2373,6870,0,5643,2824,7721,10,4496,9266,6873,0,4923,10117,7724,10,9266,6870,1120,0,10117,7721,1335,10,4744,590,4790,0,5644,805,5217,10,9267,4790,2396,0,10118,5217,2611,10,2373,4744,9267,0,2824,5644,10118,10,6870,9267,6871,0,7721,10118,7722,10,600,4475,9268,0,815,4902,10119,10,4475,2238,6872,0,4902,2453,7723,10,4791,9268,6871,0,5218,10119,7722,10,9268,6872,1120,0,10119,7723,1335,10,4474,530,4497,0,4901,741,4924,10,9269,4497,2249,0,10120,4924,2464,10,2238,4474,9269,0,2453,4901,10120,10,6872,9269,6873,0,7723,10120,7724,10,527,4517,9270,0,738,4944,10121,10,4517,2259,6874,0,4944,2474,7725,10,4498,9270,6877,0,4925,10121,7728,10,9270,6874,1121,0,10121,7725,1336,10,4516,537,4556,0,4943,748,4983,10,9271,4556,2279,0,10122,4983,2494,10,2259,4516,9271,0,2474,4943,10122,10,6874,9271,6875,0,7725,10122,7726,10,539,4451,9272,0,750,4878,10123,10,4451,2226,6876,0,4878,2441,7727,10,4557,9272,6875,0,4984,10123,7726,10,9272,6876,1121,0,10123,7727,1336,10,4450,518,4499,0,4877,728,4926,10,9273,4499,2250,0,10124,4926,2465,10,2226,4450,9273,0,2441,4877,10124,10,6876,9273,6877,0,7727,10124,7728,10,529,4749,9274,0,740,5176,10125,10,4749,2375,6878,0,5176,2590,7729,10,4500,9274,6881,0,4927,10125,7732,10,9274,6878,1122,0,10125,7729,1337,10,4748,592,4792,0,5175,807,5219,10,9275,4792,2397,0,10126,5219,2612,10,2375,4748,9275,0,2590,5175,10126,10,6878,9275,6879,0,7729,10126,7730,10,593,4449,9276,0,808,4876,10127,10,4449,2225,6880,0,4876,2440,7731,10,4793,9276,6879,0,5220,10127,7730,10,9276,6880,1122,0,10127,7731,1337,10,4448,517,4501,0,4875,727,4928,10,9277,4501,2251,0,10128,4928,2466,10,2225,4448,9277,0,2440,4875,10128,10,6880,9277,6881,0,7731,10128,7732,10,522,4509,9278,0,732,4936,10129,10,4509,2255,6882,0,4936,2470,7733,10,4502,9278,6885,0,4929,10129,7736,10,9278,6882,1123,0,10129,7733,1338,10,4508,533,4558,0,4935,744,4985,10,9279,4558,2280,0,10130,4985,2495,10,2255,4508,9279,0,2470,4935,10130,10,6882,9279,6883,0,7733,10130,7734,10,541,4457,9280,0,752,4884,10131,10,4457,2229,6884,0,4884,2444,7735,10,4559,9280,6883,0,4986,10131,7734,10,9280,6884,1123,0,10131,7735,1338,10,4456,521,4503,0,4883,731,4930,10,9281,4503,2252,0,10132,4930,2467,10,2229,4456,9281,0,2444,4883,10132,10,6884,9281,6885,0,7735,10132,7736,10,535,4512,9282,0,746,4939,10133,10,4512,2257,6886,0,4939,2472,7737,10,4532,9282,6889,0,4959,10133,7740,10,9282,6886,1124,0,10133,7737,1339,10,4513,525,4486,0,4940,736,4913,10,9283,4486,2244,0,10134,4913,2459,10,2257,4513,9283,0,2472,4940,10134,10,6886,9283,6887,0,7737,10134,7738,10,524,4511,9284,0,735,4938,10135,10,4511,2256,6888,0,4938,2471,7739,10,4487,9284,6887,0,4914,10135,7738,10,9284,6888,1124,0,10135,7739,1339,10,4510,534,4533,0,4937,745,4960,10,9285,4533,2267,0,10136,4960,2482,10,2256,4510,9285,0,2471,4937,10136,10,6888,9285,6889,0,7739,10136,7740,10,536,4514,9286,0,747,4941,10137,10,4514,2258,6890,0,4941,2473,7741,10,4534,9286,6893,0,4961,10137,7744,10,9286,6890,1125,0,10137,7741,1340,10,4515,526,4488,0,4942,737,4915,10,9287,4488,2245,0,10138,4915,2460,10,2258,4515,9287,0,2473,4942,10138,10,6890,9287,6891,0,7741,10138,7742,10,525,4513,9288,0,736,4940,10139,10,4513,2257,6892,0,4940,2472,7743,10,4489,9288,6891,0,4916,10139,7742,10,9288,6892,1125,0,10139,7743,1340,10,4512,535,4535,0,4939,746,4962,10,9289,4535,2268,0,10140,4962,2483,10,2257,4512,9289,0,2472,4939,10140,10,6892,9289,6893,0,7743,10140,7744,10,538,4518,9290,0,749,4945,10141,10,4518,2260,6894,0,4945,2475,7745,10,4536,9290,6897,0,4963,10141,7748,10,9290,6894,1126,0,10141,7745,1341,10,4519,530,4494,0,4946,741,4921,10,9291,4494,2248,0,10142,4921,2463,10,2260,4519,9291,0,2475,4946,10142,10,6894,9291,6895,0,7745,10142,7746,10,529,4472,9292,0,740,4899,10143,10,4472,2237,6896,0,4899,2452,7747,10,4495,9292,6895,0,4922,10143,7746,10,9292,6896,1126,0,10143,7747,1341,10,4473,544,4537,0,4900,756,4964,10,9293,4537,2269,0,10144,4964,2484,10,2237,4473,9293,0,2452,4900,10144,10,6896,9293,6897,0,7747,10144,7748,10,542,4461,9294,0,754,5633,10145,10,4461,2231,6898,0,5633,2819,7749,10,4538,9294,6901,0,4965,10145,7752,10,9294,6898,1127,0,10145,7749,1342,10,4460,523,4496,0,5634,734,4923,10,9295,4496,2249,0,10146,4923,2464,10,2231,4460,9295,0,2819,5634,10146,10,6898,9295,6899,0,7749,10146,7750,10,530,4519,9296,0,741,4946,10147,10,4519,2260,6900,0,4946,2475,7751,10,4497,9296,6899,0,4924,10147,7750,10,9296,6900,1127,0,10147,7751,1342,10,4518,538,4539,0,4945,749,4966,10,9297,4539,2270,0,10148,4966,2485,10,2260,4518,9297,0,2475,4945,10148,10,6900,9297,6901,0,7751,10148,7752,10,544,4473,9298,0,756,4900,10149,10,4473,2237,6902,0,4900,2452,7753,10,4540,9298,6905,0,4967,10149,7756,10,9298,6902,1128,0,10149,7753,1343,10,4472,529,4500,0,4899,740,4927,10,9299,4500,2251,0,10150,4927,2466,10,2237,4472,9299,0,2452,4899,10150,10,6902,9299,6903,0,7753,10150,7754,10,517,4505,9300,0,727,4932,10151,10,4505,2253,6904,0,4932,2468,7755,10,4501,9300,6903,0,4928,10151,7754,10,9300,6904,1128,0,10151,7755,1343,10,4504,531,4541,0,4931,742,4968,10,9301,4541,2271,0,10152,4968,2486,10,2253,4504,9301,0,2468,4931,10152,10,6904,9301,6905,0,7755,10152,7756,10,539,4520,9302,0,750,4947,10153,10,4520,2261,6906,0,4947,2476,7757,10,4542,9302,6909,0,4969,10153,7760,10,9302,6906,1129,0,10153,7757,1344,10,4521,581,4720,0,4948,794,5147,10,9303,4720,2361,0,10154,5147,2576,10,2261,4521,9303,0,2476,4948,10154,10,6906,9303,6907,0,7757,10154,7758,10,573,4682,9304,0,786,5109,10155,10,4682,2342,6908,0,5109,2557,7759,10,4721,9304,6907,0,5148,10155,7758,10,9304,6908,1129,0,10155,7759,1344,10,4683,531,4543,0,5110,742,4970,10,9305,4543,2272,0,10156,4970,2487,10,2342,4683,9305,0,2557,5110,10156,10,6908,9305,6909,0,7759,10156,7760,10,540,4522,9306,0,751,4949,10157,10,4522,2262,6910,0,4949,2477,7761,10,4544,9306,6913,0,4971,10157,7764,10,9306,6910,1130,0,10157,7761,1345,10,4523,582,4722,0,4950,795,5149,10,9307,4722,2362,0,10158,5149,2577,10,2262,4523,9307,0,2477,4950,10158,10,6910,9307,6911,0,7761,10158,7762,10,574,4684,9308,0,787,5111,10159,10,4684,2343,6912,0,5111,2558,7763,10,4723,9308,6911,0,5150,10159,7762,10,9308,6912,1130,0,10159,7763,1345,10,4685,532,4545,0,5112,743,4972,10,9309,4545,2273,0,10160,4972,2488,10,2343,4685,9309,0,2558,5112,10160,10,6912,9309,6913,0,7763,10160,7764,10,541,4524,9310,0,752,4951,10161,10,4524,2263,6914,0,4951,2478,7765,10,4546,9310,6917,0,4973,10161,7768,10,9310,6914,1131,0,10161,7765,1346,10,4525,583,4724,0,4952,796,5151,10,9311,4724,2363,0,10162,5151,2578,10,2263,4525,9311,0,2478,4952,10162,10,6914,9311,6915,0,7765,10162,7766,10,582,4523,9312,0,795,4950,10163,10,4523,2262,6916,0,4950,2477,7767,10,4725,9312,6915,0,5152,10163,7766,10,9312,6916,1131,0,10163,7767,1346,10,4522,540,4547,0,4949,751,4974,10,9313,4547,2274,0,10164,4974,2489,10,2262,4522,9313,0,2477,4949,10164,10,6916,9313,6917,0,7767,10164,7768,10,542,4526,9314,0,753,4953,10165,10,4526,2264,6918,0,4953,2479,7769,10,4548,9314,6921,0,4975,10165,7772,10,9314,6918,1132,0,10165,7769,1347,10,4527,584,4726,0,4954,797,5153,10,9315,4726,2364,0,10166,5153,2579,10,2264,4527,9315,0,2479,4954,10166,10,6918,9315,6919,0,7769,10166,7770,10,575,4686,9316,0,788,5113,10167,10,4686,2344,6920,0,5113,2559,7771,10,4727,9316,6919,0,5154,10167,7770,10,9316,6920,1132,0,10167,7771,1347,10,4687,533,4549,0,5114,744,4976,10,9317,4549,2275,0,10168,4976,2490,10,2344,4687,9317,0,2559,5114,10168,10,6920,9317,6921,0,7771,10168,7772,10,532,4685,9318,0,743,5112,10169,10,4685,2343,6922,0,5112,2558,7773,10,4550,9318,6925,0,4977,10169,7776,10,9318,6922,1133,0,10169,7773,1348,10,4684,574,4728,0,5111,787,5155,10,9319,4728,2365,0,10170,5155,2580,10,2343,4684,9319,0,2558,5111,10170,10,6922,9319,6923,0,7773,10170,7774,10,576,4688,9320,0,789,5115,10171,10,4688,2345,6924,0,5115,2560,7775,10,4729,9320,6923,0,5156,10171,7774,10,9320,6924,1133,0,10171,7775,1348,10,4689,534,4551,0,5116,745,4978,10,9321,4551,2276,0,10172,4978,2491,10,2345,4689,9321,0,2560,5116,10172,10,6924,9321,6925,0,7775,10172,7776,10,543,4528,9322,0,755,4955,10173,10,4528,2265,6926,0,4955,2480,7777,10,4552,9322,6929,0,4979,10173,7780,10,9322,6926,1134,0,10173,7777,1349,10,4529,585,4730,0,4956,799,5157,10,9323,4730,2366,0,10174,5157,2581,10,2265,4529,9323,0,2480,4956,10174,10,6926,9323,6927,0,7777,10174,7778,10,579,4694,9324,0,792,5121,10175,10,4694,2348,6928,0,5121,2563,7779,10,4731,9324,6927,0,5158,10175,7778,10,9324,6928,1134,0,10175,7779,1349,10,4695,537,4553,0,5122,748,4980,10,9325,4553,2277,0,10176,4980,2492,10,2348,4695,9325,0,2563,5122,10176,10,6928,9325,6929,0,7779,10176,7780,10,536,4693,9326,0,747,5120,10177,10,4693,2347,6930,0,5120,2562,7781,10,4554,9326,6933,0,4981,10177,7784,10,9326,6930,1135,0,10177,7781,1350,10,4692,578,4732,0,5119,791,5159,10,9327,4732,2367,0,10178,5159,2582,10,2347,4692,9327,0,2562,5119,10178,10,6930,9327,6931,0,7781,10178,7782,10,585,4529,9328,0,799,4956,10179,10,4529,2265,6932,0,4956,2480,7783,10,4733,9328,6931,0,5160,10179,7782,10,9328,6932,1135,0,10179,7783,1350,10,4528,543,4555,0,4955,755,4982,10,9329,4555,2278,0,10180,4982,2493,10,2265,4528,9329,0,2480,4955,10180,10,6932,9329,6933,0,7783,10180,7784,10,537,4695,9330,0,748,5122,10181,10,4695,2348,6934,0,5122,2563,7785,10,4556,9330,6937,0,4983,10181,7788,10,9330,6934,1136,0,10181,7785,1351,10,4694,579,4734,0,5121,792,5161,10,9331,4734,2368,0,10182,5161,2583,10,2348,4694,9331,0,2563,5121,10182,10,6934,9331,6935,0,7785,10182,7786,10,581,4521,9332,0,794,4948,10183,10,4521,2261,6936,0,4948,2476,7787,10,4735,9332,6935,0,5162,10183,7786,10,9332,6936,1136,0,10183,7787,1351,10,4520,539,4557,0,4947,750,4984,10,9333,4557,2279,0,10184,4984,2494,10,2261,4520,9333,0,2476,4947,10184,10,6936,9333,6937,0,7787,10184,7788,10,533,4687,9334,0,744,5114,10185,10,4687,2344,6938,0,5114,2559,7789,10,4558,9334,6941,0,4985,10185,7792,10,9334,6938,1137,0,10185,7789,1352,10,4686,575,4736,0,5113,788,5163,10,9335,4736,2369,0,10186,5163,2584,10,2344,4686,9335,0,2559,5113,10186,10,6938,9335,6939,0,7789,10186,7790,10,583,4525,9336,0,796,4952,10187,10,4525,2263,6940,0,4952,2478,7791,10,4737,9336,6939,0,5164,10187,7790,10,9336,6940,1137,0,10187,7791,1352,10,4524,541,4559,0,4951,752,4986,10,9337,4559,2280,0,10188,4986,2495,10,2263,4524,9337,0,2478,4951,10188,10,6940,9337,6941,0,7791,10188,7792,10,546,4622,9338,0,758,5049,10189,10,4622,2312,6942,0,5049,2527,7793,10,4561,9338,6945,0,4988,10189,7796,10,9338,6942,1138,0,10189,7793,1353,10,4623,551,4572,0,5050,763,4999,10,9339,4572,2287,0,10190,4999,2502,10,2312,4623,9339,0,2527,5050,10190,10,6942,9339,6943,0,7793,10190,7794,10,552,4620,9340,0,764,5047,10191,10,4620,2311,6944,0,5047,2526,7795,10,4573,9340,6943,0,5000,10191,7794,10,9340,6944,1138,0,10191,7795,1353,10,4621,545,4560,0,5048,757,4987,10,9341,4560,2281,0,10192,4987,2496,10,2311,4621,9341,0,2526,5048,10192,10,6944,9341,6945,0,7795,10192,7796,10,310,3600,9342,0,399,4027,10193,10,3600,1801,6946,0,4027,2016,7797,10,4588,9342,6949,0,5015,10193,7800,10,9342,6946,1139,0,10193,7797,1354,10,3601,309,4590,0,4028,398,5017,10,9343,4590,2296,0,10194,5017,2511,10,1801,3601,9343,0,2016,4028,10194,10,6946,9343,6947,0,7797,10194,7798,10,560,4654,9344,0,772,5081,10195,10,4654,2328,6948,0,5081,2543,7799,10,4591,9344,6947,0,5018,10195,7798,10,9344,6948,1139,0,10195,7799,1354,10,4655,559,4589,0,5082,771,5016,10,9345,4589,2295,0,10196,5016,2510,10,2328,4655,9345,0,2543,5082,10196,10,6948,9345,6949,0,7799,10196,7800,10,309,3602,9346,0,398,4029,10197,10,3602,1802,6950,0,4029,2017,7801,10,4590,9346,6953,0,5017,10197,7804,10,9346,6950,1140,0,10197,7801,1355,10,3603,311,4592,0,4030,400,5019,10,9347,4592,2297,0,10198,5019,2512,10,1802,3603,9347,0,2017,4030,10198,10,6950,9347,6951,0,7801,10198,7802,10,561,4656,9348,0,773,5083,10199,10,4656,2329,6952,0,5083,2544,7803,10,4593,9348,6951,0,5020,10199,7802,10,9348,6952,1140,0,10199,7803,1355,10,4657,560,4591,0,5084,772,5018,10,9349,4591,2296,0,10200,5018,2511,10,2329,4657,9349,0,2544,5084,10200,10,6952,9349,6953,0,7803,10200,7804,10,311,3674,9350,0,400,4101,10201,10,3674,1838,6954,0,4101,2053,7805,10,4592,9350,6957,0,5019,10201,7808,10,9350,6954,1141,0,10201,7805,1356,10,3675,329,4594,0,4102,420,5021,10,9351,4594,2298,0,10202,5021,2513,10,1838,3675,9351,0,2053,4102,10202,10,6954,9351,6955,0,7805,10202,7806,10,562,4658,9352,0,774,5085,10203,10,4658,2330,6956,0,5085,2545,7807,10,4595,9352,6955,0,5022,10203,7806,10,9352,6956,1141,0,10203,7807,1356,10,4659,561,4593,0,5086,773,5020,10,9353,4593,2297,0,10204,5020,2512,10,2330,4659,9353,0,2545,5086,10204,10,6956,9353,6957,0,7807,10204,7808,10,329,3680,9354,0,420,4107,10205,10,3680,1841,6958,0,4107,2056,7809,10,4594,9354,6961,0,5021,10205,7812,10,9354,6958,1142,0,10205,7809,1357,10,3681,330,4596,0,4108,421,5023,10,9355,4596,2299,0,10206,5023,2514,10,1841,3681,9355,0,2056,4108,10206,10,6958,9355,6959,0,7809,10206,7810,10,563,4660,9356,0,775,5087,10207,10,4660,2331,6960,0,5087,2546,7811,10,4597,9356,6959,0,5024,10207,7810,10,9356,6960,1142,0,10207,7811,1357,10,4661,562,4595,0,5088,774,5022,10,9357,4595,2298,0,10208,5022,2513,10,2331,4661,9357,0,2546,5088,10208,10,6960,9357,6961,0,7811,10208,7812,10,330,3684,9358,0,421,4111,10209,10,3684,1843,6962,0,4111,2058,7813,10,4596,9358,6965,0,5023,10209,7816,10,9358,6962,1143,0,10209,7813,1358,10,3685,322,4598,0,4112,411,5025,10,9359,4598,2300,0,10210,5025,2515,10,1843,3685,9359,0,2058,4112,10210,10,6962,9359,6963,0,7813,10210,7814,10,564,4662,9360,0,776,5089,10211,10,4662,2332,6964,0,5089,2547,7815,10,4599,9360,6963,0,5026,10211,7814,10,9360,6964,1143,0,10211,7815,1358,10,4663,563,4597,0,5090,775,5024,10,9361,4597,2299,0,10212,5024,2514,10,2332,4663,9361,0,2547,5090,10212,10,6964,9361,6965,0,7815,10212,7816,10,322,3630,9362,0,411,4057,10213,10,3630,1816,6966,0,4057,2031,7817,10,4598,9362,6969,0,5025,10213,7820,10,9362,6966,1144,0,10213,7817,1359,10,3631,319,4600,0,4058,408,5027,10,9363,4600,2301,0,10214,5027,2516,10,1816,3631,9363,0,2031,4058,10214,10,6966,9363,6967,0,7817,10214,7818,10,565,4664,9364,0,777,5091,10215,10,4664,2333,6968,0,5091,2548,7819,10,4601,9364,6967,0,5028,10215,7818,10,9364,6968,1144,0,10215,7819,1359,10,4665,564,4599,0,5092,776,5026,10,9365,4599,2300,0,10216,5026,2515,10,2333,4665,9365,0,2548,5092,10216,10,6968,9365,6969,0,7819,10216,7820,10,319,3622,9366,0,408,4049,10217,10,3622,1812,6970,0,4049,2027,7821,10,4600,9366,6973,0,5027,10217,7824,10,9366,6970,1145,0,10217,7821,1360,10,3623,317,4602,0,4050,406,5029,10,9367,4602,2302,0,10218,5029,2517,10,1812,3623,9367,0,2027,4050,10218,10,6970,9367,6971,0,7821,10218,7822,10,566,4666,9368,0,778,5093,10219,10,4666,2334,6972,0,5093,2549,7823,10,4603,9368,6971,0,5030,10219,7822,10,9368,6972,1145,0,10219,7823,1360,10,4667,565,4601,0,5094,777,5028,10,9369,4601,2301,0,10220,5028,2516,10,2334,4667,9369,0,2549,5094,10220,10,6972,9369,6973,0,7823,10220,7824,10,317,3616,9370,0,406,4043,10221,10,3616,1809,6974,0,4043,2024,7825,10,4602,9370,6977,0,5029,10221,7828,10,9370,6974,1146,0,10221,7825,1361,10,3617,316,4604,0,4044,405,5031,10,9371,4604,2303,0,10222,5031,2518,10,1809,3617,9371,0,2024,4044,10222,10,6974,9371,6975,0,7825,10222,7826,10,567,4668,9372,0,779,5095,10223,10,4668,2335,6976,0,5095,2550,7827,10,4605,9372,6975,0,5032,10223,7826,10,9372,6976,1146,0,10223,7827,1361,10,4669,566,4603,0,5096,778,5030,10,9373,4603,2302,0,10224,5030,2517,10,2335,4669,9373,0,2550,5096,10224,10,6976,9373,6977,0,7827,10224,7828,10,316,3618,9374,0,405,4045,10225,10,3618,1810,6978,0,4045,2025,7829,10,4604,9374,6981,0,5031,10225,7832,10,9374,6978,1147,0,10225,7829,1362,10,3619,318,4606,0,4046,407,5033,10,9375,4606,2304,0,10226,5033,2519,10,1810,3619,9375,0,2025,4046,10226,10,6978,9375,6979,0,7829,10226,7830,10,568,4670,9376,0,780,5097,10227,10,4670,2336,6980,0,5097,2551,7831,10,4607,9376,6979,0,5034,10227,7830,10,9376,6980,1147,0,10227,7831,1362,10,4671,567,4605,0,5098,779,5032,10,9377,4605,2303,0,10228,5032,2518,10,2336,4671,9377,0,2551,5098,10228,10,6980,9377,6981,0,7831,10228,7832,10,318,3664,9378,0,407,4091,10229,10,3664,1833,6982,0,4091,2048,7833,10,4606,9378,6985,0,5033,10229,7836,10,9378,6982,1148,0,10229,7833,1363,10,3665,313,4608,0,4092,402,5035,10,9379,4608,2305,0,10230,5035,2520,10,1833,3665,9379,0,2048,4092,10230,10,6982,9379,6983,0,7833,10230,7834,10,569,4672,9380,0,781,5099,10231,10,4672,2337,6984,0,5099,2552,7835,10,4609,9380,6983,0,5036,10231,7834,10,9380,6984,1148,0,10231,7835,1363,10,4673,568,4607,0,5100,780,5034,10,9381,4607,2304,0,10232,5034,2519,10,2337,4673,9381,0,2552,5100,10232,10,6984,9381,6985,0,7835,10232,7836,10,313,3604,9382,0,402,4031,10233,10,3604,1803,6986,0,4031,2018,7837,10,4608,9382,6989,0,5035,10233,7840,10,9382,6986,1149,0,10233,7837,1364,10,3605,312,4610,0,4032,401,5037,10,9383,4610,2306,0,10234,5037,2521,10,1803,3605,9383,0,2018,4032,10234,10,6986,9383,6987,0,7837,10234,7838,10,570,4674,9384,0,782,5101,10235,10,4674,2338,6988,0,5101,2553,7839,10,4611,9384,6987,0,5038,10235,7838,10,9384,6988,1149,0,10235,7839,1364,10,4675,569,4609,0,5102,781,5036,10,9385,4609,2305,0,10236,5036,2520,10,2338,4675,9385,0,2553,5102,10236,10,6988,9385,6989,0,7839,10236,7840,10,312,3608,9386,0,401,4035,10237,10,3608,1805,6990,0,4035,2020,7841,10,4610,9386,6993,0,5037,10237,7844,10,9386,6990,1150,0,10237,7841,1365,10,3609,314,4612,0,4036,403,5039,10,9387,4612,2307,0,10238,5039,2522,10,1805,3609,9387,0,2020,4036,10238,10,6990,9387,6991,0,7841,10238,7842,10,571,4676,9388,0,783,5103,10239,10,4676,2339,6992,0,5103,2554,7843,10,4613,9388,6991,0,5040,10239,7842,10,9388,6992,1150,0,10239,7843,1365,10,4677,570,4611,0,5104,782,5038,10,9389,4611,2306,0,10240,5038,2521,10,2339,4677,9389,0,2554,5104,10240,10,6992,9389,6993,0,7843,10240,7844,10,314,3654,9390,0,416,4081,10241,10,3654,1828,6994,0,4081,2043,7845,10,4612,9390,6997,0,5638,10241,7848,10,9390,6994,1151,0,10241,7845,1366,10,3655,327,4614,0,4082,417,5041,10,9391,4614,2308,0,10242,5041,2523,10,1828,3655,9391,0,2043,4082,10242,10,6994,9391,6995,0,7845,10242,7846,10,572,4678,9392,0,785,5105,10243,10,4678,2340,6996,0,5105,2555,7847,10,4615,9392,6995,0,5042,10243,7846,10,9392,6996,1151,0,10243,7847,1366,10,4679,571,4613,0,5106,784,5637,10,9393,4613,2307,0,10244,5637,2821,10,2340,4679,9393,0,2555,5106,10244,10,6996,9393,6997,0,7847,10244,7848,10,327,3682,9394,0,417,4109,10245,10,3682,1842,6998,0,4109,2057,7849,10,4614,9394,7001,0,5041,10245,7852,10,9394,6998,1152,0,10245,7849,1367,10,3683,310,4588,0,4110,399,5015,10,9395,4588,2295,0,10246,5015,2510,10,1842,3683,9395,0,2057,4110,10246,10,6998,9395,6999,0,7849,10246,7850,10,559,4680,9396,0,771,5107,10247,10,4680,2341,7000,0,5107,2556,7851,10,4589,9396,6999,0,5016,10247,7850,10,9396,7000,1152,0,10247,7851,1367,10,4681,572,4615,0,5108,785,5042,10,9397,4615,2308,0,10248,5042,2523,10,2341,4681,9397,0,2556,5108,10248,10,7000,9397,7001,0,7851,10248,7852,10,554,4578,9398,0,766,5005,10249,10,4578,2290,7002,0,5005,2505,7853,10,4616,9398,7005,0,5043,10249,7856,10,9398,7002,1153,0,10249,7853,1368,10,4579,555,4580,0,5006,767,5007,10,9399,4580,2291,0,10250,5007,2506,10,2290,4579,9399,0,2505,5006,10250,10,7002,9399,7003,0,7853,10250,7854,10,556,4582,9400,0,768,5009,10251,10,4582,2292,7004,0,5009,2507,7855,10,4581,9400,7003,0,5008,10251,7854,10,9400,7004,1153,0,10251,7855,1368,10,4583,557,4617,0,5010,769,5044,10,9401,4617,2309,0,10252,5044,2524,10,2292,4583,9401,0,2507,5010,10252,10,7004,9401,7005,0,7855,10252,7856,10,553,4576,9402,0,765,5003,10253,10,4576,2289,7006,0,5003,2504,7857,10,4618,9402,7009,0,5045,10253,7860,10,9402,7006,1154,0,10253,7857,1369,10,4577,554,4616,0,5004,766,5043,10,9403,4616,2309,0,10254,5043,2524,10,2289,4577,9403,0,2504,5004,10254,10,7006,9403,7007,0,7857,10254,7858,10,557,4584,9404,0,769,5011,10255,10,4584,2293,7008,0,5011,2508,7859,10,4617,9404,7007,0,5044,10255,7858,10,9404,7008,1154,0,10255,7859,1369,10,4585,558,4619,0,5012,770,5046,10,9405,4619,2310,0,10256,5046,2525,10,2293,4585,9405,0,2508,5012,10256,10,7008,9405,7009,0,7859,10256,7860,10,552,4574,9406,0,764,5001,10257,10,4574,2288,7010,0,5001,2503,7861,10,4620,9406,7013,0,5047,10257,7864,10,9406,7010,1155,0,10257,7861,1370,10,4575,553,4618,0,5002,765,5045,10,9407,4618,2310,0,10258,5045,2525,10,2288,4575,9407,0,2503,5002,10258,10,7010,9407,7011,0,7861,10258,7862,10,558,4586,9408,0,770,5013,10259,10,4586,2294,7012,0,5013,2509,7863,10,4619,9408,7011,0,5046,10259,7862,10,9408,7012,1155,0,10259,7863,1370,10,4587,545,4621,0,5014,757,5048,10,9409,4621,2311,0,10260,5048,2526,10,2294,4587,9409,0,2509,5014,10260,10,7012,9409,7013,0,7863,10260,7864,10,546,4562,9410,0,758,4989,10261,10,4562,2282,7014,0,4989,2497,7865,10,4622,9410,7017,0,5049,10261,7868,10,9410,7014,1156,0,10261,7865,1371,10,4563,547,4624,0,4990,759,5051,10,9411,4624,2313,0,10262,5051,2528,10,2282,4563,9411,0,2497,4990,10262,10,7014,9411,7015,0,7865,10262,7866,10,550,4570,9412,0,762,4997,10263,10,4570,2286,7016,0,4997,2501,7867,10,4625,9412,7015,0,5052,10263,7866,10,9412,7016,1156,0,10263,7867,1371,10,4571,551,4623,0,4998,763,5050,10,9413,4623,2312,0,10264,5050,2527,10,2286,4571,9413,0,2501,4998,10264,10,7016,9413,7017,0,7867,10264,7868,10,547,4564,9414,0,759,4991,10265,10,4564,2283,7018,0,4991,2498,7869,10,4624,9414,7021,0,5051,10265,7872,10,9414,7018,1157,0,10265,7869,1372,10,4565,548,4566,0,4992,760,4993,10,9415,4566,2284,0,10266,4993,2499,10,2283,4565,9415,0,2498,4992,10266,10,7018,9415,7019,0,7869,10266,7870,10,549,4568,9416,0,761,4995,10267,10,4568,2285,7020,0,4995,2500,7871,10,4567,9416,7019,0,4994,10267,7870,10,9416,7020,1157,0,10267,7871,1372,10,4569,550,4625,0,4996,762,5052,10,9417,4625,2313,0,10268,5052,2528,10,2285,4569,9417,0,2500,4996,10268,10,7020,9417,7021,0,7871,10268,7872,10,560,4628,9418,0,772,5055,10269,10,4628,2315,7022,0,5055,2530,7873,10,4654,9418,7025,0,5081,10269,7876,10,9418,7022,1158,0,10269,7873,1373,10,4629,546,4561,0,5056,758,4988,10,9419,4561,2281,0,10270,4988,2496,10,2315,4629,9419,0,2530,5056,10270,10,7022,9419,7023,0,7873,10270,7874,10,545,4627,9420,0,757,5054,10271,10,4627,2314,7024,0,5054,2529,7875,10,4560,9420,7023,0,4987,10271,7874,10,9420,7024,1158,0,10271,7875,1373,10,4626,559,4655,0,5053,771,5082,10,9421,4655,2328,0,10272,5082,2543,10,2314,4626,9421,0,2529,5053,10272,10,7024,9421,7025,0,7875,10272,7876,10,561,4630,9422,0,773,5057,10273,10,4630,2316,7026,0,5057,2531,7877,10,4656,9422,7029,0,5083,10273,7880,10,9422,7026,1159,0,10273,7877,1374,10,4631,547,4563,0,5058,759,4990,10,9423,4563,2282,0,10274,4990,2497,10,2316,4631,9423,0,2531,5058,10274,10,7026,9423,7027,0,7877,10274,7878,10,546,4629,9424,0,758,5056,10275,10,4629,2315,7028,0,5056,2530,7879,10,4562,9424,7027,0,4989,10275,7878,10,9424,7028,1159,0,10275,7879,1374,10,4628,560,4657,0,5055,772,5084,10,9425,4657,2329,0,10276,5084,2544,10,2315,4628,9425,0,2530,5055,10276,10,7028,9425,7029,0,7879,10276,7880,10,562,4632,9426,0,774,5059,10277,10,4632,2317,7030,0,5059,2532,7881,10,4658,9426,7033,0,5085,10277,7884,10,9426,7030,1160,0,10277,7881,1375,10,4633,548,4565,0,5060,760,4992,10,9427,4565,2283,0,10278,4992,2498,10,2317,4633,9427,0,2532,5060,10278,10,7030,9427,7031,0,7881,10278,7882,10,547,4631,9428,0,759,5058,10279,10,4631,2316,7032,0,5058,2531,7883,10,4564,9428,7031,0,4991,10279,7882,10,9428,7032,1160,0,10279,7883,1375,10,4630,561,4659,0,5057,773,5086,10,9429,4659,2330,0,10280,5086,2545,10,2316,4630,9429,0,2531,5057,10280,10,7032,9429,7033,0,7883,10280,7884,10,563,4634,9430,0,775,5061,10281,10,4634,2318,7034,0,5061,2533,7885,10,4660,9430,7037,0,5087,10281,7888,10,9430,7034,1161,0,10281,7885,1376,10,4635,549,4567,0,5062,761,4994,10,9431,4567,2284,0,10282,4994,2499,10,2318,4635,9431,0,2533,5062,10282,10,7034,9431,7035,0,7885,10282,7886,10,548,4633,9432,0,760,5060,10283,10,4633,2317,7036,0,5060,2532,7887,10,4566,9432,7035,0,4993,10283,7886,10,9432,7036,1161,0,10283,7887,1376,10,4632,562,4661,0,5059,774,5088,10,9433,4661,2331,0,10284,5088,2546,10,2317,4632,9433,0,2532,5059,10284,10,7036,9433,7037,0,7887,10284,7888,10,564,4636,9434,0,776,5063,10285,10,4636,2319,7038,0,5063,2534,7889,10,4662,9434,7041,0,5089,10285,7892,10,9434,7038,1162,0,10285,7889,1377,10,4637,550,4569,0,5064,762,4996,10,9435,4569,2285,0,10286,4996,2500,10,2319,4637,9435,0,2534,5064,10286,10,7038,9435,7039,0,7889,10286,7890,10,549,4635,9436,0,761,5062,10287,10,4635,2318,7040,0,5062,2533,7891,10,4568,9436,7039,0,4995,10287,7890,10,9436,7040,1162,0,10287,7891,1377,10,4634,563,4663,0,5061,775,5090,10,9437,4663,2332,0,10288,5090,2547,10,2318,4634,9437,0,2533,5061,10288,10,7040,9437,7041,0,7891,10288,7892,10,565,4638,9438,0,777,5065,10289,10,4638,2320,7042,0,5065,2535,7893,10,4664,9438,7045,0,5091,10289,7896,10,9438,7042,1163,0,10289,7893,1378,10,4639,551,4571,0,5066,763,4998,10,9439,4571,2286,0,10290,4998,2501,10,2320,4639,9439,0,2535,5066,10290,10,7042,9439,7043,0,7893,10290,7894,10,550,4637,9440,0,762,5064,10291,10,4637,2319,7044,0,5064,2534,7895,10,4570,9440,7043,0,4997,10291,7894,10,9440,7044,1163,0,10291,7895,1378,10,4636,564,4665,0,5063,776,5092,10,9441,4665,2333,0,10292,5092,2548,10,2319,4636,9441,0,2534,5063,10292,10,7044,9441,7045,0,7895,10292,7896,10,566,4640,9442,0,778,5067,10293,10,4640,2321,7046,0,5067,2536,7897,10,4666,9442,7049,0,5093,10293,7900,10,9442,7046,1164,0,10293,7897,1379,10,4641,552,4573,0,5068,764,5000,10,9443,4573,2287,0,10294,5000,2502,10,2321,4641,9443,0,2536,5068,10294,10,7046,9443,7047,0,7897,10294,7898,10,551,4639,9444,0,763,5066,10295,10,4639,2320,7048,0,5066,2535,7899,10,4572,9444,7047,0,4999,10295,7898,10,9444,7048,1164,0,10295,7899,1379,10,4638,565,4667,0,5065,777,5094,10,9445,4667,2334,0,10296,5094,2549,10,2320,4638,9445,0,2535,5065,10296,10,7048,9445,7049,0,7899,10296,7900,10,567,4642,9446,0,779,5069,10297,10,4642,2322,7050,0,5069,2537,7901,10,4668,9446,7053,0,5095,10297,7904,10,9446,7050,1165,0,10297,7901,1380,10,4643,553,4575,0,5070,765,5002,10,9447,4575,2288,0,10298,5002,2503,10,2322,4643,9447,0,2537,5070,10298,10,7050,9447,7051,0,7901,10298,7902,10,552,4641,9448,0,764,5068,10299,10,4641,2321,7052,0,5068,2536,7903,10,4574,9448,7051,0,5001,10299,7902,10,9448,7052,1165,0,10299,7903,1380,10,4640,566,4669,0,5067,778,5096,10,9449,4669,2335,0,10300,5096,2550,10,2321,4640,9449,0,2536,5067,10300,10,7052,9449,7053,0,7903,10300,7904,10,568,4644,9450,0,780,5071,10301,10,4644,2323,7054,0,5071,2538,7905,10,4670,9450,7057,0,5097,10301,7908,10,9450,7054,1166,0,10301,7905,1381,10,4645,554,4577,0,5072,766,5004,10,9451,4577,2289,0,10302,5004,2504,10,2323,4645,9451,0,2538,5072,10302,10,7054,9451,7055,0,7905,10302,7906,10,553,4643,9452,0,765,5070,10303,10,4643,2322,7056,0,5070,2537,7907,10,4576,9452,7055,0,5003,10303,7906,10,9452,7056,1166,0,10303,7907,1381,10,4642,567,4671,0,5069,779,5098,10,9453,4671,2336,0,10304,5098,2551,10,2322,4642,9453,0,2537,5069,10304,10,7056,9453,7057,0,7907,10304,7908,10,569,4646,9454,0,781,5073,10305,10,4646,2324,7058,0,5073,2539,7909,10,4672,9454,7061,0,5099,10305,7912,10,9454,7058,1167,0,10305,7909,1382,10,4647,555,4579,0,5074,767,5006,10,9455,4579,2290,0,10306,5006,2505,10,2324,4647,9455,0,2539,5074,10306,10,7058,9455,7059,0,7909,10306,7910,10,554,4645,9456,0,766,5072,10307,10,4645,2323,7060,0,5072,2538,7911,10,4578,9456,7059,0,5005,10307,7910,10,9456,7060,1167,0,10307,7911,1382,10,4644,568,4673,0,5071,780,5100,10,9457,4673,2337,0,10308,5100,2552,10,2323,4644,9457,0,2538,5071,10308,10,7060,9457,7061,0,7911,10308,7912,10,570,4648,9458,0,782,5075,10309,10,4648,2325,7062,0,5075,2540,7913,10,4674,9458,7065,0,5101,10309,7916,10,9458,7062,1168,0,10309,7913,1383,10,4649,556,4581,0,5076,768,5008,10,9459,4581,2291,0,10310,5008,2506,10,2325,4649,9459,0,2540,5076,10310,10,7062,9459,7063,0,7913,10310,7914,10,555,4647,9460,0,767,5074,10311,10,4647,2324,7064,0,5074,2539,7915,10,4580,9460,7063,0,5007,10311,7914,10,9460,7064,1168,0,10311,7915,1383,10,4646,569,4675,0,5073,781,5102,10,9461,4675,2338,0,10312,5102,2553,10,2324,4646,9461,0,2539,5073,10312,10,7064,9461,7065,0,7915,10312,7916,10,571,4650,9462,0,783,5077,10313,10,4650,2326,7066,0,5077,2541,7917,10,4676,9462,7069,0,5103,10313,7920,10,9462,7066,1169,0,10313,7917,1384,10,4651,557,4583,0,5078,769,5010,10,9463,4583,2292,0,10314,5010,2507,10,2326,4651,9463,0,2541,5078,10314,10,7066,9463,7067,0,7917,10314,7918,10,556,4649,9464,0,768,5076,10315,10,4649,2325,7068,0,5076,2540,7919,10,4582,9464,7067,0,5009,10315,7918,10,9464,7068,1169,0,10315,7919,1384,10,4648,570,4677,0,5075,782,5104,10,9465,4677,2339,0,10316,5104,2554,10,2325,4648,9465,0,2540,5075,10316,10,7068,9465,7069,0,7919,10316,7920,10,572,4652,9466,0,785,5079,10317,10,4652,2327,7070,0,5079,2542,7921,10,4678,9466,7073,0,5105,10317,7924,10,9466,7070,1170,0,10317,7921,1385,10,4653,558,4585,0,5080,770,5012,10,9467,4585,2293,0,10318,5012,2508,10,2327,4653,9467,0,2542,5080,10318,10,7070,9467,7071,0,7921,10318,7922,10,557,4651,9468,0,769,5639,10319,10,4651,2326,7072,0,5639,2822,7923,10,4584,9468,7071,0,5011,10319,7922,10,9468,7072,1170,0,10319,7923,1385,10,4650,571,4679,0,5640,784,5106,10,9469,4679,2340,0,10320,5106,2555,10,2326,4650,9469,0,2822,5640,10320,10,7072,9469,7073,0,7923,10320,7924,10,559,4626,9470,0,771,5053,10321,10,4626,2314,7074,0,5053,2529,7925,10,4680,9470,7077,0,5107,10321,7928,10,9470,7074,1171,0,10321,7925,1386,10,4627,545,4587,0,5054,757,5014,10,9471,4587,2294,0,10322,5014,2509,10,2314,4627,9471,0,2529,5054,10322,10,7074,9471,7075,0,7925,10322,7926,10,558,4653,9472,0,770,5080,10323,10,4653,2327,7076,0,5080,2542,7927,10,4586,9472,7075,0,5013,10323,7926,10,9472,7076,1171,0,10323,7927,1386,10,4652,572,4681,0,5079,785,5108,10,9473,4681,2341,0,10324,5108,2556,10,2327,4652,9473,0,2542,5079,10324,10,7076,9473,7077,0,7927,10324,7928,10,577,4690,9474,0,790,5117,10325,10,4690,2346,7078,0,5117,2561,7929,10,4710,9474,7081,0,5137,10325,7932,10,9474,7078,1172,0,10325,7929,1387,10,4691,535,4532,0,5118,746,4959,10,9475,4532,2267,0,10326,4959,2482,10,2346,4691,9475,0,2561,5118,10326,10,7078,9475,7079,0,7929,10326,7930,10,534,4689,9476,0,745,5116,10327,10,4689,2345,7080,0,5116,2560,7931,10,4533,9476,7079,0,4960,10327,7930,10,9476,7080,1172,0,10327,7931,1387,10,4688,576,4711,0,5115,789,5138,10,9477,4711,2356,0,10328,5138,2571,10,2345,4688,9477,0,2560,5115,10328,10,7080,9477,7081,0,7931,10328,7932,10,578,4692,9478,0,791,5119,10329,10,4692,2347,7082,0,5119,2562,7933,10,4712,9478,7085,0,5139,10329,7936,10,9478,7082,1173,0,10329,7933,1388,10,4693,536,4534,0,5120,747,4961,10,9479,4534,2268,0,10330,4961,2483,10,2347,4693,9479,0,2562,5120,10330,10,7082,9479,7083,0,7933,10330,7934,10,535,4691,9480,0,746,5118,10331,10,4691,2346,7084,0,5118,2561,7935,10,4535,9480,7083,0,4962,10331,7934,10,9480,7084,1173,0,10331,7935,1388,10,4690,577,4713,0,5117,790,5140,10,9481,4713,2357,0,10332,5140,2572,10,2346,4690,9481,0,2561,5117,10332,10,7084,9481,7085,0,7935,10332,7936,10,580,4696,9482,0,793,5123,10333,10,4696,2349,7086,0,5123,2564,7937,10,4714,9482,7089,0,5141,10333,7940,10,9482,7086,1174,0,10333,7937,1389,10,4697,538,4536,0,5124,749,4963,10,9483,4536,2269,0,10334,4963,2484,10,2349,4697,9483,0,2564,5124,10334,10,7086,9483,7087,0,7937,10334,7938,10,544,4530,9484,0,756,4957,10335,10,4530,2266,7088,0,4957,2481,7939,10,4537,9484,7087,0,4964,10335,7938,10,9484,7088,1174,0,10335,7939,1389,10,4531,586,4715,0,4958,800,5142,10,9485,4715,2358,0,10336,5142,2573,10,2266,4531,9485,0,2481,4958,10336,10,7088,9485,7089,0,7939,10336,7940,10,584,4527,9486,0,798,5635,10337,10,4527,2264,7090,0,5635,2820,7941,10,4716,9486,7093,0,5143,10337,7944,10,9486,7090,1175,0,10337,7941,1390,10,4526,542,4538,0,5636,754,4965,10,9487,4538,2270,0,10338,4965,2485,10,2264,4526,9487,0,2820,5636,10338,10,7090,9487,7091,0,7941,10338,7942,10,538,4697,9488,0,749,5124,10339,10,4697,2349,7092,0,5124,2564,7943,10,4539,9488,7091,0,4966,10339,7942,10,9488,7092,1175,0,10339,7943,1390,10,4696,580,4717,0,5123,793,5144,10,9489,4717,2359,0,10340,5144,2574,10,2349,4696,9489,0,2564,5123,10340,10,7092,9489,7093,0,7943,10340,7944,10,586,4531,9490,0,800,4958,10341,10,4531,2266,7094,0,4958,2481,7945,10,4718,9490,7097,0,5145,10341,7948,10,9490,7094,1176,0,10341,7945,1391,10,4530,544,4540,0,4957,756,4967,10,9491,4540,2271,0,10342,4967,2486,10,2266,4530,9491,0,2481,4957,10342,10,7094,9491,7095,0,7945,10342,7946,10,531,4683,9492,0,742,5110,10343,10,4683,2342,7096,0,5110,2557,7947,10,4541,9492,7095,0,4968,10343,7946,10,9492,7096,1176,0,10343,7947,1391,10,4682,573,4719,0,5109,786,5146,10,9493,4719,2360,0,10344,5146,2575,10,2342,4682,9493,0,2557,5109,10344,10,7096,9493,7097,0,7947,10344,7948,10,581,4698,9494,0,794,5125,10345,10,4698,2350,7098,0,5125,2565,7949,10,4720,9494,7101,0,5147,10345,7952,10,9494,7098,1177,0,10345,7949,1392,10,4699,311,3603,0,5126,400,4030,10,9495,3603,1802,0,10346,4030,2017,10,2350,4699,9495,0,2565,5126,10346,10,7098,9495,7099,0,7949,10346,7950,10,309,3584,9496,0,398,4011,10347,10,3584,1793,7100,0,4011,2008,7951,10,3602,9496,7099,0,4029,10347,7950,10,9496,7100,1177,0,10347,7951,1392,10,3585,573,4721,0,4012,786,5148,10,9497,4721,2361,0,10348,5148,2576,10,1793,3585,9497,0,2008,4012,10348,10,7100,9497,7101,0,7951,10348,7952,10,582,4700,9498,0,795,5127,10349,10,4700,2351,7102,0,5127,2566,7953,10,4722,9498,7105,0,5149,10349,7956,10,9498,7102,1178,0,10349,7953,1393,10,4701,318,3619,0,5128,407,4046,10,9499,3619,1810,0,10350,4046,2025,10,2351,4701,9499,0,2566,5128,10350,10,7102,9499,7103,0,7953,10350,7954,10,316,3592,9500,0,405,4019,10351,10,3592,1797,7104,0,4019,2012,7955,10,3618,9500,7103,0,4045,10351,7954,10,9500,7104,1178,0,10351,7955,1393,10,3593,574,4723,0,4020,787,5150,10,9501,4723,2362,0,10352,5150,2577,10,1797,3593,9501,0,2012,4020,10352,10,7104,9501,7105,0,7955,10352,7956,10,583,4702,9502,0,796,5129,10353,10,4702,2352,7106,0,5129,2567,7957,10,4724,9502,7109,0,5151,10353,7960,10,9502,7106,1179,0,10353,7957,1394,10,4703,313,3665,0,5130,402,4092,10,9503,3665,1833,0,10354,4092,2048,10,2352,4703,9503,0,2567,5130,10354,10,7106,9503,7107,0,7957,10354,7958,10,318,4701,9504,0,407,5128,10355,10,4701,2351,7108,0,5128,2566,7959,10,3664,9504,7107,0,4091,10355,7958,10,9504,7108,1179,0,10355,7959,1394,10,4700,582,4725,0,5127,795,5152,10,9505,4725,2363,0,10356,5152,2578,10,2351,4700,9505,0,2566,5127,10356,10,7108,9505,7109,0,7959,10356,7960,10,584,4704,9506,0,797,5131,10357,10,4704,2353,7110,0,5131,2568,7961,10,4726,9506,7113,0,5153,10357,7964,10,9506,7110,1180,0,10357,7961,1395,10,4705,314,3609,0,5132,403,4036,10,9507,3609,1805,0,10358,4036,2020,10,2353,4705,9507,0,2568,5132,10358,10,7110,9507,7111,0,7961,10358,7962,10,312,3606,9508,0,401,4033,10359,10,3606,1804,7112,0,4033,2019,7963,10,3608,9508,7111,0,4035,10359,7962,10,9508,7112,1180,0,10359,7963,1395,10,3607,575,4727,0,4034,788,5154,10,9509,4727,2364,0,10360,5154,2579,10,1804,3607,9509,0,2019,4034,10360,10,7112,9509,7113,0,7963,10360,7964,10,574,3593,9510,0,787,4020,10361,10,3593,1797,7114,0,4020,2012,7965,10,4728,9510,7117,0,5155,10361,7968,10,9510,7114,1181,0,10361,7965,1396,10,3592,316,3617,0,4019,405,4044,10,9511,3617,1809,0,10362,4044,2024,10,1797,3592,9511,0,2012,4019,10362,10,7114,9511,7115,0,7965,10362,7966,10,317,3614,9512,0,406,4041,10363,10,3614,1808,7116,0,4041,2023,7967,10,3616,9512,7115,0,4043,10363,7966,10,9512,7116,1181,0,10363,7967,1396,10,3615,576,4729,0,4042,789,5156,10,9513,4729,2365,0,10364,5156,2580,10,1808,3615,9513,0,2023,4042,10364,10,7116,9513,7117,0,7967,10364,7968,10,585,4706,9514,0,799,5133,10365,10,4706,2354,7118,0,5133,2569,7969,10,4730,9514,7121,0,5157,10365,7972,10,9514,7118,1182,0,10365,7969,1397,10,4707,330,3681,0,5134,421,4108,10,9515,3681,1841,0,10366,4108,2056,10,2354,4707,9515,0,2569,5134,10366,10,7118,9515,7119,0,7969,10366,7970,10,329,3638,9516,0,420,4065,10367,10,3638,1820,7120,0,4065,2035,7971,10,3680,9516,7119,0,4107,10367,7970,10,9516,7120,1182,0,10367,7971,1397,10,3639,579,4731,0,4066,792,5158,10,9517,4731,2366,0,10368,5158,2581,10,1820,3639,9517,0,2035,4066,10368,10,7120,9517,7121,0,7971,10368,7972,10,578,3629,9518,0,791,4056,10369,10,3629,1815,7122,0,4056,2030,7973,10,4732,9518,7125,0,5159,10369,7976,10,9518,7122,1183,0,10369,7973,1398,10,3628,322,3685,0,4055,411,4112,10,9519,3685,1843,0,10370,4112,2058,10,1815,3628,9519,0,2030,4055,10370,10,7122,9519,7123,0,7973,10370,7974,10,330,4707,9520,0,421,5134,10371,10,4707,2354,7124,0,5134,2569,7975,10,3684,9520,7123,0,4111,10371,7974,10,9520,7124,1183,0,10371,7975,1398,10,4706,585,4733,0,5133,799,5160,10,9521,4733,2367,0,10372,5160,2582,10,2354,4706,9521,0,2569,5133,10372,10,7124,9521,7125,0,7975,10372,7976,10,579,3639,9522,0,792,4066,10373,10,3639,1820,7126,0,4066,2035,7977,10,4734,9522,7129,0,5161,10373,7980,10,9522,7126,1184,0,10373,7977,1399,10,3638,329,3675,0,4065,420,4102,10,9523,3675,1838,0,10374,4102,2053,10,1820,3638,9523,0,2035,4065,10374,10,7126,9523,7127,0,7977,10374,7978,10,311,4699,9524,0,400,5126,10375,10,4699,2350,7128,0,5126,2565,7979,10,3674,9524,7127,0,4101,10375,7978,10,9524,7128,1184,0,10375,7979,1399,10,4698,581,4735,0,5125,794,5162,10,9525,4735,2368,0,10376,5162,2583,10,2350,4698,9525,0,2565,5125,10376,10,7128,9525,7129,0,7979,10376,7980,10,575,3607,9526,0,788,4034,10377,10,3607,1804,7130,0,4034,2019,7981,10,4736,9526,7133,0,5163,10377,7984,10,9526,7130,1185,0,10377,7981,1400,10,3606,312,3605,0,4033,401,4032,10,9527,3605,1803,0,10378,4032,2018,10,1804,3606,9527,0,2019,4033,10378,10,7130,9527,7131,0,7981,10378,7982,10,313,4703,9528,0,402,5130,10379,10,4703,2352,7132,0,5130,2567,7983,10,3604,9528,7131,0,4031,10379,7982,10,9528,7132,1185,0,10379,7983,1400,10,4702,583,4737,0,5129,796,5164,10,9529,4737,2369,0,10380,5164,2584,10,2352,4702,9529,0,2567,5129,10380,10,7132,9529,7133,0,7983,10380,7984,10,587,4738,9530,0,801,5165,10381,10,4738,2370,7134,0,5165,2585,7985,10,4766,9530,7137,0,5193,10381,7988,10,9530,7134,1186,0,10381,7985,1401,10,4739,518,4476,0,5166,728,4903,10,9531,4476,2239,0,10382,4903,2454,10,2370,4739,9531,0,2585,5166,10382,10,7134,9531,7135,0,7985,10382,7986,10,517,4448,9532,0,727,4875,10383,10,4448,2225,7136,0,4875,2440,7987,10,4477,9532,7135,0,4904,10383,7986,10,9532,7136,1186,0,10383,7987,1401,10,4449,593,4767,0,4876,808,5194,10,9533,4767,2384,0,10384,5194,2599,10,2225,4449,9533,0,2440,4876,10384,10,7136,9533,7137,0,7987,10384,7988,10,588,4740,9534,0,802,5167,10385,10,4740,2371,7138,0,5167,2586,7989,10,4768,9534,7141,0,5195,10385,7992,10,9534,7138,1187,0,10385,7989,1402,10,4741,520,4478,0,5168,730,4905,10,9535,4478,2240,0,10386,4905,2455,10,2371,4741,9535,0,2586,5168,10386,10,7138,9535,7139,0,7989,10386,7990,10,519,4452,9536,0,729,4879,10387,10,4452,2227,7140,0,4879,2442,7991,10,4479,9536,7139,0,4906,10387,7990,10,9536,7140,1187,0,10387,7991,1402,10,4453,594,4769,0,4880,809,5196,10,9537,4769,2385,0,10388,5196,2600,10,2227,4453,9537,0,2442,4880,10388,10,7140,9537,7141,0,7991,10388,7992,10,589,4742,9538,0,803,5169,10389,10,4742,2372,7142,0,5169,2587,7993,10,4770,9538,7145,0,5197,10389,7996,10,9538,7142,1188,0,10389,7993,1403,10,4743,521,4480,0,5170,731,4907,10,9539,4480,2241,0,10390,4907,2456,10,2372,4743,9539,0,2587,5170,10390,10,7142,9539,7143,0,7993,10390,7994,10,520,4741,9540,0,730,5168,10391,10,4741,2371,7144,0,5168,2586,7995,10,4481,9540,7143,0,4908,10391,7994,10,9540,7144,1188,0,10391,7995,1403,10,4740,588,4771,0,5167,802,5198,10,9541,4771,2386,0,10392,5198,2601,10,2371,4740,9541,0,2586,5167,10392,10,7144,9541,7145,0,7995,10392,7996,10,590,4744,9542,0,804,5171,10393,10,4744,2373,7146,0,5171,2588,7997,10,4772,9542,7149,0,5199,10393,8000,10,9542,7146,1189,0,10393,7997,1404,10,4745,523,4482,0,5172,733,4909,10,9543,4482,2242,0,10394,4909,2457,10,2373,4745,9543,0,2588,5172,10394,10,7146,9543,7147,0,7997,10394,7998,10,522,4458,9544,0,732,4885,10395,10,4458,2230,7148,0,4885,2445,7999,10,4483,9544,7147,0,4910,10395,7998,10,9544,7148,1189,0,10395,7999,1404,10,4459,595,4773,0,4886,810,5200,10,9545,4773,2387,0,10396,5200,2602,10,2230,4459,9545,0,2445,4886,10396,10,7148,9545,7149,0,7999,10396,8000,10,594,4453,9546,0,809,4880,10397,10,4453,2227,7150,0,4880,2442,8001,10,4774,9546,7153,0,5201,10397,8004,10,9546,7150,1190,0,10397,8001,1405,10,4452,519,4484,0,4879,729,4911,10,9547,4484,2243,0,10398,4911,2458,10,2227,4452,9547,0,2442,4879,10398,10,7150,9547,7151,0,8001,10398,8002,10,524,4462,9548,0,735,4889,10399,10,4462,2232,7152,0,4889,2447,8003,10,4485,9548,7151,0,4912,10399,8002,10,9548,7152,1190,0,10399,8003,1405,10,4463,596,4775,0,4890,811,5202,10,9549,4775,2388,0,10400,5202,2603,10,2232,4463,9549,0,2447,4890,10400,10,7152,9549,7153,0,8003,10400,8004,10,591,4746,9550,0,806,5173,10401,10,4746,2374,7154,0,5173,2589,8005,10,4776,9550,7157,0,5203,10401,8008,10,9550,7154,1191,0,10401,8005,1406,10,4747,528,4490,0,5174,739,4917,10,9551,4490,2246,0,10402,4917,2461,10,2374,4747,9551,0,2589,5174,10402,10,7154,9551,7155,0,8005,10402,8006,10,527,4468,9552,0,738,4895,10403,10,4468,2235,7156,0,4895,2450,8007,10,4491,9552,7155,0,4918,10403,8006,10,9552,7156,1191,0,10403,8007,1406,10,4469,599,4777,0,4896,814,5204,10,9553,4777,2389,0,10404,5204,2604,10,2235,4469,9553,0,2450,4896,10404,10,7156,9553,7157,0,8007,10404,8008,10,598,4467,9554,0,813,4894,10405,10,4467,2234,7158,0,4894,2449,8009,10,4778,9554,7161,0,5205,10405,8012,10,9554,7158,1192,0,10405,8009,1407,10,4466,526,4492,0,4893,737,4919,10,9555,4492,2247,0,10406,4919,2462,10,2234,4466,9555,0,2449,4893,10406,10,7158,9555,7159,0,8009,10406,8010,10,528,4747,9556,0,739,5174,10407,10,4747,2374,7160,0,5174,2589,8011,10,4493,9556,7159,0,4920,10407,8010,10,9556,7160,1192,0,10407,8011,1407,10,4746,591,4779,0,5173,806,5206,10,9557,4779,2390,0,10408,5206,2605,10,2374,4746,9557,0,2589,5173,10408,10,7160,9557,7161,0,8011,10408,8012,10,599,4469,9558,0,814,4896,10409,10,4469,2235,7162,0,4896,2450,8013,10,4780,9558,7165,0,5207,10409,8016,10,9558,7162,1193,0,10409,8013,1408,10,4468,527,4498,0,4895,738,4925,10,9559,4498,2250,0,10410,4925,2465,10,2235,4468,9559,0,2450,4895,10410,10,7162,9559,7163,0,8013,10410,8014,10,518,4739,9560,0,728,5166,10411,10,4739,2370,7164,0,5166,2585,8015,10,4499,9560,7163,0,4926,10411,8014,10,9560,7164,1193,0,10411,8015,1408,10,4738,587,4781,0,5165,801,5208,10,9561,4781,2391,0,10412,5208,2606,10,2370,4738,9561,0,2585,5165,10412,10,7164,9561,7165,0,8015,10412,8016,10,595,4459,9562,0,810,4886,10413,10,4459,2230,7166,0,4886,2445,8017,10,4782,9562,7169,0,5209,10413,8020,10,9562,7166,1194,0,10413,8017,1409,10,4458,522,4502,0,4885,732,4929,10,9563,4502,2252,0,10414,4929,2467,10,2230,4458,9563,0,2445,4885,10414,10,7166,9563,7167,0,8017,10414,8018,10,521,4743,9564,0,731,5170,10415,10,4743,2372,7168,0,5170,2587,8019,10,4503,9564,7167,0,4930,10415,8018,10,9564,7168,1194,0,10415,8019,1409,10,4742,589,4783,0,5169,803,5210,10,9565,4783,2392,0,10416,5210,2607,10,2372,4742,9565,0,2587,5169,10416,10,7168,9565,7169,0,8019,10416,8020,10,597,4758,9566,0,812,5185,10417,10,4758,2380,7170,0,5185,2595,8021,10,4784,9566,7173,0,5211,10417,8024,10,9566,7170,1195,0,10417,8021,1410,10,4759,320,3624,0,5186,409,4051,10,9567,3624,1813,0,10418,4051,2028,10,2380,4759,9567,0,2595,5186,10418,10,7170,9567,7171,0,8021,10418,8022,10,315,4757,9568,0,404,5184,10419,10,4757,2379,7172,0,5184,2594,8023,10,3625,9568,7171,0,4052,10419,8022,10,9568,7172,1195,0,10419,8023,1410,10,4756,596,4785,0,5183,811,5212,10,9569,4785,2393,0,10420,5212,2608,10,2379,4756,9569,0,2594,5183,10420,10,7172,9569,7173,0,8023,10420,8024,10,598,4760,9570,0,813,5187,10421,10,4760,2381,7174,0,5187,2596,8025,10,4786,9570,7177,0,5213,10421,8028,10,9570,7174,1196,0,10421,8025,1411,10,4761,321,3626,0,5188,410,4053,10,9571,3626,1814,0,10422,4053,2029,10,2381,4761,9571,0,2596,5188,10422,10,7174,9571,7175,0,8025,10422,8026,10,320,4759,9572,0,409,5186,10423,10,4759,2380,7176,0,5186,2595,8027,10,3627,9572,7175,0,4054,10423,8026,10,9572,7176,1196,0,10423,8027,1411,10,4758,597,4787,0,5185,812,5214,10,9573,4787,2394,0,10424,5214,2609,10,2380,4758,9573,0,2595,5185,10424,10,7176,9573,7177,0,8027,10424,8028,10,600,4764,9574,0,815,5191,10425,10,4764,2383,7178,0,5191,2598,8029,10,4788,9574,7181,0,5215,10425,8032,10,9574,7178,1197,0,10425,8029,1412,10,4765,325,3648,0,5192,414,4075,10,9575,3648,1825,0,10426,4075,2040,10,2383,4765,9575,0,2598,5192,10426,10,7178,9575,7179,0,8029,10426,8030,10,303,3646,9576,0,392,4073,10427,10,3646,1824,7180,0,4073,2039,8031,10,3649,9576,7179,0,4076,10427,8030,10,9576,7180,1197,0,10427,8031,1412,10,3647,592,4789,0,4074,807,5216,10,9577,4789,2395,0,10428,5216,2610,10,1824,3647,9577,0,2039,4074,10428,10,7180,9577,7181,0,8031,10428,8032,10,590,3611,9578,0,805,5371,10429,10,3611,1806,7182,0,5371,2688,8033,10,4790,9578,7185,0,5217,10429,8036,10,9578,7182,1198,0,10429,8033,1413,10,3610,326,3652,0,5372,415,4079,10,9579,3652,1827,0,10430,4079,2042,10,1806,3610,9579,0,2688,5372,10430,10,7182,9579,7183,0,8033,10430,8034,10,325,4765,9580,0,414,5192,10431,10,4765,2383,7184,0,5192,2598,8035,10,3653,9580,7183,0,4080,10431,8034,10,9580,7184,1198,0,10431,8035,1413,10,4764,600,4791,0,5191,815,5218,10,9581,4791,2396,0,10432,5218,2611,10,2383,4764,9581,0,2598,5191,10432,10,7184,9581,7185,0,8035,10432,8036,10,592,3647,9582,0,807,4074,10433,10,3647,1824,7186,0,4074,2039,8037,10,4792,9582,7189,0,5219,10433,8040,10,9582,7186,1199,0,10433,8037,1414,10,3646,303,3581,0,4073,392,4008,10,9583,3581,1791,0,10434,4008,2006,10,1824,3646,9583,0,2039,4073,10434,10,7186,9583,7187,0,8037,10434,8038,10,304,4751,9584,0,393,5178,10435,10,4751,2376,7188,0,5178,2591,8039,10,3580,9584,7187,0,4007,10435,8038,10,9584,7188,1199,0,10435,8039,1414,10,4750,593,4793,0,5177,808,5220,10,9585,4793,2397,0,10436,5220,2612,10,2376,4750,9585,0,2591,5177,10436,10,7188,9585,7189,0,8039,10436,8040,10,7190,2405,1,0,8041,2832,6,10,4794,7190,2398,0,5645,8041,2825,10,4797,1203,2405,0,5648,1418,2832,10,601,4797,7190,0,816,5648,8041,10,2400,7191,2399,0,2827,8042,2826,10,1201,4795,7191,0,1416,5646,8042,10,7191,4794,1200,0,8042,5645,1415,10,4795,601,4794,0,5646,816,5645,10,7192,2401,12,0,8043,2828,28,10,4796,7192,2402,0,5647,8043,2829,10,4795,1201,2401,0,5646,1416,2828,10,601,4795,7192,0,816,5646,8043,10,2404,7193,2403,0,2831,8044,2830,10,1203,4797,7193,0,1418,5648,8044,10,7193,4796,1202,0,8044,5647,1417,10,4797,601,4796,0,5648,816,5647,10,7194,2400,25,0,8045,2827,65,10,4798,7194,2406,0,5649,8045,2833,10,4801,1201,2400,0,5652,1416,2827,10,602,4801,7194,0,817,5652,8045,10,2408,7195,2407,0,2835,8046,2834,10,1205,4799,7195,0,1420,5650,8046,10,7195,4798,1204,0,8046,5649,1419,10,4799,602,4798,0,5650,817,5649,10,7196,2409,30,0,8047,2836,46,10,4800,7196,2410,0,5651,8047,2837,10,4799,1205,2409,0,5650,1420,2836,10,602,4799,7196,0,817,5650,8047,10,2401,7197,2411,0,2828,8048,2838,10,1201,4801,7197,0,1416,5652,8048,10,7197,4800,1206,0,8048,5651,1421,10,4801,602,4800,0,5652,817,5651,10,7198,2417,2,0,8049,2844,9,10,4802,7198,2412,0,5653,8049,2839,10,4805,1209,2417,0,5656,1424,2844,10,603,4805,7198,0,818,5656,8049,10,2414,7199,2413,0,2841,8050,2840,10,1208,4803,7199,0,1423,5654,8050,10,7199,4802,1207,0,8050,5653,1422,10,4803,603,4802,0,5654,818,5653,10,7200,2415,12,0,8051,2842,28,10,4804,7200,2411,0,5655,8051,2838,10,4803,1208,2415,0,5654,1423,2842,10,603,4803,7200,0,818,5654,8051,10,2416,7201,2410,0,2843,8052,2837,10,1209,4805,7201,0,1424,5656,8052,10,7201,4804,1206,0,8052,5655,1421,10,4805,603,4804,0,5656,818,5655,10,7202,2414,27,0,8053,2841,67,10,4806,7202,2418,0,5657,8053,2845,10,4809,1208,2414,0,5660,1423,2841,10,604,4809,7202,0,819,5660,8053,10,2420,7203,2419,0,2847,8054,2846,10,1211,4807,7203,0,1426,5658,8054,10,7203,4806,1210,0,8054,5657,1425,10,4807,604,4806,0,5658,819,5657,10,7204,2421,29,0,8055,2848,69,10,4808,7204,2403,0,5659,8055,2830,10,4807,1211,2421,0,5658,1426,2848,10,604,4807,7204,0,819,5658,8055,10,2415,7205,2402,0,2842,8056,2829,10,1208,4809,7205,0,1423,5660,8056,10,7205,4808,1202,0,8056,5659,1417,10,4809,604,4808,0,5660,819,5659,10,7206,2408,0,0,8057,5228,10,10,4810,7206,2422,0,5661,8057,2849,10,4813,1205,2408,0,5664,2616,5228,10,605,4813,7206,0,820,5664,8057,10,2424,7207,2423,0,2851,8058,2850,10,1213,4811,7207,0,1428,5662,8058,10,7207,4810,1212,0,8058,5661,1427,10,4811,605,4810,0,5662,820,5661,10,7208,2425,13,0,8059,2852,29,10,4812,7208,2426,0,5663,8059,2853,10,4811,1213,2425,0,5662,1428,2852,10,605,4811,7208,0,820,5662,8059,10,2409,7209,2427,0,5227,8060,2854,10,1205,4813,7209,0,2616,5664,8060,10,7209,4812,1214,0,8060,5663,1429,10,4813,605,4812,0,5664,820,5663,10,7210,2424,31,0,8061,2851,71,10,4814,7210,2428,0,5665,8061,2855,10,4817,1213,2424,0,5668,1428,2851,10,606,4817,7210,0,821,5668,8061,10,2430,7211,2429,0,2857,8062,2856,10,1216,4815,7211,0,1431,5666,8062,10,7211,4814,1215,0,8062,5665,1430,10,4815,606,4814,0,5666,821,5665,10,7212,2431,38,0,8063,2858,54,10,4816,7212,2432,0,5667,8063,2859,10,4815,1216,2431,0,5666,1431,2858,10,606,4815,7212,0,821,5666,8063,10,2425,7213,2433,0,2852,8064,2860,10,1213,4817,7213,0,1428,5668,8064,10,7213,4816,1217,0,8064,5667,1432,10,4817,606,4816,0,5668,821,5667,10,7214,2439,7,0,8065,2866,19,10,4818,7214,2434,0,5669,8065,2861,10,4821,1220,2439,0,5672,1435,2866,10,607,4821,7214,0,822,5672,8065,10,2436,7215,2435,0,2863,8066,2862,10,1219,4819,7215,0,1434,5670,8066,10,7215,4818,1218,0,8066,5669,1433,10,4819,607,4818,0,5670,822,5669,10,7216,2437,13,0,8067,2864,29,10,4820,7216,2433,0,5671,8067,2860,10,4819,1219,2437,0,5670,1434,2864,10,607,4819,7216,0,822,5670,8067,10,2438,7217,2432,0,2865,8068,2859,10,1220,4821,7217,0,1435,5672,8068,10,7217,4820,1217,0,8068,5671,1432,10,4821,607,4820,0,5672,822,5671,10,7218,2436,28,0,8069,2863,68,10,4822,7218,2440,0,5673,8069,2867,10,4825,1219,2436,0,5676,1434,2863,10,608,4825,7218,0,823,5676,8069,10,2417,7219,2441,0,5231,8070,2868,10,1209,4823,7219,0,2618,5674,8070,10,7219,4822,1221,0,8070,5673,1436,10,4823,608,4822,0,5674,823,5673,10,7220,2416,30,0,8071,5232,70,10,4824,7220,2427,0,5675,8071,2854,10,4823,1209,2416,0,5674,2618,5232,10,608,4823,7220,0,823,5674,8071,10,2437,7221,2426,0,2864,8072,2853,10,1219,4825,7221,0,1434,5676,8072,10,7221,4824,1214,0,8072,5675,1429,10,4825,608,4824,0,5676,823,5675,10,7222,2447,4,0,8073,2874,12,10,4826,7222,2429,0,5677,8073,5239,10,4829,1224,2447,0,5680,1439,2874,10,609,4829,7222,0,824,5680,8073,10,2442,7223,2428,0,2869,8074,5240,10,1222,4827,7223,0,1437,5678,8074,10,7223,4826,1215,0,8074,5677,2622,10,4827,609,4826,0,5678,824,5677,10,7224,2443,14,0,8075,2870,30,10,4828,7224,2444,0,5679,8075,2871,10,4827,1222,2443,0,5678,1437,2870,10,609,4827,7224,0,824,5678,8075,10,2446,7225,2445,0,2873,8076,2872,10,1224,4829,7225,0,1439,5680,8076,10,7225,4828,1223,0,8076,5679,1438,10,4829,609,4828,0,5680,824,5679,10,7226,2442,31,0,8077,2869,47,10,4830,7226,2423,0,5681,8077,5237,10,4833,1222,2442,0,5684,1437,2869,10,610,4833,7226,0,825,5684,8077,10,2407,7227,2422,0,5225,8078,5238,10,1204,4831,7227,0,2615,5682,8078,10,7227,4830,1212,0,8078,5681,2621,10,4831,610,4830,0,5682,825,5681,10,7228,2406,25,0,8079,5226,41,10,4832,7228,2448,0,5683,8079,2875,10,4831,1204,2406,0,5682,2615,5226,10,610,4831,7228,0,825,5682,8079,10,2443,7229,2449,0,2870,8080,2876,10,1222,4833,7229,0,1437,5684,8080,10,7229,4832,1225,0,8080,5683,1440,10,4833,610,4832,0,5684,825,5683,10,7230,2398,1,0,8081,5222,1,10,4834,7230,2450,0,5685,8081,2877,10,4837,1200,2398,0,5688,2613,5222,10,611,4837,7230,0,826,5688,8081,10,2452,7231,2451,0,2879,8082,2878,10,1227,4835,7231,0,1442,5686,8082,10,7231,4834,1226,0,8082,5685,1441,10,4835,611,4834,0,5686,826,5685,10,7232,2453,14,0,8083,2880,30,10,4836,7232,2449,0,5687,8083,2876,10,4835,1227,2453,0,5686,1442,2880,10,611,4835,7232,0,826,5686,8083,10,2399,7233,2448,0,5221,8084,2875,10,1200,4837,7233,0,2613,5688,8084,10,7233,4836,1225,0,8084,5687,1440,10,4837,611,4836,0,5688,826,5687,10,7234,2452,26,0,8085,2879,42,10,4838,7234,2454,0,5689,8085,2881,10,4841,1227,2452,0,5692,1442,2879,10,612,4841,7234,0,827,5692,8085,10,2456,7235,2455,0,2883,8086,2882,10,1229,4839,7235,0,1444,5690,8086,10,7235,4838,1228,0,8086,5689,1443,10,4839,612,4838,0,5690,827,5689,10,7236,2457,35,0,8087,2884,51,10,4840,7236,2445,0,5691,8087,2872,10,4839,1229,2457,0,5690,1444,2884,10,612,4839,7236,0,827,5690,8087,10,2453,7237,2444,0,2880,8088,2871,10,1227,4841,7237,0,1442,5692,8088,10,7237,4840,1223,0,8088,5691,1438,10,4841,612,4840,0,5692,827,5691,10,7238,2465,6,0,8089,2892,16,10,4842,7238,2458,0,5693,8089,2885,10,4845,1233,2465,0,5696,1448,2892,10,613,4845,7238,0,828,5696,8089,10,2460,7239,2459,0,2887,8090,2886,10,1231,4843,7239,0,1446,5694,8090,10,7239,4842,1230,0,8090,5693,1445,10,4843,613,4842,0,5694,828,5693,10,7240,2461,15,0,8091,2888,31,10,4844,7240,2462,0,5695,8091,2889,10,4843,1231,2461,0,5694,1446,2888,10,613,4843,7240,0,828,5694,8091,10,2464,7241,2463,0,2891,8092,2890,10,1233,4845,7241,0,1448,5696,8092,10,7241,4844,1232,0,8092,5695,1447,10,4845,613,4844,0,5696,828,5695,10,7242,2460,33,0,8093,2887,49,10,4846,7242,2466,0,5697,8093,2893,10,4849,1231,2460,0,5700,1446,2887,10,614,4849,7242,0,829,5700,8093,10,2419,7243,2467,0,5233,8094,2894,10,1210,4847,7243,0,2619,5698,8094,10,7243,4846,1234,0,8094,5697,1449,10,4847,614,4846,0,5698,829,5697,10,7244,2418,27,0,8095,5234,43,10,4848,7244,2468,0,5699,8095,2895,10,4847,1210,2418,0,5698,2619,5234,10,614,4847,7244,0,829,5698,8095,10,2461,7245,2469,0,2888,8096,2896,10,1231,4849,7245,0,1446,5700,8096,10,7245,4848,1235,0,8096,5699,1450,10,4849,614,4848,0,5700,829,5699,10,7246,2412,2,0,8097,5230,2,10,4850,7246,2441,0,5701,8097,5243,10,4853,1207,2412,0,5704,2617,5230,10,615,4853,7246,0,830,5704,8097,10,2470,7247,2440,0,2897,8098,5244,10,1236,4851,7247,0,1451,5702,8098,10,7247,4850,1221,0,8098,5701,2624,10,4851,615,4850,0,5702,830,5701,10,7248,2471,15,0,8099,2898,31,10,4852,7248,2469,0,5703,8099,2896,10,4851,1236,2471,0,5702,1451,2898,10,615,4851,7248,0,830,5702,8099,10,2413,7249,2468,0,5229,8100,2895,10,1207,4853,7249,0,2617,5704,8100,10,7249,4852,1235,0,8100,5703,1450,10,4853,615,4852,0,5704,830,5703,10,7250,2470,28,0,8101,2897,44,10,4854,7250,2435,0,5705,8101,5241,10,4857,1236,2470,0,5708,1451,2897,10,616,4857,7250,0,831,5708,8101,10,2472,7251,2434,0,2899,8102,5242,10,1237,4855,7251,0,1452,5706,8102,10,7251,4854,1218,0,8102,5705,2623,10,4855,616,4854,0,5706,831,5705,10,7252,2473,36,0,8103,2900,52,10,4856,7252,2463,0,5707,8103,2890,10,4855,1237,2473,0,5706,1452,2900,10,616,4855,7252,0,831,5706,8103,10,2471,7253,2462,0,2898,8104,2889,10,1236,4857,7253,0,1451,5708,8104,10,7253,4856,1232,0,8104,5707,1447,10,4857,616,4856,0,5708,831,5707,10,7254,2479,5,0,8105,2906,15,10,4858,7254,2455,0,5709,8105,5247,10,4861,1240,2479,0,5712,1455,2906,10,617,4861,7254,0,832,5712,8105,10,2474,7255,2454,0,2901,8106,5248,10,1238,4859,7255,0,1453,5710,8106,10,7255,4858,1228,0,8106,5709,2626,10,4859,617,4858,0,5710,832,5709,10,7256,2475,16,0,8107,2902,32,10,4860,7256,2476,0,5711,8107,2903,10,4859,1238,2475,0,5710,1453,2902,10,617,4859,7256,0,832,5710,8107,10,2478,7257,2477,0,2905,8108,2904,10,1240,4861,7257,0,1455,5712,8108,10,7257,4860,1239,0,8108,5711,1454,10,4861,617,4860,0,5712,832,5711,10,7258,2474,26,0,8109,2901,66,10,4862,7258,2451,0,5713,8109,5245,10,4865,1238,2474,0,5716,1453,2901,10,618,4865,7258,0,833,5716,8109,10,2405,7259,2450,0,5223,8110,5246,10,1203,4863,7259,0,2614,5714,8110,10,7259,4862,1226,0,8110,5713,2625,10,4863,618,4862,0,5714,833,5713,10,7260,2404,29,0,8111,5224,45,10,4864,7260,2480,0,5715,8111,2907,10,4863,1203,2404,0,5714,2614,5224,10,618,4863,7260,0,833,5714,8111,10,2475,7261,2481,0,2902,8112,2908,10,1238,4865,7261,0,1453,5716,8112,10,7261,4864,1241,0,8112,5715,1456,10,4865,618,4864,0,5716,833,5715,10,7262,2420,3,0,8113,5236,5,10,4866,7262,2467,0,5717,8113,5251,10,4869,1211,2420,0,5720,2620,5236,10,619,4869,7262,0,834,5720,8113,10,2482,7263,2466,0,2909,8114,5252,10,1242,4867,7263,0,1457,5718,8114,10,7263,4866,1234,0,8114,5717,2628,10,4867,619,4866,0,5718,834,5717,10,7264,2483,16,0,8115,2910,32,10,4868,7264,2481,0,5719,8115,2908,10,4867,1242,2483,0,5718,1457,2910,10,619,4867,7264,0,834,5718,8115,10,2421,7265,2480,0,5235,8116,2907,10,1211,4869,7265,0,2620,5720,8116,10,7265,4868,1241,0,8116,5719,1456,10,4869,619,4868,0,5720,834,5719,10,7266,2482,33,0,8117,2909,73,10,4870,7266,2459,0,5721,8117,5249,10,4873,1242,2482,0,5724,1457,2909,10,620,4873,7266,0,835,5724,8117,10,2484,7267,2458,0,2911,8118,5250,10,1243,4871,7267,0,1458,5722,8118,10,7267,4870,1230,0,8118,5721,2627,10,4871,620,4870,0,5722,835,5721,10,7268,2485,37,0,8119,2912,53,10,4872,7268,2477,0,5723,8119,2904,10,4871,1243,2485,0,5722,1458,2912,10,620,4871,7268,0,835,5722,8119,10,2483,7269,2476,0,2910,8120,2903,10,1242,4873,7269,0,1457,5724,8120,10,7269,4872,1239,0,8120,5723,1454,10,4873,620,4872,0,5724,835,5723,10,7270,2430,4,0,8121,2857,13,10,4874,7270,2486,0,5725,8121,2913,10,4877,1216,2430,0,5728,1431,2857,10,621,4877,7270,0,836,5728,8121,10,2488,7271,2487,0,2915,8122,2914,10,1245,4875,7271,0,1460,5726,8122,10,7271,4874,1244,0,8122,5725,1459,10,4875,621,4874,0,5726,836,5725,10,7272,2489,17,0,8123,2916,33,10,4876,7272,2490,0,5727,8123,2917,10,4875,1245,2489,0,5726,1460,2916,10,621,4875,7272,0,836,5726,8123,10,2431,7273,2491,0,2858,8124,2918,10,1216,4877,7273,0,1431,5728,8124,10,7273,4876,1246,0,8124,5727,1461,10,4877,621,4876,0,5728,836,5727,10,7274,2488,43,0,8125,2915,79,10,4878,7274,2492,0,5729,8125,2919,10,4881,1245,2488,0,5732,1460,2915,10,622,4881,7274,0,837,5732,8125,10,2494,7275,2493,0,2921,8126,2920,10,1248,4879,7275,0,1463,5730,8126,10,7275,4878,1247,0,8126,5729,1462,10,4879,622,4878,0,5730,837,5729,10,7276,2495,45,0,8127,2922,61,10,4880,7276,2496,0,5731,8127,2923,10,4879,1248,2495,0,5730,1463,2922,10,622,4879,7276,0,837,5730,8127,10,2489,7277,2497,0,2916,8128,2924,10,1245,4881,7277,0,1460,5732,8128,10,7277,4880,1249,0,8128,5731,1464,10,4881,622,4880,0,5732,837,5731,10,7278,2503,9,0,8129,2930,23,10,4882,7278,2498,0,5733,8129,2925,10,4885,1252,2503,0,5736,1467,2930,10,623,4885,7278,0,838,5736,8129,10,2500,7279,2499,0,2927,8130,2926,10,1251,4883,7279,0,1466,5734,8130,10,7279,4882,1250,0,8130,5733,1465,10,4883,623,4882,0,5734,838,5733,10,7280,2501,17,0,8131,2928,33,10,4884,7280,2497,0,5735,8131,2924,10,4883,1251,2501,0,5734,1466,2928,10,623,4883,7280,0,838,5734,8131,10,2502,7281,2496,0,2929,8132,2923,10,1252,4885,7281,0,1467,5736,8132,10,7281,4884,1249,0,8132,5735,1464,10,4885,623,4884,0,5736,838,5735,10,7282,2500,34,0,8133,2927,74,10,4886,7282,2504,0,5737,8133,2931,10,4889,1251,2500,0,5740,1466,2927,10,624,4889,7282,0,839,5740,8133,10,2439,7283,2505,0,2866,8134,2932,10,1220,4887,7283,0,1435,5738,8134,10,7283,4886,1253,0,8134,5737,1468,10,4887,624,4886,0,5738,839,5737,10,7284,2438,38,0,8135,2865,54,10,4888,7284,2491,0,5739,8135,2918,10,4887,1220,2438,0,5738,1435,2865,10,624,4887,7284,0,839,5738,8135,10,2501,7285,2490,0,2928,8136,2917,10,1251,4889,7285,0,1466,5740,8136,10,7285,4888,1246,0,8136,5739,1461,10,4889,624,4888,0,5740,839,5739,10,7286,2507,39,0,8137,2934,55,10,4890,7286,2508,0,5741,8137,2935,10,4893,1254,2507,0,5744,1469,2934,10,625,4893,7286,0,840,5744,8137,10,2662,7287,2509,0,3089,8138,2936,10,1332,4891,7287,0,1547,5742,8138,10,7287,4890,1255,0,8138,5741,1470,10,4891,625,4890,0,5742,840,5741,10,7288,2663,68,0,8139,3090,110,10,4892,7288,2652,0,5743,8139,3079,10,4891,1332,2663,0,5742,1547,3090,10,625,4891,7288,0,840,5742,8139,10,2506,7289,2653,0,2933,8140,3080,10,1254,4893,7289,0,1469,5744,8140,10,7289,4892,1327,0,8140,5743,1542,10,4893,625,4892,0,5744,840,5743,10,7290,2519,8,0,8141,2946,20,10,4894,7290,2514,0,5745,8141,2941,10,4897,1260,2519,0,5748,1475,2946,10,626,4897,7290,0,841,5748,8141,10,2630,7291,2515,0,3057,8142,2942,10,1316,4895,7291,0,1531,5746,8142,10,7291,4894,1258,0,8142,5745,1473,10,4895,626,4894,0,5746,841,5745,10,7292,2631,57,0,8143,3058,93,10,4896,7292,2513,0,5747,8143,2940,10,4895,1316,2631,0,5746,1531,3058,10,626,4895,7292,0,841,5746,8143,10,2518,7293,2512,0,2945,8144,2939,10,1260,4897,7293,0,1475,5748,8144,10,7293,4896,1257,0,8144,5747,1472,10,4897,626,4896,0,5748,841,5747,10,7294,2521,40,0,8145,2948,56,10,4898,7294,2522,0,5749,8145,2949,10,4901,1261,2521,0,5752,1476,2948,10,627,4901,7294,0,842,5752,8145,10,2664,7295,2523,0,3091,8146,2950,10,1333,4899,7295,0,1548,5750,8146,10,7295,4898,1262,0,8146,5749,1477,10,4899,627,4898,0,5750,842,5749,10,7296,2665,70,0,8147,3092,113,10,4900,7296,2656,0,5751,8147,3083,10,4899,1333,2665,0,5750,1548,3092,10,627,4899,7296,0,842,5750,8147,10,2520,7297,2657,0,2947,8148,3084,10,1261,4901,7297,0,1476,5752,8148,10,7297,4900,1329,0,8148,5751,1544,10,4901,627,4900,0,5752,842,5751,10,7298,2533,9,0,8149,2960,22,10,4902,7298,2528,0,5753,8149,2955,10,4905,1267,2533,0,5756,1482,2960,10,628,4905,7298,0,843,5756,8149,10,2632,7299,2529,0,3059,8150,2956,10,1317,4903,7299,0,1532,5754,8150,10,7299,4902,1265,0,8150,5753,1480,10,4903,628,4902,0,5754,843,5753,10,7300,2633,59,0,8151,3060,96,10,4904,7300,2527,0,5755,8151,2954,10,4903,1317,2633,0,5754,1532,3060,10,628,4903,7300,0,843,5754,8151,10,2532,7301,2526,0,2959,8152,2953,10,1267,4905,7301,0,1482,5756,8152,10,7301,4904,1264,0,8152,5755,1479,10,4905,628,4904,0,5756,843,5755,10,7302,2535,41,0,8153,2962,77,10,4906,7302,2655,0,5757,8153,5297,10,4909,1268,2535,0,5760,1483,2962,10,629,4909,7302,0,844,5760,8153,10,2666,7303,2654,0,3093,8154,5298,10,1334,4907,7303,0,1549,5758,8154,10,7303,4906,1328,0,8154,5757,2651,10,4907,629,4906,0,5758,844,5757,10,7304,2667,72,0,8155,3094,116,10,4908,7304,2660,0,5759,8155,3087,10,4907,1334,2667,0,5758,1549,3094,10,629,4907,7304,0,844,5758,8155,10,2534,7305,2661,0,2961,8156,3088,10,1268,4909,7305,0,1483,5760,8156,10,7305,4908,1331,0,8156,5759,1546,10,4909,629,4908,0,5760,844,5759,10,7306,2543,11,0,8157,2970,27,10,4910,7306,2627,0,5761,8157,5291,10,4913,1272,2543,0,5764,1487,2970,10,630,4913,7306,0,845,5764,8157,10,2634,7307,2626,0,3061,8158,5292,10,1318,4911,7307,0,1533,5762,8158,10,7307,4910,1314,0,8158,5761,2648,10,4911,630,4910,0,5762,845,5761,10,7308,2635,61,0,8159,3062,99,10,4912,7308,2539,0,5763,8159,2966,10,4911,1318,2635,0,5762,1533,3062,10,630,4911,7308,0,845,5762,8159,10,2542,7309,2538,0,2969,8160,2965,10,1272,4913,7309,0,1487,5764,8160,10,7309,4912,1270,0,8160,5763,1485,10,4913,630,4912,0,5764,845,5763,10,7310,2494,10,0,8161,2921,25,10,4914,7310,2625,0,5765,8161,5289,10,4917,1248,2494,0,5768,1463,2921,10,631,4917,7310,0,846,5768,8161,10,2636,7311,2624,0,3063,8162,5290,10,1319,4915,7311,0,1534,5766,8162,10,7311,4914,1313,0,8162,5765,2647,10,4915,631,4914,0,5766,846,5765,10,7312,2637,64,0,8163,3064,104,10,4916,7312,2628,0,5767,8163,3055,10,4915,1319,2637,0,5766,1534,3064,10,631,4915,7312,0,846,5766,8163,10,2495,7313,2629,0,2922,8164,3056,10,1248,4917,7313,0,1463,5768,8164,10,7313,4916,1315,0,8164,5767,1530,10,4917,631,4916,0,5768,846,5767,10,7314,2549,42,0,8165,2976,78,10,4918,7314,2659,0,5769,8165,5299,10,4921,1275,2549,0,5772,1490,2976,10,632,4921,7314,0,847,5772,8165,10,2668,7315,2658,0,3095,8166,5300,10,1335,4919,7315,0,1550,5770,8166,10,7315,4918,1330,0,8166,5769,2652,10,4919,632,4918,0,5770,847,5769,10,7316,2669,67,0,8167,3096,109,10,4920,7316,2547,0,5771,8167,2974,10,4919,1335,2669,0,5770,1550,3096,10,632,4919,7316,0,847,5770,8167,10,2548,7317,2546,0,2975,8168,2973,10,1275,4921,7317,0,1490,5772,8168,10,7317,4920,1274,0,8168,5771,1489,10,4921,632,4920,0,5772,847,5771,10,7318,2510,10,0,8169,2937,24,10,4922,7318,2493,0,5773,8169,5255,10,4925,1256,2510,0,5776,1471,2937,10,633,4925,7318,0,848,5776,8169,10,2550,7319,2492,0,2977,8170,5256,10,1276,4923,7319,0,1491,5774,8170,10,7319,4922,1247,0,8170,5773,2630,10,4923,633,4922,0,5774,848,5773,10,7320,2551,22,0,8171,2978,38,10,4924,7320,2552,0,5775,8171,2979,10,4923,1276,2551,0,5774,1491,2978,10,633,4923,7320,0,848,5774,8171,10,2511,7321,2553,0,2938,8172,2980,10,1256,4925,7321,0,1471,5776,8172,10,7321,4924,1277,0,8172,5775,1492,10,4925,633,4924,0,5776,848,5775,10,7322,2550,43,0,8173,2977,59,10,4926,7322,2487,0,5777,8173,5253,10,4929,1276,2550,0,5780,1491,2977,10,634,4929,7322,0,849,5780,8173,10,2447,7323,2486,0,2874,8174,5254,10,1224,4927,7323,0,1439,5778,8174,10,7323,4926,1244,0,8174,5777,2629,10,4927,634,4926,0,5778,849,5777,10,7324,2446,35,0,8175,2873,51,10,4928,7324,2554,0,5779,8175,2981,10,4927,1224,2446,0,5778,1439,2873,10,634,4927,7324,0,849,5778,8175,10,2551,7325,2555,0,2978,8176,2982,10,1276,4929,7325,0,1491,5780,8176,10,7325,4928,1278,0,8176,5779,1493,10,4929,634,4928,0,5780,849,5779,10,7326,2456,5,0,8177,2883,14,10,4930,7326,2556,0,5781,8177,2983,10,4933,1229,2456,0,5784,1444,2883,10,635,4933,7326,0,850,5784,8177,10,2558,7327,2557,0,2985,8178,2984,10,1280,4931,7327,0,1495,5782,8178,10,7327,4930,1279,0,8178,5781,1494,10,4931,635,4930,0,5782,850,5781,10,7328,2559,22,0,8179,2986,38,10,4932,7328,2555,0,5783,8179,2982,10,4931,1280,2559,0,5782,1495,2986,10,635,4931,7328,0,850,5782,8179,10,2457,7329,2554,0,2884,8180,2981,10,1229,4933,7329,0,1444,5784,8180,10,7329,4932,1278,0,8180,5783,1493,10,4933,635,4932,0,5784,850,5783,10,7330,2558,32,0,8181,2985,48,10,4934,7330,2560,0,5785,8181,2987,10,4937,1280,2558,0,5788,1495,2985,10,636,4937,7330,0,851,5788,8181,10,2519,7331,2561,0,2946,8182,2988,10,1260,4935,7331,0,1475,5786,8182,10,7331,4934,1281,0,8182,5785,1496,10,4935,636,4934,0,5786,851,5785,10,7332,2518,46,0,8183,2945,62,10,4936,7332,2553,0,5787,8183,2980,10,4935,1260,2518,0,5786,1475,2945,10,636,4935,7332,0,851,5786,8183,10,2559,7333,2552,0,2986,8184,2979,10,1280,4937,7333,0,1495,5788,8184,10,7333,4936,1277,0,8184,5787,1492,10,4937,636,4936,0,5788,851,5787,10,7334,2524,11,0,8185,2951,26,10,4938,7334,2562,0,5789,8185,2989,10,4941,1263,2524,0,5792,1478,2951,10,637,4941,7334,0,852,5792,8185,10,2564,7335,2563,0,2991,8186,2990,10,1283,4939,7335,0,1498,5790,8186,10,7335,4938,1282,0,8186,5789,1497,10,4939,637,4938,0,5790,852,5789,10,7336,2565,23,0,8187,2992,39,10,4940,7336,2566,0,5791,8187,2993,10,4939,1283,2565,0,5790,1498,2992,10,637,4939,7336,0,852,5790,8187,10,2525,7337,2567,0,2952,8188,2994,10,1263,4941,7337,0,1478,5792,8188,10,7337,4940,1284,0,8188,5791,1499,10,4941,637,4940,0,5792,852,5791,10,7338,2564,44,0,8189,2991,60,10,4942,7338,2568,0,5793,8189,2995,10,4945,1283,2564,0,5796,1498,2991,10,638,4945,7338,0,853,5796,8189,10,2465,7339,2569,0,2892,8190,2996,10,1233,4943,7339,0,1448,5794,8190,10,7339,4942,1285,0,8190,5793,1500,10,4943,638,4942,0,5794,853,5793,10,7340,2464,36,0,8191,2891,52,10,4944,7340,2570,0,5795,8191,2997,10,4943,1233,2464,0,5794,1448,2891,10,638,4943,7340,0,853,5794,8191,10,2565,7341,2571,0,2992,8192,2998,10,1283,4945,7341,0,1498,5796,8192,10,7341,4944,1286,0,8192,5795,1501,10,4945,638,4944,0,5796,853,5795,10,7342,2472,7,0,8193,2899,18,10,4946,7342,2505,0,5797,8193,5259,10,4949,1237,2472,0,5800,1452,2899,10,639,4949,7342,0,854,5800,8193,10,2572,7343,2504,0,2999,8194,5260,10,1287,4947,7343,0,1502,5798,8194,10,7343,4946,1253,0,8194,5797,2632,10,4947,639,4946,0,5798,854,5797,10,7344,2573,23,0,8195,3000,39,10,4948,7344,2571,0,5799,8195,2998,10,4947,1287,2573,0,5798,1502,3000,10,639,4947,7344,0,854,5798,8195,10,2473,7345,2570,0,2900,8196,2997,10,1237,4949,7345,0,1452,5800,8196,10,7345,4948,1286,0,8196,5799,1501,10,4949,639,4948,0,5800,854,5799,10,7346,2572,34,0,8197,2999,50,10,4950,7346,2499,0,5801,8197,5257,10,4953,1287,2572,0,5804,1502,2999,10,640,4953,7346,0,855,5804,8197,10,2533,7347,2498,0,2960,8198,5258,10,1267,4951,7347,0,1482,5802,8198,10,7347,4950,1250,0,8198,5801,2631,10,4951,640,4950,0,5802,855,5801,10,7348,2532,47,0,8199,2959,63,10,4952,7348,2567,0,5803,8199,2994,10,4951,1267,2532,0,5802,1482,2959,10,640,4951,7348,0,855,5802,8199,10,2573,7349,2566,0,3000,8200,2993,10,1287,4953,7349,0,1502,5804,8200,10,7349,4952,1284,0,8200,5803,1499,10,4953,640,4952,0,5804,855,5803,10,7350,2536,8,0,8201,2963,21,10,4954,7350,2561,0,5805,8201,5271,10,4957,1269,2536,0,5808,1484,2963,10,641,4957,7350,0,856,5808,8201,10,2574,7351,2560,0,3001,8202,5272,10,1288,4955,7351,0,1503,5806,8202,10,7351,4954,1281,0,8202,5805,2638,10,4955,641,4954,0,5806,856,5805,10,7352,2575,24,0,8203,3002,40,10,4956,7352,2576,0,5807,8203,3003,10,4955,1288,2575,0,5806,1503,3002,10,641,4955,7352,0,856,5806,8203,10,2537,7353,2577,0,2964,8204,3004,10,1269,4957,7353,0,1484,5808,8204,10,7353,4956,1289,0,8204,5807,1504,10,4957,641,4956,0,5808,856,5807,10,7354,2574,32,0,8205,3001,72,10,4958,7354,2557,0,5809,8205,5269,10,4961,1288,2574,0,5812,1503,3001,10,642,4961,7354,0,857,5812,8205,10,2479,7355,2556,0,2906,8206,5270,10,1240,4959,7355,0,1455,5810,8206,10,7355,4958,1279,0,8206,5809,2637,10,4959,642,4958,0,5810,857,5809,10,7356,2478,37,0,8207,2905,53,10,4960,7356,2578,0,5811,8207,3005,10,4959,1240,2478,0,5810,1455,2905,10,642,4959,7356,0,857,5810,8207,10,2575,7357,2579,0,3002,8208,3006,10,1288,4961,7357,0,1503,5812,8208,10,7357,4960,1290,0,8208,5811,1505,10,4961,642,4960,0,5812,857,5811,10,7358,2484,6,0,8209,2911,17,10,4962,7358,2569,0,5813,8209,5275,10,4965,1243,2484,0,5816,1458,2911,10,643,4965,7358,0,858,5816,8209,10,2580,7359,2568,0,3007,8210,5276,10,1291,4963,7359,0,1506,5814,8210,10,7359,4962,1285,0,8210,5813,2640,10,4963,643,4962,0,5814,858,5813,10,7360,2581,24,0,8211,3008,40,10,4964,7360,2579,0,5815,8211,3006,10,4963,1291,2581,0,5814,1506,3008,10,643,4963,7360,0,858,5814,8211,10,2485,7361,2578,0,2912,8212,3005,10,1243,4965,7361,0,1458,5816,8212,10,7361,4964,1290,0,8212,5815,1505,10,4965,643,4964,0,5816,858,5815,10,7362,2580,44,0,8213,3007,80,10,4966,7362,2563,0,5817,8213,5273,10,4969,1291,2580,0,5820,1506,3007,10,644,4969,7362,0,859,5820,8213,10,2543,7363,2562,0,2970,8214,5274,10,1272,4967,7363,0,1487,5818,8214,10,7363,4966,1282,0,8214,5817,2639,10,4967,644,4966,0,5818,859,5817,10,7364,2542,48,0,8215,2969,64,10,4968,7364,2577,0,5819,8215,3004,10,4967,1272,2542,0,5818,1487,2969,10,644,4967,7364,0,859,5818,8215,10,2581,7365,2576,0,3008,8216,3003,10,1291,4969,7365,0,1506,5820,8216,10,7365,4968,1289,0,8216,5819,1504,10,4969,644,4968,0,5820,859,5819,10,7366,2598,49,0,8217,3025,81,10,4970,7366,2582,0,5821,8217,3009,10,4973,1300,2598,0,5824,1515,3025,10,645,4973,7366,0,860,5824,8217,10,2638,7367,2583,0,3065,8218,3010,10,1320,4971,7367,0,1535,5822,8218,10,7367,4970,1292,0,8218,5821,1507,10,4971,645,4970,0,5822,860,5821,10,7368,2639,57,0,8219,3066,93,10,4972,7368,2614,0,5823,8219,3041,10,4971,1320,2639,0,5822,1535,3066,10,645,4971,7368,0,860,5822,8219,10,2599,7369,2615,0,3026,8220,3042,10,1300,4973,7369,0,1515,5824,8220,10,7369,4972,1308,0,8220,5823,1523,10,4973,645,4972,0,5824,860,5823,10,7370,2600,51,0,8221,3027,84,10,4974,7370,2586,0,5825,8221,3013,10,4977,1301,2600,0,5828,1516,3027,10,646,4977,7370,0,861,5828,8221,10,2670,7371,2587,0,3097,8222,3014,10,1336,4975,7371,0,1551,5826,8222,10,7371,4974,1294,0,8222,5825,1509,10,4975,646,4974,0,5826,861,5825,10,7372,2671,68,0,8223,3098,110,10,4976,7372,2585,0,5827,8223,3012,10,4975,1336,2671,0,5826,1551,3098,10,646,4975,7372,0,861,5826,8223,10,2601,7373,2584,0,3028,8224,3011,10,1301,4977,7373,0,1516,5828,8224,10,7373,4976,1293,0,8224,5827,1508,10,4977,646,4976,0,5828,861,5827,10,7374,2602,52,0,8225,3029,86,10,4978,7374,2588,0,5829,8225,3015,10,4981,1302,2602,0,5832,1517,3029,10,647,4981,7374,0,862,5832,8225,10,2640,7375,2589,0,3067,8226,3016,10,1321,4979,7375,0,1536,5830,8226,10,7375,4978,1295,0,8226,5829,1510,10,4979,647,4978,0,5830,862,5829,10,7376,2641,59,0,8227,3068,96,10,4980,7376,2618,0,5831,8227,3045,10,4979,1321,2641,0,5830,1536,3068,10,647,4979,7376,0,862,5830,8227,10,2603,7377,2619,0,3030,8228,3046,10,1302,4981,7377,0,1517,5832,8228,10,7377,4980,1310,0,8228,5831,1525,10,4981,647,4980,0,5832,862,5831,10,7378,2604,54,0,8229,3031,89,10,4982,7378,2592,0,5833,8229,3019,10,4985,1303,2604,0,5836,1518,3031,10,648,4985,7378,0,863,5836,8229,10,2672,7379,2593,0,3099,8230,3020,10,1337,4983,7379,0,1552,5834,8230,10,7379,4982,1297,0,8230,5833,1512,10,4983,648,4982,0,5834,863,5833,10,7380,2673,70,0,8231,3100,113,10,4984,7380,2591,0,5835,8231,3018,10,4983,1337,2673,0,5834,1552,3100,10,648,4983,7380,0,863,5834,8231,10,2605,7381,2590,0,3032,8232,3017,10,1303,4985,7381,0,1518,5836,8232,10,7381,4984,1296,0,8232,5835,1511,10,4985,648,4984,0,5836,863,5835,10,7382,2606,51,0,8233,3033,85,10,4986,7382,2617,0,5837,8233,5285,10,4989,1304,2606,0,5840,1519,3033,10,649,4989,7382,0,864,5840,8233,10,2642,7383,2616,0,3069,8234,5286,10,1322,4987,7383,0,1537,5838,8234,10,7383,4986,1309,0,8234,5837,2645,10,4987,649,4986,0,5838,864,5837,10,7384,2643,61,0,8235,3070,99,10,4988,7384,2622,0,5839,8235,3049,10,4987,1322,2643,0,5838,1537,3070,10,649,4987,7384,0,864,5838,8235,10,2607,7385,2623,0,3034,8236,3050,10,1304,4989,7385,0,1519,5840,8236,10,7385,4988,1312,0,8236,5839,1527,10,4989,649,4988,0,5840,864,5839,10,7386,2608,52,0,8237,3035,87,10,4990,7386,2649,0,5841,8237,5295,10,4993,1305,2608,0,5844,1520,3035,10,650,4993,7386,0,865,5844,8237,10,2674,7387,2648,0,3101,8238,5296,10,1338,4991,7387,0,1553,5842,8238,10,7387,4990,1325,0,8238,5841,2650,10,4991,650,4990,0,5842,865,5841,10,7388,2675,72,0,8239,3102,116,10,4992,7388,2595,0,5843,8239,3022,10,4991,1338,2675,0,5842,1553,3102,10,650,4991,7388,0,865,5842,8239,10,2609,7389,2594,0,3036,8240,3021,10,1305,4993,7389,0,1520,5844,8240,10,7389,4992,1298,0,8240,5843,1513,10,4993,650,4992,0,5844,865,5843,10,7390,2610,49,0,8241,3037,82,10,4994,7390,2647,0,5845,8241,5293,10,4997,1306,2610,0,5848,1521,3037,10,651,4997,7390,0,866,5848,8241,10,2676,7391,2646,0,3103,8242,5294,10,1339,4995,7391,0,1554,5846,8242,10,7391,4994,1324,0,8242,5845,2649,10,4995,651,4994,0,5846,866,5845,10,7392,2677,67,0,8243,3104,109,10,4996,7392,2650,0,5847,8243,3077,10,4995,1339,2677,0,5846,1554,3104,10,651,4995,7392,0,866,5846,8243,10,2611,7393,2651,0,3038,8244,3078,10,1306,4997,7393,0,1521,5848,8244,10,7393,4996,1326,0,8244,5847,1541,10,4997,651,4996,0,5848,866,5847,10,7394,2612,54,0,8245,3039,90,10,4998,7394,2621,0,5849,8245,5287,10,5001,1307,2612,0,5852,1522,3039,10,652,5001,7394,0,867,5852,8245,10,2644,7395,2620,0,3071,8246,5288,10,1323,4999,7395,0,1538,5850,8246,10,7395,4998,1311,0,8246,5849,2646,10,4999,652,4998,0,5850,867,5849,10,7396,2645,64,0,8247,3072,104,10,5000,7396,2597,0,5851,8247,3024,10,4999,1323,2645,0,5850,1538,3072,10,652,4999,7396,0,867,5850,8247,10,2613,7397,2596,0,3040,8248,3023,10,1307,5001,7397,0,1522,5852,8248,10,7397,5000,1299,0,8248,5851,1514,10,5001,652,5000,0,5852,867,5851,10,7398,2630,58,0,8249,3057,94,10,5002,7398,2616,0,5853,8249,3043,10,5005,1316,2630,0,5856,1531,3057,10,653,5005,7398,0,868,5856,8249,10,2600,7399,2617,0,3027,8250,3044,10,1301,5003,7399,0,1516,5854,8250,10,7399,5002,1309,0,8250,5853,1524,10,5003,653,5002,0,5854,868,5853,10,7400,2601,50,0,8251,3028,83,10,5004,7400,2615,0,5855,8251,3042,10,5003,1301,2601,0,5854,1516,3028,10,653,5003,7400,0,868,5854,8251,10,2631,7401,2614,0,3058,8252,3041,10,1316,5005,7401,0,1531,5856,8252,10,7401,5004,1308,0,8252,5855,1523,10,5005,653,5004,0,5856,868,5855,10,7402,2632,60,0,8253,3059,97,10,5006,7402,2620,0,5857,8253,3047,10,5009,1317,2632,0,5860,1532,3059,10,654,5009,7402,0,869,5860,8253,10,2604,7403,2621,0,3031,8254,3048,10,1303,5007,7403,0,1518,5858,8254,10,7403,5006,1311,0,8254,5857,1526,10,5007,654,5006,0,5858,869,5857,10,7404,2605,53,0,8255,3032,88,10,5008,7404,2619,0,5859,8255,3046,10,5007,1303,2605,0,5858,1518,3032,10,654,5007,7404,0,869,5858,8255,10,2633,7405,2618,0,3060,8256,3045,10,1317,5009,7405,0,1532,5860,8256,10,7405,5008,1310,0,8256,5859,1525,10,5009,654,5008,0,5860,869,5859,10,7406,2634,63,0,8257,3061,103,10,5010,7406,2589,0,5861,8257,5281,10,5013,1318,2634,0,5864,1533,3061,10,655,5013,7406,0,870,5864,8257,10,2608,7407,2588,0,3035,8258,5282,10,1305,5011,7407,0,1520,5862,8258,10,7407,5010,1295,0,8258,5861,2643,10,5011,655,5010,0,5862,870,5861,10,7408,2609,55,0,8259,3036,91,10,5012,7408,2623,0,5863,8259,3050,10,5011,1305,2609,0,5862,1520,3036,10,655,5011,7408,0,870,5862,8259,10,2635,7409,2622,0,3062,8260,3049,10,1318,5013,7409,0,1533,5864,8260,10,7409,5012,1312,0,8260,5863,1527,10,5013,655,5012,0,5864,870,5863,10,7410,2636,62,0,8261,3063,101,10,5014,7410,2583,0,5865,8261,5277,10,5017,1319,2636,0,5868,1534,3063,10,656,5017,7410,0,871,5868,8261,10,2610,7411,2582,0,3037,8262,5278,10,1306,5015,7411,0,1521,5866,8262,10,7411,5014,1292,0,8262,5865,2641,10,5015,656,5014,0,5866,871,5865,10,7412,2611,56,0,8263,3038,92,10,5016,7412,2596,0,5867,8263,3023,10,5015,1306,2611,0,5866,1521,3038,10,656,5015,7412,0,871,5866,8263,10,2637,7413,2597,0,3064,8264,3024,10,1319,5017,7413,0,1534,5868,8264,10,7413,5016,1299,0,8264,5867,1514,10,5017,656,5016,0,5868,871,5867,10,7414,2638,62,0,8265,3065,100,10,5018,7414,2624,0,5869,8265,3051,10,5021,1320,2638,0,5872,1535,3065,10,657,5021,7414,0,872,5872,8265,10,2510,7415,2625,0,2937,8266,3052,10,1256,5019,7415,0,1471,5870,8266,10,7415,5018,1313,0,8266,5869,1528,10,5019,657,5018,0,5870,872,5869,10,7416,2511,46,0,8267,2938,62,10,5020,7416,2512,0,5871,8267,2939,10,5019,1256,2511,0,5870,1471,2938,10,657,5019,7416,0,872,5870,8267,10,2639,7417,2513,0,3066,8268,2940,10,1320,5021,7417,0,1535,5872,8268,10,7417,5020,1257,0,8268,5871,1472,10,5021,657,5020,0,5872,872,5871,10,7418,2640,63,0,8269,3067,102,10,5022,7418,2626,0,5873,8269,3053,10,5025,1321,2640,0,5876,1536,3067,10,658,5025,7418,0,873,5876,8269,10,2524,7419,2627,0,2951,8270,3054,10,1263,5023,7419,0,1478,5874,8270,10,7419,5022,1314,0,8270,5873,1529,10,5023,658,5022,0,5874,873,5873,10,7420,2525,47,0,8271,2952,63,10,5024,7420,2526,0,5875,8271,2953,10,5023,1263,2525,0,5874,1478,2952,10,658,5023,7420,0,873,5874,8271,10,2641,7421,2527,0,3068,8272,2954,10,1321,5025,7421,0,1536,5876,8272,10,7421,5024,1264,0,8272,5875,1479,10,5025,658,5024,0,5876,873,5875,10,7422,2642,58,0,8273,3069,95,10,5026,7422,2515,0,5877,8273,5263,10,5029,1322,2642,0,5880,1537,3069,10,659,5029,7422,0,874,5880,8273,10,2536,7423,2514,0,2963,8274,5264,10,1269,5027,7423,0,1484,5878,8274,10,7423,5026,1258,0,8274,5877,2634,10,5027,659,5026,0,5878,874,5877,10,7424,2537,48,0,8275,2964,64,10,5028,7424,2538,0,5879,8275,2965,10,5027,1269,2537,0,5878,1484,2964,10,659,5027,7424,0,874,5878,8275,10,2643,7425,2539,0,3070,8276,2966,10,1322,5029,7425,0,1537,5880,8276,10,7425,5028,1270,0,8276,5879,1485,10,5029,659,5028,0,5880,874,5879,10,7426,2644,60,0,8277,3071,98,10,5030,7426,2529,0,5881,8277,5267,10,5033,1323,2644,0,5884,1538,3071,10,660,5033,7426,0,875,5884,8277,10,2503,7427,2528,0,2930,8278,5268,10,1252,5031,7427,0,1467,5882,8278,10,7427,5030,1265,0,8278,5881,2636,10,5031,660,5030,0,5882,875,5881,10,7428,2502,45,0,8279,2929,61,10,5032,7428,2629,0,5883,8279,3056,10,5031,1252,2502,0,5882,1467,2929,10,660,5031,7428,0,875,5882,8279,10,2645,7429,2628,0,3072,8280,3055,10,1323,5033,7429,0,1538,5884,8280,10,7429,5032,1315,0,8280,5883,1530,10,5033,660,5032,0,5884,875,5883,10,7430,2662,65,0,8281,3089,105,10,5034,7430,2646,0,5885,8281,3073,10,5037,1332,2662,0,5888,1547,3089,10,661,5037,7430,0,876,5888,8281,10,2598,7431,2647,0,3025,8282,3074,10,1300,5035,7431,0,1515,5886,8282,10,7431,5034,1324,0,8282,5885,1539,10,5035,661,5034,0,5886,876,5885,10,7432,2599,50,0,8283,3026,83,10,5036,7432,2584,0,5887,8283,3011,10,5035,1300,2599,0,5886,1515,3026,10,661,5035,7432,0,876,5886,8283,10,2663,7433,2585,0,3090,8284,3012,10,1332,5037,7433,0,1547,5888,8284,10,7433,5036,1293,0,8284,5887,1508,10,5037,661,5036,0,5888,876,5887,10,7434,2664,66,0,8285,3091,107,10,5038,7434,2648,0,5889,8285,3075,10,5041,1333,2664,0,5892,1548,3091,10,662,5041,7434,0,877,5892,8285,10,2602,7435,2649,0,3029,8286,3076,10,1302,5039,7435,0,1517,5890,8286,10,7435,5038,1325,0,8286,5889,1540,10,5039,662,5038,0,5890,877,5889,10,7436,2603,53,0,8287,3030,88,10,5040,7436,2590,0,5891,8287,3017,10,5039,1302,2603,0,5890,1517,3030,10,662,5039,7436,0,877,5890,8287,10,2665,7437,2591,0,3092,8288,3018,10,1333,5041,7437,0,1548,5892,8288,10,7437,5040,1296,0,8288,5891,1511,10,5041,662,5040,0,5892,877,5891,10,7438,2666,69,0,8289,3093,112,10,5042,7438,2587,0,5893,8289,5279,10,5045,1334,2666,0,5896,1549,3093,10,663,5045,7438,0,878,5896,8289,10,2606,7439,2586,0,3033,8290,5280,10,1304,5043,7439,0,1519,5894,8290,10,7439,5042,1294,0,8290,5893,2642,10,5043,663,5042,0,5894,878,5893,10,7440,2607,55,0,8291,3034,91,10,5044,7440,2594,0,5895,8291,3021,10,5043,1304,2607,0,5894,1519,3034,10,663,5043,7440,0,878,5894,8291,10,2667,7441,2595,0,3094,8292,3022,10,1334,5045,7441,0,1549,5896,8292,10,7441,5044,1298,0,8292,5895,1513,10,5045,663,5044,0,5896,878,5895,10,7442,2668,71,0,8293,3095,115,10,5046,7442,2593,0,5897,8293,5283,10,5049,1335,2668,0,5900,1550,3095,10,664,5049,7442,0,879,5900,8293,10,2612,7443,2592,0,3039,8294,5284,10,1307,5047,7443,0,1522,5898,8294,10,7443,5046,1297,0,8294,5897,2644,10,5047,664,5046,0,5898,879,5897,10,7444,2613,56,0,8295,3040,92,10,5048,7444,2651,0,5899,8295,3078,10,5047,1307,2613,0,5898,1522,3040,10,664,5047,7444,0,879,5898,8295,10,2669,7445,2650,0,3096,8296,3077,10,1335,5049,7445,0,1550,5900,8296,10,7445,5048,1326,0,8296,5899,1541,10,5049,664,5048,0,5900,879,5899,10,7446,2670,69,0,8297,3097,111,10,5050,7446,2654,0,5901,8297,3081,10,5053,1336,2670,0,5904,1551,3097,10,665,5053,7446,0,880,5904,8297,10,2516,7447,2655,0,2943,8298,3082,10,1259,5051,7447,0,1474,5902,8298,10,7447,5050,1328,0,8298,5901,1543,10,5051,665,5050,0,5902,880,5901,10,7448,2517,18,0,8299,2944,34,10,5052,7448,2653,0,5903,8299,3080,10,5051,1259,2517,0,5902,1474,2944,10,665,5051,7448,0,880,5902,8299,10,2671,7449,2652,0,3098,8300,3079,10,1336,5053,7449,0,1551,5904,8300,10,7449,5052,1327,0,8300,5903,1542,10,5053,665,5052,0,5904,880,5903,10,7450,2672,71,0,8301,3099,114,10,5054,7450,2658,0,5905,8301,3085,10,5057,1337,2672,0,5908,1552,3099,10,666,5057,7450,0,881,5908,8301,10,2530,7451,2659,0,2957,8302,3086,10,1266,5055,7451,0,1481,5906,8302,10,7451,5054,1330,0,8302,5905,1545,10,5055,666,5054,0,5906,881,5905,10,7452,2531,19,0,8303,2958,35,10,5056,7452,2657,0,5907,8303,3084,10,5055,1266,2531,0,5906,1481,2958,10,666,5055,7452,0,881,5906,8303,10,2673,7453,2656,0,3100,8304,3083,10,1337,5057,7453,0,1552,5908,8304,10,7453,5056,1329,0,8304,5907,1544,10,5057,666,5056,0,5908,881,5907,10,7454,2674,66,0,8305,3101,108,10,5058,7454,2523,0,5909,8305,5265,10,5061,1338,2674,0,5912,1553,3101,10,667,5061,7454,0,882,5912,8305,10,2540,7455,2522,0,2967,8306,5266,10,1271,5059,7455,0,1486,5910,8306,10,7455,5058,1262,0,8306,5909,2635,10,5059,667,5058,0,5910,882,5909,10,7456,2541,20,0,8307,2968,36,10,5060,7456,2661,0,5911,8307,3088,10,5059,1271,2541,0,5910,1486,2968,10,667,5059,7456,0,882,5910,8307,10,2675,7457,2660,0,3102,8308,3087,10,1338,5061,7457,0,1553,5912,8308,10,7457,5060,1331,0,8308,5911,1546,10,5061,667,5060,0,5912,882,5911,10,7458,2676,65,0,8309,3103,106,10,5062,7458,2509,0,5913,8309,5261,10,5065,1339,2676,0,5916,1554,3103,10,668,5065,7458,0,883,5916,8309,10,2544,7459,2508,0,2971,8310,5262,10,1273,5063,7459,0,1488,5914,8310,10,7459,5062,1255,0,8310,5913,2633,10,5063,668,5062,0,5914,883,5913,10,7460,2545,21,0,8311,2972,37,10,5064,7460,2546,0,5915,8311,2973,10,5063,1273,2545,0,5914,1488,2972,10,668,5063,7460,0,883,5914,8311,10,2677,7461,2547,0,3104,8312,2974,10,1339,5065,7461,0,1554,5916,8312,10,7461,5064,1274,0,8312,5915,1489,10,5065,668,5064,0,5916,883,5915,10,7462,2685,74,0,8313,3112,123,10,5066,7462,2678,0,5917,8313,3105,10,5069,1343,2685,0,5920,1558,3112,10,669,5069,7462,0,884,5920,8313,10,2680,7463,2679,0,3107,8314,3106,10,1341,5067,7463,0,1556,5918,8314,10,7463,5066,1340,0,8314,5917,1555,10,5067,669,5066,0,5918,884,5917,10,7464,2681,81,0,8315,3108,137,10,5068,7464,2682,0,5919,8315,3109,10,5067,1341,2681,0,5918,1556,3108,10,669,5067,7464,0,884,5918,8315,10,2684,7465,2683,0,3111,8316,3110,10,1343,5069,7465,0,1558,5920,8316,10,7465,5068,1342,0,8316,5919,1557,10,5069,669,5068,0,5920,884,5919,10,7466,2680,86,0,8317,3107,154,10,5070,7466,2686,0,5921,8317,3113,10,5073,1341,2680,0,5924,1556,3107,10,670,5073,7466,0,885,5924,8317,10,2688,7467,2687,0,3115,8318,3114,10,1345,5071,7467,0,1560,5922,8318,10,7467,5070,1344,0,8318,5921,1559,10,5071,670,5070,0,5922,885,5921,10,7468,2689,91,0,8319,3116,147,10,5072,7468,2690,0,5923,8319,3117,10,5071,1345,2689,0,5922,1560,3116,10,670,5071,7468,0,885,5922,8319,10,2681,7469,2691,0,3108,8320,3118,10,1341,5073,7469,0,1556,5924,8320,10,7469,5072,1346,0,8320,5923,1561,10,5073,670,5072,0,5924,885,5923,10,7470,2697,75,0,8321,3124,126,10,5074,7470,2692,0,5925,8321,3119,10,5077,1349,2697,0,5928,1564,3124,10,671,5077,7470,0,886,5928,8321,10,2694,7471,2693,0,3121,8322,3120,10,1348,5075,7471,0,1563,5926,8322,10,7471,5074,1347,0,8322,5925,1562,10,5075,671,5074,0,5926,886,5925,10,7472,2695,81,0,8323,3122,137,10,5076,7472,2691,0,5927,8323,3118,10,5075,1348,2695,0,5926,1563,3122,10,671,5075,7472,0,886,5926,8323,10,2696,7473,2690,0,3123,8324,3117,10,1349,5077,7473,0,1564,5928,8324,10,7473,5076,1346,0,8324,5927,1561,10,5077,671,5076,0,5928,886,5927,10,7474,2694,88,0,8325,3121,156,10,5078,7474,2698,0,5929,8325,3125,10,5081,1348,2694,0,5932,1563,3121,10,672,5081,7474,0,887,5932,8325,10,2700,7475,2699,0,3127,8326,3126,10,1351,5079,7475,0,1566,5930,8326,10,7475,5078,1350,0,8326,5929,1565,10,5079,672,5078,0,5930,887,5929,10,7476,2701,90,0,8327,3128,158,10,5080,7476,2683,0,5931,8327,3110,10,5079,1351,2701,0,5930,1566,3128,10,672,5079,7476,0,887,5930,8327,10,2695,7477,2682,0,3122,8328,3109,10,1348,5081,7477,0,1563,5932,8328,10,7477,5080,1342,0,8328,5931,1557,10,5081,672,5080,0,5932,887,5931,10,7478,2688,73,0,8329,5308,127,10,5082,7478,2702,0,5933,8329,3129,10,5085,1345,2688,0,5936,2656,5308,10,673,5085,7478,0,888,5936,8329,10,2704,7479,2703,0,3131,8330,3130,10,1353,5083,7479,0,1568,5934,8330,10,7479,5082,1352,0,8330,5933,1567,10,5083,673,5082,0,5934,888,5933,10,7480,2705,82,0,8331,3132,138,10,5084,7480,2706,0,5935,8331,3133,10,5083,1353,2705,0,5934,1568,3132,10,673,5083,7480,0,888,5934,8331,10,2689,7481,2707,0,5307,8332,3134,10,1345,5085,7481,0,2656,5936,8332,10,7481,5084,1354,0,8332,5935,1569,10,5085,673,5084,0,5936,888,5935,10,7482,2704,92,0,8333,3131,160,10,5086,7482,2708,0,5937,8333,3135,10,5089,1353,2704,0,5940,1568,3131,10,674,5089,7482,0,889,5940,8333,10,2710,7483,2709,0,3137,8334,3136,10,1356,5087,7483,0,1571,5938,8334,10,7483,5086,1355,0,8334,5937,1570,10,5087,674,5086,0,5938,889,5937,10,7484,2711,97,0,8335,3138,153,10,5088,7484,2712,0,5939,8335,3139,10,5087,1356,2711,0,5938,1571,3138,10,674,5087,7484,0,889,5938,8335,10,2705,7485,2713,0,3132,8336,3140,10,1353,5089,7485,0,1568,5940,8336,10,7485,5088,1357,0,8336,5939,1572,10,5089,674,5088,0,5940,889,5939,10,7486,2719,80,0,8337,3146,136,10,5090,7486,2714,0,5941,8337,3141,10,5093,1360,2719,0,5944,1575,3146,10,675,5093,7486,0,890,5944,8337,10,2716,7487,2715,0,3143,8338,3142,10,1359,5091,7487,0,1574,5942,8338,10,7487,5090,1358,0,8338,5941,1573,10,5091,675,5090,0,5942,890,5941,10,7488,2717,82,0,8339,3144,138,10,5092,7488,2713,0,5943,8339,3140,10,5091,1359,2717,0,5942,1574,3144,10,675,5091,7488,0,890,5942,8339,10,2718,7489,2712,0,3145,8340,3139,10,1360,5093,7489,0,1575,5944,8340,10,7489,5092,1357,0,8340,5943,1572,10,5093,675,5092,0,5944,890,5943,10,7490,2716,89,0,8341,3143,157,10,5094,7490,2720,0,5945,8341,3147,10,5097,1359,2716,0,5948,1574,3143,10,676,5097,7490,0,891,5948,8341,10,2697,7491,2721,0,5311,8342,3148,10,1349,5095,7491,0,2658,5946,8342,10,7491,5094,1361,0,8342,5945,1576,10,5095,676,5094,0,5946,891,5945,10,7492,2696,91,0,8343,5312,159,10,5096,7492,2707,0,5947,8343,3134,10,5095,1349,2696,0,5946,2658,5312,10,676,5095,7492,0,891,5946,8343,10,2717,7493,2706,0,3144,8344,3133,10,1359,5097,7493,0,1574,5948,8344,10,7493,5096,1354,0,8344,5947,1569,10,5097,676,5096,0,5948,891,5947,10,7494,2727,77,0,8345,3154,129,10,5098,7494,2709,0,5949,8345,5319,10,5101,1364,2727,0,5952,1579,3154,10,677,5101,7494,0,892,5952,8345,10,2722,7495,2708,0,3149,8346,5320,10,1362,5099,7495,0,1577,5950,8346,10,7495,5098,1355,0,8346,5949,2662,10,5099,677,5098,0,5950,892,5949,10,7496,2723,83,0,8347,3150,139,10,5100,7496,2724,0,5951,8347,3151,10,5099,1362,2723,0,5950,1577,3150,10,677,5099,7496,0,892,5950,8347,10,2726,7497,2725,0,3153,8348,3152,10,1364,5101,7497,0,1579,5952,8348,10,7497,5100,1363,0,8348,5951,1578,10,5101,677,5100,0,5952,892,5951,10,7498,2722,92,0,8349,3149,148,10,5102,7498,2703,0,5953,8349,5317,10,5105,1362,2722,0,5956,1577,3149,10,678,5105,7498,0,893,5956,8349,10,2687,7499,2702,0,5305,8350,5318,10,1344,5103,7499,0,2655,5954,8350,10,7499,5102,1352,0,8350,5953,2661,10,5103,678,5102,0,5954,893,5953,10,7500,2686,86,0,8351,5306,142,10,5104,7500,2728,0,5955,8351,3155,10,5103,1344,2686,0,5954,2655,5306,10,678,5103,7500,0,893,5954,8351,10,2723,7501,2729,0,3150,8352,3156,10,1362,5105,7501,0,1577,5956,8352,10,7501,5104,1365,0,8352,5955,1580,10,5105,678,5104,0,5956,893,5955,10,7502,2678,74,0,8353,5302,118,10,5106,7502,2730,0,5957,8353,3157,10,5109,1340,2678,0,5960,2653,5302,10,679,5109,7502,0,894,5960,8353,10,2732,7503,2731,0,3159,8354,3158,10,1367,5107,7503,0,1582,5958,8354,10,7503,5106,1366,0,8354,5957,1581,10,5107,679,5106,0,5958,894,5957,10,7504,2733,83,0,8355,3160,139,10,5108,7504,2729,0,5959,8355,3156,10,5107,1367,2733,0,5958,1582,3160,10,679,5107,7504,0,894,5958,8355,10,2679,7505,2728,0,5301,8356,3155,10,1340,5109,7505,0,2653,5960,8356,10,7505,5108,1365,0,8356,5959,1580,10,5109,679,5108,0,5960,894,5959,10,7506,2732,87,0,8357,3159,143,10,5110,7506,2734,0,5961,8357,3161,10,5113,1367,2732,0,5964,1582,3159,10,680,5113,7506,0,895,5964,8357,10,2736,7507,2735,0,3163,8358,3162,10,1369,5111,7507,0,1584,5962,8358,10,7507,5110,1368,0,8358,5961,1583,10,5111,680,5110,0,5962,895,5961,10,7508,2737,94,0,8359,3164,150,10,5112,7508,2725,0,5963,8359,3152,10,5111,1369,2737,0,5962,1584,3164,10,680,5111,7508,0,895,5962,8359,10,2733,7509,2724,0,3160,8360,3151,10,1367,5113,7509,0,1582,5964,8360,10,7509,5112,1363,0,8360,5963,1578,10,5113,680,5112,0,5964,895,5963,10,7510,2745,79,0,8361,3172,133,10,5114,7510,2738,0,5965,8361,3165,10,5117,1373,2745,0,5968,1588,3172,10,681,5117,7510,0,896,5968,8361,10,2740,7511,2739,0,3167,8362,3166,10,1371,5115,7511,0,1586,5966,8362,10,7511,5114,1370,0,8362,5965,1585,10,5115,681,5114,0,5966,896,5965,10,7512,2741,84,0,8363,3168,140,10,5116,7512,2742,0,5967,8363,3169,10,5115,1371,2741,0,5966,1586,3168,10,681,5115,7512,0,896,5966,8363,10,2744,7513,2743,0,3171,8364,3170,10,1373,5117,7513,0,1588,5968,8364,10,7513,5116,1372,0,8364,5967,1587,10,5117,681,5116,0,5968,896,5967,10,7514,2740,93,0,8365,3167,149,10,5118,7514,2746,0,5969,8365,3173,10,5121,1371,2740,0,5972,1586,3167,10,682,5121,7514,0,897,5972,8365,10,2699,7515,2747,0,5313,8366,3174,10,1350,5119,7515,0,2659,5970,8366,10,7515,5118,1374,0,8366,5969,1589,10,5119,682,5118,0,5970,897,5969,10,7516,2698,88,0,8367,5314,144,10,5120,7516,2748,0,5971,8367,3175,10,5119,1350,2698,0,5970,2659,5314,10,682,5119,7516,0,897,5970,8367,10,2741,7517,2749,0,3168,8368,3176,10,1371,5121,7517,0,1586,5972,8368,10,7517,5120,1375,0,8368,5971,1590,10,5121,682,5120,0,5972,897,5971,10,7518,2692,75,0,8369,5310,119,10,5122,7518,2721,0,5973,8369,5323,10,5125,1347,2692,0,5976,2657,5310,10,683,5125,7518,0,898,5976,8369,10,2750,7519,2720,0,3177,8370,5324,10,1376,5123,7519,0,1591,5974,8370,10,7519,5122,1361,0,8370,5973,2664,10,5123,683,5122,0,5974,898,5973,10,7520,2751,84,0,8371,3178,140,10,5124,7520,2749,0,5975,8371,3176,10,5123,1376,2751,0,5974,1591,3178,10,683,5123,7520,0,898,5974,8371,10,2693,7521,2748,0,5309,8372,3175,10,1347,5125,7521,0,2657,5976,8372,10,7521,5124,1375,0,8372,5975,1590,10,5125,683,5124,0,5976,898,5975,10,7522,2750,89,0,8373,3177,145,10,5126,7522,2715,0,5977,8373,5321,10,5129,1376,2750,0,5980,1591,3177,10,684,5129,7522,0,899,5980,8373,10,2752,7523,2714,0,3179,8374,5322,10,1377,5127,7523,0,1592,5978,8374,10,7523,5126,1358,0,8374,5977,2663,10,5127,684,5126,0,5978,899,5977,10,7524,2753,95,0,8375,3180,151,10,5128,7524,2743,0,5979,8375,3170,10,5127,1377,2753,0,5978,1592,3180,10,684,5127,7524,0,899,5978,8375,10,2751,7525,2742,0,3178,8376,3169,10,1376,5129,7525,0,1591,5980,8376,10,7525,5128,1372,0,8376,5979,1587,10,5129,684,5128,0,5980,899,5979,10,7526,2759,78,0,8377,3186,132,10,5130,7526,2735,0,5981,8377,5327,10,5133,1380,2759,0,5984,1595,3186,10,685,5133,7526,0,900,5984,8377,10,2754,7527,2734,0,3181,8378,5328,10,1378,5131,7527,0,1593,5982,8378,10,7527,5130,1368,0,8378,5981,2666,10,5131,685,5130,0,5982,900,5981,10,7528,2755,85,0,8379,3182,141,10,5132,7528,2756,0,5983,8379,3183,10,5131,1378,2755,0,5982,1593,3182,10,685,5131,7528,0,900,5982,8379,10,2758,7529,2757,0,3185,8380,3184,10,1380,5133,7529,0,1595,5984,8380,10,7529,5132,1379,0,8380,5983,1594,10,5133,685,5132,0,5984,900,5983,10,7530,2754,87,0,8381,3181,155,10,5134,7530,2731,0,5985,8381,5325,10,5137,1378,2754,0,5988,1593,3181,10,686,5137,7530,0,901,5988,8381,10,2685,7531,2730,0,5303,8382,5326,10,1343,5135,7531,0,2654,5986,8382,10,7531,5134,1366,0,8382,5985,2665,10,5135,686,5134,0,5986,901,5985,10,7532,2684,90,0,8383,5304,146,10,5136,7532,2760,0,5987,8383,3187,10,5135,1343,2684,0,5986,2654,5304,10,686,5135,7532,0,901,5986,8383,10,2755,7533,2761,0,3182,8384,3188,10,1378,5137,7533,0,1593,5988,8384,10,7533,5136,1381,0,8384,5987,1596,10,5137,686,5136,0,5988,901,5987,10,7534,2700,76,0,8385,5316,122,10,5138,7534,2747,0,5989,8385,5331,10,5141,1351,2700,0,5992,2660,5316,10,687,5141,7534,0,902,5992,8385,10,2762,7535,2746,0,3189,8386,5332,10,1382,5139,7535,0,1597,5990,8386,10,7535,5138,1374,0,8386,5989,2668,10,5139,687,5138,0,5990,902,5989,10,7536,2763,85,0,8387,3190,141,10,5140,7536,2761,0,5991,8387,3188,10,5139,1382,2763,0,5990,1597,3190,10,687,5139,7536,0,902,5990,8387,10,2701,7537,2760,0,5315,8388,3187,10,1351,5141,7537,0,2660,5992,8388,10,7537,5140,1381,0,8388,5991,1596,10,5141,687,5140,0,5992,902,5991,10,7538,2762,93,0,8389,3189,161,10,5142,7538,2739,0,5993,8389,5329,10,5145,1382,2762,0,5996,1597,3189,10,688,5145,7538,0,903,5996,8389,10,2764,7539,2738,0,3191,8390,5330,10,1383,5143,7539,0,1598,5994,8390,10,7539,5142,1370,0,8390,5993,2667,10,5143,688,5142,0,5994,903,5993,10,7540,2765,96,0,8391,3192,152,10,5144,7540,2757,0,5995,8391,3184,10,5143,1383,2765,0,5994,1598,3192,10,688,5143,7540,0,903,5994,8391,10,2763,7541,2756,0,3190,8392,3183,10,1382,5145,7541,0,1597,5996,8392,10,7541,5144,1379,0,8392,5995,1594,10,5145,688,5144,0,5996,903,5995,10,7542,2710,77,0,8393,3137,130,10,5146,7542,2766,0,5997,8393,3193,10,5149,1356,2710,0,6000,1571,3137,10,689,5149,7542,0,904,6000,8393,10,3842,7543,2767,0,4269,8394,3194,10,1922,5147,7543,0,2137,5998,8394,10,7543,5146,1384,0,8394,5997,1599,10,5147,689,5146,0,5998,904,5997,10,7544,3843,365,0,8395,4270,482,10,5148,7544,3828,0,5999,8395,4255,10,5147,1922,3843,0,5998,2137,4270,10,689,5147,7544,0,904,5998,8395,10,2711,7545,3829,0,3138,8396,4256,10,1356,5149,7545,0,1571,6000,8396,10,7545,5148,1915,0,8396,5999,2130,10,5149,689,5148,0,6000,904,5999,10,7546,3831,80,0,8397,4258,136,10,5150,7546,2719,0,6001,8397,3146,10,5153,1916,3831,0,6004,2131,4258,10,690,5153,7546,0,905,6004,8397,10,3829,7547,2718,0,4256,8398,3145,10,1915,5151,7547,0,2130,6002,8398,10,7547,5150,1360,0,8398,6001,1575,10,5151,690,5150,0,6002,905,6001,10,7548,3828,365,0,8399,4255,482,10,5152,7548,3844,0,6003,8399,4271,10,5151,1915,3828,0,6002,2130,4255,10,690,5151,7548,0,905,6002,8399,10,3830,7549,3845,0,4257,8400,4272,10,1916,5153,7549,0,2131,6004,8400,10,7549,5152,1923,0,8400,6003,2138,10,5153,690,5152,0,6004,905,6003,10,7550,2766,77,0,8401,5334,129,10,5154,7550,2727,0,6005,8401,3154,10,5157,1384,2766,0,6008,2669,5334,10,691,5157,7550,0,906,6008,8401,10,2772,7551,2726,0,3199,8402,3153,10,1387,5155,7551,0,1602,6006,8402,10,7551,5154,1364,0,8402,6005,1579,10,5155,691,5154,0,6006,906,6005,10,7552,2773,367,0,8403,3200,485,10,5156,7552,3846,0,6007,8403,4273,10,5155,1387,2773,0,6006,1602,3200,10,691,5155,7552,0,906,6006,8403,10,2767,7553,3847,0,5333,8404,4274,10,1384,5157,7553,0,2669,6008,8404,10,7553,5156,1924,0,8404,6007,2139,10,5157,691,5156,0,6008,906,6007,10,7554,2736,78,0,8405,3163,131,10,5158,7554,2774,0,6009,8405,3201,10,5161,1369,2736,0,6012,1584,3163,10,692,5161,7554,0,907,6012,8405,10,3848,7555,2775,0,4275,8406,3202,10,1925,5159,7555,0,2140,6010,8406,10,7555,5158,1388,0,8406,6009,1603,10,5159,692,5158,0,6010,907,6009,10,7556,3849,367,0,8407,4276,485,10,5160,7556,2773,0,6011,8407,3200,10,5159,1925,3849,0,6010,2140,4276,10,692,5159,7556,0,907,6010,8407,10,2737,7557,2772,0,3164,8408,3199,10,1369,5161,7557,0,1584,6012,8408,10,7557,5160,1387,0,8408,6011,1602,10,5161,692,5160,0,6012,907,6011,10,7558,3837,79,0,8409,4264,133,10,5162,7558,2745,0,6013,8409,3172,10,5165,1919,3837,0,6016,2134,4264,10,693,5165,7558,0,908,6016,8409,10,2778,7559,2744,0,3205,8410,3171,10,1390,5163,7559,0,1605,6014,8410,10,7559,5162,1373,0,8410,6013,1588,10,5163,693,5162,0,6014,908,6013,10,7560,2779,370,0,8411,3206,490,10,5164,7560,3850,0,6015,8411,4277,10,5163,1390,2779,0,6014,1605,3206,10,693,5163,7560,0,908,6014,8411,10,3836,7561,3851,0,4263,8412,4278,10,1919,5165,7561,0,2134,6016,8412,10,7561,5164,1926,0,8412,6015,2141,10,5165,693,5164,0,6016,908,6015,10,7562,2752,80,0,8413,3179,135,10,5166,7562,3831,0,6017,8413,5429,10,5169,1377,2752,0,6020,1592,3179,10,694,5169,7562,0,909,6020,8413,10,3852,7563,3830,0,4279,8414,5430,10,1927,5167,7563,0,2142,6018,8414,10,7563,5166,1916,0,8414,6017,2717,10,5167,694,5166,0,6018,909,6017,10,7564,3853,370,0,8415,4280,490,10,5168,7564,2779,0,6019,8415,3206,10,5167,1927,3853,0,6018,2142,4280,10,694,5167,7564,0,909,6018,8415,10,2753,7565,2778,0,3180,8416,3205,10,1377,5169,7565,0,1592,6020,8416,10,7565,5168,1390,0,8416,6019,1605,10,5169,694,5168,0,6020,909,6019,10,7566,2774,78,0,8417,5338,132,10,5170,7566,2759,0,6021,8417,3186,10,5173,1388,2774,0,6024,2671,5338,10,695,5173,7566,0,910,6024,8417,10,2780,7567,2758,0,3207,8418,3185,10,1391,5171,7567,0,1606,6022,8418,10,7567,5170,1380,0,8418,6021,1595,10,5171,695,5170,0,6022,910,6021,10,7568,2781,371,0,8419,3208,491,10,5172,7568,3854,0,6023,8419,4281,10,5171,1391,2781,0,6022,1606,3208,10,695,5171,7568,0,910,6022,8419,10,2775,7569,3855,0,5337,8420,4282,10,1388,5173,7569,0,2671,6024,8420,10,7569,5172,1928,0,8420,6023,2143,10,5173,695,5172,0,6024,910,6023,10,7570,2764,79,0,8421,3191,134,10,5174,7570,3837,0,6025,8421,5433,10,5177,1383,2764,0,6028,1598,3191,10,696,5177,7570,0,911,6028,8421,10,3856,7571,3836,0,4283,8422,5434,10,1929,5175,7571,0,2144,6026,8422,10,7571,5174,1919,0,8422,6025,2719,10,5175,696,5174,0,6026,911,6025,10,7572,3857,371,0,8423,4284,491,10,5176,7572,2781,0,6027,8423,3208,10,5175,1929,3857,0,6026,2144,4284,10,696,5175,7572,0,911,6026,8423,10,2765,7573,2780,0,3192,8424,3207,10,1383,5177,7573,0,1598,6028,8424,10,7573,5176,1391,0,8424,6027,1606,10,5177,696,5176,0,6028,911,6027,10,7574,2783,98,0,8425,3210,162,10,5178,7574,2788,0,6029,8425,3215,10,5181,1392,2783,0,6032,1607,3210,10,697,5181,7574,0,912,6032,8425,10,2786,7575,2789,0,3213,8426,3216,10,1394,5179,7575,0,1609,6030,8426,10,7575,5178,1395,0,8426,6029,1610,10,5179,697,5178,0,6030,912,6029,10,7576,2787,100,0,8427,3214,164,10,5180,7576,2784,0,6031,8427,3211,10,5179,1394,2787,0,6030,1609,3214,10,697,5179,7576,0,912,6030,8427,10,2782,7577,2785,0,3209,8428,3212,10,1392,5181,7577,0,1607,6032,8428,10,7577,5180,1393,0,8428,6031,1608,10,5181,697,5180,0,6032,912,6031,10,7578,2791,101,0,8429,3218,165,10,5182,7578,2789,0,6033,8429,3216,10,5185,1396,2791,0,6036,1611,3218,10,698,5185,7578,0,913,6036,8429,10,2794,7579,2788,0,3221,8430,3215,10,1398,5183,7579,0,1613,6034,8430,10,7579,5182,1395,0,8430,6033,1610,10,5183,698,5182,0,6034,913,6033,10,7580,2795,103,0,8431,3222,167,10,5184,7580,2792,0,6035,8431,3219,10,5183,1398,2795,0,6034,1613,3222,10,698,5183,7580,0,913,6034,8431,10,2790,7581,2793,0,3217,8432,3220,10,1396,5185,7581,0,1611,6036,8432,10,7581,5184,1397,0,8432,6035,1612,10,5185,698,5184,0,6036,913,6035,10,7582,2794,98,0,8433,3221,162,10,5186,7582,2800,0,6037,8433,3227,10,5189,1398,2794,0,6040,1613,3221,10,699,5189,7582,0,914,6040,8433,10,2798,7583,2801,0,3225,8434,3228,10,1400,5187,7583,0,1615,6038,8434,10,7583,5186,1401,0,8434,6037,1616,10,5187,699,5186,0,6038,914,6037,10,7584,2799,104,0,8435,3226,168,10,5188,7584,2796,0,6039,8435,3223,10,5187,1400,2799,0,6038,1615,3226,10,699,5187,7584,0,914,6038,8435,10,2795,7585,2797,0,3222,8436,3224,10,1398,5189,7585,0,1613,6040,8436,10,7585,5188,1399,0,8436,6039,1614,10,5189,699,5188,0,6040,914,6039,10,7586,2803,106,0,8437,3230,170,10,5190,7586,2804,0,6041,8437,3231,10,5193,1402,2803,0,6044,1617,3230,10,700,5193,7586,0,915,6044,8437,10,2801,7587,2805,0,3228,8438,3232,10,1401,5191,7587,0,1616,6042,8438,10,7587,5190,1403,0,8438,6041,1618,10,5191,700,5190,0,6042,915,6041,10,7588,2800,98,0,8439,3227,162,10,5192,7588,2783,0,6043,8439,3210,10,5191,1401,2800,0,6042,1616,3227,10,700,5191,7588,0,915,6042,8439,10,2802,7589,2782,0,3229,8440,3209,10,1402,5193,7589,0,1617,6044,8440,10,7589,5192,1392,0,8440,6043,1607,10,5193,700,5192,0,6044,915,6043,10,7590,2807,107,0,8441,3234,171,10,5194,7590,2812,0,6045,8441,3239,10,5197,1404,2807,0,6048,1619,3234,10,701,5197,7590,0,916,6048,8441,10,2810,7591,2813,0,3237,8442,3240,10,1406,5195,7591,0,1621,6046,8442,10,7591,5194,1407,0,8442,6045,1622,10,5195,701,5194,0,6046,916,6045,10,7592,2811,109,0,8443,3238,173,10,5196,7592,2808,0,6047,8443,3235,10,5195,1406,2811,0,6046,1621,3238,10,701,5195,7592,0,916,6046,8443,10,2806,7593,2809,0,3233,8444,3236,10,1404,5197,7593,0,1619,6048,8444,10,7593,5196,1405,0,8444,6047,1620,10,5197,701,5196,0,6048,916,6047,10,7594,2815,111,0,8445,3242,175,10,5198,7594,2820,0,6049,8445,3247,10,5201,1408,2815,0,6052,1623,3242,10,702,5201,7594,0,917,6052,8445,10,2818,7595,2821,0,3245,8446,3248,10,1410,5199,7595,0,1625,6050,8446,10,7595,5198,1411,0,8446,6049,1626,10,5199,702,5198,0,6050,917,6049,10,7596,2819,113,0,8447,3246,177,10,5200,7596,2816,0,6051,8447,3243,10,5199,1410,2819,0,6050,1625,3246,10,702,5199,7596,0,917,6050,8447,10,2814,7597,2817,0,3241,8448,3244,10,1408,5201,7597,0,1623,6052,8448,10,7597,5200,1409,0,8448,6051,1624,10,5201,702,5200,0,6052,917,6051,10,7598,2823,115,0,8449,3250,179,10,5202,7598,2828,0,6053,8449,3255,10,5205,1412,2823,0,6056,1627,3250,10,703,5205,7598,0,918,6056,8449,10,2826,7599,2829,0,3253,8450,3256,10,1414,5203,7599,0,1629,6054,8450,10,7599,5202,1415,0,8450,6053,1630,10,5203,703,5202,0,6054,918,6053,10,7600,2827,114,0,8451,3254,178,10,5204,7600,2824,0,6055,8451,3251,10,5203,1414,2827,0,6054,1629,3254,10,703,5203,7600,0,918,6054,8451,10,2822,7601,2825,0,3249,8452,3252,10,1412,5205,7601,0,1627,6056,8452,10,7601,5204,1413,0,8452,6055,1628,10,5205,703,5204,0,6056,918,6055,10,7602,2831,115,0,8453,3258,179,10,5206,7602,2823,0,6057,8453,3250,10,5209,1416,2831,0,6060,1631,3258,10,704,5209,7602,0,919,6060,8453,10,2834,7603,2822,0,3261,8454,3249,10,1418,5207,7603,0,1633,6058,8454,10,7603,5206,1412,0,8454,6057,1627,10,5207,704,5206,0,6058,919,6057,10,7604,2835,118,0,8455,3262,182,10,5208,7604,2832,0,6059,8455,3259,10,5207,1418,2835,0,6058,1633,3262,10,704,5207,7604,0,919,6058,8455,10,2830,7605,2833,0,3257,8456,3260,10,1416,5209,7605,0,1631,6060,8456,10,7605,5208,1417,0,8456,6059,1632,10,5209,704,5208,0,6060,919,6059,10,7606,2837,269,0,8457,3264,357,10,5210,7606,3354,0,6061,8457,3781,10,5213,1419,2837,0,6064,1634,3264,10,705,5213,7606,0,920,6064,8457,10,2838,7607,3355,0,3265,8458,3782,10,1420,5211,7607,0,1635,6062,8458,10,7607,5210,1678,0,8458,6061,1893,10,5211,705,5210,0,6062,920,6061,10,7608,2839,118,0,8459,3266,182,10,5212,7608,2835,0,6063,8459,3262,10,5211,1420,2839,0,6062,1635,3266,10,705,5211,7608,0,920,6062,8459,10,2836,7609,2834,0,3263,8460,3261,10,1419,5213,7609,0,1634,6064,8460,10,7609,5212,1418,0,8460,6063,1633,10,5213,705,5212,0,6064,920,6063,10,7610,2836,110,0,8461,3263,174,10,5214,7610,2813,0,6065,8461,3240,10,5217,1419,2836,0,6068,1634,3263,10,706,5217,7610,0,921,6068,8461,10,2840,7611,2812,0,3267,8462,3239,10,1421,5215,7611,0,1636,6066,8462,10,7611,5214,1407,0,8462,6065,1622,10,5215,706,5214,0,6066,921,6065,10,7612,2841,254,0,8463,3268,337,10,5216,7612,3361,0,6067,8463,3788,10,5215,1421,2841,0,6066,1636,3268,10,706,5215,7612,0,921,6066,8463,10,2837,7613,3360,0,3264,8464,3787,10,1419,5217,7613,0,1634,6068,8464,10,7613,5216,1681,0,8464,6067,1896,10,5217,706,5216,0,6068,921,6067,10,7614,2843,119,0,8465,3270,183,10,5218,7614,2848,0,6069,8465,3275,10,5221,1422,2843,0,6072,1637,3270,10,707,5221,7614,0,922,6072,8465,10,2846,7615,2849,0,3273,8466,3276,10,1424,5219,7615,0,1639,6070,8466,10,7615,5218,1425,0,8466,6069,1640,10,5219,707,5218,0,6070,922,6069,10,7616,2847,121,0,8467,3274,185,10,5220,7616,2844,0,6071,8467,3271,10,5219,1424,2847,0,6070,1639,3274,10,707,5219,7616,0,922,6070,8467,10,2842,7617,2845,0,3269,8468,3272,10,1422,5221,7617,0,1637,6072,8468,10,7617,5220,1423,0,8468,6071,1638,10,5221,707,5220,0,6072,922,6071,10,7618,2851,123,0,8469,3278,187,10,5222,7618,2854,0,6073,8469,3281,10,5225,1426,2851,0,6076,1641,3278,10,708,5225,7618,0,923,6076,8469,10,2852,7619,2855,0,3279,8470,3282,10,1427,5223,7619,0,1642,6074,8470,10,7619,5222,1428,0,8470,6073,1643,10,5223,708,5222,0,6074,923,6073,10,7620,2853,271,0,8471,3280,359,10,5224,7620,3362,0,6075,8471,3789,10,5223,1427,2853,0,6074,1642,3280,10,708,5223,7620,0,923,6074,8471,10,2850,7621,3363,0,3277,8472,3790,10,1426,5225,7621,0,1641,6076,8472,10,7621,5224,1682,0,8472,6075,1897,10,5225,708,5224,0,6076,923,6075,10,7622,2857,272,0,8473,3284,360,10,5226,7622,3369,0,6077,8473,3796,10,5229,1429,2857,0,6080,1644,3284,10,709,5229,7622,0,924,6080,8473,10,2853,7623,3368,0,5343,8474,3795,10,1427,5227,7623,0,2674,6078,8474,10,7623,5226,1685,0,8474,6077,1900,10,5227,709,5226,0,6078,924,6077,10,7624,2852,124,0,8475,5344,190,10,5228,7624,2858,0,6079,8475,3285,10,5227,1427,2852,0,6078,2674,5344,10,709,5227,7624,0,924,6078,8475,10,2856,7625,2859,0,3283,8476,3286,10,1429,5229,7625,0,1644,6080,8476,10,7625,5228,1430,0,8476,6079,1645,10,5229,709,5228,0,6080,924,6079,10,7626,2861,126,0,8477,3288,191,10,5230,7626,2864,0,6081,8477,3291,10,5233,1431,2861,0,6084,1646,3288,10,710,5233,7626,0,925,6084,8477,10,2843,7627,2865,0,5341,8478,3292,10,1422,5231,7627,0,2673,6082,8478,10,7627,5230,1433,0,8478,6081,1648,10,5231,710,5230,0,6082,925,6081,10,7628,2842,120,0,8479,5342,193,10,5232,7628,2862,0,6083,8479,3289,10,5231,1422,2842,0,6082,2673,5342,10,710,5231,7628,0,925,6082,8479,10,2860,7629,2863,0,3287,8480,3290,10,1431,5233,7629,0,1646,6084,8480,10,7629,5232,1432,0,8480,6083,1647,10,5233,710,5232,0,6084,925,6083,10,7630,2867,128,0,8481,3294,195,10,5234,7630,2872,0,6085,8481,3299,10,5237,1434,2867,0,6088,1649,3294,10,711,5237,7630,0,926,6088,8481,10,2870,7631,2873,0,3297,8482,3300,10,1436,5235,7631,0,1651,6086,8482,10,7631,5234,1437,0,8482,6085,1652,10,5235,711,5234,0,6086,926,6085,10,7632,2871,130,0,8483,3298,197,10,5236,7632,2868,0,6087,8483,3295,10,5235,1436,2871,0,6086,1651,3298,10,711,5235,7632,0,926,6086,8483,10,2866,7633,2869,0,3293,8484,3296,10,1434,5237,7633,0,1649,6088,8484,10,7633,5236,1435,0,8484,6087,1650,10,5237,711,5236,0,6088,926,6087,10,7634,2875,132,0,8485,3302,199,10,5238,7634,2878,0,6089,8485,3305,10,5241,1438,2875,0,6092,1653,3302,10,712,5241,7634,0,927,6092,8485,10,2871,7635,2879,0,3298,8486,3306,10,1436,5239,7635,0,1651,6090,8486,10,7635,5238,1440,0,8486,6089,1655,10,5239,712,5238,0,6090,927,6089,10,7636,2870,131,0,8487,3297,198,10,5240,7636,2876,0,6091,8487,3303,10,5239,1436,2870,0,6090,1651,3297,10,712,5239,7636,0,927,6090,8487,10,2874,7637,2877,0,3301,8488,3304,10,1438,5241,7637,0,1653,6092,8488,10,7637,5240,1439,0,8488,6091,1654,10,5241,712,5240,0,6092,927,6091,10,7638,2881,133,0,8489,3308,200,10,5242,7638,2877,0,6093,8489,3304,10,5245,1441,2881,0,6096,1656,3308,10,713,5245,7638,0,928,6096,8489,10,2884,7639,2876,0,3311,8490,3303,10,1443,5243,7639,0,1658,6094,8490,10,7639,5242,1439,0,8490,6093,1654,10,5243,713,5242,0,6094,928,6093,10,7640,2885,135,0,8491,3312,202,10,5244,7640,2882,0,6095,8491,3309,10,5243,1443,2885,0,6094,1658,3312,10,713,5243,7640,0,928,6094,8491,10,2880,7641,2883,0,3307,8492,3310,10,1441,5245,7641,0,1656,6096,8492,10,7641,5244,1442,0,8492,6095,1657,10,5245,713,5244,0,6096,928,6095,10,7642,2887,135,0,8493,3314,202,10,5246,7642,2885,0,6097,8493,3312,10,5249,1444,2887,0,6100,1659,3314,10,714,5249,7642,0,929,6100,8493,10,2873,7643,2884,0,3300,8494,3311,10,1437,5247,7643,0,1652,6098,8494,10,7643,5246,1443,0,8494,6097,1658,10,5247,714,5246,0,6098,929,6097,10,7644,2872,128,0,8495,3299,195,10,5248,7644,2888,0,6099,8495,3315,10,5247,1437,2872,0,6098,1652,3299,10,714,5247,7644,0,929,6098,8495,10,2886,7645,2889,0,3313,8496,3316,10,1444,5249,7645,0,1659,6100,8496,10,7645,5248,1445,0,8496,6099,1660,10,5249,714,5248,0,6100,929,6099,10,7646,2891,137,0,8497,3318,204,10,5250,7646,2896,0,6101,8497,3323,10,5253,1446,2891,0,6104,1661,3318,10,715,5253,7646,0,930,6104,8497,10,2894,7647,2897,0,3321,8498,3324,10,1448,5251,7647,0,1663,6102,8498,10,7647,5250,1449,0,8498,6101,1664,10,5251,715,5250,0,6102,930,6101,10,7648,2895,139,0,8499,3322,206,10,5252,7648,2892,0,6103,8499,3319,10,5251,1448,2895,0,6102,1663,3322,10,715,5251,7648,0,930,6102,8499,10,2890,7649,2893,0,3317,8500,3320,10,1446,5253,7649,0,1661,6104,8500,10,7649,5252,1447,0,8500,6103,1662,10,5253,715,5252,0,6104,930,6103,10,7650,2899,141,0,8501,3326,208,10,5254,7650,2904,0,6105,8501,3331,10,5257,1450,2899,0,6108,1665,3326,10,716,5257,7650,0,931,6108,8501,10,2902,7651,2905,0,3329,8502,3332,10,1452,5255,7651,0,1667,6106,8502,10,7651,5254,1453,0,8502,6105,1668,10,5255,716,5254,0,6106,931,6105,10,7652,2903,143,0,8503,3330,210,10,5256,7652,2900,0,6107,8503,3327,10,5255,1452,2903,0,6106,1667,3330,10,716,5255,7652,0,931,6106,8503,10,2898,7653,2901,0,3325,8504,3328,10,1450,5257,7653,0,1665,6108,8504,10,7653,5256,1451,0,8504,6107,1666,10,5257,716,5256,0,6108,931,6107,10,7654,2907,145,0,8505,3334,212,10,5258,7654,2912,0,6109,8505,3339,10,5261,1454,2907,0,6112,1669,3334,10,717,5261,7654,0,932,6112,8505,10,2910,7655,2913,0,3337,8506,3340,10,1456,5259,7655,0,1671,6110,8506,10,7655,5258,1457,0,8506,6109,1672,10,5259,717,5258,0,6110,932,6109,10,7656,2911,144,0,8507,3338,211,10,5260,7656,2908,0,6111,8507,3335,10,5259,1456,2911,0,6110,1671,3338,10,717,5259,7656,0,932,6110,8507,10,2906,7657,2909,0,3333,8508,3336,10,1454,5261,7657,0,1669,6112,8508,10,7657,5260,1455,0,8508,6111,1670,10,5261,717,5260,0,6112,932,6111,10,7658,2915,145,0,8509,3342,212,10,5262,7658,2907,0,6113,8509,3334,10,5265,1458,2915,0,6116,1673,3342,10,718,5265,7658,0,933,6116,8509,10,2916,7659,2906,0,3343,8510,3333,10,1459,5263,7659,0,1674,6114,8510,10,7659,5262,1454,0,8510,6113,1669,10,5263,718,5262,0,6114,933,6113,10,7660,2917,273,0,8511,3344,362,10,5264,7660,3372,0,6115,8511,3799,10,5263,1459,2917,0,6114,1674,3344,10,718,5263,7660,0,933,6114,8511,10,2914,7661,3373,0,3341,8512,3800,10,1458,5265,7661,0,1673,6116,8512,10,7661,5264,1687,0,8512,6115,1902,10,5265,718,5264,0,6116,933,6115,10,7662,2916,140,0,8513,3343,207,10,5266,7662,2897,0,6117,8513,3324,10,5269,1459,2916,0,6120,1674,3343,10,719,5269,7662,0,934,6120,8513,10,2918,7663,2896,0,3345,8514,3323,10,1460,5267,7663,0,1675,6118,8514,10,7663,5266,1449,0,8514,6117,1664,10,5267,719,5266,0,6118,934,6117,10,7664,2919,229,0,8515,3346,307,10,5268,7664,3377,0,6119,8515,3804,10,5267,1460,2919,0,6118,1675,3346,10,719,5267,7664,0,934,6118,8515,10,2917,7665,3376,0,3344,8516,3803,10,1459,5269,7665,0,1674,6120,8516,10,7665,5268,1689,0,8516,6119,1904,10,5269,719,5268,0,6120,934,6119,10,7666,2921,147,0,8517,3348,214,10,5270,7666,2926,0,6121,8517,3353,10,5273,1461,2921,0,6124,1676,3348,10,720,5273,7666,0,935,6124,8517,10,2924,7667,2927,0,3351,8518,3354,10,1463,5271,7667,0,1678,6122,8518,10,7667,5270,1464,0,8518,6121,1679,10,5271,720,5270,0,6122,935,6121,10,7668,2925,149,0,8519,3352,216,10,5272,7668,2922,0,6123,8519,3349,10,5271,1463,2925,0,6122,1678,3352,10,720,5271,7668,0,935,6122,8519,10,2920,7669,2923,0,3347,8520,3350,10,1461,5273,7669,0,1676,6124,8520,10,7669,5272,1462,0,8520,6123,1677,10,5273,720,5272,0,6124,935,6123,10,7670,2929,151,0,8521,3356,218,10,5274,7670,2934,0,6125,8521,3361,10,5277,1465,2929,0,6128,1680,3356,10,721,5277,7670,0,936,6128,8521,10,2932,7671,2935,0,3359,8522,3362,10,1467,5275,7671,0,1682,6126,8522,10,7671,5274,1468,0,8522,6125,1683,10,5275,721,5274,0,6126,936,6125,10,7672,2933,153,0,8523,3360,220,10,5276,7672,2930,0,6127,8523,3357,10,5275,1467,2933,0,6126,1682,3360,10,721,5275,7672,0,936,6126,8523,10,2928,7673,2931,0,3355,8524,3358,10,1465,5277,7673,0,1680,6128,8524,10,7673,5276,1466,0,8524,6127,1681,10,5277,721,5276,0,6128,936,6127,10,7674,2932,154,0,8525,3359,221,10,5278,7674,2938,0,6129,8525,3365,10,5281,1467,2932,0,6132,1682,3359,10,722,5281,7674,0,937,6132,8525,10,2861,7675,2939,0,3288,8526,3366,10,1431,5279,7675,0,1646,6130,8526,10,7675,5278,1470,0,8526,6129,1685,10,5279,722,5278,0,6130,937,6129,10,7676,2860,127,0,8527,3287,192,10,5280,7676,2936,0,6131,8527,3363,10,5279,1431,2860,0,6130,1646,3287,10,722,5279,7676,0,937,6130,8527,10,2933,7677,2937,0,3360,8528,3364,10,1467,5281,7677,0,1682,6132,8528,10,7677,5280,1469,0,8528,6131,1684,10,5281,722,5280,0,6132,937,6131,10,7678,2856,125,0,8529,3283,189,10,5282,7678,2942,0,6133,8529,3369,10,5285,1429,2856,0,6136,1644,3283,10,723,5285,7678,0,938,6136,8529,10,2940,7679,2943,0,3367,8530,3370,10,1471,5283,7679,0,1686,6134,8530,10,7679,5282,1472,0,8530,6133,1687,10,5283,723,5282,0,6134,938,6133,10,7680,2941,274,0,8531,3368,363,10,5284,7680,3378,0,6135,8531,3805,10,5283,1471,2941,0,6134,1686,3368,10,723,5283,7680,0,938,6134,8531,10,2857,7681,3379,0,3284,8532,3806,10,1429,5285,7681,0,1644,6136,8532,10,7681,5284,1690,0,8532,6135,1905,10,5285,723,5284,0,6136,938,6135,10,7682,2940,150,0,8533,3367,217,10,5286,7682,2927,0,6137,8533,3354,10,5289,1471,2940,0,6140,1686,3367,10,724,5289,7682,0,939,6140,8533,10,2944,7683,2926,0,3371,8534,3353,10,1473,5287,7683,0,1688,6138,8534,10,7683,5286,1464,0,8534,6137,1679,10,5287,724,5286,0,6138,939,6137,10,7684,2945,275,0,8535,3372,364,10,5288,7684,3385,0,6139,8535,3812,10,5287,1473,2945,0,6138,1688,3372,10,724,5287,7684,0,939,6138,8535,10,2941,7685,3384,0,3368,8536,3811,10,1471,5289,7685,0,1686,6140,8536,10,7685,5288,1693,0,8536,6139,1908,10,5289,724,5288,0,6140,939,6139,10,7686,2832,118,0,8537,3259,182,10,5290,7686,2950,0,6141,8537,3377,10,5293,1417,2832,0,6144,1632,3259,10,725,5293,7686,0,940,6144,8537,10,2948,7687,2951,0,3375,8538,3378,10,1475,5291,7687,0,1690,6142,8538,10,7687,5290,1476,0,8538,6141,1691,10,5291,725,5290,0,6142,940,6141,10,7688,2949,155,0,8539,3376,222,10,5292,7688,2946,0,6143,8539,3373,10,5291,1475,2949,0,6142,1690,3376,10,725,5291,7688,0,940,6142,8539,10,2833,7689,2947,0,3260,8540,3374,10,1417,5293,7689,0,1632,6144,8540,10,7689,5292,1474,0,8540,6143,1689,10,5293,725,5292,0,6144,940,6143,10,7690,2953,157,0,8541,3380,224,10,5294,7690,2956,0,6145,8541,3383,10,5297,1477,2953,0,6148,1692,3380,10,726,5297,7690,0,941,6148,8541,10,2954,7691,2957,0,3381,8542,3384,10,1478,5295,7691,0,1693,6146,8542,10,7691,5294,1479,0,8542,6145,1694,10,5295,726,5294,0,6146,941,6145,10,7692,2955,155,0,8543,3382,222,10,5296,7692,2949,0,6147,8543,3376,10,5295,1478,2955,0,6146,1693,3382,10,726,5295,7692,0,941,6146,8543,10,2952,7693,2948,0,3379,8544,3375,10,1477,5297,7693,0,1692,6148,8544,10,7693,5296,1475,0,8544,6147,1690,10,5297,726,5296,0,6148,941,6147,10,7694,2959,159,0,8545,3386,226,10,5298,7694,2962,0,6149,8545,3389,10,5301,1480,2959,0,6152,1695,3386,10,727,5301,7694,0,942,6152,8545,10,2960,7695,2963,0,3387,8546,3390,10,1481,5299,7695,0,1696,6150,8546,10,7695,5298,1482,0,8546,6149,1697,10,5299,727,5298,0,6150,942,6149,10,7696,2961,157,0,8547,3388,224,10,5300,7696,2953,0,6151,8547,3380,10,5299,1481,2961,0,6150,1696,3388,10,727,5299,7696,0,942,6150,8547,10,2958,7697,2952,0,3385,8548,3379,10,1480,5301,7697,0,1695,6152,8548,10,7697,5300,1477,0,8548,6151,1692,10,5301,727,5300,0,6152,942,6151,10,7698,2965,159,0,8549,3392,226,10,5302,7698,2959,0,6153,8549,3386,10,5305,1483,2965,0,6156,1698,3392,10,728,5305,7698,0,943,6156,8549,10,2966,7699,2958,0,3393,8550,3385,10,1484,5303,7699,0,1699,6154,8550,10,7699,5302,1480,0,8550,6153,1695,10,5303,728,5302,0,6154,943,6153,10,7700,2967,147,0,8551,3394,214,10,5304,7700,2921,0,6155,8551,3348,10,5303,1484,2967,0,6154,1699,3394,10,728,5303,7700,0,943,6154,8551,10,2964,7701,2920,0,3391,8552,3347,10,1483,5305,7701,0,1698,6156,8552,10,7701,5304,1461,0,8552,6155,1676,10,5305,728,5304,0,6156,943,6155,10,7702,2944,147,0,8553,3371,214,10,5306,7702,2967,0,6157,8553,3394,10,5309,1473,2944,0,6160,1688,3371,10,729,5309,7702,0,944,6160,8553,10,2968,7703,2966,0,3395,8554,3393,10,1485,5307,7703,0,1700,6158,8554,10,7703,5306,1484,0,8554,6157,1699,10,5307,729,5306,0,6158,944,6157,10,7704,2969,276,0,8555,3396,365,10,5308,7704,3386,0,6159,8555,3813,10,5307,1485,2969,0,6158,1700,3396,10,729,5307,7704,0,944,6158,8555,10,2945,7705,3387,0,3372,8556,3814,10,1473,5309,7705,0,1688,6160,8556,10,7705,5308,1694,0,8556,6159,1909,10,5309,729,5308,0,6160,944,6159,10,7706,2968,156,0,8557,3395,223,10,5310,7706,2951,0,6161,8557,3378,10,5313,1485,2968,0,6164,1700,3395,10,730,5313,7706,0,945,6164,8557,10,2839,7707,2950,0,3266,8558,3377,10,1420,5311,7707,0,1635,6162,8558,10,7707,5310,1476,0,8558,6161,1691,10,5311,730,5310,0,6162,945,6161,10,7708,2838,270,0,8559,3265,358,10,5312,7708,3391,0,6163,8559,3818,10,5311,1420,2838,0,6162,1635,3265,10,730,5311,7708,0,945,6162,8559,10,2969,7709,3390,0,3396,8560,3817,10,1485,5313,7709,0,1700,6164,8560,10,7709,5312,1696,0,8560,6163,1911,10,5313,730,5312,0,6164,945,6163,10,7710,2882,135,0,8561,3309,202,10,5314,7710,2974,0,6165,8561,3401,10,5317,1442,2882,0,6168,1657,3309,10,731,5317,7710,0,946,6168,8561,10,2972,7711,2975,0,3399,8562,3402,10,1487,5315,7711,0,1702,6166,8562,10,7711,5314,1488,0,8562,6165,1703,10,5315,731,5314,0,6166,946,6165,10,7712,2973,161,0,8563,3400,228,10,5316,7712,2970,0,6167,8563,3397,10,5315,1487,2973,0,6166,1702,3400,10,731,5315,7712,0,946,6166,8563,10,2883,7713,2971,0,3310,8564,3398,10,1442,5317,7713,0,1657,6168,8564,10,7713,5316,1486,0,8564,6167,1701,10,5317,731,5316,0,6168,946,6167,10,7714,2977,161,0,8565,3404,228,10,5318,7714,2973,0,6169,8565,3400,10,5321,1489,2977,0,6172,1704,3404,10,732,5321,7714,0,947,6172,8565,10,2980,7715,2972,0,3407,8566,3399,10,1491,5319,7715,0,1706,6170,8566,10,7715,5318,1487,0,8566,6169,1702,10,5319,732,5318,0,6170,947,6169,10,7716,2981,164,0,8567,3408,231,10,5320,7716,2978,0,6171,8567,3405,10,5319,1491,2981,0,6170,1706,3408,10,732,5319,7716,0,947,6170,8567,10,2976,7717,2979,0,3403,8568,3406,10,1489,5321,7717,0,1704,6172,8568,10,7717,5320,1490,0,8568,6171,1705,10,5321,732,5320,0,6172,947,6171,10,7718,2983,165,0,8569,3410,232,10,5322,7718,2988,0,6173,8569,3415,10,5325,1492,2983,0,6176,1707,3410,10,733,5325,7718,0,948,6176,8569,10,2986,7719,2989,0,3413,8570,3416,10,1494,5323,7719,0,1709,6174,8570,10,7719,5322,1495,0,8570,6173,1710,10,5323,733,5322,0,6174,948,6173,10,7720,2987,167,0,8571,3414,234,10,5324,7720,2984,0,6175,8571,3411,10,5323,1494,2987,0,6174,1709,3414,10,733,5323,7720,0,948,6174,8571,10,2982,7721,2985,0,3409,8572,3412,10,1492,5325,7721,0,1707,6176,8572,10,7721,5324,1493,0,8572,6175,1708,10,5325,733,5324,0,6176,948,6175,10,7722,2991,168,0,8573,3418,235,10,5326,7722,2989,0,6177,8573,3416,10,5329,1496,2991,0,6180,1711,3418,10,734,5329,7722,0,949,6180,8573,10,2992,7723,2988,0,3419,8574,3415,10,1497,5327,7723,0,1712,6178,8574,10,7723,5326,1495,0,8574,6177,1710,10,5327,734,5326,0,6178,949,6177,10,7724,2993,396,0,8575,3420,237,10,5328,7724,3859,0,6179,8575,5435,10,5327,1497,2993,0,6178,1712,3420,10,734,5327,7724,0,949,6178,8575,10,2990,7725,3858,0,3417,8576,5436,10,1496,5329,7725,0,1711,6180,8576,10,7725,5328,1930,0,8576,6179,2720,10,5329,734,5328,0,6180,949,6179,10,7726,2995,392,0,8577,3422,238,10,5330,7726,4003,0,6181,8577,5493,10,5333,1498,2995,0,6184,1713,3422,10,735,5333,7726,0,950,6184,8577,10,2993,7727,4002,0,3420,8578,5494,10,1497,5331,7727,0,1712,6182,8578,10,7727,5330,2002,0,8578,6181,2749,10,5331,735,5330,0,6182,950,6181,10,7728,2992,165,0,8579,3419,232,10,5332,7728,2996,0,6183,8579,3423,10,5331,1497,2992,0,6182,1712,3419,10,735,5331,7728,0,950,6182,8579,10,2994,7729,2997,0,3421,8580,3424,10,1498,5333,7729,0,1713,6184,8580,10,7729,5332,1499,0,8580,6183,1714,10,5333,735,5332,0,6184,950,6183,10,7730,2999,171,0,8581,3426,240,10,5334,7730,3004,0,6185,8581,3431,10,5337,1500,2999,0,6188,1715,3426,10,736,5337,7730,0,951,6188,8581,10,3002,7731,3005,0,3429,8582,3432,10,1502,5335,7731,0,1717,6186,8582,10,7731,5334,1503,0,8582,6185,1718,10,5335,736,5334,0,6186,951,6185,10,7732,3003,173,0,8583,3430,242,10,5336,7732,3000,0,6187,8583,3427,10,5335,1502,3003,0,6186,1717,3430,10,736,5335,7732,0,951,6186,8583,10,2998,7733,3001,0,3425,8584,3428,10,1500,5337,7733,0,1715,6188,8584,10,7733,5336,1501,0,8584,6187,1716,10,5337,736,5336,0,6188,951,6187,10,7734,3007,175,0,8585,3434,244,10,5338,7734,3012,0,6189,8585,3439,10,5341,1504,3007,0,6192,1719,3434,10,737,5341,7734,0,952,6192,8585,10,3010,7735,3013,0,3437,8586,3440,10,1506,5339,7735,0,1721,6190,8586,10,7735,5338,1507,0,8586,6189,1722,10,5339,737,5338,0,6190,952,6189,10,7736,3011,177,0,8587,3438,246,10,5340,7736,3008,0,6191,8587,3435,10,5339,1506,3011,0,6190,1721,3438,10,737,5339,7736,0,952,6190,8587,10,3006,7737,3009,0,3433,8588,3436,10,1504,5341,7737,0,1719,6192,8588,10,7737,5340,1505,0,8588,6191,1720,10,5341,737,5340,0,6192,952,6191,10,7738,3015,173,0,8589,3442,242,10,5342,7738,3003,0,6193,8589,3430,10,5345,1508,3015,0,6196,1723,3442,10,738,5345,7738,0,953,6196,8589,10,3018,7739,3002,0,3445,8590,3429,10,1510,5343,7739,0,1725,6194,8590,10,7739,5342,1502,0,8590,6193,1717,10,5343,738,5342,0,6194,953,6193,10,7740,3019,179,0,8591,3446,248,10,5344,7740,3016,0,6195,8591,3443,10,5343,1510,3019,0,6194,1725,3446,10,738,5343,7740,0,953,6194,8591,10,3014,7741,3017,0,3441,8592,3444,10,1508,5345,7741,0,1723,6196,8592,10,7741,5344,1509,0,8592,6195,1724,10,5345,738,5344,0,6196,953,6195,10,7742,3021,180,0,8593,3448,249,10,5346,7742,3026,0,6197,8593,3453,10,5349,1511,3021,0,6200,1726,3448,10,739,5349,7742,0,954,6200,8593,10,3024,7743,3027,0,3451,8594,3454,10,1513,5347,7743,0,1728,6198,8594,10,7743,5346,1514,0,8594,6197,1729,10,5347,739,5346,0,6198,954,6197,10,7744,3025,182,0,8595,3452,251,10,5348,7744,3022,0,6199,8595,3449,10,5347,1513,3025,0,6198,1728,3452,10,739,5347,7744,0,954,6198,8595,10,3020,7745,3023,0,3447,8596,3450,10,1511,5349,7745,0,1726,6200,8596,10,7745,5348,1512,0,8596,6199,1727,10,5349,739,5348,0,6200,954,6199,10,7746,3029,184,0,8597,3456,253,10,5350,7746,3032,0,6201,8597,3459,10,5353,1515,3029,0,6204,1730,3456,10,740,5353,7746,0,955,6204,8597,10,3023,7747,3033,0,3450,8598,3460,10,1512,5351,7747,0,1727,6202,8598,10,7747,5350,1517,0,8598,6201,1732,10,5351,740,5350,0,6202,955,6201,10,7748,3022,182,0,8599,3449,251,10,5352,7748,3030,0,6203,8599,3457,10,5351,1512,3022,0,6202,1727,3449,10,740,5351,7748,0,955,6202,8599,10,3028,7749,3031,0,3455,8600,3458,10,1515,5353,7749,0,1730,6204,8600,10,7749,5352,1516,0,8600,6203,1731,10,5353,740,5352,0,6204,955,6203,10,7750,3035,186,0,8601,3462,255,10,5354,7750,3040,0,6205,8601,3467,10,5357,1518,3035,0,6208,1733,3462,10,741,5357,7750,0,956,6208,8601,10,3038,7751,3041,0,3465,8602,3468,10,1520,5355,7751,0,1735,6206,8602,10,7751,5354,1521,0,8602,6205,1736,10,5355,741,5354,0,6206,956,6205,10,7752,3039,187,0,8603,3466,256,10,5356,7752,3036,0,6207,8603,3463,10,5355,1520,3039,0,6206,1735,3466,10,741,5355,7752,0,956,6206,8603,10,3034,7753,3037,0,3461,8604,3464,10,1518,5357,7753,0,1733,6208,8604,10,7753,5356,1519,0,8604,6207,1734,10,5357,741,5356,0,6208,956,6207,10,7754,3043,141,0,8605,3470,208,10,5358,7754,3048,0,6209,8605,3475,10,5361,1522,3043,0,6212,1737,3470,10,742,5361,7754,0,957,6212,8605,10,3046,7755,3049,0,3473,8606,3476,10,1524,5359,7755,0,1739,6210,8606,10,7755,5358,1525,0,8606,6209,1740,10,5359,742,5358,0,6210,957,6209,10,7756,3047,189,0,8607,3474,258,10,5360,7756,3044,0,6211,8607,3471,10,5359,1524,3047,0,6210,1739,3474,10,742,5359,7756,0,957,6210,8607,10,3042,7757,3045,0,3469,8608,3472,10,1522,5361,7757,0,1737,6212,8608,10,7757,5360,1523,0,8608,6211,1738,10,5361,742,5360,0,6212,957,6211,10,7758,3051,138,0,8609,3478,205,10,5362,7758,2893,0,6213,8609,3320,10,5365,1526,3051,0,6216,1741,3478,10,743,5365,7758,0,958,6216,8609,10,3045,7759,2892,0,3472,8610,3319,10,1523,5363,7759,0,1738,6214,8610,10,7759,5362,1447,0,8610,6213,1662,10,5363,743,5362,0,6214,958,6213,10,7760,3044,189,0,8611,3471,258,10,5364,7760,3052,0,6215,8611,3479,10,5363,1523,3044,0,6214,1738,3471,10,743,5363,7760,0,958,6214,8611,10,3050,7761,3053,0,3477,8612,3480,10,1526,5365,7761,0,1741,6216,8612,10,7761,5364,1527,0,8612,6215,1742,10,5365,743,5364,0,6216,958,6215,10,7762,3055,192,0,8613,3482,261,10,5366,7762,3056,0,6217,8613,3483,10,5369,1528,3055,0,6220,1743,3482,10,744,5369,7762,0,959,6220,8613,10,3053,7763,3057,0,3480,8614,3484,10,1527,5367,7763,0,1742,6218,8614,10,7763,5366,1529,0,8614,6217,1744,10,5367,744,5366,0,6218,959,6217,10,7764,3052,189,0,8615,3479,258,10,5368,7764,3047,0,6219,8615,3474,10,5367,1527,3052,0,6218,1742,3479,10,744,5367,7764,0,959,6218,8615,10,3054,7765,3046,0,3481,8616,3473,10,1528,5369,7765,0,1743,6220,8616,10,7765,5368,1524,0,8616,6219,1739,10,5369,744,5368,0,6220,959,6219,10,7766,3059,193,0,8617,3486,262,10,5370,7766,3064,0,6221,8617,3491,10,5373,1530,3059,0,6224,1745,3486,10,745,5373,7766,0,960,6224,8617,10,3062,7767,3065,0,3489,8618,3492,10,1532,5371,7767,0,1747,6222,8618,10,7767,5370,1533,0,8618,6221,1748,10,5371,745,5370,0,6222,960,6221,10,7768,3063,195,0,8619,3490,264,10,5372,7768,3060,0,6223,8619,3487,10,5371,1532,3063,0,6222,1747,3490,10,745,5371,7768,0,960,6222,8619,10,3058,7769,3061,0,3485,8620,3488,10,1530,5373,7769,0,1745,6224,8620,10,7769,5372,1531,0,8620,6223,1746,10,5373,745,5372,0,6224,960,6223,10,7770,3067,111,0,8621,3494,175,10,5374,7770,3072,0,6225,8621,3499,10,5377,1534,3067,0,6228,1749,3494,10,746,5377,7770,0,961,6228,8621,10,3070,7771,3073,0,3497,8622,3500,10,1536,5375,7771,0,1751,6226,8622,10,7771,5374,1537,0,8622,6225,1752,10,5375,746,5374,0,6226,961,6225,10,7772,3071,197,0,8623,3498,266,10,5376,7772,3068,0,6227,8623,3495,10,5375,1536,3071,0,6226,1751,3498,10,746,5375,7772,0,961,6226,8623,10,3066,7773,3069,0,3493,8624,3496,10,1534,5377,7773,0,1749,6228,8624,10,7773,5376,1535,0,8624,6227,1750,10,5377,746,5376,0,6228,961,6227,10,7774,3075,108,0,8625,3502,172,10,5378,7774,2809,0,6229,8625,3236,10,5381,1538,3075,0,6232,1753,3502,10,747,5381,7774,0,962,6232,8625,10,3069,7775,2808,0,3496,8626,3235,10,1535,5379,7775,0,1750,6230,8626,10,7775,5378,1405,0,8626,6229,1620,10,5379,747,5378,0,6230,962,6229,10,7776,3068,197,0,8627,3495,266,10,5380,7776,3076,0,6231,8627,3503,10,5379,1535,3068,0,6230,1750,3495,10,747,5379,7776,0,962,6230,8627,10,3074,7777,3077,0,3501,8628,3504,10,1538,5381,7777,0,1753,6232,8628,10,7777,5380,1539,0,8628,6231,1754,10,5381,747,5380,0,6232,962,6231,10,7778,3079,199,0,8629,3506,268,10,5382,7778,3084,0,6233,8629,3511,10,5385,1540,3079,0,6236,1755,3506,10,748,5385,7778,0,963,6236,8629,10,3082,7779,3085,0,3509,8630,3512,10,1542,5383,7779,0,1757,6234,8630,10,7779,5382,1543,0,8630,6233,1758,10,5383,748,5382,0,6234,963,6233,10,7780,3083,158,0,8631,3510,225,10,5384,7780,3080,0,6235,8631,3507,10,5383,1542,3083,0,6234,1757,3510,10,748,5383,7780,0,963,6234,8631,10,3078,7781,3081,0,3505,8632,3508,10,1540,5385,7781,0,1755,6236,8632,10,7781,5384,1541,0,8632,6235,1756,10,5385,748,5384,0,6236,963,6235,10,7782,2830,117,0,8633,3257,181,10,5386,7782,2947,0,6237,8633,3374,10,5389,1416,2830,0,6240,1631,3257,10,749,5389,7782,0,964,6240,8633,10,3088,7783,2946,0,3515,8634,3373,10,1545,5387,7783,0,1760,6238,8634,10,7783,5386,1474,0,8634,6237,1689,10,5387,749,5386,0,6238,964,6237,10,7784,3089,202,0,8635,3516,271,10,5388,7784,3086,0,6239,8635,3513,10,5387,1545,3089,0,6238,1760,3516,10,749,5387,7784,0,964,6238,8635,10,2831,7785,3087,0,3258,8636,3514,10,1416,5389,7785,0,1631,6240,8636,10,7785,5388,1544,0,8636,6239,1759,10,5389,749,5388,0,6240,964,6239,10,7786,3091,116,0,8637,3518,180,10,5390,7786,3094,0,6241,8637,3521,10,5393,1546,3091,0,6244,1761,3518,10,750,5393,7786,0,965,6244,8637,10,3085,7787,3095,0,3512,8638,3522,10,1543,5391,7787,0,1758,6242,8638,10,7787,5390,1548,0,8638,6241,1763,10,5391,750,5390,0,6242,965,6241,10,7788,3084,199,0,8639,3511,268,10,5392,7788,3092,0,6243,8639,3519,10,5391,1543,3084,0,6242,1758,3511,10,750,5391,7788,0,965,6242,8639,10,3090,7789,3093,0,3517,8640,3520,10,1546,5393,7789,0,1761,6244,8640,10,7789,5392,1547,0,8640,6243,1762,10,5393,750,5392,0,6244,965,6243,10,7790,3097,204,0,8641,3524,273,10,5394,7790,3100,0,6245,8641,3527,10,5397,1549,3097,0,6248,1764,3524,10,751,5397,7790,0,966,6248,8641,10,3098,7791,3101,0,3525,8642,3528,10,1550,5395,7791,0,1765,6246,8642,10,7791,5394,1551,0,8642,6245,1766,10,5395,751,5394,0,6246,966,6245,10,7792,3099,151,0,8643,3526,218,10,5396,7792,2929,0,6247,8643,3356,10,5395,1550,3099,0,6246,1765,3526,10,751,5395,7792,0,966,6246,8643,10,3096,7793,2928,0,3523,8644,3355,10,1549,5397,7793,0,1764,6248,8644,10,7793,5396,1465,0,8644,6247,1680,10,5397,751,5396,0,6248,966,6247,10,7794,2964,148,0,8645,3391,215,10,5398,7794,2923,0,6249,8645,3350,10,5401,1483,2964,0,6252,1698,3391,10,752,5401,7794,0,967,6252,8645,10,3104,7795,2922,0,3531,8646,3349,10,1553,5399,7795,0,1768,6250,8646,10,7795,5398,1462,0,8646,6249,1677,10,5399,752,5398,0,6250,967,6249,10,7796,3105,206,0,8647,3532,275,10,5400,7796,3102,0,6251,8647,3529,10,5399,1553,3105,0,6250,1768,3532,10,752,5399,7796,0,967,6250,8647,10,2965,7797,3103,0,3392,8648,3530,10,1483,5401,7797,0,1698,6252,8648,10,7797,5400,1552,0,8648,6251,1767,10,5401,752,5400,0,6252,967,6251,10,7798,3107,160,0,8649,3534,227,10,5402,7798,2963,0,6253,8649,3390,10,5405,1554,3107,0,6256,1769,3534,10,753,5405,7798,0,968,6256,8649,10,3103,7799,2962,0,3530,8650,3389,10,1552,5403,7799,0,1767,6254,8650,10,7799,5402,1482,0,8650,6253,1697,10,5403,753,5402,0,6254,968,6253,10,7800,3102,206,0,8651,3529,275,10,5404,7800,3108,0,6255,8651,3535,10,5403,1552,3102,0,6254,1767,3529,10,753,5403,7800,0,968,6254,8651,10,3106,7801,3109,0,3533,8652,3536,10,1554,5405,7801,0,1769,6256,8652,10,7801,5404,1555,0,8652,6255,1770,10,5405,753,5404,0,6256,968,6255,10,7802,3111,207,0,8653,3538,276,10,5406,7802,3114,0,6257,8653,3541,10,5409,1556,3111,0,6260,1771,3538,10,754,5409,7802,0,969,6260,8653,10,3007,7803,3115,0,3434,8654,3542,10,1504,5407,7803,0,1719,6258,8654,10,7803,5406,1558,0,8654,6257,1773,10,5407,754,5406,0,6258,969,6257,10,7804,3006,176,0,8655,3433,245,10,5408,7804,3112,0,6259,8655,3539,10,5407,1504,3006,0,6258,1719,3433,10,754,5407,7804,0,969,6258,8655,10,3110,7805,3113,0,3537,8656,3540,10,1556,5409,7805,0,1771,6260,8656,10,7805,5408,1557,0,8656,6259,1772,10,5409,754,5408,0,6260,969,6259,10,7806,3117,209,0,8657,3544,278,10,5410,7806,3120,0,6261,8657,3547,10,5413,1559,3117,0,6264,1774,3544,10,755,5413,7806,0,970,6264,8657,10,3115,7807,3121,0,3542,8658,3548,10,1558,5411,7807,0,1773,6262,8658,10,7807,5410,1561,0,8658,6261,1776,10,5411,755,5410,0,6262,970,6261,10,7808,3114,207,0,8659,3541,276,10,5412,7808,3118,0,6263,8659,3545,10,5411,1558,3114,0,6262,1773,3541,10,755,5411,7808,0,970,6262,8659,10,3116,7809,3119,0,3543,8660,3546,10,1559,5413,7809,0,1774,6264,8660,10,7809,5412,1560,0,8660,6263,1775,10,5413,755,5412,0,6264,970,6263,10,7810,3118,207,0,8661,5354,280,10,5414,7810,3124,0,6265,8661,3551,10,5417,1560,3118,0,6268,2679,5354,10,756,5417,7810,0,971,6268,8661,10,3097,7811,3125,0,3524,8662,3552,10,1549,5415,7811,0,1764,6266,8662,10,7811,5414,1563,0,8662,6265,1778,10,5415,756,5414,0,6266,971,6265,10,7812,3096,152,0,8663,3523,219,10,5416,7812,3122,0,6267,8663,3549,10,5415,1549,3096,0,6266,1764,3523,10,756,5415,7812,0,971,6266,8663,10,3119,7813,3123,0,5353,8664,3550,10,1560,5417,7813,0,2679,6268,8664,10,7813,5416,1562,0,8664,6267,1777,10,5417,756,5416,0,6268,971,6267,10,7814,3124,207,0,8665,3551,280,10,5418,7814,3111,0,6269,8665,5351,10,5421,1563,3124,0,6272,1778,3551,10,757,5421,7814,0,972,6272,8665,10,3128,7815,3110,0,3555,8666,5352,10,1565,5419,7815,0,1780,6270,8666,10,7815,5418,1556,0,8666,6269,2678,10,5419,757,5418,0,6270,972,6269,10,7816,3129,211,0,8667,3556,282,10,5420,7816,3126,0,6271,8667,3553,10,5419,1565,3129,0,6270,1780,3556,10,757,5419,7816,0,972,6270,8667,10,3125,7817,3127,0,3552,8668,3554,10,1563,5421,7817,0,1778,6272,8668,10,7817,5420,1564,0,8668,6271,1779,10,5421,757,5420,0,6272,972,6271,10,7818,3038,188,0,8669,3465,257,10,5422,7818,3134,0,6273,8669,3561,10,5425,1520,3038,0,6276,1735,3465,10,758,5425,7818,0,973,6276,8669,10,3132,7819,3135,0,3559,8670,3562,10,1567,5423,7819,0,1782,6274,8670,10,7819,5422,1568,0,8670,6273,1783,10,5423,758,5422,0,6274,973,6273,10,7820,3133,212,0,8671,3560,284,10,5424,7820,3130,0,6275,8671,3557,10,5423,1567,3133,0,6274,1782,3560,10,758,5423,7820,0,973,6274,8671,10,3039,7821,3131,0,3466,8672,3558,10,1520,5425,7821,0,1735,6276,8672,10,7821,5424,1566,0,8672,6275,1781,10,5425,758,5424,0,6276,973,6275,10,7822,3130,212,0,8673,3557,284,10,5426,7822,3140,0,6277,8673,3567,10,5429,1566,3130,0,6280,1781,3557,10,759,5429,7822,0,974,6280,8673,10,3138,7823,3141,0,3565,8674,3568,10,1570,5427,7823,0,1785,6278,8674,10,7823,5426,1571,0,8674,6277,1786,10,5427,759,5426,0,6278,974,6277,10,7824,3139,214,0,8675,3566,286,10,5428,7824,3136,0,6279,8675,3563,10,5427,1570,3139,0,6278,1785,3566,10,759,5427,7824,0,974,6278,8675,10,3131,7825,3137,0,3558,8676,3564,10,1566,5429,7825,0,1781,6280,8676,10,7825,5428,1569,0,8676,6279,1784,10,5429,759,5428,0,6280,974,6279,10,7826,3140,212,0,8677,5358,288,10,5430,7826,3144,0,6281,8677,3571,10,5433,1571,3140,0,6284,2681,5358,10,760,5433,7826,0,975,6284,8677,10,3079,7827,3145,0,3506,8678,3572,10,1540,5431,7827,0,1755,6282,8678,10,7827,5430,1573,0,8678,6281,1788,10,5431,760,5430,0,6282,975,6281,10,7828,3078,200,0,8679,3505,269,10,5432,7828,3142,0,6283,8679,3569,10,5431,1540,3078,0,6282,1755,3505,10,760,5431,7828,0,975,6282,8679,10,3141,7829,3143,0,5357,8680,3570,10,1571,5433,7829,0,2681,6284,8680,10,7829,5432,1572,0,8680,6283,1787,10,5433,760,5432,0,6284,975,6283,10,7830,3147,203,0,8681,3574,272,10,5434,7830,3093,0,6285,8681,3520,10,5437,1574,3147,0,6288,1789,3574,10,761,5437,7830,0,976,6288,8681,10,3145,7831,3092,0,3572,8682,3519,10,1573,5435,7831,0,1788,6286,8682,10,7831,5434,1547,0,8682,6285,1762,10,5435,761,5434,0,6286,976,6285,10,7832,3144,212,0,8683,3571,288,10,5436,7832,3133,0,6287,8683,5355,10,5435,1573,3144,0,6286,1788,3571,10,761,5435,7832,0,976,6286,8683,10,3146,7833,3132,0,3573,8684,5356,10,1574,5437,7833,0,1789,6288,8684,10,7833,5436,1567,0,8684,6287,2680,10,5437,761,5436,0,6288,976,6287,10,7834,3149,216,0,8685,3576,291,10,5438,7834,3154,0,6289,8685,3581,10,5441,1575,3149,0,6292,1790,3576,10,762,5441,7834,0,977,6292,8685,10,3152,7835,3155,0,3579,8686,3582,10,1577,5439,7835,0,1792,6290,8686,10,7835,5438,1578,0,8686,6289,1793,10,5439,762,5438,0,6290,977,6289,10,7836,3153,112,0,8687,3580,293,10,5440,7836,3150,0,6291,8687,3577,10,5439,1577,3153,0,6290,1792,3580,10,762,5439,7836,0,977,6290,8687,10,3148,7837,3151,0,3575,8688,3578,10,1575,5441,7837,0,1790,6292,8688,10,7837,5440,1576,0,8688,6291,1791,10,5441,762,5440,0,6292,977,6291,10,7838,3157,218,0,8689,3584,295,10,5442,7838,3158,0,6293,8689,3585,10,5445,1579,3157,0,6296,1794,3584,10,763,5445,7838,0,978,6296,8689,10,3061,7839,3159,0,5349,8690,3586,10,1531,5443,7839,0,2677,6294,8690,10,7839,5442,1580,0,8690,6293,1795,10,5443,763,5442,0,6294,978,6293,10,7840,3060,195,0,8691,5350,294,10,5444,7840,3155,0,6295,8691,3582,10,5443,1531,3060,0,6294,2677,5350,10,763,5443,7840,0,978,6294,8691,10,3156,7841,3154,0,3583,8692,3581,10,1579,5445,7841,0,1794,6296,8692,10,7841,5444,1578,0,8692,6295,1793,10,5445,763,5444,0,6296,978,6295,10,7842,3161,142,0,8693,3588,209,10,5446,7842,3164,0,6297,8693,3591,10,5449,1581,3161,0,6300,1796,3588,10,764,5449,7842,0,979,6300,8693,10,3157,7843,3165,0,3584,8694,3592,10,1579,5447,7843,0,1794,6298,8694,10,7843,5446,1583,0,8694,6297,1798,10,5447,764,5446,0,6298,979,6297,10,7844,3156,216,0,8695,3583,291,10,5448,7844,3162,0,6299,8695,3589,10,5447,1579,3156,0,6298,1794,3583,10,764,5447,7844,0,979,6298,8695,10,3160,7845,3163,0,3587,8696,3590,10,1581,5449,7845,0,1796,6300,8696,10,7845,5448,1582,0,8696,6299,1797,10,5449,764,5448,0,6300,979,6299,10,7846,3167,220,0,8697,3594,298,10,5450,7846,3168,0,6301,8697,3595,10,5453,1584,3167,0,6304,1799,3594,10,765,5453,7846,0,980,6304,8697,10,3163,7847,3169,0,3590,8698,3596,10,1582,5451,7847,0,1797,6302,8698,10,7847,5450,1585,0,8698,6301,1800,10,5451,765,5450,0,6302,980,6301,10,7848,3162,216,0,8699,3589,291,10,5452,7848,3149,0,6303,8699,3576,10,5451,1582,3162,0,6302,1797,3589,10,765,5451,7848,0,980,6302,8699,10,3166,7849,3148,0,3593,8700,3575,10,1584,5453,7849,0,1799,6304,8700,10,7849,5452,1575,0,8700,6303,1790,10,5453,765,5452,0,6304,980,6303,10,7850,3183,227,0,8701,3610,305,10,5454,7850,3186,0,6305,8701,3613,10,5457,1592,3183,0,6308,1807,3610,10,766,5457,7850,0,981,6308,8701,10,2799,7851,3187,0,3226,8702,3614,10,1400,5455,7851,0,1615,6306,8702,10,7851,5454,1594,0,8702,6305,1809,10,5455,766,5454,0,6306,981,6305,10,7852,2798,105,0,8703,3225,169,10,5456,7852,3184,0,6307,8703,3611,10,5455,1400,2798,0,6306,1615,3225,10,766,5455,7852,0,981,6306,8703,10,3182,7853,3185,0,3609,8704,3612,10,1592,5457,7853,0,1807,6308,8704,10,7853,5456,1593,0,8704,6307,1808,10,5457,766,5456,0,6308,981,6307,10,7854,3182,228,0,8705,3609,306,10,5458,7854,3190,0,6309,8705,3617,10,5461,1592,3182,0,6312,1807,3609,10,767,5461,7854,0,982,6312,8705,10,3392,7855,3191,0,3819,8706,3618,10,1697,5459,7855,0,1912,6310,8706,10,7855,5458,1596,0,8706,6309,1811,10,5459,767,5458,0,6310,982,6309,10,7856,3393,277,0,8707,3820,366,10,5460,7856,3188,0,6311,8707,3615,10,5459,1697,3393,0,6310,1912,3820,10,767,5459,7856,0,982,6310,8707,10,3183,7857,3189,0,3610,8708,3616,10,1592,5461,7857,0,1807,6312,8708,10,7857,5460,1595,0,8708,6311,1810,10,5461,767,5460,0,6312,982,6311,10,7858,3190,228,0,8709,3617,306,10,5462,7858,3192,0,6313,8709,3619,10,5465,1596,3190,0,6316,1811,3617,10,768,5465,7858,0,983,6316,8709,10,2919,7859,3193,0,3346,8710,3620,10,1460,5463,7859,0,1675,6314,8710,10,7859,5462,1597,0,8710,6313,1812,10,5463,768,5462,0,6314,983,6313,10,7860,2918,137,0,8711,3345,204,10,5464,7860,3409,0,6315,8711,3836,10,5463,1460,2918,0,6314,1675,3345,10,768,5463,7860,0,983,6314,8711,10,3191,7861,3408,0,3618,8712,3835,10,1596,5465,7861,0,1811,6316,8712,10,7861,5464,1705,0,8712,6315,1920,10,5465,768,5464,0,6316,983,6315,10,7862,3195,229,0,8713,3622,307,10,5466,7862,3193,0,6317,8713,3620,10,5469,1598,3195,0,6320,1813,3622,10,769,5469,7862,0,984,6320,8713,10,3185,7863,3192,0,3612,8714,3619,10,1593,5467,7863,0,1808,6318,8714,10,7863,5466,1597,0,8714,6317,1812,10,5467,769,5466,0,6318,984,6317,10,7864,3184,105,0,8715,3611,169,10,5468,7864,2805,0,6319,8715,3232,10,5467,1593,3184,0,6318,1808,3611,10,769,5467,7864,0,984,6318,8715,10,3194,7865,2804,0,3621,8716,3231,10,1598,5469,7865,0,1813,6320,8716,10,7865,5468,1403,0,8716,6319,1618,10,5469,769,5468,0,6320,984,6319,10,7866,3197,230,0,8717,3624,308,10,5470,7866,3202,0,6321,8717,3629,10,5473,1599,3197,0,6324,1814,3624,10,770,5473,7866,0,985,6324,8717,10,3200,7867,3203,0,3627,8718,3630,10,1601,5471,7867,0,1816,6322,8718,10,7867,5470,1602,0,8718,6321,1817,10,5471,770,5470,0,6322,985,6321,10,7868,3201,232,0,8719,3628,310,10,5472,7868,3198,0,6323,8719,3625,10,5471,1601,3201,0,6322,1816,3628,10,770,5471,7868,0,985,6322,8719,10,3196,7869,3199,0,3623,8720,3626,10,1599,5473,7869,0,1814,6324,8720,10,7869,5472,1600,0,8720,6323,1815,10,5473,770,5472,0,6324,985,6323,10,7870,3205,231,0,8721,3632,309,10,5474,7870,3199,0,6325,8721,3626,10,5477,1603,3205,0,6328,1818,3632,10,771,5477,7870,0,986,6328,8721,10,3208,7871,3198,0,3635,8722,3625,10,1605,5475,7871,0,1820,6326,8722,10,7871,5474,1600,0,8722,6325,1815,10,5475,771,5474,0,6326,986,6325,10,7872,3209,235,0,8723,3636,313,10,5476,7872,3206,0,6327,8723,3633,10,5475,1605,3209,0,6326,1820,3636,10,771,5475,7872,0,986,6326,8723,10,3204,7873,3207,0,3631,8724,3634,10,1603,5477,7873,0,1818,6328,8724,10,7873,5476,1604,0,8724,6327,1819,10,5477,771,5476,0,6328,986,6327,10,7874,3200,233,0,8725,3627,311,10,5478,7874,3212,0,6329,8725,3639,10,5481,1601,3200,0,6332,1816,3627,10,772,5481,7874,0,987,6332,8725,10,2979,7875,3213,0,3406,8726,3640,10,1490,5479,7875,0,1705,6330,8726,10,7875,5478,1607,0,8726,6329,1822,10,5479,772,5478,0,6330,987,6329,10,7876,2978,164,0,8727,3405,231,10,5480,7876,3210,0,6331,8727,3637,10,5479,1490,2978,0,6330,1705,3405,10,772,5479,7876,0,987,6330,8727,10,3201,7877,3211,0,3628,8728,3638,10,1601,5481,7877,0,1816,6332,8728,10,7877,5480,1606,0,8728,6331,1821,10,5481,772,5480,0,6332,987,6331,10,7878,3215,236,0,8729,3642,314,10,5482,7878,3218,0,6333,8729,3645,10,5485,1608,3215,0,6336,1823,3642,10,773,5485,7878,0,988,6336,8729,10,2875,7879,3219,0,3302,8730,3646,10,1438,5483,7879,0,1653,6334,8730,10,7879,5482,1610,0,8730,6333,1825,10,5483,773,5482,0,6334,988,6333,10,7880,2874,133,0,8731,3301,200,10,5484,7880,3216,0,6335,8731,3643,10,5483,1438,2874,0,6334,1653,3301,10,773,5483,7880,0,988,6334,8731,10,3214,7881,3217,0,3641,8732,3644,10,1608,5485,7881,0,1823,6336,8732,10,7881,5484,1609,0,8732,6335,1824,10,5485,773,5484,0,6336,988,6335,10,7882,2914,236,0,8733,3341,314,10,5486,7882,3215,0,6337,8733,3642,10,5489,1458,2914,0,6340,1673,3341,10,774,5489,7882,0,989,6340,8733,10,3220,7883,3214,0,3647,8734,3641,10,1611,5487,7883,0,1826,6338,8734,10,7883,5486,1608,0,8734,6337,1823,10,5487,774,5486,0,6338,989,6337,10,7884,3221,280,0,8735,3648,369,10,5488,7884,3410,0,6339,8735,3837,10,5487,1611,3221,0,6338,1826,3648,10,774,5487,7884,0,989,6338,8735,10,2915,7885,3411,0,3342,8736,3838,10,1458,5489,7885,0,1673,6340,8736,10,7885,5488,1706,0,8736,6339,1921,10,5489,774,5488,0,6340,989,6339,10,7886,3220,237,0,8737,3647,315,10,5490,7886,3224,0,6341,8737,3651,10,5493,1611,3220,0,6344,1826,3647,10,775,5493,7886,0,990,6344,8737,10,3222,7887,3225,0,3649,8738,3652,10,1612,5491,7887,0,1827,6342,8738,10,7887,5490,1613,0,8738,6341,1828,10,5491,775,5490,0,6342,990,6341,10,7888,3223,283,0,8739,3650,372,10,5492,7888,3424,0,6343,8739,3851,10,5491,1612,3223,0,6342,1827,3650,10,775,5491,7888,0,990,6342,8739,10,3221,7889,3425,0,3648,8740,3852,10,1611,5493,7889,0,1826,6344,8740,10,7889,5492,1713,0,8740,6343,1928,10,5493,775,5492,0,6344,990,6343,10,7890,3224,237,0,8741,3651,315,10,5494,7890,3217,0,6345,8741,3644,10,5497,1613,3224,0,6348,1828,3651,10,776,5497,7890,0,991,6348,8741,10,2881,7891,3216,0,3308,8742,3643,10,1441,5495,7891,0,1656,6346,8742,10,7891,5494,1609,0,8742,6345,1824,10,5495,776,5494,0,6346,991,6345,10,7892,2880,134,0,8743,3307,201,10,5496,7892,3226,0,6347,8743,3653,10,5495,1441,2880,0,6346,1656,3307,10,776,5495,7892,0,991,6346,8743,10,3225,7893,3227,0,3652,8744,3654,10,1613,5497,7893,0,1828,6348,8744,10,7893,5496,1614,0,8744,6347,1829,10,5497,776,5496,0,6348,991,6347,10,7894,2850,240,0,8745,3277,318,10,5498,7894,3230,0,6349,8745,3657,10,5501,1426,2850,0,6352,1641,3277,10,777,5501,7894,0,992,6352,8745,10,3228,7895,3231,0,3655,8746,3658,10,1615,5499,7895,0,1830,6350,8746,10,7895,5498,1616,0,8746,6349,1831,10,5499,777,5498,0,6350,992,6349,10,7896,3229,284,0,8747,3656,373,10,5500,7896,3426,0,6351,8747,3853,10,5499,1615,3229,0,6350,1830,3656,10,777,5499,7896,0,992,6350,8747,10,2851,7897,3427,0,3278,8748,3854,10,1426,5501,7897,0,1641,6352,8748,10,7897,5500,1714,0,8748,6351,1929,10,5501,777,5500,0,6352,992,6351,10,7898,3228,239,0,8749,3655,317,10,5502,7898,3234,0,6353,8749,3661,10,5505,1615,3228,0,6356,1830,3655,10,778,5505,7898,0,993,6356,8749,10,3232,7899,3235,0,3659,8750,3662,10,1617,5503,7899,0,1832,6354,8750,10,7899,5502,1618,0,8750,6353,1833,10,5503,778,5502,0,6354,993,6353,10,7900,3233,287,0,8751,3660,376,10,5504,7900,3443,0,6355,8751,3870,10,5503,1617,3233,0,6354,1832,3660,10,778,5503,7900,0,993,6354,8751,10,3229,7901,3442,0,3656,8752,3869,10,1615,5505,7901,0,1830,6356,8752,10,7901,5504,1722,0,8752,6355,1937,10,5505,778,5504,0,6356,993,6355,10,7902,3232,241,0,8753,3659,319,10,5506,7902,3238,0,6357,8753,3665,10,5509,1617,3232,0,6360,1832,3659,10,779,5509,7902,0,994,6360,8753,10,3236,7903,3239,0,3663,8754,3666,10,1619,5507,7903,0,1834,6358,8754,10,7903,5506,1620,0,8754,6357,1835,10,5507,779,5506,0,6358,994,6357,10,7904,3237,288,0,8755,3664,377,10,5508,7904,3448,0,6359,8755,3875,10,5507,1619,3237,0,6358,1834,3664,10,779,5507,7904,0,994,6358,8755,10,3233,7905,3449,0,3660,8756,3876,10,1617,5509,7905,0,1832,6360,8756,10,7905,5508,1725,0,8756,6359,1940,10,5509,779,5508,0,6360,994,6359,10,7906,3188,277,0,8757,3615,366,10,5510,7906,3463,0,6361,8757,3890,10,5513,1595,3188,0,6364,1810,3615,10,780,5513,7906,0,995,6364,8757,10,3237,7907,3462,0,3664,8758,3889,10,1619,5511,7907,0,1834,6362,8758,10,7907,5510,1732,0,8758,6361,1947,10,5511,780,5510,0,6362,995,6361,10,7908,3236,242,0,8759,3663,320,10,5512,7908,3240,0,6363,8759,3667,10,5511,1619,3236,0,6362,1834,3663,10,780,5511,7908,0,995,6362,8759,10,3189,7909,3241,0,3616,8760,3668,10,1595,5513,7909,0,1810,6364,8760,10,7909,5512,1621,0,8760,6363,1836,10,5513,780,5512,0,6364,995,6363,10,7910,3243,243,0,8761,3670,321,10,5514,7910,3246,0,6365,8761,3673,10,5517,1622,3243,0,6368,1837,3670,10,781,5517,7910,0,996,6368,8761,10,3244,7911,3247,0,3671,8762,3674,10,1623,5515,7911,0,1838,6366,8762,10,7911,5514,1624,0,8762,6365,1839,10,5515,781,5514,0,6366,996,6365,10,7912,3245,130,0,8763,3672,197,10,5516,7912,2879,0,6367,8763,3306,10,5515,1623,3245,0,6366,1838,3672,10,781,5515,7912,0,996,6366,8763,10,3242,7913,2878,0,3669,8764,3305,10,1622,5517,7913,0,1837,6368,8764,10,7913,5516,1440,0,8764,6367,1655,10,5517,781,5516,0,6368,996,6367,10,7914,3249,129,0,8765,3676,196,10,5518,7914,2869,0,6369,8765,3296,10,5521,1625,3249,0,6372,1840,3676,10,782,5521,7914,0,997,6372,8765,10,3245,7915,2868,0,3672,8766,3295,10,1623,5519,7915,0,1838,6370,8766,10,7915,5518,1435,0,8766,6369,1650,10,5519,782,5518,0,6370,997,6369,10,7916,3244,244,0,8767,3671,322,10,5520,7916,3250,0,6371,8767,3677,10,5519,1623,3244,0,6370,1838,3671,10,782,5519,7916,0,997,6370,8767,10,3248,7917,3251,0,3675,8768,3678,10,1625,5521,7917,0,1840,6372,8768,10,7917,5520,1626,0,8768,6371,1841,10,5521,782,5520,0,6372,997,6371,10,7918,2784,100,0,8769,3211,164,10,5522,7918,3254,0,6373,8769,3681,10,5525,1393,2784,0,6376,1608,3211,10,783,5525,7918,0,998,6376,8769,10,3251,7919,3255,0,3678,8770,3682,10,1626,5523,7919,0,1841,6374,8770,10,7919,5522,1628,0,8770,6373,1843,10,5523,783,5522,0,6374,998,6373,10,7920,3250,244,0,8771,3677,322,10,5524,7920,3252,0,6375,8771,3679,10,5523,1626,3250,0,6374,1841,3677,10,783,5523,7920,0,998,6374,8771,10,2785,7921,3253,0,3212,8772,3680,10,1393,5525,7921,0,1608,6376,8772,10,7921,5524,1627,0,8772,6375,1842,10,5525,783,5524,0,6376,998,6375,10,7922,3257,106,0,8773,3684,170,10,5526,7922,2803,0,6377,8773,3230,10,5529,1629,3257,0,6380,1844,3684,10,784,5529,7922,0,999,6380,8773,10,3253,7923,2802,0,3680,8774,3229,10,1627,5527,7923,0,1842,6378,8774,10,7923,5526,1402,0,8774,6377,1617,10,5527,784,5526,0,6378,999,6377,10,7924,3252,244,0,8775,3679,322,10,5528,7924,3247,0,6379,8775,3674,10,5527,1627,3252,0,6378,1842,3679,10,784,5527,7924,0,999,6378,8775,10,3256,7925,3246,0,3683,8776,3673,10,1629,5529,7925,0,1844,6380,8776,10,7925,5528,1624,0,8776,6379,1839,10,5529,784,5528,0,6380,999,6379,10,7926,3868,385,0,8777,5446,324,10,5530,7926,3262,0,6381,8777,3689,10,5533,1935,3868,0,6384,2725,5446,10,785,5533,7926,0,1000,6384,8777,10,3260,7927,3263,0,3687,8778,3690,10,1631,5531,7927,0,1846,6382,8778,10,7927,5530,1632,0,8778,6381,1847,10,5531,785,5530,0,6382,1000,6381,10,7928,3261,246,0,8779,3688,326,10,5532,7928,3258,0,6383,8779,3685,10,5531,1631,3261,0,6382,1846,3688,10,785,5531,7928,0,1000,6382,8779,10,3869,7929,3259,0,5445,8780,3686,10,1935,5533,7929,0,2725,6384,8780,10,7929,5532,1630,0,8780,6383,1845,10,5533,785,5532,0,6384,1000,6383,10,7930,3258,246,0,8781,3685,326,10,5534,7930,3266,0,6385,8781,3693,10,5537,1630,3258,0,6388,1845,3685,10,786,5537,7930,0,1001,6388,8781,10,2991,7931,3267,0,5347,8782,3694,10,1496,5535,7931,0,2676,6386,8782,10,7931,5534,1634,0,8782,6385,1849,10,5535,786,5534,0,6386,1001,6385,10,7932,2990,169,0,8783,5348,328,10,5536,7932,3264,0,6387,8783,3691,10,5535,1496,2990,0,6386,2676,5348,10,786,5535,7932,0,1001,6386,8783,10,3259,7933,3265,0,3686,8784,3692,10,1630,5537,7933,0,1845,6388,8784,10,7933,5536,1633,0,8784,6387,1848,10,5537,786,5536,0,6388,1001,6387,10,7934,2986,168,0,8785,5346,329,10,5538,7934,3267,0,6389,8785,3694,10,5541,1494,2986,0,6392,2675,5346,10,787,5541,7934,0,1002,6392,8785,10,3270,7935,3266,0,3697,8786,3693,10,1636,5539,7935,0,1851,6390,8786,10,7935,5538,1634,0,8786,6389,1849,10,5539,787,5538,0,6390,1002,6389,10,7936,3271,248,0,8787,3698,331,10,5540,7936,3268,0,6391,8787,3695,10,5539,1636,3271,0,6390,1851,3698,10,787,5539,7936,0,1002,6390,8787,10,2987,7937,3269,0,5345,8788,3696,10,1494,5541,7937,0,2675,6392,8788,10,7937,5540,1635,0,8788,6391,1850,10,5541,787,5540,0,6392,1002,6391,10,7938,3273,248,0,8789,3700,331,10,5542,7938,3271,0,6393,8789,3698,10,5545,1637,3273,0,6396,1852,3700,10,788,5545,7938,0,1003,6396,8789,10,3261,7939,3270,0,3688,8790,3697,10,1631,5543,7939,0,1846,6394,8790,10,7939,5542,1636,0,8790,6393,1851,10,5543,788,5542,0,6394,1003,6393,10,7940,3260,247,0,8791,3687,327,10,5544,7940,3274,0,6395,8791,3701,10,5543,1631,3260,0,6394,1846,3687,10,788,5543,7940,0,1003,6394,8791,10,3272,7941,3275,0,3699,8792,3702,10,1637,5545,7941,0,1852,6396,8792,10,7941,5544,1638,0,8792,6395,1853,10,5545,788,5544,0,6396,1003,6395,10,7942,3272,249,0,8793,3699,332,10,5546,7942,3280,0,6397,8793,3707,10,5549,1637,3272,0,6400,1852,3699,10,789,5549,7942,0,1004,6400,8793,10,3278,7943,3281,0,3705,8794,3708,10,1640,5547,7943,0,1855,6398,8794,10,7943,5546,1641,0,8794,6397,1856,10,5547,789,5546,0,6398,1004,6397,10,7944,3279,250,0,8795,3706,333,10,5548,7944,3276,0,6399,8795,3703,10,5547,1640,3279,0,6398,1855,3706,10,789,5547,7944,0,1004,6398,8795,10,3273,7945,3277,0,3700,8796,3704,10,1637,5549,7945,0,1852,6400,8796,10,7945,5548,1639,0,8796,6399,1854,10,5549,789,5548,0,6400,1004,6399,10,7946,3268,248,0,8797,3695,331,10,5550,7946,3277,0,6401,8797,3704,10,5553,1635,3268,0,6404,1850,3695,10,790,5553,7946,0,1005,6404,8797,10,3284,7947,3276,0,3711,8798,3703,10,1643,5551,7947,0,1858,6402,8798,10,7947,5550,1639,0,8798,6401,1854,10,5551,790,5550,0,6402,1005,6401,10,7948,3285,252,0,8799,3712,335,10,5552,7948,3282,0,6403,8799,3709,10,5551,1643,3285,0,6402,1858,3712,10,790,5551,7948,0,1005,6402,8799,10,3269,7949,3283,0,3696,8800,3710,10,1635,5553,7949,0,1850,6404,8800,10,7949,5552,1642,0,8800,6403,1857,10,5553,790,5552,0,6404,1005,6403,10,7950,3204,234,0,8801,3631,312,10,5554,7950,3288,0,6405,8801,3715,10,5557,1603,3204,0,6408,1818,3631,10,791,5557,7950,0,1006,6408,8801,10,3285,7951,3289,0,3712,8802,3716,10,1643,5555,7951,0,1858,6406,8802,10,7951,5554,1645,0,8802,6405,1860,10,5555,791,5554,0,6406,1006,6405,10,7952,3284,250,0,8803,3711,333,10,5556,7952,3286,0,6407,8803,3713,10,5555,1643,3284,0,6406,1858,3711,10,791,5555,7952,0,1006,6406,8803,10,3205,7953,3287,0,3632,8804,3714,10,1603,5557,7953,0,1818,6408,8804,10,7953,5556,1644,0,8804,6407,1859,10,5557,791,5556,0,6408,1006,6407,10,7954,3196,231,0,8805,3623,309,10,5558,7954,3287,0,6409,8805,3714,10,5561,1599,3196,0,6412,1814,3623,10,792,5561,7954,0,1007,6412,8805,10,3279,7955,3286,0,3706,8806,3713,10,1640,5559,7955,0,1855,6410,8806,10,7955,5558,1644,0,8806,6409,1859,10,5559,792,5558,0,6410,1007,6409,10,7956,3278,251,0,8807,3705,334,10,5560,7956,3290,0,6411,8807,3717,10,5559,1640,3278,0,6410,1855,3705,10,792,5559,7956,0,1007,6410,8807,10,3197,7957,3291,0,3624,8808,3718,10,1599,5561,7957,0,1814,6412,8808,10,7957,5560,1646,0,8808,6411,1861,10,5561,792,5560,0,6412,1007,6411,10,7958,2970,161,0,8809,3397,228,10,5562,7958,3294,0,6413,8809,3721,10,5565,1486,2970,0,6416,1701,3397,10,793,5565,7958,0,1008,6416,8809,10,3292,7959,3295,0,3719,8810,3722,10,1647,5563,7959,0,1862,6414,8810,10,7959,5562,1648,0,8810,6413,1863,10,5563,793,5562,0,6414,1008,6413,10,7960,3293,238,0,8811,3720,316,10,5564,7960,3227,0,6415,8811,3654,10,5563,1647,3293,0,6414,1862,3720,10,793,5563,7960,0,1008,6414,8811,10,2971,7961,3226,0,3398,8812,3653,10,1486,5565,7961,0,1701,6416,8812,10,7961,5564,1614,0,8812,6415,1829,10,5565,793,5564,0,6416,1008,6415,10,7962,3292,253,0,8813,3719,336,10,5566,7962,3296,0,6417,8813,3723,10,5569,1647,3292,0,6420,1862,3719,10,794,5569,7962,0,1009,6420,8813,10,3464,7963,3297,0,3891,8814,3724,10,1733,5567,7963,0,1948,6418,8814,10,7963,5566,1649,0,8814,6417,1864,10,5567,794,5566,0,6418,1009,6417,10,7964,3465,283,0,8815,3892,372,10,5568,7964,3223,0,6419,8815,3650,10,5567,1733,3465,0,6418,1948,3892,10,794,5567,7964,0,1009,6418,8815,10,3293,7965,3222,0,3720,8816,3649,10,1647,5569,7965,0,1862,6420,8816,10,7965,5568,1612,0,8816,6419,1827,10,5569,794,5568,0,6420,1009,6419,10,7966,3296,253,0,8817,3723,336,10,5570,7966,3298,0,6421,8817,3725,10,5573,1649,3296,0,6424,1864,3723,10,795,5573,7966,0,1010,6424,8817,10,2841,7967,3299,0,3268,8818,3726,10,1421,5571,7967,0,1636,6422,8818,10,7967,5570,1650,0,8818,6421,1865,10,5571,795,5570,0,6422,1010,6421,10,7968,2840,107,0,8819,3267,171,10,5572,7968,3479,0,6423,8819,3906,10,5571,1421,2840,0,6422,1636,3267,10,795,5571,7968,0,1010,6422,8819,10,3297,7969,3478,0,3724,8820,3905,10,1649,5573,7969,0,1864,6424,8820,10,7969,5572,1740,0,8820,6423,1955,10,5573,795,5572,0,6424,1010,6423,10,7970,2976,163,0,8821,3403,230,10,5574,7970,3300,0,6425,8821,3727,10,5577,1489,2976,0,6428,1704,3403,10,796,5577,7970,0,1011,6428,8821,10,3299,7971,3301,0,3726,8822,3728,10,1650,5575,7971,0,1865,6426,8822,10,7971,5574,1651,0,8822,6425,1866,10,5575,796,5574,0,6426,1011,6425,10,7972,3298,253,0,8823,3725,336,10,5576,7972,3295,0,6427,8823,3722,10,5575,1650,3298,0,6426,1865,3725,10,796,5575,7972,0,1011,6426,8823,10,2977,7973,3294,0,3404,8824,3721,10,1489,5577,7973,0,1704,6428,8824,10,7973,5576,1648,0,8824,6427,1863,10,5577,796,5576,0,6428,1011,6427,10,7974,3303,245,0,8825,3730,323,10,5578,7974,3255,0,6429,8825,3682,10,5581,1652,3303,0,6432,1867,3730,10,797,5581,7974,0,1012,6432,8825,10,3306,7975,3254,0,3733,8826,3681,10,1654,5579,7975,0,1869,6430,8826,10,7975,5578,1628,0,8826,6429,1843,10,5579,797,5578,0,6430,1012,6429,10,7976,3307,256,0,8827,3734,343,10,5580,7976,3304,0,6431,8827,3731,10,5579,1654,3307,0,6430,1869,3734,10,797,5579,7976,0,1012,6430,8827,10,3302,7977,3305,0,3729,8828,3732,10,1652,5581,7977,0,1867,6432,8828,10,7977,5580,1653,0,8828,6431,1868,10,5581,797,5580,0,6432,1012,6431,10,7978,3302,255,0,8829,3729,342,10,5582,7978,3310,0,6433,8829,3737,10,5585,1652,3302,0,6436,1867,3729,10,798,5585,7978,0,1013,6436,8829,10,3308,7979,3311,0,3735,8830,3738,10,1655,5583,7979,0,1870,6434,8830,10,7979,5582,1656,0,8830,6433,1871,10,5583,798,5582,0,6434,1013,6433,10,7980,3309,129,0,8831,3736,196,10,5584,7980,3249,0,6435,8831,3676,10,5583,1655,3309,0,6434,1870,3736,10,798,5583,7980,0,1013,6434,8831,10,3303,7981,3248,0,3730,8832,3675,10,1652,5585,7981,0,1867,6436,8832,10,7981,5584,1625,0,8832,6435,1840,10,5585,798,5584,0,6436,1013,6435,10,7982,3313,234,0,8833,3740,312,10,5586,7982,3207,0,6437,8833,3634,10,5589,1657,3313,0,6440,1872,3740,10,799,5589,7982,0,1014,6440,8833,10,3316,7983,3206,0,3743,8834,3633,10,1659,5587,7983,0,1874,6438,8834,10,7983,5586,1604,0,8834,6437,1819,10,5587,799,5586,0,6438,1014,6437,10,7984,3317,259,0,8835,3744,346,10,5588,7984,3314,0,6439,8835,3741,10,5587,1659,3317,0,6438,1874,3744,10,799,5587,7984,0,1014,6438,8835,10,3312,7985,3315,0,3739,8836,3742,10,1657,5589,7985,0,1872,6440,8836,10,7985,5588,1658,0,8836,6439,1873,10,5589,799,5588,0,6440,1014,6439,10,7986,3312,258,0,8837,3739,345,10,5590,7986,3320,0,6441,8837,3747,10,5593,1657,3312,0,6444,1872,3739,10,800,5593,7986,0,1015,6444,8837,10,3318,7987,3321,0,3745,8838,3748,10,1660,5591,7987,0,1875,6442,8838,10,7987,5590,1661,0,8838,6441,1876,10,5591,800,5590,0,6442,1015,6441,10,7988,3319,252,0,8839,3746,335,10,5592,7988,3289,0,6443,8839,3716,10,5591,1660,3319,0,6442,1875,3746,10,800,5591,7988,0,1015,6442,8839,10,3313,7989,3288,0,3740,8840,3715,10,1657,5593,7989,0,1872,6444,8840,10,7989,5592,1645,0,8840,6443,1860,10,5593,800,5592,0,6444,1015,6443,10,7990,3323,167,0,8841,3750,330,10,5594,7990,3283,0,6445,8841,3710,10,5597,1662,3323,0,6448,1877,3750,10,801,5597,7990,0,1016,6448,8841,10,3319,7991,3282,0,3746,8842,3709,10,1660,5595,7991,0,1875,6446,8842,10,7991,5594,1642,0,8842,6445,1857,10,5595,801,5594,0,6446,1016,6445,10,7992,3318,260,0,8843,3745,347,10,5596,7992,3324,0,6447,8843,3751,10,5595,1660,3318,0,6446,1875,3745,10,801,5595,7992,0,1016,6446,8843,10,3322,7993,3325,0,3749,8844,3752,10,1662,5597,7993,0,1877,6448,8844,10,7993,5596,1663,0,8844,6447,1878,10,5597,801,5596,0,6448,1016,6447,10,7994,3327,166,0,8845,3754,233,10,5598,7994,2985,0,6449,8845,3412,10,5601,1664,3327,0,6452,1879,3754,10,802,5601,7994,0,1017,6452,8845,10,3323,7995,2984,0,5363,8846,3411,10,1662,5599,7995,0,2684,6450,8846,10,7995,5598,1493,0,8846,6449,1708,10,5599,802,5598,0,6450,1017,6449,10,7996,3322,261,0,8847,5364,350,10,5600,7996,3328,0,6451,8847,3755,10,5599,1662,3322,0,6450,2684,5364,10,802,5599,7996,0,1017,6450,8847,10,3326,7997,3329,0,3753,8848,3756,10,1664,5601,7997,0,1879,6452,8848,10,7997,5600,1665,0,8848,6451,1880,10,5601,802,5600,0,6452,1017,6451,10,7998,3331,166,0,8849,3758,233,10,5602,7998,3327,0,6453,8849,3754,10,5605,1666,3331,0,6456,1881,3758,10,803,5605,7998,0,1018,6456,8849,10,3334,7999,3326,0,3761,8850,3753,10,1668,5603,7999,0,1883,6454,8850,10,7999,5602,1664,0,8850,6453,1879,10,5603,803,5602,0,6454,1018,6453,10,8000,3335,264,0,8851,3762,352,10,5604,8000,3332,0,6455,8851,3759,10,5603,1668,3335,0,6454,1883,3762,10,803,5603,8000,0,1018,6454,8851,10,3330,8001,3333,0,3757,8852,3760,10,1666,5605,8001,0,1881,6456,8852,10,8001,5604,1667,0,8852,6455,1882,10,5605,803,5604,0,6456,1018,6455,10,8002,3337,263,0,8853,3764,351,10,5606,8002,3333,0,6457,8853,3760,10,5609,1669,3337,0,6460,1884,3764,10,804,5609,8002,0,1019,6460,8853,10,3340,8003,3332,0,3767,8854,3759,10,1671,5607,8003,0,1886,6458,8854,10,8003,5606,1667,0,8854,6457,1882,10,5607,804,5606,0,6458,1019,6457,10,8004,3341,266,0,8855,3768,354,10,5608,8004,3338,0,6459,8855,3765,10,5607,1671,3341,0,6458,1886,3768,10,804,5607,8004,0,1019,6458,8855,10,3336,8005,3339,0,3763,8856,3766,10,1669,5609,8005,0,1884,6460,8856,10,8005,5608,1670,0,8856,6459,1885,10,5609,804,5608,0,6460,1019,6459,10,8006,3343,265,0,8857,3770,353,10,5610,8006,3339,0,6461,8857,3766,10,5613,1672,3343,0,6464,1887,3770,10,805,5613,8006,0,1020,6464,8857,10,3346,8007,3338,0,3773,8858,3765,10,1674,5611,8007,0,1889,6462,8858,10,8007,5610,1670,0,8858,6461,1885,10,5611,805,5610,0,6462,1020,6461,10,8008,3347,267,0,8859,3774,355,10,5612,8008,3344,0,6463,8859,3771,10,5611,1674,3347,0,6462,1889,3774,10,805,5611,8008,0,1020,6462,8859,10,3342,8009,3345,0,3769,8860,3772,10,1672,5613,8009,0,1887,6464,8860,10,8009,5612,1673,0,8860,6463,1888,10,5613,805,5612,0,6464,1020,6463,10,8010,2790,102,0,8861,3217,166,10,5614,8010,3345,0,6465,8861,3772,10,5617,1396,2790,0,6468,1611,3217,10,806,5617,8010,0,1021,6468,8861,10,3350,8011,3344,0,3777,8862,3771,10,1676,5615,8011,0,1891,6466,8862,10,8011,5614,1673,0,8862,6465,1888,10,5615,806,5614,0,6466,1021,6465,10,8012,3351,268,0,8863,3778,356,10,5616,8012,3348,0,6467,8863,3775,10,5615,1676,3351,0,6466,1891,3778,10,806,5615,8012,0,1021,6466,8863,10,2791,8013,3349,0,3218,8864,3776,10,1396,5617,8013,0,1611,6468,8864,10,8013,5616,1675,0,8864,6467,1890,10,5617,806,5616,0,6468,1021,6467,10,8014,2786,101,0,8865,3213,165,10,5618,8014,3349,0,6469,8865,3776,10,5621,1394,2786,0,6472,1609,3213,10,807,5621,8014,0,1022,6472,8865,10,3352,8015,3348,0,3779,8866,3775,10,1677,5619,8015,0,1892,6470,8866,10,8015,5618,1675,0,8866,6469,1890,10,5619,807,5618,0,6470,1022,6469,10,8016,3353,256,0,8867,3780,343,10,5620,8016,3307,0,6471,8867,3734,10,5619,1677,3353,0,6470,1892,3780,10,807,5619,8016,0,1022,6470,8867,10,2787,8017,3306,0,3214,8868,3733,10,1394,5621,8017,0,1609,6472,8868,10,8017,5620,1654,0,8868,6471,1869,10,5621,807,5620,0,6472,1022,6471,10,8018,3357,270,0,8869,3784,358,10,5622,8018,3355,0,6473,8869,3782,10,5625,1679,3357,0,6476,1894,3784,10,808,5625,8018,0,1023,6476,8869,10,3358,8019,3354,0,3785,8870,3781,10,1680,5623,8019,0,1895,6474,8870,10,8019,5622,1678,0,8870,6473,1893,10,5623,808,5622,0,6474,1023,6473,10,8020,3359,233,0,8871,3786,311,10,5624,8020,3203,0,6475,8871,3630,10,5623,1680,3359,0,6474,1895,3786,10,808,5623,8020,0,1023,6474,8871,10,3356,8021,3202,0,3783,8872,3629,10,1679,5625,8021,0,1894,6476,8872,10,8021,5624,1602,0,8872,6475,1817,10,5625,808,5624,0,6476,1023,6475,10,8022,3300,163,0,8873,3727,230,10,5626,8022,3213,0,6477,8873,3640,10,5629,1651,3300,0,6480,1866,3727,10,809,5629,8022,0,1024,6480,8873,10,3359,8023,3212,0,3786,8874,3639,10,1680,5627,8023,0,1895,6478,8874,10,8023,5626,1607,0,8874,6477,1822,10,5627,809,5626,0,6478,1024,6477,10,8024,3358,269,0,8875,3785,357,10,5628,8024,3360,0,6479,8875,3787,10,5627,1680,3358,0,6478,1895,3785,10,809,5627,8024,0,1024,6478,8875,10,3301,8025,3361,0,3728,8876,3788,10,1651,5629,8025,0,1866,6480,8876,10,8025,5628,1681,0,8876,6479,1896,10,5629,809,5628,0,6480,1024,6479,10,8026,3864,384,0,8877,5442,338,10,5630,8026,3366,0,6481,8877,3793,10,5633,1933,3864,0,6484,2723,5442,10,810,5633,8026,0,1025,6484,8877,10,3363,8027,3367,0,3790,8878,3794,10,1682,5631,8027,0,1897,6482,8878,10,8027,5630,1684,0,8878,6481,1899,10,5631,810,5630,0,6482,1025,6481,10,8028,3362,271,0,8879,3789,359,10,5632,8028,3364,0,6483,8879,3791,10,5631,1682,3362,0,6482,1897,3789,10,810,5631,8028,0,1025,6482,8879,10,3865,8029,3365,0,5441,8880,3792,10,1933,5633,8029,0,2723,6484,8880,10,8029,5632,1683,0,8880,6483,1898,10,5633,810,5632,0,6484,1025,6483,10,8030,3369,272,0,8881,3796,360,10,5634,8030,3370,0,6485,8881,3797,10,5637,1685,3369,0,6488,1900,3796,10,811,5637,8030,0,1026,6488,8881,10,3871,8031,3371,0,5447,8882,3798,10,1936,5635,8031,0,2726,6486,8882,10,8031,5634,1686,0,8882,6485,1901,10,5635,811,5634,0,6486,1026,6485,10,8032,3870,399,0,8883,5448,340,10,5636,8032,3365,0,6487,8883,5367,10,5635,1936,3870,0,6486,2726,5448,10,811,5635,8032,0,1026,6486,8883,10,3368,8033,3364,0,3795,8884,5368,10,1685,5637,8033,0,1900,6488,8884,10,8033,5636,1683,0,8884,6487,2686,10,5637,811,5636,0,6488,1026,6487,10,8034,3372,273,0,8885,3799,362,10,5638,8034,3374,0,6489,8885,3801,10,5641,1687,3372,0,6492,1902,3799,10,812,5641,8034,0,1027,6492,8885,10,3243,8035,3375,0,3670,8886,3802,10,1622,5639,8035,0,1837,6490,8886,10,8035,5638,1688,0,8886,6489,1903,10,5639,812,5638,0,6490,1027,6489,10,8036,3242,132,0,8887,3669,199,10,5640,8036,3219,0,6491,8887,3646,10,5639,1622,3242,0,6490,1837,3669,10,812,5639,8036,0,1027,6490,8887,10,3373,8037,3218,0,3800,8888,3645,10,1687,5641,8037,0,1902,6492,8888,10,8037,5640,1610,0,8888,6491,1825,10,5641,812,5640,0,6492,1027,6491,10,8038,3374,273,0,8889,3801,362,10,5642,8038,3376,0,6493,8889,3803,10,5645,1688,3374,0,6496,1903,3801,10,813,5645,8038,0,1028,6496,8889,10,3195,8039,3377,0,3622,8890,3804,10,1598,5643,8039,0,1813,6494,8890,10,8039,5642,1689,0,8890,6493,1904,10,5643,813,5642,0,6494,1028,6493,10,8040,3194,106,0,8891,3621,170,10,5644,8040,3257,0,6495,8891,3684,10,5643,1598,3194,0,6494,1813,3621,10,813,5643,8040,0,1028,6494,8891,10,3375,8041,3256,0,3802,8892,3683,10,1688,5645,8041,0,1903,6496,8892,10,8041,5644,1629,0,8892,6495,1844,10,5645,813,5644,0,6496,1028,6495,10,8042,3370,272,0,8893,3797,360,10,5646,8042,3379,0,6497,8893,3806,10,5649,1686,3370,0,6500,1901,3797,10,814,5649,8042,0,1029,6500,8893,10,3380,8043,3378,0,3807,8894,3805,10,1691,5647,8043,0,1906,6498,8894,10,8043,5646,1690,0,8894,6497,1905,10,5647,814,5646,0,6498,1029,6497,10,8044,3381,247,0,8895,3808,327,10,5648,8044,3263,0,6499,8895,3690,10,5647,1691,3381,0,6498,1906,3808,10,814,5647,8044,0,1029,6498,8895,10,3371,8045,3262,0,3798,8896,3689,10,1686,5649,8045,0,1901,6500,8896,10,8045,5648,1632,0,8896,6499,1847,10,5649,814,5648,0,6500,1029,6499,10,8046,3383,249,0,8897,3810,332,10,5650,8046,3275,0,6501,8897,3702,10,5653,1692,3383,0,6504,1907,3810,10,815,5653,8046,0,1030,6504,8897,10,3381,8047,3274,0,3808,8898,3701,10,1691,5651,8047,0,1906,6502,8898,10,8047,5650,1638,0,8898,6501,1853,10,5651,815,5650,0,6502,1030,6501,10,8048,3380,274,0,8899,3807,363,10,5652,8048,3384,0,6503,8899,3811,10,5651,1691,3380,0,6502,1906,3807,10,815,5651,8048,0,1030,6502,8899,10,3382,8049,3385,0,3809,8900,3812,10,1692,5653,8049,0,1907,6504,8900,10,8049,5652,1693,0,8900,6503,1908,10,5653,815,5652,0,6504,1030,6503,10,8050,3389,251,0,8901,3816,334,10,5654,8050,3281,0,6505,8901,3708,10,5657,1695,3389,0,6508,1910,3816,10,816,5657,8050,0,1031,6508,8901,10,3383,8051,3280,0,3810,8902,3707,10,1692,5655,8051,0,1907,6506,8902,10,8051,5654,1641,0,8902,6505,1856,10,5655,816,5654,0,6506,1031,6505,10,8052,3382,275,0,8903,3809,364,10,5656,8052,3387,0,6507,8903,3814,10,5655,1692,3382,0,6506,1907,3809,10,816,5655,8052,0,1031,6506,8903,10,3388,8053,3386,0,3815,8904,3813,10,1695,5657,8053,0,1910,6508,8904,10,8053,5656,1694,0,8904,6507,1909,10,5657,816,5656,0,6508,1031,6507,10,8054,3356,230,0,8905,3783,308,10,5658,8054,3291,0,6509,8905,3718,10,5661,1679,3356,0,6512,1894,3783,10,817,5661,8054,0,1032,6512,8905,10,3389,8055,3290,0,3816,8906,3717,10,1695,5659,8055,0,1910,6510,8906,10,8055,5658,1646,0,8906,6509,1861,10,5659,817,5658,0,6510,1032,6509,10,8056,3388,276,0,8907,3815,365,10,5660,8056,3390,0,6511,8907,3817,10,5659,1695,3388,0,6510,1910,3815,10,817,5659,8056,0,1032,6510,8907,10,3357,8057,3391,0,3784,8908,3818,10,1679,5661,8057,0,1894,6512,8908,10,8057,5660,1696,0,8908,6511,1911,10,5661,817,5660,0,6512,1032,6511,10,8058,3395,277,0,8909,3822,366,10,5662,8058,3393,0,6513,8909,3820,10,5665,1698,3395,0,6516,1913,3822,10,818,5665,8058,0,1033,6516,8909,10,3396,8059,3392,0,3823,8910,3819,10,1699,5663,8059,0,1914,6514,8910,10,8059,5662,1697,0,8910,6513,1912,10,5663,818,5662,0,6514,1033,6513,10,8060,3397,183,0,8911,3824,252,10,5664,8060,3027,0,6515,8911,3454,10,5663,1699,3397,0,6514,1914,3824,10,818,5663,8060,0,1033,6514,8911,10,3394,8061,3026,0,3821,8912,3453,10,1698,5665,8061,0,1913,6516,8912,10,8061,5664,1514,0,8912,6515,1729,10,5665,818,5664,0,6516,1033,6515,10,8062,3399,279,0,8913,3826,368,10,5666,8062,3402,0,6517,8913,3829,10,5669,1700,3399,0,6520,1915,3826,10,819,5669,8062,0,1034,6520,8913,10,3400,8063,3403,0,3827,8914,3830,10,1701,5667,8063,0,1916,6518,8914,10,8063,5666,1702,0,8914,6517,1917,10,5667,819,5666,0,6518,1034,6517,10,8064,3401,183,0,8915,3828,252,10,5668,8064,3397,0,6519,8915,3824,10,5667,1701,3401,0,6518,1916,3828,10,819,5667,8064,0,1034,6518,8915,10,3398,8065,3396,0,3825,8916,3823,10,1700,5669,8065,0,1915,6520,8916,10,8065,5668,1699,0,8916,6519,1914,10,5669,819,5668,0,6520,1034,6519,10,8066,3405,191,0,8917,3832,260,10,5670,8066,3057,0,6521,8917,3484,10,5673,1703,3405,0,6524,1918,3832,10,820,5673,8066,0,1035,6524,8917,10,3406,8067,3056,0,3833,8918,3483,10,1704,5671,8067,0,1919,6522,8918,10,8067,5670,1529,0,8918,6521,1744,10,5671,820,5670,0,6522,1035,6521,10,8068,3407,279,0,8919,3834,368,10,5672,8068,3399,0,6523,8919,3826,10,5671,1704,3407,0,6522,1919,3834,10,820,5671,8068,0,1035,6522,8919,10,3404,8069,3398,0,3831,8920,3825,10,1703,5673,8069,0,1918,6524,8920,10,8069,5672,1700,0,8920,6523,1915,10,5673,820,5672,0,6524,1035,6523,10,8070,3050,191,0,8921,3477,260,10,5674,8070,3405,0,6525,8921,3832,10,5677,1526,3050,0,6528,1741,3477,10,821,5677,8070,0,1036,6528,8921,10,3408,8071,3404,0,3835,8922,3831,10,1705,5675,8071,0,1920,6526,8922,10,8071,5674,1703,0,8922,6525,1918,10,5675,821,5674,0,6526,1036,6525,10,8072,3409,137,0,8923,3836,204,10,5676,8072,2891,0,6527,8923,3318,10,5675,1705,3409,0,6526,1920,3836,10,821,5675,8072,0,1036,6526,8923,10,3051,8073,2890,0,3478,8924,3317,10,1526,5677,8073,0,1741,6528,8924,10,8073,5676,1446,0,8924,6527,1661,10,5677,821,5676,0,6528,1036,6527,10,8074,3410,280,0,8925,3837,369,10,5678,8074,3414,0,6529,8925,3841,10,5681,1706,3410,0,6532,1921,3837,10,822,5681,8074,0,1037,6532,8925,10,3412,8075,3415,0,3839,8926,3842,10,1707,5679,8075,0,1922,6530,8926,10,8075,5678,1708,0,8926,6529,1923,10,5679,822,5678,0,6530,1037,6529,10,8076,3413,146,0,8927,3840,213,10,5680,8076,2913,0,6531,8927,3340,10,5679,1707,3413,0,6530,1922,3840,10,822,5679,8076,0,1037,6530,8927,10,3411,8077,2912,0,3838,8928,3339,10,1706,5681,8077,0,1921,6532,8928,10,8077,5680,1457,0,8928,6531,1672,10,5681,822,5680,0,6532,1037,6531,10,8078,3417,225,0,8929,3844,303,10,5682,8078,3422,0,6533,8929,3849,10,5685,1709,3417,0,6536,1924,3844,10,823,5685,8078,0,1038,6536,8929,10,3420,8079,3423,0,3847,8930,3850,10,1711,5683,8079,0,1926,6534,8930,10,8079,5682,1712,0,8930,6533,1927,10,5683,823,5682,0,6534,1038,6533,10,8080,3421,282,0,8931,3848,371,10,5684,8080,3418,0,6535,8931,3845,10,5683,1711,3421,0,6534,1926,3848,10,823,5683,8080,0,1038,6534,8931,10,3416,8081,3419,0,3843,8932,3846,10,1709,5685,8081,0,1924,6536,8932,10,8081,5684,1710,0,8932,6535,1925,10,5685,823,5684,0,6536,1038,6535,10,8082,3429,122,0,8933,3856,186,10,5686,8082,3432,0,6537,8933,3859,10,5689,1715,3429,0,6540,1930,3856,10,824,5689,8082,0,1039,6540,8933,10,3427,8083,3433,0,3854,8934,3860,10,1714,5687,8083,0,1929,6538,8934,10,8083,5686,1717,0,8934,6537,1932,10,5687,824,5686,0,6538,1039,6537,10,8084,3426,284,0,8935,3853,373,10,5688,8084,3430,0,6539,8935,3857,10,5687,1714,3426,0,6538,1929,3853,10,824,5687,8084,0,1039,6538,8935,10,3428,8085,3431,0,3855,8936,3858,10,1715,5689,8085,0,1930,6540,8936,10,8085,5688,1716,0,8936,6539,1931,10,5689,824,5688,0,6540,1039,6539,10,8086,3435,171,0,8937,3862,240,10,5690,8086,3440,0,6541,8937,3867,10,5693,1718,3435,0,6544,1933,3862,10,825,5693,8086,0,1040,6544,8937,10,3438,8087,3441,0,3865,8938,3868,10,1720,5691,8087,0,1935,6542,8938,10,8087,5690,1721,0,8938,6541,1936,10,5691,825,5690,0,6542,1040,6541,10,8088,3439,286,0,8939,3866,375,10,5692,8088,3436,0,6543,8939,3863,10,5691,1720,3439,0,6542,1935,3866,10,825,5691,8088,0,1040,6542,8939,10,3434,8089,3437,0,3861,8940,3864,10,1718,5693,8089,0,1933,6544,8940,10,8089,5692,1719,0,8940,6543,1934,10,5693,825,5692,0,6544,1040,6543,10,8090,3443,287,0,8941,3870,376,10,5694,8090,3446,0,6545,8941,3873,10,5697,1722,3443,0,6548,1937,3870,10,826,5697,8090,0,1041,6548,8941,10,3019,8091,3447,0,3446,8942,3874,10,1510,5695,8091,0,1725,6546,8942,10,8091,5694,1724,0,8942,6545,1939,10,5695,826,5694,0,6546,1041,6545,10,8092,3018,174,0,8943,3445,243,10,5696,8092,3444,0,6547,8943,3871,10,5695,1510,3018,0,6546,1725,3445,10,826,5695,8092,0,1041,6546,8943,10,3442,8093,3445,0,3869,8944,3872,10,1722,5697,8093,0,1937,6548,8944,10,8093,5696,1723,0,8944,6547,1938,10,5697,826,5696,0,6548,1041,6547,10,8094,3446,287,0,8945,3873,376,10,5698,8094,3449,0,6549,8945,3876,10,5701,1724,3446,0,6552,1939,3873,10,827,5701,8094,0,1042,6552,8945,10,3450,8095,3448,0,3877,8946,3875,10,1726,5699,8095,0,1941,6550,8946,10,8095,5698,1725,0,8946,6549,1940,10,5699,827,5698,0,6550,1042,6549,10,8096,3451,178,0,8947,3878,247,10,5700,8096,3017,0,6551,8947,3444,10,5699,1726,3451,0,6550,1941,3878,10,827,5699,8096,0,1042,6550,8947,10,3447,8097,3016,0,3874,8948,3443,10,1724,5701,8097,0,1939,6552,8948,10,8097,5700,1509,0,8948,6551,1724,10,5701,827,5700,0,6552,1042,6551,10,8098,3453,289,0,8949,3880,378,10,5702,8098,3456,0,6553,8949,3883,10,5705,1727,3453,0,6556,1942,3880,10,828,5705,8098,0,1043,6556,8949,10,3454,8099,3457,0,3881,8950,3884,10,1728,5703,8099,0,1943,6554,8950,10,8099,5702,1729,0,8950,6553,1944,10,5703,828,5702,0,6554,1043,6553,10,8100,3455,178,0,8951,3882,247,10,5704,8100,3451,0,6555,8951,3878,10,5703,1728,3455,0,6554,1943,3882,10,828,5703,8100,0,1043,6554,8951,10,3452,8101,3450,0,3879,8952,3877,10,1727,5705,8101,0,1942,6556,8952,10,8101,5704,1726,0,8952,6555,1941,10,5705,828,5704,0,6556,1043,6555,10,8102,3459,181,0,8953,3886,250,10,5706,8102,3033,0,6557,8953,3460,10,5709,1730,3459,0,6560,1945,3886,10,829,5709,8102,0,1044,6560,8953,10,3460,8103,3032,0,3887,8954,3459,10,1731,5707,8103,0,1946,6558,8954,10,8103,5706,1517,0,8954,6557,1732,10,5707,829,5706,0,6558,1044,6557,10,8104,3461,289,0,8955,3888,378,10,5708,8104,3453,0,6559,8955,3880,10,5707,1731,3461,0,6558,1946,3888,10,829,5707,8104,0,1044,6558,8955,10,3458,8105,3452,0,3885,8956,3879,10,1730,5709,8105,0,1945,6560,8956,10,8105,5708,1727,0,8956,6559,1942,10,5709,829,5708,0,6560,1044,6559,10,8106,3020,181,0,8957,3447,250,10,5710,8106,3459,0,6561,8957,3886,10,5713,1511,3020,0,6564,1726,3447,10,830,5713,8106,0,1045,6564,8957,10,3462,8107,3458,0,3889,8958,3885,10,1732,5711,8107,0,1947,6562,8958,10,8107,5710,1730,0,8958,6561,1945,10,5711,830,5710,0,6562,1045,6561,10,8108,3463,277,0,8959,3890,366,10,5712,8108,3395,0,6563,8959,3822,10,5711,1732,3463,0,6562,1947,3890,10,830,5711,8108,0,1045,6562,8959,10,3021,8109,3394,0,3448,8960,3821,10,1511,5713,8109,0,1726,6564,8960,10,8109,5712,1698,0,8960,6563,1913,10,5713,830,5712,0,6564,1045,6563,10,8110,3467,291,0,8961,3894,380,10,5714,8110,3470,0,6565,8961,3897,10,5717,1734,3467,0,6568,1949,3894,10,831,5717,8110,0,1046,6568,8961,10,3468,8111,3471,0,3895,8962,3898,10,1735,5715,8111,0,1950,6566,8962,10,8111,5714,1736,0,8962,6565,1951,10,5715,831,5714,0,6566,1046,6565,10,8112,3469,283,0,8963,3896,372,10,5716,8112,3465,0,6567,8963,3892,10,5715,1735,3469,0,6566,1950,3896,10,831,5715,8112,0,1046,6566,8963,10,3466,8113,3464,0,3893,8964,3891,10,1734,5717,8113,0,1949,6568,8964,10,8113,5716,1733,0,8964,6567,1948,10,5717,831,5716,0,6568,1046,6567,10,8114,3473,223,0,8965,3900,301,10,5718,8114,3476,0,6569,8965,3903,10,5721,1737,3473,0,6572,1952,3900,10,832,5721,8114,0,1047,6572,8965,10,3474,8115,3477,0,3901,8966,3904,10,1738,5719,8115,0,1953,6570,8966,10,8115,5718,1739,0,8966,6569,1954,10,5719,832,5718,0,6570,1047,6569,10,8116,3475,193,0,8967,3902,262,10,5720,8116,3059,0,6571,8967,3486,10,5719,1738,3475,0,6570,1953,3902,10,832,5719,8116,0,1047,6570,8967,10,3472,8117,3058,0,3899,8968,3485,10,1737,5721,8117,0,1952,6572,8968,10,8117,5720,1530,0,8968,6571,1745,10,5721,832,5720,0,6572,1047,6571,10,8118,3074,198,0,8969,3501,267,10,5722,8118,3480,0,6573,8969,3907,10,5725,1538,3074,0,6576,1753,3501,10,833,5725,8118,0,1048,6576,8969,10,3478,8119,3481,0,3905,8970,3908,10,1740,5723,8119,0,1955,6574,8970,10,8119,5722,1741,0,8970,6573,1956,10,5723,833,5722,0,6574,1048,6573,10,8120,3479,107,0,8971,3906,171,10,5724,8120,2807,0,6575,8971,3234,10,5723,1740,3479,0,6574,1955,3906,10,833,5723,8120,0,1048,6574,8971,10,3075,8121,2806,0,3502,8972,3233,10,1538,5725,8121,0,1753,6576,8972,10,8121,5724,1404,0,8972,6575,1619,10,5725,833,5724,0,6576,1048,6575,10,8122,3066,109,0,8973,3493,173,10,5726,8122,2811,0,6577,8973,3238,10,5729,1534,3066,0,6580,1749,3493,10,834,5729,8122,0,1049,6580,8973,10,2825,8123,2810,0,3252,8974,3237,10,1413,5727,8123,0,1628,6578,8974,10,8123,5726,1406,0,8974,6577,1621,10,5727,834,5726,0,6578,1049,6577,10,8124,2824,114,0,8975,3251,178,10,5728,8124,2821,0,6579,8975,3248,10,5727,1413,2824,0,6578,1628,3251,10,834,5727,8124,0,1049,6578,8975,10,3067,8125,2820,0,3494,8976,3247,10,1534,5729,8125,0,1749,6580,8976,10,8125,5728,1411,0,8976,6579,1626,10,5729,834,5728,0,6580,1049,6579,10,8126,2826,116,0,8977,3253,180,10,5730,8126,3091,0,6581,8977,3518,10,5733,1414,2826,0,6584,1629,3253,10,835,5733,8126,0,1050,6584,8977,10,3172,8127,3090,0,3599,8978,3517,10,1587,5731,8127,0,1802,6582,8978,10,8127,5730,1546,0,8978,6581,1761,10,5731,835,5730,0,6582,1050,6581,10,8128,3173,113,0,8979,3600,177,10,5732,8128,2819,0,6583,8979,3246,10,5731,1587,3173,0,6582,1802,3600,10,835,5731,8128,0,1050,6582,8979,10,2827,8129,2818,0,3254,8980,3245,10,1414,5733,8129,0,1629,6584,8980,10,8129,5732,1410,0,8980,6583,1625,10,5733,835,5732,0,6584,1050,6583,10,8130,3483,124,0,8981,3910,188,10,5734,8130,2855,0,6585,8981,3282,10,5737,1742,3483,0,6588,1957,3910,10,836,5737,8130,0,1051,6588,8981,10,3433,8131,2854,0,3860,8982,3281,10,1717,5735,8131,0,1932,6586,8982,10,8131,5734,1428,0,8982,6585,1643,10,5735,836,5734,0,6586,1051,6585,10,8132,3432,122,0,8983,3859,186,10,5736,8132,2849,0,6587,8983,3276,10,5735,1717,3432,0,6586,1932,3859,10,836,5735,8132,0,1051,6586,8983,10,3482,8133,2848,0,3909,8984,3275,10,1742,5737,8133,0,1957,6588,8984,10,8133,5736,1425,0,8984,6587,1640,10,5737,836,5736,0,6588,1051,6587,10,8134,3485,125,0,8985,3912,189,10,5738,8134,2859,0,6589,8985,3286,10,5741,1743,3485,0,6592,1958,3912,10,837,5741,8134,0,1052,6592,8985,10,3483,8135,2858,0,5369,8986,3285,10,1742,5739,8135,0,2687,6590,8986,10,8135,5738,1430,0,8986,6589,1645,10,5739,837,5738,0,6590,1052,6589,10,8136,3482,119,0,8987,5370,194,10,5740,8136,2865,0,6591,8987,3292,10,5739,1742,3482,0,6590,2687,5370,10,837,5739,8136,0,1052,6590,8987,10,3484,8137,2864,0,3911,8988,3291,10,1743,5741,8137,0,1958,6592,8988,10,8137,5740,1433,0,8988,6591,1648,10,5741,837,5740,0,6592,1052,6591,10,8138,3042,139,0,8989,3469,206,10,5742,8138,2895,0,6593,8989,3322,10,5745,1522,3042,0,6596,1737,3469,10,838,5745,8138,0,1053,6596,8989,10,2909,8139,2894,0,3336,8990,3321,10,1455,5743,8139,0,1670,6594,8990,10,8139,5742,1448,0,8990,6593,1663,10,5743,838,5742,0,6594,1053,6593,10,8140,2908,144,0,8991,3335,211,10,5744,8140,2905,0,6595,8991,3332,10,5743,1455,2908,0,6594,1670,3335,10,838,5743,8140,0,1053,6594,8991,10,3043,8141,2904,0,3470,8992,3331,10,1522,5745,8141,0,1737,6596,8992,10,8141,5744,1453,0,8992,6595,1668,10,5745,838,5744,0,6596,1053,6595,10,8142,2910,146,0,8993,3337,213,10,5746,8142,3486,0,6597,8993,3913,10,5749,1456,2910,0,6600,1671,3337,10,839,5749,8142,0,1054,6600,8993,10,3181,8143,3487,0,3608,8994,3914,10,1591,5747,8143,0,1806,6598,8994,10,8143,5746,1744,0,8994,6597,1959,10,5747,839,5746,0,6598,1054,6597,10,8144,3180,143,0,8995,3607,210,10,5748,8144,2903,0,6599,8995,3330,10,5747,1591,3180,0,6598,1806,3607,10,839,5747,8144,0,1054,6598,8995,10,2911,8145,2902,0,3338,8996,3329,10,1456,5749,8145,0,1671,6600,8996,10,8145,5748,1452,0,8996,6599,1667,10,5749,839,5748,0,6600,1054,6599,10,8146,3489,149,0,8997,3916,216,10,5750,8146,2925,0,6601,8997,3352,10,5753,1745,3489,0,6604,1960,3916,10,840,5753,8146,0,1055,6604,8997,10,3490,8147,2924,0,3917,8998,3351,10,1746,5751,8147,0,1961,6602,8998,10,8147,5750,1463,0,8998,6601,1678,10,5751,840,5750,0,6602,1055,6601,10,8148,3491,154,0,8999,3918,221,10,5752,8148,2935,0,6603,8999,3362,10,5751,1746,3491,0,6602,1961,3918,10,840,5751,8148,0,1055,6602,8999,10,3488,8149,2934,0,3915,9000,3361,10,1745,5753,8149,0,1960,6604,9000,10,8149,5752,1468,0,9000,6603,1683,10,5753,840,5752,0,6604,1055,6603,10,8150,3490,150,0,9001,3917,217,10,5754,8150,2943,0,6605,9001,3370,10,5757,1746,3490,0,6608,1961,3917,10,841,5757,8150,0,1056,6608,9001,10,3485,8151,2942,0,3912,9002,3369,10,1743,5755,8151,0,1958,6606,9002,10,8151,5754,1472,0,9002,6605,1687,10,5755,841,5754,0,6606,1056,6605,10,8152,3484,126,0,9003,3911,191,10,5756,8152,2939,0,6607,9003,3366,10,5755,1743,3484,0,6606,1958,3911,10,841,5755,8152,0,1056,6606,9003,10,3491,8153,2938,0,3918,9004,3365,10,1746,5757,8153,0,1961,6608,9004,10,8153,5756,1470,0,9004,6607,1685,10,5757,841,5756,0,6608,1056,6607,10,8154,3493,222,0,9005,3920,300,10,5758,8154,3174,0,6609,9005,3601,10,5761,1747,3493,0,6612,1962,3920,10,842,5761,8154,0,1057,6612,9005,10,3081,8155,3175,0,3508,9006,3602,10,1541,5759,8155,0,1756,6610,9006,10,8155,5758,1588,0,9006,6609,1803,10,5759,842,5758,0,6610,1057,6609,10,8156,3080,158,0,9007,3507,225,10,5760,8156,2957,0,6611,9007,3384,10,5759,1541,3080,0,6610,1756,3507,10,842,5759,8156,0,1057,6610,9007,10,3492,8157,2956,0,3919,9008,3383,10,1747,5761,8157,0,1962,6612,9008,10,8157,5760,1479,0,9008,6611,1694,10,5761,842,5760,0,6612,1057,6611,10,8158,3495,211,0,9009,3922,282,10,5762,8158,3496,0,6613,9009,3923,10,5765,1748,3495,0,6616,1963,3922,10,843,5765,8158,0,1058,6616,9009,10,3493,8159,3497,0,3920,9010,3924,10,1747,5763,8159,0,1962,6614,9010,10,8159,5762,1749,0,9010,6613,1964,10,5763,843,5762,0,6614,1058,6613,10,8160,3492,157,0,9011,3919,224,10,5764,8160,2961,0,6615,9011,3388,10,5763,1747,3492,0,6614,1962,3919,10,843,5763,8160,0,1058,6614,9011,10,3494,8161,2960,0,3921,9012,3387,10,1748,5765,8161,0,1963,6616,9012,10,8161,5764,1481,0,9012,6615,1696,10,5765,843,5764,0,6616,1058,6615,10,8162,2998,172,0,9013,3425,241,10,5766,8162,3013,0,6617,9013,3440,10,5769,1500,2998,0,6620,1715,3425,10,844,5769,8162,0,1059,6620,9013,10,3121,8163,3012,0,3548,9014,3439,10,1561,5767,8163,0,1776,6618,9014,10,8163,5766,1507,0,9014,6617,1722,10,5767,844,5766,0,6618,1059,6617,10,8164,3120,209,0,9015,3547,278,10,5768,8164,3441,0,6619,9015,3868,10,5767,1561,3120,0,6618,1776,3547,10,844,5767,8164,0,1059,6618,9015,10,2999,8165,3440,0,3426,9016,3867,10,1500,5769,8165,0,1715,6620,9016,10,8165,5768,1721,0,9016,6619,1936,10,5769,844,5768,0,6620,1059,6619,10,8166,3454,177,0,9017,3881,246,10,5770,8166,3011,0,6621,9017,3438,10,5773,1728,3454,0,6624,1943,3881,10,845,5773,8166,0,1060,6624,9017,10,3001,8167,3010,0,3428,9018,3437,10,1501,5771,8167,0,1716,6622,9018,10,8167,5770,1506,0,9018,6621,1721,10,5771,845,5770,0,6622,1060,6621,10,8168,3000,173,0,9019,3427,242,10,5772,8168,3015,0,6623,9019,3442,10,5771,1501,3000,0,6622,1716,3427,10,845,5771,8168,0,1060,6622,9019,10,3455,8169,3014,0,3882,9020,3441,10,1728,5773,8169,0,1943,6624,9020,10,8169,5772,1508,0,9020,6623,1723,10,5773,845,5772,0,6624,1060,6623,10,8170,3036,187,0,9021,3463,256,10,5774,8170,3137,0,6625,9021,3564,10,5777,1519,3036,0,6628,1734,3463,10,846,5777,8170,0,1061,6628,9021,10,3498,8171,3136,0,3925,9022,3563,10,1750,5775,8171,0,1965,6626,9022,10,8171,5774,1569,0,9022,6625,1784,10,5775,846,5774,0,6626,1061,6625,10,8172,3499,184,0,9023,3926,253,10,5776,8172,3029,0,6627,9023,3456,10,5775,1750,3499,0,6626,1965,3926,10,846,5775,8172,0,1061,6626,9023,10,3037,8173,3028,0,3464,9024,3455,10,1519,5777,8173,0,1734,6628,9024,10,8173,5776,1515,0,9024,6627,1730,10,5777,846,5776,0,6628,1061,6627,10,8174,3030,182,0,9025,3457,251,10,5778,8174,3025,0,6629,9025,3452,10,5781,1516,3030,0,6632,1731,3457,10,847,5781,8174,0,1062,6632,9025,10,3401,8175,3024,0,3828,9026,3451,10,1701,5779,8175,0,1916,6630,9026,10,8175,5778,1513,0,9026,6629,1728,10,5779,847,5778,0,6630,1062,6629,10,8176,3400,186,0,9027,3827,255,10,5780,8176,3035,0,6631,9027,3462,10,5779,1701,3400,0,6630,1916,3827,10,847,5779,8176,0,1062,6630,9027,10,3031,8177,3034,0,3458,9028,3461,10,1516,5781,8177,0,1731,6632,9028,10,8177,5780,1518,0,9028,6631,1733,10,5781,847,5780,0,6632,1062,6631,10,8178,3048,141,0,9029,3475,208,10,5782,8178,2899,0,6633,9029,3326,10,5785,1525,3048,0,6636,1740,3475,10,848,5785,8178,0,1063,6636,9029,10,3161,8179,2898,0,3588,9030,3325,10,1581,5783,8179,0,1796,6634,9030,10,8179,5782,1450,0,9030,6633,1665,10,5783,848,5782,0,6634,1063,6633,10,8180,3160,219,0,9031,3587,297,10,5784,8180,3500,0,6635,9031,3927,10,5783,1581,3160,0,6634,1796,3587,10,848,5783,8180,0,1063,6634,9031,10,3049,8181,3501,0,3476,9032,3928,10,1525,5785,8181,0,1740,6636,9032,10,8181,5784,1751,0,9032,6635,1966,10,5785,848,5784,0,6636,1063,6635,10,8182,3500,219,0,9033,3927,297,10,5786,8182,3169,0,6637,9033,3596,10,5789,1751,3500,0,6640,1966,3927,10,849,5789,8182,0,1064,6640,9033,10,3502,8183,3168,0,3929,9034,3595,10,1752,5787,8183,0,1967,6638,9034,10,8183,5786,1585,0,9034,6637,1800,10,5787,849,5786,0,6638,1064,6637,10,8184,3503,192,0,9035,3930,261,10,5788,8184,3055,0,6639,9035,3482,10,5787,1752,3503,0,6638,1967,3930,10,849,5787,8184,0,1064,6638,9035,10,3501,8185,3054,0,3928,9036,3481,10,1751,5789,8185,0,1966,6640,9036,10,8185,5788,1528,0,9036,6639,1743,10,5789,849,5788,0,6640,1064,6639,10,8186,3064,193,0,9037,3491,262,10,5790,8186,3504,0,6641,9037,3931,10,5793,1533,3064,0,6644,1748,3491,10,850,5793,8186,0,1065,6644,9037,10,3077,8187,3505,0,3504,9038,3932,10,1539,5791,8187,0,1754,6642,9038,10,8187,5790,1753,0,9038,6641,1968,10,5791,850,5790,0,6642,1065,6641,10,8188,3076,197,0,9039,3503,266,10,5792,8188,3071,0,6643,9039,3498,10,5791,1539,3076,0,6642,1754,3503,10,850,5791,8188,0,1065,6642,9039,10,3065,8189,3070,0,3492,9040,3497,10,1533,5793,8189,0,1748,6644,9040,10,8189,5792,1536,0,9040,6643,1751,10,5793,850,5792,0,6644,1065,6643,10,8190,3072,111,0,9041,3499,175,10,5794,8190,2815,0,6645,9041,3242,10,5797,1537,3072,0,6648,1752,3499,10,851,5797,8190,0,1066,6648,9041,10,3153,8191,2814,0,5359,9042,3241,10,1577,5795,8191,0,2682,6646,9042,10,8191,5794,1408,0,9042,6645,1623,10,5795,851,5794,0,6646,1066,6645,10,8192,3152,195,0,9043,5360,264,10,5796,8192,3063,0,6647,9043,3490,10,5795,1577,3152,0,6646,2682,5360,10,851,5795,8192,0,1066,6646,9043,10,3073,8193,3062,0,3500,9044,3489,10,1537,5797,8193,0,1752,6648,9044,10,8193,5796,1532,0,9044,6647,1747,10,5797,851,5796,0,6648,1066,6647,10,8194,3507,202,0,9045,3934,271,10,5798,8194,3089,0,6649,9045,3516,10,5801,1754,3507,0,6652,1969,3934,10,852,5801,8194,0,1067,6652,9045,10,2955,8195,3088,0,3382,9046,3515,10,1478,5799,8195,0,1693,6650,9046,10,8195,5798,1545,0,9046,6649,1760,10,5799,852,5798,0,6650,1067,6649,10,8196,2954,158,0,9047,3381,225,10,5800,8196,3083,0,6651,9047,3510,10,5799,1478,2954,0,6650,1693,3381,10,852,5799,8196,0,1067,6650,9047,10,3506,8197,3082,0,3933,9048,3509,10,1754,5801,8197,0,1969,6652,9048,10,8197,5800,1542,0,9048,6651,1757,10,5801,852,5800,0,6652,1067,6651,10,8198,3094,116,0,9049,3521,180,10,5802,8198,2829,0,6653,9049,3256,10,5805,1548,3094,0,6656,1763,3521,10,853,5805,8198,0,1068,6656,9049,10,3087,8199,2828,0,3514,9050,3255,10,1544,5803,8199,0,1759,6654,9050,10,8199,5802,1415,0,9050,6653,1630,10,5803,853,5802,0,6654,1068,6653,10,8200,3086,202,0,9051,3513,271,10,5804,8200,3507,0,6655,9051,3934,10,5803,1544,3086,0,6654,1759,3513,10,853,5803,8200,0,1068,6654,9051,10,3095,8201,3506,0,3522,9052,3933,10,1548,5805,8201,0,1763,6656,9052,10,8201,5804,1754,0,9052,6655,1969,10,5805,853,5804,0,6656,1068,6655,10,8202,3108,206,0,9053,3535,275,10,5806,8202,3105,0,6657,9053,3532,10,5809,1555,3108,0,6660,1770,3535,10,854,5809,8202,0,1069,6660,9053,10,3489,8203,3104,0,3916,9054,3531,10,1745,5807,8203,0,1960,6658,9054,10,8203,5806,1553,0,9054,6657,1768,10,5807,854,5806,0,6658,1069,6657,10,8204,3488,151,0,9055,3915,218,10,5808,8204,3099,0,6659,9055,3526,10,5807,1745,3488,0,6658,1960,3915,10,854,5807,8204,0,1069,6658,9055,10,3109,8205,3098,0,3536,9056,3525,10,1555,5809,8205,0,1770,6660,9056,10,8205,5808,1550,0,9056,6659,1765,10,5809,854,5808,0,6660,1069,6659,10,8206,3100,204,0,9057,3527,273,10,5810,8206,3127,0,6661,9057,3554,10,5813,1551,3100,0,6664,1766,3527,10,855,5813,8206,0,1070,6664,9057,10,3495,8207,3126,0,3922,9058,3553,10,1748,5811,8207,0,1963,6662,9058,10,8207,5810,1564,0,9058,6661,1779,10,5811,855,5810,0,6662,1070,6661,10,8208,3494,160,0,9059,3921,227,10,5812,8208,3107,0,6663,9059,3534,10,5811,1748,3494,0,6662,1963,3921,10,855,5811,8208,0,1070,6662,9059,10,3101,8209,3106,0,3528,9060,3533,10,1551,5813,8209,0,1766,6664,9060,10,8209,5812,1554,0,9060,6663,1769,10,5813,855,5812,0,6664,1070,6663,10,8210,3509,221,0,9061,3936,299,10,5814,8210,3170,0,6665,9061,3597,10,5817,1755,3509,0,6668,1970,3936,10,856,5817,8210,0,1071,6668,9061,10,3041,8211,3171,0,3468,9062,3598,10,1521,5815,8211,0,1736,6666,9062,10,8211,5814,1586,0,9062,6665,1801,10,5815,856,5814,0,6666,1071,6665,10,8212,3040,186,0,9063,3467,255,10,5816,8212,3403,0,6667,9063,3830,10,5815,1521,3040,0,6666,1736,3467,10,856,5815,8212,0,1071,6666,9063,10,3508,8213,3402,0,3935,9064,3829,10,1755,5817,8213,0,1970,6668,9064,10,8213,5816,1702,0,9064,6667,1917,10,5817,856,5816,0,6668,1071,6667,10,8214,3406,192,0,9065,3833,261,10,5818,8214,3503,0,6669,9065,3930,10,5821,1704,3406,0,6672,1919,3833,10,857,5821,8214,0,1072,6672,9065,10,3510,8215,3502,0,3937,9066,3929,10,1756,5819,8215,0,1971,6670,9066,10,8215,5818,1752,0,9066,6669,1967,10,5819,857,5818,0,6670,1072,6669,10,8216,3511,221,0,9067,3938,299,10,5820,8216,3509,0,6671,9067,3936,10,5819,1756,3511,0,6670,1971,3938,10,857,5819,8216,0,1072,6670,9067,10,3407,8217,3508,0,3834,9068,3935,10,1704,5821,8217,0,1919,6672,9068,10,8217,5820,1755,0,9068,6671,1970,10,5821,857,5820,0,6672,1072,6671,10,8218,3412,281,0,9069,3839,370,10,5822,8218,3423,0,6673,9069,3850,10,5825,1707,3412,0,6676,1922,3839,10,858,5825,8218,0,1073,6676,9069,10,3179,8219,3422,0,3606,9070,3849,10,1590,5823,8219,0,1805,6674,9070,10,8219,5822,1712,0,9070,6673,1927,10,5823,858,5822,0,6674,1073,6673,10,8220,3178,226,0,9071,3605,304,10,5824,8220,3487,0,6675,9071,3914,10,5823,1590,3178,0,6674,1805,3605,10,858,5823,8220,0,1073,6674,9071,10,3413,8221,3486,0,3840,9072,3913,10,1707,5825,8221,0,1922,6676,9072,10,8221,5824,1744,0,9072,6675,1959,10,5825,858,5824,0,6676,1073,6675,10,8222,3420,281,0,9073,3847,370,10,5826,8222,3415,0,6677,9073,3842,10,5829,1711,3420,0,6680,1926,3847,10,859,5829,8222,0,1074,6680,9073,10,3425,8223,3414,0,3852,9074,3841,10,1713,5827,8223,0,1928,6678,9074,10,8223,5826,1708,0,9074,6677,1923,10,5827,859,5826,0,6678,1074,6677,10,8224,3424,283,0,9075,3851,372,10,5828,8224,3469,0,6679,9075,3896,10,5827,1713,3424,0,6678,1928,3851,10,859,5827,8224,0,1074,6678,9075,10,3421,8225,3468,0,3848,9076,3895,10,1711,5829,8225,0,1926,6680,9076,10,8225,5828,1735,0,9076,6679,1950,10,5829,859,5828,0,6680,1074,6679,10,8226,3428,285,0,9077,3855,374,10,5830,8226,3437,0,6681,9077,3864,10,5833,1715,3428,0,6684,1930,3855,10,860,5833,8226,0,1075,6684,9077,10,3512,8227,3436,0,3939,9078,3863,10,1757,5831,8227,0,1972,6682,9078,10,8227,5830,1719,0,9078,6681,1934,10,5831,860,5830,0,6682,1075,6681,10,8228,3513,121,0,9079,3940,185,10,5832,8228,2847,0,6683,9079,3274,10,5831,1757,3513,0,6682,1972,3940,10,860,5831,8228,0,1075,6682,9079,10,3429,8229,2846,0,3856,9080,3273,10,1715,5833,8229,0,1930,6684,9080,10,8229,5832,1424,0,9080,6683,1639,10,5833,860,5832,0,6684,1075,6683,10,8230,3434,285,0,9081,3861,374,10,5834,8230,3431,0,6685,9081,3858,10,5837,1718,3434,0,6688,1933,3861,10,861,5837,8230,0,1076,6688,9081,10,3445,8231,3430,0,3872,9082,3857,10,1723,5835,8231,0,1938,6686,9082,10,8231,5834,1716,0,9082,6685,1931,10,5835,861,5834,0,6686,1076,6685,10,8232,3444,174,0,9083,3871,243,10,5836,8232,3005,0,6687,9083,3432,10,5835,1723,3444,0,6686,1938,3871,10,861,5835,8232,0,1076,6686,9083,10,3435,8233,3004,0,3862,9084,3431,10,1718,5837,8233,0,1933,6688,9084,10,8233,5836,1503,0,9084,6687,1718,10,5837,861,5836,0,6688,1076,6687,10,8234,3456,289,0,9085,3883,378,10,5838,8234,3516,0,6689,9085,3943,10,5841,1729,3456,0,6692,1944,3883,10,862,5841,8234,0,1077,6692,9085,10,3514,8235,3517,0,3941,9086,3944,10,1758,5839,8235,0,1973,6690,9086,10,8235,5838,1759,0,9086,6689,1974,10,5839,862,5838,0,6690,1077,6689,10,8236,3515,176,0,9087,3942,245,10,5840,8236,3009,0,6691,9087,3436,10,5839,1758,3515,0,6690,1973,3942,10,862,5839,8236,0,1077,6690,9087,10,3457,8237,3008,0,3884,9088,3435,10,1729,5841,8237,0,1944,6692,9088,10,8237,5840,1505,0,9088,6691,1720,10,5841,862,5840,0,6692,1077,6691,10,8238,3460,184,0,9089,3887,253,10,5842,8238,3499,0,6693,9089,3926,10,5845,1731,3460,0,6696,1946,3887,10,863,5845,8238,0,1078,6696,9089,10,3518,8239,3498,0,3945,9090,3925,10,1760,5843,8239,0,1975,6694,9090,10,8239,5842,1750,0,9090,6693,1965,10,5843,863,5842,0,6694,1078,6693,10,8240,3519,292,0,9091,3946,381,10,5844,8240,3517,0,6695,9091,3944,10,5843,1760,3519,0,6694,1975,3946,10,863,5843,8240,0,1078,6694,9091,10,3461,8241,3516,0,3888,9092,3943,10,1731,5845,8241,0,1946,6696,9092,10,8241,5844,1759,0,9092,6695,1974,10,5845,863,5844,0,6696,1078,6695,10,8242,3418,282,0,9093,3845,371,10,5846,8242,3471,0,6697,9093,3898,10,5849,1710,3418,0,6700,1925,3845,10,864,5849,8242,0,1079,6700,9093,10,3477,8243,3470,0,3904,9094,3897,10,1739,5847,8243,0,1954,6698,9094,10,8243,5846,1736,0,9094,6697,1951,10,5847,864,5846,0,6698,1079,6697,10,8244,3476,223,0,9095,3903,301,10,5848,8244,3177,0,6699,9095,3604,10,5847,1739,3476,0,6698,1954,3903,10,864,5847,8244,0,1079,6698,9095,10,3419,8245,3176,0,3846,9096,3603,10,1710,5849,8245,0,1925,6700,9096,10,8245,5848,1589,0,9096,6699,1804,10,5849,864,5848,0,6700,1079,6699,10,8246,3474,291,0,9097,3901,380,10,5850,8246,3467,0,6701,9097,3894,10,5853,1738,3474,0,6704,1953,3901,10,865,5853,8246,0,1080,6704,9097,10,3481,8247,3466,0,3908,9098,3893,10,1741,5851,8247,0,1956,6702,9098,10,8247,5850,1734,0,9098,6701,1949,10,5851,865,5850,0,6702,1080,6701,10,8248,3480,198,0,9099,3907,267,10,5852,8248,3505,0,6703,9099,3932,10,5851,1741,3480,0,6702,1956,3907,10,865,5851,8248,0,1080,6702,9099,10,3475,8249,3504,0,3902,9100,3931,10,1738,5853,8249,0,1953,6704,9100,10,8249,5852,1753,0,9100,6703,1968,10,5853,865,5852,0,6704,1080,6703,10,8250,3521,293,0,9101,3948,382,10,5854,8250,3522,0,6705,9101,3949,10,5857,1761,3521,0,6708,1976,3948,10,866,5857,8250,0,1081,6708,9101,10,3231,8251,3523,0,3658,9102,3950,10,1616,5855,8251,0,1831,6706,9102,10,8251,5854,1762,0,9102,6705,1977,10,5855,866,5854,0,6706,1081,6705,10,8252,3230,240,0,9103,3657,318,10,5856,8252,3367,0,6707,9103,3794,10,5855,1616,3230,0,6706,1831,3657,10,866,5855,8252,0,1081,6706,9103,10,3520,8253,3366,0,3947,9104,3793,10,1761,5857,8253,0,1976,6708,9104,10,8253,5856,1684,0,9104,6707,1899,10,5857,866,5856,0,6708,1081,6707,10,8254,3525,294,0,9105,3952,383,10,5858,8254,3526,0,6709,9105,3953,10,5861,1763,3525,0,6712,1978,3952,10,867,5861,8254,0,1082,6712,9105,10,3235,8255,3527,0,3662,9106,3954,10,1618,5859,8255,0,1833,6710,9106,10,8255,5858,1764,0,9106,6709,1979,10,5859,867,5858,0,6710,1082,6709,10,8256,3234,239,0,9107,3661,317,10,5860,8256,3523,0,6711,9107,3950,10,5859,1618,3234,0,6710,1833,3661,10,867,5859,8256,0,1082,6710,9107,10,3524,8257,3522,0,3951,9108,3949,10,1763,5861,8257,0,1978,6712,9108,10,8257,5860,1762,0,9108,6711,1977,10,5861,867,5860,0,6712,1082,6711,10,8258,3529,295,0,9109,3956,384,10,5862,8258,3532,0,6713,9109,3959,10,5865,1765,3529,0,6716,1980,3956,10,868,5865,8258,0,1083,6716,9109,10,3530,8259,3533,0,3957,9110,3960,10,1766,5863,8259,0,1981,6714,9110,10,8259,5862,1767,0,9110,6713,1982,10,5863,868,5862,0,6714,1083,6713,10,8260,3531,241,0,9111,3958,319,10,5864,8260,3527,0,6715,9111,3954,10,5863,1766,3531,0,6714,1981,3958,10,868,5863,8260,0,1083,6714,9111,10,3528,8261,3526,0,3955,9112,3953,10,1765,5865,8261,0,1980,6716,9112,10,8261,5864,1764,0,9112,6715,1979,10,5865,868,5864,0,6716,1083,6715,10,8262,3342,102,0,9113,3769,166,10,5866,8262,2793,0,6717,9113,3220,10,5869,1672,3342,0,6720,1887,3769,10,869,5869,8262,0,1084,6720,9113,10,3536,8263,2792,0,3963,9114,3219,10,1769,5867,8263,0,1984,6718,9114,10,8263,5866,1397,0,9114,6717,1612,10,5867,869,5866,0,6718,1084,6717,10,8264,3537,296,0,9115,3964,385,10,5868,8264,3534,0,6719,9115,3961,10,5867,1769,3537,0,6718,1984,3964,10,869,5867,8264,0,1084,6718,9115,10,3343,8265,3535,0,3770,9116,3962,10,1672,5869,8265,0,1887,6720,9116,10,8265,5868,1768,0,9116,6719,1983,10,5869,869,5868,0,6720,1084,6719,10,8266,3532,295,0,9117,3959,384,10,5870,8266,3538,0,6721,9117,3965,10,5873,1767,3532,0,6724,1982,3959,10,870,5873,8266,0,1085,6724,9117,10,3537,8267,3539,0,3964,9118,3966,10,1769,5871,8267,0,1984,6722,9118,10,8267,5870,1770,0,9118,6721,1985,10,5871,870,5870,0,6722,1085,6721,10,8268,3536,103,0,9119,3963,167,10,5872,8268,2797,0,6723,9119,3224,10,5871,1769,3536,0,6722,1984,3963,10,870,5871,8268,0,1085,6722,9119,10,3533,8269,2796,0,3960,9120,3223,10,1767,5873,8269,0,1982,6724,9120,10,8269,5872,1399,0,9120,6723,1614,10,5873,870,5872,0,6724,1085,6723,10,8270,3186,227,0,9121,3613,305,10,5874,8270,3241,0,6725,9121,3668,10,5877,1594,3186,0,6728,1809,3613,10,871,5877,8270,0,1086,6728,9121,10,3239,8271,3240,0,3666,9122,3667,10,1620,5875,8271,0,1835,6726,9122,10,8271,5874,1621,0,9122,6725,1836,10,5875,871,5874,0,6726,1086,6725,10,8272,3238,241,0,9123,3665,319,10,5876,8272,3531,0,6727,9123,3958,10,5875,1620,3238,0,6726,1835,3665,10,871,5875,8272,0,1086,6726,9123,10,3187,8273,3530,0,3614,9124,3957,10,1594,5877,8273,0,1809,6728,9124,10,8273,5876,1766,0,9124,6727,1981,10,5877,871,5876,0,6728,1086,6727,10,8274,3541,297,0,9125,3968,386,10,5878,8274,3542,0,6729,9125,3969,10,5881,1771,3541,0,6732,1986,3968,10,872,5881,8274,0,1087,6732,9125,10,3337,8275,3543,0,3764,9126,3970,10,1669,5879,8275,0,1884,6730,9126,10,8275,5878,1772,0,9126,6729,1987,10,5879,872,5878,0,6730,1087,6729,10,8276,3336,265,0,9127,3763,353,10,5880,8276,3535,0,6731,9127,3962,10,5879,1669,3336,0,6730,1884,3763,10,872,5879,8276,0,1087,6730,9127,10,3540,8277,3534,0,3967,9128,3961,10,1771,5881,8277,0,1986,6732,9128,10,8277,5880,1768,0,9128,6731,1983,10,5881,872,5880,0,6732,1087,6731,10,8278,3545,298,0,9129,3972,387,10,5882,8278,3546,0,6733,9129,3973,10,5885,1773,3545,0,6736,1988,3972,10,873,5885,8278,0,1088,6736,9129,10,3541,8279,3547,0,3968,9130,3974,10,1771,5883,8279,0,1986,6734,9130,10,8279,5882,1774,0,9130,6733,1989,10,5883,873,5882,0,6734,1088,6733,10,8280,3540,296,0,9131,3967,385,10,5884,8280,3539,0,6735,9131,3966,10,5883,1771,3540,0,6734,1986,3967,10,873,5883,8280,0,1088,6734,9131,10,3544,8281,3538,0,3971,9132,3965,10,1773,5885,8281,0,1988,6736,9132,10,8281,5884,1770,0,9132,6735,1985,10,5885,873,5884,0,6736,1088,6735,10,8282,3528,294,0,9133,3955,383,10,5886,8282,3550,0,6737,9133,3977,10,5889,1765,3528,0,6740,1980,3955,10,874,5889,8282,0,1089,6740,9133,10,3548,8283,3551,0,3975,9134,3978,10,1775,5887,8283,0,1990,6738,9134,10,8283,5886,1776,0,9134,6737,1991,10,5887,874,5886,0,6738,1089,6737,10,8284,3549,298,0,9135,3976,387,10,5888,8284,3545,0,6739,9135,3972,10,5887,1775,3549,0,6738,1990,3976,10,874,5887,8284,0,1089,6738,9135,10,3529,8285,3544,0,3956,9136,3971,10,1765,5889,8285,0,1980,6740,9136,10,8285,5888,1773,0,9136,6739,1988,10,5889,874,5888,0,6740,1089,6739,10,8286,3524,293,0,9137,3951,382,10,5890,8286,3554,0,6741,9137,3981,10,5893,1763,3524,0,6744,1978,3951,10,875,5893,8286,0,1090,6744,9137,10,3552,8287,3555,0,3979,9138,3982,10,1777,5891,8287,0,1992,6742,9138,10,8287,5890,1778,0,9138,6741,1993,10,5891,875,5890,0,6742,1090,6741,10,8288,3553,299,0,9139,3980,388,10,5892,8288,3551,0,6743,9139,3978,10,5891,1777,3553,0,6742,1992,3980,10,875,5891,8288,0,1090,6742,9139,10,3525,8289,3550,0,3952,9140,3977,10,1763,5893,8289,0,1978,6744,9140,10,8289,5892,1776,0,9140,6743,1991,10,5893,875,5892,0,6744,1090,6743,10,8290,3520,384,0,9141,3947,338,10,5894,8290,3863,0,6745,9141,5439,10,5897,1761,3520,0,6748,1976,3947,10,876,5897,8290,0,1091,6748,9141,10,3556,8291,3862,0,3983,9142,5440,10,1779,5895,8291,0,1994,6746,9142,10,8291,5894,1932,0,9142,6745,2722,10,5895,876,5894,0,6746,1091,6745,10,8292,3557,300,0,9143,3984,389,10,5896,8292,3555,0,6747,9143,3982,10,5895,1779,3557,0,6746,1994,3984,10,876,5895,8292,0,1091,6746,9143,10,3521,8293,3554,0,3948,9144,3981,10,1761,5897,8293,0,1976,6748,9144,10,8293,5896,1778,0,9144,6747,1993,10,5897,876,5896,0,6748,1091,6747,10,8294,3556,413,0,9145,3983,339,10,5898,8294,4007,0,6749,9145,5495,10,5901,1779,3556,0,6752,1994,3983,10,877,5901,8294,0,1092,6752,9145,10,2995,8295,4006,0,3422,9146,5496,10,1498,5899,8295,0,1713,6750,9146,10,8295,5898,2004,0,9146,6749,2750,10,5899,877,5898,0,6750,1092,6749,10,8296,2994,170,0,9147,3421,239,10,5900,8296,3558,0,6751,9147,3985,10,5899,1498,2994,0,6750,1713,3421,10,877,5899,8296,0,1092,6750,9147,10,3557,8297,3559,0,3984,9148,3986,10,1779,5901,8297,0,1994,6752,9148,10,8297,5900,1780,0,9148,6751,1995,10,5901,877,5900,0,6752,1092,6751,10,8298,3561,301,0,9149,3988,390,10,5902,8298,3562,0,6753,9149,3989,10,5905,1781,3561,0,6756,1996,3988,10,878,5905,8298,0,1093,6756,9149,10,3553,8299,3563,0,3980,9150,3990,10,1777,5903,8299,0,1992,6754,9150,10,8299,5902,1782,0,9150,6753,1997,10,5903,878,5902,0,6754,1093,6753,10,8300,3552,300,0,9151,3979,389,10,5904,8300,3559,0,6755,9151,3986,10,5903,1777,3552,0,6754,1992,3979,10,878,5903,8300,0,1093,6754,9151,10,3560,8301,3558,0,3987,9152,3985,10,1781,5905,8301,0,1996,6756,9152,10,8301,5904,1780,0,9152,6755,1995,10,5905,878,5904,0,6756,1093,6755,10,8302,3548,299,0,9153,3975,388,10,5906,8302,3563,0,6757,9153,3990,10,5909,1775,3548,0,6760,1990,3975,10,879,5909,8302,0,1094,6760,9153,10,3564,8303,3562,0,3991,9154,3989,10,1783,5907,8303,0,1998,6758,9154,10,8303,5906,1782,0,9154,6757,1997,10,5907,879,5906,0,6758,1094,6757,10,8304,3565,297,0,9155,3992,386,10,5908,8304,3547,0,6759,9155,3974,10,5907,1783,3565,0,6758,1998,3992,10,879,5907,8304,0,1094,6758,9155,10,3549,8305,3546,0,3976,9156,3973,10,1775,5909,8305,0,1990,6760,9156,10,8305,5908,1774,0,9156,6759,1989,10,5909,879,5908,0,6760,1094,6759,10,8306,2996,165,0,9157,3423,232,10,5910,8306,2983,0,6761,9157,3410,10,5913,1499,2996,0,6764,1714,3423,10,880,5913,8306,0,1095,6764,9157,10,3566,8307,2982,0,3993,9158,3409,10,1784,5911,8307,0,1999,6762,9158,10,8307,5910,1492,0,9158,6761,1707,10,5911,880,5910,0,6762,1095,6761,10,8308,3567,301,0,9159,3994,390,10,5912,8308,3561,0,6763,9159,3988,10,5911,1784,3567,0,6762,1999,3994,10,880,5911,8308,0,1095,6762,9159,10,2997,8309,3560,0,3424,9160,3987,10,1499,5913,8309,0,1714,6764,9160,10,8309,5912,1781,0,9160,6763,1996,10,5913,880,5912,0,6764,1095,6763,10,8310,3564,301,0,9161,3991,390,10,5914,8310,3567,0,6765,9161,3994,10,5917,1783,3564,0,6768,1998,3991,10,881,5917,8310,0,1096,6768,9161,10,3331,8311,3566,0,3758,9162,3993,10,1666,5915,8311,0,1881,6766,9162,10,8311,5914,1784,0,9162,6765,1999,10,5915,881,5914,0,6766,1096,6765,10,8312,3330,263,0,9163,3757,351,10,5916,8312,3543,0,6767,9163,3970,10,5915,1666,3330,0,6766,1881,3757,10,881,5915,8312,0,1096,6766,9163,10,3565,8313,3542,0,3992,9164,3969,10,1783,5917,8313,0,1998,6768,9164,10,8313,5916,1772,0,9164,6767,1987,10,5917,881,5916,0,6768,1096,6767,10,8314,2888,128,0,9165,3315,195,10,5918,8314,2867,0,6769,9165,3294,10,5921,1445,2888,0,6772,1660,3315,10,882,5921,8314,0,1097,6772,9165,10,3309,8315,2866,0,3736,9166,3293,10,1655,5919,8315,0,1870,6770,9166,10,8315,5918,1434,0,9166,6769,1649,10,5919,882,5918,0,6770,1097,6769,10,8316,3308,257,0,9167,3735,344,10,5920,8316,3568,0,6771,9167,3995,10,5919,1655,3308,0,6770,1870,3735,10,882,5919,8316,0,1097,6770,9167,10,2889,8317,3569,0,3316,9168,3996,10,1445,5921,8317,0,1660,6772,9168,10,8317,5920,1785,0,9168,6771,2000,10,5921,882,5920,0,6772,1097,6771,10,8318,2980,162,0,9169,3407,229,10,5922,8318,3570,0,6773,9169,3997,10,5925,1491,2980,0,6776,1706,3407,10,883,5925,8318,0,1098,6776,9169,10,3209,8319,3571,0,3636,9170,3998,10,1605,5923,8319,0,1820,6774,9170,10,8319,5922,1786,0,9170,6773,2001,10,5923,883,5922,0,6774,1098,6773,10,8320,3208,232,0,9171,3635,310,10,5924,8320,3211,0,6775,9171,3638,10,5923,1605,3208,0,6774,1820,3635,10,883,5923,8320,0,1098,6774,9171,10,2981,8321,3210,0,3408,9172,3637,10,1491,5925,8321,0,1706,6776,9172,10,8321,5924,1606,0,9172,6775,1821,10,5925,883,5924,0,6776,1098,6775,10,8322,3573,162,0,9173,4000,229,10,5926,8322,2975,0,6777,9173,3402,10,5929,1787,3573,0,6780,2002,4000,10,884,5929,8322,0,1099,6780,9173,10,2887,8323,2974,0,3314,9174,3401,10,1444,5927,8323,0,1659,6778,9174,10,8323,5926,1488,0,9174,6777,1703,10,5927,884,5926,0,6778,1099,6777,10,8324,2886,136,0,9175,3313,203,10,5928,8324,3574,0,6779,9175,4001,10,5927,1444,2886,0,6778,1659,3313,10,884,5927,8324,0,1099,6778,9175,10,3572,8325,3575,0,3999,9176,4002,10,1787,5929,8325,0,2002,6780,9176,10,8325,5928,1788,0,9176,6779,2003,10,5929,884,5928,0,6780,1099,6779,10,8326,3572,302,0,9177,3999,391,10,5930,8326,3576,0,6781,9177,4003,10,5933,1787,3572,0,6784,2002,3999,10,885,5933,8326,0,1100,6784,9177,10,3317,8327,3577,0,3744,9178,4004,10,1659,5931,8327,0,1874,6782,9178,10,8327,5930,1789,0,9178,6781,2004,10,5931,885,5930,0,6782,1100,6781,10,8328,3316,235,0,9179,3743,313,10,5932,8328,3571,0,6783,9179,3998,10,5931,1659,3316,0,6782,1874,3743,10,885,5931,8328,0,1100,6782,9179,10,3573,8329,3570,0,4000,9180,3997,10,1787,5933,8329,0,2002,6784,9180,10,8329,5932,1786,0,9180,6783,2001,10,5933,885,5932,0,6784,1100,6783,10,8330,3579,259,0,9181,4006,346,10,5934,8330,3577,0,6785,9181,4004,10,5937,1790,3579,0,6788,2005,4006,10,886,5937,8330,0,1101,6788,9181,10,3582,8331,3576,0,4009,9182,4003,10,1792,5935,8331,0,2007,6786,9182,10,8331,5934,1789,0,9182,6785,2004,10,5935,886,5934,0,6786,1101,6785,10,8332,3583,304,0,9183,4010,393,10,5936,8332,3580,0,6787,9183,4007,10,5935,1792,3583,0,6786,2007,4010,10,886,5935,8332,0,1101,6786,9183,10,3578,8333,3581,0,4005,9184,4008,10,1790,5937,8333,0,2005,6788,9184,10,8333,5936,1791,0,9184,6787,2006,10,5937,886,5936,0,6788,1101,6787,10,8334,4751,304,0,9185,5178,393,10,5938,8334,3588,0,6789,9185,4015,10,5941,2376,4751,0,6792,2591,5178,10,887,5941,8334,0,1102,6792,9185,10,3586,8335,3589,0,4013,9186,4016,10,1794,5939,8335,0,2009,6790,9186,10,8335,5938,1795,0,9186,6789,2010,10,5939,887,5938,0,6790,1102,6789,10,8336,3587,587,0,9187,4014,801,10,5940,8336,4766,0,6791,9187,5193,10,5939,1794,3587,0,6790,2009,4014,10,887,5939,8336,0,1102,6790,9187,10,4750,8337,4767,0,5177,9188,5194,10,2376,5941,8337,0,2591,6792,9188,10,8337,5940,2384,0,9188,6791,2599,10,5941,887,5940,0,6792,1102,6791,10,8338,3591,306,0,9189,4018,395,10,5942,8338,3594,0,6793,9189,4021,10,5945,1796,3591,0,6796,2011,4018,10,888,5945,8338,0,1103,6796,9189,10,4768,8339,3595,0,5195,9190,4022,10,2385,5943,8339,0,2600,6794,9190,10,8339,5942,1798,0,9190,6793,2013,10,5943,888,5942,0,6794,1103,6793,10,8340,4769,594,0,9191,5196,809,10,5944,8340,4752,0,6795,9191,5179,10,5943,2385,4769,0,6794,2600,5196,10,888,5943,8340,0,1103,6794,9191,10,3590,8341,4753,0,4017,9192,5180,10,1796,5945,8341,0,2011,6796,9192,10,8341,5944,2377,0,9192,6795,2592,10,5945,888,5944,0,6796,1103,6795,10,8342,3597,308,0,9193,4024,397,10,5946,8342,3598,0,6797,9193,4025,10,5949,1799,3597,0,6800,2014,4024,10,889,5949,8342,0,1104,6800,9193,10,4770,8343,3599,0,5197,9194,4026,10,2386,5947,8343,0,2601,6798,9194,10,8343,5946,1800,0,9194,6797,2015,10,5947,889,5946,0,6798,1104,6797,10,8344,4771,588,0,9195,5198,802,10,5948,8344,3595,0,6799,9195,4022,10,5947,2386,4771,0,6798,2601,5198,10,889,5947,8344,0,1104,6798,9195,10,3596,8345,3594,0,4023,9196,4021,10,1799,5949,8345,0,2014,6800,9196,10,8345,5948,1798,0,9196,6799,2013,10,5949,889,5948,0,6800,1104,6799,10,8346,4755,328,0,9197,5182,418,10,5950,8346,3662,0,6801,9197,4089,10,5953,2378,4755,0,6804,2593,5182,10,890,5953,8346,0,1105,6804,9197,10,3610,8347,3663,0,4037,9198,4090,10,1806,5951,8347,0,2021,6802,9198,10,8347,5950,1832,0,9198,6801,2047,10,5951,890,5950,0,6802,1105,6801,10,8348,3611,590,0,9199,4038,804,10,5952,8348,4772,0,6803,9199,5199,10,5951,1806,3611,0,6802,2021,4038,10,890,5951,8348,0,1105,6802,9199,10,4754,8349,4773,0,5181,9200,5200,10,2378,5953,8349,0,2593,6804,9200,10,8349,5952,2387,0,9200,6803,2602,10,5953,890,5952,0,6804,1105,6803,10,8350,3613,307,0,9201,4040,396,10,5954,8350,4753,0,6805,9201,5180,10,5957,1807,3613,0,6808,2022,4040,10,891,5957,8350,0,1106,6808,9201,10,4774,8351,4752,0,5201,9202,5179,10,2388,5955,8351,0,2603,6806,9202,10,8351,5954,2377,0,9202,6805,2592,10,5955,891,5954,0,6806,1106,6805,10,8352,4775,596,0,9203,5202,811,10,5956,8352,4756,0,6807,9203,5183,10,5955,2388,4775,0,6806,2603,5202,10,891,5955,8352,0,1106,6806,9203,10,3612,8353,4757,0,4039,9204,5184,10,1807,5957,8353,0,2022,6808,9204,10,8353,5956,2379,0,9204,6807,2594,10,5957,891,5956,0,6808,1106,6807,10,8354,3614,317,0,9205,4041,406,10,5958,8354,3623,0,6809,9205,4050,10,5961,1808,3614,0,6812,2023,4041,10,892,5961,8354,0,1107,6812,9205,10,3620,8355,3622,0,4047,9206,4049,10,1811,5959,8355,0,2026,6810,9206,10,8355,5958,1812,0,9206,6809,2027,10,5959,892,5958,0,6810,1107,6809,10,8356,3621,577,0,9207,4048,790,10,5960,8356,4710,0,6811,9207,5137,10,5959,1811,3621,0,6810,2026,4048,10,892,5959,8356,0,1107,6810,9207,10,3615,8357,4711,0,4042,9208,5138,10,1808,5961,8357,0,2023,6812,9208,10,8357,5960,2356,0,9208,6811,2571,10,5961,892,5960,0,6812,1107,6811,10,8358,3620,319,0,9209,4047,408,10,5962,8358,3631,0,6813,9209,4058,10,5965,1811,3620,0,6816,2026,4047,10,893,5965,8358,0,1108,6816,9209,10,3628,8359,3630,0,4055,9210,4057,10,1815,5963,8359,0,2030,6814,9210,10,8359,5962,1816,0,9210,6813,2031,10,5963,893,5962,0,6814,1108,6813,10,8360,3629,578,0,9211,4056,791,10,5964,8360,4712,0,6815,9211,5139,10,5963,1815,3629,0,6814,2030,4056,10,893,5963,8360,0,1108,6814,9211,10,3621,8361,4713,0,4048,9212,5140,10,1811,5965,8361,0,2026,6816,9212,10,8361,5964,2357,0,9212,6815,2572,10,5965,893,5964,0,6816,1108,6815,10,8362,3633,136,0,9213,4060,203,10,5966,8362,3569,0,6817,9213,3996,10,5969,1817,3633,0,6820,2032,4060,10,894,5969,8362,0,1109,6820,9213,10,3636,8363,3568,0,4063,9214,3995,10,1819,5967,8363,0,2034,6818,9214,10,8363,5966,1785,0,9214,6817,2000,10,5967,894,5966,0,6818,1109,6817,10,8364,3637,323,0,9215,4064,412,10,5968,8364,3634,0,6819,9215,4061,10,5967,1819,3637,0,6818,2034,4064,10,894,5967,8364,0,1109,6818,9215,10,3632,8365,3635,0,4059,9216,4062,10,1817,5969,8365,0,2032,6820,9216,10,8365,5968,1818,0,9216,6819,2033,10,5969,894,5968,0,6820,1109,6819,10,8366,4763,323,0,9217,5190,412,10,5970,8366,3642,0,6821,9217,4069,10,5973,2382,4763,0,6824,2597,5190,10,895,5973,8366,0,1110,6824,9217,10,3640,8367,3643,0,4067,9218,4070,10,1821,5971,8367,0,2036,6822,9218,10,8367,5970,1822,0,9218,6821,2037,10,5971,895,5970,0,6822,1110,6821,10,8368,3641,591,0,9219,4068,806,10,5972,8368,4776,0,6823,9219,5203,10,5971,1821,3641,0,6822,2036,4068,10,895,5971,8368,0,1110,6822,9219,10,4762,8369,4777,0,5189,9220,5204,10,2382,5973,8369,0,2597,6824,9220,10,8369,5972,2389,0,9220,6823,2604,10,5973,895,5972,0,6824,1110,6823,10,8370,3640,324,0,9221,4067,413,10,5974,8370,3644,0,6825,9221,4071,10,5977,1821,3640,0,6828,2036,4067,10,896,5977,8370,0,1111,6828,9221,10,4761,8371,3645,0,5188,9222,4072,10,2381,5975,8371,0,2596,6826,9222,10,8371,5974,1823,0,9222,6825,2038,10,5975,896,5974,0,6826,1111,6825,10,8372,4760,598,0,9223,5187,813,10,5976,8372,4778,0,6827,9223,5205,10,5975,2381,4760,0,6826,2596,5187,10,896,5975,8372,0,1111,6826,9223,10,3641,8373,4779,0,4068,9224,5206,10,1821,5977,8373,0,2036,6828,9224,10,8373,5976,2390,0,9224,6827,2605,10,5977,896,5976,0,6828,1111,6827,10,8374,4709,310,0,9225,5136,399,10,5978,8374,3683,0,6829,9225,4110,10,5981,2355,4709,0,6832,2570,5136,10,897,5981,8374,0,1112,6832,9225,10,3650,8375,3682,0,4077,9226,4109,10,1826,5979,8375,0,2041,6830,9226,10,8375,5978,1842,0,9226,6829,2057,10,5979,897,5978,0,6830,1112,6829,10,8376,3651,580,0,9227,4078,793,10,5980,8376,4714,0,6831,9227,5141,10,5979,1826,3651,0,6830,2041,4078,10,897,5979,8376,0,1112,6830,9227,10,4708,8377,4715,0,5135,9228,5142,10,2355,5981,8377,0,2570,6832,9228,10,8377,5980,2358,0,9228,6831,2573,10,5981,897,5980,0,6832,1112,6831,10,8378,3650,327,0,9229,4077,417,10,5982,8378,3655,0,6833,9229,4082,10,5985,1826,3650,0,6836,2041,4077,10,898,5985,8378,0,1113,6836,9229,10,4705,8379,3654,0,5641,9230,4081,10,2353,5983,8379,0,2823,6834,9230,10,8379,5982,1828,0,9230,6833,2043,10,5983,898,5982,0,6834,1113,6833,10,8380,4704,584,0,9231,5642,798,10,5984,8380,4716,0,6835,9231,5143,10,5983,2353,4704,0,6834,2823,5642,10,898,5983,8380,0,1113,6834,9231,10,3651,8381,4717,0,4078,9232,5144,10,1826,5985,8381,0,2041,6836,9232,10,8381,5984,2359,0,9232,6835,2574,10,5985,898,5984,0,6836,1113,6835,10,8382,3657,308,0,9233,4084,397,10,5986,8382,3660,0,6837,9233,4087,10,5989,1829,3657,0,6840,2044,4084,10,899,5989,8382,0,1114,6840,9233,10,3329,8383,3661,0,3756,9234,4088,10,1665,5987,8383,0,1880,6838,9234,10,8383,5986,1831,0,9234,6837,2046,10,5987,899,5986,0,6838,1114,6837,10,8384,3328,261,0,9235,3755,350,10,5988,8384,3658,0,6839,9235,4085,10,5987,1665,3328,0,6838,1880,3755,10,899,5987,8384,0,1114,6838,9235,10,3656,8385,3659,0,4083,9236,4086,10,1829,5989,8385,0,2044,6840,9236,10,8385,5988,1830,0,9236,6839,2045,10,5989,899,5988,0,6840,1114,6839,10,8386,3612,315,0,9237,4039,404,10,5990,8386,3668,0,6841,9237,4095,10,5993,1807,3612,0,6844,2022,4039,10,900,5993,8386,0,1115,6844,9237,10,3347,8387,3669,0,3774,9238,4096,10,1674,5991,8387,0,1889,6842,9238,10,8387,5990,1835,0,9238,6841,2050,10,5991,900,5990,0,6842,1115,6841,10,8388,3346,266,0,9239,3773,354,10,5992,8388,3666,0,6843,9239,4093,10,5991,1674,3346,0,6842,1889,3773,10,900,5991,8388,0,1115,6842,9239,10,3613,8389,3667,0,4040,9240,4094,10,1807,5993,8389,0,2022,6844,9240,10,8389,5992,1834,0,9240,6843,2049,10,5993,900,5992,0,6844,1115,6843,10,8390,3671,256,0,9241,4098,343,10,5994,8390,3353,0,6845,9241,3780,10,5997,1836,3671,0,6848,2051,4098,10,901,5997,8390,0,1116,6848,9241,10,3672,8391,3352,0,4099,9242,3779,10,1837,5995,8391,0,2052,6846,9242,10,8391,5994,1677,0,9242,6845,1892,10,5995,901,5994,0,6846,1116,6845,10,8392,3673,320,0,9243,4100,409,10,5996,8392,3627,0,6847,9243,4054,10,5995,1837,3673,0,6846,2052,4100,10,901,5995,8392,0,1116,6846,9243,10,3670,8393,3626,0,4097,9244,4053,10,1836,5997,8393,0,2051,6848,9244,10,8393,5996,1814,0,9244,6847,2029,10,5997,901,5996,0,6848,1116,6847,10,8394,3586,305,0,9245,4013,394,10,5998,8394,3635,0,6849,9245,4062,10,6001,1794,3586,0,6852,2009,4013,10,902,6001,8394,0,1117,6852,9245,10,4763,8395,3634,0,5190,9246,4061,10,2382,5999,8395,0,2597,6850,9246,10,8395,5998,1818,0,9246,6849,2033,10,5999,902,5998,0,6850,1117,6849,10,8396,4762,599,0,9247,5189,814,10,6000,8396,4780,0,6851,9247,5207,10,5999,2382,4762,0,6850,2597,5189,10,902,5999,8396,0,1117,6850,9247,10,3587,8397,4781,0,4014,9248,5208,10,1794,6001,8397,0,2009,6852,9248,10,8397,6000,2391,0,9248,6851,2606,10,6001,902,6000,0,6852,1117,6851,10,8398,3677,260,0,9249,4104,347,10,6002,8398,3321,0,6853,9249,3748,10,6005,1839,3677,0,6856,2054,4104,10,903,6005,8398,0,1118,6856,9249,10,3678,8399,3320,0,4105,9250,3747,10,1840,6003,8399,0,2055,6854,9250,10,8399,6002,1661,0,9250,6853,1876,10,6003,903,6002,0,6854,1118,6853,10,8400,3679,325,0,9251,4106,414,10,6004,8400,3653,0,6855,9251,4080,10,6003,1840,3679,0,6854,2055,4106,10,903,6003,8400,0,1118,6854,9251,10,3676,8401,3652,0,4103,9252,4079,10,1839,6005,8401,0,2054,6856,9252,10,8401,6004,1827,0,9252,6855,2042,10,6005,903,6004,0,6856,1118,6855,10,8402,3584,309,0,9253,4011,398,10,6006,8402,3601,0,6857,9253,4028,10,6009,1793,3584,0,6860,2008,4011,10,904,6009,8402,0,1119,6860,9253,10,4709,8403,3600,0,5136,9254,4027,10,2355,6007,8403,0,2570,6858,9254,10,8403,6006,1801,0,9254,6857,2016,10,6007,904,6006,0,6858,1119,6857,10,8404,4708,586,0,9255,5135,800,10,6008,8404,4718,0,6859,9255,5145,10,6007,2355,4708,0,6858,2570,5135,10,904,6007,8404,0,1119,6858,9255,10,3585,8405,4719,0,4012,9256,5146,10,1793,6009,8405,0,2008,6860,9256,10,8405,6008,2360,0,9256,6859,2575,10,6009,904,6008,0,6860,1119,6859,10,8406,3632,305,0,9257,4059,394,10,6010,8406,3589,0,6861,9257,4016,10,6013,1817,3632,0,6864,2032,4059,10,905,6013,8406,0,1120,6864,9257,10,3583,8407,3588,0,4010,9258,4015,10,1792,6011,8407,0,2007,6862,9258,10,8407,6010,1795,0,9258,6861,2010,10,6011,905,6010,0,6862,1120,6861,10,8408,3582,302,0,9259,4009,391,10,6012,8408,3575,0,6863,9259,4002,10,6011,1792,3582,0,6862,2007,4009,10,905,6011,8408,0,1120,6862,9259,10,3633,8409,3574,0,4060,9260,4001,10,1817,6013,8409,0,2032,6864,9260,10,8409,6012,1788,0,9260,6863,2003,10,6013,905,6012,0,6864,1120,6863,10,8410,3687,264,0,9261,4114,352,10,6014,8410,3335,0,6865,9261,3762,10,6017,1844,3687,0,6868,2059,4114,10,906,6017,8410,0,1121,6868,9261,10,3661,8411,3334,0,4088,9262,3761,10,1831,6015,8411,0,2046,6866,9262,10,8411,6014,1668,0,9262,6865,1883,10,6015,906,6014,0,6866,1121,6865,10,8412,3660,308,0,9263,4087,397,10,6016,8412,3597,0,6867,9263,4024,10,6015,1831,3660,0,6866,2046,4087,10,906,6015,8412,0,1121,6866,9263,10,3686,8413,3596,0,4113,9264,4023,10,1844,6017,8413,0,2059,6868,9264,10,8413,6016,1799,0,9264,6867,2014,10,6017,906,6016,0,6868,1121,6867,10,8414,3310,255,0,9265,3737,342,10,6018,8414,3688,0,6869,9265,4115,10,6021,1656,3310,0,6872,1871,3737,10,907,6021,8414,0,1122,6872,9265,10,3643,8415,3689,0,4070,9266,4116,10,1822,6019,8415,0,2037,6870,9266,10,8415,6018,1845,0,9266,6869,2060,10,6019,907,6018,0,6870,1122,6869,10,8416,3642,323,0,9267,4069,412,10,6020,8416,3637,0,6871,9267,4064,10,6019,1822,3642,0,6870,2037,4069,10,907,6019,8416,0,1122,6870,9267,10,3311,8417,3636,0,3738,9268,4063,10,1656,6021,8417,0,1871,6872,9268,10,8417,6020,1819,0,9268,6871,2034,10,6021,907,6020,0,6872,1122,6871,10,8418,3304,256,0,9269,3731,343,10,6022,8418,3671,0,6873,9269,4098,10,6025,1653,3304,0,6876,1868,3731,10,908,6025,8418,0,1123,6876,9269,10,3645,8419,3670,0,4072,9270,4097,10,1823,6023,8419,0,2038,6874,9270,10,8419,6022,1836,0,9270,6873,2051,10,6023,908,6022,0,6874,1123,6873,10,8420,3644,324,0,9271,4071,413,10,6024,8420,3689,0,6875,9271,4116,10,6023,1823,3644,0,6874,2038,4071,10,908,6023,8420,0,1123,6874,9271,10,3305,8421,3688,0,3732,9272,4115,10,1653,6025,8421,0,1868,6876,9272,10,8421,6024,1845,0,9272,6875,2060,10,6025,908,6024,0,6876,1123,6875,10,8422,3598,308,0,9273,4025,397,10,6026,8422,3657,0,6877,9273,4084,10,6029,1800,3598,0,6880,2015,4025,10,909,6029,8422,0,1124,6880,9273,10,4755,8423,3656,0,5182,9274,4083,10,2378,6027,8423,0,2593,6878,9274,10,8423,6026,1829,0,9274,6877,2044,10,6027,909,6026,0,6878,1124,6877,10,8424,4754,595,0,9275,5181,810,10,6028,8424,4782,0,6879,9275,5209,10,6027,2378,4754,0,6878,2593,5181,10,909,6027,8424,0,1124,6878,9275,10,3599,8425,4783,0,4026,9276,5210,10,1800,6029,8425,0,2015,6880,9276,10,8425,6028,2392,0,9276,6879,2607,10,6029,909,6028,0,6880,1124,6879,10,8426,3324,260,0,9277,5366,422,10,6030,8426,3677,0,6881,9277,5373,10,6033,1663,3324,0,6884,2685,5366,10,910,6033,8426,0,1125,6884,9277,10,3663,8427,3676,0,4090,9278,5374,10,1832,6031,8427,0,2047,6882,9278,10,8427,6030,1839,0,9278,6881,2689,10,6031,910,6030,0,6882,1125,6881,10,8428,3662,328,0,9279,4089,418,10,6032,8428,3659,0,6883,9279,4086,10,6031,1832,3662,0,6882,2047,4089,10,910,6031,8428,0,1125,6882,9279,10,3325,8429,3658,0,5365,9280,4085,10,1663,6033,8429,0,2685,6884,9280,10,8429,6032,1830,0,9280,6883,2045,10,6033,910,6032,0,6884,1125,6883,10,8430,3350,267,0,9281,3777,355,10,6034,8430,3669,0,6885,9281,4096,10,6037,1676,3350,0,6888,1891,3777,10,911,6037,8430,0,1126,6888,9281,10,3625,8431,3668,0,4052,9282,4095,10,1813,6035,8431,0,2028,6886,9282,10,8431,6034,1835,0,9282,6885,2050,10,6035,911,6034,0,6886,1126,6885,10,8432,3624,320,0,9283,4051,409,10,6036,8432,3673,0,6887,9283,4100,10,6035,1813,3624,0,6886,2028,4051,10,911,6035,8432,0,1126,6886,9283,10,3351,8433,3672,0,3778,9284,4099,10,1676,6037,8433,0,1891,6888,9284,10,8433,6036,1837,0,9284,6887,2052,10,6037,911,6036,0,6888,1126,6887,10,8434,3678,258,0,9285,4105,345,10,6038,8434,3315,0,6889,9285,3742,10,6041,1840,3678,0,6892,2055,4105,10,912,6041,8434,0,1127,6892,9285,10,3579,8435,3314,0,4006,9286,3741,10,1790,6039,8435,0,2005,6890,9286,10,8435,6038,1658,0,9286,6889,1873,10,6039,912,6038,0,6890,1127,6889,10,8436,3578,303,0,9287,4005,392,10,6040,8436,3649,0,6891,9287,4076,10,6039,1790,3578,0,6890,2005,4005,10,912,6039,8436,0,1127,6890,9287,10,3679,8437,3648,0,4106,9288,4075,10,1840,6041,8437,0,2055,6892,9288,10,8437,6040,1825,0,9288,6891,2040,10,6041,912,6040,0,6892,1127,6891,10,8438,3590,307,0,9289,4017,396,10,6042,8438,3667,0,6893,9289,4094,10,6045,1796,3590,0,6896,2011,4017,10,913,6045,8438,0,1128,6896,9289,10,3341,8439,3666,0,3768,9290,4093,10,1671,6043,8439,0,1886,6894,9290,10,8439,6042,1834,0,9290,6893,2049,10,6043,913,6042,0,6894,1128,6893,10,8440,3340,264,0,9291,3767,352,10,6044,8440,3687,0,6895,9291,4114,10,6043,1671,3340,0,6894,1886,3767,10,913,6043,8440,0,1128,6894,9291,10,3591,8441,3686,0,4018,9292,4113,10,1796,6045,8441,0,2011,6896,9292,10,8441,6044,1844,0,9292,6895,2059,10,6045,913,6044,0,6896,1128,6895,10,8442,3697,332,0,9293,4124,429,10,6046,8442,3690,0,6897,9293,4117,10,6049,1849,3697,0,6900,2064,4124,10,914,6049,8442,0,1129,6900,9293,10,3692,8443,3691,0,4119,9294,4118,10,1847,6047,8443,0,2062,6898,9294,10,8443,6046,1846,0,9294,6897,2061,10,6047,914,6046,0,6898,1129,6897,10,8444,3693,339,0,9295,4120,443,10,6048,8444,3694,0,6899,9295,4121,10,6047,1847,3693,0,6898,2062,4120,10,914,6047,8444,0,1129,6898,9295,10,3696,8445,3695,0,4123,9296,4122,10,1849,6049,8445,0,2064,6900,9296,10,8445,6048,1848,0,9296,6899,2063,10,6049,914,6048,0,6900,1129,6899,10,8446,3692,348,0,9297,4119,468,10,6050,8446,3698,0,6901,9297,4125,10,6053,1847,3692,0,6904,2062,4119,10,915,6053,8446,0,1130,6904,9297,10,3700,8447,3699,0,4127,9298,4126,10,1851,6051,8447,0,2066,6902,9298,10,8447,6050,1850,0,9298,6901,2065,10,6051,915,6050,0,6902,1130,6901,10,8448,3701,353,0,9299,4128,457,10,6052,8448,3702,0,6903,9299,4129,10,6051,1851,3701,0,6902,2066,4128,10,915,6051,8448,0,1130,6902,9299,10,3693,8449,3703,0,4120,9300,4130,10,1847,6053,8449,0,2062,6904,9300,10,8449,6052,1852,0,9300,6903,2067,10,6053,915,6052,0,6904,1130,6903,10,8450,3709,333,0,9301,4136,432,10,6054,8450,3704,0,6905,9301,4131,10,6057,1855,3709,0,6908,2070,4136,10,916,6057,8450,0,1131,6908,9301,10,3706,8451,3705,0,4133,9302,4132,10,1854,6055,8451,0,2069,6906,9302,10,8451,6054,1853,0,9302,6905,2068,10,6055,916,6054,0,6906,1131,6905,10,8452,3707,339,0,9303,4134,443,10,6056,8452,3703,0,6907,9303,4130,10,6055,1854,3707,0,6906,2069,4134,10,916,6055,8452,0,1131,6906,9303,10,3708,8453,3702,0,4135,9304,4129,10,1855,6057,8453,0,2070,6908,9304,10,8453,6056,1852,0,9304,6907,2067,10,6057,916,6056,0,6908,1131,6907,10,8454,3706,350,0,9305,4133,470,10,6058,8454,3710,0,6909,9305,4137,10,6061,1854,3706,0,6912,2069,4133,10,917,6061,8454,0,1132,6912,9305,10,3712,8455,3711,0,4139,9306,4138,10,1857,6059,8455,0,2072,6910,9306,10,8455,6058,1856,0,9306,6909,2071,10,6059,917,6058,0,6910,1132,6909,10,8456,3713,352,0,9307,4140,472,10,6060,8456,3695,0,6911,9307,4122,10,6059,1857,3713,0,6910,2072,4140,10,917,6059,8456,0,1132,6910,9307,10,3707,8457,3694,0,4134,9308,4121,10,1854,6061,8457,0,2069,6912,9308,10,8457,6060,1848,0,9308,6911,2063,10,6061,917,6060,0,6912,1132,6911,10,8458,3700,331,0,9309,5382,433,10,6062,8458,3714,0,6913,9309,4141,10,6065,1851,3700,0,6916,2693,5382,10,918,6065,8458,0,1133,6916,9309,10,3716,8459,3715,0,4143,9310,4142,10,1859,6063,8459,0,2074,6914,9310,10,8459,6062,1858,0,9310,6913,2073,10,6063,918,6062,0,6914,1133,6913,10,8460,3717,340,0,9311,4144,444,10,6064,8460,3718,0,6915,9311,4145,10,6063,1859,3717,0,6914,2074,4144,10,918,6063,8460,0,1133,6914,9311,10,3701,8461,3719,0,5381,9312,4146,10,1851,6065,8461,0,2693,6916,9312,10,8461,6064,1860,0,9312,6915,2075,10,6065,918,6064,0,6916,1133,6915,10,8462,3716,354,0,9313,4143,474,10,6066,8462,3720,0,6917,9313,4147,10,6069,1859,3716,0,6920,2074,4143,10,919,6069,8462,0,1134,6920,9313,10,3722,8463,3721,0,4149,9314,4148,10,1862,6067,8463,0,2077,6918,9314,10,8463,6066,1861,0,9314,6917,2076,10,6067,919,6066,0,6918,1134,6917,10,8464,3723,361,0,9315,4150,465,10,6068,8464,3724,0,6919,9315,4151,10,6067,1862,3723,0,6918,2077,4150,10,919,6067,8464,0,1134,6918,9315,10,3717,8465,3725,0,4144,9316,4152,10,1859,6069,8465,0,2074,6920,9316,10,8465,6068,1863,0,9316,6919,2078,10,6069,919,6068,0,6920,1134,6919,10,8466,3731,338,0,9317,4158,442,10,6070,8466,3726,0,6921,9317,4153,10,6073,1866,3731,0,6924,2081,4158,10,920,6073,8466,0,1135,6924,9317,10,3728,8467,3727,0,4155,9318,4154,10,1865,6071,8467,0,2080,6922,9318,10,8467,6070,1864,0,9318,6921,2079,10,6071,920,6070,0,6922,1135,6921,10,8468,3729,340,0,9319,4156,444,10,6072,8468,3725,0,6923,9319,4152,10,6071,1865,3729,0,6922,2080,4156,10,920,6071,8468,0,1135,6922,9319,10,3730,8469,3724,0,4157,9320,4151,10,1866,6073,8469,0,2081,6924,9320,10,8469,6072,1863,0,9320,6923,2078,10,6073,920,6072,0,6924,1135,6923,10,8470,3728,351,0,9321,4155,471,10,6074,8470,3732,0,6925,9321,4159,10,6077,1865,3728,0,6928,2080,4155,10,921,6077,8470,0,1136,6928,9321,10,3709,8471,3733,0,5385,9322,4160,10,1855,6075,8471,0,2695,6926,9322,10,8471,6074,1867,0,9322,6925,2082,10,6075,921,6074,0,6926,1136,6925,10,8472,3708,353,0,9323,5386,473,10,6076,8472,3719,0,6927,9323,4146,10,6075,1855,3708,0,6926,2695,5386,10,921,6075,8472,0,1136,6926,9323,10,3729,8473,3718,0,4156,9324,4145,10,1865,6077,8473,0,2080,6928,9324,10,8473,6076,1860,0,9324,6927,2075,10,6077,921,6076,0,6928,1136,6927,10,8474,3739,335,0,9325,4166,435,10,6078,8474,3721,0,6929,9325,5393,10,6081,1870,3739,0,6932,2085,4166,10,922,6081,8474,0,1137,6932,9325,10,3734,8475,3720,0,4161,9326,5394,10,1868,6079,8475,0,2083,6930,9326,10,8475,6078,1861,0,9326,6929,2699,10,6079,922,6078,0,6930,1137,6929,10,8476,3735,341,0,9327,4162,445,10,6080,8476,3736,0,6931,9327,4163,10,6079,1868,3735,0,6930,2083,4162,10,922,6079,8476,0,1137,6930,9327,10,3738,8477,3737,0,4165,9328,4164,10,1870,6081,8477,0,2085,6932,9328,10,8477,6080,1869,0,9328,6931,2084,10,6081,922,6080,0,6932,1137,6931,10,8478,3734,354,0,9329,4161,458,10,6082,8478,3715,0,6933,9329,5391,10,6085,1868,3734,0,6936,2083,4161,10,923,6085,8478,0,1138,6936,9329,10,3699,8479,3714,0,5379,9330,5392,10,1850,6083,8479,0,2692,6934,9330,10,8479,6082,1858,0,9330,6933,2698,10,6083,923,6082,0,6934,1138,6933,10,8480,3698,348,0,9331,5380,452,10,6084,8480,3740,0,6935,9331,4167,10,6083,1850,3698,0,6934,2692,5380,10,923,6083,8480,0,1138,6934,9331,10,3735,8481,3741,0,4162,9332,4168,10,1868,6085,8481,0,2083,6936,9332,10,8481,6084,1871,0,9332,6935,2086,10,6085,923,6084,0,6936,1138,6935,10,8482,3690,332,0,9333,5376,424,10,6086,8482,3742,0,6937,9333,4169,10,6089,1846,3690,0,6940,2690,5376,10,924,6089,8482,0,1139,6940,9333,10,3744,8483,3743,0,4171,9334,4170,10,1873,6087,8483,0,2088,6938,9334,10,8483,6086,1872,0,9334,6937,2087,10,6087,924,6086,0,6938,1139,6937,10,8484,3745,341,0,9335,4172,445,10,6088,8484,3741,0,6939,9335,4168,10,6087,1873,3745,0,6938,2088,4172,10,924,6087,8484,0,1139,6938,9335,10,3691,8485,3740,0,5375,9336,4167,10,1846,6089,8485,0,2690,6940,9336,10,8485,6088,1871,0,9336,6939,2086,10,6089,924,6088,0,6940,1139,6939,10,8486,3744,349,0,9337,4171,453,10,6090,8486,3746,0,6941,9337,4173,10,6093,1873,3744,0,6944,2088,4171,10,925,6093,8486,0,1140,6944,9337,10,3748,8487,3747,0,4175,9338,4174,10,1875,6091,8487,0,2090,6942,9338,10,8487,6090,1874,0,9338,6941,2089,10,6091,925,6090,0,6942,1140,6941,10,8488,3749,358,0,9339,4176,462,10,6092,8488,3737,0,6943,9339,4164,10,6091,1875,3749,0,6942,2090,4176,10,925,6091,8488,0,1140,6942,9339,10,3745,8489,3736,0,4172,9340,4163,10,1873,6093,8489,0,2088,6944,9340,10,8489,6092,1869,0,9340,6943,2084,10,6093,925,6092,0,6944,1140,6943,10,8490,3757,337,0,9341,4184,439,10,6094,8490,3750,0,6945,9341,4177,10,6097,1879,3757,0,6948,2094,4184,10,926,6097,8490,0,1141,6948,9341,10,3752,8491,3751,0,4179,9342,4178,10,1877,6095,8491,0,2092,6946,9342,10,8491,6094,1876,0,9342,6945,2091,10,6095,926,6094,0,6946,1141,6945,10,8492,3753,342,0,9343,4180,446,10,6096,8492,3754,0,6947,9343,4181,10,6095,1877,3753,0,6946,2092,4180,10,926,6095,8492,0,1141,6946,9343,10,3756,8493,3755,0,4183,9344,4182,10,1879,6097,8493,0,2094,6948,9344,10,8493,6096,1878,0,9344,6947,2093,10,6097,926,6096,0,6948,1141,6947,10,8494,3752,356,0,9345,4179,460,10,6098,8494,3758,0,6949,9345,4185,10,6101,1877,3752,0,6952,2092,4179,10,927,6101,8494,0,1142,6952,9345,10,3711,8495,3759,0,5387,9346,4186,10,1856,6099,8495,0,2696,6950,9346,10,8495,6098,1880,0,9346,6949,2095,10,6099,927,6098,0,6950,1142,6949,10,8496,3710,350,0,9347,5388,454,10,6100,8496,3760,0,6951,9347,4187,10,6099,1856,3710,0,6950,2696,5388,10,927,6099,8496,0,1142,6950,9347,10,3753,8497,3761,0,4180,9348,4188,10,1877,6101,8497,0,2092,6952,9348,10,8497,6100,1881,0,9348,6951,2096,10,6101,927,6100,0,6952,1142,6951,10,8498,3704,333,0,9349,5384,425,10,6102,8498,3733,0,6953,9349,5397,10,6105,1853,3704,0,6956,2694,5384,10,928,6105,8498,0,1143,6956,9349,10,3762,8499,3732,0,4189,9350,5398,10,1882,6103,8499,0,2097,6954,9350,10,8499,6102,1867,0,9350,6953,2701,10,6103,928,6102,0,6954,1143,6953,10,8500,3763,342,0,9351,4190,446,10,6104,8500,3761,0,6955,9351,4188,10,6103,1882,3763,0,6954,2097,4190,10,928,6103,8500,0,1143,6954,9351,10,3705,8501,3760,0,5383,9352,4187,10,1853,6105,8501,0,2694,6956,9352,10,8501,6104,1881,0,9352,6955,2096,10,6105,928,6104,0,6956,1143,6955,10,8502,3762,351,0,9353,4189,455,10,6106,8502,3727,0,6957,9353,5395,10,6109,1882,3762,0,6960,2097,4189,10,929,6109,8502,0,1144,6960,9353,10,3764,8503,3726,0,4191,9354,5396,10,1883,6107,8503,0,2098,6958,9354,10,8503,6106,1864,0,9354,6957,2700,10,6107,929,6106,0,6958,1144,6957,10,8504,3765,359,0,9355,4192,463,10,6108,8504,3755,0,6959,9355,4182,10,6107,1883,3765,0,6958,2098,4192,10,929,6107,8504,0,1144,6958,9355,10,3763,8505,3754,0,4190,9356,4181,10,1882,6109,8505,0,2097,6960,9356,10,8505,6108,1878,0,9356,6959,2093,10,6109,929,6108,0,6960,1144,6959,10,8506,3771,336,0,9357,4198,438,10,6110,8506,3747,0,6961,9357,5401,10,6113,1886,3771,0,6964,2101,4198,10,930,6113,8506,0,1145,6964,9357,10,3766,8507,3746,0,4193,9358,5402,10,1884,6111,8507,0,2099,6962,9358,10,8507,6110,1874,0,9358,6961,2703,10,6111,930,6110,0,6962,1145,6961,10,8508,3767,343,0,9359,4194,447,10,6112,8508,3768,0,6963,9359,4195,10,6111,1884,3767,0,6962,2099,4194,10,930,6111,8508,0,1145,6962,9359,10,3770,8509,3769,0,4197,9360,4196,10,1886,6113,8509,0,2101,6964,9360,10,8509,6112,1885,0,9360,6963,2100,10,6113,930,6112,0,6964,1145,6963,10,8510,3766,349,0,9361,4193,469,10,6114,8510,3743,0,6965,9361,5399,10,6117,1884,3766,0,6968,2099,4193,10,931,6117,8510,0,1146,6968,9361,10,3697,8511,3742,0,5377,9362,5400,10,1849,6115,8511,0,2691,6966,9362,10,8511,6114,1872,0,9362,6965,2702,10,6115,931,6114,0,6966,1146,6965,10,8512,3696,352,0,9363,5378,456,10,6116,8512,3772,0,6967,9363,4199,10,6115,1849,3696,0,6966,2691,5378,10,931,6115,8512,0,1146,6966,9363,10,3767,8513,3773,0,4194,9364,4200,10,1884,6117,8513,0,2099,6968,9364,10,8513,6116,1887,0,9364,6967,2102,10,6117,931,6116,0,6968,1146,6967,10,8514,3712,334,0,9365,5390,428,10,6118,8514,3759,0,6969,9365,5405,10,6121,1857,3712,0,6972,2697,5390,10,932,6121,8514,0,1147,6972,9365,10,3774,8515,3758,0,4201,9366,5406,10,1888,6119,8515,0,2103,6970,9366,10,8515,6118,1880,0,9366,6969,2705,10,6119,932,6118,0,6970,1147,6969,10,8516,3775,343,0,9367,4202,447,10,6120,8516,3773,0,6971,9367,4200,10,6119,1888,3775,0,6970,2103,4202,10,932,6119,8516,0,1147,6970,9367,10,3713,8517,3772,0,5389,9368,4199,10,1857,6121,8517,0,2697,6972,9368,10,8517,6120,1887,0,9368,6971,2102,10,6121,932,6120,0,6972,1147,6971,10,8518,3774,356,0,9369,4201,476,10,6122,8518,3751,0,6973,9369,5403,10,6125,1888,3774,0,6976,2103,4201,10,933,6125,8518,0,1148,6976,9369,10,3776,8519,3750,0,4203,9370,5404,10,1889,6123,8519,0,2104,6974,9370,10,8519,6122,1876,0,9370,6973,2704,10,6123,933,6122,0,6974,1148,6973,10,8520,3777,360,0,9371,4204,464,10,6124,8520,3769,0,6975,9371,4196,10,6123,1889,3777,0,6974,2104,4204,10,933,6123,8520,0,1148,6974,9371,10,3775,8521,3768,0,4202,9372,4195,10,1888,6125,8521,0,2103,6976,9372,10,8521,6124,1885,0,9372,6975,2100,10,6125,933,6124,0,6976,1148,6975,10,8522,3722,335,0,9373,4149,436,10,6126,8522,3778,0,6977,9373,4205,10,6129,1862,3722,0,6980,2077,4149,10,934,6129,8522,0,1149,6980,9373,10,3780,8523,3779,0,4207,9374,4206,10,1891,6127,8523,0,2106,6978,9374,10,8523,6126,1890,0,9374,6977,2105,10,6127,934,6126,0,6978,1149,6977,10,8524,3781,344,0,9375,4208,448,10,6128,8524,3782,0,6979,9375,4209,10,6127,1891,3781,0,6978,2106,4208,10,934,6127,8524,0,1149,6978,9375,10,3723,8525,3783,0,4150,9376,4210,10,1862,6129,8525,0,2077,6980,9376,10,8525,6128,1892,0,9376,6979,2107,10,6129,934,6128,0,6980,1149,6979,10,8526,3780,362,0,9377,4207,478,10,6130,8526,3817,0,6981,9377,5419,10,6133,1891,3780,0,6984,2106,4207,10,935,6133,8526,0,1150,6984,9377,10,2863,8527,3816,0,3290,9378,5420,10,1432,6131,8527,0,1647,6982,9378,10,8527,6130,1909,0,9378,6981,2712,10,6131,935,6130,0,6982,1150,6981,10,8528,2862,120,0,9379,3289,193,10,6132,8528,3818,0,6983,9379,4245,10,6131,1432,2862,0,6982,1647,3289,10,935,6131,8528,0,1150,6982,9379,10,3781,8529,3819,0,4208,9380,4246,10,1891,6133,8529,0,2106,6984,9380,10,8529,6132,1910,0,9380,6983,2125,10,6133,935,6132,0,6984,1150,6983,10,8530,3821,357,0,9381,4248,477,10,6134,8530,3784,0,6985,9381,4211,10,6137,1911,3821,0,6988,2126,4248,10,936,6137,8530,0,1151,6988,9381,10,3819,8531,3785,0,5421,9382,4212,10,1910,6135,8531,0,2713,6986,9382,10,8531,6134,1893,0,9382,6985,2108,10,6135,936,6134,0,6986,1151,6985,10,8532,3818,120,0,9383,5422,184,10,6136,8532,2845,0,6987,9383,3272,10,6135,1910,3818,0,6986,2713,5422,10,936,6135,8532,0,1151,6986,9383,10,3820,8533,2844,0,4247,9384,3271,10,1911,6137,8533,0,2126,6988,9384,10,8533,6136,1423,0,9384,6987,1638,10,6137,936,6136,0,6988,1151,6987,10,8534,3784,357,0,9385,4211,477,10,6138,8534,3786,0,6989,9385,4213,10,6141,1893,3784,0,6992,2108,4211,10,937,6141,8534,0,1152,6992,9385,10,3731,8535,3787,0,4158,9386,4214,10,1866,6139,8535,0,2081,6990,9386,10,8535,6138,1894,0,9386,6989,2109,10,6139,937,6138,0,6990,1152,6989,10,8536,3730,361,0,9387,4157,465,10,6140,8536,3783,0,6991,9387,4210,10,6139,1866,3730,0,6990,2081,4157,10,937,6139,8536,0,1152,6990,9387,10,3785,8537,3782,0,4212,9388,4209,10,1893,6141,8537,0,2108,6992,9388,10,8537,6140,1892,0,9388,6991,2107,10,6141,937,6140,0,6992,1152,6991,10,8538,3817,362,0,9389,4244,466,10,6142,8538,3788,0,6993,9389,4215,10,6145,1909,3817,0,6996,2124,4244,10,938,6145,8538,0,1153,6996,9389,10,3815,8539,3789,0,4242,9390,4216,10,1908,6143,8539,0,2123,6994,9390,10,8539,6142,1895,0,9390,6993,2110,10,6143,938,6142,0,6994,1153,6993,10,8540,3814,153,0,9391,4241,220,10,6144,8540,2937,0,6995,9391,3364,10,6143,1908,3814,0,6994,2123,4241,10,938,6143,8540,0,1153,6994,9391,10,3816,8541,2936,0,4243,9392,3363,10,1909,6145,8541,0,2124,6996,9392,10,8541,6144,1469,0,9392,6995,1684,10,6145,938,6144,0,6996,1153,6995,10,8542,3788,362,0,9393,4215,466,10,6146,8542,3779,0,6997,9393,5407,10,6149,1895,3788,0,7000,2110,4215,10,939,6149,8542,0,1154,7000,9393,10,3739,8543,3778,0,4166,9394,5408,10,1870,6147,8543,0,2085,6998,9394,10,8543,6146,1890,0,9394,6997,2706,10,6147,939,6146,0,6998,1154,6997,10,8544,3738,358,0,9395,4165,462,10,6148,8544,3790,0,6999,9395,4217,10,6147,1870,3738,0,6998,2085,4165,10,939,6147,8544,0,1154,6998,9395,10,3789,8545,3791,0,4216,9396,4218,10,1895,6149,8545,0,2110,7000,9396,10,8545,6148,1896,0,9396,6999,2111,10,6149,939,6148,0,7000,1154,6999,10,8546,3748,336,0,9397,4175,437,10,6150,8546,3792,0,7001,9397,4219,10,6153,1875,3748,0,7004,2090,4175,10,940,6153,8546,0,1155,7004,9397,10,3794,8547,3793,0,4221,9398,4220,10,1898,6151,8547,0,2113,7002,9398,10,8547,6150,1897,0,9398,7001,2112,10,6151,940,6150,0,7002,1155,7001,10,8548,3795,345,0,9399,4222,449,10,6152,8548,3791,0,7003,9399,4218,10,6151,1898,3795,0,7002,2113,4222,10,940,6151,8548,0,1155,7002,9399,10,3749,8549,3790,0,4176,9400,4217,10,1875,6153,8549,0,2090,7004,9400,10,8549,6152,1896,0,9400,7003,2111,10,6153,940,6152,0,7004,1155,7003,10,8550,3794,355,0,9401,4221,459,10,6154,8550,3813,0,7005,9401,5417,10,6157,1898,3794,0,7008,2113,4221,10,941,6157,8550,0,1156,7008,9401,10,2931,8551,3812,0,3358,9402,5418,10,1466,6155,8551,0,1681,7006,9402,10,8551,6154,1907,0,9402,7005,2711,10,6155,941,6154,0,7006,1156,7005,10,8552,2930,153,0,9403,3357,220,10,6156,8552,3814,0,7007,9403,4241,10,6155,1466,2930,0,7006,1681,3357,10,941,6155,8552,0,1156,7006,9403,10,3795,8553,3815,0,4222,9404,4242,10,1898,6157,8553,0,2113,7008,9404,10,8553,6156,1908,0,9404,7007,2123,10,6157,941,6156,0,7008,1156,7007,10,8554,3825,363,0,9405,4252,467,10,6158,8554,3796,0,7009,9405,4223,10,6161,1913,3825,0,7012,2128,4252,10,942,6161,8554,0,1157,7012,9405,10,3823,8555,3797,0,4250,9406,4224,10,1912,6159,8555,0,2127,7010,9406,10,8555,6158,1899,0,9406,7009,2114,10,6159,942,6158,0,7010,1157,7009,10,8556,3822,286,0,9407,4249,375,10,6160,8556,3439,0,7011,9407,3866,10,6159,1912,3822,0,7010,2127,4249,10,942,6159,8556,0,1157,7010,9407,10,3824,8557,3438,0,4251,9408,3865,10,1913,6161,8557,0,2128,7012,9408,10,8557,6160,1720,0,9408,7011,1935,10,6161,942,6160,0,7012,1157,7011,10,8558,3796,363,0,9409,4223,467,10,6162,8558,3798,0,7013,9409,4225,10,6165,1899,3796,0,7016,2114,4223,10,943,6165,8558,0,1158,7016,9409,10,3757,8559,3799,0,4184,9410,4226,10,1879,6163,8559,0,2094,7014,9410,10,8559,6162,1900,0,9410,7013,2115,10,6163,943,6162,0,7014,1158,7013,10,8560,3756,359,0,9411,4183,463,10,6164,8560,3800,0,7015,9411,4227,10,6163,1879,3756,0,7014,2094,4183,10,943,6163,8560,0,1158,7014,9411,10,3797,8561,3801,0,4224,9412,4228,10,1899,6165,8561,0,2114,7016,9412,10,8561,6164,1901,0,9412,7015,2116,10,6165,943,6164,0,7016,1158,7015,10,8562,3764,338,0,9413,4191,441,10,6166,8562,3787,0,7017,9413,5409,10,6169,1883,3764,0,7020,2098,4191,10,944,6169,8562,0,1159,7020,9413,10,3802,8563,3786,0,4229,9414,5410,10,1902,6167,8563,0,2117,7018,9414,10,8563,6166,1894,0,9414,7017,2707,10,6167,944,6166,0,7018,1159,7017,10,8564,3803,346,0,9415,4230,450,10,6168,8564,3801,0,7019,9415,4228,10,6167,1902,3803,0,7018,2117,4230,10,944,6167,8564,0,1159,7018,9415,10,3765,8565,3800,0,4192,9416,4227,10,1883,6169,8565,0,2098,7020,9416,10,8565,6168,1901,0,9416,7019,2116,10,6169,944,6168,0,7020,1159,7019,10,8566,3802,357,0,9417,4229,461,10,6170,8566,3821,0,7021,9417,5423,10,6173,1902,3802,0,7024,2117,4229,10,945,6173,8566,0,1160,7024,9417,10,3513,8567,3820,0,3940,9418,5424,10,1757,6171,8567,0,1972,7022,9418,10,8567,6170,1911,0,9418,7021,2714,10,6171,945,6170,0,7022,1160,7021,10,8568,3512,286,0,9419,3939,375,10,6172,8568,3822,0,7023,9419,4249,10,6171,1757,3512,0,7022,1972,3939,10,945,6171,8568,0,1160,7022,9419,10,3803,8569,3823,0,4230,9420,4250,10,1902,6173,8569,0,2117,7024,9420,10,8569,6172,1912,0,9420,7023,2127,10,6173,945,6172,0,7024,1160,7023,10,8570,3813,355,0,9421,4240,475,10,6174,8570,3804,0,7025,9421,4231,10,6177,1907,3813,0,7028,2122,4240,10,946,6177,8570,0,1161,7028,9421,10,3811,8571,3805,0,5415,9422,4232,10,1906,6175,8571,0,2710,7026,9422,10,8571,6174,1903,0,9422,7025,2118,10,6175,946,6174,0,7026,1161,7025,10,8572,3810,210,0,9423,5416,281,10,6176,8572,3123,0,7027,9423,3550,10,6175,1906,3810,0,7026,2710,5416,10,946,6175,8572,0,1161,7026,9423,10,3812,8573,3122,0,4239,9424,3549,10,1907,6177,8573,0,2122,7028,9424,10,8573,6176,1562,0,9424,7027,1777,10,6177,946,6176,0,7028,1161,7027,10,8574,3804,355,0,9425,4231,475,10,6178,8574,3793,0,7029,9425,5411,10,6181,1903,3804,0,7032,2118,4231,10,947,6181,8574,0,1162,7032,9425,10,3771,8575,3792,0,4198,9426,5412,10,1886,6179,8575,0,2101,7030,9426,10,8575,6178,1897,0,9426,7029,2708,10,6179,947,6178,0,7030,1162,7029,10,8576,3770,360,0,9427,4197,464,10,6180,8576,3806,0,7031,9427,4233,10,6179,1886,3770,0,7030,2101,4197,10,947,6179,8576,0,1162,7030,9427,10,3805,8577,3807,0,4232,9428,4234,10,1903,6181,8577,0,2118,7032,9428,10,8577,6180,1904,0,9428,7031,2119,10,6181,947,6180,0,7032,1162,7031,10,8578,3776,337,0,9429,4203,440,10,6182,8578,3799,0,7033,9429,5413,10,6185,1889,3776,0,7036,2104,4203,10,948,6185,8578,0,1163,7036,9429,10,3808,8579,3798,0,4235,9430,5414,10,1905,6183,8579,0,2120,7034,9430,10,8579,6182,1900,0,9430,7033,2709,10,6183,948,6182,0,7034,1163,7033,10,8580,3809,347,0,9431,4236,451,10,6184,8580,3807,0,7035,9431,4234,10,6183,1905,3809,0,7034,2120,4236,10,948,6183,8580,0,1163,7034,9431,10,3777,8581,3806,0,4204,9432,4233,10,1889,6185,8581,0,2104,7036,9432,10,8581,6184,1904,0,9432,7035,2119,10,6185,948,6184,0,7036,1163,7035,10,8582,3808,363,0,9433,4235,479,10,6186,8582,3825,0,7037,9433,5425,10,6189,1905,3808,0,7040,2120,4235,10,949,6189,8582,0,1164,7040,9433,10,3117,8583,3824,0,3544,9434,5426,10,1559,6187,8583,0,1774,7038,9434,10,8583,6186,1913,0,9434,7037,2715,10,6187,949,6186,0,7038,1164,7037,10,8584,3116,210,0,9435,3543,279,10,6188,8584,3810,0,7039,9435,4237,10,6187,1559,3116,0,7038,1774,3543,10,949,6187,8584,0,1164,7038,9435,10,3809,8585,3811,0,4236,9436,4238,10,1905,6189,8585,0,2120,7040,9436,10,8585,6188,1906,0,9436,7039,2121,10,6189,949,6188,0,7040,1164,7039,10,8586,3842,364,0,9437,4269,480,10,6190,8586,3826,0,7041,9437,4253,10,6193,1922,3842,0,7044,2137,4269,10,950,6193,8586,0,1165,7044,9437,10,3159,8587,3827,0,3586,9438,4254,10,1580,6191,8587,0,1795,7042,9438,10,8587,6190,1914,0,9438,7041,2129,10,6191,950,6190,0,7042,1165,7041,10,8588,3158,218,0,9439,3585,295,10,6192,8588,2768,0,7043,9439,3195,10,6191,1580,3158,0,7042,1795,3585,10,950,6191,8588,0,1165,7042,9439,10,3843,8589,2769,0,4270,9440,3196,10,1922,6193,8589,0,2137,7044,9440,10,8589,6192,1385,0,9440,7043,1600,10,6193,950,6192,0,7044,1165,7043,10,8590,3844,365,0,9441,4271,482,10,6194,8590,2769,0,7045,9441,3196,10,6197,1923,3844,0,7048,2138,4271,10,951,6197,8590,0,1166,7048,9441,10,3165,8591,2768,0,3592,9442,3195,10,1583,6195,8591,0,1798,7046,9442,10,8591,6194,1385,0,9442,7045,1600,10,6195,951,6194,0,7046,1166,7045,10,8592,3164,142,0,9443,3591,209,10,6196,8592,2770,0,7047,9443,3197,10,6195,1583,3164,0,7046,1798,3591,10,951,6195,8592,0,1166,7046,9443,10,3845,8593,2771,0,4272,9444,3198,10,1923,6197,8593,0,2138,7048,9444,10,8593,6196,1386,0,9444,7047,1601,10,6197,951,6196,0,7048,1166,7047,10,8594,3846,367,0,9445,4273,485,10,6198,8594,3832,0,7049,9445,4259,10,6201,1924,3846,0,7052,2139,4273,10,952,6201,8594,0,1167,7052,9445,10,3473,8595,3833,0,3900,9446,4260,10,1737,6199,8595,0,1952,7050,9446,10,8595,6198,1917,0,9446,7049,2132,10,6199,952,6198,0,7050,1167,7049,10,8596,3472,194,0,9447,3899,263,10,6200,8596,3827,0,7051,9447,5427,10,6199,1737,3472,0,7050,1952,3899,10,952,6199,8596,0,1167,7050,9447,10,3847,8597,3826,0,4274,9448,5428,10,1924,6201,8597,0,2139,7052,9448,10,8597,6200,1914,0,9448,7051,2716,10,6201,952,6200,0,7052,1167,7051,10,8598,3848,368,0,9449,4275,486,10,6202,8598,3834,0,7053,9449,4261,10,6205,1925,3848,0,7056,2140,4275,10,953,6205,8598,0,1168,7056,9449,10,3176,8599,3835,0,3603,9450,4262,10,1589,6203,8599,0,1804,7054,9450,10,8599,6202,1918,0,9450,7053,2133,10,6203,953,6202,0,7054,1168,7053,10,8600,3177,223,0,9451,3604,301,10,6204,8600,3833,0,7055,9451,4260,10,6203,1589,3177,0,7054,1804,3604,10,953,6203,8600,0,1168,7054,9451,10,3849,8601,3832,0,4276,9452,4259,10,1925,6205,8601,0,2140,7056,9452,10,8601,6204,1917,0,9452,7055,2132,10,6205,953,6204,0,7056,1168,7055,10,8602,3850,370,0,9453,4277,490,10,6206,8602,3838,0,7057,9453,4265,10,6209,1926,3850,0,7060,2141,4277,10,954,6209,8602,0,1169,7060,9453,10,3180,8603,3839,0,3607,9454,4266,10,1591,6207,8603,0,1806,7058,9454,10,8603,6206,1920,0,9454,7057,2135,10,6207,954,6206,0,7058,1169,7057,10,8604,3181,226,0,9455,3608,304,10,6208,8604,2776,0,7059,9455,3203,10,6207,1591,3181,0,7058,1806,3608,10,954,6207,8604,0,1169,7058,9455,10,3851,8605,2777,0,4278,9456,3204,10,1926,6209,8605,0,2141,7060,9456,10,8605,6208,1389,0,9456,7059,1604,10,6209,954,6208,0,7060,1169,7059,10,8606,3852,366,0,9457,4279,484,10,6210,8606,2771,0,7061,9457,5335,10,6213,1927,3852,0,7064,2142,4279,10,955,6213,8606,0,1170,7064,9457,10,2901,8607,2770,0,3328,9458,5336,10,1451,6211,8607,0,1666,7062,9458,10,8607,6210,1386,0,9458,7061,2670,10,6211,955,6210,0,7062,1170,7061,10,8608,2900,143,0,9459,3327,210,10,6212,8608,3839,0,7063,9459,4266,10,6211,1451,2900,0,7062,1666,3327,10,955,6211,8608,0,1170,7062,9459,10,3853,8609,3838,0,4280,9460,4265,10,1927,6213,8609,0,2142,7064,9460,10,8609,6212,1920,0,9460,7063,2135,10,6213,955,6212,0,7064,1170,7063,10,8610,3854,371,0,9461,4281,491,10,6214,8610,3840,0,7065,9461,4267,10,6217,1928,3854,0,7068,2143,4281,10,956,6217,8610,0,1171,7068,9461,10,3417,8611,3841,0,3844,9462,4268,10,1709,6215,8611,0,1924,7066,9462,10,8611,6214,1921,0,9462,7065,2136,10,6215,956,6214,0,7066,1171,7065,10,8612,3416,224,0,9463,3843,302,10,6216,8612,3835,0,7067,9463,5431,10,6215,1709,3416,0,7066,1924,3843,10,956,6215,8612,0,1171,7066,9463,10,3855,8613,3834,0,4282,9464,5432,10,1928,6217,8613,0,2143,7068,9464,10,8613,6216,1918,0,9464,7067,2718,10,6217,956,6216,0,7068,1171,7067,10,8614,3856,369,0,9465,4283,489,10,6218,8614,2777,0,7069,9465,5339,10,6221,1929,3856,0,7072,2144,4283,10,957,6221,8614,0,1172,7072,9465,10,3178,8615,2776,0,3605,9466,5340,10,1590,6219,8615,0,1805,7070,9466,10,8615,6218,1389,0,9466,7069,2672,10,6219,957,6218,0,7070,1172,7069,10,8616,3179,225,0,9467,3606,303,10,6220,8616,3841,0,7071,9467,4268,10,6219,1590,3179,0,7070,1805,3606,10,957,6219,8616,0,1172,7070,9467,10,3857,8617,3840,0,4284,9468,4267,10,1929,6221,8617,0,2144,7072,9468,10,8617,6220,1921,0,9468,7071,2136,10,6221,957,6220,0,7072,1172,7071,10,8618,3859,396,0,9469,4286,533,10,6222,8618,3860,0,7073,9469,4287,10,6225,1930,3859,0,7076,2145,4286,10,958,6225,8618,0,1173,7076,9469,10,4056,8619,3861,0,4483,9470,4288,10,2029,6223,8619,0,2244,7074,9470,10,8619,6222,1931,0,9470,7073,2146,10,6223,958,6222,0,7074,1173,7073,10,8620,4057,421,0,9471,4484,575,10,6224,8620,4042,0,7075,9471,4469,10,6223,2029,4057,0,7074,2244,4484,10,958,6223,8620,0,1173,7074,9471,10,3858,8621,4043,0,4285,9472,4470,10,1930,6225,8621,0,2145,7076,9472,10,8621,6224,2022,0,9472,7075,2237,10,6225,958,6224,0,7076,1173,7075,10,8622,3867,423,0,9473,4294,578,10,6226,8622,4060,0,7077,9473,4487,10,6229,1934,3867,0,7080,2149,4294,10,959,6229,8622,0,1174,7080,9473,10,4048,8623,4061,0,4475,9474,4488,10,2025,6227,8623,0,2240,7078,9474,10,8623,6226,2031,0,9474,7077,2246,10,6227,959,6226,0,7078,1174,7077,10,8624,4049,384,0,9475,4476,521,10,6228,8624,3864,0,7079,9475,4291,10,6227,2025,4049,0,7078,2240,4476,10,959,6227,8624,0,1174,7078,9475,10,3866,8625,3865,0,4293,9476,4292,10,1934,6229,8625,0,2149,7080,9476,10,8625,6228,1933,0,9476,7079,2148,10,6229,959,6228,0,7080,1174,7079,10,8626,3869,412,0,9477,4296,569,10,6230,8626,4045,0,7081,9477,5507,10,6233,1935,3869,0,7084,2150,4296,10,960,6233,8626,0,1175,7084,9477,10,4064,8627,4044,0,4491,9478,5508,10,2033,6231,8627,0,2248,7082,9478,10,8627,6230,2023,0,9478,7081,2756,10,6231,960,6230,0,7082,1175,7081,10,8628,4065,426,0,9479,4492,583,10,6232,8628,4052,0,7083,9479,4479,10,6231,2033,4065,0,7082,2248,4492,10,960,6231,8628,0,1175,7082,9479,10,3868,8629,4053,0,4295,9480,4480,10,1935,6233,8629,0,2150,7084,9480,10,8629,6232,2027,0,9480,7083,2242,10,6233,960,6232,0,7084,1175,7083,10,8630,3879,373,0,9481,4306,498,10,6234,8630,3872,0,7085,9481,4299,10,6237,1940,3879,0,7088,2155,4306,10,961,6237,8630,0,1176,7088,9481,10,3874,8631,3873,0,4301,9482,4300,10,1938,6235,8631,0,2153,7086,9482,10,8631,6234,1937,0,9482,7085,2152,10,6235,961,6234,0,7086,1176,7085,10,8632,3875,386,0,9483,4302,523,10,6236,8632,3876,0,7087,9483,4303,10,6235,1938,3875,0,7086,2153,4302,10,961,6235,8632,0,1176,7086,9483,10,3878,8633,3877,0,4305,9484,4304,10,1940,6237,8633,0,2155,7088,9484,10,8633,6236,1939,0,9484,7087,2154,10,6237,961,6236,0,7088,1176,7087,10,8634,3874,397,0,9485,4301,558,10,6238,8634,3880,0,7089,9485,4307,10,6241,1938,3874,0,7092,2153,4301,10,962,6241,8634,0,1177,7092,9485,10,3882,8635,3881,0,4309,9486,4308,10,1942,6239,8635,0,2157,7090,9486,10,8635,6238,1941,0,9486,7089,2156,10,6239,962,6238,0,7090,1177,7089,10,8636,3883,403,0,9487,4310,540,10,6240,8636,3884,0,7091,9487,4311,10,6239,1942,3883,0,7090,2157,4310,10,962,6239,8636,0,1177,7090,9487,10,3875,8637,3885,0,4302,9488,4312,10,1938,6241,8637,0,2153,7092,9488,10,8637,6240,1943,0,9488,7091,2158,10,6241,962,6240,0,7092,1177,7091,10,8638,3891,374,0,9489,4318,501,10,6242,8638,3886,0,7093,9489,4313,10,6245,1946,3891,0,7096,2161,4318,10,963,6245,8638,0,1178,7096,9489,10,3888,8639,3887,0,4315,9490,4314,10,1945,6243,8639,0,2160,7094,9490,10,8639,6242,1944,0,9490,7093,2159,10,6243,963,6242,0,7094,1178,7093,10,8640,3889,386,0,9491,4316,523,10,6244,8640,3885,0,7095,9491,4312,10,6243,1945,3889,0,7094,2160,4316,10,963,6243,8640,0,1178,7094,9491,10,3890,8641,3884,0,4317,9492,4311,10,1946,6245,8641,0,2161,7096,9492,10,8641,6244,1943,0,9492,7095,2158,10,6245,963,6244,0,7096,1178,7095,10,8642,3888,400,0,9493,4315,561,10,6246,8642,3892,0,7097,9493,4319,10,6249,1945,3888,0,7100,2160,4315,10,964,6249,8642,0,1179,7100,9493,10,3894,8643,3893,0,4321,9494,4320,10,1948,6247,8643,0,2163,7098,9494,10,8643,6246,1947,0,9494,7097,2162,10,6247,964,6246,0,7098,1179,7097,10,8644,3895,402,0,9495,4322,563,10,6248,8644,3877,0,7099,9495,4304,10,6247,1948,3895,0,7098,2163,4322,10,964,6247,8644,0,1179,7098,9495,10,3889,8645,3876,0,4316,9496,4303,10,1945,6249,8645,0,2160,7100,9496,10,8645,6248,1939,0,9496,7099,2154,10,6249,964,6248,0,7100,1179,7099,10,8646,3882,372,0,9497,5456,502,10,6250,8646,3896,0,7101,9497,4323,10,6253,1942,3882,0,7104,2730,5456,10,965,6253,8646,0,1180,7104,9497,10,3898,8647,3897,0,4325,9498,4324,10,1950,6251,8647,0,2165,7102,9498,10,8647,6250,1949,0,9498,7101,2164,10,6251,965,6250,0,7102,1180,7101,10,8648,3899,387,0,9499,4326,524,10,6252,8648,3900,0,7103,9499,4327,10,6251,1950,3899,0,7102,2165,4326,10,965,6251,8648,0,1180,7102,9499,10,3883,8649,3901,0,5455,9500,4328,10,1942,6253,8649,0,2730,7104,9500,10,8649,6252,1951,0,9500,7103,2166,10,6253,965,6252,0,7104,1180,7103,10,8650,3898,404,0,9501,4325,565,10,6254,8650,3902,0,7105,9501,4329,10,6257,1950,3898,0,7108,2165,4325,10,966,6257,8650,0,1181,7108,9501,10,3904,8651,3903,0,4331,9502,4330,10,1953,6255,8651,0,2168,7106,9502,10,8651,6254,1952,0,9502,7105,2167,10,6255,966,6254,0,7106,1181,7105,10,8652,3905,411,0,9503,4332,548,10,6256,8652,3906,0,7107,9503,4333,10,6255,1953,3905,0,7106,2168,4332,10,966,6255,8652,0,1181,7106,9503,10,3899,8653,3907,0,4326,9504,4334,10,1950,6257,8653,0,2165,7108,9504,10,8653,6256,1954,0,9504,7107,2169,10,6257,966,6256,0,7108,1181,7107,10,8654,3913,379,0,9505,4340,511,10,6258,8654,3908,0,7109,9505,4335,10,6261,1957,3913,0,7112,2172,4340,10,967,6261,8654,0,1182,7112,9505,10,3910,8655,3909,0,4337,9506,4336,10,1956,6259,8655,0,2171,7110,9506,10,8655,6258,1955,0,9506,7109,2170,10,6259,967,6258,0,7110,1182,7109,10,8656,3911,387,0,9507,4338,524,10,6260,8656,3907,0,7111,9507,4334,10,6259,1956,3911,0,7110,2171,4338,10,967,6259,8656,0,1182,7110,9507,10,3912,8657,3906,0,4339,9508,4333,10,1957,6261,8657,0,2172,7112,9508,10,8657,6260,1954,0,9508,7111,2169,10,6261,967,6260,0,7112,1182,7111,10,8658,3910,401,0,9509,4337,562,10,6262,8658,3914,0,7113,9509,4341,10,6265,1956,3910,0,7116,2171,4337,10,968,6265,8658,0,1183,7116,9509,10,3891,8659,3915,0,5459,9510,4342,10,1946,6263,8659,0,2732,7114,9510,10,8659,6262,1958,0,9510,7113,2173,10,6263,968,6262,0,7114,1183,7113,10,8660,3890,403,0,9511,5460,564,10,6264,8660,3901,0,7115,9511,4328,10,6263,1946,3890,0,7114,2732,5460,10,968,6263,8660,0,1183,7114,9511,10,3911,8661,3900,0,4338,9512,4327,10,1956,6265,8661,0,2171,7116,9512,10,8661,6264,1951,0,9512,7115,2166,10,6265,968,6264,0,7116,1183,7115,10,8662,3921,376,0,9513,4348,504,10,6266,8662,3903,0,7117,9513,5467,10,6269,1961,3921,0,7120,2176,4348,10,969,6269,8662,0,1184,7120,9513,10,3916,8663,3902,0,4343,9514,5468,10,1959,6267,8663,0,2174,7118,9514,10,8663,6266,1952,0,9514,7117,2736,10,6267,969,6266,0,7118,1184,7117,10,8664,3917,388,0,9515,4344,525,10,6268,8664,3918,0,7119,9515,4345,10,6267,1959,3917,0,7118,2174,4344,10,969,6267,8664,0,1184,7118,9515,10,3920,8665,3919,0,4347,9516,4346,10,1961,6269,8665,0,2176,7120,9516,10,8665,6268,1960,0,9516,7119,2175,10,6269,969,6268,0,7120,1184,7119,10,8666,3916,404,0,9517,4343,541,10,6270,8666,3897,0,7121,9517,5465,10,6273,1959,3916,0,7124,2174,4343,10,970,6273,8666,0,1185,7124,9517,10,3881,8667,3896,0,5453,9518,5466,10,1941,6271,8667,0,2729,7122,9518,10,8667,6270,1949,0,9518,7121,2735,10,6271,970,6270,0,7122,1185,7121,10,8668,3880,397,0,9519,5454,534,10,6272,8668,3922,0,7123,9519,4349,10,6271,1941,3880,0,7122,2729,5454,10,970,6271,8668,0,1185,7122,9519,10,3917,8669,3923,0,4344,9520,4350,10,1959,6273,8669,0,2174,7124,9520,10,8669,6272,1962,0,9520,7123,2177,10,6273,970,6272,0,7124,1185,7123,10,8670,3872,373,0,9521,5450,493,10,6274,8670,3924,0,7125,9521,4351,10,6277,1937,3872,0,7128,2727,5450,10,971,6277,8670,0,1186,7128,9521,10,3926,8671,3925,0,4353,9522,4352,10,1964,6275,8671,0,2179,7126,9522,10,8671,6274,1963,0,9522,7125,2178,10,6275,971,6274,0,7126,1186,7125,10,8672,3927,388,0,9523,4354,525,10,6276,8672,3923,0,7127,9523,4350,10,6275,1964,3927,0,7126,2179,4354,10,971,6275,8672,0,1186,7126,9523,10,3873,8673,3922,0,5449,9524,4349,10,1937,6277,8673,0,2727,7128,9524,10,8673,6276,1962,0,9524,7127,2177,10,6277,971,6276,0,7128,1186,7127,10,8674,3926,398,0,9525,4353,535,10,6278,8674,3928,0,7129,9525,4355,10,6281,1964,3926,0,7132,2179,4353,10,972,6281,8674,0,1187,7132,9525,10,3930,8675,3929,0,4357,9526,4356,10,1966,6279,8675,0,2181,7130,9526,10,8675,6278,1965,0,9526,7129,2180,10,6279,972,6278,0,7130,1187,7129,10,8676,3931,408,0,9527,4358,545,10,6280,8676,3919,0,7131,9527,4346,10,6279,1966,3931,0,7130,2181,4358,10,972,6279,8676,0,1187,7130,9527,10,3927,8677,3918,0,4354,9528,4345,10,1964,6281,8677,0,2179,7132,9528,10,8677,6280,1960,0,9528,7131,2175,10,6281,972,6280,0,7132,1187,7131,10,8678,3939,378,0,9529,4366,508,10,6282,8678,3932,0,7133,9529,4359,10,6285,1970,3939,0,7136,2185,4366,10,973,6285,8678,0,1188,7136,9529,10,3934,8679,3933,0,4361,9530,4360,10,1968,6283,8679,0,2183,7134,9530,10,8679,6282,1967,0,9530,7133,2182,10,6283,973,6282,0,7134,1188,7133,10,8680,3935,389,0,9531,4362,526,10,6284,8680,3936,0,7135,9531,4363,10,6283,1968,3935,0,7134,2183,4362,10,973,6283,8680,0,1188,7134,9531,10,3938,8681,3937,0,4365,9532,4364,10,1970,6285,8681,0,2185,7136,9532,10,8681,6284,1969,0,9532,7135,2184,10,6285,973,6284,0,7136,1188,7135,10,8682,3934,406,0,9533,4361,543,10,6286,8682,3940,0,7137,9533,4367,10,6289,1968,3934,0,7140,2183,4361,10,974,6289,8682,0,1189,7140,9533,10,3893,8683,3941,0,5461,9534,4368,10,1947,6287,8683,0,2733,7138,9534,10,8683,6286,1971,0,9534,7137,2186,10,6287,974,6286,0,7138,1189,7137,10,8684,3892,400,0,9535,5462,537,10,6288,8684,3942,0,7139,9535,4369,10,6287,1947,3892,0,7138,2733,5462,10,974,6287,8684,0,1189,7138,9535,10,3935,8685,3943,0,4362,9536,4370,10,1968,6289,8685,0,2183,7140,9536,10,8685,6288,1972,0,9536,7139,2187,10,6289,974,6288,0,7140,1189,7139,10,8686,3886,374,0,9537,5458,494,10,6290,8686,3915,0,7141,9537,5471,10,6293,1944,3886,0,7144,2731,5458,10,975,6293,8686,0,1190,7144,9537,10,3944,8687,3914,0,4371,9538,5472,10,1973,6291,8687,0,2188,7142,9538,10,8687,6290,1958,0,9538,7141,2738,10,6291,975,6290,0,7142,1190,7141,10,8688,3945,389,0,9539,4372,526,10,6292,8688,3943,0,7143,9539,4370,10,6291,1973,3945,0,7142,2188,4372,10,975,6291,8688,0,1190,7142,9539,10,3887,8689,3942,0,5457,9540,4369,10,1944,6293,8689,0,2731,7144,9540,10,8689,6292,1972,0,9540,7143,2187,10,6293,975,6292,0,7144,1190,7143,10,8690,3944,401,0,9541,4371,538,10,6294,8690,3909,0,7145,9541,5469,10,6297,1973,3944,0,7148,2188,4371,10,976,6297,8690,0,1191,7148,9541,10,3946,8691,3908,0,4373,9542,5470,10,1974,6295,8691,0,2189,7146,9542,10,8691,6294,1955,0,9542,7145,2737,10,6295,976,6294,0,7146,1191,7145,10,8692,3947,409,0,9543,4374,546,10,6296,8692,3937,0,7147,9543,4364,10,6295,1974,3947,0,7146,2189,4374,10,976,6295,8692,0,1191,7146,9543,10,3945,8693,3936,0,4372,9544,4363,10,1973,6297,8693,0,2188,7148,9544,10,8693,6296,1969,0,9544,7147,2184,10,6297,976,6296,0,7148,1191,7147,10,8694,3953,377,0,9545,4380,507,10,6298,8694,3929,0,7149,9545,5475,10,6301,1977,3953,0,7152,2192,4380,10,977,6301,8694,0,1192,7152,9545,10,3948,8695,3928,0,4375,9546,5476,10,1975,6299,8695,0,2190,7150,9546,10,8695,6298,1965,0,9546,7149,2740,10,6299,977,6298,0,7150,1192,7149,10,8696,3949,390,0,9547,4376,527,10,6300,8696,3950,0,7151,9547,4377,10,6299,1975,3949,0,7150,2190,4376,10,977,6299,8696,0,1192,7150,9547,10,3952,8697,3951,0,4379,9548,4378,10,1977,6301,8697,0,2192,7152,9548,10,8697,6300,1976,0,9548,7151,2191,10,6301,977,6300,0,7152,1192,7151,10,8698,3948,398,0,9549,4375,559,10,6302,8698,3925,0,7153,9549,5473,10,6305,1975,3948,0,7156,2190,4375,10,978,6305,8698,0,1193,7156,9549,10,3879,8699,3924,0,5451,9550,5474,10,1940,6303,8699,0,2728,7154,9550,10,8699,6302,1963,0,9550,7153,2739,10,6303,978,6302,0,7154,1193,7153,10,8700,3878,402,0,9551,5452,539,10,6304,8700,3954,0,7155,9551,4381,10,6303,1940,3878,0,7154,2728,5452,10,978,6303,8700,0,1193,7154,9551,10,3949,8701,3955,0,4376,9552,4382,10,1975,6305,8701,0,2190,7156,9552,10,8701,6304,1978,0,9552,7155,2193,10,6305,978,6304,0,7156,1193,7155,10,8702,3894,375,0,9553,5464,497,10,6306,8702,3941,0,7157,9553,5479,10,6309,1948,3894,0,7160,2734,5464,10,979,6309,8702,0,1194,7160,9553,10,3956,8703,3940,0,4383,9554,5480,10,1979,6307,8703,0,2194,7158,9554,10,8703,6306,1971,0,9554,7157,2742,10,6307,979,6306,0,7158,1194,7157,10,8704,3957,390,0,9555,4384,527,10,6308,8704,3955,0,7159,9555,4382,10,6307,1979,3957,0,7158,2194,4384,10,979,6307,8704,0,1194,7158,9555,10,3895,8705,3954,0,5463,9556,4381,10,1948,6309,8705,0,2734,7160,9556,10,8705,6308,1978,0,9556,7159,2193,10,6309,979,6308,0,7160,1194,7159,10,8706,3956,406,0,9557,4383,567,10,6310,8706,3933,0,7161,9557,5477,10,6313,1979,3956,0,7164,2194,4383,10,980,6313,8706,0,1195,7164,9557,10,3958,8707,3932,0,4385,9558,5478,10,1980,6311,8707,0,2195,7162,9558,10,8707,6310,1967,0,9558,7161,2741,10,6311,980,6310,0,7162,1195,7161,10,8708,3959,410,0,9559,4386,547,10,6312,8708,3951,0,7163,9559,4378,10,6311,1980,3959,0,7162,2195,4386,10,980,6311,8708,0,1195,7162,9559,10,3957,8709,3950,0,4384,9560,4377,10,1979,6313,8709,0,2194,7164,9560,10,8709,6312,1976,0,9560,7163,2191,10,6313,980,6312,0,7164,1195,7163,10,8710,3904,376,0,9561,4331,505,10,6314,8710,3960,0,7165,9561,4387,10,6317,1953,3904,0,7168,2168,4331,10,981,6317,8710,0,1196,7168,9561,10,3962,8711,3961,0,4389,9562,4388,10,1982,6315,8711,0,2197,7166,9562,10,8711,6314,1981,0,9562,7165,2196,10,6315,981,6314,0,7166,1196,7165,10,8712,3963,391,0,9563,4390,528,10,6316,8712,3964,0,7167,9563,4391,10,6315,1982,3963,0,7166,2197,4390,10,981,6315,8712,0,1196,7166,9563,10,3905,8713,3965,0,4332,9564,4392,10,1953,6317,8713,0,2168,7168,9564,10,8713,6316,1983,0,9564,7167,2198,10,6317,981,6316,0,7168,1196,7167,10,8714,3962,414,0,9565,4389,571,10,6318,8714,3966,0,7169,9565,4393,10,6321,1982,3962,0,7172,2197,4389,10,982,6321,8714,0,1197,7172,9565,10,3968,8715,3967,0,4395,9566,4394,10,1985,6319,8715,0,2200,7170,9566,10,8715,6318,1984,0,9566,7169,2199,10,6319,982,6318,0,7170,1197,7169,10,8716,3969,416,0,9567,4396,553,10,6320,8716,3970,0,7171,9567,4397,10,6319,1985,3969,0,7170,2200,4396,10,982,6319,8716,0,1197,7170,9567,10,3963,8717,3971,0,4390,9568,4398,10,1982,6321,8717,0,2197,7172,9568,10,8717,6320,1986,0,9568,7171,2201,10,6321,982,6320,0,7172,1197,7171,10,8718,3977,381,0,9569,4404,515,10,6322,8718,3972,0,7173,9569,4399,10,6325,1989,3977,0,7176,2204,4404,10,983,6325,8718,0,1198,7176,9569,10,3974,8719,3973,0,4401,9570,4400,10,1988,6323,8719,0,2203,7174,9570,10,8719,6322,1987,0,9570,7173,2202,10,6323,983,6322,0,7174,1198,7173,10,8720,3975,391,0,9571,4402,528,10,6324,8720,3971,0,7175,9571,4398,10,6323,1988,3975,0,7174,2203,4402,10,983,6323,8720,0,1198,7174,9571,10,3976,8721,3970,0,4403,9572,4397,10,1989,6325,8721,0,2204,7176,9572,10,8721,6324,1986,0,9572,7175,2201,10,6325,983,6324,0,7176,1198,7175,10,8722,3974,407,0,9573,4401,568,10,6326,8722,3978,0,7177,9573,4405,10,6329,1988,3974,0,7180,2203,4401,10,984,6329,8722,0,1199,7180,9573,10,3913,8723,3979,0,4340,9574,4406,10,1957,6327,8723,0,2172,7178,9574,10,8723,6326,1990,0,9574,7177,2205,10,6327,984,6326,0,7178,1199,7177,10,8724,3912,411,0,9575,4339,548,10,6328,8724,3965,0,7179,9575,4392,10,6327,1957,3912,0,7178,2172,4339,10,984,6327,8724,0,1199,7178,9575,10,3975,8725,3964,0,4402,9576,4391,10,1988,6329,8725,0,2203,7180,9576,10,8725,6328,1983,0,9576,7179,2198,10,6329,984,6328,0,7180,1199,7179,10,8726,3987,380,0,9577,4414,512,10,6330,8726,3984,0,7181,9577,4411,10,6333,1994,3987,0,7184,2209,4414,10,985,6333,8726,0,1200,7184,9577,10,4088,8727,3985,0,4515,9578,4412,10,2045,6331,8727,0,2260,7182,9578,10,8727,6330,1993,0,9578,7181,2208,10,6331,985,6330,0,7182,1200,7181,10,8728,4089,428,0,9579,4516,585,10,6332,8728,3983,0,7183,9579,4410,10,6331,2045,4089,0,7182,2260,4516,10,985,6331,8728,0,1200,7182,9579,10,3986,8729,3982,0,4413,9580,4409,10,1994,6333,8729,0,2209,7184,9580,10,8729,6332,1992,0,9580,7183,2207,10,6333,985,6332,0,7184,1200,7183,10,8730,3995,381,0,9581,4422,514,10,6334,8730,3992,0,7185,9581,4419,10,6337,1998,3995,0,7188,2213,4422,10,986,6337,8730,0,1201,7188,9581,10,4090,8731,3993,0,4517,9582,4420,10,2046,6335,8731,0,2261,7186,9582,10,8731,6334,1997,0,9582,7185,2212,10,6335,986,6334,0,7186,1201,7185,10,8732,4091,430,0,9583,4518,588,10,6336,8732,3991,0,7187,9583,4418,10,6335,2046,4091,0,7186,2261,4518,10,986,6335,8732,0,1201,7186,9583,10,3994,8733,3990,0,4421,9584,4417,10,1998,6337,8733,0,2213,7188,9584,10,8733,6336,1996,0,9584,7187,2211,10,6337,986,6336,0,7188,1201,7187,10,8734,4001,383,0,9585,4428,519,10,6338,8734,4085,0,7189,9585,5519,10,6341,2001,4001,0,7192,2216,4428,10,987,6341,8734,0,1202,7192,9585,10,4092,8735,4084,0,4519,9586,5520,10,2047,6339,8735,0,2262,7190,9586,10,8735,6338,2043,0,9586,7189,2762,10,6339,987,6338,0,7190,1202,7189,10,8736,4093,432,0,9587,4520,591,10,6340,8736,3999,0,7191,9587,4426,10,6339,2047,4093,0,7190,2262,4520,10,987,6339,8736,0,1202,7190,9587,10,4000,8737,3998,0,4427,9588,4425,10,2001,6341,8737,0,2216,7192,9588,10,8737,6340,2000,0,9588,7191,2215,10,6341,987,6340,0,7192,1202,7191,10,8738,4007,413,0,9589,4434,570,10,6342,8738,4051,0,7193,9589,5511,10,6345,2004,4007,0,7196,2219,4434,10,988,6345,8738,0,1203,7196,9589,10,4070,8739,4050,0,4497,9590,5512,10,2036,6343,8739,0,2251,7194,9590,10,8739,6342,2026,0,9590,7193,2758,10,6343,988,6342,0,7194,1203,7193,10,8740,4071,427,0,9591,4498,584,10,6344,8740,4005,0,7195,9591,4432,10,6343,2036,4071,0,7194,2251,4498,10,988,6343,8740,0,1203,7194,9591,10,4006,8741,4004,0,4433,9592,4431,10,2004,6345,8741,0,2219,7196,9592,10,8741,6344,2003,0,9592,7195,2218,10,6345,988,6344,0,7196,1203,7195,10,8742,3968,382,0,9593,4395,517,10,6346,8742,4083,0,7197,9593,5517,10,6349,1985,3968,0,7200,2200,4395,10,989,6349,8742,0,1204,7200,9593,10,4094,8743,4082,0,4521,9594,5518,10,2048,6347,8743,0,2263,7198,9594,10,8743,6346,2042,0,9594,7197,2761,10,6347,989,6346,0,7198,1204,7197,10,8744,4095,435,0,9595,4522,596,10,6348,8744,4086,0,7199,9595,4513,10,6347,2048,4095,0,7198,2263,4522,10,989,6347,8744,0,1204,7198,9595,10,3969,8745,4087,0,4396,9596,4514,10,1985,6349,8745,0,2200,7200,9596,10,8745,6348,2044,0,9596,7199,2259,10,6349,989,6348,0,7200,1204,7199,10,8746,3980,382,0,9597,4407,516,10,6350,8746,3967,0,7201,9597,5483,10,6353,1991,3980,0,7204,2206,4407,10,990,6353,8746,0,1205,7204,9597,10,4008,8747,3966,0,4435,9598,5484,10,2005,6351,8747,0,2220,7202,9598,10,8747,6350,1984,0,9598,7201,2744,10,6351,990,6350,0,7202,1205,7201,10,8748,4009,393,0,9599,4436,530,10,6352,8748,4010,0,7203,9599,4437,10,6351,2005,4009,0,7202,2220,4436,10,990,6351,8748,0,1205,7202,9599,10,3981,8749,4011,0,4408,9600,4438,10,1991,6353,8749,0,2206,7204,9600,10,8749,6352,2006,0,9600,7203,2221,10,6353,990,6352,0,7204,1205,7203,10,8750,4008,414,0,9601,4435,551,10,6354,8750,3961,0,7205,9601,5481,10,6357,2005,4008,0,7208,2220,4435,10,991,6357,8750,0,1206,7208,9601,10,3921,8751,3960,0,4348,9602,5482,10,1961,6355,8751,0,2176,7206,9602,10,8751,6354,1981,0,9602,7205,2743,10,6355,991,6354,0,7206,1206,7205,10,8752,3920,408,0,9603,4347,545,10,6356,8752,4012,0,7207,9603,4439,10,6355,1961,3920,0,7206,2176,4347,10,991,6355,8752,0,1206,7206,9603,10,4009,8753,4013,0,4436,9604,4440,10,2005,6357,8753,0,2220,7208,9604,10,8753,6356,2007,0,9604,7207,2222,10,6357,991,6356,0,7208,1206,7207,10,8754,3930,377,0,9605,4357,506,10,6358,8754,4014,0,7209,9605,4441,10,6361,1966,3930,0,7212,2181,4357,10,992,6361,8754,0,1207,7212,9605,10,4016,8755,4015,0,4443,9606,4442,10,2009,6359,8755,0,2224,7210,9606,10,8755,6358,2008,0,9606,7209,2223,10,6359,992,6358,0,7210,1207,7209,10,8756,4017,393,0,9607,4444,530,10,6360,8756,4013,0,7211,9607,4440,10,6359,2009,4017,0,7210,2224,4444,10,992,6359,8756,0,1207,7210,9607,10,3931,8757,4012,0,4358,9608,4439,10,1966,6361,8757,0,2181,7212,9608,10,8757,6360,2007,0,9608,7211,2222,10,6361,992,6360,0,7212,1207,7211,10,8758,4016,405,0,9609,4443,542,10,6362,8758,4018,0,7213,9609,4445,10,6365,2009,4016,0,7216,2224,4443,10,993,6365,8758,0,1208,7216,9609,10,3987,8759,4019,0,4414,9610,4446,10,1994,6363,8759,0,2209,7214,9610,10,8759,6362,2010,0,9610,7213,2225,10,6363,993,6362,0,7214,1208,7213,10,8760,3986,417,0,9611,4413,554,10,6364,8760,4011,0,7215,9611,4438,10,6363,1994,3986,0,7214,2209,4413,10,993,6363,8760,0,1208,7214,9611,10,4017,8761,4010,0,4444,9612,4437,10,2009,6365,8761,0,2224,7216,9612,10,8761,6364,2006,0,9612,7215,2221,10,6365,993,6364,0,7216,1208,7215,10,8762,3988,383,0,9613,4415,518,10,6366,8762,4020,0,7217,9613,4447,10,6369,1995,3988,0,7220,2210,4415,10,994,6369,8762,0,1209,7220,9613,10,4022,8763,4021,0,4449,9614,4448,10,2012,6367,8763,0,2227,7218,9614,10,8763,6366,2011,0,9614,7217,2226,10,6367,994,6366,0,7218,1209,7217,10,8764,4023,394,0,9615,4450,531,10,6368,8764,4024,0,7219,9615,4451,10,6367,2012,4023,0,7218,2227,4450,10,994,6367,8764,0,1209,7218,9615,10,3989,8765,4025,0,4416,9616,4452,10,1995,6369,8765,0,2210,7220,9616,10,8765,6368,2013,0,9616,7219,2228,10,6369,994,6368,0,7220,1209,7219,10,8766,4022,415,0,9617,4449,552,10,6370,8766,4026,0,7221,9617,4453,10,6373,2012,4022,0,7224,2227,4449,10,995,6373,8766,0,1210,7224,9617,10,3939,8767,4027,0,4366,9618,4454,10,1970,6371,8767,0,2185,7222,9618,10,8767,6370,2014,0,9618,7221,2229,10,6371,995,6370,0,7222,1210,7221,10,8768,3938,409,0,9619,4365,546,10,6372,8768,4028,0,7223,9619,4455,10,6371,1970,3938,0,7222,2185,4365,10,995,6371,8768,0,1210,7222,9619,10,4023,8769,4029,0,4450,9620,4456,10,2012,6373,8769,0,2227,7224,9620,10,8769,6372,2015,0,9620,7223,2230,10,6373,995,6372,0,7224,1210,7223,10,8770,3946,379,0,9621,4373,510,10,6374,8770,3979,0,7225,9621,5487,10,6377,1974,3946,0,7228,2189,4373,10,996,6377,8770,0,1211,7228,9621,10,4030,8771,3978,0,4457,9622,5488,10,2016,6375,8771,0,2231,7226,9622,10,8771,6374,1990,0,9622,7225,2746,10,6375,996,6374,0,7226,1211,7225,10,8772,4031,394,0,9623,4458,531,10,6376,8772,4029,0,7227,9623,4456,10,6375,2016,4031,0,7226,2231,4458,10,996,6375,8772,0,1211,7226,9623,10,3947,8773,4028,0,4374,9624,4455,10,1974,6377,8773,0,2189,7228,9624,10,8773,6376,2015,0,9624,7227,2230,10,6377,996,6376,0,7228,1211,7227,10,8774,4030,407,0,9625,4457,544,10,6378,8774,3973,0,7229,9625,5485,10,6381,2016,4030,0,7232,2231,4457,10,997,6381,8774,0,1212,7232,9625,10,3995,8775,3972,0,4422,9626,5486,10,1998,6379,8775,0,2213,7230,9626,10,8775,6378,1987,0,9626,7229,2745,10,6379,997,6378,0,7230,1212,7229,10,8776,3994,418,0,9627,4421,555,10,6380,8776,4025,0,7231,9627,4452,10,6379,1998,3994,0,7230,2213,4421,10,997,6379,8776,0,1212,7230,9627,10,4031,8777,4024,0,4458,9628,4451,10,2016,6381,8777,0,2231,7232,9628,10,8777,6380,2013,0,9628,7231,2228,10,6381,997,6380,0,7232,1212,7231,10,8778,3996,380,0,9629,4423,513,10,6382,8778,4019,0,7233,9629,5499,10,6385,1999,3996,0,7236,2214,4423,10,998,6385,8778,0,1213,7236,9629,10,4032,8779,4018,0,4459,9630,5500,10,2017,6383,8779,0,2232,7234,9630,10,8779,6382,2010,0,9630,7233,2752,10,6383,998,6382,0,7234,1213,7233,10,8780,4033,395,0,9631,4460,532,10,6384,8780,4034,0,7235,9631,4461,10,6383,2017,4033,0,7234,2232,4460,10,998,6383,8780,0,1213,7234,9631,10,3997,8781,4035,0,4424,9632,4462,10,1999,6385,8781,0,2214,7236,9632,10,8781,6384,2018,0,9632,7235,2233,10,6385,998,6384,0,7236,1213,7235,10,8782,4032,405,0,9633,4459,566,10,6386,8782,4015,0,7237,9633,5497,10,6389,2017,4032,0,7240,2232,4459,10,999,6389,8782,0,1214,7240,9633,10,3953,8783,4014,0,4380,9634,5498,10,1977,6387,8783,0,2192,7238,9634,10,8783,6386,2008,0,9634,7237,2751,10,6387,999,6386,0,7238,1214,7237,10,8784,3952,410,0,9635,4379,547,10,6388,8784,4036,0,7239,9635,4463,10,6387,1977,3952,0,7238,2192,4379,10,999,6387,8784,0,1214,7238,9635,10,4033,8785,4037,0,4460,9636,4464,10,2017,6389,8785,0,2232,7240,9636,10,8785,6388,2019,0,9636,7239,2234,10,6389,999,6388,0,7240,1214,7239,10,8786,3958,378,0,9637,4385,509,10,6390,8786,4027,0,7241,9637,5503,10,6393,1980,3958,0,7244,2195,4385,10,1000,6393,8786,0,1215,7244,9637,10,4038,8787,4026,0,4465,9638,5504,10,2020,6391,8787,0,2235,7242,9638,10,8787,6390,2014,0,9638,7241,2754,10,6391,1000,6390,0,7242,1215,7241,10,8788,4039,395,0,9639,4466,532,10,6392,8788,4037,0,7243,9639,4464,10,6391,2020,4039,0,7242,2235,4466,10,1000,6391,8788,0,1215,7242,9639,10,3959,8789,4036,0,4386,9640,4463,10,1980,6393,8789,0,2195,7244,9640,10,8789,6392,2019,0,9640,7243,2234,10,6393,1000,6392,0,7244,1215,7243,10,8790,4038,415,0,9641,4465,572,10,6394,8790,4021,0,7245,9641,5501,10,6397,2020,4038,0,7248,2235,4465,10,1001,6397,8790,0,1216,7248,9641,10,4001,8791,4020,0,4428,9642,5502,10,2001,6395,8791,0,2216,7246,9642,10,8791,6394,2011,0,9642,7245,2753,10,6395,1001,6394,0,7246,1216,7245,10,8792,4000,419,0,9643,4427,556,10,6396,8792,4035,0,7247,9643,4462,10,6395,2001,4000,0,7246,2216,4427,10,1001,6395,8792,0,1216,7246,9643,10,4039,8793,4034,0,4466,9644,4461,10,2020,6397,8793,0,2235,7248,9644,10,8793,6396,2018,0,9644,7247,2233,10,6397,1001,6396,0,7248,1216,7247,10,8794,4056,420,0,9645,4483,573,10,6398,8794,4040,0,7249,9645,4467,10,6401,2029,4056,0,7252,2244,4483,10,1002,6401,8794,0,1217,7252,9645,10,4096,8795,4041,0,4523,9646,4468,10,2049,6399,8795,0,2264,7250,9646,10,8795,6398,2021,0,9646,7249,2236,10,6399,1002,6398,0,7250,1217,7249,10,8796,4097,428,0,9647,4524,585,10,6400,8796,4072,0,7251,9647,4499,10,6399,2049,4097,0,7250,2264,4524,10,1002,6399,8796,0,1217,7250,9647,10,4057,8797,4073,0,4484,9648,4500,10,2029,6401,8797,0,2244,7252,9648,10,8797,6400,2037,0,9648,7251,2252,10,6401,1002,6400,0,7252,1217,7251,10,8798,4058,422,0,9649,4485,576,10,6402,8798,4044,0,7253,9649,4471,10,6405,2030,4058,0,7256,2245,4485,10,1003,6405,8798,0,1218,7256,9649,10,3265,8799,4045,0,5361,9650,4472,10,1633,6403,8799,0,2683,7254,9650,10,8799,6402,2023,0,9650,7253,2238,10,6403,1003,6402,0,7254,1218,7253,10,8800,3264,169,0,9651,5362,520,10,6404,8800,4043,0,7255,9651,4470,10,6403,1633,3264,0,7254,2683,5362,10,1003,6403,8800,0,1218,7254,9651,10,4059,8801,4042,0,4486,9652,4469,10,2030,6405,8801,0,2245,7256,9652,10,8801,6404,2022,0,9652,7255,2237,10,6405,1003,6404,0,7256,1218,7255,10,8802,4060,423,0,9653,4487,578,10,6406,8802,4046,0,7257,9653,4473,10,6409,2031,4060,0,7260,2246,4487,10,1004,6409,8802,0,1219,7260,9653,10,4098,8803,4047,0,4525,9654,4474,10,2050,6407,8803,0,2265,7258,9654,10,8803,6406,2024,0,9654,7257,2239,10,6407,1004,6406,0,7258,1219,7257,10,8804,4099,430,0,9655,4526,588,10,6408,8804,4076,0,7259,9655,4503,10,6407,2050,4099,0,7258,2265,4526,10,1004,6407,8804,0,1219,7258,9655,10,4061,8805,4077,0,4488,9656,4504,10,2031,6409,8805,0,2246,7260,9656,10,8805,6408,2039,0,9656,7259,2254,10,6409,1004,6408,0,7260,1219,7259,10,8806,4062,425,0,9657,4489,581,10,6410,8806,4050,0,7261,9657,4477,10,6413,2032,4062,0,7264,2247,4489,10,1005,6413,8806,0,1220,7264,9657,10,3862,8807,4051,0,4289,9658,4478,10,1932,6411,8807,0,2147,7262,9658,10,8807,6410,2026,0,9658,7261,2241,10,6411,1005,6410,0,7262,1220,7261,10,8808,3863,384,0,9659,4290,521,10,6412,8808,4049,0,7263,9659,4476,10,6411,1932,3863,0,7262,2147,4290,10,1005,6411,8808,0,1220,7262,9659,10,4063,8809,4048,0,4490,9660,4475,10,2032,6413,8809,0,2247,7264,9660,10,8809,6412,2025,0,9660,7263,2240,10,6413,1005,6412,0,7264,1220,7263,10,8810,4064,422,0,9661,4491,577,10,6414,8810,4075,0,7265,9661,5513,10,6417,2033,4064,0,7268,2248,4491,10,1006,6417,8810,0,1221,7268,9661,10,4100,8811,4074,0,4527,9662,5514,10,2051,6415,8811,0,2266,7266,9662,10,8811,6414,2038,0,9662,7265,2759,10,6415,1006,6414,0,7266,1221,7265,10,8812,4101,432,0,9663,4528,591,10,6416,8812,4080,0,7267,9663,4507,10,6415,2051,4101,0,7266,2266,4528,10,1006,6415,8812,0,1221,7266,9663,10,4065,8813,4081,0,4492,9664,4508,10,2033,6417,8813,0,2248,7268,9664,10,8813,6416,2041,0,9664,7267,2256,10,6417,1006,6416,0,7268,1221,7267,10,8814,4066,423,0,9665,4493,579,10,6418,8814,3867,0,7269,9665,5443,10,6421,2034,4066,0,7272,2249,4493,10,1007,6421,8814,0,1222,7272,9665,10,3870,8815,3866,0,4297,9666,5444,10,1936,6419,8815,0,2151,7270,9666,10,8815,6418,1934,0,9666,7269,2724,10,6419,1007,6418,0,7270,1222,7269,10,8816,3871,385,0,9667,4298,522,10,6420,8816,4053,0,7271,9667,4480,10,6419,1936,3871,0,7270,2151,4298,10,1007,6419,8816,0,1222,7270,9667,10,4067,8817,4052,0,4494,9668,4479,10,2034,6421,8817,0,2249,7272,9668,10,8817,6420,2027,0,9668,7271,2242,10,6421,1007,6420,0,7272,1222,7271,10,8818,4068,420,0,9669,4495,574,10,6422,8818,3861,0,7273,9669,5437,10,6425,2035,4068,0,7276,2250,4495,10,1008,6425,8818,0,1223,7276,9669,10,4002,8819,3860,0,4429,9670,5438,10,2002,6423,8819,0,2217,7274,9670,10,8819,6422,1931,0,9670,7273,2721,10,6423,1008,6422,0,7274,1223,7273,10,8820,4003,392,0,9671,4430,529,10,6424,8820,4004,0,7275,9671,4431,10,6423,2002,4003,0,7274,2217,4430,10,1008,6423,8820,0,1223,7274,9671,10,4069,8821,4005,0,4496,9672,4432,10,2035,6425,8821,0,2250,7276,9672,10,8821,6424,2003,0,9672,7275,2218,10,6425,1008,6424,0,7276,1223,7275,10,8822,4070,425,0,9673,4497,582,10,6426,8822,4079,0,7277,9673,5515,10,6429,2036,4070,0,7280,2251,4497,10,1009,6429,8822,0,1224,7280,9673,10,4102,8823,4078,0,4529,9674,5516,10,2052,6427,8823,0,2267,7278,9674,10,8823,6426,2040,0,9674,7277,2760,10,6427,1009,6426,0,7278,1224,7277,10,8824,4103,435,0,9675,4530,596,10,6428,8824,4055,0,7279,9675,4482,10,6427,2052,4103,0,7278,2267,4530,10,1009,6427,8824,0,1224,7278,9675,10,4071,8825,4054,0,4498,9676,4481,10,2036,6429,8825,0,2251,7280,9676,10,8825,6428,2028,0,9676,7279,2243,10,6429,1009,6428,0,7280,1224,7279,10,8826,4088,429,0,9677,4515,586,10,6430,8826,4074,0,7281,9677,4501,10,6433,2045,4088,0,7284,2260,4515,10,1010,6433,8826,0,1225,7284,9677,10,4058,8827,4075,0,4485,9678,4502,10,2030,6431,8827,0,2245,7282,9678,10,8827,6430,2038,0,9678,7281,2253,10,6431,1010,6430,0,7282,1225,7281,10,8828,4059,421,0,9679,4486,575,10,6432,8828,4073,0,7283,9679,4500,10,6431,2030,4059,0,7282,2245,4486,10,1010,6431,8828,0,1225,7282,9679,10,4089,8829,4072,0,4516,9680,4499,10,2045,6433,8829,0,2260,7284,9680,10,8829,6432,2037,0,9680,7283,2252,10,6433,1010,6432,0,7284,1225,7283,10,8830,4090,431,0,9681,4517,589,10,6434,8830,4078,0,7285,9681,4505,10,6437,2046,4090,0,7288,2261,4517,10,1011,6437,8830,0,1226,7288,9681,10,4062,8831,4079,0,4489,9682,4506,10,2032,6435,8831,0,2247,7286,9682,10,8831,6434,2040,0,9682,7285,2255,10,6435,1011,6434,0,7286,1226,7285,10,8832,4063,424,0,9683,4490,580,10,6436,8832,4077,0,7287,9683,4504,10,6435,2032,4063,0,7286,2247,4490,10,1011,6435,8832,0,1226,7286,9683,10,4091,8833,4076,0,4518,9684,4503,10,2046,6437,8833,0,2261,7288,9684,10,8833,6436,2039,0,9684,7287,2254,10,6437,1011,6436,0,7288,1226,7287,10,8834,4092,434,0,9685,4519,595,10,6438,8834,4047,0,7289,9685,5509,10,6441,2047,4092,0,7292,2262,4519,10,1012,6441,8834,0,1227,7292,9685,10,4066,8835,4046,0,4493,9686,5510,10,2034,6439,8835,0,2249,7290,9686,10,8835,6438,2024,0,9686,7289,2757,10,6439,1012,6438,0,7290,1227,7289,10,8836,4067,426,0,9687,4494,583,10,6440,8836,4081,0,7291,9687,4508,10,6439,2034,4067,0,7290,2249,4494,10,1012,6439,8836,0,1227,7290,9687,10,4093,8837,4080,0,4520,9688,4507,10,2047,6441,8837,0,2262,7292,9688,10,8837,6440,2041,0,9688,7291,2256,10,6441,1012,6440,0,7292,1227,7291,10,8838,4094,433,0,9689,4521,593,10,6442,8838,4041,0,7293,9689,5505,10,6445,2048,4094,0,7296,2263,4521,10,1013,6445,8838,0,1228,7296,9689,10,4068,8839,4040,0,4495,9690,5506,10,2035,6443,8839,0,2250,7294,9690,10,8839,6442,2021,0,9690,7293,2755,10,6443,1013,6442,0,7294,1228,7293,10,8840,4069,427,0,9691,4496,584,10,6444,8840,4054,0,7295,9691,4481,10,6443,2035,4069,0,7294,2250,4496,10,1013,6443,8840,0,1228,7294,9691,10,4095,8841,4055,0,4522,9692,4482,10,2048,6445,8841,0,2263,7296,9692,10,8841,6444,2028,0,9692,7295,2243,10,6445,1013,6444,0,7296,1228,7295,10,8842,4096,433,0,9693,4523,592,10,6446,8842,4082,0,7297,9693,4509,10,6449,2049,4096,0,7300,2264,4523,10,1014,6449,8842,0,1229,7300,9693,10,3980,8843,4083,0,4407,9694,4510,10,1991,6447,8843,0,2206,7298,9694,10,8843,6446,2042,0,9694,7297,2257,10,6447,1014,6446,0,7298,1229,7297,10,8844,3981,417,0,9695,4408,554,10,6448,8844,3982,0,7299,9695,4409,10,6447,1991,3981,0,7298,2206,4408,10,1014,6447,8844,0,1229,7298,9695,10,4097,8845,3983,0,4524,9696,4410,10,2049,6449,8845,0,2264,7300,9696,10,8845,6448,1992,0,9696,7299,2207,10,6449,1014,6448,0,7300,1229,7299,10,8846,4098,434,0,9697,4525,594,10,6450,8846,4084,0,7301,9697,4511,10,6453,2050,4098,0,7304,2265,4525,10,1015,6453,8846,0,1230,7304,9697,10,3988,8847,4085,0,4415,9698,4512,10,1995,6451,8847,0,2210,7302,9698,10,8847,6450,2043,0,9698,7301,2258,10,6451,1015,6450,0,7302,1230,7301,10,8848,3989,418,0,9699,4416,555,10,6452,8848,3990,0,7303,9699,4417,10,6451,1995,3989,0,7302,2210,4416,10,1015,6451,8848,0,1230,7302,9699,10,4099,8849,3991,0,4526,9700,4418,10,2050,6453,8849,0,2265,7304,9700,10,8849,6452,1996,0,9700,7303,2211,10,6453,1015,6452,0,7304,1230,7303,10,8850,4100,429,0,9701,4527,587,10,6454,8850,3985,0,7305,9701,5489,10,6457,2051,4100,0,7308,2266,4527,10,1016,6457,8850,0,1231,7308,9701,10,3996,8851,3984,0,4423,9702,5490,10,1999,6455,8851,0,2214,7306,9702,10,8851,6454,1993,0,9702,7305,2747,10,6455,1016,6454,0,7306,1231,7305,10,8852,3997,419,0,9703,4424,556,10,6456,8852,3998,0,7307,9703,4425,10,6455,1999,3997,0,7306,2214,4424,10,1016,6455,8852,0,1231,7306,9703,10,4101,8853,3999,0,4528,9704,4426,10,2051,6457,8853,0,2266,7308,9704,10,8853,6456,2000,0,9704,7307,2215,10,6457,1016,6456,0,7308,1231,7307,10,8854,4102,431,0,9705,4529,590,10,6458,8854,3993,0,7309,9705,5491,10,6461,2052,4102,0,7312,2267,4529,10,1017,6461,8854,0,1232,7312,9705,10,3977,8855,3992,0,4404,9706,5492,10,1989,6459,8855,0,2204,7310,9706,10,8855,6458,1997,0,9706,7309,2748,10,6459,1017,6458,0,7310,1232,7309,10,8856,3976,416,0,9707,4403,553,10,6460,8856,4087,0,7311,9707,4514,10,6459,1989,3976,0,7310,2204,4403,10,1017,6459,8856,0,1232,7310,9707,10,4103,8857,4086,0,4530,9708,4513,10,2052,6461,8857,0,2267,7312,9708,10,8857,6460,2044,0,9708,7311,2259,10,6461,1017,6460,0,7312,1232,7311,10,8858,4111,437,0,9709,4538,603,10,6462,8858,4104,0,7313,9709,4531,10,6465,2056,4111,0,7316,2271,4538,10,1018,6465,8858,0,1233,7316,9709,10,4106,8859,4105,0,4533,9710,4532,10,2054,6463,8859,0,2269,7314,9710,10,8859,6462,2053,0,9710,7313,2268,10,6463,1018,6462,0,7314,1233,7313,10,8860,4107,448,0,9711,4534,625,10,6464,8860,4108,0,7315,9711,4535,10,6463,2054,4107,0,7314,2269,4534,10,1018,6463,8860,0,1233,7314,9711,10,4110,8861,4109,0,4537,9712,4536,10,2056,6465,8861,0,2271,7316,9712,10,8861,6464,2055,0,9712,7315,2270,10,6465,1018,6464,0,7316,1233,7315,10,8862,4106,461,0,9713,4533,662,10,6466,8862,4112,0,7317,9713,4539,10,6469,2054,4106,0,7320,2269,4533,10,1019,6469,8862,0,1234,7320,9713,10,4114,8863,4113,0,4541,9714,4540,10,2058,6467,8863,0,2273,7318,9714,10,8863,6466,2057,0,9714,7317,2272,10,6467,1019,6466,0,7318,1234,7317,10,8864,4115,466,0,9715,4542,643,10,6468,8864,4116,0,7319,9715,4543,10,6467,2058,4115,0,7318,2273,4542,10,1019,6467,8864,0,1234,7318,9715,10,4107,8865,4117,0,4534,9716,4544,10,2054,6469,8865,0,2269,7320,9716,10,8865,6468,2059,0,9716,7319,2274,10,6469,1019,6468,0,7320,1234,7319,10,8866,4123,438,0,9717,4550,606,10,6470,8866,4118,0,7321,9717,4545,10,6473,2062,4123,0,7324,2277,4550,10,1020,6473,8866,0,1235,7324,9717,10,4120,8867,4119,0,4547,9718,4546,10,2061,6471,8867,0,2276,7322,9718,10,8867,6470,2060,0,9718,7321,2275,10,6471,1020,6470,0,7322,1235,7321,10,8868,4121,448,0,9719,4548,625,10,6472,8868,4117,0,7323,9719,4544,10,6471,2061,4121,0,7322,2276,4548,10,1020,6471,8868,0,1235,7322,9719,10,4122,8869,4116,0,4549,9720,4543,10,2062,6473,8869,0,2277,7324,9720,10,8869,6472,2059,0,9720,7323,2274,10,6473,1020,6472,0,7324,1235,7323,10,8870,4120,463,0,9721,4547,664,10,6474,8870,4124,0,7325,9721,4551,10,6477,2061,4120,0,7328,2276,4547,10,1021,6477,8870,0,1236,7328,9721,10,4126,8871,4125,0,4553,9722,4552,10,2064,6475,8871,0,2279,7326,9722,10,8871,6474,2063,0,9722,7325,2278,10,6475,1021,6474,0,7326,1236,7325,10,8872,4127,465,0,9723,4554,666,10,6476,8872,4109,0,7327,9723,4536,10,6475,2064,4127,0,7326,2279,4554,10,1021,6475,8872,0,1236,7326,9723,10,4121,8873,4108,0,4548,9724,4535,10,2061,6477,8873,0,2276,7328,9724,10,8873,6476,2055,0,9724,7327,2270,10,6477,1021,6476,0,7328,1236,7327,10,8874,4114,436,0,9725,5528,607,10,6478,8874,4128,0,7329,9725,4555,10,6481,2058,4114,0,7332,2766,5528,10,1022,6481,8874,0,1237,7332,9725,10,4130,8875,4129,0,4557,9726,4556,10,2066,6479,8875,0,2281,7330,9726,10,8875,6478,2065,0,9726,7329,2280,10,6479,1022,6478,0,7330,1237,7329,10,8876,4131,449,0,9727,4558,626,10,6480,8876,4132,0,7331,9727,4559,10,6479,2066,4131,0,7330,2281,4558,10,1022,6479,8876,0,1237,7330,9727,10,4115,8877,4133,0,5527,9728,4560,10,2058,6481,8877,0,2766,7332,9728,10,8877,6480,2067,0,9728,7331,2282,10,6481,1022,6480,0,7332,1237,7331,10,8878,4130,467,0,9729,4557,668,10,6482,8878,4134,0,7333,9729,4561,10,6485,2066,4130,0,7336,2281,4557,10,1023,6485,8878,0,1238,7336,9729,10,4136,8879,4135,0,4563,9730,4562,10,2069,6483,8879,0,2284,7334,9730,10,8879,6482,2068,0,9730,7333,2283,10,6483,1023,6482,0,7334,1238,7333,10,8880,4137,474,0,9731,4564,651,10,6484,8880,4138,0,7335,9731,4565,10,6483,2069,4137,0,7334,2284,4564,10,1023,6483,8880,0,1238,7334,9731,10,4131,8881,4139,0,4558,9732,4566,10,2066,6485,8881,0,2281,7336,9732,10,8881,6484,2070,0,9732,7335,2285,10,6485,1023,6484,0,7336,1238,7335,10,8882,4145,443,0,9733,4572,616,10,6486,8882,4140,0,7337,9733,4567,10,6489,2073,4145,0,7340,2288,4572,10,1024,6489,8882,0,1239,7340,9733,10,4142,8883,4141,0,4569,9734,4568,10,2072,6487,8883,0,2287,7338,9734,10,8883,6486,2071,0,9734,7337,2286,10,6487,1024,6486,0,7338,1239,7337,10,8884,4143,449,0,9735,4570,626,10,6488,8884,4139,0,7339,9735,4566,10,6487,2072,4143,0,7338,2287,4570,10,1024,6487,8884,0,1239,7338,9735,10,4144,8885,4138,0,4571,9736,4565,10,2073,6489,8885,0,2288,7340,9736,10,8885,6488,2070,0,9736,7339,2285,10,6489,1024,6488,0,7340,1239,7339,10,8886,4142,464,0,9737,4569,665,10,6490,8886,4146,0,7341,9737,4573,10,6493,2072,4142,0,7344,2287,4569,10,1025,6493,8886,0,1240,7344,9737,10,4123,8887,4147,0,5531,9738,4574,10,2062,6491,8887,0,2768,7342,9738,10,8887,6490,2074,0,9738,7341,2289,10,6491,1025,6490,0,7342,1240,7341,10,8888,4122,466,0,9739,5532,667,10,6492,8888,4133,0,7343,9739,4560,10,6491,2062,4122,0,7342,2768,5532,10,1025,6491,8888,0,1240,7342,9739,10,4143,8889,4132,0,4570,9740,4559,10,2072,6493,8889,0,2287,7344,9740,10,8889,6492,2067,0,9740,7343,2282,10,6493,1025,6492,0,7344,1240,7343,10,8890,4153,440,0,9741,4580,609,10,6494,8890,4135,0,7345,9741,5539,10,6497,2077,4153,0,7348,2292,4580,10,1026,6497,8890,0,1241,7348,9741,10,4148,8891,4134,0,4575,9742,5540,10,2075,6495,8891,0,2290,7346,9742,10,8891,6494,2068,0,9742,7345,2772,10,6495,1026,6494,0,7346,1241,7345,10,8892,4149,450,0,9743,4576,627,10,6496,8892,4150,0,7347,9743,4577,10,6495,2075,4149,0,7346,2290,4576,10,1026,6495,8892,0,1241,7346,9743,10,4152,8893,4151,0,4579,9744,4578,10,2077,6497,8893,0,2292,7348,9744,10,8893,6496,2076,0,9744,7347,2291,10,6497,1026,6496,0,7348,1241,7347,10,8894,4148,467,0,9745,4575,644,10,6498,8894,4129,0,7349,9745,5537,10,6501,2075,4148,0,7352,2290,4575,10,1027,6501,8894,0,1242,7352,9745,10,4113,8895,4128,0,5525,9746,5538,10,2057,6499,8895,0,2765,7350,9746,10,8895,6498,2065,0,9746,7349,2771,10,6499,1027,6498,0,7350,1242,7349,10,8896,4112,461,0,9747,5526,638,10,6500,8896,4154,0,7351,9747,4581,10,6499,2057,4112,0,7350,2765,5526,10,1027,6499,8896,0,1242,7350,9747,10,4149,8897,4155,0,4576,9748,4582,10,2075,6501,8897,0,2290,7352,9748,10,8897,6500,2078,0,9748,7351,2293,10,6501,1027,6500,0,7352,1242,7351,10,8898,4104,437,0,9749,5522,598,10,6502,8898,4156,0,7353,9749,4583,10,6505,2053,4104,0,7356,2763,5522,10,1028,6505,8898,0,1243,7356,9749,10,4158,8899,4157,0,4585,9750,4584,10,2080,6503,8899,0,2295,7354,9750,10,8899,6502,2079,0,9750,7353,2294,10,6503,1028,6502,0,7354,1243,7353,10,8900,4159,450,0,9751,4586,627,10,6504,8900,4155,0,7355,9751,4582,10,6503,2080,4159,0,7354,2295,4586,10,1028,6503,8900,0,1243,7354,9751,10,4105,8901,4154,0,5521,9752,4581,10,2053,6505,8901,0,2763,7356,9752,10,8901,6504,2078,0,9752,7355,2293,10,6505,1028,6504,0,7356,1243,7355,10,8902,4158,462,0,9753,4585,639,10,6506,8902,4160,0,7357,9753,4587,10,6509,2080,4158,0,7360,2295,4585,10,1029,6509,8902,0,1244,7360,9753,10,4162,8903,4161,0,4589,9754,4588,10,2082,6507,8903,0,2297,7358,9754,10,8903,6506,2081,0,9754,7357,2296,10,6507,1029,6506,0,7358,1244,7357,10,8904,4163,471,0,9755,4590,648,10,6508,8904,4151,0,7359,9755,4578,10,6507,2082,4163,0,7358,2297,4590,10,1029,6507,8904,0,1244,7358,9755,10,4159,8905,4150,0,4586,9756,4577,10,2080,6509,8905,0,2295,7360,9756,10,8905,6508,2076,0,9756,7359,2291,10,6509,1029,6508,0,7360,1244,7359,10,8906,4171,442,0,9757,4598,613,10,6510,8906,4164,0,7361,9757,4591,10,6513,2086,4171,0,7364,2301,4598,10,1030,6513,8906,0,1245,7364,9757,10,4166,8907,4165,0,4593,9758,4592,10,2084,6511,8907,0,2299,7362,9758,10,8907,6510,2083,0,9758,7361,2298,10,6511,1030,6510,0,7362,1245,7361,10,8908,4167,451,0,9759,4594,628,10,6512,8908,4168,0,7363,9759,4595,10,6511,2084,4167,0,7362,2299,4594,10,1030,6511,8908,0,1245,7362,9759,10,4170,8909,4169,0,4597,9760,4596,10,2086,6513,8909,0,2301,7364,9760,10,8909,6512,2085,0,9760,7363,2300,10,6513,1030,6512,0,7364,1245,7363,10,8910,4166,469,0,9761,4593,646,10,6514,8910,4172,0,7365,9761,4599,10,6517,2084,4166,0,7368,2299,4593,10,1031,6517,8910,0,1246,7368,9761,10,4125,8911,4173,0,5533,9762,4600,10,2063,6515,8911,0,2769,7366,9762,10,8911,6514,2087,0,9762,7365,2302,10,6515,1031,6514,0,7366,1246,7365,10,8912,4124,463,0,9763,5534,640,10,6516,8912,4174,0,7367,9763,4601,10,6515,2063,4124,0,7366,2769,5534,10,1031,6515,8912,0,1246,7366,9763,10,4167,8913,4175,0,4594,9764,4602,10,2084,6517,8913,0,2299,7368,9764,10,8913,6516,2088,0,9764,7367,2303,10,6517,1031,6516,0,7368,1246,7367,10,8914,4118,438,0,9765,5530,599,10,6518,8914,4147,0,7369,9765,5543,10,6521,2060,4118,0,7372,2767,5530,10,1032,6521,8914,0,1247,7372,9765,10,4176,8915,4146,0,4603,9766,5544,10,2089,6519,8915,0,2304,7370,9766,10,8915,6518,2074,0,9766,7369,2774,10,6519,1032,6518,0,7370,1247,7369,10,8916,4177,451,0,9767,4604,628,10,6520,8916,4175,0,7371,9767,4602,10,6519,2089,4177,0,7370,2304,4604,10,1032,6519,8916,0,1247,7370,9767,10,4119,8917,4174,0,5529,9768,4601,10,2060,6521,8917,0,2767,7372,9768,10,8917,6520,2088,0,9768,7371,2303,10,6521,1032,6520,0,7372,1247,7371,10,8918,4176,464,0,9769,4603,641,10,6522,8918,4141,0,7373,9769,5541,10,6525,2089,4176,0,7376,2304,4603,10,1033,6525,8918,0,1248,7376,9769,10,4178,8919,4140,0,4605,9770,5542,10,2090,6523,8919,0,2305,7374,9770,10,8919,6522,2071,0,9770,7373,2773,10,6523,1033,6522,0,7374,1248,7373,10,8920,4179,472,0,9771,4606,649,10,6524,8920,4169,0,7375,9771,4596,10,6523,2090,4179,0,7374,2305,4606,10,1033,6523,8920,0,1248,7374,9771,10,4177,8921,4168,0,4604,9772,4595,10,2089,6525,8921,0,2304,7376,9772,10,8921,6524,2085,0,9772,7375,2300,10,6525,1033,6524,0,7376,1248,7375,10,8922,4185,441,0,9773,4612,612,10,6526,8922,4161,0,7377,9773,5547,10,6529,2093,4185,0,7380,2308,4612,10,1034,6529,8922,0,1249,7380,9773,10,4180,8923,4160,0,4607,9774,5548,10,2091,6527,8923,0,2306,7378,9774,10,8923,6526,2081,0,9774,7377,2776,10,6527,1034,6526,0,7378,1249,7377,10,8924,4181,452,0,9775,4608,629,10,6528,8924,4182,0,7379,9775,4609,10,6527,2091,4181,0,7378,2306,4608,10,1034,6527,8924,0,1249,7378,9775,10,4184,8925,4183,0,4611,9776,4610,10,2093,6529,8925,0,2308,7380,9776,10,8925,6528,2092,0,9776,7379,2307,10,6529,1034,6528,0,7380,1249,7379,10,8926,4180,462,0,9777,4607,663,10,6530,8926,4157,0,7381,9777,5545,10,6533,2091,4180,0,7384,2306,4607,10,1035,6533,8926,0,1250,7384,9777,10,4111,8927,4156,0,5523,9778,5546,10,2056,6531,8927,0,2764,7382,9778,10,8927,6530,2079,0,9778,7381,2775,10,6531,1035,6530,0,7382,1250,7381,10,8928,4110,465,0,9779,5524,642,10,6532,8928,4186,0,7383,9779,4613,10,6531,2056,4110,0,7382,2764,5524,10,1035,6531,8928,0,1250,7382,9779,10,4181,8929,4187,0,4608,9780,4614,10,2091,6533,8929,0,2306,7384,9780,10,8929,6532,2094,0,9780,7383,2309,10,6533,1035,6532,0,7384,1250,7383,10,8930,4126,439,0,9781,5536,602,10,6534,8930,4173,0,7385,9781,5551,10,6537,2064,4126,0,7388,2770,5536,10,1036,6537,8930,0,1251,7388,9781,10,4188,8931,4172,0,4615,9782,5552,10,2095,6535,8931,0,2310,7386,9782,10,8931,6534,2087,0,9782,7385,2778,10,6535,1036,6534,0,7386,1251,7385,10,8932,4189,452,0,9783,4616,629,10,6536,8932,4187,0,7387,9783,4614,10,6535,2095,4189,0,7386,2310,4616,10,1036,6535,8932,0,1251,7386,9783,10,4127,8933,4186,0,5535,9784,4613,10,2064,6537,8933,0,2770,7388,9784,10,8933,6536,2094,0,9784,7387,2309,10,6537,1036,6536,0,7388,1251,7387,10,8934,4188,469,0,9785,4615,670,10,6538,8934,4165,0,7389,9785,5549,10,6541,2095,4188,0,7392,2310,4615,10,1037,6541,8934,0,1252,7392,9785,10,4190,8935,4164,0,4617,9786,5550,10,2096,6539,8935,0,2311,7390,9786,10,8935,6538,2083,0,9786,7389,2777,10,6539,1037,6538,0,7390,1252,7389,10,8936,4191,473,0,9787,4618,650,10,6540,8936,4183,0,7391,9787,4610,10,6539,2096,4191,0,7390,2311,4618,10,1037,6539,8936,0,1252,7390,9787,10,4189,8937,4182,0,4616,9788,4609,10,2095,6541,8937,0,2310,7392,9788,10,8937,6540,2092,0,9788,7391,2307,10,6541,1037,6540,0,7392,1252,7391,10,8938,4136,440,0,9789,4563,610,10,6542,8938,4192,0,7393,9789,4619,10,6545,2069,4136,0,7396,2284,4563,10,1038,6545,8938,0,1253,7396,9789,10,4194,8939,4193,0,4621,9790,4620,10,2098,6543,8939,0,2313,7394,9790,10,8939,6542,2097,0,9790,7393,2312,10,6543,1038,6542,0,7394,1253,7393,10,8940,4195,453,0,9791,4622,630,10,6544,8940,4196,0,7395,9791,4623,10,6543,2098,4195,0,7394,2313,4622,10,1038,6543,8940,0,1253,7394,9791,10,4137,8941,4197,0,4564,9792,4624,10,2069,6545,8941,0,2284,7396,9792,10,8941,6544,2099,0,9792,7395,2314,10,6545,1038,6544,0,7396,1253,7395,10,8942,4194,479,0,9793,4621,676,10,6546,8942,4198,0,7397,9793,4625,10,6549,2098,4194,0,7400,2313,4621,10,1039,6549,8942,0,1254,7400,9793,10,4200,8943,4199,0,4627,9794,4626,10,2101,6547,8943,0,2316,7398,9794,10,8943,6546,2100,0,9794,7397,2315,10,6547,1039,6546,0,7398,1254,7397,10,8944,4201,481,0,9795,4628,658,10,6548,8944,4202,0,7399,9795,4629,10,6547,2101,4201,0,7398,2316,4628,10,1039,6547,8944,0,1254,7398,9795,10,4195,8945,4203,0,4622,9796,4630,10,2098,6549,8945,0,2313,7400,9796,10,8945,6548,2102,0,9796,7399,2317,10,6549,1039,6548,0,7400,1254,7399,10,8946,4209,445,0,9797,4636,620,10,6550,8946,4204,0,7401,9797,4631,10,6553,2105,4209,0,7404,2320,4636,10,1040,6553,8946,0,1255,7404,9797,10,4206,8947,4205,0,4633,9798,4632,10,2104,6551,8947,0,2319,7402,9798,10,8947,6550,2103,0,9798,7401,2318,10,6551,1040,6550,0,7402,1255,7401,10,8948,4207,453,0,9799,4634,630,10,6552,8948,4203,0,7403,9799,4630,10,6551,2104,4207,0,7402,2319,4634,10,1040,6551,8948,0,1255,7402,9799,10,4208,8949,4202,0,4635,9800,4629,10,2105,6553,8949,0,2320,7404,9800,10,8949,6552,2102,0,9800,7403,2317,10,6553,1040,6552,0,7404,1255,7403,10,8950,4206,470,0,9801,4633,671,10,6554,8950,4210,0,7405,9801,4637,10,6557,2104,4206,0,7408,2319,4633,10,1041,6557,8950,0,1256,7408,9801,10,4145,8951,4211,0,4572,9802,4638,10,2073,6555,8951,0,2288,7406,9802,10,8951,6554,2106,0,9802,7405,2321,10,6555,1041,6554,0,7406,1256,7405,10,8952,4144,474,0,9803,4571,651,10,6556,8952,4197,0,7407,9803,4624,10,6555,2073,4144,0,7406,2288,4571,10,1041,6555,8952,0,1256,7406,9803,10,4207,8953,4196,0,4634,9804,4623,10,2104,6557,8953,0,2319,7408,9804,10,8953,6556,2099,0,9804,7407,2314,10,6557,1041,6556,0,7408,1256,7407,10,8954,4213,475,0,9805,4640,652,10,6558,8954,4214,0,7409,9805,4641,10,6561,2107,4213,0,7412,2322,4640,10,1042,6561,8954,0,1257,7412,9805,10,4368,8955,4215,0,4795,9806,4642,10,2185,6559,8955,0,2400,7410,9806,10,8955,6558,2108,0,9806,7409,2323,10,6559,1042,6558,0,7410,1257,7409,10,8956,4369,504,0,9807,4796,707,10,6560,8956,4358,0,7411,9807,4785,10,6559,2185,4369,0,7410,2400,4796,10,1042,6559,8956,0,1257,7410,9807,10,4212,8957,4359,0,4639,9808,4786,10,2107,6561,8957,0,2322,7412,9808,10,8957,6560,2180,0,9808,7411,2395,10,6561,1042,6560,0,7412,1257,7411,10,8958,4225,444,0,9809,4652,617,10,6562,8958,4220,0,7413,9809,4647,10,6565,2113,4225,0,7416,2328,4652,10,1043,6565,8958,0,1258,7416,9809,10,4336,8959,4221,0,4763,9810,4648,10,2169,6563,8959,0,2384,7414,9810,10,8959,6562,2111,0,9810,7413,2326,10,6563,1043,6562,0,7414,1258,7413,10,8960,4337,493,0,9811,4764,690,10,6564,8960,4219,0,7415,9811,4646,10,6563,2169,4337,0,7414,2384,4764,10,1043,6563,8960,0,1258,7414,9811,10,4224,8961,4218,0,4651,9812,4645,10,2113,6565,8961,0,2328,7416,9812,10,8961,6564,2110,0,9812,7415,2325,10,6565,1043,6564,0,7416,1258,7415,10,8962,4227,476,0,9813,4654,653,10,6566,8962,4228,0,7417,9813,4655,10,6569,2114,4227,0,7420,2329,4654,10,1044,6569,8962,0,1259,7420,9813,10,4370,8963,4229,0,4797,9814,4656,10,2186,6567,8963,0,2401,7418,9814,10,8963,6566,2115,0,9814,7417,2330,10,6567,1044,6566,0,7418,1259,7417,10,8964,4371,506,0,9815,4798,710,10,6568,8964,4362,0,7419,9815,4789,10,6567,2186,4371,0,7418,2401,4798,10,1044,6567,8964,0,1259,7418,9815,10,4226,8965,4363,0,4653,9816,4790,10,2114,6569,8965,0,2329,7420,9816,10,8965,6568,2182,0,9816,7419,2397,10,6569,1044,6568,0,7420,1259,7419,10,8966,4239,445,0,9817,4666,619,10,6570,8966,4234,0,7421,9817,4661,10,6573,2120,4239,0,7424,2335,4666,10,1045,6573,8966,0,1260,7424,9817,10,4338,8967,4235,0,4765,9818,4662,10,2170,6571,8967,0,2385,7422,9818,10,8967,6570,2118,0,9818,7421,2333,10,6571,1045,6570,0,7422,1260,7421,10,8968,4339,495,0,9819,4766,693,10,6572,8968,4233,0,7423,9819,4660,10,6571,2170,4339,0,7422,2385,4766,10,1045,6571,8968,0,1260,7422,9819,10,4238,8969,4232,0,4665,9820,4659,10,2120,6573,8969,0,2335,7424,9820,10,8969,6572,2117,0,9820,7423,2332,10,6573,1045,6572,0,7424,1260,7423,10,8970,4241,477,0,9821,4668,674,10,6574,8970,4361,0,7425,9821,5597,10,6577,2121,4241,0,7428,2336,4668,10,1046,6577,8970,0,1261,7428,9821,10,4372,8971,4360,0,4799,9822,5598,10,2187,6575,8971,0,2402,7426,9822,10,8971,6574,2181,0,9822,7425,2801,10,6575,1046,6574,0,7426,1261,7425,10,8972,4373,508,0,9823,4800,713,10,6576,8972,4366,0,7427,9823,4793,10,6575,2187,4373,0,7426,2402,4800,10,1046,6575,8972,0,1261,7426,9823,10,4240,8973,4367,0,4667,9824,4794,10,2121,6577,8973,0,2336,7428,9824,10,8973,6576,2184,0,9824,7427,2399,10,6577,1046,6576,0,7428,1261,7427,10,8974,4249,447,0,9825,4676,624,10,6578,8974,4333,0,7429,9825,5591,10,6581,2125,4249,0,7432,2340,4676,10,1047,6581,8974,0,1262,7432,9825,10,4340,8975,4332,0,4767,9826,5592,10,2171,6579,8975,0,2386,7430,9826,10,8975,6578,2167,0,9826,7429,2798,10,6579,1047,6578,0,7430,1262,7429,10,8976,4341,497,0,9827,4768,696,10,6580,8976,4245,0,7431,9827,4672,10,6579,2171,4341,0,7430,2386,4768,10,1047,6579,8976,0,1262,7430,9827,10,4248,8977,4244,0,4675,9828,4671,10,2125,6581,8977,0,2340,7432,9828,10,8977,6580,2123,0,9828,7431,2338,10,6581,1047,6580,0,7432,1262,7431,10,8978,4200,446,0,9829,4627,622,10,6582,8978,4331,0,7433,9829,5589,10,6585,2101,4200,0,7436,2316,4627,10,1048,6585,8978,0,1263,7436,9829,10,4342,8979,4330,0,4769,9830,5590,10,2172,6583,8979,0,2387,7434,9830,10,8979,6582,2166,0,9830,7433,2797,10,6583,1048,6582,0,7434,1263,7433,10,8980,4343,500,0,9831,4770,701,10,6584,8980,4334,0,7435,9831,4761,10,6583,2172,4343,0,7434,2387,4770,10,1048,6583,8980,0,1263,7434,9831,10,4201,8981,4335,0,4628,9832,4762,10,2101,6585,8981,0,2316,7436,9832,10,8981,6584,2168,0,9832,7435,2383,10,6585,1048,6584,0,7436,1263,7435,10,8982,4255,478,0,9833,4682,675,10,6586,8982,4365,0,7437,9833,5599,10,6589,2128,4255,0,7440,2343,4682,10,1049,6589,8982,0,1264,7440,9833,10,4374,8983,4364,0,4801,9834,5600,10,2188,6587,8983,0,2403,7438,9834,10,8983,6586,2183,0,9834,7437,2802,10,6587,1049,6586,0,7438,1264,7437,10,8984,4375,503,0,9835,4802,706,10,6588,8984,4253,0,7439,9835,4680,10,6587,2188,4375,0,7438,2403,4802,10,1049,6587,8984,0,1264,7438,9835,10,4254,8985,4252,0,4681,9836,4679,10,2128,6589,8985,0,2343,7440,9836,10,8985,6588,2127,0,9836,7439,2342,10,6589,1049,6588,0,7440,1264,7439,10,8986,4216,446,0,9837,4643,621,10,6590,8986,4199,0,7441,9837,5555,10,6593,2109,4216,0,7444,2324,4643,10,1050,6593,8986,0,1265,7444,9837,10,4256,8987,4198,0,4683,9838,5556,10,2129,6591,8987,0,2344,7442,9838,10,8987,6590,2100,0,9838,7441,2780,10,6591,1050,6590,0,7442,1265,7441,10,8988,4257,458,0,9839,4684,635,10,6592,8988,4258,0,7443,9839,4685,10,6591,2129,4257,0,7442,2344,4684,10,1050,6591,8988,0,1265,7442,9839,10,4217,8989,4259,0,4644,9840,4686,10,2109,6593,8989,0,2324,7444,9840,10,8989,6592,2130,0,9840,7443,2345,10,6593,1050,6592,0,7444,1265,7443,10,8990,4256,479,0,9841,4683,656,10,6594,8990,4193,0,7445,9841,5553,10,6597,2129,4256,0,7448,2344,4683,10,1051,6597,8990,0,1266,7448,9841,10,4153,8991,4192,0,4580,9842,5554,10,2077,6595,8991,0,2292,7446,9842,10,8991,6594,2097,0,9842,7445,2779,10,6595,1051,6594,0,7446,1266,7445,10,8992,4152,471,0,9843,4579,648,10,6596,8992,4260,0,7447,9843,4687,10,6595,2077,4152,0,7446,2292,4579,10,1051,6595,8992,0,1266,7446,9843,10,4257,8993,4261,0,4684,9844,4688,10,2129,6597,8993,0,2344,7448,9844,10,8993,6596,2131,0,9844,7447,2346,10,6597,1051,6596,0,7448,1266,7447,10,8994,4162,441,0,9845,4589,611,10,6598,8994,4262,0,7449,9845,4689,10,6601,2082,4162,0,7452,2297,4589,10,1052,6601,8994,0,1267,7452,9845,10,4264,8995,4263,0,4691,9846,4690,10,2133,6599,8995,0,2348,7450,9846,10,8995,6598,2132,0,9846,7449,2347,10,6599,1052,6598,0,7450,1267,7449,10,8996,4265,458,0,9847,4692,635,10,6600,8996,4261,0,7451,9847,4688,10,6599,2133,4265,0,7450,2348,4692,10,1052,6599,8996,0,1267,7450,9847,10,4163,8997,4260,0,4590,9848,4687,10,2082,6601,8997,0,2297,7452,9848,10,8997,6600,2131,0,9848,7451,2346,10,6601,1052,6600,0,7452,1267,7451,10,8998,4264,468,0,9849,4691,645,10,6602,8998,4266,0,7453,9849,4693,10,6605,2133,4264,0,7456,2348,4691,10,1053,6605,8998,0,1268,7456,9849,10,4225,8999,4267,0,4652,9850,4694,10,2113,6603,8999,0,2328,7454,9850,10,8999,6602,2134,0,9850,7453,2349,10,6603,1053,6602,0,7454,1268,7453,10,9000,4224,482,0,9851,4651,659,10,6604,9000,4259,0,7455,9851,4686,10,6603,2113,4224,0,7454,2328,4651,10,1053,6603,9000,0,1268,7454,9851,10,4265,9001,4258,0,4692,9852,4685,10,2133,6605,9001,0,2348,7456,9852,10,9001,6604,2130,0,9852,7455,2345,10,6605,1053,6604,0,7456,1268,7455,10,9002,4230,447,0,9853,4657,623,10,6606,9002,4268,0,7457,9853,4695,10,6609,2116,4230,0,7460,2331,4657,10,1054,6609,9002,0,1269,7460,9853,10,4270,9003,4269,0,4697,9854,4696,10,2136,6607,9003,0,2351,7458,9854,10,9003,6606,2135,0,9854,7457,2350,10,6607,1054,6606,0,7458,1269,7457,10,9004,4271,459,0,9855,4698,636,10,6608,9004,4272,0,7459,9855,4699,10,6607,2136,4271,0,7458,2351,4698,10,1054,6607,9004,0,1269,7458,9855,10,4231,9005,4273,0,4658,9856,4700,10,2116,6609,9005,0,2331,7460,9856,10,9005,6608,2137,0,9856,7459,2352,10,6609,1054,6608,0,7460,1269,7459,10,9006,4270,480,0,9857,4697,657,10,6610,9006,4274,0,7461,9857,4701,10,6613,2136,4270,0,7464,2351,4697,10,1055,6613,9006,0,1270,7464,9857,10,4171,9007,4275,0,4598,9858,4702,10,2086,6611,9007,0,2301,7462,9858,10,9007,6610,2138,0,9858,7461,2353,10,6611,1055,6610,0,7462,1270,7461,10,9008,4170,472,0,9859,4597,649,10,6612,9008,4276,0,7463,9859,4703,10,6611,2086,4170,0,7462,2301,4597,10,1055,6611,9008,0,1270,7462,9859,10,4271,9009,4277,0,4698,9860,4704,10,2136,6613,9009,0,2351,7464,9860,10,9009,6612,2139,0,9860,7463,2354,10,6613,1055,6612,0,7464,1270,7463,10,9010,4178,443,0,9861,4605,615,10,6614,9010,4211,0,7465,9861,5559,10,6617,2090,4178,0,7468,2305,4605,10,1056,6617,9010,0,1271,7468,9861,10,4278,9011,4210,0,4705,9862,5560,10,2140,6615,9011,0,2355,7466,9862,10,9011,6614,2106,0,9862,7465,2782,10,6615,1056,6614,0,7466,1271,7465,10,9012,4279,459,0,9863,4706,636,10,6616,9012,4277,0,7467,9863,4704,10,6615,2140,4279,0,7466,2355,4706,10,1056,6615,9012,0,1271,7466,9863,10,4179,9013,4276,0,4606,9864,4703,10,2090,6617,9013,0,2305,7468,9864,10,9013,6616,2139,0,9864,7467,2354,10,6617,1056,6616,0,7468,1271,7467,10,9014,4278,470,0,9865,4705,647,10,6618,9014,4205,0,7469,9865,5557,10,6621,2140,4278,0,7472,2355,4705,10,1057,6621,9014,0,1272,7472,9865,10,4239,9015,4204,0,4666,9866,5558,10,2120,6619,9015,0,2335,7470,9866,10,9015,6618,2103,0,9866,7469,2781,10,6619,1057,6618,0,7470,1272,7469,10,9016,4238,483,0,9867,4665,660,10,6620,9016,4273,0,7471,9867,4700,10,6619,2120,4238,0,7470,2335,4665,10,1057,6619,9016,0,1272,7470,9867,10,4279,9017,4272,0,4706,9868,4699,10,2140,6621,9017,0,2355,7472,9868,10,9017,6620,2137,0,9868,7471,2352,10,6621,1057,6620,0,7472,1272,7471,10,9018,4242,444,0,9869,4669,618,10,6622,9018,4267,0,7473,9869,5571,10,6625,2122,4242,0,7476,2337,4669,10,1058,6625,9018,0,1273,7476,9869,10,4280,9019,4266,0,4707,9870,5572,10,2141,6623,9019,0,2356,7474,9870,10,9019,6622,2134,0,9870,7473,2788,10,6623,1058,6622,0,7474,1273,7473,10,9020,4281,460,0,9871,4708,637,10,6624,9020,4282,0,7475,9871,4709,10,6623,2141,4281,0,7474,2356,4708,10,1058,6623,9020,0,1273,7474,9871,10,4243,9021,4283,0,4670,9872,4710,10,2122,6625,9021,0,2337,7476,9872,10,9021,6624,2142,0,9872,7475,2357,10,6625,1058,6624,0,7476,1273,7475,10,9022,4280,468,0,9873,4707,669,10,6626,9022,4263,0,7477,9873,5569,10,6629,2141,4280,0,7480,2356,4707,10,1059,6629,9022,0,1274,7480,9873,10,4185,9023,4262,0,4612,9874,5570,10,2093,6627,9023,0,2308,7478,9874,10,9023,6626,2132,0,9874,7477,2787,10,6627,1059,6626,0,7478,1274,7477,10,9024,4184,473,0,9875,4611,650,10,6628,9024,4284,0,7479,9875,4711,10,6627,2093,4184,0,7478,2308,4611,10,1059,6627,9024,0,1274,7478,9875,10,4281,9025,4285,0,4708,9876,4712,10,2141,6629,9025,0,2356,7480,9876,10,9025,6628,2143,0,9876,7479,2358,10,6629,1059,6628,0,7480,1274,7479,10,9026,4190,442,0,9877,4617,614,10,6630,9026,4275,0,7481,9877,5575,10,6633,2096,4190,0,7484,2311,4617,10,1060,6633,9026,0,1275,7484,9877,10,4286,9027,4274,0,4713,9878,5576,10,2144,6631,9027,0,2359,7482,9878,10,9027,6630,2138,0,9878,7481,2790,10,6631,1060,6630,0,7482,1275,7481,10,9028,4287,460,0,9879,4714,637,10,6632,9028,4285,0,7483,9879,4712,10,6631,2144,4287,0,7482,2359,4714,10,1060,6631,9028,0,1275,7482,9879,10,4191,9029,4284,0,4618,9880,4711,10,2096,6633,9029,0,2311,7484,9880,10,9029,6632,2143,0,9880,7483,2358,10,6633,1060,6632,0,7484,1275,7483,10,9030,4286,480,0,9881,4713,677,10,6634,9030,4269,0,7485,9881,5573,10,6637,2144,4286,0,7488,2359,4713,10,1061,6637,9030,0,1276,7488,9881,10,4249,9031,4268,0,4676,9882,5574,10,2125,6635,9031,0,2340,7486,9882,10,9031,6634,2135,0,9882,7485,2789,10,6635,1061,6634,0,7486,1276,7485,10,9032,4248,484,0,9883,4675,661,10,6636,9032,4283,0,7487,9883,4710,10,6635,2125,4248,0,7486,2340,4675,10,1061,6635,9032,0,1276,7486,9883,10,4287,9033,4282,0,4714,9884,4709,10,2144,6637,9033,0,2359,7488,9884,10,9033,6636,2142,0,9884,7487,2357,10,6637,1061,6636,0,7488,1276,7487,10,9034,4304,485,0,9885,4731,678,10,6638,9034,4288,0,7489,9885,4715,10,6641,2153,4304,0,7492,2368,4731,10,1062,6641,9034,0,1277,7492,9885,10,4344,9035,4289,0,4771,9886,4716,10,2173,6639,9035,0,2388,7490,9886,10,9035,6638,2145,0,9886,7489,2360,10,6639,1062,6638,0,7490,1277,7489,10,9036,4345,493,0,9887,4772,690,10,6640,9036,4320,0,7491,9887,4747,10,6639,2173,4345,0,7490,2388,4772,10,1062,6639,9036,0,1277,7490,9887,10,4305,9037,4321,0,4732,9888,4748,10,2153,6641,9037,0,2368,7492,9888,10,9037,6640,2161,0,9888,7491,2376,10,6641,1062,6640,0,7492,1277,7491,10,9038,4306,487,0,9889,4733,681,10,6642,9038,4292,0,7493,9889,4719,10,6645,2154,4306,0,7496,2369,4733,10,1063,6645,9038,0,1278,7496,9889,10,4376,9039,4293,0,4803,9890,4720,10,2189,6643,9039,0,2404,7494,9890,10,9039,6642,2147,0,9890,7493,2362,10,6643,1063,6642,0,7494,1278,7493,10,9040,4377,504,0,9891,4804,707,10,6644,9040,4291,0,7495,9891,4718,10,6643,2189,4377,0,7494,2404,4804,10,1063,6643,9040,0,1278,7494,9891,10,4307,9041,4290,0,4734,9892,4717,10,2154,6645,9041,0,2369,7496,9892,10,9041,6644,2146,0,9892,7495,2361,10,6645,1063,6644,0,7496,1278,7495,10,9042,4308,488,0,9893,4735,683,10,6646,9042,4294,0,7497,9893,4721,10,6649,2155,4308,0,7500,2370,4735,10,1064,6649,9042,0,1279,7500,9893,10,4346,9043,4295,0,4773,9894,4722,10,2174,6647,9043,0,2389,7498,9894,10,9043,6646,2148,0,9894,7497,2363,10,6647,1064,6646,0,7498,1279,7497,10,9044,4347,495,0,9895,4774,693,10,6648,9044,4324,0,7499,9895,4751,10,6647,2174,4347,0,7498,2389,4774,10,1064,6647,9044,0,1279,7498,9895,10,4309,9045,4325,0,4736,9896,4752,10,2155,6649,9045,0,2370,7500,9896,10,9045,6648,2163,0,9896,7499,2378,10,6649,1064,6648,0,7500,1279,7499,10,9046,4310,490,0,9897,4737,686,10,6650,9046,4298,0,7501,9897,4725,10,6653,2156,4310,0,7504,2371,4737,10,1065,6653,9046,0,1280,7504,9897,10,4378,9047,4299,0,4805,9898,4726,10,2190,6651,9047,0,2405,7502,9898,10,9047,6650,2150,0,9898,7501,2365,10,6651,1065,6650,0,7502,1280,7501,10,9048,4379,506,0,9899,4806,710,10,6652,9048,4297,0,7503,9899,4724,10,6651,2190,4379,0,7502,2405,4806,10,1065,6651,9048,0,1280,7502,9899,10,4311,9049,4296,0,4738,9900,4723,10,2156,6653,9049,0,2371,7504,9900,10,9049,6652,2149,0,9900,7503,2364,10,6653,1065,6652,0,7504,1280,7503,10,9050,4312,487,0,9901,4739,682,10,6654,9050,4323,0,7505,9901,5585,10,6657,2157,4312,0,7508,2372,4739,10,1066,6657,9050,0,1281,7508,9901,10,4348,9051,4322,0,4775,9902,5586,10,2175,6655,9051,0,2390,7506,9902,10,9051,6654,2162,0,9902,7505,2795,10,6655,1066,6654,0,7506,1281,7505,10,9052,4349,497,0,9903,4776,696,10,6656,9052,4328,0,7507,9903,4755,10,6655,2175,4349,0,7506,2390,4776,10,1066,6655,9052,0,1281,7506,9903,10,4313,9053,4329,0,4740,9904,4756,10,2157,6657,9053,0,2372,7508,9904,10,9053,6656,2165,0,9904,7507,2380,10,6657,1066,6656,0,7508,1281,7507,10,9054,4314,488,0,9905,4741,684,10,6658,9054,4355,0,7509,9905,5595,10,6661,2158,4314,0,7512,2373,4741,10,1067,6661,9054,0,1282,7512,9905,10,4380,9055,4354,0,4807,9906,5596,10,2191,6659,9055,0,2406,7510,9906,10,9055,6658,2178,0,9906,7509,2800,10,6659,1067,6658,0,7510,1282,7509,10,9056,4381,508,0,9907,4808,713,10,6660,9056,4301,0,7511,9907,4728,10,6659,2191,4381,0,7510,2406,4808,10,1067,6659,9056,0,1282,7510,9907,10,4315,9057,4300,0,4742,9908,4727,10,2158,6661,9057,0,2373,7512,9908,10,9057,6660,2151,0,9908,7511,2366,10,6661,1067,6660,0,7512,1282,7511,10,9058,4316,485,0,9909,4743,679,10,6662,9058,4353,0,7513,9909,5593,10,6665,2159,4316,0,7516,2374,4743,10,1068,6665,9058,0,1283,7516,9909,10,4382,9059,4352,0,4809,9910,5594,10,2192,6663,9059,0,2407,7514,9910,10,9059,6662,2177,0,9910,7513,2799,10,6663,1068,6662,0,7514,1283,7513,10,9060,4383,503,0,9911,4810,706,10,6664,9060,4356,0,7515,9911,4783,10,6663,2192,4383,0,7514,2407,4810,10,1068,6663,9060,0,1283,7514,9911,10,4317,9061,4357,0,4744,9912,4784,10,2159,6665,9061,0,2374,7516,9912,10,9061,6664,2179,0,9912,7515,2394,10,6665,1068,6664,0,7516,1283,7515,10,9062,4318,490,0,9913,4745,687,10,6666,9062,4327,0,7517,9913,5587,10,6669,2160,4318,0,7520,2375,4745,10,1069,6669,9062,0,1284,7520,9913,10,4350,9063,4326,0,4777,9914,5588,10,2176,6667,9063,0,2391,7518,9914,10,9063,6666,2164,0,9914,7517,2796,10,6667,1069,6666,0,7518,1284,7517,10,9064,4351,500,0,9915,4778,701,10,6668,9064,4303,0,7519,9915,4730,10,6667,2176,4351,0,7518,2391,4778,10,1069,6667,9064,0,1284,7518,9915,10,4319,9065,4302,0,4746,9916,4729,10,2160,6669,9065,0,2375,7520,9916,10,9065,6668,2152,0,9916,7519,2367,10,6669,1069,6668,0,7520,1284,7519,10,9066,4336,494,0,9917,4763,691,10,6670,9066,4322,0,7521,9917,4749,10,6673,2169,4336,0,7524,2384,4763,10,1070,6673,9066,0,1285,7524,9917,10,4306,9067,4323,0,4733,9918,4750,10,2154,6671,9067,0,2369,7522,9918,10,9067,6670,2162,0,9918,7521,2377,10,6671,1070,6670,0,7522,1285,7521,10,9068,4307,486,0,9919,4734,680,10,6672,9068,4321,0,7523,9919,4748,10,6671,2154,4307,0,7522,2369,4734,10,1070,6671,9068,0,1285,7522,9919,10,4337,9069,4320,0,4764,9920,4747,10,2169,6673,9069,0,2384,7524,9920,10,9069,6672,2161,0,9920,7523,2376,10,6673,1070,6672,0,7524,1285,7523,10,9070,4338,496,0,9921,4765,694,10,6674,9070,4326,0,7525,9921,4753,10,6677,2170,4338,0,7528,2385,4765,10,1071,6677,9070,0,1286,7528,9921,10,4310,9071,4327,0,4737,9922,4754,10,2156,6675,9071,0,2371,7526,9922,10,9071,6674,2164,0,9922,7525,2379,10,6675,1071,6674,0,7526,1286,7525,10,9072,4311,489,0,9923,4738,685,10,6676,9072,4325,0,7527,9923,4752,10,6675,2156,4311,0,7526,2371,4738,10,1071,6675,9072,0,1286,7526,9923,10,4339,9073,4324,0,4766,9924,4751,10,2170,6677,9073,0,2385,7528,9924,10,9073,6676,2163,0,9924,7527,2378,10,6677,1071,6676,0,7528,1286,7527,10,9074,4340,499,0,9925,4767,700,10,6678,9074,4295,0,7529,9925,5581,10,6681,2171,4340,0,7532,2386,4767,10,1072,6681,9074,0,1287,7532,9925,10,4314,9075,4294,0,4741,9926,5582,10,2158,6679,9075,0,2373,7530,9926,10,9075,6678,2148,0,9926,7529,2793,10,6679,1072,6678,0,7530,1287,7529,10,9076,4315,491,0,9927,4742,688,10,6680,9076,4329,0,7531,9927,4756,10,6679,2158,4315,0,7530,2373,4742,10,1072,6679,9076,0,1287,7530,9927,10,4341,9077,4328,0,4768,9928,4755,10,2171,6681,9077,0,2386,7532,9928,10,9077,6680,2165,0,9928,7531,2380,10,6681,1072,6680,0,7532,1287,7531,10,9078,4342,498,0,9929,4769,698,10,6682,9078,4289,0,7533,9929,5577,10,6685,2172,4342,0,7536,2387,4769,10,1073,6685,9078,0,1288,7536,9929,10,4316,9079,4288,0,4743,9930,5578,10,2159,6683,9079,0,2374,7534,9930,10,9079,6682,2145,0,9930,7533,2791,10,6683,1073,6682,0,7534,1288,7533,10,9080,4317,492,0,9931,4744,689,10,6684,9080,4302,0,7535,9931,4729,10,6683,2159,4317,0,7534,2374,4744,10,1073,6683,9080,0,1288,7534,9931,10,4343,9081,4303,0,4770,9932,4730,10,2172,6685,9081,0,2387,7536,9932,10,9081,6684,2152,0,9932,7535,2367,10,6685,1073,6684,0,7536,1288,7535,10,9082,4344,498,0,9933,4771,697,10,6686,9082,4330,0,7537,9933,4757,10,6689,2173,4344,0,7540,2388,4771,10,1074,6689,9082,0,1289,7540,9933,10,4216,9083,4331,0,4643,9934,4758,10,2109,6687,9083,0,2324,7538,9934,10,9083,6686,2166,0,9934,7537,2381,10,6687,1074,6686,0,7538,1289,7537,10,9084,4217,482,0,9935,4644,659,10,6688,9084,4218,0,7539,9935,4645,10,6687,2109,4217,0,7538,2324,4644,10,1074,6687,9084,0,1289,7538,9935,10,4345,9085,4219,0,4772,9936,4646,10,2173,6689,9085,0,2388,7540,9936,10,9085,6688,2110,0,9936,7539,2325,10,6689,1074,6688,0,7540,1289,7539,10,9086,4346,499,0,9937,4773,699,10,6690,9086,4332,0,7541,9937,4759,10,6693,2174,4346,0,7544,2389,4773,10,1075,6693,9086,0,1290,7544,9937,10,4230,9087,4333,0,4657,9938,4760,10,2116,6691,9087,0,2331,7542,9938,10,9087,6690,2167,0,9938,7541,2382,10,6691,1075,6690,0,7542,1290,7541,10,9088,4231,483,0,9939,4658,660,10,6692,9088,4232,0,7543,9939,4659,10,6691,2116,4231,0,7542,2331,4658,10,1075,6691,9088,0,1290,7542,9939,10,4347,9089,4233,0,4774,9940,4660,10,2174,6693,9089,0,2389,7544,9940,10,9089,6692,2117,0,9940,7543,2332,10,6693,1075,6692,0,7544,1290,7543,10,9090,4348,494,0,9941,4775,692,10,6694,9090,4221,0,7545,9941,5563,10,6697,2175,4348,0,7548,2390,4775,10,1076,6697,9090,0,1291,7548,9941,10,4242,9091,4220,0,4669,9942,5564,10,2122,6695,9091,0,2337,7546,9942,10,9091,6694,2111,0,9942,7545,2784,10,6695,1076,6694,0,7546,1291,7545,10,9092,4243,484,0,9943,4670,661,10,6696,9092,4244,0,7547,9943,4671,10,6695,2122,4243,0,7546,2337,4670,10,1076,6695,9092,0,1291,7546,9943,10,4349,9093,4245,0,4776,9944,4672,10,2175,6697,9093,0,2390,7548,9944,10,9093,6696,2123,0,9944,7547,2338,10,6697,1076,6696,0,7548,1291,7547,10,9094,4350,496,0,9945,4777,695,10,6698,9094,4235,0,7549,9945,5567,10,6701,2176,4350,0,7552,2391,4777,10,1077,6701,9094,0,1292,7552,9945,10,4209,9095,4234,0,4636,9946,5568,10,2105,6699,9095,0,2320,7550,9946,10,9095,6698,2118,0,9946,7549,2786,10,6699,1077,6698,0,7550,1292,7549,10,9096,4208,481,0,9947,4635,658,10,6700,9096,4335,0,7551,9947,4762,10,6699,2105,4208,0,7550,2320,4635,10,1077,6699,9096,0,1292,7550,9947,10,4351,9097,4334,0,4778,9948,4761,10,2176,6701,9097,0,2391,7552,9948,10,9097,6700,2168,0,9948,7551,2383,10,6701,1077,6700,0,7552,1292,7551,10,9098,4368,501,0,9949,4795,702,10,6702,9098,4352,0,7553,9949,4779,10,6705,2185,4368,0,7556,2400,4795,10,1078,6705,9098,0,1293,7556,9949,10,4304,9099,4353,0,4731,9950,4780,10,2153,6703,9099,0,2368,7554,9950,10,9099,6702,2177,0,9950,7553,2392,10,6703,1078,6702,0,7554,1293,7553,10,9100,4305,486,0,9951,4732,680,10,6704,9100,4290,0,7555,9951,4717,10,6703,2153,4305,0,7554,2368,4732,10,1078,6703,9100,0,1293,7554,9951,10,4369,9101,4291,0,4796,9952,4718,10,2185,6705,9101,0,2400,7556,9952,10,9101,6704,2146,0,9952,7555,2361,10,6705,1078,6704,0,7556,1293,7555,10,9102,4370,502,0,9953,4797,704,10,6706,9102,4354,0,7557,9953,4781,10,6709,2186,4370,0,7560,2401,4797,10,1079,6709,9102,0,1294,7560,9953,10,4308,9103,4355,0,4735,9954,4782,10,2155,6707,9103,0,2370,7558,9954,10,9103,6706,2178,0,9954,7557,2393,10,6707,1079,6706,0,7558,1294,7557,10,9104,4309,489,0,9955,4736,685,10,6708,9104,4296,0,7559,9955,4723,10,6707,2155,4309,0,7558,2370,4736,10,1079,6707,9104,0,1294,7558,9955,10,4371,9105,4297,0,4798,9956,4724,10,2186,6709,9105,0,2401,7560,9956,10,9105,6708,2149,0,9956,7559,2364,10,6709,1079,6708,0,7560,1294,7559,10,9106,4372,505,0,9957,4799,709,10,6710,9106,4293,0,7561,9957,5579,10,6713,2187,4372,0,7564,2402,4799,10,1080,6713,9106,0,1295,7564,9957,10,4312,9107,4292,0,4739,9958,5580,10,2157,6711,9107,0,2372,7562,9958,10,9107,6710,2147,0,9958,7561,2792,10,6711,1080,6710,0,7562,1295,7561,10,9108,4313,491,0,9959,4740,688,10,6712,9108,4300,0,7563,9959,4727,10,6711,2157,4313,0,7562,2372,4740,10,1080,6711,9108,0,1295,7562,9959,10,4373,9109,4301,0,4800,9960,4728,10,2187,6713,9109,0,2402,7564,9960,10,9109,6712,2151,0,9960,7563,2366,10,6713,1080,6712,0,7564,1295,7563,10,9110,4374,507,0,9961,4801,712,10,6714,9110,4299,0,7565,9961,5583,10,6717,2188,4374,0,7568,2403,4801,10,1081,6717,9110,0,1296,7568,9961,10,4318,9111,4298,0,4745,9962,5584,10,2160,6715,9111,0,2375,7566,9962,10,9111,6714,2150,0,9962,7565,2794,10,6715,1081,6714,0,7566,1296,7565,10,9112,4319,492,0,9963,4746,689,10,6716,9112,4357,0,7567,9963,4784,10,6715,2160,4319,0,7566,2375,4746,10,1081,6715,9112,0,1296,7566,9963,10,4375,9113,4356,0,4802,9964,4783,10,2188,6717,9113,0,2403,7568,9964,10,9113,6716,2179,0,9964,7567,2394,10,6717,1081,6716,0,7568,1296,7567,10,9114,4376,505,0,9965,4803,708,10,6718,9114,4360,0,7569,9965,4787,10,6721,2189,4376,0,7572,2404,4803,10,1082,6721,9114,0,1297,7572,9965,10,4222,9115,4361,0,4649,9966,4788,10,2112,6719,9115,0,2327,7570,9966,10,9115,6718,2181,0,9966,7569,2396,10,6719,1082,6718,0,7570,1297,7569,10,9116,4223,454,0,9967,4650,631,10,6720,9116,4359,0,7571,9967,4786,10,6719,2112,4223,0,7570,2327,4650,10,1082,6719,9116,0,1297,7570,9967,10,4377,9117,4358,0,4804,9968,4785,10,2189,6721,9117,0,2404,7572,9968,10,9117,6720,2180,0,9968,7571,2395,10,6721,1082,6720,0,7572,1297,7571,10,9118,4378,507,0,9969,4805,711,10,6722,9118,4364,0,7573,9969,4791,10,6725,2190,4378,0,7576,2405,4805,10,1083,6725,9118,0,1298,7576,9969,10,4236,9119,4365,0,4663,9970,4792,10,2119,6723,9119,0,2334,7574,9970,10,9119,6722,2183,0,9970,7573,2398,10,6723,1083,6722,0,7574,1298,7573,10,9120,4237,455,0,9971,4664,632,10,6724,9120,4363,0,7575,9971,4790,10,6723,2119,4237,0,7574,2334,4664,10,1083,6723,9120,0,1298,7574,9971,10,4379,9121,4362,0,4806,9972,4789,10,2190,6725,9121,0,2405,7576,9972,10,9121,6724,2182,0,9972,7575,2397,10,6725,1083,6724,0,7576,1298,7575,10,9122,4380,502,0,9973,4807,705,10,6726,9122,4229,0,7577,9973,5565,10,6729,2191,4380,0,7580,2406,4807,10,1084,6729,9122,0,1299,7580,9973,10,4246,9123,4228,0,4673,9974,5566,10,2124,6727,9123,0,2339,7578,9974,10,9123,6726,2115,0,9974,7577,2785,10,6727,1084,6726,0,7578,1299,7577,10,9124,4247,456,0,9975,4674,633,10,6728,9124,4367,0,7579,9975,4794,10,6727,2124,4247,0,7578,2339,4674,10,1084,6727,9124,0,1299,7578,9975,10,4381,9125,4366,0,4808,9976,4793,10,2191,6729,9125,0,2406,7580,9976,10,9125,6728,2184,0,9976,7579,2399,10,6729,1084,6728,0,7580,1299,7579,10,9126,4382,501,0,9977,4809,703,10,6730,9126,4215,0,7581,9977,5561,10,6733,2192,4382,0,7584,2407,4809,10,1085,6733,9126,0,1300,7584,9977,10,4250,9127,4214,0,4677,9978,5562,10,2126,6731,9127,0,2341,7582,9978,10,9127,6730,2108,0,9978,7581,2783,10,6731,1085,6730,0,7582,1300,7581,10,9128,4251,457,0,9979,4678,634,10,6732,9128,4252,0,7583,9979,4679,10,6731,2126,4251,0,7582,2341,4678,10,1085,6731,9128,0,1300,7582,9979,10,4383,9129,4253,0,4810,9980,4680,10,2192,6733,9129,0,2407,7584,9980,10,9129,6732,2127,0,9980,7583,2342,10,6733,1085,6732,0,7584,1300,7583,10,9130,4384,292,0,9981,4811,381,10,6734,9130,3519,0,7585,9981,3946,10,6737,2193,4384,0,7588,2408,4811,10,1086,6737,9130,0,1301,7588,9981,10,4386,9131,3518,0,4813,9982,3945,10,2194,6735,9131,0,2409,7586,9982,10,9131,6734,1760,0,9982,7585,1975,10,6735,1086,6734,0,7586,1301,7585,10,9132,4387,476,0,9983,4814,653,10,6736,9132,4227,0,7587,9983,4654,10,6735,2194,4387,0,7586,2409,4814,10,1086,6735,9132,0,1301,7586,9983,10,4385,9133,4226,0,4812,9984,4653,10,2193,6737,9133,0,2408,7588,9984,10,9133,6736,2114,0,9984,7587,2329,10,6737,1086,6736,0,7588,1301,7587,10,9134,4386,214,0,9985,5602,286,10,6738,9134,3139,0,7589,9985,3566,10,6741,2194,4386,0,7592,2803,5602,10,1087,6741,9134,0,1302,7592,9985,10,4388,9135,3138,0,4815,9986,3565,10,2195,6739,9135,0,2410,7590,9986,10,9135,6738,1570,0,9986,7589,1785,10,6739,1087,6738,0,7590,1302,7589,10,9136,4389,456,0,9987,4816,633,10,6740,9136,4247,0,7591,9987,4674,10,6739,2195,4389,0,7590,2410,4816,10,1087,6739,9136,0,1302,7590,9987,10,4387,9137,4246,0,5601,9988,4673,10,2194,6741,9137,0,2803,7592,9988,10,9137,6740,2124,0,9988,7591,2339,10,6741,1087,6740,0,7592,1302,7591,10,9138,4388,215,0,9989,5604,289,10,6742,9138,3143,0,7593,9989,3570,10,6745,2195,4388,0,7596,2804,5604,10,1088,6745,9138,0,1303,7596,9989,10,4390,9139,3142,0,4817,9990,3569,10,2196,6743,9139,0,2411,7594,9990,10,9139,6742,1572,0,9990,7593,1787,10,6743,1088,6742,0,7594,1303,7593,10,9140,4391,477,0,9991,4818,674,10,6744,9140,4241,0,7595,9991,4668,10,6743,2196,4391,0,7594,2411,4818,10,1088,6743,9140,0,1303,7594,9991,10,4389,9141,4240,0,5603,9992,4667,10,2195,6745,9141,0,2804,7596,9992,10,9141,6744,2121,0,9992,7595,2336,10,6745,1088,6744,0,7596,1303,7595,10,9142,4390,200,0,9993,5606,269,10,6746,9142,3175,0,7597,9993,3602,10,6749,2196,4390,0,7600,2805,5606,10,1089,6749,9142,0,1304,7600,9993,10,4392,9143,3174,0,4819,9994,3601,10,2197,6747,9143,0,2412,7598,9994,10,9143,6746,1588,0,9994,7597,1803,10,6747,1089,6746,0,7598,1304,7597,10,9144,4393,454,0,9995,4820,631,10,6748,9144,4223,0,7599,9995,4650,10,6747,2197,4393,0,7598,2412,4820,10,1089,6747,9144,0,1304,7598,9995,10,4391,9145,4222,0,5605,9996,4649,10,2196,6749,9145,0,2805,7600,9996,10,9145,6748,2112,0,9996,7599,2327,10,6749,1089,6748,0,7600,1304,7599,10,9146,4392,222,0,9997,4819,300,10,6750,9146,3497,0,7601,9997,3924,10,6753,2197,4392,0,7604,2412,4819,10,1090,6753,9146,0,1305,7604,9997,10,4394,9147,3496,0,4821,9998,3923,10,2198,6751,9147,0,2413,7602,9998,10,9147,6750,1749,0,9998,7601,1964,10,6751,1090,6750,0,7602,1305,7601,10,9148,4395,475,0,9999,4822,652,10,6752,9148,4213,0,7603,9999,4640,10,6751,2198,4395,0,7602,2413,4822,10,1090,6751,9148,0,1305,7602,9999,10,4393,9149,4212,0,4820,10000,4639,10,2197,6753,9149,0,2412,7604,10000,10,9149,6752,2107,0,10000,7603,2322,10,6753,1090,6752,0,7604,1305,7603,10,9150,4394,211,0,10001,5608,282,10,6754,9150,3129,0,7605,10001,3556,10,6757,2198,4394,0,7608,2806,5608,10,1091,6757,9150,0,1306,7608,10001,10,4396,9151,3128,0,4823,10002,3555,10,2199,6755,9151,0,2414,7606,10002,10,9151,6754,1565,0,10002,7605,1780,10,6755,1091,6754,0,7606,1306,7605,10,9152,4397,457,0,10003,4824,634,10,6756,9152,4251,0,7607,10003,4678,10,6755,2199,4397,0,7606,2414,4824,10,1091,6755,9152,0,1306,7606,10003,10,4395,9153,4250,0,5607,10004,4677,10,2198,6757,9153,0,2806,7608,10004,10,9153,6756,2126,0,10004,7607,2341,10,6757,1091,6756,0,7608,1306,7607,10,9154,4396,208,0,10005,5610,277,10,6758,9154,3113,0,7609,10005,3540,10,6761,2199,4396,0,7612,2807,5610,10,1092,6761,9154,0,1307,7612,10005,10,4398,9155,3112,0,4825,10006,3539,10,2200,6759,9155,0,2415,7610,10006,10,9155,6758,1557,0,10006,7609,1772,10,6759,1092,6758,0,7610,1307,7609,10,9156,4399,478,0,10007,4826,675,10,6760,9156,4255,0,7611,10007,4682,10,6759,2200,4399,0,7610,2415,4826,10,1092,6759,9156,0,1307,7610,10007,10,4397,9157,4254,0,5609,10008,4681,10,2199,6761,9157,0,2807,7612,10008,10,9157,6760,2128,0,10008,7611,2343,10,6761,1092,6760,0,7612,1307,7611,10,9158,4398,176,0,10009,5612,245,10,6762,9158,3515,0,7613,10009,3942,10,6765,2200,4398,0,7616,2808,5612,10,1093,6765,9158,0,1308,7616,10009,10,4384,9159,3514,0,4811,10010,3941,10,2193,6763,9159,0,2408,7614,10010,10,9159,6762,1758,0,10010,7613,1973,10,6763,1093,6762,0,7614,1308,7613,10,9160,4385,455,0,10011,4812,632,10,6764,9160,4237,0,7615,10011,4664,10,6763,2193,4385,0,7614,2408,4812,10,1093,6763,9160,0,1308,7614,10011,10,4399,9161,4236,0,5611,10012,4663,10,2200,6765,9161,0,2808,7616,10012,10,9161,6764,2119,0,10012,7615,2334,10,6765,1093,6764,0,7616,1308,7615,10,9162,4400,40,0,10013,5614,56,10,6766,9162,2521,0,7617,10013,2948,10,6769,2201,4400,0,7620,2809,5614,10,1094,6769,9162,0,1309,7620,10013,10,4402,9163,2520,0,4829,10014,2947,10,2202,6767,9163,0,2417,7618,10014,10,9163,6766,1261,0,10014,7617,1476,10,6767,1094,6766,0,7618,1309,7617,10,9164,4403,510,0,10015,4830,716,10,6768,9164,4432,0,7619,10015,4859,10,6767,2202,4403,0,7618,2417,4830,10,1094,6767,9164,0,1309,7618,10015,10,4401,9165,4433,0,5613,10016,4860,10,2201,6769,9165,0,2809,7620,10016,10,9165,6768,2217,0,10016,7619,2432,10,6769,1094,6768,0,7620,1309,7619,10,9166,4402,19,0,10017,4829,35,10,6770,9166,2531,0,7621,10017,2958,10,6773,2202,4402,0,7624,2417,4829,10,1095,6773,9166,0,1310,7624,10017,10,4404,9167,2530,0,4831,10018,2957,10,2203,6771,9167,0,2418,7622,10018,10,9167,6770,1266,0,10018,7621,1481,10,6771,1095,6770,0,7622,1310,7621,10,9168,4405,511,0,10019,4832,717,10,6772,9168,4434,0,7623,10019,4861,10,6771,2203,4405,0,7622,2418,4832,10,1095,6771,9168,0,1310,7622,10019,10,4403,9169,4435,0,4830,10020,4862,10,2202,6773,9169,0,2417,7624,10020,10,9169,6772,2218,0,10020,7623,2433,10,6773,1095,6772,0,7624,1310,7623,10,9170,4404,42,0,10021,5616,78,10,6774,9170,2549,0,7625,10021,2976,10,6777,2203,4404,0,7628,2810,5616,10,1096,6777,9170,0,1311,7628,10021,10,4406,9171,2548,0,4833,10022,2975,10,2204,6775,9171,0,2419,7626,10022,10,9171,6774,1275,0,10022,7625,1490,10,6775,1096,6774,0,7626,1311,7625,10,9172,4407,512,0,10023,4834,719,10,6776,9172,4436,0,7627,10023,4863,10,6775,2204,4407,0,7626,2419,4834,10,1096,6775,9172,0,1311,7626,10023,10,4405,9173,4437,0,5615,10024,4864,10,2203,6777,9173,0,2810,7628,10024,10,9173,6776,2219,0,10024,7627,2434,10,6777,1096,6776,0,7628,1311,7627,10,9174,4406,21,0,10025,5618,37,10,6778,9174,2545,0,7629,10025,2972,10,6781,2204,4406,0,7632,2811,5618,10,1097,6781,9174,0,1312,7632,10025,10,4408,9175,2544,0,4835,10026,2971,10,2205,6779,9175,0,2420,7630,10026,10,9175,6778,1273,0,10026,7629,1488,10,6779,1097,6778,0,7630,1312,7629,10,9176,4409,513,0,10027,4836,721,10,6780,9176,4438,0,7631,10027,4865,10,6779,2205,4409,0,7630,2420,4836,10,1097,6779,9176,0,1312,7630,10027,10,4407,9177,4439,0,5617,10028,4866,10,2204,6781,9177,0,2811,7632,10028,10,9177,6780,2220,0,10028,7631,2435,10,6781,1097,6780,0,7632,1312,7631,10,9178,4408,39,0,10029,5620,55,10,6782,9178,2507,0,7633,10029,2934,10,6785,2205,4408,0,7636,2812,5620,10,1098,6785,9178,0,1313,7636,10029,10,4410,9179,2506,0,4837,10030,2933,10,2206,6783,9179,0,2421,7634,10030,10,9179,6782,1254,0,10030,7633,1469,10,6783,1098,6782,0,7634,1313,7633,10,9180,4411,514,0,10031,4838,723,10,6784,9180,4440,0,7635,10031,4867,10,6783,2206,4411,0,7634,2421,4838,10,1098,6783,9180,0,1313,7634,10031,10,4409,9181,4441,0,5619,10032,4868,10,2205,6785,9181,0,2812,7636,10032,10,9181,6784,2221,0,10032,7635,2436,10,6785,1098,6784,0,7636,1313,7635,10,9182,4410,18,0,10033,4837,34,10,6786,9182,2517,0,7637,10033,2944,10,6789,2206,4410,0,7640,2421,4837,10,1099,6789,9182,0,1314,7640,10033,10,4412,9183,2516,0,4839,10034,2943,10,2207,6787,9183,0,2422,7638,10034,10,9183,6786,1259,0,10034,7637,1474,10,6787,1099,6786,0,7638,1314,7637,10,9184,4413,515,0,10035,4840,724,10,6788,9184,4442,0,7639,10035,4869,10,6787,2207,4413,0,7638,2422,4840,10,1099,6787,9184,0,1314,7638,10035,10,4411,9185,4443,0,4838,10036,4870,10,2206,6789,9185,0,2421,7640,10036,10,9185,6788,2222,0,10036,7639,2437,10,6789,1099,6788,0,7640,1314,7639,10,9186,4412,41,0,10037,5622,77,10,6790,9186,2535,0,7641,10037,2962,10,6793,2207,4412,0,7644,2813,5622,10,1100,6793,9186,0,1315,7644,10037,10,4414,9187,2534,0,4841,10038,2961,10,2208,6791,9187,0,2423,7642,10038,10,9187,6790,1268,0,10038,7641,1483,10,6791,1100,6790,0,7642,1315,7641,10,9188,4415,516,0,10039,4842,726,10,6792,9188,4444,0,7643,10039,4871,10,6791,2208,4415,0,7642,2423,4842,10,1100,6791,9188,0,1315,7642,10039,10,4413,9189,4445,0,5621,10040,4872,10,2207,6793,9189,0,2813,7644,10040,10,9189,6792,2223,0,10040,7643,2438,10,6793,1100,6792,0,7644,1315,7643,10,9190,4414,20,0,10041,4841,36,10,6794,9190,2541,0,7645,10041,2968,10,6797,2208,4414,0,7648,2423,4841,10,1101,6797,9190,0,1316,7648,10041,10,4400,9191,2540,0,4827,10042,2967,10,2201,6795,9191,0,2416,7646,10042,10,9191,6794,1271,0,10042,7645,1486,10,6795,1101,6794,0,7646,1316,7645,10,9192,4401,509,0,10043,4828,714,10,6796,9192,4446,0,7647,10043,4873,10,6795,2201,4401,0,7646,2416,4828,10,1101,6795,9192,0,1316,7646,10043,10,4415,9193,4447,0,4842,10044,4874,10,2208,6797,9193,0,2423,7648,10044,10,9193,6796,2224,0,10044,7647,2439,10,6797,1101,6796,0,7648,1316,7647,10,9194,4432,510,0,10045,4859,716,10,6798,9194,4418,0,7649,10045,4845,10,6801,2217,4432,0,7652,2432,4859,10,1102,6801,9194,0,1317,7652,10045,10,3511,9195,4419,0,3938,10046,4846,10,1756,6799,9195,0,1971,7650,10046,10,9195,6798,2210,0,10046,7649,2425,10,6799,1102,6798,0,7650,1317,7649,10,9196,3510,220,0,10047,3937,298,10,6800,9196,4417,0,7651,10047,5623,10,6799,1756,3510,0,7650,1971,3937,10,1102,6799,9196,0,1317,7650,10047,10,4433,9197,4416,0,4860,10048,5624,10,2217,6801,9197,0,2432,7652,10048,10,9197,6800,2209,0,10048,7651,2814,10,6801,1102,6800,0,7652,1317,7651,10,9198,4434,511,0,10049,4861,717,10,6802,9198,4420,0,7653,10049,4847,10,6805,2218,4434,0,7656,2433,4861,10,1103,6805,9198,0,1318,7656,10049,10,3171,9199,4421,0,3598,10050,4848,10,1586,6803,9199,0,1801,7654,10050,10,9199,6802,2211,0,10050,7653,2426,10,6803,1103,6802,0,7654,1318,7653,10,9200,3170,221,0,10051,3597,299,10,6804,9200,4419,0,7655,10051,4846,10,6803,1586,3170,0,7654,1801,3597,10,1103,6803,9200,0,1318,7654,10051,10,4435,9201,4418,0,4862,10052,4845,10,2218,6805,9201,0,2433,7656,10052,10,9201,6804,2210,0,10052,7655,2425,10,6805,1103,6804,0,7656,1318,7655,10,9202,4436,512,0,10053,4863,719,10,6806,9202,4422,0,7657,10053,4849,10,6809,2219,4436,0,7660,2434,4863,10,1104,6809,9202,0,1319,7660,10053,10,3135,9203,4423,0,3562,10054,4850,10,1568,6807,9203,0,1783,7658,10054,10,9203,6806,2212,0,10054,7657,2427,10,6807,1104,6806,0,7658,1319,7657,10,9204,3134,188,0,10055,3561,257,10,6808,9204,4421,0,7659,10055,5625,10,6807,1568,3134,0,7658,1783,3561,10,1104,6807,9204,0,1319,7658,10055,10,4437,9205,4420,0,4864,10056,5626,10,2219,6809,9205,0,2434,7660,10056,10,9205,6808,2211,0,10056,7659,2815,10,6809,1104,6808,0,7660,1319,7659,10,9206,4438,513,0,10057,4865,721,10,6810,9206,4424,0,7661,10057,4851,10,6813,2220,4438,0,7664,2435,4865,10,1105,6813,9206,0,1320,7664,10057,10,3147,9207,4425,0,3574,10058,4852,10,1574,6811,9207,0,1789,7662,10058,10,9207,6810,2213,0,10058,7661,2428,10,6811,1105,6810,0,7662,1320,7661,10,9208,3146,213,0,10059,3573,290,10,6812,9208,4423,0,7663,10059,5627,10,6811,1574,3146,0,7662,1789,3573,10,1105,6811,9208,0,1320,7662,10059,10,4439,9209,4422,0,4866,10060,5628,10,2220,6813,9209,0,2435,7664,10060,10,9209,6812,2212,0,10060,7663,2816,10,6813,1105,6812,0,7664,1320,7663,10,9210,4440,514,0,10061,4867,723,10,6814,9210,4426,0,7665,10061,4853,10,6817,2221,4440,0,7668,2436,4867,10,1106,6817,9210,0,1321,7668,10061,10,3173,9211,4427,0,3600,10062,4854,10,1587,6815,9211,0,1802,7666,10062,10,9211,6814,2214,0,10062,7665,2429,10,6815,1106,6814,0,7666,1321,7665,10,9212,3172,203,0,10063,3599,272,10,6816,9212,4425,0,7667,10063,5629,10,6815,1587,3172,0,7666,1802,3599,10,1106,6815,9212,0,1321,7666,10063,10,4441,9213,4424,0,4868,10064,5630,10,2221,6817,9213,0,2436,7668,10064,10,9213,6816,2213,0,10064,7667,2817,10,6817,1106,6816,0,7668,1321,7667,10,9214,4442,515,0,10065,4869,724,10,6818,9214,4428,0,7669,10065,4855,10,6821,2222,4442,0,7672,2437,4869,10,1107,6821,9214,0,1322,7672,10065,10,2817,9215,4429,0,3244,10066,4856,10,1409,6819,9215,0,1624,7670,10066,10,9215,6818,2215,0,10066,7669,2430,10,6819,1107,6818,0,7670,1322,7669,10,9216,2816,113,0,10067,3243,177,10,6820,9216,4427,0,7671,10067,4854,10,6819,1409,2816,0,7670,1624,3243,10,1107,6819,9216,0,1322,7670,10067,10,4443,9217,4426,0,4870,10068,4853,10,2222,6821,9217,0,2437,7672,10068,10,9217,6820,2214,0,10068,7671,2429,10,6821,1107,6820,0,7672,1322,7671,10,9218,4444,516,0,10069,4871,726,10,6822,9218,4430,0,7673,10069,4857,10,6825,2223,4444,0,7676,2438,4871,10,1108,6825,9218,0,1323,7676,10069,10,3151,9219,4431,0,3578,10070,4858,10,1576,6823,9219,0,1791,7674,10070,10,9219,6822,2216,0,10070,7673,2431,10,6823,1108,6822,0,7674,1323,7673,10,9220,3150,112,0,10071,3577,293,10,6824,9220,4429,0,7675,10071,5631,10,6823,1576,3150,0,7674,1791,3577,10,1108,6823,9220,0,1323,7674,10071,10,4445,9221,4428,0,4872,10072,5632,10,2223,6825,9221,0,2438,7676,10072,10,9221,6824,2215,0,10072,7675,2818,10,6825,1108,6824,0,7676,1323,7675,10,9222,4446,509,0,10073,4873,714,10,6826,9222,4416,0,7677,10073,4843,10,6829,2224,4446,0,7680,2439,4873,10,1109,6829,9222,0,1324,7680,10073,10,3167,9223,4417,0,3594,10074,4844,10,1584,6827,9223,0,1799,7678,10074,10,9223,6826,2209,0,10074,7677,2424,10,6827,1109,6826,0,7678,1324,7677,10,9224,3166,217,0,10075,3593,292,10,6828,9224,4431,0,7679,10075,4858,10,6827,1584,3166,0,7678,1799,3593,10,1109,6827,9224,0,1324,7678,10075,10,4447,9225,4430,0,4874,10076,4857,10,2224,6829,9225,0,2439,7680,10076,10,9225,6828,2216,0,10076,7679,2431,10,6829,1109,6828,0,7680,1324,7679,10,9226,4476,518,0,10077,4903,728,10,6830,9226,4450,0,7681,10077,4877,10,6833,2239,4476,0,7684,2454,4903,10,1110,6833,9226,0,1325,7684,10077,10,4542,9227,4451,0,4969,10078,4878,10,2272,6831,9227,0,2487,7682,10078,10,9227,6830,2226,0,10078,7681,2441,10,6831,1110,6830,0,7682,1325,7681,10,9228,4543,531,0,10079,4970,742,10,6832,9228,4504,0,7683,10079,4931,10,6831,2272,4543,0,7682,2487,4970,10,1110,6831,9228,0,1325,7682,10079,10,4477,9229,4505,0,4904,10080,4932,10,2239,6833,9229,0,2454,7684,10080,10,9229,6832,2253,0,10080,7683,2468,10,6833,1110,6832,0,7684,1325,7683,10,9230,4478,520,0,10081,4905,730,10,6834,9230,4454,0,7685,10081,4881,10,6837,2240,4478,0,7688,2455,4905,10,1111,6837,9230,0,1326,7688,10081,10,4544,9231,4455,0,4971,10082,4882,10,2273,6835,9231,0,2488,7686,10082,10,9231,6834,2228,0,10082,7685,2443,10,6835,1111,6834,0,7686,1326,7685,10,9232,4545,532,0,10083,4972,743,10,6836,9232,4506,0,7687,10083,4933,10,6835,2273,4545,0,7686,2488,4972,10,1111,6835,9232,0,1326,7686,10083,10,4479,9233,4507,0,4906,10084,4934,10,2240,6837,9233,0,2455,7688,10084,10,9233,6836,2254,0,10084,7687,2469,10,6837,1111,6836,0,7688,1326,7687,10,9234,4480,521,0,10085,4907,731,10,6838,9234,4456,0,7689,10085,4883,10,6841,2241,4480,0,7692,2456,4907,10,1112,6841,9234,0,1327,7692,10085,10,4546,9235,4457,0,4973,10086,4884,10,2274,6839,9235,0,2489,7690,10086,10,9235,6838,2229,0,10086,7689,2444,10,6839,1112,6838,0,7690,1327,7689,10,9236,4547,540,0,10087,4974,751,10,6840,9236,4455,0,7691,10087,4882,10,6839,2274,4547,0,7690,2489,4974,10,1112,6839,9236,0,1327,7690,10087,10,4481,9237,4454,0,4908,10088,4881,10,2241,6841,9237,0,2456,7692,10088,10,9237,6840,2228,0,10088,7691,2443,10,6841,1112,6840,0,7692,1327,7691,10,9238,4482,523,0,10089,4909,733,10,6842,9238,4460,0,7693,10089,4887,10,6845,2242,4482,0,7696,2457,4909,10,1113,6845,9238,0,1328,7696,10089,10,4548,9239,4461,0,4975,10090,4888,10,2275,6843,9239,0,2490,7694,10090,10,9239,6842,2231,0,10090,7693,2446,10,6843,1113,6842,0,7694,1328,7693,10,9240,4549,533,0,10091,4976,744,10,6844,9240,4508,0,7695,10091,4935,10,6843,2275,4549,0,7694,2490,4976,10,1113,6843,9240,0,1328,7694,10091,10,4483,9241,4509,0,4910,10092,4936,10,2242,6845,9241,0,2457,7696,10092,10,9241,6844,2255,0,10092,7695,2470,10,6845,1113,6844,0,7696,1328,7695,10,9242,4484,519,0,10093,4911,729,10,6846,9242,4507,0,7697,10093,4934,10,6849,2243,4484,0,7700,2458,4911,10,1114,6849,9242,0,1329,7700,10093,10,4550,9243,4506,0,4977,10094,4933,10,2276,6847,9243,0,2491,7698,10094,10,9243,6846,2254,0,10094,7697,2469,10,6847,1114,6846,0,7698,1329,7697,10,9244,4551,534,0,10095,4978,745,10,6848,9244,4510,0,7699,10095,4937,10,6847,2276,4551,0,7698,2491,4978,10,1114,6847,9244,0,1329,7698,10095,10,4485,9245,4511,0,4912,10096,4938,10,2243,6849,9245,0,2458,7700,10096,10,9245,6848,2256,0,10096,7699,2471,10,6849,1114,6848,0,7700,1329,7699,10,9246,4486,525,0,10097,4913,736,10,6850,9246,4464,0,7701,10097,4891,10,6853,2244,4486,0,7704,2459,4913,10,1115,6853,9246,0,1330,7704,10097,10,4784,9247,4465,0,5211,10098,4892,10,2393,6851,9247,0,2608,7702,10098,10,9247,6850,2233,0,10098,7701,2448,10,6851,1115,6850,0,7702,1330,7701,10,9248,4785,596,0,10099,5212,811,10,6852,9248,4463,0,7703,10099,4890,10,6851,2393,4785,0,7702,2608,5212,10,1115,6851,9248,0,1330,7702,10099,10,4487,9249,4462,0,4914,10100,4889,10,2244,6853,9249,0,2459,7704,10100,10,9249,6852,2232,0,10100,7703,2447,10,6853,1115,6852,0,7704,1330,7703,10,9250,4488,526,0,10101,4915,737,10,6854,9250,4466,0,7705,10101,4893,10,6857,2245,4488,0,7708,2460,4915,10,1116,6857,9250,0,1331,7708,10101,10,4786,9251,4467,0,5213,10102,4894,10,2394,6855,9251,0,2609,7706,10102,10,9251,6854,2234,0,10102,7705,2449,10,6855,1116,6854,0,7706,1331,7705,10,9252,4787,597,0,10103,5214,812,10,6856,9252,4465,0,7707,10103,4892,10,6855,2394,4787,0,7706,2609,5214,10,1116,6855,9252,0,1331,7706,10103,10,4489,9253,4464,0,4916,10104,4891,10,2245,6857,9253,0,2460,7708,10104,10,9253,6856,2233,0,10104,7707,2448,10,6857,1116,6856,0,7708,1331,7707,10,9254,4490,528,0,10105,4917,739,10,6858,9254,4470,0,7709,10105,4897,10,6861,2246,4490,0,7712,2461,4917,10,1117,6861,9254,0,1332,7712,10105,10,4552,9255,4471,0,4979,10106,4898,10,2277,6859,9255,0,2492,7710,10106,10,9255,6858,2236,0,10106,7709,2451,10,6859,1117,6858,0,7710,1332,7709,10,9256,4553,537,0,10107,4980,748,10,6860,9256,4516,0,7711,10107,4943,10,6859,2277,4553,0,7710,2492,4980,10,1117,6859,9256,0,1332,7710,10107,10,4491,9257,4517,0,4918,10108,4944,10,2246,6861,9257,0,2461,7712,10108,10,9257,6860,2259,0,10108,7711,2474,10,6861,1117,6860,0,7712,1332,7711,10,9258,4492,526,0,10109,4919,737,10,6862,9258,4515,0,7713,10109,4942,10,6865,2247,4492,0,7716,2462,4919,10,1118,6865,9258,0,1333,7716,10109,10,4554,9259,4514,0,4981,10110,4941,10,2278,6863,9259,0,2493,7714,10110,10,9259,6862,2258,0,10110,7713,2473,10,6863,1118,6862,0,7714,1333,7713,10,9260,4555,543,0,10111,4982,755,10,6864,9260,4471,0,7715,10111,4898,10,6863,2278,4555,0,7714,2493,4982,10,1118,6863,9260,0,1333,7714,10111,10,4493,9261,4470,0,4920,10112,4897,10,2247,6865,9261,0,2462,7716,10112,10,9261,6864,2236,0,10112,7715,2451,10,6865,1118,6864,0,7716,1333,7715,10,9262,4494,530,0,10113,4921,741,10,6866,9262,4474,0,7717,10113,4901,10,6869,2248,4494,0,7720,2463,4921,10,1119,6869,9262,0,1334,7720,10113,10,4788,9263,4475,0,5215,10114,4902,10,2395,6867,9263,0,2610,7718,10114,10,9263,6866,2238,0,10114,7717,2453,10,6867,1119,6866,0,7718,1334,7717,10,9264,4789,592,0,10115,5216,807,10,6868,9264,4748,0,7719,10115,5175,10,6867,2395,4789,0,7718,2610,5216,10,1119,6867,9264,0,1334,7718,10115,10,4495,9265,4749,0,4922,10116,5176,10,2248,6869,9265,0,2463,7720,10116,10,9265,6868,2375,0,10116,7719,2590,10,6869,1119,6868,0,7720,1334,7719,10,9266,4496,523,0,10117,4923,734,10,6870,9266,4745,0,7721,10117,5643,10,6873,2249,4496,0,7724,2464,4923,10,1120,6873,9266,0,1335,7724,10117,10,4790,9267,4744,0,5217,10118,5644,10,2396,6871,9267,0,2611,7722,10118,10,9267,6870,2373,0,10118,7721,2824,10,6871,1120,6870,0,7722,1335,7721,10,9268,4791,600,0,10119,5218,815,10,6872,9268,4475,0,7723,10119,4902,10,6871,2396,4791,0,7722,2611,5218,10,1120,6871,9268,0,1335,7722,10119,10,4497,9269,4474,0,4924,10120,4901,10,2249,6873,9269,0,2464,7724,10120,10,9269,6872,2238,0,10120,7723,2453,10,6873,1120,6872,0,7724,1335,7723,10,9270,4498,527,0,10121,4925,738,10,6874,9270,4517,0,7725,10121,4944,10,6877,2250,4498,0,7728,2465,4925,10,1121,6877,9270,0,1336,7728,10121,10,4556,9271,4516,0,4983,10122,4943,10,2279,6875,9271,0,2494,7726,10122,10,9271,6874,2259,0,10122,7725,2474,10,6875,1121,6874,0,7726,1336,7725,10,9272,4557,539,0,10123,4984,750,10,6876,9272,4451,0,7727,10123,4878,10,6875,2279,4557,0,7726,2494,4984,10,1121,6875,9272,0,1336,7726,10123,10,4499,9273,4450,0,4926,10124,4877,10,2250,6877,9273,0,2465,7728,10124,10,9273,6876,2226,0,10124,7727,2441,10,6877,1121,6876,0,7728,1336,7727,10,9274,4500,529,0,10125,4927,740,10,6878,9274,4749,0,7729,10125,5176,10,6881,2251,4500,0,7732,2466,4927,10,1122,6881,9274,0,1337,7732,10125,10,4792,9275,4748,0,5219,10126,5175,10,2397,6879,9275,0,2612,7730,10126,10,9275,6878,2375,0,10126,7729,2590,10,6879,1122,6878,0,7730,1337,7729,10,9276,4793,593,0,10127,5220,808,10,6880,9276,4449,0,7731,10127,4876,10,6879,2397,4793,0,7730,2612,5220,10,1122,6879,9276,0,1337,7730,10127,10,4501,9277,4448,0,4928,10128,4875,10,2251,6881,9277,0,2466,7732,10128,10,9277,6880,2225,0,10128,7731,2440,10,6881,1122,6880,0,7732,1337,7731,10,9278,4502,522,0,10129,4929,732,10,6882,9278,4509,0,7733,10129,4936,10,6885,2252,4502,0,7736,2467,4929,10,1123,6885,9278,0,1338,7736,10129,10,4558,9279,4508,0,4985,10130,4935,10,2280,6883,9279,0,2495,7734,10130,10,9279,6882,2255,0,10130,7733,2470,10,6883,1123,6882,0,7734,1338,7733,10,9280,4559,541,0,10131,4986,752,10,6884,9280,4457,0,7735,10131,4884,10,6883,2280,4559,0,7734,2495,4986,10,1123,6883,9280,0,1338,7734,10131,10,4503,9281,4456,0,4930,10132,4883,10,2252,6885,9281,0,2467,7736,10132,10,9281,6884,2229,0,10132,7735,2444,10,6885,1123,6884,0,7736,1338,7735,10,9282,4532,535,0,10133,4959,746,10,6886,9282,4512,0,7737,10133,4939,10,6889,2267,4532,0,7740,2482,4959,10,1124,6889,9282,0,1339,7740,10133,10,4486,9283,4513,0,4913,10134,4940,10,2244,6887,9283,0,2459,7738,10134,10,9283,6886,2257,0,10134,7737,2472,10,6887,1124,6886,0,7738,1339,7737,10,9284,4487,524,0,10135,4914,735,10,6888,9284,4511,0,7739,10135,4938,10,6887,2244,4487,0,7738,2459,4914,10,1124,6887,9284,0,1339,7738,10135,10,4533,9285,4510,0,4960,10136,4937,10,2267,6889,9285,0,2482,7740,10136,10,9285,6888,2256,0,10136,7739,2471,10,6889,1124,6888,0,7740,1339,7739,10,9286,4534,536,0,10137,4961,747,10,6890,9286,4514,0,7741,10137,4941,10,6893,2268,4534,0,7744,2483,4961,10,1125,6893,9286,0,1340,7744,10137,10,4488,9287,4515,0,4915,10138,4942,10,2245,6891,9287,0,2460,7742,10138,10,9287,6890,2258,0,10138,7741,2473,10,6891,1125,6890,0,7742,1340,7741,10,9288,4489,525,0,10139,4916,736,10,6892,9288,4513,0,7743,10139,4940,10,6891,2245,4489,0,7742,2460,4916,10,1125,6891,9288,0,1340,7742,10139,10,4535,9289,4512,0,4962,10140,4939,10,2268,6893,9289,0,2483,7744,10140,10,9289,6892,2257,0,10140,7743,2472,10,6893,1125,6892,0,7744,1340,7743,10,9290,4536,538,0,10141,4963,749,10,6894,9290,4518,0,7745,10141,4945,10,6897,2269,4536,0,7748,2484,4963,10,1126,6897,9290,0,1341,7748,10141,10,4494,9291,4519,0,4921,10142,4946,10,2248,6895,9291,0,2463,7746,10142,10,9291,6894,2260,0,10142,7745,2475,10,6895,1126,6894,0,7746,1341,7745,10,9292,4495,529,0,10143,4922,740,10,6896,9292,4472,0,7747,10143,4899,10,6895,2248,4495,0,7746,2463,4922,10,1126,6895,9292,0,1341,7746,10143,10,4537,9293,4473,0,4964,10144,4900,10,2269,6897,9293,0,2484,7748,10144,10,9293,6896,2237,0,10144,7747,2452,10,6897,1126,6896,0,7748,1341,7747,10,9294,4538,542,0,10145,4965,754,10,6898,9294,4461,0,7749,10145,5633,10,6901,2270,4538,0,7752,2485,4965,10,1127,6901,9294,0,1342,7752,10145,10,4496,9295,4460,0,4923,10146,5634,10,2249,6899,9295,0,2464,7750,10146,10,9295,6898,2231,0,10146,7749,2819,10,6899,1127,6898,0,7750,1342,7749,10,9296,4497,530,0,10147,4924,741,10,6900,9296,4519,0,7751,10147,4946,10,6899,2249,4497,0,7750,2464,4924,10,1127,6899,9296,0,1342,7750,10147,10,4539,9297,4518,0,4966,10148,4945,10,2270,6901,9297,0,2485,7752,10148,10,9297,6900,2260,0,10148,7751,2475,10,6901,1127,6900,0,7752,1342,7751,10,9298,4540,544,0,10149,4967,756,10,6902,9298,4473,0,7753,10149,4900,10,6905,2271,4540,0,7756,2486,4967,10,1128,6905,9298,0,1343,7756,10149,10,4500,9299,4472,0,4927,10150,4899,10,2251,6903,9299,0,2466,7754,10150,10,9299,6902,2237,0,10150,7753,2452,10,6903,1128,6902,0,7754,1343,7753,10,9300,4501,517,0,10151,4928,727,10,6904,9300,4505,0,7755,10151,4932,10,6903,2251,4501,0,7754,2466,4928,10,1128,6903,9300,0,1343,7754,10151,10,4541,9301,4504,0,4968,10152,4931,10,2271,6905,9301,0,2486,7756,10152,10,9301,6904,2253,0,10152,7755,2468,10,6905,1128,6904,0,7756,1343,7755,10,9302,4542,539,0,10153,4969,750,10,6906,9302,4520,0,7757,10153,4947,10,6909,2272,4542,0,7760,2487,4969,10,1129,6909,9302,0,1344,7760,10153,10,4720,9303,4521,0,5147,10154,4948,10,2361,6907,9303,0,2576,7758,10154,10,9303,6906,2261,0,10154,7757,2476,10,6907,1129,6906,0,7758,1344,7757,10,9304,4721,573,0,10155,5148,786,10,6908,9304,4682,0,7759,10155,5109,10,6907,2361,4721,0,7758,2576,5148,10,1129,6907,9304,0,1344,7758,10155,10,4543,9305,4683,0,4970,10156,5110,10,2272,6909,9305,0,2487,7760,10156,10,9305,6908,2342,0,10156,7759,2557,10,6909,1129,6908,0,7760,1344,7759,10,9306,4544,540,0,10157,4971,751,10,6910,9306,4522,0,7761,10157,4949,10,6913,2273,4544,0,7764,2488,4971,10,1130,6913,9306,0,1345,7764,10157,10,4722,9307,4523,0,5149,10158,4950,10,2362,6911,9307,0,2577,7762,10158,10,9307,6910,2262,0,10158,7761,2477,10,6911,1130,6910,0,7762,1345,7761,10,9308,4723,574,0,10159,5150,787,10,6912,9308,4684,0,7763,10159,5111,10,6911,2362,4723,0,7762,2577,5150,10,1130,6911,9308,0,1345,7762,10159,10,4545,9309,4685,0,4972,10160,5112,10,2273,6913,9309,0,2488,7764,10160,10,9309,6912,2343,0,10160,7763,2558,10,6913,1130,6912,0,7764,1345,7763,10,9310,4546,541,0,10161,4973,752,10,6914,9310,4524,0,7765,10161,4951,10,6917,2274,4546,0,7768,2489,4973,10,1131,6917,9310,0,1346,7768,10161,10,4724,9311,4525,0,5151,10162,4952,10,2363,6915,9311,0,2578,7766,10162,10,9311,6914,2263,0,10162,7765,2478,10,6915,1131,6914,0,7766,1346,7765,10,9312,4725,582,0,10163,5152,795,10,6916,9312,4523,0,7767,10163,4950,10,6915,2363,4725,0,7766,2578,5152,10,1131,6915,9312,0,1346,7766,10163,10,4547,9313,4522,0,4974,10164,4949,10,2274,6917,9313,0,2489,7768,10164,10,9313,6916,2262,0,10164,7767,2477,10,6917,1131,6916,0,7768,1346,7767,10,9314,4548,542,0,10165,4975,753,10,6918,9314,4526,0,7769,10165,4953,10,6921,2275,4548,0,7772,2490,4975,10,1132,6921,9314,0,1347,7772,10165,10,4726,9315,4527,0,5153,10166,4954,10,2364,6919,9315,0,2579,7770,10166,10,9315,6918,2264,0,10166,7769,2479,10,6919,1132,6918,0,7770,1347,7769,10,9316,4727,575,0,10167,5154,788,10,6920,9316,4686,0,7771,10167,5113,10,6919,2364,4727,0,7770,2579,5154,10,1132,6919,9316,0,1347,7770,10167,10,4549,9317,4687,0,4976,10168,5114,10,2275,6921,9317,0,2490,7772,10168,10,9317,6920,2344,0,10168,7771,2559,10,6921,1132,6920,0,7772,1347,7771,10,9318,4550,532,0,10169,4977,743,10,6922,9318,4685,0,7773,10169,5112,10,6925,2276,4550,0,7776,2491,4977,10,1133,6925,9318,0,1348,7776,10169,10,4728,9319,4684,0,5155,10170,5111,10,2365,6923,9319,0,2580,7774,10170,10,9319,6922,2343,0,10170,7773,2558,10,6923,1133,6922,0,7774,1348,7773,10,9320,4729,576,0,10171,5156,789,10,6924,9320,4688,0,7775,10171,5115,10,6923,2365,4729,0,7774,2580,5156,10,1133,6923,9320,0,1348,7774,10171,10,4551,9321,4689,0,4978,10172,5116,10,2276,6925,9321,0,2491,7776,10172,10,9321,6924,2345,0,10172,7775,2560,10,6925,1133,6924,0,7776,1348,7775,10,9322,4552,543,0,10173,4979,755,10,6926,9322,4528,0,7777,10173,4955,10,6929,2277,4552,0,7780,2492,4979,10,1134,6929,9322,0,1349,7780,10173,10,4730,9323,4529,0,5157,10174,4956,10,2366,6927,9323,0,2581,7778,10174,10,9323,6926,2265,0,10174,7777,2480,10,6927,1134,6926,0,7778,1349,7777,10,9324,4731,579,0,10175,5158,792,10,6928,9324,4694,0,7779,10175,5121,10,6927,2366,4731,0,7778,2581,5158,10,1134,6927,9324,0,1349,7778,10175,10,4553,9325,4695,0,4980,10176,5122,10,2277,6929,9325,0,2492,7780,10176,10,9325,6928,2348,0,10176,7779,2563,10,6929,1134,6928,0,7780,1349,7779,10,9326,4554,536,0,10177,4981,747,10,6930,9326,4693,0,7781,10177,5120,10,6933,2278,4554,0,7784,2493,4981,10,1135,6933,9326,0,1350,7784,10177,10,4732,9327,4692,0,5159,10178,5119,10,2367,6931,9327,0,2582,7782,10178,10,9327,6930,2347,0,10178,7781,2562,10,6931,1135,6930,0,7782,1350,7781,10,9328,4733,585,0,10179,5160,799,10,6932,9328,4529,0,7783,10179,4956,10,6931,2367,4733,0,7782,2582,5160,10,1135,6931,9328,0,1350,7782,10179,10,4555,9329,4528,0,4982,10180,4955,10,2278,6933,9329,0,2493,7784,10180,10,9329,6932,2265,0,10180,7783,2480,10,6933,1135,6932,0,7784,1350,7783,10,9330,4556,537,0,10181,4983,748,10,6934,9330,4695,0,7785,10181,5122,10,6937,2279,4556,0,7788,2494,4983,10,1136,6937,9330,0,1351,7788,10181,10,4734,9331,4694,0,5161,10182,5121,10,2368,6935,9331,0,2583,7786,10182,10,9331,6934,2348,0,10182,7785,2563,10,6935,1136,6934,0,7786,1351,7785,10,9332,4735,581,0,10183,5162,794,10,6936,9332,4521,0,7787,10183,4948,10,6935,2368,4735,0,7786,2583,5162,10,1136,6935,9332,0,1351,7786,10183,10,4557,9333,4520,0,4984,10184,4947,10,2279,6937,9333,0,2494,7788,10184,10,9333,6936,2261,0,10184,7787,2476,10,6937,1136,6936,0,7788,1351,7787,10,9334,4558,533,0,10185,4985,744,10,6938,9334,4687,0,7789,10185,5114,10,6941,2280,4558,0,7792,2495,4985,10,1137,6941,9334,0,1352,7792,10185,10,4736,9335,4686,0,5163,10186,5113,10,2369,6939,9335,0,2584,7790,10186,10,9335,6938,2344,0,10186,7789,2559,10,6939,1137,6938,0,7790,1352,7789,10,9336,4737,583,0,10187,5164,796,10,6940,9336,4525,0,7791,10187,4952,10,6939,2369,4737,0,7790,2584,5164,10,1137,6939,9336,0,1352,7790,10187,10,4559,9337,4524,0,4986,10188,4951,10,2280,6941,9337,0,2495,7792,10188,10,9337,6940,2263,0,10188,7791,2478,10,6941,1137,6940,0,7792,1352,7791,10,9338,4561,546,0,10189,4988,758,10,6942,9338,4622,0,7793,10189,5049,10,6945,2281,4561,0,7796,2496,4988,10,1138,6945,9338,0,1353,7796,10189,10,4572,9339,4623,0,4999,10190,5050,10,2287,6943,9339,0,2502,7794,10190,10,9339,6942,2312,0,10190,7793,2527,10,6943,1138,6942,0,7794,1353,7793,10,9340,4573,552,0,10191,5000,764,10,6944,9340,4620,0,7795,10191,5047,10,6943,2287,4573,0,7794,2502,5000,10,1138,6943,9340,0,1353,7794,10191,10,4560,9341,4621,0,4987,10192,5048,10,2281,6945,9341,0,2496,7796,10192,10,9341,6944,2311,0,10192,7795,2526,10,6945,1138,6944,0,7796,1353,7795,10,9342,4588,310,0,10193,5015,399,10,6946,9342,3600,0,7797,10193,4027,10,6949,2295,4588,0,7800,2510,5015,10,1139,6949,9342,0,1354,7800,10193,10,4590,9343,3601,0,5017,10194,4028,10,2296,6947,9343,0,2511,7798,10194,10,9343,6946,1801,0,10194,7797,2016,10,6947,1139,6946,0,7798,1354,7797,10,9344,4591,560,0,10195,5018,772,10,6948,9344,4654,0,7799,10195,5081,10,6947,2296,4591,0,7798,2511,5018,10,1139,6947,9344,0,1354,7798,10195,10,4589,9345,4655,0,5016,10196,5082,10,2295,6949,9345,0,2510,7800,10196,10,9345,6948,2328,0,10196,7799,2543,10,6949,1139,6948,0,7800,1354,7799,10,9346,4590,309,0,10197,5017,398,10,6950,9346,3602,0,7801,10197,4029,10,6953,2296,4590,0,7804,2511,5017,10,1140,6953,9346,0,1355,7804,10197,10,4592,9347,3603,0,5019,10198,4030,10,2297,6951,9347,0,2512,7802,10198,10,9347,6950,1802,0,10198,7801,2017,10,6951,1140,6950,0,7802,1355,7801,10,9348,4593,561,0,10199,5020,773,10,6952,9348,4656,0,7803,10199,5083,10,6951,2297,4593,0,7802,2512,5020,10,1140,6951,9348,0,1355,7802,10199,10,4591,9349,4657,0,5018,10200,5084,10,2296,6953,9349,0,2511,7804,10200,10,9349,6952,2329,0,10200,7803,2544,10,6953,1140,6952,0,7804,1355,7803,10,9350,4592,311,0,10201,5019,400,10,6954,9350,3674,0,7805,10201,4101,10,6957,2297,4592,0,7808,2512,5019,10,1141,6957,9350,0,1356,7808,10201,10,4594,9351,3675,0,5021,10202,4102,10,2298,6955,9351,0,2513,7806,10202,10,9351,6954,1838,0,10202,7805,2053,10,6955,1141,6954,0,7806,1356,7805,10,9352,4595,562,0,10203,5022,774,10,6956,9352,4658,0,7807,10203,5085,10,6955,2298,4595,0,7806,2513,5022,10,1141,6955,9352,0,1356,7806,10203,10,4593,9353,4659,0,5020,10204,5086,10,2297,6957,9353,0,2512,7808,10204,10,9353,6956,2330,0,10204,7807,2545,10,6957,1141,6956,0,7808,1356,7807,10,9354,4594,329,0,10205,5021,420,10,6958,9354,3680,0,7809,10205,4107,10,6961,2298,4594,0,7812,2513,5021,10,1142,6961,9354,0,1357,7812,10205,10,4596,9355,3681,0,5023,10206,4108,10,2299,6959,9355,0,2514,7810,10206,10,9355,6958,1841,0,10206,7809,2056,10,6959,1142,6958,0,7810,1357,7809,10,9356,4597,563,0,10207,5024,775,10,6960,9356,4660,0,7811,10207,5087,10,6959,2299,4597,0,7810,2514,5024,10,1142,6959,9356,0,1357,7810,10207,10,4595,9357,4661,0,5022,10208,5088,10,2298,6961,9357,0,2513,7812,10208,10,9357,6960,2331,0,10208,7811,2546,10,6961,1142,6960,0,7812,1357,7811,10,9358,4596,330,0,10209,5023,421,10,6962,9358,3684,0,7813,10209,4111,10,6965,2299,4596,0,7816,2514,5023,10,1143,6965,9358,0,1358,7816,10209,10,4598,9359,3685,0,5025,10210,4112,10,2300,6963,9359,0,2515,7814,10210,10,9359,6962,1843,0,10210,7813,2058,10,6963,1143,6962,0,7814,1358,7813,10,9360,4599,564,0,10211,5026,776,10,6964,9360,4662,0,7815,10211,5089,10,6963,2300,4599,0,7814,2515,5026,10,1143,6963,9360,0,1358,7814,10211,10,4597,9361,4663,0,5024,10212,5090,10,2299,6965,9361,0,2514,7816,10212,10,9361,6964,2332,0,10212,7815,2547,10,6965,1143,6964,0,7816,1358,7815,10,9362,4598,322,0,10213,5025,411,10,6966,9362,3630,0,7817,10213,4057,10,6969,2300,4598,0,7820,2515,5025,10,1144,6969,9362,0,1359,7820,10213,10,4600,9363,3631,0,5027,10214,4058,10,2301,6967,9363,0,2516,7818,10214,10,9363,6966,1816,0,10214,7817,2031,10,6967,1144,6966,0,7818,1359,7817,10,9364,4601,565,0,10215,5028,777,10,6968,9364,4664,0,7819,10215,5091,10,6967,2301,4601,0,7818,2516,5028,10,1144,6967,9364,0,1359,7818,10215,10,4599,9365,4665,0,5026,10216,5092,10,2300,6969,9365,0,2515,7820,10216,10,9365,6968,2333,0,10216,7819,2548,10,6969,1144,6968,0,7820,1359,7819,10,9366,4600,319,0,10217,5027,408,10,6970,9366,3622,0,7821,10217,4049,10,6973,2301,4600,0,7824,2516,5027,10,1145,6973,9366,0,1360,7824,10217,10,4602,9367,3623,0,5029,10218,4050,10,2302,6971,9367,0,2517,7822,10218,10,9367,6970,1812,0,10218,7821,2027,10,6971,1145,6970,0,7822,1360,7821,10,9368,4603,566,0,10219,5030,778,10,6972,9368,4666,0,7823,10219,5093,10,6971,2302,4603,0,7822,2517,5030,10,1145,6971,9368,0,1360,7822,10219,10,4601,9369,4667,0,5028,10220,5094,10,2301,6973,9369,0,2516,7824,10220,10,9369,6972,2334,0,10220,7823,2549,10,6973,1145,6972,0,7824,1360,7823,10,9370,4602,317,0,10221,5029,406,10,6974,9370,3616,0,7825,10221,4043,10,6977,2302,4602,0,7828,2517,5029,10,1146,6977,9370,0,1361,7828,10221,10,4604,9371,3617,0,5031,10222,4044,10,2303,6975,9371,0,2518,7826,10222,10,9371,6974,1809,0,10222,7825,2024,10,6975,1146,6974,0,7826,1361,7825,10,9372,4605,567,0,10223,5032,779,10,6976,9372,4668,0,7827,10223,5095,10,6975,2303,4605,0,7826,2518,5032,10,1146,6975,9372,0,1361,7826,10223,10,4603,9373,4669,0,5030,10224,5096,10,2302,6977,9373,0,2517,7828,10224,10,9373,6976,2335,0,10224,7827,2550,10,6977,1146,6976,0,7828,1361,7827,10,9374,4604,316,0,10225,5031,405,10,6978,9374,3618,0,7829,10225,4045,10,6981,2303,4604,0,7832,2518,5031,10,1147,6981,9374,0,1362,7832,10225,10,4606,9375,3619,0,5033,10226,4046,10,2304,6979,9375,0,2519,7830,10226,10,9375,6978,1810,0,10226,7829,2025,10,6979,1147,6978,0,7830,1362,7829,10,9376,4607,568,0,10227,5034,780,10,6980,9376,4670,0,7831,10227,5097,10,6979,2304,4607,0,7830,2519,5034,10,1147,6979,9376,0,1362,7830,10227,10,4605,9377,4671,0,5032,10228,5098,10,2303,6981,9377,0,2518,7832,10228,10,9377,6980,2336,0,10228,7831,2551,10,6981,1147,6980,0,7832,1362,7831,10,9378,4606,318,0,10229,5033,407,10,6982,9378,3664,0,7833,10229,4091,10,6985,2304,4606,0,7836,2519,5033,10,1148,6985,9378,0,1363,7836,10229,10,4608,9379,3665,0,5035,10230,4092,10,2305,6983,9379,0,2520,7834,10230,10,9379,6982,1833,0,10230,7833,2048,10,6983,1148,6982,0,7834,1363,7833,10,9380,4609,569,0,10231,5036,781,10,6984,9380,4672,0,7835,10231,5099,10,6983,2305,4609,0,7834,2520,5036,10,1148,6983,9380,0,1363,7834,10231,10,4607,9381,4673,0,5034,10232,5100,10,2304,6985,9381,0,2519,7836,10232,10,9381,6984,2337,0,10232,7835,2552,10,6985,1148,6984,0,7836,1363,7835,10,9382,4608,313,0,10233,5035,402,10,6986,9382,3604,0,7837,10233,4031,10,6989,2305,4608,0,7840,2520,5035,10,1149,6989,9382,0,1364,7840,10233,10,4610,9383,3605,0,5037,10234,4032,10,2306,6987,9383,0,2521,7838,10234,10,9383,6986,1803,0,10234,7837,2018,10,6987,1149,6986,0,7838,1364,7837,10,9384,4611,570,0,10235,5038,782,10,6988,9384,4674,0,7839,10235,5101,10,6987,2306,4611,0,7838,2521,5038,10,1149,6987,9384,0,1364,7838,10235,10,4609,9385,4675,0,5036,10236,5102,10,2305,6989,9385,0,2520,7840,10236,10,9385,6988,2338,0,10236,7839,2553,10,6989,1149,6988,0,7840,1364,7839,10,9386,4610,312,0,10237,5037,401,10,6990,9386,3608,0,7841,10237,4035,10,6993,2306,4610,0,7844,2521,5037,10,1150,6993,9386,0,1365,7844,10237,10,4612,9387,3609,0,5039,10238,4036,10,2307,6991,9387,0,2522,7842,10238,10,9387,6990,1805,0,10238,7841,2020,10,6991,1150,6990,0,7842,1365,7841,10,9388,4613,571,0,10239,5040,783,10,6992,9388,4676,0,7843,10239,5103,10,6991,2307,4613,0,7842,2522,5040,10,1150,6991,9388,0,1365,7842,10239,10,4611,9389,4677,0,5038,10240,5104,10,2306,6993,9389,0,2521,7844,10240,10,9389,6992,2339,0,10240,7843,2554,10,6993,1150,6992,0,7844,1365,7843,10,9390,4612,314,0,10241,5638,416,10,6994,9390,3654,0,7845,10241,4081,10,6997,2307,4612,0,7848,2821,5638,10,1151,6997,9390,0,1366,7848,10241,10,4614,9391,3655,0,5041,10242,4082,10,2308,6995,9391,0,2523,7846,10242,10,9391,6994,1828,0,10242,7845,2043,10,6995,1151,6994,0,7846,1366,7845,10,9392,4615,572,0,10243,5042,785,10,6996,9392,4678,0,7847,10243,5105,10,6995,2308,4615,0,7846,2523,5042,10,1151,6995,9392,0,1366,7846,10243,10,4613,9393,4679,0,5637,10244,5106,10,2307,6997,9393,0,2821,7848,10244,10,9393,6996,2340,0,10244,7847,2555,10,6997,1151,6996,0,7848,1366,7847,10,9394,4614,327,0,10245,5041,417,10,6998,9394,3682,0,7849,10245,4109,10,7001,2308,4614,0,7852,2523,5041,10,1152,7001,9394,0,1367,7852,10245,10,4588,9395,3683,0,5015,10246,4110,10,2295,6999,9395,0,2510,7850,10246,10,9395,6998,1842,0,10246,7849,2057,10,6999,1152,6998,0,7850,1367,7849,10,9396,4589,559,0,10247,5016,771,10,7000,9396,4680,0,7851,10247,5107,10,6999,2295,4589,0,7850,2510,5016,10,1152,6999,9396,0,1367,7850,10247,10,4615,9397,4681,0,5042,10248,5108,10,2308,7001,9397,0,2523,7852,10248,10,9397,7000,2341,0,10248,7851,2556,10,7001,1152,7000,0,7852,1367,7851,10,9398,4616,554,0,10249,5043,766,10,7002,9398,4578,0,7853,10249,5005,10,7005,2309,4616,0,7856,2524,5043,10,1153,7005,9398,0,1368,7856,10249,10,4580,9399,4579,0,5007,10250,5006,10,2291,7003,9399,0,2506,7854,10250,10,9399,7002,2290,0,10250,7853,2505,10,7003,1153,7002,0,7854,1368,7853,10,9400,4581,556,0,10251,5008,768,10,7004,9400,4582,0,7855,10251,5009,10,7003,2291,4581,0,7854,2506,5008,10,1153,7003,9400,0,1368,7854,10251,10,4617,9401,4583,0,5044,10252,5010,10,2309,7005,9401,0,2524,7856,10252,10,9401,7004,2292,0,10252,7855,2507,10,7005,1153,7004,0,7856,1368,7855,10,9402,4618,553,0,10253,5045,765,10,7006,9402,4576,0,7857,10253,5003,10,7009,2310,4618,0,7860,2525,5045,10,1154,7009,9402,0,1369,7860,10253,10,4616,9403,4577,0,5043,10254,5004,10,2309,7007,9403,0,2524,7858,10254,10,9403,7006,2289,0,10254,7857,2504,10,7007,1154,7006,0,7858,1369,7857,10,9404,4617,557,0,10255,5044,769,10,7008,9404,4584,0,7859,10255,5011,10,7007,2309,4617,0,7858,2524,5044,10,1154,7007,9404,0,1369,7858,10255,10,4619,9405,4585,0,5046,10256,5012,10,2310,7009,9405,0,2525,7860,10256,10,9405,7008,2293,0,10256,7859,2508,10,7009,1154,7008,0,7860,1369,7859,10,9406,4620,552,0,10257,5047,764,10,7010,9406,4574,0,7861,10257,5001,10,7013,2311,4620,0,7864,2526,5047,10,1155,7013,9406,0,1370,7864,10257,10,4618,9407,4575,0,5045,10258,5002,10,2310,7011,9407,0,2525,7862,10258,10,9407,7010,2288,0,10258,7861,2503,10,7011,1155,7010,0,7862,1370,7861,10,9408,4619,558,0,10259,5046,770,10,7012,9408,4586,0,7863,10259,5013,10,7011,2310,4619,0,7862,2525,5046,10,1155,7011,9408,0,1370,7862,10259,10,4621,9409,4587,0,5048,10260,5014,10,2311,7013,9409,0,2526,7864,10260,10,9409,7012,2294,0,10260,7863,2509,10,7013,1155,7012,0,7864,1370,7863,10,9410,4622,546,0,10261,5049,758,10,7014,9410,4562,0,7865,10261,4989,10,7017,2312,4622,0,7868,2527,5049,10,1156,7017,9410,0,1371,7868,10261,10,4624,9411,4563,0,5051,10262,4990,10,2313,7015,9411,0,2528,7866,10262,10,9411,7014,2282,0,10262,7865,2497,10,7015,1156,7014,0,7866,1371,7865,10,9412,4625,550,0,10263,5052,762,10,7016,9412,4570,0,7867,10263,4997,10,7015,2313,4625,0,7866,2528,5052,10,1156,7015,9412,0,1371,7866,10263,10,4623,9413,4571,0,5050,10264,4998,10,2312,7017,9413,0,2527,7868,10264,10,9413,7016,2286,0,10264,7867,2501,10,7017,1156,7016,0,7868,1371,7867,10,9414,4624,547,0,10265,5051,759,10,7018,9414,4564,0,7869,10265,4991,10,7021,2313,4624,0,7872,2528,5051,10,1157,7021,9414,0,1372,7872,10265,10,4566,9415,4565,0,4993,10266,4992,10,2284,7019,9415,0,2499,7870,10266,10,9415,7018,2283,0,10266,7869,2498,10,7019,1157,7018,0,7870,1372,7869,10,9416,4567,549,0,10267,4994,761,10,7020,9416,4568,0,7871,10267,4995,10,7019,2284,4567,0,7870,2499,4994,10,1157,7019,9416,0,1372,7870,10267,10,4625,9417,4569,0,5052,10268,4996,10,2313,7021,9417,0,2528,7872,10268,10,9417,7020,2285,0,10268,7871,2500,10,7021,1157,7020,0,7872,1372,7871,10,9418,4654,560,0,10269,5081,772,10,7022,9418,4628,0,7873,10269,5055,10,7025,2328,4654,0,7876,2543,5081,10,1158,7025,9418,0,1373,7876,10269,10,4561,9419,4629,0,4988,10270,5056,10,2281,7023,9419,0,2496,7874,10270,10,9419,7022,2315,0,10270,7873,2530,10,7023,1158,7022,0,7874,1373,7873,10,9420,4560,545,0,10271,4987,757,10,7024,9420,4627,0,7875,10271,5054,10,7023,2281,4560,0,7874,2496,4987,10,1158,7023,9420,0,1373,7874,10271,10,4655,9421,4626,0,5082,10272,5053,10,2328,7025,9421,0,2543,7876,10272,10,9421,7024,2314,0,10272,7875,2529,10,7025,1158,7024,0,7876,1373,7875,10,9422,4656,561,0,10273,5083,773,10,7026,9422,4630,0,7877,10273,5057,10,7029,2329,4656,0,7880,2544,5083,10,1159,7029,9422,0,1374,7880,10273,10,4563,9423,4631,0,4990,10274,5058,10,2282,7027,9423,0,2497,7878,10274,10,9423,7026,2316,0,10274,7877,2531,10,7027,1159,7026,0,7878,1374,7877,10,9424,4562,546,0,10275,4989,758,10,7028,9424,4629,0,7879,10275,5056,10,7027,2282,4562,0,7878,2497,4989,10,1159,7027,9424,0,1374,7878,10275,10,4657,9425,4628,0,5084,10276,5055,10,2329,7029,9425,0,2544,7880,10276,10,9425,7028,2315,0,10276,7879,2530,10,7029,1159,7028,0,7880,1374,7879,10,9426,4658,562,0,10277,5085,774,10,7030,9426,4632,0,7881,10277,5059,10,7033,2330,4658,0,7884,2545,5085,10,1160,7033,9426,0,1375,7884,10277,10,4565,9427,4633,0,4992,10278,5060,10,2283,7031,9427,0,2498,7882,10278,10,9427,7030,2317,0,10278,7881,2532,10,7031,1160,7030,0,7882,1375,7881,10,9428,4564,547,0,10279,4991,759,10,7032,9428,4631,0,7883,10279,5058,10,7031,2283,4564,0,7882,2498,4991,10,1160,7031,9428,0,1375,7882,10279,10,4659,9429,4630,0,5086,10280,5057,10,2330,7033,9429,0,2545,7884,10280,10,9429,7032,2316,0,10280,7883,2531,10,7033,1160,7032,0,7884,1375,7883,10,9430,4660,563,0,10281,5087,775,10,7034,9430,4634,0,7885,10281,5061,10,7037,2331,4660,0,7888,2546,5087,10,1161,7037,9430,0,1376,7888,10281,10,4567,9431,4635,0,4994,10282,5062,10,2284,7035,9431,0,2499,7886,10282,10,9431,7034,2318,0,10282,7885,2533,10,7035,1161,7034,0,7886,1376,7885,10,9432,4566,548,0,10283,4993,760,10,7036,9432,4633,0,7887,10283,5060,10,7035,2284,4566,0,7886,2499,4993,10,1161,7035,9432,0,1376,7886,10283,10,4661,9433,4632,0,5088,10284,5059,10,2331,7037,9433,0,2546,7888,10284,10,9433,7036,2317,0,10284,7887,2532,10,7037,1161,7036,0,7888,1376,7887,10,9434,4662,564,0,10285,5089,776,10,7038,9434,4636,0,7889,10285,5063,10,7041,2332,4662,0,7892,2547,5089,10,1162,7041,9434,0,1377,7892,10285,10,4569,9435,4637,0,4996,10286,5064,10,2285,7039,9435,0,2500,7890,10286,10,9435,7038,2319,0,10286,7889,2534,10,7039,1162,7038,0,7890,1377,7889,10,9436,4568,549,0,10287,4995,761,10,7040,9436,4635,0,7891,10287,5062,10,7039,2285,4568,0,7890,2500,4995,10,1162,7039,9436,0,1377,7890,10287,10,4663,9437,4634,0,5090,10288,5061,10,2332,7041,9437,0,2547,7892,10288,10,9437,7040,2318,0,10288,7891,2533,10,7041,1162,7040,0,7892,1377,7891,10,9438,4664,565,0,10289,5091,777,10,7042,9438,4638,0,7893,10289,5065,10,7045,2333,4664,0,7896,2548,5091,10,1163,7045,9438,0,1378,7896,10289,10,4571,9439,4639,0,4998,10290,5066,10,2286,7043,9439,0,2501,7894,10290,10,9439,7042,2320,0,10290,7893,2535,10,7043,1163,7042,0,7894,1378,7893,10,9440,4570,550,0,10291,4997,762,10,7044,9440,4637,0,7895,10291,5064,10,7043,2286,4570,0,7894,2501,4997,10,1163,7043,9440,0,1378,7894,10291,10,4665,9441,4636,0,5092,10292,5063,10,2333,7045,9441,0,2548,7896,10292,10,9441,7044,2319,0,10292,7895,2534,10,7045,1163,7044,0,7896,1378,7895,10,9442,4666,566,0,10293,5093,778,10,7046,9442,4640,0,7897,10293,5067,10,7049,2334,4666,0,7900,2549,5093,10,1164,7049,9442,0,1379,7900,10293,10,4573,9443,4641,0,5000,10294,5068,10,2287,7047,9443,0,2502,7898,10294,10,9443,7046,2321,0,10294,7897,2536,10,7047,1164,7046,0,7898,1379,7897,10,9444,4572,551,0,10295,4999,763,10,7048,9444,4639,0,7899,10295,5066,10,7047,2287,4572,0,7898,2502,4999,10,1164,7047,9444,0,1379,7898,10295,10,4667,9445,4638,0,5094,10296,5065,10,2334,7049,9445,0,2549,7900,10296,10,9445,7048,2320,0,10296,7899,2535,10,7049,1164,7048,0,7900,1379,7899,10,9446,4668,567,0,10297,5095,779,10,7050,9446,4642,0,7901,10297,5069,10,7053,2335,4668,0,7904,2550,5095,10,1165,7053,9446,0,1380,7904,10297,10,4575,9447,4643,0,5002,10298,5070,10,2288,7051,9447,0,2503,7902,10298,10,9447,7050,2322,0,10298,7901,2537,10,7051,1165,7050,0,7902,1380,7901,10,9448,4574,552,0,10299,5001,764,10,7052,9448,4641,0,7903,10299,5068,10,7051,2288,4574,0,7902,2503,5001,10,1165,7051,9448,0,1380,7902,10299,10,4669,9449,4640,0,5096,10300,5067,10,2335,7053,9449,0,2550,7904,10300,10,9449,7052,2321,0,10300,7903,2536,10,7053,1165,7052,0,7904,1380,7903,10,9450,4670,568,0,10301,5097,780,10,7054,9450,4644,0,7905,10301,5071,10,7057,2336,4670,0,7908,2551,5097,10,1166,7057,9450,0,1381,7908,10301,10,4577,9451,4645,0,5004,10302,5072,10,2289,7055,9451,0,2504,7906,10302,10,9451,7054,2323,0,10302,7905,2538,10,7055,1166,7054,0,7906,1381,7905,10,9452,4576,553,0,10303,5003,765,10,7056,9452,4643,0,7907,10303,5070,10,7055,2289,4576,0,7906,2504,5003,10,1166,7055,9452,0,1381,7906,10303,10,4671,9453,4642,0,5098,10304,5069,10,2336,7057,9453,0,2551,7908,10304,10,9453,7056,2322,0,10304,7907,2537,10,7057,1166,7056,0,7908,1381,7907,10,9454,4672,569,0,10305,5099,781,10,7058,9454,4646,0,7909,10305,5073,10,7061,2337,4672,0,7912,2552,5099,10,1167,7061,9454,0,1382,7912,10305,10,4579,9455,4647,0,5006,10306,5074,10,2290,7059,9455,0,2505,7910,10306,10,9455,7058,2324,0,10306,7909,2539,10,7059,1167,7058,0,7910,1382,7909,10,9456,4578,554,0,10307,5005,766,10,7060,9456,4645,0,7911,10307,5072,10,7059,2290,4578,0,7910,2505,5005,10,1167,7059,9456,0,1382,7910,10307,10,4673,9457,4644,0,5100,10308,5071,10,2337,7061,9457,0,2552,7912,10308,10,9457,7060,2323,0,10308,7911,2538,10,7061,1167,7060,0,7912,1382,7911,10,9458,4674,570,0,10309,5101,782,10,7062,9458,4648,0,7913,10309,5075,10,7065,2338,4674,0,7916,2553,5101,10,1168,7065,9458,0,1383,7916,10309,10,4581,9459,4649,0,5008,10310,5076,10,2291,7063,9459,0,2506,7914,10310,10,9459,7062,2325,0,10310,7913,2540,10,7063,1168,7062,0,7914,1383,7913,10,9460,4580,555,0,10311,5007,767,10,7064,9460,4647,0,7915,10311,5074,10,7063,2291,4580,0,7914,2506,5007,10,1168,7063,9460,0,1383,7914,10311,10,4675,9461,4646,0,5102,10312,5073,10,2338,7065,9461,0,2553,7916,10312,10,9461,7064,2324,0,10312,7915,2539,10,7065,1168,7064,0,7916,1383,7915,10,9462,4676,571,0,10313,5103,783,10,7066,9462,4650,0,7917,10313,5077,10,7069,2339,4676,0,7920,2554,5103,10,1169,7069,9462,0,1384,7920,10313,10,4583,9463,4651,0,5010,10314,5078,10,2292,7067,9463,0,2507,7918,10314,10,9463,7066,2326,0,10314,7917,2541,10,7067,1169,7066,0,7918,1384,7917,10,9464,4582,556,0,10315,5009,768,10,7068,9464,4649,0,7919,10315,5076,10,7067,2292,4582,0,7918,2507,5009,10,1169,7067,9464,0,1384,7918,10315,10,4677,9465,4648,0,5104,10316,5075,10,2339,7069,9465,0,2554,7920,10316,10,9465,7068,2325,0,10316,7919,2540,10,7069,1169,7068,0,7920,1384,7919,10,9466,4678,572,0,10317,5105,785,10,7070,9466,4652,0,7921,10317,5079,10,7073,2340,4678,0,7924,2555,5105,10,1170,7073,9466,0,1385,7924,10317,10,4585,9467,4653,0,5012,10318,5080,10,2293,7071,9467,0,2508,7922,10318,10,9467,7070,2327,0,10318,7921,2542,10,7071,1170,7070,0,7922,1385,7921,10,9468,4584,557,0,10319,5011,769,10,7072,9468,4651,0,7923,10319,5639,10,7071,2293,4584,0,7922,2508,5011,10,1170,7071,9468,0,1385,7922,10319,10,4679,9469,4650,0,5106,10320,5640,10,2340,7073,9469,0,2555,7924,10320,10,9469,7072,2326,0,10320,7923,2822,10,7073,1170,7072,0,7924,1385,7923,10,9470,4680,559,0,10321,5107,771,10,7074,9470,4626,0,7925,10321,5053,10,7077,2341,4680,0,7928,2556,5107,10,1171,7077,9470,0,1386,7928,10321,10,4587,9471,4627,0,5014,10322,5054,10,2294,7075,9471,0,2509,7926,10322,10,9471,7074,2314,0,10322,7925,2529,10,7075,1171,7074,0,7926,1386,7925,10,9472,4586,558,0,10323,5013,770,10,7076,9472,4653,0,7927,10323,5080,10,7075,2294,4586,0,7926,2509,5013,10,1171,7075,9472,0,1386,7926,10323,10,4681,9473,4652,0,5108,10324,5079,10,2341,7077,9473,0,2556,7928,10324,10,9473,7076,2327,0,10324,7927,2542,10,7077,1171,7076,0,7928,1386,7927,10,9474,4710,577,0,10325,5137,790,10,7078,9474,4690,0,7929,10325,5117,10,7081,2356,4710,0,7932,2571,5137,10,1172,7081,9474,0,1387,7932,10325,10,4532,9475,4691,0,4959,10326,5118,10,2267,7079,9475,0,2482,7930,10326,10,9475,7078,2346,0,10326,7929,2561,10,7079,1172,7078,0,7930,1387,7929,10,9476,4533,534,0,10327,4960,745,10,7080,9476,4689,0,7931,10327,5116,10,7079,2267,4533,0,7930,2482,4960,10,1172,7079,9476,0,1387,7930,10327,10,4711,9477,4688,0,5138,10328,5115,10,2356,7081,9477,0,2571,7932,10328,10,9477,7080,2345,0,10328,7931,2560,10,7081,1172,7080,0,7932,1387,7931,10,9478,4712,578,0,10329,5139,791,10,7082,9478,4692,0,7933,10329,5119,10,7085,2357,4712,0,7936,2572,5139,10,1173,7085,9478,0,1388,7936,10329,10,4534,9479,4693,0,4961,10330,5120,10,2268,7083,9479,0,2483,7934,10330,10,9479,7082,2347,0,10330,7933,2562,10,7083,1173,7082,0,7934,1388,7933,10,9480,4535,535,0,10331,4962,746,10,7084,9480,4691,0,7935,10331,5118,10,7083,2268,4535,0,7934,2483,4962,10,1173,7083,9480,0,1388,7934,10331,10,4713,9481,4690,0,5140,10332,5117,10,2357,7085,9481,0,2572,7936,10332,10,9481,7084,2346,0,10332,7935,2561,10,7085,1173,7084,0,7936,1388,7935,10,9482,4714,580,0,10333,5141,793,10,7086,9482,4696,0,7937,10333,5123,10,7089,2358,4714,0,7940,2573,5141,10,1174,7089,9482,0,1389,7940,10333,10,4536,9483,4697,0,4963,10334,5124,10,2269,7087,9483,0,2484,7938,10334,10,9483,7086,2349,0,10334,7937,2564,10,7087,1174,7086,0,7938,1389,7937,10,9484,4537,544,0,10335,4964,756,10,7088,9484,4530,0,7939,10335,4957,10,7087,2269,4537,0,7938,2484,4964,10,1174,7087,9484,0,1389,7938,10335,10,4715,9485,4531,0,5142,10336,4958,10,2358,7089,9485,0,2573,7940,10336,10,9485,7088,2266,0,10336,7939,2481,10,7089,1174,7088,0,7940,1389,7939,10,9486,4716,584,0,10337,5143,798,10,7090,9486,4527,0,7941,10337,5635,10,7093,2359,4716,0,7944,2574,5143,10,1175,7093,9486,0,1390,7944,10337,10,4538,9487,4526,0,4965,10338,5636,10,2270,7091,9487,0,2485,7942,10338,10,9487,7090,2264,0,10338,7941,2820,10,7091,1175,7090,0,7942,1390,7941,10,9488,4539,538,0,10339,4966,749,10,7092,9488,4697,0,7943,10339,5124,10,7091,2270,4539,0,7942,2485,4966,10,1175,7091,9488,0,1390,7942,10339,10,4717,9489,4696,0,5144,10340,5123,10,2359,7093,9489,0,2574,7944,10340,10,9489,7092,2349,0,10340,7943,2564,10,7093,1175,7092,0,7944,1390,7943,10,9490,4718,586,0,10341,5145,800,10,7094,9490,4531,0,7945,10341,4958,10,7097,2360,4718,0,7948,2575,5145,10,1176,7097,9490,0,1391,7948,10341,10,4540,9491,4530,0,4967,10342,4957,10,2271,7095,9491,0,2486,7946,10342,10,9491,7094,2266,0,10342,7945,2481,10,7095,1176,7094,0,7946,1391,7945,10,9492,4541,531,0,10343,4968,742,10,7096,9492,4683,0,7947,10343,5110,10,7095,2271,4541,0,7946,2486,4968,10,1176,7095,9492,0,1391,7946,10343,10,4719,9493,4682,0,5146,10344,5109,10,2360,7097,9493,0,2575,7948,10344,10,9493,7096,2342,0,10344,7947,2557,10,7097,1176,7096,0,7948,1391,7947,10,9494,4720,581,0,10345,5147,794,10,7098,9494,4698,0,7949,10345,5125,10,7101,2361,4720,0,7952,2576,5147,10,1177,7101,9494,0,1392,7952,10345,10,3603,9495,4699,0,4030,10346,5126,10,1802,7099,9495,0,2017,7950,10346,10,9495,7098,2350,0,10346,7949,2565,10,7099,1177,7098,0,7950,1392,7949,10,9496,3602,309,0,10347,4029,398,10,7100,9496,3584,0,7951,10347,4011,10,7099,1802,3602,0,7950,2017,4029,10,1177,7099,9496,0,1392,7950,10347,10,4721,9497,3585,0,5148,10348,4012,10,2361,7101,9497,0,2576,7952,10348,10,9497,7100,1793,0,10348,7951,2008,10,7101,1177,7100,0,7952,1392,7951,10,9498,4722,582,0,10349,5149,795,10,7102,9498,4700,0,7953,10349,5127,10,7105,2362,4722,0,7956,2577,5149,10,1178,7105,9498,0,1393,7956,10349,10,3619,9499,4701,0,4046,10350,5128,10,1810,7103,9499,0,2025,7954,10350,10,9499,7102,2351,0,10350,7953,2566,10,7103,1178,7102,0,7954,1393,7953,10,9500,3618,316,0,10351,4045,405,10,7104,9500,3592,0,7955,10351,4019,10,7103,1810,3618,0,7954,2025,4045,10,1178,7103,9500,0,1393,7954,10351,10,4723,9501,3593,0,5150,10352,4020,10,2362,7105,9501,0,2577,7956,10352,10,9501,7104,1797,0,10352,7955,2012,10,7105,1178,7104,0,7956,1393,7955,10,9502,4724,583,0,10353,5151,796,10,7106,9502,4702,0,7957,10353,5129,10,7109,2363,4724,0,7960,2578,5151,10,1179,7109,9502,0,1394,7960,10353,10,3665,9503,4703,0,4092,10354,5130,10,1833,7107,9503,0,2048,7958,10354,10,9503,7106,2352,0,10354,7957,2567,10,7107,1179,7106,0,7958,1394,7957,10,9504,3664,318,0,10355,4091,407,10,7108,9504,4701,0,7959,10355,5128,10,7107,1833,3664,0,7958,2048,4091,10,1179,7107,9504,0,1394,7958,10355,10,4725,9505,4700,0,5152,10356,5127,10,2363,7109,9505,0,2578,7960,10356,10,9505,7108,2351,0,10356,7959,2566,10,7109,1179,7108,0,7960,1394,7959,10,9506,4726,584,0,10357,5153,797,10,7110,9506,4704,0,7961,10357,5131,10,7113,2364,4726,0,7964,2579,5153,10,1180,7113,9506,0,1395,7964,10357,10,3609,9507,4705,0,4036,10358,5132,10,1805,7111,9507,0,2020,7962,10358,10,9507,7110,2353,0,10358,7961,2568,10,7111,1180,7110,0,7962,1395,7961,10,9508,3608,312,0,10359,4035,401,10,7112,9508,3606,0,7963,10359,4033,10,7111,1805,3608,0,7962,2020,4035,10,1180,7111,9508,0,1395,7962,10359,10,4727,9509,3607,0,5154,10360,4034,10,2364,7113,9509,0,2579,7964,10360,10,9509,7112,1804,0,10360,7963,2019,10,7113,1180,7112,0,7964,1395,7963,10,9510,4728,574,0,10361,5155,787,10,7114,9510,3593,0,7965,10361,4020,10,7117,2365,4728,0,7968,2580,5155,10,1181,7117,9510,0,1396,7968,10361,10,3617,9511,3592,0,4044,10362,4019,10,1809,7115,9511,0,2024,7966,10362,10,9511,7114,1797,0,10362,7965,2012,10,7115,1181,7114,0,7966,1396,7965,10,9512,3616,317,0,10363,4043,406,10,7116,9512,3614,0,7967,10363,4041,10,7115,1809,3616,0,7966,2024,4043,10,1181,7115,9512,0,1396,7966,10363,10,4729,9513,3615,0,5156,10364,4042,10,2365,7117,9513,0,2580,7968,10364,10,9513,7116,1808,0,10364,7967,2023,10,7117,1181,7116,0,7968,1396,7967,10,9514,4730,585,0,10365,5157,799,10,7118,9514,4706,0,7969,10365,5133,10,7121,2366,4730,0,7972,2581,5157,10,1182,7121,9514,0,1397,7972,10365,10,3681,9515,4707,0,4108,10366,5134,10,1841,7119,9515,0,2056,7970,10366,10,9515,7118,2354,0,10366,7969,2569,10,7119,1182,7118,0,7970,1397,7969,10,9516,3680,329,0,10367,4107,420,10,7120,9516,3638,0,7971,10367,4065,10,7119,1841,3680,0,7970,2056,4107,10,1182,7119,9516,0,1397,7970,10367,10,4731,9517,3639,0,5158,10368,4066,10,2366,7121,9517,0,2581,7972,10368,10,9517,7120,1820,0,10368,7971,2035,10,7121,1182,7120,0,7972,1397,7971,10,9518,4732,578,0,10369,5159,791,10,7122,9518,3629,0,7973,10369,4056,10,7125,2367,4732,0,7976,2582,5159,10,1183,7125,9518,0,1398,7976,10369,10,3685,9519,3628,0,4112,10370,4055,10,1843,7123,9519,0,2058,7974,10370,10,9519,7122,1815,0,10370,7973,2030,10,7123,1183,7122,0,7974,1398,7973,10,9520,3684,330,0,10371,4111,421,10,7124,9520,4707,0,7975,10371,5134,10,7123,1843,3684,0,7974,2058,4111,10,1183,7123,9520,0,1398,7974,10371,10,4733,9521,4706,0,5160,10372,5133,10,2367,7125,9521,0,2582,7976,10372,10,9521,7124,2354,0,10372,7975,2569,10,7125,1183,7124,0,7976,1398,7975,10,9522,4734,579,0,10373,5161,792,10,7126,9522,3639,0,7977,10373,4066,10,7129,2368,4734,0,7980,2583,5161,10,1184,7129,9522,0,1399,7980,10373,10,3675,9523,3638,0,4102,10374,4065,10,1838,7127,9523,0,2053,7978,10374,10,9523,7126,1820,0,10374,7977,2035,10,7127,1184,7126,0,7978,1399,7977,10,9524,3674,311,0,10375,4101,400,10,7128,9524,4699,0,7979,10375,5126,10,7127,1838,3674,0,7978,2053,4101,10,1184,7127,9524,0,1399,7978,10375,10,4735,9525,4698,0,5162,10376,5125,10,2368,7129,9525,0,2583,7980,10376,10,9525,7128,2350,0,10376,7979,2565,10,7129,1184,7128,0,7980,1399,7979,10,9526,4736,575,0,10377,5163,788,10,7130,9526,3607,0,7981,10377,4034,10,7133,2369,4736,0,7984,2584,5163,10,1185,7133,9526,0,1400,7984,10377,10,3605,9527,3606,0,4032,10378,4033,10,1803,7131,9527,0,2018,7982,10378,10,9527,7130,1804,0,10378,7981,2019,10,7131,1185,7130,0,7982,1400,7981,10,9528,3604,313,0,10379,4031,402,10,7132,9528,4703,0,7983,10379,5130,10,7131,1803,3604,0,7982,2018,4031,10,1185,7131,9528,0,1400,7982,10379,10,4737,9529,4702,0,5164,10380,5129,10,2369,7133,9529,0,2584,7984,10380,10,9529,7132,2352,0,10380,7983,2567,10,7133,1185,7132,0,7984,1400,7983,10,9530,4766,587,0,10381,5193,801,10,7134,9530,4738,0,7985,10381,5165,10,7137,2384,4766,0,7988,2599,5193,10,1186,7137,9530,0,1401,7988,10381,10,4476,9531,4739,0,4903,10382,5166,10,2239,7135,9531,0,2454,7986,10382,10,9531,7134,2370,0,10382,7985,2585,10,7135,1186,7134,0,7986,1401,7985,10,9532,4477,517,0,10383,4904,727,10,7136,9532,4448,0,7987,10383,4875,10,7135,2239,4477,0,7986,2454,4904,10,1186,7135,9532,0,1401,7986,10383,10,4767,9533,4449,0,5194,10384,4876,10,2384,7137,9533,0,2599,7988,10384,10,9533,7136,2225,0,10384,7987,2440,10,7137,1186,7136,0,7988,1401,7987,10,9534,4768,588,0,10385,5195,802,10,7138,9534,4740,0,7989,10385,5167,10,7141,2385,4768,0,7992,2600,5195,10,1187,7141,9534,0,1402,7992,10385,10,4478,9535,4741,0,4905,10386,5168,10,2240,7139,9535,0,2455,7990,10386,10,9535,7138,2371,0,10386,7989,2586,10,7139,1187,7138,0,7990,1402,7989,10,9536,4479,519,0,10387,4906,729,10,7140,9536,4452,0,7991,10387,4879,10,7139,2240,4479,0,7990,2455,4906,10,1187,7139,9536,0,1402,7990,10387,10,4769,9537,4453,0,5196,10388,4880,10,2385,7141,9537,0,2600,7992,10388,10,9537,7140,2227,0,10388,7991,2442,10,7141,1187,7140,0,7992,1402,7991,10,9538,4770,589,0,10389,5197,803,10,7142,9538,4742,0,7993,10389,5169,10,7145,2386,4770,0,7996,2601,5197,10,1188,7145,9538,0,1403,7996,10389,10,4480,9539,4743,0,4907,10390,5170,10,2241,7143,9539,0,2456,7994,10390,10,9539,7142,2372,0,10390,7993,2587,10,7143,1188,7142,0,7994,1403,7993,10,9540,4481,520,0,10391,4908,730,10,7144,9540,4741,0,7995,10391,5168,10,7143,2241,4481,0,7994,2456,4908,10,1188,7143,9540,0,1403,7994,10391,10,4771,9541,4740,0,5198,10392,5167,10,2386,7145,9541,0,2601,7996,10392,10,9541,7144,2371,0,10392,7995,2586,10,7145,1188,7144,0,7996,1403,7995,10,9542,4772,590,0,10393,5199,804,10,7146,9542,4744,0,7997,10393,5171,10,7149,2387,4772,0,8000,2602,5199,10,1189,7149,9542,0,1404,8000,10393,10,4482,9543,4745,0,4909,10394,5172,10,2242,7147,9543,0,2457,7998,10394,10,9543,7146,2373,0,10394,7997,2588,10,7147,1189,7146,0,7998,1404,7997,10,9544,4483,522,0,10395,4910,732,10,7148,9544,4458,0,7999,10395,4885,10,7147,2242,4483,0,7998,2457,4910,10,1189,7147,9544,0,1404,7998,10395,10,4773,9545,4459,0,5200,10396,4886,10,2387,7149,9545,0,2602,8000,10396,10,9545,7148,2230,0,10396,7999,2445,10,7149,1189,7148,0,8000,1404,7999,10,9546,4774,594,0,10397,5201,809,10,7150,9546,4453,0,8001,10397,4880,10,7153,2388,4774,0,8004,2603,5201,10,1190,7153,9546,0,1405,8004,10397,10,4484,9547,4452,0,4911,10398,4879,10,2243,7151,9547,0,2458,8002,10398,10,9547,7150,2227,0,10398,8001,2442,10,7151,1190,7150,0,8002,1405,8001,10,9548,4485,524,0,10399,4912,735,10,7152,9548,4462,0,8003,10399,4889,10,7151,2243,4485,0,8002,2458,4912,10,1190,7151,9548,0,1405,8002,10399,10,4775,9549,4463,0,5202,10400,4890,10,2388,7153,9549,0,2603,8004,10400,10,9549,7152,2232,0,10400,8003,2447,10,7153,1190,7152,0,8004,1405,8003,10,9550,4776,591,0,10401,5203,806,10,7154,9550,4746,0,8005,10401,5173,10,7157,2389,4776,0,8008,2604,5203,10,1191,7157,9550,0,1406,8008,10401,10,4490,9551,4747,0,4917,10402,5174,10,2246,7155,9551,0,2461,8006,10402,10,9551,7154,2374,0,10402,8005,2589,10,7155,1191,7154,0,8006,1406,8005,10,9552,4491,527,0,10403,4918,738,10,7156,9552,4468,0,8007,10403,4895,10,7155,2246,4491,0,8006,2461,4918,10,1191,7155,9552,0,1406,8006,10403,10,4777,9553,4469,0,5204,10404,4896,10,2389,7157,9553,0,2604,8008,10404,10,9553,7156,2235,0,10404,8007,2450,10,7157,1191,7156,0,8008,1406,8007,10,9554,4778,598,0,10405,5205,813,10,7158,9554,4467,0,8009,10405,4894,10,7161,2390,4778,0,8012,2605,5205,10,1192,7161,9554,0,1407,8012,10405,10,4492,9555,4466,0,4919,10406,4893,10,2247,7159,9555,0,2462,8010,10406,10,9555,7158,2234,0,10406,8009,2449,10,7159,1192,7158,0,8010,1407,8009,10,9556,4493,528,0,10407,4920,739,10,7160,9556,4747,0,8011,10407,5174,10,7159,2247,4493,0,8010,2462,4920,10,1192,7159,9556,0,1407,8010,10407,10,4779,9557,4746,0,5206,10408,5173,10,2390,7161,9557,0,2605,8012,10408,10,9557,7160,2374,0,10408,8011,2589,10,7161,1192,7160,0,8012,1407,8011,10,9558,4780,599,0,10409,5207,814,10,7162,9558,4469,0,8013,10409,4896,10,7165,2391,4780,0,8016,2606,5207,10,1193,7165,9558,0,1408,8016,10409,10,4498,9559,4468,0,4925,10410,4895,10,2250,7163,9559,0,2465,8014,10410,10,9559,7162,2235,0,10410,8013,2450,10,7163,1193,7162,0,8014,1408,8013,10,9560,4499,518,0,10411,4926,728,10,7164,9560,4739,0,8015,10411,5166,10,7163,2250,4499,0,8014,2465,4926,10,1193,7163,9560,0,1408,8014,10411,10,4781,9561,4738,0,5208,10412,5165,10,2391,7165,9561,0,2606,8016,10412,10,9561,7164,2370,0,10412,8015,2585,10,7165,1193,7164,0,8016,1408,8015,10,9562,4782,595,0,10413,5209,810,10,7166,9562,4459,0,8017,10413,4886,10,7169,2392,4782,0,8020,2607,5209,10,1194,7169,9562,0,1409,8020,10413,10,4502,9563,4458,0,4929,10414,4885,10,2252,7167,9563,0,2467,8018,10414,10,9563,7166,2230,0,10414,8017,2445,10,7167,1194,7166,0,8018,1409,8017,10,9564,4503,521,0,10415,4930,731,10,7168,9564,4743,0,8019,10415,5170,10,7167,2252,4503,0,8018,2467,4930,10,1194,7167,9564,0,1409,8018,10415,10,4783,9565,4742,0,5210,10416,5169,10,2392,7169,9565,0,2607,8020,10416,10,9565,7168,2372,0,10416,8019,2587,10,7169,1194,7168,0,8020,1409,8019,10,9566,4784,597,0,10417,5211,812,10,7170,9566,4758,0,8021,10417,5185,10,7173,2393,4784,0,8024,2608,5211,10,1195,7173,9566,0,1410,8024,10417,10,3624,9567,4759,0,4051,10418,5186,10,1813,7171,9567,0,2028,8022,10418,10,9567,7170,2380,0,10418,8021,2595,10,7171,1195,7170,0,8022,1410,8021,10,9568,3625,315,0,10419,4052,404,10,7172,9568,4757,0,8023,10419,5184,10,7171,1813,3625,0,8022,2028,4052,10,1195,7171,9568,0,1410,8022,10419,10,4785,9569,4756,0,5212,10420,5183,10,2393,7173,9569,0,2608,8024,10420,10,9569,7172,2379,0,10420,8023,2594,10,7173,1195,7172,0,8024,1410,8023,10,9570,4786,598,0,10421,5213,813,10,7174,9570,4760,0,8025,10421,5187,10,7177,2394,4786,0,8028,2609,5213,10,1196,7177,9570,0,1411,8028,10421,10,3626,9571,4761,0,4053,10422,5188,10,1814,7175,9571,0,2029,8026,10422,10,9571,7174,2381,0,10422,8025,2596,10,7175,1196,7174,0,8026,1411,8025,10,9572,3627,320,0,10423,4054,409,10,7176,9572,4759,0,8027,10423,5186,10,7175,1814,3627,0,8026,2029,4054,10,1196,7175,9572,0,1411,8026,10423,10,4787,9573,4758,0,5214,10424,5185,10,2394,7177,9573,0,2609,8028,10424,10,9573,7176,2380,0,10424,8027,2595,10,7177,1196,7176,0,8028,1411,8027,10,9574,4788,600,0,10425,5215,815,10,7178,9574,4764,0,8029,10425,5191,10,7181,2395,4788,0,8032,2610,5215,10,1197,7181,9574,0,1412,8032,10425,10,3648,9575,4765,0,4075,10426,5192,10,1825,7179,9575,0,2040,8030,10426,10,9575,7178,2383,0,10426,8029,2598,10,7179,1197,7178,0,8030,1412,8029,10,9576,3649,303,0,10427,4076,392,10,7180,9576,3646,0,8031,10427,4073,10,7179,1825,3649,0,8030,2040,4076,10,1197,7179,9576,0,1412,8030,10427,10,4789,9577,3647,0,5216,10428,4074,10,2395,7181,9577,0,2610,8032,10428,10,9577,7180,1824,0,10428,8031,2039,10,7181,1197,7180,0,8032,1412,8031,10,9578,4790,590,0,10429,5217,805,10,7182,9578,3611,0,8033,10429,5371,10,7185,2396,4790,0,8036,2611,5217,10,1198,7185,9578,0,1413,8036,10429,10,3652,9579,3610,0,4079,10430,5372,10,1827,7183,9579,0,2042,8034,10430,10,9579,7182,1806,0,10430,8033,2688,10,7183,1198,7182,0,8034,1413,8033,10,9580,3653,325,0,10431,4080,414,10,7184,9580,4765,0,8035,10431,5192,10,7183,1827,3653,0,8034,2042,4080,10,1198,7183,9580,0,1413,8034,10431,10,4791,9581,4764,0,5218,10432,5191,10,2396,7185,9581,0,2611,8036,10432,10,9581,7184,2383,0,10432,8035,2598,10,7185,1198,7184,0,8036,1413,8035,10,9582,4792,592,0,10433,5219,807,10,7186,9582,3647,0,8037,10433,4074,10,7189,2397,4792,0,8040,2612,5219,10,1199,7189,9582,0,1414,8040,10433,10,3581,9583,3646,0,4008,10434,4073,10,1791,7187,9583,0,2006,8038,10434,10,9583,7186,1824,0,10434,8037,2039,10,7187,1199,7186,0,8038,1414,8037,10,9584,3580,304,0,10435,4007,393,10,7188,9584,4751,0,8039,10435,5178,10,7187,1791,3580,0,8038,2006,4007,10,1199,7187,9584,0,1414,8038,10435,10,4793,9585,4750,0,5220,10436,5177,10,2397,7189,9585,0,2612,8040,10436,10,9585,7188,2376,0,10436,8039,2591,10,7189,1199,7188,0,8040,1414,8039,10,9586,9587,9603,0,10437,10438,10454,10,9587,9588,9604,0,10438,10439,10455,10,9588,9589,9605,0,10439,10440,10456,10,9589,9590,9606,0,10440,10441,10457,10,9590,9591,9607,0,10441,10442,10458,10,9591,9592,9608,0,10442,10443,10459,10,9592,9593,9609,0,10443,10444,10460,10,9593,9594,9610,0,10444,10445,10461,10,9594,9595,9611,0,10445,10446,10462,10,9595,9596,9612,0,10446,10447,10463,10,9596,9597,9613,0,10447,10448,10464,10,9597,9598,9614,0,10448,10449,10465,10,9598,9599,9615,0,10449,10450,10466,10,9599,9600,9616,0,10450,10451,10467,10,9600,9601,9617,0,10451,10452,10468,10,9601,9586,9602,0,10452,10437,10453,10,9601,9587,9586,0,10452,10438,10437,10,9617,9603,9616,0,10468,10454,10467,10,9618,9619,9625,0,10469,10470,10476,10,9619,9620,9626,0,10470,10471,10477,10,9620,9621,9627,0,10471,10472,10478,10,9621,9622,9628,0,10472,10473,10479,10,9622,9623,9629,0,10473,10474,10480,10,9623,9618,9624,0,10474,10469,10475,10,9618,9620,9619,0,10469,10471,10470,10,9624,9628,9629,0,10475,10479,10480,10,9630,9633,9631,0,10481,10484,10482,10,9634,9637,9636,0,10485,10488,10487,10,9630,9635,9634,0,10489,10492,10491,10,9631,9637,9635,0,10493,10496,10495,10,9633,9636,9637,0,10497,10500,10499,10,9632,9634,9636,0,10501,10504,10503,10,9603,9602,9586,0,10454,10453,10437,10,9604,9603,9587,0,10455,10454,10438,10,9605,9604,9588,0,10456,10455,10439,10,9606,9605,9589,0,10457,10456,10440,10,9607,9606,9590,0,10458,10457,10441,10,9608,9607,9591,0,10459,10458,10442,10,9609,9608,9592,0,10460,10459,10443,10,9610,9609,9593,0,10461,10460,10444,10,9611,9610,9594,0,10462,10461,10445,10,9612,9611,9595,0,10463,10462,10446,10,9613,9612,9596,0,10464,10463,10447,10,9614,9613,9597,0,10465,10464,10448,10,9615,9614,9598,0,10466,10465,10449,10,9616,9615,9599,0,10467,10466,10450,10,9617,9616,9600,0,10468,10467,10451,10,9602,9617,9601,0,10453,10468,10452,10,9594,9593,9592,0,10445,10444,10443,10,9595,9594,9592,0,10446,10445,10443,10,9595,9592,9591,0,10446,10443,10442,10,9596,9595,9591,0,10447,10446,10442,10,9596,9591,9590,0,10447,10442,10441,10,9597,9596,9590,0,10448,10447,10441,10,9597,9590,9589,0,10448,10441,10440,10,9598,9597,9589,0,10449,10448,10440,10,9599,9598,9589,0,10450,10449,10440,10,9599,9589,9588,0,10450,10440,10439,10,9600,9599,9588,0,10451,10450,10439,10,9600,9588,9587,0,10451,10439,10438,10,9601,9600,9587,0,10452,10451,10438,10,9617,9602,9603,0,10468,10453,10454,10,9608,9609,9610,0,10459,10460,10461,10,9608,9610,9611,0,10459,10461,10462,10,9607,9608,9611,0,10458,10459,10462,10,9607,9611,9612,0,10458,10462,10463,10,9606,9607,9612,0,10457,10458,10463,10,9606,9612,9613,0,10457,10463,10464,10,9605,9606,9613,0,10456,10457,10464,10,9605,9613,9614,0,10456,10464,10465,10,9605,9614,9615,0,10456,10465,10466,10,9604,9605,9615,0,10455,10456,10466,10,9604,9615,9616,0,10455,10466,10467,10,9603,9604,9616,0,10454,10455,10467,10,9625,9624,9618,0,10476,10475,10469,10,9626,9625,9619,0,10477,10476,10470,10,9627,9626,9620,0,10478,10477,10471,10,9628,9627,9621,0,10479,10478,10472,10,9629,9628,9622,0,10480,10479,10473,10,9624,9629,9623,0,10475,10480,10474,10,9618,9623,9622,0,10469,10474,10473,10,9622,9621,9620,0,10473,10472,10471,10,9618,9622,9620,0,10469,10473,10471,10,9624,9625,9626,0,10475,10476,10477,10,9626,9627,9628,0,10477,10478,10479,10,9624,9626,9628,0,10475,10477,10479,10,9630,9632,9633,0,10481,10483,10484,10,9634,9635,9637,0,10485,10486,10488,10,9630,9631,9635,0,10489,10490,10492,10,9631,9633,9637,0,10493,10494,10496,10,9633,9632,9636,0,10497,10498,10500,10,9632,9630,9634,0,10501,10502,10504]\n\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/webgl-pointer-lock/styles/main.css",
    "content": "body {\n  background: black;\n  margin: 0;\n  padding: 0;\n  overflow: hidden;\n}\n\n.close {\n  background-image: url('../img/button_close.png');\n  background-repeat: no-repeat;\n  position: absolute;\n  top: 5px;\n  right: 5px;\n  z-index: 1000;\n  width: 17px;\n  height: 17px;\n  cursor: pointer;\n  -webkit-app-region: no-drag;\n}\n\n.close:hover {\n  background-image: url('../img/button_close_hover.png');\n}\n\n"
  },
  {
    "path": "_archive/apps/samples/webserver/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hflhcpmgeolmjlbmdicgkjedjmkoocbe\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\nWeb Server\n==========\n\nThis sample is a demonstration of Chrome's new networking stack. Chrome has the ability to\nlisten on a tcp port AND to accept.\n\n## APIs\n* [Sockets](https://developer.chrome.com/apps/sockets_tcpServer)\n* [Network](https://developer.chrome.com/apps/system_network)\n* [Runtime](https://developer.chrome.com/apps/app_runtime)\n* [Window](https://developer.chrome.com/apps/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/webserver/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/webserver/_locales/en/messages.json",
    "content": "{\n  \"appName\": {\n    \"message\": \"HTTP Server Sample\",\n    \"description\": \"The name of the application\"\n  },\n  \"appDescription\": {\n    \"message\": \"HTTP Server Sample\",\n    \"description\": \"The description of the application\"\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/webserver/index.html",
    "content": "<!doctype html>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>HTTP Webserver</title>\n        <!-- build:css styles/app.css -->\n        <link rel=\"stylesheet\" href=\"styles/bootstrap.css\">\n        <link rel=\"stylesheet\" href=\"styles/main.css\">\n        <!-- endbuild -->\n        <script src=\"index.js\"></script>\n        <style>\n          input[type=\"file\"]::-webkit-file-upload-button {\n            background-color: red;\n            color: white;\n            text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n            background-color: #006DCC;\n            background-image: -moz-linear-gradient(top, #08C, #04C);\n            background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#08C), to(#04C));\n            background-image: -webkit-linear-gradient(top, #08C, #04C);\n            background-image: -o-linear-gradient(top, #08C, #04C);\n            background-image: linear-gradient(to bottom, #08C, #04C);\n            background-repeat: repeat-x;\n            filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n            border-color: #04C #04C #002A80;\n            border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n            filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n            padding: 9px 14px;\n            font-size: 16px;\n            line-height: normal;\n            -webkit-border-radius: 5px;\n            -moz-border-radius: 5px;\n            border-radius: 5px;\n\n          }\n          input[type=\"file\"] {\n            margin-bottom: 20px;\n          }\n          input[type=\"file\"][disabled]::-webkit-file-upload-button {\n            color: default;\n            background-color: #E6E6E6;\n            background-image: none;\n            opacity: 0.65;\n            filter: alpha(opacity=65);\n            -webkit-box-shadow: none;\n            -moz-box-shadow: none;\n            box-shadow: none;\n          }\n\n          #logger {\n            border: solid 1px #c6c6c6;\n            border-radius: 5px;\n            box-shadow: inset 0px 0px 5px #c6c6c6;\n            height: 100px;\n            overflow-y: auto;\n          }\n\n          select { \n            display: block;\n          }\n        </style>\n    </head>\n    <body>\n      <div class=\"hero-unit\">\n        <h1>HTTP Webserver</h1>\n         <p>Serving you locally</p>\n         <p>\n           <input type=\"file\" webkitdirectory id=\"directory\"/><br />\n           <select id=\"hosts\">\n             <option value=\"127.0.0.1\">lo - 127.0.0.1</option> \n           </select>\n           <input type=\"text\" id=\"port\" value=\"8080\"/><br />\n           <button id=\"start\" class=\"btn btn-primary btn-large\" disabled>Start</button>\n           <button id=\"stop\" class=\"btn btn-warning btn-large\"  disabled>Stop</button>\n         </p>\n      </div>\n      <pre id=\"logger\"></pre>\n    </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webserver/index.js",
    "content": "onload = function() {\n  var start = document.getElementById(\"start\");\n  var stop = document.getElementById(\"stop\");\n  var hosts = document.getElementById(\"hosts\");\n  var port = document.getElementById(\"port\");\n  var directory = document.getElementById(\"directory\");\n\n  var tcpServer = chrome.sockets.tcpServer;\n  var tcpSocket = chrome.sockets.tcp;\n\n  var serverSocketId = null;\n  var filesMap = {};\n\n  var stringToUint8Array = function(string) {\n    var buffer = new ArrayBuffer(string.length);\n    var view = new Uint8Array(buffer);\n    for (var i = 0; i < string.length; i++) {\n      view[i] = string.charCodeAt(i);\n    }\n    return view;\n  };\n\n  var arrayBufferToString = function(buffer) {\n    var str = '';\n    var uArrayVal = new Uint8Array(buffer);\n    for (var s = 0; s < uArrayVal.length; s++) {\n      str += String.fromCharCode(uArrayVal[s]);\n    }\n    return str;\n  };\n\n  var logToScreen = function(log) {\n    logger.textContent += log + \"\\n\";\n    logger.scrollTop = logger.scrollHeight;\n  };\n\n  var destroySocketById = function(socketId) {\n    tcpSocket.disconnect(socketId, function() {\n      tcpSocket.close(socketId);\n    });\n  };\n\n  var closeServerSocket = function() {\n    if (serverSocketId) {\n      tcpServer.close(serverSocketId, function() {\n        if (chrome.runtime.lastError) {\n          console.warn(\"chrome.sockets.tcpServer.close:\", chrome.runtime.lastError);\n        }\n      });\n    }\n\n    tcpServer.onAccept.removeListener(onAccept);\n    tcpSocket.onReceive.removeListener(onReceive);\n  };\n\n  var sendReplyToSocket = function(socketId, buffer, keepAlive) {\n    // verify that socket is still connected before trying to send data\n    tcpSocket.getInfo(socketId, function(socketInfo) {\n      if (!socketInfo.connected) {\n        destroySocketById(socketId);\n        return;\n      }\n\n      tcpSocket.setKeepAlive(socketId, keepAlive, 1, function() {\n        if (!chrome.runtime.lastError) {\n          tcpSocket.send(socketId, buffer, function(writeInfo) {\n            console.log(\"WRITE\", writeInfo);\n\n            if (!keepAlive || chrome.runtime.lastError) {\n              destroySocketById(socketId);\n            }\n          });\n        }\n        else {\n          console.warn(\"chrome.sockets.tcp.setKeepAlive:\", chrome.runtime.lastError);\n          destroySocketById(socketId);\n        }\n      });\n    });\n  };\n\n  var getResponseHeader = function(file, errorCode, keepAlive) {\n    var httpStatus = \"HTTP/1.0 200 OK\";\n    var contentType = \"text/plain\";\n    var contentLength = 0;\n\n    if (!file || errorCode) {\n      httpStatus = \"HTTP/1.0 \" + (errorCode || 404) + \" Not Found\";\n    }\n    else {\n      contentType = file.type || contentType;\n      contentLength = file.size;\n    }\n\n    var lines = [\n      httpStatus,\n      \"Content-length: \" + contentLength,\n      \"Content-type:\" + contentType\n    ];\n\n    if (keepAlive) {\n      lines.push(\"Connection: keep-alive\");\n    }\n\n    return stringToUint8Array(lines.join(\"\\n\") + \"\\n\\n\");\n  };\n\n  var getErrorHeader = function(errorCode, keepAlive) {\n    return getResponseHeader(null, errorCode, keepAlive);\n  };\n\n  var getSuccessHeader = function(file, keepAlive) {\n    return getResponseHeader(file, null, keepAlive);\n  };\n\n  var writeErrorResponse = function(socketId, errorCode, keepAlive) {\n    console.info(\"writeErrorResponse:: begin... \");\n\n    var header = getErrorHeader(errorCode, keepAlive);\n    console.info(\"writeErrorResponse:: Done setting header...\");\n    var outputBuffer = new ArrayBuffer(header.byteLength);\n    var view = new Uint8Array(outputBuffer);\n    view.set(header, 0);\n    console.info(\"writeErrorResponse:: Done setting view...\");\n\n    sendReplyToSocket(socketId, outputBuffer, keepAlive);\n\n    console.info(\"writeErrorResponse::filereader:: end onload...\");\n    console.info(\"writeErrorResponse:: end...\");\n  };\n\n  var write200Response = function(socketId, file, keepAlive) {\n    var header = getSuccessHeader(file, keepAlive);\n    var outputBuffer = new ArrayBuffer(header.byteLength + file.size);\n    var view = new Uint8Array(outputBuffer);\n    view.set(header, 0);\n\n    var fileReader = new FileReader();\n    fileReader.onload = function(e) {\n      view.set(new Uint8Array(e.target.result), header.byteLength);\n      sendReplyToSocket(socketId, outputBuffer, keepAlive);\n    };\n\n    fileReader.readAsArrayBuffer(file);\n  };\n\n  var onAccept = function(acceptInfo) {\n    tcpSocket.setPaused(acceptInfo.clientSocketId, false);\n\n    if (acceptInfo.socketId != serverSocketId)\n      return;\n\n    console.log(\"ACCEPT\", acceptInfo);\n  };\n\n  var onReceive = function(receiveInfo) {\n    console.log(\"READ\", receiveInfo);\n    var socketId = receiveInfo.socketId;\n\n    // Parse the request.\n    var data = arrayBufferToString(receiveInfo.data);\n    // we can only deal with GET requests\n    if (data.indexOf(\"GET \") !== 0) {\n      // close socket and exit handler\n      destroySocketById(socketId);\n      return;\n    }\n\n    var keepAlive = false;\n    if (data.indexOf(\"Connection: keep-alive\") != -1) {\n      keepAlive = true;\n    }\n\n    var uriEnd = data.indexOf(\" \", 4);\n    if (uriEnd < 0) { /* throw a wobbler */ return; }\n    var uri = data.substring(4, uriEnd);\n    // strip query string\n    var q = uri.indexOf(\"?\");\n    if (q != -1) {\n      uri = uri.substring(0, q);\n    }\n    var file = filesMap[uri];\n    if (!!file == false) {\n      console.warn(\"File does not exist...\" + uri);\n      writeErrorResponse(socketId, 404, keepAlive);\n      return;\n    }\n    logToScreen(\"GET 200 \" + uri);\n    write200Response(socketId, file, keepAlive);\n\n  };\n\n  directory.onchange = function(e) {\n    closeServerSocket();\n\n    var files = e.target.files;\n\n    for (var i = 0; i < files.length; i++) {\n      //remove the first first directory\n      var path = files[i].webkitRelativePath;\n      if (path && path.indexOf(\"/\") >= 0) {\n        filesMap[path.substr(path.indexOf(\"/\"))] = files[i];\n      } else {\n        filesMap[\"/\" + files[i].fileName] = files[i];\n      }\n    }\n\n    start.disabled = false;\n    stop.disabled = true;\n    directory.disabled = true;\n  };\n\n  start.onclick = function() {\n\n    tcpServer.create({}, function(socketInfo) {\n      serverSocketId = socketInfo.socketId;\n\n      tcpServer.listen(serverSocketId, hosts.value, parseInt(port.value, 10), 50, function(result) {\n        console.log(\"LISTENING:\", result);\n\n        tcpServer.onAccept.addListener(onAccept);\n        tcpSocket.onReceive.addListener(onReceive);\n      });\n    });\n\n    directory.disabled = true;\n    stop.disabled = false;\n    start.disabled = true;\n  };\n\n  stop.onclick = function() {\n    directory.disabled = false;\n    stop.disabled = true;\n    start.disabled = false;\n    closeServerSocket();\n  };\n\n  chrome.system.network.getNetworkInterfaces(function(interfaces) {\n    for (var i in interfaces) {\n      var interface = interfaces[i];\n      var opt = document.createElement(\"option\");\n      opt.value = interface.address;\n      opt.innerText = interface.name + \" - \" + interface.address;\n      hosts.appendChild(opt);\n    }\n  });\n};\n"
  },
  {
    "path": "_archive/apps/samples/webserver/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function(intentData) {\n  chrome.app.window.create('index.html', {\n  \tid: \"mainwin\",\n    innerBounds: {\n      width: 500,\n      height: 640\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/webserver/manifest.json",
    "content": "{\n  \"name\": \"__MSG_appName__\",\n  \"version\": \"3.2\",\n  \"manifest_version\": 2,\n  \"description\": \"__MSG_appDescription__\",\n  \"icons\": {\n    \"16\": \"icon-16.png\",\n    \"128\": \"icon-128.png\"\n  },\n  \"default_locale\": \"en\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\"system.network\"],\n  \"sockets\": {\n    \"tcpServer\" : {\n      \"listen\": [\"*\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/webserver/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"webserver\",\n  \"files_with_snippets\": [ ],\n  \"android\": {\"works\": true, \"comments\": \"Directory picking doesn't work on some versions of Android\"}\n}\n"
  },
  {
    "path": "_archive/apps/samples/webserver/styles/bootstrap.css",
    "content": "/*!\n * Bootstrap v2.1.1\n *\n * Copyright 2012 Twitter, Inc\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world @twitter by @mdo and @fat.\n */\n.clearfix {\n  *zoom: 1;\n}\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.clearfix:after {\n  clear: both;\n}\n.hide-text {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n.input-block-level {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nnav,\nsection {\n  display: block;\n}\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\naudio:not([controls]) {\n  display: none;\n}\nhtml {\n  font-size: 100%;\n  -webkit-text-size-adjust: 100%;\n  -ms-text-size-adjust: 100%;\n}\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\na:hover,\na:active {\n  outline: 0;\n}\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\nsup {\n  top: -0.5em;\n}\nsub {\n  bottom: -0.25em;\n}\nimg {\n  /* Responsive images (ensure images don't scale beyond their parents) */\n\n  max-width: 100%;\n  /* Part 1: Set a maxium relative to the parent */\n\n  width: auto\\9;\n  /* IE7-8 need help adjusting responsive images */\n\n  height: auto;\n  /* Part 2: Scale the height according to the width, otherwise you get stretching */\n\n  vertical-align: middle;\n  border: 0;\n  -ms-interpolation-mode: bicubic;\n}\n#map_canvas img {\n  max-width: none;\n}\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-size: 100%;\n  vertical-align: middle;\n}\nbutton,\ninput {\n  *overflow: visible;\n  line-height: normal;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\nbutton,\ninput[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\ninput[type=\"search\"]::-webkit-search-decoration,\ninput[type=\"search\"]::-webkit-search-cancel-button {\n  -webkit-appearance: none;\n}\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\nbody {\n  margin: 0;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 20px;\n  color: #333333;\n  background-color: #ffffff;\n}\na {\n  color: #0088cc;\n  text-decoration: none;\n}\na:hover {\n  color: #005580;\n  text-decoration: underline;\n}\n.img-rounded {\n  -webkit-border-radius: 6px;\n  -moz-border-radius: 6px;\n  border-radius: 6px;\n}\n.img-polaroid {\n  padding: 4px;\n  background-color: #fff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n  -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n.img-circle {\n  -webkit-border-radius: 500px;\n  -moz-border-radius: 500px;\n  border-radius: 500px;\n}\n.row {\n  margin-left: -20px;\n  *zoom: 1;\n}\n.row:before,\n.row:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.row:after {\n  clear: both;\n}\n[class*=\"span\"] {\n  float: left;\n  min-height: 1px;\n  margin-left: 20px;\n}\n.container,\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n.span12 {\n  width: 940px;\n}\n.span11 {\n  width: 860px;\n}\n.span10 {\n  width: 780px;\n}\n.span9 {\n  width: 700px;\n}\n.span8 {\n  width: 620px;\n}\n.span7 {\n  width: 540px;\n}\n.span6 {\n  width: 460px;\n}\n.span5 {\n  width: 380px;\n}\n.span4 {\n  width: 300px;\n}\n.span3 {\n  width: 220px;\n}\n.span2 {\n  width: 140px;\n}\n.span1 {\n  width: 60px;\n}\n.offset12 {\n  margin-left: 980px;\n}\n.offset11 {\n  margin-left: 900px;\n}\n.offset10 {\n  margin-left: 820px;\n}\n.offset9 {\n  margin-left: 740px;\n}\n.offset8 {\n  margin-left: 660px;\n}\n.offset7 {\n  margin-left: 580px;\n}\n.offset6 {\n  margin-left: 500px;\n}\n.offset5 {\n  margin-left: 420px;\n}\n.offset4 {\n  margin-left: 340px;\n}\n.offset3 {\n  margin-left: 260px;\n}\n.offset2 {\n  margin-left: 180px;\n}\n.offset1 {\n  margin-left: 100px;\n}\n.row-fluid {\n  width: 100%;\n  *zoom: 1;\n}\n.row-fluid:before,\n.row-fluid:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.row-fluid:after {\n  clear: both;\n}\n.row-fluid [class*=\"span\"] {\n  display: block;\n  width: 100%;\n  min-height: 30px;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  float: left;\n  margin-left: 2.127659574468085%;\n  *margin-left: 2.074468085106383%;\n}\n.row-fluid [class*=\"span\"]:first-child {\n  margin-left: 0;\n}\n.row-fluid .span12 {\n  width: 100%;\n  *width: 99.94680851063829%;\n}\n.row-fluid .span11 {\n  width: 91.48936170212765%;\n  *width: 91.43617021276594%;\n}\n.row-fluid .span10 {\n  width: 82.97872340425532%;\n  *width: 82.92553191489361%;\n}\n.row-fluid .span9 {\n  width: 74.46808510638297%;\n  *width: 74.41489361702126%;\n}\n.row-fluid .span8 {\n  width: 65.95744680851064%;\n  *width: 65.90425531914893%;\n}\n.row-fluid .span7 {\n  width: 57.44680851063829%;\n  *width: 57.39361702127659%;\n}\n.row-fluid .span6 {\n  width: 48.93617021276595%;\n  *width: 48.88297872340425%;\n}\n.row-fluid .span5 {\n  width: 40.42553191489362%;\n  *width: 40.37234042553192%;\n}\n.row-fluid .span4 {\n  width: 31.914893617021278%;\n  *width: 31.861702127659576%;\n}\n.row-fluid .span3 {\n  width: 23.404255319148934%;\n  *width: 23.351063829787233%;\n}\n.row-fluid .span2 {\n  width: 14.893617021276595%;\n  *width: 14.840425531914894%;\n}\n.row-fluid .span1 {\n  width: 6.382978723404255%;\n  *width: 6.329787234042553%;\n}\n.row-fluid .offset12 {\n  margin-left: 104.25531914893617%;\n  *margin-left: 104.14893617021275%;\n}\n.row-fluid .offset12:first-child {\n  margin-left: 102.12765957446808%;\n  *margin-left: 102.02127659574467%;\n}\n.row-fluid .offset11 {\n  margin-left: 95.74468085106382%;\n  *margin-left: 95.6382978723404%;\n}\n.row-fluid .offset11:first-child {\n  margin-left: 93.61702127659574%;\n  *margin-left: 93.51063829787232%;\n}\n.row-fluid .offset10 {\n  margin-left: 87.23404255319149%;\n  *margin-left: 87.12765957446807%;\n}\n.row-fluid .offset10:first-child {\n  margin-left: 85.1063829787234%;\n  *margin-left: 84.99999999999999%;\n}\n.row-fluid .offset9 {\n  margin-left: 78.72340425531914%;\n  *margin-left: 78.61702127659572%;\n}\n.row-fluid .offset9:first-child {\n  margin-left: 76.59574468085106%;\n  *margin-left: 76.48936170212764%;\n}\n.row-fluid .offset8 {\n  margin-left: 70.2127659574468%;\n  *margin-left: 70.10638297872339%;\n}\n.row-fluid .offset8:first-child {\n  margin-left: 68.08510638297872%;\n  *margin-left: 67.9787234042553%;\n}\n.row-fluid .offset7 {\n  margin-left: 61.70212765957446%;\n  *margin-left: 61.59574468085106%;\n}\n.row-fluid .offset7:first-child {\n  margin-left: 59.574468085106375%;\n  *margin-left: 59.46808510638297%;\n}\n.row-fluid .offset6 {\n  margin-left: 53.191489361702125%;\n  *margin-left: 53.085106382978715%;\n}\n.row-fluid .offset6:first-child {\n  margin-left: 51.063829787234035%;\n  *margin-left: 50.95744680851063%;\n}\n.row-fluid .offset5 {\n  margin-left: 44.68085106382979%;\n  *margin-left: 44.57446808510638%;\n}\n.row-fluid .offset5:first-child {\n  margin-left: 42.5531914893617%;\n  *margin-left: 42.4468085106383%;\n}\n.row-fluid .offset4 {\n  margin-left: 36.170212765957444%;\n  *margin-left: 36.06382978723405%;\n}\n.row-fluid .offset4:first-child {\n  margin-left: 34.04255319148936%;\n  *margin-left: 33.93617021276596%;\n}\n.row-fluid .offset3 {\n  margin-left: 27.659574468085104%;\n  *margin-left: 27.5531914893617%;\n}\n.row-fluid .offset3:first-child {\n  margin-left: 25.53191489361702%;\n  *margin-left: 25.425531914893618%;\n}\n.row-fluid .offset2 {\n  margin-left: 19.148936170212764%;\n  *margin-left: 19.04255319148936%;\n}\n.row-fluid .offset2:first-child {\n  margin-left: 17.02127659574468%;\n  *margin-left: 16.914893617021278%;\n}\n.row-fluid .offset1 {\n  margin-left: 10.638297872340425%;\n  *margin-left: 10.53191489361702%;\n}\n.row-fluid .offset1:first-child {\n  margin-left: 8.51063829787234%;\n  *margin-left: 8.404255319148938%;\n}\n[class*=\"span\"].hide,\n.row-fluid [class*=\"span\"].hide {\n  display: none;\n}\n[class*=\"span\"].pull-right,\n.row-fluid [class*=\"span\"].pull-right {\n  float: right;\n}\n.container {\n  margin-right: auto;\n  margin-left: auto;\n  *zoom: 1;\n}\n.container:before,\n.container:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.container:after {\n  clear: both;\n}\n.container-fluid {\n  padding-right: 20px;\n  padding-left: 20px;\n  *zoom: 1;\n}\n.container-fluid:before,\n.container-fluid:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.container-fluid:after {\n  clear: both;\n}\np {\n  margin: 0 0 10px;\n}\n.lead {\n  margin-bottom: 20px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 30px;\n}\nsmall {\n  font-size: 85%;\n}\nstrong {\n  font-weight: bold;\n}\nem {\n  font-style: italic;\n}\ncite {\n  font-style: normal;\n}\n.muted {\n  color: #999999;\n}\n.text-warning {\n  color: #c09853;\n}\n.text-error {\n  color: #b94a48;\n}\n.text-info {\n  color: #3a87ad;\n}\n.text-success {\n  color: #468847;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  margin: 10px 0;\n  font-family: inherit;\n  font-weight: bold;\n  line-height: 1;\n  color: inherit;\n  text-rendering: optimizelegibility;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\nh1 {\n  font-size: 36px;\n  line-height: 40px;\n}\nh2 {\n  font-size: 30px;\n  line-height: 40px;\n}\nh3 {\n  font-size: 24px;\n  line-height: 40px;\n}\nh4 {\n  font-size: 18px;\n  line-height: 20px;\n}\nh5 {\n  font-size: 14px;\n  line-height: 20px;\n}\nh6 {\n  font-size: 12px;\n  line-height: 20px;\n}\nh1 small {\n  font-size: 24px;\n}\nh2 small {\n  font-size: 18px;\n}\nh3 small {\n  font-size: 14px;\n}\nh4 small {\n  font-size: 14px;\n}\n.page-header {\n  padding-bottom: 9px;\n  margin: 20px 0 30px;\n  border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n  padding: 0;\n  margin: 0 0 10px 25px;\n}\nul ul,\nul ol,\nol ol,\nol ul {\n  margin-bottom: 0;\n}\nli {\n  line-height: 20px;\n}\nul.unstyled,\nol.unstyled {\n  margin-left: 0;\n  list-style: none;\n}\ndl {\n  margin-bottom: 20px;\n}\ndt,\ndd {\n  line-height: 20px;\n}\ndt {\n  font-weight: bold;\n}\ndd {\n  margin-left: 10px;\n}\n.dl-horizontal {\n  *zoom: 1;\n}\n.dl-horizontal:before,\n.dl-horizontal:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.dl-horizontal:after {\n  clear: both;\n}\n.dl-horizontal dt {\n  float: left;\n  width: 160px;\n  clear: left;\n  text-align: right;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n.dl-horizontal dd {\n  margin-left: 180px;\n}\nhr {\n  margin: 20px 0;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n  border-bottom: 1px solid #ffffff;\n}\nabbr[title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\nblockquote {\n  padding: 0 0 0 15px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\nblockquote p {\n  margin-bottom: 0;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 25px;\n}\nblockquote small {\n  display: block;\n  line-height: 20px;\n  color: #999999;\n}\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\nblockquote.pull-right {\n  float: right;\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\nblockquote.pull-right p,\nblockquote.pull-right small {\n  text-align: right;\n}\nblockquote.pull-right small:before {\n  content: '';\n}\nblockquote.pull-right small:after {\n  content: '\\00A0 \\2014';\n}\nq:before,\nq:after,\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\naddress {\n  display: block;\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 20px;\n}\ncode,\npre {\n  padding: 0 3px 2px;\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n  font-size: 12px;\n  color: #333333;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n}\ncode {\n  padding: 2px 4px;\n  color: #d14;\n  background-color: #f7f7f9;\n  border: 1px solid #e1e1e8;\n}\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 20px;\n  word-break: break-all;\n  word-wrap: break-word;\n  white-space: pre;\n  white-space: pre-wrap;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\npre.prettyprint {\n  margin-bottom: 20px;\n}\npre code {\n  padding: 0;\n  color: inherit;\n  background-color: transparent;\n  border: 0;\n}\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n.label,\n.badge {\n  font-size: 11.844px;\n  font-weight: bold;\n  line-height: 14px;\n  color: #ffffff;\n  vertical-align: baseline;\n  white-space: nowrap;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #999999;\n}\n.label {\n  padding: 1px 4px 2px;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n}\n.badge {\n  padding: 1px 9px 2px;\n  -webkit-border-radius: 9px;\n  -moz-border-radius: 9px;\n  border-radius: 9px;\n}\na.label:hover,\na.badge:hover {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n.label-important,\n.badge-important {\n  background-color: #b94a48;\n}\n.label-important[href],\n.badge-important[href] {\n  background-color: #953b39;\n}\n.label-warning,\n.badge-warning {\n  background-color: #f89406;\n}\n.label-warning[href],\n.badge-warning[href] {\n  background-color: #c67605;\n}\n.label-success,\n.badge-success {\n  background-color: #468847;\n}\n.label-success[href],\n.badge-success[href] {\n  background-color: #356635;\n}\n.label-info,\n.badge-info {\n  background-color: #3a87ad;\n}\n.label-info[href],\n.badge-info[href] {\n  background-color: #2d6987;\n}\n.label-inverse,\n.badge-inverse {\n  background-color: #333333;\n}\n.label-inverse[href],\n.badge-inverse[href] {\n  background-color: #1a1a1a;\n}\n.btn .label,\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n.btn-mini .label,\n.btn-mini .badge {\n  top: 0;\n}\ntable {\n  max-width: 100%;\n  background-color: transparent;\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n.table th,\n.table td {\n  padding: 8px;\n  line-height: 20px;\n  text-align: left;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n.table th {\n  font-weight: bold;\n}\n.table thead th {\n  vertical-align: bottom;\n}\n.table caption + thead tr:first-child th,\n.table caption + thead tr:first-child td,\n.table colgroup + thead tr:first-child th,\n.table colgroup + thead tr:first-child td,\n.table thead:first-child tr:first-child th,\n.table thead:first-child tr:first-child td {\n  border-top: 0;\n}\n.table tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n.table-condensed th,\n.table-condensed td {\n  padding: 4px 5px;\n}\n.table-bordered {\n  border: 1px solid #dddddd;\n  border-collapse: separate;\n  *border-collapse: collapse;\n  border-left: 0;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.table-bordered th,\n.table-bordered td {\n  border-left: 1px solid #dddddd;\n}\n.table-bordered caption + thead tr:first-child th,\n.table-bordered caption + tbody tr:first-child th,\n.table-bordered caption + tbody tr:first-child td,\n.table-bordered colgroup + thead tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child th,\n.table-bordered colgroup + tbody tr:first-child td,\n.table-bordered thead:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child th,\n.table-bordered tbody:first-child tr:first-child td {\n  border-top: 0;\n}\n.table-bordered thead:first-child tr:first-child th:first-child,\n.table-bordered tbody:first-child tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n  border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n.table-bordered thead:first-child tr:first-child th:last-child,\n.table-bordered tbody:first-child tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n  border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n}\n.table-bordered thead:last-child tr:last-child th:first-child,\n.table-bordered tbody:last-child tr:last-child td:first-child,\n.table-bordered tfoot:last-child tr:last-child td:first-child {\n  -webkit-border-radius: 0 0 0 4px;\n  -moz-border-radius: 0 0 0 4px;\n  border-radius: 0 0 0 4px;\n  -webkit-border-bottom-left-radius: 4px;\n  border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n}\n.table-bordered thead:last-child tr:last-child th:last-child,\n.table-bordered tbody:last-child tr:last-child td:last-child,\n.table-bordered tfoot:last-child tr:last-child td:last-child {\n  -webkit-border-bottom-right-radius: 4px;\n  border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n}\n.table-bordered caption + thead tr:first-child th:first-child,\n.table-bordered caption + tbody tr:first-child td:first-child,\n.table-bordered colgroup + thead tr:first-child th:first-child,\n.table-bordered colgroup + tbody tr:first-child td:first-child {\n  -webkit-border-top-left-radius: 4px;\n  border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n.table-bordered caption + thead tr:first-child th:last-child,\n.table-bordered caption + tbody tr:first-child td:last-child,\n.table-bordered colgroup + thead tr:first-child th:last-child,\n.table-bordered colgroup + tbody tr:first-child td:last-child {\n  -webkit-border-top-right-radius: 4px;\n  border-top-right-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n}\n.table-striped tbody tr:nth-child(odd) td,\n.table-striped tbody tr:nth-child(odd) th {\n  background-color: #f9f9f9;\n}\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th {\n  background-color: #f5f5f5;\n}\ntable [class*=span],\n.row-fluid table [class*=span] {\n  display: table-cell;\n  float: none;\n  margin-left: 0;\n}\n.table .span1 {\n  float: none;\n  width: 44px;\n  margin-left: 0;\n}\n.table .span2 {\n  float: none;\n  width: 124px;\n  margin-left: 0;\n}\n.table .span3 {\n  float: none;\n  width: 204px;\n  margin-left: 0;\n}\n.table .span4 {\n  float: none;\n  width: 284px;\n  margin-left: 0;\n}\n.table .span5 {\n  float: none;\n  width: 364px;\n  margin-left: 0;\n}\n.table .span6 {\n  float: none;\n  width: 444px;\n  margin-left: 0;\n}\n.table .span7 {\n  float: none;\n  width: 524px;\n  margin-left: 0;\n}\n.table .span8 {\n  float: none;\n  width: 604px;\n  margin-left: 0;\n}\n.table .span9 {\n  float: none;\n  width: 684px;\n  margin-left: 0;\n}\n.table .span10 {\n  float: none;\n  width: 764px;\n  margin-left: 0;\n}\n.table .span11 {\n  float: none;\n  width: 844px;\n  margin-left: 0;\n}\n.table .span12 {\n  float: none;\n  width: 924px;\n  margin-left: 0;\n}\n.table .span13 {\n  float: none;\n  width: 1004px;\n  margin-left: 0;\n}\n.table .span14 {\n  float: none;\n  width: 1084px;\n  margin-left: 0;\n}\n.table .span15 {\n  float: none;\n  width: 1164px;\n  margin-left: 0;\n}\n.table .span16 {\n  float: none;\n  width: 1244px;\n  margin-left: 0;\n}\n.table .span17 {\n  float: none;\n  width: 1324px;\n  margin-left: 0;\n}\n.table .span18 {\n  float: none;\n  width: 1404px;\n  margin-left: 0;\n}\n.table .span19 {\n  float: none;\n  width: 1484px;\n  margin-left: 0;\n}\n.table .span20 {\n  float: none;\n  width: 1564px;\n  margin-left: 0;\n}\n.table .span21 {\n  float: none;\n  width: 1644px;\n  margin-left: 0;\n}\n.table .span22 {\n  float: none;\n  width: 1724px;\n  margin-left: 0;\n}\n.table .span23 {\n  float: none;\n  width: 1804px;\n  margin-left: 0;\n}\n.table .span24 {\n  float: none;\n  width: 1884px;\n  margin-left: 0;\n}\n.table tbody tr.success td {\n  background-color: #dff0d8;\n}\n.table tbody tr.error td {\n  background-color: #f2dede;\n}\n.table tbody tr.warning td {\n  background-color: #fcf8e3;\n}\n.table tbody tr.info td {\n  background-color: #d9edf7;\n}\n.table-hover tbody tr.success:hover td {\n  background-color: #d0e9c6;\n}\n.table-hover tbody tr.error:hover td {\n  background-color: #ebcccc;\n}\n.table-hover tbody tr.warning:hover td {\n  background-color: #faf2cc;\n}\n.table-hover tbody tr.info:hover td {\n  background-color: #c4e3f3;\n}\nform {\n  margin: 0 0 20px;\n}\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: 40px;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\nlegend small {\n  font-size: 15px;\n  color: #999999;\n}\nlabel,\ninput,\nbutton,\nselect,\ntextarea {\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n}\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n}\nlabel {\n  display: block;\n  margin-bottom: 5px;\n}\nselect,\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  display: inline-block;\n  height: 20px;\n  padding: 4px 6px;\n  margin-bottom: 9px;\n  font-size: 14px;\n  line-height: 20px;\n  color: #555555;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n}\ninput,\ntextarea,\n.uneditable-input {\n  width: 206px;\n}\ntextarea {\n  height: auto;\n}\ntextarea,\ninput[type=\"text\"],\ninput[type=\"password\"],\ninput[type=\"datetime\"],\ninput[type=\"datetime-local\"],\ninput[type=\"date\"],\ninput[type=\"month\"],\ninput[type=\"time\"],\ninput[type=\"week\"],\ninput[type=\"number\"],\ninput[type=\"email\"],\ninput[type=\"url\"],\ninput[type=\"search\"],\ninput[type=\"tel\"],\ninput[type=\"color\"],\n.uneditable-input {\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border linear .2s, box-shadow linear .2s;\n  -moz-transition: border linear .2s, box-shadow linear .2s;\n  -o-transition: border linear .2s, box-shadow linear .2s;\n  transition: border linear .2s, box-shadow linear .2s;\n}\ntextarea:focus,\ninput[type=\"text\"]:focus,\ninput[type=\"password\"]:focus,\ninput[type=\"datetime\"]:focus,\ninput[type=\"datetime-local\"]:focus,\ninput[type=\"date\"]:focus,\ninput[type=\"month\"]:focus,\ninput[type=\"time\"]:focus,\ninput[type=\"week\"]:focus,\ninput[type=\"number\"]:focus,\ninput[type=\"email\"]:focus,\ninput[type=\"url\"]:focus,\ninput[type=\"search\"]:focus,\ninput[type=\"tel\"]:focus,\ninput[type=\"color\"]:focus,\n.uneditable-input:focus {\n  border-color: rgba(82, 168, 236, 0.8);\n  outline: 0;\n  outline: thin dotted \\9;\n  /* IE6-9 */\n\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  *margin-top: 0;\n  /* IE7 */\n\n  margin-top: 1px \\9;\n  /* IE8-9 */\n\n  line-height: normal;\n  cursor: pointer;\n}\ninput[type=\"file\"],\ninput[type=\"image\"],\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"],\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  width: auto;\n}\nselect,\ninput[type=\"file\"] {\n  height: 30px;\n  /* In IE7, the height of the select element cannot be changed by height, only font-size */\n\n  *margin-top: 4px;\n  /* For IE7, add top margin to align select with labels */\n\n  line-height: 30px;\n}\nselect {\n  width: 220px;\n  border: 1px solid #cccccc;\n  background-color: #ffffff;\n}\nselect[multiple],\nselect[size] {\n  height: auto;\n}\nselect:focus,\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.uneditable-input,\n.uneditable-textarea {\n  color: #999999;\n  background-color: #fcfcfc;\n  border-color: #cccccc;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);\n  cursor: not-allowed;\n}\n.uneditable-input {\n  overflow: hidden;\n  white-space: nowrap;\n}\n.uneditable-textarea {\n  width: auto;\n  height: auto;\n}\ninput:-moz-placeholder,\ntextarea:-moz-placeholder {\n  color: #999999;\n}\ninput:-ms-input-placeholder,\ntextarea:-ms-input-placeholder {\n  color: #999999;\n}\ninput::-webkit-input-placeholder,\ntextarea::-webkit-input-placeholder {\n  color: #999999;\n}\n.radio,\n.checkbox {\n  min-height: 18px;\n  padding-left: 18px;\n}\n.radio input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -18px;\n}\n.controls > .radio:first-child,\n.controls > .checkbox:first-child {\n  padding-top: 5px;\n}\n.radio.inline,\n.checkbox.inline {\n  display: inline-block;\n  padding-top: 5px;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n.radio.inline + .radio.inline,\n.checkbox.inline + .checkbox.inline {\n  margin-left: 10px;\n}\n.input-mini {\n  width: 60px;\n}\n.input-small {\n  width: 90px;\n}\n.input-medium {\n  width: 150px;\n}\n.input-large {\n  width: 210px;\n}\n.input-xlarge {\n  width: 270px;\n}\n.input-xxlarge {\n  width: 530px;\n}\ninput[class*=\"span\"],\nselect[class*=\"span\"],\ntextarea[class*=\"span\"],\n.uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"] {\n  float: none;\n  margin-left: 0;\n}\n.input-append input[class*=\"span\"],\n.input-append .uneditable-input[class*=\"span\"],\n.input-prepend input[class*=\"span\"],\n.input-prepend .uneditable-input[class*=\"span\"],\n.row-fluid input[class*=\"span\"],\n.row-fluid select[class*=\"span\"],\n.row-fluid textarea[class*=\"span\"],\n.row-fluid .uneditable-input[class*=\"span\"],\n.row-fluid .input-prepend [class*=\"span\"],\n.row-fluid .input-append [class*=\"span\"] {\n  display: inline-block;\n}\ninput,\ntextarea,\n.uneditable-input {\n  margin-left: 0;\n}\n.controls-row [class*=\"span\"] + [class*=\"span\"] {\n  margin-left: 20px;\n}\ninput.span12, textarea.span12, .uneditable-input.span12 {\n  width: 926px;\n}\ninput.span11, textarea.span11, .uneditable-input.span11 {\n  width: 846px;\n}\ninput.span10, textarea.span10, .uneditable-input.span10 {\n  width: 766px;\n}\ninput.span9, textarea.span9, .uneditable-input.span9 {\n  width: 686px;\n}\ninput.span8, textarea.span8, .uneditable-input.span8 {\n  width: 606px;\n}\ninput.span7, textarea.span7, .uneditable-input.span7 {\n  width: 526px;\n}\ninput.span6, textarea.span6, .uneditable-input.span6 {\n  width: 446px;\n}\ninput.span5, textarea.span5, .uneditable-input.span5 {\n  width: 366px;\n}\ninput.span4, textarea.span4, .uneditable-input.span4 {\n  width: 286px;\n}\ninput.span3, textarea.span3, .uneditable-input.span3 {\n  width: 206px;\n}\ninput.span2, textarea.span2, .uneditable-input.span2 {\n  width: 126px;\n}\ninput.span1, textarea.span1, .uneditable-input.span1 {\n  width: 46px;\n}\n.controls-row {\n  *zoom: 1;\n}\n.controls-row:before,\n.controls-row:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.controls-row:after {\n  clear: both;\n}\n.controls-row [class*=\"span\"] {\n  float: left;\n}\ninput[disabled],\nselect[disabled],\ntextarea[disabled],\ninput[readonly],\nselect[readonly],\ntextarea[readonly] {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"][readonly],\ninput[type=\"checkbox\"][readonly] {\n  background-color: transparent;\n}\n.control-group.warning > label,\n.control-group.warning .help-block,\n.control-group.warning .help-inline {\n  color: #c09853;\n}\n.control-group.warning .checkbox,\n.control-group.warning .radio,\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  color: #c09853;\n}\n.control-group.warning input,\n.control-group.warning select,\n.control-group.warning textarea {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.control-group.warning input:focus,\n.control-group.warning select:focus,\n.control-group.warning textarea:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n.control-group.warning .input-prepend .add-on,\n.control-group.warning .input-append .add-on {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n.control-group.error > label,\n.control-group.error .help-block,\n.control-group.error .help-inline {\n  color: #b94a48;\n}\n.control-group.error .checkbox,\n.control-group.error .radio,\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  color: #b94a48;\n}\n.control-group.error input,\n.control-group.error select,\n.control-group.error textarea {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.control-group.error input:focus,\n.control-group.error select:focus,\n.control-group.error textarea:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n.control-group.error .input-prepend .add-on,\n.control-group.error .input-append .add-on {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n.control-group.success > label,\n.control-group.success .help-block,\n.control-group.success .help-inline {\n  color: #468847;\n}\n.control-group.success .checkbox,\n.control-group.success .radio,\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  color: #468847;\n}\n.control-group.success input,\n.control-group.success select,\n.control-group.success textarea {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.control-group.success input:focus,\n.control-group.success select:focus,\n.control-group.success textarea:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n.control-group.success .input-prepend .add-on,\n.control-group.success .input-append .add-on {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n.control-group.info > label,\n.control-group.info .help-block,\n.control-group.info .help-inline {\n  color: #3a87ad;\n}\n.control-group.info .checkbox,\n.control-group.info .radio,\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  color: #3a87ad;\n}\n.control-group.info input,\n.control-group.info select,\n.control-group.info textarea {\n  border-color: #3a87ad;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.control-group.info input:focus,\n.control-group.info select:focus,\n.control-group.info textarea:focus {\n  border-color: #2d6987;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;\n}\n.control-group.info .input-prepend .add-on,\n.control-group.info .input-append .add-on {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #3a87ad;\n}\ninput:focus:required:invalid,\ntextarea:focus:required:invalid,\nselect:focus:required:invalid {\n  color: #b94a48;\n  border-color: #ee5f5b;\n}\ninput:focus:required:invalid:focus,\ntextarea:focus:required:invalid:focus,\nselect:focus:required:invalid:focus {\n  border-color: #e9322d;\n  -webkit-box-shadow: 0 0 6px #f8b9b7;\n  -moz-box-shadow: 0 0 6px #f8b9b7;\n  box-shadow: 0 0 6px #f8b9b7;\n}\n.form-actions {\n  padding: 19px 20px 20px;\n  margin-top: 20px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #e5e5e5;\n  *zoom: 1;\n}\n.form-actions:before,\n.form-actions:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.form-actions:after {\n  clear: both;\n}\n.help-block,\n.help-inline {\n  color: #595959;\n}\n.help-block {\n  display: block;\n  margin-bottom: 10px;\n}\n.help-inline {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n  vertical-align: middle;\n  padding-left: 5px;\n}\n.input-append,\n.input-prepend {\n  margin-bottom: 5px;\n  font-size: 0;\n  white-space: nowrap;\n}\n.input-append input,\n.input-prepend input,\n.input-append select,\n.input-prepend select,\n.input-append .uneditable-input,\n.input-prepend .uneditable-input {\n  position: relative;\n  margin-bottom: 0;\n  *margin-left: 0;\n  font-size: 14px;\n  vertical-align: top;\n  -webkit-border-radius: 0 3px 3px 0;\n  -moz-border-radius: 0 3px 3px 0;\n  border-radius: 0 3px 3px 0;\n}\n.input-append input:focus,\n.input-prepend input:focus,\n.input-append select:focus,\n.input-prepend select:focus,\n.input-append .uneditable-input:focus,\n.input-prepend .uneditable-input:focus {\n  z-index: 2;\n}\n.input-append .add-on,\n.input-prepend .add-on {\n  display: inline-block;\n  width: auto;\n  height: 20px;\n  min-width: 16px;\n  padding: 4px 5px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 20px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n}\n.input-append .add-on,\n.input-prepend .add-on,\n.input-append .btn,\n.input-prepend .btn {\n  vertical-align: top;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.input-append .active,\n.input-prepend .active {\n  background-color: #a9dba9;\n  border-color: #46a546;\n}\n.input-prepend .add-on,\n.input-prepend .btn {\n  margin-right: -1px;\n}\n.input-prepend .add-on:first-child,\n.input-prepend .btn:first-child {\n  -webkit-border-radius: 3px 0 0 3px;\n  -moz-border-radius: 3px 0 0 3px;\n  border-radius: 3px 0 0 3px;\n}\n.input-append input,\n.input-append select,\n.input-append .uneditable-input {\n  -webkit-border-radius: 3px 0 0 3px;\n  -moz-border-radius: 3px 0 0 3px;\n  border-radius: 3px 0 0 3px;\n}\n.input-append .add-on,\n.input-append .btn {\n  margin-left: -1px;\n}\n.input-append .add-on:last-child,\n.input-append .btn:last-child {\n  -webkit-border-radius: 0 3px 3px 0;\n  -moz-border-radius: 0 3px 3px 0;\n  border-radius: 0 3px 3px 0;\n}\n.input-prepend.input-append input,\n.input-prepend.input-append select,\n.input-prepend.input-append .uneditable-input {\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.input-prepend.input-append .add-on:first-child,\n.input-prepend.input-append .btn:first-child {\n  margin-right: -1px;\n  -webkit-border-radius: 3px 0 0 3px;\n  -moz-border-radius: 3px 0 0 3px;\n  border-radius: 3px 0 0 3px;\n}\n.input-prepend.input-append .add-on:last-child,\n.input-prepend.input-append .btn:last-child {\n  margin-left: -1px;\n  -webkit-border-radius: 0 3px 3px 0;\n  -moz-border-radius: 0 3px 3px 0;\n  border-radius: 0 3px 3px 0;\n}\ninput.search-query {\n  padding-right: 14px;\n  padding-right: 4px \\9;\n  padding-left: 14px;\n  padding-left: 4px \\9;\n  /* IE7-8 doesn't have border-radius, so don't indent the padding */\n\n  margin-bottom: 0;\n  -webkit-border-radius: 15px;\n  -moz-border-radius: 15px;\n  border-radius: 15px;\n}\n/* Allow for input prepend/append in search forms */\n.form-search .input-append .search-query,\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.form-search .input-append .search-query {\n  -webkit-border-radius: 14px 0 0 14px;\n  -moz-border-radius: 14px 0 0 14px;\n  border-radius: 14px 0 0 14px;\n}\n.form-search .input-append .btn {\n  -webkit-border-radius: 0 14px 14px 0;\n  -moz-border-radius: 0 14px 14px 0;\n  border-radius: 0 14px 14px 0;\n}\n.form-search .input-prepend .search-query {\n  -webkit-border-radius: 0 14px 14px 0;\n  -moz-border-radius: 0 14px 14px 0;\n  border-radius: 0 14px 14px 0;\n}\n.form-search .input-prepend .btn {\n  -webkit-border-radius: 14px 0 0 14px;\n  -moz-border-radius: 14px 0 0 14px;\n  border-radius: 14px 0 0 14px;\n}\n.form-search input,\n.form-inline input,\n.form-horizontal input,\n.form-search textarea,\n.form-inline textarea,\n.form-horizontal textarea,\n.form-search select,\n.form-inline select,\n.form-horizontal select,\n.form-search .help-inline,\n.form-inline .help-inline,\n.form-horizontal .help-inline,\n.form-search .uneditable-input,\n.form-inline .uneditable-input,\n.form-horizontal .uneditable-input,\n.form-search .input-prepend,\n.form-inline .input-prepend,\n.form-horizontal .input-prepend,\n.form-search .input-append,\n.form-inline .input-append,\n.form-horizontal .input-append {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n.form-search .hide,\n.form-inline .hide,\n.form-horizontal .hide {\n  display: none;\n}\n.form-search label,\n.form-inline label,\n.form-search .btn-group,\n.form-inline .btn-group {\n  display: inline-block;\n}\n.form-search .input-append,\n.form-inline .input-append,\n.form-search .input-prepend,\n.form-inline .input-prepend {\n  margin-bottom: 0;\n}\n.form-search .radio,\n.form-search .checkbox,\n.form-inline .radio,\n.form-inline .checkbox {\n  padding-left: 0;\n  margin-bottom: 0;\n  vertical-align: middle;\n}\n.form-search .radio input[type=\"radio\"],\n.form-search .checkbox input[type=\"checkbox\"],\n.form-inline .radio input[type=\"radio\"],\n.form-inline .checkbox input[type=\"checkbox\"] {\n  float: left;\n  margin-right: 3px;\n  margin-left: 0;\n}\n.control-group {\n  margin-bottom: 10px;\n}\nlegend + .control-group {\n  margin-top: 20px;\n  -webkit-margin-top-collapse: separate;\n}\n.form-horizontal .control-group {\n  margin-bottom: 20px;\n  *zoom: 1;\n}\n.form-horizontal .control-group:before,\n.form-horizontal .control-group:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.form-horizontal .control-group:after {\n  clear: both;\n}\n.form-horizontal .control-label {\n  float: left;\n  width: 160px;\n  padding-top: 5px;\n  text-align: right;\n}\n.form-horizontal .controls {\n  *display: inline-block;\n  *padding-left: 20px;\n  margin-left: 180px;\n  *margin-left: 0;\n}\n.form-horizontal .controls:first-child {\n  *padding-left: 180px;\n}\n.form-horizontal .help-block {\n  margin-bottom: 0;\n}\n.form-horizontal input + .help-block,\n.form-horizontal select + .help-block,\n.form-horizontal textarea + .help-block {\n  margin-top: 10px;\n}\n.form-horizontal .form-actions {\n  padding-left: 180px;\n}\n.btn {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n  padding: 4px 14px;\n  margin-bottom: 0;\n  font-size: 14px;\n  line-height: 20px;\n  *line-height: 20px;\n  text-align: center;\n  vertical-align: middle;\n  cursor: pointer;\n  color: #333333;\n  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);\n  background-color: #f5f5f5;\n  background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));\n  background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);\n  background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);\n  border-color: #e6e6e6 #e6e6e6 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  *background-color: #e6e6e6;\n  /* Darken IE7 buttons by default so they stand out more given they won't have borders */\n\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  border: 1px solid #bbbbbb;\n  *border: 0;\n  border-bottom-color: #a2a2a2;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n  *margin-left: .3em;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n  -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.btn:hover,\n.btn:active,\n.btn.active,\n.btn.disabled,\n.btn[disabled] {\n  color: #333333;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n}\n.btn:active,\n.btn.active {\n  background-color: #cccccc \\9;\n}\n.btn:first-child {\n  *margin-left: 0;\n}\n.btn:hover {\n  color: #333333;\n  text-decoration: none;\n  background-color: #e6e6e6;\n  *background-color: #d9d9d9;\n  /* Buttons in IE7 don't get borders, so darken on hover */\n\n  background-position: 0 -15px;\n  -webkit-transition: background-position 0.1s linear;\n  -moz-transition: background-position 0.1s linear;\n  -o-transition: background-position 0.1s linear;\n  transition: background-position 0.1s linear;\n}\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.btn.active,\n.btn:active {\n  background-color: #e6e6e6;\n  background-color: #d9d9d9 \\9;\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n  -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.btn.disabled,\n.btn[disabled] {\n  cursor: default;\n  background-color: #e6e6e6;\n  background-image: none;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n  -moz-box-shadow: none;\n  box-shadow: none;\n}\n.btn-large {\n  padding: 9px 14px;\n  font-size: 16px;\n  line-height: normal;\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  border-radius: 5px;\n}\n.btn-large [class^=\"icon-\"] {\n  margin-top: 2px;\n}\n.btn-small {\n  padding: 3px 9px;\n  font-size: 12px;\n  line-height: 18px;\n}\n.btn-small [class^=\"icon-\"] {\n  margin-top: 0;\n}\n.btn-mini {\n  padding: 2px 6px;\n  font-size: 11px;\n  line-height: 17px;\n}\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-left: 0;\n  padding-right: 0;\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n.btn-primary.active,\n.btn-warning.active,\n.btn-danger.active,\n.btn-success.active,\n.btn-info.active,\n.btn-inverse.active {\n  color: rgba(255, 255, 255, 0.75);\n}\n.btn {\n  border-color: #c5c5c5;\n  border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);\n}\n.btn-primary {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #006dcc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(to bottom, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  *background-color: #0044cc;\n  /* Darken IE7 buttons by default so they stand out more given they won't have borders */\n\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.btn-primary:hover,\n.btn-primary:active,\n.btn-primary.active,\n.btn-primary.disabled,\n.btn-primary[disabled] {\n  color: #ffffff;\n  background-color: #0044cc;\n  *background-color: #003bb3;\n}\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #003399 \\9;\n}\n.btn-warning {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n  border-color: #f89406 #f89406 #ad6704;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  *background-color: #f89406;\n  /* Darken IE7 buttons by default so they stand out more given they won't have borders */\n\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.btn-warning:hover,\n.btn-warning:active,\n.btn-warning.active,\n.btn-warning.disabled,\n.btn-warning[disabled] {\n  color: #ffffff;\n  background-color: #f89406;\n  *background-color: #df8505;\n}\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #c67605 \\9;\n}\n.btn-danger {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #da4f49;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);\n  background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);\n  border-color: #bd362f #bd362f #802420;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  *background-color: #bd362f;\n  /* Darken IE7 buttons by default so they stand out more given they won't have borders */\n\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.btn-danger:hover,\n.btn-danger:active,\n.btn-danger.active,\n.btn-danger.disabled,\n.btn-danger[disabled] {\n  color: #ffffff;\n  background-color: #bd362f;\n  *background-color: #a9302a;\n}\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #942a25 \\9;\n}\n.btn-success {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #5bb75b;\n  background-image: -moz-linear-gradient(top, #62c462, #51a351);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));\n  background-image: -webkit-linear-gradient(top, #62c462, #51a351);\n  background-image: -o-linear-gradient(top, #62c462, #51a351);\n  background-image: linear-gradient(to bottom, #62c462, #51a351);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);\n  border-color: #51a351 #51a351 #387038;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  *background-color: #51a351;\n  /* Darken IE7 buttons by default so they stand out more given they won't have borders */\n\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.btn-success:hover,\n.btn-success:active,\n.btn-success.active,\n.btn-success.disabled,\n.btn-success[disabled] {\n  color: #ffffff;\n  background-color: #51a351;\n  *background-color: #499249;\n}\n.btn-success:active,\n.btn-success.active {\n  background-color: #408140 \\9;\n}\n.btn-info {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #49afcd;\n  background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);\n  background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);\n  border-color: #2f96b4 #2f96b4 #1f6377;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  *background-color: #2f96b4;\n  /* Darken IE7 buttons by default so they stand out more given they won't have borders */\n\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.btn-info:hover,\n.btn-info:active,\n.btn-info.active,\n.btn-info.disabled,\n.btn-info[disabled] {\n  color: #ffffff;\n  background-color: #2f96b4;\n  *background-color: #2a85a0;\n}\n.btn-info:active,\n.btn-info.active {\n  background-color: #24748c \\9;\n}\n.btn-inverse {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #363636;\n  background-image: -moz-linear-gradient(top, #444444, #222222);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));\n  background-image: -webkit-linear-gradient(top, #444444, #222222);\n  background-image: -o-linear-gradient(top, #444444, #222222);\n  background-image: linear-gradient(to bottom, #444444, #222222);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);\n  border-color: #222222 #222222 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  *background-color: #222222;\n  /* Darken IE7 buttons by default so they stand out more given they won't have borders */\n\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.btn-inverse:hover,\n.btn-inverse:active,\n.btn-inverse.active,\n.btn-inverse.disabled,\n.btn-inverse[disabled] {\n  color: #ffffff;\n  background-color: #222222;\n  *background-color: #151515;\n}\n.btn-inverse:active,\n.btn-inverse.active {\n  background-color: #080808 \\9;\n}\nbutton.btn,\ninput[type=\"submit\"].btn {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\nbutton.btn::-moz-focus-inner,\ninput[type=\"submit\"].btn::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\nbutton.btn.btn-large,\ninput[type=\"submit\"].btn.btn-large {\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\nbutton.btn.btn-small,\ninput[type=\"submit\"].btn.btn-small {\n  *padding-top: 3px;\n  *padding-bottom: 3px;\n}\nbutton.btn.btn-mini,\ninput[type=\"submit\"].btn.btn-mini {\n  *padding-top: 1px;\n  *padding-bottom: 1px;\n}\n.btn-link,\n.btn-link:active,\n.btn-link[disabled] {\n  background-color: transparent;\n  background-image: none;\n  -webkit-box-shadow: none;\n  -moz-box-shadow: none;\n  box-shadow: none;\n}\n.btn-link {\n  border-color: transparent;\n  cursor: pointer;\n  color: #0088cc;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.btn-link:hover {\n  color: #005580;\n  text-decoration: underline;\n  background-color: transparent;\n}\n.btn-link[disabled]:hover {\n  color: #333333;\n  text-decoration: none;\n}\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline-block;\n  width: 14px;\n  height: 14px;\n  *margin-right: .3em;\n  line-height: 14px;\n  vertical-align: text-top;\n  background-image: url(\"../img/glyphicons-halflings.png\");\n  background-position: 14px 14px;\n  background-repeat: no-repeat;\n  margin-top: 1px;\n}\n/* White icons with optional class, or on hover/active states of certain elements */\n.icon-white,\n.nav-tabs > .active > a > [class^=\"icon-\"],\n.nav-tabs > .active > a > [class*=\" icon-\"],\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"] {\n  background-image: url(\"../img/glyphicons-halflings-white.png\");\n}\n.icon-glass {\n  background-position: 0      0;\n}\n.icon-music {\n  background-position: -24px 0;\n}\n.icon-search {\n  background-position: -48px 0;\n}\n.icon-envelope {\n  background-position: -72px 0;\n}\n.icon-heart {\n  background-position: -96px 0;\n}\n.icon-star {\n  background-position: -120px 0;\n}\n.icon-star-empty {\n  background-position: -144px 0;\n}\n.icon-user {\n  background-position: -168px 0;\n}\n.icon-film {\n  background-position: -192px 0;\n}\n.icon-th-large {\n  background-position: -216px 0;\n}\n.icon-th {\n  background-position: -240px 0;\n}\n.icon-th-list {\n  background-position: -264px 0;\n}\n.icon-ok {\n  background-position: -288px 0;\n}\n.icon-remove {\n  background-position: -312px 0;\n}\n.icon-zoom-in {\n  background-position: -336px 0;\n}\n.icon-zoom-out {\n  background-position: -360px 0;\n}\n.icon-off {\n  background-position: -384px 0;\n}\n.icon-signal {\n  background-position: -408px 0;\n}\n.icon-cog {\n  background-position: -432px 0;\n}\n.icon-trash {\n  background-position: -456px 0;\n}\n.icon-home {\n  background-position: 0 -24px;\n}\n.icon-file {\n  background-position: -24px -24px;\n}\n.icon-time {\n  background-position: -48px -24px;\n}\n.icon-road {\n  background-position: -72px -24px;\n}\n.icon-download-alt {\n  background-position: -96px -24px;\n}\n.icon-download {\n  background-position: -120px -24px;\n}\n.icon-upload {\n  background-position: -144px -24px;\n}\n.icon-inbox {\n  background-position: -168px -24px;\n}\n.icon-play-circle {\n  background-position: -192px -24px;\n}\n.icon-repeat {\n  background-position: -216px -24px;\n}\n.icon-refresh {\n  background-position: -240px -24px;\n}\n.icon-list-alt {\n  background-position: -264px -24px;\n}\n.icon-lock {\n  background-position: -287px -24px;\n}\n.icon-flag {\n  background-position: -312px -24px;\n}\n.icon-headphones {\n  background-position: -336px -24px;\n}\n.icon-volume-off {\n  background-position: -360px -24px;\n}\n.icon-volume-down {\n  background-position: -384px -24px;\n}\n.icon-volume-up {\n  background-position: -408px -24px;\n}\n.icon-qrcode {\n  background-position: -432px -24px;\n}\n.icon-barcode {\n  background-position: -456px -24px;\n}\n.icon-tag {\n  background-position: 0 -48px;\n}\n.icon-tags {\n  background-position: -25px -48px;\n}\n.icon-book {\n  background-position: -48px -48px;\n}\n.icon-bookmark {\n  background-position: -72px -48px;\n}\n.icon-print {\n  background-position: -96px -48px;\n}\n.icon-camera {\n  background-position: -120px -48px;\n}\n.icon-font {\n  background-position: -144px -48px;\n}\n.icon-bold {\n  background-position: -167px -48px;\n}\n.icon-italic {\n  background-position: -192px -48px;\n}\n.icon-text-height {\n  background-position: -216px -48px;\n}\n.icon-text-width {\n  background-position: -240px -48px;\n}\n.icon-align-left {\n  background-position: -264px -48px;\n}\n.icon-align-center {\n  background-position: -288px -48px;\n}\n.icon-align-right {\n  background-position: -312px -48px;\n}\n.icon-align-justify {\n  background-position: -336px -48px;\n}\n.icon-list {\n  background-position: -360px -48px;\n}\n.icon-indent-left {\n  background-position: -384px -48px;\n}\n.icon-indent-right {\n  background-position: -408px -48px;\n}\n.icon-facetime-video {\n  background-position: -432px -48px;\n}\n.icon-picture {\n  background-position: -456px -48px;\n}\n.icon-pencil {\n  background-position: 0 -72px;\n}\n.icon-map-marker {\n  background-position: -24px -72px;\n}\n.icon-adjust {\n  background-position: -48px -72px;\n}\n.icon-tint {\n  background-position: -72px -72px;\n}\n.icon-edit {\n  background-position: -96px -72px;\n}\n.icon-share {\n  background-position: -120px -72px;\n}\n.icon-check {\n  background-position: -144px -72px;\n}\n.icon-move {\n  background-position: -168px -72px;\n}\n.icon-step-backward {\n  background-position: -192px -72px;\n}\n.icon-fast-backward {\n  background-position: -216px -72px;\n}\n.icon-backward {\n  background-position: -240px -72px;\n}\n.icon-play {\n  background-position: -264px -72px;\n}\n.icon-pause {\n  background-position: -288px -72px;\n}\n.icon-stop {\n  background-position: -312px -72px;\n}\n.icon-forward {\n  background-position: -336px -72px;\n}\n.icon-fast-forward {\n  background-position: -360px -72px;\n}\n.icon-step-forward {\n  background-position: -384px -72px;\n}\n.icon-eject {\n  background-position: -408px -72px;\n}\n.icon-chevron-left {\n  background-position: -432px -72px;\n}\n.icon-chevron-right {\n  background-position: -456px -72px;\n}\n.icon-plus-sign {\n  background-position: 0 -96px;\n}\n.icon-minus-sign {\n  background-position: -24px -96px;\n}\n.icon-remove-sign {\n  background-position: -48px -96px;\n}\n.icon-ok-sign {\n  background-position: -72px -96px;\n}\n.icon-question-sign {\n  background-position: -96px -96px;\n}\n.icon-info-sign {\n  background-position: -120px -96px;\n}\n.icon-screenshot {\n  background-position: -144px -96px;\n}\n.icon-remove-circle {\n  background-position: -168px -96px;\n}\n.icon-ok-circle {\n  background-position: -192px -96px;\n}\n.icon-ban-circle {\n  background-position: -216px -96px;\n}\n.icon-arrow-left {\n  background-position: -240px -96px;\n}\n.icon-arrow-right {\n  background-position: -264px -96px;\n}\n.icon-arrow-up {\n  background-position: -289px -96px;\n}\n.icon-arrow-down {\n  background-position: -312px -96px;\n}\n.icon-share-alt {\n  background-position: -336px -96px;\n}\n.icon-resize-full {\n  background-position: -360px -96px;\n}\n.icon-resize-small {\n  background-position: -384px -96px;\n}\n.icon-plus {\n  background-position: -408px -96px;\n}\n.icon-minus {\n  background-position: -433px -96px;\n}\n.icon-asterisk {\n  background-position: -456px -96px;\n}\n.icon-exclamation-sign {\n  background-position: 0 -120px;\n}\n.icon-gift {\n  background-position: -24px -120px;\n}\n.icon-leaf {\n  background-position: -48px -120px;\n}\n.icon-fire {\n  background-position: -72px -120px;\n}\n.icon-eye-open {\n  background-position: -96px -120px;\n}\n.icon-eye-close {\n  background-position: -120px -120px;\n}\n.icon-warning-sign {\n  background-position: -144px -120px;\n}\n.icon-plane {\n  background-position: -168px -120px;\n}\n.icon-calendar {\n  background-position: -192px -120px;\n}\n.icon-random {\n  background-position: -216px -120px;\n  width: 16px;\n}\n.icon-comment {\n  background-position: -240px -120px;\n}\n.icon-magnet {\n  background-position: -264px -120px;\n}\n.icon-chevron-up {\n  background-position: -288px -120px;\n}\n.icon-chevron-down {\n  background-position: -313px -119px;\n}\n.icon-retweet {\n  background-position: -336px -120px;\n}\n.icon-shopping-cart {\n  background-position: -360px -120px;\n}\n.icon-folder-close {\n  background-position: -384px -120px;\n}\n.icon-folder-open {\n  background-position: -408px -120px;\n  width: 16px;\n}\n.icon-resize-vertical {\n  background-position: -432px -119px;\n}\n.icon-resize-horizontal {\n  background-position: -456px -118px;\n}\n.icon-hdd {\n  background-position: 0 -144px;\n}\n.icon-bullhorn {\n  background-position: -24px -144px;\n}\n.icon-bell {\n  background-position: -48px -144px;\n}\n.icon-certificate {\n  background-position: -72px -144px;\n}\n.icon-thumbs-up {\n  background-position: -96px -144px;\n}\n.icon-thumbs-down {\n  background-position: -120px -144px;\n}\n.icon-hand-right {\n  background-position: -144px -144px;\n}\n.icon-hand-left {\n  background-position: -168px -144px;\n}\n.icon-hand-up {\n  background-position: -192px -144px;\n}\n.icon-hand-down {\n  background-position: -216px -144px;\n}\n.icon-circle-arrow-right {\n  background-position: -240px -144px;\n}\n.icon-circle-arrow-left {\n  background-position: -264px -144px;\n}\n.icon-circle-arrow-up {\n  background-position: -288px -144px;\n}\n.icon-circle-arrow-down {\n  background-position: -312px -144px;\n}\n.icon-globe {\n  background-position: -336px -144px;\n}\n.icon-wrench {\n  background-position: -360px -144px;\n}\n.icon-tasks {\n  background-position: -384px -144px;\n}\n.icon-filter {\n  background-position: -408px -144px;\n}\n.icon-briefcase {\n  background-position: -432px -144px;\n}\n.icon-fullscreen {\n  background-position: -456px -144px;\n}\n.btn-group {\n  position: relative;\n  font-size: 0;\n  vertical-align: middle;\n  white-space: nowrap;\n  *margin-left: .3em;\n}\n.btn-group:first-child {\n  *margin-left: 0;\n}\n.btn-group + .btn-group {\n  margin-left: 5px;\n}\n.btn-toolbar {\n  font-size: 0;\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n.btn-toolbar .btn-group {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n.btn-toolbar .btn + .btn,\n.btn-toolbar .btn-group + .btn,\n.btn-toolbar .btn + .btn-group {\n  margin-left: 5px;\n}\n.btn-group > .btn {\n  position: relative;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.btn-group > .btn + .btn {\n  margin-left: -1px;\n}\n.btn-group > .btn,\n.btn-group > .dropdown-menu {\n  font-size: 14px;\n}\n.btn-group > .btn-mini {\n  font-size: 11px;\n}\n.btn-group > .btn-small {\n  font-size: 12px;\n}\n.btn-group > .btn-large {\n  font-size: 16px;\n}\n.btn-group > .btn:first-child {\n  margin-left: 0;\n  -webkit-border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n  border-top-left-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  border-bottom-left-radius: 4px;\n}\n.btn-group > .btn:last-child,\n.btn-group > .dropdown-toggle {\n  -webkit-border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  border-top-right-radius: 4px;\n  -webkit-border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  border-bottom-right-radius: 4px;\n}\n.btn-group > .btn.large:first-child {\n  margin-left: 0;\n  -webkit-border-top-left-radius: 6px;\n  -moz-border-radius-topleft: 6px;\n  border-top-left-radius: 6px;\n  -webkit-border-bottom-left-radius: 6px;\n  -moz-border-radius-bottomleft: 6px;\n  border-bottom-left-radius: 6px;\n}\n.btn-group > .btn.large:last-child,\n.btn-group > .large.dropdown-toggle {\n  -webkit-border-top-right-radius: 6px;\n  -moz-border-radius-topright: 6px;\n  border-top-right-radius: 6px;\n  -webkit-border-bottom-right-radius: 6px;\n  -moz-border-radius-bottomright: 6px;\n  border-bottom-right-radius: 6px;\n}\n.btn-group > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group > .btn:active,\n.btn-group > .btn.active {\n  z-index: 2;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n  padding-left: 8px;\n  padding-right: 8px;\n  -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n  -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);\n  *padding-top: 5px;\n  *padding-bottom: 5px;\n}\n.btn-group > .btn-mini + .dropdown-toggle {\n  padding-left: 5px;\n  padding-right: 5px;\n  *padding-top: 2px;\n  *padding-bottom: 2px;\n}\n.btn-group > .btn-small + .dropdown-toggle {\n  *padding-top: 5px;\n  *padding-bottom: 4px;\n}\n.btn-group > .btn-large + .dropdown-toggle {\n  padding-left: 12px;\n  padding-right: 12px;\n  *padding-top: 7px;\n  *padding-bottom: 7px;\n}\n.btn-group.open .dropdown-toggle {\n  background-image: none;\n  -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n  -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.btn-group.open .btn.dropdown-toggle {\n  background-color: #e6e6e6;\n}\n.btn-group.open .btn-primary.dropdown-toggle {\n  background-color: #0044cc;\n}\n.btn-group.open .btn-warning.dropdown-toggle {\n  background-color: #f89406;\n}\n.btn-group.open .btn-danger.dropdown-toggle {\n  background-color: #bd362f;\n}\n.btn-group.open .btn-success.dropdown-toggle {\n  background-color: #51a351;\n}\n.btn-group.open .btn-info.dropdown-toggle {\n  background-color: #2f96b4;\n}\n.btn-group.open .btn-inverse.dropdown-toggle {\n  background-color: #222222;\n}\n.btn .caret {\n  margin-top: 8px;\n  margin-left: 0;\n}\n.btn-mini .caret,\n.btn-small .caret,\n.btn-large .caret {\n  margin-top: 6px;\n}\n.btn-large .caret {\n  border-left-width: 5px;\n  border-right-width: 5px;\n  border-top-width: 5px;\n}\n.dropup .btn-large .caret {\n  border-bottom: 5px solid #000000;\n  border-top: 0;\n}\n.btn-primary .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret,\n.btn-success .caret,\n.btn-inverse .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n.btn-group-vertical {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n}\n.btn-group-vertical .btn {\n  display: block;\n  float: none;\n  width: 100%;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.btn-group-vertical .btn + .btn {\n  margin-left: 0;\n  margin-top: -1px;\n}\n.btn-group-vertical .btn:first-child {\n  -webkit-border-radius: 4px 4px 0 0;\n  -moz-border-radius: 4px 4px 0 0;\n  border-radius: 4px 4px 0 0;\n}\n.btn-group-vertical .btn:last-child {\n  -webkit-border-radius: 0 0 4px 4px;\n  -moz-border-radius: 0 0 4px 4px;\n  border-radius: 0 0 4px 4px;\n}\n.btn-group-vertical .btn-large:first-child {\n  -webkit-border-radius: 6px 6px 0 0;\n  -moz-border-radius: 6px 6px 0 0;\n  border-radius: 6px 6px 0 0;\n}\n.btn-group-vertical .btn-large:last-child {\n  -webkit-border-radius: 0 0 6px 6px;\n  -moz-border-radius: 0 0 6px 6px;\n  border-radius: 0 0 6px 6px;\n}\n.nav {\n  margin-left: 0;\n  margin-bottom: 20px;\n  list-style: none;\n}\n.nav > li > a {\n  display: block;\n}\n.nav > li > a:hover {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n.nav > .pull-right {\n  float: right;\n}\n.nav-header {\n  display: block;\n  padding: 3px 15px;\n  font-size: 11px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #999999;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  text-transform: uppercase;\n}\n.nav li + .nav-header {\n  margin-top: 9px;\n}\n.nav-list {\n  padding-left: 15px;\n  padding-right: 15px;\n  margin-bottom: 0;\n}\n.nav-list > li > a,\n.nav-list .nav-header {\n  margin-left: -15px;\n  margin-right: -15px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n}\n.nav-list > li > a {\n  padding: 3px 15px;\n}\n.nav-list > .active > a,\n.nav-list > .active > a:hover {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  background-color: #0088cc;\n}\n.nav-list [class^=\"icon-\"] {\n  margin-right: 2px;\n}\n.nav-list .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n.nav-tabs,\n.nav-pills {\n  *zoom: 1;\n}\n.nav-tabs:before,\n.nav-pills:before,\n.nav-tabs:after,\n.nav-pills:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.nav-tabs:after,\n.nav-pills:after {\n  clear: both;\n}\n.nav-tabs > li,\n.nav-pills > li {\n  float: left;\n}\n.nav-tabs > li > a,\n.nav-pills > li > a {\n  padding-right: 12px;\n  padding-left: 12px;\n  margin-right: 2px;\n  line-height: 14px;\n}\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n  margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  line-height: 20px;\n  border: 1px solid transparent;\n  -webkit-border-radius: 4px 4px 0 0;\n  -moz-border-radius: 4px 4px 0 0;\n  border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n.nav-tabs > .active > a,\n.nav-tabs > .active > a:hover {\n  color: #555555;\n  background-color: #ffffff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n  cursor: default;\n}\n.nav-pills > li > a {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  margin-top: 2px;\n  margin-bottom: 2px;\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  border-radius: 5px;\n}\n.nav-pills > .active > a,\n.nav-pills > .active > a:hover {\n  color: #ffffff;\n  background-color: #0088cc;\n}\n.nav-stacked > li {\n  float: none;\n}\n.nav-stacked > li > a {\n  margin-right: 0;\n}\n.nav-tabs.nav-stacked {\n  border-bottom: 0;\n}\n.nav-tabs.nav-stacked > li > a {\n  border: 1px solid #ddd;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.nav-tabs.nav-stacked > li:first-child > a {\n  -webkit-border-top-right-radius: 4px;\n  -moz-border-radius-topright: 4px;\n  border-top-right-radius: 4px;\n  -webkit-border-top-left-radius: 4px;\n  -moz-border-radius-topleft: 4px;\n  border-top-left-radius: 4px;\n}\n.nav-tabs.nav-stacked > li:last-child > a {\n  -webkit-border-bottom-right-radius: 4px;\n  -moz-border-radius-bottomright: 4px;\n  border-bottom-right-radius: 4px;\n  -webkit-border-bottom-left-radius: 4px;\n  -moz-border-radius-bottomleft: 4px;\n  border-bottom-left-radius: 4px;\n}\n.nav-tabs.nav-stacked > li > a:hover {\n  border-color: #ddd;\n  z-index: 2;\n}\n.nav-pills.nav-stacked > li > a {\n  margin-bottom: 3px;\n}\n.nav-pills.nav-stacked > li:last-child > a {\n  margin-bottom: 1px;\n}\n.nav-tabs .dropdown-menu {\n  -webkit-border-radius: 0 0 6px 6px;\n  -moz-border-radius: 0 0 6px 6px;\n  border-radius: 0 0 6px 6px;\n}\n.nav-pills .dropdown-menu {\n  -webkit-border-radius: 6px;\n  -moz-border-radius: 6px;\n  border-radius: 6px;\n}\n.nav .dropdown-toggle .caret {\n  border-top-color: #0088cc;\n  border-bottom-color: #0088cc;\n  margin-top: 6px;\n}\n.nav .dropdown-toggle:hover .caret {\n  border-top-color: #005580;\n  border-bottom-color: #005580;\n}\n/* move down carets for tabs */\n.nav-tabs .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n.nav .active .dropdown-toggle .caret {\n  border-top-color: #fff;\n  border-bottom-color: #fff;\n}\n.nav-tabs .active .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n.nav > .dropdown.active > a:hover {\n  cursor: pointer;\n}\n.nav-tabs .open .dropdown-toggle,\n.nav-pills .open .dropdown-toggle,\n.nav > li.dropdown.open.active > a:hover {\n  color: #ffffff;\n  background-color: #999999;\n  border-color: #999999;\n}\n.nav li.dropdown.open .caret,\n.nav li.dropdown.open.active .caret,\n.nav li.dropdown.open a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n  opacity: 1;\n  filter: alpha(opacity=100);\n}\n.tabs-stacked .open > a:hover {\n  border-color: #999999;\n}\n.tabbable {\n  *zoom: 1;\n}\n.tabbable:before,\n.tabbable:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.tabbable:after {\n  clear: both;\n}\n.tab-content {\n  overflow: auto;\n}\n.tabs-below > .nav-tabs,\n.tabs-right > .nav-tabs,\n.tabs-left > .nav-tabs {\n  border-bottom: 0;\n}\n.tab-content > .tab-pane,\n.pill-content > .pill-pane {\n  display: none;\n}\n.tab-content > .active,\n.pill-content > .active {\n  display: block;\n}\n.tabs-below > .nav-tabs {\n  border-top: 1px solid #ddd;\n}\n.tabs-below > .nav-tabs > li {\n  margin-top: -1px;\n  margin-bottom: 0;\n}\n.tabs-below > .nav-tabs > li > a {\n  -webkit-border-radius: 0 0 4px 4px;\n  -moz-border-radius: 0 0 4px 4px;\n  border-radius: 0 0 4px 4px;\n}\n.tabs-below > .nav-tabs > li > a:hover {\n  border-bottom-color: transparent;\n  border-top-color: #ddd;\n}\n.tabs-below > .nav-tabs > .active > a,\n.tabs-below > .nav-tabs > .active > a:hover {\n  border-color: transparent #ddd #ddd #ddd;\n}\n.tabs-left > .nav-tabs > li,\n.tabs-right > .nav-tabs > li {\n  float: none;\n}\n.tabs-left > .nav-tabs > li > a,\n.tabs-right > .nav-tabs > li > a {\n  min-width: 74px;\n  margin-right: 0;\n  margin-bottom: 3px;\n}\n.tabs-left > .nav-tabs {\n  float: left;\n  margin-right: 19px;\n  border-right: 1px solid #ddd;\n}\n.tabs-left > .nav-tabs > li > a {\n  margin-right: -1px;\n  -webkit-border-radius: 4px 0 0 4px;\n  -moz-border-radius: 4px 0 0 4px;\n  border-radius: 4px 0 0 4px;\n}\n.tabs-left > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #dddddd #eeeeee #eeeeee;\n}\n.tabs-left > .nav-tabs .active > a,\n.tabs-left > .nav-tabs .active > a:hover {\n  border-color: #ddd transparent #ddd #ddd;\n  *border-right-color: #ffffff;\n}\n.tabs-right > .nav-tabs {\n  float: right;\n  margin-left: 19px;\n  border-left: 1px solid #ddd;\n}\n.tabs-right > .nav-tabs > li > a {\n  margin-left: -1px;\n  -webkit-border-radius: 0 4px 4px 0;\n  -moz-border-radius: 0 4px 4px 0;\n  border-radius: 0 4px 4px 0;\n}\n.tabs-right > .nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #eeeeee #dddddd;\n}\n.tabs-right > .nav-tabs .active > a,\n.tabs-right > .nav-tabs .active > a:hover {\n  border-color: #ddd #ddd #ddd transparent;\n  *border-left-color: #ffffff;\n}\n.nav > .disabled > a {\n  color: #999999;\n}\n.nav > .disabled > a:hover {\n  text-decoration: none;\n  background-color: transparent;\n  cursor: default;\n}\n.navbar {\n  overflow: visible;\n  margin-bottom: 20px;\n  color: #777777;\n  *position: relative;\n  *z-index: 2;\n}\n.navbar-inner {\n  min-height: 40px;\n  padding-left: 20px;\n  padding-right: 20px;\n  background-color: #fafafa;\n  background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));\n  background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);\n  background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);\n  border: 1px solid #d4d4d4;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n  -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);\n  *zoom: 1;\n}\n.navbar-inner:before,\n.navbar-inner:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.navbar-inner:after {\n  clear: both;\n}\n.navbar .container {\n  width: auto;\n}\n.nav-collapse.collapse {\n  height: auto;\n}\n.navbar .brand {\n  float: left;\n  display: block;\n  padding: 10px 20px 10px;\n  margin-left: -20px;\n  font-size: 20px;\n  font-weight: 200;\n  color: #777777;\n  text-shadow: 0 1px 0 #ffffff;\n}\n.navbar .brand:hover {\n  text-decoration: none;\n}\n.navbar-text {\n  margin-bottom: 0;\n  line-height: 40px;\n}\n.navbar-link {\n  color: #777777;\n}\n.navbar-link:hover {\n  color: #333333;\n}\n.navbar .divider-vertical {\n  height: 40px;\n  margin: 0 9px;\n  border-left: 1px solid #f2f2f2;\n  border-right: 1px solid #ffffff;\n}\n.navbar .btn,\n.navbar .btn-group {\n  margin-top: 5px;\n}\n.navbar .btn-group .btn,\n.navbar .input-prepend .btn,\n.navbar .input-append .btn {\n  margin-top: 0;\n}\n.navbar-form {\n  margin-bottom: 0;\n  *zoom: 1;\n}\n.navbar-form:before,\n.navbar-form:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.navbar-form:after {\n  clear: both;\n}\n.navbar-form input,\n.navbar-form select,\n.navbar-form .radio,\n.navbar-form .checkbox {\n  margin-top: 5px;\n}\n.navbar-form input,\n.navbar-form select,\n.navbar-form .btn {\n  display: inline-block;\n  margin-bottom: 0;\n}\n.navbar-form input[type=\"image\"],\n.navbar-form input[type=\"checkbox\"],\n.navbar-form input[type=\"radio\"] {\n  margin-top: 3px;\n}\n.navbar-form .input-append,\n.navbar-form .input-prepend {\n  margin-top: 6px;\n  white-space: nowrap;\n}\n.navbar-form .input-append input,\n.navbar-form .input-prepend input {\n  margin-top: 0;\n}\n.navbar-search {\n  position: relative;\n  float: left;\n  margin-top: 5px;\n  margin-bottom: 0;\n}\n.navbar-search .search-query {\n  margin-bottom: 0;\n  padding: 4px 14px;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-border-radius: 15px;\n  -moz-border-radius: 15px;\n  border-radius: 15px;\n}\n.navbar-static-top {\n  position: static;\n  width: 100%;\n  margin-bottom: 0;\n}\n.navbar-static-top .navbar-inner {\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n  margin-bottom: 0;\n}\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  border-width: 0 0 1px;\n}\n.navbar-fixed-bottom .navbar-inner {\n  border-width: 1px 0 0;\n}\n.navbar-fixed-top .navbar-inner,\n.navbar-fixed-bottom .navbar-inner {\n  padding-left: 0;\n  padding-right: 0;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.navbar-static-top .container,\n.navbar-fixed-top .container,\n.navbar-fixed-bottom .container {\n  width: 940px;\n}\n.navbar-fixed-top {\n  top: 0;\n}\n.navbar-fixed-top .navbar-inner,\n.navbar-static-top .navbar-inner {\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1), 0 1px 10px rgba(0, 0, 0, 0.1);\n  -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1), 0 1px 10px rgba(0, 0, 0, 0.1);\n  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1), 0 1px 10px rgba(0, 0, 0, 0.1);\n}\n.navbar-fixed-bottom {\n  bottom: 0;\n}\n.navbar-fixed-bottom .navbar-inner {\n  -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.1), 0 -1px 10px rgba(0, 0, 0, 0.1);\n  -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.1), 0 -1px 10px rgba(0, 0, 0, 0.1);\n  box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.1), 0 -1px 10px rgba(0, 0, 0, 0.1);\n}\n.navbar .nav {\n  position: relative;\n  left: 0;\n  display: block;\n  float: left;\n  margin: 0 10px 0 0;\n}\n.navbar .nav.pull-right {\n  float: right;\n  margin-right: 0;\n}\n.navbar .nav > li {\n  float: left;\n}\n.navbar .nav > li > a {\n  float: none;\n  padding: 10px 15px 10px;\n  color: #777777;\n  text-decoration: none;\n  text-shadow: 0 1px 0 #ffffff;\n}\n.navbar .nav .dropdown-toggle .caret {\n  margin-top: 8px;\n}\n.navbar .nav > li > a:focus,\n.navbar .nav > li > a:hover {\n  background-color: transparent;\n  color: #333333;\n  text-decoration: none;\n}\n.navbar .nav > .active > a,\n.navbar .nav > .active > a:hover,\n.navbar .nav > .active > a:focus {\n  color: #555555;\n  text-decoration: none;\n  background-color: #e5e5e5;\n  -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n  -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n  box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);\n}\n.navbar .btn-navbar {\n  display: none;\n  float: right;\n  padding: 7px 10px;\n  margin-left: 5px;\n  margin-right: 5px;\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #ededed;\n  background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));\n  background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);\n  background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);\n  border-color: #e5e5e5 #e5e5e5 #bfbfbf;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  *background-color: #e5e5e5;\n  /* Darken IE7 buttons by default so they stand out more given they won't have borders */\n\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n  -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);\n}\n.navbar .btn-navbar:hover,\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active,\n.navbar .btn-navbar.disabled,\n.navbar .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #e5e5e5;\n  *background-color: #d9d9d9;\n}\n.navbar .btn-navbar:active,\n.navbar .btn-navbar.active {\n  background-color: #cccccc \\9;\n}\n.navbar .btn-navbar .icon-bar {\n  display: block;\n  width: 18px;\n  height: 2px;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 1px;\n  -moz-border-radius: 1px;\n  border-radius: 1px;\n  -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n  -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);\n}\n.btn-navbar .icon-bar + .icon-bar {\n  margin-top: 3px;\n}\n.navbar .nav > li > .dropdown-menu:before {\n  content: '';\n  display: inline-block;\n  border-left: 7px solid transparent;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  position: absolute;\n  top: -7px;\n  left: 9px;\n}\n.navbar .nav > li > .dropdown-menu:after {\n  content: '';\n  display: inline-block;\n  border-left: 6px solid transparent;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  position: absolute;\n  top: -6px;\n  left: 10px;\n}\n.navbar-fixed-bottom .nav > li > .dropdown-menu:before {\n  border-top: 7px solid #ccc;\n  border-top-color: rgba(0, 0, 0, 0.2);\n  border-bottom: 0;\n  bottom: -7px;\n  top: auto;\n}\n.navbar-fixed-bottom .nav > li > .dropdown-menu:after {\n  border-top: 6px solid #ffffff;\n  border-bottom: 0;\n  bottom: -6px;\n  top: auto;\n}\n.navbar .nav li.dropdown.open > .dropdown-toggle,\n.navbar .nav li.dropdown.active > .dropdown-toggle,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle {\n  background-color: #e5e5e5;\n  color: #555555;\n}\n.navbar .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n.navbar .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n.navbar .pull-right > li > .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right {\n  left: auto;\n  right: 0;\n}\n.navbar .pull-right > li > .dropdown-menu:before,\n.navbar .nav > li > .dropdown-menu.pull-right:before {\n  left: auto;\n  right: 12px;\n}\n.navbar .pull-right > li > .dropdown-menu:after,\n.navbar .nav > li > .dropdown-menu.pull-right:after {\n  left: auto;\n  right: 13px;\n}\n.navbar .pull-right > li > .dropdown-menu .dropdown-menu,\n.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {\n  left: auto;\n  right: 100%;\n  margin-left: 0;\n  margin-right: -1px;\n  -webkit-border-radius: 6px 0 6px 6px;\n  -moz-border-radius: 6px 0 6px 6px;\n  border-radius: 6px 0 6px 6px;\n}\n.navbar-inverse {\n  color: #999999;\n}\n.navbar-inverse .navbar-inner {\n  background-color: #1b1b1b;\n  background-image: -moz-linear-gradient(top, #222222, #111111);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));\n  background-image: -webkit-linear-gradient(top, #222222, #111111);\n  background-image: -o-linear-gradient(top, #222222, #111111);\n  background-image: linear-gradient(to bottom, #222222, #111111);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);\n  border-color: #252525;\n}\n.navbar-inverse .brand,\n.navbar-inverse .nav > li > a {\n  color: #999999;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .brand:hover,\n.navbar-inverse .nav > li > a:hover {\n  color: #ffffff;\n}\n.navbar-inverse .nav > li > a:focus,\n.navbar-inverse .nav > li > a:hover {\n  background-color: transparent;\n  color: #ffffff;\n}\n.navbar-inverse .nav .active > a,\n.navbar-inverse .nav .active > a:hover,\n.navbar-inverse .nav .active > a:focus {\n  color: #ffffff;\n  background-color: #111111;\n}\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n.navbar-inverse .divider-vertical {\n  border-left-color: #111111;\n  border-right-color: #222222;\n}\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {\n  background-color: #111111;\n  color: #ffffff;\n}\n.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,\n.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n.navbar-inverse .navbar-search .search-query {\n  color: #ffffff;\n  background-color: #515151;\n  border-color: #111111;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);\n  -webkit-transition: none;\n  -moz-transition: none;\n  -o-transition: none;\n  transition: none;\n}\n.navbar-inverse .navbar-search .search-query:-moz-placeholder {\n  color: #cccccc;\n}\n.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {\n  color: #cccccc;\n}\n.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {\n  color: #cccccc;\n}\n.navbar-inverse .navbar-search .search-query:focus,\n.navbar-inverse .navbar-search .search-query.focused {\n  padding: 5px 15px;\n  color: #333333;\n  text-shadow: 0 1px 0 #ffffff;\n  background-color: #ffffff;\n  border: 0;\n  -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n  -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n  box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);\n  outline: 0;\n}\n.navbar-inverse .btn-navbar {\n  color: #ffffff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e0e0e;\n  background-image: -moz-linear-gradient(top, #151515, #040404);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));\n  background-image: -webkit-linear-gradient(top, #151515, #040404);\n  background-image: -o-linear-gradient(top, #151515, #040404);\n  background-image: linear-gradient(to bottom, #151515, #040404);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);\n  border-color: #040404 #040404 #000000;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  *background-color: #040404;\n  /* Darken IE7 buttons by default so they stand out more given they won't have borders */\n\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.navbar-inverse .btn-navbar:hover,\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active,\n.navbar-inverse .btn-navbar.disabled,\n.navbar-inverse .btn-navbar[disabled] {\n  color: #ffffff;\n  background-color: #040404;\n  *background-color: #000000;\n}\n.navbar-inverse .btn-navbar:active,\n.navbar-inverse .btn-navbar.active {\n  background-color: #000000 \\9;\n}\n.breadcrumb {\n  padding: 8px 15px;\n  margin: 0 0 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.breadcrumb li {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n  text-shadow: 0 1px 0 #ffffff;\n}\n.breadcrumb .divider {\n  padding: 0 5px;\n  color: #ccc;\n}\n.breadcrumb .active {\n  color: #999999;\n}\n.pagination {\n  height: 40px;\n  margin: 20px 0;\n}\n.pagination ul {\n  display: inline-block;\n  *display: inline;\n  /* IE7 inline-block hack */\n\n  *zoom: 1;\n  margin-left: 0;\n  margin-bottom: 0;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n  -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.pagination ul > li {\n  display: inline;\n}\n.pagination ul > li > a,\n.pagination ul > li > span {\n  float: left;\n  padding: 0 14px;\n  line-height: 38px;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-left-width: 0;\n}\n.pagination ul > li > a:hover,\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  background-color: #f5f5f5;\n}\n.pagination ul > .active > a,\n.pagination ul > .active > span {\n  color: #999999;\n  cursor: default;\n}\n.pagination ul > .disabled > span,\n.pagination ul > .disabled > a,\n.pagination ul > .disabled > a:hover {\n  color: #999999;\n  background-color: transparent;\n  cursor: default;\n}\n.pagination ul > li:first-child > a,\n.pagination ul > li:first-child > span {\n  border-left-width: 1px;\n  -webkit-border-radius: 3px 0 0 3px;\n  -moz-border-radius: 3px 0 0 3px;\n  border-radius: 3px 0 0 3px;\n}\n.pagination ul > li:last-child > a,\n.pagination ul > li:last-child > span {\n  -webkit-border-radius: 0 3px 3px 0;\n  -moz-border-radius: 0 3px 3px 0;\n  border-radius: 0 3px 3px 0;\n}\n.pagination-centered {\n  text-align: center;\n}\n.pagination-right {\n  text-align: right;\n}\n.pager {\n  margin: 20px 0;\n  list-style: none;\n  text-align: center;\n  *zoom: 1;\n}\n.pager:before,\n.pager:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.pager:after {\n  clear: both;\n}\n.pager li {\n  display: inline;\n}\n.pager a,\n.pager span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 15px;\n  -moz-border-radius: 15px;\n  border-radius: 15px;\n}\n.pager a:hover {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n.pager .next a,\n.pager .next span {\n  float: right;\n}\n.pager .previous a {\n  float: left;\n}\n.pager .disabled a,\n.pager .disabled a:hover,\n.pager .disabled span {\n  color: #999999;\n  background-color: #fff;\n  cursor: default;\n}\n.thumbnails {\n  margin-left: -20px;\n  list-style: none;\n  *zoom: 1;\n}\n.thumbnails:before,\n.thumbnails:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.thumbnails:after {\n  clear: both;\n}\n.row-fluid .thumbnails {\n  margin-left: 0;\n}\n.thumbnails > li {\n  float: left;\n  margin-bottom: 20px;\n  margin-left: 20px;\n}\n.thumbnail {\n  display: block;\n  padding: 4px;\n  line-height: 20px;\n  border: 1px solid #ddd;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);\n  -webkit-transition: all 0.2s ease-in-out;\n  -moz-transition: all 0.2s ease-in-out;\n  -o-transition: all 0.2s ease-in-out;\n  transition: all 0.2s ease-in-out;\n}\na.thumbnail:hover {\n  border-color: #0088cc;\n  -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n  -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n  box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);\n}\n.thumbnail > img {\n  display: block;\n  max-width: 100%;\n  margin-left: auto;\n  margin-right: auto;\n}\n.thumbnail .caption {\n  padding: 9px;\n  color: #555555;\n}\n.alert {\n  padding: 8px 35px 8px 14px;\n  margin-bottom: 20px;\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n  background-color: #fcf8e3;\n  border: 1px solid #fbeed5;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n  color: #c09853;\n}\n.alert h4 {\n  margin: 0;\n}\n.alert .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  line-height: 20px;\n}\n.alert-success {\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n  color: #468847;\n}\n.alert-danger,\n.alert-error {\n  background-color: #f2dede;\n  border-color: #eed3d7;\n  color: #b94a48;\n}\n.alert-info {\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n  color: #3a87ad;\n}\n.alert-block {\n  padding-top: 14px;\n  padding-bottom: 14px;\n}\n.alert-block > p,\n.alert-block > ul {\n  margin-bottom: 0;\n}\n.alert-block p + p {\n  margin-top: 5px;\n}\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n@-ms-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n.progress {\n  overflow: hidden;\n  height: 20px;\n  margin-bottom: 20px;\n  background-color: #f7f7f7;\n  background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));\n  background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);\n  background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n  -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.progress .bar {\n  width: 0%;\n  height: 100%;\n  color: #ffffff;\n  float: left;\n  font-size: 12px;\n  text-align: center;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n  background-color: #0e90d2;\n  background-image: -moz-linear-gradient(top, #149bdf, #0480be);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));\n  background-image: -webkit-linear-gradient(top, #149bdf, #0480be);\n  background-image: -o-linear-gradient(top, #149bdf, #0480be);\n  background-image: linear-gradient(to bottom, #149bdf, #0480be);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  -webkit-transition: width 0.6s ease;\n  -moz-transition: width 0.6s ease;\n  -o-transition: width 0.6s ease;\n  transition: width 0.6s ease;\n}\n.progress .bar + .bar {\n  -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n}\n.progress-striped .bar {\n  background-color: #149bdf;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n  -moz-background-size: 40px 40px;\n  -o-background-size: 40px 40px;\n  background-size: 40px 40px;\n}\n.progress.active .bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n  -moz-animation: progress-bar-stripes 2s linear infinite;\n  -ms-animation: progress-bar-stripes 2s linear infinite;\n  -o-animation: progress-bar-stripes 2s linear infinite;\n  animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-danger .bar,\n.progress .bar-danger {\n  background-color: #dd514c;\n  background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));\n  background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);\n  background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);\n}\n.progress-danger.progress-striped .bar,\n.progress-striped .bar-danger {\n  background-color: #ee5f5b;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-success .bar,\n.progress .bar-success {\n  background-color: #5eb95e;\n  background-image: -moz-linear-gradient(top, #62c462, #57a957);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));\n  background-image: -webkit-linear-gradient(top, #62c462, #57a957);\n  background-image: -o-linear-gradient(top, #62c462, #57a957);\n  background-image: linear-gradient(to bottom, #62c462, #57a957);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);\n}\n.progress-success.progress-striped .bar,\n.progress-striped .bar-success {\n  background-color: #62c462;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-info .bar,\n.progress .bar-info {\n  background-color: #4bb1cf;\n  background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));\n  background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: -o-linear-gradient(top, #5bc0de, #339bb9);\n  background-image: linear-gradient(to bottom, #5bc0de, #339bb9);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);\n}\n.progress-info.progress-striped .bar,\n.progress-striped .bar-info {\n  background-color: #5bc0de;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-warning .bar,\n.progress .bar-warning {\n  background-color: #faa732;\n  background-image: -moz-linear-gradient(top, #fbb450, #f89406);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));\n  background-image: -webkit-linear-gradient(top, #fbb450, #f89406);\n  background-image: -o-linear-gradient(top, #fbb450, #f89406);\n  background-image: linear-gradient(to bottom, #fbb450, #f89406);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);\n}\n.progress-warning.progress-striped .bar,\n.progress-striped .bar-warning {\n  background-color: #fbb450;\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.hero-unit {\n  padding: 60px;\n  margin-bottom: 30px;\n  background-color: #eeeeee;\n  -webkit-border-radius: 6px;\n  -moz-border-radius: 6px;\n  border-radius: 6px;\n}\n.hero-unit h1 {\n  margin-bottom: 0;\n  font-size: 60px;\n  line-height: 1;\n  color: inherit;\n  letter-spacing: -1px;\n}\n.hero-unit p {\n  font-size: 18px;\n  font-weight: 200;\n  line-height: 30px;\n  color: inherit;\n}\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  visibility: visible;\n  padding: 5px;\n  font-size: 11px;\n  opacity: 0;\n  filter: alpha(opacity=0);\n}\n.tooltip.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n.tooltip.top {\n  margin-top: -3px;\n}\n.tooltip.right {\n  margin-left: 3px;\n}\n.tooltip.bottom {\n  margin-top: 3px;\n}\n.tooltip.left {\n  margin-left: -3px;\n}\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-width: 5px 5px 0;\n  border-top-color: #000000;\n}\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-width: 5px 5px 5px 0;\n  border-right-color: #000000;\n}\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-width: 5px 0 5px 5px;\n  border-left-color: #000000;\n}\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: #000000;\n}\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  width: 236px;\n  padding: 1px;\n  background-color: #ffffff;\n  -webkit-background-clip: padding-box;\n  -moz-background-clip: padding;\n  background-clip: padding-box;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  -webkit-border-radius: 6px;\n  -moz-border-radius: 6px;\n  border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n  margin-bottom: 10px;\n}\n.popover.right {\n  margin-left: 10px;\n}\n.popover.bottom {\n  margin-top: 10px;\n}\n.popover.left {\n  margin-right: 10px;\n}\n.popover-title {\n  margin: 0;\n  padding: 8px 14px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  -webkit-border-radius: 5px 5px 0 0;\n  -moz-border-radius: 5px 5px 0 0;\n  border-radius: 5px 5px 0 0;\n}\n.popover-content {\n  padding: 9px 14px;\n}\n.popover-content p,\n.popover-content ul,\n.popover-content ol {\n  margin-bottom: 0;\n}\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: inline-block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.popover .arrow:after {\n  content: \"\";\n  z-index: -1;\n}\n.popover.top .arrow {\n  bottom: -10px;\n  left: 50%;\n  margin-left: -10px;\n  border-width: 10px 10px 0;\n  border-top-color: #ffffff;\n}\n.popover.top .arrow:after {\n  border-width: 11px 11px 0;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  bottom: -1px;\n  left: -11px;\n}\n.popover.right .arrow {\n  top: 50%;\n  left: -10px;\n  margin-top: -10px;\n  border-width: 10px 10px 10px 0;\n  border-right-color: #ffffff;\n}\n.popover.right .arrow:after {\n  border-width: 11px 11px 11px 0;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  bottom: -11px;\n  left: -1px;\n}\n.popover.bottom .arrow {\n  top: -10px;\n  left: 50%;\n  margin-left: -10px;\n  border-width: 0 10px 10px;\n  border-bottom-color: #ffffff;\n}\n.popover.bottom .arrow:after {\n  border-width: 0 11px 11px;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  top: -1px;\n  left: -11px;\n}\n.popover.left .arrow {\n  top: 50%;\n  right: -10px;\n  margin-top: -10px;\n  border-width: 10px 0 10px 10px;\n  border-left-color: #ffffff;\n}\n.popover.left .arrow:after {\n  border-width: 11px 0 11px 11px;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  bottom: -11px;\n  right: -1px;\n}\n.modal-open .modal .dropdown-menu {\n  z-index: 2050;\n}\n.modal-open .modal .dropdown.open {\n  *z-index: 2050;\n}\n.modal-open .modal .popover {\n  z-index: 2060;\n}\n.modal-open .modal .tooltip {\n  z-index: 2080;\n}\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000000;\n}\n.modal-backdrop.fade {\n  opacity: 0;\n}\n.modal-backdrop,\n.modal-backdrop.fade.in {\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n}\n.modal {\n  position: fixed;\n  top: 50%;\n  left: 50%;\n  z-index: 1050;\n  overflow: auto;\n  width: 560px;\n  margin: -250px 0 0 -280px;\n  background-color: #ffffff;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.3);\n  *border: 1px solid #999;\n  /* IE6-7 */\n\n  -webkit-border-radius: 6px;\n  -moz-border-radius: 6px;\n  border-radius: 6px;\n  -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n  -webkit-background-clip: padding-box;\n  -moz-background-clip: padding-box;\n  background-clip: padding-box;\n}\n.modal.fade {\n  -webkit-transition: opacity .3s linear, top .3s ease-out;\n  -moz-transition: opacity .3s linear, top .3s ease-out;\n  -o-transition: opacity .3s linear, top .3s ease-out;\n  transition: opacity .3s linear, top .3s ease-out;\n  top: -25%;\n}\n.modal.fade.in {\n  top: 50%;\n}\n.modal-header {\n  padding: 9px 15px;\n  border-bottom: 1px solid #eee;\n}\n.modal-header .close {\n  margin-top: 2px;\n}\n.modal-header h3 {\n  margin: 0;\n  line-height: 30px;\n}\n.modal-body {\n  overflow-y: auto;\n  max-height: 400px;\n  padding: 15px;\n}\n.modal-form {\n  margin-bottom: 0;\n}\n.modal-footer {\n  padding: 14px 15px 15px;\n  margin-bottom: 0;\n  text-align: right;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  -webkit-border-radius: 0 0 6px 6px;\n  -moz-border-radius: 0 0 6px 6px;\n  border-radius: 0 0 6px 6px;\n  -webkit-box-shadow: inset 0 1px 0 #ffffff;\n  -moz-box-shadow: inset 0 1px 0 #ffffff;\n  box-shadow: inset 0 1px 0 #ffffff;\n  *zoom: 1;\n}\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \"\";\n  line-height: 0;\n}\n.modal-footer:after {\n  clear: both;\n}\n.modal-footer .btn + .btn {\n  margin-left: 5px;\n  margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n.dropup,\n.dropdown {\n  position: relative;\n}\n.dropdown-toggle {\n  *margin-bottom: -3px;\n}\n.dropdown-toggle:active,\n.open .dropdown-toggle {\n  outline: 0;\n}\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  vertical-align: top;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n  content: \"\";\n}\n.dropdown .caret {\n  margin-top: 8px;\n  margin-left: 2px;\n}\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  *border-right-width: 2px;\n  *border-bottom-width: 2px;\n  -webkit-border-radius: 6px;\n  -moz-border-radius: 6px;\n  border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  -webkit-background-clip: padding-box;\n  -moz-background-clip: padding;\n  background-clip: padding-box;\n}\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n.dropdown-menu .divider {\n  *width: 100%;\n  height: 1px;\n  margin: 9px 1px;\n  *margin: -5px 0 5px;\n  overflow: hidden;\n  background-color: #e5e5e5;\n  border-bottom: 1px solid #ffffff;\n}\n.dropdown-menu a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 20px;\n  color: #333333;\n  white-space: nowrap;\n}\n.dropdown-menu li > a:hover,\n.dropdown-menu li > a:focus,\n.dropdown-submenu:hover > a {\n  text-decoration: none;\n  color: #ffffff;\n  background-color: #0088cc;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n.dropdown-menu .active > a,\n.dropdown-menu .active > a:hover {\n  color: #ffffff;\n  text-decoration: none;\n  outline: 0;\n  background-color: #0088cc;\n  background-color: #0081c2;\n  background-image: -moz-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);\n  background-image: -o-linear-gradient(top, #0088cc, #0077b3);\n  background-image: linear-gradient(to bottom, #0088cc, #0077b3);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);\n}\n.dropdown-menu .disabled > a,\n.dropdown-menu .disabled > a:hover {\n  color: #999999;\n}\n.dropdown-menu .disabled > a:hover {\n  text-decoration: none;\n  background-color: transparent;\n  cursor: default;\n}\n.open {\n  *z-index: 1000;\n}\n.open  > .dropdown-menu {\n  display: block;\n}\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n.dropdown-submenu {\n  position: relative;\n}\n.dropdown-submenu > .dropdown-menu {\n  top: 0;\n  left: 100%;\n  margin-top: -6px;\n  margin-left: -1px;\n  -webkit-border-radius: 0 6px 6px 6px;\n  -moz-border-radius: 0 6px 6px 6px;\n  border-radius: 0 6px 6px 6px;\n}\n.dropdown-submenu:hover > .dropdown-menu {\n  display: block;\n}\n.dropdown-submenu > a:after {\n  display: block;\n  content: \" \";\n  float: right;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n  border-width: 5px 0 5px 5px;\n  border-left-color: #cccccc;\n  margin-top: 5px;\n  margin-right: -10px;\n}\n.dropdown-submenu:hover > a:after {\n  border-left-color: #ffffff;\n}\n.dropdown .dropdown-menu .nav-header {\n  padding-left: 20px;\n  padding-right: 20px;\n}\n.typeahead {\n  margin-top: 2px;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.accordion {\n  margin-bottom: 20px;\n}\n.accordion-group {\n  margin-bottom: 2px;\n  border: 1px solid #e5e5e5;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.accordion-heading {\n  border-bottom: 0;\n}\n.accordion-heading .accordion-toggle {\n  display: block;\n  padding: 8px 15px;\n}\n.accordion-toggle {\n  cursor: pointer;\n}\n.accordion-inner {\n  padding: 9px 15px;\n  border-top: 1px solid #e5e5e5;\n}\n.carousel {\n  position: relative;\n  margin-bottom: 20px;\n  line-height: 1;\n}\n.carousel-inner {\n  overflow: hidden;\n  width: 100%;\n  position: relative;\n}\n.carousel .item {\n  display: none;\n  position: relative;\n  -webkit-transition: 0.6s ease-in-out left;\n  -moz-transition: 0.6s ease-in-out left;\n  -o-transition: 0.6s ease-in-out left;\n  transition: 0.6s ease-in-out left;\n}\n.carousel .item > img {\n  display: block;\n  line-height: 1;\n}\n.carousel .active,\n.carousel .next,\n.carousel .prev {\n  display: block;\n}\n.carousel .active {\n  left: 0;\n}\n.carousel .next,\n.carousel .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n.carousel .next {\n  left: 100%;\n}\n.carousel .prev {\n  left: -100%;\n}\n.carousel .next.left,\n.carousel .prev.right {\n  left: 0;\n}\n.carousel .active.left {\n  left: -100%;\n}\n.carousel .active.right {\n  left: 100%;\n}\n.carousel-control {\n  position: absolute;\n  top: 40%;\n  left: 15px;\n  width: 40px;\n  height: 40px;\n  margin-top: -20px;\n  font-size: 60px;\n  font-weight: 100;\n  line-height: 30px;\n  color: #ffffff;\n  text-align: center;\n  background: #222222;\n  border: 3px solid #ffffff;\n  -webkit-border-radius: 23px;\n  -moz-border-radius: 23px;\n  border-radius: 23px;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n.carousel-control.right {\n  left: auto;\n  right: 15px;\n}\n.carousel-control:hover {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n.carousel-caption {\n  position: absolute;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  padding: 15px;\n  background: #333333;\n  background: rgba(0, 0, 0, 0.75);\n}\n.carousel-caption h4,\n.carousel-caption p {\n  color: #ffffff;\n  line-height: 20px;\n}\n.carousel-caption h4 {\n  margin: 0 0 5px;\n}\n.carousel-caption p {\n  margin-bottom: 0;\n}\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n  -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n.well-large {\n  padding: 24px;\n  -webkit-border-radius: 6px;\n  -moz-border-radius: 6px;\n  border-radius: 6px;\n}\n.well-small {\n  padding: 9px;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n}\n.close {\n  float: right;\n  font-size: 20px;\n  font-weight: bold;\n  line-height: 20px;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n.close:hover {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.4;\n  filter: alpha(opacity=40);\n}\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n.pull-right {\n  float: right;\n}\n.pull-left {\n  float: left;\n}\n.hide {\n  display: none;\n}\n.show {\n  display: block;\n}\n.invisible {\n  visibility: hidden;\n}\n.affix {\n  position: fixed;\n}\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n  -moz-transition: opacity 0.15s linear;\n  -o-transition: opacity 0.15s linear;\n  transition: opacity 0.15s linear;\n}\n.fade.in {\n  opacity: 1;\n}\n.collapse {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n  -moz-transition: height 0.35s ease;\n  -o-transition: height 0.35s ease;\n  transition: height 0.35s ease;\n}\n.collapse.in {\n  height: auto;\n}\n.hidden {\n  display: none;\n  visibility: hidden;\n}\n.visible-phone {\n  display: none !important;\n}\n.visible-tablet {\n  display: none !important;\n}\n.hidden-desktop {\n  display: none !important;\n}\n.visible-desktop {\n  display: inherit !important;\n}\n@media (min-width: 768px) and (max-width: 979px) {\n  .hidden-desktop {\n    display: inherit !important;\n  }\n  .visible-desktop {\n    display: none !important ;\n  }\n  .visible-tablet {\n    display: inherit !important;\n  }\n  .hidden-tablet {\n    display: none !important;\n  }\n}\n@media (max-width: 767px) {\n  .hidden-desktop {\n    display: inherit !important;\n  }\n  .visible-desktop {\n    display: none !important;\n  }\n  .visible-phone {\n    display: inherit !important;\n  }\n  .hidden-phone {\n    display: none !important;\n  }\n}\n@media (max-width: 767px) {\n  body {\n    padding-left: 20px;\n    padding-right: 20px;\n  }\n  .navbar-fixed-top,\n  .navbar-fixed-bottom,\n  .navbar-static-top {\n    margin-left: -20px;\n    margin-right: -20px;\n  }\n  .container-fluid {\n    padding: 0;\n  }\n  .dl-horizontal dt {\n    float: none;\n    clear: none;\n    width: auto;\n    text-align: left;\n  }\n  .dl-horizontal dd {\n    margin-left: 0;\n  }\n  .container {\n    width: auto;\n  }\n  .row-fluid {\n    width: 100%;\n  }\n  .row,\n  .thumbnails {\n    margin-left: 0;\n  }\n  .thumbnails > li {\n    float: none;\n    margin-left: 0;\n  }\n  [class*=\"span\"],\n  .row-fluid [class*=\"span\"] {\n    float: none;\n    display: block;\n    width: 100%;\n    margin-left: 0;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n  }\n  .span12,\n  .row-fluid .span12 {\n    width: 100%;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n  }\n  .input-large,\n  .input-xlarge,\n  .input-xxlarge,\n  input[class*=\"span\"],\n  select[class*=\"span\"],\n  textarea[class*=\"span\"],\n  .uneditable-input {\n    display: block;\n    width: 100%;\n    min-height: 30px;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n  }\n  .input-prepend input,\n  .input-append input,\n  .input-prepend input[class*=\"span\"],\n  .input-append input[class*=\"span\"] {\n    display: inline-block;\n    width: auto;\n  }\n  .controls-row [class*=\"span\"] + [class*=\"span\"] {\n    margin-left: 0;\n  }\n  .modal {\n    position: fixed;\n    top: 20px;\n    left: 20px;\n    right: 20px;\n    width: auto;\n    margin: 0;\n  }\n  .modal.fade.in {\n    top: auto;\n  }\n}\n@media (max-width: 480px) {\n  .nav-collapse {\n    -webkit-transform: translate3d(0, 0, 0);\n  }\n  .page-header h1 small {\n    display: block;\n    line-height: 20px;\n  }\n  input[type=\"checkbox\"],\n  input[type=\"radio\"] {\n    border: 1px solid #ccc;\n  }\n  .form-horizontal .control-label {\n    float: none;\n    width: auto;\n    padding-top: 0;\n    text-align: left;\n  }\n  .form-horizontal .controls {\n    margin-left: 0;\n  }\n  .form-horizontal .control-list {\n    padding-top: 0;\n  }\n  .form-horizontal .form-actions {\n    padding-left: 10px;\n    padding-right: 10px;\n  }\n  .modal {\n    top: 10px;\n    left: 10px;\n    right: 10px;\n  }\n  .modal-header .close {\n    padding: 10px;\n    margin: -10px;\n  }\n  .carousel-caption {\n    position: static;\n  }\n}\n@media (min-width: 768px) and (max-width: 979px) {\n  .row {\n    margin-left: -20px;\n    *zoom: 1;\n  }\n  .row:before,\n  .row:after {\n    display: table;\n    content: \"\";\n    line-height: 0;\n  }\n  .row:after {\n    clear: both;\n  }\n  [class*=\"span\"] {\n    float: left;\n    min-height: 1px;\n    margin-left: 20px;\n  }\n  .container,\n  .navbar-static-top .container,\n  .navbar-fixed-top .container,\n  .navbar-fixed-bottom .container {\n    width: 724px;\n  }\n  .span12 {\n    width: 724px;\n  }\n  .span11 {\n    width: 662px;\n  }\n  .span10 {\n    width: 600px;\n  }\n  .span9 {\n    width: 538px;\n  }\n  .span8 {\n    width: 476px;\n  }\n  .span7 {\n    width: 414px;\n  }\n  .span6 {\n    width: 352px;\n  }\n  .span5 {\n    width: 290px;\n  }\n  .span4 {\n    width: 228px;\n  }\n  .span3 {\n    width: 166px;\n  }\n  .span2 {\n    width: 104px;\n  }\n  .span1 {\n    width: 42px;\n  }\n  .offset12 {\n    margin-left: 764px;\n  }\n  .offset11 {\n    margin-left: 702px;\n  }\n  .offset10 {\n    margin-left: 640px;\n  }\n  .offset9 {\n    margin-left: 578px;\n  }\n  .offset8 {\n    margin-left: 516px;\n  }\n  .offset7 {\n    margin-left: 454px;\n  }\n  .offset6 {\n    margin-left: 392px;\n  }\n  .offset5 {\n    margin-left: 330px;\n  }\n  .offset4 {\n    margin-left: 268px;\n  }\n  .offset3 {\n    margin-left: 206px;\n  }\n  .offset2 {\n    margin-left: 144px;\n  }\n  .offset1 {\n    margin-left: 82px;\n  }\n  .row-fluid {\n    width: 100%;\n    *zoom: 1;\n  }\n  .row-fluid:before,\n  .row-fluid:after {\n    display: table;\n    content: \"\";\n    line-height: 0;\n  }\n  .row-fluid:after {\n    clear: both;\n  }\n  .row-fluid [class*=\"span\"] {\n    display: block;\n    width: 100%;\n    min-height: 30px;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n    float: left;\n    margin-left: 2.7624309392265194%;\n    *margin-left: 2.709239449864817%;\n  }\n  .row-fluid [class*=\"span\"]:first-child {\n    margin-left: 0;\n  }\n  .row-fluid .span12 {\n    width: 100%;\n    *width: 99.94680851063829%;\n  }\n  .row-fluid .span11 {\n    width: 91.43646408839778%;\n    *width: 91.38327259903608%;\n  }\n  .row-fluid .span10 {\n    width: 82.87292817679558%;\n    *width: 82.81973668743387%;\n  }\n  .row-fluid .span9 {\n    width: 74.30939226519337%;\n    *width: 74.25620077583166%;\n  }\n  .row-fluid .span8 {\n    width: 65.74585635359117%;\n    *width: 65.69266486422946%;\n  }\n  .row-fluid .span7 {\n    width: 57.18232044198895%;\n    *width: 57.12912895262725%;\n  }\n  .row-fluid .span6 {\n    width: 48.61878453038674%;\n    *width: 48.56559304102504%;\n  }\n  .row-fluid .span5 {\n    width: 40.05524861878453%;\n    *width: 40.00205712942283%;\n  }\n  .row-fluid .span4 {\n    width: 31.491712707182323%;\n    *width: 31.43852121782062%;\n  }\n  .row-fluid .span3 {\n    width: 22.92817679558011%;\n    *width: 22.87498530621841%;\n  }\n  .row-fluid .span2 {\n    width: 14.3646408839779%;\n    *width: 14.311449394616199%;\n  }\n  .row-fluid .span1 {\n    width: 5.801104972375691%;\n    *width: 5.747913483013988%;\n  }\n  .row-fluid .offset12 {\n    margin-left: 105.52486187845304%;\n    *margin-left: 105.41847889972962%;\n  }\n  .row-fluid .offset12:first-child {\n    margin-left: 102.76243093922652%;\n    *margin-left: 102.6560479605031%;\n  }\n  .row-fluid .offset11 {\n    margin-left: 96.96132596685082%;\n    *margin-left: 96.8549429881274%;\n  }\n  .row-fluid .offset11:first-child {\n    margin-left: 94.1988950276243%;\n    *margin-left: 94.09251204890089%;\n  }\n  .row-fluid .offset10 {\n    margin-left: 88.39779005524862%;\n    *margin-left: 88.2914070765252%;\n  }\n  .row-fluid .offset10:first-child {\n    margin-left: 85.6353591160221%;\n    *margin-left: 85.52897613729868%;\n  }\n  .row-fluid .offset9 {\n    margin-left: 79.8342541436464%;\n    *margin-left: 79.72787116492299%;\n  }\n  .row-fluid .offset9:first-child {\n    margin-left: 77.07182320441989%;\n    *margin-left: 76.96544022569647%;\n  }\n  .row-fluid .offset8 {\n    margin-left: 71.2707182320442%;\n    *margin-left: 71.16433525332079%;\n  }\n  .row-fluid .offset8:first-child {\n    margin-left: 68.50828729281768%;\n    *margin-left: 68.40190431409427%;\n  }\n  .row-fluid .offset7 {\n    margin-left: 62.70718232044199%;\n    *margin-left: 62.600799341718584%;\n  }\n  .row-fluid .offset7:first-child {\n    margin-left: 59.94475138121547%;\n    *margin-left: 59.838368402492065%;\n  }\n  .row-fluid .offset6 {\n    margin-left: 54.14364640883978%;\n    *margin-left: 54.037263430116376%;\n  }\n  .row-fluid .offset6:first-child {\n    margin-left: 51.38121546961326%;\n    *margin-left: 51.27483249088986%;\n  }\n  .row-fluid .offset5 {\n    margin-left: 45.58011049723757%;\n    *margin-left: 45.47372751851417%;\n  }\n  .row-fluid .offset5:first-child {\n    margin-left: 42.81767955801105%;\n    *margin-left: 42.71129657928765%;\n  }\n  .row-fluid .offset4 {\n    margin-left: 37.01657458563536%;\n    *margin-left: 36.91019160691196%;\n  }\n  .row-fluid .offset4:first-child {\n    margin-left: 34.25414364640884%;\n    *margin-left: 34.14776066768544%;\n  }\n  .row-fluid .offset3 {\n    margin-left: 28.45303867403315%;\n    *margin-left: 28.346655695309746%;\n  }\n  .row-fluid .offset3:first-child {\n    margin-left: 25.69060773480663%;\n    *margin-left: 25.584224756083227%;\n  }\n  .row-fluid .offset2 {\n    margin-left: 19.88950276243094%;\n    *margin-left: 19.783119783707537%;\n  }\n  .row-fluid .offset2:first-child {\n    margin-left: 17.12707182320442%;\n    *margin-left: 17.02068884448102%;\n  }\n  .row-fluid .offset1 {\n    margin-left: 11.32596685082873%;\n    *margin-left: 11.219583872105325%;\n  }\n  .row-fluid .offset1:first-child {\n    margin-left: 8.56353591160221%;\n    *margin-left: 8.457152932878806%;\n  }\n  input,\n  textarea,\n  .uneditable-input {\n    margin-left: 0;\n  }\n  .controls-row [class*=\"span\"] + [class*=\"span\"] {\n    margin-left: 20px;\n  }\n  input.span12, textarea.span12, .uneditable-input.span12 {\n    width: 710px;\n  }\n  input.span11, textarea.span11, .uneditable-input.span11 {\n    width: 648px;\n  }\n  input.span10, textarea.span10, .uneditable-input.span10 {\n    width: 586px;\n  }\n  input.span9, textarea.span9, .uneditable-input.span9 {\n    width: 524px;\n  }\n  input.span8, textarea.span8, .uneditable-input.span8 {\n    width: 462px;\n  }\n  input.span7, textarea.span7, .uneditable-input.span7 {\n    width: 400px;\n  }\n  input.span6, textarea.span6, .uneditable-input.span6 {\n    width: 338px;\n  }\n  input.span5, textarea.span5, .uneditable-input.span5 {\n    width: 276px;\n  }\n  input.span4, textarea.span4, .uneditable-input.span4 {\n    width: 214px;\n  }\n  input.span3, textarea.span3, .uneditable-input.span3 {\n    width: 152px;\n  }\n  input.span2, textarea.span2, .uneditable-input.span2 {\n    width: 90px;\n  }\n  input.span1, textarea.span1, .uneditable-input.span1 {\n    width: 28px;\n  }\n}\n@media (min-width: 1200px) {\n  .row {\n    margin-left: -30px;\n    *zoom: 1;\n  }\n  .row:before,\n  .row:after {\n    display: table;\n    content: \"\";\n    line-height: 0;\n  }\n  .row:after {\n    clear: both;\n  }\n  [class*=\"span\"] {\n    float: left;\n    min-height: 1px;\n    margin-left: 30px;\n  }\n  .container,\n  .navbar-static-top .container,\n  .navbar-fixed-top .container,\n  .navbar-fixed-bottom .container {\n    width: 1170px;\n  }\n  .span12 {\n    width: 1170px;\n  }\n  .span11 {\n    width: 1070px;\n  }\n  .span10 {\n    width: 970px;\n  }\n  .span9 {\n    width: 870px;\n  }\n  .span8 {\n    width: 770px;\n  }\n  .span7 {\n    width: 670px;\n  }\n  .span6 {\n    width: 570px;\n  }\n  .span5 {\n    width: 470px;\n  }\n  .span4 {\n    width: 370px;\n  }\n  .span3 {\n    width: 270px;\n  }\n  .span2 {\n    width: 170px;\n  }\n  .span1 {\n    width: 70px;\n  }\n  .offset12 {\n    margin-left: 1230px;\n  }\n  .offset11 {\n    margin-left: 1130px;\n  }\n  .offset10 {\n    margin-left: 1030px;\n  }\n  .offset9 {\n    margin-left: 930px;\n  }\n  .offset8 {\n    margin-left: 830px;\n  }\n  .offset7 {\n    margin-left: 730px;\n  }\n  .offset6 {\n    margin-left: 630px;\n  }\n  .offset5 {\n    margin-left: 530px;\n  }\n  .offset4 {\n    margin-left: 430px;\n  }\n  .offset3 {\n    margin-left: 330px;\n  }\n  .offset2 {\n    margin-left: 230px;\n  }\n  .offset1 {\n    margin-left: 130px;\n  }\n  .row-fluid {\n    width: 100%;\n    *zoom: 1;\n  }\n  .row-fluid:before,\n  .row-fluid:after {\n    display: table;\n    content: \"\";\n    line-height: 0;\n  }\n  .row-fluid:after {\n    clear: both;\n  }\n  .row-fluid [class*=\"span\"] {\n    display: block;\n    width: 100%;\n    min-height: 30px;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n    float: left;\n    margin-left: 2.564102564102564%;\n    *margin-left: 2.5109110747408616%;\n  }\n  .row-fluid [class*=\"span\"]:first-child {\n    margin-left: 0;\n  }\n  .row-fluid .span12 {\n    width: 100%;\n    *width: 99.94680851063829%;\n  }\n  .row-fluid .span11 {\n    width: 91.45299145299145%;\n    *width: 91.39979996362975%;\n  }\n  .row-fluid .span10 {\n    width: 82.90598290598291%;\n    *width: 82.8527914166212%;\n  }\n  .row-fluid .span9 {\n    width: 74.35897435897436%;\n    *width: 74.30578286961266%;\n  }\n  .row-fluid .span8 {\n    width: 65.81196581196582%;\n    *width: 65.75877432260411%;\n  }\n  .row-fluid .span7 {\n    width: 57.26495726495726%;\n    *width: 57.21176577559556%;\n  }\n  .row-fluid .span6 {\n    width: 48.717948717948715%;\n    *width: 48.664757228587014%;\n  }\n  .row-fluid .span5 {\n    width: 40.17094017094017%;\n    *width: 40.11774868157847%;\n  }\n  .row-fluid .span4 {\n    width: 31.623931623931625%;\n    *width: 31.570740134569924%;\n  }\n  .row-fluid .span3 {\n    width: 23.076923076923077%;\n    *width: 23.023731587561375%;\n  }\n  .row-fluid .span2 {\n    width: 14.52991452991453%;\n    *width: 14.476723040552828%;\n  }\n  .row-fluid .span1 {\n    width: 5.982905982905983%;\n    *width: 5.929714493544281%;\n  }\n  .row-fluid .offset12 {\n    margin-left: 105.12820512820512%;\n    *margin-left: 105.02182214948171%;\n  }\n  .row-fluid .offset12:first-child {\n    margin-left: 102.56410256410257%;\n    *margin-left: 102.45771958537915%;\n  }\n  .row-fluid .offset11 {\n    margin-left: 96.58119658119658%;\n    *margin-left: 96.47481360247316%;\n  }\n  .row-fluid .offset11:first-child {\n    margin-left: 94.01709401709402%;\n    *margin-left: 93.91071103837061%;\n  }\n  .row-fluid .offset10 {\n    margin-left: 88.03418803418803%;\n    *margin-left: 87.92780505546462%;\n  }\n  .row-fluid .offset10:first-child {\n    margin-left: 85.47008547008548%;\n    *margin-left: 85.36370249136206%;\n  }\n  .row-fluid .offset9 {\n    margin-left: 79.48717948717949%;\n    *margin-left: 79.38079650845607%;\n  }\n  .row-fluid .offset9:first-child {\n    margin-left: 76.92307692307693%;\n    *margin-left: 76.81669394435352%;\n  }\n  .row-fluid .offset8 {\n    margin-left: 70.94017094017094%;\n    *margin-left: 70.83378796144753%;\n  }\n  .row-fluid .offset8:first-child {\n    margin-left: 68.37606837606839%;\n    *margin-left: 68.26968539734497%;\n  }\n  .row-fluid .offset7 {\n    margin-left: 62.393162393162385%;\n    *margin-left: 62.28677941443899%;\n  }\n  .row-fluid .offset7:first-child {\n    margin-left: 59.82905982905982%;\n    *margin-left: 59.72267685033642%;\n  }\n  .row-fluid .offset6 {\n    margin-left: 53.84615384615384%;\n    *margin-left: 53.739770867430444%;\n  }\n  .row-fluid .offset6:first-child {\n    margin-left: 51.28205128205128%;\n    *margin-left: 51.175668303327875%;\n  }\n  .row-fluid .offset5 {\n    margin-left: 45.299145299145295%;\n    *margin-left: 45.1927623204219%;\n  }\n  .row-fluid .offset5:first-child {\n    margin-left: 42.73504273504273%;\n    *margin-left: 42.62865975631933%;\n  }\n  .row-fluid .offset4 {\n    margin-left: 36.75213675213675%;\n    *margin-left: 36.645753773413354%;\n  }\n  .row-fluid .offset4:first-child {\n    margin-left: 34.18803418803419%;\n    *margin-left: 34.081651209310785%;\n  }\n  .row-fluid .offset3 {\n    margin-left: 28.205128205128204%;\n    *margin-left: 28.0987452264048%;\n  }\n  .row-fluid .offset3:first-child {\n    margin-left: 25.641025641025642%;\n    *margin-left: 25.53464266230224%;\n  }\n  .row-fluid .offset2 {\n    margin-left: 19.65811965811966%;\n    *margin-left: 19.551736679396257%;\n  }\n  .row-fluid .offset2:first-child {\n    margin-left: 17.094017094017094%;\n    *margin-left: 16.98763411529369%;\n  }\n  .row-fluid .offset1 {\n    margin-left: 11.11111111111111%;\n    *margin-left: 11.004728132387708%;\n  }\n  .row-fluid .offset1:first-child {\n    margin-left: 8.547008547008547%;\n    *margin-left: 8.440625568285142%;\n  }\n  input,\n  textarea,\n  .uneditable-input {\n    margin-left: 0;\n  }\n  .controls-row [class*=\"span\"] + [class*=\"span\"] {\n    margin-left: 30px;\n  }\n  input.span12, textarea.span12, .uneditable-input.span12 {\n    width: 1156px;\n  }\n  input.span11, textarea.span11, .uneditable-input.span11 {\n    width: 1056px;\n  }\n  input.span10, textarea.span10, .uneditable-input.span10 {\n    width: 956px;\n  }\n  input.span9, textarea.span9, .uneditable-input.span9 {\n    width: 856px;\n  }\n  input.span8, textarea.span8, .uneditable-input.span8 {\n    width: 756px;\n  }\n  input.span7, textarea.span7, .uneditable-input.span7 {\n    width: 656px;\n  }\n  input.span6, textarea.span6, .uneditable-input.span6 {\n    width: 556px;\n  }\n  input.span5, textarea.span5, .uneditable-input.span5 {\n    width: 456px;\n  }\n  input.span4, textarea.span4, .uneditable-input.span4 {\n    width: 356px;\n  }\n  input.span3, textarea.span3, .uneditable-input.span3 {\n    width: 256px;\n  }\n  input.span2, textarea.span2, .uneditable-input.span2 {\n    width: 156px;\n  }\n  input.span1, textarea.span1, .uneditable-input.span1 {\n    width: 56px;\n  }\n  .thumbnails {\n    margin-left: -30px;\n  }\n  .thumbnails > li {\n    margin-left: 30px;\n  }\n  .row-fluid .thumbnails {\n    margin-left: 0;\n  }\n}\n@media (max-width: 979px) {\n  body {\n    padding-top: 0;\n  }\n  .navbar-fixed-top,\n  .navbar-fixed-bottom {\n    position: static;\n  }\n  .navbar-fixed-top {\n    margin-bottom: 20px;\n  }\n  .navbar-fixed-bottom {\n    margin-top: 20px;\n  }\n  .navbar-fixed-top .navbar-inner,\n  .navbar-fixed-bottom .navbar-inner {\n    padding: 5px;\n  }\n  .navbar .container {\n    width: auto;\n    padding: 0;\n  }\n  .navbar .brand {\n    padding-left: 10px;\n    padding-right: 10px;\n    margin: 0 0 0 -5px;\n  }\n  .nav-collapse {\n    clear: both;\n  }\n  .nav-collapse .nav {\n    float: none;\n    margin: 0 0 10px;\n  }\n  .nav-collapse .nav > li {\n    float: none;\n  }\n  .nav-collapse .nav > li > a {\n    margin-bottom: 2px;\n  }\n  .nav-collapse .nav > .divider-vertical {\n    display: none;\n  }\n  .nav-collapse .nav .nav-header {\n    color: #777777;\n    text-shadow: none;\n  }\n  .nav-collapse .nav > li > a,\n  .nav-collapse .dropdown-menu a {\n    padding: 9px 15px;\n    font-weight: bold;\n    color: #777777;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n  }\n  .nav-collapse .btn {\n    padding: 4px 10px 4px;\n    font-weight: normal;\n    -webkit-border-radius: 4px;\n    -moz-border-radius: 4px;\n    border-radius: 4px;\n  }\n  .nav-collapse .dropdown-menu li + li a {\n    margin-bottom: 2px;\n  }\n  .nav-collapse .nav > li > a:hover,\n  .nav-collapse .dropdown-menu a:hover {\n    background-color: #f2f2f2;\n  }\n  .navbar-inverse .nav-collapse .nav > li > a:hover,\n  .navbar-inverse .nav-collapse .dropdown-menu a:hover {\n    background-color: #111111;\n  }\n  .nav-collapse.in .btn-group {\n    margin-top: 5px;\n    padding: 0;\n  }\n  .nav-collapse .dropdown-menu {\n    position: static;\n    top: auto;\n    left: auto;\n    float: none;\n    display: block;\n    max-width: none;\n    margin: 0 15px;\n    padding: 0;\n    background-color: transparent;\n    border: none;\n    -webkit-border-radius: 0;\n    -moz-border-radius: 0;\n    border-radius: 0;\n    -webkit-box-shadow: none;\n    -moz-box-shadow: none;\n    box-shadow: none;\n  }\n  .nav-collapse .dropdown-menu:before,\n  .nav-collapse .dropdown-menu:after {\n    display: none;\n  }\n  .nav-collapse .dropdown-menu .divider {\n    display: none;\n  }\n  .nav-collapse .nav > li > .dropdown-menu:before,\n  .nav-collapse .nav > li > .dropdown-menu:after {\n    display: none;\n  }\n  .nav-collapse .navbar-form,\n  .nav-collapse .navbar-search {\n    float: none;\n    padding: 10px 15px;\n    margin: 10px 0;\n    border-top: 1px solid #f2f2f2;\n    border-bottom: 1px solid #f2f2f2;\n    -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n    -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n  }\n  .navbar-inverse .nav-collapse .navbar-form,\n  .navbar-inverse .nav-collapse .navbar-search {\n    border-top-color: #111111;\n    border-bottom-color: #111111;\n  }\n  .navbar .nav-collapse .nav.pull-right {\n    float: none;\n    margin-left: 0;\n  }\n  .nav-collapse,\n  .nav-collapse.collapse {\n    overflow: hidden;\n    height: 0;\n  }\n  .navbar .btn-navbar {\n    display: block;\n  }\n  .navbar-static .navbar-inner {\n    padding-left: 10px;\n    padding-right: 10px;\n  }\n}\n@media (min-width: 980px) {\n  .nav-collapse.collapse {\n    height: auto !important;\n    overflow: visible !important;\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/webserver/styles/main.css",
    "content": "/* Will be compiled down to a single stylesheet with your sass files */"
  },
  {
    "path": "_archive/apps/samples/websocket-server/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/pkbpddppnkjmlbgliipgmhjeialadokj\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Http WebSocket Server\n\nAn example Http and WebSocket server implementation with a sample app which serves itself and allows connected clients to chat with each other. The API is very similar to NodeJS with the intention that this could be an easy drop-in replacement for a NodeJS served application.\n\n## APIs\n\n* [Sockets](https://developer.chrome.com/apps/sockets_tcpServer)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/websocket-server/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/websocket-server/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n    innerBounds: {\n      width: 800,\n      height: 600,\n      minWidth: 200,\n      minHeight: 200,\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/websocket-server/http.js",
    "content": "/**\n * Copyright (c) 2013 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n **/\n\nvar http = function() {\n\nif (!chrome.sockets || !chrome.sockets.tcpServer)\n    return {};\n\n// Wrap chrome.sockets.tcp socketId with a Promise API.\nvar PSocket = (function() {\n  // chrome.sockets.tcp uses a global listener for incoming data so\n  // use a map to dispatch to the proper instance.\n  var socketMap = {};\n  chrome.sockets.tcp.onReceive.addListener(function(info) {\n    var pSocket = socketMap[info.socketId];\n    if (pSocket) {\n      if (pSocket.handlers) {\n        // Fulfil the pending read.\n        pSocket.handlers.resolve(info.data);\n        delete pSocket.handlers;\n      }\n      else {\n        // No pending read so put data on the queue.\n        pSocket.readQueue.push(info);\n      }\n    }\n  });\n\n  // Read errors also use a global listener.\n  chrome.sockets.tcp.onReceiveError.addListener(function(info) {\n    var pSocket = socketMap[info.socketId];\n    if (pSocket) {\n      if (pSocket.handlers) {\n        // Reject the pending read.\n        pSocket.handlers.reject(new Error('chrome.sockets.tcp error ' + info.resultCode));\n        delete pSocket.handlers;\n      }\n      else {\n        // No pending read so put data on the queue.\n        pSocket.readQueue.push(info);\n      }\n    }\n  });\n\n  // PSocket constructor.\n  return function(socketId) {\n    this.socketId = socketId;\n    this.readQueue = [];\n\n    // Register this instance for incoming data processing.\n    socketMap[socketId] = this;\n    chrome.sockets.tcp.setPaused(socketId, false);\n  };\n})();\n\n// Returns a Promise<ArrayBuffer> with read data.\nPSocket.prototype.read = function() {\n  var that = this;\n  if (this.readQueue.length) {\n    // Return data from the queue.\n    var info = this.readQueue.shift();\n    if (!info.resultCode)\n      return Promise.resolve(info.data);\n    else\n      return Promise.reject(new Error('chrome.sockets.tcp error ' + info.resultCode));\n  }\n  else {\n    // The queue is empty so install handlers.\n    return new Promise(function(resolve, reject) {\n      that.handlers = { resolve: resolve, reject: reject };\n    });\n  }\n};\n\n// Returns a Promise<integer> with the number of bytes written.\nPSocket.prototype.write = function(data) {\n  var that = this;\n  return new Promise(function(resolve, reject) {\n    chrome.sockets.tcp.send(that.socketId, data, function(info) {\n      if (info && info.resultCode >= 0)\n        resolve(info.bytesSent);\n      else\n        reject(new Error('chrome sockets.tcp error ' + (info && info.resultCode)));\n    });\n  });\n};\n\n// Returns a Promise.\nPSocket.prototype.close = function() {\n  var that = this;\n  return new Promise(function(resolve, reject) {\n    chrome.sockets.tcp.disconnect(that.socketId, function() {\n      chrome.sockets.tcp.close(that.socketId, resolve);\n    });\n  });\n};\n  \n// Http response code strings.\nvar responseMap = {\n  200: 'OK',\n  301: 'Moved Permanently',\n  304: 'Not Modified',\n  400: 'Bad Request',\n  401: 'Unauthorized',\n  403: 'Forbidden',\n  404: 'Not Found',\n  413: 'Request Entity Too Large',\n  414: 'Request-URI Too Long',\n  500: 'Internal Server Error'};\n\n/**\n * Convert from an ArrayBuffer to a string.\n * @param {ArrayBuffer} buffer The array buffer to convert.\n * @return {string} The textual representation of the array.\n */\nvar arrayBufferToString = function(buffer) {\n  var array = new Uint8Array(buffer);\n  var str = '';\n  for (var i = 0; i < array.length; ++i) {\n    str += String.fromCharCode(array[i]);\n  }\n  return str;\n};\n\n/**\n * Convert from an UTF-8 array to UTF-8 string.\n * @param {array} UTF-8 array\n * @return {string} UTF-8 string\n */\nvar ary2utf8 = (function() {\n\n  var patterns = [\n    {pattern: '0xxxxxxx', bytes: 1},\n    {pattern: '110xxxxx', bytes: 2},\n    {pattern: '1110xxxx', bytes: 3},\n    {pattern: '11110xxx', bytes: 4},\n    {pattern: '111110xx', bytes: 5},\n    {pattern: '1111110x', bytes: 6}\n  ];\n  patterns.forEach(function(item) {\n    item.header = item.pattern.replace(/[^10]/g, '');\n    item.pattern01 = item.pattern.replace(/[^10]/g, '0');\n    item.pattern01 = parseInt(item.pattern01, 2);\n    item.mask_length = item.header.length;\n    item.data_length = 8 - item.header.length;\n    var mask = '';\n    for (var i = 0, len = item.mask_length; i < len; i++) {\n      mask += '1';\n    }\n    for (var i = 0, len = item.data_length; i < len; i++) {\n      mask += '0';\n    }\n    item.mask = mask;\n    item.mask = parseInt(item.mask, 2);\n  });\n\n  return function(ary) {\n    var codes = [];\n    var cur = 0;\n    while(cur < ary.length) {\n      var first = ary[cur];\n      var pattern = null;\n      for (var i = 0, len = patterns.length; i < len; i++) {\n        if ((first & patterns[i].mask) == patterns[i].pattern01) {\n          pattern = patterns[i];\n          break;\n        }\n      }\n      if (pattern == null) {\n        throw 'utf-8 decode error';\n      }\n      var rest = ary.slice(cur + 1, cur + pattern.bytes);\n      cur += pattern.bytes;\n      var code = '';\n      code += ('00000000' + (first & (255 ^ pattern.mask)).toString(2)).slice(-pattern.data_length);\n      for (var i = 0, len = rest.length; i < len; i++) {\n        code += ('00000000' + (rest[i] & parseInt('111111', 2)).toString(2)).slice(-6);\n      }\n      codes.push(parseInt(code, 2));\n    }\n    return String.fromCharCode.apply(null, codes);\n  };\n\n})();\n\n/**\n * Convert from an UTF-8 string to UTF-8 array.\n * @param {string} UTF-8 string\n * @return {array} UTF-8 array\n */\nvar utf82ary = (function() {\n\n  var patterns = [\n    {pattern: '0xxxxxxx', bytes: 1},\n    {pattern: '110xxxxx', bytes: 2},\n    {pattern: '1110xxxx', bytes: 3},\n    {pattern: '11110xxx', bytes: 4},\n    {pattern: '111110xx', bytes: 5},\n    {pattern: '1111110x', bytes: 6}\n  ];\n  patterns.forEach(function(item) {\n    item.header = item.pattern.replace(/[^10]/g, '');\n    item.mask_length = item.header.length;\n    item.data_length = 8 - item.header.length;\n    item.max_bit_length = (item.bytes - 1) * 6 + item.data_length;\n  });\n\n  var code2utf8array = function(code) {\n    var pattern = null;\n    var code01 = code.toString(2);\n    for (var i = 0, len = patterns.length; i < len; i++) {\n      if (code01.length <= patterns[i].max_bit_length) {\n        pattern = patterns[i];\n        break;\n      }\n    }\n    if (pattern == null) {\n      throw 'utf-8 encode error';\n    }\n    var ary = [];\n    for (var i = 0, len = pattern.bytes - 1; i < len; i++) {\n      ary.unshift(parseInt('10' + ('000000' + code01.slice(-6)).slice(-6), 2));\n      code01 = code01.slice(0, -6);\n    }\n    ary.unshift(parseInt(pattern.header + ('00000000' + code01).slice(-pattern.data_length), 2));\n    return ary;\n  };\n\n  return function(str) {\n    var codes = [];\n    for (var i = 0, len = str.length; i < len; i++) {\n      var code = str.charCodeAt(i);\n      Array.prototype.push.apply(codes, code2utf8array(code));\n    }\n    return codes;\n  };\n\n})();\n\n/**\n * Convert a string to an ArrayBuffer.\n * @param {string} string The string to convert.\n * @return {ArrayBuffer} An array buffer whose bytes correspond to the string.\n */\nvar stringToArrayBuffer = function(string) {\n  var buffer = new ArrayBuffer(string.length);\n  var bufferView = new Uint8Array(buffer);\n  for (var i = 0; i < string.length; i++) {\n    bufferView[i] = string.charCodeAt(i);\n  }\n  return buffer;\n};\n\n/**\n * An event source can dispatch events. These are dispatched to all of the\n * functions listening for that event type with arguments.\n * @constructor\n */\nfunction EventSource() {\n  this.listeners_ = {};\n};\n\nEventSource.prototype = {\n  /**\n   * Add |callback| as a listener for |type| events.\n   * @param {string} type The type of the event.\n   * @param {function(Object|undefined): boolean} callback The function to call\n   *     when this event type is dispatched. Arguments depend on the event\n   *     source and type. The function returns whether the event was \"handled\"\n   *     which will prevent delivery to the rest of the listeners.\n   */\n  addEventListener: function(type, callback) {\n    if (!this.listeners_[type])\n      this.listeners_[type] = [];\n    this.listeners_[type].push(callback);\n  },\n\n  /**\n   * Remove |callback| as a listener for |type| events.\n   * @param {string} type The type of the event.\n   * @param {function(Object|undefined): boolean} callback The callback\n   *     function to remove from the event listeners for events having type\n   *     |type|.\n   */\n  removeEventListener: function(type, callback) {\n    if (!this.listeners_[type])\n      return;\n    for (var i = this.listeners_[type].length - 1; i >= 0; i--) {\n      if (this.listeners_[type][i] == callback) {\n        this.listeners_[type].splice(i, 1);\n      }\n    }\n  },\n\n  /**\n   * Dispatch an event to all listeners for events of type |type|.\n   * @param {type} type The type of the event being dispatched.\n   * @param {...Object} var_args The arguments to pass when calling the\n   *     callback function.\n   * @return {boolean} Returns true if the event was handled.\n   */\n  dispatchEvent: function(type, var_args) {\n    if (!this.listeners_[type])\n      return false;\n    for (var i = 0; i < this.listeners_[type].length; i++) {\n      if (this.listeners_[type][i].apply(\n              /* this */ null,\n              /* var_args */ Array.prototype.slice.call(arguments, 1))) {\n        return true;\n      }\n    }\n  }\n};\n\n/**\n * HttpServer provides a lightweight Http web server. Currently it only\n * supports GET requests and upgrading to other protocols (i.e. WebSockets).\n * @constructor\n */\nfunction HttpServer() {\n  EventSource.apply(this);\n  this.readyState_ = 0;\n}\n\nHttpServer.prototype = {\n  __proto__: EventSource.prototype,\n\n  /**\n   * Listen for connections on |port| using the interface |host|.\n   * @param {number} port The port to listen for incoming connections on.\n   * @param {string=} opt_host The host interface to listen for connections on.\n   *     This will default to 0.0.0.0 if not specified which will listen on\n   *     all interfaces.\n   */\n  listen: function(port, opt_host) {\n    var t = this;\n    chrome.sockets.tcpServer.create(function(socketInfo) {\n      chrome.sockets.tcpServer.onAccept.addListener(function(acceptInfo) {\n        if (acceptInfo.socketId === socketInfo.socketId)\n          t.readRequestFromSocket_(new PSocket(acceptInfo.clientSocketId));\n      });\n      \n      chrome.sockets.tcpServer.listen(\n        socketInfo.socketId,\n        opt_host || '0.0.0.0',\n        port,\n        50,\n        function(result) {\n          if (!result) {\n            t.readyState_ = 1;\n          }\n          else {\n            console.log(\n              'listen error ' +\n              chrome.runtime.lastError.message +\n                ' (normal if another instance is already serving requests)');\n          }\n        });\n    });\n  },\n\n  readRequestFromSocket_: function(pSocket) {\n    var t = this;\n    var requestData = '';\n    var endIndex = 0;\n    var onDataRead = function(data) {\n      requestData += arrayBufferToString(data).replace(/\\r\\n/g, '\\n');\n      // Check for end of request.\n      endIndex = requestData.indexOf('\\n\\n', endIndex);\n      if (endIndex == -1) {\n        endIndex = requestData.length - 1;\n        return pSocket.read().then(onDataRead);\n      }\n\n      var headers = requestData.substring(0, endIndex).split('\\n');\n      var headerMap = {};\n      // headers[0] should be the Request-Line\n      var requestLine = headers[0].split(' ');\n      headerMap['method'] = requestLine[0];\n      headerMap['url'] = requestLine[1];\n      headerMap['Http-Version'] = requestLine[2];\n      for (var i = 1; i < headers.length; i++) {\n        requestLine = headers[i].split(':', 2);\n        if (requestLine.length == 2)\n          headerMap[requestLine[0]] = requestLine[1].trim();\n      }\n      var request = new HttpRequest(headerMap, pSocket);\n      t.onRequest_(request);\n    };\n\n    pSocket.read().then(onDataRead).catch(function(e) {\n      pSocket.close();\n    });\n  },\n\n  onRequest_: function(request) {\n    var type = request.headers['Upgrade'] ? 'upgrade' : 'request';\n    var keepAlive = request.headers['Connection'] == 'keep-alive';\n    if (!this.dispatchEvent(type, request))\n      request.close();\n    else if (keepAlive)\n      this.readRequestFromSocket_(request.pSocket_);\n  },\n};\n\n// MIME types for common extensions.\nvar extensionTypes = {\n  'css': 'text/css',\n  'html': 'text/html',\n  'htm': 'text/html',\n  'jpg': 'image/jpeg',\n  'jpeg': 'image/jpeg',\n  'js': 'text/javascript',\n  'png': 'image/png',\n  'svg': 'image/svg+xml',\n  'txt': 'text/plain'};\n\n/**\n * Constructs an HttpRequest object which tracks all of the request headers and\n * socket for an active Http request.\n * @param {Object} headers The HTTP request headers.\n * @param {Object} pSocket The socket to use for the response.\n * @constructor\n */\nfunction HttpRequest(headers, pSocket) {\n  this.version = 'HTTP/1.1';\n  this.headers = headers;\n  this.responseHeaders_ = {};\n  this.headersSent = false;\n  this.pSocket_ = pSocket;\n  this.writes_ = 0;\n  this.bytesRemaining = 0;\n  this.finished_ = false;\n  this.readyState = 1;\n}\n\nHttpRequest.prototype = {\n  __proto__: EventSource.prototype,\n\n  /**\n   * Closes the Http request.\n   */\n  close: function() {\n    // The socket for keep alive connections will be re-used by the server.\n    // Just stop referencing or using the socket in this HttpRequest.\n    if (this.headers['Connection'] != 'keep-alive')\n      pSocket.close();\n\n    this.pSocket_ = null;\n    this.readyState = 3;\n  },\n\n  /**\n   * Write the provided headers as a response to the request.\n   * @param {int} responseCode The HTTP status code to respond with.\n   * @param {Object} responseHeaders The response headers describing the\n   *     response.\n   */\n  writeHead: function(responseCode, responseHeaders) {\n    var headerString = this.version + ' ' + responseCode + ' ' +\n        (responseMap[responseCode] || 'Unknown');\n    this.responseHeaders_ = responseHeaders;\n    if (this.headers['Connection'] == 'keep-alive')\n      responseHeaders['Connection'] = 'keep-alive';\n    if (!responseHeaders['Content-Length'] && responseHeaders['Connection'] == 'keep-alive')\n      responseHeaders['Transfer-Encoding'] = 'chunked';\n    for (var i in responseHeaders) {\n      headerString += '\\r\\n' + i + ': ' + responseHeaders[i];\n    }\n    headerString += '\\r\\n\\r\\n';\n    this.write_(stringToArrayBuffer(headerString));\n  },\n\n  /**\n   * Writes data to the response stream.\n   * @param {string|ArrayBuffer} data The data to write to the stream.\n   */\n  write: function(data) {\n    if (this.responseHeaders_['Transfer-Encoding'] == 'chunked') {\n      var newline = '\\r\\n';\n      var byteLength = (data instanceof ArrayBuffer) ? data.byteLength : data.length;\n      var chunkLength = byteLength.toString(16).toUpperCase() + newline;\n      var buffer = new ArrayBuffer(chunkLength.length + byteLength + newline.length);\n      var bufferView = new Uint8Array(buffer);\n      for (var i = 0; i < chunkLength.length; i++)\n        bufferView[i] = chunkLength.charCodeAt(i);\n      if (data instanceof ArrayBuffer) {\n        bufferView.set(new Uint8Array(data), chunkLength.length);\n      } else {\n        for (var i = 0; i < data.length; i++)\n          bufferView[chunkLength.length + i] = data.charCodeAt(i);\n      }\n      for (var i = 0; i < newline.length; i++)\n        bufferView[chunkLength.length + byteLength + i] = newline.charCodeAt(i);\n      data = buffer;\n    } else if (!(data instanceof ArrayBuffer)) {\n      data = stringToArrayBuffer(data);\n    }\n    this.write_(data);\n  },\n\n  /**\n   * Finishes the HTTP response writing |data| before closing.\n   * @param {string|ArrayBuffer=} opt_data Optional data to write to the stream\n   *     before closing it.\n   */\n  end: function(opt_data) {\n    if (opt_data)\n      this.write(opt_data);\n    if (this.responseHeaders_['Transfer-Encoding'] == 'chunked')\n      this.write('');\n    this.finished_ = true;\n    this.checkFinished_();\n  },\n\n  /**\n   * Automatically serve the given |url| request.\n   * @param {string} url The URL to fetch the file to be served from. This is\n   *     retrieved via an XmlHttpRequest and served as the response to the\n   *     request.\n   */\n  serveUrl: function(url) {\n    var t = this;\n    var xhr = new XMLHttpRequest();\n    xhr.onloadend = function() {\n      var type = 'text/plain';\n      if (this.getResponseHeader('Content-Type')) {\n        type = this.getResponseHeader('Content-Type');\n      } else if (url.indexOf('.') != -1) {\n        var extension = url.substr(url.indexOf('.') + 1);\n        type = extensionTypes[extension] || type;\n      }\n      console.log('Served ' + url);\n      var contentLength = this.getResponseHeader('Content-Length');\n      if (xhr.status == 200)\n        contentLength = (this.response && this.response.byteLength) || 0;\n      t.writeHead(this.status, {\n        'Content-Type': type,\n        'Content-Length': contentLength});\n      t.end(this.response);\n    };\n    xhr.open('GET', url, true);\n    xhr.responseType = 'arraybuffer';\n    xhr.send();\n  },\n\n  write_: function(array) {\n    var t = this;\n    this.bytesRemaining += array.byteLength;\n    this.pSocket_.write(array).then(function(bytesWritten) {\n      t.bytesRemaining -= bytesWritten;\n      t.checkFinished_();\n    }).catch(function(e) {\n      console.error(e.message);\n      return;\n    });\n  },\n\n  checkFinished_: function() {\n    if (!this.finished_ || this.bytesRemaining > 0)\n      return;\n    this.close();\n  }\n};\n\n/**\n * Constructs a server which is capable of accepting WebSocket connections.\n * @param {HttpServer} httpServer The Http Server to listen and handle\n *     WebSocket upgrade requests on.\n * @constructor\n */\nfunction WebSocketServer(httpServer) {\n  EventSource.apply(this);\n  httpServer.addEventListener('upgrade', this.upgradeToWebSocket_.bind(this));\n}\n\nWebSocketServer.prototype = {\n  __proto__: EventSource.prototype,\n\n  upgradeToWebSocket_: function(request) {\n    if (request.headers['Upgrade'] != 'websocket' ||\n        !request.headers['Sec-WebSocket-Key']) {\n      return false;\n    }\n\n    if (this.dispatchEvent('request', new WebSocketRequest(request))) {\n      if (request.pSocket_)\n        request.reject();\n      return true;\n    }\n\n    return false;\n  }\n};\n\n/**\n * Constructs a WebSocket request object from an Http request. This invalidates\n * the Http request's socket and offers accept and reject methods for accepting\n * and rejecting the WebSocket upgrade request.\n * @param {HttpRequest} httpRequest The HTTP request to upgrade.\n */\nfunction WebSocketRequest(httpRequest) {\n  // We'll assume control of the socket for this request.\n  HttpRequest.apply(this, [httpRequest.headers, httpRequest.pSocket_]);\n  httpRequest.pSocket_ = null;\n}\n\nWebSocketRequest.prototype = {\n  __proto__: HttpRequest.prototype,\n\n  /**\n   * Accepts the WebSocket request.\n   * @return {WebSocketServerSocket} The websocket for the accepted request.\n   */\n  accept: function() {\n    // Construct WebSocket response key.\n    var clientKey = this.headers['Sec-WebSocket-Key'];\n    var toArray = function(str) {\n      var a = [];\n      for (var i = 0; i < str.length; i++) {\n        a.push(str.charCodeAt(i));\n      }\n      return a;\n    }\n    var toString = function(a) {\n      var str = '';\n      for (var i = 0; i < a.length; i++) {\n        str += String.fromCharCode(a[i]);\n      }\n      return str;\n    }\n\n    // Magic string used for websocket connection key hashing:\n    // http://en.wikipedia.org/wiki/WebSocket\n    var magicStr = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';\n\n    // clientKey is base64 encoded key.\n    clientKey += magicStr;\n    var sha1 = new Sha1();\n    sha1.reset();\n    sha1.update(toArray(clientKey));\n    var responseKey = btoa(toString(sha1.digest()));\n    var responseHeader = {\n      'Upgrade': 'websocket',\n      'Connection': 'Upgrade',\n      'Sec-WebSocket-Accept': responseKey};\n    if (this.headers['Sec-WebSocket-Protocol'])\n      responseHeader['Sec-WebSocket-Protocol'] = this.headers['Sec-WebSocket-Protocol'];\n    this.writeHead(101, responseHeader);\n    var socket = new WebSocketServerSocket(this.pSocket_);\n    // Detach the socket so that we don't use it anymore.\n    this.pSocket_ = 0;\n    return socket;\n  },\n\n  /**\n   * Rejects the WebSocket request, closing the connection.\n   */\n  reject: function() {\n    this.close();\n  }\n}\n\n/**\n * Constructs a WebSocketServerSocket using the given socketId. This should be\n * a socket which has already been upgraded from an Http request.\n * @param {number} socketId The socket id with an active websocket connection.\n */\nfunction WebSocketServerSocket(pSocket) {\n  this.pSocket_ = pSocket;\n  this.readyState = 1;\n  EventSource.apply(this);\n  this.readFromSocket_();\n}\n\nWebSocketServerSocket.prototype = {\n  __proto__: EventSource.prototype,\n\n  /**\n   * Send |data| on the WebSocket.\n   * @param {string|Array.<number>|ArrayBuffer} data The data to send over the WebSocket.\n   */\n  send: function(data) {\n    // WebSocket must specify opcode when send frame.\n    // The opcode for data frame is 1(text) or 2(binary).\n    if (typeof data == 'string' || data instanceof String) {\n      this.sendFrame_(1, data);\n    } else {\n      this.sendFrame_(2, data);\n    }\n  },\n\n  /**\n   * Begin closing the WebSocket. Note that the WebSocket protocol uses a\n   * handshake to close the connection, so this call will begin the closing\n   * process.\n   */\n  close: function() {\n    if (this.readyState === 1) {\n      this.sendFrame_(8);\n      this.readyState = 2;\n    }\n  },\n\n  readFromSocket_: function() {\n    var t = this;\n    var data = [];\n    var message = '';\n    var fragmentedOp = 0;\n    var fragmentedMessages = [];\n\n    var onDataRead = function(dataBuffer) {\n      var a = new Uint8Array(dataBuffer);\n      for (var i = 0; i < a.length; i++)\n        data.push(a[i]);\n\n      while (data.length) {\n        var length_code = -1;\n        var data_start = 6;\n        var mask;\n        var fin = (data[0] & 128) >> 7;\n        var op = data[0] & 15;\n\n        if (data.length > 1)\n          length_code = data[1] & 127;\n        if (length_code > 125) {\n          if ((length_code == 126 && data.length > 7) ||\n              (length_code == 127 && data.length > 14)) {\n            if (length_code == 126) {\n              length_code = data[2] * 256 + data[3];\n              mask = data.slice(4, 8);\n              data_start = 8;\n            } else if (length_code == 127) {\n              length_code = 0;\n              for (var i = 0; i < 8; i++) {\n                length_code = length_code * 256 + data[2 + i];\n              }\n              mask = data.slice(10, 14);\n              data_start = 14;\n            }\n          } else {\n            length_code = -1; // Insufficient data to compute length\n          }\n        } else {\n          if (data.length > 5)\n            mask = data.slice(2, 6);\n        }\n\n        if (length_code > -1 && data.length >= data_start + length_code) {\n          var decoded = data.slice(data_start, data_start + length_code).map(function(byte, index) {\n            return byte ^ mask[index % 4];\n          });\n          if (op == 1) {\n            decoded = ary2utf8(decoded);\n          }\n          data = data.slice(data_start + length_code);\n          if (fin && op > 0) {\n            // Unfragmented message.\n            if (!t.onFrame_(op, decoded))\n              return;\n          } else {\n            // Fragmented message.\n            fragmentedOp = fragmentedOp || op;\n            fragmentedMessages.push(decoded);\n            if (fin) {\n              var joinMessage = null;\n              if (op == 1) {\n                joinMessage = fragmentedMessagess.join('');\n              } else {\n                joinMessage = fragmentedMessages.reduce(function(pre, cur) {\n                  return Array.prototype.push.apply(pre, cur);\n                }, []);\n              }\n              if (!t.onFrame_(fragmentedOp, joinMessage))\n                return;\n              fragmentedOp = 0;\n              fragmentedMessages = [];\n            }\n          }\n        } else {\n          break; // Insufficient data, wait for more.\n        }\n      }\n\n      return t.pSocket_.read().then(onDataRead);\n    };\n\n    this.pSocket_.read().then(function(data) {\n      return onDataRead(data);\n    }).catch(function(e) {\n      t.close_();\n    });\n  },\n\n  onFrame_: function(op, data) {\n    if (op == 1 || op == 2) {\n      if (typeof data == 'string' || data instanceof String) {\n        // Don't do anything.\n      } else if (Array.isArray(data)) {\n        data = new Uint8Array(data).buffer;\n      } else if (data instanceof ArrayBuffer) {\n        // Don't do anything.\n      } else {\n        data = data.buffer;\n      }\n      this.dispatchEvent('message', {'data': data});\n    } else if (op == 8) {\n      // A close message must be confirmed before the websocket is closed.\n      if (this.readyState === 1) {\n        this.sendFrame_(8);\n        this.readyState = 2;\n      } else {\n        this.close_();\n        return false;\n      }\n    }\n    return true;\n  },\n\n  sendFrame_: function(op, data) {\n    var t = this;\n    var WebsocketFrameData = function(op, data) {\n      var ary = data;\n      if (typeof data == 'string' || data instanceof String) {\n        ary = utf82ary(data);\n      }\n      if (Array.isArray(ary)) {\n        ary = new Uint8Array(ary);\n      }\n      if (ary instanceof ArrayBuffer) {\n        ary = new Uint8Array(ary);\n      }\n      ary = new Uint8Array(ary.buffer);\n      var length = ary.length;\n      if (ary.length > 65535)\n        length += 10;\n      else if (ary.length > 125)\n        length += 4;\n      else\n        length += 2;\n      var lengthBytes = 0;\n      var buffer = new ArrayBuffer(length);\n      var bv = new Uint8Array(buffer);\n      bv[0] = 128 | (op & 15); // Fin and type text.\n      bv[1] = ary.length > 65535 ? 127 :\n              (ary.length > 125 ? 126 : ary.length);\n      if (ary.length > 65535)\n        lengthBytes = 8;\n      else if (ary.length > 125)\n        lengthBytes = 2;\n      var len = ary.length;\n      for (var i = lengthBytes - 1; i >= 0; i--) {\n        bv[2 + i] = len & 255;\n        len = len >> 8;\n      }\n      var dataStart = lengthBytes + 2;\n      for (var i = 0; i < ary.length; i++) {\n        bv[dataStart + i] = ary[i];\n      }\n      return buffer;\n    }\n    var array = WebsocketFrameData(op, data || '');\n    this.pSocket_.write(array).then(function(bytesWritten) {\n      if (bytesWritten !== array.byteLength)\n        throw new Error('insufficient write');\n    }).catch(function(e) {\n      t.close_();\n    });\n  },\n\n  close_: function() {\n    if (this.readyState !== 3) {\n      this.pSocket_.close();\n      this.readyState = 3;\n      this.dispatchEvent('close');\n    }\n  }\n};\n\nreturn {\n  'Server': HttpServer,\n  'WebSocketServer': WebSocketServer,\n};\n}();\n"
  },
  {
    "path": "_archive/apps/samples/websocket-server/index.css",
    "content": "html,\nbody {\n  height: 100%;\n  margin: 0;\n  padding: 0;\n  width: 100%;\n}\n\nbody {\n  -webkit-box-orient: vertical;\n  display: -webkit-box;\n}\n\n#log {\n  -webkit-box-flex: 1;\n}\n\n#log,\n#input {\n  display: block;\n}\n"
  },
  {
    "path": "_archive/apps/samples/websocket-server/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <link rel=\"stylesheet\" href=\"index.css\">\n    <script src=\"sha1.js\"></script>\n    <script src=\"http.js\"></script>\n    <script src=\"index.js\"></script>\n  </head>\n  <body>\n    <textarea id=\"log\"></textarea>\n    <input type=\"text\" id=\"input\" placeholder=\"Type a message to other connected clients here\">\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/websocket-server/index.js",
    "content": "function $(id) {\n  return document.getElementById(id);\n}\n\nfunction log(text) {\n  $('log').value += text + '\\n';\n}\n\nvar port = 9999;\nvar isServer = false;\nif (http.Server && http.WebSocketServer) {\n  // Listen for HTTP connections.\n  var server = new http.Server();\n  var wsServer = new http.WebSocketServer(server);\n  server.listen(port);\n  isServer = true;\n\n  server.addEventListener('request', function(req) {\n    var url = req.headers.url;\n    if (url == '/')\n      url = '/index.html';\n    // Serve the pages of this chrome application.\n    req.serveUrl(url);\n    return true;\n  });\n\n  // A list of connected websockets.\n  var connectedSockets = [];\n\n  wsServer.addEventListener('request', function(req) {\n    log('Client connected');\n    var socket = req.accept();\n    connectedSockets.push(socket);\n\n    // When a message is received on one socket, rebroadcast it on all\n    // connected sockets.\n    socket.addEventListener('message', function(e) {\n      for (var i = 0; i < connectedSockets.length; i++)\n        connectedSockets[i].send(e.data);\n    });\n\n    // When a socket is closed, remove it from the list of connected sockets.\n    socket.addEventListener('close', function() {\n      log('Client disconnected');\n      for (var i = 0; i < connectedSockets.length; i++) {\n        if (connectedSockets[i] == socket) {\n          connectedSockets.splice(i, 1);\n          break;\n        }\n      }\n    });\n    return true;\n  });\n}\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  log('This is a test of an HTTP and WebSocket server. This application is ' +\n      'serving its own source code on port ' + port + '. Each client ' +\n      'connects to the server on a WebSocket and all messages received on ' +\n      'one WebSocket are echoed to all connected clients - i.e. a chat ' +\n      'server. Enjoy!');\n// FIXME: Wait for 1s so that HTTP Server socket is listening...\nsetTimeout(function() {\n  var address = isServer ? 'ws://localhost:' + port + '/' :\n      window.location.href.replace('http', 'ws');\n  var ws = new WebSocket(address);\n  ws.addEventListener('open', function() {\n    log('Connected');\n  });\n  ws.addEventListener('close', function() {\n    log('Connection lost');\n    $('input').disabled = true;\n  });\n  ws.addEventListener('message', function(e) {\n    log(e.data);\n  });\n  $('input').addEventListener('keydown', function(e) {\n    if (ws && ws.readyState == 1 && e.keyCode == 13) {\n      ws.send(this.value);\n      this.value = '';\n    }\n  });\n}, 1e3);\n});\n"
  },
  {
    "path": "_archive/apps/samples/websocket-server/manifest.json",
    "content": "{\n  \"name\": \"WebSocket Server Test\",\n  \"description\": \"Runs an Http and WebSocket server with a quick and dirty test chat application.\",\n  \"version\": \"0.3.2\",\n  \"manifest_version\": 2,\n\n  \"sockets\": {\n    \"tcp\": {\n      \"connect\": \"*\"\n    },\n\n    \"tcpServer\": {\n      \"listen\": \"*\"\n    }\n  },\n  \n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/websocket-server/sample_support_metadata.json",
    "content": "{\n  \"sample\": \"websocket-server\",\n  \"files_with_snippets\": [ ],\n  \"ios\": {\"works\": true}\n}\n"
  },
  {
    "path": "_archive/apps/samples/websocket-server/sha1.js",
    "content": "// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Copyright 2005 Google Inc. All Rights Reserved.\n\n/**\n * @fileoverview SHA-1 cryptographic hash.\n * Variable names follow the notation in FIPS PUB 180-3:\n * http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.\n *\n * Usage:\n *   var sha1 = new goog.crypt.sha1();\n *   sha1.update(bytes);\n *   var hash = sha1.digest();\n *\n */\n\n/**\n * SHA-1 cryptographic hash constructor.\n *\n * The properties declared here are discussed in the above algorithm document.\n * @constructor\n */\nvar Sha1 = function() {\n  /**\n   * Holds the previous values of accumulated variables a-e in the compress_\n   * function.\n   * @type {Array.<number>}\n   * @private\n   */\n  this.chain_ = [];\n\n  /**\n   * A buffer holding the partially computed hash result.\n   * @type {Array.<number>}\n   * @private\n   */\n  this.buf_ = [];\n\n  /**\n   * An array of 80 bytes, each a part of the message to be hashed.  Referred to\n   * as the message schedule in the docs.\n   * @type {Array.<number>}\n   * @private\n   */\n  this.W_ = [];\n\n  /**\n   * Contains data needed to pad messages less than 64 bytes.\n   * @type {Array.<number>}\n   * @private\n   */\n  this.pad_ = [];\n\n  this.pad_[0] = 128;\n  for (var i = 1; i < 64; ++i) {\n    this.pad_[i] = 0;\n  }\n\n  this.reset();\n};\n\n\n/**\n * Resets the internal accumulator.\n */\nSha1.prototype.reset = function() {\n  this.chain_[0] = 0x67452301;\n  this.chain_[1] = 0xefcdab89;\n  this.chain_[2] = 0x98badcfe;\n  this.chain_[3] = 0x10325476;\n  this.chain_[4] = 0xc3d2e1f0;\n\n  this.inbuf_ = 0;\n  this.total_ = 0;\n};\n\n\n/**\n * Internal helper performing 32 bit left rotate.\n * @return {number} w rotated left by r bits.\n * @private\n */\nSha1.prototype.rotl_ = function(w, r) {\n  return ((w << r) | (w >>> (32 - r))) & 0xffffffff;\n};\n\n\n/**\n * Internal compress helper function.\n * @param {Array} buf containing block to compress.\n * @private\n */\nSha1.prototype.compress_ = function(buf) {\n  var W = this.W_;\n\n  // get 16 big endian words\n  for (var i = 0; i < 64; i += 4) {\n    var w = (buf[i] << 24) |\n            (buf[i + 1] << 16) |\n            (buf[i + 2] << 8) |\n            (buf[i + 3]);\n    W[i / 4] = w;\n  }\n\n  // expand to 80 words\n  for (var i = 16; i < 80; i++) {\n    W[i] = this.rotl_(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);\n  }\n\n  var a = this.chain_[0];\n  var b = this.chain_[1];\n  var c = this.chain_[2];\n  var d = this.chain_[3];\n  var e = this.chain_[4];\n  var f, k;\n\n  for (var i = 0; i < 80; i++) {\n    if (i < 40) {\n      if (i < 20) {\n        f = d ^ (b & (c ^ d));\n        k = 0x5a827999;\n      } else {\n        f = b ^ c ^ d;\n        k = 0x6ed9eba1;\n      }\n    } else {\n      if (i < 60) {\n        f = (b & c) | (d & (b | c));\n        k = 0x8f1bbcdc;\n      } else {\n        f = b ^ c ^ d;\n        k = 0xca62c1d6;\n      }\n    }\n\n    var t = (this.rotl_(a, 5) + f + e + k + W[i]) & 0xffffffff;\n    e = d;\n    d = c;\n    c = this.rotl_(b, 30);\n    b = a;\n    a = t;\n  }\n\n  this.chain_[0] = (this.chain_[0] + a) & 0xffffffff;\n  this.chain_[1] = (this.chain_[1] + b) & 0xffffffff;\n  this.chain_[2] = (this.chain_[2] + c) & 0xffffffff;\n  this.chain_[3] = (this.chain_[3] + d) & 0xffffffff;\n  this.chain_[4] = (this.chain_[4] + e) & 0xffffffff;\n};\n\n\n/**\n * Adds a byte array to internal accumulator.\n * @param {Array.<number>} bytes to add to digest.\n * @param {number} opt_length is # of bytes to compress.\n */\nSha1.prototype.update = function(bytes, opt_length) {\n  if (!opt_length) {\n    opt_length = bytes.length;\n  }\n\n  var n = 0;\n\n  // Optimize for 64 byte chunks at 64 byte boundaries.\n  if (this.inbuf_ == 0) {\n    while (n + 64 < opt_length) {\n      this.compress_(bytes.slice(n, n + 64));\n      n += 64;\n      this.total_ += 64;\n    }\n  }\n\n  while (n < opt_length) {\n    this.buf_[this.inbuf_++] = bytes[n++];\n    this.total_++;\n\n    if (this.inbuf_ == 64) {\n      this.inbuf_ = 0;\n      this.compress_(this.buf_);\n\n      // Pick up 64 byte chunks.\n      while (n + 64 < opt_length) {\n        this.compress_(bytes.slice(n, n + 64));\n        n += 64;\n        this.total_ += 64;\n      }\n    }\n  }\n};\n\n\n/**\n * @return {Array} byte[20] containing finalized hash.\n */\nSha1.prototype.digest = function() {\n  var digest = [];\n  var totalBits = this.total_ * 8;\n\n  // Add pad 0x80 0x00*.\n  if (this.inbuf_ < 56) {\n    this.update(this.pad_, 56 - this.inbuf_);\n  } else {\n    this.update(this.pad_, 64 - (this.inbuf_ - 56));\n  }\n\n  // Add # bits.\n  for (var i = 63; i >= 56; i--) {\n    this.buf_[i] = totalBits & 255;\n    totalBits >>>= 8;\n    }\n\n  this.compress_(this.buf_);\n\n  var n = 0;\n  for (var i = 0; i < 5; i++) {\n    for (var j = 24; j >= 0; j -= 8) {\n      digest[n++] = (this.chain_[i] >> j) & 255;\n    }\n  }\n\n  return digest;\n};\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/browser/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/edggnmnajhcbhlnpjnogkjpghaikidaa\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Browser\n\nSample that shows how to use the [webview tag](http://developer.chrome.com/apps/app_external#webview)\nin an app to create a mini browser.\n\nThe app's main window contains a `<webview>` that is sized to fit most of it\n(via the `width` and `height` attributes). The location bar is used to\nupdate its `src` attribute.\n\n`<webview>` is the preferred way for you to load web content into your app. It\nruns in a separate process and has its own storage, ensuring the security and\nreliability of your application.\n\n## Resources\n\n* [Webview](http://developer.chrome.com/apps/app_external#webview)\n* [Permissions](http://developer.chrome.com/apps/manifest#permissions)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/webview-samples/browser/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/browser/browser.css",
    "content": "body {\n  margin: 0;\n  padding: 0;\n  font-family: Lucida Grande, Arial, sans-serif;\n}\n\nbutton,\ninput {\n  outline: none;\n}\n\n#controls {\n  padding: 3px;\n  border-bottom: solid 1px #ccc;\n  background-color: #eee;\n}\n\n#controls button,\n#controls input {\n  font-size: 14px;\n  line-height: 24px;\n  border-radius: 2px;\n  padding: 0 6px;\n}\n\nbutton,\ninput[type=\"submit\"],\nbutton[disabled]:hover {\n  border: solid 1px transparent;\n  background: transparent;\n}\n\nbutton:hover,\ninput[type=\"submit\"]:hover,\nbutton:focus,\ninput[type=\"submit\"]:focus {\n  border-color: #ccc;\n  background: -webkit-linear-gradient(bottom, #cccccc 0%, #f2f2f2 99%);\n}\n\nbutton:focus,\ninput[type=\"submit\"]:focus {\n  border-style: outset;\n}\n\nbutton:active,\ninput[type=\"submit\"]:active {\n  border-color: #bbb;\n  border-style: solid;\n  background: -webkit-linear-gradient(bottom, #e2e2e2 0%, #bbbbbb 99%);\n}\n\n/* These glyphs are on the small side, make them look more natural when\ncompared to the back/forward buttons */\n#controls #home,\n#controls #terminate {\n  font-size: 24px;\n}\n\n#controls #reload {\n  font-size: 20px;\n}\n\n#controls #zoom,\n#controls #find {\n  font-size: 18px;\n}\n\n#location {\n  border: solid 1px #ccc;\n  padding: 2px;\n  width: 100%;\n  -webkit-box-sizing: border-box;\n}\n\n#controls {\n  display: -webkit-flex;\n  -webit-flex-direction: column;\n}\n\n#controls #location-form {\n  -webkit-flex: 1;\n  display: -webkit-flex;\n  -webit-flex-direction: column;\n}\n\n#controls #center-column {\n  -webkit-flex: 1;\n}\n\n#zoom-box,\n#find-box {\n  background-color: #eee;\n  border: solid 1px #ccc;\n  border-top: solid 1px #eee;\n  border-bottom-left-radius: 2px;\n  border-bottom-right-radius: 2px;\n  padding: 2px;\n\n  position: fixed;\n  margin-top: -1px;\n  height: 25px;\n\n  display: none;\n}\n\n#zoom-box #zoom-form,\n#find-box #find-form {\n  -webkit-flex: 1;\n  display: -webkit-flex;\n  -webit-flex-direction: row;\n  min-width: 0;\n}\n\n#zoom-box input,\n#zoom-box button,\n#find-box button {\n  border-radius: 2px;\n}\n\n#zoom-box #zoom-text,\n#find-box #find-text {\n  border: solid 1px #ccc;\n  margin-right: 0px;\n  padding: 2px;\n  -webkit-box-sizing: border-box;\n  -webkit-flex: 1;\n  min-width: 0;\n}\n\n#zoom-box {\n  left: 5px;\n  width: 125px;\n  z-index: 1;\n}\n\n#zoom-box input[type=\"submit\"] {\n  font-size: 14px;\n  margin: 2px 0px;\n  padding: 0 2px 3px 2px;\n  width: 22px;\n}\n\n#zoom-box button {\n  font-size: 12px;\n  margin: 2px 0px;\n  padding: 0px 1px 0px 0px;\n  width: 20px;\n}\n\n#find-box {\n  right: 5px;\n  width: 280px;\n  z-index: 2;\n}\n\n#find-box #find-text {\n  border-right-style: none;\n  border-top-left-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n\n#find-box #find-results {\n  color: #888;\n  background-color: #fff;\n  border: solid 1px #ccc;\n  border-left-style: none;\n  border-top-right-radius: 2px;\n  border-bottom-right-radius: 2px;\n  padding: 3px 4px 2px 0;\n  text-align: center;\n}\n\n#find-results {\n  margin: 0px 0px;\n}\n\n#find-box #match-case {\n  margin: 2px 0px;\n  font-size: 10px;\n  width: 28px;\n}\n\n#find-box #find-backward,\n#find-box #find-forward {\n  font-size: 14px;\n  width: 24px;\n}\n\n.overlay {\n  -webkit-box-align: center;\n  -webkit-box-orient: vertical;\n  -webkit-box-pack: center;\n  -webkit-perspective: 1px;\n  -webkit-transition: 200ms opacity;\n  background-color: rgba(255, 255, 255, 0.75);\n  bottom: 0;\n  display: none;\n  left: 0;\n  overflow: auto;\n  padding: 20px;\n  position: fixed;\n  right: 0;\n  top: 0;\n}\n\n#clear-data-overlay {\n  z-index: 3;\n}\n\n#clear-data-confirm {\n  -webkit-box-orient: vertical;\n  background-clip: border-box;\n  background-color: rgb(255, 255, 255);\n  background-image: none;\n  background-origin: padding-box;\n  background-size: auto;\n  border-bottom-left-radius: 3px;\n  border-bottom-right-radius: 3px;\n  border-top-left-radius: 3px;\n  border-top-right-radius: 3px;\n  box-shadow: rgba(0, 0, 0, 0.2) 0px 4px 23px 5px, rgba(0, 0, 0, 0.14902) 0px 2px 6px 0px;\n  color: rgb(51, 51, 51);\n  display: none;\n  min-width: 400px;\n  padding-bottom: 0px;\n  padding-left: 0px;\n  padding-right: 0px;\n  padding-top: 0px;\n  transition-delay: 0s;\n  transition-duration: 0.2s;\n  transition-property: -webkit-transform;\n  transition-timing-function: ease;\n  width: 500px;\n  z-index: 0;\n  display: none;\n  position: fixed;\n  top: 25%;\n  left: 50%;\n  width: 400px;\n  margin-left: -200px;\n  padding: 16px;\n  background-color: white;\n  z-index: 4;\n  overflow: auto;\n}\n\n#clear-data-checkbox {\n  list-style-type: none;\n  margin-bottom: 5px;\n}\n\n#sad-webview,\nwebview {\n  position: absolute;\n  bottom: 0;\n  left: 0;\n}\n\n/* The reload button turns into a spinning trobber */\n.loading #reload {\n  -webkit-animation: spinner-animation .5s infinite linear;\n  -webkit-transform-origin: 50% 55.5%;\n}\n\n@-webkit-keyframes spinner-animation {\n  0% { -webkit-transform: rotate(0deg); }\n  100% {-webkit-transform: rotate(360deg); }\n}\n\n/* Due to http://crbug.com/156219 we can't use display: none */\n#sad-webview,\n.exited webview {\n  visibility: hidden;\n  visibility: hidden;\n}\n\n.exited #sad-webview {\n  visibility: visible;\n  background: #343f51;\n  text-align: center;\n  color: #fff;\n}\n\n#sad-webview h2 {\n  font-size: 14px;\n}\n\n#sad-webview p {\n  font-size: 11px;\n}\n\n#sad-webview-icon {\n  font-size: 96px;\n  margin-bottom: 10px;\n}\n\n/* Variant of the crashed page when the process is intentionally killed (in that\ncase we use a different background color and label). */\n.exited #sad-webview #killed-label {\n  display: none;\n}\n\n.killed #sad-webview {\n  background: #393058;\n}\n\n.killed #sad-webview #killed-label {\n  display: block;\n}\n\n.killed #sad-webview #crashed-label {\n  display: none;\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/browser/browser.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <link rel=\"stylesheet\" href=\"browser.css\">\n    <script src=\"browser.js\"></script>\n  </head>\n  <body>\n    <div id=\"controls\">\n\n      <button id=\"back\" title=\"Go Back\">&#9664;</button>\n      <button id=\"forward\" title=\"Go Forward\">&#9654;</button>\n      <button id=\"home\" title=\"Go Home\">&#8962;</button>\n      <button id=\"reload\" title=\"Reload\">&#10227;</button>\n      <button id=\"terminate\" title=\"Simulate Crash\">&#9760;</button>\n      <button id=\"clear-data\" title=\"Clear Data\">&#9851;</button>\n\n      <form id=\"location-form\">\n        <div id=\"center-column\">\n          <input id=\"location\" type=\"text\" value=\"http://www.google.com/\">\n        </div>\n        <input type=\"submit\" value=\"Go\">\n      </form>\n\n      <button id=\"zoom\" title=\"Change Zoom\">&#128270;</button>\n      <button id=\"find\" title=\"Find in Page\">&#128294;</button>\n\n    </div>\n\n    <div id=\"zoom-box\">\n      <form id=\"zoom-form\">\n        <input id=\"zoom-text\" type=\"text\">\n        <input type=\"submit\" value=\"&#128270;\">\n        <button id=\"zoom-in\">&#10133;</button>\n        <button id=\"zoom-out\">&#10134;</button>\n      </form>\n    </div>\n\n    <div id=\"find-box\">\n      <form id=\"find-form\">\n        <input id=\"find-text\" type=\"text\">\n        <div id=\"find-results\"></div>\n        <input type=\"submit\" style=\"position:absolute; visibility:hidden\">\n        <button id=\"match-case\">aA</button>\n        <button id=\"find-backward\">&#60;</button>\n        <button id=\"find-forward\">&#62;</button>\n      </form>\n    </div>\n\n    <div id=\"clear-data-overlay\" class=\"overlay\"></div>\n    <div id=\"clear-data-confirm\">\n      <h2>Clear browsing data</h2>\n      <p>\n        Select to clear the following items:\n      </p>\n      <li id=\"clear-data-checkbox\">\n        <label>\n          <input type=\"checkbox\" id=\"clear-appcache\"></input>\n          <span>App cache</span>\n        </label>\n      </li>\n      <li id=\"clear-data-checkbox\">\n        <label>\n          <input type=\"checkbox\" id=\"clear-cookies\"></input>\n          <span>Cookies</span>\n        </label>\n      </li>\n      <li id=\"clear-data-checkbox\">\n        <label>\n          <input type=\"checkbox\" id=\"clear-fs\"></input>\n          <span>File system</span>\n        </label>\n      </li>\n       <li id=\"clear-data-checkbox\">\n        <label>\n          <input type=\"checkbox\" id=\"clear-indexedDB\"></input>\n          <span>Indexed DB</span>\n        </label>\n      </li>\n      <li id=\"clear-data-checkbox\">\n        <label>\n          <input type=\"checkbox\" id=\"clear-localStorage\"></input>\n          <span>Local storage</span>\n        </label>\n      </li>\n      <li id=\"clear-data-checkbox\">\n        <label>\n          <input type=\"checkbox\" id=\"clear-webSQL\"></input>\n          <span>WebSQL</span>\n        </label>\n      </li>\n      <li id=\"clear-data-checkbox\">\n        <label>\n          <input type=\"checkbox\" id=\"clear-cache\"></input>\n          <span>Cache</span>\n        </label>\n      </li>\n\n      <br>\n\n      <button id=\"clear-data-cancel\">Cancel</button>\n      <button id=\"clear-data-ok\">Clear browsing data</button>\n    </div>\n\n    <webview src=\"http://www.google.com/\" style=\"width:640px; height:480px\"></webview>\n\n    <div id=\"sad-webview\">\n      <div id=\"sad-webview-icon\">&#9762;</div>\n      <h2 id=\"crashed-label\">Aw, Snap!</h2>\n      <h2 id=\"killed-label\">He's Dead, Jim!</h2>\n\n      <p>Something went wrong while displaying this webpage.\n      To continue, reload or go to another page.</p>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/browser/browser.js",
    "content": "window.onresize = doLayout;\nvar isLoading = false;\n\nonload = function() {\n  var webview = document.querySelector('webview');\n  doLayout();\n  webview.focus();\n\n  var version = navigator.appVersion.substr(navigator.appVersion.lastIndexOf('Chrome/') + 7);\n  var match = /([0-9]*)\\.([0-9]*)\\.([0-9]*)\\.([0-9]*)/.exec(version);\n  var majorVersion = parseInt(match[1]);\n  var buildVersion = parseInt(match[3]);\n\n  document.querySelector('#back').onclick = function() {\n    webview.back();\n  };\n\n  document.querySelector('#forward').onclick = function() {\n    webview.forward();\n  };\n\n  document.querySelector('#home').onclick = function() {\n    navigateTo('http://www.google.com/');\n  };\n\n  document.querySelector('#reload').onclick = function() {\n    if (isLoading) {\n      webview.stop();\n    } else {\n      webview.reload();\n    }\n  };\n  document.querySelector('#reload').addEventListener(\n    'webkitAnimationIteration',\n    function() {\n      if (!isLoading) {\n        document.body.classList.remove('loading');\n      }\n    });\n\n  document.querySelector('#terminate').onclick = function() {\n    webview.terminate();\n  };\n\n  var showClearDataConfirmation = function() {\n    document.querySelector('#clear-data-overlay').style.display = '-webkit-box';\n    document.querySelector('#clear-data-confirm').style.display = '-webkit-box';\n  };\n\n  var hideClearDataConfirmation = function() {\n    document.querySelector('#clear-data-overlay').style.display = 'none';\n    document.querySelector('#clear-data-confirm').style.display = 'none';\n  };\n\n  document.querySelector('#clear-data').onclick = showClearDataConfirmation;\n\n  document.querySelector('#clear-data-ok').onclick = function() {\n\n    hideClearDataConfirmation();\n\n    var getAndResetCheckedValueBySelector = function(sel) {\n      var val = document.querySelector(sel).checked;\n      document.querySelector(sel).checked = false;\n      return val;\n    };\n\n    var clearDataType = {\n      appcache: getAndResetCheckedValueBySelector('#clear-appcache'),\n      cookies: getAndResetCheckedValueBySelector('#clear-cookies'),\n      fileSystems: getAndResetCheckedValueBySelector('#clear-fs'),\n      indexedDB: getAndResetCheckedValueBySelector('#clear-indexedDB'),\n      localStorage: getAndResetCheckedValueBySelector('#clear-localStorage'),\n      webSQL: getAndResetCheckedValueBySelector('#clear-webSQL'),\n    }\n\n    if (majorVersion >= 44 || (majorVersion == 43 && buildVersion >= 2350)) {\n      clearDataType['cache'] = getAndResetCheckedValueBySelector('#clear-cache');\n    }\n\n    webview.clearData(\n      { since: 0 }, // Remove all browsing data.\n      clearDataType,\n      function() { webview.reload(); });\n  };\n\n  document.querySelector('#clear-data-cancel').onclick = hideClearDataConfirmation;\n\n  document.querySelector('#location-form').onsubmit = function(e) {\n    e.preventDefault();\n    navigateTo(document.querySelector('#location').value);\n  };\n\n  webview.addEventListener('exit', handleExit);\n  webview.addEventListener('loadstart', handleLoadStart);\n  webview.addEventListener('loadstop', handleLoadStop);\n  webview.addEventListener('loadabort', handleLoadAbort);\n  webview.addEventListener('loadredirect', handleLoadRedirect);\n  webview.addEventListener('loadcommit', handleLoadCommit);\n\n  // Test for the presence of the experimental <webview> zoom and find APIs.\n  if (typeof(webview.setZoom) == \"function\" &&\n      typeof(webview.find) == \"function\") {\n    var findMatchCase = false;\n\n    document.querySelector('#zoom').onclick = function() {\n      if(document.querySelector('#zoom-box').style.display == '-webkit-flex') {\n        closeZoomBox();\n      } else {\n        openZoomBox();\n      }\n    };\n\n    document.querySelector('#zoom-form').onsubmit = function(e) {\n      e.preventDefault();\n      var zoomText = document.forms['zoom-form']['zoom-text'];\n      var zoomFactor = Number(zoomText.value);\n      if (zoomFactor > 5) {\n        zoomText.value = \"5\";\n        zoomFactor = 5;\n      } else if (zoomFactor < 0.25) {\n        zoomText.value = \"0.25\";\n        zoomFactor = 0.25;\n      }\n      webview.setZoom(zoomFactor);\n    }\n\n    document.querySelector('#zoom-in').onclick = function(e) {\n      e.preventDefault();\n      increaseZoom();\n    }\n\n    document.querySelector('#zoom-out').onclick = function(e) {\n      e.preventDefault();\n      decreaseZoom();\n    }\n\n    document.querySelector('#find').onclick = function() {\n      if(document.querySelector('#find-box').style.display == 'block') {\n        document.querySelector('webview').stopFinding();\n        closeFindBox();\n      } else {\n        openFindBox();\n      }\n    };\n\n    document.querySelector('#find-text').oninput = function(e) {\n      webview.find(document.forms['find-form']['find-text'].value,\n                   {matchCase: findMatchCase});\n    }\n\n    document.querySelector('#find-text').onkeydown = function(e) {\n      if (event.ctrlKey && event.keyCode == 13) {\n        e.preventDefault();\n        webview.stopFinding('activate');\n        closeFindBox();\n      }\n    }\n\n    document.querySelector('#match-case').onclick = function(e) {\n      e.preventDefault();\n      findMatchCase = !findMatchCase;\n      var matchCase = document.querySelector('#match-case');\n      if (findMatchCase) {\n        matchCase.style.color = \"blue\";\n        matchCase.style['font-weight'] = \"bold\";\n      } else {\n        matchCase.style.color = \"black\";\n        matchCase.style['font-weight'] = \"\";\n      }\n      webview.find(document.forms['find-form']['find-text'].value,\n                   {matchCase: findMatchCase});\n    }\n\n    document.querySelector('#find-backward').onclick = function(e) {\n      e.preventDefault();\n      webview.find(document.forms['find-form']['find-text'].value,\n                   {backward: true, matchCase: findMatchCase});\n    }\n\n    document.querySelector('#find-form').onsubmit = function(e) {\n      e.preventDefault();\n      webview.find(document.forms['find-form']['find-text'].value,\n                   {matchCase: findMatchCase});\n    }\n\n    webview.addEventListener('findupdate', handleFindUpdate);\n    window.addEventListener('keydown', handleKeyDown);\n  } else {\n    var zoom = document.querySelector('#zoom');\n    var find = document.querySelector('#find');\n    zoom.style.visibility = \"hidden\";\n    zoom.style.position = \"absolute\";\n    find.style.visibility = \"hidden\";\n    find.style.position = \"absolute\";\n  }\n};\n\nfunction navigateTo(url) {\n  resetExitedState();\n  var webview = document.querySelector('webview');\n  webview.focus();\n  webview.src = url;\n}\n\nfunction doLayout() {\n  var webview = document.querySelector('webview');\n  var controls = document.querySelector('#controls');\n  var controlsHeight = controls.offsetHeight;\n  var windowWidth = document.documentElement.clientWidth;\n  var windowHeight = document.documentElement.clientHeight;\n  var webviewWidth = windowWidth;\n  var webviewHeight = windowHeight - controlsHeight;\n\n  webview.style.width = webviewWidth + 'px';\n  webview.style.height = webviewHeight + 'px';\n\n  var sadWebview = document.querySelector('#sad-webview');\n  sadWebview.style.width = webviewWidth + 'px';\n  sadWebview.style.height = webviewHeight * 2/3 + 'px';\n  sadWebview.style.paddingTop = webviewHeight/3 + 'px';\n}\n\nfunction handleExit(event) {\n  console.log(event.type);\n  document.body.classList.add('exited');\n  if (event.type == 'abnormal') {\n    document.body.classList.add('crashed');\n  } else if (event.type == 'killed') {\n    document.body.classList.add('killed');\n  }\n}\n\nfunction resetExitedState() {\n  document.body.classList.remove('exited');\n  document.body.classList.remove('crashed');\n  document.body.classList.remove('killed');\n}\n\nfunction handleFindUpdate(event) {\n  var findResults = document.querySelector('#find-results');\n  if (event.searchText == \"\") {\n    findResults.innerText = \"\";\n  } else {\n    findResults.innerText =\n        event.activeMatchOrdinal + \" of \" + event.numberOfMatches;\n  }\n\n  // Ensure that the find box does not obscure the active match.\n  if (event.finalUpdate && !event.canceled) {\n    var findBox = document.querySelector('#find-box');\n    findBox.style.left = \"\";\n    findBox.style.opacity = \"\";\n    var findBoxRect = findBox.getBoundingClientRect();\n    if (findBoxObscuresActiveMatch(findBoxRect, event.selectionRect)) {\n      // Move the find box out of the way if there is room on the screen, or\n      // make it semi-transparent otherwise.\n      var potentialLeft = event.selectionRect.left - findBoxRect.width - 10;\n      if (potentialLeft >= 5) {\n        findBox.style.left = potentialLeft + \"px\";\n      } else {\n        findBox.style.opacity = \"0.5\";\n      }\n    }\n  }\n}\n\nfunction findBoxObscuresActiveMatch(findBoxRect, matchRect) {\n  return findBoxRect.left < matchRect.left + matchRect.width &&\n      findBoxRect.right > matchRect.left &&\n      findBoxRect.top < matchRect.top + matchRect.height &&\n      findBoxRect.bottom > matchRect.top;\n}\n\nfunction handleKeyDown(event) {\n  if (event.ctrlKey) {\n    switch (event.keyCode) {\n      // Ctrl+F.\n      case 70:\n        event.preventDefault();\n        openFindBox();\n        break;\n\n      // Ctrl++.\n      case 107:\n      case 187:\n        event.preventDefault();\n        increaseZoom();\n        break;\n\n      // Ctrl+-.\n      case 109:\n      case 189:\n        event.preventDefault();\n        decreaseZoom();\n    }\n  }\n}\n\nfunction handleLoadCommit(event) {\n  resetExitedState();\n  if (!event.isTopLevel) {\n    return;\n  }\n\n  document.querySelector('#location').value = event.url;\n\n  var webview = document.querySelector('webview');\n  document.querySelector('#back').disabled = !webview.canGoBack();\n  document.querySelector('#forward').disabled = !webview.canGoForward();\n  closeBoxes();\n}\n\nfunction handleLoadStart(event) {\n  document.body.classList.add('loading');\n  isLoading = true;\n\n  resetExitedState();\n  if (!event.isTopLevel) {\n    return;\n  }\n\n  document.querySelector('#location').value = event.url;\n}\n\nfunction handleLoadStop(event) {\n  // We don't remove the loading class immediately, instead we let the animation\n  // finish, so that the spinner doesn't jerkily reset back to the 0 position.\n  isLoading = false;\n}\n\nfunction handleLoadAbort(event) {\n  console.log('LoadAbort');\n  console.log('  url: ' + event.url);\n  console.log('  isTopLevel: ' + event.isTopLevel);\n  console.log('  type: ' + event.type);\n}\n\nfunction handleLoadRedirect(event) {\n  resetExitedState();\n  if (!event.isTopLevel) {\n    return;\n  }\n\n  document.querySelector('#location').value = event.newUrl;\n}\n\nfunction getNextPresetZoom(zoomFactor) {\n  var preset = [0.25, 0.33, 0.5, 0.67, 0.75, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2,\n                2.5, 3, 4, 5];\n  var low = 0;\n  var high = preset.length - 1;\n  var mid;\n  while (high - low > 1) {\n    mid = Math.floor((high + low)/2);\n    if (preset[mid] < zoomFactor) {\n      low = mid;\n    } else if (preset[mid] > zoomFactor) {\n      high = mid;\n    } else {\n      return {low: preset[mid - 1], high: preset[mid + 1]};\n    }\n  }\n  return {low: preset[low], high: preset[high]};\n}\n\nfunction increaseZoom() {\n  var webview = document.querySelector('webview');\n  webview.getZoom(function(zoomFactor) {\n    var nextHigherZoom = getNextPresetZoom(zoomFactor).high;\n    webview.setZoom(nextHigherZoom);\n    document.forms['zoom-form']['zoom-text'].value = nextHigherZoom.toString();\n  });\n}\n\nfunction decreaseZoom() {\n  var webview = document.querySelector('webview');\n  webview.getZoom(function(zoomFactor) {\n    var nextLowerZoom = getNextPresetZoom(zoomFactor).low;\n    webview.setZoom(nextLowerZoom);\n    document.forms['zoom-form']['zoom-text'].value = nextLowerZoom.toString();\n  });\n}\n\nfunction openZoomBox() {\n  document.querySelector('webview').getZoom(function(zoomFactor) {\n    var zoomText = document.forms['zoom-form']['zoom-text'];\n    zoomText.value = Number(zoomFactor.toFixed(6)).toString();\n    document.querySelector('#zoom-box').style.display = '-webkit-flex';\n    zoomText.select();\n  });\n}\n\nfunction closeZoomBox() {\n  document.querySelector('#zoom-box').style.display = 'none';\n}\n\nfunction openFindBox() {\n  document.querySelector('#find-box').style.display = 'block';\n  document.forms['find-form']['find-text'].select();\n}\n\nfunction closeFindBox() {\n  var findBox = document.querySelector('#find-box');\n  findBox.style.display = 'none';\n  findBox.style.left = \"\";\n  findBox.style.opacity = \"\";\n  document.querySelector('#find-results').innerText= \"\";\n}\n\nfunction closeBoxes() {\n  closeZoomBox();\n  closeFindBox();\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/browser/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  runApp();\n});\n\n/**\n * Listens for the app restarting then re-creates the window.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n */\nchrome.app.runtime.onRestarted.addListener(function() {\n  runApp();\n});\n\n/**\n * Creates the window for the application.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nfunction runApp() {\n  chrome.app.window.create('browser.html', {\n  \tid: \"browserWinID\",\n    innerBounds: {\n      'width': 1024,\n      'height': 768\n    }\n  });\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/browser/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Browser Sample\",\n  \"minimum_chrome_version\": \"24.0.1307.0\",\n  \"version\": \"2.3.3\",\n  \"icons\": {\n    \"16\": \"icon_16.png\",\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"webview\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/declarative-web-request/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hhflblflkeainajnkamabjibdbfnbilb\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Declarative Web Request API\n\n**Note:** The [declarative web request\nAPI](https://developer.chrome.com/extensions/declarativeWebRequest) is\navailable only on the [beta\nchannel](https://www.google.com/landing/chrome/beta/) and [dev\nchannel](http://www.chromium.org/getting-involved/dev-channel). This sample\nwill not work on [stable channel](https://www.google.com/chrome/browser/)\nbuilds.\n\nThis sample shows how to use the declarative web request API with a\nwebview. The app implements a simple content blocker for URLs that match a\n[RE2 regular expression](https://code.google.com/p/re2/wiki/Syntax). The\ndefault pattern blocks hosts that contain `blogspot.` (such as blogspot.com\nblogs) or `gstatic.` (such as thumbnails in Google image search). Top frame\nand sub-frame navigation redirects the whole webview to a \"page blocked\" page\n(see screenshot left). Image loads are redirected to a dummy image that\ncontains a shortened version of the image URL as text (see screenshot\nright). The user can modify the URL matching pattern using a form on the\ntop-right. Content blocking actions are logged beneath the form on the\ntop-right.\n\n## Resources\n\n* [Declarative Web Request API](https://developer.chrome.com/extensions/declarativeWebRequest)\n* [Webview](http://developer.chrome.com/apps/app_external#webview)\n* [Permissions](http://developer.chrome.com/apps/manifest#permissions)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/webview-samples/declarative-web-request/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/declarative-web-request/blocked.css",
    "content": "body {\n  color: #fff;\n  background: #000;\n  font-family: Lucida Grande, Arial, sans-serif;\n  font-size: 48px;\n  font-weight: bold;\n}\n\n.a {\n  color: #33f;\n  text-decoration: none;\n}\n\n.a:hover {\n  color: #66f;\n  text-decoration: underline;\n  cursor: pointer;\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/declarative-web-request/blocked.html",
    "content": "<!DOCTYPE html>\n<html class=\"trim full\">\n  <head>\n    <link rel=\"stylesheet\" href=\"browser.css\">\n    <link rel=\"stylesheet\" href=\"blocked.css\">\n  </head>\n  <body class=\"trim full flex-container column center\">\n    <div class=\"flex flex-container row center\">\n      <div class=\"flex flex-container column center\">\n        <div class=\"flex center-text\">Page blocked</div>\n        <div class=\"flex center-text\">\n          <span class=\"a\" onclick=\"window.history.back()\">Go Back</span>\n        </div>\n      </div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/declarative-web-request/browser.css",
    "content": "body {\n  font-family: Lucida Grande, Arial, sans-serif;\n}\n\npre {\n  display: inline;\n}\n\nlabel,\ninput,\nbutton,\nhr {\n  flex: none;\n}\n\nhr {\n  width:100%;\n}\n\nlabel,\n.submit {\n  font-weight: bold;\n  font-family: inherit;\n}\n\ninput,\n#console div {\n  font-family: \"courier\";\n}\n\n#console div {\n  text-indent: -15px;\n  margin-left: 15px;\n}\n\n#console {\n  overflow-y: auto;\n}\n\n.trim {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n.full {\n  width: 100%;\n  height: 100%;\n}\n\n.padded {\n  padding: 10px;\n}\n\n.flex-container {\n  display: flex;\n}\n\n.row {\n  flex-direction: row;\n}\n\n.column {\n  flex-direction: column;\n}\n\n.center {\n  align-items: center;\n}\n\n.center-text {\n  text-align: center;\n}\n\n.flex {\n  flex-grow: 1;\n  flex-shrink: 1;\n}\n\n.flex-wide {\n  flex-grow: 4;\n  flex-shrink: 1;\n}\n\n.flex-narrow {\n  flex-grow: 1;\n  flex-shrink: 4;\n  width: 300px;\n}\n\n.rel {\n  position: relative;\n}\n\n.abs {\n  position: absolute;\n}\n\n.abs-full {\n  position: absolute;\n  top: 0px;\n  right: 0px;\n  bottom: 0px;\n  left: 0px;\n}\n\n.lightbox-overlay {\n  opacity: 0.5;\n  background: #000;\n}\n\n.lightbox {\n  padding: 20px;\n  margin: 20px;\n  background: #fff;\n  border-radius: 5px;\n}\n\n.hide {\n  visibility: hidden;\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/declarative-web-request/browser.html",
    "content": "<!DOCTYPE html>\n<html class=\"trim full\">\n  <head>\n    <link rel=\"stylesheet\" href=\"browser.css\">\n    <script src=\"config.js\"></script>\n    <script src=\"content_blocker.js\"></script>\n    <script src=\"content_blocker_main.js\"></script>\n  </head>\n  <body class=\"trim full\">\n\n    <div class=\"flex-container row\">\n\n      <div class=\"trim flex-wide rel\">\n\t<webview id=\"content-webview\" class=\"trim full\"\n\t         partition=\"blockable\"></webview>\n      </div>\n\n      <form id=\"form\" class=\"padded flex-narrow flex-container column rel\">\n  \t<input id=\"submit\" class=\"submit\" type=\"submit\" value=\"Save & Apply\" disabled>\n  \t<label for=\"url-pattern\">URL pattern to block\n  \t  (<a href=\"http://code.google.com/p/re2/wiki/Syntax\" target=\"_blank\">RE2\n  \t    syntax</a>)</label>\n\t<input id=\"url-pattern\" type=\"text\" disabled></input>\n        <hr />\n  \t<button id=\"reset\" class=\"submit\" disabled>Reset to Defaults</button>\n        <hr />\n        <label for=\"console\">Content blocking log</label>\n        <div id=\"console\" class=\"trim full flex\">\n        </div>\n      </form>\n\n    </div>\n\n    <div id=\"lightbox-overlay\" class=\"full trim abs abs-full lightbox-overlay hide\">\n    </div>\n\n    <div id=\"lightbox\" class=\"full trim abs abs-full flex-container column center hide\">\n      <div class=\"flex flex-container row center\">\n        <div class=\"flex flex-container column center lightbox\">\n          <h1 class=\"flex center-text\">Chrome Feature Not Supported</h1>\n          <div class=\"flex center-text\">\n            The feature highlighted by this sample app is not supported in\n            your version of Chrome. Make sure your browser is up to date. If\n            you still see this message after updating your browser, try\n            installing\n            a <a href=\"http://www.chromium.org/getting-involved/dev-channel\"\n            target=\"_blank\">dev channel</a> build of Chrome.\n          </div>\n        </div>\n      </div>\n    </div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/declarative-web-request/config.js",
    "content": "// Global configuration variables\nvar config = {\n  'homepage': 'https://www.google.com/search?q=Google+Blog',\n  'urlPattern': '^[^:]*:[/][/][^/]*(blogspot.|gstatic.).*$'\n};\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/declarative-web-request/content_blocker.js",
    "content": "var contentBlocker = (function(configModule) {\n  var dce = function(tagName) { return document.createElement(tagName); };\n\n  var extensionId = chrome.runtime.id;\n  var ContentBlocker = function(\n      webview,\n      form,\n      submitButton,\n      urlPatternInput,\n      resetButton,\n      consoleElement,\n      opt_cancelResourceTypes) {\n    this.urlPattern = null;\n    this.webview = webview;\n    this.form = form;\n    this.submitButton = submitButton;\n    this.urlPatternInput = urlPatternInput;\n    this.resetButton = resetButton;\n    this.consoleElement = consoleElement;\n    this.cancelResourceTypes = opt_cancelResourceTypes || [\n      'stylesheet',\n      'object',\n      'xmlhttprequest',\n      'other',\n      'main_frame',\n      'sub_frame',\n      'script'\n    ];\n\n    this.init();\n  };\n\n  ContentBlocker.prototype.init = function() {\n    (function(cb) {\n      // Respond to messages triggered by declarative web request API rules\n      cb.webview.request.onMessage.addListener(function(details) {\n        var data = JSON.parse(details.message);\n        var msgDiv = dce('div');\n        var patternPre = dce('pre');\n        var prefixSpan = dce('span');\n        var postfixSpan = dce('span');\n        prefixSpan.innerText = '\"' + data.type + '\" matching ';\n        patternPre.innerText = '/' + data.urlPattern + '/';\n        postfixSpan.innerText = ' ' + data.action;\n        msgDiv.appendChild(prefixSpan);\n        msgDiv.appendChild(patternPre);\n        msgDiv.appendChild(postfixSpan);\n        cb.consoleElement.appendChild(msgDiv);\n        cb.consoleElement.scrollTop = cb.consoleElement.scrollHeight;\n\n        // Cannot redirect immediately to package-local resources; (see\n        // http://crbug.com/379733); use message-send + message-listener instead\n        if (data.type == 'main_frame' || data.type == 'sub_frame') {\n          cb.webview.src = 'blocked.html';\n        }\n      });\n\n      // Bind to reset button event: load state from config\n      cb.resetButton.addEventListener('click', function(e) {\n          cb.removeRules();\n\n          var urlPattern = configModule.urlPattern;\n          cb.urlPattern = urlPattern;\n          cb.urlPatternInput.value = urlPattern;\n\n          chrome.storage.local.set({'urlPattern': urlPattern});\n\n          cb.refreshRules();\n          cb.addRules();\n\n          cb.consoleElement.innerHTML = '';\n\n          cb.webview.src = configModule.homepage;\n      });\n\n      // Update state and reload when committing to URL\n      cb.form.addEventListener('submit', function(e) {\n        e.preventDefault();\n\n        cb.removeRules();\n\n        var urlPattern = cb.urlPatternInput.value;\n        cb.urlPattern = urlPattern;\n\n        chrome.storage.local.set({'urlPattern': urlPattern});\n\n        cb.refreshRules();\n        cb.addRules();\n\n        cb.webview.reload();\n      });\n\n      // Load state from local storage or else config\n      chrome.storage.local.get(\n        ['urlPattern'],\n        function(data) {\n          var urlPattern = data.urlPattern ?\n              data.urlPattern :\n              configModule.urlPattern;\n          cb.urlPattern = urlPattern;\n          cb.urlPatternInput.value = urlPattern;\n\n          cb.submitButton.removeAttribute('disabled');\n          cb.urlPatternInput.removeAttribute('disabled');\n          cb.resetButton.removeAttribute('disabled');\n\n          cb.refreshRules();\n          cb.addRules();\n\n          cb.webview.src = configModule.homepage;\n        });\n    }(this));\n  };\n\n  ContentBlocker.prototype.removeRules = function() {\n    var ruleIds = this.rules.map(function(rule) { return rule.id; });\n    this.webview.request.onRequest.removeRules(ruleIds);\n  };\n\n  ContentBlocker.prototype.addRules = function() {\n    this.webview.request.onRequest.addRules(this.rules);\n  };\n\n  ContentBlocker.prototype.refreshRules = function() {\n    // Construct individual blockers for each cancel-able resource type\n    this.rules = (function(cb) {\n      return cb.cancelResourceTypes.map(function(type) {\n        return { // Cancel request for blocked resource and send a message\n          'id': type + 'Blocker',\n          'priority': 1000,\n          'conditions': [\n            new chrome.webViewRequest.RequestMatcher({\n              'url': {'urlMatches': cb.urlPattern},\n              'resourceType': [type]\n            })\n          ],\n          'actions': [\n            new chrome.webViewRequest.CancelRequest(),\n            new chrome.webViewRequest.SendMessageToExtension({\n              'message': JSON.stringify({\n                  'type': type,\n                  'action': 'cancelled',\n                  'urlPattern': cb.urlPattern\n              })\n            })\n          ]\n        };\n      });\n    }(this));\n\n    // Add on special blockers for images\n    this.rules.push({ // Redirect image requests to blocked image generator\n      'id': 'imageRedirect',\n      'priority': 100,\n      'conditions': [\n        new chrome.webViewRequest.RequestMatcher({\n          'url': {'urlMatches': this.urlPattern},\n          'resourceType': [\n            'image'\n          ]\n        })\n      ],\n      'actions': [\n        new chrome.webViewRequest.SendMessageToExtension({\n          'message': JSON.stringify({\n            'type': 'image',\n            'action': 'redirected',\n            'urlPattern': this.urlPattern\n          })\n        }),\n        new chrome.webViewRequest.RedirectByRegEx({\n          'from': '^.*:\\/\\/([^/]*)[^#?]*\\/([^#?]*)([#?].*)?$',\n          'to': 'http://dummyimage.com/xga/000/0f0.png&text=BLOCKED:$1/.../$2'\n        })\n      ]\n    },\n    { // Prevent redirect loop on image requests to blocked image generator\n      'id': 'imageRedirectStop',\n      'priority': 1000,\n      'conditions': [\n        new chrome.webViewRequest.RequestMatcher({\n          'url': {'hostSuffix': 'dummyimage.com'}\n        })\n      ],\n      'actions': [\n        new chrome.webViewRequest.IgnoreRules({\n          'lowerPriorityThan': 1000\n        })\n      ]\n    });\n  };\n\n  return {'ContentBlocker': ContentBlocker};\n}(config));\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/declarative-web-request/content_blocker_main.js",
    "content": "var mainContentBlocker = null;\n(function(configModule, contentBlockerModule) {\n  var query = function(str) { return document.querySelector(str); };\n\n  window.addEventListener('load', function(e) {\n    var webview = query('#content-webview');\n\n    // Check for declarative web request API\n    if (webview.request &&\n        webview.request.onRequest &&\n        webview.request.onMessage) {\n      mainContentBlocker = new contentBlockerModule.ContentBlocker(\n          query('#content-webview'),\n          query('#form'),\n          query('#submit'),\n          query('#url-pattern'),\n          query('#reset'),\n          query('#console'));\n    } else {\n      // When API not available, show lightbox\n      query('#lightbox-overlay').classList.remove('hide');\n      query('#lightbox').classList.remove('hide');\n    }\n  });\n}(config, contentBlocker));\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/declarative-web-request/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  runApp();\n});\n\n/**\n * Listens for the app restarting then re-creates the window.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n */\nchrome.app.runtime.onRestarted.addListener(function() {\n  runApp();\n});\n\n/**\n * Creates the window for the application.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nfunction runApp() {\n  chrome.app.window.create(\n    'browser.html',\n    {'id': 'initialBrowserWindowID', 'state': 'maximized'});\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/declarative-web-request/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Declarative Web Request API Sample\",\n  \"minimum_chrome_version\": \"24.0.1307.0\",\n  \"version\": \"2.0\",\n  \"icons\": {\n    \"16\": \"icon_16.png\",\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"config.js\", \"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"webview\",\n    \"storage\",\n    \"*://*/*\"\n  ],\n  \"webview\": {\n    \"partitions\": [\n      {\n        \"name\": \"blockable\",\n        \"accessible_resources\": [\"browser.css\", \"blocked.css\", \"blocked.html\"]\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/insert-css/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/dnedmnfnnbpgnedogbljhiacgmkbklfj\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Insert CSS\n\nSample that shows how to inject CSS into a\n[webview](http://developer.chrome.com/apps/app_external#webview). The\nuser can adjust the regular expression used to match URLs for injection, and\nadjust the injected CSS itself. Navigation is only supported through\nfollowing links within the webview.\n\n## Resources\n\n* [Webview](http://developer.chrome.com/apps/app_external#webview)\n* [Permissions](http://developer.chrome.com/apps/manifest#permissions)\n\n\n## Screenshot\n\n![screenshot](/_archive/apps/samples/webview-samples/insert-css/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/insert-css/browser.css",
    "content": "label,\ninput {\n  flex: none;\n}\n\ninput,\ntextarea {\n  font-family: \"courier\";\n}\n\ntextarea {\n  flex-grow: 1;\n  flex-shrink: 1;\n}\n\nlabel,\ninput.submit {\n  font-weight: bold;\n  font-family: inherit;\n}\n\n.trim {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n.full {\n  width: 100%;\n  height: 100%;\n}\n\n.padded {\n  padding: 10px;\n}\n\n.flex-container {\n  display: flex;\n}\n\n.row {\n  flex-direction: row;\n}\n\n.column {\n  flex-direction: column;\n}\n\n.flex-wide {\n  flex-grow: 4;\n  flex-shrink: 1;\n}\n\n.flex-narrow {\n  flex-grow: 1;\n  flex-shrink: 4;\n}\n\n.rel {\n  position: relative;\n}\n\n.abs {\n  position: absolute;\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/insert-css/browser.html",
    "content": "<!DOCTYPE html>\n<html class=\"trim full\">\n  <head>\n    <link rel=\"stylesheet\" href=\"browser.css\">\n    <script src=\"config.js\"></script>\n    <script src=\"css.js\"></script>\n    <script src=\"css_main.js\"></script>\n  </head>\n  <body class=\"trim full\">\n\n    <div class=\"flex-container row\">\n\n      <div class=\"trim flex-wide rel\">\n\t<webview id=\"content-webview\" class=\"trim full\"></webview>\n      </div>\n\n      <form id=\"css-form\" class=\"padded flex-narrow flex-container column rel\">\n  \t<input class=\"submit\" type=\"submit\" value=\"Save & Apply\">\n  \t<label for=\"location-regex\">Location regular expression</label>\n\t<input id=\"location-regex\" type=\"text\" disabled>\n  \t<label for=\"css-contents\">CSS contents</label>\n\t<textarea id=\"css-contents\" disabled></textarea>\n      </form>\n\n    </div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/insert-css/config.js",
    "content": "// Global configuration variables\nvar config = {\n  'homepage': 'https://www.google.com/search?q=Top+Secret',\n  'urlPattern': /^.*google[.]..*[/].*q=.*$/,\n  'cssFilename': 'inject.css'\n};\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/insert-css/css.js",
    "content": "var css = (function(configModule) {\n  var Css = function(\n      urlPattern,       // URL matching regular expression\n      filename,         // Name of file from which initial CSS should be loaded\n      webview,          // Webview DOM node\n      form,             // Form DOM node\n      urlPatternInput,  // Input node for URL matching regular expression\n      cssInput) {       // Input (textarea) node for CSS\n    this.urlPattern = urlPattern;\n    this.filename = filename;\n    this.webview = webview;\n    this.form = form;\n    this.urlPatternInput = urlPatternInput;\n    this.cssInput = cssInput;\n    this.loadOnStop = false;\n    this.cssString = '';\n\n    this.init();\n  };\n\n  Css.prototype.init = function() {\n    // Load \"homepage\"\n    this.webview.src = configModule.homepage;\n\n    (function(css) {\n      // Hook up CSS injection for each page load\n      css.webview.addEventListener(\n          'loadcommit',\n          function(e) { return css.doLoadCommit(e); });\n      css.webview.addEventListener(\n          'loadstop',\n          function(e) { return css.doLoadStop(e); });\n      // Update state and reload when committing to new URL pattern and CSS\n      css.form.addEventListener('submit', function(e) {\n        e.preventDefault();\n\n        var urlPattern = css.urlPatternInput.value;\n        var cssString = css.cssInput.value;\n\n        css.urlPattern = new RegExp(urlPattern);\n        css.cssString = cssString;\n\n        chrome.storage.local.set({\n          'urlPattern': urlPattern,\n          'cssString': cssString\n        });\n\n        css.webview.reload();\n      });\n\n      chrome.storage.local.get(\n        ['urlPattern', 'cssString'],\n        function(data) {\n\n          if (data.cssString) {\n            // Prepare css string from local storage\n            css.cssString = data.cssString;\n            css.cssInput.value = data.cssString;\n            css.cssInput.removeAttribute('disabled');\n          } else {\n            // Fetch initial CSS file\n            (function(xhr) {\n              xhr.addEventListener('readystatechange', function(e) {\n                if (xhr.readyState == 4) {\n                  css.cssInput.value = xhr.responseText;\n                  css.cssInput.removeAttribute('disabled');\n                }\n              });\n              xhr.open('GET', 'inject.css', true);\n              xhr.send();\n            }(new XMLHttpRequest()));\n          }\n\n          if (data.urlPattern) {\n            // Prepare URL pattern from local storage\n            css.urlPattern = new RegExp(data.urlPattern);\n            css.urlPatternInput.value = data.urlPattern;\n          } else {\n            // Use default pattern (injected into Css object already)\n            css.urlPatternInput.value = css.urlPattern.source;\n          }\n          css.urlPatternInput.removeAttribute('disabled');\n\n        });\n    }(this));\n  };\n\n  Css.prototype.doLoadCommit = function(e) {\n    if (e.url.match(this.urlPattern) !== null) {\n      this.loadOnStop = true;\n    }\n  };\n\n  Css.prototype.doLoadStop = function(e) {\n    if (this.loadOnStop) {\n      this.injectCss();\n      this.loadOnStop = false;\n    }\n  };\n\n  Css.prototype.injectCss = function() {\n    if (this.cssString) {\n      this.webview.insertCSS({'code': this.cssString});\n    } else {\n      // On initial load, cssString may not be ready yet;\n      // use the initial file instead\n      this.webview.insertCSS({'file': this.filename});\n    }\n  };\n\n  return {'Css': Css};\n}(config));\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/insert-css/css_main.js",
    "content": "var mainCss = null;\n(function(configModule, cssModule) {\n  var query = function(str) { return document.querySelector(str); };\n\n  window.addEventListener('load', function(e) {\n    mainCss = new cssModule.Css(\n        configModule.urlPattern,\n        configModule.cssFilename,\n        query('#content-webview'),\n        query('#css-form'),\n        query('#location-regex'),\n        query('#css-contents'));\n  });\n}(config, css));\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/insert-css/inject.css",
    "content": "/*\n * Black out portions of search results for a stylized \"top secret page\".\n */\n\n/*\n * Some things are styled with too much detail; just hide them.\n */\n#mngb,\n#top_nav,\n#resultStats,\nli.ads-ad {\n  display: none;\n}\n\n/*\n * We would like to just say \"body { ... }\", but more specific rules often\n * override us. This list seems to work well.\n */\nhtml,\nbody,\nbody a,\nbody h1,\nbody span,\nbody li.g,\nbody .std {\n  font-family: \"courier\" !important;\n}\n\n/*\n * Black out links, site names, and the search phrase in descriptions\n */\nb,\nem,\nh3 a:link,\nh3 a:visited,\nh3 a:hover,\nli cite,\ndiv.crl {\n  color: #000 !important;\n  background: #000 !important;\n}\n\n/*\n * Top secret sticker background for \"blacked out search results\" page.\n */\nbody#gsr {\n  background-position: center;\n  background-attachment: fixed;\n  background-repeat: no-repeat;\n  /*\n   * Image from:\n   *   http://thinkspace.com/wp-content/uploads/2012/11/20100128-top-secret.gif\n   * Image is marked for reuse with modification:\n   *   https://www.google.com/search?tbs=sur:fmc&tbm=isch&q=top+secret+sticker\n   * Inline image to avoid http/https mixing\n   */\n  background-image: url(data:image/gif;base64,R0lGODlhWAH6AKIAALcAANoAAJIAAGsAAEEAABAAAP8AAP///yH5BAEAAAcALAAAAABYAfoAAAP/eLrc/jDKSau9OOvNu/9gKI5kaZ5oqq5s675wLM9lcRQ2re987/8PG45AzAGPyKRyORkSBc8ic0qtWlXOgTawhRKv4LB4DMlCDdooAEduu98/M4E7nwPu9y98z++b5Gl5a2dceX6HiIkUZnh0gQWFkWmKlJV9WZCNkph2mXqWoKFWnJ0Cml6Mg5+irK1xgJKCRWw3sl6uuLkvsKqnmAyZjlq6xMUjpKaCaLa0Dji9t8bS0xawdY2lUhHP0EbU3+DIm91Di9yP4OnUvLGPzRXnwurzuJjKhdmzGqmr9P6IQuKhCZaHUwd7pt79W/jGGsFBwhRucLJMG8OLYgI+tFNx/2AaiQeHVByGsSQVNgiX4SNksYaagSZjImEXEc8sby6xGZLJc4e4dp7KsYjXsqfRoT91fhTaQuCko1BPaGS5ZeNNGRQDRd16zFoyX0VjiDwTlqvZRTeebRy3tAcynGfjOks7yybEr6jg+lQDSa/cuICu1VzjJIlalf3+cp1KSFjjLFO4IVZ8NuVHvBH9HiFKh3JUfnaZlV3CmaRnnqnuYR590svk0yYdrs6reVTfa7VhT0P46FRBkBkPO9LtD7RrsMDJZP1IPBzvIrNZN1yduzmo1J7s3tanaCxk67n45RNdfU/p8uD58G5HvpV3VOmvG/e9FL2fsZviJxJfdWUy6f+hnBOFfvelRhZBN9lHiXgEwsFYIHflk1x40LXV4BgG/lfhb/PgV4eCF/IQWBdsMVdcFLeFeFKGCQE1oXOCvagiDSOqthJTDHnY2YyvrNffdgDSs9xTPOpAE30WosaRPEVixeKG9X323hpNwoAdghoGeQGUULi3pIlVplAjiY4lFhI274Go3JRqhgkPXS8pZZOW8OCWHVAB1rWTmyLMJyGYIASkIXvnyCchnx8kNYBHKOKYaDBf+tficJZAyh2i+/gI4aK/kACkpZIqQ4B8/smI6QJedcHXpY8acadwoeZXCX6UnioBIx9ql0+fHHmDogJxNhahoTG2qeKYlnbi6Jn/nJp2KzSO7TirSEHZCgycwrozkql1IqhWnbawVala6FibIZZVLcvBWv/dUU26hBKbJaaCUncnbbwC9ZuW6L5kbBhD/gubprSpwi24x4lmkwU3XubsggImVGW9DvtrsMBB4BUpblTCE+5xrJTi0YwP9hYJYgfv025ov+15azZ0wJTnohqHOOaB5KrrqcWzuRxByyc/PG07Fx4pamEuDHmgL01sSuKoIUcMNXg+jrRtyn8EXbGZqNI3spcJc/0XxU8gGWUPLNMnwcoJZULh0RhfhCujmDEZAikZbFw2zXoB2bbEutyLdWxPdkSYzhMVXO4iotYtdLOaIP12aIMvVLLh/yIDejdidcvc9KuYNQB5zHQOrXHc39SoEnKoO6OxAXTD92y0THftdOsObvf1URpJDSGjlZdBmO2rkz5nboQiCAyaHcIrttzUGm613Xer6qrjZC68ze+Tag/s8M3f5XlJl0ufXenVwH6g6JJhPtI2xbMcPDH9ki/O3n9KxTeryw92489Hm5O7YqI7xKVubnm5mgE9kDBpZWw8DhMe9uZEOI4J7YBZUR/+rDc/jwVAgxcUnZwa9kDtoEkAMtlgB7sjHo+A8HC4kyA0ELa1tslQaxS035LGZww/vXBbLtBVCF1HloJcLGM2khVG2vfBjkkjVa+TXfWmhsQX2mdvOOxSCf+hpZV6AC5vDYshwOBEFFpdZYofpKIDTqi+LY2wXTdUlRJJpcHEPU2MVSCb+prYQP6daY9zgB+73Ei5O25RX1ygY2gydb5ozIxLMHMH7miWJa7JcXEe7GOKkNgrPQ3RPKerY95y9SFiSYYvkfMjCB5jFwj4Zo8YgJS+/CIYPvKxL7P64X/sCDk8AsEyxrPTAg+yx1tqUYQjVFBQLiPKB6jGYr3zZVPWaDZeptGRlzCaEFeIqjqI8CGwpCYrHcg4vtGOloKjnXYAtgUiBg12anLKMc1TuLBxs2u7I96X4GJB8cVyVb9Dp9cilsMVmZOfwUKDNW2YOzZlD4T3rAVhvlL/BoKqsZ84++frvuNMW14zZpJSo2F2iIft1TKe0HmfcsjYLn81Kl+Rq8jsCIHMj7WTkCbznjvfmbZh0uhpxatNX/DBSKetKaHuywtM2ZZG5FFSofgciPkU1DncmDRbMSoIEzJnzE9K1JtFVZY0/4CtDQpQqTvTyeogwbhmKkCXQ51nOVMJ1iqe8nR51CU8C9G0W4YVH2PdGUU4Z0SOBop9r9xfX+2A2LWSKJaNq8r26JaswDJQnFhi1ASMV9SPWtYD9Uyg5FYpV5LedQBN6Ig31Bo7ZXY1GTI8zN5Is8v+PbWYUIUfNjJ1us/+1WnHAVK+3IZZ6+12bSDsX/weu6Vl/w7ImVj0BGloVVPcFrOvtWru7X75HO5drHVZxaZEOfcl7HouVw3LZ2ptKjzn0nav2X2rdVWz2ETyFqK+/RxSi6XKDrTIX9W1in2vWtevnjO35pgNgfO7rvgtY6dZFCkyn6vRoxmJYJX16SghAilxhqqUyJWqbSeIwnfhyaRKeAe6ELwALsKXxe58XkWjy2D2ddeWZ5SKC92KT0qCU8KNRW03Lzk6IBNRrMqp7Vct1dHlqvRlGt7pJpPGi36hz7+qFTInraYs/z60vJnUKjsPSjxA3lCDuEVKEaN8EDKCahM5Hor4NNO9TfEQjAa7h6nuWONEsSSc33tNHIvJNzn/zf+JZMVVXO3V5/HC81m1zBZoK1kTpxbWNsyMXI+/WEU0v1jNh8YjMEEK0EYrV8uudByhJz091yAu0kb+ZSp1yQAcb1bVfsWCt7z6Tyj21tRH5tRMb7S6Vn001H3rDbBx2iupwvfUcq2uYx9t6P/GbT4uIpIPyHTraT+5wUbcJtI2mNfbvlhVm4bx8piYsKYQGbQ3QxFaN/M/ALZ6fX6OkJ27YLtlN8HD2fPxgA8grG6nTaa6Nm6bjLNoYW71R5AmdM0CFWlPcyOPnfhmpIxJ7bSYWbfLLRuo6/2uYJVm3g8Xs70jBFFeJTQ7kdnUN/kYVUnU+rpXdfCDV6AjGQMrMC//ViAYTjrTRT+7K1i8Zqz3cmgeqoukJQ40bEMscQ2NXLNQ5p7f2hZRGEz8zPi7M9INWvVoZ72Zr3pZMIs3csMG+43783e+xX5zvfI4ZJ07dgAgy7laNwt5aO6ltvXXdOCYUeBnc4Pyhr1jlbgCgRZHH9uuR7O5yomxPA+vQPtTya6jjeYGzzuv7+PRsl8j6997qq/ovm4rf/DqhZZghdyuno4z/t6P56IcBR3g1KN6yCa24scT7kJL5llzh1g6tHv2+B8nceDQrhMhnd3UmxL/68A4rdxnwimdq3tBPcMxoGvK1j80snZYQPaMSedz98w3qBQO0HzLZvu6s56Ysjz3/6/MX6rNVwscvpBYdwd+5mZxqTaAc4drjkF4X/F02pcOBah3gjF09KdeP5NZWARhdPcvu9d0GWV+mQNyXBcOIOVR8nZ/2+Zd67RehTR8BFd60Ld/99Vst8F2IOhYQfBj20dv88dliEZvPlaB+BJ6EQgAfmddq4VJGaB0iUUuDNhyOYhjOyhrjDZUnpdWgCSEziZjzfZ+lOdYU3MK4HY8StF+fzQvUgZPU+gWqodbuPRwGwdIbrh04ORpbfRzZddiSqd8bwc0g4cC8pRsRUROxKCACBdzflhVe5UbGEhmejgq+KGHK4FnnAdYDOZQ69eAa/hTJoiAbLh6qoWEc8iCWf+Ic5xEC6aFAR8mXruwXX1IiF4UcinWKxN2W0XIigAXckYoQSNWYBTAVGboEpjoDIq2iU6yarOIfXTxc7bohrDTVqLoiW9XfsF3ZUhXRlOWfb0lDaA3UjalfPcihXvHgt23XKo4e3zoez8FebFnV9/SQ8Y4ZPsGizGmghXAcVWnilIYSzOAErSCJAT2bSRDYsz1i6XogrrVhVB4jxIXj/J4fhz2IZphUQ5JP204jz4FOggZW6VISekjjiOlKKyjdsZUJP94i1F3a182fZRmgUHWfb74iUJ4UBKZkYMYjHKBI2R4Vn9THnIYX6QYdp44N4snk/ZEanGmX0AUH8GgjUT/BkkJZoIg0oHxs2UKk0Z7UWVxlyQV5moVmUuqkH2KNiiBZF7mNnqOpoLQR3CwRl40Ulaa2HD99ZELqRtSU1FZZHMiCIPSiIdSdX4ixVoo04++xmfclDPIVxlCaYkHSJZ40V5lx3HVcXChQ37XdAPr+HLYw2b1lWs5qWdS2Zg8GV/sZk6Nx2snlZo4AZVY4WZgyEFXCJfWuESdGJEpOWKruHpGF2oN+YvN+ELIxJaZ2XC6OJcUF5dfSYFh2IWIZ3Yv6DXZFY5x6JbkGFKDh5Oegi3UV2RcKSb9BxWLJ2D74zMPiVUFJp5cxTy3B1cyuZuvKUWwx2kEFF3d5JTecoqF/+WZtbAK+6WfotmIIoJtzxSbCUZKyfleynhIIcQZmFMdbVmCQgUt5GVqN+aDMHRh+nagIYl+RTdA9ah5fPib7QZ2ujKci2kVnMmAszWfhlRyo2V/0fGMcwUz+NUMNJpchHl4PXk1QNhEKVoMELlhWLllEDl6URR0FJV6+HVh8hRFf5iCrgg9XKIy8tlvJlQKYZZEL+VxSiYW59KRifkKK0OgwdGZ8addEfdn6GZ5z6dY8kWm+lWaA/qjXmqLGiomVnVmHKJjEXaIVPeTkoYqJmp0wpEgV5AmaJl84bhyezhWoaQUWcqcU2ckspmF+wSneMpnYIOEfkEoP+gp6jSY0P+YVe9ook6aoZiacC06LkAFZohlct65TExohkF4boMqcD5onIdqQenYBkkHqGVZi2yjArqHjN3io/Tobu0DdQ6XTe/GQpK6VjAGk2Xonda5oi66bJBnhxEBEPVDgKzFefykd0rXKlY5UWRCMSmmnZIZhLO5q7Z5p58jrKikBrnoamvJbP9pcoKzGez4qy+6H2yieD42YcK3GjNnQsmqkrDofDpXsEYpLNLTqJsqC0nmCDK6bvM0SH73lJU3g845k0f6VAF6kme5L/WAjRR4MouIUzj6plkyiQsFmRJrcWGZoyIrou9KT1qHaRN7h8GnhjeXWf7povm6n+jVRwubqaH/RT09NGdfOVgXyVAM4w4dS5VNNLOd5oXOiRTRk2lzekDUkWJ8+THfl32+J12+Jz62RokX5LDd2ppS26Z7CiPn45CuJ35Hy4xalnhpaaApaidHRl7kSWXbKpWpmjsklAQR6XxreorAp4H5+amd+aF/148sNavpurNRs40YelHENrIL+rgd2lOu9Zj0mrgBabNSqLrO6pXAhqU2Bkn/hYtsmXGpFa1Oi1yyq40oyLREprcot0Q6SAOiMlktI4R4+Ya5G26NU7Uk1284+6s8NbwVVHyJSzC8y4TAU0I2uUP71LV8i61QmnR1yKPgqUKfhatytJ746iylmWz2GUlEhZdw/9YjRAusnAuBxbsCj1pQECaug1B3caKxKqYs2aJTYokK4mu41Mut3SklNBZDaou015qmGDVgAWcRT6Nx37ilSoq7bymgyCmvGOJS4AWTOZB/OzqRZgOxL+hcTlRnuHmTY7u2iQqC6VRIAZuT+ymQ62KFlMulSmiZY5pbvmMKLTZ7Bhuq6hnDscuusRB4YaoYgElabdte7dhkxlV89Tm+K/wQ0FWDnmSvJfuPhIuG1kGRj8KhqVbBgxu+rCeRUqdyvZiXe6usqLQtv0YgTiEwuPKRzNtRmjkh/IlXskecTzpNVSN4VbzGNMmBzdoto8pBZHGOAqJ2KmSq1TuhJsyqq//KW3BMAmxLDnx3XBiXQX8pC51ikrMHPm67tF7Gx7V7RbZoUPwBQa6rJOUoy1GIsYDYkwqZjiw8xOXrvFnmt25ykgs1yPVox7K3kzH5xtDCfYMFqJ5sLXSxiINzOw5EMAtbr87LiO65yE6iI6OpzKdSjFRahmxkVqycyITVpU55MQlapy5Vu8CzyzkJq6fcnArbUvLzn+jKYcQofjdRuK3YSH+8u9pcntkYqaTEVD/bRVJWRtF2Qmkywillww35yZZDg2pC0ZUY0K0LZLWsYC+JyPi8x5S5v8vMwLBsYjSJscxqerGF0aX1lJw8UfNsvQ8NZZYay5MnvDZ8piEcgJP/yrdAqcevbKF1G9Rd6aNT6akYWavZoMXiuYtXy9ESAn8RLNUs+cjyzKA5BYxAtmtnKTpefbJbGNZirV1BlTixU9ABdZUXyAwL2J5yiib8PDGmiZ3ji5SzVn3+sXLLCh1M2tEtxat/DdhnJckx69dK46cwmiy269QbXKMg7RkWNUU9jMPWZ8Cee85ccq26GtfwBmd9JieS29RDAZfQGbeqnX6E1tpGFWAzbSWNTNWGWtte+9ZeF8qS2MDA6810BdPA/c+hbQ5LKCkz1tM2fUp0utzMgj/t/Hs5V7R7sc0ECcLWzdssizUy9zncPIU3pnVwHd7Kir1C6sz3+tg5KJLC/yzf7F3PXTbWrBdMvQqIsk0dXGff973S5ryvtLGcqDy9x/drzT3gdZpKQurTEDde/V0DmVu2Ae7g3AcWz31ve2Lf/5rEAq7h5g3UjJdpFa7DaplSrUzi3jhDkAWwu73QBOWMtO3i08WrGzbKCs5hQbXPOJ7K9JfD3u1vTauGZB3k/tq4yoTUvB1dCF19nR3kiDqVUYzGxancSp6jJRoZUvx+S7nlBJtliKjPP73eYg6vOGjNWgh1SD7laQ52gn3cAnjScV4gQuQW3o2sXDvid/6EDk3jZNw4S/rnLFStLc3Abn7jhi6wBvrkEBRyWt7oZQ7E+qM0Is3olA4xNEbnE8s9iBe66Z17y8I4JfD1J3Au6tedLsfArjet6aouCiZLcU9ip34e6wGK6BNxJecG67jefIcyStjBsnH562KresIOa1Ob5MYO7FYbp3W2MVHd7OsgnVkHkaaX6tSeeTQ534ytO5R169te5vmNmXIgiog57jkiW7iUEmf+2+q+7hB6zWAe5vEupZVl1wGU2vfOv+65ylZU3f3+RAonmPw+8CdCo52E5ggvpTDoXg2/GEkL3hGfvlZW8WPT4hjvw+K+8R7/8SAf8iI/8nGRAAA7);\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/insert-css/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  runApp();\n});\n\n/**\n * Listens for the app restarting then re-creates the window.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n */\nchrome.app.runtime.onRestarted.addListener(function() {\n  runApp();\n});\n\n/**\n * Creates the window for the application.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nfunction runApp() {\n  chrome.app.window.create(\n    'browser.html',\n    {'id': 'initialBrowserWindowID', 'state': 'maximized'});\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/insert-css/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Insert CSS API Sample\",\n  \"minimum_chrome_version\": \"24.0.1307.0\",\n  \"version\": \"2.0\",\n  \"icons\": {\n    \"16\": \"icon_16.png\",\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"config.js\", \"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"webview\",\n    \"storage\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/local-resources/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/nfeplfjagjlljomimjealpedhjgamkle\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Package-Local Resources\n\nThis sample shows good and bad examples of mixing a `<webview>` tag that\nembeds trusted content packaged within an app with a tag that embeds\nuntrusted web content that may crash. In the bad example, trusted and\nuntrusted content share the same\n[partition](https://developer.chrome.com/apps/tags/webview#partition);\nsimulating a crash in the untrusted `webview` will also crash the trusted\n`webview`. The good example separates the two into different partitions;\nsimulating a crash in the untrusted `webview` does not affect the trusted\n`webview`.\n\nFinally, the `manifest.json` file contains an example of granting permissions\nto particular `webview` partitions to access trusted package-local content.\n\n## Resources\n\n* [Webview](http://developer.chrome.com/apps/app_external#webview)\n* [Permissions](http://developer.chrome.com/apps/manifest#permissions)\n* [Partitions](https://developer.chrome.com/apps/tags/webview#partition)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/webview-samples/local-resources/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/local-resources/app.css",
    "content": "webview,\n.flex-item {\n  flex-grow: 1;\n  flex-shrink: 1;\n}\n\n.trim {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n.padded {\n  padding: 10px;\n}\n\n.full {\n  width: 100%;\n  height: 100%;\n}\n\n.flex-container {\n  display: flex;\n}\n\n.row {\n  flex-direction: row;\n}\n\n.column {\n  flex-direction: column;\n}\n\n.left {\n  text-align: left;\n}\n\n.right {\n  text-align: right;\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/local-resources/bad_app.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Bad application</title>\n    <link rel=\"stylesheet\" href=\"app.css\">\n    <script type=\"text/javascript\" src=\"crash.js\"></script>\n  </head>\n  <body class=\"trim\">\n\n    <div class=\"padded flex-container row\">\n      <div class=\"flex-item left\">\n        <button id=\"simulate-crash\">Simulate foreign web content crash</a>\n      </div>\n      <div class=\"flex-item right\">\n        <button id=\"reload\">Reload foreign web content</a>\n      </div>\n    </div>\n\n    <div class=\"flex-container row\">\n\n\t<webview id=\"trusted\" class=\"full trim\" partition=\"bad\"\n\t\t src=\"trusted.html\"></webview>\n\n\t<!-- Bad application! Putting untrusted content in the same partition\n\t  -- as trusted content! -->\n\t<webview id=\"untrusted\" class=\"full trim\" partition=\"bad\"\n\t\t src=\"http://en.wikipedia.org/wiki/Cross-site_scripting\"></webview>\n\n    </div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/local-resources/crash.js",
    "content": "window.addEventListener('load', function(e) {\n  var crashButton = document.querySelector('#simulate-crash');\n  var reloadButton = document.querySelector('#reload');\n  var webview = document.querySelector('#untrusted');\n  crashButton.addEventListener('click', function(e) {\n    webview.terminate();\n  });\n  reloadButton.addEventListener('click', function(e) {\n    webview.reload();\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/local-resources/good_app.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Good application</title>\n    <link rel=\"stylesheet\" href=\"app.css\">\n    <script type=\"text/javascript\" src=\"crash.js\"></script>\n  </head>\n  <body class=\"trim\">\n\n    <div class=\"padded flex-container row\">\n      <div class=\"flex-item left\">\n        <button id=\"simulate-crash\">Simulate foreign web content crash</a>\n      </div>\n      <div class=\"flex-item right\">\n        <button id=\"reload\">Reload foreign web content</a>\n      </div>\n    </div>\n\n    <div class=\"flex-container row\">\n\n\t<webview id=\"trusted\" class=\"full trim\" partition=\"good_trusted\"\n\t\t src=\"trusted.html\"></webview>\n\n\t<!-- Good application! Putting untrusted content in a partition with\n\t  -- no local resource access -->\n\t<webview id=\"untrusted\" class=\"full trim\" partition=\"good_untrusted\"\n\t\t src=\"http://en.wikipedia.org/wiki/Cross-site_scripting\"></webview>\n\n    </div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/local-resources/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  runApp();\n});\n\n/**\n * Listens for the app restarting then re-creates the window.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n */\nchrome.app.runtime.onRestarted.addListener(function() {\n  runApp();\n});\n\n/**\n * Creates the window for the application.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nfunction runApp() {\n  chrome.app.window.create(\n    'good_app.html',\n    {'id': 'GoodWindowID'});\n  chrome.app.window.create(\n    'bad_app.html',\n    {'id': 'BadWindowID'});\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/local-resources/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Local Resources Sample\",\n  \"minimum_chrome_version\": \"24.0.1307.0\",\n  \"version\": \"2.0\",\n  \"icons\": {\n    \"16\": \"icon_16.png\",\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"webview\"\n  ],\n  \"webview\": {\n    \"partitions\": [\n      {\n        \"name\": \"bad\",\n        \"accessible_resources\": [\"trusted.html\"]\n      },\n      {\n        \"name\": \"good_trusted\",\n        \"accessible_resources\": [\"trusted.html\"]\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/local-resources/trusted.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head></head>\n  <body>\n    <h1>Your Trusted Package Content</h1>\n\n    <p>\n      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris quis\n      arcu malesuada, ultricies nulla id, interdum metus. Suspendisse ut\n      congue quam. Fusce laoreet est at purus venenatis, nec porttitor neque\n      suscipit. Integer ac orci lacus. Maecenas tempor aliquam orci, non\n      tempus diam vulputate quis. Nullam in mauris cursus, dignissim nisl\n      quis, porttitor neque. Aenean tellus enim, elementum in adipiscing ac,\n      tempor lacinia turpis.\n    </p>\n\n    <p>\n      Mauris ac leo sit amet justo molestie lobortis. Cras in velit sit amet\n      dolor congue euismod. In venenatis velit tellus, nec vehicula urna\n      aliquam vel. Interdum et malesuada fames ac ante ipsum primis in\n      faucibus. Mauris ut lacus vel quam feugiat scelerisque id quis\n      erat. Aenean neque nibh, molestie sed tempus eget, eleifend ac\n      sem. Nullam ultricies ornare velit eu imperdiet. Curabitur aliquet\n      vestibulum orci, sed fermentum mauris sagittis eget. Suspendisse\n      viverra est felis, et posuere orci interdum ut. Duis velit dui,\n      malesuada id malesuada sit amet, dignissim vitae ipsum. Curabitur in\n      sem in ante tempor consequat. Nunc hendrerit turpis interdum, consequat\n      quam sit amet, convallis urna. Morbi vehicula massa mi, lobortis\n      malesuada odio aliquam at.\n    </p>\n\n    <p>\n      Maecenas tempus odio luctus sollicitudin fermentum. Maecenas eget\n      dapibus nisi, vitae fringilla metus. Morbi aliquam dui quis iaculis\n      convallis. Nulla bibendum ornare fermentum. Integer sodales ante nisi,\n      non rhoncus arcu sagittis id. Phasellus lobortis elit vel dui luctus\n      pretium. Mauris mattis, elit id sollicitudin fermentum, lectus sapien\n      laoreet orci, sit amet euismod tortor lectus pharetra ipsum. Sed in\n      nunc dignissim, tristique mi ut, porttitor nisl. Nulla molestie\n      lobortis sapien at semper.\n    </p>\n\n    <p>\n      Aenean lobortis, est id faucibus bibendum, lacus tortor dapibus augue,\n      in aliquam eros mauris eget mauris. Nulla magna arcu, venenatis in\n      libero ac, fringilla ornare neque. Nulla eleifend mauris id tortor\n      pharetra, tempor auctor ipsum scelerisque. Nullam in tellus sit amet\n      enim venenatis egestas non non magna. Sed suscipit quis massa mattis\n      varius. Vivamus sit amet consectetur nisi. Quisque non dictum\n      urna. Vestibulum at tellus dignissim, elementum mi sed, rhoncus\n      ligula. Nunc rhoncus libero et magna sagittis auctor. Vestibulum mauris\n      eros, faucibus id vehicula ultricies, aliquam quis massa. Nunc lectus\n      ipsum, facilisis a consectetur a, placerat at mi. Mauris et arcu\n      est. Duis non massa mattis, venenatis enim id, semper diam. Sed\n      pulvinar nibh non risus pellentesque consequat. Praesent commodo risus\n      ante, at lobortis massa fermentum nec.\n    </p>\n\n    <p>\n      Mauris congue ipsum eu posuere dignissim. Aliquam blandit arcu sit amet\n      commodo ultricies. Praesent volutpat scelerisque orci, non gravida\n      eros. Donec eget nisi convallis, vestibulum ante eu, rutrum nulla. Nam\n      fringilla magna nibh, ac aliquet tellus rutrum vitae. Curabitur et\n      tempor diam. Proin tortor eros, adipiscing non sagittis vitae, pulvinar\n      semper felis. Cras sed lacus non nulla tristique congue. Praesent\n      pellentesque est erat, eget pulvinar sem aliquam molestie. Maecenas\n      quis tortor ipsum. Integer id nisl nec risus sodales pulvinar. In quis\n      odio eget nulla posuere pretium. In lobortis tristique erat nec\n      auctor. Curabitur id quam viverra, pellentesque lorem ut, scelerisque\n      neque. Vestibulum vel eleifend dolor, ac sagittis nisi.\n    </p>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/nfcmophndjlljioblddmepjbcfnocnak\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Multi-Tab Browser\n\nSample that shows one way to combine the [New Window\nAPI](https://developer.chrome.com/apps/tags/webview#event-newwindow) with the\n[User Agent\nAPI](https://developer.chrome.com/apps/tags/webview#method-setUserAgentOverride)\nfor\n[webviews](http://developer.chrome.com/apps/app_external#webview). The\napp combines the\n[New Window User Agent Sample](https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webview-samples/new-window)\nand the [Browser Sample](https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/webview-samples/browser).\n\n## Features\n\n* All features from the [New Window User Agent Sample](https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/webview-samples/new-window-user-agent)\n* All features from the\n  [Browser Sample](https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/webview-samples/browser) except for [clearData API](https://developer.chrome.com/apps/tags/webview#method-clearData) and simulate crash.\n* Added a new permissions feature based on [webview permissionrequest event](https://developer.chrome.com/apps/tags/webview#event-permissionrequest)\n\n## Limitations\n\n* See [New Window\nSample](https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/webview-samples/new-window)\n\n## Resources\n\n* [Webview New Window API](https://developer.chrome.com/apps/tags/webview#event-newwindow)\n* [User Agent API](https://developer.chrome.com/apps/tags/webview#method-setUserAgentOverride)\n* [Webview](http://developer.chrome.com/apps/app_external#webview)\n* [Permissions](http://developer.chrome.com/apps/manifest#permissions)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/webview-samples/multi-tab-browser/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/browser.css",
    "content": "body {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n  font-family: Lucida Grande, Arial, sans-serif;\n}\n\nbutton,\ninput {\n  outline: none;\n}\n\ndiv {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n#content-container {\n  display: inline-block;\n  position: relative;\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n#controls {\n  padding: 0px;\n  background-color: #eee;\n  border-bottom: solid 1px #ccc;\n}\n\n#controls button,\n#controls input {\n  font-size: 14px;\n  line-height: 24px;\n  border-radius: 2px;\n  padding: 0 6px;\n}\n\n#controls button#reload {\n  border-radius: 16px;\n}\n\n#tab-controls {\n  padding: 3px 3px 0px 3px;\n  background: #888;\n}\n\n#browser-controls {\n  padding: 3px;\n}\n\n#controls #zoom,\n#controls #find {\n  font-size: 18px;\n}\n\nbutton,\ninput[type=\"submit\"],\nbutton[disabled]:hover {\n  border: solid 1px transparent;\n  background: transparent;\n}\n\nbutton:hover,\ninput[type=\"submit\"]:hover {\n  border-color: #ccc;\n  background: -webkit-linear-gradient(bottom, #cccccc 0%, #f2f2f2 99%);\n}\n\nbutton:active,\ninput[type=\"submit\"]:active {\n  border-color: #bbb;\n  background: -webkit-linear-gradient(bottom, #e2e2e2 0%, #bbbbbb 99%);\n}\n\n/* These glyphs are on the small side, make them look more natural when\ncompared to the back/forward buttons */\n#controls #home {\n  font-size: 24px;\n}\n\n#controls #reload {\n  font-size: 20px;\n}\n\n#location {\n  border: solid 1px #ccc;\n  padding: 2px;\n  width: 100%;\n  -webkit-box-sizing: border-box;\n}\n\n#browser-controls {\n  display: -webkit-flex;\n  -webit-flex-direction: column;\n}\n\n#browser-controls #location-form {\n  -webkit-flex: 1;\n  display: -webkit-flex;\n  -webit-flex-direction: column;\n}\n\n#browser-controls #center-column {\n  -webkit-flex: 1;\n}\n\nwebview,\n.webview-container {\n  display: inline-block;\n  padding: 0px;\n  margin: 0px;\n  border: 0px;\n  position: absolute;\n  top: 0px;\n  left: 0px;\n  visibility: hidden;\n}\n\n.selected,\n#content-container .selected {\n  visibility: visible;\n}\n\n.webview-container ul {\n  position: relative;\n  text-align: right;\n  padding: 0px;\n  margin: 0px;\n  z-index: 2;\n  list-style-type: none;\n}\n\n.webview-container ul li {\n  padding: 3px;\n  background: #ff7;\n  border-bottom: solid 1px #aa6;\n}\n\nwebview {\n  z-index: 1;\n}\n\n.popup-allow {\n  color: #0a0;\n  font-weight: bold;\n  text-decoration: none;\n}\n\n.popup-allow:hover {\n  color: #0f0;\n  font-weight: bold;\n  text-decoration: none;\n}\n\n.popup-deny {\n  color: #a00;\n  font-weight: bold;\n  text-decoration: none;\n}\n\n.popup-deny:hover {\n  color: #f00;\n  font-weight: bold;\n  text-decoration: none;\n}\n\n/* The reload button turns into a spinning trobber */\n.loading #reload {\n  -webkit-animation: spinner-animation .5s infinite linear;\n  -webkit-transform-origin: 50% 55.5%;\n}\n\n@-webkit-keyframes spinner-animation {\n  0% { -webkit-transform: rotate(0deg); }\n  100% {-webkit-transform: rotate(360deg); }\n}\n\n#tab-container {\n  margin: 5px 5px 0px 5px;\n  padding: 0px;\n  display: inline-block;\n}\n\n#tab-container li {\n  display: inline-block;\n  position: relative;\n  vertical-align: bottom;\n  width: 100px;\n  margin: 0px;\n  padding: 6px 16px 6px 6px;\n  border: 0px;\n  background: #ccc;\n}\n\n#tab-container li:hover {\n  background: #ddd;\n}\n\n#tab-container li.selected {\n  background: #eee;\n}\n\n#tab-container li p {\n  width: 100px;\n  float:left;\n  z-index: 1;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  margin: 0px;\n  padding: 0px;\n  -webkit-margin-before: 0px;\n  -webkit-margin-after: 0px;\n}\n\n#tab-container li a {\n  position: absolute;\n  right: 2px;\n  z-index: 2;\n  padding-left: 1px;\n  padding-right: 1px;\n  color: #666;\n  font-weight: bold;\n  text-decoration: none;\n  cursor: default;\n}\n\n#tab-container li a:hover {\n  color: #000;\n}\n\n#tab-container li#new-tab {\n  background: transparent;\n  vertical-align: baseline;\n  display: inline;\n}\n\n#tab-container li#new-tab a {\n  font-size: 24px;\n  padding: 0px;\n}\n\n/* Classes for general lightbox overlay */\n\n.trim {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n.full {\n  width: 100%;\n  height: 100%;\n}\n\n.padded {\n  padding: 10px;\n}\n\n.flex-container {\n  display: flex;\n}\n\n.row {\n  flex-direction: row;\n}\n\n.column {\n  flex-direction: column;\n}\n\n.center {\n  align-items: center;\n}\n\n.center-text {\n  text-align: center;\n}\n\n.flex {\n  flex-grow: 1;\n  flex-shrink: 1;\n}\n\n.flex-wide {\n  flex-grow: 4;\n  flex-shrink: 1;\n}\n\n.flex-narrow {\n  flex-grow: 1;\n  flex-shrink: 4;\n  width: 300px;\n}\n\n.rel {\n  position: relative;\n}\n\n.abs {\n  position: absolute;\n}\n\n.abs-full {\n  position: absolute;\n  top: 0px;\n  right: 0px;\n  bottom: 0px;\n  left: 0px;\n}\n\n.lightbox-overlay {\n  opacity: 0.5;\n  background: #000;\n}\n\n.lightbox {\n  padding: 20px;\n  margin: 20px;\n  background: #fff;\n  border-radius: 5px;\n}\n\n.hide {\n  visibility: hidden;\n}\n\n#zoom-box,\n#find-box {\n  background-color: #eee;\n  border: solid 1px #ccc;\n  border-top: solid 1px #eee;\n  border-bottom-left-radius: 2px;\n  border-bottom-right-radius: 2px;\n  padding: 2px;\n\n  position: fixed;\n  margin-top: -1px;\n  height: 25px;\n\n  display: none;\n}\n\n#zoom-box #zoom-form,\n#find-box #find-form {\n  -webkit-flex: 1;\n  display: -webkit-flex;\n  -webit-flex-direction: row;\n}\n\n#zoom-box input,\n#zoom-box button,\n#find-box button {\n  border-radius: 2px;\n}\n\n#zoom-box #zoom-text,\n#find-box #find-text {\n  border: solid 1px #ccc;\n  margin-right: 0px;\n  padding: 2px;\n  -webkit-box-sizing: border-box;\n  -webkit-flex: 1;\n}\n\n#zoom-box {\n  left: 5px;\n  width: 125px;\n  z-index: 2;\n}\n\n#zoom-box input[type=\"submit\"] {\n  font-size: 14px;\n  margin: 2px 0px;\n  padding: 0 2px 3px 2px;\n  width: 22px;\n}\n\n\n#zoom-box button {\n  font-size: 12px;\n  margin: 2px 0px;\n  padding: 0px 1px 0px 0px;\n  width: 20px;\n}\n\n#find-box {\n  right: 5px;\n  width: 280px;\n  z-index: 2;\n}\n\n#find-box #find-text {\n  border-right-style: none;\n  border-top-left-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n\n#find-results {\n  margin: 0px 0px;\n}\n#find-box #find-results {\n  color: #888;\n  background-color: #eee;\n  border: solid 1px #ccc;\n  border-top: solid 1px #eee;\n  border-left-style: none;\n  border-top-right-radius: 2px;\n  border-bottom-right-radius: 2px;\n  padding: 3px 4px 2px 0;\n  text-align: center;\n}\n\n#find-box #match-case {\n  margin: 2px 0px;\n  font-size: 10px;\n  width: 28px;\n}\n\n#find-box #find-backward,\n#find-box #find-forward {\n  font-size: 14px;\n  width: 24px;\n}\n\n.overlay-gray {\n  background-color: rgba(0, 0, 0, 0.8);\n  z-index: 999;\n  position: absolute;\n  left: 0;\n  top: 0;\n  width: 100%;\n  height: 100%;\n  display: none;\n}\n\n.overlay-bar {\n  background: rgb(221, 221, 221);\n  z-index: 999;\n  position: relative;\n  width: 100%;\n  height: 25px;\n  border: solid;\n  display: none;\n  -webkit-box-sizing: border-box;\n  -webkit-flex: 1;\n}\n\n#exit-box {\n  color: rgb(193, 193, 193);\n  display: none;\n  position: absolute;\n  z-index: 1000;\n}\n\n.req-exit-button {\n  color: rgb(193, 193, 193);\n  background: rgb(90, 90, 90);\n  width: 40px;\n  text-align: center;\n}\n\n.req-exit-button:focus {\n  border: 1px solid #fff;\n}\n\n#permission-box {\n  background-color: #eee;\n  border: solid 1px #ccc;\n  border-top: solid 1px #eee;\n  border-bottom-left-radius: 2px;\n  border-bottom-right-radius: 2px;\n  padding: 2px;\n\n  position: fixed;\n  margin-top: -1px;\n\n  display: none;\n  max-height: 50px;\n}\n\n#question {\n  vertical-align: middle;\n}\n\n.req-permission-button {\n  float: right;\n  padding-right: 10px;\n  height: 23px;\n  border: solid 1px #ddd;\n  margin-bottom: 2px;\n}\n\n\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/browser.html",
    "content": "<!DOCTYPE html>\n<html class=\"trim full\">\n<head>\n  <link rel=\"stylesheet\" href=\"browser.css\">\n  <script src=\"config.js\"></script>\n  <script src=\"popup.js\"></script>\n  <script src=\"context_menu.js\"></script>\n  <script src=\"tabs.js\"></script>\n  <script src=\"find_box_controller.js\"></script>\n  <script src=\"zoom_box_controller.js\"></script>\n  <script src=\"exit_box_controller.js\"></script>\n  <script src=\"permission_box_controller.js\"></script>\n  <script src=\"browser.js\"></script>\n  <script src=\"browser_main.js\"></script>\n</head>\n<body class=\"trim full\">\n  <div id=\"controls\">\n\n    <div id=\"tab-controls\">\n      <ul id=\"tab-container\">\n        <li id=\"new-tab\"><a href=\"#new-tab\">+</a></li>\n      </ul>\n    </div>\n\n    <div id=\"browser-controls\">\n      <button id=\"back\" title=\"Go Back\">&#9664;</button>\n      <button id=\"forward\" title=\"Go Forward\">&#9654;</button>\n      <button id=\"home\" title=\"Go Home\">&#8962;</button>\n      <button id=\"reload\" title=\"Reload\">&#10227;</button>\n\n      <form id=\"location-form\">\n        <div id=\"center-column\">\n          <input id=\"location\" type=\"text\" value=\"\">\n        </div>\n        <input type=\"submit\" value=\"Go\">\n      </form>\n\n      <button id=\"zoom\" title=\"Change Zoom\">&#128270;</button>\n      <button id=\"find\" title=\"Find in Page\">&#128294;</button>\n    </div>\n  </div>\n\n  <div id=\"zoom-box\">\n    <form id=\"zoom-form\">\n      <input id=\"zoom-text\" type=\"text\">\n      <input type=\"submit\" value=\"&#128270;\">\n      <button id=\"zoom-in\">&#10133;</button>\n      <button id=\"zoom-out\">&#10134;</button>\n    </form>\n  </div>\n\n  <div id=\"find-box\">\n    <form id=\"find-form\">\n      <input id=\"find-text\" type=\"text\">\n      <div id=\"find-results\"></div>\n      <input type=\"submit\" style=\"position:absolute; visibility:hidden\">\n      <button id=\"match-case\">aA</button>\n      <button id=\"find-backward\">&#60;</button>\n      <button id=\"find-forward\">&#62;</button>\n    </form>\n  </div>\n  <div id=\"exit-box\">\n    <h2> Browser Exit? </h2>\n    <h3> Do you really want to exit browser? </h3>\n    <button id=\"exit-yes\" class=\"req-exit-button\" tabindex=\"2\"> Yes </button>\n    <button id=\"exit-no\" class=\"req-exit-button\" tabindex=\"4\"> No </button>\n  </div>\n\n  <div id=\"permission-box\">\n    <span id=\"question\"></span>\n    <button id=\"allow\" class=\"req-permission-button\"> Permit </button>\n    <button id=\"deny\" class=\"req-permission-button\"> Stop </button>\n  </div>\n\n  <div id=\"content-container\">\n  </div>\n\n  <div id=\"lightbox-overlay\" class=\"full trim abs abs-full lightbox-overlay hide\">\n  </div>\n\n  <div id=\"lightbox\" class=\"full trim abs abs-full flex-container column center hide\">\n    <div class=\"flex flex-container row center\">\n      <div class=\"flex flex-container column center lightbox\">\n        <h1 class=\"flex center-text\">Chrome Feature Not Supported</h1>\n        <div class=\"flex center-text\">\n          The feature highlighted by this sample app is not supported in\n          your version of Chrome. Make sure your browser is up to date. If\n          you still see this message after updating your browser, try\n          installing\n          a <a href=\"http://www.chromium.org/getting-involved/dev-channel\"\n          target=\"_blank\">dev channel</a> build of Chrome.\n        </div>\n      </div>\n    </div>\n  </div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/browser.js",
    "content": "var browser = (function(configModule, tabsModule) {\n  var dce = function(str) { return document.createElement(str); };\n\n  var Browser = function(\n    controlsContainer,\n    back,\n    forward,\n    home,\n    reload,\n    find,\n    zoom,\n    locationForm,\n    locationBar,\n    tabContainer,\n    contentContainer,\n    findbox,\n    zoombox,\n    exitbox,\n    permissionbox,\n    newTabElement) {\n    this.controlsContainer = controlsContainer;\n    this.back = back;\n    this.forward = forward;\n    this.home = home;\n    this.reload = reload;\n    this.find = find;\n    this.zoom = zoom;\n    this.locationForm = locationForm;\n    this.locationBar = locationBar;\n    this.tabContainer = tabContainer;\n    this.contentContainer = contentContainer;\n    this.newTabElement = newTabElement;\n    this.findBoxController = new findTool.FindController(findbox, this);\n    this.zoomBoxController = new zoomTool.ZoomController(zoombox, this);\n    this.exitBoxController = new exitTool.ExitController(exitbox, this);\n    this.permissionBoxController = new permissionTool.PermissionController(\n      permissionbox, this);\n    this.tabs = new tabsModule.TabList(\n        'tabs',\n        this,\n        tabContainer,\n        contentContainer,\n        newTabElement);\n\n    this.init();\n  };\n\n  Browser.prototype.init = function() {\n    (function(browser) {\n      window.addEventListener('resize', function(e) {\n        browser.doLayout(e);\n      });\n\n      window.addEventListener('keydown', function(e) {\n        browser.doKeyDown(e);\n      });\n\n      browser.back.addEventListener('click', function(e) {\n        browser.tabs.getSelected().goBack();\n      });\n\n      browser.forward.addEventListener('click', function() {\n        browser.tabs.getSelected().goForward();\n      });\n\n      browser.home.addEventListener('click', function() {\n        browser.tabs.getSelected().navigateTo(configModule.homepage);\n      });\n\n      browser.reload.addEventListener('click', function() {\n        var tab = browser.tabs.getSelected();\n        if (tab.isLoading()) {\n          tab.stopNavigation();\n        } else {\n          tab.doReload();\n        }\n      });\n      browser.reload.addEventListener(\n        'webkitAnimationIteration',\n        function() {\n          // Between animation iterations: If loading is done, then stop spinning\n          if (!browser.tabs.getSelected().isLoading()) {\n            document.body.classList.remove('loading');\n          }\n        }\n      );\n      browser.find.addEventListener('click', function() {\n        browser.findBoxController.toggleVisibility();\n      });\n      browser.zoom.addEventListener('click', function() {\n        browser.zoomBoxController.toggleVisibility();\n      });\n\n      browser.locationForm.addEventListener('submit', function(e) {\n        e.preventDefault();\n        browser.closeAllMessagesAndDialoges();\n        browser.tabs.getSelected().navigateTo(browser.locationBar.value);\n      });\n\n      browser.newTabElement.addEventListener(\n        'click',\n        function(e) { return browser.doNewTab(e); });\n\n      browser.closeAllMessagesAndDialoges = function() {\n        this.findBoxController.deactivate();\n        this.zoomBoxController.deactivate();\n        this.permissionBoxController.deactivate();\n      };\n\n      window.addEventListener('message', function(e) {\n        if (e.data) {\n          var data = JSON.parse(e.data);;\n          var type = data.type;\n          if (type == 'titleResponse') {\n            if (data.tabName && data.title) {\n              browser.tabs.setLabelByName(data.tabName, data.title);\n            } else {\n              console.warn(\n                  'Warning: Expected message from guest to contain {tabName, title}, but got:',\n                  data);\n            }\n          } else {\n            console.warn('Warning: Unexpected message received', e);\n          }\n        } else {\n          console.warn('Warning: Empty message (no data) received', e);\n        }\n      });\n\n      var webview = dce('webview');\n      var tab = browser.tabs.append(webview);\n\n      // Globals window.userAgent and/or window.newWindowEvent may be injected\n      // by opener\n      if (window.userAgent) {\n        webview.setUserAgentOverride(window.userAgent);\n      }\n      if (window.newWindowEvent) {\n        window.newWindowEvent.window.attach(webview);\n      } else {\n        tab.navigateTo(configModule.homepage);\n      }\n      browser.tabs.selectTab(tab);\n    }(this));\n  };\n\n  Browser.prototype.doLayout = function(e) {\n    var controlsHeight = this.controlsContainer.offsetHeight;\n    var windowWidth = document.documentElement.clientWidth;\n    var windowHeight = document.documentElement.clientHeight;\n    var contentWidth = windowWidth;\n    var contentHeight = windowHeight - controlsHeight;\n\n    var tab = this.tabs.getSelected();\n    var webview = tab.getWebview();\n    var webviewContainer = tab.getWebviewContainer();\n\n    var layoutElements = [\n      this.contentContainer,\n      webviewContainer,\n      webview];\n    for (var i = 0; i < layoutElements.length; ++i) {\n      layoutElements[i].style.width = contentWidth + 'px';\n      layoutElements[i].style.height = contentHeight + 'px';\n    }\n  };\n\n  // New window that is NOT triggered by existing window\n  Browser.prototype.doNewTab = function(e) {\n    var tab = this.tabs.append(dce('webview'));\n    tab.navigateTo(configModule.homepage);\n    this.tabs.selectTab(tab);\n    return tab;\n  };\n\n  Browser.prototype.doKeyDown = function(e) {\n    if (e.keyCode === 27) {\n      this.closeAllMessagesAndDialoges();\n    }\n    if (e.ctrlKey) {\n      switch(e.keyCode) {\n        // Ctrl+T\n        case 84:\n        this.doNewTab();\n        break;\n        // Ctrl+W\n        case 87:\n        e.preventDefault();\n        this.tabs.removeTab(this.tabs.getSelected());\n        break;\n        case 122:\n        chrome.app.window.current().fullscreen();\n      }\n      // Ctrl + [1-9]\n      if (e.keyCode >= 49 && e.keyCode <= 57) {\n        var idx = e.keyCode - 49;\n        if (idx < this.tabs.getNumTabs()) {\n          this.tabs.selectIdx(idx);\n        }\n      }\n    }\n  };\n\n  Browser.prototype.doTabNavigating = function(tab, url) {\n    if (tab.selected) {\n      document.body.classList.add('loading');\n      this.locationBar.value = url;\n    }\n  };\n\n  Browser.prototype.doTabNavigated = function(tab, url) {\n    this.updateControls();\n  };\n\n  Browser.prototype.doTabSwitch = function(oldTab, newTab) {\n    this.updateControls();\n  };\n\n  Browser.prototype.updateControls = function() {\n    var selectedTab = this.tabs.getSelected();\n    if (selectedTab.isLoading()) {\n      document.body.classList.add('loading');\n    }\n    var selectedWebview = selectedTab.getWebview();\n    this.back.disabled = !selectedWebview.canGoBack();\n    this.forward.disabled = !selectedWebview.canGoForward();\n    if (this.locationBar.value != selectedTab.url) {\n      this.locationBar.value = selectedTab.url;\n    }\n  };\n\n  Browser.prototype.closeBrowser = function() {\n    this.exitBoxController.activate();\n  }\n\n  return {'Browser': Browser};\n})(config, tabs);\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/browser_main.js",
    "content": "var mainBrowser = null;\n(function(browserModule) {\n  var query = function(str) { return document.querySelector(str); };\n\n  window.addEventListener('load', function(e) {\n    var webview = document.createElement('webview');\n\n    // Check for context menu API\n    if (webview.contextMenus) {\n      mainBrowser = new browserModule.Browser(\n          query('#controls'),\n          query('#back'),\n          query('#forward'),\n          query('#home'),\n          query('#reload'),\n          query('#find'),\n          query('#zoom'),\n          query('#location-form'),\n          query('#location'),\n          query('#tab-container'),\n          query('#content-container'),\n          query('#find-box'),\n          query('#zoom-box'),\n          query('#exit-box'),\n          query('#permission-box'),\n          query('#new-tab'));\n    } else {\n      // When API not available, show lightbox\n      query('#lightbox-overlay').classList.remove('hide');\n      query('#lightbox').classList.remove('hide');\n    }\n  });\n})(browser);\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/config.js",
    "content": "// Global configuration variables\nvar config = {\n  'homepage': 'https://www.google.com',\n  'popupConfirmBox': {\n    'innerHTML': 'This webpage would like to open a window at <span class=\"popup-url\"></span> Would you like to allow this popup? <a href=\"#popup-allow\" class=\"popup-allow\">Allow</a> <a href=\"#popup-deny\" class=\"popup-deny\">Deny</a>',\n    'urlSpanClass': 'popup-url',\n    'acceptLinkClass': 'popup-allow',\n    'denyLinkClass': 'popup-deny'\n  },\n  'browsers': {\n    'android': 'Android',\n    'ios': 'iPhone',\n    'nokia': 'Nokia Mobile',\n    'bb-playbook': 'BlackBerry Playbook'\n  },\n  'browserUserAgents': {\n    'android': 'Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30',\n    'ios': 'Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3',\n    'nokia': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)',\n    'bb-playbook': 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML, like Gecko) Version/7.2.1.0 Safari/536.2+'\n  }\n};\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/context_menu.js",
    "content": "var contextMenu = (function(configModule) {\n  var ContextMenu = function(webview, popupConfirmBoxList) {\n    this.webview = webview;\n    this.popupConfirmBoxList = popupConfirmBoxList;\n    this.oneTimeUserAgentTable = {};\n\n    (function(menu) {\n      menu.webview.contextMenus.create({\n        'contexts': ['link'],\n        'id': 'newWindow',\n        'title': 'Open link in new window as...'\n      });\n      menu.webview.contextMenus.create({\n        'contexts': ['link'],\n        'id': 'newTab',\n        'title': 'Open link in new tab as...'\n      });\n\n      menu.webview.contextMenus.create({\n        'contexts': ['link'],\n        'id': 'newWindowDefault',\n        'title': 'Default browser',\n        'parentId': 'newWindow',\n        'onclick': function(e) { menu.doNewWindow(e); }\n      });\n      menu.webview.contextMenus.create({\n        'contexts': ['link'],\n        'type': 'separator',\n        'parentId': 'newWindow'\n      });\n      menu.webview.contextMenus.create({\n        'contexts': ['link'],\n        'id': 'newTabDefault',\n        'title': 'Default browser',\n        'parentId': 'newTab',\n        'onclick': function(e) { menu.doNewTab(e); }\n      });\n      menu.webview.contextMenus.create({\n        'contexts': ['link'],\n        'type': 'separator',\n        'parentId': 'newTab'\n      });\n      menu.webview.contextMenus.create({\n        'type': 'separator',\n        'parentId': 'newTab'\n      });\n\n      for (var key in configModule.browsers) {\n        (function(key, browserName) {\n          menu.webview.contextMenus.create({\n            'contexts': ['link'],\n            'id': 'newWindow_' + key,\n            'title': browserName,\n            'parentId': 'newWindow',\n            'onclick': function(e) { menu.doNewWindow(e, key); }\n          });\n          menu.webview.contextMenus.create({\n            'contexts': ['link'],\n            'id': 'newTab_' + key,\n            'title': browserName,\n            'parentId': 'newTab',\n            'onclick': function(e) { menu.doNewTab(e, key); }\n          });\n        }(key, configModule.browsers[key]));\n      }\n    }(this));\n  };\n\n  ContextMenu.prototype.doNewWindow = function(e, browser) {\n    var url = e.linkUrl;\n    this.loadOnce(url, browser);\n    this.doWindowOpen(url);\n  };\n\n  ContextMenu.prototype.doNewTab = function(e, browser) {\n    var url = e.linkUrl;\n    var code = 'window.simulateMiddleClickUrl = ';\n    console.log(code);\n    this.loadOnce(url, browser);\n    this.doTabOpen(url);\n  };\n\n  ContextMenu.prototype.doWindowOpen = function(url) {\n    var data = {\n      'type': 'simulatePopup',\n      'url': url\n    };\n    this.webview.contentWindow.postMessage(JSON.stringify(data), '*');\n  };\n\n  ContextMenu.prototype.doTabOpen = function(url) {\n    var data = {\n      'type': 'simulateCtrlClick',\n      'url': url\n    };\n    this.webview.contentWindow.postMessage(JSON.stringify(data), '*');\n  };\n\n  ContextMenu.prototype.getId = function() {\n    return 'id-' + (new Date()).getTime();\n  };\n\n  ContextMenu.prototype.getWindowFeatures = function() {\n    return 'width=100,height=100,left=100,top=100';\n  };\n\n  ContextMenu.prototype.loadOnce = function(url, browser) {\n    var userAgent = configModule.browserUserAgents[browser];\n    // Unconditionally store URL in table so that existence in table is an\n    // indicator that we are loading this URL\n    this.oneTimeUserAgentTable[url] = userAgent;\n  };\n\n  ContextMenu.prototype.doOpen = function(url, webview) {\n    var userAgent = this.oneTimeUserAgentTable[url];\n    if (webview && userAgent) {\n      webview.setUserAgentOverride(this.oneTimeUserAgentTable[url]);\n    }\n    delete this.oneTimeUserAgentTable[url];\n  };\n\n  ContextMenu.prototype.getUserAgentOverride = function(url) {\n    return this.oneTimeUserAgentTable[url];\n  };\n\n  ContextMenu.prototype.isOpening = function(url) {\n    // Existence in oneTimeUserAgentTable is an indicator for opening a URL\n    return (url in this.oneTimeUserAgentTable);\n  };\n\n  return {'ContextMenu': ContextMenu};\n}(config));\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/exit_box_controller.js",
    "content": "var exitTool = (function() {\n  var containerElement = null;\n  var browserInstance = null;\n  var controller = null;\n  var yes = null; no = null;\n  function query(id) { return containerElement.querySelector(id);}\n  var ExitController = function(container, browser) {\n    containerElement = container;\n    browserInstance = browser;\n    controller = this;\n    yes = query('#exit-yes');\n    no = query('#exit-no');\n    var curr_focus = 'no';\n    yes.onclick = function() {\n      window.close();\n    };\n    no.onclick = deactivate;\n    this.overlay = document.createElement('div');\n    this.overlay.className = 'overlay-gray';\n    document.body.appendChild(this.overlay);\n    containerElement.onkeydown = function(e) {\n      if (containerElement.style.display === 'none') {\n        return;\n      }\n      e.preventDefault();\n      if (e.keyCode === 9) {\n        if (curr_focus === 'no') {\n          curr_focus = 'yes';\n          yes.focus();\n        } else {\n          curr_focus = 'no';\n          no.focus();\n        }\n      } else if (e.keyCode === 13) {\n        if (curr_focus === 'yes') {\n          window.close();\n        } else {\n          deactivate();\n        }\n      }\n    };\n  };\n\n  ExitController.prototype.activate = function() {\n    containerElement.style.display = 'block';\n    this.overlay.style.display = 'block';\n    curr_focus = 'no';\n    no.focus();\n  };\n\n  function deactivate() {\n    containerElement.style.display = 'none';\n    controller.overlay.style.display = 'none';\n    yes.tabIndex = -1;\n    no.tabIndex = -1;\n  }\n\n  return {'ExitController': ExitController};\n\n})();\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/find_box_controller.js",
    "content": "var findTool = (function() {\n  var VISIBLE_STYLE = 'block';\n  var HIDDEN_STYLE = 'none';\n  var containerElement = null, browserInstance = null, controller = null;\n  var form = null, findText = null, matchCase = null, findBackward = null,\n  findForward = null, findResult = null;\n  var findMatchCase = false;\n  function query(id) {\n    return containerElement.querySelector(id);\n  }\n\n  var FindController = function(container, browser) {\n    containerElement = container;\n    browserInstance = browser;\n    form = query('#find-form');\n    findText = query('#find-text');\n    findResults = query('#find-results');\n    findBackward = query(\"#find-backward\");\n    findForward = query(\"#find-forward\");\n    matchCase = query(\"#match-case\");\n    controller = this;\n    initHandlers();\n  }\n\n  FindController.prototype.deactivate = function() {\n    if (isVisible) {\n      hideBox();\n    }\n  };\n\n  function isVisible() {\n    return containerElement.style.display ==  VISIBLE_STYLE;\n  }\n\n  function hideBox() {\n    containerElement.style.display = HIDDEN_STYLE;\n  }\n\n  function showBox() {\n    setWebviewFindUpdateHandler();\n    containerElement.style.display = VISIBLE_STYLE;\n    findText.select();\n  }\n\n  FindController.prototype.toggleVisibility = function() {\n    if (isVisible()) {\n      hideBox();\n    } else {\n      showBox();\n    }\n  };\n\n  function findTextOnInput(e) {\n    browserInstance.tabs.getSelected().webview.find(\n      findText.value, {matchCase: findMatchCase});\n  }\n\n  function findTextOnKeyDown(e) {\n    if (e.ctrlKey && e.keyCode == 13) {\n      e.preventDefault();\n      browserInstance.tabs.getSelected().webview.stopFinding('activate');\n      hideBox();\n    }\n  }\n  function matchCaseOnClick(e) {\n    e.preventDefault();\n    findMatchCase = !findMatchCase;\n    if (findMatchCase) {\n      matchCase.style.color = 'blue';\n      matchCase.style['font-weight'] = 'bold';\n    } else {\n      matchCase.style.color = 'black';\n      matchCase.style['font-weight'] = \"\";\n    }\n    browserInstance.tabs.getSelected().webview.find(\n      findText.value, {matchCase: findMatchCase});\n  }\n\n  function formOnSubmit(e) {\n    e.preventDefault();\n    browserInstance.tabs.getSelected().webview.find(\n      findText.value, {matchCase: findMatchCase});\n  }\n\n  function findBackwardOnClick(e) {\n    e.preventDefault();\n    browserInstance.tabs.getSelected().webview.find(\n      findText.value, {backward: true, matchCase: findMatchCase});\n  }\n\n  function handleFindUpdate(e) {\n    if (e.searchText == \"\") {\n      findResults.innerText = \"\";\n    } else {\n      findResults.innerText =\n      event.activeMatchOrdinal + \" of \" + event.numberOfMatches;\n    }\n    // Ensure that the find box does not obscure the active match\n    if (e.finalUpdate && !e.canceled) {\n      containerElement.style.left = '';\n      containerElement.style.opacity = '';\n      var rect = containerElement.getBoundingClientRect();\n      if (containerElementObscuresActiveMatch(rect, e.selectionRect)) {\n        var potentialLeft = e.selectionRect.left - rect.width - 10;\n        if (potentialLeft >= 5) {\n          containerElement.style.left = potentialLeft + 'px';\n        }  else {\n          containerElement.style.opacity = \"0.5\";\n        }\n      }\n    }\n  }\n\n  function containerElementObscuresActiveMatch(findBoxRect, matchRect) {\n    return findBoxRect.left < matchRect.left + matchRect.width &&\n    findBoxRect.right > matchRect.left &&\n    findBoxRect.top < matchRect.top + matchRect.height &&\n    findBoxRect.bottom > matchRect.top;\n\n  }\n\n  function handleKeyDown(e) {\n    // Check for Ctrl + F\n    if (e.ctrlKey && e.keyCode == 70) {\n      showBox();\n    }\n  }\n\n  function initHandlers() {\n    findText.addEventListener('input', findTextOnInput);\n    findText.addEventListener('keydown', findTextOnKeyDown);\n    matchCase.addEventListener('click', matchCaseOnClick);\n    form.addEventListener('submit', formOnSubmit);\n    window.addEventListener('keydown', handleKeyDown);\n  }\n\n  function setWebviewFindUpdateHandler() {\n    if (browserInstance && browserInstance.tabs) {\n      for (var index = 0; index < browserInstance.tabs.getNumTabs(); ++index) {\n        var wv = browserInstance.tabs.selectIdx(index).webview;\n        wv.onfindupdate = handleFindUpdate;\n        wv.stopFinding();\n      }\n    }\n  }\n  return {'FindController': FindController};\n})();\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/guest_messaging.js",
    "content": "var webviewTitleInjectionComplete = false;\n(function() {\n  // Prevent multiple injection\n  if (!webviewTitleInjectionComplete) {\n    var embedder = null;\n    var tabName = null;\n    var listenersAreBound = false;\n    var title = null;\n    var postTitle = (function() {\n      return function(e) {\n        title = document.title;\n        var data = {\n          'type': 'titleResponse',\n          'tabName': tabName,\n          'title': title || '[no title]'\n        };\n        embedder.postMessage(JSON.stringify(data), '*');\n      };\n    }());\n    var bindEmbedder = function(e) {\n      embedder = e.source;\n    };\n    var bindTabName = function(data) {\n      if (data.tabName) {\n        tabName = data.tabName;\n      } else {\n        console.warn('Warning: Title message from embedder contains no tab name');\n      }\n    };\n    var simulateCtrlClick = function(url) {\n      var a = document.createElement('a');\n      a.href = url;\n      var e = document.createEvent('MouseEvents');\n      e.initMouseEvent(\n          'click', // type\n          true,    // canBuble\n          true,    // cancelable\n          window,  // view\n          0,       // detail\n          0,       // screenX\n          0,       // screenY\n          0,       // clientX\n          0,       // clientY\n          true,    // ctrlKey <-- Important: simulate ctrl-click\n          false,   // altKey\n          false,   // shiftKey\n          false,   // metaKey\n          0,       // button\n          null);   // relatedTarget\n      a.dispatchEvent(e);\n    };\n\n    var simulatePopup = function(url) {\n      window.open(\n          url,\n          'id-' + (new Date()).getTime(),\n          'width=100,height=100,left=100,top=100');\n    };\n    window.addEventListener('message', function(e) {\n      if (e.data) {\n        var data = JSON.parse(e.data);\n        var type = data.type;\n        if (type == 'titleRequest') {\n          if (!listenersAreBound) {\n            bindTabName(data);\n            bindEmbedder(e);\n\n            // Notify the embedder of every title change\n            var titleElement = document.querySelector('title');\n            if (titleElement) {\n              titleElement.addEventListener('change', postTitle);\n            } else {\n              console.warn('Warning: No <title> element to bind to');\n              postTitle();\n            }\n\n            // Ensure initial title notification\n            if (title === null) {\n              postTitle();\n            }\n\n            listenersAreBound = true;\n          }\n        } else if (type == 'simulateCtrlClick') {\n          simulateCtrlClick(data.url);\n        } else if (type == 'simulatePopup') {\n          simulatePopup(data.url);\n        } else {\n          console.warn('Warning: Unexpected message received', e);\n        }\n      } else {\n        console.warn('Warning: Empty message (no data) received', e);\n      }\n    });\n  }\n}());\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  runApp();\n});\n\n/**\n * Listens for the app restarting then re-creates the window.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n */\nchrome.app.runtime.onRestarted.addListener(function() {\n  runApp();\n});\n\n/**\n * Creates the window for the application.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nfunction runApp() {\n  chrome.app.window.create(\n    'browser.html',\n    {'id': 'initialBrowserWindowID'},\n    function(newWindow) {\n      // Do not inject meaningful window.newWindowEvent; browser will instead\n      // load the homepage\n      newWindow.contentWindow.newWindowEvent = null;\n    });\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Multi-tabbed Browser\",\n  \"minimum_chrome_version\": \"35.0.0.0\",\n  \"version\": \"0.8\",\n  \"icons\": {\n    \"16\": \"icon_16.png\",\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"config.js\", \"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"contextMenus\",\n    \"webview\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/permission_box_controller.js",
    "content": "var permissionTool = (function() {\n  var containerElement = null;\n  var browserInstance = null;\n  var controller = null;\n  var allow = null, deny = null;\n  var hostRecords = [];\n\n  function query(id) { return containerElement.querySelector(id);}\n\n  function HostPermissions(host) {\n    this.host = host;\n    this.permissions = [];\n  }\n\n  function getHostForURL(url) {\n    var l = document.createElement('a');\n    l.href = url;\n    return l.hostname;\n  }\n\n  function getHostEntry(host) {\n    for (var index = 0; index < hostRecords.length; ++index) {\n      if (hostRecords[index].host === host) {\n        return hostRecords[index];\n      }\n    }\n    return null;\n  }\n\n  function check(host, permission) {\n    var entry = getHostEntry(host);\n    if (entry) {\n      if (entry.permissions[permission]) {\n        return entry.permissions[permission];\n      }\n    }\n    return null;\n  };\n\n\n  function addEntry(host, permission, value) {\n    var entry = getHostEntry(host);\n    if (!entry) {\n      entry = new HostPermissions(host);\n      hostRecords.push(entry);\n    }\n    entry.permissions[permission] = value;\n  };\n\n  var PermissionController = function(container, browser) {\n    containerElement = container;\n    browserInstance = browser;\n    controller = this;\n\n    query('#allow').onclick = onAllow;\n    query('#deny').onclick = onDeny;\n    container.className = 'overlay-bar';\n  };\n\n  PermissionController.prototype.ifPermits =\n      function(url, permission, callback) {        \n        var result = check(url, permission);\n        if (!result) {\n          containerElement.style.display = 'inline-block';\n          containerElement.querySelector('#question').innerHTML =\n              'The page at \"' + url + '\" is asking for permission to use <b>'\n              + permission + '</b>. What would you like to do?';\n          this.urlReq = url;\n          this.callbackReq = callback;\n          this.permissionReq = permission;\n          containerElement.style.display = 'block';\n        } else {\n          callback(result);\n        }\n      };\n\n  PermissionController.prototype.deactivate = function() {\n    deactivate();\n  };\n\n  function onAllow() {\n    deactivate();\n    addEntry(controller.urlReq, controller.permissionReq, 'ALLOW');\n    controller.callbackReq('ALLOW');\n  }\n\n  function onDeny() {\n    deactivate();\n    addEntry(controller.urlReq, controller.permissionReq, 'DENY');\n    controller.callbackReq('DENY');\n  }\n\n  function deactivate() {\n    containerElement.style.display = 'none';\n  };\n\n  return {'PermissionController': PermissionController};\n\n})();\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/popup.js",
    "content": "var popup = (function(configModule) {\n  var dce = function(str) { return document.createElement(str); };\n\n  var cfg = configModule.popupConfirmBox;\n  var popupBoxTemplate = dce('li');\n  popupBoxTemplate.innerHTML = cfg.innerHTML;\n\n  var createPopup = function(event, userAgent) {\n    (function(event) {\n      // TODO: Inspect event for window.open()'s name and attributes to\n      // correctly manage:\n      // 1. Multiple popups in the same window (i.e., window.open() twice with\n      //    the same window name)\n      // 2. Set attributes of popup window (e.g., size, location)\n      chrome.app.window.create(\n          'browser.html',\n          function(newWindow) {\n            // Pass new window event through global: window.newWindowEvent.\n            // NOTE: Webview creation and event.window.attach(webview)\n            // cannot be performed in this context; that has to happen in the\n            // context of the new window.\n            newWindow.contentWindow.newWindowEvent = event;\n            if (userAgent) {\n              newWindow.contentWindow.userAgent = userAgent;\n            }\n          });\n    }(event));\n  };\n\n  var PopupConfirmBoxList = function(listElement) {\n    this.listElement = listElement;\n    this.list = [];\n  };\n\n  PopupConfirmBoxList.prototype.getListElement = function() {\n    return this.listElement;\n  };\n\n  PopupConfirmBoxList.prototype.append = function(event) {\n    var box = new PopupConfirmBox(this, event);\n    this.list.push(box);\n    this.listElement.appendChild(box.getBoxElement());\n  };\n\n  PopupConfirmBoxList.prototype.removeBox = function(box) {\n    for (var i = 0; i < this.list.length; ++i) {\n      if (this.list[i] == box) {\n        this.listElement.removeChild(box.getBoxElement());\n        this.list.splice(i, 1);\n        break;\n      }\n    }\n  };\n\n  var PopupConfirmBox = function(popupList, event) {\n    this.popupList = popupList;\n    this.event = event;\n    this.url = event.targetUrl;\n    this.boxElement = popupBoxTemplate.cloneNode(true);\n    this.initBoxElement();\n  };\n\n  PopupConfirmBox.prototype.initBoxElement = function() {\n    var urlSpan = this.boxElement.querySelector('.' + cfg.urlSpanClass);\n    var acceptLink = this.boxElement.querySelector('.' + cfg.acceptLinkClass);\n    var denyLink = this.boxElement.querySelector('.' + cfg.denyLinkClass);\n\n    urlSpan.innerText = this.url;\n\n    (function(box) {\n      acceptLink.addEventListener('click', function(e) { box.doAccept(); });\n      denyLink.addEventListener('click', function(e) { box.doDeny(); });\n    }(this));\n  };\n\n  PopupConfirmBox.prototype.getBoxElement = function() {\n    return this.boxElement;\n  };\n\n  PopupConfirmBox.prototype.doAccept = function() {\n    createPopup(this.event);\n    this.popupList.removeBox(this);\n    this.detach();\n  };\n\n  PopupConfirmBox.prototype.doDeny = function() {\n    this.event.window.discard();\n\n    this.popupList.removeBox(this);\n    this.detach();\n  };\n\n  PopupConfirmBox.prototype.detach = function() {\n    this.popupList = null;\n  };\n\n  return {\n    'createPopup': createPopup,\n    'PopupConfirmBoxList': PopupConfirmBoxList,\n    'PopupConfirmBox': PopupConfirmBox\n  };\n}(config));\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/tabs.js",
    "content": "var tabs = (function(popupModule, contextMenuModule) {\n  var dce = function(str) { return document.createElement(str); };\n\n  var TabList = function(name, browser, tabContainer, contentContainer, newTabElement) {\n    this.name = name;\n    this.list = [];\n    this.table = {};\n    this.selected = 0;\n    this.tabNameCounter = 0;\n    this.browser = browser;\n    this.tabContainer = tabContainer;\n    this.contentContainer = contentContainer;\n    this.newTabElement = newTabElement;\n  };\n\n  TabList.prototype.getNumTabs = function() {\n    return this.list.length;\n  };\n\n  TabList.prototype.getTabIdx = function(tab) {\n    var idx = 0;\n    for (var i = 0; i < this.list.length; ++i) {\n      if (this.list[i] == tab) {\n        idx = i;\n        break;\n      }\n    }\n    if (idx < this.list.length) {\n      return idx;\n    } else {\n      console.warn('Warning: Failed to find tab in list', tab);\n      return -1;\n    }\n  };\n\n  TabList.prototype.selectIdx = function(idx) {\n    return this.selectTab(this.list[idx], idx);\n  };\n\n  TabList.prototype.selectTab = function(tab, idx) {\n    var prevTab = this.list[this.selected];\n    prevTab.deselect();\n\n    if (!(idx === 0 || idx)) {\n      idx = this.getTabIdx(tab);\n    }\n    this.selected = idx;\n\n    tab.select();\n    this.browser.doTabSwitch(prevTab, tab);\n    this.browser.doLayout();\n\n    return tab;\n  };\n\n  TabList.prototype.setLabelByName = function(tabName, tabLabel) {\n    if (tabName in this.table) {\n      return this.table[tabName].setLabel(tabLabel);\n    } else {\n      console.warn(\n          'Warning: Attempt to set label to \"', tabLabel,\n          '\" on unknown tab named \"', tabName, '\"');\n      return null;\n    }\n  };\n\n  TabList.prototype.append = function(webview) {\n    var tabName = this.name + '-' + this.tabNameCounter;\n    this.tabNameCounter = this.tabNameCounter + 1;\n    var tab = new Tab(tabName, this, webview);\n\n    this.list.push(tab);\n    this.table[tabName] = tab;\n\n    this.tabContainer.insertBefore(tab.labelContainer, this.newTabElement);\n    this.contentContainer.appendChild(tab.webviewContainer);\n\n    return tab;\n  };\n\n  TabList.prototype.removeIdx = function(idx) {\n    this.removeTab(this.list[idx], idx);\n  };\n\n  TabList.prototype.removeTab = function(tab, idx) {\n    if (this.list.length > 1) {\n      if (!(idx === 0 || idx)) {\n        idx = this.getTabIdx(tab);\n      }\n\n      var selectedIdx = this.selected;\n      if (tab.selected) {\n        // If this is the last tab, then select previous, else select next\n        selectedIdx = (this.selected + 1 == this.list.length) ?\n            this.selected - 1 :\n            this.selected + 1;\n        this.selectIdx(selectedIdx);\n      }\n\n      this.tabContainer.removeChild(tab.labelContainer);\n      this.contentContainer.removeChild(tab.webviewContainer);\n\n      tab.detach();\n      delete this.table[tab.name];\n      if (idx === 0 || idx) {\n        this.list.splice(idx, 1);\n      } else {\n        for (var i = 0; i < this.list.length; ++i) {\n          if (this.list[i] == tab) {\n            this.list.splice(i, 1);\n            break;\n          }\n        }\n      }\n\n      // If we are now selecting something that comes after the removed tab,\n      // then decrement the index: this.selected\n      if (selectedIdx > idx) {\n        this.selected = this.selected - 1;\n      }\n\n      return tab;\n    } else {\n      this.browser.closeBrowser();\n      return null;\n    }\n  };\n\n  TabList.prototype.getSelected = function() {\n    return this.list[this.selected];\n  };\n\n  TabList.prototype.detach = function() {\n    this.browser = null;\n  };\n\n  var Tab = function(name, tabList, webview) {\n    this.name = name;\n    this.tabList = tabList;\n    this.selected = false;\n    this.url = '';\n    this.loading = true;\n    this.overlay = false;\n    this.labelContainer = dce('li');\n    this.label = dce('p');\n    this.closeLink = dce('a');\n    this.webviewContainer = dce('div');\n    this.popupConfirmBoxList = new popupModule.PopupConfirmBoxList(dce('ul'));\n    this.contextMenu = new contextMenuModule.ContextMenu(\n        webview,\n        this.popupConfirmBoxList);\n    this.webview = webview;\n    this.initLabelContainer();\n    this.initWebview();\n  };\n\n  Tab.prototype.initLabelContainer = function() {\n    var name = this.name;\n    var labelContainer = this.labelContainer;\n    var label = this.label;\n    var closeLink = this.closeLink;\n\n    labelContainer.setAttribute('data-name', this.name);\n\n    this.setLabel('Loading...');\n\n    closeLink.href = '#close-' + name;\n    closeLink.innerText = 'X';\n\n    labelContainer.appendChild(label);\n    labelContainer.appendChild(closeLink);\n\n    (function(tab) {\n      labelContainer.addEventListener('click', function(e) {\n        if (tab.tabList) {\n          tab.tabList.selectTab(tab);\n        }\n      });\n      closeLink.addEventListener('click', function(e) {\n        if (tab.tabList) {\n          tab.tabList.removeTab(tab);\n        }\n      });\n    }(this));\n  };\n\n  Tab.prototype.initWebview = function() {\n    this.webview.setAttribute('data-name', this.name);\n    this.webviewContainer.setAttribute('data-name', this.name);\n    this.webviewContainer.classList.add('webview-container');\n    this.webview.addContentScripts([\n          {\n            'name': 'Messaging',\n            'matches': ['<all_urls>'],\n            'js': { 'files': ['guest_messaging.js']},\n            'run_at': 'document_start'\n          }]);\n\n    (function(tab) {\n      tab.webview.addEventListener(\n          'loadcommit',\n          function(e) { return tab.doLoadCommit(e); });\n      tab.webview.addEventListener(\n          'loadstop',\n          function(e) { return tab.doLoadStop(e); });\n      tab.webview.addEventListener(\n          'contentload',\n          function(e) { return tab.doContentLoad(e); });\n      tab.webview.addEventListener(\n          'newwindow',\n          function(e) { return tab.doNewTab(e); });\n      tab.webview.addEventListener(\n          'permissionrequest',\n          function (e) {\n            e.preventDefault();\n            checkForPermissions(tab, e);\n          });\n    }(this));\n\n    this.webviewContainer.appendChild(this.popupConfirmBoxList.getListElement());\n    this.webviewContainer.appendChild(this.webview);\n  };\n\n  Tab.prototype.setLabel = function(newLabel) {\n    this.label.innerText = newLabel;\n  };\n\n  Tab.prototype.select = function() {\n    this.labelContainer.classList.add('selected');\n    this.webviewContainer.classList.add('selected');\n    this.webview.classList.add('selected');\n    this.selected = true;\n  };\n\n  Tab.prototype.deselect = function() {\n    this.labelContainer.classList.remove('selected');\n    this.webviewContainer.classList.remove('selected');\n    this.webview.classList.remove('selected');\n    this.selected = false;\n  };\n\n  Tab.prototype.detach = function() {\n    this.tabList = null;\n  };\n\n  Tab.prototype.getWebview = function() {\n    return this.webview;\n  };\n\n  Tab.prototype.getWebviewContainer = function() {\n    return this.webviewContainer;\n  };\n\n  Tab.prototype.isLoading = function() {\n    return this.loading;\n  };\n\n  Tab.prototype.doLoadCommit = function(e) {\n    if (!e.isTopLevel) {\n      return;\n    }\n\n    this.loading = true;\n    this.url = e.url;\n    this.tabList.browser.doTabNavigating(this, e.url);\n  };\n\n  Tab.prototype.doLoadStop = function(e) {\n    if (this.loading) {\n      this.tabList.browser.doTabNavigated(this, this.url);\n    }\n    this.loading = false;\n  };\n\n  Tab.prototype.doContentLoad = function(e) {\n    var data = {\n      'type': 'titleRequest',\n      'tabName': this.name\n    };\n    this.webview.contentWindow.postMessage(JSON.stringify(data), '*');\n  };\n\n  // New window triggered by existing window\n  Tab.prototype.doNewTab = function(e) {\n    e.preventDefault();\n\n    var dis = e.windowOpenDisposition;\n    var url = e.targetUrl;\n    var userAgent = this.contextMenu.getUserAgentOverride(url);\n\n    if (dis == 'new_background_tab' || dis == 'new_foreground_tab') {\n      var newWebview = dce('webview');\n      e.window.attach(newWebview);\n\n      // Allow context menu to manipulate webview if necessary\n      if (this.contextMenu.isOpening(url)) {\n        this.contextMenu.doOpen(url, newWebview);\n      }\n\n      var newTab = this.tabList.append(newWebview);\n      if (e.windowOpenDisposition == 'new_foreground_tab') {\n        this.tabList.selectTab(newTab);\n      }\n    } else {\n      // If a context menu selection caused the popup, create it immediately;\n      // otherwise, use interstitial confirmation box\n      if (this.contextMenu.isOpening(url)) {\n        this.contextMenu.doOpen(url);\n        popupModule.createPopup(e, userAgent);\n      } else {\n        this.popupConfirmBoxList.append(e);\n      }\n    }\n  };\n\n  Tab.prototype.stopNavigation = function() {\n    this.webview.stop();\n  };\n\n  Tab.prototype.doReload = function() {\n    this.webview.reload();\n  };\n\n  Tab.prototype.goBack = function() {\n    this.webview.back();\n  };\n\n  Tab.prototype.goForward = function() {\n    this.webview.forward();\n  };\n\n  Tab.prototype.navigateTo = function(url) {\n    this.stopNavigation();\n    if (!handleInternalCommand(url)) {\n      this.webview.src = url;\n    }\n  };\n\n  function handleInternalCommand(url) {\n    if (url === 'browser://exit') {\n      window.close();\n    }\n  }\n\n  function checkForPermissions(tab, e) {\n    tab.tabList.browser.permissionBoxController.ifPermits(\n      tab.webview.src, e.permission, function(result) {\n        if (result === 'ALLOW') {\n          e.request.allow();\n        } else {\n          e.request.deny();\n        }\n      });\n  }\n\n  return {\n    'TabList': TabList,\n    'Tab': Tab\n  };\n}(popup, contextMenu));\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/multi-tab-browser/zoom_box_controller.js",
    "content": "  var zoomTool = (function() {\n  function qsel(id) {\n    return containerElement.querySelector(id);\n  }\n  var containerElement = null;\n  var browserInstance = null;\n  var controller = null;\n  var form = null, zoomIn = null, zoomOut = null, submit = null,\n    zoomFactor = null;\n  var ZoomController = function(container, browser) {\n    containerElement = container;\n    browserInstance = browser;\n    form = qsel('#zoom-form');\n    zoomFactor = qsel('#zoom-text');\n    zoomIn = qsel('#zoom-in');\n    zoomOut = qsel('#zoom-out');\n    submit = qsel('#submit');\n    containerElement.style.display = 'none';\n    controller = this;\n    initHandlers();\n  };\n\n  ZoomController.prototype.deactivate = function() {\n    if (this.isVisible()) {\n      this.toggleVisibility();\n    }\n  }\n\n  function initHandlers() {\n    zoomIn.addEventListener('click', increaseZoom);\n    zoomOut.addEventListener('click', decreaseZoom);\n    form.addEventListener('submit', function(e) {\n      e.preventDefault();\n      var zoomValue = zoomFactor.value;\n      updateZoom(zoomValue);\n    });\n  }\n\n  ZoomController.prototype.isVisible = function() {\n    return containerElement.style.display === '-webkit-flex';\n  }\n\n  ZoomController.prototype.toggleVisibility = function() {\n    if (containerElement.style.display === '-webkit-flex') {\n      containerElement.style.display = 'none';\n    } else {\n      containerElement.style.display = '-webkit-flex';\n      browserInstance.tabs.getSelected().webview.getZoom(function(factor) {\n        zoomFactor.value = Number(factor.toFixed(6)).toString();\n      });\n      zoomFactor.select();\n    }\n  };\n\n  function setZoomWithinLimits(value) {\n    return Math.max(Math.min(value, 5.0), 0.25);\n  }\n\n  function increaseZoom() {\n    var zoomValue = getNextPresetZoom(Number(zoomFactor.value));\n    updateZoom(zoomValue.high);\n  }\n\n  function decreaseZoom() {\n    var zoomValue = getNextPresetZoom(Number(zoomFactor.value));\n    updateZoom(zoomValue.low);\n  }\n\n  function updateZoom(value) {\n    zoomFactor.value = value;\n    browserInstance.tabs.getSelected().webview.setZoom(\n      Number(zoomFactor.value));\n  }\n\n  function getNextPresetZoom(zoomFactor) {\n  var preset = [0.25, 0.33, 0.5, 0.67, 0.75, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2,\n                2.5, 3, 4, 5];\n  var low = 0;\n  var high = preset.length - 1;\n  var mid;\n  while (high - low > 1) {\n    mid = Math.floor((high + low)/2);\n    if (preset[mid] < zoomFactor) {\n      low = mid;\n    } else if (preset[mid] > zoomFactor) {\n      high = mid;\n    } else {\n      return {low: preset[mid - 1], high: preset[mid + 1]};\n    }\n  }\n  return {low: preset[low], high: preset[high]};\n}\n  return {'ZoomController': ZoomController};\n})();\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/kpgjodoohleggakakpaadgjeedfgeafi\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# New Window API\n\nSample that shows how to use the [New Window\nAPI](https://developer.chrome.com/apps/tags/webview#event-newwindow) for\n[webviews](http://developer.chrome.com/apps/app_external#webview). The\napp behaves like a tabbed browser. When actions in we webview request a new\ntab or window, the browser responds appropriately. For example, clicking\nlinks with a foreign target opens a new tab in the foreground; ctrl+clicking\na link opens a new tab in the background; Javascript calls to `window.open()`\nthat identify a different window open a new window.\n\n## Features\n\n* Shortcut keys: `Ctrl+t` (new tab), `Ctrl+W` (close tab), `Ctrl + [1-9]` (select tab)\n* Popup confirmation: An attempt to open a separate window (not a separate\n  tab in the same window) must be explicitly allowed by the user (see\n  screenshot for example of Allow/Deny dilaogue)\n\n## Limitations\n\n* Managing of named windows and setting of new window attributes is not\n  supported. Attempting to open two links in a window named `foo` will not\n  navigate the same window twice. Attributes (e.g., width, height, resizable)\n  to `window.open()` will be ignored.\n\n## Resources\n\n* [Webview New Window API](https://developer.chrome.com/apps/tags/webview#event-newwindow)\n* [Webview](http://developer.chrome.com/apps/app_external#webview)\n* [Permissions](http://developer.chrome.com/apps/manifest#permissions)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/webview-samples/new-window/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window/browser.css",
    "content": "body {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n  font-family: Lucida Grande, Arial, sans-serif;\n}\n\nbutton,\ninput {\n  outline: none;\n}\n\ndiv {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n#content-container {\n  display: inline-block;\n  position: relative;\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n#controls {\n  padding: 0px;\n  background-color: #eee;\n  border-bottom: solid 1px #ccc;\n}\n\n#controls button,\n#controls input {\n  font-size: 14px;\n  line-height: 24px;\n  border-radius: 2px;\n  padding: 0 6px;\n}\n\n#controls button#reload {\n  border-radius: 16px;\n}\n\n#tab-controls {\n  padding: 3px 3px 0px 3px;\n  background: #888;\n}\n\n#browser-controls {\n  padding: 3px;\n}\n\nbutton,\ninput[type=\"submit\"],\nbutton[disabled]:hover {\n  border: solid 1px transparent;\n  background: transparent;\n}\n\nbutton:hover,\ninput[type=\"submit\"]:hover {\n  border-color: #ccc;\n  background: -webkit-linear-gradient(bottom, #cccccc 0%, #f2f2f2 99%);\n}\n\nbutton:active,\ninput[type=\"submit\"]:active {\n  border-color: #bbb;\n  background: -webkit-linear-gradient(bottom, #e2e2e2 0%, #bbbbbb 99%);\n}\n\n/* These glyphs are on the small side, make them look more natural when\ncompared to the back/forward buttons */\n#controls #home {\n  font-size: 24px;\n}\n\n#controls #reload {\n  font-size: 20px;\n}\n\n#location {\n  border: solid 1px #ccc;\n  padding: 2px;\n  width: 100%;\n  -webkit-box-sizing: border-box;\n}\n\n#browser-controls {\n  display: -webkit-flex;\n  -webit-flex-direction: column;\n}\n\n#browser-controls #location-form {\n  -webkit-flex: 1;\n  display: -webkit-flex;\n  -webit-flex-direction: column;\n}\n\n#browser-controls #center-column {\n  -webkit-flex: 1;\n}\n\nwebview,\n.webview-container {\n  display: inline-block;\n  padding: 0px;\n  margin: 0px;\n  border: 0px;\n  position: absolute;\n  top: 0px;\n  left: 0px;\n  visibility: hidden;\n}\n\n.selected,\n#content-container .selected {\n  visibility: visible;\n}\n\n.webview-container ul {\n  position: relative;\n  text-align: right;\n  padding: 0px;\n  margin: 0px;\n  z-index: 2;\n  list-style-type: none;\n}\n\n.webview-container ul li {\n  padding: 3px;\n  background: #ff7;\n  border-bottom: solid 1px #aa6;\n}\n\nwebview {\n  z-index: 1;\n}\n\n.popup-allow {\n  color: #0a0;\n  font-weight: bold;\n  text-decoration: none;\n}\n\n.popup-allow:hover {\n  color: #0f0;\n  font-weight: bold;\n  text-decoration: none;\n}\n\n.popup-deny {\n  color: #a00;\n  font-weight: bold;\n  text-decoration: none;\n}\n\n.popup-deny:hover {\n  color: #f00;\n  font-weight: bold;\n  text-decoration: none;\n}\n\n/* The reload button turns into a spinning trobber */\n.loading #reload {\n  -webkit-animation: spinner-animation .5s infinite linear;\n  -webkit-transform-origin: 50% 55.5%;\n}\n\n@-webkit-keyframes spinner-animation {\n  0% { -webkit-transform: rotate(0deg); }\n  100% {-webkit-transform: rotate(360deg); }\n}\n\n#tab-container {\n  margin: 5px 5px 0px 5px;\n  padding: 0px;\n  display: inline-block;\n}\n\n#tab-container li {\n  display: inline-block;\n  position: relative;\n  vertical-align: bottom;\n  width: 100px;\n  margin: 0px;\n  padding: 6px 16px 6px 6px;\n  border: 0px;\n  background: #ccc;\n}\n\n#tab-container li:hover {\n  background: #ddd;\n}\n\n#tab-container li.selected {\n  background: #eee;\n}\n\n#tab-container li p {\n  width: 100px;\n  float:left;\n  z-index: 1;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  margin: 0px;\n  padding: 0px;\n  -webkit-margin-before: 0px;\n  -webkit-margin-after: 0px;\n}\n\n#tab-container li a {\n  position: absolute;\n  right: 2px;\n  z-index: 2;\n  padding-left: 1px;\n  padding-right: 1px;\n  color: #666;\n  font-weight: bold;\n  text-decoration: none;\n  cursor: default;\n}\n\n#tab-container li a:hover {\n  color: #000;\n}\n\n#tab-container li#new-tab {\n  background: transparent;\n  vertical-align: baseline;\n  display: inline;\n}\n\n#tab-container li#new-tab a {\n  font-size: 24px;\n  padding: 0px;\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window/browser.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <link rel=\"stylesheet\" href=\"browser.css\">\n    <script src=\"config.js\"></script>\n    <script src=\"popup.js\"></script>\n    <script src=\"tabs.js\"></script>\n    <script src=\"browser.js\"></script>\n    <script src=\"browser_main.js\"></script>\n  </head>\n  <body>\n    <div id=\"controls\">\n\n      <div id=\"tab-controls\">\n        <ul id=\"tab-container\">\n          <li id=\"new-tab\"><a href=\"#new-tab\">+</a></li>\n        </ul>\n      </div>\n\n      <div id=\"browser-controls\">\n        <button id=\"back\" title=\"Go Back\">&#9664;</button>\n        <button id=\"forward\" title=\"Go Forward\">&#9654;</button>\n        <button id=\"home\" title=\"Go Home\">&#8962;</button>\n        <button id=\"reload\" title=\"Reload\">&#10227;</button>\n        <!-- <button id=\"terminate\" title=\"Simulate Crash\">&#9760;</button> -->\n\n        <form id=\"location-form\">\n          <div id=\"center-column\">\n            <input id=\"location\" type=\"text\" value=\"\">\n          </div>\n          <input type=\"submit\" value=\"Go\">\n        </form>\n      </div>\n\n    </div>\n\n    <div id=\"content-container\">\n    </div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window/browser.js",
    "content": "var browser = (function(configModule, tabsModule) {\n  var dce = function(str) { return document.createElement(str); };\n\n  var Browser = function(\n    controlsContainer,\n    back,\n    forward,\n    home,\n    reload,\n    locationForm,\n    locationBar,\n    tabContainer,\n    contentContainer,\n    newTabElement) {\n    this.controlsContainer = controlsContainer;\n    this.back = back;\n    this.forward = forward;\n    this.reload = reload;\n    this.home = home;\n    this.locationForm = locationForm;\n    this.locationBar = locationBar;\n    this.tabContainer = tabContainer;\n    this.contentContainer = contentContainer;\n    this.newTabElement = newTabElement;\n    this.tabs = new tabsModule.TabList(\n        'tabs',\n        this,\n        tabContainer,\n        contentContainer,\n        newTabElement);\n\n    this.init();\n  };\n\n  Browser.prototype.init = function() {\n    (function(browser) {\n      window.addEventListener('resize', function(e) {\n        browser.doLayout(e);\n      });\n\n      window.addEventListener('keydown', function(e) {\n        browser.doKeyDown(e);\n      });\n\n      browser.back.addEventListener('click', function(e) {\n        browser.tabs.getSelected().goBack();\n      });\n\n      browser.forward.addEventListener('click', function() {\n        browser.tabs.getSelected().goForward();\n      });\n\n      browser.home.addEventListener('click', function() {\n        browser.tabs.getSelected().navigateTo(configModule.homepage);\n      });\n\n      browser.reload.addEventListener('click', function() {\n        var tab = browser.tabs.getSelected();\n        if (tab.isLoading()) {\n          tab.stopNavigation();\n        } else {\n          tab.doReload();\n        }\n      });\n      browser.reload.addEventListener(\n        'webkitAnimationIteration',\n        function() {\n          // Between animation iterations: If loading is done, then stop spinning\n          if (!browser.tabs.getSelected().isLoading()) {\n            document.body.classList.remove('loading');\n          }\n        }\n      );\n\n      browser.locationForm.addEventListener('submit', function(e) {\n        e.preventDefault();\n        browser.tabs.getSelected().navigateTo(browser.locationBar.value);\n      });\n\n      browser.newTabElement.addEventListener(\n        'click',\n        function(e) { return browser.doNewTab(e); });\n\n      window.addEventListener('message', function(e) {\n        if (e.data) {\n          var data = JSON.parse(e.data);\n          if (data.name && data.title) {\n            browser.tabs.setLabelByName(data.name, data.title);\n          } else {\n            console.warn(\n                'Warning: Expected message from guest to contain {name, title}, but got:',\n                data);\n          }\n        } else {\n          console.warn('Warning: Message from guest contains no data');\n        }\n      });\n\n      var webview = dce('webview');\n      var tab = browser.tabs.append(webview);\n      // Global window.newWindowEvent may be injected by opener\n      if (window.newWindowEvent) {\n        window.newWindowEvent.window.attach(webview);\n      } else {\n        tab.navigateTo(configModule.homepage);\n      }\n      browser.tabs.selectTab(tab);\n    }(this));\n  };\n\n  Browser.prototype.doLayout = function(e) {\n    var controlsHeight = this.controlsContainer.offsetHeight;\n    var windowWidth = document.documentElement.clientWidth;\n    var windowHeight = document.documentElement.clientHeight;\n    var contentWidth = windowWidth;\n    var contentHeight = windowHeight - controlsHeight;\n\n    var tab = this.tabs.getSelected();\n    var webview = tab.getWebview();\n    var webviewContainer = tab.getWebviewContainer();\n\n    var layoutElements = [\n      this.contentContainer,\n      webviewContainer,\n      webview];\n    for (var i = 0; i < layoutElements.length; ++i) {\n      layoutElements[i].style.width = contentWidth + 'px';\n      layoutElements[i].style.height = contentHeight + 'px';\n    }\n  };\n\n  // New window that is NOT triggered by existing window\n  Browser.prototype.doNewTab = function(e) {\n    var tab = this.tabs.append(dce('webview'));\n    tab.navigateTo(configModule.homepage);\n    this.tabs.selectTab(tab);\n    return tab;\n  };\n\n  Browser.prototype.doKeyDown = function(e) {\n    if (e.ctrlKey) {\n      switch(e.keyCode) {\n        // Ctrl+T\n        case 84:\n        this.doNewTab();\n        break;\n        // Ctrl+W\n        case 87:\n        e.preventDefault();\n        this.tabs.removeTab(this.tabs.getSelected());\n        break;\n      }\n      // Ctrl + [1-9]\n      if (e.keyCode >= 49 && e.keyCode <= 57) {\n        var idx = e.keyCode - 49;\n        if (idx < this.tabs.getNumTabs()) {\n          this.tabs.selectIdx(idx);\n        }\n      }\n    }\n  };\n\n  Browser.prototype.doTabNavigating = function(tab, url) {\n    if (tab.selected) {\n      document.body.classList.add('loading');\n      this.locationBar.value = url;\n    }\n  };\n\n  Browser.prototype.doTabNavigated = function(tab, url) {\n    this.updateControls();\n  };\n\n  Browser.prototype.doTabSwitch = function(oldTab, newTab) {\n    this.updateControls();\n  };\n\n  Browser.prototype.updateControls = function() {\n    var selectedTab = this.tabs.getSelected();\n    if (selectedTab.isLoading()) {\n      document.body.classList.add('loading');\n    }\n    var selectedWebview = selectedTab.getWebview();\n    this.back.disabled = !selectedWebview.canGoBack();\n    this.forward.disabled = !selectedWebview.canGoForward();\n    if (this.locationBar.value != selectedTab.url) {\n      this.locationBar.value = selectedTab.url;\n    }\n  };\n\n  return {'Browser': Browser};\n})(config, tabs);\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window/browser_main.js",
    "content": "var mainBrowser = null;\n(function(browserModule) {\n  var query = function(str) { return document.querySelector(str); };\n\n\n  window.addEventListener('load', function(e) {\n    mainBrowser = new browserModule.Browser(\n        query('#controls'),\n        query('#back'),\n        query('#forward'),\n        query('#home'),\n        query('#reload'),\n        query('#location-form'),\n        query('#location'),\n        query('#tab-container'),\n        query('#content-container'),\n        query('#new-tab'));\n  });\n})(browser);\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window/config.js",
    "content": "// Global configuration variables\nvar config = {\n  'homepage': 'http://www.google.com/',\n  'popupConfirmBox': {\n    'innerHTML': 'This webpage would like to open a window at <span class=\"popup-url\"></span> Would you like to allow this popup? <a href=\"#popup-allow\" class=\"popup-allow\">Allow</a> <a href=\"#popup-deny\" class=\"popup-deny\">Deny</a>',\n    'urlSpanClass': 'popup-url',\n    'acceptLinkClass': 'popup-allow',\n    'denyLinkClass': 'popup-deny'\n  }\n};\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  runApp();\n});\n\n/**\n * Listens for the app restarting then re-creates the window.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n */\nchrome.app.runtime.onRestarted.addListener(function() {\n  runApp();\n});\n\n/**\n * Creates the window for the application.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nfunction runApp() {\n  chrome.app.window.create(\n    'browser.html',\n    {'id': 'initialBrowserWindowID', 'state': 'maximized'},\n    function(newWindow) {\n      // Do not inject meaningful window.newWindowEvent; browser will instead\n      // load the homepage\n      newWindow.contentWindow.newWindowEvent = null;\n    });\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"New Window API Sample\",\n  \"minimum_chrome_version\": \"24.0.1307.0\",\n  \"version\": \"2.0\",\n  \"icons\": {\n    \"16\": \"icon_16.png\",\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"config.js\", \"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"webview\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window/popup.js",
    "content": "var popup = (function(configModule) {\n  var dce = function(str) { return document.createElement(str); };\n\n  var cfg = configModule.popupConfirmBox;\n  var popupBoxTemplate = dce('li');\n  popupBoxTemplate.innerHTML = cfg.innerHTML;\n\n  var PopupConfirmBoxList = function(listElement) {\n    this.listElement = listElement;\n    this.list = [];\n  };\n\n  PopupConfirmBoxList.prototype.getListElement = function() {\n    return this.listElement;\n  };\n\n  PopupConfirmBoxList.prototype.append = function(event) {\n    var box = new PopupConfirmBox(this, event);\n    this.list.push(box);\n    this.listElement.appendChild(box.getBoxElement());\n  };\n\n  PopupConfirmBoxList.prototype.removeBox = function(box) {\n    for (var i = 0; i < this.list.length; ++i) {\n      if (this.list[i] == box) {\n        this.listElement.removeChild(box.getBoxElement());\n        this.list.splice(i, 1);\n        break;\n      }\n    }\n  };\n\n  var PopupConfirmBox = function(popupList, event) {\n    this.popupList = popupList;\n    this.event = event;\n    this.url = event.targetUrl;\n    this.boxElement = popupBoxTemplate.cloneNode(true);\n    this.initBoxElement();\n  };\n\n  PopupConfirmBox.prototype.initBoxElement = function() {\n    var urlSpan = this.boxElement.querySelector('.' + cfg.urlSpanClass);\n    var acceptLink = this.boxElement.querySelector('.' + cfg.acceptLinkClass);\n    var denyLink = this.boxElement.querySelector('.' + cfg.denyLinkClass);\n\n    urlSpan.innerText = this.url;\n\n    (function(box) {\n      acceptLink.addEventListener('click', function(e) { box.doAccept(); });\n      denyLink.addEventListener('click', function(e) { box.doDeny(); });\n    }(this));\n  };\n\n  PopupConfirmBox.prototype.getBoxElement = function() {\n    return this.boxElement;\n  };\n\n  PopupConfirmBox.prototype.doAccept = function() {\n    (function(box) {\n      // TODO: Inspect box.event for window.open()'s name and attributes to\n      // correctly manage:\n      // 1. Multiple popups in the same window (i.e., window.open() twice with\n      //    the same window name)\n      // 2. Set attributes of popup window (e.g., size, location)\n      chrome.app.window.create(\n          'browser.html',\n          function(newWindow) {\n            // Pass new window event through global: window.newWindowEvent.\n            // NOTE: Webview creation and box.event.window.attach(webview)\n            // cannot be performed in this context; that has to happen in the\n            // context of the new window.\n            newWindow.contentWindow.newWindowEvent = box.event;\n          });\n    }(this));\n\n    this.popupList.removeBox(this);\n    this.detach();\n  };\n\n  PopupConfirmBox.prototype.doDeny = function() {\n    this.event.window.discard();\n\n    this.popupList.removeBox(this);\n    this.detach();\n  };\n\n  PopupConfirmBox.prototype.detach = function() {\n    this.popupList = null;\n  };\n\n  return {\n    'PopupConfirmBoxList': PopupConfirmBoxList,\n    'PopupConfirmBox': PopupConfirmBox\n  };\n}(config));\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window/tabs.js",
    "content": "var tabs = (function(popupModule) {\n  var dce = function(str) { return document.createElement(str); };\n\n  var TabList = function(name, browser, tabContainer, contentContainer, newTabElement) {\n    this.name = name;\n    this.list = [];\n    this.table = {};\n    this.selected = 0;\n    this.tabNameCounter = 0;\n    this.browser = browser;\n    this.tabContainer = tabContainer;\n    this.contentContainer = contentContainer;\n    this.newTabElement = newTabElement;\n  };\n\n  TabList.prototype.getNumTabs = function() {\n    return this.list.length;\n  };\n\n  TabList.prototype.getTabIdx = function(tab) {\n    var idx = 0;\n    for (var i = 0; i < this.list.length; ++i) {\n      if (this.list[i] == tab) {\n        idx = i;\n        break;\n      }\n    }\n    if (idx < this.list.length) {\n      return idx;\n    } else {\n      console.warn('Warning: Failed to find tab in list', tab);\n      return -1;\n    }\n  };\n\n  TabList.prototype.selectIdx = function(idx) {\n    return this.selectTab(this.list[idx], idx);\n  };\n\n  TabList.prototype.selectTab = function(tab, idx) {\n    var prevTab = this.list[this.selected];\n    prevTab.deselect();\n\n    if (!(idx === 0 || idx)) {\n      idx = this.getTabIdx(tab);\n    }\n    this.selected = idx;\n\n    tab.select();\n    this.browser.doTabSwitch(prevTab, tab);\n    this.browser.doLayout();\n\n    return tab;\n  };\n\n  TabList.prototype.setLabelByName = function(tabName, tabLabel) {\n    if (tabName in this.table) {\n      return this.table[tabName].setLabel(tabLabel);\n    } else {\n      console.warn(\n          'Warning: Attempt to set label to \"', tabLabel,\n          '\" on unknown tab named \"', tabName, '\"');\n      return null;\n    }\n  };\n\n  TabList.prototype.append = function(webview) {\n    var tabName = this.name + '-' + this.tabNameCounter;\n    this.tabNameCounter = this.tabNameCounter + 1;\n    var tab = new Tab(tabName, this, webview);\n\n    this.list.push(tab);\n    this.table[tabName] = tab;\n\n    this.tabContainer.insertBefore(tab.labelContainer, this.newTabElement);\n    this.contentContainer.appendChild(tab.webviewContainer);\n\n    return tab;\n  };\n\n  TabList.prototype.removeIdx = function(idx) {\n    this.removeTab(this.list[idx], idx);\n  };\n\n  TabList.prototype.removeTab = function(tab, idx) {\n    if (this.list.length > 1) {\n      if (!(idx === 0 || idx)) {\n        idx = this.getTabIdx(tab);\n      }\n\n      var selectedIdx = this.selected;\n      if (tab.selected) {\n        // If this is the last tab, then select previous, else select next\n        selectedIdx = (this.selected + 1 == this.list.length) ?\n            this.selected - 1 :\n            this.selected + 1;\n        this.selectIdx(selectedIdx);\n      }\n\n      this.tabContainer.removeChild(tab.labelContainer);\n      this.contentContainer.removeChild(tab.webviewContainer);\n\n      tab.detach();\n      delete this.table[tab.name];\n      if (idx === 0 || idx) {\n        this.list.splice(idx, 1);\n      } else {\n        for (var i = 0; i < this.list.length; ++i) {\n          if (this.list[i] == tab) {\n            this.list.splice(i, 1);\n            break;\n          }\n        }\n      }\n\n      // If we are now selecting something that comes after the removed tab,\n      // then decrement the index: this.selected\n      if (selectedIdx > idx) {\n        this.selected = this.selected - 1;\n      }\n\n      return tab;\n    } else {\n      return null;\n    }\n  };\n\n  TabList.prototype.getSelected = function() {\n    return this.list[this.selected];\n  };\n\n  TabList.prototype.detach = function() {\n    this.browser = null;\n  };\n\n  var Tab = function(name, tabList, webview) {\n    this.name = name;\n    this.tabList = tabList;\n    this.selected = false;\n    this.url = '';\n    this.loading = true;\n    this.overlay = false;\n    this.labelContainer = dce('li');\n    this.label = dce('p');\n    this.closeLink = dce('a');\n    this.webviewContainer = dce('div');\n    this.popupConfirmBoxList = new popupModule.PopupConfirmBoxList(dce('ul'));\n    this.webview = webview;\n    this.scriptInjectionAttempted = false;\n\n    this.initLabelContainer();\n    this.initWebview();\n  };\n\n  Tab.prototype.initLabelContainer = function() {\n    var name = this.name;\n    var labelContainer = this.labelContainer;\n    var label = this.label;\n    var closeLink = this.closeLink;\n\n    labelContainer.setAttribute('data-name', this.name);\n\n    this.setLabel('Loading...');\n\n    closeLink.href = '#close-' + name;\n    closeLink.innerText = 'X';\n\n    labelContainer.appendChild(label);\n    labelContainer.appendChild(closeLink);\n\n    (function(tab) {\n      labelContainer.addEventListener('click', function(e) {\n        if (tab.tabList) {\n          tab.tabList.selectTab(tab);\n        }\n      });\n      closeLink.addEventListener('click', function(e) {\n        if (tab.tabList) {\n          tab.tabList.removeTab(tab);\n        }\n      });\n    }(this));\n  };\n\n  Tab.prototype.initWebview = function() {\n    this.webview.setAttribute('data-name', this.name);\n    this.webviewContainer.setAttribute('data-name', this.name);\n    this.webviewContainer.classList.add('webview-container');\n\n    (function(tab) {\n      tab.webview.addEventListener(\n          'loadcommit',\n          function(e) { return tab.doLoadCommit(e); });\n      tab.webview.addEventListener(\n          'loadstop',\n          function(e) { return tab.doLoadStop(e); });\n      tab.webview.addEventListener(\n          'newwindow',\n          function(e) { return tab.doNewTab(e); });\n    }(this));\n\n    this.webviewContainer.appendChild(this.popupConfirmBoxList.getListElement());\n    this.webviewContainer.appendChild(this.webview);\n  };\n\n  Tab.prototype.setLabel = function(newLabel) {\n    this.label.innerText = newLabel;\n  };\n\n  Tab.prototype.select = function() {\n    this.labelContainer.classList.add('selected');\n    this.webviewContainer.classList.add('selected');\n    this.webview.classList.add('selected');\n    this.selected = true;\n  };\n\n  Tab.prototype.deselect = function() {\n    this.labelContainer.classList.remove('selected');\n    this.webviewContainer.classList.remove('selected');\n    this.webview.classList.remove('selected');\n    this.selected = false;\n  };\n\n  Tab.prototype.detach = function() {\n    this.tabList = null;\n  };\n\n  Tab.prototype.getWebview = function() {\n    return this.webview;\n  };\n\n  Tab.prototype.getWebviewContainer = function() {\n    return this.webviewContainer;\n  };\n\n  Tab.prototype.isLoading = function() {\n    return this.loading;\n  };\n\n  Tab.prototype.doLoadCommit = function(e) {\n    if (!e.isTopLevel) {\n      return;\n    }\n\n    this.loading = true;\n    this.scriptInjectionAttempted = false;\n    this.url = e.url;\n    this.tabList.browser.doTabNavigating(this, e.url);\n  };\n\n  Tab.prototype.doLoadStop = function(e) {\n    if (this.loading) {\n      this.tabList.browser.doTabNavigated(this, e.url);\n    }\n    this.loading = false;\n    if (!this.scriptInjectionAttempted) {\n      // Try to inject title-update-messaging script\n      var tab = this;\n      this.webview.executeScript(\n          {'file': 'title.js'},\n          function(results) { return tab.doScriptInjected(results); });\n      this.scriptInjectionAttempted = true;\n    }\n  };\n\n  Tab.prototype.doScriptInjected = function(results) {\n    if (!results || !results.length) {\n      console.warn('Warning: Failed to inject title.js', webview);\n    } else {\n      // Send a message to the webview so it can get a reference to\n      // the embedder\n      var data = {'name': this.name };\n      this.webview.contentWindow.postMessage(JSON.stringify(data), '*');\n    }\n  };\n\n  // New window triggered by existing window\n  Tab.prototype.doNewTab = function(e) {\n    e.preventDefault();\n\n    var dis = e.windowOpenDisposition;\n\n    if (dis == 'new_background_tab' || dis == 'new_foreground_tab') {\n      var newWebview = dce('webview');\n      e.window.attach(newWebview);\n      var newTab = this.tabList.append(newWebview);\n      if (e.windowOpenDisposition == 'new_foreground_tab') {\n        this.tabList.selectTab(newTab);\n      }\n    } else {\n      this.popupConfirmBoxList.append(e);\n    }\n  };\n\n  Tab.prototype.stopNavigation = function() {\n    this.webview.stop();\n  };\n\n  Tab.prototype.doReload = function() {\n    this.webview.reload();\n  };\n\n  Tab.prototype.goBack = function() {\n    this.webview.back();\n  };\n\n  Tab.prototype.goForward = function() {\n    this.webview.forward();\n  };\n\n  Tab.prototype.navigateTo = function(url) {\n    this.stopNavigation();\n    this.webview.src = url;\n  };\n\n  return {\n    'TabList': TabList,\n    'Tab': Tab\n  };\n}(popup));\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window/title.js",
    "content": "var webviewTitleInjectionComplete = false;\n(function() {\n  // Prevent multiple injection\n  if (!webviewTitleInjectionComplete) {\n    var embedder = null;\n    var tabName = null;\n    var listenersAreBound = false;\n    var title = null;\n    var postTitle = (function() {\n      return function(e) {\n        title = document.title;\n        var data = {\n          'name': tabName,\n          'title': title || '[no title]'\n        };\n        embedder.postMessage(JSON.stringify(data), '*');\n      };\n    }());\n    var bindEmbedder = function(e) {\n      embedder = e.source;\n    };\n    var bindTabName = function(e) {\n      if (e.data) {\n        var data = JSON.parse(e.data);\n        if (data.name) {\n          tabName = data.name;\n        } else {\n          console.warn('Warning: Message from embedder contains no tab name');\n        }\n      } else {\n          console.warn('Warning: Message from embedder contains no data');\n      }\n    };\n\n    // Wait for message that gives us a reference to the embedder\n    window.addEventListener('message', function(e) {\n      if (!listenersAreBound) {\n        // Bind data\n        bindEmbedder(e);\n        bindTabName(e);\n\n        // Notify the embedder of every title change\n        var titleElement = document.querySelector('title');\n        if (titleElement) {\n          titleElement.addEventListener('change', postTitle);\n        } else {\n          console.warn('Warning: No <title> element to bind to');\n          postTitle();\n        }\n\n        // Ensure initial title notification\n        if (title === null) {\n          postTitle();\n        }\n\n        listenersAreBound = true;\n      }\n    });\n  }\n}());\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window-user-agent/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/jhgiafbilglmngpgkhcmnicfkpfihggo\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# New Window API\n\nSample that shows one way to combine the [New Window\nAPI](https://developer.chrome.com/apps/tags/webview#event-newwindow) with the\n[User Agent\nAPI](https://developer.chrome.com/apps/tags/webview#method-setUserAgentOverride)\nfor\n[webviews](http://developer.chrome.com/apps/app_external#webview). The\napp combines the [New Window\nSample](https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/_archive/apps/samples/webview-samples/new-window)\nand the [User Agent\nSample](https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/webview-samples/user-agent)\nby supporting `Open link in new tab/window as...` via the [Context Menu\nAPI](https://developer.chrome.com/extensions/contextMenus) (see screenshot).\n\n## Features\n\n* All features from the [New Window\nSample](https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/webview-samples/new-window)\n* Context menu entries for `Open link in new tab/window\n  as Android/iPhone/Nokia Mobile/BlackBerry Playbook`\n\n## Limitations\n\n* See [New Window\nSample](https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/webview-samples/new-window)\n\n## Resources\n\n* [Webview New Window API](https://developer.chrome.com/apps/tags/webview#event-newwindow)\n* [User Agent API](https://developer.chrome.com/apps/tags/webview#method-setUserAgentOverride)\n* [Webview](http://developer.chrome.com/apps/app_external#webview)\n* [Permissions](http://developer.chrome.com/apps/manifest#permissions)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/webview-samples/new-window-user-agent/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window-user-agent/browser.css",
    "content": "body {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n  font-family: Lucida Grande, Arial, sans-serif;\n}\n\nbutton,\ninput {\n  outline: none;\n}\n\ndiv {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n#content-container {\n  display: inline-block;\n  position: relative;\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n#controls {\n  padding: 0px;\n  background-color: #eee;\n  border-bottom: solid 1px #ccc;\n}\n\n#controls button,\n#controls input {\n  font-size: 14px;\n  line-height: 24px;\n  border-radius: 2px;\n  padding: 0 6px;\n}\n\n#controls button#reload {\n  border-radius: 16px;\n}\n\n#tab-controls {\n  padding: 3px 3px 0px 3px;\n  background: #888;\n}\n\n#browser-controls {\n  padding: 3px;\n}\n\nbutton,\ninput[type=\"submit\"],\nbutton[disabled]:hover {\n  border: solid 1px transparent;\n  background: transparent;\n}\n\nbutton:hover,\ninput[type=\"submit\"]:hover {\n  border-color: #ccc;\n  background: -webkit-linear-gradient(bottom, #cccccc 0%, #f2f2f2 99%);\n}\n\nbutton:active,\ninput[type=\"submit\"]:active {\n  border-color: #bbb;\n  background: -webkit-linear-gradient(bottom, #e2e2e2 0%, #bbbbbb 99%);\n}\n\n/* These glyphs are on the small side, make them look more natural when\ncompared to the back/forward buttons */\n#controls #home {\n  font-size: 24px;\n}\n\n#controls #reload {\n  font-size: 20px;\n}\n\n#location {\n  border: solid 1px #ccc;\n  padding: 2px;\n  width: 100%;\n  -webkit-box-sizing: border-box;\n}\n\n#browser-controls {\n  display: -webkit-flex;\n  -webit-flex-direction: column;\n}\n\n#browser-controls #location-form {\n  -webkit-flex: 1;\n  display: -webkit-flex;\n  -webit-flex-direction: column;\n}\n\n#browser-controls #center-column {\n  -webkit-flex: 1;\n}\n\nwebview,\n.webview-container {\n  display: inline-block;\n  padding: 0px;\n  margin: 0px;\n  border: 0px;\n  position: absolute;\n  top: 0px;\n  left: 0px;\n  visibility: hidden;\n}\n\n.selected,\n#content-container .selected {\n  visibility: visible;\n}\n\n.webview-container ul {\n  position: relative;\n  text-align: right;\n  padding: 0px;\n  margin: 0px;\n  z-index: 2;\n  list-style-type: none;\n}\n\n.webview-container ul li {\n  padding: 3px;\n  background: #ff7;\n  border-bottom: solid 1px #aa6;\n}\n\nwebview {\n  z-index: 1;\n}\n\n.popup-allow {\n  color: #0a0;\n  font-weight: bold;\n  text-decoration: none;\n}\n\n.popup-allow:hover {\n  color: #0f0;\n  font-weight: bold;\n  text-decoration: none;\n}\n\n.popup-deny {\n  color: #a00;\n  font-weight: bold;\n  text-decoration: none;\n}\n\n.popup-deny:hover {\n  color: #f00;\n  font-weight: bold;\n  text-decoration: none;\n}\n\n/* The reload button turns into a spinning trobber */\n.loading #reload {\n  -webkit-animation: spinner-animation .5s infinite linear;\n  -webkit-transform-origin: 50% 55.5%;\n}\n\n@-webkit-keyframes spinner-animation {\n  0% { -webkit-transform: rotate(0deg); }\n  100% {-webkit-transform: rotate(360deg); }\n}\n\n#tab-container {\n  margin: 5px 5px 0px 5px;\n  padding: 0px;\n  display: inline-block;\n}\n\n#tab-container li {\n  display: inline-block;\n  position: relative;\n  vertical-align: bottom;\n  width: 100px;\n  margin: 0px;\n  padding: 6px 16px 6px 6px;\n  border: 0px;\n  background: #ccc;\n}\n\n#tab-container li:hover {\n  background: #ddd;\n}\n\n#tab-container li.selected {\n  background: #eee;\n}\n\n#tab-container li p {\n  width: 100px;\n  float:left;\n  z-index: 1;\n  white-space: nowrap;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  margin: 0px;\n  padding: 0px;\n  -webkit-margin-before: 0px;\n  -webkit-margin-after: 0px;\n}\n\n#tab-container li a {\n  position: absolute;\n  right: 2px;\n  z-index: 2;\n  padding-left: 1px;\n  padding-right: 1px;\n  color: #666;\n  font-weight: bold;\n  text-decoration: none;\n  cursor: default;\n}\n\n#tab-container li a:hover {\n  color: #000;\n}\n\n#tab-container li#new-tab {\n  background: transparent;\n  vertical-align: baseline;\n  display: inline;\n}\n\n#tab-container li#new-tab a {\n  font-size: 24px;\n  padding: 0px;\n}\n\n/* Classes for general lightbox overlay */\n\n.trim {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n.full {\n  width: 100%;\n  height: 100%;\n}\n\n.padded {\n  padding: 10px;\n}\n\n.flex-container {\n  display: flex;\n}\n\n.row {\n  flex-direction: row;\n}\n\n.column {\n  flex-direction: column;\n}\n\n.center {\n  align-items: center;\n}\n\n.center-text {\n  text-align: center;\n}\n\n.flex {\n  flex-grow: 1;\n  flex-shrink: 1;\n}\n\n.flex-wide {\n  flex-grow: 4;\n  flex-shrink: 1;\n}\n\n.flex-narrow {\n  flex-grow: 1;\n  flex-shrink: 4;\n  width: 300px;\n}\n\n.rel {\n  position: relative;\n}\n\n.abs {\n  position: absolute;\n}\n\n.abs-full {\n  position: absolute;\n  top: 0px;\n  right: 0px;\n  bottom: 0px;\n  left: 0px;\n}\n\n.lightbox-overlay {\n  opacity: 0.5;\n  background: #000;\n}\n\n.lightbox {\n  padding: 20px;\n  margin: 20px;\n  background: #fff;\n  border-radius: 5px;\n}\n\n.hide {\n  visibility: hidden;\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window-user-agent/browser.html",
    "content": "<!DOCTYPE html>\n<html class=\"trim full\">\n  <head>\n    <link rel=\"stylesheet\" href=\"browser.css\">\n    <script src=\"config.js\"></script>\n    <script src=\"popup.js\"></script>\n    <script src=\"context_menu.js\"></script>\n    <script src=\"tabs.js\"></script>\n    <script src=\"browser.js\"></script>\n    <script src=\"browser_main.js\"></script>\n  </head>\n  <body class=\"trim full\">\n    <div id=\"controls\">\n\n      <div id=\"tab-controls\">\n        <ul id=\"tab-container\">\n          <li id=\"new-tab\"><a href=\"#new-tab\">+</a></li>\n        </ul>\n      </div>\n\n      <div id=\"browser-controls\">\n        <button id=\"back\" title=\"Go Back\">&#9664;</button>\n        <button id=\"forward\" title=\"Go Forward\">&#9654;</button>\n        <button id=\"home\" title=\"Go Home\">&#8962;</button>\n        <button id=\"reload\" title=\"Reload\">&#10227;</button>\n\n        <form id=\"location-form\">\n          <div id=\"center-column\">\n            <input id=\"location\" type=\"text\" value=\"\">\n          </div>\n          <input type=\"submit\" value=\"Go\">\n        </form>\n      </div>\n\n    </div>\n\n    <div id=\"content-container\">\n    </div>\n\n    <div id=\"lightbox-overlay\" class=\"full trim abs abs-full lightbox-overlay hide\">\n    </div>\n\n    <div id=\"lightbox\" class=\"full trim abs abs-full flex-container column center hide\">\n      <div class=\"flex flex-container row center\">\n        <div class=\"flex flex-container column center lightbox\">\n          <h1 class=\"flex center-text\">Chrome Feature Not Supported</h1>\n          <div class=\"flex center-text\">\n            The feature highlighted by this sample app is not supported in\n            your version of Chrome. Make sure your browser is up to date. If\n            you still see this message after updating your browser, try\n            installing\n            a <a href=\"http://www.chromium.org/getting-involved/dev-channel\"\n            target=\"_blank\">dev channel</a> build of Chrome.\n          </div>\n        </div>\n      </div>\n    </div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window-user-agent/browser.js",
    "content": "var browser = (function(configModule, tabsModule) {\n  var dce = function(str) { return document.createElement(str); };\n\n  var Browser = function(\n    controlsContainer,\n    back,\n    forward,\n    home,\n    reload,\n    locationForm,\n    locationBar,\n    tabContainer,\n    contentContainer,\n    newTabElement) {\n    this.controlsContainer = controlsContainer;\n    this.back = back;\n    this.forward = forward;\n    this.reload = reload;\n    this.home = home;\n    this.locationForm = locationForm;\n    this.locationBar = locationBar;\n    this.tabContainer = tabContainer;\n    this.contentContainer = contentContainer;\n    this.newTabElement = newTabElement;\n    this.tabs = new tabsModule.TabList(\n        'tabs',\n        this,\n        tabContainer,\n        contentContainer,\n        newTabElement);\n\n    this.init();\n  };\n\n  Browser.prototype.init = function() {\n    (function(browser) {\n      window.addEventListener('resize', function(e) {\n        browser.doLayout(e);\n      });\n\n      window.addEventListener('keydown', function(e) {\n        browser.doKeyDown(e);\n      });\n\n      browser.back.addEventListener('click', function(e) {\n        browser.tabs.getSelected().goBack();\n      });\n\n      browser.forward.addEventListener('click', function() {\n        browser.tabs.getSelected().goForward();\n      });\n\n      browser.home.addEventListener('click', function() {\n        browser.tabs.getSelected().navigateTo(configModule.homepage);\n      });\n\n      browser.reload.addEventListener('click', function() {\n        var tab = browser.tabs.getSelected();\n        if (tab.isLoading()) {\n          tab.stopNavigation();\n        } else {\n          tab.doReload();\n        }\n      });\n      browser.reload.addEventListener(\n        'webkitAnimationIteration',\n        function() {\n          // Between animation iterations: If loading is done, then stop spinning\n          if (!browser.tabs.getSelected().isLoading()) {\n            document.body.classList.remove('loading');\n          }\n        }\n      );\n\n      browser.locationForm.addEventListener('submit', function(e) {\n        e.preventDefault();\n        browser.tabs.getSelected().navigateTo(browser.locationBar.value);\n      });\n\n      browser.newTabElement.addEventListener(\n        'click',\n        function(e) { return browser.doNewTab(e); });\n\n      window.addEventListener('message', function(e) {\n        if (e.data) {\n          var data = JSON.parse(e.data);;\n          var type = data.type;\n          if (type == 'titleResponse') {\n            if (data.tabName && data.title) {\n              browser.tabs.setLabelByName(data.tabName, data.title);\n            } else {\n              console.warn(\n                  'Warning: Expected message from guest to contain {tabName, title}, but got:',\n                  data);\n            }\n          } else {\n            console.warn('Warning: Unexpected message received', e);\n          }\n        } else {\n          console.warn('Warning: Empty message (no data) received', e);\n        }\n      });\n\n      var webview = dce('webview');\n      var tab = browser.tabs.append(webview);\n\n      // Globals window.userAgent and/or window.newWindowEvent may be injected\n      // by opener\n      if (window.userAgent) {\n        webview.setUserAgentOverride(window.userAgent);\n      }\n      if (window.newWindowEvent) {\n        window.newWindowEvent.window.attach(webview);\n      } else {\n        tab.navigateTo(configModule.homepage);\n      }\n      browser.tabs.selectTab(tab);\n    }(this));\n  };\n\n  Browser.prototype.doLayout = function(e) {\n    var controlsHeight = this.controlsContainer.offsetHeight;\n    var windowWidth = document.documentElement.clientWidth;\n    var windowHeight = document.documentElement.clientHeight;\n    var contentWidth = windowWidth;\n    var contentHeight = windowHeight - controlsHeight;\n\n    var tab = this.tabs.getSelected();\n    var webview = tab.getWebview();\n    var webviewContainer = tab.getWebviewContainer();\n\n    var layoutElements = [\n      this.contentContainer,\n      webviewContainer,\n      webview];\n    for (var i = 0; i < layoutElements.length; ++i) {\n      layoutElements[i].style.width = contentWidth + 'px';\n      layoutElements[i].style.height = contentHeight + 'px';\n    }\n  };\n\n  // New window that is NOT triggered by existing window\n  Browser.prototype.doNewTab = function(e) {\n    var tab = this.tabs.append(dce('webview'));\n    tab.navigateTo(configModule.homepage);\n    this.tabs.selectTab(tab);\n    return tab;\n  };\n\n  Browser.prototype.doKeyDown = function(e) {\n    if (e.ctrlKey) {\n      switch(e.keyCode) {\n        // Ctrl+T\n        case 84:\n        this.doNewTab();\n        break;\n        // Ctrl+W\n        case 87:\n        e.preventDefault();\n        this.tabs.removeTab(this.tabs.getSelected());\n        break;\n      }\n      // Ctrl + [1-9]\n      if (e.keyCode >= 49 && e.keyCode <= 57) {\n        var idx = e.keyCode - 49;\n        if (idx < this.tabs.getNumTabs()) {\n          this.tabs.selectIdx(idx);\n        }\n      }\n    }\n  };\n\n  Browser.prototype.doTabNavigating = function(tab, url) {\n    if (tab.selected) {\n      document.body.classList.add('loading');\n      this.locationBar.value = url;\n    }\n  };\n\n  Browser.prototype.doTabNavigated = function(tab, url) {\n    this.updateControls();\n  };\n\n  Browser.prototype.doTabSwitch = function(oldTab, newTab) {\n    this.updateControls();\n  };\n\n  Browser.prototype.updateControls = function() {\n    var selectedTab = this.tabs.getSelected();\n    if (selectedTab.isLoading()) {\n      document.body.classList.add('loading');\n    }\n    var selectedWebview = selectedTab.getWebview();\n    this.back.disabled = !selectedWebview.canGoBack();\n    this.forward.disabled = !selectedWebview.canGoForward();\n    if (this.locationBar.value != selectedTab.url) {\n      this.locationBar.value = selectedTab.url;\n    }\n  };\n\n  return {'Browser': Browser};\n})(config, tabs);\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window-user-agent/browser_main.js",
    "content": "var mainBrowser = null;\n(function(browserModule) {\n  var query = function(str) { return document.querySelector(str); };\n\n  window.addEventListener('load', function(e) {\n    var webview = document.createElement('webview');\n\n    // Check for context menu API\n    if (webview.contextMenus) {\n      mainBrowser = new browserModule.Browser(\n          query('#controls'),\n          query('#back'),\n          query('#forward'),\n          query('#home'),\n          query('#reload'),\n          query('#location-form'),\n          query('#location'),\n          query('#tab-container'),\n          query('#content-container'),\n          query('#new-tab'));\n    } else {\n      // When API not available, show lightbox\n      query('#lightbox-overlay').classList.remove('hide');\n      query('#lightbox').classList.remove('hide');\n    }\n  });\n})(browser);\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window-user-agent/config.js",
    "content": "// Global configuration variables\nvar config = {\n  'homepage': 'http://www.google.com/',\n  'popupConfirmBox': {\n    'innerHTML': 'This webpage would like to open a window at <span class=\"popup-url\"></span> Would you like to allow this popup? <a href=\"#popup-allow\" class=\"popup-allow\">Allow</a> <a href=\"#popup-deny\" class=\"popup-deny\">Deny</a>',\n    'urlSpanClass': 'popup-url',\n    'acceptLinkClass': 'popup-allow',\n    'denyLinkClass': 'popup-deny'\n  },\n  'browsers': {\n    'android': 'Android',\n    'ios': 'iPhone',\n    'nokia': 'Nokia Mobile',\n    'bb-playbook': 'BlackBerry Playbook'\n  },\n  'browserUserAgents': {\n    'android': 'Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30',\n    'ios': 'Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3',\n    'nokia': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)',\n    'bb-playbook': 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML, like Gecko) Version/7.2.1.0 Safari/536.2+'\n  }\n};\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window-user-agent/context_menu.js",
    "content": "var contextMenu = (function(configModule) {\n  var ContextMenu = function(webview, popupConfirmBoxList) {\n    this.webview = webview;\n    this.popupConfirmBoxList = popupConfirmBoxList;\n    this.oneTimeUserAgentTable = {};\n\n    (function(menu) {\n      menu.webview.contextMenus.create({\n        'contexts': ['link'],\n        'id': 'newWindow',\n        'title': 'Open link in new window as...'\n      });\n      menu.webview.contextMenus.create({\n        'contexts': ['link'],\n        'id': 'newTab',\n        'title': 'Open link in new tab as...'\n      });\n\n      menu.webview.contextMenus.create({\n        'contexts': ['link'],\n        'id': 'newWindowDefault',\n        'title': 'Default browser',\n        'parentId': 'newWindow',\n        'onclick': function(e) { menu.doNewWindow(e); }\n      });\n      menu.webview.contextMenus.create({\n        'contexts': ['link'],\n        'type': 'separator',\n        'parentId': 'newWindow'\n      });\n      menu.webview.contextMenus.create({\n        'contexts': ['link'],\n        'id': 'newTabDefault',\n        'title': 'Default browser',\n        'parentId': 'newTab',\n        'onclick': function(e) { menu.doNewTab(e); }\n      });\n      menu.webview.contextMenus.create({\n        'contexts': ['link'],\n        'type': 'separator',\n        'parentId': 'newTab'\n      });\n      menu.webview.contextMenus.create({\n        'type': 'separator',\n        'parentId': 'newTab'\n      });\n\n      for (var key in configModule.browsers) {\n        (function(key, browserName) {\n          menu.webview.contextMenus.create({\n            'contexts': ['link'],\n            'id': 'newWindow_' + key,\n            'title': browserName,\n            'parentId': 'newWindow',\n            'onclick': function(e) { menu.doNewWindow(e, key); }\n          });\n          menu.webview.contextMenus.create({\n            'contexts': ['link'],\n            'id': 'newTab_' + key,\n            'title': browserName,\n            'parentId': 'newTab',\n            'onclick': function(e) { menu.doNewTab(e, key); }\n          });\n        }(key, configModule.browsers[key]));\n      }\n    }(this));\n  };\n\n  ContextMenu.prototype.doNewWindow = function(e, browser) {\n    var url = e.linkUrl;\n    this.loadOnce(url, browser);\n    this.doWindowOpen(url);\n  };\n\n  ContextMenu.prototype.doNewTab = function(e, browser) {\n    var url = e.linkUrl;\n    var code = 'window.simulateMiddleClickUrl = ';\n    console.log(code);\n    this.loadOnce(url, browser);\n    this.doTabOpen(url);\n  };\n\n  ContextMenu.prototype.doWindowOpen = function(url) {\n    var data = {\n      'type': 'simulatePopup',\n      'url': url\n    };\n    this.webview.contentWindow.postMessage(JSON.stringify(data), '*');\n  };\n\n  ContextMenu.prototype.doTabOpen = function(url) {\n    var data = {\n      'type': 'simulateCtrlClick',\n      'url': url\n    };\n    this.webview.contentWindow.postMessage(JSON.stringify(data), '*');\n  };\n\n  ContextMenu.prototype.getId = function() {\n    return 'id-' + (new Date()).getTime();\n  };\n\n  ContextMenu.prototype.getWindowFeatures = function() {\n    return 'width=100,height=100,left=100,top=100';\n  };\n\n  ContextMenu.prototype.loadOnce = function(url, browser) {\n    var userAgent = configModule.browserUserAgents[browser];\n    // Unconditionally store URL in table so that existence in table is an\n    // indicator that we are loading this URL\n    this.oneTimeUserAgentTable[url] = userAgent;\n  };\n\n  ContextMenu.prototype.doOpen = function(url, webview) {\n    var userAgent = this.oneTimeUserAgentTable[url];\n    if (webview && userAgent) {\n      webview.setUserAgentOverride(this.oneTimeUserAgentTable[url]);\n    }\n    delete this.oneTimeUserAgentTable[url];\n  };\n\n  ContextMenu.prototype.getUserAgentOverride = function(url) {\n    return this.oneTimeUserAgentTable[url];\n  };\n\n  ContextMenu.prototype.isOpening = function(url) {\n    // Existence in oneTimeUserAgentTable is an indicator for opening a URL\n    return (url in this.oneTimeUserAgentTable);\n  };\n\n  return {'ContextMenu': ContextMenu};\n}(config));\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window-user-agent/guest_messaging.js",
    "content": "var webviewTitleInjectionComplete = false;\n(function() {\n  // Prevent multiple injection\n  if (!webviewTitleInjectionComplete) {\n    var embedder = null;\n    var tabName = null;\n    var listenersAreBound = false;\n    var title = null;\n    var postTitle = (function() {\n      return function(e) {\n        title = document.title;\n        var data = {\n          'type': 'titleResponse',\n          'tabName': tabName,\n          'title': title || '[no title]'\n        };\n        embedder.postMessage(JSON.stringify(data), '*');\n      };\n    }());\n    var bindEmbedder = function(e) {\n      embedder = e.source;\n    };\n    var bindTabName = function(data) {\n      if (data.tabName) {\n        tabName = data.tabName;\n      } else {\n        console.warn('Warning: Title message from embedder contains no tab name');\n      }\n    };\n\n    var simulateCtrlClick = function(url) {\n      var a = document.createElement('a');\n      a.href = url;\n      var e = document.createEvent('MouseEvents');\n      e.initMouseEvent(\n          'click', // type\n          true,    // canBuble\n          true,    // cancelable\n          window,  // view\n          0,       // detail\n          0,       // screenX\n          0,       // screenY\n          0,       // clientX\n          0,       // clientY\n          true,    // ctrlKey <-- Important: simulate ctrl-click\n          false,   // altKey\n          false,   // shiftKey\n          false,   // metaKey\n          0,       // button\n          null);   // relatedTarget\n      a.dispatchEvent(e);\n    };\n\n    var simulatePopup = function(url) {\n      window.open(\n          url,\n          'id-' + (new Date()).getTime(),\n          'width=100,height=100,left=100,top=100');\n    };\n\n    window.addEventListener('message', function(e) {\n      if (e.data) {\n        var data = JSON.parse(e.data);\n        var type = data.type;\n        if (type == 'titleRequest') {\n          if (!listenersAreBound) {\n            bindTabName(data);\n            bindEmbedder(e);\n\n            // Notify the embedder of every title change\n            var titleElement = document.querySelector('title');\n            if (titleElement) {\n              titleElement.addEventListener('change', postTitle);\n            } else {\n              console.warn('Warning: No <title> element to bind to');\n              postTitle();\n            }\n\n            // Ensure initial title notification\n            if (title === null) {\n              postTitle();\n            }\n\n            listenersAreBound = true;\n          }\n        } else if (type == 'simulateCtrlClick') {\n          simulateCtrlClick(data.url);\n        } else if (type == 'simulatePopup') {\n          simulatePopup(data.url);\n        } else {\n          console.warn('Warning: Unexpected message received', e);\n        }\n      } else {\n        console.warn('Warning: Empty message (no data) received', e);\n      }\n    });\n  }\n}());\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window-user-agent/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  runApp();\n});\n\n/**\n * Listens for the app restarting then re-creates the window.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n */\nchrome.app.runtime.onRestarted.addListener(function() {\n  runApp();\n});\n\n/**\n * Creates the window for the application.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nfunction runApp() {\n  chrome.app.window.create(\n    'browser.html',\n    {'id': 'initialBrowserWindowID', 'state': 'maximized'},\n    function(newWindow) {\n      // Do not inject meaningful window.newWindowEvent; browser will instead\n      // load the homepage\n      newWindow.contentWindow.newWindowEvent = null;\n    });\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window-user-agent/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"New Window + User Agent API Sample\",\n  \"minimum_chrome_version\": \"24.0.1307.0\",\n  \"version\": \"2.0\",\n  \"icons\": {\n    \"16\": \"icon_16.png\",\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"config.js\", \"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"contextMenus\",\n    \"webview\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window-user-agent/popup.js",
    "content": "var popup = (function(configModule) {\n  var dce = function(str) { return document.createElement(str); };\n\n  var cfg = configModule.popupConfirmBox;\n  var popupBoxTemplate = dce('li');\n  popupBoxTemplate.innerHTML = cfg.innerHTML;\n\n  var createPopup = function(event, userAgent) {\n    (function(event) {\n      // TODO: Inspect event for window.open()'s name and attributes to\n      // correctly manage:\n      // 1. Multiple popups in the same window (i.e., window.open() twice with\n      //    the same window name)\n      // 2. Set attributes of popup window (e.g., size, location)\n      chrome.app.window.create(\n          'browser.html',\n          function(newWindow) {\n            // Pass new window event through global: window.newWindowEvent.\n            // NOTE: Webview creation and event.window.attach(webview)\n            // cannot be performed in this context; that has to happen in the\n            // context of the new window.\n            newWindow.contentWindow.newWindowEvent = event;\n            if (userAgent) {\n              newWindow.contentWindow.userAgent = userAgent;\n            }\n          });\n    }(event));\n  };\n\n  var PopupConfirmBoxList = function(listElement) {\n    this.listElement = listElement;\n    this.list = [];\n  };\n\n  PopupConfirmBoxList.prototype.getListElement = function() {\n    return this.listElement;\n  };\n\n  PopupConfirmBoxList.prototype.append = function(event) {\n    var box = new PopupConfirmBox(this, event);\n    this.list.push(box);\n    this.listElement.appendChild(box.getBoxElement());\n  };\n\n  PopupConfirmBoxList.prototype.removeBox = function(box) {\n    for (var i = 0; i < this.list.length; ++i) {\n      if (this.list[i] == box) {\n        this.listElement.removeChild(box.getBoxElement());\n        this.list.splice(i, 1);\n        break;\n      }\n    }\n  };\n\n  var PopupConfirmBox = function(popupList, event) {\n    this.popupList = popupList;\n    this.event = event;\n    this.url = event.targetUrl;\n    this.boxElement = popupBoxTemplate.cloneNode(true);\n    this.initBoxElement();\n  };\n\n  PopupConfirmBox.prototype.initBoxElement = function() {\n    var urlSpan = this.boxElement.querySelector('.' + cfg.urlSpanClass);\n    var acceptLink = this.boxElement.querySelector('.' + cfg.acceptLinkClass);\n    var denyLink = this.boxElement.querySelector('.' + cfg.denyLinkClass);\n\n    urlSpan.innerText = this.url;\n\n    (function(box) {\n      acceptLink.addEventListener('click', function(e) { box.doAccept(); });\n      denyLink.addEventListener('click', function(e) { box.doDeny(); });\n    }(this));\n  };\n\n  PopupConfirmBox.prototype.getBoxElement = function() {\n    return this.boxElement;\n  };\n\n  PopupConfirmBox.prototype.doAccept = function() {\n    createPopup(this.event);\n    this.popupList.removeBox(this);\n    this.detach();\n  };\n\n  PopupConfirmBox.prototype.doDeny = function() {\n    this.event.window.discard();\n\n    this.popupList.removeBox(this);\n    this.detach();\n  };\n\n  PopupConfirmBox.prototype.detach = function() {\n    this.popupList = null;\n  };\n\n  return {\n    'createPopup': createPopup,\n    'PopupConfirmBoxList': PopupConfirmBoxList,\n    'PopupConfirmBox': PopupConfirmBox\n  };\n}(config));\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/new-window-user-agent/tabs.js",
    "content": "var tabs = (function(popupModule, contextMenuModule) {\n  var dce = function(str) { return document.createElement(str); };\n\n  var TabList = function(name, browser, tabContainer, contentContainer, newTabElement) {\n    this.name = name;\n    this.list = [];\n    this.table = {};\n    this.selected = 0;\n    this.tabNameCounter = 0;\n    this.browser = browser;\n    this.tabContainer = tabContainer;\n    this.contentContainer = contentContainer;\n    this.newTabElement = newTabElement;\n  };\n\n  TabList.prototype.getNumTabs = function() {\n    return this.list.length;\n  };\n\n  TabList.prototype.getTabIdx = function(tab) {\n    var idx = 0;\n    for (var i = 0; i < this.list.length; ++i) {\n      if (this.list[i] == tab) {\n        idx = i;\n        break;\n      }\n    }\n    if (idx < this.list.length) {\n      return idx;\n    } else {\n      console.warn('Warning: Failed to find tab in list', tab);\n      return -1;\n    }\n  };\n\n  TabList.prototype.selectIdx = function(idx) {\n    return this.selectTab(this.list[idx], idx);\n  };\n\n  TabList.prototype.selectTab = function(tab, idx) {\n    var prevTab = this.list[this.selected];\n    prevTab.deselect();\n\n    if (!(idx === 0 || idx)) {\n      idx = this.getTabIdx(tab);\n    }\n    this.selected = idx;\n\n    tab.select();\n    this.browser.doTabSwitch(prevTab, tab);\n    this.browser.doLayout();\n\n    return tab;\n  };\n\n  TabList.prototype.setLabelByName = function(tabName, tabLabel) {\n    if (tabName in this.table) {\n      return this.table[tabName].setLabel(tabLabel);\n    } else {\n      console.warn(\n          'Warning: Attempt to set label to \"', tabLabel,\n          '\" on unknown tab named \"', tabName, '\"');\n      return null;\n    }\n  };\n\n  TabList.prototype.append = function(webview) {\n    var tabName = this.name + '-' + this.tabNameCounter;\n    this.tabNameCounter = this.tabNameCounter + 1;\n    var tab = new Tab(tabName, this, webview);\n\n    this.list.push(tab);\n    this.table[tabName] = tab;\n\n    this.tabContainer.insertBefore(tab.labelContainer, this.newTabElement);\n    this.contentContainer.appendChild(tab.webviewContainer);\n\n    return tab;\n  };\n\n  TabList.prototype.removeIdx = function(idx) {\n    this.removeTab(this.list[idx], idx);\n  };\n\n  TabList.prototype.removeTab = function(tab, idx) {\n    if (this.list.length > 1) {\n      if (!(idx === 0 || idx)) {\n        idx = this.getTabIdx(tab);\n      }\n\n      var selectedIdx = this.selected;\n      if (tab.selected) {\n        // If this is the last tab, then select previous, else select next\n        selectedIdx = (this.selected + 1 == this.list.length) ?\n            this.selected - 1 :\n            this.selected + 1;\n        this.selectIdx(selectedIdx);\n      }\n\n      this.tabContainer.removeChild(tab.labelContainer);\n      this.contentContainer.removeChild(tab.webviewContainer);\n\n      tab.detach();\n      delete this.table[tab.name];\n      if (idx === 0 || idx) {\n        this.list.splice(idx, 1);\n      } else {\n        for (var i = 0; i < this.list.length; ++i) {\n          if (this.list[i] == tab) {\n            this.list.splice(i, 1);\n            break;\n          }\n        }\n      }\n\n      // If we are now selecting something that comes after the removed tab,\n      // then decrement the index: this.selected\n      if (selectedIdx > idx) {\n        this.selected = this.selected - 1;\n      }\n\n      return tab;\n    } else {\n      return null;\n    }\n  };\n\n  TabList.prototype.getSelected = function() {\n    return this.list[this.selected];\n  };\n\n  TabList.prototype.detach = function() {\n    this.browser = null;\n  };\n\n  var Tab = function(name, tabList, webview) {\n    this.name = name;\n    this.tabList = tabList;\n    this.selected = false;\n    this.url = '';\n    this.loading = true;\n    this.overlay = false;\n    this.labelContainer = dce('li');\n    this.label = dce('p');\n    this.closeLink = dce('a');\n    this.webviewContainer = dce('div');\n    this.popupConfirmBoxList = new popupModule.PopupConfirmBoxList(dce('ul'));\n    this.contextMenu = new contextMenuModule.ContextMenu(\n        webview,\n        this.popupConfirmBoxList);\n    this.webview = webview;\n    this.scriptInjectionAttempted = false;\n\n    this.initLabelContainer();\n    this.initWebview();\n  };\n\n  Tab.prototype.initLabelContainer = function() {\n    var name = this.name;\n    var labelContainer = this.labelContainer;\n    var label = this.label;\n    var closeLink = this.closeLink;\n\n    labelContainer.setAttribute('data-name', this.name);\n\n    this.setLabel('Loading...');\n\n    closeLink.href = '#close-' + name;\n    closeLink.innerText = 'X';\n\n    labelContainer.appendChild(label);\n    labelContainer.appendChild(closeLink);\n\n    (function(tab) {\n      labelContainer.addEventListener('click', function(e) {\n        if (tab.tabList) {\n          tab.tabList.selectTab(tab);\n        }\n      });\n      closeLink.addEventListener('click', function(e) {\n        if (tab.tabList) {\n          tab.tabList.removeTab(tab);\n        }\n      });\n    }(this));\n  };\n\n  Tab.prototype.initWebview = function() {\n    this.webview.setAttribute('data-name', this.name);\n    this.webviewContainer.setAttribute('data-name', this.name);\n    this.webviewContainer.classList.add('webview-container');\n\n    (function(tab) {\n      tab.webview.addEventListener(\n          'loadcommit',\n          function(e) { return tab.doLoadCommit(e); });\n      tab.webview.addEventListener(\n          'loadstop',\n          function(e) { return tab.doLoadStop(e); });\n      tab.webview.addEventListener(\n          'contentload',\n          function(e) { return tab.doContentLoad(e); });\n      tab.webview.addEventListener(\n          'newwindow',\n          function(e) { return tab.doNewTab(e); });\n    }(this));\n\n    this.webviewContainer.appendChild(this.popupConfirmBoxList.getListElement());\n    this.webviewContainer.appendChild(this.webview);\n  };\n\n  Tab.prototype.setLabel = function(newLabel) {\n    this.label.innerText = newLabel;\n  };\n\n  Tab.prototype.select = function() {\n    this.labelContainer.classList.add('selected');\n    this.webviewContainer.classList.add('selected');\n    this.webview.classList.add('selected');\n    this.selected = true;\n  };\n\n  Tab.prototype.deselect = function() {\n    this.labelContainer.classList.remove('selected');\n    this.webviewContainer.classList.remove('selected');\n    this.webview.classList.remove('selected');\n    this.selected = false;\n  };\n\n  Tab.prototype.detach = function() {\n    this.tabList = null;\n  };\n\n  Tab.prototype.getWebview = function() {\n    return this.webview;\n  };\n\n  Tab.prototype.getWebviewContainer = function() {\n    return this.webviewContainer;\n  };\n\n  Tab.prototype.isLoading = function() {\n    return this.loading;\n  };\n\n  Tab.prototype.doLoadCommit = function(e) {\n    if (!e.isTopLevel) {\n      return;\n    }\n\n    this.loading = true;\n    this.scriptInjectionAttempted = false;\n    this.url = e.url;\n    this.tabList.browser.doTabNavigating(this, e.url);\n  };\n\n  Tab.prototype.doLoadStop = function(e) {\n    if (this.loading) {\n      this.tabList.browser.doTabNavigated(this, this.url);\n    }\n    this.loading = false;\n  };\n\n  Tab.prototype.doContentLoad = function(e) {\n    if (!this.scriptInjectionAttempted) {\n      // Try to inject title-update-messaging script\n      (function(tab) {\n        tab.webview.executeScript(\n            {'file': 'guest_messaging.js'},\n            function(results) { return tab.doScriptInjected(results); });\n      }(this));\n      this.scriptInjectionAttempted = true;\n    }\n  };\n\n  Tab.prototype.doScriptInjected = function(results) {\n    if (!results || !results.length) {\n      console.warn(\n          'Warning: Failed to inject guest_messaging.js',\n          this.webview);\n    } else {\n      // Send a message to the webview so it can get a reference to\n      // the embedder\n      var data = {\n        'type': 'titleRequest',\n        'tabName': this.name\n      };\n      this.webview.contentWindow.postMessage(JSON.stringify(data), '*');\n    }\n  };\n\n  // New window triggered by existing window\n  Tab.prototype.doNewTab = function(e) {\n    e.preventDefault();\n\n    var dis = e.windowOpenDisposition;\n    var url = e.targetUrl;\n    var userAgent = this.contextMenu.getUserAgentOverride(url);\n\n    if (dis == 'new_background_tab' || dis == 'new_foreground_tab') {\n      var newWebview = dce('webview');\n      e.window.attach(newWebview);\n\n      // Allow context menu to manipulate webview if necessary\n      if (this.contextMenu.isOpening(url)) {\n        this.contextMenu.doOpen(url, newWebview);\n      }\n\n      var newTab = this.tabList.append(newWebview);\n      if (e.windowOpenDisposition == 'new_foreground_tab') {\n        this.tabList.selectTab(newTab);\n      }\n    } else {\n      // If a context menu selection caused the popup, create it immediately;\n      // otherwise, use interstitial confirmation box\n      if (this.contextMenu.isOpening(url)) {\n        this.contextMenu.doOpen(url);\n        popupModule.createPopup(e, userAgent);\n      } else {\n        this.popupConfirmBoxList.append(e);\n      }\n    }\n  };\n\n  Tab.prototype.stopNavigation = function() {\n    this.webview.stop();\n  };\n\n  Tab.prototype.doReload = function() {\n    this.webview.reload();\n  };\n\n  Tab.prototype.goBack = function() {\n    this.webview.back();\n  };\n\n  Tab.prototype.goForward = function() {\n    this.webview.forward();\n  };\n\n  Tab.prototype.navigateTo = function(url) {\n    this.stopNavigation();\n    this.webview.src = url;\n  };\n\n  return {\n    'TabList': TabList,\n    'Tab': Tab\n  };\n}(popup, contextMenu));\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/shared-script/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/cbdacningpambfjjejgfebeagmhpdcko\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Accessing the main world with `<webview>`.executeScript()\n\nWeb view content scripts run in *an isolated world*. This means that they can\naccess the current page's DOM, but cannot share objects with scripts included\nin the DOM because scripts in the DOM run in the *main world*. For a more\ndetailed explanation, checkout [this\nvideo](https://www.youtube.com/watch?v=laLudeUmXHM).\n\nRunning in an isolated world is usually what the developer wants because\naccess to the DOM is enough. Sometimes, the developer may want to access\nJavascript objects in the main world. This sample shows good and bad examples\nof injecting Javascript into a `<webview>` that is intended to run in the\nmain world. To do this correctly, content script must create a `<script>` tag\nand inject it into the DOM. Then, the script contained within the `<script>`\ntag will be run in the main world.\n\nThe sample shows a page that contains an animated dragon. The injected script\nadds the ability to construct dragons that animate in sync. In order to do\nso, the script needs access to the `Dragon`\n[FOAM](http://foam-framework.github.io/foam/) model. To gain access, the\ninjected script inserts a `<script>` tag into the DOM.\n\nThe sample contains two app windows: *Incorrect injection* attempts to inject\nthe script directly and *Correct injection* injects the script into a\n`<script>` tag in the DOM.\n\n## Resources\n\n* [Video about isolated worlds](https://www.youtube.com/watch?v=laLudeUmXHM)\n* [Webview](http://developer.chrome.com/apps/app_external#webview)\n* [FOAM](http://foam-framework.github.io/foam/)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/webview-samples/shared-script/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/shared-script/app.css",
    "content": "webview,\n.flex-item {\n  flex-grow: 1;\n  flex-shrink: 1;\n}\n\n.trim {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n.padded {\n  padding: 10px;\n}\n\n.full {\n  width: 100%;\n  height: 100%;\n}\n\n.flex-container {\n  display: flex;\n}\n\n.row {\n  flex-direction: row;\n}\n\n.column {\n  flex-direction: column;\n}\n\n.left {\n  text-align: left;\n}\n\n.right {\n  text-align: right;\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/shared-script/correct_injection.html",
    "content": "<!DOCTYPE html>\n<html class=\"trim full\">\n  <head>\n    <title>Correct injection</title>\n    <link rel=\"stylesheet\" href=\"app.css\">\n    <script type=\"text/javascript\" src=\"more_dragons.js\"></script>\n    <script type=\"text/javascript\" src=\"correct_injection.js\"></script>\n  </head>\n  <body class=\"trim full\">\n    <webview class=\"trim full\" src=\"http://foam-framework.github.io/foam/demos/Dragon.html\"></webview>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/shared-script/correct_injection.js",
    "content": "// This is an example of what to do when we need access to objects created by\n// scripts embedded in the DOM. Keep in mind that usually we do NOT need access\n// to such objects, and this sample illustrates a special case.\n\n// Generated for script text that injects a script tag into the DOM. The script\n// tag will contain the script we intend to run wrapped in an anonymous\n// function. This way, the script we wish to run can access the guest page\n// scripting context.\nfunction generateScriptText(fn) {\n\n  // fn is going to be interpreted as a quoted string literal. As such, we need\n  // to escape double-quotes in the string, and either:\n  // (a) strip newlines and comments, or\n  // (b) replace newlines with the character sequence \"\\n\" (a slash followed by\n  //     an n) and allow comments to be parsed as part of the function.\n\n  // (a):\n  // var fnText = fn.toString()\n  //   .replace(/\"/g, '\\\\\"')                         // Escape double-quotes.\n  //   .replace(/[/][/].*\\r?\\n/g, ' ')               // Rmv single-line comments.\n  //   .replace(/\\r?\\n|\\r/g, ' ')                    // Rmv newlines.\n  //   .replace(/[/][*]((?![*][/]).)*[*][/]/g, ' '); // Rmv multi-line comments.\n\n  // (b):\n  var fnText = fn.toString()\n    .replace(/\"/g, '\\\\\"')           // Escape double-quotes.\n    .replace(/(\\r?\\n|\\r)/g, '\\\\n'); // Insert newlines correctly.\n\n  var scriptText =\n      '(function() {\\n' +\n      '  var script = document.createElement(\"script\");\\n' +\n      '  script.innerHTML = \"(function() { (' + fnText + ')(); })()\" \\n'+\n      '  document.body.appendChild(script);\\n' +\n      '})()';\n  return scriptText;\n}\n\n// When our app loads, setup a listener that will execute our script after the\n// target guest page has loaded.\nwindow.addEventListener('load', function() {\n  var webview = document.querySelector('webview');\n  webview.addEventListener('loadstop', function() {\n    if (webview.src === 'http://foam-framework.github.io/foam/demos/Dragon.html') {\n      webview.executeScript({ code: generateScriptText(addMoreDragons) });\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/shared-script/incorrect_injection.html",
    "content": "<!DOCTYPE html>\n<html class=\"trim full\">\n  <head>\n    <title>Incorrect injection</title>\n    <link rel=\"stylesheet\" href=\"app.css\">\n    <script type=\"text/javascript\" src=\"more_dragons.js\"></script>\n    <script type=\"text/javascript\" src=\"incorrect_injection.js\"></script>\n  </head>\n  <body class=\"trim full\">\n    <webview class=\"trim full\" src=\"http://foam-framework.github.io/foam/demos/Dragon.html\"></webview>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/shared-script/incorrect_injection.js",
    "content": "// This is an example of what NOT to do when we need access to objects created\n// by scripts embedded in the DOM. Keep in mind that usually we do NOT need\n// access to such objects, and this sample illustrates a special case.\n\n// When our app loads, setup a listener that will execute our script after the\n// target guest page has loaded.\nwindow.addEventListener('load', function() {\n  var webview = document.querySelector('webview');\n  webview.addEventListener('loadstop', function() {\n    if (webview.src === 'http://foam-framework.github.io/foam/demos/Dragon.html') {\n      // What NOT to do: addMoreDragons depends on objects in the guest page\n      // scripting context, but content scripts run in an \"isolated world\" that\n      // can only access the document (and no other shared Javascript objects).\n      // See correct_injection.js for an example of what to do.\n      var scriptText = '(' + addMoreDragons.toString() + ')();';\n      webview.executeScript({ code: scriptText });\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/shared-script/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  runApp();\n});\n\n/**\n * Listens for the app restarting then re-creates the window.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n */\nchrome.app.runtime.onRestarted.addListener(function() {\n  runApp();\n});\n\n/**\n * Creates the window for the application.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nfunction runApp() {\n  chrome.app.window.create('correct_injection.html', {'id': 'goodWindowID'},\n    function(appGoodWindow) {\n      var offset = 20;\n      var badWindowOuterBounds = {\n        'left': appGoodWindow.outerBounds.left + offset,\n        'top': appGoodWindow.outerBounds.top + offset\n      };\n      chrome.app.window.create('incorrect_injection.html', {'id': 'badWindowID', 'outerBounds': badWindowOuterBounds});\n    }\n  );\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/shared-script/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Shared Script Sample: More Dragons!\",\n  \"minimum_chrome_version\": \"24.0.1307.0\",\n  \"version\": \"2.0\",\n  \"icons\": {\n    \"16\": \"icon_16.png\",\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"webview\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/shared-script/more_dragons.js",
    "content": "// Starting zoom for new dragons\nvar baseZoom = 1;\n\n// Function to be run in the context of the webview guest page:\n//\n// The demo page has an animated dragon. Add a button, styled consistent with\n// the page, labeled 'More dragons!' that will instantiate more dragons hooked\n// up to the same animation timer.\nfunction addMoreDragons() {\n  var zoom = 1.0;\n  // Create the button.\n  var bttn = document.createElement(\"button\");\n  /*\n   * Style the button to get a consistent look and feel.\n   */\n  bttn.innerText = 'More dragons!';\n  bttn.classList.add('actionButton');\n  bttn.setAttribute('style', 'padding: 10px; margin: 10px; display: block;');\n  /*\n   * Hook up the button to add more dragons to the page.\n   */\n  bttn.addEventListener('click', function() {\n    // Add a new dragon.\n    var newDragon = Dragon.create({ timer: $('timer'), width: 950, height: 1000});\n    this.insertAdjacentHTML('afterend', newDragon.toHTML());\n    newDragon.initHTML();\n\n    // Scale down dragons.\n    zoom *= 0.75;\n    var timerID = $('timer').id;\n    var dragons = document.querySelectorAll('canvas');\n    var dragonsArr = Array.prototype.slice.call(dragons, 0);\n\n    // The last canvas is the timer, not a dragon.\n    dragonsArr.pop();\n\n    dragonsArr.forEach(function(dragonCanvas) {\n      dragonCanvas.style.zoom = zoom;\n    });\n\n  }.bind(bttn));\n  // Add the button to the DOM.\n  document.body.insertBefore(bttn, document.body.firstChild);\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/user-agent/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/fbkdeonndngdbojbccanjnpnlpdmgchc\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# User Agent Override\n\nSample that shows how to use the [webview\ntag](http://developer.chrome.com/apps/app_external#webview) in an app to\ncreate a browser with multiple personalities. The browser [overrides the user\nagent\nstring](https://developer.chrome.com/apps/tags/webview#method-setUserAgentOverride)\nfor multiple views of the same webpage.\n\nThe app's main window contains a series of `<webview>`s that are sized to fit\nmost of it (via the `width` and `height` attributes). Clicking links, the\nnavigation control buttons, or entering an address in the location bar\nupdate the `src` attribute of all webviews.\n\n`<webview>` is the preferred way for you to load web content into your\napp. It runs in a separate process and has its own storage, ensuring the\nsecurity and reliability of your application.\n\n## Resources\n\n* [Webview](http://developer.chrome.com/apps/app_external#webview)\n* [Permissions](http://developer.chrome.com/apps/manifest#permissions)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/webview-samples/user-agent/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/user-agent/browser.css",
    "content": "body {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n  font-family: Lucida Grande, Arial, sans-serif;\n}\n\nbutton,\ninput {\n  outline: none;\n}\n\ndiv {\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n.content-container,\n.webview-container {\n  display: inline-block;\n  position: relative;\n  margin: 0px;\n  padding: 0px;\n  border: 0px;\n}\n\n#content-overlay,\n.webview-overlay {\n  background: #000;\n  opacity: 0.5;\n  visibility: hidden;\n}\n\n#content-overlay {\n  z-index: 2;\n}\n\n.webview-overlay {\n  z-index: 1;\n}\n\n#controls {\n  padding: 3px;\n  border-bottom: solid 1px #ccc;\n  background-color: #eee;\n}\n\n#controls button,\n#controls input {\n  font-size: 14px;\n  line-height: 24px;\n  border-radius: 2px;\n  padding: 0 6px;\n}\n\n#controls button#reload {\n  border-radius: 16px;\n}\n\nbutton,\ninput[type=\"submit\"],\nbutton[disabled]:hover {\n  border: solid 1px transparent;\n  background: transparent;\n}\n\nbutton:hover,\ninput[type=\"submit\"]:hover {\n  border-color: #ccc;\n  background: -webkit-linear-gradient(bottom, #cccccc 0%, #f2f2f2 99%);\n}\n\nbutton:active,\ninput[type=\"submit\"]:active {\n  border-color: #bbb;\n  background: -webkit-linear-gradient(bottom, #e2e2e2 0%, #bbbbbb 99%);\n}\n\n/* These glyphs are on the small side, make them look more natural when\ncompared to the back/forward buttons */\n#controls #home,\n#controls #terminate {\n  font-size: 24px;\n}\n\n#controls #reload {\n  font-size: 20px;\n}\n\n#controls #zoom,\n#controls #find {\n  font-size: 18px;\n}\n\n#location {\n  border: solid 1px #ccc;\n  padding: 2px;\n  width: 100%;\n  -webkit-box-sizing: border-box;\n}\n\n#controls {\n  display: -webkit-flex;\n  -webit-flex-direction: column;\n}\n\n#controls #location-form {\n  -webkit-flex: 1;\n  display: -webkit-flex;\n  -webit-flex-direction: column;\n}\n\n#controls #center-column {\n  -webkit-flex: 1;\n}\n\n#zoom-box,\n#find-box {\n  background-color: #eee;\n  border: solid 1px #ccc;\n  border-top: solid 1px #eee;\n  border-bottom-left-radius: 2px;\n  border-bottom-right-radius: 2px;\n  padding: 2px;\n\n  position: fixed;\n  top: 36px;\n  height: 25px;\n\n  display: none;\n}\n\n#zoom-box #zoom-form,\n#find-box #find-form {\n  -webkit-flex: 1;\n  display: -webkit-flex;\n  -webit-flex-direction: row;\n}\n\n#zoom-box input,\n#zoom-box button,\n#find-box button {\n  border-radius: 2px;\n}\n\n#zoom-box #zoom-text,\n#find-box #find-text {\n  border: solid 1px #ccc;\n  margin-right: 0px;\n  padding: 2px;\n  -webkit-box-sizing: border-box;\n  -webkit-flex: 1;\n}\n\n#zoom-box {\n  left: 5px;\n  width: 125px;\n  z-index: 3;\n}\n\n#zoom-box input[type=\"submit\"] {\n  font-size: 14px;\n  margin: 2px 0px;\n  padding: 0 2px 3px 2px;\n  width: 22px;\n}\n\n#zoom-box button {\n  font-size: 12px;\n  margin: 2px 0px;\n  padding: 0px 1px 0px 0px;\n  width: 20px;\n}\n\n#find-box {\n  right: 5px;\n  width: 500px;\n  z-index: 4;\n}\n\n#find-box #find-text {\n  border-right-style: none;\n  border-top-left-radius: 2px;\n  border-bottom-left-radius: 2px;\n}\n\n#find-box #find-results {\n  color: #888;\n  background-color: #fff;\n  border: solid 1px #ccc;\n  border-left-style: none;\n  border-top-right-radius: 2px;\n  border-bottom-right-radius: 2px;\n  margin: 2px 0px;\n  padding: 3px 4px 2px 0;\n  text-align: center;\n}\n\n#find-box #match-case {\n  margin: 2px 0px;\n  font-size: 10px;\n  width: 28px;\n}\n\n#find-box #find-backward,\n#find-box #find-forward {\n  font-size: 14px;\n  width: 24px;\n}\n\n.sad-webview,\n.webview-overlay,\nwebview {\n  display: inline-block;\n  padding: 0px;\n  margin: 0px;\n  border: 0px;\n  position: absolute;\n  top: 0px;\n  left: 0px;\n}\n\n#content-overlay {\n  display: inline-block;\n  padding: 0px;\n  margin: 0px;\n  border: 0px;\n  position: absolute;\n  top: 0px;\n  left: 0px;\n}\n\n\n.loading #content-overlay,\n[data-loading=\"t\"] .webview-overlay {\n  visibility: visible;\n}\n\n/* The reload button turns into a spinning trobber */\n.loading #reload {\n  -webkit-animation: spinner-animation .5s infinite linear;\n  -webkit-transform-origin: 50% 55.5%;\n}\n\n@-webkit-keyframes spinner-animation {\n  0% { -webkit-transform: rotate(0deg); }\n  100% {-webkit-transform: rotate(360deg); }\n}\n\n/* Due to http://crbug.com/156219 we can't use display: none */\n.sad-webview,\n.exited webview {\n  visibility: hidden;\n}\n\n.exited .sad-webview,\n.killed .sad-webview {\n  visibility: visible;\n  text-align: center;\n}\n\n\n.exited webview,\n.killed webview {\n  height: 0px;\n}\n\n.sad-webview h2 {\n  font-size: 14px;\n}\n\n.sad-webview p {\n  font-size: 11px;\n}\n\n.sad-webview-icon {\n  font-size: 96px;\n  margin-bottom: 10px;\n}\n\n/* Variant of the crashed page when the process is intentionally killed (in that\ncase we use a different background color and label). */\n.exited .sad-webview .killed-label {\n  display: none;\n}\n\n.killed .sad-webview {\n  background: #393058;\n}\n\n.killed .sad-webview .killed-label {\n  display: block;\n}\n\n.killed .sad-webview .crashed-label {\n  display: none;\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/user-agent/browser.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <link rel=\"stylesheet\" href=\"browser.css\">\n    <script src=\"config.js\"></script>\n    <script src=\"browser_bindings.js\"></script>\n    <script src=\"browser.js\"></script>\n  </head>\n  <body>\n    <div id=\"controls\">\n\n      <button id=\"back\" title=\"Go Back\">&#9664;</button>\n      <button id=\"forward\" title=\"Go Forward\">&#9654;</button>\n      <button id=\"home\" title=\"Go Home\">&#8962;</button>\n      <button id=\"reload\" title=\"Reload\">&#10227;</button>\n      <button id=\"terminate\" title=\"Simulate Crash\">&#9760;</button>\n\n      <form id=\"location-form\">\n        <div id=\"center-column\">\n          <input id=\"location\" type=\"text\" value=\"http://www.google.com/\">\n        </div>\n        <input type=\"submit\" value=\"Go\">\n      </form>\n\n      <button id=\"zoom\" title=\"Change Zoom\">&#128270;</button>\n      <button id=\"find\" title=\"Find in Page\">&#128294;</button>\n\n    </div>\n\n    <div id=\"zoom-box\">\n      <form id=\"zoom-form\">\n        <input id=\"zoom-text\" type=\"text\">\n        <input type=\"submit\" value=\"&#128270;\">\n        <button id=\"zoom-in\">&#10133;</button>\n        <button id=\"zoom-out\">&#10134;</button>\n      </form>\n    </div>\n\n    <div id=\"find-box\">\n      <form id=\"find-form\">\n        <input id=\"find-text\" type=\"text\">\n        <div id=\"find-results\">\n          <span class=\"results\" data-name=\"android\"></span> |\n          <span class=\"results\" data-name=\"ios\"></span> |\n          <span class=\"results\" data-name=\"nokia\"></span> |\n          <span class=\"results\" data-name=\"bb-playbook\"></span>\n        </div>\n        <input type=\"submit\" style=\"position:absolute; visibility:hidden\">\n        <button id=\"match-case\">aA</button>\n        <button id=\"find-backward\">&#60;</button>\n        <button id=\"find-forward\">&#62;</button>\n      </form>\n    </div>\n\n    <!-- Content contains containers for several webviews with different\n    user-agent strings. The `src` attribute is set via scripting. Each\n    webview lives in a different persistent partition to ensure that one is\n    rendered in its own process (see\n    https://developer.chrome.com/apps/tags/webview#partition for\n    details). -->\n\n    <div class=\"content-container\">\n      <div class=\"webview-container\" data-name=\"android\" data-width=\"0.33\"\n           data-height=\"0.5\" data-loading=\"\">\n        <webview id=\"android-webview\" class=\"webview\" data-name=\"android\"\n                 partition=\"persist:android\"></webview><!--\n        Comment-out whitespace\n        --><div class=\"sad-webview\" data-name=\"android\">\n          <div class=\"sad-webview-icon\">&#9762;</div>\n          <h2 class=\"crashed-label\">Aw, Snap!</h2>\n          <h2 class=\"killed-label\">He's Dead, Jim!</h2>\n          <p>Something went wrong while displaying this webpage.\n            To continue, reload or go to another page.</p>\n        </div><!--\n        Comment-out whitespace\n        --><div class=\"webview-overlay\" data-name=\"android\">&nbsp;</div>\n      </div>\n      <div class=\"webview-container\" data-name=\"ios\" data-width=\"0.33\"\n           data-height=\"0.5\" data-loading=\"\">\n        <webview id=\"ios-webview\" class=\"webview\" data-name=\"ios\"\n                 partition=\"persist:ios\"></webview><!--\n        Comment-out whitespace\n        --><div class=\"sad-webview\" data-name=\"ios\">\n          <div class=\"sad-webview-icon\">&#9762;</div>\n          <h2 class=\"crashed-label\">Aw, Snap!</h2>\n          <h2 class=\"killed-label\">He's Dead, Jim!</h2>\n          <p>Something went wrong while displaying this webpage.\n            To continue, reload or go to another page.</p>\n        </div><!--\n        Comment-out whitespace\n        --><div class=\"webview-overlay\" data-name=\"ios\">&nbsp;</div>\n      </div><!--\n      Comment-out whitespace\n      --><div class=\"webview-container\" data-name=\"nokia\" data-width=\"0.33\"\n              data-height=\"0.5\" data-loading=\"\">\n        <webview id=\"nokia-webview\" class=\"webview\" data-name=\"nokia\"\n                 partition=\"persist:nokia\"></webview><!--\n        Comment-out whitespace\n        --><div class=\"sad-webview\" data-name=\"nokia\">\n          <div class=\"sad-webview-icon\">&#9762;</div>\n          <h2 class=\"crashed-label\">Aw, Snap!</h2>\n          <h2 class=\"killed-label\">He's Dead, Jim!</h2>\n          <p>Something went wrong while displaying this webpage.\n            To continue, reload or go to another page.</p>\n        </div><!--\n        Comment-out whitespace\n        --><div class=\"webview-overlay\" data-name=\"nokia\">&nbsp;</div>\n      </div><!--\n      Comment-out whitespace\n      --><div class=\"webview-container\" data-name=\"bb-playbook\"\n              data-width=\"1.0\" data-height=\"0.5\" data-loading=\"\">\n        <webview id=\"bb-playbook-webview\" class=\"webview\"\n                 data-name=\"bb-playbook\"\n                 partition=\"persist:bb-playbook\"></webview><!--\n        Comment-out whitespace\n        --><div class=\"sad-webview\" data-name=\"bb-playbook\">\n          <div class=\"sad-webview-icon\">&#9762;</div>\n          <h2 class=\"crashed-label\">Aw, Snap!</h2>\n          <h2 class=\"killed-label\">He's Dead, Jim!</h2>\n          <p>Something went wrong while displaying this webpage.\n            To continue, reload or go to another page.</p>\n        </div><!--\n        Comment-out whitespace\n        --><div class=\"webview-overlay\" data-name=\"bb-playbook\">&nbsp;</div>\n      </div><!--\n      Comment-out whitespace\n      --><div id=\"content-overlay\">&nbsp;</div>\n    </div>\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/user-agent/browser.js",
    "content": "(function(config, bindings) {\n  var currentUrl = '';        // URL where all webviews should be\n  var lastNavigator = null;   // Webview that last performed navigation\n  var contentOverlay = null;  // Div element overlay of all content\n  var locationInput = null;   // Input element for address bar\n  var findBox = null;         // Div element for find-on-page widget\n  var webViewContainers = []; // Div elements wrapping webviews\n  var webViews = [];          // Webview elements\n  var sadWebViews = [];       // Div elements displaying \"sad\" (simulated crash) webviews\n  var findResultsLists = [];  // Span elements where find-on-page results reside\n\n  // Always re-layout on resize\n  window.addEventListener('resize', function(e) {\n    doLayout();\n  });\n\n  // Boostrap code\n  window.addEventListener('load', function(e) {\n    contentOverlay = getContentOverlay();\n    locationInput = getLocationInput();\n    findBox = getFindBox();\n    webViewContainers = getWebViewContainers();\n    webViews = getWebViews();\n    sadWebViews = getSadWebViews();\n    findResultsLists = getFindResultsLists();\n    lastNavigator = webViews[0];\n\n    doLayout();\n\n    document.querySelector('#back').addEventListener('click', function(e) {\n      stopNavigation();\n      lastNavigator.back();\n    });\n\n    document.querySelector('#forward').addEventListener('click', function() {\n      stopNavigation();\n      lastNavigator.forward();\n    });\n\n    document.querySelector('#home').addEventListener('click', function() {\n      navigateTo(config.homepage, null);\n    });\n\n    document.querySelector('#reload').addEventListener('click', function() {\n      if (anyLoading()) {\n        stopNavigation();\n      } else {\n        webViews.forEach(function(wv) { wv.reload(); });\n      }\n    });\n    document.querySelector('#reload').addEventListener(\n        'webkitAnimationIteration',\n        function() {\n          // Between animation iterations: If loading is done, then stop spinning\n          if (!anyLoading()) {\n            document.body.classList.remove('loading');\n          }\n        });\n\n    document.querySelector('#terminate').addEventListener('click', function() {\n      stopNavigation();\n      webViews.forEach(function(wv) { wv.terminate(); });\n    });\n\n    document.querySelector('#location-form').addEventListener('submit', function(e) {\n      e.preventDefault();\n      navigateTo(locationInput.value, null);\n    });\n\n    webViews.forEach(function(wv) {\n      wv.addEventListener('exit', handleExit);\n      wv.addEventListener('loadstart', handleLoadStart);\n      wv.addEventListener('loadstop', handleLoadStop);\n      wv.addEventListener('loadabort', handleLoadAbort);\n      wv.addEventListener('loadredirect', handleLoadRedirect);\n      wv.addEventListener('loadcommit', handleLoadCommit);\n    });\n\n    // Test for the presence of the experimental <webview> zoom and find APIs.\n    if (typeof(webViews[0].setZoom) == 'function' &&\n        typeof(webViews[0].find) == 'function') {\n      var findMatchCase = false;\n\n      document.querySelector('#zoom').addEventListener('click', function() {\n        if(document.querySelector('#zoom-box').style.display == '-webkit-flex') {\n          closeZoomBox();\n        } else {\n          openZoomBox();\n        }\n      });\n\n      document.querySelector('#zoom-form').addEventListener('submit', function(e) {\n        e.preventDefault();\n        var zoomText = document.forms['zoom-form']['zoom-text'];\n        var zoomFactor = Number(zoomText.value);\n        if (zoomFactor > 5) {\n          zoomText.value = '5';\n          zoomFactor = 5;\n        } else if (zoomFactor < 0.25) {\n          zoomText.value = '0.25';\n          zoomFactor = 0.25;\n        }\n        webViews.forEach(function(wv) { wv.setZoom(zoomFactor); });\n      });\n\n      document.querySelector('#zoom-in').addEventListener('click', function(e) {\n        e.preventDefault();\n        increaseZoom();\n      });\n\n      document.querySelector('#zoom-out').addEventListener('click', function(e) {\n        e.preventDefault();\n        decreaseZoom();\n      });\n\n      document.querySelector('#find').addEventListener('click', function() {\n        if(findBox.style.display == 'block') {\n          closeFindBox();\n        } else {\n          openFindBox();\n        }\n      });\n\n      document.querySelector('#find-text').addEventListener('input', function(e) {\n        webViews.forEach(function(wv) {\n          wv.find(document.forms['find-form']['find-text'].value,\n                  {matchCase: findMatchCase});\n        });\n      });\n\n      document.querySelector('#find-text').addEventListener('keydown', function(e) {\n        if (e.ctrlKey && e.keyCode == 13) {\n          e.preventDefault();\n          webViews.forEach(function(wv) { wv.stopFinding('activate'); });\n          closeFindBox();\n        }\n      });\n\n      document.querySelector('#match-case').addEventListener('click', function(e) {\n        e.preventDefault();\n        findMatchCase = !findMatchCase;\n        var matchCase = document.querySelector('#match-case');\n        if (findMatchCase) {\n          matchCase.style.color = 'blue';\n          matchCase.style['font-weight'] = 'bold';\n        } else {\n          matchCase.style.color = 'black';\n          matchCase.style['font-weight'] = '';\n        }\n        webViews.forEach(function(wv) {\n          wv.find(document.forms['find-form']['find-text'].value,\n                  {matchCase: findMatchCase});\n        });\n      });\n\n      document.querySelector('#find-backward').addEventListener('click', function(e) {\n        e.preventDefault();\n        webViews.forEach(function(wv) {\n          wv.find(document.forms['find-form']['find-text'].value,\n                  {backward: true, matchCase: findMatchCase});\n        });\n      });\n\n      document.querySelector('#find-form').addEventListener('submit', function(e) {\n        e.preventDefault();\n        webViews.forEach(function(wv) { wv.find(document.forms['find-form']['find-text'].value,\n                                                {matchCase: findMatchCase});\n                                      });\n      });\n\n      webViews.forEach(function(wv) { wv.addEventListener('findupdate', handleFindUpdate); });\n      window.addEventListener('keydown', handleKeyDown);\n    } else {\n      var zoom = document.querySelector('#zoom');\n      var find = document.querySelector('#find');\n      zoom.style.visibility = 'hidden';\n      zoom.style.position = 'absolute';\n      find.style.visibility = 'hidden';\n      find.style.position = 'absolute';\n    }\n\n    navigateTo(config.homepage, null);\n  });\n\n  function toArray(arrayLikeObject) {\n    return Array.prototype.slice.call(arrayLikeObject, 0);\n  }\n\n  function getContentOverlay() {\n    return document.querySelector('#content-overlay');\n  }\n\n  function getLocationInput() {\n    return document.querySelector('#location');\n  }\n\n  function getFindBox() {\n    return document.querySelector('#find-box');\n  }\n\n  function getWebViews() {\n    return toArray(document.querySelectorAll('webview'));\n  }\n\n  function getSadWebViews() {\n    return toArray(document.querySelectorAll('.sad-webview'));\n  }\n\n  function getWebViewContainers() {\n    return toArray(document.querySelectorAll('.webview-container'));\n  }\n\n  function getWebViewContainer(webView) {\n    var name = webView.getAttribute('data-name');\n    return document.querySelector(\n        '.webview-container[data-name=\"' + name + '\"]');\n  }\n\n  function getFindResultsLists() {\n    return toArray(document.querySelectorAll('.results'));\n  }\n\n  function isLoading(container) {\n    return !!container.getAttribute('data-loading');\n  }\n\n  function setLoading(container) {\n    // Overlays block content when any webview is loading\n    document.body.classList.add('loading');\n    return container.setAttribute('data-loading', 't');\n  }\n\n  function setLoadingAll() {\n    // Overlays block content when any webview is loading\n    document.body.classList.add('loading');\n    webViewContainers.forEach(function(wvc) {\n      wvc.setAttribute('data-loading', 't');\n    });\n  }\n\n  function clearLoading(container) {\n    return container.setAttribute('data-loading', '');\n  }\n\n  function anyLoading() {\n    return webViewContainers.some(function(wvc) {\n      return isLoading(wvc);\n    });\n  }\n\n  function stopNavigation() {\n    webViews.forEach(function(wv) {\n      if (isLoading(getWebViewContainer(wv))) {\n        wv.stop();\n      }\n    });\n  }\n\n  function navigateTo(url, initiatorWebView) {\n    // !initiatorWebView => navigate all webviews\n    if (initiatorWebView) {\n      setLoading(getWebViewContainer(initiatorWebView));\n    } else {\n      setLoadingAll();\n    }\n\n    // Only update each webview src if the URL is changing\n    if (url != currentUrl) {\n      currentUrl = url;\n\n      resetExitedState();\n      stopNavigation();\n      locationInput.value = url;\n\n      webViews.forEach(function(wv) {\n        if (wv.src != url) {\n          wv.src = url;\n        }\n      });\n\n      if (initiatorWebView) {\n        lastNavigator = initiatorWebView;\n        document.querySelector('#back').disabled = !initiatorWebView.canGoBack();\n        document.querySelector('#forward').disabled = !initiatorWebView.canGoForward();\n      } else {\n        var someWebView = webViews[0];\n        document.querySelector('#back').disabled = !someWebView.canGoBack();\n        document.querySelector('#forward').disabled = !someWebView.canGoForward();\n      }\n    }\n  }\n\n  function doLayout() {\n    var controls = document.querySelector('#controls');\n    var controlsHeight = controls.offsetHeight;\n    var windowWidth = document.documentElement.clientWidth;\n    var windowHeight = document.documentElement.clientHeight;\n    var contentWidth = windowWidth;\n    var contentHeight = windowHeight - controlsHeight;\n\n    // Layout main overlay first\n    contentOverlay.style.width = contentWidth + 'px';\n    contentOverlay.style.height = contentHeight + 'px';\n\n    // Layout all webview container\n    webViewContainers.forEach(function(container) {\n      var name = container.getAttribute('data-name');\n      var webView = document.querySelector('webview[data-name=\"' + name + '\"]');\n      var sadWebView = document.querySelector('.sad-webview[data-name=\"' + name + '\"]');\n      var webViewOverlay = document.querySelector('.webview-overlay[data-name=\"' + name + '\"]');\n      var widthFactor = container.getAttribute('data-width');\n      var heightFactor = container.getAttribute('data-height');\n      var width = Math.floor(widthFactor * contentWidth);\n      var height = Math.floor(heightFactor * contentHeight);\n\n      webViewOverlay.style.width = width + 'px';\n      webView.style.width = width + 'px';\n      sadWebView.style.width = width + 'px';\n      container.style.width = width + 'px';\n\n      webViewOverlay.style.height = height + 'px';\n      webView.style.height = height + 'px';\n      sadWebView.style.height = height + 'px';\n      container.style.height = height + 'px';\n    });\n  }\n\n  function handleExit(event) {\n    document.body.classList.add('exited');\n    if (event.type == 'abnormal') {\n      document.body.classList.add('crashed');\n    } else if (event.type == 'killed') {\n      document.body.classList.add('killed');\n    }\n    webViews.forEach(function(wv) { wv.style.height = '0px'; });\n    doLayout();\n  }\n\n  function resetExitedState() {\n    document.body.classList.remove('exited');\n    document.body.classList.remove('crashed');\n    document.body.classList.remove('killed');\n    doLayout();\n  }\n\n  function handleFindUpdate(event) {\n    var sourceName = event.srcElement.getAttribute('data-name');\n    var findResults = document.querySelector(\n        '.results[data-name=' + sourceName + ']');\n    if (event.searchText == '') {\n      findResults.innerText = '';\n    } else {\n      findResults.innerText =\n          event.activeMatchOrdinal + ' of ' + event.numberOfMatches;\n    }\n\n    // Ensure that the find box does not obscure the active match.\n    if (event.finalUpdate && !event.canceled) {\n      findBox.style.left = '';\n      findBox.style.opacity = '';\n      var findBoxRect = findBox.getBoundingClientRect();\n      if (findBoxObscuresActiveMatch(findBoxRect, event.selectionRect)) {\n        // Move the find box out of the way if there is room on the screen, or\n        // make it semi-transparent otherwise.\n        var potentialLeft = event.selectionRect.left - findBoxRect.width - 10;\n        if (potentialLeft >= 5) {\n          findBox.style.left = potentialLeft + 'px';\n        } else {\n          findBox.style.opacity = '0.5';\n        }\n      }\n    }\n  }\n\n  function findBoxObscuresActiveMatch(findBoxRect, matchRect) {\n    return findBoxRect.left < matchRect.left + matchRect.width &&\n        findBoxRect.right > matchRect.left &&\n        findBoxRect.top < matchRect.top + matchRect.height &&\n        findBoxRect.bottom > matchRect.top;\n  }\n\n  function handleKeyDown(event) {\n    switch (event.keyCode) {\n      // Esc\n      case 27:\n      event.preventDefault();\n      closeBoxes();\n      break;\n    }\n    if (event.ctrlKey) {\n      switch (event.keyCode) {\n        // Ctrl+F.\n        case 70:\n        event.preventDefault();\n        openFindBox();\n        break;\n\n        // Ctrl++.\n        case 107:\n        case 187:\n        event.preventDefault();\n        increaseZoom();\n        break;\n\n        // Ctrl+-.\n        case 109:\n        case 189:\n        event.preventDefault();\n        decreaseZoom();\n        break;\n      }\n    }\n  }\n\n  function handleLoadCommit(event) {\n    resetExitedState();\n    if (!event.isTopLevel) {\n      return;\n    }\n\n    navigateTo(event.url, event.srcElement);\n    closeBoxes();\n  }\n\n  function handleLoadStart(event) {\n    resetExitedState();\n  }\n\n  function handleLoadStop(event) {\n    clearLoading(getWebViewContainer(event.srcElement));\n  }\n\n  function handleLoadAbort(event) {\n    // We sometimes get loadabort events triggered when updating multiple\n    // webviews on the same navigation pipeline\n    event.preventDefault();\n  }\n\n  function handleLoadRedirect(event) {\n    resetExitedState();\n    if (!event.isTopLevel) {\n      return;\n    }\n\n    navigateTo(event.newUrl, event.srcElement);\n  }\n\n  function getNextPresetZoom(zoomFactor) {\n    var preset = [0.25, 0.33, 0.5, 0.67, 0.75, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2,\n                  2.5, 3, 4, 5];\n    var low = 0;\n    var high = preset.length - 1;\n    var mid;\n    while (high - low > 1) {\n      mid = Math.floor((high + low)/2);\n      if (preset[mid] < zoomFactor) {\n        low = mid;\n      } else if (preset[mid] > zoomFactor) {\n        high = mid;\n      } else {\n        return {low: preset[mid - 1], high: preset[mid + 1]};\n      }\n    }\n    return {low: preset[low], high: preset[high]};\n  }\n\n  // Abstraction for changing zoom; direction, one of \"high\" or \"low\", indexes\n  // into a next-preset-zoom object\n  function changeZoom(direction) {\n    var someWebView = webViews[0];\n    someWebView.getZoom(function(zoomFactor) {\n      var nextZoom = getNextPresetZoom(zoomFactor)[direction];\n      webViews.forEach(function(wv) { wv.setZoom(nextZoom); });\n      document.forms['zoom-form']['zoom-text'].value = nextZoom.toString();\n    });\n  }\n\n  function increaseZoom() {\n    changeZoom('high');\n  }\n\n  function decreaseZoom() {\n    changeZoom('low');\n  }\n\n  function openZoomBox() {\n    document.querySelector('webview').getZoom(function(zoomFactor) {\n      var zoomText = document.forms['zoom-form']['zoom-text'];\n      zoomText.value = Number(zoomFactor.toFixed(6)).toString();\n      document.querySelector('#zoom-box').style.display = '-webkit-flex';\n      zoomText.select();\n    });\n  }\n\n  function closeZoomBox() {\n    document.querySelector('#zoom-box').style.display = 'none';\n  }\n\n  function openFindBox() {\n    findBox.style.display = 'block';\n    document.forms['find-form']['find-text'].select();\n  }\n\n  function closeFindBox() {\n    findBox.style.display = 'none';\n    findBox.style.left = '';\n    findBox.style.opacity = '';\n    findResultsLists.forEach(function(rl) { rl.innerText = ''; });\n    webViews.forEach(function(wv) { wv.stopFinding(); });\n  }\n\n  function closeBoxes() {\n    closeZoomBox();\n    closeFindBox();\n  }\n})(config, bindings);\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/user-agent/browser_bindings.js",
    "content": "/**\n * Bindings that depend on the particular collection of webviews in browser.html\n *\n * @see https://developer.chrome.com/apps/tags/webview#method-setUserAgentOverride\n */\nvar bindings = {\n  'android': 'Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30',\n  'ios': 'Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3',\n  'nokia': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 920)',\n  'bb-playbook': 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML, like Gecko) Version/7.2.1.0 Safari/536.2+'\n};\n\nwindow.addEventListener('load', function(e) {\n  for (var key in bindings) {\n    document.querySelector('webview[data-name=\"' + key + '\"]').\n        setUserAgentOverride(bindings[key]);\n  }\n});\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/user-agent/config.js",
    "content": "// Global configuration variables\nvar config = {\n  'homepage': 'http://www.google.ca/search?q=what+is+my+browser&oq=what+is+my+browser'\n};\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/user-agent/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  runApp();\n});\n\n/**\n * Listens for the app restarting then re-creates the window.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_runtime\n */\nchrome.app.runtime.onRestarted.addListener(function() {\n  runApp();\n});\n\n/**\n * Creates the window for the application.\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nfunction runApp() {\n  chrome.app.window.create(\n      'browser.html',\n      {'id': 'browserWinID', 'state': 'maximized'});\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/user-agent/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"User-Agent Sample\",\n  \"minimum_chrome_version\": \"24.0.1307.0\",\n  \"version\": \"2.0\",\n  \"icons\": {\n    \"16\": \"icon_16.png\",\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"webview\"\n  ]\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/webview/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/hnanccpkhjhkkgiipckodmdldeomdohj\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Webview explorer sample\n\nSample to explore some of the APIs in the webview tag.\n\n## APIs\n\n* [webview](https://developer.chrome.com/apps/tags/webview)\n* [Runtime](https://developer.chrome.com/docs/extensions/reference/app_runtime)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n\n## Screenshot\n![screenshot](/_archive/apps/samples/webview-samples/webview/assets/screenshot_1280_800.png)\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/webview/index.css",
    "content": "/* Basic styling */\nbody {\n\tfont-family: Verdana, Arial;\n\tcolor: #333;\n\tpadding: 20px;\n}\n\n.section {\n\tmargin-top: 20px;\n}\n\n.section h2 {\n\tfont-size: 1.2em;\n\tcolor: rgb(197, 65, 65);\n\tborder-bottom: 1px solid #ddd;\n}\n\nbutton {\n\tbackground-image: -webkit-linear-gradient(top,#4d90fe,#4787ed);\n\tcolor: white;\n\tpadding: 5px 10px;\n\tfont-weight: bold;\n\tborder-radius: 2px;\n\tborder: 1px solid #3079ed;\n\tcursor: pointer;\n}\n\nbutton:hover {\n\tbackground-image: -webkit-linear-gradient(top,#4d90fe,#357ae8);\n\tborder: 1px solid #2f5bb7;\n}\n\n\n/* Flexbox boxes */\ndiv.blocks, div.blocks > div {\n\tdisplay: -webkit-flex;\n\tdisplay: flex;\n}\n\ndiv.blocks {\n\tflex-flow: row;\n\t-webkit-flex-flow: row;\n}\n\ndiv.blocks > div {\n\tflex-flow: column;\n\t-webkit-flex-flow: column;\n\t-webkit-flex:1 1 auto;\n\tflex:1 1 auto;\n}\ndiv.blocks > div > * {\n\t-webkit-flex:1 1 auto;\n\tflex:1 1 auto;\n}\n\ndiv.blocks > div > :nth-child(2n) {\n\t-webkit-flex:1 1 auto;\n\tflex:1 1 auto;\n}\n\n\n/* Webview styling */\n.webviews label, .note {\n\tfont-size: 0.7em;\n\tcolor: #aaa;\n\tmax-width: 200px;\n\t-webkit-flex:0 0 auto !important;\n\tflex:0 0 auto !important;\n}\n\nwebview {\n\tborder: 1px solid rgb(197, 65, 65);\n}\n\n\n/* Sliders and other controllers styling */\ndiv.props, div.props > div {\n\ttext-align: right;\n}\n\ndiv.props > div > div > * {\n\tvertical-align: middle;\n}\ndiv.props > div:nth-child(2n) {\n\tmargin-right: 30px;\n\tcolor: #999;\n\ttext-align: left;\n\tpadding-left: 10px;\n}\ndiv.props input[type=\"range\"] {\n\tmargin-left: 10px;\n}\ndiv.props input[type=\"text\"] {\n\twidth: 60px;\n\theight: 1.5em;\n\tborder: 1px solid #CCC;\n\tmargin-right: 5px;\n\ttext-align: right;\n}\ndiv.props > div:nth-child(2n) {\n\t-webkit-flex:2 1 auto;\n\tflex:2 1 auto;\n}\ntextarea {\n\twidth: 100%;\n\tborder: 1px solid #CCC;\n\tfont-size: 0.9em;\n\tcolor: #aaa;\n\theight: 100px;\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/webview/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <title>WebView sample</title>\n    <link href=\"index.css\" rel=\"stylesheet\">\n</head>\n<body>\n\t<div class=\"section\"><h2>Resize webview #1</h2>\n\t\t<div class=\"blocks props\">\n\t    \t<div>\n\t    \t\t<label>CSS width:</label>\n\t    \t\t<label>attribute minwidth:</label>\n\t    \t\t<label>attribute maxwidth:</label>\n\t    \t</div>\n\t    \t<div class=\"width\">\n\t    \t\t<div class=\"css_value\"><input type=\"text\" value=\"200\"/>px<input value=\"200\" min=\"50\" max=\"300\" type=\"range\"/></div>\n\t    \t\t<div class=\"min\"><input type=\"text\" value=\"0\"/>px<input value=\"0\" min=\"0\" max=\"300\" type=\"range\"/></div>\n\t    \t\t<div class=\"max\"><input type=\"text\" value=\"0\"/>px<input value=\"0\" min=\"0\" max=\"300\" type=\"range\"/></div>\n\t    \t</div>\n\t    \t<div>\n\t    \t\t<label>CSS height:</label>\n\t    \t\t<label>attribute minheight:</label>\n\t    \t\t<label>attribute maxheight:</label>\n\t    \t</div>\n\t    \t<div class=\"height\">\n\t    \t\t<div class=\"css_value\"><input type=\"text\" value=\"200\"/>px<input value=\"200\" min=\"50\" max=\"300\" type=\"range\"/></div>\n\t    \t\t<div class=\"min\"><input type=\"text\" value=\"0\"/>px<input value=\"0\" min=\"0\" max=\"300\" type=\"range\"/></div>\n\t    \t\t<div class=\"max\"><input type=\"text\" value=\"0\"/>px<input value=\"0\" min=\"0\" max=\"300\" type=\"range\"/></div>\n\t    \t</div>\n\t\t</div>\n\n\t</div>\n\n\t<div class=\"section\"><h2>Messages and events to/from webview #1</h2>\n\t\t<textarea></textarea>\n\t</div>\n\n\t<div class=\"section\"><h2>Webviews</h2>\n\t\t<div class=\"indicator\"></div>\n\n\t\t<div class=\"blocks webviews\">\n\t    \t<div>\n\t    \t\t<label>(autosize=true, non-persistent)</label>\n\t\t\t    <webview id=\"wv1\" style=\"width:250px; height:200px;\" autosize=\"true\"\n\t\t\t    \tsrc=\"https://googledrive.com/host/0B6-v_MWWvdqWSXpkMTZhQVBvMjg/page_hosted_in_external_server.html\"></webview>\n\t    \t</div>\n\t    \t<div>\n\t    \t\t<label>(persistent at partition2)</label>\n\t\t\t    <webview id=\"wv2\" style=\"width:250px; height:200px;\"\n\t\t\t    \tsrc=\"https://googledrive.com/host/0B6-v_MWWvdqWSXpkMTZhQVBvMjg/page_hosted_in_external_server.html\"\n\t\t\t    \tpartition=\"persist:partition2\"></webview>\n\t    \t\t<div class=\"note\">try signing in at google.com, reload the app and webview 3 should be signed too,because they both share the same persistance partition</div>\n\t    \t</div>\n\t    \t<div>\n\t    \t\t<label>(persistent at partition2)</label>\n\t\t\t    <webview id=\"wv3\" style=\"width:250px; height:200px;\"\n\t\t\t    \tsrc=\"https://googledrive.com/host/0B6-v_MWWvdqWSXpkMTZhQVBvMjg/page_hosted_in_external_server.html\"\n\t\t\t    \tpartition=\"persist:partition2\"></webview>\n\t    \t</div>\n\n    <script src=\"index.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/webview/index.js",
    "content": "\nonload = function() {\n\tvar $ = function(sel) {\n\t\treturn document.querySelector(sel);\n\t};\n\n\tvar wv1=$('#wv1');\n\tvar wv2=$('#wv2');\n\tvar wv3=$('#wv3');\n\tvar logEl=$('textarea');\n\n\tfunction log(str) {\n\t\tlogEl.value = str+\"\\n\"+logEl.value;\n\t}\n\n\tfunction changeProperty(property, isCssAttribute, e) {\n\t\tvar el = e.target;\n\t\tvar value = el.value;\n\t\tif (isCssAttribute) {\n\t\t\tvalue = parseInt(el.value)+\"px\";\n\t\t\twv1.style[property]=value;\n\t\t} else {  // else is element attribute\n\t\t\twv1.setAttribute(property, value);\n\t\t}\n\t\tif (el.type==\"range\") {\n\t\t\tel.previousElementSibling.value=el.value;\n\t\t} else {\n\t\t\tel.nextElementSibling.value=el.value;\n\t\t}\n\t}\n\n\t['text', 'range'].map( function(inputtype) {\n\t\t$('.width .css_value input[type=\"'+inputtype+'\"]').addEventListener('change',\n\t\t\tchangeProperty.bind(this, 'width', true));\n\t\t$('.height .css_value input[type=\"'+inputtype+'\"]').addEventListener('change',\n\t\t\tchangeProperty.bind(this, 'height', true));\n\t\t$('.width .min input[type=\"'+inputtype+'\"]').addEventListener('change',\n\t\t\tchangeProperty.bind(this, 'minwidth', false));\n\t\t$('.height .min input[type=\"'+inputtype+'\"]').addEventListener('change',\n\t\t\tchangeProperty.bind(this, 'minheight', false));\n\t\t$('.width .max input[type=\"'+inputtype+'\"]').addEventListener('change',\n\t\t\tchangeProperty.bind(this, 'maxwidth', false));\n\t\t$('.height .max input[type=\"'+inputtype+'\"]').addEventListener('change',\n\t\t\tchangeProperty.bind(this, 'maxheight', false));\n\t});\n\n\tfunction logSizeChanged(e) {\n\t\tlog(\"[\"+e.target.id+\"] sizechanged: newWidth=\"+e.newWidth+\" newHeight=\"+e.newHeight+\" oldWidth=\"+e.oldWidth+\" oldHeight=\"+e.oldHeight);\n\t}\n\n\twv1.addEventListener('sizechanged', logSizeChanged);\n\twv2.addEventListener('sizechanged', logSizeChanged);\n\twv3.addEventListener('sizechanged', logSizeChanged);\n\n\tfunction sendInitialMessage(e) {\n\t\t// only send the message if the page was loaded from googledrive hosting\n\t\te.target.contentWindow.postMessage(\"initial message\", \"https://googledrive.com/host/*\");\n\n\t}\n\n\tfunction handlePermissionRequest(e) {\n\t\tvar allowed = false;\n\t  if (e.permission==='pointerLock' || e.permission==='media' ||\n\t  \t\te.permission==='geolocation') {\n\t  \tallowed = true;\n    \te.request.allow();\n  \t} else {\n  \t\te.request.deny();\n  \t}\n\t\tlog(\"[\"+e.target.id+\"] permissionrequest: permission=\"+e.permission+\" \"+\n\t\t\t(allowed?\"allowed\":\"DENIED\"));\n\t}\n\n\twindow.addEventListener('message', function(e) {\n\t\tlog(\"[???] messagereceived: \"+e.data);\n\t\tconsole.log(\"received message\", e);\n\t});\n\n\twv1.addEventListener('loadstop', sendInitialMessage);\n\twv2.addEventListener('loadstop', sendInitialMessage);\n\twv3.addEventListener('loadstop', sendInitialMessage);\n\n\twv1.addEventListener('permissionrequest', handlePermissionRequest);\n\twv2.addEventListener('permissionrequest', handlePermissionRequest);\n\twv3.addEventListener('permissionrequest', handlePermissionRequest);\n\n}"
  },
  {
    "path": "_archive/apps/samples/webview-samples/webview/main.js",
    "content": "/**\n * Listens for the app launching then creates the window\n *\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n    id: 'embedder',\n    innerBounds: {\n      width: 1430,\n      height: 870\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/webview/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Webview Sample\",\n  \"version\": \"2.1\",\n  \"permissions\": [\"webview\", \"pointerLock\", \"geolocation\", \"videoCapture\"],\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/webview-samples/webview/page_hosted_in_external_server.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\">\n    <title>Page hosted, for webview sample</title>\n</head>\n<body>\n  <p>This page is hosted at an external server. Observe how it interacts with the embedder application</p>\n  <button id=\"sendmessage\">Send message to app</button><br>\n  <button id=\"pointerlock\">Pointer lock</button><br>\n  <button id=\"captureimage\">Capture image</button><br>\n  <button id=\"geoloc\">Request geolocation</button><br>\n  <a href=\"http://google.com\">Go to google.com</a><br>\n  <div id=\"log\"></div><br>\n\n<script type=\"text/javascript\">\n\n(function() {\n\nvar log=document.getElementById(\"log\");\nvar appWindow, appOrigin;\n\nfunction onMessage(e) {\n  appWindow = e.source;\n  appOrigin = e.origin;\n  console.log(e);\n}\n\nfunction doSendMessage() {\n  log.innerText=\"\";\n  if (appWindow && appOrigin) {\n    appWindow.postMessage(\"this is a message from the page!\", appOrigin)\n    log.innerText=\"message sent\";\n  } else {\n    log.innerText=\"ERROR: don't have app info - no initial message received\";\n  }\n}\n\nfunction doPointerLock() {\n  document.body.webkitRequestPointerLock();\n  log.innerText=\"Pointer lock requested\";\n}\n\nfunction doCaptureImage() {\n  var video = document.querySelector('video');\n  if (!video) {\n    video = document.createElement('video');\n    video.style.width=\"200px\";\n    video.autoplay = true;\n    document.body.appendChild(video);\n  }\n  navigator.webkitGetUserMedia(\n    {video: true, audio: true},\n    function(stream) {\n      video.src = window.URL.createObjectURL(stream);\n      log.innerText=\"video running, enjoy!\";\n      }, function(err) { console.log(err);});\n}\n\nfunction doGeoloc() {\n  log.innerText=\"requested position\";\n  if (navigator.geolocation) {\n    navigator.geolocation.getCurrentPosition(function(position) {\n     log.innerText='position='+position;\n    });\n  }\n}\n\nwindow.addEventListener('message', onMessage);\n\ndocument.getElementById(\"sendmessage\").addEventListener('click', doSendMessage);\ndocument.getElementById(\"pointerlock\").addEventListener('click', doPointerLock);\ndocument.getElementById(\"captureimage\").addEventListener('click', doCaptureImage);\ndocument.getElementById(\"geoloc\").addEventListener('click', doGeoloc);\n\n})();\n\n</script>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/window-options/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/cfcgoifcnpnadlhhoolkemkjkhoajfmk\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n\n# Window Options Sample\n\nDemonstrates:\n\n* Window bounds and size constraints.\n* Options available for creating new windows.\n* Options that can be changed after creation of the window.\n\nThis sample requires Chrome Version 35 or higher.\n\n## Resources\n\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/window-options/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/window-options/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('window.html', {\n    id: \"MainWindow\",\n    innerBounds: {\n      width: 900,\n      height: 600\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/window-options/css/window.css",
    "content": "body {\n  margin: 0px;\n  padding: 0px;\n}\n\nh1, h2, h3 {\n  margin: 0px 0px 10px 0px;\n}\n\ntd {\n  padding: 2px 5px;\n}\n\n#fullscreen-area {\n  box-shadow: inset 0px 1px 10px rgba(0,0,0,1);\n  margin: 5px;\n  padding: 20px;\n  min-width: 400px;\n  min-height: 300px;\n}\n\n.size {\n  width: 60px;\n}\n\n.tab-body {\n  padding: 0px;\n  margin: 0 auto;\n  max-width: 1200px;\n  min-width: 800px;\n}\n\n.buttons {\n  text-align: center;\n  margin: 10px 0px;\n}\n\n.columns {\n  display: table;\n  width: 100%;\n  border-spacing: 10px;\n}\n\n.section {\n  border: 1px solid #aaaaaa;\n  padding: 10px;\n  display: table-cell;\n}\n\n.new-column {\n  width: 50%;\n}\n\n.edit-left {\n  width: 40%;\n}\n\n.edit-right {\n  width: 60%;\n}\n"
  },
  {
    "path": "_archive/apps/samples/window-options/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Window Options Sample\",\n  \"version\": \"2\",\n  \"minimum_chrome_version\": \"35\",\n  \"icons\": {\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [\"fullscreen\", \"alwaysOnTopWindows\"]\n}\n"
  },
  {
    "path": "_archive/apps/samples/window-options/window.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <link href=\"css/window.css\" rel=\"stylesheet\">\n  <link rel=\"stylesheet\" href=\"css/custom-theme/jquery-ui-1.10.4.custom.min.css\">\n  <script src=\"js/jquery-1.10.1.min.js\"></script>\n  <script src=\"js/jquery-ui-1.10.4.custom.min.js\"></script>\n  <script src=\"window.js\"></script>\n</head>\n<body>\n  <div id=\"tabs\">\n    <ul>\n      <li><a href=\"#tabs-edit\">Edit Current Window</a></li>\n      <li><a href=\"#tabs-new\">Create New Window</a></li>\n    </ul>\n\n    <div id=\"tabs-edit\">\n      <div class=\"tab-body\">\n        <div class=\"buttons\">\n          <button id=\"fullscreen\">Fullscreen</button>\n          <button id=\"maximize\">Maximize</button>\n          <button id=\"minimize\">Minimize</button>\n          <button id=\"restore\">Restore</button>\n          <button id=\"close\">Close</button><br>\n          <button id=\"hide\">Hide, then Show</button>\n          <button id=\"showInactive\">Hide, then Show Inactive</button>\n          <button id=\"drawAttention\">Draw Attention</button>\n          <button id=\"clearAttention\">Clear Attention</button>\n        </div>\n        <div class=\"columns\">\n          <div class=\"section edit-left\">\n            <h3>Options</h3>\n            <table>\n              <tr>\n                <td>ID:</td>\n                <td colspan=\"2\"><input type=\"text\" id=\"currentWindowId\" disabled /></td>\n              </tr>\n              <tr>\n                <td>Always On Top:</td>\n                <td><input type=\"checkbox\" id=\"currentWindowOnTop\" /></td>\n              </tr>\n            </table>\n          </div>\n\n          <div class=\"section edit-right\">\n            <h3>Bounds</h3>\n            <div id=\"accordion\">\n              <h3>Outer Bounds</h3>\n              <div>\n                <table>\n                  <tr>\n                    <td>Left, Top:</td>\n                    <td><input type=\"number\" class=\"size\" id=\"outerWindowLeft\" step=1 /></td>\n                    <td><input type=\"number\" class=\"size\" id=\"outerWindowTop\" step=1 /></td>\n                    <td><button id=\"setOuterPosition\">Set</button></td>\n                  </tr>\n                  <tr>\n                    <td>Width, Height:</td>\n                    <td><input type=\"number\" class=\"size\" id=\"outerWindowWidth\" step=1 /></td>\n                    <td><input type=\"number\" class=\"size\" id=\"outerWindowHeight\" step=1 /></td>\n                    <td><button id=\"setOuterSize\">Set</button></td>\n                  </tr>\n                  <tr>\n                    <td>Min Width, Height:</td>\n                    <td><input type=\"number\" class=\"size\" id=\"outerWindowMinWidth\" step=1 /></td>\n                    <td><input type=\"number\" class=\"size\" id=\"outerWindowMinHeight\" step=1 /></td>\n                    <td>\n                      <button id=\"setOuterMinSize\">Set</button>\n                      <button id=\"clearOuterMinSize\">Clear</button>\n                    </td>\n                  </tr>\n                  <tr>\n                    <td>Max Width, Height:</td>\n                    <td><input type=\"number\" class=\"size\" id=\"outerWindowMaxWidth\" step=1 /></td>\n                    <td><input type=\"number\" class=\"size\" id=\"outerWindowMaxHeight\" step=1 /></td>\n                    <td>\n                      <button id=\"setOuterMaxSize\">Set</button>\n                      <button id=\"clearOuterMaxSize\">Clear</button>\n                    </td>\n                  </tr>\n                </table>\n              </div>\n              <h3>Inner Bounds</h3>\n              <div>\n                <table>\n                  <tr>\n                    <td>Left, Top:</td>\n                    <td><input type=\"number\" class=\"size\" id=\"innerWindowLeft\" step=1 /></td>\n                    <td><input type=\"number\" class=\"size\" id=\"innerWindowTop\" step=1 /></td>\n                    <td><button id=\"setInnerPosition\">Set</button></td>\n                  </tr>\n                  <tr>\n                    <td>Width, Height:</td>\n                    <td><input type=\"number\" class=\"size\" id=\"innerWindowWidth\" step=1 /></td>\n                    <td><input type=\"number\" class=\"size\" id=\"innerWindowHeight\" step=1 /></td>\n                    <td><button id=\"setInnerSize\">Set</button></td>\n                  </tr>\n                  <tr>\n                    <td>Min Width, Height:</td>\n                    <td><input type=\"number\" class=\"size\" id=\"innerWindowMinWidth\" step=1 /></td>\n                    <td><input type=\"number\" class=\"size\" id=\"innerWindowMinHeight\" step=1 /></td>\n                    <td>\n                      <button id=\"setInnerMinSize\">Set</button>\n                      <button id=\"clearInnerMinSize\">Clear</button>\n                    </td>\n                  </tr>\n                  <tr>\n                    <td>Max Width, Height:</td>\n                    <td><input type=\"number\" class=\"size\" id=\"innerWindowMaxWidth\" step=1 /></td>\n                    <td><input type=\"number\" class=\"size\" id=\"innerWindowMaxHeight\" step=1 /></td>\n                    <td>\n                      <button id=\"setInnerMaxSize\">Set</button>\n                      <button id=\"clearInnerMaxSize\">Clear</button>\n                    </td>\n                  </tr>\n                </table>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n\n    <div id=\"tabs-new\">\n      <div class=\"tab-body\">\n        <div class=\"buttons\">\n          <button id=\"newWindow\">Create Window</button>\n        </div>\n        <div class=\"columns\">\n          <div class=\"section new-column\">\n            <h3>Options</h3>\n            <table>\n              <tr>\n                <td>ID:</td>\n                <td>\n                  <select id=\"newWindowId\">\n                    <option value=\"none\">Without ID</option>\n                    <option value=\"ID1\">ID1</option>\n                    <option value=\"ID2\">ID2</option>\n                  </select>\n                  <br>\n                  <small>The ID will restore the previous position</small>\n                </td>\n              </tr>\n              <tr>\n                <td>Initial State:</td>\n                <td>\n                  <select id=\"newWindowState\">\n                    <option value=\"normal\">Normal</option>\n                    <option value=\"fullscreen\">Fullscreen</option>\n                    <option value=\"maximized\">Maximized</option>\n                    <option value=\"minimized\">Minimized</option>\n                  </select>\n                </td>\n              </tr>\n              <tr>\n                <td>Frame:</td>\n                <td>\n                  <label><input type=\"radio\" name=\"newWindowFrame\" value=\"chrome\" checked />Chrome</label>\n                  <label><input type=\"radio\" name=\"newWindowFrame\" value=\"none\" />None</label>\n                </td>\n              </tr>\n              <tr>\n                <td>Color, Inactive Color:</td>\n                <td>\n                  <input type=\"text\" class=\"size\" id=\"newWindowColor\" placeholder=\"#000000\" />\n                  <input type=\"text\" class=\"size\" id=\"newWindowInactiveColor\" placeholder=\"#000000\" />\n                </td>\n              </tr>\n              <tr>\n                <td>Visibility:</td>\n                <td>\n                  <label><input type=\"radio\" name=\"newWindowHidden\" value=\"visible\" checked />Visible</label>\n                  <label><input type=\"radio\" name=\"newWindowHidden\" value=\"hidden\" />Hidden, then shown</label>\n                </td>\n              </tr>\n              <tr>\n                <td>Resizable:</td>\n                <td><input type=\"checkbox\" id=\"newWindowResizable\" checked/></td>\n              </tr>\n              <tr>\n                <td>Always On Top:</td>\n                <td><input type=\"checkbox\" id=\"newWindowOnTop\" /></td>\n              </tr>\n              <tr>\n                <td>Focused:</td>\n                <td><input type=\"checkbox\" checked id=\"newWindowFocused\"></td>\n              </tr>\n            </table>\n          </div>\n\n          <div class=\"section new-column\">\n            <h3>Bounds</h3>\n            <label><input type=\"radio\" name=\"newWindowBoundsType\" value=\"outerBounds\" checked />Outer bounds</label>\n            <label><input type=\"radio\" name=\"newWindowBoundsType\" value=\"innerBounds\" />Inner bounds</label>\n            <p></p>\n            <table>\n              <tr>\n                <td>Left, Top:</td>\n                <td><input type=\"number\" class=\"size\" id=\"newWindowLeft\" step=1 /></td>\n                <td><input type=\"number\" class=\"size\" id=\"newWindowTop\" step=1 /></td>\n              </tr>\n              <tr>\n                <td>Width, Height:</td>\n                <td><input type=\"number\" class=\"size\" id=\"newWindowWidth\" step=1 /></td>\n                <td><input type=\"number\" class=\"size\" id=\"newWindowHeight\" step=1 /></td>\n              </tr>\n              <tr>\n                <td>Min Width, Height:</td>\n                <td><input type=\"number\" class=\"size\" id=\"newWindowMinWidth\" step=1 /></td>\n                <td><input type=\"number\" class=\"size\" id=\"newWindowMinHeight\" step=1 /></td>\n              </tr>\n              <tr>\n                <td>Max Width, Height:</td>\n                <td><input type=\"number\" class=\"size\" id=\"newWindowMaxWidth\" step=1 /></td>\n                <td><input type=\"number\" class=\"size\" id=\"newWindowMaxHeight\" step=1 /></td>\n              </tr>\n            </table>\n            <p><button id=\"copyWindowBounds\">Copy this window's bounds</button></p>\n          </div>\n        </div>\n      </div>\n    </div>\n\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/window-options/window.js",
    "content": "// Variables:\n\nvar kHiddenWindowDelay = 3000;\nvar kDefaultWidth = 900;\nvar kDefaultHeight = 600;\n\n// Utils:\n\nfunction setIfANumber(dictionary, field, numberEdit) {\n  var value = $('#' + numberEdit).val();\n  var number = parseInt(value);\n  if (!isNaN(number))\n    dictionary[field] = number;\n}\n\nfunction getNumber(numberEdit) {\n  var value = $('#' + numberEdit).val();\n  var number = parseInt(value);\n  if (!isNaN(number))\n    return number;\n\n  value = $('#' + numberEdit).attr('placeholder');\n  if (!isNaN(number))\n    return number;\n\n  return null;\n}\n\nfunction setNumberEdit(value, numberEdit, attr) {\n  if (attr === 'value' && value === null)\n    $('#' + numberEdit)[0].value = '';\n  else\n    $('#' + numberEdit).attr(attr, value);\n}\n\nfunction getBounds(prefix) {\n  var bounds = {};\n  setIfANumber(bounds, 'left', prefix + 'WindowLeft');\n  setIfANumber(bounds, 'top', prefix + 'WindowTop');\n  setIfANumber(bounds, 'width', prefix + 'WindowWidth');\n  setIfANumber(bounds, 'height', prefix + 'WindowHeight');\n  setIfANumber(bounds, 'minWidth', prefix + 'WindowMinWidth');\n  setIfANumber(bounds, 'minHeight', prefix + 'WindowMinHeight');\n  setIfANumber(bounds, 'maxWidth', prefix + 'WindowMaxWidth');\n  setIfANumber(bounds, 'maxHeight', prefix + 'WindowMaxHeight');\n  return bounds;\n}\n\nfunction setBounds(bounds, prefix, attr) {\n  setNumberEdit(bounds.left, prefix + 'WindowLeft', attr);\n  setNumberEdit(bounds.top, prefix + 'WindowTop', attr);\n  setNumberEdit(bounds.width, prefix + 'WindowWidth', attr);\n  setNumberEdit(bounds.height, prefix + 'WindowHeight', attr);\n  setNumberEdit(bounds.minWidth, prefix + 'WindowMinWidth', attr);\n  setNumberEdit(bounds.minHeight, prefix + 'WindowMinHeight', attr);\n  setNumberEdit(bounds.maxWidth, prefix + 'WindowMaxWidth', attr);\n  setNumberEdit(bounds.maxHeight, prefix + 'WindowMaxHeight', attr);\n}\n\n// Create new window:\n\nfunction createNewWindow() {\n  optionsDictionary = {};\n  var callback = undefined;\n\n  if ($('#newWindowId').val() !== 'none')\n    optionsDictionary.id = $('#newWindowId').val();\n  optionsDictionary.state = $('#newWindowState').val();\n  optionsDictionary.frame = $('input[name=newWindowFrame]:checked').val();\n  optionsDictionary.hidden = $('input[name=newWindowHidden]:checked').val() === 'hidden';\n  optionsDictionary.resizable = $('#newWindowResizable').is(':checked');\n  optionsDictionary.alwaysOnTop = $('#newWindowOnTop').is(':checked');\n  optionsDictionary.focused = $('#newWindowFocused').is(':checked');\n\n  if (optionsDictionary.frame === 'chrome') {\n    optionsDictionary.frame = { type: 'chrome' };\n    if ($('#newWindowColor').val()) {\n      optionsDictionary.frame.color = $('#newWindowColor').val();\n    }\n    if ($('#newWindowInactiveColor').val()) {\n      optionsDictionary.frame.inactiveColor = $('#newWindowInactiveColor').val();\n    }\n  }\n\n  if (optionsDictionary.hidden) {\n    callback = function (win) {\n      setTimeout(function () { win.show(); }, kHiddenWindowDelay);\n    }\n  }\n\n  var boundsType = $('input[name=newWindowBoundsType]:checked').val();\n  optionsDictionary[boundsType] = getBounds('new');\n\n  chrome.app.window.create('window.html', optionsDictionary, callback);\n}\n\nfunction copyWindowBounds() {\n  var win = chrome.app.window.current();\n  var boundsType = $('input[name=newWindowBoundsType]:checked').val();\n  setBounds(win[boundsType], 'new', 'value');\n}\n\nfunction initCreateWindowTab() {\n  // Initialize default state.\n  setBounds({ width: kDefaultWidth, height: kDefaultHeight }, 'new', 'value');\n\n  // Event handlers\n  $('#newWindow').button().click(createNewWindow);\n  $('#copyWindowBounds').click(copyWindowBounds);\n}\n\nfunction updateCurrentStateReadout() {\n  var win = chrome.app.window.current();\n\n  // Also update the hinted window size.\n  setBounds(win.innerBounds, 'inner', 'placeholder');\n  setBounds(win.outerBounds, 'outer', 'placeholder');\n}\n\n// Edit current window:\n\nfunction initEditWindowTab() {\n  // Initialize the buttons.\n  $('#fullscreen').button().click(function() {\n    chrome.app.window.current().fullscreen();\n  });\n\n  $('#maximize').button().click(function() {\n    chrome.app.window.current().maximize();\n  });\n\n  $('#minimize').button().click(function() {\n    chrome.app.window.current().minimize();\n  });\n\n  $('#restore').button().click(function() {\n    chrome.app.window.current().restore();\n  });\n\n  $('#close').button().click(function() {\n    chrome.app.window.current().close();\n  });\n\n  $('#hide').button().click(function() {\n    setTimeout(function() {\n      chrome.app.window.current().show();\n    }, kHiddenWindowDelay);\n    chrome.app.window.current().hide();\n  });\n\n  $('#showInactive').button().click(function() {\n    setTimeout(function() {\n      chrome.app.window.current().show(false);\n    }, kHiddenWindowDelay);\n    chrome.app.window.current().hide();\n  });\n\n  $('#drawAttention').button().click(function() {\n    chrome.app.window.current().drawAttention();\n  });\n\n  $('#clearAttention').button().click(function() {\n    chrome.app.window.current().clearAttention();\n  });\n\n  // Initialize the current state.\n  var win = chrome.app.window.current();\n  $('#currentWindowId').val(win.id);\n  $('#currentWindowOnTop')\n    .attr('checked', win.isAlwaysOnTop())\n    .change(function() {\n      chrome.app.window.current().setAlwaysOnTop(\n        $('#currentWindowOnTop').is(':checked'));\n    });\n\n  // Update window state display on bounds change, but also on regular interval\n  // just to be paranoid.\n  updateCurrentStateReadout();\n  win.onBoundsChanged.addListener(updateCurrentStateReadout);\n  setInterval(updateCurrentStateReadout, 1000);\n}\n\n// Edit bounds:\n\nfunction initBoundsControls() {\n  $('#setOuterPosition').click(function() {\n    chrome.app.window.current().outerBounds.setPosition(\n      getNumber('outerWindowLeft'),\n      getNumber('outerWindowTop')\n    );\n  });\n\n  $('#setOuterSize').click(function() {\n    chrome.app.window.current().outerBounds.setSize(\n      getNumber('outerWindowWidth'),\n      getNumber('outerWindowHeight')\n    );\n  });\n\n  $('#setOuterMinSize').click(function() {\n    chrome.app.window.current().outerBounds.setMinimumSize(\n      getNumber('outerWindowMinWidth'),\n      getNumber('outerWindowMinHeight')\n    );\n  });\n\n  $('#clearOuterMinSize').click(function() {\n    chrome.app.window.current().outerBounds.setMinimumSize(null, null);\n    setNumberEdit(null, 'outerWindowMinWidth', 'value');\n    setNumberEdit(null, 'outerWindowMinHeight', 'value');\n  });\n\n  $('#setOuterMaxSize').click(function() {\n    chrome.app.window.current().outerBounds.setMaximumSize(\n      getNumber('outerWindowMaxWidth'),\n      getNumber('outerWindowMaxHeight')\n    );\n  });\n\n  $('#clearOuterMaxSize').click(function() {\n    chrome.app.window.current().outerBounds.setMaximumSize(null, null);\n    setNumberEdit(null, 'outerWindowMaxWidth', 'value');\n    setNumberEdit(null, 'outerWindowMaxHeight', 'value');\n  });\n\n  $('#setInnerPosition').click(function() {\n    chrome.app.window.current().innerBounds.setPosition(\n      getNumber('innerWindowLeft'),\n      getNumber('innerWindowTop')\n    );\n  });\n\n  $('#setInnerSize').click(function() {\n    chrome.app.window.current().innerBounds.setSize(\n      getNumber('innerWindowWidth'),\n      getNumber('innerWindowHeight')\n    );\n  });\n\n  $('#setInnerMinSize').click(function() {\n    chrome.app.window.current().innerBounds.setMinimumSize(\n      getNumber('innerWindowMinWidth'),\n      getNumber('innerWindowMinHeight')\n    );\n  });\n\n  $('#clearInnerMinSize').click(function() {\n    chrome.app.window.current().innerBounds.setMinimumSize(null, null);\n    setNumberEdit(null, 'innerWindowMinWidth', 'value');\n    setNumberEdit(null, 'innerWindowMinHeight', 'value');\n  });\n\n  $('#setInnerMaxSize').click(function() {\n    chrome.app.window.current().innerBounds.setMaximumSize(\n      getNumber('innerWindowMaxWidth'),\n      getNumber('innerWindowMaxHeight')\n    );\n  });\n\n  $('#clearInnerMaxSize').click(function() {\n    chrome.app.window.current().innerBounds.setMaximumSize(null, null);\n    setNumberEdit(null, 'innerWindowMaxWidth', 'value');\n    setNumberEdit(null, 'innerWindowMaxHeight', 'value');\n  });\n}\n\n// Layout:\n\nfunction resizeContent() {\n  $('#tabs').height($(window).height());\n}\n\n// Main:\n\n$(document).ready(function() {\n  // Initialize the layout of the window.\n  $('#tabs').tabs();\n  $(window).resize(resizeContent);\n  setTimeout(resizeContent, 200);\n  $('#accordion').accordion({ heightStyle: 'content' });\n\n  // Initialize the tabs.\n  initCreateWindowTab();\n  initEditWindowTab();\n  initBoundsControls();\n});\n"
  },
  {
    "path": "_archive/apps/samples/window-state/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/window-state-sample/hcbhfbnaaancmblfhdknlnojpafjohbi\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Window State Sample\n\nDemonstrates transitioning the window into minimized, maximized, fullscreen\nand hidden states. Includes HTML5 requestFullscreen and app.window.fullscreen().\n\n## Resources\n\n* [Fullscreen Specification](http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html)\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/window-state/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/window-state/background.js",
    "content": "chrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('window.html', {\n  \tid: \"mainwin\",\n    innerBounds: {\n      width: 700,\n      height: 600\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/apps/samples/window-state/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Window State Sample\",\n  \"version\": \"4.2\",\n  \"icons\": {\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [\"fullscreen\", \"alwaysOnTopWindows\"]\n}\n"
  },
  {
    "path": "_archive/apps/samples/window-state/window.css",
    "content": "#fullscreen-area {\n  box-shadow: inset 0px 1px 10px rgba(0,0,0,1);\n  margin: 5px;\n  padding: 5px;\n  border-radius: 5px;\n}\n\n.size {\n  width: 60px;\n}\n"
  },
  {
    "path": "_archive/apps/samples/window-state/window.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<link href=\"window.css\" rel=\"stylesheet\">\n<link rel=\"icon\" id=\"iconLink\">\n</head>\n<body>\n  <h1>Window State Sample</h1>\n  <div id=\"fullscreen-area\">\n\n    <p><b>HTML5 Fullscreen</b>:\n      <button id=\"html-fullscreen-enter\">Enter</button>\n      <button id=\"html-fullscreen-exit\">Exit</button>\n      <span id=\"html-fullscreen-label\"></span>\n    </p>\n\n    <p>chrome.app.<b>window actions</b>, delayed:\n      <input id=\"delay-slider\" type =\"range\" min =\"0\" max=\"20000\" step=\"1000\" value=\"0\"/>\n      <span id=\"delay-label\"></span>\n      <br>\n      <button id=\"fullscreen\">Fullscreen</button>\n      <button id=\"maximize\">Maximize</button>\n      <button id=\"minimize\">Minimize</button>\n      <button id=\"restore\">Restore</button>\n      <button id=\"hide\">Hide</button>\n      <button id=\"show\">Show</button>\n      <button id=\"showInactive\">Show Inactive</button>\n      <label id=\"alwaysOnTopLabel\"><input type=\"checkbox\" id=\"alwaysOnTop\" />Always On Top</label>\n      <br>\n      <button id=\"move\">Move To (L,T)</button> /\n      <button id=\"resize\">Resize To (W,H)</button> /\n      <button id=\"setbounds\">Set Bounds (L,T,W,H)</button>:\n      <br>\n      Left, Top: <input type=\"number\" class=\"size\" id=\"moveWindowLeft\" step=1 />\n      <input type=\"number\" class=\"size\" id=\"moveWindowTop\" step=1 />\n      Width, Height: <input type=\"number\" class=\"size\" id=\"resizeWindowWidth\" step=1 />\n      <input type=\"number\" class=\"size\" id=\"resizeWindowHeight\" step=1 />\n    </p>\n\n    <p><b>Create</b> a new window:<br>\n      <label><input type=\"radio\" name=\"newWindowId\" value=\"ID1\" checked/>id = ID1</label>\n      <label><input type=\"radio\" name=\"newWindowId\" value=\"ID2\" />id = ID2</label>\n      <label><input type=\"radio\" name=\"newWindowId\" value=\"none\" />Without id</label>\n      : The id will restore previous position.\n      <br>\n      <label>Min<input type=\"number\" class=\"size\" id=\"newWindowWidthMin\" step=1 /></label>\n      <label><input type=\"number\" class=\"size\" id=\"newWindowWidthMax\" step=1 />Max Width</label>\n      <br>\n      <label>Min<input type=\"number\" class=\"size\" id=\"newWindowHeightMin\" step=1 /></label>\n      <label><input type=\"number\" class=\"size\" id=\"newWindowHeightMax\" step=1 />Max Height</label>\n      <label><input type=\"checkbox\" id=\"newWindowResizable\" checked/>Resizable</label>\n      <label id=\"newWindowOnTopLabel\"><input type=\"checkbox\" id=\"newWindowOnTop\" />Always On Top</label>\n      <label><input type=\"checkbox\" checked id=\"newWindowFocused\">Focused</label>\n      <br>\n      <label><input type=\"radio\" name=\"newWindowHidden\" value=\"visible\" checked/>Visible</label>\n      <label><input type=\"radio\" name=\"newWindowHidden\" value=\"hidden\" />Hidden, then shown</label>\n      <br>\n      <button id=\"newWindowNormal\">Normal</button>\n      <button id=\"newWindowFullscreen\">Fullscreen</button>\n      <button id=\"newWindowMaximized\">Maximized</button>\n      <button id=\"newWindowMinimized\">Minimized</button>\n    </p>\n\n    <p>Current window state:\n      <input type=\"checkbox\" id=\"isFullscreen\" disabled>isFullscreen\n      <input type=\"checkbox\" id=\"isMaximized\"  disabled>isMaximized\n      <input type=\"checkbox\" id=\"isMinimized\"  disabled>isMinimized\n      <input type=\"checkbox\" id=\"isHidden\" disabled>document.webkitHidden\n    </p>\n\n    <p>Last 10 seconds state:\n      <input type=\"checkbox\" id=\"wasFullscreen\" disabled>wasFullscreen\n      <input type=\"checkbox\" id=\"wasMaximized\"  disabled>wasMaximized\n      <input type=\"checkbox\" id=\"wasMinimized\"  disabled>wasMinimized\n      <input type=\"checkbox\" id=\"wasHidden\" disabled>document.webkitHidden\n    </p>\n\n    <p>Window icon:\n      <button id=\"normalWindowIcon\"/>Normal</button>\n      <button id=\"customWindowIcon\"/>Custom</button>\n    </p>\n  </div>\n  This text is outside of the HTML5 fullscreen area.\n</body>\n<script src=\"window.js\"></script>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/window-state/window.js",
    "content": "// Variables:\n\nvar hiddenWindowDelay = 3000;\nvar fullscreenchangeCount = 0;\nvar fullscreenerrorCount = 0;\nvar newWindowOffset = 100;\n\n// chrome.app.window alwaysOnTop property is supported in Chrome M32 or later.\n// The option will be hidden if not supported in the current browser version.\nvar isAlwaysOnTopSupported = typeof(chrome.app.window.current().setAlwaysOnTop) !== 'undefined';\n\nvar version = window.navigator.appVersion;\nversion = version.substr(version.lastIndexOf('Chrome/') + 7);\nversion = version.substr(0, version.indexOf('.'));\nversion = parseInt(version);\n\nvar isFocusedSupported = version >= 33;\n\n// Helper functions\n$ = function(selector) { return document.querySelector(selector); }\n\nfunction setIfANumber(dictionary, field, number) {\n  if (isNaN(number))\n    return;\n  dictionary[field] = number\n}\n\nfunction createNewWindow(optionsDictionary) {\n  optionsDictionary = optionsDictionary || {};\n\n  if ($('[value=ID1]').checked)\n    optionsDictionary.id = \"ID1\";\n  else if ($('[value=ID2]').checked)\n    optionsDictionary.id = \"ID2\";\n  else\n    optionsDictionary.id = undefined;\n\n  optionsDictionary.resizable = $('#newWindowResizable').checked;\n  if (isAlwaysOnTopSupported)\n    optionsDictionary.alwaysOnTop = $('#newWindowOnTop').checked;\n  if (isFocusedSupported)\n    optionsDictionary.focused = $('#newWindowFocused').checked;\n\n  optionsDictionary.hidden = $('[value=hidden]').checked;\n  var showAfterCreated = function (win) {\n    setTimeout(function () { win.show(); }, hiddenWindowDelay);\n  }\n  var callback = optionsDictionary.hidden ? showAfterCreated : undefined;\n\n  // Set new window to be offset from current window.\n  var innerBounds = chrome.app.window.current().innerBounds;\n  innerBounds.left = (innerBounds.left + newWindowOffset) % (screen.width - innerBounds.width);\n  innerBounds.top = (innerBounds.top + newWindowOffset) % (screen.height - innerBounds.height);\n  optionsDictionary.innerBounds = {};\n  optionsDictionary.innerBounds.left = innerBounds.left;\n  optionsDictionary.innerBounds.top = innerBounds.top;\n  optionsDictionary.innerBounds.width = innerBounds.width;\n  optionsDictionary.innerBounds.height = innerBounds.height;\n  setIfANumber(optionsDictionary.innerBounds, 'minWidth', parseInt($('#newWindowWidthMin').value));\n  setIfANumber(optionsDictionary.innerBounds, 'maxWidth', parseInt($('#newWindowWidthMax').value));\n  setIfANumber(optionsDictionary.innerBounds, 'minHeight', parseInt($('#newWindowHeightMin').value));\n  setIfANumber(optionsDictionary.innerBounds, 'maxHeight', parseInt($('#newWindowHeightMax').value));\n\n  chrome.app.window.create('window.html', optionsDictionary, callback);\n};\n\nfunction getCustomIconDataURL() {\n  // Draw a red circle to a canvas and return the data URL.\n  var c = document.createElement('canvas');\n  c.width = 16;\n  c.height = 16;\n  var ctx = c.getContext('2d');\n  ctx.fillStyle = 'red';\n  ctx.beginPath();\n  ctx.arc(8, 8, 8, 0, Math.PI * 2);\n  ctx.fill();\n  ctx.closePath();\n  return c.toDataURL();\n}\n\n// Log events:\n\nvar updateFulllscreenLabel = function updateFulllscreenLabel() {\n  $('#html-fullscreen-label').innerText =\n    fullscreenchangeCount + \" change, \" +\n    fullscreenerrorCount + \" error events.\";\n}\nupdateFulllscreenLabel();  // Initial text update.\n\ndocument.onwebkitfullscreenchange = function () {\n  fullscreenchangeCount++;\n  console.log(\"onwebkitfullscreenchange\");\n  updateFulllscreenLabel();\n}\n\ndocument.onwebkitfullscreenerror = function () {\n  fullscreenerrorCount++;\n  console.log(\"onwebkitfullscreenerror\");\n  updateFulllscreenLabel();\n}\n\n// Button handlers:\n\n$('#html-fullscreen-enter').onclick = function(e) {\n  $('#fullscreen-area').webkitRequestFullscreen();\n};\n\n$('#html-fullscreen-exit').onclick = function(e) {\n  document.webkitExitFullscreen();\n};\n\n$('#fullscreen').onclick = function(e) {\n  setTimeout(chrome.app.window.current().fullscreen, $('#delay-slider').value);\n};\n\n$('#maximize').onclick = function(e) {\n  setTimeout(chrome.app.window.current().maximize, $('#delay-slider').value);\n};\n\n$('#minimize').onclick = function(e) {\n  setTimeout(chrome.app.window.current().minimize, $('#delay-slider').value);\n};\n\n$('#restore').onclick = function(e) {\n  setTimeout(chrome.app.window.current().restore, $('#delay-slider').value);\n};\n\n$('#hide').onclick = function(e) {\n  setTimeout(chrome.app.window.current().hide, $('#delay-slider').value);\n};\n\n$('#show').onclick = function(e) {\n  setTimeout(chrome.app.window.current().show, $('#delay-slider').value);\n};\n\n$('#alwaysOnTop').onchange = function(e) {\n  chrome.app.window.current().setAlwaysOnTop($('#alwaysOnTop').checked);\n};\n\n$('#move').onclick = function(e) {\n  var x = parseInt($('#moveWindowLeft').value);\n  var y = parseInt($('#moveWindowTop').value);\n  setTimeout(\n    function() {\n      var curWindow = chrome.app.window.current();\n      curWindow.outerBounds.left = x;\n      curWindow.outerBounds.top = y;\n    },\n    $('#delay-slider').value);\n};\n\n$('#resize').onclick = function(e) {\n  var w = parseInt($('#resizeWindowWidth').value);\n  var h = parseInt($('#resizeWindowHeight').value);\n  setTimeout(\n    function() {\n      var curWindow = chrome.app.window.current();\n      curWindow.outerBounds.width = w;\n      curWindow.outerBounds.height = h;\n    },\n    $('#delay-slider').value);\n};\n\n$('#setbounds').onclick = function(e) {\n  var bounds = {};\n  var currentInnerBounds = chrome.app.window.current().innerBounds;\n  setIfANumber(bounds, 'left', parseInt($('#moveWindowLeft').value) || currentInnerBounds.left);\n  setIfANumber(bounds, 'top', parseInt($('#moveWindowTop').value) || currentInnerBounds.top);\n  setIfANumber(bounds, 'width', parseInt($('#resizeWindowWidth').value) || currentInnerBounds.width);\n  setIfANumber(bounds, 'height', parseInt($('#resizeWindowHeight').value) || currentInnerBounds.height);\n  setTimeout(\n    function() {\n      chrome.app.window.current().innerBounds = bounds;\n    },\n    $('#delay-slider').value);\n};\n\nvar updateDelaySiderText = function updateDelaySiderText() {\n  $('#delay-label').innerText = $('#delay-slider').value / 1000 + \" seconds.\";\n}\n\n$('#delay-slider').onchange = updateDelaySiderText;\nupdateDelaySiderText();  // Initial text update.\n\n$('#newWindowNormal').onclick = function(e) {\n  createNewWindow();\n};\n\n$('#newWindowFullscreen').onclick = function(e) {\n  createNewWindow({ state: 'fullscreen'});\n};\n\n$('#newWindowMaximized').onclick = function(e) {\n  createNewWindow({ state: 'maximized'});\n};\n\n$('#newWindowMinimized').onclick = function(e) {\n  createNewWindow({ state: 'minimized'});\n};\n\n$('#normalWindowIcon').onclick = function(e) {\n  $('#iconLink').href = \"icon_128.png\";\n}\n\n$('#customWindowIcon').onclick = function(e) {\n  $('#iconLink').href = getCustomIconDataURL();\n}\n\n// Current window state readout:\n\n// Arrays that store previous state values, which are cleared after a delay.\nvar wasFullscreen = [];\nvar wasMaximized = [];\nvar wasMinimized = [];\nvar wasHidden = [];\nvar wasStateDelay = 10 * 1000;\n\n// Stash values into 'was' variables and clear them out after a delay.\nfunction setWasState(wasStateArray, state) {\n  if (state) {\n    wasStateArray.push(true);\n    setTimeout(function () { wasStateArray.pop() }, wasStateDelay);\n  }\n}\n\nfunction updateCurrentStateReadout() {\n  $('#isFullscreen').checked = chrome.app.window.current().isFullscreen();\n  $('#isMaximized' ).checked = chrome.app.window.current().isMaximized();\n  $('#isMinimized' ).checked = chrome.app.window.current().isMinimized();\n  $('#isHidden'    ).checked = document.webkitHidden;\n\n  // Stash values into 'was' variables and clear them out after a delay.\n  setWasState(wasFullscreen, chrome.app.window.current().isFullscreen());\n  setWasState(wasMaximized, chrome.app.window.current().isMaximized());\n  setWasState(wasMinimized, chrome.app.window.current().isMinimized());\n  setWasState(wasHidden, document.webkitHidden);\n\n  // Display the current 'was' variables.\n  $('#wasFullscreen').checked = wasFullscreen.length > 0;\n  $('#wasMaximized' ).checked = wasMaximized.length > 0;\n  $('#wasMinimized' ).checked = wasMinimized.length > 0;\n  $('#wasHidden'    ).checked = wasHidden.length > 0;\n\n  // Also update the hinted window size\n  $('#moveWindowLeft').placeholder = chrome.app.window.current().innerBounds.left;\n  $('#moveWindowTop').placeholder = chrome.app.window.current().innerBounds.top;\n  $('#resizeWindowWidth').placeholder = chrome.app.window.current().innerBounds.width;\n  $('#resizeWindowHeight').placeholder = chrome.app.window.current().innerBounds.height;\n\n  $('#newWindowWidthMin').placeholder = chrome.app.window.current().innerBounds.width;\n  $('#newWindowWidthMax').placeholder = chrome.app.window.current().innerBounds.width;\n  $('#newWindowHeightMin').placeholder = chrome.app.window.current().innerBounds.height;\n  $('#newWindowHeightMax').placeholder = chrome.app.window.current().innerBounds.height;\n}\n// Update window state display on bounds change, but also on regular interval\n// just to be paranoid.\nchrome.app.window.current().onBoundsChanged.addListener(updateCurrentStateReadout);\nsetInterval(updateCurrentStateReadout, 1000);\n\n// Set initial value of always on top\nif (isAlwaysOnTopSupported) {\n  $('#alwaysOnTop').checked = chrome.app.window.current().isAlwaysOnTop();\n} else {\n  $('#alwaysOnTopLabel').style.visibility = 'hidden';\n  $('#newWindowOnTopLabel').style.visibility = 'hidden';\n}\n\nif (!isFocusedSupported) {\n  $('#newWindowFocused').disabled = true;\n}\n"
  },
  {
    "path": "_archive/apps/samples/windows/README.md",
    "content": "<a target=\"_blank\" href=\"https://chrome.google.com/webstore/detail/ldenchfohdfgggloeimambnckhjpedgc\">![Try it now in CWS](https://raw.github.com/GoogleChrome/chrome-extensions-samples/main/_archive/apps/tryitnowbutton.png \"Click here to install this sample from the Chrome Web Store\")</a>\n\n\n# Copycat Window\n\nSample that shows how to use the [window API](https://developer.chrome.com/docs/extensions/reference/app_window) to create a window with a custom frame and manipulate its properties.\n\nThe app creates two windows, an \"original\" window and a \"copycat\" window. The copycat window mimics the position and minimize state of the original window, but it displays itself in an inverted fashion.\n\n## APIs\n\n* [Window](https://developer.chrome.com/docs/extensions/reference/app_window)\n\n## Screenshot\n![screenshot](/_archive/apps/samples/windows/assets/screenshot_1280_800.png)\n\n"
  },
  {
    "path": "_archive/apps/samples/windows/copycat.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n\n  <script src=\"scripts/window.js\"></script>\n  <link rel=\"stylesheet\" href=\"styles/window.css\">\n</head>\n<body class=\"copycat\">\n\n<h1>I'm a copycat</h1>\n\n<div id=\"stats\">\n  <p>\n    Position: (<span id=\"screenX\"></span>, <span id=\"screenY\"></span>)\n  </p>\n\n  <p>\n    Size: (<span id=\"innerWidth\"></span>, <span id=\"innerHeight\"></span>)\n  </p>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/windows/main.js",
    "content": "var windows = [];\n\n/**\n * Resets the windows and removes\n * any interval that is running\n */\nfunction reset() {\n\n  windows.forEach( function (w) {\n    w.contentWindow.close();\n  } );\n\n  windows.length = 0;\n}\n\n/**\n * Initialise and launch the windows\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nfunction launch() {\n\n  // reset everything\n  reset();\n\n  // create the original window\n  chrome.app.window.create('original.html', {\n      id: \"mainwin\",\n      innerBounds: {\n        top: 128,\n        left: 128,\n        width: 300,\n        height: 300,\n        minHeight: 300,\n        maxWidth: 500,\n        minWidth: 300\n      },\n      frame: 'none'\n    },\n\n    // when that is created store it\n    // and create the copycat window\n    function(originalWindow) {\n\n      windows.push(originalWindow);\n\n      chrome.app.window.create('copycat.html', {\n        id: \"copywin\",\n        innerBounds: {\n          top: 128,\n          left: 428 + 5,\n          width: 300,\n          height: 300,\n          minHeight: 300,\n          maxWidth: 500,\n          minWidth: 300\n        },\n        frame: 'none'\n      },\n\n      function(copycatWindow) {\n\n        // store the copycat\n        windows.push(copycatWindow);\n\n        // now have the copycat watch the\n        // original window for changes\n        originalWindow.onClosed.addListener(reset);\n        copycatWindow.onClosed.addListener(reset);\n\n        originalWindow.onBoundsChanged.addListener(function() {\n          var bounds = originalWindow.outerBounds;\n          copycatWindow.outerBounds.left = bounds.left + bounds.width + 5;\n        });\n\n        copycatWindow.onRestored.addListener(function() {\n          console.log('copy restored');\n          if (originalWindow.isMinimized())\n            originalWindow.restore();\n        })\n\n        originalWindow.onRestored.addListener(function() {\n          console.log('copy restored');\n          if (copycatWindow.isMinimized())\n            copycatWindow.restore();\n        })\n\n        originalWindow.focus();\n      });\n  });\n}\n\n/**\n * Minimises both the original and copycat windows\n * @see https://developer.chrome.com/docs/extensions/reference/app_window\n */\nfunction minimizeAll() {\n\n  windows.forEach( function (w) {\n    w.minimize();\n  });\n}\n\n// @see https://developer.chrome.com/docs/extensions/reference/app_runtime\nchrome.app.runtime.onLaunched.addListener(launch);\n"
  },
  {
    "path": "_archive/apps/samples/windows/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Windowing API Sample\",\n  \"version\": \"3\",\n  \"minimum_chrome_version\": \"23\",\n  \"icons\": {\n    \"16\": \"icon_16.png\",\n    \"128\": \"icon_128.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/windows/original.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n\n\t<script src=\"scripts/window.js\"></script>\n\t<link rel=\"stylesheet\" href=\"styles/window.css\">\n</head>\n<body class=\"original\">\n\n<h1>Move me</h1>\n\n<div id=\"stats\">\n  <p>\n    Position: (<span id=\"screenX\"></span>, <span id=\"screenY\"></span>)\n  </p>\n\n  <p>\n    Size: (<span id=\"innerWidth\"></span>, <span id=\"innerHeight\"></span>)\n  </p>\n</div>\n\n<button id=\"minimize-button\">Minimize me!</button>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/apps/samples/windows/scripts/window.js",
    "content": "onload = function() {\n  function update() {\n    ['screenX', 'screenY', 'innerWidth', 'innerHeight'].forEach(function(prop) {\n      document.getElementById(prop).innerText = window[prop];\n    });\n\n    webkitRequestAnimationFrame(update);\n  }\n\n  update();\n\n  var minimizeNode = document.getElementById('minimize-button');\n  if (minimizeNode) {\n    minimizeNode.onclick = function() {\n      chrome.runtime.getBackgroundPage(function(background) {\n        background.minimizeAll();\n      });\n    };\n  }\n\n  var closeNode = document.getElementById('close');\n  if (closeNode) {\n    closeNode.onclick = function() {\n      window.close();\n    };\n  }\n}\n"
  },
  {
    "path": "_archive/apps/samples/windows/styles/window.css",
    "content": "html, body {\n  padding: 0;\n  margin: 0;\n  width: 100%;\n  height: 100%;\n  font-family: Helvetica, Arial;\n}\n\nbody.original {\n  background: url(\"../img/original.png\") center 75px no-repeat;\n  position: relative;\n  -webkit-app-region: drag;\n}\n\nbutton {\n  -webkit-app-region: no-drag;\n}\n\nbody.copycat {\n  background: #333 url(\"../img/copycat.png\") center 75px no-repeat;\n  position: relative;\n  color: #FFF;\n}\n\nh1 {\n  padding: 0.6em 0;\n  margin: 0;\n  text-align: center;\n  border-bottom: 1px solid #CCC;\n  background: #F2F2F2;\n  font-size: 24px;\n}\n\nbutton {\n  width: 200px;\n  height: 30px;\n  font-size: 16px;\n  position: absolute;\n  bottom: 25px;\n  left: 50%;\n  margin-left: -100px;\n}\n\n#stats {\n  position: absolute;\n  top: 190px;\n  width: 100%;\n}\n\n#stats p {\n  text-align: center;\n  margin: 0 0 0.5em;\n  font-size: 12px;\n  font-weight: bold;\n  color: #888;\n}\n\n#stats p span {\n  font-style: italic;\n  font-weight: normal;\n}\n\n.copycat h1 {\n  background: #444;\n}\n"
  },
  {
    "path": "_archive/mv2/api/bookmarks/basic/manifest.json",
    "content": "{\n  \"name\": \"My Bookmarks\",\n  \"description\": \"A browser action with a popup dump of all bookmarks, including search, add, edit and delete.\",\n  \"version\": \"1.1\",\n  \"manifest_version\": 2,\n  \"permissions\": [\n    \"bookmarks\"\n  ],\n  \"browser_action\": {\n      \"default_title\": \"My Bookmarks\",\n      \"default_icon\": \"icon.png\",\n      \"default_popup\": \"popup.html\"\n  },\n  \"content_security_policy\": \"script-src 'self' https://ajax.googleapis.com; object-src 'self'\"\n}\n"
  },
  {
    "path": "_archive/mv2/api/bookmarks/basic/popup.html",
    "content": "<html>\n<head>\n  <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js\"></script>\n  <script src=\"https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js\"></script>\n  <script src=\"popup.js\"></script>\n</head>\n<body style=\"width: 400px\">\n  <div>Search Bookmarks: <input id=\"search\"></div>\n  <div id=\"bookmarks\"></div>\n  <div id=\"editdialog\"></div>\n  <div id=\"deletedialog\"></div>\n  <div id=\"adddialog\"></div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/bookmarks/basic/popup.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Search the bookmarks when entering the search keyword.\n$(function() {\n  $('#search').change(function() {\n     $('#bookmarks').empty();\n     dumpBookmarks($('#search').val());\n  });\n});\n// Traverse the bookmark tree, and print the folder and nodes.\nfunction dumpBookmarks(query) {\n  var bookmarkTreeNodes = chrome.bookmarks.getTree(\n    function(bookmarkTreeNodes) {\n      $('#bookmarks').append(dumpTreeNodes(bookmarkTreeNodes, query));\n    });\n}\nfunction dumpTreeNodes(bookmarkNodes, query) {\n  var list = $('<ul>');\n  var i;\n  for (i = 0; i < bookmarkNodes.length; i++) {\n    list.append(dumpNode(bookmarkNodes[i], query));\n  }\n  return list;\n}\nfunction dumpNode(bookmarkNode, query) {\n  if (bookmarkNode.title) {\n    if (query && !bookmarkNode.children) {\n      if (String(bookmarkNode.title).indexOf(query) == -1) {\n        return $('<span></span>');\n      }\n    }\n    var anchor = $('<a>');\n    anchor.attr('href', bookmarkNode.url);\n    anchor.text(bookmarkNode.title);\n    /*\n     * When clicking on a bookmark in the extension, a new tab is fired with\n     * the bookmark url.\n     */\n    anchor.click(function() {\n      chrome.tabs.create({url: bookmarkNode.url});\n    });\n    var span = $('<span>');\n    var options = bookmarkNode.children ?\n      $('<span>[<a href=\"#\" id=\"addlink\">Add</a>]</span>') :\n      $('<span>[<a id=\"editlink\" href=\"#\">Edit</a> <a id=\"deletelink\" ' +\n        'href=\"#\">Delete</a>]</span>');\n    var edit = bookmarkNode.children ? $('<table><tr><td>Name</td><td>' +\n      '<input id=\"title\"></td></tr><tr><td>URL</td><td><input id=\"url\">' +\n      '</td></tr></table>') : $('<input>');\n    // Show add and edit links when hover over.\n        span.hover(function() {\n        span.append(options);\n        $('#deletelink').click(function() {\n          $('#deletedialog').empty().dialog({\n                 autoOpen: false,\n                 title: 'Confirm Deletion',\n                 resizable: false,\n                 height: 140,\n                 modal: true,\n                 overlay: {\n                   backgroundColor: '#000',\n                   opacity: 0.5\n                 },\n                 buttons: {\n                   'Yes, Delete It!': function() {\n                      chrome.bookmarks.remove(String(bookmarkNode.id));\n                      span.parent().remove();\n                      $(this).dialog('destroy');\n                    },\n                    Cancel: function() {\n                      $(this).dialog('destroy');\n                    }\n                 }\n               }).dialog('open');\n         });\n        $('#addlink').click(function() {\n          $('#adddialog').empty().append(edit).dialog({autoOpen: false,\n            closeOnEscape: true, title: 'Add New Bookmark', modal: true,\n            buttons: {\n            'Add' : function() {\n               chrome.bookmarks.create({parentId: bookmarkNode.id,\n                 title: $('#title').val(), url: $('#url').val()});\n               $('#bookmarks').empty();\n               $(this).dialog('destroy');\n               window.dumpBookmarks();\n             },\n            'Cancel': function() {\n               $(this).dialog('destroy');\n            }\n          }}).dialog('open');\n        });\n        $('#editlink').click(function() {\n         edit.val(anchor.text());\n         $('#editdialog').empty().append(edit).dialog({autoOpen: false,\n           closeOnEscape: true, title: 'Edit Title', modal: true,\n           show: 'slide', buttons: {\n              'Save': function() {\n                 chrome.bookmarks.update(String(bookmarkNode.id), {\n                   title: edit.val()\n                 });\n                 anchor.text(edit.val());\n                 options.show();\n                 $(this).dialog('destroy');\n              },\n             'Cancel': function() {\n                 $(this).dialog('destroy');\n             }\n         }}).dialog('open');\n        });\n        options.fadeIn();\n      },\n      // unhover\n      function() {\n        options.remove();\n      }).append(anchor);\n  }\n  var li = $(bookmarkNode.title ? '<li>' : '<div>').append(span);\n  if (bookmarkNode.children && bookmarkNode.children.length > 0) {\n    li.append(dumpTreeNodes(bookmarkNode.children, query));\n  }\n  return li;\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  dumpBookmarks();\n});\n"
  },
  {
    "path": "_archive/mv2/api/browserAction/make_page_red/background.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Called when the user clicks on the browser action.\nchrome.browserAction.onClicked.addListener(function(tab) {\n  // No tabs or host permissions needed!\n  console.log('Turning ' + tab.url + ' red!');\n  chrome.tabs.executeScript({\n    code: 'document.body.style.backgroundColor=\"red\"'\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/browserAction/make_page_red/manifest.json",
    "content": "{\n  \"name\": \"Page Redder\",\n  \"description\": \"Make the current page red\",\n  \"version\": \"2.0\",\n  \"permissions\": [\n    \"activeTab\"\n  ],\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"browser_action\": {\n    \"default_title\": \"Make this page red\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/browserAction/print/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Called when the user clicks on the browser action.\nchrome.browserAction.onClicked.addListener(function(tab) {\n  chrome.tabs.executeScript(\n    tab.id,\n    {code: 'window.print();'});\n});\n"
  },
  {
    "path": "_archive/mv2/api/browserAction/print/manifest.json",
    "content": "{\n  \"name\": \"Print this page\",\n  \"description\": \"Adds a print button to the browser.\",\n  \"version\": \"1.2\",\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"permissions\": [\n    \"activeTab\"\n  ],\n  \"browser_action\": {\n      \"default_title\": \"Print this page\",\n      \"default_icon\": \"print_16x16.png\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/browserAction/set_icon_path/background.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nchrome.runtime.onInstalled.addListener(function() {\n  chrome.storage.sync.set({number: 1}, function() {\n    console.log('The number is set to 1.');\n  });\n});\n\nfunction updateIcon() {\n  chrome.storage.sync.get('number', function(data) {\n    var current = data.number;\n    chrome.browserAction.setIcon({path: 'icon' + current + '.png'});\n    current++;\n    if (current > 5)\n      current = 1;\n    chrome.storage.sync.set({number: current}, function() {\n      console.log('The number is set to ' + current);\n    });\n  });\n};\n\nchrome.browserAction.onClicked.addListener(updateIcon);\nupdateIcon();\n"
  },
  {
    "path": "_archive/mv2/api/browserAction/set_icon_path/manifest.json",
    "content": "{\n  \"name\": \"A browser action which changes its icon when clicked\",\n  \"description\": \"Click browser action icon to change color!\",\n  \"version\": \"1.3\",\n  \"background\": {\n     \"scripts\": [\"background.js\"],\n     \"persistent\": false\n   },\n  \"permissions\": [\"storage\"],\n  \"browser_action\": {\n      \"name\": \"Click to change the icon's color\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/browserAction/set_page_color/manifest.json",
    "content": "{\n  \"name\": \"A browser action with a popup that changes the page color\",\n  \"description\": \"Change the current page color\",\n  \"version\": \"1.0\",\n  \"permissions\": [\n    \"activeTab\"\n  ],\n  \"browser_action\": {\n      \"default_title\": \"Set this page's color.\",\n      \"default_icon\": \"icon.png\",\n      \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/browserAction/set_page_color/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Set Page Color Popup</title>\n    <style>\n    body {\n      overflow: hidden;\n      margin: 0px;\n      padding: 0px;\n      background: white;\n    }\n\n    div:first-child {\n      margin-top: 0px;\n    }\n\n    div {\n      cursor: pointer;\n      text-align: center;\n      padding: 1px 3px;\n      font-family: sans-serif;\n      font-size: 0.8em;\n      width: 100px;\n      margin-top: 1px;\n      background: #cccccc;\n    }\n    div:hover {\n      background: #aaaaaa;\n    }\n    #red {\n      border: 1px solid red;\n      color: red;\n    }\n    #blue {\n      border: 1px solid blue;\n      color: blue;\n    }\n    #green {\n      border: 1px solid green;\n      color: green;\n    }\n    #yellow {\n      border: 1px solid yellow;\n      color: yellow;\n    }\n    </style>\n    <script src=\"popup.js\"></script>\n  </head>\n  <body>\n    <div id=\"red\">red</div>\n    <div id=\"blue\">blue</div>\n    <div id=\"green\">green</div>\n    <div id=\"yellow\">yellow</div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/browserAction/set_page_color/popup.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nfunction click(e) {\n  chrome.tabs.executeScript(null,\n      {code:\"document.body.style.backgroundColor='\" + e.target.id + \"'\"});\n  window.close();\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  var divs = document.querySelectorAll('div');\n  for (var i = 0; i < divs.length; i++) {\n    divs[i].addEventListener('click', click);\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/api/browsingData/basic/manifest.json",
    "content": "{\n  \"name\" : \"BrowsingData API: Basics\",\n  \"version\" : \"1.1\",\n  \"description\" : \"A trivial usage example.\",\n  \"permissions\": [\n    \"browsingData\"\n  ],\n  \"browser_action\": {\n     \"default_icon\": \"icon.png\",\n     \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/browsingData/basic/popup.css",
    "content": "/**\n * Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nbody {\n  margin: 5px 10px 10px;\n}\n\nh1 {\n  color: #53637D;\n  font: 26px/1.2 Helvetica, sans-serif;\n  font-size: 200%;\n  margin: 0;\n  padding-bottom: 4px;\n  text-shadow: white 0 1px 2px;\n}\n\nlabel {\n  color: #222;\n  font: 18px/1.4 Helvetica, sans-serif;\n  margin: 0.5em 0;\n  display: inline-block;\n}\n\nform {\n  transition: transform 0.25s ease;\n  width: 563px;\n}\n\nbutton {\n  display: block;\n  border-radius: 2px;\n  box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);\n  -webkit-user-select: none;\n  background: -webkit-linear-gradient(#FAFAFA, #F4F4F4 40%, #E5E5E5);\n  border: 1px solid #AAA;\n  color: #444;\n  margin-bottom: 0;\n  min-width: 4em;\n  padding: 3px 12px;\n  margin-top: 0;\n  font-size: 1.1em;\n}\n\n.overlay {\n  display: block;\n  text-align: center;\n  position: absolute;\n  left: 50%;\n  top: 50%;\n  width: 500px;\n  padding: 20px;\n  margin: -40px 0 0 -270px;\n  opacity: 0;\n  background: rgba(0, 0, 0, 0.75);\n  border-radius: 5px;\n  color: #FFF;\n  font: 1.5em/1.2 Helvetica Neue, sans-serif;\n  transition: all 1.0s ease;\n  transform: scale(0);\n}\n\n.overlay a {\n  color:  #FFF;\n}\n\n.overlay.visible {\n  opacity: 1;\n  transform: scale(1);\n}\n"
  },
  {
    "path": "_archive/mv2/api/browsingData/basic/popup.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Popup</title>\n    <link href=\"popup.css\" rel=\"stylesheet\">\n    <script src=\"popup.js\"></script>\n  </head>\n  <body>\n    <h1>BrowsingData API Sample</h1>\n    <div role=\"main\">\n      <form>\n        <label for=\"timeframe\">Remove all browsing data from:</label>\n        <select id=\"timeframe\">\n          <option value=\"hour\">the past hour</option>\n          <option value=\"day\">the past day</option>\n          <option value=\"week\">the past week</option>\n          <option value=\"4weeks\">the past four weeks</option>\n          <option value=\"forever\">the beginning of time</option>\n        </select>\n        <button id=\"button\">OBLITERATE!</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/browsingData/basic/popup.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * This class wraps the popup's form, and performs the proper clearing of data\n * based on the user's selections. It depends on the form containing a single\n * select element with an id of 'timeframe', and a single button with an id of\n * 'button'. When you write actual code you should probably be a little more\n * accepting of variance, but this is just a sample app. :)\n *\n * Most of this is boilerplate binding the controller to the UI. The bits that\n * specifically will be useful when using the BrowsingData API are contained in\n * `parseMilliseconds_`, `handleCallback_`, and `handleClick_`.\n *\n * @constructor\n */\nvar PopupController = function () {\n  this.button_ = document.getElementById('button');\n  this.timeframe_ = document.getElementById('timeframe');\n  this.addListeners_();\n};\n\nPopupController.prototype = {\n  /**\n   * A cached reference to the button element.\n   *\n   * @type {Element}\n   * @private\n   */\n  button_: null,\n\n  /**\n   * A cached reference to the select element.\n   *\n   * @type {Element}\n   * @private\n   */\n  timeframe_: null,\n\n  /**\n   * Adds event listeners to the button in order to capture a user's click, and\n   * perform some action in response.\n   *\n   * @private\n   */\n  addListeners_: function () {\n    this.button_.addEventListener('click', this.handleClick_.bind(this));\n  },\n\n  /**\n   * Given a string, return milliseconds since epoch. If the string isn't\n   * valid, returns undefined.\n   *\n   * @param {string} timeframe One of 'hour', 'day', 'week', '4weeks', or\n   *     'forever'.\n   * @returns {number} Milliseconds since epoch.\n   * @private\n   */\n  parseMilliseconds_: function (timeframe) {\n    var now = new Date().getTime();\n    var milliseconds = {\n      'hour': 60 * 60 * 1000,\n      'day': 24 * 60 * 60 * 1000,\n      'week': 7 * 24 * 60 * 60 * 1000,\n      '4weeks': 4 * 7 * 24 * 60 * 60 * 1000\n    };\n\n    if (milliseconds[timeframe])\n      return now - milliseconds[timeframe];\n\n    if (timeframe === 'forever')\n      return 0;\n\n    return null;\n  },\n\n  /**\n   * Handle a success/failure callback from the `browsingData` API methods,\n   * updating the UI appropriately.\n   *\n   * @private\n   */\n  handleCallback_: function () {\n    var success = document.createElement('div');\n    success.classList.add('overlay');\n    success.setAttribute('role', 'alert');\n    success.textContent = 'Data has been cleared.';\n    document.body.appendChild(success);\n\n    setTimeout(function() { success.classList.add('visible'); }, 10);\n    setTimeout(function() {\n      if (close === false)\n        success.classList.remove('visible');\n      else\n        window.close();\n    }, 4000);\n  },\n\n  /**\n   * When a user clicks the button, this method is called: it reads the current\n   * state of `timeframe_` in order to pull a timeframe, then calls the clearing\n   * method with appropriate arguments.\n   *\n   * @private\n   */\n  handleClick_: function () {\n    var removal_start = this.parseMilliseconds_(this.timeframe_.value);\n    if (removal_start !== undefined) {\n      this.button_.setAttribute('disabled', 'disabled');\n      this.button_.innerText = 'Clearing...';\n      chrome.browsingData.remove(\n          {'since': removal_start}, {\n            'appcache': true,\n            'cache': true,\n            'cacheStorage': true,\n            'cookies': true,\n            'downloads': true,\n            'fileSystems': true,\n            'formData': true,\n            'history': true,\n            'indexedDB': true,\n            'localStorage': true,\n            'serverBoundCertificates': true,\n            'serviceWorkers': true,\n            'pluginData': true,\n            'passwords': true,\n            'webSQL': true\n          },\n          this.handleCallback_.bind(this));\n    }\n  }\n};\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  window.PC = new PopupController();\n});\n"
  },
  {
    "path": "_archive/mv2/api/commands/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.commands.onCommand.addListener(function(command) {\n  console.log('onCommand event received for message: ', command);\n});\n"
  },
  {
    "path": "_archive/mv2/api/commands/browser_action.html",
    "content": "This is a sample browser action popup."
  },
  {
    "path": "_archive/mv2/api/commands/manifest.json",
    "content": "{\n  \"name\": \"Sample Extension Commands extension\",\n  \"description\": \"Press Ctrl+Shift+F to open the browser action popup, press Ctrl+Shift+Y to send an event.\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 2,\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"browser_action\": {\n    \"default_popup\": \"browser_action.html\"\n  },\n  \"commands\": {\n    \"toggle-feature\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+Shift+Y\",\n        \"mac\": \"MacCtrl+Shift+Y\"\n       },\n      \"description\": \"Send a 'toggle-feature' event to the extension\"\n    },\n    \"_execute_browser_action\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+Shift+F\",\n        \"mac\": \"MacCtrl+Shift+F\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/contentSettings/manifest.json",
    "content": "{\n  \"name\" : \"Content settings\",\n  \"version\" : \"0.2\",\n  \"description\" : \"Shows the content settings for the current site.\",\n  \"permissions\": [ \"contentSettings\", \"tabs\" ],\n  \"browser_action\": {\n     \"default_icon\": \"contentSettings.png\",\n     \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/contentSettings/popup.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Popup</title>\n    <style>\n      dt { white-space: nowrap }\n    </style>\n    <script src=\"popup.js\"></script>\n  </head>\n  <body>\n    <fieldset>\n      <dl>\n        <dt><label for=\"cookies\">Cookies: </label></dt>\n        <dd><select id=\"cookies\" disabled>\n          <option value=\"allow\">Allow</option>\n          <option value=\"session_only\">Session only</option>\n          <option value=\"block\">Block</option>\n        </select></dd>\n        <dt><label for=\"images\">Images: </label></dt>\n        <dd><select id=\"images\" disabled>\n          <option value=\"allow\">Allow</option>\n          <option value=\"block\">Block</option>\n        </select>\n        <dt><label for=\"javascript\">Javascript: </label></dt>\n        <dd><select id=\"javascript\" disabled>\n          <option value=\"allow\">Allow</option>\n          <option value=\"block\">Block</option>\n        </select></dd>\n        <dt><label for=\"location\">Location: </label></dt>\n        <dd><select id=\"location\" disabled>\n          <option value=\"allow\">Allow</option>\n          <option value=\"ask\">Ask</option>\n          <option value=\"block\">Block</option>\n        </select></dd>\n        <dt><label for=\"plugins\">Plugins: </label></dt>\n        <dd><select id=\"plugins\" disabled>\n          <option value=\"allow\">Allow</option>\n          <option value=\"block\">Block</option>\n        </select></dd>\n        <dt><label for=\"popups\">Pop-ups: </label></dt>\n        <dd><select id=\"popups\" disabled>\n          <option value=\"allow\">Allow</option>\n          <option value=\"block\">Block</option>\n        </select></dd>\n        <dt><label for=\"notifications\">Notifications: </label></dt>\n        <dd><select id=\"notifications\" disabled>\n          <option value=\"allow\">Allow</option>\n          <option value=\"ask\">Ask</option>\n          <option value=\"block\">Block</option>\n        </select></dd>\n        <dt><label for=\"microphone\">Microphone: </label></dt>\n        <dd><select id=\"microphone\" disabled>\n          <option value=\"allow\">Allow</option>\n          <option value=\"ask\">Ask</option>\n          <option value=\"block\">Block</option>\n        </select></dd>\n        <dt><label for=\"camera\">Camera: </label></dt>\n        <dd><select id=\"camera\" disabled>\n          <option value=\"allow\">Allow</option>\n          <option value=\"ask\">Ask</option>\n          <option value=\"block\">Block</option>\n        </select></dd>\n        <dt><label for=\"unsandboxedPlugins\">Unsandboxed plugin access: </label></dt>\n        <dd><select id=\"unsandboxedPlugins\" disabled>\n          <option value=\"allow\">Allow</option>\n          <option value=\"ask\">Ask</option>\n          <option value=\"block\">Block</option>\n        </select></dd>\n        <dt><label for=\"automaticDownloads\">Automatic Downloads: </label></dt>\n        <dd><select id=\"automaticDownloads\" disabled>\n          <option value=\"allow\">Allow</option>\n          <option value=\"ask\">Ask</option>\n          <option value=\"block\">Block</option>\n        </select></dd>\n      </dl>\n    </fieldset>\n\n\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/contentSettings/popup.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar incognito;\nvar url;\n\nfunction settingChanged() {\n  var type = this.id;\n  var setting = this.value;\n  var pattern = /^file:/.test(url) ? url : url.replace(/\\/[^\\/]*?$/, '/*');\n  console.log(type+' setting for '+pattern+': '+setting);\n  // HACK: [type] is not recognised by the docserver's sample crawler, so\n  // mention an explicit\n  // type: chrome.contentSettings.cookies.set - See http://crbug.com/299634\n  chrome.contentSettings[type].set({\n        'primaryPattern': pattern,\n        'setting': setting,\n        'scope': (incognito ? 'incognito_session_only' : 'regular')\n      });\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {\n    var current = tabs[0];\n    incognito = current.incognito;\n    url = current.url;\n    var types = [\n      'cookies', 'images', 'javascript', 'location', 'popups', 'notifications',\n      'microphone', 'camera', 'automaticDownloads'\n    ];\n    types.forEach(function(type) {\n      // HACK: [type] is not recognised by the docserver's sample crawler, so\n      // mention an explicit\n      // type: chrome.contentSettings.cookies.get - See http://crbug.com/299634\n      chrome.contentSettings[type] && chrome.contentSettings[type].get({\n            'primaryUrl': url,\n            'incognito': incognito\n          },\n          function(details) {\n            document.getElementById(type).disabled = false;\n            document.getElementById(type).value = details.setting;\n          });\n    });\n  });\n\n  var selects = document.querySelectorAll('select');\n  for (var i = 0; i < selects.length; i++) {\n    selects[i].addEventListener('change', settingChanged);\n  }\n});\n\n"
  },
  {
    "path": "_archive/mv2/api/contextMenus/basic/manifest.json",
    "content": "{\n  \"name\": \"Context Menus Sample\",\n  \"description\": \"Shows some of the features of the Context Menus API\",\n  \"version\": \"0.6\",\n  \"permissions\": [\"contextMenus\"],\n  \"background\": {\n    \"scripts\": [\"sample.js\"]\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/contextMenus/basic/sample.js",
    "content": "// Copyright (c) 2010 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// A generic onclick callback function.\nfunction genericOnClick(info, tab) {\n  console.log(\"item \" + info.menuItemId + \" was clicked\");\n  console.log(\"info: \" + JSON.stringify(info));\n  console.log(\"tab: \" + JSON.stringify(tab));\n}\n\n// Create one test item for each context type.\nvar contexts = [\"page\",\"selection\",\"link\",\"editable\",\"image\",\"video\",\n                \"audio\"];\nfor (var i = 0; i < contexts.length; i++) {\n  var context = contexts[i];\n  var title = \"Test '\" + context + \"' menu item\";\n  var id = chrome.contextMenus.create({\"title\": title, \"contexts\":[context],\n                                       \"onclick\": genericOnClick});\n  console.log(\"'\" + context + \"' item:\" + id);\n}\n\n\n// Create a parent item and two children.\nvar parent = chrome.contextMenus.create({\"title\": \"Test parent item\"});\nvar child1 = chrome.contextMenus.create(\n  {\"title\": \"Child 1\", \"parentId\": parent, \"onclick\": genericOnClick});\nvar child2 = chrome.contextMenus.create(\n  {\"title\": \"Child 2\", \"parentId\": parent, \"onclick\": genericOnClick});\nconsole.log(\"parent:\" + parent + \" child1:\" + child1 + \" child2:\" + child2);\n\n\n// Create some radio items.\nfunction radioOnClick(info, tab) {\n  console.log(\"radio item \" + info.menuItemId +\n              \" was clicked (previous checked state was \"  +\n              info.wasChecked + \")\");\n}\nvar radio1 = chrome.contextMenus.create({\"title\": \"Radio 1\", \"type\": \"radio\",\n                                         \"onclick\":radioOnClick});\nvar radio2 = chrome.contextMenus.create({\"title\": \"Radio 2\", \"type\": \"radio\",\n                                         \"onclick\":radioOnClick});\nconsole.log(\"radio1:\" + radio1 + \" radio2:\" + radio2);\n\n\n// Create some checkbox items.\nfunction checkboxOnClick(info, tab) {\n  console.log(JSON.stringify(info));\n  console.log(\"checkbox item \" + info.menuItemId +\n              \" was clicked, state is now: \" + info.checked +\n              \"(previous state was \" + info.wasChecked + \")\");\n\n}\nvar checkbox1 = chrome.contextMenus.create(\n  {\"title\": \"Checkbox1\", \"type\": \"checkbox\", \"onclick\":checkboxOnClick});\nvar checkbox2 = chrome.contextMenus.create(\n  {\"title\": \"Checkbox2\", \"type\": \"checkbox\", \"onclick\":checkboxOnClick});\nconsole.log(\"checkbox1:\" + checkbox1 + \" checkbox2:\" + checkbox2);\n\n\n// Intentionally create an invalid item, to show off error checking in the\n// create callback.\nconsole.log(\"About to try creating an invalid item - an error about \" +\n            \"item 999 should show up\");\nchrome.contextMenus.create({\"title\": \"Oops\", \"parentId\":999}, function() {\n  if (chrome.extension.lastError) {\n    console.log(\"Got expected error: \" + chrome.extension.lastError.message);\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/api/contextMenus/event_page/manifest.json",
    "content": "{\n  \"name\": \"Context Menus Sample (with Event Page)\",\n  \"description\": \"Shows some of the features of the Context Menus API using an event page\",\n  \"version\": \"0.7\",\n  \"permissions\": [\"contextMenus\"],\n  \"background\": {\n    \"persistent\": false,\n    \"scripts\": [\"sample.js\"]\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/contextMenus/event_page/sample.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// The onClicked callback function.\nfunction onClickHandler(info, tab) {\n  if (info.menuItemId == \"radio1\" || info.menuItemId == \"radio2\") {\n    console.log(\"radio item \" + info.menuItemId +\n                \" was clicked (previous checked state was \"  +\n                info.wasChecked + \")\");\n  } else if (info.menuItemId == \"checkbox1\" || info.menuItemId == \"checkbox2\") {\n    console.log(JSON.stringify(info));\n    console.log(\"checkbox item \" + info.menuItemId +\n                \" was clicked, state is now: \" + info.checked +\n                \" (previous state was \" + info.wasChecked + \")\");\n\n  } else {\n    console.log(\"item \" + info.menuItemId + \" was clicked\");\n    console.log(\"info: \" + JSON.stringify(info));\n    console.log(\"tab: \" + JSON.stringify(tab));\n  }\n};\n\nchrome.contextMenus.onClicked.addListener(onClickHandler);\n\n// Set up context menu tree at install time.\nchrome.runtime.onInstalled.addListener(function() {\n  // Create one test item for each context type.\n  var contexts = [\"page\",\"selection\",\"link\",\"editable\",\"image\",\"video\",\n                  \"audio\"];\n  for (var i = 0; i < contexts.length; i++) {\n    var context = contexts[i];\n    var title = \"Test '\" + context + \"' menu item\";\n    var id = chrome.contextMenus.create({\"title\": title, \"contexts\":[context],\n                                         \"id\": \"context\" + context});\n    console.log(\"'\" + context + \"' item:\" + id);\n  }\n\n  // Create a parent item and two children.\n  chrome.contextMenus.create({\"title\": \"Test parent item\", \"id\": \"parent\"});\n  chrome.contextMenus.create(\n      {\"title\": \"Child 1\", \"parentId\": \"parent\", \"id\": \"child1\"});\n  chrome.contextMenus.create(\n      {\"title\": \"Child 2\", \"parentId\": \"parent\", \"id\": \"child2\"});\n  console.log(\"parent child1 child2\");\n\n  // Create some radio items.\n  chrome.contextMenus.create({\"title\": \"Radio 1\", \"type\": \"radio\",\n                              \"id\": \"radio1\"});\n  chrome.contextMenus.create({\"title\": \"Radio 2\", \"type\": \"radio\",\n                              \"id\": \"radio2\"});\n  console.log(\"radio1 radio2\");\n\n  // Create some checkbox items.\n  chrome.contextMenus.create(\n      {\"title\": \"Checkbox1\", \"type\": \"checkbox\", \"id\": \"checkbox1\"});\n  chrome.contextMenus.create(\n      {\"title\": \"Checkbox2\", \"type\": \"checkbox\", \"id\": \"checkbox2\"});\n  console.log(\"checkbox1 checkbox2\");\n\n  // Intentionally create an invalid item, to show off error checking in the\n  // create callback.\n  console.log(\"About to try creating an invalid item - an error about \" +\n      \"duplicate item child1 should show up\");\n  chrome.contextMenus.create({\"title\": \"Oops\", \"id\": \"child1\"}, function() {\n    if (chrome.extension.lastError) {\n      console.log(\"Got expected error: \" + chrome.extension.lastError.message);\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/contextMenus/global_context_search/background.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n// Add a listener to create the initial context menu items,\n// context menu items only need to be created at runtime.onInstalled\nchrome.runtime.onInstalled.addListener(function() {\n  for (let key of Object.keys(kLocales)) {\n    chrome.contextMenus.create({\n      id: key,\n      title: kLocales[key],\n      type: 'normal',\n      contexts: ['selection'],\n    });\n  }\n});\n\nchrome.contextMenus.onClicked.addListener(function(item, tab) {\n  let url =\n    'https://google.' + item.menuItemId + '/search?q=' + item.selectionText;\n  chrome.tabs.create({url: url, index: tab.index + 1});\n});\n\nchrome.storage.onChanged.addListener(function(list, sync) {\n  let newlyDisabled = [];\n  let newlyEnabled = [];\n  let currentRemoved = list.removedContextMenu.newValue;\n  let oldRemoved = list.removedContextMenu.oldValue || [];\n  for (let key of Object.keys(kLocales)) {\n    if (currentRemoved.includes(key) && !oldRemoved.includes(key)) {\n      newlyDisabled.push(key);\n    } else if (oldRemoved.includes(key) && !currentRemoved.includes(key)) {\n      newlyEnabled.push({\n        id: key,\n        title: kLocales[key]\n      });\n    }\n  }\n  for (let locale of newlyEnabled) {\n    chrome.contextMenus.create({\n      id: locale.id,\n      title: locale.title,\n      type: 'normal',\n      contexts: ['selection'],\n    });\n  }\n  for (let locale of newlyDisabled) {\n    chrome.contextMenus.remove(locale);\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/api/contextMenus/global_context_search/locales.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nconst kLocales = {\n  'com.au': 'Australia',\n  'com.br': 'Brazil',\n  'ca': 'Canada',\n  'cn': 'China',\n  'fr': 'France',\n  'it': 'Italy',\n  'co.in': 'India',\n  'co.jp': 'Japan',\n  'com.ms': 'Mexico',\n  'ru': 'Russia',\n  'co.za': 'South Africa',\n  'co.uk': 'United Kingdom'\n};\n"
  },
  {
    "path": "_archive/mv2/api/contextMenus/global_context_search/manifest.json",
    "content": "{\n  \"name\": \"Global Google Search\",\n  \"description\": \"Use the context menu to search a different country's Google\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 2,\n  \"options_page\": \"options.html\",\n  \"permissions\": [\"contextMenus\", \"storage\"],\n  \"background\": {\n    \"scripts\": [ \"locales.js\", \"background.js\"],\n    \"persistent\": false\n  },\n  \"browser_action\": {\n    \"default_popup\": \"options.html\"\n  },\n  \"icons\": {\n   \"16\": \"globalGoogle16.png\",\n   \"48\": \"globalGoogle48.png\",\n  \"128\": \"globalGoogle128.png\"\n }\n}\n"
  },
  {
    "path": "_archive/mv2/api/contextMenus/global_context_search/options.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Global Context Search</title>\n    <style>\n    body {\n      min-width: 300px;\n      font-size: 15px;\n    }\n    input {\n      margin: 5px;\n      outline: none;\n    }\n    </style>\n  </head>\n\n  <body>\n    <h2>Global Google Search</h2>\n    <h3>Country Options</h3>\n    <form id=\"form\">\n    </form>\n    <button type='submit' value='Submit' id='optionsSubmit'>Submit</button>\n  </body>\n  <script src=\"locales.js\"></script>\n  <script src=\"options.js\"></script>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/contextMenus/global_context_search/options.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction createForm() {\n  chrome.storage.sync.get(['removedContextMenu'], function(list) {\n    let removed = list.removedContextMenu || [];\n    let form = document.getElementById('form');\n    for (let key of Object.keys(kLocales)) {\n      let div = document.createElement('div');\n      let checkbox = document.createElement('input');\n      checkbox.type = 'checkbox';\n      checkbox.checked = true;\n      if (removed.includes(key)) {\n        checkbox.checked = false;\n      }\n      checkbox.name = key;\n      checkbox.value = kLocales[key];\n      let span = document.createElement('span');\n      span.textContent = kLocales[key];\n      div.appendChild(checkbox);\n      div.appendChild(span);\n      form.appendChild(div);\n    }\n  });\n}\n\ncreateForm();\n\ndocument.getElementById('optionsSubmit').onclick = function() {\n  let checkboxes = document.getElementsByTagName('input');\n  let removed = [];\n  for (i=0; i<checkboxes.length; i++) {\n    if (checkboxes[i].checked == false) {\n      removed.push(checkboxes[i].name);\n    }\n  }\n  chrome.storage.sync.set({removedContextMenu: removed});\n  window.close();\n}\n"
  },
  {
    "path": "_archive/mv2/api/cookies/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.cookies.onChanged.addListener(function(info) {\n  console.log(\"onChanged\" + JSON.stringify(info));\n});\n\nfunction focusOrCreateTab(url) {\n  chrome.windows.getAll({\"populate\":true}, function(windows) {\n    var existing_tab = null;\n    for (var i in windows) {\n      var tabs = windows[i].tabs;\n      for (var j in tabs) {\n        var tab = tabs[j];\n        if (tab.url == url) {\n          existing_tab = tab;\n          break;\n        }\n      }\n    }\n    if (existing_tab) {\n      chrome.tabs.update(existing_tab.id, {\"selected\":true});\n    } else {\n      chrome.tabs.create({\"url\":url, \"selected\":true});\n    }\n  });\n}\n\nchrome.browserAction.onClicked.addListener(function(tab) {\n  var manager_url = chrome.extension.getURL(\"manager.html\");\n  focusOrCreateTab(manager_url);\n});\n"
  },
  {
    "path": "_archive/mv2/api/cookies/manager.html",
    "content": "<html>\n<head>\n<style>\ntable {\n  border-collapse:collapse;\n}\n\ntd {\n  border: 1px solid black;\n  padding-left: 5px;\n}\n\ntd.button {\n  border: none;\n}\n\ntd.cookie_count {\n  text-align: right;\n}\n\n</style>\n<script src=\"manager.js\"></script>\n</head>\n<body>\n  <h2>Cookies! ... Nom Nom Nom...</h2>\n  <button id=\"remove_button\">DELETE ALL!</button>\n  <div id=\"filter_div\">\n    Filter: <input id=\"filter\" type=\"text\">\n    <button>x</button>\n  </div>\n  <br />\n  <div id=\"summary_div\">\n    Showing <span id=\"filter_count\"></span> of <span id=\"total_count\"></span> cookie domains.\n    <span id=\"delete_all_button\"></span>\n  </div>\n  <br />\n  <table id=\"cookies\">\n    <tr class=\"header\">\n      <th>Name</th>\n      <th>#Cookies</th>\n    </tr>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/cookies/manager.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nif (!chrome.cookies) {\n  chrome.cookies = chrome.experimental.cookies;\n}\n\n// A simple Timer class.\nfunction Timer() {\n  this.start_ = new Date();\n\n  this.elapsed = function() {\n    return (new Date()) - this.start_;\n  }\n\n  this.reset = function() {\n    this.start_ = new Date();\n  }\n}\n\n// Compares cookies for \"key\" (name, domain, etc.) equality, but not \"value\"\n// equality.\nfunction cookieMatch(c1, c2) {\n  return (c1.name == c2.name) && (c1.domain == c2.domain) &&\n         (c1.hostOnly == c2.hostOnly) && (c1.path == c2.path) &&\n         (c1.secure == c2.secure) && (c1.httpOnly == c2.httpOnly) &&\n         (c1.session == c2.session) && (c1.storeId == c2.storeId);\n}\n\n// Returns an array of sorted keys from an associative array.\nfunction sortedKeys(array) {\n  var keys = [];\n  for (var i in array) {\n    keys.push(i);\n  }\n  keys.sort();\n  return keys;\n}\n\n// Shorthand for document.querySelector.\nfunction select(selector) {\n  return document.querySelector(selector);\n}\n\n// An object used for caching data about the browser's cookies, which we update\n// as notifications come in.\nfunction CookieCache() {\n  this.cookies_ = {};\n\n  this.reset = function() {\n    this.cookies_ = {};\n  }\n\n  this.add = function(cookie) {\n    var domain = cookie.domain;\n    if (!this.cookies_[domain]) {\n      this.cookies_[domain] = [];\n    }\n    this.cookies_[domain].push(cookie);\n  };\n\n  this.remove = function(cookie) {\n    var domain = cookie.domain;\n    if (this.cookies_[domain]) {\n      var i = 0;\n      while (i < this.cookies_[domain].length) {\n        if (cookieMatch(this.cookies_[domain][i], cookie)) {\n          this.cookies_[domain].splice(i, 1);\n        } else {\n          i++;\n        }\n      }\n      if (this.cookies_[domain].length == 0) {\n        delete this.cookies_[domain];\n      }\n    }\n  };\n\n  // Returns a sorted list of cookie domains that match |filter|. If |filter| is\n  //  null, returns all domains.\n  this.getDomains = function(filter) {\n    var result = [];\n    sortedKeys(this.cookies_).forEach(function(domain) {\n      if (!filter || domain.indexOf(filter) != -1) {\n        result.push(domain);\n      }\n    });\n    return result;\n  }\n\n  this.getCookies = function(domain) {\n    return this.cookies_[domain];\n  };\n}\n\n\nvar cache = new CookieCache();\n\n\nfunction removeAllForFilter() {\n  var filter = select(\"#filter\").value;\n  var timer = new Timer();\n  cache.getDomains(filter).forEach(function(domain) {\n    removeCookiesForDomain(domain);\n  });\n}\n\nfunction removeAll() {\n  var all_cookies = [];\n  cache.getDomains().forEach(function(domain) {\n    cache.getCookies(domain).forEach(function(cookie) {\n      all_cookies.push(cookie);\n    });\n  });\n  cache.reset();\n  var count = all_cookies.length;\n  var timer = new Timer();\n  for (var i = 0; i < count; i++) {\n    removeCookie(all_cookies[i]);\n  }\n  timer.reset();\n  chrome.cookies.getAll({}, function(cookies) {\n    for (var i in cookies) {\n      cache.add(cookies[i]);\n      removeCookie(cookies[i]);\n    }\n  });\n}\n\nfunction removeCookie(cookie) {\n  var url = \"http\" + (cookie.secure ? \"s\" : \"\") + \"://\" + cookie.domain +\n            cookie.path;\n  chrome.cookies.remove({\"url\": url, \"name\": cookie.name});\n}\n\nfunction removeCookiesForDomain(domain) {\n  var timer = new Timer();\n  cache.getCookies(domain).forEach(function(cookie) {\n    removeCookie(cookie);\n  });\n}\n\nfunction resetTable() {\n  var table = select(\"#cookies\");\n  while (table.rows.length > 1) {\n    table.deleteRow(table.rows.length - 1);\n  }\n}\n\nvar reload_scheduled = false;\n\nfunction scheduleReloadCookieTable() {\n  if (!reload_scheduled) {\n    reload_scheduled = true;\n    setTimeout(reloadCookieTable, 250);\n  }\n}\n\nfunction reloadCookieTable() {\n  reload_scheduled = false;\n\n  var filter = select(\"#filter\").value;\n\n  var domains = cache.getDomains(filter);\n\n  select(\"#filter_count\").innerText = domains.length;\n  select(\"#total_count\").innerText = cache.getDomains().length;\n\n  select(\"#delete_all_button\").innerHTML = \"\";\n  if (domains.length) {\n    var button = document.createElement(\"button\");\n    button.onclick = removeAllForFilter;\n    button.innerText = \"delete all \" + domains.length;\n    select(\"#delete_all_button\").appendChild(button);\n  }\n\n  resetTable();\n  var table = select(\"#cookies\");\n\n  domains.forEach(function(domain) {\n    var cookies = cache.getCookies(domain);\n    var row = table.insertRow(-1);\n    row.insertCell(-1).innerText = domain;\n    var cell = row.insertCell(-1);\n    cell.innerText = cookies.length;\n    cell.setAttribute(\"class\", \"cookie_count\");\n\n    var button = document.createElement(\"button\");\n    button.innerText = \"delete\";\n    button.onclick = (function(dom){\n      return function() {\n        removeCookiesForDomain(dom);\n      };\n    }(domain));\n    var cell = row.insertCell(-1);\n    cell.appendChild(button);\n    cell.setAttribute(\"class\", \"button\");\n  });\n}\n\nfunction focusFilter() {\n  select(\"#filter\").focus();\n}\n\nfunction resetFilter() {\n  var filter = select(\"#filter\");\n  filter.focus();\n  if (filter.value.length > 0) {\n    filter.value = \"\";\n    reloadCookieTable();\n  }\n}\n\nvar ESCAPE_KEY = 27;\nwindow.onkeydown = function(event) {\n  if (event.keyCode == ESCAPE_KEY) {\n    resetFilter();\n  }\n}\n\nfunction listener(info) {\n  cache.remove(info.cookie);\n  if (!info.removed) {\n    cache.add(info.cookie);\n  }\n  scheduleReloadCookieTable();\n}\n\nfunction startListening() {\n  chrome.cookies.onChanged.addListener(listener);\n}\n\nfunction stopListening() {\n  chrome.cookies.onChanged.removeListener(listener);\n}\n\nfunction onload() {\n  focusFilter();\n  var timer = new Timer();\n  chrome.cookies.getAll({}, function(cookies) {\n    startListening();\n    start = new Date();\n    for (var i in cookies) {\n      cache.add(cookies[i]);\n    }\n    timer.reset();\n    reloadCookieTable();\n  });\n}\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  onload();\n  document.body.addEventListener('click', focusFilter);\n  document.querySelector('#remove_button').addEventListener('click', removeAll);\n  document.querySelector('#filter_div input').addEventListener(\n      'input', reloadCookieTable);\n  document.querySelector('#filter_div button').addEventListener(\n      'click', resetFilter);\n});\n"
  },
  {
    "path": "_archive/mv2/api/cookies/manifest.json",
    "content": "{\n  \"name\" : \"Cookie API Test Extension\",\n  \"version\" : \"0.8\",\n  \"description\" : \"Testing Cookie API\",\n  \"permissions\": [ \"cookies\", \"tabs\", \"http://*/*\", \"https://*/*\" ],\n  \"icons\": { \"16\": \"cookie.png\", \"48\": \"cookie.png\", \"128\": \"cookie.png\" },\n  \"browser_action\": {\n    \"default_icon\": \"cookie.png\"\n  },\n  \"background\": {\n    \"scripts\": [\"background.js\"]\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/debugger/live-headers/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.browserAction.onClicked.addListener(function(tab) {\n  chrome.debugger.attach({tabId:tab.id}, version,\n      onAttach.bind(null, tab.id));\n});\n\nvar version = \"1.0\";\n\nfunction onAttach(tabId) {\n  if (chrome.runtime.lastError) {\n    alert(chrome.runtime.lastError.message);\n    return;\n  }\n\n  chrome.windows.create(\n      {url: \"headers.html?\" + tabId, type: \"popup\", width: 800, height: 600});\n}\n"
  },
  {
    "path": "_archive/mv2/api/debugger/live-headers/headers.html",
    "content": "<!--\nCopyright (c) 2012 The Chromium Authors. All rights reserved.\nUse of this source code is governed by a BSD-style license that can be\nfound in the LICENSE file.\n-->\n\n<html>\n<head>\n<style>\nbody {\n  font-family: monospace;\n  word-wrap: break-word;\n}\n\n#container {\n  white-space: pre;\n}\n\n.request {\n  border-top: 1px solid black;\n  margin-bottom: 10px;\n}\n\n</style>\n\n<script src=\"headers.js\"></script>\n</head>\n\n<body>\n<div id=\"container\"></div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/debugger/live-headers/headers.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar tabId = parseInt(window.location.search.substring(1));\n\nwindow.addEventListener(\"load\", function() {\n  chrome.debugger.sendCommand({tabId:tabId}, \"Network.enable\");\n  chrome.debugger.onEvent.addListener(onEvent);\n});\n\nwindow.addEventListener(\"unload\", function() {\n  chrome.debugger.detach({tabId:tabId});\n});\n\nvar requests = {};\n\nfunction onEvent(debuggeeId, message, params) {\n  if (tabId != debuggeeId.tabId)\n    return;\n\n  if (message == \"Network.requestWillBeSent\") {\n    var requestDiv = requests[params.requestId];\n    if (!requestDiv) {\n      var requestDiv = document.createElement(\"div\");\n      requestDiv.className = \"request\";\n      requests[params.requestId] = requestDiv;\n      var urlLine = document.createElement(\"div\");\n      urlLine.textContent = params.request.url;\n      requestDiv.appendChild(urlLine);\n    }\n\n    if (params.redirectResponse)\n      appendResponse(params.requestId, params.redirectResponse);\n\n    var requestLine = document.createElement(\"div\");\n    requestLine.textContent = \"\\n\" + params.request.method + \" \" +\n        parseURL(params.request.url).path + \" HTTP/1.1\";\n    requestDiv.appendChild(requestLine);\n    document.getElementById(\"container\").appendChild(requestDiv);\n  } else if (message == \"Network.responseReceived\") {\n    appendResponse(params.requestId, params.response);\n  }\n}\n\nfunction appendResponse(requestId, response) {\n  var requestDiv = requests[requestId];\n  requestDiv.appendChild(formatHeaders(response.requestHeaders));\n\n  var statusLine = document.createElement(\"div\");\n  statusLine.textContent = \"\\nHTTP/1.1 \" + response.status + \" \" +\n      response.statusText;\n  requestDiv.appendChild(statusLine);\n  requestDiv.appendChild(formatHeaders(response.headers));\n}\n\nfunction formatHeaders(headers) {\n  var text = \"\";\n  for (name in headers)\n    text += name + \": \" + headers[name] + \"\\n\";\n  var div = document.createElement(\"div\");\n  div.textContent = text;\n  return div;\n}\n\nfunction parseURL(url) {\n  var result = {};\n  var match = url.match(\n      /^([^:]+):\\/\\/([^\\/:]*)(?::([\\d]+))?(?:(\\/[^#]*)(?:#(.*))?)?$/i);\n  if (!match)\n    return result;\n  result.scheme = match[1].toLowerCase();\n  result.host = match[2];\n  result.port = match[3];\n  result.path = match[4] || \"/\";\n  result.fragment = match[5];\n  return result;\n}"
  },
  {
    "path": "_archive/mv2/api/debugger/live-headers/manifest.json",
    "content": "{\n  \"name\": \"Live HTTP headers\",\n  \"description\": \"Displays the live log with the http requests headers\",\n  \"version\": \"0.7\",\n  \"permissions\": [\n    \"debugger\"\n  ],\n  \"background\": {\n    \"scripts\": [\"background.js\"]\n  },\n  \"browser_action\": {\n    \"default_icon\": \"icon.png\",\n    \"default_title\": \"Live HTTP headers\"\n  },\n  \"manifest_version\": 2\n}\n\n"
  },
  {
    "path": "_archive/mv2/api/debugger/pause-resume/background.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar attachedTabs = {};\nvar version = \"1.0\";\n\nchrome.debugger.onEvent.addListener(onEvent);\nchrome.debugger.onDetach.addListener(onDetach);\n\nchrome.browserAction.onClicked.addListener(function(tab) {\n  var tabId = tab.id;\n  var debuggeeId = {tabId:tabId};\n\n  if (attachedTabs[tabId] == \"pausing\")\n    return;\n\n  if (!attachedTabs[tabId])\n    chrome.debugger.attach(debuggeeId, version, onAttach.bind(null, debuggeeId));\n  else if (attachedTabs[tabId])\n    chrome.debugger.detach(debuggeeId, onDetach.bind(null, debuggeeId));\n});\n\nfunction onAttach(debuggeeId) {\n  if (chrome.runtime.lastError) {\n    alert(chrome.runtime.lastError.message);\n    return;\n  }\n\n  var tabId = debuggeeId.tabId;\n  chrome.browserAction.setIcon({tabId: tabId, path:\"debuggerPausing.png\"});\n  chrome.browserAction.setTitle({tabId: tabId, title:\"Pausing JavaScript\"});\n  attachedTabs[tabId] = \"pausing\";\n  chrome.debugger.sendCommand(\n      debuggeeId, \"Debugger.enable\", {},\n      onDebuggerEnabled.bind(null, debuggeeId));\n}\n\nfunction onDebuggerEnabled(debuggeeId) {\n  chrome.debugger.sendCommand(debuggeeId, \"Debugger.pause\");\n}\n\nfunction onEvent(debuggeeId, method) {\n  var tabId = debuggeeId.tabId;\n  if (method == \"Debugger.paused\") {\n    attachedTabs[tabId] = \"paused\";\n    chrome.browserAction.setIcon({tabId:tabId, path:\"debuggerContinue.png\"});\n    chrome.browserAction.setTitle({tabId:tabId, title:\"Resume JavaScript\"});\n  }\n}\n\nfunction onDetach(debuggeeId) {\n  var tabId = debuggeeId.tabId;\n  delete attachedTabs[tabId];\n  chrome.browserAction.setIcon({tabId:tabId, path:\"debuggerPause.png\"});\n  chrome.browserAction.setTitle({tabId:tabId, title:\"Pause JavaScript\"});\n}\n"
  },
  {
    "path": "_archive/mv2/api/debugger/pause-resume/manifest.json",
    "content": "{\n  \"name\": \"JavaScript pause/resume\",\n  \"description\": \"Pauses / resumes JavaScript execution\",\n  \"version\": \"0.7\",\n  \"permissions\": [\n    \"debugger\"\n  ],\n  \"background\": {\n    \"scripts\": [\"background.js\"]\n  },\n  \"browser_action\": {\n    \"default_icon\": \"debuggerPause.png\",\n    \"default_title\": \"Pause JavaScript\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/default_command_override/background.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nchrome.commands.onCommand.addListener(function(command) {\n  chrome.tabs.query({currentWindow: true}, function(tabs) {\n    // Sort tabs according to their index in the window.\n    tabs.sort((a, b) => { return a.index < b.index; });\n    let activeIndex = tabs.findIndex((tab) => { return tab.active; });\n    let lastTab = tabs.length - 1;\n    let newIndex = -1;\n    if (command === 'flip-tabs-forward')\n      newIndex = activeIndex === 0 ? lastTab : activeIndex - 1;\n    else  // 'flip-tabs-backwards'\n      newIndex = activeIndex === lastTab ? 0 : activeIndex + 1;\n    chrome.tabs.update(tabs[newIndex].id, {active: true, highlighted: true});\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/default_command_override/manifest.json",
    "content": "{\n  \"name\": \"Tab Flipper\",\n  \"description\": \"Press Ctrl+Shift+Right or Ctrl+Shift+Left (Command+Shift+Right or Command+Shift+Left on a Mac) to flip through window tabs\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 2,\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"browser_action\": {\n    \"default_icon\": \"images/tabFlipper16.png\",\n    \"default_title\": \"Press Ctrl(Win)/Command(Mac)+Shift+ Left or Right to Flip Tabs\"\n  },\n  \"commands\": {\n    \"flip-tabs-forward\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+Shift+Right\",\n        \"mac\": \"Command+Shift+Right\"\n      },\n      \"description\": \"Flip tabs forward\"\n    },\n    \"flip-tabs-backwards\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+Shift+Left\",\n        \"mac\": \"Command+Shift+Left\"\n      },\n      \"description\": \"Flip tabs backwards\"\n    }\n  },\n  \"icons\": {\n    \"16\": \"images/tabFlipper16.png\",\n    \"32\": \"images/tabFlipper32.png\",\n    \"48\": \"images/tabFlipper48.png\",\n    \"128\": \"images/tabFlipper128.png\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/desktopCapture/app.js",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nconst DESKTOP_MEDIA = ['screen', 'window', 'tab', 'audio'];\n\nvar pending_request_id = null;\nvar pc1 = null;\nvar pc2 = null;\n\n// Launch the chooseDesktopMedia().\ndocument.querySelector('#start').addEventListener('click', function(event) {\n  pending_request_id = chrome.desktopCapture.chooseDesktopMedia(\n      DESKTOP_MEDIA, onAccessApproved);\n});\n\ndocument.querySelector('#cancel').addEventListener('click', function(event) {\n  if (pending_request_id != null) {\n    chrome.desktopCapture.cancelChooseDesktopMedia(pending_request_id);\n  }\n});\n\ndocument.querySelector('#startFromBackgroundPage')\n    .addEventListener('click', function(event) {\n      chrome.runtime.sendMessage(\n          {}, function(response) { console.log(response.farewell); });\n    });\n\n// Launch webkitGetUserMedia() based on selected media id.\nfunction onAccessApproved(id, options) {\n  if (!id) {\n    console.log('Access rejected.');\n    return;\n  }\n\n  var audioConstraint = {\n      mandatory: {\n        chromeMediaSource: 'desktop',\n        chromeMediaSourceId: id\n      }\n  };\n\n  console.log(options.canRequestAudioTrack);\n  if (!options.canRequestAudioTrack)\n    audioConstraint = false;\n\n  navigator.webkitGetUserMedia({\n    audio: audioConstraint,\n    video: {\n      mandatory: {\n        chromeMediaSource: 'desktop',\n        chromeMediaSourceId: id,\n        maxWidth:screen.width,\n        maxHeight:screen.height} }\n  }, gotStream, getUserMediaError);\n}\n\nfunction getUserMediaError(error) {\n  console.log('navigator.webkitGetUserMedia() errot: ', error);\n}\n\n// Capture video/audio of media and initialize RTC communication.\nfunction gotStream(stream) {\n  console.log('Received local stream', stream);\n  var video = document.querySelector('video');\n  try {\n    video.srcObject = stream;\n  } catch (error) {\n    video.src = URL.createObjectURL(stream);\n  }\n  stream.onended = function() { console.log('Ended'); };\n\n  pc1 = new RTCPeerConnection();\n  pc1.onicecandidate = function(event) {\n    onIceCandidate(pc1, event);\n  };\n  pc2 = new RTCPeerConnection();\n  pc2.onicecandidate = function(event) {\n    onIceCandidate(pc2, event);\n  };\n  pc1.oniceconnectionstatechange = function(event) {\n    onIceStateChange(pc1, event);\n  };\n  pc2.oniceconnectionstatechange = function(event) {\n    onIceStateChange(pc2, event);\n  };\n  pc2.onaddstream = gotRemoteStream;\n\n  pc1.addStream(stream);\n\n  pc1.createOffer(onCreateOfferSuccess, function() {});\n}\n\nfunction onCreateOfferSuccess(desc) {\n  pc1.setLocalDescription(desc);\n  pc2.setRemoteDescription(desc);\n  // Since the 'remote' side has no media stream we need\n  // to pass in the right constraints in order for it to\n  // accept the incoming offer of audio and video.\n  var sdpConstraints = {\n    'mandatory': {\n      'OfferToReceiveAudio': true,\n      'OfferToReceiveVideo': true\n    }\n  };\n  pc2.createAnswer(onCreateAnswerSuccess, function(){}, sdpConstraints);\n}\n\nfunction gotRemoteStream(event) {\n  // Call the polyfill wrapper to attach the media stream to this element.\n  console.log('hitting this code');\n  try {\n    remoteVideo.srcObject = event.stream;\n  } catch (error) {\n    remoteVideo.src = URL.createObjectURL(event.stream);\n  }\n}\n\nfunction onCreateAnswerSuccess(desc) {\n  pc2.setLocalDescription(desc);\n  pc1.setRemoteDescription(desc);\n}\n\nfunction onIceCandidate(pc, event) {\n  if (event.candidate) {\n    var remotePC = (pc === pc1) ? pc2 : pc1;\n    remotePC.addIceCandidate(new RTCIceCandidate(event.candidate));\n  }\n}\n\nfunction onIceStateChange(pc, event) {\n  if (pc) {\n    console.log('ICE state change event: ', event);\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/desktopCapture/background.js",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('index.html', {\n    bounds: {\n      width: 1080,\n      height: 550\n    }\n  });\n});\n\nchrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {\n  chrome.desktopCapture.chooseDesktopMedia(\n      [\"screen\", \"window\"],\n      function(id) {\n        sendResponse({\"id\": id});\n      });\n});\n"
  },
  {
    "path": "_archive/mv2/api/desktopCapture/index.html",
    "content": "<html>\n<head>\n<style>\n  body {\n    background: white;\n    display: -webkit-flex;\n    -webkit-justify-content: center;\n    -webkit-align-items: center;\n    -webkit-flex-direction: column;\n  }\n  video {\n    width: 480px;\n    height: 360px;\n    border: 1px solid #e2e2e2;\n    box-shadow: 0 1px 1px rgba(0,0,0,0.2);\n  }\n</style>\n</head>\n<body>\n  <div>\n    <video id=\"video\" autoplay></video>\n    <video id=\"remoteVideo\" autoplay></video>\n  </div>\n  <p>\n    <button id=\"start\">Start</button>\n    <button id=\"cancel\">Cancel</button>\n    <button id=\"startFromBackgroundPage\">Start from background page</button>\n  </p>\n  <script src=\"app.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/desktopCapture/manifest.json",
    "content": "{\n  \"key\": \"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjd3VZe2un2t/ju5HGcZrbD862LLhtukwtXeySPzbQaq9zEyFzr+pVd1EeAW7ZPUA86K9/mpWiDycoSMMj9hpm+QQqBnQDrPPtBJfogkFvWsgDQaw6SXZmErTlzz1wukn/0YLQrPLJ7JPj3zGzWcoVj9AhOjQeDpq2E9P3lz85mHwG0RrxgpknP1wGNNkXl/y4WDaWHZyoX1zgcn2r3bzTdb77RWiA9pduXSn6d14GA9B9CdQA4bTDmc9HY1WaVGK0oDX2A2eJEllHqdeBJmpqPqds4cIhm0Gq6lKvxB61I2UZlbCaSIMfTTxBnt+r7NPgpxHBKJIF1xOCpuGtWuc0wIDAQAB\",\n  \"name\": \"Desktop Capture Example\",\n  \"description\": \"Show desktop media picker UI\",\n  \"version\": \"1\",\n  \"manifest_version\": 3,\n  \"icons\": {\n    \"16\": \"icon.png\",\n    \"128\": \"icon.png\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [\n    \"desktopCapture\"\n  ]\n}\n"
  },
  {
    "path": "_archive/mv2/api/deviceInfo/basic/manifest.json",
    "content": "{\n  \"name\": \"My Devices\",\n  \"version\": \"1.1\",\n  \"description\": \"A browser action with a popup dump of all devices signed into the same account as the current profile.\",\n  \"permissions\": [\n     \"signedInDevices\"\n  ],\n  \"browser_action\": {\n      \"default_title\": \"My Devices\",\n      \"default_icon\": \"icon.png\",\n      \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 2,\n  \"content_security_policy\": \"script-src 'self' https://ajax.googleapis.com; object-src 'self'\"\n}\n"
  },
  {
    "path": "_archive/mv2/api/deviceInfo/basic/popup.html",
    "content": "<html>\n<head>\n  <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js\"></script>\n  <script src=\"popup.js\"></script>\n</head>\n<body style=\"width: 400px\">\n  <div id=\"deviceinfos\"></div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/deviceInfo/basic/popup.js",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction dumpDevices(devices) {\n    $('#deviceinfos').empty();\n    $('#deviceinfos').append(outputDevicesToList(devices));\n}\n\nfunction outputDevicesToList(devices) {\n    var table = $('<table border=\"1\">');\n    table.append($(\"<tr>\" +\n                   \"<th>\" + \"Name\" + \"</th>\" +\n                   \"<th>\" + \"OS\" + \"</th>\" +\n                   \"<th>\" + \"Id\" + \"</th>\" +\n                   \"<th>\" + \"Type\" + \"</th>\" +\n                   \"<th>\" + \"Chrome Version\" + \"</th>\" +\n                   \"</tr>\"));\n    for (i = 0; i < devices.length; i++) {\n        table.append($(\"<tr>\" +\n                       \"<td>\" + devices[i].name + \"</td>\" +\n                       \"<td>\" + devices[i].os + \"</td>\" +\n                       \"<td>\" + devices[i].id + \"</td>\" +\n                       \"<td>\" + devices[i].type + \"</td>\" +\n                       \"<td>\" + devices[i].chromeVersion + \"</td>\" +\n                       \"</tr>\"));\n    }\n    return table;\n}\n\n// Add an event listener to listen for changes to device info. The\n// callback would redisplay the list of devices.\nchrome.signedInDevices.onDeviceInfoChange.addListener(dumpDevices);\n\nfunction populateDevices() {\n  // Get the list of devices and display it.\n  chrome.signedInDevices.get(false, dumpDevices);\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n    populateDevices();\n});\n"
  },
  {
    "path": "_archive/mv2/api/devtools/network/chrome-firephp/background.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nconst tab_log = function(json_args) {\n  var args = JSON.parse(unescape(json_args));\n  console[args[0]].apply(console, Array.prototype.slice.call(args, 1));\n}\n\nchrome.extension.onRequest.addListener(function(request) {\n  if (request.command !== 'sendToConsole')\n    return;\n  chrome.tabs.executeScript(request.tabId, {\n      code: \"(\"+ tab_log + \")('\" + request.args + \"');\",\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/devtools/network/chrome-firephp/devtools.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Devtools Page</title>\n    <script src=\"devtools.js\"></script>\n    <script src=\"./background.js\" type=\"text/javascript\"></script>\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/devtools/network/chrome-firephp/devtools.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction Console() {\n}\n\nConsole.Type = {\n  LOG: \"log\",\n  DEBUG: \"debug\",\n  INFO: \"info\",\n  WARN: \"warn\",\n  ERROR: \"error\",\n  GROUP: \"group\",\n  GROUP_COLLAPSED: \"groupCollapsed\",\n  GROUP_END: \"groupEnd\"\n};\n\nConsole.addMessage = function(type, format, args) {\n  chrome.extension.sendRequest({\n      command: \"sendToConsole\",\n      tabId: chrome.devtools.tabId,\n      args: escape(JSON.stringify(Array.prototype.slice.call(arguments, 0)))\n  });\n};\n\n// Generate Console output methods, i.e. Console.log(), Console.debug() etc.\n(function() {\n  var console_types = Object.getOwnPropertyNames(Console.Type);\n  for (var type = 0; type < console_types.length; ++type) {\n    var method_name = Console.Type[console_types[type]];\n    Console[method_name] = Console.addMessage.bind(Console, method_name);\n  }\n})();\n\nfunction ChromeFirePHP() {\n};\n\nChromeFirePHP.handleFirePhpHeaders = function(har_entry) {\n  var response_headers = har_entry.response.headers;\n  var wf_header_map = {};\n  var had_wf_headers = false;\n\n  for (var i = 0; i < response_headers.length; ++i) {\n    var header = response_headers[i];\n    if (/^X-Wf-/.test(header.name)) {\n      wf_header_map[header.name] = header.value;\n      had_wf_headers = true;\n    }\n  }\n\n  var proto_header = wf_header_map[\"X-Wf-Protocol-1\"];\n  if (!had_wf_headers || !this._checkProtoVersion(proto_header))\n    return;\n\n  var message_objects = this._buildMessageObjects(wf_header_map);\n  message_objects.sort(function(a, b) {\n      var aFile = a.File || \"\";\n      var bFile = b.File || \"\";\n      if (aFile !== bFile)\n        return aFile.localeCompare(bFile);\n      var aLine = a.Line !== undefined ? a.Line : -1;\n      var bLine = b.Line !== undefined ? b.Line : -1;\n      return aLine - bLine;\n  });\n\n  var context = { pageRef: har_entry.pageref };\n  for (var i = 0; i < message_objects.length; ++i)\n    this._processLogMessage(message_objects[i], context);\n  if (context.groupStarted)\n    Console.groupEnd();\n};\n\nChromeFirePHP._processLogMessage = function(message, context) {\n  var meta = message[0];\n  if (!meta) {\n    Console.error(\"No Meta in FirePHP message\");\n    return;\n  }\n\n  var body = message[1];\n  var type = meta.Type;\n  if (!type) {\n    Console.error(\"No Type for FirePHP message\");\n    return;\n  }\n\n  switch (type) {\n    case \"LOG\":\n    case \"INFO\":\n    case \"WARN\":\n    case \"ERROR\":\n      if (!context.groupStarted) {\n        context.groupStarted = true;\n        Console.groupCollapsed(context.pageRef || \"\");\n      }\n      Console.addMessage(Console.Type[type], \"%s%o\",\n          (meta.Label ? meta.Label + \": \" : \"\"), body);\n      break;\n    case \"EXCEPTION\":\n    case \"TABLE\":\n    case \"TRACE\":\n    case \"GROUP_START\":\n    case \"GROUP_END\":\n     // FIXME: implement\n     break;\n  }\n};\n\nChromeFirePHP._buildMessageObjects = function(header_map)\n{\n  const normal_header_prefix = \"X-Wf-1-1-1-\";\n\n  return this._collectMessageObjectsForPrefix(header_map, normal_header_prefix);\n};\n\nChromeFirePHP._collectMessageObjectsForPrefix = function(header_map, prefix) {\n  var results = [];\n  const header_regexp = /(?:\\d+)?\\|(.+)/;\n  var json = \"\";\n  for (var i = 1; ; ++i) {\n    var name = prefix + i;\n    var value = header_map[name];\n    if (!value)\n      break;\n\n    var match = value.match(header_regexp);\n    if (!match) {\n      Console.error(\"Failed to parse FirePHP log message: \" + value);\n      break;\n    }\n    var json_part = match[1];\n    json += json_part.substring(0, json_part.lastIndexOf(\"|\"));\n    if (json_part.charAt(json_part.length - 1) === \"\\\\\")\n      continue;\n    try {\n      var message = JSON.parse(json);\n      results.push(message);\n    } catch(e) {\n      Console.error(\"Failed to parse FirePHP log message: \" + json);\n    }\n    json = \"\";\n  }\n  return results;\n};\n\nChromeFirePHP._checkProtoVersion = function(proto_header) {\n  if (!proto_header) {\n    Console.warn(\"WildFire protocol header not found\");\n    return;\n  }\n\n  var match = /http:\\/\\/meta\\.wildfirehq\\.org\\/Protocol\\/([^\\/]+)\\/(.+)/.exec(\n      proto_header);\n  if (!match) {\n    Console.warn(\"Invalid WildFire protocol header\");\n    return;\n  }\n  var proto_name = match[1];\n  var proto_version = match[2];\n  if (proto_name !== \"JsonStream\" || proto_version !== \"0.2\") {\n    Console.warn(\n        \"Unknown FirePHP protocol version: %s (expecting JsonStream/0.2)\",\n        proto_name + \"/\" + proto_version);\n    return false;\n  }\n  return true;\n};\n\nchrome.devtools.network.addRequestHeaders({\n    \"X-FirePHP-Version\": \"0.0.6\"\n});\n\nchrome.devtools.network.getHAR(function(result) {\n  var entries = result.entries;\n  if (!entries.length) {\n    Console.warn(\"ChromeFirePHP suggests that you reload the page to track\" +\n        \" FirePHP messages for all the requests\");\n  }\n  for (var i = 0; i < entries.length; ++i)\n    ChromeFirePHP.handleFirePhp_headers(entries[i]);\n\n  chrome.devtools.network.onRequestFinished.addListener(\n      ChromeFirePHP.handleFirePhpHeaders.bind(ChromeFirePHP));\n});\n"
  },
  {
    "path": "_archive/mv2/api/devtools/network/chrome-firephp/manifest.json",
    "content": "{\n  \"name\": \"FirePHP for Chrome\",\n  \"version\": \"1.1\",\n  \"minimum_chrome_version\": \"10.0\",\n  \"description\": \"Extends the Developer Tools, adding support for parsing FirePHP messages from server\",\n  \"devtools_page\": \"devtools.html\",\n  \"background\": { \"scripts\": [\"background.js\"] },\n  \"permissions\": [\n    \"http://*/*\",\n    \"https://*/*\"\n  ],\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/devtools/panels/chrome-query/devtools.html",
    "content": "<html>\n<body>\n<script src=\"devtools.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "_archive/mv2/api/devtools/panels/chrome-query/devtools.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// The function below is executed in the context of the inspected page.\nvar page_getProperties = function() {\n  var data = window.jQuery && $0 ? jQuery.data($0) : {};\n  // Make a shallow copy with a null prototype, so that sidebar does not\n  // expose prototype.\n  var props = Object.getOwnPropertyNames(data);\n  var copy = { __proto__: null };\n  for (var i = 0; i < props.length; ++i)\n    copy[props[i]] = data[props[i]];\n  return copy;\n}\n\nchrome.devtools.panels.elements.createSidebarPane(\n    \"jQuery Properties\",\n    function(sidebar) {\n  function updateElementProperties() {\n    sidebar.setExpression(\"(\" + page_getProperties.toString() + \")()\");\n  }\n  updateElementProperties();\n  chrome.devtools.panels.elements.onSelectionChanged.addListener(\n      updateElementProperties);\n});\n"
  },
  {
    "path": "_archive/mv2/api/devtools/panels/chrome-query/manifest.json",
    "content": "{\n  \"name\": \"Chrome Query\",\n  \"version\": \"1.1\",\n  \"description\": \"Extends the Developer Tools, adding a sidebar that displays the jQuery data associated with the selected DOM element.\",\n  \"devtools_page\": \"devtools.html\",\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/displaySource/tabCast/README",
    "content": "Demo Chrome extension that utilizes chrome.displaySource API's.\nThe extension creates a WiFi Display Session from the captured tab media stream.\n"
  },
  {
    "path": "_archive/mv2/api/displaySource/tabCast/background.js",
    "content": "// Copyright 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar g_sessionInfo = {};\n\n/**\n * When extension icon clicked, get device list\n * Then return the list to popup page\n */\nchrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {\n  if (message.browserActionClicked) {\n    getDeviceList(function(deviceList) {\n      sendResponse({ returnDeviceList: deviceList });\n    });\n  }\n  return true;\n});\n\nfunction getDeviceList(callback) {\n  chrome.displaySource.getAvailableSinks(callback);\n}\n\nchrome.displaySource.onSessionTerminated.addListener(function(terminatedSink) {\n  chrome.runtime.sendMessage({ sessionTerminated: true,\n                               currentSinkId: terminatedSink });\n\n  if (g_sessionInfo.stream) {\n    g_sessionInfo.stream.getTracks().forEach(function (track) {\n        track.stop(); });\n    delete g_sessionInfo.stream;\n  }\n  delete g_sessionInfo.sinkId;\n});\n\nchrome.displaySource.onSinksUpdated.addListener(function(updatedSinks) {\n  console.log('Sinks updated');\n  chrome.runtime.sendMessage({ sinksUpdated: true,\n                               currentSinkId: g_sessionInfo.sinkId,\n                               sinksList: updatedSinks});\n});\n\nfunction start(sinkId) {\n  // If no session, proceed.\n  if (!g_sessionInfo.sinkId) {\n    g_sessionInfo.sinkId = parseInt(sinkId);\n    captureTabAndStartSession(g_sessionInfo.sinkId);\n  }\n}\n\nfunction captureTabAndStartSession(sink_id) {\n  chrome.tabs.getCurrent(function(tab) {\n      var video_constraints = {\n          mandatory: {\n              chromeMediaSource: 'tab',\n              minWidth: 1920,\n              minHeight: 1080,\n              maxWidth: 1920,\n              maxHeight: 1080,\n              minFrameRate: 60,\n              maxFrameRate: 60\n          }\n       };\n\n       var constraints = {\n           audio: true,\n           video: true,\n           videoConstraints: video_constraints\n       };\n\n       function onStream(stream) {\n         g_sessionInfo.stream = stream;\n         var session_info = {\n             sinkId: sink_id,\n             videoTrack: g_sessionInfo.stream.getVideoTracks()[0],\n             audioTrack: g_sessionInfo.stream.getAudioTracks()[0]\n         };\n\n         function onStarted() {\n           if (chrome.runtime.error) {\n           console.log('The Session to sink ' + g_sessionInfo.sinkId\n               + 'could not start, error: '\n               + chrome.runtime.lastError.message);\n           } else {\n             console.log('The Session to sink ' + g_sessionInfo.sinkId\n             + ' has started.');\n           }\n         }\n         console.log('Starting session to sink: ' + sink_id);\n         chrome.displaySource.startSession(session_info, onStarted);\n       }\n\n       chrome.tabCapture.capture(constraints, onStream);\n  });\n}\n\nfunction stop() {\n  function onTerminated() {\n    if (chrome.runtime.lastError) {\n      console.log('The Session to sink ' + g_sessionInfo.sinkId\n          + 'could not terminate, error: '\n          + chrome.runtime.lastError.message);\n    } else {\n      console.log('The Session to sink ' + g_sessionInfo.sinkId\n          + ' has terminated.');\n    }\n  }\n  console.log('Terminating session to sink: ' + g_sessionInfo.sinkId);\n  chrome.displaySource.terminateSession(g_sessionInfo.sinkId, onTerminated);\n}\n"
  },
  {
    "path": "_archive/mv2/api/displaySource/tabCast/main.css",
    "content": "/* Copyright 2016 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n.connecting {\n  animation: glowing 1500ms infinite;\n  background-color: #004A7F;\n  border-radius: 10px;\n  border: none;\n  color: #FFFFFF;\n  cursor: pointer;\n  font-size: 20px;\n  margin: 1px;\n  outline: none;\n  padding: 5px 10px;\n  width: 170px;\n}\n\n.disconnected {\n  background-color: #004A7F;\n  border-radius: 10px;\n  border: none;\n  color: #FFFFFF;\n  cursor: pointer;\n  font-size: 20px;\n  margin: 1px;\n  outline: none;\n  padding: 5px 10px;\n  width: 170px;\n}\n\n.connected {\n  background-color: #0094FF;\n  border-radius: 10px;\n  border: none;\n  box-shadow: 0 0 20px #0094FF;\n  color: #FFFFFF;\n  cursor: pointer;\n  font-size: 20px;\n  margin: 1px;\n  outline: none;\n  padding: 5px 10px;\n  width: 170px;\n}\n\n@keyframes glowing {\n  0% {\n    background-color: #004A7F;\n    box-shadow: 0 0 3px #004A7F;\n  }\n  50% {\n    background-color: #0094FF;\n    box-shadow: 0 0 10px #0094FF;\n  }\n  100% {\n    background-color: #004A7F;\n    box-shadow: 0 0 3px #004A7F;\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/displaySource/tabCast/main.html",
    "content": "<!--\n * Copyright 2016 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n<!doctype html>\n<html>\n<head>\n  <title>chrome.displaySource API test</title>\n  <script src='main.js'></script>\n  <link rel='stylesheet' type='text/css' href='main.css'>\n</head>\n<body>\n  <div id='deviceList'></div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/displaySource/tabCast/main.js",
    "content": "// Copyright 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.runtime.sendMessage({ browserActionClicked : true }, function(response) {\n  var deviceList = response.returnDeviceList;\n  var backgroundPage = chrome.extension.getBackgroundPage();\n  createButtonList(deviceList, backgroundPage);\n});\n\nchrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {\n  var deviceButton = document.getElementById(message.currentSinkId);\n  var backgroundPage = chrome.extension.getBackgroundPage();\n\n  if (message.sinksUpdated) {\n    var sinks = message.sinksList;\n    var changedSink = null;\n\n    for (let sink of sinks) {\n      if (sink.id == message.currentSinkId) {\n        changedSink = sink;\n      }\n    }\n\n    if (!changedSink) {\n      console.error('Failed to find sink: ' + message.currentSinkId);\n      return;\n    }\n\n    if (changedSink.state == 'Connecting') {\n      changeButtonState(deviceButton, 'connecting', backgroundPage.stop);\n    } else if (changedSink.state == 'Connected') {\n      changeButtonState(deviceButton, 'connected', backgroundPage.stop);\n    }\n  } else if (message.sessionTerminated) {\n    changeButtonState(deviceButton, 'disconnected', backgroundPage.start);\n  }\n});\n\nfunction createButtonList(deviceList, backgroundPage) {\n  var divElement = document.getElementById('deviceList');\n  if (!deviceList || !deviceList.length) {\n    var errorMessage = document.createTextNode('No available '\n        + 'sink devices found');\n    divElement.appendChild(errorMessage);\n    return;\n  }\n\n  deviceList.forEach(function(device) {\n    if (!document.getElementById(device.id)) {\n      var deviceButton = document.createElement('input');\n\n      deviceButton.type = 'button';\n      deviceButton.value = device.name;\n      deviceButton.id = device.id;\n\n      if (device.state == 'Disconnected') {\n        changeButtonState(deviceButton, 'disconnected', backgroundPage.start);\n      } else if (device.state == 'Connecting') {\n        changeButtonState(deviceButton, 'connecting', backgroundPage.stop);\n      } else if (device.state == 'Connected') {\n        changeButtonState(deviceButton, 'connected', backgroundPage.stop);\n      } else {\n        console.error('Unexpected sink state.');\n        return;\n      }\n\n      divElement.appendChild(deviceButton);\n    }\n  });\n}\n\nfunction changeButtonState(button, styleName, method) {\n  button.className = styleName;\n  var sinkId = parseInt(button.id);\n  button.onclick = function() { method(sinkId) };\n}\n\n"
  },
  {
    "path": "_archive/mv2/api/displaySource/tabCast/manifest.json",
    "content": "{\n  \"name\": \"tabCast\",\n  \"version\": \"0.1\",\n  \"manifest_version\": 2,\n  \"description\": \"Creates a WiFi Display Session from the captured tab media stream using chrome.displaySource API.\",\n  \"permissions\": [\n    \"tabCapture\", \"tabs\", \"displaySource\"\n  ],\n  \"browser_action\": {\n      \"default_title\": \"Tab cast\",\n      \"default_popup\": \"main.html\"\n  },\n  \"background\": {\n      \"scripts\": [\"background.js\"],\n      \"persistent\": false\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/document_scan/README.md",
    "content": "# Document Scanning API Sample\n\nThis demo interfaces with the Chrome document scanning API to acquire scanned\nimages.\n\n## APIs\n\n* [Document scanning API](https://developer.chrome.com/apps/documentScan)\n* [Runtime](https://developer.chrome.com/apps/runtime)\n* [Window](https://developer.chrome.com/apps/app_window)\n"
  },
  {
    "path": "_archive/mv2/api/document_scan/background.js",
    "content": "// Copyright 2014 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('scan.html', {\n    singleton: true,\n    id: \"ChromeApps-Sample-Document-Scan\",\n    bounds: {\n     'width': 480,\n     'height': 640\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/document_scan/manifest.json",
    "content": "{\n  \"name\": \"Document Scanning API Sample\",\n  \"version\": \"0.1\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"37\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    }\n  },\n  \"permissions\": [],\n  \"optional_permissions\": [ \"documentScan\" ]\n}\n"
  },
  {
    "path": "_archive/mv2/api/document_scan/scan.css",
    "content": "/* Copyright 2014 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#waitAnimation {\n  position: absolute;\n  left: 0px;\n  top: 0px;\n  height:100%;\n  width:100%;\n  z-index:1000;\n  background-color:black;\n  opacity:0.6;\n}\n\n#waitSpinner {\n  position: absolute;\n  height:60px;\n  width:60px;\n  top: 50%;\n  left: 50%;\n  margin-left: -30px;\n  margin-top: -30px;\n  animation: rotation .6s infinite linear;\n  border-left:6px solid rgba(180,174,239,.15);\n  border-right:6px solid rgba(180,174,239,.15);\n  border-bottom:6px solid rgba(180,174,239,.15);\n  border-top:6px solid rgba(180,174,239,.8);\n  border-radius:100%;\n}\n\n@keyframes rotation {\n  from {transform: rotate(0deg);}\n  to {transform: rotate(359deg);}\n}\n"
  },
  {
    "path": "_archive/mv2/api/document_scan/scan.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Scanner Control</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"scan.css\">\n  </head>\n  <body>\n    <div id=\"waitAnimation\" style=\"display: none;\">\n      <div id=\"waitSpinner\"></div>\n    </div>\n    </img>\n    <button id=\"requestButton\">Request App permissions</button>\n    <button id=\"scanButton\">Scan</button>\n    <div id=\"scannedImages\">\n    </div>\n    <script src=\"scan.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/document_scan/scan.js",
    "content": "// Copyright 2014 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar requestButton = document.getElementById(\"requestButton\");\nvar scanButton = document.getElementById('scanButton');\nvar scannedImages = document.getElementById('scannedImages');\nvar waitAnimation = document.getElementById('waitAnimation');\nvar imageMimeType;\n\nfunction setOnlyChild(parent, child) {\n  while (parent.firstChild) {\n    parent.removeChild(parent.firstChild);\n  }\n  parent.appendChild(child);\n}\n\nvar gotPermission = function(result) {\n  waitAnimation.style.display = 'block';\n  requestButton.style.display = 'none';\n  scanButton.style.display = 'block';\n  console.log('App was granted the \"documentScan\" permission.');\n  waitAnimation.style.display = 'none';\n};\n\nvar permissionObj = {permissions: ['documentScan']};\n\nrequestButton.addEventListener('click', function() {\n  waitAnimation.style.display = 'block';\n  chrome.permissions.request( permissionObj, function(result) {\n    if (result) {\n      gotPermission();\n    } else {\n      console.log('App was not granted the \"documentScan\" permission.');\n      console.log(chrome.runtime.lastError);\n    }\n  });\n});\n\nvar onScanCompleted = function(scan_results) {\n  waitAnimation.style.display = 'none';\n  if (chrome.runtime.lastError) {\n    console.log('Scan failed: ' + chrome.runtime.lastError.message);\n    return;\n  }\n  numImages = scan_results.dataUrls.length;\n  console.log('Scan completed with ' + numImages + ' images.');\n  for (var i = 0; i < numImages; i++) {\n    urlData = scan_results.dataUrls[i]\n    console.log('Scan ' + i + ' data length ' +\n                urlData.length + '.');\n    console.log('URL is ' + urlData);\n    var scannedImage = document.createElement('img');\n    scannedImage.src = urlData;\n    scannedImages.insertBefore(scannedImage, scannedImages.firstChild);\n  }\n};\n\nscanButton.addEventListener('click', function() {\n  var scanProperties = {};\n  waitAnimation.style.display = 'block';\n  chrome.documentScan.scan(scanProperties, onScanCompleted);\n});\n\nchrome.permissions.contains(permissionObj, function(result) {\n  if (result) {\n    gotPermission();\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_filename_controller/bg.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction matches(rule, item) {\n  if (rule.matcher == 'js')\n    return eval(rule.match_param);\n  if (rule.matcher == 'hostname') {\n    var link = document.createElement('a');\n    link.href = item.url.toLowerCase();\n    var host = (rule.match_param.indexOf(':') < 0) ? link.hostname : link.host;\n    return (host.indexOf(rule.match_param.toLowerCase()) ==\n            (host.length - rule.match_param.length));\n  }\n  if (rule.matcher == 'default')\n    return item.filename == rule.match_param;\n  if (rule.matcher == 'url-regex')\n    return (new RegExp(rule.match_param)).test(item.url);\n  if (rule.matcher == 'default-regex')\n    return (new RegExp(rule.match_param)).test(item.filename);\n  return false;\n}\n\nchrome.downloads.onDeterminingFilename.addListener(function(item, __suggest) {\n  function suggest(filename, conflictAction) {\n    __suggest({filename: filename,\n               conflictAction: conflictAction,\n               conflict_action: conflictAction});\n    // conflict_action was renamed to conflictAction in\n    // https://chromium.googlesource.com/chromium/src/+/f1d784d6938b8fe8e0d257e41b26341992c2552c\n    // which was first picked up in branch 1580.\n  }\n  var rules = localStorage.rules;\n  try {\n    rules = JSON.parse(rules);\n  } catch (e) {\n    localStorage.rules = JSON.stringify([]);\n  }\n  for (var index = 0; index < rules.length; ++index) {\n    var rule = rules[index];\n    if (rule.enabled && matches(rule, item)) {\n      if (rule.action == 'overwrite') {\n        suggest(item.filename, 'overwrite');\n      } else if (rule.action == 'prompt') {\n        suggest(item.filename, 'prompt');\n      } else if (rule.action == 'js') {\n        eval(rule.action_js);\n      }\n      break;\n    }\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_filename_controller/manifest.json",
    "content": "{\"name\": \"Download Filename Controller\",\n \"description\": \"Download Filename Controller\",\n \"version\": \"0.1\",\n \"background\": {\"scripts\": [\"bg.js\"], \"persistent\": false},\n \"options_page\": \"options.html\",\n \"permissions\": [\"downloads\"],\n \"content_security_policy\": \"script-src 'self'; default-src 'self'\",\n \"manifest_version\": 2}\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_filename_controller/options.html",
    "content": "<!doctype html>\n<html>\n<head>\n<title>Download Filename Controller</title>\n<script src=\"options.js\"></script>\n</head>\n<body>\n<table id=rules></table>\n<button id=new>New Rule</button>\n<table hidden>\n<tr id=rule-template hidden>\n  <td class=nowrap><button class=move-up>&uarr;</button>\n    <button class=move-down>&darr;</button></td>\n  <td>\n    <select class=matcher>\n      <option value=hostname>Hostname</option>\n      <option value=url-regex>URL RegExp</option>\n      <option value=default>Default Filename</option>\n      <option value=default-regex>Default Filename RegExp</option>\n      <option value=js>Javascript</option>\n    </select>\n    <input type=text class=match-param>\n    <select class=action>\n      <option value=overwrite>Overwrite default filename</option>\n      <option value=prompt>Prompt if default filename exists</option>\n      <option value=js>Javascript</option>\n    </select>\n    <textarea class=action-js rows=5 cols=83>console.log(item.url)\nconsole.log(item.filename)\n// http://developer.chrome.com/extensions/downloads.html#type-DownloadItem\n// http://developer.chrome.com/extensions/downloads.html#type-FilenameConflictAction\nsuggest('hello.txt', 'overwrite')</textarea></td>\n  <td><span class=nowrap><input type=checkbox class=enabled checked>\n      <label class=enabled-label>Enabled</label></span>\n    <button class=remove>Remove</button></td>\n</tr>\n</table>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_filename_controller/options.js",
    "content": "// Copyright (c) 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction Rule(data) {\n  var rules = document.getElementById('rules');\n  this.node = document.getElementById('rule-template').cloneNode(true);\n  this.node.id = 'rule' + (Rule.next_id++);\n  this.node.rule = this;\n  rules.appendChild(this.node);\n  this.node.hidden = false;\n\n  if (data) {\n    this.getElement('matcher').value = data.matcher;\n    this.getElement('match-param').value = data.match_param;\n    this.getElement('action').value = data.action;\n    this.getElement('action-js').value = data.action_js;\n    this.getElement('enabled').checked = data.enabled;\n  }\n\n  this.getElement('enabled-label').htmlFor = this.getElement('enabled').id =\n    this.node.id + '-enabled';\n\n  this.render();\n\n  this.getElement('matcher').onchange = storeRules;\n  this.getElement('match-param').onkeyup = storeRules;\n  this.getElement('action').onchange = storeRules;\n  this.getElement('action-js').onkeyup = storeRules;\n  this.getElement('enabled').onchange = storeRules;\n\n  var rule = this;\n  this.getElement('move-up').onclick = function() {\n    var sib = rule.node.previousSibling;\n    rule.node.parentNode.removeChild(rule.node);\n    sib.parentNode.insertBefore(rule.node, sib);\n    storeRules();\n  };\n  this.getElement('move-down').onclick = function() {\n    var parentNode = rule.node.parentNode;\n    var sib = rule.node.nextSibling.nextSibling;\n    parentNode.removeChild(rule.node);\n    if (sib) {\n      parentNode.insertBefore(rule.node, sib);\n    } else {\n      parentNode.appendChild(rule.node);\n    }\n    storeRules();\n  };\n  this.getElement('remove').onclick = function() {\n    rule.node.parentNode.removeChild(rule.node);\n    storeRules();\n  };\n  storeRules();\n}\n\nRule.prototype.getElement = function(name) {\n  return document.querySelector('#' + this.node.id + ' .' + name);\n}\n\nRule.prototype.render = function() {\n  this.getElement('move-up').disabled = !this.node.previousSibling;\n  this.getElement('move-down').disabled = !this.node.nextSibling;\n  this.getElement('action-js').style.display =\n    (this.getElement('action').value == 'js') ? 'block' : 'none';\n}\n\nRule.next_id = 0;\n\nfunction loadRules() {\n  var rules = localStorage.rules;\n  try {\n    JSON.parse(rules).forEach(function(rule) {new Rule(rule);});\n  } catch (e) {\n    localStorage.rules = JSON.stringify([]);\n  }\n}\n\nfunction storeRules() {\n  localStorage.rules = JSON.stringify(Array.prototype.slice.apply(\n      document.getElementById('rules').childNodes).map(function(node) {\n    node.rule.render();\n    return {matcher: node.rule.getElement('matcher').value,\n            match_param: node.rule.getElement('match-param').value,\n            action: node.rule.getElement('action').value,\n            action_js: node.rule.getElement('action-js').value,\n            enabled: node.rule.getElement('enabled').checked};\n  }));\n}\n\nwindow.onload = function() {\n  loadRules();\n  document.getElementById('new').onclick = function() {\n    new Rule();\n  };\n}\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_links/manifest.json",
    "content": "{\n  \"name\": \"Download Selected Links\",\n  \"description\": \"Select links on a page and download them.\",\n  \"version\": \"0.1\",\n  \"minimum_chrome_version\": \"16.0.884\",\n  \"permissions\": [\"downloads\", \"<all_urls>\"],\n  \"browser_action\": {\"default_popup\": \"popup.html\"},\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_links/popup.html",
    "content": "<!DOCTYPE html>\n<head>\n<script src='popup.js'></script>\n</head>\n<body>\n<input type=text id=filter placeholder=Filter>\n<input type=checkbox id=regex>\n<label for=regex>Regex</label><br>\n<button id=download0>Download All!</button>\n<table id=links>\n  <tr>\n    <th><input type=checkbox checked id=toggle_all></th>\n    <th align=left>URL</th>\n  </tr>\n</table>\n<button id=download1>Download All!</button>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_links/popup.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// This extension demonstrates using chrome.downloads.download() to\n// download URLs.\n\nvar allLinks = [];\nvar visibleLinks = [];\n\n// Display all visible links.\nfunction showLinks() {\n  var linksTable = document.getElementById('links');\n  while (linksTable.children.length > 1) {\n    linksTable.removeChild(linksTable.children[linksTable.children.length - 1])\n  }\n  for (var i = 0; i < visibleLinks.length; ++i) {\n    var row = document.createElement('tr');\n    var col0 = document.createElement('td');\n    var col1 = document.createElement('td');\n    var checkbox = document.createElement('input');\n    checkbox.checked = true;\n    checkbox.type = 'checkbox';\n    checkbox.id = 'check' + i;\n    col0.appendChild(checkbox);\n    col1.innerText = visibleLinks[i];\n    col1.style.whiteSpace = 'nowrap';\n    col1.onclick = function() {\n      checkbox.checked = !checkbox.checked;\n    }\n    row.appendChild(col0);\n    row.appendChild(col1);\n    linksTable.appendChild(row);\n  }\n}\n\n// Toggle the checked state of all visible links.\nfunction toggleAll() {\n  var checked = document.getElementById('toggle_all').checked;\n  for (var i = 0; i < visibleLinks.length; ++i) {\n    document.getElementById('check' + i).checked = checked;\n  }\n}\n\n// Download all visible checked links.\nfunction downloadCheckedLinks() {\n  for (var i = 0; i < visibleLinks.length; ++i) {\n    if (document.getElementById('check' + i).checked) {\n      chrome.downloads.download({url: visibleLinks[i]},\n                                             function(id) {\n      });\n    }\n  }\n  window.close();\n}\n\n// Re-filter allLinks into visibleLinks and reshow visibleLinks.\nfunction filterLinks() {\n  var filterValue = document.getElementById('filter').value;\n  if (document.getElementById('regex').checked) {\n    visibleLinks = allLinks.filter(function(link) {\n      return link.match(filterValue);\n    });\n  } else {\n    var terms = filterValue.split(' ');\n    visibleLinks = allLinks.filter(function(link) {\n      for (var termI = 0; termI < terms.length; ++termI) {\n        var term = terms[termI];\n        if (term.length != 0) {\n          var expected = (term[0] != '-');\n          if (!expected) {\n            term = term.substr(1);\n            if (term.length == 0) {\n              continue;\n            }\n          }\n          var found = (-1 !== link.indexOf(term));\n          if (found != expected) {\n            return false;\n          }\n        }\n      }\n      return true;\n    });\n  }\n  showLinks();\n}\n\n// Add links to allLinks and visibleLinks, sort and show them.  send_links.js is\n// injected into all frames of the active tab, so this listener may be called\n// multiple times.\nchrome.extension.onRequest.addListener(function(links) {\n  for (var index in links) {\n    allLinks.push(links[index]);\n  }\n  allLinks.sort();\n  visibleLinks = allLinks;\n  showLinks();\n});\n\n// Set up event handlers and inject send_links.js into all frames in the active\n// tab.\nwindow.onload = function() {\n  document.getElementById('filter').onkeyup = filterLinks;\n  document.getElementById('regex').onchange = filterLinks;\n  document.getElementById('toggle_all').onchange = toggleAll;\n  document.getElementById('download0').onclick = downloadCheckedLinks;\n  document.getElementById('download1').onclick = downloadCheckedLinks;\n\n  chrome.windows.getCurrent(function (currentWindow) {\n    chrome.tabs.query({active: true, windowId: currentWindow.id},\n                      function(activeTabs) {\n      chrome.tabs.executeScript(\n        activeTabs[0].id, {file: 'send_links.js', allFrames: true});\n    });\n  });\n};\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_links/send_links.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Send back to the popup a sorted deduped list of valid link URLs on this page.\n// The popup injects this script into all frames in the active tab.\n\nvar links = [].slice.apply(document.getElementsByTagName('a'));\nlinks = links.map(function(element) {\n  // Return an anchor's href attribute, stripping any URL fragment (hash '#').\n  // If the html specifies a relative path, chrome converts it to an absolute\n  // URL.\n  var href = element.href;\n  var hashIndex = href.indexOf('#');\n  if (hashIndex >= 0) {\n    href = href.substr(0, hashIndex);\n  }\n  return href;\n});\n\nlinks.sort();\n\n// Remove duplicates and invalid URLs.\nvar kBadPrefix = 'javascript';\nfor (var i = 0; i < links.length;) {\n  if (((i > 0) && (links[i] == links[i - 1])) ||\n      (links[i] == '') ||\n      (kBadPrefix == links[i].toLowerCase().substr(0, kBadPrefix.length))) {\n    links.splice(i, 1);\n  } else {\n    ++i;\n  }\n}\n\nchrome.extension.sendRequest(links);\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_manager/_locales/en/messages.json",
    "content": "{\"extName\": {\n   \"message\": \"Download Manager Button\",\n   \"description\": \"Extension name\"},\n \"extDesc\": {\n   \"message\": \"Browser Action Download Manager User Interface for Google Chrome\",\n   \"description\": \"Extension description\"},\n \"badChromeVersion\": {\n   \"message\": \"The downloads API is only available on the canary, dev, and beta channels.\",\n   \"description\": \"\"},\n \"tabTitle\": {\n   \"message\": \"Downloads\",\n   \"description\": \"tab title\"},\n \"searchPlaceholder\": {\n   \"message\": \"Search Downloads\",\n   \"description\": \"\"},\n \"clearAllTitle\": {\n   \"message\": \"Erase All Visible Downloads\",\n   \"description\": \"\"},\n \"openDownloadsFolderTitle\": {\n   \"message\": \"Open Downloads Folder\",\n   \"description\": \"\"},\n \"zeroItems\": {\n   \"message\": \"There are zero download items.\",\n   \"description\": \"\"},\n \"searching\": {\n   \"message\": \"Teleporting lots of goats...\",\n   \"description\": \"\"},\n \"zeroSearchResults\": {\n   \"message\": \"Zero matches\",\n   \"description\": \"\"},\n \"managementPermissionInfo\": {\n   \"message\": \"Some files were downloaded by an extension.\",\n   \"description\": \"\"},\n \"grantManagementPermission\": {\n   \"message\": \"Show links to extensions that download files.\",\n   \"description\": \"\"},\n \"showOlderDownloads\": {\n   \"message\": \"Show Older Downloads\",\n   \"description\": \"\"},\n \"loadingOlderDownloads\": {\n   \"message\": \"Loading Older Downloads...\",\n   \"description\": \"\"},\n \"openTitle\": {\n   \"message\": \"Open\",\n   \"description\": \"\"},\n \"pauseTitle\": {\n   \"message\": \"Pause\",\n   \"description\": \"\"},\n \"resumeTitle\": {\n   \"message\": \"Resume\",\n   \"description\": \"\"},\n \"cancelTitle\": {\n   \"message\": \"Cancel\",\n   \"description\": \"\"},\n \"removeFileTitle\": {\n   \"message\": \"Remove file\",\n   \"description\": \"\"},\n \"eraseTitle\": {\n   \"message\": \"Erase\",\n   \"description\": \"\"},\n \"retryTitle\": {\n   \"message\": \"Retry\",\n   \"description\": \"\"},\n \"referrerTitle\": {\n   \"message\": \"Referrer\",\n   \"description\": \"\"},\n \"month0abbr\": {\"message\": \"Jan\",\"description\": \"\"},\n \"month1abbr\": {\"message\": \"Feb\",\"description\": \"\"},\n \"month2abbr\": {\"message\": \"Mar\",\"description\": \"\"},\n \"month3abbr\": {\"message\": \"Apr\",\"description\": \"\"},\n \"month4abbr\": {\"message\": \"May\",\"description\": \"\"},\n \"month5abbr\": {\"message\": \"Jun\",\"description\": \"\"},\n \"month6abbr\": {\"message\": \"Jul\",\"description\": \"\"},\n \"month7abbr\": {\"message\": \"Aug\",\"description\": \"\"},\n \"month8abbr\": {\"message\": \"Sep\",\"description\": \"\"},\n \"month9abbr\": {\"message\": \"Oct\",\"description\": \"\"},\n \"month10abbr\": {\"message\": \"Nov\",\"description\": \"\"},\n \"month11abbr\": {\"message\": \"Dec\",\"description\": \"\"},\n \"openWhenCompleteFinishing\": {\n   \"message\": \"Opening in just a moment\",\n   \"description\": \"\"},\n \"timeLeftFinishing\": {\n   \"message\": \"finishing...\",\n   \"description\": \"\"},\n \"openWhenCompleteDays\": {\n   \"message\": \"Opening in $days$d $hours$h\",\n   \"description\": \"\",\n   \"placeholders\": {\n     \"days\": {\n       \"content\": \"$1\",\n       \"example\": \"2\"},\n     \"hours\": {\n       \"content\": \"$2\",\n       \"example\": \"23\"}}},\n \"timeLeftDays\": {\n   \"message\": \"$days$d $hours$h left\",\n   \"description\": \"\",\n   \"placeholders\": {\n     \"days\": {\n       \"content\": \"$1\",\n       \"example\": \"2\"},\n     \"hours\": {\n       \"content\": \"$2\",\n       \"example\": \"23\"}}},\n \"openWhenCompleteHours\": {\n   \"message\": \"Opening in $hours$h $mins$m\",\n   \"description\": \"\",\n   \"placeholders\": {\n     \"hours\": {\n       \"content\": \"$1\",\n       \"example\": \"23\"},\n     \"mins\": {\n       \"content\": \"$2\",\n       \"example\": \"59\"}}},\n \"timeLeftHours\": {\n   \"message\": \"$hours$h $mins$m left\",\n   \"description\": \"\",\n   \"placeholders\": {\n     \"hours\": {\n       \"content\": \"$1\",\n       \"example\": \"23\"},\n     \"mins\": {\n       \"content\": \"$2\",\n       \"example\": \"59\"}}},\n \"openWhenCompleteMinutes\": {\n   \"message\": \"Opening in $mins$m $sec$s\",\n   \"description\": \"\",\n   \"placeholders\": {\n     \"mins\": {\n       \"content\": \"$1\",\n       \"example\": \"59\"},\n     \"sec\": {\n       \"content\": \"$2\",\n       \"example\": \"59\"}}},\n \"timeLeftMinutes\": {\n   \"message\": \"$mins$m $sec$s left\",\n   \"description\": \"\",\n   \"placeholders\": {\n     \"mins\": {\n       \"content\": \"$1\",\n       \"example\": \"59\"},\n     \"sec\": {\n       \"content\": \"$2\",\n       \"example\": \"59\"}}},\n \"openWhenCompleteSeconds\": {\n   \"message\": \"Opening in $sec$s\",\n   \"description\": \"\",\n   \"placeholders\": {\n     \"sec\": {\n       \"content\": \"$1\",\n       \"example\": \"59\"}}},\n \"timeLeftSeconds\": {\n   \"message\": \"$sec$s left\",\n   \"description\": \"\",\n   \"placeholders\": {\n     \"sec\": {\n       \"content\": \"$1\",\n       \"example\": \"59\"}}},\n \"error_FILE_FAILED\": {\n   \"message\": \"File Failed\",\n   \"description\": \"\"},\n \"error_FILE_ACCESS_DENIED\": {\n   \"message\": \"File-System Access Denied\",\n   \"description\": \"\"},\n \"error_FILE_NO_SPACE\": {\n   \"message\": \"No Space On Disk\",\n   \"description\": \"\"},\n \"error_FILE_NAME_TOO_LONG\": {\n   \"message\": \"Filename Too Long\",\n   \"description\": \"\"},\n \"error_FILE_TOO_LARGE\": {\n   \"message\": \"File Too Large\",\n   \"description\": \"\"},\n \"error_FILE_VIRUS_INFECTED\": {\n   \"message\": \"Virus Infected\",\n   \"description\": \"\"},\n \"error_FILE_TRANSIENT_ERROR\": {\n   \"message\": \"Transient File-System Error\",\n   \"description\": \"\"},\n \"error_FILE_BLOCKED\": {\n   \"message\": \"File Blocked\",\n   \"description\": \"\"},\n \"error_FILE_SECURITY_CHECK_FAILED\": {\n   \"message\": \"Security Check Failed\",\n   \"description\": \"\"},\n \"error_FILE_TOO_SHORT\": {\n   \"message\": \"File Too Short\",\n   \"description\": \"\"},\n \"error_NETWORK_FAILED\": {\n   \"message\": \"Network Failure\",\n   \"description\": \"\"},\n \"error_NETWORK_TIMEOUT\": {\n   \"message\": \"Network Timeout\",\n   \"description\": \"\"},\n \"error_NETWORK_DISCONNECTED\": {\n   \"message\": \"Network Disconnected\",\n   \"description\": \"\"},\n \"error_NETWORK_SERVER_DOWN\": {\n   \"message\": \"Server Down\",\n   \"description\": \"\"},\n \"error_SERVER_FAILED\": {\n   \"message\": \"Server Failure\",\n   \"description\": \"\"},\n \"error_SERVER_NO_RANGE\": {\n   \"message\": \"Server No Range\",\n   \"description\": \"\"},\n \"error_SERVER_PRECONDITION\": {\n   \"message\": \"Server Precondition Failure\",\n   \"description\": \"\"},\n \"error_SERVER_BAD_CONTENT\": {\n   \"message\": \"Bad Content\",\n   \"description\": \"\"},\n \"error_USER_CANCELED\": {\n   \"message\": \"Cancelled\",\n   \"description\": \"\"},\n \"error_USER_SHUTDOWN\": {\n   \"message\": \"Cancelled\",\n   \"description\": \"\"},\n \"error_CRASH\": {\n   \"message\": \"Crash\",\n   \"description\": \"\"},\n \"error_1\": {\n   \"message\": \"File Failed\",\n   \"description\": \"\"},\n \"error_2\": {\n   \"message\": \"File-System Access Denied\",\n   \"description\": \"\"},\n \"error_3\": {\n   \"message\": \"No Space On Disk\",\n   \"description\": \"\"},\n \"error_5\": {\n   \"message\": \"Filename Too Long\",\n   \"description\": \"\"},\n \"error_6\": {\n   \"message\": \"File Too Large\",\n   \"description\": \"\"},\n \"error_7\": {\n   \"message\": \"Virus Infected\",\n   \"description\": \"\"},\n \"error_10\": {\n   \"message\": \"Transient File-System Error\",\n   \"description\": \"\"},\n \"error_11\": {\n   \"message\": \"File Blocked\",\n   \"description\": \"\"},\n \"error_12\": {\n   \"message\": \"Security Check Failed\",\n   \"description\": \"\"},\n \"error_13\": {\n   \"message\": \"File Too Short\",\n   \"description\": \"\"},\n \"error_20\": {\n   \"message\": \"Network Failure\",\n   \"description\": \"\"},\n \"error_21\": {\n   \"message\": \"Network Timeout\",\n   \"description\": \"\"},\n \"error_22\": {\n   \"message\": \"Network Disconnected\",\n   \"description\": \"\"},\n \"error_23\": {\n   \"message\": \"Server Down\",\n   \"description\": \"\"},\n \"error_30\": {\n   \"message\": \"Server Failure\",\n   \"description\": \"\"},\n \"error_31\": {\n   \"message\": \"Server No Range\",\n   \"description\": \"\"},\n \"error_32\": {\n   \"message\": \"Server Precondition Failure\",\n   \"description\": \"\"},\n \"error_33\": {\n   \"message\": \"Bad Content\",\n   \"description\": \"\"},\n \"error_40\": {\n   \"message\": \"Cancelled\",\n   \"description\": \"\"},\n \"error_41\": {\n   \"message\": \"Cancelled\",\n   \"description\": \"\"},\n \"error_50\": {\n   \"message\": \"Crash\",\n   \"description\": \"\"},\n \"errorRemoved\": {\n   \"message\": \"Removed\",\n   \"description\": \"\"},\n \"showInFolderTitle\": {\n   \"message\": \"Show in Folder\",\n   \"description\": \"Alt text for show in folder icon\"}}\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_manager/background.js",
    "content": "// Copyright (c) 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nif (chrome.downloads.setShelfEnabled)\n  chrome.downloads.setShelfEnabled(false);\n\nvar colors = {\n  progressColor: '#0d0',\n  arrow: '#555',\n  danger: 'red',\n  complete: 'green',\n  paused: 'grey',\n  background: 'white',\n};\n\nfunction drawLine(ctx, x1, y1, x2, y2) {\n  ctx.beginPath();\n  ctx.moveTo(x1, y1);\n  ctx.lineTo(x2, y2);\n  ctx.stroke();\n}\n\nMath.TAU = 2 * Math.PI;  // http://tauday.com/tau-manifesto\n\nfunction drawProgressArc(ctx, startAngle, endAngle) {\n  var center = ctx.canvas.width/2;\n  ctx.lineWidth = Math.round(ctx.canvas.width*0.1);\n  ctx.beginPath();\n  ctx.moveTo(center, center);\n  ctx.arc(center, center, center * 0.9, startAngle, endAngle, false);\n  ctx.fill();\n  ctx.stroke();\n}\n\nfunction drawUnknownProgressSpinner(ctx) {\n  var center = ctx.canvas.width/2;\n  const segments = 16;\n  var segArc = Math.TAU / segments;\n  for (var seg = 0; seg < segments; ++seg) {\n    ctx.fillStyle = ctx.strokeStyle = (\n      ((seg % 2) == 0) ? colors.progressColor : colors.background);\n    drawProgressArc(ctx, (seg-4)*segArc, (seg-3)*segArc);\n  }\n}\n\nfunction drawProgressSpinner(ctx, stage) {\n  ctx.fillStyle = ctx.strokeStyle = colors.progressColor;\n  var clocktop = -Math.TAU/4;\n  drawProgressArc(ctx, clocktop, clocktop + (stage * Math.TAU));\n}\n\nfunction drawArrow(ctx) {\n  ctx.beginPath();\n  ctx.lineWidth = Math.round(ctx.canvas.width*0.1);\n  ctx.lineJoin = 'round';\n  ctx.strokeStyle = ctx.fillStyle = colors.arrow;\n  var center = ctx.canvas.width/2;\n  var minw2 = center*0.2;\n  var maxw2 = center*0.60;\n  var height2 = maxw2;\n  ctx.moveTo(center-minw2, center-height2);\n  ctx.lineTo(center+minw2, center-height2);\n  ctx.lineTo(center+minw2, center);\n  ctx.lineTo(center+maxw2, center);\n  ctx.lineTo(center, center+height2);\n  ctx.lineTo(center-maxw2, center);\n  ctx.lineTo(center-minw2, center);\n  ctx.lineTo(center-minw2, center-height2);\n  ctx.lineTo(center+minw2, center-height2);\n  ctx.stroke();\n  ctx.fill();\n}\n\nfunction drawDangerBadge(ctx) {\n  var s = ctx.canvas.width/100;\n  ctx.fillStyle = colors.danger;\n  ctx.strokeStyle = colors.background;\n  ctx.lineWidth = Math.round(s*5);\n  var edge = ctx.canvas.width-ctx.lineWidth;\n  ctx.beginPath();\n  ctx.moveTo(s*75, s*55);\n  ctx.lineTo(edge, edge);\n  ctx.lineTo(s*55, edge);\n  ctx.lineTo(s*75, s*55);\n  ctx.lineTo(edge, edge);\n  ctx.fill();\n  ctx.stroke();\n}\n\nfunction drawPausedBadge(ctx) {\n  var s = ctx.canvas.width/100;\n  ctx.beginPath();\n  ctx.strokeStyle = colors.background;\n  ctx.lineWidth = Math.round(s*5);\n  ctx.rect(s*55, s*55, s*15, s*35);\n  ctx.fillStyle = colors.paused;\n  ctx.fill();\n  ctx.stroke();\n  ctx.rect(s*75, s*55, s*15, s*35);\n  ctx.fill();\n  ctx.stroke();\n}\n\nfunction drawCompleteBadge(ctx) {\n  var s = ctx.canvas.width/100;\n  ctx.beginPath();\n  ctx.arc(s*75, s*75, s*15, 0, Math.TAU, false);\n  ctx.fillStyle = colors.complete;\n  ctx.fill();\n  ctx.strokeStyle = colors.background;\n  ctx.lineWidth = Math.round(s*5);\n  ctx.stroke();\n}\n\nfunction drawIcon(side, options) {\n  var canvas = document.createElement('canvas');\n  canvas.width = canvas.height = side;\n  document.body.appendChild(canvas);\n  var ctx = canvas.getContext('2d');\n  if (options.anyInProgress) {\n    if (options.anyMissingTotalBytes) {\n      drawUnknownProgressSpinner(ctx);\n    } else {\n      drawProgressSpinner(ctx, (options.totalBytesReceived /\n                                options.totalTotalBytes));\n    }\n  }\n  drawArrow(ctx);\n  if (options.anyDangerous) {\n    drawDangerBadge(ctx);\n  } else if (options.anyPaused) {\n    drawPausedBadge(ctx);\n  } else if (options.anyRecentlyCompleted) {\n    drawCompleteBadge(ctx);\n  }\n  return canvas;\n}\n\nfunction maybeOpen(id) {\n  var openWhenComplete = [];\n  try {\n    openWhenComplete = JSON.parse(localStorage.openWhenComplete);\n  } catch (e) {\n    localStorage.openWhenComplete = JSON.stringify(openWhenComplete);\n  }\n  var openNowIndex = openWhenComplete.indexOf(id);\n  if (openNowIndex >= 0) {\n    chrome.downloads.open(id);\n    openWhenComplete.splice(openNowIndex, 1);\n    localStorage.openWhenComplete = JSON.stringify(openWhenComplete);\n  }\n}\n\nfunction setBrowserActionIcon(options) {\n  var canvas1 = drawIcon(19, options);\n  var canvas2 = drawIcon(38, options);\n  var imageData = {};\n  imageData['' + canvas1.width] = canvas1.getContext('2d').getImageData(\n        0, 0, canvas1.width, canvas1.height);\n  imageData['' + canvas2.width] = canvas2.getContext('2d').getImageData(\n        0, 0, canvas2.width, canvas2.height);\n  chrome.browserAction.setIcon({imageData:imageData});\n  canvas1.parentNode.removeChild(canvas1);\n  canvas2.parentNode.removeChild(canvas2);\n}\n\nfunction pollProgress() {\n  pollProgress.tid = -1;\n  chrome.downloads.search({}, function(items) {\n    var popupLastOpened = parseInt(localStorage.popupLastOpened);\n    var options = {anyMissingTotalBytes: false,\n                   anyInProgress: false,\n                   anyRecentlyCompleted: false,\n                   anyPaused: false,\n                   anyDangerous: false,\n                   totalBytesReceived: 0,\n                   totalTotalBytes: 0};\n    items.forEach(function(item) {\n      if (item.state == 'in_progress') {\n        options.anyInProgress = true;\n        if (item.totalBytes) {\n          options.totalTotalBytes += item.totalBytes;\n          options.totalBytesReceived += item.bytesReceived;\n        } else {\n          options.anyMissingTotalBytes = true;\n        }\n        var dangerous = ((item.danger != 'safe') &&\n                         (item.danger != 'accepted'));\n        options.anyDangerous = options.anyDangerous || dangerous;\n        options.anyPaused = options.anyPaused || item.paused;\n      } else if ((item.state == 'complete') && item.endTime && !item.error) {\n        options.anyRecentlyCompleted = (\n          options.anyRecentlyCompleted ||\n          ((new Date(item.endTime)).getTime() >= popupLastOpened));\n        maybeOpen(item.id);\n      }\n    });\n\n    var targetIcon = JSON.stringify(options);\n    if (sessionStorage.currentIcon != targetIcon) {\n      setBrowserActionIcon(options);\n      sessionStorage.currentIcon = targetIcon;\n    }\n\n    if (options.anyInProgress &&\n        (pollProgress.tid < 0)) {\n      pollProgress.start();\n    }\n  });\n}\npollProgress.tid = -1;\npollProgress.MS = 200;\n\npollProgress.start = function() {\n  if (pollProgress.tid < 0) {\n    pollProgress.tid = setTimeout(pollProgress, pollProgress.MS);\n  }\n};\n\nfunction isNumber(n) {\n  return !isNaN(parseFloat(n)) && isFinite(n);\n}\n\nif (!isNumber(localStorage.popupLastOpened)) {\n  localStorage.popupLastOpened = '' + (new Date()).getTime();\n}\n\nchrome.downloads.onCreated.addListener(function(item) {\n  pollProgress();\n});\n\npollProgress();\n\nfunction openWhenComplete(downloadId) {\n  var ids = [];\n  try {\n    ids = JSON.parse(localStorage.openWhenComplete);\n  } catch (e) {\n    localStorage.openWhenComplete = JSON.stringify(ids);\n  }\n  pollProgress.start();\n  if (ids.indexOf(downloadId) >= 0) {\n    return;\n  }\n  ids.push(downloadId);\n  localStorage.openWhenComplete = JSON.stringify(ids);\n}\n\nchrome.runtime.onMessage.addListener(function(request) {\n  if (request == 'poll') {\n    pollProgress.start();\n  }\n  if (request == 'icons') {\n    [16, 19, 38, 128].forEach(function(s) {\n      var canvas = drawIcon(s);\n      chrome.downloads.download({\n        url: canvas.toDataURL('image/png', 1.0),\n        filename: 'icon' + s + '.png',\n      });\n      canvas.parentNode.removeChild(canvas);\n    });\n  }\n  if (isNumber(request.openWhenComplete)) {\n    openWhenComplete(request.openWhenComplete);\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_manager/icons.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<title>Icon Generator</title>\n<script src='icons.js'></script>\n</head>\n<body>\n<button id=download>Generate Manifest Icons</button>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_manager/icons.js",
    "content": "// Copyright (c) 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nwindow.onload = function() {\n  var download = document.getElementById('download');\n  download.onclick = function() {\n    chrome.runtime.sendMessage('icons');\n    download.disabled = true;\n    return false;\n  };\n};\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_manager/manifest.json",
    "content": "{\"name\": \"__MSG_extName__\",\n \"version\": \"0.3\",\n \"manifest_version\": 2,\n \"description\": \"__MSG_extDesc__\",\n \"icons\": {\"128\": \"icon128.png\"},\n \"browser_action\": {\n   \"default_icon\": {\n     \"19\": \"icon19.png\",\n     \"38\": \"icon38.png\"},\n   \"default_title\": \"__MSG_extName__\",\n   \"default_popup\": \"popup.html\"},\n \"background\": {\"persistent\": false, \"scripts\": [\"background.js\"]},\n \"default_locale\": \"en\",\n \"optional_permissions\": [\"management\"],\n \"permissions\": [\"downloads\", \"downloads.open\", \"downloads.shelf\"]}\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_manager/popup.css",
    "content": "/* Copyright (c) 2013 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file. */\n\n#outer,\n#empty,\n#open-folder,\n.file-url,\n.time-left,\n.more-left {\n  display: inline-block;\n}\n\n#q-outer {\n  display:inline-block;\n  height:1.7em;\n  overflow:hidden;\n}\n\n#q {\n  margin-right: 2em;\n}\n\n#head {\n  position: fixed;\n  z-index: 2;\n  width: 100%;\n  left: 0;\n  top: 0;\n  background: white;\n  border-bottom: 1px solid grey;\n}\n\n#search-zero,\n#items {\n  margin-top: 2em;\n}\n\n#head,\n#empty,\n#searching,\n#search-zero,\n.item,\n.start-time,\n.complete-size,\n.error,\n.file-url-head,\n.removed,\n.open-filename,\n.progress,\n.time-left,\n.url,\n#text-width-probe {\n  white-space: nowrap;\n}\n\n#head,\n.item {\n  text-align: left;\n}\n\n#empty {\n  vertical-align: bottom;\n  height: 2em;\n}\n\n#q {\n  margin-left: 3%;\n}\n\n.by-ext img,\nsvg {\n  width: 2em;\n  height: 2em;\n}\n\nsvg rect.border {\n  fill-opacity: 0;\n  stroke-width: 6;\n}\n\n#open-folder svg,\n.show-folder svg {\n  stroke: brown;\n  fill: white;\n  stroke-width: 3;\n}\n\n#clear-all svg {\n  fill: white;\n  stroke-width: 3;\n}\n\n#clear-all svg,\n.remove-file svg,\n.erase svg {\n  stroke: black;\n}\n\n#older,\n#loading-older,\n.item {\n  margin-top: 1em;\n}\n\n.more {\n  position: absolute;\n  border: 1px solid grey;\n  background: white;\n  z-index: 3;\n}\n\n.complete-size,\n.error,\n.removed,\n.open-filename,\n.progress,\n.time-left {\n  margin-right: 0.4em;\n}\n\n.error {\n  color: darkred;\n}\n\n.referrer svg {\n  stroke: blue;\n  fill-opacity: 0;\n  stroke-width: 7;\n}\n\n.removed,\n.open-filename {\n  max-width: 400px;\n  overflow: hidden;\n  display: inline-block;\n}\n\n.remove-file svg {\n  fill-opacity: 0;\n  stroke-width: 5;\n}\n\n.remove-file svg line {\n  stroke-width: 7;\n  stroke: red;\n}\n\n.erase svg ellipse,\n.erase svg line {\n  fill-opacity: 0;\n  stroke-width: 5;\n}\n\n.pause svg {\n  stroke: #333;\n}\n\n.resume svg {\n  stroke: rgb(68, 187, 68);\n  fill: rgb(68, 187, 68);\n}\n\n.cancel svg line {\n  stroke-width: 7;\n}\n\n.cancel svg {\n  stroke: rgb(204, 68, 68);\n}\n\n.meter {\n  height: 0.5em;\n  position: relative;\n  background: grey;\n}\n\n.meter > span {\n  display: block;\n  height: 100%;\n  background-color: rgb(43, 194, 83);\n  background-image: -webkit-gradient(\n    linear, left bottom, left top,\n    color-stop(0, rgb(43,194,83)),\n    color-stop(1, rgb(84,240,84)));\n  position: relative;\n  overflow: hidden;\n}\n\n.meter > span:after {\n  content: '';\n  position: absolute;\n  top: 0; left: 0; bottom: 0; right: 0;\n  background-image: -webkit-gradient(\n    linear, 0 0, 100% 100%,\n    color-stop(.25, rgba(255, 255, 255, .2)),\n    color-stop(.25, transparent),\n    color-stop(.5, transparent),\n    color-stop(.5, rgba(255, 255, 255, .2)),\n    color-stop(.75, rgba(255, 255, 255, .2)),\n    color-stop(.75, transparent),\n    to(transparent));\n  z-index: 1;\n  -webkit-background-size: 50px 50px;\n  background-size: 50px 50px;\n  animation: move 2s linear infinite;\n  overflow: hidden;\n}\n\n@keyframes move {\n  0% { background-position: 0 0; }\n  100% { background-position: 50px 50px; }\n}\n\n.url {\n  color: grey;\n  max-width: 700px;\n  overflow: hidden;\n  display: block;\n}\n\n#text-width-probe {\n  position: absolute;\n  top: -100px;\n  left: 0;\n}\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_manager/popup.html",
    "content": "<!DOCTYPE HTML>\n<html>\n<head>\n  <title></title>\n  <script src=\"popup.js\"></script>\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"popup.css\">\n  <link rel=\"icon\" href=\"icon19.png\">\n</head>\n<body>\n<div id=\"outer\">\n  <div id=\"head\">\n    <a id=\"bad-chrome-version\" hidden\n        href=\"https://www.google.com/intl/en/chrome/browser/beta.html\"></a>\n    <span id=\"empty\" hidden></span>\n    <div id=\"q-outer\">\n      <input type=\"search\" id=\"q\" incremental><br>&nbsp;\n    </div>\n    <a href=\"#\" id=\"clear-all\"><svg viewBox=\"0 0 100 100\"><g>\n      <rect x=\"5\" y=\"5\" rx=\"20\" ry=\"20\" width=\"90\" height=\"90\" class=\"border\" />\n      <ellipse rx=\"30\" ry=\"8\" cx=\"50\" cy=\"55\" />\n      <ellipse rx=\"20\" ry=\"5\" cx=\"50\" cy=\"80\" />\n      <line x1=\"20\" y1=\"55\" x2=\"30\" y2=\"83\" />\n      <line x1=\"40\" y1=\"60\" x2=\"43\" y2=\"83\" />\n      <line x1=\"60\" y1=\"60\" x2=\"56\" y2=\"83\" />\n      <line x1=\"80\" y1=\"55\" x2=\"69\" y2=\"83\" />\n      <polygon points=\"25,20 35,20 35,40 40,40 30,55 20,40 25,40\" />\n      <polygon points=\"45,20 55,20 55,40 60,40 50,55 40,40 45,40\" />\n      <polygon points=\"65,20 75,20 75,40 80,40 70,55 60,40 65,40\" />\n      </g></svg></a>\n    <a href=\"#\" id=\"open-folder\"><svg viewBox=\"0 0 100 100\"><g>\n      <rect x=\"5\" y=\"5\" rx=\"20\" ry=\"20\" width=\"90\" height=\"90\" class=\"border\" />\n      <polygon points=\"20,20 20,80 60,80 60,30 35,30 35,20\" />\n      <polygon points=\"20,80 60,80 80,45 40,45\" />\n      </g></svg></a>\n  </div>\n  <div id=\"searching\" hidden></div>\n  <div id=\"search-zero\" hidden></div>\n  <div id=\"items\"></div>\n  <a href=\"#\" id=\"older\" hidden></a>\n  <span id=\"loading-older\" hidden></span>\n  <div id=\"request-management-permission\" hidden><div\n      id=\"management-permission-info\"></div>\n    <a href=\"#\" id=\"grant-management-permission\"></a>\n  </div>\n</div>\n\n<div class=\"item\" hidden>\n  <img class=\"icon\" src=\"icon38.png\">\n  <div class=\"more\" hidden>\n    <span class=\"more-left\">\n      <div class=\"start-time\"></div>\n      <div class=\"complete-size\"></div>\n    </span>\n    <a href=\"#\" class=\"referrer\"><svg viewBox=\"0 0 100 100\"><g>\n      <rect x=\"5\" y=\"5\" rx=\"20\" ry=\"20\" width=\"90\" height=\"90\" class=\"border\" />\n      <ellipse cx=\"35\" cy=\"50\" rx=\"20\" ry=\"20\" />\n      <ellipse cx=\"60\" cy=\"50\" rx=\"20\" ry=\"20\" />\n      </g></svg></a>\n    <a href=\"#\" class=\"by-ext\"><img /></a>\n    <a href=\"#\" class=\"show-folder\"><svg viewBox=\"0 0 100 100\"><g>\n      <rect x=\"5\" y=\"5\" rx=\"20\" ry=\"20\" width=\"90\" height=\"90\" class=\"border\" />\n      <polygon points=\"20,20 20,80 60,80 60,30 35,30 35,20\" />\n      <polygon points=\"20,80 60,80 80,45 40,45\" />\n      </g></svg></a>\n    <a href=\"#\" class=\"remove-file\"><svg viewBox=\"0 0 100 100\"><g>\n      <rect x=\"5\" y=\"5\" rx=\"20\" ry=\"20\" width=\"90\" height=\"90\" class=\"border\" />\n      <polygon points=\"20,45 45,20 75,20 75,75 20,75, 20,45 45,45 45,20\" />\n      <line x1=\"45\" y1=\"45\" x2=\"80\" y2=\"80\" />\n      <line x1=\"80\" y1=\"45\" x2=\"45\" y2=\"80\" />\n      </g></svg></a>\n    <a href=\"#\" class=\"erase\"><svg viewBox=\"0 0 100 100\"><g>\n      <rect x=\"5\" y=\"5\" rx=\"20\" ry=\"20\" width=\"90\" height=\"90\" class=\"border\" />\n      <ellipse rx=\"30\" ry=\"10\" cx=\"50\" cy=\"40\" />\n      <ellipse rx=\"20\" ry=\"10\" cx=\"50\" cy=\"70\" />\n      <line x1=\"20\" y1=\"35\" x2=\"30\" y2=\"75\" />\n      <line x1=\"80\" y1=\"35\" x2=\"65\" y2=\"75\" />\n      <line x1=\"50\" y1=\"50\" x2=\"50\" y2=\"80\" />\n      </g></svg></a>\n  </div>\n  <a href=\"#\" class=\"pause\"><svg viewBox=\"0 0 100 100\"><g>\n    <rect x=\"5\" y=\"5\" rx=\"20\" ry=\"20\" width=\"90\" height=\"90\" class=\"border\" />\n    <rect x=\"25\" y=\"25\" rx=\"20\" ry=\"20\" width=\"15\" height=\"50\" />\n    <rect x=\"55\" y=\"25\" rx=\"20\" ry=\"20\" width=\"15\" height=\"50\" />\n    </g></svg></a>\n  <a href=\"#\" class=\"resume\"><svg viewBox=\"0 0 100 100\"><g>\n    <rect x=\"5\" y=\"5\" rx=\"20\" ry=\"20\" width=\"90\" height=\"90\" class=\"border\" />\n    <polygon points=\"25,25 75,50 25,75\">\n    </g></svg></a>\n  <a href=\"#\" class=\"cancel\"><svg viewBox=\"0 0 100 100\"><g>\n    <rect x=\"5\" y=\"5\" rx=\"20\" ry=\"20\" width=\"90\" height=\"90\" class=\"border\" />\n    <line x1=\"25\" y1=\"25\" x2=\"75\" y2=\"75\" />\n    <line x1=\"75\" y1=\"25\" x2=\"25\" y2=\"75\" />\n    </g></svg></a>\n  <span class=\"file-url\">\n    <div class=\"file-url-head\">\n      <span class=\"removed\"></span>\n      <a href=\"#\" class=\"open-filename\"></a>\n      <span class=\"error\"></span>\n      <span class=\"in-progress\">\n        <span class=\"progress\"></span>\n        <span class=\"time-left\"></span>\n      </span>\n    </div>\n    <div class=\"meter\"><span /></div>\n    <a href=\"#\" class=\"url\" download=\"\"></a>\n  </span>\n</div>\n<span id=\"text-width-probe\"></span>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_manager/popup.js",
    "content": "// Copyright (c) 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction pointInElement(p, elem) {\n  return ((p.x >= elem.offsetLeft) &&\n          (p.x <= (elem.offsetLeft + elem.offsetWidth)) &&\n          (p.y >= elem.offsetTop) &&\n          (p.y <= (elem.offsetTop + elem.offsetHeight)));\n};\n\nfunction setLastOpened() {\n  localStorage.popupLastOpened = (new Date()).getTime();\n  chrome.runtime.sendMessage('poll');\n};\n\nfunction loadI18nMessages() {\n  function setProperty(selector, prop, msg) {\n    document.querySelector(selector)[prop] = chrome.i18n.getMessage(msg);\n  }\n\n  setProperty('title', 'innerText', 'tabTitle');\n  setProperty('#q', 'placeholder', 'searchPlaceholder');\n  setProperty('#clear-all', 'title', 'clearAllTitle');\n  setProperty('#open-folder', 'title', 'openDownloadsFolderTitle');\n  setProperty('#empty', 'innerText', 'zeroItems');\n  setProperty('#searching', 'innerText', 'searching');\n  setProperty('#search-zero', 'innerText', 'zeroSearchResults');\n  setProperty('#management-permission-info', 'innerText',\n              'managementPermissionInfo');\n  setProperty('#grant-management-permission', 'innerText',\n              'grantManagementPermission');\n  setProperty('#older', 'innerText', 'showOlderDownloads');\n  setProperty('#loading-older', 'innerText', 'loadingOlderDownloads');\n  setProperty('.pause', 'title', 'pauseTitle');\n  setProperty('.resume', 'title', 'resumeTitle');\n  setProperty('.cancel', 'title', 'cancelTitle');\n  setProperty('.show-folder', 'title', 'showInFolderTitle');\n  setProperty('.erase', 'title', 'eraseTitle');\n  setProperty('.url', 'title', 'retryTitle');\n  setProperty('.referrer', 'title', 'referrerTitle');\n  setProperty('.open-filename', 'title', 'openTitle');\n  setProperty('#bad-chrome-version', 'innerText', 'badChromeVersion');\n  setProperty('.remove-file', 'title', 'removeFileTitle');\n\n  document.querySelector('.progress').style.minWidth =\n    getTextWidth(formatBytes(1024 * 1024 * 1023.9) + '/' +\n                 formatBytes(1024 * 1024 * 1023.9)) + 'px';\n\n  // This only covers {timeLeft,openWhenComplete}{Finishing,Days}. If\n  // ...Hours/Minutes/Seconds could be longer for any locale, then this should\n  // test them.\n  var max_time_left_width = 0;\n  for (var i = 0; i < 4; ++i) {\n    max_time_left_width = Math.max(max_time_left_width, getTextWidth(\n        formatTimeLeft(0 == (i % 2),\n                       (i < 2) ? 0 : ((100 * 24) + 23) * 60 * 60 * 1000)));\n  }\n  document.querySelector('body div.item span.time-left').style.minWidth =\n     max_time_left_width + 'px';\n};\n\nfunction getTextWidth(s) {\n  var probe = document.getElementById('text-width-probe');\n  probe.innerText = s;\n  return probe.offsetWidth;\n};\n\nfunction formatDateTime(date) {\n  var now = new Date();\n  var zpad_mins = ':' + (date.getMinutes() < 10 ? '0' : '') + date.getMinutes();\n  if (date.getYear() != now.getYear()) {\n    return '' + (1900 + date.getYear());\n  } else if ((date.getMonth() != now.getMonth()) ||\n             (date.getDate() != now.getDate())) {\n    return date.getDate() + ' ' + chrome.i18n.getMessage(\n      'month' + date.getMonth() + 'abbr');\n  } else if (date.getHours() == 12) {\n    return '12' + zpad_mins + 'pm';\n  } else if (date.getHours() > 12) {\n    return (date.getHours() - 12) + zpad_mins + 'pm';\n  }\n  return date.getHours() + zpad_mins + 'am';\n}\n\nfunction formatBytes(n) {\n  if (n < 1024) {\n    return n + 'B';\n  }\n  var prefixes = 'KMGTPEZY';\n  var mul = 1024;\n  for (var i = 0; i < prefixes.length; ++i) {\n    if (n < (1024 * mul)) {\n      return (parseInt(n / mul) + '.' + parseInt(10 * ((n / mul) % 1)) +\n              prefixes[i] + 'B');\n    }\n    mul *= 1024;\n  }\n  return '!!!';\n}\n\nfunction formatTimeLeft(openWhenComplete, ms) {\n  var prefix = openWhenComplete ? 'openWhenComplete' : 'timeLeft';\n  if (ms < 1000) {\n    return chrome.i18n.getMessage(prefix + 'Finishing');\n  }\n  var days = parseInt(ms / (24 * 60 * 60 * 1000));\n  var hours = parseInt(ms / (60 * 60 * 1000)) % 24;\n  if (days) {\n    return chrome.i18n.getMessage(prefix + 'Days', [days, hours]);\n  }\n  var minutes = parseInt(ms / (60 * 1000)) % 60;\n  if (hours) {\n    return chrome.i18n.getMessage(prefix + 'Hours', [hours, minutes]);\n  }\n  var seconds = parseInt(ms / 1000) % 60;\n  if (minutes) {\n    return chrome.i18n.getMessage(prefix + 'Minutes', [minutes, seconds]);\n  }\n  return chrome.i18n.getMessage(prefix + 'Seconds', [seconds]);\n}\n\nfunction ratchetWidth(w) {\n  var current = parseInt(document.body.style.minWidth) || 0;\n  document.body.style.minWidth = Math.max(w, current) + 'px';\n}\n\nfunction ratchetHeight(h) {\n  var current = parseInt(document.body.style.minHeight) || 0;\n  document.body.style.minHeight = Math.max(h, current) + 'px';\n}\n\nfunction binarySearch(array, target, cmp) {\n  var low = 0, high = array.length - 1, i, comparison;\n  while (low <= high) {\n    i = (low + high) >> 1;\n    comparison = cmp(target, array[i]);\n    if (comparison < 0) {\n      low = i + 1;\n    } else if (comparison > 0) {\n      high = i - 1;\n    } else {\n      return i;\n    }\n  }\n  return i;\n};\n\nfunction arrayFrom(seq) {\n  return Array.prototype.slice.apply(seq);\n};\n\nfunction DownloadItem(data) {\n  var item = this;\n  for (var prop in data) {\n    item[prop] = data[prop];\n  }\n  item.startTime = new Date(item.startTime);\n  if (item.canResume == undefined) {\n    DownloadItem.canResumeHack = true;\n  }\n\n  item.div = document.querySelector('body>div.item').cloneNode(true);\n  item.div.id = 'item' + item.id;\n  item.div.item = item;\n\n  var items_div = document.getElementById('items');\n  if ((items_div.childNodes.length == 0) ||\n      (item.startTime.getTime() < items_div.childNodes[\n       items_div.childNodes.length - 1].item.startTime.getTime())) {\n    items_div.appendChild(item.div);\n  } else if (item.startTime.getTime() >\n             items_div.childNodes[0].item.startTime.getTime()) {\n    items_div.insertBefore(item.div, items_div.childNodes[0]);\n  } else {\n    var adjacent_div = items_div.childNodes[\n      binarySearch(arrayFrom(items_div.childNodes),\n                   item.startTime.getTime(),\n                   function(target, other) {\n          return target - other.item.startTime.getTime();\n    })];\n    var adjacent_item = adjacent_div.item;\n    if (adjacent_item.startTime.getTime() < item.startTime.getTime()) {\n      items_div.insertBefore(item.div, adjacent_div);\n    } else {\n      items_div.insertBefore(item.div, adjacent_div.nextSibling);\n    }\n  }\n\n  item.getElement('referrer').onclick = function() {\n    chrome.tabs.create({url: item.referrer});\n    return false;\n  };\n  item.getElement('by-ext').onclick = function() {\n    chrome.tabs.create({url: 'chrome://extensions#' + item.byExtensionId});\n    return false;\n  }\n  item.getElement('open-filename').onclick = function() {\n    item.open();\n    return false;\n  };\n  item.getElement('pause').onclick = function() {\n    item.pause();\n    return false;\n  };\n  item.getElement('cancel').onclick = function() {\n    item.cancel();\n    return false;\n  };\n  item.getElement('resume').onclick = function() {\n    item.resume();\n    return false;\n  };\n  item.getElement('show-folder').onclick = function() {\n    item.show();\n    return false;\n  };\n  item.getElement('remove-file').onclick = function() {\n    item.removeFile();\n    return false;\n  };\n  item.getElement('erase').onclick = function() {\n    item.erase();\n    return false;\n  };\n\n  item.more_mousemove = function(evt) {\n    var mouse = {x:evt.x, y:evt.y+document.body.scrollTop};\n    if (item.getElement('more') &&\n        (pointInElement(mouse, item.div) ||\n         pointInElement(mouse, item.getElement('more')))) {\n      return;\n    }\n    if (item.getElement('more')) {\n      item.getElement('more').hidden = true;\n    }\n    window.removeEventListener('mousemove', item.more_mousemove);\n  };\n  [item.div, item.getElement('more')].concat(\n      item.getElement('more').children).forEach(function(elem) {\n    elem.onmouseover = function() {\n      arrayFrom(items_div.children).forEach(function(other) {\n        if (other.item != item) {\n          other.item.getElement('more').hidden = true;\n        }\n      });\n      item.getElement('more').hidden = false;\n      item.getElement('more').style.top =\n        (item.div.offsetTop + item.div.offsetHeight) + 'px';\n      item.getElement('more').style.left = item.div.offsetLeft + 'px';\n      if (window.innerHeight < (parseInt(item.getElement('more').style.top) +\n                                item.getElement('more').offsetHeight)) {\n        item.getElement('more').style.top = (\n          item.div.offsetTop - item.getElement('more').offsetHeight) + 'px';\n      }\n      window.addEventListener('mousemove', item.more_mousemove);\n    };\n  });\n\n  if (item.referrer) {\n    item.getElement('referrer').href = item.referrer;\n  } else {\n    item.getElement('referrer').hidden = true;\n  }\n  item.getElement('url').href = item.url;\n  item.getElement('url').innerText = item.url;\n  item.render();\n}\nDownloadItem.canResumeHack = false;\n\nDownloadItem.prototype.getElement = function(name) {\n  return document.querySelector('#item' + this.id + ' .' + name);\n};\n\nDownloadItem.prototype.render = function() {\n  var item = this;\n  var now = new Date();\n  var in_progress = (item.state == 'in_progress')\n  var openable = (item.state != 'interrupted') && item.exists && !item.deleted;\n\n  item.startTime = new Date(item.startTime);\n  if (DownloadItem.canResumeHack) {\n    item.canResume = in_progress && item.paused;\n  }\n  if (item.filename) {\n    item.basename = item.filename.substring(Math.max(\n      item.filename.lastIndexOf('\\\\'),\n      item.filename.lastIndexOf('/')) + 1);\n  }\n  if (item.estimatedEndTime) {\n    item.estimatedEndTime = new Date(item.estimatedEndTime);\n  }\n  if (item.endTime) {\n    item.endTime = new Date(item.endTime);\n  }\n\n  if (item.filename && !item.icon_url) {\n    chrome.downloads.getFileIcon(\n      item.id,\n      {'size': 32},\n      function(icon_url) {\n        item.getElement('icon').hidden = !icon_url;\n        if (icon_url) {\n          item.icon_url = icon_url;\n          item.getElement('icon').src = icon_url;\n        }\n    });\n  }\n\n  item.getElement('removed').style.display = openable ? 'none' : 'inline';\n  item.getElement('open-filename').style.display = (\n    openable ? 'inline' : 'none');\n  item.getElement('in-progress').hidden = !in_progress;\n  item.getElement('pause').style.display = (\n    !in_progress || item.paused) ? 'none' : 'inline-block';\n  item.getElement('resume').style.display = (\n    !in_progress || !item.canResume) ? 'none' : 'inline-block';\n  item.getElement('cancel').style.display = (\n    !in_progress ? 'none' : 'inline-block');\n  item.getElement('remove-file').hidden = (\n    (item.state != 'complete') ||\n    !item.exists ||\n    item.deleted ||\n    !chrome.downloads.removeFile);\n  item.getElement('erase').hidden = in_progress;\n\n  var could_progress = in_progress || item.canResume;\n  item.getElement('progress').style.display = (\n    could_progress ? 'inline-block' : 'none');\n  item.getElement('meter').hidden = !could_progress || !item.totalBytes;\n\n  item.getElement('removed').innerText = item.basename;\n  item.getElement('open-filename').innerText = item.basename;\n\n  function setByExtension(show) {\n    if (show) {\n      item.getElement('by-ext').title = item.byExtensionName;\n      item.getElement('by-ext').href =\n        'chrome://extensions#' + item.byExtensionId;\n      item.getElement('by-ext img').src =\n        'chrome://extension-icon/' + item.byExtensionId + '/48/1';\n    } else {\n      item.getElement('by-ext').hidden = true;\n    }\n  }\n  if (item.byExtensionId && item.byExtensionName) {\n    chrome.permissions.contains({permissions: ['management']},\n                                function(result) {\n      if (result) {\n        setByExtension(true);\n      } else {\n        setByExtension(false);\n        if (!localStorage.managementPermissionDenied) {\n          document.getElementById('request-management-permission').hidden =\n            false;\n          document.getElementById('grant-management-permission').onclick =\n              function() {\n            chrome.permissions.request({permissions: ['management']},\n                                      function(granted) {\n              setByExtension(granted);\n              if (!granted) {\n                localStorage.managementPermissionDenied = true;\n              }\n            });\n            return false;\n          };\n        }\n      }\n    });\n  } else {\n    setByExtension(false);\n  }\n\n  if (!item.getElement('error').hidden) {\n    if (item.error) {\n      // TODO(benjhayden) When https://codereview.chromium.org/16924017/ is\n      // released, set minimum_chrome_version and remove the error_N messages.\n      item.getElement('error').innerText = chrome.i18n.getMessage(\n          'error_' + item.error);\n      if (!item.getElement('error').innerText) {\n        item.getElement('error').innerText = item.error;\n      }\n    } else if (!openable) {\n      item.getElement('error').innerText = chrome.i18n.getMessage(\n          'errorRemoved');\n    }\n  }\n\n  item.getElement('complete-size').innerText = formatBytes(\n    item.bytesReceived);\n  if (item.totalBytes && (item.state != 'complete')) {\n    item.getElement('progress').innerText = (\n      item.getElement('complete-size').innerText + '/' +\n      formatBytes(item.totalBytes));\n    item.getElement('meter').children[0].style.width = parseInt(\n        100 * item.bytesReceived / item.totalBytes) + '%';\n  }\n\n  if (in_progress) {\n    if (item.estimatedEndTime && !item.paused) {\n      var openWhenComplete = false;\n      try {\n        openWhenComplete = JSON.parse(localStorage.openWhenComplete).indexOf(\n            item.id) >= 0;\n      } catch (e) {\n      }\n      item.getElement('time-left').innerText = formatTimeLeft(\n          openWhenComplete, item.estimatedEndTime.getTime() - now.getTime());\n    } else {\n      item.getElement('time-left').innerText = String.fromCharCode(160);\n    }\n  }\n\n  if (item.startTime) {\n    item.getElement('start-time').innerText = formatDateTime(\n        item.startTime);\n  }\n\n  ratchetWidth(item.getElement('icon').offsetWidth +\n               item.getElement('file-url').offsetWidth +\n               item.getElement('cancel').offsetWidth +\n               item.getElement('pause').offsetWidth +\n               item.getElement('resume').offsetWidth);\n  ratchetWidth(item.getElement('more').offsetWidth);\n\n  this.maybeAccept();\n};\n\nDownloadItem.prototype.onChanged = function(delta) {\n  for (var key in delta) {\n    if (key != 'id') {\n      this[key] = delta[key].current;\n    }\n  }\n  this.render();\n  if (delta.state) {\n    setLastOpened();\n  }\n  if ((this.state == 'in_progress') && !this.paused) {\n    DownloadManager.startPollingProgress();\n  }\n};\n\nDownloadItem.prototype.onErased = function() {\n  window.removeEventListener('mousemove', this.more_mousemove);\n  document.getElementById('items').removeChild(this.div);\n};\n\nDownloadItem.prototype.show = function() {\n  chrome.downloads.show(this.id);\n};\n\nDownloadItem.prototype.open = function() {\n  if (this.state == 'complete') {\n    chrome.downloads.open(this.id);\n    return;\n  }\n  chrome.runtime.sendMessage({openWhenComplete:this.id});\n};\n\nDownloadItem.prototype.removeFile = function() {\n  chrome.downloads.removeFile(this.id);\n  this.deleted = true;\n  this.render();\n};\n\nDownloadItem.prototype.erase = function() {\n  chrome.downloads.erase({id: this.id});\n};\n\nDownloadItem.prototype.pause = function() {\n  chrome.downloads.pause(this.id);\n};\n\nDownloadItem.prototype.resume = function() {\n  chrome.downloads.resume(this.id);\n};\n\nDownloadItem.prototype.cancel = function() {\n  chrome.downloads.cancel(this.id);\n};\n\nDownloadItem.prototype.maybeAccept = function() {\n  // This function is safe to call at any time for any item, and it will always\n  // do the right thing, which is to display the danger prompt only if the item\n  // is in_progress and dangerous, and if the prompt is not already displayed.\n  if ((this.state != 'in_progress') ||\n      (this.danger == 'safe') ||\n      (this.danger == 'accepted') ||\n      DownloadItem.prototype.maybeAccept.accepting_danger) {\n    return;\n  }\n  ratchetWidth(400);\n  ratchetHeight(200);\n  DownloadItem.prototype.maybeAccept.accepting_danger = true;\n  // On Mac, window.onload is run while the popup is animating in, before it is\n  // considered \"visible\". Prompts will not be displayed over an invisible\n  // window, so the popup will become stuck. Just wait a little bit for the\n  // window to finish animating in. http://crbug.com/280107\n  // This has been fixed, so this setTimeout can be removed when the fix has\n  // been released to stable, and minimum_chrome_version can be set.\n  var id = this.id;\n  setTimeout(function() {\n    chrome.downloads.acceptDanger(id, function() {\n      DownloadItem.prototype.maybeAccept.accepting_danger = false;\n      arrayFrom(document.getElementById('items').childNodes).forEach(\n        function(item_div) { item_div.item.maybeAccept(); });\n    });\n  }, 500);\n};\nDownloadItem.prototype.maybeAccept.accepting_danger = false;\n\nvar DownloadManager = {};\n\nDownloadManager.showingOlder = false;\n\nDownloadManager.getItem = function(id) {\n  var item_div = document.getElementById('item' + id);\n  return item_div ? item_div.item : null;\n};\n\nDownloadManager.getOrCreate = function(data) {\n  var item = DownloadManager.getItem(data.id);\n  return item ? item : new DownloadItem(data);\n};\n\nDownloadManager.forEachItem = function(cb) {\n  // Calls cb(item, index) in the order that they are displayed, i.e. in order\n  // of decreasing startTime.\n  arrayFrom(document.getElementById('items').childNodes).forEach(\n    function(item_div, index) { cb(item_div.item, index); });\n};\n\nDownloadManager.startPollingProgress = function() {\n  if (DownloadManager.startPollingProgress.tid < 0) {\n    DownloadManager.startPollingProgress.tid = setTimeout(\n      DownloadManager.startPollingProgress.pollProgress,\n      DownloadManager.startPollingProgress.MS);\n  }\n}\nDownloadManager.startPollingProgress.MS = 200;\nDownloadManager.startPollingProgress.tid = -1;\nDownloadManager.startPollingProgress.pollProgress = function() {\n  DownloadManager.startPollingProgress.tid = -1;\n  chrome.downloads.search({state: 'in_progress', paused: false},\n      function(results) {\n    if (!results.length)\n      return;\n    results.forEach(function(result) {\n      var item = DownloadManager.getOrCreate(result);\n      for (var prop in result) {\n        item[prop] = result[prop];\n      }\n      item.render();\n      if ((item.state == 'in_progress') && !item.paused) {\n        DownloadManager.startPollingProgress();\n      }\n    });\n  });\n};\n\nDownloadManager.showNew = function() {\n  var any_items = (document.getElementById('items').childNodes.length > 0);\n  document.getElementById('empty').style.display =\n    any_items ? 'none' : 'inline-block';\n  document.getElementById('head').style.borderBottomWidth =\n    (any_items ? 1 : 0) + 'px';\n  document.getElementById('clear-all').hidden = !any_items;\n\n  var query_search = document.getElementById('q');\n  query_search.hidden = !any_items;\n\n  if (!any_items) {\n    return;\n  }\n  var old_ms = (new Date()).getTime() - kOldMs;\n  var any_hidden = false;\n  var any_showing = false;\n  // First show up to kShowNewMax items newer than kOldMs. If there aren't any\n  // items newer than kOldMs, then show up to kShowNewMax items of any age. If\n  // there are any hidden items, show the Show Older button.\n  DownloadManager.forEachItem(function(item, index) {\n    item.div.hidden = !DownloadManager.showingOlder && (\n      (item.startTime.getTime() < old_ms) || (index >= kShowNewMax));\n    any_hidden = any_hidden || item.div.hidden;\n    any_showing = any_showing || !item.div.hidden;\n  });\n  if (!any_showing) {\n    any_hidden = false;\n    DownloadManager.forEachItem(function(item, index) {\n      item.div.hidden = !DownloadManager.showingOlder && (index >= kShowNewMax);\n      any_hidden = any_hidden || item.div.hidden;\n      any_showing = any_showing || !item.div.hidden;\n    });\n  }\n  document.getElementById('older').hidden = !any_hidden;\n\n  query_search.focus();\n};\n\nDownloadManager.showOlder = function() {\n  DownloadManager.showingOlder = true;\n  var loading_older_span = document.getElementById('loading-older');\n  document.getElementById('older').hidden = true;\n  loading_older_span.hidden = false;\n  chrome.downloads.search({}, function(results) {\n    results.forEach(function(result) {\n      var item = DownloadManager.getOrCreate(result);\n      item.div.hidden = false;\n    });\n    loading_older_span.hidden = true;\n  });\n};\n\nDownloadManager.onSearch = function() {\n  // split string by space, but ignore space in quotes\n  // http://stackoverflow.com/questions/16261635\n  var query = document.getElementById('q').value.match(/(?:[^\\s\"]+|\"[^\"]*\")+/g);\n  if (!query) {\n    DownloadManager.showNew();\n    document.getElementById('search-zero').hidden = true;\n  } else {\n    query = query.map(function(term) {\n      // strip quotes\n      return (term.match(/\\s/) &&\n              term[0].match(/[\"']/) &&\n              term[term.length - 1] == term[0]) ?\n        term.substr(1, term.length - 2) : term;\n    });\n    var searching = document.getElementById('searching');\n    searching.hidden = false;\n    chrome.downloads.search({query: query}, function(results) {\n      document.getElementById('older').hidden = true;\n      DownloadManager.forEachItem(function(item) {\n        item.div.hidden = true;\n      });\n      results.forEach(function(result) {\n        DownloadManager.getOrCreate(result).div.hidden = false;\n      });\n      searching.hidden = true;\n      document.getElementById('search-zero').hidden = (results.length != 0);\n    });\n  }\n};\n\nDownloadManager.clearAll = function() {\n  DownloadManager.forEachItem(function(item) {\n    if (!item.div.hidden) {\n      item.erase();\n      // The onErased handler should circle back around to loadItems.\n    }\n  });\n};\n\nvar kShowNewMax = 50;\nvar kOldMs = 1000 * 60 * 60 * 24 * 7;\n\n// These settings can be tuned by modifying localStorage in dev-tools.\nif ('kShowNewMax' in localStorage) {\n  kShowNewMax = parseInt(localStorage.kShowNewMax);\n}\nif ('kOldMs' in localStorage) {\n  kOldMs = parseInt(localStorage.kOldMs);\n}\n\nDownloadManager.loadItems = function() {\n  // Request up to kShowNewMax + 1, but only display kShowNewMax; the +1 is a\n  // probe to see if there are any older downloads.\n  // TODO(benjhayden) When https://codereview.chromium.org/16924017/ is\n  // released, set minimum_chrome_version and remove this try/catch.\n  try {\n    chrome.downloads.search({\n        orderBy: ['-startTime'],\n        limit: kShowNewMax + 1},\n      function(results) {\n        DownloadManager.loadItems.items = results;\n        DownloadManager.loadItems.onLoaded();\n    });\n  } catch (exc) {\n    chrome.downloads.search({\n        orderBy: '-startTime',\n        limit: kShowNewMax + 1},\n      function(results) {\n        DownloadManager.loadItems.items = results;\n        DownloadManager.loadItems.onLoaded();\n    });\n  }\n};\nDownloadManager.loadItems.items = [];\nDownloadManager.loadItems.window_loaded = false;\n\nDownloadManager.loadItems.onLoaded = function() {\n  if (!DownloadManager.loadItems.window_loaded) {\n    return;\n  }\n  DownloadManager.loadItems.items.forEach(function(item) {\n    DownloadManager.getOrCreate(item);\n  });\n  DownloadManager.loadItems.items = [];\n  DownloadManager.showNew();\n};\n\nDownloadManager.loadItems.onWindowLoaded = function() {\n  DownloadManager.loadItems.window_loaded = true;\n  DownloadManager.loadItems.onLoaded();\n};\n\n// If this extension is installed on a stable-channel chrome, where the\n// downloads API is not available, do not use the downloads API, and link to the\n// beta channel.\nif (chrome.downloads) {\n  // Start searching ASAP, don't wait for onload.\n  DownloadManager.loadItems();\n\n  chrome.downloads.onCreated.addListener(function(item) {\n    DownloadManager.getOrCreate(item);\n    DownloadManager.showNew();\n    DownloadManager.startPollingProgress();\n  });\n\n  chrome.downloads.onChanged.addListener(function(delta) {\n    var item = DownloadManager.getItem(delta.id);\n    if (item) {\n      item.onChanged(delta);\n    }\n  });\n\n  chrome.downloads.onErased.addListener(function(id) {\n    var item = DownloadManager.getItem(id);\n    if (!item) {\n      return;\n    }\n    item.onErased();\n    DownloadManager.loadItems();\n  });\n\n  window.onload = function() {\n    ratchetWidth(\n      document.getElementById('q-outer').offsetWidth +\n      document.getElementById('clear-all').offsetWidth +\n      document.getElementById('open-folder').offsetWidth);\n    setLastOpened();\n    loadI18nMessages();\n    DownloadManager.loadItems.onWindowLoaded();\n    document.getElementById('older').onclick = function() {\n      DownloadManager.showOlder();\n      return false;\n    };\n    document.getElementById('q').onsearch = function() {\n      DownloadManager.onSearch();\n    };\n    document.getElementById('clear-all').onclick = function() {\n      DownloadManager.clearAll();\n      return false;\n    };\n    if (chrome.downloads.showDefaultFolder) {\n      document.getElementById('open-folder').onclick = function() {\n        chrome.downloads.showDefaultFolder();\n        return false;\n      };\n    } else {\n      document.getElementById('open-folder').hidden = true;\n    }\n  };\n} else {\n  // The downloads API is not available.\n  // TODO(benjhayden) Remove this when minimum_chrome_version is set.\n  window.onload = function() {\n    loadI18nMessages();\n    var bad_version = document.getElementById('bad-chrome-version');\n    bad_version.hidden = false;\n    bad_version.onclick = function() {\n      chrome.tabs.create({url: bad_version.href});\n      return false;\n    };\n    document.getElementById('empty').style.display = 'none';\n    document.getElementById('q').style.display = 'none';\n    document.getElementById('open-folder').style.display = 'none';\n    document.getElementById('clear-all').style.display = 'none';\n  };\n}\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_open/_locales/en/messages.json",
    "content": "{\"extName\": {\n   \"message\": \"Download and Open Button\",\n   \"description\": \"Extension name\"},\n \"extDesc\": {\n   \"message\": \"Download and Open Context Menu Button\",\n   \"description\": \"Extension description\"},\n \"openContextMenuTitle\": {\n   \"message\": \"Download and Open\",\n   \"description\": \"context menu button text\"}}\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_open/background.js",
    "content": "// Copyright (c) 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction getOpeningIds() {\n  var ids = [];\n  try {\n    ids = JSON.parse(localStorage.openWhenComplete);\n  } catch (e) {\n    localStorage.openWhenComplete = JSON.stringify(ids);\n  }\n  return ids;\n}\n\nfunction setOpeningIds(ids) {\n  localStorage.openWhenComplete = JSON.stringify(ids);\n}\n\nchrome.downloads.onChanged.addListener(function(delta) {\n  if (!delta.state ||\n      (delta.state.current != 'complete')) {\n    return;\n  }\n  var ids = getOpeningIds();\n  if (ids.indexOf(delta.id) < 0) {\n    return;\n  }\n  chrome.downloads.open(delta.id);\n  ids.splice(ids.indexOf(delta.id), 1);\n  setOpeningIds(ids);\n});\n\nchrome.contextMenus.onClicked.addListener(function(info, tab) {\n  chrome.downloads.download({url: info.linkUrl}, function(downloadId) {\n    var ids = getOpeningIds();\n    if (ids.indexOf(downloadId) >= 0) {\n      return;\n    }\n    ids.push(downloadId);\n    setOpeningIds(ids);\n  });\n});\n\nchrome.contextMenus.create({\n  id: 'open',\n  title: chrome.i18n.getMessage('openContextMenuTitle'),\n  contexts: ['link'],\n});\n"
  },
  {
    "path": "_archive/mv2/api/downloads/download_open/manifest.json",
    "content": "{\"name\": \"__MSG_extName__\",\n \"version\": \"0.1\",\n \"manifest_version\": 2,\n \"description\": \"__MSG_extDesc__\",\n \"icons\": {\"16\": \"icon16.png\", \"128\": \"icon128.png\"},\n \"background\": {\"persistent\": false, \"scripts\": [\"background.js\"]},\n \"default_locale\": \"en\",\n \"permissions\": [\"contextMenus\", \"downloads\", \"downloads.open\"]}\n"
  },
  {
    "path": "_archive/mv2/api/downloads/downloads_overwrite/bg.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Force all downloads to overwrite any existing files instead of inserting\n// ' (1)', ' (2)', etc.\n\nchrome.downloads.onDeterminingFilename.addListener(function(item, suggest) {\n  suggest({filename: item.filename,\n           conflict_action: 'overwrite',\n           conflictAction: 'overwrite'});\n  // conflict_action was renamed to conflictAction in\n  // https://chromium.googlesource.com/chromium/src/+/f1d784d6938b8fe8e0d257e41b26341992c2552c\n  // which was first picked up in branch 1580.\n});\n"
  },
  {
    "path": "_archive/mv2/api/downloads/downloads_overwrite/manifest.json",
    "content": "{\n  \"name\": \"Downloads Overwrite Existing Files\",\n  \"description\": \"All downloads overwrite existing files instead of adding ' (1)', ' (2)', etc.\",\n  \"version\": \"1\",\n  \"minimum_chrome_version\": \"26.0.1428\",\n  \"background\": {\n    \"scripts\": [\"bg.js\"],\n    \"persistent\": false\n  },\n  \"permissions\": [\n    \"downloads\"\n  ],\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/eventPage/basic/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Global variables only exist for the life of the page, so they get reset\n// each time the page is unloaded.\nvar counter = 1;\n\nvar lastTabId = -1;\nfunction sendMessage() {\n  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {\n    lastTabId = tabs[0].id;\n    chrome.tabs.sendMessage(lastTabId, \"Background page started.\");\n  });\n}\n\nsendMessage();\nchrome.browserAction.setBadgeText({text: \"ON\"});\nconsole.log(\"Loaded.\");\n\nchrome.runtime.onInstalled.addListener(function() {\n  console.log(\"Installed.\");\n\n  // localStorage is persisted, so it's a good place to keep state that you\n  // need to persist across page reloads.\n  localStorage.counter = 1;\n\n  // Register a webRequest rule to redirect bing to google.\n  var wr = chrome.declarativeWebRequest;\n  chrome.declarativeWebRequest.onRequest.addRules([{\n    id: \"0\",\n    conditions: [new wr.RequestMatcher({url: {hostSuffix: \"bing.com\"}})],\n    actions: [new wr.RedirectRequest({redirectUrl: \"http://google.com\"})]\n  }]);\n});\n\nchrome.bookmarks.onRemoved.addListener(function(id, info) {\n  alert(\"I never liked that site anyway.\");\n});\n\nchrome.browserAction.onClicked.addListener(function() {\n  // The event page will unload after handling this event (assuming nothing\n  // else is keeping it awake). The content script will become the main way to\n  // interact with us.\n  chrome.tabs.create({url: \"http://google.com\"}, function(tab) {\n    chrome.tabs.executeScript(tab.id, {file: \"content.js\"}, function() {\n      // Note: we also sent a message above, upon loading the event page,\n      // but the content script will not be loaded at that point, so we send\n      // another here.\n      sendMessage();\n    });\n  });\n});\n\nchrome.commands.onCommand.addListener(function(command) {\n  chrome.tabs.create({url: \"http://www.google.com/\"});\n});\n\nchrome.runtime.onMessage.addListener(function(msg, _, sendResponse) {\n  if (msg.setAlarm) {\n    // For testing only.  delayInMinutes will be rounded up to at least 1 in a\n    // packed or released extension.\n    chrome.alarms.create({delayInMinutes: 0.1});\n  } else if (msg.delayedResponse) {\n    // Note: setTimeout itself does NOT keep the page awake. We return true\n    // from the onMessage event handler, which keeps the message channel open -\n    // in turn keeping the event page awake - until we call sendResponse.\n    setTimeout(function() {\n      sendResponse(\"Got your message.\");\n    }, 5000);\n    return true;\n  } else if (msg.getCounters) {\n    sendResponse({counter: counter++,\n                  persistentCounter: localStorage.counter++});\n  }\n  // If we don't return anything, the message channel will close, regardless\n  // of whether we called sendResponse.\n});\n\nchrome.alarms.onAlarm.addListener(function() {\n  alert(\"Time's up!\");\n});\n\nchrome.runtime.onSuspend.addListener(function() {\n  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {\n    // After the unload event listener runs, the page will unload, so any\n    // asynchronous callbacks will not fire.\n    alert(\"This does not show up.\");\n  });\n  console.log(\"Unloading.\");\n  chrome.browserAction.setBadgeText({text: \"\"});\n  chrome.tabs.sendMessage(lastTabId, \"Background page unloaded.\");\n});\n"
  },
  {
    "path": "_archive/mv2/api/eventPage/basic/content.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\ndocument.body.innerHTML = \"\";\n\nfunction addButton(name, cb) {\n  var a = document.createElement(\"button\");\n  a.innerText = name;\n  a.onclick = cb;\n  document.body.appendChild(document.createElement(\"br\"));\n  document.body.appendChild(a);\n}\n\nfunction log(str) {\n  console.log(str);\n  logDiv.innerHTML += str + \"<br>\";\n}\n\naddButton(\"Clear logs\", function() {\n  logDiv.innerHTML = \"\";\n});\n\naddButton(\"Send message with delayed response\", function() {\n  chrome.runtime.sendMessage({delayedResponse: true}, function(response) {\n    log(\"Background page responded: \" + response);\n  });\n});\n\naddButton(\"Show counters\", function() {\n  chrome.runtime.sendMessage({getCounters: true}, function(response) {\n    log(\"In-memory counter is: \" + response.counter);\n    log(\"Persisted counter is: \" + response.persistentCounter);\n  });\n});\n\naddButton(\"Set an alarm\", function() {\n  chrome.runtime.sendMessage({setAlarm: true});\n});\n\nchrome.runtime.onMessage.addListener(function(msg, _, sendResponse) {\n  log(\"Got message from background page: \" + msg);\n});\n\nvar logDiv = document.createElement(\"div\");\nlogDiv.style.border = \"1px dashed black\";\ndocument.body.appendChild(document.createElement(\"br\"));\ndocument.body.appendChild(logDiv);\n\nlog(\"Ready.\");\n"
  },
  {
    "path": "_archive/mv2/api/eventPage/basic/manifest.json",
    "content": "{\n  \"name\": \"Event Page Example\",\n  \"description\": \"Demonstrates usage and features of the event page\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 2,\n  \"permissions\": [\"alarms\", \"tabs\", \"bookmarks\", \"declarativeWebRequest\", \"*://*/*\"],\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"browser_action\": {\n    \"default_icon\" : \"icon.png\",\n    \"default_title\": \"Start Event Page\"\n  },\n  \"commands\": {\n    \"open-google\": {\n      \"description\": \"Open a tab to google.com\",\n      \"suggested_key\": { \"default\": \"Ctrl+Shift+L\" }\n    },\n    \"_execute_browser_action\": {\n      \"suggested_key\": { \"default\": \"Ctrl+Shift+K\" }\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/extension/isAllowedAccess/manifest.json",
    "content": "{\n  \"name\" : \"`extension.isAllowedFileSchemeAccess` and `extension.isAllowedIncognitoAccess` Example\",\n  \"version\" : \"1.0.0\",\n  \"description\" : \"Demonstrates the `extension.isAllowedFileSchemeAccess` and `extesion.isAllowedIncognitoAccess` APIs\",\n  \"permissions\" : [ \"file://*\" ],\n  \"browser_action\" : {\n    \"default_popup\": \"popup.html\",\n    \"default_icon\" : \"sample-19.png\"\n  },\n  \"icons\" : {\n    \"16\" : \"sample-16.png\",\n    \"48\" : \"sample-48.png\",\n    \"128\" : \"sample-128.png\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/extension/isAllowedAccess/popup.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n<html>\n  <head>\n    <title>extension.isAllowedAccess Sample</title>\n    <link rel=\"stylesheet\" href=\"./sample.css\">\n  </head>\n  <body>\n    <h1>extension.isAllowedAccess Sample</h1>\n    <section>\n      <ol>\n        <li><p>\n          <span>1</span> chrome.extension.isAllowedFileSchemeAccess:\n          <code id=\"file\">unknown</code> (unpacked extensions always have\n          file scheme access, you'll need to install this as a packed\n          extension to toggle it properly)\n        </p></li>\n        <li><p>\n          <span>2</span> chrome.extension.isAllowedIncognitoAccess:\n          <code id=\"incognito\">unknown</code>\n        </p></li>\n      </ol>\n    </section>\n    <script src=\"./popup.js\"></script>\n    <script>\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/extension/isAllowedAccess/popup.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.extension.isAllowedFileSchemeAccess(function(state) {\n  var el = document.getElementById('file');\n  el.textContent = el.className = state ? 'true': 'false';\n});\nchrome.extension.isAllowedIncognitoAccess(function(state) {\n  var el = document.getElementById('incognito');\n  el.textContent = el.className = state ? 'true': 'false';\n});\n"
  },
  {
    "path": "_archive/mv2/api/extension/isAllowedAccess/sample.css",
    "content": "body {\n  margin: 5px 10px 10px;\n}\n\nh1 {\n  color: #53637D;\n  font: 26px/1.2 Helvetica, sans-serif;\n  font-size: 200%;\n  margin: 0;\n  padding-bottom: 4px;\n  text-shadow: white 0 1px 2px;\n}\n\nbody > section {\n  border-radius: 5px;\n  background: -webkit-linear-gradient(rgba(234, 238, 243, 0.2), #EAEEF3),\n              -webkit-linear-gradient(left, #EAEEF3, #EAEEF3 97%, #D3D7DB);\n  font: 14px/1 Arial,Sans Serif;\n  padding: 10px;\n  width:  563px;\n  max-height: 400px;\n  overflow-y: auto;\n  box-shadow: inset 0px 2px 5px rgba(0,0,0,0.5);\n}\n\nbody > section > ol {\n  padding: 0;\n  margin: 0;\n  list-style: none inside;\n}\n\nbody > section > ol > li {\n  position: relative;\n  margin: 0.5em 0 0.5em 40px;\n}\n\ncode {\n  word-wrap: break-word;\n  background: rgba(255,255,0, 0.5);\n}\n  code.true {\n    background: rgba(0, 255, 0, 0.5);\n  }\n  code.false {\n    background: rgba(255, 0, 0, 0.5);\n  }\n\nli > p > span:first-child {\n  position: absolute;\n  top: 0px;\n  left: -40px;\n  width: 30px;\n  text-align: right;\n  font: 30px/1 Helvetica, sans-serif;\n  font-weight: 700;\n}\n\np {\n  min-height: 30px;\n  line-height: 1.2;\n}\n"
  },
  {
    "path": "_archive/mv2/api/fileSystemProvider/archive/background.js",
    "content": "// Copyright 2014 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\n// Metadata is stored in files as serialized to JSON maps. See contents of\n// example1.fake and example2.fake.\n\n// Multiple volumes can be opened at the same time. The key is the\n// fileSystemId, which is the same as the file's displayPath.\n// The value is a Volume object.\nvar volumes = {};\n\n// Defines a volume object that contains information about a mounted file\n// system.\nfunction Volume(entry, metadata, openedFiles) {\n  // Used for restoring the opened file entry after resuming the event page.\n  this.entry = entry;\n\n  // The volume metadata.\n  this.metadata = [];\n  for (var path in metadata) {\n    this.metadata[path] = metadata[path];\n    // Date object is serialized in JSON as string.\n    this.metadata[path].modificationTime =\n        new Date(metadata[path].modificationTime);\n  }\n\n  // A map with currently opened files. The key is a requestId value from the\n  // openFileRequested event, and the value is the file path.\n  this.openedFiles = openedFiles;\n};\n\nfunction onUnmountRequested(options, onSuccess, onError) {\n  restoreState(options.fileSystemId, function() {\n    if (Object.keys(volumes[options.fileSystemId].openedFiles).length != 0) {\n      onError('IN_USE');\n      return;\n    }\n\n    chrome.fileSystemProvider.unmount(\n        {fileSystemId: options.fileSystemId},\n        function() {\n          if (chrome.runtime.lastError) {\n            onError(chrome.runtime.lastError.message);\n            return;\n          }\n          delete volumes[options.fileSystemId];\n          saveState();  // Remove volume from local storage state.\n          onSuccess();\n        });\n  }, onError);\n};\n\nfunction onGetMetadataRequested(options, onSuccess, onError) {\n  restoreState(options.fileSystemId, function () {\n    var entryMetadata =\n        volumes[options.fileSystemId].metadata[options.entryPath];\n    if (!entryMetadata)\n      error('NOT_FOUND');\n    else\n      onSuccess(entryMetadata);\n  }, onError);\n};\n\nfunction onReadDirectoryRequested(options, onSuccess, onError) {\n  restoreState(options.fileSystemId, function () {\n    var directoryMetadata =\n        volumes[options.fileSystemId].metadata[options.directoryPath];\n    if (!directoryMetadata) {\n      onError('NOT_FOUND');\n      return;\n    }\n    if (!directoryMetadata.isDirectory) {\n      onError('NOT_A_DIRECTORY');\n      return;\n    }\n\n    // Retrieve directory contents from metadata.\n    var entries = [];\n    for (var entry in volumes[options.fileSystemId].metadata) {\n      // Do not add itself on the list.\n      if (entry == options.directoryPath)\n        continue;\n      // Check if the entry is a child of the requested directory.\n      if (entry.indexOf(options.directoryPath) != 0)\n        continue;\n      // Restrict to direct children only.\n      if (entry.substring(options.directoryPath.length + 1).indexOf('/') != -1)\n        continue;\n\n      entries.push(volumes[options.fileSystemId].metadata[entry]);\n    }\n    onSuccess(entries, false /* Last call. */);\n  }, onError);\n};\n\nfunction onOpenFileRequested(options, onSuccess, onError) {\n  restoreState(options.fileSystemId, function () {\n    if (options.mode != 'READ' || options.create) {\n      onError('INVALID_OPERATION');\n    } else {\n      volumes[options.fileSystemId].openedFiles[options.requestId] =\n          options.filePath;\n      onSuccess();\n    }\n  }, onError);\n};\n\nfunction onCloseFileRequested(options, onSuccess, onError) {\n  restoreState(options.fileSystemId, function () {\n    if (!volumes[options.fileSystemId].openedFiles[options.openRequestId]) {\n      onError('INVALID_OPERATION');\n    } else {\n      delete volumes[options.fileSystemId].openedFiles[options.openRequestId];\n      onSuccess();\n    }\n  }, onError);\n};\n\nfunction onReadFileRequested(options, onSuccess, onError) {\n  restoreState(options.fileSystemId, function () {\n    var filePath =\n        volumes[options.fileSystemId].openedFiles[options.openRequestId];\n    if (!filePath) {\n      onError('INVALID_OPERATION');\n      return;\n    }\n\n    var contents = volumes[options.fileSystemId].metadata[filePath].contents;\n\n    // Write the contents as ASCII text.\n    var buffer = new ArrayBuffer(options.length);\n    var bufferView = new Uint8Array(buffer);\n    for (var i = 0; i < options.length; i++) {\n      bufferView[i] = contents.charCodeAt(i);\n    }\n\n    onSuccess(buffer, false /* Last call. */);\n  }, onError);\n};\n\n// Saves state in case of restarts, event page suspend, crashes, etc.\nfunction saveState() {\n  var state = {};\n  for (var volumeId in volumes) {\n    var entryId = chrome.fileSystem.retainEntry(volumes[volumeId].entry);\n    state[volumeId] = {\n      entryId: entryId\n    };\n  }\n  chrome.storage.local.set({state: state});\n}\n\n// Restores metadata for the passed file system ID.\nfunction restoreState(fileSystemId, onSuccess, onError) {\n  chrome.storage.local.get(['state'], function(result) {\n    // Check if metadata for the given file system is already in memory.\n    if (volumes[fileSystemId]) {\n      onSuccess();\n      return;\n    }\n\n    chrome.fileSystem.restoreEntry(\n        result.state[fileSystemId].entryId,\n        function(entry) {\n          readMetadataFromFile(entry,\n              function(metadata) {\n                chrome.fileSystemProvider.get(fileSystemId, function(info) {\n                  if (chrome.runtime.lastError) {\n                    onError(chrome.runtime.lastError.message);\n                    return;\n                  }\n                  volumes[fileSystemId] = new Volume(entry, metadata,\n                      info.openedFiles);\n                  onSuccess();\n                });\n              }, onError);\n        });\n  });\n}\n\n// Reads metadata from a file and returns it with the onSuccess callback.\nfunction readMetadataFromFile(entry, onSuccess, onError) {\n  entry.file(function(file) {\n    var fileReader = new FileReader();\n    fileReader.onload = function(event) {\n      onSuccess(JSON.parse(event.target.result));\n    };\n\n    fileReader.onerror = function(event) {\n      onError('FAILED');\n    };\n\n    fileReader.readAsText(file);\n  });\n}\n\n// Event called on opening a file with the extension or mime type\n// declared in the manifest file.\nchrome.app.runtime.onLaunched.addListener(function(event) {\n  event.items.forEach(function(item) {\n    readMetadataFromFile(item.entry,\n        function(metadata) {\n          // Mount the volume and save its information in local storage\n          // in order to be able to recover the metadata in case of\n          // restarts, system crashes, etc.\n          chrome.fileSystem.getDisplayPath(item.entry, function(displayPath) {\n            volumes[displayPath] = new Volume(item.entry, metadata, []);\n            chrome.fileSystemProvider.mount(\n                {fileSystemId: displayPath, displayName: item.entry.name},\n                function() {\n                  if (chrome.runtime.lastError) {\n                    console.error('Failed to mount because of: ' +\n                        chrome.runtime.lastError.message);\n                    return;\n                  };\n                  saveState();\n                });\n          });\n        },\n        function(error) {\n          console.error(error);\n        });\n  });\n});\n\n// Event called on a profile startup.\nchrome.runtime.onStartup.addListener(function () {\n  chrome.storage.local.get(['state'], function(result) {\n    // Nothing to change.\n    if (!result.state)\n      return;\n\n    chrome.storage.local.set({state: result.state});\n  });\n});\n\n// Save the state before suspending the event page, so we can resume it\n// once new events arrive.\nchrome.runtime.onSuspend.addListener(function() {\n  saveState();\n});\n\nchrome.fileSystemProvider.onUnmountRequested.addListener(\n    onUnmountRequested);\nchrome.fileSystemProvider.onGetMetadataRequested.addListener(\n    onGetMetadataRequested);\nchrome.fileSystemProvider.onReadDirectoryRequested.addListener(\n    onReadDirectoryRequested);\nchrome.fileSystemProvider.onOpenFileRequested.addListener(\n    onOpenFileRequested);\nchrome.fileSystemProvider.onCloseFileRequested.addListener(\n    onCloseFileRequested);\nchrome.fileSystemProvider.onReadFileRequested.addListener(\n    onReadFileRequested);\n"
  },
  {
    "path": "_archive/mv2/api/fileSystemProvider/archive/example1.fake",
    "content": "{\n  \"/\": {\n    \"isDirectory\": true,\n    \"name\": \"\",\n    \"size\": 0,\n    \"modificationTime\": \"2014-06-26T08:47:11.591Z\"\n  },\n  \"/file1.txt\": {\n    \"isDirectory\": false,\n    \"name\": \"file1.txt\",\n    \"size\": 46,\n    \"modificationTime\": \"2014-06-26T08:47:11.591Z\",\n    \"contents\": \"It works!\\nEverything gets displayed correctly.\"\n  },\n  \"/file2\": {\n    \"isDirectory\": false,\n    \"name\": \"file2\",\n    \"size\": 150,\n    \"modificationTime\": \"2014-06-26T08:47:11.591Z\"\n  },\n  \"/dir\": {\n    \"isDirectory\": true,\n    \"name\": \"dir\",\n    \"size\": 0,\n    \"modificationTime\": \"2014-06-26T08:47:11.591Z\"\n  },\n  \"/dir/file3.txt\": {\n    \"isDirectory\": false,\n    \"name\": \"file3.txt\",\n    \"size\": 21,\n    \"modificationTime\": \"2014-06-26T08:47:11.591Z\",\n    \"contents\": \"Just another example.\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/fileSystemProvider/archive/example2.fake",
    "content": "{\n  \"/\": {\n    \"isDirectory\": true,\n    \"name\": \"\",\n    \"size\": 0,\n    \"modificationTime\": \"2014-06-26T08:47:11.591Z\"\n  },\n  \"/file.txt\": {\n    \"isDirectory\": false,\n    \"name\": \"file.txt\",\n    \"size\": 9,\n    \"modificationTime\": \"2014-06-26T08:47:11.591Z\",\n    \"contents\": \"It works!\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/fileSystemProvider/archive/manifest.json",
    "content": "{\n  \"name\": \"Fake Archive Handler App\",\n  \"version\": \"0.1\",\n  \"manifest_version\": 2,\n  \"description\": \"Demonstrate File System Provider API usage for apps.\",\n  \"permissions\": [\n    \"fileSystemProvider\",\n    {\"fileSystem\": [\"retainEntries\"]},\n    \"storage\"\n  ],\n  \"file_handlers\": {\n    \"fake\": {\n      \"types\": [\"application/fake\"],\n      \"extensions\": [\"fake\"]\n    }\n  },\n  \"file_system_provider_capabilities\": {\n    \"multiple_mounts\": true,\n    \"source\": \"file\"\n  },\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\n        \"background.js\"\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/fileSystemProvider/basic/background.js",
    "content": "// Copyright 2014 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\n// Fake data similar to a file system structure.\nvar MODIFICATION_DATE = new Date();\nvar SHORT_CONTENTS = 'Just another example.';\nvar LONGER_CONTENTS = 'It works!\\nEverything gets displayed correctly.';\n\nvar METADATA = {\n  '/': {isDirectory: true, name: '', size: 0,\n      modificationTime: MODIFICATION_DATE},\n  '/file1.txt': {isDirectory: false, name: 'file1.txt',\n      size: LONGER_CONTENTS.length, modificationTime: MODIFICATION_DATE,\n      contents: LONGER_CONTENTS},\n  '/file2': {isDirectory: false, name: 'file2', size: 150,\n      modificationTime: MODIFICATION_DATE},\n  '/dir': {isDirectory: true, name: 'dir', size: 0,\n      modificationTime: MODIFICATION_DATE},\n  '/dir/file3.txt': {isDirectory: false, name: 'file3.txt',\n      size: SHORT_CONTENTS.length, modificationTime: MODIFICATION_DATE,\n      contents: SHORT_CONTENTS}};\n\n// A map with currently opened files. As key it has requestId of\n// openFileRequested and as a value the file path.\nvar openedFiles = {};\n\nfunction onGetMetadataRequested(options, onSuccess, onError) {\n  if (!METADATA[options.entryPath])\n    onError('NOT_FOUND');\n  else\n    onSuccess(METADATA[options.entryPath]);\n}\n\nfunction onReadDirectoryRequested(options, onSuccess, onError) {\n  if (!METADATA[options.directoryPath]) {\n    onError('NOT_FOUND');\n    return;\n  }\n  if (!METADATA[options.directoryPath].isDirectory) {\n    onError('NOT_A_DIRECTORY');\n    return;\n  }\n\n  // Retrieve directory contents from METADATA.\n  var entries = [];\n  for (var entry in METADATA) {\n    // Do not add itself on the list.\n    if (entry == options.directoryPath)\n      continue;\n    // Check if the entry is a child of the requested directory.\n    if (entry.indexOf(options.directoryPath) != 0)\n      continue;\n    // Restrict to direct children only.\n    if (entry.substring(options.directoryPath.length + 1).indexOf('/') != -1)\n      continue;\n\n    entries.push(METADATA[entry]);\n  }\n  onSuccess(entries, false /* Last call. */);\n}\n\nfunction onOpenFileRequested(options, onSuccess, onError) {\n  if (options.mode != 'READ' || options.create) {\n    onError('INVALID_OPERATION');\n  } else {\n    openedFiles[options.requestId] = options.filePath;\n    onSuccess();\n  }\n}\n\nfunction onCloseFileRequested(options, onSuccess, onError) {\n  if (!openedFiles[options.openRequestId]) {\n    onError('INVALID_OPERATION');\n  } else {\n    delete openedFiles[options.openRequestId];\n    onSuccess();\n  }\n}\n\nfunction onReadFileRequested(options, onSuccess, onError) {\n  if (!openedFiles[options.openRequestId]) {\n    onError('INVALID_OPERATION');\n    return;\n  }\n\n  var contents =\n      METADATA[openedFiles[options.openRequestId]].contents;\n\n  var remaining = Math.max(0, contents.length - options.offset);\n  var length = Math.min(remaining, options.length);\n\n  // Write the contents as ASCII text.\n  var buffer = new ArrayBuffer(length);\n  var bufferView = new Uint8Array(buffer);\n  for (var i = 0; i < length; i++) {\n    bufferView[i] = contents.charCodeAt(i + options.offset);\n  }\n\n  onSuccess(buffer, false /* Last call. */);\n}\n\nfunction onMountRequested(onSuccess, onError) {\n  chrome.fileSystemProvider.mount(\n      {fileSystemId: 'sample-file-system', displayName: 'Sample File System'},\n      function() {\n        if (chrome.runtime.lastError) {\n          onError(chrome.runtime.lastError.message);\n          console.error('Failed to mount because of: ' +\n              chrome.runtime.lastError.message);\n          return;\n        }\n        onSuccess();\n      });\n}\n\nfunction onUnmountRequested(options, onSuccess, onError) {\n  chrome.fileSystemProvider.unmount(\n      {fileSystemId: options.fileSystemId},\n      function() {\n        if (chrome.runtime.lastError) {\n          onError(chrome.runtime.lastError.message);\n          console.error('Failed to unmount because of: ' +\n              chrome.runtime.lastError.message);\n          return;\n        }\n        onSuccess();\n      });\n}\n\nchrome.fileSystemProvider.onGetMetadataRequested.addListener(\n    onGetMetadataRequested);\nchrome.fileSystemProvider.onReadDirectoryRequested.addListener(\n    onReadDirectoryRequested);\nchrome.fileSystemProvider.onOpenFileRequested.addListener(onOpenFileRequested);\nchrome.fileSystemProvider.onCloseFileRequested.addListener(\n    onCloseFileRequested);\nchrome.fileSystemProvider.onReadFileRequested.addListener(onReadFileRequested);\nchrome.fileSystemProvider.onMountRequested.addListener(onMountRequested);\nchrome.fileSystemProvider.onUnmountRequested.addListener(onUnmountRequested);\n"
  },
  {
    "path": "_archive/mv2/api/fileSystemProvider/basic/manifest.json",
    "content": "{\n  \"name\": \"File System Provider API Extension Example\",\n  \"version\": \"0.1\",\n  \"manifest_version\": 2,\n  \"description\":\n      \"Demonstrate features of the API like mounting, listing directories, etc for extensions.\",\n  \"permissions\": [\n    \"fileSystemProvider\"\n  ],\n  \"file_system_provider_capabilities\": {\n    \"source\": \"network\"\n  },\n  \"background\": {\n    \"scripts\": [\n      \"background.js\"\n    ]\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/fontSettings/css/chrome_shared.css",
    "content": "/* Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file. */\n\n/* Copy of /resources/shared/css/chrome_shared.css for sample extension. */\n\n/* Prevent CSS from overriding the hidden property. */\n[hidden] {\n  display: none !important;\n}\n\nhtml.loading * {\n  transition-delay: 0ms !important;\n  transition-duration: 0ms !important;\n}\n\nbody {\n  cursor: default;\n  margin: 0;\n}\n\np {\n  line-height: 1.8em;\n}\n\nh1,\nh2,\nh3 {\n  -webkit-user-select: none;\n  font-weight: normal;\n  /* Makes the vertical size of the text the same for all fonts. */\n  line-height: 1;\n}\n\nh1 {\n  font-size: 1.5em;\n}\n\nh2 {\n  font-size: 1.3em;\n  margin-bottom: 0.4em;\n}\n\nh3 {\n  color: black;\n  font-size: 1.2em;\n  margin-bottom: 0.8em;\n}\n\na {\n  color: rgb(17, 85, 204);\n  text-decoration: underline;\n}\n\na:active {\n  color: rgb(5, 37, 119);\n}\n\n/* Elements that need to be LTR even in an RTL context, but should align\n * right. (Namely, URLs, search engine names, etc.)\n */\nhtml[dir='rtl'] .weakrtl {\n  direction: ltr;\n  text-align: right;\n}\n\n/* Input fields in search engine table need to be weak-rtl. Since those input\n * fields are generated for all cr.ListItem elements (and we only want weakrtl\n * on some), the class needs to be on the enclosing div.\n */\nhtml[dir='rtl'] div.weakrtl input {\n  direction: ltr;\n  text-align: right;\n}\n\nhtml[dir='rtl'] .favicon-cell.weakrtl {\n  padding-inline-end: 22px;\n  padding-inline-start: 0;\n}\n\n/* weakrtl for selection drop downs needs to account for the fact that\n * Webkit does not honor the text-align attribute for the select element.\n * (See Webkit bug #40216)\n */\nhtml[dir='rtl'] select.weakrtl {\n  direction: rtl;\n}\n\nhtml[dir='rtl'] select.weakrtl option {\n  direction: ltr;\n}\n\n/* WebKit does not honor alignment for text specified via placeholder attribute.\n * This CSS is a workaround. Please remove once WebKit bug is fixed.\n * https://bugs.webkit.org/show_bug.cgi?id=63367\n */\nhtml[dir='rtl'] input.weakrtl::-webkit-input-placeholder,\nhtml[dir='rtl'] .weakrtl input::-webkit-input-placeholder {\n  direction: rtl;\n}\n"
  },
  {
    "path": "_archive/mv2/api/fontSettings/css/overlay.css",
    "content": "/* Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file. */\n\n/* The shield that overlays the background. */\n.overlay {\n  -webkit-box-align: center;\n  -webkit-box-orient: vertical;\n  -webkit-box-pack: center;\n  background-color: rgba(255, 255, 255, 0.75);\n  bottom: 0;\n  display: -webkit-box;\n  left: 0;\n  overflow: auto;\n  padding: 20px;\n  position: fixed;\n  right: 0;\n  top: 0;\n  transition: 200ms opacity;\n}\n\n/* Used to slide in the overlay. */\n.overlay.transparent .page {\n  /* TODO(flackr): Add perspective(500px) rotateX(5deg) when accelerated\n   * compositing is enabled on chrome:// pages. See http://crbug.com/116800. */\n  transform: scale(0.99) translateY(-20px);\n}\n\n/* The foreground dialog. */\n.overlay .page {\n  -webkit-border-radius: 3px;\n  -webkit-box-orient: vertical;\n  background: white;\n  box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0,0,0,0.15);\n  color: #333;\n  display: -webkit-box;\n  min-width: 400px;\n  padding: 0;\n  position: relative;\n  transition: 200ms transform;\n}\n\n/* If the options page is loading don't do the transition. */\n.loading .overlay,\n.loading .overlay .page {\n  transition-duration: 0ms !important;\n}\n\n/* keyframes used to pulse the overlay */\n@keyframes pulse {\n 0% {\n   transform: scale(1);\n }\n 40% {\n   transform: scale(1.02);\n  }\n 60% {\n   transform: scale(1.02);\n  }\n 100% {\n   transform: scale(1);\n }\n}\n\n.overlay .page.pulse {\n  animation-duration: 180ms;\n  animation-iteration-count: 1;\n  animation-name: pulse;\n  animation-timing-function: ease-in-out;\n}\n\n.overlay .page > .close-button {\n  background-image: url('../images/x.png');\n  background-position: center;\n  background-repeat: no-repeat;\n  height: 14px;\n  position: absolute;\n  right: 7px;\n  top: 7px;\n  width: 14px;\n}\n\nhtml[dir='rtl'] .overlay .page > .close-button {\n  left: 10px;\n  right: auto;\n}\n\n.overlay .page > .close-button:hover {\n  background-image: url('../images/x-hover.png');\n}\n\n.overlay .page > .close-button:active {\n  background-image: url('../images/x-pressed.png');\n}\n\n.overlay .page h1 {\n  -webkit-user-select: none;\n  color: #333;\n  /* 120% of the body's font-size of 84% is 16px. This will keep the relative\n   * size between the body and these titles consistent. */\n  font-size: 120%;\n  /* TODO(flackr): Pages like sync-setup and delete user collapse the margin\n   * above the top of the page. Use padding instead to make sure that the\n   * headers of these pages have the correct spacing, but this should not be\n   * necessary. See http://crbug.com/119029. */\n  margin: 0;\n  padding: 14px 17px 14px;\n  text-shadow: white 0 1px 2px;\n}\n\n.overlay .page .content-area {\n  -webkit-box-flex: 1;\n  overflow: auto;\n  padding: 6px 17px 6px;\n  position: relative;\n}\n\n.overlay .page .action-area {\n  -webkit-box-align: center;\n  -webkit-box-orient: horizontal;\n  -webkit-box-pack: end;\n  display: -webkit-box;\n  padding: 14px 17px;\n}\n\nhtml[dir='rtl'] .overlay .page .action-area {\n  left: 0;\n}\n\n.overlay .page .action-area-right {\n  display: -webkit-box;\n}\n\n.overlay .page .button-strip {\n  -webkit-box-orient: horizontal;\n  display: -webkit-box;\n}\n\n.overlay .page .button-strip > button {\n  display: block;\n  margin-inline-start: 10px;\n}\n\n/* On OSX 10.7, hidden scrollbars may prevent the user from realizing that the\n * overlay contains scrollable content. To resolve this, style the scrollbars on\n * OSX so they are always visible. See http://crbug.com/123010. */\n<if expr=\"is_macosx\">\n.overlay .page .content-area::-webkit-scrollbar {\n  -webkit-appearance: none;\n  width: 11px;\n}\n\n.overlay .page .content-area::-webkit-scrollbar-thumb {\n  background-color: rgba(0, 0, 0, 0.2);\n  border: 2px solid white;\n  border-radius: 8px;\n}\n\n.overlay .page .content-area::-webkit-scrollbar-thumb:hover {\n  background-color: rgba(0, 0, 0, 0.5);\n}\n</if>\n"
  },
  {
    "path": "_archive/mv2/api/fontSettings/css/uber_shared.css",
    "content": "/* Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file. */\n\nbody.uber-frame {\n  color: rgb(48, 57, 66);\n  margin-inline-start: 155px;\n}\n\nhtml[dir='rtl'] body.uber-frame {\n  /* Enable vertical scrollbar at all times in RTL to avoid visual glitches when\n   * showing sub-pages that vertically overflow. */\n  overflow-y: scroll;\n}\n\n/* TODO(dbeam): Remove .page class from overlays in settings so the junk below\n * isn't necessary. */\nbody.uber-frame #extension-settings.page,\nbody.uber-frame #mainview-content .page,\nbody.uber-frame .subpage-sheet-container .page,\nbody.uber-frame > .page {\n  margin-inline-end: 24px;\n  min-width: 576px;\n  padding-bottom: 20px;\n  padding-top: 55px;\n}\n\nbody.uber-frame header {\n  background-image: -webkit-linear-gradient(white,\n                                            white 40%,\n                                            rgba(255, 255, 255, 0.92));\n  left: 155px;\n  /* <section>s in options currently amount to 638px total, broken up into\n   * 600px max-width + 18px padding-inline-start + 20px margin-inline-end\n   * so we mirror this value here so the headers match width and horizontal\n   * alignment when scrolling sideways. */\n  max-width: 738px;\n  min-width: 600px;\n  position: fixed;\n  right: 0;\n  top: 0;\n  /* list.css sets a z-index of up to 2, this is set to 3 to ensure that the\n   * header is in front of the selected list item. */\n  z-index: 3;\n}\n\nhtml[dir='rtl'] body.uber-frame header {\n  left: 0;\n  right: 155px;\n}\n\nbody.uber-frame header > .search-field-container,\nbody.uber-frame header > .header-extras,\nbody.uber-frame header > button {\n  position: absolute;\n  right: 20px;\n  top: 21px;\n}\n\nhtml[dir='rtl'] body.uber-frame header > .search-field-container,\nhtml[dir='rtl'] body.uber-frame header > .header-extras,\nhtml[dir='rtl'] body.uber-frame header > button {\n  left: 20px;\n  right: auto;\n}\n\nbody.uber-frame header input[type='search'],\nbody.uber-frame header input[type='text'],\nbody.uber-frame header button {\n  margin: 0;\n}\n\nbody.uber-frame header > h1 {\n  margin: 0;\n  padding: 21px 0 13px;\n}\n\n/* Create a border under the h1 (but before anything that gets appended\n * to the end of the header). */\nbody.uber-frame header > h1::after {\n  background-color: #eee;\n  content: ' ';\n  display: block;\n  height: 1px;\n  margin-inline-end: 20px;\n  position: relative;\n  top: 13px;\n}\n\nbody.uber-frame footer {\n  border-top: 1px solid #eee;\n  margin-top: 16px;\n  /* min-width and max-width should match the header */\n  max-width: 638px;\n  min-width: 600px;\n  padding: 8px 0;\n}\n\n/* Sections are used in options pages, help page and history page. This defines\n * the section metrics to match the header metrics above. */\nbody.uber-frame section {\n  margin-bottom: 24px;\n  margin-top: 8px;\n  max-width: 600px;\n  padding-inline-start: 18px;\n}\n\nbody.uber-frame section:last-of-type {\n  margin-bottom: 0;\n}\n\nbody.uber-frame section > h3 {\n  margin-inline-start: -18px;\n}\n\nbody.uber-frame section > div:only-of-type {\n  -webkit-box-flex: 1;\n}\n"
  },
  {
    "path": "_archive/mv2/api/fontSettings/css/widgets.css",
    "content": "/* Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n/* This file defines styles for form controls. The order of rule blocks is\n * important as there are some rules with equal specificity that rely on order\n * as a tiebreaker. These are marked with OVERRIDE.\n */\n\n/* Default state **************************************************************/\n\n:-webkit-any(button,\n             input[type='button'],\n             input[type='submit']):not(.custom-appearance):not(.link-button),\nselect,\ninput[type='checkbox'],\ninput[type='radio'] {\n  -webkit-appearance: none;\n  -webkit-user-select: none;\n  background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);\n  border: 1px solid rgba(0, 0, 0, 0.25);\n  border-radius: 2px;\n  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08),\n      inset 0 1px 2px rgba(255, 255, 255, 0.75);\n  color: #444;\n  font: inherit;\n  margin: 0 1px 0 0;\n  text-shadow: 0 1px 0 rgb(240, 240, 240);\n}\n\n:-webkit-any(button,\n             input[type='button'],\n             input[type='submit']):not(.custom-appearance):not(.link-button),\nselect {\n  min-height: 2em;\n  min-width: 4em;\n<if expr=\"is_win\">\n  /* The following platform-specific rule is necessary to get adjacent\n   * buttons, text inputs, and so forth to align on their borders while also\n   * aligning on the text's baselines. */\n  padding-bottom: 1px;\n</if>\n}\n\n:-webkit-any(button,\n             input[type='button'],\n             input[type='submit']):not(.custom-appearance):not(.link-button) {\n  padding-inline-end: 10px;\n  padding-inline-start: 10px;\n}\n\nselect {\n  -webkit-appearance: none;\n  /* OVERRIDE */\n  background-image: url('../images/select.png'),\n      -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);\n  background-position: right center;\n  background-repeat: no-repeat;\n  padding-inline-end: 20px;\n  padding-inline-start: 6px;\n}\n\nhtml[dir='rtl'] select {\n  background-position: center left;\n}\n\ninput[type='checkbox'] {\n  bottom: 2px;\n  height: 13px;\n  position: relative;\n  vertical-align: middle;\n  width: 13px;\n}\n\ninput[type='radio'] {\n  /* OVERRIDE */\n  border-radius: 100%;\n  bottom: 3px;\n  height: 15px;\n  position: relative;\n  vertical-align: middle;\n  width: 15px;\n}\n\n/* TODO(estade): add more types here? */\ninput[type='password'],\ninput[type='search'],\ninput[type='text'],\ninput[type='url'],\ninput[type='number'],\ninput:not([type]),\ntextarea {\n  border: 1px solid #bfbfbf;\n  border-radius: 2px;\n  box-sizing: border-box;\n  color: #444;\n  font: inherit;\n  margin: 0;\n  /* Use min-height to accommodate addditional padding for touch as needed. */\n  min-height: 2em;\n  padding: 3px;\n<if expr=\"is_win or is_macosx\">\n  /* For better alignment between adjacent buttons and inputs. */\n  padding-bottom: 4px;\n</if>\n}\n\ninput[type='search'] {\n  -webkit-appearance: textfield;\n  /* NOTE: Keep a relatively high min-width for this so we don't obscure the end\n   * of the default text in relatively spacious languages (i.e. German). */\n  min-width: 160px;\n}\n\n/* Checked ********************************************************************/\n\ninput[type='checkbox']:checked::before {\n  -webkit-user-select: none;\n  background-image: url('../images/check.png');\n  background-size: 100% 100%;\n  content: '';\n  display: block;\n  height: 100%;\n  width: 100%;\n}\n\nhtml[dir='rtl'] input[type='checkbox']:checked::before {\n  transform: scaleX(-1);\n}\n\ninput[type='radio']:checked::before {\n  background-color: #666;\n  border-radius: 100%;\n  bottom: 3px;\n  content: '';\n  display: block;\n  left: 3px;\n  position: absolute;\n  right: 3px;\n  top: 3px;\n}\n\n/* Hover **********************************************************************/\n\n:enabled:hover:-webkit-any(\n    select,\n    input[type='checkbox'],\n    input[type='radio'],\n    :-webkit-any(\n        button,\n        input[type='button'],\n        input[type='submit']):not(.custom-appearance):not(.link-button)) {\n  background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0);\n  border-color: rgba(0, 0, 0, 0.3);\n  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12),\n      inset 0 1px 2px rgba(255, 255, 255, 0.95);\n  color: black;\n}\n\n:enabled:hover:-webkit-any(select) {\n  /* OVERRIDE */\n  background-image: url('../images/select.png'),\n      -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0);\n}\n\n/* Active *********************************************************************/\n\n:enabled:active:-webkit-any(\n    select,\n    input[type='checkbox'],\n    input[type='radio'],\n    :-webkit-any(\n        button,\n        input[type='button'],\n        input[type='submit']):not(.custom-appearance):not(.link-button)) {\n  background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);\n  box-shadow: none;\n  text-shadow: none;\n}\n\n:enabled:active:-webkit-any(select) {\n  /* OVERRIDE */\n  background-image: url('../images/select.png'),\n      -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);\n}\n\n/* Disabled *******************************************************************/\n\n:disabled:-webkit-any(\n    button,\n    input[type='button'],\n    input[type='submit']):not(.custom-appearance):not(.link-button),\nselect:disabled {\n  background-image: -webkit-linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6);\n  border-color: rgba(80, 80, 80, 0.2);\n  box-shadow: 0 1px 0 rgba(80, 80, 80, 0.08),\n      inset 0 1px 2px rgba(255, 255, 255, 0.75);\n  color: #aaa;\n}\n\nselect:disabled {\n  /* OVERRIDE */\n  background-image: url('../images/disabled_select.png'),\n      -webkit-linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6);\n}\n\ninput:disabled:-webkit-any([type='checkbox'],\n                           [type='radio']) {\n  opacity: .75;\n}\n\ninput:disabled:-webkit-any([type='password'],\n                           [type='search'],\n                           [type='text'],\n                           [type='url'],\n                           :not([type])) {\n  color: #999;\n}\n\n/* Focus **********************************************************************/\n\n:enabled:focus:-webkit-any(\n    select,\n    input[type='checkbox'],\n    input[type='password'],\n    input[type='radio'],\n    input[type='search'],\n    input[type='text'],\n    input[type='url'],\n    input:not([type]),\n    :-webkit-any(\n         button,\n         input[type='button'],\n         input[type='submit']):not(.custom-appearance):not(.link-button)) {\n  /* OVERRIDE */\n  transition: border-color 200ms;\n  /* We use border color because it follows the border radius (unlike outline).\n   * This is particularly noticeable on mac. */\n  border-color: rgb(77, 144, 254);\n  outline: none;\n}\n\n/* Link buttons ***************************************************************/\n\n.link-button {\n  -webkit-box-shadow: none;\n  background: transparent none;\n  border: none;\n  color: rgb(17, 85, 204);\n  cursor: pointer;\n  /* Input elements have -webkit-small-control which can override the body font.\n   * Resolve this by using 'inherit'. */\n  font: inherit;\n  margin: 0;\n  padding: 0 4px;\n}\n\n.link-button:hover {\n  text-decoration: underline;\n}\n\n.link-button:active {\n  color: rgb(5, 37, 119);\n  text-decoration: underline;\n}\n\n.link-button[disabled] {\n  color: #999;\n  cursor: default;\n  text-decoration: none;\n}\n\n/* Checkbox/radio helpers ******************************************************\n *\n * .checkbox and .radio classes wrap labels. Checkboxes and radios should use\n * these classes with the markup structure:\n *\n *   <div class=\"checkbox\">\n *     <label>\n *       <input type=\"checkbox\"></input>\n *       <span>\n *     </label>\n *   </div>\n */\n\n:-webkit-any(.checkbox, .radio) label {\n  /* Don't expand horizontally: <http://crbug.com/112091>. */\n  display: -webkit-inline-box;\n  padding-bottom: 7px;\n  padding-top: 7px;\n}\n\n:-webkit-any(.checkbox, .radio) label input ~ span {\n  /* Make sure long spans wrap at the same horizontal position they start. */\n  display: block;\n  margin-inline-start: 0.6em;\n}\n\n:-webkit-any(.checkbox, .radio) label:hover {\n  color: black;\n}\n\nlabel > input:disabled:-webkit-any([type='checkbox'], [type='radio']) ~ span {\n  color: #999;\n}\n"
  },
  {
    "path": "_archive/mv2/api/fontSettings/js/cr/ui/overlay.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview Provides dialog-like behaviors for the tracing UI.\n */\ncr.define('cr.ui.overlay', function() {\n\n  /**\n   * Gets the top, visible overlay. It makes the assumption that if multiple\n   * overlays are visible, the last in the byte order is topmost.\n   * TODO(estade): rely on aria-visibility instead?\n   * @return {HTMLElement} The overlay.\n   */\n  function getTopOverlay() {\n    var overlays = document.querySelectorAll('.overlay:not([hidden])');\n    return overlays[overlays.length - 1];\n  }\n\n  /**\n   * Makes initializations which must hook at the document level.\n   */\n  function globalInitialization() {\n    // Close the overlay on escape.\n    document.addEventListener('keydown', function(e) {\n      if (e.keyCode == 27) {  // Escape\n        var overlay = getTopOverlay();\n        if (!overlay)\n          return;\n\n        cr.dispatchSimpleEvent(overlay, 'cancelOverlay');\n      }\n    });\n\n    window.addEventListener('resize', setMaxHeightAllPages);\n\n    setMaxHeightAllPages();\n  }\n\n  /**\n   * Sets the max-height of all pages in all overlays, based on the window\n   * height.\n   */\n  function setMaxHeightAllPages() {\n    var pages = document.querySelectorAll('.overlay .page');\n\n    var maxHeight = Math.min(0.9 * window.innerHeight, 640) + 'px';\n    for (var i = 0; i < pages.length; i++)\n      pages[i].style.maxHeight = maxHeight;\n  }\n\n  /**\n   * Adds behavioral hooks for the given overlay.\n   * @param {HTMLElement} overlay The .overlay.\n   */\n  function setupOverlay(overlay) {\n    // Close the overlay on clicking any of the pages' close buttons.\n    var closeButtons = overlay.querySelectorAll('.page > .close-button');\n    for (var i = 0; i < closeButtons.length; i++) {\n      closeButtons[i].addEventListener('click', function(e) {\n        cr.dispatchSimpleEvent(overlay, 'cancelOverlay');\n      });\n    }\n\n    // Remove the 'pulse' animation any time the overlay is hidden or shown.\n    overlay.__defineSetter__('hidden', function(value) {\n      this.classList.remove('pulse');\n      if (value)\n        this.setAttribute('hidden', true);\n      else\n        this.removeAttribute('hidden');\n    });\n    overlay.__defineGetter__('hidden', function() {\n      return this.hasAttribute('hidden');\n    });\n\n    // Shake when the user clicks away.\n    overlay.addEventListener('click', function(e) {\n      // Only pulse if the overlay was the target of the click.\n      if (this != e.target)\n        return;\n\n      // This may be null while the overlay is closing.\n      var overlayPage = this.querySelector('.page:not([hidden])');\n      if (overlayPage)\n        overlayPage.classList.add('pulse');\n    });\n    overlay.addEventListener('animationend', function(e) {\n      e.target.classList.remove('pulse');\n    });\n  }\n\n  return {\n    globalInitialization: globalInitialization,\n    setupOverlay: setupOverlay,\n  };\n});\n\ndocument.addEventListener('DOMContentLoaded',\n                          cr.ui.overlay.globalInitialization);\n"
  },
  {
    "path": "_archive/mv2/api/fontSettings/js/cr/ui.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\ncr.define('cr.ui', function() {\n\n  /**\n   * Decorates elements as an instance of a class.\n   * @param {string|!Element} source The way to find the element(s) to decorate.\n   *     If this is a string then {@code querySeletorAll} is used to find the\n   *     elements to decorate.\n   * @param {!Function} constr The constructor to decorate with. The constr\n   *     needs to have a {@code decorate} function.\n   */\n  function decorate(source, constr) {\n    var elements;\n    if (typeof source == 'string')\n      elements = cr.doc.querySelectorAll(source);\n    else\n      elements = [source];\n\n    for (var i = 0, el; el = elements[i]; i++) {\n      if (!(el instanceof constr))\n        constr.decorate(el);\n    }\n  }\n\n  /**\n   * Helper function for creating new element for define.\n   */\n  function createElementHelper(tagName, opt_bag) {\n    // Allow passing in ownerDocument to create in a different document.\n    var doc;\n    if (opt_bag && opt_bag.ownerDocument)\n      doc = opt_bag.ownerDocument;\n    else\n      doc = cr.doc;\n    return doc.createElement(tagName);\n  }\n\n  /**\n   * Creates the constructor for a UI element class.\n   *\n   * Usage:\n   * <pre>\n   * var List = cr.ui.define('list');\n   * List.prototype = {\n   *   __proto__: HTMLUListElement.prototype,\n   *   decorate: function() {\n   *     ...\n   *   },\n   *   ...\n   * };\n   * </pre>\n   *\n   * @param {string|Function} tagNameOrFunction The tagName or\n   *     function to use for newly created elements. If this is a function it\n   *     needs to return a new element when called.\n   * @return {function(Object=):Element} The constructor function which takes\n   *     an optional property bag. The function also has a static\n   *     {@code decorate} method added to it.\n   */\n  function define(tagNameOrFunction) {\n    var createFunction, tagName;\n    if (typeof tagNameOrFunction == 'function') {\n      createFunction = tagNameOrFunction;\n      tagName = '';\n    } else {\n      createFunction = createElementHelper;\n      tagName = tagNameOrFunction;\n    }\n\n    /**\n     * Creates a new UI element constructor.\n     * @param {Object=} opt_propertyBag Optional bag of properties to set on the\n     *     object after created. The property {@code ownerDocument} is special\n     *     cased and it allows you to create the element in a different\n     *     document than the default.\n     * @constructor\n     */\n    function f(opt_propertyBag) {\n      var el = createFunction(tagName, opt_propertyBag);\n      f.decorate(el);\n      for (var propertyName in opt_propertyBag) {\n        el[propertyName] = opt_propertyBag[propertyName];\n      }\n      return el;\n    }\n\n    /**\n     * Decorates an element as a UI element class.\n     * @param {!Element} el The element to decorate.\n     */\n    f.decorate = function(el) {\n      el.__proto__ = f.prototype;\n      el.decorate();\n    };\n\n    return f;\n  }\n\n  /**\n   * Input elements do not grow and shrink with their content. This is a simple\n   * (and not very efficient) way of handling shrinking to content with support\n   * for min width and limited by the width of the parent element.\n   * @param {HTMLElement} el The element to limit the width for.\n   * @param {number} parentEl The parent element that should limit the size.\n   * @param {number} min The minimum width.\n   * @param {number} opt_scale Optional scale factor to apply to the width.\n   */\n  function limitInputWidth(el, parentEl, min, opt_scale) {\n    // Needs a size larger than borders\n    el.style.width = '10px';\n    var doc = el.ownerDocument;\n    var win = doc.defaultView;\n    var computedStyle = win.getComputedStyle(el);\n    var parentComputedStyle = win.getComputedStyle(parentEl);\n    var rtl = computedStyle.direction == 'rtl';\n\n    // To get the max width we get the width of the treeItem minus the position\n    // of the input.\n    var inputRect = el.getBoundingClientRect();  // box-sizing\n    var parentRect = parentEl.getBoundingClientRect();\n    var startPos = rtl ? parentRect.right - inputRect.right :\n        inputRect.left - parentRect.left;\n\n    // Add up border and padding of the input.\n    var inner = parseInt(computedStyle.borderLeftWidth, 10) +\n        parseInt(computedStyle.paddingLeft, 10) +\n        parseInt(computedStyle.paddingRight, 10) +\n        parseInt(computedStyle.borderRightWidth, 10);\n\n    // We also need to subtract the padding of parent to prevent it to overflow.\n    var parentPadding = rtl ? parseInt(parentComputedStyle.paddingLeft, 10) :\n        parseInt(parentComputedStyle.paddingRight, 10);\n\n    var max = parentEl.clientWidth - startPos - inner - parentPadding;\n    if (opt_scale)\n      max *= opt_scale;\n\n    function limit() {\n      if (el.scrollWidth > max) {\n        el.style.width = max + 'px';\n      } else {\n        el.style.width = 0;\n        var sw = el.scrollWidth;\n        if (sw < min) {\n          el.style.width = min + 'px';\n        } else {\n          el.style.width = sw + 'px';\n        }\n      }\n    }\n\n    el.addEventListener('input', limit);\n    limit();\n  }\n\n  /**\n   * Takes a number and spits out a value CSS will be happy with. To avoid\n   * subpixel layout issues, the value is rounded to the nearest integral value.\n   * @param {number} pixels The number of pixels.\n   * @return {string} e.g. '16px'.\n   */\n  function toCssPx(pixels) {\n    if (!window.isFinite(pixels))\n      console.error('Pixel value is not a number: ' + pixels);\n    return Math.round(pixels) + 'px';\n  }\n\n  return {\n    decorate: decorate,\n    define: define,\n    limitInputWidth: limitInputWidth,\n    toCssPx: toCssPx,\n  };\n});\n"
  },
  {
    "path": "_archive/mv2/api/fontSettings/js/cr.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * The global object.\n * @type {!Object}\n * @const\n */\nvar global = this;\n\n/** Platform, package, object property, and Event support. **/\nthis.cr = (function() {\n  'use strict';\n\n  /**\n   * Builds an object structure for the provided namespace path,\n   * ensuring that names that already exist are not overwritten. For\n   * example:\n   * \"a.b.c\" -> a = {};a.b={};a.b.c={};\n   * @param {string} name Name of the object that this file defines.\n   * @param {*=} opt_object The object to expose at the end of the path.\n   * @param {Object=} opt_objectToExportTo The object to add the path to;\n   *     default is {@code global}.\n   * @private\n   */\n  function exportPath(name, opt_object, opt_objectToExportTo) {\n    var parts = name.split('.');\n    var cur = opt_objectToExportTo || global;\n\n    for (var part; parts.length && (part = parts.shift());) {\n      if (!parts.length && opt_object !== undefined) {\n        // last part and we have an object; use it\n        cur[part] = opt_object;\n      } else if (part in cur) {\n        cur = cur[part];\n      } else {\n        cur = cur[part] = {};\n      }\n    }\n    return cur;\n  };\n\n  /**\n   * Fires a property change event on the target.\n   * @param {EventTarget} target The target to dispatch the event on.\n   * @param {string} propertyName The name of the property that changed.\n   * @param {*} newValue The new value for the property.\n   * @param {*} oldValue The old value for the property.\n   */\n  function dispatchPropertyChange(target, propertyName, newValue, oldValue) {\n    var e = new Event(propertyName + 'Change');\n    e.propertyName = propertyName;\n    e.newValue = newValue;\n    e.oldValue = oldValue;\n    target.dispatchEvent(e);\n  }\n\n  /**\n   * Converts a camelCase javascript property name to a hyphenated-lower-case\n   * attribute name.\n   * @param {string} jsName The javascript camelCase property name.\n   * @return {string} The equivalent hyphenated-lower-case attribute name.\n   */\n  function getAttributeName(jsName) {\n    return jsName.replace(/([A-Z])/g, '-$1').toLowerCase();\n  }\n\n  /**\n   * The kind of property to define in {@code defineProperty}.\n   * @enum {number}\n   * @const\n   */\n  var PropertyKind = {\n    /**\n     * Plain old JS property where the backing data is stored as a \"private\"\n     * field on the object.\n     */\n    JS: 'js',\n\n    /**\n     * The property backing data is stored as an attribute on an element.\n     */\n    ATTR: 'attr',\n\n    /**\n     * The property backing data is stored as an attribute on an element. If the\n     * element has the attribute then the value is true.\n     */\n    BOOL_ATTR: 'boolAttr'\n  };\n\n  /**\n   * Helper function for defineProperty that returns the getter to use for the\n   * property.\n   * @param {string} name The name of the property.\n   * @param {cr.PropertyKind} kind The kind of the property.\n   * @return {function():*} The getter for the property.\n   */\n  function getGetter(name, kind) {\n    switch (kind) {\n      case PropertyKind.JS:\n        var privateName = name + '_';\n        return function() {\n          return this[privateName];\n        };\n      case PropertyKind.ATTR:\n        var attributeName = getAttributeName(name);\n        return function() {\n          return this.getAttribute(attributeName);\n        };\n      case PropertyKind.BOOL_ATTR:\n        var attributeName = getAttributeName(name);\n        return function() {\n          return this.hasAttribute(attributeName);\n        };\n    }\n  }\n\n  /**\n   * Helper function for defineProperty that returns the setter of the right\n   * kind.\n   * @param {string} name The name of the property we are defining the setter\n   *     for.\n   * @param {cr.PropertyKind} kind The kind of property we are getting the\n   *     setter for.\n   * @param {function(*):void} opt_setHook A function to run after the property\n   *     is set, but before the propertyChange event is fired.\n   * @return {function(*):void} The function to use as a setter.\n   */\n  function getSetter(name, kind, opt_setHook) {\n    switch (kind) {\n      case PropertyKind.JS:\n        var privateName = name + '_';\n        return function(value) {\n          var oldValue = this[name];\n          if (value !== oldValue) {\n            this[privateName] = value;\n            if (opt_setHook)\n              opt_setHook.call(this, value, oldValue);\n            dispatchPropertyChange(this, name, value, oldValue);\n          }\n        };\n\n      case PropertyKind.ATTR:\n        var attributeName = getAttributeName(name);\n        return function(value) {\n          var oldValue = this[name];\n          if (value !== oldValue) {\n            if (value == undefined)\n              this.removeAttribute(attributeName);\n            else\n              this.setAttribute(attributeName, value);\n            if (opt_setHook)\n              opt_setHook.call(this, value, oldValue);\n            dispatchPropertyChange(this, name, value, oldValue);\n          }\n        };\n\n      case PropertyKind.BOOL_ATTR:\n        var attributeName = getAttributeName(name);\n        return function(value) {\n          var oldValue = this[name];\n          if (value !== oldValue) {\n            if (value)\n              this.setAttribute(attributeName, name);\n            else\n              this.removeAttribute(attributeName);\n            if (opt_setHook)\n              opt_setHook.call(this, value, oldValue);\n            dispatchPropertyChange(this, name, value, oldValue);\n          }\n        };\n    }\n  }\n\n  /**\n   * Defines a property on an object. When the setter changes the value a\n   * property change event with the type {@code name + 'Change'} is fired.\n   * @param {!Object} obj The object to define the property for.\n   * @param {string} name The name of the property.\n   * @param {cr.PropertyKind=} opt_kind What kind of underlying storage to use.\n   * @param {function(*):void} opt_setHook A function to run after the\n   *     property is set, but before the propertyChange event is fired.\n   */\n  function defineProperty(obj, name, opt_kind, opt_setHook) {\n    if (typeof obj == 'function')\n      obj = obj.prototype;\n\n    var kind = opt_kind || PropertyKind.JS;\n\n    if (!obj.__lookupGetter__(name))\n      obj.__defineGetter__(name, getGetter(name, kind));\n\n    if (!obj.__lookupSetter__(name))\n      obj.__defineSetter__(name, getSetter(name, kind, opt_setHook));\n  }\n\n  /**\n   * Counter for use with createUid\n   */\n  var uidCounter = 1;\n\n  /**\n   * @return {number} A new unique ID.\n   */\n  function createUid() {\n    return uidCounter++;\n  }\n\n  /**\n   * Returns a unique ID for the item. This mutates the item so it needs to be\n   * an object\n   * @param {!Object} item The item to get the unique ID for.\n   * @return {number} The unique ID for the item.\n   */\n  function getUid(item) {\n    if (item.hasOwnProperty('uid'))\n      return item.uid;\n    return item.uid = createUid();\n  }\n\n  /**\n   * Dispatches a simple event on an event target.\n   * @param {!EventTarget} target The event target to dispatch the event on.\n   * @param {string} type The type of the event.\n   * @param {boolean=} opt_bubbles Whether the event bubbles or not.\n   * @param {boolean=} opt_cancelable Whether the default action of the event\n   *     can be prevented. Default is true.\n   * @return {boolean} If any of the listeners called {@code preventDefault}\n   *     during the dispatch this will return false.\n   */\n  function dispatchSimpleEvent(target, type, opt_bubbles, opt_cancelable) {\n    var e = new Event(type, {\n      bubbles: opt_bubbles,\n      cancelable: opt_cancelable === undefined || opt_cancelable\n    });\n    return target.dispatchEvent(e);\n  }\n\n  /**\n   * Calls |fun| and adds all the fields of the returned object to the object\n   * named by |name|. For example, cr.define('cr.ui', function() {\n   *   function List() {\n   *     ...\n   *   }\n   *   function ListItem() {\n   *     ...\n   *   }\n   *   return {\n   *     List: List,\n   *     ListItem: ListItem,\n   *   };\n   * });\n   * defines the functions cr.ui.List and cr.ui.ListItem.\n   * @param {string} name The name of the object that we are adding fields to.\n   * @param {!Function} fun The function that will return an object containing\n   *     the names and values of the new fields.\n   */\n  function define(name, fun) {\n    var obj = exportPath(name);\n    var exports = fun();\n    for (var propertyName in exports) {\n      // Maybe we should check the prototype chain here? The current usage\n      // pattern is always using an object literal so we only care about own\n      // properties.\n      var propertyDescriptor = Object.getOwnPropertyDescriptor(exports,\n                                                               propertyName);\n      if (propertyDescriptor)\n        Object.defineProperty(obj, propertyName, propertyDescriptor);\n    }\n  }\n\n  /**\n   * Adds a {@code getInstance} static method that always return the same\n   * instance object.\n   * @param {!Function} ctor The constructor for the class to add the static\n   *     method to.\n   */\n  function addSingletonGetter(ctor) {\n    ctor.getInstance = function() {\n      return ctor.instance_ || (ctor.instance_ = new ctor());\n    };\n  }\n\n  /**\n   * Initialization which must be deferred until run-time.\n   */\n  function initialize() {\n    // If 'document' isn't defined, then we must be being pre-compiled,\n    // so set a trap so that we're initialized on first access at run-time.\n    if (!global.document) {\n      var originalCr = cr;\n\n      Object.defineProperty(global, 'cr', {\n        get: function() {\n          Object.defineProperty(global, 'cr', {value: originalCr});\n          originalCr.initialize();\n          return originalCr;\n        },\n        configurable: true\n      });\n\n      return;\n    }\n\n    cr.doc = document;\n\n    /**\n     * Whether we are using a Mac or not.\n     */\n    cr.isMac = /Mac/.test(navigator.platform);\n\n    /**\n     * Whether this is on the Windows platform or not.\n     */\n    cr.isWindows = /Win/.test(navigator.platform);\n\n    /**\n     * Whether this is on chromeOS or not.\n     */\n    cr.isChromeOS = /CrOS/.test(navigator.userAgent);\n\n    /**\n     * Whether this is on vanilla Linux (not chromeOS).\n     */\n    cr.isLinux = /Linux/.test(navigator.userAgent);\n  }\n\n  return {\n    addSingletonGetter: addSingletonGetter,\n    createUid: createUid,\n    define: define,\n    defineProperty: defineProperty,\n    dispatchPropertyChange: dispatchPropertyChange,\n    dispatchSimpleEvent: dispatchSimpleEvent,\n    getUid: getUid,\n    initialize: initialize,\n    PropertyKind: PropertyKind\n  };\n})();\n\n\n/**\n * TODO(kgr): Move this to another file which is to be loaded last.\n * This will be done as part of future work to make this code pre-compilable.\n */\ncr.initialize();\n"
  },
  {
    "path": "_archive/mv2/api/fontSettings/manifest.json",
    "content": "{\n  \"name\": \"Advanced Font Settings\",\n  \"version\": \"0.67\",\n  \"manifest_version\": 2,\n  \"description\": \"Customize per-script font settings.\",\n  \"options_page\": \"options.html\",\n  \"icons\": {\n    \"16\": \"fonts16.png\",\n    \"128\": \"fonts128.png\"\n  },\n  \"permissions\": [\"fontSettings\"]\n}\n"
  },
  {
    "path": "_archive/mv2/api/fontSettings/options.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<title>Advanced Font Settings</title>\n<script src=\"js/cr.js\"></script>\n<script src=\"js/cr/ui.js\"></script>\n<script src=\"js/cr/ui/overlay.js\"></script>\n<script src=\"slider.js\"></script>\n<script src=\"pending_changes.js\"></script>\n<script src=\"options.js\"></script>\n<link rel=\"stylesheet\" href=\"css/chrome_shared.css\">\n<link rel=\"stylesheet\" href=\"css/overlay.css\">\n<link rel=\"stylesheet\" href=\"css/widgets.css\">\n<link rel=\"stylesheet\" href=\"css/uber_shared.css\">\n<link rel=\"stylesheet\" href=\"slider.css\">\n<style>\nbody.uber-frame {\n  margin-inline-start: 18px;\n  margin-inline-end: 30px;\n}\n\nbody.uber-frame section {\n  max-width: 650px;\n}\n\nbody.uber-frame section:last-of-type {\n  margin-top: 28px;\n}\n\nbody.uber-frame header {\n  left: 0;\n  padding-inline-start: 18px;\n  right: 0;\n}\n\nbody.uber-frame header > h1 {\n  padding-bottom: 16px;\n}\n\nh1 {\n  font-size: 16px;\n}\n\n.script-header {\n  margin-top: 12px;\n}\n\nh3 {\n  margin-bottom: 11px;\n  font-size: 14px;\n}\n\nsection {\n  font-size: 12px;\n}\n\n.bordered {\n  border: 1px solid #D9D9D9;\n  border-radius: 2px;\n}\n\n.smaller {\n  font-size: smaller;\n}\n\n.font-settings-div {\n  margin-inline-end: 5px;\n  width: 180px;\n}\n\n.font-settings-div:first-of-type {\n  width: 138px;\n}\n\n.font-settings-div > :first-child {\n  margin-bottom: 10px;\n}\n\n.font-settings-div > * {\n  margin-bottom: 14px;\n}\n\n.font-settings-row {\n  display: -webkit-flex;\n  width: 800px;\n}\n\n.sample-text-div {\n  display: -webkit-flex;\n  white-space: nowrap;\n  width: 100%;\n  overflow: hidden;\n}\n\n.sample-text-span {\n  margin-top: auto;\n  margin-bottom: auto;\n  margin-left: 20px;\n}\n\n#overlay-container {\n  z-index: 100;\n}\n\n#standardFontSample {\n  font-family: standard;\n}\n\n#serifFontSample {\n  font-family: serif;\n}\n\n#sansSerifFontSample {\n  font-family: sans-serif;\n}\n\n#fixedFontSample {\n  font-family: monospace;\n}\n\n#minFontSample {\n  font-family: standard;\n}\n\nselect {\n  width: 100%;\n}\n\n#footer > button {\n  padding-inline-start: 9px;\n  padding-inline-end: 9px;\n}\n\n#footer > #apply-settings {\n  padding-inline-start: 17px;\n  padding-inline-end: 17px;\n}\n\n#apply-settings:enabled {\n  background-color: #4f7dd6;\n  background-image: none;\n  border-color: #2a4aac;\n  box-shadow: none;\n  color: #fbfafb;\n  text-shadow: none;\n}\n\n.slider-legend {\n  position: relative;\n  /* This offset is needed to get the legend to align with the slider. */\n  top: -7px;\n}\n\n.slider-container {\n  display: inline-block;\n  position: relative;\n  top: 1px;\n  height: 24px;\n  width: 88px;\n}\n</style>\n</head>\n<body class=\"uber-frame\">\n<div id=\"overlay-container\" class=\"overlay\" hidden>\n  <div id=\"reset-overlay\" class=\"page\">\n    <div class=\"close-button\"></div>\n    <div id=\"reset-this-script-overlay-dialog\" hidden>\n      <h1>Reset</h1>\n      <div id=\"reset-this-script-overlay-dialog-content\" class=\"content-area\">\n      </div>\n      <div class=\"action-area\">\n        <div class=\"button-strip\">\n          <button id=\"reset-this-script-cancel\">Cancel</button>\n          <button id=\"reset-this-script-ok\">Reset</button>\n        </div>\n      </div>\n    </div>\n    <div id=\"reset-all-scripts-overlay-dialog\" hidden>\n      <h1>Reset</h1>\n      <div class=\"content-area\">\n        Are you sure you want to reset all settings?\n      </div>\n      <div class=\"action-area\">\n        <div class=\"button-strip\">\n          <button id=\"reset-all-cancel\">Cancel</button>\n          <button id=\"reset-all-ok\">Reset</button>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n<div class=\"page\">\n  <header style=\"transform: translateX(0px);\">\n    <h1>Advanced Font Settings</h1>\n  </header>\n  <section>\n    <h3 class=\"script-header\">Script</h3>\n    <div class=\"font-settings-row\">\n      <select style=\"width: 200px\" id=\"scriptList\"></select>\n    </div>\n  </section>\n  <section>\n    <h3>Proportional fonts</h3>\n    <div class=\"font-settings-row\">\n      <div class=\"font-settings-div\">\n        <div id=\"defaultFontSizeLabel\"></div>\n        <div style=\"width: 100%; margin-bottom: 0\">\n          <span class=\"slider-legend smaller\">Aa</span>\n          <div id=\"defaultFontSizeSliderContainer\" class=\"slider-container\"></div>\n          <span class=\"slider-legend\">Aa</span>\n        </div>\n      </div>\n      <div class=\"font-settings-div\">\n        <div>Standard</div>\n        <div><select id=\"standardFontList\"></select></div>\n      </div>\n      <div class=\"font-settings-div\">\n        <div>Serif</div>\n        <div><select id=\"serifFontList\"></select></div>\n      </div>\n      <div class=\"font-settings-div\">\n        <div>Sans-Serif</div>\n        <div><select id=\"sansSerifFontList\"></select></div>\n      </div>\n    </div>\n    <div class=\"bordered\" style=\"position: relative; left: 0; right: 0; height: 160px; width: 702px;\">\n      <div class=\"sample-text-div\" style=\"height: 33%\">\n        <span id='standardFontSample' class=\"sample-text-span\">\n          The quick brown fox jumps over the lazy dog.\n        </span>\n      </div>\n      <div class=\"sample-text-div\" style=\"height: 33%\">\n        <span id=\"serifFontSample\" class=\"sample-text-span\">\n          The quick brown fox jumps over the lazy dog.\n        </span>\n      </div>\n      <div class=\"sample-text-div\" style=\"height: 33%\">\n        <span id=\"sansSerifFontSample\" class=\"sample-text-span\">\n          The quick brown fox jumps over the lazy dog.\n        </span>\n      </div>\n    </div>\n  </section>\n  <section>\n    <h3>Fixed-width fonts</h3>\n    <div class=\"font-settings-row\">\n      <div class=\"font-settings-div\">\n        <div id=\"fixedFontSizeLabel\"></div>\n        <div style=\"width: 100%; margin-bottom: 0\">\n          <span class=\"slider-legend smaller\">Aa</span>\n          <div id=\"defaultFixedFontSizeSliderContainer\" class=\"slider-container\"></div>\n          <span class=\"slider-legend\">Aa</span>\n        </div>\n      </div>\n      <div class=\"font-settings-div\">\n        <div>Fixed</div>\n        <div><select id=\"fixedFontList\"></select></div>\n      </div>\n    </div>\n    <div class=\"bordered\" style=\"position: relative; overflow: hidden; left: 0; right: 0; height: 58px; width: 702px;\">\n      <div class=\"sample-text-div\" style=\"height: 100%\">\n        <span id=\"fixedFontSample\" class=\"sample-text-span\">\n          The quick brown fox jumps over the lazy dog.\n        </span>\n      </div>\n    </div>\n  </section>\n  <section>\n    <h3>Minimum font size</h3>\n    <div class=\"font-settings-row\">\n      <div class=\"font-settings-div\">\n        <div id=\"minFontSizeLabel\" style=\"margin-bottom: 8px\"></div>\n        <div style=\"width: 100%; margin-bottom: 12px\">\n          <span class=\"slider-legend smaller\">Aa</span>\n          <div id=\"minFontSizeSliderContainer\" class=\"slider-container\"></div>\n          <span class=\"slider-legend\">Aa</span>\n        </div>\n      </div>\n    </div>\n    <div class=\"bordered\" style=\"position: relative; overflow: hidden; left: 0; right: 0; height: 58px; width: 702px;\">\n      <div class=\"sample-text-div\" style=\"height: 100%\">\n        <span id=\"minFontSample\" class=\"sample-text-span\">\n          The quick brown fox jumps over the lazy dog.\n        </span>\n      </div>\n    </div>\n  </section>\n  <section id=\"footer\">\n    <button id=\"apply-settings\">\n      Apply settings\n    </button>\n    <button id=\"reset-this-script-button\">\n      Reset settings for this script\n    </button>\n    <button id=\"reset-all-button\">\n      Reset all settings\n    </button>\n  </section>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/fontSettings/options.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\n/**\n * @fileoverview The Advanced Font Settings Extension implementation.\n */\n\nfunction $(id) {\n  return document.getElementById(id);\n}\n\n/**\n * @namespace\n */\nvar advancedFonts = {};\n\n/**\n * The ICU script code for the Common, or global, script, which is used as the\n * fallback when the script is undeclared.\n * @const\n */\nadvancedFonts.COMMON_SCRIPT = 'Zyyy';\n\n/**\n * The scripts supported by the Font Settings Extension API.\n * @const\n */\nadvancedFonts.scripts = [\n  { scriptCode: advancedFonts.COMMON_SCRIPT, scriptName: 'Default'},\n  { scriptCode: 'Afak', scriptName: 'Afaka'},\n  { scriptCode: 'Arab', scriptName: 'Arabic'},\n  { scriptCode: 'Armi', scriptName: 'Imperial Aramaic'},\n  { scriptCode: 'Armn', scriptName: 'Armenian'},\n  { scriptCode: 'Avst', scriptName: 'Avestan'},\n  { scriptCode: 'Bali', scriptName: 'Balinese'},\n  { scriptCode: 'Bamu', scriptName: 'Bamum'},\n  { scriptCode: 'Bass', scriptName: 'Bassa Vah'},\n  { scriptCode: 'Batk', scriptName: 'Batak'},\n  { scriptCode: 'Beng', scriptName: 'Bengali'},\n  { scriptCode: 'Blis', scriptName: 'Blissymbols'},\n  { scriptCode: 'Bopo', scriptName: 'Bopomofo'},\n  { scriptCode: 'Brah', scriptName: 'Brahmi'},\n  { scriptCode: 'Brai', scriptName: 'Braille'},\n  { scriptCode: 'Bugi', scriptName: 'Buginese'},\n  { scriptCode: 'Buhd', scriptName: 'Buhid'},\n  { scriptCode: 'Cakm', scriptName: 'Chakma'},\n  { scriptCode: 'Cans', scriptName: 'Unified Canadian Aboriginal Syllabics'},\n  { scriptCode: 'Cari', scriptName: 'Carian'},\n  { scriptCode: 'Cham', scriptName: 'Cham'},\n  { scriptCode: 'Cher', scriptName: 'Cherokee'},\n  { scriptCode: 'Cirt', scriptName: 'Cirth'},\n  { scriptCode: 'Copt', scriptName: 'Coptic'},\n  { scriptCode: 'Cprt', scriptName: 'Cypriot'},\n  { scriptCode: 'Cyrl', scriptName: 'Cyrillic'},\n  { scriptCode: 'Cyrs', scriptName: 'Old Church Slavonic Cyrillic'},\n  { scriptCode: 'Deva', scriptName: 'Devanagari'},\n  { scriptCode: 'Dsrt', scriptName: 'Deseret'},\n  { scriptCode: 'Dupl', scriptName: 'Duployan shorthand'},\n  { scriptCode: 'Egyd', scriptName: 'Egyptian demotic'},\n  { scriptCode: 'Egyh', scriptName: 'Egyptian hieratic'},\n  { scriptCode: 'Egyp', scriptName: 'Egyptian hieroglyphs'},\n  { scriptCode: 'Elba', scriptName: 'Elbasan'},\n  { scriptCode: 'Ethi', scriptName: 'Ethiopic'},\n  { scriptCode: 'Geok', scriptName: 'Georgian Khutsuri'},\n  { scriptCode: 'Geor', scriptName: 'Georgian'},\n  { scriptCode: 'Glag', scriptName: 'Glagolitic'},\n  { scriptCode: 'Goth', scriptName: 'Gothic'},\n  { scriptCode: 'Gran', scriptName: 'Grantha'},\n  { scriptCode: 'Grek', scriptName: 'Greek'},\n  { scriptCode: 'Gujr', scriptName: 'Gujarati'},\n  { scriptCode: 'Guru', scriptName: 'Gurmukhi'},\n  { scriptCode: 'Hang', scriptName: 'Hangul'},\n  { scriptCode: 'Hani', scriptName: 'Han'},\n  { scriptCode: 'Hano', scriptName: 'Hanunoo'},\n  { scriptCode: 'Hans', scriptName: 'Simplified Han'},\n  { scriptCode: 'Hant', scriptName: 'Traditional Han'},\n  { scriptCode: 'Hebr', scriptName: 'Hebrew'},\n  { scriptCode: 'Hluw', scriptName: 'Anatolian Hieroglyphs'},\n  { scriptCode: 'Hmng', scriptName: 'Pahawh Hmong'},\n  { scriptCode: 'Hung', scriptName: 'Old Hungarian'},\n  { scriptCode: 'Inds', scriptName: 'Indus'},\n  { scriptCode: 'Ital', scriptName: 'Old Italic'},\n  { scriptCode: 'Java', scriptName: 'Javanese'},\n  { scriptCode: 'Jpan', scriptName: 'Japanese'},\n  { scriptCode: 'Jurc', scriptName: 'Jurchen'},\n  { scriptCode: 'Kali', scriptName: 'Kayah Li'},\n  { scriptCode: 'Khar', scriptName: 'Kharoshthi'},\n  { scriptCode: 'Khmr', scriptName: 'Khmer'},\n  { scriptCode: 'Khoj', scriptName: 'Khojki'},\n  { scriptCode: 'Knda', scriptName: 'Kannada'},\n  { scriptCode: 'Kpel', scriptName: 'Kpelle'},\n  { scriptCode: 'Kthi', scriptName: 'Kaithi'},\n  { scriptCode: 'Lana', scriptName: 'Lanna'},\n  { scriptCode: 'Laoo', scriptName: 'Lao'},\n  { scriptCode: 'Latf', scriptName: 'Fraktur Latin'},\n  { scriptCode: 'Latg', scriptName: 'Gaelic Latin'},\n  { scriptCode: 'Latn', scriptName: 'Latin'},\n  { scriptCode: 'Lepc', scriptName: 'Lepcha'},\n  { scriptCode: 'Limb', scriptName: 'Limbu'},\n  { scriptCode: 'Lina', scriptName: 'Linear A'},\n  { scriptCode: 'Linb', scriptName: 'Linear B'},\n  { scriptCode: 'Lisu', scriptName: 'Fraser'},\n  { scriptCode: 'Loma', scriptName: 'Loma'},\n  { scriptCode: 'Lyci', scriptName: 'Lycian'},\n  { scriptCode: 'Lydi', scriptName: 'Lydian'},\n  { scriptCode: 'Mand', scriptName: 'Mandaean'},\n  { scriptCode: 'Mani', scriptName: 'Manichaean'},\n  { scriptCode: 'Maya', scriptName: 'Mayan hieroglyphs'},\n  { scriptCode: 'Mend', scriptName: 'Mende'},\n  { scriptCode: 'Merc', scriptName: 'Meroitic Cursive'},\n  { scriptCode: 'Mero', scriptName: 'Meroitic'},\n  { scriptCode: 'Mlym', scriptName: 'Malayalam'},\n  { scriptCode: 'Mong', scriptName: 'Mongolian'},\n  { scriptCode: 'Moon', scriptName: 'Moon'},\n  { scriptCode: 'Mroo', scriptName: 'Mro'},\n  { scriptCode: 'Mtei', scriptName: 'Meitei Mayek'},\n  { scriptCode: 'Mymr', scriptName: 'Myanmar'},\n  { scriptCode: 'Narb', scriptName: 'Old North Arabian'},\n  { scriptCode: 'Nbat', scriptName: 'Nabataean'},\n  { scriptCode: 'Nkgb', scriptName: 'Naxi Geba'},\n  { scriptCode: 'Nkoo', scriptName: 'N’Ko'},\n  { scriptCode: 'Nshu', scriptName: 'Nüshu'},\n  { scriptCode: 'Ogam', scriptName: 'Ogham'},\n  { scriptCode: 'Olck', scriptName: 'Ol Chiki'},\n  { scriptCode: 'Orkh', scriptName: 'Orkhon'},\n  { scriptCode: 'Orya', scriptName: 'Oriya'},\n  { scriptCode: 'Osma', scriptName: 'Osmanya'},\n  { scriptCode: 'Palm', scriptName: 'Palmyrene'},\n  { scriptCode: 'Perm', scriptName: 'Old Permic'},\n  { scriptCode: 'Phag', scriptName: 'Phags-pa'},\n  { scriptCode: 'Phli', scriptName: 'Inscriptional Pahlavi'},\n  { scriptCode: 'Phlp', scriptName: 'Psalter Pahlavi'},\n  { scriptCode: 'Phlv', scriptName: 'Book Pahlavi'},\n  { scriptCode: 'Phnx', scriptName: 'Phoenician'},\n  { scriptCode: 'Plrd', scriptName: 'Pollard Phonetic'},\n  { scriptCode: 'Prti', scriptName: 'Inscriptional Parthian'},\n  { scriptCode: 'Rjng', scriptName: 'Rejang'},\n  { scriptCode: 'Roro', scriptName: 'Rongorongo'},\n  { scriptCode: 'Runr', scriptName: 'Runic'},\n  { scriptCode: 'Samr', scriptName: 'Samaritan'},\n  { scriptCode: 'Sara', scriptName: 'Sarati'},\n  { scriptCode: 'Sarb', scriptName: 'Old South Arabian'},\n  { scriptCode: 'Saur', scriptName: 'Saurashtra'},\n  { scriptCode: 'Sgnw', scriptName: 'SignWriting'},\n  { scriptCode: 'Shaw', scriptName: 'Shavian'},\n  { scriptCode: 'Shrd', scriptName: 'Sharada'},\n  { scriptCode: 'Sind', scriptName: 'Khudawadi'},\n  { scriptCode: 'Sinh', scriptName: 'Sinhala'},\n  { scriptCode: 'Sora', scriptName: 'Sora Sompeng'},\n  { scriptCode: 'Sund', scriptName: 'Sundanese'},\n  { scriptCode: 'Sylo', scriptName: 'Syloti Nagri'},\n  { scriptCode: 'Syrc', scriptName: 'Syriac'},\n  { scriptCode: 'Syre', scriptName: 'Estrangelo Syriac'},\n  { scriptCode: 'Syrj', scriptName: 'Western Syriac'},\n  { scriptCode: 'Syrn', scriptName: 'Eastern Syriac'},\n  { scriptCode: 'Tagb', scriptName: 'Tagbanwa'},\n  { scriptCode: 'Takr', scriptName: 'Takri'},\n  { scriptCode: 'Tale', scriptName: 'Tai Le'},\n  { scriptCode: 'Talu', scriptName: 'New Tai Lue'},\n  { scriptCode: 'Taml', scriptName: 'Tamil'},\n  { scriptCode: 'Tang', scriptName: 'Tangut'},\n  { scriptCode: 'Tavt', scriptName: 'Tai Viet'},\n  { scriptCode: 'Telu', scriptName: 'Telugu'},\n  { scriptCode: 'Teng', scriptName: 'Tengwar'},\n  { scriptCode: 'Tfng', scriptName: 'Tifinagh'},\n  { scriptCode: 'Tglg', scriptName: 'Tagalog'},\n  { scriptCode: 'Thaa', scriptName: 'Thaana'},\n  { scriptCode: 'Thai', scriptName: 'Thai'},\n  { scriptCode: 'Tibt', scriptName: 'Tibetan'},\n  { scriptCode: 'Tirh', scriptName: 'Tirhuta'},\n  { scriptCode: 'Ugar', scriptName: 'Ugaritic'},\n  { scriptCode: 'Vaii', scriptName: 'Vai'},\n  { scriptCode: 'Visp', scriptName: 'Visible Speech'},\n  { scriptCode: 'Wara', scriptName: 'Varang Kshiti'},\n  { scriptCode: 'Wole', scriptName: 'Woleai'},\n  { scriptCode: 'Xpeo', scriptName: 'Old Persian'},\n  { scriptCode: 'Xsux', scriptName: 'Sumero-Akkadian Cuneiform'},\n  { scriptCode: 'Yiii', scriptName: 'Yi'},\n  { scriptCode: 'Zmth', scriptName: 'Mathematical Notation'},\n  { scriptCode: 'Zsym', scriptName: 'Symbols'}\n];\n\n/**\n * The generic font families supported by the Font Settings Extension API.\n * @const\n */\nadvancedFonts.FAMILIES =\n    ['standard', 'sansserif', 'serif', 'fixed', 'cursive', 'fantasy'];\n\n/**\n * Sample texts.\n * @const\n */\nadvancedFonts.SAMPLE_TEXTS = {\n  // \"Cyrllic script\".\n  Cyrl: 'Кириллица',\n  Hang: '정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날.',\n  Hans: '床前明月光，疑是地上霜。举头望明月，低头思故乡。',\n  Hant: '床前明月光，疑是地上霜。舉頭望明月，低頭思故鄉。',\n  Jpan: '吾輩は猫である。名前はまだ無い。',\n  // \"Khmer language\".\n  Khmr: '\\u1797\\u17B6\\u179F\\u17B6\\u1781\\u17D2\\u1798\\u17C2\\u179A',\n  Zyyy: 'The quick brown fox jumps over the lazy dog.'\n};\n\n/**\n * Controller of pending changes.\n * @const\n */\nadvancedFonts.pendingChanges = new PendingChanges();\n\n/**\n * Map from |genericFamily| to UI controls and data for its font setting.\n */\nadvancedFonts.fontSettings = null;\n\n/**\n * Map from |fontSizeKey| to UI controls and data for its font size setting.\n */\nadvancedFonts.fontSizeSettings = null;\n\n/**\n * Gets the font size used for |fontSizeKey|, including pending changes. Calls\n * |callback| with the result.\n *\n * @param {string} fontSizeKey The font size setting key. See\n *     PendingChanges.getFontSize().\n * @param {function(number, boolean)} callback The callback of form\n *     function(size, controllable). |size| is the effective setting,\n *     |controllable| is whether the setting can be set.\n */\nadvancedFonts.getEffectiveFontSize = function(fontSizeKey, callback) {\n  advancedFonts.fontSizeSettings[fontSizeKey].getter({}, function(details) {\n    var controllable = advancedFonts.isControllableLevel(\n        details.levelOfControl);\n    var size = details.pixelSize;\n    var pendingFontSize = advancedFonts.pendingChanges.getFontSize(fontSizeKey);\n    // If the setting is not controllable, we can have no pending change.\n    if (!controllable) {\n      if (pendingFontSize != null) {\n        advancedFonts.pendingChanges.setFontSize(fontSizeKey, null);\n        $('apply-settings').disabled = advancedFonts.pendingChanges.isEmpty();\n        pendingFontSize = null;\n      }\n    }\n\n    // If we have a pending change, it overrides the current setting.\n    if (pendingFontSize != null)\n      size = pendingFontSize;\n    callback(size, controllable);\n  });\n};\n\n/**\n * Gets the font used for |script| and |genericFamily|, including pending\n * changes. Calls |callback| with the result.\n *\n * @param {string} script The script code.\n * @param {string} genericFamily The generic family.\n * @param {function(string, boolean, string)} callback The callback of form\n *     function(font, controllable, effectiveFont). |font| is the setting\n *     (pending or not), |controllable| is whether the setting can be set,\n *     |effectiveFont| is the font used taking fallback into consideration.\n */\nadvancedFonts.getEffectiveFont = function(script, genericFamily, callback) {\n  var pendingChanges = advancedFonts.pendingChanges;\n  var details = { script: script, genericFamily: genericFamily };\n  chrome.fontSettings.getFont(details, function(result) {\n    var setting = {};\n    setting.font = result.fontId;\n    setting.controllable =\n        advancedFonts.isControllableLevel(result.levelOfControl);\n    var pendingFont =\n        pendingChanges.getFont(details.script, details.genericFamily);\n    // If the setting is not controllable, we can have no pending change.\n    if (!setting.controllable) {\n      if (pendingFont != null) {\n        pendingChanges.setFont(script, genericFamily, null);\n        $('apply-settings').disabled = advancedFonts.pendingChanges.isEmpty();\n        pendingFont = null;\n      }\n    }\n\n    // If we have a pending change, it overrides the current setting.\n    if (pendingFont != null)\n      setting.font = pendingFont;\n\n    // If we have a font, we're done.\n    if (setting.font) {\n      callback(setting.font, setting.controllable, setting.font);\n      return;\n    }\n\n    // If we're still here, we have to fallback to common script, unless this\n    // already is common script.\n    if (script == advancedFonts.COMMON_SCRIPT) {\n      callback('', setting.controllable, '');\n      return;\n    }\n    advancedFonts.getEffectiveFont(\n        advancedFonts.COMMON_SCRIPT,\n        genericFamily,\n        callback.bind(null, setting.font, setting.controllable));\n  });\n};\n\n/**\n * Refreshes the UI controls related to a font setting.\n *\n * @param {{fontList: HTMLSelectElement, samples: Array<HTMLElement>}}\n *     fontSetting The setting object (see advancedFonts.fontSettings).\n * @param {string} font The value of the font setting.\n * @param {boolean} controllable Whether the font setting can be controlled\n *     by this extension.\n * @param {string} effectiveFont The font used, including fallback to Common\n *     script.\n */\nadvancedFonts.refreshFont = function(\n    fontSetting, font, controllable, effectiveFont) {\n  for (var i = 0; i < fontSetting.samples.length; ++i)\n    fontSetting.samples[i].style.fontFamily = effectiveFont;\n  advancedFonts.setSelectedFont(fontSetting.fontList, font);\n  fontSetting.fontList.disabled = !controllable;\n};\n\n/**\n * Refreshes the UI controls related to a font size setting.\n *\n * @param {{label: HTMLElement, slider: Slider, samples: Array<HTMLElement>}}\n *     fontSizeSetting The setting object (see advancedFonts.fontSizeSettings).\n * @param size The value of the font size setting.\n * @param controllable Whether the setting can be controlled by this extension.\n */\nadvancedFonts.refreshFontSize = function(fontSizeSetting, size, controllable) {\n  fontSizeSetting.label.textContent = 'Size: ' + size + 'px';\n  advancedFonts.setFontSizeSlider(fontSizeSetting.slider, size, controllable);\n  for (var i = 0; i < fontSizeSetting.samples.length; ++i)\n    fontSizeSetting.samples[i].style.fontSize = size + 'px';\n};\n\n/**\n * Refreshes all UI controls to reflect the current settings, including pending\n * changes.\n */\nadvancedFonts.refresh = function() {\n  var script = advancedFonts.getSelectedScript();\n  var sample;\n  if (advancedFonts.SAMPLE_TEXTS[script])\n    sample = advancedFonts.SAMPLE_TEXTS[script];\n  else\n    sample = advancedFonts.SAMPLE_TEXTS[advancedFonts.COMMON_SCRIPT];\n  var sampleTexts = document.querySelectorAll('.sample-text-span');\n  for (var i = 0; i < sampleTexts.length; i++)\n    sampleTexts[i].textContent = sample;\n\n  var setting;\n  var callback;\n  for (var genericFamily in advancedFonts.fontSettings) {\n    setting = advancedFonts.fontSettings[genericFamily];\n    callback = advancedFonts.refreshFont.bind(null, setting);\n    advancedFonts.getEffectiveFont(script, genericFamily, callback);\n  }\n\n  for (var fontSizeKey in advancedFonts.fontSizeSettings) {\n    setting = advancedFonts.fontSizeSettings[fontSizeKey];\n    callback = advancedFonts.refreshFontSize.bind(null, setting);\n    advancedFonts.getEffectiveFontSize(fontSizeKey, callback);\n  }\n\n  $('apply-settings').disabled = advancedFonts.pendingChanges.isEmpty();\n};\n\n/**\n * @return {string} The currently selected script code.\n */\nadvancedFonts.getSelectedScript = function() {\n  var scriptList = $('scriptList');\n  return scriptList.options[scriptList.selectedIndex].value;\n};\n\n/**\n * @param {HTMLSelectElement} fontList The <select> containing a list of fonts.\n * @return {string} The currently selected value of |fontList|.\n */\nadvancedFonts.getSelectedFont = function(fontList) {\n  return fontList.options[fontList.selectedIndex].value;\n};\n\n/**\n * Populates the font lists.\n * @param {Array<{fontId: string, displayName: string>} fonts The list of\n *     fonts on the system.\n */\nadvancedFonts.populateFontLists = function(fonts) {\n  for (var genericFamily in advancedFonts.fontSettings) {\n    var list = advancedFonts.fontSettings[genericFamily].fontList;\n\n    // Add a special item to indicate fallback to the non-per-script\n    // font setting. The Font Settings API uses the empty string to indicate\n    // fallback.\n    var defaultItem = document.createElement('option');\n    defaultItem.value = '';\n    defaultItem.text = '(Use default)';\n    list.add(defaultItem);\n\n    for (var i = 0; i < fonts.length; ++i) {\n      var item = document.createElement('option');\n      item.value = fonts[i].fontId;\n      item.text = fonts[i].displayName;\n      list.add(item);\n    }\n  }\n  advancedFonts.refresh();\n};\n\n/**\n * Handles change events on a <select> element for a font setting.\n * @param {string} genericFamily The generic family for the font setting.\n * @param {Event} event The change event.\n */\nadvancedFonts.handleFontListChange = function(genericFamily, event) {\n  var script = advancedFonts.getSelectedScript();\n  var font = advancedFonts.getSelectedFont(event.target);\n\n  advancedFonts.pendingChanges.setFont(script, genericFamily, font);\n  advancedFonts.refresh();\n};\n\n/**\n * Sets the selected value of |fontList| to |fontId|.\n * @param {HTMLSelectElement} fontList The <select> containing a list of fonts.\n * @param {string} fontId The font to set |fontList|'s selection to.\n */\nadvancedFonts.setSelectedFont = function(fontList, fontId) {\n  var script = advancedFonts.getSelectedScript();\n  var i;\n  for (i = 0; i < fontList.length; i++) {\n    if (fontId == fontList.options[i].value) {\n      fontList.selectedIndex = i;\n      break;\n    }\n  }\n  if (i == fontList.length) {\n    console.warn(\"font '\" + fontId + \"' for \" + fontList.id + ' for ' +\n        script + ' is not on the system');\n  }\n};\n\n/**\n * Handles change events on a font size slider.\n * @param {string} fontSizeKey The key for the font size setting whose slider\n *     changed. See PendingChanges.getFont.\n * @param {string} value The new value of the slider.\n */\nadvancedFonts.handleFontSizeSliderChange = function(fontSizeKey, value) {\n  var pixelSize = parseInt(value);\n  if (!isNaN(pixelSize)) {\n    advancedFonts.pendingChanges.setFontSize(fontSizeKey, pixelSize);\n    advancedFonts.refresh();\n  }\n};\n\n/**\n * @param {string} levelOfControl The level of control string for a setting,\n *     as returned by the Font Settings Extension API.\n * @return {boolean} True if |levelOfControl| signifies that the extension can\n *     control the setting; otherwise, returns false.\n */\nadvancedFonts.isControllableLevel = function(levelOfControl) {\n  return levelOfControl == 'controllable_by_this_extension' ||\n      levelOfControl == 'controlled_by_this_extension';\n};\n\n/*\n * Updates the specified font size slider's value and enabled property.\n * @param {Slider} slider The slider for a font size setting.\n * @param {number} size The value to set the slider to.\n * @param {boolean} enabled Whether to enable or disable the slider.\n */\nadvancedFonts.setFontSizeSlider = function(slider, size, enabled) {\n  if (slider.getValue() != size)\n    slider.setValue(size);\n  var inputElement = slider.getInput();\n  if (enabled) {\n    inputElement.parentNode.classList.remove('disabled');\n    inputElement.disabled = false;\n  } else {\n    inputElement.parentNode.classList.add('disabled');\n    inputElement.disabled = true;\n  }\n};\n\n/**\n * Initializes the UI control elements related to the font size setting\n * |fontSizeKey| and registers listeners for the user adjusting its slider and\n * the setting changing on the browser-side.\n * @param {string} fontSizeKey The key for font size setting. See\n *     PendingChanges.getFont().\n */\nadvancedFonts.initFontSizeSetting = function(fontSizeKey) {\n  var fontSizeSettings = advancedFonts.fontSizeSettings;\n  var setting = fontSizeSettings[fontSizeKey];\n  var label = setting.label;\n  var samples = setting.samples;\n\n  setting.slider = new Slider(\n      setting.sliderContainer,\n      0,\n      setting.minValue,\n      setting.maxValue,\n      advancedFonts.handleFontSizeSliderChange.bind(null, fontSizeKey)\n  );\n\n  var slider = setting.slider;\n  setting.getter({}, function(details) {\n    var size = details.pixelSize.toString();\n    var controllable = advancedFonts.isControllableLevel(\n        details.levelOfControl);\n    advancedFonts.setFontSizeSlider(slider, size, controllable);\n    for (var i = 0; i < samples.length; i++)\n      samples[i].style.fontSize = size + 'px';\n  });\n  fontSizeSettings[fontSizeKey].onChanged.addListener(advancedFonts.refresh);\n};\n\n/**\n * Clears the font settings for the specified script.\n * @param {string} script The script code.\n */\nadvancedFonts.clearSettingsForScript = function(script) {\n  advancedFonts.pendingChanges.clearOneScript(script);\n  for (var i = 0; i < advancedFonts.FAMILIES.length; i++) {\n    chrome.fontSettings.clearFont({\n      script: script,\n      genericFamily: advancedFonts.FAMILIES[i]\n    });\n  }\n};\n\n/**\n * Clears all font and font size settings.\n */\nadvancedFonts.clearAllSettings = function() {\n  advancedFonts.pendingChanges.clear();\n  for (var i = 0; i < advancedFonts.scripts.length; i++)\n    advancedFonts.clearSettingsForScript(advancedFonts.scripts[i].scriptCode);\n  chrome.fontSettings.clearDefaultFixedFontSize();\n  chrome.fontSettings.clearDefaultFontSize();\n  chrome.fontSettings.clearMinimumFontSize();\n};\n\n/**\n * Closes the overlay.\n */\nadvancedFonts.closeOverlay = function() {\n  $('overlay-container').hidden = true;\n};\n\n/**\n * Initializes apply and reset buttons.\n */\nadvancedFonts.initApplyAndResetButtons = function() {\n  var applyButton = $('apply-settings');\n  applyButton.addEventListener('click', function() {\n    advancedFonts.pendingChanges.apply();\n    advancedFonts.refresh();\n  });\n\n  var overlay = $('overlay-container');\n  cr.ui.overlay.globalInitialization();\n  cr.ui.overlay.setupOverlay(overlay);\n  overlay.addEventListener('cancelOverlay', advancedFonts.closeOverlay);\n\n  $('reset-this-script-button').onclick = function(event) {\n    var scriptList = $('scriptList');\n    var scriptName = scriptList.options[scriptList.selectedIndex].text;\n    $('reset-this-script-overlay-dialog-content').innerText =\n        'Are you sure you want to reset settings for ' + scriptName +\n        ' script?';\n\n    $('overlay-container').hidden = false;\n    $('reset-this-script-overlay-dialog').hidden = false;\n    $('reset-all-scripts-overlay-dialog').hidden = true;\n  };\n  $('reset-this-script-ok').onclick = function(event) {\n    advancedFonts.clearSettingsForScript(advancedFonts.getSelectedScript());\n    advancedFonts.closeOverlay();\n    advancedFonts.refresh();\n  };\n  $('reset-this-script-cancel').onclick = advancedFonts.closeOverlay;\n\n  $('reset-all-button').onclick = function(event) {\n    $('overlay-container').hidden = false;\n    $('reset-all-scripts-overlay-dialog').hidden = false;\n    $('reset-this-script-overlay-dialog').hidden = true;\n  };\n  $('reset-all-ok').onclick = function(event) {\n    advancedFonts.clearAllSettings();\n    advancedFonts.closeOverlay();\n    advancedFonts.refresh();\n  };\n  $('reset-all-cancel').onclick = advancedFonts.closeOverlay;\n};\n\n/**\n * Best guess for system fonts, taken from the IDS_WEB_FONT_FAMILY strings in\n * Chrome.\n * TODO: The font should be localized like Chrome does.\n * @const\n */\nadvancedFonts.systemFonts = {\n  cros: 'Noto Sans UI, sans-serif',\n  linux: 'Ubuntu, sans-serif',\n  mac: 'Lucida Grande, sans-serif',\n  win: 'Segoe UI, Tahoma, sans-serif',\n  unknown: 'sans-serif'\n};\n\n/**\n * @return {string} The platform this extension is running on.\n */\nadvancedFonts.getPlatform = function() {\n  var ua = window.navigator.appVersion;\n  if (ua.indexOf('Win') != -1) return 'win';\n  if (ua.indexOf('Mac') != -1) return 'mac';\n  if (ua.indexOf('Linux') != -1) return 'linux';\n  if (ua.indexOf('CrOS') != -1) return 'cros';\n  return 'unknown';\n};\n\n/**\n * Chrome settings tries to use the system font. So does this extension.\n */\nadvancedFonts.useSystemFont = function() {\n  document.body.style.fontFamily =\n      advancedFonts.systemFonts[advancedFonts.getPlatform()];\n};\n\n/**\n * Sorts the list of script codes by scriptName. Someday this extension will\n * have localized script names, so the order will depend on locale.\n */\nadvancedFonts.sortScripts = function() {\n  var i;\n  var scripts = advancedFonts.scripts;\n  for (i = 0; i < scripts; ++i) {\n    if (scripts[i].scriptCode == advancedFonts.COMMON_SCRIPT)\n      break;\n  }\n  var defaultScript = scripts.splice(i, 1)[0];\n\n  scripts.sort(function(a, b) {\n    if (a.scriptName > b.scriptName)\n      return 1;\n    if (a.scriptName < b.scriptName)\n      return -1;\n    return 0;\n  });\n\n  scripts.unshift(defaultScript);\n};\n\n/**\n * Initializes UI controls for font settings.\n */\nadvancedFonts.initFontControls = function() {\n  advancedFonts.fontSettings = {\n    standard: {\n      fontList: $('standardFontList'),\n      samples: [$('standardFontSample'), $('minFontSample')]\n    },\n    serif: {\n      fontList: $('serifFontList'),\n      samples: [$('serifFontSample')]\n    },\n    sansserif: {\n      fontList: $('sansSerifFontList'),\n      samples: [$('sansSerifFontSample')]\n    },\n    fixed: {\n      fontList: $('fixedFontList'),\n      samples: [$('fixedFontSample')]\n    }\n  };\n\n  for (var genericFamily in advancedFonts.fontSettings) {\n    var list = advancedFonts.fontSettings[genericFamily].fontList;\n    list.addEventListener(\n        'change', advancedFonts.handleFontListChange.bind(list, genericFamily));\n  }\n  chrome.fontSettings.onFontChanged.addListener(advancedFonts.refresh);\n  chrome.fontSettings.getFontList(advancedFonts.populateFontLists);\n};\n\n/**\n * Initializes UI controls for font size settings.\n */\nadvancedFonts.initFontSizeControls = function() {\n  advancedFonts.fontSizeSettings = {\n    defaultFontSize: {\n      sliderContainer: $('defaultFontSizeSliderContainer'),\n      minValue: 6,\n      maxValue: 50,\n      samples: [\n        $('standardFontSample'), $('serifFontSample'), $('sansSerifFontSample')\n      ],\n      label: $('defaultFontSizeLabel'),\n      getter: chrome.fontSettings.getDefaultFontSize,\n      onChanged: chrome.fontSettings.onDefaultFontSizeChanged\n    },\n    defaultFixedFontSize: {\n      sliderContainer: $('defaultFixedFontSizeSliderContainer'),\n      minValue: 6,\n      maxValue: 50,\n      samples: [$('fixedFontSample')],\n      label: $('fixedFontSizeLabel'),\n      getter: chrome.fontSettings.getDefaultFixedFontSize,\n      onChanged: chrome.fontSettings.onDefaultFixedFontSizeChanged\n    },\n    minFontSize: {\n      sliderContainer: $('minFontSizeSliderContainer'),\n      minValue: 6,\n      maxValue: 24,\n      samples: [$('minFontSample')],\n      label: $('minFontSizeLabel'),\n      getter: chrome.fontSettings.getMinimumFontSize,\n      onChanged: chrome.fontSettings.onMinimumFontSizeChanged\n    }\n  };\n\n  for (var fontSizeKey in advancedFonts.fontSizeSettings)\n    advancedFonts.initFontSizeSetting(fontSizeKey);\n};\n\n/**\n * Initializes the list of scripts.\n */\nadvancedFonts.initScriptList = function() {\n  var scriptList = $('scriptList');\n  advancedFonts.sortScripts();\n  var scripts = advancedFonts.scripts;\n  for (var i = 0; i < scripts.length; i++) {\n    var script = document.createElement('option');\n    script.value = scripts[i].scriptCode;\n    script.text = scripts[i].scriptName;\n    scriptList.add(script);\n  }\n  scriptList.selectedIndex = 0;\n  scriptList.addEventListener('change', advancedFonts.refresh);\n};\n\n/**\n * Initializes the extension.\n */\nadvancedFonts.init = function() {\n  advancedFonts.useSystemFont();\n\n  advancedFonts.initFontControls();\n  advancedFonts.initFontSizeControls();\n  advancedFonts.initScriptList();\n\n  advancedFonts.initApplyAndResetButtons();\n};\n\ndocument.addEventListener('DOMContentLoaded', advancedFonts.init);\n"
  },
  {
    "path": "_archive/mv2/api/fontSettings/pending_changes.js",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\n/**\n * @fileoverview PendingChanges class tracks changes to be applied when an\n * \"Apply Changes\" button is clicked.\n */\n\n/**\n * Creates a PendingChanges object with no pending changes.\n *\n * @constructor\n */\nvar PendingChanges = function() {\n  // Format: pendingFontChanges_.Cyrl.sansserif = \"My SansSerif Cyrillic Font\"\n  this.pendingFontChanges_ = {};\n\n  // Format: pendingFontSizeChanges_.defaultFontSize = 12\n  this.pendingFontSizeChanges_ = {};\n};\n\n/**\n * Returns the pending font setting change for the specified script and family,\n * or null if it doesn't exist.\n *\n * @param {string} script The script code, like \"Cyrl\".\n * @param {string} genericFamily The generic family, like \"sansserif\".\n * @return {?string} The pending font setting, like \"My Cyrillic SansSerif Font\"\n *     or null if it doesn't exist.\n */\nPendingChanges.prototype.getFont = function(script, genericFamily) {\n  if (this.pendingFontChanges_[script])\n    return this.pendingFontChanges_[script][genericFamily];\n  return null;\n};\n\n/**\n * Returns the pending font size setting change, or null if it doesn't exist.\n *\n * @param {string} fontSizeKey The font size setting key. One of\n *     'defaultFontSize', 'defaultFixedFontSize', or 'minFontSize'.\n * @return {?number} The pending font size setting in pixels, or null if it\n *     doesn't exist.\n */\nPendingChanges.prototype.getFontSize = function(fontSizeKey) {\n  return this.pendingFontSizeChanges_[fontSizeKey];\n};\n\n/**\n * Sets the pending font change for the specified script and family.\n *\n * @param {string} script The script code, like \"Cyrl\".\n * @param {string} genericFamily The generic family, like \"sansserif\".\n * @param {?string} font The font to set the setting to, or null to clear it.\n */\nPendingChanges.prototype.setFont = function(script, genericFamily, font) {\n  if (!this.pendingFontChanges_[script])\n    this.pendingFontChanges_[script] = {};\n  if (this.pendingFontChanges_[script][genericFamily] == font)\n    return;\n  this.pendingFontChanges_[script][genericFamily] = font;\n};\n\n/**\n * Sets the pending font size change.\n *\n * @param {string} fontSizeKey The font size setting key. See\n *     getFontSize().\n * @param {number} size The font size to set the setting to.\n */\nPendingChanges.prototype.setFontSize = function(fontSizeKey, size) {\n  if (this.pendingFontSizeChanges_[fontSizeKey] == size)\n    return;\n  this.pendingFontSizeChanges_[fontSizeKey] = size;\n};\n\n/**\n * Commits the pending changes to Chrome. After this function is called, there\n * are no pending changes.\n */\nPendingChanges.prototype.apply = function() {\n  for (var script in this.pendingFontChanges_) {\n    for (var genericFamily in this.pendingFontChanges_[script]) {\n      var fontId = this.pendingFontChanges_[script][genericFamily];\n      if (fontId == null)\n        continue;\n      var details = {};\n      details.script = script;\n      details.genericFamily = genericFamily;\n      details.fontId = fontId;\n      chrome.fontSettings.setFont(details);\n    }\n  }\n\n  var size = this.pendingFontSizeChanges_['defaultFontSize'];\n  if (size != null)\n    chrome.fontSettings.setDefaultFontSize({pixelSize: size});\n\n  size = this.pendingFontSizeChanges_['defaultFixedFontSize'];\n  if (size != null)\n    chrome.fontSettings.setDefaultFixedFontSize({pixelSize: size});\n\n  size = this.pendingFontSizeChanges_['minFontSize'];\n  if (size != null)\n    chrome.fontSettings.setMinimumFontSize({pixelSize: size});\n\n  this.clear();\n};\n\n/**\n * Clears the pending font changes for a single script.\n *\n * @param {string} script The script code, like \"Cyrl\".\n */\nPendingChanges.prototype.clearOneScript = function(script) {\n  this.pendingFontChanges_[script] = {};\n};\n\n/**\n * Clears all pending font changes.\n */\nPendingChanges.prototype.clear = function() {\n  this.pendingFontChanges_ = {};\n  this.pendingFontSizeChanges_ = {};\n};\n\n/**\n * @return {boolean} True if there are no pending changes, otherwise false.\n */\nPendingChanges.prototype.isEmpty = function() {\n  for (var script in this.pendingFontChanges_) {\n    for (var genericFamily in this.pendingFontChanges_[script]) {\n      if (this.pendingFontChanges_[script][genericFamily] != null)\n        return false;\n    }\n  }\n  for (var name in this.pendingFontSizeChanges_) {\n    if (this.pendingFontSizeChanges_[name] != null)\n      return false;\n  }\n  return true;\n};\n"
  },
  {
    "path": "_archive/mv2/api/fontSettings/slider.css",
    "content": "/* Copyright 2013 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n/* Customize the standard input[type='range']. */\n.slider > input[type='range'] {\n  -webkit-appearance: none !important;  /* Hide the default thumb icon. */\n  background: transparent;  /* Hide the standard slider bar */\n  height: 100%;\n  left: -2px;  /* Required to align the input element with the parent. */\n  position: absolute;\n  top: -2px;\n  width: 100%;\n}\n\n/* Custom thumb icon. */\n.slider > input[type='range']::-webkit-slider-thumb {\n  -webkit-appearance: none;\n  background-position: center center;\n  background-repeat: no-repeat;\n  height: 24px;\n  position: relative;\n  z-index: 2;\n}\n\n/* Custom slider bar (we hide the standard one). */\n.slider > .bar {\n  /* In order to match the horizontal position of the standard slider bar\n     left and right must be equal to 1/2 of the thumb icon width. */\n  left: 8px;\n  right: 8px;\n  bottom: 10px;\n  pointer-events: none;  /* Mouse events pass through to the standard input. */\n  position: absolute;\n  top: 10px;\n  background-image: url(../images/slider/slide_bar_center.png);\n  height: 4px;\n}\n\n.slider > .bar > .filled,\n.slider > .bar > .cap {\n  position: absolute;\n}\n\n/* The filled portion of the slider bar to the left of the thumb. */\n.slider > .bar > .filled {\n  border-left-style: none;\n  border-right-style: none;\n  left: 0;\n  width: 0; /* The element style.width is manipulated from the code. */\n}\n\n.slider > .bar > .cap.right {\n  background-image: url(../images/slider/slider_bar_right.png);\n  height: 4px;\n  width: 4px;\n  left: 100%;\n}\n\n.slider > .bar > .filled {\n  background-image: url(../images/slider/slide_bar_fill_center.png);\n  height: 4px;\n}\n\n.slider > .bar > .cap.left {\n  background-image: url(../images/slider/slide_bar_fill_left.png);\n  height: 4px;\n  width: 4px;\n  right: 100%;\n}\n\n.slider.disabled  > .bar {\n  background-image: url(../images/slider/slide_bar_disabled_center.png);\n}\n\n.slider.disabled  > .bar > .filled {\n  background-image: url(../images/slider/slide_bar_disabled_center.png);\n}\n\n.slider.disabled  > .bar > .cap.left {\n  background-image: url(../images/slider/slide_bar_disabled_left.png);\n}\n\n.slider.disabled  > .bar > .cap.right {\n  background-image: url(../images/slider/slide_bar_disabled_right.png);\n}\n\n.slider.disabled,\n.slider.readonly {\n  pointer-events: none;\n}\n\n.slider {\n  -webkit-box-flex: 1;\n}\n\n.slider > input[type='range']::-webkit-slider-thumb {\n  background-image: url(../images/slider/slider_thumb.png);\n  width: 16px;\n}\n\n.slider > input[type='range']::-webkit-slider-thumb:hover {\n  background-image: url(../images/slider/slider_thumb_hover.png);\n}\n\n.slider > input[type='range']::-webkit-slider-thumb:active {\n  background-image: url(../images/slider/slider_thumb_down.png);\n}\n\n.slider.disabled > input[type='range']::-webkit-slider-thumb {\n  background-image: url(../images/slider/slider_thumb_disabled.png);\n}\n"
  },
  {
    "path": "_archive/mv2/api/fontSettings/slider.js",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\n/**\n * @fileoverview A Slider control. Based on Chromium's MediaControls.Slider.\n */\n\n/**\n * Creates a slider control.\n *\n * @param {HTMLElement} container The containing div element.\n * @param {number} value Initial value\n * @param {number} min Minimum value\n * @param {number} max Maximum value\n * @param {?function(number)=} opt_onChange Value change handler\n * @constructor\n */\nfunction Slider(container, value, min, max, opt_onChange) {\n  this.container_ = container;\n  this.onChange_ = opt_onChange;\n\n  var containerDocument = this.container_.ownerDocument;\n\n  this.container_.classList.add('slider');\n\n  this.input_ = containerDocument.createElement('input');\n  this.input_.type = 'range';\n  this.input_.min = min;\n  this.input_.max = max;\n  this.input_.value = value;\n  this.container_.appendChild(this.input_);\n\n  this.input_.addEventListener(\n      'change', this.onInputChange_.bind(this));\n  this.input_.addEventListener(\n      'input', this.onInputChange_.bind(this));\n\n  this.bar_ = containerDocument.createElement('div');\n  this.bar_.className = 'bar';\n  this.container_.appendChild(this.bar_);\n\n  this.filled_ = containerDocument.createElement('div');\n  this.filled_.className = 'filled';\n  this.bar_.appendChild(this.filled_);\n\n  var leftCap = containerDocument.createElement('div');\n  leftCap.className = 'cap left';\n  this.bar_.appendChild(leftCap);\n\n  var rightCap = containerDocument.createElement('div');\n  rightCap.className = 'cap right';\n  this.bar_.appendChild(rightCap);\n\n  this.updateFilledWidth_();\n};\n\n/**\n * @return {number} The value of the input control.\n */\nSlider.prototype.getValue = function() {\n  return this.input_.value;\n};\n\n/**\n * @param{number} value The value to set the input control to.\n */\nSlider.prototype.setValue = function(value) {\n  this.input_.value = value;\n  this.updateFilledWidth_();\n};\n\n/**\n * @return {HTMLInputElement} The underlying input control.\n */\nSlider.prototype.getInput = function() {\n  return this.input_;\n}\n\n/**\n * Updates the filled portion of the slider to reflect the slider's current\n * value.\n * @private\n */\nSlider.prototype.updateFilledWidth_ = function() {\n  var proportion = (this.input_.value - this.input_.min) /\n      (this.input_.max - this.input_.min);\n  this.filled_.style.width = proportion * 100 + '%';\n};\n\n/**\n * Called when the slider's value changes.\n * @private\n */\nSlider.prototype.onInputChange_ = function() {\n  this.updateFilledWidth_();\n  if (this.onChange_)\n    this.onChange_(this.input_.value);\n};\n\n"
  },
  {
    "path": "_archive/mv2/api/history/historyOverride/history.html",
    "content": "<html>\n  <head>\n    <title>History</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"/>\n  </head>\n  <body>\n    <div id=\"searchBar\">\n      <h1>History<sup>2</sup></h1>\n      <input id=\"searchInput\" type=\"text\" name=\"search\"\n        placeholder=\"Search History\">\n      <input type=\"submit\" id=\"searchSubmit\" value=\"Submit\">\n      <br>\n      <br>\n      <input type=\"submit\" id=\"deleteSelected\" value=\"Delete Selected\">\n      <br>\n      <br>\n      <input type=\"submit\" id=\"removeAll\" value=\"Remove All\">\n      <br>\n      <br>\n      <input type=\"submit\" id=\"seeAll\" value=\"See All\">\n    </div>\n    <div id=\"historyDiv\">\n    </div>\n    <template id=\"historyTemplate\">\n      <div class=\"history\">\n        <div class=\"imageDiv\">\n          <a class=\"titleLink\"></a>\n        </div>\n        <div class=\"urlDiv\">\n            <p class=\"pageName\"></p>\n        </div>\n        <div class=\"removeDiv\">\n          <a>\n            <button class=\"removeButton\">Delete</button>\n            <input type=\"checkbox\" class=\"removeCheck\"/>\n          </a>\n        </div>\n      </div>\n    </template>\n    <script src=\"logic.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/history/historyOverride/logic.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nconst kMillisecondsPerWeek = 1000 * 60 * 60 * 24 * 7;\nconst kOneWeekAgo = (new Date).getTime() - kMillisecondsPerWeek;\nlet historyDiv = document.getElementById('historyDiv');\nconst kColors = ['#4688F1', '#E8453C', '#F9BB2D', '#3AA757'];\nlet $ = document.getElementById.bind(document);\n\nfunction constructHistory(historyItems) {\n  let template = $('historyTemplate');\n  for (let item of historyItems) {\n    let displayDiv = template.content.querySelector(\"#history, div\");\n    let randomColor = kColors[Math.floor(Math.random() * kColors.length)];\n    displayDiv.style.backgroundColor = randomColor;\n    let titleLink = template.content.querySelector('.titleLink, a');\n    let pageName = template.content.querySelector('.pageName, p');\n    let removeButton = template.content.querySelector('.removeButton, button');\n    let checkbox = template.content.querySelector('.removeCheck, input');\n    checkbox.setAttribute('value', item.url);\n    let favicon = document.createElement('img');\n    let host = new URL(item.url).host;\n    titleLink.href = item.url;\n    favicon.src = 'chrome://favicon/' + item.url;\n    titleLink.textContent = host;\n    titleLink.appendChild(favicon);\n    pageName.innerText = item.title;\n    if (item.title === '') {\n      pageName.innerText = host;\n    }\n    var clone = document.importNode(template.content, true);\n    clone.querySelector('.removeButton, button')\n      .addEventListener('click', function() {\n        chrome.history.deleteUrl({url: item.url}, function() {\n          location.reload();\n        });\n      });\n    historyDiv.appendChild(clone);\n  }\n}\n\nchrome.history.search({\n      text: '',\n      startTime: kOneWeekAgo,\n      maxResults: 99\n    }, constructHistory);\n\n$('searchSubmit').onclick = function() {\n  historyDiv.innerHTML = \" \"\n  let searchQuery = document.getElementById('searchInput').value\n  chrome.history.search({\n        text: searchQuery,\n        startTime: kOneWeekAgo\n      }, constructHistory)\n}\n\n$('deleteSelected').onclick = function() {\n  let checkboxes = document.getElementsByTagName('input');\n  for (var i =0; i<checkboxes.length; i++) {\n    if (checkboxes[i].checked == true) {\n        chrome.history.deleteUrl({url: checkboxes[i].value})\n    }\n  }\n  location.reload();\n}\n\n$('removeAll').onclick = function() {\n  chrome.history.deleteAll(function() {\n    location.reload();\n  });\n}\n\n$('seeAll').onclick = function() {\n  location.reload();\n}\n"
  },
  {
    "path": "_archive/mv2/api/history/historyOverride/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"History Override\",\n  \"description\": \"Overrides the History Page\",\n  \"version\": \"1.0\",\n  \"chrome_url_overrides\" : {\n    \"history\": \"history.html\"\n  },\n  \"browser_action\": {\n    \"default_title\": \"History\"\n  },\n  \"permissions\": [\n    \"history\",\n    \"chrome://favicon/\"\n  ],\n  \"icons\": {\n    \"16\": \"history16.png\",\n    \"32\": \"history32.png\",\n    \"48\": \"history48.png\",\n    \"128\": \"history128.png\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/history/historyOverride/style.css",
    "content": "/* Copyright 2017 The Chromium Authors. All rights reserved.\n Use of this source code is governed by a BSD-style license that can be\n found in the LICENSE file.*/\n::-webkit-scrollbar {\n    width: 0px;  /* remove scrollbar space */\n    background: transparent;  /* make scrollbar invisible */\n}\n\n#searchBar {\n  float: left;\n  width: 250px;\n  height: auto;\n  position: absolute;\n  top: 10;\n  left: 10;\n}\n\n#historyDiv {\n  color: white;\n  font-size: 16px;\n  max-width: 1020px;\n  min-width: 320px;\n  max-height: 98vh;\n  min-height: 500px;\n  position: absolute;\n  top: 10;\n  left: 260;\n  overflow: scroll;\n  overflow-x: hidden;\n}\n\n.history {\n  float: left;\n  margin-right: 10px;\n  margin-bottom: 10px;\n  width: 300px;\n  height: 150px;\n  word-wrap: break-word;\n  padding: 10px;\n  display:inline-block;\n}\n\n.title {\n  color: black;\n  float: left;\n  position: relative;\n  left: 15;\n  bottom: 15;\n}\n\nimg {\n  float: left;\n  position: relative;\n  left: 5;\n  top: 2;\n  margin-right: 8px;\n}\n\n\n.imageDiv {\n  background-color: white;\n  width: 310px;\n  height: 20px;\n  position: relative;\n  right: 0;\n  overflow-y: hidden;\n}\n\n.removeButton {\n  position: relative;\n  right: 0;\n  bottom: 0;\n  height: 30px;\n  width: 50px;\n  border: none;\n  background-color: white;\n}\n\n.urlDiv {\n  position: relative;\n  right: 0;\n  top: -10;\n  height: 90px;\n  width: 300px;\n  overflow-y: hidden;\n}\n\n.removeCheck {\n  position: relative;\n  left: 230;\n  bottom: -15;\n  height: 30px;\n}\n\n#searchSubmit {\n  height: 30px;\n  width: 50px;\n  border: none;\n  background-color: #3AA757;\n}\n\n#deleteSelected {\n  height: 30px;\n  width: 185px;\n  border: none;\n  background-color: #F9BB2D;\n}\n\n#removeAll {\n  height: 30px;\n  width: 185px;\n  border: none;\n  background-color: #E8453C;\n}\n\n#seeAll {\n  height: 30px;\n  width: 185px;\n  border: none;\n  background-color: #4688F1;\n}\n\n#searchInput {\n  height: 30px;\n}\n\nh1 {\n  font-size: 50px;\n  font-family: Impact, Charcoal, sans-serif;\n}\n"
  },
  {
    "path": "_archive/mv2/api/history/showHistory/manifest.json",
    "content": "{\n  \"name\": \"Typed URL History\",\n  \"version\": \"1.2\",\n  \"description\": \"Reads your history, and shows the top ten pages you go to by typing the URL.\",\n  \"permissions\": [\n    \"history\"\n  ],\n  \"browser_action\": {\n    \"default_popup\": \"typedUrls.html\",\n    \"default_icon\": \"clock.png\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/history/showHistory/typedUrls.html",
    "content": "<!DOCTYPE HTML>\n<html>\n  <head>\n    <title>Recently Typed URLs</title>\n    <style>\n      body {min-width: 250px;}\n    </style>\n    <script src='typedUrls.js'></script>\n  </head>\n\n  <body>\n    <h2>Recently Typed URLs:</h2>\n    <div id=\"typedUrl_div\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/history/showHistory/typedUrls.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Event listner for clicks on links in a browser action popup.\n// Open the link in a new tab of the current window.\nfunction onAnchorClick(event) {\n  chrome.tabs.create({\n    selected: true,\n    url: event.srcElement.href\n  });\n  return false;\n}\n\n// Given an array of URLs, build a DOM list of those URLs in the\n// browser action popup.\nfunction buildPopupDom(divName, data) {\n  var popupDiv = document.getElementById(divName);\n\n  var ul = document.createElement('ul');\n  popupDiv.appendChild(ul);\n\n  for (var i = 0, ie = data.length; i < ie; ++i) {\n    var a = document.createElement('a');\n    a.href = data[i];\n    a.appendChild(document.createTextNode(data[i]));\n    a.addEventListener('click', onAnchorClick);\n\n    var li = document.createElement('li');\n    li.appendChild(a);\n\n    ul.appendChild(li);\n  }\n}\n\n// Search history to find up to ten links that a user has typed in,\n// and show those links in a popup.\nfunction buildTypedUrlList(divName) {\n  // To look for history items visited in the last week,\n  // subtract a week of microseconds from the current time.\n  var microsecondsPerWeek = 1000 * 60 * 60 * 24 * 7;\n  var oneWeekAgo = (new Date).getTime() - microsecondsPerWeek;\n\n  // Track the number of callbacks from chrome.history.getVisits()\n  // that we expect to get.  When it reaches zero, we have all results.\n  var numRequestsOutstanding = 0;\n\n  chrome.history.search({\n      'text': '',              // Return every history item....\n      'startTime': oneWeekAgo  // that was accessed less than one week ago.\n    },\n    function(historyItems) {\n      // For each history item, get details on all visits.\n      for (var i = 0; i < historyItems.length; ++i) {\n        var url = historyItems[i].url;\n        var processVisitsWithUrl = function(url) {\n          // We need the url of the visited item to process the visit.\n          // Use a closure to bind the  url into the callback's args.\n          return function(visitItems) {\n            processVisits(url, visitItems);\n          };\n        };\n        chrome.history.getVisits({url: url}, processVisitsWithUrl(url));\n        numRequestsOutstanding++;\n      }\n      if (!numRequestsOutstanding) {\n        onAllVisitsProcessed();\n      }\n    });\n\n\n  // Maps URLs to a count of the number of times the user typed that URL into\n  // the omnibox.\n  var urlToCount = {};\n\n  // Callback for chrome.history.getVisits().  Counts the number of\n  // times a user visited a URL by typing the address.\n  var processVisits = function(url, visitItems) {\n    for (var i = 0, ie = visitItems.length; i < ie; ++i) {\n      // Ignore items unless the user typed the URL.\n      if (visitItems[i].transition != 'typed') {\n        continue;\n      }\n\n      if (!urlToCount[url]) {\n        urlToCount[url] = 0;\n      }\n\n      urlToCount[url]++;\n    }\n\n    // If this is the final outstanding call to processVisits(),\n    // then we have the final results.  Use them to build the list\n    // of URLs to show in the popup.\n    if (!--numRequestsOutstanding) {\n      onAllVisitsProcessed();\n    }\n  };\n\n  // This function is called when we have the final list of URls to display.\n  var onAllVisitsProcessed = function() {\n    // Get the top scorring urls.\n    urlArray = [];\n    for (var url in urlToCount) {\n      urlArray.push(url);\n    }\n\n    // Sort the URLs by the number of times the user typed them.\n    urlArray.sort(function(a, b) {\n      return urlToCount[b] - urlToCount[a];\n    });\n\n    buildPopupDom(divName, urlArray.slice(0, 10));\n  };\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  buildTypedUrlList(\"typedUrl_div\");\n});"
  },
  {
    "path": "_archive/mv2/api/i18n/cld/background.js",
    "content": "// Copyright (c) 2009 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar selectedId = -1;\nfunction refreshLanguage() {\n  chrome.tabs.detectLanguage(null, function(language) {\n    console.log(language);\n    if (language == \" invalid_language_code\")\n      language = \"???\";\n    chrome.browserAction.setBadgeText({\"text\": language, tabId: selectedId});\n  });\n}\n\nchrome.tabs.onUpdated.addListener(function(tabId, props) {\n  if (props.status == \"complete\" && tabId == selectedId)\n    refreshLanguage();\n});\n\nchrome.tabs.onSelectionChanged.addListener(function(tabId, props) {\n  selectedId = tabId;\n  refreshLanguage();\n});\n\nchrome.tabs.query({active: true, currentWindow: true}, function(tabs) {\n  selectedId = tabs[0].id;\n  refreshLanguage();\n});\n"
  },
  {
    "path": "_archive/mv2/api/i18n/cld/manifest.json",
    "content": "{\n  \"name\": \"CLD\",\n  \"description\": \"Displays the language of a tab\",\n  \"version\": \"0.3\",\n  \"background\": {\n    \"scripts\": [\"background.js\"]\n  },\n  \"browser_action\": {\n      \"default_name\": \"Page Language\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/i18n/detectLanguage/manifest.json",
    "content": "{\n  \"name\": \"Detect Language\",\n  \"description\": \"Detects up to 3 languages and their percentages of the provided string\",\n  \"version\": \"1.0\",\n\n  \"browser_action\": {\n    \"default_icon\": \"icon.png\",\n    \"default_popup\": \"popup.html\"\n  },\n\n  \"manifest_version\": 2\n}"
  },
  {
    "path": "_archive/mv2/api/i18n/detectLanguage/popup.html",
    "content": "<html>\n  <head>\n    <style>\n      body {\n        font-family: \"Segoe UI\", \"Lucida Grande\", Tahoma, sans-serif;\n        font-size: 100%;\n      }\n    </style>\n    <script src=\"popup.js\"></script>\n  </head>\n  <body>\n    <div id=\"detect_lang\">\n      <textarea id=\"text\" placeholder=\"Text to translate\" style=\"padding: 10px; width: 300px;\"></textarea>\n      <button id=\"btn-detect\">Translate</button>\n    </div>\n  </body>\n</html>"
  },
  {
    "path": "_archive/mv2/api/i18n/detectLanguage/popup.js",
    "content": "// Copyright (c) 2015 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  document.getElementById(\"btn-detect\").addEventListener(\"click\", function() {\n    var inputText = document.getElementById(\"text\").value;\n    chrome.i18n.detectLanguage(inputText, function(result) {\n        var languages =  \"Languages: \\n\";\n        for (var i = 0; i < result.languages.length; i++) {\n           languages += result.languages[i].language + \" \";\n           languages += result.languages[i].percentage + \"\\n\";\n        }\n\n        var is_reliable = \"\\nReliable? \\n\" + result.isReliable + \"\\n\";\n        alert(languages + is_reliable);\n    });\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/i18n/getMessage/_locales/en_US/messages.json",
    "content": "{\n  \"chrome_extension_name\": {\n    \"message\": \"AcceptLanguage\"\n  },\n  \"chrome_extension_description\": {\n    \"message\": \"Returns accept languages of the browser\"\n  },\n  \"click_here\": {\n    \"message\": \"Left click to list acceptLanguages.\"\n  },\n  \"browser_action_title\": {\n    \"message\": \"Click Me\"\n  },\n  \"chrome_accept_languages\": {\n    \"message\": \"$CHROME$ accepts $languages$ languages\",\n    \"placeholders\": {\n      \"chrome\": {\n        \"content\": \"Chrome\",\n        \"example\": \"Chrome\"\n      },\n      \"languages\": {\n        \"content\": \"$1\",\n        \"example\": \"en-US,sr,de\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/i18n/getMessage/_locales/es/messages.json",
    "content": "{\n  \"chrome_extension_name\": {\n    \"message\": \"AcceptLanguage\"\n  },\n  \"chrome_extension_description\": {\n    \"message\": \"Devuelve los idiomas aceptados por el navegador\"\n  },\n  \"click_here\": {\n    \"message\": \"Click con botón izquierdo para mostrar la lista de acceptLanguages.\"\n  },\n  \"browser_action_title\": {\n    \"message\": \"Haz click aquí\"\n  },\n  \"chrome_accept_languages\": {\n    \"message\": \"$CHROME$ acepta los idiomas $languages$\",\n    \"placeholders\": {\n      \"chrome\": {\n        \"content\": \"Chrome\",\n        \"example\": \"Chrome\"\n      },\n      \"languages\": {\n        \"content\": \"$1\",\n        \"example\": \"en-US,sr,de\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/i18n/getMessage/_locales/sr/messages.json",
    "content": "{\n  \"chrome_extension_name\": {\n    \"message\": \"Прихватљиви језици\"\n  },\n  \"chrome_extension_description\": {\n    \"message\": \"Језици које прегледач прихвата\"\n  },\n  \"click_here\": {\n    \"message\": \"Кликните да излистате дозвољене језике.\"\n  },\n  \"chrome_accept_languages\": {\n    \"message\": \"$CHROME$ прихвата $languages$ језике.\",\n    \"placeholders\": {\n      \"chrome\": {\n        \"content\": \"Chrome\",\n        \"example\": \"Chrome\"\n      },\n      \"languages\": {\n        \"content\": \"$1\",\n        \"example\": \"en-US,sr,de\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/i18n/getMessage/manifest.json",
    "content": "{\n  \"name\": \"__MSG_chrome_extension_name__\",\n  \"description\": \"__MSG_chrome_extension_description__\",\n  \"version\": \"0.2\",\n  \"default_locale\": \"en_US\",\n  \"browser_action\": {\n      \"default_title\": \"__MSG_browser_action_title__\",\n      \"default_icon\": \"icon.png\",\n      \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/i18n/getMessage/popup.html",
    "content": "<!--\nCopyright (c) 2012 The Chromium Authors. All rights reserved. Use of this\nsource code is governed by a BSD-style license that can be found in the\nLICENSE file.\n-->\n\n<html>\n  <head>\n    <style>\n      body {\n        color: black;\n        width: 300px;\n      }\n    </style>\n    <script src=\"popup.js\"></script>\n  </head>\n  <body>\n    <div id=\"accept_lang\">\n      <span id=\"languageSpan\"></span>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/i18n/getMessage/popup.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction setChildTextNode(elementId, text) {\n  document.getElementById(elementId).innerText = text;\n}\n\nfunction init() {\n  setChildTextNode('languageSpan', chrome.i18n.getMessage(\"click_here\"));\n}\n\nfunction getAcceptLanguages() {\n  chrome.i18n.getAcceptLanguages(function(languageList) {\n    var languages = languageList.join(\",\");\n    setChildTextNode('languageSpan',\n        chrome.i18n.getMessage(\"chrome_accept_languages\", languages));\n  })\n}\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  document.querySelector('#accept_lang').addEventListener(\n      'click', getAcceptLanguages);\n  init();\n});\n"
  },
  {
    "path": "_archive/mv2/api/i18n/localizedHostedApp/_locales/de/messages.json",
    "content": "{\n  \"application_title\": {\n    \"message\": \"Eine lokalisierte gehostete Beispielanwendung\"\n  },\n  \"application_description\": {\n    \"message\": \"Hier steht eine Beschreibung der Applikation, die im Web Store auftauchen wird.\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/i18n/localizedHostedApp/_locales/en/messages.json",
    "content": "{\n  \"application_title\": {\n    \"message\": \"Minimal Localized Hosted App\",\n    \"description\": \"The title of the application, displayed in the web store.\"\n  },\n  \"application_description\": {\n    \"message\": \"This is the minimal set of data required to upload a localized hosted application to the web store.\",\n    \"description\": \"The description of the application, displayed in the web store.\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/i18n/localizedHostedApp/manifest.json",
    "content": "{\n  \"name\": \"__MSG_application_title__\",\n  \"description\": \"__MSG_application_description__\",\n  \"version\": \"0.2\",\n  \"default_locale\": \"en\",\n  \"app\": {\n    \"launch\": {\n      \"web_url\": \"http://example.com/\"\n    }\n  },\n  \"icons\": {\n    \"128\": \"icon128.png\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/idle/idle_simple/background.js",
    "content": "// Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n// source code is governed by a BSD-style license that can be found in the\n// LICENSE file.\n\nvar history_log = [];\n\n/**\n* Stores a state every time an \"active\" event is sent, up to 20 items.\n*/\nchrome.idle.onStateChanged.addListener(function(newstate) {\n  var time = new Date();\n  if (history_log.length >= 20) {\n    history_log.pop();\n  }\n  history_log.unshift({'state':newstate, 'time':time});\n});\n\n/**\n* Opens history.html when the browser action is clicked.\n* Used window.open because I didn't want the tabs permission.\n*/\nchrome.browserAction.onClicked.addListener(function() {\n  window.open('history.html', 'testwindow', 'width=700,height=600');\n});\n"
  },
  {
    "path": "_archive/mv2/api/idle/idle_simple/history.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n<html>\n  <head>\n    <style>\n      body {\n        width: 100%;\n        font: 13px Arial;\n      }\n    </style>\n    <script src=\"history.js\"></script>\n  </head>\n  <body>\n    <h1>Idle API Demonstration</h1>\n    <h2>Current state</h2>\n    <p>\n      Idle threshold:\n      <select id=\"idle-threshold\">\n        <option selected value=\"15\">15</option>\n        <option value=\"30\">30</option>\n        <option value=\"60\">60</option>\n      </select>\n    <p>\n      <code>chrome.idle.queryState(<strong id=\"idle-set-threshold\"></strong>, ...);</code> - \n      <span id=\"idle-state\"></span>\n    </p>\n    <p>\n      Last state change: <span id=\"idle-laststate\"></span>\n    </p>\n    \n    <h2>Idle changes:</h2>\n    <ul id='idle-history'></ul>\n  </body>\n</html>"
  },
  {
    "path": "_archive/mv2/api/idle/idle_simple/history.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * Convert a state and time into a nice styled chunk of HTML.\n */\nfunction renderState(state, time) {\n  var now = new Date().getTime();\n  var diff = Math.round((time.getTime() - now) / 1000);\n  var str = (diff == 0) ?\n      \"now\" :\n      Math.abs(diff) + \" seconds \" + (diff > 0 ? \"from now\" : \"ago\");\n  var col = (state == \"active\") ?\n      \"#009900\" :\n      \"#990000\";\n  return \"<b style='color: \" + col + \"'>\" + state + \"</b> \" + str;\n};\n\n/**\n * Creates DOM and injects a rendered state into the page.\n */\nfunction renderItem(state, time, parent) {\n  var dom_item = document.createElement('li');\n  dom_item.innerHTML = renderState(state, time);\n  parent.appendChild(dom_item);\n};\n\n// Store previous state so we can show deltas.  This is important\n// because the API currently doesn't fire idle messages, and we'd\n// like to keep track of last time we went idle.\nvar laststate = null;\nvar laststatetime = null;\n\n/**\n * Checks the current state of the browser.\n */\nfunction checkState() {\n  threshold = parseInt(document.querySelector('#idle-threshold').value);\n  var dom_threshold = document.querySelector('#idle-set-threshold');\n  dom_threshold.innerText = threshold;\n\n  // Request the state based off of the user-supplied threshold.\n  chrome.idle.queryState(threshold, function(state) {\n    var time = new Date();\n    if (laststate != state) {\n      laststate = state;\n      laststatetime = time;\n    }\n\n    // Keep rendering results so we get a nice \"seconds elapsed\" view.\n    var dom_result = document.querySelector('#idle-state');\n    dom_result.innerHTML = renderState(state, time);\n    var dom_laststate = document.querySelector('#idle-laststate');\n    dom_laststate.innerHTML = renderState(laststate, laststatetime);\n  });\n};\n\nvar dom_history = document.querySelector('#idle-history');\n\n/**\n * Render the data gathered by the background page - should show a log\n * of \"active\" states.  No events are fired upon idle.\n */\nfunction renderHistory() {\n  dom_history.innerHTML = \"\";\n  var history_log = chrome.extension.getBackgroundPage().history_log;\n  for (var i = 0; i < history_log.length; i++) {\n    var data = history_log[i];\n    renderItem(data['state'], data['time'], dom_history);\n  }\n};\n\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  // Check every second (even though this is overkill - minimum idle\n  // threshold is 15 seconds) so that the numbers appear to be counting up.\n  checkState();\n  window.setInterval(checkState, 1000);\n\n  // Check every second (see above).\n  renderHistory();\n  window.setInterval(renderHistory, 1000);\n});\n"
  },
  {
    "path": "_archive/mv2/api/idle/idle_simple/manifest.json",
    "content": "{\n  \"name\" : \"Idle - Simple Example\",\n  \"version\" : \"1.0.1\",\n  \"description\" : \"Demonstrates the Idle API\",\n  \"background\" : {\n    \"scripts\": [\"background.js\"]\n  },\n  \"permissions\" : [ \"idle\" ],\n  \"browser_action\" : {\n    \"default_icon\" : \"sample-19.png\"\n  },\n  \"icons\" : {\n    \"16\" : \"sample-16.png\",\n    \"48\" : \"sample-48.png\",\n    \"128\" : \"sample-128.png\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/input.ime/basic/main.js",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar ime_api = chrome.input.ime;\n\nvar context_id = -1;\n\nconsole.log(\"Initializing IME\");\n\nime_api.onFocus.addListener(function(context) {\n  console.log('onFocus:' + context.contextID);\n  context_id = context.contextID;\n});\nime_api.onBlur.addListener(function(contextID) {\n  console.log('onBlur:' + contextID);\n  context_id = -1;\n});\n\nime_api.onActivate.addListener(function(engineID) {\n  console.log('onActivate:' + engineID);\n});\nime_api.onDeactivated.addListener(function(engineID) {\n  console.log('onDeactivated:' + engineID);\n});\n\nime_api.onKeyEvent.addListener(\nfunction(engineID, keyData) {\n  console.log('onKeyEvent:' + keyData.key + \" context: \" + context_id);\n  if (keyData.type == \"keydown\" && keyData.key.match(/^[a-z]$/)) {\n    chrome.input.ime.commitText({\"contextID\": context_id,\n                                 \"text\": keyData.key.toUpperCase()});\n    return true;\n  }\n\n  return false\n});\n"
  },
  {
    "path": "_archive/mv2/api/input.ime/basic/manifest.json",
    "content": "{\n  \"name\": \"Test IME\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 2,\n  \"description\": \"A simple IME that converts all keystrokes to upper case.\",\n  \"background\":  {\n    \"scripts\": [\"main.js\"]\n  },\n  \"permissions\": [\n    \"input\"\n  ],\n  \"input_components\": [\n    {\n      \"name\": \"Test IME\",\n      \"type\": \"ime\",\n      \"id\": \"test\",\n      \"description\": \"Test IME\",  // A user visible description\n      \"language\": \"en-US\",  // The primary language this IME is used for\n      \"layouts\": [\"us::eng\"]  // The supported keyboard layouts for this IME\n    }\n  ]\n}\n"
  },
  {
    "path": "_archive/mv2/api/messaging/timer/manifest.json",
    "content": "{\n  \"name\": \"Message Timer\",\n  \"version\": \"1.3\",\n  \"description\": \"Times how long it takes to send a message to a content script and back.\",\n  \"content_scripts\": [\n    {\n      \"matches\": [\"http://*/*\", \"https://*/*\"],\n      \"js\": [\"page.js\"]\n    }\n  ],\n  \"browser_action\": {\n    \"default_title\": \"Time to current page\",\n    \"default_icon\": \"clock.png\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/messaging/timer/page.js",
    "content": "// Copyright (c) 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.runtime.onConnect.addListener(function(port) {\n  port.onMessage.addListener(function(msg) {\n    port.postMessage({counter: msg.counter+1});\n  });\n});\n\nchrome.runtime.onMessage.addListener(\n  function(request, sender, sendResponse) {\n    sendResponse({counter: request.counter+1});\n  });\n"
  },
  {
    "path": "_archive/mv2/api/messaging/timer/popup.html",
    "content": "<head>\n<style>\ntr {\n  white-space: nowrap;\n}\n.results {\n  text-align: right;\n  min-width: 6em;\n  color: black;\n}\n</style>\n<script src=\"popup.js\"></script>\n</head>\n<body>\n<table>\n  <tr>\n    <td><button id=\"testMessage\">Measure sendMessage</button></td>\n    <td id=\"resultsRequest\" class=\"results\">(results)</td>\n  </tr>\n  <tr>\n    <td><button id=\"testConnect\">Measure postMessage</button></td>\n    <td id=\"resultsConnect\" class=\"results\">(results)</td>\n  </tr>\n</table>\n</body>\n"
  },
  {
    "path": "_archive/mv2/api/messaging/timer/popup.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction setChildTextNode(elementId, text) {\n  document.getElementById(elementId).innerText = text;\n}\n\n// Tests the roundtrip time of sendMessage().\nfunction testMessage() {\n  setChildTextNode(\"resultsRequest\", \"running...\");\n\n  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {\n    var timer = new chrome.Interval();\n    timer.start();\n    var tab = tabs[0];\n    chrome.tabs.sendMessage(tab.id, {counter: 1}, function handler(response) {\n      if (response.counter < 1000) {\n        chrome.tabs.sendMessage(tab.id, {counter: response.counter}, handler);\n      } else {\n        timer.stop();\n        var usec = Math.round(timer.microseconds() / response.counter);\n        setChildTextNode(\"resultsRequest\", usec + \"usec\");\n      }\n    });\n  });\n}\n\n// Tests the roundtrip time of Port.postMessage() after opening a channel.\nfunction testConnect() {\n  setChildTextNode(\"resultsConnect\", \"running...\");\n\n  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {\n    var timer = new chrome.Interval();\n    timer.start();\n\n    var port = chrome.tabs.connect(tabs[0].id);\n    port.postMessage({counter: 1});\n    port.onMessage.addListener(function getResp(response) {\n      if (response.counter < 1000) {\n        port.postMessage({counter: response.counter});\n      } else {\n        timer.stop();\n        var usec = Math.round(timer.microseconds() / response.counter);\n        setChildTextNode(\"resultsConnect\", usec + \"usec\");\n      }\n    });\n  });\n}\n\n(function(){\n  if (!chrome.benchmarking) {\n    alert(\"Warning:  Looks like you forgot to run chrome with \" +\n          \" --enable-benchmarking set.\");\n    return;\n  }\n  document.addEventListener('DOMContentLoaded', function() {\n    document.querySelector('#testMessage').addEventListener(\n        'click', testMessage);\n    document.querySelector('#testConnect').addEventListener(\n        'click', testConnect);\n  });\n})();\n"
  },
  {
    "path": "_archive/mv2/api/nativeMessaging/README.md",
    "content": "This directory contains an example of chrome application that uses native\nmessaging API that allows to communicate with a native application.\n\nIn order for this example to work you must first install the native messaging\nhost from the host directory.\n\n## To install the host:\n\n\n**On Windows:**\n\n  Run install_host.bat script in the host directory.\n  This script installs the native messaging host for the current user, by\n  creating a registry key\n  HKEY_CURRENT_USER\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\com.google.chrome.example.echo\n  and setting its default value to the full path to\n  host\\com.google.chrome.example.echo-win.json .\n  If you want to install the native messaging host for all users, change HKCU to\n  HKLM.\n  Note that you need to have python installed.\n\n**On Mac and Linux:**\n\n  Run install_host.sh script in the host directory:\n    host/install_host.sh\n  By default the host is installed only for the user who runs the script, but if\n  you run it with admin privileges (i.e. 'sudo host/install_host.sh'), then the\n  host will be installed for all users. You can later use host/uninstall_host.sh\n  to uninstall the host.\n"
  },
  {
    "path": "_archive/mv2/api/nativeMessaging/app/main.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright 2013 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n\n<html>\n  <head>\n    <script src='./main.js'></script>\n  </head>\n  <body>\n    <button id='connect-button'>Connect</button>\n    <input id='input-text' type='text' />\n    <button id='send-message-button'>Send</button>\n    <div id='response'></div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/nativeMessaging/app/main.js",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar port = null;\n\nvar getKeys = function(obj){\n   var keys = [];\n   for(var key in obj){\n      keys.push(key);\n   }\n   return keys;\n}\n\n\nfunction appendMessage(text) {\n  document.getElementById('response').innerHTML += \"<p>\" + text + \"</p>\";\n}\n\nfunction updateUiState() {\n  if (port) {\n    document.getElementById('connect-button').style.display = 'none';\n    document.getElementById('input-text').style.display = 'block';\n    document.getElementById('send-message-button').style.display = 'block';\n  } else {\n    document.getElementById('connect-button').style.display = 'block';\n    document.getElementById('input-text').style.display = 'none';\n    document.getElementById('send-message-button').style.display = 'none';\n  }\n}\n\nfunction sendNativeMessage() {\n  message = {\"text\": document.getElementById('input-text').value};\n  port.postMessage(message);\n  appendMessage(\"Sent message: <b>\" + JSON.stringify(message) + \"</b>\");\n}\n\nfunction onNativeMessage(message) {\n  appendMessage(\"Received message: <b>\" + JSON.stringify(message) + \"</b>\");\n}\n\nfunction onDisconnected() {\n  appendMessage(\"Failed to connect: \" + chrome.runtime.lastError.message);\n  port = null;\n  updateUiState();\n}\n\nfunction connect() {\n  var hostName = \"com.google.chrome.example.echo\";\n  appendMessage(\"Connecting to native messaging host <b>\" + hostName + \"</b>\")\n  port = chrome.runtime.connectNative(hostName);\n  port.onMessage.addListener(onNativeMessage);\n  port.onDisconnect.addListener(onDisconnected);\n  updateUiState();\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  document.getElementById('connect-button').addEventListener(\n      'click', connect);\n  document.getElementById('send-message-button').addEventListener(\n      'click', sendNativeMessage);\n  updateUiState();\n});\n"
  },
  {
    "path": "_archive/mv2/api/nativeMessaging/app/manifest.json",
    "content": "{\n  // Extension ID: knldjmfmopnpolahpmmgbagdohdnhkik\n  \"key\": \"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB\",\n  \"name\": \"Native Messaging Example\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 2,\n  \"description\": \"Send a message to a native application.\",\n  \"app\": {\n    \"launch\": {\n      \"local_path\": \"main.html\"\n    }\n  },\n  \"icons\": {\n    \"128\": \"icon-128.png\"\n  },\n  \"permissions\": [\n    \"nativeMessaging\"\n  ]\n}\n"
  },
  {
    "path": "_archive/mv2/api/nativeMessaging/host/com.google.chrome.example.echo-win.json",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n{\n  \"name\": \"com.google.chrome.example.echo\",\n  \"description\": \"Chrome Native Messaging API Example Host\",\n  \"path\": \"native-messaging-example-host.bat\",\n  \"type\": \"stdio\",\n  \"allowed_origins\": [\n    \"chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/\"\n  ]\n}\n"
  },
  {
    "path": "_archive/mv2/api/nativeMessaging/host/com.google.chrome.example.echo.json",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n{\n  \"name\": \"com.google.chrome.example.echo\",\n  \"description\": \"Chrome Native Messaging API Example Host\",\n  \"path\": \"HOST_PATH\",\n  \"type\": \"stdio\",\n  \"allowed_origins\": [\n    \"chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/\"\n  ]\n}\n"
  },
  {
    "path": "_archive/mv2/api/nativeMessaging/host/install_host.bat",
    "content": ":: Copyright 2014 The Chromium Authors. All rights reserved.\n:: Use of this source code is governed by a BSD-style license that can be\n:: found in the LICENSE file.\n\n:: Change HKCU to HKLM if you want to install globally.\n:: %~dp0 is the directory containing this bat script and ends with a backslash.\nREG ADD \"HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\com.google.chrome.example.echo\" /ve /t REG_SZ /d \"%~dp0com.google.chrome.example.echo-win.json\" /f\n"
  },
  {
    "path": "_archive/mv2/api/nativeMessaging/host/install_host.sh",
    "content": "#!/bin/sh\n# Copyright 2013 The Chromium Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style license that can be\n# found in the LICENSE file.\n\nset -e\n\nDIR=\"$( cd \"$( dirname \"$0\" )\" && pwd )\"\nif [ $(uname -s) == 'Darwin' ]; then\n  if [ \"$(whoami)\" == \"root\" ]; then\n    TARGET_DIR=\"/Library/Google/Chrome/NativeMessagingHosts\"\n    chmod a+x \"$DIR/native-messaging-example-host\"\n  else\n    TARGET_DIR=\"$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts\"\n  fi\nelse\n  if [ \"$(whoami)\" == \"root\" ]; then\n    TARGET_DIR=\"/etc/opt/chrome/native-messaging-hosts\"\n    chmod a+x \"$DIR/native-messaging-example-host\"\n  else\n    TARGET_DIR=\"$HOME/.config/google-chrome/NativeMessagingHosts\"\n  fi\nfi\n\nHOST_NAME=com.google.chrome.example.echo\n\n# Create directory to store native messaging host.\nmkdir -p \"$TARGET_DIR\"\n\n# Copy native messaging host manifest.\ncp \"$DIR/$HOST_NAME.json\" \"$TARGET_DIR\"\n\n# Update host path in the manifest.\nHOST_PATH=\"$DIR/native-messaging-example-host\"\nESCAPED_HOST_PATH=${HOST_PATH////\\\\/}\nsed -i -e \"s/HOST_PATH/$ESCAPED_HOST_PATH/\" \"$TARGET_DIR/$HOST_NAME.json\"\n\n# Set permissions for the manifest so that all users can read it.\nchmod o+r \"$TARGET_DIR/$HOST_NAME.json\"\n\necho Native messaging host $HOST_NAME has been installed.\n"
  },
  {
    "path": "_archive/mv2/api/nativeMessaging/host/native-messaging-example-host",
    "content": "#!/usr/bin/python3\n# Copyright (c) 2012 The Chromium Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style license that can be\n# found in the LICENSE file.\n\n# A simple native messaging host. Shows a Tkinter dialog with incoming messages\n# that also allows to send message back to the webapp.\n\nimport struct\nimport sys\nimport threading\nimport queue as Queue\n\ntry:\n  import tkinter as Tkinter\n  import tkinter.messagebox\nexcept ImportError:\n  Tkinter = None\n\n# On Windows, the default I/O mode is O_TEXT. Set this to O_BINARY\n# to avoid unwanted modifications of the input/output streams.\nif sys.platform == \"win32\":\n  import os, msvcrt\n  msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)\n  msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)\n\n# Helper function that sends a message to the webapp.\ndef send_message(message):\n   # Write message size.\n  sys.stdout.buffer.write(struct.pack('I', len(message)))\n  # Write the message itself.\n  sys.stdout.write(message)\n  sys.stdout.flush()\n\n# Thread that reads messages from the webapp.\ndef read_thread_func(queue):\n  message_number = 0\n  while 1:\n    # Read the message length (first 4 bytes).\n    text_length_bytes = sys.stdin.buffer.read(4)\n\n    if len(text_length_bytes) == 0:\n      if queue:\n        queue.put(None)\n      sys.exit(0)\n\n    # Unpack message length as 4 byte integer.\n    text_length = struct.unpack('@I', text_length_bytes)[0]\n\n    # Read the text (JSON object) of the message.\n    text = sys.stdin.buffer.read(text_length).decode('utf-8')\n\n    if text == '{\"text\":\"exit\"}':\n      break\n\n    if queue:\n      queue.put(text)\n    else:\n      # In headless mode just send an echo message back.\n      send_message('{\"echo\": %s}' % text)\n\nif Tkinter:\n  class NativeMessagingWindow(tkinter.Frame):\n    def __init__(self, queue):\n      self.queue = queue\n\n      tkinter.Frame.__init__(self)\n      self.pack()\n\n      self.text = tkinter.Text(self)\n      self.text.grid(row=0, column=0, padx=10, pady=10, columnspan=2)\n      self.text.config(state=tkinter.DISABLED, height=10, width=40)\n\n      self.messageContent = tkinter.StringVar()\n      self.sendEntry = tkinter.Entry(self, textvariable=self.messageContent)\n      self.sendEntry.grid(row=1, column=0, padx=10, pady=10)\n\n      self.sendButton = tkinter.Button(self, text=\"Send\", command=self.onSend)\n      self.sendButton.grid(row=1, column=1, padx=10, pady=10)\n\n      self.after(100, self.processMessages)\n\n    def processMessages(self):\n      while not self.queue.empty():\n        message = self.queue.get_nowait()\n        if message == None:\n          self.quit()\n          return\n        self.log(\"Received %s\" % message)\n\n      self.after(100, self.processMessages)\n\n    def onSend(self):\n      text = '{\"text\": \"' + self.messageContent.get() + '\"}'\n      self.log('Sending %s' % text)\n      try:\n        send_message(text)\n      except IOError:\n        tkinter.messagebox.showinfo('Native Messaging Example',\n                              'Failed to send message.')\n        sys.exit(1)\n\n    def log(self, message):\n      self.text.config(state=tkinter.NORMAL)\n      self.text.insert(tkinter.END, message + \"\\n\")\n      self.text.config(state=tkinter.DISABLED)\n\n\ndef Main():\n  if not Tkinter:\n    send_message('\"Tkinter python module wasn\\'t found. Running in headless ' +\n                 'mode. Please consider installing Tkinter.\"')\n    read_thread_func(None)\n    sys.exit(0)\n\n  queue = Queue.Queue()\n\n  main_window = NativeMessagingWindow(queue)\n  main_window.master.title('Native Messaging Example')\n\n  thread = threading.Thread(target=read_thread_func, args=(queue,))\n  thread.daemon = True\n  thread.start()\n\n  main_window.mainloop()\n\n  sys.exit(0)\n\n\nif __name__ == '__main__':\n  Main()\n"
  },
  {
    "path": "_archive/mv2/api/nativeMessaging/host/native-messaging-example-host.bat",
    "content": "@echo off\n:: Copyright (c) 2013 The Chromium Authors. All rights reserved.\n:: Use of this source code is governed by a BSD-style license that can be\n:: found in the LICENSE file.\n\npython \"%~dp0/native-messaging-example-host\" %*\n"
  },
  {
    "path": "_archive/mv2/api/nativeMessaging/host/uninstall_host.bat",
    "content": ":: Copyright 2014 The Chromium Authors. All rights reserved.\n:: Use of this source code is governed by a BSD-style license that can be\n:: found in the LICENSE file.\n\n:: Deletes the entry created by install_host.bat\nREG DELETE \"HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\com.google.chrome.example.echo\" /f\nREG DELETE \"HKLM\\Software\\Google\\Chrome\\NativeMessagingHosts\\com.google.chrome.example.echo\" /f\n"
  },
  {
    "path": "_archive/mv2/api/nativeMessaging/host/uninstall_host.sh",
    "content": "#!/bin/sh\n# Copyright 2013 The Chromium Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style license that can be\n# found in the LICENSE file.\n\nset -e\n\nif [ \"$(uname -s)\" = \"Darwin\" ]; then\n  if [ \"$(whoami)\" = \"root\" ]; then\n    TARGET_DIR=\"/Library/Google/Chrome/NativeMessagingHosts\"\n  else\n    TARGET_DIR=\"$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts\"\n  fi\nelse\n  if [ \"$(whoami)\" = \"root\" ]; then\n    TARGET_DIR=\"/etc/opt/chrome/native-messaging-hosts\"\n  else\n    TARGET_DIR=\"$HOME/.config/google-chrome/NativeMessagingHosts\"\n  fi\nfi\n\nHOST_NAME=com.google.chrome.example.echo\nrm \"$TARGET_DIR/com.google.chrome.example.echo.json\"\necho \"Native messaging host $HOST_NAME has been uninstalled.\"\n"
  },
  {
    "path": "_archive/mv2/api/notifications/background.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/*\n  Displays a notification with the current time. Requires \"notifications\"\n  permission in the manifest file (or calling\n  \"Notification.requestPermission\" beforehand).\n*/\nfunction show() {\n  var time = /(..)(:..)/.exec(new Date());     // The prettyprinted time.\n  var hour = time[1] % 12 || 12;               // The prettyprinted hour.\n  var period = time[1] < 12 ? 'a.m.' : 'p.m.'; // The period of the day.\n  new Notification(hour + time[2] + ' ' + period, {\n    icon: '48.png',\n    body: 'Time to make the toast.'\n  });\n}\n\n// Conditionally initialize the options.\nif (!localStorage.isInitialized) {\n  localStorage.isActivated = true;   // The display activation.\n  localStorage.frequency = 1;        // The display frequency, in minutes.\n  localStorage.isInitialized = true; // The option initialization.\n}\n\n// Test for notification support.\nif (window.Notification) {\n  // While activated, show notifications at the display frequency.\n  if (JSON.parse(localStorage.isActivated)) { show(); }\n\n  var interval = 0; // The display interval, in minutes.\n\n  setInterval(function() {\n    interval++;\n\n    if (\n      JSON.parse(localStorage.isActivated) &&\n        localStorage.frequency <= interval\n    ) {\n      show();\n      interval = 0;\n    }\n  }, 60000);\n}\n"
  },
  {
    "path": "_archive/mv2/api/notifications/manifest.json",
    "content": "{\n  \"name\": \"Notification Demo\",\n  \"version\": \"1.1\",\n  \"description\":\n    \"Shows off desktop notifications, which are \\\"toast\\\" windows that pop up on the desktop.\",\n  \"icons\": {\"16\": \"16.png\", \"48\": \"48.png\", \"128\": \"128.png\"},\n  \"permissions\": [\n    \"notifications\"\n  ],\n  \"options_page\": \"options.html\",\n  \"background\": { \"scripts\": [\"background.js\"] },\n  \"manifest_version\": 2,\n\n  // crbug.com/134315\n  \"web_accessible_resources\": [\n    \"48.png\"\n  ]\n}\n"
  },
  {
    "path": "_archive/mv2/api/notifications/options.html",
    "content": "<!--\n  Copyright (c) 2012 The Chromium Authors. All rights reserved.\n  Use of this source code is governed by a BSD-style license that can be\n  found in the LICENSE file.\n\n  Brian Kennish <bkennish@chromium.org>\n\n  An option page for configuring notifications.\n-->\n<!doctype html>\n<html>\n  <head>\n    <title>Notification Demo</title>\n    <link href=\"style.css\" rel=\"stylesheet\" type=\"text/css\">\n    <script src=\"options.js\"></script>\n  </head>\n  <body>\n    <h1>\n      <img src=\"64.png\" alt=\"Toast\">\n      Notification Demo\n    </h1>\n    <h2>Options</h2>\n    <form id=\"options\">\n      <input type=\"checkbox\" name=\"isActivated\" checked>\n      Display a notification every\n      <select name=\"frequency\">\n        <option>1</option>\n        <option>2</option>\n        <option>3</option>\n        <option>4</option>\n        <option>5</option>\n        <option>10</option>\n        <option>15</option>\n        <option>20</option>\n        <option>25</option>\n        <option>30</option>\n      </select>\n      minute(s).\n    </form>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/notifications/options.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/*\n  Grays out or [whatever the opposite of graying out is called] the option\n  field.\n*/\nfunction ghost(isDeactivated) {\n  options.style.color = isDeactivated ? 'graytext' : 'black';\n                                              // The label color.\n  options.frequency.disabled = isDeactivated; // The control manipulability.\n}\n\nwindow.addEventListener('load', function() {\n  // Initialize the option controls.\n  options.isActivated.checked = JSON.parse(localStorage.isActivated);\n                                         // The display activation.\n  options.frequency.value = localStorage.frequency;\n                                         // The display frequency, in minutes.\n\n  if (!options.isActivated.checked) { ghost(true); }\n\n  // Set the display activation and frequency.\n  options.isActivated.onchange = function() {\n    localStorage.isActivated = options.isActivated.checked;\n    ghost(!options.isActivated.checked);\n  };\n\n  options.frequency.onchange = function() {\n    localStorage.frequency = options.frequency.value;\n  };\n});\n"
  },
  {
    "path": "_archive/mv2/api/notifications/style.css",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n/* Clone the look and feel of \"chrome://\" pages. */\nbody {\n  margin: 10px;\n  font: 84% Arial, sans-serif\n}\n\nh1 { font-size: 156% }\n\nh1 img {\n  margin: 1px 5px 0 1px;\n  vertical-align: middle\n}\n\nh2 {\n  border-top: 1px solid #9cc2ef;\n  background-color: #ebeff9;\n  padding: 3px 5px;\n  font-size: 100%\n}\n"
  },
  {
    "path": "_archive/mv2/api/omnibox/newtab_search/background.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// This event is fired with the user accepts the input in the omnibox.\nchrome.omnibox.onInputEntered.addListener(\n  function(text) {\n    // Encode user input for special characters , / ? : @ & = + $ #\n    var newURL = 'https://www.google.com/search?q=' + encodeURIComponent(text);\n    chrome.tabs.create({ url: newURL });\n  });\n"
  },
  {
    "path": "_archive/mv2/api/omnibox/newtab_search/manifest.json",
    "content": "{\n  \"name\": \"Omnibox New Tab Search\",\n  \"description\": \"Type 'nt' plus a search term into the Omnibox to open search in new tab.\",\n  \"version\": \"1.0\",\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"omnibox\": { \"keyword\" : \"nt\" },\n  \"manifest_version\": 2,\n  \"browser_action\": {\n    \"default_icon\": {\n      \"16\": \"newtab_search16.png\",\n      \"32\": \"newtab_search32.png\"\n      }\n  },\n  \"icons\": {\n    \"16\": \"newtab_search16.png\",\n    \"32\": \"newtab_search32.png\",\n    \"48\": \"newtab_search48.png\",\n    \"128\": \"newtab_search128.png\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/omnibox/simple-example/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\n// This event is fired each time the user updates the text in the omnibox,\n// as long as the extension's keyword mode is still active.\nchrome.omnibox.onInputChanged.addListener(\n  function(text, suggest) {\n    console.log('inputChanged: ' + text);\n    suggest([\n      {content: text + \" one\", description: \"the first one\"},\n      {content: text + \" number two\", description: \"the second entry\"}\n    ]);\n  });\n\n// This event is fired with the user accepts the input in the omnibox.\nchrome.omnibox.onInputEntered.addListener(\n  function(text) {\n    console.log('inputEntered: ' + text);\n    alert('You just typed \"' + text + '\"');\n  });\n"
  },
  {
    "path": "_archive/mv2/api/omnibox/simple-example/manifest.json",
    "content": "{\n  \"name\": \"Omnibox Example\",\n  \"description\" : \"To use, type 'omnix' plus a search term into the Omnibox.\",\n  \"version\": \"1.1\",\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"omnibox\": { \"keyword\" : \"omnix\" },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/override/blank_ntp/blank.html",
    "content": "<html>\n <head>\n  <title>Blank New Tab</title>\n  <style>\n  div {\n    color: #cccccc;\n    vertical-align: 50%;\n    text-align: center;\n    font-family: sans-serif;\n    font-size: 300%;\n  }\n  </style>\n </head>\n <body>\n  <div style=\"height:40%\"></div>\n  <div>Blank New Tab&trade;</div>\n </body>\n</html>\n\n"
  },
  {
    "path": "_archive/mv2/api/override/blank_ntp/manifest.json",
    "content": "{\n  \"name\": \"Blank new tab page\",\n  \"description\": \"Override the new tab page with a blank one\",\n  \"version\": \"0.2\",\n  \"incognito\": \"split\",\n  \"chrome_url_overrides\": {\n    \"newtab\": \"blank.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/override/override_igoogle/manifest.json",
    "content": "{\n  \"name\": \"iGoogle new tab page\",\n  \"description\": \"Override the new tab page with iGoogle\",\n  \"version\": \"0.2\",\n  \"chrome_url_overrides\": {\n    \"newtab\": \"redirect.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/override/override_igoogle/redirect.html",
    "content": "<head>\n<meta http-equiv=\"refresh\"content=\"0;URL=http://www.google.com/ig\">\n</head>\n"
  },
  {
    "path": "_archive/mv2/api/pageAction/pageaction_by_content/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Update the declarative rules on install or upgrade.\nchrome.runtime.onInstalled.addListener(function() {\n  chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {\n    chrome.declarativeContent.onPageChanged.addRules([{\n      conditions: [\n        // When a page contains a <video> tag...\n        new chrome.declarativeContent.PageStateMatcher({\n          css: [\"video\"]\n        })\n      ],\n      // ... show the page action.\n      actions: [new chrome.declarativeContent.ShowPageAction() ]\n    }]);\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/pageAction/pageaction_by_content/manifest.json",
    "content": "{\n  \"name\" : \"Page action by content\",\n  \"version\" : \"1.1\",\n  \"description\" : \"Shows a page action for HTML pages containing a video\",\n  \"background\" : {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"page_action\" :\n  {\n    \"default_icon\" : \"video-19.png\",\n    \"default_title\" : \"There's a <video> in this page!\"\n  },\n  \"permissions\": [ \"declarativeContent\" ],\n  \"icons\" : {\n    \"48\" : \"video-48.png\",\n    \"128\" : \"video-128.png\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/pageAction/pageaction_by_url/background.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// When the extension is installed or upgraded ...\nchrome.runtime.onInstalled.addListener(function() {\n  // Replace all rules ...\n  chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {\n    // With a new rule ...\n    chrome.declarativeContent.onPageChanged.addRules([\n      {\n        // That fires when a page's URL contains a 'g' ...\n        conditions: [\n          new chrome.declarativeContent.PageStateMatcher({\n            pageUrl: { urlContains: 'g' },\n          })\n        ],\n        // And shows the extension's page action.\n        actions: [ new chrome.declarativeContent.ShowPageAction() ]\n      }\n    ]);\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/pageAction/pageaction_by_url/manifest.json",
    "content": "{\n  \"name\": \"Page action by URL\",\n  \"version\": \"1.0\",\n  \"description\": \"Shows a page action for urls which have the letter 'g' in them.\",\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"page_action\" :\n  {\n    \"default_icon\" : \"icon-19.png\",\n    \"default_title\" : \"There's a 'G' in this URL!\"\n  },\n  \"permissions\" : [\n    \"declarativeContent\"\n  ],\n  \"icons\" : {\n    \"48\" : \"icon-48.png\",\n    \"128\" : \"icon-128.png\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/pageAction/set_icon/background.html",
    "content": "<html>\n<head>\n<script src=\"background.js\"></script>\n</head>\n<body>\n<canvas id=\"canvas\" width=\"19\" height=\"19\"></canvas>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/pageAction/set_icon/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar lastTabId = 0;\nvar tab_clicks = {};\n\nchrome.tabs.onSelectionChanged.addListener(function(tabId) {\n  lastTabId = tabId;\n  chrome.pageAction.show(lastTabId);\n});\n\nchrome.tabs.query({active: true, currentWindow: true}, function(tabs) {\n  lastTabId = tabs[0].id;\n  chrome.pageAction.show(lastTabId);\n});\n\n// Called when the user clicks on the page action.\nchrome.pageAction.onClicked.addListener(function(tab) {\n  var clicks = tab_clicks[tab.id] || 0;\n  chrome.pageAction.setIcon({path: \"icon\" + (clicks + 1) + \".png\",\n                             tabId: tab.id});\n  if (clicks % 2) {\n    chrome.pageAction.show(tab.id);\n  } else {\n    chrome.pageAction.hide(tab.id);\n    setTimeout(function() { chrome.pageAction.show(tab.id); }, 200);\n  }\n  chrome.pageAction.setTitle({title: \"click:\" + clicks, tabId: tab.id});\n\n  // We only have 2 icons, but cycle through 3 icons to test the\n  // out-of-bounds index bug.\n  clicks++;\n  if (clicks > 3)\n    clicks = 0;\n  tab_clicks[tab.id] = clicks;\n});\n\nvar i = 0;\nwindow.setInterval(function() {\n  var clicks = tab_clicks[lastTabId] || 0;\n\n  // Don't animate while in \"click\" mode.\n  if (clicks > 0) return;\n\n  // Don't do anything if we don't have a tab yet.\n  if (lastTabId == 0) return;\n\n  i++;\n  chrome.pageAction.setIcon({imageData: draw(i*2, i*4), tabId: lastTabId});\n}, 50);\n\nfunction draw(starty, startx) {\n  var canvas = document.getElementById('canvas');\n  var context = canvas.getContext('2d');\n  context.clearRect(0, 0, canvas.width, canvas.height);\n  context.fillStyle = \"rgba(0,200,0,255)\";\n  context.fillRect(startx % 19, starty % 19, 8, 8);\n  context.fillStyle = \"rgba(0,0,200,255)\";\n  context.fillRect((startx + 5) % 19, (starty + 5) % 19, 8, 8);\n  context.fillStyle = \"rgba(200,0,0,255)\";\n  context.fillRect((startx + 10) % 19, (starty + 10) % 19, 8, 8);\n  return context.getImageData(0, 0, 19, 19);\n}\n"
  },
  {
    "path": "_archive/mv2/api/pageAction/set_icon/manifest.json",
    "content": "{\n  \"name\": \"Animated Page Action\",\n  \"description\": \"This extension adds an animated browser action to the toolbar.\",\n  \"version\": \"1.2\",\n  \"background\": {\n    \"page\": \"background.html\"\n  },\n  \"page_action\": {\n    \"default_title\": \"First icon\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/permissions/extension-questions/manifest.json",
    "content": "{\n  \"name\": \"Top Chrome Extension Questions\",\n  \"version\": \"0.3\",\n  \"description\": \"Sample demonstration of the optional permissions API.\",\n  \"icons\": {\n    \"128\": \"images/icon.png\",\n    \"48\": \"images/icon.png\",\n    \"16\": \"images/icon.png\"\n  },\n  \"browser_action\": {\n    \"default_icon\": \"images/icon.png\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"options_page\": \"options.html\",\n  \"optional_permissions\": [\"http://api.stackoverflow.com/\"],\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/permissions/extension-questions/options.html",
    "content": "<!doctype html>\n<head>\n  <style>\n    #status { font-weight: bold; }\n  </style>\n</head>\n<body>\n  <button id=\"enable\">Grant Permission</button>\n  <button id=\"disable\">Revoke Permission</button>\n  <p>\n  Stack Overflow permission status: <span id=\"status\"></span>\n  <script src=\"options.js\"></script>\n  </p>\n</body>\n"
  },
  {
    "path": "_archive/mv2/api/permissions/extension-questions/options.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar PERMISSIONS = {origins: ['http://api.stackoverflow.com/']};\nvar YES = 'ENABLED';\nvar NO = 'DISABLED';\n\nvar $status = document.querySelector('#status');\nchrome.permissions.onAdded.addListener(function(permissions) {\n  $status.innerText = YES;\n});\nchrome.permissions.onRemoved.addListener(function(permissions) {\n  $status.innerText = NO;\n});\nchrome.permissions.contains(PERMISSIONS, function(contains) {\n  $status.innerText = contains ? YES : NO;\n});\n\ndocument.querySelector('button#enable').addEventListener('click', function() {\n  chrome.permissions.contains(PERMISSIONS, function(allowed) {\n    if (allowed) {\n      alert('You already have SO host permission!');\n    } else {\n      chrome.permissions.request(PERMISSIONS, function(result) {\n        if (result) {\n          console.log('SO host permission granted!' +\n                      'Open the browser action again.');\n        }\n      });\n    }\n  });\n});\n\ndocument.querySelector('button#disable').addEventListener('click', function() {\n  chrome.permissions.contains(PERMISSIONS, function(allowed) {\n    if (allowed) {\n      chrome.permissions.remove(PERMISSIONS, function(result) {\n        console.log('Revoked SO host permission.');\n      });\n    } else {\n      alert('No SO host permission found.');\n    }\n  });\n});\n\n"
  },
  {
    "path": "_archive/mv2/api/permissions/extension-questions/popup.html",
    "content": "<!doctype html>\n<head>\n  <style>\n    body { width: 300px; }\n  </style>\n</head>\n<body>\n  <h3 id=\"title\"></h3>\n  <ul id=\"results\"></ul>\n  <script src=\"popup.js\"></script>\n</body>\n"
  },
  {
    "path": "_archive/mv2/api/permissions/extension-questions/popup.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar PERMISSIONS = {origins: ['http://api.stackoverflow.com/']};\nvar URL = 'http://api.stackoverflow.com/1.1/questions?max=10&sort=votes&tagged=google-chrome-extension';\nvar ROOT = 'http://stackoverflow.com';\n\nchrome.permissions.contains(PERMISSIONS, function(result) {\n  if (!result) {\n    // Open options page to request permissions.\n    document.querySelector('#title').innerText =\n        'Requires Stack Overflow permission';\n    chrome.tabs.create({url: 'options.html'});\n  } else {\n    // Make the request to SO.\n    makeRequest(function(data) {\n      // Render the results.\n      renderQuestions(JSON.parse(data));\n    });\n  }\n});\n\nfunction makeRequest(callback) {\n  var xhr = new XMLHttpRequest();\n  xhr.open('GET', URL);\n  xhr.addEventListener('load', function(e) {\n    var result = xhr.responseText;\n    callback(result);\n  });\n  xhr.send();\n}\n\nfunction renderQuestions(data) {\n  var $results = document.querySelector('#results');\n  var questions = data.questions;\n  for (var i = 0; i < Math.min(10, questions.length); i++) {\n    var question = questions[i];\n    var $question = document.createElement('li');\n    var url = ROOT + question.question_answers_url;\n    $question.innerHTML = '<a href=\"' + url + '\" target=\"_blank\">' +\n        question.title + '</a>';\n    results.appendChild($question);\n  }\n  // Update title too.\n  document.querySelector('#title').innerText = 'Top Chrome Extension Questions';\n}\n"
  },
  {
    "path": "_archive/mv2/api/power/_locales/en/messages.json",
    "content": "{\n  \"extensionName\": {\n    \"message\": \"Keep Awake\",\n    \"description\": \"Extension name.\"\n  },\n  \"extensionDescription\": {\n    \"message\": \"Override system power-saving settings.\",\n    \"description\": \"Extension description.\"\n  },\n  \"disabledTitle\": {\n    \"message\": \"Default power-saving settings\",\n    \"description\": \"Browser action title when disabled.\"\n  },\n  \"displayTitle\": {\n    \"message\": \"Screen will be kept on\",\n    \"description\": \"Browser action title when preventing screen-off.\"\n  },\n  \"systemTitle\": {\n    \"message\": \"System will stay awake\",\n    \"description\": \"Browser action title when preventing system sleep.\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/power/background.js",
    "content": "// Copyright (c) 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * States that the extension can be in.\n */\nvar StateEnum = {\n  DISABLED: 'disabled',\n  DISPLAY: 'display',\n  SYSTEM: 'system'\n};\n\n/**\n * Key used for storing the current state in {localStorage}.\n */\nvar STATE_KEY = 'state';\n\n/**\n * Loads the locally-saved state asynchronously.\n * @param {function} callback Callback invoked with the loaded {StateEnum}.\n */\nfunction loadSavedState(callback) {\n  chrome.storage.local.get(STATE_KEY, function(items) {\n    var savedState = items[STATE_KEY];\n    for (var key in StateEnum) {\n      if (savedState == StateEnum[key]) {\n        callback(savedState);\n        return;\n      }\n    }\n    callback(StateEnum.DISABLED);\n  });\n}\n\n/**\n * Switches to a new state.\n * @param {string} newState New {StateEnum} to use.\n */\nfunction setState(newState) {\n  var imagePrefix = 'night';\n  var title = '';\n\n  switch (newState) {\n    case StateEnum.DISABLED:\n      chrome.power.releaseKeepAwake();\n      imagePrefix = 'night';\n      title = chrome.i18n.getMessage('disabledTitle');\n      break;\n    case StateEnum.DISPLAY:\n      chrome.power.requestKeepAwake('display');\n      imagePrefix = 'day';\n      title = chrome.i18n.getMessage('displayTitle');\n      break;\n    case StateEnum.SYSTEM:\n      chrome.power.requestKeepAwake('system');\n      imagePrefix = 'sunset';\n      title = chrome.i18n.getMessage('systemTitle');\n      break;\n    default:\n      throw 'Invalid state \"' + newState + '\"';\n  }\n\n  var items = {};\n  items[STATE_KEY] = newState;\n  chrome.storage.local.set(items);\n\n  chrome.browserAction.setIcon({\n    path: {\n      '19': 'images/' + imagePrefix + '-19.png',\n      '38': 'images/' + imagePrefix + '-38.png'\n    }\n  });\n  chrome.browserAction.setTitle({title: title});\n}\n\nchrome.browserAction.onClicked.addListener(function() {\n  loadSavedState(function(state) {\n    switch (state) {\n      case StateEnum.DISABLED:\n        setState(StateEnum.DISPLAY);\n        break;\n      case StateEnum.DISPLAY:\n        setState(StateEnum.SYSTEM);\n        break;\n      case StateEnum.SYSTEM:\n        setState(StateEnum.DISABLED);\n        break;\n      default:\n        throw 'Invalid state \"' + state + '\"';\n    }\n  });\n});\n\nchrome.runtime.onStartup.addListener(function() {\n  loadSavedState(function(state) { setState(state); });\n});\n\nchrome.runtime.onInstalled.addListener(function(details) {\n  loadSavedState(function(state) { setState(state); });\n});\n"
  },
  {
    "path": "_archive/mv2/api/power/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n\n  \"name\": \"__MSG_extensionName__\",\n  \"description\": \"__MSG_extensionDescription__\",\n  \"version\": \"1.9\",\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"48\": \"images/icon-48.png\",\n    \"128\": \"images/icon-128.png\"\n  },\n\n  \"permissions\": [\n    \"power\",\n    \"storage\"\n  ],\n  \"browser_action\": {\n    \"default_title\": \"__MSG_disabledTitle__\",\n    \"default_icon\": {\n      \"19\": \"images/night-19.png\",\n      \"38\": \"images/night-38.png\"\n    }\n  },\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n\n  \"default_locale\": \"en\"\n}\n"
  },
  {
    "path": "_archive/mv2/api/preferences/allowThirdPartyCookies/manifest.json",
    "content": "{\n  \"name\" : \"Block/allow third-party cookies API example extension\",\n  \"version\" : \"0.1\",\n  \"description\" : \"Sample extension which demonstrates how to access a preference.\",\n  \"permissions\": [ \"privacy\" ],\n  \"browser_action\": {\n     \"default_icon\": \"advicedog.jpg\",\n     \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/preferences/allowThirdPartyCookies/popup.css",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#container {\n  width: 300px;\n}\n\n#incognito {\n  display: none;\n}\n"
  },
  {
    "path": "_archive/mv2/api/preferences/allowThirdPartyCookies/popup.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <link href=\"popup.css\" rel=\"stylesheet\" type=\"text/css\">\n  <script src=\"popup.js\"></script>\n</head>\n<body>\n\n<div id=\"container\">\n  <input type=\"checkbox\" id=\"regularValue\" />\n  Allow third-party sites to set cookies\n  <div id=\"incognito\">\n    <input type=\"checkbox\" id=\"useSeparateIncognitoSettings\" />\n    Use separate setting for incognito mode:\n    <br>\n    <input type=\"checkbox\" id=\"incognitoValue\" disabled=\"disabled\"/>\n    Allow third-party sites to set cookies in incognito sessions\n  </div>\n  <div id=\"incognito-forbidden\">\n    Select \"Allow in incognito\" to access incognito preferences\n  </div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/preferences/allowThirdPartyCookies/popup.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n\nvar pref = chrome.privacy.websites.thirdPartyCookiesAllowed;\n\nfunction $(id) {\n  return document.getElementById(id);\n}\n\n/**\n * Returns whether the |levelOfControl| means that the extension can change the\n * preference value.\n *\n * @param levelOfControl{string}\n */\nfunction settingIsControllable(levelOfControl) {\n  return (levelOfControl == 'controllable_by_this_extension' ||\n          levelOfControl == 'controlled_by_this_extension');\n}\n\n/**\n * Updates the UI to reflect the state of the preference.\n *\n * @param settings{object} A settings object, as returned from |get()| or the\n * |onchange| event.\n */\nfunction updateUI(settings) {\n  var disableUI = !settingIsControllable(settings.levelOfControl);\n  document.getElementById('regularValue').disabled = disableUI;\n  document.getElementById('useSeparateIncognitoSettings').disabled = disableUI;\n  if (settings.hasOwnProperty('incognitoSpecific')) {\n    var hasIncognitoValue = settings.incognitoSpecific;\n    document.getElementById('useSeparateIncognitoSettings').checked =\n        hasIncognitoValue;\n    document.getElementById('incognitoValue').disabled =\n        disableUI || !hasIncognitoValue;\n    document.getElementById('incognitoValue').checked = settings.value;\n  } else {\n    document.getElementById('regularValue').checked = settings.value;\n  }\n}\n\n/**\n * Wrapper for |updateUI| which is used as callback for the |get()| method and\n * which logs the result.\n * If there was an error getting the preference, does nothing.\n *\n * @param settings{object} A settings object, as returned from |get()|.\n */\nfunction updateUIFromGet(settings) {\n  if (settings) {\n    console.log('pref.get result:' + JSON.stringify(settings));\n    updateUI(settings);\n  }\n}\n\n/**\n * Wrapper for |updateUI| which is used as handler for the |onchange| event\n * and which logs the result.\n *\n * @param settings{object} A settings object, as returned from the |onchange|\n * event.\n */\nfunction updateUIFromOnChange(settings) {\n  console.log('pref.onChange event:' + JSON.stringify(settings));\n  updateUI(settings);\n}\n\n/*\n * Initializes the UI.\n */\nfunction init() {\n  chrome.extension.isAllowedIncognitoAccess(function(allowed) {\n    if (allowed) {\n      pref.get({'incognito': true}, updateUIFromGet);\n      $('incognito').style.display = 'block';\n      $('incognito-forbidden').style.display = 'none';\n    }\n  });\n  pref.get({}, updateUIFromGet);\n  pref.onChange.addListener(updateUIFromOnChange);\n\n  $('regularValue').addEventListener('click', function () {\n    setPrefValue(this.checked, false);\n  });\n  $('useSeparateIncognitoSettings').addEventListener('click', function () {\n     setUseSeparateIncognitoSettings(this.checked);\n  });\n  $('incognitoValue').addEventListener('click', function () {\n    setPrefValue(this.checked, true);\n  });\n}\n\n/**\n * Called from the UI to change the preference value.\n *\n * @param enabled{boolean} The new preference value.\n * @param incognito{boolean} Whether the value is specific to incognito mode.\n */\nfunction setPrefValue(enabled, incognito) {\n  var scope = incognito ? 'incognito_session_only' : 'regular';\n  pref.set({'value': enabled, 'scope': scope});\n}\n\n/**\n * Called from the UI to change whether to use separate settings for\n * incognito mode.\n *\n * @param value{boolean} whether to use separate settings for\n * incognito mode.\n */\nfunction setUseSeparateIncognitoSettings(value) {\n  if (!value) {\n    pref.clear({'incognito': true});\n  } else {\n    // Explicitly set the value for incognito mode.\n    pref.get({'incognito': true}, function(settings) {\n      pref.set({'incognito': true, 'value': settings.value});\n    });\n  }\n  document.getElementById('incognitoValue').disabled = !value;\n}\n\n// Call `init` to kick things off.\ndocument.addEventListener('DOMContentLoaded', init);\n"
  },
  {
    "path": "_archive/mv2/api/preferences/enableReferrer/manifest.json",
    "content": "{\n  \"name\" : \"Block/allow referrer API example extension\",\n  \"version\" : \"0.1\",\n  \"description\" : \"Sample extension which demonstrates how to access a preference.\",\n  \"permissions\": [ \"privacy\" ],\n  \"browser_action\": {\n     \"default_icon\": \"advicedog.jpg\",\n     \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/preferences/enableReferrer/popup.css",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#container {\n  width: 300px;\n}\n\n#incognito {\n  display: none;\n}\n"
  },
  {
    "path": "_archive/mv2/api/preferences/enableReferrer/popup.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <link href=\"popup.css\" rel=\"stylesheet\" type=\"text/css\">\n  <script src=\"popup.js\"></script>\n</head>\n<body>\n\n<div id=\"container\">\n  <input type=\"checkbox\" id=\"regularValue\" />\n  Enable referrers\n  <div id=\"incognito\">\n    <input type=\"checkbox\" id=\"useSeparateIncognitoSettings\" />\n    Use separate setting for incognito mode:\n    <br>\n    <input type=\"checkbox\" id=\"incognitoValue\" disabled=\"disabled\"/>\n    Enable referrers in incognito sessions\n  </div>\n  <div id=\"incognito-forbidden\">\n    Select \"Allow in incognito\" to access incognito preferences\n  </div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/preferences/enableReferrer/popup.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n\nvar pref = chrome.privacy.websites.referrersEnabled;\n\nfunction $(id) {\n  return document.getElementById(id);\n}\n\n/**\n * Returns whether the |levelOfControl| means that the extension can change the\n * preference value.\n *\n * @param levelOfControl{string}\n */\nfunction settingIsControllable(levelOfControl) {\n  return (levelOfControl == 'controllable_by_this_extension' ||\n          levelOfControl == 'controlled_by_this_extension');\n}\n\n/**\n * Updates the UI to reflect the state of the preference.\n *\n * @param settings{object} A settings object, as returned from |get()| or the\n * |onchange| event.\n */\nfunction updateUI(settings) {\n  var disableUI = !settingIsControllable(settings.levelOfControl);\n  document.getElementById('regularValue').disabled = disableUI;\n  document.getElementById('useSeparateIncognitoSettings').disabled = disableUI;\n  if (settings.hasOwnProperty('incognitoSpecific')) {\n    var hasIncognitoValue = settings.incognitoSpecific;\n    document.getElementById('useSeparateIncognitoSettings').checked =\n        hasIncognitoValue;\n    document.getElementById('incognitoValue').disabled =\n        disableUI || !hasIncognitoValue;\n    document.getElementById('incognitoValue').checked = settings.value;\n  } else {\n    document.getElementById('regularValue').checked = settings.value;\n  }\n}\n\n/**\n * Wrapper for |updateUI| which is used as callback for the |get()| method and\n * which logs the result.\n * If there was an error getting the preference, does nothing.\n *\n * @param settings{object} A settings object, as returned from |get()|.\n */\nfunction updateUIFromGet(settings) {\n  if (settings) {\n    console.log('pref.get result:' + JSON.stringify(settings));\n    updateUI(settings);\n  }\n}\n\n/**\n * Wrapper for |updateUI| which is used as handler for the |onchange| event\n * and which logs the result.\n *\n * @param settings{object} A settings object, as returned from the |onchange|\n * event.\n */\nfunction updateUIFromOnChange(settings) {\n  console.log('pref.onChange event:' + JSON.stringify(settings));\n  updateUI(settings);\n}\n\n/*\n * Initializes the UI.\n */\nfunction init() {\n  chrome.extension.isAllowedIncognitoAccess(function(allowed) {\n    if (allowed) {\n      pref.get({'incognito': true}, updateUIFromGet);\n      $('incognito').style.display = 'block';\n      $('incognito-forbidden').style.display = 'none';\n    }\n  });\n  pref.get({}, updateUIFromGet);\n  pref.onChange.addListener(updateUIFromOnChange);\n\n  $('regularValue').addEventListener('click', function () {\n    setPrefValue(this.checked, false);\n  });\n  $('useSeparateIncognitoSettings').addEventListener('click', function () {\n     setUseSeparateIncognitoSettings(this.checked);\n  });\n  $('incognitoValue').addEventListener('click', function () {\n    setPrefValue(this.checked, true);\n  });\n}\n\n/**\n * Called from the UI to change the preference value.\n *\n * @param enabled{boolean} The new preference value.\n * @param incognito{boolean} Whether the value is specific to incognito mode.\n */\nfunction setPrefValue(enabled, incognito) {\n  var scope = incognito ? 'incognito_session_only' : 'regular';\n  pref.set({'value': enabled, 'scope': scope});\n}\n\n/**\n * Called from the UI to change whether to use separate settings for\n * incognito mode.\n *\n * @param value{boolean} whether to use separate settings for\n * incognito mode.\n */\nfunction setUseSeparateIncognitoSettings(value) {\n  if (!value) {\n    pref.clear({'incognito': true});\n  } else {\n    // Explicitly set the value for incognito mode.\n    pref.get({'incognito': true}, function(settings) {\n      pref.set({'incognito': true, 'value': settings.value});\n    });\n  }\n  document.getElementById('incognitoValue').disabled = !value;\n}\n\n// Call `init` to kick things off.\ndocument.addEventListener('DOMContentLoaded', init);\n"
  },
  {
    "path": "_archive/mv2/api/printing/manifest.json",
    "content": "{\n  \"name\": \"Print Extension\",\n  \"version\": \"1.0\",\n  \"description\": \"Sends print job directly to the printers installed on the Chromebook\",\n  \"permissions\": [\n    \"printing\"\n  ],\n  \"browser_action\": {\n    \"default_popup\": \"printers.html\",\n    \"default_icon\": \"icons/icon.png\"\n  },\n  \"icons\": {\n    \"16\": \"icons/icon16.png\",\n    \"48\": \"icons/icon48.png\",\n    \"128\": \"icons/icon128.png\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/printing/printers.css",
    "content": "/**\n * Copyright 2020 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\ntable, th, td, tr {\n  border: 1px solid black;\n}\n\ntable {\n  width: 100%;\n  border-collapse: collapse;\n}\n\ndiv {\n  overflow: auto;\n}\n"
  },
  {
    "path": "_archive/mv2/api/printing/printers.html",
    "content": "<!--\n * Copyright 2020 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n<!DOCTYPE HTML>\n<html>\n  <head>\n    <title>Printers</title>\n    <link href=\"printers.css\" rel=\"stylesheet\" type=\"text/css\">\n    <script src=\"printers.js\"></script>\n  </head>\n\n  <body>\n    <h2>Printers:</h2>\n    <div id=\"printers\">\n      <table id=\"printersTable\">\n        <thead>\n          <tr>\n            <th>Id</th>\n            <th>Name</th>\n            <th>Description</th>\n            <th>URI</th>\n            <th>Source</th>\n            <th>Default</th>\n            <th>Recently used</th>\n            <th>Capabilities</th>\n            <th>Status</th>\n            <th>Print</th>\n          </tr>\n        </thead>\n      </table>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/printing/printers.js",
    "content": "// Copyright 2020 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction onPrintButtonClicked(printerId, dpi) {\n  var ticket = {\n    version: '1.0',\n    print: {\n      color: {type: 'STANDARD_MONOCHROME'},\n      duplex: {type: 'NO_DUPLEX'},\n      page_orientation: {type: 'LANDSCAPE'},\n      copies: {copies: 1},\n      dpi: {horizontal_dpi: dpi.horizontal_dpi, vertical_dpi: dpi.vertical_dpi},\n      media_size: {\n        width_microns: 210000,\n        height_microns: 297000,\n        vendor_id: 'iso_a4_210x297mm'\n      },\n      collate: {collate: false}\n    }\n  };\n\n  fetch('test.pdf')\n      .then(response => response.arrayBuffer())\n      .then(arrayBuffer => {\n        const request = {\n          job: {\n            printerId: printerId,\n            title: 'test job',\n            ticket: ticket,\n            contentType: 'application/pdf',\n            document: new Blob(\n                [new Uint8Array(arrayBuffer)], {type: 'application/pdf'})\n          }\n        };\n        chrome.printing.submitJob(request, (response) => {\n          if (response !== undefined) {\n            console.log(response.status);\n          }\n          if (chrome.runtime.lastError !== undefined) {\n            console.log(chrome.runtime.lastError.message);\n          }\n        });\n      });\n}\n\nfunction createPrintButton(onClicked) {\n  const button = document.createElement('button');\n  button.innerHTML = 'Print';\n  button.onclick = onClicked;\n  return button;\n}\n\nfunction createPrintersTable() {\n  chrome.printing.getPrinters(function(printers) {\n    const tbody = document.createElement('tbody');\n\n    for (let i = 0; i < printers.length; ++i) {\n      const printer = printers[i];\n      chrome.printing.getPrinterInfo(printer.id, function(response) {\n        const columnValues = [\n          printer.id,\n          printer.name,\n          printer.description,\n          printer.uri,\n          printer.source,\n          printer.isDefault,\n          printer.recentlyUsedRank,\n          JSON.stringify(response.capabilities),\n          response.status,\n        ];\n\n        let tr = document.createElement('tr');\n        for (const columnValue of columnValues) {\n          const td = document.createElement('td');\n          td.appendChild(document.createTextNode(columnValue));\n          td.setAttribute('align', 'center');\n          tr.appendChild(td);\n        }\n\n        const printTd = document.createElement('td');\n        printTd.appendChild(createPrintButton(function() {\n          onPrintButtonClicked(\n              printer.id, response.capabilities.printer.dpi.option[0]);\n        }));\n        tr.appendChild(printTd);\n\n        tbody.appendChild(tr);\n      });\n    }\n\n    const table = document.getElementById('printersTable');\n    table.appendChild(tbody);\n  });\n}\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  createPrintersTable();\n});\n"
  },
  {
    "path": "_archive/mv2/api/printingMetrics/background.js",
    "content": "// Copyright 2019 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.printingMetrics.onPrintJobFinished.addListener(function(printJob) {\n  chrome.storage.local.get('printJobs', function(result) {\n    let printJobs = result.printJobs || 0;\n    printJobs++;\n    chrome.browserAction.setBadgeText({text: printJobs.toString()});\n    chrome.storage.local.set({printJobs: printJobs});\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/printingMetrics/manifest.json",
    "content": "{\n  \"name\": \"Print Job History\",\n  \"version\": \"1.0\",\n  \"description\": \"Reads your print history and displays the recent print jobs.\",\n  \"permissions\": [\n    \"printingMetrics\",\n    \"storage\"\n  ],\n  \"browser_action\": {\n    \"default_popup\": \"print_jobs.html\",\n    \"default_icon\": \"print.png\"\n  },\n  \"background\": {\n    \"scripts\": [\n      \"background.js\"\n    ],\n    \"persistent\": false\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/printingMetrics/print_jobs.css",
    "content": "/**\n * Copyright 2019 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\ntable, th, td, tr {\n  border: 1px solid black;\n}\n\ntable {\n  width: 100%;\n  border-collapse: collapse;\n}\n\ndiv {\n  overflow: auto;\n}\n"
  },
  {
    "path": "_archive/mv2/api/printingMetrics/print_jobs.html",
    "content": "<!--\n * Copyright 2019 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n<!DOCTYPE HTML>\n<html>\n  <head>\n    <title>Recent print jobs</title>\n    <link href=\"print_jobs.css\" rel=\"stylesheet\" type=\"text/css\">\n    <script src=\"print_jobs.js\"></script>\n  </head>\n\n  <body>\n    <h2>Recent print jobs:</h2>\n    <div id=\"printJobs\">\n      <table id=\"printJobsTable\">\n        <thead>\n          <tr>\n            <th rowspan=\"2\">Title</th>\n            <th rowspan=\"2\">Status</th>\n            <th rowspan=\"2\">Time</th>\n            <th rowspan=\"2\">Number of pages</th>\n            <th colspan=\"3\">Printer</th>\n            <th colspan=\"5\">Settings</th>\n          </tr>\n          <tr>\n            <th>Name</th>\n            <th>URI</th>\n            <th>Source</th>\n            <th>Color</th>\n            <th>Duplex</th>\n            <th>Paper width</th>\n            <th>Paper height</th>\n            <th>Copies</th>\n          </tr>\n        </thead>\n      </table>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/printingMetrics/print_jobs.js",
    "content": "// Copyright 2019 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction showPrintJobTable() {\n  chrome.printingMetrics.getPrintJobs(function(printJobs) {\n    const tbody = document.createElement('tbody');\n\n    for (let i = 0; i < printJobs.length; ++i) {\n      const columnValues = [\n        printJobs[i].title, printJobs[i].status,\n        new Date(printJobs[i].completionTime), printJobs[i].numberOfPages,\n        printJobs[i].printer.name, printJobs[i].printer.uri,\n        printJobs[i].printer.source, printJobs[i].settings.color,\n        printJobs[i].settings.duplex, printJobs[i].settings.mediaSize.width,\n        printJobs[i].settings.mediaSize.height, printJobs[i].settings.copies\n      ];\n\n      let tr = document.createElement('tr');\n      for (columnValue of columnValues) {\n        const td = document.createElement('td');\n        td.appendChild(document.createTextNode(columnValue));\n        td.setAttribute('align', 'center');\n        tr.appendChild(td);\n      }\n      tbody.appendChild(tr);\n    }\n\n    const table = document.getElementById('printJobsTable');\n    table.appendChild(tbody);\n  });\n}\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  showPrintJobTable();\n});\n"
  },
  {
    "path": "_archive/mv2/api/processes/process_monitor/manifest.json",
    "content": "{\n  \"name\": \"Process Monitor\",\n  \"version\": \"1.2\",\n  \"description\": \"Adds a browser action that monitors resource usage of all browser processes.\",\n  \"permissions\": [\n    \"processes\"\n  ],\n  \"browser_action\": {\n      \"default_title\": \"Process Monitor\",\n      \"default_icon\": \"icon.png\",\n      \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/processes/process_monitor/popup.html",
    "content": "<html>\n<head>\n<script src=\"popup.js\"></script>\n<style>\nbody {\n  overflow: hidden;\n  margin: 0px;\n  padding: 0px;\n  background: white;\n}\n\ndiv:first-child {\n  margin-top: 0px;\n}\n\ndiv, td {\n  padding: 1px 3px;\n  font-family: sans-serif;\n  font-size: 10pt;\n  margin-top: 1px;\n  white-space: nowrap;\n}\n</style>\n</head>\n<body>\n<div id=\"title\"><b>Process Monitor</b></div>\n<div id=\"process-list\"><i>Loading...</i></div>\n<div id=\"buttons\">\n  <input type=\"button\" value=\"End Process\" id=\"killProcess\" />\n</div>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/processes/process_monitor/popup.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Shows an updating list of process statistics.\nfunction init() {\n  chrome.processes.onUpdatedWithMemory.addListener(\n    function(processes) {\n      var table = \"<table>\\n\" +\n        \"<tr><td><b>Process</b></td>\" +\n        \"<td>OS ID</td>\" +\n        \"<td>Title</td>\" +\n        \"<td>Type</td>\" +\n        \"<td>Tabs</td>\" +\n        \"<td>CPU</td>\" +\n        \"<td>Network</td>\" +\n        \"<td>Private Memory</td>\" +\n        \"<td>JS Memory</td>\" +\n        \"<td></td>\" +\n        \"</tr>\\n\";\n      for (pid in processes) {\n        table = displayProcessInfo(processes[pid], table);\n      }\n      table += \"</table>\\n\";\n      var div = document.getElementById(\"process-list\");\n      div.innerHTML = table;\n    });\n\n  document.getElementById(\"killProcess\").onclick = function () {\n    var procId = parseInt(prompt(\"Enter process ID\"));\n    chrome.processes.terminate(procId);\n  }\n}\n\nfunction displayProcessInfo(process, table) {\n  // Format network string like task manager\n  var network = process.network;\n  if (network > 1024) {\n    network = (network / 1024).toFixed(1) + \" kB/s\";\n  } else if (network > 0) {\n    network += \" B/s\";\n  } else if (network == -1) {\n    network = \"N/A\";\n  }\n\n  table +=\n    \"<tr><td>\" + process.id + \"</td>\" +\n    \"<td>\" + process.osProcessId + \"</td>\" +\n    \"<td>\" + process.title + \"</td>\" +\n    \"<td>\" + process.type + \"</td>\" +\n    \"<td>\" + process.tabs + \"</td>\" +\n    \"<td>\" + process.cpu + \"</td>\" +\n    \"<td>\" + network + \"</td>\";\n\n  if (\"privateMemory\" in process) {\n    table += \"<td>\" + (process.privateMemory / 1024) + \"K</td>\";\n  } else {\n    table += \"<td>N/A</td>\";\n  }\n  if (\"jsMemoryAllocated\" in process) {\n    var allocated = process.jsMemoryAllocated / 1024;\n    var used = process.jsMemoryUsed / 1024;\n    table += \"<td>\" + allocated.toFixed(2) + \"K (\" + used.toFixed(2) +\n        \"K live)</td>\";\n  } else {\n    table += \"<td>N/A</td>\";\n  }\n\n  table +=\n    \"<td></td>\" +\n    \"</tr>\\n\";\n  return table;\n}\n\ndocument.addEventListener('DOMContentLoaded', init);\n"
  },
  {
    "path": "_archive/mv2/api/processes/show_tabs/manifest.json",
    "content": "{\n  \"name\": \"Show Tabs in Process\",\n  \"version\": \"1.0\",\n  \"description\": \"Adds a browser action showing which tabs share the current tab's process.\",\n  \"permissions\": [\n    \"processes\", \"tabs\", \"chrome://favicon/*\"\n  ],\n  \"browser_action\": {\n      \"default_title\": \"Show Tabs in this Process\",\n      \"default_icon\": \"icon.png\",\n      \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/processes/show_tabs/popup.css",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nbody {\n  overflow: hidden;\n  margin: 0px;\n  padding: 0px;\n  background: white;\n  width: 400px;\n}\n\ndiv:first-child {\n  margin-top: 0px;\n}\n\ndiv {\n  padding: 1px 3px;\n  font-family: sans-serif;\n  font-size: 10pt;\n  width: 400px;\n  margin-top: 1px;\n}\n"
  },
  {
    "path": "_archive/mv2/api/processes/show_tabs/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Popup</title>\n    <link href=\"popup.css\" rel=\"stylesheet\" type=\"text/css\">\n    <script src=\"popup.js\"></script>\n  </head>\n  <body>\n    <div id=\"title\"></div>\n    <div id=\"tab-list\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/processes/show_tabs/popup.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Show a list of all tabs in the same process as this one.\nfunction init() {\n  chrome.windows.getCurrent({populate: true}, function(currentWindow) {\n    chrome.tabs.query({currentWindow: true, active: true}, function(tabs) {\n      var current = currentWindow.tabs.filter(function(tab) {\n        return tab.active;\n      })[0];\n      chrome.processes.getProcessIdForTab(current.id,\n        function(pid) {\n          var outputDiv = document.getElementById(\"tab-list\");\n          var titleDiv = document.getElementById(\"title\");\n          titleDiv.innerHTML = \"<b>Tabs in Process \" + pid + \":</b>\";\n          displayTabInfo(currentWindow.id, current, outputDiv);\n          displaySameProcessTabs(current, pid, outputDiv);\n        }\n      );\n\n    });\n  });\n}\n\nfunction displaySameProcessTabs(selectedTab, processId, outputDiv) {\n  // Loop over all windows and their tabs\n  var tabs = [];\n  chrome.windows.getAll({ populate: true }, function(windowList) {\n    for (var i = 0; i < windowList.length; i++) {\n      for (var j = 0; j < windowList[i].tabs.length; j++) {\n        var tab = windowList[i].tabs[j];\n        if (tab.id != selectedTab.id) {\n          tabs.push(tab);\n        }\n      }\n    }\n\n    // Display tab in list if it is in the same process\n    tabs.forEach(function(tab) {\n      chrome.processes.getProcessIdForTab(tab.id,\n        function(pid) {\n          if (pid == processId) {\n            displayTabInfo(tab.windowId, tab, outputDiv);\n          }\n        }\n      );\n    });\n  });\n}\n\n// Print a link to a given tab\nfunction displayTabInfo(windowId, tab, outputDiv) {\n  if (tab.favIconUrl != undefined) {\n    outputDiv.innerHTML += \"<img src='chrome://favicon/\" + tab.url + \"'>\\n\";\n  }\n  outputDiv.innerHTML +=\n    \"<b><a href='#' onclick='showTab(window, \" + windowId + \", \" + tab.id +\n    \")'>\" + tab.title + \"</a></b><br>\\n\" +\n    \"<i>\" + tab.url + \"</i><br>\\n\";\n}\n\n// Bring the selected tab to the front\nfunction showTab(origWindow, windowId, tabId) {\n  // TODO: Bring the window to the front.  (See http://crbug.com/31434)\n  //chrome.windows.update(windowId, {focused: true});\n  chrome.tabs.update(tabId, { selected: true });\n  origWindow.close();\n}\n\n// Kick things off.\ndocument.addEventListener('DOMContentLoaded', init);\n"
  },
  {
    "path": "_archive/mv2/api/storage/stylizr/manifest.json",
    "content": "{\n  \"name\": \"Stylizr\",\n  \"description\": \"Spruce up your pages with custom CSS.\",\n  \"version\": \"1.0\",\n\n  \"permissions\": [\n    \"activeTab\",\n    \"storage\"\n  ],\n\n  \"options_page\": \"options.html\",\n\n  \"browser_action\": {\n    \"default_icon\": \"icon.png\",\n    \"default_title\": \"Stylize!\",\n    \"default_popup\": \"popup.html\"\n  },\n\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/storage/stylizr/options.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Stylizr</title>\n    <style>\n      body {\n        font-family: sans-serif;\n      }\n      label {\n        display: block;\n      }\n      textarea {\n        font-family: monospace;\n      }\n      .message {\n        height: 20px;\n        background: #eee;\n        padding: 5px;\n      }\n    </style>\n  </head>\n  <body>\n    <div class=\"message\"></div>\n    <h3>Stylizr Instructions</h3>\n\n    <ol>\n      <li>Write CSS in this textarea and save</li>\n      <li>Navigate to some page</li>\n      <li>Click the browser action icon <img src=\"icon.png\" /></li>\n      <li>Hey presto! CSS is injected!</li>\n    </ol>\n\n    <textarea name=\"style_url\" id=\"style_url\" cols=80 rows=24\n        placeholder=\"eg: * { font-size: 110%; }\"></textarea>\n\n    <br/>\n    <button class=\"submit\">Save</button>\n    <button class=\"reset\">Reset</button>\n\n    <script src=\"options.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/storage/stylizr/options.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Store CSS data in the \"local\" storage area.\n//\n// Usually we try to store settings in the \"sync\" area since a lot of the time\n// it will be a better user experience for settings to automatically sync\n// between browsers.\n//\n// However, \"sync\" is expensive with a strict quota (both in storage space and\n// bandwidth) so data that may be as large and updated as frequently as the CSS\n// may not be suitable.\nvar storage = chrome.storage.local;\n\n// Get at the DOM controls used in the sample.\nvar resetButton = document.querySelector('button.reset');\nvar submitButton = document.querySelector('button.submit');\nvar textarea = document.querySelector('textarea');\n\n// Load any CSS that may have previously been saved.\nloadChanges();\n\nsubmitButton.addEventListener('click', saveChanges);\nresetButton.addEventListener('click', reset);\n\nfunction saveChanges() {\n  // Get the current CSS snippet from the form.\n  var cssCode = textarea.value;\n  // Check that there's some code there.\n  if (!cssCode) {\n    message('Error: No CSS specified');\n    return;\n  }\n  // Save it using the Chrome extension storage API.\n  storage.set({'css': cssCode}, function() {\n    // Notify that we saved.\n    message('Settings saved');\n  });\n}\n\nfunction loadChanges() {\n  storage.get('css', function(items) {\n    // To avoid checking items.css we could specify storage.get({css: ''}) to\n    // return a default value of '' if there is no css value yet.\n    if (items.css) {\n      textarea.value = items.css;\n      message('Loaded saved CSS.');\n    }\n  });\n}\n\nfunction reset() {\n  // Remove the saved value from storage. storage.clear would achieve the same\n  // thing.\n  storage.remove('css', function(items) {\n    message('Reset stored CSS');\n  });\n  // Refresh the text area.\n  textarea.value = '';\n}\n\nfunction message(msg) {\n  var message = document.querySelector('.message');\n  message.innerText = msg;\n  setTimeout(function() {\n    message.innerText = '';\n  }, 3000);\n}\n"
  },
  {
    "path": "_archive/mv2/api/storage/stylizr/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Stylizr</title>\n    <style>\n      body {\n        font-family: sans-serif;\n        width: 200px;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"message\"></div>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/storage/stylizr/popup.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Store CSS data in the \"local\" storage area.\n//\n// See note in options.js for rationale on why not to use \"sync\".\nvar storage = chrome.storage.local;\n\nvar message = document.querySelector('#message');\n\n// Check if there is CSS specified.\nstorage.get('css', function(items) {\n  console.log(items);\n  // If there is CSS specified, inject it into the page.\n  if (items.css) {\n    chrome.tabs.insertCSS({code: items.css}, function() {\n      if (chrome.runtime.lastError) {\n        message.innerText = 'Not allowed to inject CSS into special page.';\n      } else {\n        message.innerText = 'Injected style!';\n      }\n    });\n  } else {\n    var optionsUrl = chrome.extension.getURL('options.html');\n    message.innerHTML = 'Set a style in the <a target=\"_blank\" href=\"' +\n        optionsUrl + '\">options page</a> first.';\n  }\n});\n\n"
  },
  {
    "path": "_archive/mv2/api/tabCapture/eventPage.js",
    "content": "// Copyright 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// The window (tab) opened and navigated to receiver.html.\nvar receiver = null;\n\n// Open a new window of receiver.html when browser action icon is clicked.\nfunction playCapturedStream(stream) {\n  if (!stream) {\n    console.error('Error starting tab capture: ' +\n                  (chrome.runtime.lastError.message || 'UNKNOWN'));\n    return;\n  }\n  if (receiver != null) {\n    receiver.close();\n  }\n  receiver = window.open('receiver.html');\n  receiver.currentStream = stream;\n}\n\nfunction testCapture() {\n  console.log('Test with method capture().');\n  chrome.tabCapture.capture({\n    video: true, audio: true,\n    videoConstraints: {\n      mandatory: {\n        // If minWidth/Height have the same aspect ratio (e.g., 16:9) as\n        // maxWidth/Height, the implementation will letterbox/pillarbox as\n        // needed. Otherwise, set minWidth/Height to 0 to allow output video\n        // to be of any arbitrary size.\n        minWidth: 16,\n        minHeight: 9,\n        maxWidth: 854,\n        maxHeight: 480,\n        maxFrameRate: 60,  // Note: Frame rate is variable (0 <= x <= 60).\n      },\n    },\n  },\n  function(stream) {\n    playCapturedStream(stream);\n  });\n}\n\nfunction testGetMediaStreamId() {\n  console.log('Test with method getMediaStreamId().');\n  chrome.tabCapture.getMediaStreamId(function(streamId) {\n    if (typeof streamId !== 'string') {\n      console.error('Failed to get media stream id: ' +\n                    (chrome.runtime.lastError.message || 'UNKNOWN'));\n      return;\n    }\n\n    navigator.webkitGetUserMedia({\n      audio:false,\n      video: {\n        mandatory:{\n          chromeMediaSource:'tab', // The media source must be 'tab' here.\n          chromeMediaSourceId:streamId\n        }\n      }\n    },\n    function(stream){\n      playCapturedStream(stream);\n    },\n    function(error){\n      console.error(error);\n    })\n  });\n}\n\nchrome.browserAction.onClicked.addListener(function(tab) {\n  // Retrieve the test option to test each method respectively.\n  // The captured stream will have different resolution for each test.\n  chrome.storage.local.get(['tabCaptureMethod'], function(result) {\n    if (result.tabCaptureMethod == 'streamId') {\n      testGetMediaStreamId();\n    } else {\n      testCapture();\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/tabCapture/manifest.json",
    "content": "{\n  \"name\": \"Tab Capture Example\",\n  \"description\": \"Capture a tab and play in a <video> element in a separate tab.\",\n  \"version\": \"1\",\n  \"manifest_version\": 2,\n  \"background\": {\n    \"scripts\": [\"eventPage.js\"],\n    \"persistent\": false\n  },\n  \"browser_action\": {\n    \"default_icon\": \"icon.png\"\n  },\n  \"options_ui\": {\n    \"page\": \"options.html\",\n    \"open_in_tab\": false\n  },\n  \"permissions\": [\n    \"storage\",\n    \"tabs\",\n    \"tabCapture\"\n  ]\n}\n"
  },
  {
    "path": "_archive/mv2/api/tabCapture/options.html",
    "content": "<!DOCTYPE html>\n<html>\n<head><title>tabCapture Sample Options</title></head>\n<body>\n\nTest tabCapture method:\n<form name=\"methodForm\">\n  <input type=\"radio\" name=\"method\" id=\"capture\"\n         value=\"capture\" style=\"margin-top: 5px\"> capture()<br>\n  <input type=\"radio\" name=\"method\" id=\"streamId\"\n         value=\"streamId\" style=\"margin-top: 5px\"> getMediaSteamId()<br>\n</form>\n\n<button id=\"save\" style=\"margin-top: 10px\">Save</button>\n<div id=\"status\" style=\"margin-top: 5px\"></div>\n\n<script src=\"options.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "_archive/mv2/api/tabCapture/options.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Restore the option last saved.\nwindow.onload = function() {\n  chrome.storage.local.get(['tabCaptureMethod'], function(result) {\n    if (result.tabCaptureMethod == 'streamId') {\n      document.getElementById('streamId').checked = true;\n    } else {\n      document.getElementById('capture').checked = true;\n    }\n  });\n}\n\n// Save option locally.\nfunction saveOption(){\n  var value = document.querySelector('input[name=\"method\"]:checked').value;\n  chrome.storage.local.set({'tabCaptureMethod': value}, function() {\n    var status = document.getElementById('status');\n    status.textContent = \"Option saved.\";\n    setTimeout(function() {status.textContent = '';}, 750);\n  });\n}\n\ndocument.getElementById('save').addEventListener('click', saveOption);"
  },
  {
    "path": "_archive/mv2/api/tabCapture/receiver.html",
    "content": "<html>\n  <head>\n    <style>\n      body {\n        align-items: center;\n        background-color: #224;\n        display: flex;\n        justify-content: center;\n        margin: none;\n        padding: none;\n      }\n\n      body.shutdown {\n        background-color: #422;\n      }\n\n      body.shutdown #player {\n        display: none;\n      }\n    </style>\n  </head>\n  <body>\n    <video id=\"player\"></video>\n    <script src=\"receiver.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/tabCapture/receiver.js",
    "content": "// Copyright 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Note: |window.currentStream| was set in background.js.\n\n// Stop video play-out, stop the MediaStreamTracks, and set style class to\n// \"shutdown\".\nfunction shutdownReceiver() {\n  if (!window.currentStream) {\n    return;\n  }\n\n  var player = document.getElementById('player');\n  player.srcObject = null;\n  var tracks = window.currentStream.getTracks();\n  for (var i = 0; i < tracks.length; ++i) {\n    tracks[i].stop();\n  }\n  window.currentStream = null;\n\n  document.body.className = 'shutdown';\n}\n\nwindow.addEventListener('load', function() {\n  // Start video play-out of the captured audio/video MediaStream once the page\n  // has loaded.\n  var player = document.getElementById('player');\n  player.addEventListener('canplay', function() {\n    this.volume = 0.75;\n    this.muted = false;\n    this.play();\n  });\n  player.setAttribute('controls', '1');\n  player.srcObject = window.currentStream;\n\n  // Add onended event listeners. This detects when tab capture was shut down by\n  // closing the tab being captured.\n  var tracks = window.currentStream.getTracks();\n  for (var i = 0; i < tracks.length; ++i) {\n    tracks[i].addEventListener('ended', function() {\n      console.log('MediaStreamTrack[' + i + '] ended, shutting down...');\n      shutdownReceiver();\n    });\n  }\n});\n\n// Shutdown when the receiver page is closed.\nwindow.addEventListener('beforeunload', shutdownReceiver);\n"
  },
  {
    "path": "_archive/mv2/api/tabs/inspector/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.browserAction.onClicked.addListener(function(tab) {\n  chrome.tabs.create({url:chrome.extension.getURL(\"tabs_api.html\")});\n});\n"
  },
  {
    "path": "_archive/mv2/api/tabs/inspector/jstemplate_compiled.js",
    "content": "/**\n * @fileoverview This file contains miscellaneous basic functionality.\n *\n */\n\n/**\n * Creates a DOM element with the given tag name in the document of the\n * owner element.\n *\n * @param {String} tagName  The name of the tag to create.\n * @param {Element} owner The intended owner (i.e., parent element) of\n * the created element.\n * @param {Point} opt_position  The top-left corner of the created element.\n * @param {Size} opt_size  The size of the created element.\n * @param {Boolean} opt_noAppend Do not append the new element to the owner.\n * @return {Element}  The newly created element node.\n */\nfunction createElement(tagName, owner, opt_position, opt_size, opt_noAppend) {\n  var element = ownerDocument(owner).createElement(tagName);\n  if (opt_position) {\n    setPosition(element, opt_position);\n  }\n  if (opt_size) {\n    setSize(element, opt_size);\n  }\n  if (owner && !opt_noAppend) {\n    appendChild(owner, element);\n  }\n\n  return element;\n}\n\n/**\n * Creates a text node with the given value.\n *\n * @param {String} value  The text to place in the new node.\n * @param {Element} owner The owner (i.e., parent element) of the new\n * text node.\n * @return {Text}  The newly created text node.\n */\nfunction createTextNode(value, owner) {\n  var element = ownerDocument(owner).createTextNode(value);\n  if (owner) {\n    appendChild(owner, element);\n  }\n  return element;\n}\n\n/**\n * Returns the document owner of the given element. In particular,\n * returns window.document if node is null or the browser does not\n * support ownerDocument.\n *\n * @param {Node} node  The node whose ownerDocument is required.\n * @returns {Document|Null}  The owner document or null if unsupported.\n */\nfunction ownerDocument(node) {\n  return (node ? node.ownerDocument : null) || document;\n}\n\n/**\n * Wrapper function to create CSS units (pixels) string\n *\n * @param {Number} numPixels  Number of pixels, may be floating point.\n * @returns {String}  Corresponding CSS units string.\n */\nfunction px(numPixels) {\n  return round(numPixels) + \"px\";\n}\n\n/**\n * Sets the left and top of the given element to the given point.\n *\n * @param {Element} element  The dom element to manipulate.\n * @param {Point} point  The desired position.\n */\nfunction setPosition(element, point) {\n  var style = element.style;\n  style.position = \"absolute\";\n  style.left = px(point.x);\n  style.top = px(point.y);\n}\n\n/**\n * Sets the width and height style attributes to the given size.\n *\n * @param {Element} element  The dom element to manipulate.\n * @param {Size} size  The desired size.\n */\nfunction setSize(element, size) {\n  var style = element.style;\n  style.width = px(size.width);\n  style.height = px(size.height);\n}\n\n/**\n * Sets display to none. Doing this as a function saves a few bytes for\n * the 'style.display' property and the 'none' literal.\n *\n * @param {Element} node  The dom element to manipulate.\n */\nfunction displayNone(node) {\n  node.style.display = 'none';\n}\n\n/**\n * Sets display to default.\n *\n * @param {Element} node  The dom element to manipulate.\n */\nfunction displayDefault(node) {\n  node.style.display = '';\n}\n\n/**\n * Appends the given child to the given parent in the DOM\n *\n * @param {Element} parent  The parent dom element.\n * @param {Node} child  The new child dom node.\n */\nfunction appendChild(parent, child) {\n  parent.appendChild(child);\n}\n\n\n/**\n * Wrapper for the eval() builtin function to evaluate expressions and\n * obtain their value. It wraps the expression in parentheses such\n * that object literals are really evaluated to objects. Without the\n * wrapping, they are evaluated as block, and create syntax\n * errors. Also protects against other syntax errors in the eval()ed\n * code and returns null if the eval throws an exception.\n *\n * @param {String} expr\n * @return {Object|Null}\n */\nfunction jsEval(expr) {\n  try {\n    return eval('[' + expr + '][0]');\n  } catch (e) {\n    return null;\n  }\n}\n\n\n/**\n * Wrapper for the eval() builtin function to execute statements. This\n * guards against exceptions thrown, but doesn't return a\n * value. Still, mostly for testability, it returns a boolean to\n * indicate whether execution was successful. NOTE:\n * javascript's eval semantics is murky in that it confounds\n * expression evaluation and statement execution into a single\n * construct. Cf. jsEval().\n *\n * @param {String} stmt\n * @return {Boolean}\n */\nfunction jsExec(stmt) {\n  try {\n    eval(stmt);\n    return true;\n  } catch (e) {\n    return false;\n  }\n}\n\n\n/**\n * Wrapper for eval with a context. NOTE: The style guide\n * deprecates eval, so this is the exception that proves the\n * rule. Notice also that since the value of the expression is\n * returned rather than assigned to a local variable, one major\n * objection aganist the use of the with() statement, namely that\n * properties of the with() target override local variables of the\n * same name, is void here.\n *\n * @param {String} expr\n * @param {Object} context\n * @return {Object|Null}\n */\nfunction jsEvalWith(expr, context) {\n  try {\n    with (context) {\n      return eval('[' + expr + '][0]');\n    }\n  } catch (e) {\n    return null;\n  }\n}\n\n\nvar DOM_ELEMENT_NODE = 1;\nvar DOM_ATTRIBUTE_NODE = 2;\nvar DOM_TEXT_NODE = 3;\nvar DOM_CDATA_SECTION_NODE = 4;\nvar DOM_ENTITY_REFERENCE_NODE = 5;\nvar DOM_ENTITY_NODE = 6;\nvar DOM_PROCESSING_INSTRUCTION_NODE = 7;\nvar DOM_COMMENT_NODE = 8;\nvar DOM_DOCUMENT_NODE = 9;\nvar DOM_DOCUMENT_TYPE_NODE = 10;\nvar DOM_DOCUMENT_FRAGMENT_NODE = 11;\nvar DOM_NOTATION_NODE = 12;\n\n/**\n * Traverses the element nodes in the DOM tree underneath the given\n * node and finds the first node with elemId, or null if there is no such\n * element.  Traversal is in depth-first order.\n *\n * NOTE: The reason this is not combined with the elem() function is\n * that the implementations are different.\n * elem() is a wrapper for the built-in document.getElementById() function,\n * whereas this function performs the traversal itself.\n * Modifying elem() to take an optional root node is a possibility,\n * but the in-built function would perform better than using our own traversal.\n *\n * @param {Element} node Root element of subtree to traverse.\n * @param {String} elemId The id of the element to search for.\n * @return {Element|Null} The corresponding element, or null if not found.\n */\nfunction nodeGetElementById(node, elemId) {\n  for (var c = node.firstChild; c; c = c.nextSibling) {\n    if (c.id == elemId) {\n      return c;\n    }\n    if (c.nodeType == DOM_ELEMENT_NODE) {\n      var n = arguments.callee.call(this, c, elemId);\n      if (n) {\n        return n;\n      }\n    }\n  }\n  return null;\n}\n\n\n/**\n * Get an attribute from the DOM.  Simple redirect, exists to compress code.\n *\n * @param {Element} node  Element to interrogate.\n * @param {String} name  Name of parameter to extract.\n * @return {String}  Resulting attribute.\n */\nfunction domGetAttribute(node, name) {\n  return node.getAttribute(name);\n}\n\n/**\n * Set an attribute in the DOM.  Simple redirect to compress code.\n *\n * @param {Element} node  Element to interrogate.\n * @param {String} name  Name of parameter to set.\n * @param {String} value  Set attribute to this value.\n */\nfunction domSetAttribute(node, name, value) {\n  node.setAttribute(name, value);\n}\n\n/**\n * Remove an attribute from the DOM.  Simple redirect to compress code.\n *\n * @param {Element} node  Element to interrogate.\n * @param {String} name  Name of parameter to remove.\n */\nfunction domRemoveAttribute(node, name) {\n  node.removeAttribute(name);\n}\n\n/**\n * Clone a node in the DOM.\n *\n * @param {Node} node  Node to clone.\n * @return {Node}  Cloned node.\n */\nfunction domCloneNode(node) {\n  return node.cloneNode(true);\n}\n\n\n/**\n * Return a safe string for the className of a node.\n * If className is not a string, returns \"\".\n *\n * @param {Element} node  DOM element to query.\n * @return {String}\n */\nfunction domClassName(node) {\n  return node.className ? \"\" + node.className : \"\";\n}\n\n/**\n * Adds a class name to the class attribute of the given node.\n *\n * @param {Element} node  DOM element to modify.\n * @param {String} className  Class name to add.\n */\nfunction domAddClass(node, className) {\n  var name = domClassName(node);\n  if (name) {\n    var cn = name.split(/\\s+/);\n    var found = false;\n    for (var i = 0; i < jsLength(cn); ++i) {\n      if (cn[i] == className) {\n        found = true;\n        break;\n      }\n    }\n\n    if (!found) {\n      cn.push(className);\n    }\n\n    node.className = cn.join(' ');\n  } else {\n    node.className = className;\n  }\n}\n\n/**\n * Removes a class name from the class attribute of the given node.\n *\n * @param {Element} node  DOM element to modify.\n * @param {String} className  Class name to remove.\n */\nfunction domRemoveClass(node, className) {\n  var c = domClassName(node);\n  if (!c || c.indexOf(className) == -1) {\n    return;\n  }\n  var cn = c.split(/\\s+/);\n  for (var i = 0; i < jsLength(cn); ++i) {\n    if (cn[i] == className) {\n      cn.splice(i--, 1);\n    }\n  }\n  node.className = cn.join(' ');\n}\n\n/**\n * Checks if a node belongs to a style class.\n *\n * @param {Element} node  DOM element to test.\n * @param {String} className  Class name to check for.\n * @return {Boolean}  Node belongs to style class.\n */\nfunction domTestClass(node, className) {\n  var cn = domClassName(node).split(/\\s+/);\n  for (var i = 0; i < jsLength(cn); ++i) {\n    if (cn[i] == className) {\n      return true;\n    }\n  }\n  return false;\n}\n\n/**\n * Inserts a new child before a given sibling.\n *\n * @param {Node} newChild  Node to insert.\n * @param {Node} oldChild  Sibling node.\n * @return {Node}  Reference to new child.\n */\nfunction domInsertBefore(newChild, oldChild) {\n  return oldChild.parentNode.insertBefore(newChild, oldChild);\n}\n\n/**\n * Appends a new child to the specified (parent) node.\n *\n * @param {Element} node  Parent element.\n * @param {Node} child  Child node to append.\n * @return {Node}  Newly appended node.\n */\nfunction domAppendChild(node, child) {\n  return node.appendChild(child);\n}\n\n/**\n * Remove a new child from the specified (parent) node.\n *\n * @param {Element} node  Parent element.\n * @param {Node} child  Child node to remove.\n * @return {Node}  Removed node.\n */\nfunction domRemoveChild(node, child) {\n  return node.removeChild(child);\n}\n\n/**\n * Replaces an old child node with a new child node.\n *\n * @param {Node} newChild  New child to append.\n * @param {Node} oldChild  Old child to remove.\n * @return {Node}  Replaced node.\n */\nfunction domReplaceChild(newChild, oldChild) {\n  return oldChild.parentNode.replaceChild(newChild, oldChild);\n}\n\n/**\n * Removes a node from the DOM.\n *\n * @param {Node} node  The node to remove.\n * @return {Node}  The removed node.\n */\nfunction domRemoveNode(node) {\n  return domRemoveChild(node.parentNode, node);\n}\n\n/**\n * Creates a new text node in the given document.\n *\n * @param {Document} doc  Target document.\n * @param {String} text  Text composing new text node.\n * @return {Text}  Newly constructed text node.\n */\nfunction domCreateTextNode(doc, text) {\n  return doc.createTextNode(text);\n}\n\n/**\n * Creates a new node in the given document\n *\n * @param {Document} doc  Target document.\n * @param {String} name  Name of new element (i.e. the tag name)..\n * @return {Element}  Newly constructed element.\n */\nfunction domCreateElement(doc, name) {\n  return doc.createElement(name);\n}\n\n/**\n * Creates a new attribute in the given document.\n *\n * @param {Document} doc  Target document.\n * @param {String} name  Name of new attribute.\n * @return {Attr}  Newly constructed attribute.\n */\nfunction domCreateAttribute(doc, name) {\n  return doc.createAttribute(name);\n}\n\n/**\n * Creates a new comment in the given document.\n *\n * @param {Document} doc  Target document.\n * @param {String} text  Comment text.\n * @return {Comment}  Newly constructed comment.\n */\nfunction domCreateComment(doc, text) {\n  return doc.createComment(text);\n}\n\n/**\n * Creates a document fragment.\n *\n * @param {Document} doc  Target document.\n * @return {DocumentFragment}  Resulting document fragment node.\n */\nfunction domCreateDocumentFragment(doc) {\n  return doc.createDocumentFragment();\n}\n\n/**\n * Redirect to document.getElementById\n *\n * @param {Document} doc  Target document.\n * @param {String} id  Id of requested node.\n * @return {Element|Null}  Resulting element.\n */\nfunction domGetElementById(doc, id) {\n  return doc.getElementById(id);\n}\n\n/**\n * Redirect to window.setInterval\n *\n * @param {Window} win  Target window.\n * @param {Function} fun  Callback function.\n * @param {Number} time  Time in milliseconds.\n * @return {Object}  Contract id.\n */\nfunction windowSetInterval(win, fun, time) {\n  return win.setInterval(fun, time);\n}\n\n/**\n * Redirect to window.clearInterval\n *\n * @param {Window} win  Target window.\n * @param {object} id  Contract id.\n * @return {any}  NOTE: Return type unknown?\n */\nfunction windowClearInterval(win, id) {\n  return win.clearInterval(id);\n}\n\n/**\n * Determines whether one node is recursively contained in another.\n * @param parent The parent node.\n * @param child The node to look for in parent.\n * @return parent recursively contains child\n */\nfunction containsNode(parent, child) {\n  while (parent != child && child.parentNode) {\n    child = child.parentNode;\n  }\n  return parent == child;\n};\n/**\n * @fileoverview This file contains javascript utility functions that\n * do not depend on anything defined elsewhere.\n *\n */\n\n/**\n * Returns the value of the length property of the given object. Used\n * to reduce compiled code size.\n *\n * @param {Array | String} a  The string or array to interrogate.\n * @return {Number}  The value of the length property.\n */\nfunction jsLength(a) {\n  return a.length;\n}\n\nvar min = Math.min;\nvar max = Math.max;\nvar ceil = Math.ceil;\nvar floor = Math.floor;\nvar round = Math.round;\nvar abs = Math.abs;\n\n/**\n * Copies all properties from second object to the first.  Modifies to.\n *\n * @param {Object} to  The target object.\n * @param {Object} from  The source object.\n */\nfunction copyProperties(to, from) {\n  foreachin(from, function(p) {\n    to[p] = from[p];\n  });\n}\n\n/**\n * Iterates over the array, calling the given function for each\n * element.\n *\n * @param {Array} array\n * @param {Function} fn\n */\nfunction foreach(array, fn) {\n  var I = jsLength(array);\n  for (var i = 0; i < I; ++i) {\n    fn(array[i], i);\n  }\n}\n\n/**\n * Safely iterates over all properties of the given object, calling\n * the given function for each property. If opt_all isn't true, uses\n * hasOwnProperty() to assure the property is on the object, not on\n * its prototype.\n *\n * @param {Object} object\n * @param {Function} fn\n * @param {Boolean} opt_all  If true, also iterates over inherited properties.\n */\nfunction foreachin(object, fn, opt_all) {\n  for (var i in object) {\n    if (opt_all || !object.hasOwnProperty || object.hasOwnProperty(i)) {\n      fn(i, object[i]);\n    }\n  }\n}\n\n/**\n * Appends the second array to the first, copying its elements.\n * Optionally only a slice of the second array is copied.\n *\n * @param {Array} a1  Target array (modified).\n * @param {Array} a2  Source array.\n * @param {Number} opt_begin  Begin of slice of second array (optional).\n * @param {Number} opt_end  End (exclusive) of slice of second array (optional).\n */\nfunction arrayAppend(a1, a2, opt_begin, opt_end) {\n  var i0 = opt_begin || 0;\n  var i1 = opt_end || jsLength(a2);\n  for (var i = i0; i < i1; ++i) {\n    a1.push(a2[i]);\n  }\n}\n\n/**\n * Trim whitespace from begin and end of string.\n *\n * @see testStringTrim();\n *\n * @param {String} str  Input string.\n * @return {String}  Trimmed string.\n */\nfunction stringTrim(str) {\n  return stringTrimRight(stringTrimLeft(str));\n}\n\n/**\n * Trim whitespace from beginning of string.\n *\n * @see testStringTrimLeft();\n *\n * @param {String} str  Input string.\n * @return {String}  Trimmed string.\n */\nfunction stringTrimLeft(str) {\n  return str.replace(/^\\s+/, \"\");\n}\n\n/**\n * Trim whitespace from end of string.\n *\n * @see testStringTrimRight();\n *\n * @param {String} str  Input string.\n * @return {String}  Trimmed string.\n */\nfunction stringTrimRight(str) {\n  return str.replace(/\\s+$/, \"\");\n}\n\n/**\n * Jscompiler wrapper for parseInt() with base 10.\n *\n * @param {String} s String repersentation of a number.\n *\n * @return {Number} The integer contained in s, converted on base 10.\n */\nfunction parseInt10(s) {\n  return parseInt(s, 10);\n}\n/**\n * @fileoverview A simple formatter to project JavaScript data into\n * HTML templates. The template is edited in place. I.e. in order to\n * instantiate a template, clone it from the DOM first, and then\n * process the cloned template. This allows for updating of templates:\n * If the templates is processed again, changed values are merely\n * updated.\n *\n * NOTE: IE DOM doesn't have importNode().\n *\n * NOTE: The property name \"length\" must not be used in input\n * data, see comment in jstSelect_().\n */\n\n\n/**\n * Names of jstemplate attributes. These attributes are attached to\n * normal HTML elements and bind expression context data to the HTML\n * fragment that is used as template.\n */\nvar ATT_select = 'jsselect';\nvar ATT_instance = 'jsinstance';\nvar ATT_display = 'jsdisplay';\nvar ATT_values = 'jsvalues';\nvar ATT_eval = 'jseval';\nvar ATT_transclude = 'transclude';\nvar ATT_content = 'jscontent';\n\n\n/**\n * Names of special variables defined by the jstemplate evaluation\n * context. These can be used in js expression in jstemplate\n * attributes.\n */\nvar VAR_index = '$index';\nvar VAR_this = '$this';\n\n\n/**\n * Context for processing a jstemplate. The context contains a context\n * object, whose properties can be referred to in jstemplate\n * expressions, and it holds the locally defined variables.\n *\n * @param {Object} opt_data The context object. Null if no context.\n *\n * @param {Object} opt_parent The parent context, from which local\n * variables are inherited. Normally the context object of the parent\n * context is the object whose property the parent object is. Null for the\n * context of the root object.\n *\n * @constructor\n */\nfunction JsExprContext(opt_data, opt_parent) {\n  var me = this;\n\n  /**\n   * The local context of the input data in which the jstemplate\n   * expressions are evaluated. Notice that this is usually an Object,\n   * but it can also be a scalar value (and then still the expression\n   * $this can be used to refer to it). Notice this can be a scalar\n   * value, including undefined.\n   *\n   * @type {Object}\n   */\n  me.data_ = opt_data;\n\n  /**\n   * The context for variable definitions in which the jstemplate\n   * expressions are evaluated. Other than for the local context,\n   * which replaces the parent context, variable definitions of the\n   * parent are inherited. The special variable $this points to data_.\n   *\n   * @type {Object}\n   */\n  me.vars_ = {};\n  if (opt_parent) {\n    copyProperties(me.vars_, opt_parent.vars_);\n  }\n  this.vars_[VAR_this] = me.data_;\n}\n\n\n/**\n * Evaluates the given expression in the context of the current\n * context object and the current local variables.\n *\n * @param {String} expr A javascript expression.\n *\n * @param {Element} template DOM node of the template.\n *\n * @return The value of that expression.\n */\nJsExprContext.prototype.jseval = function(expr, template) {\n  with (this.vars_) {\n    with (this.data_) {\n      try {\n        return (function() {\n          return eval('[' + expr + '][0]');\n        }).call(template);\n      } catch (e) {\n        return null;\n      }\n    }\n  }\n}\n\n\n/**\n * Clones the current context for a new context object. The cloned\n * context has the data object as its context object and the current\n * context as its parent context. It also sets the $index variable to\n * the given value. This value usually is the position of the data\n * object in a list for which a template is instantiated multiply.\n *\n * @param {Object} data The new context object.\n *\n * @param {Number} index Position of the new context when multiply\n * instantiated. (See implementation of jstSelect().)\n *\n * @return {JsExprContext}\n */\nJsExprContext.prototype.clone = function(data, index) {\n  var ret = new JsExprContext(data, this);\n  ret.setVariable(VAR_index, index);\n  if (this.resolver_) {\n    ret.setSubTemplateResolver(this.resolver_);\n  }\n  return ret;\n}\n\n\n/**\n * Binds a local variable to the given value. If set from jstemplate\n * jsvalue expressions, variable names must start with $, but in the\n * API they only have to be valid javascript identifier.\n *\n * @param {String} name\n *\n * @param {Object} value\n */\nJsExprContext.prototype.setVariable = function(name, value) {\n  this.vars_[name] = value;\n}\n\n\n/**\n * Sets the function used to resolve the values of the transclude\n * attribute into DOM nodes. By default, this is jstGetTemplate(). The\n * value set here is inherited by clones of this context.\n *\n * @param {Function} resolver The function used to resolve transclude\n * ids into a DOM node of a subtemplate. The DOM node returned by this\n * function will be inserted into the template instance being\n * processed. Thus, the resolver function must instantiate the\n * subtemplate as necessary.\n */\nJsExprContext.prototype.setSubTemplateResolver = function(resolver) {\n  this.resolver_ = resolver;\n}\n\n\n/**\n * Resolves a sub template from an id. Used to process the transclude\n * attribute. If a resolver function was set using\n * setSubTemplateResolver(), it will be used, otherwise\n * jstGetTemplate().\n *\n * @param {String} id The id of the sub template.\n *\n * @return {Node} The root DOM node of the sub template, for direct\n * insertion into the currently processed template instance.\n */\nJsExprContext.prototype.getSubTemplate = function(id) {\n  return (this.resolver_ || jstGetTemplate).call(this, id);\n}\n\n\n/**\n * HTML template processor. Data values are bound to HTML templates\n * using the attributes transclude, jsselect, jsdisplay, jscontent,\n * jsvalues. The template is modifed in place. The values of those\n * attributes are JavaScript expressions that are evaluated in the\n * context of the data object fragment.\n *\n * @param {JsExprContext} context Context created from the input data\n * object.\n *\n * @param {Element} template DOM node of the template. This will be\n * processed in place. After processing, it will still be a valid\n * template that, if processed again with the same data, will remain\n * unchanged.\n */\nfunction jstProcess(context, template) {\n  var processor = new JstProcessor();\n  processor.run_([ processor, processor.jstProcess_, context, template ]);\n}\n\n\n/**\n * Internal class used by jstemplates to maintain context.\n * NOTE: This is necessary to process deep templates in Safari\n * which has a relatively shallow stack.\n * @class\n */\nfunction JstProcessor() {\n}\n\n\n/**\n * Runs the state machine, beginning with function \"start\".\n *\n * @param {Array} start The first function to run, in the form\n * [object, method, args ...]\n */\nJstProcessor.prototype.run_ = function(start) {\n  var me = this;\n\n  me.queue_ = [ start ];\n  while (jsLength(me.queue_)) {\n    var f = me.queue_.shift();\n    f[1].apply(f[0], f.slice(2));\n  }\n}\n\n\n/**\n * Appends a function to be called later.\n * Analogous to calling that function on a subsequent line, or a subsequent\n * iteration of a loop.\n *\n * @param {Array} f  A function in the form [object, method, args ...]\n */\nJstProcessor.prototype.enqueue_ = function(f) {\n  this.queue_.push(f);\n}\n\n\n/**\n * Implements internals of jstProcess.\n *\n * @param {JsExprContext} context\n *\n * @param {Element} template\n */\nJstProcessor.prototype.jstProcess_ = function(context, template) {\n  var me = this;\n\n  var transclude = domGetAttribute(template, ATT_transclude);\n  if (transclude) {\n    var tr = context.getSubTemplate(transclude);\n    if (tr) {\n      domReplaceChild(tr, template);\n      me.enqueue_([ me, me.jstProcess_, context, tr ]);\n    } else {\n      domRemoveNode(template);\n    }\n    return;\n  }\n\n  var select = domGetAttribute(template, ATT_select);\n  if (select) {\n    me.jstSelect_(context, template, select);\n    return;\n  }\n\n  var display = domGetAttribute(template, ATT_display);\n  if (display) {\n    if (!context.jseval(display, template)) {\n      displayNone(template);\n      return;\n    }\n\n    displayDefault(template);\n  }\n\n\n  var values = domGetAttribute(template, ATT_values);\n  if (values) {\n    me.jstValues_(context, template, values);\n  }\n\n  var expressions = domGetAttribute(template, ATT_eval);\n  if (expressions) {\n    foreach(expressions.split(/\\s*;\\s*/), function(expression) {\n      expression = stringTrim(expression);\n      if (jsLength(expression)) {\n        context.jseval(expression, template);\n      }\n    });\n  }\n\n  var content = domGetAttribute(template, ATT_content);\n  if (content) {\n    me.jstContent_(context, template, content);\n\n  } else {\n    var childnodes = [];\n    for (var i = 0; i < jsLength(template.childNodes); ++i) {\n      if (template.childNodes[i].nodeType == DOM_ELEMENT_NODE) {\n      me.enqueue_(\n          [ me, me.jstProcess_, context, template.childNodes[i] ]);\n      }\n    }\n  }\n}\n\n\n/**\n * Implements the jsselect attribute: evalutes the value of the\n * jsselect attribute in the current context, with the current\n * variable bindings (see JsExprContext.jseval()). If the value is an\n * array, the current template node is multiplied once for every\n * element in the array, with the array element being the context\n * object. If the array is empty, or the value is undefined, then the\n * current template node is dropped. If the value is not an array,\n * then it is just made the context object.\n *\n * @param {JsExprContext} context The current evaluation context.\n *\n * @param {Element} template The currently processed node of the template.\n *\n * @param {String} select The javascript expression to evaluate.\n *\n * @param {Function} process The function to continue processing with.\n */\nJstProcessor.prototype.jstSelect_ = function(context, template, select) {\n  var me = this;\n\n  var value = context.jseval(select, template);\n  domRemoveAttribute(template, ATT_select);\n\n  var instance = domGetAttribute(template, ATT_instance);\n  var instance_last = false;\n  if (instance) {\n    if (instance.charAt(0) == '*') {\n      instance = parseInt10(instance.substr(1));\n      instance_last = true;\n    } else {\n      instance = parseInt10(instance);\n    }\n  }\n\n  var multiple = (value !== null &&\n                  typeof value == 'object' &&\n                  typeof value.length == 'number');\n  var multiple_empty = (multiple && value.length == 0);\n\n  if (multiple) {\n    if (multiple_empty) {\n      if (!instance) {\n        domSetAttribute(template, ATT_select, select);\n        domSetAttribute(template, ATT_instance, '*0');\n        displayNone(template);\n      } else {\n        domRemoveNode(template);\n      }\n\n    } else {\n      displayDefault(template);\n      if (instance === null || instance === \"\" || instance === undefined ||\n          (instance_last && instance < jsLength(value) - 1)) {\n        var templatenodes = [];\n        var instances_start = instance || 0;\n        for (var i = instances_start + 1; i < jsLength(value); ++i) {\n          var node = domCloneNode(template);\n          templatenodes.push(node);\n          domInsertBefore(node, template);\n        }\n        templatenodes.push(template);\n\n        for (var i = 0; i < jsLength(templatenodes); ++i) {\n          var ii = i + instances_start;\n          var v = value[ii];\n          var t = templatenodes[i];\n\n          me.enqueue_([ me, me.jstProcess_, context.clone(v, ii), t ]);\n          var instanceStr = (ii == jsLength(value) - 1 ? '*' : '') + ii;\n          me.enqueue_(\n              [ null, postProcessMultiple_, t, select, instanceStr ]);\n        }\n\n      } else if (instance < jsLength(value)) {\n        var v = value[instance];\n\n        me.enqueue_(\n            [me, me.jstProcess_, context.clone(v, instance), template]);\n        var instanceStr = (instance == jsLength(value) - 1 ? '*' : '')\n                          + instance;\n        me.enqueue_(\n            [ null, postProcessMultiple_, template, select, instanceStr ]);\n      } else {\n        domRemoveNode(template);\n      }\n    }\n  } else {\n    if (value == null) {\n      domSetAttribute(template, ATT_select, select);\n      displayNone(template);\n    } else {\n      me.enqueue_(\n          [ me, me.jstProcess_, context.clone(value, 0), template ]);\n      me.enqueue_(\n          [ null, postProcessSingle_, template, select ]);\n    }\n  }\n}\n\n\n/**\n * Sets ATT_select and ATT_instance following recursion to jstProcess.\n *\n * @param {Element} template  The template\n *\n * @param {String} select  The jsselect string\n *\n * @param {String} instanceStr  The new value for the jsinstance attribute\n */\nfunction postProcessMultiple_(template, select, instanceStr) {\n  domSetAttribute(template, ATT_select, select);\n  domSetAttribute(template, ATT_instance, instanceStr);\n}\n\n\n/**\n * Sets ATT_select and makes the element visible following recursion to\n * jstProcess.\n *\n * @param {Element} template  The template\n *\n * @param {String} select  The jsselect string\n */\nfunction postProcessSingle_(template, select) {\n  domSetAttribute(template, ATT_select, select);\n  displayDefault(template);\n}\n\n\n/**\n * Implements the jsvalues attribute: evaluates each of the values and\n * assigns them to variables in the current context (if the name\n * starts with '$', javascript properties of the current template node\n * (if the name starts with '.'), or DOM attributes of the current\n * template node (otherwise). Since DOM attribute values are always\n * strings, the value is coerced to string in the latter case,\n * otherwise it's the uncoerced javascript value.\n *\n * @param {JsExprContext} context Current evaluation context.\n *\n * @param {Element} template Currently processed template node.\n *\n * @param {String} valuesStr Value of the jsvalues attribute to be\n * processed.\n */\nJstProcessor.prototype.jstValues_ = function(context, template, valuesStr) {\n  var values = valuesStr.split(/\\s*;\\s*/);\n  for (var i = 0; i < jsLength(values); ++i) {\n    var colon = values[i].indexOf(':');\n    if (colon < 0) {\n      continue;\n    }\n    var label = stringTrim(values[i].substr(0, colon));\n    var value = context.jseval(values[i].substr(colon + 1), template);\n\n    if (label.charAt(0) == '$') {\n      context.setVariable(label, value);\n\n    } else if (label.charAt(0) == '.') {\n      var nameSpaceLabel = label.substr(1).split('.');\n      var nameSpaceObject = template;\n      var nameSpaceDepth = jsLength(nameSpaceLabel);\n      for (var j = 0, J = nameSpaceDepth - 1; j < J; ++j) {\n        var jLabel = nameSpaceLabel[j];\n        if (!nameSpaceObject[jLabel]) {\n          nameSpaceObject[jLabel] = {};\n        }\n        nameSpaceObject = nameSpaceObject[jLabel];\n      }\n      nameSpaceObject[nameSpaceLabel[nameSpaceDepth - 1]] = value;\n    } else if (label) {\n      if (typeof value == 'boolean') {\n        if (value) {\n          domSetAttribute(template, label, label);\n        } else {\n          domRemoveAttribute(template, label);\n        }\n      } else {\n        domSetAttribute(template, label, '' + value);\n      }\n    }\n  }\n}\n\n\n/**\n * Implements the jscontent attribute. Evalutes the expression in\n * jscontent in the current context and with the current variables,\n * and assigns its string value to the content of the current template\n * node.\n *\n * @param {JsExprContext} context Current evaluation context.\n *\n * @param {Element} template Currently processed template node.\n *\n * @param {String} content Value of the jscontent attribute to be\n * processed.\n */\nJstProcessor.prototype.jstContent_ = function(context, template, content) {\n  var value = '' + context.jseval(content, template);\n  if (template.innerHTML == value) {\n    return;\n  }\n  while (template.firstChild) {\n    domRemoveNode(template.firstChild);\n  }\n  var t = domCreateTextNode(ownerDocument(template), value);\n  domAppendChild(template, t);\n}\n\n\n/**\n * Helps to implement the transclude attribute, and is the initial\n * call to get hold of a template from its ID.\n *\n * @param {String} name The ID of the HTML element used as template.\n *\n * @returns {Element} The DOM node of the template. (Only element\n * nodes can be found by ID, hence it's a Element.)\n */\nfunction jstGetTemplate(name) {\n  var section = domGetElementById(document, name);\n  if (section) {\n    var ret = domCloneNode(section);\n    domRemoveAttribute(ret, 'id');\n    return ret;\n  } else {\n    return null;\n  }\n}\n\nwindow['jstGetTemplate'] = jstGetTemplate;\nwindow['jstProcess'] = jstProcess;\nwindow['JsExprContext'] = JsExprContext;\n"
  },
  {
    "path": "_archive/mv2/api/tabs/inspector/manifest.json",
    "content": "{\n  \"name\": \"Tab Inspector\",\n  \"description\": \"Utility for working with the extension tabs api\",\n  \"version\": \"0.3\",\n  \"permissions\": [\"tabs\"],\n  \"background\": {\n    \"persistent\": false,\n    \"scripts\": [\"background.js\"]\n  },\n  \"browser_action\": {\n    \"default_title\": \"show tab inspector\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/tabs/inspector/tabs_api.html",
    "content": "<html>\n<head>\n<script src=\"jstemplate_compiled.js\" type=\"text/javascript\"></script>\n<script src=\"tabs_api.js\"></script>\n</head>\n  <body>\n    <div id=\"windowList\">\n      <div style=\"background-color: #AAEEEE; margin: 4px; padding: 8px; margin: 20px\" jsselect=\"$this\"\n          jsvalues=\"id:'window_' + id\">\n        <div style=\"font-style: italic; width: 80px; display: inline-block\">\n          Window: <span jscontent=\"id\"></span>\n        </div>\n        <div style=\"display: inline-block\">\n          left: <input style=\"width: 60px\" type=\"text\" jsvalues=\"value:$this.left;id:'left_' + id\" />\n          top: <input style=\"width: 60px\" type=\"text\" jsvalues=\"value:$this.top;id:'top_' + id\" />\n          width: <input style=\"width: 60px\" type=\"text\" jsvalues=\"value:$this.width;id:'width_' + id\" />\n          height: <input style=\"width: 60px\" type=\"text\" jsvalues=\"value:$this.height;id:'height_' + id\" />\n          <input type=\"checkbox\" jsvalues=\"checked:focused; id:'focused_' + id\" /> Focused\n          <input type=\"checkbox\" jsvalues=\"checked:current; id:'current_' + id\" /> Current\n          <button onclick=\"refreshWindow(this.jstdata);\" jsvalues=\".jstdata:id\">Refresh</button>\n        </div>\n        <div id=\"tabList\">\n          <div jsselect=\"tabs\">\n            <div style=\"background-color: #EEEEEE; margin: 8px; padding: 4px\"  jsvalues=\"id:'tab_' + id\">\n              <div style=\"margin: 8px\">\n                <div style=\"font-style: italic; width: 80px; display: inline-block\" jscontent=\"'TabId: ' + id\"></div>\n                <div style=\"width: 300px; display: inline-block\">\n                  index: <input style=\"width: 20px\" type=\"text\" jsvalues=\"value:$this.index;id:'index_' + id\" />\n                  windowId: <input style=\"width: 20px\" type=\"text\" jsvalues=\"value:windowId;id:'windowId_' + id\" />\n                  <button onclick=\"moveTab(this.jstdata);\" jsvalues=\".jstdata:id\">Move</button>\n                  <button onclick=\"refreshTab(this.jstdata);\" jsvalues=\".jstdata:id\">Refresh</button>\n                </div>\n              </div>\n              <div style=\"margin: 8px\">\n                <div>\n                  <div style=\"width: 40px; display:inline-block\">title:</div>\n                  <input style=\"width: 90%\" type=\"text\" jsvalues=\"value:title;id:'title_' + id\" />\n                </div>\n                <div>\n                  <div style=\"width: 40px; display:inline-block\">url:</div>\n                  <input style=\"width: 90%\" type=\"text\" jsvalues=\"value:url;id:'url_' + id\" />\n                </div>\n                <div><input type=\"checkbox\" jsvalues=\"checked:selected; id:'selected_' + id\" /> Selected</div>\n              </div>\n              <button onclick=\"updateTab(this.jstdata)\" jsvalues=\".jstdata:id\">Update Tab</button>\n              <button onclick=\"removeTab(this.jstdata);\" jsvalues=\".jstdata:id\">Close Tab</button>\n            </div>\n          </div>\n        </div>\n        <button onclick=\"updateWindow(this.jstdata);\" jsvalues=\".jstdata:id\">Update Window</button>\n        <button onclick=\"removeWindow(this.jstdata);\" jsvalues=\".jstdata:id\">Close Window</button>\n        <button onclick=\"refreshSelectedTab(this.jstdata);\" jsvalues=\".jstdata:id\">Refresh Selected Tab</button>\n      </div>\n    </div>\n    <div style=\"background-color: #EEEEBB; margin: 20px; padding: 8px\">\n      <h3 style=\"text-align: center; margin: 8px\"> Create Window</h3>\n      <div style=\"margin: 8px\">\n        <div style=\"width: 300px; display: inline-block\">\n          left: <input style=\"width: 20px\" type=\"text\" id=\"new_window_left\" />\n          top: <input style=\"width: 20px\" type=\"text\" id=\"new_window_top\" />\n          width: <input style=\"width: 20px\" type=\"text\" id=\"new_window_width\" />\n          height: <input style=\"width: 20px\" type=\"text\" id=\"new_window_height\" />\n        </div>\n      </div>\n      <div style=\"margin: 8px\">\n        <div>\n          <div style=\"width: 40px; display:inline-block\">url:</div>\n          <input style=\"width: 90%\" type=\"text\" id=\"new_window_url\" />\n        </div>\n      </div>\n      <button onclick=\"createWindow();\">Create</button>\n    </div>\n    <div style=\"background-color: #EEEEAA; margin: 20px; padding: 8px\">\n      <h3 style=\"text-align: center; margin: 8px\"> Create Tab</h3>\n      <div style=\"margin: 8px\">\n        <div style=\"width: 300px; display: inline-block\">\n          index: <input style=\"width: 20px\" type=\"text\" id=\"index_new\" />\n          windowId: <input style=\"width: 20px\" type=\"text\" id=\"windowId_new\" />\n          <button onclick=\"moveTab(this.jstdata);\" jsvalues=\".jstdata:id\">Move</button>\n        </div>\n      </div>\n      <div style=\"margin: 8px\">\n        <div>\n          <div style=\"width: 40px; display:inline-block\">title:</div>\n          <input style=\"width: 90%\" type=\"text\" id=\"title_new\" />\n        </div>\n        <div>\n          <div style=\"width: 40px; display:inline-block\">url:</div>\n          <input style=\"width: 90%\" type=\"text\" id=\"url_new\" />\n        </div>\n        <div><input type=\"checkbox\" id=\"selected_new\" /> Selected</div>\n      </div>\n      <button onclick=\"createTab();\">Create</button>\n    </div>\n    <div style=\"margin: 20px;\">\n      <button onclick=\"loadWindowList();\">Refresh</button>\n      <button onclick=\"updateAll();\">Update All</button>\n      <button onclick=\"moveAll();\">Move All</button>\n      <button onclick=\"clearLog();\">-->Clear Log</button>\n      <button onclick=\"chrome.windows.create();\">New Window</button>\n    </div>\n    <div id=\"log\" style=\"background-color: #EEAAEE; margin: 20px; padding: 8px\">\n    </div>\n  </body>\n</html>"
  },
  {
    "path": "_archive/mv2/api/tabs/inspector/tabs_api.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\ntabs = {};\ntabIds = [];\n\nfocusedWindowId = undefined;\ncurrentWindowId = undefined;\n\nfunction bootStrap() {\n  chrome.windows.getCurrent(function(currentWindow) {\n    currentWindowId = currentWindow.id;\n    chrome.windows.getLastFocused(function(focusedWindow) {\n      focusedWindowId = focusedWindow.id;\n      loadWindowList();\n    });\n  });\n}\n\nfunction isInt(i) {\n  return (typeof i == \"number\") && !(i % 1) && !isNaN(i);\n}\n\nfunction loadWindowList() {\n  chrome.windows.getAll({ populate: true }, function(windowList) {\n    tabs = {};\n    tabIds = [];\n    for (var i = 0; i < windowList.length; i++) {\n      windowList[i].current = (windowList[i].id == currentWindowId);\n      windowList[i].focused = (windowList[i].id == focusedWindowId);\n\n      for (var j = 0; j < windowList[i].tabs.length; j++) {\n        tabIds[tabIds.length] = windowList[i].tabs[j].id;\n        tabs[windowList[i].tabs[j].id] = windowList[i].tabs[j];\n      }\n    }\n\n    var input = new JsExprContext(windowList);\n    var output = document.getElementById('windowList');\n    jstProcess(input, output);\n  });\n}\n\nfunction updateTabData(id) {\n  var retval = {\n    url: document.getElementById('url_' + id).value,\n    selected: document.getElementById('selected_' + id).value ? true : false\n  }\n\n  return retval;\n}\n\nfunction updateTab(id){\n  try {\n    chrome.tabs.update(id, updateTabData(id));\n  } catch (e) {\n    alert(e);\n  }\n}\n\nfunction moveTabData(id) {\n  return {\n    'index': parseInt(document.getElementById('index_' + id).value),\n    'windowId': parseInt(document.getElementById('windowId_' + id).value)\n  }\n}\nfunction moveTab(id) {\n  try {\n    chrome.tabs.move(id, moveTabData(id));\n  } catch (e) {\n    alert(e);\n  }\n}\n\nfunction createTabData(id) {\n  return {\n    'index': parseInt(document.getElementById('index_' + id).value),\n    'windowId': parseInt(document.getElementById('windowId_' + id).value),\n    'index': parseInt(document.getElementById('index_' + id).value),\n    'url': document.getElementById('url_' + id).value,\n    'selected': document.getElementById('selected_' + id).value ? true : false\n  }\n}\n\nfunction createTab() {\n  var args = createTabData('new')\n\n  if (!isInt(args.windowId))\n    delete args.windowId;\n  if (!isInt(args.index))\n    delete args.index;\n\n  try {\n    chrome.tabs.create(args);\n  } catch (e) {\n    alert(e);\n  }\n}\n\nfunction updateAll() {\n  try {\n    for (var i = 0; i < tabIds.length; i++) {\n      chrome.tabs.update(tabIds[i], updateTabData(tabIds[i]));\n    }\n  } catch(e) {\n    alert(e);\n  }\n}\n\nfunction moveAll() {\n  appendToLog('moving all');\n  try {\n    for (var i = 0; i < tabIds.length; i++) {\n      chrome.tabs.move(tabIds[i], moveTabData(tabIds[i]));\n    }\n  } catch(e) {\n    alert(e);\n  }\n}\n\nfunction removeTab(tabId) {\n  try {\n    chrome.tabs.remove(tabId, function() {\n      appendToLog('tab: ' + tabId + ' removed.');\n    });\n  } catch (e) {\n    alert(e);\n  }\n}\n\nfunction appendToLog(logLine) {\n  document.getElementById('log')\n      .appendChild(document.createElement('div'))\n      .innerText = \"> \" + logLine;\n}\n\nfunction clearLog() {\n  document.getElementById('log').innerText = '';\n}\n\nchrome.windows.onCreated.addListener(function(createInfo) {\n  appendToLog('windows.onCreated -- window: ' + createInfo.id);\n  loadWindowList();\n});\n\nchrome.windows.onFocusChanged.addListener(function(windowId) {\n  focusedWindowId = windowId;\n  appendToLog('windows.onFocusChanged -- window: ' + windowId);\n  loadWindowList();\n});\n\nchrome.windows.onRemoved.addListener(function(windowId) {\n  appendToLog('windows.onRemoved -- window: ' + windowId);\n  loadWindowList();\n});\n\nchrome.tabs.onCreated.addListener(function(tab) {\n  appendToLog(\n      'tabs.onCreated -- window: ' + tab.windowId + ' tab: ' + tab.id +\n      ' title: ' + tab.title + ' index ' + tab.index + ' url ' + tab.url);\n  loadWindowList();\n});\n\nchrome.tabs.onAttached.addListener(function(tabId, props) {\n  appendToLog(\n      'tabs.onAttached -- window: ' + props.newWindowId + ' tab: ' + tabId +\n      ' index ' + props.newPosition);\n  loadWindowList();\n});\n\nchrome.tabs.onMoved.addListener(function(tabId, props) {\n  appendToLog(\n      'tabs.onMoved -- window: ' + props.windowId + ' tab: ' + tabId +\n      ' from ' + props.fromIndex + ' to ' +  props.toIndex);\n  loadWindowList();\n});\n\nfunction refreshTab(tabId) {\n  chrome.tabs.get(tabId, function(tab) {\n    var input = new JsExprContext(tab);\n    var output = document.getElementById('tab_' + tab.id);\n    jstProcess(input, output);\n    appendToLog('tab refreshed -- tabId: ' + tab.id + ' url: ' + tab.url);\n  });\n}\n\nchrome.tabs.onUpdated.addListener(function(tabId, props) {\n  appendToLog(\n      'tabs.onUpdated -- tab: ' + tabId + ' status ' + props.status +\n      ' url ' + props.url);\n  refreshTab(tabId);\n});\n\nchrome.tabs.onDetached.addListener(function(tabId, props) {\n  appendToLog(\n      'tabs.onDetached -- window: ' + props.oldWindowId + ' tab: ' + tabId +\n      ' index ' + props.oldPosition);\n  loadWindowList();\n});\n\nchrome.tabs.onSelectionChanged.addListener(function(tabId, props) {\n  appendToLog(\n      'tabs.onSelectionChanged -- window: ' + props.windowId + ' tab: ' +\n      tabId);\n  loadWindowList();\n});\n\nchrome.tabs.onRemoved.addListener(function(tabId) {\n  appendToLog('tabs.onRemoved -- tab: ' + tabId);\n  loadWindowList();\n});\n\nfunction createWindow() {\n  var args = {\n    'left': parseInt(document.getElementById('new_window_left').value),\n    'top': parseInt(document.getElementById('new_window_top').value),\n    'width': parseInt(document.getElementById('new_window_width').value),\n    'height': parseInt(document.getElementById('new_window_height').value),\n    'url': document.getElementById('new_window_url').value\n  }\n\n  if (!isInt(args.left))\n    delete args.left;\n  if (!isInt(args.top))\n    delete args.top;\n  if (!isInt(args.width))\n    delete args.width;\n  if (!isInt(args.height))\n    delete args.height;\n  if (!args.url)\n    delete args.url;\n\n  try {\n    chrome.windows.create(args);\n  } catch(e) {\n    alert(e);\n  }\n}\n\nfunction refreshWindow(windowId) {\n  chrome.windows.get(windowId, function(window) {\n    chrome.tabs.getAllInWindow(window.id, function(tabList) {\n      window.tabs = tabList;\n      var input = new JsExprContext(window);\n      var output = document.getElementById('window_' + window.id);\n      jstProcess(input, output);\n      appendToLog(\n          'window refreshed -- windowId: ' + window.id + ' tab count:' +\n          window.tabs.length);\n    });\n  });\n}\n\nfunction updateWindowData(id) {\n  var retval = {\n    left: parseInt(document.getElementById('left_' + id).value),\n    top: parseInt(document.getElementById('top_' + id).value),\n    width: parseInt(document.getElementById('width_' + id).value),\n    height: parseInt(document.getElementById('height_' + id).value)\n  }\n  if (!isInt(retval.left))\n    delete retval.left;\n  if (!isInt(retval.top))\n    delete retval.top;\n  if (!isInt(retval.width))\n    delete retval.width;\n  if (!isInt(retval.height))\n    delete retval.height;\n\n  return retval;\n}\n\nfunction updateWindow(id){\n  try {\n    chrome.windows.update(id, updateWindowData(id));\n  } catch (e) {\n    alert(e);\n  }\n}\n\nfunction removeWindow(windowId) {\n  try {\n    chrome.windows.remove(windowId, function() {\n      appendToLog('window: ' + windowId + ' removed.');\n    });\n  } catch (e) {\n    alert(e);\n  }\n}\n\nfunction refreshSelectedTab(windowId) {\n  chrome.tabs.query({active: true, currentWindow: true} function(tabs) {\n    var input = new JsExprContext(tabs[0]);\n    var output = document.getElementById('tab_' + tabs[0].id);\n    jstProcess(input, output);\n    appendToLog(\n        'selected tab refreshed -- tabId: ' + tabs[0].id +\n        ' url:' + tabs[0].url);\n  });\n}\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  bootStrap();\n});"
  },
  {
    "path": "_archive/mv2/api/tabs/pin/README",
    "content": "Demo Chrome Extension that uses the Tab Pinning API. Enables a new keyboard\nshortcut (Ctrl + Shift + P) to toggle pinning and unpinning of the current tab.\n"
  },
  {
    "path": "_archive/mv2/api/tabs/pin/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.commands.onCommand.addListener(function(command) {\n  if (command == \"toggle-pin\") {\n    // Get the currently selected tab\n    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {\n      // Toggle the pinned status\n      var current = tabs[0]\n      chrome.tabs.update(current.id, {'pinned': !current.pinned});\n    });\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/api/tabs/pin/manifest.json",
    "content": "{\n  \"name\": \"Keyboard Pin\",\n  \"version\": \"0.3\",\n  \"description\": \"Creates a keyboard shortcut (Alt + Shift + P) to toggle the pinned state of the currently selected tab\",\n  \"background\": {\n    \"persistent\": false,\n    \"scripts\": [\"background.js\"]\n  },\n  \"commands\": {\n    \"toggle-pin\": {\n      \"suggested_key\": { \"default\": \"Alt+Shift+P\" },\n      \"description\": \"Toggle tab pin\"\n    }\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/tabs/screenshot/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// To make sure we can uniquely identify each screenshot tab, add an id as a\n// query param to the url that displays the screenshot.\n// Note: It's OK that this is a global variable (and not in localStorage),\n// because the event page will stay open as long as any screenshot tabs are\n// open.\nvar id = 100;\n\n// Listen for a click on the camera icon. On that click, take a screenshot.\nchrome.browserAction.onClicked.addListener(function() {\n\n  chrome.tabs.captureVisibleTab(function(screenshotUrl) {\n    var viewTabUrl = chrome.extension.getURL('screenshot.html?id=' + id++)\n    var targetId = null;\n\n    chrome.tabs.onUpdated.addListener(function listener(tabId, changedProps) {\n      // We are waiting for the tab we opened to finish loading.\n      // Check that the tab's id matches the tab we opened,\n      // and that the tab is done loading.\n      if (tabId != targetId || changedProps.status != \"complete\")\n        return;\n\n      // Passing the above test means this is the event we were waiting for.\n      // There is nothing we need to do for future onUpdated events, so we\n      // use removeListner to stop getting called when onUpdated events fire.\n      chrome.tabs.onUpdated.removeListener(listener);\n\n      // Look through all views to find the window which will display\n      // the screenshot.  The url of the tab which will display the\n      // screenshot includes a query parameter with a unique id, which\n      // ensures that exactly one view will have the matching URL.\n      var views = chrome.extension.getViews();\n      for (var i = 0; i < views.length; i++) {\n        var view = views[i];\n        if (view.location.href == viewTabUrl) {\n          view.setScreenshotUrl(screenshotUrl);\n          break;\n        }\n      }\n    });\n\n    chrome.tabs.create({url: viewTabUrl}, function(tab) {\n      targetId = tab.id;\n    });\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/tabs/screenshot/manifest.json",
    "content": "{\n  \"name\": \"Test Screenshot Extension\",\n  \"version\": \"1.3\",\n  \"description\": \"Demonstrate screenshot functionality in the chrome.tabs api.\",\n  \"background\": {\n    \"persistent\": false,\n    \"scripts\": [\"background.js\"]\n  },\n  \"browser_action\": {\n    \"default_icon\": \"camera.png\",\n    \"default_title\": \"Take a screen shot!\"\n  },\n  \"permissions\": [\n    \"activeTab\"\n  ],\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/tabs/screenshot/screenshot.html",
    "content": "<html>\n<script src=\"screenshot.js\"></script>\n<body>\n  Image here:\n  <p>\n    <img id=\"target\" src=\"white.png\" height=\"480\">\n  <p>\n  End image\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/tabs/screenshot/screenshot.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction setScreenshotUrl(url) {\n  document.getElementById('target').src = url;\n}\n"
  },
  {
    "path": "_archive/mv2/api/tabs/zoom/README",
    "content": "Demo Chrome Extension that uses the Tab Zoom API. Demonstrates manipulation of\ntab zoom levels and zoom modes and use of zoom-change event listeners.\n"
  },
  {
    "path": "_archive/mv2/api/tabs/zoom/background.js",
    "content": "// Copyright 2014 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview In this extension, the background page demonstrates how to\n *               listen for zoom change events.\n*/\n\nfunction zoomChangeListener(zoomChangeInfo) {\n  var settings_str = \"mode:\" + zoomChangeInfo.zoomSettings.mode +\n      \", scope:\" + zoomChangeInfo.zoomSettings.scope;\n\n  console.log('[ZoomDemoExtension] zoomChangeListener(tab=' +\n              zoomChangeInfo.tabId + ', new=' +\n              zoomChangeInfo.newZoomFactor + ', old=' +\n              zoomChangeInfo.oldZoomFactor + ', ' +\n              settings_str + ')');\n}\n\nchrome.tabs.onZoomChange.addListener(zoomChangeListener);\n"
  },
  {
    "path": "_archive/mv2/api/tabs/zoom/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n\n  \"name\": \"Tabs Zoom API Demo\",\n  \"description\": \"This extension allows the user to explore features of the new tabs zoom api.\",\n\n  \"version\": \"0.1\",\n\n  \"icons\": {\n    \"16\": \"zoom16.png\",\n    \"48\": \"zoom48.png\"\n  },\n\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n\n  \"browser_action\": {\n    \"default_icon\": \"zoom19.png\",\n    \"default_title\": \"Zoom Extension Demo\",\n    \"default_popup\": \"popup.html\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/tabs/zoom/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Tab Zoom Extension</title>\n    <style>\n      body {\n        width: 150px;\n        overflow-x: hidden;\n        color: #ffff00;\n        background-color: #186464;\n      }\n\n      img {\n        margin: 5px;\n        border: 2px solid black;\n        vertical-align: middle;\n        width: 19px;\n        height: 19px;\n      }\n    </style>\n    <script src=\"popup.js\"></script>\n  </head>\n  <body>\n    <div style=\"text-align: center\">\n      <table style=\"margin: 0px auto\">\n        <tr>\n          <td><button type=\"button\" id=\"decreaseButton\">-</button></td>\n          <td><div style=\"width: 50px; border-style: solid; border-width: 1px\"\n                   id=\"displayDiv\">100%</div></td>\n          <td><button type=\"button\" id=\"increaseButton\">+</button></td>\n        </td>\n      </table>\n      <button type=\"button\" id=\"defaultButton\">Reset to Default</button>\n      <div id=\"defaultLabel\"></div>\n    </div>\n    <p>\n    <div style=\"border-width: 2px; border-style: solid; border-color: #7f0000; padding: 2px\">\n      <form style=\"border-width: 2px; border-style: solid; border-color: #7f0000\">\n        <b>Mode:</b><br>\n        <input type=\"radio\" name=\"modeRadio\" value=\"automatic\">automatic<br>\n        <input type=\"radio\" name=\"modeRadio\" value=\"manual\">manual<br>\n        <input type=\"radio\" name=\"modeRadio\" value=\"disabled\">disabled\n      </form><br>\n      <form style=\"border-width: 2px; border-style: solid; border-color: #7f0000\">\n        <b>Scope:</b><br>\n        <input type=\"radio\" name=\"scopeRadio\" value=\"per-origin\">per-origin<br>\n        <input type=\"radio\" name=\"scopeRadio\" value=\"per-tab\">per-tab\n      </form>\n      <button type=\"button\" id=\"setModeButton\">Set Zoom Settings</button>\n    </div>\n    <p>\n    <button type=\"button\" id=\"closeButton\">Close</button>\n  </body>\n</html>\n\n"
  },
  {
    "path": "_archive/mv2/api/tabs/zoom/popup.js",
    "content": "// Copyright 2014 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview This code supports the popup behaviour of the extension, and\n *               demonstrates how to:\n *\n *               1) Set the zoom for a tab using tabs.setZoom()\n *               2) Read the current zoom of a tab using tabs.getZoom()\n *               3) Set the zoom mode of a tab using tabs.setZoomSettings()\n *               4) Read the current zoom mode of a tab using\n *               tabs.getZoomSettings()\n *\n *               It also demonstrates using a zoom change listener to update the\n *               contents of a control.\n */\n\nzoomStep = 1.1;\ntabId = -1;\n\nfunction displayZoomLevel(level) {\n  var percentZoom = parseFloat(level) * 100;\n  var zoom_percent_str = percentZoom.toFixed(1) + '%';\n\n  document.getElementById('displayDiv').textContent = zoom_percent_str;\n}\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  // Find the tabId of the current (active) tab. We could just omit the tabId\n  // parameter in the function calls below, and they would act on the current\n  // tab by default, but for the purposes of this demo we will always use the\n  // API with an explicit tabId to demonstrate its use.\n  chrome.tabs.query({active: true}, function (tabs) {\n    if (tabs.length > 1)\n      console.log(\n          '[ZoomDemoExtension] Query unexpectedly returned more than 1 tab.');\n    tabId = tabs[0].id;\n\n    chrome.tabs.getZoomSettings(tabId, function(zoomSettings) {\n      var modeRadios = document.getElementsByName('modeRadio');\n      for (var i = 0; i < modeRadios.length; i++) {\n        if (modeRadios[i].value == zoomSettings.mode)\n          modeRadios[i].checked = true;\n      }\n\n      var scopeRadios = document.getElementsByName('scopeRadio');\n      for (var i = 0; i < scopeRadios.length; i++) {\n        if (scopeRadios[i].value == zoomSettings.scope)\n          scopeRadios[i].checked = true;\n      }\n\n      var percentDefaultZoom =\n          parseFloat(zoomSettings.defaultZoomFactor) * 100;\n      document.getElementById('defaultLabel').textContent =\n          'Default: ' + percentDefaultZoom.toFixed(1) + '%';\n    });\n\n    chrome.tabs.getZoom(tabId, displayZoomLevel);\n  });\n\n  document.getElementById('increaseButton').onclick = doZoomIn;\n  document.getElementById('decreaseButton').onclick = doZoomOut;\n  document.getElementById('defaultButton').onclick = doZoomDefault;\n  document.getElementById('setModeButton').onclick = doSetMode;\n  document.getElementById('closeButton').onclick = doClose;\n});\n\nfunction zoomChangeListener(zoomChangeInfo) {\n  displayZoomLevel(zoomChangeInfo.newZoomFactor);\n}\n\nchrome.tabs.onZoomChange.addListener(zoomChangeListener);\n\nfunction changeZoomByFactorDelta(factorDelta) {\n  if (tabId == -1)\n    return;\n\n  chrome.tabs.getZoom(tabId, function(zoomFactor) {\n    var newZoomFactor = factorDelta * zoomFactor;\n    chrome.tabs.setZoom(tabId, newZoomFactor, function() {\n      if (chrome.runtime.lastError)\n        console.log('[ZoomDemoExtension] ' + chrome.runtime.lastError.message);\n    });\n  });\n}\n\nfunction doZoomIn() {\n  changeZoomByFactorDelta(zoomStep);\n}\n\nfunction doZoomOut() {\n  changeZoomByFactorDelta(1.0/zoomStep);\n}\n\nfunction doZoomDefault() {\n  if (tabId == -1)\n    return;\n\n  chrome.tabs.setZoom(tabId, 0, function() {\n    if (chrome.runtime.lastError)\n      console.log('[ZoomDemoExtension] ' + chrome.runtime.lastError.message);\n  });\n}\n\nfunction doSetMode() {\n  if (tabId == -1)\n    return;\n\n  var modeVal;\n  var modeRadios = document.getElementsByName('modeRadio');\n  for (var i = 0; i < modeRadios.length; i++) {\n    if (modeRadios[i].checked)\n      modeVal = modeRadios[i].value;\n  }\n\n  var scopeVal;\n  var scopeRadios = document.getElementsByName('scopeRadio');\n  for (var i = 0; i < scopeRadios.length; i++) {\n    if (scopeRadios[i].checked)\n      scopeVal = scopeRadios[i].value;\n  }\n\n  if (!modeVal || !scopeVal) {\n    console.log(\n        '[ZoomDemoExtension] Must specify values for both mode & scope.');\n    return;\n  }\n\n  chrome.tabs.setZoomSettings(tabId, { mode: modeVal, scope: scopeVal },\n    function() {\n      if (chrome.runtime.lastError) {\n        console.log('[ZoomDemoExtension] doSetMode() error: ' +\n                    chrome.runtime.lastError.message);\n      }\n    });\n}\n\nfunction doClose() {\n  self.close();\n}\n"
  },
  {
    "path": "_archive/mv2/api/topsites/basic/manifest.json",
    "content": "{\n  \"name\": \"Top Sites\",\n  \"version\": \"1.2\",\n  \"description\": \"Shows the top sites in a browser action\",\n  \"permissions\": [\"topSites\"],\n  \"browser_action\": {\n    \"default_icon\": \"icon.png\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/topsites/basic/popup.html",
    "content": "<!DOCTYPE HTML>\n<html>\n  <body>\n    <h2>Most Visited:</h2>\n    <div id='mostVisited_div'></div>\n    <script src='popup.js'></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/topsites/basic/popup.js",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Event listener for clicks on links in a browser action popup.\n// Open the link in a new tab of the current window.\nfunction onAnchorClick(event) {\n  chrome.tabs.create({ url: event.srcElement.href });\n  return false;\n}\n\n// Given an array of URLs, build a DOM list of these URLs in the\n// browser action popup.\nfunction buildPopupDom(mostVisitedURLs) {\n  var popupDiv = document.getElementById('mostVisited_div');\n  var ol = popupDiv.appendChild(document.createElement('ol'));\n\n  for (var i = 0; i < mostVisitedURLs.length; i++) {\n    var li = ol.appendChild(document.createElement('li'));\n    var a = li.appendChild(document.createElement('a'));\n    a.href = mostVisitedURLs[i].url;\n    a.appendChild(document.createTextNode(mostVisitedURLs[i].title));\n    a.addEventListener('click', onAnchorClick);\n  }\n}\n\nchrome.topSites.get(buildPopupDom);\n"
  },
  {
    "path": "_archive/mv2/api/topsites/magic8ball/manifest.json",
    "content": "{\n  \"name\": \"NTP prototyping extension\",\n  \"version\": \"1.1\",\n  \"description\": \"extension to prototype new NTP designs\",\n  \"chrome_url_overrides\" : {\n    \"newtab\": \"newTab.html\"\n  },\n  \"permissions\": [\n    \"topSites\",\n    \"chrome://favicon/\"\n  ],\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/topsites/magic8ball/newTab.css",
    "content": "/* Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nhtml {\n  background-color: #ddd;\n}\n\n#spacer {\n  height: 200px;\n}\n\n#title {\n  color: #555;\n  font-weight: bold;\n  height: 200px;\n  vertical-align: middle;\n}\n\n#mostVisitedThumb {\n  background-repeat: no-repeat;\n  height: 200px;\n  margin-left: 20px;\n  padding-left: 20px;\n  vertical-align: middle;\n  width: 212px;\n}\n"
  },
  {
    "path": "_archive/mv2/api/topsites/magic8ball/newTab.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n\n<html>\n<meta charset=\"utf-8\">\n<script src=\"newTab.js\"></script>\n<link rel=\"stylesheet\" href=\"newTab.css\">\n\n<title>New 8ball</title>\n\n<body>\n  <center>\n    <div id=\"spacer\"></div>\n    <span id='title'>Magic 8 ball says to visit</span>\n    <a id='mostVisitedThumb'>\n      <span></span>\n    </a>\n  </center>\n</body>\n\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/topsites/magic8ball/newTab.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction $(id) {\n  return document.getElementById(id);\n}\n\nfunction thumbnailsGotten(data) {\n  var eightBallWindow = $('mostVisitedThumb');\n  var rand = Math.floor(Math.random() * data.length);\n  eightBallWindow.href = data[rand].url;\n  eightBallWindow.textContent = data[rand].title;\n  eightBallWindow.style.backgroundImage = 'url(chrome://favicon/' +\n      data[rand].url + ')';\n}\n\nwindow.onload = function() {\n  chrome.topSites.get(thumbnailsGotten);\n}\n"
  },
  {
    "path": "_archive/mv2/api/ttsEngine/console_tts_engine/console_tts_engine.html",
    "content": "<html>\n<head>\n  <title>Console TTS Engine</title>\n  <style>\n    body {\n      font-family: arial, helvetica, sans-serif;\n    }\n    table {\n      text-align: center;\n      padding: 10px;\n    }\n    #text {\n      text-align: left;\n      padding: 4px;\n      border: 1px solid #aaa;\n      width: 99%;\n      min-height: 100px;\n      overflow: auto;\n    }\n  </style>\n  <script type=\"text/javascript\">\n    function clearText() {\n      document.getElementById(\"text\").innerHTML = \"\";\n    }\n  </script>\n</head>\n<body>\n  <table>\n    <tr>\n      <th>Voice Name</th>\n      <th>Language</th>\n      <th>Rate</th>\n      <th>Pitch</th>\n      <th>Volume</th>\n    </tr>\n    <tr>\n      <td id=\"voiceName\"></td>\n      <td id=\"lang\"></td>\n      <td id=\"rate\"></td>\n      <td id=\"pitch\"></td>\n      <td id=\"volume\"></td>\n    </tr>\n  </table>\n  <button onclick=\"clearText()\">Clear</button>\n  <p id=\"text\"></p>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/ttsEngine/console_tts_engine/console_tts_engine.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar timeoutId;\nvar ttsId = -1;\nvar ttsWindow;\nvar milliseconds;\nvar curOptions;\n\nfunction areNewOptions(options) {\n  var properties = ['voiceName', 'lang', 'rate', 'pitch', 'volume'];\n\n  for (var i = 0; i < properties.length; ++i) {\n    if (options[properties[i]] != curOptions[properties[i]]) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\nfunction getTtsElement(element) {\n  return ttsWindow.document.getElementById(element);\n}\n\nfunction appendText(text) {\n  getTtsElement(\"text\").innerHTML += text;\n}\n\nfunction logOptions() {\n  getTtsElement(\"voiceName\").innerHTML = curOptions.voiceName;\n  getTtsElement(\"lang\").innerHTML = curOptions.lang;\n  getTtsElement(\"rate\").innerHTML = curOptions.rate;\n  getTtsElement(\"pitch\").innerHTML = curOptions.pitch;\n  getTtsElement(\"volume\").innerHTML = curOptions.volume;\n}\n\nfunction logUtterance(utterance, index, sendTtsEvent) {\n  if (index == utterance.length) {\n    sendTtsEvent({'type': 'end', 'charIndex': utterance.length});\n    return;\n  }\n\n  appendText(utterance[index]);\n\n  if (utterance[index] == ' ') {\n    sendTtsEvent({'type': 'word', 'charIndex': index});\n  }\n  else if (utterance[index] == '.' ||\n      utterance[index] == '?' ||\n      utterance[index] == '!') {\n    sendTtsEvent({'type': 'sentence', 'charIndex': index});\n  }\n\n  timeoutId = setTimeout(function() {\n    logUtterance(utterance, ++index, sendTtsEvent)\n  }, milliseconds);\n}\n\nvar speakListener = function(utterance, options, sendTtsEvent) {\n  clearTimeout(timeoutId);\n\n  sendTtsEvent({'type': 'start', 'charIndex': 0});\n\n  if (ttsId == -1) {\n    // Create a new window that overlaps the bottom 40% of the current window\n    chrome.windows.getCurrent(function(curWindow) {\n      chrome.windows.create(\n          {\"url\": \"console_tts_engine.html\",\n           \"focused\": false,\n           \"top\": Math.round(curWindow.top + 6/10 * curWindow.height),\n           \"left\": curWindow.left,\n           \"width\": curWindow.width,\n           \"height\": Math.round(4/10 * curWindow.height)},\n          function(newWindow) {\n            ttsId = newWindow.id;\n            ttsWindow = chrome.extension.getViews({\"windowId\": ttsId})[0];\n\n            curOptions = options;\n            logOptions();\n\n            // Fastest timeout == 1 ms (@ options.rate = 10.0)\n            milliseconds = 10 / curOptions.rate;\n            logUtterance(utterance, 0, sendTtsEvent);\n          }\n      );\n    });\n  } else {\n    if (areNewOptions(options)) {\n      curOptions = options;\n      logOptions();\n\n      milliseconds = 10 / curOptions.rate;\n    }\n\n    logUtterance(utterance, 0, sendTtsEvent);\n  }\n\n};\n\nvar stopListener = function() {\n  clearTimeout(timeoutId);\n};\n\nvar removedListener = function(windowId, removeInfo) {\n  if (ttsId == windowId) {\n    ttsId = -1;\n  }\n}\n\nchrome.ttsEngine.onSpeak.addListener(speakListener);\nchrome.ttsEngine.onStop.addListener(stopListener);\nchrome.windows.onRemoved.addListener(removedListener);\n"
  },
  {
    "path": "_archive/mv2/api/ttsEngine/console_tts_engine/manifest.json",
    "content": "{\n  \"name\": \"Console TTS Engine\",\n  \"manifest_version\": 2,\n  \"version\": \"2.1\",\n  \"description\": \"A \\\"silent\\\" TTS engine that prints text to a small window rather than synthesizing speech.\",\n  \"permissions\": [\"ttsEngine\", \"tabs\"],\n  \"background\": {\n    \"persistent\": false,\n    \"scripts\": [\"console_tts_engine.js\"]\n  },\n  \"tts_engine\": {\n    \"voices\": [\n      {\n        \"voice_name\": \"Console\",\n        \"event_types\": [\"start\", \"word\", \"sentence\", \"end\"]\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/water_alarm_notification/background.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n'use strict';\n\nchrome.alarms.onAlarm.addListener(function() {\n  chrome.browserAction.setBadgeText({text: ''});\n  chrome.notifications.create({\n      type:     'basic',\n      iconUrl:  'stay_hydrated.png',\n      title:    'Time to Hydrate',\n      message:  'Everyday I\\'m Guzzlin\\'!',\n      buttons: [\n        {title: 'Keep it Flowing.'}\n      ],\n      priority: 0});\n});\n\nchrome.notifications.onButtonClicked.addListener(function() {\n  chrome.storage.sync.get(['minutes'], function(item) {\n    chrome.browserAction.setBadgeText({text: 'ON'});\n    chrome.alarms.create({delayInMinutes: item.minutes});\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/water_alarm_notification/manifest.json",
    "content": "{\n  \"name\": \"Drink Water Event Popup\",\n  \"description\": \"Demonstrates usage and features of the event page by reminding user to drink water\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 2,\n  \"permissions\": [\"alarms\", \"notifications\", \"storage\"],\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"browser_action\": {\n    \"default_title\": \"Drink Water Event\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"icons\": {\n    \"16\": \"drink_water16.png\",\n    \"32\": \"drink_water32.png\",\n    \"48\": \"drink_water48.png\",\n    \"128\": \"drink_water128.png\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/water_alarm_notification/popup.html",
    "content": "<!-- Copyright 2017 The Chromium Authors. All rights reserved.\nUse of this source code is governed by a BSD-style license that can be\nfound in the LICENSE file. -->\n<html>\n  <head>\n    <title>Water Popup</title>\n    <style>\n      body {\n        text-align: center;\n      }\n\n      #hydrateImage {\n        width: 100px;\n        margin: 5px;\n      }\n\n      button {\n        margin: 5px;\n        outline: none;\n      }\n\n      button:hover {\n        outline: #80DEEA dotted thick;\n      }\n    </style>\n    <!--\n      - JavaScript and HTML must be in separate files: see our Content Security\n      - Policy documentation[1] for details and explanation.\n      -\n      - [1]: https://developer.chrome.com/extensions/contentSecurityPolicy\n     -->\n  </head>\n  <body>\n      <img src='./stay_hydrated.png' id='hydrateImage'>\n      <!-- An Alarm delay of less than the minimum 1 minute will fire\n      in approximately 1 minute incriments if released -->\n      <button id='sampleSecond' value='0.1'>Sample Second</button>\n      <button id='15min' value='15'>15 Minutes</button>\n      <button id='30min' value='30'>30 Minutes</button>\n      <button id='cancelAlarm'>Cancel Alarm</button>\n   <!-- link to non-persistent background script -->\n   <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/water_alarm_notification/popup.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n'use strict';\n\nfunction setAlarm(event) {\n  let minutes = parseFloat(event.target.value);\n  chrome.browserAction.setBadgeText({text: 'ON'});\n  chrome.alarms.create({delayInMinutes: minutes});\n  chrome.storage.sync.set({minutes: minutes});\n  window.close();\n}\n\nfunction clearAlarm() {\n  chrome.browserAction.setBadgeText({text: ''});\n  chrome.alarms.clearAll();\n  window.close();\n}\n\n//An Alarm delay of less than the minimum 1 minute will fire\n// in approximately 1 minute increments if released\ndocument.getElementById('sampleSecond').addEventListener('click', setAlarm);\ndocument.getElementById('15min').addEventListener('click', setAlarm);\ndocument.getElementById('30min').addEventListener('click', setAlarm);\ndocument.getElementById('cancelAlarm').addEventListener('click', clearAlarm);\n"
  },
  {
    "path": "_archive/mv2/api/webNavigation/basic/_locales/en/messages.json",
    "content": "{\n  \"extName\":  {\n    \"message\": \"WebNavigation Tech Demo\",\n    \"description\": \"The extension name.\"\n  },\n  \"extDescription\": {\n    \"message\": \"Demonstration of the WebNavigation extension API.\",\n    \"description\": \"The extension description.\"\n  },\n\n  \"navigationDescription\": {\n    \"message\": \", requested $NUM$ times.  Loaded in an average of $LOAD$ miliseconds.\",\n    \"description\": \"The message posted in the popup for each stored navigation.\",\n    \"placeholders\": {\n      \"NUM\": {\n        \"content\": \"$1\",\n        \"example\": \"4 (The number of times this URL was accessed.)\"\n      },\n      \"LOAD\": {\n        \"content\": \"$2\",\n        \"example\": \"12.345 (The average load time in miliseconds.)\"\n      }\n    }\n  },\n\n  \"inHandler\": {\n    \"message\": \"In webNavigation[`%s`] handler: %o\",\n    \"description\": \"Notification displayed for each webNavigation event.\"\n  },\n\n  \"inHandlerError\": {\n    \"message\": \"In webNavigation[`%s`] handler: No data!\",\n    \"description\": \"Notification displayed in a webNavigation event handler without data!\"\n  },\n\n  \"errorCommittedWithoutPending\": {\n    \"message\": \"Wha?  `onCommitted` for `%s` called, though it's not pending: %o\",\n    \"description\": \"Error logged when `onCommitted` is triggered on a non-pending request.\"\n  },\n  \"errorCompletedWithoutPending\": {\n    \"message\": \"Wha?  `onCompleted` for `%s` called, though it's not pending: %o\",\n    \"description\": \"Error logged when `onCompleted` is triggered on a non-pending request.\"\n  },\n  \"errorErrorOccurredWithoutPending\": {\n    \"message\": \"Wha?  `onErrorOccurred` for `%s` called, though it's not pending: %o\",\n    \"description\": \"Error logged when `onErrorOccurred` is triggered on a non-pending request.\"\n  },\n  \"errorCommittedWithoutPending\": {\n    \"message\": \"Wha?  `onCompleted` for `%s` called, though it's not pending: %o\",\n    \"description\": \"Error logged when `onCompleted` is triggered on a non-pending request.\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/webNavigation/basic/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @filedescription Initializes the extension's background page.\n */\n\nvar nav = new NavigationCollector();\n\nvar eventList = ['onBeforeNavigate', 'onCreatedNavigationTarget',\n    'onCommitted', 'onCompleted', 'onDOMContentLoaded',\n    'onErrorOccurred', 'onReferenceFragmentUpdated', 'onTabReplaced',\n    'onHistoryStateUpdated'];\n\neventList.forEach(function(e) {\n  chrome.webNavigation[e].addListener(function(data) {\n    if (typeof data)\n      console.log(chrome.i18n.getMessage('inHandler'), e, data);\n    else\n      console.error(chrome.i18n.getMessage('inHandlerError'), e);\n  });\n});\n\n// Reset the navigation state on startup. We only want to collect data within a\n// session.\nchrome.runtime.onStartup.addListener(function() {\n  nav.resetDataStorage();\n});\n"
  },
  {
    "path": "_archive/mv2/api/webNavigation/basic/manifest.json",
    "content": "{\n  \"name\":           \"__MSG_extName__\",\n  \"version\":        \"0.2\",\n  \"description\":    \"__MSG_extDescription__\",\n  \"default_locale\": \"en\",\n  \"background\": {\n    \"persistent\": false,\n    \"scripts\": [\"navigation_collector.js\", \"background.js\"]\n  },\n  \"browser_action\": {\n    \"default_icon\": \"icon.png\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"permissions\":    [\n    \"webNavigation\", \"storage\"\n  ],\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/api/webNavigation/basic/navigation_collector.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * Implements the NavigationCollector object that powers the extension.\n *\n * @author mkwst@google.com (Mike West)\n */\n\n/**\n * Collects navigation events, and provides a list of successful requests\n * that you can do interesting things with. Calling the constructor will\n * automatically bind handlers to the relevant webnavigation API events,\n * and to a `getMostRequestedUrls` extension message for internal\n * communication between background pages and popups.\n *\n * @constructor\n */\nfunction NavigationCollector() {\n  /**\n   * A list of currently pending requests, implemented as a hash of each\n   * request's tab ID, frame ID, and URL in order to ensure uniqueness.\n   *\n   * @type {Object<string, {start: number}>}\n   * @private\n   */\n  this.pending_ = {};\n\n  /**\n   * A list of completed requests, implemented as a hash of each\n   * request's tab ID, frame ID, and URL in order to ensure uniqueness.\n   *\n   * @type {Object<string, Array<NavigationCollector.Request>>}\n   * @private\n   */\n  this.completed_ = {};\n\n  /**\n   * A list of requests that errored off, implemented as a hash of each\n   * request's tab ID, frame ID, and URL in order to ensure uniqueness.\n   *\n   * @type {Object<string, Array<NavigationCollector.Request>>}\n   * @private\n   */\n  this.errored_ = {};\n\n  // Bind handlers to the 'webNavigation' events that we're interested\n  // in handling in order to build up a complete picture of the whole\n  // navigation event.\n  chrome.webNavigation.onCreatedNavigationTarget.addListener(\n      this.onCreatedNavigationTargetListener_.bind(this));\n  chrome.webNavigation.onBeforeNavigate.addListener(\n      this.onBeforeNavigateListener_.bind(this));\n  chrome.webNavigation.onCompleted.addListener(\n      this.onCompletedListener_.bind(this));\n  chrome.webNavigation.onCommitted.addListener(\n      this.onCommittedListener_.bind(this));\n  chrome.webNavigation.onErrorOccurred.addListener(\n      this.onErrorOccurredListener_.bind(this));\n  chrome.webNavigation.onReferenceFragmentUpdated.addListener(\n      this.onReferenceFragmentUpdatedListener_.bind(this));\n  chrome.webNavigation.onHistoryStateUpdated.addListener(\n      this.onHistoryStateUpdatedListener_.bind(this));\n\n  // Bind handler to extension messages for communication from popup.\n  chrome.runtime.onMessage.addListener(this.onMessageListener_.bind(this));\n\n  this.loadDataStorage_();\n}\n\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n * The possible transition types that explain how the navigation event\n * was generated (i.e. \"The user clicked on a link.\" or \"The user submitted\n * a form\").\n *\n * @see http://code.google.com/chrome/extensions/trunk/history.html\n * @enum {string}\n */\nNavigationCollector.NavigationType = {\n  AUTO_BOOKMARK: 'auto_bookmark',\n  AUTO_SUBFRAME: 'auto_subframe',\n  FORM_SUBMIT: 'form_submit',\n  GENERATED: 'generated',\n  KEYWORD: 'keyword',\n  KEYWORD_GENERATED: 'keyword_generated',\n  LINK: 'link',\n  MANUAL_SUBFRAME: 'manual_subframe',\n  RELOAD: 'reload',\n  START_PAGE: 'start_page',\n  TYPED: 'typed'\n};\n\n/**\n * The possible transition qualifiers:\n *\n * * CLIENT_REDIRECT: Redirects caused by JavaScript, or a refresh meta tag\n *   on a page.\n *\n * * SERVER_REDIRECT: Redirected by the server via a 301/302 response.\n *\n * * FORWARD_BACK: User used the forward or back buttons to navigate through\n *   their browsing history.\n *\n * @enum {string}\n */\nNavigationCollector.NavigationQualifier = {\n  CLIENT_REDIRECT: 'client_redirect',\n  FORWARD_BACK: 'forward_back',\n  SERVER_REDIRECT: 'server_redirect'\n};\n\n/**\n * @typedef {{url: string, transitionType: NavigationCollector.NavigationType,\n *     transitionQualifier: Array<NavigationCollector.NavigationQualifier>,\n *     openedInNewTab: boolean, source: {frameId: ?number, tabId: ?number},\n *     duration: number}}\n */\nNavigationCollector.Request;\n\n///////////////////////////////////////////////////////////////////////////////\n\nNavigationCollector.prototype = {\n  /**\n   * Returns a somewhat unique ID for a given WebNavigation request.\n   *\n   * @param {!{tabId: ?number, frameId: ?number}} data Information\n   *     about the navigation event we'd like an ID for.\n   * @return {!string} ID created by combining the source tab ID and frame ID\n   *     (or target tab/frame IDs if there's no source), as the API ensures\n   *     that these will be unique across a single navigation event.\n   * @private\n   */\n  parseId_: function(data) {\n    return data.tabId + '-' + (data.frameId ? data.frameId : 0);\n  },\n\n\n  /**\n   * Creates an empty entry in the pending array if one doesn't already exist,\n   * and prepopulates the errored and completed arrays for ease of insertion\n   * later.\n   *\n   * @param {!string} id The request's ID, as produced by parseId_.\n   * @param {!string} url The request's URL.\n   */\n  prepareDataStorage_: function(id, url) {\n    this.pending_[id] = this.pending_[id] || {\n      openedInNewTab: false,\n      source: {\n        frameId: null,\n        tabId: null\n      },\n      start: null,\n      transitionQualifiers: [],\n      transitionType: null\n    };\n    this.completed_[url] = this.completed_[url] || [];\n    this.errored_[url] = this.errored_[url] || [];\n  },\n\n\n  /**\n   * Retrieves our saved data from storage.\n   * @private\n   */\n  loadDataStorage_: function() {\n    chrome.storage.local.get({\n      \"completed\": {},\n      \"errored\": {},\n    }, function(storage) {\n      this.completed_ = storage.completed;\n      this.errored_ = storage.errored;\n    }.bind(this));\n  },\n\n\n  /**\n   * Persists our state to the storage API.\n   * @private\n   */\n  saveDataStorage_: function() {\n    chrome.storage.local.set({\n      \"completed\": this.completed_,\n      \"errored\": this.errored_,\n    });\n  },\n\n\n  /**\n   * Resets our saved state to empty.\n   */\n  resetDataStorage: function() {\n    this.completed_ = {};\n    this.errored_ = {};\n    this.saveDataStorage_();\n    // Load again, in case there is an outstanding storage.get request. This\n    // one will reload the newly-cleared data.\n    this.loadDataStorage_();\n  },\n\n\n  /**\n   * Handler for the 'onCreatedNavigationTarget' event. Updates the\n   * pending request with a source frame/tab, and notes that it was opened in a\n   * new tab.\n   *\n   * Pushes the request onto the\n   * 'pending_' object, and stores it for later use.\n   *\n   * @param {!Object} data The event data generated for this request.\n   * @private\n   */\n  onCreatedNavigationTargetListener_: function(data) {\n    var id = this.parseId_(data);\n    this.prepareDataStorage_(id, data.url);\n    this.pending_[id].openedInNewTab = data.tabId;\n    this.pending_[id].source = {\n      tabId: data.sourceTabId,\n      frameId: data.sourceFrameId\n    };\n    this.pending_[id].start = data.timeStamp;\n  },\n\n\n  /**\n   * Handler for the 'onBeforeNavigate' event. Pushes the request onto the\n   * 'pending_' object, and stores it for later use.\n   *\n   * @param {!Object} data The event data generated for this request.\n   * @private\n   */\n  onBeforeNavigateListener_: function(data) {\n    var id = this.parseId_(data);\n    this.prepareDataStorage_(id, data.url);\n    this.pending_[id].start = this.pending_[id].start || data.timeStamp;\n  },\n\n\n  /**\n   * Handler for the 'onCommitted' event. Updates the pending request with\n   * transition information.\n   *\n   * Pushes the request onto the\n   * 'pending_' object, and stores it for later use.\n   *\n   * @param {!Object} data The event data generated for this request.\n   * @private\n   */\n  onCommittedListener_: function(data) {\n    var id = this.parseId_(data);\n    if (!this.pending_[id]) {\n      console.warn(\n          chrome.i18n.getMessage('errorCommittedWithoutPending'),\n          data.url,\n          data);\n    } else {\n      this.prepareDataStorage_(id, data.url);\n      this.pending_[id].transitionType = data.transitionType;\n      this.pending_[id].transitionQualifiers =\n          data.transitionQualifiers;\n    }\n  },\n\n\n  /**\n   * Handler for the 'onReferenceFragmentUpdated' event. Updates the pending\n   * request with transition information.\n   *\n   * Pushes the request onto the\n   * 'pending_' object, and stores it for later use.\n   *\n   * @param {!Object} data The event data generated for this request.\n   * @private\n   */\n  onReferenceFragmentUpdatedListener_: function(data) {\n    var id = this.parseId_(data);\n    if (!this.pending_[id]) {\n      this.completed_[data.url] = this.completed_[data.url] || [];\n      this.completed_[data.url].push({\n        duration: 0,\n        openedInNewWindow: false,\n        source: {\n          frameId: null,\n          tabId: null\n        },\n        transitionQualifiers: data.transitionQualifiers,\n        transitionType: data.transitionType,\n        url: data.url\n      });\n      this.saveDataStorage_();\n    } else {\n      this.prepareDataStorage_(id, data.url);\n      this.pending_[id].transitionType = data.transitionType;\n      this.pending_[id].transitionQualifiers =\n          data.transitionQualifiers;\n    }\n  },\n\n\n  /**\n   * Handler for the 'onHistoryStateUpdated' event. Updates the pending\n   * request with transition information.\n   *\n   * Pushes the request onto the\n   * 'pending_' object, and stores it for later use.\n   *\n   * @param {!Object} data The event data generated for this request.\n   * @private\n   */\n  onHistoryStateUpdatedListener_: function(data) {\n    var id = this.parseId_(data);\n    if (!this.pending_[id]) {\n      this.completed_[data.url] = this.completed_[data.url] || [];\n      this.completed_[data.url].push({\n        duration: 0,\n        openedInNewWindow: false,\n        source: {\n          frameId: null,\n          tabId: null\n        },\n        transitionQualifiers: data.transitionQualifiers,\n        transitionType: data.transitionType,\n        url: data.url\n      });\n      this.saveDataStorage_();\n    } else {\n      this.prepareDataStorage_(id, data.url);\n      this.pending_[id].transitionType = data.transitionType;\n      this.pending_[id].transitionQualifiers =\n          data.transitionQualifiers;\n    }\n  },\n\n\n  /**\n   * Handler for the 'onCompleted` event. Pulls the request's data from the\n   * 'pending_' object, combines it with the completed event's data, and pushes\n   * a new NavigationCollector.Request object onto 'completed_'.\n   *\n   * @param {!Object} data The event data generated for this request.\n   * @private\n   */\n  onCompletedListener_: function(data) {\n    var id = this.parseId_(data);\n    if (!this.pending_[id]) {\n      console.warn(\n          chrome.i18n.getMessage('errorCompletedWithoutPending'),\n          data.url,\n          data);\n    } else {\n      this.completed_[data.url].push({\n        duration: (data.timeStamp - this.pending_[id].start),\n        openedInNewWindow: this.pending_[id].openedInNewWindow,\n        source: this.pending_[id].source,\n        transitionQualifiers: this.pending_[id].transitionQualifiers,\n        transitionType: this.pending_[id].transitionType,\n        url: data.url\n      });\n      delete this.pending_[id];\n      this.saveDataStorage_();\n    }\n  },\n\n\n  /**\n   * Handler for the 'onErrorOccurred` event. Pulls the request's data from the\n   * 'pending_' object, combines it with the completed event's data, and pushes\n   * a new NavigationCollector.Request object onto 'errored_'.\n   *\n   * @param {!Object} data The event data generated for this request.\n   * @private\n   */\n  onErrorOccurredListener_: function(data) {\n    var id = this.parseId_(data);\n    if (!this.pending_[id]) {\n      console.error(\n          chrome.i18n.getMessage('errorErrorOccurredWithoutPending'),\n          data.url,\n          data);\n    } else {\n      this.prepareDataStorage_(id, data.url);\n      this.errored_[data.url].push({\n        duration: (data.timeStamp - this.pending_[id].start),\n        openedInNewWindow: this.pending_[id].openedInNewWindow,\n        source: this.pending_[id].source,\n        transitionQualifiers: this.pending_[id].transitionQualifiers,\n        transitionType: this.pending_[id].transitionType,\n        url: data.url\n      });\n      delete this.pending_[id];\n      this.saveDataStorage_();\n    }\n  },\n\n  /**\n   * Handle messages from the popup.\n   *\n   * @param {!{type:string}} message The external message to answer.\n   * @param {!MessageSender} sender Info about the script context that sent\n   *     the message.\n   * @param {!function} sendResponse Function to call to send a response.\n   * @private\n   */\n  onMessageListener_: function(message, sender, sendResponse) {\n    if (message.type === 'getMostRequestedUrls')\n      sendResponse({result: this.getMostRequestedUrls(message.num)});\n    else\n      sendResponse({});\n  },\n\n///////////////////////////////////////////////////////////////////////////////\n\n  /**\n   * @return {Object<string, NavigationCollector.Request>} The complete list of\n   *     successful navigation requests.\n   */\n  get completed() {\n    return this.completed_;\n  },\n\n\n  /**\n   * @return {Object<string, Navigationcollector.Request>} The complete list of\n   *     unsuccessful navigation requests.\n   */\n  get errored() {\n    return this.errored_;\n  },\n\n\n  /**\n   * Get a list of the X most requested URLs.\n   *\n   * @param {number=} num The number of successful navigation requests to\n   *     return. If 0 is passed in, or the argument left off entirely, all\n   *     successful requests are returned.\n   * @return {Object<string, NavigationCollector.Request>} The list of\n   *     successful navigation requests, sorted in decending order of frequency.\n   */\n  getMostRequestedUrls: function(num) {\n    return this.getMostFrequentUrls_(this.completed, num);\n  },\n\n\n  /**\n   * Get a list of the X most errored URLs.\n   *\n   * @param {number=} num The number of unsuccessful navigation requests to\n   *     return. If 0 is passed in, or the argument left off entirely, all\n   *     successful requests are returned.\n   * @return {Object<string, NavigationCollector.Request>} The list of\n   *     unsuccessful navigation requests, sorted in decending order\n   *     of frequency.\n   */\n  getMostErroredUrls: function(num) {\n    return this.getMostErroredUrls_(this.errored, num);\n  },\n\n\n  /**\n   * Get a list of the most frequent URLs in a list.\n   *\n   * @param {NavigationCollector.Request} list A list of URLs to parse.\n   * @param {number=} num The number of navigation requests to return. If\n   *     0 is passed in, or the argument left off entirely, all requests\n   *     are returned.\n   * @return {Object<string, NavigationCollector.Request>} The list of\n   *     navigation requests, sorted in decending order of frequency.\n   * @private\n   */\n  getMostFrequentUrls_: function(list, num) {\n    var result = [];\n    var avg;\n    // Convert the 'completed_' object to an array.\n    for (var x in list) {\n      avg = 0;\n      if (list.hasOwnProperty(x) && list[x].length) {\n        list[x].forEach(function(o) {\n          avg += o.duration;\n        });\n        avg = avg / list[x].length;\n        result.push({\n          url: x,\n          numRequests: list[x].length,\n          requestList: list[x],\n          average: avg\n        });\n      }\n    }\n    // Sort the array.\n    result.sort(function(a, b) {\n      return b.numRequests - a.numRequests;\n    });\n    // Return the requested number of results.\n    return num ? result.slice(0, num) : result;\n  }\n};\n"
  },
  {
    "path": "_archive/mv2/api/webNavigation/basic/popup.css",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\nbody {\n  margin: 5px 10px 10px;\n}\n\nh1 {\n  color: #53637D;\n  font: 26px/1.2 Helvetica, sans-serif;\n  font-size: 200%;\n  margin: 0;\n  padding-bottom: 4px;\n  text-shadow: white 0 1px 2px;\n}\n\nbody > section {\n  border-radius: 5px;\n  background: -webkit-linear-gradient(rgba(234, 238, 243, 0.2), #EAEEF3),\n  -webkit-linear-gradient(\n  left, #EAEEF3, #EAEEF3 97%, #D3D7DB);\n  font: 14px/1 Arial,Sans Serif;\n  padding: 10px;\n  width:  563px;\n  max-height: 400px;\n  overflow-y: auto;\n  box-shadow: inset 0px 2px 5px rgba(0,0,0,0.5);\n}\n\nbody > section > ol {\n  padding: 0;\n  margin: 0;\n  list-style: none inside;\n}\n\nbody > section > ol > li {\n  position: relative;\n  margin: 0.5em 0 0.5em 40px;\n}\n\ncode {\n  word-wrap: break-word;\n  background: rgba(255,255,0, 0.5);\n}\n\nem {\n  position: absolute;\n  top: 0px;\n  left: -40px;\n  width: 30px;\n  text-align: right;\n  font: 30px/1 Helvetica, sans-serif;\n  font-weight: 700;\n}\n\np {\n  min-height: 30px;\n  line-height: 1.2;\n}\n"
  },
  {
    "path": "_archive/mv2/api/webNavigation/basic/popup.html",
    "content": "<!doctype html>\n<!--\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n<html>\n  <head>\n    <title>WebNavigation Tech Demo Popup</title>\n    <link href=\"popup.css\" rel=\"stylesheet\" type=\"text/css\">\n  </head>\n  <body>\n    <h1>Most Requested URLs</h1>\n    <section></section>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/webNavigation/basic/popup.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @filedescription Initializes the extension's popup page.\n */\n\nchrome.runtime.sendMessage(\n    {'type': 'getMostRequestedUrls'},\n    function generateList(response) {\n      var section = document.querySelector('body>section');\n      var results = response.result;\n      var ol = document.createElement('ol');\n      var li, p, em, code, text;\n      var i;\n      for (i = 0; i < results.length; i++ ) {\n        li = document.createElement('li');\n        p = document.createElement('p');\n        em = document.createElement('em');\n        em.textContent = i + 1;\n        code = document.createElement('code');\n        code.textContent = results[i].url;\n        text = document.createTextNode(\n          chrome.i18n.getMessage('navigationDescription',\n            [results[i].numRequests,\n            results[i].average]));\n        p.appendChild(em);\n        p.appendChild(code);\n        p.appendChild(text);\n        li.appendChild(p);\n        ol.appendChild(li);\n      }\n      section.innerHTML = '';\n      section.appendChild(ol);\n    });\n"
  },
  {
    "path": "_archive/mv2/api/webview/capturevisibleregion/display.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Display Screenshot</title>\n    <style type=\"text/css\">\nbody {\n  background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==');\n  margin: 0;\n}\n    </style>\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/webview/capturevisibleregion/main.js",
    "content": "// Copyright (c) 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('test.html', {\n    innerBounds: {\n      'width': 1280,\n      'height': 800\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/webview/capturevisibleregion/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"Webview transparency\",\n  \"description\": \"Sample of the webview.captureVisibleRegion api\",\n  \"version\": \"1\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\n    \"webview\"\n  ],\n  \"webview\": {\n    \"partitions\": [\n      {\n        \"name\": \"partition\",\n        \"accessible_resources\": [ \"test2.html\" ]\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/webview/capturevisibleregion/test.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <script src=\"test.js\"></script>\n<style type=\"text/css\">\n.ib {\n  position: relative;\n  display: inline-block;\n}\n.controls {\n  margin: 4px;\n  position: absolute;\n  right: 0px;\n  top: 0px;\n}\n</style>\n  </head>\n  <body bgColor='teal'>\n    <br>\n    <button id=\"add_wv\">Add webview</button>\n    <button id=\"delete_wv\">Delete webview</button>\n    <span><input type=\"checkbox\" id=\"transparent\" checked=\"checked\"><label for=\"transparent\">Transparent</label></span>\n    <br>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/webview/capturevisibleregion/test.js",
    "content": "// Copyright (c) 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\ndocument.addEventListener('DOMContentLoaded', function() {\n\n  var deleteNode = function(node) {\n    node.parentNode.removeChild(node);\n  };\n\n  var deleteAWebview = function() {\n    deleteNode(document.querySelector('.ib'));\n  };\n\n  var findContainer = function(node) {\n    var container = node;\n    while (container && !container.classList.contains('ib')) {\n      container = container.parentElement;\n    }\n    return container;\n  };\n\n  var handleDelete = function(event) {\n    var container = findContainer(event.target);\n    if (container) {\n      deleteNode(container);\n    }\n  };\n\n  var viewScreenshot = function(wv) {\n    return function(data) {\n      chrome.app.window.create('display.html', {\n        innerBounds: { width: wv.clientWidth, height: wv.clientHeight }\n      },\n      function(aw) {\n        var d = aw.contentWindow.document;\n        d.addEventListener('DOMContentLoaded', function() {\n          var img = d.createElement('img');\n          img.src = data;\n          d.body.appendChild(img);\n        });\n      });\n    };\n  };\n\n  var handleScreenshot = function(event) {\n    var container = findContainer(event.target);\n    var wv = container.querySelector('webview');\n    wv.captureVisibleRegion({format:'png'}, viewScreenshot(wv));\n  };\n\n  var getControls = (function() {\n    var controls = document.createElement('div');\n    controls.className = 'controls';\n    controls.innerHTML = '<button id=\"screenshot\">Screenshot</button>' +\n        '<button id=\"delete\">Delete webview</button>';\n\n    return function() {\n      var c = controls.cloneNode(true);\n      c.querySelector('#delete').addEventListener('click', handleDelete);\n      c.querySelector('#screenshot').\n          addEventListener('click', handleScreenshot);\n      return c;\n    };\n  })();\n\n  var createWebview = (function(){\n    var id = 0;\n    return function() {\n      var wv = document.createElement('webview');\n      wv.partition = \"partition\";\n      wv.src = 'test2.html';\n      wv.allowtransparency = document.getElementById('transparent').checked;\n      wv.style.width = \"640px\";\n      wv.style.height = \"480px\";\n\n      var container = document.createElement('div');\n      container.id = 'wvid0' + id;\n      id++;\n\n      container.className = 'ib';\n\n      container.appendChild(wv);\n      container.appendChild(getControls());\n      return container;\n    };\n  })();\n\n  document.getElementById('delete_wv').\n      addEventListener('click', deleteAWebview);\n  document.getElementById('add_wv').\n      addEventListener('click', function() {\n        document.body.appendChild(createWebview());\n      });\n});\n"
  },
  {
    "path": "_archive/mv2/api/webview/capturevisibleregion/test2.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head></head>\n  <body>\n    Hello world!\n\n    <button id=\"newwindow\" onclick=\"window.open('http://www.google.com/');\">newwindow</button>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/webview/comm_demo_app/app.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict;'\n\nconst kWhitelistedExtensionId = 'dpicdiinminmigempanoghnpckmkfepi';\nconst kExtensionIds = [kWhitelistedExtensionId];\n\nlet portMap = {};\nlet webview = null;\n\nlet initScripts = [];\n\nfunction createWebView(initScripts) {\n  let container = document.getElementById('webview-container');\n  webview = document.createElement('webview');\n  webview.partition = 'partition';\n  webview.style = 'width: 640px; height: 400px';\n\n  webview.addContentScripts([{\n    // The value of |embedder| in the script below will persist, and can be\n    // used by content script injected into the guest any time to send data\n    // back to us.\n    name: 'embedderVar',\n    matches: ['<all_urls>'],\n    js: {code: 'var embedder = null;\\n'},\n    all_frames: true,\n    run_at: 'document_start'\n  }]);\n  webview.addContentScripts(initScripts);\n\n  webview.addEventListener('contentload', function() {\n    webview.executeScript({\n      code: 'window.addEventListener(\\'message\\', function(e){\\n' +\n          '  if (e.data != \\'connect\\')\\n' +\n          '    return;\\n' +\n          '  console.log(\\'msg = \\' + e.data);\\n' +\n          '  embedder = e.source;\\n' +\n          '  embedder.postMessage(JSON.stringify({\\n' +\n          '    \\'ext_id\\' : \\'0\\',\\n' +\n          '    \\'msg\\' : \\'Hello from guest!\\'}), \\'*\\');\\n' +\n          '});'\n    });\n    // Here we aren't enforcing any particular origin on the guest, but we\n    // could if security needs required it.\n    webview.contentWindow.postMessage('connect', '*');\n  });\n\n  addEventListener('message', function(e) {\n    if (e.source != webview.contentWindow)\n      return;\n\n    let data;\n    try {\n      data = JSON.parse(e.data);\n    } catch (err) {\n      console.warn('invalid JSON format for incoming message: ' + err.message);\n    }\n\n    if (!data) {\n      console.warn('Malformed message: ' + e.data);\n      return;\n    }\n\n    if (data.extensionId) {\n      if (!data.extensionId in portMap) {\n        console.warn('Message for unknown extension: ' + data.extensionId);\n        return;\n      }\n      if (!data.request) {\n        console.warn('malformed messgae (no request):' + e.data);\n        return;\n      }\n      // Relay this to the appropriate extension.\n      // If the app wants to monitor messages from injected code, this is one\n      // place to do it.\n      console.log('Request: ' + data.request + ' => ' + data.extensionId);\n      portMap[data.extensionId].postMessage({request: data.request});\n    } else {\n      if (!data.msg) {\n        console.warn('malformed message (no msg): ' + e.data);\n      }\n      console.log('Message for us: ' + data.msg);\n    }\n  });\n\n  webview.src = 'http://example.com';\n  container.appendChild(webview);\n}\n\nfunction connectToExtension(extensionId) {\n  let port;\n  try {\n    port = chrome.runtime.connect(extensionId);\n  } catch (e) {\n    console.error('Could not connect to extension: ' + e.message);\n    return;\n  }\n  // Save port in map.\n  portMap[extensionId] = port;\n  port.onDisconnect.addListener(() => {\n    delete portMap[extensionId];\n  });\n\n  let initPromise = new Promise((resolve, reject) => {\n    port.onMessage.addListener(function(msg) {\n      // Perhaps check here to make sure |msg.code| exists.\n      console.log('Incoming from extension: ' + msg.name + ' -> ' + msg.code);\n      if (msg.name == 'ext_getInitScripts') {\n        initScripts.push({\n          name: 'initScripts-' + extensionId,\n          matches: ['<all_urls>'],\n          js: {code: msg.code},\n          run_at: 'document_start'\n        });\n        resolve();\n      } else {\n        webview.executeScript({code: msg.code});\n      }\n    });\n    setTimeout(function() {\n      reject('Timeout waiting for initScripts from ' + extensionId);\n    }, 5000);\n  });\n\n  port.postMessage({request: 'getInitScripts'});\n\n  return initPromise;\n}\n\nfunction setUpExtensionHandlers() {\n  let port = portMap[kWhitelistedExtensionId];\n  // Some examples of UI in the app requesting services from the guest.\n  // The replies from the extension are injected into the guest and executed\n  // via the port.onMessage handler declared above.\n  document.getElementById('magnify_button')\n      .addEventListener('click', function() {\n        port.postMessage({request: 'magnify'});\n      });\n  document.getElementById('background_button')\n      .addEventListener('click', function() {\n        port.postMessage({request: 'setBackground'});\n      });\n  document.getElementById('add_div_button')\n      .addEventListener('click', function() {\n        port.postMessage({request: 'addDiv'});\n      });\n  document.getElementById('iframe_dataurl_button')\n      .addEventListener('click', function() {\n        port.postMessage({request: 'iFrameDataURL'});\n      });\n}\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  promises = [];\n  for (let extensionId of kExtensionIds)\n    promises.push(connectToExtension(extensionId));\n\n  setUpExtensionHandlers();\n\n  Promise.all(promises).then(function() {\n    createWebView(initScripts);\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/webview/comm_demo_app/main.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.app.runtime.onLaunched.addListener(function() {\n  chrome.app.window.create('test.html', {\n    innerBounds: {\n      'width': 1000,\n      'height': 800\n    }\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/webview/comm_demo_app/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n  \"name\": \"WebView Extension Communications Demo: App\",\n  \"version\": \"1\",\n  \"app\": {\n    \"background\": {\n      \"scripts\": [\"main.js\"]\n    }\n  },\n  \"permissions\": [\"webview\"],\n  \"webview\": {\n    \"partitions\": [\n      {\n        \"name\": \"partition\",\n        \"accessible_resources\": [\"\"]\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/api/webview/comm_demo_app/test.html",
    "content": "<!DOCTYPE html>\n<head>\n  <script src=\"app.js\"></script>\n</head>\n<html>\n  <body bgColor='teal'>\n    <div id='webview-container'>\n    </div>\n    <input type=button value=\"Magnify\" id=magnify_button>\n    <input type=button value=\"Background\" id=background_button>\n    <input type=button value=\"Add Div\" id=add_div_button>\n    <input type=button value=\"Scripting Data URL in IFrame\"\n           id=iframe_dataurl_button>\n    <p>Try typing 'm' in the guest window above.</p>\n  <body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/api/webview/comm_demo_ext/background.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict;'\n\n// Define globals.\n\n// This DataURI image will allow us to demonstrate injecting non-html content\n// into a guest.\nvar chromiumLogoDataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABHNCSVQICAgIfAhkiAAACmlJREFUaIG9mmtsXMd1x39n5i53yeVDlESRlERaVEXKqmq7iZW6lZyoTtzYQhuraGK7RSCnTZAoMGw0Sd0U/UQILfqhddqkeRQN0CA2EjT1AwjSvFzYUOyEslzZkS1XimW2jiTqRVkiKT72de/M6Ye7S652l8sl7fgAF7t75szM/3/mzMyZuSu8DTI8fLzpDaKhqWl3y5wGv0UgN0XebiJyqwCsmEnv3Rk1/mizFF5MJd0LZ58+9tpLL+0P32rfstKKu4cPBmuijp1Xr6b+IkqYuwqhLhRqtX2lKhEI1uW/m05Of+kHX3j6OTjgV4Jj2QSGh483/Twb7btaCP4xikz7InirlLVstKgMrL/anJj7y86x9COPP769sBw8yyLwh391bM+VTPDvTqVjKXDLIVASQzjREczs+/E/7/pho5gaIrDvH15JX7iQeCIbmjvjjqvhVGkaCKPKZkq/kzbzVI//v488/rV7ZpfCtiSBP/mbE4Nnx8PDXpKrFzr61RIAsBpeSSXP7Tr4pT0n6+GrS2Dv8NGdk5cTP3UmMFVgKnp/uwkAOHFujZ5733/9yx2HFsO4KIG9w6/unJwMRryC1jB7JwgAiFFaE+d3PvPF25+vhbMmgbs/f2zrhRk9oUHCQJXz35EQWqijROLdajn968989fdfryyvQnf38MHWsVl3yEtg1AuoorXXmXdMAjV2xvWN/N6+R9OVZVUExt/sfFJ8sDoeG0VVEaW2e4rSCL236gKVYO1sy/VPUBE11xD4+NenPtmcNh9EHd57UA8SD2NpHtQKn1+VVI58ZFrvvPX+g3eU6+bZDB/UYOwXMzNQSB1/6QSSaMNIgBqLIIiAR5GKaVN7E1PwjriGr2lXM94b2Pysj6ZeeP37XTx7ILqGwP5vzt3nQnlEgIunT3DpQg6TaAMTzJtJyVoWSJR30p5y7L6phZu3trCpJ8GqtEWA2axj/Eqe18fmOP5GhlwBjAhiBESwIhijgMFYwRiDFJcPkfi3CQQRwVqDBHzir+/d9I15Ao89pvapK5kJCaQdQDTklZFnkaa1ELTHcWZK0Sbz+EvgUwnHvb/bzt5dbTTZGqtW2ffIKUdOZHj++CyIjdszgjFgioSMEQJjMVYQK1gTgxfAWAPOTX7mw91rREQDgMNz2feUwAOoJBjYuo1fvjaKEQM2jWrMVqQUmTGLnk5leF8vfV0BChw9IxwaFUbH4cpc3GlnqzLYDbcOKjf2we/ckGbouhT/eWiO2azEo2ENQWCwgSGwBimCjruJnVYiIU10fvuZ7A7gSAAwE+pny8MCoG1tL02pU4ThDEoCE6QAwWtpHii9ncLf7++lM20Ym4R//YnhjUvVc+TStHBpGkZGhS3rlP23eTasstx7WxvfO5InHyYWvCzxxikmBm4k9pUUQ1cMCMJ0pJ8BPirDBzU4N5qdz+bLeYTZKV576RiaSILtwJgmMIIgJBPwxfu76esK+J+zwsNPCYWoxo5dpYGkVR7ao2zfoFzNKD86WvTyvKfjevEcAVNkYErgjBCGBR2/oyMwM2cKm8s7UV14EskO2le3gQshmkU1nC/749va6OsKGJtkWeBRyEfCwz8Szk1BR4twQ79ircEGgg0M1hqChCWwhsBaTBB/2sAQBJaEMTSnmuX6w7l+M+v9jlr9AKgIGwe3gYvAezTMIC6kowX27mpFicOmYfBlko+Erx80KHD9BkNzwhPYeA6YhCkSiudDovjdSqw31mCNoGJuNt7pogQATJCid/N1gAMc3mXZfWOKJmt4+YxUxXxd8BUFo+PCsbOCNbCxi9jrxmCL3i59GmsWlt2ypryTHSYK/Y6lvNW1vj/egX28Kb17awqAQ6MrB19SjZyM21jfIYgxmCD2rpGF5XqxRqNIf9uot79Wslns8VgGtw/GqYVXBnqSAIyOrxx8SU4W22hrAVjeuV6RAWOksLYR41THGppaEuAdq1otEK/zS2JcpKCknii2kQwU9TUI1EnLhXy3cSrRkugBMGzZtpV4LpQaWBiluigbUy9bvEpkAsulRivYZCud69qZmnUo8Q67qDSIck1r/JmP4jmwVBvlKueazhv1croq6GvVKq7/6wcG+OXZLACD3csHX1m0tTvWTGdBpDqPqieG8JzxRg4vBrgWITFJRi/HHd062MC5cYmiXUOx9vKMLGlcqbKBPWSs8vPFu6wtoxNtFELlxj5lyzpdaH2Z4Id64IaNivPCxau2vnEtkfCoUY1ebNB8XmYLlp/8r+YF2H+bJ2nrHzdrlaYS8OndDgGOjxXI+6Bun7XayOfDI6Z/vOPUco6JJUDP/qIpeXEaNqyCh/YoyaCBm4oy8J/f4+nthItXQk5NpupWqg0+p+dv7zxrDhwQ75Vv19vIak2HQiQ8MhIwk4PtG5S//YhnsDgh60XTUA/83R85tq1XpuYcz50sEARN9RnXECPBowdEvAB8/MuXd2hTy5HGqy9IV7vysZ0R3e1x/8fOCiMnhZPjC5vUmtZ4tdk1pNywMb4eOHc54smRSbZs6a/LeDFO2Wz4m5++I/1K6apB7vtK5pJtkoZ25UppCuD92zzvHfI01ZkPAPkQnnk1yw8PT/Ded/XQ1ta6bPC+EL75px9o6Z4/UiKi9msTD0DqOyshUIjgx68aRkYNN230bF3v6W2HdCqGMJsTzk85jp/O8+Jojpm5iKG+9hWBB3AUPiWSVii7lbj7MbXpK9PnxSTWrYREpcwfZ4lzwHx2GheGeHU0kWf3jl6SiVTNuvXAh4Xo0tgHmnsPiHgou9h6/B5x1hXufjvAlzJvV3qcQ9UVr4sc2wbaVgQewPnsXSXw1xAA+LcHup4r5HNPvBXg1Re2ivch3gvqHZ1pZeO61bXrL9F+oRD+x/4PrnmhXFeVfARtV/f5MGw4wSs/Q9cUr/EI+AjnHdcPdFQnbQ2Ad4XwwtmJU/dV6qtaeuTPBnJ5M7vDF/KusqwcbF3Q8/aK1zjPV1X6uxKs6+yotlsCvM/nwqlc7j0H7ql+AVgz/fvO/RvGLHM3e+8bBluTgFecd/EIhCFDm1Y1dP95DXj1hC7zrs/9wZpztcoXzV+/8eDGVySau1ELuaqRWBI44Oe9H4GP2HZdC+lU6hqbRjwfZqd+41N39hxfzKZuAv7NB7tfzQfZgTCTv9gI6HJQWryh9j6iOaH0bei4xnYpCbPhhcl8OFAPPCxBAOJwmggub8rn5p5cDHAlIC3GvfOKho5t/c0kg0RDXldVMpm5x8auntq0WNiUy7JedN/38Nj7okT6yUQytXjKoeC9w0ceFxVY3Zzllu3dVN691pK5fP5Nn5ve+8CHNtR8oVdLlnWGe/ShvufCnz3dk81M3xuFmYlaNqrxiuOdw4V5BvvblgRfyMxezs5MfXj89tae5YCHt/BnD1TlY1848+7QJv/cJ+xHk0HaqCrqPN55fJinf62yfXNnzbDJZGYV9FthPvdPD961/mURWdFlxcoJlMnwsJrRVWc24e3NKsEtuSi7Q1xu867NbetaOlsiCnrBWn/OGfO8cf7lQjT335c/dN3p8pRgpfL/IYD7eLJbZAcAAAAASUVORK5CYII=';\n\nvar iframeDataURL =\n    'data:text/html,' +\n    '<html>' +\n    '  <head>' +\n    '    <script>' +\n    '      document.addEventListener(\"DOMContentLoaded\", function(){' +\n    '        document.getElementById(\"target\").innerText = \"Fred.\";' +\n    '      });' +\n    '    </script>' +\n    '  </head>' +\n    '  <body>' +\n    '    <h1>Data URL IFrame</h1>' +\n    '    <img src=\"' + chromiumLogoDataURI + '\"><br>' +\n    '    <p>A data-url based iframe that has scripts.</p>' +\n    '    <p id=\"target\"></p>' +\n    '  </body>' +\n    '</html>';\n\nlet handlers = {};\n\nhandlers['magnify'] =\n    'els = document.getElementsByTagName(\\'div\\'); ' +\n    'for (i = 0; i < els.length; i++) {' +\n    '  els[i].style.fontSize = \"200%\";' +\n    '}'\n\nhandlers['setBackground'] =\n    'document.body.style.backgroundColor=\\'pink\\';';\n\nhandlers['addDiv'] =\n    'el = document.createElement(\\'div\\'); ' +\n    'el.innerText = \\'Greetings from the extension!\\'; ' +\n    'document.body.appendChild(el);';\n\nhandlers['iFrameDataURL'] =\n    'el = document.createElement(\\'iframe\\');\\n' +\n    'document.body.appendChild(el);\\n' +\n    'el.src = \\'' + iframeDataURL + '\\';';\n\nhandlers['getInitScripts'] =\n    'window.addEventListener(\\'keypress\\', function(e){\\n' +\n    '  console.log(\\'keypress!!\\');\\n' +\n    '  if (!embedder)\\n' +\n    '    return;\\n' +\n    '  if (e.keyCode == 109)\\n' +\n    '    embedder.postMessage(JSON.stringify({\\n' +\n    '      \\'extensionId\\' : \\'' + chrome.runtime.id + '\\',\\n' +\n    '      \\'request\\' : \\'magnify\\'}), \\'*\\');\\n' +\n    '});';\n\nchrome.runtime.onConnectExternal.addListener(function(port) {\n  port.onMessage.addListener((msg) => {\n    if (!handlers.hasOwnProperty(msg.request)) {\n      console.error('Unknown request: ' + msg.request);\n      return;\n    }\n    port.postMessage({code: handlers[msg.request], name: 'ext_' + msg.request});\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/api/webview/comm_demo_ext/manifest.json",
    "content": "{\n    \"manifest_version\": 2,\n\n    \"name\": \"WebView Extension Communications Demo: Extension\",\n    \"description\": \"Provides content scripts to an app hosting a WebView.\",\n    \"version\": \"1.0\",\n\n    \"background\": {\n      \"scripts\": [\"background.js\"]\n    },\n    \"permissions\": [\n    ]\n}\n"
  },
  {
    "path": "_archive/mv2/api/windows/merge_windows/NOTICE",
    "content": "This extension uses icons based on the famfamfam silk series.\nhttp://www.famfamfam.com/lab/icons/silk/"
  },
  {
    "path": "_archive/mv2/api/windows/merge_windows/background.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar targetWindow = null;\nvar tabCount = 0;\n\nfunction start(tab) {\n  chrome.windows.getCurrent(getWindows);\n}\n\nfunction getWindows(win) {\n  targetWindow = win;\n  chrome.tabs.getAllInWindow(targetWindow.id, getTabs);\n}\n\nfunction getTabs(tabs) {\n  tabCount = tabs.length;\n  // We require all the tab information to be populated.\n  chrome.windows.getAll({\"populate\" : true}, moveTabs);\n}\n\nfunction moveTabs(windows) {\n  var numWindows = windows.length;\n  var tabPosition = tabCount;\n\n  for (var i = 0; i < numWindows; i++) {\n    var win = windows[i];\n\n    if (targetWindow.id != win.id) {\n      var numTabs = win.tabs.length;\n\n      for (var j = 0; j < numTabs; j++) {\n        var tab = win.tabs[j];\n        // Move the tab into the window that triggered the browser action.\n        chrome.tabs.move(tab.id,\n            {\"windowId\": targetWindow.id, \"index\": tabPosition});\n        tabPosition++;\n      }\n    }\n  }\n}\n\n// Set up a click handler so that we can merge all the windows.\nchrome.browserAction.onClicked.addListener(start);\n"
  },
  {
    "path": "_archive/mv2/api/windows/merge_windows/manifest.json",
    "content": "{\n  \"name\": \"Merge Windows\",\n  \"version\": \"1.0.2\",\n  \"description\": \"Merges all of the browser's windows into the current window\",\n  \"icons\": {\n    \"48\": \"merge_windows_48.png\",\n    \"128\": \"merge_windows_128.png\"\n  },\n  \"background\": {\n    \"persistent\": false,\n    \"scripts\": [\"background.js\"]\n  },\n  \"browser_action\": {\n    \"default_icon\": \"arrow_in.png\",\n    \"default_title\": \"Merge Windows\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/app_launcher/manifest.json",
    "content": "{\n  \"name\": \"App Launcher\",\n  \"description\": \"Get access to your apps in a browser action\",\n  \"version\": \"0.7.3\",\n  \"permissions\": [\"management\"],\n  \"browser_action\": {\n    \"default_icon\": \"browser_action_icon.png\",\n    \"default_title\": \"App Launcher\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"icons\": {\n    \"48\": \"icon.png\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/app_launcher/popup.css",
    "content": "/* Copyright (c) 2010 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file. */\n\nhtml {\n  overflow-x: hidden;\n}\n\nbody {\n  font-family: Helvetica, Arial, sans-serif;\n}\n\n#search_container {\n  text-align: center;\n}\n\n#search {\n  width: 85%;\n}\n\n.app {\n  width: 100%;\n  margin-top: 7px;\n  margin-bottom: 7px;\n  margin-left: 2px;\n  margin-right: 20px;\n  white-space: nowrap;\n}\n\n.app img {\n  vertical-align: middle;\n  height: 38px;\n  width: 38px;\n}\n\n.app_title {\n  vertical-align: middle;\n  margin-left: 5px;\n}\n\n.app:hover {\n  background-color: rgb(250,250,250);\n  cursor:pointer;\n  outline: 1px dotted rgb(100,100,200);\n}\n\n.app_selected,.app_selected:hover {\n  background-color: rgb(230,230,230);\n}\n\n#appstore_link {\n  display: none;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/app_launcher/popup.html",
    "content": "<!doctype html>\n<!--\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n-->\n<html>\n<head>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"popup.css\">\n<script src=\"popup.js\"></script>\n</head>\n<body>\n\n<div id=\"spacer_dummy\"></div>\n<div id=\"outer\">\n\n<div id=\"appstore_link\">\n  <p>No apps installed.</p><p>\n  <button>Go get some</button></p>\n</div>\n\n<div id=\"search_container\">\n  <input id=\"search\" type=\"text\" placeholder=\"type to search\" spellcheck=\"false\">\n</div>\n\n<div id=\"apps\"></div>\n\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/app_launcher/popup.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction $(id) {\n  return document.getElementById(id);\n}\n\n// Returns the largest size icon, or a default icon, for the given |app|.\nfunction getIconURL(app) {\n  if (!app.icons || app.icons.length == 0) {\n    return chrome.extension.getURL('icon.png');\n  }\n  var largest = {size:0};\n  for (var i = 0; i < app.icons.length; i++) {\n    var icon = app.icons[i];\n    if (icon.size > largest.size) {\n      largest = icon;\n    }\n  }\n  return largest.url;\n}\n\nfunction launchApp(id) {\n  chrome.management.launchApp(id);\n  window.close(); // Only needed on OSX because of crbug.com/63594\n}\n\n// Adds DOM nodes for |app| into |appsDiv|.\nfunction addApp(appsDiv, app, selected) {\n  var div = document.createElement('div');\n  div.className = 'app' + (selected ? ' app_selected' : '');\n\n  div.onclick = function() {\n    launchApp(app.id);\n  };\n\n  var img = document.createElement('img');\n  img.src = getIconURL(app);\n  div.appendChild(img);\n\n  var title = document.createElement('span');\n  title.className = 'app_title';\n  title.innerText = app.name;\n  div.appendChild(title);\n\n  appsDiv.appendChild(div);\n}\n\n// The list of all apps & extensions.\nvar completeList = [];\n\n// A filtered list of apps we actually want to show.\nvar appList = [];\n\n// The index of an app in |appList| that should be highlighted.\nvar selectedIndex = 0;\n\nfunction reloadAppDisplay() {\n  var appsDiv = $('apps');\n\n  // Empty the current content.\n  appsDiv.innerHTML = '';\n\n  for (var i = 0; i < appList.length; i++) {\n    var item = appList[i];\n    addApp(appsDiv, item, i == selectedIndex);\n  }\n}\n\n// Puts only enabled apps from completeList into appList.\nfunction rebuildAppList(filter) {\n  selectedIndex = 0;\n  appList = [];\n  for (var i = 0; i < completeList.length; i++){\n    var item = completeList[i];\n    // Skip extensions and disabled apps.\n    if (!item.isApp || !item.enabled) {\n      continue;\n    }\n    if (filter && item.name.toLowerCase().search(filter) < 0) {\n      continue;\n    }\n    appList.push(item);\n  }\n}\n\n// In order to keep the popup bubble from shrinking as your search narrows the\n// list of apps shown, we set an explicit width on the outermost div.\nvar didSetExplicitWidth = false;\n\nfunction adjustWidthIfNeeded(filter) {\n  if (filter.length > 0 && !didSetExplicitWidth) {\n    // Set an explicit width, correcting for any scroll bar present.\n    var outer = $('outer');\n    var correction = window.innerWidth - document.documentElement.clientWidth;\n    var width = outer.offsetWidth;\n    $('spacer_dummy').style.width = width + correction + 'px';\n    didSetExplicitWidth = true;\n  }\n}\n\n// Shows the list of apps based on the search box contents.\nfunction onSearchInput() {\n  var filter = $('search').value;\n  adjustWidthIfNeeded(filter);\n  rebuildAppList(filter);\n  reloadAppDisplay();\n}\n\nfunction compare(a, b) {\n  return (a > b) ? 1 : (a == b ? 0 : -1);\n}\n\nfunction compareByName(app1, app2) {\n  return compare(app1.name.toLowerCase(), app2.name.toLowerCase());\n}\n\n// Changes the selected app in the list.\nfunction changeSelection(newIndex) {\n  if (newIndex >= 0 && newIndex <= appList.length - 1) {\n    selectedIndex = newIndex;\n    reloadAppDisplay();\n\n    var selected = document.getElementsByClassName('app_selected')[0];\n    var rect = selected.getBoundingClientRect();\n    if (newIndex == 0) {\n      window.scrollTo(0, 0);\n    } else if (newIndex == appList.length - 1) {\n      window.scrollTo(0, document.height);\n    }  else if (rect.top < 0) {\n      window.scrollBy(0, rect.top);\n    } else if (rect.bottom > innerHeight) {\n      window.scrollBy(0, rect.bottom - innerHeight);\n    }\n  }\n}\n\nvar keys = {\n  ENTER : 13,\n  ESCAPE : 27,\n  END : 35,\n  HOME : 36,\n  LEFT : 37,\n  UP : 38,\n  RIGHT : 39,\n  DOWN : 40\n};\n\n// Set up a key event handler that handles moving the selected app up/down,\n// hitting enter to launch the selected app, as well as auto-focusing the\n// search box as soon as you start typing.\nwindow.onkeydown = function(event) {\n  switch (event.keyCode) {\n    case keys.DOWN:\n      changeSelection(selectedIndex + 1);\n      break;\n    case keys.UP:\n      changeSelection(selectedIndex - 1);\n      break;\n    case keys.HOME:\n      changeSelection(0);\n      break;\n    case keys.END:\n      changeSelection(appList.length - 1);\n      break;\n    case keys.ENTER:\n      var app = appList[selectedIndex];\n      if (app) {\n        launchApp(app.id);\n      }\n      break;\n    default:\n      // Focus the search box and return true so you can just start typing even\n      // when the search box isn't focused.\n      $('search').focus();\n      return true;\n  }\n  return false;\n};\n\n\n// Initalize the popup window.\ndocument.addEventListener('DOMContentLoaded', function () {\n  chrome.management.getAll(function(info) {\n    var appCount = 0;\n    for (var i = 0; i < info.length; i++) {\n      if (info[i].isApp) {\n        appCount++;\n      }\n    }\n    if (appCount == 0) {\n      $('search').style.display = 'none';\n      $('appstore_link').style.display = '';\n      return;\n    }\n    completeList = info.sort(compareByName);\n    onSearchInput();\n  });\n\n  $('search').addEventListener('input', onSearchInput);\n\n  // Opens the webstore in a new tab.\n  document.querySelector('#appstore_link button').addEventListener('click',\n      function () {\n        chrome.tabs.create({\n          'url':'https://chrome.google.com/webstore',\n          'selected':true\n        });\n        window.close();\n      });\n});\n\n"
  },
  {
    "path": "_archive/mv2/extensions/buildbot/active_issues.js",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n(function(){\n\nwindow.buildbot = window.buildbot || {};\n\nbuildbot.ActiveIssues = function() {\n  this.issues_ = {};\n  this.eventCallback_ = null;\n};\n\nbuildbot.ActiveIssues.prototype = {\n  forEach: function(callback) {\n    for (var key in this.issues_)\n      callback(this.issues_[key]);\n  },\n\n  getIssue: function(number) {\n    return this.issues_[number];\n  },\n\n  updateIssue: function(issue) {\n    var eventType = this.issues_.hasOwnProperty(issue.issue) ?\n      \"issueUpdated\" : \"issueAdded\";\n    this.issues_[issue.issue] = issue;\n    this.postEvent_({event: eventType, issue: issue.issue});\n  },\n\n  removeIssue: function(issue) {\n    delete this.issues_[issue.issue];\n    this.postEvent_({event: \"issueRemoved\", issue: issue.issue});\n  },\n\n  setEventCallback: function(callback) {\n    this.eventCallback_ = callback;\n  },\n\n  postEvent_: function(obj) {\n    if (this.eventCallback_)\n      this.eventCallback_(obj);\n  }\n};\n\nbuildbot.getActiveIssues = function() {\n  var background = chrome.extension.getBackgroundPage();\n  if (!background.buildbot.hasOwnProperty(\"activeIssues\"))\n    background.buildbot.activeIssues = new buildbot.ActiveIssues;\n\n  return background.buildbot.activeIssues;\n};\n\n})();\n"
  },
  {
    "path": "_archive/mv2/extensions/buildbot/bg.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// TODO(wittman): Convert this extension to event pages once they work with\n// the notifications API.  Currently it's not possible to restore the\n// Notification object when event pages get reloaded.  See\n// http://crbug.com/165276.\n\n(function() {\n\nvar statusURL = \"http://chromium-status.appspot.com/current?format=raw\";\nvar statusHistoryURL =\n  \"http://chromium-status.appspot.com/allstatus?limit=20&format=json\";\nvar pollFrequencyInMs = 30000;\nvar tryPollFrequencyInMs = 30000;\n\nvar prefs = new buildbot.PrefStore;\n\nfunction updateBadgeOnErrorStatus() {\n  chrome.browserAction.setBadgeText({text:\"?\"});\n  chrome.browserAction.setBadgeBackgroundColor({color:[0,0,255,255]});\n}\n\nvar lastNotification = null;\nfunction notifyStatusChange(treeState, status) {\n  if (lastNotification)\n    lastNotification.close();\n\n  lastNotification = new Notification(\"Tree is \" + treeState, {\n    icon: chrome.extension.getURL(\"icon.png\"),\n    body: status\n  });\n}\n\n// The type parameter should be \"open\", \"closed\", or \"throttled\".\nfunction getLastStatusTime(callback, type) {\n  buildbot.requestURL(statusHistoryURL, \"text\", function(text) {\n    var entries = JSON.parse(text);\n\n    for (var i = 0; i < entries.length; i++) {\n      if (entries[i].general_state == type) {\n        callback(new Date(entries[i].date + \" UTC\"));\n        return;\n      }\n    }\n  }, updateBadgeOnErrorStatus);\n}\n\nfunction updateTimeBadge(timeDeltaInMs) {\n  var secondsSinceChangeEvent = Math.round(timeDeltaInMs / 1000);\n  var minutesSinceChangeEvent = Math.round(secondsSinceChangeEvent / 60);\n  var hoursSinceChangeEvent = Math.round(minutesSinceChangeEvent / 60);\n  var daysSinceChangeEvent = Math.round(hoursSinceChangeEvent / 24);\n\n  var text;\n  if (secondsSinceChangeEvent < 60) {\n    text = \"<1m\";\n  } else if (minutesSinceChangeEvent < 57.5) {\n    if (minutesSinceChangeEvent < 30) {\n      text = minutesSinceChangeEvent + \"m\";\n    } else {\n      text = Math.round(minutesSinceChangeEvent / 5) * 5 + \"m\";\n    }\n  } else if (minutesSinceChangeEvent < 5 * 60) {\n      var halfHours = Math.round(minutesSinceChangeEvent / 30);\n      text = Math.floor(halfHours / 2) + (halfHours % 2 ? \".5\" : \"\") + \"h\";\n  } else if (hoursSinceChangeEvent < 23.5) {\n    text = hoursSinceChangeEvent + \"h\";\n  } else {\n    text = daysSinceChangeEvent + \"d\";\n  }\n\n  chrome.browserAction.setBadgeText({text: text});\n}\n\nvar lastState;\nvar lastChangeTime;\nfunction updateStatus(status) {\n  var badgeState = {\n    open: {color: [0,255,0,255], defaultText: \"\\u2022\"},\n    closed: {color: [255,0,0,255], defaultText: \"\\u00D7\"},\n    throttled: {color: [255,255,0,255], defaultText: \"!\"}\n  };\n\n  chrome.browserAction.setTitle({title:status});\n  var treeState = (/open/i).exec(status) ? \"open\" :\n      (/throttled/i).exec(status) ? \"throttled\" : \"closed\";\n\n  if (lastState && lastState != treeState) {\n    prefs.getUseNotifications(function(useNotifications) {\n      if (useNotifications)\n        notifyStatusChange(treeState, status);\n    });\n  }\n\n  chrome.browserAction.setBadgeBackgroundColor(\n      {color: badgeState[treeState].color});\n\n  if (lastChangeTime === undefined) {\n    chrome.browserAction.setBadgeText(\n        {text: badgeState[treeState].defaultText});\n    lastState = treeState;\n    getLastStatusTime(function(time) {\n      lastChangeTime = time;\n      updateTimeBadge(Date.now() - lastChangeTime);\n    }, treeState);\n  } else {\n    if (treeState != lastState) {\n      lastState = treeState;\n      // The change event will occur 1/2 the polling frequency before we\n      // are aware of it, on average.\n      lastChangeTime = Date.now() - pollFrequencyInMs / 2;\n    }\n    updateTimeBadge(Date.now() - lastChangeTime);\n  }\n}\n\nfunction requestStatus() {\n  buildbot.requestURL(statusURL,\n                      \"text\",\n                      updateStatus,\n                      updateBadgeOnErrorStatus);\n  setTimeout(requestStatus, pollFrequencyInMs);\n}\n\n// Record of the last defunct build number we're aware of on each builder.  If\n// the build number is less than or equal to this number, the buildbot\n// information is not available and a request will return a 404.\nvar lastDefunctTryJob = {};\n\nfunction fetchTryJobResults(fullPatchset, builder, buildnumber, completed) {\n  var tryJobURL =\n    \"http://build.chromium.org/p/tryserver.chromium/json/builders/\" +\n        builder + \"/builds/\" + buildnumber;\n\n  if (lastDefunctTryJob.hasOwnProperty(builder) &&\n      buildnumber <= lastDefunctTryJob[builder]) {\n    completed();\n    return;\n  }\n\n  buildbot.requestURL(tryJobURL, \"json\", function(tryJobResult) {\n    if (!fullPatchset.full_try_job_results)\n      fullPatchset.full_try_job_results = {};\n\n    var key = builder + \"-\" + buildnumber;\n    fullPatchset.full_try_job_results[key] = tryJobResult;\n\n    completed();\n  }, function(errorStatus) {\n    if (errorStatus == 404) {\n      lastDefunctTryJob[builder] =\n          Math.max(lastDefunctTryJob[builder] || 0, buildnumber);\n    }\n    completed();\n  });\n}\n\n// Enums corresponding to how much state has been loaded for an issue.\nvar PATCHES_COMPLETE = 0;\nvar TRY_JOBS_COMPLETE = 1;\n\nfunction fetchPatches(issue, updatedCallback) {\n  // Notify updated once after receiving all patchsets, and a second time after\n  // receiving all try job results.\n  var patchsetsRetrieved = 0;\n  var tryJobResultsOutstanding = 0;\n  issue.patchsets.forEach(function(patchset) {\n    var patchURL = \"https://codereview.chromium.org/api/\" + issue.issue +\n        \"/\" + patchset;\n\n    buildbot.requestURL(patchURL, \"json\", function(patch) {\n      if (!issue.full_patchsets)\n        issue.full_patchsets = {};\n\n      issue.full_patchsets[patch.patchset] = patch;\n\n      // TODO(wittman): Revise to reduce load on the try servers. Repeatedly\n      // loading old try results increases the size of the working set of try\n      // jobs on the try servers, causing them to become disk-bound.\n      // patch.try_job_results.forEach(function(results) {\n      //   if (results.buildnumber) {\n      //     tryJobResultsOutstanding++;\n\n      //     fetchTryJobResults(patch, results.builder, results.buildnumber,\n      //                        function() {\n      //       if (--tryJobResultsOutstanding == 0)\n      //         updatedCallback(TRY_JOBS_COMPLETE);\n      //     });\n      //   }\n      // });\n\n      if (++patchsetsRetrieved == issue.patchsets.length) {\n        updatedCallback(PATCHES_COMPLETE);\n        // TODO(wittman): Remove once we revise the try job fetching code.\n        updatedCallback(TRY_JOBS_COMPLETE);\n      }\n    });\n  });\n}\n\nfunction updateTryStatus(status) {\n  var seen = {};\n  var activeIssues = buildbot.getActiveIssues();\n  status.results.forEach(function(result) {\n    var issueURL = \"https://codereview.chromium.org/api/\" + result.issue;\n\n    buildbot.requestURL(issueURL, \"json\", function(issue) {\n      fetchPatches(issue, function(state) {\n        // If the issue already exists, wait until all the issue state has\n        // loaded before updating the issue so we don't lose try job information\n        // from the display.\n        if (activeIssues.getIssue(issue.issue)) {\n          if (state == TRY_JOBS_COMPLETE)\n            activeIssues.updateIssue(issue);\n        } else {\n          activeIssues.updateIssue(issue);\n        }\n      });\n    });\n\n    seen[result.issue] = true;\n  });\n\n  activeIssues.forEach(function(issue) {\n    if (!seen[issue.issue])\n      activeIssues.removeIssue(issue);\n  });\n}\n\nfunction fetchTryStatus(username) {\n  if (!username)\n    return;\n\n  var url = \"https://codereview.chromium.org/search\" +\n      // commit=2 is CLs with commit bit set, commit=3 is CLs with commit\n      // bit cleared, commit=1 is either.\n      \"?closed=3&commit=1&limit=100&order=-modified&format=json&owner=\" +\n      username.trim();\n  buildbot.requestURL(url, \"json\", updateTryStatus);\n}\n\nfunction requestTryStatus() {\n  var searchBaseURL = \"https://codereview.chromium.org/search\";\n\n  prefs.getTryJobUsername(function(username) {\n    if (username == null) {\n      var usernameScrapingURL = \"https://codereview.chromium.org/search\";\n      // Try scraping username from Rietveld if unset.\n      buildbot.requestURL(usernameScrapingURL, \"text\", function(text) {\n        var match = /([^<>\\s]+@\\S+)\\s+\\(.+\\)/.exec(text);\n        if (match) {\n          username = match[1];\n          prefs.setTryJobUsername(username);\n          fetchTryStatus(username);\n        }\n      });\n    } else {\n      fetchTryStatus(username);\n    }\n\n    setTimeout(requestTryStatus, tryPollFrequencyInMs);\n  });\n}\n\nfunction main() {\n  requestStatus();\n  requestTryStatus();\n}\n\nmain();\n\n})();\n"
  },
  {
    "path": "_archive/mv2/extensions/buildbot/manifest.json",
    "content": "{\n  \"name\": \"Chromium Buildbot Monitor\",\n  \"version\": \"0.9.0\",\n  \"description\": \"Displays the status of the Chromium buildbot in the toolbar.  Click to see more detailed status in a popup.\",\n  \"icons\": { \"128\": \"icon.png\" },\n  \"background\": {\n    \"scripts\": [\"utils.js\",\n                \"prefs.js\",\n                \"try_status.js\",\n                \"active_issues.js\",\n                \"bg.js\"]\n  },\n  \"permissions\": [\n    \"notifications\",\n    \"storage\",\n    \"http://build.chromium.org/\",\n    \"http://chromium-status.appspot.com/\",\n    \"https://codereview.chromium.org/\"\n  ],\n  \"browser_action\": {\n    \"default_title\": \"\",\n    \"default_icon\": \"chromium.png\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"options_page\": \"options.html\",\n  \"options_ui\": {\n    \"chrome_style\": true,\n    \"page\": \"options.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/buildbot/options.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <title>Chromium Buildbot Monitor Options</title>\n  <style>\n  body {\n    padding: 10px;\n  }\n  </style>\n</head>\n<body>\n  <label>\n    Use desktop notifications:\n    <input id=\"notifications\" type=\"checkbox\">\n  </label>\n  <br>\n  <label>\n    Username for try job monitoring:\n    <input id=\"try-job-username\" type=\"text\">\n  </label>\n  <script src='prefs.js'></script>\n  <script src='options.js'></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/buildbot/options.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n(function() {\n\nwindow.buildbot = window.buildbot || {};\n\nvar prefs = new buildbot.PrefStore;\n\n// Initialize the checkbox checked state from the saved preference.\nfunction main() {\n  var checkbox = document.getElementById('notifications');\n  prefs.getUseNotifications(function(useNotifications) {\n    checkbox.checked = useNotifications;\n    checkbox.addEventListener(\n      'click',\n      function() {prefs.setUseNotifications(checkbox.checked);});\n  });\n\n  var textbox = document.getElementById('try-job-username');\n  prefs.getTryJobUsername(function(tryJobUsername) {\n    textbox.value = tryJobUsername;\n    textbox.addEventListener(\n        'change',\n        function() {prefs.setTryJobUsername(textbox.value);});\n  });\n}\n\nmain();\n\n})();\n"
  },
  {
    "path": "_archive/mv2/extensions/buildbot/popup.css",
    "content": "/**\n * Copyright 2013 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nbody {\n  font-family: sans-serif;\n  font-size: 0.8em;\n  overflow: hidden;\n}\n\na {\n  text-decoration: underline;\n  color: #444;\n}\n\na:hover {\n  color: black;\n  cursor: pointer;\n}\n\n.status-label {\n  text-align: right;\n  font-size: 12px;\n  font-weight: bold;\n  min-width: 85px;\n  padding: 0px;\n}\n\n.trunk-status-cell {\n  padding: 0px;\n}\n\n.trunk-status-cell > iframe {\n  height: 10px;\n  border: none;\n}\n\n[data-issue] + .trunk-status-row > td,\n.closer-status-row + .other-status-row > td {\n  padding-top: 5px;\n}\n\ndiv.issue-status {\n  display: table;\n  border-spacing: 1px 1px;\n  width: 284px;\n  margin: 1px 0px 1px 9px;\n}\n\n.issue-status-build {\n  display: table-cell;\n  width: 1px;\n  height: 10px;\n}\n\n/* build statuses */\n.success {\n  color: #FFFFFF;\n  background-color: #8fdf5f;\n  border-color: #4F8530;\n}\n\n.failure {\n  color: #FFFFFF;\n  background-color: #e98080;\n  border-color: #A77272;\n}\n\n.warnings {\n  color: #FFFFFF;\n  background-color: #ffc343;\n  border-color: #C29D46;\n}\n\n.never {\n  color: #FFFFFF;\n  background-color: #f0f0e0;\n  border-color: #A77272;\n}\n\n.exception, .retry {\n  color: #FFFFFF;\n  background-color: #e0b0ff;\n  border-color: #ACA0B3;\n}\n\n.running {\n  color: #666666;\n  background-color: #fffc6c;\n  border-color: #C5C56D;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/buildbot/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Chromium Buildbot Monitor Popup</title>\n    <link href=\"popup.css\" rel=\"stylesheet\" type=\"text/css\" />\n  </head>\n  <body>\n    <table id=\"status-table\"></table>\n    <script src='utils.js'></script>\n    <script src='try_status.js'></script>\n    <script src='active_issues.js'></script>\n    <script src='popup.js'></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/buildbot/popup.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n(function(){\n\nvar lkgrURL = 'http://chromium-status.appspot.com/lkgr';\n\n// Interval at which to reload the non-CL bot status.\nvar botStatusRefreshIntervalInMs = 60 * 1000;\n// Interval at which to check for LKGR updates.\nvar lkgrRefreshIntervalInMs = 60 * 1000;\n\nfunction getClassForTryJobResult(result) {\n  // Some win bots seem to report a null result while building.\n  if (result === null)\n    result = buildbot.RUNNING;\n\n  switch (parseInt(result)) {\n  case buildbot.RUNNING:\n    return \"running\";\n\n  case buildbot.SUCCESS:\n    return \"success\";\n\n  case buildbot.WARNINGS:\n    return \"warnings\";\n\n  case buildbot.FAILURE:\n    return \"failure\";\n\n  case buildbot.SKIPPED:\n    return \"skipped\";\n\n  case buildbot.EXCEPTION:\n    return \"exception\";\n\n  case buildbot.RETRY:\n    return \"retry\";\n\n  case buildbot.NOT_STARTED:\n  default:\n    return \"never\";\n  }\n}\n\n// Remove try jobs that have been supplanted by newer runs.\nfunction filterOldTryJobs(tryJobs) {\n  var latest = {};\n  tryJobs.forEach(function(tryJob) {\n    if (!latest[tryJob.builder] ||\n        latest[tryJob.builder].buildnumber < tryJob.buildnumber)\n      latest[tryJob.builder] = tryJob;\n  });\n\n  var result = [];\n  tryJobs.forEach(function(tryJob) {\n    if (tryJob.buildnumber == latest[tryJob.builder].buildnumber)\n      result.push(tryJob);\n  });\n\n  return result;\n}\n\nfunction createTryJobAnchorTitle(tryJob, fullTryJob) {\n  var title = tryJob.builder;\n\n  if (!fullTryJob)\n    return title;\n\n  var stepText = [];\n  if (fullTryJob.currentStep)\n    stepText.push(\"running \" + fullTryJob.currentStep.name);\n\n  if (fullTryJob.results == buildbot.FAILURE && fullTryJob.text) {\n    stepText.push(fullTryJob.text.join(\" \"));\n  } else {\n    // Sometimes a step can fail without setting the try job text.  Look\n    // through all the steps to identify if this is the case.\n    var text = [];\n    fullTryJob.steps.forEach(function(step) {\n      if (step.results[0] == buildbot.FAILURE)\n        text.push(step.results[1][0]);\n    });\n\n    if (text.length > 0) {\n      text.unshift(\"failure\");\n      stepText.push(text.join(\" \"));\n    }\n  }\n\n  if (stepText.length > 0)\n    title += \": \" + stepText.join(\"; \");\n\n  return title;\n}\n\nfunction createPatchsetStatusElement(patchset) {\n  var table = document.createElement(\"div\");\n  table.className = \"issue-status\";\n\n  var tryJobs = filterOldTryJobs(patchset.try_job_results);\n  tryJobs.forEach(function(tryJob) {\n    var key = tryJob.builder + \"-\" + tryJob.buildnumber;\n    var fullTryJob = patchset.full_try_job_results &&\n        patchset.full_try_job_results[key];\n\n    var tryJobAnchor = document.createElement(\"a\");\n    tryJobAnchor.textContent = \"  \";\n    tryJobAnchor.title = createTryJobAnchorTitle(tryJob, fullTryJob);\n    tryJobAnchor.className = \"issue-status-build \" +\n      getClassForTryJobResult(tryJob.result);\n    tryJobAnchor.target = \"_blank\";\n    tryJobAnchor.href = tryJob.url;\n    table.appendChild(tryJobAnchor);\n  });\n\n  return table;\n}\n\nfunction getLastFullPatchsetWithTryJobs(issue) {\n  var index = issue.patchsets.length - 1;\n  var fullPatchsets = issue.full_patchsets;\n  while (index >= 0 &&\n         (!fullPatchsets ||\n          !fullPatchsets[issue.patchsets[index]] ||\n          !fullPatchsets[issue.patchsets[index]].try_job_results ||\n          fullPatchsets[issue.patchsets[index]].try_job_results.length == 0)) {\n    index--;\n  }\n\n  return index >= 0 ? fullPatchsets[issue.patchsets[index]] : null;\n}\n\nfunction createTryStatusRow(issue) {\n  var table = document.getElementById(\"status-table\");\n\n  // Order by decreasing issue number.\n  var position =\n      document.getElementsByClassName(\"trunk-status-row\")[0].rowIndex;\n  while (position > 0 &&\n         parseInt(issue.issue) >\n             parseInt(table.rows[position - 1].getAttribute(\"data-issue\"))) {\n    position--;\n  }\n\n  var row = table.insertRow(position);\n  row.setAttribute(\"data-issue\", issue.issue);\n\n  return row;\n}\n\nfunction updateIssueDisplay(issue) {\n  var codereviewBaseURL = \"https://codereview.chromium.org\";\n\n  var lastFullPatchset = getLastFullPatchsetWithTryJobs(issue);\n\n  var row = document.querySelector(\"*[data-issue='\" + issue.issue + \"']\");\n  if (!lastFullPatchset) {\n    if (row)\n      row.parentNode.removeChild(row);\n    return;\n  }\n\n  if (!row)\n    row = createTryStatusRow(issue);\n\n  var label = row.childNodes[0] || row.insertCell(-1);\n  var status = row.childNodes[1] || row.insertCell(-1);\n\n  label.className = \"status-label\";\n  var clAnchor = label.childNodes[0] ||\n    label.appendChild(document.createElement(\"a\"));\n  clAnchor.textContent = \"CL \" + issue.issue;\n  clAnchor.href = codereviewBaseURL + \"/\" + issue.issue;\n  clAnchor.title = issue.subject;\n  if (lastFullPatchset && lastFullPatchset.message)\n    clAnchor.title += \" | \" + lastFullPatchset.message;\n  clAnchor.target = \"_blank\";\n\n  var statusElement = createPatchsetStatusElement(lastFullPatchset);\n  if (status.childElementCount < 1)\n    status.appendChild(statusElement);\n  else\n    status.replaceChild(statusElement, status.firstChild);\n}\n\nfunction removeIssueDisplay(issueNumber) {\n  var row = document.querySelector(\"*[data-issue='\" + issueNumber + \"']\");\n  row.parentNode.removeChild(row);\n}\n\nfunction addTryStatusRows() {\n  buildbot.getActiveIssues().forEach(updateIssueDisplay);\n}\n\nfunction updateLKGR(lkgr) {\n  var link = document.getElementById('link_lkgr');\n  link.textContent = 'LKGR (' + lkgr + ')';\n}\n\nfunction addBotStatusRow(bot, className) {\n  var table = document.getElementById(\"status-table\");\n\n  var baseURL = \"http://build.chromium.org/p/chromium\" +\n    (bot.id != \"\" ? \".\" + bot.id : \"\");\n  var consoleURL = baseURL + \"/console\";\n  var statusURL = baseURL + \"/horizontal_one_box_per_builder\";\n\n  var row = table.insertRow(-1);\n  row.className = \"trunk-status-row \" + className;\n  var label = row.insertCell(-1);\n  label.className = \"status-label\";\n  var labelAnchor = document.createElement(\"a\");\n  labelAnchor.href = consoleURL;\n  labelAnchor.target = \"_blank\";\n  labelAnchor.id = \"link_\" + bot.id;\n  labelAnchor.textContent = bot.label;\n  label.appendChild(labelAnchor);\n\n  var status = row.insertCell(-1);\n  status.className = \"trunk-status-cell\";\n  var statusIframe = document.createElement(\"iframe\");\n  statusIframe.scrolling = \"no\";\n  statusIframe.src = statusURL;\n  status.appendChild(statusIframe);\n}\n\nfunction addBotStatusRows() {\n  var closerBots = [\n    {id: \"\", label: \"Chromium\"},\n    {id: \"win\", label: \"Win\"},\n    {id: \"mac\", label: \"Mac\"},\n    {id: \"linux\", label: \"Linux\"},\n    {id: \"chromiumos\", label: \"ChromiumOS\"},\n    {id: \"chrome\", label: \"Official\"},\n    {id: \"memory\", label: \"Memory\"}\n  ];\n\n  var otherBots = [\n    {id: \"lkgr\", label: \"LKGR\"},\n    {id: \"perf\", label: \"Perf\"},\n    {id: \"memory.fyi\", label: \"Memory FYI\"},\n    {id: \"gpu\", label: \"GPU\"},\n    {id: \"gpu.fyi\", label: \"GPU FYI\"}\n  ];\n\n  closerBots.forEach(function(bot) {\n    addBotStatusRow(bot, \"closer-status-row\");\n  });\n\n  otherBots.forEach(function(bot) {\n    addBotStatusRow(bot, \"other-status-row\");\n  });\n}\n\nfunction fillStatusTable() {\n  addBotStatusRows();\n  addTryStatusRows();\n}\n\nfunction main() {\n  buildbot.requestURL(lkgrURL, \"text\", updateLKGR);\n  fillStatusTable();\n\n  buildbot.getActiveIssues().setEventCallback(function(request) {\n    // NOTE(wittman): It doesn't appear that we can reliably detect closing of\n    // the popup and remove the event callback, so ensure the popup window is\n    // displayed before processing the event.\n    if (!chrome.extension.getViews({type: \"popup\"}))\n      return;\n\n    switch (request.event) {\n    case \"issueUpdated\":\n    case \"issueAdded\":\n      updateIssueDisplay(buildbot.getActiveIssues().getIssue(request.issue));\n      break;\n\n    case \"issueRemoved\":\n      removeIssueDisplay(request.issue);\n      break;\n    }\n  });\n\n  setInterval(function() {\n    buildbot.requestURL(lkgrURL, \"text\", updateLKGR);\n  }, lkgrRefreshIntervalInMs);\n\n  setInterval(function() {\n    var botStatusElements =\n        document.getElementsByClassName(\"trunk-status-iframe\");\n    for (var i = 0; i < botStatusElements.length; i++)\n      // Force a reload of the iframe in a way that doesn't cause cross-domain\n      // policy violations.\n      botStatusElements.item(i).src = botStatusElements.item(i).src;\n  }, botStatusRefreshIntervalInMs);\n}\n\nmain();\n\n})();\n"
  },
  {
    "path": "_archive/mv2/extensions/buildbot/prefs.js",
    "content": "// Copyright (c) 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n(function() {\n\nwindow.buildbot = window.buildbot || {};\n\nbuildbot.PrefStore = function() {\n  this.defaults_ = {prefs: {use_notifications: false,\n                            try_job_username: null}};\n};\n\nbuildbot.PrefStore.prototype = {\n  get_: function(key, callback) {\n    chrome.storage.sync.get(this.defaults_,\n        function (storage) {\n          callback(storage.prefs[key]);\n        });\n  },\n\n  set_: function(key, value) {\n    chrome.storage.sync.get(this.defaults_,\n        function (storage) {\n          storage.prefs[key] = value;\n          chrome.storage.sync.set(storage);\n        });\n  },\n\n  getUseNotifications: function(callback) {\n    this.get_(\"use_notifications\", callback);\n  },\n\n  setUseNotifications: function(use_notifications) {\n    this.set_(\"use_notifications\", use_notifications);\n  },\n\n  getTryJobUsername: function(callback) {\n    this.get_(\"try_job_username\", callback);\n  },\n\n  setTryJobUsername: function(try_job_username) {\n    this.set_(\"try_job_username\", try_job_username);\n  }\n};\n\n})();\n"
  },
  {
    "path": "_archive/mv2/extensions/buildbot/try_status.js",
    "content": "// Copyright (c) 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n(function() {\n\nwindow.buildbot = window.buildbot || {};\n\nbuildbot.RUNNING = -1;\nbuildbot.SUCCESS = 0;\nbuildbot.WARNINGS = 1;\nbuildbot.FAILURE = 2;\nbuildbot.SKIPPED = 3;\nbuildbot.EXCEPTION = 4;\nbuildbot.RETRY = 5;\nbuildbot.NOT_STARTED = 6;\n\n})();\n"
  },
  {
    "path": "_archive/mv2/extensions/buildbot/utils.js",
    "content": "// Copyright (c) 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n(function() {\n\nwindow.buildbot = window.buildbot || {};\n\nbuildbot.requestURL =\n    function(url, responseType, callback, opt_errorStatusCallback) {\n  var xhr = new XMLHttpRequest();\n  if (responseType == \"json\")\n    // WebKit doesn't handle xhr.responseType = \"json\" as of Chrome 25.\n    xhr.responseType = \"text\";\n  else\n    xhr.responseType = responseType;\n\n  xhr.onreadystatechange = function(state) {\n    if (xhr.readyState == 4) {\n      if (xhr.status == 200) {\n        var response =\n          responseType == \"json\" ? JSON.parse(xhr.response) : xhr.response;\n        callback(response);\n      } else {\n        if (opt_errorStatusCallback)\n          opt_errorStatusCallback(xhr.status);\n      }\n    }\n  };\n\n  xhr.onerror = function(error) {\n    console.log(\"xhr error:\", error);\n  };\n\n  xhr.open(\"GET\", url, true);\n  xhr.send();\n};\n\n})();\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/ar/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (\\u062a\\u062f\\u0639\\u0645\\u0647\\u0627 Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"\\u064a\\u0645\\u0643\\u0646\\u0643 \\u0628\\u0633\\u0631\\u0639\\u0629 \\u0627\\u0644\\u062a\\u0639\\u0631\\u0641 \\u0639\\u0644\\u0649 \\u0627\\u0644\\u0648\\u0642\\u062a \\u0627\\u0644\\u0645\\u062a\\u0628\\u0642\\u064a \\u0644\\u0643 \\u0625\\u0644\\u0649 \\u0623\\u0646 \\u064a\\u062d\\u064a\\u0646 \\u0645\\u0648\\u0639\\u062f \\u0627\\u062c\\u062a\\u0645\\u0627\\u0639\\u0643 \\u0627\\u0644\\u062a\\u0627\\u0644\\u064a \\u0645\\u0646 \\u0623\\u064a \\u062a\\u0642\\u0648\\u064a\\u0645 \\u0645\\u0646 \\u062a\\u0642\\u0627\\u0648\\u064a\\u0645\\u0643. \\u0627\\u0646\\u0642\\u0631 \\u0639\\u0644\\u0649 \\u0627\\u0644\\u0632\\u0631 \\u0644\\u064a\\u062a\\u0645 \\u0646\\u0642\\u0644\\u0643 \\u0625\\u0644\\u0649 \\u0627\\u0644\\u062a\\u0642\\u0648\\u064a\\u0645.\"},\"direction\":{\"message\":\"rtl\"},\"notitle\":{\"message\":\"(\\u0644\\u064a\\u0633 \\u0647\\u0646\\u0627\\u0643 \\u0623\\u064a \\u0639\\u0646\\u0648\\u0627\\u0646)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 \\u062f\\u0642\\u064a\\u0642\\u0629\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 \\u0633\\u0627\\u0639\\u0629\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 \\u064a\\u0648\\u0645\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"\\u062f\\u0639\\u0645 \\u0645\\u062a\\u0639\\u062f\\u062f \\u0644\\u0644\\u062a\\u0642\\u0648\\u064a\\u0645\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"\\u062a\\u0645 \\u062d\\u0641\\u0638 \\u0627\\u0644\\u0625\\u0639\\u062f\\u0627\\u062f\\u0627\\u062a.\"},\"status_saving\":{\"message\":\"\\u062c\\u0627\\u0631\\u0650 \\u0627\\u0644\\u062d\\u0641\\u0638...\"},\"multicalendartooltip\":{\"message\":\"\\u0627\\u0644\\u0631\\u062c\\u0627\\u0621 \\u062a\\u062d\\u062f\\u064a\\u062f \\u0627\\u0644\\u0645\\u0631\\u0628\\u0639 \\u0644\\u062a\\u0645\\u0643\\u064a\\u0646 \\u0627\\u0644\\u062f\\u0639\\u0645 \\u0627\\u0644\\u0645\\u062a\\u0639\\u062f\\u062f \\u0644\\u0644\\u062a\\u0642\\u0648\\u064a\\u0645.\"},\"imagetooltip\":{\"message\":\"\\u062a\\u0642\\u0648\\u064a\\u0645 Google\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/bg/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (by Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"\\u0412\\u0438\\u0436\\u0442\\u0435 \\u0431\\u044a\\u0440\\u0437\\u043e \\u043a\\u043e\\u043b\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435 \\u0432\\u0438 \\u043e\\u0441\\u0442\\u0430\\u0432\\u0430 \\u0434\\u043e \\u0441\\u043b\\u0435\\u0434\\u0432\\u0430\\u0449\\u0430\\u0442\\u0430 \\u0432\\u0438 \\u0441\\u0440\\u0435\\u0449\\u0430 \\u043e\\u0442 \\u0432\\u0441\\u0435\\u043a\\u0438 \\u0441\\u0432\\u043e\\u0439 \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440. \\u041a\\u043b\\u0438\\u043a\\u043d\\u0435\\u0442\\u0435 \\u0432\\u044a\\u0440\\u0445\\u0443 \\u0431\\u0443\\u0442\\u043e\\u043d\\u0430, \\u0437\\u0430 \\u0434\\u0430 \\u0433\\u043e \\u043e\\u0442\\u0432\\u043e\\u0440\\u0438\\u0442\\u0435.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(\\u0411\\u0435\\u0437 \\u0437\\u0430\\u0433\\u043b\\u0430\\u0432\\u0438\\u0435)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 \\u043c\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 \\u0447\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 \\u0434\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"\\u041f\\u043e\\u0434\\u0434\\u0440\\u044a\\u0436\\u043a\\u0430 \\u043d\\u0430 \\u043d\\u044f\\u043a\\u043e\\u043b\\u043a\\u043e \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u0430\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"\\u041d\\u0430\\u0441\\u0442\\u0440\\u043e\\u0439\\u043a\\u0438\\u0442\\u0435 \\u0441\\u0430 \\u0437\\u0430\\u043f\\u0430\\u0437\\u0435\\u043d\\u0438.\"},\"status_saving\":{\"message\":\"\\u0417\\u0430\\u043f\\u0430\\u0437\\u0432\\u0430 \\u0441\\u0435....\"},\"multicalendartooltip\":{\"message\":\"\\u041c\\u043e\\u043b\\u044f, \\u043f\\u043e\\u0441\\u0442\\u0430\\u0432\\u0435\\u0442\\u0435 \\u043e\\u0442\\u043c\\u0435\\u0442\\u043a\\u0430 \\u0432 \\u043a\\u0432\\u0430\\u0434\\u0440\\u0430\\u0442\\u0447\\u0435\\u0442\\u043e, \\u0437\\u0430 \\u0434\\u0430 \\u0430\\u043a\\u0442\\u0438\\u0432\\u0438\\u0440\\u0430\\u0442\\u0435 \\u043f\\u043e\\u0434\\u0434\\u0440\\u044a\\u0436\\u043a\\u0430\\u0442\\u0430 \\u043d\\u0430 \\u043d\\u044f\\u043a\\u043e\\u043b\\u043a\\u043e \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u0430\"},\"imagetooltip\":{\"message\":\"Google \\u041a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/ca/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (de Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Comproveu r\\u00e0pidament el temps que falta per a la propera reuni\\u00f3 a qualsevol dels vostres calendaris. Feu clic al bot\\u00f3 per anar-hi.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Sense t\\u00edtol)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 min\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 dies\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Compatibilitat amb m\\u00faltiples calendaris\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"S'ha desat la configuraci\\u00f3.\"},\"status_saving\":{\"message\":\"S'est\\u00e0 desant...\"},\"multicalendartooltip\":{\"message\":\"Activeu la casella per activar la compatibilitat amb m\\u00faltiples calendaris\"},\"imagetooltip\":{\"message\":\"Google Calendar\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/cs/messages.json",
    "content": "{\"name\":{\"message\":\"Kontrola Kalend\\u00e1\\u0159e Google (od spole\\u010dnosti Google)\"},\"title\":{\"message\":\"Kontrola Kalend\\u00e1\\u0159e Google\"},\"description\":{\"message\":\"Umo\\u017e\\u0148uje rychle zobrazit \\u010das, kter\\u00fd zb\\u00fdv\\u00e1 do dal\\u0161\\u00ed sch\\u016fzky napl\\u00e1novan\\u00e9 v kter\\u00e9mkoli z va\\u0161ich kalend\\u00e1\\u0159\\u016f. Kliknut\\u00edm na tla\\u010d\\u00edtko p\\u0159ejdete do kalend\\u00e1\\u0159e.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Bez n\\u00e1zvu)\"},\"optionstitle\":{\"message\":\"Kontrola Kalend\\u00e1\\u0159e Google\"},\"minutes\":{\"message\":\"$1 min\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Podpora n\\u011bkolika kalend\\u00e1\\u0159\\u016f\"},\"extensionname\":{\"message\":\"Kontrola Kalend\\u00e1\\u0159e Google\"},\"status_saved\":{\"message\":\"Nastaven\\u00ed byla ulo\\u017eena.\"},\"status_saving\":{\"message\":\"Ukl\\u00e1d\\u00e1n\\u00ed....\"},\"multicalendartooltip\":{\"message\":\"Za\\u0161krtnut\\u00edm pol\\u00ed\\u010dka pros\\u00edm povolte podporu v\\u00edce kalend\\u00e1\\u0159\\u016f\"},\"imagetooltip\":{\"message\":\"Kalend\\u00e1\\u0159 Google\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/da/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (fra Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Tjek hurtigt hvor lang tid der er til n\\u00e6ste m\\u00f8de i en af dine kalendre. Klik p\\u00e5 knappen for at \\u00e5bne din kalender.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Ingen titel)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 t\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Support til flere kalendere\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Indstillingerne er gemt.\"},\"status_saving\":{\"message\":\"Gemmer...\"},\"multicalendartooltip\":{\"message\":\"S\\u00e6t kryds i feltet for at aktivere support til flere kalendere\"},\"imagetooltip\":{\"message\":\"Google Kalender\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/de/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Werfen Sie schnell einen Blick auf die verbleibende Zeit bis zum n\\u00e4chsten Termin in einem Ihrer Kalender. Klicken Sie zum \\u00d6ffnen Ihres Kalenders auf die Schaltfl\\u00e4che.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Kein Titel)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 Min.\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 Std.\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 Tage\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Unterst\\u00fctzung mehrerer Kalender\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Einstellungen gespeichert\"},\"status_saving\":{\"message\":\"Speichern....\"},\"multicalendartooltip\":{\"message\":\"Aktivieren Sie das Kontrollk\\u00e4stchen, um die Unterst\\u00fctzung mehrerer Kalender einzuschalten.\"},\"imagetooltip\":{\"message\":\"Google Kalender\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/el/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (\\u03b1\\u03c0\\u03cc \\u03c4\\u03b7\\u03bd Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"\\u0394\\u03b5\\u03af\\u03c4\\u03b5 \\u03b3\\u03c1\\u03ae\\u03b3\\u03bf\\u03c1\\u03b1 \\u03c0\\u03cc\\u03c4\\u03b5 \\u03b5\\u03af\\u03bd\\u03b1\\u03b9 \\u03b7 \\u03b5\\u03c0\\u03cc\\u03bc\\u03b5\\u03bd\\u03b7 \\u03c3\\u03c5\\u03bd\\u03ac\\u03bd\\u03c4\\u03b7\\u03c3\\u03ae \\u03c3\\u03b1\\u03c2 \\u03b1\\u03c0\\u03cc \\u03bf\\u03c0\\u03bf\\u03b9\\u03bf\\u03b4\\u03ae\\u03c0\\u03bf\\u03c4\\u03b5 \\u03b1\\u03c0\\u03cc \\u03c4\\u03b1 \\u03b7\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03ac \\u03c3\\u03b1\\u03c2. \\u039a\\u03ac\\u03bd\\u03c4\\u03b5 \\u03ba\\u03bb\\u03b9\\u03ba \\u03c3\\u03c4\\u03bf \\u03ba\\u03bf\\u03c5\\u03bc\\u03c0\\u03af \\u03b3\\u03b9\\u03b1 \\u03bd\\u03b1 \\u03bc\\u03b5\\u03c4\\u03b1\\u03c6\\u03b5\\u03c1\\u03b8\\u03b5\\u03af\\u03c4\\u03b5 \\u03c3\\u03c4\\u03bf \\u03b7\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03cc \\u03c3\\u03b1\\u03c2.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(\\u03a7\\u03c9\\u03c1\\u03af\\u03c2 \\u03c4\\u03af\\u03c4\\u03bb\\u03bf)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1\\u03bb\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1\\u03c9\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1\\u03b7\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"\\u03a5\\u03c0\\u03bf\\u03c3\\u03c4\\u03ae\\u03c1\\u03b9\\u03be\\u03b7 \\u03c0\\u03bf\\u03bb\\u03bb\\u03ce\\u03bd \\u03b7\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03bf\\u03b3\\u03af\\u03c9\\u03bd\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"\\u039f\\u03b9 \\u03c1\\u03c5\\u03b8\\u03bc\\u03af\\u03c3\\u03b5\\u03b9\\u03c2 \\u03b1\\u03c0\\u03bf\\u03b8\\u03b7\\u03ba\\u03b5\\u03cd\\u03c4\\u03b7\\u03ba\\u03b1\\u03bd.\"},\"status_saving\":{\"message\":\"\\u0391\\u03c0\\u03bf\\u03b8\\u03ae\\u03ba\\u03b5\\u03c5\\u03c3\\u03b7....\"},\"multicalendartooltip\":{\"message\":\"\\u0395\\u03c0\\u03b9\\u03bb\\u03ad\\u03be\\u03c4\\u03b5 \\u03c4\\u03bf \\u03c0\\u03bb\\u03b1\\u03af\\u03c3\\u03b9\\u03bf \\u03b3\\u03b9\\u03b1 \\u03bd\\u03b1 \\u03b5\\u03bd\\u03b5\\u03c1\\u03b3\\u03bf\\u03c0\\u03bf\\u03b9\\u03ae\\u03c3\\u03b5\\u03c4\\u03b5 \\u03c4\\u03b7\\u03bd \\u03c5\\u03c0\\u03bf\\u03c3\\u03c4\\u03ae\\u03c1\\u03b9\\u03be\\u03b7 \\u03c0\\u03bf\\u03bb\\u03bb\\u03ce\\u03bd \\u03b7\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03bf\\u03b3\\u03af\\u03c9\\u03bd\"},\"imagetooltip\":{\"message\":\"\\u0397\\u03bc\\u03b5\\u03c1\\u03bf\\u03bb\\u03cc\\u03b3\\u03b9\\u03bf Google\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/en/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (by Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Quickly see the time until your next meeting from any of your calendars. Click on the button to be taken to your calendar.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(No Title)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Multi Calendar Support\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Settings Saved.\"},\"status_saving\":{\"message\":\"Saving....\"},\"multicalendartooltip\":{\"message\":\"Please check the box to enable multiple calendar support\"},\"imagetooltip\":{\"message\":\"Google Calendar\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/en_GB/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (by Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Quickly see the time until your next meeting from any of your calendars. Click the button to be taken to your calendar.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(No Title)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Multi-Calendar Support\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Settings Saved.\"},\"status_saving\":{\"message\":\"Saving....\"},\"multicalendartooltip\":{\"message\":\"Please tick the box to enable multiple calendar support\"},\"imagetooltip\":{\"message\":\"Google Calendar\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/es/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (de Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Consulta r\\u00e1pidamente cu\\u00e1nto tiempo falta para tu pr\\u00f3xima reuni\\u00f3n en cualquiera de tus calendarios. Haz clic en el bot\\u00f3n para acceder al calendario.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Sin t\\u00edtulo)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1min\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Compatibilidad con varios calendarios\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Se ha guardado la configuraci\\u00f3n.\"},\"status_saving\":{\"message\":\"Guardando....\"},\"multicalendartooltip\":{\"message\":\"Selecciona la casilla para habilitar la compatibilidad con varios calendarios\"},\"imagetooltip\":{\"message\":\"Google Calendar\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/es_419/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (de Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"F\\u00edjate r\\u00e1pidamente cu\\u00e1nto tiempo falta para tu pr\\u00f3xima reuni\\u00f3n en alguno de tus calendarios. Haz clic en el bot\\u00f3n para que te lleve hasta tu calendario.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Sin t\\u00edtulo)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1\\u00a0m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1\\u00a0h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Ayuda de Multi Calendar\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Configuraciones guardadas\"},\"status_saving\":{\"message\":\"Guardando....\"},\"multicalendartooltip\":{\"message\":\"Marca el casillero para habilitar la ayuda del calendario m\\u00faltiple.\"},\"imagetooltip\":{\"message\":\"Google Calendar\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/et/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Vaadake kiiresti oma j\\u00e4rgmise koosolekuni j\\u00e4\\u00e4nud aega \\u00fcksk\\u00f5ik millisest oma kalendrist. Kalendrisse minekuks kl\\u00f5psake nupul.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Pealkiri puudub)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 min\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 p\\u00e4ev(a)\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Multi-Calendari tugi\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Seaded salvestatud.\"},\"status_saving\":{\"message\":\"Salvestamine ...\"},\"multicalendartooltip\":{\"message\":\"Mitme kalendri toe lubamiseks m\\u00e4rkige ruut\"},\"imagetooltip\":{\"message\":\"Google'i kalender\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/fi/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (Googlen tekem\\u00e4)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"N\\u00e4et nopeasti ajan seuraavaan tapaamiseesi mist\\u00e4 tahansa kalenteristasi. Siirryt kalenteriin napsauttamalla painiketta.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Ei nime\\u00e4)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 min\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 t\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 pv\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Useiden kalentereiden tuki\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Asetukset tallennettu.\"},\"status_saving\":{\"message\":\"Tallennetaan...\"},\"multicalendartooltip\":{\"message\":\"Ota useiden kalentereiden tuki k\\u00e4ytt\\u00f6\\u00f6n valitsemalla valintaruutu\"},\"imagetooltip\":{\"message\":\"Google-kalenteri\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/fil/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (mula sa Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Mabilisang tingnan ang oras hanggang sa iyong susunod na pagpupulong mula sa alinman sa iyong mga kalendaryo. Mag-click sa pindutan upang mapunta sa iyong kalendaryo.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Walang Pamagat)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1o\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1a\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Suporta sa Maramihang Kalendaryo\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Na-save ang Mga Setting.\"},\"status_saving\":{\"message\":\"Sine-save....\"},\"multicalendartooltip\":{\"message\":\"Pakilagyan ng check ang kahon upang paganahin ang suporta sa maramihang kalendaryo\"},\"imagetooltip\":{\"message\":\"Google Calendar\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/fr/messages.json",
    "content": "{\"name\":{\"message\":\"Google\\u00a0Calendar Checker (par Google)\"},\"title\":{\"message\":\"Google\\u00a0Calendar Checker\"},\"description\":{\"message\":\"V\\u00e9rifiez rapidement dans vos agendas le temps qu'il vous reste avant votre prochaine r\\u00e9union. Cliquez sur le bouton pour ouvrir l'agenda correspondant.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Sans titre)\"},\"optionstitle\":{\"message\":\"Google\\u00a0Calendar Checker\"},\"minutes\":{\"message\":\"$1\\u00a0mn\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1\\u00a0h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1\\u00a0j\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Prise en charge multi-agendas\"},\"extensionname\":{\"message\":\"Google\\u00a0Calendar Checker\"},\"status_saved\":{\"message\":\"Param\\u00e8tres enregistr\\u00e9s\"},\"status_saving\":{\"message\":\"Enregistrement....\"},\"multicalendartooltip\":{\"message\":\"Cocher la case pour activer la prise en charge multi-agendas\"},\"imagetooltip\":{\"message\":\"Google\\u00a0Agenda\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/he/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (\\u05de\\u05d0\\u05ea Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"\\u05e8\\u05d0\\u05d4 \\u05d1\\u05de\\u05d4\\u05d9\\u05e8\\u05d5\\u05ea \\u05db\\u05de\\u05d4 \\u05d6\\u05de\\u05df \\u05d9\\u05e9 \\u05dc\\u05da \\u05e2\\u05d3 \\u05d4\\u05e4\\u05d2\\u05d9\\u05e9\\u05d4 \\u05d4\\u05d1\\u05d0\\u05d4 \\u05e9\\u05dc\\u05da \\u05de\\u05db\\u05dc \\u05dc\\u05d5\\u05d7 \\u05e9\\u05e0\\u05d4 \\u05e9\\u05dc\\u05da. \\u05dc\\u05d7\\u05e5 \\u05e2\\u05dc \\u05d4\\u05dc\\u05d7\\u05e6\\u05df \\u05db\\u05d3\\u05d9 \\u05dc\\u05e2\\u05d1\\u05d5\\u05e8 \\u05dc\\u05dc\\u05d5\\u05d7 \\u05d4\\u05e9\\u05e0\\u05d4 \\u05e9\\u05dc\\u05da.\"},\"direction\":{\"message\":\"rtl\"},\"notitle\":{\"message\":\"(\\u05dc\\u05dc\\u05d0 \\u05db\\u05d5\\u05ea\\u05e8\\u05ea)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1\\u05d3'\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1\\u05e9'\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1\\u05d9'\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"\\u05ea\\u05de\\u05d9\\u05db\\u05d4 \\u05d1\\u05d9\\u05d5\\u05de\\u05e0\\u05d9\\u05dd \\u05de\\u05e8\\u05d5\\u05d1\\u05d9\\u05dd\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"\\u05d4\\u05d4\\u05d2\\u05d3\\u05e8\\u05d5\\u05ea \\u05e0\\u05e9\\u05de\\u05e8\\u05d5.\"},\"status_saving\":{\"message\":\"\\u05e9\\u05d5\\u05de\\u05e8....\"},\"multicalendartooltip\":{\"message\":\"\\u05e1\\u05de\\u05df \\u05d0\\u05ea \\u05d4\\u05ea\\u05d9\\u05d1\\u05d4 \\u05db\\u05d3\\u05d9 \\u05dc\\u05d4\\u05e4\\u05d5\\u05da \\u05d0\\u05ea \\u05d4\\u05ea\\u05de\\u05d9\\u05db\\u05d4 \\u05d1\\u05d9\\u05d5\\u05de\\u05e0\\u05d9\\u05dd \\u05de\\u05e8\\u05d5\\u05d1\\u05d9\\u05dd \\u05dc\\u05e4\\u05e2\\u05d9\\u05dc\\u05d4\"},\"imagetooltip\":{\"message\":\"\\u05d9\\u05d5\\u05de\\u05df Google\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/hi/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (by Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Quickly see the time until your next meeting from any of your calendars. Click on the button to be taken to your calendar.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(No Title)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Multi Calendar Support\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Settings Saved.\"},\"status_saving\":{\"message\":\"Saving....\"},\"multicalendartooltip\":{\"message\":\"Please check the box to enable multiple calendar support\"},\"imagetooltip\":{\"message\":\"Google Calendar\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/hr/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (od Googlea)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Brzo pogledajte koliko imate vremena do idu\\u0107eg sastanka iz svih svojih kalendara. Kliknite gumb koji \\u0107e vas odvesti u va\\u0161 kalendar.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Nema naslova)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Podr\\u0161ka za vi\\u0161e kalendara\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Postavke su spremljene.\"},\"status_saving\":{\"message\":\"Spremanje....\"},\"multicalendartooltip\":{\"message\":\"Uklju\\u010dite potvrdni okvir za omogu\\u0107avanje podr\\u0161ke za vi\\u0161e kalendara\"},\"imagetooltip\":{\"message\":\"Google Kalendar\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/hu/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (a Google-t\\u00f3l)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Gyorsan megn\\u00e9zheti b\\u00e1rmelyik napt\\u00e1r\\u00e1ban, hogy mennyi ideje van m\\u00e9g a k\\u00f6vetkez\\u0151 tal\\u00e1lkoz\\u00f3ig. Kattintson a gombra a napt\\u00e1r megtekint\\u00e9s\\u00e9hez.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Nincs c\\u00edm)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1p\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1\\u00f3\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1nap\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"T\\u00f6bb napt\\u00e1r t\\u00e1mogat\\u00e1sa\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Be\\u00e1ll\\u00edt\\u00e1sok elmentve.\"},\"status_saving\":{\"message\":\"Ment\\u00e9s...\"},\"multicalendartooltip\":{\"message\":\"K\\u00e9rj\\u00fck, jel\\u00f6lje be a jel\\u00f6l\\u0151n\\u00e9gyzetet t\\u00f6bb napt\\u00e1r t\\u00e1mogat\\u00e1s\\u00e1nak enged\\u00e9lyez\\u00e9s\\u00e9hez\"},\"imagetooltip\":{\"message\":\"Google Napt\\u00e1r\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/id/messages.json",
    "content": "{\"name\":{\"message\":\"Pemeriksa Google Kalender (oleh Google)\"},\"title\":{\"message\":\"Pemeriksa Google Kalender\"},\"description\":{\"message\":\"Lihat waktu dengan cepat sampai pertemuan berikutnya dari kalender apa pun. Klik tombol untuk diarahkan ke kalender Anda.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Tanpa Judul)\"},\"optionstitle\":{\"message\":\"Pemeriksa Google Kalender\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1j\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Dukungan Multi-Kalender\"},\"extensionname\":{\"message\":\"Pemeriksa Google Kalender\"},\"status_saved\":{\"message\":\"Setelan Disimpan.\"},\"status_saving\":{\"message\":\"Menyimpan...\"},\"multicalendartooltip\":{\"message\":\"Harap periksa kotak untuk mengaktifkan dukungan multi-kalender\"},\"imagetooltip\":{\"message\":\"Google Kalender\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/it/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (di Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Usa uno dei tuoi calendari per controllare rapidamente quanto manca alla prossima riunione. Fai clic sul pulsante per accedere al calendario.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Nessun titolo)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 g\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Supporto di pi\\u00f9 calendari\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Impostazioni salvate.\"},\"status_saving\":{\"message\":\"Salvataggio in corso...\"},\"multicalendartooltip\":{\"message\":\"Seleziona la casella per attivare il supporto di pi\\u00f9 calendari\"},\"imagetooltip\":{\"message\":\"Google Calendar\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/ja/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker\\uff08by Google\\uff09\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"\\u3069\\u306e\\u30ab\\u30ec\\u30f3\\u30c0\\u30fc\\u304b\\u3089\\u3067\\u3082\\u6b21\\u306e\\u4f1a\\u8b70\\u307e\\u3067\\u306e\\u6642\\u9593\\u3092\\u3059\\u3070\\u3084\\u304f\\u30c1\\u30a7\\u30c3\\u30af\\u3002\\u30dc\\u30bf\\u30f3\\u3092\\u30af\\u30ea\\u30c3\\u30af\\u3059\\u308b\\u3068\\u30ab\\u30ec\\u30f3\\u30c0\\u30fc\\u306b\\u30a2\\u30af\\u30bb\\u30b9\\u3067\\u304d\\u307e\\u3059\\u3002\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"\\uff08\\u30bf\\u30a4\\u30c8\\u30eb\\u306a\\u3057\\uff09\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"\\u8907\\u6570\\u306e\\u30ab\\u30ec\\u30f3\\u30c0\\u30fc\\u306b\\u5bfe\\u5fdc\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"\\u8a2d\\u5b9a\\u304c\\u4fdd\\u5b58\\u3055\\u308c\\u307e\\u3057\\u305f\\u3002\"},\"status_saving\":{\"message\":\"\\u4fdd\\u5b58\\u3057\\u3066\\u3044\\u307e\\u3059...\"},\"multicalendartooltip\":{\"message\":\"\\u8907\\u6570\\u306e\\u30ab\\u30ec\\u30f3\\u30c0\\u30fc\\u3092\\u4f7f\\u7528\\u3067\\u304d\\u308b\\u3088\\u3046\\u306b\\u3059\\u308b\\u306b\\u306f\\u30c1\\u30a7\\u30c3\\u30af\\u30dc\\u30c3\\u30af\\u30b9\\u3092\\u30aa\\u30f3\\u306b\\u3057\\u3066\\u304f\\u3060\\u3055\\u3044\"},\"imagetooltip\":{\"message\":\"Google \\u30ab\\u30ec\\u30f3\\u30c0\\u30fc\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/ko/messages.json",
    "content": "{\"name\":{\"message\":\"Google \\uce98\\ub9b0\\ub354 \\uccb4\\ud06c \\ub3c4\\uc6b0\\ubbf8(Google \\uc81c\\uacf5)\"},\"title\":{\"message\":\"Google \\uce98\\ub9b0\\ub354 \\uccb4\\ud06c \\ub3c4\\uc6b0\\ubbf8\"},\"description\":{\"message\":\"\\uce98\\ub9b0\\ub354 \\uc5b4\\ub514\\uc5d0\\uc11c\\ub098 \\ub2e4\\uc74c \\ubaa8\\uc784\\uae4c\\uc9c0 \\ub0a8\\uc740 \\uc2dc\\uac04\\uc744 \\uc2e0\\uc18d\\ud558\\uac8c \\uc0b4\\ud3b4\\ubcfc \\uc218 \\uc788\\uc2b5\\ub2c8\\ub2e4. \\uce98\\ub9b0\\ub354\\ub85c \\uc774\\ub3d9\\ud558\\ub824\\uba74 \\ubc84\\ud2bc\\uc744 \\ud074\\ub9ad\\ud558\\uc138\\uc694.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(\\uc81c\\ubaa9 \\uc5c6\\uc74c)\"},\"optionstitle\":{\"message\":\"Google \\uce98\\ub9b0\\ub354 \\uccb4\\ud06c \\ub3c4\\uc6b0\\ubbf8\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"\\uc5ec\\ub7ec \\uce98\\ub9b0\\ub354 \\uc9c0\\uc6d0\"},\"extensionname\":{\"message\":\"Google \\uce98\\ub9b0\\ub354 \\uccb4\\ud06c \\ub3c4\\uc6b0\\ubbf8\"},\"status_saved\":{\"message\":\"\\uc124\\uc815\\uc744 \\uc800\\uc7a5\\ud588\\uc2b5\\ub2c8\\ub2e4.\"},\"status_saving\":{\"message\":\"\\uc800\\uc7a5 \\uc911...\"},\"multicalendartooltip\":{\"message\":\"\\uc5ec\\ub7ec \\uce98\\ub9b0\\ub354 \\uc9c0\\uc6d0\\uc744 \\uc0ac\\uc6a9\\ud558\\ub3c4\\ub85d \\uc124\\uc815\\ud558\\ub824\\uba74 \\ud655\\uc778\\ub780\\uc744 \\uc120\\ud0dd\\ud558\\uc138\\uc694.\"},\"imagetooltip\":{\"message\":\"Google \\uce98\\ub9b0\\ub354\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/lt/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Bet kuriame i\\u0161 savo kalendori\\u0173 greitai \\u017ei\\u016br\\u0117kite, kiek laiko liko iki kito susitikimo. Jei norite patekti \\u012f kalendori\\u0173, spustel\\u0117kite mygtuk\\u0105.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(N\\u0117ra pavadinimo)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 min.\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 val.\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 d.\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Keli\\u0173 kalendori\\u0173 palaikymas\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Nustatymai i\\u0161saugoti.\"},\"status_saving\":{\"message\":\"I\\u0161saugoma...\"},\"multicalendartooltip\":{\"message\":\"Kad \\u012fgalintum\\u0117te keli\\u0173 kalendori\\u0173 palaikym\\u0105, pa\\u017eym\\u0117kite laukel\\u012f\"},\"imagetooltip\":{\"message\":\"\\u201eGoogle\\u201c kalendorius\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/lv/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (nodro\\u0161ina Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Varat \\u0101tri skat\\u012bt, cik daudz laika atlicis l\\u012bdz n\\u0101kamajai sapulcei, izmantojot jebkuru no saviem kalend\\u0101riem. Lai atv\\u0113rtu kalend\\u0101ru, nospiediet pogu.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Bez nosaukuma)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1\\u00a0min\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1\\u00a0h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1\\u00a0d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Vair\\u0101ku kalend\\u0101ru atbalsts\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Iestat\\u012bjumi ir saglab\\u0101ti.\"},\"status_saving\":{\"message\":\"Notiek saglab\\u0101\\u0161ana...\"},\"multicalendartooltip\":{\"message\":\"L\\u016bdzu, atz\\u012bm\\u0113jiet lodzi\\u0146u, lai iesp\\u0113jotu vair\\u0101ku kalend\\u0101ru atbalstu.\"},\"imagetooltip\":{\"message\":\"Google kalend\\u0101rs\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/nb/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (laget av Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Finn ut raskt hvor lenge det er til neste m\\u00f8te fra alle kalendrene dine. Klikk p\\u00e5 knappen for \\u00e5 g\\u00e5 videre til kalenderen.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Ingen tittel)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 min\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 t\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"St\\u00f8tte for flere kalendere\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Innstillinger lagret.\"},\"status_saving\":{\"message\":\"Lagrer \\u2026\"},\"multicalendartooltip\":{\"message\":\"Merk av i ruten for \\u00e5 aktivere st\\u00f8tte for flere kalendere\"},\"imagetooltip\":{\"message\":\"Google Kalender\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/nl/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (van Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Snel in al uw agenda's bekijken hoe lang het nog duurt voordat uw volgende vergadering begint. Klik op de knop om naar uw agenda te gaan.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Naamloos)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 u\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Ondersteuning voor meerdere agenda's\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Instellingen zijn opgeslagen.\"},\"status_saving\":{\"message\":\"Opslaan...\"},\"multicalendartooltip\":{\"message\":\"Vink het selectievakje aan om de ondersteuning voor meerdere agenda's in te schakelen\"},\"imagetooltip\":{\"message\":\"Google Agenda\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/pl/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (by Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Szybko sprawd\\u017a w dowolnym kalendarzu, ile masz czasu do nast\\u0119pnego zebrania. Kliknij przycisk, aby przej\\u015b\\u0107 do kalendarza.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Bez tytu\\u0142u)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1g\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Obs\\u0142uga wielu kalendarzy\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Zapisano ustawienia.\"},\"status_saving\":{\"message\":\"Zapisywanie...\"},\"multicalendartooltip\":{\"message\":\"Zaznacz pole, aby w\\u0142\\u0105czy\\u0107 obs\\u0142ug\\u0119 wielu kalendarzy\"},\"imagetooltip\":{\"message\":\"Kalendarz Google\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/pt_BR/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (do Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Veja rapidamente quanto tempo voc\\u00ea tem at\\u00e9 seu pr\\u00f3ximo compromisso. Clique no bot\\u00e3o para abrir sua agenda.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Sem t\\u00edtulo)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Suporte para v\\u00e1rias agendas\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Configura\\u00e7\\u00f5es salvas.\"},\"status_saving\":{\"message\":\"Salvando...\"},\"multicalendartooltip\":{\"message\":\"Marque a caixa para ativar o suporte para v\\u00e1rias agendas\"},\"imagetooltip\":{\"message\":\"Google Agenda\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/pt_PT/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (do Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Veja rapidamente quanto tempo falta para a sua pr\\u00f3xima reuni\\u00e3o a partir de qualquer um dos seus calend\\u00e1rios. Clique no bot\\u00e3o para aceder ao calend\\u00e1rio.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Sem t\\u00edtulo)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Suporte para v\\u00e1rios calend\\u00e1rios\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Defini\\u00e7\\u00f5es guardadas.\"},\"status_saving\":{\"message\":\"A guardar...\"},\"multicalendartooltip\":{\"message\":\"Marque a caixa para permitir o suporte de v\\u00e1rios calend\\u00e1rios.\"},\"imagetooltip\":{\"message\":\"Calend\\u00e1rio Google\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/ro/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (de la Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Vede\\u0163i rapid timpul p\\u00e2n\\u0103 la urm\\u0103toarea \\u00eent\\u00e2lnire, din oricare dintre calendarele dvs. Face\\u0163i clic pe buton pentru a accesa calendarul.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(F\\u0103r\\u0103 titlu)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 z\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Asisten\\u0163\\u0103 pentru mai multe calendare\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Set\\u0103rile au fost salvate.\"},\"status_saving\":{\"message\":\"Se salveaz\\u0103...\"},\"multicalendartooltip\":{\"message\":\"Bifa\\u0163i caseta pentru a activa asisten\\u0163a pentru mai multe calendare\"},\"imagetooltip\":{\"message\":\"Google Calendar\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/ru/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (\\u0440\\u0430\\u0437\\u0440\\u0430\\u0431\\u043e\\u0442\\u0430\\u043d\\u043e \\u0432 Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"\\u041e\\u0442\\u0441\\u043b\\u0435\\u0436\\u0438\\u0432\\u0430\\u0439\\u0442\\u0435 \\u0432\\u0440\\u0435\\u043c\\u044f \\u0434\\u043e \\u0431\\u043b\\u0438\\u0436\\u0430\\u0439\\u0448\\u0435\\u0433\\u043e \\u043c\\u0435\\u0440\\u043e\\u043f\\u0440\\u0438\\u044f\\u0442\\u0438\\u044f. \\u041f\\u043e\\u0434\\u0434\\u0435\\u0440\\u0436\\u0438\\u0432\\u0430\\u0435\\u0442\\u0441\\u044f \\u043d\\u0435\\u0441\\u043a\\u043e\\u043b\\u044c\\u043a\\u043e \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u0435\\u0439. \\u041d\\u0430\\u0436\\u043c\\u0438\\u0442\\u0435 \\u043a\\u043d\\u043e\\u043f\\u043a\\u0443, \\u0447\\u0442\\u043e\\u0431\\u044b \\u043e\\u0442\\u043a\\u0440\\u044b\\u0442\\u044c \\u043d\\u0443\\u0436\\u043d\\u044b\\u0439 \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u044c.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(\\u0417\\u0430\\u0433\\u043e\\u043b\\u043e\\u0432\\u043e\\u043a \\u043e\\u0442\\u0441\\u0443\\u0442\\u0441\\u0442\\u0432\\u0443\\u0435\\u0442)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1\\u043c.\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1\\u0447.\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1\\u0434.\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"\\u041f\\u043e\\u0434\\u0434\\u0435\\u0440\\u0436\\u043a\\u0430 \\u043d\\u0435\\u0441\\u043a\\u043e\\u043b\\u044c\\u043a\\u0438\\u0445 \\u041a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u0435\\u0439\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"\\u041d\\u0430\\u0441\\u0442\\u0440\\u043e\\u0439\\u043a\\u0438 \\u0441\\u043e\\u0445\\u0440\\u0430\\u043d\\u0435\\u043d\\u044b.\"},\"status_saving\":{\"message\":\"\\u0421\\u043e\\u0445\\u0440\\u0430\\u043d\\u0435\\u043d\\u0438\\u0435....\"},\"multicalendartooltip\":{\"message\":\"\\u041d\\u0435 \\u0437\\u0430\\u0431\\u0443\\u0434\\u044c\\u0442\\u0435 \\u043f\\u043e\\u0441\\u0442\\u0430\\u0432\\u0438\\u0442\\u044c \\u0444\\u043b\\u0430\\u0436\\u043e\\u043a, \\u0447\\u0442\\u043e\\u0431\\u044b \\u0430\\u043a\\u0442\\u0438\\u0432\\u0438\\u0440\\u043e\\u0432\\u0430\\u0442\\u044c \\u043f\\u043e\\u0434\\u0434\\u0435\\u0440\\u0436\\u043a\\u0443 \\u043d\\u0435\\u0441\\u043a\\u043e\\u043b\\u044c\\u043a\\u0438\\u0445 \\u041a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u0435\\u0439\"},\"imagetooltip\":{\"message\":\"\\u041a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u044c Google\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/sk/messages.json",
    "content": "{\"name\":{\"message\":\"Kontrola Kalend\\u00e1ra Google (od spolo\\u010dnosti Google)\"},\"title\":{\"message\":\"Kontrola Kalend\\u00e1ra Google\"},\"description\":{\"message\":\"V \\u013eubovo\\u013enom z va\\u0161ich kalend\\u00e1rov si v r\\u00fdchlosti si zobrazte, ko\\u013eko \\u010dasu m\\u00e1te do \\u010fal\\u0161ej sch\\u00f4dzky. Kliknut\\u00edm na tla\\u010didlo prejdete do svojho kalend\\u00e1ra.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Bez n\\u00e1zvu)\"},\"optionstitle\":{\"message\":\"Kontrola Kalend\\u00e1ra Google\"},\"minutes\":{\"message\":\"$1 min\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Podpora viacer\\u00fdch Kalend\\u00e1rov\"},\"extensionname\":{\"message\":\"Kontrola Kalend\\u00e1ra Google\"},\"status_saved\":{\"message\":\"Nastavenia boli ulo\\u017een\\u00e9.\"},\"status_saving\":{\"message\":\"Prebieha ukladanie....\"},\"multicalendartooltip\":{\"message\":\"Ak chcete povoli\\u0165 podporu viacer\\u00fdch kalend\\u00e1rov, za\\u010diarknite toto pol\\u00ed\\u010dko\"},\"imagetooltip\":{\"message\":\"Kalend\\u00e1r Google\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/sl/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Hitro preverite, koliko je \\u0161e do naslednjega sestanka v katerem koli od va\\u0161ih koledarjev. Kliknite gumb, da odprete koledar.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Brez naslova)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 min\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Podpora za ve\\u010d koledarjev\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Nastavitve shranjene.\"},\"status_saving\":{\"message\":\"Shranjevanje ...\"},\"multicalendartooltip\":{\"message\":\"Potrdite polje, da omogo\\u010dite podporo za ve\\u010d koledarjev.\"},\"imagetooltip\":{\"message\":\"Google Koledar\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/sr/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (\\u043e\\u0434 Google-\\u0430)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"\\u0411\\u0440\\u0437\\u043e \\u043f\\u043e\\u0433\\u043b\\u0435\\u0434\\u0430\\u0458\\u0442\\u0435 \\u043a\\u043e\\u043b\\u0438\\u043a\\u043e \\u0432\\u0440\\u0435\\u043c\\u0435\\u043d\\u0430 \\u0438\\u043c\\u0430\\u0442\\u0435 \\u0434\\u043e \\u0441\\u043b\\u0435\\u0434\\u0435\\u045b\\u0435\\u0433 \\u0441\\u0430\\u0441\\u0442\\u0430\\u043d\\u043a\\u0430 \\u0443 \\u0431\\u0438\\u043b\\u043e \\u043a\\u043e\\u043c \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u0443. \\u041a\\u043b\\u0438\\u043a\\u043d\\u0438\\u0442\\u0435 \\u043d\\u0430 \\u0434\\u0443\\u0433\\u043c\\u0435 \\u0434\\u0430 \\u0431\\u0438\\u0441\\u0442\\u0435 \\u043e\\u0442\\u0432\\u043e\\u0440\\u0438\\u043b\\u0438 \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(\\u0411\\u0435\\u0437 \\u043d\\u0430\\u0441\\u043b\\u043e\\u0432\\u0430)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 \\u043c\\u0438\\u043d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 \\u0441\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 \\u0434\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"\\u041f\\u043e\\u0434\\u0440\\u0448\\u043a\\u0430 \\u0437\\u0430 \\u0432\\u0438\\u0448\\u0435 \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u0430\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"\\u041f\\u043e\\u0434\\u0435\\u0448\\u0430\\u0432\\u0430\\u045a\\u0430 \\u0441\\u0443 \\u0441\\u0430\\u0447\\u0443\\u0432\\u0430\\u043d\\u0430.\"},\"status_saving\":{\"message\":\"\\u0427\\u0443\\u0432\\u0430\\u045a\\u0435....\"},\"multicalendartooltip\":{\"message\":\"\\u041f\\u043e\\u0442\\u0432\\u0440\\u0434\\u0438\\u0442\\u0435 \\u0438\\u0437\\u0431\\u043e\\u0440 \\u0443 \\u043f\\u043e\\u0459\\u0443 \\u0437\\u0430 \\u043f\\u043e\\u0442\\u0432\\u0440\\u0434\\u0443 \\u0434\\u0430 \\u0431\\u0438\\u0441\\u0442\\u0435 \\u043e\\u043c\\u043e\\u0433\\u0443\\u045b\\u0438\\u043b\\u0438 \\u043f\\u043e\\u0434\\u0440\\u0448\\u043a\\u0443 \\u0437\\u0430 \\u0432\\u0438\\u0448\\u0435 \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u0430\"},\"imagetooltip\":{\"message\":\"Google \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/sv/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (fr\\u00e5n Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Se snabbt i dina kalendrar hur l\\u00e4nge det \\u00e4r till n\\u00e4sta m\\u00f6te. Klicka p\\u00e5 knappen s\\u00e5 kommer du till kalendern.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Namnl\\u00f6s)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1min\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1tim\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Support f\\u00f6r flera kalendrar\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Inst\\u00e4llningarna har sparats.\"},\"status_saving\":{\"message\":\"Sparar...\"},\"multicalendartooltip\":{\"message\":\"Aktivera support f\\u00f6r flera kalendrar genom att markera rutan\"},\"imagetooltip\":{\"message\":\"Google Kalender\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/th/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (\\u0e42\\u0e14\\u0e22 Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"\\u0e14\\u0e39\\u0e40\\u0e27\\u0e25\\u0e32\\u0e17\\u0e35\\u0e48\\u0e04\\u0e38\\u0e13\\u0e21\\u0e35\\u0e01\\u0e48\\u0e2d\\u0e19\\u0e16\\u0e36\\u0e07\\u0e01\\u0e32\\u0e23\\u0e1b\\u0e23\\u0e30\\u0e0a\\u0e38\\u0e21\\u0e04\\u0e23\\u0e31\\u0e49\\u0e07\\u0e15\\u0e48\\u0e2d\\u0e44\\u0e1b\\u0e44\\u0e14\\u0e49\\u0e08\\u0e32\\u0e01\\u0e1b\\u0e0f\\u0e34\\u0e17\\u0e34\\u0e19\\u0e43\\u0e14\\u0e46 \\u0e01\\u0e47\\u0e44\\u0e14\\u0e49\\u0e02\\u0e2d\\u0e07\\u0e04\\u0e38\\u0e13 \\u0e43\\u0e2b\\u0e49\\u0e04\\u0e25\\u0e34\\u0e01\\u0e17\\u0e35\\u0e48\\u0e1b\\u0e38\\u0e48\\u0e21\\u0e40\\u0e1e\\u0e37\\u0e48\\u0e2d\\u0e44\\u0e1b\\u0e17\\u0e35\\u0e48\\u0e1b\\u0e0f\\u0e34\\u0e17\\u0e34\\u0e19\\u0e02\\u0e2d\\u0e07\\u0e04\\u0e38\\u0e13\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(\\u0e44\\u0e21\\u0e48\\u0e21\\u0e35\\u0e0a\\u0e37\\u0e48\\u0e2d)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"\\u0e01\\u0e32\\u0e23\\u0e2a\\u0e19\\u0e31\\u0e1a\\u0e2a\\u0e19\\u0e38\\u0e19\\u0e1b\\u0e0f\\u0e34\\u0e17\\u0e34\\u0e19\\u0e2b\\u0e25\\u0e32\\u0e22\\u0e23\\u0e30\\u0e1a\\u0e1a\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"\\u0e1a\\u0e31\\u0e19\\u0e17\\u0e36\\u0e01\\u0e01\\u0e32\\u0e23\\u0e15\\u0e31\\u0e49\\u0e07\\u0e04\\u0e48\\u0e32\\u0e41\\u0e25\\u0e49\\u0e27\"},\"status_saving\":{\"message\":\"\\u0e01\\u0e33\\u0e25\\u0e31\\u0e07\\u0e1a\\u0e31\\u0e19\\u0e17\\u0e36\\u0e01....\"},\"multicalendartooltip\":{\"message\":\"\\u0e42\\u0e1b\\u0e23\\u0e14\\u0e40\\u0e25\\u0e37\\u0e2d\\u0e01\\u0e0a\\u0e48\\u0e2d\\u0e07\\u0e17\\u0e33\\u0e40\\u0e04\\u0e23\\u0e37\\u0e48\\u0e2d\\u0e07\\u0e2b\\u0e21\\u0e32\\u0e22 \\u0e40\\u0e1e\\u0e37\\u0e48\\u0e2d\\u0e40\\u0e1b\\u0e34\\u0e14\\u0e43\\u0e0a\\u0e49\\u0e07\\u0e32\\u0e19\\u0e01\\u0e32\\u0e23\\u0e2a\\u0e19\\u0e31\\u0e1a\\u0e2a\\u0e19\\u0e38\\u0e19\\u0e1b\\u0e0f\\u0e34\\u0e17\\u0e34\\u0e19\\u0e2b\\u0e25\\u0e32\\u0e22\\u0e23\\u0e30\\u0e1a\\u0e1a\"},\"imagetooltip\":{\"message\":\"Google \\u0e1b\\u0e0f\\u0e34\\u0e17\\u0e34\\u0e19\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/tr/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (Google'dan)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Takvimlerinizden herhangi birine bakarak bir sonraki toplant\\u0131n\\u0131za ne kadar zaman kald\\u0131\\u011f\\u0131n\\u0131 hemen g\\u00f6r\\u00fcn. Takviminizi a\\u00e7mak i\\u00e7in d\\u00fc\\u011fmeyi t\\u0131klay\\u0131n.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Ba\\u015fl\\u0131ks\\u0131z)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1s\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1g\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"Birden Fazla Takvim Deste\\u011fi\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"Ayarlar Kaydedildi.\"},\"status_saving\":{\"message\":\"Kaydediliyor...\"},\"multicalendartooltip\":{\"message\":\"Birden fazla takvim deste\\u011fini etkinle\\u015ftirmek i\\u00e7in l\\u00fctfen kutuyu i\\u015faretleyin\"},\"imagetooltip\":{\"message\":\"Google Takvim\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/uk/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (\\u0432\\u0456\\u0434 Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"\\u0428\\u0432\\u0438\\u0434\\u043a\\u043e \\u043f\\u0435\\u0440\\u0435\\u0433\\u043b\\u044f\\u0434\\u0430\\u0439\\u0442\\u0435 \\u0441\\u0432\\u043e\\u0457 \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u0456, \\u0449\\u043e\\u0431 \\u0434\\u0456\\u0437\\u043d\\u0430\\u0442\\u0438\\u0441\\u044f, \\u0441\\u043a\\u0456\\u043b\\u044c\\u043a\\u0438 \\u0447\\u0430\\u0441\\u0443 \\u0437\\u0430\\u043b\\u0438\\u0448\\u0438\\u043b\\u043e\\u0441\\u044f \\u0434\\u043e \\u043d\\u0430\\u0441\\u0442\\u0443\\u043f\\u043d\\u043e\\u0457 \\u0437\\u0443\\u0441\\u0442\\u0440\\u0456\\u0447\\u0456. \\u041d\\u0430\\u0442\\u0438\\u0441\\u043d\\u0456\\u0442\\u044c \\u0446\\u044e \\u043a\\u043d\\u043e\\u043f\\u043a\\u0443, \\u0449\\u043e\\u0431 \\u043f\\u0435\\u0440\\u0435\\u0439\\u0442\\u0438 \\u0434\\u043e \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u044f.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(\\u0411\\u0435\\u0437 \\u043d\\u0430\\u0437\\u0432\\u0438)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1 \\u0445\\u0432.\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1 \\u0433\\u043e\\u0434.\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1 \\u0434\\u043d.\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"\\u041f\\u0456\\u0434\\u0442\\u0440\\u0438\\u043c\\u043a\\u0430 \\u0434\\u0435\\u043a\\u0456\\u043b\\u044c\\u043a\\u043e\\u0445 \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u0456\\u0432\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"\\u041d\\u0430\\u043b\\u0430\\u0448\\u0442\\u0443\\u0432\\u0430\\u043d\\u043d\\u044f \\u0437\\u0431\\u0435\\u0440\\u0435\\u0436\\u0435\\u043d\\u043e.\"},\"status_saving\":{\"message\":\"\\u0417\\u0431\\u0435\\u0440\\u0456\\u0433\\u0430\\u043d\\u043d\\u044f....\"},\"multicalendartooltip\":{\"message\":\"\\u041f\\u043e\\u0441\\u0442\\u0430\\u0432\\u0442\\u0435 \\u043f\\u0440\\u0430\\u043f\\u043e\\u0440\\u0435\\u0446\\u044c, \\u0449\\u043e\\u0431 \\u0443\\u0432\\u0456\\u043c\\u043a\\u043d\\u0443\\u0442\\u0438 \\u043f\\u0456\\u0434\\u0442\\u0440\\u0438\\u043c\\u043a\\u0443 \\u0434\\u0435\\u043a\\u0456\\u043b\\u044c\\u043a\\u043e\\u0445 \\u043a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440\\u0456\\u0432\"},\"imagetooltip\":{\"message\":\"\\u041a\\u0430\\u043b\\u0435\\u043d\\u0434\\u0430\\u0440 Google\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/vi/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (c\\u1ee7a Google)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"Xem nhanh th\\u1eddi gian tr\\u01b0\\u1edbc khi \\u0111\\u1ebfn cu\\u1ed9c h\\u1ecdp ti\\u1ebfp theo t\\u1eeb b\\u1ea5t k\\u1ef3 l\\u1ecbch n\\u00e0o c\\u1ee7a b\\u1ea1n. H\\u00e3y nh\\u1ea5p v\\u00e0o n\\u00fat \\u0111\\u1ec3 \\u0111\\u01b0\\u1ee3c \\u0111\\u01b0a \\u0111\\u1ebfn l\\u1ecbch c\\u1ee7a b\\u1ea1n.\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(Kh\\u00f4ng c\\u00f3 ti\\u00eau \\u0111\\u1ec1)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"H\\u1ed7 tr\\u1ee3 nhi\\u1ec1u l\\u1ecbch\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"\\u0110\\u00e3 l\\u01b0u c\\u00e0i \\u0111\\u1eb7t.\"},\"status_saving\":{\"message\":\"\\u0110ang l\\u01b0u....\"},\"multicalendartooltip\":{\"message\":\"Vui l\\u00f2ng ch\\u1ecdn h\\u1ed9p n\\u00e0y \\u0111\\u1ec3 b\\u1eadt t\\u00ednh n\\u0103ng h\\u1ed7 tr\\u1ee3 nhi\\u1ec1u l\\u1ecbch\"},\"imagetooltip\":{\"message\":\"L\\u1ecbch Google\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/zh_CN/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker\\uff08\\u7531 Google \\u63d0\\u4f9b\\uff09\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"\\u5feb\\u901f\\u67e5\\u770b\\u79bb\\u60a8\\u7684\\u4efb\\u610f\\u65e5\\u5386\\u4e2d\\u4e0b\\u4e00\\u6b21\\u4f1a\\u8bae\\u8fd8\\u6709\\u591a\\u957f\\u65f6\\u95f4\\u3002\\u60a8\\u53ea\\u9700\\u70b9\\u51fb\\u8be5\\u6309\\u94ae\\u5373\\u53ef\\u8fdb\\u5165\\u81ea\\u5df1\\u7684\\u65e5\\u5386\\u3002\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"\\uff08\\u65e0\\u6807\\u9898\\uff09\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"\\u591a\\u65e5\\u5386\\u652f\\u6301\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"\\u8bbe\\u7f6e\\u5df2\\u4fdd\\u5b58\\u3002\"},\"status_saving\":{\"message\":\"\\u6b63\\u5728\\u4fdd\\u5b58...\"},\"multicalendartooltip\":{\"message\":\"\\u8bf7\\u9009\\u4e2d\\u6b64\\u6846\\u4ee5\\u542f\\u7528\\u591a\\u65e5\\u5386\\u652f\\u6301\"},\"imagetooltip\":{\"message\":\"Google \\u65e5\\u5386\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/_locales/zh_TW/messages.json",
    "content": "{\"name\":{\"message\":\"Google Calendar Checker (\\u7531 Google \\u63d0\\u4f9b)\"},\"title\":{\"message\":\"Google Calendar Checker\"},\"description\":{\"message\":\"\\u5f9e\\u4efb\\u4f55\\u65e5\\u66c6\\u7686\\u53ef\\u8fc5\\u901f\\u67e5\\u770b\\u8ddd\\u96e2\\u4e0b\\u6b21\\u6703\\u8b70\\u9084\\u5269\\u4e0b\\u591a\\u5c11\\u6642\\u9593\\u3002\\u6309\\u4e00\\u4e0b\\u6309\\u9215\\u5373\\u53ef\\u524d\\u5f80\\u60a8\\u7684\\u65e5\\u66c6\\u3002\"},\"direction\":{\"message\":\"ltr\"},\"notitle\":{\"message\":\"(\\u7121\\u6a19\\u984c)\"},\"optionstitle\":{\"message\":\"Google Calendar Checker\"},\"minutes\":{\"message\":\"$1m\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"hours\":{\"message\":\"$1h\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"days\":{\"message\":\"$1d\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}},\"multicalendartext\":{\"message\":\"\\u591a\\u91cd\\u65e5\\u66c6\\u652f\\u63f4\"},\"extensionname\":{\"message\":\"Google Calendar Checker\"},\"status_saved\":{\"message\":\"\\u8a2d\\u5b9a\\u5df2\\u5132\\u5b58\\u3002\"},\"status_saving\":{\"message\":\"\\u5132\\u5b58\\u4e2d....\"},\"multicalendartooltip\":{\"message\":\"\\u8acb\\u52fe\\u9078\\u6b64\\u65b9\\u584a\\uff0c\\u4ee5\\u555f\\u7528\\u591a\\u91cd\\u65e5\\u66c6\\u652f\\u63f4\\u529f\\u80fd\"},\"imagetooltip\":{\"message\":\"Google \\u65e5\\u66c6\"}}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/javascript/background.js",
    "content": "/**\n * Copyright (c) 2013 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n */\n\nvar warningId = 'notification.warning';\n\nfunction hideWarning(done) {\n  chrome.notifications.clear(warningId, function() {\n    if (done) done();\n  });\n}\n\nfunction showWarning() {\n  hideWarning(function() {\n    chrome.notifications.create(warningId, {\n      iconUrl: chrome.runtime.getURL('images/icon-48.png'),\n      title: 'Removal required',\n      type: 'basic',\n      message: chrome.i18n.getMessage('name') + ' is obsolete ' +\n               'and must be removed. A replacement Extension ' +\n               'is available.',\n      buttons: [{ title: 'Learn More' }],\n      priority: 2,\n    }, function() {});\n  });\n}\n\nfunction openWarningPage() {\n  chrome.tabs.create({\n    url: 'chrome://extensions?options=' + chrome.runtime.id\n  });\n}\n\nchrome.browserAction.setBadgeBackgroundColor({ color: '#FF0000' });\nchrome.browserAction.setBadgeText({ text: '!' });\nchrome.browserAction.onClicked.addListener(openWarningPage);\nchrome.notifications.onClicked.addListener(openWarningPage);\nchrome.notifications.onButtonClicked.addListener(openWarningPage);\nchrome.runtime.onInstalled.addListener(showWarning);\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/javascript/options.js",
    "content": "/**\n * Copyright (c) 2013 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n */\n\nvar $ = document.getElementById.bind(document);\n\nvar url = 'https://chrome.google.com/webstore/detail/' +\n          'google-calendar-by-google/gmbgaklkmjakoegficnlkhebmhkjfich';\n\n$('name').textContent = chrome.i18n.getMessage('name');\n$('link').href = url;\n$('remove').onclick = function() {\n  chrome.management.uninstallSelf({showConfirmDialog: true});\n  window.close();\n};\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/manifest.json",
    "content": "{\n  \"name\": \"__MSG_name__\",\n  \"description\": \"__MSG_description__\",\n  \"manifest_version\": 2,\n  \"default_locale\":\"en\",\n  \"options_page\": \"views/options.html\",\n  \"options_ui\": {\n    \"page\": \"views/options.html\",\n    \"chrome_style\": true\n  },\n  \"version\": \"2.0.0\",\n  \"background\": {\n    \"scripts\": [\"javascript/background.js\"],\n    \"persistent\": false\n  },\n  \"permissions\": [\n    \"notifications\"\n  ],\n  \"browser_action\": {\n    \"default_icon\": {\n      \"19\": \"images/icon-19.png\",\n      \"38\": \"images/icon-38.png\"\n    },\n    \"default_title\": \"__MSG_title__\"\n  },\n  \"icons\": {\n    \"128\": \"images/icon-128.png\",\n    \"48\": \"images/icon-48.png\",\n    \"16\":\"images/icon-16.png\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/calendar/views/options.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2012 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n<html>\n<body>\n\n<p>\n<strong><span id=\"name\"></span> is now obsolete and must be removed, as it\nrelies on an API which will be turned off imminently</strong>.\n<a href=\"https://developers.google.com/google-apps/calendar/v2/developers_guide_protocol\">Learn more</a>.\n</p>\n\n<p>\nInstead, we recommend the more powerful <a id=\"link\">Google Calendar (by\nGoogle)</a> Extension.\n</p>\n\n<p>\n<button id=\"remove\">Remove from Chrome...</button>\n</p>\n\n<script src=\"../javascript/options.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/catblock/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Simple extension to replace lolcat images from\n// http://icanhascheezburger.com/ with loldog images instead.\n\nchrome.browserAction.onClicked.addListener(() => {\n  let url = \"https://icanhas.cheezburger.com/\";\n  chrome.tabs.create({ url });\n});\n\nchrome.webRequest.onBeforeRequest.addListener(\n  (info) => {\n    console.log(\"Cat intercepted: \" + info.url);\n    // Redirect the lolcal request to a random loldog URL.\n    var i = Math.round(Math.random() * loldogs.length);\n    return { redirectUrl: loldogs[i] };\n  },\n  // filters\n  {\n    urls: [\n      \"https://i.chzbgr.com/*\"\n    ],\n    types: [\"image\"]\n  },\n  // extraInfoSpec\n  [\"blocking\"]\n);\n"
  },
  {
    "path": "_archive/mv2/extensions/catblock/loldogs.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar loldogs = [\n\"https://i.chzbgr.com/full/8965253120/hCF69FD84/low-tide-in-vancouver\",\n\"https://i.chzbgr.com/full/9031345152/hF34E8252/better-be-me\",\n\"https://i.chzbgr.com/full/8818792704/h5764ABB1/incoming-ball\",\n\"https://i.chzbgr.com/full/8818830080/hF302FF3E/that-t-shirt-tho\",\n\"https://i.chzbgr.com/full/8969585408/hB747E95C/tacky-school-photos-are-greatly-improved-with-dogs\",\n\"https://i.chzbgr.com/full/8965260032/h0D5E8267/our-corgi-got-stuck-in-the-turtle-pen-this-is-how-we-found-her\",\n\"https://i.chzbgr.com/full/8820512256/hF6E19147/i-didnt-choose-the-begging-life-the-begging-life-chosezzzzzzzz\",\n\"https://i.chzbgr.com/full/8967919616/hF4A2D89D/borked-dog-got-too-excited-about-the-park\",\n\"https://i.chzbgr.com/full/8818945536/hD9E567C4/before-and-after\",\n\"https://i.chzbgr.com/full/8983674368/h40EFDA74/hot-take\",\n\"https://i.chzbgr.com/full/8999350272/hDBDA7BE2/they-are-not-related\",\n\"https://i.chzbgr.com/full/9120000000/hEE745D7F\",\n\"https://i.chzbgr.com/full/8820509184/hC4ECBE51/happy-derp\",\n\"https://i.chzbgr.com/full/8820513792/hFDE72FC9/my-dog-has-a-pink-mustache\",\n\"https://i.chzbgr.com/full/8818918144/h0092EA55/are-you-talking-to-me\",\n\"https://i.chzbgr.com/full/8817368832/h998FBF4B/these-are-pungsan-hunting-dogs-they-are-a-very-rare-dog-and-are-hardly-known-outside-of-north-korea\",\n\"https://i.chzbgr.com/full/8818794496/hB968D2EA/sleepy-hiking-pup\",\n\"https://i.chzbgr.com/full/8966097664/h18D1DD95/doggy-blep\",\n\"https://i.chzbgr.com/full/8820516608/hB8A69C0B/our-new-rescue-cooper\",\n\"https://i.chzbgr.com/full/8818996736/h08087D33/picture-of-a-dog-who-is-a-total-fluffernugget-if-you-know-what-i-mean\",\n\"https://i.chzbgr.com/full/8818376448/h2A09FEFC/best-guard-dogs-ever\",\n\"https://i.chzbgr.com/full/8976043776/h6F7F08E5/she-only-winks-for-me\",\n\"https://i.chzbgr.com/full/8819229440/h0153AC3E/a-well-fed-dog\",\n\"https://i.chzbgr.com/full/8818679296/hE42AD1F9/dogs-are-smart\",\n\"https://i.chzbgr.com/full/8971307520/hC9EA65DB/the-king-of-camping\",\n\"https://i.chzbgr.com/full/8976243456/hC126328E/when-you-just-want-to-be-free-but-youre-a-tiny-pupper-and-dont-know-very-much\",\n\"https://i.chzbgr.com/full/8818650368/h617E4E8E/clearly-dogs-dont-get-the-mondays\",\n\"https://i.chzbgr.com/full/9036930816/hF05D54D6/wanna-see-my-sleep-pose\",\n\"https://i.chzbgr.com/full/8821740032/h61ABA8B0/no-dogs\",\n\"https://i.chzbgr.com/full/8818775552/hEB0BD4BA/in-which-some-are-chihuahuas-and-some-are-raisin-muffins-and-they-really-look-alike-at-first-glance\",\n\"https://i.chzbgr.com/full/9153181184/h358177F4/dog-boarding-services-melbourne\",\n\"https://i.chzbgr.com/full/8819198976/h8294AEF8/whats-up-dawg\",\n\"https://i.chzbgr.com/full/8822310144/h8E9AD7E2/dapper-dog-does-not-appreciate-being-called-cute\",\n\"https://i.chzbgr.com/full/8979289856/h04E0B419/what-a-wrinkly-butt\",\n\"https://i.chzbgr.com/full/8822679040/h7B87C201/walkies\",\n\"https://i.chzbgr.com/full/8966299904/h12DB6920/the-best-kind-of-chocolate-kiss\",\n\"https://i.chzbgr.com/full/8819254016/h829676F4/my-dogs-eyes-turn-blue-when-the-flash-is-on\",\n\"https://i.chzbgr.com/full/8968019200/h2BF6491D/shake-shack-makes-everyone-this-happy\",\n\"https://i.chzbgr.com/full/8818709504/hB4215573/are-you-sure-we-dont-have-to-visit-the-vet-again\",\n\"https://i.chzbgr.com/full/9247000064/hDBA627A9/ugly-sweater-ollie\",\n\"https://i.chzbgr.com/full/8820511744/h31FB445B/my-dog-was-like-what-do-you-mean-no-food\",\n\"https://i.chzbgr.com/full/9176060928/hB4E16208/corgi-power\",\n\"https://i.chzbgr.com/full/8820578304/h53D9FE07/my-friends-dogs-think-they-are-going-to-the-vet-when-in-reality-they-are-headed-to-the-park\",\n\"https://i.chzbgr.com/full/9259141120/hC3A2152A/look-at-this-big-tingy\",\n\"https://i.chzbgr.com/full/8965256192/h94E0B321/german-shepard-mix\",\n\"https://i.chzbgr.com/full/9107126016/hE7E0C532/shh-i-iz-sleepin\",\n];\n"
  },
  {
    "path": "_archive/mv2/extensions/catblock/manifest.json",
    "content": "{\n  \"name\": \"CatBlock\",\n  \"description\": \"I can't has cheezburger!\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 2,\n  \"permissions\": [\n    \"webRequest\",\n    \"webRequestBlocking\",\n    \"https://i.chzbgr.com/*\",\n    \"https://*.cheezburger.com/*\"\n  ],\n  \"background\": {\n    \"scripts\": [\n      \"loldogs.js\",\n      \"background.js\"\n    ]\n  },\n  \"browser_action\": {\n    \"default_title\": \"View the demo - enjoy those good dogs!\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/catifier/event_page.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Sample extension to replace all JPEG images (but no PNG/GIF/... images) with\n// lolcat images from http://icanhascheezburger.com/ - except for images on\n// Google.\n\nvar RequestMatcher = chrome.declarativeWebRequest.RequestMatcher;\nvar IgnoreRules = chrome.declarativeWebRequest.IgnoreRules;\nvar RedirectRequest = chrome.declarativeWebRequest.RedirectRequest;\n\nvar catImageUrl =\n    'https://i.chzbgr.com/completestore/12/8/23/S__rxG9hIUK4sNuMdTIY9w2.jpg';\n\n// Registers redirect rules assuming that currently no rules are registered by\n// this extension, yet.\nfunction registerRules() {\n  var redirectRule = {\n    priority: 100,\n    conditions: [\n      // If any of these conditions is fulfilled, the actions are executed.\n      new RequestMatcher({\n        // Both, the url and the resourceType must match.\n        url: {pathSuffix: '.jpg'},\n        resourceType: ['image']\n      }),\n      new RequestMatcher({\n        url: {pathSuffix: '.jpeg'},\n        resourceType: ['image']\n      }),\n    ],\n    actions: [\n      new RedirectRequest({redirectUrl: catImageUrl})\n    ]\n  };\n\n  var exceptionRule = {\n    priority: 1000,\n    conditions: [\n      // We use hostContains to compensate for various top-level domains.\n      new RequestMatcher({url: {hostContains: '.google.'}})\n    ],\n    actions: [\n      new IgnoreRules({lowerPriorityThan: 1000})\n    ]\n  };\n\n  var callback = function() {\n    if (chrome.runtime.lastError) {\n      console.error('Error adding rules: ' + chrome.runtime.lastError);\n    } else {\n      console.info('Rules successfully installed');\n      chrome.declarativeWebRequest.onRequest.getRules(null,\n          function(rules) {\n            console.info('Now the following rules are registered: ' +\n                         JSON.stringify(rules, null, 2));\n          });\n    }\n  };\n\n  chrome.declarativeWebRequest.onRequest.addRules(\n      [redirectRule, exceptionRule], callback);\n}\n\nfunction setup() {\n  // This function is also called when the extension has been updated.  Because\n  // registered rules are persisted beyond browser restarts, we remove\n  // previously registered rules before registering new ones.\n  chrome.declarativeWebRequest.onRequest.removeRules(\n    null,\n    function() {\n      if (chrome.runtime.lastError) {\n        console.error('Error clearing rules: ' + chrome.runtime.lastError);\n      } else {\n        registerRules();\n      }\n    });\n}\n\n// This is triggered when the extension is installed or updated.\nchrome.runtime.onInstalled.addListener(setup);\n"
  },
  {
    "path": "_archive/mv2/extensions/catifier/manifest.json",
    "content": "{\n  \"name\": \"Catifier\",\n  \"version\": \"1.0\",\n  \"description\": \"Moar cats!\",\n  \"permissions\": [\"declarativeWebRequest\", \"<all_urls>\"],\n  \"background\": {\n    \"scripts\": [\"event_page.js\"],\n    \"persistent\": false\n  },\n\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/chrome_search/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar currentRequest = null;\n\nchrome.omnibox.onInputChanged.addListener(\n  function(text, suggest) {\n    if (currentRequest != null) {\n      currentRequest.onreadystatechange = null;\n      currentRequest.abort();\n      currentRequest = null;\n    }\n\n    updateDefaultSuggestion(text);\n    if (text == '' || text == 'halp')\n      return;\n\n    currentRequest = search(text, function(xml) {\n      var results = [];\n      var entries = xml.getElementsByTagName(\"entry\");\n\n      for (var i = 0, entry; i < 5 && (entry = entries[i]); i++) {\n        var path = entry.getElementsByTagName(\"file\")[0].getAttribute(\"name\");\n        var line =\n            entry.getElementsByTagName(\"match\")[0].getAttribute(\"lineNumber\");\n        var file = path.split(\"/\").pop();\n\n        var description = '<url>' + file + '</url>';\n        if (/^file:/.test(text)) {\n          description += ' <dim>' + path + '</dim>';\n        } else {\n          var content = entry.getElementsByTagName(\"content\")[0].textContent;\n\n          // There can be multiple lines. Kill all the ones except the one that\n          // contains the first match. We can ocassionally fail to find a single\n          // line that matches, so we still handle multiple lines below.\n          var matches = content.split(/\\n/);\n          for (var j = 0, match; match = matches[j]; j++) {\n            if (match.indexOf('<b>') > -1) {\n              content = match;\n              break;\n            }\n          }\n\n          // Replace any extraneous whitespace to make it look nicer.\n          content = content.replace(/[\\n\\t]/g, ' ');\n          content = content.replace(/ {2,}/g, ' ');\n\n          // Codesearch wraps the result in <pre> tags. Remove those if they're\n          // still there.\n          content = content.replace(/<\\/?pre>/g, '');\n\n          // Codesearch highlights the matches with 'b' tags. Replaces those\n          // with 'match'.\n          content = content.replace(/<(\\/)?b>/g, '<$1match>');\n\n          description += ' ' + content;\n        }\n\n        results.push({\n          content: path + '@' + line,\n          description: description\n        });\n      }\n\n      suggest(results);\n    });\n  }\n);\n\nfunction resetDefaultSuggestion() {\n  chrome.omnibox.setDefaultSuggestion({\n    description: '<url><match>src:</match></url> Search Chromium source'\n  });\n}\n\nresetDefaultSuggestion();\n\nfunction updateDefaultSuggestion(text) {\n  var isRegex = /^re:/.test(text);\n  var isFile = /^file:/.test(text);\n  var isHalp = (text == 'halp');\n  var isPlaintext = text.length && !isRegex && !isFile && !isHalp;\n\n  var description = '<match><url>src</url></match><dim> [</dim>';\n  description +=\n      isPlaintext ? ('<match>' + text + '</match>') : 'plaintext-search';\n  description += '<dim> | </dim>';\n  description += isRegex ? ('<match>' + text + '</match>') : 're:regex-search';\n  description += '<dim> | </dim>';\n  description += isFile ? ('<match>' + text + '</match>') : 'file:filename';\n  description += '<dim> | </dim>';\n  description += isHalp ? '<match>halp</match>' : 'halp';\n  description += '<dim> ]</dim>';\n\n  chrome.omnibox.setDefaultSuggestion({\n    description: description\n  });\n}\n\nchrome.omnibox.onInputStarted.addListener(function() {\n  updateDefaultSuggestion('');\n});\n\nchrome.omnibox.onInputCancelled.addListener(function() {\n  resetDefaultSuggestion();\n});\n\nfunction search(query, callback) {\n  if (query == 'halp')\n    return;\n\n  if (/^re:/.test(query))\n    query = query.substring('re:'.length);\n  else if (/^file:/.test(query))\n    query = 'file:\"' + query.substring('file:'.length) + '\"';\n  else\n    query = '\"' + query + '\"';\n\n  var url = \"https://code.google.com/p/chromium/codesearch#search/&type=cs&q=\" + query +\n      \"&exact_package=chromium&type=cs\";\n  var req = new XMLHttpRequest();\n  req.open(\"GET\", url, true);\n  req.setRequestHeader(\"GData-Version\", \"2\");\n  req.onreadystatechange = function() {\n    if (req.readyState == 4) {\n      callback(req.responseXML);\n    }\n  }\n  req.send(null);\n  return req;\n}\n\nfunction getUrl(path, line) {\n  var url = \"https://code.google.com/p/chromium/codesearch#\" + path\n      \"&sq=package:chromium\";\n  if (line)\n    url += \"&l=\" + line;\n  return url;\n}\n\nfunction getEntryUrl(entry) {\n  return getUrl(\n      entry.getElementsByTagName(\"file\")[0].getAttribute(\"name\"),\n      entry.getElementsByTagName(\"match\")[0].getAttribute(\"lineNumber\"));\n  return url;\n}\n\nfunction navigate(url) {\n  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {\n    chrome.tabs.update(tabs[0].id, {url: url});\n  });\n}\n\nchrome.omnibox.onInputEntered.addListener(function(text) {\n  // TODO(aa): We need a way to pass arbitrary data through. Maybe that is just\n  // URL?\n  if (/@\\d+\\b/.test(text)) {\n    var chunks = text.split('@');\n    var path = chunks[0];\n    var line = chunks[1];\n    navigate(getUrl(path, line));\n  } else if (text == 'halp') {\n    // TODO(aa)\n  } else {\n    navigate(\"https://code.google.com/p/chromium/codesearch#search/&type=cs\" +\n             \"&q=\" + text +\n             \"&exact_package=chromium&type=cs\");\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/chrome_search/manifest.json",
    "content": "{\n  \"background\": {\n    \"scripts\": [\"background.js\"]\n  },\n  \"description\": \"Add support to the omnibox to search the Chromium source code.\",\n  \"name\": \"Chromium Search\",\n  \"omnibox\": { \"keyword\" : \"src\" },\n  \"permissions\": [ \"http://www.google.com/\" ],\n  \"version\": \"6.1\",\n  \"minimum_chrome_version\": \"9\",\n\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/constant_context/background.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Create a rule that will show the page action when the conditions are met.\nconst kMatchRule = {\n  // Declare the rule conditions.\n  conditions: [new chrome.declarativeContent.PageStateMatcher({\n    pageUrl: {hostEquals: 'developer.chrome.com'},\n  })],\n  // Shows the page action when the condition is met.\n  actions: [new chrome.declarativeContent.ShowPageAction()]\n}\n\n// Register the runtime.onInstalled event listener.\nchrome.runtime.onInstalled.addListener(function() {\n  // Overrride the rules to replace them with kMatchRule.\n  chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {\n    chrome.declarativeContent.onPageChanged.addRules([kMatchRule]);\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/constant_context/content_script.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.storage.local.get(['words'], function(object) {\n  let regExp = new RegExp('\\\\b(' + object.words.join('|') + ')\\\\b');\n  const kSets = [\n    {selectors: 'p, span', color: '#f7d68f'},\n    {selectors: 'li, td', color: '#89b1ed'},\n    {selectors: 'h1, h2, h3, th', color: '#8ae2a0'}\n  ];\n  for (let set of kSets) {\n    let elements = Array.from(document.querySelectorAll(set.selectors));\n    for (let element of elements) {\n      if (regExp.test(element.innerText))\n        element.style.backgroundColor = set.color;\n    }\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/constant_context/manifest.json",
    "content": "{\n  \"name\": \"Constant Context\",\n  \"description\" : \"Highlights elements with keywords on developer.chrome\",\n  \"version\": \"1.0\",\n  \"page_action\": {\n    \"default_icon\": {\n      \"16\": \"images/cc16.png\",\n      \"32\": \"images/cc32.png\"\n      },\n    \"default_popup\": \"popup.html\"\n  },\n  \"icons\": {\n    \"16\": \"images/cc16.png\",\n    \"48\": \"images/cc48.png\",\n    \"32\": \"images/cc32.png\",\n    \"128\": \"images/cc128.png\"\n  },\n  \"permissions\": [\n    \"https://developer.chrome.com/*\",\n    \"storage\",\n    \"declarativeContent\"\n  ],\n  \"manifest_version\": 2,\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"web_accessible_resources\": [\"style.css\"],\n  \"content_scripts\": [\n    {\n      \"all_frames\": true,\n      \"js\": [\"content_script.js\"],\n      \"matches\": [\"https://developer.chrome.com/*\"],\n      \"run_at\": \"document_idle\"\n    }\n  ]\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/constant_context/popup.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Constant Context</title>\n    <style>\n      body {\n        min-width: 300px;\n        font-size: 15px;\n      }\n      input {\n        margin: 5px;\n        outline: none;\n      }\n    </style>\n  </head>\n\n  <body>\n    <h2>Constant Context</h2>\n    <p>Highlights context around words.</p>\n    <ul id=\"displayWords\"></ul>\n    <form id=\"form\">\n      <input type=\"text\" name=\"word\" id=\"userWords\">\n      <br>\n      <input type='submit' value='Submit' id='wordSubmit'>\n      <button id=\"clearList\">Clear</button>\n    </form>\n  </body>\n  <script src=\"popup.js\"></script>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/constant_context/popup.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction displayWords() {\n  chrome.storage.local.get(['words'], function(object) {\n    let pageList = document.getElementById('displayWords');\n    if (object.words) {\n      searchWords = object.words\n      for (var i = 0; i < searchWords.length; i++){\n        let listItem = document.createElement('li');\n        listItem.innerText = searchWords[i]\n        pageList.appendChild(listItem);\n      }\n    }\n  });\n}\n\ndisplayWords();\n\ndocument.getElementById('wordSubmit').onclick = function() {\n  let userWords = document.getElementById('userWords').value.trim();\n  chrome.storage.local.get(['words'], function(object) {\n    let newWords = object.words || [];\n    newWords.push(userWords);\n    chrome.storage.local.set({words: newWords});\n  })\n  chrome.tabs.executeScript(null, {\n    file: 'content_script.js'\n  });\n}\n\ndocument.getElementById('clearList').onclick = function() {\n  chrome.storage.local.clear();\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/download_images/background.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\n// Declare extension default properties\nlet downloadsArray = [];\nlet initialState = {\n  'savedImages': downloadsArray,\n  'thumbnails': false,\n  'saveImages': true\n};\n\n// Set extension setting on installation\nchrome.runtime.onInstalled.addListener(function() {\n  chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {\n    chrome.declarativeContent.onPageChanged.addRules([{\n      conditions: [\n        new chrome.declarativeContent.PageStateMatcher({\n          pageUrl: { hostEquals: 'developer.chrome.com', schemes: ['https'] },\n          css: ['img']\n        })\n      ],\n      actions: [ new chrome.declarativeContent.ShowPageAction() ]\n    }]);\n  });\n  chrome.storage.local.set(initialState);\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/download_images/manifest.json",
    "content": "{\n  \"name\": \"Download Images\",\n  \"description\" : \"Displays all webpage images and allows user to download\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 2,\n  \"page_action\": {\n    \"default_popup\": \"popup.html\",\n    \"default_icon\": {\n      \"16\": \"/images/download_image16.png\",\n      \"32\": \"/images/download_image32.png\",\n      \"48\": \"/images/download_image48.png\",\n      \"128\": \"/images/download_image128.png\"\n    }\n  },\n  \"icons\": {\n    \"16\": \"/images/download_image16.png\",\n    \"32\": \"/images/download_image32.png\",\n    \"48\": \"/images/download_image48.png\",\n    \"128\": \"/images/download_image128.png\"\n  },\n  \"permissions\": [\n    \"downloads\",\n    \"storage\",\n    \"activeTab\",\n    \"declarativeContent\"\n  ],\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"options_page\": \"options.html\"\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/download_images/options.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Options: Download Images</title>\n    <style>\n    #options_div {\n      margin: 30px;\n    }\n    #saved_images {\n      display: flex;\n      align-items: center;\n      justify-content: center;\n    }\n\n    img {\n        max-width: 100%;\n        max-height: 100%;\n    }\n\n    .square {\n        height: 175px;\n        width: 175px;\n        margin: 10px;\n    }\n    </style>\n  </head>\n  <body>\n    <div id=\"options_div\">\n      <input type=\"checkbox\" id=\"thumbnails\"> Display Images as Thumbnails\n      <br />\n      <br />\n      <input type=\"checkbox\" id=\"save_images\"> Save Downloaded Images\n      <br />\n      <br />\n      <button id=\"delete_button\">Delete Saved Images</button>\n    </div>\n    <div id=\"savedImages\"></div>\n    <script src=\"options.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/download_images/options.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict'\n\n// Selects saveImagesOption checkbox element\nlet saveImagesOption = document.getElementById('save_images');\n// Selects thumbnailOption checkbox element\nlet thumbnailOption = document.getElementById('thumbnails');\n\nfunction setCheckbox(data, checkbox) {\n  checkbox.checked = data;\n};\n\n// Gets thumbnails and saveImages value from storage\nchrome.storage.local.get(['saveImages', 'thumbnails'], function(data) {\n  setCheckbox(data.saveImages, saveImagesOption);\n  saveImagesOption.checked = data.saveImages === true;\n  setCheckbox(data.thumbnails, thumbnailOption);\n});\n\n// Saves users prefrences\nfunction storeOption(optionName, optionValue) {\n  let data = {};\n  data[optionName] = optionValue;\n  chrome.storage.local.set(data);\n};\n\nsaveImagesOption.onchange = function() {\n  storeOption('saveImages', saveImagesOption.checked);\n};\n\nthumbnailOption.onchange = function() {\n  storeOption('thumbnails', thumbnailOption.checked);\n};\n\nlet savedImages = document.getElementById('savedImages');\n\nlet deleteButton = document.getElementById('delete_button');\n\ndeleteButton.onclick = function() {\n  let blankArray = [];\n  chrome.storage.local.set({'savedImages': blankArray});\n  location.reload();\n};\n// Gets saved downloaded images from storage\nchrome.storage.local.get('savedImages', function(element) {\n  let pageImages = element.savedImages;\n  pageImages.forEach(function(image) {\n    // Create div element and give it class of square\n    let newDiv = document.createElement('div');\n    newDiv.className = 'square';\n    // Create image element\n    let newImage = document.createElement('img');\n    // let lineBreak = document.createElement('br');\n    // Image source is equal to saved download image\n    newImage.src = image;\n    newImage.addEventListener('click', function() {\n      chrome.downloads.download({url: newImage.src});\n    });\n    // Append all elements to options page\n    newDiv.appendChild(newImage);\n    savedImages.appendChild(newDiv);\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/download_images/popup.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Download Images</title>\n    <style>\n      body {\n        min-width: 300px;\n        font-size: 15px;\n      }\n      input {\n        margin: 5px;\n        outline: none;\n      }\n      img {\n          max-width: 100%;\n          max-height: 100%;\n      }\n      .square {\n          height: 175px;\n          width: 175px;\n          margin: 10px;\n      }\n    </style>\n  </head>\n  <body>\n    <h1>Click image to download.</h1>\n    <button id=\"options_button\">Options</button>\n    <br>\n    <div id=\"image_div\"></div>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/download_images/popup.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict'\n\n// Script code to inject on page\n// Selects images then returns array of their currentSrc\nconst scriptCode =\n  `(function() {\n      let images = document.querySelectorAll('img');\n      let srcArray =\n           Array.from(images).map(function(image) {\n             return image.currentSrc;\n           });\n      return srcArray\n    })();`;\n\n\n// Declare add image function to save downloaded images\nfunction addImage(url) {\n  chrome.storage.local.get('savedImages', function(result) {\n    // Check if storage has exsisting arrays\n    // If array found, blank array is replaced with found array\n    // If no array, we add to created blank array\n    let downloadsArray = result.savedImages || [];\n    // Images are added\n    downloadsArray.push(url);\n    // Chrome stores the new array with the new image\n    chrome.storage.local.set({'savedImages': downloadsArray}, function() {\n      if (chrome.runtime.lastError) {\n        console.log(chrome.runtime.lastError);\n      } else {\n        console.log('Image saved successfully');\n      };\n    });\n  });\n};\n\n// Grabs the imageDiv from the popup\nlet imageDiv = document.getElementById('image_div');\nfunction setUp(array) {\n  chrome.storage.local.get(\n      ['saveImages', 'thumbnails'], function(config) {\n    for (let src of array) {\n      let newImage = document.createElement('img');\n      let lineBreak = document.createElement('br');\n      newImage.src = src;\n      console.log(newImage)\n      // Add an onclick event listener\n      newImage.addEventListener('click', function() {\n        // Downloads and image when it is clicked on\n        chrome.downloads.download({url: newImage.src});\n        // Checks if extension is set to store images\n        if (config.saveImages === true) {\n          // If true, call addImage function\n          addImage(newImage.src);\n        };\n      });\n      // Checks extension thumbnail settings\n      if (config.thumbnails === true) {\n        // If on, popup displays images as thumnails\n        let newDiv = document.createElement('div');\n        newDiv.className = 'square';\n        newDiv.appendChild(newImage);\n        imageDiv.appendChild(newDiv);\n      } else {\n        // If off, images are displayed at full size\n        imageDiv.appendChild(newImage);\n      };\n      imageDiv.appendChild(lineBreak);\n    };\n  });\n};\n\n// Runs script when popup is opened\nchrome.tabs.executeScript({code: scriptCode}, function(result) {\n  setUp(result[0]);\n});\n\nlet optionsButton = document.getElementById('options_button');\n\noptionsButton.onclick = function() {\n  chrome.tabs.create({ url: \"options.html\" });\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/email_this_page/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction customMailtoUrl() {\n  if (window.localStorage == null)\n    return \"\";\n  if (window.localStorage.customMailtoUrl == null)\n    return \"\";\n  return window.localStorage.customMailtoUrl;\n}\n\nfunction executeMailto(tab_id, subject, body, selection) {\n  var default_handler = customMailtoUrl().length == 0;\n\n  var action_url = \"mailto:?\"\n      if (subject.length > 0)\n        action_url += \"subject=\" + encodeURIComponent(subject) + \"&\";\n\n  if (body.length > 0) {\n    action_url += \"body=\" + encodeURIComponent(body);\n\n    // Append the current selection to the end of the text message.\n    if (selection.length > 0) {\n      action_url += encodeURIComponent(\"\\n\\n\") +\n          encodeURIComponent(selection);\n    }\n  }\n\n  if (!default_handler) {\n    // Custom URL's (such as opening mailto in Gmail tab) should have a\n    // separate tab to avoid clobbering the page you are on.\n    var custom_url = customMailtoUrl();\n    action_url = custom_url.replace(\"%s\", encodeURIComponent(action_url));\n    console.log('Custom url: ' + action_url);\n    chrome.tabs.create({ url: action_url });\n  } else {\n    // Plain vanilla mailto links open up in the same tab to prevent\n    // blank tabs being left behind.\n    console.log('Action url: ' + action_url);\n    chrome.tabs.update(tab_id, { url: action_url });\n  }\n}\n\nchrome.runtime.onConnect.addListener(function(port) {\n  var tab = port.sender.tab;\n\n  // This will get called by the content script we execute in\n  // the tab as a result of the user pressing the browser action.\n  port.onMessage.addListener(function(info) {\n    var max_length = 1024;\n    if (info.selection.length > max_length)\n      info.selection = info.selection.substring(0, max_length);\n    executeMailto(tab.id, info.title, tab.url, info.selection);\n  });\n});\n\n// Called when the user clicks on the browser action icon.\nchrome.browserAction.onClicked.addListener(function(tab) {\n  // We can only inject scripts to find the title on pages loaded with http\n  // and https so for all other pages, we don't ask for the title.\n  if (tab.url.indexOf(\"http:\") != 0 &&\n      tab.url.indexOf(\"https:\") != 0) {\n    executeMailto(tab.id, \"\", tab.url, \"\");\n  } else {\n    chrome.tabs.executeScript(null, {file: \"content_script.js\"});\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/email_this_page/content_script.js",
    "content": "// Copyright (c) 2009 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar additionalInfo = {\n  \"title\": document.title,\n  \"selection\": window.getSelection().toString()\n};\n\nchrome.runtime.connect().postMessage(additionalInfo);\n"
  },
  {
    "path": "_archive/mv2/extensions/email_this_page/manifest.json",
    "content": "{\n  \"name\": \"Email this page (by Google)\",\n  \"description\": \"This extension adds an email button to the toolbar which allows you to email the page link using your default mail client or Gmail.\",\n  \"version\": \"1.2.6\",\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"icons\": { \"128\": \"mail_128x128.png\" },\n  \"options_page\": \"options.html\",\n  \"permissions\": [\n    \"tabs\", \"http://*/*\", \"https://*/*\"\n  ],\n  \"browser_action\": {\n    \"default_title\": \"Email this page\",\n    \"default_icon\": \"email_16x16.png\"\n  },\n\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/email_this_page/options.html",
    "content": "<!DOCTYPE>\n<!--\n * Copyright (c) 2012 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n<html>\n<head>\n  <title>Options for the Send as Email extension</title>\n<style>\n#providerSelection {\n  font-family: Helvetica, Arial, sans-serif;\n  font-size: 10pt;\n}\n</style>\n<script src=\"options.js\"></script>\n</head>\n<body>\n<table class=\"simple\">\n<tr>\n  <td rowspan=\"2\" valign=\"top\" align=\"center\" width=\"80\">\n    <img src=\"mail_128x128.png\" width=\"64\" height=\"64\" />\n  </td>\n  <td height=\"22\"></td>\n</tr>\n<tr>\n  <td valign=\"center\">\n    <div id=\"providerSelection\">\n    <strong>Select provider to use when emailing a web page address:</strong>\n    <br /><br />\n    <label>\n      <input id=\"default\" type=\"radio\" name=\"mailto\" value=\"mailto\" checked>\n      Your default mail handler<br>\n    </label>\n\n    <label>\n      <input id=\"gmail\" type=\"radio\" name=\"mailto\" value=\"gmail\">Gmail<br>\n    </label>\n    </div>\n  </td>\n</tr>\n</table>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/email_this_page/options.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar gmail = \"https://mail.google.com/mail/?extsrc=mailto&url=%s\";\n\nfunction toggle(radioButton) {\n  if (window.localStorage == null) {\n    alert('Local storage is required for changing providers');\n    return;\n  }\n  if (document.getElementById('gmail').checked) {\n    window.localStorage.customMailtoUrl = gmail;\n  } else {\n    window.localStorage.customMailtoUrl = \"\";\n  }\n}\n\nfunction main() {\n  if (window.localStorage == null) {\n    alert(\"LocalStorage must be enabled for changing options.\");\n    document.getElementById('default').disabled = true;\n    document.getElementById('gmail').disabled = true;\n    return;\n  }\n\n  // Default handler is checked. If we've chosen another provider, we must\n  // change the checkmark.\n  if (window.localStorage.customMailtoUrl == gmail)\n    document.getElementById('gmail').checked = true;\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  main();\n  document.querySelector('#default').addEventListener('click', toggle);\n  document.querySelector('#gmail').addEventListener('click', toggle);\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/fx/bg.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/*\n * Background page for Chrome Sounds extension.\n * This tracks various events from Chrome and plays sounds.\n */\n\n// Map of hostname suffixes or URLs without query params to sounds.\n// Yeah OK, some of these are a little cliche...\nvar urlSounds = {\n  \"http://www.google.ca/\": \"canadian-hello.mp3\",\n  \"chrome://histograms/\": \"time-passing.mp3\",\n  \"chrome://memory/\": \"transform!.mp3\",\n  \"chrome://crash/\": \"sadtrombone.mp3\",\n  \"chrome://extensions/\": \"beepboop.mp3\",\n  \"http://www.google.com.au/\": \"didgeridoo.mp3\",\n  \"http://www.google.com.my/\": \"my_subway.mp3\",\n  \"http://www.google.com/appserve/fiberrfi/\": \"dialup.mp3\",\n  \"lively.com\": \"cricket.mp3\",\n  \"http://www.google.co.uk/\": \"mind_the_gap.mp3\",\n  \"http://news.google.com/\": \"news.mp3\",\n  \"http://www.bing.com/\": \"sonar.mp3\",\n};\n\n// Map of query parameter words to sounds.\n// More easy cliches...\nvar searchSounds = {\n  \"scotland\": \"bagpipe.mp3\",\n  \"seattle\": \"rain.mp3\",\n};\n\n// Map of tab numbers to notes on a scale.\nvar tabNoteSounds = {\n  \"tab0\": \"mando-1.mp3\",\n  \"tab1\": \"mando-2.mp3\",\n  \"tab2\": \"mando-3.mp3\",\n  \"tab3\": \"mando-4.mp3\",\n  \"tab4\": \"mando-5.mp3\",\n  \"tab5\": \"mando-6.mp3\",\n  \"tab6\": \"mando-7.mp3\",\n};\n\n// Map of sounds that play in a continuous loop while an event is happening\n// in the content area (e.g. \"keypress\" while start and keep looping while\n// the user keeps typing).\nvar contentSounds = {\n  \"keypress\": \"typewriter-1.mp3\",\n  \"resize\": \"harp-transition-2.mp3\",\n  \"scroll\": \"shepard.mp3\"\n};\n\n// Map of events to their default sounds\nvar eventSounds = {\n  \"tabCreated\": \"conga1.mp3\",\n  \"tabMoved\": \"bell-transition.mp3\",\n  \"tabRemoved\": \"smash-glass-1.mp3\",\n  \"tabSelectionChanged\": \"click.mp3\",\n  \"tabAttached\": \"whoosh-15.mp3\",\n  \"tabDetached\": \"sword-shrill.mp3\",\n  \"tabNavigated\": \"click.mp3\",\n  \"windowCreated\": \"bell-small.mp3\",\n  \"windowFocusChanged\": \"click.mp3\",\n  \"bookmarkCreated\": \"bubble-drop.mp3\",\n  \"bookmarkMoved\": \"thud.mp3\",\n  \"bookmarkRemoved\": \"explosion-6.mp3\",\n  \"windowCreatedIncognito\": \"weird-wind1.mp3\",\n  \"startup\": \"whoosh-19.mp3\"\n};\n\nvar soundLists = [urlSounds, searchSounds, eventSounds, tabNoteSounds,\n    contentSounds];\n\nvar sounds = {};\n\n// Map of event names to extension events.\n// Events intentionally skipped:\n// chrome.windows.onRemoved - can't suppress the tab removed that comes first\nvar events = {\n  \"tabCreated\": chrome.tabs.onCreated,\n  \"tabMoved\": chrome.tabs.onMoved,\n  \"tabRemoved\": chrome.tabs.onRemoved,\n  \"tabSelectionChanged\": chrome.tabs.onSelectionChanged,\n  \"tabAttached\": chrome.tabs.onAttached,\n  \"tabDetached\": chrome.tabs.onDetached,\n  \"tabNavigated\": chrome.tabs.onUpdated,\n  \"windowCreated\": chrome.windows.onCreated,\n  \"windowFocusChanged\": chrome.windows.onFocusChanged,\n  \"bookmarkCreated\": chrome.bookmarks.onCreated,\n  \"bookmarkMoved\": chrome.bookmarks.onMoved,\n  \"bookmarkRemoved\": chrome.bookmarks.onRemoved\n};\n\n// Map of event name to a validation function that is should return true if\n// the default sound should be played for this event.\nvar eventValidator = {\n  \"tabCreated\": tabCreated,\n  \"tabNavigated\": tabNavigated,\n  \"tabRemoved\": tabRemoved,\n  \"tabSelectionChanged\": tabSelectionChanged,\n  \"windowCreated\": windowCreated,\n  \"windowFocusChanged\": windowFocusChanged,\n};\n\nvar started = false;\n\nfunction shouldPlay(id) {\n  // Ignore all events until the startup sound has finished.\n  if (id != \"startup\" && !started)\n    return false;\n  var val = localStorage.getItem(id);\n  if (val && val != \"enabled\") {\n    console.log(id + \" disabled\");\n    return false;\n  }\n  return true;\n}\n\nfunction didPlay(id) {\n  if (!localStorage.getItem(id))\n    localStorage.setItem(id, \"enabled\");\n}\n\nfunction playSound(id, loop) {\n  if (!shouldPlay(id))\n    return;\n\n  var sound = sounds[id];\n  console.log(\"playsound: \" + id);\n  if (sound && sound.src) {\n    if (!sound.paused) {\n      if (sound.currentTime < 0.2) {\n        console.log(\"ignoring fast replay: \" + id + \"/\" + sound.currentTime);\n        return;\n      }\n      sound.pause();\n      sound.currentTime = 0;\n    }\n    if (loop)\n      sound.loop = loop;\n\n    // Sometimes, when playing multiple times, readyState is HAVE_METADATA.\n    if (sound.readyState == 0) {  // HAVE_NOTHING\n      console.log(\"bad ready state: \" + sound.readyState);\n    } else if (sound.error) {\n      console.log(\"media error: \" + sound.error);\n    } else {\n      didPlay(id);\n      sound.play();\n    }\n  } else {\n    console.log(\"bad playSound: \" + id);\n  }\n}\n\nfunction stopSound(id) {\n  console.log(\"stopSound: \" + id);\n  var sound = sounds[id];\n  if (sound && sound.src && !sound.paused) {\n    sound.pause();\n    sound.currentTime = 0;\n  }\n}\n\nvar base_url = \"http://dl.google.com/dl/chrome/extensions/audio/\";\n\nfunction soundLoadError(audio, id) {\n  console.log(\"failed to load sound: \" + id + \"-\" + audio.src);\n  audio.src = \"\";\n  if (id == \"startup\")\n    started = true;\n}\n\nfunction soundLoaded(audio, id) {\n  console.log(\"loaded sound: \" + id);\n  sounds[id] = audio;\n  if (id == \"startup\")\n    playSound(id);\n}\n\n// Hack to keep a reference to the objects while we're waiting for them to load.\nvar notYetLoaded = {};\n\nfunction loadSound(file, id) {\n  if (!file.length) {\n    console.log(\"no sound for \" + id);\n    return;\n  }\n  var audio = new Audio();\n  audio.id = id;\n  audio.onerror = function() { soundLoadError(audio, id); };\n  audio.addEventListener(\"canplaythrough\",\n      function() { soundLoaded(audio, id); }, false);\n  if (id == \"startup\") {\n    audio.addEventListener(\"ended\", function() { started = true; });\n  }\n  audio.src = base_url + file;\n  audio.load();\n  notYetLoaded[id] = audio;\n}\n\n// Remember the last event so that we can avoid multiple events firing\n// unnecessarily (e.g. selection changed due to close).\nvar eventsToEat = 0;\n\nfunction eatEvent(name) {\n  if (eventsToEat > 0) {\n    console.log(\"ate event: \" + name);\n    eventsToEat--;\n    return true;\n  }\n  return false;\n}\n\nfunction soundEvent(event, name) {\n  if (event) {\n    var validator = eventValidator[name];\n    if (validator) {\n      event.addListener(function() {\n        console.log(\"handling custom event: \" + name);\n\n        // Check this first since the validator may bump the count for future\n        // events.\n        var canPlay = (eventsToEat == 0);\n        if (validator.apply(this, arguments)) {\n          if (!canPlay) {\n            console.log(\"ate event: \" + name);\n            eventsToEat--;\n            return;\n          }\n          playSound(name);\n        }\n      });\n    } else {\n      event.addListener(function() {\n        console.log(\"handling event: \" + name);\n        if (eatEvent(name)) {\n          return;\n        }\n        playSound(name);\n      });\n    }\n  } else {\n    console.log(\"no event for \" + name);\n  }\n}\n\nvar navSound;\n\nfunction stopNavSound() {\n  if (navSound) {\n    stopSound(navSound);\n    navSound = null;\n  }\n}\n\nfunction playNavSound(id) {\n  stopNavSound();\n  navSound = id;\n  playSound(id);\n}\n\nfunction tabNavigated(tabId, changeInfo, tab) {\n  // Quick fix to catch the case where the content script doesn't have a chance\n  // to stop itself.\n  stopSound(\"keypress\");\n\n  //console.log(JSON.stringify(changeInfo) + JSON.stringify(tab));\n  if (changeInfo.status != \"complete\") {\n    return false;\n  }\n  if (eatEvent(\"tabNavigated\")) {\n    return false;\n  }\n\n  console.log(JSON.stringify(tab));\n\n  if (navSound)\n    stopSound(navSound);\n\n  var re = /https?:\\/\\/([^\\/:]*)[^\\?]*\\??(.*)/i;\n  match = re.exec(tab.url);\n  if (match) {\n    if (match.length == 3) {\n      var query = match[2];\n      var parts = query.split(\"&\");\n      for (var i in parts) {\n        if (parts[i].indexOf(\"q=\") == 0) {\n          var q = decodeURIComponent(parts[i].substring(2));\n          q = q.replace(\"+\", \" \");\n          console.log(\"query == \" + q);\n          var words = q.split(\" \");\n          for (j in words) {\n            if (searchSounds[words[j]]) {\n              console.log(\"searchSound: \" + words[j]);\n              playNavSound(words[j]);\n              return false;\n            }\n          }\n          break;\n        }\n      }\n    }\n    if (match.length >= 2) {\n      var hostname = match[1];\n      if (hostname) {\n        var parts = hostname.split(\".\");\n        if (parts.length > 1) {\n          var tld2 = parts.slice(-2).join(\".\");\n          var tld3 = parts.slice(-3).join(\".\");\n          var sound = urlSounds[tld2];\n          if (sound) {\n            playNavSound(tld2);\n            return false;\n          }\n          sound = urlSounds[tld3];\n          if (sound) {\n            playNavSound(tld3);\n            return false;\n          }\n        }\n      }\n    }\n  }\n\n  // Now try a direct URL match (without query string).\n  var url = tab.url;\n  var query = url.indexOf(\"?\");\n  if (query > 0) {\n    url = tab.url.substring(0, query);\n  }\n  console.log(tab.url);\n  var sound = urlSounds[url];\n  if (sound) {\n    playNavSound(url);\n    return false;\n  }\n\n  return true;\n}\n\nvar selectedTabId = -1;\n\nfunction tabSelectionChanged(tabId) {\n  selectedTabId = tabId;\n  if (eatEvent(\"tabSelectionChanged\"))\n    return false;\n\n  var count = 7;\n  chrome.tabs.get(tabId, function(tab) {\n    var index = tab.index % count;\n    playSound(\"tab\" + index);\n  });\n  return false;\n}\n\nfunction tabCreated(tab) {\n  if (eatEvent(\"tabCreated\")) {\n    return false;\n  }\n  eventsToEat++;  // tabNavigated or tabSelectionChanged\n  // TODO - unfortunately, we can't detect whether this tab will get focus, so\n  // we can't decide whether or not to eat a second event.\n  return true;\n}\n\nfunction tabRemoved(tabId) {\n  if (eatEvent(\"tabRemoved\")) {\n    return false;\n  }\n  if (tabId == selectedTabId) {\n    eventsToEat++;  // tabSelectionChanged\n    stopNavSound();\n  }\n  return true;\n}\n\nfunction windowCreated(window) {\n  if (eatEvent(\"windowCreated\")) {\n    return false;\n  }\n  eventsToEat += 3;  // tabNavigated, tabSelectionChanged, windowFocusChanged\n  if (window.incognito) {\n    playSound(\"windowCreatedIncognito\");\n    return false;\n  }\n  return true;\n}\n\nvar selectedWindowId = -1;\n\nfunction windowFocusChanged(windowId) {\n  if (windowId == selectedWindowId) {\n    return false;\n  }\n  selectedWindowId = windowId;\n  if (eatEvent(\"windowFocusChanged\")) {\n    return false;\n  }\n  return true;\n}\n\nfunction contentScriptHandler(request) {\n  if (contentSounds[request.eventName]) {\n    if (request.eventValue == \"started\") {\n      playSound(request.eventName, true);\n    } else if (request.eventValue == \"stopped\") {\n      stopSound(request.eventName);\n    } else {\n      playSound(request.eventName);\n    }\n  }\n  console.log(\"got message: \" + JSON.stringify(request));\n}\n\n\n//////////////////////////////////////////////////////\n\n// Listen for messages from content scripts.\nchrome.extension.onRequest.addListener(contentScriptHandler);\n\n// Load the sounds and register event listeners.\nfor (var list in soundLists) {\n  for (var id in soundLists[list]) {\n    loadSound(soundLists[list][id], id);\n  }\n}\nfor (var name in events) {\n  soundEvent(events[name], name);\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/fx/content.js",
    "content": "/*\n * Content script for Chrome Sounds.\n * Tracks in-page events and notifies the background page.\n */\n\nfunction sendEvent(event, value) {\n  console.log(\"sendEvent: \" + event + \",\" + value);\n  chrome.extension.sendRequest({eventName: event, eventValue: value});\n}\n\n// Timers to trigger \"stopEvent\" for coalescing events.\nvar timers = {};\n\nfunction stopEvent(type) {\n  timers[type] = 0;\n  sendEvent(type, \"stopped\");\n}\n\n// Automatically coalesces repeating events into a start and a stop event.\n// |validator| is a function which should return true if the event is\n// considered to be a valid event of this type.\nfunction handleEvent(event, type, validator) {\n  if (validator) {\n    if (!validator(event)) {\n      return;\n    }\n  }\n  var timerId = timers[type];\n  var eventInProgress = (timerId > 0);\n  if (eventInProgress) {\n    clearTimeout(timerId);\n    timers[type] = 0;\n  } else {\n    sendEvent(type, \"started\");\n  }\n  timers[type] = setTimeout(stopEvent, 300, type);\n}\n\nfunction listenAndCoalesce(target, type, validator) {\n  target.addEventListener(type, function(event) {\n    handleEvent(event, type, validator);\n  }, true);\n}\n\nlistenAndCoalesce(document, \"scroll\");\n\n// For some reason, \"resize\" doesn't seem to work with addEventListener.\nif ((window == window.top) && document.body && !document.body.onresize) {\n  document.body.onresize = function(event) {\n    sendEvent(\"resize\", \"\");\n  };\n}\n\nlistenAndCoalesce(document, \"keypress\", function(event) {\n  if (event.charCode == 13)\n    return false;\n\n  // TODO(erikkay) This doesn't work in gmail's rich text compose window.\n  return event.target.tagName == \"TEXTAREA\" ||\n         event.target.tagName == \"INPUT\" ||\n         event.target.isContentEditable;\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/fx/manifest.json",
    "content": "{\n  \"name\": \"Chrome Sounds\",\n  \"version\": \"1.2\",\n  \"description\": \"Enjoy a more magical and immersive experience when browsing the web using the power of sound.\",\n  \"background\": {\n    \"scripts\": [\"bg.js\"]\n  },\n  \"options_page\": \"options.html\",\n  \"icons\": { \"128\": \"icon.png\" },\n  \"permissions\": [\n    \"tabs\",\n    \"bookmarks\",\n    \"http://*/*\",\n    \"https://*/*\"\n  ],\n  \"content_scripts\": [ {\n    \"matches\": [\"http://*/*\", \"https://*/*\"],\n    \"js\": [\"content.js\"],\n    \"all_frames\": true\n  }],\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/fx/options.html",
    "content": "<!doctype html>\n<html>\n<head>\n<style>\nbody {\n  font-family: sans-serif;\n}\n#attributions {\n  margin-top: 20px;\n  color: #666666;\n  Xfont-size: 10px;\n}\n.sound {\n  cursor: pointer;\n}\n</style>\n<script src=\"options.js\"></script>\n</head>\n<body>\n<div id=\"sounds\"></div>\n<div id=\"attributions\">\nSounds from:\n<ul>\n<li><a href=\"http://www.freesound.org\">www.freesound.org</a></li>\n<li><a href=\"http://www.free-samples-n-loops.com/loops.html\">www.free-samples-n-loops.com/loops.html</a></li>\n<li>Googlers with microphones.*</li>\n</ul>\n<span style=\"font-size:10px\">* Canadian sound made by actual Canadian.</span>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/fx/options.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction playSound(id) {\n  console.log(id);\n  chrome.extension.getBackgroundPage().playSound(id, false);\n}\n\nfunction stopSound(id) {\n  chrome.extension.getBackgroundPage().stopSound(id);\n}\n\nfunction soundChanged(event) {\n  var key = event.target.name;\n  var checked = event.target.checked;\n  if (checked) {\n    localStorage.setItem(key, \"enabled\");\n    playSound(event.target.name);\n  } else {\n    localStorage.setItem(key, \"disabled\");\n    stopSound(event.target.name);\n  }\n}\n\nfunction showSounds() {\n  var sounds = document.getElementById(\"sounds\");\n  if (!localStorage.length) {\n    sounds.innerText = \"\";\n    return;\n  }\n  sounds.innerText = \"Discovered sounds: (uncheck to disable)\";\n  var keys = new Array();\n  for (var key in localStorage) {\n    keys.push(key);\n    console.log(key);\n  }\n  keys.sort();\n  for (var index in keys) {\n    var key = keys[index];\n    var div = document.createElement(\"div\");\n    var check = document.createElement(\"input\");\n    check.type = \"checkbox\"\n    check.name = key;\n    check.checked = localStorage[key] == \"enabled\";\n    check.onchange = soundChanged;\n    div.appendChild(check);\n    var text = document.createElement(\"span\");\n    text.id = key;\n    text.innerText = key;\n    text.className = \"sound\";\n    text.onclick = function(event) { playSound(event.target.id); };\n    div.appendChild(text);\n    sounds.appendChild(div);\n  }\n}\n\ndocument.addEventListener('DOMContentLoaded', showSounds);\ndocument.addEventListener('focus', showSounds);\n"
  },
  {
    "path": "_archive/mv2/extensions/gdocs/README",
    "content": "Sample extension to demonstrate integration with an OAuth service.\n\nOverview\n--------\nThis sample demonstrates the use of OAuth to authorize against \nGoogle's Contacts API inside of an extension.  It implements a library which\nmay be reused generically to authorize requests to any 3-legged OAuth API.\n\nLibrary\n-------\nThe library files are:\n * chrome_ex_oauth.html\n * chrome_ex_oauth.js\n * chrome_ex_oauthsimple.js\n\nTo use these files, place them in the root of your extension and include both\n.js files in your background page in the following order:\n\n  <script type=\"text/javascript\" src=\"chrome_ex_oauthsimple.js\"></script>\n  <script type=\"text/javascript\" src=\"chrome_ex_oauth.js\"></script>   \n  \nTo initialize the API, create a ChromeExOAuth object in the background page:\n\n      var oauth = ChromeExOAuth.initBackgroundPage({\n        'request_url'     :  <OAuth request URL>, \n        'authorize_url'   :  <OAuth authorize URL>,  \n        'access_url'      :  <OAuth access token URL>,  \n        'consumer_key'    :  <OAuth consumer key>,  \n        'consumer_secret' :  <OAuth consumer secret>,  \n        'scope'           :  <scope parameter for this auth>,\n        'app_name'        :  <application name, not used by all OAuth providers>\n      }); \n\nCall the authorize() function to redirect the user to the OAuth provider in\norder to obtain an access token.  The client library abstracts most of this \nprocess, so all you need to do is pass a callback to the authorize() function\nand a new tab will open and redirect the user.  If the library already has\nstored an access token for the current scope, then no tab will be opened.  In\neither case, the callback will be called with the resulting token and secret.\n\n      oauth.authorize(onAuthorized);\n      \nThere is no need to store the token and secret, as this library already stores\nthese values in localStorage.  Once the callback you specified is called, you\ncan call the sendSignedRequest function to send OAuth-signed requests to the\nAPI.  The sendSignedRequest call takes an url to fetch, a callback function,\nand an optional parameter object as its arguments.  The callback is passed\nthe response text as well as the XMLHttpRequest object which was used to \nmake the request as its arguments.\n  \n      function callback(text, xhr) {\n        //...\n      };\n      \n      function onAuthorized() { \n        var url = <API url inside of the requested scope>;\n        var request = {\n          'method' : 'GET',\n          'parameters' : {\n             <Any request parameters as key : value pairs>\n          }\n        }\n        oauth.sendSignedRequest(url, callback, request);\n      };\n      oauth.authorize(onAuthorized);\n      \n \n\n\n"
  },
  {
    "path": "_archive/mv2/extensions/gdocs/background.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n *\n * Author: Eric Bidelman <ericbidelman@chromium.org>\n-->\n<html>\n  <head>\n    <script type=\"text/javascript\" src=\"chrome_ex_oauthsimple.js\"></script>\n    <script type=\"text/javascript\" src=\"chrome_ex_oauth.js\"></script>\n    <script type=\"text/javascript\">\n      var DOCLIST_SCOPE = 'https://docs.google.com/feeds';\n      var DOCLIST_FEED = DOCLIST_SCOPE + '/default/private/full/';\n      var docs = []; // In memory cache for the user's entire doclist.\n      var refreshRate = localStorage.refreshRate || 300; // 5 min default.\n      var pollIntervalMin = 1000 * refreshRate;\n      var requests = [];\n\n      var oauth = ChromeExOAuth.initBackgroundPage({\n        'request_url': 'https://www.google.com/accounts/OAuthGetRequestToken',\n        'authorize_url': 'https://www.google.com/accounts/OAuthAuthorizeToken',\n        'access_url': 'https://www.google.com/accounts/OAuthGetAccessToken',\n        'consumer_key': 'anonymous',\n        'consumer_secret': 'anonymous',\n        'scope': DOCLIST_SCOPE,\n        'app_name': 'Chrome Extension Sample - Accessing Google Docs with OAuth'\n      });\n\n      function setIcon(opt_badgeObj) {\n        if (opt_badgeObj) {\n          var badgeOpts = {};\n          if (opt_badgeObj && opt_badgeObj.text != undefined) {\n            badgeOpts['text'] = opt_badgeObj.text;\n          }\n          if (opt_badgeObj && opt_badgeObj.tabId) {\n            badgeOpts['tabId'] = opt_badgeObj.tabId;\n          }\n          chrome.browserAction.setBadgeText(badgeOpts);\n        }\n      };\n\n      function clearPendingRequests() {\n        for (var i = 0, req; req = requests[i]; ++i) {\n          window.clearTimeout(req);\n        }\n        requests = [];\n      };\n\n      function logout() {\n        docs = [];\n        setIcon({'text': ''});\n        oauth.clearTokens();\n        clearPendingRequests();\n      };\n    </script>\n  </head>\n  <body>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/gdocs/chrome_ex_oauth.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n *\n * Author: Eric Bidelman <ericbidelman@chromium.org>\n-->\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>OAuth Redirect Page</title>\n    <style type=\"text/css\">\n      body {\n        font: 16px Arial;\n        color: #333;\n      }\n    </style>\n    <script type=\"text/javascript\" src=\"chrome_ex_oauthsimple.js\"></script>\n    <script type=\"text/javascript\" src=\"chrome_ex_oauth.js\"></script>\n    <script type=\"text/javascript\">\n      function onLoad() {\n        ChromeExOAuth.initCallbackPage();\n      };\n    </script>\n  </head>\n  <body onload=\"onLoad();\">\n    Redirecting...\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/gdocs/chrome_ex_oauth.js",
    "content": "// Copyright (c) 2010 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * Constructor - no need to invoke directly, call initBackgroundPage instead.\n * @constructor\n * @param {String} url_request_token The OAuth request token URL.\n * @param {String} url_auth_token The OAuth authorize token URL.\n * @param {String} url_access_token The OAuth access token URL.\n * @param {String} consumer_key The OAuth consumer key.\n * @param {String} consumer_secret The OAuth consumer secret.\n * @param {String} oauth_scope The OAuth scope parameter.\n * @param {Object} opt_args Optional arguments.  Recognized parameters:\n *     \"app_name\" {String} Name of the current application\n *     \"callback_page\" {String} If you renamed chrome_ex_oauth.html, the name\n *          this file was renamed to.\n */\nfunction ChromeExOAuth(url_request_token, url_auth_token, url_access_token,\n                       consumer_key, consumer_secret, oauth_scope, opt_args) {\n  this.url_request_token = url_request_token;\n  this.url_auth_token = url_auth_token;\n  this.url_access_token = url_access_token;\n  this.consumer_key = consumer_key;\n  this.consumer_secret = consumer_secret;\n  this.oauth_scope = oauth_scope;\n  this.app_name = opt_args && opt_args['app_name'] ||\n      \"ChromeExOAuth Library\";\n  this.key_token = \"oauth_token\";\n  this.key_token_secret = \"oauth_token_secret\";\n  this.callback_page = opt_args && opt_args['callback_page'] ||\n      \"chrome_ex_oauth.html\";\n  this.auth_params = {};\n  if (opt_args && opt_args['auth_params']) {\n    for (key in opt_args['auth_params']) {\n      if (opt_args['auth_params'].hasOwnProperty(key)) {\n        this.auth_params[key] = opt_args['auth_params'][key];\n      }\n    }\n  }\n};\n\n/*******************************************************************************\n * PUBLIC API METHODS\n * Call these from your background page.\n ******************************************************************************/\n\n/**\n * Initializes the OAuth helper from the background page.  You must call this\n * before attempting to make any OAuth calls.\n * @param {Object} oauth_config Configuration parameters in a JavaScript object.\n *     The following parameters are recognized:\n *         \"request_url\" {String} OAuth request token URL.\n *         \"authorize_url\" {String} OAuth authorize token URL.\n *         \"access_url\" {String} OAuth access token URL.\n *         \"consumer_key\" {String} OAuth consumer key.\n *         \"consumer_secret\" {String} OAuth consumer secret.\n *         \"scope\" {String} OAuth access scope.\n *         \"app_name\" {String} Application name.\n *         \"auth_params\" {Object} Additional parameters to pass to the\n *             Authorization token URL.  For an example, 'hd', 'hl', 'btmpl':\n *             http://code.google.com/apis/accounts/docs/OAuth_ref.html#GetAuth\n * @return {ChromeExOAuth} An initialized ChromeExOAuth object.\n */\nChromeExOAuth.initBackgroundPage = function(oauth_config) {\n  window.chromeExOAuthConfig = oauth_config;\n  window.chromeExOAuth = ChromeExOAuth.fromConfig(oauth_config);\n  window.chromeExOAuthRedirectStarted = false;\n  window.chromeExOAuthRequestingAccess = false;\n\n  var url_match = chrome.extension.getURL(window.chromeExOAuth.callback_page);\n  var tabs = {};\n  chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {\n    if (changeInfo.url &&\n        changeInfo.url.substr(0, url_match.length) === url_match &&\n        changeInfo.url != tabs[tabId] &&\n        window.chromeExOAuthRequestingAccess == false) {\n      chrome.tabs.create({ 'url' : changeInfo.url }, function(tab) {\n        tabs[tab.id] = tab.url;\n        chrome.tabs.remove(tabId);\n      });\n    }\n  });\n\n  return window.chromeExOAuth;\n};\n\n/**\n * Authorizes the current user with the configued API.  You must call this\n * before calling sendSignedRequest.\n * @param {Function} callback A function to call once an access token has\n *     been obtained.  This callback will be passed the following arguments:\n *         token {String} The OAuth access token.\n *         secret {String} The OAuth access token secret.\n */\nChromeExOAuth.prototype.authorize = function(callback) {\n  if (this.hasToken()) {\n    callback(this.getToken(), this.getTokenSecret());\n  } else {\n    window.chromeExOAuthOnAuthorize = function(token, secret) {\n      callback(token, secret);\n    };\n    chrome.tabs.create({ 'url' :chrome.extension.getURL(this.callback_page) });\n  }\n};\n\n/**\n * Clears any OAuth tokens stored for this configuration.  Effectively a\n * \"logout\" of the configured OAuth API.\n */\nChromeExOAuth.prototype.clearTokens = function() {\n  delete localStorage[this.key_token + encodeURI(this.oauth_scope)];\n  delete localStorage[this.key_token_secret + encodeURI(this.oauth_scope)];\n};\n\n/**\n * Returns whether a token is currently stored for this configuration.\n * Effectively a check to see whether the current user is \"logged in\" to\n * the configured OAuth API.\n * @return {Boolean} True if an access token exists.\n */\nChromeExOAuth.prototype.hasToken = function() {\n  return !!this.getToken();\n};\n\n/**\n * Makes an OAuth-signed HTTP request with the currently authorized tokens.\n * @param {String} url The URL to send the request to.  Querystring parameters\n *     should be omitted.\n * @param {Function} callback A function to be called once the request is\n *     completed.  This callback will be passed the following arguments:\n *         responseText {String} The text response.\n *         xhr {XMLHttpRequest} The XMLHttpRequest object which was used to\n *             send the request.  Useful if you need to check response status\n *             code, etc.\n * @param {Object} opt_params Additional parameters to configure the request.\n *     The following parameters are accepted:\n *         \"method\" {String} The HTTP method to use.  Defaults to \"GET\".\n *         \"body\" {String} A request body to send.  Defaults to null.\n *         \"parameters\" {Object} Query parameters to include in the request.\n *         \"headers\" {Object} Additional headers to include in the request.\n */\nChromeExOAuth.prototype.sendSignedRequest = function(url, callback,\n                                                     opt_params) {\n  var method = opt_params && opt_params['method'] || 'GET';\n  var body = opt_params && opt_params['body'] || null;\n  var params = opt_params && opt_params['parameters'] || {};\n  var headers = opt_params && opt_params['headers'] || {};\n\n  var signedUrl = this.signURL(url, method, params);\n\n  ChromeExOAuth.sendRequest(method, signedUrl, headers, body, function (xhr) {\n    if (xhr.readyState == 4) {\n      callback(xhr.responseText, xhr);\n    }\n  });\n};\n\n/**\n * Adds the required OAuth parameters to the given url and returns the\n * result.  Useful if you need a signed url but don't want to make an XHR\n * request.\n * @param {String} method The http method to use.\n * @param {String} url The base url of the resource you are querying.\n * @param {Object} opt_params Query parameters to include in the request.\n * @return {String} The base url plus any query params plus any OAuth params.\n */\nChromeExOAuth.prototype.signURL = function(url, method, opt_params) {\n  var token = this.getToken();\n  var secret = this.getTokenSecret();\n  if (!token || !secret) {\n    throw new Error(\"No oauth token or token secret\");\n  }\n\n  var params = opt_params || {};\n\n  var result = OAuthSimple().sign({\n    action : method,\n    path : url,\n    parameters : params,\n    signatures: {\n      consumer_key : this.consumer_key,\n      shared_secret : this.consumer_secret,\n      oauth_secret : secret,\n      oauth_token: token\n    }\n  });\n\n  return result.signed_url;\n};\n\n/**\n * Generates the Authorization header based on the oauth parameters.\n * @param {String} url The base url of the resource you are querying.\n * @param {Object} opt_params Query parameters to include in the request.\n * @return {String} An Authorization header containing the oauth_* params.\n */\nChromeExOAuth.prototype.getAuthorizationHeader = function(url, method,\n                                                          opt_params) {\n  var token = this.getToken();\n  var secret = this.getTokenSecret();\n  if (!token || !secret) {\n    throw new Error(\"No oauth token or token secret\");\n  }\n\n  var params = opt_params || {};\n\n  return OAuthSimple().getHeaderString({\n    action: method,\n    path : url,\n    parameters : params,\n    signatures: {\n      consumer_key : this.consumer_key,\n      shared_secret : this.consumer_secret,\n      oauth_secret : secret,\n      oauth_token: token\n    }\n  });\n};\n\n/*******************************************************************************\n * PRIVATE API METHODS\n * Used by the library.  There should be no need to call these methods directly.\n ******************************************************************************/\n\n/**\n * Creates a new ChromeExOAuth object from the supplied configuration object.\n * @param {Object} oauth_config Configuration parameters in a JavaScript object.\n *     The following parameters are recognized:\n *         \"request_url\" {String} OAuth request token URL.\n *         \"authorize_url\" {String} OAuth authorize token URL.\n *         \"access_url\" {String} OAuth access token URL.\n *         \"consumer_key\" {String} OAuth consumer key.\n *         \"consumer_secret\" {String} OAuth consumer secret.\n *         \"scope\" {String} OAuth access scope.\n *         \"app_name\" {String} Application name.\n *         \"auth_params\" {Object} Additional parameters to pass to the\n *             Authorization token URL.  For an example, 'hd', 'hl', 'btmpl':\n *             http://code.google.com/apis/accounts/docs/OAuth_ref.html#GetAuth\n * @return {ChromeExOAuth} An initialized ChromeExOAuth object.\n */\nChromeExOAuth.fromConfig = function(oauth_config) {\n  return new ChromeExOAuth(\n    oauth_config['request_url'],\n    oauth_config['authorize_url'],\n    oauth_config['access_url'],\n    oauth_config['consumer_key'],\n    oauth_config['consumer_secret'],\n    oauth_config['scope'],\n    {\n      'app_name' : oauth_config['app_name'],\n      'auth_params' : oauth_config['auth_params']\n    }\n  );\n};\n\n/**\n * Initializes chrome_ex_oauth.html and redirects the page if needed to start\n * the OAuth flow.  Once an access token is obtained, this function closes\n * chrome_ex_oauth.html.\n */\nChromeExOAuth.initCallbackPage = function() {\n  var background_page = chrome.extension.getBackgroundPage();\n  var oauth_config = background_page.chromeExOAuthConfig;\n  var oauth = ChromeExOAuth.fromConfig(oauth_config);\n  background_page.chromeExOAuthRedirectStarted = true;\n  oauth.initOAuthFlow(function (token, secret) {\n    background_page.chromeExOAuthOnAuthorize(token, secret);\n    background_page.chromeExOAuthRedirectStarted = false;\n    chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {\n      chrome.tabs.remove(tabs[0].id);\n    });\n  });\n};\n\n/**\n * Sends an HTTP request.  Convenience wrapper for XMLHttpRequest calls.\n * @param {String} method The HTTP method to use.\n * @param {String} url The URL to send the request to.\n * @param {Object} headers Optional request headers in key/value format.\n * @param {String} body Optional body content.\n * @param {Function} callback Function to call when the XMLHttpRequest's\n *     ready state changes.  See documentation for XMLHttpRequest's\n *     onreadystatechange handler for more information.\n */\nChromeExOAuth.sendRequest = function(method, url, headers, body, callback) {\n  var xhr = new XMLHttpRequest();\n  xhr.onreadystatechange = function(data) {\n    callback(xhr, data);\n  }\n  xhr.open(method, url, true);\n  if (headers) {\n    for (var header in headers) {\n      if (headers.hasOwnProperty(header)) {\n        xhr.setRequestHeader(header, headers[header]);\n      }\n    }\n  }\n  xhr.send(body);\n};\n\n/**\n * Decodes a URL-encoded string into key/value pairs.\n * @param {String} encoded An URL-encoded string.\n * @return {Object} An object representing the decoded key/value pairs found\n *     in the encoded string.\n */\nChromeExOAuth.formDecode = function(encoded) {\n  var params = encoded.split(\"&\");\n  var decoded = {};\n  for (var i = 0, param; param = params[i]; i++) {\n    var keyval = param.split(\"=\");\n    if (keyval.length == 2) {\n      var key = ChromeExOAuth.fromRfc3986(keyval[0]);\n      var val = ChromeExOAuth.fromRfc3986(keyval[1]);\n      decoded[key] = val;\n    }\n  }\n  return decoded;\n};\n\n/**\n * Returns the current window's querystring decoded into key/value pairs.\n * @return {Object} A object representing any key/value pairs found in the\n *     current window's querystring.\n */\nChromeExOAuth.getQueryStringParams = function() {\n  var urlparts = window.location.href.split(\"?\");\n  if (urlparts.length >= 2) {\n    var querystring = urlparts.slice(1).join(\"?\");\n    return ChromeExOAuth.formDecode(querystring);\n  }\n  return {};\n};\n\n/**\n * Binds a function call to a specific object.  This function will also take\n * a variable number of additional arguments which will be prepended to the\n * arguments passed to the bound function when it is called.\n * @param {Function} func The function to bind.\n * @param {Object} obj The object to bind to the function's \"this\".\n * @return {Function} A closure that will call the bound function.\n */\nChromeExOAuth.bind = function(func, obj) {\n  var newargs = Array.prototype.slice.call(arguments).slice(2);\n  return function() {\n    var combinedargs = newargs.concat(Array.prototype.slice.call(arguments));\n    func.apply(obj, combinedargs);\n  };\n};\n\n/**\n * Encodes a value according to the RFC3986 specification.\n * @param {String} val The string to encode.\n */\nChromeExOAuth.toRfc3986 = function(val){\n   return encodeURIComponent(val)\n       .replace(/\\!/g, \"%21\")\n       .replace(/\\*/g, \"%2A\")\n       .replace(/'/g, \"%27\")\n       .replace(/\\(/g, \"%28\")\n       .replace(/\\)/g, \"%29\");\n};\n\n/**\n * Decodes a string that has been encoded according to RFC3986.\n * @param {String} val The string to decode.\n */\nChromeExOAuth.fromRfc3986 = function(val){\n  var tmp = val\n      .replace(/%21/g, \"!\")\n      .replace(/%2A/g, \"*\")\n      .replace(/%27/g, \"'\")\n      .replace(/%28/g, \"(\")\n      .replace(/%29/g, \")\");\n   return decodeURIComponent(tmp);\n};\n\n/**\n * Adds a key/value parameter to the supplied URL.\n * @param {String} url An URL which may or may not contain querystring values.\n * @param {String} key A key\n * @param {String} value A value\n * @return {String} The URL with URL-encoded versions of the key and value\n *     appended, prefixing them with \"&\" or \"?\" as needed.\n */\nChromeExOAuth.addURLParam = function(url, key, value) {\n  var sep = (url.indexOf('?') >= 0) ? \"&\" : \"?\";\n  return url + sep +\n         ChromeExOAuth.toRfc3986(key) + \"=\" + ChromeExOAuth.toRfc3986(value);\n};\n\n/**\n * Stores an OAuth token for the configured scope.\n * @param {String} token The token to store.\n */\nChromeExOAuth.prototype.setToken = function(token) {\n  localStorage[this.key_token + encodeURI(this.oauth_scope)] = token;\n};\n\n/**\n * Retrieves any stored token for the configured scope.\n * @return {String} The stored token.\n */\nChromeExOAuth.prototype.getToken = function() {\n  return localStorage[this.key_token + encodeURI(this.oauth_scope)];\n};\n\n/**\n * Stores an OAuth token secret for the configured scope.\n * @param {String} secret The secret to store.\n */\nChromeExOAuth.prototype.setTokenSecret = function(secret) {\n  localStorage[this.key_token_secret + encodeURI(this.oauth_scope)] = secret;\n};\n\n/**\n * Retrieves any stored secret for the configured scope.\n * @return {String} The stored secret.\n */\nChromeExOAuth.prototype.getTokenSecret = function() {\n  return localStorage[this.key_token_secret + encodeURI(this.oauth_scope)];\n};\n\n/**\n * Starts an OAuth authorization flow for the current page.  If a token exists,\n * no redirect is needed and the supplied callback is called immediately.\n * If this method detects that a redirect has finished, it grabs the\n * appropriate OAuth parameters from the URL and attempts to retrieve an\n * access token.  If no token exists and no redirect has happened, then\n * an access token is requested and the page is ultimately redirected.\n * @param {Function} callback The function to call once the flow has finished.\n *     This callback will be passed the following arguments:\n *         token {String} The OAuth access token.\n *         secret {String} The OAuth access token secret.\n */\nChromeExOAuth.prototype.initOAuthFlow = function(callback) {\n  if (!this.hasToken()) {\n    var params = ChromeExOAuth.getQueryStringParams();\n    if (params['chromeexoauthcallback'] == 'true') {\n      var oauth_token = params['oauth_token'];\n      var oauth_verifier = params['oauth_verifier']\n      this.getAccessToken(oauth_token, oauth_verifier, callback);\n    } else {\n      var request_params = {\n        'url_callback_param' : 'chromeexoauthcallback'\n      }\n      this.getRequestToken(function(url) {\n        window.location.href = url;\n      }, request_params);\n    }\n  } else {\n    callback(this.getToken(), this.getTokenSecret());\n  }\n};\n\n/**\n * Requests an OAuth request token.\n * @param {Function} callback Function to call once the authorize URL is\n *     calculated.  This callback will be passed the following arguments:\n *         url {String} The URL the user must be redirected to in order to\n *             approve the token.\n * @param {Object} opt_args Optional arguments.  The following parameters\n *     are accepted:\n *         \"url_callback\" {String} The URL the OAuth provider will redirect to.\n *         \"url_callback_param\" {String} A parameter to include in the callback\n *             URL in order to indicate to this library that a redirect has\n *             taken place.\n */\nChromeExOAuth.prototype.getRequestToken = function(callback, opt_args) {\n  if (typeof callback !== \"function\") {\n    throw new Error(\"Specified callback must be a function.\");\n  }\n  var url = opt_args && opt_args['url_callback'] ||\n            window && window.top && window.top.location &&\n            window.top.location.href;\n\n  var url_param = opt_args && opt_args['url_callback_param'] ||\n                  \"chromeexoauthcallback\";\n  var url_callback = ChromeExOAuth.addURLParam(url, url_param, \"true\");\n\n  var result = OAuthSimple().sign({\n    path : this.url_request_token,\n    parameters: {\n      \"xoauth_displayname\" : this.app_name,\n      \"scope\" : this.oauth_scope,\n      \"oauth_callback\" : url_callback\n    },\n    signatures: {\n      consumer_key : this.consumer_key,\n      shared_secret : this.consumer_secret\n    }\n  });\n  var onToken = ChromeExOAuth.bind(this.onRequestToken, this, callback);\n  ChromeExOAuth.sendRequest(\"GET\", result.signed_url, null, null, onToken);\n};\n\n/**\n * Called when a request token has been returned.  Stores the request token\n * secret for later use and sends the authorization url to the supplied\n * callback (for redirecting the user).\n * @param {Function} callback Function to call once the authorize URL is\n *     calculated.  This callback will be passed the following arguments:\n *         url {String} The URL the user must be redirected to in order to\n *             approve the token.\n * @param {XMLHttpRequest} xhr The XMLHttpRequest object used to fetch the\n *     request token.\n */\nChromeExOAuth.prototype.onRequestToken = function(callback, xhr) {\n  if (xhr.readyState == 4) {\n    if (xhr.status == 200) {\n      var params = ChromeExOAuth.formDecode(xhr.responseText);\n      var token = params['oauth_token'];\n      this.setTokenSecret(params['oauth_token_secret']);\n      var url = ChromeExOAuth.addURLParam(this.url_auth_token,\n                                          \"oauth_token\", token);\n      for (var key in this.auth_params) {\n        if (this.auth_params.hasOwnProperty(key)) {\n          url = ChromeExOAuth.addURLParam(url, key, this.auth_params[key]);\n        }\n      }\n      callback(url);\n    } else {\n      throw new Error(\"Fetching request token failed. Status \" + xhr.status);\n    }\n  }\n};\n\n/**\n * Requests an OAuth access token.\n * @param {String} oauth_token The OAuth request token.\n * @param {String} oauth_verifier The OAuth token verifier.\n * @param {Function} callback The function to call once the token is obtained.\n *     This callback will be passed the following arguments:\n *         token {String} The OAuth access token.\n *         secret {String} The OAuth access token secret.\n */\nChromeExOAuth.prototype.getAccessToken = function(oauth_token, oauth_verifier,\n                                                  callback) {\n  if (typeof callback !== \"function\") {\n    throw new Error(\"Specified callback must be a function.\");\n  }\n  var bg = chrome.extension.getBackgroundPage();\n  if (bg.chromeExOAuthRequestingAccess == false) {\n    bg.chromeExOAuthRequestingAccess = true;\n\n    var result = OAuthSimple().sign({\n      path : this.url_access_token,\n      parameters: {\n        \"oauth_token\" : oauth_token,\n        \"oauth_verifier\" : oauth_verifier\n      },\n      signatures: {\n        consumer_key : this.consumer_key,\n        shared_secret : this.consumer_secret,\n        oauth_secret : this.getTokenSecret(this.oauth_scope)\n      }\n    });\n\n    var onToken = ChromeExOAuth.bind(this.onAccessToken, this, callback);\n    ChromeExOAuth.sendRequest(\"GET\", result.signed_url, null, null, onToken);\n  }\n};\n\n/**\n * Called when an access token has been returned.  Stores the access token and\n * access token secret for later use and sends them to the supplied callback.\n * @param {Function} callback The function to call once the token is obtained.\n *     This callback will be passed the following arguments:\n *         token {String} The OAuth access token.\n *         secret {String} The OAuth access token secret.\n * @param {XMLHttpRequest} xhr The XMLHttpRequest object used to fetch the\n *     access token.\n */\nChromeExOAuth.prototype.onAccessToken = function(callback, xhr) {\n  if (xhr.readyState == 4) {\n    var bg = chrome.extension.getBackgroundPage();\n    if (xhr.status == 200) {\n      var params = ChromeExOAuth.formDecode(xhr.responseText);\n      var token = params[\"oauth_token\"];\n      var secret = params[\"oauth_token_secret\"];\n      this.setToken(token);\n      this.setTokenSecret(secret);\n      bg.chromeExOAuthRequestingAccess = false;\n      callback(token, secret);\n    } else {\n      bg.chromeExOAuthRequestingAccess = false;\n      throw new Error(\"Fetching access token failed with status \" + xhr.status);\n    }\n  }\n};\n\n"
  },
  {
    "path": "_archive/mv2/extensions/gdocs/chrome_ex_oauthsimple.js",
    "content": "/* OAuthSimple\n  * A simpler version of OAuth\n  *\n  * author:     jr conlin\n  * mail:       src@anticipatr.com\n  * copyright:  unitedHeroes.net\n  * version:    1.0\n  * url:        http://unitedHeroes.net/OAuthSimple\n  *\n  * Copyright (c) 2009, unitedHeroes.net\n  * All rights reserved.\n  *\n  * Redistribution and use in source and binary forms, with or without\n  * modification, are permitted provided that the following conditions are met:\n  *     * Redistributions of source code must retain the above copyright\n  *       notice, this list of conditions and the following disclaimer.\n  *     * Redistributions in binary form must reproduce the above copyright\n  *       notice, this list of conditions and the following disclaimer in the\n  *       documentation and/or other materials provided with the distribution.\n  *     * Neither the name of the unitedHeroes.net nor the\n  *       names of its contributors may be used to endorse or promote products\n  *       derived from this software without specific prior written permission.\n  *\n  * THIS SOFTWARE IS PROVIDED BY UNITEDHEROES.NET ''AS IS'' AND ANY\n  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  * DISCLAIMED. IN NO EVENT SHALL UNITEDHEROES.NET BE LIABLE FOR ANY\n  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\nvar OAuthSimple;\n\nif (OAuthSimple === undefined)\n{\n    /* Simple OAuth\n     *\n     * This class only builds the OAuth elements, it does not do the actual\n     * transmission or reception of the tokens. It does not validate elements\n     * of the token. It is for client use only.\n     *\n     * api_key is the API key, also known as the OAuth consumer key\n     * shared_secret is the shared secret (duh).\n     *\n     * Both the api_key and shared_secret are generally provided by the site\n     * offering OAuth services. You need to specify them at object creation\n     * because nobody <explative>ing uses OAuth without that minimal set of\n     * signatures.\n     *\n     * If you want to use the higher order security that comes from the\n     * OAuth token (sorry, I don't provide the functions to fetch that because\n     * sites aren't horribly consistent about how they offer that), you need to\n     * pass those in either with .setTokensAndSecrets() or as an argument to the\n     * .sign() or .getHeaderString() functions.\n     *\n     * Example:\n       <code>\n        var oauthObject = OAuthSimple().sign({path:'http://example.com/rest/',\n                                              parameters: 'foo=bar&gorp=banana',\n                                              signatures:{\n                                                api_key:'12345abcd',\n                                                shared_secret:'xyz-5309'\n                                             }});\n        document.getElementById('someLink').href=oauthObject.signed_url;\n       </code>\n     *\n     * that will sign as a \"GET\" using \"SHA1-MAC\" the url. If you need more than\n     * that, read on, McDuff.\n     */\n\n    /** OAuthSimple creator\n     *\n     * Create an instance of OAuthSimple\n     *\n     * @param api_key {string}       The API Key (sometimes referred to as the consumer key) This value is usually supplied by the site you wish to use.\n     * @param shared_secret (string) The shared secret. This value is also usually provided by the site you wish to use.\n     */\n    OAuthSimple = function (consumer_key,shared_secret)\n    {\n/*        if (api_key == undefined)\n            throw(\"Missing argument: api_key (oauth_consumer_key) for OAuthSimple. This is usually provided by the hosting site.\");\n        if (shared_secret == undefined)\n            throw(\"Missing argument: shared_secret (shared secret) for OAuthSimple. This is usually provided by the hosting site.\");\n*/      this._secrets={};\n        this._parameters={};\n\n        // General configuration options.\n        if (consumer_key !== undefined) {\n            this._secrets['consumer_key'] = consumer_key;\n            }\n        if (shared_secret !== undefined) {\n            this._secrets['shared_secret'] = shared_secret;\n            }\n        this._default_signature_method= \"HMAC-SHA1\";\n        this._action = \"GET\";\n        this._nonce_chars = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\n\n        this.reset = function() {\n            this._parameters={};\n            this._path=undefined;\n            return this;\n        };\n\n        /** set the parameters either from a hash or a string\n         *\n         * @param {string,object} List of parameters for the call, this can either be a URI string (e.g. \"foo=bar&gorp=banana\" or an object/hash)\n         */\n        this.setParameters = function (parameters) {\n            if (parameters === undefined) {\n                parameters = {};\n                }\n            if (typeof(parameters) == 'string') {\n                parameters=this._parseParameterString(parameters);\n                }\n            this._parameters = parameters;\n            if (this._parameters['oauth_nonce'] === undefined) {\n                this._getNonce();\n                }\n            if (this._parameters['oauth_timestamp'] === undefined) {\n                this._getTimestamp();\n                }\n            if (this._parameters['oauth_method'] === undefined) {\n                this.setSignatureMethod();\n                }\n            if (this._parameters['oauth_consumer_key'] === undefined) {\n                this._getApiKey();\n                }\n            if(this._parameters['oauth_token'] === undefined) {\n                this._getAccessToken();\n                }\n\n            return this;\n        };\n\n        /** convienence method for setParameters\n         *\n         * @param parameters {string,object} See .setParameters\n         */\n        this.setQueryString = function (parameters) {\n            return this.setParameters(parameters);\n        };\n\n        /** Set the target URL (does not include the parameters)\n         *\n         * @param path {string} the fully qualified URI (excluding query arguments) (e.g \"http://example.org/foo\")\n         */\n        this.setURL = function (path) {\n            if (path == '') {\n                throw ('No path specified for OAuthSimple.setURL');\n                }\n            this._path = path;\n            return this;\n        };\n\n        /** convienence method for setURL\n         *\n         * @param path {string} see .setURL\n         */\n        this.setPath = function(path){\n            return this.setURL(path);\n        };\n\n        /** set the \"action\" for the url, (e.g. GET,POST, DELETE, etc.)\n         *\n         * @param action {string} HTTP Action word.\n         */\n        this.setAction = function(action) {\n            if (action === undefined) {\n                action=\"GET\";\n                }\n            action = action.toUpperCase();\n            if (action.match('[^A-Z]')) {\n                throw ('Invalid action specified for OAuthSimple.setAction');\n                }\n            this._action = action;\n            return this;\n        };\n\n        /** set the signatures (as well as validate the ones you have)\n         *\n         * @param signatures {object} object/hash of the token/signature pairs {api_key:, shared_secret:, oauth_token: oauth_secret:}\n         */\n        this.setTokensAndSecrets = function(signatures) {\n            if (signatures)\n            {\n                for (var i in signatures) {\n                    this._secrets[i] = signatures[i];\n                    }\n            }\n            // Aliases\n            if (this._secrets['api_key']) {\n                this._secrets.consumer_key = this._secrets.api_key;\n                }\n            if (this._secrets['access_token']) {\n                this._secrets.oauth_token = this._secrets.access_token;\n                }\n            if (this._secrets['access_secret']) {\n                this._secrets.oauth_secret = this._secrets.access_secret;\n                }\n            // Gauntlet\n            if (this._secrets.consumer_key === undefined) {\n                throw('Missing required consumer_key in OAuthSimple.setTokensAndSecrets');\n                }\n            if (this._secrets.shared_secret === undefined) {\n                throw('Missing required shared_secret in OAuthSimple.setTokensAndSecrets');\n                }\n            if ((this._secrets.oauth_token !== undefined) && (this._secrets.oauth_secret === undefined)) {\n                throw('Missing oauth_secret for supplied oauth_token in OAuthSimple.setTokensAndSecrets');\n                }\n            return this;\n        };\n\n        /** set the signature method (currently only Plaintext or SHA-MAC1)\n         *\n         * @param method {string} Method of signing the transaction (only PLAINTEXT and SHA-MAC1 allowed for now)\n         */\n        this.setSignatureMethod = function(method) {\n            if (method === undefined) {\n                method = this._default_signature_method;\n                }\n            //TODO: accept things other than PlainText or SHA-MAC1\n            if (method.toUpperCase().match(/(PLAINTEXT|HMAC-SHA1)/) === undefined) {\n                throw ('Unknown signing method specified for OAuthSimple.setSignatureMethod');\n                }\n            this._parameters['oauth_signature_method']= method.toUpperCase();\n            return this;\n        };\n\n        /** sign the request\n         *\n         * note: all arguments are optional, provided you've set them using the\n         * other helper functions.\n         *\n         * @param args {object} hash of arguments for the call\n         *                   {action:, path:, parameters:, method:, signatures:}\n         *                   all arguments are optional.\n         */\n        this.sign = function (args) {\n            if (args === undefined) {\n                args = {};\n                }\n            // Set any given parameters\n            if(args['action'] !== undefined) {\n                this.setAction(args['action']);\n                }\n            if (args['path'] !== undefined) {\n                this.setPath(args['path']);\n                }\n            if (args['method'] !== undefined) {\n                this.setSignatureMethod(args['method']);\n                }\n            this.setTokensAndSecrets(args['signatures']);\n            if (args['parameters'] !== undefined){\n            this.setParameters(args['parameters']);\n            }\n            // check the parameters\n            var normParams = this._normalizedParameters();\n            this._parameters['oauth_signature']=this._generateSignature(normParams);\n            return {\n                parameters: this._parameters,\n                signature: this._oauthEscape(this._parameters['oauth_signature']),\n                signed_url: this._path + '?' + this._normalizedParameters(),\n                header: this.getHeaderString()\n            };\n        };\n\n        /** Return a formatted \"header\" string\n         *\n         * NOTE: This doesn't set the \"Authorization: \" prefix, which is required.\n         * I don't set it because various set header functions prefer different\n         * ways to do that.\n         *\n         * @param args {object} see .sign\n         */\n        this.getHeaderString = function(args) {\n            if (this._parameters['oauth_signature'] === undefined) {\n                this.sign(args);\n                }\n\n            var result = 'OAuth ';\n            for (var pName in this._parameters)\n            {\n                if (!pName.match(/^oauth/)) {\n                    continue;\n                    }\n                if ((this._parameters[pName]) instanceof Array)\n                {\n                    var pLength = this._parameters[pName].length;\n                    for (var j=0;j<pLength;j++)\n                    {\n                        result += pName +'=\"'+this._oauthEscape(this._parameters[pName][j])+'\" ';\n                    }\n                }\n                else\n                {\n                    result += pName + '=\"'+this._oauthEscape(this._parameters[pName])+'\" ';\n                }\n            }\n            return result;\n        };\n\n        // Start Private Methods.\n\n        /** convert the parameter string into a hash of objects.\n         *\n         */\n        this._parseParameterString = function(paramString){\n            var elements = paramString.split('&');\n            var result={};\n            for(var element=elements.shift();element;element=elements.shift())\n            {\n                var keyToken=element.split('=');\n                var value='';\n                if (keyToken[1]) {\n                    value=decodeURIComponent(keyToken[1]);\n                    }\n                if(result[keyToken[0]]){\n                    if (!(result[keyToken[0]] instanceof Array))\n                    {\n                        result[keyToken[0]] = Array(result[keyToken[0]],value);\n                    }\n                    else\n                    {\n                        result[keyToken[0]].push(value);\n                    }\n                }\n                else\n                {\n                    result[keyToken[0]]=value;\n                }\n            }\n            return result;\n        };\n\n        this._oauthEscape = function(string) {\n            if (string === undefined) {\n                return \"\";\n                }\n            if (string instanceof Array)\n            {\n                throw('Array passed to _oauthEscape');\n            }\n            return encodeURIComponent(string).replace(/\\!/g, \"%21\").\n            replace(/\\*/g, \"%2A\").\n            replace(/'/g, \"%27\").\n            replace(/\\(/g, \"%28\").\n            replace(/\\)/g, \"%29\");\n        };\n\n        this._getNonce = function (length) {\n            if (length === undefined) {\n                length=5;\n                }\n            var result = \"\";\n            var cLength = this._nonce_chars.length;\n            for (var i = 0; i < length;i++) {\n                var rnum = Math.floor(Math.random() *cLength);\n                result += this._nonce_chars.substring(rnum,rnum+1);\n            }\n            this._parameters['oauth_nonce']=result;\n            return result;\n        };\n\n        this._getApiKey = function() {\n            if (this._secrets.consumer_key === undefined) {\n                throw('No consumer_key set for OAuthSimple.');\n                }\n            this._parameters['oauth_consumer_key']=this._secrets.consumer_key;\n            return this._parameters.oauth_consumer_key;\n        };\n\n        this._getAccessToken = function() {\n            if (this._secrets['oauth_secret'] === undefined) {\n                return '';\n                }\n            if (this._secrets['oauth_token'] === undefined) {\n                throw('No oauth_token (access_token) set for OAuthSimple.');\n                }\n            this._parameters['oauth_token'] = this._secrets.oauth_token;\n            return this._parameters.oauth_token;\n        };\n\n        this._getTimestamp = function() {\n            var d = new Date();\n            var ts = Math.floor(d.getTime()/1000);\n            this._parameters['oauth_timestamp'] = ts;\n            return ts;\n        };\n\n        this.b64_hmac_sha1 = function(k,d,_p,_z){\n        // heavily optimized and compressed version of http://pajhome.org.uk/crypt/md5/sha1.js\n        // _p = b64pad, _z = character size; not used here but I left them available just in case\n        if(!_p){_p='=';}if(!_z){_z=8;}function _f(t,b,c,d){if(t<20){return(b&c)|((~b)&d);}if(t<40){return b^c^d;}if(t<60){return(b&c)|(b&d)|(c&d);}return b^c^d;}function _k(t){return(t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514;}function _s(x,y){var l=(x&0xFFFF)+(y&0xFFFF),m=(x>>16)+(y>>16)+(l>>16);return(m<<16)|(l&0xFFFF);}function _r(n,c){return(n<<c)|(n>>>(32-c));}function _c(x,l){x[l>>5]|=0x80<<(24-l%32);x[((l+64>>9)<<4)+15]=l;var w=[80],a=1732584193,b=-271733879,c=-1732584194,d=271733878,e=-1009589776;for(var i=0;i<x.length;i+=16){var o=a,p=b,q=c,r=d,s=e;for(var j=0;j<80;j++){if(j<16){w[j]=x[i+j];}else{w[j]=_r(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);}var t=_s(_s(_r(a,5),_f(j,b,c,d)),_s(_s(e,w[j]),_k(j)));e=d;d=c;c=_r(b,30);b=a;a=t;}a=_s(a,o);b=_s(b,p);c=_s(c,q);d=_s(d,r);e=_s(e,s);}return[a,b,c,d,e];}function _b(s){var b=[],m=(1<<_z)-1;for(var i=0;i<s.length*_z;i+=_z){b[i>>5]|=(s.charCodeAt(i/8)&m)<<(32-_z-i%32);}return b;}function _h(k,d){var b=_b(k);if(b.length>16){b=_c(b,k.length*_z);}var p=[16],o=[16];for(var i=0;i<16;i++){p[i]=b[i]^0x36363636;o[i]=b[i]^0x5C5C5C5C;}var h=_c(p.concat(_b(d)),512+d.length*_z);return _c(o.concat(h),512+160);}function _n(b){var t=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",s='';for(var i=0;i<b.length*4;i+=3){var r=(((b[i>>2]>>8*(3-i%4))&0xFF)<<16)|(((b[i+1>>2]>>8*(3-(i+1)%4))&0xFF)<<8)|((b[i+2>>2]>>8*(3-(i+2)%4))&0xFF);for(var j=0;j<4;j++){if(i*8+j*6>b.length*32){s+=_p;}else{s+=t.charAt((r>>6*(3-j))&0x3F);}}}return s;}function _x(k,d){return _n(_h(k,d));}return _x(k,d);\n        }\n\n\n        this._normalizedParameters = function() {\n            var elements = new Array();\n            var paramNames = [];\n            var ra =0;\n            for (var paramName in this._parameters)\n            {\n                if (ra++ > 1000) {\n                    throw('runaway 1');\n                    }\n                paramNames.unshift(paramName);\n            }\n            paramNames = paramNames.sort();\n            pLen = paramNames.length;\n            for (var i=0;i<pLen; i++)\n            {\n                paramName=paramNames[i];\n                //skip secrets.\n                if (paramName.match(/\\w+_secret/)) {\n                    continue;\n                    }\n                if (this._parameters[paramName] instanceof Array)\n                {\n                    var sorted = this._parameters[paramName].sort();\n                    var spLen = sorted.length;\n                    for (var j = 0;j<spLen;j++){\n                        if (ra++ > 1000) {\n                            throw('runaway 1');\n                            }\n                        elements.push(this._oauthEscape(paramName) + '=' +\n                                  this._oauthEscape(sorted[j]));\n                    }\n                    continue;\n                }\n                elements.push(this._oauthEscape(paramName) + '=' +\n                              this._oauthEscape(this._parameters[paramName]));\n            }\n            return elements.join('&');\n        };\n\n        this._generateSignature = function() {\n\n            var secretKey = this._oauthEscape(this._secrets.shared_secret)+'&'+\n                this._oauthEscape(this._secrets.oauth_secret);\n            if (this._parameters['oauth_signature_method'] == 'PLAINTEXT')\n            {\n                return secretKey;\n            }\n            if (this._parameters['oauth_signature_method'] == 'HMAC-SHA1')\n            {\n                var sigString = this._oauthEscape(this._action)+'&'+this._oauthEscape(this._path)+'&'+this._oauthEscape(this._normalizedParameters());\n                return this.b64_hmac_sha1(secretKey,sigString);\n            }\n            return null;\n        };\n\n    return this;\n    };\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/gdocs/manifest.json",
    "content": "{\n  \"name\": \"Google Document List Viewer\",\n  \"version\": \"1.0.2\",\n  \"icons\": {\n    \"48\": \"img/docs_spreadsheets-48.gif\",\n    \"128\": \"img/docs_spreadsheets-128.gif\"\n  },\n  \"description\": \"Demonstrates how to use OAuth to connect the Google Documents List Data API.\",\n  \"background\": {\n    \"page\": \"background.html\"\n  },\n  \"options_page\": \"options.html\",\n  \"browser_action\": {\n    \"default_title\": \"List your Google Docs\",\n    \"default_icon\": \"img/docs_spreadsheets-32.gif\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"permissions\": [\n    \"tabs\",\n    \"https://docs.google.com/feeds/*\",\n    \"https://www.google.com/accounts/OAuthGetRequestToken\",\n    \"https://www.google.com/accounts/OAuthAuthorizeToken\",\n    \"https://www.google.com/accounts/OAuthGetAccessToken\"\n  ]\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/gdocs/options.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n *\n * Author: Eric Bidelman <ericbidelman@chromium.org>\n-->\n<html>\n  <head>\n    <title>Options</title>\n    <script type=\"text/javascript\" src=\"js/jquery-1.4.1.min.js\"></script>\n  </head>\n  <body onload=\"initUI();\">\n    <p><button id=\"revoke\" onclick=\"logout();\">Revoke your OAuth token</button></p>\n    <p>Refresh rate (seconds): <input id=\"refresh_rate\" value=\"300\"></p>\n    <script type=\"text/javascript\">\n      var bgPage = chrome.extension.getBackgroundPage();\n\n      $('#refresh_rate').change(function() {\n        localStorage.refreshRate = $(this).val();\n        bgPage.refreshRate = localStorage.refreshRate;\n        bgPage.pollIntervalMin =  bgPage.refreshRate * 1000;\n      });\n\n      function logout() {\n        bgPage.logout();\n        $('#revoke').get(0).disabled = true;\n      }\n\n      function initUI() {\n        if (!bgPage.oauth.hasToken()) {\n          $('#revoke').get(0).disabled = true;\n        }\n\n        if (localStorage.refreshRate) {\n          $('#refresh_rate').val(localStorage.refreshRate);\n        } else {\n           $('#refresh_rate').val(bgPage.refreshRate);\n        }\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/gdocs/popup.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n *\n * Author: Eric Bidelman <ericbidelman@chromium.org>\n-->\n<html>\n<head>\n<title>Your Google Documents List</title>\n<script type=\"text/javascript\" src=\"js/jquery-1.4.1.min.js\"></script>\n<style type=\"text/css\">\nbody {\n  font: 12px 'Myriad Pro', 'Tw Cen MT', Arial, Verdana, sans-serif;\n  color: #666666;\n  overflow-x: hidden;\n}\nul {\n  padding: 0;\n  list-style: none;\n}\nli {\n  clear: both;\n  padding: 2px 0;\n}\nli div img {\n  margin: 0 5px;\n  vertical-align: middle;\n}\nli div {\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  overflow: hidden;\n  width: 250px;\n  float: left;\n  padding: 2px 0;\n}\nli span {\n  margin-left: 5px;\n}\nli:hover {\n  background-color: #fffccc;\n}\na {\n color: #4E7DC2;\n text-decoration: none;\n}\na:hover {\n  color: #880000;\n  text-decoration: underline;\n}\n#butter {\n  color: #fff;\n  background-color: #000033;\n  padding: 5px 20px;\n  border-radius: 15px;\n  width: auto;\n  text-align: center;\n  float: right;\n  display: none;\n}\n#butter.error {\n  background-color: red;\n}\n#new_doc_container {\n  display: none;\n}\n#new_doc_container input[type='text'],textarea {\n  width: 100%;\n}\n#output {\n  width: 375px;\n  clear: both;\n}\n[contenteditable]:hover {\n  outline: 1px dotted #666;\n}\n.star {\n  margin-top: 1px;\n  margin-right: 3px;\n  width: 16px;\n  height: 16px;\n  background: no-repeat url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAGYktHRAA3ADcAN3PbifMAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfZAwkAAh4LdI38AAAC00lEQVQoz42SS2hUZxzFz/d99zF35s7EScxEEzW1mkSlVkQJCNWSakDdxY2P0lKkSMi6G1uqbcVXF12WiiK4EMQixgeoGCMalWZRTYlG0kwNtebtzGQmmZk78937/7sQREWhB87m8DurcwTeo0Pn8xuFEN+A+djetkjnuxj5rvDbUxOLzCDTPkdOtlqU/nrvqYnG/13OZaY+rq3AZ9tb5qkP5qpPZtJTa99m2g92wXg96DjcLT2t6l2z8GVtZTwed23UVspYLFTcsfunWw8UFwaP799CAPDbd5sgdu+7XJPLl+LEosIJmYtjbqh5VWPN5zs3NyViEQszBY1z3UPPe/tHz87Olu4WvPKwEjzthu204TPtW7E0sbnCtSKGlOH51VFn9fIaGYtY0D5x1DHFhjULqlzH2DM6mftC+1TMzpYK/41nrxmaKJxIROt2tS6z41EbAMDMKJUDBlh4RFyfcMWH8xsNANFUzouevTGoh8enw2rZhp0DQ8/S1cxY2rQwbkopUNLExCwCAoghtE9MxMIrB+jsSXrXep9c1MQH1EDPmXTD+h39j5+m52nCwhX1VQ4xCx0wiF8aEIIZONeTzJ6/k7xS8unHS0faBiQAXD7clswHfOh638jIk7EclBQgYjADRIClJEZTedx6ODaeKuifrxzd9uiNnYvSnpa2FTKVhB8whABMQ0IIQAcMQwpIywp5ys69cZJP93eBlJEIlBmujNpQUiAICE8nZlDWAQwlMMe1QYbpBMqobvmhSwB4eZIcpAw7aklt3InGXQt9w2k+/cezzMBUIdNQ5VTsaq6ram6YK+oqHXcoVVwyVaZeAL4BAFoaUlpqdcRS9i9Xk8ULj1NDQUAnMvnyxWyJW+9f+qd9a1NmuQIsO2St0r7/+6uyNEzKBfjr6r/ebSG8P0tanHz4/fq/W37tx82OlSc+OnCvu3Mw+xUz1hHLPtuyfAB4AUJFSguX3LKbAAAAAElFTkSuQmCC) !important;\n}\n.star.selected {\n  background: no-repeat url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAGYktHRAA3ADcAN3PbifMAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfZAwkAAB45Qu9+AAAC1ElEQVQoz42SWUhUYRzFz/+7986dVTPT0SzNFnHBJZHCKGmTAisJgooIIrJ87CGIHopKWp/qoYdAJIIg6qEUy/aiSMoWmpbJyjJCs3SacRZnrvfe7/t6KioKOo+H3+HA4RD+oYMXxpYQ0Q5IeXLXas/FvzHsb+b2tvH8bPaiudrXUZ+rPN2yvc0s+u+wiPdVZHi1xfVzJynZE9h8Huur+ZNpPnAD9KvRdKCbxU13QVXewJFV8+SakrICet8bkO33HZ09AxU7VRF7c2b/XPGDp817Ov2huJahwEr3umRh7gRjTlWRb8O6ZWnZ5ABk8j3a75ih7qDn3HAi434s5eznkkYz3fGwakuxp640vFx1ZXocCneXT7FcFUWSkcYgxyOSVKKlVR8y/W5j6/PB/I0py5ESppV8OZR/VbWEcM+cnMhbscivK66JALIAbkCaYUkiSpKPSG+aoNqaqFpb0+0TCe678niKFRjKcyvFdeuDPf1pWSolZ5ZOTWokDEhrVJIcJfBhEB8haX+TJMZJWsDFx8XGqQcLOkzBWpTgvbPhWXVrXwQ+IkcR8anlBSEXiSiBjwAiBPAICAYB47jwqCh6+kF1V8pW9nUeXhlkAHDpUGNfwtYOXg5og4lwH4BBgA8BPAxIAwDHWFzieu/0L1+T3qNXjzS8AgD1x+wp5hpVHAmnShGAK4C0AMYBLgDBoZENRYPTYI7YbydZuPcahMqyDdLdTpcFkA0IA1YsCdgGQDYcugmTaS6uKFlL9nXRz+aQ8LIsT3RGhf+TD7pAZMiUrY+qI7cHSiPzct6mN1V1Z/pzTCqb9MnbH0uf8XEs9yEAWwUAi2mMaTR7muezfu5eYer4s8XvmLRbB+ITO2K2Xt81WNm8teRmSa5z2OHUeaWVUs//DOsaF9/s9MCx3oa7BDxJWHpbcPect40nL6F9W0NraUvPrROvl20CUGsJ5VmaM2UDwHchqUbp2jdIoAAAAABJRU5ErkJggg==) !important;\n}\n</style>\n</head>\n<body>\n\n<div style=\"height:15px;\">\n  <div style=\"float:left;\">\n    <a href=\"javascript:void(0);\" onclick=\"gdocs.refreshDocs();return false;\">Refresh list</a>,\n    <a href=\"javascript:void(0);\" onclick=\"$('#new_doc_container').toggle();return false;\">New Document</a>\n  </div>\n  <div id=\"butter\">Fetching your docs</div>\n</div>\n<div id=\"new_doc_container\">\n  Create a: <select id=\"doc_type\">\n    <option value=\"document\">document</option>\n    <option value=\"presentation\">presentation</option>\n    <option value=\"spreadsheet\">spreadsheet</option>\n  </select>\n  <input type=\"text\" id=\"doc_title\" placeholder=\"Enter a title\"><br>\n  <textarea id=\"doc_content\" placeholder=\"Enter document content\"></textarea>\n  Star it? <input type=\"checkbox\" id=\"doc_starred\">\n  <button onclick=\"gdocs.createDoc();\" style=\"float:right;\">Create new doc</button>\n</div>\n<div id=\"output\"></div>\n\n<script type=\"text/javascript\">\n// Protected namespaces.\nvar util = {};\nvar gdocs = {};\n\nvar bgPage = chrome.extension.getBackgroundPage();\nvar pollIntervalMax = 1000 * 60 * 60;  // 1 hour\nvar requestFailureCount = 0;  // used for exponential backoff\nvar requestTimeout = 1000 * 2;  // 5 seconds\n\nvar DEFAULT_MIMETYPES = {\n  'atom': 'application/atom+xml',\n  'document': 'text/plain',\n  'spreadsheet': 'text/csv',\n  'presentation': 'text/plain',\n  'pdf': 'application/pdf'\n};\n\n// Persistent click handler for star icons.\n$('#doc_type').change(function() {\n  if ($(this).val() === 'presentation') {\n    $('#doc_content').attr('disabled', 'true')\n                     .attr('placeholder', 'N/A for presentations');\n  } else {\n    $('#doc_content').removeAttr('disabled')\n                     .attr('placeholder', 'Enter document content');\n  }\n});\n\n\n// Persistent click handler for changing the title of a document.\n$('[contenteditable=\"true\"]').live('blur', function(index) {\n  var index = $(this).parent().parent().attr('data-index');\n\n  // Only make the XHR if the user chose a new title.\n  if ($(this).text() != bgPage.docs[index].title) {\n    bgPage.docs[index].title = $(this).text();\n    gdocs.updateDoc(bgPage.docs[index]);\n  }\n});\n\n// Persistent click handler for star icons.\n$('.star').live('click', function() {\n  $(this).toggleClass('selected');\n\n  var index = $(this).parent().attr('data-index');\n  bgPage.docs[index].starred = $(this).hasClass('selected');\n  gdocs.updateDoc(bgPage.docs[index]);\n});\n\n/**\n * Class to compartmentalize properties of a Google document.\n * @param {Object} entry A JSON representation of a DocList atom entry.\n * @constructor\n */\ngdocs.GoogleDoc = function(entry) {\n  this.entry = entry;\n  this.title = entry.title.$t;\n  this.resourceId = entry.gd$resourceId.$t;\n  this.type = gdocs.getCategory(\n    entry.category, 'http://schemas.google.com/g/2005#kind');\n  this.starred = gdocs.getCategory(\n    entry.category, 'http://schemas.google.com/g/2005/labels',\n    'http://schemas.google.com/g/2005/labels#starred') ? true : false;\n  this.link = {\n    'alternate': gdocs.getLink(entry.link, 'alternate').href\n  };\n  this.contentSrc = entry.content.src;\n};\n\n/**\n * Sets up a future poll for the user's document list.\n */\nutil.scheduleRequest = function() {\n  var exponent = Math.pow(2, requestFailureCount);\n  var delay = Math.min(bgPage.pollIntervalMin * exponent,\n                       pollIntervalMax);\n  delay = Math.round(delay);\n\n  if (bgPage.oauth.hasToken()) {\n    var req = bgPage.window.setTimeout(function() {\n      gdocs.getDocumentList();\n      util.scheduleRequest();\n    }, delay);\n    bgPage.requests.push(req);\n  }\n};\n\n/**\n * Urlencodes a JSON object of key/value query parameters.\n * @param {Object} parameters Key value pairs representing URL parameters.\n * @return {string} query parameters concatenated together.\n */\nutil.stringify = function(parameters) {\n  var params = [];\n  for(var p in parameters) {\n    params.push(encodeURIComponent(p) + '=' +\n                encodeURIComponent(parameters[p]));\n  }\n  return params.join('&');\n};\n\n/**\n * Creates a JSON object of key/value pairs\n * @param {string} paramStr A string of Url query parmeters.\n *    For example: max-results=5&startindex=2&showfolders=true\n * @return {Object} The query parameters as key/value pairs.\n */\nutil.unstringify = function(paramStr) {\n  var parts = paramStr.split('&');\n\n  var params = {};\n  for (var i = 0, pair; pair = parts[i]; ++i) {\n    var param = pair.split('=');\n    params[decodeURIComponent(param[0])] = decodeURIComponent(param[1]);\n  }\n  return params;\n};\n\n/**\n * Utility for displaying a message to the user.\n * @param {string} msg The message.\n */\nutil.displayMsg = function(msg) {\n  $('#butter').removeClass('error').text(msg).show();\n};\n\n/**\n * Utility for removing any messages currently showing to the user.\n */\nutil.hideMsg = function() {\n  $('#butter').fadeOut(1500);\n};\n\n/**\n * Utility for displaying an error to the user.\n * @param {string} msg The message.\n */\nutil.displayError = function(msg) {\n  util.displayMsg(msg);\n  $('#butter').addClass('error');\n};\n\n/**\n * Returns the correct atom link corresponding to the 'rel' value passed in.\n * @param {Array<Object>} links A list of atom link objects.\n * @param {string} rel The rel value of the link to return. For example: 'next'.\n * @return {string|null} The appropriate link for the 'rel' passed in, or null\n *     if one is not found.\n */\ngdocs.getLink = function(links, rel) {\n  for (var i = 0, link; link = links[i]; ++i) {\n    if (link.rel === rel) {\n      return link;\n    }\n  }\n  return null;\n};\n\n/**\n * Returns the correct atom category corresponding to the scheme/term passed in.\n * @param {Array<Object>} categories A list of atom category objects.\n * @param {string} scheme The category's scheme to look up.\n * @param {opt_term?} An optional term value for the category to look up.\n * @return {string|null} The appropriate category, or null if one is not found.\n */\ngdocs.getCategory = function(categories, scheme, opt_term) {\n  for (var i = 0, cat; cat = categories[i]; ++i) {\n    if (opt_term) {\n      if (cat.scheme === scheme && opt_term === cat.term) {\n        return cat;\n      }\n    } else if (cat.scheme === scheme) {\n      return cat;\n    }\n  }\n  return null;\n};\n\n/**\n * A generic error handler for failed XHR requests.\n * @param {XMLHttpRequest} xhr The xhr request that failed.\n * @param {string} textStatus The server's returned status.\n */\ngdocs.handleError = function(xhr, textStatus) {\n  util.displayError('Failed to fetch docs. Please try again.');\n  ++requestFailureCount;\n};\n\n/**\n * A helper for constructing the raw Atom xml send in the body of an HTTP post.\n * @param {XMLHttpRequest} xhr The xhr request that failed.\n * @param {string} docTitle A title for the document.\n * @param {string} docType The type of document to create.\n *     (eg. 'document', 'spreadsheet', etc.)\n * @param {boolean?} opt_starred Whether the document should be starred.\n * @return {string} The Atom xml as a string.\n */\ngdocs.constructAtomXml_ = function(docTitle, docType, opt_starred) {\n  var starred = opt_starred || null;\n\n  var starCat = ['<category scheme=\"http://schemas.google.com/g/2005/labels\" ',\n                 'term=\"http://schemas.google.com/g/2005/labels#starred\" ',\n                 'label=\"starred\"/>'].join('');\n\n  var atom = [\"<?xml version='1.0' encoding='UTF-8'?>\", \n              '<entry xmlns=\"http://www.w3.org/2005/Atom\">',\n              '<category scheme=\"http://schemas.google.com/g/2005#kind\"', \n              ' term=\"http://schemas.google.com/docs/2007#', docType, '\"/>',\n              starred ? starCat : '',\n              '<title>', docTitle, '</title>',\n              '</entry>'].join('');\n  return atom;\n};\n\n/**\n * A helper for constructing the body of a mime-mutlipart HTTP request.\n * @param {string} title A title for the new document.\n * @param {string} docType The type of document to create.\n *     (eg. 'document', 'spreadsheet', etc.)\n * @param {string} body The body of the HTTP request.\n * @param {string} contentType The Content-Type of the (non-Atom) portion of the\n *     http body.\n * @param {boolean?} opt_starred Whether the document should be starred.\n * @return {string} The Atom xml as a string.\n */\ngdocs.constructContentBody_ = function(title, docType, body, contentType,\n                                       opt_starred) {\n  var body = ['--END_OF_PART\\r\\n',\n              'Content-Type: application/atom+xml;\\r\\n\\r\\n',\n              gdocs.constructAtomXml_(title, docType, opt_starred), '\\r\\n',\n              '--END_OF_PART\\r\\n',\n              'Content-Type: ', contentType, '\\r\\n\\r\\n',\n              body, '\\r\\n',\n              '--END_OF_PART--\\r\\n'].join('');\n  return body;\n};\n\n/**\n * Creates a new document in Google Docs.\n */\ngdocs.createDoc = function() {\n  var title = $.trim($('#doc_title').val());\n  if (!title) {\n    alert('Please provide a title');\n    return;\n  }\n  var content = $('#doc_content').val();\n  var starred = $('#doc_starred').is(':checked');\n  var docType = $('#doc_type').val();\n\n  util.displayMsg('Creating doc...');\n\n  var handleSuccess = function(resp, xhr) {\n    bgPage.docs.splice(0, 0, new gdocs.GoogleDoc(JSON.parse(resp).entry));\n\n    gdocs.renderDocList();\n    bgPage.setIcon({'text': bgPage.docs.length.toString()});\n\n    $('#new_doc_container').hide();\n    $('#doc_title').val('');\n    $('#doc_content').val('');\n    util.displayMsg('Document created!');\n    util.hideMsg();\n\n    requestFailureCount = 0;\n  };\n\n  var params = {\n    'method': 'POST',\n    'headers': {\n      'GData-Version': '3.0',\n      'Content-Type': 'multipart/related; boundary=END_OF_PART',\n    },\n    'parameters': {'alt': 'json'},\n    'body': gdocs.constructContentBody_(title, docType, content,\n                                        DEFAULT_MIMETYPES[docType], starred)\n  };\n\n  // Presentation can only be created from binary content. Instead, create a\n  // blank presentation.\n  if (docType === 'presentation') {\n    params['headers']['Content-Type'] = DEFAULT_MIMETYPES['atom'];\n    params['body'] = gdocs.constructAtomXml_(title, docType, starred);\n  }\n\n  bgPage.oauth.sendSignedRequest(bgPage.DOCLIST_FEED, handleSuccess, params);\n};\n\n/**\n * Updates a document's metadata (title, starred, etc.).\n * @param {gdocs.GoogleDoc} googleDocObj An object containing the document to\n *     update.\n */\ngdocs.updateDoc = function(googleDocObj) {\n  var handleSuccess = function(resp) {\n    util.displayMsg('Updated!');\n    util.hideMsg();\n    requestFailureCount = 0;\n  };\n\n  var params = {\n    'method': 'PUT',\n    'headers': {\n      'GData-Version': '3.0',\n      'Content-Type': 'application/atom+xml',\n      'If-Match': '*'\n    },\n    'body': gdocs.constructAtomXml_(googleDocObj.title, googleDocObj.type,\n                                    googleDocObj.starred)\n  };\n\n  var url = bgPage.DOCLIST_FEED + googleDocObj.resourceId;\n  bgPage.oauth.sendSignedRequest(url, handleSuccess, params);\n};\n\n/**\n * Deletes a document from the user's document list.\n * @param {integer} index An index intro the background page's docs array.\n */\ngdocs.deleteDoc = function(index) {\n  var handleSuccess = function(resp, xhr) {\n    util.displayMsg('Document trashed!');\n    util.hideMsg();\n    requestFailureCount = 0;\n    bgPage.docs.splice(index, 1);\n    bgPage.setIcon({'text': bgPage.docs.length.toString()});\n  }\n\n  var params = {\n    'method': 'DELETE',\n    'headers': {\n      'GData-Version': '3.0',\n      'If-Match': '*'\n    }\n  };\n\n  $('#output li').eq(index).fadeOut('slow');\n\n  bgPage.oauth.sendSignedRequest(\n      bgPage.DOCLIST_FEED + bgPage.docs[index].resourceId,\n      handleSuccess, params);\n};\n\n/**\n * Callback for processing the JSON feed returned by the DocList API.\n * @param {string} response The server's response.\n * @param {XMLHttpRequest} xhr The xhr request that was made.\n */\ngdocs.processDocListResults = function(response, xhr) {\n  if (xhr.status != 200) {\n    gdocs.handleError(xhr, response);\n    return;\n  } else {\n    requestFailureCount = 0;\n  }\n\n  var data = JSON.parse(response);\n\n  for (var i = 0, entry; entry = data.feed.entry[i]; ++i) {\n    bgPage.docs.push(new gdocs.GoogleDoc(entry));\n  }\n\n  var nextLink = gdocs.getLink(data.feed.link, 'next');\n  if (nextLink) {\n    gdocs.getDocumentList(nextLink.href); // Fetch next page of results.\n  } else {\n    gdocs.renderDocList();\n  }\n};\n\n/**\n * Presents the in-memory documents that were fetched from the server as HTML.\n */\ngdocs.renderDocList = function() {\n  util.hideMsg();\n\n  // Construct the iframe's HTML.\n  var html = [];\n  for (var i = 0, doc; doc = bgPage.docs[i]; ++i) {\n    // If we have an arbitrary file, use generic file icon.\n    var type = doc.type.label;\n    if (doc.type.term == 'http://schemas.google.com/docs/2007#file') {\n      type = 'file';\n    }\n\n    var starred = doc.starred ? ' selected' : '';\n    html.push(\n      '<li data-index=\"', i , '\"><div class=\"star', starred, '\"></div>',\n      '<div><img src=\"img/icons/', type, '.gif\">',\n      '<span contenteditable=\"true\" class=\"doc_title\"></span></div>',\n      '<span>[<a href=\"', doc.link['alternate'],\n      '\" target=\"_new\">view</a> | <a href=\"javascript:void(0);\" ',\n      'onclick=\"gdocs.deleteDoc(',i,\n      ');return false;\">delete</a>]','</span></li>');\n  }\n  $('#output').html('<ul>' + html.join('') + '</ul>');\n\n  // Set each span's innerText to be the doc title. We're filling this after\n  // the html has been rendered to the page prevent XSS attacks when using\n  // innerHTML.\n  $('#output li span.doc_title').each(function(i, ul) {\n    $(ul).text(bgPage.docs[i].title);\n  });\n\n  bgPage.setIcon({'text': bgPage.docs.length.toString()});\n};\n\n/**\n * Fetches the user's document list.\n * @param {string?} opt_url A url to query the doclist API with. If omitted,\n *     the main doclist feed uri is used.\n */\ngdocs.getDocumentList = function(opt_url) {\n  var url = opt_url || null;\n\n  var params = {\n    'headers': {\n      'GData-Version': '3.0'\n    }\n  };\n\n  if (!url) {\n    util.displayMsg('Fetching your docs');\n    bgPage.setIcon({'text': '...'});\n\n    bgPage.docs = []; // Clear document list. We're doing a refresh.\n\n    url = bgPage.DOCLIST_FEED;\n    params['parameters'] = {\n      'alt': 'json',\n      'showfolders': 'true'\n    };\n  } else {\n    util.displayMsg($('#butter').text() + '.');\n\n    var parts = url.split('?');\n    if (parts.length > 1) {\n      url = parts[0]; // Extract base URI. Params are passed in separately.\n      params['parameters'] = util.unstringify(parts[1]);\n    }\n  }\n\n  bgPage.oauth.sendSignedRequest(url, gdocs.processDocListResults, params);\n};\n\n/**\n * Refreshes the user's document list.\n */\ngdocs.refreshDocs = function() {\n  bgPage.clearPendingRequests();\n  gdocs.getDocumentList();\n  util.scheduleRequest();\n};\n\n\nbgPage.oauth.authorize(function() {\n  if (!bgPage.docs.length) {\n    gdocs.getDocumentList();\n  } else {\n    gdocs.renderDocList();\n  }\n  util.scheduleRequest();\n});\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/ar/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"\\u0644\\u0639\\u0631\\u0636 \\u0639\\u062f\\u062f \\u0627\\u0644\\u0631\\u0633\\u0627\\u0626\\u0644 \\u063a\\u064a\\u0631 \\u0627\\u0644\\u0645\\u0642\\u0631\\u0648\\u0621\\u0629 \\u0641\\u064a \\u0627\\u0644\\u0628\\u0631\\u064a\\u062f \\u0627\\u0644\\u0648\\u0627\\u0631\\u062f \\u0641\\u064a Google Mail. \\u0643\\u0645\\u0627 \\u064a\\u0645\\u0643\\u0646\\u0643 \\u0627\\u0644\\u0646\\u0642\\u0631 \\u0639\\u0644\\u0649 \\u0627\\u0644\\u0632\\u0631 \\u0644\\u0641\\u062a\\u062d \\u0628\\u0631\\u064a\\u062f\\u0643 \\u0627\\u0644\\u0648\\u0627\\u0631\\u062f.\"},\"gmailcheck_node_error\":{\"message\":\"\\u062e\\u0637\\u0623: \\u062a\\u0645 \\u0627\\u0633\\u062a\\u0631\\u062f\\u0627\\u062f \\u0627\\u0644\\u062e\\u0644\\u0627\\u0635\\u0629\\u060c \\u0648\\u0644\\u0643\\u0646 \\u0644\\u0645 \\u064a\\u062a\\u0645 \\u0627\\u0644\\u0639\\u062b\\u0648\\u0631 \\u0639\\u0644\\u0649 &lt;fullcount&gt; \\u0645\\u0646 \\u0627\\u0644\\u0639\\u064f\\u0642\\u062f\"},\"gmailcheck_exception\":{\"message\":\"\\u0627\\u0633\\u062a\\u062b\\u0646\\u0627\\u0621: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/bg/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google \\u041f\\u0440\\u043e\\u0432\\u0435\\u0440\\u043a\\u0430 \\u043d\\u0430 \\u043f\\u043e\\u0449\\u0430\\u0442\\u0430\"},\"gmailcheck_description\":{\"message\":\"\\u041f\\u043e\\u043a\\u0430\\u0437\\u0432\\u0430 \\u0431\\u0440\\u043e\\u044f \\u043d\\u0435\\u043f\\u0440\\u043e\\u0447\\u0435\\u0442\\u0435\\u043d\\u0438 \\u0441\\u044a\\u043e\\u0431\\u0449\\u0435\\u043d\\u0438\\u044f \\u0432\\u044a\\u0432 \\u0432\\u0445\\u043e\\u0434\\u044f\\u0449\\u0430\\u0442\\u0430 \\u0432\\u0438 \\u043f\\u043e\\u0449\\u0430 \\u0432 Google Mail. \\u041c\\u043e\\u0436\\u0435\\u0442\\u0435 \\u0441\\u044a\\u0449\\u043e \\u0434\\u0430 \\u043a\\u043b\\u0438\\u043a\\u043d\\u0435\\u0442\\u0435 \\u0432\\u044a\\u0440\\u0445\\u0443 \\u0431\\u0443\\u0442\\u043e\\u043d\\u0430, \\u0437\\u0430 \\u0434\\u0430 \\u044f \\u043e\\u0442\\u0432\\u043e\\u0440\\u0438\\u0442\\u0435.\"},\"gmailcheck_node_error\":{\"message\":\"\\u0413\\u0440\\u0435\\u0448\\u043a\\u0430: \\u0415\\u043c\\u0438\\u0441\\u0438\\u044f\\u0442\\u0430 \\u0431\\u0435 \\u0438\\u0437\\u0432\\u043b\\u0435\\u0447\\u0435\\u043d\\u0430, \\u043d\\u043e \\u043d\\u044f\\u043c\\u0430 \\u043d\\u0430\\u043c\\u0435\\u0440\\u0435\\u043d \\u0432\\u044a\\u0437\\u0435\\u043b &lt;fullcount&gt;\"},\"gmailcheck_exception\":{\"message\":\"\\u0438\\u0437\\u043a\\u043b\\u044e\\u0447\\u0435\\u043d\\u0438\\u0435: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/ca/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Verificador de Google Mail\"},\"gmailcheck_description\":{\"message\":\"Mostra el nombre de missatges no llegits que hi ha a la vostra safata d'entrada de Google Mail. Tamb\\u00e9 podeu fer clic al bot\\u00f3 per obrir la safata d'entrada.\"},\"gmailcheck_node_error\":{\"message\":\"Error: s'ha recuperat el feed, per\\u00f2 no s'ha trobat cap node &lt;fullcount&gt;\"},\"gmailcheck_exception\":{\"message\":\"excepci\\u00f3: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/cs/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Kontrola e-mailu Google\"},\"gmailcheck_description\":{\"message\":\"Zobraz\\u00ed po\\u010det nep\\u0159e\\u010dten\\u00fdch zpr\\u00e1v ve slo\\u017ece Doru\\u010den\\u00e1 po\\u0161ta slu\\u017eby Google Mail. Kliknut\\u00edm na tla\\u010d\\u00edtko tuto slo\\u017eku otev\\u0159ete.\"},\"gmailcheck_node_error\":{\"message\":\"Chyba: Zdroj byl na\\u010dten, nebyl v\\u0161ak nalezen \\u017e\\u00e1dn\\u00fd uzel &lt;fullcount&gt;.\"},\"gmailcheck_exception\":{\"message\":\"v\\u00fdjimka: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/da/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google E-mail-t\\u00e6ller\"},\"gmailcheck_description\":{\"message\":\"Viser antallet af ul\\u00e6ste meddelelser i din Google Mail-indbakke. Du kan ogs\\u00e5 klikke p\\u00e5 knappen for at \\u00e5bne din indbakke.\"},\"gmailcheck_node_error\":{\"message\":\"Fejl: Feedet blev hentet, men der blev ikke fundet nogen &lt;fullcount&gt;-node\"},\"gmailcheck_exception\":{\"message\":\"undtagelse: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/de/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail-Checker\"},\"gmailcheck_description\":{\"message\":\"Zeigt die Anzahl ungelesener Nachrichten in Ihrem Google Mail-Posteingang an. Sie k\\u00f6nnen auch auf diese Schaltfl\\u00e4che klicken, um Ihren Posteingang zu \\u00f6ffnen.\"},\"gmailcheck_node_error\":{\"message\":\"Fehler: Feed abgerufen, aber kein &lt;fullcount&gt; Knoten gefunden\"},\"gmailcheck_exception\":{\"message\":\"Ausnahme: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/el/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"\\u0388\\u03bb\\u03b5\\u03b3\\u03c7\\u03bf\\u03c2 \\u03c4\\u03bf\\u03c5 Google Mail\"},\"gmailcheck_description\":{\"message\":\"\\u0395\\u03bc\\u03c6\\u03b1\\u03bd\\u03af\\u03b6\\u03b5\\u03b9 \\u03c4\\u03bf\\u03bd \\u03b1\\u03c1\\u03b9\\u03b8\\u03bc\\u03cc \\u03c4\\u03c9\\u03bd \\u03bc\\u03b7 \\u03b1\\u03bd\\u03b1\\u03b3\\u03bd\\u03c9\\u03c3\\u03bc\\u03ad\\u03bd\\u03c9\\u03bd \\u03bc\\u03b7\\u03bd\\u03c5\\u03bc\\u03ac\\u03c4\\u03c9\\u03bd \\u03c3\\u03c4\\u03b1 \\u03b5\\u03b9\\u03c3\\u03b5\\u03c1\\u03c7\\u03cc\\u03bc\\u03b5\\u03bd\\u03b1 \\u03c4\\u03bf\\u03c5 Google Mail \\u03c3\\u03b1\\u03c2. \\u039c\\u03c0\\u03bf\\u03c1\\u03b5\\u03af\\u03c4\\u03b5 \\u03b5\\u03c0\\u03af\\u03c3\\u03b7\\u03c2 \\u03bd\\u03b1 \\u03ba\\u03ac\\u03bd\\u03b5\\u03c4\\u03b5 \\u03ba\\u03bb\\u03b9\\u03ba \\u03c3\\u03c4\\u03bf \\u03ba\\u03bf\\u03c5\\u03bc\\u03c0\\u03af \\u03b3\\u03b9\\u03b1 \\u03bd\\u03b1 \\u03b1\\u03bd\\u03bf\\u03af\\u03be\\u03b5\\u03c4\\u03b5 \\u03c4\\u03b1 \\u03b5\\u03b9\\u03c3\\u03b5\\u03c1\\u03c7\\u03cc\\u03bc\\u03b5\\u03bd\\u03ac \\u03c3\\u03b1\\u03c2.\"},\"gmailcheck_node_error\":{\"message\":\"\\u03a3\\u03c6\\u03ac\\u03bb\\u03bc\\u03b1: \\u03ad\\u03b3\\u03b9\\u03bd\\u03b5 \\u03b1\\u03bd\\u03ac\\u03ba\\u03c4\\u03b7\\u03c3\\u03b7 \\u03c1\\u03bf\\u03ae\\u03c2, \\u03b1\\u03bb\\u03bb\\u03ac \\u03b4\\u03b5\\u03bd \\u03b2\\u03c1\\u03ad\\u03b8\\u03b7\\u03ba\\u03b5 \\u03ba\\u03cc\\u03bc\\u03b2\\u03bf\\u03c2 &lt;fullcount&gt;\"},\"gmailcheck_exception\":{\"message\":\"\\u03b5\\u03be\\u03b1\\u03af\\u03c1\\u03b5\\u03c3\\u03b7: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/en/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"Displays the number of unread messages in your Google Mail inbox. You can also click the button to open your inbox.\"},\"gmailcheck_node_error\":{\"message\":\"Error: feed retrieved, but no &lt;fullcount&gt; node found\"},\"gmailcheck_exception\":{\"message\":\"exception: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/en_GB/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"Displays the number of unread messages in your Google Mail inbox. You can also click the button to open your inbox.\"},\"gmailcheck_node_error\":{\"message\":\"Error: Feed retrieved, but no &lt;fullcount&gt; node found\"},\"gmailcheck_exception\":{\"message\":\"exception: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/es/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"Permite ver el n\\u00famero de mensajes sin leer en la bandeja de entrada de Google Mail. Tambi\\u00e9n puedes hacer clic en el bot\\u00f3n para abrir la bandeja de entrada.\"},\"gmailcheck_node_error\":{\"message\":\"Se ha producido un error: el feed se ha recuperado, pero no se ha encontrado ning\\u00fan nodo &lt;fullcount&gt;.\"},\"gmailcheck_exception\":{\"message\":\"excepci\\u00f3n: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/es_419/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"Muestra el n\\u00famero de mensajes sin leer en tu bandeja de entrada de Google Mail. Tambi\\u00e9n puedes hacer clic en el bot\\u00f3n para abrir tu bandeja de entrada.\"},\"gmailcheck_node_error\":{\"message\":\"Error: se recuper\\u00f3 el feed, pero no se encontr\\u00f3 el nodo &lt;fullcount&gt;\"},\"gmailcheck_exception\":{\"message\":\"excepci\\u00f3n: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/et/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google'i meilikontrollija\"},\"gmailcheck_description\":{\"message\":\"Kuvab Google Maili postkastis olevate lugemata s\\u00f5numite arvu. V\\u00f5ite kl\\u00f5psata ka nupul ja avada postkasti.\"},\"gmailcheck_node_error\":{\"message\":\"Viga: voog vastuv\\u00f5etud, kuid \\u00fchtki &lt;fullcount&gt; s\\u00f5lme ei leitud\"},\"gmailcheck_exception\":{\"message\":\"erand: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/fi/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google-s\\u00e4hk\\u00f6postin tarkistus\"},\"gmailcheck_description\":{\"message\":\"N\\u00e4ytt\\u00e4\\u00e4, kuinka monta lukematonta viesti\\u00e4 Google Mail -postilaatikossasi on. Voit my\\u00f6s avata postilaatikkosi napsauttamalla painiketta.\"},\"gmailcheck_node_error\":{\"message\":\"Virhe: sy\\u00f6te haettiin, mutta &lt;fullcount&gt;-solmua ei l\\u00f6ytynyt\"},\"gmailcheck_exception\":{\"message\":\"poikkeus: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/fil/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"Ipinapakita ang bilang ng mga hindi pa nababasang mensahe sa inbox ng iyong Google Mail. Maaari mo ring i-click ang pindutan upang buksan ang iyong inbox.\"},\"gmailcheck_node_error\":{\"message\":\"Error: nakuha ang feed, ngunit walang &lt;fullcount&gt; node na natagpuan\"},\"gmailcheck_exception\":{\"message\":\"pagbubukod: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/fr/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"V\\u00e9rificateur de messages Google\"},\"gmailcheck_description\":{\"message\":\"Affiche le nombre de messages non lus dans votre bo\\u00eete de r\\u00e9ception Google\\u00a0Mail. Vous avez \\u00e9galement la possibilit\\u00e9 de cliquer sur ce bouton pour ouvrir cette derni\\u00e8re.\"},\"gmailcheck_node_error\":{\"message\":\"Erreur\\u00a0: flux r\\u00e9cup\\u00e9r\\u00e9, mais aucun n\\u0153ud &lt;fullcount&gt; trouv\\u00e9\"},\"gmailcheck_exception\":{\"message\":\"exception\\u00a0: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/he/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"\\u05de\\u05e6\\u05d9\\u05d2 \\u05d0\\u05ea \\u05de\\u05e1\\u05e4\\u05e8 \\u05d4\\u05d4\\u05d5\\u05d3\\u05e2\\u05d5\\u05ea \\u05e9\\u05dc\\u05d0 \\u05e0\\u05e7\\u05e8\\u05d0\\u05d5 \\u05d1\\u05ea\\u05d9\\u05d1\\u05ea \\u05d4\\u05d3\\u05d5\\u05d0\\u05e8 \\u05d4\\u05e0\\u05db\\u05e0\\u05e1 \\u05e9\\u05dc\\u05da \\u05d1-Google Mail. \\u05d1\\u05e0\\u05d5\\u05e1\\u05e3, \\u05ea\\u05d5\\u05db\\u05dc \\u05dc\\u05dc\\u05d7\\u05d5\\u05e5 \\u05e2\\u05dc \\u05d4\\u05dc\\u05d7\\u05e6\\u05df \\u05db\\u05d3\\u05d9 \\u05dc\\u05e4\\u05ea\\u05d5\\u05d7 \\u05d0\\u05ea \\u05ea\\u05d9\\u05d1\\u05ea \\u05d4\\u05d3\\u05d5\\u05d0\\u05e8 \\u05d4\\u05e0\\u05db\\u05e0\\u05e1.\"},\"gmailcheck_node_error\":{\"message\":\"\\u05e9\\u05d2\\u05d9\\u05d0\\u05d4: \\u05d4\\u05e2\\u05d3\\u05db\\u05d5\\u05df \\u05d0\\u05d5\\u05d7\\u05d6\\u05e8, \\u05d0\\u05da \\u05dc\\u05d0 \\u05e0\\u05de\\u05e6\\u05d0\\u05d5 \\u05e6\\u05de\\u05ea\\u05d9\\u05dd \\u05e9\\u05dc &lt;fullcount&gt;\"},\"gmailcheck_exception\":{\"message\":\"\\u05d7\\u05e8\\u05d9\\u05d2: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/hi/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google \\u092e\\u0947\\u0932 \\u091c\\u093e\\u0902\\u091a\\u0915\\u0930\\u094d\\u0924\\u093e\"},\"gmailcheck_description\":{\"message\":\"\\u0906\\u092a\\u0915\\u0947 Google \\u092e\\u0947\\u0932 \\u0907\\u0928\\u092c\\u0949\\u0915\\u094d\\u0938 \\u092e\\u0947\\u0902 \\u0928 \\u092a\\u095d\\u0947 \\u0917\\u090f \\u0938\\u0902\\u0926\\u0947\\u0936\\u094b\\u0902 \\u0915\\u0940 \\u0938\\u0902\\u0916\\u094d\\u092f\\u093e \\u092a\\u094d\\u0930\\u0926\\u0930\\u094d\\u0936\\u093f\\u0924 \\u0915\\u0930\\u0924\\u093e \\u0939\\u0948. \\u0906\\u092a \\u0905\\u092a\\u0928\\u093e \\u0907\\u0928\\u092c\\u0949\\u0915\\u094d\\u0938 \\u0916\\u094b\\u0932\\u0928\\u0947 \\u0915\\u0947 \\u0932\\u093f\\u090f \\u092c\\u091f\\u0928 \\u0915\\u094d\\u0932\\u093f\\u0915 \\u092d\\u0940 \\u0915\\u0930 \\u0938\\u0915\\u0924\\u0947 \\u0939\\u0948\\u0902.\"},\"gmailcheck_node_error\":{\"message\":\"\\u0924\\u094d\\u0930\\u0941\\u091f\\u093f: \\u095e\\u0940\\u0921 \\u092a\\u0941\\u0928\\u0930\\u094d\\u092a\\u094d\\u0930\\u093e\\u092a\\u094d\\u0924 \\u0915\\u0940 \\u0917\\u0908, \\u0932\\u0947\\u0915\\u093f\\u0928 \\u0915\\u094b\\u0908 &lt;fullcount&gt; \\u0928\\u094b\\u0921 \\u0928\\u0939\\u0940\\u0902 \\u092e\\u093f\\u0932\\u093e\"},\"gmailcheck_exception\":{\"message\":\"\\u0905\\u092a\\u0935\\u093e\\u0926: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/hr/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Provjera po\\u0161te\"},\"gmailcheck_description\":{\"message\":\"Prikazuje broj nepro\\u010ditanih poruka u ulaznom pretincu usluge Google Mail. Mo\\u017eete tako\\u0111er kliknuti gumb za otvaranje ulazne po\\u0161te.\"},\"gmailcheck_node_error\":{\"message\":\"Pogre\\u0161ka: Feed je dohva\\u0107en, ali nije prona\\u0111eno \\u010dvori\\u0161te &lt;fullcount&gt;\"},\"gmailcheck_exception\":{\"message\":\"izuzetak: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/hu/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Lev\\u00e9lfigyel\\u0151\"},\"gmailcheck_description\":{\"message\":\"Megjelen\\u00edti az olvasatlan \\u00fczeneteket a Google Mail be\\u00e9rkez\\u0151 levelei k\\u00f6z\\u00f6tt. A gombra kattintva is megnyithatja a be\\u00e9rkez\\u0151 leveleit.\"},\"gmailcheck_node_error\":{\"message\":\"Hiba: h\\u00edrcsatorna leh\\u00edvva, de a csom\\u00f3pont (&lt;fullcount&gt;) hi\\u00e1nyzik\"},\"gmailcheck_exception\":{\"message\":\"kiv\\u00e9tel: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/id/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"Menampilkan jumlah pesan yang belum dibaca dalam kotak masuk Google Mail. Anda juga dapat mengeklik tombol ini untuk membuka kotak masuk.\"},\"gmailcheck_node_error\":{\"message\":\"Galat: umpan diperoleh, tetapi tidak ada &lt;fullcount&gt; node yang ditemukan\"},\"gmailcheck_exception\":{\"message\":\"pengecualian: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/it/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Avvisi email\"},\"gmailcheck_description\":{\"message\":\"Visualizza il numero di messaggi da leggere nella posta in arrivo di Google Mail. Puoi anche fare clic sul pulsante per aprire la tua posta in arrivo.\"},\"gmailcheck_node_error\":{\"message\":\"Errore: feed recuperato ma non sono stati trovati nodi &lt;fullcount&gt;\"},\"gmailcheck_exception\":{\"message\":\"eccezione: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/ja/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"Google Mail \\u306e\\u53d7\\u4fe1\\u30c8\\u30ec\\u30a4\\u306b\\u3042\\u308b\\u672a\\u8aad\\u306e\\u30e1\\u30fc\\u30eb\\u6570\\u3092\\u8868\\u793a\\u3057\\u307e\\u3059\\u3002\\u3053\\u306e\\u30dc\\u30bf\\u30f3\\u3092\\u30af\\u30ea\\u30c3\\u30af\\u3057\\u3066\\u53d7\\u4fe1\\u30c8\\u30ec\\u30a4\\u3092\\u958b\\u304f\\u3053\\u3068\\u3082\\u3067\\u304d\\u307e\\u3059\\u3002\"},\"gmailcheck_node_error\":{\"message\":\"\\u30a8\\u30e9\\u30fc: \\u53d6\\u5f97\\u3057\\u305f\\u30d5\\u30a3\\u30fc\\u30c9\\u306b &lt;fullcount&gt; \\u30ce\\u30fc\\u30c9\\u304c\\u3042\\u308a\\u307e\\u305b\\u3093\"},\"gmailcheck_exception\":{\"message\":\"\\u4f8b\\u5916: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/ko/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"Gmaill \\ubc1b\\uc740\\ud3b8\\uc9c0\\ud568\\uc5d0\\uc11c \\uc77d\\uc9c0 \\uc54a\\uc740 \\uba54\\uc77c\\uc758 \\uc218\\ub97c \\ub098\\ud0c0\\ub0c5\\ub2c8\\ub2e4. \\ub610\\ud55c \\ubc84\\ud2bc\\uc744 \\ud074\\ub9ad\\ud558\\uc5ec \\ubc1b\\uc740\\ud3b8\\uc9c0\\ud568\\uc744 \\uc5f4 \\uc218\\ub3c4 \\uc788\\uc2b5\\ub2c8\\ub2e4.\"},\"gmailcheck_node_error\":{\"message\":\"\\uc624\\ub958: \\ud53c\\ub4dc\\ub97c \\uac80\\uc0c9\\ud588\\uc73c\\ub098 \\ucd1d &lt;fullcount&gt;\\uac1c\\uc758 \\ub178\\ub4dc\\ub97c \\ucc3e\\uc9c0 \\ubabb\\ud588\\uc2b5\\ub2c8\\ub2e4.\"},\"gmailcheck_exception\":{\"message\":\"\\uc608\\uc678: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/lt/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"\\u201eGoogle\\u201c pa\\u0161to tikrintuvas\"},\"gmailcheck_description\":{\"message\":\"Pateikiamas \\u201eGoogle\\u201c pa\\u0161to gaut\\u0173 lai\\u0161k\\u0173 aplanke esan\\u010di\\u0173 neperskaityt\\u0173 prane\\u0161im\\u0173 skai\\u010dius. Be to, jei norite atidaryti gaut\\u0173 lai\\u0161k\\u0173 aplank\\u0105, galite spustel\\u0117ti mygtuk\\u0105.\"},\"gmailcheck_node_error\":{\"message\":\"Klaida: sklaidos kanalas nuskaitytas, ta\\u010diau nerastas joks &lt;fullcount&gt; mazgas\"},\"gmailcheck_exception\":{\"message\":\"i\\u0161imtis: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/lv/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"Tiek r\\u0101d\\u012bts nelas\\u012bto zi\\u0146ojumu skaits Google Mail ies\\u016btn\\u0113. Varat ar\\u012b noklik\\u0161\\u0137in\\u0101t uz pogas, lai atv\\u0113rtu ies\\u016btni.\"},\"gmailcheck_node_error\":{\"message\":\"K\\u013c\\u016bda: pl\\u016bsma ir izg\\u016bta, ta\\u010du netika atrasts neviens &lt;fullcount&gt; mezgls\"},\"gmailcheck_exception\":{\"message\":\"iz\\u0146\\u0113mums: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/nb/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google e-post-sjekker\"},\"gmailcheck_description\":{\"message\":\"Viser antallet uleste meldinger i innboksen for Google Mail. Du kan ogs\\u00e5 klikke p\\u00e5 knappen for \\u00e5 \\u00e5pne innboksen.\"},\"gmailcheck_node_error\":{\"message\":\"Feil: innmating hentet, men finner ingen &lt;fullcount&gt;-node\"},\"gmailcheck_exception\":{\"message\":\"unntak: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/nl/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"Hiermee wordt het aantal ongelezen berichten in uw Postvak IN van Gmail weergegeven. U kunt ook op de knop klikken om het Postvak IN te openen.\"},\"gmailcheck_node_error\":{\"message\":\"Fout: feed opgehaald, maar het knooppunt &lt;fullcount&gt; is niet gevonden\"},\"gmailcheck_exception\":{\"message\":\"uitzondering: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/pl/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Sprawdzanie poczty Google\"},\"gmailcheck_description\":{\"message\":\"Wy\\u015bwietla liczb\\u0119 nieprzeczytanych wiadomo\\u015bci w Twojej skrzynce odbiorczej Google Mail. Mo\\u017cesz te\\u017c klikn\\u0105\\u0107 przycisk, aby otworzy\\u0107 swoj\\u0105 skrzynk\\u0119 odbiorcz\\u0105.\"},\"gmailcheck_node_error\":{\"message\":\"B\\u0142\\u0105d: pobrano kana\\u0142, ale nie odnaleziono w\\u0119z\\u0142a &lt;fullcount&gt;\"},\"gmailcheck_exception\":{\"message\":\"wyj\\u0105tek: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/pt_BR/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Verificador de mensagens do Google\"},\"gmailcheck_description\":{\"message\":\"Exibe o n\\u00famero de mensagens n\\u00e3o lidas na sua Caixa de entrada do Gmail. Voc\\u00ea tamb\\u00e9m pode clicar no bot\\u00e3o para abrir a sua caixa de entrada.\"},\"gmailcheck_node_error\":{\"message\":\"Erro: feed recuperado, mas nenhum n\\u00f3 &lt;fullcount&gt; encontrado\"},\"gmailcheck_exception\":{\"message\":\"exce\\u00e7\\u00e3o: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/pt_PT/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Verificador do Google Mail\"},\"gmailcheck_description\":{\"message\":\"Apresenta o n\\u00famero de mensagens n\\u00e3o lidas existentes na sua caixa de entrada do Google Mail. Pode tamb\\u00e9m clicar no bot\\u00e3o para abrir a caixa de entrada.\"},\"gmailcheck_node_error\":{\"message\":\"Erro: obteve-se o feed, mas n\\u00e3o foi encontrado nenhum n\\u00f3 &lt;fullcount&gt;\"},\"gmailcheck_exception\":{\"message\":\"excep\\u00e7\\u00e3o: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/ro/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Verificator de e-mail\"},\"gmailcheck_description\":{\"message\":\"Afi\\u015feaz\\u0103 num\\u0103rul mesajelor necitite din folderul Mesaje primite al contului Google Mail. De asemenea, pute\\u0163i s\\u0103 face\\u0163i clic pe buton pentru a deschide folderul Mesaje primite.\"},\"gmailcheck_node_error\":{\"message\":\"Eroare: s-a preluat feedul, dar nu s-a g\\u0103sit niciun nod &lt;fullcount&gt;\"},\"gmailcheck_exception\":{\"message\":\"excep\\u0163ie: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/ru/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"\\u041e\\u0442\\u043e\\u0431\\u0440\\u0430\\u0436\\u0435\\u043d\\u0438\\u0435 \\u043a\\u043e\\u043b\\u0438\\u0447\\u0435\\u0441\\u0442\\u0432\\u0430 \\u043d\\u0435\\u043f\\u0440\\u043e\\u0447\\u0438\\u0442\\u0430\\u043d\\u043d\\u044b\\u0445 \\u0441\\u043e\\u043e\\u0431\\u0449\\u0435\\u043d\\u0438\\u0439 \\u0432 \\u043f\\u043e\\u0447\\u0442\\u043e\\u0432\\u043e\\u043c \\u044f\\u0449\\u0438\\u043a\\u0435 Google Mail. \\u041c\\u043e\\u0436\\u043d\\u043e \\u0442\\u0430\\u043a\\u0436\\u0435 \\u043d\\u0430\\u0436\\u0430\\u0442\\u044c \\u043a\\u043d\\u043e\\u043f\\u043a\\u0443, \\u0447\\u0442\\u043e\\u0431\\u044b \\u043e\\u0442\\u043a\\u0440\\u044b\\u0442\\u044c \\u043f\\u0430\\u043f\\u043a\\u0443 \\\"\\u0412\\u0445\\u043e\\u0434\\u044f\\u0449\\u0438\\u0435\\\".\"},\"gmailcheck_node_error\":{\"message\":\"\\u041e\\u0448\\u0438\\u0431\\u043a\\u0430: \\u0444\\u0438\\u0434 \\u0431\\u044b\\u043b \\u043f\\u043e\\u043b\\u0443\\u0447\\u0435\\u043d, \\u043d\\u043e \\u043d\\u0435 \\u0443\\u0434\\u0430\\u043b\\u043e\\u0441\\u044c \\u043d\\u0430\\u0439\\u0442\\u0438 \\u0443\\u0437\\u0435\\u043b &lt;fullcount&gt;\"},\"gmailcheck_exception\":{\"message\":\"\\u0438\\u0441\\u043a\\u043b\\u044e\\u0447\\u0435\\u043d\\u0438\\u0435: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/sk/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Kontrola po\\u0161ty Google\"},\"gmailcheck_description\":{\"message\":\"Zobraz\\u00ed po\\u010det nepre\\u010d\\u00edtan\\u00fdch spr\\u00e1v v prie\\u010dinku doru\\u010denej po\\u0161ty v slu\\u017ebe Gmail. Kliknut\\u00edm na tla\\u010didlo prie\\u010dinok doru\\u010denej po\\u0161ty otvor\\u00edte.\"},\"gmailcheck_node_error\":{\"message\":\"Chyba: informa\\u010dn\\u00fd kan\\u00e1l bol na\\u010d\\u00edtan\\u00fd, nena\\u0161iel sa v\\u0161ak \\u017eiadny uzol &lt;fullcount&gt;.\"},\"gmailcheck_exception\":{\"message\":\"v\\u00fdnimka: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/sl/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Preverjevalnik za Google Mail\"},\"gmailcheck_description\":{\"message\":\"Prika\\u017ee \\u0161tevilo neprebranih sporo\\u010dil v nabiralniku storitve Google Mail. Nabiralnik lahko odprete tudi s klikom gumba.\"},\"gmailcheck_node_error\":{\"message\":\"Napaka: vir prejet, vendar ni bilo najdeno nobeno vozli\\u0161\\u010de &lt;fullcount&gt;\"},\"gmailcheck_exception\":{\"message\":\"izjema: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/sr/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google \\u043f\\u0440\\u043e\\u0432\\u0435\\u0440\\u0430 \\u043f\\u043e\\u0448\\u0442\\u0435\"},\"gmailcheck_description\":{\"message\":\"\\u041f\\u0440\\u0438\\u043a\\u0430\\u0437\\u0443\\u0458\\u0435 \\u0431\\u0440\\u043e\\u0458 \\u043d\\u0435\\u043f\\u0440\\u043e\\u0447\\u0438\\u0442\\u0430\\u043d\\u0438\\u0445 \\u043f\\u0440\\u0438\\u043c\\u0459\\u0435\\u043d\\u0438\\u0445 \\u043f\\u043e\\u0440\\u0443\\u043a\\u0430 Google Mail-\\u0430. \\u041c\\u043e\\u0436\\u0435\\u0442\\u0435 \\u0438 \\u0434\\u0430 \\u043a\\u043b\\u0438\\u043a\\u043d\\u0435\\u0442\\u0435 \\u043d\\u0430 \\u0434\\u0443\\u0433\\u043c\\u0435 \\u0438 \\u043e\\u0442\\u0432\\u043e\\u0440\\u0438\\u0442\\u0435 \\u043f\\u0440\\u0438\\u043c\\u0459\\u0435\\u043d\\u0435 \\u043f\\u043e\\u0440\\u0443\\u043a\\u0435.\"},\"gmailcheck_node_error\":{\"message\":\"\\u0413\\u0440\\u0435\\u0448\\u043a\\u0430: \\u0424\\u0438\\u0434 \\u0458\\u0435 \\u043f\\u0440\\u0435\\u0443\\u0437\\u0435\\u0442, \\u0430\\u043b\\u0438 \\u0447\\u0432\\u043e\\u0440 &lt;fullcount&gt; \\u043d\\u0438\\u0458\\u0435 \\u043f\\u0440\\u043e\\u043d\\u0430\\u0452\\u0435\\u043d\"},\"gmailcheck_exception\":{\"message\":\"\\u0438\\u0437\\u0443\\u0437\\u0435\\u0442\\u0430\\u043a: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/sv/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"Visar hur m\\u00e5nga ol\\u00e4sta meddelanden du har i inkorgen i Google Mail. Du kan ocks\\u00e5 klicka p\\u00e5 knappen om du vill \\u00f6ppna inkorgen.\"},\"gmailcheck_node_error\":{\"message\":\"Fel: feeden h\\u00e4mtades, men ingen &lt;fullcount&gt;-nod hittades\"},\"gmailcheck_exception\":{\"message\":\"undantag: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/th/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"\\u0e41\\u0e2a\\u0e14\\u0e07\\u0e08\\u0e33\\u0e19\\u0e27\\u0e19\\u0e02\\u0e2d\\u0e07\\u0e02\\u0e49\\u0e2d\\u0e04\\u0e27\\u0e32\\u0e21\\u0e17\\u0e35\\u0e48\\u0e22\\u0e31\\u0e07\\u0e44\\u0e21\\u0e48\\u0e44\\u0e14\\u0e49\\u0e2d\\u0e48\\u0e32\\u0e19\\u0e43\\u0e19\\u0e01\\u0e25\\u0e48\\u0e2d\\u0e07\\u0e08\\u0e14\\u0e2b\\u0e21\\u0e32\\u0e22 Google Mail \\u0e02\\u0e2d\\u0e07\\u0e04\\u0e38\\u0e13 \\u0e41\\u0e25\\u0e30\\u0e04\\u0e38\\u0e13\\u0e2a\\u0e32\\u0e21\\u0e32\\u0e23\\u0e16\\u0e04\\u0e25\\u0e34\\u0e01\\u0e1b\\u0e38\\u0e48\\u0e21\\u0e40\\u0e1e\\u0e37\\u0e48\\u0e2d\\u0e40\\u0e1b\\u0e34\\u0e14\\u0e01\\u0e25\\u0e48\\u0e2d\\u0e07\\u0e08\\u0e14\\u0e2b\\u0e21\\u0e32\\u0e22\\u0e02\\u0e2d\\u0e07\\u0e04\\u0e38\\u0e13\\u0e44\\u0e14\\u0e49\\u0e40\\u0e0a\\u0e48\\u0e19\\u0e01\\u0e31\\u0e19\"},\"gmailcheck_node_error\":{\"message\":\"\\u0e02\\u0e49\\u0e2d\\u0e1c\\u0e34\\u0e14\\u0e1e\\u0e25\\u0e32\\u0e14: \\u0e40\\u0e23\\u0e35\\u0e22\\u0e01\\u0e04\\u0e37\\u0e19\\u0e1f\\u0e35\\u0e14\\u0e41\\u0e25\\u0e49\\u0e27 \\u0e41\\u0e15\\u0e48\\u0e44\\u0e21\\u0e48\\u0e1e\\u0e1a\\u0e42\\u0e2b\\u0e19\\u0e14 &lt;fullcount&gt;\"},\"gmailcheck_exception\":{\"message\":\"\\u0e02\\u0e49\\u0e2d\\u0e22\\u0e01\\u0e40\\u0e27\\u0e49\\u0e19: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/tr/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"Google Mail gelen kutunuzdaki okunmam\\u0131\\u015f iletilerin say\\u0131s\\u0131n\\u0131 g\\u00f6r\\u00fcnt\\u00fcler. Ayr\\u0131ca, d\\u00fc\\u011fmeyi t\\u0131klayarak gelen kutunuzu da a\\u00e7abilirsiniz.\"},\"gmailcheck_node_error\":{\"message\":\"Hata: yay\\u0131n al\\u0131nd\\u0131, ancak &lt;fullcount&gt; d\\u00fc\\u011f\\u00fcm\\u00fc bulunamad\\u0131\"},\"gmailcheck_exception\":{\"message\":\"\\u00f6zel durum: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/uk/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"\\u041f\\u0435\\u0440\\u0435\\u0432\\u0456\\u0440\\u043a\\u0430 \\u043f\\u043e\\u0448\\u0442\\u0438 Google\"},\"gmailcheck_description\":{\"message\":\"\\u0412\\u0456\\u0434\\u043e\\u0431\\u0440\\u0430\\u0436\\u0430\\u0454 \\u043a\\u0456\\u043b\\u044c\\u043a\\u0456\\u0441\\u0442\\u044c \\u043d\\u0435\\u043f\\u0440\\u043e\\u0447\\u0438\\u0442\\u0430\\u043d\\u0438\\u0445 \\u043f\\u043e\\u0432\\u0456\\u0434\\u043e\\u043c\\u043b\\u0435\\u043d\\u044c \\u0443 \\u043f\\u0430\\u043f\\u0446\\u0456 \\u0437 \\u0432\\u0445\\u0456\\u0434\\u043d\\u0438\\u043c\\u0438 \\u043f\\u043e\\u0432\\u0456\\u0434\\u043e\\u043c\\u043b\\u0435\\u043d\\u043d\\u044f\\u043c\\u0438 \\u0441\\u043b\\u0443\\u0436\\u0431\\u0438 Google Mail. \\u0429\\u043e\\u0431 \\u0432\\u0456\\u0434\\u043a\\u0440\\u0438\\u0442\\u0438 \\u043f\\u0430\\u043f\\u043a\\u0443 \\u0437 \\u0432\\u0445\\u0456\\u0434\\u043d\\u0438\\u043c\\u0438 \\u043f\\u043e\\u0432\\u0456\\u0434\\u043e\\u043c\\u043b\\u0435\\u043d\\u043d\\u044f\\u043c\\u0438, \\u043c\\u043e\\u0436\\u043d\\u0430 \\u0442\\u0430\\u043a\\u043e\\u0436 \\u043d\\u0430\\u0442\\u0438\\u0441\\u043d\\u0443\\u0442\\u0438 \\u0446\\u044e \\u043a\\u043d\\u043e\\u043f\\u043a\\u0443.\"},\"gmailcheck_node_error\":{\"message\":\"\\u041f\\u043e\\u043c\\u0438\\u043b\\u043a\\u0430: \\u043a\\u0430\\u043d\\u0430\\u043b \\u0432\\u0456\\u0434\\u043d\\u043e\\u0432\\u043b\\u0435\\u043d\\u043e, \\u0430\\u043b\\u0435 \\u0436\\u043e\\u0434\\u043d\\u043e\\u0433\\u043e \\u0432\\u0443\\u0437\\u043b\\u0430 &lt;fullcount&gt; \\u043d\\u0435 \\u0437\\u043d\\u0430\\u0439\\u0434\\u0435\\u043d\\u043e\"},\"gmailcheck_exception\":{\"message\":\"\\u0432\\u0438\\u043d\\u044f\\u0442\\u043e\\u043a: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/vi/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Tr\\u00ecnh Ki\\u1ec3m tra Th\\u01b0 c\\u1ee7a Google\"},\"gmailcheck_description\":{\"message\":\"Hi\\u1ec3n th\\u1ecb s\\u1ed1 th\\u01b0 ch\\u01b0a \\u0111\\u1ecdc trong h\\u1ed9p th\\u01b0 \\u0111\\u1ebfn Gmail c\\u1ee7a b\\u1ea1n. B\\u1ea1n c\\u0169ng c\\u00f3 th\\u1ec3 nh\\u1ea5p v\\u00e0o n\\u00fat \\u0111\\u1ec3 m\\u1edf h\\u1ed9p th\\u01b0 \\u0111\\u1ebfn c\\u1ee7a m\\u00ecnh.\"},\"gmailcheck_node_error\":{\"message\":\"L\\u1ed7i: ngu\\u1ed3n c\\u1ea5p d\\u1eef li\\u1ec7u \\u0111\\u00e3 \\u0111\\u01b0\\u1ee3c truy xu\\u1ea5t nh\\u01b0ng kh\\u00f4ng t\\u00ecm th\\u1ea5y n\\u00fat &lt;fullcount&gt; n\\u00e0o\"},\"gmailcheck_exception\":{\"message\":\"ngo\\u1ea1i l\\u1ec7: $1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/zh_CN/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"\\u663e\\u793a Google Mail \\u6536\\u4ef6\\u7bb1\\u4e2d\\u7684\\u672a\\u8bfb\\u90ae\\u4ef6\\u6570\\u3002\\u70b9\\u51fb\\u8be5\\u6309\\u94ae\\u8fd8\\u53ef\\u4ee5\\u6253\\u5f00\\u60a8\\u7684\\u6536\\u4ef6\\u7bb1\\u3002\"},\"gmailcheck_node_error\":{\"message\":\"\\u9519\\u8bef\\uff1a\\u7cfb\\u7edf\\u5df2\\u68c0\\u7d22\\u4f9b\\u7a3f\\uff0c\\u4f46\\u672a\\u53d1\\u73b0 &lt;fullcount&gt; \\u8282\\u70b9\"},\"gmailcheck_exception\":{\"message\":\"\\u5f02\\u5e38\\uff1a$1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/_locales/zh_TW/messages.json",
    "content": "{\"gmailcheck_name\":{\"message\":\"Google Mail Checker\"},\"gmailcheck_description\":{\"message\":\"\\u5728 Google Mail \\u6536\\u4ef6\\u5323\\u4e2d\\u986f\\u793a\\u672a\\u8b80\\u90f5\\u4ef6\\u7684\\u6578\\u76ee\\u3002\\u6309\\u4e00\\u4e0b\\u6309\\u9215\\u4e5f\\u53ef\\u4ee5\\u958b\\u555f\\u6536\\u4ef6\\u5323\\u3002\"},\"gmailcheck_node_error\":{\"message\":\"\\u932f\\u8aa4\\uff1a\\u64f7\\u53d6\\u5230\\u8cc7\\u8a0a\\u63d0\\u4f9b\\uff0c\\u4f46\\u627e\\u4e0d\\u5230 &lt;fullcount&gt; \\u7bc0\\u9ede\"},\"gmailcheck_exception\":{\"message\":\"\\u4f8b\\u5916\\u72c0\\u6cc1\\uff1a$1\",\"placeholders\":{\"1\":{\"content\":\"$1\"}}}}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/background.html",
    "content": "<img id=\"logged_in\" src=\"gmail_logged_in.png\">\n<canvas id=\"canvas\" width=\"19\" height=\"19\">\n<script src=\"background.js\"></script>\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar animationFrames = 36;\nvar animationSpeed = 10; // ms\nvar canvas = document.getElementById('canvas');\nvar loggedInImage = document.getElementById('logged_in');\nvar canvasContext = canvas.getContext('2d');\nvar pollIntervalMin = 1;  // 1 minute\nvar pollIntervalMax = 60;  // 1 hour\nvar requestTimeout = 1000 * 2;  // 2 seconds\nvar rotation = 0;\nvar loadingAnimation = new LoadingAnimation();\n\n// Legacy support for pre-event-pages.\nvar oldChromeVersion = !chrome.runtime;\nvar requestTimerId;\n\nfunction getGmailUrl() {\n  return \"https://mail.google.com/mail/\";\n}\n\n// Identifier used to debug the possibility of multiple instances of the\n// extension making requests on behalf of a single user.\nfunction getInstanceId() {\n  if (!localStorage.hasOwnProperty(\"instanceId\"))\n    localStorage.instanceId = 'gmc' + parseInt(Date.now() * Math.random(), 10);\n  return localStorage.instanceId;\n}\n\nfunction getFeedUrl() {\n  // \"zx\" is a Gmail query parameter that is expected to contain a random\n  // string and may be ignored/stripped.\n  return getGmailUrl() + \"feed/atom?zx=\" + encodeURIComponent(getInstanceId());\n}\n\nfunction isGmailUrl(url) {\n  // Return whether the URL starts with the Gmail prefix.\n  return url.startsWith(getGmailUrl());\n}\n\n// A \"loading\" animation displayed while we wait for the first response from\n// Gmail. This animates the badge text with a dot that cycles from left to\n// right.\nfunction LoadingAnimation() {\n  this.timerId_ = 0;\n  this.maxCount_ = 8;  // Total number of states in animation\n  this.current_ = 0;  // Current state\n  this.maxDot_ = 4;  // Max number of dots in animation\n}\n\nLoadingAnimation.prototype.paintFrame = function() {\n  var text = \"\";\n  for (var i = 0; i < this.maxDot_; i++) {\n    text += (i == this.current_) ? \".\" : \" \";\n  }\n  if (this.current_ >= this.maxDot_)\n    text += \"\";\n\n  chrome.browserAction.setBadgeText({text:text});\n  this.current_++;\n  if (this.current_ == this.maxCount_)\n    this.current_ = 0;\n}\n\nLoadingAnimation.prototype.start = function() {\n  if (this.timerId_)\n    return;\n\n  var self = this;\n  this.timerId_ = window.setInterval(function() {\n    self.paintFrame();\n  }, 100);\n}\n\nLoadingAnimation.prototype.stop = function() {\n  if (!this.timerId_)\n    return;\n\n  window.clearInterval(this.timerId_);\n  this.timerId_ = 0;\n}\n\nfunction updateIcon() {\n  if (!localStorage.hasOwnProperty('unreadCount')) {\n    chrome.browserAction.setIcon({path:\"gmail_not_logged_in.png\"});\n    chrome.browserAction.setBadgeBackgroundColor({color:[190, 190, 190, 230]});\n    chrome.browserAction.setBadgeText({text:\"?\"});\n  } else {\n    chrome.browserAction.setIcon({path: \"gmail_logged_in.png\"});\n    chrome.browserAction.setBadgeBackgroundColor({color:[208, 0, 24, 255]});\n    chrome.browserAction.setBadgeText({\n      text: localStorage.unreadCount != \"0\" ? localStorage.unreadCount : \"\"\n    });\n  }\n}\n\nfunction scheduleRequest() {\n  console.log('scheduleRequest');\n  var randomness = Math.random() * 2;\n  var exponent = Math.pow(2, localStorage.requestFailureCount || 0);\n  var multiplier = Math.max(randomness * exponent, 1);\n  var delay = Math.min(multiplier * pollIntervalMin, pollIntervalMax);\n  delay = Math.round(delay);\n  console.log('Scheduling for: ' + delay);\n\n  if (oldChromeVersion) {\n    if (requestTimerId) {\n      window.clearTimeout(requestTimerId);\n    }\n    requestTimerId = window.setTimeout(onAlarm, delay*60*1000);\n  } else {\n    console.log('Creating alarm');\n    // Use a repeating alarm so that it fires again if there was a problem\n    // setting the next alarm.\n    chrome.alarms.create('refresh', {periodInMinutes: delay});\n  }\n}\n\n// ajax stuff\nfunction startRequest(params) {\n  // Schedule request immediately. We want to be sure to reschedule, even in the\n  // case where the extension process shuts down while this request is\n  // outstanding.\n  if (params && params.scheduleRequest) scheduleRequest();\n\n  function stopLoadingAnimation() {\n    if (params && params.showLoadingAnimation) loadingAnimation.stop();\n  }\n\n  if (params && params.showLoadingAnimation)\n    loadingAnimation.start();\n\n  getInboxCount(\n    function(count) {\n      stopLoadingAnimation();\n      updateUnreadCount(count);\n    },\n    function() {\n      stopLoadingAnimation();\n      delete localStorage.unreadCount;\n      updateIcon();\n    }\n  );\n}\n\nfunction getInboxCount(onSuccess, onError) {\n  var xhr = new XMLHttpRequest();\n  var abortTimerId = window.setTimeout(function() {\n    xhr.abort();  // synchronously calls onreadystatechange\n  }, requestTimeout);\n\n  function handleSuccess(count) {\n    localStorage.requestFailureCount = 0;\n    window.clearTimeout(abortTimerId);\n    if (onSuccess)\n      onSuccess(count);\n  }\n\n  var invokedErrorCallback = false;\n  function handleError() {\n    ++localStorage.requestFailureCount;\n    window.clearTimeout(abortTimerId);\n    if (onError && !invokedErrorCallback)\n      onError();\n    invokedErrorCallback = true;\n  }\n\n  try {\n    xhr.onreadystatechange = function() {\n      if (xhr.readyState != 4)\n        return;\n\n      if (xhr.responseXML) {\n        var xmlDoc = xhr.responseXML;\n        var fullCountSet = xmlDoc.evaluate(\"/gmail:feed/gmail:fullcount\",\n            xmlDoc, gmailNSResolver, XPathResult.ANY_TYPE, null);\n        var fullCountNode = fullCountSet.iterateNext();\n        if (fullCountNode) {\n          handleSuccess(fullCountNode.textContent);\n          return;\n        } else {\n          console.error(chrome.i18n.getMessage(\"gmailcheck_node_error\"));\n        }\n      }\n\n      handleError();\n    };\n\n    xhr.onerror = function(error) {\n      handleError();\n    };\n\n    xhr.open(\"GET\", getFeedUrl(), true);\n    xhr.send(null);\n  } catch(e) {\n    console.error(chrome.i18n.getMessage(\"gmailcheck_exception\", e));\n    handleError();\n  }\n}\n\nfunction gmailNSResolver(prefix) {\n  if(prefix == 'gmail') {\n    return 'http://purl.org/atom/ns#';\n  }\n}\n\nfunction updateUnreadCount(count) {\n  var changed = localStorage.unreadCount != count;\n  localStorage.unreadCount = count;\n  updateIcon();\n  if (changed)\n    animateFlip();\n}\n\n\nfunction ease(x) {\n  return (1-Math.sin(Math.PI/2+x*Math.PI))/2;\n}\n\nfunction animateFlip() {\n  rotation += 1/animationFrames;\n  drawIconAtRotation();\n\n  if (rotation <= 1) {\n    setTimeout(animateFlip, animationSpeed);\n  } else {\n    rotation = 0;\n    updateIcon();\n  }\n}\n\nfunction drawIconAtRotation() {\n  canvasContext.save();\n  canvasContext.clearRect(0, 0, canvas.width, canvas.height);\n  canvasContext.translate(\n      Math.ceil(canvas.width/2),\n      Math.ceil(canvas.height/2));\n  canvasContext.rotate(2*Math.PI*ease(rotation));\n  canvasContext.drawImage(loggedInImage,\n      -Math.ceil(canvas.width/2),\n      -Math.ceil(canvas.height/2));\n  canvasContext.restore();\n\n  chrome.browserAction.setIcon({imageData:canvasContext.getImageData(0, 0,\n      canvas.width,canvas.height)});\n}\n\nfunction goToInbox() {\n  console.log('Going to inbox...');\n  chrome.tabs.getAllInWindow(undefined, function(tabs) {\n    for (var i = 0, tab; tab = tabs[i]; i++) {\n      if (tab.url && isGmailUrl(tab.url)) {\n        console.log('Found Gmail tab: ' + tab.url + '. ' +\n                    'Focusing and refreshing count...');\n        chrome.tabs.update(tab.id, {selected: true});\n        startRequest({scheduleRequest:false, showLoadingAnimation:false});\n        return;\n      }\n    }\n    console.log('Could not find Gmail tab. Creating one...');\n    chrome.tabs.create({url: getGmailUrl()});\n  });\n}\n\nfunction onInit() {\n  console.log('onInit');\n  localStorage.requestFailureCount = 0;  // used for exponential backoff\n  startRequest({scheduleRequest:true, showLoadingAnimation:true});\n  if (!oldChromeVersion) {\n    // TODO(mpcomplete): We should be able to remove this now, but leaving it\n    // for a little while just to be sure the refresh alarm is working nicely.\n    chrome.alarms.create('watchdog', {periodInMinutes:5});\n  }\n}\n\nfunction onAlarm(alarm) {\n  console.log('Got alarm', alarm);\n  // |alarm| can be undefined because onAlarm also gets called from\n  // window.setTimeout on old chrome versions.\n  if (alarm && alarm.name == 'watchdog') {\n    onWatchdog();\n  } else {\n    startRequest({scheduleRequest:true, showLoadingAnimation:false});\n  }\n}\n\nfunction onWatchdog() {\n  chrome.alarms.get('refresh', function(alarm) {\n    if (alarm) {\n      console.log('Refresh alarm exists. Yay.');\n    } else {\n      console.log('Refresh alarm doesn\\'t exist!? ' +\n                  'Refreshing now and rescheduling.');\n      startRequest({scheduleRequest:true, showLoadingAnimation:false});\n    }\n  });\n}\n\nif (oldChromeVersion) {\n  updateIcon();\n  onInit();\n} else {\n  chrome.runtime.onInstalled.addListener(onInit);\n  chrome.alarms.onAlarm.addListener(onAlarm);\n}\n\nvar filters = {\n  // TODO(aa): Cannot use urlPrefix because all the url fields lack the protocol\n  // part. See crbug.com/140238.\n  url: [{urlContains: getGmailUrl().replace(/^https?\\:\\/\\//, '')}]\n};\n\nfunction onNavigate(details) {\n  if (details.url && isGmailUrl(details.url)) {\n    console.log('Recognized Gmail navigation to: ' + details.url + '.' +\n                'Refreshing count...');\n    startRequest({scheduleRequest:false, showLoadingAnimation:false});\n  }\n}\nif (chrome.webNavigation && chrome.webNavigation.onDOMContentLoaded &&\n    chrome.webNavigation.onReferenceFragmentUpdated) {\n  chrome.webNavigation.onDOMContentLoaded.addListener(onNavigate, filters);\n  chrome.webNavigation.onReferenceFragmentUpdated.addListener(\n      onNavigate, filters);\n} else {\n  chrome.tabs.onUpdated.addListener(function(_, details) {\n    onNavigate(details);\n  });\n}\n\nchrome.browserAction.onClicked.addListener(goToInbox);\n\nif (chrome.runtime && chrome.runtime.onStartup) {\n  chrome.runtime.onStartup.addListener(function() {\n    console.log('Starting browser... updating icon.');\n    startRequest({scheduleRequest:false, showLoadingAnimation:false});\n    updateIcon();\n  });\n} else {\n  // This hack is needed because Chrome 22 does not persist browserAction icon\n  // state, and also doesn't expose onStartup. So the icon always starts out in\n  // wrong state. We don't actually use onStartup except as a clue that we're\n  // in a version of Chrome that has this problem.\n  chrome.windows.onCreated.addListener(function() {\n    console.log('Window created... updating icon.');\n    startRequest({scheduleRequest:false, showLoadingAnimation:false});\n    updateIcon();\n  });\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/gmail/manifest.json",
    "content": "{\n  \"background\": {\n    \"persistent\": false,\n    \"page\": \"background.html\"\n  },\n  \"browser_action\": {\n    \"default_icon\": \"gmail_not_logged_in.png\"\n  },\n  \"default_locale\": \"en\",\n  \"description\": \"__MSG_gmailcheck_description__\",\n  \"icons\": {\n    \"128\": \"icon_128.png\"\n  },\n  \"name\": \"__MSG_gmailcheck_name__\",\n  \"permissions\": [\n    \"alarms\",\n    \"tabs\",\n    \"webNavigation\",\n    \"*://*.google.com/\"\n   ],\n  \"version\": \"4.4.0\",\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/imageinfo/NOTICE",
    "content": "This extension uses code from the following JavaScript library:\n\nImageInfo - A JavaScript library for reading image metadata.\nCopyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\nMIT License [http://www.nihilogic.dk/licenses/mit-license.txt]\n"
  },
  {
    "path": "_archive/mv2/extensions/imageinfo/background.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * Returns a handler which will open a new window when activated.\n */\nfunction getClickHandler() {\n  return function(info, tab) {\n\n    // The srcUrl property is only available for image elements.\n    var url = 'info.html#' + info.srcUrl;\n\n    // Create a new window to the info page.\n    chrome.windows.create({ url: url, width: 520, height: 660 });\n  };\n};\n\n/**\n * Create a context menu which will only show up for images.\n */\nchrome.contextMenus.create({\n  \"title\" : \"Get image info\",\n  \"type\" : \"normal\",\n  \"contexts\" : [\"image\"],\n  \"onclick\" : getClickHandler()\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/imageinfo/imageinfo/binaryajax.js",
    "content": "\n/*\n * Binary Ajax 0.1.5\n * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com, http://blog.nihilogic.dk/\n * MIT License [http://www.opensource.org/licenses/mit-license.php]\n */\n\n\nvar BinaryFile = function(strData, iDataOffset, iDataLength) {\n  var data = strData;\n  var dataOffset = iDataOffset || 0;\n  var dataLength = 0;\n\n  this.getRawData = function() {\n    return data;\n  }\n\n  if (typeof strData == \"string\") {\n    dataLength = iDataLength || data.length;\n\n    this.getByteAt = function(iOffset) {\n      return data.charCodeAt(iOffset + dataOffset) & 0xFF;\n    }\n  } else if (typeof strData == \"unknown\") {\n    dataLength = iDataLength || IEBinary_getLength(data);\n\n    this.getByteAt = function(iOffset) {\n      return IEBinary_getByteAt(data, iOffset + dataOffset);\n    }\n  }\n\n  this.getLength = function() {\n    return dataLength;\n  }\n\n  this.getSByteAt = function(iOffset) {\n    var iByte = this.getByteAt(iOffset);\n    if (iByte > 127)\n      return iByte - 256;\n    else\n      return iByte;\n  }\n\n  this.getShortAt = function(iOffset, bBigEndian) {\n    var iShort = bBigEndian ?\n      (this.getByteAt(iOffset) << 8) + this.getByteAt(iOffset + 1)\n      : (this.getByteAt(iOffset + 1) << 8) + this.getByteAt(iOffset)\n    if (iShort < 0) iShort += 65536;\n    return iShort;\n  }\n  this.getSShortAt = function(iOffset, bBigEndian) {\n    var iUShort = this.getShortAt(iOffset, bBigEndian);\n    if (iUShort > 32767)\n      return iUShort - 65536;\n    else\n      return iUShort;\n  }\n  this.getLongAt = function(iOffset, bBigEndian) {\n    var iByte1 = this.getByteAt(iOffset),\n      iByte2 = this.getByteAt(iOffset + 1),\n      iByte3 = this.getByteAt(iOffset + 2),\n      iByte4 = this.getByteAt(iOffset + 3);\n\n    var iLong = bBigEndian ?\n      (((((iByte1 << 8) + iByte2) << 8) + iByte3) << 8) + iByte4\n      : (((((iByte4 << 8) + iByte3) << 8) + iByte2) << 8) + iByte1;\n    if (iLong < 0) iLong += 4294967296;\n    return iLong;\n  }\n  this.getSLongAt = function(iOffset, bBigEndian) {\n    var iULong = this.getLongAt(iOffset, bBigEndian);\n    if (iULong > 2147483647)\n      return iULong - 4294967296;\n    else\n      return iULong;\n  }\n  this.getStringAt = function(iOffset, iLength) {\n    var aStr = [];\n    for (var i=iOffset,j=0;i<iOffset+iLength;i++,j++) {\n      aStr[j] = String.fromCharCode(this.getByteAt(i));\n    }\n    return aStr.join(\"\");\n  }\n\n  this.getCharAt = function(iOffset) {\n    return String.fromCharCode(this.getByteAt(iOffset));\n  }\n  this.toBase64 = function() {\n    return window.btoa(data);\n  }\n  this.fromBase64 = function(strBase64) {\n    data = window.atob(strBase64);\n  }\n}\n\n\nvar BinaryAjax = (function() {\n\n  function createRequest() {\n    var oHTTP = null;\n    if (window.XMLHttpRequest) {\n      oHTTP = new XMLHttpRequest();\n    } else if (window.ActiveXObject) {\n      oHTTP = new ActiveXObject(\"Microsoft.XMLHTTP\");\n    }\n    return oHTTP;\n  }\n\n  function getHead(strURL, fncCallback, fncError) {\n    var oHTTP = createRequest();\n    if (oHTTP) {\n      if (fncCallback) {\n        if (typeof(oHTTP.onload) != \"undefined\") {\n          oHTTP.onload = function() {\n            if (oHTTP.status == \"200\") {\n              fncCallback(this);\n            } else {\n              if (fncError) fncError();\n            }\n            oHTTP = null;\n          };\n        } else {\n          oHTTP.onreadystatechange = function() {\n            if (oHTTP.readyState == 4) {\n              if (oHTTP.status == \"200\") {\n                fncCallback(this);\n              } else {\n                if (fncError) fncError();\n              }\n              oHTTP = null;\n            }\n          };\n        }\n      }\n      oHTTP.open(\"HEAD\", strURL, true);\n      oHTTP.send(null);\n    } else {\n      if (fncError) fncError();\n    }\n  }\n\n  function sendRequest(strURL, fncCallback, fncError, aRange, bAcceptRanges, iFileSize) {\n    var oHTTP = createRequest();\n    if (oHTTP) {\n\n      var iDataOffset = 0;\n      if (aRange && !bAcceptRanges) {\n        iDataOffset = aRange[0];\n      }\n      var iDataLen = 0;\n      if (aRange) {\n        iDataLen = aRange[1]-aRange[0]+1;\n      }\n\n      if (fncCallback) {\n        if (typeof(oHTTP.onload) != \"undefined\") {\n          oHTTP.onload = function() {\n\n            if (oHTTP.status == \"200\" || oHTTP.status == \"206\") {\n              this.binaryResponse = new BinaryFile(this.responseText, iDataOffset, iDataLen);\n              this.fileSize = iFileSize || this.getResponseHeader(\"Content-Length\");\n              fncCallback(this);\n            } else {\n              if (fncError) fncError();\n            }\n            oHTTP = null;\n          };\n        } else {\n          oHTTP.onreadystatechange = function() {\n            if (oHTTP.readyState == 4) {\n              if (oHTTP.status == \"200\" || oHTTP.status == \"206\") {\n                this.binaryResponse = new BinaryFile(oHTTP.responseBody, iDataOffset, iDataLen);\n                this.fileSize = iFileSize || this.getResponseHeader(\"Content-Length\");\n                fncCallback(this);\n              } else {\n                if (fncError) fncError();\n              }\n              oHTTP = null;\n            }\n          };\n        }\n      }\n      oHTTP.open(\"GET\", strURL, true);\n\n      if (oHTTP.overrideMimeType) oHTTP.overrideMimeType('text/plain; charset=x-user-defined');\n\n      if (aRange && bAcceptRanges) {\n        oHTTP.setRequestHeader(\"Range\", \"bytes=\" + aRange[0] + \"-\" + aRange[1]);\n      }\n\n      oHTTP.setRequestHeader(\"If-Modified-Since\", \"Sat, 1 Jan 1970 00:00:00 GMT\");\n\n      oHTTP.send(null);\n    } else {\n      if (fncError) fncError();\n    }\n  }\n\n  return function(strURL, fncCallback, fncError, aRange) {\n\n    if (aRange) {\n      getHead(\n        strURL,\n        function(oHTTP) {\n          var iLength = parseInt(oHTTP.getResponseHeader(\"Content-Length\"),10);\n          var strAcceptRanges = oHTTP.getResponseHeader(\"Accept-Ranges\");\n\n          var iStart, iEnd;\n          iStart = aRange[0];\n          if (aRange[0] < 0)\n            iStart += iLength;\n          iEnd = iStart + aRange[1] - 1;\n\n          sendRequest(strURL, fncCallback, fncError, [iStart, iEnd], (strAcceptRanges == \"bytes\"), iLength);\n        }\n      );\n\n    } else {\n      sendRequest(strURL, fncCallback, fncError);\n    }\n  }\n\n}());\n\n\ndocument.write(\n  \"<script type='text/vbscript'>\\r\\n\"\n  + \"Function IEBinary_getByteAt(strBinary, iOffset)\\r\\n\"\n  + \"\tIEBinary_getByteAt = AscB(MidB(strBinary,iOffset+1,1))\\r\\n\"\n  + \"End Function\\r\\n\"\n  + \"Function IEBinary_getLength(strBinary)\\r\\n\"\n  + \"\tIEBinary_getLength = LenB(strBinary)\\r\\n\"\n  + \"End Function\\r\\n\"\n  + \"</script>\\r\\n\"\n);\n"
  },
  {
    "path": "_archive/mv2/extensions/imageinfo/imageinfo/exif.js",
    "content": "/*\n * Javascript EXIF Reader 0.1.2\n * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com, http://blog.nihilogic.dk/\n * MIT License [http://www.opensource.org/licenses/mit-license.php]\n */\n\n\nvar EXIF = {};\n\n(function() {\n\nvar bDebug = false;\n\nEXIF.Tags = {\n\n  // version tags\n  0x9000 : \"ExifVersion\",\t\t\t// EXIF version\n  0xA000 : \"FlashpixVersion\",\t\t// Flashpix format version\n\n  // colorspace tags\n  0xA001 : \"ColorSpace\",\t\t\t// Color space information tag\n\n  // image configuration\n  0xA002 : \"PixelXDimension\",\t\t// Valid width of meaningful image\n  0xA003 : \"PixelYDimension\",\t\t// Valid height of meaningful image\n  0x9101 : \"ComponentsConfiguration\",\t// Information about channels\n  0x9102 : \"CompressedBitsPerPixel\",\t// Compressed bits per pixel\n\n  // user information\n  0x927C : \"MakerNote\",\t\t\t// Any desired information written by the manufacturer\n  0x9286 : \"UserComment\",\t\t\t// Comments by user\n\n  // related file\n  0xA004 : \"RelatedSoundFile\",\t\t// Name of related sound file\n\n  // date and time\n  0x9003 : \"DateTimeOriginal\",\t\t// Date and time when the original image was generated\n  0x9004 : \"DateTimeDigitized\",\t\t// Date and time when the image was stored digitally\n  0x9290 : \"SubsecTime\",\t\t\t// Fractions of seconds for DateTime\n  0x9291 : \"SubsecTimeOriginal\",\t\t// Fractions of seconds for DateTimeOriginal\n  0x9292 : \"SubsecTimeDigitized\",\t\t// Fractions of seconds for DateTimeDigitized\n\n  // picture-taking conditions\n  0x829A : \"ExposureTime\",\t\t// Exposure time (in seconds)\n  0x829D : \"FNumber\",\t\t\t// F number\n  0x8822 : \"ExposureProgram\",\t\t// Exposure program\n  0x8824 : \"SpectralSensitivity\",\t\t// Spectral sensitivity\n  0x8827 : \"ISOSpeedRatings\",\t\t// ISO speed rating\n  0x8828 : \"OECF\",\t\t\t// Optoelectric conversion factor\n  0x9201 : \"ShutterSpeedValue\",\t\t// Shutter speed\n  0x9202 : \"ApertureValue\",\t\t// Lens aperture\n  0x9203 : \"BrightnessValue\",\t\t// Value of brightness\n  0x9204 : \"ExposureBias\",\t\t// Exposure bias\n  0x9205 : \"MaxApertureValue\",\t\t// Smallest F number of lens\n  0x9206 : \"SubjectDistance\",\t\t// Distance to subject in meters\n  0x9207 : \"MeteringMode\", \t\t// Metering mode\n  0x9208 : \"LightSource\",\t\t\t// Kind of light source\n  0x9209 : \"Flash\",\t\t\t// Flash status\n  0x9214 : \"SubjectArea\",\t\t\t// Location and area of main subject\n  0x920A : \"FocalLength\",\t\t\t// Focal length of the lens in mm\n  0xA20B : \"FlashEnergy\",\t\t\t// Strobe energy in BCPS\n  0xA20C : \"SpatialFrequencyResponse\",\t//\n  0xA20E : \"FocalPlaneXResolution\", \t// Number of pixels in width direction per FocalPlaneResolutionUnit\n  0xA20F : \"FocalPlaneYResolution\", \t// Number of pixels in height direction per FocalPlaneResolutionUnit\n  0xA210 : \"FocalPlaneResolutionUnit\", \t// Unit for measuring FocalPlaneXResolution and FocalPlaneYResolution\n  0xA214 : \"SubjectLocation\",\t\t// Location of subject in image\n  0xA215 : \"ExposureIndex\",\t\t// Exposure index selected on camera\n  0xA217 : \"SensingMethod\", \t\t// Image sensor type\n  0xA300 : \"FileSource\", \t\t\t// Image source (3 == DSC)\n  0xA301 : \"SceneType\", \t\t\t// Scene type (1 == directly photographed)\n  0xA302 : \"CFAPattern\",\t\t\t// Color filter array geometric pattern\n  0xA401 : \"CustomRendered\",\t\t// Special processing\n  0xA402 : \"ExposureMode\",\t\t// Exposure mode\n  0xA403 : \"WhiteBalance\",\t\t// 1 = auto white balance, 2 = manual\n  0xA404 : \"DigitalZoomRation\",\t\t// Digital zoom ratio\n  0xA405 : \"FocalLengthIn35mmFilm\",\t// Equivalent foacl length assuming 35mm film camera (in mm)\n  0xA406 : \"SceneCaptureType\",\t\t// Type of scene\n  0xA407 : \"GainControl\",\t\t\t// Degree of overall image gain adjustment\n  0xA408 : \"Contrast\",\t\t\t// Direction of contrast processing applied by camera\n  0xA409 : \"Saturation\", \t\t\t// Direction of saturation processing applied by camera\n  0xA40A : \"Sharpness\",\t\t\t// Direction of sharpness processing applied by camera\n  0xA40B : \"DeviceSettingDescription\",\t//\n  0xA40C : \"SubjectDistanceRange\",\t// Distance to subject\n\n  // other tags\n  0xA005 : \"InteroperabilityIFDPointer\",\n  0xA420 : \"ImageUniqueID\"\t\t// Identifier assigned uniquely to each image\n};\n\nEXIF.TiffTags = {\n  0x0100 : \"ImageWidth\",\n  0x0101 : \"ImageHeight\",\n  0x8769 : \"ExifIFDPointer\",\n  0x8825 : \"GPSInfoIFDPointer\",\n  0xA005 : \"InteroperabilityIFDPointer\",\n  0x0102 : \"BitsPerSample\",\n  0x0103 : \"Compression\",\n  0x0106 : \"PhotometricInterpretation\",\n  0x0112 : \"Orientation\",\n  0x0115 : \"SamplesPerPixel\",\n  0x011C : \"PlanarConfiguration\",\n  0x0212 : \"YCbCrSubSampling\",\n  0x0213 : \"YCbCrPositioning\",\n  0x011A : \"XResolution\",\n  0x011B : \"YResolution\",\n  0x0128 : \"ResolutionUnit\",\n  0x0111 : \"StripOffsets\",\n  0x0116 : \"RowsPerStrip\",\n  0x0117 : \"StripByteCounts\",\n  0x0201 : \"JPEGInterchangeFormat\",\n  0x0202 : \"JPEGInterchangeFormatLength\",\n  0x012D : \"TransferFunction\",\n  0x013E : \"WhitePoint\",\n  0x013F : \"PrimaryChromaticities\",\n  0x0211 : \"YCbCrCoefficients\",\n  0x0214 : \"ReferenceBlackWhite\",\n  0x0132 : \"DateTime\",\n  0x010E : \"ImageDescription\",\n  0x010F : \"Make\",\n  0x0110 : \"Model\",\n  0x0131 : \"Software\",\n  0x013B : \"Artist\",\n  0x8298 : \"Copyright\"\n}\n\nEXIF.GPSTags = {\n  0x0000 : \"GPSVersionID\",\n  0x0001 : \"GPSLatitudeRef\",\n  0x0002 : \"GPSLatitude\",\n  0x0003 : \"GPSLongitudeRef\",\n  0x0004 : \"GPSLongitude\",\n  0x0005 : \"GPSAltitudeRef\",\n  0x0006 : \"GPSAltitude\",\n  0x0007 : \"GPSTimeStamp\",\n  0x0008 : \"GPSSatellites\",\n  0x0009 : \"GPSStatus\",\n  0x000A : \"GPSMeasureMode\",\n  0x000B : \"GPSDOP\",\n  0x000C : \"GPSSpeedRef\",\n  0x000D : \"GPSSpeed\",\n  0x000E : \"GPSTrackRef\",\n  0x000F : \"GPSTrack\",\n  0x0010 : \"GPSImgDirectionRef\",\n  0x0011 : \"GPSImgDirection\",\n  0x0012 : \"GPSMapDatum\",\n  0x0013 : \"GPSDestLatitudeRef\",\n  0x0014 : \"GPSDestLatitude\",\n  0x0015 : \"GPSDestLongitudeRef\",\n  0x0016 : \"GPSDestLongitude\",\n  0x0017 : \"GPSDestBearingRef\",\n  0x0018 : \"GPSDestBearing\",\n  0x0019 : \"GPSDestDistanceRef\",\n  0x001A : \"GPSDestDistance\",\n  0x001B : \"GPSProcessingMethod\",\n  0x001C : \"GPSAreaInformation\",\n  0x001D : \"GPSDateStamp\",\n  0x001E : \"GPSDifferential\"\n}\n\nEXIF.StringValues = {\n  ExposureProgram : {\n    0 : \"Not defined\",\n    1 : \"Manual\",\n    2 : \"Normal program\",\n    3 : \"Aperture priority\",\n    4 : \"Shutter priority\",\n    5 : \"Creative program\",\n    6 : \"Action program\",\n    7 : \"Portrait mode\",\n    8 : \"Landscape mode\"\n  },\n  MeteringMode : {\n    0 : \"Unknown\",\n    1 : \"Average\",\n    2 : \"CenterWeightedAverage\",\n    3 : \"Spot\",\n    4 : \"MultiSpot\",\n    5 : \"Pattern\",\n    6 : \"Partial\",\n    255 : \"Other\"\n  },\n  LightSource : {\n    0 : \"Unknown\",\n    1 : \"Daylight\",\n    2 : \"Fluorescent\",\n    3 : \"Tungsten (incandescent light)\",\n    4 : \"Flash\",\n    9 : \"Fine weather\",\n    10 : \"Cloudy weather\",\n    11 : \"Shade\",\n    12 : \"Daylight fluorescent (D 5700 - 7100K)\",\n    13 : \"Day white fluorescent (N 4600 - 5400K)\",\n    14 : \"Cool white fluorescent (W 3900 - 4500K)\",\n    15 : \"White fluorescent (WW 3200 - 3700K)\",\n    17 : \"Standard light A\",\n    18 : \"Standard light B\",\n    19 : \"Standard light C\",\n    20 : \"D55\",\n    21 : \"D65\",\n    22 : \"D75\",\n    23 : \"D50\",\n    24 : \"ISO studio tungsten\",\n    255 : \"Other\"\n  },\n  Flash : {\n    0x0000 : \"Flash did not fire\",\n    0x0001 : \"Flash fired\",\n    0x0005 : \"Strobe return light not detected\",\n    0x0007 : \"Strobe return light detected\",\n    0x0009 : \"Flash fired, compulsory flash mode\",\n    0x000D : \"Flash fired, compulsory flash mode, return light not detected\",\n    0x000F : \"Flash fired, compulsory flash mode, return light detected\",\n    0x0010 : \"Flash did not fire, compulsory flash mode\",\n    0x0018 : \"Flash did not fire, auto mode\",\n    0x0019 : \"Flash fired, auto mode\",\n    0x001D : \"Flash fired, auto mode, return light not detected\",\n    0x001F : \"Flash fired, auto mode, return light detected\",\n    0x0020 : \"No flash function\",\n    0x0041 : \"Flash fired, red-eye reduction mode\",\n    0x0045 : \"Flash fired, red-eye reduction mode, return light not detected\",\n    0x0047 : \"Flash fired, red-eye reduction mode, return light detected\",\n    0x0049 : \"Flash fired, compulsory flash mode, red-eye reduction mode\",\n    0x004D : \"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected\",\n    0x004F : \"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected\",\n    0x0059 : \"Flash fired, auto mode, red-eye reduction mode\",\n    0x005D : \"Flash fired, auto mode, return light not detected, red-eye reduction mode\",\n    0x005F : \"Flash fired, auto mode, return light detected, red-eye reduction mode\"\n  },\n  SensingMethod : {\n    1 : \"Not defined\",\n    2 : \"One-chip color area sensor\",\n    3 : \"Two-chip color area sensor\",\n    4 : \"Three-chip color area sensor\",\n    5 : \"Color sequential area sensor\",\n    7 : \"Trilinear sensor\",\n    8 : \"Color sequential linear sensor\"\n  },\n  SceneCaptureType : {\n    0 : \"Standard\",\n    1 : \"Landscape\",\n    2 : \"Portrait\",\n    3 : \"Night scene\"\n  },\n  SceneType : {\n    1 : \"Directly photographed\"\n  },\n  CustomRendered : {\n    0 : \"Normal process\",\n    1 : \"Custom process\"\n  },\n  WhiteBalance : {\n    0 : \"Auto white balance\",\n    1 : \"Manual white balance\"\n  },\n  GainControl : {\n    0 : \"None\",\n    1 : \"Low gain up\",\n    2 : \"High gain up\",\n    3 : \"Low gain down\",\n    4 : \"High gain down\"\n  },\n  Contrast : {\n    0 : \"Normal\",\n    1 : \"Soft\",\n    2 : \"Hard\"\n  },\n  Saturation : {\n    0 : \"Normal\",\n    1 : \"Low saturation\",\n    2 : \"High saturation\"\n  },\n  Sharpness : {\n    0 : \"Normal\",\n    1 : \"Soft\",\n    2 : \"Hard\"\n  },\n  SubjectDistanceRange : {\n    0 : \"Unknown\",\n    1 : \"Macro\",\n    2 : \"Close view\",\n    3 : \"Distant view\"\n  },\n  FileSource : {\n    3 : \"DSC\"\n  },\n\n  Components : {\n    0 : \"\",\n    1 : \"Y\",\n    2 : \"Cb\",\n    3 : \"Cr\",\n    4 : \"R\",\n    5 : \"G\",\n    6 : \"B\"\n  }\n}\n\nfunction addEvent(oElement, strEvent, fncHandler)\n{\n  if (oElement.addEventListener) {\n    oElement.addEventListener(strEvent, fncHandler, false);\n  } else if (oElement.attachEvent) {\n    oElement.attachEvent(\"on\" + strEvent, fncHandler);\n  }\n}\n\n\nfunction imageHasData(oImg)\n{\n  return !!(oImg.exifdata);\n}\n\nfunction getImageData(oImg, fncCallback)\n{\n  BinaryAjax(\n    oImg.src,\n    function(oHTTP) {\n      var oEXIF = findEXIFinJPEG(oHTTP.binaryResponse);\n      oImg.exifdata = oEXIF || {};\n      if (fncCallback) fncCallback();\n    }\n  )\n}\n\nfunction findEXIFinJPEG(oFile) {\n  var aMarkers = [];\n\n  if (oFile.getByteAt(0) != 0xFF || oFile.getByteAt(1) != 0xD8) {\n    return false; // not a valid jpeg\n  }\n\n  var iOffset = 2;\n  var iLength = oFile.getLength();\n  while (iOffset < iLength) {\n    if (oFile.getByteAt(iOffset) != 0xFF) {\n      if (bDebug) console.log(\"Not a valid marker at offset \" + iOffset + \", found: \" + oFile.getByteAt(iOffset));\n      return false; // not a valid marker, something is wrong\n    }\n\n    var iMarker = oFile.getByteAt(iOffset+1);\n\n    // we could implement handling for other markers here,\n    // but we're only looking for 0xFFE1 for EXIF data\n\n    if (iMarker == 22400) {\n      if (bDebug) console.log(\"Found 0xFFE1 marker\");\n      return readEXIFData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2);\n      iOffset += 2 + oFile.getShortAt(iOffset+2, true);\n\n    } else if (iMarker == 225) {\n      // 0xE1 = Application-specific 1 (for EXIF)\n      if (bDebug) console.log(\"Found 0xFFE1 marker\");\n      return readEXIFData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2);\n\n    } else {\n      iOffset += 2 + oFile.getShortAt(iOffset+2, true);\n    }\n\n  }\n\n}\n\n\nfunction readTags(oFile, iTIFFStart, iDirStart, oStrings, bBigEnd)\n{\n  var iEntries = oFile.getShortAt(iDirStart, bBigEnd);\n  var oTags = {};\n  for (var i=0;i<iEntries;i++) {\n    var iEntryOffset = iDirStart + i*12 + 2;\n    var strTag = oStrings[oFile.getShortAt(iEntryOffset, bBigEnd)];\n    if (!strTag && bDebug) console.log(\"Unknown tag: \" + oFile.getShortAt(iEntryOffset, bBigEnd));\n    oTags[strTag] = readTagValue(oFile, iEntryOffset, iTIFFStart, iDirStart, bBigEnd);\n  }\n  return oTags;\n}\n\n\nfunction readTagValue(oFile, iEntryOffset, iTIFFStart, iDirStart, bBigEnd)\n{\n  var iType = oFile.getShortAt(iEntryOffset+2, bBigEnd);\n  var iNumValues = oFile.getLongAt(iEntryOffset+4, bBigEnd);\n  var iValueOffset = oFile.getLongAt(iEntryOffset+8, bBigEnd) + iTIFFStart;\n\n  switch (iType) {\n    case 1: // byte, 8-bit unsigned int\n    case 7: // undefined, 8-bit byte, value depending on field\n      if (iNumValues == 1) {\n        return oFile.getByteAt(iEntryOffset + 8, bBigEnd);\n      } else {\n        var iValOffset = iNumValues > 4 ? iValueOffset : (iEntryOffset + 8);\n        var aVals = [];\n        for (var n=0;n<iNumValues;n++) {\n          aVals[n] = oFile.getByteAt(iValOffset + n);\n        }\n        return aVals;\n      }\n      break;\n\n    case 2: // ascii, 8-bit byte\n      var iStringOffset = iNumValues > 4 ? iValueOffset : (iEntryOffset + 8);\n      return oFile.getStringAt(iStringOffset, iNumValues-1);\n      break;\n\n    case 3: // short, 16 bit int\n      if (iNumValues == 1) {\n        return oFile.getShortAt(iEntryOffset + 8, bBigEnd);\n      } else {\n        var iValOffset = iNumValues > 2 ? iValueOffset : (iEntryOffset + 8);\n        var aVals = [];\n        for (var n=0;n<iNumValues;n++) {\n          aVals[n] = oFile.getShortAt(iValOffset + 2*n, bBigEnd);\n        }\n        return aVals;\n      }\n      break;\n\n    case 4: // long, 32 bit int\n      if (iNumValues == 1) {\n        return oFile.getLongAt(iEntryOffset + 8, bBigEnd);\n      } else {\n        var aVals = [];\n        for (var n=0;n<iNumValues;n++) {\n          aVals[n] = oFile.getLongAt(iValueOffset + 4*n, bBigEnd);\n        }\n        return aVals;\n      }\n      break;\n    case 5:\t// rational = two long values, first is numerator, second is denominator\n      if (iNumValues == 1) {\n        return oFile.getLongAt(iValueOffset, bBigEnd) / oFile.getLongAt(iValueOffset+4, bBigEnd);\n      } else {\n        var aVals = [];\n        for (var n=0;n<iNumValues;n++) {\n          aVals[n] = oFile.getLongAt(iValueOffset + 8*n, bBigEnd) / oFile.getLongAt(iValueOffset+4 + 8*n, bBigEnd);\n        }\n        return aVals;\n      }\n      break;\n    case 9: // slong, 32 bit signed int\n      if (iNumValues == 1) {\n        return oFile.getSLongAt(iEntryOffset + 8, bBigEnd);\n      } else {\n        var aVals = [];\n        for (var n=0;n<iNumValues;n++) {\n          aVals[n] = oFile.getSLongAt(iValueOffset + 4*n, bBigEnd);\n        }\n        return aVals;\n      }\n      break;\n    case 10: // signed rational, two slongs, first is numerator, second is denominator\n      if (iNumValues == 1) {\n        return oFile.getSLongAt(iValueOffset, bBigEnd) / oFile.getSLongAt(iValueOffset+4, bBigEnd);\n      } else {\n        var aVals = [];\n        for (var n=0;n<iNumValues;n++) {\n          aVals[n] = oFile.getSLongAt(iValueOffset + 8*n, bBigEnd) / oFile.getSLongAt(iValueOffset+4 + 8*n, bBigEnd);\n        }\n        return aVals;\n      }\n      break;\n  }\n}\n\n\nfunction readEXIFData(oFile, iStart, iLength)\n{\n  if (oFile.getStringAt(iStart, 4) != \"Exif\") {\n    if (bDebug) console.log(\"Not valid EXIF data! \" + oFile.getStringAt(iStart, 4));\n    return false;\n  }\n\n  var bBigEnd;\n\n  var iTIFFOffset = iStart + 6;\n\n  // test for TIFF validity and endianness\n  if (oFile.getShortAt(iTIFFOffset) == 0x4949) {\n    bBigEnd = false;\n  } else if (oFile.getShortAt(iTIFFOffset) == 0x4D4D) {\n    bBigEnd = true;\n  } else {\n    if (bDebug) console.log(\"Not valid TIFF data! (no 0x4949 or 0x4D4D)\");\n    return false;\n  }\n\n  if (oFile.getShortAt(iTIFFOffset+2, bBigEnd) != 0x002A) {\n    if (bDebug) console.log(\"Not valid TIFF data! (no 0x002A)\");\n    return false;\n  }\n\n  if (oFile.getLongAt(iTIFFOffset+4, bBigEnd) != 0x00000008) {\n    if (bDebug) console.log(\"Not valid TIFF data! (First offset not 8)\", oFile.getShortAt(iTIFFOffset+4, bBigEnd));\n    return false;\n  }\n\n  var oTags = readTags(oFile, iTIFFOffset, iTIFFOffset+8, EXIF.TiffTags, bBigEnd);\n\n  if (oTags.ExifIFDPointer) {\n    var oEXIFTags = readTags(oFile, iTIFFOffset, iTIFFOffset + oTags.ExifIFDPointer, EXIF.Tags, bBigEnd);\n    for (var strTag in oEXIFTags) {\n      switch (strTag) {\n        case \"LightSource\" :\n        case \"Flash\" :\n        case \"MeteringMode\" :\n        case \"ExposureProgram\" :\n        case \"SensingMethod\" :\n        case \"SceneCaptureType\" :\n        case \"SceneType\" :\n        case \"CustomRendered\" :\n        case \"WhiteBalance\" :\n        case \"GainControl\" :\n        case \"Contrast\" :\n        case \"Saturation\" :\n        case \"Sharpness\" :\n        case \"SubjectDistanceRange\" :\n        case \"FileSource\" :\n          oEXIFTags[strTag] = EXIF.StringValues[strTag][oEXIFTags[strTag]];\n          break;\n\n        case \"ExifVersion\" :\n        case \"FlashpixVersion\" :\n          oEXIFTags[strTag] = String.fromCharCode(oEXIFTags[strTag][0], oEXIFTags[strTag][1], oEXIFTags[strTag][2], oEXIFTags[strTag][3]);\n          break;\n\n        case \"ComponentsConfiguration\" :\n          oEXIFTags[strTag] =\n            EXIF.StringValues.Components[oEXIFTags[strTag][0]]\n            + EXIF.StringValues.Components[oEXIFTags[strTag][1]]\n            + EXIF.StringValues.Components[oEXIFTags[strTag][2]]\n            + EXIF.StringValues.Components[oEXIFTags[strTag][3]];\n          break;\n      }\n      oTags[strTag] = oEXIFTags[strTag];\n    }\n  }\n\n  if (oTags.GPSInfoIFDPointer) {\n    var oGPSTags = readTags(oFile, iTIFFOffset, iTIFFOffset + oTags.GPSInfoIFDPointer, EXIF.GPSTags, bBigEnd);\n    for (var strTag in oGPSTags) {\n      switch (strTag) {\n        case \"GPSVersionID\" :\n          oGPSTags[strTag] = oGPSTags[strTag][0]\n            + \".\" + oGPSTags[strTag][1]\n            + \".\" + oGPSTags[strTag][2]\n            + \".\" + oGPSTags[strTag][3];\n          break;\n      }\n      oTags[strTag] = oGPSTags[strTag];\n    }\n  }\n\n  return oTags;\n}\n\n\nEXIF.getData = function(oImg, fncCallback)\n{\n  if (!oImg.complete) return false;\n  if (!imageHasData(oImg)) {\n    getImageData(oImg, fncCallback);\n  } else {\n    if (fncCallback) fncCallback();\n  }\n  return true;\n}\n\nEXIF.getTag = function(oImg, strTag)\n{\n  if (!imageHasData(oImg)) return;\n  return oImg.exifdata[strTag];\n}\n\nEXIF.pretty = function(oImg)\n{\n  if (!imageHasData(oImg)) return \"\";\n  var oData = oImg.exifdata;\n  var strPretty = \"\";\n  for (var a in oData) {\n    if (oData.hasOwnProperty(a)) {\n      if (typeof oData[a] == \"object\") {\n        strPretty += a + \" : [\" + oData[a].length + \" values]\\r\\n\";\n      } else {\n        strPretty += a + \" : \" + oData[a] + \"\\r\\n\";\n      }\n    }\n  }\n  return strPretty;\n}\n\nEXIF.readFromBinaryFile = function(oFile) {\n  return findEXIFinJPEG(oFile);\n}\n\nfunction loadAllImages()\n{\n  var aImages = document.getElementsByTagName(\"img\");\n  for (var i=0;i<aImages.length;i++) {\n    if (aImages[i].getAttribute(\"exif\") == \"true\") {\n      if (!aImages[i].complete) {\n        addEvent(aImages[i], \"load\",\n          function() {\n            EXIF.getData(this);\n          }\n        );\n      } else {\n        EXIF.getData(aImages[i]);\n      }\n    }\n  }\n}\n\naddEvent(window, \"load\", loadAllImages);\n\n})();\n\n"
  },
  {
    "path": "_archive/mv2/extensions/imageinfo/imageinfo/imageinfo.js",
    "content": "/*\n * ImageInfo 0.1.2 - A JavaScript library for reading image metadata.\n * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\n * MIT License [http://www.nihilogic.dk/licenses/mit-license.txt]\n */\n\n\nvar ImageInfo = {};\n\nImageInfo.useRange = false;\nImageInfo.range = 10240;\n\n(function() {\n\n  var files = [];\n\n  function readFileData(url, callback) {\n    BinaryAjax(\n      url,\n      function(http) {\n        var tags = readInfoFromData(http.binaryResponse);\n        var mime = http.getResponseHeader(\"Content-Type\");\n\n        tags[\"mimeType\"] = mime;\n        tags[\"byteSize\"] = http.fileSize;\n\n        files[url] = tags;\n        if (callback) callback();\n      },\n      null,\n      ImageInfo.useRange ? [0, ImageInfo.range] : null\n    )\n  }\n\n  function readInfoFromData(data) {\n\n    var offset = 0;\n\n    if (data.getByteAt(0) == 0xFF && data.getByteAt(1) == 0xD8) {\n      return readJPEGInfo(data);\n    }\n    if (data.getByteAt(0) == 0x89 && data.getStringAt(1, 3) == \"PNG\") {\n      return readPNGInfo(data);\n    }\n    if (data.getStringAt(0,3) == \"GIF\") {\n      return readGIFInfo(data);\n    }\n    if (data.getByteAt(0) == 0x42 && data.getByteAt(1) == 0x4D) {\n      return readBMPInfo(data);\n    }\n    if (data.getByteAt(0) == 0x00 && data.getByteAt(1) == 0x00) {\n      return readICOInfo(data);\n    }\n\n    return {\n      format : \"UNKNOWN\"\n    };\n  }\n\n\n  function readPNGInfo(data) {\n    var w = data.getLongAt(16,true);\n    var h = data.getLongAt(20,true);\n\n    var bpc = data.getByteAt(24);\n    var ct = data.getByteAt(25);\n\n    var bpp = bpc;\n    if (ct == 4) bpp *= 2;\n    if (ct == 2) bpp *= 3;\n    if (ct == 6) bpp *= 4;\n\n    var alpha = data.getByteAt(25) >= 4;\n\n    return {\n      format : \"PNG\",\n      version : \"\",\n      width : w,\n      height : h,\n      bpp : bpp,\n      alpha : alpha,\n      exif : {}\n    }\n  }\n\n  function readGIFInfo(data) {\n    var version = data.getStringAt(3,3);\n    var w = data.getShortAt(6);\n    var h = data.getShortAt(8);\n\n    var bpp = ((data.getByteAt(10) >> 4) & 7) + 1;\n\n    return {\n      format : \"GIF\",\n      version : version,\n      width : w,\n      height : h,\n      bpp : bpp,\n      alpha : false,\n      exif : {}\n    }\n  }\n\n  function readJPEGInfo(data) {\n\n    var w = 0;\n    var h = 0;\n    var comps = 0;\n    var len = data.getLength();\n    var offset = 2;\n    while (offset < len) {\n      var marker = data.getShortAt(offset, true);\n      offset += 2;\n      if (marker == 0xFFC0) {\n        h = data.getShortAt(offset + 3, true);\n        w = data.getShortAt(offset + 5, true);\n        comps = data.getByteAt(offset + 7, true)\n        break;\n      } else {\n        offset += data.getShortAt(offset, true)\n      }\n    }\n\n    var exif = {};\n\n    if (typeof EXIF != \"undefined\" && EXIF.readFromBinaryFile) {\n      exif = EXIF.readFromBinaryFile(data);\n    }\n\n    return {\n      format : \"JPEG\",\n      version : \"\",\n      width : w,\n      height : h,\n      bpp : comps * 8,\n      alpha : false,\n      exif : exif\n    }\n  }\n\n  function readBMPInfo(data) {\n    var w = data.getLongAt(18);\n    var h = data.getLongAt(22);\n    var bpp = data.getShortAt(28);\n    return {\n      format : \"BMP\",\n      version : \"\",\n      width : w,\n      height : h,\n      bpp : bpp,\n      alpha : false,\n      exif : {}\n    }\n  }\n\n  ImageInfo.loadInfo = function(url, cb) {\n    if (!files[url]) {\n      readFileData(url, cb);\n    } else {\n      if (cb) cb();\n    }\n  }\n\n  ImageInfo.getAllFields = function(url) {\n    if (!files[url]) return null;\n\n    var tags = {};\n    for (var a in files[url]) {\n      if (files[url].hasOwnProperty(a))\n        tags[a] = files[url][a];\n    }\n    return tags;\n  }\n\n  ImageInfo.getField = function(url, field) {\n    if (!files[url]) return null;\n    return files[url][field];\n  }\n\n\n})();\n\n"
  },
  {
    "path": "_archive/mv2/extensions/imageinfo/imageinfo/readme.txt",
    "content": "\nImageInfo - A JavaScript library for reading image metadata.\nCopyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\nMIT License [http://www.nihilogic.dk/licenses/mit-license.txt]\n\nFor detailed information and code samples please refer to the blog post at:\nhttp://blog.nihilogic.dk/2008/07/imageinfo-reading-image-info-with-javascript.html\n"
  },
  {
    "path": "_archive/mv2/extensions/imageinfo/info.css",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nbody {\n  font: 14px Arial;\n}\n\nh1 {\n  margin: 30px 0 5px 0;\n  padding: 0;\n}\ncode {\n  padding: 0;\n  margin: 5px 0;\n  display: block;\n}\ntable {\n  border-collapse: collapse;\n  width: 100%;\n  margin: 15px 0;\n}\ntd, th {\n  padding: 4px;\n}\nth {\n  text-align: left;\n  width: 130px;\n}\ntr {\n  display: none;\n}\ntr.rendered {\n  display: block;\n}\ntr.rendered:nth-child(odd) {\n  background: #eee;\n}\n#thumbnail {\n  position: fixed;\n  right: 20px;\n  top: 20px;\n  -webkit-box-shadow: 1px 1px 6px #000;\n  border: 4px solid #fff;\n  background: #fff;\n}\n#loader {\n  font: 30px Arial;\n  text-align: center;\n  padding: 100px;\n}\n#exif, #output {\n  display: none;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/imageinfo/info.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n<html>\n  <head>\n    <script src=\"imageinfo/binaryajax.js\"></script>\n    <script src=\"imageinfo/imageinfo.js\" ></script>\n    <script src=\"imageinfo/exif.js\" ></script>\n    <link href=\"info.css\" rel=\"stylesheet\" type=\"text/css\"></link>\n    <script src=\"info.js\"></script>\n  </head>\n  <body>\n    <div id=\"loader\">\n      Loading... <img src=\"loader.gif\" />\n    </div>\n    <div id=\"output\">\n      <div id=\"info\">\n        <h1>Image Information</h1>\n        <code id=\"url\"></code>\n        <canvas id=\"thumbnail\"></canvas>\n        <table>\n          <tr>\n            <th>Format</th>\n            <td>format</td>\n          </tr>\n          <tr>\n            <th>Version</th>\n            <td>version</td>\n          </tr>\n          <tr>\n            <th>Width</th>\n            <td>width</td>\n          </tr>\n          <tr>\n            <th>Height</th>\n            <td>height</td>\n          </tr>\n          <tr>\n            <th>Mime Type</th>\n            <td>mimeType</td>\n          </tr>\n          <tr>\n            <th>Size (Bytes)</th>\n            <td>byteSize</td>\n          </tr>\n        </table>\n      </div>\n      <div id=\"exif\">\n        <h2>EXIF Information</h2>\n        <table>\n          <tr>\n            <th>Date</th>\n            <td>DateTime</td>\n          </tr>\n          <tr>\n            <th>Aperture</th>\n            <td>ApertureValue</td>\n          </tr>\n          <tr>\n            <th>Exposure</th>\n            <td>ExposureTime</td>\n          </tr>\n          <tr>\n            <th>Shutter Speed</th>\n            <td>ShutterSpeedValue</td>\n          </tr>\n          <tr>\n            <th>ISO</th>\n            <td>ISOSpeedRatings</td>\n          </tr>\n          <tr>\n            <th>Camera Make</th>\n            <td>Make</td>\n          </tr>\n          <tr>\n            <th>Camera Model</th>\n            <td>Model</td>\n          </tr>\n          <tr>\n            <th>Software</th>\n            <td>Software</td>\n          </tr>\n          <tr>\n            <th>XResolution</th>\n            <td>XResolution</td>\n          </tr>\n          <tr>\n            <th>YResolution</th>\n            <td>YResolution</td>\n          </tr>\n          <tr>\n            <th>Flash</th>\n            <td>Flash</td>\n          </tr>\n        </table>\n      </div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/imageinfo/info.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n\n/**\n * Quick template rendering function.  For each cell passed to it, check\n * to see if the cell's text content is a key in the supplied data array.\n * If yes, replace the cell's contents with the corresponding value and\n * unhide the cell.  If no, then remove the cell's parent (tr) from the\n * DOM.\n */\nfunction renderCells(cells, data) {\n  for (var i = 0; i < cells.length; i++) {\n    var cell = cells[i];\n    var key = cell.innerText;\n    if (data[key]) {\n      cell.innerText = data[key];\n      cell.parentElement.className = \"rendered\";\n    } else {\n      cell.parentElement.parentElement.removeChild(cell.parentElement);\n    }\n  }\n};\n\n/**\n * Returns true if the supplies object has no properties.\n */\nfunction isEmpty(obj) {\n  for (var key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      return false;\n    }\n  }\n  return true;\n};\n\n/**\n * Resizes the window to the current dimensions of this page's body.\n */\nfunction resizeWindow() {\n  window.setTimeout(function() {\n    chrome.tabs.getCurrent(function (tab) {\n      var newHeight = Math.min(document.body.offsetHeight + 140, 700);\n      chrome.windows.update(tab.windowId, {\n        height: newHeight,\n        width: 520\n      });\n    });\n  }, 150);\n};\n\n/**\n * Called directly by the background page with information about the\n * image.  Outputs image data to the DOM.\n */\nfunction renderImageInfo(imageinfo) {\n  console.log('imageinfo', imageinfo);\n\n  var divloader = document.querySelector('#loader');\n  var divoutput = document.querySelector('#output');\n  divloader.style.display = \"none\";\n  divoutput.style.display = \"block\";\n\n  var divinfo = document.querySelector('#info');\n  var divexif = document.querySelector('#exif');\n\n  // Render general image data.\n  var datacells = divinfo.querySelectorAll('td');\n  renderCells(datacells, imageinfo);\n\n  // If EXIF data exists, unhide the EXIF table and render.\n  if (imageinfo['exif'] && !isEmpty(imageinfo['exif'])) {\n    divexif.style.display = 'block';\n    var exifcells = divexif.querySelectorAll('td');\n    renderCells(exifcells, imageinfo['exif']);\n  }\n};\n\n/**\n * Renders the URL for the image, trimming if the length is too long.\n */\nfunction renderUrl(url) {\n  var divurl = document.querySelector('#url');\n  var urltext = (url.length < 45) ? url : url.substr(0, 42) + '...';\n  var anchor = document.createElement('a');\n  anchor.href = url;\n  anchor.innerText = urltext;\n  divurl.appendChild(anchor);\n};\n\n/**\n * Renders a thumbnail view of the image.\n */\nfunction renderThumbnail(url) {\n  var canvas = document.querySelector('#thumbnail');\n  var context = canvas.getContext('2d');\n\n  canvas.width = 100;\n  canvas.height = 100;\n\n  var image = new Image();\n  image.addEventListener('load', function() {\n    var src_w = image.width;\n    var src_h = image.height;\n    var new_w = canvas.width;\n    var new_h = canvas.height;\n    var ratio = src_w / src_h;\n    if (src_w > src_h) {\n      new_h /= ratio;\n    } else {\n      new_w *= ratio;\n    }\n    canvas.width = new_w;\n    canvas.height = new_h;\n    context.drawImage(image, 0, 0, src_w, src_h, 0, 0, new_w, new_h);\n  });\n  image.src = url;\n};\n\n/**\n * Returns a function which will handle displaying information about the\n * image once the ImageInfo class has finished loading.\n */\nfunction getImageInfoHandler(url) {\n  return function() {\n    renderUrl(url);\n    renderThumbnail(url);\n    var imageinfo = ImageInfo.getAllFields(url);\n    renderImageInfo(imageinfo);\n    resizeWindow();\n  };\n};\n\n/**\n * Load the image in question and display it, along with its metadata.\n */\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n  // The URL of the image to load is passed on the URL fragment.\n  var imageUrl = window.location.hash.substring(1);\n  if (imageUrl) {\n    // Use the ImageInfo library to load the image and parse it.\n    ImageInfo.loadInfo(imageUrl, getImageInfoHandler(imageUrl));\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/imageinfo/manifest.json",
    "content": "{\n  \"name\" : \"Imageinfo\",\n  \"version\" : \"1.0.1\",\n  \"description\" : \"Get image info for images, including EXIF data\",\n  \"background\" : { \"scripts\": [\"background.js\"] },\n  \"permissions\" : [\n    \"contextMenus\",\n    \"tabs\",\n    \"http://*/*\",\n    \"https://*/*\"\n   ],\n  \"minimum_chrome_version\" : \"6.0.0.0\",\n  \"icons\" : {\n    \"16\" : \"imageinfo-16.png\",\n    \"48\" : \"imageinfo-48.png\",\n    \"128\" : \"imageinfo-128.png\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/README.txt",
    "content": "This directory contains a simple irc app which is a work in progress.\n\n/app - contains the manifest and any additional resources which are to be\n    packaged in a crx.\n\n/servlet - contains the java servlet which will serve the live resources and\n    also proxy the irc traffic between the client and irc servers\n\n/conf - contains configuration files for running the servlet.\n\nThis example depends on WebSockets, so it must be run inside a servlet container\nwhich supports WebSockets.\n\nThe following are instructions for setting up a development jetty server to\nhost the servlet.\n\n1) Get the jetty 7.x distribution from eclipse.org. Unpack it anywhere. We'll\n   call that directory JETTY_HOME\n2) Delete the contents of JETTY_HOME/webapps.\n3) Copy /conf/irc.xml to JETTY_HOME/contexts, edit the value of resourceBase in\n   irc.xml to point to the contents of /servlet.\n4) Copy jetty.xml and webdefault.xml to JETTY_HOME/etc\n5) Copy the following jars from JETTY_HOME/lib to /servlet/WEB-INF/lib:\n\n  jetty-client, jetty-continuation, jetty-http, jetty-io, jetty-servlets,\n  jetty-util\n  \n6) Compile /servlet/src/org/chromium/IRCProxyWebSocket.java and put the\n   resulting class file in /servlet/WEB-INF/classes\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/app/manifest.json",
    "content": "{\n  \"name\": \"Chromium IRC App\",\n  \"version\": \"0.1\",\n  \"app\": {\n    \"launch\" : {\n      \"url\": \"http://localhost:8080\"\n    },\n    \"origins\": [\"http://localhost:8080\"]\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/conf/irc.xml",
    "content": "<?xml version=\"1.0\"  encoding=\"ISO-8859-1\"?>\n<!DOCTYPE Configure PUBLIC \"-//Jetty//Configure//EN\" \"http://www.eclipse.org/jetty/configure.dtd\">\n<Configure class=\"org.eclipse.jetty.webapp.WebAppContext\">\n  <Set name=\"contextPath\">/</Set>\n  <Set name=\"resourceBase\">file:/D:/eclipse/irc-proxy</Set>\n  <Set name=\"defaultsDescriptor\"><SystemProperty name=\"jetty.home\" default=\".\"/>/etc/webdefault.xml</Set>\n</Configure>\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/conf/jetty.xml",
    "content": "<?xml version=\"1.0\"?>\n<!DOCTYPE Configure PUBLIC \"-//Jetty//Configure//EN\" \"http://www.eclipse.org/jetty/configure.dtd\">\n\n<!-- =============================================================== -->\n<!-- Configure the Jetty Server                                      -->\n<!--                                                                 -->\n<!-- Documentation of this file format can be found at:              -->\n<!-- http://docs.codehaus.org/display/JETTY/jetty.xml                -->\n<!--                                                                 -->\n<!-- =============================================================== -->\n\n\n<Configure id=\"Server\" class=\"org.eclipse.jetty.server.Server\">\n\n    <!-- =========================================================== -->\n    <!-- Server Thread Pool                                          -->\n    <!-- =========================================================== -->\n    <Set name=\"ThreadPool\">\n      <!-- Default queued blocking threadpool \n      -->\n      <New class=\"org.eclipse.jetty.util.thread.QueuedThreadPool\">\n        <Set name=\"minThreads\">10</Set>\n        <Set name=\"maxThreads\">200</Set>\n      </New>\n\n      <!-- Optional Java 5 bounded threadpool with job queue \n      <New class=\"org.eclipse.thread.concurrent.ThreadPool\">\n        <Set name=\"corePoolSize\">50</Set>\n        <Set name=\"maximumPoolSize\">50</Set>\n      </New>\n      -->\n    </Set>\n\n\n\n    <!-- =========================================================== -->\n    <!-- Set connectors                                              -->\n    <!-- =========================================================== -->\n\n    <Call name=\"addConnector\">\n      <Arg>\n          <New class=\"org.eclipse.jetty.server.nio.SelectChannelConnector\">\n            <Set name=\"host\"><SystemProperty name=\"jetty.host\" /></Set>\n            <Set name=\"port\"><SystemProperty name=\"jetty.port\" default=\"8080\"/></Set>\n            <Set name=\"maxIdleTime\">300000</Set>\n            <Set name=\"Acceptors\">2</Set>\n            <Set name=\"statsOn\">false</Set>\n            <Set name=\"confidentialPort\">8443</Set>\n\t    <Set name=\"lowResourcesConnections\">20000</Set>\n\t    <Set name=\"lowResourcesMaxIdleTime\">5000</Set>\n          </New>\n      </Arg>\n    </Call>\n\n    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->\n    <!-- To add a HTTPS SSL connector                                    -->\n    <!-- mixin jetty-ssl.xml:                                            -->\n    <!--   java -jar start.jar etc/jetty.xml etc/jetty-ssl.xml           -->\n    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->\n    \n    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->\n    <!-- To add a HTTP blocking connector                                -->\n    <!-- mixin jetty-bio.xml:                                            -->\n    <!--   java -jar start.jar etc/jetty.xml etc/jetty-bio.xml           -->\n    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->\n    \n    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->\n    <!-- To allow Jetty to be started from xinetd                        -->\n    <!-- mixin jetty-xinetd.xml:                                         -->\n    <!--   java -jar start.jar etc/jetty.xml etc/jetty-xinetd.xml        -->\n    <!--                                                                 -->\n    <!-- See jetty-xinetd.xml for further instructions.                  -->\n    <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->\n\n    <!-- =========================================================== -->\n    <!-- Set handler Collection Structure                            --> \n    <!-- =========================================================== -->\n    <Set name=\"handler\">\n      <New id=\"Handlers\" class=\"org.eclipse.jetty.server.handler.HandlerCollection\">\n        <Set name=\"handlers\">\n         <Array type=\"org.eclipse.jetty.server.Handler\">\n           <Item>\n             <New id=\"Contexts\" class=\"org.eclipse.jetty.server.handler.ContextHandlerCollection\"/>\n           </Item>\n           <Item>\n             <New id=\"DefaultHandler\" class=\"org.eclipse.jetty.server.handler.DefaultHandler\"/>\n           </Item>\n           <Item>\n             <New id=\"RequestLog\" class=\"org.eclipse.jetty.server.handler.RequestLogHandler\"/>\n           </Item>\n         </Array>\n        </Set>\n      </New>\n    </Set>\n    \n    <!-- =========================================================== -->\n    <!-- Configure the context deployer                              -->\n    <!-- A context deployer will deploy contexts described in        -->\n    <!-- configuration files discovered in a directory.              -->\n    <!-- The configuration directory can be scanned for hot          -->\n    <!-- deployments at the configured scanInterval.                 -->\n    <!--                                                             -->\n    <!-- This deployer is configured to deploy contexts configured   -->\n    <!-- in the $JETTY_HOME/contexts directory                       -->\n    <!--                                                             -->\n    <!-- =========================================================== -->\n    <Call name=\"addBean\">\n      <Arg>\n        <New class=\"org.eclipse.jetty.deploy.ContextDeployer\">\n          <Set name=\"contexts\"><Ref id=\"Contexts\"/></Set>\n          <Set name=\"configurationDir\"><SystemProperty name=\"jetty.home\" default=\".\"/>/contexts</Set>\n          <Set name=\"scanInterval\">5</Set>\n          <Call name=\"setAttribute\">\n            <Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg>\n            <Arg>.*/jsp-api-[^/]*\\.jar$|.*/jsp-[^/]*\\.jar$</Arg>\n          </Call>\n        </New>\n      </Arg>\n    </Call>\n\n    <!-- =========================================================== -->\n    <!-- Configure the webapp deployer.                              -->\n    <!-- A webapp  deployer will deploy standard webapps discovered  -->\n    <!-- in a directory at startup, without the need for additional  -->\n    <!-- configuration files.    It does not support hot deploy or   -->\n    <!-- non standard contexts (see ContextDeployer above).          -->\n    <!--                                                             -->\n    <!-- This deployer is configured to deploy webapps from the      -->\n    <!-- $JETTY_HOME/webapps directory                               -->\n    <!--                                                             -->\n    <!-- Normally only one type of deployer need be used.            -->\n    <!--                                                             -->\n    <!-- =========================================================== -->\n    <Call name=\"addBean\">\n      <Arg>\n        <New class=\"org.eclipse.jetty.deploy.WebAppDeployer\">\n          <Set name=\"contexts\"><Ref id=\"Contexts\"/></Set>\n          <Set name=\"webAppDir\"><SystemProperty name=\"jetty.home\" default=\".\"/>/webapps</Set>\n\t\t  <Set name=\"parentLoaderPriority\">false</Set>\n\t\t  <Set name=\"extract\">true</Set>\n\t\t  <Set name=\"allowDuplicates\">false</Set>\n          <Set name=\"defaultsDescriptor\"><SystemProperty name=\"jetty.home\" default=\".\"/>/etc/webdefault.xml</Set>\n          <Call name=\"setAttribute\">\n            <Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg>\n            <Arg>.*/jsp-api-[^/]*\\.jar$|.*/jsp-[^/]*\\.jar$</Arg>\n          </Call>\n        </New>\n      </Arg>\n    </Call>\n\n    <!-- =========================================================== -->\n    <!-- Configure Authentication Login Service                      -->\n    <!-- Realms may be configured for the entire server here, or     -->\n    <!-- they can be configured for a specific web app in a context  -->\n    <!-- configuration (see $(jetty.home)/contexts/test.xml for an   -->\n    <!-- example).                                                   -->\n    <!-- =========================================================== -->\n    <Call name=\"addBean\">\n      <Arg>\n        <New class=\"org.eclipse.jetty.security.HashLoginService\">\n          <Set name=\"name\">Test Realm</Set>\n          <Set name=\"config\"><SystemProperty name=\"jetty.home\" default=\".\"/>/etc/realm.properties</Set>\n          <Set name=\"refreshInterval\">0</Set>\n        </New>\n      </Arg>\n    </Call>\n\n    <!-- =========================================================== -->\n    <!-- Configure Request Log                                       -->\n    <!-- Request logs  may be configured for the entire server here, -->\n    <!-- or they can be configured for a specific web app in a       -->\n    <!-- contexts configuration (see $(jetty.home)/contexts/test.xml -->\n    <!-- for an example).                                            -->\n    <!-- =========================================================== -->\n    <Ref id=\"RequestLog\">\n      <Set name=\"requestLog\">\n        <New id=\"RequestLogImpl\" class=\"org.eclipse.jetty.server.NCSARequestLog\">\n          <Set name=\"filename\"><SystemProperty name=\"jetty.home\" default=\".\"/>/logs/yyyy_mm_dd.request.log</Set>\n          <Set name=\"filenameDateFormat\">yyyy_MM_dd</Set>\n          <Set name=\"retainDays\">90</Set>\n          <Set name=\"append\">true</Set>\n          <Set name=\"extended\">false</Set>\n          <Set name=\"logCookies\">false</Set>\n          <Set name=\"LogTimeZone\">GMT</Set>\n        </New>\n      </Set>\n    </Ref>\n\n    <!-- =========================================================== -->\n    <!-- extra options                                               -->\n    <!-- =========================================================== -->\n    <Set name=\"stopAtShutdown\">true</Set>\n    <Set name=\"sendServerVersion\">true</Set>\n    <Set name=\"sendDateHeader\">true</Set>\n    <Set name=\"gracefulShutdown\">1000</Set>\n\n</Configure>\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/conf/webdefault.xml",
    "content": "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n\n<!-- ===================================================================== -->\n<!-- This file contains the default descriptor for web applications.       -->\n<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->\n<!-- The intent of this descriptor is to include jetty specific or common  -->\n<!-- configuration for all webapps.   If a context has a webdefault.xml    -->\n<!-- descriptor, it is applied before the contexts own web.xml file        -->\n<!--                                                                       -->\n<!-- A context may be assigned a default descriptor by:                    -->\n<!--  + Calling WebApplicationContext.setDefaultsDescriptor                -->\n<!--  + Passed an arg to addWebApplications                                -->\n<!--                                                                       -->\n<!-- This file is used both as the resource within the jetty.jar (which is -->\n<!-- used as the default if no explicit defaults descriptor is set) and it -->\n<!-- is copied to the etc directory of the Jetty distro and explicitly     -->\n<!-- by the jetty.xml file.                                                -->\n<!--                                                                       -->\n<!-- ===================================================================== -->\n<web-app \n   xmlns=\"http://java.sun.com/xml/ns/javaee\" \n   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n   xsi:schemaLocation=\"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd\" \n   metadata-complete=\"true\"\n   version=\"2.5\"> \n\n  <description>\n    Default web.xml file.  \n    This file is applied to a Web application before it's own WEB_INF/web.xml file\n  </description>\n\n\n  <!-- ==================================================================== -->\n  <!-- Context params to control Session Cookies                            -->\n  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->\n  <!-- UNCOMMENT TO ACTIVATE\n  <context-param>\n    <param-name>org.eclipse.jetty.servlet.SessionDomain</param-name>\n    <param-value>127.0.0.1</param-value>\n  </context-param>\n\n  <context-param>\n    <param-name>org.eclipse.jetty.servlet.SessionPath</param-name>\n    <param-value>/</param-value>\n  </context-param>\n\n  <context-param>\n    <param-name>org.eclipse.jetty.servlet.MaxAge</param-name>\n    <param-value>-1</param-value>\n  </context-param>\n  -->\n\n\n  <!-- ==================================================================== -->\n  <!-- The default servlet.                                                 -->\n  <!-- This servlet, normally mapped to /, provides the handling for static -->\n  <!-- content, OPTIONS and TRACE methods for the context.                  -->\n  <!-- The following initParameters are supported:                          -->\n  <!--                                                                      -->\n  <!--   acceptRanges     If true, range requests and responses are         -->\n  <!--                    supported                                         -->\n  <!--                                                                      -->\n  <!--   dirAllowed       If true, directory listings are returned if no    -->\n  <!--                    welcome file is found. Else 403 Forbidden.        -->\n  <!--                                                                      -->\n  <!--   welcomeServlets  If true, attempt to dispatch to welcome files     -->\n  <!--                    that are servlets, if no matching static          -->\n  <!--                    resources can be found.                           -->\n  <!--                                                                      -->\n  <!--   redirectWelcome  If true, redirect welcome file requests           -->\n  <!--                    else use request dispatcher forwards              -->\n  <!--                                                                      -->\n  <!--   gzip             If set to true, then static content will be served--> \n  <!--                    as gzip content encoded if a matching resource is -->\n  <!--                    found ending with \".gz\"                           -->\n  <!--                                                                      -->\n  <!--   resoureBase      Can be set to replace the context resource base   -->\n  <!--                                                                      -->\n  <!--   relativeResourceBase                                               -->\n  <!--                    Set with a pathname relative to the base of the   -->\n  <!--                    servlet context root. Useful for only serving     -->\n  <!--                    static content from only specific subdirectories. -->\n  <!--                                                                      -->\n  <!--   useFileMappedBuffer                                                -->\n  <!--                    If set to true (the default), a  memory mapped    -->\n  <!--                    file buffer will be used to serve static content  -->\n  <!--                    when using an NIO connector. Setting this value   -->\n  <!--                    to false means that a direct buffer will be used  -->\n  <!--                    instead. If you are having trouble with Windows   -->\n  <!--                    file locking, set this to false.                  -->\n  <!--                                                                      -->\n  <!--  cacheControl      If set, all static content will have this value   -->\n  <!--                    set as the cache-control header.                  -->\n  <!--                                                                      -->\n  <!--  maxCacheSize      Maximum size of the static resource cache         -->\n  <!--                                                                      -->\n  <!--  maxCachedFileSize Maximum size of any single file in the cache      -->\n  <!--                                                                      -->\n  <!--  maxCachedFiles    Maximum number of files in the cache              -->\n  <!--                                                                      -->\n  <!--  cacheType         \"nio\", \"bio\" or \"both\" to determine the type(s)   -->\n  <!--                    of resource cache. A bio cached buffer may be used-->\n  <!--                    by nio but is not as efficient as a nio buffer.   -->\n  <!--                    An nio cached buffer may not be used by bio.      -->\n  <!--                                                                      -->\n  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->\n  <servlet>\n    <servlet-name>default</servlet-name>\n    <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>\n    <init-param>\n      <param-name>acceptRanges</param-name>\n      <param-value>true</param-value>\n    </init-param>\n    <init-param>\n      <param-name>dirAllowed</param-name>\n      <param-value>true</param-value>\n    </init-param>\n    <init-param>\n      <param-name>welcomeServlets</param-name>\n \t    <param-value>false</param-value>\n \t  </init-param>\n    <init-param>\n      <param-name>redirectWelcome</param-name>\n      <param-value>false</param-value>\n    </init-param>\n    <init-param>\n      <param-name>maxCacheSize</param-name>\n      <param-value>256000000</param-value>\n    </init-param>\n    <init-param>\n      <param-name>maxCachedFileSize</param-name>\n      <param-value>10000000</param-value>\n    </init-param>\n    <init-param>\n      <param-name>maxCachedFiles</param-name>\n      <param-value>1000</param-value>\n    </init-param>\n    <init-param>\n      <param-name>cacheType</param-name>\n      <param-value>both</param-value>\n    </init-param>\n    <init-param>\n      <param-name>gzip</param-name>\n      <param-value>true</param-value>\n    </init-param>\n    <init-param>\n      <param-name>useFileMappedBuffer</param-name>\n      <param-value>false</param-value>\n    </init-param>  \n    <!--\n    <init-param>\n      <param-name>cacheControl</param-name>\n      <param-value>max-age=3600,public</param-value>\n    </init-param>\n    -->\n    <load-on-startup>0</load-on-startup>\n  </servlet> \n\n  <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>\n  \n\n  <!-- ==================================================================== -->\n  <!-- JSP Servlet                                                          -->\n  <!-- This is the jasper JSP servlet from the jakarta project              -->\n  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->\n  <!-- The JSP page compiler and execution servlet, which is the mechanism  -->\n  <!-- used by Glassfish to support JSP pages.  Traditionally, this servlet -->\n  <!-- is mapped to URL patterh \"*.jsp\".  This servlet supports the         -->\n  <!-- following initialization parameters (default values are in square    -->\n  <!-- brackets):                                                           -->\n  <!--                                                                      -->\n  <!--   checkInterval       If development is false and reloading is true, -->\n  <!--                       background compiles are enabled. checkInterval -->\n  <!--                       is the time in seconds between checks to see   -->\n  <!--                       if a JSP page needs to be recompiled. [300]    -->\n  <!--                                                                      -->\n  <!--   compiler            Which compiler Ant should use to compile JSP   -->\n  <!--                       pages.  See the Ant documenation for more      -->\n  <!--                       information. [javac]                           -->\n  <!--                                                                      -->\n  <!--   classdebuginfo      Should the class file be compiled with         -->\n  <!--                       debugging information?  [true]                 -->\n  <!--                                                                      -->\n  <!--   classpath           What class path should I use while compiling   -->\n  <!--                       generated servlets?  [Created dynamically      -->\n  <!--                       based on the current web application]          -->\n  <!--                       Set to ? to make the container explicitly set  -->\n  <!--                       this parameter.                                -->\n  <!--                                                                      -->\n  <!--   development         Is Jasper used in development mode (will check -->\n  <!--                       for JSP modification on every access)?  [true] -->\n  <!--                                                                      -->\n  <!--   enablePooling       Determines whether tag handler pooling is      -->\n  <!--                       enabled  [true]                                -->\n  <!--                                                                      -->\n  <!--   fork                Tell Ant to fork compiles of JSP pages so that -->\n  <!--                       a separate JVM is used for JSP page compiles   -->\n  <!--                       from the one Tomcat is running in. [true]      -->\n  <!--                                                                      -->\n  <!--   ieClassId           The class-id value to be sent to Internet      -->\n  <!--                       Explorer when using <jsp:plugin> tags.         -->\n  <!--                       [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93]   -->\n  <!--                                                                      -->\n  <!--   javaEncoding        Java file encoding to use for generating java  -->\n  <!--                       source files. [UTF-8]                          -->\n  <!--                                                                      -->\n  <!--   keepgenerated       Should we keep the generated Java source code  -->\n  <!--                       for each page instead of deleting it? [true]   -->\n  <!--                                                                      -->\n  <!--   logVerbosityLevel   The level of detailed messages to be produced  -->\n  <!--                       by this servlet.  Increasing levels cause the  -->\n  <!--                       generation of more messages.  Valid values are -->\n  <!--                       FATAL, ERROR, WARNING, INFORMATION, and DEBUG. -->\n  <!--                       [WARNING]                                      -->\n  <!--                                                                      -->\n  <!--   mappedfile          Should we generate static content with one     -->\n  <!--                       print statement per input line, to ease        -->\n  <!--                       debugging?  [false]                            -->\n  <!--                                                                      -->\n  <!--                                                                      -->\n  <!--   reloading           Should Jasper check for modified JSPs?  [true] -->\n  <!--                                                                      -->\n  <!--   suppressSmap        Should the generation of SMAP info for JSR45   -->\n  <!--                       debugging be suppressed?  [false]              -->\n  <!--                                                                      -->\n  <!--   dumpSmap            Should the SMAP info for JSR45 debugging be    -->\n  <!--                       dumped to a file? [false]                      -->\n  <!--                       False if suppressSmap is true                  -->\n  <!--                                                                      -->\n  <!--   scratchdir          What scratch directory should we use when      -->\n  <!--                       compiling JSP pages?  [default work directory  -->\n  <!--                       for the current web application]               -->\n  <!--                                                                      -->\n  <!--   tagpoolMaxSize      The maximum tag handler pool size  [5]         -->\n  <!--                                                                      -->\n  <!--   xpoweredBy          Determines whether X-Powered-By response       -->\n  <!--                       header is added by generated servlet  [false]  -->\n  <!--                                                                      -->\n  <!-- If you wish to use Jikes to compile JSP pages:                       -->\n  <!--   Set the init parameter \"compiler\" to \"jikes\".  Define              -->\n  <!--   the property \"-Dbuild.compiler.emacs=true\" when starting Jetty     -->\n  <!--   to cause Jikes to emit error messages in a format compatible with  -->\n  <!--   Jasper.                                                            -->\n  <!--   If you get an error reporting that jikes can't use UTF-8 encoding, -->\n  <!--   try setting the init parameter \"javaEncoding\" to \"ISO-8859-1\".     -->\n  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->\n  <servlet id=\"jsp\">\n    <servlet-name>jsp</servlet-name>\n    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>\n    <init-param>\n        <param-name>logVerbosityLevel</param-name>\n        <param-value>DEBUG</param-value>\n    </init-param>\n    <init-param>\n        <param-name>fork</param-name>\n        <param-value>false</param-value>\n    </init-param>\n    <init-param>\n        <param-name>xpoweredBy</param-name>\n        <param-value>false</param-value>\n    </init-param>\n    <!--  \n    <init-param>\n        <param-name>classpath</param-name>\n        <param-value>?</param-value>\n    </init-param>\n    -->\n    <load-on-startup>0</load-on-startup>\n  </servlet>\n\n  <servlet-mapping> \n    <servlet-name>jsp</servlet-name> \n    <url-pattern>*.jsp</url-pattern> \n    <url-pattern>*.jspf</url-pattern>\n    <url-pattern>*.jspx</url-pattern>\n    <url-pattern>*.xsp</url-pattern>\n    <url-pattern>*.JSP</url-pattern> \n    <url-pattern>*.JSPF</url-pattern>\n    <url-pattern>*.JSPX</url-pattern>\n    <url-pattern>*.XSP</url-pattern>\n  </servlet-mapping>\n  \n  <!-- ==================================================================== -->\n  <!-- Dynamic Servlet Invoker.                                             -->\n  <!-- This servlet invokes anonymous servlets that have not been defined   -->\n  <!-- in the web.xml or by other means. The first element of the pathInfo  -->\n  <!-- of a request passed to the envoker is treated as a servlet name for  -->\n  <!-- an existing servlet, or as a class name of a new servlet.            -->\n  <!-- This servlet is normally mapped to /servlet/*                        -->\n  <!-- This servlet support the following initParams:                       -->\n  <!--                                                                      -->\n  <!--  nonContextServlets       If false, the invoker can only load        -->\n  <!--                           servlets from the contexts classloader.    -->\n  <!--                           This is false by default and setting this  -->\n  <!--                           to true may have security implications.    -->\n  <!--                                                                      -->\n  <!--  verbose                  If true, log dynamic loads                 -->\n  <!--                                                                      -->\n  <!--  *                        All other parameters are copied to the     -->\n  <!--                           each dynamic servlet as init parameters    -->\n  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->\n  <!-- Uncomment for dynamic invocation\n  <servlet>\n    <servlet-name>invoker</servlet-name>\n    <servlet-class>org.eclipse.jetty.servlet.Invoker</servlet-class>\n    <init-param>\n      <param-name>verbose</param-name>\n      <param-value>false</param-value>\n    </init-param>\n    <init-param>\n      <param-name>nonContextServlets</param-name>\n      <param-value>false</param-value>\n    </init-param>\n    <init-param>\n      <param-name>dynamicParam</param-name>\n      <param-value>anyValue</param-value>\n    </init-param>\n    <load-on-startup>0</load-on-startup>\n  </servlet>\n\n  <servlet-mapping> <servlet-name>invoker</servlet-name> <url-pattern>/servlet/*</url-pattern> </servlet-mapping>\n  -->\n\n\n\n  <!-- ==================================================================== -->\n  <session-config>\n    <session-timeout>30</session-timeout>\n  </session-config>\n\n  <!-- ==================================================================== -->\n  <!-- Default MIME mappings                                                -->\n  <!-- The default MIME mappings are provided by the mime.properties        -->\n  <!-- resource in the org.eclipse.jetty.server.jar file.  Additional or modified  -->\n  <!-- mappings may be specified here                                       -->\n  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  -->\n  <!-- UNCOMMENT TO ACTIVATE\n  <mime-mapping>\n    <extension>mysuffix</extension>\n    <mime-type>mymime/type</mime-type>\n  </mime-mapping>\n  -->\n\n  <!-- ==================================================================== -->\n  <welcome-file-list>\n    <welcome-file>index.html</welcome-file>\n    <welcome-file>index.htm</welcome-file>\n    <welcome-file>index.jsp</welcome-file>\n  </welcome-file-list>\n\n  <!-- ==================================================================== -->\n  <locale-encoding-mapping-list>\n    <locale-encoding-mapping><locale>ar</locale><encoding>ISO-8859-6</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>be</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>bg</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>ca</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>cs</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>da</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>de</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>el</locale><encoding>ISO-8859-7</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>en</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>es</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>et</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>fi</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>fr</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>hr</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>hu</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>is</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>it</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>iw</locale><encoding>ISO-8859-8</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>ja</locale><encoding>Shift_JIS</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>ko</locale><encoding>EUC-KR</encoding></locale-encoding-mapping>     \n    <locale-encoding-mapping><locale>lt</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>lv</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>mk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>nl</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>no</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>pl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>pt</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>ro</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>ru</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>sh</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>sk</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>sl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>sq</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>sr</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>sv</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>tr</locale><encoding>ISO-8859-9</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>uk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>zh</locale><encoding>GB2312</encoding></locale-encoding-mapping>\n    <locale-encoding-mapping><locale>zh_TW</locale><encoding>Big5</encoding></locale-encoding-mapping>   \n  </locale-encoding-mapping-list>\n  \n  <security-constraint>\n    <web-resource-collection>\n      <web-resource-name>Disable TRACE</web-resource-name>\n      <url-pattern>/</url-pattern>\n      <http-method>TRACE</http-method>\n    </web-resource-collection>\n    <auth-constraint/>\n  </security-constraint>\n  \n</web-app>\n\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/servlet/WEB-INF/web.xml",
    "content": "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<web-app \n   xmlns=\"http://java.sun.com/xml/ns/javaee\" \n   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n   xsi:schemaLocation=\"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd\" \n   version=\"2.5\"> \n  <display-name>IRC-Proxy</display-name>\n  <context-param>\n    <param-name>org.eclipse.jetty.server.context.ManagedAttributes</param-name>\n    <param-value>org.eclipse.jetty.servlets.ProxyServlet.Logger,org.eclipse.jetty.servlets.ProxyServlet.ThreadPool,org.eclipse.jetty.servlets.ProxyServlet.HttpClient</param-value>\n  </context-param>\n  <servlet>\n    <servlet-name>irc-proxy</servlet-name>\n    <servlet-class>org.chromium.IRCProxyWebSocket</servlet-class>\n    <load-on-startup>1</load-on-startup>\n  </servlet>\n  <servlet-mapping>\n    <servlet-name>irc-proxy</servlet-name>\n    <url-pattern>/ws/*</url-pattern>\n  </servlet-mapping>\n</web-app>\n\n\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/servlet/addChannel.html",
    "content": "<html>\n  <head>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\"> \n    <script src=\"jstemplate/util.js\" type=\"text/javascript\"></script>\n    <script src=\"jstemplate/jsevalcontext.js\" type=\"text/javascript\"></script>\n    <script src=\"jstemplate/jstemplate.js\" type=\"text/javascript\"></script> \n    <script src=\"util.js\" type=\"text/javascript\"></script> \n    <script>\nfunction addChannel() {\n  try {\n    var servers = JSON.parse(localStorage.servers || \"[]\");\n    var channelName = $F('channel');\n    var serverName = $F('serverSelect')\n    servers.forEach(function(server) {\n      if (server.name == serverName) {\n        server.channels = server.channels || [];\n        server.channels.forEach(function(channel) {\n          if (channel == channelName) {\n            throw channelName + \" is already open\";\n          }\n        });\n        server.channels.push(channelName);\n      }\n    });\n    \n    localStorage.servers = JSON.stringify(servers);\n    window.opener.syncChannelList();\n    window.opener.joinChannel(serverName, channelName);\n    window.close();\n  } catch (ex) {\n    alert(ex);\n  }\n}\n\nwindow.onload = function() {\n  var servers = JSON.parse(localStorage.servers || \"[]\");\n  if (servers.length == 0) {\n    alert(\"You must first add a server connection\");\n    close();\n  }\n\n  jstProcess(new JsEvalContext(servers), $('serverSelect'));\n}\n\n    </script>\n  </head>\n  <body>\n    <div>\n      <select id=\"serverSelect\">\n        <option jsselect=\"$this\" jscontent=\"name\"></option>\n      </select>\n      <input id=\"channel\" type=\"text\" value=\"#channel\">\n    </div>\n    <div>\n    </div>\n    <div>\n      <input type=\"button\" value=\"Add New Channel\"\n             onclick=\"addChannel();\">\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/servlet/addServer.html",
    "content": "<html>\n  <head>\n     <link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\"> \n    <script src=\"util.js\" type=\"text/javascript\"></script> \n    <script>\nfunction addServer() {\n  try {\n    var servers = JSON.parse(localStorage.servers || \"[]\");\n    var serverName = $F('serverText');\n  \n    servers.forEach(function(server) {\n      if (server.name == serverName) {\n        throw \"Connection to \" + serverName + \" already established\";\n      }\n    });\n\n    var portValue = parseInt($F('serverPort'));\n    if (isNaN(portValue)) {\n      throw $F('serverPort') + \" is not a valid port value\";\n    }\n\n    var nickValue = $F('nick');\n    var newServer = {\n      name: serverName,\n      port: portValue,\n      nick: nickValue,\n      channels: []\n    };\n    \n    servers.push(newServer);\n    \n    localStorage.servers = JSON.stringify(servers);\n    window.opener.addServerConnection(newServer);\n    close();\n  } catch (ex) {\n    alert(ex);\n  }\n}\n    </script>\n  </head>\n  <body>\n    <div>\n      <input id=\"serverText\" type=\"text\" value=\"irc.freenode.net\">\n      <input id=\"serverPort\" type=\"text\" value=\"6667\">\n    </div>\n    <div>\n      <input id=\"nick\" type=\"text\" value=\"nick\">\n    </div>\n    <div>\n      <input type=\"button\" value=\"Add New Server\"\n             onclick=\"addServer();\">\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/servlet/index.html",
    "content": "<html>\n  <head>\n    <title>ChromiumIRC</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\"> \n    <script src=\"jstemplate/util.js\" type=\"text/javascript\"></script>\n    <script src=\"jstemplate/jsevalcontext.js\" type=\"text/javascript\"></script>\n    <script src=\"jstemplate/jstemplate.js\" type=\"text/javascript\"></script> \n    <script src=\"util.js\" type=\"text/javascript\"></script>\n    <script lang=\"JavaScript\" src=\"irc.js\"></script>\n    <script>\n\nvar ircConnections = {};\n\n// The server & channel configutation data is stored in localStorage.servers.\n// These are setters and getters for this structure.\nfunction servers() {\n  return JSON.parse(localStorage.servers || \"[]\");\n}\nfunction setServers(servers) {\n  localStorage.servers = JSON.stringify(servers);\n}\n\n// Channel list is a sorted list of \"server#channel\" strings. This maps to\n// channel slides as represented in the UI.\nfunction channelList() {\n  var channelList = [];\n  servers().forEach(function(server) {\n    server.channels = server.channels || [];\n    server.channels.forEach(function(channel) {\n      channelList.push(server.name + channel);\n    });\n  });\n\n  channelList.sort();\n  return channelList;\n}\n\nwindow.onload = function() {\n  // Setup notifications.\n  window.onfocus = function() {\n    windowHasFocus = true;\n    clearNotifications();\n  }\n  window.onblur = function() {\n    windowHasFocus = false;\n  }\n\n  syncChannelList();\n\n  // Setup channel navigation and message entry.\n  function handleBodyKeyDown(event) {\n    switch (event.keyCode) {\n      case 37: // left arrow\n        slideTo(-1);\n        break;\n      case 39: // right arrow\n        slideTo(1);\n        break;\n    }\n  }\n  document.body.addEventListener('keydown', handleBodyKeyDown, false);\n\n  // We don't want left & right arrow inside the text entry to move the channel\n  // slides.\n  $('typingDiv').addEventListener('keydown', function(event) {\n    event.stopPropagation();\n  });\n  $('entryText').addEventListener('keydown', function(event) {\n    if (event.keyCode == 13) { // RETURN key.\n      processEntryMessage();\n    }\n  });\n\n  servers().forEach(addServerConnection);\n};\n\nwindow.onunload = function() {\n  ircConnections.forEach(function(irc) {\n    irc.disconnect();  \n  });\n}\n\nfunction addServerConnection(server) {\n  var ws = new WebSocket(\"ws://\" + location.host + \"/ws\");\n  var irc = new IRCConnection(server.name, server.port, server.nick,\n                              ws.send.bind(ws), // sendFunc\n                              ws.close.bind(ws)); // closeFunc\n  ws.onopen = irc.onOpened.bind(irc);\n  ws.onclose = irc.onClosed.bind(irc);\n  ws.onmessage = function(message) {\n    irc.onMessage(message.data);  \n  };\n  irc.onConnect = function(message) {\n    server.channels.forEach(function(channel) {\n      ircConnections[server.name].joinChannel(channel);\n    });\n  };\n  irc.onDisconnect = function(message) {\n  };\n  irc.onText = function(channel, nick, message) {\n    checkForNickReference(server, channel, nick, message);\n    addMessage(server.name, channel, nick, new Date(), message);\n  };\n\n  ircConnections[server.name] = irc;\n}\n\nfunction joinChannel(serverName, channelName) {\n  ircConnections[serverName].joinChannel(channelName);\n}\n\nfunction removeChannelListener(channelName) {\n  return function(event) {\n    event.stopPropagation();\n    \n    var servers = servers();\n    servers.forEach(function(server) {\n      if (channelName.indexOf(server.name) == 0) {\n        for (var i = 0; server.channels.length; i++) {\n          if (channelName == server.name + server.channels[i]) {\n            ircConnections[server.name].quitChannel(server.channels[i]);\n            server.channels.splice(i, 1);\n            break;\n          }\n        }\n      }\n    });\n\n    setServers(servers);\n    syncChannelList();\n  };\n}\n\nfunction syncChannelList() {\n  var channels = channelList();\n  var channelSlides = $('channelSlides');\n  var channelSlideProto = $('channelSlideProto');\n\n  var channelIndex = 0;\n  var slideIndex = 0;\n\n  while(channelIndex < channels.length || \n        channels.length != channelSlides.children.length) {\n    var channel = channels[channelIndex];\n    var slide = channelSlides.children[slideIndex];\n\n    if (slideIndex == channelSlides.children.length ||\n        channel < slideChannel(slide)) {\n      // Add a new slide.\n      var newSlide = channelSlideProto.cloneNode(true);\n      jstProcess(new JsEvalContext({ name: channel }), newSlide);\n      newSlide.setAttribute(\"id\", \"channel-\" + channel);\n      newSlide.style.display = \"\";\n      if (slideIndex == channelSlides.children.length) {\n        channelSlides.appendChild(newSlide);\n      } else {\n        channelSlides.insertBefore(newSlide, slide);\n      }\n      newSlide.addEventListener('click', onClickMoveSlide);\n      childNodeWithClass(newSlide, \"removeButton\")\n          .addEventListener('click', removeChannelListener(channel));\n      \n      slide = newSlide;\n    } else if (!channel || channel > slideChannel(slide)) {\n      // Delete a removed slide.\n      \n      // If the removed slide is the current slide, we have to pick a new\n      // current slide.\n      if (localStorage.currentSlide == slideChannel(slide)) {\n        if (slide.nextSibling) {\n          localStorage.currentSlide = slideChannel(slide.nextSibling);\n        } else if (channels.length == 0) {\n          localStorage.currentSlide = \"\";\n        } else if (slideIndex < channelSlides.children.length) {\n          localStorage.currentSlide =\n              slideChannel(channelSlides.children[slideIndex - 1]);\n        }\n      }\n      channelSlides.removeChild(slide);  \n    } else {\n      channelIndex++;\n      slideIndex++;\n    }\n\n    slide.setAttribute(\"slide\", \"\" + slideIndex - 1);\n  }\n\n  slideTo();\n}\n\nfunction processEntryMessage() {\n  var message = $('entryText').value;\n  $('entryText').value = \"\";\n\n  if (!localStorage.currentSlide) {\n    alert('No current channel');\n    return;\n  }\n  \n  var server;\n  var channel;\n  var nick;\n  servers().forEach(function(s) {\n    if (localStorage.currentSlide.indexOf(s.name) == 0) {\n      server = s.name;\n      nick = s.nick;\n      s.channels.forEach(function(c) {\n        if (localStorage.currentSlide == s.name + c) {\n          channel = c;\n        }\n      });\n    }\n  });\n\n  addMessage(server, channel, nick, new Date(), message);\n  ircConnections[server].sendMessage([channel], message);\n}\n\nfunction addMessage(server, channel, nick, time, body) {\n  messageLine = childNodeWithClass($('channelSlideProto'), \"messageLine\");\n  var newMessageLine = messageLine.cloneNode(true);\n\n  jstProcess(new JsEvalContext({ \n    'nick': nick,\n    'time': time,\n    'body': body\n  }), newMessageLine);\n  newMessageLine.style.display = \"\";\n\n  var messageList =\n      childNodeWithClass($(\"channel-\" + server + channel), \"messageList\");\n  messageList.appendChild(newMessageLine);\n}\n\nfunction formatTime(time) {\n  return \"\";\n}\n\n/**\n * Slide Navigation. \n */\n \n// Returns the server#channel string value for a given |slide| element.\nfunction slideChannel(slide) {\n  return childNodeWithClass(slide, \"channel\").innerText;\n}\n\n// Handler for clicking on the visible portions of the previous & next slides.\nfunction onClickMoveSlide() {\n  if (localStorage.currentSlide != slideChannel(this)) {\n    localStorage.currentSlide = slideChannel(this);\n    slideTo();\n  }  \n}\n\n// Handles navigating between the channel slides. If |slideDelta| is given,\n// it should specify the number of slides to move left (negative value) or right\n// positive value. If |slideDelta| is not provided, It ensures that\n// |localStorage.currentSlide| is navigated to.\nfunction slideTo(slideDelta) {\n  var slide;\n  var slideNumber;\n\n  if (localStorage.currentSlide) {\n    slide = document.getElementById(\"channel-\" + localStorage.currentSlide);\n    if (slide) {\n      slideNumber = parseInt(slide.getAttribute(\"slide\"));\n    }\n  }\n  if (isNaN(slideNumber) || !slide) {\n    slideNumber = 0;\n  }\n  if (typeof(slideDelta) == \"number\") {\n    slideNumber += slideDelta;\n  }\n\n  var slides = document.getElementsByClassName(\"channelSlide\");\n  if (slideNumber < 0 || slideNumber == slides.length - 1) {\n    return;\n  }\n\n  for (var i = 0; i < slides.length; i++) {\n    var slide = slides[i];\n    var slideIndex = parseInt(slide.getAttribute(\"slide\")) - slideNumber;\n    \n    if (slideIndex <= -2) {\n      slide.className = \"channelSlide far-left\";\n    }\n    if (slideIndex >= 2) {\n      slide.className = \"channelSlide far-right\";\n    }\n    \n    switch(slideIndex) {\n      case -1:\n        slide.className = \"channelSlide left\";\n        break;\n      case 0:\n        slide.className = \"channelSlide center\";\n        localStorage.currentSlide = slideChannel(slide);\n        break;\n      case 1:\n        slide.className = \"channelSlide right\";\n        break;\n    }\n  }\n\n  clearNotifications();\n}\n\n/**\n * Notifications\n */\nvar windowHasFocus = false;\nvar notifications = {};\n\nfunction clearNotifications() {\n  for (property in notifications) {\n    notifications[property].cancel();\n  }\n\n  notifications = {};\n}\n\nfunction checkForNickReference(server, channel, nick, message) {\n  if (windowHasFocus || !message || message.indexOf(server.nick) < 0) {\n    return;\n  }\n\n  // Notifications will be enabled by the app install. Otherwise, don't notity.\n  if (Notification.permission != \"granted\") {\n    return;\n  }\n\n  // Remove a previous notification from the same channel. Show the newer one.\n  if (notifications[server.name + channel]) {\n    notifications[server.name + channel].close();\n  }\n\n  var n = new Notification(\"On \" + server.name + channel, {\n    icon: \"https://www.google.com/favicon.ico\",\n    body: nick + \": \" + message,\n  });\n\n  n.onshow = function() {};\n  n.onclose = function() {\n    delete notifications[server.name + channel];\n  };\n\n  notifications[server.name + channel] = n;\n}\n    </script>\n  </head>\n  <body>\n    <!--  TEMPLATES -->\n    <div id=\"channelSlideProto\" style=\"display:none\" class=\"channelSlide\">\n      <div class=\"channelControls\">\n        <div jscontent=\"name\" class=\"channel\">\n        </div>\n        <div class=\"removeButton\">\n          x\n        </div>\n      </div>\n      <div class=\"channelSlideContainer\">\n        <div class=\"messageListContainer\">\n          <div class=\"messageList\">\n            <div jsselect=\"messages\">\n              <div class=\"messageLine\">\n                <div jscontent=\"nick\" class=\"messageSender\"></div>:\n                <div jscontent=\"body\" class=\"messageBody\"></div>\n              </div>\n            </div>\n          </div>\n        </div>\n        <div class=\"messageListSpacer\">.</div>\n      </div>\n    </div>\n    \n    <div id=\"pageContainer\">\n      <div id=\"headerContainer\">\n        <div id=\"pageControls\">\n          <div onclick=\"window.open('addServer.html');\">\n            <div class=\"addControlLabel\">\n              add server\n            </div>\n            <div class=\"addButton\">\n              +\n            </div>\n          </div>\n          <div onclick=\" window.open('addChannel.html');\">\n            <div class=\"addControlLabel\">\n              add channel\n            </div>\n            <div class=\"addButton\">\n              +\n            </div>\n          </div>\n        </div>\n      </div>\n      <div id=\"slideContainer\">\n        <div id=\"typingDiv\">\n          <input type=\"text\" id=\"entryText\" value=\"\">\n        </div>\n        <div style=\"\" id=\"channelSlides\">\n        </div>\n      </div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/servlet/irc.js",
    "content": "/*\n * IRCConnection is a simple implementation of the IRC protocol. A small\n * subset of the IRC commands are implemented. To be functional, IRCConnection\n * needs some mechanism of transport to be hooked up by:\n * -Passing in |sendFunc| and |closeFunc| which an IRCConnection to use to send\n *  an IRC message command and to close the connection respectively.\n * -Connecting the in-bound functions |onOpened|, |onMessage|, and |onClosed|,\n *  to the transport so that the IRCConnection can respond to the connection\n *  being opened, a message being received and the connection being closed.\n */\n\nfunction NoOp() {};\nfunction log(message) { console.log(message); };\n\nfunction IRCConnection(server, port, nick, sendFunc, closeFunc) {\n  this.server = server;\n  this.port = port;\n  this.nick = nick;\n  this.connected = false;\n  \n  var that = this;\n\n  /**\n   * Client API\n   */\n  this.onConnect = NoOp;\n  this.onDisconnect = NoOp;\n  this.onText = NoOp;\n  this.onNotice = NoOp;\n  this.onNickReferenced = NoOp;\n\n  this.joinChannel = function(channel) {\n    sendCommand(commands.JOIN, [channel], \"\");\n  };\n\n  this.sendMessage = function(recipient, message) {\n    sendCommand(commands.PRIVMSG, [recipient], message);\n  };\n\n  this.quitChannel = function(channel) {\n    sendCommand(commands.PART, [channel], \"\");\n  }\n\n  this.disconnect = function(message) {\n    sendCommand(commands.QUIT, [], message);\n    closeFunc();\n  }\n\n  /**\n   * Transport Interface\n   * Whatever transport is used must provide and connect to the following\n   * in-bound events.\n   */\n  this.onOpened = function() {\n    sendFunc(that.server + \":\" + that.port);\n    sendCommand(commands.NICK, [this.nick], \"\");\n    sendCommand(commands.USER,\n                [\"chromium-irc-lib\", \"chromium-ircproxy\", \"*\"],\n                \"indigo\");\n  };\n\n  this.onMessage = function(message) {\n    log(\"<< \" + message);\n    if (!message || !message.length) {\n      return;\n    }\n\n    var parsed = parseMessage(message);\n\n    // Respond to PING command.\n    if (parsed.command == commands.PING) {\n      sendCommand(commands.PONG, [], parsed.body);\n      return;\n    }\n\n    // Process PRIVMSG.\n    if (parsed.command == commands.PRIVMSG) {\n      if (parsed.body.charCodeAt(0) == 1) {\n        // Ignore CTCP.\n        return;\n      }\n      that.onText(parsed.parameters[0],\n                  parsed.prefix.split(\"!\")[0],\n                  parsed.body);\n      return;\n    }\n\n    // TODO: Other IRC commands.\n    var commandCode = parseInt(parsed.command);\n    if (commandCode == NaN) {\n      return;\n    }\n\n    switch(commandCode) {\n      case 001:  // Server welcome message.\n        that.connected = true;\n        that.onConnect(parsed.body);\n        break;\n      case 002:\n      case 003:\n      case 004:\n      case 005:\n        if (!that.connected) {\n          that.connected = true;\n          that.onConnect();\n        }\n        break;\n      case 433:  // TODO(rafaelw): Nickname in use. \n        throw \"NOT IMPLEMENTED\";\n        break;\n      default:\n        break;\n    }\n  }\n\n  this.onClosed = function() {\n    that.connected = false;\n    that.onDisconnect();\n  };\n\n  /**\n   * IRC Implementation\n   * What follows in a minimal implementation of the IRC protocol.\n   * Only |commands| are currently implemented.\n   */\n  var commands = {\n    JOIN: \"JOIN\",\n    NICK: \"NICK\",\n    NOTICE: \"NOTICE\",\n    PART: \"PART\",\n    PING: \"PING\",\n    PONG: \"PONG\",\n    PRIVMSG: \"PRIVMSG\",\n    QUIT: \"QUIT\",\n    USER: \"USER\"\n  };\n\n  function parseMessage(message) {\n    var parsed = {};\n    parsed.prefix = \"\";\n    parsed.command = \"\";\n    parsed.parameters = [];\n    parsed.body = \"\";\n\n    // Trim trailing CRLF.\n    var crlfIndex = message.indexOf(\"\\r\\n\");\n    if(crlfIndex >= 0) {\n      message = message.substring(0, crlfIndex);\n    }\n\n    // If leading character is ':', the message starts with a prefix.\n    if (message.indexOf(':') == 0) {\n      parsed.prefix = message.substring(1, message.indexOf(\" \"));\n      message = message.substring(parsed.prefix.length + 2);\n\n      // Forward past extra whitespace.\n      while(message.indexOf(\" \") == 0) {\n        message = message.substring(1);\n      }\n    }\n\n    // If there is still a ':', then the message has trailing body.\n    var bodyMarker = message.indexOf(':');\n    if (bodyMarker >= 0) {\n      parsed.body = message.substring(bodyMarker + 1);\n      message = message.substring(0, bodyMarker);\n    }\n\n    parsed.parameters = message.split(\" \");\n    parsed.command = parsed.parameters.shift();  // First param is the command.\n\n    return parsed;\n  }\n\n  function sendCommand(command, params, message) {\n    var line = command;\n    if (params && params.length > 0) {\n      line += \" \" + params.join(\" \");\n    }\n    if (message && message.length > 0) {\n      line += \" :\"  + message;\n    }\n\n    log(\">> \" + line);\n    line += \"\\r\\n\";\n    sendFunc(line);\n  };\n};\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/servlet/jstemplate/jsevalcontext.js",
    "content": "// Copyright 2006 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n// implied. See the License for the specific language governing\n// permissions and limitations under the License.\n/**\n * Author: Steffen Meschkat <mesch@google.com>\n *\n * @fileoverview This class is used to evaluate expressions in a local\n * context. Used by JstProcessor.\n */\n\n\n/**\n * Names of special variables defined by the jstemplate evaluation\n * context. These can be used in js expression in jstemplate\n * attributes.\n */\nvar VAR_index = '$index';\nvar VAR_count = '$count';\nvar VAR_this = '$this';\nvar VAR_context = '$context';\nvar VAR_top = '$top';\n\n\n/**\n * The name of the global variable which holds the value to be returned if\n * context evaluation results in an error. \n * Use JsEvalContext.setGlobal(GLOB_default, value) to set this.\n */\nvar GLOB_default = '$default';\n\n\n/**\n * Un-inlined literals, to avoid object creation in IE6. TODO(mesch):\n * So far, these are only used here, but we could use them thoughout\n * the code and thus move them to constants.js.\n */\nvar CHAR_colon = ':';\nvar REGEXP_semicolon = /\\s*;\\s*/;\n\n\n/**\n * See constructor_()\n * @param {Object|null} opt_data\n * @param {Object} opt_parent\n * @constructor\n */\nfunction JsEvalContext(opt_data, opt_parent) {\n  this.constructor_.apply(this, arguments);\n}\n\n/**\n * Context for processing a jstemplate. The context contains a context\n * object, whose properties can be referred to in jstemplate\n * expressions, and it holds the locally defined variables.\n *\n * @param {Object|null} opt_data The context object. Null if no context.\n *\n * @param {Object} opt_parent The parent context, from which local\n * variables are inherited. Normally the context object of the parent\n * context is the object whose property the parent object is. Null for the\n * context of the root object.\n */\nJsEvalContext.prototype.constructor_ = function(opt_data, opt_parent) {\n  var me = this;\n\n  /**\n   * The context for variable definitions in which the jstemplate\n   * expressions are evaluated. Other than for the local context,\n   * which replaces the parent context, variable definitions of the\n   * parent are inherited. The special variable $this points to data_.\n   *\n   * If this instance is recycled from the cache, then the property is\n   * already initialized.\n   *\n   * @type {Object}\n   */\n  if (!me.vars_) {\n    me.vars_ = {};\n  }\n  if (opt_parent) {\n    // If there is a parent node, inherit local variables from the\n    // parent.\n    copyProperties(me.vars_, opt_parent.vars_);\n  } else {\n    // If a root node, inherit global symbols. Since every parent\n    // chain has a root with no parent, global variables will be\n    // present in the case above too. This means that globals can be\n    // overridden by locals, as it should be.\n    copyProperties(me.vars_, JsEvalContext.globals_);\n  }\n\n  /**\n   * The current context object is assigned to the special variable\n   * $this so it is possible to use it in expressions.\n   * @type Object\n   */\n  me.vars_[VAR_this] = opt_data;\n\n  /**\n   * The entire context structure is exposed as a variable so it can be\n   * passed to javascript invocations through jseval.\n   */\n  me.vars_[VAR_context] = me;\n\n  /**\n   * The local context of the input data in which the jstemplate\n   * expressions are evaluated. Notice that this is usually an Object,\n   * but it can also be a scalar value (and then still the expression\n   * $this can be used to refer to it). Notice this can even be value,\n   * undefined or null. Hence, we have to protect jsexec() from using\n   * undefined or null, yet we want $this to reflect the true value of\n   * the current context. Thus we assign the original value to $this,\n   * above, but for the expression context we replace null and\n   * undefined by the empty string.\n   *\n   * @type {Object|null}\n   */\n  me.data_ = getDefaultObject(opt_data, STRING_empty);\n\n  if (!opt_parent) {\n    // If this is a top-level context, create a variable reference to the data\n    // to allow for  accessing top-level properties of the original context\n    // data from child contexts.\n    me.vars_[VAR_top] = me.data_;\n  }\n};\n\n\n/**\n * A map of globally defined symbols. Every instance of JsExprContext\n * inherits them in its vars_.\n * @type Object\n */\nJsEvalContext.globals_ = {}\n\n\n/**\n * Sets a global symbol. It will be available like a variable in every\n * JsEvalContext instance. This is intended mainly to register\n * immutable global objects, such as functions, at load time, and not\n * to add global data at runtime. I.e. the same objections as to\n * global variables in general apply also here. (Hence the name\n * \"global\", and not \"global var\".)\n * @param {string} name\n * @param {Object|null} value\n */\nJsEvalContext.setGlobal = function(name, value) {\n  JsEvalContext.globals_[name] = value;\n};\n\n\n/**\n * Set the default value to be returned if context evaluation results in an \n * error. (This can occur if a non-existent value was requested). \n */\nJsEvalContext.setGlobal(GLOB_default, null);\n\n\n/**\n * A cache to reuse JsEvalContext instances. (IE6 perf)\n *\n * @type Array<JsEvalContext>\n */\nJsEvalContext.recycledInstances_ = [];\n\n\n/**\n * A factory to create a JsEvalContext instance, possibly reusing\n * one from recycledInstances_. (IE6 perf)\n *\n * @param {Object} opt_data\n * @param {JsEvalContext} opt_parent\n * @return {JsEvalContext}\n */\nJsEvalContext.create = function(opt_data, opt_parent) {\n  if (jsLength(JsEvalContext.recycledInstances_) > 0) {\n    var instance = JsEvalContext.recycledInstances_.pop();\n    JsEvalContext.call(instance, opt_data, opt_parent);\n    return instance;\n  } else {\n    return new JsEvalContext(opt_data, opt_parent);\n  }\n};\n\n\n/**\n * Recycle a used JsEvalContext instance, so we can avoid creating one\n * the next time we need one. (IE6 perf)\n *\n * @param {JsEvalContext} instance\n */\nJsEvalContext.recycle = function(instance) {\n  for (var i in instance.vars_) {\n    // NOTE(mesch): We avoid object creation here. (IE6 perf)\n    delete instance.vars_[i];\n  }\n  instance.data_ = null;\n  JsEvalContext.recycledInstances_.push(instance);\n};\n\n\n/**\n * Executes a function created using jsEvalToFunction() in the context\n * of vars, data, and template.\n *\n * @param {Function} exprFunction A javascript function created from\n * a jstemplate attribute value.\n *\n * @param {Element} template DOM node of the template.\n *\n * @return {Object|null} The value of the expression from which\n * exprFunction was created in the current js expression context and\n * the context of template.\n */\nJsEvalContext.prototype.jsexec = function(exprFunction, template) {\n  try {\n    return exprFunction.call(template, this.vars_, this.data_);\n  } catch (e) {\n    log('jsexec EXCEPTION: ' + e + ' at ' + template +\n        ' with ' + exprFunction);\n    return JsEvalContext.globals_[GLOB_default];\n  }\n};\n\n\n/**\n * Clones the current context for a new context object. The cloned\n * context has the data object as its context object and the current\n * context as its parent context. It also sets the $index variable to\n * the given value. This value usually is the position of the data\n * object in a list for which a template is instantiated multiply.\n *\n * @param {Object} data The new context object.\n *\n * @param {number} index Position of the new context when multiply\n * instantiated. (See implementation of jstSelect().)\n * \n * @param {number} count The total number of contexts that were multiply\n * instantiated. (See implementation of jstSelect().)\n *\n * @return {JsEvalContext}\n */\nJsEvalContext.prototype.clone = function(data, index, count) {\n  var ret = JsEvalContext.create(data, this);\n  ret.setVariable(VAR_index, index);\n  ret.setVariable(VAR_count, count);\n  return ret;\n};\n\n\n/**\n * Binds a local variable to the given value. If set from jstemplate\n * jsvalue expressions, variable names must start with $, but in the\n * API they only have to be valid javascript identifier.\n *\n * @param {string} name\n *\n * @param {Object?} value\n */\nJsEvalContext.prototype.setVariable = function(name, value) {\n  this.vars_[name] = value;\n};\n\n\n/**\n * Returns the value bound to the local variable of the given name, or\n * undefined if it wasn't set. There is no way to distinguish a\n * variable that wasn't set from a variable that was set to\n * undefined. Used mostly for testing.\n *\n * @param {string} name\n *\n * @return {Object?} value\n */\nJsEvalContext.prototype.getVariable = function(name) {\n  return this.vars_[name];\n};\n\n\n/**\n * Evaluates a string expression within the scope of this context\n * and returns the result.\n *\n * @param {string} expr A javascript expression\n * @param {Element} opt_template An optional node to serve as \"this\"\n *\n * @return {Object?} value\n */\nJsEvalContext.prototype.evalExpression = function(expr, opt_template) {\n  var exprFunction = jsEvalToFunction(expr);\n  return this.jsexec(exprFunction, opt_template);\n};\n\n\n/**\n * Uninlined string literals for jsEvalToFunction() (IE6 perf).\n */\nvar STRING_a = 'a_';\nvar STRING_b = 'b_';\nvar STRING_with = 'with (a_) with (b_) return ';\n\n\n/**\n * Cache for jsEvalToFunction results.\n * @type Object\n */\nJsEvalContext.evalToFunctionCache_ = {};\n\n\n/**\n * Evaluates the given expression as the body of a function that takes\n * vars and data as arguments. Since the resulting function depends\n * only on expr, we cache the result so we save some Function\n * invocations, and some object creations in IE6.\n *\n * @param {string} expr A javascript expression.\n *\n * @return {Function} A function that returns the value of expr in the\n * context of vars and data.\n */\nfunction jsEvalToFunction(expr) {\n  if (!JsEvalContext.evalToFunctionCache_[expr]) {\n    try {\n      // NOTE(mesch): The Function constructor is faster than eval().\n      JsEvalContext.evalToFunctionCache_[expr] =\n        new Function(STRING_a, STRING_b, STRING_with + expr);\n    } catch (e) {\n      log('jsEvalToFunction (' + expr + ') EXCEPTION ' + e);\n    }\n  }\n  return JsEvalContext.evalToFunctionCache_[expr];\n}\n\n\n/**\n * Evaluates the given expression to itself. This is meant to pass\n * through string attribute values.\n *\n * @param {string} expr\n *\n * @return {string}\n */\nfunction jsEvalToSelf(expr) {\n  return expr;\n}\n\n\n/**\n * Parses the value of the jsvalues attribute in jstemplates: splits\n * it up into a map of labels and expressions, and creates functions\n * from the expressions that are suitable for execution by\n * JsEvalContext.jsexec(). All that is returned as a flattened array\n * of pairs of a String and a Function.\n *\n * @param {string} expr\n *\n * @return {Array}\n */\nfunction jsEvalToValues(expr) {\n  // TODO(mesch): It is insufficient to split the values by simply\n  // finding semi-colons, as the semi-colon may be part of a string\n  // constant or escaped.\n  var ret = [];\n  var values = expr.split(REGEXP_semicolon);\n  for (var i = 0, I = jsLength(values); i < I; ++i) {\n    var colon = values[i].indexOf(CHAR_colon);\n    if (colon < 0) {\n      continue;\n    }\n    var label = stringTrim(values[i].substr(0, colon));\n    var value = jsEvalToFunction(values[i].substr(colon + 1));\n    ret.push(label, value);\n  }\n  return ret;\n}\n\n\n/**\n * Parses the value of the jseval attribute of jstemplates: splits it\n * up into a list of expressions, and creates functions from the\n * expressions that are suitable for execution by\n * JsEvalContext.jsexec(). All that is returned as an Array of\n * Function.\n *\n * @param {string} expr\n *\n * @return {Array<Function>}\n */\nfunction jsEvalToExpressions(expr) {\n  var ret = [];\n  var values = expr.split(REGEXP_semicolon);\n  for (var i = 0, I = jsLength(values); i < I; ++i) {\n    if (values[i]) {\n      var value = jsEvalToFunction(values[i]);\n      ret.push(value);\n    }\n  }\n  return ret;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/servlet/jstemplate/jstemplate.js",
    "content": "// Copyright 2006 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n// implied. See the License for the specific language governing\n// permissions and limitations under the License.\n/**\n * Author: Steffen Meschkat <mesch@google.com>\n *\n * @fileoverview A simple formatter to project JavaScript data into\n * HTML templates. The template is edited in place. I.e. in order to\n * instantiate a template, clone it from the DOM first, and then\n * process the cloned template. This allows for updating of templates:\n * If the templates is processed again, changed values are merely\n * updated.\n *\n * NOTE(mesch): IE DOM doesn't have importNode().\n *\n * NOTE(mesch): The property name \"length\" must not be used in input\n * data, see comment in jstSelect_().\n */\n\n\n/**\n * Names of jstemplate attributes. These attributes are attached to\n * normal HTML elements and bind expression context data to the HTML\n * fragment that is used as template.\n */\nvar ATT_select = 'jsselect';\nvar ATT_instance = 'jsinstance';\nvar ATT_display = 'jsdisplay';\nvar ATT_values = 'jsvalues';\nvar ATT_vars = 'jsvars';\nvar ATT_eval = 'jseval';\nvar ATT_transclude = 'transclude';\nvar ATT_content = 'jscontent';\nvar ATT_skip = 'jsskip';\n\n\n/**\n * Name of the attribute that caches a reference to the parsed\n * template processing attribute values on a template node.\n */\nvar ATT_jstcache = 'jstcache';\n\n\n/**\n * Name of the property that caches the parsed template processing\n * attribute values on a template node.\n */\nvar PROP_jstcache = '__jstcache';\n\n\n/**\n * ID of the element that contains dynamically loaded jstemplates.\n */\nvar STRING_jsts = 'jsts';\n\n\n/**\n * Un-inlined string literals, to avoid object creation in\n * IE6.\n */\nvar CHAR_asterisk = '*';\nvar CHAR_dollar = '$';\nvar CHAR_period = '.';\nvar CHAR_ampersand = '&';\nvar STRING_div = 'div';\nvar STRING_id = 'id';\nvar STRING_asteriskzero = '*0';\nvar STRING_zero = '0';\n\n\n/**\n * HTML template processor. Data values are bound to HTML templates\n * using the attributes transclude, jsselect, jsdisplay, jscontent,\n * jsvalues. The template is modifed in place. The values of those\n * attributes are JavaScript expressions that are evaluated in the\n * context of the data object fragment.\n *\n * @param {JsEvalContext} context Context created from the input data\n * object.\n *\n * @param {Element} template DOM node of the template. This will be\n * processed in place. After processing, it will still be a valid\n * template that, if processed again with the same data, will remain\n * unchanged.\n *\n * @param {boolean} opt_debugging Optional flag to collect debugging\n *     information while processing the template.  Only takes effect\n *     in MAPS_DEBUG.\n */\nfunction jstProcess(context, template, opt_debugging) {\n  var processor = new JstProcessor;\n  if (MAPS_DEBUG && opt_debugging) {\n    processor.setDebugging(opt_debugging);\n  }\n  JstProcessor.prepareTemplate_(template);\n\n  /**\n   * Caches the document of the template node, so we don't have to\n   * access it through ownerDocument.\n   * @type Document\n   */\n  processor.document_ = ownerDocument(template);\n\n  processor.run_(bindFully(processor, processor.jstProcessOuter_,\n                           context, template));\n  if (MAPS_DEBUG && opt_debugging) {\n    log('jstProcess:' + '\\n' + processor.getLogs().join('\\n'));\n  }\n}\n\n\n/**\n * Internal class used by jstemplates to maintain context.  This is\n * necessary to process deep templates in Safari which has a\n * relatively shallow maximum recursion depth of 100.\n * @class\n * @constructor\n */\nfunction JstProcessor() {\n  if (MAPS_DEBUG) {\n    /**\n     * An array of logging messages.  These are collected during processing\n     * and dumped to the console at the end.\n     * @type Array<string>\n     */\n    this.logs_ = [];\n  }\n}\n\n\n/**\n * Counter to generate node ids. These ids will be stored in\n * ATT_jstcache and be used to lookup the preprocessed js attributes\n * from the jstcache_. The id is stored in an attribute so it\n * suvives cloneNode() and thus cloned template nodes can share the\n * same cache entry.\n * @type number\n */\nJstProcessor.jstid_ = 0;\n\n\n/**\n * Map from jstid to processed js attributes.\n * @type Object\n */\nJstProcessor.jstcache_ = {};\n\n/**\n * The neutral cache entry. Used for all nodes that don't have any\n * jst attributes. We still set the jsid attribute on those nodes so\n * we can avoid to look again for all the other jst attributes that\n * aren't there. Remember: not only the processing of the js\n * attribute values is expensive and we thus want to cache it. The\n * access to the attributes on the Node in the first place is\n * expensive too.\n */\nJstProcessor.jstcache_[0] = {};\n\n\n/**\n * Map from concatenated attribute string to jstid.\n * The key is the concatenation of all jst atributes found on a node\n * formatted as \"name1=value1&name2=value2&...\", in the order defined by\n * JST_ATTRIBUTES. The value is the id of the jstcache_ entry that can\n * be used for this node. This allows the reuse of cache entries in cases\n * when a cached entry already exists for a given combination of attribute\n * values. (For example when two different nodes in a template share the same\n * JST attributes.)\n * @type Object\n */\nJstProcessor.jstcacheattributes_ = {};\n\n\n/**\n * Map for storing temporary attribute values in prepareNode_() so they don't\n * have to be retrieved twice. (IE6 perf)\n * @type Object\n */\nJstProcessor.attributeValues_ = {};\n\n\n/**\n * A list for storing non-empty attributes found on a node in prepareNode_().\n * The array is global since it can be reused - this way there is no need to\n * construct a new array object for each invocation. (IE6 perf)\n * @type Array\n */\nJstProcessor.attributeList_ = [];\n\n\n/**\n * Prepares the template: preprocesses all jstemplate attributes.\n *\n * @param {Element} template\n */\nJstProcessor.prepareTemplate_ = function(template) {\n  if (!template[PROP_jstcache]) {\n    domTraverseElements(template, function(node) {\n      JstProcessor.prepareNode_(node);\n    });\n  }\n};\n\n\n/**\n * A list of attributes we use to specify jst processing instructions,\n * and the functions used to parse their values.\n *\n * @type Array<Array>\n */\nvar JST_ATTRIBUTES = [\n    [ ATT_select, jsEvalToFunction ],\n    [ ATT_display, jsEvalToFunction ],\n    [ ATT_values, jsEvalToValues ],\n    [ ATT_vars, jsEvalToValues ],\n    [ ATT_eval, jsEvalToExpressions ],\n    [ ATT_transclude, jsEvalToSelf ],\n    [ ATT_content, jsEvalToFunction ],\n    [ ATT_skip, jsEvalToFunction ]\n];\n\n\n/**\n * Prepares a single node: preprocesses all template attributes of the\n * node, and if there are any, assigns a jsid attribute and stores the\n * preprocessed attributes under the jsid in the jstcache.\n *\n * @param {Element} node\n *\n * @return {Object} The jstcache entry. The processed jst attributes\n * are properties of this object. If the node has no jst attributes,\n * returns an object with no properties (the jscache_[0] entry).\n */\nJstProcessor.prepareNode_ = function(node) {\n  // If the node already has a cache property, return it.\n  if (node[PROP_jstcache]) {\n    return node[PROP_jstcache];\n  }\n\n  // If it is not found, we always set the PROP_jstcache property on the node.\n  // Accessing the property is faster than executing getAttribute(). If we\n  // don't find the property on a node that was cloned in jstSelect_(), we\n  // will fall back to check for the attribute and set the property\n  // from cache.\n\n  // If the node has an attribute indexing a cache object, set it as a property\n  // and return it.\n  var jstid = domGetAttribute(node, ATT_jstcache);\n  if (jstid != null) {\n    return node[PROP_jstcache] = JstProcessor.jstcache_[jstid];\n  }\n\n  var attributeValues = JstProcessor.attributeValues_;\n  var attributeList = JstProcessor.attributeList_;\n  attributeList.length = 0;\n\n  // Look for interesting attributes.\n  for (var i = 0, I = jsLength(JST_ATTRIBUTES); i < I; ++i) {\n    var name = JST_ATTRIBUTES[i][0];\n    var value = domGetAttribute(node, name);\n    attributeValues[name] = value;\n    if (value != null) {\n      attributeList.push(name + \"=\" + value);\n    }\n  }\n\n  // If none found, mark this node to prevent further inspection, and return\n  // an empty cache object.\n  if (attributeList.length == 0) {\n    domSetAttribute(node, ATT_jstcache, STRING_zero);\n    return node[PROP_jstcache] = JstProcessor.jstcache_[0];\n  }\n\n  // If we already have a cache object corresponding to these attributes,\n  // annotate the node with it, and return it.\n  var attstring = attributeList.join(CHAR_ampersand);\n  if (jstid = JstProcessor.jstcacheattributes_[attstring]) {\n    domSetAttribute(node, ATT_jstcache, jstid);\n    return node[PROP_jstcache] = JstProcessor.jstcache_[jstid];\n  }\n\n  // Otherwise, build a new cache object.\n  var jstcache = {};\n  for (var i = 0, I = jsLength(JST_ATTRIBUTES); i < I; ++i) {\n    var att = JST_ATTRIBUTES[i];\n    var name = att[0];\n    var parse = att[1];\n    var value = attributeValues[name];\n    if (value != null) {\n      jstcache[name] = parse(value);\n      if (MAPS_DEBUG) {\n        jstcache.jstAttributeValues = jstcache.jstAttributeValues || {};\n        jstcache.jstAttributeValues[name] = value;\n      }\n    }\n  }\n\n  jstid = STRING_empty + ++JstProcessor.jstid_;\n  domSetAttribute(node, ATT_jstcache, jstid);\n  JstProcessor.jstcache_[jstid] = jstcache;\n  JstProcessor.jstcacheattributes_[attstring] = jstid;\n\n  return node[PROP_jstcache] = jstcache;\n};\n\n\n/**\n * Runs the given function in our state machine.\n *\n * It's informative to view the set of all function calls as a tree:\n * - nodes are states\n * - edges are state transitions, implemented as calls to the pending\n *   functions in the stack.\n *   - pre-order function calls are downward edges (recursion into call).\n *   - post-order function calls are upward edges (return from call).\n * - leaves are nodes which do not recurse.\n * We represent the call tree as an array of array of calls, indexed as\n * stack[depth][index].  Here [depth] indexes into the call stack, and\n * [index] indexes into the call queue at that depth.  We require a call\n * queue so that a node may branch to more than one child\n * (which will be called serially), typically due to a loop structure.\n *\n * @param {Function} f The first function to run.\n */\nJstProcessor.prototype.run_ = function(f) {\n  var me = this;\n\n  /**\n   * A stack of queues of pre-order calls.\n   * The inner arrays (constituent queues) are structured as\n   * [ arg2, arg1, method, arg2, arg1, method, ...]\n   * ie. a flattened array of methods with 2 arguments, in reverse order\n   * for efficient push/pop.\n   *\n   * The outer array is a stack of such queues.\n   *\n   * @type Array<Array>\n   */\n  var calls = me.calls_ = [];\n\n  /**\n   * The index into the queue for each depth. NOTE: Alternative would\n   * be to maintain the queues in reverse order (popping off of the\n   * end) but the repeated calls to .pop() consumed 90% of this\n   * function's execution time.\n   * @type Array<number>\n   */\n  var queueIndices = me.queueIndices_ = [];\n\n  /**\n   * A pool of empty arrays.  Minimizes object allocation for IE6's benefit.\n   * @type Array<Array>\n   */\n  var arrayPool = me.arrayPool_ = [];\n\n  f();\n  var queue, queueIndex;\n  var method, arg1, arg2;\n  var temp;\n  while (calls.length) {\n    queue = calls[calls.length - 1];\n    queueIndex = queueIndices[queueIndices.length - 1];\n    if (queueIndex >= queue.length) {\n      me.recycleArray_(calls.pop());\n      queueIndices.pop();\n      continue;\n    }\n\n    // Run the first function in the queue.\n    method = queue[queueIndex++];\n    arg1 = queue[queueIndex++];\n    arg2 = queue[queueIndex++];\n    queueIndices[queueIndices.length - 1] = queueIndex;\n    method.call(me, arg1, arg2);\n  }\n};\n\n\n/**\n * Pushes one or more functions onto the stack.  These will be run in sequence,\n * interspersed with any recursive calls that they make.\n *\n * This method takes ownership of the given array!\n *\n * @param {Array} args Array of method calls structured as\n *     [ method, arg1, arg2, method, arg1, arg2, ... ]\n */\nJstProcessor.prototype.push_ = function(args) {\n  this.calls_.push(args);\n  this.queueIndices_.push(0);\n};\n\n\n/**\n * Enable/disable debugging.\n * @param {boolean} debugging New state\n */\nJstProcessor.prototype.setDebugging = function(debugging) {\n  if (MAPS_DEBUG) {\n    this.debugging_ = debugging;\n  }\n};\n\n\nJstProcessor.prototype.createArray_ = function() {\n  if (this.arrayPool_.length) {\n    return this.arrayPool_.pop();\n  } else {\n    return [];\n  }\n};\n\n\nJstProcessor.prototype.recycleArray_ = function(array) {\n  arrayClear(array);\n  this.arrayPool_.push(array);\n};\n\n/**\n * Implements internals of jstProcess. This processes the two\n * attributes transclude and jsselect, which replace or multiply\n * elements, hence the name \"outer\". The remainder of the attributes\n * is processed in jstProcessInner_(), below. That function\n * jsProcessInner_() only processes attributes that affect an existing\n * node, but doesn't create or destroy nodes, hence the name\n * \"inner\". jstProcessInner_() is called through jstSelect_() if there\n * is a jsselect attribute (possibly for newly created clones of the\n * current template node), or directly from here if there is none.\n *\n * @param {JsEvalContext} context\n *\n * @param {Element} template\n */\nJstProcessor.prototype.jstProcessOuter_ = function(context, template) {\n  var me = this;\n\n  var jstAttributes = me.jstAttributes_(template);\n  if (MAPS_DEBUG && me.debugging_) {\n    me.logState_('Outer', template, jstAttributes.jstAttributeValues);\n  }\n\n  var transclude = jstAttributes[ATT_transclude];\n  if (transclude) {\n    var tr = jstGetTemplate(transclude);\n    if (tr) {\n      domReplaceChild(tr, template);\n      var call = me.createArray_();\n      call.push(me.jstProcessOuter_, context, tr);\n      me.push_(call);\n    } else {\n      domRemoveNode(template);\n    }\n    return;\n  }\n\n  var select = jstAttributes[ATT_select];\n  if (select) {\n    me.jstSelect_(context, template, select);\n  } else {\n    me.jstProcessInner_(context, template);\n  }\n};\n\n\n/**\n * Implements internals of jstProcess. This processes all attributes\n * except transclude and jsselect. It is called either from\n * jstSelect_() for nodes that have a jsselect attribute so that the\n * jsselect attribute will not be processed again, or else directly\n * from jstProcessOuter_(). See the comment on jstProcessOuter_() for\n * an explanation of the name.\n *\n * @param {JsEvalContext} context\n *\n * @param {Element} template\n */\nJstProcessor.prototype.jstProcessInner_ = function(context, template) {\n  var me = this;\n\n  var jstAttributes = me.jstAttributes_(template);\n  if (MAPS_DEBUG && me.debugging_) {\n    me.logState_('Inner', template, jstAttributes.jstAttributeValues);\n  }\n\n  // NOTE(mesch): See NOTE on ATT_content why this is a separate\n  // attribute, and not a special value in ATT_values.\n  var display = jstAttributes[ATT_display];\n  if (display) {\n    var shouldDisplay = context.jsexec(display, template);\n    if (MAPS_DEBUG && me.debugging_) {\n      me.logs_.push(ATT_display + ': ' + shouldDisplay + '<br/>');\n    }\n    if (!shouldDisplay) {\n      displayNone(template);\n      return;\n    }\n    displayDefault(template);\n  }\n\n  // NOTE(mesch): jsvars is evaluated before jsvalues, because it's\n  // more useful to be able to use var values in attribute value\n  // expressions than vice versa.\n  var values = jstAttributes[ATT_vars];\n  if (values) {\n    me.jstVars_(context, template, values);\n  }\n\n  values = jstAttributes[ATT_values];\n  if (values) {\n    me.jstValues_(context, template, values);\n  }\n\n  // Evaluate expressions immediately. Useful for hooking callbacks\n  // into jstemplates.\n  //\n  // NOTE(mesch): Evaluation order is sometimes significant, e.g. when\n  // the expression evaluated in jseval relies on the values set in\n  // jsvalues, so it needs to be evaluated *after*\n  // jsvalues. TODO(mesch): This is quite arbitrary, it would be\n  // better if this would have more necessity to it.\n  var expressions = jstAttributes[ATT_eval];\n  if (expressions) {\n    for (var i = 0, I = jsLength(expressions); i < I; ++i) {\n      context.jsexec(expressions[i], template);\n    }\n  }\n\n  var skip = jstAttributes[ATT_skip];\n  if (skip) {\n    var shouldSkip = context.jsexec(skip, template);\n    if (MAPS_DEBUG && me.debugging_) {\n      me.logs_.push(ATT_skip + ': ' + shouldSkip + '<br/>');\n    }\n    if (shouldSkip) return;\n  }\n\n  // NOTE(mesch): content is a separate attribute, instead of just a\n  // special value mentioned in values, for two reasons: (1) it is\n  // fairly common to have only mapped content, and writing\n  // content=\"expr\" is shorter than writing values=\"content:expr\", and\n  // (2) the presence of content actually terminates traversal, and we\n  // need to check for that. Display is a separate attribute for a\n  // reason similar to the second, in that its presence *may*\n  // terminate traversal.\n  var content = jstAttributes[ATT_content];\n  if (content) {\n    me.jstContent_(context, template, content);\n\n  } else {\n    // Newly generated children should be ignored, so we explicitly\n    // store the children to be processed.\n    var queue = me.createArray_();\n    for (var c = template.firstChild; c; c = c.nextSibling) {\n      if (c.nodeType == DOM_ELEMENT_NODE) {\n        queue.push(me.jstProcessOuter_, context, c);\n      }\n    }\n    if (queue.length) me.push_(queue);\n  }\n};\n\n\n/**\n * Implements the jsselect attribute: evalutes the value of the\n * jsselect attribute in the current context, with the current\n * variable bindings (see JsEvalContext.jseval()). If the value is an\n * array, the current template node is multiplied once for every\n * element in the array, with the array element being the context\n * object. If the array is empty, or the value is undefined, then the\n * current template node is dropped. If the value is not an array,\n * then it is just made the context object.\n *\n * @param {JsEvalContext} context The current evaluation context.\n *\n * @param {Element} template The currently processed node of the template.\n *\n * @param {Function} select The javascript expression to evaluate.\n *\n * @notypecheck FIXME(hmitchell): See OCL6434950. instance and value need\n * type checks.\n */\nJstProcessor.prototype.jstSelect_ = function(context, template, select) {\n  var me = this;\n\n  var value = context.jsexec(select, template);\n\n  // Enable reprocessing: if this template is reprocessed, then only\n  // fill the section instance here. Otherwise do the cardinal\n  // processing of a new template.\n  var instance = domGetAttribute(template, ATT_instance);\n\n  var instanceLast = false;\n  if (instance) {\n    if (instance.charAt(0) == CHAR_asterisk) {\n      instance = parseInt10(instance.substr(1));\n      instanceLast = true;\n    } else {\n      instance = parseInt10(/** @type string */(instance));\n    }\n  }\n\n  // The expression value instanceof Array is occasionally false for\n  // arrays, seen in Firefox. Thus we recognize an array as an object\n  // which is not null that has a length property. Notice that this\n  // also matches input data with a length property, so this property\n  // name should be avoided in input data.\n  var multiple = isArray(value);\n  var count = multiple ? jsLength(value) : 1;\n  var multipleEmpty = (multiple && count == 0);\n\n  if (multiple) {\n    if (multipleEmpty) {\n      // For an empty array, keep the first template instance and mark\n      // it last. Remove all other template instances.\n      if (!instance) {\n        domSetAttribute(template, ATT_instance, STRING_asteriskzero);\n        displayNone(template);\n      } else {\n        domRemoveNode(template);\n      }\n\n    } else {\n      displayDefault(template);\n      // For a non empty array, create as many template instances as\n      // are needed. If the template is first processed, as many\n      // template instances are needed as there are values in the\n      // array. If the template is reprocessed, new template instances\n      // are only needed if there are more array values than template\n      // instances. Those additional instances are created by\n      // replicating the last template instance.\n      //\n      // When the template is first processed, there is no jsinstance\n      // attribute. This is indicated by instance === null, except in\n      // opera it is instance === \"\". Notice also that the === is\n      // essential, because 0 == \"\", presumably via type coercion to\n      // boolean.\n      if (instance === null || instance === STRING_empty ||\n          (instanceLast && instance < count - 1)) {\n        // A queue of calls to push.\n        var queue = me.createArray_();\n\n        var instancesStart = instance || 0;\n        var i, I, clone;\n        for (i = instancesStart, I = count - 1; i < I; ++i) {\n          var node = domCloneNode(template);\n          domInsertBefore(node, template);\n\n          jstSetInstance(/** @type Element */(node), value, i);\n          clone = context.clone(value[i], i, count);\n\n          queue.push(me.jstProcessInner_, clone, node,\n                     JsEvalContext.recycle, clone, null);\n                     \n        }\n        // Push the originally present template instance last to keep\n        // the order aligned with the DOM order, because the newly\n        // created template instances are inserted *before* the\n        // original instance.\n        jstSetInstance(template, value, i);\n        clone = context.clone(value[i], i, count);\n        queue.push(me.jstProcessInner_, clone, template,\n                   JsEvalContext.recycle, clone, null);\n        me.push_(queue);\n      } else if (instance < count) {\n        var v = value[instance];\n\n        jstSetInstance(template, value, instance);\n        var clone = context.clone(v, instance, count);\n        var queue = me.createArray_();\n        queue.push(me.jstProcessInner_, clone, template,\n                   JsEvalContext.recycle, clone, null);\n        me.push_(queue);\n      } else {\n        domRemoveNode(template);\n      }\n    }\n  } else {\n    if (value == null) {\n      displayNone(template);\n    } else {\n      displayDefault(template);\n      var clone = context.clone(value, 0, 1);\n      var queue = me.createArray_();\n      queue.push(me.jstProcessInner_, clone, template,\n                 JsEvalContext.recycle, clone, null);\n      me.push_(queue);\n    }\n  }\n};\n\n\n/**\n * Implements the jsvars attribute: evaluates each of the values and\n * assigns them to variables in the current context. Similar to\n * jsvalues, except that all values are treated as vars, independent\n * of their names.\n *\n * @param {JsEvalContext} context Current evaluation context.\n *\n * @param {Element} template Currently processed template node.\n *\n * @param {Array} values Processed value of the jsvalues attribute: a\n * flattened array of pairs. The second element in the pair is a\n * function that can be passed to jsexec() for evaluation in the\n * current jscontext, and the first element is the variable name that\n * the value returned by jsexec is assigned to.\n */\nJstProcessor.prototype.jstVars_ = function(context, template, values) {\n  for (var i = 0, I = jsLength(values); i < I; i += 2) {\n    var label = values[i];\n    var value = context.jsexec(values[i+1], template);\n    context.setVariable(label, value);\n  }\n};\n\n\n/**\n * Implements the jsvalues attribute: evaluates each of the values and\n * assigns them to variables in the current context (if the name\n * starts with '$', javascript properties of the current template node\n * (if the name starts with '.'), or DOM attributes of the current\n * template node (otherwise). Since DOM attribute values are always\n * strings, the value is coerced to string in the latter case,\n * otherwise it's the uncoerced javascript value.\n *\n * @param {JsEvalContext} context Current evaluation context.\n *\n * @param {Element} template Currently processed template node.\n *\n * @param {Array} values Processed value of the jsvalues attribute: a\n * flattened array of pairs. The second element in the pair is a\n * function that can be passed to jsexec() for evaluation in the\n * current jscontext, and the first element is the label that\n * determines where the value returned by jsexec is assigned to.\n */\nJstProcessor.prototype.jstValues_ = function(context, template, values) {\n  for (var i = 0, I = jsLength(values); i < I; i += 2) {\n    var label = values[i];\n    var value = context.jsexec(values[i+1], template);\n\n    if (label.charAt(0) == CHAR_dollar) {\n      // A jsvalues entry whose name starts with $ sets a local\n      // variable.\n      context.setVariable(label, value);\n\n    } else if (label.charAt(0) == CHAR_period) {\n      // A jsvalues entry whose name starts with . sets a property of\n      // the current template node. The name may have further dot\n      // separated components, which are translated into namespace\n      // objects. This specifically allows to set properties on .style\n      // using jsvalues. NOTE(mesch): Setting the style attribute has\n      // no effect in IE and hence should not be done anyway.\n      var nameSpaceLabel = label.substr(1).split(CHAR_period);\n      var nameSpaceObject = template;\n      var nameSpaceDepth = jsLength(nameSpaceLabel);\n      for (var j = 0, J = nameSpaceDepth - 1; j < J; ++j) {\n        var jLabel = nameSpaceLabel[j];\n        if (!nameSpaceObject[jLabel]) {\n          nameSpaceObject[jLabel] = {};\n        }\n        nameSpaceObject = nameSpaceObject[jLabel];\n      }\n      nameSpaceObject[nameSpaceLabel[nameSpaceDepth - 1]] = value;\n\n    } else if (label) {\n      // Any other jsvalues entry sets an attribute of the current\n      // template node.\n      if (typeof value == TYPE_boolean) {\n        // Handle boolean values that are set as attributes specially,\n        // according to the XML/HTML convention.\n        if (value) {\n          domSetAttribute(template, label, label);\n        } else {\n          domRemoveAttribute(template, label);\n        }\n      } else {\n        domSetAttribute(template, label, STRING_empty + value);\n      }\n    }\n  }\n};\n\n\n/**\n * Implements the jscontent attribute. Evalutes the expression in\n * jscontent in the current context and with the current variables,\n * and assigns its string value to the content of the current template\n * node.\n *\n * @param {JsEvalContext} context Current evaluation context.\n *\n * @param {Element} template Currently processed template node.\n *\n * @param {Function} content Processed value of the jscontent\n * attribute.\n */\nJstProcessor.prototype.jstContent_ = function(context, template, content) {\n  // NOTE(mesch): Profiling shows that this method costs significant\n  // time. In jstemplate_perf.html, it's about 50%. I tried to replace\n  // by HTML escaping and assignment to innerHTML, but that was even\n  // slower.\n  var value = STRING_empty + context.jsexec(content, template);\n  // Prevent flicker when refreshing a template and the value doesn't\n  // change.\n  if (template.innerHTML == value) {\n    return;\n  }\n  while (template.firstChild) {\n    domRemoveNode(template.firstChild);\n  }\n  var t = domCreateTextNode(this.document_, value);\n  domAppendChild(template, t);\n};\n\n\n/**\n * Caches access to and parsing of template processing attributes. If\n * domGetAttribute() is called every time a template attribute value\n * is used, it takes more than 10% of the time.\n *\n * @param {Element} template A DOM element node of the template.\n *\n * @return {Object} A javascript object that has all js template\n * processing attribute values of the node as properties.\n */\nJstProcessor.prototype.jstAttributes_ = function(template) {\n  if (template[PROP_jstcache]) {\n    return template[PROP_jstcache];\n  }\n\n  var jstid = domGetAttribute(template, ATT_jstcache);\n  if (jstid) {\n    return template[PROP_jstcache] = JstProcessor.jstcache_[jstid];\n  }\n\n  return JstProcessor.prepareNode_(template);\n};\n\n\n/**\n * Helps to implement the transclude attribute, and is the initial\n * call to get hold of a template from its ID.\n *\n * If the ID is not present in the DOM, and opt_loadHtmlFn is specified, this\n * function will call that function and add the result to the DOM, before\n * returning the template.\n *\n * @param {string} name The ID of the HTML element used as template.\n * @param {Function} opt_loadHtmlFn A function which, when called, will return\n *   HTML that contains an element whose ID is 'name'.\n *\n * @return {Element|null} The DOM node of the template. (Only element nodes\n * can be found by ID, hence it's a Element.)\n */\nfunction jstGetTemplate(name, opt_loadHtmlFn) {\n  var doc = document;\n  var section;\n  if (opt_loadHtmlFn) {\n    section = jstLoadTemplateIfNotPresent(doc, name, opt_loadHtmlFn);\n  } else {\n    section = domGetElementById(doc, name);\n  }\n  if (section) {\n    JstProcessor.prepareTemplate_(section);\n    var ret = domCloneElement(section);\n    domRemoveAttribute(ret, STRING_id);\n    return ret;\n  } else {\n    return null;\n  }\n}\n\n/**\n * This function is the same as 'jstGetTemplate' but, if the template\n * does not exist, throw an exception.\n *\n * @param {string} name The ID of the HTML element used as template.\n * @param {Function} opt_loadHtmlFn A function which, when called, will return\n *   HTML that contains an element whose ID is 'name'.\n *\n * @return {Element} The DOM node of the template. (Only element nodes\n * can be found by ID, hence it's a Element.)\n */\nfunction jstGetTemplateOrDie(name, opt_loadHtmlFn) {\n  var x = jstGetTemplate(name, opt_loadHtmlFn);\n  check(x !== null);\n  return /** @type Element */(x);\n}\n\n\n/**\n * If an element with id 'name' is not present in the document, call loadHtmlFn\n * and insert the result into the DOM.\n *\n * @param {Document} doc\n * @param {string} name\n * @param {Function} loadHtmlFn A function that returns HTML to be inserted\n * into the DOM.\n * @param {string} opt_target The id of a DOM object under which to attach the\n *   HTML once it's inserted.  An object with this id is created if it does not\n *   exist.\n * @return {Element} The node whose id is 'name'\n */\nfunction jstLoadTemplateIfNotPresent(doc, name, loadHtmlFn, opt_target) {\n  var section = domGetElementById(doc, name);\n  if (section) {\n    return section;\n  }\n  // Load any necessary HTML and try again.\n  jstLoadTemplate_(doc, loadHtmlFn(), opt_target || STRING_jsts);\n  var section = domGetElementById(doc, name);\n  if (!section) {\n    log(\"Error: jstGetTemplate was provided with opt_loadHtmlFn, \" +\n\t\"but that function did not provide the id '\" + name + \"'.\");\n  }\n  return /** @type Element */(section);\n}\n\n\n/**\n * Loads the given HTML text into the given document, so that\n * jstGetTemplate can find it.\n *\n * We append it to the element identified by targetId, which is hidden.\n * If it doesn't exist, it is created.\n *\n * @param {Document} doc The document to create the template in.\n *\n * @param {string} html HTML text to be inserted into the document.\n *\n * @param {string} targetId The id of a DOM object under which to attach the\n *   HTML once it's inserted.  An object with this id is created if it does not\n *   exist.\n */\nfunction jstLoadTemplate_(doc, html, targetId) {\n  var existing_target = domGetElementById(doc, targetId);\n  var target;\n  if (!existing_target) {\n    target = domCreateElement(doc, STRING_div);\n    target.id = targetId;\n    displayNone(target);\n    positionAbsolute(target);\n    domAppendChild(doc.body, target);\n  } else {\n    target = existing_target;\n  }\n  var div = domCreateElement(doc, STRING_div);\n  target.appendChild(div);\n  div.innerHTML = html;\n}\n\n\n/**\n * Sets the jsinstance attribute on a node according to its context.\n *\n * @param {Element} template The template DOM node to set the instance\n * attribute on.\n *\n * @param {Array} values The current input context, the array of\n * values of which the template node will render one instance.\n *\n * @param {number} index The index of this template node in values.\n */\nfunction jstSetInstance(template, values, index) {\n  if (index == jsLength(values) - 1) {\n    domSetAttribute(template, ATT_instance, CHAR_asterisk + index);\n  } else {\n    domSetAttribute(template, ATT_instance, STRING_empty + index);\n  }\n}\n\n\n/**\n * Log the current state.\n * @param {string} caller An identifier for the caller of .log_.\n * @param {Element} template The template node being processed.\n * @param {Object} jstAttributeValues The jst attributes of the template node.\n */\nJstProcessor.prototype.logState_ = function(\n    caller, template, jstAttributeValues) {\n  if (MAPS_DEBUG) {\n    var msg = '<table>';\n    msg += '<caption>' + caller + '</caption>';\n    msg += '<tbody>';\n    if (template.id) {\n      msg += '<tr><td>' + 'id:' + '</td><td>' + template.id + '</td></tr>';\n    }\n    if (template.name) {\n      msg += '<tr><td>' + 'name:' + '</td><td>' + template.name + '</td></tr>';\n    }\n    if (jstAttributeValues) {\n      msg += '<tr><td>' + 'attr:' +\n      '</td><td>' + jsToSource(jstAttributeValues) + '</td></tr>';\n    }\n    msg += '</tbody></table><br/>';\n    this.logs_.push(msg);\n  }\n};\n\n\n/**\n * Retrieve the processing logs.\n * @return {Array<string>} The processing logs.\n */\nJstProcessor.prototype.getLogs = function() {\n  return this.logs_;\n};\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/servlet/jstemplate/util.js",
    "content": "// Copyright 2006 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n// implied. See the License for the specific language governing\n// permissions and limitations under the License.\n/**\n * @fileoverview Miscellaneous constants and functions referenced in\n * the main source files.\n *\n * @author Steffen Meschkat (mesch@google.com)\n */\n\nvar MAPS_DEBUG = false;\n\nfunction log(msg) {}\n\n// String literals defined globally and not to be inlined. (IE6 perf)\n/** @const */ var STRING_empty = '';\n\n/** @const */ var CSS_display = 'display';\n/** @const */ var CSS_position = 'position';\n\n// Constants for possible values of the typeof operator.\nvar TYPE_boolean = 'boolean';\nvar TYPE_number = 'number';\nvar TYPE_object = 'object';\nvar TYPE_string = 'string';\nvar TYPE_function = 'function';\nvar TYPE_undefined = 'undefined';\n\n\n/**\n * Wrapper for the eval() builtin function to evaluate expressions and\n * obtain their value. It wraps the expression in parentheses such\n * that object literals are really evaluated to objects. Without the\n * wrapping, they are evaluated as block, and create syntax\n * errors. Also protects against other syntax errors in the eval()ed\n * code and returns null if the eval throws an exception.\n *\n * @param {string} expr\n * @return {Object|null}\n */\nfunction jsEval(expr) {\n  try {\n    // NOTE(mesch): An alternative idiom would be:\n    //\n    //   eval('(' + expr + ')');\n    //\n    // Note that using the square brackets as below, \"\" evals to undefined.\n    // The alternative of using parentheses does not work when evaluating\n    // function literals in IE.\n    // e.g. eval(\"(function() {})\") returns undefined, and not a function\n    // object, in IE.\n    return eval('[' + expr + '][0]');\n  } catch (e) {\n    log('EVAL FAILED ' + expr + ': ' + e);\n    return null;\n  }\n}\n\nfunction jsLength(obj) {\n  return obj.length;\n}\n\nfunction assert(obj) {}\n\n/**\n * Copies all properties from second object to the first.  Modifies to.\n *\n * @param {Object} to  The target object.\n * @param {Object} from  The source object.\n */\nfunction copyProperties(to, from) {\n  for (var p in from) {\n    to[p] = from[p];\n  }\n}\n\n\n/**\n * @param {Object|null|undefined} value The possible value to use.\n * @param {Object} defaultValue The default if the value is not set.\n * @return {Object} The value, if it is\n * defined and not null; otherwise the default\n */\nfunction getDefaultObject(value, defaultValue) {\n  if (typeof value != TYPE_undefined && value != null) {\n    return /** @type Object */(value);\n  } else {\n    return defaultValue;\n  }\n}\n\n/**\n * Detect if an object looks like an Array.\n * Note that instanceof Array is not robust; for example an Array\n * created in another iframe fails instanceof Array.\n * @param {Object|null} value Object to interrogate\n * @return {boolean} Is the object an array?\n */\nfunction isArray(value) {\n  return value != null &&\n      typeof value == TYPE_object &&\n      typeof value.length == TYPE_number;\n}\n\n\n/**\n * Finds a slice of an array.\n *\n * @param {Array} array  Array to be sliced.\n * @param {number} start  The start of the slice.\n * @param {number} opt_end  The end of the slice (optional).\n * @return {Array} array  The slice of the array from start to end.\n */\nfunction arraySlice(array, start, opt_end) {\n  // Use\n  //   return Function.prototype.call.apply(Array.prototype.slice, arguments);\n  // instead of the simpler\n  //   return Array.prototype.slice.call(array, start, opt_end);\n  // here because of a bug in the FF and IE implementations of\n  // Array.prototype.slice which causes this function to return an empty list\n  // if opt_end is not provided.\n  return Function.prototype.call.apply(Array.prototype.slice, arguments);\n}\n\n\n/**\n * Jscompiler wrapper for parseInt() with base 10.\n *\n * @param {string} s string repersentation of a number.\n *\n * @return {number} The integer contained in s, converted on base 10.\n */\nfunction parseInt10(s) {\n  return parseInt(s, 10);\n}\n\n\n/**\n * Clears the array by setting the length property to 0. This usually\n * works, and if it should turn out not to work everywhere, here would\n * be the place to implement the browser specific workaround.\n *\n * @param {Array} array  Array to be cleared.\n */\nfunction arrayClear(array) {\n  array.length = 0;\n}\n\n\n/**\n * Prebinds \"this\" within the given method to an object, but ignores all \n * arguments passed to the resulting function.\n * I.e. var_args are all the arguments that method is invoked with when\n * invoking the bound function.\n *\n * @param {Object|null} object  The object that the method call targets.\n * @param {Function} method  The target method.\n * @return {Function}  Method with the target object bound to it and curried by\n *                     the provided arguments.\n */\nfunction bindFully(object, method, var_args) {\n  var args = arraySlice(arguments, 2);\n  return function() {\n    return method.apply(object, args);\n  }\n}\n\n// Based on <http://www.w3.org/TR/2000/ REC-DOM-Level-2-Core-20001113/\n// core.html#ID-1950641247>.\nvar DOM_ELEMENT_NODE = 1;\nvar DOM_ATTRIBUTE_NODE = 2;\nvar DOM_TEXT_NODE = 3;\nvar DOM_CDATA_SECTION_NODE = 4;\nvar DOM_ENTITY_REFERENCE_NODE = 5;\nvar DOM_ENTITY_NODE = 6;\nvar DOM_PROCESSING_INSTRUCTION_NODE = 7;\nvar DOM_COMMENT_NODE = 8;\nvar DOM_DOCUMENT_NODE = 9;\nvar DOM_DOCUMENT_TYPE_NODE = 10;\nvar DOM_DOCUMENT_FRAGMENT_NODE = 11;\nvar DOM_NOTATION_NODE = 12;\n\n\n\nfunction domGetElementById(document, id) {\n  return document.getElementById(id);\n}\n\n/**\n * Creates a new node in the given document\n *\n * @param {Document} doc  Target document.\n * @param {string} name  Name of new element (i.e. the tag name)..\n * @return {Element}  Newly constructed element.\n */\nfunction domCreateElement(doc, name) {\n  return doc.createElement(name);\n}\n\n/**\n * Traverses the element nodes in the DOM section underneath the given\n * node and invokes the given callback as a method on every element\n * node encountered.\n *\n * @param {Element} node  Parent element of the subtree to traverse.\n * @param {Function} callback  Called on each node in the traversal.\n */\nfunction domTraverseElements(node, callback) {\n  var traverser = new DomTraverser(callback);\n  traverser.run(node);\n}\n\n/**\n * A class to hold state for a dom traversal.\n * @param {Function} callback  Called on each node in the traversal.\n * @constructor\n * @class\n */\nfunction DomTraverser(callback) {\n  this.callback_ = callback;\n}\n\n/**\n * Processes the dom tree in breadth-first order.\n * @param {Element} root  The root node of the traversal.\n */\nDomTraverser.prototype.run = function(root) {\n  var me = this;\n  me.queue_ = [ root ];\n  while (jsLength(me.queue_)) {\n    me.process_(me.queue_.shift());\n  }\n}\n\n/**\n * Processes a single node.\n * @param {Element} node  The current node of the traversal.\n */\nDomTraverser.prototype.process_ = function(node) {\n  var me = this;\n\n  me.callback_(node);\n\n  for (var c = node.firstChild; c; c = c.nextSibling) {\n    if (c.nodeType == DOM_ELEMENT_NODE) {\n      me.queue_.push(c);\n    }\n  }\n}\n\n/**\n * Get an attribute from the DOM.  Simple redirect, exists to compress code.\n *\n * @param {Element} node  Element to interrogate.\n * @param {string} name  Name of parameter to extract.\n * @return {string|null}  Resulting attribute.\n */\nfunction domGetAttribute(node, name) {\n  return node.getAttribute(name);\n  // NOTE(mesch): Neither in IE nor in Firefox, HTML DOM attributes\n  // implement namespaces. All items in the attribute collection have\n  // null localName and namespaceURI attribute values. In IE, we even\n  // encounter DIV elements that don't implement the method\n  // getAttributeNS().\n}\n\n\n/**\n * Set an attribute in the DOM.  Simple redirect to compress code.\n *\n * @param {Element} node  Element to interrogate.\n * @param {string} name  Name of parameter to set.\n * @param {string|number} value  Set attribute to this value.\n */\nfunction domSetAttribute(node, name, value) {\n  node.setAttribute(name, value);\n}\n\n/**\n * Remove an attribute from the DOM.  Simple redirect to compress code.\n *\n * @param {Element} node  Element to interrogate.\n * @param {string} name  Name of parameter to remove.\n */\nfunction domRemoveAttribute(node, name) {\n  node.removeAttribute(name);\n}\n\n/**\n * Clone a node in the DOM.\n *\n * @param {Node} node  Node to clone.\n * @return {Node}  Cloned node.\n */\nfunction domCloneNode(node) {\n  return node.cloneNode(true);\n  // NOTE(mesch): we never so far wanted to use cloneNode(false),\n  // hence the default.\n}\n\n/**\n * Clone a element in the DOM.\n *\n * @param {Element} element  Element to clone.\n * @return {Element}  Cloned element.\n */\nfunction domCloneElement(element) {\n  return /** @type {Element} */(domCloneNode(element));\n}\n\n/**\n * Returns the document owner of the given element. In particular,\n * returns window.document if node is null or the browser does not\n * support ownerDocument.  If the node is a document itself, returns\n * itself.\n *\n * @param {Node|null|undefined} node  The node whose ownerDocument is required.\n * @returns {Document}  The owner document or window.document if unsupported.\n */\nfunction ownerDocument(node) {\n  if (!node) {\n    return document;\n  } else if (node.nodeType == DOM_DOCUMENT_NODE) {\n    return /** @type Document */(node);\n  } else {\n    return node.ownerDocument || document;\n  }\n}\n\n/**\n * Creates a new text node in the given document.\n *\n * @param {Document} doc  Target document.\n * @param {string} text  Text composing new text node.\n * @return {Text}  Newly constructed text node.\n */\nfunction domCreateTextNode(doc, text) {\n  return doc.createTextNode(text);\n}\n\n/**\n * Appends a new child to the specified (parent) node.\n *\n * @param {Element} node  Parent element.\n * @param {Node} child  Child node to append.\n * @return {Node}  Newly appended node.\n */\nfunction domAppendChild(node, child) {\n  return node.appendChild(child);\n}\n\n/**\n * Sets display to default.\n *\n * @param {Element} node  The dom element to manipulate.\n */\nfunction displayDefault(node) {\n  node.style[CSS_display] = '';\n}\n\n/**\n * Sets display to none. Doing this as a function saves a few bytes for\n * the 'style.display' property and the 'none' literal.\n *\n * @param {Element} node  The dom element to manipulate.\n */\nfunction displayNone(node) {\n  node.style[CSS_display] = 'none';\n}\n\n\n/**\n * Sets position style attribute to absolute.\n *\n * @param {Element} node  The dom element to manipulate.\n */\nfunction positionAbsolute(node) {\n  node.style[CSS_position] = 'absolute';\n}\n\n\n/**\n * Inserts a new child before a given sibling.\n *\n * @param {Node} newChild  Node to insert.\n * @param {Node} oldChild  Sibling node.\n * @return {Node}  Reference to new child.\n */\nfunction domInsertBefore(newChild, oldChild) {\n  return oldChild.parentNode.insertBefore(newChild, oldChild);\n}\n\n/**\n * Replaces an old child node with a new child node.\n *\n * @param {Node} newChild  New child to append.\n * @param {Node} oldChild  Old child to remove.\n * @return {Node}  Replaced node.\n */\nfunction domReplaceChild(newChild, oldChild) {\n  return oldChild.parentNode.replaceChild(newChild, oldChild);\n}\n\n/**\n * Removes a node from the DOM.\n *\n * @param {Node} node  The node to remove.\n * @return {Node}  The removed node.\n */\nfunction domRemoveNode(node) {\n  return domRemoveChild(node.parentNode, node);\n}\n\n/**\n * Remove a child from the specified (parent) node.\n *\n * @param {Element} node  Parent element.\n * @param {Node} child  Child node to remove.\n * @return {Node}  Removed node.\n */\nfunction domRemoveChild(node, child) {\n  return node.removeChild(child);\n}\n\n\n/**\n * Trim whitespace from begin and end of string.\n *\n * @see testStringTrim();\n *\n * @param {string} str  Input string.\n * @return {string}  Trimmed string.\n */\nfunction stringTrim(str) {\n  return stringTrimRight(stringTrimLeft(str));\n}\n\n/**\n * Trim whitespace from beginning of string.\n *\n * @see testStringTrimLeft();\n *\n * @param {string} str  Input string.\n * @return {string}  Trimmed string.\n */\nfunction stringTrimLeft(str) {\n  return str.replace(/^\\s+/, \"\");\n}\n\n/**\n * Trim whitespace from end of string.\n *\n * @see testStringTrimRight();\n *\n * @param {string} str  Input string.\n * @return {string}  Trimmed string.\n  */\nfunction stringTrimRight(str) {\n  return str.replace(/\\s+$/, \"\");\n}"
  },
  {
    "path": "_archive/mv2/extensions/irc/servlet/notification.html",
    "content": "<html>\n  <head>\n    <script src=\"util.js\" type=\"text/javascript\"></script>\n    <style>\nbody {\n  margin: 0px;\n  padding: 0px;\n  -webkit-user-select: none;\n}\n\n#notification {\n  width: 300px;\n  height: 50px;\n  position: fixed;\n  overflow: hidden;\n  display: -webkit-box;\n  -webkit-box-orient: vertical;\n  -webkit-box-align: stretch;\n}\n\n#title {\n  display: -webkit-box;\n  -webkit-box-flex: 0;\n  padding: 2px 4px 2px 4px;\n  background-color: #AAAAAA;\n  color: white;\n  font-family: Verdana, sans-serif;\n  font-size: 10px;\n}\n\n#content {\n  display: -webkit-box;\n  -webkit-box-flex: 1;\n  color: #444444;\n  font-family: \"Lucida Console\", Monospace;\n  font-size: 12px;\n  padding: 4px;\n  text-overflow: ellipsis;\n}\n    </style>\n    <script>\nwindow.onload = function() {\n  var argString = location.search.substring(location.search.indexOf(\"?\") + 1);\n  var tokens = argString.split(\"&\");\n  var args = {};\n  tokens.forEach(function(token) {\n    var keyVal = token.split(\"=\");\n    args[keyVal[0]] = decodeURIComponent(keyVal[1]);\n  });\n\n  $('title').innerText = args.title;\n  $('content').innerText = args.content;\n}\n    </script>   \n  </head>\n  <body onclick=\"window.close();\">\n    <div id=\"notification\">\n      <div id=\"title\"></div>\n      <div id=\"content\"></div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/servlet/src/org/chromium/IRCProxyWebSocket.java",
    "content": "package org.chromium;\n\nimport org.eclipse.jetty.websocket.WebSocket;\nimport org.eclipse.jetty.websocket.WebSocketServlet;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.io.OutputStreamWriter;\nimport java.net.Socket;\nimport java.net.UnknownHostException;\nimport java.util.Set;\nimport java.util.concurrent.CopyOnWriteArraySet;\n\nimport javax.net.SocketFactory;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\npublic class IRCProxyWebSocket extends WebSocketServlet {\n\n  private static final long serialVersionUID = 1L;\n\n  private final Set<ChatWebSocket> members_ =\n      new CopyOnWriteArraySet<ChatWebSocket>();\n\n  protected void doGet(HttpServletRequest request, HttpServletResponse response) \n      throws ServletException ,IOException {\n    getServletContext().getNamedDispatcher(\"default\").forward(request,response);\n  }\n  \n  protected WebSocket doWebSocketConnect(HttpServletRequest request,\n                                         String protocol) {\n    return new ChatWebSocket(); \n  }\n  \n  class ChatWebSocket implements WebSocket, Runnable {\n    Outbound outbound_;\n    Socket socket_ = null;\n    OutputStreamWriter out_;\n    BufferedReader in_;\n    Thread thread_;\n    byte frame_ = 0;\n\n    public void onConnect(Outbound outbound) {\n      outbound_= outbound;\n    }\n      \n    public void onMessage(byte frame, byte[] data,int offset, int length) {}\n\n    public void onMessage(byte frame, String data) {\n      try {\n        if (socket_ == null) {\n          try {\n            // We assume the client is going to connect and initiate a\n            // connection with the message \"server:port\".\n            String tokens[] = data.split(\":\");\n            socket_ = SocketFactory.getDefault().createSocket(tokens[0],\n                Integer.parseInt(tokens[1]));\n            out_ = new OutputStreamWriter(socket_.getOutputStream());\n            InputStreamReader in = new InputStreamReader(\n                socket_.getInputStream());\n            in_ = new BufferedReader(in);\n\n            members_.add(this);\n            thread_ = new Thread(this);\n            thread_.start();\n            \n          } catch (UnknownHostException e) {\n            // TODO Auto-generated catch block\n            e.printStackTrace();\n          } catch (IOException e) {\n            // TODO Auto-generated catch block\n            e.printStackTrace();\n          } \n        } else {\n          System.out.print(\">> \" + data);\n          out_.write(data);\n          out_.flush();\n        }        \n      } catch (IOException e) {\n        // TODO Auto-generated catch block\n        e.printStackTrace();\n      }\n    }\n\n    public void onDisconnect() {\n      try {\n        socket_.close();\n        thread_.stop();\n      } catch (IOException e) {\n        // TODO Auto-generated catch block\n        e.printStackTrace();\n      }\n      members_.remove(this);\n    }\n\n    @Override\n    public void run() {\n      while(true) {\n        try {\n           if (in_.ready()) {\n            String line = in_.readLine();\n            System.out.println(\"<< \" + line);\n            outbound_.sendMessage(frame_, line + \"\\r\\n\");\n           \n          } else {\n            Thread.sleep(100);\n          }\n        } catch (IOException e) {\n        } catch (InterruptedException e) {\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/servlet/styles.css",
    "content": "body {\n  margin: 0;\n  padding: 0;\n}\n\n#pageContainer {\n  display: -webkit-box;\n  position: fixed;\n  -webkit-box-orient: vertical;\n  -webkit-box-align: stretch;\n  height: 100%;\n  width: 100%;\n }\n\n #headerContainer {\n  display: -webkit-box;\n  height: 32px;\n  -webkit-box-orient: horizontal;\n  -webkit-box-align: stretch;\n }\n\n#pageControls {\n  position: absolute;\n  right: 0px;\n  font-family: Verdana, sans-serif;\n  font-size: 16px;\n  color: #aaaaaa;\n  padding: 8px;\n}\n\n#pageControls *, .removeButton, .channel, .messageLine * {\n  display: inline-block;\n}\n\n.addControlLabel {\n  margin-left: 20px;\n}\n\n.addButton {\n  background-color: #aaaaaa;\n  color: white;\n}\n\n#slideContainer {\n  display: -webkit-box;\n  -webkit-box-flex: 1;\n  position: relative;\n}\n\n#channelSlides {\n  position: absolute;\n  width: 100%;\n  height: 100%;\n}\n\n.channelSlide {\n  position: absolute;\n  width: 80%;\n  height: 100%;\n  background: -webkit-linear-gradient(#aaa, white);\n  transition: margin 0.25s ease-in-out;\n}\n\n.channelSlide.far-left {\n  margin-left: -160%;\n}\n\n.channelSlide.left {\n  margin-left: -75%;\n}\n\n.channelSlide.center {\n  margin-left: 10%;\n}\n\n.channelSlide.right {\n  margin-left: 95%;\n}\n\n.channelSlide.far-right {\n  margin-left: 180%;\n}\n\n.channelControls {\n  position: absolute;\n  z-index: 1;\n  right: 0px;\n  top:0px;\n  color: white;\n  text-align: right;\n  padding: 8px;\n  font-family: \"Verdana\", sans-serif;\n  font-size: 20px;\n}\n\n.channelControls .removeButton {\n  background-color: white;\n  color: #999999;\n  padding: 0px 6px 4px 6px;\n  height:\n}\n\n.channelSlideContainer {\n  position: relative;\n  display: -webkit-box;\n  -webkit-box-orient: vertical;\n  -webkit-box-align: stretch;\n  height: 100%;\n  width: 100%;\n}\n\n.messageListContainer {\n  overflow: hidden;\n  position: relative;\n  display: -webkit-box;\n  -webkit-box-flex: 1;\n}\n\n.messageListSpacer {\n  display: -webkit-box;\n  -webkit-box-flex: 0;\n  height: 40px;\n  width: 100%;\n}\n\n.messageLine {\n  margin: 6px;\n  color: #999999;\n  font-family: \"Lucida Console\", Monospace;\n  font-size: 14px;\n}\n\n.messageList {\n  position: absolute;\n  bottom: 0;\n}\n\n#typingDiv {\n  position: fixed;\n  z-index: 4;\n  width: 80%;\n  height: 30px;\n  margin: 10px;\n  margin-left: 10%;\n  bottom: 0px;\n  -webkit-box-shadow: 3px 3px 5px #888;\n}\n\n#entryText {\n  width: 100%;\n  border: 0px;\n  height: 100%;\n  padding-left: 8px;\n  padding-right: 8px;\n  font-family: \"Lucida Console\", Monospace;\n  color: white;\n  border: 0px;\n  background: #777777;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/irc/servlet/util.js",
    "content": "function $(el) {\n  return document.getElementById(el);\n}\n\nfunction $F(el) {\n  return $(el).value;\n}\n\nfunction bind(obj, func) {\n  return function() {\n    return func.apply(obj, arguments);\n  };\n}\n\nfunction childNodeWithClass(node, className) {\n  var expression = \".//*[@class='\" + className + \"']\";\n  return document.evaluate(expression, node,\n      null, XPathResult.ANY_TYPE, null).iterateNext();  \n}"
  },
  {
    "path": "_archive/mv2/extensions/managed_bookmarks/_locales/en/messages.json",
    "content": "{\n  \"extName\":  {\n    \"message\": \"Managed Bookmarks\",\n    \"description\": \"The extension name.\"\n  },\n  \"extDescription\": {\n    \"message\": \"Adds bookmarks configured by your system administrator to Chrome.\",\n    \"description\": \"The extension description.\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/managed_bookmarks/background.js",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * Maps policy names to the root node that they affect.\n */\nvar policyToNodeId = {\n  'Bookmarks Bar': '1',\n  'Other Bookmarks': '2'\n};\n\n/**\n * A function that fixes a URL. Turns e.g. \"google.com\" into\n * \"http://google.com/\". This is used to correctly match against the\n * canonicalized URLs stored in bookmarks created with the bookmarks API.\n */\nvar fixURL = (function() {\n  // An \"a\" element is used to parse the given URL and build the fixed version.\n  var a = document.createElement('a');\n  return function(url) {\n    // Preserve null, undefined, etc.\n    if (!url)\n      return url;\n    a.href = url;\n    // Handle cases like \"google.com\", which will be relative to the extension.\n    if (a.protocol === 'chrome-extension:' &&\n        url.substr(0, 17) !== 'chrome-extension:') {\n      a.href = 'http://' + url;\n    }\n    return a.href;\n  }\n})();\n\n/**\n * A CallbackChain can be used to wrap other callbacks and perform a list of\n * actions at the end, once all the wrapped callbacks have been invoked.\n */\nvar CallbackChain = function() {\n  this._count = 0;\n  this._callbacks = [];\n}\n\nCallbackChain.prototype.push = function(callback) {\n  this._callbacks.push(callback);\n}\n\nCallbackChain.prototype.wrap = function(callback) {\n  var self = this;\n  self._count++;\n  return function() {\n    if (callback)\n      callback.apply(null, arguments);\n    self._count--;\n    if (self._count == 0) {\n      for (var i = 0; i < self._callbacks.length; ++i)\n        self._callbacks[i]();\n    }\n  }\n}\n\n/**\n * Represents a managed bookmark.\n */\nvar Node = function(nodesMap, id, title, url) {\n  this._nodesMap = nodesMap;\n  this._id = id;\n  this._title = title;\n  if (url !== undefined)\n    this._url = url;\n  else\n    this._children = [];\n  if (id)\n    this._nodesMap[id] = this;\n}\n\nNode.prototype.isRoot = function() {\n  return this._id in [ '0', '1', '2' ];\n}\n\nNode.prototype.getIndex = function() {\n  return this._nodesMap[this._parentId]._children.indexOf(this);\n}\n\nNode.prototype.appendChild = function(node) {\n  node._parentId = this._id;\n  this._children.push(node);\n}\n\nNode.prototype.droppedFromParent = function() {\n  // Remove |this| and its children from the |nodesMap|.\n  var nodesMap = this._nodesMap;\n  var removeFromNodesMap = function(node) {\n    delete nodesMap[node._id];\n    (node._children || []).forEach(removeFromNodesMap);\n  }\n  removeFromNodesMap(this);\n\n  if (this._children)\n    chrome.bookmarks.removeTree(this._id);\n  else\n    chrome.bookmarks.remove(this._id);\n}\n\nNode.prototype.matches = function(bookmark) {\n  return this._title === bookmark.title &&\n         this._url === bookmark.url &&\n         typeof this._children === typeof bookmark.children;\n}\n\n/**\n * Makes this node's children match |wantedChildren|.\n */\nNode.prototype.updateChildren = function(wantedChildren, callbackChain) {\n  // Rebuild the list of children to match |wantedChildren|.\n  var currentChildren = this._children;\n  this._children = [];\n  for (var i = 0; i < wantedChildren.length; ++i) {\n    var currentChild = currentChildren[i];\n    var wantedChild = wantedChildren[i];\n    wantedChild.url = fixURL(wantedChild.url);\n\n    if (currentChild && currentChild.matches(wantedChild)) {\n      this.appendChild(currentChild);\n      if (wantedChild.children)\n        currentChild.updateChildren(wantedChild.children, callbackChain);\n    } else {\n      // This child is either missing, invalid or misplaced; drop it and\n      // generate it again. Note that the actual dropping is delayed so that\n      // bookmarks.onRemoved is triggered after the changes have been persisted.\n      if (currentChild)\n        callbackChain.push(currentChild.droppedFromParent.bind(currentChild));\n      // The \"id\" comes with the callback from bookmarks.create() but the Node\n      // is created now so that the child is placed at the right position.\n      var newChild = new Node(\n          this._nodesMap, undefined, wantedChild.title, wantedChild.url);\n      this.appendChild(newChild);\n      chrome.bookmarks.create({\n        'parentId': this._id,\n        'title': newChild._title,\n        'url': newChild._url,\n        'index': i\n      }, callbackChain.wrap((function(wantedChild, newChild, createdNode) {\n        newChild._id = createdNode.id;\n        newChild._nodesMap[newChild._id] = newChild;\n        if (wantedChild.children)\n          newChild.updateChildren(wantedChild.children, callbackChain);\n      }).bind(null, wantedChild, newChild)));\n    }\n  }\n\n  // Drop all additional bookmarks past the end that are not wanted anymore.\n  if (currentChildren.length > wantedChildren.length) {\n    var chainCounter = callbackChain.wrap();\n    currentChildren.slice(wantedChildren.length).forEach(function(child) {\n      callbackChain.push(child.droppedFromParent.bind(child));\n    });\n    // This wrapped nop makes sure that the callbacks appended to the chain\n    // execute if nothing else was wrapped.\n    chainCounter();\n  }\n}\n\n/**\n * Creates new nodes in the bookmark model to represent this Node and its\n * children.\n */\nNode.prototype.regenerate = function(parentId, index, callbackChain) {\n  var self = this;\n  chrome.bookmarks.create({\n    'parentId': parentId,\n    'title': self._title,\n    'url': self._url,\n    'index': index\n  }, callbackChain.wrap(function(newNode) {\n    delete self._nodesMap[self._id];\n    self._id = newNode.id;\n    self._parentId = newNode.parentId;\n    self._nodesMap[self._id] = self;\n    (self._children || []).forEach(function(child, i) {\n      child.regenerate(self._id, i, callbackChain);\n    });\n  }));\n}\n\n/**\n * Moves this node to the correct position in the model.\n * |currentParentId| and |currentIndex| indicate the current position in\n * the model, which may not match the expected position.\n */\nNode.prototype.moveInModel = function(currentParentId, currentIndex, callback) {\n  var index = this.getIndex();\n  if (currentParentId == this._parentId) {\n    if (index == currentIndex) {\n      // Nothing to do.\n      callback();\n      return;\n    } else if (index > currentIndex) {\n      // A bookmark moved is inserted at the new position before it is removed\n      // from the previous position. So when moving forward in the same parent,\n      // the index must be adjusted by one from the desired index.\n      ++index;\n    }\n  }\n  chrome.bookmarks.move(this._id, {\n    'parentId': this._parentId,\n    'index': index\n  }, callback);\n}\n\n/**\n * Moves any misplaced child nodes into their expected positions.\n */\nNode.prototype.reorderChildren = function() {\n  var self = this;\n  chrome.bookmarks.getChildren(self._id, function(currentOrder) {\n    for (var i = 0; i < currentOrder.length; ++i) {\n      var node = currentOrder[i];\n      var child = self._nodesMap[node.id];\n      if (child && child.getIndex() != i) {\n        // Check again after moving this child.\n        child.moveInModel(\n            node.parentId, node.index, self.reorderChildren.bind(self));\n        return;\n      }\n    }\n  });\n}\n\nvar serializeNode = function(node) {\n  var result = {\n    'id': node._id,\n    'title': node._title\n  }\n  if (node._url)\n    result['url'] = node._url;\n  else\n    result['children'] = node._children.map(serializeNode);\n  return result;\n}\n\nvar unserializeNode = function(nodesMap, node) {\n  var result = new Node(nodesMap, node['id'], node['title'], node['url']);\n  if (node.children) {\n    node.children.forEach(function(child) {\n      result.appendChild(unserializeNode(nodesMap, child));\n    });\n  }\n  return result;\n}\n\n/**\n * Tracks all the managed bookmarks, and persists the known state so that\n * managed bookmarks can be updated after restarts.\n */\nvar ManagedBookmarkTree = function() {\n  // Maps a string id to its Node. Used to lookup an entry by ID.\n  this._nodesMap = {};\n  this._root = new Node(this._nodesMap, '0', '');\n  this._root.appendChild(new Node(this._nodesMap, '1', 'Bookmarks Bar'));\n  this._root.appendChild(new Node(this._nodesMap, '2', 'Other Bookmarks'));\n}\n\nManagedBookmarkTree.prototype.store = function() {\n  chrome.storage.local.set({\n    'ManagedBookmarkTree': serializeNode(this._root)\n  });\n}\n\nManagedBookmarkTree.prototype.load = function(callback) {\n  var self = this;\n  chrome.storage.local.get('ManagedBookmarkTree', function(result) {\n    if (result.hasOwnProperty('ManagedBookmarkTree')) {\n      self._nodesMap = {};\n      self._root = unserializeNode(self._nodesMap,\n                                   result['ManagedBookmarkTree']);\n    }\n    callback();\n  });\n}\n\nManagedBookmarkTree.prototype.getById = function(id) {\n  return this._nodesMap[id];\n}\n\nManagedBookmarkTree.prototype.update = function(rootNodeId, currentPolicy) {\n  // Note that the |callbackChain| is only invoked if a callback is wrapped,\n  // otherwise its callbacks are never invoked. So store() is called only if\n  // bookmarks.create() is actually used.\n  var callbackChain = new CallbackChain();\n  callbackChain.push(this.store.bind(this));\n  this._nodesMap[rootNodeId].updateChildren(currentPolicy || [], callbackChain);\n}\n\nvar tree = new ManagedBookmarkTree();\n\nchrome.runtime.onInstalled.addListener(function() {\n  // Enforce the initial policy.\n  // This load() should be empty on the first install, but is useful during\n  // development to handle reloads.\n  tree.load(function() {\n    chrome.storage.managed.get(function(policy) {\n      Object.keys(policyToNodeId).forEach(function(policyName) {\n        tree.update(policyToNodeId[policyName], policy[policyName]);\n      });\n    });\n  });\n});\n\n// Start observing policy changes. The tree is reloaded since this may be\n// called back while the page was inactive.\nchrome.storage.onChanged.addListener(function(changes, namespace) {\n  if (namespace !== 'managed')\n    return;\n  tree.load(function() {\n    Object.keys(changes).forEach(function(policyName) {\n      tree.update(policyToNodeId[policyName], changes[policyName].newValue);\n    });\n  });\n});\n\n// Observe bookmark modifications and revert any modifications made to managed\n// bookmarks. The tree is always reloaded in case the events happened while the\n// page was inactive.\n\nchrome.bookmarks.onMoved.addListener(function(id, info) {\n  tree.load(function() {\n    var managedNode = tree.getById(id);\n    if (managedNode && !managedNode.isRoot()) {\n      managedNode.moveInModel(info.parentId, info.index, function(){});\n    } else {\n      // Check if the parent node has managed children that need to move.\n      // Example: moving a non-managed bookmark in front of the managed\n      // bookmarks.\n      var parentNode = tree.getById(info.parentId);\n      if (parentNode)\n        parentNode.reorderChildren();\n    }\n  });\n});\n\nchrome.bookmarks.onChanged.addListener(function(id, info) {\n  tree.load(function() {\n    var managedNode = tree.getById(id);\n    if (!managedNode || managedNode.isRoot())\n      return;\n    chrome.bookmarks.update(id, {\n      'title': managedNode._title,\n      'url': managedNode._url\n    });\n  });\n});\n\nchrome.bookmarks.onRemoved.addListener(function(id, info) {\n  tree.load(function() {\n    var managedNode = tree.getById(id);\n    if (!managedNode || managedNode.isRoot())\n      return;\n    // A new tree.store() is needed at the end because the regenerated nodes\n    // will have new IDs.\n    var callbackChain = new CallbackChain();\n    callbackChain.push(tree.store.bind(tree));\n    managedNode.regenerate(info.parentId, info.index, callbackChain);\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/managed_bookmarks/manifest.json",
    "content": "{\n  \"name\": \"__MSG_extName__\",\n  \"description\": \"__MSG_extDescription__\",\n  \"default_locale\": \"en\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 2,\n  \"minimum_chrome_version\": \"33\",\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"permissions\": [\n    \"bookmarks\"\n  ],\n  \"storage\": {\n    \"managed_schema\": \"schema.json\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/managed_bookmarks/schema.json",
    "content": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"Bookmarks Bar\": {\n      \"title\": \"Bookmarks in the Bookmarks Bar\",\n      \"description\": \"Configures bookmarks that will appear in the Bookmarks Bar and can't be removed by the user.\",\n      \"type\": \"array\",\n      \"id\": \"ListOfBookmarks\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"title\": {\n            \"title\": \"Bookmark name\",\n            \"description\": \"The name that appears on the bookmark.\",\n            \"type\": \"string\"\n          },\n          \"url\": {\n            \"title\": \"Bookmark URL\",\n            \"description\": \"The URL for the bookmark. If a URL is not set then this bookmark will be a folder.\",\n            \"type\": \"string\"\n          },\n          \"children\": {\n            \"title\": \"Contents of this bookmark folder\",\n            \"description\": \"A list of bookmarks that will be inside this bookmark folder. If this is set then the URL for this bookmark will be ignored.\",\n            \"$ref\": \"ListOfBookmarks\"\n          }\n        }\n      }\n    },\n    \"Other Bookmarks\": {\n      \"title\": \"Bookmarks in the Other Bookmarks folder\",\n      \"description\": \"Configures bookmarks that will appear in the Other Bookmarks folder and can't be removed by the user.\",\n      \"$ref\": \"ListOfBookmarks\"\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/mappy/background.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict'\n\nchrome.runtime.onMessage.addListener(function(req, sender) {\n  chrome.storage.local.set({address: req.address})\n  chrome.pageAction.show(sender.tab.id);\n  chrome.pageAction.setTitle({tabId: sender.tab.id, title: req.address});\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/mappy/manifest.json",
    "content": "{\n  \"name\": \"Mappy\",\n  \"version\": \"1.0\",\n  \"description\": \"Finds addresses in the web page you're on and pops up a map window.\",\n  \"icons\": { \"128\": \"icon.png\" },\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"content_scripts\": [\n    {\n      \"matches\": [\"http://*/*\"],\n      \"js\": [\"mappy_content_script.js\"]\n    }\n  ],\n  \"permissions\": [\n    \"storage\",\n    \"https://maps.google.com/*\",\n    \"https://maps.googleapis.com/*\"\n  ],\n  \"page_action\": {\n      \"default_name\": \"Display Map\",\n      \"default_icon\": \"marker.png\",\n      \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 2,\n  \"content_security_policy\": \"default-src 'none'; style-src 'self'; script-src 'self'; connect-src https://maps.googleapis.com; img-src https://maps.googleapis.com\"\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/mappy/mappy_content_script.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Search the text nodes for a US-style mailing address.\n\nlet findAddress = function() {\n  let found;\n  let re = /(\\d+\\s+[':.,\\s\\w]*,\\s*[A-Za-z]+\\s*\\d{5}(-\\d{4})?)/m;\n  let node = document.body.textContent.match(re);\n  if (document.body.textContent.match(re)) {\n    found = node;\n  }\n  if (found) {\n    let text = node;\n    let match = re.exec(text);\n    if (match && match.length) {\n      console.log('found: ' + match[0]);\n      let trim = /\\s{2,}/g;\n      let address = match[0].replace(trim, ' ')\n      chrome.runtime.sendMessage({'address': address})\n    } else {\n      console.log('bad initial match: ' + found.textContent);\n      console.log('no match in: ' + text);\n    }\n  }\n}\n\nfindAddress();\n"
  },
  {
    "path": "_archive/mv2/extensions/mappy/popup.css",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nbody {\n  margin: 0px;\n  padding: 0px;\n}\n\n#map {\n  width: 512px;\n  height: 512px;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/mappy/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Popup</title>\n    <link href=\"popup.css\" rel=\"stylesheet\" type=\"text/css\">\n  </head>\n  <body>\n    <img id=\"map\">\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/mappy/popup.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict'\n\nconst kMaps_key = 'AIzaSyBa5aieunaIp3Obco-dNVYMdbnTZGAVkKQ';\n\nfunction gclient_geocode(address) {\n  let url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' +\n            encodeURIComponent(address) + '&sensor=false';\n  let request = new XMLHttpRequest();\n\n  request.open('GET', url, true);\n  console.log(url);\n  request.onreadystatechange = function (e) {\n    console.log(request, e);\n    if (request.readyState == 4) {\n      if (request.status == 200) {\n        let json = JSON.parse(request.responseText);\n        let latlng = json.results[0].geometry.location;\n        latlng = latlng.lat + ',' + latlng.lng;\n        let src = 'https://maps.googleapis.com/maps/api/staticmap?center=' +\n            latlng + '&markers=' + latlng + '&zoom=14' +\n            '&size=512x512&sensor=false&key=' + kMaps_key;\n        let map = document.getElementById('map');\n        map.src = src;\n        map.addEventListener('click', function () {\n          window.close();\n        });\n      } else {\n        console.log('Unable to resolve address into lat/lng');\n      }\n    }\n  };\n  request.send(null);\n}\n\nfunction map() {\n  chrome.storage.local.get(['address'], function(value){\n    gclient_geocode(value.address);\n  })\n}\n\nwindow.onload = map;\n"
  },
  {
    "path": "_archive/mv2/extensions/maps_app/manifest.json",
    "content": "{\n  \"name\": \"Google Maps\",\n  \"version\": \"3\",\n  \"icons\": { \"24\": \"24.png\", \"128\": \"128.png\" },\n  \"app\": {\n    \"urls\": [\n      \"http://maps.google.com/\"\n    ],\n    \"launch\": {\n      \"web_url\": \"http://maps.google.com/\"\n    }\n  },\n  \"permissions\": [\"geolocation\"],\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/news/README",
    "content": "# News\n\nThis sample demonstrates a popup panel that access a remote URL. In this case, we are the Google News RSS feed, and building a UI to display that information.\n\n## Implementation Notes\n\nNote that this is a _very_ old example, and is kept here purely for archival purposes. We do not recommend using this as a base of a new extension.\n"
  },
  {
    "path": "_archive/mv2/extensions/news/_locales/en/messages.json",
    "content": "{\n  \"extName\": {\n    \"message\": \"News Reader (by Google)\"\n  },\n  \"extDesc\": {\n    \"message\": \"Displays the latest stories from Google News in a popup.\"\n  },\n  \"ext_default_title\": {\n    \"message\": \"Google News\"\n  },\n\n  \"1\": {\n    \"message\": \"Top Stories\"\n  },\n  \"n\": {\n    \"message\": \"Nation\"\n  },\n  \"w\": {\n    \"message\": \"World\"\n  },\n  \"b\": {\n    \"message\": \"Business\"\n  },\n  \"t\": {\n    \"message\": \"Science/Technology\"\n  },\n  \"e\": {\n    \"message\": \"Entertainment\"\n  },\n  \"s\": {\n    \"message\": \"Sports\"\n  },\n  \"m\": {\n    \"message\": \"Health\"\n  },\n  \"po\": {\n    \"message\": \"Most Popular\"\n  },\n\n  \"options\": {\n    \"message\": \"Options\"\n  },\n  \"more_stories\": {\n    \"message\": \"More stories\"\n  },\n\n  \"direction\": {\n    \"message\": \"ltr\"\n  },\n\n  \"country\": {\n    \"message\": \"Country:\"\n  },\n  \"topic\": {\n    \"message\": \"Topics:\"\n  },\n  \"save\": {\n    \"message\": \"Save\"\n  },\n  \"saveStatus\": {\n    \"message\": \"Options saved\"\n  },\n  \"storyCount\": {\n    \"message\": \"Number of stories:\"\n  },\n  \"newsOption\": {\n    \"message\": \"Google News Options\"\n  },\n  \"customText\": {\n    \"message\": \"Custom Topics:\"\n  },\n  \"maximumTopics\": {\n   \"message\": \"(Maximum $count$)\",\n   \"placeholders\": {\n     \"count\": {\n       \"content\": \"$1\"\n      }\n    }\n  },\n  \"submitButton\": {\n    \"message\": \"Add\"\n  },\n  \"deleteTitle\": {\n    \"message\": \"Delete\"\n  },\n  \"invalidChars\": {\n    \"message\": \"Invalid character(s)\"\n  },\n  \"noTopic\": {\n    \"message\": \"At least one Topic must be selected\"\n  },\n\n  \"fetchError\": {\n    \"message\": \"Error: Failed to fetch news stories.\"\n  },\n  \"wrongTopic\": {\n    \"message\": \"Error: Not a valid feed.\"\n  },\n  \"noStory\": {\n    \"message\": \"No story right now\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/news/css/feed.css",
    "content": "/**\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n * \n * Sets style of different elements in pop-up page.\n * \n * Author: navneetg@google.com (Navneet Goel).\n */\n\nbody {\n  font-family: arial, sans-serif;\n  font-size: 12px;\n  min-width: 500px;\n  overflow: visible;\n}\na {\n  color: #0000CC;\n  cursor: pointer;\n  text-decoration: underline;\n}\n#noStories {\n  background-color: rgb(255, 238, 136);\n  font-size: 13px;\n  font-weight: bold;\n  margin-left: 140px;\n  margin-right: 140px;\n  text-align: center;\n}\n.open_box {\n  background-image: url(/images/sprite_arrows.gif);\n  background-position: 0px -24px;\n  clear: left;\n  cursor: pointer;\n  display: block;\n  height: 12px;\n  margin-top: 2px;\n  overflow: hidden;\n  width: 12px;\n  float: left;\n}\n.opened .open_box {\n  background-position: -12px -24px;\n}\n.item {\n  padding: 2px 0;\n}\n.item_title {\n  cursor: pointer;\n  display: block;\n  min-width: 300px;\n  padding: 0 0 0 17px;\n}\n.item_desc {\n  border: none;\n  display: block;\n  height: 0;\n  margin: 0;\n  min-width: 500px;\n  padding: 0;\n  transition: height 0.2s ease-out;\n}\n#title {\n  display: block;\n}\n.error {\n  background-color: rgb(255, 238, 136);\n  font-size: 13px;\n  font-weight: bold;\n  margin-left: 125px;\n  margin-right: 125px;\n  text-align: center;\n  white-space: nowrap;\n}\n.more {\n  color: #88C;\n  display: block;\n  margin-left: 385px;\n  padding-right: 10px;\n  padding-top: 5px;\n  text-align: right;\n}\n.topicsLTR {\n  direction: ltr;\n  font-size: 13px;\n  padding-left: 5px;\n}\n.topicsRTL {\n  direction: rtl;\n  font-size: 13px;\n  padding-right: 5px;\n}\nbody.rtl #feed {\n  direction: rtl;\n}\nbody.rtl .open_box {\n  float: right;\n}\nbody.rtl .item_title {\n  padding: 0 17px 0 0;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/news/css/options.css",
    "content": "/**\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n * \n * Sets style of different elements in options page.\n * \n * Author: navneetg@google.com (Navneet Goel).\n */\n\n@CHARSET \"UTF-8\";\nbody {\n  background-color: rgb(235, 239, 249);\n  font-family: arial , sans-serif;\n  font-size: 13px;\n}\n.suppr {\n  background-image: url(/images/delete-icon.png);\n  background-repeat: no-repeat;\n  cursor: pointer;\n  display: inline;\n  float: left;\n  height: 17px;\n  margin-top: 3px;\n  overflow: hidden;\n  width: 14px;\n}\n.checkBoxTopic {\n  float: left;\n  padding-left: 2px;\n  padding-top: 1px;\n}\n.checkBox {\n  float: left;\n}\n.boxAndTopic {\n  overflow: auto;\n  padding-bottom: 5px;\n}\n#invalid_status, #save_status {\n  background-color: rgb(255, 241, 168);\n  font-weight: bold;\n  margin-left: 10px;\n  opacity: 0;\n  padding-bottom: 3px;\n  padding-left: 7px;\n  padding-right: 7px;\n  padding-top: 3px;\n}\n#all_content {\n  background-color: white;\n  border-bottom-left-radius: 12px 12px;\n  border-bottom-right-radius: 12px 12px;\n  border-color: #B5C7DE;\n  border-style: solid;\n  border-top-left-radius: 12px 12px;\n  border-top-right-radius: 12px 12px;\n  border-width: 4px;\n  margin: 40px auto 20px;\n  padding: 12px;\n  width: 600px;\n}\n.col2 {\n  padding-left: 20px;\n}\nbody.rtl .col1, body.rtl .col2 {\n  text-align: right;\n}\nbody.rtl {\n  direction: rtl;\n}\nbody.rtl .col2 {\n  padding-right: 20px;\n}\nbody.rtl .checkBox, body.rtl .checkBoxTopic {\n  float: right;\n}\nbody.rtl table.contentTable {\n  margin:0 55px 0 0;\n}\nbody.rtl #save_div{\n  margin: 0 220px 0 0;\n}\nbody.rtl #countryList{\n  margin:0 5px 0 0;\n}\n.col1 {\n  padding-top: 3px;\n  width: 115px;\n}\n.all_rows {\n  height: 35px;\n  vertical-align: top;\n}\nbody.rtl .cusTopicsClass {\n  float: right;\n}\n.cusTopicsClass {\n  float: left;\n  width: 225px;\n}\n#save_div {\n  margin-left: 220px;\n}\n#countryList {\n  padding-left: 5px;\n}\n#logo {\n  font-size: 15px;\n  font-weight: bold;\n  text-align: center;\n}\n.noborder {\n  border: 0;\n  font-family: arial, sans-serif;\n  height: 15px;\n  outline: none;\n  overflow: hidden;\n  resize: none;\n  width:205px;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/news/javascript/feed.js",
    "content": "/**\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n */\n\n/**\n * @fileoverview This file retrieves news feed and shows news in pop-up\n * page according to country, topics and no. of stories selected in the\n * option page.\n */\n\n// Store value retrieved from locale.\nvar moreStoriesLocale = chrome.i18n.getMessage('more_stories') + ' \\u00BB ';\nvar directionLocale = chrome.i18n.getMessage('direction');\n\n// Feed URL.\nvar feedUrl = DEFAULT_NEWS_URL;\n\n//The XMLHttpRequest object that tries to load and parse the feed.\nvar req;\n\n/**\n * Sends request to Google News server\n */\nfunction main() {\n  req = new XMLHttpRequest();\n  req.onload = handleResponse;\n  req.onerror = handleError;\n  req.open('GET', feedUrl, true);\n  req.send(null);\n}\n\n/**\n * Handles feed parsing errors.\n * @param {String} error The localized error message.\n */\nfunction handleFeedParsingFailed(error) {\n  var feed = $('feed');\n  $('noStories').style.display = 'none';\n  feed.className = 'error';\n  feed.innerText = error;\n}\n\n/**\n * Handles errors during the XMLHttpRequest.\n */\nfunction handleError() {\n  handleFeedParsingFailed(chrome.i18n.getMessage('fetchError'));\n  $('topics').style.display = 'none';\n}\n\n/**\n * Parses the feed response.\n */\nfunction handleResponse() {\n  var doc = req.responseXML;\n  if (!doc) {\n    handleFeedParsingFailed(chrome.i18n.getMessage('wrongTopic'));\n    var img = $('title');\n    if(!img.src) {\n      img.src = \"/images/news.gif\";\n    }\n\n    document.querySelector('body').style.minHeight = 0;\n    return;\n  }\n  buildPreview(doc);\n}\n\n// Stores no. of stories selected in options page.\nvar maxFeedItems = (window.localStorage.getItem('count')) ?\n    window.localStorage.getItem('count') : 5;\n\n// Where the more stories link should navigate to.\nvar moreStoriesUrl;\n\n/**\n * Generates news iframe in pop-up page by parsing retrieved feed.\n * @param {HTMLDocument} doc HTML Document received in feed.\n */\nfunction buildPreview(doc) {\n  // Get the link to the feed source.\n  var link = doc.querySelector('link');\n  var parentTag = link.parentNode.tagName;\n  if (parentTag != 'item' && parentTag != 'entry') {\n    moreStoriesUrl = link.textContent;\n  }\n\n  // Setup the title image.\n  var image = doc.querySelector('image');\n  var titleImg;\n\n  // Stores whether language script is Right to Left or not for setting style\n  // of share buttons(Facebook, Twitter and Google Buzz) in iframe.\n  var isRtl = 'lTR';\n\n  if (image) {\n    var url = image.querySelector('url');\n    if (url) {\n      titleImg = url.textContent;\n\n      // Stores URL of title image to be shown on pop-up page.\n      var titleImgUrl = titleImg;\n      var pattern = /ar_/gi;\n      var result = titleImgUrl.match(pattern);\n      if (result != null || titleImgUrl == ISRAEL_IMAGE_URL) {\n        isRtl = 'rTL';\n      }\n    }\n  }\n\n  var img = $('title');\n  if (titleImg) {\n    img.src = titleImg;\n    if (moreStoriesUrl) {\n      $('title_a').addEventListener('click', moreStories);\n    }\n  } else {\n    img.style.display = 'none';\n  }\n\n  // Construct the iframe's HTML.\n  var iframe_src = '<!doctype html><html><head><script>' +\n                   $('iframe_script').textContent + '<' +\n                   '/script><style> ' +\n                   '.rTL {margin-right: 102px; text-align: right;} ' +\n                   '.lTR {margin-left: 102px; text-align: left;} ' +\n                   '</style></head><body onload=\"frameLoaded();\" ' +\n                   'style=\"padding:0px;margin:0px;\">';\n\n  var feed = $('feed');\n  feed.className = '';\n  var entries = doc.getElementsByTagName('entry');\n  if (entries.length == 0) {\n    entries = doc.getElementsByTagName('item');\n  }\n  var count = Math.min(entries.length, maxFeedItems);\n\n  // Stores required height by pop-up page.\n  var minHeight = 19;\n  minHeight = (minHeight * (count - 1)) + 100;\n  document.querySelector('body').style.minHeight = minHeight + 'px';\n  $('feed').innerHTML = '';\n\n  for (var i = 0; i < count; i++) {\n    item = entries.item(i);\n\n    // Grab the title for the feed item.\n    var itemTitle = item.querySelector('title');\n    if (itemTitle) {\n      itemTitle = itemTitle.textContent;\n    } else {\n      itemTitle = 'Unknown title';\n    }\n\n    // Grab the description.\n    var itemDesc = item.querySelector('description');\n    if (!itemDesc) {\n      itemDesc = item.querySelector('summary');\n      if (!itemDesc) {\n        itemDesc = item.querySelector('content');\n      }\n    }\n    if (itemDesc) {\n      itemDesc = itemDesc.childNodes[0].nodeValue;\n\n    } else {\n      itemDesc = '';\n    }\n    var itemLink = item.querySelector('link');\n    if (itemLink) {\n      itemLink = itemLink.textContent;\n    } else {\n      itemLink = 'Unknown itemLink';\n    }\n    var item = document.createElement('div');\n    item.className = 'item';\n    var box = document.createElement('div');\n    box.className = 'open_box';\n    box.addEventListener('click', showDesc);\n    item.appendChild(box);\n\n    var title = document.createElement('a');\n    title.className = 'item_title';\n    title.innerText = itemTitle;\n    title.addEventListener('click', showDesc);\n    item.appendChild(title);\n\n    var desc = document.createElement('iframe');\n    desc.scrolling = 'no';\n    desc.className = 'item_desc';\n    item.appendChild(desc);\n    feed.appendChild(item);\n\n    // Adds share buttons images(Facebook, Twitter and Google Buzz).\n    itemDesc += \"<div class = '\" + isRtl + \"'>\";\n    itemDesc += \"<a style='cursor: pointer' id='fb' \" +\n      \"onclick='openNewsShareWindow(this.id,\\\"\" + itemLink + \"\\\")'>\" +\n      \"<img src='\" + chrome.extension.getURL('/images/fb.png') + \"'/></a>\";\n    itemDesc += \" <a style='cursor: pointer' id='twitter' \" +\n      \"onclick='openNewsShareWindow(this.id,\\\"\" + itemLink + \"\\\")'>\" +\n      \"<img src='\" + chrome.extension.getURL('/images/twitter.png') + \"'/></a>\";\n    itemDesc += \" <a style='cursor: pointer' id='buzz' \" +\n      \"onclick='openNewsShareWindow(this.id,\\\"\" + itemLink + \"\\\")'>\" +\n      \"<img src='\" + chrome.extension.getURL('/images/buzz.png') + \"'/></a>\";\n    itemDesc += '</div>';\n\n    // The story body is created as an iframe with a data: URL in order to\n    // isolate it from this page and protect against XSS.  As a data URL, it\n    // has limited privileges and must communicate back using postMessage().\n    desc.src = 'data:text/html;charset=utf-8,' + btoa(unescape(encodeURIComponent(iframe_src + itemDesc + '</body></html>')));\n  }\n  if (moreStoriesUrl && entries.length != 0) {\n    var more = document.createElement('a');\n    more.className = 'more';\n    more.innerText = moreStoriesLocale;\n    more.addEventListener('click', moreStories);\n    feed.appendChild(more);\n  }\n  setStyleByLang(titleImgUrl);\n\n  // Checks whether feed retrieved has news story or not. If not, then shows\n  // error message accordingly.\n  if (entries.length == 0) {\n    $('noStories').innerText = chrome.i18n.getMessage('noStory');\n    $('noStories').style.display = 'block';\n  } else {\n    $('noStories').style.display = 'none';\n  }\n}\n\n/**\n * Show |url| in a new tab.\n * @param {String} url The news URL.\n */\nfunction showUrl(url) {\n  // Only allow http and https URLs.\n  if (url.indexOf('http:') != 0 && url.indexOf('https:') != 0) {\n    return;\n  }\n  chrome.tabs.create({url: url});\n}\n\n/**\n * Redirects to Google news site for more stories.\n * @param {Object} event Onclick event.\n */\nfunction moreStories(event) {\n  showUrl(moreStoriesUrl);\n}\n\n/**\n * Shows description of the news when users clicks on news title.\n * @param {Object} event Onclick event.\n */\nfunction showDesc(event) {\n  var item_ = event.currentTarget.parentNode;\n  var items = document.getElementsByClassName('item');\n  for (var i = 0, item; item = items[i]; i++) {\n    var iframe = item.querySelector('.item_desc');\n    if (item == item_ && item.className == 'item') {\n      item.className = 'item opened';\n      iframe.contentWindow.postMessage('reportHeight', '*');\n    } else {\n      item.className = 'item';\n      iframe.style.height = '0px';\n    }\n  }\n}\n\n/**\n * Handles messages between different iframes and sets the display of iframe.\n * @param {Object} e Onmessage event.\n */\nfunction iframeMessageHandler(e) {\n  var iframes = document.getElementsByTagName('IFRAME');\n  for (var i = 0, iframe; iframe = iframes[i]; i++) {\n    if (iframe.contentWindow == e.source) {\n      var msg = JSON.parse(e.data);\n      if (msg) {\n        if (msg.type == 'size') {\n          iframe.style.height = msg.size + 'px';\n        } else if (msg.type == 'show') {\n          var url = msg.url;\n          if (url.indexOf('http://news.google.com') == 0) {\n            // If the URL is a redirect URL, strip of the destination and go to\n            // that directly.  This is necessary because the Google news\n            // redirector blocks use of the redirects in this case.\n            var index = url.indexOf('&url=');\n            if (index >= 0) {\n              url = url.substring(index + 5);\n              index = url.indexOf('&');\n              if (index >= 0)\n                url = url.substring(0, index);\n            }\n          }\n          showUrl(url);\n        }\n      }\n      return;\n    }\n  }\n}\n\n/**\n * Saves last viewed topic by user in local storage on unload of pop-up page.\n */\nfunction saveLastTopic() {\n  var topicVal = $('topics').value;\n  window.localStorage.setItem('lastTopic', topicVal);\n}\n\n/**\n * Sets the URL according to selected topic(or default topic), then retrieves\n * feed and sets pop-up page.\n */\nfunction getNewsByTitle() {\n  var country = window.localStorage.getItem('country');\n  country = (country == 'noCountry' || !country) ? '' : country;\n\n  // Sets direction of topics showed under dropdown in pop-up page according\n  // to set language in browser.\n  $('topics').className = (directionLocale == 'rtl') ? 'topicsRTL' :\n      'topicsLTR';\n\n  var topicVal = $('topics').value;\n\n  // Sets Feed URL in case of custom topic selected.\n  var keywords = JSON.parse(window.localStorage.getItem('keywords'));\n  var isFound = false;\n  if (keywords) {\n    for (i = 0; i < keywords.length; i++) {\n      if (topicVal == keywords[i]) {\n      isFound = true;\n      feedUrl = DEFAULT_NEWS_URL + '&cf=all&ned=' + country + '&q=' + topicVal +\n          '&hl=' + country;\n      break;\n      }\n    }\n  }\n  if (!isFound) {\n    feedUrl = DEFAULT_NEWS_URL + '&cf=all&ned=' + country +\n        '&topic=' + topicVal;\n  }\n  main();\n}\n\n/**\n * Shows topic list retrieved from local storage(if any),else shows\n * default topics list.\n */\nfunction getTopics() {\n  var topics = JSON.parse(window.localStorage.getItem('topics'));\n  var keywords = JSON.parse(window.localStorage.getItem('keywords'));\n  var element = $('topics');\n\n  // Sets all topics as default list if no list is found from local storage.\n  if (!topics && !keywords) {\n    topics = [' ','n','w','b','t','e','s','m','po'];\n  }\n\n  if (topics) {\n    for (var i = 0; i < (topics.length); i++) {\n      var val = (topics[i] == ' ') ? '1' : topics[i];\n      element.options[element.options.length] = new Option(\n          chrome.i18n.getMessage(val), topics[i]);\n    }\n  }\n\n  // Shows custom topics in list(if any).\n  if (keywords) {\n    for (i = 0; i < (keywords.length); i++) {\n      element.options[element.options.length] = new Option(keywords[i],\n          keywords[i]);\n    }\n  }\n\n  $('option_link').innerText = chrome.i18n.getMessage('options');\n\n  var topicVal = window.localStorage.getItem('lastTopic');\n  if (topicVal) {\n    $('topics').value = topicVal;\n  }\n}\n\nwindow.addEventListener('message', iframeMessageHandler);\n"
  },
  {
    "path": "_archive/mv2/extensions/news/javascript/options.js",
    "content": "/**\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n */\n\n/**\n * @fileoverview Includes the country selection, topics selection and\n * selection of no. of news stories to be shown. Include default settings also.\n * @author navneetg@google.com (Navneet Goel).\n */\n\n/**\n * Stores number of selected topics on the options page.\n */\nvar checkCount = 0;\n\n/**\n * Stores maximum count of custom topics.\n */\nvar MAX_CUS_TOPICS = 10;\n\n/**\n * Stores temporary added custom topics which are not yet saved.\n */\nvar tempCusTopics = [];\n\n/**\n * Checks whether ENTER key is pressed or not.\n */\nfunction addCustomTopic() {\n  if (window.event.keyCode == 13) {\n    addCusTopic();\n  }\n}\n\n/**\n * Retrieves and sets last saved country from local storage(if found),\n * else sets country retrieved from feed.\n */\nfunction setCountry() {\n  var country = window.localStorage.getItem('country');\n\n  // If country is not found in localstorage or default value is selected in\n  // drop down menu.\n  if ((!country) || country == 'noCountry') {\n    // XMLHttpRequest object that tries to load the feed for the purpose of\n    // retrieving the country value out of feed.\n    var req = new XMLHttpRequest();\n    req.onload = handleResponse;\n    req.onerror = handleError;\n    req.open('GET', DEFAULT_NEWS_URL, true);\n    req.send(null);\n\n    // Sets country to default Country in dropdown menu.\n    function handleError() {\n      $('countryList').value = 'noCountry';\n    };\n\n    // Handles parsing the feed data got back from XMLHttpRequest.\n    function handleResponse() {\n      // Feed document retrieved from URL.\n      var doc = req.responseXML;\n      if (!doc) {\n        handleError();\n        return;\n      }\n      var imageLink = doc.querySelector('image link');\n      if (imageLink) {\n          // Stores link to set value of country.\n          var newsUrl = imageLink.textContent;\n      }\n\n      // Stores country value\n      $('countryList').value = newsUrl.substring(newsUrl.indexOf('&ned=') + 5,\n          newsUrl.indexOf('&hl='));\n    };\n  } else {\n    $('countryList').value = country;\n  }\n}\n\n/**\n * Displays various messages to user based on user input.\n * @param {String} id Id of status element.\n * @param {Number} timeOut Timeout value of message shown.\n * @param {String} message Message to be shown.\n */\nfunction showUserMessages(id, timeOut, message) {\n  $(id).style.setProperty('transition',\n      'opacity 0s ease-in');\n  $(id).style.opacity = 1;\n  $(id).innerText = chrome.i18n.getMessage(message);\n  window.setTimeout(function() {\n    $(id).style.setProperty(\n        'transition', 'opacity' + timeOut + 's ease-in');\n    $(id).style.opacity = 0;\n    }, 1E3\n  );\n}\n\n/**\n * Sets options page CSS according to the browser language(if found), else sets\n * to default locale.\n */\nfunction setOptionPageCSS() {\n  if (chrome.i18n.getMessage('direction') == 'rtl') {\n    document.querySelector('body').className = 'rtl';\n  }\n}\n\n/**\n * Initializes the options page by retrieving country, topics and count of\n * stories from local storage if present, else sets to default settings.\n */\nfunction initialize() {\n  setOptionPageCSS();\n  setCountry();\n  setCountAndTopicList();\n  setLocalizedTopicList();\n\n  // Adds a custom topic on press of Enter key.\n  $('newKeyword').onkeypress = addCustomTopic;\n}\n\n/**\n * Retrieves locale values from locale file.\n */\nfunction setLocalizedTopicList() {\n  var getI18nMsg = chrome.i18n.getMessage;\n\n  $('top').innerText = getI18nMsg('1');\n  $('nation').innerText = getI18nMsg('n');\n  $('world').innerText = getI18nMsg('w');\n  $('business').innerText = getI18nMsg('b');\n  $('science').innerText = getI18nMsg('t');\n  $('entertainment').innerText = getI18nMsg('e');\n  $('sports').innerText = getI18nMsg('s');\n  $('health').innerText = getI18nMsg('m');\n  $('most').innerText = getI18nMsg('po');\n  $('select_country').innerText = getI18nMsg('country');\n  $('topic').innerText = getI18nMsg('topic');\n  $('save_button').innerText = getI18nMsg('save');\n  $('story_count').innerText = getI18nMsg('storyCount');\n  $('logo').innerHTML = $('logo').innerHTML + getI18nMsg('newsOption');\n  $('custom_text').innerHTML = getI18nMsg('customText') + '<br/>' +\n    getI18nMsg('maximumTopics',[MAX_CUS_TOPICS]);\n  $('submit_button').value = getI18nMsg('submitButton');\n}\n\n/**\n * Sets topic list and number of stories retrieved from localstorage(if any)\n * otherwise sets to default.\n */\nfunction setCountAndTopicList() {\n  var topicLists = document.getElementsByClassName('checkBox');\n\n  // Retrieves topics list from localStorage.\n  var topics = JSON.parse(window.localStorage.getItem('topics'));\n\n  // Runs if retrieved topic list from local storage contains topics.\n  if (topics) {\n    for (var x = 0, topicList; topicList = topicLists[x]; x++) {\n\n      // Saves whether checkbox is checked or not.\n      var isPresent = false;\n      for (var y = 0; y < topics.length; y++) {\n        if (topics[y] == topicList.value) {\n          topicList.checked = true;\n          isPresent = true;\n          checkCount++;\n          break;\n        }\n      }\n      if (!isPresent) {\n        topicList.checked = false;\n      }\n    }\n  }\n\n  // Retrieves list of custom topics from localstorage(if any) and shows it\n  // in option page.\n  var keywords = JSON.parse(window.localStorage.getItem('keywords'));\n  if (keywords) {\n\n    // Template to store custom topics in a table.\n    var template = [];\n    var title = chrome.i18n.getMessage('deleteTitle');\n    for (var i = 0; i < keywords.length; i++) {\n      checkCount++;\n\n      template.push('<tr style = \"height: 22px;\">');\n      template.push('<td id = \"keyword_value\" class = \"cusTopicsClass\">');\n      template.push('<textarea class=\"noborder\" readonly>');\n      template.push(keywords[i]);\n      template.push('</textarea>');\n      template.push('<td class = \"suppr\" onclick = \"delCusTopic(this)\" ');\n        template.push('title=\"');\n        template.push(title);\n        template.push('\">');\n      template.push('</td>');\n      template.push('</tr>');\n    }\n    $('custom_topics').innerHTML = template.join('');\n    if (keywords.length == MAX_CUS_TOPICS) {\n      $('submit_button').disabled = true;\n      $('newKeyword').readOnly = 'readonly';\n    }\n  }\n  // Check all checkboxes(default settings) if no custom topic list and\n  // checkbox topic list from local storage is found.\n  if (!keywords && !topics) {\n    for (var x = 0, topicList; topicList = topicLists[x]; x++) {\n      topicList.checked = true;\n      checkCount++;\n    }\n  }\n\n  // Retrieves saved value of number of stories.\n  var count = window.localStorage.getItem('count');\n\n  // Sets number of stories in dropdown.\n  if (count) {\n    $('storyCount').value = count;\n  }\n}\n\n/**\n * Saves checked topic list(if any), Custom topics(if any), number of\n * stories and country value in local storage.\n */\nfunction saveTopicsCountry() {\n  var country = $('countryList').value;\n  var topicLists = document.getElementsByClassName('checkBox');\n\n  // Contains selected number of stories.\n  var count = $('storyCount').value;\n\n  // Stores checked topics list.\n  var topicArr = [];\n  for (var i = 0, topicList; topicList = topicLists[i]; i++) {\n    if (topicList.checked) {\n      topicArr.push(topicList.value);\n    }\n  }\n  var keywords = JSON.parse(window.localStorage.getItem('keywords'));\n\n  // Saves custom topics to local storage(if any).\n  if (tempCusTopics.length > 0) {\n    if (keywords) {\n      keywords = keywords.concat(tempCusTopics);\n      window.localStorage.setItem('keywords', JSON.stringify(keywords));\n    } else {\n      window.localStorage.setItem('keywords', JSON.stringify(tempCusTopics));\n    }\n    tempCusTopics.splice(0, tempCusTopics.length);\n  }\n\n  // Saves checkbox topics(if any).\n  if (topicArr.length > 0) {\n    window.localStorage.setItem('topics', JSON.stringify(topicArr));\n  } else {\n    window.localStorage.removeItem('topics');\n  }\n\n  window.localStorage.setItem('count', count);\n  window.localStorage.setItem('country', country);\n\n  showUserMessages('save_status', 0.5, 'saveStatus');\n  $('save_button').disabled = true;\n}\n\n/**\n * Disables the save button on options page if no topic is selected by the user.\n * @param {String} id Id of checkbox checked or unchecked.\n */\nfunction manageCheckCount(id) {\n  checkCount = ($(id).checked) ? (checkCount + 1) : (checkCount - 1);\n  $('save_button').disabled = (checkCount == 0) ? true : false;\n}\n\n/**\n * Enables save button if at least one topic is selected.\n */\nfunction enableSaveButton() {\n  if (checkCount != 0) {\n    $('save_button').disabled = false;\n  }\n}\n\n/**\n * Adds new entered custom topic.\n */\nfunction addCusTopic() {\n  // Retrieves custom topic list from local storage(if any), else create new\n  // array list.\n  var keywords = JSON.parse(window.localStorage.getItem('keywords') || \"[]\");\n\n  // Adds topic only if total number of added custom topics are less than 10.\n  if (keywords.length + tempCusTopics.length <= (MAX_CUS_TOPICS - 1)) {\n\n    // Stores new entered value in input textbox.\n    var val = $('newKeyword').value;\n    if (val) {\n      val = val.trim();\n      if (val.length > 0) {\n        var pattern = /,/g;\n\n        // Runs if comma(,) is not present in topic entered.\n        if (val.match(pattern) == null) {\n          checkCount++;\n          tempCusTopics.push(val);\n\n          // Template to store custom topics in a table.\n          var template = [];\n          var title = chrome.i18n.getMessage('deleteTitle');\n\n          template.push('<tr style = \"height: 22px;\">');\n          template.push('<td id = \"keyword_value\" class = \"cusTopicsClass\">');\n          template.push('<textarea class=\"noborder\" readonly>');\n          template.push(val);\n          template.push('</textarea>');\n          template.push('<td class = \"suppr\" onclick = \"delCusTopic(this)\" ');\n            template.push('title=\"');\n            template.push(title);\n            template.push('\">');\n          template.push('</td>');\n          template.push('</tr>');\n\n          $('custom_topics').innerHTML += template.join('');\n          enableSaveButton();\n        } else {\n          showUserMessages('invalid_status', 2.5, 'invalidChars');\n        }\n      }\n      $('newKeyword').value = '';\n    }\n  }\n\n  if ((keywords.length + tempCusTopics.length) == (MAX_CUS_TOPICS)) {\n    $('submit_button').disabled = true;\n    $('newKeyword').readOnly = 'readonly';\n  }\n}\n\n/**\n * Delete custom topic whenever users click on delete icon.\n * @param {HTMLTableColElement} obj HTML table column element to be deleted.\n */\nfunction delCusTopic(obj) {\n  // Deletes only if total number of topics are greater than 1, else shows\n  // error message.\n  if (checkCount > 1) {\n    var value;\n\n    // Extract custom topic value.\n    value = obj.parentNode.querySelector('.cusTopicsClass textarea').value;\n\n    // Removes custom topic element from UI.\n    $('custom_topics').removeChild(obj.parentNode);\n\n    // Removes custom topic element either from temporary array(if topic is\n    // not yet saved) or from saved topic list and saves new list to\n    // local storage.\n    var flag = 0;\n    for (var i = 0; i < tempCusTopics.length; i++) {\n      if (tempCusTopics[i] == value) {\n        tempCusTopics.splice(i, 1);\n        flag = 1;\n        break;\n      }\n    }\n\n    if (flag == 0) {\n      var keywords = JSON.parse(window.localStorage.getItem('keywords'));\n      for (i = 0; i < keywords.length; i++) {\n        if (keywords[i] == value) {\n          keywords.splice(i, 1);\n          break;\n        }\n      }\n      if (keywords.length > 0) {\n        window.localStorage.setItem('keywords', JSON.stringify(keywords));\n      } else {\n        window.localStorage.removeItem('keywords');\n      }\n    }\n\n    checkCount--;\n    $('submit_button').disabled = false;\n  } else {\n    showUserMessages('save_status', 2.5, 'noTopic');\n  }\n  $('newKeyword').readOnly = false;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/news/javascript/util.js",
    "content": "/**\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n */\n\n/**\n * @fileoverview Defines the constants and most commonly used functions.\n * @author navneetg@google.com (Navneet Goel).\n */\n\n/**\n * Default feed news URL.\n */\nvar DEFAULT_NEWS_URL = 'http://news.google.com/news?output=rss';\n\n/**\n * Image URL of Israel country.\n */\nvar ISRAEL_IMAGE_URL = 'http://www.gstatic.com/news/img/logo/iw_il/news.gif';\n\n/**\n * Alias for getElementById.\n * @param {String} elementId Element id of the HTML element to be fetched.\n * @return {Element} Element corresponding to the element id.\n */\nfunction $(elementId) {\n  return document.getElementById(elementId);\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/news/manifest.json",
    "content": "{\n  \"name\": \"__MSG_extName__\",\n  \"version\": \"2.0\",\n  \"description\": \"__MSG_extDesc__\",\n  \"icons\": { \"128\": \"images/news_icon.png\" },\n  \"default_locale\":\"en\",\n  \"browser_action\": {\n    \"default_title\": \"__MSG_ext_default_title__\",\n    \"default_icon\": \"images/news_action.png\",\n    \"default_popup\": \"views/feed.html\"\n  },\n  \"permissions\": [\n    \"tabs\",\n    \"http://news.google.com/*\"\n  ],\n  \"options_page\": \"views/options.html\",\n  \"background\": {\n    \"page\": \"views/background.html\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/news/views/background.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n\n<!--\n@fileoverview Contains script for running at the background to open up the\noptions page when the extension is reloaded.\n-->\n\n<html>\n  <body>\n    <script>\n      //Retrieves value from local storage(if found).\n      var newsFlag = window.localStorage.getItem('newsFlag');\n\n      //Runs if extension installation is done.\n      if(!newsFlag) {\n        var optionsPageURL = chrome.extension.getURL('/views/options.html');\n        chrome.tabs.create({url: optionsPageURL});\n        window.localStorage.setItem('newsFlag','1');\n      }\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/news/views/feed.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n\n<!--\n@fileoverview This file serves as the pop-up page for showing news \naccording to the settings saved in options page otherwise shows default\nsettings.\n@author navneetg@google.com (Navneet Goel).\n-->\n\n<html>\n<head>\n<script src = \"/javascript/util.js\"></script>\n<link rel = \"stylesheet\" href = \"/css/feed.css\"/>\n\n<script id = \"iframe_script\">\n\n/**\n * Facebook share URL.\n */\nvar FB_SHARE_URL = \"http://www.facebook.com/sharer.php?u=\";\n\n/**\n * Twitter share URL.\n */\nvar TWITTER_SHARE_URL = \"http://twitter.com/share?&url=\";\n\n/**\n * Buzz share URL.\n */\nvar BUZZ_SHARE_URL = \"http://www.google.com/buzz/post?&url=\";\n\n/**\n * Opens new window either of facebook, twitter or google buzz.\n * @param {String} id Specifies whether to share news on Facebook, Google Buzz\n *     or Twitter.\n * @param {String} url Contains URL of the News to be shared.\n */\nfunction openNewsShareWindow(id, url) {\n  var newsUrl = url.substring(url.indexOf('&url=') + 5);\n  var openUrl;\n  switch (id) {\n     case 'fb':\n       openUrl = FB_SHARE_URL;\n       break;\n     case 'buzz':\n       openUrl = BUZZ_SHARE_URL;\n       break;\n     case 'twitter':\n       openUrl = TWITTER_SHARE_URL;\n       break;\n   }\n  window.open(openUrl + newsUrl, '_blank',\n      'resizable=0,scrollbars=0,width=690,height=415');\n}\n\n/**\n * Checks language in image url retrieved from feed and sets style of \n * title and openbox in pop-up page(if url is found), otherwise sets\n * to default styling.\n */\nfunction setStyleByLang(titleImgUrl) {\n  var openBoxes = document.getElementsByClassName('open_box');\n  var itemTitles = document.getElementsByClassName('item_title');\n\n  if (titleImgUrl != 'NULL') {\n    var pattern = /ar_/gi;\n    var result = titleImgUrl.match(pattern);\n    if (result != null || titleImgUrl == ISRAEL_IMAGE_URL) {\n      document.querySelector('body').className = 'rtl';\n    }\n  }\n}\n\n/**\n * Reports the height.\n */\nfunction reportHeight() {\n  var msg = JSON.stringify({type:\"size\", size:document.body.offsetHeight});\n  parent.postMessage(msg, \"*\");\n}\n\n/**\n * Initialize the iframe body.\n */\nfunction frameLoaded() {\n  var links = document.getElementsByTagName(\"A\");\n  for (var i = 0, link; link = links[i]; i++) {\n    var class = link.className;\n    if (class != \"item_title\" && class != \"open_box\") {\n      link.addEventListener(\"click\", showStory);\n    }\n  }\n  window.addEventListener(\"message\", messageHandler);\n}\n\n/**\n * Redirects to Google news site according to clicked URL.\n * @param {Object} event Onclick event.\n */\nfunction showStory(event) {\n  var href = event.currentTarget.href;\n  parent.postMessage(JSON.stringify({type:\"show\", url:href}), \"*\");\n  event.preventDefault();\n}\n\n/**\n * Handles message.\n * @param {Object} event Onmessage event.\n */\nfunction messageHandler(event) {\n  reportHeight();\n}\n</script>\n<script src = \"/javascript/feed.js\"></script>\n</head>\n\n<body onload = \"getTopics();getNewsByTitle();\" onunload = \"saveLastTopic();\">\n\n<div style = \"margin-bottom: 15px;\">\n  <div style = \"float: right;\">\n    <div style = \"float: right; font-size: 11px\">\n      <a id = \"option_link\" onclick = \"chrome.tabs.create({url: '/views/options.html', selected: true})\">\n      </a>\n    </div>\n    <div style = \"margin-top: 27px\">\n      <select id = \"topics\" onchange = \"getNewsByTitle();\" style = \"display: inline;\">\n      </select>\n    </div>\n  </div>\n  <a id = \"title_a\">\n    <img id = \"title\" style = \"padding-top: 5px;\">\n  </a>\n</div>\n\n<div id = \"feed\">\n</div>\n\n<div id = \"noStories\">\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/news/views/options.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2010 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n\n<!--\n@fileoverview This file serves as the option page of the extension for\ncustomizing the settings such as setting country, topics and number of\nnews stories to be shown.\n@author navneetg@google.com (Navneet Goel).\n-->\n\n<html>\n  <head>\n    <script src = \"/javascript/util.js\"></script>\n    <meta http-equiv = \"Content-Type\" content = \"text/html; charset = UTF-8\">\n    <link rel = \"stylesheet\" href = \"/css/options.css\"/>\n    <script src = \"/javascript/options.js\"></script>\n  </head>\n  <body onload = \"initialize();\">\n    <div id = \"all_content\">\n      <div id = \"logo\">\n        <img id = \"title_image\" src = \"/images/news.gif\"/>\n        <br/>\n      </div>\n      <br/><br/>\n\n      <table class = \"contentTable\" style = \"margin-left: 55px;\" width = \"96%\">\n        <tr class = \"all_rows\">\n          <td class = \"col1\"><b id = \"select_country\"></b></td>\n          <td class = \"col2\">\n            <select id = \"countryList\" onchange = \"enableSaveButton();\">\n              <option value = \"noCountry\">-Select-</option>\n              <option value = \"es_ar\">Argentina</option>\n              <option value = \"au\">Australia</option>\n              <option value = \"nl_be\">België</option>\n              <option value = \"fr_be\">Belgique</option>\n              <option value = \"en_bw\">Botswana</option>\n              <option value = \"pt-BR_br\">Brasil</option>\n              <option value = \"ca\">Canada English</option>\n              <option value = \"fr_ca\">Canada Français</option>\n              <option value = \"cs_cz\">Česká republika</option>\n              <option value = \"es_cl\">Chile</option>\n              <option value = \"es_co\">Colombia</option>\n              <option value = \"es_cu\">Cuba</option>\n              <option value = \"de\">Deutschland</option>\n              <option value = \"es\">España</option>\n              <option value = \"es_us\">Estados Unidos</option>\n              <option value = \"en_et\">Ethiopia</option>\n              <option value = \"fr\">France</option>\n              <option value = \"en_gh\">Ghana</option>\n              <option value = \"in\">India</option>\n              <option value = \"en_ie\">Ireland</option>\n              <option value = \"en_il\">Israel English</option>\n              <option value = \"it\">Italia</option>\n              <option value = \"en_ke\">Kenya</option>\n              <option value = \"hu_hu\">Magyarország</option>\n              <option value = \"en_my\">Malaysia</option>\n              <option value = \"es_mx\">México</option>\n              <option value = \"en_na\">Namibia</option>\n              <option value = \"nl_nl\">Nederland</option>\n              <option value = \"nz\">New Zealand</option>\n              <option value = \"en_ng\">Nigeria</option>\n              <option value = \"no_no\">Norge</option>\n              <option value = \"de_at\">Österreich</option>\n              <option value = \"en_pk\">Pakistan</option>\n              <option value = \"es_pe\">Perú</option>\n              <option value = \"en_ph\">Philippines</option>\n              <option value = \"pl_pl\">Polska</option>\n              <option value = \"pt-PT_pt\">Portugal</option>\n              <option value = \"de_ch\">Schweiz</option>\n              <option value = \"fr_sn\">Sénégal</option>\n              <option value = \"en_sg\">Singapore</option>\n              <option value = \"en_za\">South Africa</option>\n              <option value = \"fr_ch\">Suisse</option>\n              <option value = \"sv_se\">Sverige</option>\n              <option value = \"en_tz\">Tanzania</option>\n              <option value = \"tr_tr\">Türkiye</option>\n              <option value = \"uk\">U.K.</option>\n              <option value = \"us\">U.S.</option>\n              <option value = \"en_ug\">Uganda</option>\n              <option value = \"es_ve\">Venezuela</option>\n              <option value = \"vi_vn\">Việt Nam (Vietnam)</option>\n              <option value = \"en_zw\">Zimbabwe</option>\n              <option value = \"el_gr\">Ελλάδα (Greece)</option>\n              <option value = \"ru_ru\">Россия (Russia)</option>\n              <option value = \"ru_ua\">Украина / русский (Ukraine)</option>\n              <option value = \"uk_ua\">Україна / українська (Ukraine)</option>\n              <option value = \"iw_il\">ישראל (Israel)</option>\n              <option value = \"ar_ae\">الإمارات (UAE)</option>\n              <option value = \"ar_sa\">السعودية (KSA)</option>\n              <option value = \"ar_me\">العالم العربي (Arabic)</option>\n              <option value = \"ar_lb\">لبنان (Lebanon)</option>\n              <option value = \"ar_eg\">مصر (Egypt)</option>\n              <option value = \"hi_in\">हिन्दी (India)</option>\n              <option value = \"ta_in\">தமிழ்(India)</option>\n              <option value = \"te_in\">తెలుగు (India)</option>\n              <option value = \"ml_in\">മലയാളം (India)</option>\n              <option value = \"kr\">한국 (Korea)</option>\n              <option value = \"cn\">中国版 (China)</option>\n              <option value = \"tw\">台灣版 (Taiwan)</option>\n              <option value = \"jp\">日本 (Japan)</option>\n              <option value = \"hk\">香港版 (Hong Kong)</option>\n            </select>\n          </td>\n        </tr>\n        <tr class = \"all_rows\">\n          <td class = \"col1\"><b id = \"story_count\"></b></td>\n          <td class = \"col2\">\n            <select id = \"storyCount\" style = \"padding-left: 3px;\" onchange = \"enableSaveButton();\">\n              <option value = \"1\">1</option>\n              <option value = \"2\">2</option>\n              <option value = \"3\">3</option>\n              <option value = \"4\">4</option>\n              <option value = \"5\" selected = \"selected\">5</option>\n              <option value = \"6\">6</option>\n              <option value = \"7\">7</option>\n              <option value = \"8\">8</option>\n              <option value = \"9\">9</option>\n              <option value = \"10\">10</option>\n            </select>\n          </td>\n        </tr>\n        <tr class = \"all_rows\">\n          <td class = \"col1\">\n            <div id = \"topic\" style = \"font-weight: bold;\"></div>\n          </td>\n          <td class = \"col2\">\n            <div>\n              <div class = \"boxAndTopic\"><input class = \"checkBox\" type = \"checkbox\" value = \" \" id = \"check11\" onchange = \"manageCheckCount(this.id)\"/><div class = \"checkBoxTopic\" id = \"top\"></div><br/></div>\n              <div class = \"boxAndTopic\"><input class = \"checkBox\" type = \"checkbox\" value = \"n\" id = \"check13\" onchange = \"manageCheckCount(this.id)\"/><div class = \"checkBoxTopic\" id = \"nation\"></div><br/></div>\n              <div class = \"boxAndTopic\"><input class = \"checkBox\" type = \"checkbox\" value = \"w\" id = \"check14\" onchange = \"manageCheckCount(this.id)\"/><div class = \"checkBoxTopic\" id = \"world\"></div><br/></div>\n              <div class = \"boxAndTopic\"><input class = \"checkBox\" type = \"checkbox\" value = \"b\" id = \"check15\" onchange = \"manageCheckCount(this.id)\"/><div class = \"checkBoxTopic\" id = \"business\"></div><br/></div>\n              <div class = \"boxAndTopic\"><input class = \"checkBox\" type = \"checkbox\" value = \"t\" id = \"check16\" onchange = \"manageCheckCount(this.id)\"/><div class = \"checkBoxTopic\" id = \"science\"></div><br/></div>\n              <div class = \"boxAndTopic\"><input class = \"checkBox\" type = \"checkbox\" value = \"e\" id = \"check17\" onchange = \"manageCheckCount(this.id)\"/><div class = \"checkBoxTopic\" id = \"entertainment\"></div><br/></div>\n              <div class = \"boxAndTopic\"><input class = \"checkBox\" type = \"checkbox\" value = \"s\" id = \"check18\" onchange = \"manageCheckCount(this.id)\"/><div class = \"checkBoxTopic\" id = \"sports\"></div><br/></div>\n              <div class = \"boxAndTopic\"><input class = \"checkBox\" type = \"checkbox\" value = \"m\" id = \"check19\" onchange = \"manageCheckCount(this.id)\"/><div class = \"checkBoxTopic\" id = \"health\"></div><br/></div>\n              <div class = \"boxAndTopic\"><input class = \"checkBox\" type = \"checkbox\" value = \"po\" id = \"check20\" onchange = \"manageCheckCount(this.id)\"/><div class = \"checkBoxTopic\" id = \"most\"></div><br/></div>\n            </div>\n          </td>\n        </tr>\n        <tr class = \"all_rows\">\n          <td class = \"col1\">\n            <div id = \"custom_text\" style = \"font-weight: bold;\"></div>\n          </td>\n          <td class = \"col2\">\n            <input id = \"newKeyword\" type = \"text\" maxlength = \"20\" style = \"width: 205px;\">\n            <input id = \"submit_button\" type = \"submit\" onclick = \"addCusTopic()\" style = \"width: 45px;\">\n            <span id = \"invalid_status\"></span>\n            <table>\n              <tbody id = \"custom_topics\"></tbody>\n            </table>\n          </td>\n        </tr>\n      </table>\n      <br/>\n      <div id = \"save_div\">\n        <button id = \"save_button\" type = \"button\" disabled = \"disabled\" onclick = \"saveTopicsCountry()\" style = \"width: 80px;\">\n        </button>\n        <span id = \"save_status\"></span>\n      </div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/news_a11y/README",
    "content": "# News (accessibility)\n\nThis sample demonstrates a popup panel that access a remote URL. In this case, we are the Google News RSS feed, and building a UI to display that information. The UI here was built in a way to be particularly mindful of accessibility, and is fully navigable by a keyboard.\n\n## Implementation Notes\n\nNote that this is a _very_ old example, and is kept here purely for archival purposes. We do not recommend using this as a base of a new extension.\n"
  },
  {
    "path": "_archive/mv2/extensions/news_a11y/feed.css",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nbody {\n  font-family: helvetica, arial, sans-serif;\n  font-size: 12px;\n  overflow: hidden;\n}\n\na {\n  color:#0000CC;\n  text-decoration: underline;\n  cursor: pointer;\n}\n\n.open_box {\n  display: block;\n  overflow: hidden;\n  margin-right: 4px;\n  margin-top: 2px;\n  height: 12px;\n  width: 12px;\n  float: left;\n  clear: left;\n  background-image: url(sprite_arrows.gif);\n  background-position: 0px -24px;\n  cursor: pointer;\n}\n\n.opened .open_box {\n  background-position:-12px -24px;\n}\n\n.item {\n  padding: 2px 0px;\n}\n\n.item_title {\n  display: block;\n  min-width: 300px;\n  padding-left: 15px;\n  cursor: pointer;\n}\n\n.item_desc {\n  min-width: 500px;\n  height: 0px;\n  display: block;\n  border: none;\n  padding: 0px;\n  margin: 0px;\n  transition: height 0.2s ease-out;\n}\n\n#title {\n  display: block;\n  margin-left: auto;\n}\n\n.error {\n  white-space: nowrap;\n  color: red;\n}\n\n.more {\n  display: block;\n  text-align: right;\n  padding-top: 20px;\n  padding-right: 10px;\n  color: #88C;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/news_a11y/feed.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <link href=\"feed.css\" rel=\"stylesheet\" type=\"text/css\">\n    <script src=\"feed.js\"></script>\n  </head>\n  <body>\n    <a id=\"title_a\" tabIndex=\"0\"><img id='title' alt=\"Google News logo\"></a>\n    <div id=\"feed\"></div>\n  </body>\n</html>\n\n"
  },
  {
    "path": "_archive/mv2/extensions/news_a11y/feed.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Feed\nvar feedUrl = 'https://news.google.com/?output=rss';\n\n// The XMLHttpRequest object that tries to load and parse the feed.\nvar req;\n\nfunction main() {\n  req = new XMLHttpRequest();\n  req.onload = handleResponse;\n  req.onerror = handleError;\n  req.open('GET', feedUrl, true);\n  req.send(null);\n}\n\n// Handles feed parsing errors.\nfunction handleFeedParsingFailed(error) {\n  var feed = document.getElementById('feed');\n  feed.className = 'error';\n  feed.innerText = 'Error: ' + error;\n}\n\n// Handles errors during the XMLHttpRequest.\nfunction handleError() {\n  handleFeedParsingFailed('Failed to fetch RSS feed.');\n}\n\n// Handles parsing the feed data we got back from XMLHttpRequest.\nfunction handleResponse() {\n  var doc = req.responseXML;\n  if (!doc) {\n    handleFeedParsingFailed('Not a valid feed.');\n    return;\n  }\n  buildPreview(doc);\n}\n\n// The maximum number of feed items to show in the preview.\nvar maxFeedItems = 5;\n\n// Where the more stories link should navigate to.\nvar moreStoriesUrl;\n\nfunction buildPreview(doc) {\n  // Get the link to the feed source.\n  var link = doc.getElementsByTagName('link');\n  var parentTag = link[0].parentNode.tagName;\n  if (parentTag != 'item' && parentTag != 'entry') {\n    moreStoriesUrl = link[0].textContent;\n  }\n\n  // Setup the title image.\n  var images = doc.getElementsByTagName('image');\n  var titleImg;\n  if (images.length != 0) {\n    var urls = images[0].getElementsByTagName('url');\n    if (urls.length != 0) {\n      titleImg = urls[0].textContent;\n    }\n  }\n  var img = document.getElementById('title');\n  // Listen for mouse and key events\n  if (titleImg) {\n    img.src = titleImg;\n    if (moreStoriesUrl) {\n      document.getElementById('title_a').addEventListener('click',\n          moreStories);\n      document.getElementById('title_a').addEventListener('keydown',\n                                         function(event) {\n                                           if (event.keyCode == 13) {\n                                             moreStories(event);\n                                           }});\n    }\n  } else {\n    img.style.display = 'none';\n  }\n\n  // Construct the iframe's HTML.\n  var iframe_src = `<!doctype html><html><head><title>f</title>\n    <script src=\"${chrome.runtime.getURL('/feed_iframe.js')}\"></script>\n    <link href=\"${chrome.runtime.getURL('/feed_iframe.css')} rel=\"stylesheet\" type=\"text/css\">\n    </head><body>`;\n\n\n  var feed = document.getElementById('feed');\n  // Set ARIA role indicating the feed element has a tree structure\n  feed.setAttribute('role', 'tree');\n\n  var entries = doc.getElementsByTagName('entry');\n  if (entries.length == 0) {\n    entries = doc.getElementsByTagName('item');\n  }\n  var count = Math.min(entries.length, maxFeedItems);\n  for (var i = 0; i < count; i++) {\n    item = entries.item(i);\n\n    // Grab the title for the feed item.\n    var itemTitle = item.getElementsByTagName('title')[0];\n    if (itemTitle) {\n      itemTitle = itemTitle.textContent;\n    } else {\n      itemTitle = 'Unknown title';\n    }\n\n    // Grab the description.\n    var itemDesc = item.getElementsByTagName('description')[0];\n    if (!itemDesc) {\n      itemDesc = item.getElementsByTagName('summary')[0];\n      if (!itemDesc) {\n        itemDesc = item.getElementsByTagName('content')[0];\n      }\n    }\n    if (itemDesc) {\n      itemDesc = itemDesc.childNodes[0].nodeValue;\n    } else {\n      itemDesc = '';\n    }\n\n    var item = document.createElement('div');\n    item.className = 'item';\n    var box = document.createElement('div');\n    box.className = 'open_box';\n    box.addEventListener('click', showDesc);\n    // Disable focusing on box image separately from rest of tree item\n    box.tabIndex = -1;\n    item.appendChild(box);\n\n    var title = document.createElement('a');\n    title.className = 'item_title';\n    // Give title an ID for use with ARIA\n    title.id = 'item' + i;\n    title.innerText = itemTitle;\n    title.addEventListener('click', showDesc);\n    title.addEventListener('keydown', keyHandlerShowDesc);\n    // Update aria-activedescendant property in response to focus change\n    // within the tree\n    title.addEventListener('focus', function(event) {\n                                      feed.setAttribute(\n                                        'aria-activedescendant', this.id);\n                                    });\n    // Enable keyboard focus on the item title element\n    title.tabIndex = 0;\n    // Set ARIA role role indicating that the title element is a node in the\n    // tree structure\n    title.setAttribute('role', 'treeitem');\n    // Set the ARIA state indicating this tree item is currently collapsed.\n    title.setAttribute('aria-expanded', 'false');\n    // Set ARIA property indicating that all items are at the same hierarchical\n    // level (no nesting)\n    title.setAttribute('aria-level', '1');\n    item.appendChild(title);\n\n    var desc = document.createElement('iframe');\n    desc.scrolling = 'no';\n    desc.className = 'item_desc';\n    // Disable keyboard focus on elements in iFrames that have not been\n    // displayed yet\n    desc.tabIndex = -1;\n    // The story body is created as an iframe with a data: URL in order to\n    // isolate it from this page and protect against XSS.  As a data URL, it\n    // has limited privileges and must communicate back using postMessage().\n    desc.src=`data:text/html,${iframe_src}${itemDesc.replace(/#/g,\"\")}</body></html>`;\n\n    item.appendChild(desc);\n    feed.appendChild(item);\n  }\n\n  if (moreStoriesUrl) {\n    var more = document.createElement('a');\n    more.className = 'more';\n    more.innerText = 'More stories \\u00BB';\n    more.tabIndex = 0;\n    more.addEventListener('click', moreStories);\n    more.addEventListener('keydown', function(event) {\n                                       if (event.keyCode == 13) {\n                                         moreStories(event);\n                                       }});\n    feed.appendChild(more);\n  }\n}\n\n// Show |url| in a new tab.\nfunction showUrl(url) {\n  // Only allow http and https URLs.\n  if (!url.startsWith('http:') && !url.startsWith('https:'))\n    return;\n\n  chrome.tabs.create({url: url});\n}\n\nfunction moreStories(event) {\n  showUrl(moreStoriesUrl);\n}\n\nfunction keyHandlerShowDesc(event) {\n// Display content under heading when spacebar or right-arrow pressed\n// Hide content when spacebar pressed again or left-arrow pressed\n// Move to next heading when down-arrow pressed\n// Move to previous heading when up-arrow pressed\n  if (event.keyCode == 32) {\n    showDesc(event);\n  } else if ((this.parentNode.className == 'item opened') &&\n           (event.keyCode == 37)) {\n    showDesc(event);\n  } else if ((this.parentNode.className == 'item') && (event.keyCode == 39)) {\n    showDesc(event);\n  } else if (event.keyCode == 40) {\n    if (this.parentNode.nextSibling) {\n      this.parentNode.nextSibling.children[1].focus();\n    }\n  } else if (event.keyCode == 38) {\n    if (this.parentNode.previousSibling) {\n      this.parentNode.previousSibling.children[1].focus();\n    }\n  }\n}\n\nfunction showDesc(event) {\n  var item = event.currentTarget.parentNode;\n  var items = document.getElementsByClassName('item');\n  for (var i = 0; i < items.length; i++) {\n    var iframe = items[i].getElementsByClassName('item_desc')[0];\n    if (items[i] == item && items[i].className == 'item') {\n      items[i].className = 'item opened';\n      iframe.contentWindow.postMessage('reportHeight', '*');\n      // Set the ARIA state indicating the tree item is currently expanded.\n      items[i].getElementsByClassName('item_title')[0].\n        setAttribute('aria-expanded', 'true');\n      iframe.tabIndex = 0;\n    } else {\n      items[i].className = 'item';\n      iframe.style.height = '0px';\n      // Set the ARIA state indicating the tree item is currently collapsed.\n      items[i].getElementsByClassName('item_title')[0].\n        setAttribute('aria-expanded', 'false');\n      iframe.tabIndex = -1;\n    }\n  }\n}\n\nfunction iframeMessageHandler(e) {\n  // Only listen to messages from one of our own iframes.\n  var iframes = document.getElementsByTagName('IFRAME');\n  for (var i = 0; i < iframes.length; i++) {\n    if (iframes[i].contentWindow == e.source) {\n      var msg = JSON.parse(e.data);\n      if (msg) {\n        if (msg.type == 'size') {\n          iframes[i].style.height = msg.size + 'px';\n        } else if (msg.type == 'show') {\n          var url = msg.url;\n          if (url.startsWith('http://news.google.com')) {\n            // If the URL is a redirect URL, strip of the destination and go to\n            // that directly.  This is necessary because the Google news\n            // redirector blocks use of the redirects in this case.\n            var index = url.indexOf('&url=');\n            if (index >= 0) {\n              url = url.substring(index + 5);\n              index = url.indexOf('&');\n              if (index >= 0)\n                url = url.substring(0, index);\n            }\n          }\n          showUrl(url);\n        }\n      }\n      return;\n    }\n  }\n}\n\nwindow.addEventListener('message', iframeMessageHandler);\ndocument.addEventListener('DOMContentLoaded', main);\n"
  },
  {
    "path": "_archive/mv2/extensions/news_a11y/feed_iframe.css",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nbody {\n  margin: 0;\n  padding: 0;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/news_a11y/feed_iframe.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction reportHeight() {\n  var msg = JSON.stringify({type:\"size\", size:document.body.offsetHeight});\n  parent.postMessage(msg, \"*\");\n}\n\nfunction frameLoaded() {\n  var links = document.getElementsByTagName(\"A\");\n  for (i = 0; i < links.length; i++) {\n    var c = links[i].className;\n    if (c != \"item_title\" && c != \"open_box\") {\n      links[i].addEventListener(\"click\", showStory);\n    }\n  }\n  window.addEventListener(\"message\", messageHandler);\n}\n\nfunction showStory(event) {\n  var href = event.currentTarget.href;\n  parent.postMessage(JSON.stringify({type:\"show\", url:href}), \"*\");\n  event.preventDefault();\n}\n\nfunction messageHandler(event) {\n  reportHeight();\n}\n\ndocument.addEventListener('DOMContentLoaded', frameLoaded);\n"
  },
  {
    "path": "_archive/mv2/extensions/news_a11y/manifest.json",
    "content": "{\n  \"name\": \"News Reader\",\n  \"version\": \"1.1\",\n  \"description\": \"Displays the first 5 items from the 'Google News - top news' RSS feed in a popup.\",\n  \"icons\": { \"128\": \"news_icon.png\" },\n  \"browser_action\": {\n    \"default_title\": \"Google News\",\n    \"default_icon\": \"news_action.png\",\n    \"default_popup\": \"feed.html\"\n  },\n  \"permissions\": [\n    \"tabs\",\n    \"https://news.google.com/*\"\n  ],\n  \"manifest_version\": 2,\n  \"content_security_policy\": \"default-src; img-src 'self' http://* https://*; script-src 'self'; connect-src http://news.google.com; frame-src data:\"\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/news_i18n/README",
    "content": "# News (i18n)\n\nThis sample demonstrates a popup panel that access a remote URL. In this case, we are the Google News RSS feed, and building a UI to display that information. Additionally, this sample was built for multiple languages, to demonstrate how to support multiple languages within one extension.\n\n## Implementation Notes\n\nNote that this is a _very_ old example, and is kept here purely for archival purposes. We do not recommend using this as a base of a new extension.\n"
  },
  {
    "path": "_archive/mv2/extensions/news_i18n/_locales/en/messages.json",
    "content": "{\n  \"name\": {\n    \"message\": \"News Reader\",\n    \"description\": \"Extension name in manifest.\"\n  },\n  \"description\": {\n    \"message\": \"Displays the first 5 items from the '$Google$ News - top news' RSS feed in a popup.\",\n    \"description\": \"Extension description in manifest.\",\n    \"placeholders\": {\n      \"google\": {\n        \"content\": \"Google\",\n        \"example\": \"Google\"\n      }\n    }\n  },\n  \"default_title\": {\n    \"message\": \"$Google$ News\",\n    \"description\": \"Extension browser action tooltip text in manifest.\",\n    \"placeholders\": {\n      \"google\": {\n        \"content\": \"Google\",\n        \"example\": \"Google\"\n      }\n    }\n  },\n  \"unknown_title\": {\n    \"message\": \"Unknown title\",\n    \"description\": \"Unknown news title.\"\n  },\n  \"error\": {\n    \"message\": \"Error: $error$\",\n    \"description\": \"Generic error template. Expects error parameter to be passed in.\",\n    \"placeholders\": {\n      \"error\": {\n        \"content\": \"$1\",\n        \"example\": \"Failed to fetch RSS feed.\"\n      }\n    }\n  },\n  \"failed_to_fetch_rss\": {\n    \"message\": \"Failed to fetch RSS feed.\",\n    \"description\": \"User visible error message.\"\n  },\n  \"not_a_valid_feed\": {\n    \"message\": \"Not a valid feed.\",\n    \"description\": \"User visible error message.\"\n  },\n  \"more_stories\": {\n    \"message\": \"To $Google$ News \\u00BB\",\n    \"description\": \"Link name to more Google News.\",\n    \"placeholders\": {\n      \"google\": {\n        \"content\": \"Google\",\n        \"example\": \"Google\"\n      }\n    }\n  },\n  \"newsUrl\": {\n    \"message\": \"https://news.google.com\",\n    \"description\": \"Url to Google News.\"\n  }\n}\n\n"
  },
  {
    "path": "_archive/mv2/extensions/news_i18n/_locales/es/messages.json",
    "content": "{\n  \"name\": {\n    \"message\": \"Lector de noticias\",\n    \"description\": \"Nombre de la extensi\\xC3\\xB3n en el manifiesto.\"\n  },\n  \"description\": {\n    \"message\": \"Muestra los primeros 5 eventos de '$Google$ noticias - destacados' RSS feed en una ventana.\",\n    \"description\": \"Descripci\\xC3\\xB3n de la extensi\\xC3\\xB3n en el manifiesto.\",\n    \"placeholders\": {\n      \"google\": {\n        \"content\": \"Google\",\n        \"example\": \"Google\"\n      }\n    }\n  },\n  \"default_title\": {\n    \"message\": \"$Google$ noticias\",\n    \"description\": \"Texto de la accion de men\\xC3\\xBA de la extension en el manifiesto.\",\n    \"placeholders\": {\n      \"google\": {\n        \"content\": \"Google\",\n        \"example\": \"Google\"\n      }\n    }\n  },\n  \"unknown_title\": {\n    \"message\": \"T\\xC3\\xADtulo desconocido\",\n    \"description\": \"Noticia con t\\xC3\\xADtulo desconocido.\"\n  },\n  \"error\": {\n    \"message\": \"Error: $error$\",\n    \"description\": \"Plantilla de error gen\\xC3\\xA9rico. Hace falta pasar un par\\xC3\\xA1metro de error.\",\n    \"placeholders\": {\n      \"error\": {\n        \"content\": \"$1\",\n        \"example\": \"Fallo al capturar el RSS feed.\"\n      }\n    }\n  },\n  \"failed_to_fetch_rss\": {\n    \"message\": \"Fallo al capturar el RSS feed.\",\n    \"description\": \"Mensaje de error visible para el usuario.\"\n  },\n  \"not_a_valid_feed\": {\n    \"message\": \"Feed no v\\xC3\\xA1lido.\",\n    \"description\": \"Mensaje de error visible para el usuario.\"\n  },\n  \"more_stories\": {\n    \"message\": \"Ir a $Google$ noticias \\u00BB\",\n    \"description\": \"Nombre del enlace a Google noticias.\",\n    \"placeholders\": {\n      \"google\": {\n        \"content\": \"Google\",\n        \"example\": \"Google\"\n      }\n    }\n  },\n  \"newsUrl\": {\n    \"message\": \"https://news.google.es\",\n    \"description\": \"Direcci\\xC3\\xB3n de Google News.\"\n  }\n}\n\n"
  },
  {
    "path": "_archive/mv2/extensions/news_i18n/_locales/sr/messages.json",
    "content": "{\n  \"name\": {\n    \"message\": \"Читач вести\",\n    \"description\": \"Назив екстензије у манифесту.\"\n  },\n  \"description\": {\n    \"message\": \"Приказује првих 5 вести са '$Google$ Вести - главне вести' у прозорчићу.\",\n    \"description\": \"Опис екстензије у манифесту.\",\n    \"placeholders\": {\n      \"google\": {\n        \"content\": \"Google\",\n        \"example\": \"Google\"\n      }\n    }\n  },\n  \"default_title\": {\n    \"message\": \"$Google$ Вести\",\n    \"description\": \"Назив дугмета екстензије.\",\n    \"placeholders\": {\n      \"google\": {\n        \"content\": \"Google\",\n        \"example\": \"Google\"\n      }\n    }\n  },\n  \"unknown_title\": {\n    \"message\": \"Непознат наслов\",\n    \"description\": \"Непознат наслов вести.\"\n  },\n  \"error\": {\n    \"message\": \"Грешка - $error$\",\n    \"description\": \"Општи облик грешке.\",\n    \"placeholders\": {\n      \"error\": {\n        \"content\": \"$1\",\n        \"example\": \"фид је недоступан.\"\n      }\n    }\n  },\n  \"failed_to_fetch_rss\": {\n    \"message\": \"фид је недоступан.\",\n    \"description\": \"Порука грешке коју види корисник када је фид недоступан.\"\n  },\n  \"not_a_valid_feed\": {\n    \"message\": \"неисправан фид.\",\n    \"description\": \"Порука грешке коју види корисник када је фид неисправан.\"\n  },\n  \"more_stories\": {\n    \"message\": \"Ка $Google$ Вестима \\u00BB\",\n    \"description\": \"Назив везе ка још вести.\",\n    \"placeholders\": {\n      \"google\": {\n        \"content\": \"Google\",\n        \"example\": \"Google\"\n      }\n    }\n  }\n}\n\n"
  },
  {
    "path": "_archive/mv2/extensions/news_i18n/feed.css",
    "content": "body {\n  font-family: helvetica, arial, sans-serif;\n  font-size: 12px;\n  overflow: hidden;\n}\n\na {\n  color:#0000CC;\n  text-decoration: underline;\n  cursor: pointer;\n}\n\n.open_box {\n  display: block;\n  overflow: hidden;\n  margin-right: 4px;\n  margin-top: 2px;\n  height: 12px;\n  width: 12px;\n  float: left;\n  clear: left;\n  background-image: url(sprite_arrows.gif);\n  background-position: 0px -24px;\n  cursor: pointer;\n}\n\n.opened .open_box {\n  background-position:-12px -24px;\n}\n\n.item {\n  padding: 2px 0px;\n}\n\n.item_title {\n  display: block;\n  min-width: 300px;\n  padding-left: 15px;\n  cursor: pointer;\n}\n\n.item_desc {\n  min-width: 500px;\n  height: 0px;\n  display: block;\n  border: none;\n  padding: 0px;\n  margin: 0px;\n  transition: height 0.2s ease-out;\n}\n\n#title {\n  display: block;\n  margin-left: auto;\n}\n\n.error {\n  white-space: nowrap;\n  color: red;\n}\n\n.more {\n  display: block;\n  text-align: right;\n  padding-top: 20px;\n  padding-right: 10px;\n  color: #88C;\n}\n\n"
  },
  {
    "path": "_archive/mv2/extensions/news_i18n/feed.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <link rel=\"stylesheet\" href=\"./feed.css\" />\n    <script id=\"iframe_script\" src=\"./feed.js\"></script>\n</head>\n<body>\n<a id=\"title_a\"><img id='title'></a>\n<div id=\"feed\"></div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/news_i18n/feed.js",
    "content": "function reportHeight() {\n  var msg = JSON.stringify({type:\"size\", size:document.body.offsetHeight});\n  parent.postMessage(msg, \"*\");\n}\n\nfunction frameLoaded() {\n  var links = document.getElementsByTagName(\"A\");\n  for (i = 0; i < links.length; i++) {\n    var klass = links[i].klassName;\n    if (klass != \"item_title\" && klass != \"open_box\") {\n      links[i].addEventListener(\"click\", showStory);\n    }\n  }\n  window.addEventListener(\"message\", messageHandler);\n}\n\nfunction showStory(event) {\n  var href = event.currentTarget.href;\n  parent.postMessage(JSON.stringify({type:\"show\", url:href}), \"*\");\n  event.preventDefault();\n}\n\nfunction messageHandler(event) {\n  reportHeight();\n}\n\n// Feed URL.\nvar feedUrl = chrome.i18n.getMessage('newsUrl') + '/?output=rss';\n\n// The XMLHttpRequest object that tries to load and parse the feed.\nvar req;\n\nfunction main() {\n  req = new XMLHttpRequest();\n  req.onload = handleResponse;\n  req.onerror = handleError;\n  req.open(\"GET\", feedUrl, true);\n  req.send(null);\n}\n\n// Handles feed parsing errors.\nfunction handleFeedParsingFailed(error) {\n  var feed = document.getElementById(\"feed\");\n  feed.klassName = \"error\";\n  feed.innerText = chrome.i18n.getMessage(\"error\", error);\n}\n\n// Handles errors during the XMLHttpRequest.\nfunction handleError() {\n  handleFeedParsingFailed(chrome.i18n.getMessage('failed_to_fetch_rss'));\n}\n\n// Handles parsing the feed data we got back from XMLHttpRequest.\nfunction handleResponse() {\n  var doc = req.responseXML;\n  if (!doc) {\n    handleFeedParsingFailed(chrome.i18n.getMessage('not_a_valid_feed'));\n    return;\n  }\n  buildPreview(doc);\n}\n\n// The maximum number of feed items to show in the preview.\nvar maxFeedItems = 5;\n\n// Where the more stories link should navigate to.\nvar moreStoriesUrl;\n\nfunction buildPreview(doc) {\n  // Get the link to the feed source.\n  var link = doc.getElementsByTagName(\"link\");\n  var parentTag = link[0].parentNode.tagName;\n  if (parentTag != \"item\" && parentTag != \"entry\") {\n    moreStoriesUrl = link[0].textContent;\n  }\n\n  // Setup the title image.\n  var images = doc.getElementsByTagName(\"image\");\n  var titleImg;\n  if (images.length != 0) {\n    var urls = images[0].getElementsByTagName(\"url\");\n    if (urls.length != 0) {\n      titleImg = urls[0].textContent;\n    }\n  }\n  var img = document.getElementById(\"title\");\n  if (titleImg) {\n    img.src = titleImg;\n    if (moreStoriesUrl) {\n      document.getElementById(\"title_a\").addEventListener(\"click\", moreStories);\n    }\n  } else {\n    img.style.display = \"none\";\n  }\n\n  // Construct the iframe's HTML.\n  var iframe_src = \"<!doctype html><html><head><script>\" +\n                   document.getElementById(\"iframe_script\").textContent + \"<\" +\n                   \"/script></head><body onload='frameLoaded();' \" +\n                   \"style='padding:0px;margin:0px;'>\";\n\n  var feed = document.getElementById(\"feed\");\n  var entries = doc.getElementsByTagName('entry');\n  if (entries.length == 0) {\n    entries = doc.getElementsByTagName('item');\n  }\n  var count = Math.min(entries.length, maxFeedItems);\n  for (var i = 0; i < count; i++) {\n    item = entries.item(i);\n\n    // Grab the title for the feed item.\n    var itemTitle = item.getElementsByTagName('title')[0];\n    if (itemTitle) {\n      itemTitle = itemTitle.textContent;\n    } else {\n      itemTitle = chrome.i18n.getMessage(\"unknown_title\");\n    }\n\n    // Grab the description.\n    var itemDesc = item.getElementsByTagName('description')[0];\n    if (!itemDesc) {\n      itemDesc = item.getElementsByTagName('summary')[0];\n      if (!itemDesc) {\n        itemDesc = item.getElementsByTagName('content')[0];\n      }\n    }\n    if (itemDesc) {\n      itemDesc = itemDesc.childNodes[0].nodeValue;\n    } else {\n      itemDesc = '';\n    }\n\n    var item = document.createElement(\"div\");\n    item.klassName = \"item\";\n    var box = document.createElement(\"div\");\n    box.klassName = \"open_box\";\n    box.addEventListener(\"click\", showDesc);\n    item.appendChild(box);\n\n    var title = document.createElement(\"a\");\n    title.klassName = \"item_title\";\n    title.innerText = itemTitle;\n    title.addEventListener(\"click\", showDesc);\n    item.appendChild(title);\n\n    var desc = document.createElement(\"iframe\");\n    desc.scrolling = \"no\";\n    desc.klassName = \"item_desc\";\n    item.appendChild(desc);\n    feed.appendChild(item);\n\n    // The story body is created as an iframe with a data: URL in order to\n    // isolate it from this page and protect against XSS.  As a data URL, it\n    // has limited privileges and must communicate back using postMessage().\n    desc.src=\"data:text/html,\" + iframe_src + itemDesc + \"</body></html>\";\n  }\n\n  if (moreStoriesUrl) {\n    var more = document.createElement(\"a\");\n    more.klassName = \"more\";\n    more.innerText = chrome.i18n.getMessage(\"more_stories\");\n    more.addEventListener(\"click\", moreStories);\n    feed.appendChild(more);\n  }\n}\n\n// Show |url| in a new tab.\nfunction showUrl(url) {\n  // Only allow http and https URLs.\n  if (url.indexOf(\"http:\") != 0 && url.indexOf(\"https:\") != 0) {\n    return;\n  }\n  chrome.tabs.create({url: url});\n}\n\nfunction moreStories(event) {\n  showUrl(moreStoriesUrl);\n}\n\nfunction showDesc(event) {\n  var item = event.currentTarget.parentNode;\n  var items = document.getElementsByClassName(\"item\");\n  for (var i = 0; i < items.length; i++) {\n    var iframe = items[i].getElementsByClassName(\"item_desc\")[0];\n    if (items[i] == item && items[i].klassName == \"item\") {\n      items[i].klassName = \"item opened\";\n      iframe.contentWindow.postMessage(\"reportHeight\", \"*\");\n    } else {\n      items[i].klassName = \"item\";\n      iframe.style.height = \"0px\";\n    }\n  }\n}\n\nfunction iframeMessageHandler(e) {\n  // Only listen to messages from one of our own iframes.\n  var iframes = document.getElementsByTagName(\"IFRAME\");\n  for (var i = 0; i < iframes.length; i++) {\n    if (iframes[i].contentWindow == e.source) {\n      var msg = JSON.parse(e.data);\n      if (msg) {\n        if (msg.type == \"size\") {\n          iframes[i].style.height = msg.size + \"px\";\n        } else if (msg.type == \"show\") {\n          var url = msg.url;\n          if (url.indexOf(chrome.i18n.getMessage('newsUrl')) == 0) {\n            // If the URL is a redirect URL, strip of the destination and go to\n            // that directly.  This is necessary because the Google news\n            // redirector blocks use of the redirects in this case.\n            var index = url.indexOf(\"&url=\");\n            if (index >= 0) {\n              url = url.substring(index + 5);\n              index = url.indexOf(\"&\");\n              if (index >= 0)\n                url = url.substring(0, index);\n            }\n          }\n          showUrl(url);\n        }\n      }\n      return;\n    }\n  }\n}\n\nwindow.addEventListener(\"message\", iframeMessageHandler);\nwindow.addEventListener(\"DOMContentLoaded\", main);\n"
  },
  {
    "path": "_archive/mv2/extensions/news_i18n/manifest.json",
    "content": "{\n  \"name\": \"News Reader\",\n  \"version\": \"1.1\",\n  \"description\": \"Displays the first 5 items from the 'Google News - top news' RSS feed in a popup.\",\n  \"icons\": { \"128\": \"news_icon.png\" },\n  \"browser_action\": {\n    \"default_title\": \"Google News\",\n    \"default_icon\": \"news_action.png\",\n    \"default_popup\": \"feed.html\"\n  },\n  \"default_locale\": \"en\",\n  \"permissions\": [\n    \"tabs\",\n    \"https://news.google.es/*\",\n    \"https://news.google.com/*\"\n  ],\n  \"manifest_version\": 2,\n  \"content_security_policy\": \"default-src; img-src 'self' http://* https://*; script-src 'self'; connect-src https://news.google.com; frame-src data:\"\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/no_cookies/background.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\n// Simple extension to remove 'Cookie' request header and 'Set-Cookie' response\n// header.\n\nfunction removeHeader(headers, name) {\n  for (var i = 0; i < headers.length; i++) {\n    if (headers[i].name.toLowerCase() == name) {\n      console.log('Removing \"' + name + '\" header.');\n      headers.splice(i, 1);\n      break;\n    }\n  }\n}\n\nchrome.webRequest.onBeforeSendHeaders.addListener(\n  function(details) {\n    removeHeader(details.requestHeaders, 'cookie');\n    return {requestHeaders: details.requestHeaders};\n  },\n  // filters\n  {urls: ['https://*/*', 'http://*/*']},\n  // extraInfoSpec\n  ['blocking', 'requestHeaders', 'extraHeaders']);\n\nchrome.webRequest.onHeadersReceived.addListener(\n  function(details) {\n    removeHeader(details.responseHeaders, 'set-cookie');\n    return {responseHeaders: details.responseHeaders};\n  },\n  // filters\n  {urls: ['https://*/*', 'http://*/*']},\n  // extraInfoSpec\n  ['blocking', 'responseHeaders', 'extraHeaders']);\n"
  },
  {
    "path": "_archive/mv2/extensions/no_cookies/manifest.json",
    "content": "{\n  \"name\": \"No Cookies\",\n  \"description\": \"Removes 'Cookie' and 'Set-Cookie' headers.\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 2,\n  \"permissions\": [\n    \"webRequest\",\n    \"webRequestBlocking\",\n    \"https://*/*\",\n    \"http://*/*\"\n  ],\n  \"background\": {\n    \"scripts\": [\"background.js\"]\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/oauth_contacts/NOTICE",
    "content": "This extension uses code from the following two JavaScript libraries:\n\nhttp://unitedheroes.net/OAuthSimple/js/OAuthSimple.js\n=====================================================\n/* OAuthSimple\n  * A simpler version of OAuth\n  *\n  * author:     jr conlin\n  * mail:       src@anticipatr.com\n  * copyright:  unitedHeroes.net\n  * version:    1.0 \n  * url:        http://unitedHeroes.net/OAuthSimple\n  *\n  * Copyright (c) 2009, unitedHeroes.net\n  * All rights reserved.\n  *\n  * Redistribution and use in source and binary forms, with or without\n  * modification, are permitted provided that the following conditions are met:\n  *     * Redistributions of source code must retain the above copyright\n  *       notice, this list of conditions and the following disclaimer.\n  *     * Redistributions in binary form must reproduce the above copyright\n  *       notice, this list of conditions and the following disclaimer in the\n  *       documentation and/or other materials provided with the distribution.\n  *     * Neither the name of the unitedHeroes.net nor the\n  *       names of its contributors may be used to endorse or promote products\n  *       derived from this software without specific prior written permission.\n  *\n  * THIS SOFTWARE IS PROVIDED BY UNITEDHEROES.NET ''AS IS'' AND ANY\n  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  * DISCLAIMED. IN NO EVENT SHALL UNITEDHEROES.NET BE LIABLE FOR ANY\n  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n \n http://pajhome.org.uk/crypt/md5/sha1.js\n =======================================\n /*\n * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined\n * in FIPS PUB 180-1\n * Version 2.1a Copyright Paul Johnston 2000 - 2002.\n * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\n * Distributed under the BSD License\n * See http://pajhome.org.uk/crypt/md5 for details.\n */\n"
  },
  {
    "path": "_archive/mv2/extensions/oauth_contacts/README",
    "content": "Sample extension to demonstrate integration with an OAuth service.\n\nOverview\n--------\nThis sample demonstrates the use of OAuth to authorize against \nGoogle's Contacts API inside of an extension.  It implements a library which\nmay be reused generically to authorize requests to any 3-legged OAuth API.\n\nLibrary\n-------\nThe library files are:\n * chrome_ex_oauth.html\n * chrome_ex_oauth.js\n * chrome_ex_oauthsimple.js\n\nTo use these files, place them in the root of your extension and include both\n.js files in your background page in the following order:\n\n  <script type=\"text/javascript\" src=\"chrome_ex_oauthsimple.js\"></script>\n  <script type=\"text/javascript\" src=\"chrome_ex_oauth.js\"></script>   \n  \nTo initialize the API, create a ChromeExOAuth object in the background page:\n\n      var oauth = ChromeExOAuth.initBackgroundPage({\n        'request_url'     :  <OAuth request URL>, \n        'authorize_url'   :  <OAuth authorize URL>,  \n        'access_url'      :  <OAuth access token URL>,  \n        'consumer_key'    :  <OAuth consumer key>,  \n        'consumer_secret' :  <OAuth consumer secret>,  \n        'scope'           :  <scope parameter for this auth>,\n        'app_name'        :  <application name, not used by all OAuth providers>\n      }); \n\nCall the authorize() function to redirect the user to the OAuth provider in\norder to obtain an access token.  The client library abstracts most of this \nprocess, so all you need to do is pass a callback to the authorize() function\nand a new tab will open and redirect the user.  If the library already has\nstored an access token for the current scope, then no tab will be opened.  In\neither case, the callback will be called with the resulting token and secret.\n\n      oauth.authorize(onAuthorized);\n      \nThere is no need to store the token and secret, as this library already stores\nthese values in localStorage.  Once the callback you specified is called, you\ncan call the sendSignedRequest function to send OAuth-signed requests to the\nAPI.  The sendSignedRequest call takes an url to fetch, a callback function,\nand an optional parameter object as its arguments.  The callback is passed\nthe response text as well as the XMLHttpRequest object which was used to \nmake the request as its arguments.\n  \n      function callback(text, xhr) {\n        //...\n      };\n      \n      function onAuthorized() { \n        var url = <API url inside of the requested scope>;\n        var request = {\n          'method' : 'GET',\n          'parameters' : {\n             <Any request parameters as key : value pairs>\n          }\n        }\n        oauth.sendSignedRequest(url, callback, request);\n      };\n      oauth.authorize(onAuthorized);\n      \n \n\n\n"
  },
  {
    "path": "_archive/mv2/extensions/oauth_contacts/background.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar oauth = ChromeExOAuth.initBackgroundPage({\n  'request_url' : 'https://www.google.com/accounts/OAuthGetRequestToken',\n  'authorize_url' : 'https://www.google.com/accounts/OAuthAuthorizeToken',\n  'access_url' : 'https://www.google.com/accounts/OAuthGetAccessToken',\n  'consumer_key' : 'anonymous',\n  'consumer_secret' : 'anonymous',\n  'scope' : 'http://www.google.com/m8/feeds/',\n  'app_name' : 'Sample - OAuth Contacts'\n});\n\nvar contacts = null;\n\nfunction setIcon() {\n  if (oauth.hasToken()) {\n    chrome.browserAction.setIcon({ 'path' : 'img/icon-19-on.png'});\n  } else {\n    chrome.browserAction.setIcon({ 'path' : 'img/icon-19-off.png'});\n  }\n};\n\nfunction onContacts(text, xhr) {\n  contacts = [];\n  var data = JSON.parse(text);\n  for (var i = 0, entry; entry = data.feed.entry[i]; i++) {\n    var contact = {\n      'name' : entry['title']['$t'],\n      'id' : entry['id']['$t'],\n      'emails' : []\n    };\n\n    if (entry['gd$email']) {\n      var emails = entry['gd$email'];\n      for (var j = 0, email; email = emails[j]; j++) {\n        contact['emails'].push(email['address']);\n      }\n    }\n\n    if (!contact['name']) {\n      contact['name'] = contact['emails'][0] || \"<Unknown>\";\n    }\n    contacts.push(contact);\n  }\n\n  chrome.tabs.create({ 'url' : 'contacts.html'});\n};\n\nfunction getContacts() {\n  oauth.authorize(function() {\n    console.log(\"on authorize\");\n    setIcon();\n    var url = \"http://www.google.com/m8/feeds/contacts/default/full\";\n    oauth.sendSignedRequest(url, onContacts, {\n      'parameters' : {\n        'alt' : 'json',\n        'max-results' : 100\n      }\n    });\n  });\n};\n\nfunction logout() {\n  oauth.clearTokens();\n  setIcon();\n};\n\nsetIcon();\nchrome.browserAction.onClicked.addListener(getContacts);\n"
  },
  {
    "path": "_archive/mv2/extensions/oauth_contacts/chrome_ex_oauth.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2009 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n<html>\n  <head>\n    <title>OAuth Redirect Page</title>\n    <style type=\"text/css\">\n      body {\n        font: 16px Arial;\n        color: #333;\n      }\n    </style>\n    <script type=\"text/javascript\" src=\"chrome_ex_oauthsimple.js\"></script>\n    <script type=\"text/javascript\" src=\"chrome_ex_oauth.js\"></script>\n    <script type=\"text/javascript\" src=\"onload.js\"></script>\n  </head>\n  <body>\n    Redirecting...\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/oauth_contacts/chrome_ex_oauth.js",
    "content": "// Copyright (c) 2010 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * Constructor - no need to invoke directly, call initBackgroundPage instead.\n * @constructor\n * @param {String} url_request_token The OAuth request token URL.\n * @param {String} url_auth_token The OAuth authorize token URL.\n * @param {String} url_access_token The OAuth access token URL.\n * @param {String} consumer_key The OAuth consumer key.\n * @param {String} consumer_secret The OAuth consumer secret.\n * @param {String} oauth_scope The OAuth scope parameter.\n * @param {Object} opt_args Optional arguments.  Recognized parameters:\n *     \"app_name\" {String} Name of the current application\n *     \"callback_page\" {String} If you renamed chrome_ex_oauth.html, the name\n *          this file was renamed to.\n */\nfunction ChromeExOAuth(url_request_token, url_auth_token, url_access_token,\n                       consumer_key, consumer_secret, oauth_scope, opt_args) {\n  this.url_request_token = url_request_token;\n  this.url_auth_token = url_auth_token;\n  this.url_access_token = url_access_token;\n  this.consumer_key = consumer_key;\n  this.consumer_secret = consumer_secret;\n  this.oauth_scope = oauth_scope;\n  this.app_name = opt_args && opt_args['app_name'] ||\n      \"ChromeExOAuth Library\";\n  this.key_token = \"oauth_token\";\n  this.key_token_secret = \"oauth_token_secret\";\n  this.callback_page = opt_args && opt_args['callback_page'] ||\n      \"chrome_ex_oauth.html\";\n  this.auth_params = {};\n  if (opt_args && opt_args['auth_params']) {\n    for (key in opt_args['auth_params']) {\n      if (opt_args['auth_params'].hasOwnProperty(key)) {\n        this.auth_params[key] = opt_args['auth_params'][key];\n      }\n    }\n  }\n};\n\n/*******************************************************************************\n * PUBLIC API METHODS\n * Call these from your background page.\n ******************************************************************************/\n\n/**\n * Initializes the OAuth helper from the background page.  You must call this\n * before attempting to make any OAuth calls.\n * @param {Object} oauth_config Configuration parameters in a JavaScript object.\n *     The following parameters are recognized:\n *         \"request_url\" {String} OAuth request token URL.\n *         \"authorize_url\" {String} OAuth authorize token URL.\n *         \"access_url\" {String} OAuth access token URL.\n *         \"consumer_key\" {String} OAuth consumer key.\n *         \"consumer_secret\" {String} OAuth consumer secret.\n *         \"scope\" {String} OAuth access scope.\n *         \"app_name\" {String} Application name.\n *         \"auth_params\" {Object} Additional parameters to pass to the\n *             Authorization token URL.  For an example, 'hd', 'hl', 'btmpl':\n *             http://code.google.com/apis/accounts/docs/OAuth_ref.html#GetAuth\n * @return {ChromeExOAuth} An initialized ChromeExOAuth object.\n */\nChromeExOAuth.initBackgroundPage = function(oauth_config) {\n  window.chromeExOAuthConfig = oauth_config;\n  window.chromeExOAuth = ChromeExOAuth.fromConfig(oauth_config);\n  window.chromeExOAuthRedirectStarted = false;\n  window.chromeExOAuthRequestingAccess = false;\n\n  var url_match = chrome.extension.getURL(window.chromeExOAuth.callback_page);\n  var tabs = {};\n  chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {\n    if (changeInfo.url &&\n        changeInfo.url.substr(0, url_match.length) === url_match &&\n        changeInfo.url != tabs[tabId] &&\n        window.chromeExOAuthRequestingAccess == false) {\n      chrome.tabs.create({ 'url' : changeInfo.url }, function(tab) {\n        tabs[tab.id] = tab.url;\n        chrome.tabs.remove(tabId);\n      });\n    }\n  });\n\n  return window.chromeExOAuth;\n};\n\n/**\n * Authorizes the current user with the configued API.  You must call this\n * before calling sendSignedRequest.\n * @param {Function} callback A function to call once an access token has\n *     been obtained.  This callback will be passed the following arguments:\n *         token {String} The OAuth access token.\n *         secret {String} The OAuth access token secret.\n */\nChromeExOAuth.prototype.authorize = function(callback) {\n  if (this.hasToken()) {\n    callback(this.getToken(), this.getTokenSecret());\n  } else {\n    window.chromeExOAuthOnAuthorize = function(token, secret) {\n      callback(token, secret);\n    };\n    chrome.tabs.create({ 'url' :chrome.extension.getURL(this.callback_page) });\n  }\n};\n\n/**\n * Clears any OAuth tokens stored for this configuration.  Effectively a\n * \"logout\" of the configured OAuth API.\n */\nChromeExOAuth.prototype.clearTokens = function() {\n  delete localStorage[this.key_token + encodeURI(this.oauth_scope)];\n  delete localStorage[this.key_token_secret + encodeURI(this.oauth_scope)];\n};\n\n/**\n * Returns whether a token is currently stored for this configuration.\n * Effectively a check to see whether the current user is \"logged in\" to\n * the configured OAuth API.\n * @return {Boolean} True if an access token exists.\n */\nChromeExOAuth.prototype.hasToken = function() {\n  return !!this.getToken();\n};\n\n/**\n * Makes an OAuth-signed HTTP request with the currently authorized tokens.\n * @param {String} url The URL to send the request to.  Querystring parameters\n *     should be omitted.\n * @param {Function} callback A function to be called once the request is\n *     completed.  This callback will be passed the following arguments:\n *         responseText {String} The text response.\n *         xhr {XMLHttpRequest} The XMLHttpRequest object which was used to\n *             send the request.  Useful if you need to check response status\n *             code, etc.\n * @param {Object} opt_params Additional parameters to configure the request.\n *     The following parameters are accepted:\n *         \"method\" {String} The HTTP method to use.  Defaults to \"GET\".\n *         \"body\" {String} A request body to send.  Defaults to null.\n *         \"parameters\" {Object} Query parameters to include in the request.\n *         \"headers\" {Object} Additional headers to include in the request.\n */\nChromeExOAuth.prototype.sendSignedRequest = function(url, callback,\n                                                     opt_params) {\n  var method = opt_params && opt_params['method'] || 'GET';\n  var body = opt_params && opt_params['body'] || null;\n  var params = opt_params && opt_params['parameters'] || {};\n  var headers = opt_params && opt_params['headers'] || {};\n\n  var signedUrl = this.signURL(url, method, params);\n\n  ChromeExOAuth.sendRequest(method, signedUrl, headers, body, function (xhr) {\n    if (xhr.readyState == 4) {\n      callback(xhr.responseText, xhr);\n    }\n  });\n};\n\n/**\n * Adds the required OAuth parameters to the given url and returns the\n * result.  Useful if you need a signed url but don't want to make an XHR\n * request.\n * @param {String} method The http method to use.\n * @param {String} url The base url of the resource you are querying.\n * @param {Object} opt_params Query parameters to include in the request.\n * @return {String} The base url plus any query params plus any OAuth params.\n */\nChromeExOAuth.prototype.signURL = function(url, method, opt_params) {\n  var token = this.getToken();\n  var secret = this.getTokenSecret();\n  if (!token || !secret) {\n    throw new Error(\"No oauth token or token secret\");\n  }\n\n  var params = opt_params || {};\n\n  var result = OAuthSimple().sign({\n    action : method,\n    path : url,\n    parameters : params,\n    signatures: {\n      consumer_key : this.consumer_key,\n      shared_secret : this.consumer_secret,\n      oauth_secret : secret,\n      oauth_token: token\n    }\n  });\n\n  return result.signed_url;\n};\n\n/**\n * Generates the Authorization header based on the oauth parameters.\n * @param {String} url The base url of the resource you are querying.\n * @param {Object} opt_params Query parameters to include in the request.\n * @return {String} An Authorization header containing the oauth_* params.\n */\nChromeExOAuth.prototype.getAuthorizationHeader = function(url, method,\n                                                          opt_params) {\n  var token = this.getToken();\n  var secret = this.getTokenSecret();\n  if (!token || !secret) {\n    throw new Error(\"No oauth token or token secret\");\n  }\n\n  var params = opt_params || {};\n\n  return OAuthSimple().getHeaderString({\n    action: method,\n    path : url,\n    parameters : params,\n    signatures: {\n      consumer_key : this.consumer_key,\n      shared_secret : this.consumer_secret,\n      oauth_secret : secret,\n      oauth_token: token\n    }\n  });\n};\n\n/*******************************************************************************\n * PRIVATE API METHODS\n * Used by the library.  There should be no need to call these methods directly.\n ******************************************************************************/\n\n/**\n * Creates a new ChromeExOAuth object from the supplied configuration object.\n * @param {Object} oauth_config Configuration parameters in a JavaScript object.\n *     The following parameters are recognized:\n *         \"request_url\" {String} OAuth request token URL.\n *         \"authorize_url\" {String} OAuth authorize token URL.\n *         \"access_url\" {String} OAuth access token URL.\n *         \"consumer_key\" {String} OAuth consumer key.\n *         \"consumer_secret\" {String} OAuth consumer secret.\n *         \"scope\" {String} OAuth access scope.\n *         \"app_name\" {String} Application name.\n *         \"auth_params\" {Object} Additional parameters to pass to the\n *             Authorization token URL.  For an example, 'hd', 'hl', 'btmpl':\n *             http://code.google.com/apis/accounts/docs/OAuth_ref.html#GetAuth\n * @return {ChromeExOAuth} An initialized ChromeExOAuth object.\n */\nChromeExOAuth.fromConfig = function(oauth_config) {\n  return new ChromeExOAuth(\n    oauth_config['request_url'],\n    oauth_config['authorize_url'],\n    oauth_config['access_url'],\n    oauth_config['consumer_key'],\n    oauth_config['consumer_secret'],\n    oauth_config['scope'],\n    {\n      'app_name' : oauth_config['app_name'],\n      'auth_params' : oauth_config['auth_params']\n    }\n  );\n};\n\n/**\n * Initializes chrome_ex_oauth.html and redirects the page if needed to start\n * the OAuth flow.  Once an access token is obtained, this function closes\n * chrome_ex_oauth.html.\n */\nChromeExOAuth.initCallbackPage = function() {\n  var background_page = chrome.extension.getBackgroundPage();\n  var oauth_config = background_page.chromeExOAuthConfig;\n  var oauth = ChromeExOAuth.fromConfig(oauth_config);\n  background_page.chromeExOAuthRedirectStarted = true;\n  oauth.initOAuthFlow(function (token, secret) {\n    background_page.chromeExOAuthOnAuthorize(token, secret);\n    background_page.chromeExOAuthRedirectStarted = false;\n    chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {\n      chrome.tabs.remove(tabs[0].id);\n    });\n  });\n};\n\n/**\n * Sends an HTTP request.  Convenience wrapper for XMLHttpRequest calls.\n * @param {String} method The HTTP method to use.\n * @param {String} url The URL to send the request to.\n * @param {Object} headers Optional request headers in key/value format.\n * @param {String} body Optional body content.\n * @param {Function} callback Function to call when the XMLHttpRequest's\n *     ready state changes.  See documentation for XMLHttpRequest's\n *     onreadystatechange handler for more information.\n */\nChromeExOAuth.sendRequest = function(method, url, headers, body, callback) {\n  var xhr = new XMLHttpRequest();\n  xhr.onreadystatechange = function(data) {\n    callback(xhr, data);\n  }\n  xhr.open(method, url, true);\n  if (headers) {\n    for (var header in headers) {\n      if (headers.hasOwnProperty(header)) {\n        xhr.setRequestHeader(header, headers[header]);\n      }\n    }\n  }\n  xhr.send(body);\n};\n\n/**\n * Decodes a URL-encoded string into key/value pairs.\n * @param {String} encoded An URL-encoded string.\n * @return {Object} An object representing the decoded key/value pairs found\n *     in the encoded string.\n */\nChromeExOAuth.formDecode = function(encoded) {\n  var params = encoded.split(\"&\");\n  var decoded = {};\n  for (var i = 0, param; param = params[i]; i++) {\n    var keyval = param.split(\"=\");\n    if (keyval.length == 2) {\n      var key = ChromeExOAuth.fromRfc3986(keyval[0]);\n      var val = ChromeExOAuth.fromRfc3986(keyval[1]);\n      decoded[key] = val;\n    }\n  }\n  return decoded;\n};\n\n/**\n * Returns the current window's querystring decoded into key/value pairs.\n * @return {Object} A object representing any key/value pairs found in the\n *     current window's querystring.\n */\nChromeExOAuth.getQueryStringParams = function() {\n  var urlparts = window.location.href.split(\"?\");\n  if (urlparts.length >= 2) {\n    var querystring = urlparts.slice(1).join(\"?\");\n    return ChromeExOAuth.formDecode(querystring);\n  }\n  return {};\n};\n\n/**\n * Binds a function call to a specific object.  This function will also take\n * a variable number of additional arguments which will be prepended to the\n * arguments passed to the bound function when it is called.\n * @param {Function} func The function to bind.\n * @param {Object} obj The object to bind to the function's \"this\".\n * @return {Function} A closure that will call the bound function.\n */\nChromeExOAuth.bind = function(func, obj) {\n  var newargs = Array.prototype.slice.call(arguments).slice(2);\n  return function() {\n    var combinedargs = newargs.concat(Array.prototype.slice.call(arguments));\n    func.apply(obj, combinedargs);\n  };\n};\n\n/**\n * Encodes a value according to the RFC3986 specification.\n * @param {String} val The string to encode.\n */\nChromeExOAuth.toRfc3986 = function(val){\n   return encodeURIComponent(val)\n       .replace(/\\!/g, \"%21\")\n       .replace(/\\*/g, \"%2A\")\n       .replace(/'/g, \"%27\")\n       .replace(/\\(/g, \"%28\")\n       .replace(/\\)/g, \"%29\");\n};\n\n/**\n * Decodes a string that has been encoded according to RFC3986.\n * @param {String} val The string to decode.\n */\nChromeExOAuth.fromRfc3986 = function(val){\n  var tmp = val\n      .replace(/%21/g, \"!\")\n      .replace(/%2A/g, \"*\")\n      .replace(/%27/g, \"'\")\n      .replace(/%28/g, \"(\")\n      .replace(/%29/g, \")\");\n   return decodeURIComponent(tmp);\n};\n\n/**\n * Adds a key/value parameter to the supplied URL.\n * @param {String} url An URL which may or may not contain querystring values.\n * @param {String} key A key\n * @param {String} value A value\n * @return {String} The URL with URL-encoded versions of the key and value\n *     appended, prefixing them with \"&\" or \"?\" as needed.\n */\nChromeExOAuth.addURLParam = function(url, key, value) {\n  var sep = (url.indexOf('?') >= 0) ? \"&\" : \"?\";\n  return url + sep +\n         ChromeExOAuth.toRfc3986(key) + \"=\" + ChromeExOAuth.toRfc3986(value);\n};\n\n/**\n * Stores an OAuth token for the configured scope.\n * @param {String} token The token to store.\n */\nChromeExOAuth.prototype.setToken = function(token) {\n  localStorage[this.key_token + encodeURI(this.oauth_scope)] = token;\n};\n\n/**\n * Retrieves any stored token for the configured scope.\n * @return {String} The stored token.\n */\nChromeExOAuth.prototype.getToken = function() {\n  return localStorage[this.key_token + encodeURI(this.oauth_scope)];\n};\n\n/**\n * Stores an OAuth token secret for the configured scope.\n * @param {String} secret The secret to store.\n */\nChromeExOAuth.prototype.setTokenSecret = function(secret) {\n  localStorage[this.key_token_secret + encodeURI(this.oauth_scope)] = secret;\n};\n\n/**\n * Retrieves any stored secret for the configured scope.\n * @return {String} The stored secret.\n */\nChromeExOAuth.prototype.getTokenSecret = function() {\n  return localStorage[this.key_token_secret + encodeURI(this.oauth_scope)];\n};\n\n/**\n * Starts an OAuth authorization flow for the current page.  If a token exists,\n * no redirect is needed and the supplied callback is called immediately.\n * If this method detects that a redirect has finished, it grabs the\n * appropriate OAuth parameters from the URL and attempts to retrieve an\n * access token.  If no token exists and no redirect has happened, then\n * an access token is requested and the page is ultimately redirected.\n * @param {Function} callback The function to call once the flow has finished.\n *     This callback will be passed the following arguments:\n *         token {String} The OAuth access token.\n *         secret {String} The OAuth access token secret.\n */\nChromeExOAuth.prototype.initOAuthFlow = function(callback) {\n  if (!this.hasToken()) {\n    var params = ChromeExOAuth.getQueryStringParams();\n    if (params['chromeexoauthcallback'] == 'true') {\n      var oauth_token = params['oauth_token'];\n      var oauth_verifier = params['oauth_verifier']\n      this.getAccessToken(oauth_token, oauth_verifier, callback);\n    } else {\n      var request_params = {\n        'url_callback_param' : 'chromeexoauthcallback'\n      }\n      this.getRequestToken(function(url) {\n        window.location.href = url;\n      }, request_params);\n    }\n  } else {\n    callback(this.getToken(), this.getTokenSecret());\n  }\n};\n\n/**\n * Requests an OAuth request token.\n * @param {Function} callback Function to call once the authorize URL is\n *     calculated.  This callback will be passed the following arguments:\n *         url {String} The URL the user must be redirected to in order to\n *             approve the token.\n * @param {Object} opt_args Optional arguments.  The following parameters\n *     are accepted:\n *         \"url_callback\" {String} The URL the OAuth provider will redirect to.\n *         \"url_callback_param\" {String} A parameter to include in the callback\n *             URL in order to indicate to this library that a redirect has\n *             taken place.\n */\nChromeExOAuth.prototype.getRequestToken = function(callback, opt_args) {\n  if (typeof callback !== \"function\") {\n    throw new Error(\"Specified callback must be a function.\");\n  }\n  var url = opt_args && opt_args['url_callback'] ||\n            window && window.top && window.top.location &&\n            window.top.location.href;\n\n  var url_param = opt_args && opt_args['url_callback_param'] ||\n                  \"chromeexoauthcallback\";\n  var url_callback = ChromeExOAuth.addURLParam(url, url_param, \"true\");\n\n  var result = OAuthSimple().sign({\n    path : this.url_request_token,\n    parameters: {\n      \"xoauth_displayname\" : this.app_name,\n      \"scope\" : this.oauth_scope,\n      \"oauth_callback\" : url_callback\n    },\n    signatures: {\n      consumer_key : this.consumer_key,\n      shared_secret : this.consumer_secret\n    }\n  });\n  var onToken = ChromeExOAuth.bind(this.onRequestToken, this, callback);\n  ChromeExOAuth.sendRequest(\"GET\", result.signed_url, null, null, onToken);\n};\n\n/**\n * Called when a request token has been returned.  Stores the request token\n * secret for later use and sends the authorization url to the supplied\n * callback (for redirecting the user).\n * @param {Function} callback Function to call once the authorize URL is\n *     calculated.  This callback will be passed the following arguments:\n *         url {String} The URL the user must be redirected to in order to\n *             approve the token.\n * @param {XMLHttpRequest} xhr The XMLHttpRequest object used to fetch the\n *     request token.\n */\nChromeExOAuth.prototype.onRequestToken = function(callback, xhr) {\n  if (xhr.readyState == 4) {\n    if (xhr.status == 200) {\n      var params = ChromeExOAuth.formDecode(xhr.responseText);\n      var token = params['oauth_token'];\n      this.setTokenSecret(params['oauth_token_secret']);\n      var url = ChromeExOAuth.addURLParam(this.url_auth_token,\n                                          \"oauth_token\", token);\n      for (var key in this.auth_params) {\n        if (this.auth_params.hasOwnProperty(key)) {\n          url = ChromeExOAuth.addURLParam(url, key, this.auth_params[key]);\n        }\n      }\n      callback(url);\n    } else {\n      throw new Error(\"Fetching request token failed. Status \" + xhr.status);\n    }\n  }\n};\n\n/**\n * Requests an OAuth access token.\n * @param {String} oauth_token The OAuth request token.\n * @param {String} oauth_verifier The OAuth token verifier.\n * @param {Function} callback The function to call once the token is obtained.\n *     This callback will be passed the following arguments:\n *         token {String} The OAuth access token.\n *         secret {String} The OAuth access token secret.\n */\nChromeExOAuth.prototype.getAccessToken = function(oauth_token, oauth_verifier,\n                                                  callback) {\n  if (typeof callback !== \"function\") {\n    throw new Error(\"Specified callback must be a function.\");\n  }\n  var bg = chrome.extension.getBackgroundPage();\n  if (bg.chromeExOAuthRequestingAccess == false) {\n    bg.chromeExOAuthRequestingAccess = true;\n\n    var result = OAuthSimple().sign({\n      path : this.url_access_token,\n      parameters: {\n        \"oauth_token\" : oauth_token,\n        \"oauth_verifier\" : oauth_verifier\n      },\n      signatures: {\n        consumer_key : this.consumer_key,\n        shared_secret : this.consumer_secret,\n        oauth_secret : this.getTokenSecret(this.oauth_scope)\n      }\n    });\n\n    var onToken = ChromeExOAuth.bind(this.onAccessToken, this, callback);\n    ChromeExOAuth.sendRequest(\"GET\", result.signed_url, null, null, onToken);\n  }\n};\n\n/**\n * Called when an access token has been returned.  Stores the access token and\n * access token secret for later use and sends them to the supplied callback.\n * @param {Function} callback The function to call once the token is obtained.\n *     This callback will be passed the following arguments:\n *         token {String} The OAuth access token.\n *         secret {String} The OAuth access token secret.\n * @param {XMLHttpRequest} xhr The XMLHttpRequest object used to fetch the\n *     access token.\n */\nChromeExOAuth.prototype.onAccessToken = function(callback, xhr) {\n  if (xhr.readyState == 4) {\n    var bg = chrome.extension.getBackgroundPage();\n    if (xhr.status == 200) {\n      var params = ChromeExOAuth.formDecode(xhr.responseText);\n      var token = params[\"oauth_token\"];\n      var secret = params[\"oauth_token_secret\"];\n      this.setToken(token);\n      this.setTokenSecret(secret);\n      bg.chromeExOAuthRequestingAccess = false;\n      callback(token, secret);\n    } else {\n      bg.chromeExOAuthRequestingAccess = false;\n      throw new Error(\"Fetching access token failed with status \" + xhr.status);\n    }\n  }\n};"
  },
  {
    "path": "_archive/mv2/extensions/oauth_contacts/chrome_ex_oauthsimple.js",
    "content": "/* OAuthSimple\n  * A simpler version of OAuth\n  *\n  * author:     jr conlin\n  * mail:       src@anticipatr.com\n  * copyright:  unitedHeroes.net\n  * version:    1.0\n  * url:        http://unitedHeroes.net/OAuthSimple\n  *\n  * Copyright (c) 2009, unitedHeroes.net\n  * All rights reserved.\n  *\n  * Redistribution and use in source and binary forms, with or without\n  * modification, are permitted provided that the following conditions are met:\n  *     * Redistributions of source code must retain the above copyright\n  *       notice, this list of conditions and the following disclaimer.\n  *     * Redistributions in binary form must reproduce the above copyright\n  *       notice, this list of conditions and the following disclaimer in the\n  *       documentation and/or other materials provided with the distribution.\n  *     * Neither the name of the unitedHeroes.net nor the\n  *       names of its contributors may be used to endorse or promote products\n  *       derived from this software without specific prior written permission.\n  *\n  * THIS SOFTWARE IS PROVIDED BY UNITEDHEROES.NET ''AS IS'' AND ANY\n  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  * DISCLAIMED. IN NO EVENT SHALL UNITEDHEROES.NET BE LIABLE FOR ANY\n  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\nvar OAuthSimple;\n\nif (OAuthSimple === undefined)\n{\n    /* Simple OAuth\n     *\n     * This class only builds the OAuth elements, it does not do the actual\n     * transmission or reception of the tokens. It does not validate elements\n     * of the token. It is for client use only.\n     *\n     * api_key is the API key, also known as the OAuth consumer key\n     * shared_secret is the shared secret (duh).\n     *\n     * Both the api_key and shared_secret are generally provided by the site\n     * offering OAuth services. You need to specify them at object creation\n     * because nobody <explative>ing uses OAuth without that minimal set of\n     * signatures.\n     *\n     * If you want to use the higher order security that comes from the\n     * OAuth token (sorry, I don't provide the functions to fetch that because\n     * sites aren't horribly consistent about how they offer that), you need to\n     * pass those in either with .setTokensAndSecrets() or as an argument to the\n     * .sign() or .getHeaderString() functions.\n     *\n     * Example:\n       <code>\n        var oauthObject = OAuthSimple().sign({path:'http://example.com/rest/',\n                                              parameters: 'foo=bar&gorp=banana',\n                                              signatures:{\n                                                api_key:'12345abcd',\n                                                shared_secret:'xyz-5309'\n                                             }});\n        document.getElementById('someLink').href=oauthObject.signed_url;\n       </code>\n     *\n     * that will sign as a \"GET\" using \"SHA1-MAC\" the url. If you need more than\n     * that, read on, McDuff.\n     */\n\n    /** OAuthSimple creator\n     *\n     * Create an instance of OAuthSimple\n     *\n     * @param api_key {string}       The API Key (sometimes referred to as the consumer key) This value is usually supplied by the site you wish to use.\n     * @param shared_secret (string) The shared secret. This value is also usually provided by the site you wish to use.\n     */\n    OAuthSimple = function (consumer_key,shared_secret)\n    {\n/*        if (api_key == undefined)\n            throw(\"Missing argument: api_key (oauth_consumer_key) for OAuthSimple. This is usually provided by the hosting site.\");\n        if (shared_secret == undefined)\n            throw(\"Missing argument: shared_secret (shared secret) for OAuthSimple. This is usually provided by the hosting site.\");\n*/      this._secrets={};\n        this._parameters={};\n\n        // General configuration options.\n        if (consumer_key !== undefined) {\n            this._secrets['consumer_key'] = consumer_key;\n            }\n        if (shared_secret !== undefined) {\n            this._secrets['shared_secret'] = shared_secret;\n            }\n        this._default_signature_method= \"HMAC-SHA1\";\n        this._action = \"GET\";\n        this._nonce_chars = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\n\n        this.reset = function() {\n            this._parameters={};\n            this._path=undefined;\n            return this;\n        };\n\n        /** set the parameters either from a hash or a string\n         *\n         * @param {string,object} List of parameters for the call, this can either be a URI string (e.g. \"foo=bar&gorp=banana\" or an object/hash)\n         */\n        this.setParameters = function (parameters) {\n            if (parameters === undefined) {\n                parameters = {};\n                }\n            if (typeof(parameters) == 'string') {\n                parameters=this._parseParameterString(parameters);\n                }\n            this._parameters = parameters;\n            if (this._parameters['oauth_nonce'] === undefined) {\n                this._getNonce();\n                }\n            if (this._parameters['oauth_timestamp'] === undefined) {\n                this._getTimestamp();\n                }\n            if (this._parameters['oauth_method'] === undefined) {\n                this.setSignatureMethod();\n                }\n            if (this._parameters['oauth_consumer_key'] === undefined) {\n                this._getApiKey();\n                }\n            if(this._parameters['oauth_token'] === undefined) {\n                this._getAccessToken();\n                }\n\n            return this;\n        };\n\n        /** convienence method for setParameters\n         *\n         * @param parameters {string,object} See .setParameters\n         */\n        this.setQueryString = function (parameters) {\n            return this.setParameters(parameters);\n        };\n\n        /** Set the target URL (does not include the parameters)\n         *\n         * @param path {string} the fully qualified URI (excluding query arguments) (e.g \"http://example.org/foo\")\n         */\n        this.setURL = function (path) {\n            if (path == '') {\n                throw ('No path specified for OAuthSimple.setURL');\n                }\n            this._path = path;\n            return this;\n        };\n\n        /** convienence method for setURL\n         *\n         * @param path {string} see .setURL\n         */\n        this.setPath = function(path){\n            return this.setURL(path);\n        };\n\n        /** set the \"action\" for the url, (e.g. GET,POST, DELETE, etc.)\n         *\n         * @param action {string} HTTP Action word.\n         */\n        this.setAction = function(action) {\n            if (action === undefined) {\n                action=\"GET\";\n                }\n            action = action.toUpperCase();\n            if (action.match('[^A-Z]')) {\n                throw ('Invalid action specified for OAuthSimple.setAction');\n                }\n            this._action = action;\n            return this;\n        };\n\n        /** set the signatures (as well as validate the ones you have)\n         *\n         * @param signatures {object} object/hash of the token/signature pairs {api_key:, shared_secret:, oauth_token: oauth_secret:}\n         */\n        this.setTokensAndSecrets = function(signatures) {\n            if (signatures)\n            {\n                for (var i in signatures) {\n                    this._secrets[i] = signatures[i];\n                    }\n            }\n            // Aliases\n            if (this._secrets['api_key']) {\n                this._secrets.consumer_key = this._secrets.api_key;\n                }\n            if (this._secrets['access_token']) {\n                this._secrets.oauth_token = this._secrets.access_token;\n                }\n            if (this._secrets['access_secret']) {\n                this._secrets.oauth_secret = this._secrets.access_secret;\n                }\n            // Gauntlet\n            if (this._secrets.consumer_key === undefined) {\n                throw('Missing required consumer_key in OAuthSimple.setTokensAndSecrets');\n                }\n            if (this._secrets.shared_secret === undefined) {\n                throw('Missing required shared_secret in OAuthSimple.setTokensAndSecrets');\n                }\n            if ((this._secrets.oauth_token !== undefined) && (this._secrets.oauth_secret === undefined)) {\n                throw('Missing oauth_secret for supplied oauth_token in OAuthSimple.setTokensAndSecrets');\n                }\n            return this;\n        };\n\n        /** set the signature method (currently only Plaintext or SHA-MAC1)\n         *\n         * @param method {string} Method of signing the transaction (only PLAINTEXT and SHA-MAC1 allowed for now)\n         */\n        this.setSignatureMethod = function(method) {\n            if (method === undefined) {\n                method = this._default_signature_method;\n                }\n            //TODO: accept things other than PlainText or SHA-MAC1\n            if (method.toUpperCase().match(/(PLAINTEXT|HMAC-SHA1)/) === undefined) {\n                throw ('Unknown signing method specified for OAuthSimple.setSignatureMethod');\n                }\n            this._parameters['oauth_signature_method']= method.toUpperCase();\n            return this;\n        };\n\n        /** sign the request\n         *\n         * note: all arguments are optional, provided you've set them using the\n         * other helper functions.\n         *\n         * @param args {object} hash of arguments for the call\n         *                   {action:, path:, parameters:, method:, signatures:}\n         *                   all arguments are optional.\n         */\n        this.sign = function (args) {\n            if (args === undefined) {\n                args = {};\n                }\n            // Set any given parameters\n            if(args['action'] !== undefined) {\n                this.setAction(args['action']);\n                }\n            if (args['path'] !== undefined) {\n                this.setPath(args['path']);\n                }\n            if (args['method'] !== undefined) {\n                this.setSignatureMethod(args['method']);\n                }\n            this.setTokensAndSecrets(args['signatures']);\n            if (args['parameters'] !== undefined){\n            this.setParameters(args['parameters']);\n            }\n            // check the parameters\n            var normParams = this._normalizedParameters();\n            this._parameters['oauth_signature']=this._generateSignature(normParams);\n            return {\n                parameters: this._parameters,\n                signature: this._oauthEscape(this._parameters['oauth_signature']),\n                signed_url: this._path + '?' + this._normalizedParameters(),\n                header: this.getHeaderString()\n            };\n        };\n\n        /** Return a formatted \"header\" string\n         *\n         * NOTE: This doesn't set the \"Authorization: \" prefix, which is required.\n         * I don't set it because various set header functions prefer different\n         * ways to do that.\n         *\n         * @param args {object} see .sign\n         */\n        this.getHeaderString = function(args) {\n            if (this._parameters['oauth_signature'] === undefined) {\n                this.sign(args);\n                }\n\n            var result = 'OAuth ';\n            for (var pName in this._parameters)\n            {\n                if (!pName.match(/^oauth/)) {\n                    continue;\n                    }\n                if ((this._parameters[pName]) instanceof Array)\n                {\n                    var pLength = this._parameters[pName].length;\n                    for (var j=0;j<pLength;j++)\n                    {\n                        result += pName +'=\"'+this._oauthEscape(this._parameters[pName][j])+'\" ';\n                    }\n                }\n                else\n                {\n                    result += pName + '=\"'+this._oauthEscape(this._parameters[pName])+'\" ';\n                }\n            }\n            return result;\n        };\n\n        // Start Private Methods.\n\n        /** convert the parameter string into a hash of objects.\n         *\n         */\n        this._parseParameterString = function(paramString){\n            var elements = paramString.split('&');\n            var result={};\n            for(var element=elements.shift();element;element=elements.shift())\n            {\n                var keyToken=element.split('=');\n                var value='';\n                if (keyToken[1]) {\n                    value=decodeURIComponent(keyToken[1]);\n                    }\n                if(result[keyToken[0]]){\n                    if (!(result[keyToken[0]] instanceof Array))\n                    {\n                        result[keyToken[0]] = Array(result[keyToken[0]],value);\n                    }\n                    else\n                    {\n                        result[keyToken[0]].push(value);\n                    }\n                }\n                else\n                {\n                    result[keyToken[0]]=value;\n                }\n            }\n            return result;\n        };\n\n        this._oauthEscape = function(string) {\n            if (string === undefined) {\n                return \"\";\n                }\n            if (string instanceof Array)\n            {\n                throw('Array passed to _oauthEscape');\n            }\n            return encodeURIComponent(string).replace(/\\!/g, \"%21\").\n            replace(/\\*/g, \"%2A\").\n            replace(/'/g, \"%27\").\n            replace(/\\(/g, \"%28\").\n            replace(/\\)/g, \"%29\");\n        };\n\n        this._getNonce = function (length) {\n            if (length === undefined) {\n                length=5;\n                }\n            var result = \"\";\n            var cLength = this._nonce_chars.length;\n            for (var i = 0; i < length;i++) {\n                var rnum = Math.floor(Math.random() *cLength);\n                result += this._nonce_chars.substring(rnum,rnum+1);\n            }\n            this._parameters['oauth_nonce']=result;\n            return result;\n        };\n\n        this._getApiKey = function() {\n            if (this._secrets.consumer_key === undefined) {\n                throw('No consumer_key set for OAuthSimple.');\n                }\n            this._parameters['oauth_consumer_key']=this._secrets.consumer_key;\n            return this._parameters.oauth_consumer_key;\n        };\n\n        this._getAccessToken = function() {\n            if (this._secrets['oauth_secret'] === undefined) {\n                return '';\n                }\n            if (this._secrets['oauth_token'] === undefined) {\n                throw('No oauth_token (access_token) set for OAuthSimple.');\n                }\n            this._parameters['oauth_token'] = this._secrets.oauth_token;\n            return this._parameters.oauth_token;\n        };\n\n        this._getTimestamp = function() {\n            var d = new Date();\n            var ts = Math.floor(d.getTime()/1000);\n            this._parameters['oauth_timestamp'] = ts;\n            return ts;\n        };\n\n        this.b64_hmac_sha1 = function(k,d,_p,_z){\n        // heavily optimized and compressed version of http://pajhome.org.uk/crypt/md5/sha1.js\n        // _p = b64pad, _z = character size; not used here but I left them available just in case\n        if(!_p){_p='=';}if(!_z){_z=8;}function _f(t,b,c,d){if(t<20){return(b&c)|((~b)&d);}if(t<40){return b^c^d;}if(t<60){return(b&c)|(b&d)|(c&d);}return b^c^d;}function _k(t){return(t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514;}function _s(x,y){var l=(x&0xFFFF)+(y&0xFFFF),m=(x>>16)+(y>>16)+(l>>16);return(m<<16)|(l&0xFFFF);}function _r(n,c){return(n<<c)|(n>>>(32-c));}function _c(x,l){x[l>>5]|=0x80<<(24-l%32);x[((l+64>>9)<<4)+15]=l;var w=[80],a=1732584193,b=-271733879,c=-1732584194,d=271733878,e=-1009589776;for(var i=0;i<x.length;i+=16){var o=a,p=b,q=c,r=d,s=e;for(var j=0;j<80;j++){if(j<16){w[j]=x[i+j];}else{w[j]=_r(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);}var t=_s(_s(_r(a,5),_f(j,b,c,d)),_s(_s(e,w[j]),_k(j)));e=d;d=c;c=_r(b,30);b=a;a=t;}a=_s(a,o);b=_s(b,p);c=_s(c,q);d=_s(d,r);e=_s(e,s);}return[a,b,c,d,e];}function _b(s){var b=[],m=(1<<_z)-1;for(var i=0;i<s.length*_z;i+=_z){b[i>>5]|=(s.charCodeAt(i/8)&m)<<(32-_z-i%32);}return b;}function _h(k,d){var b=_b(k);if(b.length>16){b=_c(b,k.length*_z);}var p=[16],o=[16];for(var i=0;i<16;i++){p[i]=b[i]^0x36363636;o[i]=b[i]^0x5C5C5C5C;}var h=_c(p.concat(_b(d)),512+d.length*_z);return _c(o.concat(h),512+160);}function _n(b){var t=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\",s='';for(var i=0;i<b.length*4;i+=3){var r=(((b[i>>2]>>8*(3-i%4))&0xFF)<<16)|(((b[i+1>>2]>>8*(3-(i+1)%4))&0xFF)<<8)|((b[i+2>>2]>>8*(3-(i+2)%4))&0xFF);for(var j=0;j<4;j++){if(i*8+j*6>b.length*32){s+=_p;}else{s+=t.charAt((r>>6*(3-j))&0x3F);}}}return s;}function _x(k,d){return _n(_h(k,d));}return _x(k,d);\n        }\n\n\n        this._normalizedParameters = function() {\n            var elements = new Array();\n            var paramNames = [];\n            var ra =0;\n            for (var paramName in this._parameters)\n            {\n                if (ra++ > 1000) {\n                    throw('runaway 1');\n                    }\n                paramNames.unshift(paramName);\n            }\n            paramNames = paramNames.sort();\n            pLen = paramNames.length;\n            for (var i=0;i<pLen; i++)\n            {\n                paramName=paramNames[i];\n                //skip secrets.\n                if (paramName.match(/\\w+_secret/)) {\n                    continue;\n                    }\n                if (this._parameters[paramName] instanceof Array)\n                {\n                    var sorted = this._parameters[paramName].sort();\n                    var spLen = sorted.length;\n                    for (var j = 0;j<spLen;j++){\n                        if (ra++ > 1000) {\n                            throw('runaway 1');\n                            }\n                        elements.push(this._oauthEscape(paramName) + '=' +\n                                  this._oauthEscape(sorted[j]));\n                    }\n                    continue;\n                }\n                elements.push(this._oauthEscape(paramName) + '=' +\n                              this._oauthEscape(this._parameters[paramName]));\n            }\n            return elements.join('&');\n        };\n\n        this._generateSignature = function() {\n\n            var secretKey = this._oauthEscape(this._secrets.shared_secret)+'&'+\n                this._oauthEscape(this._secrets.oauth_secret);\n            if (this._parameters['oauth_signature_method'] == 'PLAINTEXT')\n            {\n                return secretKey;\n            }\n            if (this._parameters['oauth_signature_method'] == 'HMAC-SHA1')\n            {\n                var sigString = this._oauthEscape(this._action)+'&'+this._oauthEscape(this._path)+'&'+this._oauthEscape(this._normalizedParameters());\n                return this.b64_hmac_sha1(secretKey,sigString);\n            }\n            return null;\n        };\n\n    return this;\n    };\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/oauth_contacts/contacts.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2009 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n<html>\n  <head>\n    <title>Your Google Contacts List</title>\n    <style type=\"text/css\">\n      body {\n        font: 14px Arial;\n      }\n      p {\n        font-weight: bold;\n      }\n    </style>\n  </head>\n  <body>\n    <h1>Your Google Contacts List</h1>\n    <h2>Listing the first 100 results of a standard query to\n      <a href=\"http://code.google.com/apis/contacts/\">Google's\n      Contacts API</a></h2>\n    <button id=\"clear\">Click here to clear your OAuth token</button>\n    <div id=\"output\">\n    </div>\n    <script src=\"contacts.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/oauth_contacts/contacts.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar contacts = chrome.extension.getBackgroundPage().contacts;\nvar output = document.getElementById('output');\nfor (var i = 0, contact; contact = contacts[i]; i++) {\n  var div = document.createElement('div');\n  var pName = document.createElement('p');\n  var ulEmails = document.createElement('ul');\n\n  pName.innerText = contact['name'];\n  div.appendChild(pName);\n\n  for (var j = 0, email; email = contact['emails'][j]; j++) {\n    var liEmail = document.createElement('li');\n    liEmail.innerText = email;\n    ulEmails.appendChild(liEmail);\n  }\n\n  div.appendChild(ulEmails);\n  output.appendChild(div);\n}\n\nfunction logout() {\n  chrome.extension.getBackgroundPage().logout();\n  window.close();\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  document.querySelector('#clear').addEventListener('click', logout);\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/oauth_contacts/manifest.json",
    "content": "{\n  \"name\": \"Sample - OAuth Contacts\",\n  \"version\": \"1.0.6\",\n  \"icons\": { \"48\": \"img/icon-48.png\",\n            \"128\": \"img/icon-128.png\" },\n  \"description\": \"Uses OAuth to connect to Google's contacts service and display a list of your contacts.\",\n  \"background\": {\n    \"scripts\": [\n      \"chrome_ex_oauthsimple.js\",\n      \"chrome_ex_oauth.js\",\n      \"background.js\"\n    ]\n  },\n  \"browser_action\": {\n    \"default_title\": \"\",\n    \"default_icon\": \"img/icon-19-off.png\"\n  },\n  \"permissions\": [\n    \"tabs\",\n    \"http://www.google.com/m8/feeds/*\",\n    \"https://www.google.com/accounts/OAuthGetRequestToken\",\n    \"https://www.google.com/accounts/OAuthAuthorizeToken\",\n    \"https://www.google.com/accounts/OAuthGetAccessToken\"\n  ],\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/oauth_contacts/onload.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nwindow.onload = function() {\n  ChromeExOAuth.initCallbackPage();\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/optional_permissions/logic.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nconst kPermissionObj = {\n  permissions: ['topSites']\n};\n\nconst sites_div = document.getElementById('display_top');\n\nconst todo = document.getElementById('display_todo');\n\nconst form = document.querySelector('form');\n\nconst footer = document.querySelector('footer');\n\nfunction createTop(){chrome.topSites.get(function(topSites) {\n  topSites.forEach(function(site) {\n    let div = document.createElement('div');\n    div.className = 'colorFun';\n    let tooltip = document.createElement('a');\n    tooltip.href = site.url;\n    tooltip.innerText = site.title;\n    tooltip.className = 'tooltip';\n    let url = document.createElement('a');\n    url.href = site.url;\n    let imageContainer = document.createElement('div');\n    imageContainer.className = 'imageContainer';\n    let image = document.createElement('img');\n    image.title = site.title;\n    image.src = 'chrome://favicon/' + site.url;\n    imageContainer.appendChild(image);\n    url.appendChild(imageContainer);\n    div.appendChild(url);\n    div.appendChild(tooltip);\n    sites_div.appendChild(div);\n  })\n})};\n\nchrome.permissions.contains({permissions: ['topSites']}, function(result) {\n  if (result) {\n    // The extension has the permissions.\n    createTop();\n  } else {\n    // The extension doesn't have the permissions.\n    let button = document.createElement('button');\n    button.innerText = 'Allow Extension to Access Top Sites';\n    button.addEventListener('click', function() {\n      chrome.permissions.request(kPermissionObj, function(granted) {\n        if (granted) {\n          console.log('granted');\n          sites_div.innerText = '';\n          createTop();\n        } else {\n          console.log('not granted');\n        }\n      });\n    });\n    footer.appendChild(button);\n  }\n});\n\nform.addEventListener('submit', function() {\n  let todo_value = document.getElementById('todo_value');\n  chrome.storage.sync.set({todo: todo_value.value});\n});\n\nfunction setToDo() {\n  chrome.storage.sync.get(['todo'], function(value) {\n    if (!value.todo) {\n      todo.innerText = '';\n    } else {\n      todo.innerText = value.todo;\n    }\n  });\n};\n\nsetToDo();\n"
  },
  {
    "path": "_archive/mv2/extensions/optional_permissions/manifest.json",
    "content": "{\n  \"name\": \"Optional Permissions New Tab\",\n  \"version\": \"1.2.5.0\",\n  \"description\": \"Demonstrates optional permissions in extensions\",\n  \"permissions\": [\"storage\", \"chrome://favicon/*\"],\n  \"optional_permissions\": [\n    \"topSites\"\n  ],\n  \"icons\": {\n    \"16\": \"images/optional_permissions16.png\",\n    \"32\": \"images/optional_permissions32.png\",\n    \"48\": \"images/optional_permissions48.png\",\n    \"128\": \"images/optional_permissions128.png\"\n  },\n  \"chrome_url_overrides\": {\n    \"newtab\": \"newtab.html\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/optional_permissions/newtab.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>New Tab - Optional Permissions</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n  </head>\n  <body>\n    <div id=\"todo_div\" class=\"center colorFun\">\n      <h1 id=\"display_todo\"></h1>\n    </div>\n    <div id=\"display_top\"></div>\n    <form class=\"center\">\n      <input id=\"todo_value\" placeholder=\"My focus today is...\" />\n      <input type=\"submit\" value=\"Submit\">\n    </form>\n    <footer></footer>\n    <script src=\"logic.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/optional_permissions/style.css",
    "content": "/* Copyright 2018 The Chromium Authors. All rights reserved.\n Use of this source code is governed by a BSD-style license that can be\n found in the LICENSE file.*/\n\nh1 {\n  font-family: \"Courier New\", Courier, monospaces;\n}\n\n#display_top {\n  margin: auto;\n  margin-bottom: 40px;\n  width: 600px;\n}\n\n#todo_div {\n  margin-top: 0px;\n  height: 100px;\n  width: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n\n  animation-name: color-extravaganza;\n  animation-duration: 6s;\n  animation-iteration-count: infinite;\n  animation-direction: alternate;\n}\n\n.center {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n@keyframes color-extravaganza {\n  0%   {background-color: #4285F4;}\n  10%  {background-color: #4285F4;}\n  25%  {background-color: #EA4335;}\n  50%  {background-color: #FBBC04;}\n  100% {background-color: #34A853;}\n}\n\n.colorFun {\n  position: relative;\n  height: 70px;\n  width: 100px;\n  padding: 10px;\n  display: inline-block;\n  margin-top: 40px;\n}\n\n.colorFun .tooltip {\n  width: 100px;\n  text-align: center;\n  padding: 5px 0;\n  position: absolute;\n  z-index: 1;\n  bottom: 0%;\n  left: 50%;\n  transform: translateX(-50%);\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.imageContainer {\n  background-color: #cdcdcd;\n  width: 50px;\n  height: 50px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  border-radius: 50%;\n  justify-self: center;\n}\n\n.imageContainer img {\n  width: 14px;\n  height: 14px;\n}\n\nfooter {\n  position: absolute;\n  bottom: 20px;\n  left: 20px;\n}\n\ninput#todo_value {\n  width: 300px;\n  height: 40px;\n  font-size: 18px;\n  padding: 12px 20px;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n  box-sizing: border-box;\n  margin-right: 4px;\n}\n\ninput#todo_value ~ input[type=\"submit\"] {\n  background-color: #4285F4;\n  color: white;\n  padding: 12px 20px;\n  border: none;\n  border-radius: 4px;\n  cursor: pointer;\n}\n\ninput#todo_value ~ input[type=\"submit\"]:hover {\n  background-color: #45a049;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/_locales/en/messages.json",
    "content": "{\n  \"extName\": {\n    \"message\": \"Per-plugin content settings\"\n  },\n  \"extDescription\": {\n    \"message\": \"Customize your content setting for different plugins.\"\n  },\n  \"patternColumnHeader\": {\n    \"message\": \"Hostname Pattern\"\n  },\n  \"settingColumnHeader\": {\n    \"message\": \"Behavior\"\n  },\n  \"allowRule\": {\n    \"message\": \"Allow\"\n  },\n  \"blockRule\": {\n    \"message\": \"Block\"\n  },\n  \"addNewPattern\": {\n    \"message\": \"Add a new hostname pattern\"\n  }\n}"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/css/plugin_list.css",
    "content": "/* Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file. */\n\nbody {\n  font-family: Helvetica, sans-serif;\n  background-color: white;\n  color: black;\n  margin: 10px;\n}\n\n.plugin-list {\n  border: 1px solid #d9d9d9;\n  border-radius: 2px;\n  width: 517px;\n}\n\n.plugin-list > li {\n  padding: 3px;\n}\n\n.plugin-name {\n  display: inline-block;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  font-weight: bold;\n}\n\n.num-rules:before {\n  content: ' ';\n}\n\n.plugin-show-details .num-rules {\n  display: none;\n}\n\n.plugin-description {\n  display: inline-block;\n  padding-inline-start: 7px;\n  width: auto;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  font-size: 95%;\n}\n\n.plugin-details {\n  background: #f5f8f8;\n  border: 1px solid #b2b2b2;\n  border-radius: 5px;\n  padding: 5px;\n  height: 0;\n  width: 500px;\n  opacity: 0;\n  transition: height .5s ease-in-out;\n}\n\n.plugin-measure-details .plugin-details {\n  height: auto;\n  transition: none;\n  visibility: hidden;\n}\n\nli.plugin-show-details {\n  height: auto;\n}\n\n.plugin-show-details .plugin-description {\n  height: auto;\n}\n\n.plugin-show-details .plugin-details {\n  opacity: 1;\n  height: auto;\n}\n\n.column-headers {\n  display: -webkit-box;\n  margin-inline-start: 17px;\n}\n\n.column-headers > div {\n  font-weight: bold;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/css/rule_list.css",
    "content": "/* Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file. */\n\n.rule-pattern {\n  -webkit-box-flex: 1;\n  margin-inline-end: 10px;\n  margin-inline-start: 14px;\n}\n\n.rule-behavior {\n  display: inline-block;\n  width: 120px;\n}\n\nselect.rule-behavior {\n  vertical-align: middle;\n}\n\n.rule-list {\n  border: 1px solid #d9d9d9;\n  border-radius: 2px;\n}\n\n.pattern-column-header {\n  -webkit-box-flex: 1;\n}\n\n.setting-column-header {\n  width: 145px;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/css/button.css",
    "content": "button,\ninput[type='button'],\ninput[type='submit'] {\n  -webkit-border-radius: 2px;\n  -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);\n  -webkit-user-select: none;\n  background: -webkit-linear-gradient(#fafafa, #f4f4f4 40%, #e5e5e5);\n  border: 1px solid #aaa;\n  color: #444;\n  font-size: inherit;\n  margin-bottom: 0px;\n  min-width: 4em;\n  padding: 3px 12px 3px 12px;\n}\n\nbutton:hover,\ninput[type='button']:hover,\ninput[type='submit']:hover {\n  -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.2);\n  background: #ebebeb -webkit-linear-gradient(#fefefe, #f8f8f8 40%, #e9e9e9);\n  border-color: #999;\n  color: #222;\n}\n\nbutton:active,\ninput[type='button']:active,\ninput[type='submit']:active {\n  -webkit-box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.2);\n  background: #ebebeb -webkit-linear-gradient(#f4f4f4, #efefef 40%, #dcdcdc);\n  color: #333;\n}\n\nbutton[disabled],\ninput[type='button'][disabled],\ninput[type='submit'][disabled],\nbutton[disabled]:hover,\ninput[type='button'][disabled]:hover,\ninput[type='submit'][disabled]:hover {\n  -webkit-box-shadow: none;\n  background: -webkit-linear-gradient(#fafafa, #f4f4f4 40%, #e5e5e5);\n  border-color: #aaa;\n  color: #888;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/css/chrome_shared.css",
    "content": "/* Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file. */\n\n/* Styles common to WebUI pages that share the options pages style */\nbody {\n  cursor: default;\n  font-size: 13px;\n}\n\na:link {\n  color: rgb(63, 110, 194);\n}\n\na:active {\n  color: rgb(37, 64, 113);\n}\n\n#navbar-content-title {\n  -webkit-user-select: none;\n  color: #53637d;\n  cursor: pointer;\n  font-size: 200%;\n  font-weight: normal;\n  margin: 0;\n  padding-bottom: 14px;\n  padding-inline-end: 24px;\n  padding-top: 13px;\n  text-align: end;\n  text-shadow: white 0 1px 2px;\n}\n\n#main-content {\n  display: -webkit-box;\n  position: absolute;\n  left: 0;\n  right: 0;\n  top: 0;\n  bottom: 0;\n}\n\n#navbar {\n  margin: 0;\n}\n\n#navbar-container {\n  background: -webkit-linear-gradient(rgba(234, 238, 243, 0.2), #eaeef3),\n              -webkit-linear-gradient(left, #eaeef3, #eaeef3 97%, #d3d7db);\n  border-inline-end: 1px solid #c6c9ce;\n  position: fixed;\n  bottom: 0;\n  /* We set both left and right for the sake of RTL. */\n  left: 0;\n  right: 0;\n  top: 0;\n  width: 216px;\n  z-index: 2;\n}\n\nhtml[dir='rtl'] #navbar-container {\n  background: -webkit-linear-gradient(rgba(234, 238, 243, 0), #EAEEF3),\n              -webkit-linear-gradient(right, #EAEEF3, #EAEEF3 97%, #D3D7DB);\n}\n\nhtml.hide-menu #navbar-container {\n  display: none;\n}\n\n#navbar-container > ul {\n  -webkit-user-select: none;\n  list-style-type: none;\n  margin: 0;\n  padding: 0;\n}\n\n.navbar-item {\n  border-bottom: 1px solid transparent;\n  border-top: 1px solid transparent;\n  color: #426dc9;\n  cursor: pointer;\n  display: block;\n  font-size: 105%;\n  outline: none;\n  padding: 7px 0;\n  padding-inline-end: 24px;\n  text-align: end;\n  text-shadow: white 0 1px 1px;\n}\n\n.navbar-item:focus {\n  border-bottom: 1px solid #8faad9;\n  border-top: 1px solid #8faad9;\n}\n\n.navbar-item-selected {\n  -webkit-box-shadow: 0px 1px 0px #f7f7f7;\n  background: -webkit-linear-gradient(left, #bbcee9, #bbcee9 97%, #aabedc);\n  border-bottom: 1px solid #8faad9;\n  border-top: 1px solid #8faad9;\n  color: black;\n  text-shadow: #bbcee9 0 1px 1px;\n}\n\n#mainview {\n  -webkit-box-align: stretch;\n  margin: 0;\n  position: absolute;\n  left: 0;\n  padding-inline-start: 216px;\n  right: 0;\n  top: 0;\n  bottom: 0;\n  z-index: 1;\n}\n\nhtml.hide-menu #mainview {\n  padding-inline-start: 0;\n}\n\n#mainview-content {\n  min-height: 100%;\n  position: relative;\n}\n\n#page-container {\n  box-sizing: border-box;\n  max-width: 888px;\n  min-width: 600px;\n  padding: 0 24px;\n}\n\ndiv.checkbox,\ndiv.radio {\n  margin: 5px 0;\n  color: #444;\n}\n\ndiv.disabled {\n  color: #888;\n}\n\n/* TEXT */\ninput[type='password'],\ninput[type='text'],\ninput[type='url'],\ninput:not([type]) {\n  -webkit-border-radius: 2px;\n  border: 1px solid #aaa;\n  font-size: inherit;\n  padding: 3px;\n}\n\n/* CHECKBOX, RADIO */\ninput[type=checkbox],\ninput[type=radio] {\n  margin-left: 0;\n  margin-right: 0;\n  position: relative;\n  top: 1px;\n}\n\n/* Checkbox and radio buttons have different sizes on different platforms. The\n * following rules have platform specific tweaks.\n * TODO(arv): Test the vertical position on Linux and CrOS as well.\n */\n\nlabel > input[type=checkbox],\nlabel > input[type=radio] {\n  opacity: 0.7;\n  margin-top: 1px;\n}\n\nhtml[os=mac] label > input[type=checkbox],\nhtml[os=mac] label > input[type=radio] {\n  margin-top: 2px;\n}\n\nhtml[os=chromeos] label > input[type=checkbox],\nhtml[os=chromeos] label > input[type=radio] {\n  top: 2px;\n}\n\n/* Checkbox and radio hover visuals.\n * Their appearance when checked is set to be the same.\n */\nlabel:hover > input[type=checkbox]:not([disabled]),\nlabel:hover > input[type=radio]:not([disabled]),\nlabel > input:not([disabled]):checked {\n  opacity: 1;\n}\n\nlabel:hover > input[type=checkbox]:not([disabled]) ~ span,\nlabel:hover > input[type=radio]:not([disabled]) ~ span,\nlabel > input:not([disabled]):checked ~ span {\n  color: #222;\n}\n\n/* This will 'disable' the label associated with any input whose next sibling is\n * the span containing the label (usually a checkbox or radio).\n */\nlabel > input[disabled] ~ span {\n  color: #888;\n}\n\n/* Elements that need to be LTR even in an RTL context, but should align\n * right. (Namely, URLs, search engine names, etc.)\n */\nhtml[dir='rtl'] .weakrtl {\n  direction: ltr;\n  text-align: right;\n}\n\n/* Input fields in search engine table need to be weak-rtl. Since those input\n * fields are generated for all cr.ListItem elements (and we only want weakrtl\n * on some), the class needs to be on the enclosing div.\n */\nhtml[dir='rtl'] div.weakrtl input {\n    direction: ltr;\n    text-align: right;\n}\n\nhtml[dir='rtl'] .favicon-cell.weakrtl {\n  padding-inline-end: 22px;\n  padding-inline-start: 0;\n}\n\n/* weakrtl for selection drop downs needs to account for the fact that\n * Webkit does not honor the text-align attribute for the select element.\n * (See Webkit bug #40216)\n */\nhtml[dir='rtl'] select.weakrtl {\n  direction: rtl;\n}\n\nhtml[dir='rtl'] select.weakrtl option {\n  direction: ltr;\n}\n\n/* WebKit does not honor alignment for text specified via placeholder attrib.\n * This CSS is a workaround. Please remove once WebKit bug is fixed.\n * https://bugs.webkit.org/show_bug.cgi?id=63367\n */\nhtml[dir='rtl'] input.weakrtl::-webkit-input-placeholder,\nhtml[dir='rtl'] .weakrtl input::-webkit-input-placeholder {\n  direction: rtl;\n}\n\n.page h1 {\n  -webkit-user-select: none;\n  border-bottom: 1px solid #eeeeee;\n  color: #53637d;\n  font-size: 200%;\n  font-weight: normal;\n  margin: 0;\n  padding-bottom: 4px;\n  padding-inline-end: 24px;\n  padding-top: 13px;\n  text-shadow: white 0 1px 2px;\n}\n\n\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/css/list.css",
    "content": "\nlist,\ngrid {\n  display: block;\n  outline: none;\n  overflow: auto;\n  position: relative; /* Make sure that item offsets are relative to the\n                         list. */\n}\n\nlist > *,\ngrid > * {\n  -webkit-user-select: none;\n  background-color: rgba(255,255,255,0);\n  border: 1px solid rgba(255,255,255,0); /* transparent white */\n  border-radius: 2px;\n  cursor: default;\n  line-height: 20px;\n  margin: -1px 0;\n  overflow: hidden;\n  padding: 0px 3px;\n  position: relative; /* to allow overlap */\n  text-overflow: ellipsis;\n  white-space: pre;\n}\n\nlist > * {\n  display: block;\n}\n\ngrid > * {\n  display: inline-block;\n}\n\nlist > [lead],\ngrid > [lead] {\n  border-color: transparent;\n}\n\nlist:focus > [lead],\ngrid:focus > [lead] {\n  border-color: hsl(214, 91%, 65%);\n  z-index: 2;\n}\n\nlist > [anchor],\ngrid > [anchor] {\n\n}\n\nlist:not([disabled]) > :hover,\ngrid:not([disabled]) > :hover {\n  border-color: hsl(214, 91%, 85%);\n  z-index: 1;\n  background-color: hsl(214, 91%, 97%);\n}\n\nlist > [selected],\ngrid > [selected] {\n  border-color: hsl(0, 0%, 85%);\n  background-color: hsl(0,0%,90%);\n  z-index: 2;\n  background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.8),\n                                            rgba(255, 255, 255, 0));\n}\n\nlist:focus > [selected],\ngrid:focus > [selected] {\n  background-color: hsl(214,91%,89%);\n  border-color: hsl(214, 91%, 65%);\n}\n\nlist:focus > [lead][selected],\nlist > [selected]:hover,\ngrid:focus > [lead][selected],\ngrid > [selected]:hover {\n  background-color: hsl(214, 91%, 87%);\n  border-color: hsl(214, 91%, 65%);\n}\n\nlist > .spacer,\ngrid > .spacer {\n  border: 0;\n  box-sizing: border-box;\n  display: block;\n  overflow: hidden;\n  visibility: hidden;\n  margin: 0;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/css/select.css",
    "content": "/* Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n *\n * This is the generic select css used on various WebUI implementations.\n */\n\nselect {\n  -webkit-appearance: button;\n  -webkit-border-radius: 2px;\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n  -webkit-user-select: none;\n  background-image: url(\"../images/select.png\"),\n                    -webkit-linear-gradient(#fafafa, #f4f4f4 40%, #e5e5e5);\n  background-position: center right;\n  background-repeat: no-repeat;\n  border: 1px solid #aaa;\n  color: #555;\n  font-size: inherit;\n  margin: 0;\n  overflow: hidden;\n  padding-top: 2px;\n  padding-inline-end: 20px;\n  padding-inline-start: 2px;\n  padding-bottom: 2px;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\nhtml[dir='rtl'] select {\n  background-position: center left;\n}\n\n\nselect:disabled {\n  color: graytext;\n}\n\nselect:enabled:hover {\n  -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n  background-image: url(\"../images/select.png\"),\n                    -webkit-linear-gradient(#fefefe, #f8f8f8 40%, #e9e9e9);\n  color: #333;\n}\n\nselect:enabled:active {\n  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);\n  background-image: url(\"../images/select.png\"),\n                    -webkit-linear-gradient(#f4f4f4, #efefef 40%, #dcdcdc);\n  color: #444;\n}"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/js/cr/event_target.js",
    "content": "// Copyright (c) 2010 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview This contains an implementation of the EventTarget interface\n * as defined by DOM Level 2 Events.\n */\n\ncr.define('cr', function() {\n\n  /**\n   * Creates a new EventTarget. This class implements the DOM level 2\n   * EventTarget interface and can be used wherever those are used.\n   * @constructor\n   */\n  function EventTarget() {\n  }\n\n  EventTarget.prototype = {\n\n    /**\n     * Adds an event listener to the target.\n     * @param {string} type The name of the event.\n     * @param {!Function|{handleEvent:Function}} handler The handler for the\n     *     event. This is called when the event is dispatched.\n     */\n    addEventListener: function(type, handler) {\n      if (!this.listeners_)\n        this.listeners_ = Object.create(null);\n      if (!(type in this.listeners_)) {\n        this.listeners_[type] = [handler];\n      } else {\n        var handlers = this.listeners_[type];\n        if (handlers.indexOf(handler) < 0)\n          handlers.push(handler);\n      }\n    },\n\n    /**\n     * Removes an event listener from the target.\n     * @param {string} type The name of the event.\n     * @param {!Function|{handleEvent:Function}} handler The handler for the\n     *     event.\n     */\n    removeEventListener: function(type, handler) {\n      if (!this.listeners_)\n        return;\n      if (type in this.listeners_) {\n        var handlers = this.listeners_[type];\n        var index = handlers.indexOf(handler);\n        if (index >= 0) {\n          // Clean up if this was the last listener.\n          if (handlers.length == 1)\n            delete this.listeners_[type];\n          else\n            handlers.splice(index, 1);\n        }\n      }\n    },\n\n    /**\n     * Dispatches an event and calls all the listeners that are listening to\n     * the type of the event.\n     * @param {!cr.event.Event} event The event to dispatch.\n     * @return {boolean} Whether the default action was prevented. If someone\n     *     calls preventDefault on the event object then this returns false.\n     */\n    dispatchEvent: function(event) {\n      if (!this.listeners_)\n        return true;\n\n      // Since we are using DOM Event objects we need to override some of the\n      // properties and methods so that we can emulate this correctly.\n      var self = this;\n      event.__defineGetter__('target', function() {\n        return self;\n      });\n      event.preventDefault = function() {\n        this.returnValue = false;\n      };\n\n      var type = event.type;\n      var prevented = 0;\n      if (type in this.listeners_) {\n        // Clone to prevent removal during dispatch\n        var handlers = this.listeners_[type].concat();\n        for (var i = 0, handler; handler = handlers[i]; i++) {\n          if (handler.handleEvent)\n            prevented |= handler.handleEvent.call(handler, event) === false;\n          else\n            prevented |= handler.call(this, event) === false;\n        }\n      }\n\n      return !prevented && event.returnValue;\n    }\n  };\n\n  // Export\n  return {\n    EventTarget: EventTarget\n  };\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/js/cr/ui/array_data_model.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview This is a data model representin\n */\n\ncr.define('cr.ui', function() {\n  /** @const */ var EventTarget = cr.EventTarget;\n\n  /**\n   * A data model that wraps a simple array and supports sorting by storing\n   * initial indexes of elements for each position in sorted array.\n   * @param {!Array} array The underlying array.\n   * @constructor\n   * @extends {EventTarget}\n   */\n  function ArrayDataModel(array) {\n    this.array_ = array;\n    this.indexes_ = [];\n    this.compareFunctions_ = {};\n\n    for (var i = 0; i < array.length; i++) {\n      this.indexes_.push(i);\n    }\n  }\n\n  ArrayDataModel.prototype = {\n    __proto__: EventTarget.prototype,\n\n    /**\n     * The length of the data model.\n     * @type {number}\n     */\n    get length() {\n      return this.array_.length;\n    },\n\n    /**\n     * Returns the item at the given index.\n     * This implementation returns the item at the given index in the sorted\n     * array.\n     * @param {number} index The index of the element to get.\n     * @return {*} The element at the given index.\n     */\n    item: function(index) {\n      if (index >= 0 && index < this.length)\n        return this.array_[this.indexes_[index]];\n      return undefined;\n    },\n\n    /**\n     * Returns compare function set for given field.\n     * @param {string} field The field to get compare function for.\n     * @return {function(*, *): number} Compare function set for given field.\n     */\n    compareFunction: function(field) {\n      return this.compareFunctions_[field];\n    },\n\n    /**\n     * Sets compare function for given field.\n     * @param {string} field The field to set compare function.\n     * @param {function(*, *): number} Compare function to set for given field.\n     */\n    setCompareFunction: function(field, compareFunction) {\n      if (!this.compareFunctions_) {\n        this.compareFunctions_ = {};\n      }\n      this.compareFunctions_[field] = compareFunction;\n    },\n\n    /**\n     * Returns current sort status.\n     * @return {!Object} Current sort status.\n     */\n    get sortStatus() {\n      if (this.sortStatus_) {\n        return this.createSortStatus(\n            this.sortStatus_.field, this.sortStatus_.direction);\n      } else {\n        return this.createSortStatus(null, null);\n      }\n    },\n\n    /**\n     * Returns the first matching item.\n     * @param {*} item The item to find.\n     * @param {number=} opt_fromIndex If provided, then the searching start at\n     *     the {@code opt_fromIndex}.\n     * @return {number} The index of the first found element or -1 if not found.\n     */\n    indexOf: function(item, opt_fromIndex) {\n      return this.array_.indexOf(item, opt_fromIndex);\n    },\n\n    /**\n     * Returns an array of elements in a selected range.\n     * @param {number=} opt_from The starting index of the selected range.\n     * @param {number=} opt_to The ending index of selected range.\n     * @return {Array} An array of elements in the selected range.\n     */\n    slice: function(opt_from, opt_to) {\n      return this.array_.slice.apply(this.array_, arguments);\n    },\n\n    /**\n     * This removes and adds items to the model.\n     * This dispatches a splice event.\n     * This implementation runs sort after splice and creates permutation for\n     * the whole change.\n     * @param {number} index The index of the item to update.\n     * @param {number} deleteCount The number of items to remove.\n     * @param {...*} The items to add.\n     * @return {!Array} An array with the removed items.\n     */\n    splice: function(index, deleteCount, var_args) {\n      var addCount = arguments.length - 2;\n      var newIndexes = [];\n      var deletePermutation = [];\n      var deleted = 0;\n      for (var i = 0; i < this.indexes_.length; i++) {\n        var oldIndex = this.indexes_[i];\n        if (oldIndex < index) {\n          newIndexes.push(oldIndex);\n          deletePermutation.push(i - deleted);\n        } else if (oldIndex >= index + deleteCount) {\n          newIndexes.push(oldIndex - deleteCount + addCount);\n          deletePermutation.push(i - deleted);\n        } else {\n          deletePermutation.push(-1);\n          deleted++;\n        }\n      }\n      for (var i = 0; i < addCount; i++) {\n        newIndexes.push(index + i);\n      }\n      this.indexes_ = newIndexes;\n\n      var arr = this.array_;\n\n      // TODO(arv): Maybe unify splice and change events?\n      var spliceEvent = new Event('splice');\n      spliceEvent.index = index;\n      spliceEvent.removed = arr.slice(index, index + deleteCount);\n      spliceEvent.added = Array.prototype.slice.call(arguments, 2);\n\n      var rv = arr.splice.apply(arr, arguments);\n\n      var status = this.sortStatus;\n      // if sortStatus.field is null, this restores original order.\n      var sortPermutation = this.doSort_(this.sortStatus.field,\n                                         this.sortStatus.direction);\n      if (sortPermutation) {\n        var splicePermutation = deletePermutation.map(function(element) {\n          return element != -1 ? sortPermutation[element] : -1;\n        });\n        this.dispatchPermutedEvent_(splicePermutation);\n      } else {\n        this.dispatchPermutedEvent_(deletePermutation);\n      }\n\n      this.dispatchEvent(spliceEvent);\n\n      // If real sorting is needed, we should first call prepareSort (data may\n      // change), and then sort again.\n      // Still need to finish the sorting above (including events), so\n      // list will not go to inconsistent state.\n      if (status.field) {\n        setTimeout(this.sort.bind(this, status.field, status.direction), 0);\n      }\n      return rv;\n    },\n\n    /**\n     * Appends items to the end of the model.\n     *\n     * This dispatches a splice event.\n     *\n     * @param {...*} The items to append.\n     * @return {number} The new length of the model.\n     */\n    push: function(var_args) {\n      var args = Array.prototype.slice.call(arguments);\n      args.unshift(this.length, 0);\n      this.splice.apply(this, args);\n      return this.length;\n    },\n\n    /**\n     * Use this to update a given item in the array. This does not remove and\n     * reinsert a new item.\n     * This dispatches a change event.\n     * This runs sort after updating.\n     * @param {number} index The index of the item to update.\n     */\n    updateIndex: function(index) {\n      if (index < 0 || index >= this.length)\n        throw Error('Invalid index, ' + index);\n\n      // TODO(arv): Maybe unify splice and change events?\n      var e = new Event('change');\n      e.index = index;\n      this.dispatchEvent(e);\n\n      if (this.sortStatus.field) {\n        var status = this.sortStatus;\n        var sortPermutation = this.doSort_(this.sortStatus.field,\n                                           this.sortStatus.direction);\n        if (sortPermutation)\n          this.dispatchPermutedEvent_(sortPermutation);\n        // We should first call prepareSort (data may change), and then sort.\n        // Still need to finish the sorting above (including events), so\n        // list will not go to inconsistent state.\n        setTimeout(this.sort.bind(this, status.field, status.direction), 0);\n      }\n    },\n\n    /**\n     * Creates sort status with given field and direction.\n     * @param {string} field Sort field.\n     * @param {string} direction Sort direction.\n     * @return {!Object} Created sort status.\n     */\n    createSortStatus: function(field, direction) {\n      return {\n        field: field,\n        direction: direction\n      };\n    },\n\n    /**\n     * Called before a sort happens so that you may fetch additional data\n     * required for the sort.\n     *\n     * @param {string} field Sort field.\n     * @param {function()} callback The function to invoke when preparation\n     *     is complete.\n     */\n    prepareSort: function(field, callback) {\n      callback();\n    },\n\n    /**\n     * Sorts data model according to given field and direction and dispathes\n     * sorted event.\n     * @param {string} field Sort field.\n     * @param {string} direction Sort direction.\n     */\n    sort: function(field, direction) {\n      var self = this;\n\n      this.prepareSort(field, function() {\n        var sortPermutation = self.doSort_(field, direction);\n        if (sortPermutation)\n          self.dispatchPermutedEvent_(sortPermutation);\n        self.dispatchSortEvent_();\n      });\n    },\n\n    /**\n     * Sorts data model according to given field and direction.\n     * @param {string} field Sort field.\n     * @param {string} direction Sort direction.\n     */\n    doSort_: function(field, direction) {\n      var compareFunction = this.sortFunction_(field, direction);\n      var positions = [];\n      for (var i = 0; i < this.length; i++) {\n        positions[this.indexes_[i]] = i;\n      }\n      this.indexes_.sort(compareFunction);\n      this.sortStatus_ = this.createSortStatus(field, direction);\n      var sortPermutation = [];\n      var changed = false;\n      for (var i = 0; i < this.length; i++) {\n        if (positions[this.indexes_[i]] != i)\n          changed = true;\n        sortPermutation[positions[this.indexes_[i]]] = i;\n      }\n      if (changed)\n        return sortPermutation;\n      return null;\n    },\n\n    dispatchSortEvent_: function() {\n      var e = new Event('sorted');\n      this.dispatchEvent(e);\n    },\n\n    dispatchPermutedEvent_: function(permutation) {\n      var e = new Event('permuted');\n      e.permutation = permutation;\n      e.newLength = this.length;\n      this.dispatchEvent(e);\n    },\n\n    /**\n     * Creates compare function for the field.\n     * Returns the function set as sortFunction for given field\n     * or default compare function\n     * @param {string} field Sort field.\n     * @param {function(*, *): number} Compare function.\n     */\n    createCompareFunction_: function(field) {\n      var compareFunction =\n          this.compareFunctions_ ? this.compareFunctions_[field] : null;\n      var defaultValuesCompareFunction = this.defaultValuesCompareFunction;\n      if (compareFunction) {\n        return compareFunction;\n      } else {\n        return function(a, b) {\n          return defaultValuesCompareFunction.call(null, a[field], b[field]);\n        }\n      }\n      return compareFunction;\n    },\n\n    /**\n     * Creates compare function for given field and direction.\n     * @param {string} field Sort field.\n     * @param {string} direction Sort direction.\n     * @param {function(*, *): number} Compare function.\n     */\n    sortFunction_: function(field, direction) {\n      var compareFunction = null;\n      if (field !== null)\n        compareFunction = this.createCompareFunction_(field);\n      var dirMultiplier = direction == 'desc' ? -1 : 1;\n\n      return function(index1, index2) {\n        var item1 = this.array_[index1];\n        var item2 = this.array_[index2];\n\n        var compareResult = 0;\n        if (typeof(compareFunction) === 'function')\n          compareResult = compareFunction.call(null, item1, item2);\n        if (compareResult != 0)\n          return dirMultiplier * compareResult;\n        return dirMultiplier * this.defaultValuesCompareFunction(index1,\n                                                                 index2);\n      }.bind(this);\n    },\n\n    /**\n     * Default compare function.\n     */\n    defaultValuesCompareFunction: function(a, b) {\n      // We could insert i18n comparisons here.\n      if (a < b)\n        return -1;\n      if (a > b)\n        return 1;\n      return 0;\n    }\n  };\n\n  return {\n    ArrayDataModel: ArrayDataModel\n  };\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/js/cr/ui/list.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// require: array_data_model.js\n// require: list_selection_model.js\n// require: list_selection_controller.js\n// require: list_item.js\n\n/**\n * @fileoverview This implements a list control.\n */\n\ncr.define('cr.ui', function() {\n  const ListSelectionModel = cr.ui.ListSelectionModel;\n  const ListSelectionController = cr.ui.ListSelectionController;\n  const ArrayDataModel = cr.ui.ArrayDataModel;\n\n  /**\n   * Whether a mouse event is inside the element viewport. This will return\n   * false if the mouseevent was generated over a border or a scrollbar.\n   * @param {!HTMLElement} el The element to test the event with.\n   * @param {!Event} e The mouse event.\n   * @param {boolean} Whether the mouse event was inside the viewport.\n   */\n  function inViewport(el, e) {\n    var rect = el.getBoundingClientRect();\n    var x = e.clientX;\n    var y = e.clientY;\n    return x >= rect.left + el.clientLeft &&\n           x < rect.left + el.clientLeft + el.clientWidth &&\n           y >= rect.top + el.clientTop &&\n           y < rect.top + el.clientTop + el.clientHeight;\n  }\n\n  /**\n   * Creates an item (dataModel.item(0)) and measures its height.\n   * @param {!List} list The list to create the item for.\n   * @param {ListItem=} opt_item The list item to use to do the measuring. If\n   *     this is not provided an item will be created based on the first value\n   *     in the model.\n   * @return {{height: number, marginVertical: number, width: number,\n   *     marginHorizontal: number}} The height and width of the item, taking\n   *     margins into account, and the height and width of the margins\n   *     themselves.\n   */\n  function measureItem(list, opt_item) {\n    var dataModel = list.dataModel;\n    if (!dataModel || !dataModel.length)\n      return 0;\n    var item = opt_item || list.createItem(dataModel.item(0));\n    if (!opt_item)\n      list.appendChild(item);\n\n    var rect = item.getBoundingClientRect();\n    var cs = getComputedStyle(item);\n    var mt = parseFloat(cs.marginTop);\n    var mb = parseFloat(cs.marginBottom);\n    var ml = parseFloat(cs.marginLeft);\n    var mr = parseFloat(cs.marginRight);\n    var h = rect.height;\n    var w = rect.width;\n    var mh = 0;\n    var mv = 0;\n\n    // Handle margin collapsing.\n    if (mt < 0 && mb < 0) {\n      mv = Math.min(mt, mb);\n    } else if (mt >= 0 && mb >= 0) {\n      mv = Math.max(mt, mb);\n    } else {\n      mv = mt + mb;\n    }\n    h += mv;\n\n    if (ml < 0 && mr < 0) {\n      mh = Math.min(ml, mr);\n    } else if (ml >= 0 && mr >= 0) {\n      mh = Math.max(ml, mr);\n    } else {\n      mh = ml + mr;\n    }\n    w += mh;\n\n    if (!opt_item)\n      list.removeChild(item);\n    return {\n        height: Math.max(0, h), marginVertical: mv,\n        width: Math.max(0, w), marginHorizontal: mh};\n  }\n\n  function getComputedStyle(el) {\n    return el.ownerDocument.defaultView.getComputedStyle(el);\n  }\n\n  /**\n   * Creates a new list element.\n   * @param {Object=} opt_propertyBag Optional properties.\n   * @constructor\n   * @extends {HTMLUListElement}\n   */\n  var List = cr.ui.define('list');\n\n  List.prototype = {\n    __proto__: HTMLUListElement.prototype,\n\n    /**\n     * Measured size of list items. This is lazily calculated the first time it\n     * is needed. Note that lead item is allowed to have a different height, to\n     * accommodate lists where a single item at a time can be expanded to show\n     * more detail.\n     * @type {{height: number, marginVertical: number, width: number,\n     *     marginHorizontal: number}}\n     * @private\n     */\n    measured_: undefined,\n\n    /**\n     * The height of the lead item, which is allowed to have a different height\n     * than other list items to accommodate lists where a single item at a time\n     * can be expanded to show more detail. It is explicitly set by client code\n     * when the height of the lead item is changed with {@code set\n     * leadItemHeight}, and presumed equal to {@code itemHeight_} otherwise.\n     * @type {number}\n     * @private\n     */\n    leadItemHeight_: 0,\n\n    /**\n     * Whether or not the list is autoexpanding. If true, the list resizes\n     * its height to accomadate all children.\n     * @type {boolean}\n     * @private\n     */\n    autoExpands_: false,\n\n    /**\n     * Function used to create grid items.\n     * @type {function(): !ListItem}\n     * @private\n     */\n    itemConstructor_: cr.ui.ListItem,\n\n    /**\n     * Function used to create grid items.\n     * @type {function(): !ListItem}\n     */\n    get itemConstructor() {\n      return this.itemConstructor_;\n    },\n    set itemConstructor(func) {\n      if (func != this.itemConstructor_) {\n        this.itemConstructor_ = func;\n        this.cachedItems_ = {};\n        this.redraw();\n      }\n    },\n\n    dataModel_: null,\n\n    /**\n     * The data model driving the list.\n     * @type {ArrayDataModel}\n     */\n    set dataModel(dataModel) {\n      if (this.dataModel_ != dataModel) {\n        if (!this.boundHandleDataModelPermuted_) {\n          this.boundHandleDataModelPermuted_ =\n              this.handleDataModelPermuted_.bind(this);\n          this.boundHandleDataModelChange_ =\n              this.handleDataModelChange_.bind(this);\n        }\n\n        if (this.dataModel_) {\n          this.dataModel_.removeEventListener(\n              'permuted',\n              this.boundHandleDataModelPermuted_);\n          this.dataModel_.removeEventListener('change',\n                                              this.boundHandleDataModelChange_);\n        }\n\n        this.dataModel_ = dataModel;\n\n        this.cachedItems_ = {};\n        this.selectionModel.clear();\n        if (dataModel)\n          this.selectionModel.adjustLength(dataModel.length);\n\n        if (this.dataModel_) {\n          this.dataModel_.addEventListener(\n              'permuted',\n              this.boundHandleDataModelPermuted_);\n          this.dataModel_.addEventListener('change',\n                                           this.boundHandleDataModelChange_);\n        }\n\n        this.redraw();\n      }\n    },\n\n    get dataModel() {\n      return this.dataModel_;\n    },\n\n    /**\n     * The selection model to use.\n     * @type {cr.ui.ListSelectionModel}\n     */\n    get selectionModel() {\n      return this.selectionModel_;\n    },\n    set selectionModel(sm) {\n      var oldSm = this.selectionModel_;\n      if (oldSm == sm)\n        return;\n\n      if (!this.boundHandleOnChange_) {\n        this.boundHandleOnChange_ = this.handleOnChange_.bind(this);\n        this.boundHandleLeadChange_ = this.handleLeadChange_.bind(this);\n      }\n\n      if (oldSm) {\n        oldSm.removeEventListener('change', this.boundHandleOnChange_);\n        oldSm.removeEventListener('leadIndexChange',\n                                  this.boundHandleLeadChange_);\n      }\n\n      this.selectionModel_ = sm;\n      this.selectionController_ = this.createSelectionController(sm);\n\n      if (sm) {\n        sm.addEventListener('change', this.boundHandleOnChange_);\n        sm.addEventListener('leadIndexChange', this.boundHandleLeadChange_);\n      }\n    },\n\n    /**\n     * Whether or not the list auto-expands.\n     * @type {boolean}\n     */\n    get autoExpands() {\n      return this.autoExpands_;\n    },\n    set autoExpands(autoExpands) {\n      if (this.autoExpands_ == autoExpands)\n        return;\n      this.autoExpands_ = autoExpands;\n      this.redraw();\n    },\n\n    /**\n     * Convenience alias for selectionModel.selectedItem\n     * @type {cr.ui.ListItem}\n     */\n    get selectedItem() {\n      var dataModel = this.dataModel;\n      if (dataModel) {\n        var index = this.selectionModel.selectedIndex;\n        if (index != -1)\n          return dataModel.item(index);\n      }\n      return null;\n    },\n    set selectedItem(selectedItem) {\n      var dataModel = this.dataModel;\n      if (dataModel) {\n        var index = this.dataModel.indexOf(selectedItem);\n        this.selectionModel.selectedIndex = index;\n      }\n    },\n\n    /**\n     * The height of the lead item.\n     * If set to 0, resets to the same height as other items.\n     * @type {number}\n     */\n    get leadItemHeight() {\n      return this.leadItemHeight_ || this.getItemHeight_();\n    },\n    set leadItemHeight(height) {\n      if (height) {\n        var size = this.getItemSize_();\n        this.leadItemHeight_ = Math.max(0, height + size.marginVertical);\n      } else {\n        this.leadItemHeight_ = 0;\n      }\n    },\n\n    /**\n     * Convenience alias for selectionModel.selectedItems\n     * @type {!Array<cr.ui.ListItem>}\n     */\n    get selectedItems() {\n      var indexes = this.selectionModel.selectedIndexes;\n      var dataModel = this.dataModel;\n      if (dataModel) {\n        return indexes.map(function(i) {\n          return dataModel.item(i);\n        });\n      }\n      return [];\n    },\n\n    /**\n     * The HTML elements representing the items. This is just all the list item\n     * children but subclasses may override this to filter out certain elements.\n     * @type {HTMLCollection}\n     */\n    get items() {\n      return Array.prototype.filter.call(this.children, function(child) {\n        return !child.classList.contains('spacer');\n      });\n    },\n\n    batchCount_: 0,\n\n    /**\n     * When making a lot of updates to the list, the code could be wrapped in\n     * the startBatchUpdates and finishBatchUpdates to increase performance. Be\n     * sure that the code will not return without calling endBatchUpdates or the\n     * list will not be correctly updated.\n     */\n    startBatchUpdates: function() {\n      this.batchCount_++;\n    },\n\n    /**\n     * See startBatchUpdates.\n     */\n    endBatchUpdates: function() {\n      this.batchCount_--;\n      if (this.batchCount_ == 0)\n        this.redraw();\n    },\n\n    /**\n     * Initializes the element.\n     */\n    decorate: function() {\n      // Add fillers.\n      this.beforeFiller_ = this.ownerDocument.createElement('div');\n      this.afterFiller_ = this.ownerDocument.createElement('div');\n      this.beforeFiller_.className = 'spacer';\n      this.afterFiller_.className = 'spacer';\n      this.appendChild(this.beforeFiller_);\n      this.appendChild(this.afterFiller_);\n\n      var length = this.dataModel ? this.dataModel.length : 0;\n      this.selectionModel = new ListSelectionModel(length);\n\n      this.addEventListener('dblclick', this.handleDoubleClick_);\n      this.addEventListener('mousedown', this.handleMouseDownUp_);\n      this.addEventListener('mouseup', this.handleMouseDownUp_);\n      this.addEventListener('keydown', this.handleKeyDown);\n      this.addEventListener('focus', this.handleElementFocus_, true);\n      this.addEventListener('blur', this.handleElementBlur_, true);\n      this.addEventListener('scroll', this.redraw.bind(this));\n      this.setAttribute('role', 'listbox');\n\n      // Make list focusable\n      if (!this.hasAttribute('tabindex'))\n        this.tabIndex = 0;\n    },\n\n    /**\n     * @return {number} The height of an item, measuring it if necessary.\n     * @private\n     */\n    getItemHeight_: function() {\n      return this.getItemSize_().height;\n    },\n\n    /**\n     * @return {number} The width of an item, measuring it if necessary.\n     * @private\n     */\n    getItemWidth_: function() {\n      return this.getItemSize_().width;\n    },\n\n    /**\n     * @return {{height: number, width: number}} The height and width\n     *     of an item, measuring it if necessary.\n     * @private\n     */\n    getItemSize_: function() {\n      if (!this.measured_ || !this.measured_.height) {\n        this.measured_ = measureItem(this);\n      }\n      return this.measured_;\n    },\n\n    /**\n     * Callback for the double click event.\n     * @param {Event} e The mouse event object.\n     * @private\n     */\n    handleDoubleClick_: function(e) {\n      if (this.disabled)\n        return;\n\n      var target = this.getListItemAncestor(e.target);\n      if (target)\n        this.activateItemAtIndex(this.getIndexOfListItem(target));\n    },\n\n    /**\n     * Callback for mousedown and mouseup events.\n     * @param {Event} e The mouse event object.\n     * @private\n     */\n    handleMouseDownUp_: function(e) {\n      if (this.disabled)\n        return;\n\n      var target = e.target;\n\n      // If the target was this element we need to make sure that the user did\n      // not click on a border or a scrollbar.\n      if (target == this && !inViewport(target, e))\n        return;\n\n      target = this.getListItemAncestor(target);\n\n      var index = target ? this.getIndexOfListItem(target) : -1;\n      this.selectionController_.handleMouseDownUp(e, index);\n    },\n\n    /**\n     * Called when an element in the list is focused. Marks the list as having\n     * a focused element, and dispatches an event if it didn't have focus.\n     * @param {Event} e The focus event.\n     * @private\n     */\n    handleElementFocus_: function(e) {\n      if (!this.hasElementFocus) {\n        this.hasElementFocus = true;\n        // Force styles based on hasElementFocus to take effect.\n        this.forceRepaint_();\n      }\n    },\n\n    /**\n     * Called when an element in the list is blurred. If focus moves outside\n     * the list, marks the list as no longer having focus and dispatches an\n     * event.\n     * @param {Event} e The blur event.\n     * @private\n     */\n    handleElementBlur_: function(e) {\n      // When the blur event happens we do not know who is getting focus so we\n      // delay this a bit until we know if the new focus node is outside the\n      // list.\n      var list = this;\n      var doc = e.target.ownerDocument;\n      window.setTimeout(function() {\n        var activeElement = doc.activeElement;\n        if (!list.contains(activeElement)) {\n          list.hasElementFocus = false;\n          // Force styles based on hasElementFocus to take effect.\n          list.forceRepaint_();\n        }\n      });\n    },\n\n    /**\n     * Forces a repaint of the list. Changing custom attributes, even if there\n     * are style rules depending on them, doesn't cause a repaint\n     * (<https://bugs.webkit.org/show_bug.cgi?id=12519>), so this can be called\n     * to force the list to repaint.\n     * @private\n     */\n    forceRepaint_: function(e) {\n      var dummyElement = document.createElement('div');\n      this.appendChild(dummyElement);\n      this.removeChild(dummyElement);\n    },\n\n    /**\n     * Returns the list item element containing the given element, or null if\n     * it doesn't belong to any list item element.\n     * @param {HTMLElement} element The element.\n     * @return {ListItem} The list item containing |element|, or null.\n     */\n    getListItemAncestor: function(element) {\n      var container = element;\n      while (container && container.parentNode != this) {\n        container = container.parentNode;\n      }\n      return container;\n    },\n\n    /**\n     * Handle a keydown event.\n     * @param {Event} e The keydown event.\n     * @return {boolean} Whether the key event was handled.\n     */\n    handleKeyDown: function(e) {\n      if (this.disabled)\n        return;\n\n      return this.selectionController_.handleKeyDown(e);\n    },\n\n    /**\n     * Callback from the selection model. We dispatch {@code change} events\n     * when the selection changes.\n     * @param {!Event} e Event with change info.\n     * @private\n     */\n    handleOnChange_: function(ce) {\n      ce.changes.forEach(function(change) {\n        var listItem = this.getListItemByIndex(change.index);\n        if (listItem)\n          listItem.selected = change.selected;\n      }, this);\n\n      cr.dispatchSimpleEvent(this, 'change');\n    },\n\n    /**\n     * Handles a change of the lead item from the selection model.\n     * @property {Event} pe The property change event.\n     * @private\n     */\n    handleLeadChange_: function(pe) {\n      var element;\n      if (pe.oldValue != -1) {\n        if ((element = this.getListItemByIndex(pe.oldValue)))\n          element.lead = false;\n      }\n\n      if (pe.newValue != -1) {\n        if ((element = this.getListItemByIndex(pe.newValue)))\n          element.lead = true;\n        this.scrollIndexIntoView(pe.newValue);\n        // If the lead item has a different height than other items, then we\n        // may run into a problem that requires a second attempt to scroll\n        // it into view. The first scroll attempt will trigger a redraw,\n        // which will clear out the list and repopulate it with new items.\n        // During the redraw, the list may shrink temporarily, which if the\n        // lead item is the last item, will move the scrollTop up since it\n        // cannot extend beyond the end of the list. (Sadly, being scrolled to\n        // the bottom of the list is not \"sticky.\") So, we set a timeout to\n        // rescroll the list after this all gets sorted out. This is perhaps\n        // not the most elegant solution, but no others seem obvious.\n        var self = this;\n        window.setTimeout(function() {\n          self.scrollIndexIntoView(pe.newValue);\n        });\n      }\n    },\n\n    /**\n     * This handles data model 'permuted' event.\n     * this event is dispatched as a part of sort or splice.\n     * We need to\n     *  - adjust the cache.\n     *  - adjust selection.\n     *  - redraw.\n     *  - scroll the list to show selection.\n     *  It is important that the cache adjustment happens before selection model\n     *  adjustments.\n     * @param {Event} e The 'permuted' event.\n     */\n    handleDataModelPermuted_: function(e) {\n      var newCachedItems = {};\n      for (var index in this.cachedItems_) {\n        if (e.permutation[index] != -1)\n          newCachedItems[e.permutation[index]] = this.cachedItems_[index];\n        else\n          delete this.cachedItems_[index];\n      }\n      this.cachedItems_ = newCachedItems;\n\n      this.startBatchUpdates();\n\n      var sm = this.selectionModel;\n      sm.adjustLength(e.newLength);\n      sm.adjustToReordering(e.permutation);\n\n      this.endBatchUpdates();\n\n      if (sm.leadIndex != -1)\n        this.scrollIndexIntoView(sm.leadIndex);\n    },\n\n    handleDataModelChange_: function(e) {\n      if (e.index >= this.firstIndex_ && e.index < this.lastIndex_) {\n        if (this.cachedItems_[e.index])\n          delete this.cachedItems_[e.index];\n        this.redraw();\n      }\n    },\n\n    /**\n     * @param {number} index The index of the item.\n     * @return {number} The top position of the item inside the list, not taking\n     *     into account lead item. May vary in the case of multiple columns.\n     */\n    getItemTop: function(index) {\n      return index * this.getItemHeight_();\n    },\n\n    /**\n     * @param {number} index The index of the item.\n     * @return {number} The row of the item. May vary in the case\n     *     of multiple columns.\n     */\n    getItemRow: function(index) {\n      return index;\n    },\n\n    /**\n     * @param {number} row The row.\n     * @return {number} The index of the first item in the row.\n     */\n    getFirstItemInRow: function(row) {\n      return row;\n    },\n\n    /**\n     * Ensures that a given index is inside the viewport.\n     * @param {number} index The index of the item to scroll into view.\n     * @return {boolean} Whether any scrolling was needed.\n     */\n    scrollIndexIntoView: function(index) {\n      var dataModel = this.dataModel;\n      if (!dataModel || index < 0 || index >= dataModel.length)\n        return false;\n\n      var itemHeight = this.getItemHeight_();\n      var scrollTop = this.scrollTop;\n      var top = this.getItemTop(index);\n      var leadIndex = this.selectionModel.leadIndex;\n\n      // Adjust for the lead item if it is above the given index.\n      if (leadIndex > -1 && leadIndex < index)\n        top += this.leadItemHeight - itemHeight;\n      else if (leadIndex == index)\n        itemHeight = this.leadItemHeight;\n\n      if (top < scrollTop) {\n        this.scrollTop = top;\n        return true;\n      } else {\n        var clientHeight = this.clientHeight;\n        var cs = getComputedStyle(this);\n        var paddingY = parseInt(cs.paddingTop, 10) +\n                       parseInt(cs.paddingBottom, 10);\n\n        if (top + itemHeight > scrollTop + clientHeight - paddingY) {\n          this.scrollTop = top + itemHeight - clientHeight + paddingY;\n          return true;\n        }\n      }\n\n      return false;\n    },\n\n    /**\n     * @return {!ClientRect} The rect to use for the context menu.\n     */\n    getRectForContextMenu: function() {\n      // TODO(arv): Add trait support so we can share more code between trees\n      // and lists.\n      var index = this.selectionModel.selectedIndex;\n      var el = this.getListItemByIndex(index);\n      if (el)\n        return el.getBoundingClientRect();\n      return this.getBoundingClientRect();\n    },\n\n    /**\n     * Takes a value from the data model and finds the associated list item.\n     * @param {*} value The value in the data model that we want to get the list\n     *     item for.\n     * @return {ListItem} The first found list item or null if not found.\n     */\n    getListItem: function(value) {\n      var dataModel = this.dataModel;\n      if (dataModel) {\n        var index = dataModel.indexOf(value);\n        return this.getListItemByIndex(index);\n      }\n      return null;\n    },\n\n    /**\n     * Find the list item element at the given index.\n     * @param {number} index The index of the list item to get.\n     * @return {ListItem} The found list item or null if not found.\n     */\n    getListItemByIndex: function(index) {\n      return this.cachedItems_[index] || null;\n    },\n\n    /**\n     * Find the index of the given list item element.\n     * @param {ListItem} item The list item to get the index of.\n     * @return {number} The index of the list item, or -1 if not found.\n     */\n    getIndexOfListItem: function(item) {\n      var index = item.listIndex;\n      if (this.cachedItems_[index] == item) {\n        return index;\n      }\n      return -1;\n    },\n\n    /**\n     * Creates a new list item.\n     * @param {*} value The value to use for the item.\n     * @return {!ListItem} The newly created list item.\n     */\n    createItem: function(value) {\n      var item = new this.itemConstructor_(value);\n      item.label = value;\n      if (typeof item.decorate == 'function')\n        item.decorate();\n      return item;\n    },\n\n    /**\n     * Creates the selection controller to use internally.\n     * @param {cr.ui.ListSelectionModel} sm The underlying selection model.\n     * @return {!cr.ui.ListSelectionController} The newly created selection\n     *     controller.\n     */\n    createSelectionController: function(sm) {\n      return new ListSelectionController(sm);\n    },\n\n    /**\n     * Return the heights (in pixels) of the top of the given item index within\n     * the list, and the height of the given item itself, accounting for the\n     * possibility that the lead item may be a different height.\n     * @param {number} index The index to find the top height of.\n     * @return {{top: number, height: number}} The heights for the given index.\n     * @private\n     */\n    getHeightsForIndex_: function(index) {\n      var itemHeight = this.getItemHeight_();\n      var top = this.getItemTop(index);\n      if (this.selectionModel.leadIndex > -1 &&\n          this.selectionModel.leadIndex < index) {\n        top += this.leadItemHeight - itemHeight;\n      } else if (this.selectionModel.leadIndex == index) {\n        itemHeight = this.leadItemHeight;\n      }\n      return {top: top, height: itemHeight};\n    },\n\n    /**\n     * Find the index of the list item containing the given y offset (measured\n     * in pixels from the top) within the list. In the case of multiple columns,\n     * returns the first index in the row.\n     * @param {number} offset The y offset in pixels to get the index of.\n     * @return {number} The index of the list item.\n     * @private\n     */\n    getIndexForListOffset_: function(offset) {\n      var itemHeight = this.getItemHeight_();\n      var leadIndex = this.selectionModel.leadIndex;\n      var leadItemHeight = this.leadItemHeight;\n      if (leadIndex < 0 || leadItemHeight == itemHeight) {\n        // Simple case: no lead item or lead item height is not different.\n        return this.getFirstItemInRow(Math.floor(offset / itemHeight));\n      }\n      var leadTop = this.getItemTop(leadIndex);\n      // If the given offset is above the lead item, it's also simple.\n      if (offset < leadTop)\n        return this.getFirstItemInRow(Math.floor(offset / itemHeight));\n      // If the lead item contains the given offset, we just return its index.\n      if (offset < leadTop + leadItemHeight)\n        return this.getFirstItemInRow(this.getItemRow(leadIndex));\n      // The given offset must be below the lead item. Adjust and recalculate.\n      offset -= leadItemHeight - itemHeight;\n      return this.getFirstItemInRow(Math.floor(offset / itemHeight));\n    },\n\n    /**\n     * Return the number of items that occupy the range of heights between the\n     * top of the start item and the end offset.\n     * @param {number} startIndex The index of the first visible item.\n     * @param {number} endOffset The y offset in pixels of the end of the list.\n     * @return {number} The number of list items visible.\n     * @private\n     */\n    countItemsInRange_: function(startIndex, endOffset) {\n      var endIndex = this.getIndexForListOffset_(endOffset);\n      return endIndex - startIndex + 1;\n    },\n\n    /**\n     * Calculates the number of items fitting in viewport given the index of\n     * first item and heights.\n     * @param {number} itemHeight The height of the item.\n     * @param {number} firstIndex Index of the first item in viewport.\n     * @param {number} scrollTop The scroll top position.\n     * @return {number} The number of items in view port.\n     */\n    getItemsInViewPort: function(itemHeight, firstIndex, scrollTop) {\n      // This is a bit tricky. We take the minimum of the available items to\n      // show and the number we want to show, so as not to go off the end of the\n      // list. For the number we want to show, we take the maximum of the number\n      // that would fit without a differently-sized lead item, and with one. We\n      // do this so that if the size of the lead item changes without a scroll\n      // event to trigger redrawing the list, we won't end up with empty space.\n      var clientHeight = this.clientHeight;\n      return this.autoExpands_ ? this.dataModel.length : Math.min(\n          this.dataModel.length - firstIndex,\n          Math.max(\n              Math.ceil(clientHeight / itemHeight) + 1,\n              this.countItemsInRange_(firstIndex, scrollTop + clientHeight)));\n    },\n\n    /**\n     * Adds items to the list and {@code newCachedItems}.\n     * @param {number} firstIndex The index of first item, inclusively.\n     * @param {number} lastIndex The index of last item, exclusively.\n     * @param {Object<string, ListItem>} cachedItems Old items cache.\n     * @param {Object<string, ListItem>} newCachedItems New items cache.\n     */\n    addItems: function(firstIndex, lastIndex, cachedItems, newCachedItems) {\n      var listItem;\n      var dataModel = this.dataModel;\n\n      window.l = this;\n      for (var y = firstIndex; y < lastIndex; y++) {\n        var dataItem = dataModel.item(y);\n        listItem = cachedItems[y] || this.createItem(dataItem);\n        listItem.listIndex = y;\n        this.appendChild(listItem);\n        newCachedItems[y] = listItem;\n      }\n    },\n\n    /**\n     * Returns the height of after filler in the list.\n     * @param {number} lastIndex The index of item past the last in viewport.\n     * @param {number} itemHeight The height of the item.\n     * @return {number} The height of after filler.\n     */\n    getAfterFillerHeight: function(lastIndex, itemHeight) {\n      return (this.dataModel.length - lastIndex) * itemHeight;\n    },\n\n    /**\n     * Redraws the viewport.\n     */\n    redraw: function() {\n      if (this.batchCount_ != 0)\n        return;\n\n      var dataModel = this.dataModel;\n      if (!dataModel) {\n        this.textContent = '';\n        return;\n      }\n\n      var scrollTop = this.scrollTop;\n      var clientHeight = this.clientHeight;\n\n      var itemHeight = this.getItemHeight_();\n\n      // We cache the list items since creating the DOM nodes is the most\n      // expensive part of redrawing.\n      var cachedItems = this.cachedItems_ || {};\n      var newCachedItems = {};\n\n      var desiredScrollHeight = this.getHeightsForIndex_(dataModel.length).top;\n\n      var autoExpands = this.autoExpands_;\n      var firstIndex = autoExpands ? 0 : this.getIndexForListOffset_(scrollTop);\n      var itemsInViewPort = this.getItemsInViewPort(itemHeight, firstIndex,\n          scrollTop);\n      var lastIndex = firstIndex + itemsInViewPort;\n\n      this.textContent = '';\n\n      this.beforeFiller_.style.height =\n          this.getHeightsForIndex_(firstIndex).top + 'px';\n      this.appendChild(this.beforeFiller_);\n\n      var sm = this.selectionModel;\n      var leadIndex = sm.leadIndex;\n\n      this.addItems(firstIndex, lastIndex, cachedItems, newCachedItems);\n\n      var afterFillerHeight = this.getAfterFillerHeight(lastIndex, itemHeight);\n      if (leadIndex >= lastIndex)\n        afterFillerHeight += this.leadItemHeight - itemHeight;\n      this.afterFiller_.style.height = afterFillerHeight + 'px';\n      this.appendChild(this.afterFiller_);\n\n      // We don't set the lead or selected properties until after adding all\n      // items, in case they force relayout in response to these events.\n      var listItem = null;\n      if (newCachedItems[leadIndex])\n        newCachedItems[leadIndex].lead = true;\n      for (var y = firstIndex; y < lastIndex; y++) {\n        if (sm.getIndexSelected(y))\n          newCachedItems[y].selected = true;\n        else if (y != leadIndex)\n          listItem = newCachedItems[y];\n      }\n\n      this.firstIndex_ = firstIndex;\n      this.lastIndex_ = lastIndex;\n\n      this.cachedItems_ = newCachedItems;\n\n      // Measure again in case the item height has changed due to a page zoom.\n      //\n      // The measure above is only done the first time but this measure is done\n      // after every redraw. It is done in a timeout so it will not trigger\n      // a reflow (which made the redraw speed 3 times slower on my system).\n      // By using a timeout the measuring will happen later when there is no\n      // need for a reflow.\n      if (listItem) {\n        var list = this;\n        window.setTimeout(function() {\n          if (listItem.parentNode == list) {\n            list.measured_ = measureItem(list, listItem);\n          }\n        });\n      }\n    },\n\n    /**\n     * Invalidates list by removing cached items.\n     */\n    invalidate: function() {\n      this.cachedItems_ = {};\n    },\n\n    /**\n     * Redraws a single item.\n     * @param {number} index The row index to redraw.\n     */\n    redrawItem: function(index) {\n      if (index >= this.firstIndex_ && index < this.lastIndex_) {\n        delete this.cachedItems_[index];\n        this.redraw();\n      }\n    },\n\n    /**\n     * Called when a list item is activated, currently only by a double click\n     * event.\n     * @param {number} index The index of the activated item.\n     */\n    activateItemAtIndex: function(index) {\n    },\n  };\n\n  cr.defineProperty(List, 'disabled', cr.PropertyKind.BOOL_ATTR);\n\n  /**\n   * Whether the list or one of its descendents has focus. This is necessary\n   * because list items can contain controls that can be focused, and for some\n   * purposes (e.g., styling), the list can still be conceptually focused at\n   * that point even though it doesn't actually have the page focus.\n   */\n  cr.defineProperty(List, 'hasElementFocus', cr.PropertyKind.BOOL_ATTR);\n\n  return {\n    List: List\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/js/cr/ui/list_item.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\ncr.define('cr.ui', function() {\n\n  /**\n   * Creates a new list item element.\n   * @param {string} opt_label The text label for the item.\n   * @constructor\n   * @extends {HTMLLIElement}\n   */\n  var ListItem = cr.ui.define('li');\n\n  ListItem.prototype = {\n    __proto__: HTMLLIElement.prototype,\n\n    /**\n     * Plain text label.\n     * @type {string}\n     */\n    get label() {\n      return this.textContent;\n    },\n    set label(label) {\n      this.textContent = label;\n    },\n\n    /**\n     * This item's index in the containing list.\n     * @type {number}\n     */\n    listIndex_: -1,\n\n    /**\n     * Called when an element is decorated as a list item.\n     */\n    decorate: function() {\n      this.setAttribute('role', 'listitem');\n    },\n\n    /**\n     * Called when the selection state of this element changes.\n     */\n    selectionChanged: function() {\n    },\n  };\n\n  /**\n   * Whether the item is selected. Setting this does not update the underlying\n   * selection model. This is only used for display purpose.\n   * @type {boolean}\n   */\n  cr.defineProperty(ListItem, 'selected', cr.PropertyKind.BOOL_ATTR,\n                    function() {\n                      this.selectionChanged();\n                    });\n\n  /**\n   * Whether the item is the lead in a selection. Setting this does not update\n   * the underlying selection model. This is only used for display purpose.\n   * @type {boolean}\n   */\n  cr.defineProperty(ListItem, 'lead', cr.PropertyKind.BOOL_ATTR);\n\n  /**\n   * This item's index in the containing list.\n   * @type {number}\n   */\n  cr.defineProperty(ListItem, 'listIndex');\n\n  return {\n    ListItem: ListItem\n  };\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/js/cr/ui/list_selection_controller.js",
    "content": "// Copyright (c) 2010 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\ncr.define('cr.ui', function() {\n  /**\n   * Creates a selection controller that is to be used with lists. This is\n   * implemented for vertical lists but changing the behavior for horizontal\n   * lists or icon views is a matter of overriding {@code getIndexBefore},\n   * {@code getIndexAfter}, {@code getIndexAbove} as well as\n   * {@code getIndexBelow}.\n   *\n   * @param {cr.ui.ListSelectionModel} selectionModel The selection model to\n   *     interact with.\n   *\n   * @constructor\n   * @extends {!cr.EventTarget}\n   */\n  function ListSelectionController(selectionModel) {\n    this.selectionModel_ = selectionModel;\n  }\n\n  ListSelectionController.prototype = {\n\n    /**\n     * The selection model we are interacting with.\n     * @type {cr.ui.ListSelectionModel}\n     */\n    get selectionModel() {\n      return this.selectionModel_;\n    },\n\n    /**\n     * Returns the index below (y axis) the given element.\n     * @param {number} index The index to get the index below.\n     * @return {number} The index below or -1 if not found.\n     */\n    getIndexBelow: function(index) {\n      if (index == this.getLastIndex())\n        return -1;\n      return index + 1;\n    },\n\n    /**\n     * Returns the index above (y axis) the given element.\n     * @param {number} index The index to get the index above.\n     * @return {number} The index below or -1 if not found.\n     */\n    getIndexAbove: function(index) {\n      return index - 1;\n    },\n\n    /**\n     * Returns the index before (x axis) the given element. This returns -1\n     * by default but override this for icon view and horizontal selection\n     * models.\n     *\n     * @param {number} index The index to get the index before.\n     * @return {number} The index before or -1 if not found.\n     */\n    getIndexBefore: function(index) {\n      return -1;\n    },\n\n    /**\n     * Returns the index after (x axis) the given element. This returns -1\n     * by default but override this for icon view and horizontal selection\n     * models.\n     *\n     * @param {number} index The index to get the index after.\n     * @return {number} The index after or -1 if not found.\n     */\n    getIndexAfter: function(index) {\n      return -1;\n    },\n\n    /**\n     * Returns the next list index. This is the next logical and should not\n     * depend on any kind of layout of the list.\n     * @param {number} index The index to get the next index for.\n     * @return {number} The next index or -1 if not found.\n     */\n    getNextIndex: function(index) {\n      if (index == this.getLastIndex())\n        return -1;\n      return index + 1;\n    },\n\n    /**\n     * Returns the prevous list index. This is the previous logical and should\n     * not depend on any kind of layout of the list.\n     * @param {number} index The index to get the previous index for.\n     * @return {number} The previous index or -1 if not found.\n     */\n    getPreviousIndex: function(index) {\n      return index - 1;\n    },\n\n    /**\n     * @return {number} The first index.\n     */\n    getFirstIndex: function() {\n      return 0;\n    },\n\n    /**\n     * @return {number} The last index.\n     */\n    getLastIndex: function() {\n      return this.selectionModel.length - 1;\n    },\n\n    /**\n     * Called by the view when the user does a mousedown or mouseup on the list.\n     * @param {!Event} e The browser mousedown event.\n     * @param {number} index The index that was under the mouse pointer, -1 if\n     *     none.\n     */\n    handleMouseDownUp: function(e, index) {\n      var sm = this.selectionModel;\n      var anchorIndex = sm.anchorIndex;\n      var isDown = e.type == 'mousedown';\n\n      sm.beginChange();\n\n      if (index == -1) {\n        // On Mac we always clear the selection if the user clicks a blank area.\n        // On Windows, we only clear the selection if neither Shift nor Ctrl are\n        // pressed.\n        if (cr.isMac) {\n          sm.leadIndex = sm.anchorIndex = -1;\n          if (sm.multiple)\n            sm.unselectAll();\n        } else if (!isDown && !e.shiftKey && !e.ctrlKey)\n          // Keep anchor and lead indexes. Note that this is intentionally\n          // different than on the Mac.\n          if (sm.multiple)\n            sm.unselectAll();\n      } else {\n        if (sm.multiple && (cr.isMac ? e.metaKey :\n                                       (e.ctrlKey && !e.shiftKey))) {\n          // Selection is handled at mouseUp on windows/linux, mouseDown on mac.\n          if (cr.isMac? isDown : !isDown) {\n            // Toggle the current one and make it anchor index.\n            sm.setIndexSelected(index, !sm.getIndexSelected(index));\n            sm.leadIndex = index;\n            sm.anchorIndex = index;\n          }\n        } else if (e.shiftKey && anchorIndex != -1 && anchorIndex != index) {\n          // Shift is done in mousedown.\n          if (isDown) {\n            sm.unselectAll();\n            sm.leadIndex = index;\n            if (sm.multiple)\n              sm.selectRange(anchorIndex, index);\n            else\n              sm.setIndexSelected(index, true);\n          }\n        } else {\n          // Right click for a context menu needs to not clear the selection.\n          var isRightClick = e.button == 2;\n\n          // If the index is selected this is handled in mouseup.\n          var indexSelected = sm.getIndexSelected(index);\n          if ((indexSelected && !isDown || !indexSelected && isDown) &&\n              !(indexSelected && isRightClick)) {\n            sm.unselectAll();\n            sm.setIndexSelected(index, true);\n            sm.leadIndex = index;\n            sm.anchorIndex = index;\n          }\n        }\n      }\n\n      sm.endChange();\n    },\n\n    /**\n     * Called by the view when it receives a keydown event.\n     * @param {Event} e The keydown event.\n     */\n    handleKeyDown: function(e) {\n      const SPACE_KEY_CODE = 32;\n      var tagName = e.target.tagName;\n      // If focus is in an input field of some kind, only handle navigation keys\n      // that aren't likely to conflict with input interaction (e.g., text\n      // editing, or changing the value of a checkbox or select).\n      if (tagName == 'INPUT') {\n        var inputType = e.target.type;\n        // Just protect space (for toggling) for checkbox and radio.\n        if (inputType == 'checkbox' || inputType == 'radio') {\n          if (e.keyCode == SPACE_KEY_CODE)\n            return;\n        // Protect all but the most basic navigation commands in anything else.\n        } else if (e.key != 'ArrowUp' && e.key != 'ArrowDown') {\n          return;\n        }\n      }\n      // Similarly, don't interfere with select element handling.\n      if (tagName == 'SELECT')\n        return;\n\n      var sm = this.selectionModel;\n      var newIndex = -1;\n      var leadIndex = sm.leadIndex;\n      var prevent = true;\n\n      // Ctrl/Meta+A\n      if (sm.multiple && e.keyCode == 65 &&\n          (cr.isMac && e.metaKey || !cr.isMac && e.ctrlKey)) {\n        sm.selectAll();\n        e.preventDefault();\n        return;\n      }\n\n      // Space\n      if (e.keyCode == SPACE_KEY_CODE) {\n        if (leadIndex != -1) {\n          var selected = sm.getIndexSelected(leadIndex);\n          if (e.ctrlKey || !selected) {\n            sm.setIndexSelected(leadIndex, !selected || !sm.multiple);\n            return;\n          }\n        }\n      }\n\n      switch (e.key) {\n        case 'Home':\n          newIndex = this.getFirstIndex();\n          break;\n        case 'End':\n          newIndex = this.getLastIndex();\n          break;\n        case 'ArrowUp':\n          newIndex = leadIndex == -1 ?\n              this.getLastIndex() : this.getIndexAbove(leadIndex);\n          break;\n        case 'ArrowDown':\n          newIndex = leadIndex == -1 ?\n              this.getFirstIndex() : this.getIndexBelow(leadIndex);\n          break;\n        case 'ArrrowLeft':\n          newIndex = leadIndex == -1 ?\n              this.getLastIndex() : this.getIndexBefore(leadIndex);\n          break;\n        case 'ArrowRight':\n          newIndex = leadIndex == -1 ?\n              this.getFirstIndex() : this.getIndexAfter(leadIndex);\n          break;\n        default:\n          prevent = false;\n      }\n\n      if (newIndex != -1) {\n        sm.beginChange();\n\n        sm.leadIndex = newIndex;\n        if (e.shiftKey) {\n          var anchorIndex = sm.anchorIndex;\n          if (sm.multiple)\n            sm.unselectAll();\n          if (anchorIndex == -1) {\n            sm.setIndexSelected(newIndex, true);\n            sm.anchorIndex = newIndex;\n          } else {\n            sm.selectRange(anchorIndex, newIndex);\n          }\n        } else if (e.ctrlKey && !cr.isMac) {\n          // Setting the lead index is done above.\n          // Mac does not allow you to change the lead.\n        } else {\n          if (sm.multiple)\n            sm.unselectAll();\n          sm.setIndexSelected(newIndex, true);\n          sm.anchorIndex = newIndex;\n        }\n\n        sm.endChange();\n\n        if (prevent)\n          e.preventDefault();\n      }\n    }\n  };\n\n  return {\n    ListSelectionController: ListSelectionController\n  };\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/js/cr/ui/list_selection_model.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\ncr.define('cr.ui', function() {\n  /** @const */ var EventTarget = cr.EventTarget;\n\n  /**\n   * Creates a new selection model that is to be used with lists.\n   *\n   * @param {number=} opt_length The number items in the selection.\n   *\n   * @constructor\n   * @extends {!cr.EventTarget}\n   */\n  function ListSelectionModel(opt_length) {\n    this.length_ = opt_length || 0;\n    // Even though selectedIndexes_ is really a map we use an array here to get\n    // iteration in the order of the indexes.\n    this.selectedIndexes_ = [];\n  }\n\n  ListSelectionModel.prototype = {\n    __proto__: EventTarget.prototype,\n\n    /**\n     * The number of items in the model.\n     * @type {number}\n     */\n    get length() {\n      return this.length_;\n    },\n\n    /**\n     * @type {!Array} The selected indexes.\n     */\n    get selectedIndexes() {\n      return Object.keys(this.selectedIndexes_).map(Number);\n    },\n    set selectedIndexes(selectedIndexes) {\n      this.beginChange();\n      this.unselectAll();\n      for (var i = 0; i < selectedIndexes.length; i++) {\n        this.setIndexSelected(selectedIndexes[i], true);\n      }\n      if (selectedIndexes.length) {\n        this.leadIndex = this.anchorIndex = selectedIndexes[0];\n      } else {\n        this.leadIndex = this.anchorIndex = -1;\n      }\n      this.endChange();\n    },\n\n    /**\n     * Convenience getter which returns the first selected index.\n     * @type {number}\n     */\n    get selectedIndex() {\n      for (var i in this.selectedIndexes_) {\n        return Number(i);\n      }\n      return -1;\n    },\n    set selectedIndex(selectedIndex) {\n      this.beginChange();\n      this.unselectAll();\n      if (selectedIndex != -1) {\n        this.selectedIndexes = [selectedIndex];\n      } else {\n        this.leadIndex = this.anchorIndex = -1;\n      }\n      this.endChange();\n    },\n\n    /**\n     * Selects a range of indexes, starting with {@code start} and ends with\n     * {@code end}.\n     * @param {number} start The first index to select.\n     * @param {number} end The last index to select.\n     */\n    selectRange: function(start, end) {\n      // Swap if starts comes after end.\n      if (start > end) {\n        var tmp = start;\n        start = end;\n        end = tmp;\n      }\n\n      this.beginChange();\n\n      for (var index = start; index != end; index++) {\n        this.setIndexSelected(index, true);\n      }\n      this.setIndexSelected(end, true);\n\n      this.endChange();\n    },\n\n    /**\n     * Selects all indexes.\n     */\n    selectAll: function() {\n      this.selectRange(0, this.length - 1);\n    },\n\n    /**\n     * Clears the selection\n     */\n    clear: function() {\n      this.beginChange();\n      this.length_ = 0;\n      this.anchorIndex = this.leadIndex = -1;\n      this.unselectAll();\n      this.endChange();\n    },\n\n    /**\n     * Unselects all selected items.\n     */\n    unselectAll: function() {\n      this.beginChange();\n      for (var i in this.selectedIndexes_) {\n        this.setIndexSelected(i, false);\n      }\n      this.endChange();\n    },\n\n    /**\n     * Sets the selected state for an index.\n     * @param {number} index The index to set the selected state for.\n     * @param {boolean} b Whether to select the index or not.\n     */\n    setIndexSelected: function(index, b) {\n      var oldSelected = index in this.selectedIndexes_;\n      if (oldSelected == b)\n        return;\n\n      if (b)\n        this.selectedIndexes_[index] = true;\n      else\n        delete this.selectedIndexes_[index];\n\n      this.beginChange();\n\n      // Changing back?\n      if (index in this.changedIndexes_ && this.changedIndexes_[index] == !b) {\n        delete this.changedIndexes_[index];\n      } else {\n        this.changedIndexes_[index] = b;\n      }\n\n      // End change dispatches an event which in turn may update the view.\n      this.endChange();\n    },\n\n    /**\n     * Whether a given index is selected or not.\n     * @param {number} index The index to check.\n     * @return {boolean} Whether an index is selected.\n     */\n    getIndexSelected: function(index) {\n      return index in this.selectedIndexes_;\n    },\n\n    /**\n     * This is used to begin batching changes. Call {@code endChange} when you\n     * are done making changes.\n     */\n    beginChange: function() {\n      if (!this.changeCount_) {\n        this.changeCount_ = 0;\n        this.changedIndexes_ = {};\n      }\n      this.changeCount_++;\n    },\n\n    /**\n     * Call this after changes are done and it will dispatch a change event if\n     * any changes were actually done.\n     */\n    endChange: function() {\n      this.changeCount_--;\n      if (!this.changeCount_) {\n        var indexes = Object.keys(this.changedIndexes_);\n        if (indexes.length) {\n          var e = new Event('change');\n          e.changes = indexes.map(function(index) {\n            return {\n              index: index,\n              selected: this.changedIndexes_[index]\n            };\n          }, this);\n          this.dispatchEvent(e);\n        }\n        this.changedIndexes_ = {};\n      }\n    },\n\n    leadIndex_: -1,\n\n    /**\n     * The leadIndex is used with multiple selection and it is the index that\n     * the user is moving using the arrow keys.\n     * @type {number}\n     */\n    get leadIndex() {\n      return this.leadIndex_;\n    },\n    set leadIndex(leadIndex) {\n      var li = Math.max(-1, Math.min(this.length_ - 1, leadIndex));\n      if (li != this.leadIndex_) {\n        var oldLeadIndex = this.leadIndex_;\n        this.leadIndex_ = li;\n        cr.dispatchPropertyChange(this, 'leadIndex', li, oldLeadIndex);\n      }\n    },\n\n    anchorIndex_: -1,\n\n    /**\n     * The anchorIndex is used with multiple selection.\n     * @type {number}\n     */\n    get anchorIndex() {\n      return this.anchorIndex_;\n    },\n    set anchorIndex(anchorIndex) {\n      var ai = Math.max(-1, Math.min(this.length_ - 1, anchorIndex));\n      if (ai != this.anchorIndex_) {\n        var oldAnchorIndex = this.anchorIndex_;\n        this.anchorIndex_ = ai;\n        cr.dispatchPropertyChange(this, 'anchorIndex', ai, oldAnchorIndex);\n      }\n    },\n\n    /**\n     * Whether the selection model supports multiple selected items.\n     * @type {boolean}\n     */\n    get multiple() {\n      return true;\n    },\n\n    /**\n     * Adjusts the selection after reordering of items in the table.\n     * @param {!Array<number>} permutation The reordering permutation.\n     */\n    adjustToReordering: function(permutation) {\n      var oldLeadIndex = this.leadIndex;\n\n      var oldSelectedIndexes = this.selectedIndexes;\n      this.selectedIndexes = oldSelectedIndexes.map(function(oldIndex) {\n        return permutation[oldIndex];\n      }).filter(function(index) {\n        return index != -1;\n      });\n\n      if (oldLeadIndex != -1)\n        this.leadIndex = permutation[oldLeadIndex];\n    },\n\n    /**\n     * Adjusts selection model length.\n     * @param {number} length New selection model length.\n     */\n    adjustLength: function(length) {\n      this.length_ = length;\n    }\n  };\n\n  return {\n    ListSelectionModel: ListSelectionModel\n  };\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/js/cr/ui/list_single_selection_model.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\ncr.define('cr.ui', function() {\n  /** @const */ var EventTarget = cr.EventTarget;\n\n  /**\n   * Creates a new selection model that is to be used with lists. This only\n   * allows a single index to be selected.\n   *\n   * @param {number=} opt_length The number items in the selection.\n   *\n   * @constructor\n   * @extends {!cr.EventTarget}\n   */\n  function ListSingleSelectionModel(opt_length) {\n    this.length_ = opt_length || 0;\n    this.selectedIndex = -1;\n  }\n\n  ListSingleSelectionModel.prototype = {\n    __proto__: EventTarget.prototype,\n\n    /**\n     * The number of items in the model.\n     * @type {number}\n     */\n    get length() {\n      return this.length_;\n    },\n\n    /**\n     * @type {!Array} The selected indexes.\n     */\n    get selectedIndexes() {\n      var i = this.selectedIndex;\n      return i != -1 ? [this.selectedIndex] : [];\n    },\n\n    /**\n     * Convenience getter which returns the first selected index.\n     * @type {number}\n     */\n    get selectedIndex() {\n      return this.selectedIndex_;\n    },\n    set selectedIndex(selectedIndex) {\n      var oldSelectedIndex = this.selectedIndex;\n      var i = Math.max(-1, Math.min(this.length_ - 1, selectedIndex));\n\n      if (i != oldSelectedIndex) {\n        this.beginChange();\n        this.selectedIndex_ = i\n        this.endChange();\n      }\n    },\n\n    /**\n     * Selects a range of indexes, starting with {@code start} and ends with\n     * {@code end}.\n     * @param {number} start The first index to select.\n     * @param {number} end The last index to select.\n     */\n    selectRange: function(start, end) {\n      // Only select first index.\n      this.selectedIndex = Math.min(start, end);\n    },\n\n    /**\n     * Selects all indexes.\n     */\n    selectAll: function() {\n      // Select all is not allowed on a single selection model\n    },\n\n    /**\n     * Clears the selection\n     */\n    clear: function() {\n      this.beginChange();\n      this.length_ = 0;\n      this.selectedIndex = this.anchorIndex = this.leadIndex = -1;\n      this.endChange();\n    },\n\n    /**\n     * Unselects all selected items.\n     */\n    unselectAll: function() {\n      this.selectedIndex = -1;\n    },\n\n    /**\n     * Sets the selected state for an index.\n     * @param {number} index The index to set the selected state for.\n     * @param {boolean} b Whether to select the index or not.\n     */\n    setIndexSelected: function(index, b) {\n      // Only allow selection\n      var oldSelected = index == this.selectedIndex_;\n      if (oldSelected == b)\n        return;\n\n      if (b)\n        this.selectedIndex = index;\n      else if (index == this.selectedIndex_)\n        this.selectedIndex = -1;\n    },\n\n    /**\n     * Whether a given index is selected or not.\n     * @param {number} index The index to check.\n     * @return {boolean} Whether an index is selected.\n     */\n    getIndexSelected: function(index) {\n      return index == this.selectedIndex_;\n    },\n\n    /**\n     * This is used to begin batching changes. Call {@code endChange} when you\n     * are done making changes.\n     */\n    beginChange: function() {\n      if (!this.changeCount_) {\n        this.changeCount_ = 0;\n        this.selectedIndexBefore_ = this.selectedIndex_;\n      }\n      this.changeCount_++;\n    },\n\n    /**\n     * Call this after changes are done and it will dispatch a change event if\n     * any changes were actually done.\n     */\n    endChange: function() {\n      this.changeCount_--;\n      if (!this.changeCount_) {\n        if (this.selectedIndexBefore_ != this.selectedIndex_) {\n          var e = new Event('change');\n          var indexes = [this.selectedIndexBefore_, this.selectedIndex_];\n          e.changes = indexes.filter(function(index) {\n            return index != -1;\n          }).map(function(index) {\n            return {\n              index: index,\n              selected: index == this.selectedIndex_\n            };\n          }, this);\n          this.dispatchEvent(e);\n        }\n      }\n    },\n\n    leadIndex_: -1,\n\n    /**\n     * The leadIndex is used with multiple selection and it is the index that\n     * the user is moving using the arrow keys.\n     * @type {number}\n     */\n    get leadIndex() {\n      return this.leadIndex_;\n    },\n    set leadIndex(leadIndex) {\n      var li = Math.max(-1, Math.min(this.length_ - 1, leadIndex));\n      if (li != this.leadIndex_) {\n        var oldLeadIndex = this.leadIndex_;\n        this.leadIndex_ = li;\n        cr.dispatchPropertyChange(this, 'leadIndex', li, oldLeadIndex);\n        cr.dispatchPropertyChange(this, 'anchorIndex', li, oldLeadIndex);\n      }\n    },\n\n    /**\n     * The anchorIndex is used with multiple selection.\n     * @type {number}\n     */\n    get anchorIndex() {\n      return this.leadIndex;\n    },\n    set anchorIndex(anchorIndex) {\n      this.leadIndex = anchorIndex;\n    },\n\n    /**\n     * Whether the selection model supports multiple selected items.\n     * @type {boolean}\n     */\n    get multiple() {\n      return false;\n    },\n\n    /**\n     * Adjusts the selection after reordering of items in the table.\n     * @param {!Array<number>} permutation The reordering permutation.\n     */\n    adjustToReordering: function(permutation) {\n      if (this.leadIndex != -1)\n        this.leadIndex = permutation[this.leadIndex];\n\n      var oldSelectedIndex = this.selectedIndex;\n      if (oldSelectedIndex != -1) {\n        this.selectedIndex = permutation[oldSelectedIndex];\n      }\n    },\n\n    /**\n     * Adjusts selection model length.\n     * @param {number} length New selection model length.\n     */\n    adjustLength: function(length) {\n      this.length_ = length;\n    }\n  };\n\n  return {\n    ListSingleSelectionModel: ListSingleSelectionModel\n  };\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/js/cr/ui.js",
    "content": "// Copyright (c) 2010 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\ncr.define('cr.ui', function() {\n\n  /**\n   * Decorates elements as an instance of a class.\n   * @param {string|!Element} source The way to find the element(s) to decorate.\n   *     If this is a string then {@code querySeletorAll} is used to find the\n   *     elements to decorate.\n   * @param {!Function} constr The constructor to decorate with. The constr\n   *     needs to have a {@code decorate} function.\n   */\n  function decorate(source, constr) {\n    var elements;\n    if (typeof source == 'string')\n      elements = cr.doc.querySelectorAll(source);\n    else\n      elements = [source];\n\n    for (var i = 0, el; el = elements[i]; i++) {\n      if (!(el instanceof constr))\n        constr.decorate(el);\n    }\n  }\n\n  /**\n   * Helper function for creating new element for define.\n   */\n  function createElementHelper(tagName, opt_bag) {\n    // Allow passing in ownerDocument to create in a different document.\n    var doc;\n    if (opt_bag && opt_bag.ownerDocument)\n      doc = opt_bag.ownerDocument;\n    else\n      doc = cr.doc;\n    return doc.createElement(tagName);\n  }\n\n  /**\n   * Creates the constructor for a UI element class.\n   *\n   * Usage:\n   * <pre>\n   * var List = cr.ui.define('list');\n   * List.prototype = {\n   *   __proto__: HTMLUListElement.prototype,\n   *   decorate: function() {\n   *     ...\n   *   },\n   *   ...\n   * };\n   * </pre>\n   *\n   * @param {string|Function} tagNameOrFunction The tagName or\n   *     function to use for newly created elements. If this is a function it\n   *     needs to return a new element when called.\n   * @return {function(Object=):Element} The constructor function which takes\n   *     an optional property bag. The function also has a static\n   *     {@code decorate} method added to it.\n   */\n  function define(tagNameOrFunction) {\n    var createFunction, tagName;\n    if (typeof tagNameOrFunction == 'function') {\n      createFunction = tagNameOrFunction;\n      tagName = '';\n    } else {\n      createFunction = createElementHelper;\n      tagName = tagNameOrFunction;\n    }\n\n    /**\n     * Creates a new UI element constructor.\n     * @param {Object=} opt_propertyBag Optional bag of properties to set on the\n     *     object after created. The property {@code ownerDocument} is special\n     *     cased and it allows you to create the element in a different\n     *     document than the default.\n     * @constructor\n     */\n    function f(opt_propertyBag) {\n      var el = createFunction(tagName, opt_propertyBag);\n      f.decorate(el);\n      for (var propertyName in opt_propertyBag) {\n        el[propertyName] = opt_propertyBag[propertyName];\n      }\n      return el;\n    }\n\n    /**\n     * Decorates an element as a UI element class.\n     * @param {!Element} el The element to decorate.\n     */\n    f.decorate = function(el) {\n      el.__proto__ = f.prototype;\n      el.decorate();\n    };\n\n    return f;\n  }\n\n  /**\n   * Input elements do not grow and shrink with their content. This is a simple\n   * (and not very efficient) way of handling shrinking to content with support\n   * for min width and limited by the width of the parent element.\n   * @param {HTMLElement} el The element to limit the width for.\n   * @param {number} parentEl The parent element that should limit the size.\n   * @param {number} min The minimum width.\n   */\n  function limitInputWidth(el, parentEl, min) {\n    // Needs a size larger than borders\n    el.style.width = '10px';\n    var doc = el.ownerDocument;\n    var win = doc.defaultView;\n    var computedStyle = win.getComputedStyle(el);\n    var parentComputedStyle = win.getComputedStyle(parentEl);\n    var rtl = computedStyle.direction == 'rtl';\n\n    // To get the max width we get the width of the treeItem minus the position\n    // of the input.\n    var inputRect = el.getBoundingClientRect();  // box-sizing\n    var parentRect = parentEl.getBoundingClientRect();\n    var startPos = rtl ? parentRect.right - inputRect.right :\n        inputRect.left - parentRect.left;\n\n    // Add up border and padding of the input.\n    var inner = parseInt(computedStyle.borderLeftWidth, 10) +\n        parseInt(computedStyle.paddingLeft, 10) +\n        parseInt(computedStyle.paddingRight, 10) +\n        parseInt(computedStyle.borderRightWidth, 10);\n\n    // We also need to subtract the padding of parent to prevent it to overflow.\n    var parentPadding = rtl ? parseInt(parentComputedStyle.paddingLeft, 10) :\n        parseInt(parentComputedStyle.paddingRight, 10);\n\n    var max = parentEl.clientWidth - startPos - inner - parentPadding;\n\n    function limit() {\n      if (el.scrollWidth > max) {\n        el.style.width = max + 'px';\n      } else {\n        el.style.width = 0;\n        var sw = el.scrollWidth;\n        if (sw < min) {\n          el.style.width = min + 'px';\n        } else {\n          el.style.width = sw + 'px';\n        }\n      }\n    }\n\n    el.addEventListener('input', limit);\n    limit();\n  }\n\n  return {\n    decorate: decorate,\n    define: define,\n    limitInputWidth: limitInputWidth\n  };\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/js/cr.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nconst cr = (function() {\n\n  /**\n   * Whether we are using a Mac or not.\n   * @type {boolean}\n   */\n  const isMac = /Mac/.test(navigator.platform);\n\n  /**\n   * Whether this is on the Windows platform or not.\n   * @type {boolean}\n   */\n  const isWindows = /Win/.test(navigator.platform);\n\n  /**\n   * Whether this is on chromeOS or not.\n   * @type {boolean}\n   */\n  const isChromeOS = /CrOS/.test(navigator.userAgent);\n\n  /**\n   * Whether this is on vanilla Linux (not chromeOS).\n   * @type {boolean}\n   */\n  const isLinux = /Linux/.test(navigator.userAgent);\n\n  /**\n   * Sets the os and toolkit attributes in the <html> element so that platform\n   * specific css rules can be applied.\n   */\n  function enablePlatformSpecificCSSRules() {\n    if (isMac)\n      doc.documentElement.setAttribute('os', 'mac');\n    if (isWindows)\n      doc.documentElement.setAttribute('os', 'windows');\n    if (isChromeOS)\n      doc.documentElement.setAttribute('os', 'chromeos');\n    if (isLinux)\n      doc.documentElement.setAttribute('os', 'linux');\n  }\n\n  /**\n   * Builds an object structure for the provided namespace path,\n   * ensuring that names that already exist are not overwritten. For\n   * example:\n   * \"a.b.c\" -> a = {};a.b={};a.b.c={};\n   * @param {string} name Name of the object that this file defines.\n   * @param {*=} opt_object The object to expose at the end of the path.\n   * @param {Object=} opt_objectToExportTo The object to add the path to;\n   *     default is {@code window}.\n   * @private\n   */\n  function exportPath(name, opt_object, opt_objectToExportTo) {\n    var parts = name.split('.');\n    var cur = opt_objectToExportTo || window /* global */;\n\n    for (var part; parts.length && (part = parts.shift());) {\n      if (!parts.length && opt_object !== undefined) {\n        // last part and we have an object; use it\n        cur[part] = opt_object;\n      } else if (part in cur) {\n        cur = cur[part];\n      } else {\n        cur = cur[part] = {};\n      }\n    }\n    return cur;\n  };\n\n  /**\n   * Fires a property change event on the target.\n   * @param {EventTarget} target The target to dispatch the event on.\n   * @param {string} propertyName The name of the property that changed.\n   * @param {*} newValue The new value for the property.\n   * @param {*} oldValue The old value for the property.\n   */\n  function dispatchPropertyChange(target, propertyName, newValue, oldValue) {\n    var e = new CrEvent(propertyName + 'Change');\n    e.propertyName = propertyName;\n    e.newValue = newValue;\n    e.oldValue = oldValue;\n    target.dispatchEvent(e);\n  }\n\n  /**\n   * The kind of property to define in {@code defineProperty}.\n   * @enum {number}\n   */\n  const PropertyKind = {\n    /**\n     * Plain old JS property where the backing data is stored as a \"private\"\n     * field on the object.\n     */\n    JS: 'js',\n\n    /**\n     * The property backing data is stored as an attribute on an element.\n     */\n    ATTR: 'attr',\n\n    /**\n     * The property backing data is stored as an attribute on an element. If the\n     * element has the attribute then the value is true.\n     */\n    BOOL_ATTR: 'boolAttr'\n  };\n\n  /**\n   * Helper function for defineProperty that returns the getter to use for the\n   * property.\n   * @param {string} name\n   * @param {cr.PropertyKind} kind\n   * @return {function():*} The getter for the property.\n   */\n  function getGetter(name, kind) {\n    switch (kind) {\n      case PropertyKind.JS:\n        var privateName = name + '_';\n        return function() {\n          return this[privateName];\n        };\n      case PropertyKind.ATTR:\n        return function() {\n          return this.getAttribute(name);\n        };\n      case PropertyKind.BOOL_ATTR:\n        return function() {\n          return this.hasAttribute(name);\n        };\n    }\n  }\n\n  /**\n   * Helper function for defineProperty that returns the setter of the right\n   * kind.\n   * @param {string} name The name of the property we are defining the setter\n   *     for.\n   * @param {cr.PropertyKind} kind The kind of property we are getting the\n   *     setter for.\n   * @param {function(*):void} opt_setHook A function to run after the property\n   *     is set, but before the propertyChange event is fired.\n   * @return {function(*):void} The function to use as a setter.\n   */\n  function getSetter(name, kind, opt_setHook) {\n    switch (kind) {\n      case PropertyKind.JS:\n        var privateName = name + '_';\n        return function(value) {\n          var oldValue = this[privateName];\n          if (value !== oldValue) {\n            this[privateName] = value;\n            if (opt_setHook)\n              opt_setHook.call(this, value, oldValue);\n            dispatchPropertyChange(this, name, value, oldValue);\n          }\n        };\n\n      case PropertyKind.ATTR:\n        return function(value) {\n          var oldValue = this[name];\n          if (value !== oldValue) {\n            if (value == undefined)\n              this.removeAttribute(name);\n            else\n              this.setAttribute(name, value);\n            if (opt_setHook)\n              opt_setHook.call(this, value, oldValue);\n            dispatchPropertyChange(this, name, value, oldValue);\n          }\n        };\n\n      case PropertyKind.BOOL_ATTR:\n        return function(value) {\n          var oldValue = this[name];\n          if (value !== oldValue) {\n            if (value)\n              this.setAttribute(name, name);\n            else\n              this.removeAttribute(name);\n            if (opt_setHook)\n              opt_setHook.call(this, value, oldValue);\n            dispatchPropertyChange(this, name, value, oldValue);\n          }\n        };\n    }\n  }\n\n  /**\n   * Defines a property on an object. When the setter changes the value a\n   * property change event with the type {@code name + 'Change'} is fired.\n   * @param {!Object} obj The object to define the property for.\n   * @param {string} name The name of the property.\n   * @param {cr.PropertyKind=} opt_kind What kind of underlying storage to use.\n   * @param {function(*):void} opt_setHook A function to run after the\n   *     property is set, but before the propertyChange event is fired.\n   */\n  function defineProperty(obj, name, opt_kind, opt_setHook) {\n    if (typeof obj == 'function')\n      obj = obj.prototype;\n\n    var kind = opt_kind || PropertyKind.JS;\n\n    if (!obj.__lookupGetter__(name)) {\n      obj.__defineGetter__(name, getGetter(name, kind));\n    }\n\n    if (!obj.__lookupSetter__(name)) {\n      obj.__defineSetter__(name, getSetter(name, kind, opt_setHook));\n    }\n  }\n\n  /**\n   * Counter for use with createUid\n   */\n  var uidCounter = 1;\n\n  /**\n   * @return {number} A new unique ID.\n   */\n  function createUid() {\n    return uidCounter++;\n  }\n\n  /**\n   * Returns a unique ID for the item. This mutates the item so it needs to be\n   * an object\n   * @param {!Object} item The item to get the unique ID for.\n   * @return {number} The unique ID for the item.\n   */\n  function getUid(item) {\n    if (item.hasOwnProperty('uid'))\n      return item.uid;\n    return item.uid = createUid();\n  }\n\n  /**\n   * Dispatches a simple event on an event target.\n   * @param {!EventTarget} target The event target to dispatch the event on.\n   * @param {string} type The type of the event.\n   * @param {boolean=} opt_bubbles Whether the event bubbles or not.\n   * @param {boolean=} opt_cancelable Whether the default action of the event\n   *     can be prevented. Default is true.\n   * @return {boolean} If any of the listeners called {@code preventDefault}\n   *     during the dispatch this will return false.\n   */\n  function dispatchSimpleEvent(target, type, opt_bubbles, opt_cancelable) {\n    var e = new Event(type, {\n      bubbles: opt_bubbles,\n      cancelable: opt_cancelable === undefined || opt_cancelable\n    });\n    return target.dispatchEvent(e);\n  }\n\n  /**\n   * @param {string} name\n   * @param {!Function} fun\n   */\n  function define(name, fun) {\n    var obj = exportPath(name);\n    var exports = fun();\n    for (var propertyName in exports) {\n      // Maybe we should check the prototype chain here? The current usage\n      // pattern is always using an object literal so we only care about own\n      // properties.\n      var propertyDescriptor = Object.getOwnPropertyDescriptor(exports,\n                                                               propertyName);\n      if (propertyDescriptor)\n        Object.defineProperty(obj, propertyName, propertyDescriptor);\n    }\n  }\n\n  /**\n   * Document used for various document related operations.\n   * @type {!Document}\n   */\n  var doc = document;\n\n\n  /**\n   * Allows you to run func in the context of a different document.\n   * @param {!Document} document The document to use.\n   * @param {function():*} func The function to call.\n   */\n  function withDoc(document, func) {\n    var oldDoc = doc;\n    doc = document;\n    try {\n      func();\n    } finally {\n      doc = oldDoc;\n    }\n  }\n\n  /**\n   * Adds a {@code getInstance} static method that always return the same\n   * instance object.\n   * @param {!Function} ctor The constructor for the class to add the static\n   *     method to.\n   */\n  function addSingletonGetter(ctor) {\n    ctor.getInstance = function() {\n      return ctor.instance_ || (ctor.instance_ = new ctor());\n    };\n  }\n\n  return {\n    addSingletonGetter: addSingletonGetter,\n    isChromeOS: isChromeOS,\n    isMac: isMac,\n    isWindows: isWindows,\n    isLinux: isLinux,\n    enablePlatformSpecificCSSRules: enablePlatformSpecificCSSRules,\n    define: define,\n    defineProperty: defineProperty,\n    PropertyKind: PropertyKind,\n    createUid: createUid,\n    getUid: getUid,\n    dispatchSimpleEvent: dispatchSimpleEvent,\n    dispatchPropertyChange: dispatchPropertyChange,\n\n    /**\n     * The document that we are currently using.\n     * @type {!Document}\n     */\n    get doc() {\n      return doc;\n    },\n    withDoc: withDoc\n  };\n})();\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/domui/js/util.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * The global object.\n * @type {!Object}\n */\nconst global = this;\n\n/**\n * Alias for document.getElementById.\n * @param {string} id The ID of the element to find.\n * @return {HTMLElement} The found element or null if not found.\n */\nfunction $(id) {\n  return document.getElementById(id);\n}\n\n/**\n * Calls chrome.send with a callback and restores the original afterwards.\n * @param {string} name The name of the message to send.\n * @param {!Array} params The parameters to send.\n * @param {string} callbackName The name of the function that the backend calls.\n * @param {!Function} The function to call.\n */\nfunction chromeSend(name, params, callbackName, callback) {\n  var old = global[callbackName];\n  global[callbackName] = function() {\n    // restore\n    global[callbackName] = old;\n\n    var args = Array.prototype.slice.call(arguments);\n    return callback.apply(global, args);\n  };\n  chrome.send(name, params);\n}\n\n/**\n * Generates a CSS url string.\n * @param {string} s The URL to generate the CSS url for.\n * @return {string} The CSS url string.\n */\nfunction url(s) {\n  // http://www.w3.org/TR/css3-values/#uris\n  // Parentheses, commas, whitespace characters, single quotes (') and double\n  // quotes (\") appearing in a URI must be escaped with a backslash\n  var s2 = s.replace(/(\\(|\\)|\\,|\\s|\\'|\\\"|\\\\)/g, '\\\\$1');\n  // WebKit has a bug when it comes to URLs that end with \\\n  // https://bugs.webkit.org/show_bug.cgi?id=28885\n  if (/\\\\\\\\$/.test(s2)) {\n    // Add a space to work around the WebKit bug.\n    s2 += ' ';\n  }\n  return 'url(\"' + s2 + '\")';\n}\n\n/**\n * Parses query parameters from Location.\n * @param {string} s The URL to generate the CSS url for.\n * @return {object} Dictionary containing name value pairs for URL\n */\nfunction parseQueryParams(location) {\n  var params = {};\n  var query = unescape(location.search.substring(1));\n  var vars = query.split(\"&\");\n  for (var i=0; i < vars.length; i++) {\n    var pair = vars[i].split(\"=\");\n    params[pair[0]] = pair[1];\n  }\n  return params;\n}\n\nfunction findAncestorByClass(el, className) {\n  return findAncestor(el, function(el) {\n    if (el.classList)\n      return el.classList.contains(className);\n    return null;\n  });\n}\n\n/**\n * Return the first ancestor for which the {@code predicate} returns true.\n * @param {Node} node The node to check.\n * @param {function(Node) : boolean} predicate The function that tests the\n *     nodes.\n * @return {Node} The found ancestor or null if not found.\n */\nfunction findAncestor(node, predicate) {\n  var last = false;\n  while (node != null && !(last = predicate(node))) {\n    node = node.parentNode;\n  }\n  return last ? node : null;\n}\n\nfunction swapDomNodes(a, b) {\n  var afterA = a.nextSibling;\n  if (afterA == b) {\n    swapDomNodes(b, a);\n    return;\n  }\n  var aParent = a.parentNode;\n  b.parentNode.replaceChild(a, b);\n  aParent.insertBefore(b, afterA);\n}\n\n/**\n * Disables text selection and dragging.\n */\nfunction disableTextSelectAndDrag() {\n  // Disable text selection.\n  document.onselectstart = function(e) {\n    e.preventDefault();\n  }\n\n  // Disable dragging.\n  document.ondragstart = function(e) {\n    e.preventDefault();\n  }\n}\n\n// Handle click on a link. If the link points to a chrome: or file: url, then\n// call into the browser to do the navigation.\ndocument.addEventListener('click', function(e) {\n  // Allow preventDefault to work.\n  if (!e.returnValue)\n    return;\n\n  var el = e.target;\n  if (el.nodeType == Node.ELEMENT_NODE &&\n      el.webkitMatchesSelector('A, A *')) {\n    while (el.tagName != 'A') {\n      el = el.parentElement;\n    }\n\n    if ((el.protocol == 'file:' || el.protocol == 'about:') &&\n        (e.button == 0 || e.button == 1)) {\n      chrome.send('navigateToUrl', [\n        el.href,\n        el.target,\n        e.button,\n        e.altKey,\n        e.ctrlKey,\n        e.metaKey,\n        e.shiftKey\n      ]);\n      e.preventDefault();\n    }\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/js/chrome_stubs.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview Stubs for Chrome extension APIs that aren't available to\n * regular web pages, to allow tests to run.\n */\n\nchrome = chrome || {};\nchrome.extension = chrome.extension || {};\nchrome.contentSettings = chrome.contentSettings || {};\n\nvar _rules = {};\nchrome.contentSettings.plugins = {\n  'set': function(details, callback) {\n    assertObjectEquals({'id': 'myplugin'}, details.resourceIdentifier);\n    var pattern = details.primaryPattern;\n    var setting = details.setting;\n    if (pattern == '__invalid_pattern') {\n      chrome.runtime.lastError = {'message': 'Invalid pattern'};\n    } else if (setting == '__invalid_setting') {\n      throw Error('Invalid setting');\n    } else {\n      chrome.runtime.lastError = undefined;\n      _rules[pattern] = setting;\n    }\n    callback();\n  },\n\n  'clear': function(details, callback) {\n    assertObjectEquals({}, details);\n    _rules = {};\n    callback();\n  }\n};\n\nchrome.i18n = chrome.i18n || {};\nchrome.i18n.getMessage = function(id) {\n  var messages = {\n    'patternColumnHeader': 'Hostname Pattern',\n    'settingColumnHeader': 'Behavior',\n    'allowRule': 'Allow',\n    'blockRule': 'Block',\n    'addNewPattern': 'Add a new hostname pattern',\n  };\n  return messages[id];\n}\n\n/**\n * Creates a new Settings object with a set of rules for a dummy plugin.\n * Because we provide stub implementations for the Chrome contentSettings\n * extension API, we know that the methods will execute immediately instead of\n * asynchronously.\n * @param {!Object} rules A map from content settings pattern to setting.\n * @return {!pluginSettings.Settings} A newly created Settings object with the\n *     passed in set of rules.\n */\nfunction createSettings(rules) {\n  var settings = new pluginSettings.Settings('myplugin');\n  if (rules) {\n    for (var pattern in rules) {\n      settings.set(pattern, rules[pattern], function() {});\n    }\n  }\n  return settings;\n}\n\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/js/main.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview Main entry point that creates a new plugin list on document\n * load.\n */\n\ndocument.addEventListener('DOMContentLoaded', function() {\n  chrome.contentSettings.plugins.getResourceIdentifiers(function(r) {\n    if (chrome.runtime.lastError) {\n      $('error').textContent =\n          'Error: ' + chrome.runtime.lastError.message;\n      return;\n    }\n    var pluginList = $('plugin-list');\n    pluginSettings.ui.PluginList.decorate(pluginList);\n    pluginList.dataModel = new cr.ui.ArrayDataModel(r);\n  });\n});\n\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/js/plugin_list.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview Defines a list of plugins that shows for each plugin a list\n * of content setting rules.\n */\n\ncr.define('pluginSettings.ui', function() {\n  const List = cr.ui.List;\n  const ListItem = cr.ui.ListItem;\n  const ListSingleSelectionModel = cr.ui.ListSingleSelectionModel;\n\n  /**\n   * CSS classes used by this class.\n   * @enum {string}\n   */\n  const CSSClass = {\n\n    /**\n     * Hides an element.\n     */\n    HIDDEN: 'hidden',\n\n    /**\n     * A plugin list.\n     */\n    PLUGIN_LIST: 'plugin-list',\n\n    /**\n     * Set on a plugin list entry to show details about the plugin.\n     */\n    PLUGIN_SHOW_DETAILS: 'plugin-show-details',\n\n    /**\n     * The plugin name.\n     */\n    PLUGIN_NAME: 'plugin-name',\n\n    /**\n     * The number of rules set for a plugin.\n     */\n    NUM_RULES: 'num-rules',\n\n    /**\n     * The element containing details about a plugin.\n     */\n    PLUGIN_DETAILS: 'plugin-details',\n\n    /**\n     * The element containing the column headers for the list of rules.\n     */\n    COLUMN_HEADERS: 'column-headers',\n\n    /**\n     * The header for the pattern column.\n     */\n    PATTERN_COLUMN_HEADER: 'pattern-column-header',\n\n    /**\n     * The header for the setting column.\n     */\n    SETTING_COLUMN_HEADER: 'setting-column-header',\n  };\n\n  /**\n   * Returns the item's height, like offsetHeight but such that it works better\n   * when the page is zoomed. See the similar calculation in @{code cr.ui.List}.\n   * This version also accounts for the animation done in this file.\n   * @param {!Element} item The item to get the height of.\n   * @return {number} The height of the item, calculated with zooming in mind.\n   */\n  function getItemHeight(item) {\n    var height = item.style.height;\n    // Use the fixed animation target height if set, in case the element is\n    // currently being animated and we'd get an intermediate height below.\n    if (height && height.substr(-2) == 'px') {\n      return parseInt(height.substr(0, height.length - 2));\n    }\n    return item.getBoundingClientRect().height;\n  }\n\n  /**\n   * Creates a new plugin list item element.\n   * @param {!PluginList} list The plugin list containing this item.\n   * @param {!Object} info Information about the plugin.\n   * @constructor\n   * @extends {cr.ui.ListItem}\n   */\n  function PluginListItem(list, info) {\n    var el = cr.doc.createElement('li');\n\n    /**\n     * The plugin list containing this item.\n     * @type {!PluginList}\n     * @private\n     */\n    el.list_ = list;\n\n    /**\n     * Information about the plugin.\n     * @type {!Object}\n     * @private\n     */\n    el.info_ = info;\n\n    el.__proto__ = PluginListItem.prototype;\n    el.decorate();\n    return el;\n  }\n\n  PluginListItem.prototype = {\n    __proto__: ListItem.prototype,\n\n    /**\n     * The element containing details about the plugin. This is only null in\n     * the prototype.\n     * @type {?HTMLDivElement}\n     * @private\n     */\n    detailsElement_: null,\n\n    /**\n     * Initializes the element.\n     */\n    decorate: function() {\n      ListItem.prototype.decorate.call(this);\n\n      var info = this.info_;\n\n      var contentElement = this.ownerDocument.createElement('div');\n\n      var titleEl = this.ownerDocument.createElement('div');\n      var nameEl = this.ownerDocument.createElement('span');\n      nameEl.className = CSSClass.PLUGIN_NAME;\n      nameEl.textContent = info.description;\n      nameEl.title = info.description;\n      titleEl.appendChild(nameEl);\n      this.numRulesEl_ = this.ownerDocument.createElement('span');\n      this.numRulesEl_.className = CSSClass.NUM_RULES;\n      titleEl.appendChild(this.numRulesEl_);\n      contentElement.appendChild(titleEl);\n\n      this.detailsElement_ = this.ownerDocument.createElement('div');\n      this.detailsElement_.classList.add(CSSClass.PLUGIN_DETAILS);\n      this.detailsElement_.classList.add(CSSClass.HIDDEN);\n\n      var columnHeadersEl = this.ownerDocument.createElement('div');\n      columnHeadersEl.className = CSSClass.COLUMN_HEADERS;\n      var patternColumnEl = this.ownerDocument.createElement('div');\n      patternColumnEl.textContent =\n          chrome.i18n.getMessage('patternColumnHeader');\n      patternColumnEl.className = CSSClass.PATTERN_COLUMN_HEADER;\n      var settingColumnEl = this.ownerDocument.createElement('div');\n      settingColumnEl.textContent =\n          chrome.i18n.getMessage('settingColumnHeader');\n      settingColumnEl.className = CSSClass.SETTING_COLUMN_HEADER;\n      columnHeadersEl.appendChild(patternColumnEl);\n      columnHeadersEl.appendChild(settingColumnEl);\n      this.detailsElement_.appendChild(columnHeadersEl);\n      contentElement.appendChild(this.detailsElement_);\n\n      this.appendChild(contentElement);\n\n      var settings = new pluginSettings.Settings(this.info_.id);\n      this.updateRulesCount_(settings);\n      settings.addEventListener(\n          'change',\n          this.updateRulesCount_.bind(this, settings));\n\n      // Create the rule list asynchronously, to make sure that it is already\n      // fully integrated in the DOM tree.\n      window.setTimeout(this.loadRules_.bind(this, settings), 0);\n    },\n\n    /**\n     * Create the list of content setting rules applying to this plugin.\n     * @param {!pluginSettings.Settings} The settings object storing the content\n     *     setting rules.\n     * @private\n     */\n    loadRules_: function(settings) {\n      var rulesEl = this.ownerDocument.createElement('list');\n      this.detailsElement_.appendChild(rulesEl);\n\n      pluginSettings.ui.RuleList.decorate(rulesEl);\n      rulesEl.setPluginSettings(settings);\n    },\n\n    /**\n     * Called when the list of rules changes to update the rule count shown when\n     * the list is not expanded.\n     * @param {!pluginSettings.Settings} The settings object storing the content\n     *     setting rules.\n     * @private\n     */\n    updateRulesCount_: function(settings) {\n      this.numRulesEl_.textContent = '(' + settings.getAll().length + ' rules)';\n    },\n\n    /**\n     * Whether this item is expanded or not.\n     * @type {boolean}\n     */\n    expanded_: false,\n    /**\n     * Whether this item is expanded or not.\n     * @type {boolean}\n     */\n    get expanded() {\n      return this.expanded_;\n    },\n    set expanded(expanded) {\n      if (this.expanded_ == expanded) {\n        return;\n      }\n      this.expanded_ = expanded;\n      if (expanded) {\n        var oldExpanded = this.list_.expandItem;\n        this.list_.expandItem = this;\n        this.detailsElement_.classList.remove(CSSClass.HIDDEN);\n        if (oldExpanded) {\n          oldExpanded.expanded = false;\n        }\n        this.classList.add(CSSClass.PLUGIN_SHOW_DETAILS);\n      } else {\n        if (this.list_.expandItem == this) {\n          this.list_.leadItemHeight = 0;\n          this.list_.expandItem = null;\n        }\n        this.style.height = '';\n        this.detailsElement_.classList.add(CSSClass.HIDDEN);\n        this.classList.remove(CSSClass.PLUGIN_SHOW_DETAILS);\n      }\n    },\n  };\n\n  /**\n   * Creates a new plugin list.\n   * @constructor\n   * @extends {cr.ui.List}\n   */\n  var PluginList = cr.ui.define('list');\n\n  PluginList.prototype = {\n    __proto__: List.prototype,\n\n    /**\n     * Initializes the element.\n     */\n    decorate: function() {\n      List.prototype.decorate.call(this);\n      this.classList.add(CSSClass.PLUGIN_LIST);\n      var sm = new ListSingleSelectionModel();\n      sm.addEventListener('change', this.handleSelectionChange_.bind(this));\n      this.selectionModel = sm;\n      this.autoExpands = true;\n    },\n\n    /**\n     * Creates a new plugin list item.\n     * @param {!Object} info Information about the plugin.\n     */\n    createItem: function(info) {\n      return new PluginListItem(this, info);\n    },\n\n    /**\n     * Called when the selection changes.\n     * @param {!Event} ce The change event.\n     * @private\n     */\n    handleSelectionChange_: function(ce) {\n      ce.changes.forEach(function(change) {\n        var listItem = this.getListItemByIndex(change.index);\n        if (listItem) {\n          if (!change.selected) {\n            // TODO(bsmith) explain window timeout (from cookies_list.js)\n            window.setTimeout(function() {\n              if (!listItem.selected || !listItem.lead) {\n                listItem.expanded = false;\n              }\n            }, 0);\n          } else if (listItem.lead) {\n            listItem.expanded = true;\n          }\n        }\n      }, this);\n    },\n  };\n\n  return {\n    PluginList: PluginList,\n    PluginListItem: PluginListItem,\n  };\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/js/plugin_list_test.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<style>\n#error {\n  display: none;\n}\n</style>\n<link rel=\"stylesheet\" href=\"../domui/css/button.css\">\n<link rel=\"stylesheet\" href=\"../domui/css/chrome_shared.css\">\n<link rel=\"stylesheet\" href=\"../domui/css/list.css\">\n<link rel=\"stylesheet\" href=\"../domui/css/select.css\">\n\n<link rel=\"stylesheet\" href=\"../options/css/list.css\">\n\n<link rel=\"stylesheet\" href=\"../css/plugin_list.css\">\n<link rel=\"stylesheet\" href=\"../css/rule_list.css\">\n\n<script src=\"http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js\"></script>\n<script src=\"../domui/js/cr.js\"></script>\n<script src=\"../domui/js/cr/event_target.js\"></script>\n<script src=\"../domui/js/cr/ui.js\"></script>\n<script src=\"../domui/js/cr/ui/array_data_model.js\"></script>\n<script src=\"../domui/js/cr/ui/list_item.js\"></script>\n<script src=\"../domui/js/cr/ui/list_selection_controller.js\"></script>\n<script src=\"../domui/js/cr/ui/list_selection_model.js\"></script>\n<script src=\"../domui/js/cr/ui/list_single_selection_model.js\"></script>\n<script src=\"../domui/js/cr/ui/list.js\"></script>\n<script src=\"../domui/js/util.js\"></script>\n\n<script src=\"../options/js/deletable_item_list.js\"></script>\n<script src=\"../options/js/inline_editable_list.js\"></script>\n\n<script src=\"plugin_list.js\" type=\"text/javascript\"></script>\n<script src=\"plugin_settings.js\" type=\"text/javascript\"></script>\n<script src=\"rule_list.js\" type=\"text/javascript\"></script>\n\n<script>\ngoog.require('goog.testing.jsunit');\n</script>\n<script src=\"chrome_stubs.js\" type=\"text/javascript\"></script>\n</head>\n<body>\n<div id=\"error\"></div>\n<script>\nfunction testConstruction() {\n  var pluginList = document.createElement('list');\n  document.body.appendChild(pluginList);\n  pluginSettings.ui.PluginList.decorate(pluginList);\n  var plugins = [\n    {\n      'id': 'myplugin',\n      'description': 'My Plugin'\n    }\n  ];\n  var rules = {\n    'http://example.com/*': 'block',\n    'http://moose.org/*': 'allow',\n  };\n  createSettings(rules);\n  pluginList.dataModel = new cr.ui.ArrayDataModel(plugins);\n  assertEquals('My Plugin',\n               pluginList.querySelector('.plugin-name').textContent);\n  assertEquals('(2 rules)', pluginList.querySelector('.num-rules').textContent);\n}\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/js/plugin_settings.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview Defines a class that provides some convenient wrapper methods\n * around the Chrome contentSettings extension API.\n */\n\ncr.define('pluginSettings', function() {\n  /** @const */ var EventTarget = cr.EventTarget;\n\n  /**\n   * Creates a new content settings model.\n   * @param {string} plugin Identifies the plugin for which this object stores\n   *     settings.\n   * @constructor\n   * @extends {cr.EventTarget}\n   */\n  function Settings(plugin) {\n    /**\n     * Identifies the plugin for which this object stores settings.\n     * @type {string}\n     * @private\n     */\n    this.plugin_ = plugin;\n  }\n\n  Settings.prototype = {\n    __proto__: cr.EventTarget.prototype,\n\n    /**\n     * Clears all content settings, and recreates them from local storage. If a\n     * content setting can't be set (which shouldn't really happen, as it has\n     * been successfully set previously), it is removed from local storage as\n     * well.\n     * @param {function()} callback Called when the content settings have been\n     *     recreated, or on error.\n     * @private\n     */\n    recreateRules_: function(callback) {\n      chrome.contentSettings.plugins.clear(\n          {}, this.didClearRules_.bind(this, callback));\n    },\n\n    /**\n     * Recreates all content settings from local storage.\n     * @param {function()} callback Called when the content settings have been\n     *     recreated, or on error.\n     * @private\n     */\n    didClearRules_: function(callback) {\n      if (chrome.runtime.lastError) {\n        console.error('Error clearing rules');\n        callback();\n        return;\n      }\n      var length = window.localStorage.length;\n      if (length == 0) {\n        cr.dispatchSimpleEvent(settings, 'change');\n        callback();\n        return;\n      }\n      var counter = {\n        'value': length\n      };\n      for (var i = 0; i < length; i++) {\n        var key = window.localStorage.key(i);\n        var keyArray = JSON.parse(key);\n        var plugin = keyArray[0];\n        var pattern = keyArray[1];\n        var setting = window.localStorage.getItem(key)\n        chrome.contentSettings.plugins.set(\n            {\n              'primaryPattern': pattern,\n              'resourceIdentifier': {'id': plugin},\n              'setting': setting,\n            },\n            this.didSetContentSetting_.bind(\n                this, key, setting, counter, callback));\n      }\n    },\n\n    /**\n     * Checks if we're finished with recreating content settings and calls the\n     * passed in callback if so.\n     * @param {string} key The local storage key under which the content\n     *     setting was stored.\n     * @param {string} value The content setting value in local storage.\n     * @param {{value:number}} counter Contains the number of callbacks still\n     *     outstanding.\n     * @param {function()} callback Called when the content settings have been\n     *     recreated, or on error.\n     * @private\n     */\n    didSetContentSetting_: function(plugin, pattern, key, counter, callback) {\n      if (chrome.runtime.lastError) {\n        console.error(\n            'Error restoring [' + key + ': ' + value + ']: ' +\n                chrome.runtime.lastError.message);\n        window.localStorage.removeItem(key);\n      }\n      counter.value--;\n      if (counter.value == 0) {\n        cr.dispatchSimpleEvent(this, 'change');\n        callback();\n      }\n    },\n\n    /**\n     * Creates a content setting rule and calls the passed in callback with the\n     * result.\n     * @param {string} pattern The content setting pattern for the rule.\n     * @param {string} setting The setting for the rule.\n     * @param {function(?string)} callback Called when the content settings\n     *     have been updated, or on error.\n     */\n    set: function(pattern, setting, callback) {\n      var plugin = this.plugin_;\n      var settings = this;\n      chrome.contentSettings.plugins.set({\n        'primaryPattern': pattern,\n        'resourceIdentifier': { 'id': plugin },\n        'setting': setting,\n      }, function() {\n        if (chrome.runtime.lastError) {\n          callback(chrome.runtime.lastError.message);\n        } else {\n          window.localStorage.setItem(JSON.stringify([plugin, pattern]),\n                                      setting);\n          cr.dispatchSimpleEvent(settings, 'change');\n          callback();\n        }\n      });\n    },\n\n    /**\n     * Removes the content setting rule with a given pattern, and calls the\n     * passed in callback afterwards.\n     * @param {string} pattern The content setting pattern for the rule.\n     * @param {function()} callback Called when the content settings have\n     * been updated.\n     */\n    clear: function(pattern, callback) {\n      window.localStorage.removeItem(\n          JSON.stringify([this.plugin_, pattern]));\n      this.recreateRules_(callback);\n    },\n\n    /**\n     * Updates the content setting rule with a given pattern to a new pattern\n     * and setting and calls the passed in callback with the result.\n     * @param {string} oldPattern The old content setting pattern for the rule.\n     * @param {string} newPattern The new content setting pattern for the rule.\n     * @param {string} setting The setting for the rule.\n     * @param {function(?string)} callback Called when the content settings\n     *     have been updated, or on error.\n     */\n    update: function(oldPattern, newPattern, setting, callback) {\n      if (oldPattern == newPattern) {\n        // Avoid recreating all rules if only the setting changed.\n        this.set(newPattern, setting, callback);\n        return;\n      }\n      var oldSetting = this.get(oldPattern);\n      var settings = this;\n      // Remove the old rule.\n      this.clear(oldPattern, function() {\n        // Try to set the new rule.\n        settings.set(newPattern, setting, function(error) {\n          if (error) {\n            // If setting the new rule failed, restore the old rule.\n            settings.set(oldPattern, oldSetting, function(restoreError) {\n              if (restoreError) {\n                console.error('Error restoring [' + settings.plugin_ + ', ' +\n                              oldPattern + oldSetting + ']: ' + restoreError);\n              }\n              callback(error);\n            });\n          } else {\n            callback();\n          }\n        });\n      });\n    },\n\n    /**\n     * Returns the content setting for a given pattern.\n     * @param {string} pattern The content setting pattern for the rule.\n     * @return {string} The setting for the rule.\n     */\n    get: function(primaryPattern) {\n      return window.localStorage.getItem(\n          JSON.stringify([this.plugin_, primaryPattern]));\n    },\n\n    /**\n     * @return {!Array} A list of all content setting rules for this plugin.\n     */\n    getAll: function() {\n      var rules = [];\n      for (var i = 0; i < window.localStorage.length; i++) {\n        var key = window.localStorage.key(i);\n        var keyArray = JSON.parse(key);\n        if (keyArray[0] == this.plugin_) {\n          rules.push({\n            'primaryPattern': keyArray[1],\n            'setting': window.localStorage.getItem(key),\n          });\n        }\n      }\n      return rules;\n    }\n  };\n\n  return {\n    Settings: Settings,\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/js/plugin_settings_test.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<script src=\"http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js\"></script>\n<script src=\"../domui/js/cr.js\"></script>\n<script src=\"../domui/js/cr/event_target.js\"></script>\n<script src=\"plugin_settings.js\" type=\"text/javascript\"></script>\n<script>\ngoog.require('goog.testing.jsunit');\n</script>\n<script src=\"chrome_stubs.js\" type=\"text/javascript\"></script>\n</head>\n<body>\n<script>\nfunction testConstruction() {\n  var settings = createSettings();\n}\n\nfunction testSet() {\n  var settings = createSettings();\n  var rules = {\n    'http://example.com/*': 'block',\n    'http://google.com/*': 'allow',\n    'http://moose.org/*': 'allow',\n  };\n  var numCallbacks = 0;\n  for (var pattern in rules) {\n    settings.set(pattern, rules[pattern], function(error) {\n      numCallbacks++;\n      assertUndefined(error);\n    });\n  }\n  assertEquals(Object.keys(rules).length, numCallbacks);\n  assertObjectEquals(rules, _rules);\n}\n\nfunction testSetInvalid() {\n  var settings = createSettings();\n  // Attempting to set an invalid pattern should return an error in the\n  // callback.\n  var callbackCalled = false;\n  settings.set('__invalid_pattern', 'block', function(error) {\n    callbackCalled = true;\n    assertEquals('Invalid pattern', error);\n  });\n  assertTrue(callbackCalled);\n  assertObjectEquals({}, _rules);\n\n  // Attempting to set an invalid setting should immediately throw an exception.\n  callbackCalled = false;\n  assertThrows(function() {\n    settings.set('http://example.com/*', '__invalid_setting', function() {\n      callbackCalled = true;\n    });\n  });\n  assertFalse(callbackCalled);\n  assertObjectEquals({}, _rules);\n}\n\nfunction testGet() {\n  var rules = {\n    'http://example.com/*': 'block',\n    'http://google.com/*': 'allow',\n    'http://moose.org/*': 'allow',\n  };\n  var settings = createSettings(rules);\n  for (var pattern in rules)\n    assertEquals(rules[pattern], settings.get(pattern));\n}\n\nfunction testGetAll() {\n  var settings = createSettings({\n    'http://example.com/*': 'block',\n    'http://google.com/*': 'allow',\n    'http://moose.org/*': 'allow',\n  });\n  var rules = settings.getAll();\n  // Sort the rules lexicographically by their pattern.\n  rules.sort(function(a, b) {\n    if (a.primaryPattern == b.primaryPattern) {\n      return 0;\n    }\n    if (a.primaryPattern > b.primaryPattern) {\n      return 1;\n    }\n    return -1;\n  });\n  assertEquals(3, rules.length);\n  assertObjectEquals({'primaryPattern': 'http://example.com/*',\n                      'setting': 'block'},\n                     rules[0]);\n  assertObjectEquals({'primaryPattern': 'http://google.com/*',\n                      'setting': 'allow'},\n                     rules[1]);\n  assertObjectEquals({'primaryPattern': 'http://moose.org/*',\n                      'setting': 'allow'},\n                     rules[2]);\n}\n\nfunction testUpdate() {\n  var settings = createSettings({\n    'http://example.com/*': 'block',\n    'http://google.com/*': 'allow',\n    'http://moose.org/*': 'allow',\n  });\n  var numCallbacks = 0;\n  settings.update('http://google.com/*', 'http://google.com/*', 'ask',\n                  function(error) {\n    numCallbacks++;\n    assertUndefined(error);\n  });\n  assertEquals('ask', _rules['http://google.com/*']);\n\n  settings.update('http://google.com/*', 'http://blurp.net/*', 'ask',\n                  function(error) {\n    numCallbacks++;\n    assertUndefined(error);\n  });\n  assertUndefined(_rules['http://google.com/*']);\n  assertEquals('ask', _rules['http://blurp.net/*']);\n\n  // Attempting to update a rule to an invalid pattern should return an error\n  // and leave the rules unchanged.\n  settings.update('http://example.com/*', '__invalid_pattern', 'ask',\n                  function(error) {\n    numCallbacks++;\n    assertEquals('Invalid pattern', error);\n  });\n  assertUndefined(_rules['__invalid_pattern']);\n  assertEquals('block', _rules['http://example.com/*']);\n\n  assertEquals(3, numCallbacks);\n}\n\nfunction tearDown() {\n  // Clear local storage and |rules_| to make sure no state leaks into the next\n  // test.\n  window.localStorage.clear();\n  _rules = {};\n}\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/js/rule_list.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview Defines a list of content setting rules.\n */\n\ncr.define('pluginSettings.ui', function() {\n  const InlineEditableItemList = options.InlineEditableItemList;\n  const InlineEditableItem = options.InlineEditableItem;\n  const ArrayDataModel = cr.ui.ArrayDataModel;\n\n  /**\n   * CSS classes used by this class.\n   * @enum {string}\n   */\n  const CSSClass = {\n    /**\n     * A list of content setting rules.\n     */\n    RULE_LIST: 'rule-list',\n\n    /**\n     * The element containing the content setting pattern for a rule.\n     */\n    RULE_PATTERN: 'rule-pattern',\n\n    /**\n     * The element containing the behavior (allow or block) for a rule.\n     */\n    RULE_BEHAVIOR: 'rule-behavior',\n\n    /**\n     * Static text (as opposed to an editable text field).\n     */\n    STATIC_TEXT: 'static-text',\n  };\n  /**\n   * A single item in a list of rules.\n   * @param {!RuleList} list The rule list containing this item.\n   * @param {!Object} rule The content setting rule.\n   * @constructor\n   * @extends {options.InlineEditableItem}\n   */\n  function RuleListItem(list, rule) {\n    var el = cr.doc.createElement('li');\n\n    /**\n     * The content setting rule.\n     * @type {!Object}\n     * @private\n     */\n    el.dataItem_ = rule;\n\n    /**\n     * The rule list containing this item.\n     * @type {!RuleList}\n     * @private\n     */\n    el.list_ = list;\n    el.__proto__ = RuleListItem.prototype;\n    el.decorate();\n\n    return el;\n  }\n\n  RuleListItem.prototype = {\n    __proto__: InlineEditableItem.prototype,\n\n    /**\n     * The text input element for the pattern. This is only null in the\n     * prototype.\n     * @type {?HTMLInputElement}\n     * @private\n     */\n    input_: null,\n\n    /**\n     * The popup button for the setting. This is only null in the prototype.\n     * @type {?HTMLSelectElement}\n     * @private\n     */\n    select_: null,\n\n    /**\n     * The static text field containing the pattern.\n     * @type {?HTMLDivElement}\n     * @private\n     */\n    patternLabel_: null,\n\n    /**\n     * The static text field containing the setting.\n     * @type {?HTMLDivElement}\n     * @private\n     */\n    settingLabel_: null,\n\n    /**\n     * Decorates an elements as a list item.\n     */\n    decorate: function() {\n      InlineEditableItem.prototype.decorate.call(this);\n\n      this.isPlaceholder = !this.pattern;\n      var patternCell = this.createEditableTextCell(this.pattern);\n      patternCell.className = CSSClass.RULE_PATTERN;\n      this.contentElement.appendChild(patternCell);\n      var input = patternCell.querySelector('input');\n      if (this.pattern) {\n        this.patternLabel_ =\n            patternCell.querySelector('.' + CSSClass.STATIC_TEXT);\n      } else {\n        input.placeholder = chrome.i18n.getMessage('addNewPattern');\n      }\n\n      // Setting label for display mode. |pattern| will be null for the 'add new\n      // exception' row.\n      if (this.pattern) {\n        var settingLabel = cr.doc.createElement('span');\n        settingLabel.textContent = this.settingForDisplay();\n        settingLabel.className = CSSClass.RULE_BEHAVIOR;\n        settingLabel.setAttribute('displaymode', 'static');\n        this.contentElement.appendChild(settingLabel);\n        this.settingLabel_ = settingLabel;\n      }\n\n      // Setting select element for edit mode.\n      var select = cr.doc.createElement('select');\n      var optionAllow = cr.doc.createElement('option');\n      optionAllow.textContent = chrome.i18n.getMessage('allowRule');\n      optionAllow.value = 'allow';\n      select.appendChild(optionAllow);\n\n      var optionBlock = cr.doc.createElement('option');\n      optionBlock.textContent = chrome.i18n.getMessage('blockRule');\n      optionBlock.value = 'block';\n      select.appendChild(optionBlock);\n\n      this.contentElement.appendChild(select);\n      select.className = CSSClass.RULE_BEHAVIOR;\n      if (this.pattern) {\n        select.setAttribute('displaymode', 'edit');\n      }\n\n      this.input_ = input;\n      this.select_ = select;\n\n      this.updateEditables();\n\n      // Listen for edit events.\n      this.addEventListener('canceledit', this.onEditCancelled_);\n      this.addEventListener('commitedit', this.onEditCommitted_);\n    },\n\n    /**\n     * The pattern (e.g., a URL) for the rule.\n     * @type {string}\n     */\n    get pattern() {\n      return this.dataItem_['primaryPattern'];\n    },\n    set pattern(pattern) {\n      this.dataItem_['primaryPattern'] = pattern;\n    },\n\n    /**\n     * The setting (allow/block) for the rule.\n     * @type {string}\n     */\n    get setting() {\n      return this.dataItem_['setting'];\n    },\n    set setting(setting) {\n      this.dataItem_['setting'] = setting;\n    },\n\n    /**\n     * Gets a human-readable setting string.\n     * @type {string}\n     */\n    settingForDisplay: function() {\n      var setting = this.setting;\n      if (setting == 'allow') {\n        return chrome.i18n.getMessage('allowRule');\n      }\n      if (setting == 'block') {\n        return chrome.i18n.getMessage('blockRule');\n      }\n    },\n\n    /**\n     * Set the <input> to its original contents. Used when the user quits\n     * editing.\n     */\n    resetInput: function() {\n      this.input_.value = this.pattern;\n    },\n\n    /**\n     * Copy the data model values to the editable nodes.\n     */\n    updateEditables: function() {\n      this.resetInput();\n\n      var settingOption =\n          this.select_.querySelector('[value=\\'' + this.setting + '\\']');\n      if (settingOption) {\n        settingOption.selected = true;\n      }\n    },\n\n    /** @inheritDoc */\n    get hasBeenEdited() {\n      var livePattern = this.input_.value;\n      var liveSetting = this.select_.value;\n      return livePattern != this.pattern || liveSetting != this.setting;\n    },\n\n    /**\n     * Called when committing an edit.\n     * @param {!Event} e The end event.\n     * @private\n     */\n    onEditCommitted_: function(e) {\n      var newPattern = this.input_.value;\n      var newSetting = this.select_.value;\n\n      this.finishEdit(newPattern, newSetting);\n    },\n\n    /**\n     * Called when cancelling an edit; resets the control states.\n     * @param {!Event} e The cancel event.\n     * @private\n     */\n    onEditCancelled_: function() {\n      this.updateEditables();\n    },\n\n    /**\n     * Editing is complete; update the model.\n     * @param {string} newPattern The pattern that the user entered.\n     * @param {string} newSetting The setting the user chose.\n     */\n    finishEdit: function(newPattern, newSetting) {\n      this.patternLabel_.textContent = newPattern;\n      this.settingLabel_.textContent = this.settingForDisplay();\n      var oldPattern = this.pattern;\n      this.pattern = newPattern;\n      this.setting = newSetting;\n\n      this.list_.settings.update(oldPattern, newPattern, newSetting,\n                                 this.list_.settingsChangedCallback());\n    }\n  };\n\n  /**\n   * Create a new list item to add a rule.\n   * @param {!RuleList} list The rule list containing this item.\n   * @constructor\n   * @extends {AddRuleListItem}\n   */\n  function AddRuleListItem(list) {\n    var el = cr.doc.createElement('div');\n    el.dataItem_ = {};\n    el.list_ = list;\n    el.__proto__ = AddRuleListItem.prototype;\n    el.decorate();\n\n    return el;\n  }\n\n  AddRuleListItem.prototype = {\n    __proto__: RuleListItem.prototype,\n\n    /**\n     * Initializes the element.\n     */\n    decorate: function() {\n      RuleListItem.prototype.decorate.call(this);\n\n      this.setting = 'allow';\n    },\n\n    /**\n     * Clear the <input> and let the placeholder text show again.\n     */\n    resetInput: function() {\n      this.input_.value = '';\n    },\n\n    /** @inheritDoc */\n    get hasBeenEdited() {\n      return this.input_.value != '';\n    },\n\n    /**\n     * Editing is complete; update the model. As long as the pattern isn't\n     * empty, we'll just add it.\n     * @param {string} newPattern The pattern that the user entered.\n     * @param {string} newSetting The setting the user chose.\n     */\n    finishEdit: function(newPattern, newSetting) {\n      this.resetInput();\n      this.list_.settings.set(newPattern, newSetting,\n                              this.list_.settingsChangedCallback());\n    },\n  };\n\n  /**\n   * A list of content setting rules.\n   * @constructor\n   * @extends {cr.ui.List}\n   */\n  var RuleList = cr.ui.define('list');\n\n  RuleList.prototype = {\n    __proto__: InlineEditableItemList.prototype,\n\n    /**\n     * The content settings model for this list.\n     * @type {?Settings}\n     */\n    settings: null,\n\n    /**\n     * Called when an element is decorated as a list.\n     */\n    decorate: function() {\n      InlineEditableItemList.prototype.decorate.call(this);\n\n      this.classList.add(CSSClass.RULE_LIST);\n\n      this.autoExpands = true;\n      this.reset();\n    },\n\n    /**\n     * Creates an item to go in the list.\n     * @param {?Object} entry The element from the data model for this row.\n     */\n    createItem: function(entry) {\n      if (entry) {\n        return new RuleListItem(this, entry);\n      } else {\n        var addRuleItem = new AddRuleListItem(this);\n        addRuleItem.deletable = false;\n        return addRuleItem;\n      }\n    },\n\n    /**\n     * Sets the rules in the js model.\n     * @param {!Array} entries A list of dictionaries of values, each dictionary\n     *     represents a rule.\n     */\n    setRules_: function(entries) {\n      var deleteCount = this.dataModel.length - 1;\n\n      var args = [0, deleteCount];\n      args.push.apply(args, entries);\n      this.dataModel.splice.apply(this.dataModel, args);\n    },\n\n    /**\n     * Called when the list of content setting rules has been changed.\n     * @param {?string} error The error message, if an error occurred.\n     *     Otherwise, this is null.\n     * @private\n     */\n    settingsChanged_: function(error) {\n      if (error) {\n        $('error').textContent = 'Error: ' + error;\n      } else {\n        $('error').textContent = '';\n      }\n      this.setRules_(this.settings.getAll());\n    },\n\n    /**\n     * @return {function()} A bound callback to update the UI after the\n     *     settings have been changed.\n     */\n    settingsChangedCallback: function() {\n      return this.settingsChanged_.bind(this);\n    },\n\n    /**\n     * Binds this list to the content settings model.\n     * @param {!Settings} settings The content settings model.\n     */\n    setPluginSettings: function(settings) {\n      this.settings = settings;\n      this.settingsChanged_();\n    },\n\n    /**\n     * Removes all rules from the js model.\n     */\n    reset: function() {\n      // The null creates the Add New Rule row.\n      this.dataModel = new ArrayDataModel([null]);\n    },\n\n    /** @inheritDoc */\n    deleteItemAtIndex: function(index) {\n      var listItem = this.getListItemByIndex(index);\n      if (listItem.undeletable) {\n        return;\n      }\n\n      this.settings.clear(listItem.pattern, this.settingsChangedCallback());\n    },\n  };\n\n  return {\n    RuleListItem: RuleListItem,\n    AddRuleListItem: AddRuleListItem,\n    RuleList: RuleList,\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/js/rule_list_test.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<link rel=\"stylesheet\" href=\"../domui/css/button.css\">\n<link rel=\"stylesheet\" href=\"../domui/css/chrome_shared.css\">\n<link rel=\"stylesheet\" href=\"../domui/css/list.css\">\n<link rel=\"stylesheet\" href=\"../domui/css/select.css\">\n\n<link rel=\"stylesheet\" href=\"../options/css/list.css\">\n\n<link rel=\"stylesheet\" href=\"../css/rule_list.css\">\n\n<script src=\"http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js\"></script>\n<script src=\"../domui/js/cr.js\"></script>\n<script src=\"../domui/js/cr/event_target.js\"></script>\n<script src=\"../domui/js/cr/ui.js\"></script>\n<script src=\"../domui/js/cr/ui/array_data_model.js\"></script>\n<script src=\"../domui/js/cr/ui/list_item.js\"></script>\n<script src=\"../domui/js/cr/ui/list_selection_controller.js\"></script>\n<script src=\"../domui/js/cr/ui/list_selection_model.js\"></script>\n<script src=\"../domui/js/cr/ui/list_single_selection_model.js\"></script>\n<script src=\"../domui/js/cr/ui/list.js\"></script>\n<script src=\"../domui/js/util.js\"></script>\n\n<script src=\"../options/js/deletable_item_list.js\"></script>\n<script src=\"../options/js/inline_editable_list.js\"></script>\n\n<script src=\"plugin_settings.js\" type=\"text/javascript\"></script>\n<script src=\"rule_list.js\" type=\"text/javascript\"></script>\n\n<script>\ngoog.require('goog.testing.jsunit');\n</script>\n<script src=\"chrome_stubs.js\" type=\"text/javascript\"></script>\n</head>\n<body>\n<list id=\"rule-list\"></list>\n<div id=\"error\"></div>\n<script>\nfunction testConstruction() {\n  var rulesEl = document.createElement('list');\n  document.body.appendChild(rulesEl);\n  pluginSettings.ui.RuleList.decorate(rulesEl);\n  var rules = {\n    'http://example.com/*': 'block',\n    'http://moose.org/*': 'allow',\n  };\n  rulesEl.setPluginSettings(createSettings(rules));\n  var ruleElements = rulesEl.querySelectorAll('[role=listitem]');\n  assertEquals(3, ruleElements.length);\n  assertEquals('http://example.com/*',\n               ruleElements[0].querySelector('.rule-pattern').textContent);\n  assertEquals('http://moose.org/*',\n               ruleElements[1].querySelector('.rule-pattern').textContent);\n  assertEquals('', ruleElements[2].querySelector('.rule-pattern').textContent);\n  assertEquals('Block',\n               ruleElements[0].querySelector('.rule-behavior').textContent);\n  assertEquals('Allow',\n               ruleElements[1].querySelector('.rule-behavior').textContent);\n  assertEquals('allow', ruleElements[2].querySelector('.rule-behavior').value);\n}\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/manifest.json",
    "content": "{\n  \"name\" : \"__MSG_extName__\",\n  \"version\" : \"0.6\",\n  \"description\" : \"__MSG_extDescription__\",\n  \"options_page\": \"options.html\",\n  \"permissions\": [\n    \"contentSettings\"\n  ],\n  \"icons\": {\n    \"128\": \"bunny128.png\",\n    \"48\": \"bunny48.png\"\n  },\n  \"minimum_chrome_version\": \"16.0.912\",\n  \"default_locale\": \"en\",\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/options/css/list.css",
    "content": "/* Copyright 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file. */\n\n.raw-button,\n.raw-button:hover,\n.raw-button:active {\n  -webkit-box-shadow: none;\n  background-color: transparent;\n  background-repeat: no-repeat;\n  border: none;\n  min-width: 0;\n  padding: 1px 6px;\n}\n\nlist > * {\n  -webkit-box-align: center;\n  box-sizing: border-box;\n  border-radius: 0;\n  display: -webkit-box;\n  height: 32px;\n  border: none;\n  margin: 0;\n  transition: .15s background-color;\n}\n\nlist:not([disabled]) > :hover {\n  background-color: #e4ecf7;\n}\n\nlist:not([hasElementFocus]) > [selected],\nlist:not([hasElementFocus]) > [lead][selected] {\n  background-color: #d0d0d0;\n  background-image: none;\n}\n\nlist[hasElementFocus] > [selected],\nlist[hasElementFocus] > [lead][selected],\nlist:not([hasElementFocus]) > [selected]:hover,\nlist:not([hasElementFocus]) > [selected][lead]:hover {\n  background-color: #bbcee9;\n  background-image: none;\n}\n\nlist[disabled] {\n  opacity: 0.6;\n}\n\nlist > .heading {\n  color: #666666;\n}\n\nlist > .heading:hover {\n  background-color: transparent;\n  border-color: transparent;\n}\n\nlist .deletable-item {\n  -webkit-box-align: center;\n}\n\nlist .deletable-item > :first-child {\n  -webkit-box-align: center;\n  -webkit-box-flex: 1;\n  display: -webkit-box;\n  padding-inline-end: 5px;\n}\n\nlist .close-button {\n  background-color: transparent;\n  background-image: url(\"../images/close_bar.png\");\n  border: none;\n  display: block;\n  height: 16px;\n  opacity: 1;\n  transition: .15s opacity;\n  width: 16px;\n}\n\nlist > *:not(:hover):not([lead]) .close-button,\nlist > *:not(:hover):not([selected]) .close-button,\nlist:not([hasElementFocus]) > *:not(:hover) .close-button,\nlist[disabled] .close-button,\nlist .close-button[disabled] {\n  opacity: 0;\n  pointer-events: none;\n}\n\nlist .close-button:hover {\n  background-image: url(\"../images/close_bar_h.png\");\n}\n\nlist .close-button:active {\n  background-image: url(\"../images/close_bar_p.png\");\n}\n\nlist .static-text {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\nlist[inlineeditable] input {\n  box-sizing: border-box;\n  margin: 0;\n  width: 100%;\n}\n\nlist[inlineeditable] > :not([editing]) [displaymode=\"edit\"],\nlist[inlineeditable] > [editing] [displaymode=\"static\"] {\n  display: none;\n}\n\nlist > [editing] input:invalid {\n  background-color: pink;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/options/js/deletable_item_list.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\ncr.define('options', function() {\n  const List = cr.ui.List;\n  const ListItem = cr.ui.ListItem;\n\n  /**\n   * Creates a deletable list item, which has a button that will trigger a call\n   * to deleteItemAtIndex(index) in the list.\n   */\n  var DeletableItem = cr.ui.define('li');\n\n  DeletableItem.prototype = {\n    __proto__: ListItem.prototype,\n\n    /**\n     * The element subclasses should populate with content.\n     * @type {HTMLElement}\n     * @private\n     */\n    contentElement_: null,\n\n    /**\n     * The close button element.\n     * @type {HTMLElement}\n     * @private\n     */\n    closeButtonElement_: null,\n\n    /**\n     * Whether or not this item can be deleted.\n     * @type {boolean}\n     * @private\n     */\n    deletable_: true,\n\n    /** @inheritDoc */\n    decorate: function() {\n      ListItem.prototype.decorate.call(this);\n\n      this.classList.add('deletable-item');\n\n      this.contentElement_ = this.ownerDocument.createElement('div');\n      this.appendChild(this.contentElement_);\n\n      this.closeButtonElement_ = this.ownerDocument.createElement('button');\n      this.closeButtonElement_.classList.add('raw-button');\n      this.closeButtonElement_.classList.add('close-button');\n      this.closeButtonElement_.addEventListener('mousedown',\n                                                this.handleMouseDownUpOnClose_);\n      this.closeButtonElement_.addEventListener('mouseup',\n                                                this.handleMouseDownUpOnClose_);\n      this.closeButtonElement_.addEventListener('focus',\n                                                this.handleFocus_.bind(this));\n      this.appendChild(this.closeButtonElement_);\n    },\n\n    /**\n     * Returns the element subclasses should add content to.\n     * @return {HTMLElement} The element subclasses should popuplate.\n     */\n    get contentElement() {\n      return this.contentElement_;\n    },\n\n    /* Gets/sets the deletable property. An item that is not deletable doesn't\n     * show the delete button (although space is still reserved for it).\n     */\n    get deletable() {\n      return this.deletable_;\n    },\n    set deletable(value) {\n      this.deletable_ = value;\n      this.closeButtonElement_.disabled = !value;\n    },\n\n    /**\n     * Called when a focusable child element receives focus. Selects this item\n     * in the list selection model.\n     * @private\n     */\n    handleFocus_: function() {\n      var list = this.parentNode;\n      var index = list.getIndexOfListItem(this);\n      list.selectionModel.selectedIndex = index;\n      list.selectionModel.anchorIndex = index;\n    },\n\n    /**\n     * Don't let the list have a crack at the event. We don't want clicking the\n     * close button to change the selection of the list.\n     * @param {Event} e The mouse down/up event object.\n     * @private\n     */\n    handleMouseDownUpOnClose_: function(e) {\n      if (!e.target.disabled)\n        e.stopPropagation();\n    },\n  };\n\n  var DeletableItemList = cr.ui.define('list');\n\n  DeletableItemList.prototype = {\n    __proto__: List.prototype,\n\n    /** @inheritDoc */\n    decorate: function() {\n      List.prototype.decorate.call(this);\n      this.addEventListener('click', this.handleClick_);\n      this.addEventListener('keydown', this.handleKeyDown_);\n    },\n\n    /**\n     * Callback for onclick events.\n     * @param {Event} e The click event object.\n     * @private\n     */\n    handleClick_: function(e) {\n      if (this.disabled)\n        return;\n\n      var target = e.target;\n      if (target.classList.contains('close-button')) {\n        var listItem = this.getListItemAncestor(target);\n        var selected = this.selectionModel.selectedIndexes;\n\n        // Check if the list item that contains the close button being clicked\n        // is not in the list of selected items. Only delete this item in that\n        // case.\n        var idx = this.getIndexOfListItem(listItem);\n        if (selected.indexOf(idx) == -1) {\n          this.deleteItemAtIndex(idx);\n        } else {\n          this.deleteSelectedItems_();\n        }\n      }\n    },\n\n    /**\n     * Callback for keydown events.\n     * @param {Event} e The keydown event object.\n     * @private\n     */\n    handleKeyDown_: function(e) {\n      // Map delete (and backspace on Mac) to item deletion (unless focus is\n      // in an input field, where it's intended for text editing).\n      if ((e.keyCode == 46 || (e.keyCode == 8 && cr.isMac)) &&\n          e.target.tagName != 'INPUT') {\n        this.deleteSelectedItems_();\n        // Prevent the browser from going back.\n        e.preventDefault();\n      }\n    },\n\n    /**\n     * Deletes all the currently selected items that are deletable.\n     * @private\n     */\n    deleteSelectedItems_: function() {\n      var selected = this.selectionModel.selectedIndexes;\n      // Reverse through the list of selected indexes to maintain the\n      // correct index values after deletion.\n      for (var j = selected.length - 1; j >= 0; j--) {\n        var index = selected[j];\n        if (this.getListItemByIndex(index).deletable)\n          this.deleteItemAtIndex(index);\n      }\n    },\n\n    /**\n     * Called when an item should be deleted; subclasses are responsible for\n     * implementing.\n     * @param {number} index The index of the item that is being deleted.\n     */\n    deleteItemAtIndex: function(index) {\n    },\n  };\n\n  return {\n    DeletableItemList: DeletableItemList,\n    DeletableItem: DeletableItem,\n  };\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/options/js/inline_editable_list.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\ncr.define('options', function() {\n  const DeletableItem = options.DeletableItem;\n  const DeletableItemList = options.DeletableItemList;\n\n  /**\n   * Creates a new list item with support for inline editing.\n   * @constructor\n   * @extends {options.DeletableListItem}\n   */\n  function InlineEditableItem() {\n    var el = cr.doc.createElement('div');\n    InlineEditableItem.decorate(el);\n    return el;\n  }\n\n  /**\n   * Decorates an element as a inline-editable list item. Note that this is\n   * a subclass of DeletableItem.\n   * @param {!HTMLElement} el The element to decorate.\n   */\n  InlineEditableItem.decorate = function(el) {\n    el.__proto__ = InlineEditableItem.prototype;\n    el.decorate();\n  };\n\n  InlineEditableItem.prototype = {\n    __proto__: DeletableItem.prototype,\n\n    /**\n     * Whether or not this item can be edited.\n     * @type {boolean}\n     * @private\n     */\n    editable_: true,\n\n    /**\n     * Whether or not this is a placeholder for adding a new item.\n     * @type {boolean}\n     * @private\n     */\n    isPlaceholder_: false,\n\n    /**\n     * Fields associated with edit mode.\n     * @type {array}\n     * @private\n     */\n    editFields_: null,\n\n    /**\n     * Whether or not the current edit should be considered cancelled, rather\n     * than committed, when editing ends.\n     * @type {boolean}\n     * @private\n     */\n    editCancelled_: true,\n\n    /**\n     * The editable item corresponding to the last click, if any. Used to decide\n     * initial focus when entering edit mode.\n     * @type {HTMLElement}\n     * @private\n     */\n    editClickTarget_: null,\n\n    /** @inheritDoc */\n    decorate: function() {\n      DeletableItem.prototype.decorate.call(this);\n\n      this.editFields_ = [];\n      this.addEventListener('mousedown', this.handleMouseDown_);\n      this.addEventListener('keydown', this.handleKeyDown_);\n      this.addEventListener('leadChange', this.handleLeadChange_);\n    },\n\n    /** @inheritDoc */\n    selectionChanged: function() {\n      this.updateEditState();\n    },\n\n    /**\n     * Called when this element gains or loses 'lead' status. Updates editing\n     * mode accordingly.\n     * @private\n     */\n    handleLeadChange_: function() {\n      this.updateEditState();\n    },\n\n    /**\n     * Updates the edit state based on the current selected and lead states.\n     */\n    updateEditState: function() {\n      if (this.editable)\n        this.editing = this.selected && this.lead;\n    },\n\n    /**\n     * Whether the user is currently editing the list item.\n     * @type {boolean}\n     */\n    get editing() {\n      return this.hasAttribute('editing');\n    },\n    set editing(editing) {\n      if (this.editing == editing)\n        return;\n\n      if (editing)\n        this.setAttribute('editing', '');\n      else\n        this.removeAttribute('editing');\n\n      if (editing) {\n        this.editCancelled_ = false;\n\n        cr.dispatchSimpleEvent(this, 'edit', true);\n\n        var focusElement = this.editClickTarget_ || this.initialFocusElement;\n        this.editClickTarget_ = null;\n\n        // When this is called in response to the selectedChange event,\n        // the list grabs focus immediately afterwards. Thus we must delay\n        // our focus grab.\n        var self = this;\n        if (focusElement) {\n          window.setTimeout(function() {\n            // Make sure we are still in edit mode by the time we execute.\n            if (self.editing) {\n              focusElement.focus();\n              focusElement.select();\n            }\n          }, 50);\n        }\n      } else {\n        if (!this.editCancelled_ && this.hasBeenEdited &&\n            this.currentInputIsValid) {\n          if (this.isPlaceholder)\n            this.parentNode.focusPlaceholder = true;\n\n          this.updateStaticValues_();\n          cr.dispatchSimpleEvent(this, 'commitedit', true);\n        } else {\n          this.resetEditableValues_();\n          cr.dispatchSimpleEvent(this, 'canceledit', true);\n        }\n      }\n    },\n\n    /**\n     * Whether the item is editable.\n     * @type {boolean}\n     */\n    get editable() {\n      return this.editable_;\n    },\n    set editable(editable) {\n      this.editable_ = editable;\n      if (!editable)\n        this.editing = false;\n    },\n\n    /**\n     * Whether the item is a new item placeholder.\n     * @type {boolean}\n     */\n    get isPlaceholder() {\n      return this.isPlaceholder_;\n    },\n    set isPlaceholder(isPlaceholder) {\n      this.isPlaceholder_ = isPlaceholder;\n      if (isPlaceholder)\n        this.deletable = false;\n    },\n\n    /**\n     * The HTML element that should have focus initially when editing starts,\n     * if a specific element wasn't clicked.\n     * Defaults to the first <input> element; can be overriden by subclasses if\n     * a different element should be focused.\n     * @type {HTMLElement}\n     */\n    get initialFocusElement() {\n      return this.contentElement.querySelector('input');\n    },\n\n    /**\n     * Whether the input in currently valid to submit. If this returns false\n     * when editing would be submitted, either editing will not be ended,\n     * or it will be cancelled, depending on the context.\n     * Can be overrided by subclasses to perform input validation.\n     * @type {boolean}\n     */\n    get currentInputIsValid() {\n      return true;\n    },\n\n    /**\n     * Returns true if the item has been changed by an edit.\n     * Can be overrided by subclasses to return false when nothing has changed\n     * to avoid unnecessary commits.\n     * @type {boolean}\n     */\n    get hasBeenEdited() {\n      return true;\n    },\n\n    /**\n     * Returns a div containing an <input>, as well as static text if\n     * isPlaceholder is not true.\n     * @param {string} text The text of the cell.\n     * @return {HTMLElement} The HTML element for the cell.\n     * @private\n     */\n    createEditableTextCell: function(text) {\n      var container = this.ownerDocument.createElement('div');\n\n      if (!this.isPlaceholder) {\n        var textEl = this.ownerDocument.createElement('div');\n        textEl.className = 'static-text';\n        textEl.textContent = text;\n        textEl.setAttribute('displaymode', 'static');\n        container.appendChild(textEl);\n      }\n\n      var inputEl = this.ownerDocument.createElement('input');\n      inputEl.type = 'text';\n      inputEl.value = text;\n      if (!this.isPlaceholder) {\n        inputEl.setAttribute('displaymode', 'edit');\n        inputEl.staticVersion = textEl;\n      } else {\n        // At this point |this| is not attached to the parent list yet, so give\n        // a short timeout in order for the attachment to occur.\n        var self = this;\n        window.setTimeout(function() {\n          var list = self.parentNode;\n          if (list && list.focusPlaceholder) {\n            list.focusPlaceholder = false;\n            if (list.shouldFocusPlaceholder())\n              inputEl.focus();\n          }\n        }, 50);\n      }\n\n      inputEl.addEventListener('focus', this.handleFocus_.bind(this));\n      container.appendChild(inputEl);\n      this.editFields_.push(inputEl);\n\n      return container;\n    },\n\n    /**\n     * Resets the editable version of any controls created by createEditable*\n     * to match the static text.\n     * @private\n     */\n    resetEditableValues_: function() {\n      var editFields = this.editFields_;\n      for (var i = 0; i < editFields.length; i++) {\n        var staticLabel = editFields[i].staticVersion;\n        if (!staticLabel && !this.isPlaceholder)\n          continue;\n\n        if (editFields[i].tagName == 'INPUT') {\n          editFields[i].value =\n            this.isPlaceholder ? '' : staticLabel.textContent;\n        }\n        // Add more tag types here as new createEditable* methods are added.\n\n        editFields[i].setCustomValidity('');\n      }\n    },\n\n    /**\n     * Sets the static version of any controls created by createEditable*\n     * to match the current value of the editable version. Called on commit so\n     * that there's no flicker of the old value before the model updates.\n     * @private\n     */\n    updateStaticValues_: function() {\n      var editFields = this.editFields_;\n      for (var i = 0; i < editFields.length; i++) {\n        var staticLabel = editFields[i].staticVersion;\n        if (!staticLabel)\n          continue;\n\n        if (editFields[i].tagName == 'INPUT')\n          staticLabel.textContent = editFields[i].value;\n        // Add more tag types here as new createEditable* methods are added.\n      }\n    },\n\n    /**\n     * Called a key is pressed. Handles committing and cancelling edits.\n     * @param {Event} e The key down event.\n     * @private\n     */\n    handleKeyDown_: function(e) {\n      if (!this.editing)\n        return;\n\n      var endEdit = false;\n      switch (e.key) {\n        case 'Escape':\n          this.editCancelled_ = true;\n          endEdit = true;\n          break;\n        case 'Enter':\n          if (this.currentInputIsValid)\n            endEdit = true;\n          break;\n      }\n\n      if (endEdit) {\n        // Blurring will trigger the edit to end; see InlineEditableItemList.\n        this.ownerDocument.activeElement.blur();\n        // Make sure that handled keys aren't passed on and double-handled.\n        // (e.g., esc shouldn't both cancel an edit and close a subpage)\n        e.stopPropagation();\n      }\n    },\n\n    /**\n     * Called when the list item is clicked. If the click target corresponds to\n     * an editable item, stores that item to focus when edit mode is started.\n     * @param {Event} e The mouse down event.\n     * @private\n     */\n    handleMouseDown_: function(e) {\n      if (!this.editable || this.editing)\n        return;\n\n      var clickTarget = e.target;\n      var editFields = this.editFields_;\n      for (var i = 0; i < editFields.length; i++) {\n        if (editFields[i] == clickTarget ||\n            editFields[i].staticVersion == clickTarget) {\n          this.editClickTarget_ = editFields[i];\n          return;\n        }\n      }\n    },\n  };\n\n  /**\n   * Takes care of committing changes to inline editable list items when the\n   * window loses focus.\n   */\n  function handleWindowBlurs() {\n    window.addEventListener('blur', function(e) {\n      var itemAncestor = findAncestor(document.activeElement, function(node) {\n        return node instanceof InlineEditableItem;\n      });\n      if (itemAncestor);\n        document.activeElement.blur();\n    });\n  }\n  handleWindowBlurs();\n\n  var InlineEditableItemList = cr.ui.define('list');\n\n  InlineEditableItemList.prototype = {\n    __proto__: DeletableItemList.prototype,\n\n    /**\n     * Focuses the input element of the placeholder if true.\n     * @type {boolean}\n     */\n    focusPlaceholder: false,\n\n    /** @inheritDoc */\n    decorate: function() {\n      DeletableItemList.prototype.decorate.call(this);\n      this.setAttribute('inlineeditable', '');\n      this.addEventListener('hasElementFocusChange',\n                            this.handleListFocusChange_);\n    },\n\n    /**\n     * Called when the list hierarchy as a whole loses or gains focus; starts\n     * or ends editing for the lead item if necessary.\n     * @param {Event} e The change event.\n     * @private\n     */\n    handleListFocusChange_: function(e) {\n      var leadItem = this.getListItemByIndex(this.selectionModel.leadIndex);\n      if (leadItem) {\n        if (e.newValue)\n          leadItem.updateEditState();\n        else\n          leadItem.editing = false;\n      }\n    },\n\n    /**\n     * May be overridden by subclasses to disable focusing the placeholder.\n     * @return true if the placeholder element should be focused on edit commit.\n     */\n    shouldFocusPlaceholder: function() {\n      return true;\n    },\n  };\n\n  // Export\n  return {\n    InlineEditableItem: InlineEditableItem,\n    InlineEditableItemList: InlineEditableItemList,\n  };\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/plugin_settings/options.html",
    "content": "<!DOCTYPE HTML>\n<html>\n<head>\n<link rel=\"stylesheet\" href=\"domui/css/button.css\">\n<link rel=\"stylesheet\" href=\"domui/css/chrome_shared.css\">\n<link rel=\"stylesheet\" href=\"domui/css/list.css\">\n<link rel=\"stylesheet\" href=\"domui/css/select.css\">\n\n<link rel=\"stylesheet\" href=\"options/css/list.css\">\n\n<link rel=\"stylesheet\" href=\"css/plugin_list.css\">\n<link rel=\"stylesheet\" href=\"css/rule_list.css\">\n\n<script src=\"domui/js/cr.js\"></script>\n<script src=\"domui/js/cr/event_target.js\"></script>\n<script src=\"domui/js/cr/ui.js\"></script>\n<script src=\"domui/js/cr/ui/array_data_model.js\"></script>\n<script src=\"domui/js/cr/ui/list_item.js\"></script>\n<script src=\"domui/js/cr/ui/list_selection_controller.js\"></script>\n<script src=\"domui/js/cr/ui/list_selection_model.js\"></script>\n<script src=\"domui/js/cr/ui/list_single_selection_model.js\"></script>\n<script src=\"domui/js/cr/ui/list.js\"></script>\n<script src=\"domui/js/util.js\"></script>\n\n<script src=\"options/js/deletable_item_list.js\"></script>\n<script src=\"options/js/inline_editable_list.js\"></script>\n\n<script src=\"js/plugin_list.js\" type=\"text/javascript\"></script>\n<script src=\"js/plugin_settings.js\" type=\"text/javascript\"></script>\n<script src=\"js/rule_list.js\" type=\"text/javascript\"></script>\n\n<script src=\"js/main.js\" type=\"text/javascript\"></script>\n</head>\n<body>\n<list id=\"plugin-list\"></list>\n<div id=\"error\"></div>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/proxy_configuration/_locales/en/messages.json",
    "content": "{\n  \"extName\":  {\n    \"message\": \"Proxy Extension API Sample\",\n    \"description\": \"The extension name.\"\n  },\n  \"extDescription\": {\n    \"message\": \"Set Chrome-specific proxies; a demonstration of Chrome's Proxy API\",\n    \"description\": \"The extension description.\"\n  },\n  \"headerDirectConnection\": {\n    \"message\": \"Direct Connection\",\n    \"description\": \"Header for 'Direct Connection' configuration `fieldset`.\"\n  },\n  \"errorNoExtensionAccess\": {\n    \"message\": \"Sorry. This browser's proxy settings cannot be controlled via extensions.\",\n    \"description\": \"Error message displayed when `levelOfControl` is 'not_controllable'.\"\n  },\n  \"errorOtherExtensionControls\": {\n    \"message\": \"Sorry. This browser's proxy settings are being controlled by another extension. Please visit chrome://extensions for details.\",\n    \"description\": \"Error message displayed when `levelOfControl` is 'controlled_by_other_extensions'.\"\n  },\n  \"errorSettingRegularProxy\": {\n    \"message\": \"Setting regular proxy settings failed.  Sorry!\",\n    \"description\": \"Error message, displayed when failing to set regular proxy settings.\"\n  },\n  \"errorSettingIncognitoProxy\": {\n    \"message\": \"Setting incognito proxy settings failed.  Sorry!\",\n    \"description\": \"Error message, displayed when failing to set incognito proxy settings.\"\n  },\n  \"successfullySetProxy\": {\n    \"message\": \"Your proxy settings have been saved successfully; this window will close automagically. Have a nice day!\",\n    \"description\": \"Success message, displayed after proxy settings have been written.\"\n  },\n  \"errorPopupTitle\": {\n    \"message\": \"Error: $1\",\n    \"description\": \"Error message used as popup title.\"\n  },\n  \"errorProxyError\": {\n    \"message\": \"ProxyError: $1.\",\n    \"description\": \"Error message displayed in popup when an error occurs.\"\n  },\n  \"errorProxyDetailedError\": {\n    \"message\": \"ProxyError: $1. $2.\",\n    \"description\": \"Error message displayed in popup when an error occurs.\"\n  },\n  \"errorIdNotFound\": {\n    \"message\": \"Element with ID `$1` doesn't exist in the document\",\n    \"description\": \"Error message thrown when the given `id` doesn't exist\"\n  },\n  \"errorIdNotForm\": {\n    \"message\": \"Element with ID `$1` isn't a form element.\",\n    \"description\": \"Error message thrown when the given `id` isn't a form element.\"\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/proxy_configuration/background.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview This file initializes the background page by loading a\n * ProxyErrorHandler, and resetting proxy settings if required.\n *\n * @author Mike West <mkwst@google.com>\n */\n\ndocument.addEventListener(\"DOMContentLoaded\", function () {\n  var errorHandler = new ProxyErrorHandler();\n\n  // If this extension has already set the proxy settings, then reset it\n  // once as the background page initializes.  This is essential, as\n  // incognito settings are wiped on restart.\n  var persistedSettings = ProxyFormController.getPersistedSettings();\n  if (persistedSettings !== null) {\n    chrome.proxy.settings.set(\n        {'value': persistedSettings.regular});\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/proxy_configuration/manifest.json",
    "content": "{\n  \"name\": \"__MSG_extName__\",\n  \"version\": \"0.4\",\n  \"description\": \"__MSG_extDescription__\",\n  \"default_locale\": \"en\",\n  \"browser_action\": {\n    \"default_icon\": \"icon16.png\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"icons\": {\n    \"16\": \"icon16.png\",\n    \"32\": \"icon32.png\",\n    \"48\": \"icon48.png\",\n    \"128\": \"icon128.png\"\n  },\n  \"background\": {\n    \"scripts\": [\n      \"proxy_form_controller.js\",\n      \"proxy_error_handler.js\",\n      \"background.js\"\n    ]\n  },\n  \"permissions\": [\n    \"proxy\"\n  ],\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/proxy_configuration/popup.css",
    "content": "body {\n  margin: 5px 10px 10px;\n}\n\nh1 {\n  color: #53637D;\n  font: 26px/1.2 Helvetica, sans-serif;\n  font-size: 200%;\n  margin: 0;\n  padding-bottom: 4px;\n  text-shadow: white 0 1px 2px;\n}\n\ndiv[role='main'] {\n  border-radius: 5px;\n  background: #EAEEF3;\n  font: 14px/1 Arial,Sans Serif;\n  padding: 10px;\n  width: 563px;\n  box-shadow: inset 0px 2px 5px rgba(0,0,0,0.5);\n  overflow: hidden;\n  transition: background-color 0.5s ease-out;\n}\n\ndiv[role='main'].incognito {\n  background: #496281 url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAhCAYAAABeD2IVAAAFz0lEQVRYw8VYC0xcRRQtUEprERQ1VkohSGNpwaCYYNBUjS2K+KEVTUkDiqY0hWD5xxhDINgQqIZviRAkSiiWNDRxWypNpaatEQk/CwvlWyks3+XPAssu7I7nbmabx+suPzfrTU7yljfz5sy95947w5YtpjcLwBLYBuzgsAGs+DuzGZGwBh4BHIDdwHPA8xxuwBOcnIWpPUAL7wQeB54CngYcAWdO4kXgDeBoWFhYSk5OTtmFCxeuxsbGpuBv3sCTwFZTkrLmXtgH+AJ+QAAQCBzz8/P7MiUl5aebN29Kh4eHFVNTU2xoaIgNDAywe/fusYyMjO858R2mJEUe2ldZWfljd3f3P+3t7bK2trZBuVyuYCJbXFxkXV1drLOzU4e7d++yzMzMasz3AexMSYq89CoRYuuwvr6+B6Q6OjpYUVFRG+Yf4iE0iZYoc5woVK2trUPrIUXh05Mir9XW1qow/33gmf8idj0ZypjHuIgj5ubm1OshpdFoVoTwzp07zMbGJsTb23s/16fFZlKcyDjY29u7+fr6HoJFV1dXt7EN2MjIyANSUqmUubq6Jtna2r7OvWW7kUy04IR2+fj4HDx+/HhUYmJiIQQuhZ5mN0JKqVSuEHtWVlbd6dOns+3s7N7h9YtKynbuhFWNQuYQGBh4ODs7u2B0dHRauNDMzIx2eXmZabXadRG7f/++jhSylV25ckXOk2D4yJEjSVjnNV7ntq9Fily6Jzg4+CTEOqf/OJFoampSFRQUjDc3Ny+QF9RqtU47hozGE3mUDIbxOtTX1ytQt5T6MQipFGu9zDPbYq0i+ey5c+dyxAvBSxrsXHXixIlmVOsOaGykp6dnYXZ2lt49BHhIWVdXN1VaWipLS0trCQ8P/xseUwrD6+HhEUJO4BFa3VMREREx4+PjCkNhunjx4iAWuI0x16KjowlVYkA7uncYczUyMpJ+3z579mzXwsLCA9fimcXHx6djvb3cGatmHrnTBxr4jSZShaYwCQnC89PQXFNUVNSvMTExv6C/XYqLi6sg0DMISRISEq7h+QY81dHY2DgpDq9CoWCYm8Fbl8FmLaxLROoA8OGpU6dKL1++LCMdGdIPEkF569atIYlE0oNNdGFsNz03NDTI0QOVhrRG31GpVCR4JcrEV1jnFWOZaMVrBx07vIDDQBiQil3XQENDMplseWlpiW3WBOLXovWoy8vLBxA+CTT6NdZ5gR9vtooFvis1NfWTioqKn6uqqv6ihius4NCYZn5+Xuf2zRAi4OSgQQIsT05OrnA71qrmR6BtQlL0wwVpL1nPIqQzCgFpzlB50HuFxlF2TkxMUKiXxBKgb4Dooqen5zHeX63FWUfl/22k/aix+qM3IkEeS05Obs7Pz6+vqakZgAcUY2Njur8T2cHBwSXobbSwsPCPgICAAny7QJgstAaVjry8vEquKwexpiz5WccrJCTkDO1yLWIILcP474DPgQ8oMahpA9+C0FxJSUk7nr/h2vwMSAfhJWFJQAKN8Xku4tCJveWP3d8gb6zWToh0aGjoJYz/FHgToGYbTMmBUM0RnJyccvE7GkiEVlv1cylhpqenGbI7l4v8UWNVfRsn5efs7Jxx/vz5fr0+VvGWuqysrMbNzS0R88KDgoLyEMo+/XvyDI4tcmHC6GsUSkgL5rxFCWbsxGDFY/oSdn+mt7d3gj5w/fp15VrENmokbvRANTbyBdbbz8/tBgsn1agD/v7+cUh7lfAj2KmGmdAoI9PT0//kOnQ01vesedF8t7+/X27oQ0hbrSmJoXBKucD3GAsd3VS8cDIoY2YykgM6RS4/Zj8kckt+sfTDeaeHmdFwHxzj98Y94qKpOz+5u7ufZGY28haOyOX89rzCW9SZ3YuLi39g/4Mhy4ex/kHejFeQ2tvS0vI79ShqE+YEmjxLSkoK5aQsheGjW6snv8EeBT42Az4C3uP/l3DhyWYhvuPZ84PWbt6tzQFH7pCdvCzoSP0LtBi6oflBr2wAAAAASUVORK5CYII=') no-repeat 533px bottom;\n}\n\nform {\n  transition: transform 0.25s ease;\n  width: 563px;\n}\n\nform.offscreen {\n  transform: translateX(-600px);\n}\n\nfieldset {\n  border: 0;\n  margin: 0;\n  padding: 0;\n  position: relative;\n}\n\nlegend {\n  position: absolute;\n  left: -999em;\n}\n\nform > fieldset {\n  border-radius:  5px;\n  border: 1px solid transparent;\n  padding: 10px 10px 10px 30px;\n  margin: 5px 0;\n  transition: all 0.5s ease;\n}\n\nform > fieldset:hover {\n  background: rgba(255,255,255,0.1);\n  border-color: rgba(0,0,0,0.1);\n}\n\nform > fieldset.active {\n  background: rgba(255,255,255,0.25);\n  border-color: rgba(0,0,0,0.25);\n}\n\nform > fieldset > input {\n  margin-left:  -20px;\n}\n\nsection {\n  margin: 5px 0 0;\n}\n\nsection fieldset:not(:first-child):not(:last-child) {\n  max-height: 1.6em;\n  overflow: hidden;\n  transition: all 0.5s ease;\n}\n\nsection.single fieldset:not(:first-child):not(:last-child) {\n  max-height: 0px;\n}\n\nsection fieldset:last-child {\n  margin-top: 5px;\n}\n\nsection fieldset:last-child label {\n  display: block;\n}\n\nsection fieldset:last-child textarea {\n  width: 412px;\n}\n\nsection > fieldset {\n  position: relative;\n  padding-left: 60px;\n}\n\nsection > fieldset > legend {\n  left: 0;\n  top: 4px;\n  width: 53px;\n  text-align: right;\n}\n\ninput[type='url']:invalid:not(:active):not(:focus) {\n  border-color: rgba(255,0,0,0.5);\n  background: rgba(255,0,0,0.25);\n}\n\ninput:invalid:not(:active):not(:focus):after {\n  content: \"This isn't a valid URL!\";\n  display:block;\n}\n\ninput[type=\"checkbox\"] {\n  margin: 5px 0 5px 35px;\n}\n\ninput[type=\"text\"] {\n  width: 200px;\n  margin: 0 10px 0 0;\n}\n\ninput.port {\n  width: 50px;\n  margin: 2px 10px 0 5px;\n}\n\nsection label,\nsection legend {\n  color:  #999;\n  transition: color 0.5s ease;\n}\n\n.incognito section label,\n.incognito section legend {\n  color:  #BBB;\n}\n\n.active section label,\n.active section legend,\nform > fieldset > label  {\n  color:  #000;\n  transition: color 0.5s ease;\n}\n\n.incognito .active section label,\n.incognito .active section legend,\n.incognito form > fieldset > label {\n  color: #FFF;\n}\n\ninput[type=\"submit\"],\nbutton {\n  border-radius: 2px;\n  box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);\n  -webkit-user-select: none;\n  background: -webkit-linear-gradient(#FAFAFA, #F4F4F4 40%, #E5E5E5);\n  border: 1px solid #AAA;\n  color: #444;\n  margin-bottom: 0;\n  min-width: 4em;\n  padding: 3px 12px;\n  margin-top: 0;\n  font-size: 1.1em;\n}\n\n.overlay {\n  display: block;\n  text-align: center;\n  position: absolute;\n  left: 50%;\n  top: 50%;\n  width: 500px;\n  padding: 20px;\n  margin: -80px 0 0 -270px;\n  opacity: 0;\n  background: rgba(0, 0, 0, 0.75);\n  border-radius: 5px;\n  color: #FFF;\n  font: 1.5em/1.2 Helvetica Neue, sans-serif;\n  transform: scale(0);\n  transition: all 1.0s ease;\n}\n\n.overlay a {\n  color:  #FFF;\n}\n\n.overlay.visible {\n  opacity: 1;\n  transform: scale(1);\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/proxy_configuration/popup.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <title>Popup for Proxy API Test</title>\n  <link href=\"./popup.css\" type=\"text/css\" rel=\"stylesheet\">\n</head>\n<body>\n  <h1>Proxy Configuration</h1>\n  <div role=\"main\">\n    <form id=\"proxyForm\">\n      <fieldset id=\"system\">\n        <legend>System Settings</legend>\n        <input type=\"radio\" name=\"proxyType\" id=\"proxyTypeSystem\" value=\"system\">\n        <label for=\"proxyTypeSystem\">Use the <em>system's proxy settings</em>.</label>\n      </fieldset>\n      <fieldset id=\"direct\">\n        <legend>Direct Connection</legend>\n        <input type=\"radio\" name=\"proxyType\" id=\"proxyTypeDirect\" value=\"direct\">\n        <label for=\"proxyTypeDirect\">Your computer is <em>directly connected</em> to the internet; no need for a proxy.</label>\n      </fieldset>\n      <fieldset id=\"pac_script\">\n        <legend>Automatic Configuration</legend>\n        <input type=\"radio\" name=\"proxyType\" id=\"proxyTypeAutoconfig\" value=\"autoconfig\">\n        <label for=\"proxyTypeAutoconfig\">Your proxy supports <em>automatic configuration</em>.</label>\n\n        <section>\n          <label for=\"autoconfigURL\">Autoconfiguration URL (PAC file)</label>\n          <input type=\"url\" name=\"autoconfigURL\" id=\"autoconfigURL\">\n          <input type=\"hidden\" name=\"autoconfigData\" id=\"autoconfigData\">\n        </section>\n      </fieldset>\n      <fieldset id=\"fixed_servers\">\n        <legend>Manual Proxy</legend>\n        <input type=\"radio\" name=\"proxyType\" id=\"proxyTypeManual\" value=\"manual\">\n        <label for=\"proxyTypeManual\">Configure your proxy settings <em>manually</em>.</label>\n        <section>\n          <fieldset>\n            <legend>HTTP</legend>\n            <label for=\"proxyHostHttp\">Host</label>\n            <select id=\"proxySchemeHttp\" name=\"proxySchemeHttp\">\n              <option selected value=\"http\">http://</option>\n              <option value=\"https\">https://</option>\n              <option value=\"socks4\">socks4://</option>\n              <option value=\"socks5\">socks5://</option>\n            </select>\n            <input type=\"text\" name=\"proxyHostHttp\" id=\"proxyHostHttp\">\n\n            <label for=\"proxyPortHttp\">Port</label>\n            <input type=\"text\" name=\"proxyPortHttp\" id=\"proxyPortHttp\" class=\"port\">\n\n            <input type=\"checkbox\" name=\"singleProxyForEverything\" id=\"singleProxyForEverything\">\n            <label for=\"singleProxyForEverything\">Use the same proxy server for all protocols</label>\n          </fieldset>\n          <fieldset>\n            <legend>HTTPS</legend>\n            <label for=\"proxyHostHttps\">Host</label>\n            <select id=\"proxySchemeHttps\" name=\"proxySchemeHttps\">\n              <option selected value=\"http\">http://</option>\n              <option value=\"https\">https://</option>\n              <option value=\"socks4\">socks4://</option>\n              <option value=\"socks5\">socks5://</option>\n            </select>\n            <input type=\"text\" name=\"proxyHostHttps\" id=\"proxyHostHttps\">\n\n            <label for=\"proxyPortHttps\">Port</label>\n            <input type=\"text\" name=\"proxyPortHttps\" id=\"proxyPortHttps\" class=\"port\">\n          </fieldset>\n          <fieldset>\n            <legend>FTP</legend>\n            <label for=\"proxyHostFtp\">Host</label>\n            <select id=\"proxySchemeFtp\" name=\"proxySchemeFtp\">\n              <option selected value=\"http\">http://</option>\n              <option value=\"https\">https://</option>\n              <option value=\"socks4\">socks4://</option>\n              <option value=\"socks5\">socks5://</option>\n            </select>\n            <input type=\"text\" name=\"proxyHostFtp\" id=\"proxyHostFtp\">\n\n            <label for=\"proxyPortFtp\">Port</label>\n            <input type=\"text\" name=\"proxyPortFtp\" id=\"proxyPortFtp\" class=\"port\">\n          </fieldset>\n          <fieldset>\n            <legend>Fallback</legend>\n            <label for=\"proxyHostFallback\">Host</label>\n            <select id=\"proxySchemeFallback\" name=\"proxySchemeFallback\">\n              <option selected value=\"http\">http://</option>\n              <option value=\"https\">https://</option>\n              <option value=\"socks4\">socks4://</option>\n              <option value=\"socks5\">socks5://</option>\n            </select>\n            <input type=\"text\" name=\"proxyHostFallback\" id=\"proxyHostFallback\">\n\n            <label for=\"proxyPortFallback\">Port</label>\n            <input type=\"text\" name=\"proxyPortFallback\" id=\"proxyPortFallback\" class=\"port\">\n          </fieldset>\n          <fieldset>\n            <label for=\"bypassList\">Bypass proxy for these hosts:</label>\n            <textarea id=\"bypassList\" name=\"bypassList\" placeholder=\"<local>,192.168.1.1/16, .example.com\"></textarea>\n          </fieldset>\n        </section>\n      </fieldset>\n      <input type=\"submit\" value=\"Save proxy settings\">\n      <button value=\"incognito\">Configure incognito window settings.</button>\n    </form>\n  </div>\n  <script src=\"./proxy_form_controller.js\"></script>\n  <script src=\"./popup.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/proxy_configuration/popup.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview This file initializes the extension's popup by creating a\n * ProxyFormController object.\n *\n * @author Mike West <mkwst@google.com>\n */\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  var c = new ProxyFormController( 'proxyForm' );\n});\n"
  },
  {
    "path": "_archive/mv2/extensions/proxy_configuration/proxy_error_handler.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview This file implements the ProxyErrorHandler class, which will\n * flag proxy errors in a visual way for the extension's user.\n *\n * @author Mike West <mkwst@google.com>\n */\n\n\n/**\n * The proxy error handling object. Binds to the 'onProxyError' event, and\n * changes the extensions badge to reflect the error state (yellow for\n * non-fatal errors, red for fatal).\n *\n * @constructor\n */\nfunction ProxyErrorHandler() {\n  // Handle proxy error events.\n  chrome.proxy.onProxyError.addListener(this.handleError_.bind(this));\n\n  // Handle message events from popup.\n  chrome.extension.onRequest.addListener(this.handleOnRequest_.bind(this));\n};\n\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n * @typedef {{fatal: boolean, error: string, details: string}}\n */\nProxyErrorHandler.ErrorDetails;\n\n///////////////////////////////////////////////////////////////////////////////\n\nProxyErrorHandler.prototype = {\n  /**\n   * Details of the most recent error.\n   * @type {?ProxyErrorHandler.ErrorDetails}\n   * @private\n   */\n  lastError_: null,\n\n   /**\n    * Handle request messages from the popup.\n    *\n    * @param {!{type:string}} request The external request to answer.\n    * @param {!MessageSender} sender Info about the script context that sent\n    *     the request.\n    * @param {!function} sendResponse Function to call to send a response.\n    * @private\n    */\n  handleOnRequest_: function(request, sender, sendResponse) {\n    if (request.type === 'getError') {\n      sendResponse({result: this.getErrorDetails()});\n    } else if (request.type === 'clearError') {\n      this.clearErrorDetails();\n      sendResponse({result: true});\n    }\n  },\n\n  /**\n   * Handles the error event, storing the error details for later use, and\n   * badges the browser action icon.\n   *\n   * @param {!ProxyErrorHandler.ErrorDetails} details The error details.\n   * @private\n   */\n  handleError_: function(details) {\n    var RED = [255, 0, 0, 255];\n    var YELLOW = [255, 205, 0, 255];\n\n    // Badge the popup icon.\n    var color = details.fatal ? RED : YELLOW;\n    chrome.browserAction.setBadgeBackgroundColor({color: color});\n    chrome.browserAction.setBadgeText({text: 'X'});\n    chrome.browserAction.setTitle({\n      title: chrome.i18n.getMessage('errorPopupTitle', details.error)\n    });\n\n    // Store the error for display in the popup.\n    this.lastError_ = JSON.stringify(details);\n  },\n\n\n  /**\n   * Returns details of the last error handled.\n   *\n   * @return {?ProxyErrorHandler.ErrorDetails}\n   */\n  getErrorDetails: function() {\n    return this.lastError_;\n  },\n\n\n  /**\n   * Clears last handled error.\n   */\n  clearErrorDetails: function() {\n    chrome.browserAction.setBadgeText({text: ''});\n    this.lastError_ = null;\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/proxy_configuration/proxy_form_controller.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * @fileoverview This file implements the ProxyFormController class, which\n * wraps a form element with logic that enables implementation of proxy\n * settings.\n *\n * @author mkwst@google.com (Mike West)\n */\n\n/**\n * Wraps the proxy configuration form, binding proper handlers to its various\n * `change`, `click`, etc. events in order to take appropriate action in\n * response to user events.\n *\n * @param {string} id The form's DOM ID.\n * @constructor\n */\nvar ProxyFormController = function(id) {\n  /**\n   * The wrapped form element\n   * @type {Node}\n   * @private\n   */\n  this.form_ = document.getElementById(id);\n\n  // Throw an error if the element either doesn't exist, or isn't a form.\n  if (!this.form_)\n    throw chrome.i18n.getMessage('errorIdNotFound', id);\n  else if (this.form_.nodeName !== 'FORM')\n    throw chrome.i18n.getMessage('errorIdNotForm', id);\n\n  /**\n   * Cached references to the `fieldset` groups that define the configuration\n   * options presented to the user.\n   *\n   * @type {NodeList}\n   * @private\n   */\n  this.configGroups_ = document.querySelectorAll('#' + id + ' > fieldset');\n\n  this.bindEventHandlers_();\n  this.readCurrentState_();\n\n  // Handle errors\n  this.handleProxyErrors_();\n};\n\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n * The proxy types we're capable of handling.\n * @enum {string}\n */\nProxyFormController.ProxyTypes = {\n  AUTO: 'auto_detect',\n  PAC: 'pac_script',\n  DIRECT: 'direct',\n  FIXED: 'fixed_servers',\n  SYSTEM: 'system'\n};\n\n/**\n * The window types we're capable of handling.\n * @enum {int}\n */\nProxyFormController.WindowTypes = {\n  REGULAR: 1,\n  INCOGNITO: 2\n};\n\n/**\n * The extension's level of control of Chrome's roxy setting\n * @enum {string}\n */\nProxyFormController.LevelOfControl = {\n  NOT_CONTROLLABLE: 'not_controllable',\n  OTHER_EXTENSION: 'controlled_by_other_extension',\n  AVAILABLE: 'controllable_by_this_extension',\n  CONTROLLING: 'controlled_by_this_extension'\n};\n\n/**\n * The response type from 'proxy.settings.get'\n *\n * @typedef {{value: ProxyConfig,\n *     levelOfControl: ProxyFormController.LevelOfControl}}\n */\nProxyFormController.WrappedProxyConfig;\n\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n * Retrieves proxy settings that have been persisted across restarts.\n *\n * @return {?ProxyConfig} The persisted proxy configuration, or null if no\n *     value has been persisted.\n * @static\n */\nProxyFormController.getPersistedSettings = function() {\n  var result = null;\n  if (window.localStorage['proxyConfig'] !== undefined)\n    result = JSON.parse(window.localStorage['proxyConfig']);\n  return result ? result : null;\n};\n\n\n/**\n * Persists proxy settings across restarts.\n *\n * @param {!ProxyConfig} config The proxy config to persist.\n * @static\n */\nProxyFormController.setPersistedSettings = function(config) {\n  window.localStorage['proxyConfig'] = JSON.stringify(config);\n};\n\n///////////////////////////////////////////////////////////////////////////////\n\nProxyFormController.prototype = {\n  /**\n   * The form's current state.\n   * @type {regular: ?ProxyConfig, incognito: ?ProxyConfig}\n   * @private\n   */\n  config_: {regular: null, incognito: null},\n\n  /**\n   * Do we have access to incognito mode?\n   * @type {boolean}\n   * @private\n   */\n  isAllowedIncognitoAccess_: false,\n\n  /**\n   * @return {string} The PAC file URL (or an empty string).\n   */\n  get pacURL() {\n    return document.getElementById('autoconfigURL').value;\n  },\n\n\n  /**\n   * @param {!string} value The PAC file URL.\n   */\n  set pacURL(value) {\n    document.getElementById('autoconfigURL').value = value;\n  },\n\n\n  /**\n   * @return {string} The PAC file data (or an empty string).\n   */\n  get manualPac() {\n    return document.getElementById('autoconfigData').value;\n  },\n\n\n  /**\n   * @param {!string} value The PAC file data.\n   */\n  set manualPac(value) {\n    document.getElementById('autoconfigData').value = value;\n  },\n\n\n  /**\n   * @return {Array<string>} A list of hostnames that should bypass the proxy.\n   */\n  get bypassList() {\n    return document.getElementById('bypassList').value.split(/\\s*(?:,|^)\\s*/m);\n  },\n\n\n  /**\n   * @param {?Array<string>} data A list of hostnames that should bypass\n   *     the proxy. If empty, the bypass list is emptied.\n   */\n  set bypassList(data) {\n    if (!data)\n      data = [];\n    document.getElementById('bypassList').value = data.join(', ');\n  },\n\n\n  /**\n   * @see http://code.google.com/chrome/extensions/trunk/proxy.html\n   * @return {?ProxyServer} An object containing the proxy server host, port,\n   *     and scheme. If null, there is no single proxy.\n   */\n  get singleProxy() {\n    var checkbox = document.getElementById('singleProxyForEverything');\n    return checkbox.checked ? this.httpProxy : null;\n  },\n\n\n  /**\n   * @see http://code.google.com/chrome/extensions/trunk/proxy.html\n   * @param {?ProxyServer} data An object containing the proxy server host,\n   *     port, and scheme. If null, the single proxy checkbox will be unchecked.\n   */\n  set singleProxy(data) {\n    var checkbox = document.getElementById('singleProxyForEverything');\n    checkbox.checked = !!data;\n\n    if (data)\n      this.httpProxy = data;\n\n    if (checkbox.checked)\n      checkbox.parentNode.parentNode.classList.add('single');\n    else\n      checkbox.parentNode.parentNode.classList.remove('single');\n  },\n\n  /**\n   * @return {?ProxyServer} An object containing the proxy server host, port\n   *     and scheme.\n   */\n  get httpProxy() {\n    return this.getProxyImpl_('Http');\n  },\n\n\n  /**\n   * @param {?ProxyServer} data An object containing the proxy server host,\n   *     port, and scheme. If empty, empties the proxy setting.\n   */\n  set httpProxy(data) {\n    this.setProxyImpl_('Http', data);\n  },\n\n\n  /**\n   * @return {?ProxyServer} An object containing the proxy server host, port\n   *     and scheme.\n   */\n  get httpsProxy() {\n    return this.getProxyImpl_('Https');\n  },\n\n\n  /**\n   * @param {?ProxyServer} data An object containing the proxy server host,\n   *     port, and scheme. If empty, empties the proxy setting.\n   */\n  set httpsProxy(data) {\n    this.setProxyImpl_('Https', data);\n  },\n\n\n  /**\n   * @return {?ProxyServer} An object containing the proxy server host, port\n   *     and scheme.\n   */\n  get ftpProxy() {\n    return this.getProxyImpl_('Ftp');\n  },\n\n\n  /**\n   * @param {?ProxyServer} data An object containing the proxy server host,\n   *     port, and scheme. If empty, empties the proxy setting.\n   */\n  set ftpProxy(data) {\n    this.setProxyImpl_('Ftp', data);\n  },\n\n\n  /**\n   * @return {?ProxyServer} An object containing the proxy server host, port\n   *     and scheme.\n   */\n  get fallbackProxy() {\n    return this.getProxyImpl_('Fallback');\n  },\n\n\n  /**\n   * @param {?ProxyServer} data An object containing the proxy server host,\n   *     port, and scheme. If empty, empties the proxy setting.\n   */\n  set fallbackProxy(data) {\n    this.setProxyImpl_('Fallback', data);\n  },\n\n\n  /**\n   * @param {string} type The type of proxy that's being set (\"Http\",\n   *     \"Https\", etc.).\n   * @return {?ProxyServer} An object containing the proxy server host,\n   *     port, and scheme.\n   * @private\n   */\n  getProxyImpl_: function(type) {\n    var result = {\n      scheme: document.getElementById('proxyScheme' + type).value,\n      host: document.getElementById('proxyHost' + type).value,\n      port: parseInt(document.getElementById('proxyPort' + type).value, 10)\n    };\n    return (result.scheme && result.host && result.port) ? result : undefined;\n  },\n\n\n  /**\n   * A generic mechanism for setting proxy data.\n   *\n   * @see http://code.google.com/chrome/extensions/trunk/proxy.html\n   * @param {string} type The type of proxy that's being set (\"Http\",\n   *     \"Https\", etc.).\n   * @param {?ProxyServer} data An object containing the proxy server host,\n   *     port, and scheme. If empty, empties the proxy setting.\n   * @private\n   */\n  setProxyImpl_: function(type, data) {\n    if (!data)\n      data = {scheme: 'http', host: '', port: ''};\n\n    document.getElementById('proxyScheme' + type).value = data.scheme;\n    document.getElementById('proxyHost' + type).value = data.host;\n    document.getElementById('proxyPort' + type).value = data.port;\n  },\n\n///////////////////////////////////////////////////////////////////////////////\n\n  /**\n   * Calls the proxy API to read the current settings, and populates the form\n   * accordingly.\n   *\n   * @private\n   */\n  readCurrentState_: function() {\n    chrome.extension.isAllowedIncognitoAccess(\n        this.handleIncognitoAccessResponse_.bind(this));\n  },\n\n  /**\n   * Handles the respnse from `chrome.extension.isAllowedIncognitoAccess`\n   * We can't render the form until we know what our access level is, so\n   * we wait until we have confirmed incognito access levels before\n   * asking for the proxy state.\n   *\n   * @param {boolean} state The state of incognito access.\n   * @private\n   */\n  handleIncognitoAccessResponse_: function(state) {\n    this.isAllowedIncognitoAccess_ = state;\n    chrome.proxy.settings.get({incognito: false},\n        this.handleRegularState_.bind(this));\n    if (this.isAllowedIncognitoAccess_) {\n      chrome.proxy.settings.get({incognito: true},\n          this.handleIncognitoState_.bind(this));\n    }\n  },\n\n  /**\n   * Handles the response from 'proxy.settings.get' for regular\n   * settings.\n   *\n   * @param {ProxyFormController.WrappedProxyConfig} c The proxy data and\n   *     extension's level of control thereof.\n   * @private\n   */\n  handleRegularState_: function(c) {\n    if (c.levelOfControl === ProxyFormController.LevelOfControl.AVAILABLE ||\n        c.levelOfControl === ProxyFormController.LevelOfControl.CONTROLLING) {\n      this.recalcFormValues_(c.value);\n      this.config_.regular = c.value;\n    } else {\n      this.handleLackOfControl_(c.levelOfControl);\n    }\n  },\n\n  /**\n   * Handles the response from 'proxy.settings.get' for incognito\n   * settings.\n   *\n   * @param {ProxyFormController.WrappedProxyConfig} c The proxy data and\n   *     extension's level of control thereof.\n   * @private\n   */\n  handleIncognitoState_: function(c) {\n    if (c.levelOfControl === ProxyFormController.LevelOfControl.AVAILABLE ||\n        c.levelOfControl === ProxyFormController.LevelOfControl.CONTROLLING) {\n      if (this.isIncognitoMode_())\n        this.recalcFormValues_(c.value);\n\n      this.config_.incognito = c.value;\n    } else {\n      this.handleLackOfControl_(c.levelOfControl);\n    }\n  },\n\n  /**\n   * Binds event handlers for the various bits and pieces of the form that\n   * are interesting to the controller.\n   *\n   * @private\n   */\n  bindEventHandlers_: function() {\n    this.form_.addEventListener('click', this.dispatchFormClick_.bind(this));\n  },\n\n\n  /**\n   * When a `click` event is triggered on the form, this function handles it by\n   * analyzing the context, and dispatching the click to the correct handler.\n   *\n   * @param {Event} e The event to be handled.\n   * @private\n   * @return {boolean} True if the event should bubble, false otherwise.\n   */\n  dispatchFormClick_: function(e) {\n    var t = e.target;\n\n    // Case 1: \"Apply\"\n    if (t.nodeName === 'INPUT' && t.getAttribute('type') === 'submit') {\n      return this.applyChanges_(e);\n\n    // Case 2: \"Use the same proxy for all protocols\" in an active section\n    } else if (t.nodeName === 'INPUT' &&\n               t.getAttribute('type') === 'checkbox' &&\n               t.parentNode.parentNode.parentNode.classList.contains('active')\n              ) {\n      return this.toggleSingleProxyConfig_(e);\n\n    // Case 3: \"Flip to incognito mode.\"\n    } else if (t.nodeName === 'BUTTON') {\n      return this.toggleIncognitoMode_(e);\n\n    // Case 4: Click on something random: maybe changing active config group?\n    } else {\n      // Walk up the tree until we hit `form > fieldset` or fall off the top\n      while (t && (t.nodeName !== 'FIELDSET' ||\n             t.parentNode.nodeName !== 'FORM')) {\n        t = t.parentNode;\n      }\n      if (t) {\n        this.changeActive_(t);\n        return false;\n      }\n    }\n    return true;\n  },\n\n\n  /**\n   * Sets the form's active config group.\n   *\n   * @param {DOMElement} fieldset The configuration group to activate.\n   * @private\n   */\n  changeActive_: function(fieldset) {\n    for (var i = 0; i < this.configGroups_.length; i++) {\n      var el = this.configGroups_[i];\n      var radio = el.querySelector(\"input[type='radio']\");\n      if (el === fieldset) {\n        el.classList.add('active');\n        radio.checked = true;\n      } else {\n        el.classList.remove('active');\n      }\n    }\n    this.recalcDisabledInputs_();\n  },\n\n\n  /**\n   * Recalculates the `disabled` state of the form's input elements, based\n   * on the currently active group, and that group's contents.\n   *\n   * @private\n   */\n  recalcDisabledInputs_: function() {\n    var i, j;\n    for (i = 0; i < this.configGroups_.length; i++) {\n      var el = this.configGroups_[i];\n      var inputs = el.querySelectorAll(\n          \"input:not([type='radio']), select, textarea\");\n      if (el.classList.contains('active')) {\n        for (j = 0; j < inputs.length; j++) {\n          inputs[j].removeAttribute('disabled');\n        }\n      } else {\n        for (j = 0; j < inputs.length; j++) {\n          inputs[j].setAttribute('disabled', 'disabled');\n        }\n      }\n    }\n  },\n\n\n  /**\n   * Handler called in response to click on form's submission button. Generates\n   * the proxy configuration and passes it to `useCustomProxySettings`, or\n   * handles errors in user input.\n   *\n   * Proxy errors (and the browser action's badge) are cleared upon setting new\n   * values.\n   *\n   * @param {Event} e DOM event generated by the user's click.\n   * @private\n   */\n  applyChanges_: function(e) {\n    e.preventDefault();\n    e.stopPropagation();\n\n    if (this.isIncognitoMode_())\n      this.config_.incognito = this.generateProxyConfig_();\n    else\n      this.config_.regular = this.generateProxyConfig_();\n\n    chrome.proxy.settings.set(\n        {value: this.config_.regular, scope: 'regular'},\n        this.callbackForRegularSettings_.bind(this));\n    chrome.extension.sendRequest({type: 'clearError'});\n  },\n\n  /**\n   * Called in response to setting a regular window's proxy settings: checks\n   * for `lastError`, and then sets incognito settings (if they exist).\n   *\n   * @private\n   */\n  callbackForRegularSettings_: function() {\n    if (chrome.runtime.lastError) {\n      this.generateAlert_(chrome.i18n.getMessage('errorSettingRegularProxy'));\n      return;\n    }\n    if (this.config_.incognito) {\n      chrome.proxy.settings.set(\n          {value: this.config_.incognito, scope: 'incognito_persistent'},\n          this.callbackForIncognitoSettings_.bind(this));\n    } else {\n      ProxyFormController.setPersistedSettings(this.config_);\n      this.generateAlert_(chrome.i18n.getMessage('successfullySetProxy'));\n    }\n  },\n\n  /**\n   * Called in response to setting an incognito window's proxy settings: checks\n   * for `lastError` and sets a success message.\n   *\n   * @private\n   */\n  callbackForIncognitoSettings_: function() {\n    if (chrome.runtime.lastError) {\n      this.generateAlert_(chrome.i18n.getMessage('errorSettingIncognitoProxy'));\n      return;\n    }\n    ProxyFormController.setPersistedSettings(this.config_);\n    this.generateAlert_(\n        chrome.i18n.getMessage('successfullySetProxy'));\n  },\n\n  /**\n   * Generates an alert overlay inside the proxy's popup, then closes the popup\n   * after a short delay.\n   *\n   * @param {string} msg The message to be displayed in the overlay.\n   * @param {?boolean} close Should the window be closed?  Defaults to true.\n   * @private\n   */\n  generateAlert_: function(msg, close) {\n    var success = document.createElement('div');\n    success.classList.add('overlay');\n    success.setAttribute('role', 'alert');\n    success.textContent = msg;\n    document.body.appendChild(success);\n\n    setTimeout(function() { success.classList.add('visible'); }, 10);\n    setTimeout(function() {\n      if (close === false)\n        success.classList.remove('visible');\n      else\n        window.close();\n    }, 4000);\n  },\n\n\n  /**\n   * Parses the proxy configuration form, and generates a ProxyConfig object\n   * that can be passed to `useCustomProxyConfig`.\n   *\n   * @see http://code.google.com/chrome/extensions/trunk/proxy.html\n   * @return {ProxyConfig} The proxy configuration represented by the form.\n   * @private\n   */\n  generateProxyConfig_: function() {\n    var active = document.getElementsByClassName('active')[0];\n    switch (active.id) {\n      case ProxyFormController.ProxyTypes.SYSTEM:\n        return {mode: 'system'};\n      case ProxyFormController.ProxyTypes.DIRECT:\n        return {mode: 'direct'};\n      case ProxyFormController.ProxyTypes.PAC:\n        var pacScriptURL = this.pacURL;\n        var pacManual = this.manualPac;\n        if (pacScriptURL)\n          return {mode: 'pac_script',\n                  pacScript: {url: pacScriptURL, mandatory: true}};\n        else if (pacManual)\n          return {mode: 'pac_script',\n                  pacScript: {data: pacManual, mandatory: true}};\n        else\n          return {mode: 'auto_detect'};\n      case ProxyFormController.ProxyTypes.FIXED:\n        var config = {mode: 'fixed_servers'};\n        if (this.singleProxy) {\n          config.rules = {\n            singleProxy: this.singleProxy,\n            bypassList: this.bypassList\n          };\n        } else {\n          config.rules = {\n            proxyForHttp: this.httpProxy,\n            proxyForHttps: this.httpsProxy,\n            proxyForFtp: this.ftpProxy,\n            fallbackProxy: this.fallbackProxy,\n            bypassList: this.bypassList\n          };\n        }\n        return config;\n    }\n  },\n\n\n  /**\n   * Sets the proper display classes based on the \"Use the same proxy server\n   * for all protocols\" checkbox. Expects to be called as an event handler\n   * when that field is clicked.\n   *\n   * @param {Event} e The `click` event to respond to.\n   * @private\n   */\n  toggleSingleProxyConfig_: function(e) {\n    var checkbox = e.target;\n    if (checkbox.nodeName === 'INPUT' &&\n        checkbox.getAttribute('type') === 'checkbox') {\n      if (checkbox.checked)\n        checkbox.parentNode.parentNode.classList.add('single');\n      else\n        checkbox.parentNode.parentNode.classList.remove('single');\n    }\n  },\n\n\n  /**\n   * Returns the form's current incognito status.\n   *\n   * @return {boolean} True if the form is in incognito mode, false otherwise.\n   * @private\n   */\n  isIncognitoMode_: function(e) {\n    return this.form_.parentNode.classList.contains('incognito');\n  },\n\n\n  /**\n   * Toggles the form's incognito mode. Saves the current state to an object\n   * property for later use, clears the form, and toggles the appropriate state.\n   *\n   * @param {Event} e The `click` event to respond to.\n   * @private\n   */\n  toggleIncognitoMode_: function(e) {\n    var div = this.form_.parentNode;\n    var button = document.getElementsByTagName('button')[0];\n\n    // Cancel the button click.\n    e.preventDefault();\n    e.stopPropagation();\n\n    // If we can't access Incognito settings, throw a message and return.\n    if (!this.isAllowedIncognitoAccess_) {\n      var msg = \"I'm sorry, Dave, I'm afraid I can't do that. Give me access \" +\n                \"to Incognito settings by checking the checkbox labeled \" +\n                \"'Allow in Incognito mode', which is visible at \" +\n                \"chrome://extensions.\";\n      this.generateAlert_(msg, false);\n      return;\n    }\n\n    if (this.isIncognitoMode_()) {\n      // In incognito mode, switching to cognito.\n      this.config_.incognito = this.generateProxyConfig_();\n      div.classList.remove('incognito');\n      this.recalcFormValues_(this.config_.regular);\n      button.innerText = 'Configure incognito window settings.';\n    } else {\n      // In cognito mode, switching to incognito.\n      this.config_.regular = this.generateProxyConfig_();\n      div.classList.add('incognito');\n      this.recalcFormValues_(this.config_.incognito);\n      button.innerText = 'Configure regular window settings.';\n    }\n  },\n\n\n  /**\n   * Sets the form's values based on a ProxyConfig.\n   *\n   * @param {!ProxyConfig} c The ProxyConfig object.\n   * @private\n   */\n  recalcFormValues_: function(c) {\n    // Normalize `auto_detect`\n    if (c.mode === 'auto_detect')\n      c.mode = 'pac_script';\n    // Activate one of the groups, based on `mode`.\n    this.changeActive_(document.getElementById(c.mode));\n    // Populate the PAC script\n    if (c.pacScript) {\n      if (c.pacScript.url)\n        this.pacURL = c.pacScript.url;\n    } else {\n      this.pacURL = '';\n    }\n    // Evaluate the `rules`\n    if (c.rules) {\n      var rules = c.rules;\n      if (rules.singleProxy) {\n        this.singleProxy = rules.singleProxy;\n      } else {\n        this.singleProxy = null;\n        this.httpProxy = rules.proxyForHttp;\n        this.httpsProxy = rules.proxyForHttps;\n        this.ftpProxy = rules.proxyForFtp;\n        this.fallbackProxy = rules.fallbackProxy;\n      }\n      this.bypassList = rules.bypassList;\n    } else {\n      this.singleProxy = null;\n      this.httpProxy = null;\n      this.httpsProxy = null;\n      this.ftpProxy = null;\n      this.fallbackProxy = null;\n      this.bypassList = '';\n    }\n  },\n\n\n  /**\n   * Handles the case in which this extension doesn't have the ability to\n   * control the Proxy settings, either because of an overriding policy\n   * or an extension with higher priority.\n   *\n   * @param {ProxyFormController.LevelOfControl} l The level of control this\n   *     extension has over the proxy settings.\n   * @private\n   */\n  handleLackOfControl_: function(l) {\n    var msg;\n    if (l === ProxyFormController.LevelOfControl.NO_ACCESS)\n      msg = chrome.i18n.getMessage('errorNoExtensionAccess');\n    else if (l === ProxyFormController.LevelOfControl.OTHER_EXTENSION)\n      msg = chrome.i18n.getMessage('errorOtherExtensionControls');\n    this.generateAlert_(msg);\n  },\n\n\n  /**\n   * Handle the case in which errors have been generated outside the context\n   * of this popup.\n   *\n   * @private\n   */\n  handleProxyErrors_: function() {\n    chrome.extension.sendRequest(\n        {type: 'getError'},\n        this.handleProxyErrorHandlerResponse_.bind(this));\n  },\n\n  /**\n   * Handles response from ProxyErrorHandler\n   *\n   * @param {{result: !string}} response The message sent in response to this\n   *     popup's request.\n   */\n  handleProxyErrorHandlerResponse_: function(response) {\n    if (response.result !== null) {\n      var error = JSON.parse(response.result);\n      console.error(error);\n      // TODO(mkwst): Do something more interesting\n      this.generateAlert_(\n          chrome.i18n.getMessage(\n              error.details ? 'errorProxyDetailedError' : 'errorProxyError',\n              [error.error, error.details]),\n          false);\n    }\n  }\n};\n"
  },
  {
    "path": "_archive/mv2/extensions/proxy_configuration/test/jsunittest.js",
    "content": "/*  Jsunittest, version 0.6.0\n *  (c) 2008 Dr Nic Williams\n *\n *  Jsunittest is freely distributable under\n *  the terms of an MIT-style license.\n *  For details, see the web site: http://jsunittest.rubyforge.org\n *\n *--------------------------------------------------------------------------*/\n\nvar JsUnitTest = {\n  Version: '0.6.0',\n};\n\nvar DrNicTest = {\n  Unit: {},\n  inspect: function(object) {\n    try {\n      if (typeof object == \"undefined\") return 'undefined';\n      if (object === null) return 'null';\n      if (typeof object == \"string\") {\n        var useDoubleQuotes = arguments[1];\n        var escapedString = this.gsub(object, /[\\x00-\\x1f\\\\]/, function(match) {\n          var character = String.specialChar[match[0]];\n          return character ? character : '\\\\u00' + match[0].charCodeAt().toPaddedString(2, 16);\n        });\n        if (useDoubleQuotes) return '\"' + escapedString.replace(/\"/g, '\\\\\"') + '\"';\n        return \"'\" + escapedString.replace(/'/g, '\\\\\\'') + \"'\";\n      };\n      return String(object);\n    } catch (e) {\n      if (e instanceof RangeError) return '...';\n      throw e;\n    }\n  },\n  $: function(element) {\n    if (arguments.length > 1) {\n      for (var i = 0, elements = [], length = arguments.length; i < length; i++)\n        elements.push(this.$(arguments[i]));\n      return elements;\n    }\n    if (typeof element == \"string\")\n      element = document.getElementById(element);\n    return element;\n  },\n  gsub: function(source, pattern, replacement) {\n    var result = '', match;\n    replacement = arguments.callee.prepareReplacement(replacement);\n\n    while (source.length > 0) {\n      if (match = source.match(pattern)) {\n        result += source.slice(0, match.index);\n        result += DrNicTest.String.interpret(replacement(match));\n        source  = source.slice(match.index + match[0].length);\n      } else {\n        result += source, source = '';\n      }\n    }\n    return result;\n  },\n  scan: function(source, pattern, iterator) {\n    this.gsub(source, pattern, iterator);\n    return String(source);\n  },\n  escapeHTML: function(data) {\n    return data.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n  },\n  arrayfromargs: function(args) {\n    var myarray = new Array();\n    var i;\n\n    for (i=0;i<args.length;i++)\n      myarray[i] = args[i];\n\n    return myarray;\n  },\n  hashToSortedArray: function(hash) {\n    var results = [];\n    for (key in hash) {\n      results.push([key, hash[key]]);\n    }\n    return results.sort();\n  },\n  flattenArray: function(array) {\n    var results = arguments[1] || [];\n    for (var i=0; i < array.length; i++) {\n      var object = array[i];\n      if (object != null && typeof object == \"object\" &&\n        'splice' in object && 'join' in object) {\n          this.flattenArray(object, results);\n      } else {\n        results.push(object);\n      }\n    };\n    return results;\n  },\n  selectorMatch: function(expression, element) {\n    var tokens = [];\n    var patterns = {\n      // combinators must be listed first\n      // (and descendant needs to be last combinator)\n      laterSibling: /^\\s*~\\s*/,\n      child:        /^\\s*>\\s*/,\n      adjacent:     /^\\s*\\+\\s*/,\n      descendant:   /^\\s/,\n\n      // selectors follow\n      tagName:      /^\\s*(\\*|[\\w\\-]+)(\\b|$)?/,\n      id:           /^#([\\w\\-\\*]+)(\\b|$)/,\n      className:    /^\\.([\\w\\-\\*]+)(\\b|$)/,\n      pseudo:\n  /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\\((.*?)\\))?(\\b|$|(?=\\s|[:+~>]))/,\n      attrPresence: /^\\[((?:[\\w]+:)?[\\w]+)\\]/,\n      attr:         /\\[((?:[\\w-]*:)?[\\w-]+)\\s*(?:([!^$*~|]?=)\\s*((['\"])([^\\4]*?)\\4|([^'\"][^\\]]*?)))?\\]/\n    };\n\n    var assertions = {\n      tagName: function(element, matches) {\n        return matches[1].toUpperCase() == element.tagName.toUpperCase();\n      },\n\n      className: function(element, matches) {\n        return Element.hasClassName(element, matches[1]);\n      },\n\n      id: function(element, matches) {\n        return element.id === matches[1];\n      },\n\n      attrPresence: function(element, matches) {\n        return Element.hasAttribute(element, matches[1]);\n      },\n\n      attr: function(element, matches) {\n        var nodeValue = Element.readAttribute(element, matches[1]);\n        return nodeValue && operators[matches[2]](nodeValue, matches[5] || matches[6]);\n      }\n    };\n    var e = this.expression, ps = patterns, as = assertions;\n    var le, p, m;\n\n    while (e && le !== e && (/\\S/).test(e)) {\n      le = e;\n      for (var i in ps) {\n        p = ps[i];\n        if (m = e.match(p)) {\n          // use the Selector.assertions methods unless the selector\n          // is too complex.\n          if (as[i]) {\n            tokens.push([i, Object.clone(m)]);\n            e = e.replace(m[0], '');\n          }\n        }\n      }\n    }\n\n    var match = true, name, matches;\n    for (var i = 0, token; token = tokens[i]; i++) {\n      name = token[0], matches = token[1];\n      if (!assertions[name](element, matches)) {\n        match = false; break;\n      }\n    }\n\n    return match;\n  },\n  toQueryParams: function(query, separator) {\n    var query = query || window.location.search;\n    var match = query.replace(/^\\s+/, '').replace(/\\s+$/, '').match(/([^?#]*)(#.*)?$/);\n    if (!match) return { };\n\n    var hash = {};\n    var parts = match[1].split(separator || '&');\n    for (var i=0; i < parts.length; i++) {\n      var pair = parts[i].split('=');\n      if (pair[0]) {\n        var key = decodeURIComponent(pair.shift());\n        var value = pair.length > 1 ? pair.join('=') : pair[0];\n        if (value != undefined) value = decodeURIComponent(value);\n\n        if (key in hash) {\n          var object = hash[key];\n          var isArray = object != null && typeof object == \"object\" &&\n            'splice' in object && 'join' in object\n          if (!isArray) hash[key] = [hash[key]];\n          hash[key].push(value);\n        }\n        else hash[key] = value;\n      }\n    };\n    return hash;\n  },\n\n  String: {\n    interpret: function(value) {\n      return value == null ? '' : String(value);\n    }\n  }\n};\n\nDrNicTest.gsub.prepareReplacement = function(replacement) {\n  if (typeof replacement == \"function\") return replacement;\n  var template = new Template(replacement);\n  return function(match) { return template.evaluate(match) };\n};\n\nDrNicTest.Template = function(template, pattern) {\n  this.template = template; //template.toString();\n  this.pattern = pattern || DrNicTest.Template.Pattern;\n};\n\nDrNicTest.Template.prototype.evaluate = function(object) {\n  if (typeof object.toTemplateReplacements == \"function\")\n    object = object.toTemplateReplacements();\n\n  return DrNicTest.gsub(this.template, this.pattern, function(match) {\n    if (object == null) return '';\n\n    var before = match[1] || '';\n    if (before == '\\\\') return match[2];\n\n    var ctx = object, expr = match[3];\n    var pattern = /^([^.[]+|\\[((?:.*?[^\\\\])?)\\])(\\.|\\[|$)/;\n    match = pattern.exec(expr);\n    if (match == null) return before;\n\n    while (match != null) {\n      var comp = (match[1].indexOf('[]') === 0) ? match[2].gsub('\\\\\\\\]', ']') : match[1];\n      ctx = ctx[comp];\n      if (null == ctx || '' == match[3]) break;\n      expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);\n      match = pattern.exec(expr);\n    }\n\n    return before + DrNicTest.String.interpret(ctx);\n  });\n}\n\nDrNicTest.Template.Pattern = /(^|.|\\r|\\n)(#\\{(.*?)\\})/;\nDrNicTest.Event = {};\n// written by Dean Edwards, 2005\n// with input from Tino Zijdel, Matthias Miller, Diego Perini\n// namespaced by Dr Nic Williams 2008\n\n// http://dean.edwards.name/weblog/2005/10/add-event/\n// http://dean.edwards.name/weblog/2005/10/add-event2/\nDrNicTest.Event.addEvent = function(element, type, handler) {\n  if (element.addEventListener) {\n    element.addEventListener(type, handler, false);\n  } else {\n    // assign each event handler a unique ID\n    if (!handler.$$guid) handler.$$guid = addEvent.guid++;\n    // create a hash table of event types for the element\n    if (!element.events) element.events = {};\n    // create a hash table of event handlers for each element/event pair\n    var handlers = element.events[type];\n    if (!handlers) {\n      handlers = element.events[type] = {};\n      // store the existing event handler (if there is one)\n      if (element[\"on\" + type]) {\n        handlers[0] = element[\"on\" + type];\n      }\n    }\n    // store the event handler in the hash table\n    handlers[handler.$$guid] = handler;\n    // assign a global event handler to do all the work\n    element[\"on\" + type] = handleEvent;\n  }\n};\n// a counter used to create unique IDs\nDrNicTest.Event.addEvent.guid = 1;\n\nDrNicTest.Event.removeEvent = function(element, type, handler) {\n  if (element.removeEventListener) {\n    element.removeEventListener(type, handler, false);\n  } else {\n    // delete the event handler from the hash table\n    if (element.events && element.events[type]) {\n      delete element.events[type][handler.$$guid];\n    }\n  }\n};\n\nDrNicTest.Event.handleEvent = function(event) {\n  var returnValue = true;\n  // grab the event object (IE uses a global event object)\n  event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);\n  // get a reference to the hash table of event handlers\n  var handlers = this.events[event.type];\n  // execute each event handler\n  for (var i in handlers) {\n    this.$$handleEvent = handlers[i];\n    if (this.$$handleEvent(event) === false) {\n      returnValue = false;\n    }\n  }\n  return returnValue;\n};\n\nDrNicTest.Event.fixEvent = function(event) {\n  // add W3C standard event methods\n  event.preventDefault = fixEvent.preventDefault;\n  event.stopPropagation = fixEvent.stopPropagation;\n  return event;\n};\nDrNicTest.Event.fixEvent.preventDefault = function() {\n  this.returnValue = false;\n};\nDrNicTest.Event.fixEvent.stopPropagation = function() {\n  this.cancelBubble = true;\n};\n\nDrNicTest.Unit.Logger = function(element) {\n  this.element = DrNicTest.$(element);\n  if (this.element) this._createLogTable();\n};\n\nDrNicTest.Unit.Logger.prototype.start = function(testName) {\n  if (!this.element) return;\n  var tbody = this.element.getElementsByTagName('tbody')[0];\n  tbody.innerHTML = tbody.innerHTML + '<tr><td>' + testName + '</td><td></td><td></td></tr>';\n};\n\nDrNicTest.Unit.Logger.prototype.setStatus = function(status) {\n  var logline = this.getLastLogLine();\n  logline.className = status;\n  var statusCell = logline.getElementsByTagName('td')[1];\n  statusCell.innerHTML = status;\n};\n\nDrNicTest.Unit.Logger.prototype.finish = function(status, summary) {\n  if (!this.element) return;\n  this.setStatus(status);\n  this.message(summary);\n};\n\nDrNicTest.Unit.Logger.prototype.message = function(message) {\n  if (!this.element) return;\n  var cell = this.getMessageCell();\n  cell.innerHTML = this._toHTML(message);\n};\n\nDrNicTest.Unit.Logger.prototype.summary = function(summary) {\n  if (!this.element) return;\n  var div = this.element.getElementsByTagName('div')[0];\n  div.innerHTML = this._toHTML(summary);\n};\n\nDrNicTest.Unit.Logger.prototype.getLastLogLine = function() {\n  var tbody = this.element.getElementsByTagName('tbody')[0];\n  var loglines = tbody.getElementsByTagName('tr');\n  return loglines[loglines.length - 1];\n};\n\nDrNicTest.Unit.Logger.prototype.getMessageCell = function() {\n  var logline = this.getLastLogLine();\n  return logline.getElementsByTagName('td')[2];\n};\n\nDrNicTest.Unit.Logger.prototype._createLogTable = function() {\n  var html = '<div class=\"logsummary\">running...</div>' +\n  '<table class=\"logtable\">' +\n  '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +\n  '<tbody class=\"loglines\"></tbody>' +\n  '</table>';\n  this.element.innerHTML = html;\n};\n\nDrNicTest.Unit.Logger.prototype.appendActionButtons = function(actions) {\n  // actions = $H(actions);\n  // if (!actions.any()) return;\n  // var div = new Element(\"div\", {className: 'action_buttons'});\n  // actions.inject(div, function(container, action) {\n  //   var button = new Element(\"input\").setValue(action.key).observe(\"click\", action.value);\n  //   button.type = \"button\";\n  //   return container.insert(button);\n  // });\n  // this.getMessageCell().insert(div);\n};\n\nDrNicTest.Unit.Logger.prototype._toHTML = function(txt) {\n  return DrNicTest.escapeHTML(txt).replace(/\\n/g,\"<br/>\");\n};\nDrNicTest.Unit.MessageTemplate = function(string) {\n  var parts = [];\n  var str = DrNicTest.scan((string || ''), /(?=[^\\\\])\\?|(?:\\\\\\?|[^\\?])+/, function(part) {\n    parts.push(part[0]);\n  });\n  this.parts = parts;\n};\n\nDrNicTest.Unit.MessageTemplate.prototype.evaluate = function(params) {\n  var results = [];\n  for (var i=0; i < this.parts.length; i++) {\n    var part = this.parts[i];\n    var result = (part == '?') ? DrNicTest.inspect(params.shift()) : part.replace(/\\\\\\?/, '?');\n    results.push(result);\n  };\n  return results.join('');\n};\n// A generic function for performming AJAX requests\n// It takes one argument, which is an object that contains a set of options\n// All of which are outline in the comments, below\n// From John Resig's book Pro JavaScript Techniques\n// published by Apress, 2006-8\nDrNicTest.ajax = function( options ) {\n\n    // Load the options object with defaults, if no\n    // values were provided by the user\n    options = {\n        // The type of HTTP Request\n        type: options.type || \"POST\",\n\n        // The URL the request will be made to\n        url: options.url || \"\",\n\n        // How long to wait before considering the request to be a timeout\n        timeout: options.timeout || 5000,\n\n        // Functions to call when the request fails, succeeds,\n        // or completes (either fail or succeed)\n        onComplete: options.onComplete || function(){},\n        onError: options.onError || function(){},\n        onSuccess: options.onSuccess || function(){},\n\n        // The data type that'll be returned from the server\n        // the default is simply to determine what data was returned from the\n        // and act accordingly.\n        data: options.data || \"\"\n    };\n\n    // Create the request object\n    var xml = new XMLHttpRequest();\n\n    // Open the asynchronous POST request\n    xml.open(options.type, options.url, true);\n\n    // We're going to wait for a request for 5 seconds, before giving up\n    var timeoutLength = 5000;\n\n    // Keep track of when the request has been succesfully completed\n    var requestDone = false;\n\n    // Initalize a callback which will fire 5 seconds from now, cancelling\n    // the request (if it has not already occurred).\n    setTimeout(function(){\n         requestDone = true;\n    }, timeoutLength);\n\n    // Watch for when the state of the document gets updated\n    xml.onreadystatechange = function(){\n        // Wait until the data is fully loaded,\n        // and make sure that the request hasn't already timed out\n        if ( xml.readyState == 4 && !requestDone ) {\n\n            // Check to see if the request was successful\n            if ( httpSuccess( xml ) ) {\n\n                // Execute the success callback with the data returned from the server\n                options.onSuccess( httpData( xml, options.type ) );\n\n            // Otherwise, an error occurred, so execute the error callback\n            } else {\n                options.onError();\n            }\n\n            // Call the completion callback\n            options.onComplete();\n\n            // Clean up after ourselves, to avoid memory leaks\n            xml = null;\n        }\n    };\n\n    // Establish the connection to the server\n    xml.send();\n\n    // Determine the success of the HTTP response\n    function httpSuccess(r) {\n        try {\n            // If no server status is provided, and we're actually\n            // requesting a local file, then it was successful\n            return !r.status && location.protocol == \"file:\" ||\n\n                // Any status in the 200 range is good\n                ( r.status >= 200 && r.status < 300 ) ||\n\n                // Successful if the document has not been modified\n                r.status == 304 ||\n\n                // Safari returns an empty status if the file has not been modified\n                navigator.userAgent.indexOf(\"Safari\") >= 0 && typeof r.status == \"undefined\";\n        } catch(e){}\n\n        // If checking the status failed, then assume that the request failed too\n        return false;\n    }\n\n    // Extract the correct data from the HTTP response\n    function httpData(r,type) {\n        // Get the content-type header\n        var ct = r.getResponseHeader(\"content-type\");\n\n        // If no default type was provided, determine if some\n        // form of XML was returned from the server\n        var data = !type && ct && ct.indexOf(\"xml\") >= 0;\n\n        // Get the XML Document object if XML was returned from\n        // the server, otherwise return the text contents returned by the server\n        data = type == \"xml\" || data ? r.responseXML : r.responseText;\n\n        // If the specified type is \"script\", execute the returned text\n        // response as if it was JavaScript\n        if ( type == \"script\" )\n            eval.call( window, data );\n\n        // Return the response data (either an XML Document or a text string)\n        return data;\n    }\n\n}\nDrNicTest.Unit.Assertions = {\n  buildMessage: function(message, template) {\n    var args = DrNicTest.arrayfromargs(arguments).slice(2);\n    return (message ? message + '\\n' : '') +\n      new DrNicTest.Unit.MessageTemplate(template).evaluate(args);\n  },\n\n  flunk: function(message) {\n    this.assertBlock(message || 'Flunked', function() { return false });\n  },\n\n  assertBlock: function(message, block) {\n    try {\n      block.call(this) ? this.pass() : this.fail(message);\n    } catch(e) { this.error(e) }\n  },\n\n  assert: function(expression, message) {\n    message = this.buildMessage(message || 'assert', 'got <?>', expression);\n    this.assertBlock(message, function() { return expression });\n  },\n\n  assertEqual: function(expected, actual, message) {\n    message = this.buildMessage(message || 'assertEqual', 'expected <?>, actual: <?>', expected, actual);\n    this.assertBlock(message, function() { return expected == actual });\n  },\n\n  assertNotEqual: function(expected, actual, message) {\n    message = this.buildMessage(message || 'assertNotEqual', 'expected <?>, actual: <?>', expected, actual);\n    this.assertBlock(message, function() { return expected != actual });\n  },\n\n  assertEnumEqual: function(expected, actual, message) {\n    message = this.buildMessage(message || 'assertEnumEqual', 'expected <?>, actual: <?>', expected, actual);\n    var expected_array = DrNicTest.flattenArray(expected);\n    var actual_array   = DrNicTest.flattenArray(actual);\n    this.assertBlock(message, function() {\n      if (expected_array.length == actual_array.length) {\n        for (var i=0; i < expected_array.length; i++) {\n          if (expected_array[i] != actual_array[i]) return false;\n        };\n        return true;\n      }\n      return false;\n    });\n  },\n\n  assertEnumNotEqual: function(expected, actual, message) {\n    message = this.buildMessage(message || 'assertEnumNotEqual', '<?> was the same as <?>', expected, actual);\n    var expected_array = DrNicTest.flattenArray(expected);\n    var actual_array   = DrNicTest.flattenArray(actual);\n    this.assertBlock(message, function() {\n      if (expected_array.length == actual_array.length) {\n        for (var i=0; i < expected_array.length; i++) {\n          if (expected_array[i] != actual_array[i]) return true;\n        };\n        return false;\n      }\n      return true;\n    });\n  },\n\n  assertHashEqual: function(expected, actual, message) {\n    message = this.buildMessage(message || 'assertHashEqual', 'expected <?>, actual: <?>', expected, actual);\n    var expected_array = DrNicTest.flattenArray(DrNicTest.hashToSortedArray(expected));\n    var actual_array   = DrNicTest.flattenArray(DrNicTest.hashToSortedArray(actual));\n    var block = function() {\n      if (expected_array.length == actual_array.length) {\n        for (var i=0; i < expected_array.length; i++) {\n          if (expected_array[i] != actual_array[i]) return false;\n        };\n        return true;\n      }\n      return false;\n    };\n    this.assertBlock(message, block);\n  },\n\n  assertHashNotEqual: function(expected, actual, message) {\n    message = this.buildMessage(message || 'assertHashNotEqual', '<?> was the same as <?>', expected, actual);\n    var expected_array = DrNicTest.flattenArray(DrNicTest.hashToSortedArray(expected));\n    var actual_array   = DrNicTest.flattenArray(DrNicTest.hashToSortedArray(actual));\n    // from now we recursively zip & compare nested arrays\n    var block = function() {\n      if (expected_array.length == actual_array.length) {\n        for (var i=0; i < expected_array.length; i++) {\n          if (expected_array[i] != actual_array[i]) return true;\n        };\n        return false;\n      }\n      return true;\n    };\n    this.assertBlock(message, block);\n  },\n\n  assertIdentical: function(expected, actual, message) {\n    message = this.buildMessage(message || 'assertIdentical', 'expected <?>, actual: <?>', expected, actual);\n    this.assertBlock(message, function() { return expected === actual });\n  },\n\n  assertNotIdentical: function(expected, actual, message) {\n    message = this.buildMessage(message || 'assertNotIdentical', 'expected <?>, actual: <?>', expected, actual);\n    this.assertBlock(message, function() { return expected !== actual });\n  },\n\n  assertNull: function(obj, message) {\n    message = this.buildMessage(message || 'assertNull', 'got <?>', obj);\n    this.assertBlock(message, function() { return obj === null });\n  },\n\n  assertNotNull: function(obj, message) {\n    message = this.buildMessage(message || 'assertNotNull', 'got <?>', obj);\n    this.assertBlock(message, function() { return obj !== null });\n  },\n\n  assertUndefined: function(obj, message) {\n    message = this.buildMessage(message || 'assertUndefined', 'got <?>', obj);\n    this.assertBlock(message, function() { return typeof obj == \"undefined\" });\n  },\n\n  assertNotUndefined: function(obj, message) {\n    message = this.buildMessage(message || 'assertNotUndefined', 'got <?>', obj);\n    this.assertBlock(message, function() { return typeof obj != \"undefined\" });\n  },\n\n  assertNullOrUndefined: function(obj, message) {\n    message = this.buildMessage(message || 'assertNullOrUndefined', 'got <?>', obj);\n    this.assertBlock(message, function() { return obj == null });\n  },\n\n  assertNotNullOrUndefined: function(obj, message) {\n    message = this.buildMessage(message || 'assertNotNullOrUndefined', 'got <?>', obj);\n    this.assertBlock(message, function() { return obj != null });\n  },\n\n  assertMatch: function(expected, actual, message) {\n    message = this.buildMessage(message || 'assertMatch', 'regex <?> did not match <?>', expected, actual);\n    this.assertBlock(message, function() { return new RegExp(expected).exec(actual) });\n  },\n\n  assertNoMatch: function(expected, actual, message) {\n    message = this.buildMessage(message || 'assertNoMatch', 'regex <?> matched <?>', expected, actual);\n    this.assertBlock(message, function() { return !(new RegExp(expected).exec(actual)) });\n  },\n\n  assertHidden: function(element, message) {\n    message = this.buildMessage(message || 'assertHidden', '? isn\\'t hidden.', element);\n    this.assertBlock(message, function() { return element.style.display == 'none' });\n  },\n\n  assertInstanceOf: function(expected, actual, message) {\n    message = this.buildMessage(message || 'assertInstanceOf', '<?> was not an instance of the expected type', actual);\n    this.assertBlock(message, function() { return actual instanceof expected });\n  },\n\n  assertNotInstanceOf: function(expected, actual, message) {\n    message = this.buildMessage(message || 'assertNotInstanceOf', '<?> was an instance of the expected type', actual);\n    this.assertBlock(message, function() { return !(actual instanceof expected) });\n  },\n\n  assertRespondsTo: function(method, obj, message) {\n    message = this.buildMessage(message || 'assertRespondsTo', 'object doesn\\'t respond to <?>', method);\n    this.assertBlock(message, function() { return (method in obj && typeof obj[method] == 'function') });\n  },\n\n  assertRaise: function(exceptionName, method, message) {\n    message = this.buildMessage(message || 'assertRaise', '<?> exception expected but none was raised', exceptionName);\n    var block = function() {\n      try {\n        method();\n        return false;\n      } catch(e) {\n        if (e.name == exceptionName) return true;\n        else throw e;\n      }\n    };\n    this.assertBlock(message, block);\n  },\n\n  assertNothingRaised: function(method, message) {\n    try {\n      method();\n      this.assert(true, \"Expected nothing to be thrown\");\n    } catch(e) {\n      message = this.buildMessage(message || 'assertNothingRaised', '<?> was thrown when nothing was expected.', e);\n      this.flunk(message);\n    }\n  },\n\n  _isVisible: function(element) {\n    element = DrNicTest.$(element);\n    if(!element.parentNode) return true;\n    this.assertNotNull(element);\n    if(element.style && element.style.display == 'none')\n      return false;\n\n    return arguments.callee.call(this, element.parentNode);\n  },\n\n  assertVisible: function(element, message) {\n    message = this.buildMessage(message, '? was not visible.', element);\n    this.assertBlock(message, function() { return this._isVisible(element) });\n  },\n\n  assertNotVisible: function(element, message) {\n    message = this.buildMessage(message, '? was not hidden and didn\\'t have a hidden parent either.', element);\n    this.assertBlock(message, function() { return !this._isVisible(element) });\n  },\n\n  assertElementsMatch: function() {\n    var pass = true, expressions = DrNicTest.arrayfromargs(arguments);\n    var elements = expressions.shift();\n    if (elements.length != expressions.length) {\n      message = this.buildMessage('assertElementsMatch', 'size mismatch: ? elements, ? expressions (?).', elements.length, expressions.length, expressions);\n      this.flunk(message);\n      pass = false;\n    }\n    for (var i=0; i < expressions.length; i++) {\n      var expression = expressions[i];\n      var element    = DrNicTest.$(elements[i]);\n      if (DrNicTest.selectorMatch(expression, element)) {\n        pass = true;\n        break;\n      }\n      message = this.buildMessage('assertElementsMatch', 'In index <?>: expected <?> but got ?', index, expression, element);\n      this.flunk(message);\n      pass = false;\n    };\n    this.assert(pass, \"Expected all elements to match.\");\n  },\n\n  assertElementMatches: function(element, expression, message) {\n    this.assertElementsMatch([element], expression);\n  }\n};\nDrNicTest.Unit.Runner = function(testcases) {\n  var argumentOptions = arguments[1] || {};\n  var options = this.options = {};\n  options.testLog = ('testLog' in argumentOptions) ? argumentOptions.testLog : 'testlog';\n  options.resultsURL = this.queryParams.resultsURL;\n  options.testLog = DrNicTest.$(options.testLog);\n\n  this.tests = this.getTests(testcases);\n  this.currentTest = 0;\n  this.logger = new DrNicTest.Unit.Logger(options.testLog);\n\n  var self = this;\n  DrNicTest.Event.addEvent(window, \"load\", function() {\n    setTimeout(function() {\n      self.runTests();\n    }, 0.1);\n  });\n};\n\nDrNicTest.Unit.Runner.prototype.queryParams = DrNicTest.toQueryParams();\n\nDrNicTest.Unit.Runner.prototype.portNumber = function() {\n  if (window.location.search.length > 0) {\n    var matches = window.location.search.match(/\\:(\\d{3,5})\\//);\n    if (matches) {\n      return parseInt(matches[1]);\n    }\n  }\n  return null;\n};\n\nDrNicTest.Unit.Runner.prototype.getTests = function(testcases) {\n  var tests = [], options = this.options;\n  if (this.queryParams.tests) tests = this.queryParams.tests.split(',');\n  else if (options.tests) tests = options.tests;\n  else if (options.test) tests = [option.test];\n  else {\n    for (testname in testcases) {\n      if (testname.match(/^test/)) tests.push(testname);\n    }\n  }\n  var results = [];\n  for (var i=0; i < tests.length; i++) {\n    var test = tests[i];\n    if (testcases[test])\n      results.push(\n        new DrNicTest.Unit.Testcase(test, testcases[test], testcases.setup, testcases.teardown)\n      );\n  };\n  return results;\n};\n\nDrNicTest.Unit.Runner.prototype.getResult = function() {\n  var results = {\n    tests: this.tests.length,\n    assertions: 0,\n    failures: 0,\n    errors: 0\n  };\n\n  for (var i=0; i < this.tests.length; i++) {\n    var test = this.tests[i];\n    results.assertions += test.assertions;\n    results.failures   += test.failures;\n    results.errors     += test.errors;\n  };\n  return results;\n};\n\nDrNicTest.Unit.Runner.prototype.postResults = function() {\n  if (this.options.resultsURL) {\n    // new Ajax.Request(this.options.resultsURL,\n    //   { method: 'get', parameters: this.getResult(), asynchronous: false });\n    var results = this.getResult();\n    var url = this.options.resultsURL + \"?\";\n    url += \"assertions=\"+ results.assertions + \"&\";\n    url += \"failures=\"  + results.failures + \"&\";\n    url += \"errors=\"    + results.errors;\n    DrNicTest.ajax({\n      url: url,\n      type: 'GET'\n    })\n  }\n};\n\nDrNicTest.Unit.Runner.prototype.runTests = function() {\n  var test = this.tests[this.currentTest], actions;\n\n  if (!test) return this.finish();\n  if (!test.isWaiting) this.logger.start(test.name);\n  test.run();\n  var self = this;\n  if(test.isWaiting) {\n    this.logger.message(\"Waiting for \" + test.timeToWait + \"ms\");\n    // setTimeout(this.runTests.bind(this), test.timeToWait || 1000);\n    setTimeout(function() {\n      self.runTests();\n    }, test.timeToWait || 1000);\n    return;\n  }\n\n  this.logger.finish(test.status(), test.summary());\n  if (actions = test.actions) this.logger.appendActionButtons(actions);\n  this.currentTest++;\n  // tail recursive, hopefully the browser will skip the stackframe\n  this.runTests();\n};\n\nDrNicTest.Unit.Runner.prototype.finish = function() {\n  this.postResults();\n  this.logger.summary(this.summary());\n};\n\nDrNicTest.Unit.Runner.prototype.summary = function() {\n  return new DrNicTest.Template('#{tests} tests, #{assertions} assertions, #{failures} failures, #{errors} errors').evaluate(this.getResult());\n};\nDrNicTest.Unit.Testcase = function(name, test, setup, teardown) {\n  this.name           = name;\n  this.test           = test     || function() {};\n  this.setup          = setup    || function() {};\n  this.teardown       = teardown || function() {};\n  this.messages       = [];\n  this.actions        = {};\n};\n// import DrNicTest.Unit.Assertions\n\nfor (method in DrNicTest.Unit.Assertions) {\n  DrNicTest.Unit.Testcase.prototype[method] = DrNicTest.Unit.Assertions[method];\n}\n\nDrNicTest.Unit.Testcase.prototype.isWaiting  = false;\nDrNicTest.Unit.Testcase.prototype.timeToWait = 1000;\nDrNicTest.Unit.Testcase.prototype.assertions = 0;\nDrNicTest.Unit.Testcase.prototype.failures   = 0;\nDrNicTest.Unit.Testcase.prototype.errors     = 0;\n// DrNicTest.Unit.Testcase.prototype.isRunningFromRake = window.location.port == 4711;\nDrNicTest.Unit.Testcase.prototype.isRunningFromRake = window.location.port;\n\nDrNicTest.Unit.Testcase.prototype.wait = function(time, nextPart) {\n  this.isWaiting = true;\n  this.test = nextPart;\n  this.timeToWait = time;\n};\n\nDrNicTest.Unit.Testcase.prototype.run = function(rethrow) {\n  try {\n    try {\n      if (!this.isWaiting) this.setup();\n      this.isWaiting = false;\n      this.test();\n    } finally {\n      if(!this.isWaiting) {\n        this.teardown();\n      }\n    }\n  }\n  catch(e) {\n    if (rethrow) throw e;\n    this.error(e, this);\n  }\n};\n\nDrNicTest.Unit.Testcase.prototype.summary = function() {\n  var msg = '#{assertions} assertions, #{failures} failures, #{errors} errors\\n';\n  return new DrNicTest.Template(msg).evaluate(this) +\n    this.messages.join(\"\\n\");\n};\n\nDrNicTest.Unit.Testcase.prototype.pass = function() {\n  this.assertions++;\n};\n\nDrNicTest.Unit.Testcase.prototype.fail = function(message) {\n  this.failures++;\n  var line = \"\";\n  try {\n    throw new Error(\"stack\");\n  } catch(e){\n    line = (/\\.html:(\\d+)/.exec(e.stack || '') || ['',''])[1];\n  }\n  this.messages.push(\"Failure: \" + message + (line ? \" Line #\" + line : \"\"));\n};\n\nDrNicTest.Unit.Testcase.prototype.info = function(message) {\n  this.messages.push(\"Info: \" + message);\n};\n\nDrNicTest.Unit.Testcase.prototype.error = function(error, test) {\n  this.errors++;\n  this.actions['retry with throw'] = function() { test.run(true) };\n  this.messages.push(error.name + \": \"+ error.message + \"(\" + DrNicTest.inspect(error) + \")\");\n};\n\nDrNicTest.Unit.Testcase.prototype.status = function() {\n  if (this.failures > 0) return 'failed';\n  if (this.errors > 0) return 'error';\n  return 'passed';\n};\n\nDrNicTest.Unit.Testcase.prototype.benchmark = function(operation, iterations) {\n  var startAt = new Date();\n  (iterations || 1).times(operation);\n  var timeTaken = ((new Date())-startAt);\n  this.info((arguments[2] || 'Operation') + ' finished ' +\n     iterations + ' iterations in ' + (timeTaken/1000)+'s' );\n  return timeTaken;\n};\n\nTest = DrNicTest\n"
  },
  {
    "path": "_archive/mv2/extensions/proxy_configuration/test/proxy_form_controller_test.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <title>Popup for Proxy API Test</title>\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"./unittest.css\">\n  <script src=\"./jsunittest.js\"></script>\n  <script src=\"../proxy_form_controller.js\"></script>\n</head>\n<body>\n  <h1>Proxy Configuration Unit Tests</h1>\n\n  <h2>ProxyFormController</h2>\n  <div id=\"proxyformcontrollerlog\"></div>\n\n  <div id=\"fixture\">\n  <form id=\"proxyForm\">\n    <fieldset id=\"system\">\n      <legend>System Settings</legend>\n      <input type=\"radio\" name=\"proxyType\" id=\"proxyTypeSystem\" value=\"system\">\n      <label for=\"proxyTypeSystem\">Use the <em>system's proxy settings</em>.</label>\n    </fieldset>\n    <fieldset id=\"direct\">\n      <legend>Direct Connection</legend>\n      <input type=\"radio\" name=\"proxyType\" id=\"proxyTypeDirect\" value=\"direct\">\n      <label for=\"proxyTypeDirect\">Your computer is <em>directly connected</em> to the internet; no need for a proxy.</label>\n    </fieldset>\n    <fieldset id=\"pac_script\">\n      <legend>Automatic Configuration</legend>\n      <input type=\"radio\" name=\"proxyType\" id=\"proxyTypeAutoconfig\" value=\"autoconfig\">\n      <label for=\"proxyTypeAutoconfig\">Your proxy supports <em>automatic configuration</em>.</label>\n\n      <section>\n        <label for=\"autoconfigURL\">Autoconfiguration URL (PAC file)</label>\n        <input type=\"url\" name=\"autoconfigURL\" id=\"autoconfigURL\">\n        <input type=\"hidden\" name=\"autoconfigData\" id=\"autoconfigData\">\n      </section>\n    </fieldset>\n    <fieldset id=\"fixed_servers\">\n      <legend>Manual Proxy</legend>\n      <input type=\"radio\" name=\"proxyType\" id=\"proxyTypeManual\" value=\"manual\">\n      <label for=\"proxyTypeManual\">Configure your proxy settings <em>manually</em>.</label>\n      <section>\n        <fieldset>\n          <legend>HTTP</legend>\n          <label for=\"proxyHostHttp\">Host</label>\n          <select id=\"proxySchemeHttp\" name=\"proxySchemeHttp\">\n            <option selected value=\"http\">http://</option>\n            <option value=\"https\">https://</option>\n            <option value=\"socks4\">socks4://</option>\n            <option value=\"socks5\">socks5://</option>\n          </select>\n          <input type=\"text\" name=\"proxyHostHttp\" id=\"proxyHostHttp\">\n\n          <label for=\"proxyPortHttp\">Port</label>\n          <input type=\"number\" min=\"1\" step=\"1\" name=\"proxyPortHttp\" id=\"proxyPortHttp\">\n\n          <input type=\"checkbox\" name=\"singleProxyForEverything\" id=\"singleProxyForEverything\">\n          <label for=\"singleProxyForEverything\">Use the same proxy server for all protocols</label>\n        </fieldset>\n        <fieldset>\n          <legend>HTTPS</legend>\n          <label for=\"proxyHostHttps\">Host</label>\n          <select id=\"proxySchemeHttps\" name=\"proxySchemeHttps\">\n            <option selected value=\"http\">http://</option>\n            <option value=\"https\">https://</option>\n            <option value=\"socks4\">socks4://</option>\n            <option value=\"socks5\">socks5://</option>\n          </select>\n          <input type=\"text\" name=\"proxyHostHttps\" id=\"proxyHostHttps\">\n\n          <label for=\"proxyPortHttps\">Port</label>\n          <input type=\"number\" min=\"1\" step=\"1\" name=\"proxyPortHttps\" id=\"proxyPortHttps\">\n        </fieldset>\n        <fieldset>\n          <legend>FTP</legend>\n          <label for=\"proxyHostFtp\">Host</label>\n          <select id=\"proxySchemeFtp\" name=\"proxySchemeFtp\">\n            <option selected value=\"http\">http://</option>\n            <option value=\"https\">https://</option>\n            <option value=\"socks4\">socks4://</option>\n            <option value=\"socks5\">socks5://</option>\n          </select>\n          <input type=\"text\" name=\"proxyHostFtp\" id=\"proxyHostFtp\">\n\n          <label for=\"proxyPortFtp\">Port</label>\n          <input type=\"number\" min=\"1\" step=\"1\" name=\"proxyPortFtp\" id=\"proxyPortFtp\">\n        </fieldset>\n        <fieldset>\n          <legend>Fallback</legend>\n          <label for=\"proxyHostFallback\">Host</label>\n          <select id=\"proxySchemeFallback\" name=\"proxySchemeFallback\">\n            <option selected value=\"http\">http://</option>\n            <option value=\"https\">https://</option>\n            <option value=\"socks4\">socks4://</option>\n            <option value=\"socks5\">socks5://</option>\n          </select>\n          <input type=\"text\" name=\"proxyHostFallback\" id=\"proxyHostFallback\">\n\n          <label for=\"proxyPortFallback\">Port</label>\n          <input type=\"number\" min=\"1\" step=\"1\" name=\"proxyPortFallback\" id=\"proxyPortFallback\">\n        </fieldset>\n        <fieldset>\n          <label for=\"bypassList\">Bypass proxy for these hosts:</label>\n          <textarea id=\"bypassList\" name=\"bypassList\" placeholder=\"localhost,192.168.1.1/16, .example.com\"></textarea>\n        </fieldset>\n      </section>\n    </fieldset>\n    <input type=\"submit\" value=\"Save proxy settings\">\n  </form>\n  </div>\n  <script src=\"./proxy_form_controller_test.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/proxy_configuration/test/proxy_form_controller_test.js",
    "content": "// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Stub out the `chrome.proxy`, `chrome.i18n`, and `chrome.extension` APIs\nchrome = chrome || {\n  proxy: {\n    settings: {\n      get: function() {},\n      clear: function() {},\n      set: function() {}\n    }\n  },\n  i18n: {\n    getMessage: function(x) { return x; }\n  },\n  extension: {\n    sendRequest: function() {},\n    isAllowedIncognitoAccess: function(funk) {\n      funk(true);\n    }\n  }\n};\n\nvar fixture = document.getElementById('fixture');\nvar baselineHTML = fixture.innerHTML;\nvar groupIDs = [ProxyFormController.ProxyTypes.DIRECT,\n                ProxyFormController.ProxyTypes.SYSTEM,\n                ProxyFormController.ProxyTypes.PAC,\n                ProxyFormController.ProxyTypes.FIXED];\n\nvar mockFunctionFactory = function(returnValue, logging) {\n  var called = [];\n  returnValue = returnValue || null;\n\n  var funky = function() {\n    called.push(arguments);\n    if (arguments[1] && typeof(arguments[1]) === 'function') {\n      var funk = arguments[1];\n      funk(returnValue);\n    }\n    return returnValue;\n  };\n  funky.getCallList = function() { return called; };\n  funky.getValue = function() { return returnValue; };\n  return funky;\n};\n\nvar proxyform = new Test.Unit.Runner({\n  setup: function() {\n    fixture.innerHTML = baselineHTML;\n    this.controller_ = new ProxyFormController('proxyForm');\n    this.clickEvent_ = document.createEvent('MouseEvents');\n    this.clickEvent_.initMouseEvent('click', true, true, window,\n        0, 0, 0, 0, 0, false, false, false, false, 0, null);\n    // Reset mock functions.\n    chrome.proxy = {\n      settings: {\n        get: mockFunctionFactory({\n               value: {mode: 'system' },\n               levelOfControl: 'controllable_by_this_extension' }),\n        clear: mockFunctionFactory({\n                 value: {mode: 'system' },\n                 levelOfControl: 'controllable_by_this_extension' }),\n        set: mockFunctionFactory({\n               value: {mode: 'system' },\n               levelOfControl: 'controllable_by_this_extension' })\n      }\n    };\n  },\n\n  teardown: function() {\n    fixture.removeChild(fixture.childNodes[0]);\n    delete(this.controller_);\n  },\n\n  // Clicking on various bits of the interface should set correct classes,\n  // and select correct radio buttons.\n  testActivationClicks: function() {\n    var self = this;\n    var i;\n    groupIDs.forEach(function(id) {\n      var group = document.getElementById(id);\n      var all = group.querySelectorAll('*');\n      for (i = 0; i < all.length; i++) {\n        group.classList.remove('active');\n        all[i].dispatchEvent(self.clickEvent_);\n        self.assert(group.classList.contains('active'));\n      }\n    });\n  },\n\n  // Elements inside an active group should not be disabled, and vice versa\n  testDisabledElements: function() {\n    var self = this;\n    var i, j;\n    groupIDs.forEach(function(id) {\n      var group = document.getElementById(id);\n      var all = group.querySelectorAll('*');\n      // First, check that activating a group enables its form elements\n      for (i = 0; i < all.length; i++) {\n        group.classList.remove('active');\n        var inputs = group.querySelectorAll('input:not([type=\"radio\"]),select');\n        for (j = 0; j < inputs.length; j++) {\n          inputs[j].setAttribute('disabled', 'disabled');\n        }\n        all[i].dispatchEvent(self.clickEvent_);\n        for (j = 0; j < inputs.length; j++) {\n          self.assert(!inputs[j].hasAttribute('disabled'));\n        }\n      }\n    });\n  },\n\n  // Clicking the \"Use single proxy\" checkbox should set the correct\n  // classes on the form.\n  testSingleProxyToggle: function() {\n    var group = document.getElementById(\n        ProxyFormController.ProxyTypes.FIXED);\n    var checkbox = document.getElementById('singleProxyForEverything');\n    var section = checkbox.parentNode.parentNode;\n    // Checkbox only works in active group, `testActivationClicks` tests\n    // the inactive click behavior.\n    group.classList.add('active');\n\n    checkbox.checked = false;\n    checkbox.dispatchEvent(this.clickEvent_);\n    this.assert(section.classList.contains('single'));\n    checkbox.dispatchEvent(this.clickEvent_);\n    this.assert(!section.classList.contains('single'));\n  },\n\n  // On instantiation, ProxyFormController should read the current state\n  // from `chrome.proxy.settings.get`, and react accordingly.\n  // Let's see if that happens with the next four sets of assertions.\n  testSetupFormSystem: function() {\n    chrome.proxy.settings.get = mockFunctionFactory({\n      value: {mode: 'system'},\n      levelOfControl: 'controllable_by_this_extension'\n    });\n\n    fixture.innerHTML = baselineHTML;\n    this.controller_ = new ProxyFormController('proxyForm');\n    // Wait for async calls to fire\n    this.wait(100, function() {\n      this.assertEqual(\n          6,\n          chrome.proxy.settings.get.getCallList().length);\n      this.assert(\n          document.getElementById(ProxyFormController.ProxyTypes.SYSTEM)\n              .classList.contains('active'));\n    });\n  },\n\n  testSetupFormDirect: function() {\n    chrome.proxy.settings.get =\n        mockFunctionFactory({value: {mode: 'direct'},\n             levelOfControl: 'controllable_by_this_extension'}, true);\n\n    fixture.innerHTML = baselineHTML;\n    this.controller_ = new ProxyFormController('proxyForm');\n    // Wait for async calls to fire\n    this.wait(100, function() {\n      this.assertEqual(\n          2,\n          chrome.proxy.settings.get.getCallList().length);\n      this.assert(\n          document.getElementById(ProxyFormController.ProxyTypes.DIRECT)\n              .classList.contains('active'));\n    });\n  },\n\n  testSetupFormPac: function() {\n    chrome.proxy.settings.get =\n        mockFunctionFactory({value: {mode: 'pac_script' },\n             levelOfControl: 'controllable_by_this_extension'});\n\n    fixture.innerHTML = baselineHTML;\n    this.controller_ = new ProxyFormController('proxyForm');\n    // Wait for async calls to fire\n    this.wait(100, function() {\n      this.assertEqual(\n          2,\n          chrome.proxy.settings.get.getCallList().length);\n      this.assert(\n          document.getElementById(ProxyFormController.ProxyTypes.PAC)\n              .classList.contains('active'));\n    });\n  },\n\n  testSetupFormFixed: function() {\n    chrome.proxy.settings.get =\n        mockFunctionFactory({value: {mode: 'fixed_servers' },\n             levelOfControl: 'controllable_by_this_extension'});\n\n    fixture.innerHTML = baselineHTML;\n    this.controller_ = new ProxyFormController('proxyForm');\n    // Wait for async calls to fire\n    this.wait(100, function() {\n      this.assertEqual(\n          2,\n          chrome.proxy.settings.get.getCallList().length);\n      this.assert(\n          document.getElementById(ProxyFormController.ProxyTypes.FIXED)\n              .classList.contains('active'));\n    });\n  },\n\n  // Test that `recalcFormValues_` correctly sets DOM field values when\n  // given a `ProxyConfig` structure\n  testRecalcFormValuesGroups: function() {\n    // Test `AUTO` normalization to `PAC`\n    this.controller_.recalcFormValues_({\n      mode: ProxyFormController.ProxyTypes.AUTO,\n      rules: {},\n      pacScript: ''\n    });\n    this.assert(\n        document.getElementById(ProxyFormController.ProxyTypes.PAC)\n            .classList.contains('active'));\n\n    // DIRECT\n    this.controller_.recalcFormValues_({\n      mode: ProxyFormController.ProxyTypes.DIRECT,\n      rules: {},\n      pacScript: ''\n    });\n    this.assert(\n        document.getElementById(ProxyFormController.ProxyTypes.DIRECT)\n            .classList.contains('active'));\n\n    // FIXED\n    this.controller_.recalcFormValues_({\n      mode: ProxyFormController.ProxyTypes.FIXED,\n      rules: {},\n      pacScript: ''\n    });\n    this.assert(\n        document.getElementById(ProxyFormController.ProxyTypes.FIXED)\n            .classList.contains('active'));\n\n    // PAC\n    this.controller_.recalcFormValues_({\n      mode: ProxyFormController.ProxyTypes.PAC,\n      rules: {},\n      pacScript: ''\n    });\n    this.assert(\n        document.getElementById(ProxyFormController.ProxyTypes.PAC)\n          .classList.contains('active'));\n\n    // SYSTEM\n    this.controller_.recalcFormValues_({\n      mode: ProxyFormController.ProxyTypes.SYSTEM,\n      rules: {},\n      pacScript: ''\n    });\n    this.assert(\n        document.getElementById(ProxyFormController.ProxyTypes.SYSTEM)\n          .classList.contains('active'));\n  },\n\n  testRecalcFormValuesFixedSingle: function() {\n    this.controller_.recalcFormValues_({\n      mode: ProxyFormController.ProxyTypes.FIXED,\n      rules: {\n         singleProxy: {\n           scheme: 'socks5',\n           host: 'singleproxy.example.com',\n           port: '1234'\n        }\n      }\n    });\n    var single = this.controller_.singleProxy;\n    this.assertEqual('socks5', single.scheme);\n    this.assertEqual('singleproxy.example.com', single.host);\n    this.assertEqual(1234, single.port);\n  },\n\n  testRecalcFormValuesPacScript: function() {\n    this.controller_.recalcFormValues_({\n      mode: ProxyFormController.ProxyTypes.PAC,\n      rules: {},\n      pacScript: {url: 'http://example.com/this/is/a/pac.script'}\n    });\n    this.assertEqual(\n        'http://example.com/this/is/a/pac.script',\n        document.getElementById('autoconfigURL').value);\n  },\n\n  testRecalcFormValuesSingle: function() {\n    this.controller_.recalcFormValues_({\n       mode: ProxyFormController.ProxyTypes.FIXED,\n       rules: {\n         singleProxy: {\n           scheme: 'https',\n           host: 'example.com',\n           port: 80\n        }\n      }\n    });\n    // Single!\n    this.assert(\n      document.querySelector('#' + ProxyFormController.ProxyTypes.FIXED +\n          ' > section').classList.contains('single'));\n\n    var single = this.controller_.singleProxy;\n    this.assertEqual('https', single.scheme);\n    this.assertEqual('example.com', single.host);\n    this.assertEqual(80, single.port);\n  },\n\n  testRecalcFormValuesMultiple: function() {\n    this.controller_.recalcFormValues_({\n       mode: ProxyFormController.ProxyTypes.FIXED,\n       rules: {\n         proxyForHttp: {\n           scheme: 'http',\n           host: 'http.example.com',\n           port: 1\n        },\n         proxyForHttps: {\n           scheme: 'https',\n           host: 'https.example.com',\n           port: 2\n        },\n         proxyForFtp: {\n           scheme: 'socks4',\n           host: 'socks4.example.com',\n           port: 3\n        },\n         fallbackProxy: {\n           scheme: 'socks5',\n           host: 'socks5.example.com',\n           port: 4\n        }\n      }\n    });\n    // Not Single!\n    this.assert(\n      !document.querySelector('#' + ProxyFormController.ProxyTypes.FIXED\n          + ' > section').classList.contains('single'));\n    var server = this.controller_.singleProxy;\n    this.assertNull(server);\n\n    server = this.controller_.httpProxy;\n    this.assertEqual('http', server.scheme);\n    this.assertEqual('http.example.com', server.host);\n    this.assertEqual(1, server.port);\n\n    server = this.controller_.httpsProxy;\n    this.assertEqual('https', server.scheme);\n    this.assertEqual('https.example.com', server.host);\n    this.assertEqual(2, server.port);\n\n    server = this.controller_.ftpProxy;\n    this.assertEqual('socks4', server.scheme);\n    this.assertEqual('socks4.example.com', server.host);\n    this.assertEqual(3, server.port);\n\n    server = this.controller_.fallbackProxy;\n    this.assertEqual('socks5', server.scheme);\n    this.assertEqual('socks5.example.com', server.host);\n    this.assertEqual(4, server.port);\n  },\n\n  testBypassList: function() {\n    this.controller_.bypassList = ['1.example.com',\n                                   '2.example.com',\n                                   '3.example.com'];\n    this.assertEnumEqual(\n        document.getElementById('bypassList').value,\n        '1.example.com, 2.example.com, 3.example.com');\n    this.assertEnumEqual(\n        this.controller_.bypassList,\n        ['1.example.com', '2.example.com', '3.example.com']);\n  },\n\n  // Test that \"system\" rules are correctly generated\n  testProxyRulesGenerationSystem: function() {\n    this.controller_.changeActive_(\n        document.getElementById(ProxyFormController.ProxyTypes.SYSTEM));\n\n    this.assertHashEqual(\n        {mode: 'system'},\n        this.controller_.generateProxyConfig_());\n  },\n\n  // Test that \"direct\" rules are correctly generated\n  testProxyRulesGenerationDirect: function() {\n    this.controller_.changeActive_(\n        document.getElementById(ProxyFormController.ProxyTypes.DIRECT));\n\n    this.assertHashEqual(\n        {mode: 'direct'},\n        this.controller_.generateProxyConfig_());\n  },\n\n  // Test that auto detection rules are correctly generated when \"automatic\"\n  // is selected, and no PAC file URL is given\n  testProxyRulesGenerationAuto: function() {\n    this.controller_.changeActive_(\n        document.getElementById(ProxyFormController.ProxyTypes.PAC));\n\n    this.assertHashEqual(\n        {mode: 'auto_detect'},\n        this.controller_.generateProxyConfig_());\n  },\n\n  // Test that PAC URL rules are correctly generated when \"automatic\"\n  // is selected, and a PAC file URL is given\n  testProxyRulesGenerationPacURL: function() {\n    this.controller_.changeActive_(\n        document.getElementById(ProxyFormController.ProxyTypes.PAC));\n    this.controller_.pacURL = 'http://example.com/pac.pac';\n    var result = this.controller_.generateProxyConfig_();\n    this.assertEqual('pac_script', result.mode);\n    this.assertEqual('http://example.com/pac.pac', result.pacScript.url);\n  },\n\n  // Manual PAC definitions\n  testProxyRulesGenerationPacData: function() {\n    var pacData = 'function FindProxyForURL(url,host) { return \"DIRECT\"; }';\n    this.controller_.changeActive_(\n        document.getElementById(ProxyFormController.ProxyTypes.PAC));\n    this.controller_.manualPac = pacData;\n    var result = this.controller_.generateProxyConfig_();\n    this.assertEqual('pac_script', result.mode);\n    this.assertEqual(pacData, result.pacScript.data);\n  },\n\n  // PAC URLs override manual PAC definitions\n  testProxyRulesGenerationPacURLOverridesData: function() {\n    this.controller_.changeActive_(\n        document.getElementById(ProxyFormController.ProxyTypes.PAC));\n    this.controller_.pacURL = 'http://example.com/pac.pac';\n    this.controller_.manualPac =\n        'function FindProxyForURL(url,host) { return \"DIRECT\"; }';\n    var result = this.controller_.generateProxyConfig_();\n    this.assertEqual('pac_script', result.mode);\n    this.assertEqual('http://example.com/pac.pac', result.pacScript.url);\n  },\n\n  // Test that fixed, manual servers are correctly transformed into a\n  // `ProxyRules` structure.\n  testProxyRulesGenerationSingle: function() {\n    this.controller_.changeActive_(\n        document.getElementById(ProxyFormController.ProxyTypes.FIXED));\n\n    this.controller_.singleProxy = {\n      scheme: 'http',\n      host: 'example.com',\n      port: '80'\n    };\n\n    var result = this.controller_.generateProxyConfig_();\n    this.assertEqual('fixed_servers', result.mode);\n    this.assertEqual('http', result.rules.singleProxy.scheme);\n    this.assertEqual('example.com', result.rules.singleProxy.host);\n    this.assertEqual(80, result.rules.singleProxy.port);\n    this.assertEqual(undefined, result.rules.proxyForHttp);\n    this.assertEqual(undefined, result.rules.proxyForHttps);\n    this.assertEqual(undefined, result.rules.proxyForFtp);\n    this.assertEqual(undefined, result.rules.fallbackProxy);\n  },\n\n  // Test that proxy configuration rules are correctly generated\n  // for separate manually entered servers.\n  testProxyRulesGenerationSeparate: function() {\n    this.controller_.changeActive_(\n        document.getElementById(ProxyFormController.ProxyTypes.FIXED));\n\n    this.controller_.singleProxy = false;\n    this.controller_.httpProxy = {\n      scheme: 'http',\n      host: 'http.example.com',\n      port: 80\n    };\n    this.controller_.httpsProxy = {\n      scheme: 'https',\n      host: 'https.example.com',\n      port: 443\n    };\n    this.controller_.ftpProxy = {\n      scheme: 'socks4',\n      host: 'ftp.example.com',\n      port: 80\n    };\n    this.controller_.fallbackProxy = {\n      scheme: 'socks5',\n      host: 'fallback.example.com',\n      port: 80\n    };\n\n    var result = this.controller_.generateProxyConfig_();\n    this.assertEqual('fixed_servers', result.mode);\n    this.assertEqual(undefined, result.rules.singleProxy);\n    this.assertEqual('http', result.rules.proxyForHttp.scheme);\n    this.assertEqual('http.example.com', result.rules.proxyForHttp.host);\n    this.assertEqual('80', result.rules.proxyForHttp.port);\n    this.assertEqual('https', result.rules.proxyForHttps.scheme);\n    this.assertEqual('https.example.com', result.rules.proxyForHttps.host);\n    this.assertEqual('443', result.rules.proxyForHttps.port);\n    this.assertEqual('socks4', result.rules.proxyForFtp.scheme);\n    this.assertEqual('ftp.example.com', result.rules.proxyForFtp.host);\n    this.assertEqual('80', result.rules.proxyForFtp.port);\n    this.assertEqual('socks5', result.rules.fallbackProxy.scheme);\n    this.assertEqual('fallback.example.com', result.rules.fallbackProxy.host);\n    this.assertEqual('80', result.rules.fallbackProxy.port);\n  }\n}, { testLog: 'proxyformcontrollerlog' });\n\nvar c = new ProxyFormController('proxyForm');\n"
  },
  {
    "path": "_archive/mv2/extensions/proxy_configuration/test/unittest.css",
    "content": "body, div, p, h1, h2, h3, ul, ol, span, a, table, td, form, img, li {\n  font-family: sans-serif;\n}\n\nbody {\n  font-size:0.8em;\n}\n\n#log {\n  padding-bottom: 1em;\n  border-bottom: 2px solid #000;\n  margin-bottom: 2em;\n}\n\n.logsummary {\n  margin-top: 1em;\n  margin-bottom: 1em;\n  padding: 1ex;\n  border: 1px solid #000;\n  font-weight: bold;\n}\n\n.logtable {\n  width:100%;\n  border-collapse: collapse;\n  border: 1px dotted #666;\n}\n\n.logtable td, .logtable th {\n  text-align: left;\n  padding: 3px 8px;\n  border: 1px dotted #666;\n}\n\n.logtable .passed {\n  background-color: #cfc;\n}\n\n.logtable .failed, .logtable .error {\n  background-color: #fcc;\n}\n\n.logtable .warning {\n  background-color: #FC6;\n}\n\n.logtable td div.action_buttons {\n  display: inline;\n}\n\n.logtable td div.action_buttons input {\n  margin: 0 5px;\n  font-size: 10px;\n}\n\n#fixture {\n  display: none;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/speak_selection/background.js",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nvar lastUtterance = '';\nvar speaking = false;\nvar globalUtteranceIndex = 0;\n\nif (localStorage['lastVersionUsed'] != '1') {\n  localStorage['lastVersionUsed'] = '1';\n  chrome.tabs.create({\n    url: chrome.extension.getURL('options.html')\n  });\n}\n\nfunction speak(utterance) {\n  if (speaking && utterance == lastUtterance) {\n    chrome.tts.stop();\n    return;\n  }\n\n  speaking = true;\n  lastUtterance = utterance;\n  globalUtteranceIndex++;\n  var utteranceIndex = globalUtteranceIndex;\n\n  chrome.browserAction.setIcon({path: 'SpeakSel19-active.png'});\n\n  var rate = localStorage['rate'] || 1.0;\n  var pitch = localStorage['pitch'] || 1.0;\n  var volume = localStorage['volume'] || 1.0;\n  var voice = localStorage['voice'];\n  chrome.tts.speak(\n      utterance,\n      {voiceName: voice,\n       rate: parseFloat(rate),\n       pitch: parseFloat(pitch),\n       volume: parseFloat(volume),\n       onEvent: function(evt) {\n         if (evt.type == 'end' ||\n             evt.type == 'interrupted' ||\n             evt.type == 'cancelled' ||\n             evt.type == 'error') {\n           if (utteranceIndex == globalUtteranceIndex) {\n             speaking = false;\n             chrome.browserAction.setIcon({path: 'SpeakSel19.png'});\n           }\n         }\n       }\n      });\n}\n\nfunction initBackground() {\n  loadContentScriptInAllTabs();\n\n  var defaultKeyString = getDefaultKeyString();\n  var keyString = localStorage['speakKey'];\n  if (keyString == undefined) {\n    keyString = defaultKeyString;\n    localStorage['speakKey'] = keyString;\n  }\n  sendKeyToAllTabs(keyString);\n\n  chrome.extension.onRequest.addListener(\n      function(request, sender, sendResponse) {\n        if (request['init']) {\n          sendResponse({'key': localStorage['speakKey']});\n        } else if (request['speak']) {\n          speak(request['speak']);\n        }\n      });\n\n  chrome.browserAction.onClicked.addListener(\n      function(tab) {\n        chrome.tabs.sendRequest(\n            tab.id,\n            {'speakSelection': true});\n      });\n}\n\ninitBackground();\n"
  },
  {
    "path": "_archive/mv2/extensions/speak_selection/content_script.js",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nvar speakKeyStr;\n\nfunction speakSelection() {\n  var focused = document.activeElement;\n  var selectedText;\n  if (focused) {\n    try {\n      selectedText = focused.value.substring(\n          focused.selectionStart, focused.selectionEnd);\n    } catch (err) {\n    }\n  }\n  if (selectedText == undefined) {\n    var sel = window.getSelection();\n    var selectedText = sel.toString();\n  }\n  chrome.extension.sendRequest({'speak': selectedText});\n}\n\nfunction onExtensionMessage(request) {\n  if (request['speakSelection'] != undefined) {\n    if (!document.hasFocus()) {\n      return;\n    }\n    speakSelection();\n  } else if (request['key'] != undefined) {\n    speakKeyStr = request['key'];\n  }\n}\n\nfunction initContentScript() {\n  chrome.extension.onRequest.addListener(onExtensionMessage);\n  chrome.extension.sendRequest({'init': true}, onExtensionMessage);\n\n  document.addEventListener('keydown', function(evt) {\n    if (!document.hasFocus()) {\n      return true;\n    }\n    var keyStr = keyEventToString(evt);\n    if (keyStr == speakKeyStr && speakKeyStr.length > 0) {\n      speakSelection();\n      evt.stopPropagation();\n      evt.preventDefault();\n      return false;\n    }\n    return true;\n  }, false);\n}\n\ninitContentScript();\n"
  },
  {
    "path": "_archive/mv2/extensions/speak_selection/keycodes.js",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nvar KEY_MAP = {\n  12: 'Clear',\n  14: 'Enter',\n  33: 'PgUp',\n  34: 'PgDown',\n  35: 'End',\n  36: 'Home',\n  37: 'Left',\n  38: 'Up',\n  39: 'Right',\n  40: 'Down',\n  45: 'Insert',\n  46: 'Delete',\n  96: 'Numpad0',\n  97: 'Numpad1',\n  98: 'Numpad2',\n  99: 'Numpad3',\n  100: 'Numpad4',\n  101: 'Numpad5',\n  102: 'Numpad6',\n  103: 'Numpad7',\n  104: 'Numpad8',\n  105: 'Numpad9',\n  106: '*',\n  107: 'Plus',\n  108: '_',\n  109: '-',\n  111: '/',\n  112: 'F1',\n  113: 'F2',\n  114: 'F3',\n  115: 'F4',\n  116: 'F5',\n  117: 'F6',\n  118: 'F7',\n  119: 'F8',\n  120: 'F9',\n  121: 'F10',\n  122: 'F11',\n  123: 'F12',\n  124: 'F13',\n  125: 'F14',\n  126: 'F15',\n  186: ';',\n  187: '=',\n  188: ',',\n  189: '-',\n  190: '.',\n  191: '/',\n  192: '`',\n  219: '[',\n  221: ']'\n};\n\nvar isMac = (navigator.appVersion.indexOf(\"Mac\") != -1);\n\nfunction keyEventToString(evt) {\n  var tokens = [];\n  if (evt.ctrlKey) {\n    tokens.push('Control');\n  }\n  if (evt.altKey) {\n    tokens.push(isMac ? 'Option' : 'Alt');\n  }\n  if (evt.metaKey) {\n    tokens.push(isMac ? 'Command' : 'Meta');\n  }\n  if (evt.shiftKey) {\n    tokens.push('Shift');\n  }\n  if (evt.keyCode >= 48 && evt.keyCode <= 90) {\n    tokens.push(String.fromCharCode(evt.keyCode));\n  } else if (KEY_MAP[evt.keyCode]) {\n    tokens.push(KEY_MAP[evt.keyCode]);\n        } else {\n    return '';\n        }\n  return tokens.join('+');\n}\n\nfunction getDefaultKeyString() {\n  return keyEventToString({\n    keyCode: 83,  // 's'\n    shiftKey: true,\n    altKey: true,\n    ctrlKey: true,\n    metaKey: false});\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/speak_selection/manifest.json",
    "content": "{\n  \"name\": \"Speak Selection\",\n  \"version\": \"1.1\",\n  \"description\": \"Speaks the current selection out loud.\",\n  \"permissions\": [\n    \"<all_urls>\",\n    \"tts\",\n    \"tabs\"\n  ],\n\n  \"background\": {\n    \"scripts\": [\n      \"keycodes.js\",\n      \"tabs.js\",\n      \"background.js\"\n    ]\n  },\n\n  \"browser_action\": {\n    \"default_icon\": \"SpeakSel19.png\",\n    \"default_title\": \"Speak Selection\"\n  },\n\n  \"options_page\": \"options.html\",\n\n  \"minimum_chrome_version\": \"14\",\n\n  \"content_scripts\": [\n    {\n      \"matches\": [\n        \"<all_urls>\"\n      ],\n      \"all_frames\": true,\n      \"js\": [\n        \"keycodes.js\",\n        \"content_script.js\"\n      ]\n    }\n  ],\n\n  \"icons\": {\n    \"16\": \"SpeakSel16.png\",\n    \"48\": \"SpeakSel48.png\",\n    \"128\": \"SpeakSel128.png\",\n    \"256\": \"SpeakSel256.png\"\n  },\n\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/speak_selection/options.html",
    "content": "<html>\n<head>\n  <title>Speak Selection Options</title>\n  <style>\n    body {\n      font-family: arial, helvetica, sans-serif;\n    }\n    .banner {\n      width: 100%;\n      float: left;\n    }\n    .banner_left {\n      padding: 8px;\n      float: left;\n    }\n    .banner_right {\n      padding: 8px;\n    }\n    .body_wrapper {\n      width: 100%;\n      float: left;\n    }\n    .body_left {\n      border: 0;\n      padding: 0;\n      margin: 0;\n      width: 50%;\n      float: left;\n    }\n    .body_right {\n      border: 0;\n      padding: 0;\n      margin: 0;\n      width: 46%;\n      float: left;\n    }\n    .body_inner {\n      padding: 0 32px;\n    }\n    .browser_action {\n      vertical-align: middle;\n      margin: 0 2px 3px 2px;\n    }\n    .ctrl_label {\n      width: 100px;\n      float: left;\n    }\n    .ctrl_wrap {\n      margin: 18px 8px;\n    }\n    .ctrl {\n      width: 200px;\n    }\n    #hotkey {\n      font-size: 16px;\n      width: 15em;\n      margin-left: 12px;\n    }\n    #test {\n    }\n    #defaults {\n      margin-left: 24px;\n    }\n  </style>\n  <script src=\"keycodes.js\"></script>\n  <script src=\"tabs.js\"></script>\n  <script src=\"options.js\"></script>\n  <script src=\"content_script.js\"></script>\n</head>\n<body>\n\n<div class=\"banner\">\n  <div class=\"banner_left\">\n    <img src=\"SpeakSel128.png\" class=\"logo\" alt=\"\">\n  </div>\n  <div class=\"banner_right\">\n    <h1>Speak Selection</h1>\n    <p>\n      This extension lets you use Chrome's text-to-speech (TTS) capabilities\n      to speak any text you find on the web.\n    </p>\n  </div>\n</div>\n\n<div class=\"body_wrapper\">\n  <div class=\"body_left\">\n    <div class=\"body_inner\">\n      <h2>Speech Settings</h2>\n\n      <div class=\"ctrl_label\">\n        <label for=\"voice\">Voice:</label>\n      </div>\n      <div class=\"ctrl_wrap\">\n        <select id=\"voice\" class=\"ctrl\"></select>\n      </div>\n\n      <div class=\"ctrl_label\">\n        <label for=\"rate\">Rate:</label>\n      </div>\n      <div class=\"ctrl_wrap\">\n        <input id=\"rate\" type=\"range\" class=\"ctrl\"\n               min=0.5 max=2.0 step=0.1 value=1.0></input>\n      </div>\n\n      <div class=\"ctrl_label\">\n        <label for=\"pitch\">Pitch:</label>\n      </div>\n      <div class=\"ctrl_wrap\">\n        <input id=\"pitch\" type=\"range\" class=\"ctrl\"\n               min=0.5 max=1.5 step=0.1 value=1.0></input>\n      </div>\n\n      <div class=\"ctrl_label\">\n        <label for=\"volume\">Volume:</label>\n      </div>\n      <div class=\"ctrl_wrap\">\n        <input id=\"volume\" type=\"range\" class=\"ctrl\"\n               min=0.0 max=1.0 step=0.1 value=1.0></input>\n      </div>\n\n      <div class=\"ctrl_label\">\n         &nbsp;\n      </div>\n      <div class=\"ctrl_wrap\">\n        <button id=\"test\">Test Speech</button>\n        <button id=\"defaults\">Defaults</button>\n      </div>\n\n    </div>\n  </div>\n  <div class=\"body_right\">\n    <div class=\"body_inner\">\n      <h2>When to speak</h2>\n      <p>\n        <span id=\"selected\">Select some text</span>\n        anywhere on a webpage, then either:\n      </p>\n\n      <p>1. Click on the\n        <img class=\"browser_action\" src=\"SpeakSel19.png\" alt=\"Speak Selection\">\n        button in the toolbar &#x2197;, or\n      </p>\n\n      <p>2. Use this hot key: <input type=\"text\" id=\"hotkey\"></input>\n      </p>\n      <p>Click the button or press the key again to stop speech.</p>\n    </div>\n  </div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/speak_selection/options.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nfunction load() {\n  var selectedElement = document.getElementById('selected');\n  var sel = window.getSelection();\n  sel.removeAllRanges();\n  var range = document.createRange();\n  range.selectNode(selectedElement);\n  sel.addRange(range);\n\n  var rateElement = document.getElementById('rate');\n  var pitchElement = document.getElementById('pitch');\n  var volumeElement = document.getElementById('volume');\n  var rate = localStorage['rate'] || 1.0;\n  var pitch = localStorage['pitch'] || 1.0;\n  var volume = localStorage['volume'] || 1.0;\n  rateElement.value = rate;\n  pitchElement.value = pitch;\n  volumeElement.value = volume;\n  function listener(evt) {\n    rate = rateElement.value;\n    localStorage['rate'] = rate;\n    pitch = pitchElement.value;\n    localStorage['pitch'] = pitch;\n    volume = volumeElement.value;\n    localStorage['volume'] = volume;\n  }\n  rateElement.addEventListener('keyup', listener, false);\n  pitchElement.addEventListener('keyup', listener, false);\n  volumeElement.addEventListener('keyup', listener, false);\n  rateElement.addEventListener('mouseup', listener, false);\n  pitchElement.addEventListener('mouseup', listener, false);\n  volumeElement.addEventListener('mouseup', listener, false);\n\n  var defaultsButton = document.getElementById('defaults');\n  defaultsButton.addEventListener('click', function(evt) {\n    rate = 1.0;\n    pitch = 1.0;\n    volume = 1.0;\n    localStorage['rate'] = rate;\n    localStorage['pitch'] = pitch;\n    localStorage['volume'] = volume;\n    rateElement.value = rate;\n    pitchElement.value = pitch;\n    volumeElement.value = volume;\n  }, false);\n\n  var voice = document.getElementById('voice');\n  var voiceArray = [];\n  chrome.tts.getVoices(function(va) {\n    voiceArray = va;\n    for (var i = 0; i < voiceArray.length; i++) {\n      var opt = document.createElement('option');\n      var name = voiceArray[i].voiceName;\n      if (name == localStorage['voice']) {\n        opt.setAttribute('selected', '');\n      }\n      opt.setAttribute('value', name);\n      opt.innerText = voiceArray[i].voiceName;\n      voice.appendChild(opt);\n    }\n  });\n  voice.addEventListener('change', function() {\n    var i = voice.selectedIndex;\n    localStorage['voice'] = voiceArray[i].voiceName;\n  }, false);\n\n  var defaultKeyString = getDefaultKeyString();\n\n  var keyString = localStorage['speakKey'];\n  if (keyString == undefined) {\n    keyString = defaultKeyString;\n  }\n\n  var testButton = document.getElementById('test');\n  testButton.addEventListener('click', function(evt) {\n    chrome.tts.speak(\n        'Testing speech synthesis',\n        {voiceName: localStorage['voice'],\n         rate: parseFloat(rate),\n         pitch: parseFloat(pitch),\n         volume: parseFloat(volume)});\n  });\n\n  var hotKeyElement = document.getElementById('hotkey');\n  hotKeyElement.value = keyString;\n  hotKeyElement.addEventListener('keydown', function(evt) {\n    switch (evt.keyCode) {\n      case 27:  // Escape\n        evt.stopPropagation();\n        evt.preventDefault();\n        hotKeyElement.blur();\n        return false;\n      case 8:   // Backspace\n      case 46:  // Delete\n        evt.stopPropagation();\n        evt.preventDefault();\n        hotKeyElement.value = '';\n        localStorage['speakKey'] = '';\n        sendKeyToAllTabs('');\n        window.speakKeyStr = '';\n        return false;\n      case 9:  // Tab\n        return false;\n      case 16:  // Shift\n      case 17:  // Control\n      case 18:  // Alt/Option\n      case 91:  // Meta/Command\n        evt.stopPropagation();\n        evt.preventDefault();\n        return false;\n    }\n    var keyStr = keyEventToString(evt);\n    if (keyStr) {\n      hotKeyElement.value = keyStr;\n      localStorage['speakKey'] = keyStr;\n      sendKeyToAllTabs(keyStr);\n\n      // Set the key used by the content script running in the options page.\n      window.speakKeyStr = keyStr;\n    }\n    evt.stopPropagation();\n    evt.preventDefault();\n    return false;\n  }, true);\n}\n\ndocument.addEventListener('DOMContentLoaded', load);\n"
  },
  {
    "path": "_archive/mv2/extensions/speak_selection/tabs.js",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nfunction sendKeyToAllTabs(keyStr) {\n  chrome.windows.getAll({'populate': true}, function(windows) {\n    for (var i = 0; i < windows.length; i++) {\n      var tabs = windows[i].tabs;\n      for (var j = 0; j < tabs.length; j++) {\n        chrome.tabs.sendRequest(\n            tabs[j].id,\n            {'key': keyStr});\n      }\n    }\n  });\n}\n\nfunction loadContentScriptInAllTabs() {\n  chrome.windows.getAll({'populate': true}, function(windows) {\n    for (var i = 0; i < windows.length; i++) {\n      var tabs = windows[i].tabs;\n      for (var j = 0; j < tabs.length; j++) {\n        chrome.tabs.executeScript(\n            tabs[j].id,\n            {file: 'keycodes.js', allFrames: true});\n        chrome.tabs.executeScript(\n            tabs[j].id,\n            {file: 'content_script.js', allFrames: true});\n      }\n    }\n  });\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/talking_alarm_clock/background.js",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nvar a1Timer = null;\nvar a2Timer = null;\nvar port = null;\nvar iconFlashTimer = null;\n\nvar HOUR_MS = 1000 * 60 * 60;\n\n// Override from common.js\nwindow.stopFlashingIcon = function() {\n  window.clearTimeout(iconFlashTimer);\n  chrome.browserAction.setIcon({'path': 'clock-19.png'});\n};\n\n// Override from common.js\nwindow.flashIcon = function() {\n  var flashes = 10;\n  function flash() {\n    if (flashes == 0) {\n      stopFlashingIcon();\n      return;\n    }\n\n    if (flashes % 2 == 0) {\n      chrome.browserAction.setIcon({'path': 'clock-highlighted-19.png'});\n    } else {\n      chrome.browserAction.setIcon({'path': 'clock-19.png'});\n    }\n    flashes--;\n    iconFlashTimer = window.setTimeout(flash, 500);\n  }\n  flash();\n};\n\nfunction setTimer(alarmHours, alarmMinutes) {\n  var alarmTime = (alarmHours * 60 + alarmMinutes) * 60 * 1000;\n  var d = new Date();\n  var now = d.getHours() * HOUR_MS +\n            d.getMinutes() * 60 * 1000 +\n            d.getSeconds() * 1000;\n  var delta = (alarmTime - now);\n\n  if (delta >= -5000 && delta < 1000) {\n    ringAlarm(alarmHours, alarmMinutes);\n    if (port) {\n      port.postMessage({'cmd': 'anim'});\n    }\n    return null;\n  }\n\n  if (delta < 0) {\n    delta += HOUR_MS * 24;\n  }\n  if (delta >= 1000) {\n    if (delta > HOUR_MS) {\n      delta = HOUR_MS;\n    }\n    console.log('Timer set for ' + delta + ' ms');\n    return window.setTimeout(resetTimers, delta);\n  }\n\n  return null;\n};\n\nfunction resetTimers() {\n  if (a1Timer) {\n    window.clearTimeout(a1Timer);\n  }\n\n  try {\n    var a1_on = (localStorage['a1_on'] == 'true');\n    var a1_tt = localStorage['a1_tt'] || DEFAULT_A1_TT;\n    var a1_ampm = localStorage['a1_ampm'] || DEFAULT_A1_AMPM;\n    if (a1_on) {\n      var alarmHoursMinutes = parseTime(a1_tt, a1_ampm);\n      var alarmHours = alarmHoursMinutes[0];\n      var alarmMinutes = alarmHoursMinutes[1];\n      a1Timer = setTimer(alarmHours, alarmMinutes);\n    }\n  } catch (e) {\n    console.log(e);\n  }\n\n  try {\n    var a2_on = (localStorage['a2_on'] == 'true');\n    var a2_tt = localStorage['a2_tt'] || DEFAULT_A2_TT;\n    var a2_ampm = localStorage['a2_ampm'] || DEFAULT_A2_AMPM;\n    if (a2_on) {\n      var alarmHoursMinutes = parseTime(a2_tt, a2_ampm);\n      var alarmHours = alarmHoursMinutes[0];\n      var alarmMinutes = alarmHoursMinutes[1];\n      a2Timer = setTimer(alarmHours, alarmMinutes);\n    }\n  } catch (e) {\n    console.log(e);\n  }\n\n  if (a1_on || a2_on) {\n    chrome.browserAction.setIcon({'path': 'clock-19.png'});\n  } else {\n    chrome.browserAction.setIcon({'path': 'clock-disabled-19.png'});\n  }\n}\n\nfunction onLocalStorageChange() {\n  resetTimers();\n}\n\nfunction initBackground() {\n  window.addEventListener('storage', onLocalStorageChange, false);\n\n  chrome.runtime.onConnect.addListener(function(popupPort) {\n    port = popupPort;\n    port.onDisconnect.addListener(function() {\n      port = null;\n    });\n  });\n}\n\ninitBackground();\nresetTimers();\n"
  },
  {
    "path": "_archive/mv2/extensions/talking_alarm_clock/common.js",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nvar DEFAULT_A1_TT = '09:30';\nvar DEFAULT_A1_AMPM = 0;\nvar DEFAULT_A2_TT = '03:30';\nvar DEFAULT_A2_AMPM = 1;\nvar DEFAULT_RATE = 1.0;\nvar DEFAULT_VOLUME = 1.0;\nvar DEFAULT_PHRASE = 'It\\'s $TIME, so get up!';\nvar DEFAULT_SOUND = 'ringing';\n\nvar audio = null;\n\nvar isPlaying = false;\nvar isSpeaking = false;\nvar isAnimating = false;\n\n// Overridden in popup.js but not in background.js.\nwindow.displayAlarmAnimation = function() {\n};\n\n// Overridden in popup.js but not in background.js.\nwindow.stopAlarmAnimation = function() {\n};\n\n// Overridden in background.js but not in popup.js.\nwindow.flashIcon = function() {\n};\n\n// Overridden in background.js but not in popup.js.\nwindow.stopFlashingIcon = function() {\n};\n\nfunction $(id) {\n  return document.getElementById(id);\n}\n\nfunction parseTime(timeString, ampm) {\n  var time = timeString.match(/^(\\d\\d):(\\d\\d)$/);\n  if (!time) {\n    throw 'Cannot parse: ' + timeString;\n  }\n\n  var hours = parseInt(time[1], 10);\n  if (hours == 12 && ampm == 0) {\n    hours = 0;\n  } else {\n    hours += (hours < 12 && ampm == 1)? 12 : 0;\n  }\n  var minutes = parseInt(time[2], 10) || 0;\n\n  return [hours, minutes];\n}\n\nfunction stopAll() {\n  if (audio) {\n    audio.pause();\n    isPlaying = false;\n  }\n  try {\n    chrome.tts.stop();\n    isSpeaking = false;\n  } catch (e) {\n  }\n  window.stopAlarmAnimation();\n  window.stopFlashingIcon();\n}\n\nfunction playSound(duckAudio) {\n  if (audio) {\n    audio.pause();\n    document.body.removeChild(audio);\n    audio = null;\n  }\n\n  var currentSound = localStorage['sound'] || DEFAULT_SOUND;\n  if (currentSound == 'none') {\n    return;\n  }\n\n  audio = document.createElement('audio');\n  audio.addEventListener('ended', function(evt) {\n    isPlaying = false;\n  });\n  document.body.appendChild(audio);\n  audio.autoplay = true;\n\n  var src = 'audio/' + currentSound + '.ogg';\n  var volume = parseFloat(localStorage['volume']) || DEFAULT_VOLUME;\n  audio.volume = volume;\n  audio.src = src;\n  isPlaying = true;\n\n  if (duckAudio) {\n    for (var i = 0; i < 10; i++) {\n      (function(i) {\n         window.setTimeout(function() {\n           var duckedVolume = volume * (1.0 - 0.07 * (i + 1));\n           audio.volume = duckedVolume;\n         }, 1800 + 50 * i);\n      })(i);\n    }\n  }\n}\n\nfunction getTimeString(hh, mm) {\n  var ampm = hh >= 12 ? 'P M' : 'A M';\n  hh = (hh % 12);\n  if (hh == 0)\n    hh = 12;\n  if (mm == 0)\n    mm = 'o\\'clock';\n  else if (mm < 10)\n    mm = 'O ' + mm;\n\n  return hh + ' ' + mm + ' ' + ampm;\n}\n\nfunction speak(text) {\n  var rate = parseFloat(localStorage['rate']) || DEFAULT_RATE;\n  var pitch = 1.0;\n  var volume = parseFloat(localStorage['volume']) || DEFAULT_VOLUME;\n  var voice = localStorage['voice'];\n  chrome.tts.speak(\n      text,\n      {voiceName: voice,\n       rate: rate,\n       pitch: pitch,\n       volume: volume,\n       onEvent: function(evt) {\n         if (evt.type == 'end') {\n           isSpeaking = false;\n         }\n       }\n      });\n}\n\nfunction speakPhraseWithTimeString(timeString) {\n  var phraseTemplate = localStorage['phrase'] || DEFAULT_PHRASE;\n  var utterance = phraseTemplate.replace(/\\$TIME/g, timeString);\n  speak(utterance);\n}\n\nfunction speakPhraseWithCurrentTime() {\n  var d = new Date();\n  speakPhraseWithTimeString(getTimeString(d.getHours(), d.getMinutes()));\n}\n\nfunction ringAlarm(alarmHours, alarmMinutes) {\n  window.displayAlarmAnimation();\n  window.flashIcon();\n\n  var phraseTemplate = localStorage['phrase'] || DEFAULT_PHRASE;\n  var currentSound = localStorage['sound'] || DEFAULT_SOUND;\n\n  if (phraseTemplate == '') {\n    playSound(false);\n  } else if (currentSound == 'none') {\n    speakPhraseWithTimeString(getTimeString(alarmHours, alarmMinutes));\n  } else {\n    chrome.tts.stop();\n    playSound(true);\n    isSpeaking = true;\n    window.setTimeout(function() {\n      if (isSpeaking) {\n        speakPhraseWithTimeString(getTimeString(alarmHours, alarmMinutes));\n      }\n    }, 2000);\n  }\n}\n\nfunction ringAlarmWithCurrentTime() {\n  var d = new Date();\n  ringAlarm(d.getHours(), d.getMinutes());\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/talking_alarm_clock/credits.html",
    "content": "<html>\n<head>\n  <title>Talking Alarm Clock</title>\n  <style>\n    body {\n      font-family: arial, helvetica, sans-serif;\n      font-size: 13;\n    }\n  </style>\n</head>\n<body>\n\n<img src=\"clock-128.png\" style=\"float: left; margin: 0 20px 200px 0;\">\n\n<p>\n<b>Talking Alarm Clock for Google Chrome</b>\n</p>\n\n<p>\nby Dominic Mazzoni\n</p>\n\n<p>\nTalking Alarm Clock uses the following sound files from Freesound\n(<a href=\"http://www.freesound.org\">http://www.freesound.org</a>):\n</p>\n\n<ul style=\"margin-left: 150px;\">\n<li>alarmclockbeeps from tedthetrumpet\n<li>alarm_clock_ringing from joedeshon\n<li>CuckooClock6DP from acclivity\n<li>ClockStrikes12 from acclivity\n<li>Maxines from TexasMusicForge\n<li>fat_beat_1 from -zin-\n<li>20070812.rooster from dobroide\n</ul>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/talking_alarm_clock/manifest.json",
    "content": "{\n  \"name\": \"Talking Alarm Clock\",\n  \"version\": \"1.3\",\n  \"description\": \"A clock with two configurable alarms that will play a sound and speak a phrase of your choice.\",\n  \"permissions\": [ \"background\", \"tts\" ],\n\n  \"background\": { \"scripts\": [\"common.js\", \"background.js\"] },\n\n  \"browser_action\": {\n    \"default_icon\": \"clock-19.png\",\n    \"default_title\": \"Talking Alarm Clock\",\n    \"default_popup\": \"popup.html\"\n  },\n\n  \"icons\": {\n    \"16\": \"clock-16.png\",\n    \"48\": \"clock-48.png\",\n    \"128\": \"clock-128.png\",\n    \"256\": \"clock-256.png\"\n  },\n\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/talking_alarm_clock/popup.html",
    "content": "<html>\n<head>\n  <title>Talking Alarm Clock</title>\n  <link href='http://fonts.googleapis.com/css?family=Nova%20Mono' rel='stylesheet' type='text/css'>\n  <style>\n    body {\n      overflow: hidden;\n      margin-top: 0px;\n    }\n    #main {\n      width: 200px;\n      font-family: arial, helvetica, sans-serif;\n      font-size: 13;\n    }\n    #clock {\n      cursor: pointer;\n    }\n    .alarm_wrap {\n      margin-top: 6px;\n      padding: 6px;\n      background-color: #dfd;\n      border: 1px solid #aaa;\n      border-radius: 4px;\n    }\n    .alarm_wrap.disabled {\n      background-color: #eee;\n    }\n    .alarm_wrap[aria-invalid] {\n      background-color: #f99;\n    }\n    .alarm_wrap[aria-invalid] input {\n      color: #900;\n    }\n    .alarm_wrap input {\n      font-size: 20;\n    }\n    .alarm_wrap input[type=time] {\n      font-size: 20;\n      width: 85px;\n    }\n    .alarm_wrap.disabled input {\n      color: #999;\n    }\n    .ctrl_label { \n      float: left;\n      width: 100%;\n      margin-top: 6px;\n    }\n    .ctrl_wrap {\n      width: 200px;\n      float: left;\n    }\n    .ctrl_wrap input[type=range] {\n      width: 180px;\n      height: 16px;\n    }\n    .buttons {\n      margin-top: 10px;\n    }\n    .voice_options {\n    }\n    #sound {\n      float: left;\n      width: 160px;\n      margin: 8px 0px;\n    }\n    #playsound {\n      padding: 5px;\n      margin: 5px;\n    }\n    #phrase {\n      float: left;\n      width: 160px;\n    }\n    #playspeech {\n      padding: 5px;\n      margin: 5px;\n    }\n    #a1_tt {\n      font-family: Nova Mono;\n      height: 34px;\n    }\n    #a2_tt {\n      font-family: Nova Mono;\n      height: 34px;\n    }\n    #a1_ampm {\n      font-family: Nova Mono;\n    }\n    #a2_ampm {\n      font-family: Nova Mono;\n    }\n    #current_time {\n      font-family: Nova Mono;\n      font-size: 24;\n      height: 32px;\n    }\n    body.nooutline * {\n      outline: none;\n    }\n    .footer {\n      clear:left;\n    }\n  </style>\n  <script src=\"common.js\"></script>\n  <script src=\"popup.js\"></script>\n</head>\n<body>\n\n<div id=\"main\">\n\n  <center>\n    <canvas id=\"clock\" width=\"150\" height=\"150\"\n            role=\"button\" tabindex=\"0\"></canvas>\n    <div id=\"current_time\">00:00:00</div>\n  </center>\n\n  <div id=\"a1_wrap\" class=\"alarm_wrap\">\n    <label for=\"a1_on\">Alarm 1</label>\n    <br>\n    <input id=\"a1_on\" type=\"checkbox\">\n    <input id=\"a1_tt\" type=\"time\" step=\"300\" size=\"5\">\n    <select id=\"a1_ampm\">\n      <option>AM</option>\n      <option selected>PM</option>\n    </select>\n  </div>\n  <div id=\"a2_wrap\" class=\"alarm_wrap\">\n    <label for=\"a2_on\">Alarm 2</label>\n    <br>\n    <input id=\"a2_on\" type=\"checkbox\">\n    <input id=\"a2_tt\" type=\"time\" step=\"300\" size=\"5\">\n    <select id=\"a2_ampm\">\n      <option>AM</option>\n      <option selected>PM</option>\n    </select>\n  </div>\n\n  <div class=\"voice_options\">\n    <div>\n      <div class=\"ctrl_label\">\n        <label for=\"sound\">Sound:</label>\n      </div>\n      <div class=\"ctrl_wrap\">\n        <select id=\"sound\" class=\"ctrl\">\n          <option value=\"none\">None</option>\n          <option selected value=\"cuckoo\">Cuckoo Clock</option>\n          <option value=\"digital\">Digital Alarm Clock</option>\n          <option value=\"metal\">Metal</option>\n          <option value=\"ringing\">Ringing Alarm Clock</option>\n          <option value=\"rooster\">Rooster</option>\n        </select>\n\n        <button id=\"playsound\" title=\"Play Sound\">\n          <img src=\"play.png\">\n        </button>\n      </div>\n\n      <div class=\"ctrl_label\">\n        <label for=\"sound\">Phrase (use $TIME to say time):</label>\n      </div>\n      <div class=\"ctrl_wrap\">\n        <textarea id=\"phrase\"></textarea>\n\n        <button id=\"playspeech\" title=\"Play Speech\">\n          <img src=\"play.png\">\n        </button>\n      </div>\n\n      <div class=\"ctrl_label\">\n        <label for=\"voice\">Voice:</label>\n      </div>\n      <div class=\"ctrl_wrap\">\n        <select id=\"voice\" class=\"ctrl\"></select>\n      </div>\n\n      <div class=\"ctrl_label\">\n        <label for=\"rate\">Speech rate:</label>\n      </div>\n      <div class=\"ctrl_wrap\">\n        <input id=\"rate\" type=\"range\" class=\"ctrl\"\n               min=0.5 max=1.5 step=0.1 value=1.0></input>\n      </div>\n\n      <div class=\"ctrl_label\">\n        <label for=\"volume\">Speech and sound volume:</label>\n      </div>\n      <div class=\"ctrl_wrap\">\n        <input id=\"volume\" type=\"range\" class=\"ctrl\"\n               min=0.0 max=1.0 step=0.1 value=1.0></input>\n      </div>\n    </div>\n  </div>\n\n  <div class=\"footer\">\n    <a href=\"credits.html\" target=\"_blank\">Credits</a>\n    &nbsp;|&nbsp;\n    <a href=\"https://chrome.google.com/webstore/search?q=tts\"\n       target=\"_blank\">Get more voices</a>\n  </div>\n\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/talking_alarm_clock/popup.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nvar blankClockImage;\nvar blankClockAnim1Image;\nvar blankClockAnim2Image;\nvar animationTimer;\nvar currentClockImage;\nvar port;\n\nfunction updateEnabledStatus(alarm) {\n  var enabled = $('a' + alarm + '_on').checked;\n  $('a' + alarm + '_tt').disabled = !enabled;\n  $('a' + alarm + '_ampm').disabled = !enabled;\n  var valid = true;\n  try {\n    var tt = $('a' + alarm + '_tt').value;\n    var ampm = $('a' + alarm + '_ampm').selectedIndex;\n    parseTime(tt, ampm);\n  } catch (x) {\n    valid = false;\n  }\n  if (valid) {\n    $('a' + alarm + '_wrap').removeAttribute('aria-invalid');\n  } else {\n    $('a' + alarm + '_wrap').setAttribute('aria-invalid', 'true');\n  }\n  if (enabled) {\n    $('a' + alarm + '_wrap').classList.remove('disabled');\n  } else {\n    $('a' + alarm + '_wrap').classList.add('disabled');\n  }\n}\n\nfunction loadAllImages() {\n  var loadCount = 0;\n  var img = new Image();\n  img.onload = function() {\n    blankClockImage = img;\n    currentClockImage = blankClockImage;\n    drawClock();\n  };\n  img.src = 'blank-clock-150.png';\n\n  // These will finish loading before they're needed, no need\n  // for an onload handler.\n  blankClockAnim1Image = new Image();\n  blankClockAnim1Image.src = 'blank-clock-ring1-150.png';\n  blankClockAnim2Image = new Image();\n  blankClockAnim2Image.src = 'blank-clock-ring2-150.png';\n}\n\nfunction drawClock(hh, mm, ss) {\n  if (hh == undefined || mm == undefined) {\n    var d = new Date();\n    hh = d.getHours();\n    mm = d.getMinutes();\n    ss = d.getSeconds() + 0.001 * d.getMilliseconds();\n  }\n\n  if (!currentClockImage) {\n    loadAllImages();\n    return;\n  }\n\n  var ctx = $('clock').getContext('2d');\n  ctx.drawImage(currentClockImage, 0, 0);\n\n  // Move the hour by the fraction of the minute\n  hh = (hh % 12) + (mm / 60);\n\n  // Move the minute by the fraction of the second\n  mm += (ss / 60);\n\n  var hourAngle = Math.PI * hh / 6;\n  var hourX = Math.sin(hourAngle);\n  var hourY = -Math.cos(hourAngle);\n  var minAngle = Math.PI * mm / 30;\n  var minX = Math.sin(minAngle);\n  var minY = -Math.cos(minAngle);\n  var secAngle = Math.PI * ss / 30;\n  var secX = Math.sin(secAngle);\n  var secY = -Math.cos(secAngle);\n\n  var cx = 75;\n  var cy = 77;\n\n  ctx.lineWidth = 5;\n  ctx.strokeStyle = '#ffffff';\n  ctx.globalAlpha = 0.5;\n  ctx.beginPath();\n  ctx.moveTo(cx - 4 * hourX, cy - 4 * hourY);\n  ctx.lineTo(cx + 20 * hourX, cy + 20 * hourY);\n  ctx.stroke();\n  ctx.beginPath();\n  ctx.moveTo(cx - 8 * minX, cy - 8 * minY);\n  ctx.lineTo(cx + 35 * minX, cy + 33 * minY);\n  ctx.stroke();\n\n  ctx.lineWidth = 3;\n  ctx.strokeStyle = '#696969';\n  ctx.globalAlpha = 1.0;\n  ctx.beginPath();\n  ctx.moveTo(cx - 4 * hourX, cy - 4 * hourY);\n  ctx.lineTo(cx + 20 * hourX, cy + 20 * hourY);\n  ctx.stroke();\n  ctx.beginPath();\n  ctx.moveTo(cx - 8 * minX, cy - 8 * minY);\n  ctx.lineTo(cx + 35 * minX, cy + 33 * minY);\n  ctx.stroke();\n\n  ctx.lineWidth = 1;\n  ctx.strokeStyle = '#990000';\n  ctx.globalAlpha = 1.0;\n  ctx.beginPath();\n  ctx.moveTo(cx - 4 * secX, cy - 4 * secY);\n  ctx.lineTo(cx + 40 * secX, cy + 40 * secY);\n  ctx.stroke();\n}\n\nfunction updateCurrentTime() {\n  var now = new Date();\n  var hh = now.getHours();\n  var mm = now.getMinutes();\n  var ss = now.getSeconds();\n  var str = '';\n  if (hh % 12 == 0) {\n    str += '12';\n  } else {\n    str += (hh % 12);\n  }\n  str += ':';\n  if (mm >= 10) {\n    str += mm;\n  } else {\n    str += '0' + mm;\n  }\n  str += ':';\n  if (ss >= 10) {\n    str += ss;\n  } else {\n    str += '0' + ss;\n  }\n  if (hh >= 12) {\n    str += \" PM\";\n  } else {\n    str += \" AM\";\n  }\n  $('current_time').innerText = str;\n}\n\n// Override from common.js\nwindow.stopAlarmAnimation = function() {\n  window.clearTimeout(animationTimer);\n  currentClockImage = blankClockImage;\n  drawClock();\n  isAnimating = false;\n};\n\n// Override from common.js\nwindow.displayAlarmAnimation = function() {\n  isAnimating = true;\n  var rings = 100;\n  function ring() {\n    if (rings == 0) {\n      stopAlarmAnimation();\n      return;\n    }\n    currentClockImage = (rings % 2 == 0)?\n                        blankClockAnim1Image:\n                        blankClockAnim2Image;\n    drawClock();\n    rings--;\n    animationTimer = window.setTimeout(ring, 50);\n  }\n  ring();\n};\n\nfunction addOutlineStyleListeners() {\n  document.addEventListener('click', function(evt) {\n    document.body.classList.add('nooutline');\n    return true;\n  }, true);\n  document.addEventListener('keydown', function(evt) {\n    document.body.classList.remove('nooutline');\n    return true;\n  }, true);\n}\n\nfunction load() {\n  try {\n    port = chrome.runtime.connect();\n    port.onMessage.addListener(function(msg) {\n      if (msg.cmd == 'anim') {\n        displayAlarmAnimation();\n      }\n    });\n  } catch (e) {\n  }\n\n  addOutlineStyleListeners();\n\n  stopAll();\n  drawClock();\n  setInterval(drawClock, 100);\n\n  updateCurrentTime();\n  setInterval(updateCurrentTime, 250);\n\n  function updateTime(timeElement) {\n    if (!parseTime(timeElement.value)) {\n      return false;\n    }\n\n    timeElement.valueAsNumber =\n        timeElement.valueAsNumber % (12 * 60 * 60 * 1000);\n    if (timeElement.valueAsNumber < (1 * 60 * 60 * 1000))\n      timeElement.valueAsNumber += (12 * 60 * 60 * 1000);\n    return true;\n  }\n\n  $('clock').addEventListener('click', function(evt) {\n    if (isPlaying || isSpeaking || isAnimating) {\n      stopAll();\n    } else {\n      ringAlarmWithCurrentTime();\n    }\n  }, false);\n  $('clock').addEventListener('keydown', function(evt) {\n    if (evt.keyCode == 13 || evt.keyCode == 32) {\n      if (isPlaying || isSpeaking || isAnimating) {\n        stopAll();\n      } else {\n        ringAlarmWithCurrentTime();\n      }\n    }\n  }, false);\n\n  // Alarm 1\n\n  var a1_tt = localStorage['a1_tt'] || DEFAULT_A1_TT;\n  $('a1_tt').value = a1_tt;\n  $('a1_tt').addEventListener('input', function(evt) {\n    updateEnabledStatus(1);\n    if (!updateTime($('a1_tt'))) {\n      evt.stopPropagation();\n      return false;\n    }\n    localStorage['a1_tt'] = $('a1_tt').value;\n    updateEnabledStatus(1);\n    return true;\n  }, false);\n  $('a1_tt').addEventListener('change', function(evt) {\n    if ($('a1_tt').value.length == 4 &&\n        parseTime('0' + $('a1_tt').value)) {\n      $('a1_tt').value = '0' + $('a1_tt').value;\n    }\n    if (!updateTime($('a1_tt'))) {\n      evt.stopPropagation();\n      return false;\n    }\n    localStorage['a1_tt'] = $('a1_tt').value;\n    updateEnabledStatus(1);\n    return true;\n  }, false);\n\n  var a1_on = (localStorage['a1_on'] == 'true');\n  $('a1_on').checked = a1_on;\n  $('a1_on').addEventListener('change', function(evt) {\n    window.setTimeout(function() {\n      localStorage['a1_on'] = $('a1_on').checked;\n      updateEnabledStatus(1);\n    }, 0);\n  }, false);\n\n  var a1_ampm = localStorage['a1_ampm'] || DEFAULT_A1_AMPM;\n  $('a1_ampm').selectedIndex = a1_ampm;\n  $('a1_ampm').addEventListener('change', function(evt) {\n    localStorage['a1_ampm'] = $('a1_ampm').selectedIndex;\n  }, false);\n\n  updateEnabledStatus(1);\n\n  // Alarm 2\n\n  var a2_tt = localStorage['a2_tt'] || DEFAULT_A2_TT;\n  $('a2_tt').value = a2_tt;\n  $('a2_tt').addEventListener('input', function(evt) {\n    updateEnabledStatus(2);\n    if (!updateTime($('a2_tt'))) {\n      evt.stopPropagation();\n      return false;\n    }\n    localStorage['a2_tt'] = $('a2_tt').value;\n    updateEnabledStatus(2);\n    return true;\n  }, false);\n  $('a2_tt').addEventListener('change', function(evt) {\n    if ($('a2_tt').value.length == 4 &&\n        parseTime('0' + $('a2_tt').value)) {\n      $('a2_tt').value = '0' + $('a2_tt').value;\n    }\n    if (!updateTime($('a2_tt'))) {\n      evt.stopPropagation();\n      return false;\n    }\n    localStorage['a2_tt'] = $('a2_tt').value;\n    updateEnabledStatus(2);\n    return true;\n  }, false);\n\n  var a2_on = (localStorage['a2_on'] == 'true');\n  $('a2_on').checked = a2_on;\n  $('a2_on').addEventListener('change', function(evt) {\n    window.setTimeout(function() {\n      localStorage['a2_on'] = $('a2_on').checked;\n      updateEnabledStatus(2);\n    }, 0);\n  }, false);\n\n  var a2_ampm = localStorage['a2_ampm'] || DEFAULT_A2_AMPM;\n  $('a2_ampm').selectedIndex = a2_ampm;\n  $('a2_ampm').addEventListener('change', function(evt) {\n    localStorage['a2_ampm'] = $('a2_ampm').selectedIndex;\n  }, false);\n\n  updateEnabledStatus(2);\n\n  // Phrase\n\n  var phrase = localStorage['phrase'] || DEFAULT_PHRASE;\n  $('phrase').value = phrase;\n  $('phrase').addEventListener('change', function(evt) {\n    localStorage['phrase'] = $('phrase').value;\n  }, false);\n\n  // Speech parameters\n\n  var rateElement = $('rate');\n  var volumeElement = $('volume');\n  var rate = localStorage['rate'] || DEFAULT_RATE;\n  var volume = localStorage['volume'] || DEFAULT_VOLUME;\n  rateElement.value = rate;\n  volumeElement.value = volume;\n  function listener(evt) {\n    rate = rateElement.value;\n    localStorage['rate'] = rate;\n    volume = volumeElement.value;\n    localStorage['volume'] = volume;\n  }\n  rateElement.addEventListener('keyup', listener, false);\n  volumeElement.addEventListener('keyup', listener, false);\n  rateElement.addEventListener('mouseup', listener, false);\n  volumeElement.addEventListener('mouseup', listener, false);\n\n  var sound = $('sound');\n  var currentSound = localStorage['sound'] || DEFAULT_SOUND;\n  for (var i = 0; i < sound.options.length; i++) {\n    if (sound.options[i].value == currentSound) {\n      sound.selectedIndex = i;\n      break;\n    }\n  }\n  localStorage['sound'] = sound.options[sound.selectedIndex].value;\n  sound.addEventListener('change', function() {\n    localStorage['sound'] = sound.options[sound.selectedIndex].value;\n  }, false);\n\n  var playSoundButton = $('playsound');\n  playSoundButton.addEventListener('click', function(evt) {\n    playSound(false);\n  });\n\n  var playSpeechButton = $('playspeech');\n  playSpeechButton.addEventListener('click', function(evt) {\n    speakPhraseWithCurrentTime();\n  });\n\n  var voice = $('voice');\n  var voiceArray = [];\n  if (chrome && chrome.tts) {\n    chrome.tts.getVoices(function(va) {\n      voiceArray = va;\n      for (var i = 0; i < voiceArray.length; i++) {\n        var opt = document.createElement('option');\n        var name = voiceArray[i].voiceName;\n        if (name == localStorage['voice']) {\n          opt.setAttribute('selected', '');\n        }\n        opt.setAttribute('value', name);\n        opt.innerText = voiceArray[i].voiceName;\n        voice.appendChild(opt);\n      }\n    });\n  }\n  voice.addEventListener('change', function() {\n    var i = voice.selectedIndex;\n    localStorage['voice'] = voiceArray[i].voiceName;\n  }, false);\n}\n\ndocument.addEventListener('DOMContentLoaded', load);\n"
  },
  {
    "path": "_archive/mv2/extensions/ttsdebug/manifest.json",
    "content": "{\n  \"app\": {\n    \"launch\": {\n       \"local_path\": \"ttsdebug.html\"\n    }\n  },\n  \"description\": \"Tool for developers of Chrome TTS engine extensions to help them test their engines are implementing the API correctly.\",\n  \"icons\": {\n    \"16\": \"16.png\",\n    \"128\": \"128.png\",\n    \"256\": \"256.png\"\n  },\n  \"minimum_chrome_version\": \"14\",\n  \"name\": \"TTS Debug\",\n  \"permissions\": [ \"tts\" ],\n  \"version\": \"1.0\",\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/ttsdebug/ttsdebug.css",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#main {\n  font-family: arial,helvetica;\n  font-size: 10pt;\n  text-align: center;\n  margin-left: auto;\n  margin-right: auto;\n  padding: 10px 30px 20px 30px;\n  width: 800px;\n  border-left: solid 1px #ccc;\n  border-right: solid 1px #ccc;\n}\n#stop {\n  margin-left: 100px;\n}\n#container {\n  text-align: left;\n}\n#instructions {\n  text-align: left;\n}\n.outer {\n  margin: 12px 6px 6px 6px;\n  padding: 6px;\n  border: 1px solid #000;\n}\n.outer.disabled {\n  border: 1px solid #696969;\n}\n.runTestButton {\n  margin: 12px;\n}\n.description {\n  margin: 6px 12px;\n}\n.results {\n  margin: 12px;\n}\n.messages {\n  margin: 12px;\n}\n.error {\n  color: #900;\n}\n.result {\n  margin: 6px;\n  padding: 6px;\n}\n.success {\n  font-weight: bold;\n  color: #090;\n}\n.failure {\n  font-weight: bold;\n  color: #900;\n}\n.disabled {\n  color: #696969 !important;\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/ttsdebug/ttsdebug.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Chrome TTS Debug</title>\n    <link href=\"ttsdebug.css\" rel=\"stylesheet\" type=\"text/css\">\n    <script src=\"ttsdebug.js\"></script>\n  </head>\n  <body>\n    <div id=\"main\">\n      <h2>Chrome Text-to-Speech Debug</h2>\n\n      <div id=\"instructions\">\n        <p>\n        This app is for developers of Chrome TTS engines, to help validate that\n        an engine is properly implementing the API. Click on a button to run a\n        test. A lot of errors can be detected automatically, but some tests\n        require manually listening to the speech, and it's important to listen to\n        all tests running to identify other potential glitches.</p>\n        <p>For more diagnostic information, open the JavaScript console.</p>\n      </div>\n\n      <div>\n        <label for=\"voices\">Voice:</label>\n        &nbsp;\n        <select id=\"voices\">\n          <option value=\"\">Unspecified</option>\n        </select>\n\n        <button id=\"stop\">Emergency Stop!</button>\n      </div>\n\n      <div id=\"container\"></div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/ttsdebug/ttsdebug.js",
    "content": "/**\n * Copyright (c) 2011 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nvar voiceArray;\nvar trials = 3;\nvar resultMap = {};\nvar updateDependencyFunctions = [];\nvar testRunIndex = 0;\nvar emergencyStop = false;\n\nfunction $(id) {\n  return document.getElementById(id);\n}\n\nfunction isErrorEvent(evt) {\n  return (evt.type == 'error' ||\n          evt.type == 'interrupted' ||\n          evt.type == 'cancelled');\n}\n\nfunction logEvent(callTime, testRunName, evt) {\n  var elapsed = ((new Date() - callTime) / 1000).toFixed(3);\n  while (elapsed.length < 7) {\n    elapsed = ' ' + elapsed;\n  }\n  console.log(elapsed + ' ' + testRunName + ': ' + JSON.stringify(evt));\n}\n\nfunction logSpeakCall(utterance, options, callback) {\n  var optionsCopy = {};\n  for (var key in options) {\n    if (key != 'onEvent') {\n      optionsCopy[key] = options[key];\n    }\n  }\n  console.log('Calling chrome.tts.speak(\\'' +\n              utterance + '\\', ' +\n              JSON.stringify(optionsCopy) + ')');\n  if (callback)\n    chrome.tts.speak(utterance, options, callback);\n  else\n    chrome.tts.speak(utterance, options);\n}\n\nvar tests = [\n  {\n    name: 'Baseline',\n    description: 'Ensures that the speech engine sends both start and ' +\n                 'end events, and establishes a baseline time to speak a ' +\n                 'key phrase, to compare other tests against.',\n    dependencies: [],\n    trials: 3,\n    run: function(testRunName, voiceName, callback) {\n      var callTime = new Date();\n      var startTime;\n      var warnings = [];\n      var errors = [];\n      logSpeakCall('Alpha Bravo Charlie Delta Echo', {\n        voiceName: voiceName,\n        onEvent: function(evt) {\n          logEvent(callTime, testRunName, evt);\n          if (isErrorEvent(evt)) {\n            callback(false, null, []);\n          } else if (evt.type == 'start') {\n            startTime = new Date();\n            if (evt.charIndex != 0) {\n              errors.push('Error: start event should have a charIndex of 0.');\n            }\n          } else if (evt.type == 'end') {\n            if (startTime == undefined) {\n              errors.push('Error: no \"start\" event received!');\n              startTime = callTime;\n            }\n            if (evt.charIndex != 30) {\n              errors.push('Error: end event should have a charIndex of 30.');\n            }\n            var endTime = new Date();\n            if (startTime - callTime > 1000) {\n              var delta = ((startTime - callTime) / 1000).toFixed(3);\n              warnings.push('Note: Delay of ' + delta +\n                            ' before speech started. ' +\n                            'Less than 1.0 s latency is recommended.');\n            }\n            var delta = (endTime - startTime) / 1000;\n            if (delta < 1.0) {\n              warnings.push('Warning: Default speech rate seems too fast.');\n            } else if (delta > 3.0) {\n              warnings.push('Warning: Default speech rate seems too slow.');\n            }\n            callback(errors.length == 0, delta, warnings.concat(errors));\n          }\n        }\n      });\n    }\n  },\n  {\n    name: 'Fast',\n    description: 'Speaks twice as fast and compares the time to the baseline.',\n    dependencies: ['Baseline'],\n    trials: 3,\n    run: function(testRunName, voiceName, callback) {\n      var callTime = new Date();\n      var startTime;\n      var errors = [];\n      logSpeakCall('Alpha Bravo Charlie Delta Echo', {\n        voiceName: voiceName,\n        rate: 2.0,\n        onEvent: function(evt) {\n          logEvent(callTime, testRunName, evt);\n          if (isErrorEvent(evt)) {\n            callback(false, null, []);\n          } else if (evt.type == 'start') {\n            startTime = new Date();\n          } else if (evt.type == 'end') {\n            if (startTime == undefined)\n              startTime = callTime;\n            var endTime = new Date();\n            var delta = (endTime - startTime) / 1000;\n            var relative = delta / resultMap['Baseline'];\n            if (relative < 0.35) {\n              errors.push('2x speech rate seems too fast.');\n            } else if (relative > 0.65) {\n              errors.push('2x speech rate seems too slow.');\n            }\n            callback(errors.length == 0, delta, errors);\n          }\n        }\n      });\n    }\n  },\n  {\n    name: 'Slow',\n    description: 'Speaks twice as slow and compares the time to the baseline.',\n    dependencies: ['Baseline'],\n    trials: 3,\n    run: function(testRunName, voiceName, callback) {\n      var callTime = new Date();\n      var startTime;\n      var errors = [];\n      logSpeakCall('Alpha Bravo Charlie Delta Echo', {\n        voiceName: voiceName,\n        rate: 0.5,\n        onEvent: function(evt) {\n          logEvent(callTime, testRunName, evt);\n          if (isErrorEvent(evt)) {\n            callback(false, null, []);\n          } else if (evt.type == 'start') {\n            startTime = new Date();\n          } else if (evt.type == 'end') {\n            if (startTime == undefined)\n              startTime = callTime;\n            var endTime = new Date();\n            var delta = (endTime - startTime) / 1000;\n            var relative = delta / resultMap['Baseline'];\n            if (relative < 1.6) {\n              errors.push('Half-speed speech rate seems too fast.');\n            } else if (relative > 2.4) {\n              errors.push('Half-speed speech rate seems too slow.');\n            }\n            callback(errors.length == 0, delta, errors);\n          }\n        }\n      });\n    }\n  },\n  {\n    name: 'Interrupt and restart',\n    description: 'Interrupts partway through a long sentence and then ' +\n                 'the baseline utterance, to make sure that speech after ' +\n                 'an interruption works correctly.',\n    dependencies: ['Baseline'],\n    trials: 1,\n    run: function(testRunName, voiceName, callback) {\n      var callTime = new Date();\n      var startTime;\n      var errors = [];\n      logSpeakCall('When in the course of human events it becomes ' +\n                       'necessary for one people to dissolve the political ' +\n                       'bands which have connected them ', {\n        voiceName: voiceName,\n        onEvent: function(evt) {\n          logEvent(callTime, testRunName, evt);\n        }\n      });\n      window.setTimeout(function() {\n        logSpeakCall('Alpha Bravo Charlie Delta Echo', {\n          voiceName: voiceName,\n          onEvent: function(evt) {\n            logEvent(callTime, testRunName, evt);\n            if (isErrorEvent(evt)) {\n              callback(false, null, []);\n            } else if (evt.type == 'start') {\n              startTime = new Date();\n            } else if (evt.type == 'end') {\n              if (startTime == undefined)\n                startTime = callTime;\n              var endTime = new Date();\n              var delta = (endTime - startTime) / 1000;\n              var relative = delta / resultMap['Baseline'];\n              if (relative < 0.9) {\n                errors.push('Interrupting speech seems too short.');\n              } else if (relative > 1.1) {\n                errors.push('Interrupting speech seems too long.');\n              }\n              callback(errors.length == 0, delta, errors);\n            }\n          }\n        });\n      }, 4000);\n    }\n  },\n  {\n    name: 'Low volume',\n    description: '<b>Manual</b> test - verify that the volume is lower.',\n    dependencies: [],\n    trials: 1,\n    run: function(testRunName, voiceName, callback) {\n      var callTime = new Date();\n      logSpeakCall('Alpha Bravo Charlie Delta Echo', {\n        voiceName: voiceName,\n        volume: 0.5,\n        onEvent: function(evt) {\n          logEvent(callTime, testRunName, evt);\n          if (isErrorEvent(evt)) {\n            callback(false, null, []);\n          } else if (evt.type == 'end') {\n            callback(true, null, []);\n          }\n        }\n      });\n    }\n  },\n  {\n    name: 'High pitch',\n    description: '<b>Manual</b> test - verify that the pitch is ' +\n                 'moderately higher, but quite understandable.',\n    dependencies: [],\n    trials: 1,\n    run: function(testRunName, voiceName, callback) {\n      var callTime = new Date();\n      logSpeakCall('Alpha Bravo Charlie Delta Echo', {\n        voiceName: voiceName,\n        pitch: 1.2,\n        onEvent: function(evt) {\n          logEvent(callTime, testRunName, evt);\n          if (isErrorEvent(evt)) {\n            callback(false, null, []);\n          } else if (evt.type == 'end') {\n            callback(true, null, []);\n          }\n        }\n      });\n    }\n  },\n  {\n    name: 'Low pitch',\n    description: '<b>Manual</b> test - verify that the pitch is ' +\n                 'moderately lower, but quite understandable.',\n    dependencies: [],\n    trials: 1,\n    run: function(testRunName, voiceName, callback) {\n      var callTime = new Date();\n      logSpeakCall('Alpha Bravo Charlie Delta Echo', {\n        voiceName: voiceName,\n        pitch: 0.8,\n        onEvent: function(evt) {\n          logEvent(callTime, testRunName, evt);\n          if (isErrorEvent(evt)) {\n            callback(false, null, []);\n          } else if (evt.type == 'end') {\n            callback(true, null, []);\n          }\n        }\n      });\n    }\n  },\n  {\n    name: 'Word and sentence callbacks',\n    description: 'Checks to see if proper word and sentence callbacks ' +\n                 'are received.',\n    dependencies: ['Baseline'],\n    trials: 1,\n    run: function(testRunName, voiceName, callback) {\n      var callTime = new Date();\n      var startTime;\n      var errors = [];\n      var wordExpected = [{min: 5, max: 6},\n                          {min: 11, max: 12},\n                          {min: 19, max: 20},\n                          {min: 25, max: 26},\n                          {min: 30, max: 32},\n                          {min: 37, max: 38},\n                          {min: 43, max: 44},\n                          {min: 51, max: 52},\n                          {min: 57, max: 58}];\n      var sentenceExpected = [{min: 30, max: 32}]\n      var wordCount = 0;\n      var sentenceCount = 0;\n      var lastWordTime = callTime;\n      var lastSentenceTime = callTime;\n      var avgWordTime = resultMap['Baseline'] / 5;\n      logSpeakCall('Alpha Bravo Charlie Delta Echo. ' +\n                       'Alpha Bravo Charlie Delta Echo.', {\n        voiceName: voiceName,\n        onEvent: function(evt) {\n          logEvent(callTime, testRunName, evt);\n          if (isErrorEvent(evt)) {\n            callback(false, null, []);\n          } else if (evt.type == 'start') {\n            startTime = new Date();\n            lastWordTime = startTime;\n            lastSentenceTime = startTime;\n          } else if (evt.type == 'word') {\n            if (evt.charIndex > 0 && evt.charIndex < 62) {\n              var min = wordExpected[wordCount].min;\n              var max = wordExpected[wordCount].max;\n              if (evt.charIndex < min || evt.charIndex > max) {\n                errors.push('Got word at charIndex ' + evt.charIndex + ', ' +\n                            'was expecting next word callback charIndex ' +\n                            'in the range ' + min + ':' + max + '.');\n              }\n              if (wordCount != 4) {\n                var delta = (new Date() - lastWordTime) / 1000;\n                if (delta < 0.6 * avgWordTime) {\n                  errors.push('Word at charIndex ' + evt.charIndex +\n                              ' came after only ' + delta.toFixed(3) +\n                              ' s, which seems too short.');\n                } else if (delta > 1.3 * avgWordTime) {\n                  errors.push('Word at charIndex ' + evt.charIndex +\n                              ' came after ' + delta.toFixed(3) +\n                              ' s, which seems too long.');\n                }\n              }\n              wordCount++;\n            }\n            lastWordTime = new Date();\n          } else if (evt.type == 'sentence') {\n            if (evt.charIndex > 0 && evt.charIndex < 62) {\n              var min = sentenceExpected[sentenceCount].min;\n              var max = sentenceExpected[sentenceCount].max;\n              if (evt.charIndex < min || evt.charIndex > max) {\n                errors.push('Got sentence at charIndex ' + evt.charIndex +\n                            ', was expecting next callback charIndex ' +\n                            'in the range ' + min + ':' + max + '.');\n              }\n              var delta = (new Date() - lastSentenceTime) / 1000;\n              if (delta < 0.75 * resultMap['Baseline']) {\n                errors.push('Sentence at charIndex ' + evt.charIndex +\n                            ' came after only ' + delta.toFixed(3) +\n                            ' s, which seems too short.');\n              } else if (delta > 1.25 * resultMap['Baseline']) {\n                errors.push('Sentence at charIndex ' + evt.charIndex +\n                            ' came after ' + delta.toFixed(3) +\n                            ' s, which seems too long.');\n              }\n              sentenceCount++;\n            }\n            lastSentenceTime = new Date();\n          } else if (evt.type == 'end') {\n            if (wordCount == 0) {\n              errors.push('Didn\\'t get any word callbacks.');\n            } else if (wordCount < wordExpected.length) {\n              errors.push('Not enough word callbacks.');\n            } else if (wordCount > wordExpected.length) {\n              errors.push('Too many word callbacks.');\n            }\n            if (sentenceCount == 0) {\n              errors.push('Didn\\'t get any sentence callbacks.');\n            } else if (sentenceCount < sentenceExpected.length) {\n              errors.push('Not enough sentence callbacks.');\n            } else if (sentenceCount > sentenceExpected.length) {\n              errors.push('Too many sentence callbacks.');\n            }\n            if (startTime == undefined) {\n              errors.push('Error: no \"start\" event received!');\n              startTime = callTime;\n            }\n            var endTime = new Date();\n            var delta = (endTime - startTime) / 1000;\n            if (delta < 2.5) {\n              errors.push('Default speech rate seems too fast.');\n            } else if (delta > 7.0) {\n              errors.push('Default speech rate seems too slow.');\n            }\n            callback(errors.length == 0, delta, errors);\n          }\n        }\n      });\n    }\n  },\n  {\n    name: 'Baseline Queueing Test',\n    description: 'Establishes a baseline time to speak a ' +\n                 'sequence of three enqueued phrases, to compare ' +\n                 'other tests against.',\n    dependencies: [],\n    trials: 3,\n    run: function(testRunName, voiceName, callback) {\n      var callTime = new Date();\n      var startTime;\n      var errors = [];\n      logSpeakCall('Alpha Alpha', {\n        voiceName: voiceName,\n        onEvent: function(evt) {\n          logEvent(callTime, testRunName, evt);\n          if (isErrorEvent(evt)) {\n            callback(false, null, []);\n          } else if (evt.type == 'start') {\n            startTime = new Date();\n          }\n        }\n      });\n      logSpeakCall('Bravo bravo.', {\n        voiceName: voiceName,\n        enqueue: true,\n        onEvent: function(evt) {\n          logEvent(callTime, testRunName, evt);\n          if (isErrorEvent(evt)) {\n            callback(false, null, []);\n          }\n        }\n      });\n      logSpeakCall('Charlie charlie', {\n        voiceName: voiceName,\n        enqueue: true,\n        onEvent: function(evt) {\n          logEvent(callTime, testRunName, evt);\n          if (isErrorEvent(evt)) {\n            callback(false, null, []);\n          } else if (evt.type == 'end') {\n            if (startTime == undefined) {\n              errors.push('Error: no \"start\" event received!');\n              startTime = callTime;\n            }\n            var endTime = new Date();\n            var delta = (endTime - startTime) / 1000;\n            callback(errors.length == 0, delta, errors);\n          }\n        }\n      });\n    }\n  },\n  {\n    name: 'Interruption with Queueing',\n    description: 'Queue a sequence of three utterances, then before they ' +\n                 'are finished, interrupt and queue a sequence of three ' +\n                 'more utterances. Make sure that interrupting and ' +\n                 'cancelling the previous utterances doesn\\'t interfere ' +\n                 'with the interrupting utterances.',\n    dependencies: ['Baseline Queueing Test'],\n    trials: 1,\n    run: function(testRunName, voiceName, callback) {\n      var callTime = new Date();\n      var startTime;\n      var errors = [];\n\n      logSpeakCall('Just when I\\'m about to say something interesting,', {\n        voiceName: voiceName\n      });\n      logSpeakCall('it seems that I always get interrupted.', {\n        voiceName: voiceName,\n        enqueue: true,\n      });\n      logSpeakCall('How rude! Will you ever let me finish?', {\n        voiceName: voiceName,\n        enqueue: true,\n      });\n\n      window.setTimeout(function() {\n        logSpeakCall('Alpha Alpha', {\n          voiceName: voiceName,\n          onEvent: function(evt) {\n            logEvent(callTime, testRunName, evt);\n            if (isErrorEvent(evt)) {\n              callback(false, null, []);\n            } else if (evt.type == 'start') {\n              startTime = new Date();\n            }\n          }\n        });\n        logSpeakCall('Bravo bravo.', {\n          voiceName: voiceName,\n          enqueue: true,\n          onEvent: function(evt) {\n            logEvent(callTime, testRunName, evt);\n            if (isErrorEvent(evt)) {\n              callback(false, null, []);\n            }\n          }\n        });\n        logSpeakCall('Charlie charlie', {\n          voiceName: voiceName,\n          enqueue: true,\n          onEvent: function(evt) {\n            logEvent(callTime, testRunName, evt);\n            if (isErrorEvent(evt)) {\n              callback(false, null, []);\n            } else if (evt.type == 'end') {\n              if (startTime == undefined) {\n                errors.push('Error: no \"start\" event received!');\n                startTime = callTime;\n              }\n              var endTime = new Date();\n              var delta = (endTime - startTime) / 1000;\n              var relative = delta / resultMap['Baseline Queueing Test'];\n              if (relative < 0.9) {\n                errors.push('Interrupting speech seems too short.');\n              } else if (relative > 1.1) {\n                errors.push('Interrupting speech seems too long.');\n              }\n              callback(errors.length == 0, delta, errors);\n            }\n          }\n        });\n      }, 4000);\n    }\n  }\n];\n\nfunction updateDependencies() {\n  for (var i = 0; i < updateDependencyFunctions.length; i++) {\n    updateDependencyFunctions[i]();\n  }\n}\n\nfunction registerTest(test) {\n  var outer = document.createElement('div');\n  outer.className = 'outer';\n  $('container').appendChild(outer);\n\n  var buttonWrap = document.createElement('div');\n  buttonWrap.className = 'buttonWrap';\n  outer.appendChild(buttonWrap);\n\n  var button = document.createElement('button');\n  button.className = 'runTestButton';\n  button.innerText = test.name;\n  buttonWrap.appendChild(button);\n\n  var busy = document.createElement('img');\n  busy.src = 'pacman.gif';\n  busy.alt = 'Busy indicator';\n  buttonWrap.appendChild(busy);\n  busy.style.visibility = 'hidden';\n\n  var description = document.createElement('div');\n  description.className = 'description';\n  description.innerHTML = test.description;\n  outer.appendChild(description);\n\n  var resultsWrap = document.createElement('div');\n  resultsWrap.className = 'results';\n  outer.appendChild(resultsWrap);\n  var results = [];\n  for (var j = 0; j < test.trials; j++) {\n    var result = document.createElement('span');\n    resultsWrap.appendChild(result);\n    results.push(result);\n  }\n  var avg = document.createElement('span');\n  resultsWrap.appendChild(avg);\n\n  var messagesWrap = document.createElement('div');\n  messagesWrap.className = 'messages';\n  outer.appendChild(messagesWrap);\n\n  var totalTime;\n  var successCount;\n\n  function finishTrials() {\n    busy.style.visibility = 'hidden';\n    if (successCount == test.trials) {\n      console.log('Test succeeded.');\n      var success = document.createElement('div');\n      success.className = 'success';\n      success.innerText = 'Test succeeded.';\n      messagesWrap.appendChild(success);\n      if (totalTime > 0.0) {\n        var avgTime = totalTime / test.trials;\n        avg.className = 'result';\n        avg.innerText = 'Avg: ' + avgTime.toFixed(3) + ' s';\n        resultMap[test.name] = avgTime;\n        updateDependencies();\n      }\n    } else {\n      console.log('Test failed.');\n      var failure = document.createElement('div');\n      failure.className = 'failure';\n      failure.innerText = 'Test failed.';\n      messagesWrap.appendChild(failure);\n    }\n  }\n\n  function runTest(index, voiceName) {\n    if (emergencyStop) {\n      busy.style.visibility = 'hidden';\n      emergencyStop = false;\n      return;\n    }\n    var testRunName = 'Test run ' + testRunIndex + ', ' +\n                      test.name + ', trial ' + (index+1) + ' of ' +\n                      test.trials;\n    console.log('*** Beginning ' + testRunName +\n                ' with voice ' + voiceName);\n    test.run(testRunName, voiceName, function(success, resultTime, errors) {\n      if (success) {\n        successCount++;\n      }\n      for (var i = 0; i < errors.length; i++) {\n        console.log(errors[i]);\n        var error = document.createElement('div');\n        error.className = 'error';\n        error.innerText = errors[i];\n        messagesWrap.appendChild(error);\n      }\n      if (resultTime != null) {\n        results[index].className = 'result';\n        results[index].innerText = resultTime.toFixed(3) + ' s';\n        totalTime += resultTime;\n      }\n      index++;\n      if (index < test.trials) {\n        runTest(index, voiceName);\n      } else {\n        finishTrials();\n      }\n    });\n  }\n\n  button.addEventListener('click', function() {\n    var voiceIndex = $('voices').selectedIndex - 1;\n    if (voiceIndex < 0) {\n      alert('Please select a voice first!');\n      return;\n    }\n    testRunIndex++;\n    busy.style.visibility = 'visible';\n    totalTime = 0.0;\n    successCount = 0;\n    messagesWrap.innerHTML = '';\n    var voiceName = voiceArray[voiceIndex].voiceName;\n    runTest(0, voiceName);\n  }, false);\n\n  updateDependencyFunctions.push(function() {\n    for (var i = 0; i < test.dependencies.length; i++) {\n      if (resultMap[test.dependencies[i]] != undefined) {\n        button.disabled = false;\n        outer.className = 'outer';\n      } else {\n        button.disabled = true;\n        outer.className = 'outer disabled';\n      }\n    }\n  });\n}\n\nfunction load() {\n  var voice = localStorage['voice'];\n  chrome.tts.getVoices(function(va) {\n    voiceArray = va;\n    for (var i = 0; i < voiceArray.length; i++) {\n      var opt = document.createElement('option');\n      var name = voiceArray[i].voiceName;\n      if (name == localStorage['voice']) {\n        opt.setAttribute('selected', '');\n      }\n      opt.setAttribute('value', name);\n      opt.innerText = voiceArray[i].voiceName;\n      $('voices').appendChild(opt);\n    }\n  });\n  $('voices').addEventListener('change', function() {\n    var i = $('voices').selectedIndex;\n    localStorage['voice'] = $('voices').item(i).value;\n  }, false);\n  $('stop').addEventListener('click', stop);\n\n  for (var i = 0; i < tests.length; i++) {\n    registerTest(tests[i]);\n  }\n  updateDependencies();\n}\n\nfunction stop() {\n  console.log('*** Emergency stop!');\n  emergencyStop = true;\n  chrome.tts.stop();\n}\n\ndocument.addEventListener('DOMContentLoaded', load);\n"
  },
  {
    "path": "_archive/mv2/extensions/ttsdemo/manifest.json",
    "content": "{\n  \"app\": {\n    \"launch\": {\n       \"local_path\": \"ttsdemo.html\"\n    }\n  },\n  \"description\": \"Demo Chrome's synthesized text-to-speech capabilities.\",\n  \"icons\": {\n    \"16\": \"16.png\",\n    \"128\": \"128.png\",\n    \"256\": \"256.png\"\n  },\n  \"minimum_chrome_version\": \"14\",\n  \"name\": \"TTS Demo\",\n  \"permissions\": [ \"tts\" ],\n  \"version\": \"2.1\",\n\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/extensions/ttsdemo/ttsdemo.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>Chrome TTS Demo</title>\n  <style>\n    body {\n      font-family: arial, helvetica, sans-serif;\n    }\n    .banner {\n      width: 100%;\n      float: left;\n    }\n    .banner_left {\n      padding: 8px;\n      float: left;\n    }\n    .banner_right {\n      padding: 8px;\n    }\n    .body_wrapper {\n      width: 100%;\n      float: left;\n    }\n    .body_left {\n      border: 0;\n      padding: 0;\n      margin: 0;\n      width: 50%;\n      float: left;\n    }\n    .body_right {\n      border: 0;\n      padding: 0;\n      margin: 0;\n      width: 46%;\n      float: left;\n    }\n    .body_inner {\n      padding: 0 32px;\n    }\n    #srctext {\n      width: 100%;\n      font-size: 133%;\n    }\n    .large_button {\n      font-size: 166%;\n      padding: 6pt 12pt 6pt 12pt;\n    }\n    .box {\n      margin: 10px;\n      padding: 10px;\n      border: 1px solid #999;\n    }\n    .tabbable {\n      padding: 10px;\n      border: 1px solid #00C;\n    }\n    table {\n      margin-left: auto;\n      margin-right: auto;\n    }\n    #help {\n      text-align: left;\n    }\n    #voiceInfo {\n      text-align: left;\n      padding: 4px;\n      border: 1px solid #aaa;\n      width: 100%;\n      min-height: 100px;\n      overflow: auto;\n    }\n  </style>\n  <script src=\"ttsdemo.js\"></script>\n</head>\n\n<body>\n\n<div class=\"banner\">\n  <div class=\"banner_left\">\n    <img src=\"128.png\" class=\"logo\" alt=\"\">\n  </div>\n  <div class=\"banner_right\">\n    <h1>Chrome Text-to-Speech Demo</h1>\n    <p>\n      Use this application to try out all of the text-to-speech voices in Chrome, or\n      <a href=\"https://chrome.google.com/webstore/search?q=tts\">Search the Chrome Web Store</a>\n      for more TTS voices.\n    </p>\n  </div>\n</div>\n\n<div class=\"body_wrapper\">\n  <div class=\"body_left\">\n    <div class=\"body_inner\">\n\n      Enter text here:\n      <textarea id=\"srctext\" rows=\"6\" cols=\"40\">This is a demo of text-to-speech in Chrome.</textarea>\n\n      <p>\n        <button class=\"large_button\" id=\"speakUserTextButton\">Speak</button>\n        <button class=\"large_button\" id=\"stopButton\">Stop</button>\n      </p>\n\n      <div class=\"box\" id=\"ttsStatusBox\">\n        TTS status: <b><span id=\"ttsStatus\"></span></b>\n      </div>\n\n      <p>\n\n        Click on or tab to these boxes:\n\n      <p>\n\n      <span tabindex=\"0\" class=\"tabbable\" id=\"speakAlpha\">Alpha</span>\n      <span tabindex=\"0\" class=\"tabbable\" id=\"speakBravo\">Bravo</span>\n      <span tabindex=\"0\" class=\"tabbable\" id=\"speakCharlie\">Charlie</span>\n      <span tabindex=\"0\" class=\"tabbable\" id=\"speakDelta\">Delta</span>\n      <span tabindex=\"0\" class=\"tabbable\" id=\"speakEcho\">Echo</span>\n      <span tabindex=\"0\" class=\"tabbable\" id=\"speakFoxtrot\">Foxtrot</span>\n\n    </div>\n  </div>\n  <div class=\"body_right\">\n    <div class=\"body_inner\">\n\n      <table class=\"simple\">\n        <tr>\n        <td>Voice:</td>\n        <td><select id=\"voices\">\n              <option value=\"\">Unspecified</option>\n            </select></td>\n        </td>\n        </tr>\n        <tr>\n        <td>Lang:</td>\n        <td><select id=\"lang\">\n          <option value=\"\">Unspecified</option>\n          <option value=\"de\">de (German)</option>\n          <option value=\"en-GB\">en-GB (British English)</option>\n          <option value=\"en-US\" selected>en-US (American English)</option>\n          <option value=\"es\">es (Spanish)</option>\n          <option value=\"fr\">fr (French)</option>\n          <option value=\"it\">it (Italian)</option>\n        </select></td></tr>\n        <tr>\n        <td>Queuing mode:</td>\n        <td><select id=\"enqueue\">\n          <option value=\"\">Interrupt</option>\n          <option value=\"true\">Enqueue</option>\n        </select></td></tr>\n        <tr>\n        <td>Rate:</td>\n        <td><input id=\"rate\" type=\"range\" min=\"0.5\" max=\"4.0\" value=\"1.0\" step=\"0.1\">\n        </td></tr>\n        <tr>\n        <td>Pitch:</td>\n        <td><input id=\"pitch\" type=\"range\" min=\"0.0\" max=\"2.0\" value=\"1.0\" step=\"0.2\">\n        </td></tr>\n        <tr>\n        <td>Volume:</td>\n        <td><input id=\"volume\" type=\"range\" min=\"0.0\" max=\"1.0\" value=\"1.0\" step=\"0.1\">\n        </td></tr>\n      </table>\n\n      <pre id=\"voiceInfo\"></pre>\n    </div>\n  </div>\n</div>\n\n</body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/extensions/ttsdemo/ttsdemo.js",
    "content": "/**\n * Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nvar text;\nvar ttsStatus;\nvar ttsStatusBox;\nvar lang;\nvar enqueue;\nvar voices;\nvar voiceInfo;\nvar voiceArray;\nvar utteranceIndex = 0;\n\nfunction load() {\n  text = document.getElementById('srctext');\n  ttsStatus = document.getElementById('ttsStatus');\n  ttsStatusBox = document.getElementById('ttsStatusBox');\n  lang = document.getElementById('lang');\n  enqueue = document.getElementById('enqueue');\n  voices = document.getElementById('voices');\n  voiceInfo = document.getElementById('voiceInfo');\n\n  document.getElementById('speakUserTextButton')\n      .addEventListener('click', speakUserText);\n  document.getElementById('stopButton')\n      .addEventListener('click', stop);\n\n  const speechOptions = [\n    { id: 'speakAlpha', text: 'Alpha' },\n    { id: 'speakBravo', text: 'Bravo' },\n    { id: 'speakCharlie', text: 'Charlie' },\n    { id: 'speakDelta', text: 'Delta' },\n    { id: 'speakEcho', text: 'Echo' },\n    { id: 'speakFoxtrot', text: 'Foxtrot' },\n  ];\n\n  for (const option of speechOptions) {\n    document.getElementById(option.id)\n        .addEventListener('focus', function(){ speak(option.text); });\n  }\n\n  chrome.tts.getVoices(function(va) {\n    voiceArray = va;\n    for (var i = 0; i < voiceArray.length; i++) {\n      var opt = document.createElement('option');\n      opt.setAttribute('value', voiceArray[i].voiceName);\n      opt.innerText = voiceArray[i].voiceName;\n      voices.appendChild(opt);\n    }\n  });\n  voices.addEventListener('change', function() {\n    var i = voices.selectedIndex - 1;\n    if (i >= 0) {\n      voiceInfo.innerText = JSON.stringify(voiceArray[i], null, 2);\n    } else {\n      voiceInfo.innerText = '';\n    }\n  }, false);\n}\n\nfunction speak(str, options, highlightText) {\n  if (!options) {\n    options = {};\n  }\n  if (enqueue.value) {\n    options.enqueue = Boolean(enqueue.value);\n  }\n  var voiceIndex = voices.selectedIndex - 1;\n  if (voiceIndex >= 0) {\n    options.voiceName = voiceArray[voiceIndex].voiceName;\n  }\n  var rateValue = Number(rate.value);\n  if (rateValue >= 0.1 && rateValue <= 10.0) {\n    options.rate = rateValue;\n  }\n  var pitchValue = Number(pitch.value);\n  if (pitchValue >= 0.0 && pitchValue <= 2.0) {\n    options.pitch = pitchValue;\n  }\n  var volumeValue = Number(volume.value);\n  if (volumeValue >= 0.0 && volumeValue <= 1.0) {\n    options.volume = volumeValue;\n  }\n  utteranceIndex++;\n  console.log(utteranceIndex + ': ' + JSON.stringify(options));\n  options.onEvent = function(event) {\n    console.log(utteranceIndex + ': ' + JSON.stringify(event));\n    if (highlightText) {\n      text.setSelectionRange(0, event.charIndex);\n    }\n    if (event.type == 'end' ||\n        event.type == 'interrupted' ||\n        event.type == 'cancelled' ||\n        event.type == 'error') {\n      chrome.tts.isSpeaking(function(isSpeaking) {\n        if (!isSpeaking) {\n          ttsStatus.innerHTML = 'Idle';\n          ttsStatusBox.style.background = '#fff';\n        }\n      });\n    }\n  };\n  chrome.tts.speak(\n      str, options, function() {\n    if (chrome.runtime.lastError) {\n      console.log('TTS Error: ' + chrome.runtime.lastError.message);\n    }\n  });\n  ttsStatus.innerHTML = 'Busy';\n  ttsStatusBox.style.background = '#ffc';\n}\n\nfunction stop() {\n  chrome.tts.stop();\n}\n\nfunction speakUserText() {\n  var options = {};\n  if (lang.value) {\n    options.lang = lang.value;\n  }\n  speak(text.value, options, true);\n}\n\ndocument.addEventListener('DOMContentLoaded', load);\n"
  },
  {
    "path": "_archive/mv2/howto/sandbox/LICENSE.handlebars",
    "content": "Copyright (C) 2011 by Yehuda Katz\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n"
  },
  {
    "path": "_archive/mv2/howto/sandbox/eventpage.html",
    "content": "<!--\n  - Copyright (c) 2012 The Chromium Authors. All rights reserved.\n  - Use of this source code is governed by a BSD-style license that can be\n  - found in the LICENSE file.\n  -->\n<!doctype html>\n<html>\n  <head>\n    <script src=\"eventpage.js\"></script>\n  </head>\n  <body>\n    <iframe id=\"theFrame\" src=\"sandbox.html\"></iframe>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/howto/sandbox/eventpage.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nchrome.browserAction.onClicked.addListener(function() {\n  var iframe = document.getElementById('theFrame');\n  var message = {\n    command: 'render',\n    context: {thing: 'world'}\n  };\n  iframe.contentWindow.postMessage(message, '*');\n});\n\n\nwindow.addEventListener('message', function(event) {\n  if (event.data.html) {\n    new Notification('Templated!', {\n      icon: 'icon.png',\n      body: 'HTML Received for \"' + event.data.name + '\": `' +\n          event.data.html + '`'\n    });\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/howto/sandbox/handlebars-1.0.0.beta.6.js",
    "content": "// Copyright (C) 2011 by Yehuda Katz\n// Licensing details in LICENSE.handlebars\n\n// lib/handlebars/base.js\nvar Handlebars = {};\n\nHandlebars.VERSION = \"1.0.beta.6\";\n\nHandlebars.helpers  = {};\nHandlebars.partials = {};\n\nHandlebars.registerHelper = function(name, fn, inverse) {\n  if(inverse) { fn.not = inverse; }\n  this.helpers[name] = fn;\n};\n\nHandlebars.registerPartial = function(name, str) {\n  this.partials[name] = str;\n};\n\nHandlebars.registerHelper('helperMissing', function(arg) {\n  if(arguments.length === 2) {\n    return undefined;\n  } else {\n    throw new Error(\"Could not find property '\" + arg + \"'\");\n  }\n});\n\nvar toString = Object.prototype.toString, functionType = \"[object Function]\";\n\nHandlebars.registerHelper('blockHelperMissing', function(context, options) {\n  var inverse = options.inverse || function() {}, fn = options.fn;\n\n\n  var ret = \"\";\n  var type = toString.call(context);\n\n  if(type === functionType) { context = context.call(this); }\n\n  if(context === true) {\n    return fn(this);\n  } else if(context === false || context == null) {\n    return inverse(this);\n  } else if(type === \"[object Array]\") {\n    if(context.length > 0) {\n      for(var i=0, j=context.length; i<j; i++) {\n        ret = ret + fn(context[i]);\n      }\n    } else {\n      ret = inverse(this);\n    }\n    return ret;\n  } else {\n    return fn(context);\n  }\n});\n\nHandlebars.registerHelper('each', function(context, options) {\n  var fn = options.fn, inverse = options.inverse;\n  var ret = \"\";\n\n  if(context && context.length > 0) {\n    for(var i=0, j=context.length; i<j; i++) {\n      ret = ret + fn(context[i]);\n    }\n  } else {\n    ret = inverse(this);\n  }\n  return ret;\n});\n\nHandlebars.registerHelper('if', function(context, options) {\n  var type = toString.call(context);\n  if(type === functionType) { context = context.call(this); }\n\n  if(!context || Handlebars.Utils.isEmpty(context)) {\n    return options.inverse(this);\n  } else {\n    return options.fn(this);\n  }\n});\n\nHandlebars.registerHelper('unless', function(context, options) {\n  var fn = options.fn, inverse = options.inverse;\n  options.fn = inverse;\n  options.inverse = fn;\n\n  return Handlebars.helpers['if'].call(this, context, options);\n});\n\nHandlebars.registerHelper('with', function(context, options) {\n  return options.fn(context);\n});\n\nHandlebars.registerHelper('log', function(context) {\n  Handlebars.log(context);\n});\n;\n// lib/handlebars/compiler/parser.js\n/* Jison generated parser */\nvar handlebars = (function(){\n\nvar parser = {trace: function trace() { },\nyy: {},\nsymbols_: {\"error\":2,\"root\":3,\"program\":4,\"EOF\":5,\"statements\":6,\"simpleInverse\":7,\"statement\":8,\"openInverse\":9,\"closeBlock\":10,\"openBlock\":11,\"mustache\":12,\"partial\":13,\"CONTENT\":14,\"COMMENT\":15,\"OPEN_BLOCK\":16,\"inMustache\":17,\"CLOSE\":18,\"OPEN_INVERSE\":19,\"OPEN_ENDBLOCK\":20,\"path\":21,\"OPEN\":22,\"OPEN_UNESCAPED\":23,\"OPEN_PARTIAL\":24,\"params\":25,\"hash\":26,\"param\":27,\"STRING\":28,\"INTEGER\":29,\"BOOLEAN\":30,\"hashSegments\":31,\"hashSegment\":32,\"ID\":33,\"EQUALS\":34,\"pathSegments\":35,\"SEP\":36,\"$accept\":0,\"$end\":1},\nterminals_: {2:\"error\",5:\"EOF\",14:\"CONTENT\",15:\"COMMENT\",16:\"OPEN_BLOCK\",18:\"CLOSE\",19:\"OPEN_INVERSE\",20:\"OPEN_ENDBLOCK\",22:\"OPEN\",23:\"OPEN_UNESCAPED\",24:\"OPEN_PARTIAL\",28:\"STRING\",29:\"INTEGER\",30:\"BOOLEAN\",33:\"ID\",34:\"EQUALS\",36:\"SEP\"},\nproductions_: [0,[3,2],[4,3],[4,1],[4,0],[6,1],[6,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,3],[13,4],[7,2],[17,3],[17,2],[17,2],[17,1],[25,2],[25,1],[27,1],[27,1],[27,1],[27,1],[26,1],[31,2],[31,1],[32,3],[32,3],[32,3],[32,3],[21,1],[35,3],[35,1]],\nperformAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {\n\nvar $0 = $$.length - 1;\nswitch (yystate) {\ncase 1: return $$[$0-1] \nbreak;\ncase 2: this.$ = new yy.ProgramNode($$[$0-2], $$[$0]) \nbreak;\ncase 3: this.$ = new yy.ProgramNode($$[$0]) \nbreak;\ncase 4: this.$ = new yy.ProgramNode([]) \nbreak;\ncase 5: this.$ = [$$[$0]] \nbreak;\ncase 6: $$[$0-1].push($$[$0]); this.$ = $$[$0-1] \nbreak;\ncase 7: this.$ = new yy.InverseNode($$[$0-2], $$[$0-1], $$[$0]) \nbreak;\ncase 8: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0]) \nbreak;\ncase 9: this.$ = $$[$0] \nbreak;\ncase 10: this.$ = $$[$0] \nbreak;\ncase 11: this.$ = new yy.ContentNode($$[$0]) \nbreak;\ncase 12: this.$ = new yy.CommentNode($$[$0]) \nbreak;\ncase 13: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) \nbreak;\ncase 14: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) \nbreak;\ncase 15: this.$ = $$[$0-1] \nbreak;\ncase 16: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) \nbreak;\ncase 17: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], true) \nbreak;\ncase 18: this.$ = new yy.PartialNode($$[$0-1]) \nbreak;\ncase 19: this.$ = new yy.PartialNode($$[$0-2], $$[$0-1]) \nbreak;\ncase 20: \nbreak;\ncase 21: this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]] \nbreak;\ncase 22: this.$ = [[$$[$0-1]].concat($$[$0]), null] \nbreak;\ncase 23: this.$ = [[$$[$0-1]], $$[$0]] \nbreak;\ncase 24: this.$ = [[$$[$0]], null] \nbreak;\ncase 25: $$[$0-1].push($$[$0]); this.$ = $$[$0-1]; \nbreak;\ncase 26: this.$ = [$$[$0]] \nbreak;\ncase 27: this.$ = $$[$0] \nbreak;\ncase 28: this.$ = new yy.StringNode($$[$0]) \nbreak;\ncase 29: this.$ = new yy.IntegerNode($$[$0]) \nbreak;\ncase 30: this.$ = new yy.BooleanNode($$[$0]) \nbreak;\ncase 31: this.$ = new yy.HashNode($$[$0]) \nbreak;\ncase 32: $$[$0-1].push($$[$0]); this.$ = $$[$0-1] \nbreak;\ncase 33: this.$ = [$$[$0]] \nbreak;\ncase 34: this.$ = [$$[$0-2], $$[$0]] \nbreak;\ncase 35: this.$ = [$$[$0-2], new yy.StringNode($$[$0])] \nbreak;\ncase 36: this.$ = [$$[$0-2], new yy.IntegerNode($$[$0])] \nbreak;\ncase 37: this.$ = [$$[$0-2], new yy.BooleanNode($$[$0])] \nbreak;\ncase 38: this.$ = new yy.IdNode($$[$0]) \nbreak;\ncase 39: $$[$0-2].push($$[$0]); this.$ = $$[$0-2]; \nbreak;\ncase 40: this.$ = [$$[$0]] \nbreak;\n}\n},\ntable: [{3:1,4:2,5:[2,4],6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{1:[3]},{5:[1,16]},{5:[2,3],7:17,8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,19],20:[2,3],22:[1,13],23:[1,14],24:[1,15]},{5:[2,5],14:[2,5],15:[2,5],16:[2,5],19:[2,5],20:[2,5],22:[2,5],23:[2,5],24:[2,5]},{4:20,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{4:21,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],24:[2,9]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],24:[2,10]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],24:[2,11]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],24:[2,12]},{17:22,21:23,33:[1,25],35:24},{17:26,21:23,33:[1,25],35:24},{17:27,21:23,33:[1,25],35:24},{17:28,21:23,33:[1,25],35:24},{21:29,33:[1,25],35:24},{1:[2,1]},{6:30,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{5:[2,6],14:[2,6],15:[2,6],16:[2,6],19:[2,6],20:[2,6],22:[2,6],23:[2,6],24:[2,6]},{17:22,18:[1,31],21:23,33:[1,25],35:24},{10:32,20:[1,33]},{10:34,20:[1,33]},{18:[1,35]},{18:[2,24],21:40,25:36,26:37,27:38,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,38],28:[2,38],29:[2,38],30:[2,38],33:[2,38],36:[1,46]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],36:[2,40]},{18:[1,47]},{18:[1,48]},{18:[1,49]},{18:[1,50],21:51,33:[1,25],35:24},{5:[2,2],8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,2],22:[1,13],23:[1,14],24:[1,15]},{14:[2,20],15:[2,20],16:[2,20],19:[2,20],22:[2,20],23:[2,20],24:[2,20]},{5:[2,7],14:[2,7],15:[2,7],16:[2,7],19:[2,7],20:[2,7],22:[2,7],23:[2,7],24:[2,7]},{21:52,33:[1,25],35:24},{5:[2,8],14:[2,8],15:[2,8],16:[2,8],19:[2,8],20:[2,8],22:[2,8],23:[2,8],24:[2,8]},{14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],24:[2,14]},{18:[2,22],21:40,26:53,27:54,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,23]},{18:[2,26],28:[2,26],29:[2,26],30:[2,26],33:[2,26]},{18:[2,31],32:55,33:[1,56]},{18:[2,27],28:[2,27],29:[2,27],30:[2,27],33:[2,27]},{18:[2,28],28:[2,28],29:[2,28],30:[2,28],33:[2,28]},{18:[2,29],28:[2,29],29:[2,29],30:[2,29],33:[2,29]},{18:[2,30],28:[2,30],29:[2,30],30:[2,30],33:[2,30]},{18:[2,33],33:[2,33]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],34:[1,57],36:[2,40]},{33:[1,58]},{14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],24:[2,13]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],24:[2,16]},{5:[2,17],14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],24:[2,17]},{5:[2,18],14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],24:[2,18]},{18:[1,59]},{18:[1,60]},{18:[2,21]},{18:[2,25],28:[2,25],29:[2,25],30:[2,25],33:[2,25]},{18:[2,32],33:[2,32]},{34:[1,57]},{21:61,28:[1,62],29:[1,63],30:[1,64],33:[1,25],35:24},{18:[2,39],28:[2,39],29:[2,39],30:[2,39],33:[2,39],36:[2,39]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],24:[2,19]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],24:[2,15]},{18:[2,34],33:[2,34]},{18:[2,35],33:[2,35]},{18:[2,36],33:[2,36]},{18:[2,37],33:[2,37]}],\ndefaultActions: {16:[2,1],37:[2,23],53:[2,21]},\nparseError: function parseError(str, hash) {\n    throw new Error(str);\n},\nparse: function parse(input) {\n    var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = \"\", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;\n    this.lexer.setInput(input);\n    this.lexer.yy = this.yy;\n    this.yy.lexer = this.lexer;\n    if (typeof this.lexer.yylloc == \"undefined\")\n        this.lexer.yylloc = {};\n    var yyloc = this.lexer.yylloc;\n    lstack.push(yyloc);\n    if (typeof this.yy.parseError === \"function\")\n        this.parseError = this.yy.parseError;\n    function popStack(n) {\n        stack.length = stack.length - 2 * n;\n        vstack.length = vstack.length - n;\n        lstack.length = lstack.length - n;\n    }\n    function lex() {\n        var token;\n        token = self.lexer.lex() || 1;\n        if (typeof token !== \"number\") {\n            token = self.symbols_[token] || token;\n        }\n        return token;\n    }\n    var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;\n    while (true) {\n        state = stack[stack.length - 1];\n        if (this.defaultActions[state]) {\n            action = this.defaultActions[state];\n        } else {\n            if (symbol == null)\n                symbol = lex();\n            action = table[state] && table[state][symbol];\n        }\n        if (typeof action === \"undefined\" || !action.length || !action[0]) {\n            if (!recovering) {\n                expected = [];\n                for (p in table[state])\n                    if (this.terminals_[p] && p > 2) {\n                        expected.push(\"'\" + this.terminals_[p] + \"'\");\n                    }\n                var errStr = \"\";\n                if (this.lexer.showPosition) {\n                    errStr = \"Parse error on line \" + (yylineno + 1) + \":\\n\" + this.lexer.showPosition() + \"\\nExpecting \" + expected.join(\", \") + \", got '\" + this.terminals_[symbol] + \"'\";\n                } else {\n                    errStr = \"Parse error on line \" + (yylineno + 1) + \": Unexpected \" + (symbol == 1?\"end of input\":\"'\" + (this.terminals_[symbol] || symbol) + \"'\");\n                }\n                this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});\n            }\n        }\n        if (action[0] instanceof Array && action.length > 1) {\n            throw new Error(\"Parse Error: multiple actions possible at state: \" + state + \", token: \" + symbol);\n        }\n        switch (action[0]) {\n        case 1:\n            stack.push(symbol);\n            vstack.push(this.lexer.yytext);\n            lstack.push(this.lexer.yylloc);\n            stack.push(action[1]);\n            symbol = null;\n            if (!preErrorSymbol) {\n                yyleng = this.lexer.yyleng;\n                yytext = this.lexer.yytext;\n                yylineno = this.lexer.yylineno;\n                yyloc = this.lexer.yylloc;\n                if (recovering > 0)\n                    recovering--;\n            } else {\n                symbol = preErrorSymbol;\n                preErrorSymbol = null;\n            }\n            break;\n        case 2:\n            len = this.productions_[action[1]][1];\n            yyval.$ = vstack[vstack.length - len];\n            yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column};\n            r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);\n            if (typeof r !== \"undefined\") {\n                return r;\n            }\n            if (len) {\n                stack = stack.slice(0, -1 * len * 2);\n                vstack = vstack.slice(0, -1 * len);\n                lstack = lstack.slice(0, -1 * len);\n            }\n            stack.push(this.productions_[action[1]][0]);\n            vstack.push(yyval.$);\n            lstack.push(yyval._$);\n            newState = table[stack[stack.length - 2]][stack[stack.length - 1]];\n            stack.push(newState);\n            break;\n        case 3:\n            return true;\n        }\n    }\n    return true;\n}\n};/* Jison generated lexer */\nvar lexer = (function(){\n\nvar lexer = ({EOF:1,\nparseError:function parseError(str, hash) {\n        if (this.yy.parseError) {\n            this.yy.parseError(str, hash);\n        } else {\n            throw new Error(str);\n        }\n    },\nsetInput:function (input) {\n        this._input = input;\n        this._more = this._less = this.done = false;\n        this.yylineno = this.yyleng = 0;\n        this.yytext = this.matched = this.match = '';\n        this.conditionStack = ['INITIAL'];\n        this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};\n        return this;\n    },\ninput:function () {\n        var ch = this._input[0];\n        this.yytext+=ch;\n        this.yyleng++;\n        this.match+=ch;\n        this.matched+=ch;\n        var lines = ch.match(/\\n/);\n        if (lines) this.yylineno++;\n        this._input = this._input.slice(1);\n        return ch;\n    },\nunput:function (ch) {\n        this._input = ch + this._input;\n        return this;\n    },\nmore:function () {\n        this._more = true;\n        return this;\n    },\npastInput:function () {\n        var past = this.matched.substr(0, this.matched.length - this.match.length);\n        return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\\n/g, \"\");\n    },\nupcomingInput:function () {\n        var next = this.match;\n        if (next.length < 20) {\n            next += this._input.substr(0, 20-next.length);\n        }\n        return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\\n/g, \"\");\n    },\nshowPosition:function () {\n        var pre = this.pastInput();\n        var c = new Array(pre.length + 1).join(\"-\");\n        return pre + this.upcomingInput() + \"\\n\" + c+\"^\";\n    },\nnext:function () {\n        if (this.done) {\n            return this.EOF;\n        }\n        if (!this._input) this.done = true;\n\n        var token,\n            match,\n            col,\n            lines;\n        if (!this._more) {\n            this.yytext = '';\n            this.match = '';\n        }\n        var rules = this._currentRules();\n        for (var i=0;i < rules.length; i++) {\n            match = this._input.match(this.rules[rules[i]]);\n            if (match) {\n                lines = match[0].match(/\\n.*/g);\n                if (lines) this.yylineno += lines.length;\n                this.yylloc = {first_line: this.yylloc.last_line,\n                               last_line: this.yylineno+1,\n                               first_column: this.yylloc.last_column,\n                               last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}\n                this.yytext += match[0];\n                this.match += match[0];\n                this.matches = match;\n                this.yyleng = this.yytext.length;\n                this._more = false;\n                this._input = this._input.slice(match[0].length);\n                this.matched += match[0];\n                token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]);\n                if (token) return token;\n                else return;\n            }\n        }\n        if (this._input === \"\") {\n            return this.EOF;\n        } else {\n            this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\\n'+this.showPosition(), \n                    {text: \"\", token: null, line: this.yylineno});\n        }\n    },\nlex:function lex() {\n        var r = this.next();\n        if (typeof r !== 'undefined') {\n            return r;\n        } else {\n            return this.lex();\n        }\n    },\nbegin:function begin(condition) {\n        this.conditionStack.push(condition);\n    },\npopState:function popState() {\n        return this.conditionStack.pop();\n    },\n_currentRules:function _currentRules() {\n        return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;\n    },\ntopState:function () {\n        return this.conditionStack[this.conditionStack.length-2];\n    },\npushState:function begin(condition) {\n        this.begin(condition);\n    }});\nlexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {\n\nvar YYSTATE=YY_START\nswitch($avoiding_name_collisions) {\ncase 0:\n                                   if(yy_.yytext.slice(-1) !== \"\\\\\") this.begin(\"mu\");\n                                   if(yy_.yytext.slice(-1) === \"\\\\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1), this.begin(\"emu\");\n                                   if(yy_.yytext) return 14;\n                                 \nbreak;\ncase 1: return 14; \nbreak;\ncase 2: this.popState(); return 14; \nbreak;\ncase 3: return 24; \nbreak;\ncase 4: return 16; \nbreak;\ncase 5: return 20; \nbreak;\ncase 6: return 19; \nbreak;\ncase 7: return 19; \nbreak;\ncase 8: return 23; \nbreak;\ncase 9: return 23; \nbreak;\ncase 10: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15; \nbreak;\ncase 11: return 22; \nbreak;\ncase 12: return 34; \nbreak;\ncase 13: return 33; \nbreak;\ncase 14: return 33; \nbreak;\ncase 15: return 36; \nbreak;\ncase 16: /*ignore whitespace*/ \nbreak;\ncase 17: this.popState(); return 18; \nbreak;\ncase 18: this.popState(); return 18; \nbreak;\ncase 19: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\\\\"/g,'\"'); return 28; \nbreak;\ncase 20: return 30; \nbreak;\ncase 21: return 30; \nbreak;\ncase 22: return 29; \nbreak;\ncase 23: return 33; \nbreak;\ncase 24: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 33; \nbreak;\ncase 25: return 'INVALID'; \nbreak;\ncase 26: return 5; \nbreak;\n}\n};\nlexer.rules = [/^[^\\x00]*?(?=(\\{\\{))/,/^[^\\x00]+/,/^[^\\x00]{2,}?(?=(\\{\\{))/,/^\\{\\{>/,/^\\{\\{#/,/^\\{\\{\\//,/^\\{\\{\\^/,/^\\{\\{\\s*else\\b/,/^\\{\\{\\{/,/^\\{\\{&/,/^\\{\\{![\\s\\S]*?\\}\\}/,/^\\{\\{/,/^=/,/^\\.(?=[} ])/,/^\\.\\./,/^[\\/.]/,/^\\s+/,/^\\}\\}\\}/,/^\\}\\}/,/^\"(\\\\[\"]|[^\"])*\"/,/^true(?=[}\\s])/,/^false(?=[}\\s])/,/^[0-9]+(?=[}\\s])/,/^[a-zA-Z0-9_$-]+(?=[=}\\s\\/.])/,/^\\[[^\\]]*\\]/,/^./,/^$/];\nlexer.conditions = {\"mu\":{\"rules\":[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],\"inclusive\":false},\"emu\":{\"rules\":[2],\"inclusive\":false},\"INITIAL\":{\"rules\":[0,1,26],\"inclusive\":true}};return lexer;})()\nparser.lexer = lexer;\nreturn parser;\n})();\nif (typeof require !== 'undefined' && typeof exports !== 'undefined') {\nexports.parser = handlebars;\nexports.parse = function () { return handlebars.parse.apply(handlebars, arguments); }\nexports.main = function commonjsMain(args) {\n    if (!args[1])\n        throw new Error('Usage: '+args[0]+' FILE');\n    if (typeof process !== 'undefined') {\n        var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), \"utf8\");\n    } else {\n        var cwd = require(\"file\").path(require(\"file\").cwd());\n        var source = cwd.join(args[1]).read({charset: \"utf-8\"});\n    }\n    return exports.parser.parse(source);\n}\nif (typeof module !== 'undefined' && require.main === module) {\n  exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require(\"system\").args);\n}\n};\n;\n// lib/handlebars/compiler/base.js\nHandlebars.Parser = handlebars;\n\nHandlebars.parse = function(string) {\n  Handlebars.Parser.yy = Handlebars.AST;\n  return Handlebars.Parser.parse(string);\n};\n\nHandlebars.print = function(ast) {\n  return new Handlebars.PrintVisitor().accept(ast);\n};\n\nHandlebars.logger = {\n  DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3,\n\n  // override in the host environment\n  log: function(level, str) {}\n};\n\nHandlebars.log = function(level, str) { Handlebars.logger.log(level, str); };\n;\n// lib/handlebars/compiler/ast.js\n(function() {\n\n  Handlebars.AST = {};\n\n  Handlebars.AST.ProgramNode = function(statements, inverse) {\n    this.type = \"program\";\n    this.statements = statements;\n    if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); }\n  };\n\n  Handlebars.AST.MustacheNode = function(params, hash, unescaped) {\n    this.type = \"mustache\";\n    this.id = params[0];\n    this.params = params.slice(1);\n    this.hash = hash;\n    this.escaped = !unescaped;\n  };\n\n  Handlebars.AST.PartialNode = function(id, context) {\n    this.type    = \"partial\";\n\n    // TODO: disallow complex IDs\n\n    this.id      = id;\n    this.context = context;\n  };\n\n  var verifyMatch = function(open, close) {\n    if(open.original !== close.original) {\n      throw new Handlebars.Exception(open.original + \" doesn't match \" + close.original);\n    }\n  };\n\n  Handlebars.AST.BlockNode = function(mustache, program, close) {\n    verifyMatch(mustache.id, close);\n    this.type = \"block\";\n    this.mustache = mustache;\n    this.program  = program;\n  };\n\n  Handlebars.AST.InverseNode = function(mustache, program, close) {\n    verifyMatch(mustache.id, close);\n    this.type = \"inverse\";\n    this.mustache = mustache;\n    this.program  = program;\n  };\n\n  Handlebars.AST.ContentNode = function(string) {\n    this.type = \"content\";\n    this.string = string;\n  };\n\n  Handlebars.AST.HashNode = function(pairs) {\n    this.type = \"hash\";\n    this.pairs = pairs;\n  };\n\n  Handlebars.AST.IdNode = function(parts) {\n    this.type = \"ID\";\n    this.original = parts.join(\".\");\n\n    var dig = [], depth = 0;\n\n    for(var i=0,l=parts.length; i<l; i++) {\n      var part = parts[i];\n\n      if(part === \"..\") { depth++; }\n      else if(part === \".\" || part === \"this\") { this.isScoped = true; }\n      else { dig.push(part); }\n    }\n\n    this.parts    = dig;\n    this.string   = dig.join('.');\n    this.depth    = depth;\n    this.isSimple = (dig.length === 1) && (depth === 0);\n  };\n\n  Handlebars.AST.StringNode = function(string) {\n    this.type = \"STRING\";\n    this.string = string;\n  };\n\n  Handlebars.AST.IntegerNode = function(integer) {\n    this.type = \"INTEGER\";\n    this.integer = integer;\n  };\n\n  Handlebars.AST.BooleanNode = function(bool) {\n    this.type = \"BOOLEAN\";\n    this.bool = bool;\n  };\n\n  Handlebars.AST.CommentNode = function(comment) {\n    this.type = \"comment\";\n    this.comment = comment;\n  };\n\n})();;\n// lib/handlebars/utils.js\nHandlebars.Exception = function(message) {\n  var tmp = Error.prototype.constructor.apply(this, arguments);\n\n  for (var p in tmp) {\n    if (tmp.hasOwnProperty(p)) { this[p] = tmp[p]; }\n  }\n\n  this.message = tmp.message;\n};\nHandlebars.Exception.prototype = new Error;\n\n// Build out our basic SafeString type\nHandlebars.SafeString = function(string) {\n  this.string = string;\n};\nHandlebars.SafeString.prototype.toString = function() {\n  return this.string.toString();\n};\n\n(function() {\n  var escape = {\n    \"<\": \"&lt;\",\n    \">\": \"&gt;\",\n    '\"': \"&quot;\",\n    \"'\": \"&#x27;\",\n    \"`\": \"&#x60;\"\n  };\n\n  var badChars = /&(?!\\w+;)|[<>\"'`]/g;\n  var possible = /[&<>\"'`]/;\n\n  var escapeChar = function(chr) {\n    return escape[chr] || \"&amp;\";\n  };\n\n  Handlebars.Utils = {\n    escapeExpression: function(string) {\n      // don't escape SafeStrings, since they're already safe\n      if (string instanceof Handlebars.SafeString) {\n        return string.toString();\n      } else if (string == null || string === false) {\n        return \"\";\n      }\n\n      if(!possible.test(string)) { return string; }\n      return string.replace(badChars, escapeChar);\n    },\n\n    isEmpty: function(value) {\n      if (typeof value === \"undefined\") {\n        return true;\n      } else if (value === null) {\n        return true;\n      } else if (value === false) {\n        return true;\n      } else if(Object.prototype.toString.call(value) === \"[object Array]\" && value.length === 0) {\n        return true;\n      } else {\n        return false;\n      }\n    }\n  };\n})();;\n// lib/handlebars/compiler/compiler.js\nHandlebars.Compiler = function() {};\nHandlebars.JavaScriptCompiler = function() {};\n\n(function(Compiler, JavaScriptCompiler) {\n  Compiler.OPCODE_MAP = {\n    appendContent: 1,\n    getContext: 2,\n    lookupWithHelpers: 3,\n    lookup: 4,\n    append: 5,\n    invokeMustache: 6,\n    appendEscaped: 7,\n    pushString: 8,\n    truthyOrFallback: 9,\n    functionOrFallback: 10,\n    invokeProgram: 11,\n    invokePartial: 12,\n    push: 13,\n    assignToHash: 15,\n    pushStringParam: 16\n  };\n\n  Compiler.MULTI_PARAM_OPCODES = {\n    appendContent: 1,\n    getContext: 1,\n    lookupWithHelpers: 2,\n    lookup: 1,\n    invokeMustache: 3,\n    pushString: 1,\n    truthyOrFallback: 1,\n    functionOrFallback: 1,\n    invokeProgram: 3,\n    invokePartial: 1,\n    push: 1,\n    assignToHash: 1,\n    pushStringParam: 1\n  };\n\n  Compiler.DISASSEMBLE_MAP = {};\n\n  for(var prop in Compiler.OPCODE_MAP) {\n    var value = Compiler.OPCODE_MAP[prop];\n    Compiler.DISASSEMBLE_MAP[value] = prop;\n  }\n\n  Compiler.multiParamSize = function(code) {\n    return Compiler.MULTI_PARAM_OPCODES[Compiler.DISASSEMBLE_MAP[code]];\n  };\n\n  Compiler.prototype = {\n    compiler: Compiler,\n\n    disassemble: function() {\n      var opcodes = this.opcodes, opcode, nextCode;\n      var out = [], str, name, value;\n\n      for(var i=0, l=opcodes.length; i<l; i++) {\n        opcode = opcodes[i];\n\n        if(opcode === 'DECLARE') {\n          name = opcodes[++i];\n          value = opcodes[++i];\n          out.push(\"DECLARE \" + name + \" = \" + value);\n        } else {\n          str = Compiler.DISASSEMBLE_MAP[opcode];\n\n          var extraParams = Compiler.multiParamSize(opcode);\n          var codes = [];\n\n          for(var j=0; j<extraParams; j++) {\n            nextCode = opcodes[++i];\n\n            if(typeof nextCode === \"string\") {\n              nextCode = \"\\\"\" + nextCode.replace(\"\\n\", \"\\\\n\") + \"\\\"\";\n            }\n\n            codes.push(nextCode);\n          }\n\n          str = str + \" \" + codes.join(\" \");\n\n          out.push(str);\n        }\n      }\n\n      return out.join(\"\\n\");\n    },\n\n    guid: 0,\n\n    compile: function(program, options) {\n      this.children = [];\n      this.depths = {list: []};\n      this.options = options;\n\n      // These changes will propagate to the other compiler components\n      var knownHelpers = this.options.knownHelpers;\n      this.options.knownHelpers = {\n        'helperMissing': true,\n        'blockHelperMissing': true,\n        'each': true,\n        'if': true,\n        'unless': true,\n        'with': true,\n        'log': true\n      };\n      if (knownHelpers) {\n        for (var name in knownHelpers) {\n          this.options.knownHelpers[name] = knownHelpers[name];\n        }\n      }\n\n      return this.program(program);\n    },\n\n    accept: function(node) {\n      return this[node.type](node);\n    },\n\n    program: function(program) {\n      var statements = program.statements, statement;\n      this.opcodes = [];\n\n      for(var i=0, l=statements.length; i<l; i++) {\n        statement = statements[i];\n        this[statement.type](statement);\n      }\n      this.isSimple = l === 1;\n\n      this.depths.list = this.depths.list.sort(function(a, b) {\n        return a - b;\n      });\n\n      return this;\n    },\n\n    compileProgram: function(program) {\n      var result = new this.compiler().compile(program, this.options);\n      var guid = this.guid++;\n\n      this.usePartial = this.usePartial || result.usePartial;\n\n      this.children[guid] = result;\n\n      for(var i=0, l=result.depths.list.length; i<l; i++) {\n        depth = result.depths.list[i];\n\n        if(depth < 2) { continue; }\n        else { this.addDepth(depth - 1); }\n      }\n\n      return guid;\n    },\n\n    block: function(block) {\n      var mustache = block.mustache;\n      var depth, child, inverse, inverseGuid;\n\n      var params = this.setupStackForMustache(mustache);\n\n      var programGuid = this.compileProgram(block.program);\n\n      if(block.program.inverse) {\n        inverseGuid = this.compileProgram(block.program.inverse);\n        this.declare('inverse', inverseGuid);\n      }\n\n      this.opcode('invokeProgram', programGuid, params.length, !!mustache.hash);\n      this.declare('inverse', null);\n      this.opcode('append');\n    },\n\n    inverse: function(block) {\n      var params = this.setupStackForMustache(block.mustache);\n\n      var programGuid = this.compileProgram(block.program);\n\n      this.declare('inverse', programGuid);\n\n      this.opcode('invokeProgram', null, params.length, !!block.mustache.hash);\n      this.declare('inverse', null);\n      this.opcode('append');\n    },\n\n    hash: function(hash) {\n      var pairs = hash.pairs, pair, val;\n\n      this.opcode('push', '{}');\n\n      for(var i=0, l=pairs.length; i<l; i++) {\n        pair = pairs[i];\n        val  = pair[1];\n\n        this.accept(val);\n        this.opcode('assignToHash', pair[0]);\n      }\n    },\n\n    partial: function(partial) {\n      var id = partial.id;\n      this.usePartial = true;\n\n      if(partial.context) {\n        this.ID(partial.context);\n      } else {\n        this.opcode('push', 'depth0');\n      }\n\n      this.opcode('invokePartial', id.original);\n      this.opcode('append');\n    },\n\n    content: function(content) {\n      this.opcode('appendContent', content.string);\n    },\n\n    mustache: function(mustache) {\n      var params = this.setupStackForMustache(mustache);\n\n      this.opcode('invokeMustache', params.length, mustache.id.original, !!mustache.hash);\n\n      if(mustache.escaped && !this.options.noEscape) {\n        this.opcode('appendEscaped');\n      } else {\n        this.opcode('append');\n      }\n    },\n\n    ID: function(id) {\n      this.addDepth(id.depth);\n\n      this.opcode('getContext', id.depth);\n\n      this.opcode('lookupWithHelpers', id.parts[0] || null, id.isScoped || false);\n\n      for(var i=1, l=id.parts.length; i<l; i++) {\n        this.opcode('lookup', id.parts[i]);\n      }\n    },\n\n    STRING: function(string) {\n      this.opcode('pushString', string.string);\n    },\n\n    INTEGER: function(integer) {\n      this.opcode('push', integer.integer);\n    },\n\n    BOOLEAN: function(bool) {\n      this.opcode('push', bool.bool);\n    },\n\n    comment: function() {},\n\n    // HELPERS\n    pushParams: function(params) {\n      var i = params.length, param;\n\n      while(i--) {\n        param = params[i];\n\n        if(this.options.stringParams) {\n          if(param.depth) {\n            this.addDepth(param.depth);\n          }\n\n          this.opcode('getContext', param.depth || 0);\n          this.opcode('pushStringParam', param.string);\n        } else {\n          this[param.type](param);\n        }\n      }\n    },\n\n    opcode: function(name, val1, val2, val3) {\n      this.opcodes.push(Compiler.OPCODE_MAP[name]);\n      if(val1 !== undefined) { this.opcodes.push(val1); }\n      if(val2 !== undefined) { this.opcodes.push(val2); }\n      if(val3 !== undefined) { this.opcodes.push(val3); }\n    },\n\n    declare: function(name, value) {\n      this.opcodes.push('DECLARE');\n      this.opcodes.push(name);\n      this.opcodes.push(value);\n    },\n\n    addDepth: function(depth) {\n      if(depth === 0) { return; }\n\n      if(!this.depths[depth]) {\n        this.depths[depth] = true;\n        this.depths.list.push(depth);\n      }\n    },\n\n    setupStackForMustache: function(mustache) {\n      var params = mustache.params;\n\n      this.pushParams(params);\n\n      if(mustache.hash) {\n        this.hash(mustache.hash);\n      }\n\n      this.ID(mustache.id);\n\n      return params;\n    }\n  };\n\n  JavaScriptCompiler.prototype = {\n    // PUBLIC API: You can override these methods in a subclass to provide\n    // alternative compiled forms for name lookup and buffering semantics\n    nameLookup: function(parent, name, type) {\n      if (/^[0-9]+$/.test(name)) {\n        return parent + \"[\" + name + \"]\";\n      } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {\n        return parent + \".\" + name;\n      }\n      else {\n        return parent + \"['\" + name + \"']\";\n      }\n    },\n\n    appendToBuffer: function(string) {\n      if (this.environment.isSimple) {\n        return \"return \" + string + \";\";\n      } else {\n        return \"buffer += \" + string + \";\";\n      }\n    },\n\n    initializeBuffer: function() {\n      return this.quotedString(\"\");\n    },\n\n    namespace: \"Handlebars\",\n    // END PUBLIC API\n\n    compile: function(environment, options, context, asObject) {\n      this.environment = environment;\n      this.options = options || {};\n\n      this.name = this.environment.name;\n      this.isChild = !!context;\n      this.context = context || {\n        programs: [],\n        aliases: { self: 'this' },\n        registers: {list: []}\n      };\n\n      this.preamble();\n\n      this.stackSlot = 0;\n      this.stackVars = [];\n\n      this.compileChildren(environment, options);\n\n      var opcodes = environment.opcodes, opcode;\n\n      this.i = 0;\n\n      for(l=opcodes.length; this.i<l; this.i++) {\n        opcode = this.nextOpcode(0);\n\n        if(opcode[0] === 'DECLARE') {\n          this.i = this.i + 2;\n          this[opcode[1]] = opcode[2];\n        } else {\n          this.i = this.i + opcode[1].length;\n          this[opcode[0]].apply(this, opcode[1]);\n        }\n      }\n\n      return this.createFunctionContext(asObject);\n    },\n\n    nextOpcode: function(n) {\n      var opcodes = this.environment.opcodes, opcode = opcodes[this.i + n], name, val;\n      var extraParams, codes;\n\n      if(opcode === 'DECLARE') {\n        name = opcodes[this.i + 1];\n        val  = opcodes[this.i + 2];\n        return ['DECLARE', name, val];\n      } else {\n        name = Compiler.DISASSEMBLE_MAP[opcode];\n\n        extraParams = Compiler.multiParamSize(opcode);\n        codes = [];\n\n        for(var j=0; j<extraParams; j++) {\n          codes.push(opcodes[this.i + j + 1 + n]);\n        }\n\n        return [name, codes];\n      }\n    },\n\n    eat: function(opcode) {\n      this.i = this.i + opcode.length;\n    },\n\n    preamble: function() {\n      var out = [];\n\n      // this register will disambiguate helper lookup from finding a function in\n      // a context. This is necessary for mustache compatibility, which requires\n      // that context functions in blocks are evaluated by blockHelperMissing, and\n      // then proceed as if the resulting value was provided to blockHelperMissing.\n      this.useRegister('foundHelper');\n\n      if (!this.isChild) {\n        var namespace = this.namespace;\n        var copies = \"helpers = helpers || \" + namespace + \".helpers;\";\n        if(this.environment.usePartial) { copies = copies + \" partials = partials || \" + namespace + \".partials;\"; }\n        out.push(copies);\n      } else {\n        out.push('');\n      }\n\n      if (!this.environment.isSimple) {\n        out.push(\", buffer = \" + this.initializeBuffer());\n      } else {\n        out.push(\"\");\n      }\n\n      // track the last context pushed into place to allow skipping the\n      // getContext opcode when it would be a noop\n      this.lastContext = 0;\n      this.source = out;\n    },\n\n    createFunctionContext: function(asObject) {\n      var locals = this.stackVars;\n      if (!this.isChild) {\n        locals = locals.concat(this.context.registers.list);\n      }\n\n      if(locals.length > 0) {\n        this.source[1] = this.source[1] + \", \" + locals.join(\", \");\n      }\n\n      // Generate minimizer alias mappings\n      if (!this.isChild) {\n        var aliases = []\n        for (var alias in this.context.aliases) {\n          this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];\n        }\n      }\n\n      if (this.source[1]) {\n        this.source[1] = \"var \" + this.source[1].substring(2) + \";\";\n      }\n\n      // Merge children\n      if (!this.isChild) {\n        this.source[1] += '\\n' + this.context.programs.join('\\n') + '\\n';\n      }\n\n      if (!this.environment.isSimple) {\n        this.source.push(\"return buffer;\");\n      }\n\n      var params = this.isChild ? [\"depth0\", \"data\"] : [\"Handlebars\", \"depth0\", \"helpers\", \"partials\", \"data\"];\n\n      for(var i=0, l=this.environment.depths.list.length; i<l; i++) {\n        params.push(\"depth\" + this.environment.depths.list[i]);\n      }\n\n      if (asObject) {\n        params.push(this.source.join(\"\\n  \"));\n\n        return Function.apply(this, params);\n      } else {\n        var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\\n  ' + this.source.join(\"\\n  \") + '}';\n        Handlebars.log(Handlebars.logger.DEBUG, functionSource + \"\\n\\n\");\n        return functionSource;\n      }\n    },\n\n    appendContent: function(content) {\n      this.source.push(this.appendToBuffer(this.quotedString(content)));\n    },\n\n    append: function() {\n      var local = this.popStack();\n      this.source.push(\"if(\" + local + \" || \" + local + \" === 0) { \" + this.appendToBuffer(local) + \" }\");\n      if (this.environment.isSimple) {\n        this.source.push(\"else { \" + this.appendToBuffer(\"''\") + \" }\");\n      }\n    },\n\n    appendEscaped: function() {\n      var opcode = this.nextOpcode(1), extra = \"\";\n      this.context.aliases.escapeExpression = 'this.escapeExpression';\n\n      if(opcode[0] === 'appendContent') {\n        extra = \" + \" + this.quotedString(opcode[1][0]);\n        this.eat(opcode);\n      }\n\n      this.source.push(this.appendToBuffer(\"escapeExpression(\" + this.popStack() + \")\" + extra));\n    },\n\n    getContext: function(depth) {\n      if(this.lastContext !== depth) {\n        this.lastContext = depth;\n      }\n    },\n\n    lookupWithHelpers: function(name, isScoped) {\n      if(name) {\n        var topStack = this.nextStack();\n\n        this.usingKnownHelper = false;\n\n        var toPush;\n        if (!isScoped && this.options.knownHelpers[name]) {\n          toPush = topStack + \" = \" + this.nameLookup('helpers', name, 'helper');\n          this.usingKnownHelper = true;\n        } else if (isScoped || this.options.knownHelpersOnly) {\n          toPush = topStack + \" = \" + this.nameLookup('depth' + this.lastContext, name, 'context');\n        } else {\n          this.register('foundHelper', this.nameLookup('helpers', name, 'helper'));\n          toPush = topStack + \" = foundHelper || \" + this.nameLookup('depth' + this.lastContext, name, 'context');\n        }\n\n        toPush += ';';\n        this.source.push(toPush);\n      } else {\n        this.pushStack('depth' + this.lastContext);\n      }\n    },\n\n    lookup: function(name) {\n      var topStack = this.topStack();\n      this.source.push(topStack + \" = (\" + topStack + \" === null || \" + topStack + \" === undefined || \" + topStack + \" === false ? \" +\n        topStack + \" : \" + this.nameLookup(topStack, name, 'context') + \");\");\n    },\n\n    pushStringParam: function(string) {\n      this.pushStack('depth' + this.lastContext);\n      this.pushString(string);\n    },\n\n    pushString: function(string) {\n      this.pushStack(this.quotedString(string));\n    },\n\n    push: function(name) {\n      this.pushStack(name);\n    },\n\n    invokeMustache: function(paramSize, original, hasHash) {\n      this.populateParams(paramSize, this.quotedString(original), \"{}\", null, hasHash, function(nextStack, helperMissingString, id) {\n        if (!this.usingKnownHelper) {\n          this.context.aliases.helperMissing = 'helpers.helperMissing';\n          this.context.aliases.undef = 'void 0';\n          this.source.push(\"else if(\" + id + \"=== undef) { \" + nextStack + \" = helperMissing.call(\" + helperMissingString + \"); }\");\n          if (nextStack !== id) {\n            this.source.push(\"else { \" + nextStack + \" = \" + id + \"; }\");\n          }\n        }\n      });\n    },\n\n    invokeProgram: function(guid, paramSize, hasHash) {\n      var inverse = this.programExpression(this.inverse);\n      var mainProgram = this.programExpression(guid);\n\n      this.populateParams(paramSize, null, mainProgram, inverse, hasHash, function(nextStack, helperMissingString, id) {\n        if (!this.usingKnownHelper) {\n          this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';\n          this.source.push(\"else { \" + nextStack + \" = blockHelperMissing.call(\" + helperMissingString + \"); }\");\n        }\n      });\n    },\n\n    populateParams: function(paramSize, helperId, program, inverse, hasHash, fn) {\n      var needsRegister = hasHash || this.options.stringParams || inverse || this.options.data;\n      var id = this.popStack(), nextStack;\n      var params = [], param, stringParam, stringOptions;\n\n      if (needsRegister) {\n        this.register('tmp1', program);\n        stringOptions = 'tmp1';\n      } else {\n        stringOptions = '{ hash: {} }';\n      }\n\n      if (needsRegister) {\n        var hash = (hasHash ? this.popStack() : '{}');\n        this.source.push('tmp1.hash = ' + hash + ';');\n      }\n\n      if(this.options.stringParams) {\n        this.source.push('tmp1.contexts = [];');\n      }\n\n      for(var i=0; i<paramSize; i++) {\n        param = this.popStack();\n        params.push(param);\n\n        if(this.options.stringParams) {\n          this.source.push('tmp1.contexts.push(' + this.popStack() + ');');\n        }\n      }\n\n      if(inverse) {\n        this.source.push('tmp1.fn = tmp1;');\n        this.source.push('tmp1.inverse = ' + inverse + ';');\n      }\n\n      if(this.options.data) {\n        this.source.push('tmp1.data = data;');\n      }\n\n      params.push(stringOptions);\n\n      this.populateCall(params, id, helperId || id, fn, program !== '{}');\n    },\n\n    populateCall: function(params, id, helperId, fn, program) {\n      var paramString = [\"depth0\"].concat(params).join(\", \");\n      var helperMissingString = [\"depth0\"].concat(helperId).concat(params).join(\", \");\n\n      var nextStack = this.nextStack();\n\n      if (this.usingKnownHelper) {\n        this.source.push(nextStack + \" = \" + id + \".call(\" + paramString + \");\");\n      } else {\n        this.context.aliases.functionType = '\"function\"';\n        var condition = program ? \"foundHelper && \" : \"\"\n        this.source.push(\"if(\" + condition + \"typeof \" + id + \" === functionType) { \" + nextStack + \" = \" + id + \".call(\" + paramString + \"); }\");\n      }\n      fn.call(this, nextStack, helperMissingString, id);\n      this.usingKnownHelper = false;\n    },\n\n    invokePartial: function(context) {\n      params = [this.nameLookup('partials', context, 'partial'), \"'\" + context + \"'\", this.popStack(), \"helpers\", \"partials\"];\n\n      if (this.options.data) {\n        params.push(\"data\");\n      }\n\n      this.pushStack(\"self.invokePartial(\" + params.join(\", \") + \");\");\n    },\n\n    assignToHash: function(key) {\n      var value = this.popStack();\n      var hash = this.topStack();\n\n      this.source.push(hash + \"['\" + key + \"'] = \" + value + \";\");\n    },\n\n    // HELPERS\n\n    compiler: JavaScriptCompiler,\n\n    compileChildren: function(environment, options) {\n      var children = environment.children, child, compiler;\n\n      for(var i=0, l=children.length; i<l; i++) {\n        child = children[i];\n        compiler = new this.compiler();\n\n        this.context.programs.push('');     // Placeholder to prevent name conflicts for nested children\n        var index = this.context.programs.length;\n        child.index = index;\n        child.name = 'program' + index;\n        this.context.programs[index] = compiler.compile(child, options, this.context);\n      }\n    },\n\n    programExpression: function(guid) {\n      if(guid == null) { return \"self.noop\"; }\n\n      var child = this.environment.children[guid],\n          depths = child.depths.list;\n      var programParams = [child.index, child.name, \"data\"];\n\n      for(var i=0, l = depths.length; i<l; i++) {\n        depth = depths[i];\n\n        if(depth === 1) { programParams.push(\"depth0\"); }\n        else { programParams.push(\"depth\" + (depth - 1)); }\n      }\n\n      if(depths.length === 0) {\n        return \"self.program(\" + programParams.join(\", \") + \")\";\n      } else {\n        programParams.shift();\n        return \"self.programWithDepth(\" + programParams.join(\", \") + \")\";\n      }\n    },\n\n    register: function(name, val) {\n      this.useRegister(name);\n      this.source.push(name + \" = \" + val + \";\");\n    },\n\n    useRegister: function(name) {\n      if(!this.context.registers[name]) {\n        this.context.registers[name] = true;\n        this.context.registers.list.push(name);\n      }\n    },\n\n    pushStack: function(item) {\n      this.source.push(this.nextStack() + \" = \" + item + \";\");\n      return \"stack\" + this.stackSlot;\n    },\n\n    nextStack: function() {\n      this.stackSlot++;\n      if(this.stackSlot > this.stackVars.length) { this.stackVars.push(\"stack\" + this.stackSlot); }\n      return \"stack\" + this.stackSlot;\n    },\n\n    popStack: function() {\n      return \"stack\" + this.stackSlot--;\n    },\n\n    topStack: function() {\n      return \"stack\" + this.stackSlot;\n    },\n\n    quotedString: function(str) {\n      return '\"' + str\n        .replace(/\\\\/g, '\\\\\\\\')\n        .replace(/\"/g, '\\\\\"')\n        .replace(/\\n/g, '\\\\n')\n        .replace(/\\r/g, '\\\\r') + '\"';\n    }\n  };\n\n  var reservedWords = (\n    \"break else new var\" +\n    \" case finally return void\" +\n    \" catch for switch while\" +\n    \" continue function this with\" +\n    \" default if throw\" +\n    \" delete in try\" +\n    \" do instanceof typeof\" +\n    \" abstract enum int short\" +\n    \" boolean export interface static\" +\n    \" byte extends long super\" +\n    \" char final native synchronized\" +\n    \" class float package throws\" +\n    \" const goto private transient\" +\n    \" debugger implements protected volatile\" +\n    \" double import public let yield\"\n  ).split(\" \");\n\n  var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};\n\n  for(var i=0, l=reservedWords.length; i<l; i++) {\n    compilerWords[reservedWords[i]] = true;\n  }\n\n  JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {\n    if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) {\n      return true;\n    }\n    return false;\n  }\n\n})(Handlebars.Compiler, Handlebars.JavaScriptCompiler);\n\nHandlebars.precompile = function(string, options) {\n  options = options || {};\n\n  var ast = Handlebars.parse(string);\n  var environment = new Handlebars.Compiler().compile(ast, options);\n  return new Handlebars.JavaScriptCompiler().compile(environment, options);\n};\n\nHandlebars.compile = function(string, options) {\n  options = options || {};\n\n  var compiled;\n  function compile() {\n    var ast = Handlebars.parse(string);\n    var environment = new Handlebars.Compiler().compile(ast, options);\n    var templateSpec = new Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);\n    return Handlebars.template(templateSpec);\n  }\n\n  // Template is only compiled on first use and cached after that point.\n  return function(context, options) {\n    if (!compiled) {\n      compiled = compile();\n    }\n    return compiled.call(this, context, options);\n  };\n};\n;\n// lib/handlebars/runtime.js\nHandlebars.VM = {\n  template: function(templateSpec) {\n    // Just add water\n    var container = {\n      escapeExpression: Handlebars.Utils.escapeExpression,\n      invokePartial: Handlebars.VM.invokePartial,\n      programs: [],\n      program: function(i, fn, data) {\n        var programWrapper = this.programs[i];\n        if(data) {\n          return Handlebars.VM.program(fn, data);\n        } else if(programWrapper) {\n          return programWrapper;\n        } else {\n          programWrapper = this.programs[i] = Handlebars.VM.program(fn);\n          return programWrapper;\n        }\n      },\n      programWithDepth: Handlebars.VM.programWithDepth,\n      noop: Handlebars.VM.noop\n    };\n\n    return function(context, options) {\n      options = options || {};\n      return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);\n    };\n  },\n\n  programWithDepth: function(fn, data, $depth) {\n    var args = Array.prototype.slice.call(arguments, 2);\n\n    return function(context, options) {\n      options = options || {};\n\n      return fn.apply(this, [context, options.data || data].concat(args));\n    };\n  },\n  program: function(fn, data) {\n    return function(context, options) {\n      options = options || {};\n\n      return fn(context, options.data || data);\n    };\n  },\n  noop: function() { return \"\"; },\n  invokePartial: function(partial, name, context, helpers, partials, data) {\n    options = { helpers: helpers, partials: partials, data: data };\n\n    if(partial === undefined) {\n      throw new Handlebars.Exception(\"The partial \" + name + \" could not be found\");\n    } else if(partial instanceof Function) {\n      return partial(context, options);\n    } else if (!Handlebars.compile) {\n      throw new Handlebars.Exception(\"The partial \" + name + \" could not be compiled when running in runtime-only mode\");\n    } else {\n      partials[name] = Handlebars.compile(partial);\n      return partials[name](context, options);\n    }\n  }\n};\n\nHandlebars.template = Handlebars.VM.template;\n;\n"
  },
  {
    "path": "_archive/mv2/howto/sandbox/manifest.json",
    "content": "{\n  \"name\": \"Sandboxed Frame\",\n  \"description\": \"Demonstrate use of handlebars inside a sandboxed frame\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 2,\n  \"permissions\": [\"notifications\"],\n  \"background\": {\n    \"page\": \"eventpage.html\",\n    \"persistent\": false\n  },\n  \"browser_action\": {\n    \"default_icon\" : \"icon.png\",\n    \"default_title\": \"Start Event Page\"\n  },\n  \"sandbox\": {\n    \"pages\": [\"sandbox.html\"]\n  },\n  \"web_accessible_resources\": [\"icon.png\"]\n}\n"
  },
  {
    "path": "_archive/mv2/howto/sandbox/sandbox.html",
    "content": "<!--\n  - Copyright (c) 2012 The Chromium Authors. All rights reserved.\n  - Use of this source code is governed by a BSD-style license that can be\n  - found in the LICENSE file.\n  -->\n<!doctype html>\n<html>\n  <head>\n    <script src=\"handlebars-1.0.0.beta.6.js\"></script>\n  </head>\n  <body>\n    <script id=\"hello-world-template\" type=\"text/x-handlebars-template\">\n      <div class=\"entry\">\n        <h1>Hello, {{thing}}!</h1>\n      </div>\n    </script>\n    <script>\n      var templates = [];\n      var source = document.getElementById('hello-world-template').innerHTML;\n      templates['hello'] = Handlebars.compile(source);\n\n      // Set up message event handler:\n      window.addEventListener('message', function(event) {\n        var command = event.data.command;\n        var name = event.data.name || 'hello';\n        switch(command) {\n          case 'render':\n            event.source.postMessage({\n              name: name,\n              html: templates[name](event.data.context)\n            }, event.origin);\n            break;\n\n          // You could imagine additional functionality. For instance:\n          //\n          // case 'new':\n          //   templates[event.data.name] = Handlebars.compile(event.data.source);\n          //   event.source.postMessage({name: name, success: true}, event.origin);\n          //   break;\n        }\n      });\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/howto/tab_shortcuts/manifest.json",
    "content": "{\n  \"name\": \"Tab Shortcuts\",\n  \"version\": \"1.0\",\n  \"description\": \"Allows pinning and duplication of tabs via keyboard shortcuts.\",\n  \"manifest_version\": 2,\n  \"background\": {\n    \"scripts\": [\"tab_shortcuts.js\"],\n    \"persistent\": false\n  },\n  \"commands\": {\n    \"toggle-pin-tab\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+Shift+X\",\n        \"mac\": \"Command+Shift+X\"\n      },\n      \"description\": \"Toggles whether the current tab is pinned.\"\n    },\n    \"duplicate-tab\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+Shift+Z\",\n        \"mac\": \"Command+Shift+Z\"\n      },\n      \"description\": \"Duplicates the current tab.\"\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/howto/tab_shortcuts/tab_shortcuts.js",
    "content": "// Copyright (c) 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * Register a callback function with the commands api, which will be called when\n * one of our registered commands is detected.\n */\nchrome.commands.onCommand.addListener(function(command) {\n  // Call 'update' with an empty properties object to get access to the current\n  // tab (given to us in the callback function).\n  chrome.tabs.update({}, function(tab) {\n    if (command == 'toggle-pin-tab')\n      chrome.tabs.update({pinned: !tab.pinned});\n    else if (command == 'duplicate-tab')\n      chrome.tabs.duplicate(tab.id);\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/readme.md",
    "content": "# Chrome Extensions samples (Manifest v2)\n\nOfficial samples for Chrome Extensions and the Chrome Apps platform.\nNote that Chrome Apps are deprecated—learn more [on the Chromium blog](https://blog.chromium.org/2020/08/changes-to-chrome-app-support-timeline.html).\n\nFor more information on extensions, see [Chrome Developers](https://developer.chrome.com).\n\n## Samples\n\nThe directory structure is as follows:\n\n* api/ - extensions focused on a single API package\n* howto/ - extensions that show how to perform a particular task\n* tutorials/ - multi-step walkthroughs referenced inline in the docs\n* extensions/ - full featured extensions spanning multiple API packages\n\nTo experiment with these samples, please clone this repo and use 'Load Unpacked Extension'.\nRead more on [Getting Started](https://developer.chrome.com/extensions/getstarted).\n\nSample | Calls\n--- | ---\n[My Bookmarks](api/bookmarks/basic)<br />A browser action with a popup dump of all bookmarks, including search, add, edit and delete. | <ul><li>bookmarks.create</li><li>bookmarks.getTree</li><li>bookmarks.remove</li><li>bookmarks.update</li><li>tabs.create</li></ul>\n[Page Redder](api/browserAction/make_page_red)<br />Make the current page red | <ul><li>browserAction.onClicked</li><li>tabs.executeScript</li></ul>\n[Print this page](api/browserAction/print)<br />Adds a print button to the browser. | <ul><li>browserAction.onClicked</li><li>tabs.executeScript</li></ul>\n[A browser action which changes its icon when clicked](api/browserAction/set_icon_path)<br />Click browser action icon to change color! | <ul><li>browserAction.onClicked</li><li>browserAction.setIcon</li><li>runtime.onInstalled</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li></ul>\n[A browser action with a popup that changes the page color](api/browserAction/set_page_color)<br />Change the current page color | <ul><li>tabs.executeScript</li></ul>\n[BrowsingData API: Basics](api/browsingData/basic)<br />A trivial usage example. | <ul><li>browsingData.remove</li></ul>\n[Sample Extension Commands extension](api/commands)<br />Press Ctrl+Shift+F to open the browser action popup, press Ctrl+Shift+Y to send an event. | <ul><li>commands.onCommand</li></ul>\n[Content settings](api/contentSettings)<br />Shows the content settings for the current site. | <ul><li>contentSettings.ContentSetting.get</li><li>contentSettings.ContentSetting.set</li><li>tabs.query</li></ul>\n[Context Menus Sample](api/contextMenus/basic)<br />Shows some of the features of the Context Menus API | <ul><li>contextMenus.create</li><li>extension.lastError</li></ul>\n[Context Menus Sample (with Event Page)](api/contextMenus/event_page)<br />Shows some of the features of the Context Menus API using an event page | <ul><li>contextMenus.create</li><li>contextMenus.onClicked</li><li>extension.lastError</li><li>runtime.onInstalled</li></ul>\n[Global Google Search](api/contextMenus/global_context_search)<br />Use the context menu to search a different country's Google | <ul><li>contextMenus.create</li><li>contextMenus.onClicked</li><li>contextMenus.remove</li><li>runtime.onInstalled</li><li>storage.onChanged</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li><li>tabs.create</li></ul>\n[Cookie API Test Extension](api/cookies)<br />Testing Cookie API | <ul><li>browserAction.onClicked</li><li>cookies.getAll</li><li>cookies.onChanged</li><li>cookies.remove</li><li>extension.getURL</li><li>tabs.create</li><li>tabs.update</li><li>windows.getAll</li></ul>\n[Live HTTP headers](api/debugger/live-headers)<br />Displays the live log with the http requests headers | <ul><li>browserAction.onClicked</li><li>debugger.attach</li><li>debugger.detach</li><li>debugger.onEvent</li><li>debugger.sendCommand</li><li>runtime.lastError</li><li>windows.create</li></ul>\n[JavaScript pause/resume](api/debugger/pause-resume)<br />Pauses / resumes JavaScript execution | <ul><li>browserAction.onClicked</li><li>browserAction.setIcon</li><li>browserAction.setTitle</li><li>debugger.attach</li><li>debugger.detach</li><li>debugger.onDetach</li><li>debugger.onEvent</li><li>debugger.sendCommand</li><li>runtime.lastError</li></ul>\n[Tab Flipper](api/default_command_override)<br />Press Ctrl+Shift+Right or Ctrl+Shift+Left (Command+Shift+Right or Command+Shift+Left on a Mac) to flip through window tabs | <ul><li>commands.onCommand</li><li>tabs.query</li><li>tabs.update</li></ul>\n[Desktop Capture Example](api/desktopCapture)<br />Show desktop media picker UI | <ul><li>desktopCapture.cancelChooseDesktopMedia</li><li>desktopCapture.chooseDesktopMedia</li><li>runtime.onMessage</li><li>runtime.sendMessage</li></ul>\n[My Devices](api/deviceInfo/basic)<br />A browser action with a popup dump of all devices signed into the same account as the current profile. | <ul><li>signedInDevices.get</li><li>signedInDevices.onDeviceInfoChange</li></ul>\n[FirePHP for Chrome](api/devtools/network/chrome-firephp)<br />Extends the Developer Tools, adding support for parsing FirePHP messages from server | <ul><li>devtools.network.getHAR</li><li>devtools.network.onRequestFinished</li><li>extension.onRequest</li><li>extension.sendRequest</li><li>tabs.executeScript</li></ul>\n[Chrome Query](api/devtools/panels/chrome-query)<br />Extends the Developer Tools, adding a sidebar that displays the jQuery data associated with the selected DOM element. | <ul><li>devtools.panels.ElementsPanel.createSidebarPane</li><li>devtools.panels.ElementsPanel.onSelectionChanged</li></ul>\n[tabCast](api/displaySource/tabCast)<br />Creates a WiFi Display Session from the captured tab media stream using chrome.displaySource API. | <ul><li>displaySource.getAvailableSinks</li><li>displaySource.onSessionTerminated</li><li>displaySource.onSinksUpdated</li><li>displaySource.startSession</li><li>displaySource.terminateSession</li><li>extension.getBackgroundPage</li><li>runtime.lastError</li><li>runtime.onMessage</li><li>runtime.sendMessage</li><li>tabCapture.capture</li><li>tabs.getCurrent</li></ul>\n[Document Scanning API Sample](api/document_scan)<br /> | <ul><li>documentScan.scan</li><li>permissions.contains</li><li>permissions.request</li><li>runtime.lastError</li></ul>\n[Download Filename Controller](api/downloads/download_filename_controller)<br />Download Filename Controller | <ul><li>downloads.onDeterminingFilename</li></ul>\n[Download Selected Links](api/downloads/download_links)<br />Select links on a page and download them. | <ul><li>downloads.download</li><li>extension.onRequest</li><li>extension.sendRequest</li><li>tabs.executeScript</li><li>tabs.query</li><li>windows.getCurrent</li></ul>\n[Download Manager Button](api/downloads/download_manager)<br />Browser Action Download Manager User Interface for Google Chrome | <ul><li>browserAction.setIcon</li><li>downloads.acceptDanger</li><li>downloads.cancel</li><li>downloads.download</li><li>downloads.erase</li><li>downloads.getFileIcon</li><li>downloads.onChanged</li><li>downloads.onCreated</li><li>downloads.onErased</li><li>downloads.open</li><li>downloads.pause</li><li>downloads.removeFile</li><li>downloads.resume</li><li>downloads.search</li><li>downloads.setShelfEnabled</li><li>downloads.show</li><li>downloads.showDefaultFolder</li><li>i18n.getMessage</li><li>permissions.contains</li><li>permissions.request</li><li>runtime.onMessage</li><li>runtime.sendMessage</li><li>tabs.create</li></ul>\n[Download and Open Button](api/downloads/download_open)<br />Download and Open Context Menu Button | <ul><li>contextMenus.create</li><li>contextMenus.onClicked</li><li>downloads.download</li><li>downloads.onChanged</li><li>downloads.open</li><li>i18n.getMessage</li></ul>\n[Downloads Overwrite Existing Files](api/downloads/downloads_overwrite)<br />All downloads overwrite existing files instead of adding ' (1)', ' (2)', etc. | <ul><li>downloads.onDeterminingFilename</li></ul>\n[Event Page Example](api/eventPage/basic)<br />Demonstrates usage and features of the event page | <ul><li>alarms.create</li><li>alarms.onAlarm</li><li>bookmarks.onRemoved</li><li>browserAction.onClicked</li><li>browserAction.setBadgeText</li><li>commands.onCommand</li><li>declarativeWebRequest.RedirectRequest</li><li>declarativeWebRequest.RequestMatcher</li><li>runtime.onInstalled</li><li>runtime.onMessage</li><li>runtime.onSuspend</li><li>runtime.sendMessage</li><li>tabs.create</li><li>tabs.executeScript</li><li>tabs.query</li><li>tabs.sendMessage</li></ul>\n[`extension.isAllowedFileSchemeAccess` and `extension.isAllowedIncognitoAccess` Example](api/extension/isAllowedAccess)<br />Demonstrates the `extension.isAllowedFileSchemeAccess` and `extesion.isAllowedIncognitoAccess` APIs | <ul><li>extension.isAllowedFileSchemeAccess</li><li>extension.isAllowedIncognitoAccess</li></ul>\n[Fake Archive Handler App](api/fileSystemProvider/archive)<br />Demonstrate File System Provider API usage for apps. | <ul><li>fileSystemProvider.get</li><li>fileSystemProvider.mount</li><li>fileSystemProvider.onCloseFileRequested</li><li>fileSystemProvider.onGetMetadataRequested</li><li>fileSystemProvider.onOpenFileRequested</li><li>fileSystemProvider.onReadDirectoryRequested</li><li>fileSystemProvider.onReadFileRequested</li><li>fileSystemProvider.onUnmountRequested</li><li>fileSystemProvider.unmount</li><li>runtime.lastError</li><li>runtime.onStartup</li><li>runtime.onSuspend</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li></ul>\n[File System Provider API Extension Example](api/fileSystemProvider/basic)<br />Demonstrate features of the API like mounting, listing directories, etc for extensions. | <ul><li>fileSystemProvider.mount</li><li>fileSystemProvider.onCloseFileRequested</li><li>fileSystemProvider.onGetMetadataRequested</li><li>fileSystemProvider.onMountRequested</li><li>fileSystemProvider.onOpenFileRequested</li><li>fileSystemProvider.onReadDirectoryRequested</li><li>fileSystemProvider.onReadFileRequested</li><li>fileSystemProvider.onUnmountRequested</li><li>fileSystemProvider.unmount</li><li>runtime.lastError</li></ul>\n[Advanced Font Settings](api/fontSettings)<br />Customize per-script font settings. | <ul><li>fontSettings.clearDefaultFixedFontSize</li><li>fontSettings.clearDefaultFontSize</li><li>fontSettings.clearFont</li><li>fontSettings.clearMinimumFontSize</li><li>fontSettings.getDefaultFixedFontSize</li><li>fontSettings.getDefaultFontSize</li><li>fontSettings.getFont</li><li>fontSettings.getFontList</li><li>fontSettings.getMinimumFontSize</li><li>fontSettings.onDefaultFixedFontSizeChanged</li><li>fontSettings.onDefaultFontSizeChanged</li><li>fontSettings.onFontChanged</li><li>fontSettings.onMinimumFontSizeChanged</li><li>fontSettings.setDefaultFixedFontSize</li><li>fontSettings.setDefaultFontSize</li><li>fontSettings.setFont</li><li>fontSettings.setMinimumFontSize</li></ul>\n[History Override](api/history/historyOverride)<br />Overrides the History Page | <ul><li>history.deleteAll</li><li>history.deleteUrl</li><li>history.search</li></ul>\n[Typed URL History](api/history/showHistory)<br />Reads your history, and shows the top ten pages you go to by typing the URL. | <ul><li>history.getVisits</li><li>history.search</li><li>tabs.create</li></ul>\n[CLD](api/i18n/cld)<br />Displays the language of a tab | <ul><li>browserAction.setBadgeText</li><li>tabs.detectLanguage</li><li>tabs.onSelectionChanged</li><li>tabs.onUpdated</li><li>tabs.query</li></ul>\n[Detect Language](api/i18n/detectLanguage)<br />Detects up to 3 languages and their percentages of the provided string | <ul><li>i18n.detectLanguage</li></ul>\n[AcceptLanguage](api/i18n/getMessage)<br />Returns accept languages of the browser | <ul><li>i18n.getAcceptLanguages</li><li>i18n.getMessage</li></ul>\n[Minimal Localized Hosted App](api/i18n/localizedHostedApp)<br />This is the minimal set of data required to upload a localized hosted application to the web store. | <ul></ul>\n[Idle - Simple Example](api/idle/idle_simple)<br />Demonstrates the Idle API | <ul><li>browserAction.onClicked</li><li>extension.getBackgroundPage</li><li>idle.onStateChanged</li><li>idle.queryState</li></ul>\n[Test IME](api/input.ime/basic)<br />A simple IME that converts all keystrokes to upper case. | <ul><li>input.ime</li><li>input.ime.commitText</li><li>input.ime.onActivate</li><li>input.ime.onBlur</li><li>input.ime.onDeactivated</li><li>input.ime.onFocus</li><li>input.ime.onKeyEvent</li></ul>\n[Message Timer](api/messaging/timer)<br />Times how long it takes to send a message to a content script and back. | <ul><li>runtime.onConnect</li><li>runtime.onMessage</li><li>tabs.connect</li><li>tabs.query</li><li>tabs.sendMessage</li></ul>\n[Native Messaging Example](api/nativeMessaging/app)<br />Send a message to a native application. | <ul><li>runtime.connectNative</li></ul>\n[Notification Demo](api/notifications)<br />Shows off desktop notifications, which are \"toast\" windows that pop up on the desktop. | <ul></ul>\n[Omnibox New Tab Search](api/omnibox/newtab_search)<br />Type 'nt' plus a search term into the Omnibox to open search in new tab. | <ul><li>omnibox.onInputEntered</li><li>tabs.create</li></ul>\n[Omnibox Example](api/omnibox/simple-example)<br />To use, type 'omnix' plus a search term into the Omnibox. | <ul><li>omnibox.onInputChanged</li><li>omnibox.onInputEntered</li></ul>\n[Blank new tab page](api/override/blank_ntp)<br />Override the new tab page with a blank one | <ul></ul>\n[iGoogle new tab page](api/override/override_igoogle)<br />Override the new tab page with iGoogle | <ul></ul>\n[Page action by content](api/pageAction/pageaction_by_content)<br />Shows a page action for HTML pages containing a video | <ul><li>declarativeContent.PageStateMatcher</li><li>declarativeContent.ShowPageAction</li><li>runtime.onInstalled</li></ul>\n[Page action by URL](api/pageAction/pageaction_by_url)<br />Shows a page action for urls which have the letter 'g' in them. | <ul><li>declarativeContent.PageStateMatcher</li><li>declarativeContent.ShowPageAction</li><li>runtime.onInstalled</li></ul>\n[Animated Page Action](api/pageAction/set_icon)<br />This extension adds an animated browser action to the toolbar. | <ul><li>pageAction.hide</li><li>pageAction.onClicked</li><li>pageAction.setIcon</li><li>pageAction.setTitle</li><li>pageAction.show</li><li>tabs.onSelectionChanged</li><li>tabs.query</li></ul>\n[Top Chrome Extension Questions](api/permissions/extension-questions)<br />Sample demonstration of the optional permissions API. | <ul><li>permissions.contains</li><li>permissions.onAdded</li><li>permissions.onRemoved</li><li>permissions.remove</li><li>permissions.request</li><li>tabs.create</li></ul>\n[Keep Awake](api/power)<br />Override system power-saving settings. | <ul><li>browserAction.onClicked</li><li>browserAction.setIcon</li><li>browserAction.setTitle</li><li>i18n.getMessage</li><li>power.releaseKeepAwake</li><li>power.requestKeepAwake</li><li>runtime.onInstalled</li><li>runtime.onStartup</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li></ul>\n[Block/allow third-party cookies API example extension](api/preferences/allowThirdPartyCookies)<br />Sample extension which demonstrates how to access a preference. | <ul><li>extension.isAllowedIncognitoAccess</li></ul>\n[Block/allow referrer API example extension](api/preferences/enableReferrer)<br />Sample extension which demonstrates how to access a preference. | <ul><li>extension.isAllowedIncognitoAccess</li></ul>\n[Print Extension](api/printing)<br />Sends print job directly to the printers installed on the Chromebook | <ul><li>printing.getPrinterInfo</li><li>printing.getPrinters</li><li>printing.submitJob</li><li>runtime.lastError</li></ul>\n[Print Job History](api/printingMetrics)<br />Reads your print history and displays the recent print jobs. | <ul><li>browserAction.setBadgeText</li><li>printingMetrics.getPrintJobs</li><li>printingMetrics.onPrintJobFinished</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li></ul>\n[Process Monitor](api/processes/process_monitor)<br />Adds a browser action that monitors resource usage of all browser processes. | <ul><li>processes.onUpdatedWithMemory</li><li>processes.terminate</li></ul>\n[Show Tabs in Process](api/processes/show_tabs)<br />Adds a browser action showing which tabs share the current tab's process. | <ul><li>processes.getProcessIdForTab</li><li>tabs.query</li><li>tabs.update</li><li>windows.getAll</li><li>windows.getCurrent</li><li>windows.update</li></ul>\n[Stylizr](api/storage/stylizr)<br />Spruce up your pages with custom CSS. | <ul><li>extension.getURL</li><li>runtime.lastError</li><li>storage.local</li><li>storage.StorageArea.clear</li><li>storage.StorageArea.get</li><li>storage.StorageArea.remove</li><li>storage.StorageArea.set</li><li>tabs.insertCSS</li></ul>\n[Tab Capture Example](api/tabCapture)<br />Capture a tab and play in a | <ul><li>browserAction.onClicked</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li><li>tabCapture.capture</li><li>tabCapture.getMediaStreamId</li></ul>\n[Tab Inspector](api/tabs/inspector)<br />Utility for working with the extension tabs api | <ul><li>browserAction.onClicked</li><li>extension.getURL</li><li>tabs.create</li><li>tabs.get</li><li>tabs.getAllInWindow</li><li>tabs.move</li><li>tabs.onAttached</li><li>tabs.onCreated</li><li>tabs.onDetached</li><li>tabs.onMoved</li><li>tabs.onRemoved</li><li>tabs.onSelectionChanged</li><li>tabs.onUpdated</li><li>tabs.query</li><li>tabs.remove</li><li>tabs.update</li><li>windows.create</li><li>windows.get</li><li>windows.getAll</li><li>windows.getCurrent</li><li>windows.getLastFocused</li><li>windows.onCreated</li><li>windows.onFocusChanged</li><li>windows.onRemoved</li><li>windows.remove</li><li>windows.update</li></ul>\n[Keyboard Pin](api/tabs/pin)<br />Creates a keyboard shortcut (Alt + Shift + P) to toggle the pinned state of the currently selected tab | <ul><li>commands.onCommand</li><li>tabs.query</li><li>tabs.update</li></ul>\n[Test Screenshot Extension](api/tabs/screenshot)<br />Demonstrate screenshot functionality in the chrome.tabs api. | <ul><li>browserAction.onClicked</li><li>extension.getURL</li><li>extension.getViews</li><li>tabs.captureVisibleTab</li><li>tabs.create</li><li>tabs.onUpdated</li></ul>\n[Tabs Zoom API Demo](api/tabs/zoom)<br />This extension allows the user to explore features of the new tabs zoom api. | <ul><li>runtime.lastError</li><li>tabs.getZoom</li><li>tabs.getZoomSettings</li><li>tabs.onZoomChange</li><li>tabs.query</li><li>tabs.setZoom</li><li>tabs.setZoomSettings</li></ul>\n[Top Sites](api/topsites/basic)<br />Shows the top sites in a browser action | <ul><li>tabs.create</li><li>topSites.get</li></ul>\n[NTP prototyping extension](api/topsites/magic8ball)<br />extension to prototype new NTP designs | <ul><li>topSites.get</li></ul>\n[Console TTS Engine](api/ttsEngine/console_tts_engine)<br />A \"silent\" TTS engine that prints text to a small window rather than synthesizing speech. | <ul><li>extension.getViews</li><li>ttsEngine.onSpeak</li><li>ttsEngine.onStop</li><li>windows.create</li><li>windows.getCurrent</li><li>windows.onRemoved</li></ul>\n[Drink Water Event Popup](api/water_alarm_notification)<br />Demonstrates usage and features of the event page by reminding user to drink water | <ul><li>alarms.clearAll</li><li>alarms.create</li><li>alarms.onAlarm</li><li>browserAction.setBadgeText</li><li>notifications.create</li><li>notifications.onButtonClicked</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li></ul>\n[WebNavigation Tech Demo](api/webNavigation/basic)<br />Demonstration of the WebNavigation extension API. | <ul><li>i18n.getMessage</li><li>runtime.onMessage</li><li>runtime.onStartup</li><li>runtime.sendMessage</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li><li>webNavigation.onBeforeNavigate</li><li>webNavigation.onCommitted</li><li>webNavigation.onCompleted</li><li>webNavigation.onCreatedNavigationTarget</li><li>webNavigation.onErrorOccurred</li><li>webNavigation.onHistoryStateUpdated</li><li>webNavigation.onReferenceFragmentUpdated</li></ul>\n[Webview transparency](api/webview/capturevisibleregion)<br />Sample of the webview.captureVisibleRegion api | <ul></ul>\n[WebView Extension Communications Demo: App](api/webview/comm_demo_app)<br /> | <ul><li>runtime.connect</li></ul>\n[WebView Extension Communications Demo: Extension](api/webview/comm_demo_ext)<br />Provides content scripts to an app hosting a WebView. | <ul><li>runtime.id</li><li>runtime.onConnectExternal</li></ul>\n[Merge Windows](api/windows/merge_windows)<br />Merges all of the browser's windows into the current window | <ul><li>browserAction.onClicked</li><li>tabs.getAllInWindow</li><li>tabs.move</li><li>windows.getAll</li><li>windows.getCurrent</li></ul>\n[Chrome Apps](../apps)<br />A collection of samples demonstrating the Chrome App platform. | <ul></ul>\n[App Launcher](extensions/app_launcher)<br />Get access to your apps in a browser action | <ul><li>extension.getURL</li><li>management.getAll</li><li>management.launchApp</li><li>tabs.create</li></ul>\n[Chromium Buildbot Monitor](extensions/buildbot)<br />Displays the status of the Chromium buildbot in the toolbar. Click to see more detailed status in a popup. | <ul><li>browserAction.setBadgeBackgroundColor</li><li>browserAction.setBadgeText</li><li>browserAction.setTitle</li><li>extension.getBackgroundPage</li><li>extension.getURL</li><li>extension.getViews</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li></ul>\n[Google Calendar Checker (by Google)](extensions/calendar)<br />Quickly see the time until your next meeting from any of your calendars. Click on the button to be taken to your calendar. | <ul><li>browserAction.onClicked</li><li>browserAction.setBadgeBackgroundColor</li><li>browserAction.setBadgeText</li><li>i18n.getMessage</li><li>management.uninstallSelf</li><li>notifications.clear</li><li>notifications.create</li><li>notifications.onButtonClicked</li><li>notifications.onClicked</li><li>runtime.getURL</li><li>runtime.id</li><li>runtime.onInstalled</li><li>tabs.create</li></ul>\n[CatBlock](extensions/catblock)<br />I can't has cheezburger! | <ul><li>webRequest.onBeforeRequest</li></ul>\n[Catifier](extensions/catifier)<br />Moar cats! | <ul><li>declarativeWebRequest.IgnoreRules</li><li>declarativeWebRequest.RedirectRequest</li><li>declarativeWebRequest.RequestMatcher</li><li>runtime.lastError</li><li>runtime.onInstalled</li></ul>\n[Chromium Search](extensions/chrome_search)<br />Add support to the omnibox to search the Chromium source code. | <ul><li>omnibox.onInputCancelled</li><li>omnibox.onInputChanged</li><li>omnibox.onInputEntered</li><li>omnibox.onInputStarted</li><li>omnibox.setDefaultSuggestion</li><li>tabs.query</li><li>tabs.update</li></ul>\n[Constant Context](extensions/constant_context)<br />Highlights elements with keywords on developer.chrome | <ul><li>declarativeContent.PageStateMatcher</li><li>declarativeContent.ShowPageAction</li><li>runtime.onInstalled</li><li>storage.StorageArea.clear</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li><li>tabs.executeScript</li></ul>\n[Download Images](extensions/download_images)<br />Displays all webpage images and allows user to download | <ul><li>declarativeContent.PageStateMatcher</li><li>declarativeContent.ShowPageAction</li><li>downloads.download</li><li>runtime.lastError</li><li>runtime.onInstalled</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li><li>tabs.create</li><li>tabs.executeScript</li></ul>\n[Email this page (by Google)](extensions/email_this_page)<br />This extension adds an email button to the toolbar which allows you to email the page link using your default mail client or Gmail. | <ul><li>browserAction.onClicked</li><li>runtime.connect</li><li>runtime.onConnect</li><li>tabs.create</li><li>tabs.executeScript</li><li>tabs.update</li></ul>\n[Chrome Sounds](extensions/fx)<br />Enjoy a more magical and immersive experience when browsing the web using the power of sound. | <ul><li>bookmarks.onCreated</li><li>bookmarks.onMoved</li><li>bookmarks.onRemoved</li><li>extension.getBackgroundPage</li><li>extension.onRequest</li><li>extension.sendRequest</li><li>tabs.get</li><li>tabs.onAttached</li><li>tabs.onCreated</li><li>tabs.onDetached</li><li>tabs.onMoved</li><li>tabs.onRemoved</li><li>tabs.onSelectionChanged</li><li>tabs.onUpdated</li><li>windows.onCreated</li><li>windows.onFocusChanged</li><li>windows.onRemoved</li></ul>\n[Google Document List Viewer](extensions/gdocs)<br />Demonstrates how to use OAuth to connect the Google Documents List Data API. | <ul><li>extension.getBackgroundPage</li><li>extension.getURL</li><li>tabs.create</li><li>tabs.onUpdated</li><li>tabs.query</li><li>tabs.remove</li></ul>\n[Google Mail Checker](extensions/gmail)<br />Displays the number of unread messages in your Google Mail inbox. You can also click the button to open your inbox. | <ul><li>alarms.create</li><li>alarms.get</li><li>alarms.onAlarm</li><li>browserAction.onClicked</li><li>browserAction.setBadgeBackgroundColor</li><li>browserAction.setBadgeText</li><li>browserAction.setIcon</li><li>i18n.getMessage</li><li>runtime.onInstalled</li><li>runtime.onStartup</li><li>runtime.onStartup</li><li>tabs.create</li><li>tabs.getAllInWindow</li><li>tabs.onUpdated</li><li>tabs.update</li><li>webNavigation.onDOMContentLoaded</li><li>webNavigation.onDOMContentLoaded</li><li>webNavigation.onReferenceFragmentUpdated</li><li>webNavigation.onReferenceFragmentUpdated</li><li>windows.onCreated</li></ul>\n[Imageinfo](extensions/imageinfo)<br />Get image info for images, including EXIF data | <ul><li>contextMenus.create</li><li>tabs.getCurrent</li><li>windows.create</li><li>windows.update</li></ul>\n[Chromium IRC App](extensions/irc/app)<br /> | <ul></ul>\n[Managed Bookmarks](extensions/managed_bookmarks)<br />Adds bookmarks configured by your system administrator to Chrome. | <ul><li>bookmarks.create</li><li>bookmarks.getChildren</li><li>bookmarks.move</li><li>bookmarks.onChanged</li><li>bookmarks.onMoved</li><li>bookmarks.onRemoved</li><li>bookmarks.remove</li><li>bookmarks.removeTree</li><li>bookmarks.update</li><li>runtime.onInstalled</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li><li>storage.StorageArea.get</li><li>storage.onChanged</li></ul>\n[Mappy](extensions/mappy)<br />Finds addresses in the web page you're on and pops up a map window. | <ul><li>pageAction.setTitle</li><li>pageAction.show</li><li>runtime.onMessage</li><li>runtime.sendMessage</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li></ul>\n[Google Maps](extensions/maps_app)<br /> | <ul></ul>\n[News Reader (by Google)](extensions/news)<br />Displays the latest stories from Google News in a popup. | <ul><li>extension.getURL</li><li>i18n.getMessage</li><li>tabs.create</li></ul>\n[News Reader](extensions/news_a11y)<br />Displays the first 5 items from the 'Google News - top news' RSS feed in a popup. | <ul><li>tabs.create</li></ul>\n[News Reader](extensions/news_i18n)<br />Displays the first 5 items from the '$Google$ News - top news' RSS feed in a popup. | <ul></ul>\n[No Cookies](extensions/no_cookies)<br />Removes 'Cookie' and 'Set-Cookie' headers. | <ul><li>webRequest.onBeforeSendHeaders</li><li>webRequest.onHeadersReceived</li></ul>\n[Sample - OAuth Contacts](extensions/oauth_contacts)<br />Uses OAuth to connect to Google's contacts service and display a list of your contacts. | <ul><li>browserAction.onClicked</li><li>browserAction.setIcon</li><li>extension.getBackgroundPage</li><li>extension.getURL</li><li>tabs.create</li><li>tabs.onUpdated</li><li>tabs.query</li><li>tabs.remove</li></ul>\n[Optional Permissions New Tab](extensions/optional_permissions)<br />Demonstrates optional permissions in extensions | <ul><li>permissions.contains</li><li>permissions.request</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li><li>topSites.get</li></ul>\n[Per-plugin content settings](extensions/plugin_settings)<br />Customize your content setting for different plugins. | <ul><li>contentSettings.plugins</li><li>contentSettings.ContentSetting.clear</li><li>contentSettings.ContentSetting.getResourceIdentifiers</li><li>contentSettings.ContentSetting.set</li><li>i18n.getMessage</li><li>runtime.lastError</li></ul>\n[Proxy Extension API Sample](extensions/proxy_configuration)<br />Set Chrome-specific proxies; a demonstration of Chrome's Proxy API | <ul><li>browserAction.setBadgeBackgroundColor</li><li>browserAction.setBadgeText</li><li>browserAction.setTitle</li><li>extension.isAllowedIncognitoAccess</li><li>extension.onRequest</li><li>extension.sendRequest</li><li>i18n.getMessage</li><li>proxy.onProxyError</li><li>runtime.lastError</li></ul>\n[Speak Selection](extensions/speak_selection)<br />Speaks the current selection out loud. | <ul><li>browserAction.onClicked</li><li>browserAction.setIcon</li><li>extension.getURL</li><li>extension.onRequest</li><li>extension.sendRequest</li><li>tabs.create</li><li>tabs.executeScript</li><li>tabs.sendRequest</li><li>tts.getVoices</li><li>tts.speak</li><li>tts.stop</li><li>windows.getAll</li></ul>\n[Talking Alarm Clock](extensions/talking_alarm_clock)<br />A clock with two configurable alarms that will play a sound and speak a phrase of your choice. | <ul><li>browserAction.setIcon</li><li>runtime.connect</li><li>runtime.onConnect</li><li>tts.getVoices</li><li>tts.speak</li><li>tts.stop</li></ul>\n[TTS Debug](extensions/ttsdebug)<br />Tool for developers of Chrome TTS engine extensions to help them test their engines are implementing the API correctly. | <ul><li>tts.getVoices</li><li>tts.speak</li><li>tts.stop</li></ul>\n[TTS Demo](extensions/ttsdemo)<br />Demo Chrome's synthesized text-to-speech capabilities. | <ul><li>runtime.lastError</li><li>tts.getVoices</li><li>tts.isSpeaking</li><li>tts.speak</li><li>tts.stop</li></ul>\n[Sandboxed Frame](howto/sandbox)<br />Demonstrate use of handlebars inside a sandboxed frame | <ul><li>browserAction.onClicked</li></ul>\n[Tab Shortcuts](howto/tab_shortcuts)<br />Allows pinning and duplication of tabs via keyboard shortcuts. | <ul><li>commands.onCommand</li><li>tabs.duplicate</li><li>tabs.update</li></ul>\n[Event Tracking with Google Analytics](tutorials/analytics)<br />A sample extension which uses Google Analytics to track usage. | <ul></ul>\n[Broken Background Color](tutorials/broken_background_color)<br />Fix an Extension! | <ul><li>declarativeContent.PageStateMatcher</li><li>declarativeContent.ShowPageAction</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li><li>tabs.executeScript</li></ul>\n[Getting Started Example](tutorials/get_started)<br />Build an Extension! | <ul><li>runtime.onInstalled</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li></ul>\n[Getting Started Example](tutorials/get_started_complete)<br />Build an Extension! | <ul><li>declarativeContent.PageStateMatcher</li><li>declarativeContent.ShowPageAction</li><li>runtime.onInstalled</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li><li>tabs.executeScript</li><li>tabs.query</li></ul>\n[Getting started example](tutorials/getstarted)<br />This extension allows the user to change the background color of the current page. | <ul><li>runtime.lastError</li><li>storage.local</li><li>storage.sync</li><li>storage.StorageArea.get</li><li>storage.StorageArea.set</li><li>tabs.executeScript</li><li>tabs.query</li></ul>\n[Hello Extensions](tutorials/hello_extensions)<br />Base Level Extension | <ul></ul>\n[OAuth Tutorial FriendBlock](tutorials/oauth_starter)<br />Uses OAuth to connect to Google's People API and display contacts photos. | <ul><li>browserAction.onClicked</li><li>identity.getAuthToken</li><li>tabs.create</li></ul>\n[OAuth Tutorial FriendBlock](tutorials/oauth_tutorial_complete)<br />Uses OAuth to connect to Google's People API and display contacts photos. | <ul><li>browserAction.onClicked</li><li>identity.getAuthToken</li><li>tabs.create</li></ul>\n"
  },
  {
    "path": "_archive/mv2/tutorials/analytics/manifest.json",
    "content": "{\n  \"name\": \"Event Tracking with Google Analytics\",\n  \"version\": \"2.0.0\",\n  \"description\": \"A sample extension which uses Google Analytics to track usage.\",\n  \"browser_action\": {\n    \"default_title\": \"Open the popup\",\n    \"default_icon\": \"analytics-extension-icon-19.png\",\n    \"default_popup\" : \"popup.html\"\n  },\n  \"icons\": {\n    \"48\": \"analytics-extension-icon-48.png\",\n    \"128\": \"analytics-extension-icon-128.png\"\n  },\n\n  \"manifest_version\": 2,\n  \"content_security_policy\": \"script-src 'self' https://ssl.google-analytics.com; object-src 'self'\"\n}\n"
  },
  {
    "path": "_archive/mv2/tutorials/analytics/popup.html",
    "content": "<!DOCTYPE html>\n<!--\n * Copyright (c) 2012 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n<html>\n  <head>\n    <style>\n      body {\n        width: 300px;\n        color: #000;\n        font-family: Arial;\n      }\n      #output {\n        color: #d00;\n        text-align: center;\n      }\n    </style>\n    <script src=\"popup.js\"></script>\n  </head>\n  <body>\n    <h1>Popup</h1>\n    <p>Track the following actions:</p>\n    <button id='button1'>Button 1</button>\n    <button id='button2'>Button 2</button>\n    <button id='button3'>Button 3</button>\n    <button id='button4'>Button 4</button>\n    <button id='button5'>Button 5</button>\n    <button id='button6'>Button 6</button>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/tutorials/analytics/popup.js",
    "content": "// Copyright (c) 2012 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * Add your Analytics tracking ID here.\n */\nvar _AnalyticsCode = 'UA-XXXXXX-X';\n\n/**\n * Below is a modified version of the Google Analytics asynchronous tracking\n * code snippet.  It has been modified to pull the HTTPS version of ga.js\n * instead of the default HTTP version.  It is recommended that you use this\n * snippet instead of the standard tracking snippet provided when setting up\n * a Google Analytics account.\n */\nvar _gaq = _gaq || [];\n_gaq.push(['_setAccount', _AnalyticsCode]);\n_gaq.push(['_trackPageview']);\n\n(function() {\n  var ga = document.createElement('script');\n  ga.type = 'text/javascript';\n  ga.async = true;\n  ga.src = 'https://ssl.google-analytics.com/ga.js';\n  var s = document.getElementsByTagName('script')[0];\n  s.parentNode.insertBefore(ga, s);\n})();\n\n/**\n * Track a click on a button using the asynchronous tracking API.\n *\n * See http://code.google.com/apis/analytics/docs/tracking/asyncTracking.html\n * for information on how to use the asynchronous tracking API.\n */\nfunction trackButtonClick(e) {\n  _gaq.push(['_trackEvent', e.target.id, 'clicked']);\n}\n\n/**\n * Now set up your event handlers for the popup's `button` elements once the\n * popup's DOM has loaded.\n */\ndocument.addEventListener('DOMContentLoaded', function () {\n  var buttons = document.querySelectorAll('button');\n  for (var i = 0; i < buttons.length; i++) {\n    buttons[i].addEventListener('click', trackButtonClick);\n  }\n});\n"
  },
  {
    "path": "_archive/mv2/tutorials/broken_background_color/background.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\n// There's a typo in the line below; oninstalled should be onInstalled.\nchrome.runtime.oninstalled.addListener(function() {\n  chrome.storage.sync.set({color: '#3aa757'}, function() {\n    console.log('The color is green.');\n  });\n  chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {\n    chrome.declarativeContent.onPageChanged.addRules([{\n      conditions: [new chrome.declarativeContent.PageStateMatcher({\n        pageUrl: {hostEquals: 'developer.chrome.com'},\n      })],\n      actions: [new chrome.declarativeContent.ShowPageAction()]\n    }]);\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/tutorials/broken_background_color/manifest.json",
    "content": "{\n  \"name\": \"Broken Background Color\",\n  \"version\": \"1.0\",\n  \"description\": \"Fix an Extension!\",\n  \"permissions\": [\"activeTab\", \"declarativeContent\", \"storage\"],\n  \"options_page\": \"options.html\",\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"page_action\": {\n    \"default_popup\": \"popup.html\",\n    \"default_icon\": {\n      \"16\": \"images/get_started16.png\",\n      \"32\": \"images/get_started32.png\",\n      \"48\": \"images/get_started48.png\",\n      \"128\": \"images/get_started128.png\"\n    }\n  },\n  \"icons\": {\n    \"16\": \"images/get_started16.png\",\n    \"32\": \"images/get_started32.png\",\n    \"48\": \"images/get_started48.png\",\n    \"128\": \"images/get_started128.png\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/tutorials/broken_background_color/options.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <style>\n      button {\n        height: 30px;\n        width: 30px;\n        outline: none;\n        margin: 10px;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"buttonDiv\">\n    </div>\n    <div>\n      <p>Choose a different background color!</p>\n    </div>\n  </body>\n  <script src=\"options.js\"></script>\n</html>\n"
  },
  {
    "path": "_archive/mv2/tutorials/broken_background_color/options.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nlet page = document.getElementById('buttonDiv');\nconst kButtonColors = ['#3aa757', '#e8453c', '#f9bb2d', '#4688f1'];\nfunction constructOptions(kButtonColors) {\n  for (let item of kButtonColors) {\n    let button = document.createElement('button');\n    button.style.backgroundColor = item;\n    button.addEventListener('click', function() {\n      chrome.storage.sync.set({color: item}, function() {\n        console.log('color is ' + item);\n      })\n    });\n    page.appendChild(button);\n  }\n}\nconstructOptions(kButtonColors);\n"
  },
  {
    "path": "_archive/mv2/tutorials/broken_background_color/popup.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <style>\n      button {\n        height: 30px;\n        width: 30px;\n        outline: none;\n        background-color: #3aa757;\n      }\n    </style>\n  </head>\n  <body>\n    <button id=\"changeColor\"></button>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/tutorials/broken_background_color/popup.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nlet changeColor = document.getElementById('changeColor');\n\nchrome.storage.sync.get('color', function(data) {\n  changeColor.style.backgroundColor = data.color;\n  changeColor.setAttribute('value', data.color);\n});\n\nchangeColor.onclick = function(element) {\n  let color = element.target.value;\n  // The extension must query the active tab\n  // before it can injected a content script\n  chrome.tabs.executeScript(\n      tabs[0].id,\n      // Scripts injected with tabs.executeScript() will not have access to\n      // variables from this context, leaving |color| undefined.\n      {code: 'document.body.style.backgroundColor = color;'});\n};\n"
  },
  {
    "path": "_archive/mv2/tutorials/get_started/background.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nchrome.runtime.onInstalled.addListener(function() {\n  chrome.storage.sync.set({color: '#3aa757'}, function() {\n    console.log(\"The color is green.\");\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/tutorials/get_started/manifest.json",
    "content": "{\n  \"name\": \"Getting Started Example\",\n  \"version\": \"1.0\",\n  \"description\": \"Build an Extension!\",\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/tutorials/get_started/options.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <style>\n      button {\n        height: 30px;\n        width: 30px;\n        outline: none;\n        margin: 10px;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"buttonDiv\">\n    </div>\n  </body>\n  <script src=\"options.js\"></script>\n</html>\n"
  },
  {
    "path": "_archive/mv2/tutorials/get_started/options.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nlet page = document.getElementById('buttonDiv');\nconst kButtonColors = ['#3aa757', '#e8453c', '#f9bb2d', '#4688f1'];\nfunction constructOptions(kButtonColors) {\n  for (let item of kButtonColors) {\n    let button = document.createElement('button');\n    button.style.backgroundColor = item;\n    button.addEventListener('click', function() {\n      chrome.storage.sync.set({color: item}, function() {\n        console.log('color is ' + item);\n      })\n    });\n    page.appendChild(button);\n  }\n}\nconstructOptions(kButtonColors);\n"
  },
  {
    "path": "_archive/mv2/tutorials/get_started/popup.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <style>\n      button {\n        height: 30px;\n        width: 30px;\n        outline: none;\n      }\n    </style>\n  </head>\n  <body>\n    <button id=\"changeColor\"></button>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/tutorials/get_started/popup.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nlet changeColor = document.getElementById('changeColor');\nchrome.storage.sync.get('color', function(data) {\n  changeColor.style.backgroundColor = data.color;\n  changeColor.setAttribute('value', data.color);\n});\n"
  },
  {
    "path": "_archive/mv2/tutorials/get_started_complete/background.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nchrome.runtime.onInstalled.addListener(function() {\n  chrome.storage.sync.set({color: '#3aa757'}, function() {\n    console.log('The color is green.');\n  });\n  chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {\n    chrome.declarativeContent.onPageChanged.addRules([{\n      conditions: [new chrome.declarativeContent.PageStateMatcher({\n        pageUrl: {hostEquals: 'developer.chrome.com'},\n      })],\n      actions: [new chrome.declarativeContent.ShowPageAction()]\n    }]);\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/tutorials/get_started_complete/manifest.json",
    "content": "{\n  \"name\": \"Getting Started Example\",\n  \"version\": \"1.0\",\n  \"description\": \"Build an Extension!\",\n  \"permissions\": [\"activeTab\", \"declarativeContent\", \"storage\"],\n  \"options_page\": \"options.html\",\n  \"background\": {\n    \"scripts\": [\"background.js\"],\n    \"persistent\": false\n  },\n  \"page_action\": {\n    \"default_popup\": \"popup.html\",\n    \"default_icon\": {\n      \"16\": \"images/get_started16.png\",\n      \"32\": \"images/get_started32.png\",\n      \"48\": \"images/get_started48.png\",\n      \"128\": \"images/get_started128.png\"\n    }\n  },\n  \"icons\": {\n    \"16\": \"images/get_started16.png\",\n    \"32\": \"images/get_started32.png\",\n    \"48\": \"images/get_started48.png\",\n    \"128\": \"images/get_started128.png\"\n  },\n  \"manifest_version\": 2\n}\n"
  },
  {
    "path": "_archive/mv2/tutorials/get_started_complete/options.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <style>\n      button {\n        height: 30px;\n        width: 30px;\n        outline: none;\n        margin: 10px;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"buttonDiv\">\n    </div>\n    <div>\n      <p>Choose a different background color!</p>\n    </div>\n  </body>\n  <script src=\"options.js\"></script>\n</html>\n"
  },
  {
    "path": "_archive/mv2/tutorials/get_started_complete/options.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nlet page = document.getElementById('buttonDiv');\nconst kButtonColors = ['#3aa757', '#e8453c', '#f9bb2d', '#4688f1'];\nfunction constructOptions(kButtonColors) {\n  for (let item of kButtonColors) {\n    let button = document.createElement('button');\n    button.style.backgroundColor = item;\n    button.addEventListener('click', function() {\n      chrome.storage.sync.set({color: item}, function() {\n        console.log('color is ' + item);\n      })\n    });\n    page.appendChild(button);\n  }\n}\nconstructOptions(kButtonColors);\n"
  },
  {
    "path": "_archive/mv2/tutorials/get_started_complete/popup.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <style>\n      button {\n        height: 30px;\n        width: 30px;\n        outline: none;\n      }\n    </style>\n  </head>\n  <body>\n    <button id=\"changeColor\"></button>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/tutorials/get_started_complete/popup.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nlet changeColor = document.getElementById('changeColor');\n\nchrome.storage.sync.get('color', function(data) {\n  changeColor.style.backgroundColor = data.color;\n  changeColor.setAttribute('value', data.color);\n});\n\nchangeColor.onclick = function(element) {\n  let color = element.target.value;\n  chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {\n    chrome.tabs.executeScript(\n        tabs[0].id,\n        {code: 'document.body.style.backgroundColor = \"' + color + '\";'});\n  });\n};\n"
  },
  {
    "path": "_archive/mv2/tutorials/getstarted/manifest.json",
    "content": "{\n  \"manifest_version\": 2,\n\n  \"name\": \"Getting started example\",\n  \"description\": \"This extension allows the user to change the background color of the current page.\",\n  \"version\": \"1.0\",\n\n  \"browser_action\": {\n    \"default_icon\": \"icon.png\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"permissions\": [\n    \"activeTab\",\n    \"storage\"\n  ]\n}\n"
  },
  {
    "path": "_archive/mv2/tutorials/getstarted/popup.html",
    "content": "<!doctype html>\n<!--\n This page is shown when the extension button is clicked, because the\n \"browser_action\" field in manifest.json contains the \"default_popup\" key with\n value \"popup.html\".\n -->\n<html>\n  <head>\n    <title>Getting Started Extension's Popup</title>\n    <style type=\"text/css\">\n      body {\n        margin: 10px;\n        white-space: nowrap;\n      }\n\n      h1 {\n        font-size: 15px;\n      }\n\n      #container {\n        align-items: center;\n        display: flex;\n        justify-content: space-between;\n      }\n    </style>\n\n    <!--\n      - JavaScript and HTML must be in separate files: see our Content Security\n      - Policy documentation[1] for details and explanation.\n      -\n      - [1]: https://developer.chrome.com/extensions/contentSecurityPolicy\n    -->\n    <script src=\"popup.js\"></script>\n  </head>\n\n  <body>\n    <h1>Background Color Changer</h1>\n    <div id=\"container\">\n      <span>Choose a color</span>\n      <select id=\"dropdown\">\n        <option selected disabled hidden value=''></option>\n        <option value=\"white\">White</option>\n        <option value=\"pink\">Pink</option>\n        <option value=\"green\">Green</option>\n        <option value=\"yellow\">Yellow</option>\n      </select>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/tutorials/getstarted/popup.js",
    "content": "// Copyright (c) 2014 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * Get the current URL.\n *\n * @param {function(string)} callback called when the URL of the current tab\n *   is found.\n */\nfunction getCurrentTabUrl(callback) {\n  // Query filter to be passed to chrome.tabs.query - see\n  // https://developer.chrome.com/extensions/tabs#method-query\n  var queryInfo = {\n    active: true,\n    currentWindow: true\n  };\n\n  chrome.tabs.query(queryInfo, (tabs) => {\n    // chrome.tabs.query invokes the callback with a list of tabs that match the\n    // query. When the popup is opened, there is certainly a window and at least\n    // one tab, so we can safely assume that |tabs| is a non-empty array.\n    // A window can only have one active tab at a time, so the array consists of\n    // exactly one tab.\n    var tab = tabs[0];\n\n    // A tab is a plain object that provides information about the tab.\n    // See https://developer.chrome.com/extensions/tabs#type-Tab\n    var url = tab.url;\n\n    // tab.url is only available if the \"activeTab\" permission is declared.\n    // If you want to see the URL of other tabs (e.g. after removing active:true\n    // from |queryInfo|), then the \"tabs\" permission is required to see their\n    // \"url\" properties.\n    console.assert(typeof url == 'string', 'tab.url should be a string');\n\n    callback(url);\n  });\n\n  // Most methods of the Chrome extension APIs are asynchronous. This means that\n  // you CANNOT do something like this:\n  //\n  // var url;\n  // chrome.tabs.query(queryInfo, (tabs) => {\n  //   url = tabs[0].url;\n  // });\n  // alert(url); // Shows \"undefined\", because chrome.tabs.query is async.\n}\n\n/**\n * Change the background color of the current page.\n *\n * @param {string} color The new background color.\n */\nfunction changeBackgroundColor(color) {\n  var script = 'document.body.style.backgroundColor=\"' + color + '\";';\n  // See https://developer.chrome.com/extensions/tabs#method-executeScript.\n  // chrome.tabs.executeScript allows us to programmatically inject JavaScript\n  // into a page. Since we omit the optional first argument \"tabId\", the script\n  // is inserted into the active tab of the current window, which serves as the\n  // default.\n  chrome.tabs.executeScript({\n    code: script\n  });\n}\n\n/**\n * Gets the saved background color for url.\n *\n * @param {string} url URL whose background color is to be retrieved.\n * @param {function(string)} callback called with the saved background color for\n *     the given url on success, or a falsy value if no color is retrieved.\n */\nfunction getSavedBackgroundColor(url, callback) {\n  // See https://developer.chrome.com/apps/storage#type-StorageArea. We check\n  // for chrome.runtime.lastError to ensure correctness even when the API call\n  // fails.\n  chrome.storage.sync.get(url, (items) => {\n    callback(chrome.runtime.lastError ? null : items[url]);\n  });\n}\n\n/**\n * Sets the given background color for url.\n *\n * @param {string} url URL for which background color is to be saved.\n * @param {string} color The background color to be saved.\n */\nfunction saveBackgroundColor(url, color) {\n  var items = {};\n  items[url] = color;\n  // See https://developer.chrome.com/apps/storage#type-StorageArea. We omit the\n  // optional callback since we don't need to perform any action once the\n  // background color is saved.\n  chrome.storage.sync.set(items);\n}\n\n// This extension loads the saved background color for the current tab if one\n// exists. The user can select a new background color from the dropdown for the\n// current page, and it will be saved as part of the extension's isolated\n// storage. The chrome.storage API is used for this purpose. This is different\n// from the window.localStorage API, which is synchronous and stores data bound\n// to a document's origin. Also, using chrome.storage.sync instead of\n// chrome.storage.local allows the extension data to be synced across multiple\n// user devices.\ndocument.addEventListener('DOMContentLoaded', () => {\n  getCurrentTabUrl((url) => {\n    var dropdown = document.getElementById('dropdown');\n\n    // Load the saved background color for this page and modify the dropdown\n    // value, if needed.\n    getSavedBackgroundColor(url, (savedColor) => {\n      if (savedColor) {\n        changeBackgroundColor(savedColor);\n        dropdown.value = savedColor;\n      }\n    });\n\n    // Ensure the background color is changed and saved when the dropdown\n    // selection changes.\n    dropdown.addEventListener('change', () => {\n      changeBackgroundColor(dropdown.value);\n      saveBackgroundColor(url, dropdown.value);\n    });\n  });\n});\n"
  },
  {
    "path": "_archive/mv2/tutorials/hello_extensions/hello.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title> Hello Extensions </title>\n  </head>\n\n  <body>\n    <h1>Hello Extensions</h1>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/tutorials/hello_extensions/manifest.json",
    "content": "{\n  \"name\": \"Hello Extensions\",\n  \"description\": \"Base Level Extension\",\n  \"version\": \"1.0\",\n  \"browser_action\": {\n    \"default_popup\": \"hello.html\",\n    \"default_icon\": \"hello_extensions.png\"\n  },\n  \"manifest_version\": 2,\n  \"commands\": {\n    \"_execute_browser_action\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+Shift+F\",\n        \"mac\": \"MacCtrl+Shift+F\"\n      },\n      \"description\": \"Opens hello.html\"\n    }\n  }\n}\n"
  },
  {
    "path": "_archive/mv2/tutorials/oauth_starter/background.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nchrome.browserAction.onClicked.addListener(function() {\n  chrome.tabs.create({url: 'index.html'});\n});\n"
  },
  {
    "path": "_archive/mv2/tutorials/oauth_starter/index.html",
    "content": "<!-- Copyright 2018 The Chromium Authors. All rights reserved.\nUse of this source code is governed by a BSD-style license that can be\nfound in the LICENSE file. -->\n\n<html>\n  <head>\n    <title>FriendBlock</title>\n    <style>\n      button {\n        padding: 10px;\n        background-color: #3C79F8;\n        display: inline-block;\n        }\n    </style>\n  </head>\n  <body>\n    <button>FriendBlock Contacts</button>\n    <div id=\"friendDiv\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "_archive/mv2/tutorials/oauth_starter/manifest.json",
    "content": "{\n   \"name\": \"OAuth Tutorial FriendBlock\",\n   \"version\": \"1.0\",\n   \"description\": \"Uses OAuth to connect to Google's People API and display contacts photos.\",\n   \"manifest_version\": 2,\n   \"browser_action\": {\n     \"default_title\": \"FriendBlock, friends face's in a block.\"\n   },\n   \"background\": {\n     \"scripts\": [\n       \"background.js\"\n     ],\n     \"persistent\": false\n   }\n }\n"
  },
  {
    "path": "_archive/mv2/tutorials/oauth_starter/oauth.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nwindow.onload = function() {\n  document.querySelector('button').addEventListener('click', function() {\n    chrome.identity.getAuthToken({interactive: true}, function(token) {\n      console.log(token);\n    });\n  });\n};\n"
  },
  {
    "path": "_archive/mv2/tutorials/oauth_tutorial_complete/background.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nchrome.browserAction.onClicked.addListener(function() {\n  chrome.tabs.create({url: 'index.html'});\n});\n"
  },
  {
    "path": "_archive/mv2/tutorials/oauth_tutorial_complete/index.html",
    "content": "<html>\n   <head>\n     <title>FriendBlock</title>\n     <style>\n       button {\n         padding: 10px;\n         background-color: #3C79F8;\n         display: inline-block;\n       }\n     </style>\n     <script type=\"text/javascript\" src=\"oauth.js\"></script>\n   </head>\n   <body>\n     <button>FriendBlock Contacts</button>\n     <div id=\"friendDiv\"></div>\n   </body>\n </html>\n"
  },
  {
    "path": "_archive/mv2/tutorials/oauth_tutorial_complete/manifest.json",
    "content": "{\n  \"name\": \"OAuth Tutorial FriendBlock\",\n  \"version\": \"1.0\",\n  \"description\": \"Uses OAuth to connect to Google's People API and display contacts photos.\",\n  \"manifest_version\": 2,\n  \"browser_action\": {\n    \"default_title\": \"FriendBlock, friends face's in a block.\"\n  },\n  \"permissions\": [\n    \"identity\"\n  ],\n  \"background\": {\n    \"scripts\": [\n      \"background.js\"\n    ],\n    \"persistent\": false\n  },\n  \"oauth2\": {\n    \"client_id\": \"ClientIDFromGoogleAPIConsole\",\n    \"scopes\":[\"https://www.googleapis.com/auth/contacts.readonly\"]\n  },\n  \"key\": \"KeyFromDeveloperDashboardHere\"\n}\n"
  },
  {
    "path": "_archive/mv2/tutorials/oauth_tutorial_complete/oauth.js",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n'use strict';\n\nwindow.onload = function() {\n  document.querySelector('button').addEventListener('click', function() {\n    chrome.identity.getAuthToken({interactive: true}, function(token) {\n      var init = {\n        method: 'GET',\n        async: true,\n        headers: {\n          Authorization: 'Bearer ' + token,\n          'Content-Type': 'application/json'\n        },\n        'contentType': 'json'\n      };\n      fetch(\n          'https://people.googleapis.com/v1/contactGroups/all?maxMembers=20&key=<API_Key_Here>',\n          init)\n          .then((response) => response.json())\n          .then(function(data) {\n            let photoDiv = document.querySelector('#friendDiv');\n            let returnedContacts = data.memberResourceNames;\n            for (var i = 0; i < returnedContacts.length; i++) {\n              fetch(\n                  'https://people.googleapis.com/v1/' + returnedContacts[i] +\n                      '?personFields=photos&key=<API_Key_Here>',\n                  init)\n                  .then((response) => response.json())\n                  .then(function(data) {\n                    let profileImg = document.createElement('img');\n                    profileImg.src = data.photos[0].url;\n                    photoDiv.appendChild(profileImg);\n                  });\n            };\n          });\n    });\n  });\n};\n"
  },
  {
    "path": "api-samples/action/README.md",
    "content": "# chrome.action\n\nThis sample demonstrates the use of Action API which changes the badge text,icon,hover text or popup page depending on the user's choice or action.\n\n[API Link](https://developer.chrome.com/docs/extensions/reference/action/)\n\n## Overview\n\nThis sample demonstrates the Action API by allowing the user to perform the below actions:\n\n- Toggle Enabled State : to enable or disable the extensions' action button in Chrome's toolbar and menu.\n- Change Popup Page : to change the popup page by entering a new string or url.\n- Badge Text : to insert a text overlay with a solid background color.\n- Icon Image : to change the action button's icon.\n- Hover Text : it is visible when mousing over the extension's icon.\n\n## Implementation Notes\n\nThe user can set values to implement above functionalities from [here](demo/index.html)\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension's icon in the toolbar to open the demo page.\n"
  },
  {
    "path": "api-samples/action/background.js",
    "content": "// Copyright 2021 Google LLC\n//\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file or at\n// https://developers.google.com/open-source/licenses/bsd\n\n// Show the demo page once the extension is installed\nchrome.runtime.onInstalled.addListener((_reason) => {\n  chrome.tabs.create({\n    url: 'demo/index.html'\n  });\n});\n"
  },
  {
    "path": "api-samples/action/demo/index.css",
    "content": "p {\n  hyphens: initial;\n}\n\n.flex {\n  display: flex;\n  gap: 0.25em;\n  margin: 0.5em 0;\n  align-items: flex-end;\n}\n\n.spaced {\n  margin: 0.5em 0;\n}\n\n.full-width {\n  width: 100%;\n}\n\nbutton {\n  white-space: nowrap;\n}\n"
  },
  {
    "path": "api-samples/action/demo/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Document</title>\n    <script defer src=\"index.js\"></script>\n    <link rel=\"stylesheet\" href=\"../third-party/awsm/awsm.css\" />\n    <link rel=\"stylesheet\" href=\"index.css\" />\n  </head>\n  <body>\n    <main>\n      <section>\n        <h1>Action API Demo</h1>\n        <p>\n          Before experimenting with these APIs, we recommend you pin the\n          extension's action button to your toolbar in order to make it easier\n          to see the changes.\n        </p>\n        <img src=\"../images/pin-action.png\" />\n      </section>\n\n      <section id=\"toggle-state\">\n        <h2>enable / disable</h2>\n\n        <p>\n          Clicking the below <em>toggle enabled state</em> button will enable or\n          disable the extensions' action button in Chrome's toolbar and\n          extensions menu.\n        </p>\n\n        <p>\n          When disabled, clicking the action will not open a popup or trigger\n          <a\n            href=\"https://developer.chrome.com/docs/extensions/reference/action/#event-onClicked\"\n            ><code>action.onClicked</code></a\n          >\n          events.\n        </p>\n\n        <button id=\"toggle-state-button\">toggle enabled state</button>\n\n        <div class=\"flex\">\n          <figure>\n            <img src=\"../images/action-enabled.png\" />\n            <figcaption>Action enabled</figcaption>\n          </figure>\n          <figure>\n            <img src=\"../images/action-disabled.png\" />\n            <figcaption>Action disabled</figcaption>\n          </figure>\n        </div>\n      </section>\n\n      <section id=\"popup\">\n        <h2>Popup</h2>\n\n        <p>\n          This demo's <a href=\"manifest.json\">manifest.json</a> file sets the\n          value of <code>action.default_popup</code> to\n          <code>popups/popup.html</code>. We can change that behavior at runtime\n          using\n          <a\n            href=\"https://developer.chrome.com/docs/extensions/reference/action/#method-setPopup\"\n            ><code>action.setPopup</code></a\n          >.\n        </p>\n\n        <label>\n          Change popup page<br />\n          <select id=\"popup-options\">\n            <option value=\"/popups/popup.html\">Hello world (default)</option>\n            <option value=\"/popups/a.html\">A</option>\n            <option value=\"/popups/b.html\">B</option>\n            <option value=\"\">onClicked handler</option>\n          </select>\n        </label>\n\n        <div class=\"spaced\">\n          <label>\n            Current popup value\n            <input type=\"text\" id=\"current-popup-value\" disabled />\n          </label>\n        </div>\n\n        <p>\n          Register a handler to change how the action button behaves. Once\n          changed, clicking the action will open your new favorite website.\n        </p>\n        <button id=\"onclicked-button\">Change action click behavior</button>\n        <button id=\"onclicked-reset-button\">reset</button>\n      </section>\n\n      <!-- badge -->\n\n      <section id=\"badge-text\">\n        <h2>Badge Text</h2>\n\n        <p>\n          The action's badge text is a text overlay with a solid background\n          color. This provides a passive UI surface to share information with\n          the user. It is most commonly used to show a notification count or\n          number of actions taken on the current page.\n        </p>\n\n        <div class=\"spaced\">\n          <label>\n            Enter badge text (live update)<br />\n            <input type=\"text\" id=\"badge-text-input\" />\n          </label>\n        </div>\n\n        <div class=\"flex\">\n          <label class=\"full-width\">\n            Current badge text\n            <input type=\"text\" id=\"current-badge-text\" disabled />\n          </label>\n          <button id=\"clear-badge-button\">clear badge text</button>\n        </div>\n\n        <div class=\"spaced\">\n          <button id=\"set-badge-background-color-button\">\n            Randomize badge background color\n          </button>\n        </div>\n\n        <div class=\"flex\">\n          <label class=\"full-width\">\n            Current badge color\n            <input type=\"text\" id=\"current-badge-bg-color\" disabled />\n          </label>\n          <button id=\"reset-badge-background-color-button\">\n            Reset badge color\n          </button>\n        </div>\n      </section>\n      <!-- Badge Text Color !-->\n      <section>\n        <h2>Badge Text Color</h2>\n        <p>\n          The\n          <a\n            href=\"https://developer.chrome.com/docs/extensions/reference/action/#method-setBadgeTextColor\"\n            ><code>action.setBadgeTextColor</code></a\n          >\n          method allows you to change the color of the badge text.\n        </p>\n\n        <div class=\"spaced\">\n          <button id=\"set-badge-txt-color-button\">\n            Randomize badge text color\n          </button>\n        </div>\n\n        <p>\n          The\n          <a\n            href=\"https://developer.chrome.com/docs/extensions/reference/action/#method-getBadgeTextColor\"\n            ><code>action.getBadgeTextColor</code></a\n          >\n          method allows you to read the current color of the badge text.\n        </p>\n\n        <div class=\"flex\">\n          <label class=\"full-width\">\n            Current badge text color\n            <input type=\"text\" id=\"current-badge-txt-color\" disabled />\n          </label>\n          <button id=\"reset-badge-txt-color-button\">\n            Reset badge text color\n          </button>\n        </div>\n      </section>\n\n      <!-- badge - icon -->\n\n      <section id=\"setIcon\">\n        <h2>Icon</h2>\n\n        <p>\n          The\n          <a\n            href=\"https://developer.chrome.com/docs/extensions/reference/action/#method-setIcon\"\n            ><code>action.setIcon</code></a\n          >\n          method allows you to change the action button's icon by either\n          providing the path of an image or the raw\n          <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/ImageData\"\n            >ImageData</a\n          >.\n        </p>\n\n        <button id=\"set-icon-button\">set a new action icon</button>\n        <button id=\"reset-icon-button\">reset action icon</button>\n      </section>\n\n      <!-- badge - hover text (title) -->\n\n      <section id=\"title\">\n        <h2>Hover Text</h2>\n\n        <p>\n          The action's title is visible when mousing over the extension's action\n          button.\n        </p>\n\n        <p>\n          This value can be read and changed at runtime using the\n          <a\n            href=\"https://developer.chrome.com/docs/extensions/reference/action/#method-getTitle\"\n            ><code>action.getTitle</code></a\n          >\n          and\n          <a\n            href=\"https://developer.chrome.com/docs/extensions/reference/action/#method-setTitle\"\n            ><code>action.setTitle</code></a\n          >\n          methods, respectively.\n        </p>\n\n        <div class=\"spaced\">\n          <label>\n            Enter a new title (debounced)<br />\n            <input type=\"text\" id=\"title-input\" />\n          </label>\n        </div>\n\n        <div class=\"flex\">\n          <label class=\"full-width\">\n            Current title\n            <input type=\"text\" id=\"current-title\" disabled />\n          </label>\n          <button id=\"reset-title-button\">reset title</button>\n        </div>\n\n        <div class=\"flex\">\n          <figure>\n            <img src=\"../images/title-no-hover.png\" />\n            <figcaption>Default appearance</figcaption>\n          </figure>\n          <figure>\n            <img src=\"../images/title-hover.png\" />\n            <figcaption>Title appears on hover</figcaption>\n          </figure>\n        </div>\n      </section>\n    </main>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/action/demo/index.js",
    "content": "// Copyright 2021 Google LLC\n//\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file or at\n// https://developers.google.com/open-source/licenses/bsd\n\n/**\n * @param {number} timeout\n * @param {(event: Event) => void} callback\n * @return {(event: Event) => void}\n */\nfunction debounce(timeout, callback) {\n  let timeoutID = 0;\n  return (event) => {\n    clearTimeout(timeoutID);\n    timeoutID = setTimeout(() => callback(event), timeout);\n  };\n}\n\n// ------------------\n// .enable / .disable\n// ------------------\n\ndocument\n  .getElementById('toggle-state-button')\n  .addEventListener('click', async () => {\n    // Use the isEnabled method to read the action's current state.\n    let actionEnabled = await chrome.action.isEnabled();\n    // when the button is clicked negate the state\n    if (actionEnabled) {\n      chrome.action.disable();\n    } else {\n      chrome.action.enable();\n    }\n  });\n\ndocument\n  .getElementById('popup-options')\n  .addEventListener('change', async (event) => {\n    const popup = event.target.value;\n    await chrome.action.setPopup({ popup });\n\n    // Show the updated popup path\n    await getCurrentPopup();\n  });\n\nasync function getCurrentPopup() {\n  const popup = await chrome.action.getPopup({});\n  document.getElementById('current-popup-value').value = popup;\n  return popup;\n}\n\nasync function showCurrentPage() {\n  const popup = await getCurrentPopup();\n  let pathname = '';\n  if (popup) {\n    pathname = new URL(popup).pathname;\n  }\n\n  const options = document.getElementById('popup-options');\n  const option = options.querySelector(`option[value=\"${pathname}\"]`);\n  option.selected = true;\n}\n\n// Populate popup inputs on page load\nshowCurrentPage();\n\n// ----------\n// .onClicked\n// ----------\n\n// If a popup is specified, our on click handler won't be called. We declare it here rather than in\n// the `onclicked-button` handler to prevent the user from accidentally registering multiple\n// onClicked listeners.\nchrome.action.onClicked.addListener(() => {\n  chrome.tabs.create({ url: 'https://html5zombo.com/' });\n});\n\ndocument\n  .getElementById('onclicked-button')\n  .addEventListener('click', async () => {\n    // Our listener will only receive the action's click event after clear out the popup URL\n    await chrome.action.setPopup({ popup: '' });\n    await showCurrentPage();\n  });\n\ndocument\n  .getElementById('onclicked-reset-button')\n  .addEventListener('click', async () => {\n    await chrome.action.setPopup({ popup: 'popups/popup.html' });\n    await showCurrentPage();\n  });\n\n// ----------\n// badge text\n// ----------\n\nasync function showBadgeText() {\n  const text = await chrome.action.getBadgeText({});\n  document.getElementById('current-badge-text').value = text;\n}\n\n// Populate badge text inputs on page load\nshowBadgeText();\n\ndocument\n  .getElementById('badge-text-input')\n  .addEventListener('input', async (event) => {\n    const text = event.target.value;\n    await chrome.action.setBadgeText({ text });\n\n    showBadgeText();\n  });\n\ndocument\n  .getElementById('clear-badge-button')\n  .addEventListener('click', async () => {\n    await chrome.action.setBadgeText({ text: '' });\n\n    showBadgeText();\n  });\n\n// --------------------------\n// get/set badge text color\n// --------------------------\nasync function showBadgeTextColor() {\n  const color = await chrome.action.getBadgeTextColor({});\n  document.getElementById('current-badge-txt-color').value = JSON.stringify(\n    color,\n    null,\n    0\n  );\n}\n\nshowBadgeTextColor();\n\ndocument\n  .getElementById('set-badge-txt-color-button')\n  .addEventListener('click', async () => {\n    // To show off this method, we must first make sure the badge has text\n    let currentText = await chrome.action.getBadgeText({});\n    if (!currentText) {\n      chrome.action.setBadgeText({ text: 'Test' });\n      showBadgeText();\n    }\n\n    // Next, generate a random RGBA color\n    const color = [0, 0, 0].map(() => Math.floor(Math.random() * 255));\n\n    // Use the default background color ~10% of the time.\n    //\n    // NOTE: Alpha color cannot be set due to crbug.com/1184905. At the time of writing (Chrome 89),\n    // an alpha value of 0 sets the default color while a value of 1-255 will make the RGB color\n    // fully opaque.\n    if (Math.random() < 0.1) {\n      color.push(0);\n    } else {\n      color.push(255);\n    }\n\n    chrome.action.setBadgeTextColor({ color });\n    showBadgeTextColor();\n  });\n\ndocument\n  .getElementById('reset-badge-txt-color-button')\n  .addEventListener('click', async () => {\n    chrome.action.setBadgeTextColor({ color: '#000000' });\n    showBadgeTextColor();\n  });\n\n// ----------------------\n// badge background color\n// ----------------------\n\nasync function showBadgeColor() {\n  const color = await chrome.action.getBadgeBackgroundColor({});\n  document.getElementById('current-badge-bg-color').value = JSON.stringify(\n    color,\n    null,\n    0\n  );\n}\n\n// Populate badge background color inputs on page load\nshowBadgeColor();\n\ndocument\n  .getElementById('set-badge-background-color-button')\n  .addEventListener('click', async () => {\n    // To show off this method, we must first make sure the badge has text\n    let currentText = await chrome.action.getBadgeText({});\n    if (!currentText) {\n      chrome.action.setBadgeText({ text: 'hi :)' });\n      showBadgeText();\n    }\n\n    // Next, generate a random RGBA color\n    const color = [0, 0, 0].map(() => Math.floor(Math.random() * 255));\n\n    // Use the default background color ~10% of the time.\n    //\n    // NOTE: Alpha color cannot be set due to crbug.com/1184905. At the time of writing (Chrome 89),\n    // an alpha value of 0 sets the default color while a value of 1-255 will make the RGB color\n    // fully opaque.\n    if (Math.random() < 0.1) {\n      color.push(0);\n    } else {\n      color.push(255);\n    }\n\n    chrome.action.setBadgeBackgroundColor({ color });\n    showBadgeColor();\n  });\n\ndocument\n  .getElementById('reset-badge-background-color-button')\n  .addEventListener('click', async () => {\n    chrome.action.setBadgeBackgroundColor({ color: [0, 0, 0, 0] });\n    showBadgeColor();\n  });\n\n// -----------\n// action icon\n// -----------\n\nconst EMOJI = ['confetti', 'suit', 'bow', 'dog', 'skull', 'yoyo', 'cat'];\n\nlet lastIconIndex = 0;\ndocument\n  .getElementById('set-icon-button')\n  .addEventListener('click', async () => {\n    // Clear out the badge text in order to make the icon change easier to see\n    chrome.action.setBadgeText({ text: '' });\n\n    // Randomly pick a new icon\n    let index = lastIconIndex;\n    index = Math.floor(Math.random() * EMOJI.length);\n    if (index === lastIconIndex) {\n      // Dupe detected! Increment the index & modulo to make sure we don't go out of bounds\n      index = (index + 1) % EMOJI.length;\n    }\n    const emojiFile = `images/emoji-${EMOJI[index]}.png`;\n    lastIconIndex = index;\n\n    // There are easier ways for a page to extract an image's imageData, but the approach used here\n    // works in both extension pages and service workers.\n    const response = await fetch(chrome.runtime.getURL(emojiFile));\n    const blob = await response.blob();\n    const imageBitmap = await createImageBitmap(blob);\n    const osc = new OffscreenCanvas(imageBitmap.width, imageBitmap.height);\n    let ctx = osc.getContext('2d');\n    ctx.drawImage(imageBitmap, 0, 0);\n    const imageData = ctx.getImageData(0, 0, osc.width, osc.height);\n\n    chrome.action.setIcon({ imageData });\n  });\n\ndocument.getElementById('reset-icon-button').addEventListener('click', () => {\n  const manifest = chrome.runtime.getManifest();\n  chrome.action.setIcon({ path: manifest.action.default_icon });\n});\n\n// -------------\n// get/set title\n// -------------\n\nconst titleInput = document.getElementById('title-input');\ntitleInput.addEventListener(\n  'input',\n  debounce(200, async (event) => {\n    const title = event.target.value;\n    chrome.action.setTitle({ title });\n\n    showActionTitle();\n  })\n);\n\ndocument\n  .getElementById('reset-title-button')\n  .addEventListener('click', async () => {\n    const manifest = chrome.runtime.getManifest();\n    let title = manifest.action.default_title;\n\n    chrome.action.setTitle({ title });\n\n    showActionTitle();\n  });\n\nasync function showActionTitle() {\n  let title = await chrome.action.getTitle({});\n\n  // If empty, the title falls back to the name of the extension\n  if (title === '') {\n    // … which we can get from the extension's manifest\n    const manifest = chrome.runtime.getManifest();\n    title = manifest.name;\n  }\n\n  document.getElementById('current-title').value = title;\n}\n\n// Populate action title inputs on page load\nshowActionTitle();\n"
  },
  {
    "path": "api-samples/action/manifest.json",
    "content": "{\n  \"name\": \"Action API Demo\",\n  \"version\": \"1.0\",\n  \"description\": \"Uses the Action API to change the badge text, icon, hover text, or popup page.\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"action\": {\n    \"default_title\": \"Default Title\",\n    \"default_popup\": \"popups/popup.html\",\n    \"default_icon\": {\n      \"32\": \"icons/32.png\",\n      \"72\": \"icons/72.png\",\n      \"128\": \"icons/128.png\",\n      \"512\": \"icons/512.png\"\n    }\n  },\n  \"icons\": {\n    \"32\": \"icons/32.png\",\n    \"72\": \"icons/72.png\",\n    \"128\": \"icons/128.png\",\n    \"512\": \"icons/512.png\"\n  }\n}\n"
  },
  {
    "path": "api-samples/action/popups/a.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Document</title>\n    <style>\n      .center {\n        min-height: 100px;\n        min-width: 200px;\n        display: grid;\n        flex-direction: column;\n        align-items: center;\n        justify-content: center;\n        gap: 1ch;\n        background-color: salmon;\n      }\n      .text {\n        font-size: 2rem;\n        font-weight: bold;\n        color: white;\n      }\n    </style>\n  </head>\n  <body>\n    <h2>Action API Demo</h2>\n    <div class=\"center\">\n      <span class=\"text\">A</span>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/action/popups/b.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Document</title>\n    <style>\n      .center {\n        min-height: 100px;\n        min-width: 200px;\n        display: grid;\n        flex-direction: column;\n        align-items: center;\n        justify-content: center;\n        gap: 1ch;\n        background-color: royalblue;\n      }\n      .text {\n        font-size: 2rem;\n        font-weight: bold;\n        color: white;\n      }\n    </style>\n  </head>\n  <body>\n    <h2>Action API Demo</h2>\n    <div class=\"center\">\n      <span class=\"text\">B</span>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/action/popups/popup.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Document</title>\n    <style>\n      .center {\n        min-height: 100px;\n        min-width: 200px;\n        display: grid;\n        flex-direction: column;\n        align-items: center;\n        justify-content: center;\n        gap: 1ch;\n        background-color: lightseagreen;\n      }\n      .text {\n        font-size: 2rem;\n        font-weight: bold;\n        color: white;\n      }\n    </style>\n  </head>\n  <body>\n    <h2>Action API Demo</h2>\n    <div class=\"center\">\n      <span class=\"text\">Hello, world!</span>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/action/third-party/awsm/awsm.css",
    "content": "@charset \"UTF-8\";\n/*!\n * awsm.css v3.0.7 (https://igoradamenko.github.io/awsm.css/)\n * Copyright 2015 Igor Adamenko <mail@igoradamenko.com> (https://igoradamenko.com)\n * Licensed under MIT (https://github.com/igoradamenko/awsm.css/blob/master/LICENSE.md)\n */\nhtml{font-family:system-ui,-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen,Ubuntu,Cantarell,\"PT Sans\",\"Open Sans\",\"Fira Sans\",\"Droid Sans\",\"Helvetica Neue\",Helvetica,Arial,sans-serif;font-size:100%;line-height:1.4;background:#fff;color:#000;-webkit-overflow-scrolling:touch}body{margin:1.2em;font-size:1rem}@media (min-width:20rem){body{font-size:calc(1rem + .00625*(100vw - 20rem))}}@media (min-width:40rem){body{font-size:1.125rem}}body article,body footer,body header,body main{position:relative;max-width:40rem;margin:0 auto}body>header{margin-bottom:3.5em}body>header h1{margin:0;font-size:1.5em}body>header p{margin:0;font-size:.85em}body>footer{margin-top:6em;padding-bottom:1.5em;text-align:center;font-size:.8rem;color:#aaa}details,nav{margin:1em 0}nav ul{list-style:none;margin:0;padding:0}nav li{display:inline-block;margin-right:1em;margin-bottom:.25em}nav li:last-child{margin-right:0}a,nav a:visited{color:#0064c1}article header h1 a:visited:hover,article header h2 a:visited:hover,nav a:hover{color:#f00000}ol,ul{margin-top:0;padding-top:0;padding-left:2.5em}article header h1+p,article header h2+p,ol li+li,ul li+li{margin-top:.25em}ol li>details,ul li>details{margin:0}p{margin:1em 0;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto}aside:first-child,form legend:first-child+label,p:first-child{margin-top:0}aside:last-child,p:last-child{margin-bottom:0}p+ol,p+ul{margin-top:-.75em}p img,p picture{float:right;margin-bottom:.5em;margin-left:.5em}p picture img{float:none;margin:0}blockquote,dd{padding-left:2.5em}dd{margin-bottom:1em;margin-left:0}dt{font-weight:700}blockquote{margin:0}aside{margin:.5em 0;font-style:italic;color:#aaa}@media (min-width:65rem){aside{position:absolute;right:-12.5rem;width:9.375rem;max-width:9.375rem;margin:0;padding-left:.5em;font-size:.8em;border-left:1px solid #f2f2f2}}section+section{margin-top:2em}h1,h2,h3,h4,h5,h6{margin:1.25em 0 0;line-height:1.2}h1:focus>a[href^=\"#\"][id]:empty,h1:hover>a[href^=\"#\"][id]:empty,h2:focus>a[href^=\"#\"][id]:empty,h2:hover>a[href^=\"#\"][id]:empty,h3:focus>a[href^=\"#\"][id]:empty,h3:hover>a[href^=\"#\"][id]:empty,h4:focus>a[href^=\"#\"][id]:empty,h4:hover>a[href^=\"#\"][id]:empty,h5:focus>a[href^=\"#\"][id]:empty,h5:hover>a[href^=\"#\"][id]:empty,h6:focus>a[href^=\"#\"][id]:empty,h6:hover>a[href^=\"#\"][id]:empty{opacity:1}figure+p,h1+details,h1+p,h2+details,h2+p,h3+details,h3+p,h4+details,h4+p,h5+details,h5+p,h6+details,h6+p{margin-top:.5em}h1>a[href^=\"#\"][id]:empty,h2>a[href^=\"#\"][id]:empty,h3>a[href^=\"#\"][id]:empty,h4>a[href^=\"#\"][id]:empty,h5>a[href^=\"#\"][id]:empty,h6>a[href^=\"#\"][id]:empty{position:absolute;left:-.65em;opacity:0;text-decoration:none;font-weight:400;line-height:1;color:#aaa}@media (min-width:40rem){h1>a[href^=\"#\"][id]:empty,h2>a[href^=\"#\"][id]:empty,h3>a[href^=\"#\"][id]:empty,h4>a[href^=\"#\"][id]:empty,h5>a[href^=\"#\"][id]:empty,h6>a[href^=\"#\"][id]:empty{left:-.8em}}h1>a[href^=\"#\"][id]:empty:focus,h1>a[href^=\"#\"][id]:empty:hover,h1>a[href^=\"#\"][id]:empty:target,h2>a[href^=\"#\"][id]:empty:focus,h2>a[href^=\"#\"][id]:empty:hover,h2>a[href^=\"#\"][id]:empty:target,h3>a[href^=\"#\"][id]:empty:focus,h3>a[href^=\"#\"][id]:empty:hover,h3>a[href^=\"#\"][id]:empty:target,h4>a[href^=\"#\"][id]:empty:focus,h4>a[href^=\"#\"][id]:empty:hover,h4>a[href^=\"#\"][id]:empty:target,h5>a[href^=\"#\"][id]:empty:focus,h5>a[href^=\"#\"][id]:empty:hover,h5>a[href^=\"#\"][id]:empty:target,h6>a[href^=\"#\"][id]:empty:focus,h6>a[href^=\"#\"][id]:empty:hover,h6>a[href^=\"#\"][id]:empty:target{opacity:1;box-shadow:none;color:#000}h1>a[href^=\"#\"][id]:empty:target:focus,h2>a[href^=\"#\"][id]:empty:target:focus,h3>a[href^=\"#\"][id]:empty:target:focus,h4>a[href^=\"#\"][id]:empty:target:focus,h5>a[href^=\"#\"][id]:empty:target:focus,h6>a[href^=\"#\"][id]:empty:target:focus{outline:0}h1>a[href^=\"#\"][id]:empty::before,h2>a[href^=\"#\"][id]:empty::before,h3>a[href^=\"#\"][id]:empty::before,h4>a[href^=\"#\"][id]:empty::before,h5>a[href^=\"#\"][id]:empty::before,h6>a[href^=\"#\"][id]:empty::before{content:\"§ \"}h1{font-size:2.5em}h2{font-size:1.75em}h3{font-size:1.25em}h4{font-size:1.15em}a abbr,h5,h6{font-size:1em}h6{margin-top:1em}article+article{margin-top:4em}article header p{font-size:.6em;color:#aaa}article header p+h1,article header p+h2{margin-top:-.25em}article header h1 a,article header h2 a{color:#000}article header h1 a:visited,article header h2 a:visited,h6,legend{color:#aaa}article>footer{margin-top:1.5em;font-size:.85em}a:visited{color:#8d39d0}a:active,a:hover{outline-width:0}a:hover{color:#f00000}abbr{margin-right:-.075em;text-decoration:none;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none;letter-spacing:.075em;font-size:.9em}img,picture{display:block;max-width:100%;margin:0 auto}audio,video{width:100%;max-width:100%}figure{margin:1em 0 .5em;padding:0}figure figcaption{opacity:.65;font-size:.85em}table{display:inline-block;border-spacing:0;border-collapse:collapse;overflow-x:auto;max-width:100%;text-align:left;vertical-align:top;background:linear-gradient(rgba(0,0,0,.15) 0%,rgba(0,0,0,.15) 100%) 0 0,linear-gradient(rgba(0,0,0,.15) 0%,rgba(0,0,0,.15) 100%) 100% 0;background-attachment:scroll,scroll;background-size:1px 100%,1px 100%;background-repeat:no-repeat,no-repeat}table caption{font-size:.9em;background:#fff}table td,table th{padding:.35em .75em;vertical-align:top;font-size:.9em;border:1px solid #f2f2f2;border-top:0;border-left:0}table td:first-child,table th:first-child{padding-left:0;background-image:linear-gradient(to right,#fff 50%,rgba(255,255,255,0) 100%);background-size:2px 100%;background-repeat:no-repeat}table td:last-child,table th:last-child{padding-right:0;border-right:0;background-image:linear-gradient(to left,#fff 50%,rgba(255,255,255,0) 100%);background-position:100% 0;background-size:2px 100%;background-repeat:no-repeat}table td:only-child,table th:only-child{background-image:linear-gradient(to right,#fff 50%,rgba(255,255,255,0) 100%),linear-gradient(to left,#fff 50%,rgba(255,255,255,0) 100%);background-position:0 0,100% 0;background-size:2px 100%,2px 100%;background-repeat:no-repeat,no-repeat}table th{line-height:1.2}form{margin-right:auto;margin-left:auto}@media (min-width:40rem){form{max-width:80%}}form label,form select,output{display:block}form label:not(:first-child){margin-top:1em}form p label{display:inline}form p label+label{margin-left:1em}form input[type],form select,form textarea{margin-bottom:1em}form input[type=checkbox],form input[type=radio]{margin-bottom:0}button,fieldset{margin:0;border:1px solid #aaa}fieldset{padding:.5em 1em}button{outline:0;box-sizing:border-box;height:2em;padding:calc(.25em - 1px) .5em;font-family:inherit;font-size:1em;border-radius:2px;background:#fff;display:inline-block;width:auto;background:#f2f2f2;color:#000;cursor:pointer}button:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus,input[type^=date]:focus,select:focus{border:1px solid #000}button:not([disabled]):hover,input[type=button]:not([disabled]):hover,input[type=file]:not([disabled]):hover,input[type=reset]:not([disabled]):hover,input[type=submit]:not([disabled]):hover,select:not([disabled]):hover{border:1px solid #000}button:active,select:active{background-color:#aaa}button[disabled],select[disabled]{color:#aaa;cursor:not-allowed}select{outline:0;box-sizing:border-box;height:2em;margin:0;padding:calc(.25em - 1px) .5em;font-family:inherit;font-size:1em;border:1px solid #aaa;border-radius:2px;background:#fff;display:inline-block;width:auto;background:#f2f2f2;color:#000;cursor:pointer;padding-right:1.2em;background-position:top 55% right .35em;background-size:.5em;background-repeat:no-repeat;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 2'%3E%3Cpath fill='rgb(170, 170, 170)' fill-rule='nonzero' d='M1.5 2L3 0H0z'/%3E%3C/svg%3E\")}select:not([disabled]):focus,select:not([disabled]):hover{background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 2'%3E%3Cpath fill='rgb(0, 0, 0)' fill-rule='nonzero' d='M1.5 2L3 0H0z'/%3E%3C/svg%3E\")}input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],input[type^=date]{outline:0;box-sizing:border-box;height:2em;margin:0;padding:calc(.25em - 1px) .5em;font-family:inherit;font-size:1em;border:1px solid #aaa;border-radius:2px;background:#fff;color:#000;display:block;width:100%;line-height:calc(2em - 1px*2 - (.25em - 1px)*2);-webkit-appearance:none;-moz-appearance:none;appearance:none}input[type=email]::-moz-placeholder,input[type=month]::-moz-placeholder,input[type=number]::-moz-placeholder,input[type=password]::-moz-placeholder,input[type=search]::-moz-placeholder,input[type=tel]::-moz-placeholder,input[type=text]::-moz-placeholder,input[type=time]::-moz-placeholder,input[type=url]::-moz-placeholder,input[type=week]::-moz-placeholder,input[type^=date]::-moz-placeholder{color:#aaa}input[type=email]::-webkit-input-placeholder,input[type=month]::-webkit-input-placeholder,input[type=number]::-webkit-input-placeholder,input[type=password]::-webkit-input-placeholder,input[type=search]::-webkit-input-placeholder,input[type=tel]::-webkit-input-placeholder,input[type=text]::-webkit-input-placeholder,input[type=time]::-webkit-input-placeholder,input[type=url]::-webkit-input-placeholder,input[type=week]::-webkit-input-placeholder,input[type^=date]::-webkit-input-placeholder{color:#aaa}input[type=email]:-ms-input-placeholder,input[type=month]:-ms-input-placeholder,input[type=number]:-ms-input-placeholder,input[type=password]:-ms-input-placeholder,input[type=search]:-ms-input-placeholder,input[type=tel]:-ms-input-placeholder,input[type=text]:-ms-input-placeholder,input[type=time]:-ms-input-placeholder,input[type=url]:-ms-input-placeholder,input[type=week]:-ms-input-placeholder,input[type^=date]:-ms-input-placeholder{color:#aaa}input[type=button],input[type=reset],input[type=submit]{outline:0;box-sizing:border-box;height:2em;margin:0;padding:calc(.25em - 1px) .5em;font-family:inherit;font-size:1em;border:1px solid #aaa;border-radius:2px;background:#fff;display:inline-block;width:auto;background:#f2f2f2;color:#000;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none}input[type=button]:focus,input[type=reset]:focus,input[type=submit]:focus{border:1px solid #000}input[type=button]:active,input[type=reset]:active,input[type=submit]:active{background-color:#aaa}input[type=button][disabled],input[type=reset][disabled],input[type=submit][disabled]{color:#aaa;cursor:not-allowed}input[type=color]{outline:0;box-sizing:border-box;height:2em;margin:0;padding:calc(.25em - 1px) .5em;font-family:inherit;font-size:1em;border:1px solid #aaa;border-radius:2px;background:#fff;color:#000;display:block;line-height:calc(2em - 1px*2 - (.25em - 1px)*2);-webkit-appearance:none;-moz-appearance:none;appearance:none;width:6em}input[type=color]:focus{border:1px solid #000}input[type=color]::-moz-placeholder,textarea::-moz-placeholder{color:#aaa}input[type=color]::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#aaa}input[type=color]:-ms-input-placeholder{color:#aaa}input[type=color]:hover{border:1px solid #000}input[type=file]{outline:0;box-sizing:border-box;margin:0;padding:calc(.25em - 1px) .5em;font-family:inherit;border:1px solid #aaa;border-radius:2px;background:#fff;background:#f2f2f2;color:#000;cursor:pointer;display:block;width:100%;height:auto;padding:.75em .5em;font-size:12px;line-height:1}input[type=file]:focus,textarea:focus{border:1px solid #000}input[type=file]:active{background-color:#aaa}input[type=file][disabled]{color:#aaa;cursor:not-allowed}input[type=checkbox],input[type=radio]{margin:-.2em .75em 0 0;vertical-align:middle}textarea{outline:0;box-sizing:border-box;margin:0;padding:calc(.25em - 1px) .5em;font-family:inherit;font-size:1em;border:1px solid #aaa;border-radius:2px;background:#fff;color:#000;display:block;width:100%;line-height:calc(2em - 1px*2 - (.25em - 1px)*2);-webkit-appearance:none;-moz-appearance:none;appearance:none;height:4.5em;resize:vertical;padding-top:.5em;padding-bottom:.5em}textarea:-ms-input-placeholder{color:#aaa}code,kbd,samp,var{font-family:Consolas,\"Lucida Console\",Monaco,monospace;font-style:normal}pre{overflow-x:auto;font-size:.8em;background:linear-gradient(rgba(0,0,0,.15) 0%,rgba(0,0,0,.15) 100%) 0 0,linear-gradient(rgba(0,0,0,.15) 0%,rgba(0,0,0,.15) 100%) 100% 0;background-attachment:scroll,scroll;background-size:1px 100%,1px 100%;background-repeat:no-repeat,no-repeat}pre>code,summary{display:inline-block}pre>code{overflow-x:visible;box-sizing:border-box;min-width:100%;border-right:3px solid #fff;border-left:1px solid #fff}hr{height:1px;margin:2em 0;border:0;background:#f2f2f2}details[open]{padding-bottom:.5em;border-bottom:1px solid #f2f2f2}summary{font-weight:700;border-bottom:1px dashed;cursor:pointer}noscript{color:#d00000}::selection{background:rgba(0,100,193,.25)}\n"
  },
  {
    "path": "api-samples/alarms/README.md",
    "content": "# chrome.alarms\n\nThis sample demonstrates the `chrome.alarms` API by allowing the user to set alarms using an extension page.\n\n## Overview\n\nThe extension calls `chrome.alarms.create()` to set an initial alarm that is displayed on the extension page. More alarms can be set with user input.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extension to the taskbar to access the action button.\n4. Open the extension popup by clicking the action button and interact with the UI.\n"
  },
  {
    "path": "api-samples/alarms/background.js",
    "content": "// Copyright 2021 Google LLC\n//\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file or at\n// https://developers.google.com/open-source/licenses/bsd\n\n// Initialize the demo on install\nchrome.runtime.onInstalled.addListener(({ reason }) => {\n  if (reason !== chrome.runtime.OnInstalledReason.INSTALL) {\n    return;\n  }\n\n  openDemoTab();\n\n  // Create an alarm so we have something to look at in the demo\n  chrome.alarms.create('demo-default-alarm', {\n    delayInMinutes: 1,\n    periodInMinutes: 1\n  });\n});\n\nchrome.action.onClicked.addListener(openDemoTab);\n\nfunction openDemoTab() {\n  chrome.tabs.create({ url: 'index.html' });\n}\n"
  },
  {
    "path": "api-samples/alarms/bg-wrapper.js",
    "content": "// Copyright 2021 Google LLC\n//\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file or at\n// https://developers.google.com/open-source/licenses/bsd\n\ntry {\n  importScripts('background.js');\n} catch (error) {\n  console.error(error);\n}\n"
  },
  {
    "path": "api-samples/alarms/index.css",
    "content": ":root {\n  --card-min-width: 20em;\n  --card-max-width: 25em;\n}\n\n* {\n  box-sizing: border-box;\n}\n\nbody {\n  font-size: 16px;\n}\n\n/* Alarm creation form */\n\n.create-alarm {\n  display: grid;\n  grid-template-columns: minmax(100px, 1fr) minmax(150px, 2fr);\n  column-gap: 20px;\n  row-gap: 10px;\n\n  max-width: 500px;\n  margin: 0 auto;\n}\n\n.create-alarm__label {\n  text-align: right;\n  font-weight: bold;\n}\n\n.create-alarm__submit {\n  grid-column: 1 / -1;\n}\n\n/* Alarm list and log wrapper */\n\n.col-2 {\n  display: grid;\n  grid-template-columns: 1fr 1fr;\n  column-gap: 10px;\n}\n\n.alarm-display,\n.alarm-log {\n  min-height: 2em;\n  padding: 0.5em;\n  background-color: hsl(0, 0%, 95%);\n  border: 1px solid hsl(0, 0%, 80%);\n  border-radius: 4px;\n  padding: 0;\n}\n\n.alarm-log {\n  white-space: pre-wrap;\n}\n\n.alarm-log > * {\n  padding: 0.5em;\n}\n\n.alarm-log > *:not(:first-child) {\n  border-top: 1px solid hsl(0, 0%, 70%);\n}\n\n.display-buttons {\n  display: inline-block;\n}\n\n.alarm-row {\n  padding: 0.5em;\n  position: relative;\n  border-top: 1px solid transparent;\n  border-bottom: 1px solid transparent;\n}\n\n.alarm-row:hover,\n.alarm-log > *:hover {\n  background: hsl(190, 20%, 90%);\n}\n\n.alarm-row:not(:first-child) {\n  margin-top: -1px;\n}\n\n.alarm-row:not(:first-child):hover {\n  border-top: 1px solid hsl(0, 0%, 70%);\n}\n\n.alarm-row:not(:last-child):hover {\n  border-bottom: 1px solid hsl(0, 0%, 70%);\n}\n\n.alarm-row__cancel-button {\n  position: absolute;\n  top: 0.5em;\n  right: 0.5em;\n}\n"
  },
  {
    "path": "api-samples/alarms/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Document</title>\n    <link rel=\"stylesheet\" href=\"index.css\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <section>\n      <h2>Create Alarm</h2>\n      <form class=\"create-alarm\">\n        <div class=\"create-alarm__label\">Name</div>\n        <div class=\"create-alarm__value\">\n          <input type=\"text\" name=\"alarm-name\" value=\"my-alarm\" />\n        </div>\n\n        <div class=\"create-alarm__label\">Initial delay *</div>\n        <div class=\"create-alarm__value\">\n          <input type=\"number\" step=\"0.1\" name=\"time-value\" min=\"0\" value=\"1\" />\n\n          <select name=\"time-format\">\n            <option id=\"format-minutes\" value=\"min\" selected>minutes</option>\n            <option id=\"format-ms\" value=\"ms\">milliseconds</option>\n          </select>\n        </div>\n\n        <div class=\"create-alarm__label\">Repetition period *</div>\n        <div class=\"create-alarm__value\">\n          <input type=\"number\" step=\"0.1\" min=\"0\" name=\"period\" value=\"0\" />\n          minutes <br /><i\n            >Non-zero values create a repeating alarm that repeats every\n            period.</i\n          >\n        </div>\n\n        <div class=\"create-alarm__label\">*</div>\n        <div class=\"create-alarm__value\">\n          <i\n            >Can be set to &lt; 1 min in an unpacked extension, but not in a\n            distributed CRX file.</i\n          >\n        </div>\n\n        <button type=\"submit\" class=\"create-alarm__submit\">Submit</button>\n      </form>\n    </section>\n\n    <section class=\"col-2\">\n      <section class=\"\">\n        <h2>\n          Current Alarms\n          <div class=\"display-buttons\">\n            <button id=\"clear-display\">Cancel all alarms</button>\n            <button\n              id=\"refresh-display\"\n              title=\"Clear display and re-recreate alarm UI\"\n            >\n              Refresh\n            </button>\n          </div>\n        </h2>\n\n        <pre class=\"alarm-display\"></pre>\n      </section>\n\n      <section>\n        <h2>Alarm log</h2>\n        <pre class=\"alarm-log\"></pre>\n      </section>\n    </section>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/alarms/index.js",
    "content": "// Copyright 2021 Google LLC\n//\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file or at\n// https://developers.google.com/open-source/licenses/bsd\n\nconst display = document.querySelector('.alarm-display');\nconst log = document.querySelector('.alarm-log');\nconst form = document.querySelector('.create-alarm');\nconst clearButton = document.getElementById('clear-display');\nconst refreshButton = document.getElementById('refresh-display');\n\n// DOM event bindings\n\n// Alarm display buttons\n\nclearButton.addEventListener('click', () => manager.cancelAllAlarms());\nrefreshButton.addEventListener('click', () => manager.refreshDisplay());\n\n// New alarm form\n\nform.addEventListener('submit', (event) => {\n  event.preventDefault();\n  const formData = new FormData(form);\n  const data = Object.fromEntries(formData);\n\n  // Extract form values\n  const name = data['alarm-name'];\n  const delay = Number.parseFloat(data['time-value']);\n  const delayFormat = data['time-format'];\n  const period = Number.parseFloat(data['period']);\n\n  // Prepare alarm info for creation call\n  const alarmInfo = {};\n\n  if (delayFormat === 'ms') {\n    // Specified in milliseconds, use `when` property\n    alarmInfo.when = Date.now() + delay;\n  } else if (delayFormat === 'min') {\n    // specified in minutes, use `delayInMinutes` property\n    alarmInfo.delayInMinutes = delay;\n  }\n\n  if (period) {\n    alarmInfo.periodInMinutes = period;\n  }\n\n  // Create the alarm – this uses the same signature as chrome.alarms.create\n  manager.createAlarm(name, alarmInfo);\n});\n\nclass AlarmManager {\n  constructor(display, log) {\n    this.displayElement = display;\n    this.logElement = log;\n\n    this.logMessage('Manager: initializing demo');\n\n    this.displayElement.addEventListener('click', this.handleCancelAlarm);\n    chrome.alarms.onAlarm.addListener(this.handleAlarm);\n  }\n\n  logMessage(message) {\n    const date = new Date();\n    const pad = (val, len = 2) => val.toString().padStart(len, '0');\n    const h = pad(date.getHours());\n    const m = pad(date.getMinutes());\n    const s = pad(date.getSeconds());\n    const ms = pad(date.getMilliseconds(), 3);\n    const time = `${h}:${m}:${s}.${ms}`;\n\n    const logLine = document.createElement('div');\n    logLine.textContent = `[${time}] ${message}`;\n\n    // Log events in reverse chronological order\n    this.logElement.insertBefore(logLine, this.logElement.firstChild);\n  }\n\n  handleAlarm = async (alarm) => {\n    const json = JSON.stringify(alarm);\n    this.logMessage(`Alarm \"${alarm.name}\" fired\\n${json}}`);\n    await this.refreshDisplay();\n  };\n\n  handleCancelAlarm = async (event) => {\n    if (!event.target.classList.contains('alarm-row__cancel-button')) {\n      return;\n    }\n\n    const name = event.target.parentElement.dataset.name;\n    await this.cancelAlarm(name);\n    await this.refreshDisplay();\n  };\n\n  async cancelAlarm(name) {\n    return chrome.alarms.clear(name, (wasCleared) => {\n      if (wasCleared) {\n        this.logMessage(`Manager: canceled alarm \"${name}\"`);\n      } else {\n        this.logMessage(`Manager: could not canceled alarm \"${name}\"`);\n      }\n    });\n  }\n\n  // Thin wrapper around alarms.create to log creation event\n  createAlarm(name, alarmInfo) {\n    chrome.alarms.create(name, alarmInfo);\n    const json = JSON.stringify(alarmInfo, null, 2).replace(/\\s+/g, ' ');\n    this.logMessage(`Created \"${name}\"\\n${json}`);\n    this.refreshDisplay();\n  }\n\n  renderAlarm(alarm, isLast) {\n    const alarmEl = document.createElement('div');\n    alarmEl.classList.add('alarm-row');\n    alarmEl.dataset.name = alarm.name;\n    alarmEl.textContent = JSON.stringify(alarm, 0, 2) + (isLast ? '' : ',');\n\n    const cancelButton = document.createElement('button');\n    cancelButton.classList.add('alarm-row__cancel-button');\n    cancelButton.textContent = 'cancel';\n    alarmEl.appendChild(cancelButton);\n\n    this.displayElement.appendChild(alarmEl);\n  }\n\n  async cancelAllAlarms() {\n    return chrome.alarms.clearAll((wasCleared) => {\n      if (wasCleared) {\n        this.logMessage(`Manager: canceled all alarms\"`);\n      } else {\n        this.logMessage(`Manager: could not canceled all alarms`);\n      }\n    });\n  }\n\n  async populateDisplay() {\n    return chrome.alarms.getAll((alarms) => {\n      for (const [index, alarm] of alarms.entries()) {\n        const isLast = index === alarms.length - 1;\n        this.renderAlarm(alarm, isLast);\n      }\n    });\n  }\n\n  // Simple locking mechanism to prevent multiple concurrent refreshes from rendering duplicate\n  // entries in the alarms list\n  #refreshing = false;\n\n  async refreshDisplay() {\n    if (this.#refreshing) {\n      return;\n    } // refresh in progress, bail\n\n    this.#refreshing = true; // acquire lock\n    try {\n      await this.clearDisplay();\n      await this.populateDisplay();\n    } finally {\n      this.#refreshing = false; // release lock\n    }\n  }\n\n  async clearDisplay() {\n    this.displayElement.textContent = '';\n  }\n}\n\nconst manager = new AlarmManager(display, log);\nmanager.refreshDisplay();\n"
  },
  {
    "path": "api-samples/alarms/manifest.json",
    "content": "{\n  \"name\": \"Alarms API Demo\",\n  \"version\": \"1.0\",\n  \"description\": \"Uses the chrome.alarms API to allow the user to set alarms using an extension page.\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"bg-wrapper.js\"\n  },\n  \"permissions\": [\"alarms\"],\n  \"action\": {}\n}\n"
  },
  {
    "path": "api-samples/bookmarks/README.md",
    "content": "# chrome.bookmarks\n\nThis sample demonstrates using the `chrome.bookmarks` API to search through, add, and delete bookmarks from the user's bookmark tree.\n\n## Overview\n\nThe full bookmark tree is displayed on the extension popup usin `chrome.bookmarks.getTree`.\n`chrome.bookmarks.create`is used to add 'https://www.google.com/' to the user's bookmarks. The `chrome.bookmarks.remove` and `chrome.bookmarks.search` APIs are used to find and delete any bookmarks that match 'https://www.google.com/'.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extension to the taskbar and open up the popup by clicking the action button.\n4. Experiment with adding and removing bookmarks using the buttons within the popup.\n"
  },
  {
    "path": "api-samples/bookmarks/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Bookmark Viewer\",\n  \"version\": \"1.0\",\n  \"description\": \"Uses the chrome.bookmarks API to search through, add, and delete bookmarks from the user's bookmark tree.\",\n  \"action\": {\n    \"default_popup\": \"popup.html\",\n    \"default_icon\": \"icon.png\"\n  },\n  \"permissions\": [\"bookmarks\"]\n}\n"
  },
  {
    "path": "api-samples/bookmarks/popup.html",
    "content": "<!--\n Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n\n<!doctype html>\n<html>\n  <head>\n    <title>Bookmark Viewer</title>\n    <script src=\"popup.js\" type=\"module\"></script>\n  </head>\n  <body>\n    <button id=\"addButton\">Add Bookmark</button>\n    <button id=\"removeButton\">Remove Added Bookmarks</button>\n    <ul id=\"bookmarkList\"></ul>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/bookmarks/popup.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Search the bookmarks when entering the search keyword.\n// Get the bookmarks and display them in the popup\nchrome.bookmarks.getTree((tree) => {\n  const bookmarkList = document.getElementById('bookmarkList');\n  displayBookmarks(tree[0].children, bookmarkList);\n});\n\n// Recursively display the bookmarks\nfunction displayBookmarks(nodes, parentNode) {\n  for (const node of nodes) {\n    // If the node is a bookmark, create a list item and append it to the parent node\n    if (node.url) {\n      const listItem = document.createElement('li');\n      listItem.textContent = node.title;\n      parentNode.appendChild(listItem);\n    }\n\n    // If the node has children, recursively display them\n    if (node.children) {\n      const sublist = document.createElement('ul');\n      parentNode.appendChild(sublist);\n      displayBookmarks(node.children, sublist);\n    }\n  }\n}\n\n// Add a bookmark for www.google.com\nfunction addBookmark() {\n  chrome.bookmarks.create(\n    {\n      title: 'Google',\n      url: 'https://www.google.com'\n    },\n    () => {\n      console.log('Bookmark added');\n      location.reload(); // Refresh the popup\n    }\n  );\n}\n\n// Remove the bookmark for www.google.com\nfunction removeBookmark() {\n  chrome.bookmarks.search({ url: 'https://www.google.com/' }, (results) => {\n    for (const result of results) {\n      if (result.url === 'https://www.google.com/') {\n        chrome.bookmarks.remove(result.id, () => {});\n      }\n    }\n    location.reload();\n  });\n}\n\n// Add click event listeners to the buttons\ndocument.getElementById('addButton').addEventListener('click', addBookmark);\ndocument\n  .getElementById('removeButton')\n  .addEventListener('click', removeBookmark);\n"
  },
  {
    "path": "api-samples/browsingData/README.md",
    "content": "# chrome.browsingData\n\nThis sample demonstrates using the `chrome.browsingData` API to clear the user's history without having to visit the history page.\n\n## Overview\n\nElements on the extension popup are used to take in user input, and `chrome.browsingData.remove` is implemented to delete the user's history.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extension to the taskbar to access the action button.\n4. Open the extension popup by clicking the action button and interact with the UI. Caution: This extension deletes your browser history.\n"
  },
  {
    "path": "api-samples/browsingData/manifest.json",
    "content": "{\n  \"name\": \"BrowsingData API: Basics\",\n  \"version\": \"1.2\",\n  \"description\": \"Uses the chrome.browsingData API to clear the user's history without requiring the user to visit the history page.\",\n  \"permissions\": [\"browsingData\"],\n  \"action\": {\n    \"default_icon\": \"icon.png\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/browsingData/popup.css",
    "content": "/**\n // Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n */\n\nbody {\n  margin: 5px 10px 10px;\n}\n\nh1 {\n  color: #53637D;\n  font: 26px/1.2 Helvetica, sans-serif;\n  font-size: 200%;\n  margin: 0;\n  padding-bottom: 4px;\n  text-shadow: white 0 1px 2px;\n}\n\nlabel {\n  color: #222;\n  font: 18px/1.4 Helvetica, sans-serif;\n  margin: 0.5em 0;\n  display: inline-block;\n}\n\nform {\n  transition: transform 0.25s ease;\n  width: 563px;\n}\n\nbutton {\n  display: block;\n  border-radius: 2px;\n  box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1);\n  -webkit-user-select: none;\n  background: -webkit-linear-gradient(#FAFAFA, #F4F4F4 40%, #E5E5E5);\n  border: 1px solid #AAA;\n  color: #444;\n  margin-bottom: 0;\n  min-width: 4em;\n  padding: 3px 12px;\n  margin-top: 0;\n  font-size: 1.1em;\n}\n\n.overlay {\n  display: block;\n  text-align: center;\n  position: absolute;\n  left: 50%;\n  top: 50%;\n  width: 500px;\n  padding: 20px;\n  margin: -40px 0 0 -270px;\n  opacity: 0;\n  background: rgba(0, 0, 0, 0.75);\n  border-radius: 5px;\n  color: #FFF;\n  font: 1.5em/1.2 Helvetica Neue, sans-serif;\n  transition: all 1.0s ease;\n  transform: scale(0);\n}\n\n.overlay a {\n  color:  #FFF;\n}\n\n.overlay.visible {\n  opacity: 1;\n  transform: scale(1);\n}\n"
  },
  {
    "path": "api-samples/browsingData/popup.html",
    "content": "<!--\n Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n\n<!doctype html>\n<html>\n  <head>\n    <title>Popup</title>\n    <link href=\"popup.css\" rel=\"stylesheet\" />\n    <script src=\"popup.js\"></script>\n  </head>\n  <body>\n    <h1>BrowsingData API Sample</h1>\n    <div role=\"main\">\n      <form>\n        <label for=\"timeframe\">Remove all browsing data from:</label>\n        <select id=\"timeframe\">\n          <option value=\"hour\">the past hour</option>\n          <option value=\"day\">the past day</option>\n          <option value=\"week\">the past week</option>\n          <option value=\"4weeks\">the past four weeks</option>\n          <option value=\"forever\">the beginning of time</option>\n        </select>\n        <button id=\"button\">OBLITERATE!</button>\n      </form>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/browsingData/popup.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nfunction parseMilliseconds(timeframe) {\n  let now = new Date().getTime();\n  let milliseconds = {\n    hour: 60 * 60 * 1000,\n    day: 24 * 60 * 60 * 1000,\n    week: 7 * 24 * 60 * 60 * 1000,\n    '4weeks': 4 * 7 * 24 * 60 * 60 * 1000\n  };\n\n  if (milliseconds[timeframe]) return now - milliseconds[timeframe];\n\n  if (timeframe === 'forever') return 0;\n\n  return null;\n}\n\nfunction buttonClicked(event) {\n  event.preventDefault();\n  const option = document.getElementById('timeframe');\n  let selectedTimeframe = option.value;\n  let removal_start = parseMilliseconds(selectedTimeframe);\n  if (removal_start == undefined) {\n    return null;\n  }\n  chrome.browsingData.remove(\n    { since: removal_start },\n    {\n      appcache: true,\n      cache: true,\n      cacheStorage: true,\n      cookies: true,\n      downloads: true,\n      fileSystems: true,\n      formData: true,\n      history: true,\n      indexedDB: true,\n      localStorage: true,\n      serverBoundCertificates: true,\n      serviceWorkers: true,\n      pluginData: true,\n      passwords: true,\n      webSQL: true\n    }\n  );\n  const success = document.createElement('div');\n  success.classList.add('overlay');\n  success.setAttribute('role', 'alert');\n  success.textContent = 'Data has been cleared.';\n  document.body.appendChild(success);\n\n  setTimeout(function () {\n    success.classList.add('visible');\n  }, 10);\n  setTimeout(function () {\n    if (close === false) success.classList.remove('visible');\n    else window.close();\n  }, 4000);\n}\n\nwindow.addEventListener('DOMContentLoaded', function () {\n  const selection = document.getElementById('button');\n  selection.addEventListener('click', buttonClicked);\n});\n"
  },
  {
    "path": "api-samples/commands/README.md",
    "content": "# chrome.commands\n\nThis sample demonstrates the [`chrome.commands`](https://developer.chrome.com/docs/extensions/reference/api/commands) API by defining custom keyboard shortcuts and responding to command events.\n\n## Overview\n\nThe extension registers two custom keyboard shortcuts in the manifest and listens for them using `chrome.commands.onCommand`. One command shows a notification, the other toggles a feature on and off with badge text feedback. The popup uses `chrome.commands.getAll()` to display all registered shortcuts and their current key bindings.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Use the keyboard shortcuts shown in the popup or customize them at `chrome://extensions/shortcuts`.\n"
  },
  {
    "path": "api-samples/commands/background.js",
    "content": "// Copyright 2025 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nlet featureEnabled = false;\n\nchrome.commands.onCommand.addListener(async (command) => {\n  if (command === 'run-action') {\n    chrome.notifications.create({\n      type: 'basic',\n      iconUrl: 'images/icon-128.png',\n      title: 'Commands API Demo',\n      message: 'The \"run-action\" command was triggered.'\n    });\n  }\n\n  if (command === 'toggle-feature') {\n    featureEnabled = !featureEnabled;\n    const state = featureEnabled ? 'ON' : 'OFF';\n\n    chrome.action.setBadgeText({ text: featureEnabled ? 'ON' : '' });\n    chrome.action.setBadgeBackgroundColor({ color: '#4688F1' });\n\n    chrome.notifications.create({\n      type: 'basic',\n      iconUrl: 'images/icon-128.png',\n      title: 'Feature Toggled',\n      message: `The feature is now ${state}.`\n    });\n  }\n});\n"
  },
  {
    "path": "api-samples/commands/manifest.json",
    "content": "{\n  \"name\": \"Commands API Demo\",\n  \"version\": \"1.0\",\n  \"description\": \"Uses the chrome.commands API to define keyboard shortcuts and handle command events.\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"permissions\": [\"notifications\"],\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"48\": \"images/icon-48.png\",\n    \"128\": \"images/icon-128.png\"\n  },\n  \"action\": {\n    \"default_popup\": \"popup.html\",\n    \"default_icon\": {\n      \"16\": \"images/icon-16.png\",\n      \"48\": \"images/icon-48.png\",\n      \"128\": \"images/icon-128.png\"\n    }\n  },\n  \"commands\": {\n    \"run-action\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+Shift+Y\",\n        \"mac\": \"Command+Shift+Y\"\n      },\n      \"description\": \"Run the sample action\"\n    },\n    \"toggle-feature\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+Shift+U\",\n        \"mac\": \"Command+Shift+U\"\n      },\n      \"description\": \"Toggle a feature on or off\"\n    }\n  }\n}\n"
  },
  {
    "path": "api-samples/commands/popup.css",
    "content": "body {\n  width: 300px;\n  padding: 12px 16px;\n  font-family: system-ui, sans-serif;\n  font-size: 14px;\n  color: #202124;\n}\n\nh1 {\n  font-size: 16px;\n  font-weight: 600;\n  margin: 0 0 12px;\n}\n\n.command-row {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  padding: 8px 0;\n  border-bottom: 1px solid #e8eaed;\n}\n\n.command-row:last-child {\n  border-bottom: none;\n}\n\n.command-name {\n  color: #3c4043;\n}\n\nkbd {\n  background: #f1f3f4;\n  border: 1px solid #dadce0;\n  border-radius: 4px;\n  padding: 2px 8px;\n  font-family: monospace;\n  font-size: 12px;\n  color: #5f6368;\n}\n\n#hint {\n  margin: 12px 0 0;\n  font-size: 12px;\n  color: #80868b;\n}\n\n#hint code {\n  background: #f1f3f4;\n  padding: 1px 4px;\n  border-radius: 3px;\n  font-size: 11px;\n}\n"
  },
  {
    "path": "api-samples/commands/popup.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"stylesheet\" href=\"popup.css\" />\n  </head>\n  <body>\n    <h1>Registered Commands</h1>\n    <div id=\"commands\"></div>\n    <p id=\"hint\">\n      Customize shortcuts at\n      <code>chrome://extensions/shortcuts</code>\n    </p>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/commands/popup.js",
    "content": "// Copyright 2025 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nasync function listCommands() {\n  const commands = await chrome.commands.getAll();\n  const container = document.getElementById('commands');\n\n  for (const command of commands) {\n    const row = document.createElement('div');\n    row.className = 'command-row';\n\n    const name = document.createElement('span');\n    name.className = 'command-name';\n    name.textContent = command.description || command.name;\n\n    const shortcut = document.createElement('kbd');\n    shortcut.textContent = command.shortcut || 'Not set';\n\n    row.appendChild(name);\n    row.appendChild(shortcut);\n    container.appendChild(row);\n  }\n}\n\nlistCommands();\n"
  },
  {
    "path": "api-samples/contentSettings/README.md",
    "content": "# chrome.contentSettings\n\nThis sample demonstrates using `chrome.contentSettings` to display the settings of a given page in the extension's popup.\n\n## Overview\n\nThe extension calls `chrome.contentSettings.get()` and `chrome.contentSettings.set()` to manage the value of each content setting on the user's currently active tab.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extenion to the browser's taskbar and click on the popup to see the content settings for a given site.\n"
  },
  {
    "path": "api-samples/contentSettings/manifest.json",
    "content": "{\n  \"name\": \"Content settings\",\n  \"version\": \"0.3\",\n  \"description\": \"Uses chrome.contentSettings to display the settings of a given page in the extension's popup.\",\n  \"permissions\": [\"contentSettings\", \"activeTab\"],\n  \"action\": {\n    \"default_icon\": \"contentSettings.png\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/contentSettings/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Popup</title>\n    <style>\n      dt {\n        white-space: nowrap;\n      }\n    </style>\n    <script src=\"popup.js\"></script>\n  </head>\n  <body>\n    <fieldset>\n      <dl>\n        <dt><label for=\"cookies\">Cookies: </label></dt>\n        <dd>\n          <select id=\"cookies\" disabled>\n            <option value=\"allow\">Allow</option>\n            <option value=\"session_only\">Session only</option>\n            <option value=\"block\">Block</option>\n          </select>\n        </dd>\n        <dt><label for=\"images\">Images: </label></dt>\n        <dd>\n          <select id=\"images\" disabled>\n            <option value=\"allow\">Allow</option>\n            <option value=\"block\">Block</option>\n          </select>\n        </dd>\n\n        <dt><label for=\"javascript\">Javascript: </label></dt>\n        <dd>\n          <select id=\"javascript\" disabled>\n            <option value=\"allow\">Allow</option>\n            <option value=\"block\">Block</option>\n          </select>\n        </dd>\n        <dt><label for=\"location\">Location: </label></dt>\n        <dd>\n          <select id=\"location\" disabled>\n            <option value=\"allow\">Allow</option>\n            <option value=\"ask\">Ask</option>\n            <option value=\"block\">Block</option>\n          </select>\n        </dd>\n        <dt><label for=\"plugins\">Plugins: </label></dt>\n        <dd>\n          <select id=\"plugins\" disabled>\n            <option value=\"allow\">Allow</option>\n            <option value=\"block\">Block</option>\n          </select>\n        </dd>\n        <dt><label for=\"popups\">Pop-ups: </label></dt>\n        <dd>\n          <select id=\"popups\" disabled>\n            <option value=\"allow\">Allow</option>\n            <option value=\"block\">Block</option>\n          </select>\n        </dd>\n        <dt><label for=\"notifications\">Notifications: </label></dt>\n        <dd>\n          <select id=\"notifications\" disabled>\n            <option value=\"allow\">Allow</option>\n            <option value=\"ask\">Ask</option>\n            <option value=\"block\">Block</option>\n          </select>\n        </dd>\n        <dt><label for=\"microphone\">Microphone: </label></dt>\n        <dd>\n          <select id=\"microphone\" disabled>\n            <option value=\"allow\">Allow</option>\n            <option value=\"ask\">Ask</option>\n            <option value=\"block\">Block</option>\n          </select>\n        </dd>\n        <dt><label for=\"camera\">Camera: </label></dt>\n        <dd>\n          <select id=\"camera\" disabled>\n            <option value=\"allow\">Allow</option>\n            <option value=\"ask\">Ask</option>\n            <option value=\"block\">Block</option>\n          </select>\n        </dd>\n        <dt>\n          <label for=\"unsandboxedPlugins\">Unsandboxed plugin access: </label>\n        </dt>\n        <dd>\n          <select id=\"unsandboxedPlugins\" disabled>\n            <option value=\"allow\">Allow</option>\n            <option value=\"ask\">Ask</option>\n            <option value=\"block\">Block</option>\n          </select>\n        </dd>\n        <dt><label for=\"automaticDownloads\">Automatic Downloads: </label></dt>\n        <dd>\n          <select id=\"automaticDownloads\" disabled>\n            <option value=\"allow\">Allow</option>\n            <option value=\"ask\">Ask</option>\n            <option value=\"block\">Block</option>\n          </select>\n        </dd>\n      </dl>\n    </fieldset>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/contentSettings/popup.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nlet incognito;\nlet url;\n\nfunction settingChanged() {\n  let type = this.id;\n  let setting = this.value;\n  let pattern = /^file:/.test(url) ? url : url.replace(/\\/[^/]*?$/, '/*');\n  console.log(type + ' setting for ' + pattern + ': ' + setting);\n  // HACK: [type] is not recognised by the docserver's sample crawler, so\n  // mention an explicit\n  // type: chrome.contentSettings.cookies.set - See http://crbug.com/299634\n  chrome.contentSettings[type].set({\n    primaryPattern: pattern,\n    setting: setting,\n    scope: incognito ? 'incognito_session_only' : 'regular'\n  });\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {\n    let current = tabs[0];\n    incognito = current.incognito;\n    url = current.url;\n    let types = [\n      'cookies',\n      'images',\n      'javascript',\n      'location',\n      'popups',\n      'notifications',\n      'microphone',\n      'camera',\n      'automaticDownloads'\n    ];\n    types.forEach(function (type) {\n      // HACK: [type] is not recognised by the docserver's sample crawler, so\n      // mention an explicit\n      // type: chrome.contentSettings.cookies.get - See http://crbug.com/299634\n      chrome.contentSettings[type] &&\n        chrome.contentSettings[type].get(\n          {\n            primaryUrl: url,\n            incognito: incognito\n          },\n          function (details) {\n            document.getElementById(type).disabled = false;\n            document.getElementById(type).value = details.setting;\n          }\n        );\n    });\n  });\n\n  let selects = document.querySelectorAll('select');\n  for (let i = 0; i < selects.length; i++) {\n    selects[i].addEventListener('change', settingChanged);\n  }\n});\n"
  },
  {
    "path": "api-samples/contextMenus/basic/README.md",
    "content": "# chrome.contextMenus\n\nA sample extension demonstrating use of the chrome.contextMenus API.\n\n## Overview\n\nIn this sample the chrome.contextMenus API is used to create menu items, listen for different context menu types being clicked, and run code based on what the user has selected.\n\n## Implementation Notes\n\nDifferent console readouts are made when context menu items are clicked. This can be quickly adapted to use new functions or API calls for more advaced functionality.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Right-click within the browser to view the context menu.\n"
  },
  {
    "path": "api-samples/contextMenus/basic/manifest.json",
    "content": "{\n  \"name\": \"Context Menus Sample\",\n  \"description\": \"Uses the chrome.contextMenus API to customize the context menu.\",\n  \"version\": \"0.7\",\n  \"permissions\": [\"contextMenus\"],\n  \"background\": {\n    \"service_worker\": \"sample.js\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/contextMenus/basic/sample.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// A generic onclick callback function.\nchrome.contextMenus.onClicked.addListener(genericOnClick);\n\n// A generic onclick callback function.\nfunction genericOnClick(info) {\n  switch (info.menuItemId) {\n    case 'radio':\n      // Radio item function\n      console.log('Radio item clicked. Status:', info.checked);\n      break;\n    case 'checkbox':\n      // Checkbox item function\n      console.log('Checkbox item clicked. Status:', info.checked);\n      break;\n    default:\n      // Standard context menu item function\n      console.log('Standard context menu item clicked.');\n  }\n}\nchrome.runtime.onInstalled.addListener(function () {\n  // Create one test item for each context type.\n  let contexts = [\n    'page',\n    'selection',\n    'link',\n    'editable',\n    'image',\n    'video',\n    'audio'\n  ];\n  for (let i = 0; i < contexts.length; i++) {\n    let context = contexts[i];\n    let title = \"Test '\" + context + \"' menu item\";\n    chrome.contextMenus.create({\n      title: title,\n      contexts: [context],\n      id: context\n    });\n  }\n\n  // Create a parent item and two children.\n  let parent = chrome.contextMenus.create({\n    title: 'Test parent item',\n    id: 'parent'\n  });\n  chrome.contextMenus.create({\n    title: 'Child 1',\n    parentId: parent,\n    id: 'child1'\n  });\n  chrome.contextMenus.create({\n    title: 'Child 2',\n    parentId: parent,\n    id: 'child2'\n  });\n\n  // Create a radio item.\n  chrome.contextMenus.create({\n    title: 'radio',\n    type: 'radio',\n    id: 'radio'\n  });\n\n  // Create a checkbox item.\n  chrome.contextMenus.create({\n    title: 'checkbox',\n    type: 'checkbox',\n    id: 'checkbox'\n  });\n\n  // Intentionally create an invalid item, to show off error checking in the\n  // create callback.\n  chrome.contextMenus.create(\n    { title: 'Oops', parentId: 999, id: 'errorItem' },\n    function () {\n      if (chrome.runtime.lastError) {\n        console.log('Got expected error: ' + chrome.runtime.lastError.message);\n      }\n    }\n  );\n});\n"
  },
  {
    "path": "api-samples/contextMenus/global_context_search/README.md",
    "content": "# chrome.contextMenus\n\nThis sample demonstrates the `chrome.contextMenus` API by letting a user switch between searching different countries' versions of Google via a `contextMenu`.\n\n## Overview\n\nThe extension uses `chrome.contextMenus.create()` to populate the context menu with locale options based on an options menu in the popup. A `chrome.contextMenus.onClicked.addListener()` event will open a specific locale's Google homepage when one of the extension's context menu options are clicked.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extension to the taskbar to access the action button.\n4. Open the extension popup by clicking the action button and interact with the UI.\n5. Select the text you want to search and right-click within the selection to view and interact with the context menu.\n"
  },
  {
    "path": "api-samples/contextMenus/global_context_search/background.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// When you specify \"type\": \"module\" in the manifest background,\n// you can include the service worker as an ES Module,\nimport { tldLocales } from './locales.js';\n\n// Add a listener to create the initial context menu items,\n// context menu items only need to be created at runtime.onInstalled\nchrome.runtime.onInstalled.addListener(async () => {\n  for (const [tld, locale] of Object.entries(tldLocales)) {\n    chrome.contextMenus.create({\n      id: tld,\n      title: locale,\n      type: 'normal',\n      contexts: ['selection']\n    });\n  }\n});\n\n// Open a new search tab when the user clicks a context menu\nchrome.contextMenus.onClicked.addListener((item, tab) => {\n  const tld = item.menuItemId;\n  const url = new URL(`https://google.${tld}/search`);\n  url.searchParams.set('q', item.selectionText);\n  chrome.tabs.create({ url: url.href, index: tab.index + 1 });\n});\n\n// Add or removes the locale from context menu\n// when the user checks or unchecks the locale in the popup\nchrome.storage.onChanged.addListener(({ enabledTlds }) => {\n  if (typeof enabledTlds === 'undefined') return;\n\n  const allTlds = Object.keys(tldLocales);\n  const currentTlds = new Set(enabledTlds.newValue);\n  const oldTlds = new Set(enabledTlds.oldValue ?? allTlds);\n  const changes = allTlds.map((tld) => ({\n    tld,\n    added: currentTlds.has(tld) && !oldTlds.has(tld),\n    removed: !currentTlds.has(tld) && oldTlds.has(tld)\n  }));\n\n  for (const { tld, added, removed } of changes) {\n    if (added) {\n      chrome.contextMenus.create({\n        id: tld,\n        title: tldLocales[tld],\n        type: 'normal',\n        contexts: ['selection']\n      });\n    } else if (removed) {\n      chrome.contextMenus.remove(tld);\n    }\n  }\n});\n"
  },
  {
    "path": "api-samples/contextMenus/global_context_search/locales.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// TLD: top level domain; the \"com\" in \"google.com\"\nexport const tldLocales = {\n  'com.au': 'Australia',\n  'com.br': 'Brazil',\n  ca: 'Canada',\n  cn: 'China',\n  fr: 'France',\n  it: 'Italy',\n  'co.in': 'India',\n  'co.jp': 'Japan',\n  'com.ms': 'Mexico',\n  ru: 'Russia',\n  'co.za': 'South Africa',\n  'co.uk': 'United Kingdom'\n};\n"
  },
  {
    "path": "api-samples/contextMenus/global_context_search/manifest.json",
    "content": "{\n  \"name\": \"Global Google Search\",\n  \"description\": \"Uses the context menu to search a different country's Google\",\n  \"version\": \"1.1\",\n  \"manifest_version\": 3,\n  \"permissions\": [\"contextMenus\", \"storage\"],\n  \"background\": {\n    \"service_worker\": \"background.js\",\n    \"type\": \"module\"\n  },\n  \"action\": {\n    \"default_popup\": \"popup.html\"\n  },\n  \"icons\": {\n    \"16\": \"globalGoogle16.png\",\n    \"48\": \"globalGoogle48.png\",\n    \"128\": \"globalGoogle128.png\"\n  }\n}\n"
  },
  {
    "path": "api-samples/contextMenus/global_context_search/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Global Context Search</title>\n    <style>\n      body {\n        min-width: 300px;\n        font-size: 15px;\n      }\n\n      input {\n        margin: 5px;\n        outline: none;\n      }\n    </style>\n  </head>\n\n  <body>\n    <h2>Global Google Search</h2>\n    <h3>Countries</h3>\n    <form id=\"form\"></form>\n    <script src=\"popup.js\" type=\"module\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/contextMenus/global_context_search/popup.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// TLD: top level domain; the \"com\" in \"google.com\"\nimport { tldLocales } from './locales.js';\n\ncreateForm().catch(console.error);\n\nasync function createForm() {\n  const { enabledTlds = Object.keys(tldLocales) } =\n    await chrome.storage.sync.get('enabledTlds');\n  const checked = new Set(enabledTlds);\n\n  const form = document.getElementById('form');\n  for (const [tld, locale] of Object.entries(tldLocales)) {\n    const checkbox = document.createElement('input');\n    checkbox.type = 'checkbox';\n    checkbox.checked = checked.has(tld);\n    checkbox.name = tld;\n    checkbox.addEventListener('click', (event) => {\n      handleCheckboxClick(event).catch(console.error);\n    });\n\n    const span = document.createElement('span');\n    span.textContent = locale;\n\n    const div = document.createElement('div');\n    div.appendChild(checkbox);\n    div.appendChild(span);\n\n    form.appendChild(div);\n  }\n}\n\nasync function handleCheckboxClick(event) {\n  const checkbox = event.target;\n  const tld = checkbox.name;\n  const enabled = checkbox.checked;\n\n  const { enabledTlds = Object.keys(tldLocales) } =\n    await chrome.storage.sync.get('enabledTlds');\n  const tldSet = new Set(enabledTlds);\n\n  if (enabled) tldSet.add(tld);\n  else tldSet.delete(tld);\n\n  await chrome.storage.sync.set({ enabledTlds: [...tldSet] });\n}\n"
  },
  {
    "path": "api-samples/cookies/cookie-clearer/README.md",
    "content": "# chrome.cookies\n\nThis sample demonstrates the `chrome.cookies` API by letting a user delete their cookies via a popup UI.\n\n## Overview\n\nThe extension uses `chrome.cookies.getAll()` and `chrome.cookies.remove()` to delete the user's cookies when prompted.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extension to the taskbar to access the action button.\n4. Open the extension popup by clicking the action button and interact with the UI.\n"
  },
  {
    "path": "api-samples/cookies/cookie-clearer/manifest.json",
    "content": "{\n  \"name\": \"Cookie Clearer\",\n  \"manifest_version\": 3,\n  \"version\": \"1.0\",\n  \"description\": \"Uses the chrome.cookies API by letting a user delete their cookies via a popup.\",\n  \"permissions\": [\"cookies\"],\n  \"host_permissions\": [\"<all_urls>\"],\n  \"action\": {\n    \"default_popup\": \"popup.html\"\n  }\n}\n"
  },
  {
    "path": "api-samples/cookies/cookie-clearer/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <script src=\"popup.js\" type=\"module\"></script>\n  </head>\n  <body>\n    <form id=\"control-row\">\n      <label for=\"input\">Domain:</label>\n      <input type=\"text\" id=\"input\" />\n      <br />\n      <button id=\"go\">Clear Cookies</button>\n    </form>\n    <span id=\"message\" hidden></span>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/cookies/cookie-clearer/popup.js",
    "content": "const form = document.getElementById('control-row');\nconst input = document.getElementById('input');\nconst message = document.getElementById('message');\n\n// The async IIFE is necessary because Chrome <89 does not support top level await.\n(async function initPopupWindow() {\n  let [tab] = await chrome.tabs.query({ active: true, currentWindow: true });\n\n  if (tab?.url) {\n    try {\n      let url = new URL(tab.url);\n      input.value = url.hostname;\n    } catch {\n      // ignore\n    }\n  }\n\n  input.focus();\n})();\n\nform.addEventListener('submit', handleFormSubmit);\n\nasync function handleFormSubmit(event) {\n  event.preventDefault();\n\n  clearMessage();\n\n  let url = stringToUrl(input.value);\n  if (!url) {\n    setMessage('Invalid URL');\n    return;\n  }\n\n  let message = await deleteDomainCookies(url.hostname);\n  setMessage(message);\n}\n\nfunction stringToUrl(input) {\n  // Start with treating the provided value as a URL\n  try {\n    return new URL(input);\n  } catch {\n    // ignore\n  }\n  // If that fails, try assuming the provided input is an HTTP host\n  try {\n    return new URL('http://' + input);\n  } catch {\n    // ignore\n  }\n  // If that fails ¯\\_(ツ)_/¯\n  return null;\n}\n\nasync function deleteDomainCookies(domain) {\n  let cookiesDeleted = 0;\n  try {\n    const cookies = await chrome.cookies.getAll({ domain });\n\n    if (cookies.length === 0) {\n      return 'No cookies found';\n    }\n\n    let pending = cookies.map(deleteCookie);\n    await Promise.all(pending);\n\n    cookiesDeleted = pending.length;\n  } catch (error) {\n    return `Unexpected error: ${error.message}`;\n  }\n\n  return `Deleted ${cookiesDeleted} cookie(s).`;\n}\n\nfunction deleteCookie(cookie) {\n  // Cookie deletion is largely modeled off of how deleting cookies works when using HTTP headers.\n  // Specific flags on the cookie object like `secure` or `hostOnly` are not exposed for deletion\n  // purposes. Instead, cookies are deleted by URL, name, and storeId. Unlike HTTP headers, though,\n  // we don't have to delete cookies by setting Max-Age=0; we have a method for that ;)\n  //\n  // To remove cookies set with a Secure attribute, we must provide the correct protocol in the\n  // details object's `url` property.\n  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Secure\n  const protocol = cookie.secure ? 'https:' : 'http:';\n\n  // Note that the final URL may not be valid. The domain value for a standard cookie is prefixed\n  // with a period (invalid) while cookies that are set to `cookie.hostOnly == true` do not have\n  // this prefix (valid).\n  // https://developer.chrome.com/docs/extensions/reference/cookies/#type-Cookie\n  const cookieUrl = `${protocol}//${cookie.domain}${cookie.path}`;\n\n  return chrome.cookies.remove({\n    url: cookieUrl,\n    name: cookie.name,\n    storeId: cookie.storeId\n  });\n}\n\nfunction setMessage(str) {\n  message.textContent = str;\n  message.hidden = false;\n}\n\nfunction clearMessage() {\n  message.hidden = true;\n  message.textContent = '';\n}\n"
  },
  {
    "path": "api-samples/debugger/README.md",
    "content": "# chrome.debugger\n\nThis sample demonstrates using the [`chrome.debugger`](https://developer.chrome.com/docs/extensions/reference/debugger/) API to capture network events on webpages.\n\n## Overview\n\nThe extension calls `chrome.debugger.attach()` on a tab to capture network events when you click the extension's action button. The response data is logged in the developer console, to demonstrate extracting a network response's data such as the request headers and URL.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Navigate to an HTTP/HTTPS webpage and open the devtools window.\n4. Pin the extension to the browser's taskbar and click on the action button to see the network event data logged to the console.\n"
  },
  {
    "path": "api-samples/debugger/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Debugger Extension\",\n  \"description\": \"Uses the chrome.debugger API to capture network events on web pages.\",\n  \"version\": \"1.0\",\n  \"permissions\": [\"debugger\", \"tabs\"],\n  \"host_permissions\": [\"https://www.google.com/*\"],\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"action\": {}\n}\n"
  },
  {
    "path": "api-samples/debugger/service-worker.js",
    "content": "chrome.action.onClicked.addListener(function (tab) {\n  if (tab.url.startsWith('http')) {\n    chrome.debugger.attach({ tabId: tab.id }, '1.2', function () {\n      chrome.debugger.sendCommand(\n        { tabId: tab.id },\n        'Network.enable',\n        {},\n        function () {\n          if (chrome.runtime.lastError) {\n            console.error(chrome.runtime.lastError);\n          }\n        }\n      );\n    });\n  } else {\n    console.log('Debugger can only be attached to HTTP/HTTPS pages.');\n  }\n});\n\nchrome.debugger.onEvent.addListener(function (source, method, params) {\n  if (method === 'Network.responseReceived') {\n    console.log('Response received:', params.response);\n    // Perform your desired action with the response data\n  }\n});\n"
  },
  {
    "path": "api-samples/declarativeNetRequest/no-cookies/README.md",
    "content": "# chrome.declarativeNetRequest - No Cookies\n\nThis sample demonstrates using the [`chrome.declarativeNetRequest`](https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/) API to remove the \"Cookie\" header from requests.\n\n## Overview\n\nOnce this extension is installed, any main frame requests ending in `?no-cookies=1` will be sent without the \"Cookie\" header.\n\nFor example, install this extension and try navigating to https://github.com/GoogleChrome/chrome-extensions-samples?no-cookies=1. You should appear signed out.\n\n## Implementation Notes\n\nThis sample uses the `chrome.declarativeNetRequest.onRuleMatchedDebug` event which is only available in unpacked extensions.\n"
  },
  {
    "path": "api-samples/declarativeNetRequest/no-cookies/manifest.json",
    "content": "{\n  \"name\": \"No Cookies\",\n  \"description\": \"Uses the chrome.declarativeNetRequest API to remove the \\\"Cookie\\\" header from requests.\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"permissions\": [\"declarativeNetRequest\", \"declarativeNetRequestFeedback\"],\n  \"host_permissions\": [\"<all_urls>\"],\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"declarative_net_request\": {\n    \"rule_resources\": [\n      {\n        \"id\": \"ruleset_1\",\n        \"enabled\": true,\n        \"path\": \"rules_1.json\"\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "api-samples/declarativeNetRequest/no-cookies/rules_1.json",
    "content": "[\n  {\n    \"id\": 1,\n    \"priority\": 1,\n    \"action\": {\n      \"type\": \"modifyHeaders\",\n      \"requestHeaders\": [{ \"header\": \"cookie\", \"operation\": \"remove\" }]\n    },\n    \"condition\": {\n      \"urlFilter\": \"|*?no-cookies=1\",\n      \"resourceTypes\": [\"main_frame\"]\n    }\n  }\n]\n"
  },
  {
    "path": "api-samples/declarativeNetRequest/no-cookies/service-worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n'use strict';\n\n// Simple extension to remove the 'Cookie' request header.\n\nchrome.declarativeNetRequest.onRuleMatchedDebug.addListener((e) => {\n  const msg = `Cookies removed in request to ${e.request.url} on tab ${e.request.tabId}.`;\n  console.log(msg);\n});\n\nconsole.log('Service worker started.');\n"
  },
  {
    "path": "api-samples/declarativeNetRequest/url-blocker/README.md",
    "content": "# chrome.declarativeNetRequest - URL Blocker\n\nThis sample demonstrates using the [`chrome.declarativeNetRequest`](https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/) API to block requests.\n\n## Overview\n\nOnce this extension is installed, any requests made in the main frame to example.com will be blocked.\n\n## Implementation Notes\n\nThis sample uses the `chrome.declarativeNetRequest.onRuleMatchedDebug` event which is only available in unpacked extensions.\n"
  },
  {
    "path": "api-samples/declarativeNetRequest/url-blocker/manifest.json",
    "content": "{\n  \"name\": \"URL Blocker\",\n  \"version\": \"0.1\",\n  \"manifest_version\": 3,\n  \"description\": \"Uses the chrome.declarativeNetRequest API to block requests.\",\n  \"background\": {\n    \"service_worker\": \"service_worker.js\"\n  },\n  \"declarative_net_request\": {\n    \"rule_resources\": [\n      {\n        \"id\": \"ruleset_1\",\n        \"enabled\": true,\n        \"path\": \"rules_1.json\"\n      }\n    ]\n  },\n  \"permissions\": [\"declarativeNetRequest\", \"declarativeNetRequestFeedback\"]\n}\n"
  },
  {
    "path": "api-samples/declarativeNetRequest/url-blocker/rules_1.json",
    "content": "[\n  {\n    \"id\": 1,\n    \"priority\": 1,\n    \"action\": { \"type\": \"block\" },\n    \"condition\": {\n      \"urlFilter\": \"||example.com\",\n      \"resourceTypes\": [\"main_frame\"]\n    }\n  }\n]\n"
  },
  {
    "path": "api-samples/declarativeNetRequest/url-blocker/service_worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n'use strict';\n\nchrome.declarativeNetRequest.onRuleMatchedDebug.addListener((e) => {\n  const msg = `Navigation blocked to ${e.request.url} on tab ${e.request.tabId}.`;\n  console.log(msg);\n});\n\nconsole.log('Service worker started.');\n"
  },
  {
    "path": "api-samples/declarativeNetRequest/url-redirect/README.md",
    "content": "# chrome.declarativeNetRequest - URL Redirect\n\nThis sample demonstrates using the [`chrome.declarativeNetRequest`](https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/) API to redirect requests.\n\n## Overview\n\nOnce this extension is installed, any requests made in the main frame to the following URLs will be redirected:\n\n- https://developer.chrome.com/docs/extensions/mv2/\n- https://developer.chrome.com/docs/extensions/reference/browserAction/\n- https://developer.chrome.com/docs/extensions/reference/declarativeWebRequest/\n- https://developer.chrome.com/docs/extensions/reference/pageAction/\n- https://developer.chrome.com/docs/extensions/reference/webRequest/\n\n## Implementation Notes\n\nThis sample uses the `chrome.declarativeNetRequest.onRuleMatchedDebug` event which is only available in unpacked extensions.\n"
  },
  {
    "path": "api-samples/declarativeNetRequest/url-redirect/manifest.json",
    "content": "{\n  \"name\": \"URL Redirect\",\n  \"version\": \"0.1\",\n  \"manifest_version\": 3,\n  \"description\": \"Uses the chrome.declarativeNetRequest API to redirect requests.\",\n  \"background\": {\n    \"service_worker\": \"service_worker.js\"\n  },\n  \"declarative_net_request\": {\n    \"rule_resources\": [\n      {\n        \"id\": \"ruleset_1\",\n        \"enabled\": true,\n        \"path\": \"rules_1.json\"\n      }\n    ]\n  },\n  \"permissions\": [\n    \"declarativeNetRequest\",\n    \"declarativeNetRequestFeedback\",\n    \"declarativeNetRequestWithHostAccess\"\n  ],\n  \"host_permissions\": [\"https://developer.chrome.com/\"]\n}\n"
  },
  {
    "path": "api-samples/declarativeNetRequest/url-redirect/rules_1.json",
    "content": "[\n  {\n    \"id\": 1,\n    \"priority\": 1,\n    \"action\": {\n      \"type\": \"redirect\",\n      \"redirect\": {\n        \"url\": \"https://developer.chrome.com/docs/extensions/mv3/intro/\"\n      }\n    },\n    \"condition\": {\n      \"urlFilter\": \"https://developer.chrome.com/docs/extensions/mv2/\",\n      \"resourceTypes\": [\"main_frame\"]\n    }\n  },\n  {\n    \"id\": 2,\n    \"priority\": 1,\n    \"action\": {\n      \"type\": \"redirect\",\n      \"redirect\": {\n        \"url\": \"https://developer.chrome.com/docs/extensions/reference/action/\"\n      }\n    },\n    \"condition\": {\n      \"urlFilter\": \"https://developer.chrome.com/docs/extensions/reference/browserAction/\",\n      \"resourceTypes\": [\"main_frame\"]\n    }\n  },\n  {\n    \"id\": 3,\n    \"priority\": 1,\n    \"action\": {\n      \"type\": \"redirect\",\n      \"redirect\": {\n        \"url\": \"https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/\"\n      }\n    },\n    \"condition\": {\n      \"urlFilter\": \"https://developer.chrome.com/docs/extensions/reference/declarativeWebRequest/\",\n      \"resourceTypes\": [\"main_frame\"]\n    }\n  },\n  {\n    \"id\": 4,\n    \"priority\": 1,\n    \"action\": {\n      \"type\": \"redirect\",\n      \"redirect\": {\n        \"url\": \"https://developer.chrome.com/docs/extensions/reference/action/\"\n      }\n    },\n    \"condition\": {\n      \"urlFilter\": \"https://developer.chrome.com/docs/extensions/reference/pageAction/\",\n      \"resourceTypes\": [\"main_frame\"]\n    }\n  },\n  {\n    \"id\": 5,\n    \"priority\": 1,\n    \"action\": {\n      \"type\": \"redirect\",\n      \"redirect\": {\n        \"url\": \"https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/\"\n      }\n    },\n    \"condition\": {\n      \"urlFilter\": \"https://developer.chrome.com/docs/extensions/reference/webRequest/\",\n      \"resourceTypes\": [\"main_frame\"]\n    }\n  }\n]\n"
  },
  {
    "path": "api-samples/declarativeNetRequest/url-redirect/service_worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n'use strict';\n\nchrome.declarativeNetRequest.onRuleMatchedDebug.addListener((e) => {\n  const msg = `Navigation to ${e.request.url} redirected on tab ${e.request.tabId}.`;\n  console.log(msg);\n});\n\nconsole.log('Service worker started.');\n"
  },
  {
    "path": "api-samples/default_command_override/README.md",
    "content": "# chrome.commands\n\nThis sample demonstrates the `chrome.commands` API by creating a new keyboard macro for switching tabs in the browser window.\n\n## Overview\n\nThe extension sets Ctrl+Shift+Left and Ctrl+Shift+Right as command inputs in the manifest, and uses `chrome.commands.onCommand.addListener()` to trigger switching tabs.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Input the keyboard commands to switch between tabs.\n"
  },
  {
    "path": "api-samples/default_command_override/background.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nchrome.commands.onCommand.addListener(async (command) => {\n  const tabs = await chrome.tabs.query({ currentWindow: true });\n  // Sort tabs according to their index in the window.\n  tabs.sort((a, b) => {\n    return a.index < b.index;\n  });\n  const activeIndex = tabs.findIndex((tab) => {\n    return tab.active;\n  });\n  const lastTab = tabs.length - 1;\n  let newIndex = -1;\n  if (command === 'flip-tabs-forward') {\n    newIndex = activeIndex === lastTab ? 0 : activeIndex + 1;\n  }\n  // 'flip-tabs-backwards'\n  else newIndex = activeIndex === 0 ? lastTab : activeIndex - 1;\n  chrome.tabs.update(tabs[newIndex].id, { active: true, highlighted: true });\n});\n"
  },
  {
    "path": "api-samples/default_command_override/manifest.json",
    "content": "{\n  \"name\": \"chrome.commands\",\n  \"description\": \"Uses the chrome.commands API by creating a new keyboard macro for switching tabs in the browser window.\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"action\": {\n    \"default_icon\": {\n      \"16\": \"images/tabFlipper16.png\",\n      \"32\": \"images/tabFlipper32.png\",\n      \"48\": \"images/tabFlipper48.png\",\n      \"128\": \"images/tabFlipper128.png\"\n    },\n    \"default_title\": \"Press Ctrl(Win)/Command(Mac)+Shift+ Left or Right to Flip Tabs\"\n  },\n  \"commands\": {\n    \"flip-tabs-forward\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+Shift+Right\",\n        \"mac\": \"Command+Shift+Right\"\n      },\n      \"description\": \"Flip tabs forward\"\n    },\n    \"flip-tabs-backwards\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+Shift+Left\",\n        \"mac\": \"Command+Shift+Left\"\n      },\n      \"description\": \"Flip tabs backwards\"\n    }\n  },\n  \"icons\": {\n    \"16\": \"images/tabFlipper16.png\",\n    \"32\": \"images/tabFlipper32.png\",\n    \"48\": \"images/tabFlipper48.png\",\n    \"128\": \"images/tabFlipper128.png\"\n  }\n}\n"
  },
  {
    "path": "api-samples/devtools/inspectedWindow/README.md",
    "content": "# devtools.inspectedWindow\n\nThis sample demonstrates using the `inspectedWindow` API to collect and use data on the resources used in a webpage.\n\n## Overview\n\n`devtools.inspectedWindow.getResources()` is used to collect information about the webpage. A devtools panel is then created to display the amount of resources of each type used on the page.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Navigate to a webpage and open the devtools window.\n4. Navigate to the new devtools panel named \"demo panel\", and click on the button.\n"
  },
  {
    "path": "api-samples/devtools/inspectedWindow/devtools.html",
    "content": "<!--\n Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n\n<!doctype html>\n<button>Display Types</button>\n<script src=\"devtools.js\"></script>\n"
  },
  {
    "path": "api-samples/devtools/inspectedWindow/devtools.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.devtools.panels.create('demo panel', 'icon.png', 'panel.html', () => {\n  console.log('user switched to this panel');\n});\n"
  },
  {
    "path": "api-samples/devtools/inspectedWindow/manifest.json",
    "content": "{\n  \"name\": \"Devtools - inspectedWindow API sample\",\n  \"description\": \"Uses devtools.inspectedWindow to collect and use data on the resouces used in a web page.\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"devtools_page\": \"devtools.html\"\n}\n"
  },
  {
    "path": "api-samples/devtools/inspectedWindow/panel.html",
    "content": "<!--\n Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n\n<!doctype html>\n<html style=\"display: flex\">\n  <head>\n    <meta charset=\"utf8\" />\n    <style>\n      html {\n        display: flex;\n        position: fixed;\n        top: 0;\n        left: 0;\n        right: 0;\n        bottom: 0;\n      }\n      body {\n        margin: 0;\n        padding: 0;\n        flex: 1;\n        display: flex;\n        width: 100%;\n      }\n      #container {\n        display: flex;\n        flex: 1;\n        width: 100%;\n      }\n    </style>\n  </head>\n  <body>\n    <script src=\"panel.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/devtools/inspectedWindow/panel.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst types = {};\nchrome.devtools.inspectedWindow.getResources((resources) => {\n  resources.forEach((resource) => {\n    if (!(resource.type in types)) {\n      types[resource.type] = 0;\n    }\n    types[resource.type] += 1;\n  });\n  let result = `Resources on this page: \n  ${Object.entries(types)\n    .map((entry) => {\n      const [type, count] = entry;\n      return `${type}: ${count}`;\n    })\n    .join('\\n')}`;\n  let div = document.createElement('div');\n  div.innerText = result;\n  document.body.appendChild(div);\n});\n"
  },
  {
    "path": "api-samples/devtools/panels/devtools.html",
    "content": "<!--\n Copyright 2023 Google LLC\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n     https://www.apache.org/licenses/LICENSE-2.0\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n<html>\n  <body>\n    <script src=\"devtools.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/devtools/panels/devtools.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// The function below is executed in the context of the inspected page.\n/*global $0*/\nconst page_getProperties = function () {\n  let data = window.jQuery && $0 ? jQuery.data($0) : {};\n  // Make a shallow copy with a null prototype, so that sidebar does not\n  // expose prototype.\n  let props = Object.getOwnPropertyNames(data);\n  let copy = { __proto__: null };\n  for (let i = 0; i < props.length; ++i) copy[props[i]] = data[props[i]];\n  return copy;\n};\n\nchrome.devtools.panels.elements.createSidebarPane(\n  'jQuery Properties',\n  function (sidebar) {\n    function updateElementProperties() {\n      sidebar.setExpression('(' + page_getProperties.toString() + ')()');\n    }\n    updateElementProperties();\n    chrome.devtools.panels.elements.onSelectionChanged.addListener(\n      updateElementProperties\n    );\n  }\n);\n"
  },
  {
    "path": "api-samples/devtools/panels/manifest.json",
    "content": "{\n  \"name\": \"Devtools - Chrome Query\",\n  \"version\": \"1.2\",\n  \"description\": \"Uses the devtools API to add a sidebar that displays the jQuery data associated with the selected DOM element.\",\n  \"devtools_page\": \"devtools.html\",\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/devtools/panels/readme.md",
    "content": "# devtools\n\nThis sample demonstrates using the devtools API to add a sidebar that displays the jQuery data associated with the selected DOM element.\n\n## Overview\n\nThis extension shows how DevTools can be expanded with new elements. It contains HTML and JavaScript files that are injected into the DevTools page to expand its functionality.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Go to https://jqueryui.com/resources/demos/draggable/default.html (a site that uses jQuery).\n4. Open DevTools and select the div id=\"draggable\" in the elements panel.\n5. Find the \"jQuery Properties\" section and open it to access the newly added sidear.\n"
  },
  {
    "path": "api-samples/favicon/README.md",
    "content": "# favicon\n\nThis sample demonstrates the favicon manifest permission by displaying the favicon of a url in the extension popup.\n\n## Overview\n\nThe extension calls `chrome.runtime.getURL('/_favicon/')` to create a fully-qualified URL pointing to the \"\\_favicon/\" folder. Then it returns a new string representing the URL with several query parameters. Finally, the extension appends the image to the body of the extension popup.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extension to the taskbar to access the action button.\n4. Open the extension popup by clicking the action button.\n"
  },
  {
    "path": "api-samples/favicon/manifest.json",
    "content": "{\n  \"name\": \"Favicon API in a popup\",\n  \"version\": \"1.1\",\n  \"description\": \"Demonstrates the favicon manifest permission by displaying the favicon of a url in the extension popup.\",\n  \"manifest_version\": 3,\n  \"permissions\": [\"favicon\"],\n  \"action\": {\n    \"default_popup\": \"popup.html\"\n  }\n}\n"
  },
  {
    "path": "api-samples/favicon/popup.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <body>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/favicon/popup.js",
    "content": "function faviconURL(u) {\n  const url = new URL(chrome.runtime.getURL('/_favicon/'));\n  url.searchParams.set('pageUrl', u); // this encodes the URL as well\n  url.searchParams.set('size', '32');\n  return url.toString();\n}\n\nconst img = document.createElement('img');\n// chrome-extension://EXTENSION_ID/_favicon/?pageUrl=https%3A%2F%2Fwww.google.com&size=32\nimg.src = faviconURL('https://www.google.com');\ndocument.body.appendChild(img);\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/README.md",
    "content": "# chrome.fontSettings\n\nDemonstrates the `chrome.fontSettings` API by allowing users to modify the styling displayed fonts on webpages.\n\n## Overview\n\nCreates a user interface in the extension's options page that allows users to see and modify font settings using `chrome.fontSettings` to change parameters.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin th extension to the taskbar and click the action button.\n4. Visit the extension's options page and make changes to the font settings.\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/css/chrome_shared.css",
    "content": "/* Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file. */\n\n/* Copy of /resources/shared/css/chrome_shared.css for sample extension. */\n\n/* Prevent CSS from overriding the hidden property. */\n[hidden] {\n  display: none !important;\n}\n\nhtml.loading * {\n  transition-delay: 0ms !important;\n  transition-duration: 0ms !important;\n}\n\nbody {\n  cursor: default;\n  margin: 0;\n}\n\np {\n  line-height: 1.8em;\n}\n\nh1,\nh2,\nh3 {\n  -webkit-user-select: none;\n  font-weight: normal;\n  /* Makes the vertical size of the text the same for all fonts. */\n  line-height: 1;\n}\n\nh1 {\n  font-size: 1.5em;\n}\n\nh2 {\n  font-size: 1.3em;\n  margin-bottom: 0.4em;\n}\n\nh3 {\n  color: black;\n  font-size: 1.2em;\n  margin-bottom: 0.8em;\n}\n\na {\n  color: rgb(17, 85, 204);\n  text-decoration: underline;\n}\n\na:active {\n  color: rgb(5, 37, 119);\n}\n\n/* Elements that need to be LTR even in an RTL context, but should align\n * right. (Namely, URLs, search engine names, etc.)\n */\nhtml[dir='rtl'] .weakrtl {\n  direction: ltr;\n  text-align: right;\n}\n\n/* Input fields in search engine table need to be weak-rtl. Since those input\n * fields are generated for all cr.ListItem elements (and we only want weakrtl\n * on some), the class needs to be on the enclosing div.\n */\nhtml[dir='rtl'] div.weakrtl input {\n  direction: ltr;\n  text-align: right;\n}\n\nhtml[dir='rtl'] .favicon-cell.weakrtl {\n  padding-inline-end: 22px;\n  padding-inline-start: 0;\n}\n\n/* weakrtl for selection drop downs needs to account for the fact that\n * Webkit does not honor the text-align attribute for the select element.\n * (See Webkit bug #40216)\n */\nhtml[dir='rtl'] select.weakrtl {\n  direction: rtl;\n}\n\nhtml[dir='rtl'] select.weakrtl option {\n  direction: ltr;\n}\n\n/* WebKit does not honor alignment for text specified via placeholder attribute.\n * This CSS is a workaround. Please remove once WebKit bug is fixed.\n * https://bugs.webkit.org/show_bug.cgi?id=63367\n */\nhtml[dir='rtl'] input.weakrtl::-webkit-input-placeholder,\nhtml[dir='rtl'] .weakrtl input::-webkit-input-placeholder {\n  direction: rtl;\n}\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/css/overlay.css",
    "content": "/* Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file. */\n\n/* The shield that overlays the background. */\n.overlay {\n  -webkit-box-align: center;\n  -webkit-box-orient: vertical;\n  -webkit-box-pack: center;\n  background-color: rgba(255, 255, 255, 0.75);\n  bottom: 0;\n  display: -webkit-box;\n  left: 0;\n  overflow: auto;\n  padding: 20px;\n  position: fixed;\n  right: 0;\n  top: 0;\n  transition: 200ms opacity;\n}\n\n/* Used to slide in the overlay. */\n.overlay.transparent .page {\n  /* TODO(flackr): Add perspective(500px) rotateX(5deg) when accelerated\n   * compositing is enabled on chrome:// pages. See http://crbug.com/116800. */\n  transform: scale(0.99) translateY(-20px);\n}\n\n/* The foreground dialog. */\n.overlay .page {\n  -webkit-border-radius: 3px;\n  -webkit-box-orient: vertical;\n  background: white;\n  box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0,0,0,0.15);\n  color: #333;\n  display: -webkit-box;\n  min-width: 400px;\n  padding: 0;\n  position: relative;\n  transition: 200ms transform;\n}\n\n/* If the options page is loading don't do the transition. */\n.loading .overlay,\n.loading .overlay .page {\n  transition-duration: 0ms !important;\n}\n\n/* keyframes used to pulse the overlay */\n@keyframes pulse {\n 0% {\n   transform: scale(1);\n }\n 40% {\n   transform: scale(1.02);\n  }\n 60% {\n   transform: scale(1.02);\n  }\n 100% {\n   transform: scale(1);\n }\n}\n\n.overlay .page.pulse {\n  animation-duration: 180ms;\n  animation-iteration-count: 1;\n  animation-name: pulse;\n  animation-timing-function: ease-in-out;\n}\n\n.overlay .page > .close-button {\n  background-image: url('../images/x.png');\n  background-position: center;\n  background-repeat: no-repeat;\n  height: 14px;\n  position: absolute;\n  right: 7px;\n  top: 7px;\n  width: 14px;\n}\n\nhtml[dir='rtl'] .overlay .page > .close-button {\n  left: 10px;\n  right: auto;\n}\n\n.overlay .page > .close-button:hover {\n  background-image: url('../images/x-hover.png');\n}\n\n.overlay .page > .close-button:active {\n  background-image: url('../images/x-pressed.png');\n}\n\n.overlay .page h1 {\n  -webkit-user-select: none;\n  color: #333;\n  /* 120% of the body's font-size of 84% is 16px. This will keep the relative\n   * size between the body and these titles consistent. */\n  font-size: 120%;\n  /* TODO(flackr): Pages like sync-setup and delete user collapse the margin\n   * above the top of the page. Use padding instead to make sure that the\n   * headers of these pages have the correct spacing, but this should not be\n   * necessary. See http://crbug.com/119029. */\n  margin: 0;\n  padding: 14px 17px 14px;\n  text-shadow: white 0 1px 2px;\n}\n\n.overlay .page .content-area {\n  -webkit-box-flex: 1;\n  overflow: auto;\n  padding: 6px 17px 6px;\n  position: relative;\n}\n\n.overlay .page .action-area {\n  -webkit-box-align: center;\n  -webkit-box-orient: horizontal;\n  -webkit-box-pack: end;\n  display: -webkit-box;\n  padding: 14px 17px;\n}\n\nhtml[dir='rtl'] .overlay .page .action-area {\n  left: 0;\n}\n\n.overlay .page .action-area-right {\n  display: -webkit-box;\n}\n\n.overlay .page .button-strip {\n  -webkit-box-orient: horizontal;\n  display: -webkit-box;\n}\n\n.overlay .page .button-strip > button {\n  display: block;\n  margin-inline-start: 10px;\n}\n\n/* On OSX 10.7, hidden scrollbars may prevent the user from realizing that the\n * overlay contains scrollable content. To resolve this, style the scrollbars on\n * OSX so they are always visible. See http://crbug.com/123010. */\n<if expr=\"is_macosx\">\n.overlay .page .content-area::-webkit-scrollbar {\n  -webkit-appearance: none;\n  width: 11px;\n}\n\n.overlay .page .content-area::-webkit-scrollbar-thumb {\n  background-color: rgba(0, 0, 0, 0.2);\n  border: 2px solid white;\n  border-radius: 8px;\n}\n\n.overlay .page .content-area::-webkit-scrollbar-thumb:hover {\n  background-color: rgba(0, 0, 0, 0.5);\n}\n</if>\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/css/uber_shared.css",
    "content": "/* Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file. */\n\nbody.uber-frame {\n  color: rgb(48, 57, 66);\n  margin-inline-start: 155px;\n}\n\nhtml[dir='rtl'] body.uber-frame {\n  /* Enable vertical scrollbar at all times in RTL to avoid visual glitches when\n   * showing sub-pages that vertically overflow. */\n  overflow-y: scroll;\n}\n\n/* TODO(dbeam): Remove .page class from overlays in settings so the junk below\n * isn't necessary. */\nbody.uber-frame #extension-settings.page,\nbody.uber-frame #mainview-content .page,\nbody.uber-frame .subpage-sheet-container .page,\nbody.uber-frame > .page {\n  margin-inline-end: 24px;\n  min-width: 576px;\n  padding-bottom: 20px;\n  padding-top: 55px;\n}\n\nbody.uber-frame header {\n  background-image: -webkit-linear-gradient(white,\n                                            white 40%,\n                                            rgba(255, 255, 255, 0.92));\n  left: 155px;\n  /* <section>s in options currently amount to 638px total, broken up into\n   * 600px max-width + 18px padding-inline-start + 20px margin-inline-end\n   * so we mirror this value here so the headers match width and horizontal\n   * alignment when scrolling sideways. */\n  max-width: 738px;\n  min-width: 600px;\n  position: fixed;\n  right: 0;\n  top: 0;\n  /* list.css sets a z-index of up to 2, this is set to 3 to ensure that the\n   * header is in front of the selected list item. */\n  z-index: 3;\n}\n\nhtml[dir='rtl'] body.uber-frame header {\n  left: 0;\n  right: 155px;\n}\n\nbody.uber-frame header > .search-field-container,\nbody.uber-frame header > .header-extras,\nbody.uber-frame header > button {\n  position: absolute;\n  right: 20px;\n  top: 21px;\n}\n\nhtml[dir='rtl'] body.uber-frame header > .search-field-container,\nhtml[dir='rtl'] body.uber-frame header > .header-extras,\nhtml[dir='rtl'] body.uber-frame header > button {\n  left: 20px;\n  right: auto;\n}\n\nbody.uber-frame header input[type='search'],\nbody.uber-frame header input[type='text'],\nbody.uber-frame header button {\n  margin: 0;\n}\n\nbody.uber-frame header > h1 {\n  margin: 0;\n  padding: 21px 0 13px;\n}\n\n/* Create a border under the h1 (but before anything that gets appended\n * to the end of the header). */\nbody.uber-frame header > h1::after {\n  background-color: #eee;\n  content: ' ';\n  display: block;\n  height: 1px;\n  margin-inline-end: 20px;\n  position: relative;\n  top: 13px;\n}\n\nbody.uber-frame footer {\n  border-top: 1px solid #eee;\n  margin-top: 16px;\n  /* min-width and max-width should match the header */\n  max-width: 638px;\n  min-width: 600px;\n  padding: 8px 0;\n}\n\n/* Sections are used in options pages, help page and history page. This defines\n * the section metrics to match the header metrics above. */\nbody.uber-frame section {\n  margin-bottom: 24px;\n  margin-top: 8px;\n  max-width: 600px;\n  padding-inline-start: 18px;\n}\n\nbody.uber-frame section:last-of-type {\n  margin-bottom: 0;\n}\n\nbody.uber-frame section > h3 {\n  margin-inline-start: -18px;\n}\n\nbody.uber-frame section > div:only-of-type {\n  -webkit-box-flex: 1;\n}\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/css/widgets.css",
    "content": "/* Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n/* This file defines styles for form controls. The order of rule blocks is\n * important as there are some rules with equal specificity that rely on order\n * as a tiebreaker. These are marked with OVERRIDE.\n */\n\n/* Default state **************************************************************/\n\n:-webkit-any(button,\n             input[type='button'],\n             input[type='submit']):not(.custom-appearance):not(.link-button),\nselect,\ninput[type='checkbox'],\ninput[type='radio'] {\n  -webkit-appearance: none;\n  -webkit-user-select: none;\n  background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);\n  border: 1px solid rgba(0, 0, 0, 0.25);\n  border-radius: 2px;\n  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08),\n      inset 0 1px 2px rgba(255, 255, 255, 0.75);\n  color: #444;\n  font: inherit;\n  margin: 0 1px 0 0;\n  text-shadow: 0 1px 0 rgb(240, 240, 240);\n}\n\n:-webkit-any(button,\n             input[type='button'],\n             input[type='submit']):not(.custom-appearance):not(.link-button),\nselect {\n  min-height: 2em;\n  min-width: 4em;\n<if expr=\"is_win\">\n  /* The following platform-specific rule is necessary to get adjacent\n   * buttons, text inputs, and so forth to align on their borders while also\n   * aligning on the text's baselines. */\n  padding-bottom: 1px;\n</if>\n}\n\n:-webkit-any(button,\n             input[type='button'],\n             input[type='submit']):not(.custom-appearance):not(.link-button) {\n  padding-inline-end: 10px;\n  padding-inline-start: 10px;\n}\n\nselect {\n  -webkit-appearance: none;\n  /* OVERRIDE */\n  background-image: url('../images/select.png'),\n      -webkit-linear-gradient(#ededed, #ededed 38%, #dedede);\n  background-position: right center;\n  background-repeat: no-repeat;\n  padding-inline-end: 20px;\n  padding-inline-start: 6px;\n}\n\nhtml[dir='rtl'] select {\n  background-position: center left;\n}\n\ninput[type='checkbox'] {\n  bottom: 2px;\n  height: 13px;\n  position: relative;\n  vertical-align: middle;\n  width: 13px;\n}\n\ninput[type='radio'] {\n  /* OVERRIDE */\n  border-radius: 100%;\n  bottom: 3px;\n  height: 15px;\n  position: relative;\n  vertical-align: middle;\n  width: 15px;\n}\n\n/* TODO(estade): add more types here? */\ninput[type='password'],\ninput[type='search'],\ninput[type='text'],\ninput[type='url'],\ninput[type='number'],\ninput:not([type]),\ntextarea {\n  border: 1px solid #bfbfbf;\n  border-radius: 2px;\n  box-sizing: border-box;\n  color: #444;\n  font: inherit;\n  margin: 0;\n  /* Use min-height to accommodate addditional padding for touch as needed. */\n  min-height: 2em;\n  padding: 3px;\n<if expr=\"is_win or is_macosx\">\n  /* For better alignment between adjacent buttons and inputs. */\n  padding-bottom: 4px;\n</if>\n}\n\ninput[type='search'] {\n  -webkit-appearance: textfield;\n  /* NOTE: Keep a relatively high min-width for this so we don't obscure the end\n   * of the default text in relatively spacious languages (i.e. German). */\n  min-width: 160px;\n}\n\n/* Checked ********************************************************************/\n\ninput[type='checkbox']:checked::before {\n  -webkit-user-select: none;\n  background-image: url('../images/check.png');\n  background-size: 100% 100%;\n  content: '';\n  display: block;\n  height: 100%;\n  width: 100%;\n}\n\nhtml[dir='rtl'] input[type='checkbox']:checked::before {\n  transform: scaleX(-1);\n}\n\ninput[type='radio']:checked::before {\n  background-color: #666;\n  border-radius: 100%;\n  bottom: 3px;\n  content: '';\n  display: block;\n  left: 3px;\n  position: absolute;\n  right: 3px;\n  top: 3px;\n}\n\n/* Hover **********************************************************************/\n\n:enabled:hover:-webkit-any(\n    select,\n    input[type='checkbox'],\n    input[type='radio'],\n    :-webkit-any(\n        button,\n        input[type='button'],\n        input[type='submit']):not(.custom-appearance):not(.link-button)) {\n  background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0);\n  border-color: rgba(0, 0, 0, 0.3);\n  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12),\n      inset 0 1px 2px rgba(255, 255, 255, 0.95);\n  color: black;\n}\n\n:enabled:hover:-webkit-any(select) {\n  /* OVERRIDE */\n  background-image: url('../images/select.png'),\n      -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0);\n}\n\n/* Active *********************************************************************/\n\n:enabled:active:-webkit-any(\n    select,\n    input[type='checkbox'],\n    input[type='radio'],\n    :-webkit-any(\n        button,\n        input[type='button'],\n        input[type='submit']):not(.custom-appearance):not(.link-button)) {\n  background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);\n  box-shadow: none;\n  text-shadow: none;\n}\n\n:enabled:active:-webkit-any(select) {\n  /* OVERRIDE */\n  background-image: url('../images/select.png'),\n      -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7);\n}\n\n/* Disabled *******************************************************************/\n\n:disabled:-webkit-any(\n    button,\n    input[type='button'],\n    input[type='submit']):not(.custom-appearance):not(.link-button),\nselect:disabled {\n  background-image: -webkit-linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6);\n  border-color: rgba(80, 80, 80, 0.2);\n  box-shadow: 0 1px 0 rgba(80, 80, 80, 0.08),\n      inset 0 1px 2px rgba(255, 255, 255, 0.75);\n  color: #aaa;\n}\n\nselect:disabled {\n  /* OVERRIDE */\n  background-image: url('../images/disabled_select.png'),\n      -webkit-linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6);\n}\n\ninput:disabled:-webkit-any([type='checkbox'],\n                           [type='radio']) {\n  opacity: .75;\n}\n\ninput:disabled:-webkit-any([type='password'],\n                           [type='search'],\n                           [type='text'],\n                           [type='url'],\n                           :not([type])) {\n  color: #999;\n}\n\n/* Focus **********************************************************************/\n\n:enabled:focus:-webkit-any(\n    select,\n    input[type='checkbox'],\n    input[type='password'],\n    input[type='radio'],\n    input[type='search'],\n    input[type='text'],\n    input[type='url'],\n    input:not([type]),\n    :-webkit-any(\n         button,\n         input[type='button'],\n         input[type='submit']):not(.custom-appearance):not(.link-button)) {\n  /* OVERRIDE */\n  transition: border-color 200ms;\n  /* We use border color because it follows the border radius (unlike outline).\n   * This is particularly noticeable on mac. */\n  border-color: rgb(77, 144, 254);\n  outline: none;\n}\n\n/* Link buttons ***************************************************************/\n\n.link-button {\n  -webkit-box-shadow: none;\n  background: transparent none;\n  border: none;\n  color: rgb(17, 85, 204);\n  cursor: pointer;\n  /* Input elements have -webkit-small-control which can override the body font.\n   * Resolve this by using 'inherit'. */\n  font: inherit;\n  margin: 0;\n  padding: 0 4px;\n}\n\n.link-button:hover {\n  text-decoration: underline;\n}\n\n.link-button:active {\n  color: rgb(5, 37, 119);\n  text-decoration: underline;\n}\n\n.link-button[disabled] {\n  color: #999;\n  cursor: default;\n  text-decoration: none;\n}\n\n/* Checkbox/radio helpers ******************************************************\n *\n * .checkbox and .radio classes wrap labels. Checkboxes and radios should use\n * these classes with the markup structure:\n *\n *   <div class=\"checkbox\">\n *     <label>\n *       <input type=\"checkbox\"></input>\n *       <span>\n *     </label>\n *   </div>\n */\n\n:-webkit-any(.checkbox, .radio) label {\n  /* Don't expand horizontally: <http://crbug.com/112091>. */\n  display: -webkit-inline-box;\n  padding-bottom: 7px;\n  padding-top: 7px;\n}\n\n:-webkit-any(.checkbox, .radio) label input ~ span {\n  /* Make sure long spans wrap at the same horizontal position they start. */\n  display: block;\n  margin-inline-start: 0.6em;\n}\n\n:-webkit-any(.checkbox, .radio) label:hover {\n  color: black;\n}\n\nlabel > input:disabled:-webkit-any([type='checkbox'], [type='radio']) ~ span {\n  color: #999;\n}\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/js/cr/ui/overlay.js",
    "content": "/* eslint-disable no-undef */\n// Ported from MV2 samples. Some coding practices are non-standard in MV3, but the sample remains a robust demonstration of the chrome.fontsettings API.\n// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n/**\n * @fileoverview Provides dialog-like behaviors for the tracing UI.\n */\ncr.define('cr.ui.overlay', function () {\n  /**\n   * Gets the top, visible overlay. It makes the assumption that if multiple\n   * overlays are visible, the last in the byte order is topmost.\n   * TODO(estade): rely on aria-visibility instead?\n   * @return {HTMLElement} The overlay.\n   */\n  function getTopOverlay() {\n    let overlays = document.querySelectorAll('.overlay:not([hidden])');\n    return overlays[overlays.length - 1];\n  }\n\n  /**\n   * Makes initializations which must hook at the document level.\n   */\n  function globalInitialization() {\n    // Close the overlay on escape.\n    document.addEventListener('keydown', function () {\n      // Escape\n      let overlay = getTopOverlay();\n      if (!overlay) return;\n\n      cr.dispatchSimpleEvent(overlay, 'cancelOverlay');\n    });\n\n    window.addEventListener('resize', setMaxHeightAllPages);\n\n    setMaxHeightAllPages();\n  }\n\n  /**\n   * Sets the max-height of all pages in all overlays, based on the window\n   * height.\n   */\n  function setMaxHeightAllPages() {\n    let pages = document.querySelectorAll('.overlay .page');\n\n    let maxHeight = Math.min(0.9 * window.innerHeight, 640) + 'px';\n    for (let i = 0; i < pages.length; i++) pages[i].style.maxHeight = maxHeight;\n  }\n\n  /**\n   * Adds behavioral hooks for the given overlay.\n   * @param {HTMLElement} overlay The .overlay.\n   */\n  function setupOverlay(overlay) {\n    // Close the overlay on clicking any of the pages' close buttons.\n    let closeButtons = overlay.querySelectorAll('.page > .close-button');\n    for (let i = 0; i < closeButtons.length; i++) {\n      closeButtons[i].addEventListener('click', function () {\n        cr.dispatchSimpleEvent(overlay, 'cancelOverlay');\n      });\n    }\n\n    // Remove the 'pulse' animation any time the overlay is hidden or shown.\n    overlay.__defineSetter__('hidden', function (value) {\n      this.classList.remove('pulse');\n      if (value) this.setAttribute('hidden', true);\n      else this.removeAttribute('hidden');\n    });\n    overlay.__defineGetter__('hidden', function () {\n      return this.hasAttribute('hidden');\n    });\n\n    // Shake when the user clicks away.\n    overlay.addEventListener('click', function () {\n      // This may be null while the overlay is closing.\n      let overlayPage = this.querySelector('.page:not([hidden])');\n      if (overlayPage) overlayPage.classList.add('pulse');\n    });\n  }\n\n  return {\n    globalInitialization: globalInitialization,\n    setupOverlay: setupOverlay\n  };\n});\n\ndocument.addEventListener(\n  'DOMContentLoaded',\n  cr.ui.overlay.globalInitialization\n);\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/js/cr/ui.js",
    "content": "/* eslint-disable no-undef */\n// Ported from MV2 samples. Some coding practices are non-standard in MV3, but the sample remains a robust demonstration of the chrome.fontsettings API.\n// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\ncr.define('cr.ui', function () {\n  /**\n   * Decorates elements as an instance of a class.\n   * @param {string|!Element} source The way to find the element(s) to decorate.\n   *     If this is a string then {@code querySeletorAll} is used to find the\n   *     elements to decorate.\n   * @param {!Function} constr The constructor to decorate with. The constr\n   *     needs to have a {@code decorate} function.\n   */\n  function decorate(source, constr) {\n    let elements;\n    if (typeof source == 'string') elements = cr.doc.querySelectorAll(source);\n    else elements = [source];\n\n    for (let i = 0, el; (el = elements[i]); i++) {\n      if (!(el instanceof constr)) constr.decorate(el);\n    }\n  }\n\n  /**\n   * Helper function for creating new element for define.\n   */\n  function createElementHelper(tagName, opt_bag) {\n    // Allow passing in ownerDocument to create in a different document.\n    let doc;\n    if (opt_bag && opt_bag.ownerDocument) doc = opt_bag.ownerDocument;\n    else doc = cr.doc;\n    return doc.createElement(tagName);\n  }\n\n  /**\n   * Creates the constructor for a UI element class.\n   *\n   * Usage:\n   * <pre>\n   * var List = cr.ui.define('list');\n   * List.prototype = {\n   *   __proto__: HTMLUListElement.prototype,\n   *   decorate: function() {\n   *     ...\n   *   },\n   *   ...\n   * };\n   * </pre>\n   *\n   * @param {string|Function} tagNameOrFunction The tagName or\n   *     function to use for newly created elements. If this is a function it\n   *     needs to return a new element when called.\n   * @return {function(Object=):Element} The constructor function which takes\n   *     an optional property bag. The function also has a static\n   *     {@code decorate} method added to it.\n   */\n  function define(tagNameOrFunction) {\n    let createFunction, tagName;\n    if (typeof tagNameOrFunction == 'function') {\n      createFunction = tagNameOrFunction;\n      tagName = '';\n    } else {\n      createFunction = createElementHelper;\n      tagName = tagNameOrFunction;\n    }\n\n    /**\n     * Creates a new UI element constructor.\n     * @param {Object=} opt_propertyBag Optional bag of properties to set on the\n     *     object after created. The property {@code ownerDocument} is special\n     *     cased and it allows you to create the element in a different\n     *     document than the default.\n     * @constructor\n     */\n    function f(opt_propertyBag) {\n      let el = createFunction(tagName, opt_propertyBag);\n      f.decorate(el);\n      for (let propertyName in opt_propertyBag) {\n        el[propertyName] = opt_propertyBag[propertyName];\n      }\n      return el;\n    }\n\n    /**\n     * Decorates an element as a UI element class.\n     * @param {!Element} el The element to decorate.\n     */\n    f.decorate = function (el) {\n      el.__proto__ = f.prototype;\n      el.decorate();\n    };\n\n    return f;\n  }\n\n  /**\n   * Input elements do not grow and shrink with their content. This is a simple\n   * (and not very efficient) way of handling shrinking to content with support\n   * for min width and limited by the width of the parent element.\n   * @param {HTMLElement} el The element to limit the width for.\n   * @param {number} parentEl The parent element that should limit the size.\n   * @param {number} min The minimum width.\n   * @param {number} opt_scale Optional scale factor to apply to the width.\n   */\n  function limitInputWidth(el, parentEl, min, opt_scale) {\n    // Needs a size larger than borders\n    el.style.width = '10px';\n    let doc = el.ownerDocument;\n    let win = doc.defaultView;\n    let computedStyle = win.getComputedStyle(el);\n    let parentComputedStyle = win.getComputedStyle(parentEl);\n    let rtl = computedStyle.direction == 'rtl';\n\n    // To get the max width we get the width of the treeItem minus the position\n    // of the input.\n    let inputRect = el.getBoundingClientRect(); // box-sizing\n    let parentRect = parentEl.getBoundingClientRect();\n    let startPos = rtl\n      ? parentRect.right - inputRect.right\n      : inputRect.left - parentRect.left;\n\n    // Add up border and padding of the input.\n    let inner =\n      parseInt(computedStyle.borderLeftWidth, 10) +\n      parseInt(computedStyle.paddingLeft, 10) +\n      parseInt(computedStyle.paddingRight, 10) +\n      parseInt(computedStyle.borderRightWidth, 10);\n\n    // We also need to subtract the padding of parent to prevent it to overflow.\n    let parentPadding = rtl\n      ? parseInt(parentComputedStyle.paddingLeft, 10)\n      : parseInt(parentComputedStyle.paddingRight, 10);\n\n    let max = parentEl.clientWidth - startPos - inner - parentPadding;\n    if (opt_scale) max *= opt_scale;\n\n    function limit() {\n      if (el.scrollWidth > max) {\n        el.style.width = max + 'px';\n      } else {\n        el.style.width = 0;\n        let sw = el.scrollWidth;\n        if (sw < min) {\n          el.style.width = min + 'px';\n        } else {\n          el.style.width = sw + 'px';\n        }\n      }\n    }\n\n    el.addEventListener('input', limit);\n    limit();\n  }\n\n  /**\n   * Takes a number and spits out a value CSS will be happy with. To avoid\n   * subpixel layout issues, the value is rounded to the nearest integral value.\n   * @param {number} pixels The number of pixels.\n   * @return {string} e.g. '16px'.\n   */\n  function toCssPx(pixels) {\n    if (!window.isFinite(pixels))\n      console.error('Pixel value is not a number: ' + pixels);\n    return Math.round(pixels) + 'px';\n  }\n\n  return {\n    decorate: decorate,\n    define: define,\n    limitInputWidth: limitInputWidth,\n    toCssPx: toCssPx\n  };\n});\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/js/cr.js",
    "content": "/* eslint-disable no-undef */\n/* eslint-disable no-prototype-builtins */\n/* eslint-disable no-case-declarations */\n// Ported from MV2 samples. Some coding practices are non-standard in MV3, but the sample remains a robust demonstration of the chrome.fontsettings API.\n// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n/**\n * The global object.\n * @type {!Object}\n * @const\n */\nlet global = this;\n\n/** Platform, package, object property, and Event support. **/\nthis.cr = (function () {\n  'use strict';\n\n  /**\n   * Builds an object structure for the provided namespace path,\n   * ensuring that names that already exist are not overwritten. For\n   * example:\n   * \"a.b.c\" -> a = {};a.b={};a.b.c={};\n   * @param {string} name Name of the object that this file defines.\n   * @param {*=} opt_object The object to expose at the end of the path.\n   * @param {Object=} opt_objectToExportTo The object to add the path to;\n   *     default is {@code global}.\n   * @private\n   */\n  function exportPath(name, opt_object, opt_objectToExportTo) {\n    let parts = name.split('.');\n    let cur = opt_objectToExportTo || global;\n\n    for (let part; parts.length && (part = parts.shift()); ) {\n      if (!parts.length && opt_object !== undefined) {\n        // last part and we have an object; use it\n        cur[part] = opt_object;\n      } else if (part in cur) {\n        cur = cur[part];\n      } else {\n        cur = cur[part] = {};\n      }\n    }\n    return cur;\n  }\n\n  /**\n   * Fires a property change event on the target.\n   * @param {EventTarget} target The target to dispatch the event on.\n   * @param {string} propertyName The name of the property that changed.\n   * @param {*} newValue The new value for the property.\n   * @param {*} oldValue The old value for the property.\n   */\n  function dispatchPropertyChange(target, propertyName, newValue, oldValue) {\n    let e = new Event(propertyName + 'Change');\n    e.propertyName = propertyName;\n    e.newValue = newValue;\n    e.oldValue = oldValue;\n    target.dispatchEvent(e);\n  }\n\n  /**\n   * Converts a camelCase javascript property name to a hyphenated-lower-case\n   * attribute name.\n   * @param {string} jsName The javascript camelCase property name.\n   * @return {string} The equivalent hyphenated-lower-case attribute name.\n   */\n  function getAttributeName(jsName) {\n    return jsName.replace(/([A-Z])/g, '-$1').toLowerCase();\n  }\n\n  /**\n   * The kind of property to define in {@code defineProperty}.\n   * @enum {number}\n   * @const\n   */\n  let PropertyKind = {\n    /**\n     * Plain old JS property where the backing data is stored as a \"private\"\n     * field on the object.\n     */\n    JS: 'js',\n\n    /**\n     * The property backing data is stored as an attribute on an element.\n     */\n    ATTR: 'attr',\n\n    /**\n     * The property backing data is stored as an attribute on an element. If the\n     * element has the attribute then the value is true.\n     */\n    BOOL_ATTR: 'boolAttr'\n  };\n\n  /**\n   * Helper function for defineProperty that returns the getter to use for the\n   * property.\n   * @param {string} name The name of the property.\n   * @param {cr.PropertyKind} kind The kind of the property.\n   * @return {function():*} The getter for the property.\n   */\n  function getGetter(name, kind) {\n    switch (kind) {\n      case PropertyKind.JS:\n        let privateName = name + '_';\n        let attributeName = null;\n        return function () {\n          return this[privateName];\n        };\n      case PropertyKind.ATTR:\n        attributeName = getAttributeName(name);\n        return function () {\n          return this.getAttribute(attributeName);\n        };\n      case PropertyKind.BOOL_ATTR:\n        attributeName = getAttributeName(name);\n        return function () {\n          return this.hasAttribute(attributeName);\n        };\n    }\n  }\n\n  /**\n   * Helper function for defineProperty that returns the setter of the right\n   * kind.\n   * @param {string} name The name of the property we are defining the setter\n   *     for.\n   * @param {cr.PropertyKind} kind The kind of property we are getting the\n   *     setter for.\n   * @param {function(*):void} opt_setHook A function to run after the property\n   *     is set, but before the propertyChange event is fired.\n   * @return {function(*):void} The function to use as a setter.\n   */\n  function getSetter(name, kind, opt_setHook) {\n    switch (kind) {\n      case PropertyKind.JS:\n        let privateName = name + '_';\n        return function (value) {\n          let oldValue = this[name];\n          if (value !== oldValue) {\n            this[privateName] = value;\n            if (opt_setHook) opt_setHook.call(this, value, oldValue);\n            dispatchPropertyChange(this, name, value, oldValue);\n          }\n        };\n\n      case PropertyKind.ATTR:\n        attributeName = getAttributeName(name);\n        return function (value) {\n          let oldValue = this[name];\n          if (value !== oldValue) {\n            if (value == undefined) this.removeAttribute(attributeName);\n            else this.setAttribute(attributeName, value);\n            if (opt_setHook) opt_setHook.call(this, value, oldValue);\n            dispatchPropertyChange(this, name, value, oldValue);\n          }\n        };\n\n      case PropertyKind.BOOL_ATTR:\n        let attributeName = getAttributeName(name);\n        return function (value) {\n          let oldValue = this[name];\n          if (value !== oldValue) {\n            if (value) this.setAttribute(attributeName, name);\n            else this.removeAttribute(attributeName);\n            if (opt_setHook) opt_setHook.call(this, value, oldValue);\n            dispatchPropertyChange(this, name, value, oldValue);\n          }\n        };\n    }\n  }\n\n  /**\n   * Defines a property on an object. When the setter changes the value a\n   * property change event with the type {@code name + 'Change'} is fired.\n   * @param {!Object} obj The object to define the property for.\n   * @param {string} name The name of the property.\n   * @param {cr.PropertyKind=} opt_kind What kind of underlying storage to use.\n   * @param {function(*):void} opt_setHook A function to run after the\n   *     property is set, but before the propertyChange event is fired.\n   */\n  function defineProperty(obj, name, opt_kind, opt_setHook) {\n    if (typeof obj == 'function') obj = obj.prototype;\n\n    let kind = opt_kind || PropertyKind.JS;\n\n    if (!obj.__lookupGetter__(name))\n      obj.__defineGetter__(name, getGetter(name, kind));\n\n    if (!obj.__lookupSetter__(name))\n      obj.__defineSetter__(name, getSetter(name, kind, opt_setHook));\n  }\n\n  /**\n   * Counter for use with createUid\n   */\n  let uidCounter = 1;\n\n  /**\n   * @return {number} A new unique ID.\n   */\n  function createUid() {\n    return uidCounter++;\n  }\n\n  /**\n   * Returns a unique ID for the item. This mutates the item so it needs to be\n   * an object\n   * @param {!Object} item The item to get the unique ID for.\n   * @return {number} The unique ID for the item.\n   */\n  function getUid(item) {\n    if (item.hasOwnProperty('uid')) return item.uid;\n    return (item.uid = createUid());\n  }\n\n  /**\n   * Dispatches a simple event on an event target.\n   * @param {!EventTarget} target The event target to dispatch the event on.\n   * @param {string} type The type of the event.\n   * @param {boolean=} opt_bubbles Whether the event bubbles or not.\n   * @param {boolean=} opt_cancelable Whether the default action of the event\n   *     can be prevented. Default is true.\n   * @return {boolean} If any of the listeners called {@code preventDefault}\n   *     during the dispatch this will return false.\n   */\n  function dispatchSimpleEvent(target, type, opt_bubbles, opt_cancelable) {\n    let e = new Event(type, {\n      bubbles: opt_bubbles,\n      cancelable: opt_cancelable === undefined || opt_cancelable\n    });\n    return target.dispatchEvent(e);\n  }\n\n  /**\n   * Calls |fun| and adds all the fields of the returned object to the object\n   * named by |name|. For example, cr.define('cr.ui', function() {\n   *   function List() {\n   *     ...\n   *   }\n   *   function ListItem() {\n   *     ...\n   *   }\n   *   return {\n   *     List: List,\n   *     ListItem: ListItem,\n   *   };\n   * });\n   * defines the functions cr.ui.List and cr.ui.ListItem.\n   * @param {string} name The name of the object that we are adding fields to.\n   * @param {!Function} fun The function that will return an object containing\n   *     the names and values of the new fields.\n   */\n  function define(name, fun) {\n    let obj = exportPath(name);\n    let exports = fun();\n    for (let propertyName in exports) {\n      // Maybe we should check the prototype chain here? The current usage\n      // pattern is always using an object literal so we only care about own\n      // properties.\n      let propertyDescriptor = Object.getOwnPropertyDescriptor(\n        exports,\n        propertyName\n      );\n      if (propertyDescriptor)\n        Object.defineProperty(obj, propertyName, propertyDescriptor);\n    }\n  }\n\n  /**\n   * Adds a {@code getInstance} static method that always return the same\n   * instance object.\n   * @param {!Function} ctor The constructor for the class to add the static\n   *     method to.\n   */\n  function addSingletonGetter(ctor) {\n    ctor.getInstance = function () {\n      return ctor.instance_ || (ctor.instance_ = new ctor());\n    };\n  }\n\n  /**\n   * Initialization which must be deferred until run-time.\n   */\n  function initialize() {\n    // If 'document' isn't defined, then we must be being pre-compiled,\n    // so set a trap so that we're initialized on first access at run-time.\n    if (!global.document) {\n      let originalCr = cr;\n\n      Object.defineProperty(global, 'cr', {\n        get: function () {\n          Object.defineProperty(global, 'cr', { value: originalCr });\n          originalCr.initialize();\n          return originalCr;\n        },\n        configurable: true\n      });\n\n      return;\n    }\n\n    cr.doc = document;\n\n    /**\n     * Whether we are using a Mac or not.\n     */\n    cr.isMac = /Mac/.test(navigator.platform);\n\n    /**\n     * Whether this is on the Windows platform or not.\n     */\n    cr.isWindows = /Win/.test(navigator.platform);\n\n    /**\n     * Whether this is on chromeOS or not.\n     */\n    cr.isChromeOS = /CrOS/.test(navigator.userAgent);\n\n    /**\n     * Whether this is on vanilla Linux (not chromeOS).\n     */\n    cr.isLinux = /Linux/.test(navigator.userAgent);\n  }\n\n  return {\n    addSingletonGetter: addSingletonGetter,\n    createUid: createUid,\n    define: define,\n    defineProperty: defineProperty,\n    dispatchPropertyChange: dispatchPropertyChange,\n    dispatchSimpleEvent: dispatchSimpleEvent,\n    getUid: getUid,\n    initialize: initialize,\n    PropertyKind: PropertyKind\n  };\n})();\n\n/**\n * TODO(kgr): Move this to another file which is to be loaded last.\n * This will be done as part of future work to make this code pre-compilable.\n */\ncr.initialize();\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/manifest.json",
    "content": "{\n  \"name\": \"Advanced Font Settings\",\n  \"version\": \"0.71\",\n  \"manifest_version\": 3,\n  \"description\": \"Demonstrates the chrome.fontSettings API by allowing users to modify the style of displayed fonts on web pages.\",\n  \"options_page\": \"options.html\",\n  \"icons\": {\n    \"16\": \"fonts16.png\",\n    \"128\": \"fonts128.png\"\n  },\n  \"permissions\": [\"fontSettings\"]\n}\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/options.html",
    "content": "<!--\n Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Advanced Font Settings</title>\n    <script src=\"js/cr.js\"></script>\n    <script src=\"js/cr/ui.js\"></script>\n    <script src=\"js/cr/ui/overlay.js\"></script>\n    <script src=\"slider.js\"></script>\n    <script src=\"pending_changes.js\"></script>\n    <script src=\"options.js\"></script>\n    <link rel=\"stylesheet\" href=\"css/chrome_shared.css\" />\n    <link rel=\"stylesheet\" href=\"css/overlay.css\" />\n    <link rel=\"stylesheet\" href=\"css/widgets.css\" />\n    <link rel=\"stylesheet\" href=\"css/uber_shared.css\" />\n    <link rel=\"stylesheet\" href=\"slider.css\" />\n    <style>\n      body.uber-frame {\n        margin-inline-start: 18px;\n        margin-inline-end: 30px;\n      }\n\n      body.uber-frame section {\n        max-width: 650px;\n      }\n\n      body.uber-frame section:last-of-type {\n        margin-top: 28px;\n      }\n\n      body.uber-frame header {\n        left: 0;\n        padding-inline-start: 18px;\n        right: 0;\n      }\n\n      body.uber-frame header > h1 {\n        padding-bottom: 16px;\n      }\n\n      h1 {\n        font-size: 16px;\n      }\n\n      .script-header {\n        margin-top: 12px;\n      }\n\n      h3 {\n        margin-bottom: 11px;\n        font-size: 14px;\n      }\n\n      section {\n        font-size: 12px;\n      }\n\n      .bordered {\n        border: 1px solid #d9d9d9;\n        border-radius: 2px;\n      }\n\n      .smaller {\n        font-size: smaller;\n      }\n\n      .font-settings-div {\n        margin-inline-end: 5px;\n        width: 180px;\n      }\n\n      .font-settings-div:first-of-type {\n        width: 138px;\n      }\n\n      .font-settings-div > :first-child {\n        margin-bottom: 10px;\n      }\n\n      .font-settings-div > * {\n        margin-bottom: 14px;\n      }\n\n      .font-settings-row {\n        display: -webkit-flex;\n        width: 800px;\n      }\n\n      .sample-text-div {\n        display: -webkit-flex;\n        white-space: nowrap;\n        width: 100%;\n        overflow: hidden;\n      }\n\n      .sample-text-span {\n        margin-top: auto;\n        margin-bottom: auto;\n        margin-left: 20px;\n      }\n\n      #overlay-container {\n        z-index: 100;\n      }\n\n      #standardFontSample {\n        font-family: standard;\n      }\n\n      #serifFontSample {\n        font-family: serif;\n      }\n\n      #sansSerifFontSample {\n        font-family: sans-serif;\n      }\n\n      #fixedFontSample {\n        font-family: monospace;\n      }\n\n      #minFontSample {\n        font-family: standard;\n      }\n\n      select {\n        width: 100%;\n      }\n\n      #footer > button {\n        padding-inline-start: 9px;\n        padding-inline-end: 9px;\n      }\n\n      #footer > #apply-settings {\n        padding-inline-start: 17px;\n        padding-inline-end: 17px;\n      }\n\n      #apply-settings:enabled {\n        background-color: #4f7dd6;\n        background-image: none;\n        border-color: #2a4aac;\n        box-shadow: none;\n        color: #fbfafb;\n        text-shadow: none;\n      }\n\n      .slider-legend {\n        position: relative;\n        /* This offset is needed to get the legend to align with the slider. */\n        top: -7px;\n      }\n\n      .slider-container {\n        display: inline-block;\n        position: relative;\n        top: 1px;\n        height: 24px;\n        width: 88px;\n      }\n    </style>\n  </head>\n  <body class=\"uber-frame\">\n    <div id=\"overlay-container\" class=\"overlay\" hidden>\n      <div id=\"reset-overlay\" class=\"page\">\n        <div class=\"close-button\"></div>\n        <div id=\"reset-this-script-overlay-dialog\" hidden>\n          <h1>Reset</h1>\n          <div\n            id=\"reset-this-script-overlay-dialog-content\"\n            class=\"content-area\"\n          ></div>\n          <div class=\"action-area\">\n            <div class=\"button-strip\">\n              <button id=\"reset-this-script-cancel\">Cancel</button>\n              <button id=\"reset-this-script-ok\">Reset</button>\n            </div>\n          </div>\n        </div>\n        <div id=\"reset-all-scripts-overlay-dialog\" hidden>\n          <h1>Reset</h1>\n          <div class=\"content-area\">\n            Are you sure you want to reset all settings?\n          </div>\n          <div class=\"action-area\">\n            <div class=\"button-strip\">\n              <button id=\"reset-all-cancel\">Cancel</button>\n              <button id=\"reset-all-ok\">Reset</button>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n    <div class=\"page\">\n      <header style=\"transform: translateX(0px)\">\n        <h1>Advanced Font Settings</h1>\n      </header>\n      <section>\n        <h3 class=\"script-header\">Script</h3>\n        <div class=\"font-settings-row\">\n          <select style=\"width: 200px\" id=\"scriptList\"></select>\n        </div>\n      </section>\n      <section>\n        <h3>Proportional fonts</h3>\n        <div class=\"font-settings-row\">\n          <div class=\"font-settings-div\">\n            <div id=\"defaultFontSizeLabel\"></div>\n            <div style=\"width: 100%; margin-bottom: 0\">\n              <span class=\"slider-legend smaller\">Aa</span>\n              <div\n                id=\"defaultFontSizeSliderContainer\"\n                class=\"slider-container\"\n              ></div>\n              <span class=\"slider-legend\">Aa</span>\n            </div>\n          </div>\n          <div class=\"font-settings-div\">\n            <div>Standard</div>\n            <div><select id=\"standardFontList\"></select></div>\n          </div>\n          <div class=\"font-settings-div\">\n            <div>Serif</div>\n            <div><select id=\"serifFontList\"></select></div>\n          </div>\n          <div class=\"font-settings-div\">\n            <div>Sans-Serif</div>\n            <div><select id=\"sansSerifFontList\"></select></div>\n          </div>\n        </div>\n        <div\n          class=\"bordered\"\n          style=\"\n            position: relative;\n            left: 0;\n            right: 0;\n            height: 160px;\n            width: 702px;\n          \"\n        >\n          <div class=\"sample-text-div\" style=\"height: 33%\">\n            <span id=\"standardFontSample\" class=\"sample-text-span\">\n              The quick brown fox jumps over the lazy dog.\n            </span>\n          </div>\n          <div class=\"sample-text-div\" style=\"height: 33%\">\n            <span id=\"serifFontSample\" class=\"sample-text-span\">\n              The quick brown fox jumps over the lazy dog.\n            </span>\n          </div>\n          <div class=\"sample-text-div\" style=\"height: 33%\">\n            <span id=\"sansSerifFontSample\" class=\"sample-text-span\">\n              The quick brown fox jumps over the lazy dog.\n            </span>\n          </div>\n        </div>\n      </section>\n      <section>\n        <h3>Fixed-width fonts</h3>\n        <div class=\"font-settings-row\">\n          <div class=\"font-settings-div\">\n            <div id=\"fixedFontSizeLabel\"></div>\n            <div style=\"width: 100%; margin-bottom: 0\">\n              <span class=\"slider-legend smaller\">Aa</span>\n              <div\n                id=\"defaultFixedFontSizeSliderContainer\"\n                class=\"slider-container\"\n              ></div>\n              <span class=\"slider-legend\">Aa</span>\n            </div>\n          </div>\n          <div class=\"font-settings-div\">\n            <div>Fixed</div>\n            <div><select id=\"fixedFontList\"></select></div>\n          </div>\n        </div>\n        <div\n          class=\"bordered\"\n          style=\"\n            position: relative;\n            overflow: hidden;\n            left: 0;\n            right: 0;\n            height: 58px;\n            width: 702px;\n          \"\n        >\n          <div class=\"sample-text-div\" style=\"height: 100%\">\n            <span id=\"fixedFontSample\" class=\"sample-text-span\">\n              The quick brown fox jumps over the lazy dog.\n            </span>\n          </div>\n        </div>\n      </section>\n      <section>\n        <h3>Minimum font size</h3>\n        <div class=\"font-settings-row\">\n          <div class=\"font-settings-div\">\n            <div id=\"minFontSizeLabel\" style=\"margin-bottom: 8px\"></div>\n            <div style=\"width: 100%; margin-bottom: 12px\">\n              <span class=\"slider-legend smaller\">Aa</span>\n              <div\n                id=\"minFontSizeSliderContainer\"\n                class=\"slider-container\"\n              ></div>\n              <span class=\"slider-legend\">Aa</span>\n            </div>\n          </div>\n        </div>\n        <div\n          class=\"bordered\"\n          style=\"\n            position: relative;\n            overflow: hidden;\n            left: 0;\n            right: 0;\n            height: 58px;\n            width: 702px;\n          \"\n        >\n          <div class=\"sample-text-div\" style=\"height: 100%\">\n            <span id=\"minFontSample\" class=\"sample-text-span\">\n              The quick brown fox jumps over the lazy dog.\n            </span>\n          </div>\n        </div>\n      </section>\n      <section>\n        <button id=\"apply-settings\">Apply settings</button>\n        <button id=\"reset-this-script-button\">\n          Reset settings for this script\n        </button>\n        <button id=\"reset-all-button\">Reset all settings</button>\n      </section>\n      <section id=\"footer\">\n        <button id=\"import-settings\">Import settings file</button>\n        <button id=\"export-settings\">Export current settings</button>\n      </section>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/options.js",
    "content": "/* eslint-disable no-unused-vars */\n/* eslint-disable no-undef */\n// Ported from MV2 samples. Some coding practices are non-standard in MV3, but the sample remains a robust demonstration of the chrome.fontsettings API.\n// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n'use strict';\n\n/**\n * @fileoverview The Advanced Font Settings Extension implementation.\n */\n\nfunction $(id) {\n  return document.getElementById(id);\n}\n\n/**\n * A version, for any config files that are exported. Otherwise unused as of now\n * @const\n */\nconst SETTINGS_VERSION = 1;\n\n/**\n * @namespace\n */\nlet advancedFonts = {};\n\n/**\n * The ICU script code for the Common, or global, script, which is used as the\n * fallback when the script is undeclared.\n * @const\n */\nadvancedFonts.COMMON_SCRIPT = 'Zyyy';\n\n/**\n * The scripts supported by the Font Settings Extension API.\n * @const\n */\nadvancedFonts.scripts = [\n  { scriptCode: advancedFonts.COMMON_SCRIPT, scriptName: 'Default' },\n  { scriptCode: 'Afak', scriptName: 'Afaka' },\n  { scriptCode: 'Arab', scriptName: 'Arabic' },\n  { scriptCode: 'Armi', scriptName: 'Imperial Aramaic' },\n  { scriptCode: 'Armn', scriptName: 'Armenian' },\n  { scriptCode: 'Avst', scriptName: 'Avestan' },\n  { scriptCode: 'Bali', scriptName: 'Balinese' },\n  { scriptCode: 'Bamu', scriptName: 'Bamum' },\n  { scriptCode: 'Bass', scriptName: 'Bassa Vah' },\n  { scriptCode: 'Batk', scriptName: 'Batak' },\n  { scriptCode: 'Beng', scriptName: 'Bengali' },\n  { scriptCode: 'Blis', scriptName: 'Blissymbols' },\n  { scriptCode: 'Bopo', scriptName: 'Bopomofo' },\n  { scriptCode: 'Brah', scriptName: 'Brahmi' },\n  { scriptCode: 'Brai', scriptName: 'Braille' },\n  { scriptCode: 'Bugi', scriptName: 'Buginese' },\n  { scriptCode: 'Buhd', scriptName: 'Buhid' },\n  { scriptCode: 'Cakm', scriptName: 'Chakma' },\n  { scriptCode: 'Cans', scriptName: 'Unified Canadian Aboriginal Syllabics' },\n  { scriptCode: 'Cari', scriptName: 'Carian' },\n  { scriptCode: 'Cham', scriptName: 'Cham' },\n  { scriptCode: 'Cher', scriptName: 'Cherokee' },\n  { scriptCode: 'Cirt', scriptName: 'Cirth' },\n  { scriptCode: 'Copt', scriptName: 'Coptic' },\n  { scriptCode: 'Cprt', scriptName: 'Cypriot' },\n  { scriptCode: 'Cyrl', scriptName: 'Cyrillic' },\n  { scriptCode: 'Cyrs', scriptName: 'Old Church Slavonic Cyrillic' },\n  { scriptCode: 'Deva', scriptName: 'Devanagari' },\n  { scriptCode: 'Dsrt', scriptName: 'Deseret' },\n  { scriptCode: 'Dupl', scriptName: 'Duployan shorthand' },\n  { scriptCode: 'Egyd', scriptName: 'Egyptian demotic' },\n  { scriptCode: 'Egyh', scriptName: 'Egyptian hieratic' },\n  { scriptCode: 'Egyp', scriptName: 'Egyptian hieroglyphs' },\n  { scriptCode: 'Elba', scriptName: 'Elbasan' },\n  { scriptCode: 'Ethi', scriptName: 'Ethiopic' },\n  { scriptCode: 'Geok', scriptName: 'Georgian Khutsuri' },\n  { scriptCode: 'Geor', scriptName: 'Georgian' },\n  { scriptCode: 'Glag', scriptName: 'Glagolitic' },\n  { scriptCode: 'Goth', scriptName: 'Gothic' },\n  { scriptCode: 'Gran', scriptName: 'Grantha' },\n  { scriptCode: 'Grek', scriptName: 'Greek' },\n  { scriptCode: 'Gujr', scriptName: 'Gujarati' },\n  { scriptCode: 'Guru', scriptName: 'Gurmukhi' },\n  { scriptCode: 'Hang', scriptName: 'Hangul' },\n  { scriptCode: 'Hani', scriptName: 'Han' },\n  { scriptCode: 'Hano', scriptName: 'Hanunoo' },\n  { scriptCode: 'Hans', scriptName: 'Simplified Han' },\n  { scriptCode: 'Hant', scriptName: 'Traditional Han' },\n  { scriptCode: 'Hebr', scriptName: 'Hebrew' },\n  { scriptCode: 'Hluw', scriptName: 'Anatolian Hieroglyphs' },\n  { scriptCode: 'Hmng', scriptName: 'Pahawh Hmong' },\n  { scriptCode: 'Hung', scriptName: 'Old Hungarian' },\n  { scriptCode: 'Inds', scriptName: 'Indus' },\n  { scriptCode: 'Ital', scriptName: 'Old Italic' },\n  { scriptCode: 'Java', scriptName: 'Javanese' },\n  { scriptCode: 'Jpan', scriptName: 'Japanese' },\n  { scriptCode: 'Jurc', scriptName: 'Jurchen' },\n  { scriptCode: 'Kali', scriptName: 'Kayah Li' },\n  { scriptCode: 'Khar', scriptName: 'Kharoshthi' },\n  { scriptCode: 'Khmr', scriptName: 'Khmer' },\n  { scriptCode: 'Khoj', scriptName: 'Khojki' },\n  { scriptCode: 'Knda', scriptName: 'Kannada' },\n  { scriptCode: 'Kpel', scriptName: 'Kpelle' },\n  { scriptCode: 'Kthi', scriptName: 'Kaithi' },\n  { scriptCode: 'Lana', scriptName: 'Lanna' },\n  { scriptCode: 'Laoo', scriptName: 'Lao' },\n  { scriptCode: 'Latf', scriptName: 'Fraktur Latin' },\n  { scriptCode: 'Latg', scriptName: 'Gaelic Latin' },\n  { scriptCode: 'Latn', scriptName: 'Latin' },\n  { scriptCode: 'Lepc', scriptName: 'Lepcha' },\n  { scriptCode: 'Limb', scriptName: 'Limbu' },\n  { scriptCode: 'Lina', scriptName: 'Linear A' },\n  { scriptCode: 'Linb', scriptName: 'Linear B' },\n  { scriptCode: 'Lisu', scriptName: 'Fraser' },\n  { scriptCode: 'Loma', scriptName: 'Loma' },\n  { scriptCode: 'Lyci', scriptName: 'Lycian' },\n  { scriptCode: 'Lydi', scriptName: 'Lydian' },\n  { scriptCode: 'Mand', scriptName: 'Mandaean' },\n  { scriptCode: 'Mani', scriptName: 'Manichaean' },\n  { scriptCode: 'Maya', scriptName: 'Mayan hieroglyphs' },\n  { scriptCode: 'Mend', scriptName: 'Mende' },\n  { scriptCode: 'Merc', scriptName: 'Meroitic Cursive' },\n  { scriptCode: 'Mero', scriptName: 'Meroitic' },\n  { scriptCode: 'Mlym', scriptName: 'Malayalam' },\n  { scriptCode: 'Mong', scriptName: 'Mongolian' },\n  { scriptCode: 'Moon', scriptName: 'Moon' },\n  { scriptCode: 'Mroo', scriptName: 'Mro' },\n  { scriptCode: 'Mtei', scriptName: 'Meitei Mayek' },\n  { scriptCode: 'Mymr', scriptName: 'Myanmar' },\n  { scriptCode: 'Narb', scriptName: 'Old North Arabian' },\n  { scriptCode: 'Nbat', scriptName: 'Nabataean' },\n  { scriptCode: 'Nkgb', scriptName: 'Naxi Geba' },\n  { scriptCode: 'Nkoo', scriptName: 'N’Ko' },\n  { scriptCode: 'Nshu', scriptName: 'Nüshu' },\n  { scriptCode: 'Ogam', scriptName: 'Ogham' },\n  { scriptCode: 'Olck', scriptName: 'Ol Chiki' },\n  { scriptCode: 'Orkh', scriptName: 'Orkhon' },\n  { scriptCode: 'Orya', scriptName: 'Oriya' },\n  { scriptCode: 'Osma', scriptName: 'Osmanya' },\n  { scriptCode: 'Palm', scriptName: 'Palmyrene' },\n  { scriptCode: 'Perm', scriptName: 'Old Permic' },\n  { scriptCode: 'Phag', scriptName: 'Phags-pa' },\n  { scriptCode: 'Phli', scriptName: 'Inscriptional Pahlavi' },\n  { scriptCode: 'Phlp', scriptName: 'Psalter Pahlavi' },\n  { scriptCode: 'Phlv', scriptName: 'Book Pahlavi' },\n  { scriptCode: 'Phnx', scriptName: 'Phoenician' },\n  { scriptCode: 'Plrd', scriptName: 'Pollard Phonetic' },\n  { scriptCode: 'Prti', scriptName: 'Inscriptional Parthian' },\n  { scriptCode: 'Rjng', scriptName: 'Rejang' },\n  { scriptCode: 'Roro', scriptName: 'Rongorongo' },\n  { scriptCode: 'Runr', scriptName: 'Runic' },\n  { scriptCode: 'Samr', scriptName: 'Samaritan' },\n  { scriptCode: 'Sara', scriptName: 'Sarati' },\n  { scriptCode: 'Sarb', scriptName: 'Old South Arabian' },\n  { scriptCode: 'Saur', scriptName: 'Saurashtra' },\n  { scriptCode: 'Sgnw', scriptName: 'SignWriting' },\n  { scriptCode: 'Shaw', scriptName: 'Shavian' },\n  { scriptCode: 'Shrd', scriptName: 'Sharada' },\n  { scriptCode: 'Sind', scriptName: 'Khudawadi' },\n  { scriptCode: 'Sinh', scriptName: 'Sinhala' },\n  { scriptCode: 'Sora', scriptName: 'Sora Sompeng' },\n  { scriptCode: 'Sund', scriptName: 'Sundanese' },\n  { scriptCode: 'Sylo', scriptName: 'Syloti Nagri' },\n  { scriptCode: 'Syrc', scriptName: 'Syriac' },\n  { scriptCode: 'Syre', scriptName: 'Estrangelo Syriac' },\n  { scriptCode: 'Syrj', scriptName: 'Western Syriac' },\n  { scriptCode: 'Syrn', scriptName: 'Eastern Syriac' },\n  { scriptCode: 'Tagb', scriptName: 'Tagbanwa' },\n  { scriptCode: 'Takr', scriptName: 'Takri' },\n  { scriptCode: 'Tale', scriptName: 'Tai Le' },\n  { scriptCode: 'Talu', scriptName: 'New Tai Lue' },\n  { scriptCode: 'Taml', scriptName: 'Tamil' },\n  { scriptCode: 'Tang', scriptName: 'Tangut' },\n  { scriptCode: 'Tavt', scriptName: 'Tai Viet' },\n  { scriptCode: 'Telu', scriptName: 'Telugu' },\n  { scriptCode: 'Teng', scriptName: 'Tengwar' },\n  { scriptCode: 'Tfng', scriptName: 'Tifinagh' },\n  { scriptCode: 'Tglg', scriptName: 'Tagalog' },\n  { scriptCode: 'Thaa', scriptName: 'Thaana' },\n  { scriptCode: 'Thai', scriptName: 'Thai' },\n  { scriptCode: 'Tibt', scriptName: 'Tibetan' },\n  { scriptCode: 'Tirh', scriptName: 'Tirhuta' },\n  { scriptCode: 'Ugar', scriptName: 'Ugaritic' },\n  { scriptCode: 'Vaii', scriptName: 'Vai' },\n  { scriptCode: 'Visp', scriptName: 'Visible Speech' },\n  { scriptCode: 'Wara', scriptName: 'Varang Kshiti' },\n  { scriptCode: 'Wole', scriptName: 'Woleai' },\n  { scriptCode: 'Xpeo', scriptName: 'Old Persian' },\n  { scriptCode: 'Xsux', scriptName: 'Sumero-Akkadian Cuneiform' },\n  { scriptCode: 'Yiii', scriptName: 'Yi' },\n  { scriptCode: 'Zmth', scriptName: 'Mathematical Notation' },\n  { scriptCode: 'Zsym', scriptName: 'Symbols' }\n];\n\n/**\n * The generic font families supported by the Font Settings Extension API.\n * @const\n */\nadvancedFonts.FAMILIES = [\n  'standard',\n  'sansserif',\n  'serif',\n  'fixed',\n  'cursive',\n  'fantasy'\n];\n\n/**\n * Sample texts.\n * @const\n */\nadvancedFonts.SAMPLE_TEXTS = {\n  // \"Cyrllic script\".\n  Cyrl: 'Кириллица',\n  Hang: '정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날.',\n  Hans: '床前明月光，疑是地上霜。举头望明月，低头思故乡。',\n  Hant: '床前明月光，疑是地上霜。舉頭望明月，低頭思故鄉。',\n  Jpan: '吾輩は猫である。名前はまだ無い。',\n  // \"Khmer language\".\n  Khmr: '\\u1797\\u17B6\\u179F\\u17B6\\u1781\\u17D2\\u1798\\u17C2\\u179A',\n  Zyyy: 'The quick brown fox jumps over the lazy dog.'\n};\n\n/**\n * Controller of pending changes.\n * @const\n */\nadvancedFonts.pendingChanges = new PendingChanges();\n\n/**\n * Map from |genericFamily| to UI controls and data for its font setting.\n */\nadvancedFonts.fontSettings = null;\n\n/**\n * Map from |fontSizeKey| to UI controls and data for its font size setting.\n */\nadvancedFonts.fontSizeSettings = null;\n\n/**\n * Gets the font size used for |fontSizeKey|, including pending changes. Calls\n * |callback| with the result.\n *\n * @param {string} fontSizeKey The font size setting key. See\n *     PendingChanges.getFontSize().\n * @param {function(number, boolean)} callback The callback of form\n *     function(size, controllable). |size| is the effective setting,\n *     |controllable| is whether the setting can be set.\n */\nadvancedFonts.getEffectiveFontSize = function (fontSizeKey, callback) {\n  advancedFonts.fontSizeSettings[fontSizeKey].getter({}, function (details) {\n    let controllable = advancedFonts.isControllableLevel(\n      details.levelOfControl\n    );\n    let size = details.pixelSize;\n    let pendingFontSize = advancedFonts.pendingChanges.getFontSize(fontSizeKey);\n    // If the setting is not controllable, we can have no pending change.\n    if (!controllable) {\n      if (pendingFontSize != null) {\n        advancedFonts.pendingChanges.setFontSize(fontSizeKey, null);\n        $('apply-settings').disabled = advancedFonts.pendingChanges.isEmpty();\n        pendingFontSize = null;\n      }\n    }\n\n    // If we have a pending change, it overrides the current setting.\n    if (pendingFontSize != null) size = pendingFontSize;\n    callback(size, controllable);\n  });\n};\n\n/**\n * Gets the font used for |script| and |genericFamily|, including pending\n * changes. Calls |callback| with the result.\n *\n * @param {string} script The script code.\n * @param {string} genericFamily The generic family.\n * @param {function(string, boolean, string)} callback The callback of form\n *     function(font, controllable, effectiveFont). |font| is the setting\n *     (pending or not), |controllable| is whether the setting can be set,\n *     |effectiveFont| is the font used taking fallback into consideration.\n */\nadvancedFonts.getEffectiveFont = function (script, genericFamily, callback) {\n  let pendingChanges = advancedFonts.pendingChanges;\n  let details = { script: script, genericFamily: genericFamily };\n  chrome.fontSettings.getFont(details, function (result) {\n    let setting = {};\n    setting.font = result.fontId;\n    setting.controllable = advancedFonts.isControllableLevel(\n      result.levelOfControl\n    );\n    let pendingFont = pendingChanges.getFont(\n      details.script,\n      details.genericFamily\n    );\n    // If the setting is not controllable, we can have no pending change.\n    if (!setting.controllable) {\n      if (pendingFont != null) {\n        pendingChanges.setFont(script, genericFamily, null);\n        $('apply-settings').disabled = advancedFonts.pendingChanges.isEmpty();\n        pendingFont = null;\n      }\n    }\n\n    // If we have a pending change, it overrides the current setting.\n    if (pendingFont != null) setting.font = pendingFont;\n\n    // If we have a font, we're done.\n    if (setting.font) {\n      callback(setting.font, setting.controllable, setting.font);\n      return;\n    }\n\n    // If we're still here, we have to fallback to common script, unless this\n    // already is common script.\n    if (script == advancedFonts.COMMON_SCRIPT) {\n      callback('', setting.controllable, '');\n      return;\n    }\n    advancedFonts.getEffectiveFont(\n      advancedFonts.COMMON_SCRIPT,\n      genericFamily,\n      callback.bind(null, setting.font, setting.controllable)\n    );\n  });\n};\n\n/**\n * Refreshes the UI controls related to a font setting.\n *\n * @param {{fontList: HTMLSelectElement, samples: Array<HTMLElement>}}\n *     fontSetting The setting object (see advancedFonts.fontSettings).\n * @param {string} font The value of the font setting.\n * @param {boolean} controllable Whether the font setting can be controlled\n *     by this extension.\n * @param {string} effectiveFont The font used, including fallback to Common\n *     script.\n */\nadvancedFonts.refreshFont = function (\n  fontSetting,\n  font,\n  controllable,\n  effectiveFont\n) {\n  for (let i = 0; i < fontSetting.samples.length; ++i)\n    fontSetting.samples[i].style.fontFamily = effectiveFont;\n  advancedFonts.setSelectedFont(fontSetting.fontList, font);\n  fontSetting.fontList.disabled = !controllable;\n};\n\n/**\n * Refreshes the UI controls related to a font size setting.\n *\n * @param {{label: HTMLElement, slider: Slider, samples: Array<HTMLElement>}}\n *     fontSizeSetting The setting object (see advancedFonts.fontSizeSettings).\n * @param size The value of the font size setting.\n * @param controllable Whether the setting can be controlled by this extension.\n */\nadvancedFonts.refreshFontSize = function (fontSizeSetting, size, controllable) {\n  fontSizeSetting.label.textContent = 'Size: ' + size + 'px';\n  advancedFonts.setFontSizeSlider(fontSizeSetting.slider, size, controllable);\n  for (let i = 0; i < fontSizeSetting.samples.length; ++i)\n    fontSizeSetting.samples[i].style.fontSize = size + 'px';\n};\n\n/**\n * Refreshes all UI controls to reflect the current settings, including pending\n * changes.\n */\nadvancedFonts.refresh = function () {\n  let script = advancedFonts.getSelectedScript();\n  let sample;\n  if (advancedFonts.SAMPLE_TEXTS[script])\n    sample = advancedFonts.SAMPLE_TEXTS[script];\n  else sample = advancedFonts.SAMPLE_TEXTS[advancedFonts.COMMON_SCRIPT];\n  let sampleTexts = document.querySelectorAll('.sample-text-span');\n  for (let i = 0; i < sampleTexts.length; i++)\n    sampleTexts[i].textContent = sample;\n\n  let setting;\n  let callback;\n  for (let genericFamily in advancedFonts.fontSettings) {\n    setting = advancedFonts.fontSettings[genericFamily];\n    callback = advancedFonts.refreshFont.bind(null, setting);\n    advancedFonts.getEffectiveFont(script, genericFamily, callback);\n  }\n\n  for (let fontSizeKey in advancedFonts.fontSizeSettings) {\n    setting = advancedFonts.fontSizeSettings[fontSizeKey];\n    callback = advancedFonts.refreshFontSize.bind(null, setting);\n    advancedFonts.getEffectiveFontSize(fontSizeKey, callback);\n  }\n\n  $('apply-settings').disabled = advancedFonts.pendingChanges.isEmpty();\n};\n\n/**\n * @return {string} The currently selected script code.\n */\nadvancedFonts.getSelectedScript = function () {\n  let scriptList = $('scriptList');\n  return scriptList.options[scriptList.selectedIndex].value;\n};\n\n/**\n * @param {HTMLSelectElement} fontList The <select> containing a list of fonts.\n * @return {string} The currently selected value of |fontList|.\n */\nadvancedFonts.getSelectedFont = function (fontList) {\n  return fontList.options[fontList.selectedIndex].value;\n};\n\n/**\n * Populates the font lists.\n * @param {Array<{fontId: string, displayName: string>} fonts The list of\n *     fonts on the system.\n */\nadvancedFonts.populateFontLists = function (fonts) {\n  for (let genericFamily in advancedFonts.fontSettings) {\n    let list = advancedFonts.fontSettings[genericFamily].fontList;\n\n    // Add a special item to indicate fallback to the non-per-script\n    // font setting. The Font Settings API uses the empty string to indicate\n    // fallback.\n    let defaultItem = document.createElement('option');\n    defaultItem.value = '';\n    defaultItem.text = '(Use default)';\n    list.add(defaultItem);\n\n    for (let i = 0; i < fonts.length; ++i) {\n      let item = document.createElement('option');\n      item.value = fonts[i].fontId;\n      item.text = fonts[i].displayName;\n      list.add(item);\n    }\n  }\n  advancedFonts.refresh();\n};\n\n/**\n * Handles change events on a <select> element for a font setting.\n * @param {string} genericFamily The generic family for the font setting.\n * @param {Event} event The change event.\n */\nadvancedFonts.handleFontListChange = function (genericFamily, event) {\n  let script = advancedFonts.getSelectedScript();\n  let font = advancedFonts.getSelectedFont(event.target);\n\n  advancedFonts.pendingChanges.setFont(script, genericFamily, font);\n  advancedFonts.refresh();\n};\n\n/**\n * Sets the selected value of |fontList| to |fontId|.\n * @param {HTMLSelectElement} fontList The <select> containing a list of fonts.\n * @param {string} fontId The font to set |fontList|'s selection to.\n */\nadvancedFonts.setSelectedFont = function (fontList, fontId) {\n  let script = advancedFonts.getSelectedScript();\n  let i;\n  for (i = 0; i < fontList.length; i++) {\n    if (fontId == fontList.options[i].value) {\n      fontList.selectedIndex = i;\n      break;\n    }\n  }\n  if (i == fontList.length) {\n    console.warn(\n      \"font '\" +\n        fontId +\n        \"' for \" +\n        fontList.id +\n        ' for ' +\n        script +\n        ' is not on the system'\n    );\n  }\n};\n\n/**\n * Handles change events on a font size slider.\n * @param {string} fontSizeKey The key for the font size setting whose slider\n *     changed. See PendingChanges.getFont.\n * @param {string} value The new value of the slider.\n */\nadvancedFonts.handleFontSizeSliderChange = function (fontSizeKey, value) {\n  let pixelSize = parseInt(value);\n  if (!isNaN(pixelSize)) {\n    advancedFonts.pendingChanges.setFontSize(fontSizeKey, pixelSize);\n    advancedFonts.refresh();\n  }\n};\n\n/**\n * @param {string} levelOfControl The level of control string for a setting,\n *     as returned by the Font Settings Extension API.\n * @return {boolean} True if |levelOfControl| signifies that the extension can\n *     control the setting; otherwise, returns false.\n */\nadvancedFonts.isControllableLevel = function (levelOfControl) {\n  return (\n    levelOfControl == 'controllable_by_this_extension' ||\n    levelOfControl == 'controlled_by_this_extension'\n  );\n};\n\n/*\n * Updates the specified font size slider's value and enabled property.\n * @param {Slider} slider The slider for a font size setting.\n * @param {number} size The value to set the slider to.\n * @param {boolean} enabled Whether to enable or disable the slider.\n */\nadvancedFonts.setFontSizeSlider = function (slider, size, enabled) {\n  if (slider.getValue() != size) slider.setValue(size);\n  let inputElement = slider.getInput();\n  if (enabled) {\n    inputElement.parentNode.classList.remove('disabled');\n    inputElement.disabled = false;\n  } else {\n    inputElement.parentNode.classList.add('disabled');\n    inputElement.disabled = true;\n  }\n};\n\n/**\n * Initializes the UI control elements related to the font size setting\n * |fontSizeKey| and registers listeners for the user adjusting its slider and\n * the setting changing on the browser-side.\n * @param {string} fontSizeKey The key for font size setting. See\n *     PendingChanges.getFont().\n */\nadvancedFonts.initFontSizeSetting = function (fontSizeKey) {\n  let fontSizeSettings = advancedFonts.fontSizeSettings;\n  let setting = fontSizeSettings[fontSizeKey];\n  let label = setting.label;\n  let samples = setting.samples;\n\n  setting.slider = new Slider(\n    setting.sliderContainer,\n    0,\n    setting.minValue,\n    setting.maxValue,\n    advancedFonts.handleFontSizeSliderChange.bind(null, fontSizeKey)\n  );\n\n  let slider = setting.slider;\n  setting.getter({}, function (details) {\n    let size = details.pixelSize.toString();\n    let controllable = advancedFonts.isControllableLevel(\n      details.levelOfControl\n    );\n    advancedFonts.setFontSizeSlider(slider, size, controllable);\n    for (let i = 0; i < samples.length; i++)\n      samples[i].style.fontSize = size + 'px';\n  });\n  fontSizeSettings[fontSizeKey].onChanged.addListener(advancedFonts.refresh);\n};\n\n/**\n * Clears the font settings for the specified script.\n * @param {string} script The script code.\n */\nadvancedFonts.clearSettingsForScript = function (script) {\n  advancedFonts.pendingChanges.clearOneScript(script);\n  for (let i = 0; i < advancedFonts.FAMILIES.length; i++) {\n    chrome.fontSettings.clearFont({\n      script: script,\n      genericFamily: advancedFonts.FAMILIES[i]\n    });\n  }\n};\n\n/**\n * Clears all font and font size settings.\n */\nadvancedFonts.clearAllSettings = function () {\n  advancedFonts.pendingChanges.clear();\n  for (let i = 0; i < advancedFonts.scripts.length; i++)\n    advancedFonts.clearSettingsForScript(advancedFonts.scripts[i].scriptCode);\n  chrome.fontSettings.clearDefaultFixedFontSize();\n  chrome.fontSettings.clearDefaultFontSize();\n  chrome.fontSettings.clearMinimumFontSize();\n};\n\n/**\n * Closes the overlay.\n */\nadvancedFonts.closeOverlay = function () {\n  $('overlay-container').hidden = true;\n};\n\n/**\n * Import a JSON file of existing font settings\n */\nadvancedFonts.importSettings = function () {\n  const fileInput = document.createElement('input');\n  fileInput.type = 'file';\n  fileInput.accept = '.json'; // Only allow JSON files\n\n  // Set the event listener for file selection\n  fileInput.addEventListener('change', handleFileSelection);\n\n  function handleFileSelection(event) {\n    const selectedFile = event.target.files[0];\n\n    if (selectedFile) {\n      if (selectedFile.type === 'application/json') {\n        const reader = new FileReader();\n\n        reader.onload = async function (e) {\n          const jsonContent = e.target.result;\n\n          try {\n            const parsedConfig = JSON.parse(jsonContent);\n\n            await advancedFonts.applyImportedSettings(parsedConfig);\n            window.location.reload();\n          } catch (error) {\n            console.error('Error parsing JSON:', error);\n          }\n        };\n\n        reader.readAsText(selectedFile);\n      } else {\n        console.error('Please select a valid JSON file.');\n      }\n    }\n  }\n\n  fileInput.click();\n};\n\nconst isNumeric = function (key, config) {\n  if (key in config) {\n    if (typeof config[key] === 'number') {\n      return true;\n    } else {\n      console.error(\n        `Invalid value for ${key}. It needs to be an integer, recieved ${typeof config[\n          key\n        ]}`\n      );\n      return false;\n    }\n  } else {\n    console.error(`${key} not found in config.`);\n    return false;\n  }\n};\n\nconst isString = function (...data) {\n  const result = data.every((e) => typeof e === 'string');\n\n  if (!result) {\n    console.error(\n      `Invalid value provided. It needs to be a string, recieved ${typeof data}`\n    );\n  }\n\n  return result;\n};\n\nadvancedFonts.applyImportedSettings = async function (config) {\n  if (isNumeric('defaultFixedFontSize', config)) {\n    await chrome.fontSettings.setDefaultFixedFontSize({\n      pixelSize: config.defaultFixedFontSize\n    });\n  }\n  if (isNumeric('minimumFontSize', config)) {\n    await chrome.fontSettings.setMinimumFontSize({\n      pixelSize: config.minimumFontSize\n    });\n  }\n  if (isNumeric('defaultFontSize', config)) {\n    await chrome.fontSettings.setDefaultFontSize({\n      pixelSize: config.defaultFontSize\n    });\n  }\n\n  if (Array.isArray(config.configuredFonts)) {\n    await Promise.all(\n      config.configuredFonts.map(async ({ script, scriptData }) => {\n        if (Array.isArray(scriptData)) {\n          await Promise.all(\n            scriptData.map(async ({ fontId, genericFamily }) => {\n              if (isString(fontId, genericFamily, script)) {\n                try {\n                  await chrome.fontSettings.setFont({\n                    fontId,\n                    genericFamily,\n                    script\n                  });\n                } catch (e) {\n                  console.warn(\n                    `Unable to set ${script},${fonId},${genericFamily}: ${e}`\n                  );\n                }\n              }\n            })\n          );\n        }\n      })\n    );\n  } else if (typeof config.configuredFonts !== 'undefined') {\n    console.error(\n      `Invalid value for configuredFonts. It needs to be an array, recieved ${typeof config[\n        key\n      ]}`\n    );\n  }\n};\n\n/**\n * Export a JSON file of the current font settings;\n */\nadvancedFonts.exportSettings = async function () {\n  const settings = await advancedFonts.getCurrentSettings();\n  const blob = new Blob([JSON.stringify(settings)], {\n    type: 'application/json'\n  });\n  const blobUrl = URL.createObjectURL(blob);\n  const downloadLink = document.createElement('a');\n  downloadLink.href = blobUrl;\n  downloadLink.download = `\"Advanced_Font_Settings_Data.v${SETTINGS_VERSION}\".json`;\n\n  document.body.appendChild(downloadLink);\n  downloadLink.click();\n  document.body.removeChild(downloadLink);\n  URL.revokeObjectURL(blobUrl);\n};\n\n/**\n * Generate a JSON object that represents all of the font settings data\n */\nadvancedFonts.getCurrentSettings = async function () {\n  const configuredFonts = [\n    ...(await Promise.all(\n      // iterate over every script (i.e. language code - \"Cyrl\", \"Hebr\", etc)\n      advancedFonts.scripts.map(async (scriptInfo) => {\n        const script = scriptInfo.scriptCode;\n\n        // for each script, we also iterage over any font that is configured for any generic value (e.g. \"fixed\", \"sansserif\", etc)\n        let scriptData = [\n          ...(await Promise.all(\n            advancedFonts.FAMILIES.map(async (genericFamily) => {\n              const { fontId } = await chrome.fontSettings.getFont({\n                genericFamily,\n                script\n              });\n\n              return {\n                genericFamily,\n                fontId\n              };\n            })\n          ))\n        ]\n          .filter((entry) => {\n            // any entry that is blank hasnt been configured, so no need to include it\n            return entry.fontId !== '';\n          })\n          .map(({ fontId, genericFamily }) => {\n            // filter the output to only the data we care about\n            return {\n              fontId,\n              genericFamily\n            };\n          });\n\n        return {\n          script,\n          scriptData\n        };\n      })\n    ))\n  ].filter((entry) => {\n    // remove any script that has no scriptData, in order to reduce our file size\n    return entry.scriptData.length > 0;\n  });\n\n  const defaultFixedFontSize = (\n    await chrome.fontSettings.getDefaultFixedFontSize()\n  ).pixelSize;\n  const minimumFontSize = (await chrome.fontSettings.getMinimumFontSize())\n    .pixelSize;\n  const defaultFontSize = (await chrome.fontSettings.getDefaultFontSize())\n    .pixelSize;\n\n  return {\n    defaultFixedFontSize,\n    defaultFontSize,\n    minimumFontSize,\n    configuredFonts,\n    _version: SETTINGS_VERSION\n  };\n};\n\n/**\n * Initializes apply and reset buttons.\n */\nadvancedFonts.initApplyAndResetButtons = function () {\n  let applyButton = $('apply-settings');\n  applyButton.addEventListener('click', function () {\n    advancedFonts.pendingChanges.apply();\n    advancedFonts.refresh();\n  });\n\n  let overlay = $('overlay-container');\n  cr.ui.overlay.globalInitialization();\n  cr.ui.overlay.setupOverlay(overlay);\n  overlay.addEventListener('cancelOverlay', advancedFonts.closeOverlay);\n\n  $('reset-this-script-button').onclick = function (event) {\n    let scriptList = $('scriptList');\n    let scriptName = scriptList.options[scriptList.selectedIndex].text;\n    $('reset-this-script-overlay-dialog-content').innerText =\n      'Are you sure you want to reset settings for ' + scriptName + ' script?';\n\n    $('overlay-container').hidden = false;\n    $('reset-this-script-overlay-dialog').hidden = false;\n    $('reset-all-scripts-overlay-dialog').hidden = true;\n  };\n  $('reset-this-script-ok').onclick = function (event) {\n    advancedFonts.clearSettingsForScript(advancedFonts.getSelectedScript());\n    advancedFonts.closeOverlay();\n    advancedFonts.refresh();\n  };\n  $('reset-this-script-cancel').onclick = advancedFonts.closeOverlay;\n\n  $('reset-all-button').onclick = function (event) {\n    $('overlay-container').hidden = false;\n    $('reset-all-scripts-overlay-dialog').hidden = false;\n    $('reset-this-script-overlay-dialog').hidden = true;\n  };\n  $('reset-all-ok').onclick = function (event) {\n    advancedFonts.clearAllSettings();\n    advancedFonts.closeOverlay();\n    advancedFonts.refresh();\n  };\n  $('reset-all-cancel').onclick = advancedFonts.closeOverlay;\n\n  $('import-settings').onclick = advancedFonts.importSettings;\n  $('export-settings').onclick = advancedFonts.exportSettings;\n};\n\n/**\n * Best guess for system fonts, taken from the IDS_WEB_FONT_FAMILY strings in\n * Chrome.\n * TODO: The font should be localized like Chrome does.\n * @const\n */\nadvancedFonts.systemFonts = {\n  cros: 'Noto Sans UI, sans-serif',\n  linux: 'Ubuntu, sans-serif',\n  mac: 'Lucida Grande, sans-serif',\n  win: 'Segoe UI, Tahoma, sans-serif',\n  unknown: 'sans-serif'\n};\n\n/**\n * @return {string} The platform this extension is running on.\n */\nadvancedFonts.getPlatform = function () {\n  let ua = window.navigator.appVersion;\n  if (ua.indexOf('Win') != -1) return 'win';\n  if (ua.indexOf('Mac') != -1) return 'mac';\n  if (ua.indexOf('Linux') != -1) return 'linux';\n  if (ua.indexOf('CrOS') != -1) return 'cros';\n  return 'unknown';\n};\n\n/**\n * Chrome settings tries to use the system font. So does this extension.\n */\nadvancedFonts.useSystemFont = function () {\n  document.body.style.fontFamily =\n    advancedFonts.systemFonts[advancedFonts.getPlatform()];\n};\n\n/**\n * Sorts the list of script codes by scriptName. Someday this extension will\n * have localized script names, so the order will depend on locale.\n */\nadvancedFonts.sortScripts = function () {\n  let i;\n  let scripts = advancedFonts.scripts;\n  for (i = 0; i < scripts; ++i) {\n    if (scripts[i].scriptCode == advancedFonts.COMMON_SCRIPT) break;\n  }\n  let defaultScript = scripts.splice(i, 1)[0];\n\n  scripts.sort(function (a, b) {\n    if (a.scriptName > b.scriptName) return 1;\n    if (a.scriptName < b.scriptName) return -1;\n    return 0;\n  });\n\n  scripts.unshift(defaultScript);\n};\n\n/**\n * Initializes UI controls for font settings.\n */\nadvancedFonts.initFontControls = function () {\n  advancedFonts.fontSettings = {\n    standard: {\n      fontList: $('standardFontList'),\n      samples: [$('standardFontSample'), $('minFontSample')]\n    },\n    serif: {\n      fontList: $('serifFontList'),\n      samples: [$('serifFontSample')]\n    },\n    sansserif: {\n      fontList: $('sansSerifFontList'),\n      samples: [$('sansSerifFontSample')]\n    },\n    fixed: {\n      fontList: $('fixedFontList'),\n      samples: [$('fixedFontSample')]\n    }\n  };\n\n  for (let genericFamily in advancedFonts.fontSettings) {\n    let list = advancedFonts.fontSettings[genericFamily].fontList;\n    list.addEventListener(\n      'change',\n      advancedFonts.handleFontListChange.bind(list, genericFamily)\n    );\n  }\n  chrome.fontSettings.onFontChanged.addListener(advancedFonts.refresh);\n  chrome.fontSettings.getFontList(advancedFonts.populateFontLists);\n};\n\n/**\n * Initializes UI controls for font size settings.\n */\nadvancedFonts.initFontSizeControls = function () {\n  advancedFonts.fontSizeSettings = {\n    defaultFontSize: {\n      sliderContainer: $('defaultFontSizeSliderContainer'),\n      minValue: 6,\n      maxValue: 50,\n      samples: [\n        $('standardFontSample'),\n        $('serifFontSample'),\n        $('sansSerifFontSample')\n      ],\n      label: $('defaultFontSizeLabel'),\n      getter: chrome.fontSettings.getDefaultFontSize,\n      onChanged: chrome.fontSettings.onDefaultFontSizeChanged\n    },\n    defaultFixedFontSize: {\n      sliderContainer: $('defaultFixedFontSizeSliderContainer'),\n      minValue: 6,\n      maxValue: 50,\n      samples: [$('fixedFontSample')],\n      label: $('fixedFontSizeLabel'),\n      getter: chrome.fontSettings.getDefaultFixedFontSize,\n      onChanged: chrome.fontSettings.onDefaultFixedFontSizeChanged\n    },\n    minFontSize: {\n      sliderContainer: $('minFontSizeSliderContainer'),\n      minValue: 6,\n      maxValue: 24,\n      samples: [$('minFontSample')],\n      label: $('minFontSizeLabel'),\n      getter: chrome.fontSettings.getMinimumFontSize,\n      onChanged: chrome.fontSettings.onMinimumFontSizeChanged\n    }\n  };\n\n  for (let fontSizeKey in advancedFonts.fontSizeSettings)\n    advancedFonts.initFontSizeSetting(fontSizeKey);\n};\n\n/**\n * Initializes the list of scripts.\n */\nadvancedFonts.initScriptList = function () {\n  let scriptList = $('scriptList');\n  advancedFonts.sortScripts();\n  let scripts = advancedFonts.scripts;\n  for (let i = 0; i < scripts.length; i++) {\n    let script = document.createElement('option');\n    script.value = scripts[i].scriptCode;\n    script.text = scripts[i].scriptName;\n    scriptList.add(script);\n  }\n  scriptList.selectedIndex = 0;\n  scriptList.addEventListener('change', advancedFonts.refresh);\n};\n\n/**\n * Initializes the extension.\n */\nadvancedFonts.init = function () {\n  advancedFonts.useSystemFont();\n\n  advancedFonts.initFontControls();\n  advancedFonts.initFontSizeControls();\n  advancedFonts.initScriptList();\n\n  advancedFonts.initApplyAndResetButtons();\n};\n\ndocument.addEventListener('DOMContentLoaded', advancedFonts.init);\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/pending_changes.js",
    "content": "/// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// Ported from MV2 samples. Some coding practices are non-standard in MV3, but the sample remains a robust demonstration of the chrome.fontsettings API.\n\n'use strict';\n\n/**\n * @fileoverview PendingChanges class tracks changes to be applied when an\n * \"Apply Changes\" button is clicked.\n */\n\n/**\n * Creates a PendingChanges object with no pending changes.\n *\n * @constructor\n */\nlet PendingChanges = function () {\n  // Format: pendingFontChanges_.Cyrl.sansserif = \"My SansSerif Cyrillic Font\"\n  this.pendingFontChanges_ = {};\n\n  // Format: pendingFontSizeChanges_.defaultFontSize = 12\n  this.pendingFontSizeChanges_ = {};\n};\n\n/**\n * Returns the pending font setting change for the specified script and family,\n * or null if it doesn't exist.\n *\n * @param {string} script The script code, like \"Cyrl\".\n * @param {string} genericFamily The generic family, like \"sansserif\".\n * @return {?string} The pending font setting, like \"My Cyrillic SansSerif Font\"\n *     or null if it doesn't exist.\n */\nPendingChanges.prototype.getFont = function (script, genericFamily) {\n  if (this.pendingFontChanges_[script])\n    return this.pendingFontChanges_[script][genericFamily];\n  return null;\n};\n\n/**\n * Returns the pending font size setting change, or null if it doesn't exist.\n *\n * @param {string} fontSizeKey The font size setting key. One of\n *     'defaultFontSize', 'defaultFixedFontSize', or 'minFontSize'.\n * @return {?number} The pending font size setting in pixels, or null if it\n *     doesn't exist.\n */\nPendingChanges.prototype.getFontSize = function (fontSizeKey) {\n  return this.pendingFontSizeChanges_[fontSizeKey];\n};\n\n/**\n * Sets the pending font change for the specified script and family.\n *\n * @param {string} script The script code, like \"Cyrl\".\n * @param {string} genericFamily The generic family, like \"sansserif\".\n * @param {?string} font The font to set the setting to, or null to clear it.\n */\nPendingChanges.prototype.setFont = function (script, genericFamily, font) {\n  if (!this.pendingFontChanges_[script]) this.pendingFontChanges_[script] = {};\n  if (this.pendingFontChanges_[script][genericFamily] == font) return;\n  this.pendingFontChanges_[script][genericFamily] = font;\n};\n\n/**\n * Sets the pending font size change.\n *\n * @param {string} fontSizeKey The font size setting key. See\n *     getFontSize().\n * @param {number} size The font size to set the setting to.\n */\nPendingChanges.prototype.setFontSize = function (fontSizeKey, size) {\n  if (this.pendingFontSizeChanges_[fontSizeKey] == size) return;\n  this.pendingFontSizeChanges_[fontSizeKey] = size;\n};\n\n/**\n * Commits the pending changes to Chrome. After this function is called, there\n * are no pending changes.\n */\nPendingChanges.prototype.apply = function () {\n  for (let script in this.pendingFontChanges_) {\n    for (let genericFamily in this.pendingFontChanges_[script]) {\n      let fontId = this.pendingFontChanges_[script][genericFamily];\n      if (fontId == null) continue;\n      let details = {};\n      details.script = script;\n      details.genericFamily = genericFamily;\n      details.fontId = fontId;\n      chrome.fontSettings.setFont(details);\n    }\n  }\n\n  let size = this.pendingFontSizeChanges_['defaultFontSize'];\n  if (size != null) chrome.fontSettings.setDefaultFontSize({ pixelSize: size });\n\n  size = this.pendingFontSizeChanges_['defaultFixedFontSize'];\n  if (size != null)\n    chrome.fontSettings.setDefaultFixedFontSize({ pixelSize: size });\n\n  size = this.pendingFontSizeChanges_['minFontSize'];\n  if (size != null) chrome.fontSettings.setMinimumFontSize({ pixelSize: size });\n\n  this.clear();\n};\n\n/**\n * Clears the pending font changes for a single script.\n *\n * @param {string} script The script code, like \"Cyrl\".\n */\nPendingChanges.prototype.clearOneScript = function (script) {\n  this.pendingFontChanges_[script] = {};\n};\n\n/**\n * Clears all pending font changes.\n */\nPendingChanges.prototype.clear = function () {\n  this.pendingFontChanges_ = {};\n  this.pendingFontSizeChanges_ = {};\n};\n\n/**\n * @return {boolean} True if there are no pending changes, otherwise false.\n */\nPendingChanges.prototype.isEmpty = function () {\n  for (let script in this.pendingFontChanges_) {\n    for (let genericFamily in this.pendingFontChanges_[script]) {\n      if (this.pendingFontChanges_[script][genericFamily] != null) return false;\n    }\n  }\n  for (let name in this.pendingFontSizeChanges_) {\n    if (this.pendingFontSizeChanges_[name] != null) return false;\n  }\n  return true;\n};\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/slider.css",
    "content": "/* Copyright 2013 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n/* Customize the standard input[type='range']. */\n.slider > input[type='range'] {\n  -webkit-appearance: none !important;  /* Hide the default thumb icon. */\n  background: transparent;  /* Hide the standard slider bar */\n  height: 100%;\n  left: -2px;  /* Required to align the input element with the parent. */\n  position: absolute;\n  top: -2px;\n  width: 100%;\n}\n\n/* Custom thumb icon. */\n.slider > input[type='range']::-webkit-slider-thumb {\n  -webkit-appearance: none;\n  background-position: center center;\n  background-repeat: no-repeat;\n  height: 24px;\n  position: relative;\n  z-index: 2;\n}\n\n/* Custom slider bar (we hide the standard one). */\n.slider > .bar {\n  /* In order to match the horizontal position of the standard slider bar\n     left and right must be equal to 1/2 of the thumb icon width. */\n  left: 8px;\n  right: 8px;\n  bottom: 10px;\n  pointer-events: none;  /* Mouse events pass through to the standard input. */\n  position: absolute;\n  top: 10px;\n  background-image: url(../images/slider/slide_bar_center.png);\n  height: 4px;\n}\n\n.slider > .bar > .filled,\n.slider > .bar > .cap {\n  position: absolute;\n}\n\n/* The filled portion of the slider bar to the left of the thumb. */\n.slider > .bar > .filled {\n  border-left-style: none;\n  border-right-style: none;\n  left: 0;\n  width: 0; /* The element style.width is manipulated from the code. */\n}\n\n.slider > .bar > .cap.right {\n  background-image: url(../images/slider/slider_bar_right.png);\n  height: 4px;\n  width: 4px;\n  left: 100%;\n}\n\n.slider > .bar > .filled {\n  background-image: url(../images/slider/slide_bar_fill_center.png);\n  height: 4px;\n}\n\n.slider > .bar > .cap.left {\n  background-image: url(../images/slider/slide_bar_fill_left.png);\n  height: 4px;\n  width: 4px;\n  right: 100%;\n}\n\n.slider.disabled  > .bar {\n  background-image: url(../images/slider/slide_bar_disabled_center.png);\n}\n\n.slider.disabled  > .bar > .filled {\n  background-image: url(../images/slider/slide_bar_disabled_center.png);\n}\n\n.slider.disabled  > .bar > .cap.left {\n  background-image: url(../images/slider/slide_bar_disabled_left.png);\n}\n\n.slider.disabled  > .bar > .cap.right {\n  background-image: url(../images/slider/slide_bar_disabled_right.png);\n}\n\n.slider.disabled,\n.slider.readonly {\n  pointer-events: none;\n}\n\n.slider {\n  -webkit-box-flex: 1;\n}\n\n.slider > input[type='range']::-webkit-slider-thumb {\n  background-image: url(../images/slider/slider_thumb.png);\n  width: 16px;\n}\n\n.slider > input[type='range']::-webkit-slider-thumb:hover {\n  background-image: url(../images/slider/slider_thumb_hover.png);\n}\n\n.slider > input[type='range']::-webkit-slider-thumb:active {\n  background-image: url(../images/slider/slider_thumb_down.png);\n}\n\n.slider.disabled > input[type='range']::-webkit-slider-thumb {\n  background-image: url(../images/slider/slider_thumb_disabled.png);\n}\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Advanced/slider.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n// Ported from MV2 samples. Some coding practices are non-standard in MV3, but the sample remains a robust demonstration of the chrome.fontsettings API.\n\n'use strict';\n\n/**\n * @fileoverview A Slider control. Based on Chromium's MediaControls.Slider.\n */\n\n/**\n * Creates a slider control.\n *\n * @param {HTMLElement} container The containing div element.\n * @param {number} value Initial value\n * @param {number} min Minimum value\n * @param {number} max Maximum value\n * @param {?function(number)=} opt_onChange Value change handler\n * @constructor\n */\nfunction Slider(container, value, min, max, opt_onChange) {\n  this.container_ = container;\n  this.onChange_ = opt_onChange;\n\n  let containerDocument = this.container_.ownerDocument;\n\n  this.container_.classList.add('slider');\n\n  this.input_ = containerDocument.createElement('input');\n  this.input_.type = 'range';\n  this.input_.min = min;\n  this.input_.max = max;\n  this.input_.value = value;\n  this.container_.appendChild(this.input_);\n\n  this.input_.addEventListener('change', this.onInputChange_.bind(this));\n  this.input_.addEventListener('input', this.onInputChange_.bind(this));\n\n  this.bar_ = containerDocument.createElement('div');\n  this.bar_.className = 'bar';\n  this.container_.appendChild(this.bar_);\n\n  this.filled_ = containerDocument.createElement('div');\n  this.filled_.className = 'filled';\n  this.bar_.appendChild(this.filled_);\n\n  let leftCap = containerDocument.createElement('div');\n  leftCap.className = 'cap left';\n  this.bar_.appendChild(leftCap);\n\n  let rightCap = containerDocument.createElement('div');\n  rightCap.className = 'cap right';\n  this.bar_.appendChild(rightCap);\n\n  this.updateFilledWidth_();\n}\n\n/**\n * @return {number} The value of the input control.\n */\nSlider.prototype.getValue = function () {\n  return this.input_.value;\n};\n\n/**\n * @param{number} value The value to set the input control to.\n */\nSlider.prototype.setValue = function (value) {\n  this.input_.value = value;\n  this.updateFilledWidth_();\n};\n\n/**\n * @return {HTMLInputElement} The underlying input control.\n */\nSlider.prototype.getInput = function () {\n  return this.input_;\n};\n\n/**\n * Updates the filled portion of the slider to reflect the slider's current\n * value.\n * @private\n */\nSlider.prototype.updateFilledWidth_ = function () {\n  let proportion =\n    (this.input_.value - this.input_.min) / (this.input_.max - this.input_.min);\n  this.filled_.style.width = proportion * 100 + '%';\n};\n\n/**\n * Called when the slider's value changes.\n * @private\n */\nSlider.prototype.onInputChange_ = function () {\n  this.updateFilledWidth_();\n  if (this.onChange_) this.onChange_(this.input_.value);\n};\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Basic/README.md",
    "content": "# chrome.fontSettings\n\nThis extension demonstrates the `chrome.fontSettings` API by allowing users to modify the size of fonts on webpages.\n\n## Overview\n\nThe extension creates a user interface in the extension's options page that allows users to see and modify font settings using `chrome.fontSettings` to change parameters.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin th extension to the taskbar and click the action button.\n4. Click the extension's action button to visit the popup page.\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Basic/manifest.json",
    "content": "{\n  \"name\": \"Font Settings API Sample\",\n  \"version\": \"1\",\n  \"manifest_version\": 3,\n  \"description\": \"Demonstrates the chrome.fontSettings API by allowing users to modify the size of fonts on webpages.\",\n  \"action\": {\n    \"default_popup\": \"popup.html\"\n  },\n  \"permissions\": [\"fontSettings\"]\n}\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Basic/popup.html",
    "content": "<!--\n Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n<!doctype html>\n<html>\n  <head>\n    <title>Font Settings</title>\n    <script src=\"popup.js\"></script>\n  </head>\n  <body>\n    <h1>Font Settings</h1>\n    <label for=\"fontSize\">Font Size:</label>\n    <button id=\"decreaseFontSize\">-</button>\n    <span id=\"fontSize\"></span>\n    <button id=\"increaseFontSize\">+</button>\n    <label for=\"minFontSize\">Minimum Font Size:</label>\n    <input type=\"number\" id=\"minFontSize\" min=\"0\" />\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/fontSettings/fontSettings Basic/popup.js",
    "content": "// Ported from MV2 samples. Some coding practices are non-standard in MV3, but the sample remains a robust demonstration of the chrome.fontsettings API.\n// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\ndocument.addEventListener('DOMContentLoaded', () => {\n  const increaseFontSizeButton = document.getElementById('increaseFontSize');\n  const decreaseFontSizeButton = document.getElementById('decreaseFontSize');\n  const fontSizeElement = document.getElementById('fontSize');\n  const minFontSizeElement = document.getElementById('minFontSize');\n\n  function updateFontSize(newFontSize) {\n    chrome.fontSettings.setDefaultFontSize({ pixelSize: newFontSize }, () => {\n      fontSizeElement.textContent = newFontSize.toString();\n    });\n  }\n\n  function updateMinFontSize(newMinFontSize) {\n    chrome.fontSettings.setMinimumFontSize({ pixelSize: newMinFontSize });\n  }\n\n  increaseFontSizeButton.addEventListener('click', () => {\n    chrome.fontSettings.getDefaultFontSize({}, (fontInfo) => {\n      const newFontSize = fontInfo.pixelSize + 2;\n      updateFontSize(newFontSize);\n    });\n  });\n\n  decreaseFontSizeButton.addEventListener('click', () => {\n    chrome.fontSettings.getDefaultFontSize({}, (fontInfo) => {\n      const newFontSize = fontInfo.pixelSize - 2;\n      updateFontSize(newFontSize);\n    });\n  });\n\n  minFontSizeElement.addEventListener('change', () => {\n    const newMinFontSize = parseInt(minFontSizeElement.value);\n    updateMinFontSize(newMinFontSize);\n  });\n});\n"
  },
  {
    "path": "api-samples/history/historyOverride/README.md",
    "content": "# chrome.history - History Override\n\nA sample that demonstrates how to override the default history page.\n\n## Overview\n\nOnce this extension is installed, `chrome://history` will be overridden by the extension's custom page.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Open `chrome://history` and you will find the custom history page.\n"
  },
  {
    "path": "api-samples/history/historyOverride/history.html",
    "content": "<html>\n  <head>\n    <title>History</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />\n  </head>\n\n  <body>\n    <div id=\"searchbar\">\n      <h1>\n        Custom History Page\n        <br />\n        <small>Only show the history within one week.</small>\n      </h1>\n      <input\n        id=\"searchInput\"\n        type=\"text\"\n        name=\"search\"\n        placeholder=\"Search History\"\n      />\n      <input type=\"submit\" id=\"searchSubmit\" value=\"Search\" />\n      <input type=\"submit\" id=\"deleteSelected\" value=\"Remove Selected\" />\n      <input type=\"submit\" id=\"removeAll\" value=\"Remove All\" />\n    </div>\n    <div id=\"historyDiv\"></div>\n    <template id=\"historyTemplate\">\n      <div class=\"history\">\n        <div class=\"image-wrapper\"></div>\n        <div class=\"page-meta\">\n          <div class=\"page-detail\">\n            <p class=\"page-title\"></p>\n            <a class=\"page-link\" target=\"_blank\"></a>\n          </div>\n          <div class=\"page-visit-time\"></div>\n        </div>\n        <div class=\"actions\">\n          <input type=\"checkbox\" class=\"removeCheck\" />\n          <button class=\"removeButton\">remove</button>\n        </div>\n      </div>\n    </template>\n    <script src=\"logic.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/history/historyOverride/logic.js",
    "content": "const kMillisecondsPerWeek = 1000 * 60 * 60 * 24 * 7;\nconst kOneWeekAgo = new Date().getTime() - kMillisecondsPerWeek;\nconst historyDiv = document.getElementById('historyDiv');\n\nfunction faviconURL(u) {\n  const url = new URL(chrome.runtime.getURL('/_favicon/'));\n  url.searchParams.set('pageUrl', u);\n  url.searchParams.set('size', '24');\n  return url.toString();\n}\n\nfunction constructHistory(historyItems) {\n  const template = document.getElementById('historyTemplate');\n  for (let item of historyItems) {\n    const clone = document.importNode(template.content, true);\n    const pageLinkEl = clone.querySelector('.page-link');\n    const pageTitleEl = clone.querySelector('.page-title');\n    const pageVisitTimeEl = clone.querySelector('.page-visit-time');\n    const imageWrapperEl = clone.querySelector('.image-wrapper');\n    const checkbox = clone.querySelector('.removeCheck, input');\n    checkbox.setAttribute('value', item.url);\n    const favicon = document.createElement('img');\n    pageLinkEl.href = item.url;\n    favicon.src = faviconURL(item.url);\n    pageLinkEl.textContent = item.url;\n    imageWrapperEl.prepend(favicon);\n    pageVisitTimeEl.textContent = new Date(item.lastVisitTime).toLocaleString();\n    if (!item.title) {\n      pageTitleEl.style.display = 'none';\n    }\n    pageTitleEl.innerText = item.title;\n\n    clone\n      .querySelector('.removeButton, button')\n      .addEventListener('click', async function () {\n        await chrome.history.deleteUrl({ url: item.url });\n        location.reload();\n      });\n\n    clone\n      .querySelector('.history')\n      .addEventListener('click', async function (event) {\n        // fix double click\n        if (event.target.className === 'removeCheck') {\n          return;\n        }\n\n        checkbox.checked = !checkbox.checked;\n      });\n    historyDiv.appendChild(clone);\n  }\n}\n\ndocument.getElementById('searchSubmit').onclick = async function () {\n  historyDiv.innerHTML = ' ';\n  const searchQuery = document.getElementById('searchInput').value;\n  const historyItems = await chrome.history.search({\n    text: searchQuery,\n    startTime: kOneWeekAgo\n  });\n  constructHistory(historyItems);\n};\n\ndocument.getElementById('deleteSelected').onclick = async function () {\n  const checkboxes = document.getElementsByTagName('input');\n  for (let checkbox of checkboxes) {\n    if (checkbox.checked == true) {\n      await chrome.history.deleteUrl({ url: checkbox.value });\n    }\n  }\n  location.reload();\n};\n\ndocument.getElementById('removeAll').onclick = async function () {\n  await chrome.history.deleteAll();\n  location.reload();\n};\n\nchrome.history\n  .search({\n    text: '',\n    startTime: kOneWeekAgo,\n    maxResults: 99\n  })\n  .then(constructHistory);\n"
  },
  {
    "path": "api-samples/history/historyOverride/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"History Override\",\n  \"description\": \"Demonstrates how to override the default history page.\",\n  \"version\": \"1.0\",\n  \"chrome_url_overrides\": {\n    \"history\": \"history.html\"\n  },\n  \"permissions\": [\"history\", \"favicon\"],\n  \"icons\": {\n    \"16\": \"history16.png\",\n    \"32\": \"history32.png\",\n    \"48\": \"history48.png\",\n    \"128\": \"history128.png\"\n  }\n}\n"
  },
  {
    "path": "api-samples/history/historyOverride/style.css",
    "content": "small {\n  font-size: 12px;\n  font-weight: normal;\n}\n\n#historyDiv {\n  margin-top: 10px;\n  display: flex;\n  flex-direction: column;\n  gap: 10px;\n  max-width: 1000px;\n}\n\n.history {\n  box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.2);\n  border-radius: 10px;\n  display: flex;\n  height: 60px;\n  padding: 10px;\n  cursor: pointer;\n}\n\n.image-wrapper {\n  width: 24px;\n  height: 100%;\n  margin-right: 10px;\n  flex-grow: 0;\n  flex-shrink: 0;\n}\n\n.image-wrapper img {\n  width: 100%;\n}\n\n.page-meta {\n  flex-grow: 1;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n  max-width: calc(100% - 180px);\n}\n\n.page-title {\n  font-weight: bold;\n  font-size: 0.8rem;\n}\n\n.page-detail {\n  display: flex;\n  flex-direction: column;\n  align-items: start;\n}\n\n.page-link,\n.page-title {\n  overflow: hidden;\n  white-space: nowrap;\n  max-width: 100%;\n  display: inline-block;\n  text-overflow: ellipsis;\n  margin: 0;\n}\n\n.page-link {\n  font-size: 0.8rem;\n  color: #8c8c8c;\n}\n\n.page-link:hover {\n  color: #000;\n}\n\n.page-visit-time {\n  font-size: 0.8rem;\n  color: #a5a5a5;\n}\n\n.actions {\n  flex-grow: 0;\n  flex-shrink: 0;\n  display: flex;\n  flex-grow: 1;\n  flex-shrink: 0;\n  flex-direction: column;\n  justify-content: space-between;\n  align-items: end;\n  gap: 5px;\n}\n"
  },
  {
    "path": "api-samples/history/showHistory/README.md",
    "content": "# chrome.history\n\nThis sample uses the [`chrome.history`](https://developer.chrome.com/docs/extensions/reference/history/) API to display in a popup the user's most visited pages.\n\n## Overview\n\nThis extension calls `chrome.history.search()` to scrape the browser's history and count occurrences of each visited URL.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extension to the browser's taskbar.\n4. Click on the extension's action button to view your most visited pages.\n"
  },
  {
    "path": "api-samples/history/showHistory/manifest.json",
    "content": "{\n  \"name\": \"Typed URL History\",\n  \"version\": \"1.3\",\n  \"key\": \"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0FAp+xWiJpGBmsKPhGcqF4/gQN9F5tmXgEVYEHUHc8HcBIUcT+9w+jo4q2OtXa2ThqgEXsx2zcNZIWJ/5yXcofVry5E2/HKBuLWHNtYOlI1rhwc/CLujo0RHhzF7rIiYcMPQdBhzr6L0u5u9N29VUWjLozltquKRcUbjXNe4LT7+q/akhn5tvfvWHkQ9qC6mRjvGwGTFlh1A6+vWKKSVYx/J+IBHW+I2X5NlAxwG734OMYVWRWK487jf1wsWZ2jHRTqg9TB3htT+84r7+E3kFYMycow9+2EhvoI2k5VGhZw1tAJcpie1Poozc5u8CTrZ4sZ5LK4h59OCOxmejC048QIDAQAB\",\n  \"description\": \"Uses the chrome.history API to display in a popup the user's most visited pages.\",\n  \"permissions\": [\"history\"],\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"action\": {\n    \"default_popup\": \"popup.html\",\n    \"default_icon\": \"clock.png\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/history/showHistory/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Recently Typed URLs</title>\n    <style>\n      body {\n        min-width: 250px;\n      }\n    </style>\n  </head>\n\n  <body>\n    <h2>Recently Typed URLs:</h2>\n    <script src=\"popup.js\"></script>\n    <div id=\"typedUrl_div\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/history/showHistory/popup.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Event listner for clicks on links in a browser action popup.\n// Open the link in a new tab of the current window.\nfunction onAnchorClick(event) {\n  chrome.tabs.create({\n    selected: true,\n    url: event.srcElement.href\n  });\n  return false;\n}\n\n// Given an array of URLs, build a DOM list of those URLs in the\n// browser action popup.\nfunction buildPopupDom(divName, data) {\n  let popupDiv = document.getElementById(divName);\n\n  let ul = document.createElement('ul');\n  popupDiv.appendChild(ul);\n\n  for (let i = 0, ie = data.length; i < ie; ++i) {\n    let a = document.createElement('a');\n    a.href = data[i];\n    a.appendChild(document.createTextNode(data[i]));\n    a.addEventListener('click', onAnchorClick);\n\n    let li = document.createElement('li');\n    li.appendChild(a);\n\n    ul.appendChild(li);\n  }\n}\n\n// Search history to find up to ten links that a user has typed in,\n// and show those links in a popup.\nfunction buildTypedUrlList(divName) {\n  // To look for history items visited in the last week,\n  // subtract a week of milliseconds from the current time.\n  let millisecondsPerWeek = 1000 * 60 * 60 * 24 * 7;\n  let oneWeekAgo = new Date().getTime() - millisecondsPerWeek;\n\n  // Track the number of callbacks from chrome.history.getVisits()\n  // that we expect to get.  When it reaches zero, we have all results.\n  let numRequestsOutstanding = 0;\n\n  chrome.history.search(\n    {\n      text: '', // Return every history item....\n      startTime: oneWeekAgo // that was accessed less than one week ago.\n    },\n    function (historyItems) {\n      // For each history item, get details on all visits.\n      for (let i = 0; i < historyItems.length; ++i) {\n        let url = historyItems[i].url;\n        let processVisitsWithUrl = function (url) {\n          // We need the url of the visited item to process the visit.\n          // Use a closure to bind the  url into the callback's args.\n          return function (visitItems) {\n            processVisits(url, visitItems);\n          };\n        };\n        chrome.history.getVisits({ url: url }, processVisitsWithUrl(url));\n        numRequestsOutstanding++;\n      }\n      if (!numRequestsOutstanding) {\n        onAllVisitsProcessed();\n      }\n    }\n  );\n\n  // Maps URLs to a count of the number of times the user typed that URL into\n  // the omnibox.\n  let urlToCount = {};\n\n  // Callback for chrome.history.getVisits().  Counts the number of\n  // times a user visited a URL by typing the address.\n  const processVisits = function (url, visitItems) {\n    for (let i = 0, ie = visitItems.length; i < ie; ++i) {\n      // Ignore items unless the user typed the URL.\n      if (visitItems[i].transition != 'typed') {\n        continue;\n      }\n\n      if (!urlToCount[url]) {\n        urlToCount[url] = 0;\n      }\n\n      urlToCount[url]++;\n    }\n\n    // If this is the final outstanding call to processVisits(),\n    // then we have the final results.  Use them to build the list\n    // of URLs to show in the popup.\n    if (!--numRequestsOutstanding) {\n      onAllVisitsProcessed();\n    }\n  };\n\n  // This function is called when we have the final list of URls to display.\n  const onAllVisitsProcessed = () => {\n    // Get the top scorring urls.\n    let urlArray = [];\n    for (let url in urlToCount) {\n      urlArray.push(url);\n    }\n\n    // Sort the URLs by the number of times the user typed them.\n    urlArray.sort(function (a, b) {\n      return urlToCount[b] - urlToCount[a];\n    });\n\n    buildPopupDom(divName, urlArray.slice(0, 10));\n  };\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  buildTypedUrlList('typedUrl_div');\n});\n"
  },
  {
    "path": "api-samples/history/showHistory/service-worker.js",
    "content": "chrome.runtime.onInstalled.addListener(() => {\n  console.log('Hello world!');\n});\n"
  },
  {
    "path": "api-samples/identity/README.md",
    "content": "# chrome.identity\n\nA sample extension that uses the\n[Identity API](https://developer.chrome.com/docs/extensions/reference/api/identity)\nto request information of the logged in user and present this info on the\nscreen. If the user has a profile picture, their profile image is also fetched\nand shown in the app.\n\n## Overview\n\nThis extension uses the getAuthToken flow of the Identity API, so it only\nworks with Google accounts. If you want to identify the user in a non-Google\nOAuth2 flow, you should use the launchWebAuthFlow method instead.\n\n![screenshot](assets/screenshot.png)\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension icon to open the UI.\n"
  },
  {
    "path": "api-samples/identity/identity.js",
    "content": "'use strict';\n\nfunction onLoad() {\n  const STATE_START = 1;\n  const STATE_ACQUIRING_AUTHTOKEN = 2;\n  const STATE_AUTHTOKEN_ACQUIRED = 3;\n\n  let state = STATE_START;\n\n  document.querySelector('#get-email').addEventListener('click', getEmail);\n\n  const signin_button = document.querySelector('#signin');\n  signin_button.addEventListener('click', interactiveSignIn);\n\n  const userinfo_button = document.querySelector('#userinfo');\n  userinfo_button.addEventListener(\n    'click',\n    getUserInfo.bind(userinfo_button, true)\n  );\n\n  const revoke_button = document.querySelector('#revoke');\n  revoke_button.addEventListener('click', revokeToken);\n\n  const user_info_div = document.querySelector('#user_info');\n\n  // Trying to get user's info without signing in, it will work if the\n  // application was previously authorized by the user.\n  getUserInfo(false);\n\n  function disableButton(button) {\n    button.setAttribute('disabled', 'disabled');\n  }\n\n  function enableButton(button) {\n    button.removeAttribute('disabled');\n  }\n\n  // Gets the email address for the primary account.\n  // This uses the chrome.identity.getProfileUserInfo API, and does not require\n  // an auth token.\n  function getEmail() {\n    chrome.identity\n      .getProfileUserInfo({ accountStatus: chrome.identity.AccountStatus.ANY })\n      .then((profile_user_info) => {\n        displayOutput(\n          'chrome.identity.getProfileUserInfo() returned: ' +\n            JSON.stringify(profile_user_info)\n        );\n        document.getElementById('email-info').innerText =\n          profile_user_info.email;\n      });\n  }\n\n  function changeState(newState) {\n    state = newState;\n    switch (state) {\n      case STATE_START:\n        enableButton(signin_button);\n        disableButton(userinfo_button);\n        disableButton(revoke_button);\n        break;\n      case STATE_ACQUIRING_AUTHTOKEN:\n        displayOutput('Acquiring token...');\n        disableButton(signin_button);\n        disableButton(userinfo_button);\n        disableButton(revoke_button);\n        break;\n      case STATE_AUTHTOKEN_ACQUIRED:\n        disableButton(signin_button);\n        enableButton(userinfo_button);\n        enableButton(revoke_button);\n        break;\n    }\n  }\n\n  function displayOutput(message) {\n    let messageStr = message;\n    if (typeof message != 'string') {\n      messageStr = JSON.stringify(message);\n    }\n\n    document.getElementById('__logarea').value = messageStr;\n  }\n\n  function fetchWithAuth(method, url, interactive, callback) {\n    let access_token;\n    let retry = true;\n\n    getToken();\n\n    function getToken() {\n      chrome.identity\n        .getAuthToken({ interactive: interactive })\n        .then((token) => {\n          access_token = token.token;\n          requestStart();\n        })\n        .catch((error) => {\n          callback(error.message);\n        });\n    }\n\n    function requestStart() {\n      fetch(url, {\n        method: method,\n        headers: {\n          Authorization: 'Bearer ' + access_token\n        }\n      }).then((response) => {\n        if (response.status == 401 && retry) {\n          retry = false;\n          chrome.identity\n            .removeCachedAuthToken({ token: access_token })\n            .then(getToken);\n        } else {\n          callback(null, response.status, response);\n        }\n      });\n    }\n  }\n\n  // This fetches user information over the network, providing an access token\n  // scoped to this extension.\n  function getUserInfo(interactive) {\n    // See https://developers.google.com/identity/openid-connect/openid-connect#obtaininguserprofileinformation\n    fetchWithAuth(\n      'GET',\n      'https://openidconnect.googleapis.com/v1/userinfo',\n      interactive,\n      onUserInfoFetched\n    );\n  }\n\n  // Code updating the user interface, when the user information has been\n  // fetched or displaying the error.\n  function onUserInfoFetched(error, status, response) {\n    if (!error && status == 200) {\n      changeState(STATE_AUTHTOKEN_ACQUIRED);\n      response.json().then((user_info) => {\n        displayOutput(user_info);\n        populateUserInfo(user_info);\n      });\n    } else {\n      changeState(STATE_START);\n    }\n  }\n\n  function populateUserInfo(user_info) {\n    if (!user_info || !user_info.picture) return;\n\n    user_info_div.innerText = 'Hello ' + user_info.name;\n\n    const imgElem = document.createElement('img');\n    imgElem.src = user_info.picture;\n    imgElem.style.width = '24px';\n    user_info_div.insertAdjacentElement('afterbegin', imgElem);\n  }\n\n  // OnClick event handlers for the buttons.\n\n  /**\n    Retrieves a valid token. Since this is initiated by the user\n    clicking in the Sign In button, we want it to be interactive -\n    ie, when no token is found, the auth window is presented to the user.\n\n    Observe that the token does not need to be cached by the app.\n    Chrome caches tokens and takes care of renewing when it is expired.\n    In that sense, getAuthToken only goes to the server if there is\n    no cached token or if it is expired. If you want to force a new\n    token (for example when user changes the password on the service)\n    you need to call removeCachedAuthToken()\n  **/\n  function interactiveSignIn() {\n    changeState(STATE_ACQUIRING_AUTHTOKEN);\n    console.log('interactiveSignIn');\n\n    // This is the normal flow for authentication/authorization on Google\n    // properties. You need to add the oauth2 client_id and scopes to the app\n    // manifest. The interactive param indicates if a new window will be opened\n    // when the user is not yet authenticated or not.\n    //\n    // See https://developer.chrome.com/docs/extensions/reference/api/identity#method-getAuthToken\n    chrome.identity\n      .getAuthToken({ interactive: true })\n      .then((token) => {\n        displayOutput('Token acquired:\\n' + token.token);\n        changeState(STATE_AUTHTOKEN_ACQUIRED);\n      })\n      .catch((error) => {\n        displayOutput(error.message);\n        changeState(STATE_START);\n      });\n  }\n\n  function revokeToken() {\n    user_info_div.innerHTML = '';\n    chrome.identity\n      .getAuthToken({ interactive: false })\n      .then((current_token) => {\n        // Remove the local cached token\n        chrome.identity.removeCachedAuthToken({ token: current_token.token });\n\n        // Make a request to revoke token in the server.\n        // See https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow#tokenrevoke\n        fetch(\n          'https://oauth2.googleapis.com/revoke?token=' + current_token.token,\n          { method: 'POST' }\n        ).then(() => {\n          // Update the user interface accordingly\n          changeState(STATE_START);\n          displayOutput('Token revoked and removed from cache.');\n        });\n      });\n  }\n}\n\nwindow.addEventListener('load', onLoad);\n"
  },
  {
    "path": "api-samples/identity/index.html",
    "content": "<html>\n  <head>\n    <title>Identity API Sample Extension</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\">\n    <script src=\"identity.js\"></script>\n  </head>\n  <body>\n    <div class=\"header\">\n      <h1>Identity API</h1>\n      <div class=\"links\">\n        Learn more:\n        <a target=\"_blank\" href=\"https://developer.chrome.com/docs/extensions/reference/api/identity\">API docs</a>\n        <a id=\"_open_snippets\" href=\"https://github.com/GoogleChrome/chrome-extensions-samples/tree/main/api-samples/identity\">Source</a>\n      </div>\n      <hr>\n    </div>\n    <div class=\"flows\">\n      <h2>Query local Chrome account information</h2>\n      <div class=\"flow\">\n        <button id=\"get-email\">Get primary account email address</button>\n        <div id=\"email-info\"></div>\n      </div>\n      <h2>OAuth on Google properties</h2>\n      <div class=\"flow\">\n        <button id=\"signin\">Sign in</button>\n        <button id=\"userinfo\" disabled>Get personal data</button>\n        <button id=\"revoke\" disabled>Revoke token</button>\n        <div id=\"user_info\"></div>\n      </div>\n    </div>\n    <div class=\"log\">\n      <textarea id=\"__logarea\" disabled></textarea>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/identity/main.js",
    "content": "chrome.action.onClicked.addListener(() => {\n  chrome.tabs.create({\n    active: true,\n    url: 'index.html'\n  });\n});\n"
  },
  {
    "path": "api-samples/identity/manifest.json",
    "content": "{\n  \"name\": \"Identity API Sample\",\n  \"version\": \"4.0\",\n  \"manifest_version\": 3,\n  \"key\": \"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDJB6ZGcGxtlr/34s+TKgi84QiP7DMekqOjSUS2ubmbhchlM6CN9gYdGQ1aBI3TBXG3YaAu+XyutFA8M8NLLWc4OOGByWaGV11DP6p67g8a+Ids/gX6cNSRnRHiDZXAd44ATxoN4OZjZJk9iQ26RIUjwX07bzntlI+frwwKCk4WQIDAQAB\",\n  \"action\": {},\n  \"background\": {\n    \"service_worker\": \"main.js\"\n  },\n  \"permissions\": [\"identity\", \"identity.email\"],\n  \"oauth2\": {\n    \"client_id\": \"497291774654.apps.googleusercontent.com\",\n    \"scopes\": [\"https://www.googleapis.com/auth/userinfo.profile\"]\n  }\n}\n"
  },
  {
    "path": "api-samples/identity/style.css",
    "content": "html, body {\n  margin: 0;\n  font-family: 'Open Sans Regular', sans;\n  color: #666;\n  background: #fafafa;\n}\n\n.header {\n  text-align: center;\n  padding: 10px 0 10px 0;\n}\n\n.header hr {\n  height: 6px;\n  border: none;\n  margin-top: 20px;\n  background: -webkit-linear-gradient(0deg,\n    rgb(51,105,232) 0%,\n    rgb(51,105,232) 25%,\n    rgb(222,30,37) 25%,\n    rgb(222,30,37) 50%,\n    rgb(255, 210, 0) 50%,\n    rgb(255, 210, 0) 75%,\n    rgb(76,187,71) 75%,\n    rgb(76,187,71) 100%\n    );\n }\n\n.header .links * {\n  margin-left: 5px;\n}\n\n.header .links a {\n  color: #666;\n}\n\n.header:hover .links a {\n  color: #3399cc;\n}\n\n.flows h2 {\n  margin-left: 5px;\n  margin-bottom: 10px;\n}\n\n.flow {\n  margin: 10px 20px 20px 20px;\n  border: 1px solid #ddd;\n  padding: 8px;\n  background: white;\n}\n\n.flow button {\n  cursor: pointer;\n  background: -webkit-linear-gradient(top,#008dfd 0,#0370ea 100%);\n  border: 1px solid #076bd2;\n  text-shadow: 1px 1px 1px #076bd2;\n  color: white;\n  font-weight: 700;\n  font-size: 13px;\n  margin: .5em 0 1em;\n  padding: 8px 17px 8px 17px;\n  border-radius: 3px;\n}\n\n.flow button.error {\n  background: -webkit-linear-gradient(top,#008dfd 0,#0370ea 100%);\n  border: 1px solid #076bd2;\n  text-shadow: 1px 1px 1px #076bd2;\n  color: white;\n  font-weight: 700;\n  font-size: 13px;\n  margin: .5em 0 1em;\n  padding: 8px 17px 8px 17px;\n  border-radius: 3px;\n}\n\n.flow button:disabled {\n  background: -webkit-linear-gradient(top, #dcdcdc 0, #fafafa 100%);\n  color: #999;\n  text-shadow: 1px 1px 1px #fafafa;\n  border: 1px solid #ddd;\n  cursor: auto;\n}\n\n.log {\n  margin: 10px 20px 20px 20px;\n}\n\n.log textarea {\n  width: 100%;\n  min-height: 200px;\n  font-family: \"Courier New\", Courier, monospace;\n  margin: 2px;\n  background: #FFFFFF;\n  color: #727272;\n  border: 1px solid rgb(182, 182, 182);\n}\n"
  },
  {
    "path": "api-samples/idle/README.md",
    "content": "# chrome.idle\n\nThis sample demonstrates how to use the [`chrome.idle`](https://developer.chrome.com/docs/extensions/reference/idle/) API.\n\n## Overview\n\nIn this sample, the `chrome.idle` API detects and stores the history of the user's idle state.\n\n## Implementation Notes\n\nThe detection interval of [`chrome.idle.onStateChanged`](https://developer.chrome.com/docs/extensions/reference/idle/#event-onStateChanged) event needs to be modified using the [`chrome.idle.setDetectionInterval`](https://developer.chrome.com/docs/extensions/reference/idle/#method-setDetectionInterval) method.\n\nThe idle state history is stored in the [`chrome.storage.session`](https://developer.chrome.com/docs/extensions/reference/storage/#property-session) storage area.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension's action icon to open the window.\n"
  },
  {
    "path": "api-samples/idle/history.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <style>\n      body {\n        width: 100%;\n        margin: 0;\n        padding: 0 1em;\n        box-sizing: border-box;\n        font: 13px Arial;\n      }\n    </style>\n  </head>\n\n  <body>\n    <h1>Idle API Demonstration</h1>\n    <h2>Current state</h2>\n    <p>\n      Idle threshold:\n      <select id=\"idle-threshold\">\n        <option selected value=\"15\">15</option>\n        <option value=\"30\">30</option>\n        <option value=\"60\">60</option>\n      </select>\n    </p>\n\n    <p>\n      <code\n        >chrome.idle.queryState(<strong id=\"idle-set-threshold\"></strong>,\n        ...);</code\n      >\n      -\n      <span id=\"idle-state\"></span>\n    </p>\n    <p>Last state change: <span id=\"idle-laststate\"></span></p>\n\n    <h2>Idle changes:</h2>\n    <ul id=\"idle-history\"></ul>\n    <script src=\"history.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/idle/history.js",
    "content": "/**\n * Convert a state and time into a nice styled chunk of DOM elements.\n * @returns {DocumentFragment}\n */\nfunction renderState(state, time) {\n  const now = Date.now();\n  const diff = Math.round((time - now) / 1000);\n  const str =\n    diff == 0\n      ? 'now'\n      : Math.abs(diff) + ' seconds ' + (diff > 0 ? 'from now' : 'ago');\n  const col = state == 'active' ? '#009900' : '#990000';\n\n  const fragment = document.createDocumentFragment();\n  const bold = document.createElement('b');\n  bold.style.color = col;\n  bold.textContent = state;\n  fragment.appendChild(bold);\n  fragment.appendChild(document.createTextNode(' ' + str));\n\n  return fragment;\n}\n\n/**\n * Creates DOM and injects a rendered state into the page.\n */\nfunction renderItem(state, time, parent) {\n  const dom_item = document.createElement('li');\n  dom_item.appendChild(renderState(state, time));\n  parent.appendChild(dom_item);\n}\n\n// Store previous state so we can show deltas.  This is important\n// because the API currently doesn't fire idle messages, and we'd\n// like to keep track of last time we went idle.\nlet laststate = null;\nlet laststatetime = null;\n\n/**\n * Checks the current state of the browser.\n */\nasync function checkState() {\n  const threshold = parseInt(document.querySelector('#idle-threshold').value);\n  const dom_threshold = document.querySelector('#idle-set-threshold');\n  dom_threshold.innerText = threshold;\n\n  // Request the state based off of the user-supplied threshold.\n  chrome.idle.queryState(threshold, function (state) {\n    const time = new Date();\n    if (laststate != state) {\n      laststate = state;\n      laststatetime = time;\n    }\n\n    // Keep rendering results so we get a nice \"seconds elapsed\" view.\n    const dom_result = document.querySelector('#idle-state');\n    dom_result.replaceChildren(renderState(state, time));\n    const dom_laststate = document.querySelector('#idle-laststate');\n    dom_laststate.replaceChildren(renderState(laststate, laststatetime));\n  });\n}\n\n/**\n * Render the data gathered by the background service worker - should show a log\n * of \"active\" states.\n */\nasync function renderHistory() {\n  const dom_history = document.querySelector('#idle-history');\n  dom_history.replaceChildren();\n  const { history_log } = await chrome.storage.session.get(['history_log']);\n  if (!history_log) {\n    return;\n  }\n\n  for (let i = 0; i < history_log.length; i++) {\n    const data = history_log[i];\n    renderItem(data['state'], data['time'], dom_history);\n  }\n}\n\ndocument.addEventListener('DOMContentLoaded', async function () {\n  // Set the threshold to the last value the user set, or 15 if not set.\n  let { threshold: stored_threshold } = await chrome.storage.local.get([\n    'threshold'\n  ]);\n  if (!stored_threshold || ![15, 30, 60].includes(stored_threshold)) {\n    stored_threshold = 15;\n  }\n\n  document.querySelector(\n    `#idle-threshold option[value=\"${stored_threshold}\"]`\n  ).selected = true;\n  chrome.idle.setDetectionInterval(stored_threshold);\n\n  document\n    .querySelector('#idle-threshold')\n    .addEventListener('change', function (e) {\n      const threshold = parseInt(e.target.value);\n      chrome.storage.local.set({ threshold: threshold });\n      chrome.idle.setDetectionInterval(threshold);\n    });\n\n  // Check every second (even though this is overkill - minimum idle\n  // threshold is 15 seconds) so that the numbers appear to be counting up.\n  checkState();\n  window.setInterval(checkState, 1000);\n\n  // Check every second (see above).\n  renderHistory();\n  window.setInterval(renderHistory, 1000);\n});\n"
  },
  {
    "path": "api-samples/idle/manifest.json",
    "content": "{\n  \"name\": \"Idle - Simple Example\",\n  \"version\": \"1.0.1\",\n  \"description\": \"Demonstrates the Idle API\",\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"permissions\": [\"idle\", \"storage\"],\n  \"action\": {\n    \"default_icon\": \"sample-19.png\"\n  },\n  \"icons\": {\n    \"16\": \"sample-16.png\",\n    \"48\": \"sample-48.png\",\n    \"128\": \"sample-128.png\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/idle/service-worker.js",
    "content": "/**\n * Stores a state every time it changes, up to 20 items.\n */\nchrome.idle.onStateChanged.addListener(async function (newstate) {\n  let { history_log } = await chrome.storage.session.get(['history_log']);\n  if (!history_log) {\n    history_log = [];\n  }\n  const time = Date.now();\n  if (history_log.length >= 20) {\n    history_log.pop();\n  }\n  history_log.unshift({ state: newstate, time: time });\n  chrome.storage.session.set({ history_log: history_log });\n});\n\n/**\n * Opens history.html when the browser action is clicked.\n */\nchrome.action.onClicked.addListener(function () {\n  chrome.windows.create({\n    url: 'history.html',\n    width: 700,\n    height: 600,\n    type: 'popup'\n  });\n});\n"
  },
  {
    "path": "api-samples/il8n/README.md",
    "content": "# chrome.i18n\n\nThis sample demonstrates the `chrome.i18n` API by localizing text in the extension popup.\n\n## Overview\n\nThe extension includes localized translations of its UI text in the `\\_locales\\' folder. It then calls `chrome.i18n.getMessage()` to populate the text in the extension UI with either French or English, depending on the current language setting.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extension to the taskbar to access the action button.\n4. Open the extension popup by clicking the action button.\n"
  },
  {
    "path": "api-samples/il8n/_locales/en/messages.json",
    "content": "{\n  \"title\": {\n    \"message\": \"This is a title\",\n    \"description\": \"The title of the extension page\"\n  },\n  \"content\": {\n    \"message\": \"Hello world!\",\n    \"description\": \"The content of the extension page\"\n  }\n}\n"
  },
  {
    "path": "api-samples/il8n/_locales/fr/messages.json",
    "content": "{\n  \"title\": {\n    \"message\": \"C'est une Titre\",\n    \"description\": \"le titre de la page d'extension\"\n  },\n  \"content\": {\n    \"message\": \"Bonjour le monde!\",\n    \"description\": \"le contenu de la page d'extension\"\n  }\n}\n"
  },
  {
    "path": "api-samples/il8n/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"il8n API Example\",\n  \"description\": \"Demonstrates the chrome.i18n API by localizing text in the extension popup.\",\n  \"version\": \"3\",\n  \"action\": {\n    \"default_popup\": \"popup.html\"\n  },\n  \"default_locale\": \"en\",\n  \"permissions\": [\"activeTab\"]\n}\n"
  },
  {
    "path": "api-samples/il8n/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n  </head>\n  <body>\n    <h1 id=\"title\"></h1>\n    <p id=\"content\"></p>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/il8n/popup.js",
    "content": "document.getElementById('title').textContent = chrome.i18n.getMessage('title');\ndocument.getElementById('content').textContent =\n  chrome.i18n.getMessage('content');\n"
  },
  {
    "path": "api-samples/nativeMessaging/README.md",
    "content": "# Native Messaging\n\nThis directory contains an example of Chrome extension that uses [Native Messaging](https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging) to communicate with a native application.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Follow the installation instructions below.\n4. Open the popup.\n5. Send messages from either the native application or extension.\n\n## To install the host:\n\n### Windows\n\nRun `install_host.bat` script in the host directory.\n\nThis script installs the native messaging host for the current user, by creating a registry key\n` HKEY_CURRENT_USER\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\com.google.chrome.example.echo`\nand setting its default value to the full path to `host\\com.google.chrome.example.echo-win.json`.\n\nIf you want to install the native messaging host for all users, change HKCU to HKLM.\n\nNote that you need to have Python installed.\n\n### Mac and Linux\n\nRun `install_host.sh` script in the host directory: `host/install_host.sh`\n\nBy default the host is installed only for the user who runs the script, but if\nyou run it with admin privileges (i.e. `sudo host/install_host.sh`), then the\nhost will be installed for all users. You can later use `host/uninstall_host.sh`\nto uninstall the host.\n"
  },
  {
    "path": "api-samples/nativeMessaging/extension/main.html",
    "content": "<!doctype html>\n<!--\n * Copyright 2013 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n\n<html>\n  <head>\n    <script src=\"./main.js\"></script>\n  </head>\n  <body>\n    <button id=\"connect-button\">Connect</button>\n    <input id=\"input-text\" type=\"text\" />\n    <button id=\"send-message-button\">Send</button>\n    <div id=\"response\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/nativeMessaging/extension/main.js",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nlet message;\nlet port = null;\n\nfunction appendMessage(text) {\n  document.getElementById('response').innerHTML += '<p>' + text + '</p>';\n}\n\nfunction updateUiState() {\n  if (port) {\n    document.getElementById('connect-button').style.display = 'none';\n    document.getElementById('input-text').style.display = 'block';\n    document.getElementById('send-message-button').style.display = 'block';\n  } else {\n    document.getElementById('connect-button').style.display = 'block';\n    document.getElementById('input-text').style.display = 'none';\n    document.getElementById('send-message-button').style.display = 'none';\n  }\n}\n\nfunction sendNativeMessage() {\n  message = { text: document.getElementById('input-text').value };\n  port.postMessage(message);\n  appendMessage('Sent message: <b>' + JSON.stringify(message) + '</b>');\n}\n\nfunction onNativeMessage(message) {\n  appendMessage('Received message: <b>' + JSON.stringify(message) + '</b>');\n}\n\nfunction onDisconnected() {\n  appendMessage('Failed to connect: ' + chrome.runtime.lastError.message);\n  port = null;\n  updateUiState();\n}\n\nfunction connect() {\n  const hostName = 'com.google.chrome.example.echo';\n  appendMessage('Connecting to native messaging host <b>' + hostName + '</b>');\n  port = chrome.runtime.connectNative(hostName);\n  port.onMessage.addListener(onNativeMessage);\n  port.onDisconnect.addListener(onDisconnected);\n  updateUiState();\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  document.getElementById('connect-button').addEventListener('click', connect);\n  document\n    .getElementById('send-message-button')\n    .addEventListener('click', sendNativeMessage);\n  updateUiState();\n});\n"
  },
  {
    "path": "api-samples/nativeMessaging/extension/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"key\": \"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB\",\n  \"name\": \"Native Messaging Example\",\n  \"version\": \"1.0\",\n  \"description\": \"Send a message to a native application.\",\n  \"action\": {\n    \"default_title\": \"Native Messaging Example\",\n    \"default_popup\": \"main.html\"\n  },\n  \"icons\": {\n    \"128\": \"icon-128.png\"\n  },\n  \"permissions\": [\"nativeMessaging\"]\n}\n"
  },
  {
    "path": "api-samples/nativeMessaging/host/com.google.chrome.example.echo-win.json",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n{\n  \"name\": \"com.google.chrome.example.echo\",\n  \"description\": \"Chrome Native Messaging API Example Host\",\n  \"path\": \"native-messaging-example-host.bat\",\n  \"type\": \"stdio\",\n  \"allowed_origins\": [\"chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/\"]\n}\n"
  },
  {
    "path": "api-samples/nativeMessaging/host/com.google.chrome.example.echo.json",
    "content": "// Copyright 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n{\n  \"name\": \"com.google.chrome.example.echo\",\n  \"description\": \"Chrome Native Messaging API Example Host\",\n  \"path\": \"HOST_PATH\",\n  \"type\": \"stdio\",\n  \"allowed_origins\": [\"chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/\"]\n}\n"
  },
  {
    "path": "api-samples/nativeMessaging/host/install_host.bat",
    "content": ":: Copyright 2014 The Chromium Authors. All rights reserved.\n:: Use of this source code is governed by a BSD-style license that can be\n:: found in the LICENSE file.\n\n:: Change HKCU to HKLM if you want to install globally.\n:: %~dp0 is the directory containing this bat script and ends with a backslash.\nREG ADD \"HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\com.google.chrome.example.echo\" /ve /t REG_SZ /d \"%~dp0com.google.chrome.example.echo-win.json\" /f\n"
  },
  {
    "path": "api-samples/nativeMessaging/host/install_host.sh",
    "content": "#!/bin/sh\n# Copyright 2013 The Chromium Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style license that can be\n# found in the LICENSE file.\n\nset -e\n\nDIR=\"$( cd \"$( dirname \"$0\" )\" && pwd )\"\nif [ $(uname -s) == 'Darwin' ]; then\n  if [ \"$(whoami)\" == \"root\" ]; then\n    # Due to macOS permission changes we need to put the host in /Applications\n    HOST_PATH=\"/Applications/native-messaging-example-host\"\n    cp \"$DIR/native-messaging-example-host\" $HOST_PATH\n\n    TARGET_DIR=\"/Library/Google/Chrome/NativeMessagingHosts\"\n    chmod a+x \"$DIR/native-messaging-example-host\"\n  else\n    # Due to macOS permission changes we need to put the host in ~/Applications\n    HOST_PATH=\"/Users/$USER/Applications/native-messaging-example-host\"\n    cp \"$DIR/native-messaging-example-host\" $HOST_PATH\n\n    TARGET_DIR=\"$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts\"\n  fi\nelse\n  HOST_PATH=\"$DIR/native-messaging-example-host\"\n  if [ \"$(whoami)\" == \"root\" ]; then\n    TARGET_DIR=\"/etc/opt/chrome/native-messaging-hosts\"\n    chmod a+x \"$DIR/native-messaging-example-host\"\n  else\n    TARGET_DIR=\"$HOME/.config/google-chrome/NativeMessagingHosts\"\n  fi\nfi\n\nHOST_NAME=com.google.chrome.example.echo\n\n# Create directory to store native messaging host.\nmkdir -p \"$TARGET_DIR\"\n\n# Copy native messaging host manifest.\ncp \"$DIR/$HOST_NAME.json\" \"$TARGET_DIR\"\n\n# Update host path in the manifest.\nESCAPED_HOST_PATH=${HOST_PATH////\\\\/}\nsed -i -e \"s/HOST_PATH/$ESCAPED_HOST_PATH/\" \"$TARGET_DIR/$HOST_NAME.json\"\n\n# Set permissions for the manifest so that all users can read it.\nchmod o+r \"$TARGET_DIR/$HOST_NAME.json\"\n\necho Native messaging host $HOST_NAME has been installed.\n"
  },
  {
    "path": "api-samples/nativeMessaging/host/native-messaging-example-host",
    "content": "#!/usr/bin/python3\n# Copyright (c) 2012 The Chromium Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style license that can be\n# found in the LICENSE file.\n\n# A simple native messaging host. Shows a Tkinter dialog with incoming messages\n# that also allows to send message back to the webapp.\n\nimport struct\nimport sys\nimport threading\nimport queue as Queue\n\ntry:\n  import tkinter as Tkinter\n  import tkinter.messagebox\nexcept ImportError:\n  Tkinter = None\n\n# On Windows, the default I/O mode is O_TEXT. Set this to O_BINARY\n# to avoid unwanted modifications of the input/output streams.\nif sys.platform == \"win32\":\n  import os, msvcrt\n  msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)\n  msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)\n\n# Helper function that sends a message to the webapp.\ndef send_message(message):\n   # Write message size.\n  sys.stdout.buffer.write(struct.pack('I', len(message)))\n  # Write the message itself.\n  sys.stdout.write(message)\n  sys.stdout.flush()\n\n# Thread that reads messages from the webapp.\ndef read_thread_func(queue):\n  message_number = 0\n  while 1:\n    # Read the message length (first 4 bytes).\n    text_length_bytes = sys.stdin.buffer.read(4)\n\n    if len(text_length_bytes) == 0:\n      if queue:\n        queue.put(None)\n      sys.exit(0)\n\n    # Unpack message length as 4 byte integer.\n    text_length = struct.unpack('@I', text_length_bytes)[0]\n\n    # Read the text (JSON object) of the message.\n    text = sys.stdin.buffer.read(text_length).decode('utf-8')\n\n    if text == '{\"text\":\"exit\"}':\n      break\n\n    if queue:\n      queue.put(text)\n    else:\n      # In headless mode just send an echo message back.\n      send_message('{\"echo\": %s}' % text)\n\nif Tkinter:\n  class NativeMessagingWindow(tkinter.Frame):\n    def __init__(self, queue):\n      self.queue = queue\n\n      tkinter.Frame.__init__(self)\n      self.pack()\n\n      self.text = tkinter.Text(self)\n      self.text.grid(row=0, column=0, padx=10, pady=10, columnspan=2)\n      self.text.config(state=tkinter.DISABLED, height=10, width=40)\n\n      self.messageContent = tkinter.StringVar()\n      self.sendEntry = tkinter.Entry(self, textvariable=self.messageContent)\n      self.sendEntry.grid(row=1, column=0, padx=10, pady=10)\n\n      self.sendButton = tkinter.Button(self, text=\"Send\", command=self.onSend)\n      self.sendButton.grid(row=1, column=1, padx=10, pady=10)\n\n      self.after(100, self.processMessages)\n\n    def processMessages(self):\n      while not self.queue.empty():\n        message = self.queue.get_nowait()\n        if message == None:\n          self.quit()\n          return\n        self.log(\"Received %s\" % message)\n\n      self.after(100, self.processMessages)\n\n    def onSend(self):\n      text = '{\"text\": \"' + self.messageContent.get() + '\"}'\n      self.log('Sending %s' % text)\n      try:\n        send_message(text)\n      except IOError:\n        tkinter.messagebox.showinfo('Native Messaging Example',\n                              'Failed to send message.')\n        sys.exit(1)\n\n    def log(self, message):\n      self.text.config(state=tkinter.NORMAL)\n      self.text.insert(tkinter.END, message + \"\\n\")\n      self.text.config(state=tkinter.DISABLED)\n\n\ndef Main():\n  if not Tkinter:\n    send_message('\"Tkinter python module wasn\\'t found. Running in headless ' +\n                 'mode. Please consider installing Tkinter.\"')\n    read_thread_func(None)\n    sys.exit(0)\n\n  queue = Queue.Queue()\n\n  main_window = NativeMessagingWindow(queue)\n  main_window.master.title('Native Messaging Example')\n\n  thread = threading.Thread(target=read_thread_func, args=(queue,))\n  thread.daemon = True\n  thread.start()\n\n  main_window.mainloop()\n\n  sys.exit(0)\n\n\nif __name__ == '__main__':\n  Main()\n"
  },
  {
    "path": "api-samples/nativeMessaging/host/native-messaging-example-host.bat",
    "content": "@echo off\n:: Copyright (c) 2013 The Chromium Authors. All rights reserved.\n:: Use of this source code is governed by a BSD-style license that can be\n:: found in the LICENSE file.\n\npython \"%~dp0/native-messaging-example-host\" %*\n"
  },
  {
    "path": "api-samples/nativeMessaging/host/uninstall_host.bat",
    "content": ":: Copyright 2014 The Chromium Authors. All rights reserved.\n:: Use of this source code is governed by a BSD-style license that can be\n:: found in the LICENSE file.\n\n:: Deletes the entry created by install_host.bat\nREG DELETE \"HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\com.google.chrome.example.echo\" /f\nREG DELETE \"HKLM\\Software\\Google\\Chrome\\NativeMessagingHosts\\com.google.chrome.example.echo\" /f\n"
  },
  {
    "path": "api-samples/nativeMessaging/host/uninstall_host.sh",
    "content": "#!/bin/sh\n# Copyright 2013 The Chromium Authors. All rights reserved.\n# Use of this source code is governed by a BSD-style license that can be\n# found in the LICENSE file.\n\nset -e\n\nif [ \"$(uname -s)\" = \"Darwin\" ]; then\n  if [ \"$(whoami)\" = \"root\" ]; then\n    HOST_PATH=\"/Applications/native-messaging-example-host\"\n    rm $HOST_PATH\n    TARGET_DIR=\"/Library/Google/Chrome/NativeMessagingHosts\"\n  else\n    HOST_PATH=\"/Users/$USER/Applications/native-messaging-example-host\"\n    rm $HOST_PATH\n    TARGET_DIR=\"$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts\"\n  fi\nelse\n  if [ \"$(whoami)\" = \"root\" ]; then\n    TARGET_DIR=\"/etc/opt/chrome/native-messaging-hosts\"\n  else\n    TARGET_DIR=\"$HOME/.config/google-chrome/NativeMessagingHosts\"\n  fi\nfi\n\nHOST_NAME=com.google.chrome.example.echo\nrm \"$TARGET_DIR/com.google.chrome.example.echo.json\"\necho \"Native messaging host $HOST_NAME has been uninstalled.\"\n"
  },
  {
    "path": "api-samples/omnibox/new-tab-search/README.md",
    "content": "# chrome.omnibox\n\nThis sample demonstrates the `\"omnibox\"` manifest key and API by creating a keyword that opens up a browser search in a new tab.\n\n## Overview\n\nThe extension uses the `\"omnibox\"` manifest key and its parameter `\"keyword\"`. When `chrome.omnibox.onInputEntered.addListener()` is called and the keyword 'newTab' is used, a new tab is opened with a google search for the user's input text.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Type 'newTab' and some text you wish to google within the browser omnibox.\n"
  },
  {
    "path": "api-samples/omnibox/new-tab-search/background.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// This event is fired with the user accepts the input in the omnibox.\nchrome.omnibox.onInputEntered.addListener((text) => {\n  // Encode user input for special characters , / ? : @ & = + $ #\n  const newURL = 'https://www.google.com/search?q=' + encodeURIComponent(text);\n  chrome.tabs.create({ url: newURL });\n});\n"
  },
  {
    "path": "api-samples/omnibox/new-tab-search/manifest.json",
    "content": "{\n  \"name\": \"Omnibox - New Tab Search\",\n  \"description\": \"Demonstrates the \\\"omnibox\\\" manifest key and API by creating a keyword that opens a browser search in a new tab.\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"omnibox\": { \"keyword\": \"newTab\" },\n  \"action\": {\n    \"default_icon\": {\n      \"16\": \"newtab_search16.png\",\n      \"32\": \"newtab_search32.png\",\n      \"48\": \"newtab_search48.png\",\n      \"128\": \"newtab_search128.png\"\n    }\n  },\n  \"icons\": {\n    \"16\": \"newtab_search16.png\",\n    \"32\": \"newtab_search32.png\",\n    \"48\": \"newtab_search48.png\",\n    \"128\": \"newtab_search128.png\"\n  }\n}\n"
  },
  {
    "path": "api-samples/omnibox/simple-example/README.md",
    "content": "# chrome.omnibox - Simple Example\n\nThis sample demonstrates the `\"omnibox\"` manifest key and most of the omnibox APIs.\n\n## Overview\n\nThe extension uses the `\"omnibox\"` manifest key and its parameter `\"keyword\"`. The extension will print logs to the logs page when the omnibox events are triggered.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension's action icon to open the logs page.\n4. Type `omnix` in the omnibox and press `Space` to see the suggestions.\n5. Try to type something to see how the `onInputChanged` event is triggered.\n6. Try to left-click or middle-click on the suggestions to see how the `onInputEntered` event is triggered.\n7. Try to remove some suggestions by clicking the `x` icon on the right of the suggestion to see how the `onInputCancelled` event is triggered.\n"
  },
  {
    "path": "api-samples/omnibox/simple-example/logs.css",
    "content": "html,\nbody {\n    font-family: \"Segoe UI\", Tahoma, Geneva, Verdana, sans-serif;\n    font-size: 14px;\n    margin: 0;\n    padding: 0;\n}\n\n* {\n    box-sizing: border-box;\n}\n\nbody {\n    padding: 10px;\n    height: 100vh;\n}\n\nh1 {\n    margin: 0;\n    padding: 0;\n}\n\n#logs {\n    max-height: calc(100vh - 100px);\n    font-size: 1.2rem;\n    position: fixed;\n    bottom: 10px;\n    left: 10px;\n    right: 10px;\n    overflow: auto;\n}\n"
  },
  {
    "path": "api-samples/omnibox/simple-example/logs.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Omnibox Logs Output</title>\n    <link rel=\"stylesheet\" href=\"./logs.css\" />\n  </head>\n\n  <body>\n    <header>\n      <h1>Omnibox Logs Output</h1>\n      <small\n        >Type 'omnix' plus a search term into the Omnibox and you could find\n        logs here.</small\n      >\n    </header>\n    <div id=\"logs\">\n      <div class=\"log-item\">---------------Logs--------------</div>\n      <!-- New logs will be appended here -->\n    </div>\n    <script src=\"./logs.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/omnibox/simple-example/logs.js",
    "content": "const LOGS_CONTAINER = document.getElementById('logs');\n\nconst getFormattedTime = () => {\n  const now = new Date();\n  const hours = now.getHours().toString().padStart(2, '0');\n  const minutes = now.getMinutes().toString().padStart(2, '0');\n  const seconds = now.getSeconds().toString().padStart(2, '0');\n  const milliseconds = now.getMilliseconds().toString().padStart(3, '0');\n  return `${hours}:${minutes}:${seconds}.${milliseconds}`;\n};\n\nconst appendLog = (text) => {\n  const log = document.createElement('div');\n  log.classList.add('log-item');\n  log.innerText = `[${getFormattedTime()}] ${text}`;\n  LOGS_CONTAINER.appendChild(log);\n  LOGS_CONTAINER.scrollTop = LOGS_CONTAINER.scrollHeight;\n};\n\nchrome.runtime.onMessage.addListener((message) => {\n  if (message.type === 'append-log') {\n    appendLog(message.text);\n  }\n});\n"
  },
  {
    "path": "api-samples/omnibox/simple-example/manifest.json",
    "content": "{\n  \"name\": \"Omnibox Simple Example\",\n  \"description\": \"Demonstrates the \\\"omnibox\\\" manifest key and most members of the omnibox API.\",\n  \"version\": \"1.1\",\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"action\": {},\n  \"omnibox\": {\n    \"keyword\": \"omnix\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/omnibox/simple-example/service-worker.js",
    "content": "const appendLog = (text) => {\n  chrome.runtime.sendMessage({ type: 'append-log', text });\n};\n\nchrome.action.onClicked.addListener(() => {\n  chrome.tabs.create({ url: 'logs.html' });\n});\n\nchrome.omnibox.onInputStarted.addListener(function () {\n  appendLog('💬 onInputStarted');\n\n  chrome.omnibox.setDefaultSuggestion({\n    description:\n      \"Here is a default <match>suggestion</match>. <url>It's <match>url</match> here</url>\"\n  });\n});\n\nchrome.omnibox.onInputChanged.addListener(function (text, suggest) {\n  appendLog('✏️ onInputChanged: ' + text);\n  suggest([\n    { content: text + ' one', description: 'the first one', deletable: true },\n    {\n      content: text + ' number two',\n      description: 'the second entry',\n      deletable: true\n    }\n  ]);\n});\n\nchrome.omnibox.onInputEntered.addListener(function (text, disposition) {\n  appendLog(\n    `✔️ onInputEntered: text -> ${text} | disposition -> ${disposition}`\n  );\n});\n\nchrome.omnibox.onInputCancelled.addListener(function () {\n  appendLog('❌ onInputCancelled');\n});\n\nchrome.omnibox.onDeleteSuggestion.addListener(function (text) {\n  appendLog('⛔ onDeleteSuggestion: ' + text);\n});\n"
  },
  {
    "path": "api-samples/override/blank_ntp/README.md",
    "content": "# \"chrome_url_overrides\"\n\nThis sample demonstrates the ` \"chrome_url_overrides\"` manifest key by replacing the user's default New Tab page with a new html file.\n\n## Overview\n\nThe extension calls ` \"chrome_url_overrides\"` and its parameter `\"newtab\"` to replace the New Tab page with blank.html.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Open a new tab while the extension is enabled.\n"
  },
  {
    "path": "api-samples/override/blank_ntp/blank.html",
    "content": "<html>\n  <head>\n    <title>Blank New Tab</title>\n    <style>\n      div {\n        color: #cccccc;\n        vertical-align: 50%;\n        text-align: center;\n        font-family: sans-serif;\n        font-size: 300%;\n      }\n    </style>\n  </head>\n  <body>\n    <div style=\"height: 40%\"></div>\n    <div>Blank New Tab&trade;</div>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/override/blank_ntp/manifest.json",
    "content": "{\n  \"name\": \"Blank new tab page\",\n  \"description\": \"Uses the \\\"chrome_url_overrides\\\" manifest key by replacing the user's default new tab page with a new html file.\",\n  \"version\": \"0.3\",\n  \"incognito\": \"split\",\n  \"chrome_url_overrides\": {\n    \"newtab\": \"blank.html\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/power/README.md",
    "content": "# chrome.power\n\nThis extension demonstrates the `chrome.power` API by allowing users to override their system's power management features.\n\n## Overview\n\nThe extension adds a popup that cycles different states when clicked. It will go though a mode that prevents the display from dimming or going to sleep, a mode that keeps the system awake but allows the screen to dim/go to sleep, and a mode that uses the system's default.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extension and click the action button.\n"
  },
  {
    "path": "api-samples/power/_locales/en/messages.json",
    "content": "{\n  \"extensionName\": {\n    \"message\": \"Keep Awake\",\n    \"description\": \"Extension name.\"\n  },\n  \"extensionDescription\": {\n    \"message\": \"Override system power-saving settings.\",\n    \"description\": \"Extension description.\"\n  },\n  \"disabledTitle\": {\n    \"message\": \"Default power-saving settings\",\n    \"description\": \"Browser action title when disabled.\"\n  },\n  \"displayTitle\": {\n    \"message\": \"Screen will be kept on\",\n    \"description\": \"Browser action title when preventing screen-off.\"\n  },\n  \"systemTitle\": {\n    \"message\": \"System will stay awake\",\n    \"description\": \"Browser action title when preventing system sleep.\"\n  }\n}\n"
  },
  {
    "path": "api-samples/power/background.js",
    "content": "// Copyright (c) 2013 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * States that the extension can be in.\n */\nlet StateEnum = {\n  DISABLED: 'disabled',\n  DISPLAY: 'display',\n  SYSTEM: 'system'\n};\n\n/**\n * Key used for storing the current state in {localStorage}.\n */\nlet STATE_KEY = 'state';\n\n/**\n * Loads the locally-saved state asynchronously.\n * @param {function} callback Callback invoked with the loaded {StateEnum}.\n */\nfunction loadSavedState(callback) {\n  chrome.storage.local.get(STATE_KEY, function (items) {\n    let savedState = items[STATE_KEY];\n    for (let key in StateEnum) {\n      if (savedState == StateEnum[key]) {\n        callback(savedState);\n        return;\n      }\n    }\n    callback(StateEnum.DISABLED);\n  });\n}\n\n/**\n * Switches to a new state.\n * @param {string} newState New {StateEnum} to use.\n */\nfunction setState(newState) {\n  let imagePrefix = 'night';\n  let title = '';\n\n  switch (newState) {\n    case StateEnum.DISABLED:\n      chrome.power.releaseKeepAwake();\n      imagePrefix = 'night';\n      title = chrome.i18n.getMessage('disabledTitle');\n      break;\n    case StateEnum.DISPLAY:\n      chrome.power.requestKeepAwake('display');\n      imagePrefix = 'day';\n      title = chrome.i18n.getMessage('displayTitle');\n      break;\n    case StateEnum.SYSTEM:\n      chrome.power.requestKeepAwake('system');\n      imagePrefix = 'sunset';\n      title = chrome.i18n.getMessage('systemTitle');\n      break;\n    default:\n      throw 'Invalid state \"' + newState + '\"';\n  }\n\n  let items = {};\n  items[STATE_KEY] = newState;\n  chrome.storage.local.set(items);\n\n  chrome.action.setIcon({\n    path: {\n      19: 'images/' + imagePrefix + '-19.png',\n      38: 'images/' + imagePrefix + '-38.png'\n    }\n  });\n  chrome.action.setTitle({ title: title });\n}\n\nchrome.action.onClicked.addListener(function () {\n  loadSavedState(function (state) {\n    switch (state) {\n      case StateEnum.DISABLED:\n        setState(StateEnum.DISPLAY);\n        break;\n      case StateEnum.DISPLAY:\n        setState(StateEnum.SYSTEM);\n        break;\n      case StateEnum.SYSTEM:\n        setState(StateEnum.DISABLED);\n        break;\n      default:\n        throw 'Invalid state \"' + state + '\"';\n    }\n  });\n});\n\nchrome.runtime.onStartup.addListener(function () {\n  loadSavedState(function (state) {\n    setState(state);\n  });\n});\n"
  },
  {
    "path": "api-samples/power/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n\n  \"name\": \"__MSG_extensionName__\",\n  \"description\": \"__MSG_extensionDescription__\",\n  \"version\": \"1.9\",\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"48\": \"images/icon-48.png\",\n    \"128\": \"images/icon-128.png\"\n  },\n\n  \"permissions\": [\"power\", \"storage\"],\n  \"action\": {\n    \"default_title\": \"__MSG_disabledTitle__\",\n    \"default_icon\": {\n      \"19\": \"images/night-19.png\",\n      \"38\": \"images/night-38.png\"\n    }\n  },\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n\n  \"default_locale\": \"en\"\n}\n"
  },
  {
    "path": "api-samples/printing/README.md",
    "content": "# chrome.printing\n\nThis sample demonstrates all four methods of the `chrome.printing` namespace.\n\n## Overview\n\nThe `chrome.printing` namespace only works on ChromeOS. The sample demonstrates how to get a list of available printers and display it to a user. A 'Print' button sends a sample PDF to the selected printer and makes a 'Cancel Printing' visible. This button is visible while the print job's status is `\"PENDING\"` or `\"IN_PROGRESS\"`. Note that on some systems, the print job is passed to the printer so quickly that you may never see the 'Cancel Printing' button.\n\nCalling `submitJob()` triggers a dialog box asking the user to confirm printing. Use the [`PrintingAPIExtensionsAllowlist`](https://chromeenterprise.google/policies/#PrintingAPIExtensionsAllowlist\") policy to bypass confirmation.\n\nIf the **Roll Printers** checkbox is selected, only printers capable of roll printing will appear in the table. In this case, a separate test file is printed and the height of the media can be variable. See [`Roll printing`](https://developer.chrome.com/docs/extensions/reference/printing/#roll-printing) for more information.\n\n## Implementation Notes\n\nBefore Chrome 120, `submitJob()` function throws an error when returning a promise.\n"
  },
  {
    "path": "api-samples/printing/background.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.action.onClicked.addListener(() => {\n  chrome.tabs.create({\n    url: 'printers.html'\n  });\n});\n"
  },
  {
    "path": "api-samples/printing/manifest.json",
    "content": "{\n  \"name\": \"Print Extension\",\n  \"version\": \"1.0\",\n  \"description\": \"Demonstrates all four methods of the chrome.printing namespace.\",\n  \"permissions\": [\"printing\"],\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"action\": {\n    \"default_icon\": {\n      \"16\": \"icons/icon16.png\",\n      \"48\": \"icons/icon48.png\",\n      \"128\": \"icons/icon128.png\"\n    }\n  },\n  \"icons\": {\n    \"16\": \"icons/icon16.png\",\n    \"48\": \"icons/icon48.png\",\n    \"128\": \"icons/icon128.png\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/printing/printers.css",
    "content": "/**\n * Copyright 2020 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\ntable, th, td, tr {\n  border: 1px solid black;\n}\n\ntable {\n  width: 100%;\n  border-collapse: collapse;\n}\n\ndiv {\n  overflow: auto;\n}\n"
  },
  {
    "path": "api-samples/printing/printers.html",
    "content": "<!--\n * Copyright 2020 The Chromium Authors. All rights reserved.  Use of this\n * source code is governed by a BSD-style license that can be found in the\n * LICENSE file.\n-->\n<!doctype html>\n<html>\n  <head>\n    <title>Printers</title>\n    <link href=\"printers.css\" rel=\"stylesheet\" type=\"text/css\" />\n    <script src=\"printers.js\"></script>\n  </head>\n\n  <body>\n    <h2>Print Job:</h2>\n    <p>\n      On some systems, the print job may leave the queue too quickly to be\n      visible in this list.\n    </p>\n    <div id=\"printJob\">\n      <table id=\"printJobTable\">\n        <thread>\n          <tr>\n            <th>Cancel</th>\n            <th>Job Id</th>\n            <th>Status</th>\n          </tr>\n        </thread>\n        <tbody id=\"printJobTbody\"></tbody>\n      </table>\n    </div>\n\n    <h2>Printers:</h2>\n    <div id=\"printers\">\n      <input type=\"checkbox\" id=\"rollPrinters\" name=\"rollPrinters\" />\n      <label for=\"rollPrinters\">Roll Printers</label>\n      <table id=\"printersTable\">\n        <thead>\n          <tr>\n            <th>Print</th>\n            <th>Id</th>\n            <th>Name</th>\n            <th>Description</th>\n            <th>URI</th>\n            <th>Source</th>\n            <th>Default</th>\n            <th>Recently used</th>\n            <th>Capabilities</th>\n            <th>Supports trim</th>\n            <th>Status</th>\n          </tr>\n        </thead>\n        <tbody id=\"tbody\" />\n      </table>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/printing/printers.js",
    "content": "// Copyright 2020 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nlet listOfPrinters = [];\nlet filename;\n\nfunction rollPrintingEnabled() {\n  return document.getElementById('rollPrinters').checked;\n}\n\nfunction onPrintButtonClicked(printerId, dpi, performTrim) {\n  let ticket = {\n    version: '1.0',\n    print: {\n      color: { type: 'STANDARD_MONOCHROME' },\n      duplex: { type: 'NO_DUPLEX' },\n      page_orientation: { type: 'LANDSCAPE' },\n      copies: { copies: 1 },\n      dpi: {\n        horizontal_dpi: dpi.horizontal_dpi,\n        vertical_dpi: dpi.vertical_dpi\n      },\n      collate: { collate: false }\n    }\n  };\n\n  if (rollPrintingEnabled()) {\n    filename = 'test-rollprinting.pdf';\n    ticket.print.media_size = {\n      width_microns: 72320,\n      // Note that this value needs to be between min_height_microns and\n      // max_height_microns.  Usually this matches the height of the document\n      // being printed.\n      height_microns: 110000\n    };\n    // This only makese sense to specify if the printer supports the trim\n    // option.\n    if (performTrim) {\n      ticket.print.vendor_ticket_item = [{ id: 'finishings', value: 'trim' }];\n    }\n  } else {\n    filename = 'test.pdf';\n    ticket.print.media_size = {\n      width_microns: 210000,\n      height_microns: 297000,\n      vendor_id: 'iso_a4_210x297mm'\n    };\n  }\n\n  fetch(filename)\n    .then((response) => response.arrayBuffer())\n    .then((arrayBuffer) => {\n      const request = {\n        job: {\n          printerId: printerId,\n          title: 'test job',\n          ticket: ticket,\n          contentType: 'application/pdf',\n          document: new Blob([new Uint8Array(arrayBuffer)], {\n            type: 'application/pdf'\n          })\n        }\n      };\n      chrome.printing.submitJob(request).then((response) => {\n        if (response !== undefined) {\n          console.log(response.status);\n        }\n        if (chrome.runtime.lastError !== undefined) {\n          console.log(chrome.runtime.lastError.message);\n        }\n        window.scrollTo(0, document.body.scrollHeight);\n      });\n    });\n}\n\nfunction onCancelButtonClicked(jobId) {\n  chrome.printing.cancelJob(jobId).then((response) => {\n    if (response !== undefined) {\n      console.log(response.status);\n    }\n    if (chrome.runtime.lastError !== undefined) {\n      console.log(chrome.runtime.lastError.message);\n    }\n  });\n}\n\nfunction createButton(label, onClicked) {\n  const button = document.createElement('button');\n  button.textContent = label;\n  button.onclick = onClicked;\n  return button;\n}\n\nfunction addCell(parent) {\n  const newCell = document.createElement('td');\n  parent.appendChild(newCell);\n  return newCell;\n}\n\nfunction supportsRollPrinting(printerInfo) {\n  // If any of the media size options support continuous feed, return true.\n  return printerInfo.capabilities.printer.media_size.option.find(\n    (option) => option.is_continuous_feed\n  );\n}\n\nfunction createPrintersTable() {\n  // Reset this so the table can be rebuilt with either all printers or just\n  // printers capable of roll printing.\n  let tbody = document.getElementById('tbody');\n  while (tbody.firstChild) {\n    tbody.removeChild(tbody.firstChild);\n  }\n\n  listOfPrinters.forEach((printer) => {\n    if (!rollPrintingEnabled() || supportsRollPrinting(printer.info)) {\n      // The printer needs to support this specific vendor capability if the\n      // print job ticket is going to specify the trim option.\n      const supportsTrim =\n        printer.info.capabilities.printer.vendor_capability.some(\n          (capability) => capability.display_name == 'finishings/11'\n        );\n      const columnValues = [\n        printer.data.id,\n        printer.data.name,\n        printer.data.description,\n        printer.data.uri,\n        printer.data.source,\n        printer.data.isDefault,\n        printer.data.recentlyUsedRank,\n        JSON.stringify(printer.info.capabilities),\n        supportsTrim,\n        printer.info.status\n      ];\n\n      let tr = document.createElement('tr');\n      const printTd = document.createElement('td');\n      printTd.appendChild(\n        createButton('Print', () => {\n          onPrintButtonClicked(\n            printer.data.id,\n            printer.info.capabilities.printer.dpi.option[0],\n            supportsTrim\n          );\n        })\n      );\n\n      tr.appendChild(printTd);\n\n      for (const columnValue of columnValues) {\n        const td = document.createElement('td');\n        td.appendChild(document.createTextNode(columnValue));\n        td.setAttribute('align', 'center');\n        tr.appendChild(td);\n      }\n\n      tbody.appendChild(tr);\n    }\n  });\n\n  chrome.printing.onJobStatusChanged.addListener((jobId, status) => {\n    console.log(`jobId: ${jobId}, status: ${status}`);\n    let jobTr = document.getElementById(jobId);\n    if (jobTr == undefined) {\n      jobTr = document.createElement('tr');\n      jobTr.setAttribute('id', jobId);\n\n      const cancelTd = addCell(jobTr);\n      let cancelBtn = createButton('Cancel', () => {\n        onCancelButtonClicked(jobId);\n      });\n      cancelBtn.setAttribute('id', `id ${jobId}-cancelBtn`);\n      cancelTd.appendChild(cancelBtn);\n\n      const jobIdTd = addCell(jobTr);\n      jobIdTd.appendChild(document.createTextNode(jobId));\n\n      let jobStatusTd = addCell(jobTr);\n      jobStatusTd.id = `${jobId}-status`;\n      jobStatusTd.appendChild(document.createTextNode(status));\n\n      document.getElementById('printJobTbody').appendChild(jobTr);\n    } else {\n      document.getElementById(`${jobId}-status`).innerText = status;\n      if (status !== 'PENDING' && status !== 'IN_PROGRESS') {\n        jobTr.remove();\n      }\n    }\n  });\n}\n\ndocument.addEventListener('DOMContentLoaded', () => {\n  chrome.printing.getPrinters().then((printers) => {\n    printers.forEach((printer) => {\n      chrome.printing.getPrinterInfo(printer.id).then((printerInfo) => {\n        listOfPrinters.push({ data: printer, info: printerInfo });\n        createPrintersTable();\n      });\n    });\n  });\n\n  let checkbox = document.getElementById('rollPrinters');\n  checkbox.addEventListener('change', function () {\n    createPrintersTable();\n  });\n});\n"
  },
  {
    "path": "api-samples/privacy/README.md",
    "content": "# chrome.privacy\n\nThis sample demonstrates using `chrome.privacy.services` to get and set privacy settings.\n\n## Overview\n\nThe service worker sets the default value for autofill using `chrome.privacy.services.autofillCreditCardEnabled.set()` when the extension is installed. Whenever the action button is clicked, the extension toggles the current autofill setting of `autofillCreditCardEnabled` and updates the extension badge.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extension to the taskbar and click the action button.\n"
  },
  {
    "path": "api-samples/privacy/manifest.json",
    "content": "{\n  \"name\": \"Privacy API sample\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"description\": \"Uses the chrome.privacy.services property to get and set privacy settings.\",\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"permissions\": [\"privacy\"],\n  \"action\": {}\n}\n"
  },
  {
    "path": "api-samples/privacy/service-worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.runtime.onInstalled.addListener(() => {\n  // Set default value for credit card autofill enabled\n  chrome.privacy.services.autofillCreditCardEnabled.set({ value: true });\n  updateAutofillEnabledStatus();\n});\n\nchrome.runtime.onStartup.addListener(() => {\n  updateAutofillEnabledStatus();\n});\n\nasync function updateAutofillEnabledStatus(toggle = false) {\n  const details = await chrome.privacy.services.autofillCreditCardEnabled.get(\n    {}\n  );\n  let autofillEnabled = details.value;\n\n  if (toggle) {\n    autofillEnabled = !autofillEnabled;\n    await chrome.privacy.services.autofillCreditCardEnabled.set({\n      value: autofillEnabled\n    });\n  }\n\n  const badgeText = autofillEnabled ? 'Enabled' : 'Disabled';\n  const badgeColor = autofillEnabled ? '#00FF00' : '#FF0000';\n\n  chrome.action.setBadgeText({ text: badgeText });\n  chrome.action.setBadgeBackgroundColor({ color: badgeColor });\n}\n\nchrome.action.onClicked.addListener(() => {\n  updateAutofillEnabledStatus(true);\n});\n"
  },
  {
    "path": "api-samples/readingList/README.md",
    "content": "# chrome.readingList API\n\nThis sample demonstrates using the [chrome.readingList](https://developer.chrome.com/docs/extensions/reference/readingList/) API to view items in the reading list.\n\n## Overview\n\nThe extension's action icon opens a page that allows you to add new items, as well as update or delete existing ones.\n\n<img src=\"screenshot.png\" height=300 alt=\"Screenshot showing the chrome.readingList API demo running in Chrome.\">\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click on the action icon.\n4. An extension page will open.\n\n## Implementation Notes\n\nListeners are added for all events, so the table automatically updates when data in the reading list changes.\n"
  },
  {
    "path": "api-samples/readingList/index.css",
    "content": "/* Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License. */\n\nform {\n  display: inline-block;\n  border: 1px solid #dadce0;\n  min-width: 500px;\n}\n\nh1 {\n  background: #f6f9fe;\n  margin: 0;\n  padding: 15px;\n  font-size: 20px;\n  text-align: center;\n}\n\nlabel {\n  margin: 20px;\n  display: flex;\n  justify-content: space-between;\n}\n\nsection {\n  margin: 10px;\n  border: 2px solid grey;\n  padding: 10px;\n}\n\nsection h2 {\n  margin: 0;\n}\n\n#error {\n  display: none;\n  color: rgb(136, 0, 0);\n}\n\ntable {\n  margin-top: 10px;\n  border-collapse: collapse;\n  width: 500px;\n}\n\ntr {\n  border: 1px solid black;\n}\n\nth:first-child,\ntd:first-child {\n  width: 40%;\n}\n\nth,\ntd {\n  border: 1px solid black;\n  padding: 5px;\n  text-align: center;\n  width: 20%;\n}\n\nbutton {\n  display: block;\n  margin: 5px 0;\n  width: 100%;\n}\n"
  },
  {
    "path": "api-samples/readingList/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Reading List Demo</title>\n    <link rel=\"stylesheet\" href=\"index.css\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <template id=\"table-item\">\n      <tr>\n        <td><a>Title</a></td>\n        <td>\n          <select name=\"read\" value=\"no\">\n            <option value=\"no\">No</option>\n            <option value=\"yes\">Yes</option>\n          </select>\n        </td>\n        <td>1/1/1970, 00:00:00</td>\n        <td>\n          <button class=\"update-button\">Update</button>\n          <button class=\"delete-button\">Delete</button>\n        </td>\n      </tr>\n    </template>\n    <form>\n      <h1>Reading List Demo</h1>\n      <section>\n        <h2>Add new item</h2>\n        <label>\n          <span>Title</span>\n          <input type=\"text\" name=\"title\" value=\"Example URL\" />\n        </label>\n        <label>\n          <span>URL</span>\n          <input type=\"text\" name=\"url\" value=\"https://example.com/*\" />\n        </label>\n        <label>\n          <span>Has been read</span>\n          <select name=\"read\" value=\"no\">\n            <option value=\"no\">No</option>\n            <option value=\"yes\">Yes</option>\n          </select>\n        </label>\n        <button type=\"button\" id=\"add-item\">Add item</button>\n        <p id=\"error\"></p>\n      </section>\n      <section>\n        <h2>Items</h2>\n        <table id=\"items\">\n          <tr>\n            <th>Title</th>\n            <th>Read</th>\n            <th>Created At</th>\n            <th>Actions</th>\n          </tr>\n        </table>\n      </section>\n    </form>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/readingList/index.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst ADD_ITEM_BUTTON_ID = 'add-item';\nconst ITEMS_TABLE_ID = 'items';\nconst TABLE_ITEM_TEMPLATE_ID = 'table-item';\nconst READ_SELECT_YES_VALUE = 'yes';\nconst READ_SELECT_NO_VALUE = 'no';\n\n/**\n * Removes an entry from the reading list.\n *\n * @param url URL of entry to remove.\n */\nasync function removeEntry(url) {\n  await chrome.readingList.removeEntry({ url });\n}\n\n/**\n * Adds an entry to the reading list.\n *\n * @param title Title of the entry\n * @param url URL of entry to add\n * @param hasBeenRead If the entry has been read\n */\nasync function addEntry(title, url, hasBeenRead) {\n  await chrome.readingList.addEntry({ title, url, hasBeenRead });\n}\n\n/**\n * Updates an entry in the reading list.\n *\n * @param url URL of entry to update\n * @param hasBeenRead If the entry has been read\n */\nasync function updateEntry(url, hasBeenRead) {\n  await chrome.readingList.updateEntry({ url, hasBeenRead });\n}\n\n/**\n * Updates the UI with the current reading list items.\n */\nasync function updateUI() {\n  const items = await chrome.readingList.query({});\n\n  const table = document.getElementById(ITEMS_TABLE_ID);\n\n  for (const item of items) {\n    // Use existing row if possible, otherwise create a new one.\n    const row =\n      document.querySelector(`[data-url=\"${item.url}\"]`) ||\n      document.getElementById(TABLE_ITEM_TEMPLATE_ID).content.cloneNode(true)\n        .children[0];\n\n    updateRow(row, item);\n\n    table.appendChild(row);\n  }\n\n  // Remove any rows that no longer exist\n  table.querySelectorAll('tr').forEach((row, i) => {\n    // Ignore header row\n    if (i === 0) return;\n    if (!items.find((i) => i.url === row.getAttribute('data-url'))) {\n      row.remove();\n    }\n  });\n}\n\n/**\n * Updates a row with the data from item.\n *\n * @param row Table row element to update.\n * @param item Data from reading list API.\n */\nfunction updateRow(row, item) {\n  row.setAttribute('data-url', item.url);\n\n  const titleField = row.querySelector('td:nth-child(1) a');\n  titleField.href = item.url;\n  titleField.innerText = item.title;\n\n  const readField = row.querySelector('td:nth-child(2) select');\n  readField.value = item.hasBeenRead\n    ? READ_SELECT_YES_VALUE\n    : READ_SELECT_NO_VALUE;\n\n  const createdAtField = row.querySelector('td:nth-child(3)');\n  createdAtField.innerText = `${new Date(item.creationTime).toLocaleString()}`;\n\n  const deleteButton = row.querySelector('.delete-button');\n  deleteButton.addEventListener('click', async (event) => {\n    event.preventDefault();\n    await removeEntry(item.url);\n    updateUI();\n  });\n\n  const updateButton = row.querySelector('.update-button');\n  updateButton.addEventListener('click', async (event) => {\n    event.preventDefault();\n    await updateEntry(item.url, readField.value === READ_SELECT_YES_VALUE);\n  });\n}\n\nconst ERROR_ID = 'error';\n\nconst ITEM_TITLE_SELECTOR = '[name=\"title\"]';\nconst ITEM_URL_SELECTOR = '[name=\"url\"]';\nconst ITEM_READ_SELECTOR = '[name=\"read\"]';\n\n// Add item button click handler\ndocument\n  .getElementById(ADD_ITEM_BUTTON_ID)\n  .addEventListener('click', async () => {\n    try {\n      // Get data from input fields\n      const title = document.querySelector(ITEM_TITLE_SELECTOR).value;\n      const url = document.querySelector(ITEM_URL_SELECTOR).value;\n      const hasBeenRead =\n        document.querySelector(ITEM_READ_SELECTOR).value ===\n        READ_SELECT_YES_VALUE;\n\n      // Attempt to add the entry\n      await addEntry(title, url, hasBeenRead);\n      document.getElementById(ERROR_ID).style.display = 'none';\n    } catch (ex) {\n      // Something went wrong, show an error\n      document.getElementById(ERROR_ID).innerText = ex.message;\n      document.getElementById(ERROR_ID).style.display = 'block';\n    }\n\n    updateUI();\n  });\n\nupdateUI();\n\n// Update the UI whenever data in the reading list changes\nchrome.readingList.onEntryAdded.addListener(updateUI);\nchrome.readingList.onEntryRemoved.addListener(updateUI);\nchrome.readingList.onEntryUpdated.addListener(updateUI);\n"
  },
  {
    "path": "api-samples/readingList/manifest.json",
    "content": "{\n  \"name\": \"Reading List API Demo\",\n  \"version\": \"1.0\",\n  \"minimum_chrome_version\": \"120\",\n  \"manifest_version\": 3,\n  \"description\": \"Uses the chrome.readingList API to display, update and remove reading list entries.\",\n  \"background\": {\n    \"service_worker\": \"sw.js\"\n  },\n  \"permissions\": [\"readingList\"],\n  \"action\": {}\n}\n"
  },
  {
    "path": "api-samples/readingList/sw.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.action.onClicked.addListener(openDemoTab);\n\nfunction openDemoTab() {\n  chrome.tabs.create({ url: 'index.html' });\n}\n"
  },
  {
    "path": "api-samples/richNotification/manifest.json",
    "content": "{\n  \"name\": \"Notifications API sample\",\n  \"description\": \"Demonstrates the creation of, and interaction with, each of the notification template types.\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"action\": {\n    \"default_popup\": \"popup.html\"\n  },\n  \"permissions\": [\"notifications\"]\n}\n"
  },
  {
    "path": "api-samples/richNotification/popup.html",
    "content": "<!--\n Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n<!doctype html>\n<html>\n  <head>\n    <title>Rich Notifications</title>\n    <script src=\"popup.js\"></script>\n  </head>\n  <body>\n    <h1>Notification Types</h1>\n    <button id=\"basic\">Basic Notification</button>\n    <button id=\"progress\">\n      Progress Notification (Progress bar not shown on MacOS)\n    </button>\n    <button id=\"list\">\n      List Notification (First item only shown on MacOS)\n    </button>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/richNotification/popup.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\ndocument.addEventListener('DOMContentLoaded', () => {\n  const basic = document.getElementById('basic');\n  const progressNotif = document.getElementById('progress');\n  const list = document.getElementById('list');\n\n  basic.addEventListener('click', () => {\n    let options = {\n      type: 'basic',\n      title: 'Basic Notification',\n      message: 'This is a Basic Notification',\n      iconUrl: 'icon.png'\n    };\n    chrome.notifications.create(options);\n  });\n\n  progressNotif.addEventListener('click', () => {\n    let options = {\n      type: 'progress',\n      title: 'Progress Notification',\n      message: 'This is a Progress Notification',\n      iconUrl: 'icon.png',\n      progress: 99\n    };\n    chrome.notifications.create(options);\n  });\n\n  list.addEventListener('click', () => {\n    let options = {\n      type: 'list',\n      title: 'List Notification',\n      message: 'This is a List Notification',\n      iconUrl: 'icon.png',\n      items: [\n        { title: 'list element 1', message: 'list message 1' },\n        { title: 'list element 2', message: 'list message 2' }\n      ]\n    };\n    chrome.notifications.create(options);\n  });\n});\n"
  },
  {
    "path": "api-samples/richNotification/readme.md",
    "content": "# chrome.notifications\n\nThis sample demonstrates the creation of, and interaction with, each of the notification template types.\n\n## Overview\n\nThe sample uses `chrome.notification.create` to cycle through creating notifications of different types. The `chrome.notifications.onClicked` event listener is used to allow the user to interact with the notifications to cycle through creating new template types.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Make sure notifications are set to on.\n4. Click the extension's action button to create a notification to interact with.\n"
  },
  {
    "path": "api-samples/sandbox/sandbox/LICENSE.handlebars",
    "content": "Copyright (C) 2011 by Yehuda Katz\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n"
  },
  {
    "path": "api-samples/sandbox/sandbox/handlebars-1.0.0.beta.6.js",
    "content": "// Copyright (C) 2011 by Yehuda Katz\n// Licensing details in LICENSE.handlebars\n\n// lib/handlebars/base.js\n/* eslint-disable */\nvar Handlebars = {};\n\nHandlebars.VERSION = '1.0.beta.6';\n\nHandlebars.helpers = {};\nHandlebars.partials = {};\n\nHandlebars.registerHelper = function (name, fn, inverse) {\n  if (inverse) {\n    fn.not = inverse;\n  }\n  this.helpers[name] = fn;\n};\n\nHandlebars.registerPartial = function (name, str) {\n  this.partials[name] = str;\n};\n\nHandlebars.registerHelper('helperMissing', function (arg) {\n  if (arguments.length === 2) {\n    return undefined;\n  } else {\n    throw new Error(\"Could not find property '\" + arg + \"'\");\n  }\n});\n\nvar toString = Object.prototype.toString,\n  functionType = '[object Function]';\n\nHandlebars.registerHelper('blockHelperMissing', function (context, options) {\n  var inverse = options.inverse || function () {},\n    fn = options.fn;\n\n  var ret = '';\n  var type = toString.call(context);\n\n  if (type === functionType) {\n    context = context.call(this);\n  }\n\n  if (context === true) {\n    return fn(this);\n  } else if (context === false || context == null) {\n    return inverse(this);\n  } else if (type === '[object Array]') {\n    if (context.length > 0) {\n      for (var i = 0, j = context.length; i < j; i++) {\n        ret = ret + fn(context[i]);\n      }\n    } else {\n      ret = inverse(this);\n    }\n    return ret;\n  } else {\n    return fn(context);\n  }\n});\n\nHandlebars.registerHelper('each', function (context, options) {\n  var fn = options.fn,\n    inverse = options.inverse;\n  var ret = '';\n\n  if (context && context.length > 0) {\n    for (var i = 0, j = context.length; i < j; i++) {\n      ret = ret + fn(context[i]);\n    }\n  } else {\n    ret = inverse(this);\n  }\n  return ret;\n});\n\nHandlebars.registerHelper('if', function (context, options) {\n  var type = toString.call(context);\n  if (type === functionType) {\n    context = context.call(this);\n  }\n\n  if (!context || Handlebars.Utils.isEmpty(context)) {\n    return options.inverse(this);\n  } else {\n    return options.fn(this);\n  }\n});\n\nHandlebars.registerHelper('unless', function (context, options) {\n  var fn = options.fn,\n    inverse = options.inverse;\n  options.fn = inverse;\n  options.inverse = fn;\n\n  return Handlebars.helpers['if'].call(this, context, options);\n});\n\nHandlebars.registerHelper('with', function (context, options) {\n  return options.fn(context);\n});\n\nHandlebars.registerHelper('log', function (context) {\n  Handlebars.log(context);\n});\n// lib/handlebars/compiler/parser.js\n/* Jison generated parser */\nvar handlebars = (function () {\n  var parser = {\n    trace: function trace() {},\n    yy: {},\n    symbols_: {\n      error: 2,\n      root: 3,\n      program: 4,\n      EOF: 5,\n      statements: 6,\n      simpleInverse: 7,\n      statement: 8,\n      openInverse: 9,\n      closeBlock: 10,\n      openBlock: 11,\n      mustache: 12,\n      partial: 13,\n      CONTENT: 14,\n      COMMENT: 15,\n      OPEN_BLOCK: 16,\n      inMustache: 17,\n      CLOSE: 18,\n      OPEN_INVERSE: 19,\n      OPEN_ENDBLOCK: 20,\n      path: 21,\n      OPEN: 22,\n      OPEN_UNESCAPED: 23,\n      OPEN_PARTIAL: 24,\n      params: 25,\n      hash: 26,\n      param: 27,\n      STRING: 28,\n      INTEGER: 29,\n      BOOLEAN: 30,\n      hashSegments: 31,\n      hashSegment: 32,\n      ID: 33,\n      EQUALS: 34,\n      pathSegments: 35,\n      SEP: 36,\n      $accept: 0,\n      $end: 1\n    },\n    terminals_: {\n      2: 'error',\n      5: 'EOF',\n      14: 'CONTENT',\n      15: 'COMMENT',\n      16: 'OPEN_BLOCK',\n      18: 'CLOSE',\n      19: 'OPEN_INVERSE',\n      20: 'OPEN_ENDBLOCK',\n      22: 'OPEN',\n      23: 'OPEN_UNESCAPED',\n      24: 'OPEN_PARTIAL',\n      28: 'STRING',\n      29: 'INTEGER',\n      30: 'BOOLEAN',\n      33: 'ID',\n      34: 'EQUALS',\n      36: 'SEP'\n    },\n    productions_: [\n      0,\n      [3, 2],\n      [4, 3],\n      [4, 1],\n      [4, 0],\n      [6, 1],\n      [6, 2],\n      [8, 3],\n      [8, 3],\n      [8, 1],\n      [8, 1],\n      [8, 1],\n      [8, 1],\n      [11, 3],\n      [9, 3],\n      [10, 3],\n      [12, 3],\n      [12, 3],\n      [13, 3],\n      [13, 4],\n      [7, 2],\n      [17, 3],\n      [17, 2],\n      [17, 2],\n      [17, 1],\n      [25, 2],\n      [25, 1],\n      [27, 1],\n      [27, 1],\n      [27, 1],\n      [27, 1],\n      [26, 1],\n      [31, 2],\n      [31, 1],\n      [32, 3],\n      [32, 3],\n      [32, 3],\n      [32, 3],\n      [21, 1],\n      [35, 3],\n      [35, 1]\n    ],\n    performAction: function anonymous(\n      yytext,\n      yyleng,\n      yylineno,\n      yy,\n      yystate,\n      $$,\n      _$\n    ) {\n      var $0 = $$.length - 1;\n      switch (yystate) {\n        case 1:\n          return $$[$0 - 1];\n          break;\n        case 2:\n          this.$ = new yy.ProgramNode($$[$0 - 2], $$[$0]);\n          break;\n        case 3:\n          this.$ = new yy.ProgramNode($$[$0]);\n          break;\n        case 4:\n          this.$ = new yy.ProgramNode([]);\n          break;\n        case 5:\n          this.$ = [$$[$0]];\n          break;\n        case 6:\n          $$[$0 - 1].push($$[$0]);\n          this.$ = $$[$0 - 1];\n          break;\n        case 7:\n          this.$ = new yy.InverseNode($$[$0 - 2], $$[$0 - 1], $$[$0]);\n          break;\n        case 8:\n          this.$ = new yy.BlockNode($$[$0 - 2], $$[$0 - 1], $$[$0]);\n          break;\n        case 9:\n          this.$ = $$[$0];\n          break;\n        case 10:\n          this.$ = $$[$0];\n          break;\n        case 11:\n          this.$ = new yy.ContentNode($$[$0]);\n          break;\n        case 12:\n          this.$ = new yy.CommentNode($$[$0]);\n          break;\n        case 13:\n          this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1]);\n          break;\n        case 14:\n          this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1]);\n          break;\n        case 15:\n          this.$ = $$[$0 - 1];\n          break;\n        case 16:\n          this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1]);\n          break;\n        case 17:\n          this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1], true);\n          break;\n        case 18:\n          this.$ = new yy.PartialNode($$[$0 - 1]);\n          break;\n        case 19:\n          this.$ = new yy.PartialNode($$[$0 - 2], $$[$0 - 1]);\n          break;\n        case 20:\n          break;\n        case 21:\n          this.$ = [[$$[$0 - 2]].concat($$[$0 - 1]), $$[$0]];\n          break;\n        case 22:\n          this.$ = [[$$[$0 - 1]].concat($$[$0]), null];\n          break;\n        case 23:\n          this.$ = [[$$[$0 - 1]], $$[$0]];\n          break;\n        case 24:\n          this.$ = [[$$[$0]], null];\n          break;\n        case 25:\n          $$[$0 - 1].push($$[$0]);\n          this.$ = $$[$0 - 1];\n          break;\n        case 26:\n          this.$ = [$$[$0]];\n          break;\n        case 27:\n          this.$ = $$[$0];\n          break;\n        case 28:\n          this.$ = new yy.StringNode($$[$0]);\n          break;\n        case 29:\n          this.$ = new yy.IntegerNode($$[$0]);\n          break;\n        case 30:\n          this.$ = new yy.BooleanNode($$[$0]);\n          break;\n        case 31:\n          this.$ = new yy.HashNode($$[$0]);\n          break;\n        case 32:\n          $$[$0 - 1].push($$[$0]);\n          this.$ = $$[$0 - 1];\n          break;\n        case 33:\n          this.$ = [$$[$0]];\n          break;\n        case 34:\n          this.$ = [$$[$0 - 2], $$[$0]];\n          break;\n        case 35:\n          this.$ = [$$[$0 - 2], new yy.StringNode($$[$0])];\n          break;\n        case 36:\n          this.$ = [$$[$0 - 2], new yy.IntegerNode($$[$0])];\n          break;\n        case 37:\n          this.$ = [$$[$0 - 2], new yy.BooleanNode($$[$0])];\n          break;\n        case 38:\n          this.$ = new yy.IdNode($$[$0]);\n          break;\n        case 39:\n          $$[$0 - 2].push($$[$0]);\n          this.$ = $$[$0 - 2];\n          break;\n        case 40:\n          this.$ = [$$[$0]];\n          break;\n      }\n    },\n    table: [\n      {\n        3: 1,\n        4: 2,\n        5: [2, 4],\n        6: 3,\n        8: 4,\n        9: 5,\n        11: 6,\n        12: 7,\n        13: 8,\n        14: [1, 9],\n        15: [1, 10],\n        16: [1, 12],\n        19: [1, 11],\n        22: [1, 13],\n        23: [1, 14],\n        24: [1, 15]\n      },\n      { 1: [3] },\n      { 5: [1, 16] },\n      {\n        5: [2, 3],\n        7: 17,\n        8: 18,\n        9: 5,\n        11: 6,\n        12: 7,\n        13: 8,\n        14: [1, 9],\n        15: [1, 10],\n        16: [1, 12],\n        19: [1, 19],\n        20: [2, 3],\n        22: [1, 13],\n        23: [1, 14],\n        24: [1, 15]\n      },\n      {\n        5: [2, 5],\n        14: [2, 5],\n        15: [2, 5],\n        16: [2, 5],\n        19: [2, 5],\n        20: [2, 5],\n        22: [2, 5],\n        23: [2, 5],\n        24: [2, 5]\n      },\n      {\n        4: 20,\n        6: 3,\n        8: 4,\n        9: 5,\n        11: 6,\n        12: 7,\n        13: 8,\n        14: [1, 9],\n        15: [1, 10],\n        16: [1, 12],\n        19: [1, 11],\n        20: [2, 4],\n        22: [1, 13],\n        23: [1, 14],\n        24: [1, 15]\n      },\n      {\n        4: 21,\n        6: 3,\n        8: 4,\n        9: 5,\n        11: 6,\n        12: 7,\n        13: 8,\n        14: [1, 9],\n        15: [1, 10],\n        16: [1, 12],\n        19: [1, 11],\n        20: [2, 4],\n        22: [1, 13],\n        23: [1, 14],\n        24: [1, 15]\n      },\n      {\n        5: [2, 9],\n        14: [2, 9],\n        15: [2, 9],\n        16: [2, 9],\n        19: [2, 9],\n        20: [2, 9],\n        22: [2, 9],\n        23: [2, 9],\n        24: [2, 9]\n      },\n      {\n        5: [2, 10],\n        14: [2, 10],\n        15: [2, 10],\n        16: [2, 10],\n        19: [2, 10],\n        20: [2, 10],\n        22: [2, 10],\n        23: [2, 10],\n        24: [2, 10]\n      },\n      {\n        5: [2, 11],\n        14: [2, 11],\n        15: [2, 11],\n        16: [2, 11],\n        19: [2, 11],\n        20: [2, 11],\n        22: [2, 11],\n        23: [2, 11],\n        24: [2, 11]\n      },\n      {\n        5: [2, 12],\n        14: [2, 12],\n        15: [2, 12],\n        16: [2, 12],\n        19: [2, 12],\n        20: [2, 12],\n        22: [2, 12],\n        23: [2, 12],\n        24: [2, 12]\n      },\n      { 17: 22, 21: 23, 33: [1, 25], 35: 24 },\n      { 17: 26, 21: 23, 33: [1, 25], 35: 24 },\n      { 17: 27, 21: 23, 33: [1, 25], 35: 24 },\n      { 17: 28, 21: 23, 33: [1, 25], 35: 24 },\n      { 21: 29, 33: [1, 25], 35: 24 },\n      { 1: [2, 1] },\n      {\n        6: 30,\n        8: 4,\n        9: 5,\n        11: 6,\n        12: 7,\n        13: 8,\n        14: [1, 9],\n        15: [1, 10],\n        16: [1, 12],\n        19: [1, 11],\n        22: [1, 13],\n        23: [1, 14],\n        24: [1, 15]\n      },\n      {\n        5: [2, 6],\n        14: [2, 6],\n        15: [2, 6],\n        16: [2, 6],\n        19: [2, 6],\n        20: [2, 6],\n        22: [2, 6],\n        23: [2, 6],\n        24: [2, 6]\n      },\n      { 17: 22, 18: [1, 31], 21: 23, 33: [1, 25], 35: 24 },\n      { 10: 32, 20: [1, 33] },\n      { 10: 34, 20: [1, 33] },\n      { 18: [1, 35] },\n      {\n        18: [2, 24],\n        21: 40,\n        25: 36,\n        26: 37,\n        27: 38,\n        28: [1, 41],\n        29: [1, 42],\n        30: [1, 43],\n        31: 39,\n        32: 44,\n        33: [1, 45],\n        35: 24\n      },\n      {\n        18: [2, 38],\n        28: [2, 38],\n        29: [2, 38],\n        30: [2, 38],\n        33: [2, 38],\n        36: [1, 46]\n      },\n      {\n        18: [2, 40],\n        28: [2, 40],\n        29: [2, 40],\n        30: [2, 40],\n        33: [2, 40],\n        36: [2, 40]\n      },\n      { 18: [1, 47] },\n      { 18: [1, 48] },\n      { 18: [1, 49] },\n      { 18: [1, 50], 21: 51, 33: [1, 25], 35: 24 },\n      {\n        5: [2, 2],\n        8: 18,\n        9: 5,\n        11: 6,\n        12: 7,\n        13: 8,\n        14: [1, 9],\n        15: [1, 10],\n        16: [1, 12],\n        19: [1, 11],\n        20: [2, 2],\n        22: [1, 13],\n        23: [1, 14],\n        24: [1, 15]\n      },\n      {\n        14: [2, 20],\n        15: [2, 20],\n        16: [2, 20],\n        19: [2, 20],\n        22: [2, 20],\n        23: [2, 20],\n        24: [2, 20]\n      },\n      {\n        5: [2, 7],\n        14: [2, 7],\n        15: [2, 7],\n        16: [2, 7],\n        19: [2, 7],\n        20: [2, 7],\n        22: [2, 7],\n        23: [2, 7],\n        24: [2, 7]\n      },\n      { 21: 52, 33: [1, 25], 35: 24 },\n      {\n        5: [2, 8],\n        14: [2, 8],\n        15: [2, 8],\n        16: [2, 8],\n        19: [2, 8],\n        20: [2, 8],\n        22: [2, 8],\n        23: [2, 8],\n        24: [2, 8]\n      },\n      {\n        14: [2, 14],\n        15: [2, 14],\n        16: [2, 14],\n        19: [2, 14],\n        20: [2, 14],\n        22: [2, 14],\n        23: [2, 14],\n        24: [2, 14]\n      },\n      {\n        18: [2, 22],\n        21: 40,\n        26: 53,\n        27: 54,\n        28: [1, 41],\n        29: [1, 42],\n        30: [1, 43],\n        31: 39,\n        32: 44,\n        33: [1, 45],\n        35: 24\n      },\n      { 18: [2, 23] },\n      { 18: [2, 26], 28: [2, 26], 29: [2, 26], 30: [2, 26], 33: [2, 26] },\n      { 18: [2, 31], 32: 55, 33: [1, 56] },\n      { 18: [2, 27], 28: [2, 27], 29: [2, 27], 30: [2, 27], 33: [2, 27] },\n      { 18: [2, 28], 28: [2, 28], 29: [2, 28], 30: [2, 28], 33: [2, 28] },\n      { 18: [2, 29], 28: [2, 29], 29: [2, 29], 30: [2, 29], 33: [2, 29] },\n      { 18: [2, 30], 28: [2, 30], 29: [2, 30], 30: [2, 30], 33: [2, 30] },\n      { 18: [2, 33], 33: [2, 33] },\n      {\n        18: [2, 40],\n        28: [2, 40],\n        29: [2, 40],\n        30: [2, 40],\n        33: [2, 40],\n        34: [1, 57],\n        36: [2, 40]\n      },\n      { 33: [1, 58] },\n      {\n        14: [2, 13],\n        15: [2, 13],\n        16: [2, 13],\n        19: [2, 13],\n        20: [2, 13],\n        22: [2, 13],\n        23: [2, 13],\n        24: [2, 13]\n      },\n      {\n        5: [2, 16],\n        14: [2, 16],\n        15: [2, 16],\n        16: [2, 16],\n        19: [2, 16],\n        20: [2, 16],\n        22: [2, 16],\n        23: [2, 16],\n        24: [2, 16]\n      },\n      {\n        5: [2, 17],\n        14: [2, 17],\n        15: [2, 17],\n        16: [2, 17],\n        19: [2, 17],\n        20: [2, 17],\n        22: [2, 17],\n        23: [2, 17],\n        24: [2, 17]\n      },\n      {\n        5: [2, 18],\n        14: [2, 18],\n        15: [2, 18],\n        16: [2, 18],\n        19: [2, 18],\n        20: [2, 18],\n        22: [2, 18],\n        23: [2, 18],\n        24: [2, 18]\n      },\n      { 18: [1, 59] },\n      { 18: [1, 60] },\n      { 18: [2, 21] },\n      { 18: [2, 25], 28: [2, 25], 29: [2, 25], 30: [2, 25], 33: [2, 25] },\n      { 18: [2, 32], 33: [2, 32] },\n      { 34: [1, 57] },\n      { 21: 61, 28: [1, 62], 29: [1, 63], 30: [1, 64], 33: [1, 25], 35: 24 },\n      {\n        18: [2, 39],\n        28: [2, 39],\n        29: [2, 39],\n        30: [2, 39],\n        33: [2, 39],\n        36: [2, 39]\n      },\n      {\n        5: [2, 19],\n        14: [2, 19],\n        15: [2, 19],\n        16: [2, 19],\n        19: [2, 19],\n        20: [2, 19],\n        22: [2, 19],\n        23: [2, 19],\n        24: [2, 19]\n      },\n      {\n        5: [2, 15],\n        14: [2, 15],\n        15: [2, 15],\n        16: [2, 15],\n        19: [2, 15],\n        20: [2, 15],\n        22: [2, 15],\n        23: [2, 15],\n        24: [2, 15]\n      },\n      { 18: [2, 34], 33: [2, 34] },\n      { 18: [2, 35], 33: [2, 35] },\n      { 18: [2, 36], 33: [2, 36] },\n      { 18: [2, 37], 33: [2, 37] }\n    ],\n    defaultActions: { 16: [2, 1], 37: [2, 23], 53: [2, 21] },\n    parseError: function parseError(str, hash) {\n      throw new Error(str);\n    },\n    parse: function parse(input) {\n      var self = this,\n        stack = [0],\n        vstack = [null],\n        lstack = [],\n        table = this.table,\n        yytext = '',\n        yylineno = 0,\n        yyleng = 0,\n        recovering = 0,\n        TERROR = 2,\n        EOF = 1;\n      this.lexer.setInput(input);\n      this.lexer.yy = this.yy;\n      this.yy.lexer = this.lexer;\n      if (typeof this.lexer.yylloc == 'undefined') this.lexer.yylloc = {};\n      var yyloc = this.lexer.yylloc;\n      lstack.push(yyloc);\n      if (typeof this.yy.parseError === 'function')\n        this.parseError = this.yy.parseError;\n      function popStack(n) {\n        stack.length = stack.length - 2 * n;\n        vstack.length = vstack.length - n;\n        lstack.length = lstack.length - n;\n      }\n      function lex() {\n        var token;\n        token = self.lexer.lex() || 1;\n        if (typeof token !== 'number') {\n          token = self.symbols_[token] || token;\n        }\n        return token;\n      }\n      var symbol,\n        preErrorSymbol,\n        state,\n        action,\n        a,\n        r,\n        yyval = {},\n        p,\n        len,\n        newState,\n        expected;\n      while (true) {\n        state = stack[stack.length - 1];\n        if (this.defaultActions[state]) {\n          action = this.defaultActions[state];\n        } else {\n          if (symbol == null) symbol = lex();\n          action = table[state] && table[state][symbol];\n        }\n        if (typeof action === 'undefined' || !action.length || !action[0]) {\n          if (!recovering) {\n            expected = [];\n            for (p in table[state])\n              if (this.terminals_[p] && p > 2) {\n                expected.push(\"'\" + this.terminals_[p] + \"'\");\n              }\n            var errStr = '';\n            if (this.lexer.showPosition) {\n              errStr =\n                'Parse error on line ' +\n                (yylineno + 1) +\n                ':\\n' +\n                this.lexer.showPosition() +\n                '\\nExpecting ' +\n                expected.join(', ') +\n                \", got '\" +\n                this.terminals_[symbol] +\n                \"'\";\n            } else {\n              errStr =\n                'Parse error on line ' +\n                (yylineno + 1) +\n                ': Unexpected ' +\n                (symbol == 1\n                  ? 'end of input'\n                  : \"'\" + (this.terminals_[symbol] || symbol) + \"'\");\n            }\n            this.parseError(errStr, {\n              text: this.lexer.match,\n              token: this.terminals_[symbol] || symbol,\n              line: this.lexer.yylineno,\n              loc: yyloc,\n              expected: expected\n            });\n          }\n        }\n        if (action[0] instanceof Array && action.length > 1) {\n          throw new Error(\n            'Parse Error: multiple actions possible at state: ' +\n              state +\n              ', token: ' +\n              symbol\n          );\n        }\n        switch (action[0]) {\n          case 1:\n            stack.push(symbol);\n            vstack.push(this.lexer.yytext);\n            lstack.push(this.lexer.yylloc);\n            stack.push(action[1]);\n            symbol = null;\n            if (!preErrorSymbol) {\n              yyleng = this.lexer.yyleng;\n              yytext = this.lexer.yytext;\n              yylineno = this.lexer.yylineno;\n              yyloc = this.lexer.yylloc;\n              if (recovering > 0) recovering--;\n            } else {\n              symbol = preErrorSymbol;\n              preErrorSymbol = null;\n            }\n            break;\n          case 2:\n            len = this.productions_[action[1]][1];\n            yyval.$ = vstack[vstack.length - len];\n            yyval._$ = {\n              first_line: lstack[lstack.length - (len || 1)].first_line,\n              last_line: lstack[lstack.length - 1].last_line,\n              first_column: lstack[lstack.length - (len || 1)].first_column,\n              last_column: lstack[lstack.length - 1].last_column\n            };\n            r = this.performAction.call(\n              yyval,\n              yytext,\n              yyleng,\n              yylineno,\n              this.yy,\n              action[1],\n              vstack,\n              lstack\n            );\n            if (typeof r !== 'undefined') {\n              return r;\n            }\n            if (len) {\n              stack = stack.slice(0, -1 * len * 2);\n              vstack = vstack.slice(0, -1 * len);\n              lstack = lstack.slice(0, -1 * len);\n            }\n            stack.push(this.productions_[action[1]][0]);\n            vstack.push(yyval.$);\n            lstack.push(yyval._$);\n            newState = table[stack[stack.length - 2]][stack[stack.length - 1]];\n            stack.push(newState);\n            break;\n          case 3:\n            return true;\n        }\n      }\n      return true;\n    }\n  }; /* Jison generated lexer */\n  var lexer = (function () {\n    var lexer = {\n      EOF: 1,\n      parseError: function parseError(str, hash) {\n        if (this.yy.parseError) {\n          this.yy.parseError(str, hash);\n        } else {\n          throw new Error(str);\n        }\n      },\n      setInput: function (input) {\n        this._input = input;\n        this._more = this._less = this.done = false;\n        this.yylineno = this.yyleng = 0;\n        this.yytext = this.matched = this.match = '';\n        this.conditionStack = ['INITIAL'];\n        this.yylloc = {\n          first_line: 1,\n          first_column: 0,\n          last_line: 1,\n          last_column: 0\n        };\n        return this;\n      },\n      input: function () {\n        var ch = this._input[0];\n        this.yytext += ch;\n        this.yyleng++;\n        this.match += ch;\n        this.matched += ch;\n        var lines = ch.match(/\\n/);\n        if (lines) this.yylineno++;\n        this._input = this._input.slice(1);\n        return ch;\n      },\n      unput: function (ch) {\n        this._input = ch + this._input;\n        return this;\n      },\n      more: function () {\n        this._more = true;\n        return this;\n      },\n      pastInput: function () {\n        var past = this.matched.substr(\n          0,\n          this.matched.length - this.match.length\n        );\n        return (\n          (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\\n/g, '')\n        );\n      },\n      upcomingInput: function () {\n        var next = this.match;\n        if (next.length < 20) {\n          next += this._input.substr(0, 20 - next.length);\n        }\n        return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(\n          /\\n/g,\n          ''\n        );\n      },\n      showPosition: function () {\n        var pre = this.pastInput();\n        var c = new Array(pre.length + 1).join('-');\n        return pre + this.upcomingInput() + '\\n' + c + '^';\n      },\n      next: function () {\n        if (this.done) {\n          return this.EOF;\n        }\n        if (!this._input) this.done = true;\n\n        var token, match, col, lines;\n        if (!this._more) {\n          this.yytext = '';\n          this.match = '';\n        }\n        var rules = this._currentRules();\n        for (var i = 0; i < rules.length; i++) {\n          match = this._input.match(this.rules[rules[i]]);\n          if (match) {\n            lines = match[0].match(/\\n.*/g);\n            if (lines) this.yylineno += lines.length;\n            this.yylloc = {\n              first_line: this.yylloc.last_line,\n              last_line: this.yylineno + 1,\n              first_column: this.yylloc.last_column,\n              last_column: lines\n                ? lines[lines.length - 1].length - 1\n                : this.yylloc.last_column + match[0].length\n            };\n            this.yytext += match[0];\n            this.match += match[0];\n            this.matches = match;\n            this.yyleng = this.yytext.length;\n            this._more = false;\n            this._input = this._input.slice(match[0].length);\n            this.matched += match[0];\n            token = this.performAction.call(\n              this,\n              this.yy,\n              this,\n              rules[i],\n              this.conditionStack[this.conditionStack.length - 1]\n            );\n            if (token) return token;\n            else return;\n          }\n        }\n        if (this._input === '') {\n          return this.EOF;\n        } else {\n          this.parseError(\n            'Lexical error on line ' +\n              (this.yylineno + 1) +\n              '. Unrecognized text.\\n' +\n              this.showPosition(),\n            { text: '', token: null, line: this.yylineno }\n          );\n        }\n      },\n      lex: function lex() {\n        var r = this.next();\n        if (typeof r !== 'undefined') {\n          return r;\n        } else {\n          return this.lex();\n        }\n      },\n      begin: function begin(condition) {\n        this.conditionStack.push(condition);\n      },\n      popState: function popState() {\n        return this.conditionStack.pop();\n      },\n      _currentRules: function _currentRules() {\n        return this.conditions[\n          this.conditionStack[this.conditionStack.length - 1]\n        ].rules;\n      },\n      topState: function () {\n        return this.conditionStack[this.conditionStack.length - 2];\n      },\n      pushState: function begin(condition) {\n        this.begin(condition);\n      }\n    };\n    lexer.performAction = function anonymous(\n      yy,\n      yy_,\n      $avoiding_name_collisions,\n      YY_START\n    ) {\n      var YYSTATE = YY_START;\n      switch ($avoiding_name_collisions) {\n        case 0:\n          if (yy_.yytext.slice(-1) !== '\\\\') this.begin('mu');\n          if (yy_.yytext.slice(-1) === '\\\\')\n            (yy_.yytext = yy_.yytext.substr(0, yy_.yyleng - 1)),\n              this.begin('emu');\n          if (yy_.yytext) return 14;\n\n          break;\n        case 1:\n          return 14;\n          break;\n        case 2:\n          this.popState();\n          return 14;\n          break;\n        case 3:\n          return 24;\n          break;\n        case 4:\n          return 16;\n          break;\n        case 5:\n          return 20;\n          break;\n        case 6:\n          return 19;\n          break;\n        case 7:\n          return 19;\n          break;\n        case 8:\n          return 23;\n          break;\n        case 9:\n          return 23;\n          break;\n        case 10:\n          yy_.yytext = yy_.yytext.substr(3, yy_.yyleng - 5);\n          this.popState();\n          return 15;\n          break;\n        case 11:\n          return 22;\n          break;\n        case 12:\n          return 34;\n          break;\n        case 13:\n          return 33;\n          break;\n        case 14:\n          return 33;\n          break;\n        case 15:\n          return 36;\n          break;\n        case 16 /*ignore whitespace*/:\n          break;\n        case 17:\n          this.popState();\n          return 18;\n          break;\n        case 18:\n          this.popState();\n          return 18;\n          break;\n        case 19:\n          yy_.yytext = yy_.yytext\n            .substr(1, yy_.yyleng - 2)\n            .replace(/\\\\\"/g, '\"');\n          return 28;\n          break;\n        case 20:\n          return 30;\n          break;\n        case 21:\n          return 30;\n          break;\n        case 22:\n          return 29;\n          break;\n        case 23:\n          return 33;\n          break;\n        case 24:\n          yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2);\n          return 33;\n          break;\n        case 25:\n          return 'INVALID';\n          break;\n        case 26:\n          return 5;\n          break;\n      }\n    };\n    lexer.rules = [\n      /^[^\\x00]*?(?=(\\{\\{))/,\n      /^[^\\x00]+/,\n      /^[^\\x00]{2,}?(?=(\\{\\{))/,\n      /^\\{\\{>/,\n      /^\\{\\{#/,\n      /^\\{\\{\\//,\n      /^\\{\\{\\^/,\n      /^\\{\\{\\s*else\\b/,\n      /^\\{\\{\\{/,\n      /^\\{\\{&/,\n      /^\\{\\{![\\s\\S]*?\\}\\}/,\n      /^\\{\\{/,\n      /^=/,\n      /^\\.(?=[} ])/,\n      /^\\.\\./,\n      /^[\\/.]/,\n      /^\\s+/,\n      /^\\}\\}\\}/,\n      /^\\}\\}/,\n      /^\"(\\\\[\"]|[^\"])*\"/,\n      /^true(?=[}\\s])/,\n      /^false(?=[}\\s])/,\n      /^[0-9]+(?=[}\\s])/,\n      /^[a-zA-Z0-9_$-]+(?=[=}\\s\\/.])/,\n      /^\\[[^\\]]*\\]/,\n      /^./,\n      /^$/\n    ];\n    lexer.conditions = {\n      mu: {\n        rules: [\n          3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,\n          22, 23, 24, 25, 26\n        ],\n        inclusive: false\n      },\n      emu: { rules: [2], inclusive: false },\n      INITIAL: { rules: [0, 1, 26], inclusive: true }\n    };\n    return lexer;\n  })();\n  parser.lexer = lexer;\n  return parser;\n})();\nif (typeof require !== 'undefined' && typeof exports !== 'undefined') {\n  exports.parser = handlebars;\n  exports.parse = function () {\n    return handlebars.parse.apply(handlebars, arguments);\n  };\n  exports.main = function commonjsMain(args) {\n    if (!args[1]) throw new Error('Usage: ' + args[0] + ' FILE');\n    if (typeof process !== 'undefined') {\n      var source = require('fs').readFileSync(\n        require('path').join(process.cwd(), args[1]),\n        'utf8'\n      );\n    } else {\n      var cwd = require('file').path(require('file').cwd());\n      var source = cwd.join(args[1]).read({ charset: 'utf-8' });\n    }\n    return exports.parser.parse(source);\n  };\n  if (typeof module !== 'undefined' && require.main === module) {\n    exports.main(\n      typeof process !== 'undefined'\n        ? process.argv.slice(1)\n        : require('system').args\n    );\n  }\n}\n// lib/handlebars/compiler/base.js\nHandlebars.Parser = handlebars;\n\nHandlebars.parse = function (string) {\n  Handlebars.Parser.yy = Handlebars.AST;\n  return Handlebars.Parser.parse(string);\n};\n\nHandlebars.print = function (ast) {\n  return new Handlebars.PrintVisitor().accept(ast);\n};\n\nHandlebars.logger = {\n  DEBUG: 0,\n  INFO: 1,\n  WARN: 2,\n  ERROR: 3,\n  level: 3,\n\n  // override in the host environment\n  log: function (level, str) {}\n};\n\nHandlebars.log = function (level, str) {\n  Handlebars.logger.log(level, str);\n};\n// lib/handlebars/compiler/ast.js\n(function () {\n  Handlebars.AST = {};\n\n  Handlebars.AST.ProgramNode = function (statements, inverse) {\n    this.type = 'program';\n    this.statements = statements;\n    if (inverse) {\n      this.inverse = new Handlebars.AST.ProgramNode(inverse);\n    }\n  };\n\n  Handlebars.AST.MustacheNode = function (params, hash, unescaped) {\n    this.type = 'mustache';\n    this.id = params[0];\n    this.params = params.slice(1);\n    this.hash = hash;\n    this.escaped = !unescaped;\n  };\n\n  Handlebars.AST.PartialNode = function (id, context) {\n    this.type = 'partial';\n\n    // TODO: disallow complex IDs\n\n    this.id = id;\n    this.context = context;\n  };\n\n  var verifyMatch = function (open, close) {\n    if (open.original !== close.original) {\n      throw new Handlebars.Exception(\n        open.original + \" doesn't match \" + close.original\n      );\n    }\n  };\n\n  Handlebars.AST.BlockNode = function (mustache, program, close) {\n    verifyMatch(mustache.id, close);\n    this.type = 'block';\n    this.mustache = mustache;\n    this.program = program;\n  };\n\n  Handlebars.AST.InverseNode = function (mustache, program, close) {\n    verifyMatch(mustache.id, close);\n    this.type = 'inverse';\n    this.mustache = mustache;\n    this.program = program;\n  };\n\n  Handlebars.AST.ContentNode = function (string) {\n    this.type = 'content';\n    this.string = string;\n  };\n\n  Handlebars.AST.HashNode = function (pairs) {\n    this.type = 'hash';\n    this.pairs = pairs;\n  };\n\n  Handlebars.AST.IdNode = function (parts) {\n    this.type = 'ID';\n    this.original = parts.join('.');\n\n    var dig = [],\n      depth = 0;\n\n    for (var i = 0, l = parts.length; i < l; i++) {\n      var part = parts[i];\n\n      if (part === '..') {\n        depth++;\n      } else if (part === '.' || part === 'this') {\n        this.isScoped = true;\n      } else {\n        dig.push(part);\n      }\n    }\n\n    this.parts = dig;\n    this.string = dig.join('.');\n    this.depth = depth;\n    this.isSimple = dig.length === 1 && depth === 0;\n  };\n\n  Handlebars.AST.StringNode = function (string) {\n    this.type = 'STRING';\n    this.string = string;\n  };\n\n  Handlebars.AST.IntegerNode = function (integer) {\n    this.type = 'INTEGER';\n    this.integer = integer;\n  };\n\n  Handlebars.AST.BooleanNode = function (bool) {\n    this.type = 'BOOLEAN';\n    this.bool = bool;\n  };\n\n  Handlebars.AST.CommentNode = function (comment) {\n    this.type = 'comment';\n    this.comment = comment;\n  };\n})();\n// lib/handlebars/utils.js\nHandlebars.Exception = function (message) {\n  var tmp = Error.prototype.constructor.apply(this, arguments);\n\n  for (var p in tmp) {\n    if (tmp.hasOwnProperty(p)) {\n      this[p] = tmp[p];\n    }\n  }\n\n  this.message = tmp.message;\n};\nHandlebars.Exception.prototype = new Error();\n\n// Build out our basic SafeString type\nHandlebars.SafeString = function (string) {\n  this.string = string;\n};\nHandlebars.SafeString.prototype.toString = function () {\n  return this.string.toString();\n};\n\n(function () {\n  var escape = {\n    '<': '&lt;',\n    '>': '&gt;',\n    '\"': '&quot;',\n    \"'\": '&#x27;',\n    '`': '&#x60;'\n  };\n\n  var badChars = /&(?!\\w+;)|[<>\"'`]/g;\n  var possible = /[&<>\"'`]/;\n\n  var escapeChar = function (chr) {\n    return escape[chr] || '&amp;';\n  };\n\n  Handlebars.Utils = {\n    escapeExpression: function (string) {\n      // don't escape SafeStrings, since they're already safe\n      if (string instanceof Handlebars.SafeString) {\n        return string.toString();\n      } else if (string == null || string === false) {\n        return '';\n      }\n\n      if (!possible.test(string)) {\n        return string;\n      }\n      return string.replace(badChars, escapeChar);\n    },\n\n    isEmpty: function (value) {\n      if (typeof value === 'undefined') {\n        return true;\n      } else if (value === null) {\n        return true;\n      } else if (value === false) {\n        return true;\n      } else if (\n        Object.prototype.toString.call(value) === '[object Array]' &&\n        value.length === 0\n      ) {\n        return true;\n      } else {\n        return false;\n      }\n    }\n  };\n})();\n// lib/handlebars/compiler/compiler.js\nHandlebars.Compiler = function () {};\nHandlebars.JavaScriptCompiler = function () {};\n\n(function (Compiler, JavaScriptCompiler) {\n  Compiler.OPCODE_MAP = {\n    appendContent: 1,\n    getContext: 2,\n    lookupWithHelpers: 3,\n    lookup: 4,\n    append: 5,\n    invokeMustache: 6,\n    appendEscaped: 7,\n    pushString: 8,\n    truthyOrFallback: 9,\n    functionOrFallback: 10,\n    invokeProgram: 11,\n    invokePartial: 12,\n    push: 13,\n    assignToHash: 15,\n    pushStringParam: 16\n  };\n\n  Compiler.MULTI_PARAM_OPCODES = {\n    appendContent: 1,\n    getContext: 1,\n    lookupWithHelpers: 2,\n    lookup: 1,\n    invokeMustache: 3,\n    pushString: 1,\n    truthyOrFallback: 1,\n    functionOrFallback: 1,\n    invokeProgram: 3,\n    invokePartial: 1,\n    push: 1,\n    assignToHash: 1,\n    pushStringParam: 1\n  };\n\n  Compiler.DISASSEMBLE_MAP = {};\n\n  for (var prop in Compiler.OPCODE_MAP) {\n    var value = Compiler.OPCODE_MAP[prop];\n    Compiler.DISASSEMBLE_MAP[value] = prop;\n  }\n\n  Compiler.multiParamSize = function (code) {\n    return Compiler.MULTI_PARAM_OPCODES[Compiler.DISASSEMBLE_MAP[code]];\n  };\n\n  Compiler.prototype = {\n    compiler: Compiler,\n\n    disassemble: function () {\n      var opcodes = this.opcodes,\n        opcode,\n        nextCode;\n      var out = [],\n        str,\n        name,\n        value;\n\n      for (var i = 0, l = opcodes.length; i < l; i++) {\n        opcode = opcodes[i];\n\n        if (opcode === 'DECLARE') {\n          name = opcodes[++i];\n          value = opcodes[++i];\n          out.push('DECLARE ' + name + ' = ' + value);\n        } else {\n          str = Compiler.DISASSEMBLE_MAP[opcode];\n\n          var extraParams = Compiler.multiParamSize(opcode);\n          var codes = [];\n\n          for (var j = 0; j < extraParams; j++) {\n            nextCode = opcodes[++i];\n\n            if (typeof nextCode === 'string') {\n              nextCode = '\"' + nextCode.replace('\\n', '\\\\n') + '\"';\n            }\n\n            codes.push(nextCode);\n          }\n\n          str = str + ' ' + codes.join(' ');\n\n          out.push(str);\n        }\n      }\n\n      return out.join('\\n');\n    },\n\n    guid: 0,\n\n    compile: function (program, options) {\n      this.children = [];\n      this.depths = { list: [] };\n      this.options = options;\n\n      // These changes will propagate to the other compiler components\n      var knownHelpers = this.options.knownHelpers;\n      this.options.knownHelpers = {\n        helperMissing: true,\n        blockHelperMissing: true,\n        each: true,\n        if: true,\n        unless: true,\n        with: true,\n        log: true\n      };\n      if (knownHelpers) {\n        for (var name in knownHelpers) {\n          this.options.knownHelpers[name] = knownHelpers[name];\n        }\n      }\n\n      return this.program(program);\n    },\n\n    accept: function (node) {\n      return this[node.type](node);\n    },\n\n    program: function (program) {\n      var statements = program.statements,\n        statement;\n      this.opcodes = [];\n\n      for (var i = 0, l = statements.length; i < l; i++) {\n        statement = statements[i];\n        this[statement.type](statement);\n      }\n      this.isSimple = l === 1;\n\n      this.depths.list = this.depths.list.sort(function (a, b) {\n        return a - b;\n      });\n\n      return this;\n    },\n\n    compileProgram: function (program) {\n      var result = new this.compiler().compile(program, this.options);\n      var guid = this.guid++;\n\n      this.usePartial = this.usePartial || result.usePartial;\n\n      this.children[guid] = result;\n\n      for (var i = 0, l = result.depths.list.length; i < l; i++) {\n        depth = result.depths.list[i];\n\n        if (depth < 2) {\n          continue;\n        } else {\n          this.addDepth(depth - 1);\n        }\n      }\n\n      return guid;\n    },\n\n    block: function (block) {\n      var mustache = block.mustache;\n      var depth, child, inverse, inverseGuid;\n\n      var params = this.setupStackForMustache(mustache);\n\n      var programGuid = this.compileProgram(block.program);\n\n      if (block.program.inverse) {\n        inverseGuid = this.compileProgram(block.program.inverse);\n        this.declare('inverse', inverseGuid);\n      }\n\n      this.opcode('invokeProgram', programGuid, params.length, !!mustache.hash);\n      this.declare('inverse', null);\n      this.opcode('append');\n    },\n\n    inverse: function (block) {\n      var params = this.setupStackForMustache(block.mustache);\n\n      var programGuid = this.compileProgram(block.program);\n\n      this.declare('inverse', programGuid);\n\n      this.opcode('invokeProgram', null, params.length, !!block.mustache.hash);\n      this.declare('inverse', null);\n      this.opcode('append');\n    },\n\n    hash: function (hash) {\n      var pairs = hash.pairs,\n        pair,\n        val;\n\n      this.opcode('push', '{}');\n\n      for (var i = 0, l = pairs.length; i < l; i++) {\n        pair = pairs[i];\n        val = pair[1];\n\n        this.accept(val);\n        this.opcode('assignToHash', pair[0]);\n      }\n    },\n\n    partial: function (partial) {\n      var id = partial.id;\n      this.usePartial = true;\n\n      if (partial.context) {\n        this.ID(partial.context);\n      } else {\n        this.opcode('push', 'depth0');\n      }\n\n      this.opcode('invokePartial', id.original);\n      this.opcode('append');\n    },\n\n    content: function (content) {\n      this.opcode('appendContent', content.string);\n    },\n\n    mustache: function (mustache) {\n      var params = this.setupStackForMustache(mustache);\n\n      this.opcode(\n        'invokeMustache',\n        params.length,\n        mustache.id.original,\n        !!mustache.hash\n      );\n\n      if (mustache.escaped && !this.options.noEscape) {\n        this.opcode('appendEscaped');\n      } else {\n        this.opcode('append');\n      }\n    },\n\n    ID: function (id) {\n      this.addDepth(id.depth);\n\n      this.opcode('getContext', id.depth);\n\n      this.opcode(\n        'lookupWithHelpers',\n        id.parts[0] || null,\n        id.isScoped || false\n      );\n\n      for (var i = 1, l = id.parts.length; i < l; i++) {\n        this.opcode('lookup', id.parts[i]);\n      }\n    },\n\n    STRING: function (string) {\n      this.opcode('pushString', string.string);\n    },\n\n    INTEGER: function (integer) {\n      this.opcode('push', integer.integer);\n    },\n\n    BOOLEAN: function (bool) {\n      this.opcode('push', bool.bool);\n    },\n\n    comment: function () {},\n\n    // HELPERS\n    pushParams: function (params) {\n      var i = params.length,\n        param;\n\n      while (i--) {\n        param = params[i];\n\n        if (this.options.stringParams) {\n          if (param.depth) {\n            this.addDepth(param.depth);\n          }\n\n          this.opcode('getContext', param.depth || 0);\n          this.opcode('pushStringParam', param.string);\n        } else {\n          this[param.type](param);\n        }\n      }\n    },\n\n    opcode: function (name, val1, val2, val3) {\n      this.opcodes.push(Compiler.OPCODE_MAP[name]);\n      if (val1 !== undefined) {\n        this.opcodes.push(val1);\n      }\n      if (val2 !== undefined) {\n        this.opcodes.push(val2);\n      }\n      if (val3 !== undefined) {\n        this.opcodes.push(val3);\n      }\n    },\n\n    declare: function (name, value) {\n      this.opcodes.push('DECLARE');\n      this.opcodes.push(name);\n      this.opcodes.push(value);\n    },\n\n    addDepth: function (depth) {\n      if (depth === 0) {\n        return;\n      }\n\n      if (!this.depths[depth]) {\n        this.depths[depth] = true;\n        this.depths.list.push(depth);\n      }\n    },\n\n    setupStackForMustache: function (mustache) {\n      var params = mustache.params;\n\n      this.pushParams(params);\n\n      if (mustache.hash) {\n        this.hash(mustache.hash);\n      }\n\n      this.ID(mustache.id);\n\n      return params;\n    }\n  };\n\n  JavaScriptCompiler.prototype = {\n    // PUBLIC API: You can override these methods in a subclass to provide\n    // alternative compiled forms for name lookup and buffering semantics\n    nameLookup: function (parent, name, type) {\n      if (/^[0-9]+$/.test(name)) {\n        return parent + '[' + name + ']';\n      } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {\n        return parent + '.' + name;\n      } else {\n        return parent + \"['\" + name + \"']\";\n      }\n    },\n\n    appendToBuffer: function (string) {\n      if (this.environment.isSimple) {\n        return 'return ' + string + ';';\n      } else {\n        return 'buffer += ' + string + ';';\n      }\n    },\n\n    initializeBuffer: function () {\n      return this.quotedString('');\n    },\n\n    namespace: 'Handlebars',\n    // END PUBLIC API\n\n    compile: function (environment, options, context, asObject) {\n      this.environment = environment;\n      this.options = options || {};\n\n      this.name = this.environment.name;\n      this.isChild = !!context;\n      this.context = context || {\n        programs: [],\n        aliases: { self: 'this' },\n        registers: { list: [] }\n      };\n\n      this.preamble();\n\n      this.stackSlot = 0;\n      this.stackVars = [];\n\n      this.compileChildren(environment, options);\n\n      var opcodes = environment.opcodes,\n        opcode;\n\n      this.i = 0;\n\n      for (l = opcodes.length; this.i < l; this.i++) {\n        opcode = this.nextOpcode(0);\n\n        if (opcode[0] === 'DECLARE') {\n          this.i = this.i + 2;\n          this[opcode[1]] = opcode[2];\n        } else {\n          this.i = this.i + opcode[1].length;\n          this[opcode[0]].apply(this, opcode[1]);\n        }\n      }\n\n      return this.createFunctionContext(asObject);\n    },\n\n    nextOpcode: function (n) {\n      var opcodes = this.environment.opcodes,\n        opcode = opcodes[this.i + n],\n        name,\n        val;\n      var extraParams, codes;\n\n      if (opcode === 'DECLARE') {\n        name = opcodes[this.i + 1];\n        val = opcodes[this.i + 2];\n        return ['DECLARE', name, val];\n      } else {\n        name = Compiler.DISASSEMBLE_MAP[opcode];\n\n        extraParams = Compiler.multiParamSize(opcode);\n        codes = [];\n\n        for (var j = 0; j < extraParams; j++) {\n          codes.push(opcodes[this.i + j + 1 + n]);\n        }\n\n        return [name, codes];\n      }\n    },\n\n    eat: function (opcode) {\n      this.i = this.i + opcode.length;\n    },\n\n    preamble: function () {\n      var out = [];\n\n      // this register will disambiguate helper lookup from finding a function in\n      // a context. This is necessary for mustache compatibility, which requires\n      // that context functions in blocks are evaluated by blockHelperMissing, and\n      // then proceed as if the resulting value was provided to blockHelperMissing.\n      this.useRegister('foundHelper');\n\n      if (!this.isChild) {\n        var namespace = this.namespace;\n        var copies = 'helpers = helpers || ' + namespace + '.helpers;';\n        if (this.environment.usePartial) {\n          copies =\n            copies + ' partials = partials || ' + namespace + '.partials;';\n        }\n        out.push(copies);\n      } else {\n        out.push('');\n      }\n\n      if (!this.environment.isSimple) {\n        out.push(', buffer = ' + this.initializeBuffer());\n      } else {\n        out.push('');\n      }\n\n      // track the last context pushed into place to allow skipping the\n      // getContext opcode when it would be a noop\n      this.lastContext = 0;\n      this.source = out;\n    },\n\n    createFunctionContext: function (asObject) {\n      var locals = this.stackVars;\n      if (!this.isChild) {\n        locals = locals.concat(this.context.registers.list);\n      }\n\n      if (locals.length > 0) {\n        this.source[1] = this.source[1] + ', ' + locals.join(', ');\n      }\n\n      // Generate minimizer alias mappings\n      if (!this.isChild) {\n        var aliases = [];\n        for (var alias in this.context.aliases) {\n          this.source[1] =\n            this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];\n        }\n      }\n\n      if (this.source[1]) {\n        this.source[1] = 'var ' + this.source[1].substring(2) + ';';\n      }\n\n      // Merge children\n      if (!this.isChild) {\n        this.source[1] += '\\n' + this.context.programs.join('\\n') + '\\n';\n      }\n\n      if (!this.environment.isSimple) {\n        this.source.push('return buffer;');\n      }\n\n      var params = this.isChild\n        ? ['depth0', 'data']\n        : ['Handlebars', 'depth0', 'helpers', 'partials', 'data'];\n\n      for (var i = 0, l = this.environment.depths.list.length; i < l; i++) {\n        params.push('depth' + this.environment.depths.list[i]);\n      }\n\n      if (asObject) {\n        params.push(this.source.join('\\n  '));\n\n        return Function.apply(this, params);\n      } else {\n        var functionSource =\n          'function ' +\n          (this.name || '') +\n          '(' +\n          params.join(',') +\n          ') {\\n  ' +\n          this.source.join('\\n  ') +\n          '}';\n        Handlebars.log(Handlebars.logger.DEBUG, functionSource + '\\n\\n');\n        return functionSource;\n      }\n    },\n\n    appendContent: function (content) {\n      this.source.push(this.appendToBuffer(this.quotedString(content)));\n    },\n\n    append: function () {\n      var local = this.popStack();\n      this.source.push(\n        'if(' +\n          local +\n          ' || ' +\n          local +\n          ' === 0) { ' +\n          this.appendToBuffer(local) +\n          ' }'\n      );\n      if (this.environment.isSimple) {\n        this.source.push('else { ' + this.appendToBuffer(\"''\") + ' }');\n      }\n    },\n\n    appendEscaped: function () {\n      var opcode = this.nextOpcode(1),\n        extra = '';\n      this.context.aliases.escapeExpression = 'this.escapeExpression';\n\n      if (opcode[0] === 'appendContent') {\n        extra = ' + ' + this.quotedString(opcode[1][0]);\n        this.eat(opcode);\n      }\n\n      this.source.push(\n        this.appendToBuffer('escapeExpression(' + this.popStack() + ')' + extra)\n      );\n    },\n\n    getContext: function (depth) {\n      if (this.lastContext !== depth) {\n        this.lastContext = depth;\n      }\n    },\n\n    lookupWithHelpers: function (name, isScoped) {\n      if (name) {\n        var topStack = this.nextStack();\n\n        this.usingKnownHelper = false;\n\n        var toPush;\n        if (!isScoped && this.options.knownHelpers[name]) {\n          toPush =\n            topStack + ' = ' + this.nameLookup('helpers', name, 'helper');\n          this.usingKnownHelper = true;\n        } else if (isScoped || this.options.knownHelpersOnly) {\n          toPush =\n            topStack +\n            ' = ' +\n            this.nameLookup('depth' + this.lastContext, name, 'context');\n        } else {\n          this.register(\n            'foundHelper',\n            this.nameLookup('helpers', name, 'helper')\n          );\n          toPush =\n            topStack +\n            ' = foundHelper || ' +\n            this.nameLookup('depth' + this.lastContext, name, 'context');\n        }\n\n        toPush += ';';\n        this.source.push(toPush);\n      } else {\n        this.pushStack('depth' + this.lastContext);\n      }\n    },\n\n    lookup: function (name) {\n      var topStack = this.topStack();\n      this.source.push(\n        topStack +\n          ' = (' +\n          topStack +\n          ' === null || ' +\n          topStack +\n          ' === undefined || ' +\n          topStack +\n          ' === false ? ' +\n          topStack +\n          ' : ' +\n          this.nameLookup(topStack, name, 'context') +\n          ');'\n      );\n    },\n\n    pushStringParam: function (string) {\n      this.pushStack('depth' + this.lastContext);\n      this.pushString(string);\n    },\n\n    pushString: function (string) {\n      this.pushStack(this.quotedString(string));\n    },\n\n    push: function (name) {\n      this.pushStack(name);\n    },\n\n    invokeMustache: function (paramSize, original, hasHash) {\n      this.populateParams(\n        paramSize,\n        this.quotedString(original),\n        '{}',\n        null,\n        hasHash,\n        function (nextStack, helperMissingString, id) {\n          if (!this.usingKnownHelper) {\n            this.context.aliases.helperMissing = 'helpers.helperMissing';\n            this.context.aliases.undef = 'void 0';\n            this.source.push(\n              'else if(' +\n                id +\n                '=== undef) { ' +\n                nextStack +\n                ' = helperMissing.call(' +\n                helperMissingString +\n                '); }'\n            );\n            if (nextStack !== id) {\n              this.source.push('else { ' + nextStack + ' = ' + id + '; }');\n            }\n          }\n        }\n      );\n    },\n\n    invokeProgram: function (guid, paramSize, hasHash) {\n      var inverse = this.programExpression(this.inverse);\n      var mainProgram = this.programExpression(guid);\n\n      this.populateParams(\n        paramSize,\n        null,\n        mainProgram,\n        inverse,\n        hasHash,\n        function (nextStack, helperMissingString, id) {\n          if (!this.usingKnownHelper) {\n            this.context.aliases.blockHelperMissing =\n              'helpers.blockHelperMissing';\n            this.source.push(\n              'else { ' +\n                nextStack +\n                ' = blockHelperMissing.call(' +\n                helperMissingString +\n                '); }'\n            );\n          }\n        }\n      );\n    },\n\n    populateParams: function (\n      paramSize,\n      helperId,\n      program,\n      inverse,\n      hasHash,\n      fn\n    ) {\n      var needsRegister =\n        hasHash || this.options.stringParams || inverse || this.options.data;\n      var id = this.popStack(),\n        nextStack;\n      var params = [],\n        param,\n        stringParam,\n        stringOptions;\n\n      if (needsRegister) {\n        this.register('tmp1', program);\n        stringOptions = 'tmp1';\n      } else {\n        stringOptions = '{ hash: {} }';\n      }\n\n      if (needsRegister) {\n        var hash = hasHash ? this.popStack() : '{}';\n        this.source.push('tmp1.hash = ' + hash + ';');\n      }\n\n      if (this.options.stringParams) {\n        this.source.push('tmp1.contexts = [];');\n      }\n\n      for (var i = 0; i < paramSize; i++) {\n        param = this.popStack();\n        params.push(param);\n\n        if (this.options.stringParams) {\n          this.source.push('tmp1.contexts.push(' + this.popStack() + ');');\n        }\n      }\n\n      if (inverse) {\n        this.source.push('tmp1.fn = tmp1;');\n        this.source.push('tmp1.inverse = ' + inverse + ';');\n      }\n\n      if (this.options.data) {\n        this.source.push('tmp1.data = data;');\n      }\n\n      params.push(stringOptions);\n\n      this.populateCall(params, id, helperId || id, fn, program !== '{}');\n    },\n\n    populateCall: function (params, id, helperId, fn, program) {\n      var paramString = ['depth0'].concat(params).join(', ');\n      var helperMissingString = ['depth0']\n        .concat(helperId)\n        .concat(params)\n        .join(', ');\n\n      var nextStack = this.nextStack();\n\n      if (this.usingKnownHelper) {\n        this.source.push(\n          nextStack + ' = ' + id + '.call(' + paramString + ');'\n        );\n      } else {\n        this.context.aliases.functionType = '\"function\"';\n        var condition = program ? 'foundHelper && ' : '';\n        this.source.push(\n          'if(' +\n            condition +\n            'typeof ' +\n            id +\n            ' === functionType) { ' +\n            nextStack +\n            ' = ' +\n            id +\n            '.call(' +\n            paramString +\n            '); }'\n        );\n      }\n      fn.call(this, nextStack, helperMissingString, id);\n      this.usingKnownHelper = false;\n    },\n\n    invokePartial: function (context) {\n      params = [\n        this.nameLookup('partials', context, 'partial'),\n        \"'\" + context + \"'\",\n        this.popStack(),\n        'helpers',\n        'partials'\n      ];\n\n      if (this.options.data) {\n        params.push('data');\n      }\n\n      this.pushStack('self.invokePartial(' + params.join(', ') + ');');\n    },\n\n    assignToHash: function (key) {\n      var value = this.popStack();\n      var hash = this.topStack();\n\n      this.source.push(hash + \"['\" + key + \"'] = \" + value + ';');\n    },\n\n    // HELPERS\n\n    compiler: JavaScriptCompiler,\n\n    compileChildren: function (environment, options) {\n      var children = environment.children,\n        child,\n        compiler;\n\n      for (var i = 0, l = children.length; i < l; i++) {\n        child = children[i];\n        compiler = new this.compiler();\n\n        this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children\n        var index = this.context.programs.length;\n        child.index = index;\n        child.name = 'program' + index;\n        this.context.programs[index] = compiler.compile(\n          child,\n          options,\n          this.context\n        );\n      }\n    },\n\n    programExpression: function (guid) {\n      if (guid == null) {\n        return 'self.noop';\n      }\n\n      var child = this.environment.children[guid],\n        depths = child.depths.list;\n      var programParams = [child.index, child.name, 'data'];\n\n      for (var i = 0, l = depths.length; i < l; i++) {\n        depth = depths[i];\n\n        if (depth === 1) {\n          programParams.push('depth0');\n        } else {\n          programParams.push('depth' + (depth - 1));\n        }\n      }\n\n      if (depths.length === 0) {\n        return 'self.program(' + programParams.join(', ') + ')';\n      } else {\n        programParams.shift();\n        return 'self.programWithDepth(' + programParams.join(', ') + ')';\n      }\n    },\n\n    register: function (name, val) {\n      this.useRegister(name);\n      this.source.push(name + ' = ' + val + ';');\n    },\n\n    useRegister: function (name) {\n      if (!this.context.registers[name]) {\n        this.context.registers[name] = true;\n        this.context.registers.list.push(name);\n      }\n    },\n\n    pushStack: function (item) {\n      this.source.push(this.nextStack() + ' = ' + item + ';');\n      return 'stack' + this.stackSlot;\n    },\n\n    nextStack: function () {\n      this.stackSlot++;\n      if (this.stackSlot > this.stackVars.length) {\n        this.stackVars.push('stack' + this.stackSlot);\n      }\n      return 'stack' + this.stackSlot;\n    },\n\n    popStack: function () {\n      return 'stack' + this.stackSlot--;\n    },\n\n    topStack: function () {\n      return 'stack' + this.stackSlot;\n    },\n\n    quotedString: function (str) {\n      return (\n        '\"' +\n        str\n          .replace(/\\\\/g, '\\\\\\\\')\n          .replace(/\"/g, '\\\\\"')\n          .replace(/\\n/g, '\\\\n')\n          .replace(/\\r/g, '\\\\r') +\n        '\"'\n      );\n    }\n  };\n\n  var reservedWords = (\n    'break else new var' +\n    ' case finally return void' +\n    ' catch for switch while' +\n    ' continue function this with' +\n    ' default if throw' +\n    ' delete in try' +\n    ' do instanceof typeof' +\n    ' abstract enum int short' +\n    ' boolean export interface static' +\n    ' byte extends long super' +\n    ' char final native synchronized' +\n    ' class float package throws' +\n    ' const goto private transient' +\n    ' debugger implements protected volatile' +\n    ' double import public let yield'\n  ).split(' ');\n\n  var compilerWords = (JavaScriptCompiler.RESERVED_WORDS = {});\n\n  for (var i = 0, l = reservedWords.length; i < l; i++) {\n    compilerWords[reservedWords[i]] = true;\n  }\n\n  JavaScriptCompiler.isValidJavaScriptVariableName = function (name) {\n    if (\n      !JavaScriptCompiler.RESERVED_WORDS[name] &&\n      /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)\n    ) {\n      return true;\n    }\n    return false;\n  };\n})(Handlebars.Compiler, Handlebars.JavaScriptCompiler);\n\nHandlebars.precompile = function (string, options) {\n  options = options || {};\n\n  var ast = Handlebars.parse(string);\n  var environment = new Handlebars.Compiler().compile(ast, options);\n  return new Handlebars.JavaScriptCompiler().compile(environment, options);\n};\n\nHandlebars.compile = function (string, options) {\n  options = options || {};\n\n  var compiled;\n  function compile() {\n    var ast = Handlebars.parse(string);\n    var environment = new Handlebars.Compiler().compile(ast, options);\n    var templateSpec = new Handlebars.JavaScriptCompiler().compile(\n      environment,\n      options,\n      undefined,\n      true\n    );\n    return Handlebars.template(templateSpec);\n  }\n\n  // Template is only compiled on first use and cached after that point.\n  return function (context, options) {\n    if (!compiled) {\n      compiled = compile();\n    }\n    return compiled.call(this, context, options);\n  };\n};\n// lib/handlebars/runtime.js\nHandlebars.VM = {\n  template: function (templateSpec) {\n    // Just add water\n    var container = {\n      escapeExpression: Handlebars.Utils.escapeExpression,\n      invokePartial: Handlebars.VM.invokePartial,\n      programs: [],\n      program: function (i, fn, data) {\n        var programWrapper = this.programs[i];\n        if (data) {\n          return Handlebars.VM.program(fn, data);\n        } else if (programWrapper) {\n          return programWrapper;\n        } else {\n          programWrapper = this.programs[i] = Handlebars.VM.program(fn);\n          return programWrapper;\n        }\n      },\n      programWithDepth: Handlebars.VM.programWithDepth,\n      noop: Handlebars.VM.noop\n    };\n\n    return function (context, options) {\n      options = options || {};\n      return templateSpec.call(\n        container,\n        Handlebars,\n        context,\n        options.helpers,\n        options.partials,\n        options.data\n      );\n    };\n  },\n\n  programWithDepth: function (fn, data, $depth) {\n    var args = Array.prototype.slice.call(arguments, 2);\n\n    return function (context, options) {\n      options = options || {};\n\n      return fn.apply(this, [context, options.data || data].concat(args));\n    };\n  },\n  program: function (fn, data) {\n    return function (context, options) {\n      options = options || {};\n\n      return fn(context, options.data || data);\n    };\n  },\n  noop: function () {\n    return '';\n  },\n  invokePartial: function (partial, name, context, helpers, partials, data) {\n    options = { helpers: helpers, partials: partials, data: data };\n\n    if (partial === undefined) {\n      throw new Handlebars.Exception(\n        'The partial ' + name + ' could not be found'\n      );\n    } else if (partial instanceof Function) {\n      return partial(context, options);\n    } else if (!Handlebars.compile) {\n      throw new Handlebars.Exception(\n        'The partial ' +\n          name +\n          ' could not be compiled when running in runtime-only mode'\n      );\n    } else {\n      partials[name] = Handlebars.compile(partial);\n      return partials[name](context, options);\n    }\n  }\n};\n\nHandlebars.template = Handlebars.VM.template;\n"
  },
  {
    "path": "api-samples/sandbox/sandbox/mainpage.html",
    "content": "<!--\n Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n<!doctype html>\n<html>\n  <head>\n    <script src=\"mainpage.js\"></script>\n    <link href=\"styles/main.css\" rel=\"stylesheet\" />\n  </head>\n  <body>\n    <div id=\"buttons\">\n      <button id=\"sendMessage\">Click me</button>\n      <button id=\"reset\">Reset counter</button>\n    </div>\n\n    <div id=\"result\"></div>\n\n    <iframe id=\"theFrame\" src=\"sandbox.html\" style=\"display: none\"></iframe>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/sandbox/sandbox/mainpage.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nlet counter = 0;\ndocument.addEventListener('DOMContentLoaded', () => {\n  document.getElementById('reset').addEventListener('click', function () {\n    counter = 0;\n    document.querySelector('#result').innerHTML = '';\n  });\n\n  document.getElementById('sendMessage').addEventListener('click', function () {\n    counter++;\n    let message = {\n      command: 'render',\n      templateName: 'sample-template-' + counter,\n      context: { counter: counter }\n    };\n    document.getElementById('theFrame').contentWindow.postMessage(message, '*');\n  });\n\n  // on result from sandboxed frame:\n  window.addEventListener('message', function () {\n    document.querySelector('#result').innerHTML =\n      event.data.result || 'invalid result';\n  });\n});\n"
  },
  {
    "path": "api-samples/sandbox/sandbox/manifest.json",
    "content": "{\n  \"name\": \"Sandboxed Frame Sample\",\n  \"version\": \"1.0.3\",\n  \"description\": \"Demonstrates creation of a tab with a sandboxed iframe to which the main page passes a counter variable.\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"icons\": {\n    \"128\": \"icon_128.png\"\n  },\n  \"sandbox\": {\n    \"pages\": [\"sandbox.html\"]\n  },\n  \"action\": {}\n}\n"
  },
  {
    "path": "api-samples/sandbox/sandbox/sandbox.html",
    "content": "<!--\nCopyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n<!doctype html>\n<html>\n  <head>\n    <script src=\"handlebars-1.0.0.beta.6.js\"></script>\n  </head>\n  <body>\n    <script id=\"sample-template-1\" type=\"text/x-handlebars-template\">\n      <div class='entry'>\n        <h1>Hello</h1>\n        <p>This is a Handlebar template compiled inside a hidden sandboxed\n          iframe.</p>\n        <p>The counter parameter from postMessage() (outer frame) is:\n          {{counter}}</p>\n      </div>\n    </script>\n\n    <script id=\"sample-template-2\" type=\"text/x-handlebars-template\">\n      <div class='entry'>\n        <h1>Welcome back</h1>\n        <p>This is another Handlebar template compiled inside a hidden sandboxed\n          iframe.</p>\n        <p>The counter parameter from postMessage() (outer frame) is:\n          {{counter}}</p>\n      </div>\n    </script>\n\n    <script>\n      const templatesElements = document.querySelectorAll(\n        \"script[type='text/x-handlebars-template']\"\n      );\n      let templates = {},\n        source,\n        name;\n\n      // precompile all templates in this page\n      for (let i = 0; i < templatesElements.length; i++) {\n        source = templatesElements[i].innerHTML;\n        name = templatesElements[i].id;\n        templates[name] = Handlebars.compile(source);\n      }\n\n      // Set up message event handler:\n      window.addEventListener('message', function (event) {\n        const command = event.data.command;\n        const template = templates[event.data.templateName];\n        let result = 'invalid request';\n\n        // if we don't know the templateName requested, return an error message\n        if (template) {\n          switch (command) {\n            case 'render':\n              result = template(event.data.context);\n              break;\n            // you could even do dynamic compilation, by accepting a command\n            // to compile a new template instead of using static ones, for example:\n            // case 'new':\n            //   template = Handlebars.compile(event.data.templateSource);\n            //   result = template(event.data.context);\n            //   break;\n          }\n        } else {\n          result = 'Unknown template: ' + event.data.templateName;\n        }\n        event.source.postMessage({ result: result }, event.origin);\n      });\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/sandbox/sandbox/sandbox.md",
    "content": "# Sandbox\n\nThis sample creates a tab with a sandboxed iframe (`sandbox.html`) to which the main page (`mainpage.html`)\npasses a counter variable. The sandboxed page uses the\nHandlebars template library to evaluate and compose a message\nusing the counter variable which is then passed back to the main page for rendering.\n\n## Overview\n\nThe default Content Security Policy (CSP) settings of the extension disallows the use of `eval()` so using a sandbox is necessary to use external resources for this extension.\n"
  },
  {
    "path": "api-samples/sandbox/sandbox/service-worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n/**\n * Listens for the extension launching then creates a new tab\n *\n * @see http://developer.chrome.com/docs/extensions/reference/runtime\n * @see http://developer.chrome.com/docs/extensions/reference/tabs\n */\nchrome.action.onClicked.addListener(() => {\n  chrome.tabs.create({\n    url: 'mainpage.html'\n  });\n  console.log('Opened a tab with a sandboxed page!');\n});\n"
  },
  {
    "path": "api-samples/sandbox/sandbox/styles/main.css",
    "content": "html,\nbody {\n  font-family: Helvetica, Arial, sans-serif;\n}\n\nbutton {\n  width: 150px;\n  line-height: 26px;\n  font-size: 14px;\n  border-radius:4px;\n  border: 1px solid #666;\n  background: -webkit-linear-gradient(top, #ffffff 0%, #f2f2f2 99%);\n  box-shadow: 0 1px 1px rgba(0,0,0,0.3);\n  color: #555;\n}\n\nbutton:hover {\n  color: #333;\n}\n\nbutton:active {\n  color: #000;\n}\n\n#buttons {\n  text-align: center;\n  padding: 15px;\n  background: #fcfcfc;\n  border-bottom: 1px solid #f2f2f2;\n}\n\n#result {\n  padding: 20px;\n}\n\n#result h1 {\n  margin: 0 0 0.2em 0;\n}\n\n#result p {\n  line-height: 140%\n}\n"
  },
  {
    "path": "api-samples/sandbox/sandboxed-content/README.md",
    "content": "# Sandboxed Content\n\nThis sample creates a tab containing a sandboxed iframe (`sandbox.html`).\nThe sandbox calls `eval()` to write some HTML to its own document.\n\n## Overview\n\nThe default Content Security Policy (CSP) settings of the extension disallows the use of `eval()` so using a sandbox is necessary to use external resources for this extension.\n"
  },
  {
    "path": "api-samples/sandbox/sandboxed-content/main.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Sandboxed Content</title>\n    <link rel=\"stylesheet\" href=\"styles/main.css\" />\n  </head>\n  <body>\n    <h1>Main Window</h1>\n    <p>I am the main window. I am not sandboxed.</p>\n    <iframe src=\"sandboxed.html\" width=\"380\" height=\"140\"></iframe>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/sandbox/sandboxed-content/manifest.json",
    "content": "{\n  \"name\": \"Sandboxed Content Sample\",\n  \"version\": \"1.0.3\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"description\": \"Demonstrates creating a tab for a sandboxed iframe. The sandbox calls eval() to write HTML to its own document.\",\n  \"icons\": {\n    \"128\": \"icon_128.png\"\n  },\n  \"sandbox\": {\n    \"pages\": [\"sandboxed.html\"]\n  }\n}\n"
  },
  {
    "path": "api-samples/sandbox/sandboxed-content/sandboxed.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Sandboxed Content</title>\n    <link rel=\"stylesheet\" href=\"styles/main.css\" />\n  </head>\n  <body>\n    <h1>Sandboxed Content</h1>\n    <p>I am the sandboxed iframe.</p>\n    <div id=\"message\"></div>\n    <script>\n      eval(\n        \"document.getElementById('message').innerHTML = '<p>I am the \" +\n          \"output of an eval-ed inline script.</p>'\"\n      );\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/sandbox/sandboxed-content/service-worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n/**\n * Listens for the extension launching then creates the window\n *\n * @see http://developer.chrome.com/docs/extensions/reference/runtime.html\n * @see http://developer.chrome.com/docs/extensions/reference/tab.html\n */\nchrome.runtime.onInstalled.addListener(() => {\n  chrome.tabs.create({\n    url: 'main.html'\n  });\n});\n"
  },
  {
    "path": "api-samples/sandbox/sandboxed-content/styles/main.css",
    "content": "html, body {\n  font-family: Helvetica, Arial;\n  color: #444;\n}\n\nh1 {\n  margin: 0 0 0.3em 0;\n}\n\np {\n  color: #888;\n  margin: 0 0 1em 0;\n}\n\niframe {\n  border: 1px solid #CCC;\n  margin-top: 20px;\n}\n"
  },
  {
    "path": "api-samples/scripting/README.md",
    "content": "# chrome.scripting API\n\nThis sample demonstrates using the [chrome.scripting](https://developer.chrome.com/docs/extensions/reference/scripting/) API to inject JavaScript into web pages.\n\n## Overview\n\nOnce this extension is installed, clicking this extension's action icon will open an extension page.\n\n<img src=\"screenshot.png\" height=300 alt=\"Screenshot showing the chrome.scripting API demo running in Chrome.\">\n\n## Features\n\nThis sample allows you to experiment with the following injection mechanisms:\n\n- [Dynamic Declarations](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#dynamic-declarative), where a content script is registered at runtime.\n- [Programmatic Injection](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#programmatic), where a script is programatically executed in a tab which is already open.\n\nLearn more at https://developer.chrome.com/docs/extensions/mv3/content_scripts/.\n\n## Implementation Notes\n\nProgrammatic injection is handled in the service worker. A tab is opened to a specific URL (https://example.com/#inject-programmatic). When the page finishes loading, a script is then run using `chrome.scripting.executeScript`.\n\nWhen registering a dynamic content script, a tab is automatically opened if using the default matches URL. Otherwise, no tab is opened and the correct URL needs to be manually navigated to.\n"
  },
  {
    "path": "api-samples/scripting/content-script.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nalert('Hello World!');\n"
  },
  {
    "path": "api-samples/scripting/index.css",
    "content": "/* Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License. */\n\nform {\n  display: inline-block;\n  border: 1px solid #dadce0;\n  min-width: 500px;\n}\n\nh1 {\n  background: #f6f9fe;\n  margin: 0;\n  padding: 15px;\n  font-size: 20px;\n  text-align: center;\n}\n\n.tabs {\n  border-top: 1px solid #dadce0;\n  border-bottom: 1px solid #dadce0;\n  display: flex;\n}\n\n.tabs label:first-child {\n  border-right: 1px solid grey;\n}\n\n.tabs label.selected {\n  background: white;\n  font-weight: bold;\n}\n\n.tabs label {\n  display: block;\n  background: #f6f9fe;\n  text-align: center;\n  width: 100%;\n  padding: 7px 0;\n  margin: 0;\n}\n\n.tabs input {\n  display: none;\n}\n\nlabel {\n  margin: 20px;\n  display: flex;\n  justify-content: space-between;\n}\n\n.hint {\n  margin: 0 20px;\n  background: #f6f6f6;\n  padding: 7px 12px;\n}\n\n.buttons {\n  display: flex;\n  margin: 20px;\n}\n\n.buttons button {\n  margin-right: 15px;\n}\n"
  },
  {
    "path": "api-samples/scripting/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Scripting Demo</title>\n    <link rel=\"stylesheet\" href=\"index.css\" />\n    <script defer src=\"index.js\"></script>\n  </head>\n  <body>\n    <form>\n      <h1>Scripting Demo</h1>\n      <div class=\"tabs\">\n        <label>\n          Dynamic\n          <input type=\"radio\" name=\"type\" value=\"dynamic\" checked />\n        </label>\n        <label class=\"selected\">\n          Programmatic\n          <input type=\"radio\" name=\"type\" value=\"programmatic\" />\n        </label>\n      </div>\n      <label>\n        <span>Persist across sessions</span>\n        <select name=\"persist\" value=\"no\">\n          <option value=\"no\">No</option>\n          <option value=\"yes\">Yes</option>\n        </select>\n      </label>\n      <label>\n        <span>Run at</span>\n        <select name=\"run-at\" value=\"document_idle\">\n          <option value=\"document_start\">document_start</option>\n          <option value=\"document_end\">document_end</option>\n          <option value=\"document_idle\">document_idle</option>\n        </select>\n      </label>\n      <label>\n        <span>World</span>\n        <select name=\"world\" value=\"ISOLATED\">\n          <option value=\"ISOLATED\">ISOLATED</option>\n          <option value=\"MAIN\">MAIN</option>\n        </select>\n      </label>\n      <label>\n        <span>All Frames</span>\n        <select name=\"all-frames\" value=\"no\">\n          <option value=\"no\">No</option>\n          <option value=\"yes\">Yes</option>\n        </select>\n      </label>\n      <label>\n        <span>Matches</span>\n        <input type=\"text\" name=\"matches\" value=\"https://example.com/*\" />\n      </label>\n      <p class=\"hint\">\n        Note: Make sure you request the required\n        <code>host_permissions</code> in the manifest.\n      </p>\n      <div class=\"buttons programmatic-buttons\">\n        <button type=\"button\" id=\"inject-programmatic\">Execute Script</button>\n      </div>\n      <div class=\"buttons dynamic-buttons\">\n        <button type=\"button\" id=\"register-dynamic\" disabled>\n          Register Script\n        </button>\n        <button type=\"button\" id=\"unregister-dynamic\" disabled>\n          Unregister Script\n        </button>\n      </div>\n    </form>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/scripting/index.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst DYNAMIC_SCRIPT_ID = 'dynamic-script';\n\nasync function isDynamicContentScriptRegistered() {\n  const scripts = await chrome.scripting.getRegisteredContentScripts();\n  return scripts.some((s) => s.id === DYNAMIC_SCRIPT_ID);\n}\n\ndocument\n  .querySelector('#inject-programmatic')\n  .addEventListener('click', async () => {\n    // Unregister the dynamic content script to avoid multiple injections.\n    const dynamicContentScriptRegistered =\n      await isDynamicContentScriptRegistered();\n\n    if (dynamicContentScriptRegistered) {\n      await chrome.scripting.unregisterContentScripts({\n        ids: [DYNAMIC_SCRIPT_ID]\n      });\n    }\n\n    // Now, execute the script. We handle this in the service worker so we can\n    // wait for the tab to open and **then** inject our script.\n    const world = document.querySelector(\"[name='world']\").value;\n    chrome.runtime.sendMessage({\n      name: 'inject-programmatic',\n      options: { world }\n    });\n  });\n\ndocument\n  .querySelector('#register-dynamic')\n  .addEventListener('click', async () => {\n    const persistAcrossSessions =\n      document.querySelector(\"[name='persist']\").value === 'yes';\n    const matches = document.querySelector(\"[name='matches']\").value;\n    const runAt = document.querySelector(\"[name='run-at']\").value;\n    const allFrames =\n      document.querySelector(\"[name='all-frames']\").value === 'yes';\n    const world = document.querySelector(\"[name='world']\").value;\n\n    await chrome.scripting.registerContentScripts([\n      {\n        id: DYNAMIC_SCRIPT_ID,\n        js: ['content-script.js'],\n        persistAcrossSessions,\n        matches: [matches],\n        runAt,\n        allFrames,\n        world\n      }\n    ]);\n\n    // Only open the page by default if the `matches` field hasn't been changed.\n    if (matches === 'https://example.com/*') {\n      await chrome.tabs.create({ url: 'https://example.com' });\n    }\n\n    updateUI();\n  });\n\ndocument\n  .querySelector('#unregister-dynamic')\n  .addEventListener('click', async () => {\n    await chrome.scripting.unregisterContentScripts({\n      ids: [DYNAMIC_SCRIPT_ID]\n    });\n    updateUI();\n  });\n\nconst PROGRAMMATIC_TAB_SELECTOR = \"[name='type'][value='programmatic']\";\nconst DYNAMIC_TAB_SELECTOR = \"[name='type'][value='dynamic']\";\n\nfunction updateUI() {\n  const type = document.querySelector(PROGRAMMATIC_TAB_SELECTOR).checked\n    ? 'programmatic'\n    : 'dynamic';\n\n  // Update selected tab.\n  document.querySelector(PROGRAMMATIC_TAB_SELECTOR).parentElement.className =\n    type === 'programmatic' ? 'selected' : '';\n  document.querySelector(DYNAMIC_TAB_SELECTOR).parentElement.className =\n    type === 'dynamic' ? 'selected' : '';\n\n  // Only show some fields for dynamic scripts.\n  document.querySelector(\"[name='run-at']\").parentElement.style.display =\n    type === 'dynamic' ? '' : 'none';\n  document.querySelector(\"[name='persist']\").parentElement.style.display =\n    type === 'dynamic' ? '' : 'none';\n  document.querySelector(\"[name='all-frames']\").parentElement.style.display =\n    type === 'dynamic' ? '' : 'none';\n  document.querySelector(\"[name='matches']\").parentElement.style.display =\n    type === 'dynamic' ? '' : 'none';\n  document.querySelector('.hint').style.display =\n    type === 'dynamic' ? '' : 'none';\n\n  // Update visible buttons.\n  document.querySelector('.programmatic-buttons').style.display =\n    type === 'programmatic' ? 'flex' : 'none';\n  document.querySelector('.dynamic-buttons').style.display =\n    type === 'dynamic' ? 'flex' : 'none';\n\n  // Decide if the register or unregister button is visible for dynamic scripts.\n  isDynamicContentScriptRegistered().then((dynamicContentScriptRegistered) => {\n    document\n      .querySelector('#register-dynamic')\n      .toggleAttribute('disabled', dynamicContentScriptRegistered);\n    document\n      .querySelector('#unregister-dynamic')\n      .toggleAttribute('disabled', !dynamicContentScriptRegistered);\n  });\n}\n\nupdateUI();\n\ndocument\n  .querySelector(PROGRAMMATIC_TAB_SELECTOR)\n  .addEventListener('change', (e) => {\n    e.target.checked && updateUI();\n  });\n\ndocument.querySelector(DYNAMIC_TAB_SELECTOR).addEventListener('change', (e) => {\n  e.target.checked && updateUI();\n});\n"
  },
  {
    "path": "api-samples/scripting/manifest.json",
    "content": "{\n  \"name\": \"Scripting API Demo\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"description\": \"Uses the chrome.scripting API to inject JavaScript into web pages.\",\n  \"background\": {\n    \"service_worker\": \"sw.js\"\n  },\n  \"permissions\": [\"scripting\", \"webNavigation\", \"storage\"],\n  \"host_permissions\": [\"https://example.com/*\"],\n  \"action\": {}\n}\n"
  },
  {
    "path": "api-samples/scripting/sw.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.action.onClicked.addListener(openDemoTab);\n\nfunction openDemoTab() {\n  chrome.tabs.create({ url: 'index.html' });\n}\n\nchrome.webNavigation.onDOMContentLoaded.addListener(async ({ tabId, url }) => {\n  if (url !== 'https://example.com/#inject-programmatic') return;\n  const { options } = await chrome.storage.local.get('options');\n  chrome.scripting.executeScript({\n    target: { tabId },\n    files: ['content-script.js'],\n    ...options\n  });\n});\n\nchrome.runtime.onMessage.addListener(async ({ name, options }) => {\n  if (name === 'inject-programmatic') {\n    await chrome.storage.local.set({ options });\n    await chrome.tabs.create({\n      url: 'https://example.com/#inject-programmatic'\n    });\n  }\n});\n"
  },
  {
    "path": "api-samples/storage/stylizr/README.md",
    "content": "# chrome.storage - Stylizr\n\nA sample that demonstrates how to use the [`chrome.storage`](https://developer.chrome.com/docs/extensions/reference/storage/) API.\n\n## Overview\n\nIn this sample, the `chrome.storage` API stores a custom style string that will be applied to the active page when the extension's action icon is clicked.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension's action icon to see the effect.\n"
  },
  {
    "path": "api-samples/storage/stylizr/manifest.json",
    "content": "{\n  \"name\": \"Stylizr\",\n  \"description\": \"Demonstrates how to use the chrome.storage API.\",\n  \"version\": \"1.0\",\n  \"permissions\": [\"activeTab\", \"storage\", \"scripting\"],\n  \"options_page\": \"options.html\",\n  \"action\": {\n    \"default_icon\": \"icon.png\",\n    \"default_title\": \"Stylize!\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/storage/stylizr/options.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Stylizr</title>\n    <style>\n      body {\n        font-family: sans-serif;\n      }\n\n      label {\n        display: block;\n      }\n\n      textarea {\n        font-family: monospace;\n      }\n\n      .message {\n        height: 20px;\n        background: #eee;\n        padding: 5px;\n      }\n    </style>\n  </head>\n\n  <body>\n    <div class=\"message\"></div>\n    <h3>Stylizr Instructions</h3>\n\n    <ol>\n      <li>Write CSS in this textarea and save</li>\n      <li>Navigate to some page</li>\n      <li>Click the browser action icon <img src=\"icon.png\" /></li>\n      <li>Hey presto! CSS is injected!</li>\n    </ol>\n\n    <textarea\n      name=\"style_url\"\n      id=\"style_url\"\n      cols=\"80\"\n      rows=\"24\"\n      placeholder=\"eg: * { font-size: 110%; }\"\n    ></textarea>\n\n    <br />\n    <button class=\"submit\">Save</button>\n    <button class=\"reset\">Reset</button>\n\n    <script src=\"options.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/storage/stylizr/options.js",
    "content": "// Store CSS data in the \"local\" storage area.\nconst storage = chrome.storage.local;\n\n// Get at the DOM controls used in the sample.\nconst resetButton = document.querySelector('button.reset');\nconst submitButton = document.querySelector('button.submit');\nconst textarea = document.querySelector('textarea');\n\n// Load any CSS that may have previously been saved.\nloadChanges();\n\nsubmitButton.addEventListener('click', saveChanges);\nresetButton.addEventListener('click', reset);\n\nasync function saveChanges() {\n  // Get the current CSS snippet from the form.\n  const cssCode = textarea.value;\n  // Check that there's some code there.\n  if (!cssCode) {\n    message('Error: No CSS specified');\n    return;\n  }\n  // Save it using the Chrome extension storage API.\n  await storage.set({ css: cssCode });\n  message('Settings saved');\n}\n\nfunction loadChanges() {\n  storage.get('css', function (items) {\n    // To avoid checking items.css we could specify storage.get({css: ''}) to\n    // return a default value of '' if there is no css value yet.\n    if (items.css) {\n      textarea.value = items.css;\n      message('Loaded saved CSS.');\n    }\n  });\n}\n\nasync function reset() {\n  // Remove the saved value from storage. storage.clear would achieve the same\n  // thing.\n  await storage.remove('css');\n  message('Reset stored CSS');\n  // Refresh the text area.\n  textarea.value = '';\n}\n\nlet messageClearTimer;\nfunction message(msg) {\n  clearTimeout(messageClearTimer);\n  const message = document.querySelector('.message');\n  message.innerText = msg;\n  messageClearTimer = setTimeout(function () {\n    message.innerText = '';\n  }, 3000);\n}\n"
  },
  {
    "path": "api-samples/storage/stylizr/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Stylizr</title>\n    <style>\n      body {\n        font-family: sans-serif;\n        width: 200px;\n      }\n    </style>\n  </head>\n\n  <body>\n    <div id=\"message\"></div>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/storage/stylizr/popup.js",
    "content": "// Store CSS data in the \"local\" storage area.\nconst storage = chrome.storage.local;\n\nconst message = document.querySelector('#message');\n\n// Check if there is CSS specified.\nasync function run() {\n  const items = await storage.get('css');\n  if (items.css) {\n    const [currentTab] = await chrome.tabs.query({\n      active: true,\n      currentWindow: true\n    });\n    try {\n      await chrome.scripting.insertCSS({\n        css: items.css,\n        target: {\n          tabId: currentTab.id\n        }\n      });\n      message.innerText = 'Injected style!';\n    } catch (e) {\n      console.error(e);\n      message.innerText = 'Injection failed. Are you on a special page?';\n    }\n  } else {\n    const optionsUrl = chrome.runtime.getURL('options.html');\n    const optionsPageLink = document.createElement('a');\n    optionsPageLink.target = '_blank';\n    optionsPageLink.href = optionsUrl;\n    optionsPageLink.textContent = 'options page';\n    message.innerText = '';\n    message.appendChild(document.createTextNode('Set a style in the '));\n    message.appendChild(optionsPageLink);\n    message.appendChild(document.createTextNode(' first.'));\n  }\n}\n\nrun();\n"
  },
  {
    "path": "api-samples/tabCapture/README.md",
    "content": "# chrome.tabCapture\n\nA sample that demonstrates how to use the [`chrome.tabCapture`](https://developer.chrome.com/docs/extensions/reference/tabCapture/) API.\n\n## Overview\n\nIn this sample, the `chrome.tabCapture` API captures the contents of the active tab. The captured stream is displayed in a new window.\n\n## Implementation Notes\n\nCall [`tabCapture.getMediaStreamId()`](https://developer.chrome.com/docs/extensions/reference/tabCapture/#method-getMediaStreamId) to capture specific tabs.\n\nThe `targetTabId` and `consumerTabId` are obtained in the Service Worker, and then passed to the receiver page through the [`tabs.sendMessage()`](https://developer.chrome.com/docs/extensions/reference/tabs/#method-sendMessage) method.\n\nSee the [Audio recording and screen capture guide](https://developer.chrome.com/docs/extensions/mv3/screen_capture/#audio-and-video) for a more detailed implementation.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension's action icon.\n"
  },
  {
    "path": "api-samples/tabCapture/manifest.json",
    "content": "{\n  \"name\": \"Tab Capture Example\",\n  \"description\": \"Demonstrates how to use the chrome.tabCapture API.\",\n  \"version\": \"1\",\n  \"manifest_version\": 3,\n  \"action\": {\n    \"default_icon\": \"icon.png\"\n  },\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"permissions\": [\"tabs\", \"tabCapture\"]\n}\n"
  },
  {
    "path": "api-samples/tabCapture/receiver.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>receiver</title>\n  </head>\n\n  <body>\n    <p id=\"echo-msg\"></p>\n    <video id=\"player\" width=\"100%\"></video>\n    <script src=\"./receiver.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/tabCapture/receiver.js",
    "content": "let currentStream = null;\n\nfunction printErrorMessage(message) {\n  const element = document.getElementById('echo-msg');\n  element.innerText = message;\n  console.error(message);\n}\n\n// Stop video play-out and stop the MediaStreamTracks.\nfunction shutdownReceiver() {\n  if (!currentStream) {\n    return;\n  }\n\n  const player = document.getElementById('player');\n  player.srcObject = null;\n  const tracks = currentStream.getTracks();\n  for (let i = 0; i < tracks.length; ++i) {\n    tracks[i].stop();\n  }\n  currentStream = null;\n}\n\n// Start video play-out of the captured MediaStream.\nfunction playCapturedStream(stream) {\n  if (!stream) {\n    printErrorMessage(\n      'Error starting tab capture: ' +\n        (chrome.runtime.lastError.message || 'UNKNOWN')\n    );\n    return;\n  }\n  if (currentStream != null) {\n    shutdownReceiver();\n  }\n  currentStream = stream;\n  const player = document.getElementById('player');\n  player.addEventListener(\n    'canplay',\n    function () {\n      this.volume = 0.75;\n      this.muted = false;\n      this.play();\n    },\n    {\n      once: true\n    }\n  );\n  player.setAttribute('controls', '1');\n  player.srcObject = stream;\n}\n\nfunction testGetMediaStreamId(targetTabId, consumerTabId) {\n  chrome.tabCapture.getMediaStreamId(\n    { targetTabId, consumerTabId },\n    function (streamId) {\n      if (typeof streamId !== 'string') {\n        printErrorMessage(\n          'Failed to get media stream id: ' +\n            (chrome.runtime.lastError.message || 'UNKNOWN')\n        );\n        return;\n      }\n\n      navigator.webkitGetUserMedia(\n        {\n          audio: false,\n          video: {\n            mandatory: {\n              chromeMediaSource: 'tab', // The media source must be 'tab' here.\n              chromeMediaSourceId: streamId\n            }\n          }\n        },\n        function (stream) {\n          playCapturedStream(stream);\n        },\n        function (error) {\n          printErrorMessage(error);\n        }\n      );\n    }\n  );\n}\n\nchrome.runtime.onMessage.addListener(function (request) {\n  const { targetTabId, consumerTabId } = request;\n  testGetMediaStreamId(targetTabId, consumerTabId);\n});\n\nwindow.addEventListener('beforeunload', shutdownReceiver);\n"
  },
  {
    "path": "api-samples/tabCapture/service-worker.js",
    "content": "async function closePrevReceiverTab() {\n  const tabs = await chrome.tabs.query({\n    url: chrome.runtime.getURL('receiver.html')\n  });\n\n  await Promise.all(tabs.map((tab) => chrome.tabs.remove(tab.id)));\n}\n\nchrome.action.onClicked.addListener(async (tab) => {\n  const currentTabId = tab.id;\n\n  await closePrevReceiverTab();\n\n  // Open a new tab with the receiver.html page\n  const { tabs } = await chrome.windows.create({\n    url: chrome.runtime.getURL('receiver.html')\n  });\n\n  const receiverTabId = tabs[0].id;\n\n  // Wait for the receiver tab to load\n  await new Promise((resolve) => {\n    chrome.tabs.onUpdated.addListener(function listener(tabId, info) {\n      if (tabId === receiverTabId && info.status === 'complete') {\n        chrome.tabs.onUpdated.removeListener(listener);\n        resolve();\n      }\n    });\n  });\n\n  // Send a message to the receiver tab\n  chrome.tabs.sendMessage(receiverTabId, {\n    targetTabId: currentTabId,\n    consumerTabId: receiverTabId\n  });\n});\n"
  },
  {
    "path": "api-samples/tabs/inspector/README.md",
    "content": "# chrome.tabs - Tab Inspector\n\nA sample that demonstrates how to use the [`chrome.tabs`](https://developer.chrome.com/docs/extensions/reference/tabs/) API.\n\n## Overview\n\nIn the sample, a simple tab inspector manipulates the tabs and windows.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension's icon to open the tab inspector.\n"
  },
  {
    "path": "api-samples/tabs/inspector/manifest.json",
    "content": "{\n  \"name\": \"Tab Inspector\",\n  \"description\": \"Demonstrates the chrome.tabs API and the chrome.windows API by providing a user interface to manage tabs and windows.\",\n  \"version\": \"0.3\",\n  \"permissions\": [\"tabs\"],\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"action\": {\n    \"default_title\": \"Show tab inspector\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/tabs/inspector/service-worker.js",
    "content": "chrome.action.onClicked.addListener(function () {\n  chrome.tabs.create({\n    url: chrome.runtime.getURL('window_and_tabs_manager.html')\n  });\n});\n"
  },
  {
    "path": "api-samples/tabs/inspector/window_and_tabs_manager.css",
    "content": ".window-item {\n    background-color: #aaeeee;\n    margin: 4px;\n    padding: 8px;\n    margin: 20px;\n}\n\n.window-id-wrapper {\n    font-style: italic;\n    width: 80px;\n    display: inline-block;\n}\n\n.window_left,\n.window_right,\n.window_width,\n.window_height {\n    display: inline-block;\n}\n\n.window-status-input {\n    width: 60px;\n}\n\n.tab-item {\n    background-color: #eeeeee;\n    margin: 8px;\n    padding: 4px;\n}\n\n.wrapper {\n    margin: 8px;\n}\n\n.tab_id {\n    font-style: italic;\n    width: 80px;\n    display: inline-block;\n}\n\n.tab-actions-wrapper {\n    display: inline-block;\n}\n\n.tab_index {\n    width: 20px;\n}\n\n.tab_window_id {\n    width: 80px;\n}\n\n#log {\n    background-color: #eeaaee;\n    margin: 20px;\n    padding: 8px;\n}\n\n.input-group {\n    display: flex;\n    justify-content: space-between;\n}\n\n.label {\n    display: inline-block;\n}\n\n.tab_title,\n.tab_url,\n#new_window_url,\n#window_id_new,\n#url_new {\n    width: 90%;\n}\n\n.new-window-wrapper {\n    background-color: #eeeebb;\n    margin: 20px;\n    padding: 8px;\n}\n\n.new-tab-wrapper {\n    background-color: #eeeeaa;\n    margin: 20px;\n    padding: 8px;\n}\n\nh3 {\n    text-align: center;\n    margin: 8px;\n}\n\n.window_left,\n.window_top,\n.window_width,\n.window_height,\n#new_window_left,\n#new_window_top,\n#new_window_width,\n#new_window_height {\n    width: 50px;\n}\n\n.new-window-status-wrapper {\n    display: inline-block;\n}\n\n.actions-wrapper {\n    margin: 20px;\n}\n"
  },
  {
    "path": "api-samples/tabs/inspector/window_and_tabs_manager.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Tabs Inspector</title>\n    <link rel=\"stylesheet\" href=\"./window_and_tabs_manager.css\" />\n  </head>\n\n  <body>\n    <div id=\"windowList\">\n      <!-- WindowItems Here -->\n    </div>\n    <template id=\"windowItem\">\n      <div class=\"window-item\">\n        <div class=\"window-id-wrapper\">\n          Window: <span class=\"window_id\"></span>\n        </div>\n        <div class=\"window-status-wrapper\">\n          left:\n          <input class=\"window_left\" type=\"text\" /> top:\n          <input class=\"window_top\" type=\"text\" /> width:\n          <input class=\"window_width\" type=\"text\" /> height:\n          <input class=\"window_height\" type=\"text\" />\n          <input class=\"window_focused\" type=\"checkbox\" disabled /> Focused\n          <input class=\"window_current\" type=\"checkbox\" disabled /> Current\n          <button class=\"window_refresh\">Refresh</button>\n        </div>\n        <div id=\"tabList\">\n          <!-- TabItems Here -->\n        </div>\n        <button class=\"update_window_button\">Update Window</button>\n        <button class=\"remove_window_button\">Close Window</button>\n        <button class=\"refresh_active_tab_button\">Refresh Active Tab</button>\n      </div>\n    </template>\n    <template id=\"tabItem\">\n      <div class=\"tab-item\">\n        <div class=\"wrapper\">\n          <div class=\"tab_id\"></div>\n          <div class=\"tab-actions-wrapper\">\n            index:\n            <input type=\"text\" class=\"tab_index\" />\n            windowId:\n            <input type=\"text\" class=\"tab_window_id\" />\n            <button class=\"move_tab_button\">Move</button>\n            <button class=\"refresh_tab_button\">Refresh</button>\n          </div>\n        </div>\n        <div class=\"wrapper\">\n          <div class=\"input-group\">\n            <div class=\"label\">title:</div>\n            <input type=\"text\" class=\"tab_title\" />\n          </div>\n          <div class=\"input-group\">\n            <div class=\"label\">url:</div>\n            <input type=\"text\" class=\"tab_url\" />\n          </div>\n          <div><input type=\"checkbox\" class=\"tab_active\" /> Active</div>\n        </div>\n        <button class=\"update_tab_button\">Update Tab</button>\n        <button class=\"remove_tab_button\">Close Tab</button>\n      </div>\n    </template>\n    <div class=\"new-window-wrapper\">\n      <h3>Create Window</h3>\n      <div class=\"wrapper\">\n        <div class=\"new-window-status-wrapper\">\n          left:\n          <input type=\"text\" id=\"new_window_left\" /> top:\n          <input type=\"text\" id=\"new_window_top\" /> width:\n          <input type=\"text\" id=\"new_window_width\" /> height:\n          <input type=\"text\" id=\"new_window_height\" />\n        </div>\n      </div>\n      <div class=\"wrapper\">\n        <div class=\"input-group\">\n          <div class=\"label\">url:</div>\n          <input type=\"text\" id=\"new_window_url\" />\n        </div>\n      </div>\n      <button id=\"create_window_button\">Create</button>\n    </div>\n    <div class=\"new-tab-wrapper\">\n      <h3>Create Tab</h3>\n      <div class=\"wrapper\">\n        <div class=\"input-group\">\n          <div class=\"label\">windowId:</div>\n          <input type=\"text\" id=\"window_id_new\" />\n        </div>\n        <div class=\"input-group\">\n          <div class=\"label\">url:</div>\n          <input type=\"text\" id=\"url_new\" />\n        </div>\n        <div><input type=\"checkbox\" id=\"active_new\" /> active</div>\n      </div>\n      <button id=\"create_tab_button\">Create</button>\n    </div>\n    <div class=\"actions-wrapper\">\n      <button id=\"load_window_list_button\">Refresh</button>\n      <button id=\"update_all_button\">Update All</button>\n      <button id=\"move_all_button\">Move All</button>\n      <button id=\"clear_log_button\">Clear Log</button>\n      <button id=\"new_window_button\">New Window</button>\n    </div>\n    <div id=\"log\"></div>\n    <script src=\"window_and_tabs_manager.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/tabs/inspector/window_and_tabs_manager.js",
    "content": "let tabs = {};\nlet tabIds = [];\n\nlet focusedWindowId = undefined;\nlet currentWindowId = undefined;\n\nasync function bootstrap() {\n  const currentWindow = await chrome.windows.getCurrent();\n  currentWindowId = currentWindow.id;\n  const focusedWindow = await chrome.windows.getLastFocused();\n  focusedWindowId = focusedWindow.id;\n  loadWindowList();\n}\n\nfunction isInt(i) {\n  return typeof i == 'number' && !(i % 1) && !isNaN(i);\n}\n\nconst windowTemplate = document.getElementById('windowItem').content;\nconst tabTemplate = document.getElementById('tabItem').content;\n\nasync function loadWindowList() {\n  const windowList = await chrome.windows.getAll({ populate: true });\n  tabs = {};\n  tabIds = [];\n  for (let window of windowList) {\n    for (let tab of window.tabs) {\n      tabIds.push(tab.id);\n      tabs[tab.id] = tab;\n    }\n  }\n\n  const output = document.getElementById('windowList');\n  output.replaceChildren();\n\n  for (let window of windowList) {\n    const windowItem = document.importNode(windowTemplate, true).children[0];\n    renderWindow(window, windowItem);\n    registerWindowEvents(window, windowItem);\n\n    output.appendChild(windowItem);\n  }\n}\n\nfunction renderWindow(window, windowItem) {\n  windowItem.id = `window_${window.id}`;\n  windowItem.querySelector('.window_left').id = `left_${window.id}`;\n  windowItem.querySelector('.window_top').id = `top_${window.id}`;\n  windowItem.querySelector('.window_width').id = `width_${window.id}`;\n  windowItem.querySelector('.window_height').id = `height_${window.id}`;\n  windowItem.querySelector('.window_focused').id = `focused_${window.id}`;\n  windowItem.querySelector('.window_current').id = `current_${window.id}`;\n  windowItem.querySelector('.window_id').innerText = window.id;\n  windowItem.querySelector('.window_left').value = window.left;\n  windowItem.querySelector('.window_top').value = window.top;\n  windowItem.querySelector('.window_width').value = window.width;\n  windowItem.querySelector('.window_height').value = window.height;\n  windowItem.querySelector('.window_focused').checked =\n    window.id == focusedWindowId;\n  windowItem.querySelector('.window_current').checked =\n    window.id == currentWindowId;\n\n  windowItem.querySelector('#tabList').innerHTML = '';\n  for (let tab of window.tabs) {\n    const tabItem = document.importNode(tabTemplate, true).children[0];\n    renderTab(tab, tabItem);\n    registerTabEvents(tab, tabItem);\n    windowItem.querySelector('#tabList').appendChild(tabItem);\n  }\n}\n\nfunction registerWindowEvents(window, windowItem) {\n  windowItem\n    .querySelector('.window_refresh')\n    .addEventListener('click', function () {\n      refreshWindow(window.id);\n    });\n\n  windowItem\n    .querySelector('.update_window_button')\n    .addEventListener('click', function () {\n      updateWindow(window.id);\n    });\n\n  windowItem\n    .querySelector('.remove_window_button')\n    .addEventListener('click', function () {\n      removeWindow(window.id);\n    });\n\n  windowItem\n    .querySelector('.refresh_active_tab_button')\n    .addEventListener('click', function () {\n      refreshActiveTab(window.id);\n    });\n}\n\nfunction renderTab(tab, tabItem) {\n  tabItem.id = `tab_${tab.id}`;\n  tabItem.querySelector('.tab_index').id = `index_${tab.id}`;\n  tabItem.querySelector('.tab_window_id').id = `windowId_${tab.id}`;\n  tabItem.querySelector('.tab_title').id = `title_${tab.id}`;\n  tabItem.querySelector('.tab_url').id = `url_${tab.id}`;\n  tabItem.querySelector('.tab_active').id = `active_${tab.id}`;\n\n  tabItem.querySelector('.tab_id').innerText = `TabId: ${tab.id}`;\n  tabItem.querySelector('.tab_index').value = tab.index;\n  tabItem.querySelector('.tab_window_id').value = tab.windowId;\n  tabItem.querySelector('.tab_title').value = tab.title;\n  tabItem.querySelector('.tab_url').value = tab.url;\n  tabItem.querySelector('.tab_active').checked = tab.active;\n}\n\nfunction registerTabEvents(tab, tabItem) {\n  tabItem\n    .querySelector('.move_tab_button')\n    .addEventListener('click', function () {\n      moveTab(tab.id);\n    });\n  tabItem\n    .querySelector('.refresh_tab_button')\n    .addEventListener('click', function () {\n      refreshTab(tab.id);\n    });\n  tabItem\n    .querySelector('.update_tab_button')\n    .addEventListener('click', function () {\n      updateTab(tab.id);\n    });\n  tabItem\n    .querySelector('.remove_tab_button')\n    .addEventListener('click', function () {\n      removeTab(tab.id);\n    });\n  tabItem\n    .querySelector('.tab_active')\n    .addEventListener('change', function (event) {\n      const active = event.target.checked;\n      const tabId = parseInt(event.target.id.split('_')[1]);\n      chrome.tabs.update(tabId, { active });\n    });\n}\n\nfunction updateTabData(id) {\n  const retval = {\n    url: document.getElementById('url_' + id).value,\n    active: document.getElementById('active_' + id).value ? true : false\n  };\n\n  return retval;\n}\n\nasync function updateTab(id) {\n  try {\n    await chrome.tabs.update(id, updateTabData(id));\n  } catch (e) {\n    alert(e);\n  }\n}\n\nfunction moveTabData(id) {\n  return {\n    index: parseInt(document.getElementById('index_' + id).value),\n    windowId: parseInt(document.getElementById('windowId_' + id).value)\n  };\n}\n\nfunction moveTab(id) {\n  chrome.tabs.move(id, moveTabData(id)).catch(alert);\n}\n\nfunction createTabData() {\n  return {\n    windowId: parseInt(document.getElementById('window_id_new').value),\n    url: document.getElementById('url_new').value,\n    active: document.getElementById('active_new').checked\n  };\n}\n\nfunction createTab() {\n  const args = createTabData();\n\n  if (!isInt(args.windowId)) delete args.windowId;\n  if (!args.url) delete args.url;\n\n  chrome.tabs.create(args).catch(alert);\n}\n\ndocument\n  .getElementById('create_tab_button')\n  .addEventListener('click', createTab);\n\nasync function updateAll() {\n  try {\n    for (let i = 0; i < tabIds.length; i++) {\n      await chrome.tabs.update(tabIds[i], updateTabData(tabIds[i]));\n    }\n  } catch (e) {\n    alert(e);\n  }\n}\n\nasync function moveAll() {\n  appendToLog('moving all');\n  try {\n    for (let i = 0; i < tabIds.length; i++) {\n      await chrome.tabs.move(tabIds[i], moveTabData(tabIds[i]));\n    }\n  } catch (e) {\n    alert(e);\n  }\n}\n\nfunction removeTab(tabId) {\n  chrome.tabs\n    .remove(tabId)\n    .then(function () {\n      appendToLog('tab: ' + tabId + ' removed.');\n    })\n    .catch(alert);\n}\n\nfunction appendToLog(logLine) {\n  document\n    .getElementById('log')\n    .appendChild(document.createElement('div')).innerText = '> ' + logLine;\n}\n\nfunction clearLog() {\n  document.getElementById('log').innerText = '';\n}\n\nchrome.windows.onCreated.addListener(function (createInfo) {\n  appendToLog('windows.onCreated -- window: ' + createInfo.id);\n  loadWindowList();\n});\n\nchrome.windows.onBoundsChanged.addListener(function (window) {\n  appendToLog('windows.onBoundsChanged -- window: ' + window.id);\n  refreshWindow(window.id);\n});\n\nchrome.windows.onFocusChanged.addListener(function (windowId) {\n  focusedWindowId = windowId;\n  appendToLog('windows.onFocusChanged -- window: ' + windowId);\n  loadWindowList();\n});\n\nchrome.windows.onRemoved.addListener(function (windowId) {\n  appendToLog('windows.onRemoved -- window: ' + windowId);\n  loadWindowList();\n});\n\nchrome.tabs.onCreated.addListener(function (tab) {\n  appendToLog(\n    'tabs.onCreated -- window: ' +\n      tab.windowId +\n      ' tab: ' +\n      tab.id +\n      ' title: ' +\n      tab.title +\n      ' index ' +\n      tab.index +\n      ' url ' +\n      tab.url\n  );\n  loadWindowList();\n});\n\nchrome.tabs.onAttached.addListener(function (tabId, props) {\n  appendToLog(\n    'tabs.onAttached -- window: ' +\n      props.newWindowId +\n      ' tab: ' +\n      tabId +\n      ' index ' +\n      props.newPosition\n  );\n  loadWindowList();\n});\n\nchrome.tabs.onMoved.addListener(function (tabId, props) {\n  appendToLog(\n    'tabs.onMoved -- window: ' +\n      props.windowId +\n      ' tab: ' +\n      tabId +\n      ' from ' +\n      props.fromIndex +\n      ' to ' +\n      props.toIndex\n  );\n  loadWindowList();\n});\n\nasync function refreshTab(tabId) {\n  const tab = await chrome.tabs.get(tabId);\n  const output = document.getElementById('tab_' + tab.id);\n  if (!output) return;\n  renderTab(tab, output);\n  appendToLog('tab refreshed -- tabId: ' + tab.id + ' url: ' + tab.url);\n}\n\nchrome.tabs.onUpdated.addListener(function (tabId, props) {\n  appendToLog(\n    'tabs.onUpdated -- tab: ' +\n      tabId +\n      ' status ' +\n      props.status +\n      ' url ' +\n      props.url\n  );\n  refreshTab(tabId);\n});\n\nchrome.tabs.onDetached.addListener(function (tabId, props) {\n  appendToLog(\n    'tabs.onDetached -- window: ' +\n      props.oldWindowId +\n      ' tab: ' +\n      tabId +\n      ' index ' +\n      props.oldPosition\n  );\n  loadWindowList();\n});\n\nchrome.tabs.onActivated.addListener(function (props) {\n  appendToLog(\n    'tabs.onActivated -- window: ' + props.windowId + ' tab: ' + props.tabId\n  );\n  loadWindowList();\n});\n\nchrome.tabs.onRemoved.addListener(function (tabId) {\n  appendToLog('tabs.onRemoved -- tab: ' + tabId);\n  loadWindowList();\n});\n\nasync function createWindow() {\n  const args = {\n    left: parseInt(document.getElementById('new_window_left').value),\n    top: parseInt(document.getElementById('new_window_top').value),\n    width: parseInt(document.getElementById('new_window_width').value),\n    height: parseInt(document.getElementById('new_window_height').value),\n    url: document.getElementById('new_window_url').value\n  };\n\n  if (!isInt(args.left)) delete args.left;\n  if (!isInt(args.top)) delete args.top;\n  if (!isInt(args.width)) delete args.width;\n  if (!isInt(args.height)) delete args.height;\n  if (!args.url) delete args.url;\n\n  chrome.windows.create(args).catch(alert);\n}\n\ndocument\n  .getElementById('create_window_button')\n  .addEventListener('click', createWindow);\n\nasync function refreshWindow(windowId) {\n  const window = await chrome.windows.get(windowId);\n  const tabList = await chrome.tabs.query({ windowId });\n  window.tabs = tabList;\n  const output = document.getElementById('window_' + window.id);\n  if (!output) return;\n  renderWindow(window, output);\n}\n\nfunction updateWindowData(id) {\n  const retval = {\n    left: parseInt(document.getElementById('left_' + id).value),\n    top: parseInt(document.getElementById('top_' + id).value),\n    width: parseInt(document.getElementById('width_' + id).value),\n    height: parseInt(document.getElementById('height_' + id).value)\n  };\n  if (!isInt(retval.left)) delete retval.left;\n  if (!isInt(retval.top)) delete retval.top;\n  if (!isInt(retval.width)) delete retval.width;\n  if (!isInt(retval.height)) delete retval.height;\n\n  return retval;\n}\n\nfunction updateWindow(id) {\n  chrome.windows.update(id, updateWindowData(id)).catch(alert);\n}\n\nfunction removeWindow(windowId) {\n  chrome.windows\n    .remove(windowId)\n    .then(function () {\n      appendToLog('window: ' + windowId + ' removed.');\n    })\n    .catch(alert);\n}\n\nasync function refreshActiveTab(windowId) {\n  const tabs = await chrome.tabs.query({ active: true, windowId });\n  const output = document.getElementById('tab_' + tabs[0].id);\n  if (!output) return;\n  renderTab(tabs[0], output);\n  appendToLog(\n    'Active tab refreshed -- tabId: ' + tabs[0].id + ' url:' + tabs[0].url\n  );\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  bootstrap();\n});\n\ndocument\n  .getElementById('load_window_list_button')\n  .addEventListener('click', function () {\n    loadWindowList();\n  });\ndocument\n  .getElementById('update_all_button')\n  .addEventListener('click', function () {\n    updateAll();\n  });\ndocument\n  .getElementById('move_all_button')\n  .addEventListener('click', function () {\n    moveAll();\n  });\ndocument\n  .getElementById('clear_log_button')\n  .addEventListener('click', function () {\n    clearLog();\n  });\ndocument\n  .getElementById('new_window_button')\n  .addEventListener('click', function () {\n    chrome.windows.create();\n  });\n"
  },
  {
    "path": "api-samples/tabs/pin/README.md",
    "content": "# chrome.tabs - Keyboard Pin\n\nA sample that demonstrates how to use the [`chrome.tabs`](https://developer.chrome.com/docs/extensions/reference/tabs/) API to toggle the pinned state of the current tab.\n\n## Overview\n\nIn this sample, a new keyboard shortcut (Alt + Shift + P) is enabled to pin the current tab.\n\n## Implementation Notes\n\nChrome fires [`chrome.commands.onCommand`](https://developer.chrome.com/docs/extensions/reference/commands/#event-onCommand) when the user presses a registered keyboard shortcut.\n\nCalls [`chrome.tabs.update()`](https://developer.chrome.com/docs/extensions/reference/tabs/#method-update) to pin or unpin the current tab.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Press Alt + Shift + P to pin the current tab.\n"
  },
  {
    "path": "api-samples/tabs/pin/manifest.json",
    "content": "{\n  \"name\": \"Keyboard Pin\",\n  \"version\": \"0.3\",\n  \"description\": \"Uses the chrome.tabs API to toggle the pinned state of the current tab.\",\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"commands\": {\n    \"toggle-pin\": {\n      \"suggested_key\": {\n        \"default\": \"Alt+Shift+P\"\n      },\n      \"description\": \"Toggle tab pin\"\n    }\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/tabs/pin/service-worker.js",
    "content": "chrome.commands.onCommand.addListener(async function (command) {\n  if (command == 'toggle-pin') {\n    // Get the currently selected tab\n    const tabs = await chrome.tabs.query({ active: true, currentWindow: true });\n    // Toggle the pinned status\n    const current = tabs[0];\n    chrome.tabs.update(current.id, { pinned: !current.pinned });\n  }\n});\n"
  },
  {
    "path": "api-samples/tabs/screenshot/README.md",
    "content": "# chrome.tabs - Tab Screenshot\n\nA sample that demonstrates how to use the [`chrome.tabs`](https://developer.chrome.com/docs/extensions/reference/tabs/) API to take a screenshot of the current tab.\n\n## Overview\n\nWhen the user clicks the action icon, the extension takes a screenshot of the current tab and displays it in a new tab.\n\n## Implementation Notes\n\nCalls [`chrome.tabs.captureVisibleTab()`](https://developer.chrome.com/docs/extensions/reference/tabs/#method-captureVisibleTab) to capture the visible area of the current tab.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension's icon to take a screenshot of the current tab.\n"
  },
  {
    "path": "api-samples/tabs/screenshot/manifest.json",
    "content": "{\n  \"name\": \"Test Screenshot Extension\",\n  \"version\": \"1.3\",\n  \"description\": \"Uses the chrome.tabs API to take a screenshot of the active tab.\",\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"action\": {\n    \"default_icon\": \"camera.png\",\n    \"default_title\": \"Take a screen shot!\"\n  },\n  \"permissions\": [\"activeTab\"],\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/tabs/screenshot/screenshot.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Tab Screenshot</title>\n  </head>\n\n  <body>\n    Image here:\n    <p>\n      <img\n        id=\"target\"\n        src=\"white.png\"\n        height=\"480\"\n        style=\"border: black solid 1px\"\n      />\n    </p>\n\n    <script src=\"screenshot.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/tabs/screenshot/screenshot.js",
    "content": "function setScreenshotUrl(url) {\n  document.getElementById('target').src = url;\n}\n\nchrome.runtime.onMessage.addListener(function (request) {\n  if (request.msg === 'screenshot') {\n    setScreenshotUrl(request.data);\n  }\n});\n"
  },
  {
    "path": "api-samples/tabs/screenshot/service-worker.js",
    "content": "// Listen for a click on the camera icon. On that click, take a screenshot.\nchrome.action.onClicked.addListener(async function () {\n  const screenshotUrl = await chrome.tabs.captureVisibleTab();\n  const viewTabUrl = chrome.runtime.getURL('screenshot.html');\n  let targetId = null;\n\n  chrome.tabs.onUpdated.addListener(function listener(tabId, changedProps) {\n    // We are waiting for the tab we opened to finish loading.\n    // Check that the tab's id matches the tab we opened,\n    // and that the tab is done loading.\n    if (tabId != targetId || changedProps.status != 'complete') return;\n\n    // Passing the above test means this is the event we were waiting for.\n    // There is nothing we need to do for future onUpdated events, so we\n    // use removeListner to stop getting called when onUpdated events fire.\n    chrome.tabs.onUpdated.removeListener(listener);\n\n    // Send screenshotUrl to the tab.\n    chrome.tabs.sendMessage(tabId, { msg: 'screenshot', data: screenshotUrl });\n  });\n\n  const tab = await chrome.tabs.create({ url: viewTabUrl });\n  targetId = tab.id;\n});\n"
  },
  {
    "path": "api-samples/tabs/zoom/README.md",
    "content": "# chrome.tabs - Tab zoom\n\nA sample that demonstrates how to use the zoom features of the [`chrome.tabs`](https://developer.chrome.com/docs/extensions/reference/tabs/) API.\n\n## Overview\n\nIn this sample, the zoom related [`chrome.tabs`](https://developer.chrome.com/docs/extensions/reference/tabs/) APIs are used to change the magnification and zoom mode of the active tab.\n\n## Implementation Notes\n\n- [`chrome.tabs.getZoom()`](https://developer.chrome.com/docs/extensions/reference/tabs/#method-getZoom) returns the current zoom level of the tab.\n- [`chrome.tabs.setZoom()`](https://developer.chrome.com/docs/extensions/reference/tabs/#method-setZoom) changes the zoom level of the tab.\n- [`chrome.tabs.setZoomSettings()`](https://developer.chrome.com/docs/extensions/reference/tabs/#method-setZoomSettings) sets the zoom settings of the tab.\n- [`chrome.tabs.getZoomSettings()`](https://developer.chrome.com/docs/extensions/reference/tabs/#method-getZoomSettings) returns the zoom settings of the tab.\n- [`chrome.tabs.onZoomChange()`](https://developer.chrome.com/docs/extensions/reference/tabs/#event-onZoomChange) listens for zoom changes in the tab.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Open any website, such as `https://google.com` in a new tab, and then click the extension icon to open the popup.\n"
  },
  {
    "path": "api-samples/tabs/zoom/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Tabs zoom API Demo\",\n  \"description\": \"Uses the tabs.zoom API to manipulate the zoom level of the current tab.\",\n  \"version\": \"0.1\",\n  \"icons\": {\n    \"16\": \"zoom16.png\",\n    \"48\": \"zoom48.png\"\n  },\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"action\": {\n    \"default_icon\": \"zoom19.png\",\n    \"default_title\": \"Zoom Extension Demo\",\n    \"default_popup\": \"popup.html\"\n  }\n}\n"
  },
  {
    "path": "api-samples/tabs/zoom/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Tab Zoom Extension</title>\n    <style>\n      body {\n        width: 150px;\n        overflow-x: hidden;\n        color: #ffff00;\n        background-color: #186464;\n      }\n\n      img {\n        margin: 5px;\n        border: 2px solid black;\n        vertical-align: middle;\n        width: 19px;\n        height: 19px;\n      }\n    </style>\n  </head>\n\n  <body>\n    <div style=\"text-align: center\">\n      <table style=\"margin: 0px auto\">\n        <tr>\n          <td><button type=\"button\" id=\"decreaseButton\">-</button></td>\n          <td>\n            <div\n              style=\"width: 50px; border-style: solid; border-width: 1px\"\n              id=\"displayDiv\"\n            >\n              100%\n            </div>\n          </td>\n          <td><button type=\"button\" id=\"increaseButton\">+</button></td>\n        </tr>\n      </table>\n      <button type=\"button\" id=\"defaultButton\">Reset to Default</button>\n      <div id=\"defaultLabel\"></div>\n    </div>\n    <p></p>\n    <div\n      style=\"\n        border-width: 2px;\n        border-style: solid;\n        border-color: #7f0000;\n        padding: 2px;\n      \"\n    >\n      <form\n        style=\"border-width: 2px; border-style: solid; border-color: #7f0000\"\n      >\n        <b>Mode:</b><br />\n        <input type=\"radio\" name=\"modeRadio\" value=\"automatic\" />automatic<br />\n        <input type=\"radio\" name=\"modeRadio\" value=\"manual\" />manual<br />\n        <input type=\"radio\" name=\"modeRadio\" value=\"disabled\" />disabled\n      </form>\n      <br />\n      <form\n        style=\"border-width: 2px; border-style: solid; border-color: #7f0000\"\n      >\n        <b>Scope:</b><br />\n        <input\n          type=\"radio\"\n          name=\"scopeRadio\"\n          value=\"per-origin\"\n        />per-origin<br />\n        <input type=\"radio\" name=\"scopeRadio\" value=\"per-tab\" />per-tab\n      </form>\n      <button type=\"button\" id=\"setModeButton\">Set Zoom Settings</button>\n    </div>\n    <p>\n      <button type=\"button\" id=\"closeButton\">Close</button>\n    </p>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/tabs/zoom/popup.js",
    "content": "/**\n * @fileoverview This code supports the popup behaviour of the extension, and\n *               demonstrates how to:\n *\n *               1) Set the zoom for a tab using tabs.setZoom()\n *               2) Read the current zoom of a tab using tabs.getZoom()\n *               3) Set the zoom mode of a tab using tabs.setZoomSettings()\n *               4) Read the current zoom mode of a tab using\n *               tabs.getZoomSettings()\n *\n *               It also demonstrates using a zoom change listener to update the\n *               contents of a control.\n */\n\nconst zoomStep = 1.1;\nlet tabId = -1;\n\nfunction displayZoomLevel(level) {\n  const percentZoom = parseFloat(level) * 100;\n  const zoom_percent_str = percentZoom.toFixed(1) + '%';\n\n  document.getElementById('displayDiv').textContent = zoom_percent_str;\n}\n\ndocument.addEventListener('DOMContentLoaded', async function () {\n  // Find the tabId of the current (active) tab. We could just omit the tabId\n  // parameter in the function calls below, and they would act on the current\n  // tab by default, but for the purposes of this demo we will always use the\n  // API with an explicit tabId to demonstrate its use.\n  const tabs = await chrome.tabs.query({ active: true });\n  if (tabs.length > 1)\n    console.log(\n      '[ZoomDemoExtension] Query unexpectedly returned more than 1 tab.'\n    );\n  tabId = tabs[0].id;\n\n  const zoomSettings = await chrome.tabs.getZoomSettings(tabId);\n  const modeRadios = document.getElementsByName('modeRadio');\n  for (let i = 0; i < modeRadios.length; i++) {\n    if (modeRadios[i].value == zoomSettings.mode) modeRadios[i].checked = true;\n  }\n\n  const scopeRadios = document.getElementsByName('scopeRadio');\n  for (let i = 0; i < scopeRadios.length; i++) {\n    if (scopeRadios[i].value == zoomSettings.scope)\n      scopeRadios[i].checked = true;\n  }\n\n  const percentDefaultZoom = parseFloat(zoomSettings.defaultZoomFactor) * 100;\n  document.getElementById('defaultLabel').textContent =\n    'Default: ' + percentDefaultZoom.toFixed(1) + '%';\n\n  const zoomFactor = await chrome.tabs.getZoom(tabId);\n  displayZoomLevel(zoomFactor);\n\n  document.getElementById('increaseButton').onclick = doZoomIn;\n  document.getElementById('decreaseButton').onclick = doZoomOut;\n  document.getElementById('defaultButton').onclick = doZoomDefault;\n  document.getElementById('setModeButton').onclick = doSetMode;\n  document.getElementById('closeButton').onclick = doClose;\n});\n\nfunction zoomChangeListener(zoomChangeInfo) {\n  displayZoomLevel(zoomChangeInfo.newZoomFactor);\n}\n\nchrome.tabs.onZoomChange.addListener(zoomChangeListener);\n\nfunction errorHandler(error) {\n  console.log('[ZoomDemoExtension] ' + error.message);\n}\n\nasync function changeZoomByFactorDelta(factorDelta) {\n  if (tabId == -1) return;\n\n  const zoomFactor = await chrome.tabs.getZoom(tabId);\n  const newZoomFactor = factorDelta * zoomFactor;\n  chrome.tabs.setZoom(tabId, newZoomFactor).catch(errorHandler);\n}\n\nfunction doZoomIn() {\n  changeZoomByFactorDelta(zoomStep);\n}\n\nfunction doZoomOut() {\n  changeZoomByFactorDelta(1.0 / zoomStep);\n}\n\nfunction doZoomDefault() {\n  if (tabId == -1) return;\n\n  chrome.tabs.setZoom(tabId, 0).catch(errorHandler);\n}\n\nfunction doSetMode() {\n  if (tabId == -1) return;\n\n  let modeVal;\n  const modeRadios = document.getElementsByName('modeRadio');\n  for (let i = 0; i < modeRadios.length; i++) {\n    if (modeRadios[i].checked) modeVal = modeRadios[i].value;\n  }\n\n  let scopeVal;\n  const scopeRadios = document.getElementsByName('scopeRadio');\n  for (let i = 0; i < scopeRadios.length; i++) {\n    if (scopeRadios[i].checked) scopeVal = scopeRadios[i].value;\n  }\n\n  if (!modeVal || !scopeVal) {\n    console.log(\n      '[ZoomDemoExtension] Must specify values for both mode & scope.'\n    );\n    return;\n  }\n\n  chrome.tabs\n    .setZoomSettings(tabId, { mode: modeVal, scope: scopeVal })\n    .catch(errorHandler);\n}\n\nfunction doClose() {\n  self.close();\n}\n"
  },
  {
    "path": "api-samples/tabs/zoom/service-worker.js",
    "content": "/**\n * @fileoverview In this extension, the background script demonstrates how to\n *               listen for zoom change events.\n */\n\nfunction zoomChangeListener(zoomChangeInfo) {\n  const settings_str =\n    'mode:' +\n    zoomChangeInfo.zoomSettings.mode +\n    ', scope:' +\n    zoomChangeInfo.zoomSettings.scope;\n\n  console.log(\n    '[ZoomDemoExtension] zoomChangeListener(tab=' +\n      zoomChangeInfo.tabId +\n      ', new=' +\n      zoomChangeInfo.newZoomFactor +\n      ', old=' +\n      zoomChangeInfo.oldZoomFactor +\n      ', ' +\n      settings_str +\n      ')'\n  );\n}\n\nchrome.tabs.onZoomChange.addListener(zoomChangeListener);\n"
  },
  {
    "path": "api-samples/topSites/basic/README.md",
    "content": "# chrome.topSites - Basic\n\nThis sample demonstrates using the `chrome.topSites` API to get the user's most visited sites.\n\n## Overview\n\nThe extension uses `chrome.topSites.get` to get the user's most visited sites, and then renders them in the popup.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension's action icon.\n"
  },
  {
    "path": "api-samples/topSites/basic/manifest.json",
    "content": "{\n  \"name\": \"Top Sites\",\n  \"version\": \"1.2\",\n  \"description\": \"Uses the chrome.topSites API to get the user's most visited sites.\",\n  \"permissions\": [\"topSites\"],\n  \"action\": {\n    \"default_icon\": \"icon.png\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/topSites/basic/popup.html",
    "content": "<!doctype html>\n<html>\n  <body>\n    <h2 style=\"width: 300px\">Most Visited:</h2>\n    <div id=\"mostVisited_div\"></div>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/topSites/basic/popup.js",
    "content": "// Event listener for clicks on links in an action popup.\n// Open the link in a new tab of the current window.\nfunction onAnchorClick(event) {\n  chrome.tabs.create({ url: event.target.href });\n  return false;\n}\n\n// Given an array of URLs, build a DOM list of these URLs in the action popup.\nfunction buildPopupDom(mostVisitedURLs) {\n  const popupDiv = document.getElementById('mostVisited_div');\n  const ol = popupDiv.appendChild(document.createElement('ol'));\n\n  for (let i = 0; i < mostVisitedURLs.length; i++) {\n    const li = ol.appendChild(document.createElement('li'));\n    const a = li.appendChild(document.createElement('a'));\n    a.href = mostVisitedURLs[i].url;\n    a.appendChild(document.createTextNode(mostVisitedURLs[i].title));\n    a.addEventListener('click', onAnchorClick);\n  }\n}\n\nwindow.onload = async () => {\n  const mostVisitedURLs = await chrome.topSites.get();\n  buildPopupDom(mostVisitedURLs);\n};\n"
  },
  {
    "path": "api-samples/topSites/magic8ball/README.md",
    "content": "# chrome.topSites - New Tab Page\n\nThis sample demonstrates using the `chrome.topSites` API to suggest which sites a user should visit.\n\n## Overview\n\nThe extension replaces the user's new tab page, and uses `chrome.topSites.get` to display a link to a site to visit.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Enable the extension and open a new tab.\n"
  },
  {
    "path": "api-samples/topSites/magic8ball/manifest.json",
    "content": "{\n  \"name\": \"topSites API sample\",\n  \"version\": \"2\",\n  \"description\": \"Uses the chrome.topSites API to suggest which sites a user should visit.\",\n  \"chrome_url_overrides\": {\n    \"newtab\": \"newTab.html\"\n  },\n  \"permissions\": [\"topSites\", \"favicon\"],\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/topSites/magic8ball/newTab.css",
    "content": "/* Copyright (c) 2012 The Chromium Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\nhtml {\n  background-color: #ddd;\n}\n\n#spacer {\n  height: 200px;\n}\n\n#title {\n  color: #555;\n  font-weight: bold;\n  height: 200px;\n  vertical-align: middle;\n}\n\n#mostVisitedThumb {\n  background-repeat: no-repeat;\n  height: 200px;\n  margin-left: 20px;\n  padding-left: 20px;\n  vertical-align: middle;\n  width: 212px;\n}\n"
  },
  {
    "path": "api-samples/topSites/magic8ball/newTab.html",
    "content": "<!doctype html>\n<!--\n Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n\n<html>\n  <meta charset=\"utf-8\" />\n  <script src=\"newTab.js\"></script>\n  <link rel=\"stylesheet\" href=\"newTab.css\" />\n\n  <title>New 8ball</title>\n\n  <body>\n    <center>\n      <div id=\"spacer\"></div>\n      <span id=\"title\">Magic 8 ball says to visit</span>\n      <a id=\"mostVisitedThumb\">\n        <span></span>\n      </a>\n    </center>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/topSites/magic8ball/newTab.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nfunction faviconURL(u) {\n  const url = new URL(chrome.runtime.getURL('/_favicon/'));\n  url.searchParams.set('pageUrl', u); // this encodes the URL as well\n  url.searchParams.set('size', '16');\n  return url.toString();\n}\n\nfunction thumbnailsGotten(data) {\n  let eightBallWindow = document.getElementById('mostVisitedThumb');\n  let rand = Math.floor(Math.random() * data.length);\n  eightBallWindow.href = data[rand].url;\n  eightBallWindow.textContent = data[rand].title;\n  eightBallWindow.style.backgroundImage =\n    'url(' + faviconURL(data[rand].url) + ')';\n}\n\nwindow.onload = function () {\n  chrome.topSites.get(thumbnailsGotten);\n};\n"
  },
  {
    "path": "api-samples/userScripts/README.md",
    "content": "# chrome.userScripts API\n\nThis sample demonstrates using the [`chrome.userScripts`](https://developer.chrome.com/docs/extensions/reference/scripting/) API to inject JavaScript into web pages.\n\n## Overview\n\nClicking this extension's action icon opens an options page.\n\n<img src=\"screenshot.png\" height=250 alt=\"Screenshot showing the chrome.userScripts API demo running in Chrome.\">\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension's action icon to open the options page.\n4. Once a user script has been configured, visit https://example.com/.\n\n## Features\n\nThis sample allows you to inject the following:\n\n- Files\n- Arbitrary code\n\n## Implementation Notes\n\nThe User Scripts API requires users to enabled developer mode. We check for this by attempting to access `chrome.userScripts`, which throws an error on property access if it is disabled.\n\nWhen a change is made on the options page, use the `chrome.userScripts` API to update the user script registration.\n"
  },
  {
    "path": "api-samples/userScripts/manifest.json",
    "content": "{\n  \"name\": \"User Scripts API Demo\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"minimum_chrome_version\": \"120\",\n  \"description\": \"Uses the chrome.userScripts API to inject JavaScript into web pages.\",\n  \"background\": {\n    \"service_worker\": \"sw.js\"\n  },\n  \"permissions\": [\"storage\", \"userScripts\"],\n  \"host_permissions\": [\"https://example.com/*\"],\n  \"action\": {},\n  \"options_ui\": {\n    \"page\": \"options.html\",\n    \"open_in_tab\": false\n  }\n}\n"
  },
  {
    "path": "api-samples/userScripts/options.css",
    "content": "/* \nCopyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nhtml {\n  padding: 0 10px;\n}\n\n#warning {\n  display: none;\n  margin-bottom: 30px;\n}\n\nlabel {\n  display: flex;\n  align-items: center;\n}\n\nlabel input {\n  margin-right: 10px;\n}\n\ntextarea {\n  resize: none;\n  width: calc(100% - 35px);\n  border: 2px solid black;\n  background: rgb(34, 34, 34);\n  padding: 15px;\n  color: white;\n}\n\ntextarea:focus {\n  border: 2px solid grey;\n  outline: none;\n}\n\nbutton {\n  margin: 20px 0;\n}\n\n/* Hide custom script textarea by default */\n#custom-script-wrapper {\n  display: none;\n}\n\n/* Only show custom script textarea when custom type is selected */\nform:has(input[name='type'][value='custom']:checked) #custom-script-wrapper {\n  display: block;\n}\n"
  },
  {
    "path": "api-samples/userScripts/options.html",
    "content": "<!--\n Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n\n<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>User Scripts API Demo</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"options.css\" />\n    <script defer src=\"options.js\"></script>\n  </head>\n  <body>\n    <div id=\"warning\">\n      <p>\n        ⚠️ To use the User Scripts API, you need to first enable developer mode\n        at <b>chrome://extensions</b>.\n      </p>\n      <a href=\"\">Reload</a>\n    </div>\n    <form id=\"settings-form\">\n      <h1>Settings</h1>\n      <h2>Type</h2>\n      <label>\n        <input type=\"radio\" name=\"type\" value=\"file\" />\n        <span>File</span>\n      </label>\n      <label>\n        <input type=\"radio\" name=\"type\" value=\"custom\" />\n        <span>Custom text</span>\n      </label>\n      <div id=\"custom-script-wrapper\">\n        <h2>Custom script</h2>\n        <textarea\n          name=\"custom-script\"\n          draggable=\"false\"\n          rows=\"8\"\n          placeholder=\"alert('hi');\"\n        ></textarea>\n      </div>\n      <button type=\"button\" id=\"save-button\">Save & Enable</button>\n    </form>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/userScripts/options.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst USER_SCRIPT_ID = 'default';\nconst SAVE_BUTTON_ID = 'save-button';\n\nconst FORM_ID = 'settings-form';\nconst FORM = document.getElementById(FORM_ID);\n\nconst TYPE_INPUT_NAME = 'type';\nconst SCRIPT_TEXTAREA_NAME = 'custom-script';\n\n/**\n * Checks if the user has developer mode enabled, which is required to use the\n * User Scripts API.\n *\n * @returns If the chrome.userScripts API is available.\n */\nfunction isUserScriptsAvailable() {\n  try {\n    // Property access which throws if developer mode is not enabled.\n    chrome.userScripts;\n    return true;\n  } catch {\n    // Not available, so hide UI and show error.\n    document.getElementById('warning').style.display = 'block';\n    FORM.style.display = 'none';\n    return false;\n  }\n}\n\nasync function updateUi() {\n  if (!isUserScriptsAvailable()) return;\n\n  // Access settings from storage with default values.\n  const { type, script } = await chrome.storage.local.get({\n    type: 'file',\n    script: \"alert('hi');\"\n  });\n\n  // Update UI with current values.\n  FORM.elements[TYPE_INPUT_NAME].value = type;\n  FORM.elements[SCRIPT_TEXTAREA_NAME].value = script;\n}\n\nasync function onSave() {\n  if (!isUserScriptsAvailable()) return;\n\n  // Get values from form.\n  const type = FORM.elements[TYPE_INPUT_NAME].value;\n  const script = FORM.elements[SCRIPT_TEXTAREA_NAME].value;\n\n  // Save to storage.\n  chrome.storage.local.set({\n    type,\n    script\n  });\n\n  const existingScripts = await chrome.userScripts.getScripts({\n    ids: [USER_SCRIPT_ID]\n  });\n\n  if (existingScripts.length > 0) {\n    // Update existing script.\n    await chrome.userScripts.update([\n      {\n        id: USER_SCRIPT_ID,\n        matches: ['https://example.com/*'],\n        js: type === 'file' ? [{ file: 'user-script.js' }] : [{ code: script }]\n      }\n    ]);\n  } else {\n    // Register new script.\n    await chrome.userScripts.register([\n      {\n        id: USER_SCRIPT_ID,\n        matches: ['https://example.com/*'],\n        js: type === 'file' ? [{ file: 'user-script.js' }] : [{ code: script }]\n      }\n    ]);\n  }\n}\n\n// Update UI immediately, and on any storage changes.\nupdateUi();\nchrome.storage.local.onChanged.addListener(updateUi);\n\n// Register listener for save button click.\ndocument.getElementById(SAVE_BUTTON_ID).addEventListener('click', onSave);\n"
  },
  {
    "path": "api-samples/userScripts/sw.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.runtime.onInstalled.addListener(({ reason }) => {\n  if (reason == chrome.runtime.OnInstalledReason.INSTALL) {\n    chrome.runtime.openOptionsPage();\n  }\n});\n\nchrome.action.onClicked.addListener(() => {\n  chrome.runtime.openOptionsPage();\n});\n"
  },
  {
    "path": "api-samples/userScripts/user-script.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nalert('Hello World!');\n"
  },
  {
    "path": "api-samples/web-accessible-resources/README.md",
    "content": "# Web Accessible Resources\n\nThis sample demonstrates using the [web_accessible_resources](https://developer.chrome.com/docs/extensions/mv3/manifest/web_accessible_resources/)\nkey in the manifest.json file to control access to assets within an extension.\n\n## Overview\n\nThis sample shows how image assets within an extension can be exposed to pages on the web.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Follow the instructions on the newly opened tab.\n"
  },
  {
    "path": "api-samples/web-accessible-resources/content-script.js",
    "content": "const imageIds = ['test2', 'test4'];\n\nconst loadButton = document.createElement('button');\nloadButton.innerText = 'Load images';\nloadButton.addEventListener('click', handleLoadRequest);\n\ndocument.querySelector('body').append(loadButton);\n\nfunction handleLoadRequest() {\n  for (const id of imageIds) {\n    const element = document.getElementById(id);\n    element.src = chrome.runtime.getURL(`${id}.png`);\n  }\n}\n"
  },
  {
    "path": "api-samples/web-accessible-resources/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Web Accessible Resources</title>\n    <style>\n      body {\n        font-family: Helvetica, Arial, sans-serif;\n        font-size: 14px;\n      }\n      table {\n        padding: 0;\n        border-collapse: collapse;\n      }\n      th {\n        background: hsl(0, 0%, 90%);\n        padding: 0.25em 0.5em;\n        text-align: left;\n      }\n      td {\n        padding: 0.25em 0.5em;\n        border-top: 1px solid hsl(0, 0%, 50%);\n      }\n    </style>\n  </head>\n  <body>\n    <h1>Web Accessible Resources Demo</h1>\n    <p>This demo shows off the core features of web accessible resources.</p>\n    <p>\n      In this demo we have 4 images (test1.png, etc.) that we want to expose on\n      2 different websites. Each website should only be able to load two\n      specific images, but both websites will attempt to access all 4 images. To\n      do this, we define a set of\n      <a\n        href=\"https://developer.chrome.com/docs/extensions/mv3/manifest/web_accessible_resources/\"\n        ><code>\"web_accessible_resources\"</code></a\n      >\n      in our <a href=\"manifest.json\">manifest.json</a>. This object specifies\n      what assets should be accessible to which external resources.\n    </p>\n\n    <p>\n      The first image on each site is statically referenced by the site using a\n      URL in the following format:\n      <code>chrome-extension://&lt;extension-id>/&lt;image-path></code>. The\n      second image on each site will only be injected into the page when you\n      click the \"Load images\" button for that page. This injection is performed\n      by using\n      <a\n        href=\"https://developer.chrome.com/docs/extensions/reference/runtime/#method-getURL\"\n        >chrome.runtime.getURL()</a\n      >\n      to build the image's URL at runtime.\n    </p>\n\n    <p>\n      The third example shows the second website again, but this time using the\n      `use_dynamic_urls` flag which only allows resources to be accessed through\n      a dynamic ID. The id is regenerated when the browser restarts or the\n      extension reloads.\n    </p>\n\n    <table>\n      <thead>\n        <tr>\n          <th>File</th>\n          <th>Target domain</th>\n          <th>Injection method</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>\n            <code><a href=\"test1.png\">test1.png</a></code>\n          </td>\n          <td>web-accessible-resources-1.glitch.me</td>\n          <td>Statically referenced</td>\n        </tr>\n        <tr>\n          <td>\n            <code><a href=\"test2.png\">test2.png</a></code>\n          </td>\n          <td>web-accessible-resources-1.glitch.me</td>\n          <td>Dynamically injected</td>\n        </tr>\n        <tr>\n          <td>\n            <code><a href=\"test3.png\">test3.png</a></code>\n          </td>\n          <td>web-accessible-resources-2.glitch.me</td>\n          <td>Statically referenced</td>\n        </tr>\n        <tr>\n          <td>\n            <code><a href=\"test4.png\">test4.png</a></code>\n          </td>\n          <td>web-accessible-resources-2.glitch.me</td>\n          <td>Dynamically injected</td>\n        </tr>\n        <tr>\n          <td>\n            <code><a href=\"test3.png\">test3.png</a></code>\n          </td>\n          <td>web-accessible-resources-3.glitch.me</td>\n          <td>Statically referenced with <code>use_dynamic_url</code></td>\n        </tr>\n        <tr>\n          <td>\n            <code><a href=\"test4.png\">test4.png</a></code>\n          </td>\n          <td>web-accessible-resources-3.glitch.me</td>\n          <td>Dynamically injected with <code>use_dynamic_url</code></td>\n        </tr>\n      </tbody>\n    </table>\n\n    <figure>\n      <figcaption>\n        https://web-accessible-resources-1.glitch.me/ can access images\n        <a href=\"test1.png\"><code>test1.png</code></a> and\n        <a href=\"test2.png\"><code>test2.png</code></a>\n      </figcaption>\n      <iframe\n        src=\"https://web-accessible-resources-1.glitch.me/\"\n        width=\"100%\"\n        height=\"200\"\n      ></iframe>\n    </figure>\n    <figure>\n      <figcaption>\n        https://web-accessible-resources-2.glitch.me/ can access images\n        <a href=\"test3.png\"><code>test3.png</code></a> and\n        <a href=\"test4.png\"><code>test4.png</code></a>\n      </figcaption>\n      <iframe\n        src=\"https://web-accessible-resources-2.glitch.me/\"\n        width=\"100%\"\n        height=\"200\"\n      ></iframe>\n    </figure>\n    <figure>\n      <figcaption>\n        https://web-accessible-resources-3.glitch.me/ can access image\n        <a href=\"test4.png\"><code>test4.png</code></a>\n      </figcaption>\n      <iframe\n        src=\"https://web-accessible-resources-3.glitch.me/\"\n        width=\"100%\"\n        height=\"200\"\n      ></iframe>\n    </figure>\n  </body>\n</html>\n"
  },
  {
    "path": "api-samples/web-accessible-resources/manifest.json",
    "content": "{\n  \"name\": \"Web Accessible Resources Demo\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"description\": \"Uses the web_accessible_resources key in the manifest.json file to control access to assets within an extension.\",\n  \"action\": {},\n  \"content_scripts\": [\n    {\n      \"matches\": [\n        \"https://web-accessible-resources-1.glitch.me/*\",\n        \"https://web-accessible-resources-2.glitch.me/*\",\n        \"https://web-accessible-resources-3.glitch.me/*\"\n      ],\n      \"all_frames\": true,\n      \"js\": [\"content-script.js\"]\n    }\n  ],\n  \"web_accessible_resources\": [\n    {\n      \"resources\": [\"test1.png\", \"test2.png\"],\n      \"matches\": [\"https://web-accessible-resources-1.glitch.me/*\"]\n    },\n    {\n      \"resources\": [\"test3.png\", \"test4.png\"],\n      \"matches\": [\"https://web-accessible-resources-2.glitch.me/*\"]\n    },\n    {\n      \"resources\": [\"test3.png\", \"test4.png\"],\n      \"matches\": [\"https://web-accessible-resources-3.glitch.me/*\"],\n      \"use_dynamic_url\": true\n    }\n  ],\n  \"key\": \"AAAAB3NzaC1yc2EAAAADAQABAAABAQCnCTnUK8jgYTxnQLdtE6QzkZgn3rZv0U1naCx4csdSDqYEBXgW2pR2m/uUIAU1HzAUfkDckqTezyIG1bPw8l5X8FyWfgMQANFgTPXGRNXTmDSqHcqvS7zvuEr0xF12oGLBKa7cdEsaQzdfDWsm5BlwFIPfPXUokaHEGvxPBjrXHQmx+Z4xAyhzNh+v5bFr63lsL0ysS8z4KVKc1G1lcUZnp7Oz9n0pZP9QW0Oei2KCumDqGpqVd249232a0E9TUeQ+lqAxiN4ybzBgUT5al7Yh1nIhGHxPyRnihtHmx+hxupCuhzXeaoKjWiADp+FEK/aPAzvP5ynLDQHelez/eGdF\"\n}\n"
  },
  {
    "path": "api-samples/web-accessible-resources/service-worker.js",
    "content": "chrome.runtime.onInstalled.addListener(({ reason }) => {\n  if (reason === chrome.runtime.OnInstalledReason.INSTALL) {\n    showReadme();\n  }\n});\n\nchrome.action.onClicked.addListener(() => {\n  showReadme();\n});\n\nfunction showReadme() {\n  chrome.tabs.create({ url: '/index.html' });\n}\n"
  },
  {
    "path": "api-samples/webNavigation/basic/README.md",
    "content": "# chrome.webNavigation\n\nThis sample demonstrates using the webNavigation API to send notifications.\n\n## Overview\n\nThe extension calls the `chrome.webNavigation.onCompleted.addListener()` event listener to trigger a notification whenever a the user navigates to a new webpage.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Navigate the web with notifications on.\n"
  },
  {
    "path": "api-samples/webNavigation/basic/manifest.json",
    "content": "{\n  \"name\": \"webNavigation API Sample\",\n  \"version\": \"2\",\n  \"description\": \"Uses the webNavigation API to send notifications.\",\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"permissions\": [\"webNavigation\", \"notifications\"],\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "api-samples/webNavigation/basic/service-worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.webNavigation.onCompleted.addListener((details) => {\n  chrome.notifications.create({\n    type: 'basic',\n    iconUrl: 'icon.png',\n    title: 'page loaded',\n    message:\n      'Completed loading: ' +\n      details.url +\n      ' at ' +\n      details.timeStamp +\n      ' milliseconds since the epoch.'\n  });\n});\n"
  },
  {
    "path": "api-samples/webRequest/http-auth/README.md",
    "content": "# webRequest.onAuthRequired\n\nThis sample demonstrates the `webRequest.onAuthRequired` listener to detect an authentication request and log the user into the designated site.\n\n## Overview\n\nWhen an authentication check is detected, a check is made to confirm that the request has come from the correct source. Account credentials are then provided for the response via an auth handler.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Open a new tab and navigate to <https://httpbin.org/basic-auth/guest/guest>. You will be prompted to enter a username and password. With this extension installed, the username and password will be automatically provided.\n"
  },
  {
    "path": "api-samples/webRequest/http-auth/manifest.json",
    "content": "{\n  \"name\": \"webRequest.onAuthRequired Demo\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"description\": \"Demonstrates the webRequest.onAuthRequired listener to detect an authentication request and log the user into the designated site.\",\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"permissions\": [\"webRequest\", \"webRequestAuthProvider\"],\n  \"host_permissions\": [\"https://httpbin.org/*\"]\n}\n"
  },
  {
    "path": "api-samples/webRequest/http-auth/service-worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Provides credentials when an HTTP Basic Auth request is received.\nchrome.webRequest.onAuthRequired.addListener(\n  (details, callback) => {\n    console.log('An authorization request has been detected');\n    if (details.url == 'https://httpbin.org/basic-auth/guest/guest') {\n      // Creating some credentials\n      const username = 'guest';\n      const password = 'guest';\n      // Creating an auth handler to use the credentials\n      const authCredentials = {\n        authCredentials: {\n          username: username,\n          password: password\n        }\n      };\n      callback(authCredentials);\n    }\n  },\n  { urls: ['https://httpbin.org/basic-auth/guest/guest'] },\n  ['asyncBlocking']\n);\n"
  },
  {
    "path": "api-samples/windows/README.md",
    "content": "# chrome.windows\n\nThis sample demonstrates using the `chrome.windows` and `chrome.tabs` API to manage tabs across different windows.\n\n## Overview\n\nThe extension interates across all tabs and moves them to the currently active window.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Make sure you have multiple windows of chrome open.\n4. Pin the extension and click on the action button.\n"
  },
  {
    "path": "api-samples/windows/background.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nasync function start() {\n  const current = await chrome.windows.getCurrent();\n\n  const allTabs = await chrome.tabs.query({});\n  allTabs.forEach((tab) => {\n    if (tab.windowId != current.id) {\n      chrome.tabs.move(tab.id, {\n        windowId: current.id,\n        index: tab.index\n      });\n    }\n  });\n}\n\n// Set up a click handler so that we can merge all the windows.\nchrome.action.onClicked.addListener(start);\n"
  },
  {
    "path": "api-samples/windows/manifest.json",
    "content": "{\n  \"name\": \"Merge Windows\",\n  \"version\": \"1.0.3\",\n  \"description\": \"Uses the chrome.windows and chrome.tabs APIs to manage tabs across different windows.\",\n  \"icons\": {\n    \"48\": \"merge_windows_48.png\",\n    \"128\": \"merge_windows_128.png\"\n  },\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"action\": {\n    \"default_icon\": \"arrow_in.png\",\n    \"default_title\": \"Merge Windows\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "eslint.config.js",
    "content": "const js = require('@eslint/js');\nconst globals = require('globals');\n\nconst prettier = require('eslint-plugin-prettier');\nconst eslintPluginPrettierRecommended = require('eslint-plugin-prettier/recommended');\n\nconst jest = require('eslint-plugin-jest');\n\nmodule.exports = [\n  js.configs.recommended,\n  eslintPluginPrettierRecommended,\n  {\n    plugins: {\n      prettier\n    },\n    rules: {\n      'prettier/prettier': ['error'],\n      'no-var': ['error'],\n      'no-unused-vars': [\n        'warn',\n        {\n          argsIgnorePattern: '^_',\n          varsIgnorePattern: '^_'\n        }\n      ]\n    },\n    languageOptions: {\n      ecmaVersion: 'latest',\n      sourceType: 'module',\n      globals: {\n        ...globals.browser,\n        ...globals.webextensions,\n        ...globals.es2021,\n        ...globals.jquery,\n        ...globals.serviceworker\n      }\n    }\n  },\n  {\n    files: [\n      'functional-samples/tutorial.puppeteer/**/*',\n      'functional-samples/tutorial.terminate-sw/**/*'\n    ],\n    plugins: { jest },\n    rules: {\n      ...jest.configs['flat/recommended'].rules\n    },\n    languageOptions: {\n      globals: {\n        ...globals.jest\n      }\n    },\n    settings: {\n      jest: {\n        version: '29.7.0'\n      }\n    }\n  },\n  {\n    // Ignores must be in a separate block to apply globally:\n    // https://eslint.org/docs/latest/use/configure/configuration-files#globally-ignoring-files-with-ignores\n    ignores: [\n      'eslint.config.js',\n      '.repo/**/*',\n      '_archive/**/*',\n      '**/third-party/**',\n      '**/node_modules/**/*',\n      '**/dist/**/*',\n      // These are autogenerated files that we shouldn't lint\n      'functional-samples/cookbook.wasm-helloworld-print/wasm/pkg/**/*',\n      'functional-samples/cookbook.wasm-helloworld-print-nomodule/wasm/pkg/**/*'\n    ]\n  }\n];\n"
  },
  {
    "path": "functional-samples/ai.gemini-in-the-cloud/.gitignore",
    "content": "dist\n"
  },
  {
    "path": "functional-samples/ai.gemini-in-the-cloud/README.md",
    "content": "# Using the Gemini API in a Chrome Extension.\n\nThis sample demonstrates how to use the Gemini Cloud API in a Chrome Extension.\n\n## Overview\n\nThe extension provides a chat interface for the Gemini API. To learn more about the API head over to [https://ai.google.dev/](https://ai.google.dev/).\n\n## Running this extension\n\n1. Clone this repository.\n2. Download the Gemini API client by running:\n   ```sh\n   npm install\n   ```\n3. [Retrieve an API key](https://ai.google.dev/gemini-api/docs/api-key) and update [functional-samples/ai.gemini-in-the-cloud/sidepanel/index.js](functional-samples/ai.gemini-in-the-cloud/sidepanel/index.js) (only for testing).\n4. Compile the JS bundle for the sidepanel implementation by running:\n   ```sh\n   npm run build\n   ```\n5. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n6. Click the extension icon.\n7. Interact with the prompt API in the sidebar.\n"
  },
  {
    "path": "functional-samples/ai.gemini-in-the-cloud/background.js",
    "content": "chrome.sidePanel\n  .setPanelBehavior({ openPanelOnActionClick: true })\n  .catch((error) => console.error(error));\n"
  },
  {
    "path": "functional-samples/ai.gemini-in-the-cloud/manifest.json",
    "content": "{\n  \"name\": \"Google Gemini Demo\",\n  \"version\": \"0.1\",\n  \"manifest_version\": 3,\n  \"description\": \"Try the Gemini Models.\",\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"permissions\": [\"sidePanel\"],\n  \"side_panel\": {\n    \"default_path\": \"sidepanel/index.html\"\n  },\n  \"action\": {\n    \"default_icon\": {\n      \"16\": \"images/icon16.png\",\n      \"32\": \"images/icon32.png\",\n      \"48\": \"images/icon48.png\",\n      \"128\": \"images/icon128.png\"\n    },\n    \"default_title\": \"Open Chat Interface\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-in-the-cloud/package.json",
    "content": "{\n  \"name\": \"Chrome Extensions Gemini Demo\",\n  \"version\": \"1.0\",\n  \"scripts\": {\n    \"build\": \"rollup sidepanel/index.js --file dist/sidepanel.bundle.js --format iife\"\n  },\n  \"private\": true,\n  \"devDependencies\": {\n    \"@google/genai\": \"^1.36.0\",\n    \"rollup\": \"4.22.4\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-in-the-cloud/sidepanel/index.css",
    "content": "body {\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica,\n    Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';\n  color: #1f1f1f;\n  background-color: #f2f2f2;\n  font-size: 16px;\n  padding: 8px;\n}\n\ninput,\nbutton,\ntextarea,\nselect {\n  font-family: inherit;\n  font-size: inherit;\n}\n\nbutton {\n  background: #333;\n  color: white;\n  border-radius: 8px;\n  border: none;\n  min-width: 100px;\n  padding: 8px;\n  margin: 16px 0;\n  cursor: pointer;\n}\n\nbutton.primary {\n  background: #333;\n  color: white;\n}\n\nbutton.secondary {\n  background: #ccc;\n  color: black;\n}\n\nbutton[disabled] {\n  background: #ddd;\n  color: #aaa;\n}\n\ninput[type='range'] {\n  margin-top: 16px;\n  accent-color: black;\n}\n\ntextarea {\n  --padding: 32px;\n  width: calc(100% - var(--padding));\n  max-width: calc(100% - var(--padding));\n}\n\n.text,\ntextarea {\n  background-color: white;\n  padding: 16px;\n  border-radius: 16px;\n  box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px, rgb(51, 51, 51) 0px 0px 0px 3px;\n  outline: none;\n}\n\n.blink {\n  animation: 1s ease-in-out 1s infinite reverse both running blink;\n}\n\n@keyframes blink {\n  25% {\n    opacity: 0.5;\n  }\n  50% {\n    opacity: 0;\n  }\n  75% {\n    opacity: 0.5;\n  }\n}\n\n[hidden] {\n  display: none;\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-in-the-cloud/sidepanel/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"index.css\" />\n  </head>\n  <body>\n    <h1>Google Gemini</h1>\n    <textarea\n      id=\"input-prompt\"\n      placeholder='Type something, e.g. \"Write a haiku about Chrome Extensions\"'\n      cols=\"30\"\n      rows=\"5\"\n    ></textarea>\n    <div>\n      <input\n        type=\"range\"\n        id=\"temperature\"\n        name=\"temperature\"\n        min=\"0\"\n        max=\"2\"\n        step=\"0.01\"\n        value=\"1\"\n      />\n      <label for=\"temperature\"\n        >Temperature: <span id=\"label-temperature\">1</span></label\n      >\n    </div>\n    <button id=\"button-prompt\" class=\"primary\" disabled>Run</button>\n    <div id=\"response\" class=\"text\" hidden></div>\n    <div id=\"loading\" class=\"text\" hidden><span class=\"blink\">...</span></div>\n    <div id=\"error\" class=\"text\" hidden></div>\n    <script src=\"../dist/sidepanel.bundle.js\" type=\"module\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/ai.gemini-in-the-cloud/sidepanel/index.js",
    "content": "import { GoogleGenAI } from '../node_modules/@google/genai/dist/index.mjs';\n\n// Important! Do not expose your API in your extension code. You have to\n// options:\n//\n// 1. Let users provide their own API key.\n// 2. Manage API keys in your own server and proxy all calls to the Gemini\n// API through your own server, where you can implement additional security\n// measures such as authentification.\n//\n// It is only OK to put your API key into this file if you're the only\n// user of your extension or for testing.\nconst apiKey = '...';\n\nlet genAI = null;\nlet generationConfig = {\n  temperature: 1\n};\n\nconst inputPrompt = document.body.querySelector('#input-prompt');\nconst buttonPrompt = document.body.querySelector('#button-prompt');\nconst elementResponse = document.body.querySelector('#response');\nconst elementLoading = document.body.querySelector('#loading');\nconst elementError = document.body.querySelector('#error');\nconst sliderTemperature = document.body.querySelector('#temperature');\nconst labelTemperature = document.body.querySelector('#label-temperature');\n\nasync function runPrompt(prompt, config) {\n  try {\n    const response = await genAI.models.generateContent({\n      model: 'gemini-2.5-flash',\n      contents: prompt,\n      config: {\n        safetySettings: [\n          {\n            category: 'HARM_CATEGORY_DANGEROUS_CONTENT',\n            threshold: 'BLOCK_NONE'\n          }\n        ],\n        temperature: config.temperature\n      }\n    });\n    return response.text;\n  } catch (e) {\n    console.log('Prompt failed');\n    console.error(e);\n    console.log('Prompt:', prompt);\n    throw e;\n  }\n}\n\nsliderTemperature.addEventListener('input', (event) => {\n  labelTemperature.textContent = event.target.value;\n  generationConfig.temperature = event.target.value;\n});\n\ninputPrompt.addEventListener('input', () => {\n  if (inputPrompt.value.trim()) {\n    buttonPrompt.removeAttribute('disabled');\n  } else {\n    buttonPrompt.setAttribute('disabled', '');\n  }\n});\n\nbuttonPrompt.addEventListener('click', async () => {\n  const prompt = inputPrompt.value.trim();\n  showLoading();\n  try {\n    const config = {\n      temperature: parseFloat(sliderTemperature.value)\n    };\n    genAI = new GoogleGenAI({ apiKey });\n    const response = await runPrompt(prompt, config);\n    showResponse(response);\n  } catch (e) {\n    showError(e);\n  }\n});\n\nfunction showLoading() {\n  hide(elementResponse);\n  hide(elementError);\n  show(elementLoading);\n}\n\nfunction showResponse(response) {\n  hide(elementLoading);\n  show(elementResponse);\n  // Make sure to preserve line breaks in the response\n  elementResponse.textContent = '';\n  const paragraphs = response.split(/\\r?\\n/);\n  for (let i = 0; i < paragraphs.length; i++) {\n    const paragraph = paragraphs[i];\n    if (paragraph) {\n      elementResponse.appendChild(document.createTextNode(paragraph));\n    }\n    // Don't add a new line after the final paragraph\n    if (i < paragraphs.length - 1) {\n      elementResponse.appendChild(document.createElement('BR'));\n    }\n  }\n}\n\nfunction showError(error) {\n  show(elementError);\n  hide(elementResponse);\n  hide(elementLoading);\n  elementError.textContent = error;\n}\n\nfunction show(element) {\n  element.removeAttribute('hidden');\n}\n\nfunction hide(element) {\n  element.setAttribute('hidden', '');\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device/.gitignore",
    "content": "dist\nnode_modules\n*.swp\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device/README.md",
    "content": "# On-device AI with Gemini Nano\n\nThis sample demonstrates how to use the Gemini Nano prompt API in Chrome Extensions. To learn more about the API, head over to [Built-in AI on developer.chrome.com](https://developer.chrome.com/docs/extensions/ai/prompt-api).\n\n## Overview\n\nThe extension provides a chat interface using the Prompt API with Chrome's built-in Gemini Nano model.\n\n## Running this extension\n\n1. Clone this repository.\n1. Run `npm install` in the project directory.\n1. Run `npm run build` in the project directory to build the extension.\n1. Load the newly created `dist` directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world#load-unpacked).\n1. Click the extension icon.\n1. Interact with the Prompt API in the sidebar.\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device/background.js",
    "content": "chrome.runtime.onInstalled.addListener(({ reason }) => {\n  if (reason === 'install') {\n    chrome.sidePanel\n      .setPanelBehavior({ openPanelOnActionClick: true })\n      .catch((error) => console.error(error));\n  }\n});\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device/manifest.json",
    "content": "{\n  \"name\": \"Chrome Prompt AI Demo\",\n  \"version\": \"0.2\",\n  \"manifest_version\": 3,\n  \"description\": \"Try Chrome's built-in prompt API built with Gemini Nano.\",\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"permissions\": [\"sidePanel\"],\n  \"minimum_chrome_version\": \"138\",\n  \"side_panel\": {\n    \"default_path\": \"sidepanel/index.html\"\n  },\n  \"action\": {\n    \"default_icon\": {\n      \"16\": \"images/icon16.png\",\n      \"32\": \"images/icon32.png\",\n      \"48\": \"images/icon48.png\",\n      \"128\": \"images/icon128.png\"\n    },\n    \"default_title\": \"Open Chat Interface\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device/package.json",
    "content": "{\n  \"name\": \"Chrome Prompt API Example\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"background.js\",\n  \"scripts\": {\n    \"build\": \"rollup -c rollup.config.mjs\"\n  },\n  \"keywords\": [],\n  \"license\": \"Apache 2.0\",\n  \"devDependencies\": {\n    \"dompurify\": \"3.2.4\",\n    \"marked\": \"14.1.2\",\n    \"@rollup/plugin-commonjs\": \"26.0.1\",\n    \"@rollup/plugin-node-resolve\": \"15.2.3\",\n    \"rollup\": \"4.22.4\",\n    \"rollup-plugin-copy\": \"3.5.0\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device/privacy.txt",
    "content": "This extension does not collect, use or share any user data.\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device/rollup.config.mjs",
    "content": "import { nodeResolve } from '@rollup/plugin-node-resolve';\nimport commonjs from '@rollup/plugin-commonjs';\nimport copy from 'rollup-plugin-copy';\n\nexport default [\n  {\n    input: 'sidepanel/index.js',\n    output: {\n      dir: 'dist/sidepanel',\n      format: 'iife',\n    },\n    plugins: [\n      nodeResolve({\n        jsnext: true,\n        main: true,\n        browser: true\n      }),\n      commonjs(),\n      copy({\n        targets: [\n          {\n            src: ['manifest.json', 'background.js', 'sidepanel', 'images'],\n            dest: 'dist'\n          }\n        ]\n      })\n    ]\n  }\n];\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device/sidepanel/index.css",
    "content": "body {\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica,\n    Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';\n  color: #1f1f1f;\n  background-color: #f2f2f2;\n  font-size: 16px;\n  padding: 8px;\n}\n\ninput,\nbutton,\ntextarea,\nselect {\n  font-family: inherit;\n  font-size: inherit;\n}\n\nbutton {\n  background: #333;\n  color: white;\n  border-radius: 8px;\n  border: none;\n  min-width: 100px;\n  padding: 8px;\n  margin: 16px 0;\n  cursor: pointer;\n}\n\nbutton.primary {\n  background: #333;\n  color: white;\n}\n\nbutton.secondary {\n  background: #ccc;\n  color: black;\n}\n\nbutton[disabled] {\n  background: #ddd;\n  color: #aaa;\n}\n\ninput[type='range'] {\n  margin-top: 16px;\n  accent-color: black;\n}\n\ntextarea {\n  --padding: 32px;\n  width: calc(100% - var(--padding));\n  max-width: calc(100% - var(--padding));\n}\n\n.text,\ntextarea {\n  background-color: white;\n  padding: 16px;\n  border-radius: 16px;\n  box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px, rgb(51, 51, 51) 0px 0px 0px 3px;\n  outline: none;\n}\n\n.blink {\n  animation: 1s ease-in-out 1s infinite reverse both running blink;\n}\n\n@keyframes blink {\n  25% {\n    opacity: 0.5;\n  }\n  50% {\n    opacity: 0;\n  }\n  75% {\n    opacity: 0.5;\n  }\n}\n\n[hidden] {\n  display: none;\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device/sidepanel/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"index.css\" />\n  </head>\n  <body>\n    <textarea\n      id=\"input-prompt\"\n      placeholder='Type something, e.g. \"Write a haiku about Chrome Extensions\"'\n      cols=\"30\"\n      rows=\"5\"\n    ></textarea>\n    <div>\n      <input\n        type=\"range\"\n        id=\"temperature\"\n        name=\"temperature\"\n        min=\"0\"\n        max=\"2\"\n        step=\"0.01\"\n      />\n      <label for=\"temperature\"\n        >Temperature: <span id=\"label-temperature\"></span\n      ></label>\n    </div>\n    <div>\n      <input type=\"range\" id=\"top-k\" name=\"top-k\" min=\"1\" max=\"8\" step=\"1\" />\n      <label for=\"top-k\">Top-k: <span id=\"label-top-k\"></span></label>\n    </div>\n    <button id=\"button-prompt\" class=\"primary\" disabled>Run</button>\n    <button id=\"button-reset\" class=\"secondary\" disabled>Reset</button>\n    <div id=\"response\" class=\"text\" hidden></div>\n    <div id=\"loading\" class=\"text\" hidden><span class=\"blink\">...</span></div>\n    <div id=\"error\" class=\"text\" hidden></div>\n    <script src=\"index.js\" type=\"module\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device/sidepanel/index.js",
    "content": "/* global LanguageModel */\n\nimport DOMPurify from 'dompurify';\nimport { marked } from 'marked';\n\nconst inputPrompt = document.body.querySelector('#input-prompt');\nconst buttonPrompt = document.body.querySelector('#button-prompt');\nconst buttonReset = document.body.querySelector('#button-reset');\nconst elementResponse = document.body.querySelector('#response');\nconst elementLoading = document.body.querySelector('#loading');\nconst elementError = document.body.querySelector('#error');\nconst sliderTemperature = document.body.querySelector('#temperature');\nconst sliderTopK = document.body.querySelector('#top-k');\nconst labelTemperature = document.body.querySelector('#label-temperature');\nconst labelTopK = document.body.querySelector('#label-top-k');\n\nlet session;\n\nasync function runPrompt(prompt, params) {\n  try {\n    if (!session) {\n      session = await LanguageModel.create(params);\n    }\n    return session.prompt(prompt);\n  } catch (e) {\n    console.log('Prompt failed');\n    console.error(e);\n    console.log('Prompt:', prompt);\n    // Reset session\n    reset();\n    throw e;\n  }\n}\n\nasync function reset() {\n  if (session) {\n    session.destroy();\n  }\n  session = null;\n}\n\nasync function initDefaults() {\n  const defaults = await LanguageModel.params();\n  console.log('Model default:', defaults);\n  if (!('LanguageModel' in self)) {\n    showResponse('Model not available');\n    return;\n  }\n  sliderTemperature.value = defaults.defaultTemperature;\n  // Pending https://issues.chromium.org/issues/367771112.\n  // sliderTemperature.max = defaults.maxTemperature;\n  if (defaults.defaultTopK > 3) {\n    // limit default topK to 3\n    sliderTopK.value = 3;\n    labelTopK.textContent = 3;\n  } else {\n    sliderTopK.value = defaults.defaultTopK;\n    labelTopK.textContent = defaults.defaultTopK;\n  }\n  sliderTopK.max = defaults.maxTopK;\n  labelTemperature.textContent = defaults.defaultTemperature;\n}\n\ninitDefaults();\n\nbuttonReset.addEventListener('click', () => {\n  hide(elementLoading);\n  hide(elementError);\n  hide(elementResponse);\n  reset();\n  buttonReset.setAttribute('disabled', '');\n});\n\nsliderTemperature.addEventListener('input', (event) => {\n  labelTemperature.textContent = event.target.value;\n  reset();\n});\n\nsliderTopK.addEventListener('input', (event) => {\n  labelTopK.textContent = event.target.value;\n  reset();\n});\n\ninputPrompt.addEventListener('input', () => {\n  if (inputPrompt.value.trim()) {\n    buttonPrompt.removeAttribute('disabled');\n  } else {\n    buttonPrompt.setAttribute('disabled', '');\n  }\n});\n\nbuttonPrompt.addEventListener('click', async () => {\n  const prompt = inputPrompt.value.trim();\n  showLoading();\n  try {\n    const params = {\n      initialPrompts: [\n        { role: 'system', content: 'You are a helpful and friendly assistant.' }\n      ],\n      temperature: sliderTemperature.value,\n      topK: sliderTopK.value\n    };\n    const response = await runPrompt(prompt, params);\n    showResponse(response);\n  } catch (e) {\n    showError(e);\n  }\n});\n\nfunction showLoading() {\n  buttonReset.removeAttribute('disabled');\n  hide(elementResponse);\n  hide(elementError);\n  show(elementLoading);\n}\n\nfunction showResponse(response) {\n  hide(elementLoading);\n  show(elementResponse);\n  elementResponse.innerHTML = DOMPurify.sanitize(marked.parse(response));\n}\n\nfunction showError(error) {\n  show(elementError);\n  hide(elementResponse);\n  hide(elementLoading);\n  elementError.textContent = error;\n}\n\nfunction show(element) {\n  element.removeAttribute('hidden');\n}\n\nfunction hide(element) {\n  element.setAttribute('hidden', '');\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-alt-texter/README.md",
    "content": "# Alt Texter: Generate accessible image descriptions with Chrome's built-in Prompt API\n\nThis sample demonstrates how to use Chrome's built-in AI APIs to generate alt text for images, making web content more accessible. It combines two on-device AI capabilities:\n\n- **[Prompt API](https://developer.chrome.com/docs/extensions/ai/prompt-api)** with multimodal input (Gemini Nano) for image understanding\n- **[Translator API](https://developer.chrome.com/docs/ai/translator-api)** for translating descriptions into multiple languages\n\n## Overview\n\nAlt Texter adds a context menu entry for images on the web. When activated, it:\n\n1. Analyzes the image using Gemini Nano's multimodal capabilities.\n2. Generates a concise, functional description following accessibility best practices (object-action-context framework).\n3. Displays the description in a popup where you can optionally translate it.\n4. Lets you copy the alt text to your clipboard for use elsewhere.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world#load-unpacked).\n3. Right-click an image on a webpage and select \"Generate alt text\".\n4. Wait for the description to be generated, then optionally translate it or copy it to your clipboard.\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-alt-texter/background.js",
    "content": "chrome.runtime.onInstalled.addListener(() => {\n  chrome.contextMenus.create({\n    id: 'generateAltText',\n    title: 'Generate alt text',\n    contexts: ['image']\n  });\n});\nasync function generateAltText(imgSrc) {\n  // Create the model (we're not checking availability here, but will simply fail with an exception\n  const session = await self.LanguageModel.create({\n    temperature: 0.0,\n    topK: 1.0,\n    expectedInputs: [{ type: 'image' }]\n  });\n\n  // Create an image bitmap to pass it to the prompt\n  const response = await fetch(imgSrc);\n  const blob = await response.blob();\n  const imageBitmap = await createImageBitmap(blob);\n\n  // Run the prompt\n  const prompt = [\n    {\n      role: 'user',\n      content: [\n        {\n          type: 'text',\n          value: `Please provide a functional, objective description of the provided image in no more than around 30 words so that someone who could not see it would be able to imagine it. If possible, follow an “object-action-context” framework. The object is the main focus. The action describes what’s happening, usually what the object is doing. The context describes the surrounding environment. If there is text found in the image, do your best to transcribe the important bits, even if it extends the word count beyond 30 words. It should not contain quotation marks, as those tend to cause issues when rendered on the web. If there is no text found in the image, then there is no need to mention it. You should not begin the description with any variation of “The image”.`\n        },\n        { type: 'image', value: imageBitmap }\n      ]\n    }\n  ];\n  return await session.prompt(prompt);\n}\n\nchrome.contextMenus.onClicked.addListener(async (info, _tab) => {\n  if (info.menuItemId === 'generateAltText' && info.srcUrl) {\n    // Start opening the popup\n    const [result] = await Promise.allSettled([\n      generateAltText(info.srcUrl),\n      chrome.action.openPopup()\n    ]);\n    chrome.runtime.sendMessage({\n      action: 'alt-text',\n      text: result.status === 'fulfilled' ? result.value : result.reason.message\n    });\n  }\n});\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-alt-texter/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Alt Texter\",\n  \"version\": \"1.0\",\n  \"description\": \"Generates alt text for images using the Gemini Nano Prompt API.\",\n  \"permissions\": [\"contextMenus\", \"clipboardWrite\", \"activeTab\"],\n  \"minimum_chrome_version\": \"138\",\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"action\": {\n    \"default_popup\": \"popup.html\"\n  },\n  \"icons\": {\n    \"16\": \"icons/icon16.png\",\n    \"32\": \"icons/icon32.png\",\n    \"48\": \"icons/icon48.png\",\n    \"128\": \"icons/icon128.png\"\n  },\n  \"key\": \"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDL9gFsh0Ud/aHVnAA3EvADYbkvEiSWrRBEm45RQjHXK8BEz45myY8WYeEFTEkmbEOIWjpcL80J0931OhSdgk6O+VnHlbxG6fQzgxZnLclA/u8ZoRSI2VE5OxtrHRcHurg3dAl0sqwjVfxdO6uELYU2WgEVGMOHvw/yQGouYmMDgNu/Fz7SRM8GOT4Zrhfuk5zPnW+LGccIS4PiYMYFFLaHYxK9AZL3QpL9Ovp9v6+Qw3p/staYi9m0cHLNJvZrazL8fw9qP2tp2mtd9gZ5bCWe36uZpLCm173boD38vI9FH7z31VChzvmfesfCdNvL/jLSRsrF4uk4trFGA3DcSh7hAgMBAAECggEAd2HPA49JzXwftcBR/+p9wfz5P6wG7ort8rp6WuW79o4NRDmYyGFB93/jDg7Q4kSMYsstTbhM82unh1ovpuIWyWj6O/BQ+9EEtwILoukR25FcskuukUtiV3VZXyDv0f5gxVSOFFhgmW5DAO9kPUHHr0CPUaHlEResZcd+XxgHjIxcaobsvVHJWD4CG9gepev3wFgQ+H4jXP4y2b61j7R4eX3RFcD4S5IoVhOl+l9kKie5kKwNK2pEf/8P82r3dLZgqIYxrCEK2567W/M6Fdn6IXcuENU55REGr4EcBepCvEn50+WujuyhkV2/4PEn0L/q8A5NAoWvpRJgChBSiXNE4QKBgQDsjIHxgMsbCjKViOgPh0WgoSDz5G4v5oWmw2xJZe6UDTWuTPqu66yPjdYe/j58d5lh051dCyoVajkGjXJ4rY51Z6UEkkTVF3MzxVsDT3XaD3xpdBjSr/yLOhc6BEjJPjWvcufYZSKFU4NEKIp1TpfoA1K6vNMBdwGWfRE+eegHmwKBgQDcu4DpjzPuwI4XLNCIqCedLIMYLwgWcZQ2jDtWrDc3ywUDWkit0z6JR5e1w+naCQPYVfvBeIK1U23Tl+JVRmRrXqtrTU9E0bmoEZgkeK8FYlGW+0sx4FwpEiJFieUq1cPWwaJVxTimfueK3vDNTeKcR7X9qgMGK4LHM51ibCsBMwKBgQDe0KtF9O9cFQr41/DfT6hCWgRUOAOikx2pq8LAkIdeZeL+v/wR8GSnBA+BOjNZwr5z64T7M5z8dwYoKex9x928sVg7Khw0LNaTGX9Vau+z64phOr53FtZnvtxKBecZyMOA9Fd2+iy+MaAf/6AMR2/HV/oBdAO+CX8xZbVsiCALqQKBgG9qVY+OsO/6Ub5w6HGSLyyuox054CM0AVPnRKxjERwgZc9javwSfKZedL1Svl9H3aD9Ba6KXa+ZBP6g06WneliX2H647yIVmlizSNBf+jgFgJltDm+Gh/5TIOloyTvt2oQ0CPSyL/4aYFVAYtu+THwF1l7Lyer7W2+hJffgEXTxAoGAZhw8fturfUgEyPTstYiMJRA3gwe5NZ5h5ZRgpaSBtChI6psdm31FOqS08i8x5ymA30eOI9yVI9R/9NRSqIeQEhi/mCV1csHOdhWZoNYEetl7Vvm52eAVyMIBLIs3lozriaOWUAX5AP7ZR+iz4VXwKMCen/ZQDTXSoNb8qxP0s5A=\",\n  \"trial_tokens\": [\"Apyea3ieRfA2TLmHaL4OloKK4nlHsAx1zQ7BejbPI07xZijjHlKRFg+4v2wNHT3R8WFHIiCJ/yru79tT3yvGgwwAAAB7eyJvcmlnaW4iOiJjaHJvbWUtZXh0ZW5zaW9uOi8vYWRjbmhwY29qZWdmYW9oY2ttZmNiZGRwZWJjZXBram0iLCJmZWF0dXJlIjoiQUlQcm9tcHRBUElNdWx0aW1vZGFsSW5wdXQiLCJleHBpcnkiOjE3ODE1NjgwMDB9\"]\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-alt-texter/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Alt Text Generator</title>\n    <style>\n      @import 'https://unpkg.com/open-props';\n      @import 'https://unpkg.com/open-props/normalize.min.css';\n      @import 'https://unpkg.com/open-props/buttons.min.css';\n      @import 'https://unpkg.com/open-props/theme.light.switch.min.css';\n      @import 'https://unpkg.com/open-props/theme.dark.switch.min.css';\n\n      :root {\n        --font-size-00: 0.6rem;\n      }\n      body {\n        margin: auto;\n        padding: var(--size-2);\n        width: 500px;\n        padding: 10px;\n      }\n      h4 {\n        margin-bottom: var(--size-2);\n      }\n      textarea {\n        width: 100%;\n        height: 100px;\n      }\n      button {\n        margin-right: 5px;\n      }\n      #loading,\n      textarea {\n        margin: 16px 0;\n        height: 200px;\n      }\n    </style>\n  </head>\n  <body>\n    <h4>Alt Texter</h4>\n    <label\n      >Target language:\n      <select id=\"lang\">\n        <option value=\"bn\">Bengali</option>\n        <option value=\"en\" selected>English</option>\n        <option value=\"de\">German</option>\n        <option value=\"fr\">French</option>\n        <option value=\"hi\">Hindi</option>\n        <option value=\"ja\">Japanese</option>\n        <option value=\"zh\">Mandarin Chinese (Simplified)</option>\n        <option value=\"pt\">Portuguese</option>\n        <option value=\"ru\">Russian</option>\n        <option value=\"es\">Spanish</option>\n        <option value=\"zh-Hant\">Taiwanese Mandarin (Traditional)</option>\n        <option value=\"tr\">Turkish</option>\n        <option value=\"vi\">Vietnamese</option>\n      </select>\n    </label>\n    <textarea id=\"loading\">Generating alt text ...</textarea>\n    <textarea id=\"altText\" hidden></textarea>\n    <button type=\"button\" id=\"copyClose\">Copy and close</button>\n    <button type=\"reset\" id=\"discard\">Discard</button>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-alt-texter/popup.js",
    "content": "/* global Translator */\nconst altTextInput = document.getElementById('altText');\nconst loading = document.getElementById('loading');\nconst lang = document.getElementById('lang');\nlet text = '';\n\nlang.addEventListener('change', async function () {\n  altTextInput.setAttribute('hidden', true);\n  loading.removeAttribute('hidden');\n  text = await translate(text);\n  showAltText();\n});\n\nasync function translate(string) {\n  try {\n    const translator = await Translator.create({\n      sourceLanguage: 'en',\n      targetLanguage: lang.value\n    });\n    return translator.translate(string);\n  } catch (e) {\n    console.error(e);\n    return e.message;\n  }\n}\n\nasync function showAltText() {\n  altTextInput.value = text;\n  loading.setAttribute('hidden', true);\n  altTextInput.removeAttribute('hidden');\n}\n\nchrome.runtime.onMessage.addListener(async function (request) {\n  if (request.action === 'alt-text') {\n    text = request.text;\n    if (lang.value != 'en') {\n      text = await translate(text);\n    }\n    showAltText();\n  }\n});\n\ndocument.getElementById('copyClose').addEventListener('click', async () => {\n  const altText = altTextInput.value;\n  await navigator.clipboard.writeText(altText);\n  window.close();\n});\n\ndocument.getElementById('discard').addEventListener('click', () => {\n  window.close();\n});\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-audio-scribe/README.md",
    "content": "# Audio-Scribe: Transcribe audio messages with Chrome's multimodal Prompt API\n\nThis sample demonstrates how to use Chrome's built-in AI APIs to transcribe audio messages directly in the browser. It uses:\n\n- **[Prompt API](https://developer.chrome.com/docs/extensions/ai/prompt-api)** with multimodal audio input (Gemini Nano) for on-device speech-to-text transcription\n\n## Overview\n\nAudio-Scribe adds a side panel that automatically transcribes audio messages from chat applications. When activated, it:\n\n1. Monitors the page for audio blobs created via `URL.createObjectURL`.\n2. Detects audio content and sends it to Gemini Nano for transcription.\n3. Streams the transcribed text in real-time to the side panel.\n4. Works with messaging apps like WhatsApp Web that use blob URLs for audio messages.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world#load-unpacked).\n3. Open a chat app in the browser, for example https://web.whatsapp.com/. You can also run the included demo chat app:\n   ```\n   npx serve demo-chat-app\n   ```\n4. Open the Audio-Scribe side panel by clicking the extension icon or pressing `Alt+A`.\n5. Play or load audio messages in the chat - they will be automatically transcribed in the side panel.\n\n![Screenshot displaying a demo chat app with a few audio messages. On the right, there is the audio-scribe extension's sidepanel which displayes the transcribed text messages](assets/screenshot.png)\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-audio-scribe/background.js",
    "content": "// Copyright 2025 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true });\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-audio-scribe/bridge.js",
    "content": "// Copyright 2025 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Forward messages from the content script in the MAIN world to the\n// side panel\nwindow.addEventListener('message', ({ data }) => {\n  if (data.type !== 'audio-scribe') {\n    return;\n  }\n  chrome.runtime.sendMessage({ data });\n});\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-audio-scribe/demo-chat-app/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Chat App Demo</title>\n    <link rel=\"stylesheet\" href=\"style.css\" />\n  </head>\n  <body>\n    <div class=\"app-container\">\n      <div class=\"sidebar\">\n        <!-- Chat list will go here -->\n        <h2>Chats</h2>\n        <ul id=\"chat-list\">\n          <!-- Example chat items -->\n          <li class=\"chat-item active\" data-chat=\"Alice\">\n            <span class=\"avatar\">😊</span>\n            <span>Alice</span>\n          </li>\n          <li class=\"chat-item\" data-chat=\"Bob\">\n            <span class=\"avatar\">😎</span>\n            <span>Bob</span>\n          </li>\n          <li class=\"chat-item\" data-chat=\"Charlie\">\n            <span class=\"avatar\">🥳</span>\n            <span>Charlie</span>\n          </li>\n        </ul>\n      </div>\n      <div class=\"chat-panel\">\n        <div class=\"chat-header\">\n          <!-- Header for the current chat -->\n          <span class=\"avatar\" id=\"current-chat-avatar\">😊</span>\n          <h3 id=\"current-chat-name\">Alice</h3>\n        </div>\n        <div class=\"message-list\" id=\"message-list\">\n          <!-- Messages will be loaded here by JavaScript -->\n        </div>\n        <div class=\"message-input\">\n          <input\n            type=\"text\"\n            id=\"message-input-field\"\n            placeholder=\"Type a message...\"\n          />\n          <button id=\"send-button\">Send</button>\n        </div>\n      </div>\n    </div>\n\n    <script src=\"script.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-audio-scribe/demo-chat-app/script.js",
    "content": "document.addEventListener('DOMContentLoaded', () => {\n  const messageList = document.getElementById('message-list');\n\n  const sampleMessages = [\n    { type: 'received', text: '', isAudio: true, audioSrc: 'intro.mp3' },\n    { type: 'sent', text: \"I'm in a meeting right now\" },\n    { type: 'received', text: '', isAudio: true, audioSrc: 'msg1.mp3' },\n    { type: 'sent', text: '🙄' }\n  ];\n\n  async function renderMessages() {\n    messageList.innerHTML = ''; // Clear existing messages\n    const delayIncrement = 3000; // 5 seconds in milliseconds\n\n    await timeout(3000);\n\n    sampleMessages.forEach(async (msg, index) => {\n      // Use setTimeout to delay the appearance of each message\n      setTimeout(async () => {\n        const messageElement = document.createElement('div');\n        messageElement.classList.add('message', msg.type);\n\n        // Add a class for fade-in animation (optional, but nice)\n        messageElement.style.opacity = '0'; // Start transparent\n        messageElement.style.transition = 'opacity 0.5s ease-in-out';\n\n        if (msg.isAudio && msg.audioSrc) {\n          messageElement.classList.add('audio');\n\n          // Create audio element (hidden controls)\n          const audioElement = document.createElement('audio');\n          audioElement.preload = 'metadata'; // Important for getting duration\n          const sourceElement = document.createElement('source');\n          sourceElement.type = 'audio/mpeg'; // Assuming MP3\n          audioElement.appendChild(sourceElement);\n\n          const response = await fetch(msg.audioSrc);\n          const data = await response.arrayBuffer();\n          const blob = new Blob([data], { type: 'audio/wav' });\n          sourceElement.src = URL.createObjectURL(blob);\n          // Keep the audio element in the DOM but hidden for playback logic\n          audioElement.style.display = 'none';\n          messageElement.appendChild(audioElement);\n\n          // Create custom controls container\n          const controlsContainer = document.createElement('div');\n          controlsContainer.classList.add('audio-controls');\n\n          // Play/Pause Button\n          const playPauseButton = document.createElement('button');\n          playPauseButton.classList.add('audio-play-pause');\n          playPauseButton.textContent = '▶'; // Play icon initially\n          controlsContainer.appendChild(playPauseButton);\n\n          // Progress Bar (Slider)\n          const progressBar = document.createElement('input');\n          progressBar.type = 'range';\n          progressBar.classList.add('audio-progress');\n          progressBar.value = 0;\n          progressBar.min = 0;\n          progressBar.max = 100; // Will be updated with duration\n          progressBar.step = 0.1;\n          controlsContainer.appendChild(progressBar);\n\n          // Duration Display\n          const durationDisplay = document.createElement('span');\n          durationDisplay.classList.add('audio-duration');\n          durationDisplay.textContent = '0:00'; // Initial display\n          controlsContainer.appendChild(durationDisplay);\n\n          // Append custom controls to the message element\n          messageElement.appendChild(controlsContainer);\n\n          // --- Event Listeners for Custom Controls ---\n\n          // Format time helper function\n          function formatTime(seconds) {\n            const minutes = Math.floor(seconds / 60);\n            const secs = Math.floor(seconds % 60);\n            return `${minutes}:${secs < 10 ? '0' : ''}${secs}`;\n          }\n\n          // Update duration when metadata loads\n          audioElement.addEventListener('loadedmetadata', () => {\n            progressBar.max = audioElement.duration;\n            durationDisplay.textContent = formatTime(audioElement.duration);\n          });\n\n          // Play/Pause functionality\n          playPauseButton.addEventListener('click', () => {\n            if (audioElement.paused) {\n              audioElement.play();\n              playPauseButton.textContent = '❚❚'; // Pause icon\n            } else {\n              audioElement.pause();\n              playPauseButton.textContent = '▶'; // Play icon\n            }\n          });\n\n          // Update progress bar as audio plays\n          audioElement.addEventListener('timeupdate', () => {\n            progressBar.value = audioElement.currentTime;\n            // Update duration display to show current time while playing (optional)\n            durationDisplay.textContent = `${formatTime(audioElement.currentTime)} / ${formatTime(audioElement.duration)}`;\n          });\n\n          // Seek audio when progress bar is changed\n          progressBar.addEventListener('input', () => {\n            audioElement.currentTime = progressBar.value;\n          });\n\n          // Reset button to play when audio ends\n          audioElement.addEventListener('ended', () => {\n            playPauseButton.textContent = '▶';\n            progressBar.value = 0; // Reset progress bar\n          });\n        } else {\n          messageElement.textContent = msg.text;\n          // Check if the message is emoji-only\n          if (isEmojiOnly(msg.text)) {\n            messageElement.classList.add('message-emoji-only');\n          }\n        }\n\n        messageList.appendChild(messageElement);\n\n        // Trigger the fade-in effect\n        requestAnimationFrame(() => {\n          // Ensures the element is in the DOM before changing opacity\n          messageElement.style.opacity = '1';\n        });\n\n        // Scroll to the bottom after adding the message\n        messageList.scrollTop = messageList.scrollHeight;\n      }, index * delayIncrement); // Stagger delay based on index\n    });\n  }\n\n  // Helper function to check if a string contains only emojis\n  function isEmojiOnly(str) {\n    // Regex to match one or more emojis and nothing else\n    const emojiRegex = /^(\\p{Emoji_Presentation}|\\p{Extended_Pictographic})+$/u;\n    return emojiRegex.test(str.trim());\n  }\n\n  renderMessages();\n\n  // Basic send functionality (optional, just for demo)\n  const sendButton = document.getElementById('send-button'); // Use ID selector\n  const messageInput = document.getElementById('message-input-field'); // Use ID selector\n\n  function sendMessage() {\n    const text = messageInput.value.trim();\n    if (text) {\n      // No need to re-render everything, just add the new message\n      const newMessage = { type: 'sent', text: text };\n      sampleMessages.push(newMessage); // Add to data source\n\n      // Create and append the new message element directly\n      const messageElement = document.createElement('div');\n      messageElement.classList.add('message', 'sent');\n      messageElement.textContent = text;\n\n      // Check if the new message is emoji-only\n      if (isEmojiOnly(text)) {\n        messageElement.classList.add('message-emoji-only');\n      }\n\n      // Add fade-in effect (optional, consistent with renderMessages)\n      messageElement.style.opacity = '0';\n      messageElement.style.transition = 'opacity 0.5s ease-in-out';\n\n      messageList.appendChild(messageElement);\n\n      // Trigger fade-in\n      requestAnimationFrame(() => {\n        messageElement.style.opacity = '1';\n      });\n\n      // Scroll to bottom\n      messageList.scrollTop = messageList.scrollHeight;\n\n      messageInput.value = ''; // Clear input\n    }\n  }\n\n  sendButton.addEventListener('click', sendMessage);\n  messageInput.addEventListener('keypress', (e) => {\n    if (e.key === 'Enter') {\n      sendMessage();\n    }\n  });\n\n  // Chat switching functionality\n  const chatList = document.getElementById('chat-list');\n  const chatItems = chatList.querySelectorAll('.chat-item');\n  const currentChatName = document.getElementById('current-chat-name');\n  const currentChatAvatar = document.getElementById('current-chat-avatar');\n\n  chatItems.forEach((item) => {\n    item.addEventListener('click', () => {\n      // Remove active class from previously active item\n      const currentActive = chatList.querySelector('.chat-item.active');\n      if (currentActive) {\n        currentActive.classList.remove('active');\n      }\n\n      // Add active class to clicked item\n      item.classList.add('active');\n\n      // Update chat header\n      const chatName = item.querySelector('span:not(.avatar)').textContent; // Get name span specifically\n      const avatarEmoji = item.querySelector('.avatar').textContent; // Get emoji from avatar span\n\n      currentChatName.textContent = chatName;\n      currentChatAvatar.textContent = avatarEmoji; // Set emoji in header avatar span\n    });\n  });\n});\n\nfunction timeout(ms) {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-audio-scribe/demo-chat-app/style.css",
    "content": "/* General Reset and Body Styles */\nbody {\n    font-family: 'Segoe UI', 'Helvetica Neue', Helvetica, Arial, sans-serif;\n    margin: 0;\n    background-color: #f0f4f8; /* Lighter, cooler background */\n    height: 100vh;\n    display: flex;\n    overflow: hidden; /* Prevent body scroll */\n}\n\n/* Main App Container */\n.app-container {\n    display: flex;\n    width: 100%;\n    height: 100%;\n    max-width: 1600px;\n    margin: auto;\n    background-color: #ffffff; /* Keep main container white */\n    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 2px 8px rgba(0, 0, 0, 0.08); /* Slightly softer shadow */\n}\n\n/* Sidebar (Chat List) */\n.sidebar {\n    width: 30%;\n    min-width: 250px;\n    max-width: 400px;\n    background-color: #ffffff;\n    border-right: 1px solid #e8e8e8; /* Lighter separator */\n    display: flex;\n    flex-direction: column;\n}\n\n.sidebar h2 {\n    padding: 15px 20px;\n    margin: 0;\n    font-size: 18px;\n    font-weight: 500;\n    color: #333; /* Standard dark grey */\n    border-bottom: 1px solid #e8e8e8; /* Lighter separator */\n    background-color: #f8f9fa; /* Very light grey header */\n}\n\n#chat-list {\n    list-style: none;\n    padding: 0;\n    margin: 0;\n    overflow-y: auto; /* Allow scrolling for chat list */\n    flex-grow: 1;\n}\n\n/* Style for avatar emojis */\n.avatar {\n    width: 40px;\n    height: 40px;\n    border-radius: 50%; /* Make avatars circular */\n    margin-right: 10px; /* Space between avatar and name */\n    display: flex; /* Use flexbox for centering */\n    align-items: center;\n    justify-content: center;\n    font-size: 24px; /* Adjust emoji size */\n    background-color: #eee; /* Optional: Add a background */\n    flex-shrink: 0; /* Prevent shrinking */\n}\n\n.chat-item {\n    padding: 10px 15px; /* Slightly less padding */\n    border-bottom: 1px solid #f0f0f0; /* Lighter separator */\n    cursor: pointer;\n    display: flex;\n    align-items: center;\n    /* gap: 15px; */ /* Replaced by avatar margin */\n}\n\n.chat-item:hover {\n    background-color: #f0f4f8; /* Light blue hover */\n}\n\n.chat-item.active {\n    background-color: #e2eaf1; /* Slightly darker blue for active */\n}\n\n/* Chat Panel (Conversation View) */\n.chat-panel {\n    flex-grow: 1;\n    display: flex;\n    flex-direction: column;\n    background-color: #e8f0f4; /* Lighter blue chat background */\n}\n\n.chat-header {\n    padding: 10px 16px;\n    background-color: #f8f9fa; /* Match sidebar header */\n    border-bottom: 1px solid #e8e8e8; /* Lighter separator */\n    display: flex;\n    align-items: center;\n    min-height: 40px;\n}\n\n/* No specific override needed for header avatar anymore if base style is good */\n/* .chat-header .avatar { ... } */ /* Removed redundant/conflicting styles */\n\n.chat-header h3 {\n    margin: 0;\n    font-size: 16px;\n    font-weight: 500;\n    color: #333; /* Standard dark grey */\n}\n\n/* Message List */\n.message-list {\n    flex-grow: 1;\n    padding: 20px 5%; /* Padding relative to width */\n    overflow-y: auto;\n    display: flex;\n    flex-direction: column;\n    gap: 5px; /* Smaller gap between messages */\n}\n\n/* Individual Messages */\n.message {\n    padding: 6px 12px;\n    border-radius: 7.5px; /* WhatsApp's bubble radius */\n    max-width: 65%;\n    word-wrap: break-word;\n    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.08); /* Softer shadow */\n    font-size: 14.5px;\n    line-height: 1.4;\n}\n\n.message.sent {\n    background-color: #cce5ff; /* Light blue for sent messages */\n    color: #004085; /* Darker blue text for contrast */\n    align-self: flex-end;\n    margin-left: auto;\n}\n\n.message.received {\n    background-color: #ffffff; /* White for received */\n    color: #333; /* Standard dark text */\n    align-self: flex-start;\n    margin-right: auto;\n}\n\n/* Style for messages containing only emojis */\n.message.message-emoji-only {\n    font-size: 29px; /* Double the base message font size */\n    line-height: 1.2; /* Adjust line height for larger font */\n    padding: 2px 6px; /* Adjust padding slightly */\n    /* Optional: Remove background for pure emoji look */\n    /* background-color: transparent; */\n    /* box-shadow: none; */\n}\n\n/* Message Input Area */\n.message-input {\n    display: flex;\n    align-items: center;\n    padding: 10px 20px;\n    background-color: #f8f9fa; /* Match header background */\n    border-top: 1px solid #e8e8e8; /* Lighter separator */\n}\n\n#message-input-field { /* Use the ID from HTML */\n    flex-grow: 1;\n    padding: 10px 15px;\n    border: none; /* Remove default border */\n    border-radius: 20px; /* Rounded input */\n    margin-right: 10px;\n    font-size: 15px;\n    outline: none;\n}\n\n#send-button {\n    padding: 10px 15px;\n    background-color: #007bff; /* Standard blue send button */\n    color: white;\n    border: none;\n    border-radius: 20px; /* Rounded corners like input */\n    cursor: pointer;\n    font-size: 15px; /* Match input field font size */\n    /* Remove fixed width and height */\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    /* Consider adding an SVG icon here */\n}\n\n#send-button:hover {\n    background-color: #0056b3; /* Darker blue on hover */\n}\n\n/* Custom Audio Player Styles */\n.message.audio {\n    /* Adjust padding if needed for controls */\n    padding-top: 8px;\n    padding-bottom: 8px;\n}\n\n.audio-controls {\n    display: flex;\n    align-items: center;\n    gap: 10px; /* Space between button, progress, duration */\n    width: 100%; /* Ensure controls take available width */\n    margin-top: 5px; /* Space above controls if there was text */\n}\n\n.audio-play-pause {\n    background-color: #007bff; /* Match send button color */\n    color: white;\n    border: none;\n    border-radius: 50%; /* Circular button */\n    width: 30px;\n    height: 30px;\n    font-size: 14px; /* Adjust icon size */\n    cursor: pointer;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    padding: 0; /* Remove default padding */\n    flex-shrink: 0; /* Prevent button from shrinking */\n}\n\n.audio-play-pause:hover {\n    background-color: #0056b3; /* Darker blue on hover */\n}\n\n.audio-progress {\n    flex-grow: 1; /* Take up remaining space */\n    height: 6px; /* Slimmer progress bar */\n    cursor: pointer;\n    appearance: none; /* Override default look */\n    background: #ddd; /* Track background */\n    border-radius: 3px;\n    outline: none;\n}\n\n/* Styling the progress bar thumb (the draggable part) */\n.audio-progress::-webkit-slider-thumb {\n    appearance: none;\n    width: 12px;\n    height: 12px;\n    background: #007bff; /* Thumb color */\n    border-radius: 50%;\n    cursor: pointer;\n    margin-top: -3px; /* Adjust vertical alignment ( (track_height - thumb_height) / 2 ) */\n}\n\n.audio-progress::-moz-range-thumb {\n    width: 12px;\n    height: 12px;\n    background: #007bff;\n    border-radius: 50%;\n    cursor: pointer;\n    border: none; /* Remove default border in Firefox */\n}\n\n/* Styling the progress bar track */\n.audio-progress::-webkit-slider-runnable-track {\n    height: 6px;\n    background: #ccc; /* Slightly darker track */\n    border-radius: 3px;\n}\n\n.audio-progress::-moz-range-track {\n    height: 6px;\n    background: #ccc;\n    border-radius: 3px;\n}\n\n.audio-duration {\n    font-size: 12px;\n    color: #555; /* Muted color for duration */\n    min-width: 35px; /* Ensure space for MM:SS */\n    text-align: right;\n    flex-shrink: 0; /* Prevent duration from shrinking */\n}\n\n#chat {\n    background-color: red;\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-audio-scribe/manifest.json",
    "content": "{\n  \"name\": \"Audio scribe\",\n  \"description\": \"Use Gemini Nano to transcribe audio messages in chat conversations.\",\n  \"version\": \"0.2\",\n  \"icons\": {\n    \"128\": \"assets/icon128.png\"\n  },\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"content_scripts\": [\n    {\n      \"matches\": [\"<all_urls>\"],\n      \"js\": [\"override-createobject-url.js\"],\n      \"run_at\": \"document_start\",\n      \"world\": \"MAIN\"\n    },\n    {\n      \"matches\": [\"<all_urls>\"],\n      \"js\": [\"bridge.js\"],\n      \"run_at\": \"document_start\"\n    }\n  ],\n  \"action\": {},\n  \"side_panel\": {\n    \"default_path\": \"sidepanel.html\"\n  },\n  \"permissions\": [\"sidePanel\"],\n  \"commands\": {\n    \"_execute_action\": {\n      \"suggested_key\": {\n        \"windows\": \"Alt+A\",\n        \"mac\": \"Alt+A\",\n        \"chromeos\": \"Alt+A\",\n        \"linux\": \"Alt+A\"\n      }\n    }\n  },\n  \"manifest_version\": 3,\n  \"key\": \"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQChPL1IhK1Q6QNu2/vrZznTj1uRuhx1auZNAHLBX8S2JBDOEV7yieOQRH3NK0I9XrWVFTeG09PCCPLfpgzPL9ZtwjqaminVBeSZoojXRwisBTUN+kHAdW+bo1LVNSqOqxR0eUwh1yukGWr/HgzRUY8BWm//45NZ1PWXZnVFWuvREirXRz8OOV89WWfxZ0tOFRSpShGAIhpDY2dfuCDdaKlxU//7aIcbyXdM2GjyH5zTdUcrHPSFXEWYvetB/DJBKfHZis144GT+PEEYIks+XuXvwKijj0kAggHX8EFXN12ttg1qGmyyMYKzzlXJmc7+7LRJQ2KMe94yv89LmMd/sL93AgMBAAECggEAKr8us64xQPU16ss5w9RPOW6VaVI9P0gDHMEUq33Xai6voeJrGMRD57iw3ZctbZXRcF/6o60/Q/8ZXP/p/3gAUoMfBGQA2TBBxhWYT/LOMsUCpt0FV6AK4elwCYSZ7s8eki6iZ4pjUJNIkbCG12vXDRXMAbx1EWjrX6NTTfrn8DqEEr3R48Xej8L59ehkMF4hicgmjne5YopXCLHGP7WlSEWaV8GFKLxlRFMGJWQA+RtIxhRJ5YbhunkTDfE3qrRLYWc6M/wGQGkx3EilAQNav6cHtIMXIwRa93uzG6qluKJdla5dvwTVkbGXsyhKlSjRw25J1xjXpqTkfRHPSmmVuQKBgQDNsJ7tOkCTGWwdgE2mHnlwfy1Rt//Ilk0CRHApIobEYKGb1xRVIHXlV02db7QHkg93NMBcZWDPt64LJ6T+zPJjPpeOdukwLKVudsgIMImd5lpSeK3Lhz+Nu6eqtgEWSBrA9BNp0XLWs+e9bxa2MnPj/Bq1yVXNG365ht4UmOj8OwKBgQDIrLFMR4SaBXbVxDVbrroCUJoC04TnuKwcisKNyWlXxOhlcqurz9a7Av1nAQaTz1bnS5xRfmZZu3qdNg0JZ6KJu5sokKE7JdhiXcaf+HL3Vurn+uVTexCJH48y5+iRKjpkIzldeG+DXubp2ZdjoAdhEnktKWu3mu/ikawXoh9h9QKBgBaGdhESpQm26gEdEOPVSIVKWCMv3EISO6K47fODRXDyCCCx4Bcmc+LGucg4+GUv2KO8UiiMLZrxyYyNLeN9fDnkG+LNIOJWsVM0jNlgv2FcXZ3Ue2vjhtE1sLngLqRLBysET6/x8PqUPxeet8UCJ3DbJe2se8n3bdxRabalvDYLAoGATT+NEJwHQ3MPB8L790sPd4ynfKcH5luEhYg01HfQAWVfQI4f34emVV8VRO10JroN7gOBLS3HIIu264W/BvvJ6dM6KydhqW8sGNGYgEQXnXbr/ljqpnQdLWvkp+f18suapqmYj46o/p0trp+AU21q6cc+tk/Xk1olNcZ1xLM3+XECgYEAtWnWy5CQ6l0Ctv3CVRZnUU2Hss8DVSbrmApUoWNTe3cukFF3661z8uheAtT4KrtaVJN+ZNdj7Y8AjayhXy83pb5ISUeYKYOiWiOAGDTJB/RlmGYxNF1wlp+3pge+Jkjo2F20g77OqSklzPOepWv0DkjtU+W5UhBJ8ir36Fl6phY=\",\n  \"trial_tokens\": [\"ApTXP8QDHwYTK2R3rSt2faBqqLrPCuy6tIn5pzY/mBY924J/RCio2l42sw7llpEiC5x2U9rBmlBBfATkD+iAbQ0AAAB7eyJvcmlnaW4iOiJjaHJvbWUtZXh0ZW5zaW9uOi8vbW9vbGdsamtsb3BqZmNiZ29lbW9jZW9wZWZsYWloaWwiLCJmZWF0dXJlIjoiQUlQcm9tcHRBUElNdWx0aW1vZGFsSW5wdXQiLCJleHBpcnkiOjE3ODE1NjgwMDB9\"]\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-audio-scribe/override-createobject-url.js",
    "content": "// Copyright 2025 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst originalCreateObjectURL = URL.createObjectURL;\n\n// Signal the creation of object URLs to the side panel\n// Note: you should be only doing this for specific websites\n// and not for all (as we do in this demo)\nURL.createObjectURL = (object) => {\n  const objectUrl = originalCreateObjectURL.call(URL, object);\n  window.postMessage({ type: 'audio-scribe', objectUrl });\n  return objectUrl;\n};\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-audio-scribe/sidepanel.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <style>\n      @import 'https://unpkg.com/open-props';\n      @import 'https://unpkg.com/open-props/normalize.min.css';\n      @import 'https://unpkg.com/open-props/buttons.min.css';\n      @import 'https://unpkg.com/open-props/theme.light.switch.min.css';\n      @import 'https://unpkg.com/open-props/theme.dark.switch.min.css';\n\n      :root {\n        --font-size-00: 0.6rem;\n      }\n      body {\n        margin: auto;\n        padding: var(--size-2);\n      }\n      ul {\n        padding: var(--size-2);\n      }\n      li {\n        background: var(--surface-3);\n        border: 1px solid var(--surface-1);\n        padding: var(--size-4);\n        margin-bottom: var(--size-3);\n        border-radius: var(--radius-3);\n        box-shadow: var(--shadow-2);\n        list-style: none;\n        border-radius: var(--radius-2);\n        padding: var(--size-fluid-3);\n        box-shadow: var(--shadow-2);\n\n        &:hover {\n          box-shadow: var(--shadow-3);\n        }\n\n        @media (--motionOK) {\n          animation: var(--animation-fade-in);\n        }\n      }\n    </style>\n  </head>\n  <body>\n    <ul id=\"messages\"></ul>\n    <script src=\"sidepanel.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-audio-scribe/sidepanel.js",
    "content": "// Copyright 2025 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//      http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n/* global LanguageModel */\n\nchrome.runtime.onMessage.addListener(async ({ data }) => {\n  let content;\n  try {\n    if (data.type != 'audio-scribe' || !data || !isValidUrl(data.objectUrl)) {\n      return;\n    }\n    // Check if it's an audio file\n    const audio = await fetch(data.objectUrl);\n    content = await audio.blob();\n    if (!content.type || !content.type.startsWith('audio/')) {\n      return;\n    }\n  } catch (e) {\n    console.log(e);\n  }\n\n  // Setup message UI\n  const messages = document.getElementById('messages');\n  const li = document.createElement('li');\n  li.append('...');\n  messages.append(li);\n\n  try {\n    // Transcribe audio\n    const availability = await LanguageModel.availability();\n    if (availability !== 'available') {\n      console.error('Model is', availability);\n      throw new Error('Model is not available');\n    }\n    const session = await LanguageModel.create({\n      expectedInputs: [{ type: 'audio' }]\n    });\n\n    const stream = session.promptStreaming([\n      {\n        role: 'user',\n        content: [\n          { type: 'text', value: 'transcribe this audio' },\n          { type: 'audio', value: content }\n        ]\n      }\n    ]);\n\n    // Render streamed response\n    let first = true;\n    for await (const chunk of stream) {\n      if (first) {\n        li.textContent = '';\n        first = false;\n      }\n      li.append(chunk);\n    }\n  } catch (error) {\n    console.log(error);\n    li.textContent = error.message;\n  }\n});\n\nfunction isValidUrl(string) {\n  try {\n    new URL(string);\n    return true;\n    // eslint-disable-next-line no-unused-vars\n  } catch (_) {\n    return false;\n  }\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-calendar-mate/.gitignore",
    "content": "dist\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-calendar-mate/README.md",
    "content": "# Calendar Mate: On-device AI with Gemini Nano\n\nThis sample demonstrates how to use Chrome's built-in Prompt API in an extension to extract calendar event details from natural language text. To learn more about the API, see [Prompt API on developer.chrome.com](https://developer.chrome.com/docs/extensions/ai/prompt-api).\n\n## Overview\n\nCalendar Mate allows users to quickly create Google Calendar events from any selected text on a webpage. Simply highlight text describing an event (e.g., \"Team meeting on Friday at 3pm in Conference Room A\"), right-click, and select \"Create Calendar Event\". The extension uses Gemini Nano to intelligently extract:\n\n- Event title\n- Start and end date/time\n- Location\n- Description\n- Timezone\n\nThe extracted details are used to pre-populate a new Google Calendar event.\n\n## Running this extension\n\n1. Clone this repository.\n2. Run `npm install` in the project directory.\n3. Run `npm run build` to build the extension.\n4. Load the `dist` directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world#load-unpacked).\n5. Select any text on a webpage that describes an event.\n6. Right-click and choose \"Create Calendar Event\" from the context menu.\n\n## How it works\n\n1. **Context Menu**: The extension adds a \"Create Calendar Event\" option to Chrome's right-click context menu when text is selected.\n2. **AI Extraction**: When triggered, the selected text is sent to Gemini Nano with a prompt to extract event details as structured JSON.\n3. **Date Parsing**: The extracted date/time strings are parsed using the [any-date-parser](https://www.npmjs.com/package/any-date-parser) library.\n4. **Calendar Integration**: A Google Calendar URL is generated with the extracted details and opened in a new tab.\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-calendar-mate/background.js",
    "content": "/* global LanguageModel */\n\nimport anyDateParser from './node_modules/any-date-parser/dist/index.mjs';\n\nchrome.runtime.onInstalled.addListener(() => {\n  chrome.contextMenus.create({\n    id: 'createCalendarEvent',\n    title: 'Create Calendar Event',\n    contexts: ['selection']\n  });\n});\n\nchrome.contextMenus.onClicked.addListener(async (info) => {\n  if (info.menuItemId === 'createCalendarEvent') {\n    const selectedText = info.selectionText;\n    try {\n      // Extract event details from text using the prompt API\n      const event = await parseEventDetails(selectedText);\n      // Convert date to RFC 5545 date format\n      const startDate = parse(\n        [\n          event.start_time,\n          event.start_date,\n          event.start_year,\n          event.timezone\n        ].join(' ')\n      );\n      const endDate = parse(\n        [event.end_time, event.end_date, event.end_year, event.timezone].join(\n          ' '\n        )\n      );\n      event.dates = format(startDate) + '/' + format(endDate);\n\n      const googleCalendarUrl = createGoogleCalendarUrl(event);\n      chrome.tabs.create({ url: googleCalendarUrl.toString() });\n    } catch (e) {\n      console.log(e);\n    }\n  }\n});\n\nfunction parse(dateString) {\n  const parsed = anyDateParser.attempt(dateString);\n  return new Date(\n    parsed.year,\n    parsed.month - 1,\n    parsed.day,\n    parsed.hour,\n    parsed.minute\n  );\n}\n\nfunction format(date) {\n  const month = String(date.getMonth() + 1).padStart(2, '0');\n  const day = String(date.getDate() + 1).padStart(2, '0');\n  const year = date.getFullYear();\n  const hours = String(date.getHours()).padStart(2, '0');\n  const minutes = String(date.getMinutes()).padStart(2, '0');\n  const seconds = String(date.getSeconds()).padStart(2, '0');\n\n  return [year, month, day, 'T', hours, minutes, seconds].join('');\n}\n\nfunction createGoogleCalendarUrl(eventDetails) {\n  const googleCalendarUrl = new URL(\n    'https://calendar.google.com/calendar/render?action=TEMPLATE'\n  );\n  const params = googleCalendarUrl.searchParams;\n  if (eventDetails.title) {\n    params.append('text', eventDetails.title);\n  }\n  if (eventDetails.dates) {\n    params.append('dates', eventDetails.dates);\n  }\n  if (eventDetails.description) {\n    params.append('details', eventDetails.description);\n  }\n  if (eventDetails.location) {\n    params.append('location', eventDetails.location);\n  }\n  return googleCalendarUrl;\n}\n\nasync function parseEventDetails(text) {\n  const session = await LanguageModel.create({\n    temperature: 0,\n    topK: 1.0\n  });\n\n  let prompt = `\n    The following text describes an event. Extract \"title\", \"start_time\", \"start_date\", \"start_year\", \"end_time\", \"end_date\", \"end_year\", \"description\", \"timezone\" and \"location\" of the event. Return only JSON as result.\n\n    * If no year is provided, use the current year ${new Date().getFullYear()}.\n    * If no timezone is provided, leave it empty.\n    * Do not convert the start time or end time\n\n    Here is the text:\n\n     ${text}`;\n\n  const result = await session.prompt(prompt);\n  return JSON.parse(fixCommonJSONMistakes(result), null, '  ');\n}\n\nfunction addCommaBetweenQuotes(str) {\n  return str.replace(/\"([^\"]*)\"\\s+\"([^\"]*)\"/g, '\"$1\", \"$2\"');\n}\n\nfunction extractTextBetweenCurlyBraces(str) {\n  if (str[0] === '[') return str;\n  const firstBraceIndex = str.indexOf('{');\n  const lastBraceIndex = str.lastIndexOf('}');\n\n  if (firstBraceIndex === -1 || lastBraceIndex === -1) {\n    return null; // No curly braces found\n  }\n\n  return str.substring(firstBraceIndex, lastBraceIndex + 1);\n}\n\nfunction curlyToBrackets(str) {\n  // Check if the input is a string\n  if (typeof str !== 'string') {\n    return 'Input must be a string.';\n  }\n\n  // Use a regular expression to match curly braces with quoted strings inside\n  return str.replace(/\\{(\"([^\"]*)\"(?:,\\s*)?)*\\}/g, function (match) {\n    // Remove curly braces and replace with brackets\n    return '[' + match.slice(1, -1) + ']';\n  });\n}\n\nfunction fixCommonJSONMistakes(str) {\n  str = str.trim();\n  str = curlyToBrackets(str);\n  str = extractTextBetweenCurlyBraces(str);\n  str = addCommaBetweenQuotes(str);\n  return str;\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-calendar-mate/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Calendar Mate\",\n  \"version\": \"1.0\",\n  \"description\": \"Create Google Calendar events from selected text using Gemini Nano.\",\n  \"permissions\": [\"contextMenus\"],\n  \"minimum_chrome_version\": \"138\",\n  \"background\": {\n    \"service_worker\": \"background.js\",\n    \"type\": \"module\"\n  },\n  \"icons\": {\n    \"16\": \"icons/icon16.png\",\n    \"32\": \"icons/icon32.png\",\n    \"48\": \"icons/icon48.png\",\n    \"128\": \"icons/icon128.png\"\n  },\n  \"action\": {\n    \"default_icon\": {\n      \"16\": \"icons/icon16.png\",\n      \"32\": \"icons/icon32.png\"\n    }\n  }\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-calendar-mate/package.json",
    "content": "{\n  \"name\": \"calendar-mate\",\n  \"version\": \"1.0.0\",\n  \"main\": \"background.js\",\n  \"scripts\": {\n    \"build\": \"rollup -c\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"description\": \"\",\n  \"dependencies\": {\n    \"any-date-parser\": \"2.1.0\",\n    \"@rollup/plugin-commonjs\": \"26.0.1\",\n    \"@rollup/plugin-node-resolve\": \"15.2.3\",\n    \"rollup\": \"4.22.4\",\n    \"rollup-plugin-copy\": \"3.5.0\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-calendar-mate/rollup.config.mjs",
    "content": "import { nodeResolve } from '@rollup/plugin-node-resolve';\nimport commonjs from '@rollup/plugin-commonjs';\nimport copy from 'rollup-plugin-copy';\n\nexport default [\n  {\n    input: 'background.js',\n    output: {\n      dir: 'dist',\n      format: 'iife',\n    },\n    plugins: [\n      nodeResolve({\n        jsnext: true,\n        main: true,\n        browser: true\n      }),\n      commonjs(),\n      copy({\n        targets: [\n          {\n            src: ['manifest.json', 'icons'],\n            dest: 'dist'\n          }\n        ]\n      })\n    ]\n  }\n];\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-summarization/.gitignore",
    "content": "dist\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-summarization/README.md",
    "content": "# On-device Summarization with Gemini Nano\n\nThis sample demonstrates how to use Chrome's built-in Summarizer API to generate AI-powered summaries of web pages directly on the user's device. The summarization runs entirely locally using Gemini Nano, ensuring privacy and fast performance without requiring an internet connection or API keys.\n\nTo learn more about the Summarizer API, head over to the [Summarizer API guide on developer.chrome.com](https://developer.chrome.com/docs/ai/summarizer-api).\n\n## Overview\n\nThis extension adds a side panel that automatically displays AI-generated summaries of any web page you visit. It uses Mozilla's [Readability](https://github.com/mozilla/readability) library to extract the main content from web pages (stripping away navigation, ads, and other clutter), then passes that content to Chrome's built-in Summarizer API.\n\n## Running this extension\n\n1. Clone this repository.\n2. Run `npm install` in this folder to install all dependencies.\n3. Run `npm run build` to build the extension.\n4. Load the newly created `dist` directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world#load-unpacked).\n5. Click the extension icon to open the summary side panel.\n6. Open any web page. The page's content summary will automatically be displayed in the side panel.\n\n## Creating your own extension\n\nIf you use this sample as the foundation for your own extension, be sure to update the `\"trial_tokens\"` field [with your own origin trial token](https://developer.chrome.com/docs/web-platform/origin-trials#extensions) and to remove the `\"key\"` field in `manifest.json`.\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-summarization/background.js",
    "content": "chrome.sidePanel\n  .setPanelBehavior({ openPanelOnActionClick: true })\n  .catch((error) => console.error(error));\n\nchrome.tabs.onActivated.addListener((activeInfo) => {\n  showSummary(activeInfo.tabId);\n});\nchrome.tabs.onUpdated.addListener(async (tabId) => {\n  showSummary(tabId);\n});\n\nasync function showSummary(tabId) {\n  const tab = await chrome.tabs.get(tabId);\n  if (!tab.url.startsWith('http')) {\n    return;\n  }\n  const injection = await chrome.scripting.executeScript({\n    target: { tabId },\n    files: ['scripts/extract-content.js']\n  });\n  chrome.storage.session.set({ pageContent: injection[0].result });\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-summarization/manifest.json",
    "content": "{\n  \"name\": \"Summarization API sample\",\n  \"version\": \"0.1\",\n  \"manifest_version\": 3,\n  \"description\": \"Get a short summary of webpage content using Chrome's built-in summarization API.\",\n  \"key\": \"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0rGdYnMnAJm24F1aVoygD+UJtTtFkRfju36f2Pp3keQQU6fXHNrddqpfMZXb+E9YJmRz+2jJgeEbMSN4m8zFD/9NrbNmfUrCvvnu6id6o1cMtdRsFNvLDsvDfY895kQ9d8543q5TCmGt1NGFBgzSp8wORBQNOYXlAmtRh2Ru2+pMC/v8i5lirkMQbWKe7y+tr6aq95KrILc+TxZmujqoTd0Tay5sNp3jCafdSexo2dOnCUR369KLRnkrakaZ9Jzak5C2ysHwcgmsJwvenFCbET2AvHjiHLGDDWNCQ+FYwzlMOnJCOjDskWur8XAGozKKYpPXtJ88BYfuPu80QXfZaQIDAQAB\",\n  \"trial_tokens\": [\n    \"AkGcfoMTs5K71isPlCiY033XA9HKSjUJvPCF6K56eqY7mAUAsR7NDbmIWDjomLgCREuOS38XAuafVTz209utDwQAAABzeyJvcmlnaW4iOiJjaHJvbWUtZXh0ZW5zaW9uOi8vamdrYm1sZmZlYWRtZWZqZmdrY2tmYnBja3Bvb2loY2UiLCJmZWF0dXJlIjoiQUlTdW1tYXJpemF0aW9uQVBJIiwiZXhwaXJ5IjoxNzUzMTQyNDAwfQ==\"\n  ],\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"permissions\": [\"tabs\", \"scripting\", \"sidePanel\", \"storage\"],\n  \"host_permissions\": [\"http://*/*\", \"https://*/*\"],\n  \"side_panel\": {\n    \"default_path\": \"sidepanel/index.html\"\n  },\n  \"action\": {\n    \"default_icon\": {\n      \"16\": \"images/icon16.png\",\n      \"32\": \"images/icon32.png\",\n      \"48\": \"images/icon48.png\",\n      \"128\": \"images/icon128.png\"\n    },\n    \"default_title\": \"Generate a summary\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-summarization/package.json",
    "content": "{\n  \"name\": \"Summarization Example\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"background.js\",\n  \"scripts\": {\n    \"build\": \"rollup -c rollup.config.mjs\"\n  },\n  \"keywords\": [],\n  \"license\": \"Apache 2.0\",\n  \"devDependencies\": {\n    \"@mozilla/readability\": \"0.5.0\",\n    \"@rollup/plugin-commonjs\": \"28.0.1\",\n    \"@rollup/plugin-node-resolve\": \"15.3.0\",\n    \"dompurify\": \"3.1.7\",\n    \"marked\": \"14.1.4\",\n    \"rollup\": \"4.24.4\",\n    \"rollup-plugin-copy\": \"^3.5.0\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-summarization/rollup.config.mjs",
    "content": "import { nodeResolve } from '@rollup/plugin-node-resolve';\nimport commonjs from '@rollup/plugin-commonjs';\nimport copy from 'rollup-plugin-copy';\n\nexport default [\n  {\n    input: 'sidepanel/index.js',\n    output: {\n      dir: 'dist/sidepanel',\n      format: 'iife',\n    },\n    plugins: [\n      commonjs(),\n      nodeResolve(),\n      copy({\n        targets: [\n          {\n            src: ['manifest.json', 'background.js', 'sidepanel', 'images'],\n            dest: 'dist'\n          }\n        ]\n      })\n    ]\n  },\n  {\n    input: 'scripts/extract-content.js',\n    output: {\n      dir: 'dist/scripts',\n      format: 'es'\n    },\n    plugins: [\n      commonjs(),\n      nodeResolve(),\n    ]\n  }\n];\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-summarization/scripts/extract-content.js",
    "content": "import { isProbablyReaderable, Readability } from '@mozilla/readability';\n\nfunction canBeParsed(document) {\n  return isProbablyReaderable(document, {\n    minContentLength: 100\n  });\n}\n\nfunction parse(document) {\n  if (!canBeParsed(document)) {\n    return false;\n  }\n  const documentClone = document.cloneNode(true);\n  const article = new Readability(documentClone).parse();\n  return article.textContent;\n}\n\nparse(window.document);\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-summarization/sidepanel/index.css",
    "content": "@import 'https://unpkg.com/open-props';\n\n@import 'https://unpkg.com/open-props/normalize.min.css';\n@import 'https://unpkg.com/open-props/buttons.min.css';\n\n:root {\n  --font-size-00: 0.6rem;\n}\n\nbody {\n  margin: auto;\n  padding: var(--size-2);\n  font-size: var(--font-size-2);\n}\n\n:where(ol, ul) {\n  padding: 0 var(--size-3);\n}\n\n[hidden] {\n  display: none !important;\n}\n\nfieldset > * {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  margin-bottom: var(--size-2);\n}\n\n.card {\n  flex-basis: var(--size-content-1);\n  display: flex;\n  flex-direction: column;\n  gap: var(--size-2);\n  background: var(--surface-3);\n  border: 1px solid var(--surface-1);\n  padding: var(--size-4);\n  border-radius: var(--radius-3);\n  box-shadow: var(--shadow-2);\n  margin-bottom: var(--size-2);\n}\n\n.card > h5 {\n  line-height: var(--font-lineheight-1);\n}\n\n.warning {\n  background-color: var(--red-6);\n}\n\n.result {\n  position: relative;\n  background: #00aabb;\n  border-radius: 0.4em;\n  color: white;\n  padding: 1em;\n}\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-summarization/sidepanel/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"index.css\" />\n  </head>\n  <body>\n    <div class=\"card\">\n      <fieldset>\n        <legend>Settings</legend>\n        <div>\n          <label for=\"type\">Summary Type:</label>\n          <select id=\"type\">\n            <option value=\"key-points\" selected>Key Points</option>\n            <option value=\"tldr\">TL;DR</option>\n            <option value=\"teaser\">Teaser</option>\n            <option value=\"headline\">Headline</option>\n          </select>\n        </div>\n        <div>\n          <label for=\"length\">Length:</label>\n          <select id=\"length\">\n            <option value=\"short\" selected>Short</option>\n            <option value=\"medium\">Medium</option>\n            <option value=\"long\">Long</option>\n          </select>\n        </div>\n        <div>\n          <label for=\"format\">Format:</label>\n          <select id=\"format\">\n            <option value=\"markdown\" selected>Markdown</option>\n            <option value=\"plain-text\">Plain text</option>\n          </select>\n        </div>\n      </fieldset>\n    </div>\n    <div class=\"warning card\" hidden id=\"warning\"></div>\n    <div class=\"card\" id=\"summary\">Nothing to show...</div>\n    <script src=\"index.js\" type=\"module\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/ai.gemini-on-device-summarization/sidepanel/index.js",
    "content": "/* global Summarizer */\nimport DOMPurify from 'dompurify';\nimport { marked } from 'marked';\n\n// The underlying model has a context of 1,024 tokens, out of which 26 are used by the internal prompt,\n// leaving about 998 tokens for the input text. Each token corresponds, roughly, to about 4 characters, so 4,000\n// is used as a limit to warn the user the content might be too long to summarize.\nconst MAX_MODEL_CHARS = 4000;\n\nlet pageContent = '';\n\nconst summaryElement = document.body.querySelector('#summary');\nconst warningElement = document.body.querySelector('#warning');\nconst summaryTypeSelect = document.querySelector('#type');\nconst summaryFormatSelect = document.querySelector('#format');\nconst summaryLengthSelect = document.querySelector('#length');\n\nfunction onConfigChange() {\n  const oldContent = pageContent;\n  pageContent = '';\n  onContentChange(oldContent);\n}\n\n[summaryTypeSelect, summaryFormatSelect, summaryLengthSelect].forEach((e) =>\n  e.addEventListener('change', onConfigChange)\n);\n\nchrome.storage.session.get('pageContent', ({ pageContent }) => {\n  onContentChange(pageContent);\n});\n\nchrome.storage.session.onChanged.addListener((changes) => {\n  const pageContent = changes['pageContent'];\n  onContentChange(pageContent.newValue);\n});\n\nasync function onContentChange(newContent) {\n  if (pageContent == newContent) {\n    // no new content, do nothing\n    return;\n  }\n  pageContent = newContent;\n  let summary;\n  if (newContent) {\n    if (newContent.length > MAX_MODEL_CHARS) {\n      updateWarning(\n        `Text is too long for summarization with ${newContent.length} characters (maximum supported content length is ~4000 characters).`\n      );\n    } else {\n      updateWarning('');\n    }\n    showSummary('Loading...');\n    summary = await generateSummary(newContent);\n  } else {\n    summary = \"There's nothing to summarize\";\n  }\n  showSummary(summary);\n}\n\nasync function generateSummary(text) {\n  try {\n    const options = {\n      sharedContext: 'this is a website',\n      type: summaryTypeSelect.value,\n      format: summaryFormatSelect.value,\n      length: length.value\n    };\n\n    const availability = await Summarizer.availability();\n    let summarizer;\n    if (availability === 'unavailable') {\n      return 'Summarizer API is not available';\n    }\n    if (availability === 'available') {\n      // The Summarizer API can be used immediately .\n      summarizer = await Summarizer.create(options);\n    } else {\n      // The Summarizer API can be used after the model is downloaded.\n      summarizer = await Summarizer.create(options);\n      summarizer.addEventListener('downloadprogress', (e) => {\n        console.log(`Downloaded ${e.loaded * 100}%`);\n      });\n      await summarizer.ready;\n    }\n    const summary = await summarizer.summarize(text);\n    summarizer.destroy();\n    return summary;\n  } catch (e) {\n    console.log('Summary generation failed');\n    console.error(e);\n    return 'Error: ' + e.message;\n  }\n}\n\nasync function showSummary(text) {\n  summaryElement.innerHTML = DOMPurify.sanitize(marked.parse(text));\n}\n\nasync function updateWarning(warning) {\n  warningElement.textContent = warning;\n  if (warning) {\n    warningElement.removeAttribute('hidden');\n  } else {\n    warningElement.setAttribute('hidden', '');\n  }\n}\n"
  },
  {
    "path": "functional-samples/cookbook.file_handlers/README.md",
    "content": "# Cookbook - File Handling\n\nThis sample demonstrates file handling in an extension.\n\n## Overview\n\nOn ChromeOS only, extensions can use the `file_handlers` manifest key to\nregister as a file handler for particular file types. This behaves in a similar way to the\n[equivalent key](https://developer.mozilla.org/docs/Web/Manifest/file_handlers) in web\napplications. As with web applications, you use the [Launch Handler API](https://developer.mozilla.org/en-US/docs/Web/API/Launch_Handler_API) to open and process a file.\n\nThis extension lets you open text files and see their name and size on the opened extension page. This could be a good starting point for building an extension that displays or interacts with an opened file.\n\n<img src=\"screenshot.png\" height=300 alt=\"Screenshot showing the File Handling API demo running in Chrome.\">\n\n## Running this extension\n\n**This API is only supported on ChromeOS**.\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Create a text file on your ChromeOS device.\n4. In the Files app, select the file.\n5. In the toolbar, choose \"Open\" and then \"File Handling Demo\".\n"
  },
  {
    "path": "functional-samples/cookbook.file_handlers/manifest.json",
    "content": "{\n  \"name\": \"File Handling Demo\",\n  \"version\": \"1.0\",\n  \"minimum_chrome_version\": \"120\",\n  \"description\": \"Shows how to use the file_handlers manifest key with the web platform's Launch Handler API.\",\n  \"manifest_version\": 3,\n  \"file_handlers\": [\n    {\n      \"name\": \"TXT file\",\n      \"action\": \"/view-file.html\",\n      \"accept\": {\n        \"text/plain\": [\".txt\"]\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "functional-samples/cookbook.file_handlers/view-file.html",
    "content": "<!--\n Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n\n<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>File Handling Demo</title>\n    <script defer src=\"view-file.js\"></script>\n  </head>\n  <body>\n    <pre id=\"data\"></pre>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/cookbook.file_handlers/view-file.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst OUTPUT_ELEMENT_ID = 'data';\n\nasync function consumer(launchParams) {\n  if (!launchParams.files || !launchParams.files.length) return;\n\n  // Get metadata for each file.\n  const files = await Promise.all(\n    launchParams.files.map(async (f) => {\n      const file = await f.getFile();\n\n      return {\n        name: file.name,\n        size: file.size\n      };\n    })\n  );\n\n  // Show data on DOM.\n  document.getElementById(OUTPUT_ELEMENT_ID).innerText = JSON.stringify(\n    files,\n    undefined,\n    2\n  );\n}\n\n// Register a consumer if the launchQueue API is available.\nif ('launchQueue' in window) {\n  window.launchQueue.setConsumer(consumer);\n}\n"
  },
  {
    "path": "functional-samples/cookbook.geolocation-contentscript/README.md",
    "content": "# geolocation via content script\n\nThis recipe shows how to get `geolocation` access within a [content script][5]\n\n## Overview\n\nTo get geolocation information in extensions, use the same [`navigator.geolocation`][6] DOM API that any website normally would. This demo shows how to access this data in a [content script][5]. We also have demos for a [Service Worker][4] (via [offscreen document][2]), and using a [popup][3].\n\n## Running this extension\n\n1. Clone this repository.\n1. Load this directory in Chrome as an [unpacked extension][1].\n1. Navigate to example.com\n1. Inspect the page to see the location being logged to the console.\n\n[1]: https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked\n[2]: https://developer.chrome.com/docs/extensions/reference/offscreen/\n[3]: /functional-samples/cookbook.geolocation-popup\n[4]: /functional-samples/cookbook.geolocation-offscreen\n[5]: https://developer.chrome.com/docs/extensions/mv3/content_scripts/\n[6]: https://developer.mozilla.org/docs/Web/API/Navigator/geolocation\n"
  },
  {
    "path": "functional-samples/cookbook.geolocation-contentscript/content-script.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Registering this listener when the script is first executed ensures that the\n// offscreen document will be able to receive messages when the promise returned\n// by `offscreen.createDocument()` resolves.\n\nconst header = document.querySelector('h1');\n\nconst generateDMS = (coords, isLat) => {\n  const absCoords = Math.abs(coords);\n  const deg = Math.floor(absCoords);\n  const min = Math.floor((absCoords - deg) * 60);\n  const sec = ((absCoords - deg - min / 60) * 3600).toFixed(1);\n  const direction = coords >= 0 ? (isLat ? 'N' : 'E') : isLat ? 'S' : 'W';\n\n  return `${deg}°${min}'${sec}\"${direction}`;\n};\n\nnavigator.geolocation.getCurrentPosition(\n  (loc) => {\n    const { coords } = loc;\n    let { latitude, longitude } = coords;\n    latitude = generateDMS(latitude, true);\n    longitude = generateDMS(longitude);\n\n    console.log(`position: ${latitude}, ${longitude}`);\n  },\n  (err) => {\n    header.innerText = 'error (check console)';\n    console.error(err);\n  }\n);\n"
  },
  {
    "path": "functional-samples/cookbook.geolocation-contentscript/manifest.json",
    "content": "{\n  \"name\": \"Geolocation - content script\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"description\": \"Shows how to get geolocation access within a content script.\",\n  \"content_scripts\": [\n    {\n      \"matches\": [\"https://example.com/*\"],\n      \"js\": [\"content-script.js\"]\n    }\n  ]\n}\n"
  },
  {
    "path": "functional-samples/cookbook.geolocation-offscreen/README.md",
    "content": "# geolocation via offscreen document\n\nThis recipe shows how to get `geolocation` access within a service worker\n\n## Overview\n\nTo get geolocation information in extensions, use the same [`navigator.geolocation`][6] DOM API that any website normally would. This demo shows how to access this data in a Service Worker (via [offscreen document][2]). We also have samples for a [popup][3], or a [content script][4].\n\n## Running this extension\n\n1. Clone this repository.\n1. Load this directory in Chrome as an [unpacked extension][1].\n1. Open the Extension menu and click the extension named \"Geolocation - offscreen\".\n1. Click on the extension's icon to request the location. You can see it by hovering over the icon.\n1. Alternatively, you can open the console for service_worker.js, and call getGeolocation directly.\n\n[1]: https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked\n[2]: https://developer.chrome.com/docs/extensions/reference/offscreen/\n[3]: /functional-samples/cookbook.geolocation-popup\n[4]: /functional-samples/cookbook.geolocation-contentscript\n[6]: https://developer.mozilla.org/docs/Web/API/Navigator/geolocation\n"
  },
  {
    "path": "functional-samples/cookbook.geolocation-offscreen/manifest.json",
    "content": "{\n  \"name\": \"Geolocation - offscreen\",\n  \"version\": \"1.0\",\n  \"description\": \"Shows how to get geolocation access within a service worker.\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"service_worker.js\"\n  },\n  \"action\": {\n    \"default_title\": \"Click to find location...\",\n    \"default_icon\": {\n      \"48\": \"images/grey.png\"\n    }\n  },\n  \"permissions\": [\"offscreen\", \"geolocation\"]\n}\n"
  },
  {
    "path": "functional-samples/cookbook.geolocation-offscreen/offscreen.html",
    "content": "<!doctype html>\n<script src=\"offscreen.js\"></script>\n"
  },
  {
    "path": "functional-samples/cookbook.geolocation-offscreen/offscreen.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Registering this listener when the script is first executed ensures that the\n// offscreen document will be able to receive messages when the promise returned\n// by `offscreen.createDocument()` resolves.\n\nchrome.runtime.onMessage.addListener(handleMessages);\n\nfunction handleMessages(message, sender, sendResponse) {\n  // Return early if this message isn't meant for the offscreen document.\n  if (message.target !== 'offscreen') {\n    return false;\n  }\n\n  if (message.type !== 'get-geolocation') {\n    console.warn(`Unexpected message type received: '${message.type}'.`);\n    return;\n  }\n\n  getGeolocation().then((geolocation) => sendResponse(geolocation));\n\n  // we need to explictly return true in our chrome.runtime.onMessage handler\n  // in order to allow the requestor to handle the request asynchronous.\n  return true;\n}\n\n// getCurrentPosition returns a prototype based object, so the properties\n// end up being stripped off when sent over to our service worker. To get\n// around this, we deeply clone it\nfunction clone(obj) {\n  const copy = {};\n\n  // Return the value of any non true object (typeof(null) is \"object\") directly.\n  // null will throw an error if you try to for/in it. We can just return\n  // the value early.\n  if (obj === null || !(obj instanceof Object)) {\n    return obj;\n  } else {\n    for (const p in obj) {\n      copy[p] = clone(obj[p]);\n    }\n  }\n  return copy;\n}\n\nasync function getGeolocation() {\n  return new Promise((resolve, reject) => {\n    navigator.geolocation.getCurrentPosition(\n      (loc) => resolve(clone(loc)),\n      // in case the user doesnt have or is blocking `geolocation`\n      (err) => reject(err)\n    );\n  });\n}\n"
  },
  {
    "path": "functional-samples/cookbook.geolocation-offscreen/service_worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst OFFSCREEN_DOCUMENT_PATH = '/offscreen.html';\n\n// A global promise to avoid concurrency issues\nlet creating;\nlet locating;\n\n// There can only be one offscreenDocument. So we create a helper function\n// that returns a boolean indicating if a document is already active.\nasync function hasDocument() {\n  // Check all windows controlled by the service worker to see if one\n  // of them is the offscreen document with the given path\n  const matchedClients = await clients.matchAll();\n\n  return matchedClients.some(\n    (c) => c.url === chrome.runtime.getURL(OFFSCREEN_DOCUMENT_PATH)\n  );\n}\n\nasync function setupOffscreenDocument(path) {\n  //if we do not have a document, we are already setup and can skip\n  if (!(await hasDocument())) {\n    // create offscreen document\n    if (creating) {\n      await creating;\n    } else {\n      creating = chrome.offscreen.createDocument({\n        url: path,\n        reasons: [\n          chrome.offscreen.Reason.GEOLOCATION ||\n            chrome.offscreen.Reason.DOM_SCRAPING\n        ],\n        justification: 'add justification for geolocation use here'\n      });\n\n      await creating;\n      creating = null;\n    }\n  }\n}\n\nasync function getGeolocation() {\n  await setupOffscreenDocument(OFFSCREEN_DOCUMENT_PATH);\n\n  const geolocation = await chrome.runtime.sendMessage({\n    type: 'get-geolocation',\n    target: 'offscreen'\n  });\n\n  await closeOffscreenDocument();\n  return geolocation;\n}\n\nasync function closeOffscreenDocument() {\n  if (!(await hasDocument())) {\n    return;\n  }\n  await chrome.offscreen.closeDocument();\n}\n\n// takes a raw coordinate, and returns a DMS formatted string\nconst generateDMS = (coords, isLat) => {\n  const abs = Math.abs(coords);\n  const deg = Math.floor(abs);\n  const min = Math.floor((abs - deg) * 60);\n  const sec = ((abs - deg - min / 60) * 3600).toFixed(1);\n  const direction = coords >= 0 ? (isLat ? 'N' : 'E') : isLat ? 'S' : 'W';\n\n  return `${deg}°${min}'${sec}\"${direction}`;\n};\n\nasync function setTitle(title) {\n  return chrome.action.setTitle({ title });\n}\n\nasync function setIcon(filename) {\n  return chrome.action.setIcon({ path: `images/${filename}.png` });\n}\n\nchrome.action.onClicked.addListener(async () => {\n  try {\n    if (locating) {\n      return await locating;\n    }\n\n    setIcon('lightgreen');\n    await setTitle('locating...');\n\n    locating = await getGeolocation();\n    const { coords } = locating;\n    let { latitude, longitude } = coords;\n    latitude = generateDMS(latitude, true);\n    longitude = generateDMS(longitude);\n\n    setIcon('green');\n    await setTitle(`position: ${latitude}, ${longitude}`);\n  } catch (e) {\n    setIcon('red');\n    await setTitle(`unable to set location - ${e.message}`);\n  }\n\n  locating = null;\n});\n"
  },
  {
    "path": "functional-samples/cookbook.geolocation-popup/README.md",
    "content": "# geolocation inside a popup\n\nThis recipe shows how to get `geolocation` access within a popup\n\n## Overview\n\nTo get geolocation information in extensions, use the same [`navigator.geolocation`][6] DOM API that any website normally would.This demo shows how to access this data in a [popup][3]. We also have demos for a [Service Worker][5](via [offscreen document][2]), and using a [content script][4]\n\n## Running this extension\n\n1. Clone this repository.\n1. Load this directory in Chrome as an [unpacked extension][2].\n1. Open the Extension menu and click the extension named \"Geolocation - popup\".\n\n[1]: https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked\n[2]: https://developer.chrome.com/docs/extensions/reference/offscreen/\n[3]: /functional-samples/cookbook.geolocation-popup\n[4]: /functional-samples/cookbook.geolocation-contentscript\n[5]: /functional-samples/cookbook.geolocation-offscreen\n[6]: https://developer.mozilla.org/docs/Web/API/Navigator/geolocation\n"
  },
  {
    "path": "functional-samples/cookbook.geolocation-popup/manifest.json",
    "content": "{\n  \"name\": \"Geolocation - popup\",\n  \"version\": \"1.0\",\n  \"description\": \"Shows how to get geolocation access within a popup.\",\n  \"manifest_version\": 3,\n  \"action\": {\n    \"default_popup\": \"popup.html\"\n  },\n  \"permissions\": [\"geolocation\"]\n}\n"
  },
  {
    "path": "functional-samples/cookbook.geolocation-popup/popup.html",
    "content": "<!doctype html>\n<head>\n  <title>geolocation - popup</title>\n</head>\n<body>\n  <h1>getting location...</h1>\n  <script src=\"popup.js\"></script>\n</body>\n"
  },
  {
    "path": "functional-samples/cookbook.geolocation-popup/popup.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Registering this listener when the script is first executed ensures that the\n// offscreen document will be able to receive messages when the promise returned\n// by `offscreen.createDocument()` resolves.\n\nconst header = document.querySelector('h1');\n\nconst generateDMS = (coords, isLat) => {\n  const absCoords = Math.abs(coords);\n  const deg = Math.floor(absCoords);\n  const min = Math.floor((absCoords - deg) * 60);\n  const sec = ((absCoords - deg - min / 60) * 3600).toFixed(1);\n  const direction = coords >= 0 ? (isLat ? 'N' : 'E') : isLat ? 'S' : 'W';\n\n  return `${deg}°${min}'${sec}\"${direction}`;\n};\n\nnavigator.geolocation.getCurrentPosition(\n  (loc) => {\n    const { coords } = loc;\n    let { latitude, longitude } = coords;\n    latitude = generateDMS(latitude, true);\n    longitude = generateDMS(longitude);\n\n    header.innerText = `position: ${latitude}, ${longitude}`;\n  },\n  (err) => {\n    header.innerText = 'error (check console)';\n    console.error(err);\n  }\n);\n"
  },
  {
    "path": "functional-samples/cookbook.offscreen-clipboard-write/README.md",
    "content": "This recipe shows how to write a string to the system clipboard using the [Offscreen document][1].\n\n## Context\n\nAs of January 2023, the web platform has two ways to interact with the clipboard: `document.execCommand()` and `navigator.clipboard` (see [MDN's docs][0]). Unfortunately, neither of these APIs are exposed to JavaScript workers. This means that in order for an extension to read from or write values to the system clipboard, the extension _must_ do so in a web page. Enter the Offscreen API. This API was introduced to give extension developers an unobtrusive way to use DOM APIs in the background.\n\nIn the future, the Chrome team is planning to add clipboard support directly to extension service workers. As such, this recipe is written to make it as easy as possible to replace `addToClipboard()`'s offscreen document-based implementation with one that directly uses the appropriate clipboard API.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension][2].\n3. Open the Extension menu and click the extension named \"Offscreen API - Clipboard\".\n\nYou will now have \"Hello, World!\" on your system clipboard.\n\n[0]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard\n[1]: https://developer.chrome.com/docs/extensions/reference/offscreen/\n[2]: https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked\n"
  },
  {
    "path": "functional-samples/cookbook.offscreen-clipboard-write/background.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// The value that will be written to the clipboard.\nconst textToCopy = `Hello world!`;\n\n// When the browser action is clicked, `addToClipboard()` will use an offscreen\n// document to write the value of `textToCopy` to the system clipboard.\nchrome.action.onClicked.addListener(async () => {\n  await addToClipboard(textToCopy);\n});\n\n// Solution 1 - As of Jan 2023, service workers cannot directly interact with\n// the system clipboard using either `navigator.clipboard` or\n// `document.execCommand()`. To work around this, we'll create an offscreen\n// document and pass it the data we want to write to the clipboard.\nasync function addToClipboard(value) {\n  await chrome.offscreen.createDocument({\n    url: 'offscreen.html',\n    reasons: [chrome.offscreen.Reason.CLIPBOARD],\n    justification: 'Write text to the clipboard.'\n  });\n\n  // Now that we have an offscreen document, we can dispatch the\n  // message.\n  chrome.runtime.sendMessage({\n    type: 'copy-data-to-clipboard',\n    target: 'offscreen-doc',\n    data: value\n  });\n}\n\n// Solution 2 – Once extension service workers can use the Clipboard API,\n// replace the offscreen document based implementation with something like this.\n// eslint-disable-next-line no-unused-vars -- This is an alternative implementation\nasync function addToClipboardV2(value) {\n  navigator.clipboard.writeText(value);\n}\n"
  },
  {
    "path": "functional-samples/cookbook.offscreen-clipboard-write/manifest.json",
    "content": "{\n  \"name\": \"Offscreen API - Clipboard\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"description\": \"Shows how to write a string to the system clipboard using the offscreen document.\",\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"action\": {},\n  \"permissions\": [\"offscreen\", \"clipboardWrite\"]\n}\n"
  },
  {
    "path": "functional-samples/cookbook.offscreen-clipboard-write/offscreen.html",
    "content": "<!doctype html>\n<textarea id=\"text\"></textarea>\n<script src=\"offscreen.js\"></script>\n"
  },
  {
    "path": "functional-samples/cookbook.offscreen-clipboard-write/offscreen.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Once the message has been posted from the service worker, checks are made to\n// confirm the message type and target before proceeding. This is so that the\n// module can easily be adapted into existing workflows where secondary uses for\n// the document (or alternate offscreen documents) might be implemented.\n\n// Registering this listener when the script is first executed ensures that the\n// offscreen document will be able to receive messages when the promise returned\n// by `offscreen.createDocument()` resolves.\nchrome.runtime.onMessage.addListener(handleMessages);\n\n// This function performs basic filtering and error checking on messages before\n// dispatching the\n// message to a more specific message handler.\nasync function handleMessages(message) {\n  // Return early if this message isn't meant for the offscreen document.\n  if (message.target !== 'offscreen-doc') {\n    return;\n  }\n\n  // Dispatch the message to an appropriate handler.\n  switch (message.type) {\n    case 'copy-data-to-clipboard':\n      handleClipboardWrite(message.data);\n      break;\n    default:\n      console.warn(`Unexpected message type received: '${message.type}'.`);\n  }\n}\n\n// We use a <textarea> element for two main reasons:\n//  1. preserve the formatting of multiline text,\n//  2. select the node's content using this element's `.select()` method.\nconst textEl = document.querySelector('#text');\n\n// Use the offscreen document's `document` interface to write a new value to the\n// system clipboard.\n//\n// At the time this demo was created (Jan 2023) the `navigator.clipboard` API\n// requires that the window is focused, but offscreen documents cannot be\n// focused. As such, we have to fall back to `document.execCommand()`.\nasync function handleClipboardWrite(data) {\n  try {\n    // Error if we received the wrong kind of data.\n    if (typeof data !== 'string') {\n      throw new TypeError(\n        `Value provided must be a 'string', got '${typeof data}'.`\n      );\n    }\n\n    // `document.execCommand('copy')` works against the user's selection in a web\n    // page. As such, we must insert the string we want to copy to the web page\n    // and to select that content in the page before calling `execCommand()`.\n    textEl.value = data;\n    textEl.select();\n    document.execCommand('copy');\n  } finally {\n    // Job's done! Close the offscreen document.\n    window.close();\n  }\n}\n"
  },
  {
    "path": "functional-samples/cookbook.offscreen-dom/README.md",
    "content": "This recipe shows how to use DOMParser in an Extension Service Worker using the [Offscreen document][1].\n\n## Context\n\nExtension Service Workers don't have direct access to the DOM. This example demonstrates how to use an\noffscreen document for parsing and modifying DOM from an Extension Service Worker. Offscreen documents\nand Extension Service Workers exchange data using message passing.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension][2].\n3. Open the Extension menu and click the extension named \"Offscreen API - DOM Parsing\".\n\nIf you inspect the Extension Service Worker in Chrome DevTools, you can see the result of the DOM transformation in the console view.\n\n[1]: https://developer.chrome.com/docs/extensions/reference/offscreen/\n[2]: https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked\n"
  },
  {
    "path": "functional-samples/cookbook.offscreen-dom/background.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst OFFSCREEN_DOCUMENT_PATH = '/offscreen.html';\n\nchrome.action.onClicked.addListener(async () => {\n  sendMessageToOffscreenDocument(\n    'add-exclamationmarks-to-headings',\n    '<html><head></head><body><h1>Hello World</h1></body></html>'\n  );\n});\n\nasync function sendMessageToOffscreenDocument(type, data) {\n  // Create an offscreen document if one doesn't exist yet\n  if (!(await hasDocument())) {\n    await chrome.offscreen.createDocument({\n      url: OFFSCREEN_DOCUMENT_PATH,\n      reasons: [chrome.offscreen.Reason.DOM_PARSER],\n      justification: 'Parse DOM'\n    });\n  }\n  // Now that we have an offscreen document, we can dispatch the\n  // message.\n  chrome.runtime.sendMessage({\n    type,\n    target: 'offscreen',\n    data\n  });\n}\n\nchrome.runtime.onMessage.addListener(handleMessages);\n\n// This function performs basic filtering and error checking on messages before\n// dispatching the message to a more specific message handler.\nasync function handleMessages(message) {\n  // Return early if this message isn't meant for the background script\n  if (message.target !== 'background') {\n    return;\n  }\n\n  // Dispatch the message to an appropriate handler.\n  switch (message.type) {\n    case 'add-exclamationmarks-result':\n      handleAddExclamationMarkResult(message.data);\n      closeOffscreenDocument();\n      break;\n    default:\n      console.warn(`Unexpected message type received: '${message.type}'.`);\n  }\n}\n\nasync function handleAddExclamationMarkResult(dom) {\n  console.log('Received dom', dom);\n}\n\nasync function closeOffscreenDocument() {\n  if (!(await hasDocument())) {\n    return;\n  }\n  await chrome.offscreen.closeDocument();\n}\n\nasync function hasDocument() {\n  // Check all windows controlled by the service worker if one of them is the offscreen document\n  const matchedClients = await clients.matchAll();\n  for (const client of matchedClients) {\n    if (client.url.endsWith(OFFSCREEN_DOCUMENT_PATH)) {\n      return true;\n    }\n  }\n  return false;\n}\n"
  },
  {
    "path": "functional-samples/cookbook.offscreen-dom/manifest.json",
    "content": "{\n  \"name\": \"Offscreen API - DOM Parsing\",\n  \"version\": \"1.0\",\n  \"description\": \"Shows how to use DOMParser in an extension service worker using the offscreen document.\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"action\": {},\n  \"permissions\": [\"offscreen\"]\n}\n"
  },
  {
    "path": "functional-samples/cookbook.offscreen-dom/offscreen.html",
    "content": "<!doctype html>\n<script src=\"offscreen.js\"></script>\n"
  },
  {
    "path": "functional-samples/cookbook.offscreen-dom/offscreen.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// Registering this listener when the script is first executed ensures that the\n// offscreen document will be able to receive messages when the promise returned\n// by `offscreen.createDocument()` resolves.\nchrome.runtime.onMessage.addListener(handleMessages);\n\n// This function performs basic filtering and error checking on messages before\n// dispatching the message to a more specific message handler.\nasync function handleMessages(message) {\n  // Return early if this message isn't meant for the offscreen document.\n  if (message.target !== 'offscreen') {\n    return false;\n  }\n\n  // Dispatch the message to an appropriate handler.\n  switch (message.type) {\n    case 'add-exclamationmarks-to-headings':\n      addExclamationMarksToHeadings(message.data);\n      break;\n    default:\n      console.warn(`Unexpected message type received: '${message.type}'.`);\n      return false;\n  }\n}\n\nfunction addExclamationMarksToHeadings(htmlString) {\n  const parser = new DOMParser();\n  const document = parser.parseFromString(htmlString, 'text/html');\n  document\n    .querySelectorAll('h1')\n    .forEach((heading) => (heading.textContent = heading.textContent + '!!!'));\n  sendToBackground(\n    'add-exclamationmarks-result',\n    document.documentElement.outerHTML\n  );\n}\n\nfunction sendToBackground(type, data) {\n  chrome.runtime.sendMessage({\n    type,\n    target: 'background',\n    data\n  });\n}\n"
  },
  {
    "path": "functional-samples/cookbook.permissions-addhostaccessrequest/README.md",
    "content": "# permissions.addHostAccessRequest() Demo\n\nThis sample demonstrates using the `permissions.addHostAccessRequest` API to request access to a host.\n\n## Overview\n\nThis API allows you to request access to an origin listed in `optional_host_permissions` (or withheld by the user) at runtime.\n\n## Running this extension\n\n1. Clone this repository.\n2. Make sure you have the latest version of Chrome Canary installed.\n3. At chrome://flags, enable the \"Extensions Menu Access Control\" flag.\n4. Restart Chrome Canary.\n5. Load this directory as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n6. At chrome://extensions, click on \"Details\" for the extension and unselect \"Automatically allow access on the following sites\".\n7. Visit https://example.com/checkout.\n8. Click \"Allow 1?\"\n\nYou will see a banner injected on the page to show that the extension has run.\n"
  },
  {
    "path": "functional-samples/cookbook.permissions-addhostaccessrequest/background.js",
    "content": "// Copyright 2024 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n/**\n * Adds a host access request if the user visits https://example.com/checkout.\n * This could be useful for an extension that wishes to offer users coupons or\n * order tracking but needs access to the site to do so.\n */\nchrome.tabs.onUpdated.addListener(async (tabId, changes) => {\n  if (typeof changes.url !== 'string') return;\n\n  const url = new URL(changes.url);\n\n  // If we are on the /checkout page of example.com.\n  if (url.origin === 'https://example.com' && url.pathname === '/checkout') {\n    const hasPermission = await chrome.permissions.contains({\n      origins: ['https://example.com/*']\n    });\n\n    // We already have host permissions.\n    if (hasPermission) {\n      return;\n    }\n\n    // Add a host access request if the API is available.\n    if (chrome.permissions.addHostAccessRequest) {\n      chrome.permissions.addHostAccessRequest({ tabId });\n    }\n  }\n});\n\nchrome.permissions.onAdded.addListener((permissions) => {\n  if (permissions.origins?.includes('https://example.com/*')) {\n    console.log('Permission granted.');\n    // FIXME: Run any code you wanted to run here.\n  }\n});\n"
  },
  {
    "path": "functional-samples/cookbook.permissions-addhostaccessrequest/banner.js",
    "content": "const banner = document.createElement('div');\nbanner.innerText = 'Extension has access to page.';\n\nbanner.style.width = '100vw';\nbanner.style.position = 'fixed';\nbanner.style.top = '0';\nbanner.style.left = '0';\nbanner.style.margin = '0';\nbanner.style.borderRadius = '0';\nbanner.style.padding = '20px';\nbanner.style.background = '#4CAF50';\nbanner.style.color = 'white';\n\ndocument.body.prepend(banner);\n"
  },
  {
    "path": "functional-samples/cookbook.permissions-addhostaccessrequest/manifest.json",
    "content": "{\n  \"name\": \"Permissions (Add Host Access Request)\",\n  \"description\": \"Uses the `permissions.addHostAccessRequest()` API to request access to a site.\",\n  \"version\": \"0.3\",\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"host_permissions\": [\"https://example.com/*\"],\n  \"permissions\": [\"tabs\", \"scripting\"],\n  \"content_scripts\": [\n    {\n      \"matches\": [\"https://example.com/*\"],\n      \"js\": [\"banner.js\"]\n    }\n  ],\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "functional-samples/cookbook.push/README.md",
    "content": "# Service worker with push notification\n\nThis sample demonstrates using the [Push API](https://developer.mozilla.org/en-US/docs/Web/API/Push_API) with `self.registration.pushManager.subscribe()` and specifically how to use `userVisibleOnly` to silence required notifications when receiving a push message in a service worker based extension.\n\n## Overview\n\nBy calling a method in the sample and using an external push server website we can simulate an extension receiving a push message where it is not required to emit a notification by setting (`userVisibleOnly = false`) on registration.\n\n## Running this extension\n\nNote: This sample requires Chrome 132+. Before Chrome 132, the same code works with the additional requirement of the `notification` extension permission.\n\n1. Clone this repository.\n1. Go to the [web push test server](https://web-push-codelab.glitch.me/) and copy the “Public Key” to the `APPLICATION_SERVER_PUBLIC_KEY` variable in background.js.\n1. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n1. Click “service worker (Inactive)” on the extension to load DevTools for background.js\n1. In DevTools call: `await subscribeUserVisibleOnlyFalse();`\n1. Copy the output after “Subscription data to be sent to the push notification server:” and paste it into the [web push test server](https://web-push-codelab.glitch.me/) inside “Subscription to Send To” text box\n1. Enter some text into “Text to Send”\n1. Click “SEND PUSH MESSAGE”\n1. Observe that there is no notification with the text you sent in the browser and no generic notification notification being shown by the browser (that is usually enforced). You’ll see the text you sent in the DevTools log proving the extension service worker received the push data.\n"
  },
  {
    "path": "functional-samples/cookbook.push/background.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n/*eslint no-unused-vars: [\"error\", { \"varsIgnorePattern\": \"subscribeUserVisibleOnlyFalse\" }]*/\n\nconst APPLICATION_SERVER_PUBLIC_KEY = '<key>';\n\nasync function subscribeUserVisibleOnlyFalse() {\n  const applicationServerKey = urlB64ToUint8Array(\n    APPLICATION_SERVER_PUBLIC_KEY\n  );\n  try {\n    let subscriptionData = await self.registration.pushManager.subscribe({\n      // With our new change[1], this can be set to false. Before it must\n      // always be set to true otherwise an error will be thrown about\n      // permissions denied.\n      userVisibleOnly: false,\n      applicationServerKey: applicationServerKey\n    });\n    console.log('[Service Worker] Extension is subscribed to push server.');\n    logSubscriptionDataToConsole(subscriptionData);\n  } catch (error) {\n    console.error('[Service Worker] Failed to subscribe, error: ', error);\n  }\n}\n\nfunction logSubscriptionDataToConsole(subscription) {\n  // The `subscription` data would normally only be know by the push server,\n  // but for this sample we'll print it out to the console so it can be pasted\n  // into a testing push notification server (at\n  // https://web-push-codelab.glitch.me/) to send push messages to this\n  // endpoint (extension).\n  console.log(\n    '[Service Worker] Subscription data to be pasted in the test push' +\n      'notification server: '\n  );\n  console.log(JSON.stringify(subscription));\n}\n\n// Push message event listener.\nself.addEventListener('push', function (event) {\n  console.log('[Service Worker] Push Received.');\n  console.log(\n    `[Service Worker] Push had this data/text: \"${event.data.text()}\"`\n  );\n\n  // Before `userVisibleOnly` could be passed as false we would have to show a\n  // notification at this point (or if we didn't the browser would show a\n  // generic notification), but now we no longer have to.\n});\n\n// Helper method for converting the server key to an array that is passed\n// when subscribing to a push server.\nfunction urlB64ToUint8Array(base64String) {\n  const padding = '='.repeat((4 - (base64String.length % 4)) % 4);\n  const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');\n\n  const rawData = atob(base64);\n  const outputArray = new Uint8Array(rawData.length);\n\n  for (let i = 0; i < rawData.length; ++i) {\n    outputArray[i] = rawData.charCodeAt(i);\n  }\n  return outputArray;\n}\n\n// [1]: https://chromiumdash.appspot.com/commit/f6a8800208dc4bc20a0250a7964983ce5aa746f0\n"
  },
  {
    "path": "functional-samples/cookbook.push/manifest.json",
    "content": "{\n  \"name\": \"Service worker with silent push message\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-global/README.md",
    "content": "# Global Side panel example\n\nThis example demonstrates how to display the same side panel on every site using the [Side Panel API](https://developer.chrome.com/docs/extensions/reference/sidePanel/).\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Open the side panel UI\n\n   <img src=\"../../.repo/images/global-side-panel.png\" alt=\"Global side panel\" width=400>\n\n4. Choose the \"Global side panel\".\n\n   <img src=\"../../.repo/images/global-side-panel-open.png\" alt=\"Global side panel\" width=700>\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-global/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Global side panel\",\n  \"version\": \"1.0\",\n  \"description\": \"Shows how to display the same side panel on every site using the Side Panel API.\",\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"48\": \"images/icon-48.png\",\n    \"128\": \"images/icon-128.png\"\n  },\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"action\": {\n    \"default_title\": \"Click to open panel\"\n  },\n  \"side_panel\": {\n    \"default_path\": \"sidepanel.html\"\n  },\n  \"permissions\": [\"sidePanel\"]\n}\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-global/service-worker.js",
    "content": "chrome.runtime.onInstalled.addListener(() => {\n  chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true });\n});\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-global/sidepanel.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>My Sidepanel</title>\n  </head>\n  <body>\n    <h1>All sites sidepanel extension</h1>\n    <p>This side panel is enabled on all sites</p>\n    <script src=\"sidepanel.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-global/sidepanel.js",
    "content": "console.log('sidepanel.js');\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-multiple/README.md",
    "content": "# Multiple side panels example\n\nYou can use [`sidepanel.getOptions()`](https://developer.chrome.com/docs/extensions/reference/sidePanel/#method-getOptions) to retrieve the current side panel and switch between side panels. This example sets a welcome side panel when the extension is first installed, then when the user navigates to a different tab, it replaces it with the main side panel.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Open the side panel UI\n4. Choose \"Multiple side panels\" to see the welcome page.\n\n<img src=\"../../.repo/images/multiple-side-panel-welcome.png\" alt=\"Welcome side panel\" width=600>\n\n5. Navigate to https://developer.chrome.com to see the main side panel.\n\n<img src=\"../../.repo/images/multiple-side-panel-main.png\" alt=\"Main side panel\" width=600>\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-multiple/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Multiple side panels\",\n  \"version\": \"1.0\",\n  \"description\": \"This recipe shows how to use sidePanel.getOptions() to retrieve the current side panel and switch between side panels.\",\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"action\": {\n    \"default_title\": \"Click to open panel\"\n  },\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"48\": \"images/icon-48.png\",\n    \"128\": \"images/icon-128.png\"\n  },\n  \"permissions\": [\"sidePanel\"]\n}\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-multiple/service-worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst welcomePage = 'sidepanels/welcome-sp.html';\nconst mainPage = 'sidepanels/main-sp.html';\n\nchrome.runtime.onInstalled.addListener(() => {\n  chrome.sidePanel.setOptions({ path: welcomePage });\n  chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true });\n});\n\nchrome.tabs.onActivated.addListener(async ({ tabId }) => {\n  const { path } = await chrome.sidePanel.getOptions({ tabId });\n  if (path === welcomePage) {\n    chrome.sidePanel.setOptions({ path: mainPage });\n  }\n});\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-multiple/sidepanels/main-sp.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>My Sidepanel extension</title>\n  </head>\n  <body>\n    <h1>This is the main side panel</h1>\n    <p>Use this extension to make your dreams come true!</p>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-multiple/sidepanels/welcome-sp.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Welcome to this side panel</title>\n  </head>\n  <body>\n    <h1>Welcome!</h1>\n    <p>Thank you for installing this side panel extension</p>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-open/README.md",
    "content": "# Opening the side panel through a user interaction\n\nThis example demonstrates using [`chrome.sidePanel.open()`](https://developer.chrome.com/docs/extensions/reference/sidePanel/#method-open) to open a global side panel through a context menu click and a tab-specific side panel by clicking a button in an extension page or a button click injected by a content script. This feature will be available starting **Chrome 116**.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n\n### Test with a context menu\n\n1. Navigate to any page, like [example.com](http://example.com/).\n2. Right-click on any word.\n3. Choose the context menu \"Open side panel\".\n\n### Test in an extension page\n\n1. The extension page will open when you install the extension.\n2. Click on the \"Open side panel\" button.\n\n### Test by clicking on an injected element\n\n1. Navigate to [google.com](http://www.google.com/).\n2. Scroll to the very bottom of the page.\n3. Click on the \"Open side panel\" button.\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-open/content-script.js",
    "content": "const button = new DOMParser().parseFromString(\n  '<button>Click to open side panel</button>',\n  'text/html'\n).body.firstElementChild;\nbutton.addEventListener('click', function () {\n  chrome.runtime.sendMessage({ type: 'open_side_panel' });\n});\ndocument.body.append(button);\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-open/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Open side panel\",\n  \"version\": \"1.0\",\n  \"description\": \"Shows how to call sidePanel.open() to open a global side panel.\",\n  \"minimum_chrome_version\": \"116\",\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"side_panel\": {\n    \"default_path\": \"sidepanel-global.html\"\n  },\n  \"content_scripts\": [\n    {\n      \"js\": [\"content-script.js\"],\n      \"matches\": [\"https://www.google.com/*\"]\n    }\n  ],\n  \"permissions\": [\"sidePanel\", \"contextMenus\"],\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"48\": \"images/icon-48.png\",\n    \"128\": \"images/icon-128.png\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-open/page.html",
    "content": "<!doctype html>\n<html>\n  <body>\n    <h1>This is an extension page</h1>\n    <p>Click on the button below to open the side panel</p>\n    <button id=\"openSidePanel\">Open side panel</button>\n    <script src=\"script.js\" type=\"module\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-open/script.js",
    "content": "// top level await is available in ES modules loaded from script tags\nconst [tab] = await chrome.tabs.query({\n  active: true,\n  lastFocusedWindow: true\n});\n\nconst tabId = tab.id;\nconst button = document.getElementById('openSidePanel');\nbutton.addEventListener('click', async () => {\n  await chrome.sidePanel.open({ tabId });\n  await chrome.sidePanel.setOptions({\n    tabId,\n    path: 'sidepanel-tab.html',\n    enabled: true\n  });\n});\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-open/service-worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.runtime.onInstalled.addListener(() => {\n  chrome.contextMenus.create({\n    id: 'openSidePanel',\n    title: 'Open side panel',\n    contexts: ['all']\n  });\n  chrome.tabs.create({ url: 'page.html' });\n});\n\nchrome.contextMenus.onClicked.addListener((info, tab) => {\n  if (info.menuItemId === 'openSidePanel') {\n    // This will open the panel in all the pages on the current window.\n    chrome.sidePanel.open({ windowId: tab.windowId });\n  }\n});\n\nchrome.runtime.onMessage.addListener((message, sender) => {\n  // The callback for runtime.onMessage must return falsy if we're not sending a response\n  (async () => {\n    if (message.type === 'open_side_panel') {\n      // This will open a tab-specific side panel only on the current tab.\n      await chrome.sidePanel.open({ tabId: sender.tab.id });\n      await chrome.sidePanel.setOptions({\n        tabId: sender.tab.id,\n        path: 'sidepanel-tab.html',\n        enabled: true\n      });\n    }\n  })();\n});\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-open/sidepanel-global.html",
    "content": "<!doctype html>\n<html>\n  <body>\n    <h1>Global side panel</h1>\n    <p>\n      This is a global side panel, which means it remains open on every tab.\n    </p>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-open/sidepanel-tab.html",
    "content": "<!doctype html>\n<html>\n  <body>\n    <h1>Tab-specific side panel</h1>\n    <p>This side panel is available and stays open only on the current tab</p>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-site-specific/README.md",
    "content": "# Site-specific side panel example\n\nThis example demonstrates how to display the side panel only on google.com using the [Side Panel API](https://developer.chrome.com/docs/extensions/reference/sidePanel/). It also allows users to open the side panel by clicking on the [action icon](https://developer.chrome.com/docs/extensions/reference/action/) or a keyboard shortcut.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. [Pin](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#pin) the extension.\n4. Go to https://www.google.com.\n5. Click on the action icon to open the side panel.\n\n💡 You can also open the side panel by pressing `Ctrl+B` (Windows) or `Cmd+B` (macOS).\n\n<img src=\"../../.repo/images/site-specific-side-panel.png\" alt=\"Google.com side panel\" width=700>\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-site-specific/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Site-specific side panel\",\n  \"version\": \"1.0\",\n  \"description\": \"Shows how to display the side panel only on google.com using the Side Panel API.\",\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"action\": {\n    \"default_title\": \"Click to open panel\"\n  },\n  \"permissions\": [\"sidePanel\", \"tabs\"],\n  \"commands\": {\n    \"_execute_action\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+B\",\n        \"mac\": \"Command+B\"\n      }\n    }\n  },\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"48\": \"images/icon-48.png\",\n    \"128\": \"images/icon-128.png\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-site-specific/service-worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst GOOGLE_ORIGIN = 'https://www.google.com';\n\n// Allows users to open the side panel by clicking on the action toolbar icon\nchrome.sidePanel\n  .setPanelBehavior({ openPanelOnActionClick: true })\n  .catch((error) => console.error(error));\n\nchrome.tabs.onUpdated.addListener(async (tabId, info, tab) => {\n  if (!tab.url) return;\n  const url = new URL(tab.url);\n  // Enables the side panel on google.com\n  if (url.origin === GOOGLE_ORIGIN) {\n    await chrome.sidePanel.setOptions({\n      tabId,\n      path: 'sidepanel.html',\n      enabled: true\n    });\n  } else {\n    // Disables the side panel on all other sites\n    await chrome.sidePanel.setOptions({\n      tabId,\n      enabled: false\n    });\n  }\n});\n"
  },
  {
    "path": "functional-samples/cookbook.sidepanel-site-specific/sidepanel.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>My Google side panel extension</title>\n  </head>\n  <body>\n    <h1>My google.com sidepanel</h1>\n    <p>This side panel will display only on www.google.com</p>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print/README.md",
    "content": "# Using WASM as a module in Manifest V3\n\nThis recipe shows how to use WASM in Manifest V3.\n\nTo load WASM in Manifest V3, we need to use the `wasm-unsafe-eval` CSP directive ([Content Security Policy][0]).\n\n## Overview\n\n### Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Find the extension named \"WASM Load Example - Helloworld\" and [inspect the service worker](https://developer.chrome.com/docs/extensions/mv3/tut_debugging/#debug-bg).\n\nYou will see the following output:\n\n```\n[from wasm] Inited.\n[from wasm] Hello World!\n[from wasm] Hello John\n```\n\n### Build WASM locally\n\nWe have already built the WASM file for you. If you want to build it yourself, follow the steps below.\n\n1. Install [Rust](https://www.rust-lang.org/install.html).\n\n2. Install [wasm-pack](https://rustwasm.github.io/wasm-pack/installer/).\n\n   ```bash\n   cargo install wasm-pack\n   ```\n\n3. Build WASM.\n\n   ```bash\n   cd wasm\n   wasm-pack build --target web\n   ```\n\n## Implementation Notes\n\n- To import the script generated by `wasm-pack`, we need to [declare the service worker as an ES Module][1].\n\n```diff\n // manifest.json\n ...\n \"background\": {\n     \"service_worker\": \"background.js\",\n+    \"type\": \"module\"\n },\n ...\n```\n\n[0]: https://developer.chrome.com/docs/extensions/mv3/manifest/content_security_policy/\n[1]: https://developer.chrome.com/docs/extensions/mv3/service_workers/basics/#import-scripts\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print/background.js",
    "content": "import init, { print, print_with_value } from './wasm/pkg/helloworld_demo.js';\n\nchrome.runtime.onInstalled.addListener(() => {\n  runDemo();\n});\n\nasync function runDemo() {\n  // Initialize the WASM module\n  await init();\n\n  // Call the exported functions from the WASM module\n  print();\n  print_with_value('John');\n}\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print/manifest.json",
    "content": "{\n  \"name\": \"WASM Load Example - Helloworld\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"description\": \"Shows how to use WebAssembly (WASM) as a module in Manifest V3.\",\n  \"background\": {\n    \"service_worker\": \"background.js\",\n    \"type\": \"module\"\n  },\n  \"content_security_policy\": {\n    \"extension_pages\": \"default-src 'self' 'wasm-unsafe-eval'\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print/wasm/.gitignore",
    "content": "target\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print/wasm/Cargo.toml",
    "content": "[package]\nname = \"helloworld-demo\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\nwasm-bindgen = \"0.2.84\"\nweb-sys = { version = \"0.3.61\", features = ['console'] }\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print/wasm/pkg/helloworld_demo.d.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n/**\n*/\nexport function main(): void;\n/**\n*/\nexport function print(): void;\n/**\n* @param {string} value\n*/\nexport function print_with_value(value: string): void;\n\nexport type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;\n\nexport interface InitOutput {\n  readonly memory: WebAssembly.Memory;\n  readonly main: () => void;\n  readonly print: () => void;\n  readonly print_with_value: (a: number, b: number) => void;\n  readonly __wbindgen_malloc: (a: number) => number;\n  readonly __wbindgen_realloc: (a: number, b: number, c: number) => number;\n  readonly __wbindgen_start: () => void;\n}\n\nexport type SyncInitInput = BufferSource | WebAssembly.Module;\n/**\n* Instantiates the given `module`, which can either be bytes or\n* a precompiled `WebAssembly.Module`.\n*\n* @param {SyncInitInput} module\n*\n* @returns {InitOutput}\n*/\nexport function initSync(module: SyncInitInput): InitOutput;\n\n/**\n* If `module_or_path` is {RequestInfo} or {URL}, makes a request and\n* for everything else, calls `WebAssembly.instantiate` directly.\n*\n* @param {InitInput | Promise<InitInput>} module_or_path\n*\n* @returns {Promise<InitOutput>}\n*/\nexport default function __wbg_init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print/wasm/pkg/helloworld_demo.js",
    "content": "let wasm;\n\nconst cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );\n\nif (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };\n\nlet cachedUint8Memory0 = null;\n\nfunction getUint8Memory0() {\n    if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {\n        cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);\n    }\n    return cachedUint8Memory0;\n}\n\nfunction getStringFromWasm0(ptr, len) {\n    ptr = ptr >>> 0;\n    return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));\n}\n\nconst heap = new Array(128).fill(undefined);\n\nheap.push(undefined, null, true, false);\n\nlet heap_next = heap.length;\n\nfunction addHeapObject(obj) {\n    if (heap_next === heap.length) heap.push(heap.length + 1);\n    const idx = heap_next;\n    heap_next = heap[idx];\n\n    heap[idx] = obj;\n    return idx;\n}\n\nfunction getObject(idx) { return heap[idx]; }\n\nfunction dropObject(idx) {\n    if (idx < 132) return;\n    heap[idx] = heap_next;\n    heap_next = idx;\n}\n\nfunction takeObject(idx) {\n    const ret = getObject(idx);\n    dropObject(idx);\n    return ret;\n}\n/**\n*/\nexport function main() {\n    wasm.main();\n}\n\n/**\n*/\nexport function print() {\n    wasm.print();\n}\n\nlet WASM_VECTOR_LEN = 0;\n\nconst cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );\n\nconst encodeString = (typeof cachedTextEncoder.encodeInto === 'function'\n    ? function (arg, view) {\n    return cachedTextEncoder.encodeInto(arg, view);\n}\n    : function (arg, view) {\n    const buf = cachedTextEncoder.encode(arg);\n    view.set(buf);\n    return {\n        read: arg.length,\n        written: buf.length\n    };\n});\n\nfunction passStringToWasm0(arg, malloc, realloc) {\n\n    if (realloc === undefined) {\n        const buf = cachedTextEncoder.encode(arg);\n        const ptr = malloc(buf.length) >>> 0;\n        getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);\n        WASM_VECTOR_LEN = buf.length;\n        return ptr;\n    }\n\n    let len = arg.length;\n    let ptr = malloc(len) >>> 0;\n\n    const mem = getUint8Memory0();\n\n    let offset = 0;\n\n    for (; offset < len; offset++) {\n        const code = arg.charCodeAt(offset);\n        if (code > 0x7F) break;\n        mem[ptr + offset] = code;\n    }\n\n    if (offset !== len) {\n        if (offset !== 0) {\n            arg = arg.slice(offset);\n        }\n        ptr = realloc(ptr, len, len = offset + arg.length * 3) >>> 0;\n        const view = getUint8Memory0().subarray(ptr + offset, ptr + len);\n        const ret = encodeString(arg, view);\n\n        offset += ret.written;\n    }\n\n    WASM_VECTOR_LEN = offset;\n    return ptr;\n}\n/**\n* @param {string} value\n*/\nexport function print_with_value(value) {\n    const ptr0 = passStringToWasm0(value, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n    const len0 = WASM_VECTOR_LEN;\n    wasm.print_with_value(ptr0, len0);\n}\n\nasync function __wbg_load(module, imports) {\n    if (typeof Response === 'function' && module instanceof Response) {\n        if (typeof WebAssembly.instantiateStreaming === 'function') {\n            try {\n                return await WebAssembly.instantiateStreaming(module, imports);\n\n            } catch (e) {\n                if (module.headers.get('Content-Type') != 'application/wasm') {\n                    console.warn(\"`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\\n\", e);\n\n                } else {\n                    throw e;\n                }\n            }\n        }\n\n        const bytes = await module.arrayBuffer();\n        return await WebAssembly.instantiate(bytes, imports);\n\n    } else {\n        const instance = await WebAssembly.instantiate(module, imports);\n\n        if (instance instanceof WebAssembly.Instance) {\n            return { instance, module };\n\n        } else {\n            return instance;\n        }\n    }\n}\n\nfunction __wbg_get_imports() {\n    const imports = {};\n    imports.wbg = {};\n    imports.wbg.__wbindgen_string_new = function(arg0, arg1) {\n        const ret = getStringFromWasm0(arg0, arg1);\n        return addHeapObject(ret);\n    };\n    imports.wbg.__wbindgen_object_drop_ref = function(arg0) {\n        takeObject(arg0);\n    };\n    imports.wbg.__wbg_log_003c998d6df63565 = function(arg0) {\n        console.log(getObject(arg0));\n    };\n    imports.wbg.__wbg_log_12a0c96d2facdfce = function(arg0, arg1) {\n        console.log(getObject(arg0), getObject(arg1));\n    };\n    imports.wbg.__wbindgen_throw = function(arg0, arg1) {\n        throw new Error(getStringFromWasm0(arg0, arg1));\n    };\n\n    return imports;\n}\n\nfunction __wbg_init_memory(imports, maybe_memory) {\n\n}\n\nfunction __wbg_finalize_init(instance, module) {\n    wasm = instance.exports;\n    __wbg_init.__wbindgen_wasm_module = module;\n    cachedUint8Memory0 = null;\n\n    wasm.__wbindgen_start();\n    return wasm;\n}\n\nfunction initSync(module) {\n    if (wasm !== undefined) return wasm;\n\n    const imports = __wbg_get_imports();\n\n    __wbg_init_memory(imports);\n\n    if (!(module instanceof WebAssembly.Module)) {\n        module = new WebAssembly.Module(module);\n    }\n\n    const instance = new WebAssembly.Instance(module, imports);\n\n    return __wbg_finalize_init(instance, module);\n}\n\nasync function __wbg_init(input) {\n    if (wasm !== undefined) return wasm;\n\n    if (typeof input === 'undefined') {\n        input = new URL('helloworld_demo_bg.wasm', import.meta.url);\n    }\n    const imports = __wbg_get_imports();\n\n    if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {\n        input = fetch(input);\n    }\n\n    __wbg_init_memory(imports);\n\n    const { instance, module } = await __wbg_load(await input, imports);\n\n    return __wbg_finalize_init(instance, module);\n}\n\nexport { initSync }\nexport default __wbg_init;\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print/wasm/pkg/helloworld_demo_bg.wasm.d.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\nexport const memory: WebAssembly.Memory;\nexport function main(): void;\nexport function print(): void;\nexport function print_with_value(a: number, b: number): void;\nexport function __wbindgen_malloc(a: number): number;\nexport function __wbindgen_realloc(a: number, b: number, c: number): number;\nexport function __wbindgen_start(): void;\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print/wasm/src/lib.rs",
    "content": "use wasm_bindgen::prelude::*;\nuse web_sys::console;\n\n// will be called when the wasm module is loaded\n// https://rustwasm.github.io/docs/wasm-bindgen/reference/attributes/on-rust-exports/start.html\n#[wasm_bindgen(start)]\npub fn main() {\n    console::log_1(&\"[from wasm] Inited.\".into());\n}\n\n#[wasm_bindgen]\npub fn print() {\n    console::log_1(&\"[from wasm] Hello World!\".into());\n}\n\n#[wasm_bindgen]\npub fn print_with_value(value: &str) {\n    // with 2-args log function\n    console::log_2(&\"[from wasm] Hello\".into(), &value.into());\n}\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print-nomodule/README.md",
    "content": "# Using WASM in Manifest V3\n\nThis recipe shows how to use WASM in Manifest V3.\n\nTo load WASM in Manifest V3, we need to use the `wasm-unsafe-eval` CSP directive ([Content Security Policy][0]).\n\n## Overview\n\n### Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an unpacked extension.\n3. Find the extension named \"WASM Load Example - Helloworld (no-modules)\" and inspect the service worker.\n\nYou will see the following output:\n\n```\n[from wasm] Inited.\n[from wasm] Hello World!\n[from wasm] Hello John\n```\n\n### Build WASM locally\n\nWe have already built the WASM file for you. If you want to build it yourself, follow the steps below.\n\n1. Install [Rust](https://www.rust-lang.org/install.html).\n\n2. Install [wasm-pack](https://rustwasm.github.io/wasm-pack/installer/).\n\n   ```bash\n   cargo install wasm-pack\n   ```\n\n3. Build WASM.\n\n   ```bash\n   cd wasm\n   wasm-pack build --target no-modules\n   ```\n\n[0]: https://developer.chrome.com/docs/extensions/mv3/manifest/content_security_policy/\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print-nomodule/background.js",
    "content": "/* eslint-disable no-undef */\n\nimportScripts('./wasm/pkg/helloworld_demo.js');\n\nchrome.runtime.onInstalled.addListener(() => {\n  runDemo();\n});\n\nasync function runDemo() {\n  // Initialize the WASM module\n  await wasm_bindgen('./wasm/pkg/helloworld_demo_bg.wasm');\n\n  // Call the exported functions from the WASM module\n  wasm_bindgen.print();\n  wasm_bindgen.print_with_value('John');\n}\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print-nomodule/manifest.json",
    "content": "{\n  \"name\": \"WASM Load Example - Helloworld (no-modules)\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"description\": \"Shows how to use WebAssembly (WASM) in Manifest V3.\",\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"content_security_policy\": {\n    \"extension_pages\": \"default-src 'self' 'wasm-unsafe-eval'\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print-nomodule/wasm/.gitignore",
    "content": "target\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print-nomodule/wasm/Cargo.toml",
    "content": "[package]\nname = \"helloworld-demo\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\nwasm-bindgen = \"0.2.84\"\nweb-sys = { version = \"0.3.61\", features = ['console'] }\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print-nomodule/wasm/pkg/helloworld_demo.d.ts",
    "content": "declare namespace wasm_bindgen {\n\t/* tslint:disable */\n\t/* eslint-disable */\n\t/**\n\t*/\n\texport function main(): void;\n\t/**\n\t*/\n\texport function print(): void;\n\t/**\n\t* @param {string} value\n\t*/\n\texport function print_with_value(value: string): void;\n\t\n}\n\ndeclare type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;\n\ndeclare interface InitOutput {\n  readonly memory: WebAssembly.Memory;\n  readonly main: () => void;\n  readonly print: () => void;\n  readonly print_with_value: (a: number, b: number) => void;\n  readonly __wbindgen_malloc: (a: number) => number;\n  readonly __wbindgen_realloc: (a: number, b: number, c: number) => number;\n  readonly __wbindgen_start: () => void;\n}\n\n/**\n* If `module_or_path` is {RequestInfo} or {URL}, makes a request and\n* for everything else, calls `WebAssembly.instantiate` directly.\n*\n* @param {InitInput | Promise<InitInput>} module_or_path\n*\n* @returns {Promise<InitOutput>}\n*/\ndeclare function wasm_bindgen (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print-nomodule/wasm/pkg/helloworld_demo.js",
    "content": "let wasm_bindgen;\n(function() {\n    const __exports = {};\n    let script_src;\n    if (typeof document !== 'undefined' && typeof document.currentScript !== 'null') {\n        script_src = new URL(document.currentScript.src, location.href).toString();\n    }\n    let wasm = undefined;\n\n    const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );\n\n    if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };\n\n    let cachedUint8Memory0 = null;\n\n    function getUint8Memory0() {\n        if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {\n            cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);\n        }\n        return cachedUint8Memory0;\n    }\n\n    function getStringFromWasm0(ptr, len) {\n        ptr = ptr >>> 0;\n        return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));\n    }\n\n    const heap = new Array(128).fill(undefined);\n\n    heap.push(undefined, null, true, false);\n\n    let heap_next = heap.length;\n\n    function addHeapObject(obj) {\n        if (heap_next === heap.length) heap.push(heap.length + 1);\n        const idx = heap_next;\n        heap_next = heap[idx];\n\n        heap[idx] = obj;\n        return idx;\n    }\n\nfunction getObject(idx) { return heap[idx]; }\n\nfunction dropObject(idx) {\n    if (idx < 132) return;\n    heap[idx] = heap_next;\n    heap_next = idx;\n}\n\nfunction takeObject(idx) {\n    const ret = getObject(idx);\n    dropObject(idx);\n    return ret;\n}\n/**\n*/\n__exports.main = function() {\n    wasm.main();\n};\n\n/**\n*/\n__exports.print = function() {\n    wasm.print();\n};\n\nlet WASM_VECTOR_LEN = 0;\n\nconst cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );\n\nconst encodeString = (typeof cachedTextEncoder.encodeInto === 'function'\n    ? function (arg, view) {\n    return cachedTextEncoder.encodeInto(arg, view);\n}\n    : function (arg, view) {\n    const buf = cachedTextEncoder.encode(arg);\n    view.set(buf);\n    return {\n        read: arg.length,\n        written: buf.length\n    };\n});\n\nfunction passStringToWasm0(arg, malloc, realloc) {\n\n    if (realloc === undefined) {\n        const buf = cachedTextEncoder.encode(arg);\n        const ptr = malloc(buf.length) >>> 0;\n        getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);\n        WASM_VECTOR_LEN = buf.length;\n        return ptr;\n    }\n\n    let len = arg.length;\n    let ptr = malloc(len) >>> 0;\n\n    const mem = getUint8Memory0();\n\n    let offset = 0;\n\n    for (; offset < len; offset++) {\n        const code = arg.charCodeAt(offset);\n        if (code > 0x7F) break;\n        mem[ptr + offset] = code;\n    }\n\n    if (offset !== len) {\n        if (offset !== 0) {\n            arg = arg.slice(offset);\n        }\n        ptr = realloc(ptr, len, len = offset + arg.length * 3) >>> 0;\n        const view = getUint8Memory0().subarray(ptr + offset, ptr + len);\n        const ret = encodeString(arg, view);\n\n        offset += ret.written;\n    }\n\n    WASM_VECTOR_LEN = offset;\n    return ptr;\n}\n/**\n* @param {string} value\n*/\n__exports.print_with_value = function(value) {\n    const ptr0 = passStringToWasm0(value, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n    const len0 = WASM_VECTOR_LEN;\n    wasm.print_with_value(ptr0, len0);\n};\n\nasync function __wbg_load(module, imports) {\n    if (typeof Response === 'function' && module instanceof Response) {\n        if (typeof WebAssembly.instantiateStreaming === 'function') {\n            try {\n                return await WebAssembly.instantiateStreaming(module, imports);\n\n            } catch (e) {\n                if (module.headers.get('Content-Type') != 'application/wasm') {\n                    console.warn(\"`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\\n\", e);\n\n                } else {\n                    throw e;\n                }\n            }\n        }\n\n        const bytes = await module.arrayBuffer();\n        return await WebAssembly.instantiate(bytes, imports);\n\n    } else {\n        const instance = await WebAssembly.instantiate(module, imports);\n\n        if (instance instanceof WebAssembly.Instance) {\n            return { instance, module };\n\n        } else {\n            return instance;\n        }\n    }\n}\n\nfunction __wbg_get_imports() {\n    const imports = {};\n    imports.wbg = {};\n    imports.wbg.__wbindgen_string_new = function(arg0, arg1) {\n        const ret = getStringFromWasm0(arg0, arg1);\n        return addHeapObject(ret);\n    };\n    imports.wbg.__wbindgen_object_drop_ref = function(arg0) {\n        takeObject(arg0);\n    };\n    imports.wbg.__wbg_log_003c998d6df63565 = function(arg0) {\n        console.log(getObject(arg0));\n    };\n    imports.wbg.__wbg_log_12a0c96d2facdfce = function(arg0, arg1) {\n        console.log(getObject(arg0), getObject(arg1));\n    };\n    imports.wbg.__wbindgen_throw = function(arg0, arg1) {\n        throw new Error(getStringFromWasm0(arg0, arg1));\n    };\n\n    return imports;\n}\n\nfunction __wbg_init_memory(imports, maybe_memory) {\n\n}\n\nfunction __wbg_finalize_init(instance, module) {\n    wasm = instance.exports;\n    __wbg_init.__wbindgen_wasm_module = module;\n    cachedUint8Memory0 = null;\n\n    wasm.__wbindgen_start();\n    return wasm;\n}\n\nfunction initSync(module) {\n    if (wasm !== undefined) return wasm;\n\n    const imports = __wbg_get_imports();\n\n    __wbg_init_memory(imports);\n\n    if (!(module instanceof WebAssembly.Module)) {\n        module = new WebAssembly.Module(module);\n    }\n\n    const instance = new WebAssembly.Instance(module, imports);\n\n    return __wbg_finalize_init(instance, module);\n}\n\nasync function __wbg_init(input) {\n    if (wasm !== undefined) return wasm;\n\n    if (typeof input === 'undefined' && script_src !== 'undefined') {\n        input = script_src.replace(/\\.js$/, '_bg.wasm');\n    }\n    const imports = __wbg_get_imports();\n\n    if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {\n        input = fetch(input);\n    }\n\n    __wbg_init_memory(imports);\n\n    const { instance, module } = await __wbg_load(await input, imports);\n\n    return __wbg_finalize_init(instance, module);\n}\n\nwasm_bindgen = Object.assign(__wbg_init, { initSync }, __exports);\n\n})();\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print-nomodule/wasm/pkg/helloworld_demo_bg.wasm.d.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\nexport const memory: WebAssembly.Memory;\nexport function main(): void;\nexport function print(): void;\nexport function print_with_value(a: number, b: number): void;\nexport function __wbindgen_malloc(a: number): number;\nexport function __wbindgen_realloc(a: number, b: number, c: number): number;\nexport function __wbindgen_start(): void;\n"
  },
  {
    "path": "functional-samples/cookbook.wasm-helloworld-print-nomodule/wasm/src/lib.rs",
    "content": "use wasm_bindgen::prelude::*;\nuse web_sys::console;\n\n// will be called when the wasm module is loaded\n// https://rustwasm.github.io/docs/wasm-bindgen/reference/attributes/on-rust-exports/start.html\n#[wasm_bindgen(start)]\npub fn main() {\n    console::log_1(&\"[from wasm] Inited.\".into());\n}\n\n#[wasm_bindgen]\npub fn print() {\n    console::log_1(&\"[from wasm] Hello World!\".into());\n}\n\n#[wasm_bindgen]\npub fn print_with_value(value: &str) {\n    // with 2-args log function\n    console::log_2(&\"[from wasm] Hello\".into(), &value.into());\n}\n"
  },
  {
    "path": "functional-samples/libraries-xhr-in-sw/.gitignore",
    "content": "dist\n"
  },
  {
    "path": "functional-samples/libraries-xhr-in-sw/README.md",
    "content": "# Using XHR in Service Workers\n\nThis sample demonstrates how to use code that relies on XHR within a extension's background service worker.\n\n## Overview\n\nThe default background environment for extensions is the service worker. As a result, it only has direct access to [Fetch](https://developer.mozilla.org/docs/Web/API/Fetch_API/Using_Fetch). If you want to use a library that is built with XHR, this will not work by default. However, you can usually monkeypatch the expected behavior by polyfilling XHR. This sample shows an example of how you can use build tools to automatically inject a polyfill for XHR that covers most common XHR use cases, allowing for seamless integration into your extension.\n\nIn this sample, we are using a \"library\" that exports a function called [`fetchTitle`](./third_party/fetchTitle.js). For the fiction of this sample, this is a dependency we _must_ use, but we are unable to change ourselves. Unfortunately, it uses XHR. In order to make this work, we [import](./background.js#L1) a [shim](./third_party/xhr-shim/xhr-shim.js), and then [set the global `XMLHttpRequest` to it](./background.js#L4).\n\nThis is all packaged by a build system, in this case [Rollup](https://rollupjs.org/).\n\n## Running this extension\n\n1. Clone this repository\n2. Run `npm install` in this folder to install all dependencies.\n3. Run `npm run build` to bundle the extension.\n"
  },
  {
    "path": "functional-samples/libraries-xhr-in-sw/background.js",
    "content": "import xhrShim from './third_party/xhr-shim/xhr-shim.js';\nimport fetchTitle from './third_party/fetchTitle.js';\n\nglobalThis.XMLHttpRequest = xhrShim;\n\nchrome.action.onClicked.addListener(({ windowId, url }) => {\n  chrome.sidePanel.open({ windowId });\n\n  fetchTitle(url, (err, title) => {\n    chrome.sidePanel.setOptions({\n      enabled: true,\n      path: `./sidePanel/index.html?title=${title}`\n    });\n  });\n});\n"
  },
  {
    "path": "functional-samples/libraries-xhr-in-sw/manifest.json",
    "content": "{\n  \"name\": \"Fetching Titles\",\n  \"version\": \"0.1\",\n  \"manifest_version\": 3,\n  \"description\": \"This extension fetches the titles of all the tabs in the current window and displays them in a side panel.\",\n  \"background\": {\n    \"service_worker\": \"dist/background.js\"\n  },\n  \"permissions\": [\"activeTab\", \"sidePanel\"],\n  \"host_permissions\": [\"<all_urls>\"],\n  \"side_panel\": {\n    \"default_path\": \"sidepanel/index.html\"\n  },\n  \"action\": {\n    \"default_title\": \"Fetch the title of the current tab\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/libraries-xhr-in-sw/package.json",
    "content": "{\n  \"name\": \"XHR polyfill sample\",\n  \"private\": true,\n  \"version\": \"1.0.0\",\n  \"main\": \"background.js\",\n  \"scripts\": {\n    \"build\": \"rollup -c rollup.config.mjs\"\n  },\n  \"license\": \"Apache 2.0\",\n  \"devDependencies\": {\n    \"@rollup/plugin-commonjs\": \"26.0.1\",\n    \"@rollup/plugin-node-resolve\": \"^15.2.3\",\n    \"rollup\": \"^4.22.4\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/libraries-xhr-in-sw/rollup.config.mjs",
    "content": "import { nodeResolve } from '@rollup/plugin-node-resolve';\nimport commonjs from '@rollup/plugin-commonjs';\n\nexport default {\n  input: 'background.js',\n  output: {\n    inlineDynamicImports: true,\n    file: 'dist/background.js',\n  },\n  plugins: [\n    commonjs(),\n    nodeResolve(),\n  ]\n};\n"
  },
  {
    "path": "functional-samples/libraries-xhr-in-sw/sidepanel/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Title Fetcher</title>\n  </head>\n  <body>\n    <h1>Hello, world!</h1>\n    <script src=\"/sidepanel/script.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/libraries-xhr-in-sw/sidepanel/script.js",
    "content": "const fetchedTitle = new URLSearchParams(location.search).get('title');\ndocument.body.innerText = `This tab has the title \"${fetchedTitle}\"`;\n"
  },
  {
    "path": "functional-samples/libraries-xhr-in-sw/third_party/fetchTitle.js",
    "content": "export default function fetchTitle(url, callback) {\n  let xhr = new XMLHttpRequest();\n\n  xhr.open('GET', url, true);\n\n  xhr.onload = function () {\n    if (xhr.status === 200) {\n      let title = xhr.responseText.match(/<title>([^<]+)<\\/title>/)[1];\n      callback(null, title);\n    } else {\n      callback(new Error('Failed to load URL: ' + xhr.statusText));\n    }\n  };\n\n  xhr.onerror = function () {\n    callback(new Error('Network error'));\n  };\n\n  xhr.send();\n}\n"
  },
  {
    "path": "functional-samples/libraries-xhr-in-sw/third_party/xhr-shim/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2022 apple502j\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "functional-samples/libraries-xhr-in-sw/third_party/xhr-shim/xhr-shim.js",
    "content": "/* global module */\n\nconst sHeaders = Symbol('headers');\nconst sRespHeaders = Symbol('response headers');\nconst sAbortController = Symbol('AbortController');\nconst sMethod = Symbol('method');\nconst sURL = Symbol('URL');\nconst sMIME = Symbol('MIME');\nconst sDispatch = Symbol('dispatch');\nconst sErrored = Symbol('errored');\nconst sTimeout = Symbol('timeout');\nconst sTimedOut = Symbol('timedOut');\nconst sIsResponseText = Symbol('isResponseText');\n\nconst XMLHttpRequestShim = class XMLHttpRequest extends EventTarget {\n  constructor() {\n    super();\n    this.readyState = this.constructor.UNSENT;\n    this.response = null;\n    this.responseType = '';\n    this.responseURL = '';\n    this.status = 0;\n    this.statusText = '';\n    this.timeout = 0;\n    this.withCredentials = false;\n    this[sHeaders] = Object.create(null);\n    this[sHeaders].accept = '*/*';\n    this[sRespHeaders] = Object.create(null);\n    this[sAbortController] = new AbortController();\n    this[sMethod] = '';\n    this[sURL] = '';\n    this[sMIME] = '';\n    this[sErrored] = false;\n    this[sTimeout] = 0;\n    this[sTimedOut] = false;\n    this[sIsResponseText] = true;\n  }\n  static get UNSENT() {\n    return 0;\n  }\n  static get OPENED() {\n    return 1;\n  }\n  static get HEADERS_RECEIVED() {\n    return 2;\n  }\n  static get LOADING() {\n    return 3;\n  }\n  static get DONE() {\n    return 4;\n  }\n  get responseText() {\n    if (this[sErrored]) return null;\n    if (this.readyState < this.constructor.HEADERS_RECEIVED) return '';\n    if (this[sIsResponseText]) return this.response;\n    throw new DOMException(\n      'Response type not set to text',\n      'InvalidStateError'\n    );\n  }\n  get responseXML() {\n    throw new Error('XML not supported');\n  }\n  [sDispatch](evt) {\n    const attr = `on${evt.type}`;\n    if (typeof this[attr] === 'function') {\n      this.addEventListener(evt.type, this[attr].bind(this), {\n        once: true\n      });\n    }\n    this.dispatchEvent(evt);\n  }\n  abort() {\n    this[sAbortController].abort();\n    this.status = 0;\n    this.readyState = this.constructor.UNSENT;\n  }\n  open(method, url) {\n    this.status = 0;\n    this[sMethod] = method;\n    this[sURL] = url;\n    this.readyState = this.constructor.OPENED;\n  }\n  setRequestHeader(header, value) {\n    header = String(header).toLowerCase();\n    if (typeof this[sHeaders][header] === 'undefined') {\n      this[sHeaders][header] = String(value);\n    } else {\n      this[sHeaders][header] += `, ${value}`;\n    }\n  }\n  overrideMimeType(mimeType) {\n    this[sMIME] = String(mimeType);\n  }\n  getAllResponseHeaders() {\n    if (this[sErrored] || this.readyState < this.constructor.HEADERS_RECEIVED)\n      return '';\n    return Object.entries(this[sRespHeaders])\n      .map(([header, value]) => `${header}: ${value}`)\n      .join('\\r\\n');\n  }\n  getResponseHeader(headerName) {\n    const value = this[sRespHeaders][String(headerName).toLowerCase()];\n    return typeof value === 'string' ? value : null;\n  }\n  send(body = null) {\n    if (this.timeout > 0) {\n      this[sTimeout] = setTimeout(() => {\n        this[sTimedOut] = true;\n        this[sAbortController].abort();\n      }, this.timeout);\n    }\n    const responseType = this.responseType || 'text';\n    this[sIsResponseText] = responseType === 'text';\n    fetch(this[sURL], {\n      method: this[sMethod] || 'GET',\n      signal: this[sAbortController].signal,\n      headers: this[sHeaders],\n      credentials: this.withCredentials ? 'include' : 'same-origin',\n      body\n    })\n      .finally(() => {\n        this.readyState = this.constructor.DONE;\n        clearTimeout(this[sTimeout]);\n        this[sDispatch](new CustomEvent('loadstart'));\n      })\n      .then(\n        async (resp) => {\n          this.responseURL = resp.url;\n          this.status = resp.status;\n          this.statusText = resp.statusText;\n          const finalMIME =\n            this[sMIME] || this[sRespHeaders]['content-type'] || 'text/plain';\n          Object.assign(this[sRespHeaders], resp.headers);\n          switch (responseType) {\n            case 'text':\n              this.response = await resp.text();\n              break;\n            case 'blob':\n              this.response = new Blob([await resp.arrayBuffer()], {\n                type: finalMIME\n              });\n              break;\n            case 'arraybuffer':\n              this.response = await resp.arrayBuffer();\n              break;\n            case 'json':\n              this.response = await resp.json();\n              break;\n          }\n          this[sDispatch](new CustomEvent('load'));\n        },\n        (err) => {\n          let eventName = 'abort';\n          if (err.name !== 'AbortError') {\n            this[sErrored] = true;\n            eventName = 'error';\n          } else if (this[sTimedOut]) {\n            eventName = 'timeout';\n          }\n          this[sDispatch](new CustomEvent(eventName));\n        }\n      )\n      .finally(() => this[sDispatch](new CustomEvent('loadend')));\n  }\n};\n\nif (typeof module === 'object' && module.exports) {\n  module.exports = XMLHttpRequestShim;\n} else {\n  (globalThis || self).XMLHttpRequestShim = XMLHttpRequestShim;\n}\n"
  },
  {
    "path": "functional-samples/reference.mv3-content-scripts/README.md",
    "content": "Sample code for the [Executing arbitrary strings][section] section of the MV3 migration documentation.\n\n[section]: https://developer.chrome.com/docs/extensions/mv3/intro/mv3-migration/#executing-arbitrary-strings\n"
  },
  {
    "path": "functional-samples/reference.mv3-content-scripts/content-script.js",
    "content": "alert('File test alert');\n"
  },
  {
    "path": "functional-samples/reference.mv3-content-scripts/manifest.json",
    "content": "{\n  \"name\": \"MV3 Migration - content script example\",\n  \"version\": \"0.1\",\n  \"manifest_version\": 3,\n  \"permissions\": [\"scripting\", \"activeTab\"],\n  \"action\": {\n    \"default_popup\": \"popup.html\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/reference.mv3-content-scripts/popup.css",
    "content": "* {\n  box-sizing: border-box;\n}\nhtml,\nbody,\nmain {\n  height: 100%;\n  margin: 0;\n  padding: 0;\n}\nbody {\n  min-width: 20em;\n  min-height: 10em;\n}\nmain {\n  padding: 1em 0.5em;\n  display: grid;\n  place-items: center;\n}\n"
  },
  {
    "path": "functional-samples/reference.mv3-content-scripts/popup.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Document</title>\n    <link rel=\"stylesheet\" href=\"popup.css\" />\n    <script src=\"popup.js\" defer></script>\n  </head>\n  <body>\n    <main>\n      <div>\n        <button id=\"inject-file\">Inject file</button>\n      </div>\n      <div>\n        <button id=\"inject-function\">Inject function</button>\n      </div>\n    </main>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/reference.mv3-content-scripts/popup.js",
    "content": "const injectFile = document.getElementById('inject-file');\nconst injectFunction = document.getElementById('inject-function');\n\nasync function getCurrentTab() {\n  const queryOptions = { active: true, currentWindow: true };\n  const [tab] = await chrome.tabs.query(queryOptions);\n  return tab;\n}\n\ninjectFile.addEventListener('click', async () => {\n  const tab = await getCurrentTab();\n\n  chrome.scripting.executeScript({\n    target: { tabId: tab.id },\n    files: ['content-script.js']\n  });\n});\n\nfunction showAlert(givenName) {\n  alert(`Hello, ${givenName}`);\n}\n\ninjectFunction.addEventListener('click', async () => {\n  const tab = await getCurrentTab();\n\n  const name = 'World';\n  chrome.scripting.executeScript({\n    target: { tabId: tab.id },\n    func: showAlert,\n    args: [name]\n  });\n});\n"
  },
  {
    "path": "functional-samples/sample.bookmarks/README.md",
    "content": "# Bookmarks Manager\n\nThis sample demonstrates how to use the [chrome.bookmarks](https://developer.chrome.com/docs/extensions/reference/api/bookmarks) API to search, add, edit, and delete bookmarks.\n\n## Overview\n\nThe extension provides a bookmarks manager that is accessible by clicking the extension icon.\nThe manager provides a popup where you can manage your bookmarks.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension icon.\n4. Manage your bookmarks.\n"
  },
  {
    "path": "functional-samples/sample.bookmarks/manifest.json",
    "content": "{\n  \"name\": \"My Bookmarks\",\n  \"description\": \"A browser action with a popup dump of all bookmarks, including search, add, edit and delete.\",\n  \"version\": \"1.1\",\n  \"manifest_version\": 3,\n  \"permissions\": [\"bookmarks\"],\n  \"action\": {\n    \"default_title\": \"My Bookmarks\",\n    \"default_icon\": \"icon.png\",\n    \"default_popup\": \"popup.html\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/sample.bookmarks/popup.css",
    "content": "body {\n  width: 400px;\n  min-height: 150px;\n}\n\n#editdialog input {\n  width: 100%;\n}\n"
  },
  {
    "path": "functional-samples/sample.bookmarks/popup.html",
    "content": "<html>\n  <head>\n    <link rel=\"stylesheet\" href=\"third-party/jquery-ui.css\" />\n    <link rel=\"stylesheet\" href=\"third-party/jquery-ui.structure.css\" />\n    <link rel=\"stylesheet\" href=\"third-party/jquery-ui.theme.css\" />\n    <link rel=\"stylesheet\" href=\"popup.css\" />\n    <script src=\"third-party/jquery-1.12.4.js\"></script>\n    <script src=\"third-party/jquery-ui-1.12.1.js\"></script>\n  </head>\n  <body>\n    <div>Search Bookmarks: <input id=\"search\" /></div>\n    <div id=\"bookmarks\"></div>\n    <div id=\"editdialog\"></div>\n    <div id=\"deletedialog\"></div>\n    <div id=\"adddialog\"></div>\n    <div id=\"test-frame\"></div>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/sample.bookmarks/popup.js",
    "content": "// Copyright 2021 Google LLC\n//\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file or at\n// https://developers.google.com/open-source/licenses/bsd\n\n// Search the bookmarks when entering the search keyword.\n$('#search').change(function () {\n  $('#bookmarks').empty();\n  dumpBookmarks($('#search').val());\n});\n\n// Traverse the bookmark tree, and print the folder and nodes.\nfunction dumpBookmarks(query) {\n  chrome.bookmarks.getTree(function (bookmarkTreeNodes) {\n    $('#bookmarks').append(dumpTreeNodes(bookmarkTreeNodes, query));\n  });\n}\n\nfunction dumpTreeNodes(bookmarkNodes, query) {\n  const list = $('<ul>');\n  for (let i = 0; i < bookmarkNodes.length; i++) {\n    list.append(dumpNode(bookmarkNodes[i], query));\n  }\n\n  return list;\n}\n\nfunction dumpNode(bookmarkNode, query) {\n  let span = '';\n  if (bookmarkNode.title) {\n    if (query && !bookmarkNode.children) {\n      if (\n        String(bookmarkNode.title.toLowerCase()).indexOf(query.toLowerCase()) ==\n        -1\n      ) {\n        return $('<span></span>');\n      }\n    }\n\n    const anchor = $('<a>');\n    anchor.attr('href', bookmarkNode.url);\n\n    // Chrome may have multiple top-level folder nodes with the same title. To\n    // disambiguate them, include a suffix depending on the value of the\n    // syncing property.\n    //\n    // folderType is set for top-level folders in the tree, and not for child\n    // folders. In Chrome versions prior to milestone 134, folderType is never\n    // set.\n    let title_text = bookmarkNode.title;\n    if (bookmarkNode.folderType) {\n      title_text += bookmarkNode.syncing ? ' (Account)' : ' (Local)';\n    }\n    anchor.text(title_text);\n\n    /*\n     * When clicking on a bookmark in the extension, a new tab is fired with\n     * the bookmark url.\n     */\n    anchor.click(function () {\n      chrome.tabs.create({ url: bookmarkNode.url });\n    });\n\n    span = $('<span>');\n    const options = bookmarkNode.children\n      ? $('<span>[<a href=\"#\" id=\"addlink\">Add</a>]</span>')\n      : $(\n          '<span>[<a id=\"editlink\" href=\"#\">Edit</a> <a id=\"deletelink\" ' +\n            'href=\"#\">Delete</a>]</span>'\n        );\n    const edit = bookmarkNode.children\n      ? $(\n          '<table><tr><td>Name</td><td>' +\n            '<input id=\"title\"></td></tr><tr><td>URL</td><td><input id=\"url\">' +\n            '</td></tr></table>'\n        )\n      : $('<input>');\n\n    // Show add and edit links when hover over.\n    span\n      .hover(\n        function () {\n          span.append(options);\n          $('#deletelink').click(function (event) {\n            console.log(event);\n            $('#deletedialog')\n              .empty()\n              .dialog({\n                autoOpen: false,\n                closeOnEscape: true,\n                title: 'Confirm Deletion',\n                modal: true,\n                show: 'slide',\n                position: {\n                  my: 'left',\n                  at: 'center',\n                  of: event.target.parentElement.parentElement\n                },\n                buttons: {\n                  'Yes, Delete It!': function () {\n                    chrome.bookmarks.remove(String(bookmarkNode.id));\n                    span.parent().remove();\n                    $(this).dialog('destroy');\n                  },\n                  Cancel: function () {\n                    $(this).dialog('destroy');\n                  }\n                }\n              })\n              .dialog('open');\n          });\n          $('#addlink').click(function (event) {\n            edit.show();\n            $('#adddialog')\n              .empty()\n              .append(edit)\n              .dialog({\n                autoOpen: false,\n                closeOnEscape: true,\n                title: 'Add New Bookmark',\n                modal: true,\n                show: 'slide',\n                position: {\n                  my: 'left',\n                  at: 'center',\n                  of: event.target.parentElement.parentElement\n                },\n                buttons: {\n                  Add: function () {\n                    edit.hide();\n                    chrome.bookmarks.create({\n                      parentId: bookmarkNode.id,\n                      title: $('#title').val(),\n                      url: $('#url').val()\n                    });\n                    $('#bookmarks').empty();\n                    $(this).dialog('destroy');\n                    window.dumpBookmarks();\n                  },\n                  Cancel: function () {\n                    edit.hide();\n                    $(this).dialog('destroy');\n                  }\n                }\n              })\n              .dialog('open');\n          });\n          $('#editlink').click(function (event) {\n            edit.show();\n            edit.val(anchor.text());\n            $('#editdialog')\n              .empty()\n              .append(edit)\n              .dialog({\n                autoOpen: false,\n                closeOnEscape: true,\n                title: 'Edit Title',\n                modal: true,\n                show: 'fade',\n                position: {\n                  my: 'left',\n                  at: 'center',\n                  of: event.target.parentElement.parentElement\n                },\n                buttons: {\n                  Save: function () {\n                    edit.hide();\n                    chrome.bookmarks.update(String(bookmarkNode.id), {\n                      title: edit.val()\n                    });\n                    anchor.text(edit.val());\n                    options.show();\n                    $(this).dialog('destroy');\n                  },\n                  Cancel: function () {\n                    edit.hide();\n                    $(this).dialog('destroy');\n                  }\n                }\n              })\n              .dialog('open');\n          });\n          options.fadeIn();\n        },\n\n        // unhover\n        function () {\n          options.remove();\n        }\n      )\n      .append(anchor);\n  }\n\n  const li = $(bookmarkNode.title ? '<li>' : '<div>').append(span);\n\n  if (bookmarkNode.children && bookmarkNode.children.length > 0) {\n    li.append(dumpTreeNodes(bookmarkNode.children, query));\n  }\n\n  return li;\n}\n\ndocument.addEventListener('DOMContentLoaded', function () {\n  dumpBookmarks();\n});\n"
  },
  {
    "path": "functional-samples/sample.bookmarks/third-party/jquery-1.12.4.js",
    "content": "/*!\n * jQuery JavaScript Library v1.12.4\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2016-05-20T17:17Z\n */\n\n(function( global, factory ) {\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t// is present, execute the factory and get jQuery.\n\t\t// For environments that do not have a `window` with a `document`\n\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t// This accentuates the need for the creation of a real `window`.\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info.\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n}(typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Support: Firefox 18+\n// Can't be in strict mode, several libs including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n//\"use strict\";\nvar deletedIds = [];\n\nvar document = window.document;\n\nvar slice = deletedIds.slice;\n\nvar concat = deletedIds.concat;\n\nvar push = deletedIds.push;\n\nvar indexOf = deletedIds.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar support = {};\n\n\n\nvar\n\tversion = \"1.12.4\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t},\n\n\t// Support: Android<4.1, IE<9\n\t// Make sure we trim BOM and NBSP\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\n\njQuery.fn = jQuery.prototype = {\n\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num != null ?\n\n\t\t\t// Return just the one element from the set\n\t\t\t( num < 0 ? this[ num + this.length ] : this[ num ] ) :\n\n\t\t\t// Return all the elements in a clean array\n\t\t\tslice.call( this );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\t\tret.context = this.context;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\teach: function( callback ) {\n\t\treturn jQuery.each( this, callback );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map( this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t} ) );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor();\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: deletedIds.sort,\n\tsplice: deletedIds.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar src, copyIsArray, copy, name, options, clone,\n\t\ttarget = arguments[ 0 ] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction( target ) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\n\t\t// Only deal with non-null/undefined values\n\t\tif ( ( options = arguments[ i ] ) != null ) {\n\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject( copy ) ||\n\t\t\t\t\t( copyIsArray = jQuery.isArray( copy ) ) ) ) {\n\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray( src ) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject( src ) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend( {\n\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type( obj ) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type( obj ) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\t/* jshint eqeqeq: false */\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\n\t\t// parseFloat NaNs numeric-cast false positives (null|true|false|\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\t// adding 1 corrects loss of precision from parseFloat (#15100)\n\t\tvar realStringObj = obj && obj.toString();\n\t\treturn !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\tvar key;\n\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type( obj ) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call( obj, \"constructor\" ) &&\n\t\t\t\t!hasOwn.call( obj.constructor.prototype, \"isPrototypeOf\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Handle iteration over inherited properties before own properties.\n\t\tif ( !support.ownFirst ) {\n\t\t\tfor ( key in obj ) {\n\t\t\t\treturn hasOwn.call( obj, key );\n\t\t\t}\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || hasOwn.call( obj, key );\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn obj + \"\";\n\t\t}\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ toString.call( obj ) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && jQuery.trim( data ) ) {\n\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data ); // jscs:ignore requireDotNotation\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\teach: function( obj, callback ) {\n\t\tvar length, i = 0;\n\n\t\tif ( isArrayLike( obj ) ) {\n\t\t\tlength = obj.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( i in obj ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Support: Android<4.1, IE<9\n\ttrim: function( text ) {\n\t\treturn text == null ?\n\t\t\t\"\" :\n\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArrayLike( Object( arr ) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\tvar len;\n\n\t\tif ( arr ) {\n\t\t\tif ( indexOf ) {\n\t\t\t\treturn indexOf.call( arr, elem, i );\n\t\t\t}\n\n\t\t\tlen = arr.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in arr && arr[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\twhile ( j < len ) {\n\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)\n\t\tif ( len !== len ) {\n\t\t\twhile ( second[ j ] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar length, value,\n\t\t\ti = 0,\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArrayLike( elems ) ) {\n\t\t\tlength = elems.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar args, proxy, tmp;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\tnow: function() {\n\t\treturn +( new Date() );\n\t},\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n} );\n\n// JSHint would error on this code due to the Symbol not being defined in ES5.\n// Defining this global in .jshintrc would create a danger of using the global\n// unguarded in another place, it seems safer to just disable JSHint for these\n// three lines.\n/* jshint ignore: start */\nif ( typeof Symbol === \"function\" ) {\n\tjQuery.fn[ Symbol.iterator ] = deletedIds[ Symbol.iterator ];\n}\n/* jshint ignore: end */\n\n// Populate the class2type map\njQuery.each( \"Boolean Number String Function Array Date RegExp Object Error Symbol\".split( \" \" ),\nfunction( i, name ) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n} );\n\nfunction isArrayLike( obj ) {\n\n\t// Support: iOS 8.2 (not reproducible in simulator)\n\t// `in` check used to prevent JIT error (gh-2145)\n\t// hasOwn isn't used here due to false negatives\n\t// regarding Nodelist length in IE\n\tvar length = !!obj && \"length\" in obj && obj.length,\n\t\ttype = jQuery.type( obj );\n\n\tif ( type === \"function\" || jQuery.isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v2.2.1\n * http://sizzlejs.com/\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2015-10-17\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// General-purpose constants\n\tMAX_NEGATIVE = 1 << 31,\n\n\t// Instance methods\n\thasOwn = ({}).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpush_native = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf as it's faster than native\n\t// http://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\n\t// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + identifier + \")(?:\" + whitespace +\n\t\t// Operator (capture 2)\n\t\t\"*([*^$|!~]?=)\" + whitespace +\n\t\t// \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n\t\t\"*\\\\]\",\n\n\tpseudos = \":(\" + identifier + \")(?:\\\\((\" +\n\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\t\t// 2. simple (capture 6)\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\t\t// 3. anything else (capture 2)\n\t\t\".*\" +\n\t\t\")\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n\trattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + identifier + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + identifier + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + identifier + \"|[*])\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\trescape = /'|\\\\/g,\n\n\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\t// Support: Firefox<24\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\n\t\t\tescaped :\n\t\t\thigh < 0 ?\n\t\t\t\t// BMP codepoint\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t};\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\tpreferredDoc.childNodes\n\t);\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar m, i, elem, nid, nidselect, match, groups, newSelector,\n\t\tnewContext = context && context.ownerDocument,\n\n\t\t// nodeType defaults to 9, since context defaults to document\n\t\tnodeType = context ? context.nodeType : 9;\n\n\tresults = results || [];\n\n\t// Return early from calls with invalid selector or context\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\t// Try to shortcut find operations (as opposed to filters) in HTML documents\n\tif ( !seed ) {\n\n\t\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\t\tsetDocument( context );\n\t\t}\n\t\tcontext = context || document;\n\n\t\tif ( documentIsHTML ) {\n\n\t\t\t// If the selector is sufficiently simple, try using a \"get*By*\" DOM method\n\t\t\t// (excepting DocumentFragment context, where the methods don't exist)\n\t\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\n\t\t\t\t// ID selector\n\t\t\t\tif ( (m = match[1]) ) {\n\n\t\t\t\t\t// Document context\n\t\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\t\tif ( (elem = context.getElementById( m )) ) {\n\n\t\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t// Element context\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\tif ( newContext && (elem = newContext.getElementById( m )) &&\n\t\t\t\t\t\t\tcontains( context, elem ) &&\n\t\t\t\t\t\t\telem.id === m ) {\n\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t// Type selector\n\t\t\t\t} else if ( match[2] ) {\n\t\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\t\treturn results;\n\n\t\t\t\t// Class selector\n\t\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName &&\n\t\t\t\t\tcontext.getElementsByClassName ) {\n\n\t\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Take advantage of querySelectorAll\n\t\t\tif ( support.qsa &&\n\t\t\t\t!compilerCache[ selector + \" \" ] &&\n\t\t\t\t(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\n\t\t\t\tif ( nodeType !== 1 ) {\n\t\t\t\t\tnewContext = context;\n\t\t\t\t\tnewSelector = selector;\n\n\t\t\t\t// qSA looks outside Element context, which is not what we want\n\t\t\t\t// Thanks to Andrew Dupont for this workaround technique\n\t\t\t\t// Support: IE <=8\n\t\t\t\t// Exclude object elements\n\t\t\t\t} else if ( context.nodeName.toLowerCase() !== \"object\" ) {\n\n\t\t\t\t\t// Capture the context ID, setting it first if necessary\n\t\t\t\t\tif ( (nid = context.getAttribute( \"id\" )) ) {\n\t\t\t\t\t\tnid = nid.replace( rescape, \"\\\\$&\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", (nid = expando) );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prefix every selector in the list\n\t\t\t\t\tgroups = tokenize( selector );\n\t\t\t\t\ti = groups.length;\n\t\t\t\t\tnidselect = ridentifier.test( nid ) ? \"#\" + nid : \"[id='\" + nid + \"']\";\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tgroups[i] = nidselect + \" \" + toSelector( groups[i] );\n\t\t\t\t\t}\n\t\t\t\t\tnewSelector = groups.join( \",\" );\n\n\t\t\t\t\t// Expand context for sibling selectors\n\t\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) ||\n\t\t\t\t\t\tcontext;\n\t\t\t\t}\n\n\t\t\t\tif ( newSelector ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t} catch ( qsaError ) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( nid === expando ) {\n\t\t\t\t\t\t\tcontext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {function(string, object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key + \" \" ] = value);\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created div and expects a boolean result\n */\nfunction assert( fn ) {\n\tvar div = document.createElement(\"div\");\n\n\ttry {\n\t\treturn !!fn( div );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// Remove from its parent by default\n\t\tif ( div.parentNode ) {\n\t\t\tdiv.parentNode.removeChild( div );\n\t\t}\n\t\t// release memory in IE\n\t\tdiv = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split(\"|\"),\n\t\ti = arr.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\t( ~b.sourceIndex || MAX_NEGATIVE ) -\n\t\t\t( ~a.sourceIndex || MAX_NEGATIVE );\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, parent,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// Return early if doc is invalid or already selected\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Update global variables\n\tdocument = doc;\n\tdocElem = document.documentElement;\n\tdocumentIsHTML = !isXML( document );\n\n\t// Support: IE 9-11, Edge\n\t// Accessing iframe documents after unload throws \"permission denied\" errors (jQuery #13936)\n\tif ( (parent = document.defaultView) && parent.top !== parent ) {\n\t\t// Support: IE 11\n\t\tif ( parent.addEventListener ) {\n\t\t\tparent.addEventListener( \"unload\", unloadHandler, false );\n\n\t\t// Support: IE 9 - 10 only\n\t\t} else if ( parent.attachEvent ) {\n\t\t\tparent.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties\n\t// (excepting IE8 booleans)\n\tsupport.attributes = assert(function( div ) {\n\t\tdiv.className = \"i\";\n\t\treturn !div.getAttribute(\"className\");\n\t});\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert(function( div ) {\n\t\tdiv.appendChild( document.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( document.getElementsByClassName );\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert(function( div ) {\n\t\tdocElem.appendChild( div ).id = expando;\n\t\treturn !document.getElementsByName || !document.getElementsByName( expando ).length;\n\t});\n\n\t// ID find and filter\n\tif ( support.getById ) {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\treturn m ? [ m ] : [];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t} else {\n\t\t// Support: IE6/7\n\t\t// getElementById is not reliable as a find shortcut\n\t\tdelete Expr.find[\"ID\"];\n\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" &&\n\t\t\t\t\telem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t} else if ( support.qsa ) {\n\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t}\n\t\t} :\n\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See http://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( (support.qsa = rnative.test( document.querySelectorAll )) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( div ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\r\\\\' msallowcapture=''>\" +\n\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( div.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+\n\t\t\tif ( !div.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibing-combinator selector` fails\n\t\t\tif ( !div.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = document.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tdiv.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( div.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tdiv.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( div ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( div, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully self-exclusive\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\tif ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\t\t\treturn a === document ? -1 :\n\t\t\t\tb === document ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\treturn document;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t!compilerCache[ expr + \" \" ] &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch (e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( (elem = results[i++]) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( (node = elem[i++]) ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[3] || match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[6] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[3] ) {\n\t\t\t\tmatch[2] = match[4] || match[5] || \"\";\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() { return true; } :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, uniqueCache, outerCache, node, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType,\n\t\t\t\t\t\tdiff = false;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) {\n\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\n\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\tnode = parent;\n\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\tdiff = nodeIndex && cache[ 2 ];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\t\tdiff = nodeIndex;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// xml :nth-child(...)\n\t\t\t\t\t\t\t// or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t\tif ( diff === false ) {\n\t\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t\tif ( ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) &&\n\t\t\t\t\t\t\t\t\t\t++diff ) {\n\n\t\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\tinput[0] = null;\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\ttext = text.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( (tokens = []) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push({\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t});\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, uniqueCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\n\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\tuniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});\n\n\t\t\t\t\t\tif ( (oldCache = uniqueCache[ dir ]) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\tuniqueCache[ dir ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context === document || context || outermost;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\tif ( !context && elem.ownerDocument !== document ) {\n\t\t\t\t\t\tsetDocument( elem );\n\t\t\t\t\t\txml = !documentIsHTML;\n\t\t\t\t\t}\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context || document, xml) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// `i` is now the count of elements visited above, and adding it to `matchedCount`\n\t\t\t// makes the latter nonnegative.\n\t\t\tmatchedCount += i;\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\t// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`\n\t\t\t// equals `i`), unless we didn't visit _any_ elements in the above loop because we have\n\t\t\t// no element matchers and no seed.\n\t\t\t// Incrementing an initially-string \"0\" `i` allows `i` to remain a string only in that\n\t\t\t// case, which will result in a \"00\" `matchedCount` that differs from `i` but is also\n\t\t\t// numerically zero.\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !match ) {\n\t\t\tmatch = tokenize( selector );\n\t\t}\n\t\ti = match.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( match[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n\t\t// Save selector and tokenization\n\t\tcached.selector = selector;\n\t}\n\treturn cached;\n};\n\n/**\n * A low-level selection function that works with Sizzle's compiled\n *  selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n *  selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\nselect = Sizzle.select = function( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tcompiled = typeof selector === \"function\" && selector,\n\t\tmatch = !seed && tokenize( (selector = compiled.selector || selector) );\n\n\tresults = results || [];\n\n\t// Try to minimize operations if there is only one selector in the list and no seed\n\t// (the latter of which guarantees us context)\n\tif ( match.length === 1 ) {\n\n\t\t// Reduce context if the leading compound selector is an ID\n\t\ttokens = match[0] = match[0].slice( 0 );\n\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\tsupport.getById && context.nodeType === 9 && documentIsHTML &&\n\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[i];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( (seed = find(\n\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t)) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\t!context || rsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n};\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n// Support: Chrome 14-35+\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert(function( div1 ) {\n\t// Should return 1, but returns 4 (following)\n\treturn div1.compareDocumentPosition( document.createElement(\"div\") ) & 1;\n});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert(function( div ) {\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\treturn div.firstChild.getAttribute(\"href\") === \"#\" ;\n}) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert(function( div ) {\n\tdiv.innerHTML = \"<input/>\";\n\tdiv.firstChild.setAttribute( \"value\", \"\" );\n\treturn div.firstChild.getAttribute( \"value\" ) === \"\";\n}) ) {\n\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert(function( div ) {\n\treturn div.getAttribute(\"disabled\") == null;\n}) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\tnull;\n\t\t}\n\t});\n}\n\nreturn Sizzle;\n\n})( window );\n\n\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[ \":\" ] = jQuery.expr.pseudos;\njQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n\nvar dir = function( elem, dir, until ) {\n\tvar matched = [],\n\t\ttruncate = until !== undefined;\n\n\twhile ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmatched.push( elem );\n\t\t}\n\t}\n\treturn matched;\n};\n\n\nvar siblings = function( n, elem ) {\n\tvar matched = [];\n\n\tfor ( ; n; n = n.nextSibling ) {\n\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\tmatched.push( n );\n\t\t}\n\t}\n\n\treturn matched;\n};\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\nvar rsingleTag = ( /^<([\\w-]+)\\s*\\/?>(?:<\\/\\1>|)$/ );\n\n\n\nvar risSimple = /^.[^:#\\[\\.,]*$/;\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\t/* jshint -W018 */\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t} );\n\n\t}\n\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t} );\n\n\t}\n\n\tif ( typeof qualifier === \"string\" ) {\n\t\tif ( risSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter( qualifier, elements, not );\n\t\t}\n\n\t\tqualifier = jQuery.filter( qualifier, elements );\n\t}\n\n\treturn jQuery.grep( elements, function( elem ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) > -1 ) !== not;\n\t} );\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\treturn elems.length === 1 && elem.nodeType === 1 ?\n\t\tjQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :\n\t\tjQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t} ) );\n};\n\njQuery.fn.extend( {\n\tfind: function( selector ) {\n\t\tvar i,\n\t\t\tret = [],\n\t\t\tself = this,\n\t\t\tlen = self.length;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter( function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} ) );\n\t\t}\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\t// Needed because $( selector, context ) becomes $( context ).find( selector )\n\t\tret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );\n\t\tret.selector = this.selector ? this.selector + \" \" + selector : selector;\n\t\treturn ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], false ) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], true ) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n} );\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,\n\n\tinit = jQuery.fn.init = function( selector, context, root ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// init accepts an alternate rootjQuery\n\t\t// so migrate can support jQuery.sub (gh-2101)\n\t\troot = root || rootjQuery;\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector.charAt( 0 ) === \"<\" &&\n\t\t\t\tselector.charAt( selector.length - 1 ) === \">\" &&\n\t\t\t\tselector.length >= 3 ) {\n\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && ( match[ 1 ] || !context ) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[ 1 ] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[ 0 ] : context;\n\n\t\t\t\t\t// scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[ 1 ],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[ 2 ] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[ 2 ] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[ 0 ] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || root ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis.context = this[ 0 ] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn typeof root.ready !== \"undefined\" ?\n\t\t\t\troot.ready( selector ) :\n\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend( {\n\thas: function( target ) {\n\t\tvar i,\n\t\t\ttargets = jQuery( target, this ),\n\t\t\tlen = targets.length;\n\n\t\treturn this.filter( function() {\n\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[ i ] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\tpos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tfor ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {\n\n\t\t\t\t// Always skip document fragments\n\t\t\t\tif ( cur.nodeType < 11 && ( pos ?\n\t\t\t\t\tpos.index( cur ) > -1 :\n\n\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\tjQuery.find.matchesSelector( cur, selectors ) ) ) {\n\n\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[ 0 ], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.uniqueSort(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t}\n} );\n\nfunction sibling( cur, dir ) {\n\tdo {\n\t\tcur = cur[ dir ];\n\t} while ( cur && cur.nodeType !== 1 );\n\n\treturn cur;\n}\n\njQuery.each( {\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn siblings( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn siblings( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tret = jQuery.uniqueSort( ret );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tret = ret.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n} );\nvar rnotwhite = ( /\\S+/g );\n\n\n\n// Convert String-formatted options into Object-formatted ones\nfunction createOptions( options ) {\n\tvar object = {};\n\tjQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t} );\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\tcreateOptions( options ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\n\t\t// Last fire value for non-forgettable lists\n\t\tmemory,\n\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\n\t\t// Flag to prevent firing\n\t\tlocked,\n\n\t\t// Actual callback list\n\t\tlist = [],\n\n\t\t// Queue of execution data for repeatable lists\n\t\tqueue = [],\n\n\t\t// Index of currently firing callback (modified by add/remove as needed)\n\t\tfiringIndex = -1,\n\n\t\t// Fire callbacks\n\t\tfire = function() {\n\n\t\t\t// Enforce single-firing\n\t\t\tlocked = options.once;\n\n\t\t\t// Execute callbacks for all pending executions,\n\t\t\t// respecting firingIndex overrides and runtime changes\n\t\t\tfired = firing = true;\n\t\t\tfor ( ; queue.length; firingIndex = -1 ) {\n\t\t\t\tmemory = queue.shift();\n\t\t\t\twhile ( ++firingIndex < list.length ) {\n\n\t\t\t\t\t// Run callback and check for early termination\n\t\t\t\t\tif ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&\n\t\t\t\t\t\toptions.stopOnFalse ) {\n\n\t\t\t\t\t\t// Jump to end and forget the data so .add doesn't re-fire\n\t\t\t\t\t\tfiringIndex = list.length;\n\t\t\t\t\t\tmemory = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Forget the data if we're done with it\n\t\t\tif ( !options.memory ) {\n\t\t\t\tmemory = false;\n\t\t\t}\n\n\t\t\tfiring = false;\n\n\t\t\t// Clean up if we're done firing for good\n\t\t\tif ( locked ) {\n\n\t\t\t\t// Keep an empty list if we have data for future add calls\n\t\t\t\tif ( memory ) {\n\t\t\t\t\tlist = [];\n\n\t\t\t\t// Otherwise, this object is spent\n\t\t\t\t} else {\n\t\t\t\t\tlist = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Actual Callbacks object\n\t\tself = {\n\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\n\t\t\t\t\t// If we have memory from a past run, we should fire after adding\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfiringIndex = list.length - 1;\n\t\t\t\t\t\tqueue.push( memory );\n\t\t\t\t\t}\n\n\t\t\t\t\t( function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tif ( jQuery.isFunction( arg ) ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && jQuery.type( arg ) !== \"string\" ) {\n\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\t\t\t\t\t} )( arguments );\n\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\tvar index;\n\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\tlist.splice( index, 1 );\n\n\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ?\n\t\t\t\t\tjQuery.inArray( fn, list ) > -1 :\n\t\t\t\t\tlist.length > 0;\n\t\t\t},\n\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Disable .fire and .add\n\t\t\t// Abort any current/pending executions\n\t\t\t// Clear all callbacks and values\n\t\t\tdisable: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tlist = memory = \"\";\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\n\t\t\t// Disable .fire\n\t\t\t// Also disable .add unless we have memory (since it would have no effect)\n\t\t\t// Abort any pending executions\n\t\t\tlock: function() {\n\t\t\t\tlocked = true;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tlocked: function() {\n\t\t\t\treturn !!locked;\n\t\t\t},\n\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( !locked ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tqueue.push( args );\n\t\t\t\t\tif ( !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\njQuery.extend( {\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\n\t\t\t\t// action, add listener, listener list, final state\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks( \"once memory\" ), \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks( \"once memory\" ), \"rejected\" ],\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks( \"memory\" ) ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\t\t\tvar fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\n\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n\t\t\t\t\t\t\tdeferred[ tuple[ 1 ] ]( function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify )\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ](\n\t\t\t\t\t\t\t\t\t\tthis === promise ? newDefer.promise() : this,\n\t\t\t\t\t\t\t\t\t\tfn ? [ returned ] : arguments\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Keep pipe for back-compat\n\t\tpromise.pipe = promise.then;\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 3 ];\n\n\t\t\t// promise[ done | fail | progress ] = list.add\n\t\t\tpromise[ tuple[ 1 ] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add( function() {\n\n\t\t\t\t\t// state = [ resolved | rejected ]\n\t\t\t\t\tstate = stateString;\n\n\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n\t\t\t}\n\n\t\t\t// deferred[ resolve | reject | notify ]\n\t\t\tdeferred[ tuple[ 0 ] ] = function() {\n\t\t\t\tdeferred[ tuple[ 0 ] + \"With\" ]( this === deferred ? promise : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\t\t\tdeferred[ tuple[ 0 ] + \"With\" ] = list.fireWith;\n\t\t} );\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( subordinate /* , ..., subordinateN */ ) {\n\t\tvar i = 0,\n\t\t\tresolveValues = slice.call( arguments ),\n\t\t\tlength = resolveValues.length,\n\n\t\t\t// the count of uncompleted subordinates\n\t\t\tremaining = length !== 1 ||\n\t\t\t\t( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred.\n\t\t\t// If resolveValues consist of only a single Deferred, just use that.\n\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n\t\t\t// Update function for both resolve and progress values\n\t\t\tupdateFunc = function( i, contexts, values ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tcontexts[ i ] = this;\n\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( values === progressValues ) {\n\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n\n\t\t\t\t\t} else if ( !( --remaining ) ) {\n\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tprogressValues, progressContexts, resolveContexts;\n\n\t\t// add listeners to Deferred subordinates; treat others as resolved\n\t\tif ( length > 1 ) {\n\t\t\tprogressValues = new Array( length );\n\t\t\tprogressContexts = new Array( length );\n\t\t\tresolveContexts = new Array( length );\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n\t\t\t\t\tresolveValues[ i ].promise()\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) )\n\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject );\n\t\t\t\t} else {\n\t\t\t\t\t--remaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we're not waiting on anything, resolve the master\n\t\tif ( !remaining ) {\n\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n\t\t}\n\n\t\treturn deferred.promise();\n\t}\n} );\n\n\n// The deferred used on DOM ready\nvar readyList;\n\njQuery.fn.ready = function( fn ) {\n\n\t// Add the callback\n\tjQuery.ready.promise().done( fn );\n\n\treturn this;\n};\n\njQuery.extend( {\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.triggerHandler ) {\n\t\t\tjQuery( document ).triggerHandler( \"ready\" );\n\t\t\tjQuery( document ).off( \"ready\" );\n\t\t}\n\t}\n} );\n\n/**\n * Clean-up method for dom ready events\n */\nfunction detach() {\n\tif ( document.addEventListener ) {\n\t\tdocument.removeEventListener( \"DOMContentLoaded\", completed );\n\t\twindow.removeEventListener( \"load\", completed );\n\n\t} else {\n\t\tdocument.detachEvent( \"onreadystatechange\", completed );\n\t\twindow.detachEvent( \"onload\", completed );\n\t}\n}\n\n/**\n * The ready event handler and self cleanup method\n */\nfunction completed() {\n\n\t// readyState === \"complete\" is good enough for us to call the dom ready in oldIE\n\tif ( document.addEventListener ||\n\t\twindow.event.type === \"load\" ||\n\t\tdocument.readyState === \"complete\" ) {\n\n\t\tdetach();\n\t\tjQuery.ready();\n\t}\n}\n\njQuery.ready.promise = function( obj ) {\n\tif ( !readyList ) {\n\n\t\treadyList = jQuery.Deferred();\n\n\t\t// Catch cases where $(document).ready() is called\n\t\t// after the browser event has already occurred.\n\t\t// Support: IE6-10\n\t\t// Older IE sometimes signals \"interactive\" too soon\n\t\tif ( document.readyState === \"complete\" ||\n\t\t\t( document.readyState !== \"loading\" && !document.documentElement.doScroll ) ) {\n\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\twindow.setTimeout( jQuery.ready );\n\n\t\t// Standards-based browsers support DOMContentLoaded\n\t\t} else if ( document.addEventListener ) {\n\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed );\n\n\t\t// If IE event model is used\n\t\t} else {\n\n\t\t\t// Ensure firing before onload, maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", completed );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", completed );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar top = false;\n\n\t\t\ttry {\n\t\t\t\ttop = window.frameElement == null && document.documentElement;\n\t\t\t} catch ( e ) {}\n\n\t\t\tif ( top && top.doScroll ) {\n\t\t\t\t( function doScrollCheck() {\n\t\t\t\t\tif ( !jQuery.isReady ) {\n\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Use the trick by Diego Perini\n\t\t\t\t\t\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\t\t\t\t\t\ttop.doScroll( \"left\" );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn window.setTimeout( doScrollCheck, 50 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// detach all dom ready events\n\t\t\t\t\t\tdetach();\n\n\t\t\t\t\t\t// and execute any waiting functions\n\t\t\t\t\t\tjQuery.ready();\n\t\t\t\t\t}\n\t\t\t\t} )();\n\t\t\t}\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n// Kick off the DOM ready check even if the user does not\njQuery.ready.promise();\n\n\n\n\n// Support: IE<9\n// Iteration over object's inherited properties before its own\nvar i;\nfor ( i in jQuery( support ) ) {\n\tbreak;\n}\nsupport.ownFirst = i === \"0\";\n\n// Note: most support tests are defined in their respective modules.\n// false until the test is run\nsupport.inlineBlockNeedsLayout = false;\n\n// Execute ASAP in case we need to set body.style.zoom\njQuery( function() {\n\n\t// Minified: var a,b,c,d\n\tvar val, div, body, container;\n\n\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\tif ( !body || !body.style ) {\n\n\t\t// Return for frameset docs that don't have a body\n\t\treturn;\n\t}\n\n\t// Setup\n\tdiv = document.createElement( \"div\" );\n\tcontainer = document.createElement( \"div\" );\n\tcontainer.style.cssText = \"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\";\n\tbody.appendChild( container ).appendChild( div );\n\n\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\n\t\t// Support: IE<8\n\t\t// Check if natively block-level elements act like inline-block\n\t\t// elements when setting their display to 'inline' and giving\n\t\t// them layout\n\t\tdiv.style.cssText = \"display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1\";\n\n\t\tsupport.inlineBlockNeedsLayout = val = div.offsetWidth === 3;\n\t\tif ( val ) {\n\n\t\t\t// Prevent IE 6 from affecting layout for positioned elements #11048\n\t\t\t// Prevent IE from shrinking the body in IE 7 mode #12869\n\t\t\t// Support: IE<8\n\t\t\tbody.style.zoom = 1;\n\t\t}\n\t}\n\n\tbody.removeChild( container );\n} );\n\n\n( function() {\n\tvar div = document.createElement( \"div\" );\n\n\t// Support: IE<9\n\tsupport.deleteExpando = true;\n\ttry {\n\t\tdelete div.test;\n\t} catch ( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\t// Null elements to avoid leaks in IE.\n\tdiv = null;\n} )();\nvar acceptData = function( elem ) {\n\tvar noData = jQuery.noData[ ( elem.nodeName + \" \" ).toLowerCase() ],\n\t\tnodeType = +elem.nodeType || 1;\n\n\t// Do not set data on non-element DOM nodes because it will not be cleared (#8335).\n\treturn nodeType !== 1 && nodeType !== 9 ?\n\t\tfalse :\n\n\t\t// Nodes accept data unless otherwise specified; rejection can be conditional\n\t\t!noData || noData !== true && elem.getAttribute( \"classid\" ) === noData;\n};\n\n\n\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction dataAttr( elem, key, data ) {\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch ( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tvar name;\n\tfor ( name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[ name ] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nfunction internalData( elem, name, data, pvt /* Internal Use Only */ ) {\n\tif ( !acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar ret, thisCache,\n\t\tinternalKey = jQuery.expando,\n\n\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t// can't GC object references properly across the DOM-JS boundary\n\t\tisNode = elem.nodeType,\n\n\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t// attached directly to the object so GC can occur automatically\n\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;\n\n\t// Avoid doing any more work than we need to when trying to get data on an\n\t// object that has no data at all\n\tif ( ( !id || !cache[ id ] || ( !pvt && !cache[ id ].data ) ) &&\n\t\tdata === undefined && typeof name === \"string\" ) {\n\t\treturn;\n\t}\n\n\tif ( !id ) {\n\n\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t// ends up in the global cache\n\t\tif ( isNode ) {\n\t\t\tid = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;\n\t\t} else {\n\t\t\tid = internalKey;\n\t\t}\n\t}\n\n\tif ( !cache[ id ] ) {\n\n\t\t// Avoid exposing jQuery metadata on plain JS objects when the object\n\t\t// is serialized using JSON.stringify\n\t\tcache[ id ] = isNode ? {} : { toJSON: jQuery.noop };\n\t}\n\n\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t// shallow copied over onto the existing cache\n\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\tif ( pvt ) {\n\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t} else {\n\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t}\n\t}\n\n\tthisCache = cache[ id ];\n\n\t// jQuery data() is stored in a separate object inside the object's internal data\n\t// cache in order to avoid key collisions between internal data and user-defined\n\t// data.\n\tif ( !pvt ) {\n\t\tif ( !thisCache.data ) {\n\t\t\tthisCache.data = {};\n\t\t}\n\n\t\tthisCache = thisCache.data;\n\t}\n\n\tif ( data !== undefined ) {\n\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t}\n\n\t// Check for both converted-to-camel and non-converted data property names\n\t// If a data property was specified\n\tif ( typeof name === \"string\" ) {\n\n\t\t// First Try to find as-is property data\n\t\tret = thisCache[ name ];\n\n\t\t// Test for null|undefined property data\n\t\tif ( ret == null ) {\n\n\t\t\t// Try to find the camelCased property\n\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t}\n\t} else {\n\t\tret = thisCache;\n\t}\n\n\treturn ret;\n}\n\nfunction internalRemoveData( elem, name, pvt ) {\n\tif ( !acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar thisCache, i,\n\t\tisNode = elem.nodeType,\n\n\t\t// See jQuery.data for more information\n\t\tcache = isNode ? jQuery.cache : elem,\n\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t// If there is already no cache entry for this object, there is no\n\t// purpose in continuing\n\tif ( !cache[ id ] ) {\n\t\treturn;\n\t}\n\n\tif ( name ) {\n\n\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\tif ( thisCache ) {\n\n\t\t\t// Support array or space separated string names for data keys\n\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\tname = [ name ];\n\t\t\t\t} else {\n\n\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tname = name.split( \" \" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = name.concat( jQuery.map( name, jQuery.camelCase ) );\n\t\t\t}\n\n\t\t\ti = name.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete thisCache[ name[ i ] ];\n\t\t\t}\n\n\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t// and let the cache object itself get destroyed\n\t\t\tif ( pvt ? !isEmptyDataObject( thisCache ) : !jQuery.isEmptyObject( thisCache ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t// See jQuery.data for more information\n\tif ( !pvt ) {\n\t\tdelete cache[ id ].data;\n\n\t\t// Don't destroy the parent cache unless the internal data object\n\t\t// had been the only thing left in it\n\t\tif ( !isEmptyDataObject( cache[ id ] ) ) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// Destroy the cache\n\tif ( isNode ) {\n\t\tjQuery.cleanData( [ elem ], true );\n\n\t// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)\n\t/* jshint eqeqeq: false */\n\t} else if ( support.deleteExpando || cache != cache.window ) {\n\t\t/* jshint eqeqeq: true */\n\t\tdelete cache[ id ];\n\n\t// When all else fails, undefined\n\t} else {\n\t\tcache[ id ] = undefined;\n\t}\n}\n\njQuery.extend( {\n\tcache: {},\n\n\t// The following elements (space-suffixed to avoid Object.prototype collisions)\n\t// throw uncatchable exceptions if you attempt to set expando properties\n\tnoData: {\n\t\t\"applet \": true,\n\t\t\"embed \": true,\n\n\t\t// ...but Flash objects (which have this classid) *can* handle expandos\n\t\t\"object \": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[ jQuery.expando ] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name );\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data, true );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name, true );\n\t}\n} );\n\njQuery.fn.extend( {\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[ 0 ],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Special expections of .data basically thwart jQuery.access,\n\t\t// so implement the relevant behavior ourselves\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t// Support: IE11+\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice( 5 ) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t} );\n\t\t}\n\n\t\treturn arguments.length > 1 ?\n\n\t\t\t// Sets one value\n\t\t\tthis.each( function() {\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t} ) :\n\n\t\t\t// Gets one value\n\t\t\t// Try to fetch any internally stored data first\n\t\t\telem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t} );\n\t}\n} );\n\n\njQuery.extend( {\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray( data ) ) {\n\t\t\t\t\tqueue = jQuery._data( elem, type, jQuery.makeArray( data ) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// not intended for public consumption - generates a queueHooks object,\n\t// or returns the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn jQuery._data( elem, key ) || jQuery._data( elem, key, {\n\t\t\tempty: jQuery.Callbacks( \"once memory\" ).add( function() {\n\t\t\t\tjQuery._removeData( elem, type + \"queue\" );\n\t\t\t\tjQuery._removeData( elem, key );\n\t\t\t} )\n\t\t} );\n\t}\n} );\n\njQuery.fn.extend( {\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[ 0 ], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each( function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[ 0 ] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t} );\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t} );\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = jQuery._data( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n} );\n\n\n( function() {\n\tvar shrinkWrapBlocksVal;\n\n\tsupport.shrinkWrapBlocks = function() {\n\t\tif ( shrinkWrapBlocksVal != null ) {\n\t\t\treturn shrinkWrapBlocksVal;\n\t\t}\n\n\t\t// Will be changed later if needed.\n\t\tshrinkWrapBlocksVal = false;\n\n\t\t// Minified: var b,c,d\n\t\tvar div, body, container;\n\n\t\tbody = document.getElementsByTagName( \"body\" )[ 0 ];\n\t\tif ( !body || !body.style ) {\n\n\t\t\t// Test fired too early or in an unsupported environment, exit.\n\t\t\treturn;\n\t\t}\n\n\t\t// Setup\n\t\tdiv = document.createElement( \"div\" );\n\t\tcontainer = document.createElement( \"div\" );\n\t\tcontainer.style.cssText = \"position:absolute;border:0;width:0;height:0;top:0;left:-9999px\";\n\t\tbody.appendChild( container ).appendChild( div );\n\n\t\t// Support: IE6\n\t\t// Check if elements with layout shrink-wrap their children\n\t\tif ( typeof div.style.zoom !== \"undefined\" ) {\n\n\t\t\t// Reset CSS: box-sizing; display; margin; border\n\t\t\tdiv.style.cssText =\n\n\t\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t\t// Vendor-prefix box-sizing\n\t\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;\" +\n\t\t\t\t\"box-sizing:content-box;display:block;margin:0;border:0;\" +\n\t\t\t\t\"padding:1px;width:1px;zoom:1\";\n\t\t\tdiv.appendChild( document.createElement( \"div\" ) ).style.width = \"5px\";\n\t\t\tshrinkWrapBlocksVal = div.offsetWidth !== 3;\n\t\t}\n\n\t\tbody.removeChild( container );\n\n\t\treturn shrinkWrapBlocksVal;\n\t};\n\n} )();\nvar pnum = ( /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/ ).source;\n\nvar rcssNum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" );\n\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar isHidden = function( elem, el ) {\n\n\t\t// isHidden might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\t\treturn jQuery.css( elem, \"display\" ) === \"none\" ||\n\t\t\t!jQuery.contains( elem.ownerDocument, elem );\n\t};\n\n\n\nfunction adjustCSS( elem, prop, valueParts, tween ) {\n\tvar adjusted,\n\t\tscale = 1,\n\t\tmaxIterations = 20,\n\t\tcurrentValue = tween ?\n\t\t\tfunction() { return tween.cur(); } :\n\t\t\tfunction() { return jQuery.css( elem, prop, \"\" ); },\n\t\tinitial = currentValue(),\n\t\tunit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t// Starting value computation is required for potential unit mismatches\n\t\tinitialInUnit = ( jQuery.cssNumber[ prop ] || unit !== \"px\" && +initial ) &&\n\t\t\trcssNum.exec( jQuery.css( elem, prop ) );\n\n\tif ( initialInUnit && initialInUnit[ 3 ] !== unit ) {\n\n\t\t// Trust units reported by jQuery.css\n\t\tunit = unit || initialInUnit[ 3 ];\n\n\t\t// Make sure we update the tween properties later on\n\t\tvalueParts = valueParts || [];\n\n\t\t// Iteratively approximate from a nonzero starting point\n\t\tinitialInUnit = +initial || 1;\n\n\t\tdo {\n\n\t\t\t// If previous iteration zeroed out, double until we get *something*.\n\t\t\t// Use string for doubling so we don't accidentally see scale as unchanged below\n\t\t\tscale = scale || \".5\";\n\n\t\t\t// Adjust and apply\n\t\t\tinitialInUnit = initialInUnit / scale;\n\t\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\n\t\t// Update scale, tolerating zero or NaN from tween.cur()\n\t\t// Break the loop if scale is unchanged or perfect, or if we've just had enough.\n\t\t} while (\n\t\t\tscale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations\n\t\t);\n\t}\n\n\tif ( valueParts ) {\n\t\tinitialInUnit = +initialInUnit || +initial || 0;\n\n\t\t// Apply relative offset (+=/-=) if specified\n\t\tadjusted = valueParts[ 1 ] ?\n\t\t\tinitialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :\n\t\t\t+valueParts[ 2 ];\n\t\tif ( tween ) {\n\t\t\ttween.unit = unit;\n\t\t\ttween.start = initialInUnit;\n\t\t\ttween.end = adjusted;\n\t\t}\n\t}\n\treturn adjusted;\n}\n\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlength = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( jQuery.type( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\taccess( elems, fn, i, key[ i ], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tfn(\n\t\t\t\t\telems[ i ],\n\t\t\t\t\tkey,\n\t\t\t\t\traw ? value : value.call( elems[ i ], i, fn( elems[ i ], key ) )\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn chainable ?\n\t\telems :\n\n\t\t// Gets\n\t\tbulk ?\n\t\t\tfn.call( elems ) :\n\t\t\tlength ? fn( elems[ 0 ], key ) : emptyGet;\n};\nvar rcheckableType = ( /^(?:checkbox|radio)$/i );\n\nvar rtagName = ( /<([\\w:-]+)/ );\n\nvar rscriptType = ( /^$|\\/(?:java|ecma)script/i );\n\nvar rleadingWhitespace = ( /^\\s+/ );\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|\" +\n\t\t\"details|dialog|figcaption|figure|footer|header|hgroup|main|\" +\n\t\t\"mark|meter|nav|output|picture|progress|section|summary|template|time|video\";\n\n\n\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\t\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\n\n( function() {\n\tvar div = document.createElement( \"div\" ),\n\t\tfragment = document.createDocumentFragment(),\n\t\tinput = document.createElement( \"input\" );\n\n\t// Setup\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\n\t// IE strips leading whitespace when .innerHTML is used\n\tsupport.leadingWhitespace = div.firstChild.nodeType === 3;\n\n\t// Make sure that tbody elements aren't automatically inserted\n\t// IE will insert them into empty tables\n\tsupport.tbody = !div.getElementsByTagName( \"tbody\" ).length;\n\n\t// Make sure that link elements get serialized correctly by innerHTML\n\t// This requires a wrapper element in IE\n\tsupport.htmlSerialize = !!div.getElementsByTagName( \"link\" ).length;\n\n\t// Makes sure cloning an html5 element does not cause problems\n\t// Where outerHTML is undefined, this still works\n\tsupport.html5Clone =\n\t\tdocument.createElement( \"nav\" ).cloneNode( true ).outerHTML !== \"<:nav></:nav>\";\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tinput.type = \"checkbox\";\n\tinput.checked = true;\n\tfragment.appendChild( input );\n\tsupport.appendChecked = input.checked;\n\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\t// Support: IE6-IE11+\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tfragment.appendChild( div );\n\n\t// Support: Windows Web Apps (WWA)\n\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\tinput = document.createElement( \"input\" );\n\tinput.setAttribute( \"type\", \"radio\" );\n\tinput.setAttribute( \"checked\", \"checked\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\n\t// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3\n\t// old WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE<9\n\t// Cloned elements keep attachEvent handlers, we use addEventListener on IE9+\n\tsupport.noCloneEvent = !!div.addEventListener;\n\n\t// Support: IE<9\n\t// Since attributes and properties are the same in IE,\n\t// cleanData must set properties to undefined rather than use removeAttribute\n\tdiv[ jQuery.expando ] = 1;\n\tsupport.attributes = !div.getAttribute( jQuery.expando );\n} )();\n\n\n// We have to close these tags to support XHTML (#13200)\nvar wrapMap = {\n\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\tarea: [ 1, \"<map>\", \"</map>\" ],\n\n\t// Support: IE8\n\tparam: [ 1, \"<object>\", \"</object>\" ],\n\tthead: [ 1, \"<table>\", \"</table>\" ],\n\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n\t// unless wrapped in a div with non-breaking characters in front of it.\n\t_default: support.htmlSerialize ? [ 0, \"\", \"\" ] : [ 1, \"X<div>\", \"</div>\" ]\n};\n\n// Support: IE8-IE9\nwrapMap.optgroup = wrapMap.option;\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n\nfunction getAll( context, tag ) {\n\tvar elems, elem,\n\t\ti = 0,\n\t\tfound = typeof context.getElementsByTagName !== \"undefined\" ?\n\t\t\tcontext.getElementsByTagName( tag || \"*\" ) :\n\t\t\ttypeof context.querySelectorAll !== \"undefined\" ?\n\t\t\t\tcontext.querySelectorAll( tag || \"*\" ) :\n\t\t\t\tundefined;\n\n\tif ( !found ) {\n\t\tfor ( found = [], elems = context.childNodes || context;\n\t\t\t( elem = elems[ i ] ) != null;\n\t\t\ti++\n\t\t) {\n\t\t\tif ( !tag || jQuery.nodeName( elem, tag ) ) {\n\t\t\t\tfound.push( elem );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( found, getAll( elem, tag ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], found ) :\n\t\tfound;\n}\n\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar elem,\n\t\ti = 0;\n\tfor ( ; ( elem = elems[ i ] ) != null; i++ ) {\n\t\tjQuery._data(\n\t\t\telem,\n\t\t\t\"globalEval\",\n\t\t\t!refElements || jQuery._data( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\n\nvar rhtml = /<|&#?\\w+;/,\n\trtbody = /<tbody/i;\n\nfunction fixDefaultChecked( elem ) {\n\tif ( rcheckableType.test( elem.type ) ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n\nfunction buildFragment( elems, context, scripts, selection, ignored ) {\n\tvar j, elem, contains,\n\t\ttmp, tag, tbody, wrap,\n\t\tl = elems.length,\n\n\t\t// Ensure a safe fragment\n\t\tsafe = createSafeFragment( context ),\n\n\t\tnodes = [],\n\t\ti = 0;\n\n\tfor ( ; i < l; i++ ) {\n\t\telem = elems[ i ];\n\n\t\tif ( elem || elem === 0 ) {\n\n\t\t\t// Add nodes directly\n\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t// Convert non-html into a text node\n\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t// Convert html into DOM nodes\n\t\t\t} else {\n\t\t\t\ttmp = tmp || safe.appendChild( context.createElement( \"div\" ) );\n\n\t\t\t\t// Deserialize a standard representation\n\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\n\t\t\t\ttmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];\n\n\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\tj = wrap[ 0 ];\n\t\t\t\twhile ( j-- ) {\n\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t}\n\n\t\t\t\t// Manually add leading whitespace removed by IE\n\t\t\t\tif ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[ 0 ] ) );\n\t\t\t\t}\n\n\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\tif ( !support.tbody ) {\n\n\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\telem = tag === \"table\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\ttmp.firstChild :\n\n\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\twrap[ 1 ] === \"<table>\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\ttmp :\n\t\t\t\t\t\t\t0;\n\n\t\t\t\t\tj = elem && elem.childNodes.length;\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\tif ( jQuery.nodeName( ( tbody = elem.childNodes[ j ] ), \"tbody\" ) &&\n\t\t\t\t\t\t\t!tbody.childNodes.length ) {\n\n\t\t\t\t\t\t\telem.removeChild( tbody );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t// Fix #12392 for WebKit and IE > 9\n\t\t\t\ttmp.textContent = \"\";\n\n\t\t\t\t// Fix #12392 for oldIE\n\t\t\t\twhile ( tmp.firstChild ) {\n\t\t\t\t\ttmp.removeChild( tmp.firstChild );\n\t\t\t\t}\n\n\t\t\t\t// Remember the top-level container for proper cleanup\n\t\t\t\ttmp = safe.lastChild;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fix #11356: Clear elements from fragment\n\tif ( tmp ) {\n\t\tsafe.removeChild( tmp );\n\t}\n\n\t// Reset defaultChecked for any radios and checkboxes\n\t// about to be appended to the DOM in IE 6/7 (#8060)\n\tif ( !support.appendChecked ) {\n\t\tjQuery.grep( getAll( nodes, \"input\" ), fixDefaultChecked );\n\t}\n\n\ti = 0;\n\twhile ( ( elem = nodes[ i++ ] ) ) {\n\n\t\t// Skip elements already in the context collection (trac-4087)\n\t\tif ( selection && jQuery.inArray( elem, selection ) > -1 ) {\n\t\t\tif ( ignored ) {\n\t\t\t\tignored.push( elem );\n\t\t\t}\n\n\t\t\tcontinue;\n\t\t}\n\n\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Append to fragment\n\t\ttmp = getAll( safe.appendChild( elem ), \"script\" );\n\n\t\t// Preserve script evaluation history\n\t\tif ( contains ) {\n\t\t\tsetGlobalEval( tmp );\n\t\t}\n\n\t\t// Capture executables\n\t\tif ( scripts ) {\n\t\t\tj = 0;\n\t\t\twhile ( ( elem = tmp[ j++ ] ) ) {\n\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\tscripts.push( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\ttmp = null;\n\n\treturn safe;\n}\n\n\n( function() {\n\tvar i, eventName,\n\t\tdiv = document.createElement( \"div\" );\n\n\t// Support: IE<9 (lack submit/change bubble), Firefox (lack focus(in | out) events)\n\tfor ( i in { submit: true, change: true, focusin: true } ) {\n\t\teventName = \"on\" + i;\n\n\t\tif ( !( support[ i ] = eventName in window ) ) {\n\n\t\t\t// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)\n\t\t\tdiv.setAttribute( eventName, \"t\" );\n\t\t\tsupport[ i ] = div.attributes[ eventName ].expando === false;\n\t\t}\n\t}\n\n\t// Null elements to avoid leaks in IE.\n\tdiv = null;\n} )();\n\n\nvar rformElems = /^(?:input|select|textarea)$/i,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\n// Support: IE9\n// See #13393 for more info\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\nfunction on( elem, types, selector, data, fn, one ) {\n\tvar origFn, type;\n\n\t// Types can be a map of types/handlers\n\tif ( typeof types === \"object\" ) {\n\n\t\t// ( types-Object, selector, data )\n\t\tif ( typeof selector !== \"string\" ) {\n\n\t\t\t// ( types-Object, data )\n\t\t\tdata = data || selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tfor ( type in types ) {\n\t\t\ton( elem, type, selector, data, types[ type ], one );\n\t\t}\n\t\treturn elem;\n\t}\n\n\tif ( data == null && fn == null ) {\n\n\t\t// ( types, fn )\n\t\tfn = selector;\n\t\tdata = selector = undefined;\n\t} else if ( fn == null ) {\n\t\tif ( typeof selector === \"string\" ) {\n\n\t\t\t// ( types, selector, fn )\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t} else {\n\n\t\t\t// ( types, data, fn )\n\t\t\tfn = data;\n\t\t\tdata = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t}\n\tif ( fn === false ) {\n\t\tfn = returnFalse;\n\t} else if ( !fn ) {\n\t\treturn elem;\n\t}\n\n\tif ( one === 1 ) {\n\t\torigFn = fn;\n\t\tfn = function( event ) {\n\n\t\t\t// Can use an empty set, since event contains the info\n\t\t\tjQuery().off( event );\n\t\t\treturn origFn.apply( this, arguments );\n\t\t};\n\n\t\t// Use same guid so caller can remove using origFn\n\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t}\n\treturn elem.each( function() {\n\t\tjQuery.event.add( this, types, fn, data, selector );\n\t} );\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\t\tvar tmp, events, t, handleObjIn,\n\t\t\tspecial, eventHandle, handleObj,\n\t\t\thandlers, type, namespaces, origType,\n\t\t\telemData = jQuery._data( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !( events = elemData.events ) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !( eventHandle = elemData.handle ) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" &&\n\t\t\t\t\t( !e || jQuery.event.triggered !== e.type ) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak\n\t\t\t// with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend( {\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join( \".\" )\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !( handlers = events[ type ] ) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup ||\n\t\t\t\t\tspecial.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\t\tvar j, handleObj, tmp,\n\t\t\torigCount, t, events,\n\t\t\tspecial, handlers, type,\n\t\t\tnamespaces, origType,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem );\n\n\t\tif ( !elemData || !( events = elemData.events ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[ 2 ] &&\n\t\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector ||\n\t\t\t\t\t\tselector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown ||\n\t\t\t\t\tspecial.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdelete elemData.handle;\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery._removeData( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\tvar handle, ontype, cur,\n\t\t\tbubbleType, special, tmp, i,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split( \".\" ) : [];\n\n\t\tcur = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) > -1 ) {\n\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split( \".\" );\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf( \":\" ) < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.rnamespace = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === ( elem.ownerDocument || document ) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {\n\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] &&\n\t\t\t\tjQuery._data( cur, \"handle\" );\n\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif (\n\t\t\t\t( !special._default ||\n\t\t\t\t special._default.apply( eventPath.pop(), data ) === false\n\t\t\t\t) && acceptData( elem )\n\t\t\t) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\ttry {\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486,#12518)\n\t\t\t\t\t\t// only reproducible on winXP IE8 native, not IE9 in IE8 mode\n\t\t\t\t\t}\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, j, ret, matched, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\targs = slice.call( arguments ),\n\t\t\thandlers = ( jQuery._data( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[ 0 ] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( ( handleObj = matched.handlers[ j++ ] ) &&\n\t\t\t\t!event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or 2) have namespace(s)\n\t\t\t\t// a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||\n\t\t\t\t\t\thandleObj.handler ).apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( ( event.result = ret ) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar i, matches, sel, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Support (at least): Chrome, IE9\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t//\n\t\t// Support: Firefox<=42+\n\t\t// Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)\n\t\tif ( delegateCount && cur.nodeType &&\n\t\t\t( event.type !== \"click\" || isNaN( event.button ) || event.button < 1 ) ) {\n\n\t\t\t/* jshint eqeqeq: false */\n\t\t\tfor ( ; cur != this; cur = cur.parentNode || this ) {\n\t\t\t\t/* jshint eqeqeq: true */\n\n\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== \"click\" ) ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) > -1 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push( { elem: cur, handlers: matches } );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } );\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Fix target property (#1925)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Support: Safari 6-8+\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)\n\t\tevent.metaKey = !!event.metaKey;\n\n\t\treturn fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: ( \"altKey bubbles cancelable ctrlKey currentTarget detail eventPhase \" +\n\t\t\"metaKey relatedTarget shiftKey target timeStamp view which\" ).split( \" \" ),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split( \" \" ),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: ( \"button buttons clientX clientY fromElement offsetX offsetY \" +\n\t\t\t\"pageX pageY screenX screenY toElement\" ).split( \" \" ),\n\t\tfilter: function( event, original ) {\n\t\t\tvar body, eventDoc, doc,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX +\n\t\t\t\t\t( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -\n\t\t\t\t\t( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY +\n\t\t\t\t\t( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) -\n\t\t\t\t\t( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ?\n\t\t\t\t\toriginal.toElement :\n\t\t\t\t\tfromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tspecial: {\n\t\tload: {\n\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tfocus: {\n\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.focus();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t\t// If we error on focus to hidden element (#1486, #12518),\n\t\t\t\t\t\t// let .trigger() run the handlers\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\t\tclick: {\n\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( jQuery.nodeName( this, \"input\" ) && this.type === \"checkbox\" && this.click ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t_default: function( event ) {\n\t\t\t\treturn jQuery.nodeName( event.target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Piggyback on a donor event to simulate a different one\n\tsimulate: function( type, elem, event ) {\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true\n\n\t\t\t\t// Previously, `originalEvent: {}` was set here, so stopPropagation call\n\t\t\t\t// would not be triggered on donor event, since in our own\n\t\t\t\t// jQuery.event.stopPropagation function we had a check for existence of\n\t\t\t\t// originalEvent.stopPropagation method, so, consequently it would be a noop.\n\t\t\t\t//\n\t\t\t\t// Guard for simulated events was moved to jQuery.event.stopPropagation function\n\t\t\t\t// since `originalEvent` should point to the original event for the\n\t\t\t\t// constancy with other events and for more focused logic\n\t\t\t}\n\t\t);\n\n\t\tjQuery.event.trigger( e, null, elem );\n\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\n\t\t// This \"if\" is needed for plain objects\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tvar name = \"on\" + type;\n\n\t\tif ( elem.detachEvent ) {\n\n\t\t\t// #8545, #7054, preventing memory leaks for custom events in IE6-8\n\t\t\t// detachEvent needed property on element, by name of that event,\n\t\t\t// to properly expose it to GC\n\t\t\tif ( typeof elem[ name ] === \"undefined\" ) {\n\t\t\t\telem[ name ] = null;\n\t\t\t}\n\n\t\t\telem.detachEvent( name, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\n\t// Allow instantiation without the 'new' keyword\n\tif ( !( this instanceof jQuery.Event ) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\n\t\t\t\t// Support: IE < 9, Android < 4.0\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tconstructor: jQuery.Event,\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If preventDefault exists, run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// Support: IE\n\t\t// Otherwise set the returnValue property of the original event to false\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( !e || this.isSimulated ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If stopPropagation exists, run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\n\t\t// Support: IE\n\t\t// Set the cancelBubble property of the original event to true\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopImmediatePropagation ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// so that event delegation works in jQuery.\n// Do the same for pointerenter/pointerleave and pointerover/pointerout\n//\n// Support: Safari 7 only\n// Safari sends mouseenter too often; see:\n// https://code.google.com/p/chromium/issues/detail?id=470258\n// for the description of the bug (it existed in older Chrome versions as well).\njQuery.each( {\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\",\n\tpointerenter: \"pointerover\",\n\tpointerleave: \"pointerout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mouseenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n} );\n\n// IE submit delegation\nif ( !support.submit ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ?\n\n\t\t\t\t\t\t// Support: IE <=8\n\t\t\t\t\t\t// We use jQuery.prop instead of elem.form\n\t\t\t\t\t\t// to allow fixing the IE8 delegated submit issue (gh-2332)\n\t\t\t\t\t\t// by 3rd party polyfills/workarounds.\n\t\t\t\t\t\tjQuery.prop( elem, \"form\" ) :\n\t\t\t\t\t\tundefined;\n\n\t\t\t\tif ( form && !jQuery._data( form, \"submit\" ) ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submitBubble = true;\n\t\t\t\t\t} );\n\t\t\t\t\tjQuery._data( form, \"submit\", true );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\n\t\tpostDispatch: function( event ) {\n\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submitBubble ) {\n\t\t\t\tdelete event._submitBubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !support.change ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._justChanged = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._justChanged && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._justChanged = false;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Allow triggered, simulated change events (#11500)\n\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, \"change\" ) ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t\tjQuery._data( elem, \"change\", true );\n\t\t\t\t}\n\t\t\t} );\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger ||\n\t\t\t\t( elem.type !== \"radio\" && elem.type !== \"checkbox\" ) ) {\n\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn !rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Support: Firefox\n// Firefox doesn't have focus(in | out) events\n// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787\n//\n// Support: Chrome, Safari\n// focus(in | out) events fire after focus & blur events,\n// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order\n// Related ticket - https://code.google.com/p/chromium/issues/detail?id=449857\nif ( !support.focusin ) {\n\tjQuery.each( { focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );\n\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = jQuery._data( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tjQuery._data( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = jQuery._data( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tjQuery._removeData( doc, fix );\n\t\t\t\t} else {\n\t\t\t\t\tjQuery._data( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t} );\n}\n\njQuery.fn.extend( {\n\n\ton: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn );\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ?\n\t\t\t\t\thandleObj.origType + \".\" + handleObj.namespace :\n\t\t\t\t\thandleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t} );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t} );\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[ 0 ];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n} );\n\n\nvar rinlinejQuery = / jQuery\\d+=\"(?:null|\\d+)\"/g,\n\trnoshimcache = new RegExp( \"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\" ),\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:-]+)[^>]*)\\/>/gi,\n\n\t// Support: IE 10-11, Edge 10240+\n\t// In IE/Edge using regex groups here causes severe slowdowns.\n\t// See https://connect.microsoft.com/IE/feedback/details/1736512/\n\trnoInnerhtml = /<script|<style|<link/i,\n\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,\n\tsafeFragment = createSafeFragment( document ),\n\tfragmentDiv = safeFragment.appendChild( document.createElement( \"div\" ) );\n\n// Support: IE<8\n// Manipulating tables requires a tbody\nfunction manipulationTarget( elem, content ) {\n\treturn jQuery.nodeName( elem, \"table\" ) &&\n\t\tjQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ?\n\n\t\telem.getElementsByTagName( \"tbody\" )[ 0 ] ||\n\t\t\telem.appendChild( elem.ownerDocument.createElement( \"tbody\" ) ) :\n\t\telem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = ( jQuery.find.attr( elem, \"type\" ) !== null ) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\tif ( match ) {\n\t\telem.type = match[ 1 ];\n\t} else {\n\t\telem.removeAttribute( \"type\" );\n\t}\n\treturn elem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction fixCloneNodeIssues( src, dest ) {\n\tvar nodeName, e, data;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 copies events bound via attachEvent when using cloneNode.\n\tif ( !support.noCloneEvent && dest[ jQuery.expando ] ) {\n\t\tdata = jQuery._data( dest );\n\n\t\tfor ( e in data.events ) {\n\t\t\tjQuery.removeEvent( dest, e, data.handle );\n\t\t}\n\n\t\t// Event data gets referenced instead of copied if the expando gets copied too\n\t\tdest.removeAttribute( jQuery.expando );\n\t}\n\n\t// IE blanks contents when cloning scripts, and tries to evaluate newly-set text\n\tif ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdisableScript( dest ).text = src.text;\n\t\trestoreScript( dest );\n\n\t// IE6-10 improperly clones children of object elements using classid.\n\t// IE10 throws NoModificationAllowedError if parent is null, #12132.\n\t} else if ( nodeName === \"object\" ) {\n\t\tif ( dest.parentNode ) {\n\t\t\tdest.outerHTML = src.outerHTML;\n\t\t}\n\n\t\t// This path appears unavoidable for IE9. When cloning an object\n\t\t// element in IE9, the outerHTML strategy above is not sufficient.\n\t\t// If the src has innerHTML and the destination does not,\n\t\t// copy the src.innerHTML into the dest.innerHTML. #10324\n\t\tif ( support.html5Clone && ( src.innerHTML && !jQuery.trim( dest.innerHTML ) ) ) {\n\t\t\tdest.innerHTML = src.innerHTML;\n\t\t}\n\n\t} else if ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\n\t\tdest.defaultChecked = dest.checked = src.checked;\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.defaultSelected = dest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\nfunction domManip( collection, args, callback, ignored ) {\n\n\t// Flatten any nested arrays\n\targs = concat.apply( [], args );\n\n\tvar first, node, hasScripts,\n\t\tscripts, doc, fragment,\n\t\ti = 0,\n\t\tl = collection.length,\n\t\tiNoClone = l - 1,\n\t\tvalue = args[ 0 ],\n\t\tisFunction = jQuery.isFunction( value );\n\n\t// We can't cloneNode fragments that contain checked, in WebKit\n\tif ( isFunction ||\n\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\treturn collection.each( function( index ) {\n\t\t\tvar self = collection.eq( index );\n\t\t\tif ( isFunction ) {\n\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t}\n\t\t\tdomManip( self, args, callback, ignored );\n\t\t} );\n\t}\n\n\tif ( l ) {\n\t\tfragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );\n\t\tfirst = fragment.firstChild;\n\n\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\tfragment = first;\n\t\t}\n\n\t\t// Require either new content or an interest in ignored elements to invoke the callback\n\t\tif ( first || ignored ) {\n\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\thasScripts = scripts.length;\n\n\t\t\t// Use the original fragment for the last item\n\t\t\t// instead of the first because it can end up\n\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tnode = fragment;\n\n\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\tif ( hasScripts ) {\n\n\t\t\t\t\t\t// Support: Android<4.1, PhantomJS<2\n\t\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcallback.call( collection[ i ], node, i );\n\t\t\t}\n\n\t\t\tif ( hasScripts ) {\n\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t// Reenable scripts\n\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t!jQuery._data( node, \"globalEval\" ) &&\n\t\t\t\t\t\tjQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\tif ( node.src ) {\n\n\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\tif ( jQuery._evalUrl ) {\n\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjQuery.globalEval(\n\t\t\t\t\t\t\t\t( node.text || node.textContent || node.innerHTML || \"\" )\n\t\t\t\t\t\t\t\t\t.replace( rcleanScript, \"\" )\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fix #11809: Avoid leaking memory\n\t\t\tfragment = first = null;\n\t\t}\n\t}\n\n\treturn collection;\n}\n\nfunction remove( elem, selector, keepData ) {\n\tvar node,\n\t\telems = selector ? jQuery.filter( selector, elem ) : elem,\n\t\ti = 0;\n\n\tfor ( ; ( node = elems[ i ] ) != null; i++ ) {\n\n\t\tif ( !keepData && node.nodeType === 1 ) {\n\t\t\tjQuery.cleanData( getAll( node ) );\n\t\t}\n\n\t\tif ( node.parentNode ) {\n\t\t\tif ( keepData && jQuery.contains( node.ownerDocument, node ) ) {\n\t\t\t\tsetGlobalEval( getAll( node, \"script\" ) );\n\t\t\t}\n\t\t\tnode.parentNode.removeChild( node );\n\t\t}\n\t}\n\n\treturn elem;\n}\n\njQuery.extend( {\n\thtmlPrefilter: function( html ) {\n\t\treturn html.replace( rxhtmlTag, \"<$1></$2>\" );\n\t},\n\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar destElements, node, clone, i, srcElements,\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\tif ( support.html5Clone || jQuery.isXMLDoc( elem ) ||\n\t\t\t!rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ) {\n\n\t\t\tclone = elem.cloneNode( true );\n\n\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t} else {\n\t\t\tfragmentDiv.innerHTML = elem.outerHTML;\n\t\t\tfragmentDiv.removeChild( clone = fragmentDiv.firstChild );\n\t\t}\n\n\t\tif ( ( !support.noCloneEvent || !support.noCloneChecked ) &&\n\t\t\t\t( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\t// Fix all IE cloning issues\n\t\t\tfor ( i = 0; ( node = srcElements[ i ] ) != null; ++i ) {\n\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[ i ] ) {\n\t\t\t\t\tfixCloneNodeIssues( node, destElements[ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0; ( node = srcElements[ i ] ) != null; i++ ) {\n\t\t\t\t\tcloneCopyEvent( node, destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\tdestElements = srcElements = node = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tcleanData: function( elems, /* internal */ forceAcceptData ) {\n\t\tvar elem, type, id, data,\n\t\t\ti = 0,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tcache = jQuery.cache,\n\t\t\tattributes = support.attributes,\n\t\t\tspecial = jQuery.event.special;\n\n\t\tfor ( ; ( elem = elems[ i ] ) != null; i++ ) {\n\t\t\tif ( forceAcceptData || acceptData( elem ) ) {\n\n\t\t\t\tid = elem[ internalKey ];\n\t\t\t\tdata = id && cache[ id ];\n\n\t\t\t\tif ( data ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove cache only if it was not already removed by jQuery.event.remove\n\t\t\t\t\tif ( cache[ id ] ) {\n\n\t\t\t\t\t\tdelete cache[ id ];\n\n\t\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t\t// IE does not allow us to delete expando properties from nodes\n\t\t\t\t\t\t// IE creates expando attributes along with the property\n\t\t\t\t\t\t// IE does not have a removeAttribute function on Document nodes\n\t\t\t\t\t\tif ( !attributes && typeof elem.removeAttribute !== \"undefined\" ) {\n\t\t\t\t\t\t\telem.removeAttribute( internalKey );\n\n\t\t\t\t\t\t// Webkit & Blink performance suffers when deleting properties\n\t\t\t\t\t\t// from DOM nodes, so set to undefined instead\n\t\t\t\t\t\t// https://code.google.com/p/chromium/issues/detail?id=378607\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\telem[ internalKey ] = undefined;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdeletedIds.push( id );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n} );\n\njQuery.fn.extend( {\n\n\t// Keep domManip exposed until 3.0 (gh-2225)\n\tdomManip: domManip,\n\n\tdetach: function( selector ) {\n\t\treturn remove( this, selector, true );\n\t},\n\n\tremove: function( selector ) {\n\t\treturn remove( this, selector );\n\t},\n\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append(\n\t\t\t\t\t( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value )\n\t\t\t\t);\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t} );\n\t},\n\n\tprepend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t} );\n\t},\n\n\tbefore: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t} );\n\t},\n\n\tafter: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t} );\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( elem = this[ i ] ) != null; i++ ) {\n\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\n\t\t\t// If this is a select, ensure that it displays empty (#12336)\n\t\t\t// Support: IE<9\n\t\t\tif ( elem.options && jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\telem.options.length = 0;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t} );\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tundefined;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( support.htmlSerialize || !rnoshimcache.test( value )  ) &&\n\t\t\t\t( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = jQuery.htmlPrefilter( value );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[ i ] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch ( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar ignored = [];\n\n\t\t// Make the changes, replacing each non-ignored context element with the new content\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tvar parent = this.parentNode;\n\n\t\t\tif ( jQuery.inArray( this, ignored ) < 0 ) {\n\t\t\t\tjQuery.cleanData( getAll( this ) );\n\t\t\t\tif ( parent ) {\n\t\t\t\t\tparent.replaceChild( elem, this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Force callback invocation\n\t\t}, ignored );\n\t}\n} );\n\njQuery.each( {\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\ti = 0,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n} );\n\n\nvar iframe,\n\telemdisplay = {\n\n\t\t// Support: Firefox\n\t\t// We have to pre-define these values for FF (#10227)\n\t\tHTML: \"block\",\n\t\tBODY: \"block\"\n\t};\n\n/**\n * Retrieve the actual display of a element\n * @param {String} name nodeName of the element\n * @param {Object} doc Document object\n */\n\n// Called only from within defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\n\t\tdisplay = jQuery.css( elem[ 0 ], \"display\" );\n\n\t// We don't have any data stored on the element,\n\t// so use \"detach\" method as fast way to get rid of the element\n\telem.detach();\n\n\treturn display;\n}\n\n/**\n * Try to determine the default display value of an element\n * @param {String} nodeName\n */\nfunction defaultDisplay( nodeName ) {\n\tvar doc = document,\n\t\tdisplay = elemdisplay[ nodeName ];\n\n\tif ( !display ) {\n\t\tdisplay = actualDisplay( nodeName, doc );\n\n\t\t// If the simple way fails, read from inside an iframe\n\t\tif ( display === \"none\" || !display ) {\n\n\t\t\t// Use the already-created iframe if possible\n\t\t\tiframe = ( iframe || jQuery( \"<iframe frameborder='0' width='0' height='0'/>\" ) )\n\t\t\t\t.appendTo( doc.documentElement );\n\n\t\t\t// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse\n\t\t\tdoc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;\n\n\t\t\t// Support: IE\n\t\t\tdoc.write();\n\t\t\tdoc.close();\n\n\t\t\tdisplay = actualDisplay( nodeName, doc );\n\t\t\tiframe.detach();\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn display;\n}\nvar rmargin = ( /^margin/ );\n\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\nvar swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\nvar documentElement = document.documentElement;\n\n\n\n( function() {\n\tvar pixelPositionVal, pixelMarginRightVal, boxSizingReliableVal,\n\t\treliableHiddenOffsetsVal, reliableMarginRightVal, reliableMarginLeftVal,\n\t\tcontainer = document.createElement( \"div\" ),\n\t\tdiv = document.createElement( \"div\" );\n\n\t// Finish early in limited (non-browser) environments\n\tif ( !div.style ) {\n\t\treturn;\n\t}\n\n\tdiv.style.cssText = \"float:left;opacity:.5\";\n\n\t// Support: IE<9\n\t// Make sure that element opacity exists (as opposed to filter)\n\tsupport.opacity = div.style.opacity === \"0.5\";\n\n\t// Verify style float existence\n\t// (IE uses styleFloat instead of cssFloat)\n\tsupport.cssFloat = !!div.style.cssFloat;\n\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\tcontainer = document.createElement( \"div\" );\n\tcontainer.style.cssText = \"border:0;width:8px;height:0;top:0;left:-9999px;\" +\n\t\t\"padding:0;margin-top:1px;position:absolute\";\n\tdiv.innerHTML = \"\";\n\tcontainer.appendChild( div );\n\n\t// Support: Firefox<29, Android 2.3\n\t// Vendor-prefix box-sizing\n\tsupport.boxSizing = div.style.boxSizing === \"\" || div.style.MozBoxSizing === \"\" ||\n\t\tdiv.style.WebkitBoxSizing === \"\";\n\n\tjQuery.extend( support, {\n\t\treliableHiddenOffsets: function() {\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn reliableHiddenOffsetsVal;\n\t\t},\n\n\t\tboxSizingReliable: function() {\n\n\t\t\t// We're checking for pixelPositionVal here instead of boxSizingReliableVal\n\t\t\t// since that compresses better and they're computed together anyway.\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn boxSizingReliableVal;\n\t\t},\n\n\t\tpixelMarginRight: function() {\n\n\t\t\t// Support: Android 4.0-4.3\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn pixelMarginRightVal;\n\t\t},\n\n\t\tpixelPosition: function() {\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn pixelPositionVal;\n\t\t},\n\n\t\treliableMarginRight: function() {\n\n\t\t\t// Support: Android 2.3\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn reliableMarginRightVal;\n\t\t},\n\n\t\treliableMarginLeft: function() {\n\n\t\t\t// Support: IE <=8 only, Android 4.0 - 4.3 only, Firefox <=3 - 37\n\t\t\tif ( pixelPositionVal == null ) {\n\t\t\t\tcomputeStyleTests();\n\t\t\t}\n\t\t\treturn reliableMarginLeftVal;\n\t\t}\n\t} );\n\n\tfunction computeStyleTests() {\n\t\tvar contents, divStyle,\n\t\t\tdocumentElement = document.documentElement;\n\n\t\t// Setup\n\t\tdocumentElement.appendChild( container );\n\n\t\tdiv.style.cssText =\n\n\t\t\t// Support: Android 2.3\n\t\t\t// Vendor-prefix box-sizing\n\t\t\t\"-webkit-box-sizing:border-box;box-sizing:border-box;\" +\n\t\t\t\"position:relative;display:block;\" +\n\t\t\t\"margin:auto;border:1px;padding:1px;\" +\n\t\t\t\"top:1%;width:50%\";\n\n\t\t// Support: IE<9\n\t\t// Assume reasonable values in the absence of getComputedStyle\n\t\tpixelPositionVal = boxSizingReliableVal = reliableMarginLeftVal = false;\n\t\tpixelMarginRightVal = reliableMarginRightVal = true;\n\n\t\t// Check for getComputedStyle so that this code is not run in IE<9.\n\t\tif ( window.getComputedStyle ) {\n\t\t\tdivStyle = window.getComputedStyle( div );\n\t\t\tpixelPositionVal = ( divStyle || {} ).top !== \"1%\";\n\t\t\treliableMarginLeftVal = ( divStyle || {} ).marginLeft === \"2px\";\n\t\t\tboxSizingReliableVal = ( divStyle || { width: \"4px\" } ).width === \"4px\";\n\n\t\t\t// Support: Android 4.0 - 4.3 only\n\t\t\t// Some styles come back with percentage values, even though they shouldn't\n\t\t\tdiv.style.marginRight = \"50%\";\n\t\t\tpixelMarginRightVal = ( divStyle || { marginRight: \"4px\" } ).marginRight === \"4px\";\n\n\t\t\t// Support: Android 2.3 only\n\t\t\t// Div with explicit width and no margin-right incorrectly\n\t\t\t// gets computed margin-right based on width of container (#3333)\n\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\tcontents = div.appendChild( document.createElement( \"div\" ) );\n\n\t\t\t// Reset CSS: box-sizing; display; margin; border; padding\n\t\t\tcontents.style.cssText = div.style.cssText =\n\n\t\t\t\t// Support: Android 2.3\n\t\t\t\t// Vendor-prefix box-sizing\n\t\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;\" +\n\t\t\t\t\"box-sizing:content-box;display:block;margin:0;border:0;padding:0\";\n\t\t\tcontents.style.marginRight = contents.style.width = \"0\";\n\t\t\tdiv.style.width = \"1px\";\n\n\t\t\treliableMarginRightVal =\n\t\t\t\t!parseFloat( ( window.getComputedStyle( contents ) || {} ).marginRight );\n\n\t\t\tdiv.removeChild( contents );\n\t\t}\n\n\t\t// Support: IE6-8\n\t\t// First check that getClientRects works as expected\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\tdiv.style.display = \"none\";\n\t\treliableHiddenOffsetsVal = div.getClientRects().length === 0;\n\t\tif ( reliableHiddenOffsetsVal ) {\n\t\t\tdiv.style.display = \"\";\n\t\t\tdiv.innerHTML = \"<table><tr><td></td><td>t</td></tr></table>\";\n\t\t\tdiv.childNodes[ 0 ].style.borderCollapse = \"separate\";\n\t\t\tcontents = div.getElementsByTagName( \"td\" );\n\t\t\tcontents[ 0 ].style.cssText = \"margin:0;border:0;padding:0;display:none\";\n\t\t\treliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;\n\t\t\tif ( reliableHiddenOffsetsVal ) {\n\t\t\t\tcontents[ 0 ].style.display = \"\";\n\t\t\t\tcontents[ 1 ].style.display = \"none\";\n\t\t\t\treliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;\n\t\t\t}\n\t\t}\n\n\t\t// Teardown\n\t\tdocumentElement.removeChild( container );\n\t}\n\n} )();\n\n\nvar getStyles, curCSS,\n\trposition = /^(top|right|bottom|left)$/;\n\nif ( window.getComputedStyle ) {\n\tgetStyles = function( elem ) {\n\n\t\t// Support: IE<=11+, Firefox<=30+ (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\tvar view = elem.ownerDocument.defaultView;\n\n\t\tif ( !view || !view.opener ) {\n\t\t\tview = window;\n\t\t}\n\n\t\treturn view.getComputedStyle( elem );\n\t};\n\n\tcurCSS = function( elem, name, computed ) {\n\t\tvar width, minWidth, maxWidth, ret,\n\t\t\tstyle = elem.style;\n\n\t\tcomputed = computed || getStyles( elem );\n\n\t\t// getPropertyValue is only needed for .css('filter') in IE9, see #12537\n\t\tret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;\n\n\t\t// Support: Opera 12.1x only\n\t\t// Fall back to style even without computed\n\t\t// computed is undefined for elems on document fragments\n\t\tif ( ( ret === \"\" || ret === undefined ) && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\tif ( computed ) {\n\n\t\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t\t// Chrome < 17 and Safari 5.0 uses \"computed value\"\n\t\t\t// instead of \"used value\" for margin-right\n\t\t\t// Safari 5.1.7 (at least) returns percentage for a larger set of values,\n\t\t\t// but width seems to be reliably pixels\n\t\t\t// this is against the CSSOM draft spec:\n\t\t\t// http://dev.w3.org/csswg/cssom/#resolved-values\n\t\t\tif ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t\t// Remember the original values\n\t\t\t\twidth = style.width;\n\t\t\t\tminWidth = style.minWidth;\n\t\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t\t// Put in the new values to get a computed value out\n\t\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\t\tret = computed.width;\n\n\t\t\t\t// Revert the changed values\n\t\t\t\tstyle.width = width;\n\t\t\t\tstyle.minWidth = minWidth;\n\t\t\t\tstyle.maxWidth = maxWidth;\n\t\t\t}\n\t\t}\n\n\t\t// Support: IE\n\t\t// IE returns zIndex value as an integer.\n\t\treturn ret === undefined ?\n\t\t\tret :\n\t\t\tret + \"\";\n\t};\n} else if ( documentElement.currentStyle ) {\n\tgetStyles = function( elem ) {\n\t\treturn elem.currentStyle;\n\t};\n\n\tcurCSS = function( elem, name, computed ) {\n\t\tvar left, rs, rsLeft, ret,\n\t\t\tstyle = elem.style;\n\n\t\tcomputed = computed || getStyles( elem );\n\t\tret = computed ? computed[ name ] : undefined;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && style[ name ] ) {\n\t\t\tret = style[ name ];\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\t// but not position css attributes, as those are\n\t\t// proportional to the parent element instead\n\t\t// and we can't measure the parent instead because it\n\t\t// might trigger a \"stacking dolls\" problem\n\t\tif ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trs = elem.runtimeStyle;\n\t\t\trsLeft = rs && rs.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\t// Support: IE\n\t\t// IE returns zIndex value as an integer.\n\t\treturn ret === undefined ?\n\t\t\tret :\n\t\t\tret + \"\" || \"auto\";\n\t};\n}\n\n\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\n\t// Define the hook, we'll check on the first run if it's really needed.\n\treturn {\n\t\tget: function() {\n\t\t\tif ( conditionFn() ) {\n\n\t\t\t\t// Hook not needed (or it's not possible to use it due\n\t\t\t\t// to missing dependency), remove it.\n\t\t\t\tdelete this.get;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\t\t\treturn ( this.get = hookFn ).apply( this, arguments );\n\t\t}\n\t};\n}\n\n\nvar\n\n\t\tralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity\\s*=\\s*([^)]*)/i,\n\n\t// swappable if display is none or starts with table except\n\t// \"table\", \"table-cell\", or \"table-caption\"\n\t// see here for display values:\n\t// https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trnumsplit = new RegExp( \"^(\" + pnum + \")(.*)$\", \"i\" ),\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t},\n\n\tcssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ],\n\temptyStyle = document.createElement( \"div\" ).style;\n\n\n// return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( name ) {\n\n\t// shortcut for names that are not vendor prefixed\n\tif ( name in emptyStyle ) {\n\t\treturn name;\n\t}\n\n\t// check for vendor prefixed names\n\tvar capName = name.charAt( 0 ).toUpperCase() + name.slice( 1 ),\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in emptyStyle ) {\n\t\t\treturn name;\n\t\t}\n\t}\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem, hidden,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] =\n\t\t\t\t\tjQuery._data( elem, \"olddisplay\", defaultDisplay( elem.nodeName ) );\n\t\t\t}\n\t\t} else {\n\t\t\thidden = isHidden( elem );\n\n\t\t\tif ( display && display !== \"none\" || !hidden ) {\n\t\t\t\tjQuery._data(\n\t\t\t\t\telem,\n\t\t\t\t\t\"olddisplay\",\n\t\t\t\t\thidden ? display : jQuery.css( elem, \"display\" )\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of most of the elements in a second loop\n\t// to avoid the constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n\t\t\telem.style.display = show ? values[ index ] || \"\" : \"none\";\n\t\t}\n\t}\n\n\treturn elements;\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\tvar matches = rnumsplit.exec( value );\n\treturn matches ?\n\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\tvar i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n\n\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\n\n\t\t// Otherwise initialize for horizontal or vertical properties\n\t\tname === \"width\" ? 1 : 0,\n\n\t\tval = 0;\n\n\tfor ( ; i < 4; i += 2 ) {\n\n\t\t// both box models exclude margin, so add it if we want it\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\tif ( isBorderBox ) {\n\n\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\tif ( extra === \"content\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// at this point, extra isn't border nor margin, so remove border\n\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t} else {\n\n\t\t\t// at this point, extra isn't content, so add padding\n\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// at this point, extra isn't content nor padding, so add border\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property, which is equivalent to the border-box value\n\tvar valueIsBorderBox = true,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\tstyles = getStyles( elem ),\n\t\tisBorderBox = support.boxSizing &&\n\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\tif ( val <= 0 || val == null ) {\n\n\t\t// Fall back to computed then uncomputed css if necessary\n\t\tval = curCSS( elem, name, styles );\n\t\tif ( val < 0 || val == null ) {\n\t\t\tval = elem.style[ name ];\n\t\t}\n\n\t\t// Computed unit is not pixels. Stop here and return.\n\t\tif ( rnumnonpx.test( val ) ) {\n\t\t\treturn val;\n\t\t}\n\n\t\t// we need the check for style in case a browser which returns unreliable values\n\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\tvalueIsBorderBox = isBorderBox &&\n\t\t\t( support.boxSizingReliable() || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles\n\t\t)\n\t) + \"px\";\n}\n\njQuery.extend( {\n\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Don't automatically add \"px\" to these possibly-unitless properties\n\tcssNumber: {\n\t\t\"animationIterationCount\": true,\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"flexGrow\": true,\n\t\t\"flexShrink\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"order\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\n\t\t// normalize float css property\n\t\t\"float\": support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style;\n\n\t\tname = jQuery.cssProps[ origName ] ||\n\t\t\t( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Convert \"+=\" or \"-=\" to relative numbers (#7345)\n\t\t\tif ( type === \"string\" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {\n\t\t\t\tvalue = adjustCSS( elem, name, ret );\n\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that null and NaN values aren't set. See: #7116\n\t\t\tif ( value == null || value !== value ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add the unit (except for certain CSS properties)\n\t\t\tif ( type === \"number\" ) {\n\t\t\t\tvalue += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? \"\" : \"px\" );\n\t\t\t}\n\n\t\t\t// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,\n\t\t\t// but it would mean to define eight\n\t\t\t// (for every problematic property) identical functions\n\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf( \"background\" ) === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !( \"set\" in hooks ) ||\n\t\t\t\t( value = hooks.set( elem, value, extra ) ) !== undefined ) {\n\n\t\t\t\t// Support: IE\n\t\t\t\t// Swallow errors from 'invalid' CSS values (#5509)\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch ( e ) {}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks &&\n\t\t\t\t( ret = hooks.get( elem, false, extra ) ) !== undefined ) {\n\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar num, val, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] ||\n\t\t\t( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t//convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Return, converting to number if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || isFinite( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t}\n} );\n\njQuery.each( [ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\n\t\t\t\t// certain elements can have dimension info if we invisibly show them\n\t\t\t\t// however, it must have a current display style that would benefit from this\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) &&\n\t\t\t\t\telem.offsetWidth === 0 ?\n\t\t\t\t\t\tswap( elem, cssShow, function() {\n\t\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t\t} ) :\n\t\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar styles = extra && getStyles( elem );\n\t\t\treturn setPositiveNumber( elem, value, extra ?\n\t\t\t\taugmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra,\n\t\t\t\t\tsupport.boxSizing &&\n\t\t\t\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\tstyles\n\t\t\t\t) : 0\n\t\t\t);\n\t\t}\n\t};\n} );\n\nif ( !support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( ( computed && elem.currentStyle ?\n\t\t\t\telem.currentStyle.filter :\n\t\t\t\telem.style.filter ) || \"\" ) ?\n\t\t\t\t\t( 0.01 * parseFloat( RegExp.$1 ) ) + \"\" :\n\t\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist -\n\t\t\t// attempt to remove filter attribute #6652\n\t\t\t// if value === \"\", then remove inline opacity #12685\n\t\t\tif ( ( value >= 1 || value === \"\" ) &&\n\t\t\t\t\tjQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" &&\n\t\t\t\t\tstyle.removeAttribute ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there is no filter style applied in a css rule\n\t\t\t\t// or unset inline opacity, we are done\n\t\t\t\tif ( value === \"\" || currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\njQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn swap( elem, { \"display\": \"inline-block\" },\n\t\t\t\tcurCSS, [ elem, \"marginRight\" ] );\n\t\t}\n\t}\n);\n\njQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn (\n\t\t\t\tparseFloat( curCSS( elem, \"marginLeft\" ) ) ||\n\n\t\t\t\t// Support: IE<=11+\n\t\t\t\t// Running getBoundingClientRect on a disconnected node in IE throws an error\n\t\t\t\t// Support: IE8 only\n\t\t\t\t// getClientRects() errors on disconnected elems\n\t\t\t\t( jQuery.contains( elem.ownerDocument, elem ) ?\n\t\t\t\t\telem.getBoundingClientRect().left -\n\t\t\t\t\t\tswap( elem, { marginLeft: 0 }, function() {\n\t\t\t\t\t\t\treturn elem.getBoundingClientRect().left;\n\t\t\t\t\t\t} ) :\n\t\t\t\t\t0\n\t\t\t\t)\n\t\t\t) + \"px\";\n\t\t}\n\t}\n);\n\n// These hooks are used by animate to expand properties\njQuery.each( {\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split( \" \" ) : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( !rmargin.test( prefix ) ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n} );\n\njQuery.fn.extend( {\n\tcss: function( name, value ) {\n\t\treturn access( this, function( elem, name, value ) {\n\t\t\tvar styles, len,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t},\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tif ( typeof state === \"boolean\" ) {\n\t\t\treturn state ? this.show() : this.hide();\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tif ( isHidden( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t} );\n\t}\n} );\n\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || jQuery.easing._default;\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\t// Use a property on the element directly when it is not a DOM element,\n\t\t\t// or when there is no matching style property that exists.\n\t\t\tif ( tween.elem.nodeType !== 1 ||\n\t\t\t\ttween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails\n\t\t\t// so, simple values such as \"10px\" are parsed to Float.\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\n\t\t\t// use step hook for back compat - use cssHook if its there - use .style if its\n\t\t\t// available and use plain properties where available\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.nodeType === 1 &&\n\t\t\t\t( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||\n\t\t\t\t\tjQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Support: IE <=9\n// Panic based approach to setting things on disconnected nodes\n\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p * Math.PI ) / 2;\n\t},\n\t_default: \"swing\"\n};\n\njQuery.fx = Tween.prototype.init;\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\n\n\n\nvar\n\tfxNow, timerId,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trrun = /queueHooks$/;\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\twindow.setTimeout( function() {\n\t\tfxNow = undefined;\n\t} );\n\treturn ( fxNow = jQuery.now() );\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\tattrs = { height: type },\n\t\ti = 0;\n\n\t// if we include width, step value is 1 to do all cssExpand values,\n\t// if we don't include width, step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth ? 1 : 0;\n\tfor ( ; i < 4 ; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\nfunction createTween( value, prop, animation ) {\n\tvar tween,\n\t\tcollection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ \"*\" ] ),\n\t\tindex = 0,\n\t\tlength = collection.length;\n\tfor ( ; index < length; index++ ) {\n\t\tif ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {\n\n\t\t\t// we're done with this property\n\t\t\treturn tween;\n\t\t}\n\t}\n}\n\nfunction defaultPrefilter( elem, props, opts ) {\n\t/* jshint validthis: true */\n\tvar prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHidden( elem ),\n\t\tdataShow = jQuery._data( elem, \"fxshow\" );\n\n\t// handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always( function() {\n\n\t\t\t// doing this makes sure that the complete handler will be called\n\t\t\t// before this completes\n\t\t\tanim.always( function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\t}\n\n\t// height/width overflow pass\n\tif ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n\n\t\t// Make sure that nothing sneaks out\n\t\t// Record all 3 overflow attributes because IE does not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t// Test default display if display is currently \"none\"\n\t\tcheckDisplay = display === \"none\" ?\n\t\t\tjQuery._data( elem, \"olddisplay\" ) || defaultDisplay( elem.nodeName ) : display;\n\n\t\tif ( checkDisplay === \"inline\" && jQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t// inline-level elements accept inline-block;\n\t\t\t// block-level elements need to be inline with layout\n\t\t\tif ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === \"inline\" ) {\n\t\t\t\tstyle.display = \"inline-block\";\n\t\t\t} else {\n\t\t\t\tstyle.zoom = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tif ( !support.shrinkWrapBlocks() ) {\n\t\t\tanim.always( function() {\n\t\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t\t} );\n\t\t}\n\t}\n\n\t// show/hide pass\n\tfor ( prop in props ) {\n\t\tvalue = props[ prop ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ prop ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t// If there is dataShow left over from a stopped hide or show\n\t\t\t\t// and we are going to proceed with show, we should pretend to be hidden\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\n\t\t// Any non-fx value stops us from restoring the original display value\n\t\t} else {\n\t\t\tdisplay = undefined;\n\t\t}\n\t}\n\n\tif ( !jQuery.isEmptyObject( orig ) ) {\n\t\tif ( dataShow ) {\n\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\thidden = dataShow.hidden;\n\t\t\t}\n\t\t} else {\n\t\t\tdataShow = jQuery._data( elem, \"fxshow\", {} );\n\t\t}\n\n\t\t// store state if its toggle - enables .stop().toggle() to \"reverse\"\n\t\tif ( toggle ) {\n\t\t\tdataShow.hidden = !hidden;\n\t\t}\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done( function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t} );\n\t\t}\n\t\tanim.done( function() {\n\t\t\tvar prop;\n\t\t\tjQuery._removeData( elem, \"fxshow\" );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t} );\n\t\tfor ( prop in orig ) {\n\t\t\ttween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t// If this is a noop like .hide().hide(), restore an overwritten display value\n\t} else if ( ( display === \"none\" ? defaultDisplay( elem.nodeName ) : display ) === \"inline\" ) {\n\t\tstyle.display = display;\n\t}\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar index, name, easing, value, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t// also - reusing 'index' from above because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = Animation.prefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\n\t\t\t// don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t} ),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\n\t\t\t\t// Support: Android 2.3\n\t\t\t\t// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ] );\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise( {\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, {\n\t\t\t\tspecialEasing: {},\n\t\t\t\teasing: jQuery.easing._default\n\t\t\t}, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\n\t\t\t\t\t// if we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// resolve when we played the last frame\n\t\t\t\t// otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.notifyWith( elem, [ animation, 1, 0 ] );\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t} ),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length ; index++ ) {\n\t\tresult = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\tif ( jQuery.isFunction( result.stop ) ) {\n\t\t\t\tjQuery._queueHooks( animation.elem, animation.opts.queue ).stop =\n\t\t\t\t\tjQuery.proxy( result.stop, result );\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tjQuery.map( props, createTween, animation );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t} )\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweeners: {\n\t\t\"*\": [ function( prop, value ) {\n\t\t\tvar tween = this.createTween( prop, value );\n\t\t\tadjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );\n\t\t\treturn tween;\n\t\t} ]\n\t},\n\n\ttweener: function( props, callback ) {\n\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.match( rnotwhite );\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length ; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\tAnimation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];\n\t\t\tAnimation.tweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilters: [ defaultPrefilter ],\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tAnimation.prefilters.unshift( callback );\n\t\t} else {\n\t\t\tAnimation.prefilters.push( callback );\n\t\t}\n\t}\n} );\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t};\n\n\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\topt.duration in jQuery.fx.speeds ?\n\t\t\tjQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.fn.extend( {\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n\t\t\t// animate to the value specified\n\t\t\t.end().animate( { opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || jQuery._data( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this &&\n\t\t\t\t\t( type == null || timers[ index ].queue === type ) ) {\n\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t} );\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tvar index,\n\t\t\t\tdata = jQuery._data( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\thooks.stop.call( this, true );\n\t\t\t}\n\n\t\t\t// look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t} );\n\t}\n} );\n\njQuery.each( [ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n} );\n\n// Generate shortcuts for custom animations\njQuery.each( {\n\tslideDown: genFx( \"show\" ),\n\tslideUp: genFx( \"hide\" ),\n\tslideToggle: genFx( \"toggle\" ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n} );\n\njQuery.timers = [];\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ttimers = jQuery.timers,\n\t\ti = 0;\n\n\tfxNow = jQuery.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\n\t\t// Checks the timer has not already been removed\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tjQuery.timers.push( timer );\n\tif ( timer() ) {\n\t\tjQuery.fx.start();\n\t} else {\n\t\tjQuery.timers.pop();\n\t}\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.start = function() {\n\tif ( !timerId ) {\n\t\ttimerId = window.setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\twindow.clearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\n\t// Default speed\n\t_default: 400\n};\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// http://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/\njQuery.fn.delay = function( time, type ) {\n\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\ttype = type || \"fx\";\n\n\treturn this.queue( type, function( next, hooks ) {\n\t\tvar timeout = window.setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\twindow.clearTimeout( timeout );\n\t\t};\n\t} );\n};\n\n\n( function() {\n\tvar a,\n\t\tinput = document.createElement( \"input\" ),\n\t\tdiv = document.createElement( \"div\" ),\n\t\tselect = document.createElement( \"select\" ),\n\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\t// Setup\n\tdiv = document.createElement( \"div\" );\n\tdiv.setAttribute( \"className\", \"t\" );\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// Support: Windows Web Apps (WWA)\n\t// `type` must use .setAttribute for WWA (#14901)\n\tinput.setAttribute( \"type\", \"checkbox\" );\n\tdiv.appendChild( input );\n\n\ta = div.getElementsByTagName( \"a\" )[ 0 ];\n\n\t// First batch of tests.\n\ta.style.cssText = \"top:1px\";\n\n\t// Test setAttribute on camelCase class.\n\t// If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\tsupport.getSetAttribute = div.className !== \"t\";\n\n\t// Get the style information from getAttribute\n\t// (IE uses .cssText instead)\n\tsupport.style = /top/.test( a.getAttribute( \"style\" ) );\n\n\t// Make sure that URLs aren't manipulated\n\t// (IE normalizes it by default)\n\tsupport.hrefNormalized = a.getAttribute( \"href\" ) === \"/a\";\n\n\t// Check the default checkbox/radio value (\"\" on WebKit; \"on\" elsewhere)\n\tsupport.checkOn = !!input.value;\n\n\t// Make sure that a selected-by-default option has a working selected property.\n\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\tsupport.optSelected = opt.selected;\n\n\t// Tests for enctype support on a form (#6743)\n\tsupport.enctype = !!document.createElement( \"form\" ).enctype;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Support: IE8 only\n\t// Check if we can trust getAttribute(\"value\")\n\tinput = document.createElement( \"input\" );\n\tinput.setAttribute( \"value\", \"\" );\n\tsupport.input = input.getAttribute( \"value\" ) === \"\";\n\n\t// Check if an input maintains its value after becoming a radio\n\tinput.value = \"t\";\n\tinput.setAttribute( \"type\", \"radio\" );\n\tsupport.radioValue = input.value === \"t\";\n} )();\n\n\nvar rreturn = /\\r/g,\n\trspaces = /[\\x20\\t\\r\\n\\f]+/g;\n\njQuery.fn.extend( {\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] ||\n\t\t\t\t\tjQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif (\n\t\t\t\t\thooks &&\n\t\t\t\t\t\"get\" in hooks &&\n\t\t\t\t\t( ret = hooks.get( elem, \"value\" ) ) !== undefined\n\t\t\t\t) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace( rreturn, \"\" ) :\n\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each( function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !( \"set\" in hooks ) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\treturn val != null ?\n\t\t\t\t\tval :\n\n\t\t\t\t\t// Support: IE10-11+\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\t// Strip and collapse whitespace\n\t\t\t\t\t// https://html.spec.whatwg.org/#strip-and-collapse-whitespace\n\t\t\t\t\tjQuery.trim( jQuery.text( elem ) ).replace( rspaces, \" \" );\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\" || index < 0,\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length,\n\t\t\t\t\ti = index < 0 ?\n\t\t\t\t\t\tmax :\n\t\t\t\t\t\tone ? index : 0;\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// oldIE doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t( support.optDisabled ?\n\t\t\t\t\t\t\t\t!option.disabled :\n\t\t\t\t\t\t\t\toption.getAttribute( \"disabled\" ) === null ) &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled ||\n\t\t\t\t\t\t\t\t!jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar optionSet, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\ti = options.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\tif ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 ) {\n\n\t\t\t\t\t\t// Support: IE6\n\t\t\t\t\t\t// When new option element is added to select box we need to\n\t\t\t\t\t\t// force reflow of newly added node in order to workaround delay\n\t\t\t\t\t\t// of initialization properties\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\toption.selected = optionSet = true;\n\n\t\t\t\t\t\t} catch ( _ ) {\n\n\t\t\t\t\t\t\t// Will be executed only in IE6\n\t\t\t\t\t\t\toption.scrollHeight;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\toption.selected = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\n\t\t\t\treturn options;\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Radios and checkboxes getter/setter\njQuery.each( [ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );\n\t\t\t}\n\t\t}\n\t};\n\tif ( !support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\treturn elem.getAttribute( \"value\" ) === null ? \"on\" : elem.value;\n\t\t};\n\t}\n} );\n\n\n\n\nvar nodeHook, boolHook,\n\tattrHandle = jQuery.expr.attrHandle,\n\truseDefault = /^(?:checked|selected)$/i,\n\tgetSetAttribute = support.getSetAttribute,\n\tgetSetInput = support.input;\n\njQuery.fn.extend( {\n\tattr: function( name, value ) {\n\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tattr: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set attributes on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\treturn value;\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tret = jQuery.find.attr( elem, name );\n\n\t\t// Non-existent attributes return null, we normalize to undefined\n\t\treturn ret == null ? undefined : ret;\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !support.radioValue && value === \"radio\" &&\n\t\t\t\t\tjQuery.nodeName( elem, \"input\" ) ) {\n\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE8-9\n\t\t\t\t\t// Reset value to default in case type is set after value during creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name, propName,\n\t\t\ti = 0,\n\t\t\tattrNames = value && value.match( rnotwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( ( name = attrNames[ i++ ] ) ) {\n\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t// Boolean attributes get special treatment (#10870)\n\t\t\t\tif ( jQuery.expr.match.bool.test( name ) ) {\n\n\t\t\t\t\t// Set corresponding property to false\n\t\t\t\t\tif ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\t\t\t\t\t\telem[ propName ] = false;\n\n\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t// Also clear defaultChecked/defaultSelected (if appropriate)\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] =\n\t\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\n\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\n\t\t\t// IE<8 needs the *property* name\n\t\t\telem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );\n\n\t\t} else {\n\n\t\t\t// Support: IE<9\n\t\t\t// Use defaultChecked and defaultSelected for oldIE\n\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] = elem[ name ] = true;\n\t\t}\n\t\treturn name;\n\t}\n};\n\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tif ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\t\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\t\tvar ret, handle;\n\t\t\tif ( !isXML ) {\n\n\t\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\t\thandle = attrHandle[ name ];\n\t\t\t\tattrHandle[ name ] = ret;\n\t\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tnull;\n\t\t\t\tattrHandle[ name ] = handle;\n\t\t\t}\n\t\t\treturn ret;\n\t\t};\n\t} else {\n\t\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\t\tif ( !isXML ) {\n\t\t\t\treturn elem[ jQuery.camelCase( \"default-\" + name ) ] ?\n\t\t\t\t\tname.toLowerCase() :\n\t\t\t\t\tnull;\n\t\t\t}\n\t\t};\n\t}\n} );\n\n// fix oldIE attroperties\nif ( !getSetInput || !getSetAttribute ) {\n\tjQuery.attrHooks.value = {\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.defaultValue = value;\n\t\t\t} else {\n\n\t\t\t\t// Use nodeHook if defined (#1954); otherwise setAttribute is fine\n\t\t\t\treturn nodeHook && nodeHook.set( elem, value, name );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = {\n\t\tset: function( elem, value, name ) {\n\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\telem.setAttributeNode(\n\t\t\t\t\t( ret = elem.ownerDocument.createAttribute( name ) )\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tret.value = value += \"\";\n\n\t\t\t// Break association with cloned elements by also using setAttribute (#9646)\n\t\t\tif ( name === \"value\" || value === elem.getAttribute( name ) ) {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t};\n\n\t// Some attributes are constructed with empty-string values when not defined\n\tattrHandle.id = attrHandle.name = attrHandle.coords =\n\t\tfunction( elem, name, isXML ) {\n\t\t\tvar ret;\n\t\t\tif ( !isXML ) {\n\t\t\t\treturn ( ret = elem.getAttributeNode( name ) ) && ret.value !== \"\" ?\n\t\t\t\t\tret.value :\n\t\t\t\t\tnull;\n\t\t\t}\n\t\t};\n\n\t// Fixing value retrieval on a button requires this module\n\tjQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( ret && ret.specified ) {\n\t\t\t\treturn ret.value;\n\t\t\t}\n\t\t},\n\t\tset: nodeHook.set\n\t};\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tset: function( elem, value, name ) {\n\t\t\tnodeHook.set( elem, value === \"\" ? false : value, name );\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each( [ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t} );\n}\n\nif ( !support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Note: IE uppercases css property names, but if we were to .toLowerCase()\n\t\t\t// .cssText, that would destroy case sensitivity in URL's, like in \"background\"\n\t\t\treturn elem.style.cssText || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = value + \"\" );\n\t\t}\n\t};\n}\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button|object)$/i,\n\trclickable = /^(?:a|area)$/i;\n\njQuery.fn.extend( {\n\tprop: function( name, value ) {\n\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each( function() {\n\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch ( e ) {}\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\treturn ( elem[ name ] = value );\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\treturn elem[ name ];\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\t// elem.tabIndex doesn't always return the\n\t\t\t\t// correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\t// Use proper attribute retrieval(#12072)\n\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\treturn tabindex ?\n\t\t\t\t\tparseInt( tabindex, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) ||\n\t\t\t\t\t\trclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t\t0 :\n\t\t\t\t\t\t\t-1;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t}\n} );\n\n// Some attributes require a special call on IE\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !support.hrefNormalized ) {\n\n\t// href/src property should get the full normalized URL (#10299/#12915)\n\tjQuery.each( [ \"href\", \"src\" ], function( i, name ) {\n\t\tjQuery.propHooks[ name ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\treturn elem.getAttribute( name, 4 );\n\t\t\t}\n\t\t};\n\t} );\n}\n\n// Support: Safari, IE9+\n// Accessing the selectedIndex property\n// forces the browser to respect setting selected\n// on the option\n// The getter ensures a default option is selected\n// when in an optgroup\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tset: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\njQuery.each( [\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n} );\n\n// IE6/7 call enctype encoding\nif ( !support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n\n\n\nvar rclass = /[\\t\\r\\n\\f]/g;\n\nfunction getClass( elem ) {\n\treturn jQuery.attr( elem, \"class\" ) || \"\";\n}\n\njQuery.fn.extend( {\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tif ( typeof value === \"string\" && value ) {\n\t\t\tclasses = value.match( rnotwhite ) || [];\n\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\t\t\t\tcur = elem.nodeType === 1 &&\n\t\t\t\t\t( \" \" + curValue + \" \" ).replace( rclass, \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = jQuery.trim( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\tjQuery.attr( elem, \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tif ( !arguments.length ) {\n\t\t\treturn this.attr( \"class\", \"\" );\n\t\t}\n\n\t\tif ( typeof value === \"string\" && value ) {\n\t\t\tclasses = value.match( rnotwhite ) || [];\n\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 &&\n\t\t\t\t\t( \" \" + curValue + \" \" ).replace( rclass, \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) > -1 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = jQuery.trim( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\tjQuery.attr( elem, \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value;\n\n\t\tif ( typeof stateVal === \"boolean\" && type === \"string\" ) {\n\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t}\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).toggleClass(\n\t\t\t\t\tvalue.call( this, i, getClass( this ), stateVal ),\n\t\t\t\t\tstateVal\n\t\t\t\t);\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar className, i, self, classNames;\n\n\t\t\tif ( type === \"string\" ) {\n\n\t\t\t\t// Toggle individual class names\n\t\t\t\ti = 0;\n\t\t\t\tself = jQuery( this );\n\t\t\t\tclassNames = value.match( rnotwhite ) || [];\n\n\t\t\t\twhile ( ( className = classNames[ i++ ] ) ) {\n\n\t\t\t\t\t// Check each className given, space separated list\n\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( value === undefined || type === \"boolean\" ) {\n\t\t\t\tclassName = getClass( this );\n\t\t\t\tif ( className ) {\n\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed \"false\",\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tjQuery.attr( this, \"class\",\n\t\t\t\t\tclassName || value === false ?\n\t\t\t\t\t\"\" :\n\t\t\t\t\tjQuery._data( this, \"__className__\" ) || \"\"\n\t\t\t\t);\n\t\t\t}\n\t\t} );\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className, elem,\n\t\t\ti = 0;\n\n\t\tclassName = \" \" + selector + \" \";\n\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\tif ( elem.nodeType === 1 &&\n\t\t\t\t( \" \" + getClass( elem ) + \" \" ).replace( rclass, \" \" )\n\t\t\t\t\t.indexOf( className ) > -1\n\t\t\t) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n} );\n\n\n\n\n// Return jQuery for attributes-only inclusion\n\n\njQuery.each( ( \"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\" ).split( \" \" ),\n\tfunction( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n} );\n\njQuery.fn.extend( {\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n} );\n\n\nvar location = window.location;\n\nvar nonce = jQuery.now();\n\nvar rquery = ( /\\?/ );\n\n\n\nvar rvalidtokens = /(,)|(\\[|{)|(}|])|\"(?:[^\"\\\\\\r\\n]|\\\\[\"\\\\\\/bfnrt]|\\\\u[\\da-fA-F]{4})*\"\\s*:?|true|false|null|-?(?!0\\d)\\d+(?:\\.\\d+|)(?:[eE][+-]?\\d+|)/g;\n\njQuery.parseJSON = function( data ) {\n\n\t// Attempt to parse using the native JSON parser first\n\tif ( window.JSON && window.JSON.parse ) {\n\n\t\t// Support: Android 2.3\n\t\t// Workaround failure to string-cast null input\n\t\treturn window.JSON.parse( data + \"\" );\n\t}\n\n\tvar requireNonComma,\n\t\tdepth = null,\n\t\tstr = jQuery.trim( data + \"\" );\n\n\t// Guard against invalid (and possibly dangerous) input by ensuring that nothing remains\n\t// after removing valid tokens\n\treturn str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {\n\n\t\t// Force termination if we see a misplaced comma\n\t\tif ( requireNonComma && comma ) {\n\t\t\tdepth = 0;\n\t\t}\n\n\t\t// Perform no more replacements after returning to outermost depth\n\t\tif ( depth === 0 ) {\n\t\t\treturn token;\n\t\t}\n\n\t\t// Commas must not follow \"[\", \"{\", or \",\"\n\t\trequireNonComma = open || comma;\n\n\t\t// Determine new depth\n\t\t// array/object open (\"[\" or \"{\"): depth += true - false (increment)\n\t\t// array/object close (\"]\" or \"}\"): depth += false - true (decrement)\n\t\t// other cases (\",\" or primitive): depth += true - true (numeric cast)\n\t\tdepth += !close - !open;\n\n\t\t// Remove this token\n\t\treturn \"\";\n\t} ) ) ?\n\t\t( Function( \"return \" + str ) )() :\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n};\n\n\n// Cross-browser xml parsing\njQuery.parseXML = function( data ) {\n\tvar xml, tmp;\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\ttry {\n\t\tif ( window.DOMParser ) { // Standard\n\t\t\ttmp = new window.DOMParser();\n\t\t\txml = tmp.parseFromString( data, \"text/xml\" );\n\t\t} else { // IE\n\t\t\txml = new window.ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\txml.async = \"false\";\n\t\t\txml.loadXML( data );\n\t\t}\n\t} catch ( e ) {\n\t\txml = undefined;\n\t}\n\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\tjQuery.error( \"Invalid XML: \" + data );\n\t}\n\treturn xml;\n};\n\n\nvar\n\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\n\t// IE leaves an \\r character at EOL\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg,\n\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat( \"*\" ),\n\n\t// Document location\n\tajaxLocation = location.href,\n\n\t// Segment location into parts\n\tajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( ( dataType = dataTypes[ i++ ] ) ) {\n\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType.charAt( 0 ) === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif ( typeof dataTypeOrTransport === \"string\" &&\n\t\t\t\t!seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t} );\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar deep, key,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\n/* Handles responses to an ajax request:\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\tvar firstDataType, ct, finalDataType, type,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes;\n\n\t// Remove auto dataType and get content-type in the process\n\twhile ( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"Content-Type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[ 0 ] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n/* Chain conversions given the request and the original response\n * Also sets the responseXXX fields on the jqXHR instance\n */\nfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\tvar conv2, current, conv, tmp, prev,\n\t\tconverters = {},\n\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice();\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\tcurrent = dataTypes.shift();\n\n\t// Convert to each sequential dataType\n\twhile ( current ) {\n\n\t\tif ( s.responseFields[ current ] ) {\n\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t}\n\n\t\t// Apply the dataFilter if provided\n\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t}\n\n\t\tprev = current;\n\t\tcurrent = dataTypes.shift();\n\n\t\tif ( current ) {\n\n\t\t\t// There's only work to do if current dataType is non-auto\n\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\tcurrent = prev;\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[ \"throws\" ] ) { // jscs:ignore requireDotNotation\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tstate: \"parsererror\",\n\t\t\t\t\t\t\t\terror: conv ? e : \"No conversion from \" + prev + \" to \" + current\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n\njQuery.extend( {\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /\\bxml\\b/,\n\t\t\thtml: /\\bhtml/,\n\t\t\tjson: /\\bjson\\b/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\",\n\t\t\tjson: \"responseJSON\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar\n\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\n\t\t\t// Loop variable\n\t\t\ti,\n\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\n\t\t\t// Response headers as string\n\t\t\tresponseHeadersString,\n\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\n\t\t\ttransport,\n\n\t\t\t// Response headers\n\t\t\tresponseHeaders,\n\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context &&\n\t\t\t\t( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\t\tjQuery.event,\n\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\t\t\tfor ( code in map ) {\n\n\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || ajaxLocation ) + \"\" )\n\t\t\t.replace( rhash, \"\" )\n\t\t\t.replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( rnotwhite ) || [ \"\" ];\n\n\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) !==\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\tcacheURL = s.url;\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\tcacheURL = ( s.url += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data );\n\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\ts.url = rts.test( cacheURL ) ?\n\n\t\t\t\t\t// If there is already a '_' parameter, set its value\n\t\t\t\t\tcacheURL.replace( rts, \"$1_=\" + nonce++ ) :\n\n\t\t\t\t\t// Otherwise add one to the end\n\t\t\t\t\tcacheURL + ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + nonce++;\n\t\t\t}\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[ 0 ] ] +\n\t\t\t\t\t( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend &&\n\t\t\t( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\n\t\t\t// If request was aborted inside ajaxSend, stop there\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn jqXHR;\n\t\t\t}\n\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = window.setTimeout( function() {\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\twindow.clearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Determine if successful\n\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( isSuccess ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"Last-Modified\" );\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"etag\" );\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 || s.type === \"HEAD\" ) {\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tstatusText = response.state;\n\t\t\t\t\tsuccess = response.data;\n\t\t\t\t\terror = response.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t}\n} );\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\t// The url can be an options object (which then must have .url)\n\t\treturn jQuery.ajax( jQuery.extend( {\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t}, jQuery.isPlainObject( url ) && url ) );\n\t};\n} );\n\n\njQuery._evalUrl = function( url ) {\n\treturn jQuery.ajax( {\n\t\turl: url,\n\n\t\t// Make this explicit, since user can override this through ajaxSetup (#11264)\n\t\ttype: \"GET\",\n\t\tdataType: \"script\",\n\t\tcache: true,\n\t\tasync: false,\n\t\tglobal: false,\n\t\t\"throws\": true\n\t} );\n};\n\n\njQuery.fn.extend( {\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).wrapAll( html.call( this, i ) );\n\t\t\t} );\n\t\t}\n\n\t\tif ( this[ 0 ] ) {\n\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t}\n\n\t\t\twrap.map( function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t} ).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).wrapInner( html.call( this, i ) );\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t} );\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each( function( i ) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );\n\t\t} );\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each( function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t} ).end();\n\t}\n} );\n\n\nfunction getDisplay( elem ) {\n\treturn elem.style && elem.style.display || jQuery.css( elem, \"display\" );\n}\n\nfunction filterHidden( elem ) {\n\n\t// Disconnected elements are considered hidden\n\tif ( !jQuery.contains( elem.ownerDocument || document, elem ) ) {\n\t\treturn true;\n\t}\n\twhile ( elem && elem.nodeType === 1 ) {\n\t\tif ( getDisplay( elem ) === \"none\" || elem.type === \"hidden\" ) {\n\t\t\treturn true;\n\t\t}\n\t\telem = elem.parentNode;\n\t}\n\treturn false;\n}\n\njQuery.expr.filters.hidden = function( elem ) {\n\n\t// Support: Opera <= 12.12\n\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n\treturn support.reliableHiddenOffsets() ?\n\t\t( elem.offsetWidth <= 0 && elem.offsetHeight <= 0 &&\n\t\t\t!elem.getClientRects().length ) :\n\t\t\tfilterHidden( elem );\n};\n\njQuery.expr.filters.visible = function( elem ) {\n\treturn !jQuery.expr.filters.hidden( elem );\n};\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( jQuery.isArray( obj ) ) {\n\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams(\n\t\t\t\t\tprefix + \"[\" + ( typeof v === \"object\" && v != null ? i : \"\" ) + \"]\",\n\t\t\t\t\tv,\n\t\t\t\t\ttraditional,\n\t\t\t\t\tadd\n\t\t\t\t);\n\t\t\t}\n\t\t} );\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, value ) {\n\n\t\t\t// If value is a function, invoke it and return its value\n\t\t\tvalue = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t};\n\n\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\tif ( traditional === undefined ) {\n\t\ttraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t} );\n\n\t} else {\n\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" ).replace( r20, \"+\" );\n};\n\njQuery.fn.extend( {\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map( function() {\n\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t} )\n\t\t.filter( function() {\n\t\t\tvar type = this.type;\n\n\t\t\t// Use .is(\":disabled\") so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t} )\n\t\t.map( function( i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val ) {\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t} ) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t} ).get();\n\t}\n} );\n\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?\n\n\t// Support: IE6-IE8\n\tfunction() {\n\n\t\t// XHR cannot access local files, always use ActiveX for that case\n\t\tif ( this.isLocal ) {\n\t\t\treturn createActiveXHR();\n\t\t}\n\n\t\t// Support: IE 9-11\n\t\t// IE seems to error on cross-domain PATCH requests when ActiveX XHR\n\t\t// is used. In IE 9+ always use the native XHR.\n\t\t// Note: this condition won't catch Edge as it doesn't define\n\t\t// document.documentMode but it also doesn't support ActiveX so it won't\n\t\t// reach this code.\n\t\tif ( document.documentMode > 8 ) {\n\t\t\treturn createStandardXHR();\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// oldIE XHR does not support non-RFC2616 methods (#13240)\n\t\t// See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx\n\t\t// and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9\n\t\t// Although this check for six methods instead of eight\n\t\t// since IE also does not support \"trace\" and \"connect\"\n\t\treturn /^(get|post|head|put|delete|options)$/i.test( this.type ) &&\n\t\t\tcreateStandardXHR() || createActiveXHR();\n\t} :\n\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\nvar xhrId = 0,\n\txhrCallbacks = {},\n\txhrSupported = jQuery.ajaxSettings.xhr();\n\n// Support: IE<10\n// Open requests must be manually aborted on unload (#5280)\n// See https://support.microsoft.com/kb/2856746 for more info\nif ( window.attachEvent ) {\n\twindow.attachEvent( \"onunload\", function() {\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( undefined, true );\n\t\t}\n\t} );\n}\n\n// Determine support properties\nsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nxhrSupported = support.ajax = !!xhrSupported;\n\n// Create transport if the browser can provide an xhr\nif ( xhrSupported ) {\n\n\tjQuery.ajaxTransport( function( options ) {\n\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !options.crossDomain || support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\t\t\t\t\tvar i,\n\t\t\t\t\t\txhr = options.xhr(),\n\t\t\t\t\t\tid = ++xhrId;\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\txhr.open(\n\t\t\t\t\t\toptions.type,\n\t\t\t\t\t\toptions.url,\n\t\t\t\t\t\toptions.async,\n\t\t\t\t\t\toptions.username,\n\t\t\t\t\t\toptions.password\n\t\t\t\t\t);\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !options.crossDomain && !headers[ \"X-Requested-With\" ] ) {\n\t\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Set headers\n\t\t\t\t\tfor ( i in headers ) {\n\n\t\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t\t// IE's ActiveXObject throws a 'Type Mismatch' exception when setting\n\t\t\t\t\t\t// request header to a null-value.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// To keep consistent with other XHR implementations, cast the value\n\t\t\t\t\t\t// to string and ignore `undefined`.\n\t\t\t\t\t\tif ( headers[ i ] !== undefined ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] + \"\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( options.hasContent && options.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\t\t\t\t\t\tvar status, statusText, responses;\n\n\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t// Clean up\n\t\t\t\t\t\t\tdelete xhrCallbacks[ id ];\n\t\t\t\t\t\t\tcallback = undefined;\n\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\n\t\t\t\t\t\t\t// Abort manually if needed\n\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\tstatus = xhr.status;\n\n\t\t\t\t\t\t\t\t// Support: IE<10\n\t\t\t\t\t\t\t\t// Accessing binary-data responseText throws an exception\n\t\t\t\t\t\t\t\t// (#11426)\n\t\t\t\t\t\t\t\tif ( typeof xhr.responseText === \"string\" ) {\n\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\tif ( !status && options.isLocal && !options.crossDomain ) {\n\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\n\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, xhr.getAllResponseHeaders() );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// `xhr.send` may raise an exception, but it will be\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\tif ( !options.async ) {\n\n\t\t\t\t\t\t// If we're in sync mode we fire the callback\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else if ( xhr.readyState === 4 ) {\n\n\t\t\t\t\t\t// (IE6 & IE7) if it's in cache and has been\n\t\t\t\t\t\t// retrieved directly we need to fire the callback\n\t\t\t\t\t\twindow.setTimeout( callback );\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Register the callback, but delay it in case `xhr.send` throws\n\t\t\t\t\t\t// Add to the list of active xhr callbacks\n\t\t\t\t\t\txhr.onreadystatechange = xhrCallbacks[ id ] = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback( undefined, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t} );\n}\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch ( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject( \"Microsoft.XMLHTTP\" );\n\t} catch ( e ) {}\n}\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup( {\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, \" +\n\t\t\t\"application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /\\b(?:java|ecma)script\\b/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n} );\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n} );\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function( s ) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || jQuery( \"head\" )[ 0 ] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement( \"script\" );\n\n\t\t\t\tscript.async = true;\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( script.parentNode ) {\n\t\t\t\t\t\t\tscript.parentNode.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = null;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending\n\t\t\t\t// Use native DOM manipulation to avoid our domManip AJAX trickery\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( undefined, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n} );\n\n\n\n\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup( {\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n} );\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" &&\n\t\t\t\t( s.contentType || \"\" )\n\t\t\t\t\t.indexOf( \"application/x-www-form-urlencoded\" ) === 0 &&\n\t\t\t\trjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[ \"script json\" ] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always( function() {\n\n\t\t\t// If previous value didn't exist - remove it\n\t\t\tif ( overwritten === undefined ) {\n\t\t\t\tjQuery( window ).removeProp( callbackName );\n\n\t\t\t// Otherwise restore preexisting value\n\t\t\t} else {\n\t\t\t\twindow[ callbackName ] = overwritten;\n\t\t\t}\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\n\t\t\t\t// make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t} );\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n} );\n\n\n\n\n// data: string of html\n// context (optional): If specified, the fragment will be created in this context,\n// defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\tcontext = context || document;\n\n\tvar parsed = rsingleTag.exec( data ),\n\t\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[ 1 ] ) ];\n\t}\n\n\tparsed = buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\n\n// Keep a copy of the old load method\nvar _load = jQuery.fn.load;\n\n/**\n * Load a url into a page\n */\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, type, response,\n\t\tself = this,\n\t\toff = url.indexOf( \" \" );\n\n\tif ( off > -1 ) {\n\t\tselector = jQuery.trim( url.slice( off, url.length ) );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax( {\n\t\t\turl: url,\n\n\t\t\t// If \"type\" variable is undefined, then \"GET\" method will be used.\n\t\t\t// Make value of this field explicit since\n\t\t\t// user can override it through ajaxSetup method\n\t\t\ttype: type || \"GET\",\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t} ).done( function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery( \"<div>\" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t// If the request succeeds, this function gets \"data\", \"status\", \"jqXHR\"\n\t\t// but they are ignored because response was set above.\n\t\t// If it fails, this function gets \"jqXHR\", \"status\", \"error\"\n\t\t} ).always( callback && function( jqXHR, status ) {\n\t\t\tself.each( function() {\n\t\t\t\tcallback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t\t} );\n\t\t} );\n\t}\n\n\treturn this;\n};\n\n\n\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [\n\t\"ajaxStart\",\n\t\"ajaxStop\",\n\t\"ajaxComplete\",\n\t\"ajaxError\",\n\t\"ajaxSuccess\",\n\t\"ajaxSend\"\n], function( i, type ) {\n\tjQuery.fn[ type ] = function( fn ) {\n\t\treturn this.on( type, fn );\n\t};\n} );\n\n\n\n\njQuery.expr.filters.animated = function( elem ) {\n\treturn jQuery.grep( jQuery.timers, function( fn ) {\n\t\treturn elem === fn.elem;\n\t} ).length;\n};\n\n\n\n\n\n/**\n * Gets a window from an element\n */\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n\njQuery.offset = {\n\tsetOffset: function( elem, options, i ) {\n\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\tcurElem = jQuery( elem ),\n\t\t\tprops = {};\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tcurOffset = curElem.offset();\n\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\tjQuery.inArray( \"auto\", [ curCSSTop, curCSSLeft ] ) > -1;\n\n\t\t// need to be able to calculate position if either top or left\n\t\t// is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\n\t\t\t// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)\n\t\t\toptions = options.call( elem, i, jQuery.extend( {}, curOffset ) );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\njQuery.fn.extend( {\n\toffset: function( options ) {\n\t\tif ( arguments.length ) {\n\t\t\treturn options === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each( function( i ) {\n\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t} );\n\t\t}\n\n\t\tvar docElem, win,\n\t\t\tbox = { top: 0, left: 0 },\n\t\t\telem = this[ 0 ],\n\t\t\tdoc = elem && elem.ownerDocument;\n\n\t\tif ( !doc ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure it's not a disconnected DOM node\n\t\tif ( !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box;\n\t\t}\n\n\t\t// If we don't have gBCR, just use 0,0 rather than error\n\t\t// BlackBerry 5, iOS 3 (original iPhone)\n\t\tif ( typeof elem.getBoundingClientRect !== \"undefined\" ) {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t}\n\t\twin = getWindow( doc );\n\t\treturn {\n\t\t\ttop: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),\n\t\t\tleft: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )\n\t\t};\n\t},\n\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset,\n\t\t\tparentOffset = { top: 0, left: 0 },\n\t\t\telem = this[ 0 ];\n\n\t\t// Fixed elements are offset from window (parentOffset = {top:0, left: 0},\n\t\t// because it is its only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\n\t\t\t// we assume that getBoundingClientRect is available when computed position is fixed\n\t\t\toffset = elem.getBoundingClientRect();\n\t\t} else {\n\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset.top  += jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true );\n\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true );\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map( function() {\n\t\t\tvar offsetParent = this.offsetParent;\n\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) &&\n\t\t\t\tjQuery.css( offsetParent, \"position\" ) === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent || documentElement;\n\t\t} );\n\t}\n} );\n\n// Create scrollLeft and scrollTop methods\njQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? ( prop in win ) ? win[ prop ] :\n\t\t\t\t\twin.document.documentElement[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\ttop ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n} );\n\n// Support: Safari<7-8+, Chrome<37-44+\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// getComputedStyle returns percent when specified for top/left/bottom/right\n// rather than make the css module depend on the offset module, we just check for it here\njQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\tcomputed = curCSS( elem, prop );\n\n\t\t\t\t// if curCSS returns percentage, fallback to offset\n\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\tcomputed;\n\t\t\t}\n\t\t}\n\t);\n} );\n\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name },\n\tfunction( defaultExtra, funcName ) {\n\n\t\t// margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n\t\t\t\t\t// isn't a whole lot we can do. See pull request at this URL for discussion:\n\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n\t\t\t\t\treturn elem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\t// unfortunately, this causes bug #3838 in IE6/8 only,\n\t\t\t\t\t// but there is currently no good, small way to fix it.\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t} );\n} );\n\n\njQuery.fn.extend( {\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ?\n\t\t\tthis.off( selector, \"**\" ) :\n\t\t\tthis.off( types, selector || \"**\", fn );\n\t}\n} );\n\n// The number of elements contained in the matched element set\njQuery.fn.size = function() {\n\treturn this.length;\n};\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\n\n\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine( \"jquery\", [], function() {\n\t\treturn jQuery;\n\t} );\n}\n\n\n\nvar\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$;\n\njQuery.noConflict = function( deep ) {\n\tif ( window.$ === jQuery ) {\n\t\twindow.$ = _$;\n\t}\n\n\tif ( deep && window.jQuery === jQuery ) {\n\t\twindow.jQuery = _jQuery;\n\t}\n\n\treturn jQuery;\n};\n\n// Expose jQuery and $ identifiers, even in\n// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( !noGlobal ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\nreturn jQuery;\n}));\n"
  },
  {
    "path": "functional-samples/sample.bookmarks/third-party/jquery-ui-1.12.1.js",
    "content": "/*! jQuery UI - v1.12.1 - 2021-03-02\n* http://jqueryui.com\n* Includes: widget.js, position.js, data.js, disable-selection.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/draggable.js, widgets/droppable.js, widgets/resizable.js, widgets/selectable.js, widgets/sortable.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/selectmenu.js, widgets/slider.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js\n* Copyright jQuery Foundation and other contributors; Licensed MIT */\n\n(function( factory ) {\n\tif ( typeof define === \"function\" && define.amd ) {\n\n\t\t// AMD. Register as an anonymous module.\n\t\tdefine([ \"jquery\" ], factory );\n\t} else {\n\n\t\t// Browser globals\n\t\tfactory( jQuery );\n\t}\n}(function( $ ) {\n\n$.ui = $.ui || {};\n\nvar version = $.ui.version = \"1.12.1\";\n\n\n/*!\n * jQuery UI Widget 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Widget\n//>>group: Core\n//>>description: Provides a factory for creating stateful widgets with a common API.\n//>>docs: http://api.jqueryui.com/jQuery.widget/\n//>>demos: http://jqueryui.com/widget/\n\n\n\nvar widgetUuid = 0;\nvar widgetSlice = Array.prototype.slice;\n\n$.cleanData = ( function( orig ) {\n\treturn function( elems ) {\n\t\tvar events, elem, i;\n\t\tfor ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {\n\t\t\ttry {\n\n\t\t\t\t// Only trigger remove when necessary to save time\n\t\t\t\tevents = $._data( elem, \"events\" );\n\t\t\t\tif ( events && events.remove ) {\n\t\t\t\t\t$( elem ).triggerHandler( \"remove\" );\n\t\t\t\t}\n\n\t\t\t// Http://bugs.jquery.com/ticket/8235\n\t\t\t} catch ( e ) {}\n\t\t}\n\t\torig( elems );\n\t};\n} )( $.cleanData );\n\n$.widget = function( name, base, prototype ) {\n\tvar existingConstructor, constructor, basePrototype;\n\n\t// ProxiedPrototype allows the provided prototype to remain unmodified\n\t// so that it can be used as a mixin for multiple widgets (#8876)\n\tvar proxiedPrototype = {};\n\n\tvar namespace = name.split( \".\" )[ 0 ];\n\tname = name.split( \".\" )[ 1 ];\n\tvar fullName = namespace + \"-\" + name;\n\n\tif ( !prototype ) {\n\t\tprototype = base;\n\t\tbase = $.Widget;\n\t}\n\n\tif ( $.isArray( prototype ) ) {\n\t\tprototype = $.extend.apply( null, [ {} ].concat( prototype ) );\n\t}\n\n\t// Create selector for plugin\n\t$.expr[ \":\" ][ fullName.toLowerCase() ] = function( elem ) {\n\t\treturn !!$.data( elem, fullName );\n\t};\n\n\t$[ namespace ] = $[ namespace ] || {};\n\texistingConstructor = $[ namespace ][ name ];\n\tconstructor = $[ namespace ][ name ] = function( options, element ) {\n\n\t\t// Allow instantiation without \"new\" keyword\n\t\tif ( !this._createWidget ) {\n\t\t\treturn new constructor( options, element );\n\t\t}\n\n\t\t// Allow instantiation without initializing for simple inheritance\n\t\t// must use \"new\" keyword (the code above always passes args)\n\t\tif ( arguments.length ) {\n\t\t\tthis._createWidget( options, element );\n\t\t}\n\t};\n\n\t// Extend with the existing constructor to carry over any static properties\n\t$.extend( constructor, existingConstructor, {\n\t\tversion: prototype.version,\n\n\t\t// Copy the object used to create the prototype in case we need to\n\t\t// redefine the widget later\n\t\t_proto: $.extend( {}, prototype ),\n\n\t\t// Track widgets that inherit from this widget in case this widget is\n\t\t// redefined after a widget inherits from it\n\t\t_childConstructors: []\n\t} );\n\n\tbasePrototype = new base();\n\n\t// We need to make the options hash a property directly on the new instance\n\t// otherwise we'll modify the options hash on the prototype that we're\n\t// inheriting from\n\tbasePrototype.options = $.widget.extend( {}, basePrototype.options );\n\t$.each( prototype, function( prop, value ) {\n\t\tif ( !$.isFunction( value ) ) {\n\t\t\tproxiedPrototype[ prop ] = value;\n\t\t\treturn;\n\t\t}\n\t\tproxiedPrototype[ prop ] = ( function() {\n\t\t\tfunction _super() {\n\t\t\t\treturn base.prototype[ prop ].apply( this, arguments );\n\t\t\t}\n\n\t\t\tfunction _superApply( args ) {\n\t\t\t\treturn base.prototype[ prop ].apply( this, args );\n\t\t\t}\n\n\t\t\treturn function() {\n\t\t\t\tvar __super = this._super;\n\t\t\t\tvar __superApply = this._superApply;\n\t\t\t\tvar returnValue;\n\n\t\t\t\tthis._super = _super;\n\t\t\t\tthis._superApply = _superApply;\n\n\t\t\t\treturnValue = value.apply( this, arguments );\n\n\t\t\t\tthis._super = __super;\n\t\t\t\tthis._superApply = __superApply;\n\n\t\t\t\treturn returnValue;\n\t\t\t};\n\t\t} )();\n\t} );\n\tconstructor.prototype = $.widget.extend( basePrototype, {\n\n\t\t// TODO: remove support for widgetEventPrefix\n\t\t// always use the name + a colon as the prefix, e.g., draggable:start\n\t\t// don't prefix for widgets that aren't DOM-based\n\t\twidgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name\n\t}, proxiedPrototype, {\n\t\tconstructor: constructor,\n\t\tnamespace: namespace,\n\t\twidgetName: name,\n\t\twidgetFullName: fullName\n\t} );\n\n\t// If this widget is being redefined then we need to find all widgets that\n\t// are inheriting from it and redefine all of them so that they inherit from\n\t// the new version of this widget. We're essentially trying to replace one\n\t// level in the prototype chain.\n\tif ( existingConstructor ) {\n\t\t$.each( existingConstructor._childConstructors, function( i, child ) {\n\t\t\tvar childPrototype = child.prototype;\n\n\t\t\t// Redefine the child widget using the same prototype that was\n\t\t\t// originally used, but inherit from the new version of the base\n\t\t\t$.widget( childPrototype.namespace + \".\" + childPrototype.widgetName, constructor,\n\t\t\t\tchild._proto );\n\t\t} );\n\n\t\t// Remove the list of existing child constructors from the old constructor\n\t\t// so the old child constructors can be garbage collected\n\t\tdelete existingConstructor._childConstructors;\n\t} else {\n\t\tbase._childConstructors.push( constructor );\n\t}\n\n\t$.widget.bridge( name, constructor );\n\n\treturn constructor;\n};\n\n$.widget.extend = function( target ) {\n\tvar input = widgetSlice.call( arguments, 1 );\n\tvar inputIndex = 0;\n\tvar inputLength = input.length;\n\tvar key;\n\tvar value;\n\n\tfor ( ; inputIndex < inputLength; inputIndex++ ) {\n\t\tfor ( key in input[ inputIndex ] ) {\n\t\t\tvalue = input[ inputIndex ][ key ];\n\t\t\tif ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {\n\n\t\t\t\t// Clone objects\n\t\t\t\tif ( $.isPlainObject( value ) ) {\n\t\t\t\t\ttarget[ key ] = $.isPlainObject( target[ key ] ) ?\n\t\t\t\t\t\t$.widget.extend( {}, target[ key ], value ) :\n\n\t\t\t\t\t\t// Don't extend strings, arrays, etc. with objects\n\t\t\t\t\t\t$.widget.extend( {}, value );\n\n\t\t\t\t// Copy everything else by reference\n\t\t\t\t} else {\n\t\t\t\t\ttarget[ key ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn target;\n};\n\n$.widget.bridge = function( name, object ) {\n\tvar fullName = object.prototype.widgetFullName || name;\n\t$.fn[ name ] = function( options ) {\n\t\tvar isMethodCall = typeof options === \"string\";\n\t\tvar args = widgetSlice.call( arguments, 1 );\n\t\tvar returnValue = this;\n\n\t\tif ( isMethodCall ) {\n\n\t\t\t// If this is an empty collection, we need to have the instance method\n\t\t\t// return undefined instead of the jQuery instance\n\t\t\tif ( !this.length && options === \"instance\" ) {\n\t\t\t\treturnValue = undefined;\n\t\t\t} else {\n\t\t\t\tthis.each( function() {\n\t\t\t\t\tvar methodValue;\n\t\t\t\t\tvar instance = $.data( this, fullName );\n\n\t\t\t\t\tif ( options === \"instance\" ) {\n\t\t\t\t\t\treturnValue = instance;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !instance ) {\n\t\t\t\t\t\treturn $.error( \"cannot call methods on \" + name +\n\t\t\t\t\t\t\t\" prior to initialization; \" +\n\t\t\t\t\t\t\t\"attempted to call method '\" + options + \"'\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === \"_\" ) {\n\t\t\t\t\t\treturn $.error( \"no such method '\" + options + \"' for \" + name +\n\t\t\t\t\t\t\t\" widget instance\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tmethodValue = instance[ options ].apply( instance, args );\n\n\t\t\t\t\tif ( methodValue !== instance && methodValue !== undefined ) {\n\t\t\t\t\t\treturnValue = methodValue && methodValue.jquery ?\n\t\t\t\t\t\t\treturnValue.pushStack( methodValue.get() ) :\n\t\t\t\t\t\t\tmethodValue;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Allow multiple hashes to be passed on init\n\t\t\tif ( args.length ) {\n\t\t\t\toptions = $.widget.extend.apply( null, [ options ].concat( args ) );\n\t\t\t}\n\n\t\t\tthis.each( function() {\n\t\t\t\tvar instance = $.data( this, fullName );\n\t\t\t\tif ( instance ) {\n\t\t\t\t\tinstance.option( options || {} );\n\t\t\t\t\tif ( instance._init ) {\n\t\t\t\t\t\tinstance._init();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$.data( this, fullName, new object( options, this ) );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\treturn returnValue;\n\t};\n};\n\n$.Widget = function( /* options, element */ ) {};\n$.Widget._childConstructors = [];\n\n$.Widget.prototype = {\n\twidgetName: \"widget\",\n\twidgetEventPrefix: \"\",\n\tdefaultElement: \"<div>\",\n\n\toptions: {\n\t\tclasses: {},\n\t\tdisabled: false,\n\n\t\t// Callbacks\n\t\tcreate: null\n\t},\n\n\t_createWidget: function( options, element ) {\n\t\telement = $( element || this.defaultElement || this )[ 0 ];\n\t\tthis.element = $( element );\n\t\tthis.uuid = widgetUuid++;\n\t\tthis.eventNamespace = \".\" + this.widgetName + this.uuid;\n\n\t\tthis.bindings = $();\n\t\tthis.hoverable = $();\n\t\tthis.focusable = $();\n\t\tthis.classesElementLookup = {};\n\n\t\tif ( element !== this ) {\n\t\t\t$.data( element, this.widgetFullName, this );\n\t\t\tthis._on( true, this.element, {\n\t\t\t\tremove: function( event ) {\n\t\t\t\t\tif ( event.target === element ) {\n\t\t\t\t\t\tthis.destroy();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t\tthis.document = $( element.style ?\n\n\t\t\t\t// Element within the document\n\t\t\t\telement.ownerDocument :\n\n\t\t\t\t// Element is window or document\n\t\t\t\telement.document || element );\n\t\t\tthis.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );\n\t\t}\n\n\t\tthis.options = $.widget.extend( {},\n\t\t\tthis.options,\n\t\t\tthis._getCreateOptions(),\n\t\t\toptions );\n\n\t\tthis._create();\n\n\t\tif ( this.options.disabled ) {\n\t\t\tthis._setOptionDisabled( this.options.disabled );\n\t\t}\n\n\t\tthis._trigger( \"create\", null, this._getCreateEventData() );\n\t\tthis._init();\n\t},\n\n\t_getCreateOptions: function() {\n\t\treturn {};\n\t},\n\n\t_getCreateEventData: $.noop,\n\n\t_create: $.noop,\n\n\t_init: $.noop,\n\n\tdestroy: function() {\n\t\tvar that = this;\n\n\t\tthis._destroy();\n\t\t$.each( this.classesElementLookup, function( key, value ) {\n\t\t\tthat._removeClass( value, key );\n\t\t} );\n\n\t\t// We can probably remove the unbind calls in 2.0\n\t\t// all event bindings should go through this._on()\n\t\tthis.element\n\t\t\t.off( this.eventNamespace )\n\t\t\t.removeData( this.widgetFullName );\n\t\tthis.widget()\n\t\t\t.off( this.eventNamespace )\n\t\t\t.removeAttr( \"aria-disabled\" );\n\n\t\t// Clean up events and states\n\t\tthis.bindings.off( this.eventNamespace );\n\t},\n\n\t_destroy: $.noop,\n\n\twidget: function() {\n\t\treturn this.element;\n\t},\n\n\toption: function( key, value ) {\n\t\tvar options = key;\n\t\tvar parts;\n\t\tvar curOption;\n\t\tvar i;\n\n\t\tif ( arguments.length === 0 ) {\n\n\t\t\t// Don't return a reference to the internal hash\n\t\t\treturn $.widget.extend( {}, this.options );\n\t\t}\n\n\t\tif ( typeof key === \"string\" ) {\n\n\t\t\t// Handle nested keys, e.g., \"foo.bar\" => { foo: { bar: ___ } }\n\t\t\toptions = {};\n\t\t\tparts = key.split( \".\" );\n\t\t\tkey = parts.shift();\n\t\t\tif ( parts.length ) {\n\t\t\t\tcurOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );\n\t\t\t\tfor ( i = 0; i < parts.length - 1; i++ ) {\n\t\t\t\t\tcurOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};\n\t\t\t\t\tcurOption = curOption[ parts[ i ] ];\n\t\t\t\t}\n\t\t\t\tkey = parts.pop();\n\t\t\t\tif ( arguments.length === 1 ) {\n\t\t\t\t\treturn curOption[ key ] === undefined ? null : curOption[ key ];\n\t\t\t\t}\n\t\t\t\tcurOption[ key ] = value;\n\t\t\t} else {\n\t\t\t\tif ( arguments.length === 1 ) {\n\t\t\t\t\treturn this.options[ key ] === undefined ? null : this.options[ key ];\n\t\t\t\t}\n\t\t\t\toptions[ key ] = value;\n\t\t\t}\n\t\t}\n\n\t\tthis._setOptions( options );\n\n\t\treturn this;\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar key;\n\n\t\tfor ( key in options ) {\n\t\t\tthis._setOption( key, options[ key ] );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"classes\" ) {\n\t\t\tthis._setOptionClasses( value );\n\t\t}\n\n\t\tthis.options[ key ] = value;\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis._setOptionDisabled( value );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_setOptionClasses: function( value ) {\n\t\tvar classKey, elements, currentElements;\n\n\t\tfor ( classKey in value ) {\n\t\t\tcurrentElements = this.classesElementLookup[ classKey ];\n\t\t\tif ( value[ classKey ] === this.options.classes[ classKey ] ||\n\t\t\t\t\t!currentElements ||\n\t\t\t\t\t!currentElements.length ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// We are doing this to create a new jQuery object because the _removeClass() call\n\t\t\t// on the next line is going to destroy the reference to the current elements being\n\t\t\t// tracked. We need to save a copy of this collection so that we can add the new classes\n\t\t\t// below.\n\t\t\telements = $( currentElements.get() );\n\t\t\tthis._removeClass( currentElements, classKey );\n\n\t\t\t// We don't use _addClass() here, because that uses this.options.classes\n\t\t\t// for generating the string of classes. We want to use the value passed in from\n\t\t\t// _setOption(), this is the new value of the classes option which was passed to\n\t\t\t// _setOption(). We pass this value directly to _classes().\n\t\t\telements.addClass( this._classes( {\n\t\t\t\telement: elements,\n\t\t\t\tkeys: classKey,\n\t\t\t\tclasses: value,\n\t\t\t\tadd: true\n\t\t\t} ) );\n\t\t}\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._toggleClass( this.widget(), this.widgetFullName + \"-disabled\", null, !!value );\n\n\t\t// If the widget is becoming disabled, then nothing is interactive\n\t\tif ( value ) {\n\t\t\tthis._removeClass( this.hoverable, null, \"ui-state-hover\" );\n\t\t\tthis._removeClass( this.focusable, null, \"ui-state-focus\" );\n\t\t}\n\t},\n\n\tenable: function() {\n\t\treturn this._setOptions( { disabled: false } );\n\t},\n\n\tdisable: function() {\n\t\treturn this._setOptions( { disabled: true } );\n\t},\n\n\t_classes: function( options ) {\n\t\tvar full = [];\n\t\tvar that = this;\n\n\t\toptions = $.extend( {\n\t\t\telement: this.element,\n\t\t\tclasses: this.options.classes || {}\n\t\t}, options );\n\n\t\tfunction processClassString( classes, checkOption ) {\n\t\t\tvar current, i;\n\t\t\tfor ( i = 0; i < classes.length; i++ ) {\n\t\t\t\tcurrent = that.classesElementLookup[ classes[ i ] ] || $();\n\t\t\t\tif ( options.add ) {\n\t\t\t\t\tcurrent = $( $.unique( current.get().concat( options.element.get() ) ) );\n\t\t\t\t} else {\n\t\t\t\t\tcurrent = $( current.not( options.element ).get() );\n\t\t\t\t}\n\t\t\t\tthat.classesElementLookup[ classes[ i ] ] = current;\n\t\t\t\tfull.push( classes[ i ] );\n\t\t\t\tif ( checkOption && options.classes[ classes[ i ] ] ) {\n\t\t\t\t\tfull.push( options.classes[ classes[ i ] ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._on( options.element, {\n\t\t\t\"remove\": \"_untrackClassesElement\"\n\t\t} );\n\n\t\tif ( options.keys ) {\n\t\t\tprocessClassString( options.keys.match( /\\S+/g ) || [], true );\n\t\t}\n\t\tif ( options.extra ) {\n\t\t\tprocessClassString( options.extra.match( /\\S+/g ) || [] );\n\t\t}\n\n\t\treturn full.join( \" \" );\n\t},\n\n\t_untrackClassesElement: function( event ) {\n\t\tvar that = this;\n\t\t$.each( that.classesElementLookup, function( key, value ) {\n\t\t\tif ( $.inArray( event.target, value ) !== -1 ) {\n\t\t\t\tthat.classesElementLookup[ key ] = $( value.not( event.target ).get() );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_removeClass: function( element, keys, extra ) {\n\t\treturn this._toggleClass( element, keys, extra, false );\n\t},\n\n\t_addClass: function( element, keys, extra ) {\n\t\treturn this._toggleClass( element, keys, extra, true );\n\t},\n\n\t_toggleClass: function( element, keys, extra, add ) {\n\t\tadd = ( typeof add === \"boolean\" ) ? add : extra;\n\t\tvar shift = ( typeof element === \"string\" || element === null ),\n\t\t\toptions = {\n\t\t\t\textra: shift ? keys : extra,\n\t\t\t\tkeys: shift ? element : keys,\n\t\t\t\telement: shift ? this.element : element,\n\t\t\t\tadd: add\n\t\t\t};\n\t\toptions.element.toggleClass( this._classes( options ), add );\n\t\treturn this;\n\t},\n\n\t_on: function( suppressDisabledCheck, element, handlers ) {\n\t\tvar delegateElement;\n\t\tvar instance = this;\n\n\t\t// No suppressDisabledCheck flag, shuffle arguments\n\t\tif ( typeof suppressDisabledCheck !== \"boolean\" ) {\n\t\t\thandlers = element;\n\t\t\telement = suppressDisabledCheck;\n\t\t\tsuppressDisabledCheck = false;\n\t\t}\n\n\t\t// No element argument, shuffle and use this.element\n\t\tif ( !handlers ) {\n\t\t\thandlers = element;\n\t\t\telement = this.element;\n\t\t\tdelegateElement = this.widget();\n\t\t} else {\n\t\t\telement = delegateElement = $( element );\n\t\t\tthis.bindings = this.bindings.add( element );\n\t\t}\n\n\t\t$.each( handlers, function( event, handler ) {\n\t\t\tfunction handlerProxy() {\n\n\t\t\t\t// Allow widgets to customize the disabled handling\n\t\t\t\t// - disabled as an array instead of boolean\n\t\t\t\t// - disabled class as method for disabling individual parts\n\t\t\t\tif ( !suppressDisabledCheck &&\n\t\t\t\t\t\t( instance.options.disabled === true ||\n\t\t\t\t\t\t$( this ).hasClass( \"ui-state-disabled\" ) ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t\t.apply( instance, arguments );\n\t\t\t}\n\n\t\t\t// Copy the guid so direct unbinding works\n\t\t\tif ( typeof handler !== \"string\" ) {\n\t\t\t\thandlerProxy.guid = handler.guid =\n\t\t\t\t\thandler.guid || handlerProxy.guid || $.guid++;\n\t\t\t}\n\n\t\t\tvar match = event.match( /^([\\w:-]*)\\s*(.*)$/ );\n\t\t\tvar eventName = match[ 1 ] + instance.eventNamespace;\n\t\t\tvar selector = match[ 2 ];\n\n\t\t\tif ( selector ) {\n\t\t\t\tdelegateElement.on( eventName, selector, handlerProxy );\n\t\t\t} else {\n\t\t\t\telement.on( eventName, handlerProxy );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_off: function( element, eventName ) {\n\t\teventName = ( eventName || \"\" ).split( \" \" ).join( this.eventNamespace + \" \" ) +\n\t\t\tthis.eventNamespace;\n\t\telement.off( eventName ).off( eventName );\n\n\t\t// Clear the stack to avoid memory leaks (#10056)\n\t\tthis.bindings = $( this.bindings.not( element ).get() );\n\t\tthis.focusable = $( this.focusable.not( element ).get() );\n\t\tthis.hoverable = $( this.hoverable.not( element ).get() );\n\t},\n\n\t_delay: function( handler, delay ) {\n\t\tfunction handlerProxy() {\n\t\t\treturn ( typeof handler === \"string\" ? instance[ handler ] : handler )\n\t\t\t\t.apply( instance, arguments );\n\t\t}\n\t\tvar instance = this;\n\t\treturn setTimeout( handlerProxy, delay || 0 );\n\t},\n\n\t_hoverable: function( element ) {\n\t\tthis.hoverable = this.hoverable.add( element );\n\t\tthis._on( element, {\n\t\t\tmouseenter: function( event ) {\n\t\t\t\tthis._addClass( $( event.currentTarget ), null, \"ui-state-hover\" );\n\t\t\t},\n\t\t\tmouseleave: function( event ) {\n\t\t\t\tthis._removeClass( $( event.currentTarget ), null, \"ui-state-hover\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_focusable: function( element ) {\n\t\tthis.focusable = this.focusable.add( element );\n\t\tthis._on( element, {\n\t\t\tfocusin: function( event ) {\n\t\t\t\tthis._addClass( $( event.currentTarget ), null, \"ui-state-focus\" );\n\t\t\t},\n\t\t\tfocusout: function( event ) {\n\t\t\t\tthis._removeClass( $( event.currentTarget ), null, \"ui-state-focus\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_trigger: function( type, event, data ) {\n\t\tvar prop, orig;\n\t\tvar callback = this.options[ type ];\n\n\t\tdata = data || {};\n\t\tevent = $.Event( event );\n\t\tevent.type = ( type === this.widgetEventPrefix ?\n\t\t\ttype :\n\t\t\tthis.widgetEventPrefix + type ).toLowerCase();\n\n\t\t// The original event may come from any element\n\t\t// so we need to reset the target on the new event\n\t\tevent.target = this.element[ 0 ];\n\n\t\t// Copy original event properties over to the new event\n\t\torig = event.originalEvent;\n\t\tif ( orig ) {\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tif ( !( prop in event ) ) {\n\t\t\t\t\tevent[ prop ] = orig[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.element.trigger( event, data );\n\t\treturn !( $.isFunction( callback ) &&\n\t\t\tcallback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||\n\t\t\tevent.isDefaultPrevented() );\n\t}\n};\n\n$.each( { show: \"fadeIn\", hide: \"fadeOut\" }, function( method, defaultEffect ) {\n\t$.Widget.prototype[ \"_\" + method ] = function( element, options, callback ) {\n\t\tif ( typeof options === \"string\" ) {\n\t\t\toptions = { effect: options };\n\t\t}\n\n\t\tvar hasOptions;\n\t\tvar effectName = !options ?\n\t\t\tmethod :\n\t\t\toptions === true || typeof options === \"number\" ?\n\t\t\t\tdefaultEffect :\n\t\t\t\toptions.effect || defaultEffect;\n\n\t\toptions = options || {};\n\t\tif ( typeof options === \"number\" ) {\n\t\t\toptions = { duration: options };\n\t\t}\n\n\t\thasOptions = !$.isEmptyObject( options );\n\t\toptions.complete = callback;\n\n\t\tif ( options.delay ) {\n\t\t\telement.delay( options.delay );\n\t\t}\n\n\t\tif ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {\n\t\t\telement[ method ]( options );\n\t\t} else if ( effectName !== method && element[ effectName ] ) {\n\t\t\telement[ effectName ]( options.duration, options.easing, callback );\n\t\t} else {\n\t\t\telement.queue( function( next ) {\n\t\t\t\t$( this )[ method ]();\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback.call( element[ 0 ] );\n\t\t\t\t}\n\t\t\t\tnext();\n\t\t\t} );\n\t\t}\n\t};\n} );\n\nvar widget = $.widget;\n\n\n/*!\n * jQuery UI Position 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * http://api.jqueryui.com/position/\n */\n\n//>>label: Position\n//>>group: Core\n//>>description: Positions elements relative to other elements.\n//>>docs: http://api.jqueryui.com/position/\n//>>demos: http://jqueryui.com/position/\n\n\n( function() {\nvar cachedScrollbarWidth,\n\tmax = Math.max,\n\tabs = Math.abs,\n\trhorizontal = /left|center|right/,\n\trvertical = /top|center|bottom/,\n\troffset = /[\\+\\-]\\d+(\\.[\\d]+)?%?/,\n\trposition = /^\\w+/,\n\trpercent = /%$/,\n\t_position = $.fn.position;\n\nfunction getOffsets( offsets, width, height ) {\n\treturn [\n\t\tparseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),\n\t\tparseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )\n\t];\n}\n\nfunction parseCss( element, property ) {\n\treturn parseInt( $.css( element, property ), 10 ) || 0;\n}\n\nfunction getDimensions( elem ) {\n\tvar raw = elem[ 0 ];\n\tif ( raw.nodeType === 9 ) {\n\t\treturn {\n\t\t\twidth: elem.width(),\n\t\t\theight: elem.height(),\n\t\t\toffset: { top: 0, left: 0 }\n\t\t};\n\t}\n\tif ( $.isWindow( raw ) ) {\n\t\treturn {\n\t\t\twidth: elem.width(),\n\t\t\theight: elem.height(),\n\t\t\toffset: { top: elem.scrollTop(), left: elem.scrollLeft() }\n\t\t};\n\t}\n\tif ( raw.preventDefault ) {\n\t\treturn {\n\t\t\twidth: 0,\n\t\t\theight: 0,\n\t\t\toffset: { top: raw.pageY, left: raw.pageX }\n\t\t};\n\t}\n\treturn {\n\t\twidth: elem.outerWidth(),\n\t\theight: elem.outerHeight(),\n\t\toffset: elem.offset()\n\t};\n}\n\n$.position = {\n\tscrollbarWidth: function() {\n\t\tif ( cachedScrollbarWidth !== undefined ) {\n\t\t\treturn cachedScrollbarWidth;\n\t\t}\n\t\tvar w1, w2,\n\t\t\tdiv = $( \"<div \" +\n\t\t\t\t\"style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>\" +\n\t\t\t\t\"<div style='height:100px;width:auto;'></div></div>\" ),\n\t\t\tinnerDiv = div.children()[ 0 ];\n\n\t\t$( \"body\" ).append( div );\n\t\tw1 = innerDiv.offsetWidth;\n\t\tdiv.css( \"overflow\", \"scroll\" );\n\n\t\tw2 = innerDiv.offsetWidth;\n\n\t\tif ( w1 === w2 ) {\n\t\t\tw2 = div[ 0 ].clientWidth;\n\t\t}\n\n\t\tdiv.remove();\n\n\t\treturn ( cachedScrollbarWidth = w1 - w2 );\n\t},\n\tgetScrollInfo: function( within ) {\n\t\tvar overflowX = within.isWindow || within.isDocument ? \"\" :\n\t\t\t\twithin.element.css( \"overflow-x\" ),\n\t\t\toverflowY = within.isWindow || within.isDocument ? \"\" :\n\t\t\t\twithin.element.css( \"overflow-y\" ),\n\t\t\thasOverflowX = overflowX === \"scroll\" ||\n\t\t\t\t( overflowX === \"auto\" && within.width < within.element[ 0 ].scrollWidth ),\n\t\t\thasOverflowY = overflowY === \"scroll\" ||\n\t\t\t\t( overflowY === \"auto\" && within.height < within.element[ 0 ].scrollHeight );\n\t\treturn {\n\t\t\twidth: hasOverflowY ? $.position.scrollbarWidth() : 0,\n\t\t\theight: hasOverflowX ? $.position.scrollbarWidth() : 0\n\t\t};\n\t},\n\tgetWithinInfo: function( element ) {\n\t\tvar withinElement = $( element || window ),\n\t\t\tisWindow = $.isWindow( withinElement[ 0 ] ),\n\t\t\tisDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,\n\t\t\thasOffset = !isWindow && !isDocument;\n\t\treturn {\n\t\t\telement: withinElement,\n\t\t\tisWindow: isWindow,\n\t\t\tisDocument: isDocument,\n\t\t\toffset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },\n\t\t\tscrollLeft: withinElement.scrollLeft(),\n\t\t\tscrollTop: withinElement.scrollTop(),\n\t\t\twidth: withinElement.outerWidth(),\n\t\t\theight: withinElement.outerHeight()\n\t\t};\n\t}\n};\n\n$.fn.position = function( options ) {\n\tif ( !options || !options.of ) {\n\t\treturn _position.apply( this, arguments );\n\t}\n\n\t// Make a copy, we don't want to modify arguments\n\toptions = $.extend( {}, options );\n\n\tvar atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,\n\t\ttarget = $( options.of ),\n\t\twithin = $.position.getWithinInfo( options.within ),\n\t\tscrollInfo = $.position.getScrollInfo( within ),\n\t\tcollision = ( options.collision || \"flip\" ).split( \" \" ),\n\t\toffsets = {};\n\n\tdimensions = getDimensions( target );\n\tif ( target[ 0 ].preventDefault ) {\n\n\t\t// Force left top to allow flipping\n\t\toptions.at = \"left top\";\n\t}\n\ttargetWidth = dimensions.width;\n\ttargetHeight = dimensions.height;\n\ttargetOffset = dimensions.offset;\n\n\t// Clone to reuse original targetOffset later\n\tbasePosition = $.extend( {}, targetOffset );\n\n\t// Force my and at to have valid horizontal and vertical positions\n\t// if a value is missing or invalid, it will be converted to center\n\t$.each( [ \"my\", \"at\" ], function() {\n\t\tvar pos = ( options[ this ] || \"\" ).split( \" \" ),\n\t\t\thorizontalOffset,\n\t\t\tverticalOffset;\n\n\t\tif ( pos.length === 1 ) {\n\t\t\tpos = rhorizontal.test( pos[ 0 ] ) ?\n\t\t\t\tpos.concat( [ \"center\" ] ) :\n\t\t\t\trvertical.test( pos[ 0 ] ) ?\n\t\t\t\t\t[ \"center\" ].concat( pos ) :\n\t\t\t\t\t[ \"center\", \"center\" ];\n\t\t}\n\t\tpos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : \"center\";\n\t\tpos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : \"center\";\n\n\t\t// Calculate offsets\n\t\thorizontalOffset = roffset.exec( pos[ 0 ] );\n\t\tverticalOffset = roffset.exec( pos[ 1 ] );\n\t\toffsets[ this ] = [\n\t\t\thorizontalOffset ? horizontalOffset[ 0 ] : 0,\n\t\t\tverticalOffset ? verticalOffset[ 0 ] : 0\n\t\t];\n\n\t\t// Reduce to just the positions without the offsets\n\t\toptions[ this ] = [\n\t\t\trposition.exec( pos[ 0 ] )[ 0 ],\n\t\t\trposition.exec( pos[ 1 ] )[ 0 ]\n\t\t];\n\t} );\n\n\t// Normalize collision option\n\tif ( collision.length === 1 ) {\n\t\tcollision[ 1 ] = collision[ 0 ];\n\t}\n\n\tif ( options.at[ 0 ] === \"right\" ) {\n\t\tbasePosition.left += targetWidth;\n\t} else if ( options.at[ 0 ] === \"center\" ) {\n\t\tbasePosition.left += targetWidth / 2;\n\t}\n\n\tif ( options.at[ 1 ] === \"bottom\" ) {\n\t\tbasePosition.top += targetHeight;\n\t} else if ( options.at[ 1 ] === \"center\" ) {\n\t\tbasePosition.top += targetHeight / 2;\n\t}\n\n\tatOffset = getOffsets( offsets.at, targetWidth, targetHeight );\n\tbasePosition.left += atOffset[ 0 ];\n\tbasePosition.top += atOffset[ 1 ];\n\n\treturn this.each( function() {\n\t\tvar collisionPosition, using,\n\t\t\telem = $( this ),\n\t\t\telemWidth = elem.outerWidth(),\n\t\t\telemHeight = elem.outerHeight(),\n\t\t\tmarginLeft = parseCss( this, \"marginLeft\" ),\n\t\t\tmarginTop = parseCss( this, \"marginTop\" ),\n\t\t\tcollisionWidth = elemWidth + marginLeft + parseCss( this, \"marginRight\" ) +\n\t\t\t\tscrollInfo.width,\n\t\t\tcollisionHeight = elemHeight + marginTop + parseCss( this, \"marginBottom\" ) +\n\t\t\t\tscrollInfo.height,\n\t\t\tposition = $.extend( {}, basePosition ),\n\t\t\tmyOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );\n\n\t\tif ( options.my[ 0 ] === \"right\" ) {\n\t\t\tposition.left -= elemWidth;\n\t\t} else if ( options.my[ 0 ] === \"center\" ) {\n\t\t\tposition.left -= elemWidth / 2;\n\t\t}\n\n\t\tif ( options.my[ 1 ] === \"bottom\" ) {\n\t\t\tposition.top -= elemHeight;\n\t\t} else if ( options.my[ 1 ] === \"center\" ) {\n\t\t\tposition.top -= elemHeight / 2;\n\t\t}\n\n\t\tposition.left += myOffset[ 0 ];\n\t\tposition.top += myOffset[ 1 ];\n\n\t\tcollisionPosition = {\n\t\t\tmarginLeft: marginLeft,\n\t\t\tmarginTop: marginTop\n\t\t};\n\n\t\t$.each( [ \"left\", \"top\" ], function( i, dir ) {\n\t\t\tif ( $.ui.position[ collision[ i ] ] ) {\n\t\t\t\t$.ui.position[ collision[ i ] ][ dir ]( position, {\n\t\t\t\t\ttargetWidth: targetWidth,\n\t\t\t\t\ttargetHeight: targetHeight,\n\t\t\t\t\telemWidth: elemWidth,\n\t\t\t\t\telemHeight: elemHeight,\n\t\t\t\t\tcollisionPosition: collisionPosition,\n\t\t\t\t\tcollisionWidth: collisionWidth,\n\t\t\t\t\tcollisionHeight: collisionHeight,\n\t\t\t\t\toffset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],\n\t\t\t\t\tmy: options.my,\n\t\t\t\t\tat: options.at,\n\t\t\t\t\twithin: within,\n\t\t\t\t\telem: elem\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t\tif ( options.using ) {\n\n\t\t\t// Adds feedback as second argument to using callback, if present\n\t\t\tusing = function( props ) {\n\t\t\t\tvar left = targetOffset.left - position.left,\n\t\t\t\t\tright = left + targetWidth - elemWidth,\n\t\t\t\t\ttop = targetOffset.top - position.top,\n\t\t\t\t\tbottom = top + targetHeight - elemHeight,\n\t\t\t\t\tfeedback = {\n\t\t\t\t\t\ttarget: {\n\t\t\t\t\t\t\telement: target,\n\t\t\t\t\t\t\tleft: targetOffset.left,\n\t\t\t\t\t\t\ttop: targetOffset.top,\n\t\t\t\t\t\t\twidth: targetWidth,\n\t\t\t\t\t\t\theight: targetHeight\n\t\t\t\t\t\t},\n\t\t\t\t\t\telement: {\n\t\t\t\t\t\t\telement: elem,\n\t\t\t\t\t\t\tleft: position.left,\n\t\t\t\t\t\t\ttop: position.top,\n\t\t\t\t\t\t\twidth: elemWidth,\n\t\t\t\t\t\t\theight: elemHeight\n\t\t\t\t\t\t},\n\t\t\t\t\t\thorizontal: right < 0 ? \"left\" : left > 0 ? \"right\" : \"center\",\n\t\t\t\t\t\tvertical: bottom < 0 ? \"top\" : top > 0 ? \"bottom\" : \"middle\"\n\t\t\t\t\t};\n\t\t\t\tif ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {\n\t\t\t\t\tfeedback.horizontal = \"center\";\n\t\t\t\t}\n\t\t\t\tif ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {\n\t\t\t\t\tfeedback.vertical = \"middle\";\n\t\t\t\t}\n\t\t\t\tif ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {\n\t\t\t\t\tfeedback.important = \"horizontal\";\n\t\t\t\t} else {\n\t\t\t\t\tfeedback.important = \"vertical\";\n\t\t\t\t}\n\t\t\t\toptions.using.call( this, props, feedback );\n\t\t\t};\n\t\t}\n\n\t\telem.offset( $.extend( position, { using: using } ) );\n\t} );\n};\n\n$.ui.position = {\n\tfit: {\n\t\tleft: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.isWindow ? within.scrollLeft : within.offset.left,\n\t\t\t\touterWidth = within.width,\n\t\t\t\tcollisionPosLeft = position.left - data.collisionPosition.marginLeft,\n\t\t\t\toverLeft = withinOffset - collisionPosLeft,\n\t\t\t\toverRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,\n\t\t\t\tnewOverRight;\n\n\t\t\t// Element is wider than within\n\t\t\tif ( data.collisionWidth > outerWidth ) {\n\n\t\t\t\t// Element is initially over the left side of within\n\t\t\t\tif ( overLeft > 0 && overRight <= 0 ) {\n\t\t\t\t\tnewOverRight = position.left + overLeft + data.collisionWidth - outerWidth -\n\t\t\t\t\t\twithinOffset;\n\t\t\t\t\tposition.left += overLeft - newOverRight;\n\n\t\t\t\t// Element is initially over right side of within\n\t\t\t\t} else if ( overRight > 0 && overLeft <= 0 ) {\n\t\t\t\t\tposition.left = withinOffset;\n\n\t\t\t\t// Element is initially over both left and right sides of within\n\t\t\t\t} else {\n\t\t\t\t\tif ( overLeft > overRight ) {\n\t\t\t\t\t\tposition.left = withinOffset + outerWidth - data.collisionWidth;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tposition.left = withinOffset;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Too far left -> align with left edge\n\t\t\t} else if ( overLeft > 0 ) {\n\t\t\t\tposition.left += overLeft;\n\n\t\t\t// Too far right -> align with right edge\n\t\t\t} else if ( overRight > 0 ) {\n\t\t\t\tposition.left -= overRight;\n\n\t\t\t// Adjust based on position and margin\n\t\t\t} else {\n\t\t\t\tposition.left = max( position.left - collisionPosLeft, position.left );\n\t\t\t}\n\t\t},\n\t\ttop: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.isWindow ? within.scrollTop : within.offset.top,\n\t\t\t\touterHeight = data.within.height,\n\t\t\t\tcollisionPosTop = position.top - data.collisionPosition.marginTop,\n\t\t\t\toverTop = withinOffset - collisionPosTop,\n\t\t\t\toverBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,\n\t\t\t\tnewOverBottom;\n\n\t\t\t// Element is taller than within\n\t\t\tif ( data.collisionHeight > outerHeight ) {\n\n\t\t\t\t// Element is initially over the top of within\n\t\t\t\tif ( overTop > 0 && overBottom <= 0 ) {\n\t\t\t\t\tnewOverBottom = position.top + overTop + data.collisionHeight - outerHeight -\n\t\t\t\t\t\twithinOffset;\n\t\t\t\t\tposition.top += overTop - newOverBottom;\n\n\t\t\t\t// Element is initially over bottom of within\n\t\t\t\t} else if ( overBottom > 0 && overTop <= 0 ) {\n\t\t\t\t\tposition.top = withinOffset;\n\n\t\t\t\t// Element is initially over both top and bottom of within\n\t\t\t\t} else {\n\t\t\t\t\tif ( overTop > overBottom ) {\n\t\t\t\t\t\tposition.top = withinOffset + outerHeight - data.collisionHeight;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tposition.top = withinOffset;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Too far up -> align with top\n\t\t\t} else if ( overTop > 0 ) {\n\t\t\t\tposition.top += overTop;\n\n\t\t\t// Too far down -> align with bottom edge\n\t\t\t} else if ( overBottom > 0 ) {\n\t\t\t\tposition.top -= overBottom;\n\n\t\t\t// Adjust based on position and margin\n\t\t\t} else {\n\t\t\t\tposition.top = max( position.top - collisionPosTop, position.top );\n\t\t\t}\n\t\t}\n\t},\n\tflip: {\n\t\tleft: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.offset.left + within.scrollLeft,\n\t\t\t\touterWidth = within.width,\n\t\t\t\toffsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,\n\t\t\t\tcollisionPosLeft = position.left - data.collisionPosition.marginLeft,\n\t\t\t\toverLeft = collisionPosLeft - offsetLeft,\n\t\t\t\toverRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,\n\t\t\t\tmyOffset = data.my[ 0 ] === \"left\" ?\n\t\t\t\t\t-data.elemWidth :\n\t\t\t\t\tdata.my[ 0 ] === \"right\" ?\n\t\t\t\t\t\tdata.elemWidth :\n\t\t\t\t\t\t0,\n\t\t\t\tatOffset = data.at[ 0 ] === \"left\" ?\n\t\t\t\t\tdata.targetWidth :\n\t\t\t\t\tdata.at[ 0 ] === \"right\" ?\n\t\t\t\t\t\t-data.targetWidth :\n\t\t\t\t\t\t0,\n\t\t\t\toffset = -2 * data.offset[ 0 ],\n\t\t\t\tnewOverRight,\n\t\t\t\tnewOverLeft;\n\n\t\t\tif ( overLeft < 0 ) {\n\t\t\t\tnewOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -\n\t\t\t\t\touterWidth - withinOffset;\n\t\t\t\tif ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {\n\t\t\t\t\tposition.left += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t} else if ( overRight > 0 ) {\n\t\t\t\tnewOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +\n\t\t\t\t\tatOffset + offset - offsetLeft;\n\t\t\t\tif ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {\n\t\t\t\t\tposition.left += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\ttop: function( position, data ) {\n\t\t\tvar within = data.within,\n\t\t\t\twithinOffset = within.offset.top + within.scrollTop,\n\t\t\t\touterHeight = within.height,\n\t\t\t\toffsetTop = within.isWindow ? within.scrollTop : within.offset.top,\n\t\t\t\tcollisionPosTop = position.top - data.collisionPosition.marginTop,\n\t\t\t\toverTop = collisionPosTop - offsetTop,\n\t\t\t\toverBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,\n\t\t\t\ttop = data.my[ 1 ] === \"top\",\n\t\t\t\tmyOffset = top ?\n\t\t\t\t\t-data.elemHeight :\n\t\t\t\t\tdata.my[ 1 ] === \"bottom\" ?\n\t\t\t\t\t\tdata.elemHeight :\n\t\t\t\t\t\t0,\n\t\t\t\tatOffset = data.at[ 1 ] === \"top\" ?\n\t\t\t\t\tdata.targetHeight :\n\t\t\t\t\tdata.at[ 1 ] === \"bottom\" ?\n\t\t\t\t\t\t-data.targetHeight :\n\t\t\t\t\t\t0,\n\t\t\t\toffset = -2 * data.offset[ 1 ],\n\t\t\t\tnewOverTop,\n\t\t\t\tnewOverBottom;\n\t\t\tif ( overTop < 0 ) {\n\t\t\t\tnewOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -\n\t\t\t\t\touterHeight - withinOffset;\n\t\t\t\tif ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {\n\t\t\t\t\tposition.top += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t} else if ( overBottom > 0 ) {\n\t\t\t\tnewOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +\n\t\t\t\t\toffset - offsetTop;\n\t\t\t\tif ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {\n\t\t\t\t\tposition.top += myOffset + atOffset + offset;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tflipfit: {\n\t\tleft: function() {\n\t\t\t$.ui.position.flip.left.apply( this, arguments );\n\t\t\t$.ui.position.fit.left.apply( this, arguments );\n\t\t},\n\t\ttop: function() {\n\t\t\t$.ui.position.flip.top.apply( this, arguments );\n\t\t\t$.ui.position.fit.top.apply( this, arguments );\n\t\t}\n\t}\n};\n\n} )();\n\nvar position = $.ui.position;\n\n\n/*!\n * jQuery UI :data 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: :data Selector\n//>>group: Core\n//>>description: Selects elements which have data stored under the specified key.\n//>>docs: http://api.jqueryui.com/data-selector/\n\n\nvar data = $.extend( $.expr[ \":\" ], {\n\tdata: $.expr.createPseudo ?\n\t\t$.expr.createPseudo( function( dataName ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn !!$.data( elem, dataName );\n\t\t\t};\n\t\t} ) :\n\n\t\t// Support: jQuery <1.8\n\t\tfunction( elem, i, match ) {\n\t\t\treturn !!$.data( elem, match[ 3 ] );\n\t\t}\n} );\n\n/*!\n * jQuery UI Disable Selection 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: disableSelection\n//>>group: Core\n//>>description: Disable selection of text content within the set of matched elements.\n//>>docs: http://api.jqueryui.com/disableSelection/\n\n// This file is deprecated\n\n\nvar disableSelection = $.fn.extend( {\n\tdisableSelection: ( function() {\n\t\tvar eventType = \"onselectstart\" in document.createElement( \"div\" ) ?\n\t\t\t\"selectstart\" :\n\t\t\t\"mousedown\";\n\n\t\treturn function() {\n\t\t\treturn this.on( eventType + \".ui-disableSelection\", function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t} );\n\t\t};\n\t} )(),\n\n\tenableSelection: function() {\n\t\treturn this.off( \".ui-disableSelection\" );\n\t}\n} );\n\n\n/*!\n * jQuery UI Focusable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: :focusable Selector\n//>>group: Core\n//>>description: Selects elements which can be focused.\n//>>docs: http://api.jqueryui.com/focusable-selector/\n\n\n\n// Selectors\n$.ui.focusable = function( element, hasTabindex ) {\n\tvar map, mapName, img, focusableIfVisible, fieldset,\n\t\tnodeName = element.nodeName.toLowerCase();\n\n\tif ( \"area\" === nodeName ) {\n\t\tmap = element.parentNode;\n\t\tmapName = map.name;\n\t\tif ( !element.href || !mapName || map.nodeName.toLowerCase() !== \"map\" ) {\n\t\t\treturn false;\n\t\t}\n\t\timg = $( \"img[usemap='#\" + mapName + \"']\" );\n\t\treturn img.length > 0 && img.is( \":visible\" );\n\t}\n\n\tif ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {\n\t\tfocusableIfVisible = !element.disabled;\n\n\t\tif ( focusableIfVisible ) {\n\n\t\t\t// Form controls within a disabled fieldset are disabled.\n\t\t\t// However, controls within the fieldset's legend do not get disabled.\n\t\t\t// Since controls generally aren't placed inside legends, we skip\n\t\t\t// this portion of the check.\n\t\t\tfieldset = $( element ).closest( \"fieldset\" )[ 0 ];\n\t\t\tif ( fieldset ) {\n\t\t\t\tfocusableIfVisible = !fieldset.disabled;\n\t\t\t}\n\t\t}\n\t} else if ( \"a\" === nodeName ) {\n\t\tfocusableIfVisible = element.href || hasTabindex;\n\t} else {\n\t\tfocusableIfVisible = hasTabindex;\n\t}\n\n\treturn focusableIfVisible && $( element ).is( \":visible\" ) && visible( $( element ) );\n};\n\n// Support: IE 8 only\n// IE 8 doesn't resolve inherit to visible/hidden for computed values\nfunction visible( element ) {\n\tvar visibility = element.css( \"visibility\" );\n\twhile ( visibility === \"inherit\" ) {\n\t\telement = element.parent();\n\t\tvisibility = element.css( \"visibility\" );\n\t}\n\treturn visibility !== \"hidden\";\n}\n\n$.extend( $.expr[ \":\" ], {\n\tfocusable: function( element ) {\n\t\treturn $.ui.focusable( element, $.attr( element, \"tabindex\" ) != null );\n\t}\n} );\n\nvar focusable = $.ui.focusable;\n\n\n\n\n// Support: IE8 Only\n// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop\n// with a string, so we need to find the proper form.\nvar form = $.fn.form = function() {\n\treturn typeof this[ 0 ].form === \"string\" ? this.closest( \"form\" ) : $( this[ 0 ].form );\n};\n\n\n/*!\n * jQuery UI Form Reset Mixin 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Form Reset Mixin\n//>>group: Core\n//>>description: Refresh input widgets when their form is reset\n//>>docs: http://api.jqueryui.com/form-reset-mixin/\n\n\n\nvar formResetMixin = $.ui.formResetMixin = {\n\t_formResetHandler: function() {\n\t\tvar form = $( this );\n\n\t\t// Wait for the form reset to actually happen before refreshing\n\t\tsetTimeout( function() {\n\t\t\tvar instances = form.data( \"ui-form-reset-instances\" );\n\t\t\t$.each( instances, function() {\n\t\t\t\tthis.refresh();\n\t\t\t} );\n\t\t} );\n\t},\n\n\t_bindFormResetHandler: function() {\n\t\tthis.form = this.element.form();\n\t\tif ( !this.form.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar instances = this.form.data( \"ui-form-reset-instances\" ) || [];\n\t\tif ( !instances.length ) {\n\n\t\t\t// We don't use _on() here because we use a single event handler per form\n\t\t\tthis.form.on( \"reset.ui-form-reset\", this._formResetHandler );\n\t\t}\n\t\tinstances.push( this );\n\t\tthis.form.data( \"ui-form-reset-instances\", instances );\n\t},\n\n\t_unbindFormResetHandler: function() {\n\t\tif ( !this.form.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar instances = this.form.data( \"ui-form-reset-instances\" );\n\t\tinstances.splice( $.inArray( this, instances ), 1 );\n\t\tif ( instances.length ) {\n\t\t\tthis.form.data( \"ui-form-reset-instances\", instances );\n\t\t} else {\n\t\t\tthis.form\n\t\t\t\t.removeData( \"ui-form-reset-instances\" )\n\t\t\t\t.off( \"reset.ui-form-reset\" );\n\t\t}\n\t}\n};\n\n\n/*!\n * jQuery UI Support for jQuery core 1.7.x 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n */\n\n//>>label: jQuery 1.7 Support\n//>>group: Core\n//>>description: Support version 1.7.x of jQuery core\n\n\n\n// Support: jQuery 1.7 only\n// Not a great way to check versions, but since we only support 1.7+ and only\n// need to detect <1.8, this is a simple check that should suffice. Checking\n// for \"1.7.\" would be a bit safer, but the version string is 1.7, not 1.7.0\n// and we'll never reach 1.70.0 (if we do, we certainly won't be supporting\n// 1.7 anymore). See #11197 for why we're not using feature detection.\nif ( $.fn.jquery.substring( 0, 3 ) === \"1.7\" ) {\n\n\t// Setters for .innerWidth(), .innerHeight(), .outerWidth(), .outerHeight()\n\t// Unlike jQuery Core 1.8+, these only support numeric values to set the\n\t// dimensions in pixels\n\t$.each( [ \"Width\", \"Height\" ], function( i, name ) {\n\t\tvar side = name === \"Width\" ? [ \"Left\", \"Right\" ] : [ \"Top\", \"Bottom\" ],\n\t\t\ttype = name.toLowerCase(),\n\t\t\torig = {\n\t\t\t\tinnerWidth: $.fn.innerWidth,\n\t\t\t\tinnerHeight: $.fn.innerHeight,\n\t\t\t\touterWidth: $.fn.outerWidth,\n\t\t\t\touterHeight: $.fn.outerHeight\n\t\t\t};\n\n\t\tfunction reduce( elem, size, border, margin ) {\n\t\t\t$.each( side, function() {\n\t\t\t\tsize -= parseFloat( $.css( elem, \"padding\" + this ) ) || 0;\n\t\t\t\tif ( border ) {\n\t\t\t\t\tsize -= parseFloat( $.css( elem, \"border\" + this + \"Width\" ) ) || 0;\n\t\t\t\t}\n\t\t\t\tif ( margin ) {\n\t\t\t\t\tsize -= parseFloat( $.css( elem, \"margin\" + this ) ) || 0;\n\t\t\t\t}\n\t\t\t} );\n\t\t\treturn size;\n\t\t}\n\n\t\t$.fn[ \"inner\" + name ] = function( size ) {\n\t\t\tif ( size === undefined ) {\n\t\t\t\treturn orig[ \"inner\" + name ].call( this );\n\t\t\t}\n\n\t\t\treturn this.each( function() {\n\t\t\t\t$( this ).css( type, reduce( this, size ) + \"px\" );\n\t\t\t} );\n\t\t};\n\n\t\t$.fn[ \"outer\" + name ] = function( size, margin ) {\n\t\t\tif ( typeof size !== \"number\" ) {\n\t\t\t\treturn orig[ \"outer\" + name ].call( this, size );\n\t\t\t}\n\n\t\t\treturn this.each( function() {\n\t\t\t\t$( this ).css( type, reduce( this, size, true, margin ) + \"px\" );\n\t\t\t} );\n\t\t};\n\t} );\n\n\t$.fn.addBack = function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t};\n}\n\n;\n/*!\n * jQuery UI Keycode 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Keycode\n//>>group: Core\n//>>description: Provide keycodes as keynames\n//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/\n\n\nvar keycode = $.ui.keyCode = {\n\tBACKSPACE: 8,\n\tCOMMA: 188,\n\tDELETE: 46,\n\tDOWN: 40,\n\tEND: 35,\n\tENTER: 13,\n\tESCAPE: 27,\n\tHOME: 36,\n\tLEFT: 37,\n\tPAGE_DOWN: 34,\n\tPAGE_UP: 33,\n\tPERIOD: 190,\n\tRIGHT: 39,\n\tSPACE: 32,\n\tTAB: 9,\n\tUP: 38\n};\n\n\n\n\n// Internal use only\nvar escapeSelector = $.ui.escapeSelector = ( function() {\n\tvar selectorEscape = /([!\"#$%&'()*+,./:;<=>?@[\\]^`{|}~])/g;\n\treturn function( selector ) {\n\t\treturn selector.replace( selectorEscape, \"\\\\$1\" );\n\t};\n} )();\n\n\n/*!\n * jQuery UI Labels 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: labels\n//>>group: Core\n//>>description: Find all the labels associated with a given input\n//>>docs: http://api.jqueryui.com/labels/\n\n\n\nvar labels = $.fn.labels = function() {\n\tvar ancestor, selector, id, labels, ancestors;\n\n\t// Check control.labels first\n\tif ( this[ 0 ].labels && this[ 0 ].labels.length ) {\n\t\treturn this.pushStack( this[ 0 ].labels );\n\t}\n\n\t// Support: IE <= 11, FF <= 37, Android <= 2.3 only\n\t// Above browsers do not support control.labels. Everything below is to support them\n\t// as well as document fragments. control.labels does not work on document fragments\n\tlabels = this.eq( 0 ).parents( \"label\" );\n\n\t// Look for the label based on the id\n\tid = this.attr( \"id\" );\n\tif ( id ) {\n\n\t\t// We don't search against the document in case the element\n\t\t// is disconnected from the DOM\n\t\tancestor = this.eq( 0 ).parents().last();\n\n\t\t// Get a full set of top level ancestors\n\t\tancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );\n\n\t\t// Create a selector for the label based on the id\n\t\tselector = \"label[for='\" + $.ui.escapeSelector( id ) + \"']\";\n\n\t\tlabels = labels.add( ancestors.find( selector ).addBack( selector ) );\n\n\t}\n\n\t// Return whatever we have found for labels\n\treturn this.pushStack( labels );\n};\n\n\n/*!\n * jQuery UI Scroll Parent 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: scrollParent\n//>>group: Core\n//>>description: Get the closest ancestor element that is scrollable.\n//>>docs: http://api.jqueryui.com/scrollParent/\n\n\n\nvar scrollParent = $.fn.scrollParent = function( includeHidden ) {\n\tvar position = this.css( \"position\" ),\n\t\texcludeStaticParent = position === \"absolute\",\n\t\toverflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,\n\t\tscrollParent = this.parents().filter( function() {\n\t\t\tvar parent = $( this );\n\t\t\tif ( excludeStaticParent && parent.css( \"position\" ) === \"static\" ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn overflowRegex.test( parent.css( \"overflow\" ) + parent.css( \"overflow-y\" ) +\n\t\t\t\tparent.css( \"overflow-x\" ) );\n\t\t} ).eq( 0 );\n\n\treturn position === \"fixed\" || !scrollParent.length ?\n\t\t$( this[ 0 ].ownerDocument || document ) :\n\t\tscrollParent;\n};\n\n\n/*!\n * jQuery UI Tabbable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: :tabbable Selector\n//>>group: Core\n//>>description: Selects elements which can be tabbed to.\n//>>docs: http://api.jqueryui.com/tabbable-selector/\n\n\n\nvar tabbable = $.extend( $.expr[ \":\" ], {\n\ttabbable: function( element ) {\n\t\tvar tabIndex = $.attr( element, \"tabindex\" ),\n\t\t\thasTabindex = tabIndex != null;\n\t\treturn ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );\n\t}\n} );\n\n\n/*!\n * jQuery UI Unique ID 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: uniqueId\n//>>group: Core\n//>>description: Functions to generate and remove uniqueId's\n//>>docs: http://api.jqueryui.com/uniqueId/\n\n\n\nvar uniqueId = $.fn.extend( {\n\tuniqueId: ( function() {\n\t\tvar uuid = 0;\n\n\t\treturn function() {\n\t\t\treturn this.each( function() {\n\t\t\t\tif ( !this.id ) {\n\t\t\t\t\tthis.id = \"ui-id-\" + ( ++uuid );\n\t\t\t\t}\n\t\t\t} );\n\t\t};\n\t} )(),\n\n\tremoveUniqueId: function() {\n\t\treturn this.each( function() {\n\t\t\tif ( /^ui-id-\\d+$/.test( this.id ) ) {\n\t\t\t\t$( this ).removeAttr( \"id\" );\n\t\t\t}\n\t\t} );\n\t}\n} );\n\n\n\n\n// This file is deprecated\nvar ie = $.ui.ie = !!/msie [\\w.]+/.exec( navigator.userAgent.toLowerCase() );\n\n/*!\n * jQuery UI Mouse 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Mouse\n//>>group: Widgets\n//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.\n//>>docs: http://api.jqueryui.com/mouse/\n\n\n\nvar mouseHandled = false;\n$( document ).on( \"mouseup\", function() {\n\tmouseHandled = false;\n} );\n\nvar widgetsMouse = $.widget( \"ui.mouse\", {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tcancel: \"input, textarea, button, select, option\",\n\t\tdistance: 1,\n\t\tdelay: 0\n\t},\n\t_mouseInit: function() {\n\t\tvar that = this;\n\n\t\tthis.element\n\t\t\t.on( \"mousedown.\" + this.widgetName, function( event ) {\n\t\t\t\treturn that._mouseDown( event );\n\t\t\t} )\n\t\t\t.on( \"click.\" + this.widgetName, function( event ) {\n\t\t\t\tif ( true === $.data( event.target, that.widgetName + \".preventClickEvent\" ) ) {\n\t\t\t\t\t$.removeData( event.target, that.widgetName + \".preventClickEvent\" );\n\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t} );\n\n\t\tthis.started = false;\n\t},\n\n\t// TODO: make sure destroying one instance of mouse doesn't mess with\n\t// other instances of mouse\n\t_mouseDestroy: function() {\n\t\tthis.element.off( \".\" + this.widgetName );\n\t\tif ( this._mouseMoveDelegate ) {\n\t\t\tthis.document\n\t\t\t\t.off( \"mousemove.\" + this.widgetName, this._mouseMoveDelegate )\n\t\t\t\t.off( \"mouseup.\" + this.widgetName, this._mouseUpDelegate );\n\t\t}\n\t},\n\n\t_mouseDown: function( event ) {\n\n\t\t// don't let more than one widget handle mouseStart\n\t\tif ( mouseHandled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._mouseMoved = false;\n\n\t\t// We may have missed mouseup (out of window)\n\t\t( this._mouseStarted && this._mouseUp( event ) );\n\n\t\tthis._mouseDownEvent = event;\n\n\t\tvar that = this,\n\t\t\tbtnIsLeft = ( event.which === 1 ),\n\n\t\t\t// event.target.nodeName works around a bug in IE 8 with\n\t\t\t// disabled inputs (#7620)\n\t\t\telIsCancel = ( typeof this.options.cancel === \"string\" && event.target.nodeName ?\n\t\t\t\t$( event.target ).closest( this.options.cancel ).length : false );\n\t\tif ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\tthis.mouseDelayMet = !this.options.delay;\n\t\tif ( !this.mouseDelayMet ) {\n\t\t\tthis._mouseDelayTimer = setTimeout( function() {\n\t\t\t\tthat.mouseDelayMet = true;\n\t\t\t}, this.options.delay );\n\t\t}\n\n\t\tif ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {\n\t\t\tthis._mouseStarted = ( this._mouseStart( event ) !== false );\n\t\t\tif ( !this._mouseStarted ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\t// Click event may never have fired (Gecko & Opera)\n\t\tif ( true === $.data( event.target, this.widgetName + \".preventClickEvent\" ) ) {\n\t\t\t$.removeData( event.target, this.widgetName + \".preventClickEvent\" );\n\t\t}\n\n\t\t// These delegates are required to keep context\n\t\tthis._mouseMoveDelegate = function( event ) {\n\t\t\treturn that._mouseMove( event );\n\t\t};\n\t\tthis._mouseUpDelegate = function( event ) {\n\t\t\treturn that._mouseUp( event );\n\t\t};\n\n\t\tthis.document\n\t\t\t.on( \"mousemove.\" + this.widgetName, this._mouseMoveDelegate )\n\t\t\t.on( \"mouseup.\" + this.widgetName, this._mouseUpDelegate );\n\n\t\tevent.preventDefault();\n\n\t\tmouseHandled = true;\n\t\treturn true;\n\t},\n\n\t_mouseMove: function( event ) {\n\n\t\t// Only check for mouseups outside the document if you've moved inside the document\n\t\t// at least once. This prevents the firing of mouseup in the case of IE<9, which will\n\t\t// fire a mousemove event if content is placed under the cursor. See #7778\n\t\t// Support: IE <9\n\t\tif ( this._mouseMoved ) {\n\n\t\t\t// IE mouseup check - mouseup happened when mouse was out of window\n\t\t\tif ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&\n\t\t\t\t\t!event.button ) {\n\t\t\t\treturn this._mouseUp( event );\n\n\t\t\t// Iframe mouseup check - mouseup occurred in another document\n\t\t\t} else if ( !event.which ) {\n\n\t\t\t\t// Support: Safari <=8 - 9\n\t\t\t\t// Safari sets which to 0 if you press any of the following keys\n\t\t\t\t// during a drag (#14461)\n\t\t\t\tif ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||\n\t\t\t\t\t\tevent.originalEvent.metaKey || event.originalEvent.shiftKey ) {\n\t\t\t\t\tthis.ignoreMissingWhich = true;\n\t\t\t\t} else if ( !this.ignoreMissingWhich ) {\n\t\t\t\t\treturn this._mouseUp( event );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( event.which || event.button ) {\n\t\t\tthis._mouseMoved = true;\n\t\t}\n\n\t\tif ( this._mouseStarted ) {\n\t\t\tthis._mouseDrag( event );\n\t\t\treturn event.preventDefault();\n\t\t}\n\n\t\tif ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {\n\t\t\tthis._mouseStarted =\n\t\t\t\t( this._mouseStart( this._mouseDownEvent, event ) !== false );\n\t\t\t( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event ) );\n\t\t}\n\n\t\treturn !this._mouseStarted;\n\t},\n\n\t_mouseUp: function( event ) {\n\t\tthis.document\n\t\t\t.off( \"mousemove.\" + this.widgetName, this._mouseMoveDelegate )\n\t\t\t.off( \"mouseup.\" + this.widgetName, this._mouseUpDelegate );\n\n\t\tif ( this._mouseStarted ) {\n\t\t\tthis._mouseStarted = false;\n\n\t\t\tif ( event.target === this._mouseDownEvent.target ) {\n\t\t\t\t$.data( event.target, this.widgetName + \".preventClickEvent\", true );\n\t\t\t}\n\n\t\t\tthis._mouseStop( event );\n\t\t}\n\n\t\tif ( this._mouseDelayTimer ) {\n\t\t\tclearTimeout( this._mouseDelayTimer );\n\t\t\tdelete this._mouseDelayTimer;\n\t\t}\n\n\t\tthis.ignoreMissingWhich = false;\n\t\tmouseHandled = false;\n\t\tevent.preventDefault();\n\t},\n\n\t_mouseDistanceMet: function( event ) {\n\t\treturn ( Math.max(\n\t\t\t\tMath.abs( this._mouseDownEvent.pageX - event.pageX ),\n\t\t\t\tMath.abs( this._mouseDownEvent.pageY - event.pageY )\n\t\t\t) >= this.options.distance\n\t\t);\n\t},\n\n\t_mouseDelayMet: function( /* event */ ) {\n\t\treturn this.mouseDelayMet;\n\t},\n\n\t// These are placeholder methods, to be overriden by extending plugin\n\t_mouseStart: function( /* event */ ) {},\n\t_mouseDrag: function( /* event */ ) {},\n\t_mouseStop: function( /* event */ ) {},\n\t_mouseCapture: function( /* event */ ) { return true; }\n} );\n\n\n\n\n// $.ui.plugin is deprecated. Use $.widget() extensions instead.\nvar plugin = $.ui.plugin = {\n\tadd: function( module, option, set ) {\n\t\tvar i,\n\t\t\tproto = $.ui[ module ].prototype;\n\t\tfor ( i in set ) {\n\t\t\tproto.plugins[ i ] = proto.plugins[ i ] || [];\n\t\t\tproto.plugins[ i ].push( [ option, set[ i ] ] );\n\t\t}\n\t},\n\tcall: function( instance, name, args, allowDisconnected ) {\n\t\tvar i,\n\t\t\tset = instance.plugins[ name ];\n\n\t\tif ( !set ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||\n\t\t\t\tinstance.element[ 0 ].parentNode.nodeType === 11 ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( i = 0; i < set.length; i++ ) {\n\t\t\tif ( instance.options[ set[ i ][ 0 ] ] ) {\n\t\t\t\tset[ i ][ 1 ].apply( instance.element, args );\n\t\t\t}\n\t\t}\n\t}\n};\n\n\n\nvar safeActiveElement = $.ui.safeActiveElement = function( document ) {\n\tvar activeElement;\n\n\t// Support: IE 9 only\n\t// IE9 throws an \"Unspecified error\" accessing document.activeElement from an <iframe>\n\ttry {\n\t\tactiveElement = document.activeElement;\n\t} catch ( error ) {\n\t\tactiveElement = document.body;\n\t}\n\n\t// Support: IE 9 - 11 only\n\t// IE may return null instead of an element\n\t// Interestingly, this only seems to occur when NOT in an iframe\n\tif ( !activeElement ) {\n\t\tactiveElement = document.body;\n\t}\n\n\t// Support: IE 11 only\n\t// IE11 returns a seemingly empty object in some cases when accessing\n\t// document.activeElement from an <iframe>\n\tif ( !activeElement.nodeName ) {\n\t\tactiveElement = document.body;\n\t}\n\n\treturn activeElement;\n};\n\n\n\nvar safeBlur = $.ui.safeBlur = function( element ) {\n\n\t// Support: IE9 - 10 only\n\t// If the <body> is blurred, IE will switch windows, see #9420\n\tif ( element && element.nodeName.toLowerCase() !== \"body\" ) {\n\t\t$( element ).trigger( \"blur\" );\n\t}\n};\n\n\n/*!\n * jQuery UI Draggable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Draggable\n//>>group: Interactions\n//>>description: Enables dragging functionality for any element.\n//>>docs: http://api.jqueryui.com/draggable/\n//>>demos: http://jqueryui.com/draggable/\n//>>css.structure: ../../themes/base/draggable.css\n\n\n\n$.widget( \"ui.draggable\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"drag\",\n\toptions: {\n\t\taddClasses: true,\n\t\tappendTo: \"parent\",\n\t\taxis: false,\n\t\tconnectToSortable: false,\n\t\tcontainment: false,\n\t\tcursor: \"auto\",\n\t\tcursorAt: false,\n\t\tgrid: false,\n\t\thandle: false,\n\t\thelper: \"original\",\n\t\tiframeFix: false,\n\t\topacity: false,\n\t\trefreshPositions: false,\n\t\trevert: false,\n\t\trevertDuration: 500,\n\t\tscope: \"default\",\n\t\tscroll: true,\n\t\tscrollSensitivity: 20,\n\t\tscrollSpeed: 20,\n\t\tsnap: false,\n\t\tsnapMode: \"both\",\n\t\tsnapTolerance: 20,\n\t\tstack: false,\n\t\tzIndex: false,\n\n\t\t// Callbacks\n\t\tdrag: null,\n\t\tstart: null,\n\t\tstop: null\n\t},\n\t_create: function() {\n\n\t\tif ( this.options.helper === \"original\" ) {\n\t\t\tthis._setPositionRelative();\n\t\t}\n\t\tif ( this.options.addClasses ) {\n\t\t\tthis._addClass( \"ui-draggable\" );\n\t\t}\n\t\tthis._setHandleClassName();\n\n\t\tthis._mouseInit();\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\t\tif ( key === \"handle\" ) {\n\t\t\tthis._removeHandleClassName();\n\t\t\tthis._setHandleClassName();\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tif ( ( this.helper || this.element ).is( \".ui-draggable-dragging\" ) ) {\n\t\t\tthis.destroyOnClear = true;\n\t\t\treturn;\n\t\t}\n\t\tthis._removeHandleClassName();\n\t\tthis._mouseDestroy();\n\t},\n\n\t_mouseCapture: function( event ) {\n\t\tvar o = this.options;\n\n\t\t// Among others, prevent a drag on a resizable-handle\n\t\tif ( this.helper || o.disabled ||\n\t\t\t\t$( event.target ).closest( \".ui-resizable-handle\" ).length > 0 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t//Quit if we're not on a valid handle\n\t\tthis.handle = this._getHandle( event );\n\t\tif ( !this.handle ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis._blurActiveElement( event );\n\n\t\tthis._blockFrames( o.iframeFix === true ? \"iframe\" : o.iframeFix );\n\n\t\treturn true;\n\n\t},\n\n\t_blockFrames: function( selector ) {\n\t\tthis.iframeBlocks = this.document.find( selector ).map( function() {\n\t\t\tvar iframe = $( this );\n\n\t\t\treturn $( \"<div>\" )\n\t\t\t\t.css( \"position\", \"absolute\" )\n\t\t\t\t.appendTo( iframe.parent() )\n\t\t\t\t.outerWidth( iframe.outerWidth() )\n\t\t\t\t.outerHeight( iframe.outerHeight() )\n\t\t\t\t.offset( iframe.offset() )[ 0 ];\n\t\t} );\n\t},\n\n\t_unblockFrames: function() {\n\t\tif ( this.iframeBlocks ) {\n\t\t\tthis.iframeBlocks.remove();\n\t\t\tdelete this.iframeBlocks;\n\t\t}\n\t},\n\n\t_blurActiveElement: function( event ) {\n\t\tvar activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),\n\t\t\ttarget = $( event.target );\n\n\t\t// Don't blur if the event occurred on an element that is within\n\t\t// the currently focused element\n\t\t// See #10527, #12472\n\t\tif ( target.closest( activeElement ).length ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Blur any element that currently has focus, see #4261\n\t\t$.ui.safeBlur( activeElement );\n\t},\n\n\t_mouseStart: function( event ) {\n\n\t\tvar o = this.options;\n\n\t\t//Create and append the visible helper\n\t\tthis.helper = this._createHelper( event );\n\n\t\tthis._addClass( this.helper, \"ui-draggable-dragging\" );\n\n\t\t//Cache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t//If ddmanager is used for droppables, set the global draggable\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.current = this;\n\t\t}\n\n\t\t/*\n\t\t * - Position generation -\n\t\t * This block generates everything position related - it's the core of draggables.\n\t\t */\n\n\t\t//Cache the margins of the original element\n\t\tthis._cacheMargins();\n\n\t\t//Store the helper's css position\n\t\tthis.cssPosition = this.helper.css( \"position\" );\n\t\tthis.scrollParent = this.helper.scrollParent( true );\n\t\tthis.offsetParent = this.helper.offsetParent();\n\t\tthis.hasFixedAncestor = this.helper.parents().filter( function() {\n\t\t\t\treturn $( this ).css( \"position\" ) === \"fixed\";\n\t\t\t} ).length > 0;\n\n\t\t//The element's absolute position on the page minus margins\n\t\tthis.positionAbs = this.element.offset();\n\t\tthis._refreshOffsets( event );\n\n\t\t//Generate the original position\n\t\tthis.originalPosition = this.position = this._generatePosition( event, false );\n\t\tthis.originalPageX = event.pageX;\n\t\tthis.originalPageY = event.pageY;\n\n\t\t//Adjust the mouse offset relative to the helper if \"cursorAt\" is supplied\n\t\t( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );\n\n\t\t//Set a containment if given in the options\n\t\tthis._setContainment();\n\n\t\t//Trigger event + callbacks\n\t\tif ( this._trigger( \"start\", event ) === false ) {\n\t\t\tthis._clear();\n\t\t\treturn false;\n\t\t}\n\n\t\t//Recache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t//Prepare the droppable offsets\n\t\tif ( $.ui.ddmanager && !o.dropBehaviour ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( this, event );\n\t\t}\n\n\t\t// Execute the drag once - this causes the helper not to be visible before getting its\n\t\t// correct position\n\t\tthis._mouseDrag( event, true );\n\n\t\t// If the ddmanager is used for droppables, inform the manager that dragging has started\n\t\t// (see #5003)\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.dragStart( this, event );\n\t\t}\n\n\t\treturn true;\n\t},\n\n\t_refreshOffsets: function( event ) {\n\t\tthis.offset = {\n\t\t\ttop: this.positionAbs.top - this.margins.top,\n\t\t\tleft: this.positionAbs.left - this.margins.left,\n\t\t\tscroll: false,\n\t\t\tparent: this._getParentOffset(),\n\t\t\trelative: this._getRelativeOffset()\n\t\t};\n\n\t\tthis.offset.click = {\n\t\t\tleft: event.pageX - this.offset.left,\n\t\t\ttop: event.pageY - this.offset.top\n\t\t};\n\t},\n\n\t_mouseDrag: function( event, noPropagation ) {\n\n\t\t// reset any necessary cached properties (see #5009)\n\t\tif ( this.hasFixedAncestor ) {\n\t\t\tthis.offset.parent = this._getParentOffset();\n\t\t}\n\n\t\t//Compute the helpers position\n\t\tthis.position = this._generatePosition( event, true );\n\t\tthis.positionAbs = this._convertPositionTo( \"absolute\" );\n\n\t\t//Call plugins and callbacks and use the resulting position if something is returned\n\t\tif ( !noPropagation ) {\n\t\t\tvar ui = this._uiHash();\n\t\t\tif ( this._trigger( \"drag\", event, ui ) === false ) {\n\t\t\t\tthis._mouseUp( new $.Event( \"mouseup\", event ) );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthis.position = ui.position;\n\t\t}\n\n\t\tthis.helper[ 0 ].style.left = this.position.left + \"px\";\n\t\tthis.helper[ 0 ].style.top = this.position.top + \"px\";\n\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.drag( this, event );\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function( event ) {\n\n\t\t//If we are using droppables, inform the manager about the drop\n\t\tvar that = this,\n\t\t\tdropped = false;\n\t\tif ( $.ui.ddmanager && !this.options.dropBehaviour ) {\n\t\t\tdropped = $.ui.ddmanager.drop( this, event );\n\t\t}\n\n\t\t//if a drop comes from outside (a sortable)\n\t\tif ( this.dropped ) {\n\t\t\tdropped = this.dropped;\n\t\t\tthis.dropped = false;\n\t\t}\n\n\t\tif ( ( this.options.revert === \"invalid\" && !dropped ) ||\n\t\t\t\t( this.options.revert === \"valid\" && dropped ) ||\n\t\t\t\tthis.options.revert === true || ( $.isFunction( this.options.revert ) &&\n\t\t\t\tthis.options.revert.call( this.element, dropped ) )\n\t\t) {\n\t\t\t$( this.helper ).animate(\n\t\t\t\tthis.originalPosition,\n\t\t\t\tparseInt( this.options.revertDuration, 10 ),\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( that._trigger( \"stop\", event ) !== false ) {\n\t\t\t\t\t\tthat._clear();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t} else {\n\t\t\tif ( this._trigger( \"stop\", event ) !== false ) {\n\t\t\t\tthis._clear();\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_mouseUp: function( event ) {\n\t\tthis._unblockFrames();\n\n\t\t// If the ddmanager is used for droppables, inform the manager that dragging has stopped\n\t\t// (see #5003)\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.dragStop( this, event );\n\t\t}\n\n\t\t// Only need to focus if the event occurred on the draggable itself, see #10527\n\t\tif ( this.handleElement.is( event.target ) ) {\n\n\t\t\t// The interaction is over; whether or not the click resulted in a drag,\n\t\t\t// focus the element\n\t\t\tthis.element.trigger( \"focus\" );\n\t\t}\n\n\t\treturn $.ui.mouse.prototype._mouseUp.call( this, event );\n\t},\n\n\tcancel: function() {\n\n\t\tif ( this.helper.is( \".ui-draggable-dragging\" ) ) {\n\t\t\tthis._mouseUp( new $.Event( \"mouseup\", { target: this.element[ 0 ] } ) );\n\t\t} else {\n\t\t\tthis._clear();\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\t_getHandle: function( event ) {\n\t\treturn this.options.handle ?\n\t\t\t!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :\n\t\t\ttrue;\n\t},\n\n\t_setHandleClassName: function() {\n\t\tthis.handleElement = this.options.handle ?\n\t\t\tthis.element.find( this.options.handle ) : this.element;\n\t\tthis._addClass( this.handleElement, \"ui-draggable-handle\" );\n\t},\n\n\t_removeHandleClassName: function() {\n\t\tthis._removeClass( this.handleElement, \"ui-draggable-handle\" );\n\t},\n\n\t_createHelper: function( event ) {\n\n\t\tvar o = this.options,\n\t\t\thelperIsFunction = $.isFunction( o.helper ),\n\t\t\thelper = helperIsFunction ?\n\t\t\t\t$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :\n\t\t\t\t( o.helper === \"clone\" ?\n\t\t\t\t\tthis.element.clone().removeAttr( \"id\" ) :\n\t\t\t\t\tthis.element );\n\n\t\tif ( !helper.parents( \"body\" ).length ) {\n\t\t\thelper.appendTo( ( o.appendTo === \"parent\" ?\n\t\t\t\tthis.element[ 0 ].parentNode :\n\t\t\t\to.appendTo ) );\n\t\t}\n\n\t\t// Http://bugs.jqueryui.com/ticket/9446\n\t\t// a helper function can return the original element\n\t\t// which wouldn't have been set to relative in _create\n\t\tif ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {\n\t\t\tthis._setPositionRelative();\n\t\t}\n\n\t\tif ( helper[ 0 ] !== this.element[ 0 ] &&\n\t\t\t\t!( /(fixed|absolute)/ ).test( helper.css( \"position\" ) ) ) {\n\t\t\thelper.css( \"position\", \"absolute\" );\n\t\t}\n\n\t\treturn helper;\n\n\t},\n\n\t_setPositionRelative: function() {\n\t\tif ( !( /^(?:r|a|f)/ ).test( this.element.css( \"position\" ) ) ) {\n\t\t\tthis.element[ 0 ].style.position = \"relative\";\n\t\t}\n\t},\n\n\t_adjustOffsetFromHelper: function( obj ) {\n\t\tif ( typeof obj === \"string\" ) {\n\t\t\tobj = obj.split( \" \" );\n\t\t}\n\t\tif ( $.isArray( obj ) ) {\n\t\t\tobj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };\n\t\t}\n\t\tif ( \"left\" in obj ) {\n\t\t\tthis.offset.click.left = obj.left + this.margins.left;\n\t\t}\n\t\tif ( \"right\" in obj ) {\n\t\t\tthis.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\n\t\t}\n\t\tif ( \"top\" in obj ) {\n\t\t\tthis.offset.click.top = obj.top + this.margins.top;\n\t\t}\n\t\tif ( \"bottom\" in obj ) {\n\t\t\tthis.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\n\t\t}\n\t},\n\n\t_isRootNode: function( element ) {\n\t\treturn ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];\n\t},\n\n\t_getParentOffset: function() {\n\n\t\t//Get the offsetParent and cache its position\n\t\tvar po = this.offsetParent.offset(),\n\t\t\tdocument = this.document[ 0 ];\n\n\t\t// This is a special case where we need to modify a offset calculated on start, since the\n\t\t// following happened:\n\t\t// 1. The position of the helper is absolute, so it's position is calculated based on the\n\t\t// next positioned parent\n\t\t// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't\n\t\t// the document, which means that the scroll is included in the initial calculation of the\n\t\t// offset of the parent, and never recalculated upon drag\n\t\tif ( this.cssPosition === \"absolute\" && this.scrollParent[ 0 ] !== document &&\n\t\t\t\t$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {\n\t\t\tpo.left += this.scrollParent.scrollLeft();\n\t\t\tpo.top += this.scrollParent.scrollTop();\n\t\t}\n\n\t\tif ( this._isRootNode( this.offsetParent[ 0 ] ) ) {\n\t\t\tpo = { top: 0, left: 0 };\n\t\t}\n\n\t\treturn {\n\t\t\ttop: po.top + ( parseInt( this.offsetParent.css( \"borderTopWidth\" ), 10 ) || 0 ),\n\t\t\tleft: po.left + ( parseInt( this.offsetParent.css( \"borderLeftWidth\" ), 10 ) || 0 )\n\t\t};\n\n\t},\n\n\t_getRelativeOffset: function() {\n\t\tif ( this.cssPosition !== \"relative\" ) {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t\tvar p = this.element.position(),\n\t\t\tscrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );\n\n\t\treturn {\n\t\t\ttop: p.top - ( parseInt( this.helper.css( \"top\" ), 10 ) || 0 ) +\n\t\t\t\t( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),\n\t\t\tleft: p.left - ( parseInt( this.helper.css( \"left\" ), 10 ) || 0 ) +\n\t\t\t\t( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )\n\t\t};\n\n\t},\n\n\t_cacheMargins: function() {\n\t\tthis.margins = {\n\t\t\tleft: ( parseInt( this.element.css( \"marginLeft\" ), 10 ) || 0 ),\n\t\t\ttop: ( parseInt( this.element.css( \"marginTop\" ), 10 ) || 0 ),\n\t\t\tright: ( parseInt( this.element.css( \"marginRight\" ), 10 ) || 0 ),\n\t\t\tbottom: ( parseInt( this.element.css( \"marginBottom\" ), 10 ) || 0 )\n\t\t};\n\t},\n\n\t_cacheHelperProportions: function() {\n\t\tthis.helperProportions = {\n\t\t\twidth: this.helper.outerWidth(),\n\t\t\theight: this.helper.outerHeight()\n\t\t};\n\t},\n\n\t_setContainment: function() {\n\n\t\tvar isUserScrollable, c, ce,\n\t\t\to = this.options,\n\t\t\tdocument = this.document[ 0 ];\n\n\t\tthis.relativeContainer = null;\n\n\t\tif ( !o.containment ) {\n\t\t\tthis.containment = null;\n\t\t\treturn;\n\t\t}\n\n\t\tif ( o.containment === \"window\" ) {\n\t\t\tthis.containment = [\n\t\t\t\t$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,\n\t\t\t\t$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,\n\t\t\t\t$( window ).scrollLeft() + $( window ).width() -\n\t\t\t\t\tthis.helperProportions.width - this.margins.left,\n\t\t\t\t$( window ).scrollTop() +\n\t\t\t\t\t( $( window ).height() || document.body.parentNode.scrollHeight ) -\n\t\t\t\t\tthis.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t\treturn;\n\t\t}\n\n\t\tif ( o.containment === \"document\" ) {\n\t\t\tthis.containment = [\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\t$( document ).width() - this.helperProportions.width - this.margins.left,\n\t\t\t\t( $( document ).height() || document.body.parentNode.scrollHeight ) -\n\t\t\t\t\tthis.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t\treturn;\n\t\t}\n\n\t\tif ( o.containment.constructor === Array ) {\n\t\t\tthis.containment = o.containment;\n\t\t\treturn;\n\t\t}\n\n\t\tif ( o.containment === \"parent\" ) {\n\t\t\to.containment = this.helper[ 0 ].parentNode;\n\t\t}\n\n\t\tc = $( o.containment );\n\t\tce = c[ 0 ];\n\n\t\tif ( !ce ) {\n\t\t\treturn;\n\t\t}\n\n\t\tisUserScrollable = /(scroll|auto)/.test( c.css( \"overflow\" ) );\n\n\t\tthis.containment = [\n\t\t\t( parseInt( c.css( \"borderLeftWidth\" ), 10 ) || 0 ) +\n\t\t\t\t( parseInt( c.css( \"paddingLeft\" ), 10 ) || 0 ),\n\t\t\t( parseInt( c.css( \"borderTopWidth\" ), 10 ) || 0 ) +\n\t\t\t\t( parseInt( c.css( \"paddingTop\" ), 10 ) || 0 ),\n\t\t\t( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -\n\t\t\t\t( parseInt( c.css( \"borderRightWidth\" ), 10 ) || 0 ) -\n\t\t\t\t( parseInt( c.css( \"paddingRight\" ), 10 ) || 0 ) -\n\t\t\t\tthis.helperProportions.width -\n\t\t\t\tthis.margins.left -\n\t\t\t\tthis.margins.right,\n\t\t\t( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -\n\t\t\t\t( parseInt( c.css( \"borderBottomWidth\" ), 10 ) || 0 ) -\n\t\t\t\t( parseInt( c.css( \"paddingBottom\" ), 10 ) || 0 ) -\n\t\t\t\tthis.helperProportions.height -\n\t\t\t\tthis.margins.top -\n\t\t\t\tthis.margins.bottom\n\t\t];\n\t\tthis.relativeContainer = c;\n\t},\n\n\t_convertPositionTo: function( d, pos ) {\n\n\t\tif ( !pos ) {\n\t\t\tpos = this.position;\n\t\t}\n\n\t\tvar mod = d === \"absolute\" ? 1 : -1,\n\t\t\tscrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );\n\n\t\treturn {\n\t\t\ttop: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpos.top\t+\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.top * mod +\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.top * mod -\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.offset.scroll.top :\n\t\t\t\t\t( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )\n\t\t\t),\n\t\t\tleft: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpos.left +\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.left * mod +\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.left * mod\t-\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.offset.scroll.left :\n\t\t\t\t\t( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_generatePosition: function( event, constrainPosition ) {\n\n\t\tvar containment, co, top, left,\n\t\t\to = this.options,\n\t\t\tscrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),\n\t\t\tpageX = event.pageX,\n\t\t\tpageY = event.pageY;\n\n\t\t// Cache the scroll\n\t\tif ( !scrollIsRootNode || !this.offset.scroll ) {\n\t\t\tthis.offset.scroll = {\n\t\t\t\ttop: this.scrollParent.scrollTop(),\n\t\t\t\tleft: this.scrollParent.scrollLeft()\n\t\t\t};\n\t\t}\n\n\t\t/*\n\t\t * - Position constraining -\n\t\t * Constrain the position to a mix of grid, containment.\n\t\t */\n\n\t\t// If we are not dragging yet, we won't check for options\n\t\tif ( constrainPosition ) {\n\t\t\tif ( this.containment ) {\n\t\t\t\tif ( this.relativeContainer ) {\n\t\t\t\t\tco = this.relativeContainer.offset();\n\t\t\t\t\tcontainment = [\n\t\t\t\t\t\tthis.containment[ 0 ] + co.left,\n\t\t\t\t\t\tthis.containment[ 1 ] + co.top,\n\t\t\t\t\t\tthis.containment[ 2 ] + co.left,\n\t\t\t\t\t\tthis.containment[ 3 ] + co.top\n\t\t\t\t\t];\n\t\t\t\t} else {\n\t\t\t\t\tcontainment = this.containment;\n\t\t\t\t}\n\n\t\t\t\tif ( event.pageX - this.offset.click.left < containment[ 0 ] ) {\n\t\t\t\t\tpageX = containment[ 0 ] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif ( event.pageY - this.offset.click.top < containment[ 1 ] ) {\n\t\t\t\t\tpageY = containment[ 1 ] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t\tif ( event.pageX - this.offset.click.left > containment[ 2 ] ) {\n\t\t\t\t\tpageX = containment[ 2 ] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif ( event.pageY - this.offset.click.top > containment[ 3 ] ) {\n\t\t\t\t\tpageY = containment[ 3 ] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( o.grid ) {\n\n\t\t\t\t//Check for grid elements set to 0 to prevent divide by 0 error causing invalid\n\t\t\t\t// argument errors in IE (see ticket #6950)\n\t\t\t\ttop = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -\n\t\t\t\t\tthis.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;\n\t\t\t\tpageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||\n\t\t\t\t\ttop - this.offset.click.top > containment[ 3 ] ) ?\n\t\t\t\t\t\ttop :\n\t\t\t\t\t\t( ( top - this.offset.click.top >= containment[ 1 ] ) ?\n\t\t\t\t\t\t\ttop - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;\n\n\t\t\t\tleft = o.grid[ 0 ] ? this.originalPageX +\n\t\t\t\t\tMath.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :\n\t\t\t\t\tthis.originalPageX;\n\t\t\t\tpageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||\n\t\t\t\t\tleft - this.offset.click.left > containment[ 2 ] ) ?\n\t\t\t\t\t\tleft :\n\t\t\t\t\t\t( ( left - this.offset.click.left >= containment[ 0 ] ) ?\n\t\t\t\t\t\t\tleft - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;\n\t\t\t}\n\n\t\t\tif ( o.axis === \"y\" ) {\n\t\t\t\tpageX = this.originalPageX;\n\t\t\t}\n\n\t\t\tif ( o.axis === \"x\" ) {\n\t\t\t\tpageY = this.originalPageY;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\ttop: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpageY -\n\n\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.click.top -\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.top -\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.top +\n\t\t\t\t( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.offset.scroll.top :\n\t\t\t\t\t( scrollIsRootNode ? 0 : this.offset.scroll.top ) )\n\t\t\t),\n\t\t\tleft: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpageX -\n\n\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.click.left -\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.left -\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.left +\n\t\t\t\t( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.offset.scroll.left :\n\t\t\t\t\t( scrollIsRootNode ? 0 : this.offset.scroll.left ) )\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_clear: function() {\n\t\tthis._removeClass( this.helper, \"ui-draggable-dragging\" );\n\t\tif ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {\n\t\t\tthis.helper.remove();\n\t\t}\n\t\tthis.helper = null;\n\t\tthis.cancelHelperRemoval = false;\n\t\tif ( this.destroyOnClear ) {\n\t\t\tthis.destroy();\n\t\t}\n\t},\n\n\t// From now on bulk stuff - mainly helpers\n\n\t_trigger: function( type, event, ui ) {\n\t\tui = ui || this._uiHash();\n\t\t$.ui.plugin.call( this, type, [ event, ui, this ], true );\n\n\t\t// Absolute position and offset (see #6884 ) have to be recalculated after plugins\n\t\tif ( /^(drag|start|stop)/.test( type ) ) {\n\t\t\tthis.positionAbs = this._convertPositionTo( \"absolute\" );\n\t\t\tui.offset = this.positionAbs;\n\t\t}\n\t\treturn $.Widget.prototype._trigger.call( this, type, event, ui );\n\t},\n\n\tplugins: {},\n\n\t_uiHash: function() {\n\t\treturn {\n\t\t\thelper: this.helper,\n\t\t\tposition: this.position,\n\t\t\toriginalPosition: this.originalPosition,\n\t\t\toffset: this.positionAbs\n\t\t};\n\t}\n\n} );\n\n$.ui.plugin.add( \"draggable\", \"connectToSortable\", {\n\tstart: function( event, ui, draggable ) {\n\t\tvar uiSortable = $.extend( {}, ui, {\n\t\t\titem: draggable.element\n\t\t} );\n\n\t\tdraggable.sortables = [];\n\t\t$( draggable.options.connectToSortable ).each( function() {\n\t\t\tvar sortable = $( this ).sortable( \"instance\" );\n\n\t\t\tif ( sortable && !sortable.options.disabled ) {\n\t\t\t\tdraggable.sortables.push( sortable );\n\n\t\t\t\t// RefreshPositions is called at drag start to refresh the containerCache\n\t\t\t\t// which is used in drag. This ensures it's initialized and synchronized\n\t\t\t\t// with any changes that might have happened on the page since initialization.\n\t\t\t\tsortable.refreshPositions();\n\t\t\t\tsortable._trigger( \"activate\", event, uiSortable );\n\t\t\t}\n\t\t} );\n\t},\n\tstop: function( event, ui, draggable ) {\n\t\tvar uiSortable = $.extend( {}, ui, {\n\t\t\titem: draggable.element\n\t\t} );\n\n\t\tdraggable.cancelHelperRemoval = false;\n\n\t\t$.each( draggable.sortables, function() {\n\t\t\tvar sortable = this;\n\n\t\t\tif ( sortable.isOver ) {\n\t\t\t\tsortable.isOver = 0;\n\n\t\t\t\t// Allow this sortable to handle removing the helper\n\t\t\t\tdraggable.cancelHelperRemoval = true;\n\t\t\t\tsortable.cancelHelperRemoval = false;\n\n\t\t\t\t// Use _storedCSS To restore properties in the sortable,\n\t\t\t\t// as this also handles revert (#9675) since the draggable\n\t\t\t\t// may have modified them in unexpected ways (#8809)\n\t\t\t\tsortable._storedCSS = {\n\t\t\t\t\tposition: sortable.placeholder.css( \"position\" ),\n\t\t\t\t\ttop: sortable.placeholder.css( \"top\" ),\n\t\t\t\t\tleft: sortable.placeholder.css( \"left\" )\n\t\t\t\t};\n\n\t\t\t\tsortable._mouseStop( event );\n\n\t\t\t\t// Once drag has ended, the sortable should return to using\n\t\t\t\t// its original helper, not the shared helper from draggable\n\t\t\t\tsortable.options.helper = sortable.options._helper;\n\t\t\t} else {\n\n\t\t\t\t// Prevent this Sortable from removing the helper.\n\t\t\t\t// However, don't set the draggable to remove the helper\n\t\t\t\t// either as another connected Sortable may yet handle the removal.\n\t\t\t\tsortable.cancelHelperRemoval = true;\n\n\t\t\t\tsortable._trigger( \"deactivate\", event, uiSortable );\n\t\t\t}\n\t\t} );\n\t},\n\tdrag: function( event, ui, draggable ) {\n\t\t$.each( draggable.sortables, function() {\n\t\t\tvar innermostIntersecting = false,\n\t\t\t\tsortable = this;\n\n\t\t\t// Copy over variables that sortable's _intersectsWith uses\n\t\t\tsortable.positionAbs = draggable.positionAbs;\n\t\t\tsortable.helperProportions = draggable.helperProportions;\n\t\t\tsortable.offset.click = draggable.offset.click;\n\n\t\t\tif ( sortable._intersectsWith( sortable.containerCache ) ) {\n\t\t\t\tinnermostIntersecting = true;\n\n\t\t\t\t$.each( draggable.sortables, function() {\n\n\t\t\t\t\t// Copy over variables that sortable's _intersectsWith uses\n\t\t\t\t\tthis.positionAbs = draggable.positionAbs;\n\t\t\t\t\tthis.helperProportions = draggable.helperProportions;\n\t\t\t\t\tthis.offset.click = draggable.offset.click;\n\n\t\t\t\t\tif ( this !== sortable &&\n\t\t\t\t\t\t\tthis._intersectsWith( this.containerCache ) &&\n\t\t\t\t\t\t\t$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {\n\t\t\t\t\t\tinnermostIntersecting = false;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn innermostIntersecting;\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\tif ( innermostIntersecting ) {\n\n\t\t\t\t// If it intersects, we use a little isOver variable and set it once,\n\t\t\t\t// so that the move-in stuff gets fired only once.\n\t\t\t\tif ( !sortable.isOver ) {\n\t\t\t\t\tsortable.isOver = 1;\n\n\t\t\t\t\t// Store draggable's parent in case we need to reappend to it later.\n\t\t\t\t\tdraggable._parent = ui.helper.parent();\n\n\t\t\t\t\tsortable.currentItem = ui.helper\n\t\t\t\t\t\t.appendTo( sortable.element )\n\t\t\t\t\t\t.data( \"ui-sortable-item\", true );\n\n\t\t\t\t\t// Store helper option to later restore it\n\t\t\t\t\tsortable.options._helper = sortable.options.helper;\n\n\t\t\t\t\tsortable.options.helper = function() {\n\t\t\t\t\t\treturn ui.helper[ 0 ];\n\t\t\t\t\t};\n\n\t\t\t\t\t// Fire the start events of the sortable with our passed browser event,\n\t\t\t\t\t// and our own helper (so it doesn't create a new one)\n\t\t\t\t\tevent.target = sortable.currentItem[ 0 ];\n\t\t\t\t\tsortable._mouseCapture( event, true );\n\t\t\t\t\tsortable._mouseStart( event, true, true );\n\n\t\t\t\t\t// Because the browser event is way off the new appended portlet,\n\t\t\t\t\t// modify necessary variables to reflect the changes\n\t\t\t\t\tsortable.offset.click.top = draggable.offset.click.top;\n\t\t\t\t\tsortable.offset.click.left = draggable.offset.click.left;\n\t\t\t\t\tsortable.offset.parent.left -= draggable.offset.parent.left -\n\t\t\t\t\t\tsortable.offset.parent.left;\n\t\t\t\t\tsortable.offset.parent.top -= draggable.offset.parent.top -\n\t\t\t\t\t\tsortable.offset.parent.top;\n\n\t\t\t\t\tdraggable._trigger( \"toSortable\", event );\n\n\t\t\t\t\t// Inform draggable that the helper is in a valid drop zone,\n\t\t\t\t\t// used solely in the revert option to handle \"valid/invalid\".\n\t\t\t\t\tdraggable.dropped = sortable.element;\n\n\t\t\t\t\t// Need to refreshPositions of all sortables in the case that\n\t\t\t\t\t// adding to one sortable changes the location of the other sortables (#9675)\n\t\t\t\t\t$.each( draggable.sortables, function() {\n\t\t\t\t\t\tthis.refreshPositions();\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Hack so receive/update callbacks work (mostly)\n\t\t\t\t\tdraggable.currentItem = draggable.element;\n\t\t\t\t\tsortable.fromOutside = draggable;\n\t\t\t\t}\n\n\t\t\t\tif ( sortable.currentItem ) {\n\t\t\t\t\tsortable._mouseDrag( event );\n\n\t\t\t\t\t// Copy the sortable's position because the draggable's can potentially reflect\n\t\t\t\t\t// a relative position, while sortable is always absolute, which the dragged\n\t\t\t\t\t// element has now become. (#8809)\n\t\t\t\t\tui.position = sortable.position;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// If it doesn't intersect with the sortable, and it intersected before,\n\t\t\t\t// we fake the drag stop of the sortable, but make sure it doesn't remove\n\t\t\t\t// the helper by using cancelHelperRemoval.\n\t\t\t\tif ( sortable.isOver ) {\n\n\t\t\t\t\tsortable.isOver = 0;\n\t\t\t\t\tsortable.cancelHelperRemoval = true;\n\n\t\t\t\t\t// Calling sortable's mouseStop would trigger a revert,\n\t\t\t\t\t// so revert must be temporarily false until after mouseStop is called.\n\t\t\t\t\tsortable.options._revert = sortable.options.revert;\n\t\t\t\t\tsortable.options.revert = false;\n\n\t\t\t\t\tsortable._trigger( \"out\", event, sortable._uiHash( sortable ) );\n\t\t\t\t\tsortable._mouseStop( event, true );\n\n\t\t\t\t\t// Restore sortable behaviors that were modfied\n\t\t\t\t\t// when the draggable entered the sortable area (#9481)\n\t\t\t\t\tsortable.options.revert = sortable.options._revert;\n\t\t\t\t\tsortable.options.helper = sortable.options._helper;\n\n\t\t\t\t\tif ( sortable.placeholder ) {\n\t\t\t\t\t\tsortable.placeholder.remove();\n\t\t\t\t\t}\n\n\t\t\t\t\t// Restore and recalculate the draggable's offset considering the sortable\n\t\t\t\t\t// may have modified them in unexpected ways. (#8809, #10669)\n\t\t\t\t\tui.helper.appendTo( draggable._parent );\n\t\t\t\t\tdraggable._refreshOffsets( event );\n\t\t\t\t\tui.position = draggable._generatePosition( event, true );\n\n\t\t\t\t\tdraggable._trigger( \"fromSortable\", event );\n\n\t\t\t\t\t// Inform draggable that the helper is no longer in a valid drop zone\n\t\t\t\t\tdraggable.dropped = false;\n\n\t\t\t\t\t// Need to refreshPositions of all sortables just in case removing\n\t\t\t\t\t// from one sortable changes the location of other sortables (#9675)\n\t\t\t\t\t$.each( draggable.sortables, function() {\n\t\t\t\t\t\tthis.refreshPositions();\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"cursor\", {\n\tstart: function( event, ui, instance ) {\n\t\tvar t = $( \"body\" ),\n\t\t\to = instance.options;\n\n\t\tif ( t.css( \"cursor\" ) ) {\n\t\t\to._cursor = t.css( \"cursor\" );\n\t\t}\n\t\tt.css( \"cursor\", o.cursor );\n\t},\n\tstop: function( event, ui, instance ) {\n\t\tvar o = instance.options;\n\t\tif ( o._cursor ) {\n\t\t\t$( \"body\" ).css( \"cursor\", o._cursor );\n\t\t}\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"opacity\", {\n\tstart: function( event, ui, instance ) {\n\t\tvar t = $( ui.helper ),\n\t\t\to = instance.options;\n\t\tif ( t.css( \"opacity\" ) ) {\n\t\t\to._opacity = t.css( \"opacity\" );\n\t\t}\n\t\tt.css( \"opacity\", o.opacity );\n\t},\n\tstop: function( event, ui, instance ) {\n\t\tvar o = instance.options;\n\t\tif ( o._opacity ) {\n\t\t\t$( ui.helper ).css( \"opacity\", o._opacity );\n\t\t}\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"scroll\", {\n\tstart: function( event, ui, i ) {\n\t\tif ( !i.scrollParentNotHidden ) {\n\t\t\ti.scrollParentNotHidden = i.helper.scrollParent( false );\n\t\t}\n\n\t\tif ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&\n\t\t\t\ti.scrollParentNotHidden[ 0 ].tagName !== \"HTML\" ) {\n\t\t\ti.overflowOffset = i.scrollParentNotHidden.offset();\n\t\t}\n\t},\n\tdrag: function( event, ui, i  ) {\n\n\t\tvar o = i.options,\n\t\t\tscrolled = false,\n\t\t\tscrollParent = i.scrollParentNotHidden[ 0 ],\n\t\t\tdocument = i.document[ 0 ];\n\n\t\tif ( scrollParent !== document && scrollParent.tagName !== \"HTML\" ) {\n\t\t\tif ( !o.axis || o.axis !== \"x\" ) {\n\t\t\t\tif ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;\n\t\t\t\t} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {\n\t\t\t\t\tscrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !o.axis || o.axis !== \"y\" ) {\n\t\t\t\tif ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;\n\t\t\t\t} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {\n\t\t\t\t\tscrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif ( !o.axis || o.axis !== \"x\" ) {\n\t\t\t\tif ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {\n\t\t\t\t\tscrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );\n\t\t\t\t} else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !o.axis || o.axis !== \"y\" ) {\n\t\t\t\tif ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {\n\t\t\t\t\tscrolled = $( document ).scrollLeft(\n\t\t\t\t\t\t$( document ).scrollLeft() - o.scrollSpeed\n\t\t\t\t\t);\n\t\t\t\t} else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrolled = $( document ).scrollLeft(\n\t\t\t\t\t\t$( document ).scrollLeft() + o.scrollSpeed\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tif ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( i, event );\n\t\t}\n\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"snap\", {\n\tstart: function( event, ui, i ) {\n\n\t\tvar o = i.options;\n\n\t\ti.snapElements = [];\n\n\t\t$( o.snap.constructor !== String ? ( o.snap.items || \":data(ui-draggable)\" ) : o.snap )\n\t\t\t.each( function() {\n\t\t\t\tvar $t = $( this ),\n\t\t\t\t\t$o = $t.offset();\n\t\t\t\tif ( this !== i.element[ 0 ] ) {\n\t\t\t\t\ti.snapElements.push( {\n\t\t\t\t\t\titem: this,\n\t\t\t\t\t\twidth: $t.outerWidth(), height: $t.outerHeight(),\n\t\t\t\t\t\ttop: $o.top, left: $o.left\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} );\n\n\t},\n\tdrag: function( event, ui, inst ) {\n\n\t\tvar ts, bs, ls, rs, l, r, t, b, i, first,\n\t\t\to = inst.options,\n\t\t\td = o.snapTolerance,\n\t\t\tx1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,\n\t\t\ty1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;\n\n\t\tfor ( i = inst.snapElements.length - 1; i >= 0; i-- ) {\n\n\t\t\tl = inst.snapElements[ i ].left - inst.margins.left;\n\t\t\tr = l + inst.snapElements[ i ].width;\n\t\t\tt = inst.snapElements[ i ].top - inst.margins.top;\n\t\t\tb = t + inst.snapElements[ i ].height;\n\n\t\t\tif ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||\n\t\t\t\t\t!$.contains( inst.snapElements[ i ].item.ownerDocument,\n\t\t\t\t\tinst.snapElements[ i ].item ) ) {\n\t\t\t\tif ( inst.snapElements[ i ].snapping ) {\n\t\t\t\t\t( inst.options.snap.release &&\n\t\t\t\t\t\tinst.options.snap.release.call(\n\t\t\t\t\t\t\tinst.element,\n\t\t\t\t\t\t\tevent,\n\t\t\t\t\t\t\t$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )\n\t\t\t\t\t\t) );\n\t\t\t\t}\n\t\t\t\tinst.snapElements[ i ].snapping = false;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( o.snapMode !== \"inner\" ) {\n\t\t\t\tts = Math.abs( t - y2 ) <= d;\n\t\t\t\tbs = Math.abs( b - y1 ) <= d;\n\t\t\t\tls = Math.abs( l - x2 ) <= d;\n\t\t\t\trs = Math.abs( r - x1 ) <= d;\n\t\t\t\tif ( ts ) {\n\t\t\t\t\tui.position.top = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: t - inst.helperProportions.height,\n\t\t\t\t\t\tleft: 0\n\t\t\t\t\t} ).top;\n\t\t\t\t}\n\t\t\t\tif ( bs ) {\n\t\t\t\t\tui.position.top = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: b,\n\t\t\t\t\t\tleft: 0\n\t\t\t\t\t} ).top;\n\t\t\t\t}\n\t\t\t\tif ( ls ) {\n\t\t\t\t\tui.position.left = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tleft: l - inst.helperProportions.width\n\t\t\t\t\t} ).left;\n\t\t\t\t}\n\t\t\t\tif ( rs ) {\n\t\t\t\t\tui.position.left = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tleft: r\n\t\t\t\t\t} ).left;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfirst = ( ts || bs || ls || rs );\n\n\t\t\tif ( o.snapMode !== \"outer\" ) {\n\t\t\t\tts = Math.abs( t - y1 ) <= d;\n\t\t\t\tbs = Math.abs( b - y2 ) <= d;\n\t\t\t\tls = Math.abs( l - x1 ) <= d;\n\t\t\t\trs = Math.abs( r - x2 ) <= d;\n\t\t\t\tif ( ts ) {\n\t\t\t\t\tui.position.top = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: t,\n\t\t\t\t\t\tleft: 0\n\t\t\t\t\t} ).top;\n\t\t\t\t}\n\t\t\t\tif ( bs ) {\n\t\t\t\t\tui.position.top = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: b - inst.helperProportions.height,\n\t\t\t\t\t\tleft: 0\n\t\t\t\t\t} ).top;\n\t\t\t\t}\n\t\t\t\tif ( ls ) {\n\t\t\t\t\tui.position.left = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tleft: l\n\t\t\t\t\t} ).left;\n\t\t\t\t}\n\t\t\t\tif ( rs ) {\n\t\t\t\t\tui.position.left = inst._convertPositionTo( \"relative\", {\n\t\t\t\t\t\ttop: 0,\n\t\t\t\t\t\tleft: r - inst.helperProportions.width\n\t\t\t\t\t} ).left;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {\n\t\t\t\t( inst.options.snap.snap &&\n\t\t\t\t\tinst.options.snap.snap.call(\n\t\t\t\t\t\tinst.element,\n\t\t\t\t\t\tevent,\n\t\t\t\t\t\t$.extend( inst._uiHash(), {\n\t\t\t\t\t\t\tsnapItem: inst.snapElements[ i ].item\n\t\t\t\t\t\t} ) ) );\n\t\t\t}\n\t\t\tinst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );\n\n\t\t}\n\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"stack\", {\n\tstart: function( event, ui, instance ) {\n\t\tvar min,\n\t\t\to = instance.options,\n\t\t\tgroup = $.makeArray( $( o.stack ) ).sort( function( a, b ) {\n\t\t\t\treturn ( parseInt( $( a ).css( \"zIndex\" ), 10 ) || 0 ) -\n\t\t\t\t\t( parseInt( $( b ).css( \"zIndex\" ), 10 ) || 0 );\n\t\t\t} );\n\n\t\tif ( !group.length ) { return; }\n\n\t\tmin = parseInt( $( group[ 0 ] ).css( \"zIndex\" ), 10 ) || 0;\n\t\t$( group ).each( function( i ) {\n\t\t\t$( this ).css( \"zIndex\", min + i );\n\t\t} );\n\t\tthis.css( \"zIndex\", ( min + group.length ) );\n\t}\n} );\n\n$.ui.plugin.add( \"draggable\", \"zIndex\", {\n\tstart: function( event, ui, instance ) {\n\t\tvar t = $( ui.helper ),\n\t\t\to = instance.options;\n\n\t\tif ( t.css( \"zIndex\" ) ) {\n\t\t\to._zIndex = t.css( \"zIndex\" );\n\t\t}\n\t\tt.css( \"zIndex\", o.zIndex );\n\t},\n\tstop: function( event, ui, instance ) {\n\t\tvar o = instance.options;\n\n\t\tif ( o._zIndex ) {\n\t\t\t$( ui.helper ).css( \"zIndex\", o._zIndex );\n\t\t}\n\t}\n} );\n\nvar widgetsDraggable = $.ui.draggable;\n\n\n/*!\n * jQuery UI Droppable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Droppable\n//>>group: Interactions\n//>>description: Enables drop targets for draggable elements.\n//>>docs: http://api.jqueryui.com/droppable/\n//>>demos: http://jqueryui.com/droppable/\n\n\n\n$.widget( \"ui.droppable\", {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"drop\",\n\toptions: {\n\t\taccept: \"*\",\n\t\taddClasses: true,\n\t\tgreedy: false,\n\t\tscope: \"default\",\n\t\ttolerance: \"intersect\",\n\n\t\t// Callbacks\n\t\tactivate: null,\n\t\tdeactivate: null,\n\t\tdrop: null,\n\t\tout: null,\n\t\tover: null\n\t},\n\t_create: function() {\n\n\t\tvar proportions,\n\t\t\to = this.options,\n\t\t\taccept = o.accept;\n\n\t\tthis.isover = false;\n\t\tthis.isout = true;\n\n\t\tthis.accept = $.isFunction( accept ) ? accept : function( d ) {\n\t\t\treturn d.is( accept );\n\t\t};\n\n\t\tthis.proportions = function( /* valueToWrite */ ) {\n\t\t\tif ( arguments.length ) {\n\n\t\t\t\t// Store the droppable's proportions\n\t\t\t\tproportions = arguments[ 0 ];\n\t\t\t} else {\n\n\t\t\t\t// Retrieve or derive the droppable's proportions\n\t\t\t\treturn proportions ?\n\t\t\t\t\tproportions :\n\t\t\t\t\tproportions = {\n\t\t\t\t\t\twidth: this.element[ 0 ].offsetWidth,\n\t\t\t\t\t\theight: this.element[ 0 ].offsetHeight\n\t\t\t\t\t};\n\t\t\t}\n\t\t};\n\n\t\tthis._addToManager( o.scope );\n\n\t\to.addClasses && this._addClass( \"ui-droppable\" );\n\n\t},\n\n\t_addToManager: function( scope ) {\n\n\t\t// Add the reference and positions to the manager\n\t\t$.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];\n\t\t$.ui.ddmanager.droppables[ scope ].push( this );\n\t},\n\n\t_splice: function( drop ) {\n\t\tvar i = 0;\n\t\tfor ( ; i < drop.length; i++ ) {\n\t\t\tif ( drop[ i ] === this ) {\n\t\t\t\tdrop.splice( i, 1 );\n\t\t\t}\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tvar drop = $.ui.ddmanager.droppables[ this.options.scope ];\n\n\t\tthis._splice( drop );\n\t},\n\n\t_setOption: function( key, value ) {\n\n\t\tif ( key === \"accept\" ) {\n\t\t\tthis.accept = $.isFunction( value ) ? value : function( d ) {\n\t\t\t\treturn d.is( value );\n\t\t\t};\n\t\t} else if ( key === \"scope\" ) {\n\t\t\tvar drop = $.ui.ddmanager.droppables[ this.options.scope ];\n\n\t\t\tthis._splice( drop );\n\t\t\tthis._addToManager( value );\n\t\t}\n\n\t\tthis._super( key, value );\n\t},\n\n\t_activate: function( event ) {\n\t\tvar draggable = $.ui.ddmanager.current;\n\n\t\tthis._addActiveClass();\n\t\tif ( draggable ) {\n\t\t\tthis._trigger( \"activate\", event, this.ui( draggable ) );\n\t\t}\n\t},\n\n\t_deactivate: function( event ) {\n\t\tvar draggable = $.ui.ddmanager.current;\n\n\t\tthis._removeActiveClass();\n\t\tif ( draggable ) {\n\t\t\tthis._trigger( \"deactivate\", event, this.ui( draggable ) );\n\t\t}\n\t},\n\n\t_over: function( event ) {\n\n\t\tvar draggable = $.ui.ddmanager.current;\n\n\t\t// Bail if draggable and droppable are same element\n\t\tif ( !draggable || ( draggable.currentItem ||\n\t\t\t\tdraggable.element )[ 0 ] === this.element[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||\n\t\t\t\tdraggable.element ) ) ) {\n\t\t\tthis._addHoverClass();\n\t\t\tthis._trigger( \"over\", event, this.ui( draggable ) );\n\t\t}\n\n\t},\n\n\t_out: function( event ) {\n\n\t\tvar draggable = $.ui.ddmanager.current;\n\n\t\t// Bail if draggable and droppable are same element\n\t\tif ( !draggable || ( draggable.currentItem ||\n\t\t\t\tdraggable.element )[ 0 ] === this.element[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||\n\t\t\t\tdraggable.element ) ) ) {\n\t\t\tthis._removeHoverClass();\n\t\t\tthis._trigger( \"out\", event, this.ui( draggable ) );\n\t\t}\n\n\t},\n\n\t_drop: function( event, custom ) {\n\n\t\tvar draggable = custom || $.ui.ddmanager.current,\n\t\t\tchildrenIntersection = false;\n\n\t\t// Bail if draggable and droppable are same element\n\t\tif ( !draggable || ( draggable.currentItem ||\n\t\t\t\tdraggable.element )[ 0 ] === this.element[ 0 ] ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.element\n\t\t\t.find( \":data(ui-droppable)\" )\n\t\t\t.not( \".ui-draggable-dragging\" )\n\t\t\t.each( function() {\n\t\t\t\tvar inst = $( this ).droppable( \"instance\" );\n\t\t\t\tif (\n\t\t\t\t\tinst.options.greedy &&\n\t\t\t\t\t!inst.options.disabled &&\n\t\t\t\t\tinst.options.scope === draggable.options.scope &&\n\t\t\t\t\tinst.accept.call(\n\t\t\t\t\t\tinst.element[ 0 ], ( draggable.currentItem || draggable.element )\n\t\t\t\t\t) &&\n\t\t\t\t\tintersect(\n\t\t\t\t\t\tdraggable,\n\t\t\t\t\t\t$.extend( inst, { offset: inst.element.offset() } ),\n\t\t\t\t\t\tinst.options.tolerance, event\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tchildrenIntersection = true;\n\t\t\t\t\treturn false; }\n\t\t\t} );\n\t\tif ( childrenIntersection ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( this.accept.call( this.element[ 0 ],\n\t\t\t\t( draggable.currentItem || draggable.element ) ) ) {\n\t\t\tthis._removeActiveClass();\n\t\t\tthis._removeHoverClass();\n\n\t\t\tthis._trigger( \"drop\", event, this.ui( draggable ) );\n\t\t\treturn this.element;\n\t\t}\n\n\t\treturn false;\n\n\t},\n\n\tui: function( c ) {\n\t\treturn {\n\t\t\tdraggable: ( c.currentItem || c.element ),\n\t\t\thelper: c.helper,\n\t\t\tposition: c.position,\n\t\t\toffset: c.positionAbs\n\t\t};\n\t},\n\n\t// Extension points just to make backcompat sane and avoid duplicating logic\n\t// TODO: Remove in 1.13 along with call to it below\n\t_addHoverClass: function() {\n\t\tthis._addClass( \"ui-droppable-hover\" );\n\t},\n\n\t_removeHoverClass: function() {\n\t\tthis._removeClass( \"ui-droppable-hover\" );\n\t},\n\n\t_addActiveClass: function() {\n\t\tthis._addClass( \"ui-droppable-active\" );\n\t},\n\n\t_removeActiveClass: function() {\n\t\tthis._removeClass( \"ui-droppable-active\" );\n\t}\n} );\n\nvar intersect = $.ui.intersect = ( function() {\n\tfunction isOverAxis( x, reference, size ) {\n\t\treturn ( x >= reference ) && ( x < ( reference + size ) );\n\t}\n\n\treturn function( draggable, droppable, toleranceMode, event ) {\n\n\t\tif ( !droppable.offset ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar x1 = ( draggable.positionAbs ||\n\t\t\t\tdraggable.position.absolute ).left + draggable.margins.left,\n\t\t\ty1 = ( draggable.positionAbs ||\n\t\t\t\tdraggable.position.absolute ).top + draggable.margins.top,\n\t\t\tx2 = x1 + draggable.helperProportions.width,\n\t\t\ty2 = y1 + draggable.helperProportions.height,\n\t\t\tl = droppable.offset.left,\n\t\t\tt = droppable.offset.top,\n\t\t\tr = l + droppable.proportions().width,\n\t\t\tb = t + droppable.proportions().height;\n\n\t\tswitch ( toleranceMode ) {\n\t\tcase \"fit\":\n\t\t\treturn ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );\n\t\tcase \"intersect\":\n\t\t\treturn ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half\n\t\t\t\tx2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half\n\t\t\t\tt < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half\n\t\t\t\ty2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half\n\t\tcase \"pointer\":\n\t\t\treturn isOverAxis( event.pageY, t, droppable.proportions().height ) &&\n\t\t\t\tisOverAxis( event.pageX, l, droppable.proportions().width );\n\t\tcase \"touch\":\n\t\t\treturn (\n\t\t\t\t( y1 >= t && y1 <= b ) || // Top edge touching\n\t\t\t\t( y2 >= t && y2 <= b ) || // Bottom edge touching\n\t\t\t\t( y1 < t && y2 > b ) // Surrounded vertically\n\t\t\t) && (\n\t\t\t\t( x1 >= l && x1 <= r ) || // Left edge touching\n\t\t\t\t( x2 >= l && x2 <= r ) || // Right edge touching\n\t\t\t\t( x1 < l && x2 > r ) // Surrounded horizontally\n\t\t\t);\n\t\tdefault:\n\t\t\treturn false;\n\t\t}\n\t};\n} )();\n\n/*\n\tThis manager tracks offsets of draggables and droppables\n*/\n$.ui.ddmanager = {\n\tcurrent: null,\n\tdroppables: { \"default\": [] },\n\tprepareOffsets: function( t, event ) {\n\n\t\tvar i, j,\n\t\t\tm = $.ui.ddmanager.droppables[ t.options.scope ] || [],\n\t\t\ttype = event ? event.type : null, // workaround for #2317\n\t\t\tlist = ( t.currentItem || t.element ).find( \":data(ui-droppable)\" ).addBack();\n\n\t\tdroppablesLoop: for ( i = 0; i < m.length; i++ ) {\n\n\t\t\t// No disabled and non-accepted\n\t\t\tif ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],\n\t\t\t\t\t( t.currentItem || t.element ) ) ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Filter out elements in the current dragged item\n\t\t\tfor ( j = 0; j < list.length; j++ ) {\n\t\t\t\tif ( list[ j ] === m[ i ].element[ 0 ] ) {\n\t\t\t\t\tm[ i ].proportions().height = 0;\n\t\t\t\t\tcontinue droppablesLoop;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm[ i ].visible = m[ i ].element.css( \"display\" ) !== \"none\";\n\t\t\tif ( !m[ i ].visible ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Activate the droppable if used directly from draggables\n\t\t\tif ( type === \"mousedown\" ) {\n\t\t\t\tm[ i ]._activate.call( m[ i ], event );\n\t\t\t}\n\n\t\t\tm[ i ].offset = m[ i ].element.offset();\n\t\t\tm[ i ].proportions( {\n\t\t\t\twidth: m[ i ].element[ 0 ].offsetWidth,\n\t\t\t\theight: m[ i ].element[ 0 ].offsetHeight\n\t\t\t} );\n\n\t\t}\n\n\t},\n\tdrop: function( draggable, event ) {\n\n\t\tvar dropped = false;\n\n\t\t// Create a copy of the droppables in case the list changes during the drop (#9116)\n\t\t$.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {\n\n\t\t\tif ( !this.options ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( !this.options.disabled && this.visible &&\n\t\t\t\t\tintersect( draggable, this, this.options.tolerance, event ) ) {\n\t\t\t\tdropped = this._drop.call( this, event ) || dropped;\n\t\t\t}\n\n\t\t\tif ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],\n\t\t\t\t\t( draggable.currentItem || draggable.element ) ) ) {\n\t\t\t\tthis.isout = true;\n\t\t\t\tthis.isover = false;\n\t\t\t\tthis._deactivate.call( this, event );\n\t\t\t}\n\n\t\t} );\n\t\treturn dropped;\n\n\t},\n\tdragStart: function( draggable, event ) {\n\n\t\t// Listen for scrolling so that if the dragging causes scrolling the position of the\n\t\t// droppables can be recalculated (see #5003)\n\t\tdraggable.element.parentsUntil( \"body\" ).on( \"scroll.droppable\", function() {\n\t\t\tif ( !draggable.options.refreshPositions ) {\n\t\t\t\t$.ui.ddmanager.prepareOffsets( draggable, event );\n\t\t\t}\n\t\t} );\n\t},\n\tdrag: function( draggable, event ) {\n\n\t\t// If you have a highly dynamic page, you might try this option. It renders positions\n\t\t// every time you move the mouse.\n\t\tif ( draggable.options.refreshPositions ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( draggable, event );\n\t\t}\n\n\t\t// Run through all droppables and check their positions based on specific tolerance options\n\t\t$.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {\n\n\t\t\tif ( this.options.disabled || this.greedyChild || !this.visible ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar parentInstance, scope, parent,\n\t\t\t\tintersects = intersect( draggable, this, this.options.tolerance, event ),\n\t\t\t\tc = !intersects && this.isover ?\n\t\t\t\t\t\"isout\" :\n\t\t\t\t\t( intersects && !this.isover ? \"isover\" : null );\n\t\t\tif ( !c ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this.options.greedy ) {\n\n\t\t\t\t// find droppable parents with same scope\n\t\t\t\tscope = this.options.scope;\n\t\t\t\tparent = this.element.parents( \":data(ui-droppable)\" ).filter( function() {\n\t\t\t\t\treturn $( this ).droppable( \"instance\" ).options.scope === scope;\n\t\t\t\t} );\n\n\t\t\t\tif ( parent.length ) {\n\t\t\t\t\tparentInstance = $( parent[ 0 ] ).droppable( \"instance\" );\n\t\t\t\t\tparentInstance.greedyChild = ( c === \"isover\" );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// We just moved into a greedy child\n\t\t\tif ( parentInstance && c === \"isover\" ) {\n\t\t\t\tparentInstance.isover = false;\n\t\t\t\tparentInstance.isout = true;\n\t\t\t\tparentInstance._out.call( parentInstance, event );\n\t\t\t}\n\n\t\t\tthis[ c ] = true;\n\t\t\tthis[ c === \"isout\" ? \"isover\" : \"isout\" ] = false;\n\t\t\tthis[ c === \"isover\" ? \"_over\" : \"_out\" ].call( this, event );\n\n\t\t\t// We just moved out of a greedy child\n\t\t\tif ( parentInstance && c === \"isout\" ) {\n\t\t\t\tparentInstance.isout = false;\n\t\t\t\tparentInstance.isover = true;\n\t\t\t\tparentInstance._over.call( parentInstance, event );\n\t\t\t}\n\t\t} );\n\n\t},\n\tdragStop: function( draggable, event ) {\n\t\tdraggable.element.parentsUntil( \"body\" ).off( \"scroll.droppable\" );\n\n\t\t// Call prepareOffsets one final time since IE does not fire return scroll events when\n\t\t// overflow was caused by drag (see #5003)\n\t\tif ( !draggable.options.refreshPositions ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( draggable, event );\n\t\t}\n\t}\n};\n\n// DEPRECATED\n// TODO: switch return back to widget declaration at top of file when this is removed\nif ( $.uiBackCompat !== false ) {\n\n\t// Backcompat for activeClass and hoverClass options\n\t$.widget( \"ui.droppable\", $.ui.droppable, {\n\t\toptions: {\n\t\t\thoverClass: false,\n\t\t\tactiveClass: false\n\t\t},\n\t\t_addActiveClass: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.activeClass ) {\n\t\t\t\tthis.element.addClass( this.options.activeClass );\n\t\t\t}\n\t\t},\n\t\t_removeActiveClass: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.activeClass ) {\n\t\t\t\tthis.element.removeClass( this.options.activeClass );\n\t\t\t}\n\t\t},\n\t\t_addHoverClass: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.hoverClass ) {\n\t\t\t\tthis.element.addClass( this.options.hoverClass );\n\t\t\t}\n\t\t},\n\t\t_removeHoverClass: function() {\n\t\t\tthis._super();\n\t\t\tif ( this.options.hoverClass ) {\n\t\t\t\tthis.element.removeClass( this.options.hoverClass );\n\t\t\t}\n\t\t}\n\t} );\n}\n\nvar widgetsDroppable = $.ui.droppable;\n\n\n/*!\n * jQuery UI Resizable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Resizable\n//>>group: Interactions\n//>>description: Enables resize functionality for any element.\n//>>docs: http://api.jqueryui.com/resizable/\n//>>demos: http://jqueryui.com/resizable/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/resizable.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.resizable\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"resize\",\n\toptions: {\n\t\talsoResize: false,\n\t\tanimate: false,\n\t\tanimateDuration: \"slow\",\n\t\tanimateEasing: \"swing\",\n\t\taspectRatio: false,\n\t\tautoHide: false,\n\t\tclasses: {\n\t\t\t\"ui-resizable-se\": \"ui-icon ui-icon-gripsmall-diagonal-se\"\n\t\t},\n\t\tcontainment: false,\n\t\tghost: false,\n\t\tgrid: false,\n\t\thandles: \"e,s,se\",\n\t\thelper: false,\n\t\tmaxHeight: null,\n\t\tmaxWidth: null,\n\t\tminHeight: 10,\n\t\tminWidth: 10,\n\n\t\t// See #7960\n\t\tzIndex: 90,\n\n\t\t// Callbacks\n\t\tresize: null,\n\t\tstart: null,\n\t\tstop: null\n\t},\n\n\t_num: function( value ) {\n\t\treturn parseFloat( value ) || 0;\n\t},\n\n\t_isNumber: function( value ) {\n\t\treturn !isNaN( parseFloat( value ) );\n\t},\n\n\t_hasScroll: function( el, a ) {\n\n\t\tif ( $( el ).css( \"overflow\" ) === \"hidden\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar scroll = ( a && a === \"left\" ) ? \"scrollLeft\" : \"scrollTop\",\n\t\t\thas = false;\n\n\t\tif ( el[ scroll ] > 0 ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// TODO: determine which cases actually cause this to happen\n\t\t// if the element doesn't have the scroll set, see if it's possible to\n\t\t// set the scroll\n\t\tel[ scroll ] = 1;\n\t\thas = ( el[ scroll ] > 0 );\n\t\tel[ scroll ] = 0;\n\t\treturn has;\n\t},\n\n\t_create: function() {\n\n\t\tvar margins,\n\t\t\to = this.options,\n\t\t\tthat = this;\n\t\tthis._addClass( \"ui-resizable\" );\n\n\t\t$.extend( this, {\n\t\t\t_aspectRatio: !!( o.aspectRatio ),\n\t\t\taspectRatio: o.aspectRatio,\n\t\t\toriginalElement: this.element,\n\t\t\t_proportionallyResizeElements: [],\n\t\t\t_helper: o.helper || o.ghost || o.animate ? o.helper || \"ui-resizable-helper\" : null\n\t\t} );\n\n\t\t// Wrap the element if it cannot hold child nodes\n\t\tif ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {\n\n\t\t\tthis.element.wrap(\n\t\t\t\t$( \"<div class='ui-wrapper' style='overflow: hidden;'></div>\" ).css( {\n\t\t\t\t\tposition: this.element.css( \"position\" ),\n\t\t\t\t\twidth: this.element.outerWidth(),\n\t\t\t\t\theight: this.element.outerHeight(),\n\t\t\t\t\ttop: this.element.css( \"top\" ),\n\t\t\t\t\tleft: this.element.css( \"left\" )\n\t\t\t\t} )\n\t\t\t);\n\n\t\t\tthis.element = this.element.parent().data(\n\t\t\t\t\"ui-resizable\", this.element.resizable( \"instance\" )\n\t\t\t);\n\n\t\t\tthis.elementIsWrapper = true;\n\n\t\t\tmargins = {\n\t\t\t\tmarginTop: this.originalElement.css( \"marginTop\" ),\n\t\t\t\tmarginRight: this.originalElement.css( \"marginRight\" ),\n\t\t\t\tmarginBottom: this.originalElement.css( \"marginBottom\" ),\n\t\t\t\tmarginLeft: this.originalElement.css( \"marginLeft\" )\n\t\t\t};\n\n\t\t\tthis.element.css( margins );\n\t\t\tthis.originalElement.css( \"margin\", 0 );\n\n\t\t\t// support: Safari\n\t\t\t// Prevent Safari textarea resize\n\t\t\tthis.originalResizeStyle = this.originalElement.css( \"resize\" );\n\t\t\tthis.originalElement.css( \"resize\", \"none\" );\n\n\t\t\tthis._proportionallyResizeElements.push( this.originalElement.css( {\n\t\t\t\tposition: \"static\",\n\t\t\t\tzoom: 1,\n\t\t\t\tdisplay: \"block\"\n\t\t\t} ) );\n\n\t\t\t// Support: IE9\n\t\t\t// avoid IE jump (hard set the margin)\n\t\t\tthis.originalElement.css( margins );\n\n\t\t\tthis._proportionallyResize();\n\t\t}\n\n\t\tthis._setupHandles();\n\n\t\tif ( o.autoHide ) {\n\t\t\t$( this.element )\n\t\t\t\t.on( \"mouseenter\", function() {\n\t\t\t\t\tif ( o.disabled ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthat._removeClass( \"ui-resizable-autohide\" );\n\t\t\t\t\tthat._handles.show();\n\t\t\t\t} )\n\t\t\t\t.on( \"mouseleave\", function() {\n\t\t\t\t\tif ( o.disabled ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif ( !that.resizing ) {\n\t\t\t\t\t\tthat._addClass( \"ui-resizable-autohide\" );\n\t\t\t\t\t\tthat._handles.hide();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}\n\n\t\tthis._mouseInit();\n\t},\n\n\t_destroy: function() {\n\n\t\tthis._mouseDestroy();\n\n\t\tvar wrapper,\n\t\t\t_destroy = function( exp ) {\n\t\t\t\t$( exp )\n\t\t\t\t\t.removeData( \"resizable\" )\n\t\t\t\t\t.removeData( \"ui-resizable\" )\n\t\t\t\t\t.off( \".resizable\" )\n\t\t\t\t\t.find( \".ui-resizable-handle\" )\n\t\t\t\t\t\t.remove();\n\t\t\t};\n\n\t\t// TODO: Unwrap at same DOM position\n\t\tif ( this.elementIsWrapper ) {\n\t\t\t_destroy( this.element );\n\t\t\twrapper = this.element;\n\t\t\tthis.originalElement.css( {\n\t\t\t\tposition: wrapper.css( \"position\" ),\n\t\t\t\twidth: wrapper.outerWidth(),\n\t\t\t\theight: wrapper.outerHeight(),\n\t\t\t\ttop: wrapper.css( \"top\" ),\n\t\t\t\tleft: wrapper.css( \"left\" )\n\t\t\t} ).insertAfter( wrapper );\n\t\t\twrapper.remove();\n\t\t}\n\n\t\tthis.originalElement.css( \"resize\", this.originalResizeStyle );\n\t\t_destroy( this.originalElement );\n\n\t\treturn this;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\n\t\tswitch ( key ) {\n\t\tcase \"handles\":\n\t\t\tthis._removeHandles();\n\t\t\tthis._setupHandles();\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t},\n\n\t_setupHandles: function() {\n\t\tvar o = this.options, handle, i, n, hname, axis, that = this;\n\t\tthis.handles = o.handles ||\n\t\t\t( !$( \".ui-resizable-handle\", this.element ).length ?\n\t\t\t\t\"e,s,se\" : {\n\t\t\t\t\tn: \".ui-resizable-n\",\n\t\t\t\t\te: \".ui-resizable-e\",\n\t\t\t\t\ts: \".ui-resizable-s\",\n\t\t\t\t\tw: \".ui-resizable-w\",\n\t\t\t\t\tse: \".ui-resizable-se\",\n\t\t\t\t\tsw: \".ui-resizable-sw\",\n\t\t\t\t\tne: \".ui-resizable-ne\",\n\t\t\t\t\tnw: \".ui-resizable-nw\"\n\t\t\t\t} );\n\n\t\tthis._handles = $();\n\t\tif ( this.handles.constructor === String ) {\n\n\t\t\tif ( this.handles === \"all\" ) {\n\t\t\t\tthis.handles = \"n,e,s,w,se,sw,ne,nw\";\n\t\t\t}\n\n\t\t\tn = this.handles.split( \",\" );\n\t\t\tthis.handles = {};\n\n\t\t\tfor ( i = 0; i < n.length; i++ ) {\n\n\t\t\t\thandle = $.trim( n[ i ] );\n\t\t\t\thname = \"ui-resizable-\" + handle;\n\t\t\t\taxis = $( \"<div>\" );\n\t\t\t\tthis._addClass( axis, \"ui-resizable-handle \" + hname );\n\n\t\t\t\taxis.css( { zIndex: o.zIndex } );\n\n\t\t\t\tthis.handles[ handle ] = \".ui-resizable-\" + handle;\n\t\t\t\tthis.element.append( axis );\n\t\t\t}\n\n\t\t}\n\n\t\tthis._renderAxis = function( target ) {\n\n\t\t\tvar i, axis, padPos, padWrapper;\n\n\t\t\ttarget = target || this.element;\n\n\t\t\tfor ( i in this.handles ) {\n\n\t\t\t\tif ( this.handles[ i ].constructor === String ) {\n\t\t\t\t\tthis.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();\n\t\t\t\t} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {\n\t\t\t\t\tthis.handles[ i ] = $( this.handles[ i ] );\n\t\t\t\t\tthis._on( this.handles[ i ], { \"mousedown\": that._mouseDown } );\n\t\t\t\t}\n\n\t\t\t\tif ( this.elementIsWrapper &&\n\t\t\t\t\t\tthis.originalElement[ 0 ]\n\t\t\t\t\t\t\t.nodeName\n\t\t\t\t\t\t\t.match( /^(textarea|input|select|button)$/i ) ) {\n\t\t\t\t\taxis = $( this.handles[ i ], this.element );\n\n\t\t\t\t\tpadWrapper = /sw|ne|nw|se|n|s/.test( i ) ?\n\t\t\t\t\t\taxis.outerHeight() :\n\t\t\t\t\t\taxis.outerWidth();\n\n\t\t\t\t\tpadPos = [ \"padding\",\n\t\t\t\t\t\t/ne|nw|n/.test( i ) ? \"Top\" :\n\t\t\t\t\t\t/se|sw|s/.test( i ) ? \"Bottom\" :\n\t\t\t\t\t\t/^e$/.test( i ) ? \"Right\" : \"Left\" ].join( \"\" );\n\n\t\t\t\t\ttarget.css( padPos, padWrapper );\n\n\t\t\t\t\tthis._proportionallyResize();\n\t\t\t\t}\n\n\t\t\t\tthis._handles = this._handles.add( this.handles[ i ] );\n\t\t\t}\n\t\t};\n\n\t\t// TODO: make renderAxis a prototype function\n\t\tthis._renderAxis( this.element );\n\n\t\tthis._handles = this._handles.add( this.element.find( \".ui-resizable-handle\" ) );\n\t\tthis._handles.disableSelection();\n\n\t\tthis._handles.on( \"mouseover\", function() {\n\t\t\tif ( !that.resizing ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\taxis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );\n\t\t\t\t}\n\t\t\t\tthat.axis = axis && axis[ 1 ] ? axis[ 1 ] : \"se\";\n\t\t\t}\n\t\t} );\n\n\t\tif ( o.autoHide ) {\n\t\t\tthis._handles.hide();\n\t\t\tthis._addClass( \"ui-resizable-autohide\" );\n\t\t}\n\t},\n\n\t_removeHandles: function() {\n\t\tthis._handles.remove();\n\t},\n\n\t_mouseCapture: function( event ) {\n\t\tvar i, handle,\n\t\t\tcapture = false;\n\n\t\tfor ( i in this.handles ) {\n\t\t\thandle = $( this.handles[ i ] )[ 0 ];\n\t\t\tif ( handle === event.target || $.contains( handle, event.target ) ) {\n\t\t\t\tcapture = true;\n\t\t\t}\n\t\t}\n\n\t\treturn !this.options.disabled && capture;\n\t},\n\n\t_mouseStart: function( event ) {\n\n\t\tvar curleft, curtop, cursor,\n\t\t\to = this.options,\n\t\t\tel = this.element;\n\n\t\tthis.resizing = true;\n\n\t\tthis._renderProxy();\n\n\t\tcurleft = this._num( this.helper.css( \"left\" ) );\n\t\tcurtop = this._num( this.helper.css( \"top\" ) );\n\n\t\tif ( o.containment ) {\n\t\t\tcurleft += $( o.containment ).scrollLeft() || 0;\n\t\t\tcurtop += $( o.containment ).scrollTop() || 0;\n\t\t}\n\n\t\tthis.offset = this.helper.offset();\n\t\tthis.position = { left: curleft, top: curtop };\n\n\t\tthis.size = this._helper ? {\n\t\t\t\twidth: this.helper.width(),\n\t\t\t\theight: this.helper.height()\n\t\t\t} : {\n\t\t\t\twidth: el.width(),\n\t\t\t\theight: el.height()\n\t\t\t};\n\n\t\tthis.originalSize = this._helper ? {\n\t\t\t\twidth: el.outerWidth(),\n\t\t\t\theight: el.outerHeight()\n\t\t\t} : {\n\t\t\t\twidth: el.width(),\n\t\t\t\theight: el.height()\n\t\t\t};\n\n\t\tthis.sizeDiff = {\n\t\t\twidth: el.outerWidth() - el.width(),\n\t\t\theight: el.outerHeight() - el.height()\n\t\t};\n\n\t\tthis.originalPosition = { left: curleft, top: curtop };\n\t\tthis.originalMousePosition = { left: event.pageX, top: event.pageY };\n\n\t\tthis.aspectRatio = ( typeof o.aspectRatio === \"number\" ) ?\n\t\t\to.aspectRatio :\n\t\t\t( ( this.originalSize.width / this.originalSize.height ) || 1 );\n\n\t\tcursor = $( \".ui-resizable-\" + this.axis ).css( \"cursor\" );\n\t\t$( \"body\" ).css( \"cursor\", cursor === \"auto\" ? this.axis + \"-resize\" : cursor );\n\n\t\tthis._addClass( \"ui-resizable-resizing\" );\n\t\tthis._propagate( \"start\", event );\n\t\treturn true;\n\t},\n\n\t_mouseDrag: function( event ) {\n\n\t\tvar data, props,\n\t\t\tsmp = this.originalMousePosition,\n\t\t\ta = this.axis,\n\t\t\tdx = ( event.pageX - smp.left ) || 0,\n\t\t\tdy = ( event.pageY - smp.top ) || 0,\n\t\t\ttrigger = this._change[ a ];\n\n\t\tthis._updatePrevProperties();\n\n\t\tif ( !trigger ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tdata = trigger.apply( this, [ event, dx, dy ] );\n\n\t\tthis._updateVirtualBoundaries( event.shiftKey );\n\t\tif ( this._aspectRatio || event.shiftKey ) {\n\t\t\tdata = this._updateRatio( data, event );\n\t\t}\n\n\t\tdata = this._respectSize( data, event );\n\n\t\tthis._updateCache( data );\n\n\t\tthis._propagate( \"resize\", event );\n\n\t\tprops = this._applyChanges();\n\n\t\tif ( !this._helper && this._proportionallyResizeElements.length ) {\n\t\t\tthis._proportionallyResize();\n\t\t}\n\n\t\tif ( !$.isEmptyObject( props ) ) {\n\t\t\tthis._updatePrevProperties();\n\t\t\tthis._trigger( \"resize\", event, this.ui() );\n\t\t\tthis._applyChanges();\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function( event ) {\n\n\t\tthis.resizing = false;\n\t\tvar pr, ista, soffseth, soffsetw, s, left, top,\n\t\t\to = this.options, that = this;\n\n\t\tif ( this._helper ) {\n\n\t\t\tpr = this._proportionallyResizeElements;\n\t\t\tista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );\n\t\t\tsoffseth = ista && this._hasScroll( pr[ 0 ], \"left\" ) ? 0 : that.sizeDiff.height;\n\t\t\tsoffsetw = ista ? 0 : that.sizeDiff.width;\n\n\t\t\ts = {\n\t\t\t\twidth: ( that.helper.width()  - soffsetw ),\n\t\t\t\theight: ( that.helper.height() - soffseth )\n\t\t\t};\n\t\t\tleft = ( parseFloat( that.element.css( \"left\" ) ) +\n\t\t\t\t( that.position.left - that.originalPosition.left ) ) || null;\n\t\t\ttop = ( parseFloat( that.element.css( \"top\" ) ) +\n\t\t\t\t( that.position.top - that.originalPosition.top ) ) || null;\n\n\t\t\tif ( !o.animate ) {\n\t\t\t\tthis.element.css( $.extend( s, { top: top, left: left } ) );\n\t\t\t}\n\n\t\t\tthat.helper.height( that.size.height );\n\t\t\tthat.helper.width( that.size.width );\n\n\t\t\tif ( this._helper && !o.animate ) {\n\t\t\t\tthis._proportionallyResize();\n\t\t\t}\n\t\t}\n\n\t\t$( \"body\" ).css( \"cursor\", \"auto\" );\n\n\t\tthis._removeClass( \"ui-resizable-resizing\" );\n\n\t\tthis._propagate( \"stop\", event );\n\n\t\tif ( this._helper ) {\n\t\t\tthis.helper.remove();\n\t\t}\n\n\t\treturn false;\n\n\t},\n\n\t_updatePrevProperties: function() {\n\t\tthis.prevPosition = {\n\t\t\ttop: this.position.top,\n\t\t\tleft: this.position.left\n\t\t};\n\t\tthis.prevSize = {\n\t\t\twidth: this.size.width,\n\t\t\theight: this.size.height\n\t\t};\n\t},\n\n\t_applyChanges: function() {\n\t\tvar props = {};\n\n\t\tif ( this.position.top !== this.prevPosition.top ) {\n\t\t\tprops.top = this.position.top + \"px\";\n\t\t}\n\t\tif ( this.position.left !== this.prevPosition.left ) {\n\t\t\tprops.left = this.position.left + \"px\";\n\t\t}\n\t\tif ( this.size.width !== this.prevSize.width ) {\n\t\t\tprops.width = this.size.width + \"px\";\n\t\t}\n\t\tif ( this.size.height !== this.prevSize.height ) {\n\t\t\tprops.height = this.size.height + \"px\";\n\t\t}\n\n\t\tthis.helper.css( props );\n\n\t\treturn props;\n\t},\n\n\t_updateVirtualBoundaries: function( forceAspectRatio ) {\n\t\tvar pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,\n\t\t\to = this.options;\n\n\t\tb = {\n\t\t\tminWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,\n\t\t\tmaxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,\n\t\t\tminHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,\n\t\t\tmaxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity\n\t\t};\n\n\t\tif ( this._aspectRatio || forceAspectRatio ) {\n\t\t\tpMinWidth = b.minHeight * this.aspectRatio;\n\t\t\tpMinHeight = b.minWidth / this.aspectRatio;\n\t\t\tpMaxWidth = b.maxHeight * this.aspectRatio;\n\t\t\tpMaxHeight = b.maxWidth / this.aspectRatio;\n\n\t\t\tif ( pMinWidth > b.minWidth ) {\n\t\t\t\tb.minWidth = pMinWidth;\n\t\t\t}\n\t\t\tif ( pMinHeight > b.minHeight ) {\n\t\t\t\tb.minHeight = pMinHeight;\n\t\t\t}\n\t\t\tif ( pMaxWidth < b.maxWidth ) {\n\t\t\t\tb.maxWidth = pMaxWidth;\n\t\t\t}\n\t\t\tif ( pMaxHeight < b.maxHeight ) {\n\t\t\t\tb.maxHeight = pMaxHeight;\n\t\t\t}\n\t\t}\n\t\tthis._vBoundaries = b;\n\t},\n\n\t_updateCache: function( data ) {\n\t\tthis.offset = this.helper.offset();\n\t\tif ( this._isNumber( data.left ) ) {\n\t\t\tthis.position.left = data.left;\n\t\t}\n\t\tif ( this._isNumber( data.top ) ) {\n\t\t\tthis.position.top = data.top;\n\t\t}\n\t\tif ( this._isNumber( data.height ) ) {\n\t\t\tthis.size.height = data.height;\n\t\t}\n\t\tif ( this._isNumber( data.width ) ) {\n\t\t\tthis.size.width = data.width;\n\t\t}\n\t},\n\n\t_updateRatio: function( data ) {\n\n\t\tvar cpos = this.position,\n\t\t\tcsize = this.size,\n\t\t\ta = this.axis;\n\n\t\tif ( this._isNumber( data.height ) ) {\n\t\t\tdata.width = ( data.height * this.aspectRatio );\n\t\t} else if ( this._isNumber( data.width ) ) {\n\t\t\tdata.height = ( data.width / this.aspectRatio );\n\t\t}\n\n\t\tif ( a === \"sw\" ) {\n\t\t\tdata.left = cpos.left + ( csize.width - data.width );\n\t\t\tdata.top = null;\n\t\t}\n\t\tif ( a === \"nw\" ) {\n\t\t\tdata.top = cpos.top + ( csize.height - data.height );\n\t\t\tdata.left = cpos.left + ( csize.width - data.width );\n\t\t}\n\n\t\treturn data;\n\t},\n\n\t_respectSize: function( data ) {\n\n\t\tvar o = this._vBoundaries,\n\t\t\ta = this.axis,\n\t\t\tismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),\n\t\t\tismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),\n\t\t\tisminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),\n\t\t\tisminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),\n\t\t\tdw = this.originalPosition.left + this.originalSize.width,\n\t\t\tdh = this.originalPosition.top + this.originalSize.height,\n\t\t\tcw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );\n\t\tif ( isminw ) {\n\t\t\tdata.width = o.minWidth;\n\t\t}\n\t\tif ( isminh ) {\n\t\t\tdata.height = o.minHeight;\n\t\t}\n\t\tif ( ismaxw ) {\n\t\t\tdata.width = o.maxWidth;\n\t\t}\n\t\tif ( ismaxh ) {\n\t\t\tdata.height = o.maxHeight;\n\t\t}\n\n\t\tif ( isminw && cw ) {\n\t\t\tdata.left = dw - o.minWidth;\n\t\t}\n\t\tif ( ismaxw && cw ) {\n\t\t\tdata.left = dw - o.maxWidth;\n\t\t}\n\t\tif ( isminh && ch ) {\n\t\t\tdata.top = dh - o.minHeight;\n\t\t}\n\t\tif ( ismaxh && ch ) {\n\t\t\tdata.top = dh - o.maxHeight;\n\t\t}\n\n\t\t// Fixing jump error on top/left - bug #2330\n\t\tif ( !data.width && !data.height && !data.left && data.top ) {\n\t\t\tdata.top = null;\n\t\t} else if ( !data.width && !data.height && !data.top && data.left ) {\n\t\t\tdata.left = null;\n\t\t}\n\n\t\treturn data;\n\t},\n\n\t_getPaddingPlusBorderDimensions: function( element ) {\n\t\tvar i = 0,\n\t\t\twidths = [],\n\t\t\tborders = [\n\t\t\t\telement.css( \"borderTopWidth\" ),\n\t\t\t\telement.css( \"borderRightWidth\" ),\n\t\t\t\telement.css( \"borderBottomWidth\" ),\n\t\t\t\telement.css( \"borderLeftWidth\" )\n\t\t\t],\n\t\t\tpaddings = [\n\t\t\t\telement.css( \"paddingTop\" ),\n\t\t\t\telement.css( \"paddingRight\" ),\n\t\t\t\telement.css( \"paddingBottom\" ),\n\t\t\t\telement.css( \"paddingLeft\" )\n\t\t\t];\n\n\t\tfor ( ; i < 4; i++ ) {\n\t\t\twidths[ i ] = ( parseFloat( borders[ i ] ) || 0 );\n\t\t\twidths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );\n\t\t}\n\n\t\treturn {\n\t\t\theight: widths[ 0 ] + widths[ 2 ],\n\t\t\twidth: widths[ 1 ] + widths[ 3 ]\n\t\t};\n\t},\n\n\t_proportionallyResize: function() {\n\n\t\tif ( !this._proportionallyResizeElements.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar prel,\n\t\t\ti = 0,\n\t\t\telement = this.helper || this.element;\n\n\t\tfor ( ; i < this._proportionallyResizeElements.length; i++ ) {\n\n\t\t\tprel = this._proportionallyResizeElements[ i ];\n\n\t\t\t// TODO: Seems like a bug to cache this.outerDimensions\n\t\t\t// considering that we are in a loop.\n\t\t\tif ( !this.outerDimensions ) {\n\t\t\t\tthis.outerDimensions = this._getPaddingPlusBorderDimensions( prel );\n\t\t\t}\n\n\t\t\tprel.css( {\n\t\t\t\theight: ( element.height() - this.outerDimensions.height ) || 0,\n\t\t\t\twidth: ( element.width() - this.outerDimensions.width ) || 0\n\t\t\t} );\n\n\t\t}\n\n\t},\n\n\t_renderProxy: function() {\n\n\t\tvar el = this.element, o = this.options;\n\t\tthis.elementOffset = el.offset();\n\n\t\tif ( this._helper ) {\n\n\t\t\tthis.helper = this.helper || $( \"<div style='overflow:hidden;'></div>\" );\n\n\t\t\tthis._addClass( this.helper, this._helper );\n\t\t\tthis.helper.css( {\n\t\t\t\twidth: this.element.outerWidth(),\n\t\t\t\theight: this.element.outerHeight(),\n\t\t\t\tposition: \"absolute\",\n\t\t\t\tleft: this.elementOffset.left + \"px\",\n\t\t\t\ttop: this.elementOffset.top + \"px\",\n\t\t\t\tzIndex: ++o.zIndex //TODO: Don't modify option\n\t\t\t} );\n\n\t\t\tthis.helper\n\t\t\t\t.appendTo( \"body\" )\n\t\t\t\t.disableSelection();\n\n\t\t} else {\n\t\t\tthis.helper = this.element;\n\t\t}\n\n\t},\n\n\t_change: {\n\t\te: function( event, dx ) {\n\t\t\treturn { width: this.originalSize.width + dx };\n\t\t},\n\t\tw: function( event, dx ) {\n\t\t\tvar cs = this.originalSize, sp = this.originalPosition;\n\t\t\treturn { left: sp.left + dx, width: cs.width - dx };\n\t\t},\n\t\tn: function( event, dx, dy ) {\n\t\t\tvar cs = this.originalSize, sp = this.originalPosition;\n\t\t\treturn { top: sp.top + dy, height: cs.height - dy };\n\t\t},\n\t\ts: function( event, dx, dy ) {\n\t\t\treturn { height: this.originalSize.height + dy };\n\t\t},\n\t\tse: function( event, dx, dy ) {\n\t\t\treturn $.extend( this._change.s.apply( this, arguments ),\n\t\t\t\tthis._change.e.apply( this, [ event, dx, dy ] ) );\n\t\t},\n\t\tsw: function( event, dx, dy ) {\n\t\t\treturn $.extend( this._change.s.apply( this, arguments ),\n\t\t\t\tthis._change.w.apply( this, [ event, dx, dy ] ) );\n\t\t},\n\t\tne: function( event, dx, dy ) {\n\t\t\treturn $.extend( this._change.n.apply( this, arguments ),\n\t\t\t\tthis._change.e.apply( this, [ event, dx, dy ] ) );\n\t\t},\n\t\tnw: function( event, dx, dy ) {\n\t\t\treturn $.extend( this._change.n.apply( this, arguments ),\n\t\t\t\tthis._change.w.apply( this, [ event, dx, dy ] ) );\n\t\t}\n\t},\n\n\t_propagate: function( n, event ) {\n\t\t$.ui.plugin.call( this, n, [ event, this.ui() ] );\n\t\t( n !== \"resize\" && this._trigger( n, event, this.ui() ) );\n\t},\n\n\tplugins: {},\n\n\tui: function() {\n\t\treturn {\n\t\t\toriginalElement: this.originalElement,\n\t\t\telement: this.element,\n\t\t\thelper: this.helper,\n\t\t\tposition: this.position,\n\t\t\tsize: this.size,\n\t\t\toriginalSize: this.originalSize,\n\t\t\toriginalPosition: this.originalPosition\n\t\t};\n\t}\n\n} );\n\n/*\n * Resizable Extensions\n */\n\n$.ui.plugin.add( \"resizable\", \"animate\", {\n\n\tstop: function( event ) {\n\t\tvar that = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tpr = that._proportionallyResizeElements,\n\t\t\tista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),\n\t\t\tsoffseth = ista && that._hasScroll( pr[ 0 ], \"left\" ) ? 0 : that.sizeDiff.height,\n\t\t\tsoffsetw = ista ? 0 : that.sizeDiff.width,\n\t\t\tstyle = {\n\t\t\t\twidth: ( that.size.width - soffsetw ),\n\t\t\t\theight: ( that.size.height - soffseth )\n\t\t\t},\n\t\t\tleft = ( parseFloat( that.element.css( \"left\" ) ) +\n\t\t\t\t( that.position.left - that.originalPosition.left ) ) || null,\n\t\t\ttop = ( parseFloat( that.element.css( \"top\" ) ) +\n\t\t\t\t( that.position.top - that.originalPosition.top ) ) || null;\n\n\t\tthat.element.animate(\n\t\t\t$.extend( style, top && left ? { top: top, left: left } : {} ), {\n\t\t\t\tduration: o.animateDuration,\n\t\t\t\teasing: o.animateEasing,\n\t\t\t\tstep: function() {\n\n\t\t\t\t\tvar data = {\n\t\t\t\t\t\twidth: parseFloat( that.element.css( \"width\" ) ),\n\t\t\t\t\t\theight: parseFloat( that.element.css( \"height\" ) ),\n\t\t\t\t\t\ttop: parseFloat( that.element.css( \"top\" ) ),\n\t\t\t\t\t\tleft: parseFloat( that.element.css( \"left\" ) )\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( pr && pr.length ) {\n\t\t\t\t\t\t$( pr[ 0 ] ).css( { width: data.width, height: data.height } );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Propagating resize, and updating values for each animation step\n\t\t\t\t\tthat._updateCache( data );\n\t\t\t\t\tthat._propagate( \"resize\", event );\n\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n} );\n\n$.ui.plugin.add( \"resizable\", \"containment\", {\n\n\tstart: function() {\n\t\tvar element, p, co, ch, cw, width, height,\n\t\t\tthat = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tel = that.element,\n\t\t\toc = o.containment,\n\t\t\tce = ( oc instanceof $ ) ?\n\t\t\t\toc.get( 0 ) :\n\t\t\t\t( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;\n\n\t\tif ( !ce ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthat.containerElement = $( ce );\n\n\t\tif ( /document/.test( oc ) || oc === document ) {\n\t\t\tthat.containerOffset = {\n\t\t\t\tleft: 0,\n\t\t\t\ttop: 0\n\t\t\t};\n\t\t\tthat.containerPosition = {\n\t\t\t\tleft: 0,\n\t\t\t\ttop: 0\n\t\t\t};\n\n\t\t\tthat.parentData = {\n\t\t\t\telement: $( document ),\n\t\t\t\tleft: 0,\n\t\t\t\ttop: 0,\n\t\t\t\twidth: $( document ).width(),\n\t\t\t\theight: $( document ).height() || document.body.parentNode.scrollHeight\n\t\t\t};\n\t\t} else {\n\t\t\telement = $( ce );\n\t\t\tp = [];\n\t\t\t$( [ \"Top\", \"Right\", \"Left\", \"Bottom\" ] ).each( function( i, name ) {\n\t\t\t\tp[ i ] = that._num( element.css( \"padding\" + name ) );\n\t\t\t} );\n\n\t\t\tthat.containerOffset = element.offset();\n\t\t\tthat.containerPosition = element.position();\n\t\t\tthat.containerSize = {\n\t\t\t\theight: ( element.innerHeight() - p[ 3 ] ),\n\t\t\t\twidth: ( element.innerWidth() - p[ 1 ] )\n\t\t\t};\n\n\t\t\tco = that.containerOffset;\n\t\t\tch = that.containerSize.height;\n\t\t\tcw = that.containerSize.width;\n\t\t\twidth = ( that._hasScroll ( ce, \"left\" ) ? ce.scrollWidth : cw );\n\t\t\theight = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;\n\n\t\t\tthat.parentData = {\n\t\t\t\telement: ce,\n\t\t\t\tleft: co.left,\n\t\t\t\ttop: co.top,\n\t\t\t\twidth: width,\n\t\t\t\theight: height\n\t\t\t};\n\t\t}\n\t},\n\n\tresize: function( event ) {\n\t\tvar woset, hoset, isParent, isOffsetRelative,\n\t\t\tthat = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tco = that.containerOffset,\n\t\t\tcp = that.position,\n\t\t\tpRatio = that._aspectRatio || event.shiftKey,\n\t\t\tcop = {\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0\n\t\t\t},\n\t\t\tce = that.containerElement,\n\t\t\tcontinueResize = true;\n\n\t\tif ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( \"position\" ) ) ) {\n\t\t\tcop = co;\n\t\t}\n\n\t\tif ( cp.left < ( that._helper ? co.left : 0 ) ) {\n\t\t\tthat.size.width = that.size.width +\n\t\t\t\t( that._helper ?\n\t\t\t\t\t( that.position.left - co.left ) :\n\t\t\t\t\t( that.position.left - cop.left ) );\n\n\t\t\tif ( pRatio ) {\n\t\t\t\tthat.size.height = that.size.width / that.aspectRatio;\n\t\t\t\tcontinueResize = false;\n\t\t\t}\n\t\t\tthat.position.left = o.helper ? co.left : 0;\n\t\t}\n\n\t\tif ( cp.top < ( that._helper ? co.top : 0 ) ) {\n\t\t\tthat.size.height = that.size.height +\n\t\t\t\t( that._helper ?\n\t\t\t\t\t( that.position.top - co.top ) :\n\t\t\t\t\tthat.position.top );\n\n\t\t\tif ( pRatio ) {\n\t\t\t\tthat.size.width = that.size.height * that.aspectRatio;\n\t\t\t\tcontinueResize = false;\n\t\t\t}\n\t\t\tthat.position.top = that._helper ? co.top : 0;\n\t\t}\n\n\t\tisParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );\n\t\tisOffsetRelative = /relative|absolute/.test( that.containerElement.css( \"position\" ) );\n\n\t\tif ( isParent && isOffsetRelative ) {\n\t\t\tthat.offset.left = that.parentData.left + that.position.left;\n\t\t\tthat.offset.top = that.parentData.top + that.position.top;\n\t\t} else {\n\t\t\tthat.offset.left = that.element.offset().left;\n\t\t\tthat.offset.top = that.element.offset().top;\n\t\t}\n\n\t\twoset = Math.abs( that.sizeDiff.width +\n\t\t\t( that._helper ?\n\t\t\t\tthat.offset.left - cop.left :\n\t\t\t\t( that.offset.left - co.left ) ) );\n\n\t\thoset = Math.abs( that.sizeDiff.height +\n\t\t\t( that._helper ?\n\t\t\t\tthat.offset.top - cop.top :\n\t\t\t\t( that.offset.top - co.top ) ) );\n\n\t\tif ( woset + that.size.width >= that.parentData.width ) {\n\t\t\tthat.size.width = that.parentData.width - woset;\n\t\t\tif ( pRatio ) {\n\t\t\t\tthat.size.height = that.size.width / that.aspectRatio;\n\t\t\t\tcontinueResize = false;\n\t\t\t}\n\t\t}\n\n\t\tif ( hoset + that.size.height >= that.parentData.height ) {\n\t\t\tthat.size.height = that.parentData.height - hoset;\n\t\t\tif ( pRatio ) {\n\t\t\t\tthat.size.width = that.size.height * that.aspectRatio;\n\t\t\t\tcontinueResize = false;\n\t\t\t}\n\t\t}\n\n\t\tif ( !continueResize ) {\n\t\t\tthat.position.left = that.prevPosition.left;\n\t\t\tthat.position.top = that.prevPosition.top;\n\t\t\tthat.size.width = that.prevSize.width;\n\t\t\tthat.size.height = that.prevSize.height;\n\t\t}\n\t},\n\n\tstop: function() {\n\t\tvar that = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tco = that.containerOffset,\n\t\t\tcop = that.containerPosition,\n\t\t\tce = that.containerElement,\n\t\t\thelper = $( that.helper ),\n\t\t\tho = helper.offset(),\n\t\t\tw = helper.outerWidth() - that.sizeDiff.width,\n\t\t\th = helper.outerHeight() - that.sizeDiff.height;\n\n\t\tif ( that._helper && !o.animate && ( /relative/ ).test( ce.css( \"position\" ) ) ) {\n\t\t\t$( this ).css( {\n\t\t\t\tleft: ho.left - cop.left - co.left,\n\t\t\t\twidth: w,\n\t\t\t\theight: h\n\t\t\t} );\n\t\t}\n\n\t\tif ( that._helper && !o.animate && ( /static/ ).test( ce.css( \"position\" ) ) ) {\n\t\t\t$( this ).css( {\n\t\t\t\tleft: ho.left - cop.left - co.left,\n\t\t\t\twidth: w,\n\t\t\t\theight: h\n\t\t\t} );\n\t\t}\n\t}\n} );\n\n$.ui.plugin.add( \"resizable\", \"alsoResize\", {\n\n\tstart: function() {\n\t\tvar that = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options;\n\n\t\t$( o.alsoResize ).each( function() {\n\t\t\tvar el = $( this );\n\t\t\tel.data( \"ui-resizable-alsoresize\", {\n\t\t\t\twidth: parseFloat( el.width() ), height: parseFloat( el.height() ),\n\t\t\t\tleft: parseFloat( el.css( \"left\" ) ), top: parseFloat( el.css( \"top\" ) )\n\t\t\t} );\n\t\t} );\n\t},\n\n\tresize: function( event, ui ) {\n\t\tvar that = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tos = that.originalSize,\n\t\t\top = that.originalPosition,\n\t\t\tdelta = {\n\t\t\t\theight: ( that.size.height - os.height ) || 0,\n\t\t\t\twidth: ( that.size.width - os.width ) || 0,\n\t\t\t\ttop: ( that.position.top - op.top ) || 0,\n\t\t\t\tleft: ( that.position.left - op.left ) || 0\n\t\t\t};\n\n\t\t\t$( o.alsoResize ).each( function() {\n\t\t\t\tvar el = $( this ), start = $( this ).data( \"ui-resizable-alsoresize\" ), style = {},\n\t\t\t\t\tcss = el.parents( ui.originalElement[ 0 ] ).length ?\n\t\t\t\t\t\t\t[ \"width\", \"height\" ] :\n\t\t\t\t\t\t\t[ \"width\", \"height\", \"top\", \"left\" ];\n\n\t\t\t\t$.each( css, function( i, prop ) {\n\t\t\t\t\tvar sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );\n\t\t\t\t\tif ( sum && sum >= 0 ) {\n\t\t\t\t\t\tstyle[ prop ] = sum || null;\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t\tel.css( style );\n\t\t\t} );\n\t},\n\n\tstop: function() {\n\t\t$( this ).removeData( \"ui-resizable-alsoresize\" );\n\t}\n} );\n\n$.ui.plugin.add( \"resizable\", \"ghost\", {\n\n\tstart: function() {\n\n\t\tvar that = $( this ).resizable( \"instance\" ), cs = that.size;\n\n\t\tthat.ghost = that.originalElement.clone();\n\t\tthat.ghost.css( {\n\t\t\topacity: 0.25,\n\t\t\tdisplay: \"block\",\n\t\t\tposition: \"relative\",\n\t\t\theight: cs.height,\n\t\t\twidth: cs.width,\n\t\t\tmargin: 0,\n\t\t\tleft: 0,\n\t\t\ttop: 0\n\t\t} );\n\n\t\tthat._addClass( that.ghost, \"ui-resizable-ghost\" );\n\n\t\t// DEPRECATED\n\t\t// TODO: remove after 1.12\n\t\tif ( $.uiBackCompat !== false && typeof that.options.ghost === \"string\" ) {\n\n\t\t\t// Ghost option\n\t\t\tthat.ghost.addClass( this.options.ghost );\n\t\t}\n\n\t\tthat.ghost.appendTo( that.helper );\n\n\t},\n\n\tresize: function() {\n\t\tvar that = $( this ).resizable( \"instance\" );\n\t\tif ( that.ghost ) {\n\t\t\tthat.ghost.css( {\n\t\t\t\tposition: \"relative\",\n\t\t\t\theight: that.size.height,\n\t\t\t\twidth: that.size.width\n\t\t\t} );\n\t\t}\n\t},\n\n\tstop: function() {\n\t\tvar that = $( this ).resizable( \"instance\" );\n\t\tif ( that.ghost && that.helper ) {\n\t\t\tthat.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );\n\t\t}\n\t}\n\n} );\n\n$.ui.plugin.add( \"resizable\", \"grid\", {\n\n\tresize: function() {\n\t\tvar outerDimensions,\n\t\t\tthat = $( this ).resizable( \"instance\" ),\n\t\t\to = that.options,\n\t\t\tcs = that.size,\n\t\t\tos = that.originalSize,\n\t\t\top = that.originalPosition,\n\t\t\ta = that.axis,\n\t\t\tgrid = typeof o.grid === \"number\" ? [ o.grid, o.grid ] : o.grid,\n\t\t\tgridX = ( grid[ 0 ] || 1 ),\n\t\t\tgridY = ( grid[ 1 ] || 1 ),\n\t\t\tox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,\n\t\t\toy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,\n\t\t\tnewWidth = os.width + ox,\n\t\t\tnewHeight = os.height + oy,\n\t\t\tisMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),\n\t\t\tisMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),\n\t\t\tisMinWidth = o.minWidth && ( o.minWidth > newWidth ),\n\t\t\tisMinHeight = o.minHeight && ( o.minHeight > newHeight );\n\n\t\to.grid = grid;\n\n\t\tif ( isMinWidth ) {\n\t\t\tnewWidth += gridX;\n\t\t}\n\t\tif ( isMinHeight ) {\n\t\t\tnewHeight += gridY;\n\t\t}\n\t\tif ( isMaxWidth ) {\n\t\t\tnewWidth -= gridX;\n\t\t}\n\t\tif ( isMaxHeight ) {\n\t\t\tnewHeight -= gridY;\n\t\t}\n\n\t\tif ( /^(se|s|e)$/.test( a ) ) {\n\t\t\tthat.size.width = newWidth;\n\t\t\tthat.size.height = newHeight;\n\t\t} else if ( /^(ne)$/.test( a ) ) {\n\t\t\tthat.size.width = newWidth;\n\t\t\tthat.size.height = newHeight;\n\t\t\tthat.position.top = op.top - oy;\n\t\t} else if ( /^(sw)$/.test( a ) ) {\n\t\t\tthat.size.width = newWidth;\n\t\t\tthat.size.height = newHeight;\n\t\t\tthat.position.left = op.left - ox;\n\t\t} else {\n\t\t\tif ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {\n\t\t\t\touterDimensions = that._getPaddingPlusBorderDimensions( this );\n\t\t\t}\n\n\t\t\tif ( newHeight - gridY > 0 ) {\n\t\t\t\tthat.size.height = newHeight;\n\t\t\t\tthat.position.top = op.top - oy;\n\t\t\t} else {\n\t\t\t\tnewHeight = gridY - outerDimensions.height;\n\t\t\t\tthat.size.height = newHeight;\n\t\t\t\tthat.position.top = op.top + os.height - newHeight;\n\t\t\t}\n\t\t\tif ( newWidth - gridX > 0 ) {\n\t\t\t\tthat.size.width = newWidth;\n\t\t\t\tthat.position.left = op.left - ox;\n\t\t\t} else {\n\t\t\t\tnewWidth = gridX - outerDimensions.width;\n\t\t\t\tthat.size.width = newWidth;\n\t\t\t\tthat.position.left = op.left + os.width - newWidth;\n\t\t\t}\n\t\t}\n\t}\n\n} );\n\nvar widgetsResizable = $.ui.resizable;\n\n\n/*!\n * jQuery UI Selectable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Selectable\n//>>group: Interactions\n//>>description: Allows groups of elements to be selected with the mouse.\n//>>docs: http://api.jqueryui.com/selectable/\n//>>demos: http://jqueryui.com/selectable/\n//>>css.structure: ../../themes/base/selectable.css\n\n\n\nvar widgetsSelectable = $.widget( \"ui.selectable\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tappendTo: \"body\",\n\t\tautoRefresh: true,\n\t\tdistance: 0,\n\t\tfilter: \"*\",\n\t\ttolerance: \"touch\",\n\n\t\t// Callbacks\n\t\tselected: null,\n\t\tselecting: null,\n\t\tstart: null,\n\t\tstop: null,\n\t\tunselected: null,\n\t\tunselecting: null\n\t},\n\t_create: function() {\n\t\tvar that = this;\n\n\t\tthis._addClass( \"ui-selectable\" );\n\n\t\tthis.dragged = false;\n\n\t\t// Cache selectee children based on filter\n\t\tthis.refresh = function() {\n\t\t\tthat.elementPos = $( that.element[ 0 ] ).offset();\n\t\t\tthat.selectees = $( that.options.filter, that.element[ 0 ] );\n\t\t\tthat._addClass( that.selectees, \"ui-selectee\" );\n\t\t\tthat.selectees.each( function() {\n\t\t\t\tvar $this = $( this ),\n\t\t\t\t\tselecteeOffset = $this.offset(),\n\t\t\t\t\tpos = {\n\t\t\t\t\t\tleft: selecteeOffset.left - that.elementPos.left,\n\t\t\t\t\t\ttop: selecteeOffset.top - that.elementPos.top\n\t\t\t\t\t};\n\t\t\t\t$.data( this, \"selectable-item\", {\n\t\t\t\t\telement: this,\n\t\t\t\t\t$element: $this,\n\t\t\t\t\tleft: pos.left,\n\t\t\t\t\ttop: pos.top,\n\t\t\t\t\tright: pos.left + $this.outerWidth(),\n\t\t\t\t\tbottom: pos.top + $this.outerHeight(),\n\t\t\t\t\tstartselected: false,\n\t\t\t\t\tselected: $this.hasClass( \"ui-selected\" ),\n\t\t\t\t\tselecting: $this.hasClass( \"ui-selecting\" ),\n\t\t\t\t\tunselecting: $this.hasClass( \"ui-unselecting\" )\n\t\t\t\t} );\n\t\t\t} );\n\t\t};\n\t\tthis.refresh();\n\n\t\tthis._mouseInit();\n\n\t\tthis.helper = $( \"<div>\" );\n\t\tthis._addClass( this.helper, \"ui-selectable-helper\" );\n\t},\n\n\t_destroy: function() {\n\t\tthis.selectees.removeData( \"selectable-item\" );\n\t\tthis._mouseDestroy();\n\t},\n\n\t_mouseStart: function( event ) {\n\t\tvar that = this,\n\t\t\toptions = this.options;\n\n\t\tthis.opos = [ event.pageX, event.pageY ];\n\t\tthis.elementPos = $( this.element[ 0 ] ).offset();\n\n\t\tif ( this.options.disabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.selectees = $( options.filter, this.element[ 0 ] );\n\n\t\tthis._trigger( \"start\", event );\n\n\t\t$( options.appendTo ).append( this.helper );\n\n\t\t// position helper (lasso)\n\t\tthis.helper.css( {\n\t\t\t\"left\": event.pageX,\n\t\t\t\"top\": event.pageY,\n\t\t\t\"width\": 0,\n\t\t\t\"height\": 0\n\t\t} );\n\n\t\tif ( options.autoRefresh ) {\n\t\t\tthis.refresh();\n\t\t}\n\n\t\tthis.selectees.filter( \".ui-selected\" ).each( function() {\n\t\t\tvar selectee = $.data( this, \"selectable-item\" );\n\t\t\tselectee.startselected = true;\n\t\t\tif ( !event.metaKey && !event.ctrlKey ) {\n\t\t\t\tthat._removeClass( selectee.$element, \"ui-selected\" );\n\t\t\t\tselectee.selected = false;\n\t\t\t\tthat._addClass( selectee.$element, \"ui-unselecting\" );\n\t\t\t\tselectee.unselecting = true;\n\n\t\t\t\t// selectable UNSELECTING callback\n\t\t\t\tthat._trigger( \"unselecting\", event, {\n\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t\t$( event.target ).parents().addBack().each( function() {\n\t\t\tvar doSelect,\n\t\t\t\tselectee = $.data( this, \"selectable-item\" );\n\t\t\tif ( selectee ) {\n\t\t\t\tdoSelect = ( !event.metaKey && !event.ctrlKey ) ||\n\t\t\t\t\t!selectee.$element.hasClass( \"ui-selected\" );\n\t\t\t\tthat._removeClass( selectee.$element, doSelect ? \"ui-unselecting\" : \"ui-selected\" )\n\t\t\t\t\t._addClass( selectee.$element, doSelect ? \"ui-selecting\" : \"ui-unselecting\" );\n\t\t\t\tselectee.unselecting = !doSelect;\n\t\t\t\tselectee.selecting = doSelect;\n\t\t\t\tselectee.selected = doSelect;\n\n\t\t\t\t// selectable (UN)SELECTING callback\n\t\t\t\tif ( doSelect ) {\n\t\t\t\t\tthat._trigger( \"selecting\", event, {\n\t\t\t\t\t\tselecting: selectee.element\n\t\t\t\t\t} );\n\t\t\t\t} else {\n\t\t\t\t\tthat._trigger( \"unselecting\", event, {\n\t\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} );\n\n\t},\n\n\t_mouseDrag: function( event ) {\n\n\t\tthis.dragged = true;\n\n\t\tif ( this.options.disabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar tmp,\n\t\t\tthat = this,\n\t\t\toptions = this.options,\n\t\t\tx1 = this.opos[ 0 ],\n\t\t\ty1 = this.opos[ 1 ],\n\t\t\tx2 = event.pageX,\n\t\t\ty2 = event.pageY;\n\n\t\tif ( x1 > x2 ) { tmp = x2; x2 = x1; x1 = tmp; }\n\t\tif ( y1 > y2 ) { tmp = y2; y2 = y1; y1 = tmp; }\n\t\tthis.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );\n\n\t\tthis.selectees.each( function() {\n\t\t\tvar selectee = $.data( this, \"selectable-item\" ),\n\t\t\t\thit = false,\n\t\t\t\toffset = {};\n\n\t\t\t//prevent helper from being selected if appendTo: selectable\n\t\t\tif ( !selectee || selectee.element === that.element[ 0 ] ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\toffset.left   = selectee.left   + that.elementPos.left;\n\t\t\toffset.right  = selectee.right  + that.elementPos.left;\n\t\t\toffset.top    = selectee.top    + that.elementPos.top;\n\t\t\toffset.bottom = selectee.bottom + that.elementPos.top;\n\n\t\t\tif ( options.tolerance === \"touch\" ) {\n\t\t\t\thit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||\n                    offset.bottom < y1 ) );\n\t\t\t} else if ( options.tolerance === \"fit\" ) {\n\t\t\t\thit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&\n                    offset.bottom < y2 );\n\t\t\t}\n\n\t\t\tif ( hit ) {\n\n\t\t\t\t// SELECT\n\t\t\t\tif ( selectee.selected ) {\n\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-selected\" );\n\t\t\t\t\tselectee.selected = false;\n\t\t\t\t}\n\t\t\t\tif ( selectee.unselecting ) {\n\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-unselecting\" );\n\t\t\t\t\tselectee.unselecting = false;\n\t\t\t\t}\n\t\t\t\tif ( !selectee.selecting ) {\n\t\t\t\t\tthat._addClass( selectee.$element, \"ui-selecting\" );\n\t\t\t\t\tselectee.selecting = true;\n\n\t\t\t\t\t// selectable SELECTING callback\n\t\t\t\t\tthat._trigger( \"selecting\", event, {\n\t\t\t\t\t\tselecting: selectee.element\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// UNSELECT\n\t\t\t\tif ( selectee.selecting ) {\n\t\t\t\t\tif ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {\n\t\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-selecting\" );\n\t\t\t\t\t\tselectee.selecting = false;\n\t\t\t\t\t\tthat._addClass( selectee.$element, \"ui-selected\" );\n\t\t\t\t\t\tselectee.selected = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-selecting\" );\n\t\t\t\t\t\tselectee.selecting = false;\n\t\t\t\t\t\tif ( selectee.startselected ) {\n\t\t\t\t\t\t\tthat._addClass( selectee.$element, \"ui-unselecting\" );\n\t\t\t\t\t\t\tselectee.unselecting = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// selectable UNSELECTING callback\n\t\t\t\t\t\tthat._trigger( \"unselecting\", event, {\n\t\t\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( selectee.selected ) {\n\t\t\t\t\tif ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {\n\t\t\t\t\t\tthat._removeClass( selectee.$element, \"ui-selected\" );\n\t\t\t\t\t\tselectee.selected = false;\n\n\t\t\t\t\t\tthat._addClass( selectee.$element, \"ui-unselecting\" );\n\t\t\t\t\t\tselectee.unselecting = true;\n\n\t\t\t\t\t\t// selectable UNSELECTING callback\n\t\t\t\t\t\tthat._trigger( \"unselecting\", event, {\n\t\t\t\t\t\t\tunselecting: selectee.element\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function( event ) {\n\t\tvar that = this;\n\n\t\tthis.dragged = false;\n\n\t\t$( \".ui-unselecting\", this.element[ 0 ] ).each( function() {\n\t\t\tvar selectee = $.data( this, \"selectable-item\" );\n\t\t\tthat._removeClass( selectee.$element, \"ui-unselecting\" );\n\t\t\tselectee.unselecting = false;\n\t\t\tselectee.startselected = false;\n\t\t\tthat._trigger( \"unselected\", event, {\n\t\t\t\tunselected: selectee.element\n\t\t\t} );\n\t\t} );\n\t\t$( \".ui-selecting\", this.element[ 0 ] ).each( function() {\n\t\t\tvar selectee = $.data( this, \"selectable-item\" );\n\t\t\tthat._removeClass( selectee.$element, \"ui-selecting\" )\n\t\t\t\t._addClass( selectee.$element, \"ui-selected\" );\n\t\t\tselectee.selecting = false;\n\t\t\tselectee.selected = true;\n\t\t\tselectee.startselected = true;\n\t\t\tthat._trigger( \"selected\", event, {\n\t\t\t\tselected: selectee.element\n\t\t\t} );\n\t\t} );\n\t\tthis._trigger( \"stop\", event );\n\n\t\tthis.helper.remove();\n\n\t\treturn false;\n\t}\n\n} );\n\n\n/*!\n * jQuery UI Sortable 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Sortable\n//>>group: Interactions\n//>>description: Enables items in a list to be sorted using the mouse.\n//>>docs: http://api.jqueryui.com/sortable/\n//>>demos: http://jqueryui.com/sortable/\n//>>css.structure: ../../themes/base/sortable.css\n\n\n\nvar widgetsSortable = $.widget( \"ui.sortable\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"sort\",\n\tready: false,\n\toptions: {\n\t\tappendTo: \"parent\",\n\t\taxis: false,\n\t\tconnectWith: false,\n\t\tcontainment: false,\n\t\tcursor: \"auto\",\n\t\tcursorAt: false,\n\t\tdropOnEmpty: true,\n\t\tforcePlaceholderSize: false,\n\t\tforceHelperSize: false,\n\t\tgrid: false,\n\t\thandle: false,\n\t\thelper: \"original\",\n\t\titems: \"> *\",\n\t\topacity: false,\n\t\tplaceholder: false,\n\t\trevert: false,\n\t\tscroll: true,\n\t\tscrollSensitivity: 20,\n\t\tscrollSpeed: 20,\n\t\tscope: \"default\",\n\t\ttolerance: \"intersect\",\n\t\tzIndex: 1000,\n\n\t\t// Callbacks\n\t\tactivate: null,\n\t\tbeforeStop: null,\n\t\tchange: null,\n\t\tdeactivate: null,\n\t\tout: null,\n\t\tover: null,\n\t\treceive: null,\n\t\tremove: null,\n\t\tsort: null,\n\t\tstart: null,\n\t\tstop: null,\n\t\tupdate: null\n\t},\n\n\t_isOverAxis: function( x, reference, size ) {\n\t\treturn ( x >= reference ) && ( x < ( reference + size ) );\n\t},\n\n\t_isFloating: function( item ) {\n\t\treturn ( /left|right/ ).test( item.css( \"float\" ) ) ||\n\t\t\t( /inline|table-cell/ ).test( item.css( \"display\" ) );\n\t},\n\n\t_create: function() {\n\t\tthis.containerCache = {};\n\t\tthis._addClass( \"ui-sortable\" );\n\n\t\t//Get the items\n\t\tthis.refresh();\n\n\t\t//Let's determine the parent's offset\n\t\tthis.offset = this.element.offset();\n\n\t\t//Initialize mouse events for interaction\n\t\tthis._mouseInit();\n\n\t\tthis._setHandleClassName();\n\n\t\t//We're ready to go\n\t\tthis.ready = true;\n\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"handle\" ) {\n\t\t\tthis._setHandleClassName();\n\t\t}\n\t},\n\n\t_setHandleClassName: function() {\n\t\tvar that = this;\n\t\tthis._removeClass( this.element.find( \".ui-sortable-handle\" ), \"ui-sortable-handle\" );\n\t\t$.each( this.items, function() {\n\t\t\tthat._addClass(\n\t\t\t\tthis.instance.options.handle ?\n\t\t\t\t\tthis.item.find( this.instance.options.handle ) :\n\t\t\t\t\tthis.item,\n\t\t\t\t\"ui-sortable-handle\"\n\t\t\t);\n\t\t} );\n\t},\n\n\t_destroy: function() {\n\t\tthis._mouseDestroy();\n\n\t\tfor ( var i = this.items.length - 1; i >= 0; i-- ) {\n\t\t\tthis.items[ i ].item.removeData( this.widgetName + \"-item\" );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_mouseCapture: function( event, overrideHandle ) {\n\t\tvar currentItem = null,\n\t\t\tvalidHandle = false,\n\t\t\tthat = this;\n\n\t\tif ( this.reverting ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( this.options.disabled || this.options.type === \"static\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t//We have to refresh the items data once first\n\t\tthis._refreshItems( event );\n\n\t\t//Find out if the clicked node (or one of its parents) is a actual item in this.items\n\t\t$( event.target ).parents().each( function() {\n\t\t\tif ( $.data( this, that.widgetName + \"-item\" ) === that ) {\n\t\t\t\tcurrentItem = $( this );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} );\n\t\tif ( $.data( event.target, that.widgetName + \"-item\" ) === that ) {\n\t\t\tcurrentItem = $( event.target );\n\t\t}\n\n\t\tif ( !currentItem ) {\n\t\t\treturn false;\n\t\t}\n\t\tif ( this.options.handle && !overrideHandle ) {\n\t\t\t$( this.options.handle, currentItem ).find( \"*\" ).addBack().each( function() {\n\t\t\t\tif ( this === event.target ) {\n\t\t\t\t\tvalidHandle = true;\n\t\t\t\t}\n\t\t\t} );\n\t\t\tif ( !validHandle ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tthis.currentItem = currentItem;\n\t\tthis._removeCurrentsFromItems();\n\t\treturn true;\n\n\t},\n\n\t_mouseStart: function( event, overrideHandle, noActivation ) {\n\n\t\tvar i, body,\n\t\t\to = this.options;\n\n\t\tthis.currentContainer = this;\n\n\t\t//We only need to call refreshPositions, because the refreshItems call has been moved to\n\t\t// mouseCapture\n\t\tthis.refreshPositions();\n\n\t\t//Create and append the visible helper\n\t\tthis.helper = this._createHelper( event );\n\n\t\t//Cache the helper size\n\t\tthis._cacheHelperProportions();\n\n\t\t/*\n\t\t * - Position generation -\n\t\t * This block generates everything position related - it's the core of draggables.\n\t\t */\n\n\t\t//Cache the margins of the original element\n\t\tthis._cacheMargins();\n\n\t\t//Get the next scrolling parent\n\t\tthis.scrollParent = this.helper.scrollParent();\n\n\t\t//The element's absolute position on the page minus margins\n\t\tthis.offset = this.currentItem.offset();\n\t\tthis.offset = {\n\t\t\ttop: this.offset.top - this.margins.top,\n\t\t\tleft: this.offset.left - this.margins.left\n\t\t};\n\n\t\t$.extend( this.offset, {\n\t\t\tclick: { //Where the click happened, relative to the element\n\t\t\t\tleft: event.pageX - this.offset.left,\n\t\t\t\ttop: event.pageY - this.offset.top\n\t\t\t},\n\t\t\tparent: this._getParentOffset(),\n\n\t\t\t// This is a relative to absolute position minus the actual position calculation -\n\t\t\t// only used for relative positioned helper\n\t\t\trelative: this._getRelativeOffset()\n\t\t} );\n\n\t\t// Only after we got the offset, we can change the helper's position to absolute\n\t\t// TODO: Still need to figure out a way to make relative sorting possible\n\t\tthis.helper.css( \"position\", \"absolute\" );\n\t\tthis.cssPosition = this.helper.css( \"position\" );\n\n\t\t//Generate the original position\n\t\tthis.originalPosition = this._generatePosition( event );\n\t\tthis.originalPageX = event.pageX;\n\t\tthis.originalPageY = event.pageY;\n\n\t\t//Adjust the mouse offset relative to the helper if \"cursorAt\" is supplied\n\t\t( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );\n\n\t\t//Cache the former DOM position\n\t\tthis.domPosition = {\n\t\t\tprev: this.currentItem.prev()[ 0 ],\n\t\t\tparent: this.currentItem.parent()[ 0 ]\n\t\t};\n\n\t\t// If the helper is not the original, hide the original so it's not playing any role during\n\t\t// the drag, won't cause anything bad this way\n\t\tif ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {\n\t\t\tthis.currentItem.hide();\n\t\t}\n\n\t\t//Create the placeholder\n\t\tthis._createPlaceholder();\n\n\t\t//Set a containment if given in the options\n\t\tif ( o.containment ) {\n\t\t\tthis._setContainment();\n\t\t}\n\n\t\tif ( o.cursor && o.cursor !== \"auto\" ) { // cursor option\n\t\t\tbody = this.document.find( \"body\" );\n\n\t\t\t// Support: IE\n\t\t\tthis.storedCursor = body.css( \"cursor\" );\n\t\t\tbody.css( \"cursor\", o.cursor );\n\n\t\t\tthis.storedStylesheet =\n\t\t\t\t$( \"<style>*{ cursor: \" + o.cursor + \" !important; }</style>\" ).appendTo( body );\n\t\t}\n\n\t\tif ( o.opacity ) { // opacity option\n\t\t\tif ( this.helper.css( \"opacity\" ) ) {\n\t\t\t\tthis._storedOpacity = this.helper.css( \"opacity\" );\n\t\t\t}\n\t\t\tthis.helper.css( \"opacity\", o.opacity );\n\t\t}\n\n\t\tif ( o.zIndex ) { // zIndex option\n\t\t\tif ( this.helper.css( \"zIndex\" ) ) {\n\t\t\t\tthis._storedZIndex = this.helper.css( \"zIndex\" );\n\t\t\t}\n\t\t\tthis.helper.css( \"zIndex\", o.zIndex );\n\t\t}\n\n\t\t//Prepare scrolling\n\t\tif ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\tthis.scrollParent[ 0 ].tagName !== \"HTML\" ) {\n\t\t\tthis.overflowOffset = this.scrollParent.offset();\n\t\t}\n\n\t\t//Call callbacks\n\t\tthis._trigger( \"start\", event, this._uiHash() );\n\n\t\t//Recache the helper size\n\t\tif ( !this._preserveHelperProportions ) {\n\t\t\tthis._cacheHelperProportions();\n\t\t}\n\n\t\t//Post \"activate\" events to possible containers\n\t\tif ( !noActivation ) {\n\t\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\t\tthis.containers[ i ]._trigger( \"activate\", event, this._uiHash( this ) );\n\t\t\t}\n\t\t}\n\n\t\t//Prepare possible droppables\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.current = this;\n\t\t}\n\n\t\tif ( $.ui.ddmanager && !o.dropBehaviour ) {\n\t\t\t$.ui.ddmanager.prepareOffsets( this, event );\n\t\t}\n\n\t\tthis.dragging = true;\n\n\t\tthis._addClass( this.helper, \"ui-sortable-helper\" );\n\n\t\t// Execute the drag once - this causes the helper not to be visiblebefore getting its\n\t\t// correct position\n\t\tthis._mouseDrag( event );\n\t\treturn true;\n\n\t},\n\n\t_mouseDrag: function( event ) {\n\t\tvar i, item, itemElement, intersection,\n\t\t\to = this.options,\n\t\t\tscrolled = false;\n\n\t\t//Compute the helpers position\n\t\tthis.position = this._generatePosition( event );\n\t\tthis.positionAbs = this._convertPositionTo( \"absolute\" );\n\n\t\tif ( !this.lastPositionAbs ) {\n\t\t\tthis.lastPositionAbs = this.positionAbs;\n\t\t}\n\n\t\t//Do scrolling\n\t\tif ( this.options.scroll ) {\n\t\t\tif ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\t\tthis.scrollParent[ 0 ].tagName !== \"HTML\" ) {\n\n\t\t\t\tif ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -\n\t\t\t\t\t\tevent.pageY < o.scrollSensitivity ) {\n\t\t\t\t\tthis.scrollParent[ 0 ].scrollTop =\n\t\t\t\t\t\tscrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;\n\t\t\t\t} else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {\n\t\t\t\t\tthis.scrollParent[ 0 ].scrollTop =\n\t\t\t\t\t\tscrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;\n\t\t\t\t}\n\n\t\t\t\tif ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -\n\t\t\t\t\t\tevent.pageX < o.scrollSensitivity ) {\n\t\t\t\t\tthis.scrollParent[ 0 ].scrollLeft = scrolled =\n\t\t\t\t\t\tthis.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;\n\t\t\t\t} else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {\n\t\t\t\t\tthis.scrollParent[ 0 ].scrollLeft = scrolled =\n\t\t\t\t\t\tthis.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {\n\t\t\t\t\tscrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );\n\t\t\t\t} else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );\n\t\t\t\t}\n\n\t\t\t\tif ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {\n\t\t\t\t\tscrolled = this.document.scrollLeft(\n\t\t\t\t\t\tthis.document.scrollLeft() - o.scrollSpeed\n\t\t\t\t\t);\n\t\t\t\t} else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <\n\t\t\t\t\t\to.scrollSensitivity ) {\n\t\t\t\t\tscrolled = this.document.scrollLeft(\n\t\t\t\t\t\tthis.document.scrollLeft() + o.scrollSpeed\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {\n\t\t\t\t$.ui.ddmanager.prepareOffsets( this, event );\n\t\t\t}\n\t\t}\n\n\t\t//Regenerate the absolute position used for position checks\n\t\tthis.positionAbs = this._convertPositionTo( \"absolute\" );\n\n\t\t//Set the helper position\n\t\tif ( !this.options.axis || this.options.axis !== \"y\" ) {\n\t\t\tthis.helper[ 0 ].style.left = this.position.left + \"px\";\n\t\t}\n\t\tif ( !this.options.axis || this.options.axis !== \"x\" ) {\n\t\t\tthis.helper[ 0 ].style.top = this.position.top + \"px\";\n\t\t}\n\n\t\t//Rearrange\n\t\tfor ( i = this.items.length - 1; i >= 0; i-- ) {\n\n\t\t\t//Cache variables and intersection, continue if no intersection\n\t\t\titem = this.items[ i ];\n\t\t\titemElement = item.item[ 0 ];\n\t\t\tintersection = this._intersectsWithPointer( item );\n\t\t\tif ( !intersection ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Only put the placeholder inside the current Container, skip all\n\t\t\t// items from other containers. This works because when moving\n\t\t\t// an item from one container to another the\n\t\t\t// currentContainer is switched before the placeholder is moved.\n\t\t\t//\n\t\t\t// Without this, moving items in \"sub-sortables\" can cause\n\t\t\t// the placeholder to jitter between the outer and inner container.\n\t\t\tif ( item.instance !== this.currentContainer ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Cannot intersect with itself\n\t\t\t// no useless actions that have been done before\n\t\t\t// no action if the item moved is the parent of the item checked\n\t\t\tif ( itemElement !== this.currentItem[ 0 ] &&\n\t\t\t\tthis.placeholder[ intersection === 1 ? \"next\" : \"prev\" ]()[ 0 ] !== itemElement &&\n\t\t\t\t!$.contains( this.placeholder[ 0 ], itemElement ) &&\n\t\t\t\t( this.options.type === \"semi-dynamic\" ?\n\t\t\t\t\t!$.contains( this.element[ 0 ], itemElement ) :\n\t\t\t\t\ttrue\n\t\t\t\t)\n\t\t\t) {\n\n\t\t\t\tthis.direction = intersection === 1 ? \"down\" : \"up\";\n\n\t\t\t\tif ( this.options.tolerance === \"pointer\" || this._intersectsWithSides( item ) ) {\n\t\t\t\t\tthis._rearrange( event, item );\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tthis._trigger( \"change\", event, this._uiHash() );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t//Post events to containers\n\t\tthis._contactContainers( event );\n\n\t\t//Interconnect with droppables\n\t\tif ( $.ui.ddmanager ) {\n\t\t\t$.ui.ddmanager.drag( this, event );\n\t\t}\n\n\t\t//Call callbacks\n\t\tthis._trigger( \"sort\", event, this._uiHash() );\n\n\t\tthis.lastPositionAbs = this.positionAbs;\n\t\treturn false;\n\n\t},\n\n\t_mouseStop: function( event, noPropagation ) {\n\n\t\tif ( !event ) {\n\t\t\treturn;\n\t\t}\n\n\t\t//If we are using droppables, inform the manager about the drop\n\t\tif ( $.ui.ddmanager && !this.options.dropBehaviour ) {\n\t\t\t$.ui.ddmanager.drop( this, event );\n\t\t}\n\n\t\tif ( this.options.revert ) {\n\t\t\tvar that = this,\n\t\t\t\tcur = this.placeholder.offset(),\n\t\t\t\taxis = this.options.axis,\n\t\t\t\tanimation = {};\n\n\t\t\tif ( !axis || axis === \"x\" ) {\n\t\t\t\tanimation.left = cur.left - this.offset.parent.left - this.margins.left +\n\t\t\t\t\t( this.offsetParent[ 0 ] === this.document[ 0 ].body ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tthis.offsetParent[ 0 ].scrollLeft\n\t\t\t\t\t);\n\t\t\t}\n\t\t\tif ( !axis || axis === \"y\" ) {\n\t\t\t\tanimation.top = cur.top - this.offset.parent.top - this.margins.top +\n\t\t\t\t\t( this.offsetParent[ 0 ] === this.document[ 0 ].body ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tthis.offsetParent[ 0 ].scrollTop\n\t\t\t\t\t);\n\t\t\t}\n\t\t\tthis.reverting = true;\n\t\t\t$( this.helper ).animate(\n\t\t\t\tanimation,\n\t\t\t\tparseInt( this.options.revert, 10 ) || 500,\n\t\t\t\tfunction() {\n\t\t\t\t\tthat._clear( event );\n\t\t\t\t}\n\t\t\t);\n\t\t} else {\n\t\t\tthis._clear( event, noPropagation );\n\t\t}\n\n\t\treturn false;\n\n\t},\n\n\tcancel: function() {\n\n\t\tif ( this.dragging ) {\n\n\t\t\tthis._mouseUp( new $.Event( \"mouseup\", { target: null } ) );\n\n\t\t\tif ( this.options.helper === \"original\" ) {\n\t\t\t\tthis.currentItem.css( this._storedCSS );\n\t\t\t\tthis._removeClass( this.currentItem, \"ui-sortable-helper\" );\n\t\t\t} else {\n\t\t\t\tthis.currentItem.show();\n\t\t\t}\n\n\t\t\t//Post deactivating events to containers\n\t\t\tfor ( var i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\t\tthis.containers[ i ]._trigger( \"deactivate\", null, this._uiHash( this ) );\n\t\t\t\tif ( this.containers[ i ].containerCache.over ) {\n\t\t\t\t\tthis.containers[ i ]._trigger( \"out\", null, this._uiHash( this ) );\n\t\t\t\t\tthis.containers[ i ].containerCache.over = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\tif ( this.placeholder ) {\n\n\t\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,\n\t\t\t// it unbinds ALL events from the original node!\n\t\t\tif ( this.placeholder[ 0 ].parentNode ) {\n\t\t\t\tthis.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );\n\t\t\t}\n\t\t\tif ( this.options.helper !== \"original\" && this.helper &&\n\t\t\t\t\tthis.helper[ 0 ].parentNode ) {\n\t\t\t\tthis.helper.remove();\n\t\t\t}\n\n\t\t\t$.extend( this, {\n\t\t\t\thelper: null,\n\t\t\t\tdragging: false,\n\t\t\t\treverting: false,\n\t\t\t\t_noFinalSort: null\n\t\t\t} );\n\n\t\t\tif ( this.domPosition.prev ) {\n\t\t\t\t$( this.domPosition.prev ).after( this.currentItem );\n\t\t\t} else {\n\t\t\t\t$( this.domPosition.parent ).prepend( this.currentItem );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tserialize: function( o ) {\n\n\t\tvar items = this._getItemsAsjQuery( o && o.connected ),\n\t\t\tstr = [];\n\t\to = o || {};\n\n\t\t$( items ).each( function() {\n\t\t\tvar res = ( $( o.item || this ).attr( o.attribute || \"id\" ) || \"\" )\n\t\t\t\t.match( o.expression || ( /(.+)[\\-=_](.+)/ ) );\n\t\t\tif ( res ) {\n\t\t\t\tstr.push(\n\t\t\t\t\t( o.key || res[ 1 ] + \"[]\" ) +\n\t\t\t\t\t\"=\" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );\n\t\t\t}\n\t\t} );\n\n\t\tif ( !str.length && o.key ) {\n\t\t\tstr.push( o.key + \"=\" );\n\t\t}\n\n\t\treturn str.join( \"&\" );\n\n\t},\n\n\ttoArray: function( o ) {\n\n\t\tvar items = this._getItemsAsjQuery( o && o.connected ),\n\t\t\tret = [];\n\n\t\to = o || {};\n\n\t\titems.each( function() {\n\t\t\tret.push( $( o.item || this ).attr( o.attribute || \"id\" ) || \"\" );\n\t\t} );\n\t\treturn ret;\n\n\t},\n\n\t/* Be careful with the following core functions */\n\t_intersectsWith: function( item ) {\n\n\t\tvar x1 = this.positionAbs.left,\n\t\t\tx2 = x1 + this.helperProportions.width,\n\t\t\ty1 = this.positionAbs.top,\n\t\t\ty2 = y1 + this.helperProportions.height,\n\t\t\tl = item.left,\n\t\t\tr = l + item.width,\n\t\t\tt = item.top,\n\t\t\tb = t + item.height,\n\t\t\tdyClick = this.offset.click.top,\n\t\t\tdxClick = this.offset.click.left,\n\t\t\tisOverElementHeight = ( this.options.axis === \"x\" ) || ( ( y1 + dyClick ) > t &&\n\t\t\t\t( y1 + dyClick ) < b ),\n\t\t\tisOverElementWidth = ( this.options.axis === \"y\" ) || ( ( x1 + dxClick ) > l &&\n\t\t\t\t( x1 + dxClick ) < r ),\n\t\t\tisOverElement = isOverElementHeight && isOverElementWidth;\n\n\t\tif ( this.options.tolerance === \"pointer\" ||\n\t\t\tthis.options.forcePointerForContainers ||\n\t\t\t( this.options.tolerance !== \"pointer\" &&\n\t\t\t\tthis.helperProportions[ this.floating ? \"width\" : \"height\" ] >\n\t\t\t\titem[ this.floating ? \"width\" : \"height\" ] )\n\t\t) {\n\t\t\treturn isOverElement;\n\t\t} else {\n\n\t\t\treturn ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half\n\t\t\t\tx2 - ( this.helperProportions.width / 2 ) < r && // Left Half\n\t\t\t\tt < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half\n\t\t\t\ty2 - ( this.helperProportions.height / 2 ) < b ); // Top Half\n\n\t\t}\n\t},\n\n\t_intersectsWithPointer: function( item ) {\n\t\tvar verticalDirection, horizontalDirection,\n\t\t\tisOverElementHeight = ( this.options.axis === \"x\" ) ||\n\t\t\t\tthis._isOverAxis(\n\t\t\t\t\tthis.positionAbs.top + this.offset.click.top, item.top, item.height ),\n\t\t\tisOverElementWidth = ( this.options.axis === \"y\" ) ||\n\t\t\t\tthis._isOverAxis(\n\t\t\t\t\tthis.positionAbs.left + this.offset.click.left, item.left, item.width ),\n\t\t\tisOverElement = isOverElementHeight && isOverElementWidth;\n\n\t\tif ( !isOverElement ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tverticalDirection = this._getDragVerticalDirection();\n\t\thorizontalDirection = this._getDragHorizontalDirection();\n\n\t\treturn this.floating ?\n\t\t\t( ( horizontalDirection === \"right\" || verticalDirection === \"down\" ) ? 2 : 1 )\n\t\t\t: ( verticalDirection && ( verticalDirection === \"down\" ? 2 : 1 ) );\n\n\t},\n\n\t_intersectsWithSides: function( item ) {\n\n\t\tvar isOverBottomHalf = this._isOverAxis( this.positionAbs.top +\n\t\t\t\tthis.offset.click.top, item.top + ( item.height / 2 ), item.height ),\n\t\t\tisOverRightHalf = this._isOverAxis( this.positionAbs.left +\n\t\t\t\tthis.offset.click.left, item.left + ( item.width / 2 ), item.width ),\n\t\t\tverticalDirection = this._getDragVerticalDirection(),\n\t\t\thorizontalDirection = this._getDragHorizontalDirection();\n\n\t\tif ( this.floating && horizontalDirection ) {\n\t\t\treturn ( ( horizontalDirection === \"right\" && isOverRightHalf ) ||\n\t\t\t\t( horizontalDirection === \"left\" && !isOverRightHalf ) );\n\t\t} else {\n\t\t\treturn verticalDirection && ( ( verticalDirection === \"down\" && isOverBottomHalf ) ||\n\t\t\t\t( verticalDirection === \"up\" && !isOverBottomHalf ) );\n\t\t}\n\n\t},\n\n\t_getDragVerticalDirection: function() {\n\t\tvar delta = this.positionAbs.top - this.lastPositionAbs.top;\n\t\treturn delta !== 0 && ( delta > 0 ? \"down\" : \"up\" );\n\t},\n\n\t_getDragHorizontalDirection: function() {\n\t\tvar delta = this.positionAbs.left - this.lastPositionAbs.left;\n\t\treturn delta !== 0 && ( delta > 0 ? \"right\" : \"left\" );\n\t},\n\n\trefresh: function( event ) {\n\t\tthis._refreshItems( event );\n\t\tthis._setHandleClassName();\n\t\tthis.refreshPositions();\n\t\treturn this;\n\t},\n\n\t_connectWith: function() {\n\t\tvar options = this.options;\n\t\treturn options.connectWith.constructor === String ?\n\t\t\t[ options.connectWith ] :\n\t\t\toptions.connectWith;\n\t},\n\n\t_getItemsAsjQuery: function( connected ) {\n\n\t\tvar i, j, cur, inst,\n\t\t\titems = [],\n\t\t\tqueries = [],\n\t\t\tconnectWith = this._connectWith();\n\n\t\tif ( connectWith && connected ) {\n\t\t\tfor ( i = connectWith.length - 1; i >= 0; i-- ) {\n\t\t\t\tcur = $( connectWith[ i ], this.document[ 0 ] );\n\t\t\t\tfor ( j = cur.length - 1; j >= 0; j-- ) {\n\t\t\t\t\tinst = $.data( cur[ j ], this.widgetFullName );\n\t\t\t\t\tif ( inst && inst !== this && !inst.options.disabled ) {\n\t\t\t\t\t\tqueries.push( [ $.isFunction( inst.options.items ) ?\n\t\t\t\t\t\t\tinst.options.items.call( inst.element ) :\n\t\t\t\t\t\t\t$( inst.options.items, inst.element )\n\t\t\t\t\t\t\t\t.not( \".ui-sortable-helper\" )\n\t\t\t\t\t\t\t\t.not( \".ui-sortable-placeholder\" ), inst ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tqueries.push( [ $.isFunction( this.options.items ) ?\n\t\t\tthis.options.items\n\t\t\t\t.call( this.element, null, { options: this.options, item: this.currentItem } ) :\n\t\t\t$( this.options.items, this.element )\n\t\t\t\t.not( \".ui-sortable-helper\" )\n\t\t\t\t.not( \".ui-sortable-placeholder\" ), this ] );\n\n\t\tfunction addItems() {\n\t\t\titems.push( this );\n\t\t}\n\t\tfor ( i = queries.length - 1; i >= 0; i-- ) {\n\t\t\tqueries[ i ][ 0 ].each( addItems );\n\t\t}\n\n\t\treturn $( items );\n\n\t},\n\n\t_removeCurrentsFromItems: function() {\n\n\t\tvar list = this.currentItem.find( \":data(\" + this.widgetName + \"-item)\" );\n\n\t\tthis.items = $.grep( this.items, function( item ) {\n\t\t\tfor ( var j = 0; j < list.length; j++ ) {\n\t\t\t\tif ( list[ j ] === item.item[ 0 ] ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} );\n\n\t},\n\n\t_refreshItems: function( event ) {\n\n\t\tthis.items = [];\n\t\tthis.containers = [ this ];\n\n\t\tvar i, j, cur, inst, targetData, _queries, item, queriesLength,\n\t\t\titems = this.items,\n\t\t\tqueries = [ [ $.isFunction( this.options.items ) ?\n\t\t\t\tthis.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :\n\t\t\t\t$( this.options.items, this.element ), this ] ],\n\t\t\tconnectWith = this._connectWith();\n\n\t\t//Shouldn't be run the first time through due to massive slow-down\n\t\tif ( connectWith && this.ready ) {\n\t\t\tfor ( i = connectWith.length - 1; i >= 0; i-- ) {\n\t\t\t\tcur = $( connectWith[ i ], this.document[ 0 ] );\n\t\t\t\tfor ( j = cur.length - 1; j >= 0; j-- ) {\n\t\t\t\t\tinst = $.data( cur[ j ], this.widgetFullName );\n\t\t\t\t\tif ( inst && inst !== this && !inst.options.disabled ) {\n\t\t\t\t\t\tqueries.push( [ $.isFunction( inst.options.items ) ?\n\t\t\t\t\t\t\tinst.options.items\n\t\t\t\t\t\t\t\t.call( inst.element[ 0 ], event, { item: this.currentItem } ) :\n\t\t\t\t\t\t\t$( inst.options.items, inst.element ), inst ] );\n\t\t\t\t\t\tthis.containers.push( inst );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor ( i = queries.length - 1; i >= 0; i-- ) {\n\t\t\ttargetData = queries[ i ][ 1 ];\n\t\t\t_queries = queries[ i ][ 0 ];\n\n\t\t\tfor ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {\n\t\t\t\titem = $( _queries[ j ] );\n\n\t\t\t\t// Data for target checking (mouse manager)\n\t\t\t\titem.data( this.widgetName + \"-item\", targetData );\n\n\t\t\t\titems.push( {\n\t\t\t\t\titem: item,\n\t\t\t\t\tinstance: targetData,\n\t\t\t\t\twidth: 0, height: 0,\n\t\t\t\t\tleft: 0, top: 0\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t},\n\n\trefreshPositions: function( fast ) {\n\n\t\t// Determine whether items are being displayed horizontally\n\t\tthis.floating = this.items.length ?\n\t\t\tthis.options.axis === \"x\" || this._isFloating( this.items[ 0 ].item ) :\n\t\t\tfalse;\n\n\t\t//This has to be redone because due to the item being moved out/into the offsetParent,\n\t\t// the offsetParent's position will change\n\t\tif ( this.offsetParent && this.helper ) {\n\t\t\tthis.offset.parent = this._getParentOffset();\n\t\t}\n\n\t\tvar i, item, t, p;\n\n\t\tfor ( i = this.items.length - 1; i >= 0; i-- ) {\n\t\t\titem = this.items[ i ];\n\n\t\t\t//We ignore calculating positions of all connected containers when we're not over them\n\t\t\tif ( item.instance !== this.currentContainer && this.currentContainer &&\n\t\t\t\t\titem.item[ 0 ] !== this.currentItem[ 0 ] ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tt = this.options.toleranceElement ?\n\t\t\t\t$( this.options.toleranceElement, item.item ) :\n\t\t\t\titem.item;\n\n\t\t\tif ( !fast ) {\n\t\t\t\titem.width = t.outerWidth();\n\t\t\t\titem.height = t.outerHeight();\n\t\t\t}\n\n\t\t\tp = t.offset();\n\t\t\titem.left = p.left;\n\t\t\titem.top = p.top;\n\t\t}\n\n\t\tif ( this.options.custom && this.options.custom.refreshContainers ) {\n\t\t\tthis.options.custom.refreshContainers.call( this );\n\t\t} else {\n\t\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\t\tp = this.containers[ i ].element.offset();\n\t\t\t\tthis.containers[ i ].containerCache.left = p.left;\n\t\t\t\tthis.containers[ i ].containerCache.top = p.top;\n\t\t\t\tthis.containers[ i ].containerCache.width =\n\t\t\t\t\tthis.containers[ i ].element.outerWidth();\n\t\t\t\tthis.containers[ i ].containerCache.height =\n\t\t\t\t\tthis.containers[ i ].element.outerHeight();\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t_createPlaceholder: function( that ) {\n\t\tthat = that || this;\n\t\tvar className,\n\t\t\to = that.options;\n\n\t\tif ( !o.placeholder || o.placeholder.constructor === String ) {\n\t\t\tclassName = o.placeholder;\n\t\t\to.placeholder = {\n\t\t\t\telement: function() {\n\n\t\t\t\t\tvar nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(),\n\t\t\t\t\t\telement = $( \"<\" + nodeName + \">\", that.document[ 0 ] );\n\n\t\t\t\t\t\tthat._addClass( element, \"ui-sortable-placeholder\",\n\t\t\t\t\t\t\t\tclassName || that.currentItem[ 0 ].className )\n\t\t\t\t\t\t\t._removeClass( element, \"ui-sortable-helper\" );\n\n\t\t\t\t\tif ( nodeName === \"tbody\" ) {\n\t\t\t\t\t\tthat._createTrPlaceholder(\n\t\t\t\t\t\t\tthat.currentItem.find( \"tr\" ).eq( 0 ),\n\t\t\t\t\t\t\t$( \"<tr>\", that.document[ 0 ] ).appendTo( element )\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if ( nodeName === \"tr\" ) {\n\t\t\t\t\t\tthat._createTrPlaceholder( that.currentItem, element );\n\t\t\t\t\t} else if ( nodeName === \"img\" ) {\n\t\t\t\t\t\telement.attr( \"src\", that.currentItem.attr( \"src\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !className ) {\n\t\t\t\t\t\telement.css( \"visibility\", \"hidden\" );\n\t\t\t\t\t}\n\n\t\t\t\t\treturn element;\n\t\t\t\t},\n\t\t\t\tupdate: function( container, p ) {\n\n\t\t\t\t\t// 1. If a className is set as 'placeholder option, we don't force sizes -\n\t\t\t\t\t// the class is responsible for that\n\t\t\t\t\t// 2. The option 'forcePlaceholderSize can be enabled to force it even if a\n\t\t\t\t\t// class name is specified\n\t\t\t\t\tif ( className && !o.forcePlaceholderSize ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t//If the element doesn't have a actual height by itself (without styles coming\n\t\t\t\t\t// from a stylesheet), it receives the inline height from the dragged item\n\t\t\t\t\tif ( !p.height() ) {\n\t\t\t\t\t\tp.height(\n\t\t\t\t\t\t\tthat.currentItem.innerHeight() -\n\t\t\t\t\t\t\tparseInt( that.currentItem.css( \"paddingTop\" ) || 0, 10 ) -\n\t\t\t\t\t\t\tparseInt( that.currentItem.css( \"paddingBottom\" ) || 0, 10 ) );\n\t\t\t\t\t}\n\t\t\t\t\tif ( !p.width() ) {\n\t\t\t\t\t\tp.width(\n\t\t\t\t\t\t\tthat.currentItem.innerWidth() -\n\t\t\t\t\t\t\tparseInt( that.currentItem.css( \"paddingLeft\" ) || 0, 10 ) -\n\t\t\t\t\t\t\tparseInt( that.currentItem.css( \"paddingRight\" ) || 0, 10 ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t//Create the placeholder\n\t\tthat.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );\n\n\t\t//Append it after the actual current item\n\t\tthat.currentItem.after( that.placeholder );\n\n\t\t//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)\n\t\to.placeholder.update( that, that.placeholder );\n\n\t},\n\n\t_createTrPlaceholder: function( sourceTr, targetTr ) {\n\t\tvar that = this;\n\n\t\tsourceTr.children().each( function() {\n\t\t\t$( \"<td>&#160;</td>\", that.document[ 0 ] )\n\t\t\t\t.attr( \"colspan\", $( this ).attr( \"colspan\" ) || 1 )\n\t\t\t\t.appendTo( targetTr );\n\t\t} );\n\t},\n\n\t_contactContainers: function( event ) {\n\t\tvar i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,\n\t\t\tfloating, axis,\n\t\t\tinnermostContainer = null,\n\t\t\tinnermostIndex = null;\n\n\t\t// Get innermost container that intersects with item\n\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\n\t\t\t// Never consider a container that's located within the item itself\n\t\t\tif ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( this._intersectsWith( this.containers[ i ].containerCache ) ) {\n\n\t\t\t\t// If we've already found a container and it's more \"inner\" than this, then continue\n\t\t\t\tif ( innermostContainer &&\n\t\t\t\t\t\t$.contains(\n\t\t\t\t\t\t\tthis.containers[ i ].element[ 0 ],\n\t\t\t\t\t\t\tinnermostContainer.element[ 0 ] ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tinnermostContainer = this.containers[ i ];\n\t\t\t\tinnermostIndex = i;\n\n\t\t\t} else {\n\n\t\t\t\t// container doesn't intersect. trigger \"out\" event if necessary\n\t\t\t\tif ( this.containers[ i ].containerCache.over ) {\n\t\t\t\t\tthis.containers[ i ]._trigger( \"out\", event, this._uiHash( this ) );\n\t\t\t\t\tthis.containers[ i ].containerCache.over = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t\t// If no intersecting containers found, return\n\t\tif ( !innermostContainer ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Move the item into the container if it's not there already\n\t\tif ( this.containers.length === 1 ) {\n\t\t\tif ( !this.containers[ innermostIndex ].containerCache.over ) {\n\t\t\t\tthis.containers[ innermostIndex ]._trigger( \"over\", event, this._uiHash( this ) );\n\t\t\t\tthis.containers[ innermostIndex ].containerCache.over = 1;\n\t\t\t}\n\t\t} else {\n\n\t\t\t// When entering a new container, we will find the item with the least distance and\n\t\t\t// append our item near it\n\t\t\tdist = 10000;\n\t\t\titemWithLeastDistance = null;\n\t\t\tfloating = innermostContainer.floating || this._isFloating( this.currentItem );\n\t\t\tposProperty = floating ? \"left\" : \"top\";\n\t\t\tsizeProperty = floating ? \"width\" : \"height\";\n\t\t\taxis = floating ? \"pageX\" : \"pageY\";\n\n\t\t\tfor ( j = this.items.length - 1; j >= 0; j-- ) {\n\t\t\t\tif ( !$.contains(\n\t\t\t\t\t\tthis.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tcur = this.items[ j ].item.offset()[ posProperty ];\n\t\t\t\tnearBottom = false;\n\t\t\t\tif ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {\n\t\t\t\t\tnearBottom = true;\n\t\t\t\t}\n\n\t\t\t\tif ( Math.abs( event[ axis ] - cur ) < dist ) {\n\t\t\t\t\tdist = Math.abs( event[ axis ] - cur );\n\t\t\t\t\titemWithLeastDistance = this.items[ j ];\n\t\t\t\t\tthis.direction = nearBottom ? \"up\" : \"down\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//Check if dropOnEmpty is enabled\n\t\t\tif ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this.currentContainer === this.containers[ innermostIndex ] ) {\n\t\t\t\tif ( !this.currentContainer.containerCache.over ) {\n\t\t\t\t\tthis.containers[ innermostIndex ]._trigger( \"over\", event, this._uiHash() );\n\t\t\t\t\tthis.currentContainer.containerCache.over = 1;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\titemWithLeastDistance ?\n\t\t\t\tthis._rearrange( event, itemWithLeastDistance, null, true ) :\n\t\t\t\tthis._rearrange( event, null, this.containers[ innermostIndex ].element, true );\n\t\t\tthis._trigger( \"change\", event, this._uiHash() );\n\t\t\tthis.containers[ innermostIndex ]._trigger( \"change\", event, this._uiHash( this ) );\n\t\t\tthis.currentContainer = this.containers[ innermostIndex ];\n\n\t\t\t//Update the placeholder\n\t\t\tthis.options.placeholder.update( this.currentContainer, this.placeholder );\n\n\t\t\tthis.containers[ innermostIndex ]._trigger( \"over\", event, this._uiHash( this ) );\n\t\t\tthis.containers[ innermostIndex ].containerCache.over = 1;\n\t\t}\n\n\t},\n\n\t_createHelper: function( event ) {\n\n\t\tvar o = this.options,\n\t\t\thelper = $.isFunction( o.helper ) ?\n\t\t\t\t$( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :\n\t\t\t\t( o.helper === \"clone\" ? this.currentItem.clone() : this.currentItem );\n\n\t\t//Add the helper to the DOM if that didn't happen already\n\t\tif ( !helper.parents( \"body\" ).length ) {\n\t\t\t$( o.appendTo !== \"parent\" ?\n\t\t\t\to.appendTo :\n\t\t\t\tthis.currentItem[ 0 ].parentNode )[ 0 ].appendChild( helper[ 0 ] );\n\t\t}\n\n\t\tif ( helper[ 0 ] === this.currentItem[ 0 ] ) {\n\t\t\tthis._storedCSS = {\n\t\t\t\twidth: this.currentItem[ 0 ].style.width,\n\t\t\t\theight: this.currentItem[ 0 ].style.height,\n\t\t\t\tposition: this.currentItem.css( \"position\" ),\n\t\t\t\ttop: this.currentItem.css( \"top\" ),\n\t\t\t\tleft: this.currentItem.css( \"left\" )\n\t\t\t};\n\t\t}\n\n\t\tif ( !helper[ 0 ].style.width || o.forceHelperSize ) {\n\t\t\thelper.width( this.currentItem.width() );\n\t\t}\n\t\tif ( !helper[ 0 ].style.height || o.forceHelperSize ) {\n\t\t\thelper.height( this.currentItem.height() );\n\t\t}\n\n\t\treturn helper;\n\n\t},\n\n\t_adjustOffsetFromHelper: function( obj ) {\n\t\tif ( typeof obj === \"string\" ) {\n\t\t\tobj = obj.split( \" \" );\n\t\t}\n\t\tif ( $.isArray( obj ) ) {\n\t\t\tobj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };\n\t\t}\n\t\tif ( \"left\" in obj ) {\n\t\t\tthis.offset.click.left = obj.left + this.margins.left;\n\t\t}\n\t\tif ( \"right\" in obj ) {\n\t\t\tthis.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\n\t\t}\n\t\tif ( \"top\" in obj ) {\n\t\t\tthis.offset.click.top = obj.top + this.margins.top;\n\t\t}\n\t\tif ( \"bottom\" in obj ) {\n\t\t\tthis.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\n\t\t}\n\t},\n\n\t_getParentOffset: function() {\n\n\t\t//Get the offsetParent and cache its position\n\t\tthis.offsetParent = this.helper.offsetParent();\n\t\tvar po = this.offsetParent.offset();\n\n\t\t// This is a special case where we need to modify a offset calculated on start, since the\n\t\t// following happened:\n\t\t// 1. The position of the helper is absolute, so it's position is calculated based on the\n\t\t// next positioned parent\n\t\t// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't\n\t\t// the document, which means that the scroll is included in the initial calculation of the\n\t\t// offset of the parent, and never recalculated upon drag\n\t\tif ( this.cssPosition === \"absolute\" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\t$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {\n\t\t\tpo.left += this.scrollParent.scrollLeft();\n\t\t\tpo.top += this.scrollParent.scrollTop();\n\t\t}\n\n\t\t// This needs to be actually done for all browsers, since pageX/pageY includes this\n\t\t// information with an ugly IE fix\n\t\tif ( this.offsetParent[ 0 ] === this.document[ 0 ].body ||\n\t\t\t\t( this.offsetParent[ 0 ].tagName &&\n\t\t\t\tthis.offsetParent[ 0 ].tagName.toLowerCase() === \"html\" && $.ui.ie ) ) {\n\t\t\tpo = { top: 0, left: 0 };\n\t\t}\n\n\t\treturn {\n\t\t\ttop: po.top + ( parseInt( this.offsetParent.css( \"borderTopWidth\" ), 10 ) || 0 ),\n\t\t\tleft: po.left + ( parseInt( this.offsetParent.css( \"borderLeftWidth\" ), 10 ) || 0 )\n\t\t};\n\n\t},\n\n\t_getRelativeOffset: function() {\n\n\t\tif ( this.cssPosition === \"relative\" ) {\n\t\t\tvar p = this.currentItem.position();\n\t\t\treturn {\n\t\t\t\ttop: p.top - ( parseInt( this.helper.css( \"top\" ), 10 ) || 0 ) +\n\t\t\t\t\tthis.scrollParent.scrollTop(),\n\t\t\t\tleft: p.left - ( parseInt( this.helper.css( \"left\" ), 10 ) || 0 ) +\n\t\t\t\t\tthis.scrollParent.scrollLeft()\n\t\t\t};\n\t\t} else {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t},\n\n\t_cacheMargins: function() {\n\t\tthis.margins = {\n\t\t\tleft: ( parseInt( this.currentItem.css( \"marginLeft\" ), 10 ) || 0 ),\n\t\t\ttop: ( parseInt( this.currentItem.css( \"marginTop\" ), 10 ) || 0 )\n\t\t};\n\t},\n\n\t_cacheHelperProportions: function() {\n\t\tthis.helperProportions = {\n\t\t\twidth: this.helper.outerWidth(),\n\t\t\theight: this.helper.outerHeight()\n\t\t};\n\t},\n\n\t_setContainment: function() {\n\n\t\tvar ce, co, over,\n\t\t\to = this.options;\n\t\tif ( o.containment === \"parent\" ) {\n\t\t\to.containment = this.helper[ 0 ].parentNode;\n\t\t}\n\t\tif ( o.containment === \"document\" || o.containment === \"window\" ) {\n\t\t\tthis.containment = [\n\t\t\t\t0 - this.offset.relative.left - this.offset.parent.left,\n\t\t\t\t0 - this.offset.relative.top - this.offset.parent.top,\n\t\t\t\to.containment === \"document\" ?\n\t\t\t\t\tthis.document.width() :\n\t\t\t\t\tthis.window.width() - this.helperProportions.width - this.margins.left,\n\t\t\t\t( o.containment === \"document\" ?\n\t\t\t\t\t( this.document.height() || document.body.parentNode.scrollHeight ) :\n\t\t\t\t\tthis.window.height() || this.document[ 0 ].body.parentNode.scrollHeight\n\t\t\t\t) - this.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t}\n\n\t\tif ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {\n\t\t\tce = $( o.containment )[ 0 ];\n\t\t\tco = $( o.containment ).offset();\n\t\t\tover = ( $( ce ).css( \"overflow\" ) !== \"hidden\" );\n\n\t\t\tthis.containment = [\n\t\t\t\tco.left + ( parseInt( $( ce ).css( \"borderLeftWidth\" ), 10 ) || 0 ) +\n\t\t\t\t\t( parseInt( $( ce ).css( \"paddingLeft\" ), 10 ) || 0 ) - this.margins.left,\n\t\t\t\tco.top + ( parseInt( $( ce ).css( \"borderTopWidth\" ), 10 ) || 0 ) +\n\t\t\t\t\t( parseInt( $( ce ).css( \"paddingTop\" ), 10 ) || 0 ) - this.margins.top,\n\t\t\t\tco.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -\n\t\t\t\t\t( parseInt( $( ce ).css( \"borderLeftWidth\" ), 10 ) || 0 ) -\n\t\t\t\t\t( parseInt( $( ce ).css( \"paddingRight\" ), 10 ) || 0 ) -\n\t\t\t\t\tthis.helperProportions.width - this.margins.left,\n\t\t\t\tco.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -\n\t\t\t\t\t( parseInt( $( ce ).css( \"borderTopWidth\" ), 10 ) || 0 ) -\n\t\t\t\t\t( parseInt( $( ce ).css( \"paddingBottom\" ), 10 ) || 0 ) -\n\t\t\t\t\tthis.helperProportions.height - this.margins.top\n\t\t\t];\n\t\t}\n\n\t},\n\n\t_convertPositionTo: function( d, pos ) {\n\n\t\tif ( !pos ) {\n\t\t\tpos = this.position;\n\t\t}\n\t\tvar mod = d === \"absolute\" ? 1 : -1,\n\t\t\tscroll = this.cssPosition === \"absolute\" &&\n\t\t\t\t!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\t$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?\n\t\t\t\t\tthis.offsetParent :\n\t\t\t\t\tthis.scrollParent,\n\t\t\tscrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );\n\n\t\treturn {\n\t\t\ttop: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpos.top\t+\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.top * mod +\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.top * mod -\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.scrollParent.scrollTop() :\n\t\t\t\t\t( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )\n\t\t\t),\n\t\t\tleft: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpos.left +\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.left * mod +\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.left * mod\t-\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :\n\t\t\t\t\tscroll.scrollLeft() ) * mod )\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_generatePosition: function( event ) {\n\n\t\tvar top, left,\n\t\t\to = this.options,\n\t\t\tpageX = event.pageX,\n\t\t\tpageY = event.pageY,\n\t\t\tscroll = this.cssPosition === \"absolute\" &&\n\t\t\t\t!( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\t$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?\n\t\t\t\t\tthis.offsetParent :\n\t\t\t\t\tthis.scrollParent,\n\t\t\t\tscrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );\n\n\t\t// This is another very weird special case that only happens for relative elements:\n\t\t// 1. If the css position is relative\n\t\t// 2. and the scroll parent is the document or similar to the offset parent\n\t\t// we have to refresh the relative offset during the scroll so there are no jumps\n\t\tif ( this.cssPosition === \"relative\" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&\n\t\t\t\tthis.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {\n\t\t\tthis.offset.relative = this._getRelativeOffset();\n\t\t}\n\n\t\t/*\n\t\t * - Position constraining -\n\t\t * Constrain the position to a mix of grid, containment.\n\t\t */\n\n\t\tif ( this.originalPosition ) { //If we are not dragging yet, we won't check for options\n\n\t\t\tif ( this.containment ) {\n\t\t\t\tif ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {\n\t\t\t\t\tpageX = this.containment[ 0 ] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {\n\t\t\t\t\tpageY = this.containment[ 1 ] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t\tif ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {\n\t\t\t\t\tpageX = this.containment[ 2 ] + this.offset.click.left;\n\t\t\t\t}\n\t\t\t\tif ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {\n\t\t\t\t\tpageY = this.containment[ 3 ] + this.offset.click.top;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( o.grid ) {\n\t\t\t\ttop = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /\n\t\t\t\t\to.grid[ 1 ] ) * o.grid[ 1 ];\n\t\t\t\tpageY = this.containment ?\n\t\t\t\t\t( ( top - this.offset.click.top >= this.containment[ 1 ] &&\n\t\t\t\t\t\ttop - this.offset.click.top <= this.containment[ 3 ] ) ?\n\t\t\t\t\t\t\ttop :\n\t\t\t\t\t\t\t( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?\n\t\t\t\t\t\t\t\ttop - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :\n\t\t\t\t\t\t\t\ttop;\n\n\t\t\t\tleft = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /\n\t\t\t\t\to.grid[ 0 ] ) * o.grid[ 0 ];\n\t\t\t\tpageX = this.containment ?\n\t\t\t\t\t( ( left - this.offset.click.left >= this.containment[ 0 ] &&\n\t\t\t\t\t\tleft - this.offset.click.left <= this.containment[ 2 ] ) ?\n\t\t\t\t\t\t\tleft :\n\t\t\t\t\t\t\t( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?\n\t\t\t\t\t\t\t\tleft - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :\n\t\t\t\t\t\t\t\tleft;\n\t\t\t}\n\n\t\t}\n\n\t\treturn {\n\t\t\ttop: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpageY -\n\n\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.click.top -\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.top -\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.top +\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.scrollParent.scrollTop() :\n\t\t\t\t\t( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )\n\t\t\t),\n\t\t\tleft: (\n\n\t\t\t\t// The absolute mouse position\n\t\t\t\tpageX -\n\n\t\t\t\t// Click offset (relative to the element)\n\t\t\t\tthis.offset.click.left -\n\n\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n\t\t\t\tthis.offset.relative.left -\n\n\t\t\t\t// The offsetParent's offset without borders (offset + border)\n\t\t\t\tthis.offset.parent.left +\n\t\t\t\t( ( this.cssPosition === \"fixed\" ?\n\t\t\t\t\t-this.scrollParent.scrollLeft() :\n\t\t\t\t\tscrollIsRootNode ? 0 : scroll.scrollLeft() ) )\n\t\t\t)\n\t\t};\n\n\t},\n\n\t_rearrange: function( event, i, a, hardRefresh ) {\n\n\t\ta ? a[ 0 ].appendChild( this.placeholder[ 0 ] ) :\n\t\t\ti.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],\n\t\t\t\t( this.direction === \"down\" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );\n\n\t\t//Various things done here to improve the performance:\n\t\t// 1. we create a setTimeout, that calls refreshPositions\n\t\t// 2. on the instance, we have a counter variable, that get's higher after every append\n\t\t// 3. on the local scope, we copy the counter variable, and check in the timeout,\n\t\t// if it's still the same\n\t\t// 4. this lets only the last addition to the timeout stack through\n\t\tthis.counter = this.counter ? ++this.counter : 1;\n\t\tvar counter = this.counter;\n\n\t\tthis._delay( function() {\n\t\t\tif ( counter === this.counter ) {\n\n\t\t\t\t//Precompute after each DOM insertion, NOT on mousemove\n\t\t\t\tthis.refreshPositions( !hardRefresh );\n\t\t\t}\n\t\t} );\n\n\t},\n\n\t_clear: function( event, noPropagation ) {\n\n\t\tthis.reverting = false;\n\n\t\t// We delay all events that have to be triggered to after the point where the placeholder\n\t\t// has been removed and everything else normalized again\n\t\tvar i,\n\t\t\tdelayedTriggers = [];\n\n\t\t// We first have to update the dom position of the actual currentItem\n\t\t// Note: don't do it if the current item is already removed (by a user), or it gets\n\t\t// reappended (see #4088)\n\t\tif ( !this._noFinalSort && this.currentItem.parent().length ) {\n\t\t\tthis.placeholder.before( this.currentItem );\n\t\t}\n\t\tthis._noFinalSort = null;\n\n\t\tif ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {\n\t\t\tfor ( i in this._storedCSS ) {\n\t\t\t\tif ( this._storedCSS[ i ] === \"auto\" || this._storedCSS[ i ] === \"static\" ) {\n\t\t\t\t\tthis._storedCSS[ i ] = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.currentItem.css( this._storedCSS );\n\t\t\tthis._removeClass( this.currentItem, \"ui-sortable-helper\" );\n\t\t} else {\n\t\t\tthis.currentItem.show();\n\t\t}\n\n\t\tif ( this.fromOutside && !noPropagation ) {\n\t\t\tdelayedTriggers.push( function( event ) {\n\t\t\t\tthis._trigger( \"receive\", event, this._uiHash( this.fromOutside ) );\n\t\t\t} );\n\t\t}\n\t\tif ( ( this.fromOutside ||\n\t\t\t\tthis.domPosition.prev !==\n\t\t\t\tthis.currentItem.prev().not( \".ui-sortable-helper\" )[ 0 ] ||\n\t\t\t\tthis.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {\n\n\t\t\t// Trigger update callback if the DOM position has changed\n\t\t\tdelayedTriggers.push( function( event ) {\n\t\t\t\tthis._trigger( \"update\", event, this._uiHash() );\n\t\t\t} );\n\t\t}\n\n\t\t// Check if the items Container has Changed and trigger appropriate\n\t\t// events.\n\t\tif ( this !== this.currentContainer ) {\n\t\t\tif ( !noPropagation ) {\n\t\t\t\tdelayedTriggers.push( function( event ) {\n\t\t\t\t\tthis._trigger( \"remove\", event, this._uiHash() );\n\t\t\t\t} );\n\t\t\t\tdelayedTriggers.push( ( function( c ) {\n\t\t\t\t\treturn function( event ) {\n\t\t\t\t\t\tc._trigger( \"receive\", event, this._uiHash( this ) );\n\t\t\t\t\t};\n\t\t\t\t} ).call( this, this.currentContainer ) );\n\t\t\t\tdelayedTriggers.push( ( function( c ) {\n\t\t\t\t\treturn function( event ) {\n\t\t\t\t\t\tc._trigger( \"update\", event, this._uiHash( this ) );\n\t\t\t\t\t};\n\t\t\t\t} ).call( this, this.currentContainer ) );\n\t\t\t}\n\t\t}\n\n\t\t//Post events to containers\n\t\tfunction delayEvent( type, instance, container ) {\n\t\t\treturn function( event ) {\n\t\t\t\tcontainer._trigger( type, event, instance._uiHash( instance ) );\n\t\t\t};\n\t\t}\n\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n\t\t\tif ( !noPropagation ) {\n\t\t\t\tdelayedTriggers.push( delayEvent( \"deactivate\", this, this.containers[ i ] ) );\n\t\t\t}\n\t\t\tif ( this.containers[ i ].containerCache.over ) {\n\t\t\t\tdelayedTriggers.push( delayEvent( \"out\", this, this.containers[ i ] ) );\n\t\t\t\tthis.containers[ i ].containerCache.over = 0;\n\t\t\t}\n\t\t}\n\n\t\t//Do what was originally in plugins\n\t\tif ( this.storedCursor ) {\n\t\t\tthis.document.find( \"body\" ).css( \"cursor\", this.storedCursor );\n\t\t\tthis.storedStylesheet.remove();\n\t\t}\n\t\tif ( this._storedOpacity ) {\n\t\t\tthis.helper.css( \"opacity\", this._storedOpacity );\n\t\t}\n\t\tif ( this._storedZIndex ) {\n\t\t\tthis.helper.css( \"zIndex\", this._storedZIndex === \"auto\" ? \"\" : this._storedZIndex );\n\t\t}\n\n\t\tthis.dragging = false;\n\n\t\tif ( !noPropagation ) {\n\t\t\tthis._trigger( \"beforeStop\", event, this._uiHash() );\n\t\t}\n\n\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,\n\t\t// it unbinds ALL events from the original node!\n\t\tthis.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );\n\n\t\tif ( !this.cancelHelperRemoval ) {\n\t\t\tif ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {\n\t\t\t\tthis.helper.remove();\n\t\t\t}\n\t\t\tthis.helper = null;\n\t\t}\n\n\t\tif ( !noPropagation ) {\n\t\t\tfor ( i = 0; i < delayedTriggers.length; i++ ) {\n\n\t\t\t\t// Trigger all delayed events\n\t\t\t\tdelayedTriggers[ i ].call( this, event );\n\t\t\t}\n\t\t\tthis._trigger( \"stop\", event, this._uiHash() );\n\t\t}\n\n\t\tthis.fromOutside = false;\n\t\treturn !this.cancelHelperRemoval;\n\n\t},\n\n\t_trigger: function() {\n\t\tif ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {\n\t\t\tthis.cancel();\n\t\t}\n\t},\n\n\t_uiHash: function( _inst ) {\n\t\tvar inst = _inst || this;\n\t\treturn {\n\t\t\thelper: inst.helper,\n\t\t\tplaceholder: inst.placeholder || $( [] ),\n\t\t\tposition: inst.position,\n\t\t\toriginalPosition: inst.originalPosition,\n\t\t\toffset: inst.positionAbs,\n\t\t\titem: inst.currentItem,\n\t\t\tsender: _inst ? _inst.element : null\n\t\t};\n\t}\n\n} );\n\n\n/*!\n * jQuery UI Accordion 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Accordion\n//>>group: Widgets\n// jscs:disable maximumLineLength\n//>>description: Displays collapsible content panels for presenting information in a limited amount of space.\n// jscs:enable maximumLineLength\n//>>docs: http://api.jqueryui.com/accordion/\n//>>demos: http://jqueryui.com/accordion/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/accordion.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\nvar widgetsAccordion = $.widget( \"ui.accordion\", {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tactive: 0,\n\t\tanimate: {},\n\t\tclasses: {\n\t\t\t\"ui-accordion-header\": \"ui-corner-top\",\n\t\t\t\"ui-accordion-header-collapsed\": \"ui-corner-all\",\n\t\t\t\"ui-accordion-content\": \"ui-corner-bottom\"\n\t\t},\n\t\tcollapsible: false,\n\t\tevent: \"click\",\n\t\theader: \"> li > :first-child, > :not(li):even\",\n\t\theightStyle: \"auto\",\n\t\ticons: {\n\t\t\tactiveHeader: \"ui-icon-triangle-1-s\",\n\t\t\theader: \"ui-icon-triangle-1-e\"\n\t\t},\n\n\t\t// Callbacks\n\t\tactivate: null,\n\t\tbeforeActivate: null\n\t},\n\n\thideProps: {\n\t\tborderTopWidth: \"hide\",\n\t\tborderBottomWidth: \"hide\",\n\t\tpaddingTop: \"hide\",\n\t\tpaddingBottom: \"hide\",\n\t\theight: \"hide\"\n\t},\n\n\tshowProps: {\n\t\tborderTopWidth: \"show\",\n\t\tborderBottomWidth: \"show\",\n\t\tpaddingTop: \"show\",\n\t\tpaddingBottom: \"show\",\n\t\theight: \"show\"\n\t},\n\n\t_create: function() {\n\t\tvar options = this.options;\n\n\t\tthis.prevShow = this.prevHide = $();\n\t\tthis._addClass( \"ui-accordion\", \"ui-widget ui-helper-reset\" );\n\t\tthis.element.attr( \"role\", \"tablist\" );\n\n\t\t// Don't allow collapsible: false and active: false / null\n\t\tif ( !options.collapsible && ( options.active === false || options.active == null ) ) {\n\t\t\toptions.active = 0;\n\t\t}\n\n\t\tthis._processPanels();\n\n\t\t// handle negative values\n\t\tif ( options.active < 0 ) {\n\t\t\toptions.active += this.headers.length;\n\t\t}\n\t\tthis._refresh();\n\t},\n\n\t_getCreateEventData: function() {\n\t\treturn {\n\t\t\theader: this.active,\n\t\t\tpanel: !this.active.length ? $() : this.active.next()\n\t\t};\n\t},\n\n\t_createIcons: function() {\n\t\tvar icon, children,\n\t\t\ticons = this.options.icons;\n\n\t\tif ( icons ) {\n\t\t\ticon = $( \"<span>\" );\n\t\t\tthis._addClass( icon, \"ui-accordion-header-icon\", \"ui-icon \" + icons.header );\n\t\t\ticon.prependTo( this.headers );\n\t\t\tchildren = this.active.children( \".ui-accordion-header-icon\" );\n\t\t\tthis._removeClass( children, icons.header )\n\t\t\t\t._addClass( children, null, icons.activeHeader )\n\t\t\t\t._addClass( this.headers, \"ui-accordion-icons\" );\n\t\t}\n\t},\n\n\t_destroyIcons: function() {\n\t\tthis._removeClass( this.headers, \"ui-accordion-icons\" );\n\t\tthis.headers.children( \".ui-accordion-header-icon\" ).remove();\n\t},\n\n\t_destroy: function() {\n\t\tvar contents;\n\n\t\t// Clean up main element\n\t\tthis.element.removeAttr( \"role\" );\n\n\t\t// Clean up headers\n\t\tthis.headers\n\t\t\t.removeAttr( \"role aria-expanded aria-selected aria-controls tabIndex\" )\n\t\t\t.removeUniqueId();\n\n\t\tthis._destroyIcons();\n\n\t\t// Clean up content panels\n\t\tcontents = this.headers.next()\n\t\t\t.css( \"display\", \"\" )\n\t\t\t.removeAttr( \"role aria-hidden aria-labelledby\" )\n\t\t\t.removeUniqueId();\n\n\t\tif ( this.options.heightStyle !== \"content\" ) {\n\t\t\tcontents.css( \"height\", \"\" );\n\t\t}\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"active\" ) {\n\n\t\t\t// _activate() will handle invalid values and update this.options\n\t\t\tthis._activate( value );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key === \"event\" ) {\n\t\t\tif ( this.options.event ) {\n\t\t\t\tthis._off( this.headers, this.options.event );\n\t\t\t}\n\t\t\tthis._setupEvents( value );\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\t// Setting collapsible: false while collapsed; open first panel\n\t\tif ( key === \"collapsible\" && !value && this.options.active === false ) {\n\t\t\tthis._activate( 0 );\n\t\t}\n\n\t\tif ( key === \"icons\" ) {\n\t\t\tthis._destroyIcons();\n\t\t\tif ( value ) {\n\t\t\t\tthis._createIcons();\n\t\t\t}\n\t\t}\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._super( value );\n\n\t\tthis.element.attr( \"aria-disabled\", value );\n\n\t\t// Support: IE8 Only\n\t\t// #5332 / #6059 - opacity doesn't cascade to positioned elements in IE\n\t\t// so we need to add the disabled class to the headers and panels\n\t\tthis._toggleClass( null, \"ui-state-disabled\", !!value );\n\t\tthis._toggleClass( this.headers.add( this.headers.next() ), null, \"ui-state-disabled\",\n\t\t\t!!value );\n\t},\n\n\t_keydown: function( event ) {\n\t\tif ( event.altKey || event.ctrlKey ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar keyCode = $.ui.keyCode,\n\t\t\tlength = this.headers.length,\n\t\t\tcurrentIndex = this.headers.index( event.target ),\n\t\t\ttoFocus = false;\n\n\t\tswitch ( event.keyCode ) {\n\t\tcase keyCode.RIGHT:\n\t\tcase keyCode.DOWN:\n\t\t\ttoFocus = this.headers[ ( currentIndex + 1 ) % length ];\n\t\t\tbreak;\n\t\tcase keyCode.LEFT:\n\t\tcase keyCode.UP:\n\t\t\ttoFocus = this.headers[ ( currentIndex - 1 + length ) % length ];\n\t\t\tbreak;\n\t\tcase keyCode.SPACE:\n\t\tcase keyCode.ENTER:\n\t\t\tthis._eventHandler( event );\n\t\t\tbreak;\n\t\tcase keyCode.HOME:\n\t\t\ttoFocus = this.headers[ 0 ];\n\t\t\tbreak;\n\t\tcase keyCode.END:\n\t\t\ttoFocus = this.headers[ length - 1 ];\n\t\t\tbreak;\n\t\t}\n\n\t\tif ( toFocus ) {\n\t\t\t$( event.target ).attr( \"tabIndex\", -1 );\n\t\t\t$( toFocus ).attr( \"tabIndex\", 0 );\n\t\t\t$( toFocus ).trigger( \"focus\" );\n\t\t\tevent.preventDefault();\n\t\t}\n\t},\n\n\t_panelKeyDown: function( event ) {\n\t\tif ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {\n\t\t\t$( event.currentTarget ).prev().trigger( \"focus\" );\n\t\t}\n\t},\n\n\trefresh: function() {\n\t\tvar options = this.options;\n\t\tthis._processPanels();\n\n\t\t// Was collapsed or no panel\n\t\tif ( ( options.active === false && options.collapsible === true ) ||\n\t\t\t\t!this.headers.length ) {\n\t\t\toptions.active = false;\n\t\t\tthis.active = $();\n\n\t\t// active false only when collapsible is true\n\t\t} else if ( options.active === false ) {\n\t\t\tthis._activate( 0 );\n\n\t\t// was active, but active panel is gone\n\t\t} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {\n\n\t\t\t// all remaining panel are disabled\n\t\t\tif ( this.headers.length === this.headers.find( \".ui-state-disabled\" ).length ) {\n\t\t\t\toptions.active = false;\n\t\t\t\tthis.active = $();\n\n\t\t\t// activate previous panel\n\t\t\t} else {\n\t\t\t\tthis._activate( Math.max( 0, options.active - 1 ) );\n\t\t\t}\n\n\t\t// was active, active panel still exists\n\t\t} else {\n\n\t\t\t// make sure active index is correct\n\t\t\toptions.active = this.headers.index( this.active );\n\t\t}\n\n\t\tthis._destroyIcons();\n\n\t\tthis._refresh();\n\t},\n\n\t_processPanels: function() {\n\t\tvar prevHeaders = this.headers,\n\t\t\tprevPanels = this.panels;\n\n\t\tthis.headers = this.element.find( this.options.header );\n\t\tthis._addClass( this.headers, \"ui-accordion-header ui-accordion-header-collapsed\",\n\t\t\t\"ui-state-default\" );\n\n\t\tthis.panels = this.headers.next().filter( \":not(.ui-accordion-content-active)\" ).hide();\n\t\tthis._addClass( this.panels, \"ui-accordion-content\", \"ui-helper-reset ui-widget-content\" );\n\n\t\t// Avoid memory leaks (#10056)\n\t\tif ( prevPanels ) {\n\t\t\tthis._off( prevHeaders.not( this.headers ) );\n\t\t\tthis._off( prevPanels.not( this.panels ) );\n\t\t}\n\t},\n\n\t_refresh: function() {\n\t\tvar maxHeight,\n\t\t\toptions = this.options,\n\t\t\theightStyle = options.heightStyle,\n\t\t\tparent = this.element.parent();\n\n\t\tthis.active = this._findActive( options.active );\n\t\tthis._addClass( this.active, \"ui-accordion-header-active\", \"ui-state-active\" )\n\t\t\t._removeClass( this.active, \"ui-accordion-header-collapsed\" );\n\t\tthis._addClass( this.active.next(), \"ui-accordion-content-active\" );\n\t\tthis.active.next().show();\n\n\t\tthis.headers\n\t\t\t.attr( \"role\", \"tab\" )\n\t\t\t.each( function() {\n\t\t\t\tvar header = $( this ),\n\t\t\t\t\theaderId = header.uniqueId().attr( \"id\" ),\n\t\t\t\t\tpanel = header.next(),\n\t\t\t\t\tpanelId = panel.uniqueId().attr( \"id\" );\n\t\t\t\theader.attr( \"aria-controls\", panelId );\n\t\t\t\tpanel.attr( \"aria-labelledby\", headerId );\n\t\t\t} )\n\t\t\t.next()\n\t\t\t\t.attr( \"role\", \"tabpanel\" );\n\n\t\tthis.headers\n\t\t\t.not( this.active )\n\t\t\t\t.attr( {\n\t\t\t\t\t\"aria-selected\": \"false\",\n\t\t\t\t\t\"aria-expanded\": \"false\",\n\t\t\t\t\ttabIndex: -1\n\t\t\t\t} )\n\t\t\t\t.next()\n\t\t\t\t\t.attr( {\n\t\t\t\t\t\t\"aria-hidden\": \"true\"\n\t\t\t\t\t} )\n\t\t\t\t\t.hide();\n\n\t\t// Make sure at least one header is in the tab order\n\t\tif ( !this.active.length ) {\n\t\t\tthis.headers.eq( 0 ).attr( \"tabIndex\", 0 );\n\t\t} else {\n\t\t\tthis.active.attr( {\n\t\t\t\t\"aria-selected\": \"true\",\n\t\t\t\t\"aria-expanded\": \"true\",\n\t\t\t\ttabIndex: 0\n\t\t\t} )\n\t\t\t\t.next()\n\t\t\t\t\t.attr( {\n\t\t\t\t\t\t\"aria-hidden\": \"false\"\n\t\t\t\t\t} );\n\t\t}\n\n\t\tthis._createIcons();\n\n\t\tthis._setupEvents( options.event );\n\n\t\tif ( heightStyle === \"fill\" ) {\n\t\t\tmaxHeight = parent.height();\n\t\t\tthis.element.siblings( \":visible\" ).each( function() {\n\t\t\t\tvar elem = $( this ),\n\t\t\t\t\tposition = elem.css( \"position\" );\n\n\t\t\t\tif ( position === \"absolute\" || position === \"fixed\" ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tmaxHeight -= elem.outerHeight( true );\n\t\t\t} );\n\n\t\t\tthis.headers.each( function() {\n\t\t\t\tmaxHeight -= $( this ).outerHeight( true );\n\t\t\t} );\n\n\t\t\tthis.headers.next()\n\t\t\t\t.each( function() {\n\t\t\t\t\t$( this ).height( Math.max( 0, maxHeight -\n\t\t\t\t\t\t$( this ).innerHeight() + $( this ).height() ) );\n\t\t\t\t} )\n\t\t\t\t.css( \"overflow\", \"auto\" );\n\t\t} else if ( heightStyle === \"auto\" ) {\n\t\t\tmaxHeight = 0;\n\t\t\tthis.headers.next()\n\t\t\t\t.each( function() {\n\t\t\t\t\tvar isVisible = $( this ).is( \":visible\" );\n\t\t\t\t\tif ( !isVisible ) {\n\t\t\t\t\t\t$( this ).show();\n\t\t\t\t\t}\n\t\t\t\t\tmaxHeight = Math.max( maxHeight, $( this ).css( \"height\", \"\" ).height() );\n\t\t\t\t\tif ( !isVisible ) {\n\t\t\t\t\t\t$( this ).hide();\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t\t\t.height( maxHeight );\n\t\t}\n\t},\n\n\t_activate: function( index ) {\n\t\tvar active = this._findActive( index )[ 0 ];\n\n\t\t// Trying to activate the already active panel\n\t\tif ( active === this.active[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Trying to collapse, simulate a click on the currently active header\n\t\tactive = active || this.active[ 0 ];\n\n\t\tthis._eventHandler( {\n\t\t\ttarget: active,\n\t\t\tcurrentTarget: active,\n\t\t\tpreventDefault: $.noop\n\t\t} );\n\t},\n\n\t_findActive: function( selector ) {\n\t\treturn typeof selector === \"number\" ? this.headers.eq( selector ) : $();\n\t},\n\n\t_setupEvents: function( event ) {\n\t\tvar events = {\n\t\t\tkeydown: \"_keydown\"\n\t\t};\n\t\tif ( event ) {\n\t\t\t$.each( event.split( \" \" ), function( index, eventName ) {\n\t\t\t\tevents[ eventName ] = \"_eventHandler\";\n\t\t\t} );\n\t\t}\n\n\t\tthis._off( this.headers.add( this.headers.next() ) );\n\t\tthis._on( this.headers, events );\n\t\tthis._on( this.headers.next(), { keydown: \"_panelKeyDown\" } );\n\t\tthis._hoverable( this.headers );\n\t\tthis._focusable( this.headers );\n\t},\n\n\t_eventHandler: function( event ) {\n\t\tvar activeChildren, clickedChildren,\n\t\t\toptions = this.options,\n\t\t\tactive = this.active,\n\t\t\tclicked = $( event.currentTarget ),\n\t\t\tclickedIsActive = clicked[ 0 ] === active[ 0 ],\n\t\t\tcollapsing = clickedIsActive && options.collapsible,\n\t\t\ttoShow = collapsing ? $() : clicked.next(),\n\t\t\ttoHide = active.next(),\n\t\t\teventData = {\n\t\t\t\toldHeader: active,\n\t\t\t\toldPanel: toHide,\n\t\t\t\tnewHeader: collapsing ? $() : clicked,\n\t\t\t\tnewPanel: toShow\n\t\t\t};\n\n\t\tevent.preventDefault();\n\n\t\tif (\n\n\t\t\t\t// click on active header, but not collapsible\n\t\t\t\t( clickedIsActive && !options.collapsible ) ||\n\n\t\t\t\t// allow canceling activation\n\t\t\t\t( this._trigger( \"beforeActivate\", event, eventData ) === false ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\toptions.active = collapsing ? false : this.headers.index( clicked );\n\n\t\t// When the call to ._toggle() comes after the class changes\n\t\t// it causes a very odd bug in IE 8 (see #6720)\n\t\tthis.active = clickedIsActive ? $() : clicked;\n\t\tthis._toggle( eventData );\n\n\t\t// Switch classes\n\t\t// corner classes on the previously active header stay after the animation\n\t\tthis._removeClass( active, \"ui-accordion-header-active\", \"ui-state-active\" );\n\t\tif ( options.icons ) {\n\t\t\tactiveChildren = active.children( \".ui-accordion-header-icon\" );\n\t\t\tthis._removeClass( activeChildren, null, options.icons.activeHeader )\n\t\t\t\t._addClass( activeChildren, null, options.icons.header );\n\t\t}\n\n\t\tif ( !clickedIsActive ) {\n\t\t\tthis._removeClass( clicked, \"ui-accordion-header-collapsed\" )\n\t\t\t\t._addClass( clicked, \"ui-accordion-header-active\", \"ui-state-active\" );\n\t\t\tif ( options.icons ) {\n\t\t\t\tclickedChildren = clicked.children( \".ui-accordion-header-icon\" );\n\t\t\t\tthis._removeClass( clickedChildren, null, options.icons.header )\n\t\t\t\t\t._addClass( clickedChildren, null, options.icons.activeHeader );\n\t\t\t}\n\n\t\t\tthis._addClass( clicked.next(), \"ui-accordion-content-active\" );\n\t\t}\n\t},\n\n\t_toggle: function( data ) {\n\t\tvar toShow = data.newPanel,\n\t\t\ttoHide = this.prevShow.length ? this.prevShow : data.oldPanel;\n\n\t\t// Handle activating a panel during the animation for another activation\n\t\tthis.prevShow.add( this.prevHide ).stop( true, true );\n\t\tthis.prevShow = toShow;\n\t\tthis.prevHide = toHide;\n\n\t\tif ( this.options.animate ) {\n\t\t\tthis._animate( toShow, toHide, data );\n\t\t} else {\n\t\t\ttoHide.hide();\n\t\t\ttoShow.show();\n\t\t\tthis._toggleComplete( data );\n\t\t}\n\n\t\ttoHide.attr( {\n\t\t\t\"aria-hidden\": \"true\"\n\t\t} );\n\t\ttoHide.prev().attr( {\n\t\t\t\"aria-selected\": \"false\",\n\t\t\t\"aria-expanded\": \"false\"\n\t\t} );\n\n\t\t// if we're switching panels, remove the old header from the tab order\n\t\t// if we're opening from collapsed state, remove the previous header from the tab order\n\t\t// if we're collapsing, then keep the collapsing header in the tab order\n\t\tif ( toShow.length && toHide.length ) {\n\t\t\ttoHide.prev().attr( {\n\t\t\t\t\"tabIndex\": -1,\n\t\t\t\t\"aria-expanded\": \"false\"\n\t\t\t} );\n\t\t} else if ( toShow.length ) {\n\t\t\tthis.headers.filter( function() {\n\t\t\t\treturn parseInt( $( this ).attr( \"tabIndex\" ), 10 ) === 0;\n\t\t\t} )\n\t\t\t\t.attr( \"tabIndex\", -1 );\n\t\t}\n\n\t\ttoShow\n\t\t\t.attr( \"aria-hidden\", \"false\" )\n\t\t\t.prev()\n\t\t\t\t.attr( {\n\t\t\t\t\t\"aria-selected\": \"true\",\n\t\t\t\t\t\"aria-expanded\": \"true\",\n\t\t\t\t\ttabIndex: 0\n\t\t\t\t} );\n\t},\n\n\t_animate: function( toShow, toHide, data ) {\n\t\tvar total, easing, duration,\n\t\t\tthat = this,\n\t\t\tadjust = 0,\n\t\t\tboxSizing = toShow.css( \"box-sizing\" ),\n\t\t\tdown = toShow.length &&\n\t\t\t\t( !toHide.length || ( toShow.index() < toHide.index() ) ),\n\t\t\tanimate = this.options.animate || {},\n\t\t\toptions = down && animate.down || animate,\n\t\t\tcomplete = function() {\n\t\t\t\tthat._toggleComplete( data );\n\t\t\t};\n\n\t\tif ( typeof options === \"number\" ) {\n\t\t\tduration = options;\n\t\t}\n\t\tif ( typeof options === \"string\" ) {\n\t\t\teasing = options;\n\t\t}\n\n\t\t// fall back from options to animation in case of partial down settings\n\t\teasing = easing || options.easing || animate.easing;\n\t\tduration = duration || options.duration || animate.duration;\n\n\t\tif ( !toHide.length ) {\n\t\t\treturn toShow.animate( this.showProps, duration, easing, complete );\n\t\t}\n\t\tif ( !toShow.length ) {\n\t\t\treturn toHide.animate( this.hideProps, duration, easing, complete );\n\t\t}\n\n\t\ttotal = toShow.show().outerHeight();\n\t\ttoHide.animate( this.hideProps, {\n\t\t\tduration: duration,\n\t\t\teasing: easing,\n\t\t\tstep: function( now, fx ) {\n\t\t\t\tfx.now = Math.round( now );\n\t\t\t}\n\t\t} );\n\t\ttoShow\n\t\t\t.hide()\n\t\t\t.animate( this.showProps, {\n\t\t\t\tduration: duration,\n\t\t\t\teasing: easing,\n\t\t\t\tcomplete: complete,\n\t\t\t\tstep: function( now, fx ) {\n\t\t\t\t\tfx.now = Math.round( now );\n\t\t\t\t\tif ( fx.prop !== \"height\" ) {\n\t\t\t\t\t\tif ( boxSizing === \"content-box\" ) {\n\t\t\t\t\t\t\tadjust += fx.now;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( that.options.heightStyle !== \"content\" ) {\n\t\t\t\t\t\tfx.now = Math.round( total - toHide.outerHeight() - adjust );\n\t\t\t\t\t\tadjust = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t},\n\n\t_toggleComplete: function( data ) {\n\t\tvar toHide = data.oldPanel,\n\t\t\tprev = toHide.prev();\n\n\t\tthis._removeClass( toHide, \"ui-accordion-content-active\" );\n\t\tthis._removeClass( prev, \"ui-accordion-header-active\" )\n\t\t\t._addClass( prev, \"ui-accordion-header-collapsed\" );\n\n\t\t// Work around for rendering bug in IE (#5421)\n\t\tif ( toHide.length ) {\n\t\t\ttoHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;\n\t\t}\n\t\tthis._trigger( \"activate\", null, data );\n\t}\n} );\n\n\n/*!\n * jQuery UI Menu 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Menu\n//>>group: Widgets\n//>>description: Creates nestable menus.\n//>>docs: http://api.jqueryui.com/menu/\n//>>demos: http://jqueryui.com/menu/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/menu.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\nvar widgetsMenu = $.widget( \"ui.menu\", {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<ul>\",\n\tdelay: 300,\n\toptions: {\n\t\ticons: {\n\t\t\tsubmenu: \"ui-icon-caret-1-e\"\n\t\t},\n\t\titems: \"> *\",\n\t\tmenus: \"ul\",\n\t\tposition: {\n\t\t\tmy: \"left top\",\n\t\t\tat: \"right top\"\n\t\t},\n\t\trole: \"menu\",\n\n\t\t// Callbacks\n\t\tblur: null,\n\t\tfocus: null,\n\t\tselect: null\n\t},\n\n\t_create: function() {\n\t\tthis.activeMenu = this.element;\n\n\t\t// Flag used to prevent firing of the click handler\n\t\t// as the event bubbles up through nested menus\n\t\tthis.mouseHandled = false;\n\t\tthis.element\n\t\t\t.uniqueId()\n\t\t\t.attr( {\n\t\t\t\trole: this.options.role,\n\t\t\t\ttabIndex: 0\n\t\t\t} );\n\n\t\tthis._addClass( \"ui-menu\", \"ui-widget ui-widget-content\" );\n\t\tthis._on( {\n\n\t\t\t// Prevent focus from sticking to links inside menu after clicking\n\t\t\t// them (focus should always stay on UL during navigation).\n\t\t\t\"mousedown .ui-menu-item\": function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t},\n\t\t\t\"click .ui-menu-item\": function( event ) {\n\t\t\t\tvar target = $( event.target );\n\t\t\t\tvar active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );\n\t\t\t\tif ( !this.mouseHandled && target.not( \".ui-state-disabled\" ).length ) {\n\t\t\t\t\tthis.select( event );\n\n\t\t\t\t\t// Only set the mouseHandled flag if the event will bubble, see #9469.\n\t\t\t\t\tif ( !event.isPropagationStopped() ) {\n\t\t\t\t\t\tthis.mouseHandled = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Open submenu on click\n\t\t\t\t\tif ( target.has( \".ui-menu\" ).length ) {\n\t\t\t\t\t\tthis.expand( event );\n\t\t\t\t\t} else if ( !this.element.is( \":focus\" ) &&\n\t\t\t\t\t\t\tactive.closest( \".ui-menu\" ).length ) {\n\n\t\t\t\t\t\t// Redirect focus to the menu\n\t\t\t\t\t\tthis.element.trigger( \"focus\", [ true ] );\n\n\t\t\t\t\t\t// If the active item is on the top level, let it stay active.\n\t\t\t\t\t\t// Otherwise, blur the active item since it is no longer visible.\n\t\t\t\t\t\tif ( this.active && this.active.parents( \".ui-menu\" ).length === 1 ) {\n\t\t\t\t\t\t\tclearTimeout( this.timer );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"mouseenter .ui-menu-item\": function( event ) {\n\n\t\t\t\t// Ignore mouse events while typeahead is active, see #10458.\n\t\t\t\t// Prevents focusing the wrong item when typeahead causes a scroll while the mouse\n\t\t\t\t// is over an item in the menu\n\t\t\t\tif ( this.previousFilter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar actualTarget = $( event.target ).closest( \".ui-menu-item\" ),\n\t\t\t\t\ttarget = $( event.currentTarget );\n\n\t\t\t\t// Ignore bubbled events on parent items, see #11641\n\t\t\t\tif ( actualTarget[ 0 ] !== target[ 0 ] ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Remove ui-state-active class from siblings of the newly focused menu item\n\t\t\t\t// to avoid a jump caused by adjacent elements both having a class with a border\n\t\t\t\tthis._removeClass( target.siblings().children( \".ui-state-active\" ),\n\t\t\t\t\tnull, \"ui-state-active\" );\n\t\t\t\tthis.focus( event, target );\n\t\t\t},\n\t\t\tmouseleave: \"collapseAll\",\n\t\t\t\"mouseleave .ui-menu\": \"collapseAll\",\n\t\t\tfocus: function( event, keepActiveItem ) {\n\n\t\t\t\t// If there's already an active item, keep it active\n\t\t\t\t// If not, activate the first item\n\t\t\t\tvar item = this.active || this.element.find( this.options.items ).eq( 0 );\n\n\t\t\t\tif ( !keepActiveItem ) {\n\t\t\t\t\tthis.focus( event, item );\n\t\t\t\t}\n\t\t\t},\n\t\t\tblur: function( event ) {\n\t\t\t\tthis._delay( function() {\n\t\t\t\t\tvar notContained = !$.contains(\n\t\t\t\t\t\tthis.element[ 0 ],\n\t\t\t\t\t\t$.ui.safeActiveElement( this.document[ 0 ] )\n\t\t\t\t\t);\n\t\t\t\t\tif ( notContained ) {\n\t\t\t\t\t\tthis.collapseAll( event );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t},\n\t\t\tkeydown: \"_keydown\"\n\t\t} );\n\n\t\tthis.refresh();\n\n\t\t// Clicks outside of a menu collapse any open menus\n\t\tthis._on( this.document, {\n\t\t\tclick: function( event ) {\n\t\t\t\tif ( this._closeOnDocumentClick( event ) ) {\n\t\t\t\t\tthis.collapseAll( event );\n\t\t\t\t}\n\n\t\t\t\t// Reset the mouseHandled flag\n\t\t\t\tthis.mouseHandled = false;\n\t\t\t}\n\t\t} );\n\t},\n\n\t_destroy: function() {\n\t\tvar items = this.element.find( \".ui-menu-item\" )\n\t\t\t\t.removeAttr( \"role aria-disabled\" ),\n\t\t\tsubmenus = items.children( \".ui-menu-item-wrapper\" )\n\t\t\t\t.removeUniqueId()\n\t\t\t\t.removeAttr( \"tabIndex role aria-haspopup\" );\n\n\t\t// Destroy (sub)menus\n\t\tthis.element\n\t\t\t.removeAttr( \"aria-activedescendant\" )\n\t\t\t.find( \".ui-menu\" ).addBack()\n\t\t\t\t.removeAttr( \"role aria-labelledby aria-expanded aria-hidden aria-disabled \" +\n\t\t\t\t\t\"tabIndex\" )\n\t\t\t\t.removeUniqueId()\n\t\t\t\t.show();\n\n\t\tsubmenus.children().each( function() {\n\t\t\tvar elem = $( this );\n\t\t\tif ( elem.data( \"ui-menu-submenu-caret\" ) ) {\n\t\t\t\telem.remove();\n\t\t\t}\n\t\t} );\n\t},\n\n\t_keydown: function( event ) {\n\t\tvar match, prev, character, skip,\n\t\t\tpreventDefault = true;\n\n\t\tswitch ( event.keyCode ) {\n\t\tcase $.ui.keyCode.PAGE_UP:\n\t\t\tthis.previousPage( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.PAGE_DOWN:\n\t\t\tthis.nextPage( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.HOME:\n\t\t\tthis._move( \"first\", \"first\", event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.END:\n\t\t\tthis._move( \"last\", \"last\", event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.UP:\n\t\t\tthis.previous( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.DOWN:\n\t\t\tthis.next( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.LEFT:\n\t\t\tthis.collapse( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.RIGHT:\n\t\t\tif ( this.active && !this.active.is( \".ui-state-disabled\" ) ) {\n\t\t\t\tthis.expand( event );\n\t\t\t}\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.ENTER:\n\t\tcase $.ui.keyCode.SPACE:\n\t\t\tthis._activate( event );\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.ESCAPE:\n\t\t\tthis.collapse( event );\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tpreventDefault = false;\n\t\t\tprev = this.previousFilter || \"\";\n\t\t\tskip = false;\n\n\t\t\t// Support number pad values\n\t\t\tcharacter = event.keyCode >= 96 && event.keyCode <= 105 ?\n\t\t\t\t( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );\n\n\t\t\tclearTimeout( this.filterTimer );\n\n\t\t\tif ( character === prev ) {\n\t\t\t\tskip = true;\n\t\t\t} else {\n\t\t\t\tcharacter = prev + character;\n\t\t\t}\n\n\t\t\tmatch = this._filterMenuItems( character );\n\t\t\tmatch = skip && match.index( this.active.next() ) !== -1 ?\n\t\t\t\tthis.active.nextAll( \".ui-menu-item\" ) :\n\t\t\t\tmatch;\n\n\t\t\t// If no matches on the current filter, reset to the last character pressed\n\t\t\t// to move down the menu to the first item that starts with that character\n\t\t\tif ( !match.length ) {\n\t\t\t\tcharacter = String.fromCharCode( event.keyCode );\n\t\t\t\tmatch = this._filterMenuItems( character );\n\t\t\t}\n\n\t\t\tif ( match.length ) {\n\t\t\t\tthis.focus( event, match );\n\t\t\t\tthis.previousFilter = character;\n\t\t\t\tthis.filterTimer = this._delay( function() {\n\t\t\t\t\tdelete this.previousFilter;\n\t\t\t\t}, 1000 );\n\t\t\t} else {\n\t\t\t\tdelete this.previousFilter;\n\t\t\t}\n\t\t}\n\n\t\tif ( preventDefault ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t},\n\n\t_activate: function( event ) {\n\t\tif ( this.active && !this.active.is( \".ui-state-disabled\" ) ) {\n\t\t\tif ( this.active.children( \"[aria-haspopup='true']\" ).length ) {\n\t\t\t\tthis.expand( event );\n\t\t\t} else {\n\t\t\t\tthis.select( event );\n\t\t\t}\n\t\t}\n\t},\n\n\trefresh: function() {\n\t\tvar menus, items, newSubmenus, newItems, newWrappers,\n\t\t\tthat = this,\n\t\t\ticon = this.options.icons.submenu,\n\t\t\tsubmenus = this.element.find( this.options.menus );\n\n\t\tthis._toggleClass( \"ui-menu-icons\", null, !!this.element.find( \".ui-icon\" ).length );\n\n\t\t// Initialize nested menus\n\t\tnewSubmenus = submenus.filter( \":not(.ui-menu)\" )\n\t\t\t.hide()\n\t\t\t.attr( {\n\t\t\t\trole: this.options.role,\n\t\t\t\t\"aria-hidden\": \"true\",\n\t\t\t\t\"aria-expanded\": \"false\"\n\t\t\t} )\n\t\t\t.each( function() {\n\t\t\t\tvar menu = $( this ),\n\t\t\t\t\titem = menu.prev(),\n\t\t\t\t\tsubmenuCaret = $( \"<span>\" ).data( \"ui-menu-submenu-caret\", true );\n\n\t\t\t\tthat._addClass( submenuCaret, \"ui-menu-icon\", \"ui-icon \" + icon );\n\t\t\t\titem\n\t\t\t\t\t.attr( \"aria-haspopup\", \"true\" )\n\t\t\t\t\t.prepend( submenuCaret );\n\t\t\t\tmenu.attr( \"aria-labelledby\", item.attr( \"id\" ) );\n\t\t\t} );\n\n\t\tthis._addClass( newSubmenus, \"ui-menu\", \"ui-widget ui-widget-content ui-front\" );\n\n\t\tmenus = submenus.add( this.element );\n\t\titems = menus.find( this.options.items );\n\n\t\t// Initialize menu-items containing spaces and/or dashes only as dividers\n\t\titems.not( \".ui-menu-item\" ).each( function() {\n\t\t\tvar item = $( this );\n\t\t\tif ( that._isDivider( item ) ) {\n\t\t\t\tthat._addClass( item, \"ui-menu-divider\", \"ui-widget-content\" );\n\t\t\t}\n\t\t} );\n\n\t\t// Don't refresh list items that are already adapted\n\t\tnewItems = items.not( \".ui-menu-item, .ui-menu-divider\" );\n\t\tnewWrappers = newItems.children()\n\t\t\t.not( \".ui-menu\" )\n\t\t\t\t.uniqueId()\n\t\t\t\t.attr( {\n\t\t\t\t\ttabIndex: -1,\n\t\t\t\t\trole: this._itemRole()\n\t\t\t\t} );\n\t\tthis._addClass( newItems, \"ui-menu-item\" )\n\t\t\t._addClass( newWrappers, \"ui-menu-item-wrapper\" );\n\n\t\t// Add aria-disabled attribute to any disabled menu item\n\t\titems.filter( \".ui-state-disabled\" ).attr( \"aria-disabled\", \"true\" );\n\n\t\t// If the active item has been removed, blur the menu\n\t\tif ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {\n\t\t\tthis.blur();\n\t\t}\n\t},\n\n\t_itemRole: function() {\n\t\treturn {\n\t\t\tmenu: \"menuitem\",\n\t\t\tlistbox: \"option\"\n\t\t}[ this.options.role ];\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"icons\" ) {\n\t\t\tvar icons = this.element.find( \".ui-menu-icon\" );\n\t\t\tthis._removeClass( icons, null, this.options.icons.submenu )\n\t\t\t\t._addClass( icons, null, value.submenu );\n\t\t}\n\t\tthis._super( key, value );\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._super( value );\n\n\t\tthis.element.attr( \"aria-disabled\", String( value ) );\n\t\tthis._toggleClass( null, \"ui-state-disabled\", !!value );\n\t},\n\n\tfocus: function( event, item ) {\n\t\tvar nested, focused, activeParent;\n\t\tthis.blur( event, event && event.type === \"focus\" );\n\n\t\tthis._scrollIntoView( item );\n\n\t\tthis.active = item.first();\n\n\t\tfocused = this.active.children( \".ui-menu-item-wrapper\" );\n\t\tthis._addClass( focused, null, \"ui-state-active\" );\n\n\t\t// Only update aria-activedescendant if there's a role\n\t\t// otherwise we assume focus is managed elsewhere\n\t\tif ( this.options.role ) {\n\t\t\tthis.element.attr( \"aria-activedescendant\", focused.attr( \"id\" ) );\n\t\t}\n\n\t\t// Highlight active parent menu item, if any\n\t\tactiveParent = this.active\n\t\t\t.parent()\n\t\t\t\t.closest( \".ui-menu-item\" )\n\t\t\t\t\t.children( \".ui-menu-item-wrapper\" );\n\t\tthis._addClass( activeParent, null, \"ui-state-active\" );\n\n\t\tif ( event && event.type === \"keydown\" ) {\n\t\t\tthis._close();\n\t\t} else {\n\t\t\tthis.timer = this._delay( function() {\n\t\t\t\tthis._close();\n\t\t\t}, this.delay );\n\t\t}\n\n\t\tnested = item.children( \".ui-menu\" );\n\t\tif ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {\n\t\t\tthis._startOpening( nested );\n\t\t}\n\t\tthis.activeMenu = item.parent();\n\n\t\tthis._trigger( \"focus\", event, { item: item } );\n\t},\n\n\t_scrollIntoView: function( item ) {\n\t\tvar borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;\n\t\tif ( this._hasScroll() ) {\n\t\t\tborderTop = parseFloat( $.css( this.activeMenu[ 0 ], \"borderTopWidth\" ) ) || 0;\n\t\t\tpaddingTop = parseFloat( $.css( this.activeMenu[ 0 ], \"paddingTop\" ) ) || 0;\n\t\t\toffset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;\n\t\t\tscroll = this.activeMenu.scrollTop();\n\t\t\telementHeight = this.activeMenu.height();\n\t\t\titemHeight = item.outerHeight();\n\n\t\t\tif ( offset < 0 ) {\n\t\t\t\tthis.activeMenu.scrollTop( scroll + offset );\n\t\t\t} else if ( offset + itemHeight > elementHeight ) {\n\t\t\t\tthis.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );\n\t\t\t}\n\t\t}\n\t},\n\n\tblur: function( event, fromFocus ) {\n\t\tif ( !fromFocus ) {\n\t\t\tclearTimeout( this.timer );\n\t\t}\n\n\t\tif ( !this.active ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._removeClass( this.active.children( \".ui-menu-item-wrapper\" ),\n\t\t\tnull, \"ui-state-active\" );\n\n\t\tthis._trigger( \"blur\", event, { item: this.active } );\n\t\tthis.active = null;\n\t},\n\n\t_startOpening: function( submenu ) {\n\t\tclearTimeout( this.timer );\n\n\t\t// Don't open if already open fixes a Firefox bug that caused a .5 pixel\n\t\t// shift in the submenu position when mousing over the caret icon\n\t\tif ( submenu.attr( \"aria-hidden\" ) !== \"true\" ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.timer = this._delay( function() {\n\t\t\tthis._close();\n\t\t\tthis._open( submenu );\n\t\t}, this.delay );\n\t},\n\n\t_open: function( submenu ) {\n\t\tvar position = $.extend( {\n\t\t\tof: this.active\n\t\t}, this.options.position );\n\n\t\tclearTimeout( this.timer );\n\t\tthis.element.find( \".ui-menu\" ).not( submenu.parents( \".ui-menu\" ) )\n\t\t\t.hide()\n\t\t\t.attr( \"aria-hidden\", \"true\" );\n\n\t\tsubmenu\n\t\t\t.show()\n\t\t\t.removeAttr( \"aria-hidden\" )\n\t\t\t.attr( \"aria-expanded\", \"true\" )\n\t\t\t.position( position );\n\t},\n\n\tcollapseAll: function( event, all ) {\n\t\tclearTimeout( this.timer );\n\t\tthis.timer = this._delay( function() {\n\n\t\t\t// If we were passed an event, look for the submenu that contains the event\n\t\t\tvar currentMenu = all ? this.element :\n\t\t\t\t$( event && event.target ).closest( this.element.find( \".ui-menu\" ) );\n\n\t\t\t// If we found no valid submenu ancestor, use the main menu to close all\n\t\t\t// sub menus anyway\n\t\t\tif ( !currentMenu.length ) {\n\t\t\t\tcurrentMenu = this.element;\n\t\t\t}\n\n\t\t\tthis._close( currentMenu );\n\n\t\t\tthis.blur( event );\n\n\t\t\t// Work around active item staying active after menu is blurred\n\t\t\tthis._removeClass( currentMenu.find( \".ui-state-active\" ), null, \"ui-state-active\" );\n\n\t\t\tthis.activeMenu = currentMenu;\n\t\t}, this.delay );\n\t},\n\n\t// With no arguments, closes the currently active menu - if nothing is active\n\t// it closes all menus.  If passed an argument, it will search for menus BELOW\n\t_close: function( startMenu ) {\n\t\tif ( !startMenu ) {\n\t\t\tstartMenu = this.active ? this.active.parent() : this.element;\n\t\t}\n\n\t\tstartMenu.find( \".ui-menu\" )\n\t\t\t.hide()\n\t\t\t.attr( \"aria-hidden\", \"true\" )\n\t\t\t.attr( \"aria-expanded\", \"false\" );\n\t},\n\n\t_closeOnDocumentClick: function( event ) {\n\t\treturn !$( event.target ).closest( \".ui-menu\" ).length;\n\t},\n\n\t_isDivider: function( item ) {\n\n\t\t// Match hyphen, em dash, en dash\n\t\treturn !/[^\\-\\u2014\\u2013\\s]/.test( item.text() );\n\t},\n\n\tcollapse: function( event ) {\n\t\tvar newItem = this.active &&\n\t\t\tthis.active.parent().closest( \".ui-menu-item\", this.element );\n\t\tif ( newItem && newItem.length ) {\n\t\t\tthis._close();\n\t\t\tthis.focus( event, newItem );\n\t\t}\n\t},\n\n\texpand: function( event ) {\n\t\tvar newItem = this.active &&\n\t\t\tthis.active\n\t\t\t\t.children( \".ui-menu \" )\n\t\t\t\t\t.find( this.options.items )\n\t\t\t\t\t\t.first();\n\n\t\tif ( newItem && newItem.length ) {\n\t\t\tthis._open( newItem.parent() );\n\n\t\t\t// Delay so Firefox will not hide activedescendant change in expanding submenu from AT\n\t\t\tthis._delay( function() {\n\t\t\t\tthis.focus( event, newItem );\n\t\t\t} );\n\t\t}\n\t},\n\n\tnext: function( event ) {\n\t\tthis._move( \"next\", \"first\", event );\n\t},\n\n\tprevious: function( event ) {\n\t\tthis._move( \"prev\", \"last\", event );\n\t},\n\n\tisFirstItem: function() {\n\t\treturn this.active && !this.active.prevAll( \".ui-menu-item\" ).length;\n\t},\n\n\tisLastItem: function() {\n\t\treturn this.active && !this.active.nextAll( \".ui-menu-item\" ).length;\n\t},\n\n\t_move: function( direction, filter, event ) {\n\t\tvar next;\n\t\tif ( this.active ) {\n\t\t\tif ( direction === \"first\" || direction === \"last\" ) {\n\t\t\t\tnext = this.active\n\t\t\t\t\t[ direction === \"first\" ? \"prevAll\" : \"nextAll\" ]( \".ui-menu-item\" )\n\t\t\t\t\t.eq( -1 );\n\t\t\t} else {\n\t\t\t\tnext = this.active\n\t\t\t\t\t[ direction + \"All\" ]( \".ui-menu-item\" )\n\t\t\t\t\t.eq( 0 );\n\t\t\t}\n\t\t}\n\t\tif ( !next || !next.length || !this.active ) {\n\t\t\tnext = this.activeMenu.find( this.options.items )[ filter ]();\n\t\t}\n\n\t\tthis.focus( event, next );\n\t},\n\n\tnextPage: function( event ) {\n\t\tvar item, base, height;\n\n\t\tif ( !this.active ) {\n\t\t\tthis.next( event );\n\t\t\treturn;\n\t\t}\n\t\tif ( this.isLastItem() ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( this._hasScroll() ) {\n\t\t\tbase = this.active.offset().top;\n\t\t\theight = this.element.height();\n\t\t\tthis.active.nextAll( \".ui-menu-item\" ).each( function() {\n\t\t\t\titem = $( this );\n\t\t\t\treturn item.offset().top - base - height < 0;\n\t\t\t} );\n\n\t\t\tthis.focus( event, item );\n\t\t} else {\n\t\t\tthis.focus( event, this.activeMenu.find( this.options.items )\n\t\t\t\t[ !this.active ? \"first\" : \"last\" ]() );\n\t\t}\n\t},\n\n\tpreviousPage: function( event ) {\n\t\tvar item, base, height;\n\t\tif ( !this.active ) {\n\t\t\tthis.next( event );\n\t\t\treturn;\n\t\t}\n\t\tif ( this.isFirstItem() ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( this._hasScroll() ) {\n\t\t\tbase = this.active.offset().top;\n\t\t\theight = this.element.height();\n\t\t\tthis.active.prevAll( \".ui-menu-item\" ).each( function() {\n\t\t\t\titem = $( this );\n\t\t\t\treturn item.offset().top - base + height > 0;\n\t\t\t} );\n\n\t\t\tthis.focus( event, item );\n\t\t} else {\n\t\t\tthis.focus( event, this.activeMenu.find( this.options.items ).first() );\n\t\t}\n\t},\n\n\t_hasScroll: function() {\n\t\treturn this.element.outerHeight() < this.element.prop( \"scrollHeight\" );\n\t},\n\n\tselect: function( event ) {\n\n\t\t// TODO: It should never be possible to not have an active item at this\n\t\t// point, but the tests don't trigger mouseenter before click.\n\t\tthis.active = this.active || $( event.target ).closest( \".ui-menu-item\" );\n\t\tvar ui = { item: this.active };\n\t\tif ( !this.active.has( \".ui-menu\" ).length ) {\n\t\t\tthis.collapseAll( event, true );\n\t\t}\n\t\tthis._trigger( \"select\", event, ui );\n\t},\n\n\t_filterMenuItems: function( character ) {\n\t\tvar escapedCharacter = character.replace( /[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, \"\\\\$&\" ),\n\t\t\tregex = new RegExp( \"^\" + escapedCharacter, \"i\" );\n\n\t\treturn this.activeMenu\n\t\t\t.find( this.options.items )\n\n\t\t\t\t// Only match on items, not dividers or other content (#10571)\n\t\t\t\t.filter( \".ui-menu-item\" )\n\t\t\t\t\t.filter( function() {\n\t\t\t\t\t\treturn regex.test(\n\t\t\t\t\t\t\t$.trim( $( this ).children( \".ui-menu-item-wrapper\" ).text() ) );\n\t\t\t\t\t} );\n\t}\n} );\n\n\n/*!\n * jQuery UI Autocomplete 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Autocomplete\n//>>group: Widgets\n//>>description: Lists suggested words as the user is typing.\n//>>docs: http://api.jqueryui.com/autocomplete/\n//>>demos: http://jqueryui.com/autocomplete/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/autocomplete.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.autocomplete\", {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<input>\",\n\toptions: {\n\t\tappendTo: null,\n\t\tautoFocus: false,\n\t\tdelay: 300,\n\t\tminLength: 1,\n\t\tposition: {\n\t\t\tmy: \"left top\",\n\t\t\tat: \"left bottom\",\n\t\t\tcollision: \"none\"\n\t\t},\n\t\tsource: null,\n\n\t\t// Callbacks\n\t\tchange: null,\n\t\tclose: null,\n\t\tfocus: null,\n\t\topen: null,\n\t\tresponse: null,\n\t\tsearch: null,\n\t\tselect: null\n\t},\n\n\trequestIndex: 0,\n\tpending: 0,\n\n\t_create: function() {\n\n\t\t// Some browsers only repeat keydown events, not keypress events,\n\t\t// so we use the suppressKeyPress flag to determine if we've already\n\t\t// handled the keydown event. #7269\n\t\t// Unfortunately the code for & in keypress is the same as the up arrow,\n\t\t// so we use the suppressKeyPressRepeat flag to avoid handling keypress\n\t\t// events when we know the keydown event was used to modify the\n\t\t// search term. #7799\n\t\tvar suppressKeyPress, suppressKeyPressRepeat, suppressInput,\n\t\t\tnodeName = this.element[ 0 ].nodeName.toLowerCase(),\n\t\t\tisTextarea = nodeName === \"textarea\",\n\t\t\tisInput = nodeName === \"input\";\n\n\t\t// Textareas are always multi-line\n\t\t// Inputs are always single-line, even if inside a contentEditable element\n\t\t// IE also treats inputs as contentEditable\n\t\t// All other element types are determined by whether or not they're contentEditable\n\t\tthis.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );\n\n\t\tthis.valueMethod = this.element[ isTextarea || isInput ? \"val\" : \"text\" ];\n\t\tthis.isNewMenu = true;\n\n\t\tthis._addClass( \"ui-autocomplete-input\" );\n\t\tthis.element.attr( \"autocomplete\", \"off\" );\n\n\t\tthis._on( this.element, {\n\t\t\tkeydown: function( event ) {\n\t\t\t\tif ( this.element.prop( \"readOnly\" ) ) {\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tsuppressInput = true;\n\t\t\t\t\tsuppressKeyPressRepeat = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tsuppressKeyPress = false;\n\t\t\t\tsuppressInput = false;\n\t\t\t\tsuppressKeyPressRepeat = false;\n\t\t\t\tvar keyCode = $.ui.keyCode;\n\t\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase keyCode.PAGE_UP:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._move( \"previousPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.PAGE_DOWN:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._move( \"nextPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.UP:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._keyEvent( \"previous\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.DOWN:\n\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\tthis._keyEvent( \"next\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.ENTER:\n\n\t\t\t\t\t// when menu is open and has focus\n\t\t\t\t\tif ( this.menu.active ) {\n\n\t\t\t\t\t\t// #6055 - Opera still allows the keypress to occur\n\t\t\t\t\t\t// which causes forms to submit\n\t\t\t\t\t\tsuppressKeyPress = true;\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tthis.menu.select( event );\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.TAB:\n\t\t\t\t\tif ( this.menu.active ) {\n\t\t\t\t\t\tthis.menu.select( event );\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.ESCAPE:\n\t\t\t\t\tif ( this.menu.element.is( \":visible\" ) ) {\n\t\t\t\t\t\tif ( !this.isMultiLine ) {\n\t\t\t\t\t\t\tthis._value( this.term );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.close( event );\n\n\t\t\t\t\t\t// Different browsers have different default behavior for escape\n\t\t\t\t\t\t// Single press can mean undo or clear\n\t\t\t\t\t\t// Double press in IE means clear the whole form\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tsuppressKeyPressRepeat = true;\n\n\t\t\t\t\t// search timeout should be triggered before the input value is changed\n\t\t\t\t\tthis._searchTimeout( event );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tkeypress: function( event ) {\n\t\t\t\tif ( suppressKeyPress ) {\n\t\t\t\t\tsuppressKeyPress = false;\n\t\t\t\t\tif ( !this.isMultiLine || this.menu.element.is( \":visible\" ) ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ( suppressKeyPressRepeat ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Replicate some key handlers to allow them to repeat in Firefox and Opera\n\t\t\t\tvar keyCode = $.ui.keyCode;\n\t\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase keyCode.PAGE_UP:\n\t\t\t\t\tthis._move( \"previousPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.PAGE_DOWN:\n\t\t\t\t\tthis._move( \"nextPage\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.UP:\n\t\t\t\t\tthis._keyEvent( \"previous\", event );\n\t\t\t\t\tbreak;\n\t\t\t\tcase keyCode.DOWN:\n\t\t\t\t\tthis._keyEvent( \"next\", event );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t\tinput: function( event ) {\n\t\t\t\tif ( suppressInput ) {\n\t\t\t\t\tsuppressInput = false;\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._searchTimeout( event );\n\t\t\t},\n\t\t\tfocus: function() {\n\t\t\t\tthis.selectedItem = null;\n\t\t\t\tthis.previous = this._value();\n\t\t\t},\n\t\t\tblur: function( event ) {\n\t\t\t\tif ( this.cancelBlur ) {\n\t\t\t\t\tdelete this.cancelBlur;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tclearTimeout( this.searching );\n\t\t\t\tthis.close( event );\n\t\t\t\tthis._change( event );\n\t\t\t}\n\t\t} );\n\n\t\tthis._initSource();\n\t\tthis.menu = $( \"<ul>\" )\n\t\t\t.appendTo( this._appendTo() )\n\t\t\t.menu( {\n\n\t\t\t\t// disable ARIA support, the live region takes care of that\n\t\t\t\trole: null\n\t\t\t} )\n\t\t\t.hide()\n\t\t\t.menu( \"instance\" );\n\n\t\tthis._addClass( this.menu.element, \"ui-autocomplete\", \"ui-front\" );\n\t\tthis._on( this.menu.element, {\n\t\t\tmousedown: function( event ) {\n\n\t\t\t\t// prevent moving focus out of the text field\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// IE doesn't prevent moving focus even with event.preventDefault()\n\t\t\t\t// so we set a flag to know when we should ignore the blur event\n\t\t\t\tthis.cancelBlur = true;\n\t\t\t\tthis._delay( function() {\n\t\t\t\t\tdelete this.cancelBlur;\n\n\t\t\t\t\t// Support: IE 8 only\n\t\t\t\t\t// Right clicking a menu item or selecting text from the menu items will\n\t\t\t\t\t// result in focus moving out of the input. However, we've already received\n\t\t\t\t\t// and ignored the blur event because of the cancelBlur flag set above. So\n\t\t\t\t\t// we restore focus to ensure that the menu closes properly based on the user's\n\t\t\t\t\t// next actions.\n\t\t\t\t\tif ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {\n\t\t\t\t\t\tthis.element.trigger( \"focus\" );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t},\n\t\t\tmenufocus: function( event, ui ) {\n\t\t\t\tvar label, item;\n\n\t\t\t\t// support: Firefox\n\t\t\t\t// Prevent accidental activation of menu items in Firefox (#7024 #9118)\n\t\t\t\tif ( this.isNewMenu ) {\n\t\t\t\t\tthis.isNewMenu = false;\n\t\t\t\t\tif ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {\n\t\t\t\t\t\tthis.menu.blur();\n\n\t\t\t\t\t\tthis.document.one( \"mousemove\", function() {\n\t\t\t\t\t\t\t$( event.target ).trigger( event.originalEvent );\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\titem = ui.item.data( \"ui-autocomplete-item\" );\n\t\t\t\tif ( false !== this._trigger( \"focus\", event, { item: item } ) ) {\n\n\t\t\t\t\t// use value to match what will end up in the input, if it was a key event\n\t\t\t\t\tif ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {\n\t\t\t\t\t\tthis._value( item.value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Announce the value in the liveRegion\n\t\t\t\tlabel = ui.item.attr( \"aria-label\" ) || item.value;\n\t\t\t\tif ( label && $.trim( label ).length ) {\n\t\t\t\t\tthis.liveRegion.children().hide();\n\t\t\t\t\t$( \"<div>\" ).text( label ).appendTo( this.liveRegion );\n\t\t\t\t}\n\t\t\t},\n\t\t\tmenuselect: function( event, ui ) {\n\t\t\t\tvar item = ui.item.data( \"ui-autocomplete-item\" ),\n\t\t\t\t\tprevious = this.previous;\n\n\t\t\t\t// Only trigger when focus was lost (click on menu)\n\t\t\t\tif ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {\n\t\t\t\t\tthis.element.trigger( \"focus\" );\n\t\t\t\t\tthis.previous = previous;\n\n\t\t\t\t\t// #6109 - IE triggers two focus events and the second\n\t\t\t\t\t// is asynchronous, so we need to reset the previous\n\t\t\t\t\t// term synchronously and asynchronously :-(\n\t\t\t\t\tthis._delay( function() {\n\t\t\t\t\t\tthis.previous = previous;\n\t\t\t\t\t\tthis.selectedItem = item;\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\tif ( false !== this._trigger( \"select\", event, { item: item } ) ) {\n\t\t\t\t\tthis._value( item.value );\n\t\t\t\t}\n\n\t\t\t\t// reset the term after the select event\n\t\t\t\t// this allows custom select handling to work properly\n\t\t\t\tthis.term = this._value();\n\n\t\t\t\tthis.close( event );\n\t\t\t\tthis.selectedItem = item;\n\t\t\t}\n\t\t} );\n\n\t\tthis.liveRegion = $( \"<div>\", {\n\t\t\trole: \"status\",\n\t\t\t\"aria-live\": \"assertive\",\n\t\t\t\"aria-relevant\": \"additions\"\n\t\t} )\n\t\t\t.appendTo( this.document[ 0 ].body );\n\n\t\tthis._addClass( this.liveRegion, null, \"ui-helper-hidden-accessible\" );\n\n\t\t// Turning off autocomplete prevents the browser from remembering the\n\t\t// value when navigating through history, so we re-enable autocomplete\n\t\t// if the page is unloaded before the widget is destroyed. #7790\n\t\tthis._on( this.window, {\n\t\t\tbeforeunload: function() {\n\t\t\t\tthis.element.removeAttr( \"autocomplete\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_destroy: function() {\n\t\tclearTimeout( this.searching );\n\t\tthis.element.removeAttr( \"autocomplete\" );\n\t\tthis.menu.element.remove();\n\t\tthis.liveRegion.remove();\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tthis._super( key, value );\n\t\tif ( key === \"source\" ) {\n\t\t\tthis._initSource();\n\t\t}\n\t\tif ( key === \"appendTo\" ) {\n\t\t\tthis.menu.element.appendTo( this._appendTo() );\n\t\t}\n\t\tif ( key === \"disabled\" && value && this.xhr ) {\n\t\t\tthis.xhr.abort();\n\t\t}\n\t},\n\n\t_isEventTargetInWidget: function( event ) {\n\t\tvar menuElement = this.menu.element[ 0 ];\n\n\t\treturn event.target === this.element[ 0 ] ||\n\t\t\tevent.target === menuElement ||\n\t\t\t$.contains( menuElement, event.target );\n\t},\n\n\t_closeOnClickOutside: function( event ) {\n\t\tif ( !this._isEventTargetInWidget( event ) ) {\n\t\t\tthis.close();\n\t\t}\n\t},\n\n\t_appendTo: function() {\n\t\tvar element = this.options.appendTo;\n\n\t\tif ( element ) {\n\t\t\telement = element.jquery || element.nodeType ?\n\t\t\t\t$( element ) :\n\t\t\t\tthis.document.find( element ).eq( 0 );\n\t\t}\n\n\t\tif ( !element || !element[ 0 ] ) {\n\t\t\telement = this.element.closest( \".ui-front, dialog\" );\n\t\t}\n\n\t\tif ( !element.length ) {\n\t\t\telement = this.document[ 0 ].body;\n\t\t}\n\n\t\treturn element;\n\t},\n\n\t_initSource: function() {\n\t\tvar array, url,\n\t\t\tthat = this;\n\t\tif ( $.isArray( this.options.source ) ) {\n\t\t\tarray = this.options.source;\n\t\t\tthis.source = function( request, response ) {\n\t\t\t\tresponse( $.ui.autocomplete.filter( array, request.term ) );\n\t\t\t};\n\t\t} else if ( typeof this.options.source === \"string\" ) {\n\t\t\turl = this.options.source;\n\t\t\tthis.source = function( request, response ) {\n\t\t\t\tif ( that.xhr ) {\n\t\t\t\t\tthat.xhr.abort();\n\t\t\t\t}\n\t\t\t\tthat.xhr = $.ajax( {\n\t\t\t\t\turl: url,\n\t\t\t\t\tdata: request,\n\t\t\t\t\tdataType: \"json\",\n\t\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\t\tresponse( data );\n\t\t\t\t\t},\n\t\t\t\t\terror: function() {\n\t\t\t\t\t\tresponse( [] );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t};\n\t\t} else {\n\t\t\tthis.source = this.options.source;\n\t\t}\n\t},\n\n\t_searchTimeout: function( event ) {\n\t\tclearTimeout( this.searching );\n\t\tthis.searching = this._delay( function() {\n\n\t\t\t// Search if the value has changed, or if the user retypes the same value (see #7434)\n\t\t\tvar equalValues = this.term === this._value(),\n\t\t\t\tmenuVisible = this.menu.element.is( \":visible\" ),\n\t\t\t\tmodifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;\n\n\t\t\tif ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {\n\t\t\t\tthis.selectedItem = null;\n\t\t\t\tthis.search( null, event );\n\t\t\t}\n\t\t}, this.options.delay );\n\t},\n\n\tsearch: function( value, event ) {\n\t\tvalue = value != null ? value : this._value();\n\n\t\t// Always save the actual value, not the one passed as an argument\n\t\tthis.term = this._value();\n\n\t\tif ( value.length < this.options.minLength ) {\n\t\t\treturn this.close( event );\n\t\t}\n\n\t\tif ( this._trigger( \"search\", event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn this._search( value );\n\t},\n\n\t_search: function( value ) {\n\t\tthis.pending++;\n\t\tthis._addClass( \"ui-autocomplete-loading\" );\n\t\tthis.cancelSearch = false;\n\n\t\tthis.source( { term: value }, this._response() );\n\t},\n\n\t_response: function() {\n\t\tvar index = ++this.requestIndex;\n\n\t\treturn $.proxy( function( content ) {\n\t\t\tif ( index === this.requestIndex ) {\n\t\t\t\tthis.__response( content );\n\t\t\t}\n\n\t\t\tthis.pending--;\n\t\t\tif ( !this.pending ) {\n\t\t\t\tthis._removeClass( \"ui-autocomplete-loading\" );\n\t\t\t}\n\t\t}, this );\n\t},\n\n\t__response: function( content ) {\n\t\tif ( content ) {\n\t\t\tcontent = this._normalize( content );\n\t\t}\n\t\tthis._trigger( \"response\", null, { content: content } );\n\t\tif ( !this.options.disabled && content && content.length && !this.cancelSearch ) {\n\t\t\tthis._suggest( content );\n\t\t\tthis._trigger( \"open\" );\n\t\t} else {\n\n\t\t\t// use ._close() instead of .close() so we don't cancel future searches\n\t\t\tthis._close();\n\t\t}\n\t},\n\n\tclose: function( event ) {\n\t\tthis.cancelSearch = true;\n\t\tthis._close( event );\n\t},\n\n\t_close: function( event ) {\n\n\t\t// Remove the handler that closes the menu on outside clicks\n\t\tthis._off( this.document, \"mousedown\" );\n\n\t\tif ( this.menu.element.is( \":visible\" ) ) {\n\t\t\tthis.menu.element.hide();\n\t\t\tthis.menu.blur();\n\t\t\tthis.isNewMenu = true;\n\t\t\tthis._trigger( \"close\", event );\n\t\t}\n\t},\n\n\t_change: function( event ) {\n\t\tif ( this.previous !== this._value() ) {\n\t\t\tthis._trigger( \"change\", event, { item: this.selectedItem } );\n\t\t}\n\t},\n\n\t_normalize: function( items ) {\n\n\t\t// assume all items have the right format when the first item is complete\n\t\tif ( items.length && items[ 0 ].label && items[ 0 ].value ) {\n\t\t\treturn items;\n\t\t}\n\t\treturn $.map( items, function( item ) {\n\t\t\tif ( typeof item === \"string\" ) {\n\t\t\t\treturn {\n\t\t\t\t\tlabel: item,\n\t\t\t\t\tvalue: item\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn $.extend( {}, item, {\n\t\t\t\tlabel: item.label || item.value,\n\t\t\t\tvalue: item.value || item.label\n\t\t\t} );\n\t\t} );\n\t},\n\n\t_suggest: function( items ) {\n\t\tvar ul = this.menu.element.empty();\n\t\tthis._renderMenu( ul, items );\n\t\tthis.isNewMenu = true;\n\t\tthis.menu.refresh();\n\n\t\t// Size and position menu\n\t\tul.show();\n\t\tthis._resizeMenu();\n\t\tul.position( $.extend( {\n\t\t\tof: this.element\n\t\t}, this.options.position ) );\n\n\t\tif ( this.options.autoFocus ) {\n\t\t\tthis.menu.next();\n\t\t}\n\n\t\t// Listen for interactions outside of the widget (#6642)\n\t\tthis._on( this.document, {\n\t\t\tmousedown: \"_closeOnClickOutside\"\n\t\t} );\n\t},\n\n\t_resizeMenu: function() {\n\t\tvar ul = this.menu.element;\n\t\tul.outerWidth( Math.max(\n\n\t\t\t// Firefox wraps long text (possibly a rounding bug)\n\t\t\t// so we add 1px to avoid the wrapping (#7513)\n\t\t\tul.width( \"\" ).outerWidth() + 1,\n\t\t\tthis.element.outerWidth()\n\t\t) );\n\t},\n\n\t_renderMenu: function( ul, items ) {\n\t\tvar that = this;\n\t\t$.each( items, function( index, item ) {\n\t\t\tthat._renderItemData( ul, item );\n\t\t} );\n\t},\n\n\t_renderItemData: function( ul, item ) {\n\t\treturn this._renderItem( ul, item ).data( \"ui-autocomplete-item\", item );\n\t},\n\n\t_renderItem: function( ul, item ) {\n\t\treturn $( \"<li>\" )\n\t\t\t.append( $( \"<div>\" ).text( item.label ) )\n\t\t\t.appendTo( ul );\n\t},\n\n\t_move: function( direction, event ) {\n\t\tif ( !this.menu.element.is( \":visible\" ) ) {\n\t\t\tthis.search( null, event );\n\t\t\treturn;\n\t\t}\n\t\tif ( this.menu.isFirstItem() && /^previous/.test( direction ) ||\n\t\t\t\tthis.menu.isLastItem() && /^next/.test( direction ) ) {\n\n\t\t\tif ( !this.isMultiLine ) {\n\t\t\t\tthis._value( this.term );\n\t\t\t}\n\n\t\t\tthis.menu.blur();\n\t\t\treturn;\n\t\t}\n\t\tthis.menu[ direction ]( event );\n\t},\n\n\twidget: function() {\n\t\treturn this.menu.element;\n\t},\n\n\t_value: function() {\n\t\treturn this.valueMethod.apply( this.element, arguments );\n\t},\n\n\t_keyEvent: function( keyEvent, event ) {\n\t\tif ( !this.isMultiLine || this.menu.element.is( \":visible\" ) ) {\n\t\t\tthis._move( keyEvent, event );\n\n\t\t\t// Prevents moving cursor to beginning/end of the text field in some browsers\n\t\t\tevent.preventDefault();\n\t\t}\n\t},\n\n\t// Support: Chrome <=50\n\t// We should be able to just use this.element.prop( \"isContentEditable\" )\n\t// but hidden elements always report false in Chrome.\n\t// https://code.google.com/p/chromium/issues/detail?id=313082\n\t_isContentEditable: function( element ) {\n\t\tif ( !element.length ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar editable = element.prop( \"contentEditable\" );\n\n\t\tif ( editable === \"inherit\" ) {\n\t\t  return this._isContentEditable( element.parent() );\n\t\t}\n\n\t\treturn editable === \"true\";\n\t}\n} );\n\n$.extend( $.ui.autocomplete, {\n\tescapeRegex: function( value ) {\n\t\treturn value.replace( /[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, \"\\\\$&\" );\n\t},\n\tfilter: function( array, term ) {\n\t\tvar matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), \"i\" );\n\t\treturn $.grep( array, function( value ) {\n\t\t\treturn matcher.test( value.label || value.value || value );\n\t\t} );\n\t}\n} );\n\n// Live region extension, adding a `messages` option\n// NOTE: This is an experimental API. We are still investigating\n// a full solution for string manipulation and internationalization.\n$.widget( \"ui.autocomplete\", $.ui.autocomplete, {\n\toptions: {\n\t\tmessages: {\n\t\t\tnoResults: \"No search results.\",\n\t\t\tresults: function( amount ) {\n\t\t\t\treturn amount + ( amount > 1 ? \" results are\" : \" result is\" ) +\n\t\t\t\t\t\" available, use up and down arrow keys to navigate.\";\n\t\t\t}\n\t\t}\n\t},\n\n\t__response: function( content ) {\n\t\tvar message;\n\t\tthis._superApply( arguments );\n\t\tif ( this.options.disabled || this.cancelSearch ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( content && content.length ) {\n\t\t\tmessage = this.options.messages.results( content.length );\n\t\t} else {\n\t\t\tmessage = this.options.messages.noResults;\n\t\t}\n\t\tthis.liveRegion.children().hide();\n\t\t$( \"<div>\" ).text( message ).appendTo( this.liveRegion );\n\t}\n} );\n\nvar widgetsAutocomplete = $.ui.autocomplete;\n\n\n/*!\n * jQuery UI Controlgroup 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Controlgroup\n//>>group: Widgets\n//>>description: Visually groups form control widgets\n//>>docs: http://api.jqueryui.com/controlgroup/\n//>>demos: http://jqueryui.com/controlgroup/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/controlgroup.css\n//>>css.theme: ../../themes/base/theme.css\n\n\nvar controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;\n\nvar widgetsControlgroup = $.widget( \"ui.controlgroup\", {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<div>\",\n\toptions: {\n\t\tdirection: \"horizontal\",\n\t\tdisabled: null,\n\t\tonlyVisible: true,\n\t\titems: {\n\t\t\t\"button\": \"input[type=button], input[type=submit], input[type=reset], button, a\",\n\t\t\t\"controlgroupLabel\": \".ui-controlgroup-label\",\n\t\t\t\"checkboxradio\": \"input[type='checkbox'], input[type='radio']\",\n\t\t\t\"selectmenu\": \"select\",\n\t\t\t\"spinner\": \".ui-spinner-input\"\n\t\t}\n\t},\n\n\t_create: function() {\n\t\tthis._enhance();\n\t},\n\n\t// To support the enhanced option in jQuery Mobile, we isolate DOM manipulation\n\t_enhance: function() {\n\t\tthis.element.attr( \"role\", \"toolbar\" );\n\t\tthis.refresh();\n\t},\n\n\t_destroy: function() {\n\t\tthis._callChildMethod( \"destroy\" );\n\t\tthis.childWidgets.removeData( \"ui-controlgroup-data\" );\n\t\tthis.element.removeAttr( \"role\" );\n\t\tif ( this.options.items.controlgroupLabel ) {\n\t\t\tthis.element\n\t\t\t\t.find( this.options.items.controlgroupLabel )\n\t\t\t\t.find( \".ui-controlgroup-label-contents\" )\n\t\t\t\t.contents().unwrap();\n\t\t}\n\t},\n\n\t_initWidgets: function() {\n\t\tvar that = this,\n\t\t\tchildWidgets = [];\n\n\t\t// First we iterate over each of the items options\n\t\t$.each( this.options.items, function( widget, selector ) {\n\t\t\tvar labels;\n\t\t\tvar options = {};\n\n\t\t\t// Make sure the widget has a selector set\n\t\t\tif ( !selector ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( widget === \"controlgroupLabel\" ) {\n\t\t\t\tlabels = that.element.find( selector );\n\t\t\t\tlabels.each( function() {\n\t\t\t\t\tvar element = $( this );\n\n\t\t\t\t\tif ( element.children( \".ui-controlgroup-label-contents\" ).length ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\telement.contents()\n\t\t\t\t\t\t.wrapAll( \"<span class='ui-controlgroup-label-contents'></span>\" );\n\t\t\t\t} );\n\t\t\t\tthat._addClass( labels, null, \"ui-widget ui-widget-content ui-state-default\" );\n\t\t\t\tchildWidgets = childWidgets.concat( labels.get() );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Make sure the widget actually exists\n\t\t\tif ( !$.fn[ widget ] ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// We assume everything is in the middle to start because we can't determine\n\t\t\t// first / last elements until all enhancments are done.\n\t\t\tif ( that[ \"_\" + widget + \"Options\" ] ) {\n\t\t\t\toptions = that[ \"_\" + widget + \"Options\" ]( \"middle\" );\n\t\t\t} else {\n\t\t\t\toptions = { classes: {} };\n\t\t\t}\n\n\t\t\t// Find instances of this widget inside controlgroup and init them\n\t\t\tthat.element\n\t\t\t\t.find( selector )\n\t\t\t\t.each( function() {\n\t\t\t\t\tvar element = $( this );\n\t\t\t\t\tvar instance = element[ widget ]( \"instance\" );\n\n\t\t\t\t\t// We need to clone the default options for this type of widget to avoid\n\t\t\t\t\t// polluting the variable options which has a wider scope than a single widget.\n\t\t\t\t\tvar instanceOptions = $.widget.extend( {}, options );\n\n\t\t\t\t\t// If the button is the child of a spinner ignore it\n\t\t\t\t\t// TODO: Find a more generic solution\n\t\t\t\t\tif ( widget === \"button\" && element.parent( \".ui-spinner\" ).length ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Create the widget if it doesn't exist\n\t\t\t\t\tif ( !instance ) {\n\t\t\t\t\t\tinstance = element[ widget ]()[ widget ]( \"instance\" );\n\t\t\t\t\t}\n\t\t\t\t\tif ( instance ) {\n\t\t\t\t\t\tinstanceOptions.classes =\n\t\t\t\t\t\t\tthat._resolveClassesValues( instanceOptions.classes, instance );\n\t\t\t\t\t}\n\t\t\t\t\telement[ widget ]( instanceOptions );\n\n\t\t\t\t\t// Store an instance of the controlgroup to be able to reference\n\t\t\t\t\t// from the outermost element for changing options and refresh\n\t\t\t\t\tvar widgetElement = element[ widget ]( \"widget\" );\n\t\t\t\t\t$.data( widgetElement[ 0 ], \"ui-controlgroup-data\",\n\t\t\t\t\t\tinstance ? instance : element[ widget ]( \"instance\" ) );\n\n\t\t\t\t\tchildWidgets.push( widgetElement[ 0 ] );\n\t\t\t\t} );\n\t\t} );\n\n\t\tthis.childWidgets = $( $.unique( childWidgets ) );\n\t\tthis._addClass( this.childWidgets, \"ui-controlgroup-item\" );\n\t},\n\n\t_callChildMethod: function( method ) {\n\t\tthis.childWidgets.each( function() {\n\t\t\tvar element = $( this ),\n\t\t\t\tdata = element.data( \"ui-controlgroup-data\" );\n\t\t\tif ( data && data[ method ] ) {\n\t\t\t\tdata[ method ]();\n\t\t\t}\n\t\t} );\n\t},\n\n\t_updateCornerClass: function( element, position ) {\n\t\tvar remove = \"ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all\";\n\t\tvar add = this._buildSimpleOptions( position, \"label\" ).classes.label;\n\n\t\tthis._removeClass( element, null, remove );\n\t\tthis._addClass( element, null, add );\n\t},\n\n\t_buildSimpleOptions: function( position, key ) {\n\t\tvar direction = this.options.direction === \"vertical\";\n\t\tvar result = {\n\t\t\tclasses: {}\n\t\t};\n\t\tresult.classes[ key ] = {\n\t\t\t\"middle\": \"\",\n\t\t\t\"first\": \"ui-corner-\" + ( direction ? \"top\" : \"left\" ),\n\t\t\t\"last\": \"ui-corner-\" + ( direction ? \"bottom\" : \"right\" ),\n\t\t\t\"only\": \"ui-corner-all\"\n\t\t}[ position ];\n\n\t\treturn result;\n\t},\n\n\t_spinnerOptions: function( position ) {\n\t\tvar options = this._buildSimpleOptions( position, \"ui-spinner\" );\n\n\t\toptions.classes[ \"ui-spinner-up\" ] = \"\";\n\t\toptions.classes[ \"ui-spinner-down\" ] = \"\";\n\n\t\treturn options;\n\t},\n\n\t_buttonOptions: function( position ) {\n\t\treturn this._buildSimpleOptions( position, \"ui-button\" );\n\t},\n\n\t_checkboxradioOptions: function( position ) {\n\t\treturn this._buildSimpleOptions( position, \"ui-checkboxradio-label\" );\n\t},\n\n\t_selectmenuOptions: function( position ) {\n\t\tvar direction = this.options.direction === \"vertical\";\n\t\treturn {\n\t\t\twidth: direction ? \"auto\" : false,\n\t\t\tclasses: {\n\t\t\t\tmiddle: {\n\t\t\t\t\t\"ui-selectmenu-button-open\": \"\",\n\t\t\t\t\t\"ui-selectmenu-button-closed\": \"\"\n\t\t\t\t},\n\t\t\t\tfirst: {\n\t\t\t\t\t\"ui-selectmenu-button-open\": \"ui-corner-\" + ( direction ? \"top\" : \"tl\" ),\n\t\t\t\t\t\"ui-selectmenu-button-closed\": \"ui-corner-\" + ( direction ? \"top\" : \"left\" )\n\t\t\t\t},\n\t\t\t\tlast: {\n\t\t\t\t\t\"ui-selectmenu-button-open\": direction ? \"\" : \"ui-corner-tr\",\n\t\t\t\t\t\"ui-selectmenu-button-closed\": \"ui-corner-\" + ( direction ? \"bottom\" : \"right\" )\n\t\t\t\t},\n\t\t\t\tonly: {\n\t\t\t\t\t\"ui-selectmenu-button-open\": \"ui-corner-top\",\n\t\t\t\t\t\"ui-selectmenu-button-closed\": \"ui-corner-all\"\n\t\t\t\t}\n\n\t\t\t}[ position ]\n\t\t};\n\t},\n\n\t_resolveClassesValues: function( classes, instance ) {\n\t\tvar result = {};\n\t\t$.each( classes, function( key ) {\n\t\t\tvar current = instance.options.classes[ key ] || \"\";\n\t\t\tcurrent = $.trim( current.replace( controlgroupCornerRegex, \"\" ) );\n\t\t\tresult[ key ] = ( current + \" \" + classes[ key ] ).replace( /\\s+/g, \" \" );\n\t\t} );\n\t\treturn result;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"direction\" ) {\n\t\t\tthis._removeClass( \"ui-controlgroup-\" + this.options.direction );\n\t\t}\n\n\t\tthis._super( key, value );\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis._callChildMethod( value ? \"disable\" : \"enable\" );\n\t\t\treturn;\n\t\t}\n\n\t\tthis.refresh();\n\t},\n\n\trefresh: function() {\n\t\tvar children,\n\t\t\tthat = this;\n\n\t\tthis._addClass( \"ui-controlgroup ui-controlgroup-\" + this.options.direction );\n\n\t\tif ( this.options.direction === \"horizontal\" ) {\n\t\t\tthis._addClass( null, \"ui-helper-clearfix\" );\n\t\t}\n\t\tthis._initWidgets();\n\n\t\tchildren = this.childWidgets;\n\n\t\t// We filter here because we need to track all childWidgets not just the visible ones\n\t\tif ( this.options.onlyVisible ) {\n\t\t\tchildren = children.filter( \":visible\" );\n\t\t}\n\n\t\tif ( children.length ) {\n\n\t\t\t// We do this last because we need to make sure all enhancment is done\n\t\t\t// before determining first and last\n\t\t\t$.each( [ \"first\", \"last\" ], function( index, value ) {\n\t\t\t\tvar instance = children[ value ]().data( \"ui-controlgroup-data\" );\n\n\t\t\t\tif ( instance && that[ \"_\" + instance.widgetName + \"Options\" ] ) {\n\t\t\t\t\tvar options = that[ \"_\" + instance.widgetName + \"Options\" ](\n\t\t\t\t\t\tchildren.length === 1 ? \"only\" : value\n\t\t\t\t\t);\n\t\t\t\t\toptions.classes = that._resolveClassesValues( options.classes, instance );\n\t\t\t\t\tinstance.element[ instance.widgetName ]( options );\n\t\t\t\t} else {\n\t\t\t\t\tthat._updateCornerClass( children[ value ](), value );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// Finally call the refresh method on each of the child widgets.\n\t\t\tthis._callChildMethod( \"refresh\" );\n\t\t}\n\t}\n} );\n\n/*!\n * jQuery UI Checkboxradio 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Checkboxradio\n//>>group: Widgets\n//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.\n//>>docs: http://api.jqueryui.com/checkboxradio/\n//>>demos: http://jqueryui.com/checkboxradio/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/button.css\n//>>css.structure: ../../themes/base/checkboxradio.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.checkboxradio\", [ $.ui.formResetMixin, {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tdisabled: null,\n\t\tlabel: null,\n\t\ticon: true,\n\t\tclasses: {\n\t\t\t\"ui-checkboxradio-label\": \"ui-corner-all\",\n\t\t\t\"ui-checkboxradio-icon\": \"ui-corner-all\"\n\t\t}\n\t},\n\n\t_getCreateOptions: function() {\n\t\tvar disabled, labels;\n\t\tvar that = this;\n\t\tvar options = this._super() || {};\n\n\t\t// We read the type here, because it makes more sense to throw a element type error first,\n\t\t// rather then the error for lack of a label. Often if its the wrong type, it\n\t\t// won't have a label (e.g. calling on a div, btn, etc)\n\t\tthis._readType();\n\n\t\tlabels = this.element.labels();\n\n\t\t// If there are multiple labels, use the last one\n\t\tthis.label = $( labels[ labels.length - 1 ] );\n\t\tif ( !this.label.length ) {\n\t\t\t$.error( \"No label found for checkboxradio widget\" );\n\t\t}\n\n\t\tthis.originalLabel = \"\";\n\n\t\t// We need to get the label text but this may also need to make sure it does not contain the\n\t\t// input itself.\n\t\tthis.label.contents().not( this.element[ 0 ] ).each( function() {\n\n\t\t\t// The label contents could be text, html, or a mix. We concat each element to get a\n\t\t\t// string representation of the label, without the input as part of it.\n\t\t\tthat.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML;\n\t\t} );\n\n\t\t// Set the label option if we found label text\n\t\tif ( this.originalLabel ) {\n\t\t\toptions.label = this.originalLabel;\n\t\t}\n\n\t\tdisabled = this.element[ 0 ].disabled;\n\t\tif ( disabled != null ) {\n\t\t\toptions.disabled = disabled;\n\t\t}\n\t\treturn options;\n\t},\n\n\t_create: function() {\n\t\tvar checked = this.element[ 0 ].checked;\n\n\t\tthis._bindFormResetHandler();\n\n\t\tif ( this.options.disabled == null ) {\n\t\t\tthis.options.disabled = this.element[ 0 ].disabled;\n\t\t}\n\n\t\tthis._setOption( \"disabled\", this.options.disabled );\n\t\tthis._addClass( \"ui-checkboxradio\", \"ui-helper-hidden-accessible\" );\n\t\tthis._addClass( this.label, \"ui-checkboxradio-label\", \"ui-button ui-widget\" );\n\n\t\tif ( this.type === \"radio\" ) {\n\t\t\tthis._addClass( this.label, \"ui-checkboxradio-radio-label\" );\n\t\t}\n\n\t\tif ( this.options.label && this.options.label !== this.originalLabel ) {\n\t\t\tthis._updateLabel();\n\t\t} else if ( this.originalLabel ) {\n\t\t\tthis.options.label = this.originalLabel;\n\t\t}\n\n\t\tthis._enhance();\n\n\t\tif ( checked ) {\n\t\t\tthis._addClass( this.label, \"ui-checkboxradio-checked\", \"ui-state-active\" );\n\t\t\tif ( this.icon ) {\n\t\t\t\tthis._addClass( this.icon, null, \"ui-state-hover\" );\n\t\t\t}\n\t\t}\n\n\t\tthis._on( {\n\t\t\tchange: \"_toggleClasses\",\n\t\t\tfocus: function() {\n\t\t\t\tthis._addClass( this.label, null, \"ui-state-focus ui-visual-focus\" );\n\t\t\t},\n\t\t\tblur: function() {\n\t\t\t\tthis._removeClass( this.label, null, \"ui-state-focus ui-visual-focus\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_readType: function() {\n\t\tvar nodeName = this.element[ 0 ].nodeName.toLowerCase();\n\t\tthis.type = this.element[ 0 ].type;\n\t\tif ( nodeName !== \"input\" || !/radio|checkbox/.test( this.type ) ) {\n\t\t\t$.error( \"Can't create checkboxradio on element.nodeName=\" + nodeName +\n\t\t\t\t\" and element.type=\" + this.type );\n\t\t}\n\t},\n\n\t// Support jQuery Mobile enhanced option\n\t_enhance: function() {\n\t\tthis._updateIcon( this.element[ 0 ].checked );\n\t},\n\n\twidget: function() {\n\t\treturn this.label;\n\t},\n\n\t_getRadioGroup: function() {\n\t\tvar group;\n\t\tvar name = this.element[ 0 ].name;\n\t\tvar nameSelector = \"input[name='\" + $.ui.escapeSelector( name ) + \"']\";\n\n\t\tif ( !name ) {\n\t\t\treturn $( [] );\n\t\t}\n\n\t\tif ( this.form.length ) {\n\t\t\tgroup = $( this.form[ 0 ].elements ).filter( nameSelector );\n\t\t} else {\n\n\t\t\t// Not inside a form, check all inputs that also are not inside a form\n\t\t\tgroup = $( nameSelector ).filter( function() {\n\t\t\t\treturn $( this ).form().length === 0;\n\t\t\t} );\n\t\t}\n\n\t\treturn group.not( this.element );\n\t},\n\n\t_toggleClasses: function() {\n\t\tvar checked = this.element[ 0 ].checked;\n\t\tthis._toggleClass( this.label, \"ui-checkboxradio-checked\", \"ui-state-active\", checked );\n\n\t\tif ( this.options.icon && this.type === \"checkbox\" ) {\n\t\t\tthis._toggleClass( this.icon, null, \"ui-icon-check ui-state-checked\", checked )\n\t\t\t\t._toggleClass( this.icon, null, \"ui-icon-blank\", !checked );\n\t\t}\n\n\t\tif ( this.type === \"radio\" ) {\n\t\t\tthis._getRadioGroup()\n\t\t\t\t.each( function() {\n\t\t\t\t\tvar instance = $( this ).checkboxradio( \"instance\" );\n\n\t\t\t\t\tif ( instance ) {\n\t\t\t\t\t\tinstance._removeClass( instance.label,\n\t\t\t\t\t\t\t\"ui-checkboxradio-checked\", \"ui-state-active\" );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tthis._unbindFormResetHandler();\n\n\t\tif ( this.icon ) {\n\t\t\tthis.icon.remove();\n\t\t\tthis.iconSpace.remove();\n\t\t}\n\t},\n\n\t_setOption: function( key, value ) {\n\n\t\t// We don't allow the value to be set to nothing\n\t\tif ( key === \"label\" && !value ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis._toggleClass( this.label, null, \"ui-state-disabled\", value );\n\t\t\tthis.element[ 0 ].disabled = value;\n\n\t\t\t// Don't refresh when setting disabled\n\t\t\treturn;\n\t\t}\n\t\tthis.refresh();\n\t},\n\n\t_updateIcon: function( checked ) {\n\t\tvar toAdd = \"ui-icon ui-icon-background \";\n\n\t\tif ( this.options.icon ) {\n\t\t\tif ( !this.icon ) {\n\t\t\t\tthis.icon = $( \"<span>\" );\n\t\t\t\tthis.iconSpace = $( \"<span> </span>\" );\n\t\t\t\tthis._addClass( this.iconSpace, \"ui-checkboxradio-icon-space\" );\n\t\t\t}\n\n\t\t\tif ( this.type === \"checkbox\" ) {\n\t\t\t\ttoAdd += checked ? \"ui-icon-check ui-state-checked\" : \"ui-icon-blank\";\n\t\t\t\tthis._removeClass( this.icon, null, checked ? \"ui-icon-blank\" : \"ui-icon-check\" );\n\t\t\t} else {\n\t\t\t\ttoAdd += \"ui-icon-blank\";\n\t\t\t}\n\t\t\tthis._addClass( this.icon, \"ui-checkboxradio-icon\", toAdd );\n\t\t\tif ( !checked ) {\n\t\t\t\tthis._removeClass( this.icon, null, \"ui-icon-check ui-state-checked\" );\n\t\t\t}\n\t\t\tthis.icon.prependTo( this.label ).after( this.iconSpace );\n\t\t} else if ( this.icon !== undefined ) {\n\t\t\tthis.icon.remove();\n\t\t\tthis.iconSpace.remove();\n\t\t\tdelete this.icon;\n\t\t}\n\t},\n\n\t_updateLabel: function() {\n\n\t\t// Remove the contents of the label ( minus the icon, icon space, and input )\n\t\tvar contents = this.label.contents().not( this.element[ 0 ] );\n\t\tif ( this.icon ) {\n\t\t\tcontents = contents.not( this.icon[ 0 ] );\n\t\t}\n\t\tif ( this.iconSpace ) {\n\t\t\tcontents = contents.not( this.iconSpace[ 0 ] );\n\t\t}\n\t\tcontents.remove();\n\n\t\tthis.label.append( this.options.label );\n\t},\n\n\trefresh: function() {\n\t\tvar checked = this.element[ 0 ].checked,\n\t\t\tisDisabled = this.element[ 0 ].disabled;\n\n\t\tthis._updateIcon( checked );\n\t\tthis._toggleClass( this.label, \"ui-checkboxradio-checked\", \"ui-state-active\", checked );\n\t\tif ( this.options.label !== null ) {\n\t\t\tthis._updateLabel();\n\t\t}\n\n\t\tif ( isDisabled !== this.options.disabled ) {\n\t\t\tthis._setOptions( { \"disabled\": isDisabled } );\n\t\t}\n\t}\n\n} ] );\n\nvar widgetsCheckboxradio = $.ui.checkboxradio;\n\n\n/*!\n * jQuery UI Button 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Button\n//>>group: Widgets\n//>>description: Enhances a form with themeable buttons.\n//>>docs: http://api.jqueryui.com/button/\n//>>demos: http://jqueryui.com/button/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/button.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.button\", {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<button>\",\n\toptions: {\n\t\tclasses: {\n\t\t\t\"ui-button\": \"ui-corner-all\"\n\t\t},\n\t\tdisabled: null,\n\t\ticon: null,\n\t\ticonPosition: \"beginning\",\n\t\tlabel: null,\n\t\tshowLabel: true\n\t},\n\n\t_getCreateOptions: function() {\n\t\tvar disabled,\n\n\t\t\t// This is to support cases like in jQuery Mobile where the base widget does have\n\t\t\t// an implementation of _getCreateOptions\n\t\t\toptions = this._super() || {};\n\n\t\tthis.isInput = this.element.is( \"input\" );\n\n\t\tdisabled = this.element[ 0 ].disabled;\n\t\tif ( disabled != null ) {\n\t\t\toptions.disabled = disabled;\n\t\t}\n\n\t\tthis.originalLabel = this.isInput ? this.element.val() : this.element.html();\n\t\tif ( this.originalLabel ) {\n\t\t\toptions.label = this.originalLabel;\n\t\t}\n\n\t\treturn options;\n\t},\n\n\t_create: function() {\n\t\tif ( !this.option.showLabel & !this.options.icon ) {\n\t\t\tthis.options.showLabel = true;\n\t\t}\n\n\t\t// We have to check the option again here even though we did in _getCreateOptions,\n\t\t// because null may have been passed on init which would override what was set in\n\t\t// _getCreateOptions\n\t\tif ( this.options.disabled == null ) {\n\t\t\tthis.options.disabled = this.element[ 0 ].disabled || false;\n\t\t}\n\n\t\tthis.hasTitle = !!this.element.attr( \"title\" );\n\n\t\t// Check to see if the label needs to be set or if its already correct\n\t\tif ( this.options.label && this.options.label !== this.originalLabel ) {\n\t\t\tif ( this.isInput ) {\n\t\t\t\tthis.element.val( this.options.label );\n\t\t\t} else {\n\t\t\t\tthis.element.html( this.options.label );\n\t\t\t}\n\t\t}\n\t\tthis._addClass( \"ui-button\", \"ui-widget\" );\n\t\tthis._setOption( \"disabled\", this.options.disabled );\n\t\tthis._enhance();\n\n\t\tif ( this.element.is( \"a\" ) ) {\n\t\t\tthis._on( {\n\t\t\t\t\"keyup\": function( event ) {\n\t\t\t\t\tif ( event.keyCode === $.ui.keyCode.SPACE ) {\n\t\t\t\t\t\tevent.preventDefault();\n\n\t\t\t\t\t\t// Support: PhantomJS <= 1.9, IE 8 Only\n\t\t\t\t\t\t// If a native click is available use it so we actually cause navigation\n\t\t\t\t\t\t// otherwise just trigger a click event\n\t\t\t\t\t\tif ( this.element[ 0 ].click ) {\n\t\t\t\t\t\t\tthis.element[ 0 ].click();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.element.trigger( \"click\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t},\n\n\t_enhance: function() {\n\t\tif ( !this.element.is( \"button\" ) ) {\n\t\t\tthis.element.attr( \"role\", \"button\" );\n\t\t}\n\n\t\tif ( this.options.icon ) {\n\t\t\tthis._updateIcon( \"icon\", this.options.icon );\n\t\t\tthis._updateTooltip();\n\t\t}\n\t},\n\n\t_updateTooltip: function() {\n\t\tthis.title = this.element.attr( \"title\" );\n\n\t\tif ( !this.options.showLabel && !this.title ) {\n\t\t\tthis.element.attr( \"title\", this.options.label );\n\t\t}\n\t},\n\n\t_updateIcon: function( option, value ) {\n\t\tvar icon = option !== \"iconPosition\",\n\t\t\tposition = icon ? this.options.iconPosition : value,\n\t\t\tdisplayBlock = position === \"top\" || position === \"bottom\";\n\n\t\t// Create icon\n\t\tif ( !this.icon ) {\n\t\t\tthis.icon = $( \"<span>\" );\n\n\t\t\tthis._addClass( this.icon, \"ui-button-icon\", \"ui-icon\" );\n\n\t\t\tif ( !this.options.showLabel ) {\n\t\t\t\tthis._addClass( \"ui-button-icon-only\" );\n\t\t\t}\n\t\t} else if ( icon ) {\n\n\t\t\t// If we are updating the icon remove the old icon class\n\t\t\tthis._removeClass( this.icon, null, this.options.icon );\n\t\t}\n\n\t\t// If we are updating the icon add the new icon class\n\t\tif ( icon ) {\n\t\t\tthis._addClass( this.icon, null, value );\n\t\t}\n\n\t\tthis._attachIcon( position );\n\n\t\t// If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove\n\t\t// the iconSpace if there is one.\n\t\tif ( displayBlock ) {\n\t\t\tthis._addClass( this.icon, null, \"ui-widget-icon-block\" );\n\t\t\tif ( this.iconSpace ) {\n\t\t\t\tthis.iconSpace.remove();\n\t\t\t}\n\t\t} else {\n\n\t\t\t// Position is beginning or end so remove the ui-widget-icon-block class and add the\n\t\t\t// space if it does not exist\n\t\t\tif ( !this.iconSpace ) {\n\t\t\t\tthis.iconSpace = $( \"<span> </span>\" );\n\t\t\t\tthis._addClass( this.iconSpace, \"ui-button-icon-space\" );\n\t\t\t}\n\t\t\tthis._removeClass( this.icon, null, \"ui-wiget-icon-block\" );\n\t\t\tthis._attachIconSpace( position );\n\t\t}\n\t},\n\n\t_destroy: function() {\n\t\tthis.element.removeAttr( \"role\" );\n\n\t\tif ( this.icon ) {\n\t\t\tthis.icon.remove();\n\t\t}\n\t\tif ( this.iconSpace ) {\n\t\t\tthis.iconSpace.remove();\n\t\t}\n\t\tif ( !this.hasTitle ) {\n\t\t\tthis.element.removeAttr( \"title\" );\n\t\t}\n\t},\n\n\t_attachIconSpace: function( iconPosition ) {\n\t\tthis.icon[ /^(?:end|bottom)/.test( iconPosition ) ? \"before\" : \"after\" ]( this.iconSpace );\n\t},\n\n\t_attachIcon: function( iconPosition ) {\n\t\tthis.element[ /^(?:end|bottom)/.test( iconPosition ) ? \"append\" : \"prepend\" ]( this.icon );\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar newShowLabel = options.showLabel === undefined ?\n\t\t\t\tthis.options.showLabel :\n\t\t\t\toptions.showLabel,\n\t\t\tnewIcon = options.icon === undefined ? this.options.icon : options.icon;\n\n\t\tif ( !newShowLabel && !newIcon ) {\n\t\t\toptions.showLabel = true;\n\t\t}\n\t\tthis._super( options );\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"icon\" ) {\n\t\t\tif ( value ) {\n\t\t\t\tthis._updateIcon( key, value );\n\t\t\t} else if ( this.icon ) {\n\t\t\t\tthis.icon.remove();\n\t\t\t\tif ( this.iconSpace ) {\n\t\t\t\t\tthis.iconSpace.remove();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( key === \"iconPosition\" ) {\n\t\t\tthis._updateIcon( key, value );\n\t\t}\n\n\t\t// Make sure we can't end up with a button that has neither text nor icon\n\t\tif ( key === \"showLabel\" ) {\n\t\t\t\tthis._toggleClass( \"ui-button-icon-only\", null, !value );\n\t\t\t\tthis._updateTooltip();\n\t\t}\n\n\t\tif ( key === \"label\" ) {\n\t\t\tif ( this.isInput ) {\n\t\t\t\tthis.element.val( value );\n\t\t\t} else {\n\n\t\t\t\t// If there is an icon, append it, else nothing then append the value\n\t\t\t\t// this avoids removal of the icon when setting label text\n\t\t\t\tthis.element.html( value );\n\t\t\t\tif ( this.icon ) {\n\t\t\t\t\tthis._attachIcon( this.options.iconPosition );\n\t\t\t\t\tthis._attachIconSpace( this.options.iconPosition );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\tthis._toggleClass( null, \"ui-state-disabled\", value );\n\t\t\tthis.element[ 0 ].disabled = value;\n\t\t\tif ( value ) {\n\t\t\t\tthis.element.blur();\n\t\t\t}\n\t\t}\n\t},\n\n\trefresh: function() {\n\n\t\t// Make sure to only check disabled if its an element that supports this otherwise\n\t\t// check for the disabled class to determine state\n\t\tvar isDisabled = this.element.is( \"input, button\" ) ?\n\t\t\tthis.element[ 0 ].disabled : this.element.hasClass( \"ui-button-disabled\" );\n\n\t\tif ( isDisabled !== this.options.disabled ) {\n\t\t\tthis._setOptions( { disabled: isDisabled } );\n\t\t}\n\n\t\tthis._updateTooltip();\n\t}\n} );\n\n// DEPRECATED\nif ( $.uiBackCompat !== false ) {\n\n\t// Text and Icons options\n\t$.widget( \"ui.button\", $.ui.button, {\n\t\toptions: {\n\t\t\ttext: true,\n\t\t\ticons: {\n\t\t\t\tprimary: null,\n\t\t\t\tsecondary: null\n\t\t\t}\n\t\t},\n\n\t\t_create: function() {\n\t\t\tif ( this.options.showLabel && !this.options.text ) {\n\t\t\t\tthis.options.showLabel = this.options.text;\n\t\t\t}\n\t\t\tif ( !this.options.showLabel && this.options.text ) {\n\t\t\t\tthis.options.text = this.options.showLabel;\n\t\t\t}\n\t\t\tif ( !this.options.icon && ( this.options.icons.primary ||\n\t\t\t\t\tthis.options.icons.secondary ) ) {\n\t\t\t\tif ( this.options.icons.primary ) {\n\t\t\t\t\tthis.options.icon = this.options.icons.primary;\n\t\t\t\t} else {\n\t\t\t\t\tthis.options.icon = this.options.icons.secondary;\n\t\t\t\t\tthis.options.iconPosition = \"end\";\n\t\t\t\t}\n\t\t\t} else if ( this.options.icon ) {\n\t\t\t\tthis.options.icons.primary = this.options.icon;\n\t\t\t}\n\t\t\tthis._super();\n\t\t},\n\n\t\t_setOption: function( key, value ) {\n\t\t\tif ( key === \"text\" ) {\n\t\t\t\tthis._super( \"showLabel\", value );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( key === \"showLabel\" ) {\n\t\t\t\tthis.options.text = value;\n\t\t\t}\n\t\t\tif ( key === \"icon\" ) {\n\t\t\t\tthis.options.icons.primary = value;\n\t\t\t}\n\t\t\tif ( key === \"icons\" ) {\n\t\t\t\tif ( value.primary ) {\n\t\t\t\t\tthis._super( \"icon\", value.primary );\n\t\t\t\t\tthis._super( \"iconPosition\", \"beginning\" );\n\t\t\t\t} else if ( value.secondary ) {\n\t\t\t\t\tthis._super( \"icon\", value.secondary );\n\t\t\t\t\tthis._super( \"iconPosition\", \"end\" );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._superApply( arguments );\n\t\t}\n\t} );\n\n\t$.fn.button = ( function( orig ) {\n\t\treturn function() {\n\t\t\tif ( !this.length || ( this.length && this[ 0 ].tagName !== \"INPUT\" ) ||\n\t\t\t\t\t( this.length && this[ 0 ].tagName === \"INPUT\" && (\n\t\t\t\t\t\tthis.attr( \"type\" ) !== \"checkbox\" && this.attr( \"type\" ) !== \"radio\"\n\t\t\t\t\t) ) ) {\n\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t}\n\t\t\tif ( !$.ui.checkboxradio ) {\n\t\t\t\t$.error( \"Checkboxradio widget missing\" );\n\t\t\t}\n\t\t\tif ( arguments.length === 0 ) {\n\t\t\t\treturn this.checkboxradio( {\n\t\t\t\t\t\"icon\": false\n\t\t\t\t} );\n\t\t\t}\n\t\t\treturn this.checkboxradio.apply( this, arguments );\n\t\t};\n\t} )( $.fn.button );\n\n\t$.fn.buttonset = function() {\n\t\tif ( !$.ui.controlgroup ) {\n\t\t\t$.error( \"Controlgroup widget missing\" );\n\t\t}\n\t\tif ( arguments[ 0 ] === \"option\" && arguments[ 1 ] === \"items\" && arguments[ 2 ] ) {\n\t\t\treturn this.controlgroup.apply( this,\n\t\t\t\t[ arguments[ 0 ], \"items.button\", arguments[ 2 ] ] );\n\t\t}\n\t\tif ( arguments[ 0 ] === \"option\" && arguments[ 1 ] === \"items\" ) {\n\t\t\treturn this.controlgroup.apply( this, [ arguments[ 0 ], \"items.button\" ] );\n\t\t}\n\t\tif ( typeof arguments[ 0 ] === \"object\" && arguments[ 0 ].items ) {\n\t\t\targuments[ 0 ].items = {\n\t\t\t\tbutton: arguments[ 0 ].items\n\t\t\t};\n\t\t}\n\t\treturn this.controlgroup.apply( this, arguments );\n\t};\n}\n\nvar widgetsButton = $.ui.button;\n\n\n// jscs:disable maximumLineLength\n/* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */\n/*!\n * jQuery UI Datepicker 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Datepicker\n//>>group: Widgets\n//>>description: Displays a calendar from an input or inline for selecting dates.\n//>>docs: http://api.jqueryui.com/datepicker/\n//>>demos: http://jqueryui.com/datepicker/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/datepicker.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.extend( $.ui, { datepicker: { version: \"1.12.1\" } } );\n\nvar datepicker_instActive;\n\nfunction datepicker_getZindex( elem ) {\n\tvar position, value;\n\twhile ( elem.length && elem[ 0 ] !== document ) {\n\n\t\t// Ignore z-index if position is set to a value where z-index is ignored by the browser\n\t\t// This makes behavior of this function consistent across browsers\n\t\t// WebKit always returns auto if the element is positioned\n\t\tposition = elem.css( \"position\" );\n\t\tif ( position === \"absolute\" || position === \"relative\" || position === \"fixed\" ) {\n\n\t\t\t// IE returns 0 when zIndex is not specified\n\t\t\t// other browsers return a string\n\t\t\t// we ignore the case of nested elements with an explicit value of 0\n\t\t\t// <div style=\"z-index: -10;\"><div style=\"z-index: 0;\"></div></div>\n\t\t\tvalue = parseInt( elem.css( \"zIndex\" ), 10 );\n\t\t\tif ( !isNaN( value ) && value !== 0 ) {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t}\n\t\telem = elem.parent();\n\t}\n\n\treturn 0;\n}\n/* Date picker manager.\n   Use the singleton instance of this class, $.datepicker, to interact with the date picker.\n   Settings for (groups of) date pickers are maintained in an instance object,\n   allowing multiple different settings on the same page. */\n\nfunction Datepicker() {\n\tthis._curInst = null; // The current instance in use\n\tthis._keyEvent = false; // If the last event was a key event\n\tthis._disabledInputs = []; // List of date picker inputs that have been disabled\n\tthis._datepickerShowing = false; // True if the popup picker is showing , false if not\n\tthis._inDialog = false; // True if showing within a \"dialog\", false if not\n\tthis._mainDivId = \"ui-datepicker-div\"; // The ID of the main datepicker division\n\tthis._inlineClass = \"ui-datepicker-inline\"; // The name of the inline marker class\n\tthis._appendClass = \"ui-datepicker-append\"; // The name of the append marker class\n\tthis._triggerClass = \"ui-datepicker-trigger\"; // The name of the trigger marker class\n\tthis._dialogClass = \"ui-datepicker-dialog\"; // The name of the dialog marker class\n\tthis._disableClass = \"ui-datepicker-disabled\"; // The name of the disabled covering marker class\n\tthis._unselectableClass = \"ui-datepicker-unselectable\"; // The name of the unselectable cell marker class\n\tthis._currentClass = \"ui-datepicker-current-day\"; // The name of the current day marker class\n\tthis._dayOverClass = \"ui-datepicker-days-cell-over\"; // The name of the day hover marker class\n\tthis.regional = []; // Available regional settings, indexed by language code\n\tthis.regional[ \"\" ] = { // Default regional settings\n\t\tcloseText: \"Done\", // Display text for close link\n\t\tprevText: \"Prev\", // Display text for previous month link\n\t\tnextText: \"Next\", // Display text for next month link\n\t\tcurrentText: \"Today\", // Display text for current month link\n\t\tmonthNames: [ \"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\n\t\t\t\"July\",\"August\",\"September\",\"October\",\"November\",\"December\" ], // Names of months for drop-down and formatting\n\t\tmonthNamesShort: [ \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\" ], // For formatting\n\t\tdayNames: [ \"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\" ], // For formatting\n\t\tdayNamesShort: [ \"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\" ], // For formatting\n\t\tdayNamesMin: [ \"Su\",\"Mo\",\"Tu\",\"We\",\"Th\",\"Fr\",\"Sa\" ], // Column headings for days starting at Sunday\n\t\tweekHeader: \"Wk\", // Column header for week of the year\n\t\tdateFormat: \"mm/dd/yy\", // See format options on parseDate\n\t\tfirstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...\n\t\tisRTL: false, // True if right-to-left language, false if left-to-right\n\t\tshowMonthAfterYear: false, // True if the year select precedes month, false for month then year\n\t\tyearSuffix: \"\" // Additional text to append to the year in the month headers\n\t};\n\tthis._defaults = { // Global defaults for all the date picker instances\n\t\tshowOn: \"focus\", // \"focus\" for popup on focus,\n\t\t\t// \"button\" for trigger button, or \"both\" for either\n\t\tshowAnim: \"fadeIn\", // Name of jQuery animation for popup\n\t\tshowOptions: {}, // Options for enhanced animations\n\t\tdefaultDate: null, // Used when field is blank: actual date,\n\t\t\t// +/-number for offset from today, null for today\n\t\tappendText: \"\", // Display text following the input box, e.g. showing the format\n\t\tbuttonText: \"...\", // Text for trigger button\n\t\tbuttonImage: \"\", // URL for trigger button image\n\t\tbuttonImageOnly: false, // True if the image appears alone, false if it appears on a button\n\t\thideIfNoPrevNext: false, // True to hide next/previous month links\n\t\t\t// if not applicable, false to just disable them\n\t\tnavigationAsDateFormat: false, // True if date formatting applied to prev/today/next links\n\t\tgotoCurrent: false, // True if today link goes back to current selection instead\n\t\tchangeMonth: false, // True if month can be selected directly, false if only prev/next\n\t\tchangeYear: false, // True if year can be selected directly, false if only prev/next\n\t\tyearRange: \"c-10:c+10\", // Range of years to display in drop-down,\n\t\t\t// either relative to today's year (-nn:+nn), relative to currently displayed year\n\t\t\t// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)\n\t\tshowOtherMonths: false, // True to show dates in other months, false to leave blank\n\t\tselectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable\n\t\tshowWeek: false, // True to show week of the year, false to not show it\n\t\tcalculateWeek: this.iso8601Week, // How to calculate the week of the year,\n\t\t\t// takes a Date and returns the number of the week for it\n\t\tshortYearCutoff: \"+10\", // Short year values < this are in the current century,\n\t\t\t// > this are in the previous century,\n\t\t\t// string value starting with \"+\" for current year + value\n\t\tminDate: null, // The earliest selectable date, or null for no limit\n\t\tmaxDate: null, // The latest selectable date, or null for no limit\n\t\tduration: \"fast\", // Duration of display/closure\n\t\tbeforeShowDay: null, // Function that takes a date and returns an array with\n\t\t\t// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or \"\",\n\t\t\t// [2] = cell title (optional), e.g. $.datepicker.noWeekends\n\t\tbeforeShow: null, // Function that takes an input field and\n\t\t\t// returns a set of custom settings for the date picker\n\t\tonSelect: null, // Define a callback function when a date is selected\n\t\tonChangeMonthYear: null, // Define a callback function when the month or year is changed\n\t\tonClose: null, // Define a callback function when the datepicker is closed\n\t\tnumberOfMonths: 1, // Number of months to show at a time\n\t\tshowCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)\n\t\tstepMonths: 1, // Number of months to step back/forward\n\t\tstepBigMonths: 12, // Number of months to step back/forward for the big links\n\t\taltField: \"\", // Selector for an alternate field to store selected dates into\n\t\taltFormat: \"\", // The date format to use for the alternate field\n\t\tconstrainInput: true, // The input is constrained by the current date format\n\t\tshowButtonPanel: false, // True to show button panel, false to not show it\n\t\tautoSize: false, // True to size the input for the date format, false to leave as is\n\t\tdisabled: false // The initial disabled state\n\t};\n\t$.extend( this._defaults, this.regional[ \"\" ] );\n\tthis.regional.en = $.extend( true, {}, this.regional[ \"\" ] );\n\tthis.regional[ \"en-US\" ] = $.extend( true, {}, this.regional.en );\n\tthis.dpDiv = datepicker_bindHover( $( \"<div id='\" + this._mainDivId + \"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>\" ) );\n}\n\n$.extend( Datepicker.prototype, {\n\t/* Class name added to elements to indicate already configured with a date picker. */\n\tmarkerClassName: \"hasDatepicker\",\n\n\t//Keep track of the maximum number of rows displayed (see #7043)\n\tmaxRows: 4,\n\n\t// TODO rename to \"widget\" when switching to widget factory\n\t_widgetDatepicker: function() {\n\t\treturn this.dpDiv;\n\t},\n\n\t/* Override the default settings for all instances of the date picker.\n\t * @param  settings  object - the new settings to use as defaults (anonymous object)\n\t * @return the manager object\n\t */\n\tsetDefaults: function( settings ) {\n\t\tdatepicker_extendRemove( this._defaults, settings || {} );\n\t\treturn this;\n\t},\n\n\t/* Attach the date picker to a jQuery selection.\n\t * @param  target\telement - the target input field or division or span\n\t * @param  settings  object - the new settings to use for this date picker instance (anonymous)\n\t */\n\t_attachDatepicker: function( target, settings ) {\n\t\tvar nodeName, inline, inst;\n\t\tnodeName = target.nodeName.toLowerCase();\n\t\tinline = ( nodeName === \"div\" || nodeName === \"span\" );\n\t\tif ( !target.id ) {\n\t\t\tthis.uuid += 1;\n\t\t\ttarget.id = \"dp\" + this.uuid;\n\t\t}\n\t\tinst = this._newInst( $( target ), inline );\n\t\tinst.settings = $.extend( {}, settings || {} );\n\t\tif ( nodeName === \"input\" ) {\n\t\t\tthis._connectDatepicker( target, inst );\n\t\t} else if ( inline ) {\n\t\t\tthis._inlineDatepicker( target, inst );\n\t\t}\n\t},\n\n\t/* Create a new instance object. */\n\t_newInst: function( target, inline ) {\n\t\tvar id = target[ 0 ].id.replace( /([^A-Za-z0-9_\\-])/g, \"\\\\\\\\$1\" ); // escape jQuery meta chars\n\t\treturn { id: id, input: target, // associated target\n\t\t\tselectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection\n\t\t\tdrawMonth: 0, drawYear: 0, // month being drawn\n\t\t\tinline: inline, // is datepicker inline or not\n\t\t\tdpDiv: ( !inline ? this.dpDiv : // presentation div\n\t\t\tdatepicker_bindHover( $( \"<div class='\" + this._inlineClass + \" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>\" ) ) ) };\n\t},\n\n\t/* Attach the date picker to an input field. */\n\t_connectDatepicker: function( target, inst ) {\n\t\tvar input = $( target );\n\t\tinst.append = $( [] );\n\t\tinst.trigger = $( [] );\n\t\tif ( input.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\t\tthis._attachments( input, inst );\n\t\tinput.addClass( this.markerClassName ).on( \"keydown\", this._doKeyDown ).\n\t\t\ton( \"keypress\", this._doKeyPress ).on( \"keyup\", this._doKeyUp );\n\t\tthis._autoSize( inst );\n\t\t$.data( target, \"datepicker\", inst );\n\n\t\t//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)\n\t\tif ( inst.settings.disabled ) {\n\t\t\tthis._disableDatepicker( target );\n\t\t}\n\t},\n\n\t/* Make attachments based on settings. */\n\t_attachments: function( input, inst ) {\n\t\tvar showOn, buttonText, buttonImage,\n\t\t\tappendText = this._get( inst, \"appendText\" ),\n\t\t\tisRTL = this._get( inst, \"isRTL\" );\n\n\t\tif ( inst.append ) {\n\t\t\tinst.append.remove();\n\t\t}\n\t\tif ( appendText ) {\n\t\t\tinst.append = $( \"<span class='\" + this._appendClass + \"'>\" + appendText + \"</span>\" );\n\t\t\tinput[ isRTL ? \"before\" : \"after\" ]( inst.append );\n\t\t}\n\n\t\tinput.off( \"focus\", this._showDatepicker );\n\n\t\tif ( inst.trigger ) {\n\t\t\tinst.trigger.remove();\n\t\t}\n\n\t\tshowOn = this._get( inst, \"showOn\" );\n\t\tif ( showOn === \"focus\" || showOn === \"both\" ) { // pop-up date picker when in the marked field\n\t\t\tinput.on( \"focus\", this._showDatepicker );\n\t\t}\n\t\tif ( showOn === \"button\" || showOn === \"both\" ) { // pop-up date picker when button clicked\n\t\t\tbuttonText = this._get( inst, \"buttonText\" );\n\t\t\tbuttonImage = this._get( inst, \"buttonImage\" );\n\t\t\tinst.trigger = $( this._get( inst, \"buttonImageOnly\" ) ?\n\t\t\t\t$( \"<img/>\" ).addClass( this._triggerClass ).\n\t\t\t\t\tattr( { src: buttonImage, alt: buttonText, title: buttonText } ) :\n\t\t\t\t$( \"<button type='button'></button>\" ).addClass( this._triggerClass ).\n\t\t\t\t\thtml( !buttonImage ? buttonText : $( \"<img/>\" ).attr(\n\t\t\t\t\t{ src:buttonImage, alt:buttonText, title:buttonText } ) ) );\n\t\t\tinput[ isRTL ? \"before\" : \"after\" ]( inst.trigger );\n\t\t\tinst.trigger.on( \"click\", function() {\n\t\t\t\tif ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {\n\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\t} else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {\n\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\t\t$.datepicker._showDatepicker( input[ 0 ] );\n\t\t\t\t} else {\n\t\t\t\t\t$.datepicker._showDatepicker( input[ 0 ] );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} );\n\t\t}\n\t},\n\n\t/* Apply the maximum length for the date format. */\n\t_autoSize: function( inst ) {\n\t\tif ( this._get( inst, \"autoSize\" ) && !inst.inline ) {\n\t\t\tvar findMax, max, maxI, i,\n\t\t\t\tdate = new Date( 2009, 12 - 1, 20 ), // Ensure double digits\n\t\t\t\tdateFormat = this._get( inst, \"dateFormat\" );\n\n\t\t\tif ( dateFormat.match( /[DM]/ ) ) {\n\t\t\t\tfindMax = function( names ) {\n\t\t\t\t\tmax = 0;\n\t\t\t\t\tmaxI = 0;\n\t\t\t\t\tfor ( i = 0; i < names.length; i++ ) {\n\t\t\t\t\t\tif ( names[ i ].length > max ) {\n\t\t\t\t\t\t\tmax = names[ i ].length;\n\t\t\t\t\t\t\tmaxI = i;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn maxI;\n\t\t\t\t};\n\t\t\t\tdate.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?\n\t\t\t\t\t\"monthNames\" : \"monthNamesShort\" ) ) ) );\n\t\t\t\tdate.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?\n\t\t\t\t\t\"dayNames\" : \"dayNamesShort\" ) ) ) + 20 - date.getDay() );\n\t\t\t}\n\t\t\tinst.input.attr( \"size\", this._formatDate( inst, date ).length );\n\t\t}\n\t},\n\n\t/* Attach an inline date picker to a div. */\n\t_inlineDatepicker: function( target, inst ) {\n\t\tvar divSpan = $( target );\n\t\tif ( divSpan.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\t\tdivSpan.addClass( this.markerClassName ).append( inst.dpDiv );\n\t\t$.data( target, \"datepicker\", inst );\n\t\tthis._setDate( inst, this._getDefaultDate( inst ), true );\n\t\tthis._updateDatepicker( inst );\n\t\tthis._updateAlternate( inst );\n\n\t\t//If disabled option is true, disable the datepicker before showing it (see ticket #5665)\n\t\tif ( inst.settings.disabled ) {\n\t\t\tthis._disableDatepicker( target );\n\t\t}\n\n\t\t// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements\n\t\t// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height\n\t\tinst.dpDiv.css( \"display\", \"block\" );\n\t},\n\n\t/* Pop-up the date picker in a \"dialog\" box.\n\t * @param  input element - ignored\n\t * @param  date\tstring or Date - the initial date to display\n\t * @param  onSelect  function - the function to call when a date is selected\n\t * @param  settings  object - update the dialog date picker instance's settings (anonymous object)\n\t * @param  pos int[2] - coordinates for the dialog's position within the screen or\n\t *\t\t\t\t\tevent - with x/y coordinates or\n\t *\t\t\t\t\tleave empty for default (screen centre)\n\t * @return the manager object\n\t */\n\t_dialogDatepicker: function( input, date, onSelect, settings, pos ) {\n\t\tvar id, browserWidth, browserHeight, scrollX, scrollY,\n\t\t\tinst = this._dialogInst; // internal instance\n\n\t\tif ( !inst ) {\n\t\t\tthis.uuid += 1;\n\t\t\tid = \"dp\" + this.uuid;\n\t\t\tthis._dialogInput = $( \"<input type='text' id='\" + id +\n\t\t\t\t\"' style='position: absolute; top: -100px; width: 0px;'/>\" );\n\t\t\tthis._dialogInput.on( \"keydown\", this._doKeyDown );\n\t\t\t$( \"body\" ).append( this._dialogInput );\n\t\t\tinst = this._dialogInst = this._newInst( this._dialogInput, false );\n\t\t\tinst.settings = {};\n\t\t\t$.data( this._dialogInput[ 0 ], \"datepicker\", inst );\n\t\t}\n\t\tdatepicker_extendRemove( inst.settings, settings || {} );\n\t\tdate = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );\n\t\tthis._dialogInput.val( date );\n\n\t\tthis._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );\n\t\tif ( !this._pos ) {\n\t\t\tbrowserWidth = document.documentElement.clientWidth;\n\t\t\tbrowserHeight = document.documentElement.clientHeight;\n\t\t\tscrollX = document.documentElement.scrollLeft || document.body.scrollLeft;\n\t\t\tscrollY = document.documentElement.scrollTop || document.body.scrollTop;\n\t\t\tthis._pos = // should use actual width/height below\n\t\t\t\t[ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];\n\t\t}\n\n\t\t// Move input on screen for focus, but hidden behind dialog\n\t\tthis._dialogInput.css( \"left\", ( this._pos[ 0 ] + 20 ) + \"px\" ).css( \"top\", this._pos[ 1 ] + \"px\" );\n\t\tinst.settings.onSelect = onSelect;\n\t\tthis._inDialog = true;\n\t\tthis.dpDiv.addClass( this._dialogClass );\n\t\tthis._showDatepicker( this._dialogInput[ 0 ] );\n\t\tif ( $.blockUI ) {\n\t\t\t$.blockUI( this.dpDiv );\n\t\t}\n\t\t$.data( this._dialogInput[ 0 ], \"datepicker\", inst );\n\t\treturn this;\n\t},\n\n\t/* Detach a datepicker from its control.\n\t * @param  target\telement - the target input field or division or span\n\t */\n\t_destroyDatepicker: function( target ) {\n\t\tvar nodeName,\n\t\t\t$target = $( target ),\n\t\t\tinst = $.data( target, \"datepicker\" );\n\n\t\tif ( !$target.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnodeName = target.nodeName.toLowerCase();\n\t\t$.removeData( target, \"datepicker\" );\n\t\tif ( nodeName === \"input\" ) {\n\t\t\tinst.append.remove();\n\t\t\tinst.trigger.remove();\n\t\t\t$target.removeClass( this.markerClassName ).\n\t\t\t\toff( \"focus\", this._showDatepicker ).\n\t\t\t\toff( \"keydown\", this._doKeyDown ).\n\t\t\t\toff( \"keypress\", this._doKeyPress ).\n\t\t\t\toff( \"keyup\", this._doKeyUp );\n\t\t} else if ( nodeName === \"div\" || nodeName === \"span\" ) {\n\t\t\t$target.removeClass( this.markerClassName ).empty();\n\t\t}\n\n\t\tif ( datepicker_instActive === inst ) {\n\t\t\tdatepicker_instActive = null;\n\t\t}\n\t},\n\n\t/* Enable the date picker to a jQuery selection.\n\t * @param  target\telement - the target input field or division or span\n\t */\n\t_enableDatepicker: function( target ) {\n\t\tvar nodeName, inline,\n\t\t\t$target = $( target ),\n\t\t\tinst = $.data( target, \"datepicker\" );\n\n\t\tif ( !$target.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnodeName = target.nodeName.toLowerCase();\n\t\tif ( nodeName === \"input\" ) {\n\t\t\ttarget.disabled = false;\n\t\t\tinst.trigger.filter( \"button\" ).\n\t\t\t\teach( function() { this.disabled = false; } ).end().\n\t\t\t\tfilter( \"img\" ).css( { opacity: \"1.0\", cursor: \"\" } );\n\t\t} else if ( nodeName === \"div\" || nodeName === \"span\" ) {\n\t\t\tinline = $target.children( \".\" + this._inlineClass );\n\t\t\tinline.children().removeClass( \"ui-state-disabled\" );\n\t\t\tinline.find( \"select.ui-datepicker-month, select.ui-datepicker-year\" ).\n\t\t\t\tprop( \"disabled\", false );\n\t\t}\n\t\tthis._disabledInputs = $.map( this._disabledInputs,\n\t\t\tfunction( value ) { return ( value === target ? null : value ); } ); // delete entry\n\t},\n\n\t/* Disable the date picker to a jQuery selection.\n\t * @param  target\telement - the target input field or division or span\n\t */\n\t_disableDatepicker: function( target ) {\n\t\tvar nodeName, inline,\n\t\t\t$target = $( target ),\n\t\t\tinst = $.data( target, \"datepicker\" );\n\n\t\tif ( !$target.hasClass( this.markerClassName ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnodeName = target.nodeName.toLowerCase();\n\t\tif ( nodeName === \"input\" ) {\n\t\t\ttarget.disabled = true;\n\t\t\tinst.trigger.filter( \"button\" ).\n\t\t\t\teach( function() { this.disabled = true; } ).end().\n\t\t\t\tfilter( \"img\" ).css( { opacity: \"0.5\", cursor: \"default\" } );\n\t\t} else if ( nodeName === \"div\" || nodeName === \"span\" ) {\n\t\t\tinline = $target.children( \".\" + this._inlineClass );\n\t\t\tinline.children().addClass( \"ui-state-disabled\" );\n\t\t\tinline.find( \"select.ui-datepicker-month, select.ui-datepicker-year\" ).\n\t\t\t\tprop( \"disabled\", true );\n\t\t}\n\t\tthis._disabledInputs = $.map( this._disabledInputs,\n\t\t\tfunction( value ) { return ( value === target ? null : value ); } ); // delete entry\n\t\tthis._disabledInputs[ this._disabledInputs.length ] = target;\n\t},\n\n\t/* Is the first field in a jQuery collection disabled as a datepicker?\n\t * @param  target\telement - the target input field or division or span\n\t * @return boolean - true if disabled, false if enabled\n\t */\n\t_isDisabledDatepicker: function( target ) {\n\t\tif ( !target ) {\n\t\t\treturn false;\n\t\t}\n\t\tfor ( var i = 0; i < this._disabledInputs.length; i++ ) {\n\t\t\tif ( this._disabledInputs[ i ] === target ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t},\n\n\t/* Retrieve the instance data for the target control.\n\t * @param  target  element - the target input field or division or span\n\t * @return  object - the associated instance data\n\t * @throws  error if a jQuery problem getting data\n\t */\n\t_getInst: function( target ) {\n\t\ttry {\n\t\t\treturn $.data( target, \"datepicker\" );\n\t\t}\n\t\tcatch ( err ) {\n\t\t\tthrow \"Missing instance data for this datepicker\";\n\t\t}\n\t},\n\n\t/* Update or retrieve the settings for a date picker attached to an input field or division.\n\t * @param  target  element - the target input field or division or span\n\t * @param  name\tobject - the new settings to update or\n\t *\t\t\t\tstring - the name of the setting to change or retrieve,\n\t *\t\t\t\twhen retrieving also \"all\" for all instance settings or\n\t *\t\t\t\t\"defaults\" for all global defaults\n\t * @param  value   any - the new value for the setting\n\t *\t\t\t\t(omit if above is an object or to retrieve a value)\n\t */\n\t_optionDatepicker: function( target, name, value ) {\n\t\tvar settings, date, minDate, maxDate,\n\t\t\tinst = this._getInst( target );\n\n\t\tif ( arguments.length === 2 && typeof name === \"string\" ) {\n\t\t\treturn ( name === \"defaults\" ? $.extend( {}, $.datepicker._defaults ) :\n\t\t\t\t( inst ? ( name === \"all\" ? $.extend( {}, inst.settings ) :\n\t\t\t\tthis._get( inst, name ) ) : null ) );\n\t\t}\n\n\t\tsettings = name || {};\n\t\tif ( typeof name === \"string\" ) {\n\t\t\tsettings = {};\n\t\t\tsettings[ name ] = value;\n\t\t}\n\n\t\tif ( inst ) {\n\t\t\tif ( this._curInst === inst ) {\n\t\t\t\tthis._hideDatepicker();\n\t\t\t}\n\n\t\t\tdate = this._getDateDatepicker( target, true );\n\t\t\tminDate = this._getMinMaxDate( inst, \"min\" );\n\t\t\tmaxDate = this._getMinMaxDate( inst, \"max\" );\n\t\t\tdatepicker_extendRemove( inst.settings, settings );\n\n\t\t\t// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided\n\t\t\tif ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {\n\t\t\t\tinst.settings.minDate = this._formatDate( inst, minDate );\n\t\t\t}\n\t\t\tif ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {\n\t\t\t\tinst.settings.maxDate = this._formatDate( inst, maxDate );\n\t\t\t}\n\t\t\tif ( \"disabled\" in settings ) {\n\t\t\t\tif ( settings.disabled ) {\n\t\t\t\t\tthis._disableDatepicker( target );\n\t\t\t\t} else {\n\t\t\t\t\tthis._enableDatepicker( target );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._attachments( $( target ), inst );\n\t\t\tthis._autoSize( inst );\n\t\t\tthis._setDate( inst, date );\n\t\t\tthis._updateAlternate( inst );\n\t\t\tthis._updateDatepicker( inst );\n\t\t}\n\t},\n\n\t// Change method deprecated\n\t_changeDatepicker: function( target, name, value ) {\n\t\tthis._optionDatepicker( target, name, value );\n\t},\n\n\t/* Redraw the date picker attached to an input field or division.\n\t * @param  target  element - the target input field or division or span\n\t */\n\t_refreshDatepicker: function( target ) {\n\t\tvar inst = this._getInst( target );\n\t\tif ( inst ) {\n\t\t\tthis._updateDatepicker( inst );\n\t\t}\n\t},\n\n\t/* Set the dates for a jQuery selection.\n\t * @param  target element - the target input field or division or span\n\t * @param  date\tDate - the new date\n\t */\n\t_setDateDatepicker: function( target, date ) {\n\t\tvar inst = this._getInst( target );\n\t\tif ( inst ) {\n\t\t\tthis._setDate( inst, date );\n\t\t\tthis._updateDatepicker( inst );\n\t\t\tthis._updateAlternate( inst );\n\t\t}\n\t},\n\n\t/* Get the date(s) for the first entry in a jQuery selection.\n\t * @param  target element - the target input field or division or span\n\t * @param  noDefault boolean - true if no default date is to be used\n\t * @return Date - the current date\n\t */\n\t_getDateDatepicker: function( target, noDefault ) {\n\t\tvar inst = this._getInst( target );\n\t\tif ( inst && !inst.inline ) {\n\t\t\tthis._setDateFromField( inst, noDefault );\n\t\t}\n\t\treturn ( inst ? this._getDate( inst ) : null );\n\t},\n\n\t/* Handle keystrokes. */\n\t_doKeyDown: function( event ) {\n\t\tvar onSelect, dateStr, sel,\n\t\t\tinst = $.datepicker._getInst( event.target ),\n\t\t\thandled = true,\n\t\t\tisRTL = inst.dpDiv.is( \".ui-datepicker-rtl\" );\n\n\t\tinst._keyEvent = true;\n\t\tif ( $.datepicker._datepickerShowing ) {\n\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase 9: $.datepicker._hideDatepicker();\n\t\t\t\t\t\thandled = false;\n\t\t\t\t\t\tbreak; // hide on tab out\n\t\t\t\tcase 13: sel = $( \"td.\" + $.datepicker._dayOverClass + \":not(.\" +\n\t\t\t\t\t\t\t\t\t$.datepicker._currentClass + \")\", inst.dpDiv );\n\t\t\t\t\t\tif ( sel[ 0 ] ) {\n\t\t\t\t\t\t\t$.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tonSelect = $.datepicker._get( inst, \"onSelect\" );\n\t\t\t\t\t\tif ( onSelect ) {\n\t\t\t\t\t\t\tdateStr = $.datepicker._formatDate( inst );\n\n\t\t\t\t\t\t\t// Trigger custom callback\n\t\t\t\t\t\t\tonSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn false; // don't submit the form\n\t\t\t\tcase 27: $.datepicker._hideDatepicker();\n\t\t\t\t\t\tbreak; // hide on escape\n\t\t\t\tcase 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?\n\t\t\t\t\t\t\t-$.datepicker._get( inst, \"stepBigMonths\" ) :\n\t\t\t\t\t\t\t-$.datepicker._get( inst, \"stepMonths\" ) ), \"M\" );\n\t\t\t\t\t\tbreak; // previous month/year on page up/+ ctrl\n\t\t\t\tcase 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?\n\t\t\t\t\t\t\t+$.datepicker._get( inst, \"stepBigMonths\" ) :\n\t\t\t\t\t\t\t+$.datepicker._get( inst, \"stepMonths\" ) ), \"M\" );\n\t\t\t\t\t\tbreak; // next month/year on page down/+ ctrl\n\t\t\t\tcase 35: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._clearDate( event.target );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // clear on ctrl or command +end\n\t\t\t\tcase 36: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._gotoToday( event.target );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // current on ctrl or command +home\n\t\t\t\tcase 37: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), \"D\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\n\t\t\t\t\t\t// -1 day on ctrl or command +left\n\t\t\t\t\t\tif ( event.originalEvent.altKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, ( event.ctrlKey ?\n\t\t\t\t\t\t\t\t-$.datepicker._get( inst, \"stepBigMonths\" ) :\n\t\t\t\t\t\t\t\t-$.datepicker._get( inst, \"stepMonths\" ) ), \"M\" );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// next month/year on alt +left on Mac\n\t\t\t\t\t\tbreak;\n\t\t\t\tcase 38: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, -7, \"D\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // -1 week on ctrl or command +up\n\t\t\t\tcase 39: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), \"D\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\n\t\t\t\t\t\t// +1 day on ctrl or command +right\n\t\t\t\t\t\tif ( event.originalEvent.altKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, ( event.ctrlKey ?\n\t\t\t\t\t\t\t\t+$.datepicker._get( inst, \"stepBigMonths\" ) :\n\t\t\t\t\t\t\t\t+$.datepicker._get( inst, \"stepMonths\" ) ), \"M\" );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// next month/year on alt +right\n\t\t\t\t\t\tbreak;\n\t\t\t\tcase 40: if ( event.ctrlKey || event.metaKey ) {\n\t\t\t\t\t\t\t$.datepicker._adjustDate( event.target, +7, \"D\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n\t\t\t\t\t\tbreak; // +1 week on ctrl or command +down\n\t\t\t\tdefault: handled = false;\n\t\t\t}\n\t\t} else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home\n\t\t\t$.datepicker._showDatepicker( this );\n\t\t} else {\n\t\t\thandled = false;\n\t\t}\n\n\t\tif ( handled ) {\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\t},\n\n\t/* Filter entered characters - based on date format. */\n\t_doKeyPress: function( event ) {\n\t\tvar chars, chr,\n\t\t\tinst = $.datepicker._getInst( event.target );\n\n\t\tif ( $.datepicker._get( inst, \"constrainInput\" ) ) {\n\t\t\tchars = $.datepicker._possibleChars( $.datepicker._get( inst, \"dateFormat\" ) );\n\t\t\tchr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );\n\t\t\treturn event.ctrlKey || event.metaKey || ( chr < \" \" || !chars || chars.indexOf( chr ) > -1 );\n\t\t}\n\t},\n\n\t/* Synchronise manual entry and field/alternate field. */\n\t_doKeyUp: function( event ) {\n\t\tvar date,\n\t\t\tinst = $.datepicker._getInst( event.target );\n\n\t\tif ( inst.input.val() !== inst.lastVal ) {\n\t\t\ttry {\n\t\t\t\tdate = $.datepicker.parseDate( $.datepicker._get( inst, \"dateFormat\" ),\n\t\t\t\t\t( inst.input ? inst.input.val() : null ),\n\t\t\t\t\t$.datepicker._getFormatConfig( inst ) );\n\n\t\t\t\tif ( date ) { // only if valid\n\t\t\t\t\t$.datepicker._setDateFromField( inst );\n\t\t\t\t\t$.datepicker._updateAlternate( inst );\n\t\t\t\t\t$.datepicker._updateDatepicker( inst );\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch ( err ) {\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t},\n\n\t/* Pop-up the date picker for a given input field.\n\t * If false returned from beforeShow event handler do not show.\n\t * @param  input  element - the input field attached to the date picker or\n\t *\t\t\t\t\tevent - if triggered by focus\n\t */\n\t_showDatepicker: function( input ) {\n\t\tinput = input.target || input;\n\t\tif ( input.nodeName.toLowerCase() !== \"input\" ) { // find from button/image trigger\n\t\t\tinput = $( \"input\", input.parentNode )[ 0 ];\n\t\t}\n\n\t\tif ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here\n\t\t\treturn;\n\t\t}\n\n\t\tvar inst, beforeShow, beforeShowSettings, isFixed,\n\t\t\toffset, showAnim, duration;\n\n\t\tinst = $.datepicker._getInst( input );\n\t\tif ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {\n\t\t\t$.datepicker._curInst.dpDiv.stop( true, true );\n\t\t\tif ( inst && $.datepicker._datepickerShowing ) {\n\t\t\t\t$.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );\n\t\t\t}\n\t\t}\n\n\t\tbeforeShow = $.datepicker._get( inst, \"beforeShow\" );\n\t\tbeforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};\n\t\tif ( beforeShowSettings === false ) {\n\t\t\treturn;\n\t\t}\n\t\tdatepicker_extendRemove( inst.settings, beforeShowSettings );\n\n\t\tinst.lastVal = null;\n\t\t$.datepicker._lastInput = input;\n\t\t$.datepicker._setDateFromField( inst );\n\n\t\tif ( $.datepicker._inDialog ) { // hide cursor\n\t\t\tinput.value = \"\";\n\t\t}\n\t\tif ( !$.datepicker._pos ) { // position below input\n\t\t\t$.datepicker._pos = $.datepicker._findPos( input );\n\t\t\t$.datepicker._pos[ 1 ] += input.offsetHeight; // add the height\n\t\t}\n\n\t\tisFixed = false;\n\t\t$( input ).parents().each( function() {\n\t\t\tisFixed |= $( this ).css( \"position\" ) === \"fixed\";\n\t\t\treturn !isFixed;\n\t\t} );\n\n\t\toffset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };\n\t\t$.datepicker._pos = null;\n\n\t\t//to avoid flashes on Firefox\n\t\tinst.dpDiv.empty();\n\n\t\t// determine sizing offscreen\n\t\tinst.dpDiv.css( { position: \"absolute\", display: \"block\", top: \"-1000px\" } );\n\t\t$.datepicker._updateDatepicker( inst );\n\n\t\t// fix width for dynamic number of date pickers\n\t\t// and adjust position before showing\n\t\toffset = $.datepicker._checkOffset( inst, offset, isFixed );\n\t\tinst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?\n\t\t\t\"static\" : ( isFixed ? \"fixed\" : \"absolute\" ) ), display: \"none\",\n\t\t\tleft: offset.left + \"px\", top: offset.top + \"px\" } );\n\n\t\tif ( !inst.inline ) {\n\t\t\tshowAnim = $.datepicker._get( inst, \"showAnim\" );\n\t\t\tduration = $.datepicker._get( inst, \"duration\" );\n\t\t\tinst.dpDiv.css( \"z-index\", datepicker_getZindex( $( input ) ) + 1 );\n\t\t\t$.datepicker._datepickerShowing = true;\n\n\t\t\tif ( $.effects && $.effects.effect[ showAnim ] ) {\n\t\t\t\tinst.dpDiv.show( showAnim, $.datepicker._get( inst, \"showOptions\" ), duration );\n\t\t\t} else {\n\t\t\t\tinst.dpDiv[ showAnim || \"show\" ]( showAnim ? duration : null );\n\t\t\t}\n\n\t\t\tif ( $.datepicker._shouldFocusInput( inst ) ) {\n\t\t\t\tinst.input.trigger( \"focus\" );\n\t\t\t}\n\n\t\t\t$.datepicker._curInst = inst;\n\t\t}\n\t},\n\n\t/* Generate the date picker content. */\n\t_updateDatepicker: function( inst ) {\n\t\tthis.maxRows = 4; //Reset the max number of rows being displayed (see #7043)\n\t\tdatepicker_instActive = inst; // for delegate hover events\n\t\tinst.dpDiv.empty().append( this._generateHTML( inst ) );\n\t\tthis._attachHandlers( inst );\n\n\t\tvar origyearshtml,\n\t\t\tnumMonths = this._getNumberOfMonths( inst ),\n\t\t\tcols = numMonths[ 1 ],\n\t\t\twidth = 17,\n\t\t\tactiveCell = inst.dpDiv.find( \".\" + this._dayOverClass + \" a\" );\n\n\t\tif ( activeCell.length > 0 ) {\n\t\t\tdatepicker_handleMouseover.apply( activeCell.get( 0 ) );\n\t\t}\n\n\t\tinst.dpDiv.removeClass( \"ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4\" ).width( \"\" );\n\t\tif ( cols > 1 ) {\n\t\t\tinst.dpDiv.addClass( \"ui-datepicker-multi-\" + cols ).css( \"width\", ( width * cols ) + \"em\" );\n\t\t}\n\t\tinst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? \"add\" : \"remove\" ) +\n\t\t\t\"Class\" ]( \"ui-datepicker-multi\" );\n\t\tinst.dpDiv[ ( this._get( inst, \"isRTL\" ) ? \"add\" : \"remove\" ) +\n\t\t\t\"Class\" ]( \"ui-datepicker-rtl\" );\n\n\t\tif ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {\n\t\t\tinst.input.trigger( \"focus\" );\n\t\t}\n\n\t\t// Deffered render of the years select (to avoid flashes on Firefox)\n\t\tif ( inst.yearshtml ) {\n\t\t\torigyearshtml = inst.yearshtml;\n\t\t\tsetTimeout( function() {\n\n\t\t\t\t//assure that inst.yearshtml didn't change.\n\t\t\t\tif ( origyearshtml === inst.yearshtml && inst.yearshtml ) {\n\t\t\t\t\tinst.dpDiv.find( \"select.ui-datepicker-year:first\" ).replaceWith( inst.yearshtml );\n\t\t\t\t}\n\t\t\t\torigyearshtml = inst.yearshtml = null;\n\t\t\t}, 0 );\n\t\t}\n\t},\n\n\t// #6694 - don't focus the input if it's already focused\n\t// this breaks the change event in IE\n\t// Support: IE and jQuery <1.9\n\t_shouldFocusInput: function( inst ) {\n\t\treturn inst.input && inst.input.is( \":visible\" ) && !inst.input.is( \":disabled\" ) && !inst.input.is( \":focus\" );\n\t},\n\n\t/* Check positioning to remain on screen. */\n\t_checkOffset: function( inst, offset, isFixed ) {\n\t\tvar dpWidth = inst.dpDiv.outerWidth(),\n\t\t\tdpHeight = inst.dpDiv.outerHeight(),\n\t\t\tinputWidth = inst.input ? inst.input.outerWidth() : 0,\n\t\t\tinputHeight = inst.input ? inst.input.outerHeight() : 0,\n\t\t\tviewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),\n\t\t\tviewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );\n\n\t\toffset.left -= ( this._get( inst, \"isRTL\" ) ? ( dpWidth - inputWidth ) : 0 );\n\t\toffset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;\n\t\toffset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;\n\n\t\t// Now check if datepicker is showing outside window viewport - move to a better place if so.\n\t\toffset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?\n\t\t\tMath.abs( offset.left + dpWidth - viewWidth ) : 0 );\n\t\toffset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?\n\t\t\tMath.abs( dpHeight + inputHeight ) : 0 );\n\n\t\treturn offset;\n\t},\n\n\t/* Find an object's position on the screen. */\n\t_findPos: function( obj ) {\n\t\tvar position,\n\t\t\tinst = this._getInst( obj ),\n\t\t\tisRTL = this._get( inst, \"isRTL\" );\n\n\t\twhile ( obj && ( obj.type === \"hidden\" || obj.nodeType !== 1 || $.expr.filters.hidden( obj ) ) ) {\n\t\t\tobj = obj[ isRTL ? \"previousSibling\" : \"nextSibling\" ];\n\t\t}\n\n\t\tposition = $( obj ).offset();\n\t\treturn [ position.left, position.top ];\n\t},\n\n\t/* Hide the date picker from view.\n\t * @param  input  element - the input field attached to the date picker\n\t */\n\t_hideDatepicker: function( input ) {\n\t\tvar showAnim, duration, postProcess, onClose,\n\t\t\tinst = this._curInst;\n\n\t\tif ( !inst || ( input && inst !== $.data( input, \"datepicker\" ) ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this._datepickerShowing ) {\n\t\t\tshowAnim = this._get( inst, \"showAnim\" );\n\t\t\tduration = this._get( inst, \"duration\" );\n\t\t\tpostProcess = function() {\n\t\t\t\t$.datepicker._tidyDialog( inst );\n\t\t\t};\n\n\t\t\t// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed\n\t\t\tif ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {\n\t\t\t\tinst.dpDiv.hide( showAnim, $.datepicker._get( inst, \"showOptions\" ), duration, postProcess );\n\t\t\t} else {\n\t\t\t\tinst.dpDiv[ ( showAnim === \"slideDown\" ? \"slideUp\" :\n\t\t\t\t\t( showAnim === \"fadeIn\" ? \"fadeOut\" : \"hide\" ) ) ]( ( showAnim ? duration : null ), postProcess );\n\t\t\t}\n\n\t\t\tif ( !showAnim ) {\n\t\t\t\tpostProcess();\n\t\t\t}\n\t\t\tthis._datepickerShowing = false;\n\n\t\t\tonClose = this._get( inst, \"onClose\" );\n\t\t\tif ( onClose ) {\n\t\t\t\tonClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : \"\" ), inst ] );\n\t\t\t}\n\n\t\t\tthis._lastInput = null;\n\t\t\tif ( this._inDialog ) {\n\t\t\t\tthis._dialogInput.css( { position: \"absolute\", left: \"0\", top: \"-100px\" } );\n\t\t\t\tif ( $.blockUI ) {\n\t\t\t\t\t$.unblockUI();\n\t\t\t\t\t$( \"body\" ).append( this.dpDiv );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._inDialog = false;\n\t\t}\n\t},\n\n\t/* Tidy up after a dialog display. */\n\t_tidyDialog: function( inst ) {\n\t\tinst.dpDiv.removeClass( this._dialogClass ).off( \".ui-datepicker-calendar\" );\n\t},\n\n\t/* Close date picker if clicked elsewhere. */\n\t_checkExternalClick: function( event ) {\n\t\tif ( !$.datepicker._curInst ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar $target = $( event.target ),\n\t\t\tinst = $.datepicker._getInst( $target[ 0 ] );\n\n\t\tif ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&\n\t\t\t\t$target.parents( \"#\" + $.datepicker._mainDivId ).length === 0 &&\n\t\t\t\t!$target.hasClass( $.datepicker.markerClassName ) &&\n\t\t\t\t!$target.closest( \".\" + $.datepicker._triggerClass ).length &&\n\t\t\t\t$.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||\n\t\t\t( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {\n\t\t\t\t$.datepicker._hideDatepicker();\n\t\t}\n\t},\n\n\t/* Adjust one of the date sub-fields. */\n\t_adjustDate: function( id, offset, period ) {\n\t\tvar target = $( id ),\n\t\t\tinst = this._getInst( target[ 0 ] );\n\n\t\tif ( this._isDisabledDatepicker( target[ 0 ] ) ) {\n\t\t\treturn;\n\t\t}\n\t\tthis._adjustInstDate( inst, offset +\n\t\t\t( period === \"M\" ? this._get( inst, \"showCurrentAtPos\" ) : 0 ), // undo positioning\n\t\t\tperiod );\n\t\tthis._updateDatepicker( inst );\n\t},\n\n\t/* Action for current link. */\n\t_gotoToday: function( id ) {\n\t\tvar date,\n\t\t\ttarget = $( id ),\n\t\t\tinst = this._getInst( target[ 0 ] );\n\n\t\tif ( this._get( inst, \"gotoCurrent\" ) && inst.currentDay ) {\n\t\t\tinst.selectedDay = inst.currentDay;\n\t\t\tinst.drawMonth = inst.selectedMonth = inst.currentMonth;\n\t\t\tinst.drawYear = inst.selectedYear = inst.currentYear;\n\t\t} else {\n\t\t\tdate = new Date();\n\t\t\tinst.selectedDay = date.getDate();\n\t\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n\t\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n\t\t}\n\t\tthis._notifyChange( inst );\n\t\tthis._adjustDate( target );\n\t},\n\n\t/* Action for selecting a new month/year. */\n\t_selectMonthYear: function( id, select, period ) {\n\t\tvar target = $( id ),\n\t\t\tinst = this._getInst( target[ 0 ] );\n\n\t\tinst[ \"selected\" + ( period === \"M\" ? \"Month\" : \"Year\" ) ] =\n\t\tinst[ \"draw\" + ( period === \"M\" ? \"Month\" : \"Year\" ) ] =\n\t\t\tparseInt( select.options[ select.selectedIndex ].value, 10 );\n\n\t\tthis._notifyChange( inst );\n\t\tthis._adjustDate( target );\n\t},\n\n\t/* Action for selecting a day. */\n\t_selectDay: function( id, month, year, td ) {\n\t\tvar inst,\n\t\t\ttarget = $( id );\n\n\t\tif ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tinst = this._getInst( target[ 0 ] );\n\t\tinst.selectedDay = inst.currentDay = $( \"a\", td ).html();\n\t\tinst.selectedMonth = inst.currentMonth = month;\n\t\tinst.selectedYear = inst.currentYear = year;\n\t\tthis._selectDate( id, this._formatDate( inst,\n\t\t\tinst.currentDay, inst.currentMonth, inst.currentYear ) );\n\t},\n\n\t/* Erase the input field and hide the date picker. */\n\t_clearDate: function( id ) {\n\t\tvar target = $( id );\n\t\tthis._selectDate( target, \"\" );\n\t},\n\n\t/* Update the input field with the selected date. */\n\t_selectDate: function( id, dateStr ) {\n\t\tvar onSelect,\n\t\t\ttarget = $( id ),\n\t\t\tinst = this._getInst( target[ 0 ] );\n\n\t\tdateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );\n\t\tif ( inst.input ) {\n\t\t\tinst.input.val( dateStr );\n\t\t}\n\t\tthis._updateAlternate( inst );\n\n\t\tonSelect = this._get( inst, \"onSelect\" );\n\t\tif ( onSelect ) {\n\t\t\tonSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback\n\t\t} else if ( inst.input ) {\n\t\t\tinst.input.trigger( \"change\" ); // fire the change event\n\t\t}\n\n\t\tif ( inst.inline ) {\n\t\t\tthis._updateDatepicker( inst );\n\t\t} else {\n\t\t\tthis._hideDatepicker();\n\t\t\tthis._lastInput = inst.input[ 0 ];\n\t\t\tif ( typeof( inst.input[ 0 ] ) !== \"object\" ) {\n\t\t\t\tinst.input.trigger( \"focus\" ); // restore focus\n\t\t\t}\n\t\t\tthis._lastInput = null;\n\t\t}\n\t},\n\n\t/* Update any alternate field to synchronise with the main field. */\n\t_updateAlternate: function( inst ) {\n\t\tvar altFormat, date, dateStr,\n\t\t\taltField = this._get( inst, \"altField\" );\n\n\t\tif ( altField ) { // update alternate field too\n\t\t\taltFormat = this._get( inst, \"altFormat\" ) || this._get( inst, \"dateFormat\" );\n\t\t\tdate = this._getDate( inst );\n\t\t\tdateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );\n\t\t\t$( altField ).val( dateStr );\n\t\t}\n\t},\n\n\t/* Set as beforeShowDay function to prevent selection of weekends.\n\t * @param  date  Date - the date to customise\n\t * @return [boolean, string] - is this date selectable?, what is its CSS class?\n\t */\n\tnoWeekends: function( date ) {\n\t\tvar day = date.getDay();\n\t\treturn [ ( day > 0 && day < 6 ), \"\" ];\n\t},\n\n\t/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.\n\t * @param  date  Date - the date to get the week for\n\t * @return  number - the number of the week within the year that contains this date\n\t */\n\tiso8601Week: function( date ) {\n\t\tvar time,\n\t\t\tcheckDate = new Date( date.getTime() );\n\n\t\t// Find Thursday of this week starting on Monday\n\t\tcheckDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );\n\n\t\ttime = checkDate.getTime();\n\t\tcheckDate.setMonth( 0 ); // Compare with Jan 1\n\t\tcheckDate.setDate( 1 );\n\t\treturn Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;\n\t},\n\n\t/* Parse a string value into a date object.\n\t * See formatDate below for the possible formats.\n\t *\n\t * @param  format string - the expected format of the date\n\t * @param  value string - the date in the above format\n\t * @param  settings Object - attributes include:\n\t *\t\t\t\t\tshortYearCutoff  number - the cutoff year for determining the century (optional)\n\t *\t\t\t\t\tdayNamesShort\tstring[7] - abbreviated names of the days from Sunday (optional)\n\t *\t\t\t\t\tdayNames\t\tstring[7] - names of the days from Sunday (optional)\n\t *\t\t\t\t\tmonthNamesShort string[12] - abbreviated names of the months (optional)\n\t *\t\t\t\t\tmonthNames\t\tstring[12] - names of the months (optional)\n\t * @return  Date - the extracted date value or null if value is blank\n\t */\n\tparseDate: function( format, value, settings ) {\n\t\tif ( format == null || value == null ) {\n\t\t\tthrow \"Invalid arguments\";\n\t\t}\n\n\t\tvalue = ( typeof value === \"object\" ? value.toString() : value + \"\" );\n\t\tif ( value === \"\" ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tvar iFormat, dim, extra,\n\t\t\tiValue = 0,\n\t\t\tshortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,\n\t\t\tshortYearCutoff = ( typeof shortYearCutoffTemp !== \"string\" ? shortYearCutoffTemp :\n\t\t\t\tnew Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),\n\t\t\tdayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,\n\t\t\tdayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,\n\t\t\tmonthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,\n\t\t\tmonthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,\n\t\t\tyear = -1,\n\t\t\tmonth = -1,\n\t\t\tday = -1,\n\t\t\tdoy = -1,\n\t\t\tliteral = false,\n\t\t\tdate,\n\n\t\t\t// Check whether a format character is doubled\n\t\t\tlookAhead = function( match ) {\n\t\t\t\tvar matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );\n\t\t\t\tif ( matches ) {\n\t\t\t\t\tiFormat++;\n\t\t\t\t}\n\t\t\t\treturn matches;\n\t\t\t},\n\n\t\t\t// Extract a number from the string value\n\t\t\tgetNumber = function( match ) {\n\t\t\t\tvar isDoubled = lookAhead( match ),\n\t\t\t\t\tsize = ( match === \"@\" ? 14 : ( match === \"!\" ? 20 :\n\t\t\t\t\t( match === \"y\" && isDoubled ? 4 : ( match === \"o\" ? 3 : 2 ) ) ) ),\n\t\t\t\t\tminSize = ( match === \"y\" ? size : 1 ),\n\t\t\t\t\tdigits = new RegExp( \"^\\\\d{\" + minSize + \",\" + size + \"}\" ),\n\t\t\t\t\tnum = value.substring( iValue ).match( digits );\n\t\t\t\tif ( !num ) {\n\t\t\t\t\tthrow \"Missing number at position \" + iValue;\n\t\t\t\t}\n\t\t\t\tiValue += num[ 0 ].length;\n\t\t\t\treturn parseInt( num[ 0 ], 10 );\n\t\t\t},\n\n\t\t\t// Extract a name from the string value and convert to an index\n\t\t\tgetName = function( match, shortNames, longNames ) {\n\t\t\t\tvar index = -1,\n\t\t\t\t\tnames = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {\n\t\t\t\t\t\treturn [ [ k, v ] ];\n\t\t\t\t\t} ).sort( function( a, b ) {\n\t\t\t\t\t\treturn -( a[ 1 ].length - b[ 1 ].length );\n\t\t\t\t\t} );\n\n\t\t\t\t$.each( names, function( i, pair ) {\n\t\t\t\t\tvar name = pair[ 1 ];\n\t\t\t\t\tif ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {\n\t\t\t\t\t\tindex = pair[ 0 ];\n\t\t\t\t\t\tiValue += name.length;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\tif ( index !== -1 ) {\n\t\t\t\t\treturn index + 1;\n\t\t\t\t} else {\n\t\t\t\t\tthrow \"Unknown name at position \" + iValue;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// Confirm that a literal character matches the string value\n\t\t\tcheckLiteral = function() {\n\t\t\t\tif ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {\n\t\t\t\t\tthrow \"Unexpected literal at position \" + iValue;\n\t\t\t\t}\n\t\t\t\tiValue++;\n\t\t\t};\n\n\t\tfor ( iFormat = 0; iFormat < format.length; iFormat++ ) {\n\t\t\tif ( literal ) {\n\t\t\t\tif ( format.charAt( iFormat ) === \"'\" && !lookAhead( \"'\" ) ) {\n\t\t\t\t\tliteral = false;\n\t\t\t\t} else {\n\t\t\t\t\tcheckLiteral();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch ( format.charAt( iFormat ) ) {\n\t\t\t\t\tcase \"d\":\n\t\t\t\t\t\tday = getNumber( \"d\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"D\":\n\t\t\t\t\t\tgetName( \"D\", dayNamesShort, dayNames );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"o\":\n\t\t\t\t\t\tdoy = getNumber( \"o\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"m\":\n\t\t\t\t\t\tmonth = getNumber( \"m\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"M\":\n\t\t\t\t\t\tmonth = getName( \"M\", monthNamesShort, monthNames );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"y\":\n\t\t\t\t\t\tyear = getNumber( \"y\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"@\":\n\t\t\t\t\t\tdate = new Date( getNumber( \"@\" ) );\n\t\t\t\t\t\tyear = date.getFullYear();\n\t\t\t\t\t\tmonth = date.getMonth() + 1;\n\t\t\t\t\t\tday = date.getDate();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"!\":\n\t\t\t\t\t\tdate = new Date( ( getNumber( \"!\" ) - this._ticksTo1970 ) / 10000 );\n\t\t\t\t\t\tyear = date.getFullYear();\n\t\t\t\t\t\tmonth = date.getMonth() + 1;\n\t\t\t\t\t\tday = date.getDate();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\tif ( lookAhead( \"'\" ) ) {\n\t\t\t\t\t\t\tcheckLiteral();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tliteral = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tcheckLiteral();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( iValue < value.length ) {\n\t\t\textra = value.substr( iValue );\n\t\t\tif ( !/^\\s+/.test( extra ) ) {\n\t\t\t\tthrow \"Extra/unparsed characters found in date: \" + extra;\n\t\t\t}\n\t\t}\n\n\t\tif ( year === -1 ) {\n\t\t\tyear = new Date().getFullYear();\n\t\t} else if ( year < 100 ) {\n\t\t\tyear += new Date().getFullYear() - new Date().getFullYear() % 100 +\n\t\t\t\t( year <= shortYearCutoff ? 0 : -100 );\n\t\t}\n\n\t\tif ( doy > -1 ) {\n\t\t\tmonth = 1;\n\t\t\tday = doy;\n\t\t\tdo {\n\t\t\t\tdim = this._getDaysInMonth( year, month - 1 );\n\t\t\t\tif ( day <= dim ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmonth++;\n\t\t\t\tday -= dim;\n\t\t\t} while ( true );\n\t\t}\n\n\t\tdate = this._daylightSavingAdjust( new Date( year, month - 1, day ) );\n\t\tif ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {\n\t\t\tthrow \"Invalid date\"; // E.g. 31/02/00\n\t\t}\n\t\treturn date;\n\t},\n\n\t/* Standard date formats. */\n\tATOM: \"yy-mm-dd\", // RFC 3339 (ISO 8601)\n\tCOOKIE: \"D, dd M yy\",\n\tISO_8601: \"yy-mm-dd\",\n\tRFC_822: \"D, d M y\",\n\tRFC_850: \"DD, dd-M-y\",\n\tRFC_1036: \"D, d M y\",\n\tRFC_1123: \"D, d M yy\",\n\tRFC_2822: \"D, d M yy\",\n\tRSS: \"D, d M y\", // RFC 822\n\tTICKS: \"!\",\n\tTIMESTAMP: \"@\",\n\tW3C: \"yy-mm-dd\", // ISO 8601\n\n\t_ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +\n\t\tMath.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),\n\n\t/* Format a date object into a string value.\n\t * The format can be combinations of the following:\n\t * d  - day of month (no leading zero)\n\t * dd - day of month (two digit)\n\t * o  - day of year (no leading zeros)\n\t * oo - day of year (three digit)\n\t * D  - day name short\n\t * DD - day name long\n\t * m  - month of year (no leading zero)\n\t * mm - month of year (two digit)\n\t * M  - month name short\n\t * MM - month name long\n\t * y  - year (two digit)\n\t * yy - year (four digit)\n\t * @ - Unix timestamp (ms since 01/01/1970)\n\t * ! - Windows ticks (100ns since 01/01/0001)\n\t * \"...\" - literal text\n\t * '' - single quote\n\t *\n\t * @param  format string - the desired format of the date\n\t * @param  date Date - the date value to format\n\t * @param  settings Object - attributes include:\n\t *\t\t\t\t\tdayNamesShort\tstring[7] - abbreviated names of the days from Sunday (optional)\n\t *\t\t\t\t\tdayNames\t\tstring[7] - names of the days from Sunday (optional)\n\t *\t\t\t\t\tmonthNamesShort string[12] - abbreviated names of the months (optional)\n\t *\t\t\t\t\tmonthNames\t\tstring[12] - names of the months (optional)\n\t * @return  string - the date in the above format\n\t */\n\tformatDate: function( format, date, settings ) {\n\t\tif ( !date ) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tvar iFormat,\n\t\t\tdayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,\n\t\t\tdayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,\n\t\t\tmonthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,\n\t\t\tmonthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,\n\n\t\t\t// Check whether a format character is doubled\n\t\t\tlookAhead = function( match ) {\n\t\t\t\tvar matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );\n\t\t\t\tif ( matches ) {\n\t\t\t\t\tiFormat++;\n\t\t\t\t}\n\t\t\t\treturn matches;\n\t\t\t},\n\n\t\t\t// Format a number, with leading zero if necessary\n\t\t\tformatNumber = function( match, value, len ) {\n\t\t\t\tvar num = \"\" + value;\n\t\t\t\tif ( lookAhead( match ) ) {\n\t\t\t\t\twhile ( num.length < len ) {\n\t\t\t\t\t\tnum = \"0\" + num;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn num;\n\t\t\t},\n\n\t\t\t// Format a name, short or long as requested\n\t\t\tformatName = function( match, value, shortNames, longNames ) {\n\t\t\t\treturn ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );\n\t\t\t},\n\t\t\toutput = \"\",\n\t\t\tliteral = false;\n\n\t\tif ( date ) {\n\t\t\tfor ( iFormat = 0; iFormat < format.length; iFormat++ ) {\n\t\t\t\tif ( literal ) {\n\t\t\t\t\tif ( format.charAt( iFormat ) === \"'\" && !lookAhead( \"'\" ) ) {\n\t\t\t\t\t\tliteral = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\toutput += format.charAt( iFormat );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tswitch ( format.charAt( iFormat ) ) {\n\t\t\t\t\t\tcase \"d\":\n\t\t\t\t\t\t\toutput += formatNumber( \"d\", date.getDate(), 2 );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"D\":\n\t\t\t\t\t\t\toutput += formatName( \"D\", date.getDay(), dayNamesShort, dayNames );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"o\":\n\t\t\t\t\t\t\toutput += formatNumber( \"o\",\n\t\t\t\t\t\t\t\tMath.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"m\":\n\t\t\t\t\t\t\toutput += formatNumber( \"m\", date.getMonth() + 1, 2 );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"M\":\n\t\t\t\t\t\t\toutput += formatName( \"M\", date.getMonth(), monthNamesShort, monthNames );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"y\":\n\t\t\t\t\t\t\toutput += ( lookAhead( \"y\" ) ? date.getFullYear() :\n\t\t\t\t\t\t\t\t( date.getFullYear() % 100 < 10 ? \"0\" : \"\" ) + date.getFullYear() % 100 );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"@\":\n\t\t\t\t\t\t\toutput += date.getTime();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"!\":\n\t\t\t\t\t\t\toutput += date.getTime() * 10000 + this._ticksTo1970;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\t\tif ( lookAhead( \"'\" ) ) {\n\t\t\t\t\t\t\t\toutput += \"'\";\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tliteral = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\toutput += format.charAt( iFormat );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t},\n\n\t/* Extract all possible characters from the date format. */\n\t_possibleChars: function( format ) {\n\t\tvar iFormat,\n\t\t\tchars = \"\",\n\t\t\tliteral = false,\n\n\t\t\t// Check whether a format character is doubled\n\t\t\tlookAhead = function( match ) {\n\t\t\t\tvar matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );\n\t\t\t\tif ( matches ) {\n\t\t\t\t\tiFormat++;\n\t\t\t\t}\n\t\t\t\treturn matches;\n\t\t\t};\n\n\t\tfor ( iFormat = 0; iFormat < format.length; iFormat++ ) {\n\t\t\tif ( literal ) {\n\t\t\t\tif ( format.charAt( iFormat ) === \"'\" && !lookAhead( \"'\" ) ) {\n\t\t\t\t\tliteral = false;\n\t\t\t\t} else {\n\t\t\t\t\tchars += format.charAt( iFormat );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch ( format.charAt( iFormat ) ) {\n\t\t\t\t\tcase \"d\": case \"m\": case \"y\": case \"@\":\n\t\t\t\t\t\tchars += \"0123456789\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"D\": case \"M\":\n\t\t\t\t\t\treturn null; // Accept anything\n\t\t\t\t\tcase \"'\":\n\t\t\t\t\t\tif ( lookAhead( \"'\" ) ) {\n\t\t\t\t\t\t\tchars += \"'\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tliteral = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tchars += format.charAt( iFormat );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn chars;\n\t},\n\n\t/* Get a setting value, defaulting if necessary. */\n\t_get: function( inst, name ) {\n\t\treturn inst.settings[ name ] !== undefined ?\n\t\t\tinst.settings[ name ] : this._defaults[ name ];\n\t},\n\n\t/* Parse existing date and initialise date picker. */\n\t_setDateFromField: function( inst, noDefault ) {\n\t\tif ( inst.input.val() === inst.lastVal ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar dateFormat = this._get( inst, \"dateFormat\" ),\n\t\t\tdates = inst.lastVal = inst.input ? inst.input.val() : null,\n\t\t\tdefaultDate = this._getDefaultDate( inst ),\n\t\t\tdate = defaultDate,\n\t\t\tsettings = this._getFormatConfig( inst );\n\n\t\ttry {\n\t\t\tdate = this.parseDate( dateFormat, dates, settings ) || defaultDate;\n\t\t} catch ( event ) {\n\t\t\tdates = ( noDefault ? \"\" : dates );\n\t\t}\n\t\tinst.selectedDay = date.getDate();\n\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n\t\tinst.currentDay = ( dates ? date.getDate() : 0 );\n\t\tinst.currentMonth = ( dates ? date.getMonth() : 0 );\n\t\tinst.currentYear = ( dates ? date.getFullYear() : 0 );\n\t\tthis._adjustInstDate( inst );\n\t},\n\n\t/* Retrieve the default date shown on opening. */\n\t_getDefaultDate: function( inst ) {\n\t\treturn this._restrictMinMax( inst,\n\t\t\tthis._determineDate( inst, this._get( inst, \"defaultDate\" ), new Date() ) );\n\t},\n\n\t/* A date may be specified as an exact value or a relative one. */\n\t_determineDate: function( inst, date, defaultDate ) {\n\t\tvar offsetNumeric = function( offset ) {\n\t\t\t\tvar date = new Date();\n\t\t\t\tdate.setDate( date.getDate() + offset );\n\t\t\t\treturn date;\n\t\t\t},\n\t\t\toffsetString = function( offset ) {\n\t\t\t\ttry {\n\t\t\t\t\treturn $.datepicker.parseDate( $.datepicker._get( inst, \"dateFormat\" ),\n\t\t\t\t\t\toffset, $.datepicker._getFormatConfig( inst ) );\n\t\t\t\t}\n\t\t\t\tcatch ( e ) {\n\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\n\t\t\t\tvar date = ( offset.toLowerCase().match( /^c/ ) ?\n\t\t\t\t\t$.datepicker._getDate( inst ) : null ) || new Date(),\n\t\t\t\t\tyear = date.getFullYear(),\n\t\t\t\t\tmonth = date.getMonth(),\n\t\t\t\t\tday = date.getDate(),\n\t\t\t\t\tpattern = /([+\\-]?[0-9]+)\\s*(d|D|w|W|m|M|y|Y)?/g,\n\t\t\t\t\tmatches = pattern.exec( offset );\n\n\t\t\t\twhile ( matches ) {\n\t\t\t\t\tswitch ( matches[ 2 ] || \"d\" ) {\n\t\t\t\t\t\tcase \"d\" : case \"D\" :\n\t\t\t\t\t\t\tday += parseInt( matches[ 1 ], 10 ); break;\n\t\t\t\t\t\tcase \"w\" : case \"W\" :\n\t\t\t\t\t\t\tday += parseInt( matches[ 1 ], 10 ) * 7; break;\n\t\t\t\t\t\tcase \"m\" : case \"M\" :\n\t\t\t\t\t\t\tmonth += parseInt( matches[ 1 ], 10 );\n\t\t\t\t\t\t\tday = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase \"y\": case \"Y\" :\n\t\t\t\t\t\t\tyear += parseInt( matches[ 1 ], 10 );\n\t\t\t\t\t\t\tday = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tmatches = pattern.exec( offset );\n\t\t\t\t}\n\t\t\t\treturn new Date( year, month, day );\n\t\t\t},\n\t\t\tnewDate = ( date == null || date === \"\" ? defaultDate : ( typeof date === \"string\" ? offsetString( date ) :\n\t\t\t\t( typeof date === \"number\" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );\n\n\t\tnewDate = ( newDate && newDate.toString() === \"Invalid Date\" ? defaultDate : newDate );\n\t\tif ( newDate ) {\n\t\t\tnewDate.setHours( 0 );\n\t\t\tnewDate.setMinutes( 0 );\n\t\t\tnewDate.setSeconds( 0 );\n\t\t\tnewDate.setMilliseconds( 0 );\n\t\t}\n\t\treturn this._daylightSavingAdjust( newDate );\n\t},\n\n\t/* Handle switch to/from daylight saving.\n\t * Hours may be non-zero on daylight saving cut-over:\n\t * > 12 when midnight changeover, but then cannot generate\n\t * midnight datetime, so jump to 1AM, otherwise reset.\n\t * @param  date  (Date) the date to check\n\t * @return  (Date) the corrected date\n\t */\n\t_daylightSavingAdjust: function( date ) {\n\t\tif ( !date ) {\n\t\t\treturn null;\n\t\t}\n\t\tdate.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );\n\t\treturn date;\n\t},\n\n\t/* Set the date(s) directly. */\n\t_setDate: function( inst, date, noChange ) {\n\t\tvar clear = !date,\n\t\t\torigMonth = inst.selectedMonth,\n\t\t\torigYear = inst.selectedYear,\n\t\t\tnewDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );\n\n\t\tinst.selectedDay = inst.currentDay = newDate.getDate();\n\t\tinst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();\n\t\tinst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();\n\t\tif ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {\n\t\t\tthis._notifyChange( inst );\n\t\t}\n\t\tthis._adjustInstDate( inst );\n\t\tif ( inst.input ) {\n\t\t\tinst.input.val( clear ? \"\" : this._formatDate( inst ) );\n\t\t}\n\t},\n\n\t/* Retrieve the date(s) directly. */\n\t_getDate: function( inst ) {\n\t\tvar startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === \"\" ) ? null :\n\t\t\tthis._daylightSavingAdjust( new Date(\n\t\t\tinst.currentYear, inst.currentMonth, inst.currentDay ) ) );\n\t\t\treturn startDate;\n\t},\n\n\t/* Attach the onxxx handlers.  These are declared statically so\n\t * they work with static code transformers like Caja.\n\t */\n\t_attachHandlers: function( inst ) {\n\t\tvar stepMonths = this._get( inst, \"stepMonths\" ),\n\t\t\tid = \"#\" + inst.id.replace( /\\\\\\\\/g, \"\\\\\" );\n\t\tinst.dpDiv.find( \"[data-handler]\" ).map( function() {\n\t\t\tvar handler = {\n\t\t\t\tprev: function() {\n\t\t\t\t\t$.datepicker._adjustDate( id, -stepMonths, \"M\" );\n\t\t\t\t},\n\t\t\t\tnext: function() {\n\t\t\t\t\t$.datepicker._adjustDate( id, +stepMonths, \"M\" );\n\t\t\t\t},\n\t\t\t\thide: function() {\n\t\t\t\t\t$.datepicker._hideDatepicker();\n\t\t\t\t},\n\t\t\t\ttoday: function() {\n\t\t\t\t\t$.datepicker._gotoToday( id );\n\t\t\t\t},\n\t\t\t\tselectDay: function() {\n\t\t\t\t\t$.datepicker._selectDay( id, +this.getAttribute( \"data-month\" ), +this.getAttribute( \"data-year\" ), this );\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\tselectMonth: function() {\n\t\t\t\t\t$.datepicker._selectMonthYear( id, this, \"M\" );\n\t\t\t\t\treturn false;\n\t\t\t\t},\n\t\t\t\tselectYear: function() {\n\t\t\t\t\t$.datepicker._selectMonthYear( id, this, \"Y\" );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t};\n\t\t\t$( this ).on( this.getAttribute( \"data-event\" ), handler[ this.getAttribute( \"data-handler\" ) ] );\n\t\t} );\n\t},\n\n\t/* Generate the HTML for the current state of the date picker. */\n\t_generateHTML: function( inst ) {\n\t\tvar maxDraw, prevText, prev, nextText, next, currentText, gotoDate,\n\t\t\tcontrols, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,\n\t\t\tmonthNames, monthNamesShort, beforeShowDay, showOtherMonths,\n\t\t\tselectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,\n\t\t\tcornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,\n\t\t\tprintDate, dRow, tbody, daySettings, otherMonth, unselectable,\n\t\t\ttempDate = new Date(),\n\t\t\ttoday = this._daylightSavingAdjust(\n\t\t\t\tnew Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time\n\t\t\tisRTL = this._get( inst, \"isRTL\" ),\n\t\t\tshowButtonPanel = this._get( inst, \"showButtonPanel\" ),\n\t\t\thideIfNoPrevNext = this._get( inst, \"hideIfNoPrevNext\" ),\n\t\t\tnavigationAsDateFormat = this._get( inst, \"navigationAsDateFormat\" ),\n\t\t\tnumMonths = this._getNumberOfMonths( inst ),\n\t\t\tshowCurrentAtPos = this._get( inst, \"showCurrentAtPos\" ),\n\t\t\tstepMonths = this._get( inst, \"stepMonths\" ),\n\t\t\tisMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),\n\t\t\tcurrentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :\n\t\t\t\tnew Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),\n\t\t\tminDate = this._getMinMaxDate( inst, \"min\" ),\n\t\t\tmaxDate = this._getMinMaxDate( inst, \"max\" ),\n\t\t\tdrawMonth = inst.drawMonth - showCurrentAtPos,\n\t\t\tdrawYear = inst.drawYear;\n\n\t\tif ( drawMonth < 0 ) {\n\t\t\tdrawMonth += 12;\n\t\t\tdrawYear--;\n\t\t}\n\t\tif ( maxDate ) {\n\t\t\tmaxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),\n\t\t\t\tmaxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );\n\t\t\tmaxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );\n\t\t\twhile ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {\n\t\t\t\tdrawMonth--;\n\t\t\t\tif ( drawMonth < 0 ) {\n\t\t\t\t\tdrawMonth = 11;\n\t\t\t\t\tdrawYear--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tinst.drawMonth = drawMonth;\n\t\tinst.drawYear = drawYear;\n\n\t\tprevText = this._get( inst, \"prevText\" );\n\t\tprevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,\n\t\t\tthis._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),\n\t\t\tthis._getFormatConfig( inst ) ) );\n\n\t\tprev = ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ?\n\t\t\t\"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'\" +\n\t\t\t\" title='\" + prevText + \"'><span class='ui-icon ui-icon-circle-triangle-\" + ( isRTL ? \"e\" : \"w\" ) + \"'>\" + prevText + \"</span></a>\" :\n\t\t\t( hideIfNoPrevNext ? \"\" : \"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='\" + prevText + \"'><span class='ui-icon ui-icon-circle-triangle-\" + ( isRTL ? \"e\" : \"w\" ) + \"'>\" + prevText + \"</span></a>\" ) );\n\n\t\tnextText = this._get( inst, \"nextText\" );\n\t\tnextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,\n\t\t\tthis._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),\n\t\t\tthis._getFormatConfig( inst ) ) );\n\n\t\tnext = ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ?\n\t\t\t\"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'\" +\n\t\t\t\" title='\" + nextText + \"'><span class='ui-icon ui-icon-circle-triangle-\" + ( isRTL ? \"w\" : \"e\" ) + \"'>\" + nextText + \"</span></a>\" :\n\t\t\t( hideIfNoPrevNext ? \"\" : \"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='\" + nextText + \"'><span class='ui-icon ui-icon-circle-triangle-\" + ( isRTL ? \"w\" : \"e\" ) + \"'>\" + nextText + \"</span></a>\" ) );\n\n\t\tcurrentText = this._get( inst, \"currentText\" );\n\t\tgotoDate = ( this._get( inst, \"gotoCurrent\" ) && inst.currentDay ? currentDate : today );\n\t\tcurrentText = ( !navigationAsDateFormat ? currentText :\n\t\t\tthis.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );\n\n\t\tcontrols = ( !inst.inline ? \"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>\" +\n\t\t\tthis._get( inst, \"closeText\" ) + \"</button>\" : \"\" );\n\n\t\tbuttonPanel = ( showButtonPanel ) ? \"<div class='ui-datepicker-buttonpane ui-widget-content'>\" + ( isRTL ? controls : \"\" ) +\n\t\t\t( this._isInRange( inst, gotoDate ) ? \"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'\" +\n\t\t\t\">\" + currentText + \"</button>\" : \"\" ) + ( isRTL ? \"\" : controls ) + \"</div>\" : \"\";\n\n\t\tfirstDay = parseInt( this._get( inst, \"firstDay\" ), 10 );\n\t\tfirstDay = ( isNaN( firstDay ) ? 0 : firstDay );\n\n\t\tshowWeek = this._get( inst, \"showWeek\" );\n\t\tdayNames = this._get( inst, \"dayNames\" );\n\t\tdayNamesMin = this._get( inst, \"dayNamesMin\" );\n\t\tmonthNames = this._get( inst, \"monthNames\" );\n\t\tmonthNamesShort = this._get( inst, \"monthNamesShort\" );\n\t\tbeforeShowDay = this._get( inst, \"beforeShowDay\" );\n\t\tshowOtherMonths = this._get( inst, \"showOtherMonths\" );\n\t\tselectOtherMonths = this._get( inst, \"selectOtherMonths\" );\n\t\tdefaultDate = this._getDefaultDate( inst );\n\t\thtml = \"\";\n\n\t\tfor ( row = 0; row < numMonths[ 0 ]; row++ ) {\n\t\t\tgroup = \"\";\n\t\t\tthis.maxRows = 4;\n\t\t\tfor ( col = 0; col < numMonths[ 1 ]; col++ ) {\n\t\t\t\tselectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );\n\t\t\t\tcornerClass = \" ui-corner-all\";\n\t\t\t\tcalender = \"\";\n\t\t\t\tif ( isMultiMonth ) {\n\t\t\t\t\tcalender += \"<div class='ui-datepicker-group\";\n\t\t\t\t\tif ( numMonths[ 1 ] > 1 ) {\n\t\t\t\t\t\tswitch ( col ) {\n\t\t\t\t\t\t\tcase 0: calender += \" ui-datepicker-group-first\";\n\t\t\t\t\t\t\t\tcornerClass = \" ui-corner-\" + ( isRTL ? \"right\" : \"left\" ); break;\n\t\t\t\t\t\t\tcase numMonths[ 1 ] - 1: calender += \" ui-datepicker-group-last\";\n\t\t\t\t\t\t\t\tcornerClass = \" ui-corner-\" + ( isRTL ? \"left\" : \"right\" ); break;\n\t\t\t\t\t\t\tdefault: calender += \" ui-datepicker-group-middle\"; cornerClass = \"\"; break;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcalender += \"'>\";\n\t\t\t\t}\n\t\t\t\tcalender += \"<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix\" + cornerClass + \"'>\" +\n\t\t\t\t\t( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : \"\" ) +\n\t\t\t\t\t( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : \"\" ) +\n\t\t\t\t\tthis._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,\n\t\t\t\t\trow > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers\n\t\t\t\t\t\"</div><table class='ui-datepicker-calendar'><thead>\" +\n\t\t\t\t\t\"<tr>\";\n\t\t\t\tthead = ( showWeek ? \"<th class='ui-datepicker-week-col'>\" + this._get( inst, \"weekHeader\" ) + \"</th>\" : \"\" );\n\t\t\t\tfor ( dow = 0; dow < 7; dow++ ) { // days of the week\n\t\t\t\t\tday = ( dow + firstDay ) % 7;\n\t\t\t\t\tthead += \"<th scope='col'\" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? \" class='ui-datepicker-week-end'\" : \"\" ) + \">\" +\n\t\t\t\t\t\t\"<span title='\" + dayNames[ day ] + \"'>\" + dayNamesMin[ day ] + \"</span></th>\";\n\t\t\t\t}\n\t\t\t\tcalender += thead + \"</tr></thead><tbody>\";\n\t\t\t\tdaysInMonth = this._getDaysInMonth( drawYear, drawMonth );\n\t\t\t\tif ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {\n\t\t\t\t\tinst.selectedDay = Math.min( inst.selectedDay, daysInMonth );\n\t\t\t\t}\n\t\t\t\tleadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;\n\t\t\t\tcurRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate\n\t\t\t\tnumRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)\n\t\t\t\tthis.maxRows = numRows;\n\t\t\t\tprintDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );\n\t\t\t\tfor ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows\n\t\t\t\t\tcalender += \"<tr>\";\n\t\t\t\t\ttbody = ( !showWeek ? \"\" : \"<td class='ui-datepicker-week-col'>\" +\n\t\t\t\t\t\tthis._get( inst, \"calculateWeek\" )( printDate ) + \"</td>\" );\n\t\t\t\t\tfor ( dow = 0; dow < 7; dow++ ) { // create date picker days\n\t\t\t\t\t\tdaySettings = ( beforeShowDay ?\n\t\t\t\t\t\t\tbeforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, \"\" ] );\n\t\t\t\t\t\totherMonth = ( printDate.getMonth() !== drawMonth );\n\t\t\t\t\t\tunselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||\n\t\t\t\t\t\t\t( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );\n\t\t\t\t\t\ttbody += \"<td class='\" +\n\t\t\t\t\t\t\t( ( dow + firstDay + 6 ) % 7 >= 5 ? \" ui-datepicker-week-end\" : \"\" ) + // highlight weekends\n\t\t\t\t\t\t\t( otherMonth ? \" ui-datepicker-other-month\" : \"\" ) + // highlight days from other months\n\t\t\t\t\t\t\t( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key\n\t\t\t\t\t\t\t( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?\n\n\t\t\t\t\t\t\t// or defaultDate is current printedDate and defaultDate is selectedDate\n\t\t\t\t\t\t\t\" \" + this._dayOverClass : \"\" ) + // highlight selected day\n\t\t\t\t\t\t\t( unselectable ? \" \" + this._unselectableClass + \" ui-state-disabled\" : \"\" ) +  // highlight unselectable days\n\t\t\t\t\t\t\t( otherMonth && !showOtherMonths ? \"\" : \" \" + daySettings[ 1 ] + // highlight custom dates\n\t\t\t\t\t\t\t( printDate.getTime() === currentDate.getTime() ? \" \" + this._currentClass : \"\" ) + // highlight selected day\n\t\t\t\t\t\t\t( printDate.getTime() === today.getTime() ? \" ui-datepicker-today\" : \"\" ) ) + \"'\" + // highlight today (if different)\n\t\t\t\t\t\t\t( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? \" title='\" + daySettings[ 2 ].replace( /'/g, \"&#39;\" ) + \"'\" : \"\" ) + // cell title\n\t\t\t\t\t\t\t( unselectable ? \"\" : \" data-handler='selectDay' data-event='click' data-month='\" + printDate.getMonth() + \"' data-year='\" + printDate.getFullYear() + \"'\" ) + \">\" + // actions\n\t\t\t\t\t\t\t( otherMonth && !showOtherMonths ? \"&#xa0;\" : // display for other months\n\t\t\t\t\t\t\t( unselectable ? \"<span class='ui-state-default'>\" + printDate.getDate() + \"</span>\" : \"<a class='ui-state-default\" +\n\t\t\t\t\t\t\t( printDate.getTime() === today.getTime() ? \" ui-state-highlight\" : \"\" ) +\n\t\t\t\t\t\t\t( printDate.getTime() === currentDate.getTime() ? \" ui-state-active\" : \"\" ) + // highlight selected day\n\t\t\t\t\t\t\t( otherMonth ? \" ui-priority-secondary\" : \"\" ) + // distinguish dates from other months\n\t\t\t\t\t\t\t\"' href='#'>\" + printDate.getDate() + \"</a>\" ) ) + \"</td>\"; // display selectable date\n\t\t\t\t\t\tprintDate.setDate( printDate.getDate() + 1 );\n\t\t\t\t\t\tprintDate = this._daylightSavingAdjust( printDate );\n\t\t\t\t\t}\n\t\t\t\t\tcalender += tbody + \"</tr>\";\n\t\t\t\t}\n\t\t\t\tdrawMonth++;\n\t\t\t\tif ( drawMonth > 11 ) {\n\t\t\t\t\tdrawMonth = 0;\n\t\t\t\t\tdrawYear++;\n\t\t\t\t}\n\t\t\t\tcalender += \"</tbody></table>\" + ( isMultiMonth ? \"</div>\" +\n\t\t\t\t\t\t\t( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? \"<div class='ui-datepicker-row-break'></div>\" : \"\" ) : \"\" );\n\t\t\t\tgroup += calender;\n\t\t\t}\n\t\t\thtml += group;\n\t\t}\n\t\thtml += buttonPanel;\n\t\tinst._keyEvent = false;\n\t\treturn html;\n\t},\n\n\t/* Generate the month and year header. */\n\t_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,\n\t\t\tsecondary, monthNames, monthNamesShort ) {\n\n\t\tvar inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,\n\t\t\tchangeMonth = this._get( inst, \"changeMonth\" ),\n\t\t\tchangeYear = this._get( inst, \"changeYear\" ),\n\t\t\tshowMonthAfterYear = this._get( inst, \"showMonthAfterYear\" ),\n\t\t\thtml = \"<div class='ui-datepicker-title'>\",\n\t\t\tmonthHtml = \"\";\n\n\t\t// Month selection\n\t\tif ( secondary || !changeMonth ) {\n\t\t\tmonthHtml += \"<span class='ui-datepicker-month'>\" + monthNames[ drawMonth ] + \"</span>\";\n\t\t} else {\n\t\t\tinMinYear = ( minDate && minDate.getFullYear() === drawYear );\n\t\t\tinMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );\n\t\t\tmonthHtml += \"<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>\";\n\t\t\tfor ( month = 0; month < 12; month++ ) {\n\t\t\t\tif ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {\n\t\t\t\t\tmonthHtml += \"<option value='\" + month + \"'\" +\n\t\t\t\t\t\t( month === drawMonth ? \" selected='selected'\" : \"\" ) +\n\t\t\t\t\t\t\">\" + monthNamesShort[ month ] + \"</option>\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tmonthHtml += \"</select>\";\n\t\t}\n\n\t\tif ( !showMonthAfterYear ) {\n\t\t\thtml += monthHtml + ( secondary || !( changeMonth && changeYear ) ? \"&#xa0;\" : \"\" );\n\t\t}\n\n\t\t// Year selection\n\t\tif ( !inst.yearshtml ) {\n\t\t\tinst.yearshtml = \"\";\n\t\t\tif ( secondary || !changeYear ) {\n\t\t\t\thtml += \"<span class='ui-datepicker-year'>\" + drawYear + \"</span>\";\n\t\t\t} else {\n\n\t\t\t\t// determine range of years to display\n\t\t\t\tyears = this._get( inst, \"yearRange\" ).split( \":\" );\n\t\t\t\tthisYear = new Date().getFullYear();\n\t\t\t\tdetermineYear = function( value ) {\n\t\t\t\t\tvar year = ( value.match( /c[+\\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :\n\t\t\t\t\t\t( value.match( /[+\\-].*/ ) ? thisYear + parseInt( value, 10 ) :\n\t\t\t\t\t\tparseInt( value, 10 ) ) );\n\t\t\t\t\treturn ( isNaN( year ) ? thisYear : year );\n\t\t\t\t};\n\t\t\t\tyear = determineYear( years[ 0 ] );\n\t\t\t\tendYear = Math.max( year, determineYear( years[ 1 ] || \"\" ) );\n\t\t\t\tyear = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );\n\t\t\t\tendYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );\n\t\t\t\tinst.yearshtml += \"<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>\";\n\t\t\t\tfor ( ; year <= endYear; year++ ) {\n\t\t\t\t\tinst.yearshtml += \"<option value='\" + year + \"'\" +\n\t\t\t\t\t\t( year === drawYear ? \" selected='selected'\" : \"\" ) +\n\t\t\t\t\t\t\">\" + year + \"</option>\";\n\t\t\t\t}\n\t\t\t\tinst.yearshtml += \"</select>\";\n\n\t\t\t\thtml += inst.yearshtml;\n\t\t\t\tinst.yearshtml = null;\n\t\t\t}\n\t\t}\n\n\t\thtml += this._get( inst, \"yearSuffix\" );\n\t\tif ( showMonthAfterYear ) {\n\t\t\thtml += ( secondary || !( changeMonth && changeYear ) ? \"&#xa0;\" : \"\" ) + monthHtml;\n\t\t}\n\t\thtml += \"</div>\"; // Close datepicker_header\n\t\treturn html;\n\t},\n\n\t/* Adjust one of the date sub-fields. */\n\t_adjustInstDate: function( inst, offset, period ) {\n\t\tvar year = inst.selectedYear + ( period === \"Y\" ? offset : 0 ),\n\t\t\tmonth = inst.selectedMonth + ( period === \"M\" ? offset : 0 ),\n\t\t\tday = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === \"D\" ? offset : 0 ),\n\t\t\tdate = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );\n\n\t\tinst.selectedDay = date.getDate();\n\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n\t\tif ( period === \"M\" || period === \"Y\" ) {\n\t\t\tthis._notifyChange( inst );\n\t\t}\n\t},\n\n\t/* Ensure a date is within any min/max bounds. */\n\t_restrictMinMax: function( inst, date ) {\n\t\tvar minDate = this._getMinMaxDate( inst, \"min\" ),\n\t\t\tmaxDate = this._getMinMaxDate( inst, \"max\" ),\n\t\t\tnewDate = ( minDate && date < minDate ? minDate : date );\n\t\treturn ( maxDate && newDate > maxDate ? maxDate : newDate );\n\t},\n\n\t/* Notify change of month/year. */\n\t_notifyChange: function( inst ) {\n\t\tvar onChange = this._get( inst, \"onChangeMonthYear\" );\n\t\tif ( onChange ) {\n\t\t\tonChange.apply( ( inst.input ? inst.input[ 0 ] : null ),\n\t\t\t\t[ inst.selectedYear, inst.selectedMonth + 1, inst ] );\n\t\t}\n\t},\n\n\t/* Determine the number of months to show. */\n\t_getNumberOfMonths: function( inst ) {\n\t\tvar numMonths = this._get( inst, \"numberOfMonths\" );\n\t\treturn ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === \"number\" ? [ 1, numMonths ] : numMonths ) );\n\t},\n\n\t/* Determine the current maximum date - ensure no time components are set. */\n\t_getMinMaxDate: function( inst, minMax ) {\n\t\treturn this._determineDate( inst, this._get( inst, minMax + \"Date\" ), null );\n\t},\n\n\t/* Find the number of days in a given month. */\n\t_getDaysInMonth: function( year, month ) {\n\t\treturn 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();\n\t},\n\n\t/* Find the day of the week of the first of a month. */\n\t_getFirstDayOfMonth: function( year, month ) {\n\t\treturn new Date( year, month, 1 ).getDay();\n\t},\n\n\t/* Determines if we should allow a \"next/prev\" month display change. */\n\t_canAdjustMonth: function( inst, offset, curYear, curMonth ) {\n\t\tvar numMonths = this._getNumberOfMonths( inst ),\n\t\t\tdate = this._daylightSavingAdjust( new Date( curYear,\n\t\t\tcurMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );\n\n\t\tif ( offset < 0 ) {\n\t\t\tdate.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );\n\t\t}\n\t\treturn this._isInRange( inst, date );\n\t},\n\n\t/* Is the given date in the accepted range? */\n\t_isInRange: function( inst, date ) {\n\t\tvar yearSplit, currentYear,\n\t\t\tminDate = this._getMinMaxDate( inst, \"min\" ),\n\t\t\tmaxDate = this._getMinMaxDate( inst, \"max\" ),\n\t\t\tminYear = null,\n\t\t\tmaxYear = null,\n\t\t\tyears = this._get( inst, \"yearRange\" );\n\t\t\tif ( years ) {\n\t\t\t\tyearSplit = years.split( \":\" );\n\t\t\t\tcurrentYear = new Date().getFullYear();\n\t\t\t\tminYear = parseInt( yearSplit[ 0 ], 10 );\n\t\t\t\tmaxYear = parseInt( yearSplit[ 1 ], 10 );\n\t\t\t\tif ( yearSplit[ 0 ].match( /[+\\-].*/ ) ) {\n\t\t\t\t\tminYear += currentYear;\n\t\t\t\t}\n\t\t\t\tif ( yearSplit[ 1 ].match( /[+\\-].*/ ) ) {\n\t\t\t\t\tmaxYear += currentYear;\n\t\t\t\t}\n\t\t\t}\n\n\t\treturn ( ( !minDate || date.getTime() >= minDate.getTime() ) &&\n\t\t\t( !maxDate || date.getTime() <= maxDate.getTime() ) &&\n\t\t\t( !minYear || date.getFullYear() >= minYear ) &&\n\t\t\t( !maxYear || date.getFullYear() <= maxYear ) );\n\t},\n\n\t/* Provide the configuration settings for formatting/parsing. */\n\t_getFormatConfig: function( inst ) {\n\t\tvar shortYearCutoff = this._get( inst, \"shortYearCutoff\" );\n\t\tshortYearCutoff = ( typeof shortYearCutoff !== \"string\" ? shortYearCutoff :\n\t\t\tnew Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );\n\t\treturn { shortYearCutoff: shortYearCutoff,\n\t\t\tdayNamesShort: this._get( inst, \"dayNamesShort\" ), dayNames: this._get( inst, \"dayNames\" ),\n\t\t\tmonthNamesShort: this._get( inst, \"monthNamesShort\" ), monthNames: this._get( inst, \"monthNames\" ) };\n\t},\n\n\t/* Format the given date for display. */\n\t_formatDate: function( inst, day, month, year ) {\n\t\tif ( !day ) {\n\t\t\tinst.currentDay = inst.selectedDay;\n\t\t\tinst.currentMonth = inst.selectedMonth;\n\t\t\tinst.currentYear = inst.selectedYear;\n\t\t}\n\t\tvar date = ( day ? ( typeof day === \"object\" ? day :\n\t\t\tthis._daylightSavingAdjust( new Date( year, month, day ) ) ) :\n\t\t\tthis._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );\n\t\treturn this.formatDate( this._get( inst, \"dateFormat\" ), date, this._getFormatConfig( inst ) );\n\t}\n} );\n\n/*\n * Bind hover events for datepicker elements.\n * Done via delegate so the binding only occurs once in the lifetime of the parent div.\n * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.\n */\nfunction datepicker_bindHover( dpDiv ) {\n\tvar selector = \"button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a\";\n\treturn dpDiv.on( \"mouseout\", selector, function() {\n\t\t\t$( this ).removeClass( \"ui-state-hover\" );\n\t\t\tif ( this.className.indexOf( \"ui-datepicker-prev\" ) !== -1 ) {\n\t\t\t\t$( this ).removeClass( \"ui-datepicker-prev-hover\" );\n\t\t\t}\n\t\t\tif ( this.className.indexOf( \"ui-datepicker-next\" ) !== -1 ) {\n\t\t\t\t$( this ).removeClass( \"ui-datepicker-next-hover\" );\n\t\t\t}\n\t\t} )\n\t\t.on( \"mouseover\", selector, datepicker_handleMouseover );\n}\n\nfunction datepicker_handleMouseover() {\n\tif ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {\n\t\t$( this ).parents( \".ui-datepicker-calendar\" ).find( \"a\" ).removeClass( \"ui-state-hover\" );\n\t\t$( this ).addClass( \"ui-state-hover\" );\n\t\tif ( this.className.indexOf( \"ui-datepicker-prev\" ) !== -1 ) {\n\t\t\t$( this ).addClass( \"ui-datepicker-prev-hover\" );\n\t\t}\n\t\tif ( this.className.indexOf( \"ui-datepicker-next\" ) !== -1 ) {\n\t\t\t$( this ).addClass( \"ui-datepicker-next-hover\" );\n\t\t}\n\t}\n}\n\n/* jQuery extend now ignores nulls! */\nfunction datepicker_extendRemove( target, props ) {\n\t$.extend( target, props );\n\tfor ( var name in props ) {\n\t\tif ( props[ name ] == null ) {\n\t\t\ttarget[ name ] = props[ name ];\n\t\t}\n\t}\n\treturn target;\n}\n\n/* Invoke the datepicker functionality.\n   @param  options  string - a command, optionally followed by additional parameters or\n\t\t\t\t\tObject - settings for attaching new datepicker functionality\n   @return  jQuery object */\n$.fn.datepicker = function( options ) {\n\n\t/* Verify an empty collection wasn't passed - Fixes #6976 */\n\tif ( !this.length ) {\n\t\treturn this;\n\t}\n\n\t/* Initialise the date picker. */\n\tif ( !$.datepicker.initialized ) {\n\t\t$( document ).on( \"mousedown\", $.datepicker._checkExternalClick );\n\t\t$.datepicker.initialized = true;\n\t}\n\n\t/* Append datepicker main container to body if not exist. */\n\tif ( $( \"#\" + $.datepicker._mainDivId ).length === 0 ) {\n\t\t$( \"body\" ).append( $.datepicker.dpDiv );\n\t}\n\n\tvar otherArgs = Array.prototype.slice.call( arguments, 1 );\n\tif ( typeof options === \"string\" && ( options === \"isDisabled\" || options === \"getDate\" || options === \"widget\" ) ) {\n\t\treturn $.datepicker[ \"_\" + options + \"Datepicker\" ].\n\t\t\tapply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );\n\t}\n\tif ( options === \"option\" && arguments.length === 2 && typeof arguments[ 1 ] === \"string\" ) {\n\t\treturn $.datepicker[ \"_\" + options + \"Datepicker\" ].\n\t\t\tapply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );\n\t}\n\treturn this.each( function() {\n\t\ttypeof options === \"string\" ?\n\t\t\t$.datepicker[ \"_\" + options + \"Datepicker\" ].\n\t\t\t\tapply( $.datepicker, [ this ].concat( otherArgs ) ) :\n\t\t\t$.datepicker._attachDatepicker( this, options );\n\t} );\n};\n\n$.datepicker = new Datepicker(); // singleton instance\n$.datepicker.initialized = false;\n$.datepicker.uuid = new Date().getTime();\n$.datepicker.version = \"1.12.1\";\n\nvar widgetsDatepicker = $.datepicker;\n\n\n/*!\n * jQuery UI Dialog 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Dialog\n//>>group: Widgets\n//>>description: Displays customizable dialog windows.\n//>>docs: http://api.jqueryui.com/dialog/\n//>>demos: http://jqueryui.com/dialog/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/dialog.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.dialog\", {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tappendTo: \"body\",\n\t\tautoOpen: true,\n\t\tbuttons: [],\n\t\tclasses: {\n\t\t\t\"ui-dialog\": \"ui-corner-all\",\n\t\t\t\"ui-dialog-titlebar\": \"ui-corner-all\"\n\t\t},\n\t\tcloseOnEscape: true,\n\t\tcloseText: \"Close\",\n\t\tdraggable: true,\n\t\thide: null,\n\t\theight: \"auto\",\n\t\tmaxHeight: null,\n\t\tmaxWidth: null,\n\t\tminHeight: 150,\n\t\tminWidth: 150,\n\t\tmodal: false,\n\t\tposition: {\n\t\t\tmy: \"center\",\n\t\t\tat: \"center\",\n\t\t\tof: window,\n\t\t\tcollision: \"fit\",\n\n\t\t\t// Ensure the titlebar is always visible\n\t\t\tusing: function( pos ) {\n\t\t\t\tvar topOffset = $( this ).css( pos ).offset().top;\n\t\t\t\tif ( topOffset < 0 ) {\n\t\t\t\t\t$( this ).css( \"top\", pos.top - topOffset );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tresizable: true,\n\t\tshow: null,\n\t\ttitle: null,\n\t\twidth: 300,\n\n\t\t// Callbacks\n\t\tbeforeClose: null,\n\t\tclose: null,\n\t\tdrag: null,\n\t\tdragStart: null,\n\t\tdragStop: null,\n\t\tfocus: null,\n\t\topen: null,\n\t\tresize: null,\n\t\tresizeStart: null,\n\t\tresizeStop: null\n\t},\n\n\tsizeRelatedOptions: {\n\t\tbuttons: true,\n\t\theight: true,\n\t\tmaxHeight: true,\n\t\tmaxWidth: true,\n\t\tminHeight: true,\n\t\tminWidth: true,\n\t\twidth: true\n\t},\n\n\tresizableRelatedOptions: {\n\t\tmaxHeight: true,\n\t\tmaxWidth: true,\n\t\tminHeight: true,\n\t\tminWidth: true\n\t},\n\n\t_create: function() {\n\t\tthis.originalCss = {\n\t\t\tdisplay: this.element[ 0 ].style.display,\n\t\t\twidth: this.element[ 0 ].style.width,\n\t\t\tminHeight: this.element[ 0 ].style.minHeight,\n\t\t\tmaxHeight: this.element[ 0 ].style.maxHeight,\n\t\t\theight: this.element[ 0 ].style.height\n\t\t};\n\t\tthis.originalPosition = {\n\t\t\tparent: this.element.parent(),\n\t\t\tindex: this.element.parent().children().index( this.element )\n\t\t};\n\t\tthis.originalTitle = this.element.attr( \"title\" );\n\t\tif ( this.options.title == null && this.originalTitle != null ) {\n\t\t\tthis.options.title = this.originalTitle;\n\t\t}\n\n\t\t// Dialogs can't be disabled\n\t\tif ( this.options.disabled ) {\n\t\t\tthis.options.disabled = false;\n\t\t}\n\n\t\tthis._createWrapper();\n\n\t\tthis.element\n\t\t\t.show()\n\t\t\t.removeAttr( \"title\" )\n\t\t\t.appendTo( this.uiDialog );\n\n\t\tthis._addClass( \"ui-dialog-content\", \"ui-widget-content\" );\n\n\t\tthis._createTitlebar();\n\t\tthis._createButtonPane();\n\n\t\tif ( this.options.draggable && $.fn.draggable ) {\n\t\t\tthis._makeDraggable();\n\t\t}\n\t\tif ( this.options.resizable && $.fn.resizable ) {\n\t\t\tthis._makeResizable();\n\t\t}\n\n\t\tthis._isOpen = false;\n\n\t\tthis._trackFocus();\n\t},\n\n\t_init: function() {\n\t\tif ( this.options.autoOpen ) {\n\t\t\tthis.open();\n\t\t}\n\t},\n\n\t_appendTo: function() {\n\t\tvar element = this.options.appendTo;\n\t\tif ( element && ( element.jquery || element.nodeType ) ) {\n\t\t\treturn $( element );\n\t\t}\n\t\treturn this.document.find( element || \"body\" ).eq( 0 );\n\t},\n\n\t_destroy: function() {\n\t\tvar next,\n\t\t\toriginalPosition = this.originalPosition;\n\n\t\tthis._untrackInstance();\n\t\tthis._destroyOverlay();\n\n\t\tthis.element\n\t\t\t.removeUniqueId()\n\t\t\t.css( this.originalCss )\n\n\t\t\t// Without detaching first, the following becomes really slow\n\t\t\t.detach();\n\n\t\tthis.uiDialog.remove();\n\n\t\tif ( this.originalTitle ) {\n\t\t\tthis.element.attr( \"title\", this.originalTitle );\n\t\t}\n\n\t\tnext = originalPosition.parent.children().eq( originalPosition.index );\n\n\t\t// Don't try to place the dialog next to itself (#8613)\n\t\tif ( next.length && next[ 0 ] !== this.element[ 0 ] ) {\n\t\t\tnext.before( this.element );\n\t\t} else {\n\t\t\toriginalPosition.parent.append( this.element );\n\t\t}\n\t},\n\n\twidget: function() {\n\t\treturn this.uiDialog;\n\t},\n\n\tdisable: $.noop,\n\tenable: $.noop,\n\n\tclose: function( event ) {\n\t\tvar that = this;\n\n\t\tif ( !this._isOpen || this._trigger( \"beforeClose\", event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._isOpen = false;\n\t\tthis._focusedElement = null;\n\t\tthis._destroyOverlay();\n\t\tthis._untrackInstance();\n\n\t\tif ( !this.opener.filter( \":focusable\" ).trigger( \"focus\" ).length ) {\n\n\t\t\t// Hiding a focused element doesn't trigger blur in WebKit\n\t\t\t// so in case we have nothing to focus on, explicitly blur the active element\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=47182\n\t\t\t$.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) );\n\t\t}\n\n\t\tthis._hide( this.uiDialog, this.options.hide, function() {\n\t\t\tthat._trigger( \"close\", event );\n\t\t} );\n\t},\n\n\tisOpen: function() {\n\t\treturn this._isOpen;\n\t},\n\n\tmoveToTop: function() {\n\t\tthis._moveToTop();\n\t},\n\n\t_moveToTop: function( event, silent ) {\n\t\tvar moved = false,\n\t\t\tzIndices = this.uiDialog.siblings( \".ui-front:visible\" ).map( function() {\n\t\t\t\treturn +$( this ).css( \"z-index\" );\n\t\t\t} ).get(),\n\t\t\tzIndexMax = Math.max.apply( null, zIndices );\n\n\t\tif ( zIndexMax >= +this.uiDialog.css( \"z-index\" ) ) {\n\t\t\tthis.uiDialog.css( \"z-index\", zIndexMax + 1 );\n\t\t\tmoved = true;\n\t\t}\n\n\t\tif ( moved && !silent ) {\n\t\t\tthis._trigger( \"focus\", event );\n\t\t}\n\t\treturn moved;\n\t},\n\n\topen: function() {\n\t\tvar that = this;\n\t\tif ( this._isOpen ) {\n\t\t\tif ( this._moveToTop() ) {\n\t\t\t\tthis._focusTabbable();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis._isOpen = true;\n\t\tthis.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) );\n\n\t\tthis._size();\n\t\tthis._position();\n\t\tthis._createOverlay();\n\t\tthis._moveToTop( null, true );\n\n\t\t// Ensure the overlay is moved to the top with the dialog, but only when\n\t\t// opening. The overlay shouldn't move after the dialog is open so that\n\t\t// modeless dialogs opened after the modal dialog stack properly.\n\t\tif ( this.overlay ) {\n\t\t\tthis.overlay.css( \"z-index\", this.uiDialog.css( \"z-index\" ) - 1 );\n\t\t}\n\n\t\tthis._show( this.uiDialog, this.options.show, function() {\n\t\t\tthat._focusTabbable();\n\t\t\tthat._trigger( \"focus\" );\n\t\t} );\n\n\t\t// Track the dialog immediately upon openening in case a focus event\n\t\t// somehow occurs outside of the dialog before an element inside the\n\t\t// dialog is focused (#10152)\n\t\tthis._makeFocusTarget();\n\n\t\tthis._trigger( \"open\" );\n\t},\n\n\t_focusTabbable: function() {\n\n\t\t// Set focus to the first match:\n\t\t// 1. An element that was focused previously\n\t\t// 2. First element inside the dialog matching [autofocus]\n\t\t// 3. Tabbable element inside the content element\n\t\t// 4. Tabbable element inside the buttonpane\n\t\t// 5. The close button\n\t\t// 6. The dialog itself\n\t\tvar hasFocus = this._focusedElement;\n\t\tif ( !hasFocus ) {\n\t\t\thasFocus = this.element.find( \"[autofocus]\" );\n\t\t}\n\t\tif ( !hasFocus.length ) {\n\t\t\thasFocus = this.element.find( \":tabbable\" );\n\t\t}\n\t\tif ( !hasFocus.length ) {\n\t\t\thasFocus = this.uiDialogButtonPane.find( \":tabbable\" );\n\t\t}\n\t\tif ( !hasFocus.length ) {\n\t\t\thasFocus = this.uiDialogTitlebarClose.filter( \":tabbable\" );\n\t\t}\n\t\tif ( !hasFocus.length ) {\n\t\t\thasFocus = this.uiDialog;\n\t\t}\n\t\thasFocus.eq( 0 ).trigger( \"focus\" );\n\t},\n\n\t_keepFocus: function( event ) {\n\t\tfunction checkFocus() {\n\t\t\tvar activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),\n\t\t\t\tisActive = this.uiDialog[ 0 ] === activeElement ||\n\t\t\t\t\t$.contains( this.uiDialog[ 0 ], activeElement );\n\t\t\tif ( !isActive ) {\n\t\t\t\tthis._focusTabbable();\n\t\t\t}\n\t\t}\n\t\tevent.preventDefault();\n\t\tcheckFocus.call( this );\n\n\t\t// support: IE\n\t\t// IE <= 8 doesn't prevent moving focus even with event.preventDefault()\n\t\t// so we check again later\n\t\tthis._delay( checkFocus );\n\t},\n\n\t_createWrapper: function() {\n\t\tthis.uiDialog = $( \"<div>\" )\n\t\t\t.hide()\n\t\t\t.attr( {\n\n\t\t\t\t// Setting tabIndex makes the div focusable\n\t\t\t\ttabIndex: -1,\n\t\t\t\trole: \"dialog\"\n\t\t\t} )\n\t\t\t.appendTo( this._appendTo() );\n\n\t\tthis._addClass( this.uiDialog, \"ui-dialog\", \"ui-widget ui-widget-content ui-front\" );\n\t\tthis._on( this.uiDialog, {\n\t\t\tkeydown: function( event ) {\n\t\t\t\tif ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&\n\t\t\t\t\t\tevent.keyCode === $.ui.keyCode.ESCAPE ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tthis.close( event );\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Prevent tabbing out of dialogs\n\t\t\t\tif ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tvar tabbables = this.uiDialog.find( \":tabbable\" ),\n\t\t\t\t\tfirst = tabbables.filter( \":first\" ),\n\t\t\t\t\tlast = tabbables.filter( \":last\" );\n\n\t\t\t\tif ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&\n\t\t\t\t\t\t!event.shiftKey ) {\n\t\t\t\t\tthis._delay( function() {\n\t\t\t\t\t\tfirst.trigger( \"focus\" );\n\t\t\t\t\t} );\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t} else if ( ( event.target === first[ 0 ] ||\n\t\t\t\t\t\tevent.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {\n\t\t\t\t\tthis._delay( function() {\n\t\t\t\t\t\tlast.trigger( \"focus\" );\n\t\t\t\t\t} );\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t},\n\t\t\tmousedown: function( event ) {\n\t\t\t\tif ( this._moveToTop( event ) ) {\n\t\t\t\t\tthis._focusTabbable();\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\t// We assume that any existing aria-describedby attribute means\n\t\t// that the dialog content is marked up properly\n\t\t// otherwise we brute force the content as the description\n\t\tif ( !this.element.find( \"[aria-describedby]\" ).length ) {\n\t\t\tthis.uiDialog.attr( {\n\t\t\t\t\"aria-describedby\": this.element.uniqueId().attr( \"id\" )\n\t\t\t} );\n\t\t}\n\t},\n\n\t_createTitlebar: function() {\n\t\tvar uiDialogTitle;\n\n\t\tthis.uiDialogTitlebar = $( \"<div>\" );\n\t\tthis._addClass( this.uiDialogTitlebar,\n\t\t\t\"ui-dialog-titlebar\", \"ui-widget-header ui-helper-clearfix\" );\n\t\tthis._on( this.uiDialogTitlebar, {\n\t\t\tmousedown: function( event ) {\n\n\t\t\t\t// Don't prevent click on close button (#8838)\n\t\t\t\t// Focusing a dialog that is partially scrolled out of view\n\t\t\t\t// causes the browser to scroll it into view, preventing the click event\n\t\t\t\tif ( !$( event.target ).closest( \".ui-dialog-titlebar-close\" ) ) {\n\n\t\t\t\t\t// Dialog isn't getting focus when dragging (#8063)\n\t\t\t\t\tthis.uiDialog.trigger( \"focus\" );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\t// Support: IE\n\t\t// Use type=\"button\" to prevent enter keypresses in textboxes from closing the\n\t\t// dialog in IE (#9312)\n\t\tthis.uiDialogTitlebarClose = $( \"<button type='button'></button>\" )\n\t\t\t.button( {\n\t\t\t\tlabel: $( \"<a>\" ).text( this.options.closeText ).html(),\n\t\t\t\ticon: \"ui-icon-closethick\",\n\t\t\t\tshowLabel: false\n\t\t\t} )\n\t\t\t.appendTo( this.uiDialogTitlebar );\n\n\t\tthis._addClass( this.uiDialogTitlebarClose, \"ui-dialog-titlebar-close\" );\n\t\tthis._on( this.uiDialogTitlebarClose, {\n\t\t\tclick: function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tthis.close( event );\n\t\t\t}\n\t\t} );\n\n\t\tuiDialogTitle = $( \"<span>\" ).uniqueId().prependTo( this.uiDialogTitlebar );\n\t\tthis._addClass( uiDialogTitle, \"ui-dialog-title\" );\n\t\tthis._title( uiDialogTitle );\n\n\t\tthis.uiDialogTitlebar.prependTo( this.uiDialog );\n\n\t\tthis.uiDialog.attr( {\n\t\t\t\"aria-labelledby\": uiDialogTitle.attr( \"id\" )\n\t\t} );\n\t},\n\n\t_title: function( title ) {\n\t\tif ( this.options.title ) {\n\t\t\ttitle.text( this.options.title );\n\t\t} else {\n\t\t\ttitle.html( \"&#160;\" );\n\t\t}\n\t},\n\n\t_createButtonPane: function() {\n\t\tthis.uiDialogButtonPane = $( \"<div>\" );\n\t\tthis._addClass( this.uiDialogButtonPane, \"ui-dialog-buttonpane\",\n\t\t\t\"ui-widget-content ui-helper-clearfix\" );\n\n\t\tthis.uiButtonSet = $( \"<div>\" )\n\t\t\t.appendTo( this.uiDialogButtonPane );\n\t\tthis._addClass( this.uiButtonSet, \"ui-dialog-buttonset\" );\n\n\t\tthis._createButtons();\n\t},\n\n\t_createButtons: function() {\n\t\tvar that = this,\n\t\t\tbuttons = this.options.buttons;\n\n\t\t// If we already have a button pane, remove it\n\t\tthis.uiDialogButtonPane.remove();\n\t\tthis.uiButtonSet.empty();\n\n\t\tif ( $.isEmptyObject( buttons ) || ( $.isArray( buttons ) && !buttons.length ) ) {\n\t\t\tthis._removeClass( this.uiDialog, \"ui-dialog-buttons\" );\n\t\t\treturn;\n\t\t}\n\n\t\t$.each( buttons, function( name, props ) {\n\t\t\tvar click, buttonOptions;\n\t\t\tprops = $.isFunction( props ) ?\n\t\t\t\t{ click: props, text: name } :\n\t\t\t\tprops;\n\n\t\t\t// Default to a non-submitting button\n\t\t\tprops = $.extend( { type: \"button\" }, props );\n\n\t\t\t// Change the context for the click callback to be the main element\n\t\t\tclick = props.click;\n\t\t\tbuttonOptions = {\n\t\t\t\ticon: props.icon,\n\t\t\t\ticonPosition: props.iconPosition,\n\t\t\t\tshowLabel: props.showLabel,\n\n\t\t\t\t// Deprecated options\n\t\t\t\ticons: props.icons,\n\t\t\t\ttext: props.text\n\t\t\t};\n\n\t\t\tdelete props.click;\n\t\t\tdelete props.icon;\n\t\t\tdelete props.iconPosition;\n\t\t\tdelete props.showLabel;\n\n\t\t\t// Deprecated options\n\t\t\tdelete props.icons;\n\t\t\tif ( typeof props.text === \"boolean\" ) {\n\t\t\t\tdelete props.text;\n\t\t\t}\n\n\t\t\t$( \"<button></button>\", props )\n\t\t\t\t.button( buttonOptions )\n\t\t\t\t.appendTo( that.uiButtonSet )\n\t\t\t\t.on( \"click\", function() {\n\t\t\t\t\tclick.apply( that.element[ 0 ], arguments );\n\t\t\t\t} );\n\t\t} );\n\t\tthis._addClass( this.uiDialog, \"ui-dialog-buttons\" );\n\t\tthis.uiDialogButtonPane.appendTo( this.uiDialog );\n\t},\n\n\t_makeDraggable: function() {\n\t\tvar that = this,\n\t\t\toptions = this.options;\n\n\t\tfunction filteredUi( ui ) {\n\t\t\treturn {\n\t\t\t\tposition: ui.position,\n\t\t\t\toffset: ui.offset\n\t\t\t};\n\t\t}\n\n\t\tthis.uiDialog.draggable( {\n\t\t\tcancel: \".ui-dialog-content, .ui-dialog-titlebar-close\",\n\t\t\thandle: \".ui-dialog-titlebar\",\n\t\t\tcontainment: \"document\",\n\t\t\tstart: function( event, ui ) {\n\t\t\t\tthat._addClass( $( this ), \"ui-dialog-dragging\" );\n\t\t\t\tthat._blockFrames();\n\t\t\t\tthat._trigger( \"dragStart\", event, filteredUi( ui ) );\n\t\t\t},\n\t\t\tdrag: function( event, ui ) {\n\t\t\t\tthat._trigger( \"drag\", event, filteredUi( ui ) );\n\t\t\t},\n\t\t\tstop: function( event, ui ) {\n\t\t\t\tvar left = ui.offset.left - that.document.scrollLeft(),\n\t\t\t\t\ttop = ui.offset.top - that.document.scrollTop();\n\n\t\t\t\toptions.position = {\n\t\t\t\t\tmy: \"left top\",\n\t\t\t\t\tat: \"left\" + ( left >= 0 ? \"+\" : \"\" ) + left + \" \" +\n\t\t\t\t\t\t\"top\" + ( top >= 0 ? \"+\" : \"\" ) + top,\n\t\t\t\t\tof: that.window\n\t\t\t\t};\n\t\t\t\tthat._removeClass( $( this ), \"ui-dialog-dragging\" );\n\t\t\t\tthat._unblockFrames();\n\t\t\t\tthat._trigger( \"dragStop\", event, filteredUi( ui ) );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_makeResizable: function() {\n\t\tvar that = this,\n\t\t\toptions = this.options,\n\t\t\thandles = options.resizable,\n\n\t\t\t// .ui-resizable has position: relative defined in the stylesheet\n\t\t\t// but dialogs have to use absolute or fixed positioning\n\t\t\tposition = this.uiDialog.css( \"position\" ),\n\t\t\tresizeHandles = typeof handles === \"string\" ?\n\t\t\t\thandles :\n\t\t\t\t\"n,e,s,w,se,sw,ne,nw\";\n\n\t\tfunction filteredUi( ui ) {\n\t\t\treturn {\n\t\t\t\toriginalPosition: ui.originalPosition,\n\t\t\t\toriginalSize: ui.originalSize,\n\t\t\t\tposition: ui.position,\n\t\t\t\tsize: ui.size\n\t\t\t};\n\t\t}\n\n\t\tthis.uiDialog.resizable( {\n\t\t\tcancel: \".ui-dialog-content\",\n\t\t\tcontainment: \"document\",\n\t\t\talsoResize: this.element,\n\t\t\tmaxWidth: options.maxWidth,\n\t\t\tmaxHeight: options.maxHeight,\n\t\t\tminWidth: options.minWidth,\n\t\t\tminHeight: this._minHeight(),\n\t\t\thandles: resizeHandles,\n\t\t\tstart: function( event, ui ) {\n\t\t\t\tthat._addClass( $( this ), \"ui-dialog-resizing\" );\n\t\t\t\tthat._blockFrames();\n\t\t\t\tthat._trigger( \"resizeStart\", event, filteredUi( ui ) );\n\t\t\t},\n\t\t\tresize: function( event, ui ) {\n\t\t\t\tthat._trigger( \"resize\", event, filteredUi( ui ) );\n\t\t\t},\n\t\t\tstop: function( event, ui ) {\n\t\t\t\tvar offset = that.uiDialog.offset(),\n\t\t\t\t\tleft = offset.left - that.document.scrollLeft(),\n\t\t\t\t\ttop = offset.top - that.document.scrollTop();\n\n\t\t\t\toptions.height = that.uiDialog.height();\n\t\t\t\toptions.width = that.uiDialog.width();\n\t\t\t\toptions.position = {\n\t\t\t\t\tmy: \"left top\",\n\t\t\t\t\tat: \"left\" + ( left >= 0 ? \"+\" : \"\" ) + left + \" \" +\n\t\t\t\t\t\t\"top\" + ( top >= 0 ? \"+\" : \"\" ) + top,\n\t\t\t\t\tof: that.window\n\t\t\t\t};\n\t\t\t\tthat._removeClass( $( this ), \"ui-dialog-resizing\" );\n\t\t\t\tthat._unblockFrames();\n\t\t\t\tthat._trigger( \"resizeStop\", event, filteredUi( ui ) );\n\t\t\t}\n\t\t} )\n\t\t\t.css( \"position\", position );\n\t},\n\n\t_trackFocus: function() {\n\t\tthis._on( this.widget(), {\n\t\t\tfocusin: function( event ) {\n\t\t\t\tthis._makeFocusTarget();\n\t\t\t\tthis._focusedElement = $( event.target );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_makeFocusTarget: function() {\n\t\tthis._untrackInstance();\n\t\tthis._trackingInstances().unshift( this );\n\t},\n\n\t_untrackInstance: function() {\n\t\tvar instances = this._trackingInstances(),\n\t\t\texists = $.inArray( this, instances );\n\t\tif ( exists !== -1 ) {\n\t\t\tinstances.splice( exists, 1 );\n\t\t}\n\t},\n\n\t_trackingInstances: function() {\n\t\tvar instances = this.document.data( \"ui-dialog-instances\" );\n\t\tif ( !instances ) {\n\t\t\tinstances = [];\n\t\t\tthis.document.data( \"ui-dialog-instances\", instances );\n\t\t}\n\t\treturn instances;\n\t},\n\n\t_minHeight: function() {\n\t\tvar options = this.options;\n\n\t\treturn options.height === \"auto\" ?\n\t\t\toptions.minHeight :\n\t\t\tMath.min( options.minHeight, options.height );\n\t},\n\n\t_position: function() {\n\n\t\t// Need to show the dialog to get the actual offset in the position plugin\n\t\tvar isVisible = this.uiDialog.is( \":visible\" );\n\t\tif ( !isVisible ) {\n\t\t\tthis.uiDialog.show();\n\t\t}\n\t\tthis.uiDialog.position( this.options.position );\n\t\tif ( !isVisible ) {\n\t\t\tthis.uiDialog.hide();\n\t\t}\n\t},\n\n\t_setOptions: function( options ) {\n\t\tvar that = this,\n\t\t\tresize = false,\n\t\t\tresizableOptions = {};\n\n\t\t$.each( options, function( key, value ) {\n\t\t\tthat._setOption( key, value );\n\n\t\t\tif ( key in that.sizeRelatedOptions ) {\n\t\t\t\tresize = true;\n\t\t\t}\n\t\t\tif ( key in that.resizableRelatedOptions ) {\n\t\t\t\tresizableOptions[ key ] = value;\n\t\t\t}\n\t\t} );\n\n\t\tif ( resize ) {\n\t\t\tthis._size();\n\t\t\tthis._position();\n\t\t}\n\t\tif ( this.uiDialog.is( \":data(ui-resizable)\" ) ) {\n\t\t\tthis.uiDialog.resizable( \"option\", resizableOptions );\n\t\t}\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tvar isDraggable, isResizable,\n\t\t\tuiDialog = this.uiDialog;\n\n\t\tif ( key === \"disabled\" ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"appendTo\" ) {\n\t\t\tthis.uiDialog.appendTo( this._appendTo() );\n\t\t}\n\n\t\tif ( key === \"buttons\" ) {\n\t\t\tthis._createButtons();\n\t\t}\n\n\t\tif ( key === \"closeText\" ) {\n\t\t\tthis.uiDialogTitlebarClose.button( {\n\n\t\t\t\t// Ensure that we always pass a string\n\t\t\t\tlabel: $( \"<a>\" ).text( \"\" + this.options.closeText ).html()\n\t\t\t} );\n\t\t}\n\n\t\tif ( key === \"draggable\" ) {\n\t\t\tisDraggable = uiDialog.is( \":data(ui-draggable)\" );\n\t\t\tif ( isDraggable && !value ) {\n\t\t\t\tuiDialog.draggable( \"destroy\" );\n\t\t\t}\n\n\t\t\tif ( !isDraggable && value ) {\n\t\t\t\tthis._makeDraggable();\n\t\t\t}\n\t\t}\n\n\t\tif ( key === \"position\" ) {\n\t\t\tthis._position();\n\t\t}\n\n\t\tif ( key === \"resizable\" ) {\n\n\t\t\t// currently resizable, becoming non-resizable\n\t\t\tisResizable = uiDialog.is( \":data(ui-resizable)\" );\n\t\t\tif ( isResizable && !value ) {\n\t\t\t\tuiDialog.resizable( \"destroy\" );\n\t\t\t}\n\n\t\t\t// Currently resizable, changing handles\n\t\t\tif ( isResizable && typeof value === \"string\" ) {\n\t\t\t\tuiDialog.resizable( \"option\", \"handles\", value );\n\t\t\t}\n\n\t\t\t// Currently non-resizable, becoming resizable\n\t\t\tif ( !isResizable && value !== false ) {\n\t\t\t\tthis._makeResizable();\n\t\t\t}\n\t\t}\n\n\t\tif ( key === \"title\" ) {\n\t\t\tthis._title( this.uiDialogTitlebar.find( \".ui-dialog-title\" ) );\n\t\t}\n\t},\n\n\t_size: function() {\n\n\t\t// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content\n\t\t// divs will both have width and height set, so we need to reset them\n\t\tvar nonContentHeight, minContentHeight, maxContentHeight,\n\t\t\toptions = this.options;\n\n\t\t// Reset content sizing\n\t\tthis.element.show().css( {\n\t\t\twidth: \"auto\",\n\t\t\tminHeight: 0,\n\t\t\tmaxHeight: \"none\",\n\t\t\theight: 0\n\t\t} );\n\n\t\tif ( options.minWidth > options.width ) {\n\t\t\toptions.width = options.minWidth;\n\t\t}\n\n\t\t// Reset wrapper sizing\n\t\t// determine the height of all the non-content elements\n\t\tnonContentHeight = this.uiDialog.css( {\n\t\t\theight: \"auto\",\n\t\t\twidth: options.width\n\t\t} )\n\t\t\t.outerHeight();\n\t\tminContentHeight = Math.max( 0, options.minHeight - nonContentHeight );\n\t\tmaxContentHeight = typeof options.maxHeight === \"number\" ?\n\t\t\tMath.max( 0, options.maxHeight - nonContentHeight ) :\n\t\t\t\"none\";\n\n\t\tif ( options.height === \"auto\" ) {\n\t\t\tthis.element.css( {\n\t\t\t\tminHeight: minContentHeight,\n\t\t\t\tmaxHeight: maxContentHeight,\n\t\t\t\theight: \"auto\"\n\t\t\t} );\n\t\t} else {\n\t\t\tthis.element.height( Math.max( 0, options.height - nonContentHeight ) );\n\t\t}\n\n\t\tif ( this.uiDialog.is( \":data(ui-resizable)\" ) ) {\n\t\t\tthis.uiDialog.resizable( \"option\", \"minHeight\", this._minHeight() );\n\t\t}\n\t},\n\n\t_blockFrames: function() {\n\t\tthis.iframeBlocks = this.document.find( \"iframe\" ).map( function() {\n\t\t\tvar iframe = $( this );\n\n\t\t\treturn $( \"<div>\" )\n\t\t\t\t.css( {\n\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\twidth: iframe.outerWidth(),\n\t\t\t\t\theight: iframe.outerHeight()\n\t\t\t\t} )\n\t\t\t\t.appendTo( iframe.parent() )\n\t\t\t\t.offset( iframe.offset() )[ 0 ];\n\t\t} );\n\t},\n\n\t_unblockFrames: function() {\n\t\tif ( this.iframeBlocks ) {\n\t\t\tthis.iframeBlocks.remove();\n\t\t\tdelete this.iframeBlocks;\n\t\t}\n\t},\n\n\t_allowInteraction: function( event ) {\n\t\tif ( $( event.target ).closest( \".ui-dialog\" ).length ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// TODO: Remove hack when datepicker implements\n\t\t// the .ui-front logic (#8989)\n\t\treturn !!$( event.target ).closest( \".ui-datepicker\" ).length;\n\t},\n\n\t_createOverlay: function() {\n\t\tif ( !this.options.modal ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// We use a delay in case the overlay is created from an\n\t\t// event that we're going to be cancelling (#2804)\n\t\tvar isOpening = true;\n\t\tthis._delay( function() {\n\t\t\tisOpening = false;\n\t\t} );\n\n\t\tif ( !this.document.data( \"ui-dialog-overlays\" ) ) {\n\n\t\t\t// Prevent use of anchors and inputs\n\t\t\t// Using _on() for an event handler shared across many instances is\n\t\t\t// safe because the dialogs stack and must be closed in reverse order\n\t\t\tthis._on( this.document, {\n\t\t\t\tfocusin: function( event ) {\n\t\t\t\t\tif ( isOpening ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !this._allowInteraction( event ) ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\tthis._trackingInstances()[ 0 ]._focusTabbable();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tthis.overlay = $( \"<div>\" )\n\t\t\t.appendTo( this._appendTo() );\n\n\t\tthis._addClass( this.overlay, null, \"ui-widget-overlay ui-front\" );\n\t\tthis._on( this.overlay, {\n\t\t\tmousedown: \"_keepFocus\"\n\t\t} );\n\t\tthis.document.data( \"ui-dialog-overlays\",\n\t\t\t( this.document.data( \"ui-dialog-overlays\" ) || 0 ) + 1 );\n\t},\n\n\t_destroyOverlay: function() {\n\t\tif ( !this.options.modal ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.overlay ) {\n\t\t\tvar overlays = this.document.data( \"ui-dialog-overlays\" ) - 1;\n\n\t\t\tif ( !overlays ) {\n\t\t\t\tthis._off( this.document, \"focusin\" );\n\t\t\t\tthis.document.removeData( \"ui-dialog-overlays\" );\n\t\t\t} else {\n\t\t\t\tthis.document.data( \"ui-dialog-overlays\", overlays );\n\t\t\t}\n\n\t\t\tthis.overlay.remove();\n\t\t\tthis.overlay = null;\n\t\t}\n\t}\n} );\n\n// DEPRECATED\n// TODO: switch return back to widget declaration at top of file when this is removed\nif ( $.uiBackCompat !== false ) {\n\n\t// Backcompat for dialogClass option\n\t$.widget( \"ui.dialog\", $.ui.dialog, {\n\t\toptions: {\n\t\t\tdialogClass: \"\"\n\t\t},\n\t\t_createWrapper: function() {\n\t\t\tthis._super();\n\t\t\tthis.uiDialog.addClass( this.options.dialogClass );\n\t\t},\n\t\t_setOption: function( key, value ) {\n\t\t\tif ( key === \"dialogClass\" ) {\n\t\t\t\tthis.uiDialog\n\t\t\t\t\t.removeClass( this.options.dialogClass )\n\t\t\t\t\t.addClass( value );\n\t\t\t}\n\t\t\tthis._superApply( arguments );\n\t\t}\n\t} );\n}\n\nvar widgetsDialog = $.ui.dialog;\n\n\n/*!\n * jQuery UI Progressbar 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Progressbar\n//>>group: Widgets\n// jscs:disable maximumLineLength\n//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.\n// jscs:enable maximumLineLength\n//>>docs: http://api.jqueryui.com/progressbar/\n//>>demos: http://jqueryui.com/progressbar/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/progressbar.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\nvar widgetsProgressbar = $.widget( \"ui.progressbar\", {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tclasses: {\n\t\t\t\"ui-progressbar\": \"ui-corner-all\",\n\t\t\t\"ui-progressbar-value\": \"ui-corner-left\",\n\t\t\t\"ui-progressbar-complete\": \"ui-corner-right\"\n\t\t},\n\t\tmax: 100,\n\t\tvalue: 0,\n\n\t\tchange: null,\n\t\tcomplete: null\n\t},\n\n\tmin: 0,\n\n\t_create: function() {\n\n\t\t// Constrain initial value\n\t\tthis.oldValue = this.options.value = this._constrainedValue();\n\n\t\tthis.element.attr( {\n\n\t\t\t// Only set static values; aria-valuenow and aria-valuemax are\n\t\t\t// set inside _refreshValue()\n\t\t\trole: \"progressbar\",\n\t\t\t\"aria-valuemin\": this.min\n\t\t} );\n\t\tthis._addClass( \"ui-progressbar\", \"ui-widget ui-widget-content\" );\n\n\t\tthis.valueDiv = $( \"<div>\" ).appendTo( this.element );\n\t\tthis._addClass( this.valueDiv, \"ui-progressbar-value\", \"ui-widget-header\" );\n\t\tthis._refreshValue();\n\t},\n\n\t_destroy: function() {\n\t\tthis.element.removeAttr( \"role aria-valuemin aria-valuemax aria-valuenow\" );\n\n\t\tthis.valueDiv.remove();\n\t},\n\n\tvalue: function( newValue ) {\n\t\tif ( newValue === undefined ) {\n\t\t\treturn this.options.value;\n\t\t}\n\n\t\tthis.options.value = this._constrainedValue( newValue );\n\t\tthis._refreshValue();\n\t},\n\n\t_constrainedValue: function( newValue ) {\n\t\tif ( newValue === undefined ) {\n\t\t\tnewValue = this.options.value;\n\t\t}\n\n\t\tthis.indeterminate = newValue === false;\n\n\t\t// Sanitize value\n\t\tif ( typeof newValue !== \"number\" ) {\n\t\t\tnewValue = 0;\n\t\t}\n\n\t\treturn this.indeterminate ? false :\n\t\t\tMath.min( this.options.max, Math.max( this.min, newValue ) );\n\t},\n\n\t_setOptions: function( options ) {\n\n\t\t// Ensure \"value\" option is set after other values (like max)\n\t\tvar value = options.value;\n\t\tdelete options.value;\n\n\t\tthis._super( options );\n\n\t\tthis.options.value = this._constrainedValue( value );\n\t\tthis._refreshValue();\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"max\" ) {\n\n\t\t\t// Don't allow a max less than min\n\t\t\tvalue = Math.max( this.min, value );\n\t\t}\n\t\tthis._super( key, value );\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._super( value );\n\n\t\tthis.element.attr( \"aria-disabled\", value );\n\t\tthis._toggleClass( null, \"ui-state-disabled\", !!value );\n\t},\n\n\t_percentage: function() {\n\t\treturn this.indeterminate ?\n\t\t\t100 :\n\t\t\t100 * ( this.options.value - this.min ) / ( this.options.max - this.min );\n\t},\n\n\t_refreshValue: function() {\n\t\tvar value = this.options.value,\n\t\t\tpercentage = this._percentage();\n\n\t\tthis.valueDiv\n\t\t\t.toggle( this.indeterminate || value > this.min )\n\t\t\t.width( percentage.toFixed( 0 ) + \"%\" );\n\n\t\tthis\n\t\t\t._toggleClass( this.valueDiv, \"ui-progressbar-complete\", null,\n\t\t\t\tvalue === this.options.max )\n\t\t\t._toggleClass( \"ui-progressbar-indeterminate\", null, this.indeterminate );\n\n\t\tif ( this.indeterminate ) {\n\t\t\tthis.element.removeAttr( \"aria-valuenow\" );\n\t\t\tif ( !this.overlayDiv ) {\n\t\t\t\tthis.overlayDiv = $( \"<div>\" ).appendTo( this.valueDiv );\n\t\t\t\tthis._addClass( this.overlayDiv, \"ui-progressbar-overlay\" );\n\t\t\t}\n\t\t} else {\n\t\t\tthis.element.attr( {\n\t\t\t\t\"aria-valuemax\": this.options.max,\n\t\t\t\t\"aria-valuenow\": value\n\t\t\t} );\n\t\t\tif ( this.overlayDiv ) {\n\t\t\t\tthis.overlayDiv.remove();\n\t\t\t\tthis.overlayDiv = null;\n\t\t\t}\n\t\t}\n\n\t\tif ( this.oldValue !== value ) {\n\t\t\tthis.oldValue = value;\n\t\t\tthis._trigger( \"change\" );\n\t\t}\n\t\tif ( value === this.options.max ) {\n\t\t\tthis._trigger( \"complete\" );\n\t\t}\n\t}\n} );\n\n\n/*!\n * jQuery UI Selectmenu 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Selectmenu\n//>>group: Widgets\n// jscs:disable maximumLineLength\n//>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select.\n// jscs:enable maximumLineLength\n//>>docs: http://api.jqueryui.com/selectmenu/\n//>>demos: http://jqueryui.com/selectmenu/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\nvar widgetsSelectmenu = $.widget( \"ui.selectmenu\", [ $.ui.formResetMixin, {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<select>\",\n\toptions: {\n\t\tappendTo: null,\n\t\tclasses: {\n\t\t\t\"ui-selectmenu-button-open\": \"ui-corner-top\",\n\t\t\t\"ui-selectmenu-button-closed\": \"ui-corner-all\"\n\t\t},\n\t\tdisabled: null,\n\t\ticons: {\n\t\t\tbutton: \"ui-icon-triangle-1-s\"\n\t\t},\n\t\tposition: {\n\t\t\tmy: \"left top\",\n\t\t\tat: \"left bottom\",\n\t\t\tcollision: \"none\"\n\t\t},\n\t\twidth: false,\n\n\t\t// Callbacks\n\t\tchange: null,\n\t\tclose: null,\n\t\tfocus: null,\n\t\topen: null,\n\t\tselect: null\n\t},\n\n\t_create: function() {\n\t\tvar selectmenuId = this.element.uniqueId().attr( \"id\" );\n\t\tthis.ids = {\n\t\t\telement: selectmenuId,\n\t\t\tbutton: selectmenuId + \"-button\",\n\t\t\tmenu: selectmenuId + \"-menu\"\n\t\t};\n\n\t\tthis._drawButton();\n\t\tthis._drawMenu();\n\t\tthis._bindFormResetHandler();\n\n\t\tthis._rendered = false;\n\t\tthis.menuItems = $();\n\t},\n\n\t_drawButton: function() {\n\t\tvar icon,\n\t\t\tthat = this,\n\t\t\titem = this._parseOption(\n\t\t\t\tthis.element.find( \"option:selected\" ),\n\t\t\t\tthis.element[ 0 ].selectedIndex\n\t\t\t);\n\n\t\t// Associate existing label with the new button\n\t\tthis.labels = this.element.labels().attr( \"for\", this.ids.button );\n\t\tthis._on( this.labels, {\n\t\t\tclick: function( event ) {\n\t\t\t\tthis.button.focus();\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t} );\n\n\t\t// Hide original select element\n\t\tthis.element.hide();\n\n\t\t// Create button\n\t\tthis.button = $( \"<span>\", {\n\t\t\ttabindex: this.options.disabled ? -1 : 0,\n\t\t\tid: this.ids.button,\n\t\t\trole: \"combobox\",\n\t\t\t\"aria-expanded\": \"false\",\n\t\t\t\"aria-autocomplete\": \"list\",\n\t\t\t\"aria-owns\": this.ids.menu,\n\t\t\t\"aria-haspopup\": \"true\",\n\t\t\ttitle: this.element.attr( \"title\" )\n\t\t} )\n\t\t\t.insertAfter( this.element );\n\n\t\tthis._addClass( this.button, \"ui-selectmenu-button ui-selectmenu-button-closed\",\n\t\t\t\"ui-button ui-widget\" );\n\n\t\ticon = $( \"<span>\" ).appendTo( this.button );\n\t\tthis._addClass( icon, \"ui-selectmenu-icon\", \"ui-icon \" + this.options.icons.button );\n\t\tthis.buttonItem = this._renderButtonItem( item )\n\t\t\t.appendTo( this.button );\n\n\t\tif ( this.options.width !== false ) {\n\t\t\tthis._resizeButton();\n\t\t}\n\n\t\tthis._on( this.button, this._buttonEvents );\n\t\tthis.button.one( \"focusin\", function() {\n\n\t\t\t// Delay rendering the menu items until the button receives focus.\n\t\t\t// The menu may have already been rendered via a programmatic open.\n\t\t\tif ( !that._rendered ) {\n\t\t\t\tthat._refreshMenu();\n\t\t\t}\n\t\t} );\n\t},\n\n\t_drawMenu: function() {\n\t\tvar that = this;\n\n\t\t// Create menu\n\t\tthis.menu = $( \"<ul>\", {\n\t\t\t\"aria-hidden\": \"true\",\n\t\t\t\"aria-labelledby\": this.ids.button,\n\t\t\tid: this.ids.menu\n\t\t} );\n\n\t\t// Wrap menu\n\t\tthis.menuWrap = $( \"<div>\" ).append( this.menu );\n\t\tthis._addClass( this.menuWrap, \"ui-selectmenu-menu\", \"ui-front\" );\n\t\tthis.menuWrap.appendTo( this._appendTo() );\n\n\t\t// Initialize menu widget\n\t\tthis.menuInstance = this.menu\n\t\t\t.menu( {\n\t\t\t\tclasses: {\n\t\t\t\t\t\"ui-menu\": \"ui-corner-bottom\"\n\t\t\t\t},\n\t\t\t\trole: \"listbox\",\n\t\t\t\tselect: function( event, ui ) {\n\t\t\t\t\tevent.preventDefault();\n\n\t\t\t\t\t// Support: IE8\n\t\t\t\t\t// If the item was selected via a click, the text selection\n\t\t\t\t\t// will be destroyed in IE\n\t\t\t\t\tthat._setSelection();\n\n\t\t\t\t\tthat._select( ui.item.data( \"ui-selectmenu-item\" ), event );\n\t\t\t\t},\n\t\t\t\tfocus: function( event, ui ) {\n\t\t\t\t\tvar item = ui.item.data( \"ui-selectmenu-item\" );\n\n\t\t\t\t\t// Prevent inital focus from firing and check if its a newly focused item\n\t\t\t\t\tif ( that.focusIndex != null && item.index !== that.focusIndex ) {\n\t\t\t\t\t\tthat._trigger( \"focus\", event, { item: item } );\n\t\t\t\t\t\tif ( !that.isOpen ) {\n\t\t\t\t\t\t\tthat._select( item, event );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthat.focusIndex = item.index;\n\n\t\t\t\t\tthat.button.attr( \"aria-activedescendant\",\n\t\t\t\t\t\tthat.menuItems.eq( item.index ).attr( \"id\" ) );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.menu( \"instance\" );\n\n\t\t// Don't close the menu on mouseleave\n\t\tthis.menuInstance._off( this.menu, \"mouseleave\" );\n\n\t\t// Cancel the menu's collapseAll on document click\n\t\tthis.menuInstance._closeOnDocumentClick = function() {\n\t\t\treturn false;\n\t\t};\n\n\t\t// Selects often contain empty items, but never contain dividers\n\t\tthis.menuInstance._isDivider = function() {\n\t\t\treturn false;\n\t\t};\n\t},\n\n\trefresh: function() {\n\t\tthis._refreshMenu();\n\t\tthis.buttonItem.replaceWith(\n\t\t\tthis.buttonItem = this._renderButtonItem(\n\n\t\t\t\t// Fall back to an empty object in case there are no options\n\t\t\t\tthis._getSelectedItem().data( \"ui-selectmenu-item\" ) || {}\n\t\t\t)\n\t\t);\n\t\tif ( this.options.width === null ) {\n\t\t\tthis._resizeButton();\n\t\t}\n\t},\n\n\t_refreshMenu: function() {\n\t\tvar item,\n\t\t\toptions = this.element.find( \"option\" );\n\n\t\tthis.menu.empty();\n\n\t\tthis._parseOptions( options );\n\t\tthis._renderMenu( this.menu, this.items );\n\n\t\tthis.menuInstance.refresh();\n\t\tthis.menuItems = this.menu.find( \"li\" )\n\t\t\t.not( \".ui-selectmenu-optgroup\" )\n\t\t\t\t.find( \".ui-menu-item-wrapper\" );\n\n\t\tthis._rendered = true;\n\n\t\tif ( !options.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\titem = this._getSelectedItem();\n\n\t\t// Update the menu to have the correct item focused\n\t\tthis.menuInstance.focus( null, item );\n\t\tthis._setAria( item.data( \"ui-selectmenu-item\" ) );\n\n\t\t// Set disabled state\n\t\tthis._setOption( \"disabled\", this.element.prop( \"disabled\" ) );\n\t},\n\n\topen: function( event ) {\n\t\tif ( this.options.disabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If this is the first time the menu is being opened, render the items\n\t\tif ( !this._rendered ) {\n\t\t\tthis._refreshMenu();\n\t\t} else {\n\n\t\t\t// Menu clears focus on close, reset focus to selected item\n\t\t\tthis._removeClass( this.menu.find( \".ui-state-active\" ), null, \"ui-state-active\" );\n\t\t\tthis.menuInstance.focus( null, this._getSelectedItem() );\n\t\t}\n\n\t\t// If there are no options, don't open the menu\n\t\tif ( !this.menuItems.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.isOpen = true;\n\t\tthis._toggleAttr();\n\t\tthis._resizeMenu();\n\t\tthis._position();\n\n\t\tthis._on( this.document, this._documentClick );\n\n\t\tthis._trigger( \"open\", event );\n\t},\n\n\t_position: function() {\n\t\tthis.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );\n\t},\n\n\tclose: function( event ) {\n\t\tif ( !this.isOpen ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.isOpen = false;\n\t\tthis._toggleAttr();\n\n\t\tthis.range = null;\n\t\tthis._off( this.document );\n\n\t\tthis._trigger( \"close\", event );\n\t},\n\n\twidget: function() {\n\t\treturn this.button;\n\t},\n\n\tmenuWidget: function() {\n\t\treturn this.menu;\n\t},\n\n\t_renderButtonItem: function( item ) {\n\t\tvar buttonItem = $( \"<span>\" );\n\n\t\tthis._setText( buttonItem, item.label );\n\t\tthis._addClass( buttonItem, \"ui-selectmenu-text\" );\n\n\t\treturn buttonItem;\n\t},\n\n\t_renderMenu: function( ul, items ) {\n\t\tvar that = this,\n\t\t\tcurrentOptgroup = \"\";\n\n\t\t$.each( items, function( index, item ) {\n\t\t\tvar li;\n\n\t\t\tif ( item.optgroup !== currentOptgroup ) {\n\t\t\t\tli = $( \"<li>\", {\n\t\t\t\t\ttext: item.optgroup\n\t\t\t\t} );\n\t\t\t\tthat._addClass( li, \"ui-selectmenu-optgroup\", \"ui-menu-divider\" +\n\t\t\t\t\t( item.element.parent( \"optgroup\" ).prop( \"disabled\" ) ?\n\t\t\t\t\t\t\" ui-state-disabled\" :\n\t\t\t\t\t\t\"\" ) );\n\n\t\t\t\tli.appendTo( ul );\n\n\t\t\t\tcurrentOptgroup = item.optgroup;\n\t\t\t}\n\n\t\t\tthat._renderItemData( ul, item );\n\t\t} );\n\t},\n\n\t_renderItemData: function( ul, item ) {\n\t\treturn this._renderItem( ul, item ).data( \"ui-selectmenu-item\", item );\n\t},\n\n\t_renderItem: function( ul, item ) {\n\t\tvar li = $( \"<li>\" ),\n\t\t\twrapper = $( \"<div>\", {\n\t\t\t\ttitle: item.element.attr( \"title\" )\n\t\t\t} );\n\n\t\tif ( item.disabled ) {\n\t\t\tthis._addClass( li, null, \"ui-state-disabled\" );\n\t\t}\n\t\tthis._setText( wrapper, item.label );\n\n\t\treturn li.append( wrapper ).appendTo( ul );\n\t},\n\n\t_setText: function( element, value ) {\n\t\tif ( value ) {\n\t\t\telement.text( value );\n\t\t} else {\n\t\t\telement.html( \"&#160;\" );\n\t\t}\n\t},\n\n\t_move: function( direction, event ) {\n\t\tvar item, next,\n\t\t\tfilter = \".ui-menu-item\";\n\n\t\tif ( this.isOpen ) {\n\t\t\titem = this.menuItems.eq( this.focusIndex ).parent( \"li\" );\n\t\t} else {\n\t\t\titem = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( \"li\" );\n\t\t\tfilter += \":not(.ui-state-disabled)\";\n\t\t}\n\n\t\tif ( direction === \"first\" || direction === \"last\" ) {\n\t\t\tnext = item[ direction === \"first\" ? \"prevAll\" : \"nextAll\" ]( filter ).eq( -1 );\n\t\t} else {\n\t\t\tnext = item[ direction + \"All\" ]( filter ).eq( 0 );\n\t\t}\n\n\t\tif ( next.length ) {\n\t\t\tthis.menuInstance.focus( event, next );\n\t\t}\n\t},\n\n\t_getSelectedItem: function() {\n\t\treturn this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( \"li\" );\n\t},\n\n\t_toggle: function( event ) {\n\t\tthis[ this.isOpen ? \"close\" : \"open\" ]( event );\n\t},\n\n\t_setSelection: function() {\n\t\tvar selection;\n\n\t\tif ( !this.range ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( window.getSelection ) {\n\t\t\tselection = window.getSelection();\n\t\t\tselection.removeAllRanges();\n\t\t\tselection.addRange( this.range );\n\n\t\t// Support: IE8\n\t\t} else {\n\t\t\tthis.range.select();\n\t\t}\n\n\t\t// Support: IE\n\t\t// Setting the text selection kills the button focus in IE, but\n\t\t// restoring the focus doesn't kill the selection.\n\t\tthis.button.focus();\n\t},\n\n\t_documentClick: {\n\t\tmousedown: function( event ) {\n\t\t\tif ( !this.isOpen ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( !$( event.target ).closest( \".ui-selectmenu-menu, #\" +\n\t\t\t\t\t$.ui.escapeSelector( this.ids.button ) ).length ) {\n\t\t\t\tthis.close( event );\n\t\t\t}\n\t\t}\n\t},\n\n\t_buttonEvents: {\n\n\t\t// Prevent text selection from being reset when interacting with the selectmenu (#10144)\n\t\tmousedown: function() {\n\t\t\tvar selection;\n\n\t\t\tif ( window.getSelection ) {\n\t\t\t\tselection = window.getSelection();\n\t\t\t\tif ( selection.rangeCount ) {\n\t\t\t\t\tthis.range = selection.getRangeAt( 0 );\n\t\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t} else {\n\t\t\t\tthis.range = document.selection.createRange();\n\t\t\t}\n\t\t},\n\n\t\tclick: function( event ) {\n\t\t\tthis._setSelection();\n\t\t\tthis._toggle( event );\n\t\t},\n\n\t\tkeydown: function( event ) {\n\t\t\tvar preventDefault = true;\n\t\t\tswitch ( event.keyCode ) {\n\t\t\tcase $.ui.keyCode.TAB:\n\t\t\tcase $.ui.keyCode.ESCAPE:\n\t\t\t\tthis.close( event );\n\t\t\t\tpreventDefault = false;\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.ENTER:\n\t\t\t\tif ( this.isOpen ) {\n\t\t\t\t\tthis._selectFocusedItem( event );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.UP:\n\t\t\t\tif ( event.altKey ) {\n\t\t\t\t\tthis._toggle( event );\n\t\t\t\t} else {\n\t\t\t\t\tthis._move( \"prev\", event );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.DOWN:\n\t\t\t\tif ( event.altKey ) {\n\t\t\t\t\tthis._toggle( event );\n\t\t\t\t} else {\n\t\t\t\t\tthis._move( \"next\", event );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.SPACE:\n\t\t\t\tif ( this.isOpen ) {\n\t\t\t\t\tthis._selectFocusedItem( event );\n\t\t\t\t} else {\n\t\t\t\t\tthis._toggle( event );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.LEFT:\n\t\t\t\tthis._move( \"prev\", event );\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.RIGHT:\n\t\t\t\tthis._move( \"next\", event );\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.HOME:\n\t\t\tcase $.ui.keyCode.PAGE_UP:\n\t\t\t\tthis._move( \"first\", event );\n\t\t\t\tbreak;\n\t\t\tcase $.ui.keyCode.END:\n\t\t\tcase $.ui.keyCode.PAGE_DOWN:\n\t\t\t\tthis._move( \"last\", event );\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis.menu.trigger( event );\n\t\t\t\tpreventDefault = false;\n\t\t\t}\n\n\t\t\tif ( preventDefault ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t},\n\n\t_selectFocusedItem: function( event ) {\n\t\tvar item = this.menuItems.eq( this.focusIndex ).parent( \"li\" );\n\t\tif ( !item.hasClass( \"ui-state-disabled\" ) ) {\n\t\t\tthis._select( item.data( \"ui-selectmenu-item\" ), event );\n\t\t}\n\t},\n\n\t_select: function( item, event ) {\n\t\tvar oldIndex = this.element[ 0 ].selectedIndex;\n\n\t\t// Change native select element\n\t\tthis.element[ 0 ].selectedIndex = item.index;\n\t\tthis.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );\n\t\tthis._setAria( item );\n\t\tthis._trigger( \"select\", event, { item: item } );\n\n\t\tif ( item.index !== oldIndex ) {\n\t\t\tthis._trigger( \"change\", event, { item: item } );\n\t\t}\n\n\t\tthis.close( event );\n\t},\n\n\t_setAria: function( item ) {\n\t\tvar id = this.menuItems.eq( item.index ).attr( \"id\" );\n\n\t\tthis.button.attr( {\n\t\t\t\"aria-labelledby\": id,\n\t\t\t\"aria-activedescendant\": id\n\t\t} );\n\t\tthis.menu.attr( \"aria-activedescendant\", id );\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"icons\" ) {\n\t\t\tvar icon = this.button.find( \"span.ui-icon\" );\n\t\t\tthis._removeClass( icon, null, this.options.icons.button )\n\t\t\t\t._addClass( icon, null, value.button );\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"appendTo\" ) {\n\t\t\tthis.menuWrap.appendTo( this._appendTo() );\n\t\t}\n\n\t\tif ( key === \"width\" ) {\n\t\t\tthis._resizeButton();\n\t\t}\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._super( value );\n\n\t\tthis.menuInstance.option( \"disabled\", value );\n\t\tthis.button.attr( \"aria-disabled\", value );\n\t\tthis._toggleClass( this.button, null, \"ui-state-disabled\", value );\n\n\t\tthis.element.prop( \"disabled\", value );\n\t\tif ( value ) {\n\t\t\tthis.button.attr( \"tabindex\", -1 );\n\t\t\tthis.close();\n\t\t} else {\n\t\t\tthis.button.attr( \"tabindex\", 0 );\n\t\t}\n\t},\n\n\t_appendTo: function() {\n\t\tvar element = this.options.appendTo;\n\n\t\tif ( element ) {\n\t\t\telement = element.jquery || element.nodeType ?\n\t\t\t\t$( element ) :\n\t\t\t\tthis.document.find( element ).eq( 0 );\n\t\t}\n\n\t\tif ( !element || !element[ 0 ] ) {\n\t\t\telement = this.element.closest( \".ui-front, dialog\" );\n\t\t}\n\n\t\tif ( !element.length ) {\n\t\t\telement = this.document[ 0 ].body;\n\t\t}\n\n\t\treturn element;\n\t},\n\n\t_toggleAttr: function() {\n\t\tthis.button.attr( \"aria-expanded\", this.isOpen );\n\n\t\t// We can't use two _toggleClass() calls here, because we need to make sure\n\t\t// we always remove classes first and add them second, otherwise if both classes have the\n\t\t// same theme class, it will be removed after we add it.\n\t\tthis._removeClass( this.button, \"ui-selectmenu-button-\" +\n\t\t\t( this.isOpen ? \"closed\" : \"open\" ) )\n\t\t\t._addClass( this.button, \"ui-selectmenu-button-\" +\n\t\t\t\t( this.isOpen ? \"open\" : \"closed\" ) )\n\t\t\t._toggleClass( this.menuWrap, \"ui-selectmenu-open\", null, this.isOpen );\n\n\t\tthis.menu.attr( \"aria-hidden\", !this.isOpen );\n\t},\n\n\t_resizeButton: function() {\n\t\tvar width = this.options.width;\n\n\t\t// For `width: false`, just remove inline style and stop\n\t\tif ( width === false ) {\n\t\t\tthis.button.css( \"width\", \"\" );\n\t\t\treturn;\n\t\t}\n\n\t\t// For `width: null`, match the width of the original element\n\t\tif ( width === null ) {\n\t\t\twidth = this.element.show().outerWidth();\n\t\t\tthis.element.hide();\n\t\t}\n\n\t\tthis.button.outerWidth( width );\n\t},\n\n\t_resizeMenu: function() {\n\t\tthis.menu.outerWidth( Math.max(\n\t\t\tthis.button.outerWidth(),\n\n\t\t\t// Support: IE10\n\t\t\t// IE10 wraps long text (possibly a rounding bug)\n\t\t\t// so we add 1px to avoid the wrapping\n\t\t\tthis.menu.width( \"\" ).outerWidth() + 1\n\t\t) );\n\t},\n\n\t_getCreateOptions: function() {\n\t\tvar options = this._super();\n\n\t\toptions.disabled = this.element.prop( \"disabled\" );\n\n\t\treturn options;\n\t},\n\n\t_parseOptions: function( options ) {\n\t\tvar that = this,\n\t\t\tdata = [];\n\t\toptions.each( function( index, item ) {\n\t\t\tdata.push( that._parseOption( $( item ), index ) );\n\t\t} );\n\t\tthis.items = data;\n\t},\n\n\t_parseOption: function( option, index ) {\n\t\tvar optgroup = option.parent( \"optgroup\" );\n\n\t\treturn {\n\t\t\telement: option,\n\t\t\tindex: index,\n\t\t\tvalue: option.val(),\n\t\t\tlabel: option.text(),\n\t\t\toptgroup: optgroup.attr( \"label\" ) || \"\",\n\t\t\tdisabled: optgroup.prop( \"disabled\" ) || option.prop( \"disabled\" )\n\t\t};\n\t},\n\n\t_destroy: function() {\n\t\tthis._unbindFormResetHandler();\n\t\tthis.menuWrap.remove();\n\t\tthis.button.remove();\n\t\tthis.element.show();\n\t\tthis.element.removeUniqueId();\n\t\tthis.labels.attr( \"for\", this.ids.element );\n\t}\n} ] );\n\n\n/*!\n * jQuery UI Slider 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Slider\n//>>group: Widgets\n//>>description: Displays a flexible slider with ranges and accessibility via keyboard.\n//>>docs: http://api.jqueryui.com/slider/\n//>>demos: http://jqueryui.com/slider/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/slider.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\nvar widgetsSlider = $.widget( \"ui.slider\", $.ui.mouse, {\n\tversion: \"1.12.1\",\n\twidgetEventPrefix: \"slide\",\n\n\toptions: {\n\t\tanimate: false,\n\t\tclasses: {\n\t\t\t\"ui-slider\": \"ui-corner-all\",\n\t\t\t\"ui-slider-handle\": \"ui-corner-all\",\n\n\t\t\t// Note: ui-widget-header isn't the most fittingly semantic framework class for this\n\t\t\t// element, but worked best visually with a variety of themes\n\t\t\t\"ui-slider-range\": \"ui-corner-all ui-widget-header\"\n\t\t},\n\t\tdistance: 0,\n\t\tmax: 100,\n\t\tmin: 0,\n\t\torientation: \"horizontal\",\n\t\trange: false,\n\t\tstep: 1,\n\t\tvalue: 0,\n\t\tvalues: null,\n\n\t\t// Callbacks\n\t\tchange: null,\n\t\tslide: null,\n\t\tstart: null,\n\t\tstop: null\n\t},\n\n\t// Number of pages in a slider\n\t// (how many times can you page up/down to go through the whole range)\n\tnumPages: 5,\n\n\t_create: function() {\n\t\tthis._keySliding = false;\n\t\tthis._mouseSliding = false;\n\t\tthis._animateOff = true;\n\t\tthis._handleIndex = null;\n\t\tthis._detectOrientation();\n\t\tthis._mouseInit();\n\t\tthis._calculateNewMax();\n\n\t\tthis._addClass( \"ui-slider ui-slider-\" + this.orientation,\n\t\t\t\"ui-widget ui-widget-content\" );\n\n\t\tthis._refresh();\n\n\t\tthis._animateOff = false;\n\t},\n\n\t_refresh: function() {\n\t\tthis._createRange();\n\t\tthis._createHandles();\n\t\tthis._setupEvents();\n\t\tthis._refreshValue();\n\t},\n\n\t_createHandles: function() {\n\t\tvar i, handleCount,\n\t\t\toptions = this.options,\n\t\t\texistingHandles = this.element.find( \".ui-slider-handle\" ),\n\t\t\thandle = \"<span tabindex='0'></span>\",\n\t\t\thandles = [];\n\n\t\thandleCount = ( options.values && options.values.length ) || 1;\n\n\t\tif ( existingHandles.length > handleCount ) {\n\t\t\texistingHandles.slice( handleCount ).remove();\n\t\t\texistingHandles = existingHandles.slice( 0, handleCount );\n\t\t}\n\n\t\tfor ( i = existingHandles.length; i < handleCount; i++ ) {\n\t\t\thandles.push( handle );\n\t\t}\n\n\t\tthis.handles = existingHandles.add( $( handles.join( \"\" ) ).appendTo( this.element ) );\n\n\t\tthis._addClass( this.handles, \"ui-slider-handle\", \"ui-state-default\" );\n\n\t\tthis.handle = this.handles.eq( 0 );\n\n\t\tthis.handles.each( function( i ) {\n\t\t\t$( this )\n\t\t\t\t.data( \"ui-slider-handle-index\", i )\n\t\t\t\t.attr( \"tabIndex\", 0 );\n\t\t} );\n\t},\n\n\t_createRange: function() {\n\t\tvar options = this.options;\n\n\t\tif ( options.range ) {\n\t\t\tif ( options.range === true ) {\n\t\t\t\tif ( !options.values ) {\n\t\t\t\t\toptions.values = [ this._valueMin(), this._valueMin() ];\n\t\t\t\t} else if ( options.values.length && options.values.length !== 2 ) {\n\t\t\t\t\toptions.values = [ options.values[ 0 ], options.values[ 0 ] ];\n\t\t\t\t} else if ( $.isArray( options.values ) ) {\n\t\t\t\t\toptions.values = options.values.slice( 0 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !this.range || !this.range.length ) {\n\t\t\t\tthis.range = $( \"<div>\" )\n\t\t\t\t\t.appendTo( this.element );\n\n\t\t\t\tthis._addClass( this.range, \"ui-slider-range\" );\n\t\t\t} else {\n\t\t\t\tthis._removeClass( this.range, \"ui-slider-range-min ui-slider-range-max\" );\n\n\t\t\t\t// Handle range switching from true to min/max\n\t\t\t\tthis.range.css( {\n\t\t\t\t\t\"left\": \"\",\n\t\t\t\t\t\"bottom\": \"\"\n\t\t\t\t} );\n\t\t\t}\n\t\t\tif ( options.range === \"min\" || options.range === \"max\" ) {\n\t\t\t\tthis._addClass( this.range, \"ui-slider-range-\" + options.range );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( this.range ) {\n\t\t\t\tthis.range.remove();\n\t\t\t}\n\t\t\tthis.range = null;\n\t\t}\n\t},\n\n\t_setupEvents: function() {\n\t\tthis._off( this.handles );\n\t\tthis._on( this.handles, this._handleEvents );\n\t\tthis._hoverable( this.handles );\n\t\tthis._focusable( this.handles );\n\t},\n\n\t_destroy: function() {\n\t\tthis.handles.remove();\n\t\tif ( this.range ) {\n\t\t\tthis.range.remove();\n\t\t}\n\n\t\tthis._mouseDestroy();\n\t},\n\n\t_mouseCapture: function( event ) {\n\t\tvar position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,\n\t\t\tthat = this,\n\t\t\to = this.options;\n\n\t\tif ( o.disabled ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.elementSize = {\n\t\t\twidth: this.element.outerWidth(),\n\t\t\theight: this.element.outerHeight()\n\t\t};\n\t\tthis.elementOffset = this.element.offset();\n\n\t\tposition = { x: event.pageX, y: event.pageY };\n\t\tnormValue = this._normValueFromMouse( position );\n\t\tdistance = this._valueMax() - this._valueMin() + 1;\n\t\tthis.handles.each( function( i ) {\n\t\t\tvar thisDistance = Math.abs( normValue - that.values( i ) );\n\t\t\tif ( ( distance > thisDistance ) ||\n\t\t\t\t( distance === thisDistance &&\n\t\t\t\t\t( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {\n\t\t\t\tdistance = thisDistance;\n\t\t\t\tclosestHandle = $( this );\n\t\t\t\tindex = i;\n\t\t\t}\n\t\t} );\n\n\t\tallowed = this._start( event, index );\n\t\tif ( allowed === false ) {\n\t\t\treturn false;\n\t\t}\n\t\tthis._mouseSliding = true;\n\n\t\tthis._handleIndex = index;\n\n\t\tthis._addClass( closestHandle, null, \"ui-state-active\" );\n\t\tclosestHandle.trigger( \"focus\" );\n\n\t\toffset = closestHandle.offset();\n\t\tmouseOverHandle = !$( event.target ).parents().addBack().is( \".ui-slider-handle\" );\n\t\tthis._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {\n\t\t\tleft: event.pageX - offset.left - ( closestHandle.width() / 2 ),\n\t\t\ttop: event.pageY - offset.top -\n\t\t\t\t( closestHandle.height() / 2 ) -\n\t\t\t\t( parseInt( closestHandle.css( \"borderTopWidth\" ), 10 ) || 0 ) -\n\t\t\t\t( parseInt( closestHandle.css( \"borderBottomWidth\" ), 10 ) || 0 ) +\n\t\t\t\t( parseInt( closestHandle.css( \"marginTop\" ), 10 ) || 0 )\n\t\t};\n\n\t\tif ( !this.handles.hasClass( \"ui-state-hover\" ) ) {\n\t\t\tthis._slide( event, index, normValue );\n\t\t}\n\t\tthis._animateOff = true;\n\t\treturn true;\n\t},\n\n\t_mouseStart: function() {\n\t\treturn true;\n\t},\n\n\t_mouseDrag: function( event ) {\n\t\tvar position = { x: event.pageX, y: event.pageY },\n\t\t\tnormValue = this._normValueFromMouse( position );\n\n\t\tthis._slide( event, this._handleIndex, normValue );\n\n\t\treturn false;\n\t},\n\n\t_mouseStop: function( event ) {\n\t\tthis._removeClass( this.handles, null, \"ui-state-active\" );\n\t\tthis._mouseSliding = false;\n\n\t\tthis._stop( event, this._handleIndex );\n\t\tthis._change( event, this._handleIndex );\n\n\t\tthis._handleIndex = null;\n\t\tthis._clickOffset = null;\n\t\tthis._animateOff = false;\n\n\t\treturn false;\n\t},\n\n\t_detectOrientation: function() {\n\t\tthis.orientation = ( this.options.orientation === \"vertical\" ) ? \"vertical\" : \"horizontal\";\n\t},\n\n\t_normValueFromMouse: function( position ) {\n\t\tvar pixelTotal,\n\t\t\tpixelMouse,\n\t\t\tpercentMouse,\n\t\t\tvalueTotal,\n\t\t\tvalueMouse;\n\n\t\tif ( this.orientation === \"horizontal\" ) {\n\t\t\tpixelTotal = this.elementSize.width;\n\t\t\tpixelMouse = position.x - this.elementOffset.left -\n\t\t\t\t( this._clickOffset ? this._clickOffset.left : 0 );\n\t\t} else {\n\t\t\tpixelTotal = this.elementSize.height;\n\t\t\tpixelMouse = position.y - this.elementOffset.top -\n\t\t\t\t( this._clickOffset ? this._clickOffset.top : 0 );\n\t\t}\n\n\t\tpercentMouse = ( pixelMouse / pixelTotal );\n\t\tif ( percentMouse > 1 ) {\n\t\t\tpercentMouse = 1;\n\t\t}\n\t\tif ( percentMouse < 0 ) {\n\t\t\tpercentMouse = 0;\n\t\t}\n\t\tif ( this.orientation === \"vertical\" ) {\n\t\t\tpercentMouse = 1 - percentMouse;\n\t\t}\n\n\t\tvalueTotal = this._valueMax() - this._valueMin();\n\t\tvalueMouse = this._valueMin() + percentMouse * valueTotal;\n\n\t\treturn this._trimAlignValue( valueMouse );\n\t},\n\n\t_uiHash: function( index, value, values ) {\n\t\tvar uiHash = {\n\t\t\thandle: this.handles[ index ],\n\t\t\thandleIndex: index,\n\t\t\tvalue: value !== undefined ? value : this.value()\n\t\t};\n\n\t\tif ( this._hasMultipleValues() ) {\n\t\t\tuiHash.value = value !== undefined ? value : this.values( index );\n\t\t\tuiHash.values = values || this.values();\n\t\t}\n\n\t\treturn uiHash;\n\t},\n\n\t_hasMultipleValues: function() {\n\t\treturn this.options.values && this.options.values.length;\n\t},\n\n\t_start: function( event, index ) {\n\t\treturn this._trigger( \"start\", event, this._uiHash( index ) );\n\t},\n\n\t_slide: function( event, index, newVal ) {\n\t\tvar allowed, otherVal,\n\t\t\tcurrentValue = this.value(),\n\t\t\tnewValues = this.values();\n\n\t\tif ( this._hasMultipleValues() ) {\n\t\t\totherVal = this.values( index ? 0 : 1 );\n\t\t\tcurrentValue = this.values( index );\n\n\t\t\tif ( this.options.values.length === 2 && this.options.range === true ) {\n\t\t\t\tnewVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );\n\t\t\t}\n\n\t\t\tnewValues[ index ] = newVal;\n\t\t}\n\n\t\tif ( newVal === currentValue ) {\n\t\t\treturn;\n\t\t}\n\n\t\tallowed = this._trigger( \"slide\", event, this._uiHash( index, newVal, newValues ) );\n\n\t\t// A slide can be canceled by returning false from the slide callback\n\t\tif ( allowed === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this._hasMultipleValues() ) {\n\t\t\tthis.values( index, newVal );\n\t\t} else {\n\t\t\tthis.value( newVal );\n\t\t}\n\t},\n\n\t_stop: function( event, index ) {\n\t\tthis._trigger( \"stop\", event, this._uiHash( index ) );\n\t},\n\n\t_change: function( event, index ) {\n\t\tif ( !this._keySliding && !this._mouseSliding ) {\n\n\t\t\t//store the last changed value index for reference when handles overlap\n\t\t\tthis._lastChangedValue = index;\n\t\t\tthis._trigger( \"change\", event, this._uiHash( index ) );\n\t\t}\n\t},\n\n\tvalue: function( newValue ) {\n\t\tif ( arguments.length ) {\n\t\t\tthis.options.value = this._trimAlignValue( newValue );\n\t\t\tthis._refreshValue();\n\t\t\tthis._change( null, 0 );\n\t\t\treturn;\n\t\t}\n\n\t\treturn this._value();\n\t},\n\n\tvalues: function( index, newValue ) {\n\t\tvar vals,\n\t\t\tnewValues,\n\t\t\ti;\n\n\t\tif ( arguments.length > 1 ) {\n\t\t\tthis.options.values[ index ] = this._trimAlignValue( newValue );\n\t\t\tthis._refreshValue();\n\t\t\tthis._change( null, index );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( arguments.length ) {\n\t\t\tif ( $.isArray( arguments[ 0 ] ) ) {\n\t\t\t\tvals = this.options.values;\n\t\t\t\tnewValues = arguments[ 0 ];\n\t\t\t\tfor ( i = 0; i < vals.length; i += 1 ) {\n\t\t\t\t\tvals[ i ] = this._trimAlignValue( newValues[ i ] );\n\t\t\t\t\tthis._change( null, i );\n\t\t\t\t}\n\t\t\t\tthis._refreshValue();\n\t\t\t} else {\n\t\t\t\tif ( this._hasMultipleValues() ) {\n\t\t\t\t\treturn this._values( index );\n\t\t\t\t} else {\n\t\t\t\t\treturn this.value();\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn this._values();\n\t\t}\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tvar i,\n\t\t\tvalsLength = 0;\n\n\t\tif ( key === \"range\" && this.options.range === true ) {\n\t\t\tif ( value === \"min\" ) {\n\t\t\t\tthis.options.value = this._values( 0 );\n\t\t\t\tthis.options.values = null;\n\t\t\t} else if ( value === \"max\" ) {\n\t\t\t\tthis.options.value = this._values( this.options.values.length - 1 );\n\t\t\t\tthis.options.values = null;\n\t\t\t}\n\t\t}\n\n\t\tif ( $.isArray( this.options.values ) ) {\n\t\t\tvalsLength = this.options.values.length;\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\tswitch ( key ) {\n\t\t\tcase \"orientation\":\n\t\t\t\tthis._detectOrientation();\n\t\t\t\tthis._removeClass( \"ui-slider-horizontal ui-slider-vertical\" )\n\t\t\t\t\t._addClass( \"ui-slider-\" + this.orientation );\n\t\t\t\tthis._refreshValue();\n\t\t\t\tif ( this.options.range ) {\n\t\t\t\t\tthis._refreshRange( value );\n\t\t\t\t}\n\n\t\t\t\t// Reset positioning from previous orientation\n\t\t\t\tthis.handles.css( value === \"horizontal\" ? \"bottom\" : \"left\", \"\" );\n\t\t\t\tbreak;\n\t\t\tcase \"value\":\n\t\t\t\tthis._animateOff = true;\n\t\t\t\tthis._refreshValue();\n\t\t\t\tthis._change( null, 0 );\n\t\t\t\tthis._animateOff = false;\n\t\t\t\tbreak;\n\t\t\tcase \"values\":\n\t\t\t\tthis._animateOff = true;\n\t\t\t\tthis._refreshValue();\n\n\t\t\t\t// Start from the last handle to prevent unreachable handles (#9046)\n\t\t\t\tfor ( i = valsLength - 1; i >= 0; i-- ) {\n\t\t\t\t\tthis._change( null, i );\n\t\t\t\t}\n\t\t\t\tthis._animateOff = false;\n\t\t\t\tbreak;\n\t\t\tcase \"step\":\n\t\t\tcase \"min\":\n\t\t\tcase \"max\":\n\t\t\t\tthis._animateOff = true;\n\t\t\t\tthis._calculateNewMax();\n\t\t\t\tthis._refreshValue();\n\t\t\t\tthis._animateOff = false;\n\t\t\t\tbreak;\n\t\t\tcase \"range\":\n\t\t\t\tthis._animateOff = true;\n\t\t\t\tthis._refresh();\n\t\t\t\tthis._animateOff = false;\n\t\t\t\tbreak;\n\t\t}\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._super( value );\n\n\t\tthis._toggleClass( null, \"ui-state-disabled\", !!value );\n\t},\n\n\t//internal value getter\n\t// _value() returns value trimmed by min and max, aligned by step\n\t_value: function() {\n\t\tvar val = this.options.value;\n\t\tval = this._trimAlignValue( val );\n\n\t\treturn val;\n\t},\n\n\t//internal values getter\n\t// _values() returns array of values trimmed by min and max, aligned by step\n\t// _values( index ) returns single value trimmed by min and max, aligned by step\n\t_values: function( index ) {\n\t\tvar val,\n\t\t\tvals,\n\t\t\ti;\n\n\t\tif ( arguments.length ) {\n\t\t\tval = this.options.values[ index ];\n\t\t\tval = this._trimAlignValue( val );\n\n\t\t\treturn val;\n\t\t} else if ( this._hasMultipleValues() ) {\n\n\t\t\t// .slice() creates a copy of the array\n\t\t\t// this copy gets trimmed by min and max and then returned\n\t\t\tvals = this.options.values.slice();\n\t\t\tfor ( i = 0; i < vals.length; i += 1 ) {\n\t\t\t\tvals[ i ] = this._trimAlignValue( vals[ i ] );\n\t\t\t}\n\n\t\t\treturn vals;\n\t\t} else {\n\t\t\treturn [];\n\t\t}\n\t},\n\n\t// Returns the step-aligned value that val is closest to, between (inclusive) min and max\n\t_trimAlignValue: function( val ) {\n\t\tif ( val <= this._valueMin() ) {\n\t\t\treturn this._valueMin();\n\t\t}\n\t\tif ( val >= this._valueMax() ) {\n\t\t\treturn this._valueMax();\n\t\t}\n\t\tvar step = ( this.options.step > 0 ) ? this.options.step : 1,\n\t\t\tvalModStep = ( val - this._valueMin() ) % step,\n\t\t\talignValue = val - valModStep;\n\n\t\tif ( Math.abs( valModStep ) * 2 >= step ) {\n\t\t\talignValue += ( valModStep > 0 ) ? step : ( -step );\n\t\t}\n\n\t\t// Since JavaScript has problems with large floats, round\n\t\t// the final value to 5 digits after the decimal point (see #4124)\n\t\treturn parseFloat( alignValue.toFixed( 5 ) );\n\t},\n\n\t_calculateNewMax: function() {\n\t\tvar max = this.options.max,\n\t\t\tmin = this._valueMin(),\n\t\t\tstep = this.options.step,\n\t\t\taboveMin = Math.round( ( max - min ) / step ) * step;\n\t\tmax = aboveMin + min;\n\t\tif ( max > this.options.max ) {\n\n\t\t\t//If max is not divisible by step, rounding off may increase its value\n\t\t\tmax -= step;\n\t\t}\n\t\tthis.max = parseFloat( max.toFixed( this._precision() ) );\n\t},\n\n\t_precision: function() {\n\t\tvar precision = this._precisionOf( this.options.step );\n\t\tif ( this.options.min !== null ) {\n\t\t\tprecision = Math.max( precision, this._precisionOf( this.options.min ) );\n\t\t}\n\t\treturn precision;\n\t},\n\n\t_precisionOf: function( num ) {\n\t\tvar str = num.toString(),\n\t\t\tdecimal = str.indexOf( \".\" );\n\t\treturn decimal === -1 ? 0 : str.length - decimal - 1;\n\t},\n\n\t_valueMin: function() {\n\t\treturn this.options.min;\n\t},\n\n\t_valueMax: function() {\n\t\treturn this.max;\n\t},\n\n\t_refreshRange: function( orientation ) {\n\t\tif ( orientation === \"vertical\" ) {\n\t\t\tthis.range.css( { \"width\": \"\", \"left\": \"\" } );\n\t\t}\n\t\tif ( orientation === \"horizontal\" ) {\n\t\t\tthis.range.css( { \"height\": \"\", \"bottom\": \"\" } );\n\t\t}\n\t},\n\n\t_refreshValue: function() {\n\t\tvar lastValPercent, valPercent, value, valueMin, valueMax,\n\t\t\toRange = this.options.range,\n\t\t\to = this.options,\n\t\t\tthat = this,\n\t\t\tanimate = ( !this._animateOff ) ? o.animate : false,\n\t\t\t_set = {};\n\n\t\tif ( this._hasMultipleValues() ) {\n\t\t\tthis.handles.each( function( i ) {\n\t\t\t\tvalPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -\n\t\t\t\t\tthat._valueMin() ) * 100;\n\t\t\t\t_set[ that.orientation === \"horizontal\" ? \"left\" : \"bottom\" ] = valPercent + \"%\";\n\t\t\t\t$( this ).stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( _set, o.animate );\n\t\t\t\tif ( that.options.range === true ) {\n\t\t\t\t\tif ( that.orientation === \"horizontal\" ) {\n\t\t\t\t\t\tif ( i === 0 ) {\n\t\t\t\t\t\t\tthat.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\t\t\t\tleft: valPercent + \"%\"\n\t\t\t\t\t\t\t}, o.animate );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( i === 1 ) {\n\t\t\t\t\t\t\tthat.range[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\t\t\t\twidth: ( valPercent - lastValPercent ) + \"%\"\n\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\tqueue: false,\n\t\t\t\t\t\t\t\tduration: o.animate\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( i === 0 ) {\n\t\t\t\t\t\t\tthat.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\t\t\t\tbottom: ( valPercent ) + \"%\"\n\t\t\t\t\t\t\t}, o.animate );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( i === 1 ) {\n\t\t\t\t\t\t\tthat.range[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\t\t\t\theight: ( valPercent - lastValPercent ) + \"%\"\n\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\tqueue: false,\n\t\t\t\t\t\t\t\tduration: o.animate\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlastValPercent = valPercent;\n\t\t\t} );\n\t\t} else {\n\t\t\tvalue = this.value();\n\t\t\tvalueMin = this._valueMin();\n\t\t\tvalueMax = this._valueMax();\n\t\t\tvalPercent = ( valueMax !== valueMin ) ?\n\t\t\t\t\t( value - valueMin ) / ( valueMax - valueMin ) * 100 :\n\t\t\t\t\t0;\n\t\t\t_set[ this.orientation === \"horizontal\" ? \"left\" : \"bottom\" ] = valPercent + \"%\";\n\t\t\tthis.handle.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( _set, o.animate );\n\n\t\t\tif ( oRange === \"min\" && this.orientation === \"horizontal\" ) {\n\t\t\t\tthis.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\twidth: valPercent + \"%\"\n\t\t\t\t}, o.animate );\n\t\t\t}\n\t\t\tif ( oRange === \"max\" && this.orientation === \"horizontal\" ) {\n\t\t\t\tthis.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\twidth: ( 100 - valPercent ) + \"%\"\n\t\t\t\t}, o.animate );\n\t\t\t}\n\t\t\tif ( oRange === \"min\" && this.orientation === \"vertical\" ) {\n\t\t\t\tthis.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\theight: valPercent + \"%\"\n\t\t\t\t}, o.animate );\n\t\t\t}\n\t\t\tif ( oRange === \"max\" && this.orientation === \"vertical\" ) {\n\t\t\t\tthis.range.stop( 1, 1 )[ animate ? \"animate\" : \"css\" ]( {\n\t\t\t\t\theight: ( 100 - valPercent ) + \"%\"\n\t\t\t\t}, o.animate );\n\t\t\t}\n\t\t}\n\t},\n\n\t_handleEvents: {\n\t\tkeydown: function( event ) {\n\t\t\tvar allowed, curVal, newVal, step,\n\t\t\t\tindex = $( event.target ).data( \"ui-slider-handle-index\" );\n\n\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase $.ui.keyCode.HOME:\n\t\t\t\tcase $.ui.keyCode.END:\n\t\t\t\tcase $.ui.keyCode.PAGE_UP:\n\t\t\t\tcase $.ui.keyCode.PAGE_DOWN:\n\t\t\t\tcase $.ui.keyCode.UP:\n\t\t\t\tcase $.ui.keyCode.RIGHT:\n\t\t\t\tcase $.ui.keyCode.DOWN:\n\t\t\t\tcase $.ui.keyCode.LEFT:\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tif ( !this._keySliding ) {\n\t\t\t\t\t\tthis._keySliding = true;\n\t\t\t\t\t\tthis._addClass( $( event.target ), null, \"ui-state-active\" );\n\t\t\t\t\t\tallowed = this._start( event, index );\n\t\t\t\t\t\tif ( allowed === false ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tstep = this.options.step;\n\t\t\tif ( this._hasMultipleValues() ) {\n\t\t\t\tcurVal = newVal = this.values( index );\n\t\t\t} else {\n\t\t\t\tcurVal = newVal = this.value();\n\t\t\t}\n\n\t\t\tswitch ( event.keyCode ) {\n\t\t\t\tcase $.ui.keyCode.HOME:\n\t\t\t\t\tnewVal = this._valueMin();\n\t\t\t\t\tbreak;\n\t\t\t\tcase $.ui.keyCode.END:\n\t\t\t\t\tnewVal = this._valueMax();\n\t\t\t\t\tbreak;\n\t\t\t\tcase $.ui.keyCode.PAGE_UP:\n\t\t\t\t\tnewVal = this._trimAlignValue(\n\t\t\t\t\t\tcurVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )\n\t\t\t\t\t);\n\t\t\t\t\tbreak;\n\t\t\t\tcase $.ui.keyCode.PAGE_DOWN:\n\t\t\t\t\tnewVal = this._trimAlignValue(\n\t\t\t\t\t\tcurVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );\n\t\t\t\t\tbreak;\n\t\t\t\tcase $.ui.keyCode.UP:\n\t\t\t\tcase $.ui.keyCode.RIGHT:\n\t\t\t\t\tif ( curVal === this._valueMax() ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tnewVal = this._trimAlignValue( curVal + step );\n\t\t\t\t\tbreak;\n\t\t\t\tcase $.ui.keyCode.DOWN:\n\t\t\t\tcase $.ui.keyCode.LEFT:\n\t\t\t\t\tif ( curVal === this._valueMin() ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tnewVal = this._trimAlignValue( curVal - step );\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tthis._slide( event, index, newVal );\n\t\t},\n\t\tkeyup: function( event ) {\n\t\t\tvar index = $( event.target ).data( \"ui-slider-handle-index\" );\n\n\t\t\tif ( this._keySliding ) {\n\t\t\t\tthis._keySliding = false;\n\t\t\t\tthis._stop( event, index );\n\t\t\t\tthis._change( event, index );\n\t\t\t\tthis._removeClass( $( event.target ), null, \"ui-state-active\" );\n\t\t\t}\n\t\t}\n\t}\n} );\n\n\n/*!\n * jQuery UI Spinner 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Spinner\n//>>group: Widgets\n//>>description: Displays buttons to easily input numbers via the keyboard or mouse.\n//>>docs: http://api.jqueryui.com/spinner/\n//>>demos: http://jqueryui.com/spinner/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/spinner.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\nfunction spinnerModifer( fn ) {\n\treturn function() {\n\t\tvar previous = this.element.val();\n\t\tfn.apply( this, arguments );\n\t\tthis._refresh();\n\t\tif ( previous !== this.element.val() ) {\n\t\t\tthis._trigger( \"change\" );\n\t\t}\n\t};\n}\n\n$.widget( \"ui.spinner\", {\n\tversion: \"1.12.1\",\n\tdefaultElement: \"<input>\",\n\twidgetEventPrefix: \"spin\",\n\toptions: {\n\t\tclasses: {\n\t\t\t\"ui-spinner\": \"ui-corner-all\",\n\t\t\t\"ui-spinner-down\": \"ui-corner-br\",\n\t\t\t\"ui-spinner-up\": \"ui-corner-tr\"\n\t\t},\n\t\tculture: null,\n\t\ticons: {\n\t\t\tdown: \"ui-icon-triangle-1-s\",\n\t\t\tup: \"ui-icon-triangle-1-n\"\n\t\t},\n\t\tincremental: true,\n\t\tmax: null,\n\t\tmin: null,\n\t\tnumberFormat: null,\n\t\tpage: 10,\n\t\tstep: 1,\n\n\t\tchange: null,\n\t\tspin: null,\n\t\tstart: null,\n\t\tstop: null\n\t},\n\n\t_create: function() {\n\n\t\t// handle string values that need to be parsed\n\t\tthis._setOption( \"max\", this.options.max );\n\t\tthis._setOption( \"min\", this.options.min );\n\t\tthis._setOption( \"step\", this.options.step );\n\n\t\t// Only format if there is a value, prevents the field from being marked\n\t\t// as invalid in Firefox, see #9573.\n\t\tif ( this.value() !== \"\" ) {\n\n\t\t\t// Format the value, but don't constrain.\n\t\t\tthis._value( this.element.val(), true );\n\t\t}\n\n\t\tthis._draw();\n\t\tthis._on( this._events );\n\t\tthis._refresh();\n\n\t\t// Turning off autocomplete prevents the browser from remembering the\n\t\t// value when navigating through history, so we re-enable autocomplete\n\t\t// if the page is unloaded before the widget is destroyed. #7790\n\t\tthis._on( this.window, {\n\t\t\tbeforeunload: function() {\n\t\t\t\tthis.element.removeAttr( \"autocomplete\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t_getCreateOptions: function() {\n\t\tvar options = this._super();\n\t\tvar element = this.element;\n\n\t\t$.each( [ \"min\", \"max\", \"step\" ], function( i, option ) {\n\t\t\tvar value = element.attr( option );\n\t\t\tif ( value != null && value.length ) {\n\t\t\t\toptions[ option ] = value;\n\t\t\t}\n\t\t} );\n\n\t\treturn options;\n\t},\n\n\t_events: {\n\t\tkeydown: function( event ) {\n\t\t\tif ( this._start( event ) && this._keydown( event ) ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t},\n\t\tkeyup: \"_stop\",\n\t\tfocus: function() {\n\t\t\tthis.previous = this.element.val();\n\t\t},\n\t\tblur: function( event ) {\n\t\t\tif ( this.cancelBlur ) {\n\t\t\t\tdelete this.cancelBlur;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._stop();\n\t\t\tthis._refresh();\n\t\t\tif ( this.previous !== this.element.val() ) {\n\t\t\t\tthis._trigger( \"change\", event );\n\t\t\t}\n\t\t},\n\t\tmousewheel: function( event, delta ) {\n\t\t\tif ( !delta ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( !this.spinning && !this._start( event ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tthis._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );\n\t\t\tclearTimeout( this.mousewheelTimer );\n\t\t\tthis.mousewheelTimer = this._delay( function() {\n\t\t\t\tif ( this.spinning ) {\n\t\t\t\t\tthis._stop( event );\n\t\t\t\t}\n\t\t\t}, 100 );\n\t\t\tevent.preventDefault();\n\t\t},\n\t\t\"mousedown .ui-spinner-button\": function( event ) {\n\t\t\tvar previous;\n\n\t\t\t// We never want the buttons to have focus; whenever the user is\n\t\t\t// interacting with the spinner, the focus should be on the input.\n\t\t\t// If the input is focused then this.previous is properly set from\n\t\t\t// when the input first received focus. If the input is not focused\n\t\t\t// then we need to set this.previous based on the value before spinning.\n\t\t\tprevious = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ?\n\t\t\t\tthis.previous : this.element.val();\n\t\t\tfunction checkFocus() {\n\t\t\t\tvar isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] );\n\t\t\t\tif ( !isActive ) {\n\t\t\t\t\tthis.element.trigger( \"focus\" );\n\t\t\t\t\tthis.previous = previous;\n\n\t\t\t\t\t// support: IE\n\t\t\t\t\t// IE sets focus asynchronously, so we need to check if focus\n\t\t\t\t\t// moved off of the input because the user clicked on the button.\n\t\t\t\t\tthis._delay( function() {\n\t\t\t\t\t\tthis.previous = previous;\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Ensure focus is on (or stays on) the text field\n\t\t\tevent.preventDefault();\n\t\t\tcheckFocus.call( this );\n\n\t\t\t// Support: IE\n\t\t\t// IE doesn't prevent moving focus even with event.preventDefault()\n\t\t\t// so we set a flag to know when we should ignore the blur event\n\t\t\t// and check (again) if focus moved off of the input.\n\t\t\tthis.cancelBlur = true;\n\t\t\tthis._delay( function() {\n\t\t\t\tdelete this.cancelBlur;\n\t\t\t\tcheckFocus.call( this );\n\t\t\t} );\n\n\t\t\tif ( this._start( event ) === false ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis._repeat( null, $( event.currentTarget )\n\t\t\t\t.hasClass( \"ui-spinner-up\" ) ? 1 : -1, event );\n\t\t},\n\t\t\"mouseup .ui-spinner-button\": \"_stop\",\n\t\t\"mouseenter .ui-spinner-button\": function( event ) {\n\n\t\t\t// button will add ui-state-active if mouse was down while mouseleave and kept down\n\t\t\tif ( !$( event.currentTarget ).hasClass( \"ui-state-active\" ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this._start( event ) === false ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthis._repeat( null, $( event.currentTarget )\n\t\t\t\t.hasClass( \"ui-spinner-up\" ) ? 1 : -1, event );\n\t\t},\n\n\t\t// TODO: do we really want to consider this a stop?\n\t\t// shouldn't we just stop the repeater and wait until mouseup before\n\t\t// we trigger the stop event?\n\t\t\"mouseleave .ui-spinner-button\": \"_stop\"\n\t},\n\n\t// Support mobile enhanced option and make backcompat more sane\n\t_enhance: function() {\n\t\tthis.uiSpinner = this.element\n\t\t\t.attr( \"autocomplete\", \"off\" )\n\t\t\t.wrap( \"<span>\" )\n\t\t\t.parent()\n\n\t\t\t\t// Add buttons\n\t\t\t\t.append(\n\t\t\t\t\t\"<a></a><a></a>\"\n\t\t\t\t);\n\t},\n\n\t_draw: function() {\n\t\tthis._enhance();\n\n\t\tthis._addClass( this.uiSpinner, \"ui-spinner\", \"ui-widget ui-widget-content\" );\n\t\tthis._addClass( \"ui-spinner-input\" );\n\n\t\tthis.element.attr( \"role\", \"spinbutton\" );\n\n\t\t// Button bindings\n\t\tthis.buttons = this.uiSpinner.children( \"a\" )\n\t\t\t.attr( \"tabIndex\", -1 )\n\t\t\t.attr( \"aria-hidden\", true )\n\t\t\t.button( {\n\t\t\t\tclasses: {\n\t\t\t\t\t\"ui-button\": \"\"\n\t\t\t\t}\n\t\t\t} );\n\n\t\t// TODO: Right now button does not support classes this is already updated in button PR\n\t\tthis._removeClass( this.buttons, \"ui-corner-all\" );\n\n\t\tthis._addClass( this.buttons.first(), \"ui-spinner-button ui-spinner-up\" );\n\t\tthis._addClass( this.buttons.last(), \"ui-spinner-button ui-spinner-down\" );\n\t\tthis.buttons.first().button( {\n\t\t\t\"icon\": this.options.icons.up,\n\t\t\t\"showLabel\": false\n\t\t} );\n\t\tthis.buttons.last().button( {\n\t\t\t\"icon\": this.options.icons.down,\n\t\t\t\"showLabel\": false\n\t\t} );\n\n\t\t// IE 6 doesn't understand height: 50% for the buttons\n\t\t// unless the wrapper has an explicit height\n\t\tif ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&\n\t\t\t\tthis.uiSpinner.height() > 0 ) {\n\t\t\tthis.uiSpinner.height( this.uiSpinner.height() );\n\t\t}\n\t},\n\n\t_keydown: function( event ) {\n\t\tvar options = this.options,\n\t\t\tkeyCode = $.ui.keyCode;\n\n\t\tswitch ( event.keyCode ) {\n\t\tcase keyCode.UP:\n\t\t\tthis._repeat( null, 1, event );\n\t\t\treturn true;\n\t\tcase keyCode.DOWN:\n\t\t\tthis._repeat( null, -1, event );\n\t\t\treturn true;\n\t\tcase keyCode.PAGE_UP:\n\t\t\tthis._repeat( null, options.page, event );\n\t\t\treturn true;\n\t\tcase keyCode.PAGE_DOWN:\n\t\t\tthis._repeat( null, -options.page, event );\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_start: function( event ) {\n\t\tif ( !this.spinning && this._trigger( \"start\", event ) === false ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( !this.counter ) {\n\t\t\tthis.counter = 1;\n\t\t}\n\t\tthis.spinning = true;\n\t\treturn true;\n\t},\n\n\t_repeat: function( i, steps, event ) {\n\t\ti = i || 500;\n\n\t\tclearTimeout( this.timer );\n\t\tthis.timer = this._delay( function() {\n\t\t\tthis._repeat( 40, steps, event );\n\t\t}, i );\n\n\t\tthis._spin( steps * this.options.step, event );\n\t},\n\n\t_spin: function( step, event ) {\n\t\tvar value = this.value() || 0;\n\n\t\tif ( !this.counter ) {\n\t\t\tthis.counter = 1;\n\t\t}\n\n\t\tvalue = this._adjustValue( value + step * this._increment( this.counter ) );\n\n\t\tif ( !this.spinning || this._trigger( \"spin\", event, { value: value } ) !== false ) {\n\t\t\tthis._value( value );\n\t\t\tthis.counter++;\n\t\t}\n\t},\n\n\t_increment: function( i ) {\n\t\tvar incremental = this.options.incremental;\n\n\t\tif ( incremental ) {\n\t\t\treturn $.isFunction( incremental ) ?\n\t\t\t\tincremental( i ) :\n\t\t\t\tMath.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );\n\t\t}\n\n\t\treturn 1;\n\t},\n\n\t_precision: function() {\n\t\tvar precision = this._precisionOf( this.options.step );\n\t\tif ( this.options.min !== null ) {\n\t\t\tprecision = Math.max( precision, this._precisionOf( this.options.min ) );\n\t\t}\n\t\treturn precision;\n\t},\n\n\t_precisionOf: function( num ) {\n\t\tvar str = num.toString(),\n\t\t\tdecimal = str.indexOf( \".\" );\n\t\treturn decimal === -1 ? 0 : str.length - decimal - 1;\n\t},\n\n\t_adjustValue: function( value ) {\n\t\tvar base, aboveMin,\n\t\t\toptions = this.options;\n\n\t\t// Make sure we're at a valid step\n\t\t// - find out where we are relative to the base (min or 0)\n\t\tbase = options.min !== null ? options.min : 0;\n\t\taboveMin = value - base;\n\n\t\t// - round to the nearest step\n\t\taboveMin = Math.round( aboveMin / options.step ) * options.step;\n\n\t\t// - rounding is based on 0, so adjust back to our base\n\t\tvalue = base + aboveMin;\n\n\t\t// Fix precision from bad JS floating point math\n\t\tvalue = parseFloat( value.toFixed( this._precision() ) );\n\n\t\t// Clamp the value\n\t\tif ( options.max !== null && value > options.max ) {\n\t\t\treturn options.max;\n\t\t}\n\t\tif ( options.min !== null && value < options.min ) {\n\t\t\treturn options.min;\n\t\t}\n\n\t\treturn value;\n\t},\n\n\t_stop: function( event ) {\n\t\tif ( !this.spinning ) {\n\t\t\treturn;\n\t\t}\n\n\t\tclearTimeout( this.timer );\n\t\tclearTimeout( this.mousewheelTimer );\n\t\tthis.counter = 0;\n\t\tthis.spinning = false;\n\t\tthis._trigger( \"stop\", event );\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tvar prevValue, first, last;\n\n\t\tif ( key === \"culture\" || key === \"numberFormat\" ) {\n\t\t\tprevValue = this._parse( this.element.val() );\n\t\t\tthis.options[ key ] = value;\n\t\t\tthis.element.val( this._format( prevValue ) );\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key === \"max\" || key === \"min\" || key === \"step\" ) {\n\t\t\tif ( typeof value === \"string\" ) {\n\t\t\t\tvalue = this._parse( value );\n\t\t\t}\n\t\t}\n\t\tif ( key === \"icons\" ) {\n\t\t\tfirst = this.buttons.first().find( \".ui-icon\" );\n\t\t\tthis._removeClass( first, null, this.options.icons.up );\n\t\t\tthis._addClass( first, null, value.up );\n\t\t\tlast = this.buttons.last().find( \".ui-icon\" );\n\t\t\tthis._removeClass( last, null, this.options.icons.down );\n\t\t\tthis._addClass( last, null, value.down );\n\t\t}\n\n\t\tthis._super( key, value );\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis._super( value );\n\n\t\tthis._toggleClass( this.uiSpinner, null, \"ui-state-disabled\", !!value );\n\t\tthis.element.prop( \"disabled\", !!value );\n\t\tthis.buttons.button( value ? \"disable\" : \"enable\" );\n\t},\n\n\t_setOptions: spinnerModifer( function( options ) {\n\t\tthis._super( options );\n\t} ),\n\n\t_parse: function( val ) {\n\t\tif ( typeof val === \"string\" && val !== \"\" ) {\n\t\t\tval = window.Globalize && this.options.numberFormat ?\n\t\t\t\tGlobalize.parseFloat( val, 10, this.options.culture ) : +val;\n\t\t}\n\t\treturn val === \"\" || isNaN( val ) ? null : val;\n\t},\n\n\t_format: function( value ) {\n\t\tif ( value === \"\" ) {\n\t\t\treturn \"\";\n\t\t}\n\t\treturn window.Globalize && this.options.numberFormat ?\n\t\t\tGlobalize.format( value, this.options.numberFormat, this.options.culture ) :\n\t\t\tvalue;\n\t},\n\n\t_refresh: function() {\n\t\tthis.element.attr( {\n\t\t\t\"aria-valuemin\": this.options.min,\n\t\t\t\"aria-valuemax\": this.options.max,\n\n\t\t\t// TODO: what should we do with values that can't be parsed?\n\t\t\t\"aria-valuenow\": this._parse( this.element.val() )\n\t\t} );\n\t},\n\n\tisValid: function() {\n\t\tvar value = this.value();\n\n\t\t// Null is invalid\n\t\tif ( value === null ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If value gets adjusted, it's invalid\n\t\treturn value === this._adjustValue( value );\n\t},\n\n\t// Update the value without triggering change\n\t_value: function( value, allowAny ) {\n\t\tvar parsed;\n\t\tif ( value !== \"\" ) {\n\t\t\tparsed = this._parse( value );\n\t\t\tif ( parsed !== null ) {\n\t\t\t\tif ( !allowAny ) {\n\t\t\t\t\tparsed = this._adjustValue( parsed );\n\t\t\t\t}\n\t\t\t\tvalue = this._format( parsed );\n\t\t\t}\n\t\t}\n\t\tthis.element.val( value );\n\t\tthis._refresh();\n\t},\n\n\t_destroy: function() {\n\t\tthis.element\n\t\t\t.prop( \"disabled\", false )\n\t\t\t.removeAttr( \"autocomplete role aria-valuemin aria-valuemax aria-valuenow\" );\n\n\t\tthis.uiSpinner.replaceWith( this.element );\n\t},\n\n\tstepUp: spinnerModifer( function( steps ) {\n\t\tthis._stepUp( steps );\n\t} ),\n\t_stepUp: function( steps ) {\n\t\tif ( this._start() ) {\n\t\t\tthis._spin( ( steps || 1 ) * this.options.step );\n\t\t\tthis._stop();\n\t\t}\n\t},\n\n\tstepDown: spinnerModifer( function( steps ) {\n\t\tthis._stepDown( steps );\n\t} ),\n\t_stepDown: function( steps ) {\n\t\tif ( this._start() ) {\n\t\t\tthis._spin( ( steps || 1 ) * -this.options.step );\n\t\t\tthis._stop();\n\t\t}\n\t},\n\n\tpageUp: spinnerModifer( function( pages ) {\n\t\tthis._stepUp( ( pages || 1 ) * this.options.page );\n\t} ),\n\n\tpageDown: spinnerModifer( function( pages ) {\n\t\tthis._stepDown( ( pages || 1 ) * this.options.page );\n\t} ),\n\n\tvalue: function( newVal ) {\n\t\tif ( !arguments.length ) {\n\t\t\treturn this._parse( this.element.val() );\n\t\t}\n\t\tspinnerModifer( this._value ).call( this, newVal );\n\t},\n\n\twidget: function() {\n\t\treturn this.uiSpinner;\n\t}\n} );\n\n// DEPRECATED\n// TODO: switch return back to widget declaration at top of file when this is removed\nif ( $.uiBackCompat !== false ) {\n\n\t// Backcompat for spinner html extension points\n\t$.widget( \"ui.spinner\", $.ui.spinner, {\n\t\t_enhance: function() {\n\t\t\tthis.uiSpinner = this.element\n\t\t\t\t.attr( \"autocomplete\", \"off\" )\n\t\t\t\t.wrap( this._uiSpinnerHtml() )\n\t\t\t\t.parent()\n\n\t\t\t\t\t// Add buttons\n\t\t\t\t\t.append( this._buttonHtml() );\n\t\t},\n\t\t_uiSpinnerHtml: function() {\n\t\t\treturn \"<span>\";\n\t\t},\n\n\t\t_buttonHtml: function() {\n\t\t\treturn \"<a></a><a></a>\";\n\t\t}\n\t} );\n}\n\nvar widgetsSpinner = $.ui.spinner;\n\n\n/*!\n * jQuery UI Tabs 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Tabs\n//>>group: Widgets\n//>>description: Transforms a set of container elements into a tab structure.\n//>>docs: http://api.jqueryui.com/tabs/\n//>>demos: http://jqueryui.com/tabs/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/tabs.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.tabs\", {\n\tversion: \"1.12.1\",\n\tdelay: 300,\n\toptions: {\n\t\tactive: null,\n\t\tclasses: {\n\t\t\t\"ui-tabs\": \"ui-corner-all\",\n\t\t\t\"ui-tabs-nav\": \"ui-corner-all\",\n\t\t\t\"ui-tabs-panel\": \"ui-corner-bottom\",\n\t\t\t\"ui-tabs-tab\": \"ui-corner-top\"\n\t\t},\n\t\tcollapsible: false,\n\t\tevent: \"click\",\n\t\theightStyle: \"content\",\n\t\thide: null,\n\t\tshow: null,\n\n\t\t// Callbacks\n\t\tactivate: null,\n\t\tbeforeActivate: null,\n\t\tbeforeLoad: null,\n\t\tload: null\n\t},\n\n\t_isLocal: ( function() {\n\t\tvar rhash = /#.*$/;\n\n\t\treturn function( anchor ) {\n\t\t\tvar anchorUrl, locationUrl;\n\n\t\t\tanchorUrl = anchor.href.replace( rhash, \"\" );\n\t\t\tlocationUrl = location.href.replace( rhash, \"\" );\n\n\t\t\t// Decoding may throw an error if the URL isn't UTF-8 (#9518)\n\t\t\ttry {\n\t\t\t\tanchorUrl = decodeURIComponent( anchorUrl );\n\t\t\t} catch ( error ) {}\n\t\t\ttry {\n\t\t\t\tlocationUrl = decodeURIComponent( locationUrl );\n\t\t\t} catch ( error ) {}\n\n\t\t\treturn anchor.hash.length > 1 && anchorUrl === locationUrl;\n\t\t};\n\t} )(),\n\n\t_create: function() {\n\t\tvar that = this,\n\t\t\toptions = this.options;\n\n\t\tthis.running = false;\n\n\t\tthis._addClass( \"ui-tabs\", \"ui-widget ui-widget-content\" );\n\t\tthis._toggleClass( \"ui-tabs-collapsible\", null, options.collapsible );\n\n\t\tthis._processTabs();\n\t\toptions.active = this._initialActive();\n\n\t\t// Take disabling tabs via class attribute from HTML\n\t\t// into account and update option properly.\n\t\tif ( $.isArray( options.disabled ) ) {\n\t\t\toptions.disabled = $.unique( options.disabled.concat(\n\t\t\t\t$.map( this.tabs.filter( \".ui-state-disabled\" ), function( li ) {\n\t\t\t\t\treturn that.tabs.index( li );\n\t\t\t\t} )\n\t\t\t) ).sort();\n\t\t}\n\n\t\t// Check for length avoids error when initializing empty list\n\t\tif ( this.options.active !== false && this.anchors.length ) {\n\t\t\tthis.active = this._findActive( options.active );\n\t\t} else {\n\t\t\tthis.active = $();\n\t\t}\n\n\t\tthis._refresh();\n\n\t\tif ( this.active.length ) {\n\t\t\tthis.load( options.active );\n\t\t}\n\t},\n\n\t_initialActive: function() {\n\t\tvar active = this.options.active,\n\t\t\tcollapsible = this.options.collapsible,\n\t\t\tlocationHash = location.hash.substring( 1 );\n\n\t\tif ( active === null ) {\n\n\t\t\t// check the fragment identifier in the URL\n\t\t\tif ( locationHash ) {\n\t\t\t\tthis.tabs.each( function( i, tab ) {\n\t\t\t\t\tif ( $( tab ).attr( \"aria-controls\" ) === locationHash ) {\n\t\t\t\t\t\tactive = i;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// Check for a tab marked active via a class\n\t\t\tif ( active === null ) {\n\t\t\t\tactive = this.tabs.index( this.tabs.filter( \".ui-tabs-active\" ) );\n\t\t\t}\n\n\t\t\t// No active tab, set to false\n\t\t\tif ( active === null || active === -1 ) {\n\t\t\t\tactive = this.tabs.length ? 0 : false;\n\t\t\t}\n\t\t}\n\n\t\t// Handle numbers: negative, out of range\n\t\tif ( active !== false ) {\n\t\t\tactive = this.tabs.index( this.tabs.eq( active ) );\n\t\t\tif ( active === -1 ) {\n\t\t\t\tactive = collapsible ? false : 0;\n\t\t\t}\n\t\t}\n\n\t\t// Don't allow collapsible: false and active: false\n\t\tif ( !collapsible && active === false && this.anchors.length ) {\n\t\t\tactive = 0;\n\t\t}\n\n\t\treturn active;\n\t},\n\n\t_getCreateEventData: function() {\n\t\treturn {\n\t\t\ttab: this.active,\n\t\t\tpanel: !this.active.length ? $() : this._getPanelForTab( this.active )\n\t\t};\n\t},\n\n\t_tabKeydown: function( event ) {\n\t\tvar focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( \"li\" ),\n\t\t\tselectedIndex = this.tabs.index( focusedTab ),\n\t\t\tgoingForward = true;\n\n\t\tif ( this._handlePageNav( event ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ( event.keyCode ) {\n\t\tcase $.ui.keyCode.RIGHT:\n\t\tcase $.ui.keyCode.DOWN:\n\t\t\tselectedIndex++;\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.UP:\n\t\tcase $.ui.keyCode.LEFT:\n\t\t\tgoingForward = false;\n\t\t\tselectedIndex--;\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.END:\n\t\t\tselectedIndex = this.anchors.length - 1;\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.HOME:\n\t\t\tselectedIndex = 0;\n\t\t\tbreak;\n\t\tcase $.ui.keyCode.SPACE:\n\n\t\t\t// Activate only, no collapsing\n\t\t\tevent.preventDefault();\n\t\t\tclearTimeout( this.activating );\n\t\t\tthis._activate( selectedIndex );\n\t\t\treturn;\n\t\tcase $.ui.keyCode.ENTER:\n\n\t\t\t// Toggle (cancel delayed activation, allow collapsing)\n\t\t\tevent.preventDefault();\n\t\t\tclearTimeout( this.activating );\n\n\t\t\t// Determine if we should collapse or activate\n\t\t\tthis._activate( selectedIndex === this.options.active ? false : selectedIndex );\n\t\t\treturn;\n\t\tdefault:\n\t\t\treturn;\n\t\t}\n\n\t\t// Focus the appropriate tab, based on which key was pressed\n\t\tevent.preventDefault();\n\t\tclearTimeout( this.activating );\n\t\tselectedIndex = this._focusNextTab( selectedIndex, goingForward );\n\n\t\t// Navigating with control/command key will prevent automatic activation\n\t\tif ( !event.ctrlKey && !event.metaKey ) {\n\n\t\t\t// Update aria-selected immediately so that AT think the tab is already selected.\n\t\t\t// Otherwise AT may confuse the user by stating that they need to activate the tab,\n\t\t\t// but the tab will already be activated by the time the announcement finishes.\n\t\t\tfocusedTab.attr( \"aria-selected\", \"false\" );\n\t\t\tthis.tabs.eq( selectedIndex ).attr( \"aria-selected\", \"true\" );\n\n\t\t\tthis.activating = this._delay( function() {\n\t\t\t\tthis.option( \"active\", selectedIndex );\n\t\t\t}, this.delay );\n\t\t}\n\t},\n\n\t_panelKeydown: function( event ) {\n\t\tif ( this._handlePageNav( event ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Ctrl+up moves focus to the current tab\n\t\tif ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {\n\t\t\tevent.preventDefault();\n\t\t\tthis.active.trigger( \"focus\" );\n\t\t}\n\t},\n\n\t// Alt+page up/down moves focus to the previous/next tab (and activates)\n\t_handlePageNav: function( event ) {\n\t\tif ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {\n\t\t\tthis._activate( this._focusNextTab( this.options.active - 1, false ) );\n\t\t\treturn true;\n\t\t}\n\t\tif ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {\n\t\t\tthis._activate( this._focusNextTab( this.options.active + 1, true ) );\n\t\t\treturn true;\n\t\t}\n\t},\n\n\t_findNextTab: function( index, goingForward ) {\n\t\tvar lastTabIndex = this.tabs.length - 1;\n\n\t\tfunction constrain() {\n\t\t\tif ( index > lastTabIndex ) {\n\t\t\t\tindex = 0;\n\t\t\t}\n\t\t\tif ( index < 0 ) {\n\t\t\t\tindex = lastTabIndex;\n\t\t\t}\n\t\t\treturn index;\n\t\t}\n\n\t\twhile ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {\n\t\t\tindex = goingForward ? index + 1 : index - 1;\n\t\t}\n\n\t\treturn index;\n\t},\n\n\t_focusNextTab: function( index, goingForward ) {\n\t\tindex = this._findNextTab( index, goingForward );\n\t\tthis.tabs.eq( index ).trigger( \"focus\" );\n\t\treturn index;\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tif ( key === \"active\" ) {\n\n\t\t\t// _activate() will handle invalid values and update this.options\n\t\t\tthis._activate( value );\n\t\t\treturn;\n\t\t}\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"collapsible\" ) {\n\t\t\tthis._toggleClass( \"ui-tabs-collapsible\", null, value );\n\n\t\t\t// Setting collapsible: false while collapsed; open first panel\n\t\t\tif ( !value && this.options.active === false ) {\n\t\t\t\tthis._activate( 0 );\n\t\t\t}\n\t\t}\n\n\t\tif ( key === \"event\" ) {\n\t\t\tthis._setupEvents( value );\n\t\t}\n\n\t\tif ( key === \"heightStyle\" ) {\n\t\t\tthis._setupHeightStyle( value );\n\t\t}\n\t},\n\n\t_sanitizeSelector: function( hash ) {\n\t\treturn hash ? hash.replace( /[!\"$%&'()*+,.\\/:;<=>?@\\[\\]\\^`{|}~]/g, \"\\\\$&\" ) : \"\";\n\t},\n\n\trefresh: function() {\n\t\tvar options = this.options,\n\t\t\tlis = this.tablist.children( \":has(a[href])\" );\n\n\t\t// Get disabled tabs from class attribute from HTML\n\t\t// this will get converted to a boolean if needed in _refresh()\n\t\toptions.disabled = $.map( lis.filter( \".ui-state-disabled\" ), function( tab ) {\n\t\t\treturn lis.index( tab );\n\t\t} );\n\n\t\tthis._processTabs();\n\n\t\t// Was collapsed or no tabs\n\t\tif ( options.active === false || !this.anchors.length ) {\n\t\t\toptions.active = false;\n\t\t\tthis.active = $();\n\n\t\t// was active, but active tab is gone\n\t\t} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {\n\n\t\t\t// all remaining tabs are disabled\n\t\t\tif ( this.tabs.length === options.disabled.length ) {\n\t\t\t\toptions.active = false;\n\t\t\t\tthis.active = $();\n\n\t\t\t// activate previous tab\n\t\t\t} else {\n\t\t\t\tthis._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );\n\t\t\t}\n\n\t\t// was active, active tab still exists\n\t\t} else {\n\n\t\t\t// make sure active index is correct\n\t\t\toptions.active = this.tabs.index( this.active );\n\t\t}\n\n\t\tthis._refresh();\n\t},\n\n\t_refresh: function() {\n\t\tthis._setOptionDisabled( this.options.disabled );\n\t\tthis._setupEvents( this.options.event );\n\t\tthis._setupHeightStyle( this.options.heightStyle );\n\n\t\tthis.tabs.not( this.active ).attr( {\n\t\t\t\"aria-selected\": \"false\",\n\t\t\t\"aria-expanded\": \"false\",\n\t\t\ttabIndex: -1\n\t\t} );\n\t\tthis.panels.not( this._getPanelForTab( this.active ) )\n\t\t\t.hide()\n\t\t\t.attr( {\n\t\t\t\t\"aria-hidden\": \"true\"\n\t\t\t} );\n\n\t\t// Make sure one tab is in the tab order\n\t\tif ( !this.active.length ) {\n\t\t\tthis.tabs.eq( 0 ).attr( \"tabIndex\", 0 );\n\t\t} else {\n\t\t\tthis.active\n\t\t\t\t.attr( {\n\t\t\t\t\t\"aria-selected\": \"true\",\n\t\t\t\t\t\"aria-expanded\": \"true\",\n\t\t\t\t\ttabIndex: 0\n\t\t\t\t} );\n\t\t\tthis._addClass( this.active, \"ui-tabs-active\", \"ui-state-active\" );\n\t\t\tthis._getPanelForTab( this.active )\n\t\t\t\t.show()\n\t\t\t\t.attr( {\n\t\t\t\t\t\"aria-hidden\": \"false\"\n\t\t\t\t} );\n\t\t}\n\t},\n\n\t_processTabs: function() {\n\t\tvar that = this,\n\t\t\tprevTabs = this.tabs,\n\t\t\tprevAnchors = this.anchors,\n\t\t\tprevPanels = this.panels;\n\n\t\tthis.tablist = this._getList().attr( \"role\", \"tablist\" );\n\t\tthis._addClass( this.tablist, \"ui-tabs-nav\",\n\t\t\t\"ui-helper-reset ui-helper-clearfix ui-widget-header\" );\n\n\t\t// Prevent users from focusing disabled tabs via click\n\t\tthis.tablist\n\t\t\t.on( \"mousedown\" + this.eventNamespace, \"> li\", function( event ) {\n\t\t\t\tif ( $( this ).is( \".ui-state-disabled\" ) ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t} )\n\n\t\t\t// Support: IE <9\n\t\t\t// Preventing the default action in mousedown doesn't prevent IE\n\t\t\t// from focusing the element, so if the anchor gets focused, blur.\n\t\t\t// We don't have to worry about focusing the previously focused\n\t\t\t// element since clicking on a non-focusable element should focus\n\t\t\t// the body anyway.\n\t\t\t.on( \"focus\" + this.eventNamespace, \".ui-tabs-anchor\", function() {\n\t\t\t\tif ( $( this ).closest( \"li\" ).is( \".ui-state-disabled\" ) ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t}\n\t\t\t} );\n\n\t\tthis.tabs = this.tablist.find( \"> li:has(a[href])\" )\n\t\t\t.attr( {\n\t\t\t\trole: \"tab\",\n\t\t\t\ttabIndex: -1\n\t\t\t} );\n\t\tthis._addClass( this.tabs, \"ui-tabs-tab\", \"ui-state-default\" );\n\n\t\tthis.anchors = this.tabs.map( function() {\n\t\t\treturn $( \"a\", this )[ 0 ];\n\t\t} )\n\t\t\t.attr( {\n\t\t\t\trole: \"presentation\",\n\t\t\t\ttabIndex: -1\n\t\t\t} );\n\t\tthis._addClass( this.anchors, \"ui-tabs-anchor\" );\n\n\t\tthis.panels = $();\n\n\t\tthis.anchors.each( function( i, anchor ) {\n\t\t\tvar selector, panel, panelId,\n\t\t\t\tanchorId = $( anchor ).uniqueId().attr( \"id\" ),\n\t\t\t\ttab = $( anchor ).closest( \"li\" ),\n\t\t\t\toriginalAriaControls = tab.attr( \"aria-controls\" );\n\n\t\t\t// Inline tab\n\t\t\tif ( that._isLocal( anchor ) ) {\n\t\t\t\tselector = anchor.hash;\n\t\t\t\tpanelId = selector.substring( 1 );\n\t\t\t\tpanel = that.element.find( that._sanitizeSelector( selector ) );\n\n\t\t\t// remote tab\n\t\t\t} else {\n\n\t\t\t\t// If the tab doesn't already have aria-controls,\n\t\t\t\t// generate an id by using a throw-away element\n\t\t\t\tpanelId = tab.attr( \"aria-controls\" ) || $( {} ).uniqueId()[ 0 ].id;\n\t\t\t\tselector = \"#\" + panelId;\n\t\t\t\tpanel = that.element.find( selector );\n\t\t\t\tif ( !panel.length ) {\n\t\t\t\t\tpanel = that._createPanel( panelId );\n\t\t\t\t\tpanel.insertAfter( that.panels[ i - 1 ] || that.tablist );\n\t\t\t\t}\n\t\t\t\tpanel.attr( \"aria-live\", \"polite\" );\n\t\t\t}\n\n\t\t\tif ( panel.length ) {\n\t\t\t\tthat.panels = that.panels.add( panel );\n\t\t\t}\n\t\t\tif ( originalAriaControls ) {\n\t\t\t\ttab.data( \"ui-tabs-aria-controls\", originalAriaControls );\n\t\t\t}\n\t\t\ttab.attr( {\n\t\t\t\t\"aria-controls\": panelId,\n\t\t\t\t\"aria-labelledby\": anchorId\n\t\t\t} );\n\t\t\tpanel.attr( \"aria-labelledby\", anchorId );\n\t\t} );\n\n\t\tthis.panels.attr( \"role\", \"tabpanel\" );\n\t\tthis._addClass( this.panels, \"ui-tabs-panel\", \"ui-widget-content\" );\n\n\t\t// Avoid memory leaks (#10056)\n\t\tif ( prevTabs ) {\n\t\t\tthis._off( prevTabs.not( this.tabs ) );\n\t\t\tthis._off( prevAnchors.not( this.anchors ) );\n\t\t\tthis._off( prevPanels.not( this.panels ) );\n\t\t}\n\t},\n\n\t// Allow overriding how to find the list for rare usage scenarios (#7715)\n\t_getList: function() {\n\t\treturn this.tablist || this.element.find( \"ol, ul\" ).eq( 0 );\n\t},\n\n\t_createPanel: function( id ) {\n\t\treturn $( \"<div>\" )\n\t\t\t.attr( \"id\", id )\n\t\t\t.data( \"ui-tabs-destroy\", true );\n\t},\n\n\t_setOptionDisabled: function( disabled ) {\n\t\tvar currentItem, li, i;\n\n\t\tif ( $.isArray( disabled ) ) {\n\t\t\tif ( !disabled.length ) {\n\t\t\t\tdisabled = false;\n\t\t\t} else if ( disabled.length === this.anchors.length ) {\n\t\t\t\tdisabled = true;\n\t\t\t}\n\t\t}\n\n\t\t// Disable tabs\n\t\tfor ( i = 0; ( li = this.tabs[ i ] ); i++ ) {\n\t\t\tcurrentItem = $( li );\n\t\t\tif ( disabled === true || $.inArray( i, disabled ) !== -1 ) {\n\t\t\t\tcurrentItem.attr( \"aria-disabled\", \"true\" );\n\t\t\t\tthis._addClass( currentItem, null, \"ui-state-disabled\" );\n\t\t\t} else {\n\t\t\t\tcurrentItem.removeAttr( \"aria-disabled\" );\n\t\t\t\tthis._removeClass( currentItem, null, \"ui-state-disabled\" );\n\t\t\t}\n\t\t}\n\n\t\tthis.options.disabled = disabled;\n\n\t\tthis._toggleClass( this.widget(), this.widgetFullName + \"-disabled\", null,\n\t\t\tdisabled === true );\n\t},\n\n\t_setupEvents: function( event ) {\n\t\tvar events = {};\n\t\tif ( event ) {\n\t\t\t$.each( event.split( \" \" ), function( index, eventName ) {\n\t\t\t\tevents[ eventName ] = \"_eventHandler\";\n\t\t\t} );\n\t\t}\n\n\t\tthis._off( this.anchors.add( this.tabs ).add( this.panels ) );\n\n\t\t// Always prevent the default action, even when disabled\n\t\tthis._on( true, this.anchors, {\n\t\t\tclick: function( event ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t} );\n\t\tthis._on( this.anchors, events );\n\t\tthis._on( this.tabs, { keydown: \"_tabKeydown\" } );\n\t\tthis._on( this.panels, { keydown: \"_panelKeydown\" } );\n\n\t\tthis._focusable( this.tabs );\n\t\tthis._hoverable( this.tabs );\n\t},\n\n\t_setupHeightStyle: function( heightStyle ) {\n\t\tvar maxHeight,\n\t\t\tparent = this.element.parent();\n\n\t\tif ( heightStyle === \"fill\" ) {\n\t\t\tmaxHeight = parent.height();\n\t\t\tmaxHeight -= this.element.outerHeight() - this.element.height();\n\n\t\t\tthis.element.siblings( \":visible\" ).each( function() {\n\t\t\t\tvar elem = $( this ),\n\t\t\t\t\tposition = elem.css( \"position\" );\n\n\t\t\t\tif ( position === \"absolute\" || position === \"fixed\" ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tmaxHeight -= elem.outerHeight( true );\n\t\t\t} );\n\n\t\t\tthis.element.children().not( this.panels ).each( function() {\n\t\t\t\tmaxHeight -= $( this ).outerHeight( true );\n\t\t\t} );\n\n\t\t\tthis.panels.each( function() {\n\t\t\t\t$( this ).height( Math.max( 0, maxHeight -\n\t\t\t\t\t$( this ).innerHeight() + $( this ).height() ) );\n\t\t\t} )\n\t\t\t\t.css( \"overflow\", \"auto\" );\n\t\t} else if ( heightStyle === \"auto\" ) {\n\t\t\tmaxHeight = 0;\n\t\t\tthis.panels.each( function() {\n\t\t\t\tmaxHeight = Math.max( maxHeight, $( this ).height( \"\" ).height() );\n\t\t\t} ).height( maxHeight );\n\t\t}\n\t},\n\n\t_eventHandler: function( event ) {\n\t\tvar options = this.options,\n\t\t\tactive = this.active,\n\t\t\tanchor = $( event.currentTarget ),\n\t\t\ttab = anchor.closest( \"li\" ),\n\t\t\tclickedIsActive = tab[ 0 ] === active[ 0 ],\n\t\t\tcollapsing = clickedIsActive && options.collapsible,\n\t\t\ttoShow = collapsing ? $() : this._getPanelForTab( tab ),\n\t\t\ttoHide = !active.length ? $() : this._getPanelForTab( active ),\n\t\t\teventData = {\n\t\t\t\toldTab: active,\n\t\t\t\toldPanel: toHide,\n\t\t\t\tnewTab: collapsing ? $() : tab,\n\t\t\t\tnewPanel: toShow\n\t\t\t};\n\n\t\tevent.preventDefault();\n\n\t\tif ( tab.hasClass( \"ui-state-disabled\" ) ||\n\n\t\t\t\t// tab is already loading\n\t\t\t\ttab.hasClass( \"ui-tabs-loading\" ) ||\n\n\t\t\t\t// can't switch durning an animation\n\t\t\t\tthis.running ||\n\n\t\t\t\t// click on active header, but not collapsible\n\t\t\t\t( clickedIsActive && !options.collapsible ) ||\n\n\t\t\t\t// allow canceling activation\n\t\t\t\t( this._trigger( \"beforeActivate\", event, eventData ) === false ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\toptions.active = collapsing ? false : this.tabs.index( tab );\n\n\t\tthis.active = clickedIsActive ? $() : tab;\n\t\tif ( this.xhr ) {\n\t\t\tthis.xhr.abort();\n\t\t}\n\n\t\tif ( !toHide.length && !toShow.length ) {\n\t\t\t$.error( \"jQuery UI Tabs: Mismatching fragment identifier.\" );\n\t\t}\n\n\t\tif ( toShow.length ) {\n\t\t\tthis.load( this.tabs.index( tab ), event );\n\t\t}\n\t\tthis._toggle( event, eventData );\n\t},\n\n\t// Handles show/hide for selecting tabs\n\t_toggle: function( event, eventData ) {\n\t\tvar that = this,\n\t\t\ttoShow = eventData.newPanel,\n\t\t\ttoHide = eventData.oldPanel;\n\n\t\tthis.running = true;\n\n\t\tfunction complete() {\n\t\t\tthat.running = false;\n\t\t\tthat._trigger( \"activate\", event, eventData );\n\t\t}\n\n\t\tfunction show() {\n\t\t\tthat._addClass( eventData.newTab.closest( \"li\" ), \"ui-tabs-active\", \"ui-state-active\" );\n\n\t\t\tif ( toShow.length && that.options.show ) {\n\t\t\t\tthat._show( toShow, that.options.show, complete );\n\t\t\t} else {\n\t\t\t\ttoShow.show();\n\t\t\t\tcomplete();\n\t\t\t}\n\t\t}\n\n\t\t// Start out by hiding, then showing, then completing\n\t\tif ( toHide.length && this.options.hide ) {\n\t\t\tthis._hide( toHide, this.options.hide, function() {\n\t\t\t\tthat._removeClass( eventData.oldTab.closest( \"li\" ),\n\t\t\t\t\t\"ui-tabs-active\", \"ui-state-active\" );\n\t\t\t\tshow();\n\t\t\t} );\n\t\t} else {\n\t\t\tthis._removeClass( eventData.oldTab.closest( \"li\" ),\n\t\t\t\t\"ui-tabs-active\", \"ui-state-active\" );\n\t\t\ttoHide.hide();\n\t\t\tshow();\n\t\t}\n\n\t\ttoHide.attr( \"aria-hidden\", \"true\" );\n\t\teventData.oldTab.attr( {\n\t\t\t\"aria-selected\": \"false\",\n\t\t\t\"aria-expanded\": \"false\"\n\t\t} );\n\n\t\t// If we're switching tabs, remove the old tab from the tab order.\n\t\t// If we're opening from collapsed state, remove the previous tab from the tab order.\n\t\t// If we're collapsing, then keep the collapsing tab in the tab order.\n\t\tif ( toShow.length && toHide.length ) {\n\t\t\teventData.oldTab.attr( \"tabIndex\", -1 );\n\t\t} else if ( toShow.length ) {\n\t\t\tthis.tabs.filter( function() {\n\t\t\t\treturn $( this ).attr( \"tabIndex\" ) === 0;\n\t\t\t} )\n\t\t\t\t.attr( \"tabIndex\", -1 );\n\t\t}\n\n\t\ttoShow.attr( \"aria-hidden\", \"false\" );\n\t\teventData.newTab.attr( {\n\t\t\t\"aria-selected\": \"true\",\n\t\t\t\"aria-expanded\": \"true\",\n\t\t\ttabIndex: 0\n\t\t} );\n\t},\n\n\t_activate: function( index ) {\n\t\tvar anchor,\n\t\t\tactive = this._findActive( index );\n\n\t\t// Trying to activate the already active panel\n\t\tif ( active[ 0 ] === this.active[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Trying to collapse, simulate a click on the current active header\n\t\tif ( !active.length ) {\n\t\t\tactive = this.active;\n\t\t}\n\n\t\tanchor = active.find( \".ui-tabs-anchor\" )[ 0 ];\n\t\tthis._eventHandler( {\n\t\t\ttarget: anchor,\n\t\t\tcurrentTarget: anchor,\n\t\t\tpreventDefault: $.noop\n\t\t} );\n\t},\n\n\t_findActive: function( index ) {\n\t\treturn index === false ? $() : this.tabs.eq( index );\n\t},\n\n\t_getIndex: function( index ) {\n\n\t\t// meta-function to give users option to provide a href string instead of a numerical index.\n\t\tif ( typeof index === \"string\" ) {\n\t\t\tindex = this.anchors.index( this.anchors.filter( \"[href$='\" +\n\t\t\t\t$.ui.escapeSelector( index ) + \"']\" ) );\n\t\t}\n\n\t\treturn index;\n\t},\n\n\t_destroy: function() {\n\t\tif ( this.xhr ) {\n\t\t\tthis.xhr.abort();\n\t\t}\n\n\t\tthis.tablist\n\t\t\t.removeAttr( \"role\" )\n\t\t\t.off( this.eventNamespace );\n\n\t\tthis.anchors\n\t\t\t.removeAttr( \"role tabIndex\" )\n\t\t\t.removeUniqueId();\n\n\t\tthis.tabs.add( this.panels ).each( function() {\n\t\t\tif ( $.data( this, \"ui-tabs-destroy\" ) ) {\n\t\t\t\t$( this ).remove();\n\t\t\t} else {\n\t\t\t\t$( this ).removeAttr( \"role tabIndex \" +\n\t\t\t\t\t\"aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded\" );\n\t\t\t}\n\t\t} );\n\n\t\tthis.tabs.each( function() {\n\t\t\tvar li = $( this ),\n\t\t\t\tprev = li.data( \"ui-tabs-aria-controls\" );\n\t\t\tif ( prev ) {\n\t\t\t\tli\n\t\t\t\t\t.attr( \"aria-controls\", prev )\n\t\t\t\t\t.removeData( \"ui-tabs-aria-controls\" );\n\t\t\t} else {\n\t\t\t\tli.removeAttr( \"aria-controls\" );\n\t\t\t}\n\t\t} );\n\n\t\tthis.panels.show();\n\n\t\tif ( this.options.heightStyle !== \"content\" ) {\n\t\t\tthis.panels.css( \"height\", \"\" );\n\t\t}\n\t},\n\n\tenable: function( index ) {\n\t\tvar disabled = this.options.disabled;\n\t\tif ( disabled === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( index === undefined ) {\n\t\t\tdisabled = false;\n\t\t} else {\n\t\t\tindex = this._getIndex( index );\n\t\t\tif ( $.isArray( disabled ) ) {\n\t\t\t\tdisabled = $.map( disabled, function( num ) {\n\t\t\t\t\treturn num !== index ? num : null;\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\tdisabled = $.map( this.tabs, function( li, num ) {\n\t\t\t\t\treturn num !== index ? num : null;\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\tthis._setOptionDisabled( disabled );\n\t},\n\n\tdisable: function( index ) {\n\t\tvar disabled = this.options.disabled;\n\t\tif ( disabled === true ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( index === undefined ) {\n\t\t\tdisabled = true;\n\t\t} else {\n\t\t\tindex = this._getIndex( index );\n\t\t\tif ( $.inArray( index, disabled ) !== -1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( $.isArray( disabled ) ) {\n\t\t\t\tdisabled = $.merge( [ index ], disabled ).sort();\n\t\t\t} else {\n\t\t\t\tdisabled = [ index ];\n\t\t\t}\n\t\t}\n\t\tthis._setOptionDisabled( disabled );\n\t},\n\n\tload: function( index, event ) {\n\t\tindex = this._getIndex( index );\n\t\tvar that = this,\n\t\t\ttab = this.tabs.eq( index ),\n\t\t\tanchor = tab.find( \".ui-tabs-anchor\" ),\n\t\t\tpanel = this._getPanelForTab( tab ),\n\t\t\teventData = {\n\t\t\t\ttab: tab,\n\t\t\t\tpanel: panel\n\t\t\t},\n\t\t\tcomplete = function( jqXHR, status ) {\n\t\t\t\tif ( status === \"abort\" ) {\n\t\t\t\t\tthat.panels.stop( false, true );\n\t\t\t\t}\n\n\t\t\t\tthat._removeClass( tab, \"ui-tabs-loading\" );\n\t\t\t\tpanel.removeAttr( \"aria-busy\" );\n\n\t\t\t\tif ( jqXHR === that.xhr ) {\n\t\t\t\t\tdelete that.xhr;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Not remote\n\t\tif ( this._isLocal( anchor[ 0 ] ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );\n\n\t\t// Support: jQuery <1.8\n\t\t// jQuery <1.8 returns false if the request is canceled in beforeSend,\n\t\t// but as of 1.8, $.ajax() always returns a jqXHR object.\n\t\tif ( this.xhr && this.xhr.statusText !== \"canceled\" ) {\n\t\t\tthis._addClass( tab, \"ui-tabs-loading\" );\n\t\t\tpanel.attr( \"aria-busy\", \"true\" );\n\n\t\t\tthis.xhr\n\t\t\t\t.done( function( response, status, jqXHR ) {\n\n\t\t\t\t\t// support: jQuery <1.8\n\t\t\t\t\t// http://bugs.jquery.com/ticket/11778\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tpanel.html( response );\n\t\t\t\t\t\tthat._trigger( \"load\", event, eventData );\n\n\t\t\t\t\t\tcomplete( jqXHR, status );\n\t\t\t\t\t}, 1 );\n\t\t\t\t} )\n\t\t\t\t.fail( function( jqXHR, status ) {\n\n\t\t\t\t\t// support: jQuery <1.8\n\t\t\t\t\t// http://bugs.jquery.com/ticket/11778\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tcomplete( jqXHR, status );\n\t\t\t\t\t}, 1 );\n\t\t\t\t} );\n\t\t}\n\t},\n\n\t_ajaxSettings: function( anchor, event, eventData ) {\n\t\tvar that = this;\n\t\treturn {\n\n\t\t\t// Support: IE <11 only\n\t\t\t// Strip any hash that exists to prevent errors with the Ajax request\n\t\t\turl: anchor.attr( \"href\" ).replace( /#.*$/, \"\" ),\n\t\t\tbeforeSend: function( jqXHR, settings ) {\n\t\t\t\treturn that._trigger( \"beforeLoad\", event,\n\t\t\t\t\t$.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );\n\t\t\t}\n\t\t};\n\t},\n\n\t_getPanelForTab: function( tab ) {\n\t\tvar id = $( tab ).attr( \"aria-controls\" );\n\t\treturn this.element.find( this._sanitizeSelector( \"#\" + id ) );\n\t}\n} );\n\n// DEPRECATED\n// TODO: Switch return back to widget declaration at top of file when this is removed\nif ( $.uiBackCompat !== false ) {\n\n\t// Backcompat for ui-tab class (now ui-tabs-tab)\n\t$.widget( \"ui.tabs\", $.ui.tabs, {\n\t\t_processTabs: function() {\n\t\t\tthis._superApply( arguments );\n\t\t\tthis._addClass( this.tabs, \"ui-tab\" );\n\t\t}\n\t} );\n}\n\nvar widgetsTabs = $.ui.tabs;\n\n\n/*!\n * jQuery UI Tooltip 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Tooltip\n//>>group: Widgets\n//>>description: Shows additional information for any element on hover or focus.\n//>>docs: http://api.jqueryui.com/tooltip/\n//>>demos: http://jqueryui.com/tooltip/\n//>>css.structure: ../../themes/base/core.css\n//>>css.structure: ../../themes/base/tooltip.css\n//>>css.theme: ../../themes/base/theme.css\n\n\n\n$.widget( \"ui.tooltip\", {\n\tversion: \"1.12.1\",\n\toptions: {\n\t\tclasses: {\n\t\t\t\"ui-tooltip\": \"ui-corner-all ui-widget-shadow\"\n\t\t},\n\t\tcontent: function() {\n\n\t\t\t// support: IE<9, Opera in jQuery <1.7\n\t\t\t// .text() can't accept undefined, so coerce to a string\n\t\t\tvar title = $( this ).attr( \"title\" ) || \"\";\n\n\t\t\t// Escape title, since we're going from an attribute to raw HTML\n\t\t\treturn $( \"<a>\" ).text( title ).html();\n\t\t},\n\t\thide: true,\n\n\t\t// Disabled elements have inconsistent behavior across browsers (#8661)\n\t\titems: \"[title]:not([disabled])\",\n\t\tposition: {\n\t\t\tmy: \"left top+15\",\n\t\t\tat: \"left bottom\",\n\t\t\tcollision: \"flipfit flip\"\n\t\t},\n\t\tshow: true,\n\t\ttrack: false,\n\n\t\t// Callbacks\n\t\tclose: null,\n\t\topen: null\n\t},\n\n\t_addDescribedBy: function( elem, id ) {\n\t\tvar describedby = ( elem.attr( \"aria-describedby\" ) || \"\" ).split( /\\s+/ );\n\t\tdescribedby.push( id );\n\t\telem\n\t\t\t.data( \"ui-tooltip-id\", id )\n\t\t\t.attr( \"aria-describedby\", $.trim( describedby.join( \" \" ) ) );\n\t},\n\n\t_removeDescribedBy: function( elem ) {\n\t\tvar id = elem.data( \"ui-tooltip-id\" ),\n\t\t\tdescribedby = ( elem.attr( \"aria-describedby\" ) || \"\" ).split( /\\s+/ ),\n\t\t\tindex = $.inArray( id, describedby );\n\n\t\tif ( index !== -1 ) {\n\t\t\tdescribedby.splice( index, 1 );\n\t\t}\n\n\t\telem.removeData( \"ui-tooltip-id\" );\n\t\tdescribedby = $.trim( describedby.join( \" \" ) );\n\t\tif ( describedby ) {\n\t\t\telem.attr( \"aria-describedby\", describedby );\n\t\t} else {\n\t\t\telem.removeAttr( \"aria-describedby\" );\n\t\t}\n\t},\n\n\t_create: function() {\n\t\tthis._on( {\n\t\t\tmouseover: \"open\",\n\t\t\tfocusin: \"open\"\n\t\t} );\n\n\t\t// IDs of generated tooltips, needed for destroy\n\t\tthis.tooltips = {};\n\n\t\t// IDs of parent tooltips where we removed the title attribute\n\t\tthis.parents = {};\n\n\t\t// Append the aria-live region so tooltips announce correctly\n\t\tthis.liveRegion = $( \"<div>\" )\n\t\t\t.attr( {\n\t\t\t\trole: \"log\",\n\t\t\t\t\"aria-live\": \"assertive\",\n\t\t\t\t\"aria-relevant\": \"additions\"\n\t\t\t} )\n\t\t\t.appendTo( this.document[ 0 ].body );\n\t\tthis._addClass( this.liveRegion, null, \"ui-helper-hidden-accessible\" );\n\n\t\tthis.disabledTitles = $( [] );\n\t},\n\n\t_setOption: function( key, value ) {\n\t\tvar that = this;\n\n\t\tthis._super( key, value );\n\n\t\tif ( key === \"content\" ) {\n\t\t\t$.each( this.tooltips, function( id, tooltipData ) {\n\t\t\t\tthat._updateContent( tooltipData.element );\n\t\t\t} );\n\t\t}\n\t},\n\n\t_setOptionDisabled: function( value ) {\n\t\tthis[ value ? \"_disable\" : \"_enable\" ]();\n\t},\n\n\t_disable: function() {\n\t\tvar that = this;\n\n\t\t// Close open tooltips\n\t\t$.each( this.tooltips, function( id, tooltipData ) {\n\t\t\tvar event = $.Event( \"blur\" );\n\t\t\tevent.target = event.currentTarget = tooltipData.element[ 0 ];\n\t\t\tthat.close( event, true );\n\t\t} );\n\n\t\t// Remove title attributes to prevent native tooltips\n\t\tthis.disabledTitles = this.disabledTitles.add(\n\t\t\tthis.element.find( this.options.items ).addBack()\n\t\t\t\t.filter( function() {\n\t\t\t\t\tvar element = $( this );\n\t\t\t\t\tif ( element.is( \"[title]\" ) ) {\n\t\t\t\t\t\treturn element\n\t\t\t\t\t\t\t.data( \"ui-tooltip-title\", element.attr( \"title\" ) )\n\t\t\t\t\t\t\t.removeAttr( \"title\" );\n\t\t\t\t\t}\n\t\t\t\t} )\n\t\t);\n\t},\n\n\t_enable: function() {\n\n\t\t// restore title attributes\n\t\tthis.disabledTitles.each( function() {\n\t\t\tvar element = $( this );\n\t\t\tif ( element.data( \"ui-tooltip-title\" ) ) {\n\t\t\t\telement.attr( \"title\", element.data( \"ui-tooltip-title\" ) );\n\t\t\t}\n\t\t} );\n\t\tthis.disabledTitles = $( [] );\n\t},\n\n\topen: function( event ) {\n\t\tvar that = this,\n\t\t\ttarget = $( event ? event.target : this.element )\n\n\t\t\t\t// we need closest here due to mouseover bubbling,\n\t\t\t\t// but always pointing at the same event target\n\t\t\t\t.closest( this.options.items );\n\n\t\t// No element to show a tooltip for or the tooltip is already open\n\t\tif ( !target.length || target.data( \"ui-tooltip-id\" ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( target.attr( \"title\" ) ) {\n\t\t\ttarget.data( \"ui-tooltip-title\", target.attr( \"title\" ) );\n\t\t}\n\n\t\ttarget.data( \"ui-tooltip-open\", true );\n\n\t\t// Kill parent tooltips, custom or native, for hover\n\t\tif ( event && event.type === \"mouseover\" ) {\n\t\t\ttarget.parents().each( function() {\n\t\t\t\tvar parent = $( this ),\n\t\t\t\t\tblurEvent;\n\t\t\t\tif ( parent.data( \"ui-tooltip-open\" ) ) {\n\t\t\t\t\tblurEvent = $.Event( \"blur\" );\n\t\t\t\t\tblurEvent.target = blurEvent.currentTarget = this;\n\t\t\t\t\tthat.close( blurEvent, true );\n\t\t\t\t}\n\t\t\t\tif ( parent.attr( \"title\" ) ) {\n\t\t\t\t\tparent.uniqueId();\n\t\t\t\t\tthat.parents[ this.id ] = {\n\t\t\t\t\t\telement: this,\n\t\t\t\t\t\ttitle: parent.attr( \"title\" )\n\t\t\t\t\t};\n\t\t\t\t\tparent.attr( \"title\", \"\" );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tthis._registerCloseHandlers( event, target );\n\t\tthis._updateContent( target, event );\n\t},\n\n\t_updateContent: function( target, event ) {\n\t\tvar content,\n\t\t\tcontentOption = this.options.content,\n\t\t\tthat = this,\n\t\t\teventType = event ? event.type : null;\n\n\t\tif ( typeof contentOption === \"string\" || contentOption.nodeType ||\n\t\t\t\tcontentOption.jquery ) {\n\t\t\treturn this._open( event, target, contentOption );\n\t\t}\n\n\t\tcontent = contentOption.call( target[ 0 ], function( response ) {\n\n\t\t\t// IE may instantly serve a cached response for ajax requests\n\t\t\t// delay this call to _open so the other call to _open runs first\n\t\t\tthat._delay( function() {\n\n\t\t\t\t// Ignore async response if tooltip was closed already\n\t\t\t\tif ( !target.data( \"ui-tooltip-open\" ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// JQuery creates a special event for focusin when it doesn't\n\t\t\t\t// exist natively. To improve performance, the native event\n\t\t\t\t// object is reused and the type is changed. Therefore, we can't\n\t\t\t\t// rely on the type being correct after the event finished\n\t\t\t\t// bubbling, so we set it back to the previous value. (#8740)\n\t\t\t\tif ( event ) {\n\t\t\t\t\tevent.type = eventType;\n\t\t\t\t}\n\t\t\t\tthis._open( event, target, response );\n\t\t\t} );\n\t\t} );\n\t\tif ( content ) {\n\t\t\tthis._open( event, target, content );\n\t\t}\n\t},\n\n\t_open: function( event, target, content ) {\n\t\tvar tooltipData, tooltip, delayedShow, a11yContent,\n\t\t\tpositionOption = $.extend( {}, this.options.position );\n\n\t\tif ( !content ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Content can be updated multiple times. If the tooltip already\n\t\t// exists, then just update the content and bail.\n\t\ttooltipData = this._find( target );\n\t\tif ( tooltipData ) {\n\t\t\ttooltipData.tooltip.find( \".ui-tooltip-content\" ).html( content );\n\t\t\treturn;\n\t\t}\n\n\t\t// If we have a title, clear it to prevent the native tooltip\n\t\t// we have to check first to avoid defining a title if none exists\n\t\t// (we don't want to cause an element to start matching [title])\n\t\t//\n\t\t// We use removeAttr only for key events, to allow IE to export the correct\n\t\t// accessible attributes. For mouse events, set to empty string to avoid\n\t\t// native tooltip showing up (happens only when removing inside mouseover).\n\t\tif ( target.is( \"[title]\" ) ) {\n\t\t\tif ( event && event.type === \"mouseover\" ) {\n\t\t\t\ttarget.attr( \"title\", \"\" );\n\t\t\t} else {\n\t\t\t\ttarget.removeAttr( \"title\" );\n\t\t\t}\n\t\t}\n\n\t\ttooltipData = this._tooltip( target );\n\t\ttooltip = tooltipData.tooltip;\n\t\tthis._addDescribedBy( target, tooltip.attr( \"id\" ) );\n\t\ttooltip.find( \".ui-tooltip-content\" ).html( content );\n\n\t\t// Support: Voiceover on OS X, JAWS on IE <= 9\n\t\t// JAWS announces deletions even when aria-relevant=\"additions\"\n\t\t// Voiceover will sometimes re-read the entire log region's contents from the beginning\n\t\tthis.liveRegion.children().hide();\n\t\ta11yContent = $( \"<div>\" ).html( tooltip.find( \".ui-tooltip-content\" ).html() );\n\t\ta11yContent.removeAttr( \"name\" ).find( \"[name]\" ).removeAttr( \"name\" );\n\t\ta11yContent.removeAttr( \"id\" ).find( \"[id]\" ).removeAttr( \"id\" );\n\t\ta11yContent.appendTo( this.liveRegion );\n\n\t\tfunction position( event ) {\n\t\t\tpositionOption.of = event;\n\t\t\tif ( tooltip.is( \":hidden\" ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttooltip.position( positionOption );\n\t\t}\n\t\tif ( this.options.track && event && /^mouse/.test( event.type ) ) {\n\t\t\tthis._on( this.document, {\n\t\t\t\tmousemove: position\n\t\t\t} );\n\n\t\t\t// trigger once to override element-relative positioning\n\t\t\tposition( event );\n\t\t} else {\n\t\t\ttooltip.position( $.extend( {\n\t\t\t\tof: target\n\t\t\t}, this.options.position ) );\n\t\t}\n\n\t\ttooltip.hide();\n\n\t\tthis._show( tooltip, this.options.show );\n\n\t\t// Handle tracking tooltips that are shown with a delay (#8644). As soon\n\t\t// as the tooltip is visible, position the tooltip using the most recent\n\t\t// event.\n\t\t// Adds the check to add the timers only when both delay and track options are set (#14682)\n\t\tif ( this.options.track && this.options.show && this.options.show.delay ) {\n\t\t\tdelayedShow = this.delayedShow = setInterval( function() {\n\t\t\t\tif ( tooltip.is( \":visible\" ) ) {\n\t\t\t\t\tposition( positionOption.of );\n\t\t\t\t\tclearInterval( delayedShow );\n\t\t\t\t}\n\t\t\t}, $.fx.interval );\n\t\t}\n\n\t\tthis._trigger( \"open\", event, { tooltip: tooltip } );\n\t},\n\n\t_registerCloseHandlers: function( event, target ) {\n\t\tvar events = {\n\t\t\tkeyup: function( event ) {\n\t\t\t\tif ( event.keyCode === $.ui.keyCode.ESCAPE ) {\n\t\t\t\t\tvar fakeEvent = $.Event( event );\n\t\t\t\t\tfakeEvent.currentTarget = target[ 0 ];\n\t\t\t\t\tthis.close( fakeEvent, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Only bind remove handler for delegated targets. Non-delegated\n\t\t// tooltips will handle this in destroy.\n\t\tif ( target[ 0 ] !== this.element[ 0 ] ) {\n\t\t\tevents.remove = function() {\n\t\t\t\tthis._removeTooltip( this._find( target ).tooltip );\n\t\t\t};\n\t\t}\n\n\t\tif ( !event || event.type === \"mouseover\" ) {\n\t\t\tevents.mouseleave = \"close\";\n\t\t}\n\t\tif ( !event || event.type === \"focusin\" ) {\n\t\t\tevents.focusout = \"close\";\n\t\t}\n\t\tthis._on( true, target, events );\n\t},\n\n\tclose: function( event ) {\n\t\tvar tooltip,\n\t\t\tthat = this,\n\t\t\ttarget = $( event ? event.currentTarget : this.element ),\n\t\t\ttooltipData = this._find( target );\n\n\t\t// The tooltip may already be closed\n\t\tif ( !tooltipData ) {\n\n\t\t\t// We set ui-tooltip-open immediately upon open (in open()), but only set the\n\t\t\t// additional data once there's actually content to show (in _open()). So even if the\n\t\t\t// tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in\n\t\t\t// the period between open() and _open().\n\t\t\ttarget.removeData( \"ui-tooltip-open\" );\n\t\t\treturn;\n\t\t}\n\n\t\ttooltip = tooltipData.tooltip;\n\n\t\t// Disabling closes the tooltip, so we need to track when we're closing\n\t\t// to avoid an infinite loop in case the tooltip becomes disabled on close\n\t\tif ( tooltipData.closing ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Clear the interval for delayed tracking tooltips\n\t\tclearInterval( this.delayedShow );\n\n\t\t// Only set title if we had one before (see comment in _open())\n\t\t// If the title attribute has changed since open(), don't restore\n\t\tif ( target.data( \"ui-tooltip-title\" ) && !target.attr( \"title\" ) ) {\n\t\t\ttarget.attr( \"title\", target.data( \"ui-tooltip-title\" ) );\n\t\t}\n\n\t\tthis._removeDescribedBy( target );\n\n\t\ttooltipData.hiding = true;\n\t\ttooltip.stop( true );\n\t\tthis._hide( tooltip, this.options.hide, function() {\n\t\t\tthat._removeTooltip( $( this ) );\n\t\t} );\n\n\t\ttarget.removeData( \"ui-tooltip-open\" );\n\t\tthis._off( target, \"mouseleave focusout keyup\" );\n\n\t\t// Remove 'remove' binding only on delegated targets\n\t\tif ( target[ 0 ] !== this.element[ 0 ] ) {\n\t\t\tthis._off( target, \"remove\" );\n\t\t}\n\t\tthis._off( this.document, \"mousemove\" );\n\n\t\tif ( event && event.type === \"mouseleave\" ) {\n\t\t\t$.each( this.parents, function( id, parent ) {\n\t\t\t\t$( parent.element ).attr( \"title\", parent.title );\n\t\t\t\tdelete that.parents[ id ];\n\t\t\t} );\n\t\t}\n\n\t\ttooltipData.closing = true;\n\t\tthis._trigger( \"close\", event, { tooltip: tooltip } );\n\t\tif ( !tooltipData.hiding ) {\n\t\t\ttooltipData.closing = false;\n\t\t}\n\t},\n\n\t_tooltip: function( element ) {\n\t\tvar tooltip = $( \"<div>\" ).attr( \"role\", \"tooltip\" ),\n\t\t\tcontent = $( \"<div>\" ).appendTo( tooltip ),\n\t\t\tid = tooltip.uniqueId().attr( \"id\" );\n\n\t\tthis._addClass( content, \"ui-tooltip-content\" );\n\t\tthis._addClass( tooltip, \"ui-tooltip\", \"ui-widget ui-widget-content\" );\n\n\t\ttooltip.appendTo( this._appendTo( element ) );\n\n\t\treturn this.tooltips[ id ] = {\n\t\t\telement: element,\n\t\t\ttooltip: tooltip\n\t\t};\n\t},\n\n\t_find: function( target ) {\n\t\tvar id = target.data( \"ui-tooltip-id\" );\n\t\treturn id ? this.tooltips[ id ] : null;\n\t},\n\n\t_removeTooltip: function( tooltip ) {\n\t\ttooltip.remove();\n\t\tdelete this.tooltips[ tooltip.attr( \"id\" ) ];\n\t},\n\n\t_appendTo: function( target ) {\n\t\tvar element = target.closest( \".ui-front, dialog\" );\n\n\t\tif ( !element.length ) {\n\t\t\telement = this.document[ 0 ].body;\n\t\t}\n\n\t\treturn element;\n\t},\n\n\t_destroy: function() {\n\t\tvar that = this;\n\n\t\t// Close open tooltips\n\t\t$.each( this.tooltips, function( id, tooltipData ) {\n\n\t\t\t// Delegate to close method to handle common cleanup\n\t\t\tvar event = $.Event( \"blur\" ),\n\t\t\t\telement = tooltipData.element;\n\t\t\tevent.target = event.currentTarget = element[ 0 ];\n\t\t\tthat.close( event, true );\n\n\t\t\t// Remove immediately; destroying an open tooltip doesn't use the\n\t\t\t// hide animation\n\t\t\t$( \"#\" + id ).remove();\n\n\t\t\t// Restore the title\n\t\t\tif ( element.data( \"ui-tooltip-title\" ) ) {\n\n\t\t\t\t// If the title attribute has changed since open(), don't restore\n\t\t\t\tif ( !element.attr( \"title\" ) ) {\n\t\t\t\t\telement.attr( \"title\", element.data( \"ui-tooltip-title\" ) );\n\t\t\t\t}\n\t\t\t\telement.removeData( \"ui-tooltip-title\" );\n\t\t\t}\n\t\t} );\n\t\tthis.liveRegion.remove();\n\t}\n} );\n\n// DEPRECATED\n// TODO: Switch return back to widget declaration at top of file when this is removed\nif ( $.uiBackCompat !== false ) {\n\n\t// Backcompat for tooltipClass option\n\t$.widget( \"ui.tooltip\", $.ui.tooltip, {\n\t\toptions: {\n\t\t\ttooltipClass: null\n\t\t},\n\t\t_tooltip: function() {\n\t\t\tvar tooltipData = this._superApply( arguments );\n\t\t\tif ( this.options.tooltipClass ) {\n\t\t\t\ttooltipData.tooltip.addClass( this.options.tooltipClass );\n\t\t\t}\n\t\t\treturn tooltipData;\n\t\t}\n\t} );\n}\n\nvar widgetsTooltip = $.ui.tooltip;\n\n\n/*!\n * jQuery UI Effects 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Effects Core\n//>>group: Effects\n// jscs:disable maximumLineLength\n//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.\n// jscs:enable maximumLineLength\n//>>docs: http://api.jqueryui.com/category/effects-core/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar dataSpace = \"ui-effects-\",\n\tdataSpaceStyle = \"ui-effects-style\",\n\tdataSpaceAnimated = \"ui-effects-animated\",\n\n\t// Create a local jQuery because jQuery Color relies on it and the\n\t// global may not exist with AMD and a custom build (#10199)\n\tjQuery = $;\n\n$.effects = {\n\teffect: {}\n};\n\n/*!\n * jQuery Color Animations v2.1.2\n * https://github.com/jquery/jquery-color\n *\n * Copyright 2014 jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * Date: Wed Jan 16 08:47:09 2013 -0600\n */\n( function( jQuery, undefined ) {\n\n\tvar stepHooks = \"backgroundColor borderBottomColor borderLeftColor borderRightColor \" +\n\t\t\"borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor\",\n\n\t// Plusequals test for += 100 -= 100\n\trplusequals = /^([\\-+])=\\s*(\\d+\\.?\\d*)/,\n\n\t// A set of RE's that can match strings and generate color tuples.\n\tstringParsers = [ {\n\t\t\tre: /rgba?\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\texecResult[ 1 ],\n\t\t\t\t\texecResult[ 2 ],\n\t\t\t\t\texecResult[ 3 ],\n\t\t\t\t\texecResult[ 4 ]\n\t\t\t\t];\n\t\t\t}\n\t\t}, {\n\t\t\tre: /rgba?\\(\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\texecResult[ 1 ] * 2.55,\n\t\t\t\t\texecResult[ 2 ] * 2.55,\n\t\t\t\t\texecResult[ 3 ] * 2.55,\n\t\t\t\t\texecResult[ 4 ]\n\t\t\t\t];\n\t\t\t}\n\t\t}, {\n\n\t\t\t// This regex ignores A-F because it's compared against an already lowercased string\n\t\t\tre: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\tparseInt( execResult[ 1 ], 16 ),\n\t\t\t\t\tparseInt( execResult[ 2 ], 16 ),\n\t\t\t\t\tparseInt( execResult[ 3 ], 16 )\n\t\t\t\t];\n\t\t\t}\n\t\t}, {\n\n\t\t\t// This regex ignores A-F because it's compared against an already lowercased string\n\t\t\tre: /#([a-f0-9])([a-f0-9])([a-f0-9])/,\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\tparseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),\n\t\t\t\t\tparseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),\n\t\t\t\t\tparseInt( execResult[ 3 ] + execResult[ 3 ], 16 )\n\t\t\t\t];\n\t\t\t}\n\t\t}, {\n\t\t\tre: /hsla?\\(\\s*(\\d+(?:\\.\\d+)?)\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,\n\t\t\tspace: \"hsla\",\n\t\t\tparse: function( execResult ) {\n\t\t\t\treturn [\n\t\t\t\t\texecResult[ 1 ],\n\t\t\t\t\texecResult[ 2 ] / 100,\n\t\t\t\t\texecResult[ 3 ] / 100,\n\t\t\t\t\texecResult[ 4 ]\n\t\t\t\t];\n\t\t\t}\n\t\t} ],\n\n\t// JQuery.Color( )\n\tcolor = jQuery.Color = function( color, green, blue, alpha ) {\n\t\treturn new jQuery.Color.fn.parse( color, green, blue, alpha );\n\t},\n\tspaces = {\n\t\trgba: {\n\t\t\tprops: {\n\t\t\t\tred: {\n\t\t\t\t\tidx: 0,\n\t\t\t\t\ttype: \"byte\"\n\t\t\t\t},\n\t\t\t\tgreen: {\n\t\t\t\t\tidx: 1,\n\t\t\t\t\ttype: \"byte\"\n\t\t\t\t},\n\t\t\t\tblue: {\n\t\t\t\t\tidx: 2,\n\t\t\t\t\ttype: \"byte\"\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\thsla: {\n\t\t\tprops: {\n\t\t\t\thue: {\n\t\t\t\t\tidx: 0,\n\t\t\t\t\ttype: \"degrees\"\n\t\t\t\t},\n\t\t\t\tsaturation: {\n\t\t\t\t\tidx: 1,\n\t\t\t\t\ttype: \"percent\"\n\t\t\t\t},\n\t\t\t\tlightness: {\n\t\t\t\t\tidx: 2,\n\t\t\t\t\ttype: \"percent\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tpropTypes = {\n\t\t\"byte\": {\n\t\t\tfloor: true,\n\t\t\tmax: 255\n\t\t},\n\t\t\"percent\": {\n\t\t\tmax: 1\n\t\t},\n\t\t\"degrees\": {\n\t\t\tmod: 360,\n\t\t\tfloor: true\n\t\t}\n\t},\n\tsupport = color.support = {},\n\n\t// Element for support tests\n\tsupportElem = jQuery( \"<p>\" )[ 0 ],\n\n\t// Colors = jQuery.Color.names\n\tcolors,\n\n\t// Local aliases of functions called often\n\teach = jQuery.each;\n\n// Determine rgba support immediately\nsupportElem.style.cssText = \"background-color:rgba(1,1,1,.5)\";\nsupport.rgba = supportElem.style.backgroundColor.indexOf( \"rgba\" ) > -1;\n\n// Define cache name and alpha properties\n// for rgba and hsla spaces\neach( spaces, function( spaceName, space ) {\n\tspace.cache = \"_\" + spaceName;\n\tspace.props.alpha = {\n\t\tidx: 3,\n\t\ttype: \"percent\",\n\t\tdef: 1\n\t};\n} );\n\nfunction clamp( value, prop, allowEmpty ) {\n\tvar type = propTypes[ prop.type ] || {};\n\n\tif ( value == null ) {\n\t\treturn ( allowEmpty || !prop.def ) ? null : prop.def;\n\t}\n\n\t// ~~ is an short way of doing floor for positive numbers\n\tvalue = type.floor ? ~~value : parseFloat( value );\n\n\t// IE will pass in empty strings as value for alpha,\n\t// which will hit this case\n\tif ( isNaN( value ) ) {\n\t\treturn prop.def;\n\t}\n\n\tif ( type.mod ) {\n\n\t\t// We add mod before modding to make sure that negatives values\n\t\t// get converted properly: -10 -> 350\n\t\treturn ( value + type.mod ) % type.mod;\n\t}\n\n\t// For now all property types without mod have min and max\n\treturn 0 > value ? 0 : type.max < value ? type.max : value;\n}\n\nfunction stringParse( string ) {\n\tvar inst = color(),\n\t\trgba = inst._rgba = [];\n\n\tstring = string.toLowerCase();\n\n\teach( stringParsers, function( i, parser ) {\n\t\tvar parsed,\n\t\t\tmatch = parser.re.exec( string ),\n\t\t\tvalues = match && parser.parse( match ),\n\t\t\tspaceName = parser.space || \"rgba\";\n\n\t\tif ( values ) {\n\t\t\tparsed = inst[ spaceName ]( values );\n\n\t\t\t// If this was an rgba parse the assignment might happen twice\n\t\t\t// oh well....\n\t\t\tinst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];\n\t\t\trgba = inst._rgba = parsed._rgba;\n\n\t\t\t// Exit each( stringParsers ) here because we matched\n\t\t\treturn false;\n\t\t}\n\t} );\n\n\t// Found a stringParser that handled it\n\tif ( rgba.length ) {\n\n\t\t// If this came from a parsed string, force \"transparent\" when alpha is 0\n\t\t// chrome, (and maybe others) return \"transparent\" as rgba(0,0,0,0)\n\t\tif ( rgba.join() === \"0,0,0,0\" ) {\n\t\t\tjQuery.extend( rgba, colors.transparent );\n\t\t}\n\t\treturn inst;\n\t}\n\n\t// Named colors\n\treturn colors[ string ];\n}\n\ncolor.fn = jQuery.extend( color.prototype, {\n\tparse: function( red, green, blue, alpha ) {\n\t\tif ( red === undefined ) {\n\t\t\tthis._rgba = [ null, null, null, null ];\n\t\t\treturn this;\n\t\t}\n\t\tif ( red.jquery || red.nodeType ) {\n\t\t\tred = jQuery( red ).css( green );\n\t\t\tgreen = undefined;\n\t\t}\n\n\t\tvar inst = this,\n\t\t\ttype = jQuery.type( red ),\n\t\t\trgba = this._rgba = [];\n\n\t\t// More than 1 argument specified - assume ( red, green, blue, alpha )\n\t\tif ( green !== undefined ) {\n\t\t\tred = [ red, green, blue, alpha ];\n\t\t\ttype = \"array\";\n\t\t}\n\n\t\tif ( type === \"string\" ) {\n\t\t\treturn this.parse( stringParse( red ) || colors._default );\n\t\t}\n\n\t\tif ( type === \"array\" ) {\n\t\t\teach( spaces.rgba.props, function( key, prop ) {\n\t\t\t\trgba[ prop.idx ] = clamp( red[ prop.idx ], prop );\n\t\t\t} );\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( type === \"object\" ) {\n\t\t\tif ( red instanceof color ) {\n\t\t\t\teach( spaces, function( spaceName, space ) {\n\t\t\t\t\tif ( red[ space.cache ] ) {\n\t\t\t\t\t\tinst[ space.cache ] = red[ space.cache ].slice();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\teach( spaces, function( spaceName, space ) {\n\t\t\t\t\tvar cache = space.cache;\n\t\t\t\t\teach( space.props, function( key, prop ) {\n\n\t\t\t\t\t\t// If the cache doesn't exist, and we know how to convert\n\t\t\t\t\t\tif ( !inst[ cache ] && space.to ) {\n\n\t\t\t\t\t\t\t// If the value was null, we don't need to copy it\n\t\t\t\t\t\t\t// if the key was alpha, we don't need to copy it either\n\t\t\t\t\t\t\tif ( key === \"alpha\" || red[ key ] == null ) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tinst[ cache ] = space.to( inst._rgba );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// This is the only case where we allow nulls for ALL properties.\n\t\t\t\t\t\t// call clamp with alwaysAllowEmpty\n\t\t\t\t\t\tinst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Everything defined but alpha?\n\t\t\t\t\tif ( inst[ cache ] &&\n\t\t\t\t\t\t\tjQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {\n\n\t\t\t\t\t\t// Use the default of 1\n\t\t\t\t\t\tinst[ cache ][ 3 ] = 1;\n\t\t\t\t\t\tif ( space.from ) {\n\t\t\t\t\t\t\tinst._rgba = space.from( inst[ cache ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t},\n\tis: function( compare ) {\n\t\tvar is = color( compare ),\n\t\t\tsame = true,\n\t\t\tinst = this;\n\n\t\teach( spaces, function( _, space ) {\n\t\t\tvar localCache,\n\t\t\t\tisCache = is[ space.cache ];\n\t\t\tif ( isCache ) {\n\t\t\t\tlocalCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];\n\t\t\t\teach( space.props, function( _, prop ) {\n\t\t\t\t\tif ( isCache[ prop.idx ] != null ) {\n\t\t\t\t\t\tsame = ( isCache[ prop.idx ] === localCache[ prop.idx ] );\n\t\t\t\t\t\treturn same;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t\treturn same;\n\t\t} );\n\t\treturn same;\n\t},\n\t_space: function() {\n\t\tvar used = [],\n\t\t\tinst = this;\n\t\teach( spaces, function( spaceName, space ) {\n\t\t\tif ( inst[ space.cache ] ) {\n\t\t\t\tused.push( spaceName );\n\t\t\t}\n\t\t} );\n\t\treturn used.pop();\n\t},\n\ttransition: function( other, distance ) {\n\t\tvar end = color( other ),\n\t\t\tspaceName = end._space(),\n\t\t\tspace = spaces[ spaceName ],\n\t\t\tstartColor = this.alpha() === 0 ? color( \"transparent\" ) : this,\n\t\t\tstart = startColor[ space.cache ] || space.to( startColor._rgba ),\n\t\t\tresult = start.slice();\n\n\t\tend = end[ space.cache ];\n\t\teach( space.props, function( key, prop ) {\n\t\t\tvar index = prop.idx,\n\t\t\t\tstartValue = start[ index ],\n\t\t\t\tendValue = end[ index ],\n\t\t\t\ttype = propTypes[ prop.type ] || {};\n\n\t\t\t// If null, don't override start value\n\t\t\tif ( endValue === null ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If null - use end\n\t\t\tif ( startValue === null ) {\n\t\t\t\tresult[ index ] = endValue;\n\t\t\t} else {\n\t\t\t\tif ( type.mod ) {\n\t\t\t\t\tif ( endValue - startValue > type.mod / 2 ) {\n\t\t\t\t\t\tstartValue += type.mod;\n\t\t\t\t\t} else if ( startValue - endValue > type.mod / 2 ) {\n\t\t\t\t\t\tstartValue -= type.mod;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresult[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );\n\t\t\t}\n\t\t} );\n\t\treturn this[ spaceName ]( result );\n\t},\n\tblend: function( opaque ) {\n\n\t\t// If we are already opaque - return ourself\n\t\tif ( this._rgba[ 3 ] === 1 ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tvar rgb = this._rgba.slice(),\n\t\t\ta = rgb.pop(),\n\t\t\tblend = color( opaque )._rgba;\n\n\t\treturn color( jQuery.map( rgb, function( v, i ) {\n\t\t\treturn ( 1 - a ) * blend[ i ] + a * v;\n\t\t} ) );\n\t},\n\ttoRgbaString: function() {\n\t\tvar prefix = \"rgba(\",\n\t\t\trgba = jQuery.map( this._rgba, function( v, i ) {\n\t\t\t\treturn v == null ? ( i > 2 ? 1 : 0 ) : v;\n\t\t\t} );\n\n\t\tif ( rgba[ 3 ] === 1 ) {\n\t\t\trgba.pop();\n\t\t\tprefix = \"rgb(\";\n\t\t}\n\n\t\treturn prefix + rgba.join() + \")\";\n\t},\n\ttoHslaString: function() {\n\t\tvar prefix = \"hsla(\",\n\t\t\thsla = jQuery.map( this.hsla(), function( v, i ) {\n\t\t\t\tif ( v == null ) {\n\t\t\t\t\tv = i > 2 ? 1 : 0;\n\t\t\t\t}\n\n\t\t\t\t// Catch 1 and 2\n\t\t\t\tif ( i && i < 3 ) {\n\t\t\t\t\tv = Math.round( v * 100 ) + \"%\";\n\t\t\t\t}\n\t\t\t\treturn v;\n\t\t\t} );\n\n\t\tif ( hsla[ 3 ] === 1 ) {\n\t\t\thsla.pop();\n\t\t\tprefix = \"hsl(\";\n\t\t}\n\t\treturn prefix + hsla.join() + \")\";\n\t},\n\ttoHexString: function( includeAlpha ) {\n\t\tvar rgba = this._rgba.slice(),\n\t\t\talpha = rgba.pop();\n\n\t\tif ( includeAlpha ) {\n\t\t\trgba.push( ~~( alpha * 255 ) );\n\t\t}\n\n\t\treturn \"#\" + jQuery.map( rgba, function( v ) {\n\n\t\t\t// Default to 0 when nulls exist\n\t\t\tv = ( v || 0 ).toString( 16 );\n\t\t\treturn v.length === 1 ? \"0\" + v : v;\n\t\t} ).join( \"\" );\n\t},\n\ttoString: function() {\n\t\treturn this._rgba[ 3 ] === 0 ? \"transparent\" : this.toRgbaString();\n\t}\n} );\ncolor.fn.parse.prototype = color.fn;\n\n// Hsla conversions adapted from:\n// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021\n\nfunction hue2rgb( p, q, h ) {\n\th = ( h + 1 ) % 1;\n\tif ( h * 6 < 1 ) {\n\t\treturn p + ( q - p ) * h * 6;\n\t}\n\tif ( h * 2 < 1 ) {\n\t\treturn q;\n\t}\n\tif ( h * 3 < 2 ) {\n\t\treturn p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;\n\t}\n\treturn p;\n}\n\nspaces.hsla.to = function( rgba ) {\n\tif ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {\n\t\treturn [ null, null, null, rgba[ 3 ] ];\n\t}\n\tvar r = rgba[ 0 ] / 255,\n\t\tg = rgba[ 1 ] / 255,\n\t\tb = rgba[ 2 ] / 255,\n\t\ta = rgba[ 3 ],\n\t\tmax = Math.max( r, g, b ),\n\t\tmin = Math.min( r, g, b ),\n\t\tdiff = max - min,\n\t\tadd = max + min,\n\t\tl = add * 0.5,\n\t\th, s;\n\n\tif ( min === max ) {\n\t\th = 0;\n\t} else if ( r === max ) {\n\t\th = ( 60 * ( g - b ) / diff ) + 360;\n\t} else if ( g === max ) {\n\t\th = ( 60 * ( b - r ) / diff ) + 120;\n\t} else {\n\t\th = ( 60 * ( r - g ) / diff ) + 240;\n\t}\n\n\t// Chroma (diff) == 0 means greyscale which, by definition, saturation = 0%\n\t// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)\n\tif ( diff === 0 ) {\n\t\ts = 0;\n\t} else if ( l <= 0.5 ) {\n\t\ts = diff / add;\n\t} else {\n\t\ts = diff / ( 2 - add );\n\t}\n\treturn [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];\n};\n\nspaces.hsla.from = function( hsla ) {\n\tif ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {\n\t\treturn [ null, null, null, hsla[ 3 ] ];\n\t}\n\tvar h = hsla[ 0 ] / 360,\n\t\ts = hsla[ 1 ],\n\t\tl = hsla[ 2 ],\n\t\ta = hsla[ 3 ],\n\t\tq = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,\n\t\tp = 2 * l - q;\n\n\treturn [\n\t\tMath.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),\n\t\tMath.round( hue2rgb( p, q, h ) * 255 ),\n\t\tMath.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),\n\t\ta\n\t];\n};\n\neach( spaces, function( spaceName, space ) {\n\tvar props = space.props,\n\t\tcache = space.cache,\n\t\tto = space.to,\n\t\tfrom = space.from;\n\n\t// Makes rgba() and hsla()\n\tcolor.fn[ spaceName ] = function( value ) {\n\n\t\t// Generate a cache for this space if it doesn't exist\n\t\tif ( to && !this[ cache ] ) {\n\t\t\tthis[ cache ] = to( this._rgba );\n\t\t}\n\t\tif ( value === undefined ) {\n\t\t\treturn this[ cache ].slice();\n\t\t}\n\n\t\tvar ret,\n\t\t\ttype = jQuery.type( value ),\n\t\t\tarr = ( type === \"array\" || type === \"object\" ) ? value : arguments,\n\t\t\tlocal = this[ cache ].slice();\n\n\t\teach( props, function( key, prop ) {\n\t\t\tvar val = arr[ type === \"object\" ? key : prop.idx ];\n\t\t\tif ( val == null ) {\n\t\t\t\tval = local[ prop.idx ];\n\t\t\t}\n\t\t\tlocal[ prop.idx ] = clamp( val, prop );\n\t\t} );\n\n\t\tif ( from ) {\n\t\t\tret = color( from( local ) );\n\t\t\tret[ cache ] = local;\n\t\t\treturn ret;\n\t\t} else {\n\t\t\treturn color( local );\n\t\t}\n\t};\n\n\t// Makes red() green() blue() alpha() hue() saturation() lightness()\n\teach( props, function( key, prop ) {\n\n\t\t// Alpha is included in more than one space\n\t\tif ( color.fn[ key ] ) {\n\t\t\treturn;\n\t\t}\n\t\tcolor.fn[ key ] = function( value ) {\n\t\t\tvar vtype = jQuery.type( value ),\n\t\t\t\tfn = ( key === \"alpha\" ? ( this._hsla ? \"hsla\" : \"rgba\" ) : spaceName ),\n\t\t\t\tlocal = this[ fn ](),\n\t\t\t\tcur = local[ prop.idx ],\n\t\t\t\tmatch;\n\n\t\t\tif ( vtype === \"undefined\" ) {\n\t\t\t\treturn cur;\n\t\t\t}\n\n\t\t\tif ( vtype === \"function\" ) {\n\t\t\t\tvalue = value.call( this, cur );\n\t\t\t\tvtype = jQuery.type( value );\n\t\t\t}\n\t\t\tif ( value == null && prop.empty ) {\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\tif ( vtype === \"string\" ) {\n\t\t\t\tmatch = rplusequals.exec( value );\n\t\t\t\tif ( match ) {\n\t\t\t\t\tvalue = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === \"+\" ? 1 : -1 );\n\t\t\t\t}\n\t\t\t}\n\t\t\tlocal[ prop.idx ] = value;\n\t\t\treturn this[ fn ]( local );\n\t\t};\n\t} );\n} );\n\n// Add cssHook and .fx.step function for each named hook.\n// accept a space separated string of properties\ncolor.hook = function( hook ) {\n\tvar hooks = hook.split( \" \" );\n\teach( hooks, function( i, hook ) {\n\t\tjQuery.cssHooks[ hook ] = {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar parsed, curElem,\n\t\t\t\t\tbackgroundColor = \"\";\n\n\t\t\t\tif ( value !== \"transparent\" && ( jQuery.type( value ) !== \"string\" ||\n\t\t\t\t\t\t( parsed = stringParse( value ) ) ) ) {\n\t\t\t\t\tvalue = color( parsed || value );\n\t\t\t\t\tif ( !support.rgba && value._rgba[ 3 ] !== 1 ) {\n\t\t\t\t\t\tcurElem = hook === \"backgroundColor\" ? elem.parentNode : elem;\n\t\t\t\t\t\twhile (\n\t\t\t\t\t\t\t( backgroundColor === \"\" || backgroundColor === \"transparent\" ) &&\n\t\t\t\t\t\t\tcurElem && curElem.style\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tbackgroundColor = jQuery.css( curElem, \"backgroundColor\" );\n\t\t\t\t\t\t\t\tcurElem = curElem.parentNode;\n\t\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvalue = value.blend( backgroundColor && backgroundColor !== \"transparent\" ?\n\t\t\t\t\t\t\tbackgroundColor :\n\t\t\t\t\t\t\t\"_default\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tvalue = value.toRgbaString();\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\telem.style[ hook ] = value;\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t// Wrapped to prevent IE from throwing errors on \"invalid\" values like\n\t\t\t\t\t// 'auto' or 'inherit'\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\tjQuery.fx.step[ hook ] = function( fx ) {\n\t\t\tif ( !fx.colorInit ) {\n\t\t\t\tfx.start = color( fx.elem, hook );\n\t\t\t\tfx.end = color( fx.end );\n\t\t\t\tfx.colorInit = true;\n\t\t\t}\n\t\t\tjQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );\n\t\t};\n\t} );\n\n};\n\ncolor.hook( stepHooks );\n\njQuery.cssHooks.borderColor = {\n\texpand: function( value ) {\n\t\tvar expanded = {};\n\n\t\teach( [ \"Top\", \"Right\", \"Bottom\", \"Left\" ], function( i, part ) {\n\t\t\texpanded[ \"border\" + part + \"Color\" ] = value;\n\t\t} );\n\t\treturn expanded;\n\t}\n};\n\n// Basic color names only.\n// Usage of any of the other color names requires adding yourself or including\n// jquery.color.svg-names.js.\ncolors = jQuery.Color.names = {\n\n\t// 4.1. Basic color keywords\n\taqua: \"#00ffff\",\n\tblack: \"#000000\",\n\tblue: \"#0000ff\",\n\tfuchsia: \"#ff00ff\",\n\tgray: \"#808080\",\n\tgreen: \"#008000\",\n\tlime: \"#00ff00\",\n\tmaroon: \"#800000\",\n\tnavy: \"#000080\",\n\tolive: \"#808000\",\n\tpurple: \"#800080\",\n\tred: \"#ff0000\",\n\tsilver: \"#c0c0c0\",\n\tteal: \"#008080\",\n\twhite: \"#ffffff\",\n\tyellow: \"#ffff00\",\n\n\t// 4.2.3. \"transparent\" color keyword\n\ttransparent: [ null, null, null, 0 ],\n\n\t_default: \"#ffffff\"\n};\n\n} )( jQuery );\n\n/******************************************************************************/\n/****************************** CLASS ANIMATIONS ******************************/\n/******************************************************************************/\n( function() {\n\nvar classAnimationActions = [ \"add\", \"remove\", \"toggle\" ],\n\tshorthandStyles = {\n\t\tborder: 1,\n\t\tborderBottom: 1,\n\t\tborderColor: 1,\n\t\tborderLeft: 1,\n\t\tborderRight: 1,\n\t\tborderTop: 1,\n\t\tborderWidth: 1,\n\t\tmargin: 1,\n\t\tpadding: 1\n\t};\n\n$.each(\n\t[ \"borderLeftStyle\", \"borderRightStyle\", \"borderBottomStyle\", \"borderTopStyle\" ],\n\tfunction( _, prop ) {\n\t\t$.fx.step[ prop ] = function( fx ) {\n\t\t\tif ( fx.end !== \"none\" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {\n\t\t\t\tjQuery.style( fx.elem, prop, fx.end );\n\t\t\t\tfx.setAttr = true;\n\t\t\t}\n\t\t};\n\t}\n);\n\nfunction getElementStyles( elem ) {\n\tvar key, len,\n\t\tstyle = elem.ownerDocument.defaultView ?\n\t\t\telem.ownerDocument.defaultView.getComputedStyle( elem, null ) :\n\t\t\telem.currentStyle,\n\t\tstyles = {};\n\n\tif ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {\n\t\tlen = style.length;\n\t\twhile ( len-- ) {\n\t\t\tkey = style[ len ];\n\t\t\tif ( typeof style[ key ] === \"string\" ) {\n\t\t\t\tstyles[ $.camelCase( key ) ] = style[ key ];\n\t\t\t}\n\t\t}\n\n\t// Support: Opera, IE <9\n\t} else {\n\t\tfor ( key in style ) {\n\t\t\tif ( typeof style[ key ] === \"string\" ) {\n\t\t\t\tstyles[ key ] = style[ key ];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn styles;\n}\n\nfunction styleDifference( oldStyle, newStyle ) {\n\tvar diff = {},\n\t\tname, value;\n\n\tfor ( name in newStyle ) {\n\t\tvalue = newStyle[ name ];\n\t\tif ( oldStyle[ name ] !== value ) {\n\t\t\tif ( !shorthandStyles[ name ] ) {\n\t\t\t\tif ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {\n\t\t\t\t\tdiff[ name ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn diff;\n}\n\n// Support: jQuery <1.8\nif ( !$.fn.addBack ) {\n\t$.fn.addBack = function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t};\n}\n\n$.effects.animateClass = function( value, duration, easing, callback ) {\n\tvar o = $.speed( duration, easing, callback );\n\n\treturn this.queue( function() {\n\t\tvar animated = $( this ),\n\t\t\tbaseClass = animated.attr( \"class\" ) || \"\",\n\t\t\tapplyClassChange,\n\t\t\tallAnimations = o.children ? animated.find( \"*\" ).addBack() : animated;\n\n\t\t// Map the animated objects to store the original styles.\n\t\tallAnimations = allAnimations.map( function() {\n\t\t\tvar el = $( this );\n\t\t\treturn {\n\t\t\t\tel: el,\n\t\t\t\tstart: getElementStyles( this )\n\t\t\t};\n\t\t} );\n\n\t\t// Apply class change\n\t\tapplyClassChange = function() {\n\t\t\t$.each( classAnimationActions, function( i, action ) {\n\t\t\t\tif ( value[ action ] ) {\n\t\t\t\t\tanimated[ action + \"Class\" ]( value[ action ] );\n\t\t\t\t}\n\t\t\t} );\n\t\t};\n\t\tapplyClassChange();\n\n\t\t// Map all animated objects again - calculate new styles and diff\n\t\tallAnimations = allAnimations.map( function() {\n\t\t\tthis.end = getElementStyles( this.el[ 0 ] );\n\t\t\tthis.diff = styleDifference( this.start, this.end );\n\t\t\treturn this;\n\t\t} );\n\n\t\t// Apply original class\n\t\tanimated.attr( \"class\", baseClass );\n\n\t\t// Map all animated objects again - this time collecting a promise\n\t\tallAnimations = allAnimations.map( function() {\n\t\t\tvar styleInfo = this,\n\t\t\t\tdfd = $.Deferred(),\n\t\t\t\topts = $.extend( {}, o, {\n\t\t\t\t\tqueue: false,\n\t\t\t\t\tcomplete: function() {\n\t\t\t\t\t\tdfd.resolve( styleInfo );\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\tthis.el.animate( this.diff, opts );\n\t\t\treturn dfd.promise();\n\t\t} );\n\n\t\t// Once all animations have completed:\n\t\t$.when.apply( $, allAnimations.get() ).done( function() {\n\n\t\t\t// Set the final class\n\t\t\tapplyClassChange();\n\n\t\t\t// For each animated element,\n\t\t\t// clear all css properties that were animated\n\t\t\t$.each( arguments, function() {\n\t\t\t\tvar el = this.el;\n\t\t\t\t$.each( this.diff, function( key ) {\n\t\t\t\t\tel.css( key, \"\" );\n\t\t\t\t} );\n\t\t\t} );\n\n\t\t\t// This is guarnteed to be there if you use jQuery.speed()\n\t\t\t// it also handles dequeuing the next anim...\n\t\t\to.complete.call( animated[ 0 ] );\n\t\t} );\n\t} );\n};\n\n$.fn.extend( {\n\taddClass: ( function( orig ) {\n\t\treturn function( classNames, speed, easing, callback ) {\n\t\t\treturn speed ?\n\t\t\t\t$.effects.animateClass.call( this,\n\t\t\t\t\t{ add: classNames }, speed, easing, callback ) :\n\t\t\t\torig.apply( this, arguments );\n\t\t};\n\t} )( $.fn.addClass ),\n\n\tremoveClass: ( function( orig ) {\n\t\treturn function( classNames, speed, easing, callback ) {\n\t\t\treturn arguments.length > 1 ?\n\t\t\t\t$.effects.animateClass.call( this,\n\t\t\t\t\t{ remove: classNames }, speed, easing, callback ) :\n\t\t\t\torig.apply( this, arguments );\n\t\t};\n\t} )( $.fn.removeClass ),\n\n\ttoggleClass: ( function( orig ) {\n\t\treturn function( classNames, force, speed, easing, callback ) {\n\t\t\tif ( typeof force === \"boolean\" || force === undefined ) {\n\t\t\t\tif ( !speed ) {\n\n\t\t\t\t\t// Without speed parameter\n\t\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t\t} else {\n\t\t\t\t\treturn $.effects.animateClass.call( this,\n\t\t\t\t\t\t( force ? { add: classNames } : { remove: classNames } ),\n\t\t\t\t\t\tspeed, easing, callback );\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// Without force parameter\n\t\t\t\treturn $.effects.animateClass.call( this,\n\t\t\t\t\t{ toggle: classNames }, force, speed, easing );\n\t\t\t}\n\t\t};\n\t} )( $.fn.toggleClass ),\n\n\tswitchClass: function( remove, add, speed, easing, callback ) {\n\t\treturn $.effects.animateClass.call( this, {\n\t\t\tadd: add,\n\t\t\tremove: remove\n\t\t}, speed, easing, callback );\n\t}\n} );\n\n} )();\n\n/******************************************************************************/\n/*********************************** EFFECTS **********************************/\n/******************************************************************************/\n\n( function() {\n\nif ( $.expr && $.expr.filters && $.expr.filters.animated ) {\n\t$.expr.filters.animated = ( function( orig ) {\n\t\treturn function( elem ) {\n\t\t\treturn !!$( elem ).data( dataSpaceAnimated ) || orig( elem );\n\t\t};\n\t} )( $.expr.filters.animated );\n}\n\nif ( $.uiBackCompat !== false ) {\n\t$.extend( $.effects, {\n\n\t\t// Saves a set of properties in a data storage\n\t\tsave: function( element, set ) {\n\t\t\tvar i = 0, length = set.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( set[ i ] !== null ) {\n\t\t\t\t\telement.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Restores a set of previously saved properties from a data storage\n\t\trestore: function( element, set ) {\n\t\t\tvar val, i = 0, length = set.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( set[ i ] !== null ) {\n\t\t\t\t\tval = element.data( dataSpace + set[ i ] );\n\t\t\t\t\telement.css( set[ i ], val );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tsetMode: function( el, mode ) {\n\t\t\tif ( mode === \"toggle\" ) {\n\t\t\t\tmode = el.is( \":hidden\" ) ? \"show\" : \"hide\";\n\t\t\t}\n\t\t\treturn mode;\n\t\t},\n\n\t\t// Wraps the element around a wrapper that copies position properties\n\t\tcreateWrapper: function( element ) {\n\n\t\t\t// If the element is already wrapped, return it\n\t\t\tif ( element.parent().is( \".ui-effects-wrapper\" ) ) {\n\t\t\t\treturn element.parent();\n\t\t\t}\n\n\t\t\t// Wrap the element\n\t\t\tvar props = {\n\t\t\t\t\twidth: element.outerWidth( true ),\n\t\t\t\t\theight: element.outerHeight( true ),\n\t\t\t\t\t\"float\": element.css( \"float\" )\n\t\t\t\t},\n\t\t\t\twrapper = $( \"<div></div>\" )\n\t\t\t\t\t.addClass( \"ui-effects-wrapper\" )\n\t\t\t\t\t.css( {\n\t\t\t\t\t\tfontSize: \"100%\",\n\t\t\t\t\t\tbackground: \"transparent\",\n\t\t\t\t\t\tborder: \"none\",\n\t\t\t\t\t\tmargin: 0,\n\t\t\t\t\t\tpadding: 0\n\t\t\t\t\t} ),\n\n\t\t\t\t// Store the size in case width/height are defined in % - Fixes #5245\n\t\t\t\tsize = {\n\t\t\t\t\twidth: element.width(),\n\t\t\t\t\theight: element.height()\n\t\t\t\t},\n\t\t\t\tactive = document.activeElement;\n\n\t\t\t// Support: Firefox\n\t\t\t// Firefox incorrectly exposes anonymous content\n\t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=561664\n\t\t\ttry {\n\t\t\t\tactive.id;\n\t\t\t} catch ( e ) {\n\t\t\t\tactive = document.body;\n\t\t\t}\n\n\t\t\telement.wrap( wrapper );\n\n\t\t\t// Fixes #7595 - Elements lose focus when wrapped.\n\t\t\tif ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {\n\t\t\t\t$( active ).trigger( \"focus\" );\n\t\t\t}\n\n\t\t\t// Hotfix for jQuery 1.4 since some change in wrap() seems to actually\n\t\t\t// lose the reference to the wrapped element\n\t\t\twrapper = element.parent();\n\n\t\t\t// Transfer positioning properties to the wrapper\n\t\t\tif ( element.css( \"position\" ) === \"static\" ) {\n\t\t\t\twrapper.css( { position: \"relative\" } );\n\t\t\t\telement.css( { position: \"relative\" } );\n\t\t\t} else {\n\t\t\t\t$.extend( props, {\n\t\t\t\t\tposition: element.css( \"position\" ),\n\t\t\t\t\tzIndex: element.css( \"z-index\" )\n\t\t\t\t} );\n\t\t\t\t$.each( [ \"top\", \"left\", \"bottom\", \"right\" ], function( i, pos ) {\n\t\t\t\t\tprops[ pos ] = element.css( pos );\n\t\t\t\t\tif ( isNaN( parseInt( props[ pos ], 10 ) ) ) {\n\t\t\t\t\t\tprops[ pos ] = \"auto\";\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\telement.css( {\n\t\t\t\t\tposition: \"relative\",\n\t\t\t\t\ttop: 0,\n\t\t\t\t\tleft: 0,\n\t\t\t\t\tright: \"auto\",\n\t\t\t\t\tbottom: \"auto\"\n\t\t\t\t} );\n\t\t\t}\n\t\t\telement.css( size );\n\n\t\t\treturn wrapper.css( props ).show();\n\t\t},\n\n\t\tremoveWrapper: function( element ) {\n\t\t\tvar active = document.activeElement;\n\n\t\t\tif ( element.parent().is( \".ui-effects-wrapper\" ) ) {\n\t\t\t\telement.parent().replaceWith( element );\n\n\t\t\t\t// Fixes #7595 - Elements lose focus when wrapped.\n\t\t\t\tif ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {\n\t\t\t\t\t$( active ).trigger( \"focus\" );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn element;\n\t\t}\n\t} );\n}\n\n$.extend( $.effects, {\n\tversion: \"1.12.1\",\n\n\tdefine: function( name, mode, effect ) {\n\t\tif ( !effect ) {\n\t\t\teffect = mode;\n\t\t\tmode = \"effect\";\n\t\t}\n\n\t\t$.effects.effect[ name ] = effect;\n\t\t$.effects.effect[ name ].mode = mode;\n\n\t\treturn effect;\n\t},\n\n\tscaledDimensions: function( element, percent, direction ) {\n\t\tif ( percent === 0 ) {\n\t\t\treturn {\n\t\t\t\theight: 0,\n\t\t\t\twidth: 0,\n\t\t\t\touterHeight: 0,\n\t\t\t\touterWidth: 0\n\t\t\t};\n\t\t}\n\n\t\tvar x = direction !== \"horizontal\" ? ( ( percent || 100 ) / 100 ) : 1,\n\t\t\ty = direction !== \"vertical\" ? ( ( percent || 100 ) / 100 ) : 1;\n\n\t\treturn {\n\t\t\theight: element.height() * y,\n\t\t\twidth: element.width() * x,\n\t\t\touterHeight: element.outerHeight() * y,\n\t\t\touterWidth: element.outerWidth() * x\n\t\t};\n\n\t},\n\n\tclipToBox: function( animation ) {\n\t\treturn {\n\t\t\twidth: animation.clip.right - animation.clip.left,\n\t\t\theight: animation.clip.bottom - animation.clip.top,\n\t\t\tleft: animation.clip.left,\n\t\t\ttop: animation.clip.top\n\t\t};\n\t},\n\n\t// Injects recently queued functions to be first in line (after \"inprogress\")\n\tunshift: function( element, queueLength, count ) {\n\t\tvar queue = element.queue();\n\n\t\tif ( queueLength > 1 ) {\n\t\t\tqueue.splice.apply( queue,\n\t\t\t\t[ 1, 0 ].concat( queue.splice( queueLength, count ) ) );\n\t\t}\n\t\telement.dequeue();\n\t},\n\n\tsaveStyle: function( element ) {\n\t\telement.data( dataSpaceStyle, element[ 0 ].style.cssText );\n\t},\n\n\trestoreStyle: function( element ) {\n\t\telement[ 0 ].style.cssText = element.data( dataSpaceStyle ) || \"\";\n\t\telement.removeData( dataSpaceStyle );\n\t},\n\n\tmode: function( element, mode ) {\n\t\tvar hidden = element.is( \":hidden\" );\n\n\t\tif ( mode === \"toggle\" ) {\n\t\t\tmode = hidden ? \"show\" : \"hide\";\n\t\t}\n\t\tif ( hidden ? mode === \"hide\" : mode === \"show\" ) {\n\t\t\tmode = \"none\";\n\t\t}\n\t\treturn mode;\n\t},\n\n\t// Translates a [top,left] array into a baseline value\n\tgetBaseline: function( origin, original ) {\n\t\tvar y, x;\n\n\t\tswitch ( origin[ 0 ] ) {\n\t\tcase \"top\":\n\t\t\ty = 0;\n\t\t\tbreak;\n\t\tcase \"middle\":\n\t\t\ty = 0.5;\n\t\t\tbreak;\n\t\tcase \"bottom\":\n\t\t\ty = 1;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\ty = origin[ 0 ] / original.height;\n\t\t}\n\n\t\tswitch ( origin[ 1 ] ) {\n\t\tcase \"left\":\n\t\t\tx = 0;\n\t\t\tbreak;\n\t\tcase \"center\":\n\t\t\tx = 0.5;\n\t\t\tbreak;\n\t\tcase \"right\":\n\t\t\tx = 1;\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tx = origin[ 1 ] / original.width;\n\t\t}\n\n\t\treturn {\n\t\t\tx: x,\n\t\t\ty: y\n\t\t};\n\t},\n\n\t// Creates a placeholder element so that the original element can be made absolute\n\tcreatePlaceholder: function( element ) {\n\t\tvar placeholder,\n\t\t\tcssPosition = element.css( \"position\" ),\n\t\t\tposition = element.position();\n\n\t\t// Lock in margins first to account for form elements, which\n\t\t// will change margin if you explicitly set height\n\t\t// see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380\n\t\t// Support: Safari\n\t\telement.css( {\n\t\t\tmarginTop: element.css( \"marginTop\" ),\n\t\t\tmarginBottom: element.css( \"marginBottom\" ),\n\t\t\tmarginLeft: element.css( \"marginLeft\" ),\n\t\t\tmarginRight: element.css( \"marginRight\" )\n\t\t} )\n\t\t.outerWidth( element.outerWidth() )\n\t\t.outerHeight( element.outerHeight() );\n\n\t\tif ( /^(static|relative)/.test( cssPosition ) ) {\n\t\t\tcssPosition = \"absolute\";\n\n\t\t\tplaceholder = $( \"<\" + element[ 0 ].nodeName + \">\" ).insertAfter( element ).css( {\n\n\t\t\t\t// Convert inline to inline block to account for inline elements\n\t\t\t\t// that turn to inline block based on content (like img)\n\t\t\t\tdisplay: /^(inline|ruby)/.test( element.css( \"display\" ) ) ?\n\t\t\t\t\t\"inline-block\" :\n\t\t\t\t\t\"block\",\n\t\t\t\tvisibility: \"hidden\",\n\n\t\t\t\t// Margins need to be set to account for margin collapse\n\t\t\t\tmarginTop: element.css( \"marginTop\" ),\n\t\t\t\tmarginBottom: element.css( \"marginBottom\" ),\n\t\t\t\tmarginLeft: element.css( \"marginLeft\" ),\n\t\t\t\tmarginRight: element.css( \"marginRight\" ),\n\t\t\t\t\"float\": element.css( \"float\" )\n\t\t\t} )\n\t\t\t.outerWidth( element.outerWidth() )\n\t\t\t.outerHeight( element.outerHeight() )\n\t\t\t.addClass( \"ui-effects-placeholder\" );\n\n\t\t\telement.data( dataSpace + \"placeholder\", placeholder );\n\t\t}\n\n\t\telement.css( {\n\t\t\tposition: cssPosition,\n\t\t\tleft: position.left,\n\t\t\ttop: position.top\n\t\t} );\n\n\t\treturn placeholder;\n\t},\n\n\tremovePlaceholder: function( element ) {\n\t\tvar dataKey = dataSpace + \"placeholder\",\n\t\t\t\tplaceholder = element.data( dataKey );\n\n\t\tif ( placeholder ) {\n\t\t\tplaceholder.remove();\n\t\t\telement.removeData( dataKey );\n\t\t}\n\t},\n\n\t// Removes a placeholder if it exists and restores\n\t// properties that were modified during placeholder creation\n\tcleanUp: function( element ) {\n\t\t$.effects.restoreStyle( element );\n\t\t$.effects.removePlaceholder( element );\n\t},\n\n\tsetTransition: function( element, list, factor, value ) {\n\t\tvalue = value || {};\n\t\t$.each( list, function( i, x ) {\n\t\t\tvar unit = element.cssUnit( x );\n\t\t\tif ( unit[ 0 ] > 0 ) {\n\t\t\t\tvalue[ x ] = unit[ 0 ] * factor + unit[ 1 ];\n\t\t\t}\n\t\t} );\n\t\treturn value;\n\t}\n} );\n\n// Return an effect options object for the given parameters:\nfunction _normalizeArguments( effect, options, speed, callback ) {\n\n\t// Allow passing all options as the first parameter\n\tif ( $.isPlainObject( effect ) ) {\n\t\toptions = effect;\n\t\teffect = effect.effect;\n\t}\n\n\t// Convert to an object\n\teffect = { effect: effect };\n\n\t// Catch (effect, null, ...)\n\tif ( options == null ) {\n\t\toptions = {};\n\t}\n\n\t// Catch (effect, callback)\n\tif ( $.isFunction( options ) ) {\n\t\tcallback = options;\n\t\tspeed = null;\n\t\toptions = {};\n\t}\n\n\t// Catch (effect, speed, ?)\n\tif ( typeof options === \"number\" || $.fx.speeds[ options ] ) {\n\t\tcallback = speed;\n\t\tspeed = options;\n\t\toptions = {};\n\t}\n\n\t// Catch (effect, options, callback)\n\tif ( $.isFunction( speed ) ) {\n\t\tcallback = speed;\n\t\tspeed = null;\n\t}\n\n\t// Add options to effect\n\tif ( options ) {\n\t\t$.extend( effect, options );\n\t}\n\n\tspeed = speed || options.duration;\n\teffect.duration = $.fx.off ? 0 :\n\t\ttypeof speed === \"number\" ? speed :\n\t\tspeed in $.fx.speeds ? $.fx.speeds[ speed ] :\n\t\t$.fx.speeds._default;\n\n\teffect.complete = callback || options.complete;\n\n\treturn effect;\n}\n\nfunction standardAnimationOption( option ) {\n\n\t// Valid standard speeds (nothing, number, named speed)\n\tif ( !option || typeof option === \"number\" || $.fx.speeds[ option ] ) {\n\t\treturn true;\n\t}\n\n\t// Invalid strings - treat as \"normal\" speed\n\tif ( typeof option === \"string\" && !$.effects.effect[ option ] ) {\n\t\treturn true;\n\t}\n\n\t// Complete callback\n\tif ( $.isFunction( option ) ) {\n\t\treturn true;\n\t}\n\n\t// Options hash (but not naming an effect)\n\tif ( typeof option === \"object\" && !option.effect ) {\n\t\treturn true;\n\t}\n\n\t// Didn't match any standard API\n\treturn false;\n}\n\n$.fn.extend( {\n\teffect: function( /* effect, options, speed, callback */ ) {\n\t\tvar args = _normalizeArguments.apply( this, arguments ),\n\t\t\teffectMethod = $.effects.effect[ args.effect ],\n\t\t\tdefaultMode = effectMethod.mode,\n\t\t\tqueue = args.queue,\n\t\t\tqueueName = queue || \"fx\",\n\t\t\tcomplete = args.complete,\n\t\t\tmode = args.mode,\n\t\t\tmodes = [],\n\t\t\tprefilter = function( next ) {\n\t\t\t\tvar el = $( this ),\n\t\t\t\t\tnormalizedMode = $.effects.mode( el, mode ) || defaultMode;\n\n\t\t\t\t// Sentinel for duck-punching the :animated psuedo-selector\n\t\t\t\tel.data( dataSpaceAnimated, true );\n\n\t\t\t\t// Save effect mode for later use,\n\t\t\t\t// we can't just call $.effects.mode again later,\n\t\t\t\t// as the .show() below destroys the initial state\n\t\t\t\tmodes.push( normalizedMode );\n\n\t\t\t\t// See $.uiBackCompat inside of run() for removal of defaultMode in 1.13\n\t\t\t\tif ( defaultMode && ( normalizedMode === \"show\" ||\n\t\t\t\t\t\t( normalizedMode === defaultMode && normalizedMode === \"hide\" ) ) ) {\n\t\t\t\t\tel.show();\n\t\t\t\t}\n\n\t\t\t\tif ( !defaultMode || normalizedMode !== \"none\" ) {\n\t\t\t\t\t$.effects.saveStyle( el );\n\t\t\t\t}\n\n\t\t\t\tif ( $.isFunction( next ) ) {\n\t\t\t\t\tnext();\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( $.fx.off || !effectMethod ) {\n\n\t\t\t// Delegate to the original method (e.g., .show()) if possible\n\t\t\tif ( mode ) {\n\t\t\t\treturn this[ mode ]( args.duration, complete );\n\t\t\t} else {\n\t\t\t\treturn this.each( function() {\n\t\t\t\t\tif ( complete ) {\n\t\t\t\t\t\tcomplete.call( this );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\tfunction run( next ) {\n\t\t\tvar elem = $( this );\n\n\t\t\tfunction cleanup() {\n\t\t\t\telem.removeData( dataSpaceAnimated );\n\n\t\t\t\t$.effects.cleanUp( elem );\n\n\t\t\t\tif ( args.mode === \"hide\" ) {\n\t\t\t\t\telem.hide();\n\t\t\t\t}\n\n\t\t\t\tdone();\n\t\t\t}\n\n\t\t\tfunction done() {\n\t\t\t\tif ( $.isFunction( complete ) ) {\n\t\t\t\t\tcomplete.call( elem[ 0 ] );\n\t\t\t\t}\n\n\t\t\t\tif ( $.isFunction( next ) ) {\n\t\t\t\t\tnext();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override mode option on a per element basis,\n\t\t\t// as toggle can be either show or hide depending on element state\n\t\t\targs.mode = modes.shift();\n\n\t\t\tif ( $.uiBackCompat !== false && !defaultMode ) {\n\t\t\t\tif ( elem.is( \":hidden\" ) ? mode === \"hide\" : mode === \"show\" ) {\n\n\t\t\t\t\t// Call the core method to track \"olddisplay\" properly\n\t\t\t\t\telem[ mode ]();\n\t\t\t\t\tdone();\n\t\t\t\t} else {\n\t\t\t\t\teffectMethod.call( elem[ 0 ], args, done );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( args.mode === \"none\" ) {\n\n\t\t\t\t\t// Call the core method to track \"olddisplay\" properly\n\t\t\t\t\telem[ mode ]();\n\t\t\t\t\tdone();\n\t\t\t\t} else {\n\t\t\t\t\teffectMethod.call( elem[ 0 ], args, cleanup );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Run prefilter on all elements first to ensure that\n\t\t// any showing or hiding happens before placeholder creation,\n\t\t// which ensures that any layout changes are correctly captured.\n\t\treturn queue === false ?\n\t\t\tthis.each( prefilter ).each( run ) :\n\t\t\tthis.queue( queueName, prefilter ).queue( queueName, run );\n\t},\n\n\tshow: ( function( orig ) {\n\t\treturn function( option ) {\n\t\t\tif ( standardAnimationOption( option ) ) {\n\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t} else {\n\t\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n\t\t\t\targs.mode = \"show\";\n\t\t\t\treturn this.effect.call( this, args );\n\t\t\t}\n\t\t};\n\t} )( $.fn.show ),\n\n\thide: ( function( orig ) {\n\t\treturn function( option ) {\n\t\t\tif ( standardAnimationOption( option ) ) {\n\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t} else {\n\t\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n\t\t\t\targs.mode = \"hide\";\n\t\t\t\treturn this.effect.call( this, args );\n\t\t\t}\n\t\t};\n\t} )( $.fn.hide ),\n\n\ttoggle: ( function( orig ) {\n\t\treturn function( option ) {\n\t\t\tif ( standardAnimationOption( option ) || typeof option === \"boolean\" ) {\n\t\t\t\treturn orig.apply( this, arguments );\n\t\t\t} else {\n\t\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n\t\t\t\targs.mode = \"toggle\";\n\t\t\t\treturn this.effect.call( this, args );\n\t\t\t}\n\t\t};\n\t} )( $.fn.toggle ),\n\n\tcssUnit: function( key ) {\n\t\tvar style = this.css( key ),\n\t\t\tval = [];\n\n\t\t$.each( [ \"em\", \"px\", \"%\", \"pt\" ], function( i, unit ) {\n\t\t\tif ( style.indexOf( unit ) > 0 ) {\n\t\t\t\tval = [ parseFloat( style ), unit ];\n\t\t\t}\n\t\t} );\n\t\treturn val;\n\t},\n\n\tcssClip: function( clipObj ) {\n\t\tif ( clipObj ) {\n\t\t\treturn this.css( \"clip\", \"rect(\" + clipObj.top + \"px \" + clipObj.right + \"px \" +\n\t\t\t\tclipObj.bottom + \"px \" + clipObj.left + \"px)\" );\n\t\t}\n\t\treturn parseClip( this.css( \"clip\" ), this );\n\t},\n\n\ttransfer: function( options, done ) {\n\t\tvar element = $( this ),\n\t\t\ttarget = $( options.to ),\n\t\t\ttargetFixed = target.css( \"position\" ) === \"fixed\",\n\t\t\tbody = $( \"body\" ),\n\t\t\tfixTop = targetFixed ? body.scrollTop() : 0,\n\t\t\tfixLeft = targetFixed ? body.scrollLeft() : 0,\n\t\t\tendPosition = target.offset(),\n\t\t\tanimation = {\n\t\t\t\ttop: endPosition.top - fixTop,\n\t\t\t\tleft: endPosition.left - fixLeft,\n\t\t\t\theight: target.innerHeight(),\n\t\t\t\twidth: target.innerWidth()\n\t\t\t},\n\t\t\tstartPosition = element.offset(),\n\t\t\ttransfer = $( \"<div class='ui-effects-transfer'></div>\" )\n\t\t\t\t.appendTo( \"body\" )\n\t\t\t\t.addClass( options.className )\n\t\t\t\t.css( {\n\t\t\t\t\ttop: startPosition.top - fixTop,\n\t\t\t\t\tleft: startPosition.left - fixLeft,\n\t\t\t\t\theight: element.innerHeight(),\n\t\t\t\t\twidth: element.innerWidth(),\n\t\t\t\t\tposition: targetFixed ? \"fixed\" : \"absolute\"\n\t\t\t\t} )\n\t\t\t\t.animate( animation, options.duration, options.easing, function() {\n\t\t\t\t\ttransfer.remove();\n\t\t\t\t\tif ( $.isFunction( done ) ) {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t}\n\t\t\t\t} );\n\t}\n} );\n\nfunction parseClip( str, element ) {\n\t\tvar outerWidth = element.outerWidth(),\n\t\t\touterHeight = element.outerHeight(),\n\t\t\tclipRegex = /^rect\\((-?\\d*\\.?\\d*px|-?\\d+%|auto),?\\s*(-?\\d*\\.?\\d*px|-?\\d+%|auto),?\\s*(-?\\d*\\.?\\d*px|-?\\d+%|auto),?\\s*(-?\\d*\\.?\\d*px|-?\\d+%|auto)\\)$/,\n\t\t\tvalues = clipRegex.exec( str ) || [ \"\", 0, outerWidth, outerHeight, 0 ];\n\n\t\treturn {\n\t\t\ttop: parseFloat( values[ 1 ] ) || 0,\n\t\t\tright: values[ 2 ] === \"auto\" ? outerWidth : parseFloat( values[ 2 ] ),\n\t\t\tbottom: values[ 3 ] === \"auto\" ? outerHeight : parseFloat( values[ 3 ] ),\n\t\t\tleft: parseFloat( values[ 4 ] ) || 0\n\t\t};\n}\n\n$.fx.step.clip = function( fx ) {\n\tif ( !fx.clipInit ) {\n\t\tfx.start = $( fx.elem ).cssClip();\n\t\tif ( typeof fx.end === \"string\" ) {\n\t\t\tfx.end = parseClip( fx.end, fx.elem );\n\t\t}\n\t\tfx.clipInit = true;\n\t}\n\n\t$( fx.elem ).cssClip( {\n\t\ttop: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,\n\t\tright: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,\n\t\tbottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,\n\t\tleft: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left\n\t} );\n};\n\n} )();\n\n/******************************************************************************/\n/*********************************** EASING ***********************************/\n/******************************************************************************/\n\n( function() {\n\n// Based on easing equations from Robert Penner (http://www.robertpenner.com/easing)\n\nvar baseEasings = {};\n\n$.each( [ \"Quad\", \"Cubic\", \"Quart\", \"Quint\", \"Expo\" ], function( i, name ) {\n\tbaseEasings[ name ] = function( p ) {\n\t\treturn Math.pow( p, i + 2 );\n\t};\n} );\n\n$.extend( baseEasings, {\n\tSine: function( p ) {\n\t\treturn 1 - Math.cos( p * Math.PI / 2 );\n\t},\n\tCirc: function( p ) {\n\t\treturn 1 - Math.sqrt( 1 - p * p );\n\t},\n\tElastic: function( p ) {\n\t\treturn p === 0 || p === 1 ? p :\n\t\t\t-Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );\n\t},\n\tBack: function( p ) {\n\t\treturn p * p * ( 3 * p - 2 );\n\t},\n\tBounce: function( p ) {\n\t\tvar pow2,\n\t\t\tbounce = 4;\n\n\t\twhile ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}\n\t\treturn 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );\n\t}\n} );\n\n$.each( baseEasings, function( name, easeIn ) {\n\t$.easing[ \"easeIn\" + name ] = easeIn;\n\t$.easing[ \"easeOut\" + name ] = function( p ) {\n\t\treturn 1 - easeIn( 1 - p );\n\t};\n\t$.easing[ \"easeInOut\" + name ] = function( p ) {\n\t\treturn p < 0.5 ?\n\t\t\teaseIn( p * 2 ) / 2 :\n\t\t\t1 - easeIn( p * -2 + 2 ) / 2;\n\t};\n} );\n\n} )();\n\nvar effect = $.effects;\n\n\n/*!\n * jQuery UI Effects Blind 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Blind Effect\n//>>group: Effects\n//>>description: Blinds the element.\n//>>docs: http://api.jqueryui.com/blind-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectBlind = $.effects.define( \"blind\", \"hide\", function( options, done ) {\n\tvar map = {\n\t\t\tup: [ \"bottom\", \"top\" ],\n\t\t\tvertical: [ \"bottom\", \"top\" ],\n\t\t\tdown: [ \"top\", \"bottom\" ],\n\t\t\tleft: [ \"right\", \"left\" ],\n\t\t\thorizontal: [ \"right\", \"left\" ],\n\t\t\tright: [ \"left\", \"right\" ]\n\t\t},\n\t\telement = $( this ),\n\t\tdirection = options.direction || \"up\",\n\t\tstart = element.cssClip(),\n\t\tanimate = { clip: $.extend( {}, start ) },\n\t\tplaceholder = $.effects.createPlaceholder( element );\n\n\tanimate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];\n\n\tif ( options.mode === \"show\" ) {\n\t\telement.cssClip( animate.clip );\n\t\tif ( placeholder ) {\n\t\t\tplaceholder.css( $.effects.clipToBox( animate ) );\n\t\t}\n\n\t\tanimate.clip = start;\n\t}\n\n\tif ( placeholder ) {\n\t\tplaceholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );\n\t}\n\n\telement.animate( animate, {\n\t\tqueue: false,\n\t\tduration: options.duration,\n\t\teasing: options.easing,\n\t\tcomplete: done\n\t} );\n} );\n\n\n/*!\n * jQuery UI Effects Bounce 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Bounce Effect\n//>>group: Effects\n//>>description: Bounces an element horizontally or vertically n times.\n//>>docs: http://api.jqueryui.com/bounce-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectBounce = $.effects.define( \"bounce\", function( options, done ) {\n\tvar upAnim, downAnim, refValue,\n\t\telement = $( this ),\n\n\t\t// Defaults:\n\t\tmode = options.mode,\n\t\thide = mode === \"hide\",\n\t\tshow = mode === \"show\",\n\t\tdirection = options.direction || \"up\",\n\t\tdistance = options.distance,\n\t\ttimes = options.times || 5,\n\n\t\t// Number of internal animations\n\t\tanims = times * 2 + ( show || hide ? 1 : 0 ),\n\t\tspeed = options.duration / anims,\n\t\teasing = options.easing,\n\n\t\t// Utility:\n\t\tref = ( direction === \"up\" || direction === \"down\" ) ? \"top\" : \"left\",\n\t\tmotion = ( direction === \"up\" || direction === \"left\" ),\n\t\ti = 0,\n\n\t\tqueuelen = element.queue().length;\n\n\t$.effects.createPlaceholder( element );\n\n\trefValue = element.css( ref );\n\n\t// Default distance for the BIGGEST bounce is the outer Distance / 3\n\tif ( !distance ) {\n\t\tdistance = element[ ref === \"top\" ? \"outerHeight\" : \"outerWidth\" ]() / 3;\n\t}\n\n\tif ( show ) {\n\t\tdownAnim = { opacity: 1 };\n\t\tdownAnim[ ref ] = refValue;\n\n\t\t// If we are showing, force opacity 0 and set the initial position\n\t\t// then do the \"first\" animation\n\t\telement\n\t\t\t.css( \"opacity\", 0 )\n\t\t\t.css( ref, motion ? -distance * 2 : distance * 2 )\n\t\t\t.animate( downAnim, speed, easing );\n\t}\n\n\t// Start at the smallest distance if we are hiding\n\tif ( hide ) {\n\t\tdistance = distance / Math.pow( 2, times - 1 );\n\t}\n\n\tdownAnim = {};\n\tdownAnim[ ref ] = refValue;\n\n\t// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here\n\tfor ( ; i < times; i++ ) {\n\t\tupAnim = {};\n\t\tupAnim[ ref ] = ( motion ? \"-=\" : \"+=\" ) + distance;\n\n\t\telement\n\t\t\t.animate( upAnim, speed, easing )\n\t\t\t.animate( downAnim, speed, easing );\n\n\t\tdistance = hide ? distance * 2 : distance / 2;\n\t}\n\n\t// Last Bounce when Hiding\n\tif ( hide ) {\n\t\tupAnim = { opacity: 0 };\n\t\tupAnim[ ref ] = ( motion ? \"-=\" : \"+=\" ) + distance;\n\n\t\telement.animate( upAnim, speed, easing );\n\t}\n\n\telement.queue( done );\n\n\t$.effects.unshift( element, queuelen, anims + 1 );\n} );\n\n\n/*!\n * jQuery UI Effects Clip 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Clip Effect\n//>>group: Effects\n//>>description: Clips the element on and off like an old TV.\n//>>docs: http://api.jqueryui.com/clip-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectClip = $.effects.define( \"clip\", \"hide\", function( options, done ) {\n\tvar start,\n\t\tanimate = {},\n\t\telement = $( this ),\n\t\tdirection = options.direction || \"vertical\",\n\t\tboth = direction === \"both\",\n\t\thorizontal = both || direction === \"horizontal\",\n\t\tvertical = both || direction === \"vertical\";\n\n\tstart = element.cssClip();\n\tanimate.clip = {\n\t\ttop: vertical ? ( start.bottom - start.top ) / 2 : start.top,\n\t\tright: horizontal ? ( start.right - start.left ) / 2 : start.right,\n\t\tbottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,\n\t\tleft: horizontal ? ( start.right - start.left ) / 2 : start.left\n\t};\n\n\t$.effects.createPlaceholder( element );\n\n\tif ( options.mode === \"show\" ) {\n\t\telement.cssClip( animate.clip );\n\t\tanimate.clip = start;\n\t}\n\n\telement.animate( animate, {\n\t\tqueue: false,\n\t\tduration: options.duration,\n\t\teasing: options.easing,\n\t\tcomplete: done\n\t} );\n\n} );\n\n\n/*!\n * jQuery UI Effects Drop 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Drop Effect\n//>>group: Effects\n//>>description: Moves an element in one direction and hides it at the same time.\n//>>docs: http://api.jqueryui.com/drop-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectDrop = $.effects.define( \"drop\", \"hide\", function( options, done ) {\n\n\tvar distance,\n\t\telement = $( this ),\n\t\tmode = options.mode,\n\t\tshow = mode === \"show\",\n\t\tdirection = options.direction || \"left\",\n\t\tref = ( direction === \"up\" || direction === \"down\" ) ? \"top\" : \"left\",\n\t\tmotion = ( direction === \"up\" || direction === \"left\" ) ? \"-=\" : \"+=\",\n\t\toppositeMotion = ( motion === \"+=\" ) ? \"-=\" : \"+=\",\n\t\tanimation = {\n\t\t\topacity: 0\n\t\t};\n\n\t$.effects.createPlaceholder( element );\n\n\tdistance = options.distance ||\n\t\telement[ ref === \"top\" ? \"outerHeight\" : \"outerWidth\" ]( true ) / 2;\n\n\tanimation[ ref ] = motion + distance;\n\n\tif ( show ) {\n\t\telement.css( animation );\n\n\t\tanimation[ ref ] = oppositeMotion + distance;\n\t\tanimation.opacity = 1;\n\t}\n\n\t// Animate\n\telement.animate( animation, {\n\t\tqueue: false,\n\t\tduration: options.duration,\n\t\teasing: options.easing,\n\t\tcomplete: done\n\t} );\n} );\n\n\n/*!\n * jQuery UI Effects Explode 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Explode Effect\n//>>group: Effects\n// jscs:disable maximumLineLength\n//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.\n// jscs:enable maximumLineLength\n//>>docs: http://api.jqueryui.com/explode-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectExplode = $.effects.define( \"explode\", \"hide\", function( options, done ) {\n\n\tvar i, j, left, top, mx, my,\n\t\trows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,\n\t\tcells = rows,\n\t\telement = $( this ),\n\t\tmode = options.mode,\n\t\tshow = mode === \"show\",\n\n\t\t// Show and then visibility:hidden the element before calculating offset\n\t\toffset = element.show().css( \"visibility\", \"hidden\" ).offset(),\n\n\t\t// Width and height of a piece\n\t\twidth = Math.ceil( element.outerWidth() / cells ),\n\t\theight = Math.ceil( element.outerHeight() / rows ),\n\t\tpieces = [];\n\n\t// Children animate complete:\n\tfunction childComplete() {\n\t\tpieces.push( this );\n\t\tif ( pieces.length === rows * cells ) {\n\t\t\tanimComplete();\n\t\t}\n\t}\n\n\t// Clone the element for each row and cell.\n\tfor ( i = 0; i < rows; i++ ) { // ===>\n\t\ttop = offset.top + i * height;\n\t\tmy = i - ( rows - 1 ) / 2;\n\n\t\tfor ( j = 0; j < cells; j++ ) { // |||\n\t\t\tleft = offset.left + j * width;\n\t\t\tmx = j - ( cells - 1 ) / 2;\n\n\t\t\t// Create a clone of the now hidden main element that will be absolute positioned\n\t\t\t// within a wrapper div off the -left and -top equal to size of our pieces\n\t\t\telement\n\t\t\t\t.clone()\n\t\t\t\t.appendTo( \"body\" )\n\t\t\t\t.wrap( \"<div></div>\" )\n\t\t\t\t.css( {\n\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\tvisibility: \"visible\",\n\t\t\t\t\tleft: -j * width,\n\t\t\t\t\ttop: -i * height\n\t\t\t\t} )\n\n\t\t\t\t// Select the wrapper - make it overflow: hidden and absolute positioned based on\n\t\t\t\t// where the original was located +left and +top equal to the size of pieces\n\t\t\t\t.parent()\n\t\t\t\t\t.addClass( \"ui-effects-explode\" )\n\t\t\t\t\t.css( {\n\t\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\t\toverflow: \"hidden\",\n\t\t\t\t\t\twidth: width,\n\t\t\t\t\t\theight: height,\n\t\t\t\t\t\tleft: left + ( show ? mx * width : 0 ),\n\t\t\t\t\t\ttop: top + ( show ? my * height : 0 ),\n\t\t\t\t\t\topacity: show ? 0 : 1\n\t\t\t\t\t} )\n\t\t\t\t\t.animate( {\n\t\t\t\t\t\tleft: left + ( show ? 0 : mx * width ),\n\t\t\t\t\t\ttop: top + ( show ? 0 : my * height ),\n\t\t\t\t\t\topacity: show ? 1 : 0\n\t\t\t\t\t}, options.duration || 500, options.easing, childComplete );\n\t\t}\n\t}\n\n\tfunction animComplete() {\n\t\telement.css( {\n\t\t\tvisibility: \"visible\"\n\t\t} );\n\t\t$( pieces ).remove();\n\t\tdone();\n\t}\n} );\n\n\n/*!\n * jQuery UI Effects Fade 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Fade Effect\n//>>group: Effects\n//>>description: Fades the element.\n//>>docs: http://api.jqueryui.com/fade-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectFade = $.effects.define( \"fade\", \"toggle\", function( options, done ) {\n\tvar show = options.mode === \"show\";\n\n\t$( this )\n\t\t.css( \"opacity\", show ? 0 : 1 )\n\t\t.animate( {\n\t\t\topacity: show ? 1 : 0\n\t\t}, {\n\t\t\tqueue: false,\n\t\t\tduration: options.duration,\n\t\t\teasing: options.easing,\n\t\t\tcomplete: done\n\t\t} );\n} );\n\n\n/*!\n * jQuery UI Effects Fold 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Fold Effect\n//>>group: Effects\n//>>description: Folds an element first horizontally and then vertically.\n//>>docs: http://api.jqueryui.com/fold-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectFold = $.effects.define( \"fold\", \"hide\", function( options, done ) {\n\n\t// Create element\n\tvar element = $( this ),\n\t\tmode = options.mode,\n\t\tshow = mode === \"show\",\n\t\thide = mode === \"hide\",\n\t\tsize = options.size || 15,\n\t\tpercent = /([0-9]+)%/.exec( size ),\n\t\thorizFirst = !!options.horizFirst,\n\t\tref = horizFirst ? [ \"right\", \"bottom\" ] : [ \"bottom\", \"right\" ],\n\t\tduration = options.duration / 2,\n\n\t\tplaceholder = $.effects.createPlaceholder( element ),\n\n\t\tstart = element.cssClip(),\n\t\tanimation1 = { clip: $.extend( {}, start ) },\n\t\tanimation2 = { clip: $.extend( {}, start ) },\n\n\t\tdistance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],\n\n\t\tqueuelen = element.queue().length;\n\n\tif ( percent ) {\n\t\tsize = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];\n\t}\n\tanimation1.clip[ ref[ 0 ] ] = size;\n\tanimation2.clip[ ref[ 0 ] ] = size;\n\tanimation2.clip[ ref[ 1 ] ] = 0;\n\n\tif ( show ) {\n\t\telement.cssClip( animation2.clip );\n\t\tif ( placeholder ) {\n\t\t\tplaceholder.css( $.effects.clipToBox( animation2 ) );\n\t\t}\n\n\t\tanimation2.clip = start;\n\t}\n\n\t// Animate\n\telement\n\t\t.queue( function( next ) {\n\t\t\tif ( placeholder ) {\n\t\t\t\tplaceholder\n\t\t\t\t\t.animate( $.effects.clipToBox( animation1 ), duration, options.easing )\n\t\t\t\t\t.animate( $.effects.clipToBox( animation2 ), duration, options.easing );\n\t\t\t}\n\n\t\t\tnext();\n\t\t} )\n\t\t.animate( animation1, duration, options.easing )\n\t\t.animate( animation2, duration, options.easing )\n\t\t.queue( done );\n\n\t$.effects.unshift( element, queuelen, 4 );\n} );\n\n\n/*!\n * jQuery UI Effects Highlight 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Highlight Effect\n//>>group: Effects\n//>>description: Highlights the background of an element in a defined color for a custom duration.\n//>>docs: http://api.jqueryui.com/highlight-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectHighlight = $.effects.define( \"highlight\", \"show\", function( options, done ) {\n\tvar element = $( this ),\n\t\tanimation = {\n\t\t\tbackgroundColor: element.css( \"backgroundColor\" )\n\t\t};\n\n\tif ( options.mode === \"hide\" ) {\n\t\tanimation.opacity = 0;\n\t}\n\n\t$.effects.saveStyle( element );\n\n\telement\n\t\t.css( {\n\t\t\tbackgroundImage: \"none\",\n\t\t\tbackgroundColor: options.color || \"#ffff99\"\n\t\t} )\n\t\t.animate( animation, {\n\t\t\tqueue: false,\n\t\t\tduration: options.duration,\n\t\t\teasing: options.easing,\n\t\t\tcomplete: done\n\t\t} );\n} );\n\n\n/*!\n * jQuery UI Effects Size 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Size Effect\n//>>group: Effects\n//>>description: Resize an element to a specified width and height.\n//>>docs: http://api.jqueryui.com/size-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectSize = $.effects.define( \"size\", function( options, done ) {\n\n\t// Create element\n\tvar baseline, factor, temp,\n\t\telement = $( this ),\n\n\t\t// Copy for children\n\t\tcProps = [ \"fontSize\" ],\n\t\tvProps = [ \"borderTopWidth\", \"borderBottomWidth\", \"paddingTop\", \"paddingBottom\" ],\n\t\thProps = [ \"borderLeftWidth\", \"borderRightWidth\", \"paddingLeft\", \"paddingRight\" ],\n\n\t\t// Set options\n\t\tmode = options.mode,\n\t\trestore = mode !== \"effect\",\n\t\tscale = options.scale || \"both\",\n\t\torigin = options.origin || [ \"middle\", \"center\" ],\n\t\tposition = element.css( \"position\" ),\n\t\tpos = element.position(),\n\t\toriginal = $.effects.scaledDimensions( element ),\n\t\tfrom = options.from || original,\n\t\tto = options.to || $.effects.scaledDimensions( element, 0 );\n\n\t$.effects.createPlaceholder( element );\n\n\tif ( mode === \"show\" ) {\n\t\ttemp = from;\n\t\tfrom = to;\n\t\tto = temp;\n\t}\n\n\t// Set scaling factor\n\tfactor = {\n\t\tfrom: {\n\t\t\ty: from.height / original.height,\n\t\t\tx: from.width / original.width\n\t\t},\n\t\tto: {\n\t\t\ty: to.height / original.height,\n\t\t\tx: to.width / original.width\n\t\t}\n\t};\n\n\t// Scale the css box\n\tif ( scale === \"box\" || scale === \"both\" ) {\n\n\t\t// Vertical props scaling\n\t\tif ( factor.from.y !== factor.to.y ) {\n\t\t\tfrom = $.effects.setTransition( element, vProps, factor.from.y, from );\n\t\t\tto = $.effects.setTransition( element, vProps, factor.to.y, to );\n\t\t}\n\n\t\t// Horizontal props scaling\n\t\tif ( factor.from.x !== factor.to.x ) {\n\t\t\tfrom = $.effects.setTransition( element, hProps, factor.from.x, from );\n\t\t\tto = $.effects.setTransition( element, hProps, factor.to.x, to );\n\t\t}\n\t}\n\n\t// Scale the content\n\tif ( scale === \"content\" || scale === \"both\" ) {\n\n\t\t// Vertical props scaling\n\t\tif ( factor.from.y !== factor.to.y ) {\n\t\t\tfrom = $.effects.setTransition( element, cProps, factor.from.y, from );\n\t\t\tto = $.effects.setTransition( element, cProps, factor.to.y, to );\n\t\t}\n\t}\n\n\t// Adjust the position properties based on the provided origin points\n\tif ( origin ) {\n\t\tbaseline = $.effects.getBaseline( origin, original );\n\t\tfrom.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;\n\t\tfrom.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;\n\t\tto.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;\n\t\tto.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;\n\t}\n\telement.css( from );\n\n\t// Animate the children if desired\n\tif ( scale === \"content\" || scale === \"both\" ) {\n\n\t\tvProps = vProps.concat( [ \"marginTop\", \"marginBottom\" ] ).concat( cProps );\n\t\thProps = hProps.concat( [ \"marginLeft\", \"marginRight\" ] );\n\n\t\t// Only animate children with width attributes specified\n\t\t// TODO: is this right? should we include anything with css width specified as well\n\t\telement.find( \"*[width]\" ).each( function() {\n\t\t\tvar child = $( this ),\n\t\t\t\tchildOriginal = $.effects.scaledDimensions( child ),\n\t\t\t\tchildFrom = {\n\t\t\t\t\theight: childOriginal.height * factor.from.y,\n\t\t\t\t\twidth: childOriginal.width * factor.from.x,\n\t\t\t\t\touterHeight: childOriginal.outerHeight * factor.from.y,\n\t\t\t\t\touterWidth: childOriginal.outerWidth * factor.from.x\n\t\t\t\t},\n\t\t\t\tchildTo = {\n\t\t\t\t\theight: childOriginal.height * factor.to.y,\n\t\t\t\t\twidth: childOriginal.width * factor.to.x,\n\t\t\t\t\touterHeight: childOriginal.height * factor.to.y,\n\t\t\t\t\touterWidth: childOriginal.width * factor.to.x\n\t\t\t\t};\n\n\t\t\t// Vertical props scaling\n\t\t\tif ( factor.from.y !== factor.to.y ) {\n\t\t\t\tchildFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );\n\t\t\t\tchildTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );\n\t\t\t}\n\n\t\t\t// Horizontal props scaling\n\t\t\tif ( factor.from.x !== factor.to.x ) {\n\t\t\t\tchildFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );\n\t\t\t\tchildTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );\n\t\t\t}\n\n\t\t\tif ( restore ) {\n\t\t\t\t$.effects.saveStyle( child );\n\t\t\t}\n\n\t\t\t// Animate children\n\t\t\tchild.css( childFrom );\n\t\t\tchild.animate( childTo, options.duration, options.easing, function() {\n\n\t\t\t\t// Restore children\n\t\t\t\tif ( restore ) {\n\t\t\t\t\t$.effects.restoreStyle( child );\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\t}\n\n\t// Animate\n\telement.animate( to, {\n\t\tqueue: false,\n\t\tduration: options.duration,\n\t\teasing: options.easing,\n\t\tcomplete: function() {\n\n\t\t\tvar offset = element.offset();\n\n\t\t\tif ( to.opacity === 0 ) {\n\t\t\t\telement.css( \"opacity\", from.opacity );\n\t\t\t}\n\n\t\t\tif ( !restore ) {\n\t\t\t\telement\n\t\t\t\t\t.css( \"position\", position === \"static\" ? \"relative\" : position )\n\t\t\t\t\t.offset( offset );\n\n\t\t\t\t// Need to save style here so that automatic style restoration\n\t\t\t\t// doesn't restore to the original styles from before the animation.\n\t\t\t\t$.effects.saveStyle( element );\n\t\t\t}\n\n\t\t\tdone();\n\t\t}\n\t} );\n\n} );\n\n\n/*!\n * jQuery UI Effects Scale 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Scale Effect\n//>>group: Effects\n//>>description: Grows or shrinks an element and its content.\n//>>docs: http://api.jqueryui.com/scale-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectScale = $.effects.define( \"scale\", function( options, done ) {\n\n\t// Create element\n\tvar el = $( this ),\n\t\tmode = options.mode,\n\t\tpercent = parseInt( options.percent, 10 ) ||\n\t\t\t( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== \"effect\" ? 0 : 100 ) ),\n\n\t\tnewOptions = $.extend( true, {\n\t\t\tfrom: $.effects.scaledDimensions( el ),\n\t\t\tto: $.effects.scaledDimensions( el, percent, options.direction || \"both\" ),\n\t\t\torigin: options.origin || [ \"middle\", \"center\" ]\n\t\t}, options );\n\n\t// Fade option to support puff\n\tif ( options.fade ) {\n\t\tnewOptions.from.opacity = 1;\n\t\tnewOptions.to.opacity = 0;\n\t}\n\n\t$.effects.effect.size.call( this, newOptions, done );\n} );\n\n\n/*!\n * jQuery UI Effects Puff 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Puff Effect\n//>>group: Effects\n//>>description: Creates a puff effect by scaling the element up and hiding it at the same time.\n//>>docs: http://api.jqueryui.com/puff-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectPuff = $.effects.define( \"puff\", \"hide\", function( options, done ) {\n\tvar newOptions = $.extend( true, {}, options, {\n\t\tfade: true,\n\t\tpercent: parseInt( options.percent, 10 ) || 150\n\t} );\n\n\t$.effects.effect.scale.call( this, newOptions, done );\n} );\n\n\n/*!\n * jQuery UI Effects Pulsate 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Pulsate Effect\n//>>group: Effects\n//>>description: Pulsates an element n times by changing the opacity to zero and back.\n//>>docs: http://api.jqueryui.com/pulsate-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectPulsate = $.effects.define( \"pulsate\", \"show\", function( options, done ) {\n\tvar element = $( this ),\n\t\tmode = options.mode,\n\t\tshow = mode === \"show\",\n\t\thide = mode === \"hide\",\n\t\tshowhide = show || hide,\n\n\t\t// Showing or hiding leaves off the \"last\" animation\n\t\tanims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),\n\t\tduration = options.duration / anims,\n\t\tanimateTo = 0,\n\t\ti = 1,\n\t\tqueuelen = element.queue().length;\n\n\tif ( show || !element.is( \":visible\" ) ) {\n\t\telement.css( \"opacity\", 0 ).show();\n\t\tanimateTo = 1;\n\t}\n\n\t// Anims - 1 opacity \"toggles\"\n\tfor ( ; i < anims; i++ ) {\n\t\telement.animate( { opacity: animateTo }, duration, options.easing );\n\t\tanimateTo = 1 - animateTo;\n\t}\n\n\telement.animate( { opacity: animateTo }, duration, options.easing );\n\n\telement.queue( done );\n\n\t$.effects.unshift( element, queuelen, anims + 1 );\n} );\n\n\n/*!\n * jQuery UI Effects Shake 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Shake Effect\n//>>group: Effects\n//>>description: Shakes an element horizontally or vertically n times.\n//>>docs: http://api.jqueryui.com/shake-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectShake = $.effects.define( \"shake\", function( options, done ) {\n\n\tvar i = 1,\n\t\telement = $( this ),\n\t\tdirection = options.direction || \"left\",\n\t\tdistance = options.distance || 20,\n\t\ttimes = options.times || 3,\n\t\tanims = times * 2 + 1,\n\t\tspeed = Math.round( options.duration / anims ),\n\t\tref = ( direction === \"up\" || direction === \"down\" ) ? \"top\" : \"left\",\n\t\tpositiveMotion = ( direction === \"up\" || direction === \"left\" ),\n\t\tanimation = {},\n\t\tanimation1 = {},\n\t\tanimation2 = {},\n\n\t\tqueuelen = element.queue().length;\n\n\t$.effects.createPlaceholder( element );\n\n\t// Animation\n\tanimation[ ref ] = ( positiveMotion ? \"-=\" : \"+=\" ) + distance;\n\tanimation1[ ref ] = ( positiveMotion ? \"+=\" : \"-=\" ) + distance * 2;\n\tanimation2[ ref ] = ( positiveMotion ? \"-=\" : \"+=\" ) + distance * 2;\n\n\t// Animate\n\telement.animate( animation, speed, options.easing );\n\n\t// Shakes\n\tfor ( ; i < times; i++ ) {\n\t\telement\n\t\t\t.animate( animation1, speed, options.easing )\n\t\t\t.animate( animation2, speed, options.easing );\n\t}\n\n\telement\n\t\t.animate( animation1, speed, options.easing )\n\t\t.animate( animation, speed / 2, options.easing )\n\t\t.queue( done );\n\n\t$.effects.unshift( element, queuelen, anims + 1 );\n} );\n\n\n/*!\n * jQuery UI Effects Slide 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Slide Effect\n//>>group: Effects\n//>>description: Slides an element in and out of the viewport.\n//>>docs: http://api.jqueryui.com/slide-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effectsEffectSlide = $.effects.define( \"slide\", \"show\", function( options, done ) {\n\tvar startClip, startRef,\n\t\telement = $( this ),\n\t\tmap = {\n\t\t\tup: [ \"bottom\", \"top\" ],\n\t\t\tdown: [ \"top\", \"bottom\" ],\n\t\t\tleft: [ \"right\", \"left\" ],\n\t\t\tright: [ \"left\", \"right\" ]\n\t\t},\n\t\tmode = options.mode,\n\t\tdirection = options.direction || \"left\",\n\t\tref = ( direction === \"up\" || direction === \"down\" ) ? \"top\" : \"left\",\n\t\tpositiveMotion = ( direction === \"up\" || direction === \"left\" ),\n\t\tdistance = options.distance ||\n\t\t\telement[ ref === \"top\" ? \"outerHeight\" : \"outerWidth\" ]( true ),\n\t\tanimation = {};\n\n\t$.effects.createPlaceholder( element );\n\n\tstartClip = element.cssClip();\n\tstartRef = element.position()[ ref ];\n\n\t// Define hide animation\n\tanimation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;\n\tanimation.clip = element.cssClip();\n\tanimation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];\n\n\t// Reverse the animation if we're showing\n\tif ( mode === \"show\" ) {\n\t\telement.cssClip( animation.clip );\n\t\telement.css( ref, animation[ ref ] );\n\t\tanimation.clip = startClip;\n\t\tanimation[ ref ] = startRef;\n\t}\n\n\t// Actually animate\n\telement.animate( animation, {\n\t\tqueue: false,\n\t\tduration: options.duration,\n\t\teasing: options.easing,\n\t\tcomplete: done\n\t} );\n} );\n\n\n/*!\n * jQuery UI Effects Transfer 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n */\n\n//>>label: Transfer Effect\n//>>group: Effects\n//>>description: Displays a transfer effect from one element to another.\n//>>docs: http://api.jqueryui.com/transfer-effect/\n//>>demos: http://jqueryui.com/effect/\n\n\n\nvar effect;\nif ( $.uiBackCompat !== false ) {\n\teffect = $.effects.define( \"transfer\", function( options, done ) {\n\t\t$( this ).transfer( options, done );\n\t} );\n}\nvar effectsEffectTransfer = effect;\n\n\n\n\n}));"
  },
  {
    "path": "functional-samples/sample.bookmarks/third-party/jquery-ui.css",
    "content": "/*! jQuery UI - v1.12.1 - 2021-03-02\n* http://jqueryui.com\n* Includes: draggable.css, core.css, resizable.css, selectable.css, sortable.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, progressbar.css, selectmenu.css, slider.css, spinner.css, tabs.css, tooltip.css, theme.css\n* To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=base&cornerRadiusShadow=8px&offsetLeftShadow=0px&offsetTopShadow=0px&thicknessShadow=5px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=666666&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=aaaaaa&iconColorError=cc0000&fcError=5f3f3f&borderColorError=f1a899&bgTextureError=flat&bgColorError=fddfdf&iconColorHighlight=777620&fcHighlight=777620&borderColorHighlight=dad55e&bgTextureHighlight=flat&bgColorHighlight=fffa90&iconColorActive=ffffff&fcActive=ffffff&borderColorActive=003eff&bgTextureActive=flat&bgColorActive=007fff&iconColorHover=555555&fcHover=2b2b2b&borderColorHover=cccccc&bgTextureHover=flat&bgColorHover=ededed&iconColorDefault=777777&fcDefault=454545&borderColorDefault=c5c5c5&bgTextureDefault=flat&bgColorDefault=f6f6f6&iconColorContent=444444&fcContent=333333&borderColorContent=dddddd&bgTextureContent=flat&bgColorContent=ffffff&iconColorHeader=444444&fcHeader=333333&borderColorHeader=dddddd&bgTextureHeader=flat&bgColorHeader=e9e9e9&cornerRadius=3px&fwDefault=normal&fsDefault=1em&ffDefault=Arial%2CHelvetica%2Csans-serif\n* Copyright jQuery Foundation and other contributors; Licensed MIT */\n\n.ui-draggable-handle {\n\t-ms-touch-action: none;\n\ttouch-action: none;\n}\n/* Layout helpers\n----------------------------------*/\n.ui-helper-hidden {\n\tdisplay: none;\n}\n.ui-helper-hidden-accessible {\n\tborder: 0;\n\tclip: rect(0 0 0 0);\n\theight: 1px;\n\tmargin: -1px;\n\toverflow: hidden;\n\tpadding: 0;\n\tposition: absolute;\n\twidth: 1px;\n}\n.ui-helper-reset {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\toutline: 0;\n\tline-height: 1.3;\n\ttext-decoration: none;\n\tfont-size: 100%;\n\tlist-style: none;\n}\n.ui-helper-clearfix:before,\n.ui-helper-clearfix:after {\n\tcontent: \"\";\n\tdisplay: table;\n\tborder-collapse: collapse;\n}\n.ui-helper-clearfix:after {\n\tclear: both;\n}\n.ui-helper-zfix {\n\twidth: 100%;\n\theight: 100%;\n\ttop: 0;\n\tleft: 0;\n\tposition: absolute;\n\topacity: 0;\n\tfilter:Alpha(Opacity=0); /* support: IE8 */\n}\n\n.ui-front {\n\tz-index: 100;\n}\n\n\n/* Interaction Cues\n----------------------------------*/\n.ui-state-disabled {\n\tcursor: default !important;\n\tpointer-events: none;\n}\n\n\n/* Icons\n----------------------------------*/\n.ui-icon {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tmargin-top: -.25em;\n\tposition: relative;\n\ttext-indent: -99999px;\n\toverflow: hidden;\n\tbackground-repeat: no-repeat;\n}\n\n.ui-widget-icon-block {\n\tleft: 50%;\n\tmargin-left: -8px;\n\tdisplay: block;\n}\n\n/* Misc visuals\n----------------------------------*/\n\n/* Overlays */\n.ui-widget-overlay {\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n}\n.ui-resizable {\n\tposition: relative;\n}\n.ui-resizable-handle {\n\tposition: absolute;\n\tfont-size: 0.1px;\n\tdisplay: block;\n\t-ms-touch-action: none;\n\ttouch-action: none;\n}\n.ui-resizable-disabled .ui-resizable-handle,\n.ui-resizable-autohide .ui-resizable-handle {\n\tdisplay: none;\n}\n.ui-resizable-n {\n\tcursor: n-resize;\n\theight: 7px;\n\twidth: 100%;\n\ttop: -5px;\n\tleft: 0;\n}\n.ui-resizable-s {\n\tcursor: s-resize;\n\theight: 7px;\n\twidth: 100%;\n\tbottom: -5px;\n\tleft: 0;\n}\n.ui-resizable-e {\n\tcursor: e-resize;\n\twidth: 7px;\n\tright: -5px;\n\ttop: 0;\n\theight: 100%;\n}\n.ui-resizable-w {\n\tcursor: w-resize;\n\twidth: 7px;\n\tleft: -5px;\n\ttop: 0;\n\theight: 100%;\n}\n.ui-resizable-se {\n\tcursor: se-resize;\n\twidth: 12px;\n\theight: 12px;\n\tright: 1px;\n\tbottom: 1px;\n}\n.ui-resizable-sw {\n\tcursor: sw-resize;\n\twidth: 9px;\n\theight: 9px;\n\tleft: -5px;\n\tbottom: -5px;\n}\n.ui-resizable-nw {\n\tcursor: nw-resize;\n\twidth: 9px;\n\theight: 9px;\n\tleft: -5px;\n\ttop: -5px;\n}\n.ui-resizable-ne {\n\tcursor: ne-resize;\n\twidth: 9px;\n\theight: 9px;\n\tright: -5px;\n\ttop: -5px;\n}\n.ui-selectable {\n\t-ms-touch-action: none;\n\ttouch-action: none;\n}\n.ui-selectable-helper {\n\tposition: absolute;\n\tz-index: 100;\n\tborder: 1px dotted black;\n}\n.ui-sortable-handle {\n\t-ms-touch-action: none;\n\ttouch-action: none;\n}\n.ui-accordion .ui-accordion-header {\n\tdisplay: block;\n\tcursor: pointer;\n\tposition: relative;\n\tmargin: 2px 0 0 0;\n\tpadding: .5em .5em .5em .7em;\n\tfont-size: 100%;\n}\n.ui-accordion .ui-accordion-content {\n\tpadding: 1em 2.2em;\n\tborder-top: 0;\n\toverflow: auto;\n}\n.ui-autocomplete {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tcursor: default;\n}\n.ui-menu {\n\tlist-style: none;\n\tpadding: 0;\n\tmargin: 0;\n\tdisplay: block;\n\toutline: 0;\n}\n.ui-menu .ui-menu {\n\tposition: absolute;\n}\n.ui-menu .ui-menu-item {\n\tmargin: 0;\n\tcursor: pointer;\n\t/* support: IE10, see #8844 */\n\tlist-style-image: url(\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\");\n}\n.ui-menu .ui-menu-item-wrapper {\n\tposition: relative;\n\tpadding: 3px 1em 3px .4em;\n}\n.ui-menu .ui-menu-divider {\n\tmargin: 5px 0;\n\theight: 0;\n\tfont-size: 0;\n\tline-height: 0;\n\tborder-width: 1px 0 0 0;\n}\n.ui-menu .ui-state-focus,\n.ui-menu .ui-state-active {\n\tmargin: -1px;\n}\n\n/* icon support */\n.ui-menu-icons {\n\tposition: relative;\n}\n.ui-menu-icons .ui-menu-item-wrapper {\n\tpadding-left: 2em;\n}\n\n/* left-aligned */\n.ui-menu .ui-icon {\n\tposition: absolute;\n\ttop: 0;\n\tbottom: 0;\n\tleft: .2em;\n\tmargin: auto 0;\n}\n\n/* right-aligned */\n.ui-menu .ui-menu-icon {\n\tleft: auto;\n\tright: 0;\n}\n.ui-button {\n\tpadding: .4em 1em;\n\tdisplay: inline-block;\n\tposition: relative;\n\tline-height: normal;\n\tmargin-right: .1em;\n\tcursor: pointer;\n\tvertical-align: middle;\n\ttext-align: center;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n\n\t/* Support: IE <= 11 */\n\toverflow: visible;\n}\n\n.ui-button,\n.ui-button:link,\n.ui-button:visited,\n.ui-button:hover,\n.ui-button:active {\n\ttext-decoration: none;\n}\n\n/* to make room for the icon, a width needs to be set here */\n.ui-button-icon-only {\n\twidth: 2em;\n\tbox-sizing: border-box;\n\ttext-indent: -9999px;\n\twhite-space: nowrap;\n}\n\n/* no icon support for input elements */\ninput.ui-button.ui-button-icon-only {\n\ttext-indent: 0;\n}\n\n/* button icon element(s) */\n.ui-button-icon-only .ui-icon {\n\tposition: absolute;\n\ttop: 50%;\n\tleft: 50%;\n\tmargin-top: -8px;\n\tmargin-left: -8px;\n}\n\n.ui-button.ui-icon-notext .ui-icon {\n\tpadding: 0;\n\twidth: 2.1em;\n\theight: 2.1em;\n\ttext-indent: -9999px;\n\twhite-space: nowrap;\n\n}\n\ninput.ui-button.ui-icon-notext .ui-icon {\n\twidth: auto;\n\theight: auto;\n\ttext-indent: 0;\n\twhite-space: normal;\n\tpadding: .4em 1em;\n}\n\n/* workarounds */\n/* Support: Firefox 5 - 40 */\ninput.ui-button::-moz-focus-inner,\nbutton.ui-button::-moz-focus-inner {\n\tborder: 0;\n\tpadding: 0;\n}\n.ui-controlgroup {\n\tvertical-align: middle;\n\tdisplay: inline-block;\n}\n.ui-controlgroup > .ui-controlgroup-item {\n\tfloat: left;\n\tmargin-left: 0;\n\tmargin-right: 0;\n}\n.ui-controlgroup > .ui-controlgroup-item:focus,\n.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus {\n\tz-index: 9999;\n}\n.ui-controlgroup-vertical > .ui-controlgroup-item {\n\tdisplay: block;\n\tfloat: none;\n\twidth: 100%;\n\tmargin-top: 0;\n\tmargin-bottom: 0;\n\ttext-align: left;\n}\n.ui-controlgroup-vertical .ui-controlgroup-item {\n\tbox-sizing: border-box;\n}\n.ui-controlgroup .ui-controlgroup-label {\n\tpadding: .4em 1em;\n}\n.ui-controlgroup .ui-controlgroup-label span {\n\tfont-size: 80%;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item {\n\tborder-left: none;\n}\n.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item {\n\tborder-top: none;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content {\n\tborder-right: none;\n}\n.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content {\n\tborder-bottom: none;\n}\n\n/* Spinner specific style fixes */\n.ui-controlgroup-vertical .ui-spinner-input {\n\n\t/* Support: IE8 only, Android < 4.4 only */\n\twidth: 75%;\n\twidth: calc( 100% - 2.4em );\n}\n.ui-controlgroup-vertical .ui-spinner .ui-spinner-up {\n\tborder-top-style: solid;\n}\n\n.ui-checkboxradio-label .ui-icon-background {\n\tbox-shadow: inset 1px 1px 1px #ccc;\n\tborder-radius: .12em;\n\tborder: none;\n}\n.ui-checkboxradio-radio-label .ui-icon-background {\n\twidth: 16px;\n\theight: 16px;\n\tborder-radius: 1em;\n\toverflow: visible;\n\tborder: none;\n}\n.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,\n.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon {\n\tbackground-image: none;\n\twidth: 8px;\n\theight: 8px;\n\tborder-width: 4px;\n\tborder-style: solid;\n}\n.ui-checkboxradio-disabled {\n\tpointer-events: none;\n}\n.ui-datepicker {\n\twidth: 17em;\n\tpadding: .2em .2em 0;\n\tdisplay: none;\n}\n.ui-datepicker .ui-datepicker-header {\n\tposition: relative;\n\tpadding: .2em 0;\n}\n.ui-datepicker .ui-datepicker-prev,\n.ui-datepicker .ui-datepicker-next {\n\tposition: absolute;\n\ttop: 2px;\n\twidth: 1.8em;\n\theight: 1.8em;\n}\n.ui-datepicker .ui-datepicker-prev-hover,\n.ui-datepicker .ui-datepicker-next-hover {\n\ttop: 1px;\n}\n.ui-datepicker .ui-datepicker-prev {\n\tleft: 2px;\n}\n.ui-datepicker .ui-datepicker-next {\n\tright: 2px;\n}\n.ui-datepicker .ui-datepicker-prev-hover {\n\tleft: 1px;\n}\n.ui-datepicker .ui-datepicker-next-hover {\n\tright: 1px;\n}\n.ui-datepicker .ui-datepicker-prev span,\n.ui-datepicker .ui-datepicker-next span {\n\tdisplay: block;\n\tposition: absolute;\n\tleft: 50%;\n\tmargin-left: -8px;\n\ttop: 50%;\n\tmargin-top: -8px;\n}\n.ui-datepicker .ui-datepicker-title {\n\tmargin: 0 2.3em;\n\tline-height: 1.8em;\n\ttext-align: center;\n}\n.ui-datepicker .ui-datepicker-title select {\n\tfont-size: 1em;\n\tmargin: 1px 0;\n}\n.ui-datepicker select.ui-datepicker-month,\n.ui-datepicker select.ui-datepicker-year {\n\twidth: 45%;\n}\n.ui-datepicker table {\n\twidth: 100%;\n\tfont-size: .9em;\n\tborder-collapse: collapse;\n\tmargin: 0 0 .4em;\n}\n.ui-datepicker th {\n\tpadding: .7em .3em;\n\ttext-align: center;\n\tfont-weight: bold;\n\tborder: 0;\n}\n.ui-datepicker td {\n\tborder: 0;\n\tpadding: 1px;\n}\n.ui-datepicker td span,\n.ui-datepicker td a {\n\tdisplay: block;\n\tpadding: .2em;\n\ttext-align: right;\n\ttext-decoration: none;\n}\n.ui-datepicker .ui-datepicker-buttonpane {\n\tbackground-image: none;\n\tmargin: .7em 0 0 0;\n\tpadding: 0 .2em;\n\tborder-left: 0;\n\tborder-right: 0;\n\tborder-bottom: 0;\n}\n.ui-datepicker .ui-datepicker-buttonpane button {\n\tfloat: right;\n\tmargin: .5em .2em .4em;\n\tcursor: pointer;\n\tpadding: .2em .6em .3em .6em;\n\twidth: auto;\n\toverflow: visible;\n}\n.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {\n\tfloat: left;\n}\n\n/* with multiple calendars */\n.ui-datepicker.ui-datepicker-multi {\n\twidth: auto;\n}\n.ui-datepicker-multi .ui-datepicker-group {\n\tfloat: left;\n}\n.ui-datepicker-multi .ui-datepicker-group table {\n\twidth: 95%;\n\tmargin: 0 auto .4em;\n}\n.ui-datepicker-multi-2 .ui-datepicker-group {\n\twidth: 50%;\n}\n.ui-datepicker-multi-3 .ui-datepicker-group {\n\twidth: 33.3%;\n}\n.ui-datepicker-multi-4 .ui-datepicker-group {\n\twidth: 25%;\n}\n.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,\n.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {\n\tborder-left-width: 0;\n}\n.ui-datepicker-multi .ui-datepicker-buttonpane {\n\tclear: left;\n}\n.ui-datepicker-row-break {\n\tclear: both;\n\twidth: 100%;\n\tfont-size: 0;\n}\n\n/* RTL support */\n.ui-datepicker-rtl {\n\tdirection: rtl;\n}\n.ui-datepicker-rtl .ui-datepicker-prev {\n\tright: 2px;\n\tleft: auto;\n}\n.ui-datepicker-rtl .ui-datepicker-next {\n\tleft: 2px;\n\tright: auto;\n}\n.ui-datepicker-rtl .ui-datepicker-prev:hover {\n\tright: 1px;\n\tleft: auto;\n}\n.ui-datepicker-rtl .ui-datepicker-next:hover {\n\tleft: 1px;\n\tright: auto;\n}\n.ui-datepicker-rtl .ui-datepicker-buttonpane {\n\tclear: right;\n}\n.ui-datepicker-rtl .ui-datepicker-buttonpane button {\n\tfloat: left;\n}\n.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,\n.ui-datepicker-rtl .ui-datepicker-group {\n\tfloat: right;\n}\n.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,\n.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {\n\tborder-right-width: 0;\n\tborder-left-width: 1px;\n}\n\n/* Icons */\n.ui-datepicker .ui-icon {\n\tdisplay: block;\n\ttext-indent: -99999px;\n\toverflow: hidden;\n\tbackground-repeat: no-repeat;\n\tleft: .5em;\n\ttop: .3em;\n}\n.ui-dialog {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tpadding: .2em;\n\toutline: 0;\n}\n.ui-dialog .ui-dialog-titlebar {\n\tpadding: .4em 1em;\n\tposition: relative;\n}\n.ui-dialog .ui-dialog-title {\n\tfloat: left;\n\tmargin: .1em 0;\n\twhite-space: nowrap;\n\twidth: 90%;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n.ui-dialog .ui-dialog-titlebar-close {\n\tposition: absolute;\n\tright: .3em;\n\ttop: 50%;\n\twidth: 20px;\n\tmargin: -10px 0 0 0;\n\tpadding: 1px;\n\theight: 20px;\n}\n.ui-dialog .ui-dialog-content {\n\tposition: relative;\n\tborder: 0;\n\tpadding: .5em 1em;\n\tbackground: none;\n\toverflow: auto;\n}\n.ui-dialog .ui-dialog-buttonpane {\n\ttext-align: left;\n\tborder-width: 1px 0 0 0;\n\tbackground-image: none;\n\tmargin-top: .5em;\n\tpadding: .3em 1em .5em .4em;\n}\n.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {\n\tfloat: right;\n}\n.ui-dialog .ui-dialog-buttonpane button {\n\tmargin: .5em .4em .5em 0;\n\tcursor: pointer;\n}\n.ui-dialog .ui-resizable-n {\n\theight: 2px;\n\ttop: 0;\n}\n.ui-dialog .ui-resizable-e {\n\twidth: 2px;\n\tright: 0;\n}\n.ui-dialog .ui-resizable-s {\n\theight: 2px;\n\tbottom: 0;\n}\n.ui-dialog .ui-resizable-w {\n\twidth: 2px;\n\tleft: 0;\n}\n.ui-dialog .ui-resizable-se,\n.ui-dialog .ui-resizable-sw,\n.ui-dialog .ui-resizable-ne,\n.ui-dialog .ui-resizable-nw {\n\twidth: 7px;\n\theight: 7px;\n}\n.ui-dialog .ui-resizable-se {\n\tright: 0;\n\tbottom: 0;\n}\n.ui-dialog .ui-resizable-sw {\n\tleft: 0;\n\tbottom: 0;\n}\n.ui-dialog .ui-resizable-ne {\n\tright: 0;\n\ttop: 0;\n}\n.ui-dialog .ui-resizable-nw {\n\tleft: 0;\n\ttop: 0;\n}\n.ui-draggable .ui-dialog-titlebar {\n\tcursor: move;\n}\n.ui-progressbar {\n\theight: 2em;\n\ttext-align: left;\n\toverflow: hidden;\n}\n.ui-progressbar .ui-progressbar-value {\n\tmargin: -1px;\n\theight: 100%;\n}\n.ui-progressbar .ui-progressbar-overlay {\n\tbackground: url(\"data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==\");\n\theight: 100%;\n\tfilter: alpha(opacity=25); /* support: IE8 */\n\topacity: 0.25;\n}\n.ui-progressbar-indeterminate .ui-progressbar-value {\n\tbackground-image: none;\n}\n.ui-selectmenu-menu {\n\tpadding: 0;\n\tmargin: 0;\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tdisplay: none;\n}\n.ui-selectmenu-menu .ui-menu {\n\toverflow: auto;\n\toverflow-x: hidden;\n\tpadding-bottom: 1px;\n}\n.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {\n\tfont-size: 1em;\n\tfont-weight: bold;\n\tline-height: 1.5;\n\tpadding: 2px 0.4em;\n\tmargin: 0.5em 0 0 0;\n\theight: auto;\n\tborder: 0;\n}\n.ui-selectmenu-open {\n\tdisplay: block;\n}\n.ui-selectmenu-text {\n\tdisplay: block;\n\tmargin-right: 20px;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n.ui-selectmenu-button.ui-button {\n\ttext-align: left;\n\twhite-space: nowrap;\n\twidth: 14em;\n}\n.ui-selectmenu-icon.ui-icon {\n\tfloat: right;\n\tmargin-top: 0;\n}\n.ui-slider {\n\tposition: relative;\n\ttext-align: left;\n}\n.ui-slider .ui-slider-handle {\n\tposition: absolute;\n\tz-index: 2;\n\twidth: 1.2em;\n\theight: 1.2em;\n\tcursor: default;\n\t-ms-touch-action: none;\n\ttouch-action: none;\n}\n.ui-slider .ui-slider-range {\n\tposition: absolute;\n\tz-index: 1;\n\tfont-size: .7em;\n\tdisplay: block;\n\tborder: 0;\n\tbackground-position: 0 0;\n}\n\n/* support: IE8 - See #6727 */\n.ui-slider.ui-state-disabled .ui-slider-handle,\n.ui-slider.ui-state-disabled .ui-slider-range {\n\tfilter: inherit;\n}\n\n.ui-slider-horizontal {\n\theight: .8em;\n}\n.ui-slider-horizontal .ui-slider-handle {\n\ttop: -.3em;\n\tmargin-left: -.6em;\n}\n.ui-slider-horizontal .ui-slider-range {\n\ttop: 0;\n\theight: 100%;\n}\n.ui-slider-horizontal .ui-slider-range-min {\n\tleft: 0;\n}\n.ui-slider-horizontal .ui-slider-range-max {\n\tright: 0;\n}\n\n.ui-slider-vertical {\n\twidth: .8em;\n\theight: 100px;\n}\n.ui-slider-vertical .ui-slider-handle {\n\tleft: -.3em;\n\tmargin-left: 0;\n\tmargin-bottom: -.6em;\n}\n.ui-slider-vertical .ui-slider-range {\n\tleft: 0;\n\twidth: 100%;\n}\n.ui-slider-vertical .ui-slider-range-min {\n\tbottom: 0;\n}\n.ui-slider-vertical .ui-slider-range-max {\n\ttop: 0;\n}\n.ui-spinner {\n\tposition: relative;\n\tdisplay: inline-block;\n\toverflow: hidden;\n\tpadding: 0;\n\tvertical-align: middle;\n}\n.ui-spinner-input {\n\tborder: none;\n\tbackground: none;\n\tcolor: inherit;\n\tpadding: .222em 0;\n\tmargin: .2em 0;\n\tvertical-align: middle;\n\tmargin-left: .4em;\n\tmargin-right: 2em;\n}\n.ui-spinner-button {\n\twidth: 1.6em;\n\theight: 50%;\n\tfont-size: .5em;\n\tpadding: 0;\n\tmargin: 0;\n\ttext-align: center;\n\tposition: absolute;\n\tcursor: default;\n\tdisplay: block;\n\toverflow: hidden;\n\tright: 0;\n}\n/* more specificity required here to override default borders */\n.ui-spinner a.ui-spinner-button {\n\tborder-top-style: none;\n\tborder-bottom-style: none;\n\tborder-right-style: none;\n}\n.ui-spinner-up {\n\ttop: 0;\n}\n.ui-spinner-down {\n\tbottom: 0;\n}\n.ui-tabs {\n\tposition: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as \"fixed\") */\n\tpadding: .2em;\n}\n.ui-tabs .ui-tabs-nav {\n\tmargin: 0;\n\tpadding: .2em .2em 0;\n}\n.ui-tabs .ui-tabs-nav li {\n\tlist-style: none;\n\tfloat: left;\n\tposition: relative;\n\ttop: 0;\n\tmargin: 1px .2em 0 0;\n\tborder-bottom-width: 0;\n\tpadding: 0;\n\twhite-space: nowrap;\n}\n.ui-tabs .ui-tabs-nav .ui-tabs-anchor {\n\tfloat: left;\n\tpadding: .5em 1em;\n\ttext-decoration: none;\n}\n.ui-tabs .ui-tabs-nav li.ui-tabs-active {\n\tmargin-bottom: -1px;\n\tpadding-bottom: 1px;\n}\n.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,\n.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,\n.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {\n\tcursor: text;\n}\n.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {\n\tcursor: pointer;\n}\n.ui-tabs .ui-tabs-panel {\n\tdisplay: block;\n\tborder-width: 0;\n\tpadding: 1em 1.4em;\n\tbackground: none;\n}\n.ui-tooltip {\n\tpadding: 8px;\n\tposition: absolute;\n\tz-index: 9999;\n\tmax-width: 300px;\n}\nbody .ui-tooltip {\n\tborder-width: 2px;\n}\n\n/* Component containers\n----------------------------------*/\n.ui-widget {\n\tfont-family: Arial,Helvetica,sans-serif;\n\tfont-size: 1em;\n}\n.ui-widget .ui-widget {\n\tfont-size: 1em;\n}\n.ui-widget input,\n.ui-widget select,\n.ui-widget textarea,\n.ui-widget button {\n\tfont-family: Arial,Helvetica,sans-serif;\n\tfont-size: 1em;\n}\n.ui-widget.ui-widget-content {\n\tborder: 1px solid #c5c5c5;\n}\n.ui-widget-content {\n\tborder: 1px solid #dddddd;\n\tbackground: #ffffff;\n\tcolor: #333333;\n}\n.ui-widget-content a {\n\tcolor: #333333;\n}\n.ui-widget-header {\n\tborder: 1px solid #dddddd;\n\tbackground: #e9e9e9;\n\tcolor: #333333;\n\tfont-weight: bold;\n}\n.ui-widget-header a {\n\tcolor: #333333;\n}\n\n/* Interaction states\n----------------------------------*/\n.ui-state-default,\n.ui-widget-content .ui-state-default,\n.ui-widget-header .ui-state-default,\n.ui-button,\n\n/* We use html here because we need a greater specificity to make sure disabled\nworks properly when clicked or hovered */\nhtml .ui-button.ui-state-disabled:hover,\nhtml .ui-button.ui-state-disabled:active {\n\tborder: 1px solid #c5c5c5;\n\tbackground: #f6f6f6;\n\tfont-weight: normal;\n\tcolor: #454545;\n}\n.ui-state-default a,\n.ui-state-default a:link,\n.ui-state-default a:visited,\na.ui-button,\na:link.ui-button,\na:visited.ui-button,\n.ui-button {\n\tcolor: #454545;\n\ttext-decoration: none;\n}\n.ui-state-hover,\n.ui-widget-content .ui-state-hover,\n.ui-widget-header .ui-state-hover,\n.ui-state-focus,\n.ui-widget-content .ui-state-focus,\n.ui-widget-header .ui-state-focus,\n.ui-button:hover,\n.ui-button:focus {\n\tborder: 1px solid #cccccc;\n\tbackground: #ededed;\n\tfont-weight: normal;\n\tcolor: #2b2b2b;\n}\n.ui-state-hover a,\n.ui-state-hover a:hover,\n.ui-state-hover a:link,\n.ui-state-hover a:visited,\n.ui-state-focus a,\n.ui-state-focus a:hover,\n.ui-state-focus a:link,\n.ui-state-focus a:visited,\na.ui-button:hover,\na.ui-button:focus {\n\tcolor: #2b2b2b;\n\ttext-decoration: none;\n}\n\n.ui-visual-focus {\n\tbox-shadow: 0 0 3px 1px rgb(94, 158, 214);\n}\n.ui-state-active,\n.ui-widget-content .ui-state-active,\n.ui-widget-header .ui-state-active,\na.ui-button:active,\n.ui-button:active,\n.ui-button.ui-state-active:hover {\n\tborder: 1px solid #003eff;\n\tbackground: #007fff;\n\tfont-weight: normal;\n\tcolor: #ffffff;\n}\n.ui-icon-background,\n.ui-state-active .ui-icon-background {\n\tborder: #003eff;\n\tbackground-color: #ffffff;\n}\n.ui-state-active a,\n.ui-state-active a:link,\n.ui-state-active a:visited {\n\tcolor: #ffffff;\n\ttext-decoration: none;\n}\n\n/* Interaction Cues\n----------------------------------*/\n.ui-state-highlight,\n.ui-widget-content .ui-state-highlight,\n.ui-widget-header .ui-state-highlight {\n\tborder: 1px solid #dad55e;\n\tbackground: #fffa90;\n\tcolor: #777620;\n}\n.ui-state-checked {\n\tborder: 1px solid #dad55e;\n\tbackground: #fffa90;\n}\n.ui-state-highlight a,\n.ui-widget-content .ui-state-highlight a,\n.ui-widget-header .ui-state-highlight a {\n\tcolor: #777620;\n}\n.ui-state-error,\n.ui-widget-content .ui-state-error,\n.ui-widget-header .ui-state-error {\n\tborder: 1px solid #f1a899;\n\tbackground: #fddfdf;\n\tcolor: #5f3f3f;\n}\n.ui-state-error a,\n.ui-widget-content .ui-state-error a,\n.ui-widget-header .ui-state-error a {\n\tcolor: #5f3f3f;\n}\n.ui-state-error-text,\n.ui-widget-content .ui-state-error-text,\n.ui-widget-header .ui-state-error-text {\n\tcolor: #5f3f3f;\n}\n.ui-priority-primary,\n.ui-widget-content .ui-priority-primary,\n.ui-widget-header .ui-priority-primary {\n\tfont-weight: bold;\n}\n.ui-priority-secondary,\n.ui-widget-content .ui-priority-secondary,\n.ui-widget-header .ui-priority-secondary {\n\topacity: .7;\n\tfilter:Alpha(Opacity=70); /* support: IE8 */\n\tfont-weight: normal;\n}\n.ui-state-disabled,\n.ui-widget-content .ui-state-disabled,\n.ui-widget-header .ui-state-disabled {\n\topacity: .35;\n\tfilter:Alpha(Opacity=35); /* support: IE8 */\n\tbackground-image: none;\n}\n.ui-state-disabled .ui-icon {\n\tfilter:Alpha(Opacity=35); /* support: IE8 - See #6059 */\n}\n\n/* Icons\n----------------------------------*/\n\n/* states and images */\n.ui-icon {\n\twidth: 16px;\n\theight: 16px;\n}\n.ui-icon,\n.ui-widget-content .ui-icon {\n\tbackground-image: url(\"images/ui-icons_444444_256x240.png\");\n}\n.ui-widget-header .ui-icon {\n\tbackground-image: url(\"images/ui-icons_444444_256x240.png\");\n}\n.ui-state-hover .ui-icon,\n.ui-state-focus .ui-icon,\n.ui-button:hover .ui-icon,\n.ui-button:focus .ui-icon {\n\tbackground-image: url(\"images/ui-icons_555555_256x240.png\");\n}\n.ui-state-active .ui-icon,\n.ui-button:active .ui-icon {\n\tbackground-image: url(\"images/ui-icons_ffffff_256x240.png\");\n}\n.ui-state-highlight .ui-icon,\n.ui-button .ui-state-highlight.ui-icon {\n\tbackground-image: url(\"images/ui-icons_777620_256x240.png\");\n}\n.ui-state-error .ui-icon,\n.ui-state-error-text .ui-icon {\n\tbackground-image: url(\"images/ui-icons_cc0000_256x240.png\");\n}\n.ui-button .ui-icon {\n\tbackground-image: url(\"images/ui-icons_777777_256x240.png\");\n}\n\n/* positioning */\n.ui-icon-blank { background-position: 16px 16px; }\n.ui-icon-caret-1-n { background-position: 0 0; }\n.ui-icon-caret-1-ne { background-position: -16px 0; }\n.ui-icon-caret-1-e { background-position: -32px 0; }\n.ui-icon-caret-1-se { background-position: -48px 0; }\n.ui-icon-caret-1-s { background-position: -65px 0; }\n.ui-icon-caret-1-sw { background-position: -80px 0; }\n.ui-icon-caret-1-w { background-position: -96px 0; }\n.ui-icon-caret-1-nw { background-position: -112px 0; }\n.ui-icon-caret-2-n-s { background-position: -128px 0; }\n.ui-icon-caret-2-e-w { background-position: -144px 0; }\n.ui-icon-triangle-1-n { background-position: 0 -16px; }\n.ui-icon-triangle-1-ne { background-position: -16px -16px; }\n.ui-icon-triangle-1-e { background-position: -32px -16px; }\n.ui-icon-triangle-1-se { background-position: -48px -16px; }\n.ui-icon-triangle-1-s { background-position: -65px -16px; }\n.ui-icon-triangle-1-sw { background-position: -80px -16px; }\n.ui-icon-triangle-1-w { background-position: -96px -16px; }\n.ui-icon-triangle-1-nw { background-position: -112px -16px; }\n.ui-icon-triangle-2-n-s { background-position: -128px -16px; }\n.ui-icon-triangle-2-e-w { background-position: -144px -16px; }\n.ui-icon-arrow-1-n { background-position: 0 -32px; }\n.ui-icon-arrow-1-ne { background-position: -16px -32px; }\n.ui-icon-arrow-1-e { background-position: -32px -32px; }\n.ui-icon-arrow-1-se { background-position: -48px -32px; }\n.ui-icon-arrow-1-s { background-position: -65px -32px; }\n.ui-icon-arrow-1-sw { background-position: -80px -32px; }\n.ui-icon-arrow-1-w { background-position: -96px -32px; }\n.ui-icon-arrow-1-nw { background-position: -112px -32px; }\n.ui-icon-arrow-2-n-s { background-position: -128px -32px; }\n.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }\n.ui-icon-arrow-2-e-w { background-position: -160px -32px; }\n.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }\n.ui-icon-arrowstop-1-n { background-position: -192px -32px; }\n.ui-icon-arrowstop-1-e { background-position: -208px -32px; }\n.ui-icon-arrowstop-1-s { background-position: -224px -32px; }\n.ui-icon-arrowstop-1-w { background-position: -240px -32px; }\n.ui-icon-arrowthick-1-n { background-position: 1px -48px; }\n.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }\n.ui-icon-arrowthick-1-e { background-position: -32px -48px; }\n.ui-icon-arrowthick-1-se { background-position: -48px -48px; }\n.ui-icon-arrowthick-1-s { background-position: -64px -48px; }\n.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }\n.ui-icon-arrowthick-1-w { background-position: -96px -48px; }\n.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }\n.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }\n.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }\n.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }\n.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }\n.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }\n.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }\n.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }\n.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }\n.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }\n.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }\n.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }\n.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }\n.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }\n.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }\n.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }\n.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }\n.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }\n.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }\n.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }\n.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }\n.ui-icon-arrow-4 { background-position: 0 -80px; }\n.ui-icon-arrow-4-diag { background-position: -16px -80px; }\n.ui-icon-extlink { background-position: -32px -80px; }\n.ui-icon-newwin { background-position: -48px -80px; }\n.ui-icon-refresh { background-position: -64px -80px; }\n.ui-icon-shuffle { background-position: -80px -80px; }\n.ui-icon-transfer-e-w { background-position: -96px -80px; }\n.ui-icon-transferthick-e-w { background-position: -112px -80px; }\n.ui-icon-folder-collapsed { background-position: 0 -96px; }\n.ui-icon-folder-open { background-position: -16px -96px; }\n.ui-icon-document { background-position: -32px -96px; }\n.ui-icon-document-b { background-position: -48px -96px; }\n.ui-icon-note { background-position: -64px -96px; }\n.ui-icon-mail-closed { background-position: -80px -96px; }\n.ui-icon-mail-open { background-position: -96px -96px; }\n.ui-icon-suitcase { background-position: -112px -96px; }\n.ui-icon-comment { background-position: -128px -96px; }\n.ui-icon-person { background-position: -144px -96px; }\n.ui-icon-print { background-position: -160px -96px; }\n.ui-icon-trash { background-position: -176px -96px; }\n.ui-icon-locked { background-position: -192px -96px; }\n.ui-icon-unlocked { background-position: -208px -96px; }\n.ui-icon-bookmark { background-position: -224px -96px; }\n.ui-icon-tag { background-position: -240px -96px; }\n.ui-icon-home { background-position: 0 -112px; }\n.ui-icon-flag { background-position: -16px -112px; }\n.ui-icon-calendar { background-position: -32px -112px; }\n.ui-icon-cart { background-position: -48px -112px; }\n.ui-icon-pencil { background-position: -64px -112px; }\n.ui-icon-clock { background-position: -80px -112px; }\n.ui-icon-disk { background-position: -96px -112px; }\n.ui-icon-calculator { background-position: -112px -112px; }\n.ui-icon-zoomin { background-position: -128px -112px; }\n.ui-icon-zoomout { background-position: -144px -112px; }\n.ui-icon-search { background-position: -160px -112px; }\n.ui-icon-wrench { background-position: -176px -112px; }\n.ui-icon-gear { background-position: -192px -112px; }\n.ui-icon-heart { background-position: -208px -112px; }\n.ui-icon-star { background-position: -224px -112px; }\n.ui-icon-link { background-position: -240px -112px; }\n.ui-icon-cancel { background-position: 0 -128px; }\n.ui-icon-plus { background-position: -16px -128px; }\n.ui-icon-plusthick { background-position: -32px -128px; }\n.ui-icon-minus { background-position: -48px -128px; }\n.ui-icon-minusthick { background-position: -64px -128px; }\n.ui-icon-close { background-position: -80px -128px; }\n.ui-icon-closethick { background-position: -96px -128px; }\n.ui-icon-key { background-position: -112px -128px; }\n.ui-icon-lightbulb { background-position: -128px -128px; }\n.ui-icon-scissors { background-position: -144px -128px; }\n.ui-icon-clipboard { background-position: -160px -128px; }\n.ui-icon-copy { background-position: -176px -128px; }\n.ui-icon-contact { background-position: -192px -128px; }\n.ui-icon-image { background-position: -208px -128px; }\n.ui-icon-video { background-position: -224px -128px; }\n.ui-icon-script { background-position: -240px -128px; }\n.ui-icon-alert { background-position: 0 -144px; }\n.ui-icon-info { background-position: -16px -144px; }\n.ui-icon-notice { background-position: -32px -144px; }\n.ui-icon-help { background-position: -48px -144px; }\n.ui-icon-check { background-position: -64px -144px; }\n.ui-icon-bullet { background-position: -80px -144px; }\n.ui-icon-radio-on { background-position: -96px -144px; }\n.ui-icon-radio-off { background-position: -112px -144px; }\n.ui-icon-pin-w { background-position: -128px -144px; }\n.ui-icon-pin-s { background-position: -144px -144px; }\n.ui-icon-play { background-position: 0 -160px; }\n.ui-icon-pause { background-position: -16px -160px; }\n.ui-icon-seek-next { background-position: -32px -160px; }\n.ui-icon-seek-prev { background-position: -48px -160px; }\n.ui-icon-seek-end { background-position: -64px -160px; }\n.ui-icon-seek-start { background-position: -80px -160px; }\n/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */\n.ui-icon-seek-first { background-position: -80px -160px; }\n.ui-icon-stop { background-position: -96px -160px; }\n.ui-icon-eject { background-position: -112px -160px; }\n.ui-icon-volume-off { background-position: -128px -160px; }\n.ui-icon-volume-on { background-position: -144px -160px; }\n.ui-icon-power { background-position: 0 -176px; }\n.ui-icon-signal-diag { background-position: -16px -176px; }\n.ui-icon-signal { background-position: -32px -176px; }\n.ui-icon-battery-0 { background-position: -48px -176px; }\n.ui-icon-battery-1 { background-position: -64px -176px; }\n.ui-icon-battery-2 { background-position: -80px -176px; }\n.ui-icon-battery-3 { background-position: -96px -176px; }\n.ui-icon-circle-plus { background-position: 0 -192px; }\n.ui-icon-circle-minus { background-position: -16px -192px; }\n.ui-icon-circle-close { background-position: -32px -192px; }\n.ui-icon-circle-triangle-e { background-position: -48px -192px; }\n.ui-icon-circle-triangle-s { background-position: -64px -192px; }\n.ui-icon-circle-triangle-w { background-position: -80px -192px; }\n.ui-icon-circle-triangle-n { background-position: -96px -192px; }\n.ui-icon-circle-arrow-e { background-position: -112px -192px; }\n.ui-icon-circle-arrow-s { background-position: -128px -192px; }\n.ui-icon-circle-arrow-w { background-position: -144px -192px; }\n.ui-icon-circle-arrow-n { background-position: -160px -192px; }\n.ui-icon-circle-zoomin { background-position: -176px -192px; }\n.ui-icon-circle-zoomout { background-position: -192px -192px; }\n.ui-icon-circle-check { background-position: -208px -192px; }\n.ui-icon-circlesmall-plus { background-position: 0 -208px; }\n.ui-icon-circlesmall-minus { background-position: -16px -208px; }\n.ui-icon-circlesmall-close { background-position: -32px -208px; }\n.ui-icon-squaresmall-plus { background-position: -48px -208px; }\n.ui-icon-squaresmall-minus { background-position: -64px -208px; }\n.ui-icon-squaresmall-close { background-position: -80px -208px; }\n.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }\n.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }\n.ui-icon-grip-solid-vertical { background-position: -32px -224px; }\n.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }\n.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }\n.ui-icon-grip-diagonal-se { background-position: -80px -224px; }\n\n\n/* Misc visuals\n----------------------------------*/\n\n/* Corner radius */\n.ui-corner-all,\n.ui-corner-top,\n.ui-corner-left,\n.ui-corner-tl {\n\tborder-top-left-radius: 3px;\n}\n.ui-corner-all,\n.ui-corner-top,\n.ui-corner-right,\n.ui-corner-tr {\n\tborder-top-right-radius: 3px;\n}\n.ui-corner-all,\n.ui-corner-bottom,\n.ui-corner-left,\n.ui-corner-bl {\n\tborder-bottom-left-radius: 3px;\n}\n.ui-corner-all,\n.ui-corner-bottom,\n.ui-corner-right,\n.ui-corner-br {\n\tborder-bottom-right-radius: 3px;\n}\n\n/* Overlays */\n.ui-widget-overlay {\n\tbackground: #aaaaaa;\n\topacity: .3;\n\tfilter: Alpha(Opacity=30); /* support: IE8 */\n}\n.ui-widget-shadow {\n\t-webkit-box-shadow: 0px 0px 5px #666666;\n\tbox-shadow: 0px 0px 5px #666666;\n}\n"
  },
  {
    "path": "functional-samples/sample.bookmarks/third-party/jquery-ui.structure.css",
    "content": "/*!\n * jQuery UI CSS Framework 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * http://api.jqueryui.com/category/theming/\n */\n.ui-draggable-handle {\n\t-ms-touch-action: none;\n\ttouch-action: none;\n}\n/* Layout helpers\n----------------------------------*/\n.ui-helper-hidden {\n\tdisplay: none;\n}\n.ui-helper-hidden-accessible {\n\tborder: 0;\n\tclip: rect(0 0 0 0);\n\theight: 1px;\n\tmargin: -1px;\n\toverflow: hidden;\n\tpadding: 0;\n\tposition: absolute;\n\twidth: 1px;\n}\n.ui-helper-reset {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\toutline: 0;\n\tline-height: 1.3;\n\ttext-decoration: none;\n\tfont-size: 100%;\n\tlist-style: none;\n}\n.ui-helper-clearfix:before,\n.ui-helper-clearfix:after {\n\tcontent: \"\";\n\tdisplay: table;\n\tborder-collapse: collapse;\n}\n.ui-helper-clearfix:after {\n\tclear: both;\n}\n.ui-helper-zfix {\n\twidth: 100%;\n\theight: 100%;\n\ttop: 0;\n\tleft: 0;\n\tposition: absolute;\n\topacity: 0;\n\tfilter:Alpha(Opacity=0); /* support: IE8 */\n}\n\n.ui-front {\n\tz-index: 100;\n}\n\n\n/* Interaction Cues\n----------------------------------*/\n.ui-state-disabled {\n\tcursor: default !important;\n\tpointer-events: none;\n}\n\n\n/* Icons\n----------------------------------*/\n.ui-icon {\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tmargin-top: -.25em;\n\tposition: relative;\n\ttext-indent: -99999px;\n\toverflow: hidden;\n\tbackground-repeat: no-repeat;\n}\n\n.ui-widget-icon-block {\n\tleft: 50%;\n\tmargin-left: -8px;\n\tdisplay: block;\n}\n\n/* Misc visuals\n----------------------------------*/\n\n/* Overlays */\n.ui-widget-overlay {\n\tposition: fixed;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n}\n.ui-resizable {\n\tposition: relative;\n}\n.ui-resizable-handle {\n\tposition: absolute;\n\tfont-size: 0.1px;\n\tdisplay: block;\n\t-ms-touch-action: none;\n\ttouch-action: none;\n}\n.ui-resizable-disabled .ui-resizable-handle,\n.ui-resizable-autohide .ui-resizable-handle {\n\tdisplay: none;\n}\n.ui-resizable-n {\n\tcursor: n-resize;\n\theight: 7px;\n\twidth: 100%;\n\ttop: -5px;\n\tleft: 0;\n}\n.ui-resizable-s {\n\tcursor: s-resize;\n\theight: 7px;\n\twidth: 100%;\n\tbottom: -5px;\n\tleft: 0;\n}\n.ui-resizable-e {\n\tcursor: e-resize;\n\twidth: 7px;\n\tright: -5px;\n\ttop: 0;\n\theight: 100%;\n}\n.ui-resizable-w {\n\tcursor: w-resize;\n\twidth: 7px;\n\tleft: -5px;\n\ttop: 0;\n\theight: 100%;\n}\n.ui-resizable-se {\n\tcursor: se-resize;\n\twidth: 12px;\n\theight: 12px;\n\tright: 1px;\n\tbottom: 1px;\n}\n.ui-resizable-sw {\n\tcursor: sw-resize;\n\twidth: 9px;\n\theight: 9px;\n\tleft: -5px;\n\tbottom: -5px;\n}\n.ui-resizable-nw {\n\tcursor: nw-resize;\n\twidth: 9px;\n\theight: 9px;\n\tleft: -5px;\n\ttop: -5px;\n}\n.ui-resizable-ne {\n\tcursor: ne-resize;\n\twidth: 9px;\n\theight: 9px;\n\tright: -5px;\n\ttop: -5px;\n}\n.ui-selectable {\n\t-ms-touch-action: none;\n\ttouch-action: none;\n}\n.ui-selectable-helper {\n\tposition: absolute;\n\tz-index: 100;\n\tborder: 1px dotted black;\n}\n.ui-sortable-handle {\n\t-ms-touch-action: none;\n\ttouch-action: none;\n}\n.ui-accordion .ui-accordion-header {\n\tdisplay: block;\n\tcursor: pointer;\n\tposition: relative;\n\tmargin: 2px 0 0 0;\n\tpadding: .5em .5em .5em .7em;\n\tfont-size: 100%;\n}\n.ui-accordion .ui-accordion-content {\n\tpadding: 1em 2.2em;\n\tborder-top: 0;\n\toverflow: auto;\n}\n.ui-autocomplete {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tcursor: default;\n}\n.ui-menu {\n\tlist-style: none;\n\tpadding: 0;\n\tmargin: 0;\n\tdisplay: block;\n\toutline: 0;\n}\n.ui-menu .ui-menu {\n\tposition: absolute;\n}\n.ui-menu .ui-menu-item {\n\tmargin: 0;\n\tcursor: pointer;\n\t/* support: IE10, see #8844 */\n\tlist-style-image: url(\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\");\n}\n.ui-menu .ui-menu-item-wrapper {\n\tposition: relative;\n\tpadding: 3px 1em 3px .4em;\n}\n.ui-menu .ui-menu-divider {\n\tmargin: 5px 0;\n\theight: 0;\n\tfont-size: 0;\n\tline-height: 0;\n\tborder-width: 1px 0 0 0;\n}\n.ui-menu .ui-state-focus,\n.ui-menu .ui-state-active {\n\tmargin: -1px;\n}\n\n/* icon support */\n.ui-menu-icons {\n\tposition: relative;\n}\n.ui-menu-icons .ui-menu-item-wrapper {\n\tpadding-left: 2em;\n}\n\n/* left-aligned */\n.ui-menu .ui-icon {\n\tposition: absolute;\n\ttop: 0;\n\tbottom: 0;\n\tleft: .2em;\n\tmargin: auto 0;\n}\n\n/* right-aligned */\n.ui-menu .ui-menu-icon {\n\tleft: auto;\n\tright: 0;\n}\n.ui-button {\n\tpadding: .4em 1em;\n\tdisplay: inline-block;\n\tposition: relative;\n\tline-height: normal;\n\tmargin-right: .1em;\n\tcursor: pointer;\n\tvertical-align: middle;\n\ttext-align: center;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n\n\t/* Support: IE <= 11 */\n\toverflow: visible;\n}\n\n.ui-button,\n.ui-button:link,\n.ui-button:visited,\n.ui-button:hover,\n.ui-button:active {\n\ttext-decoration: none;\n}\n\n/* to make room for the icon, a width needs to be set here */\n.ui-button-icon-only {\n\twidth: 2em;\n\tbox-sizing: border-box;\n\ttext-indent: -9999px;\n\twhite-space: nowrap;\n}\n\n/* no icon support for input elements */\ninput.ui-button.ui-button-icon-only {\n\ttext-indent: 0;\n}\n\n/* button icon element(s) */\n.ui-button-icon-only .ui-icon {\n\tposition: absolute;\n\ttop: 50%;\n\tleft: 50%;\n\tmargin-top: -8px;\n\tmargin-left: -8px;\n}\n\n.ui-button.ui-icon-notext .ui-icon {\n\tpadding: 0;\n\twidth: 2.1em;\n\theight: 2.1em;\n\ttext-indent: -9999px;\n\twhite-space: nowrap;\n\n}\n\ninput.ui-button.ui-icon-notext .ui-icon {\n\twidth: auto;\n\theight: auto;\n\ttext-indent: 0;\n\twhite-space: normal;\n\tpadding: .4em 1em;\n}\n\n/* workarounds */\n/* Support: Firefox 5 - 40 */\ninput.ui-button::-moz-focus-inner,\nbutton.ui-button::-moz-focus-inner {\n\tborder: 0;\n\tpadding: 0;\n}\n.ui-controlgroup {\n\tvertical-align: middle;\n\tdisplay: inline-block;\n}\n.ui-controlgroup > .ui-controlgroup-item {\n\tfloat: left;\n\tmargin-left: 0;\n\tmargin-right: 0;\n}\n.ui-controlgroup > .ui-controlgroup-item:focus,\n.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus {\n\tz-index: 9999;\n}\n.ui-controlgroup-vertical > .ui-controlgroup-item {\n\tdisplay: block;\n\tfloat: none;\n\twidth: 100%;\n\tmargin-top: 0;\n\tmargin-bottom: 0;\n\ttext-align: left;\n}\n.ui-controlgroup-vertical .ui-controlgroup-item {\n\tbox-sizing: border-box;\n}\n.ui-controlgroup .ui-controlgroup-label {\n\tpadding: .4em 1em;\n}\n.ui-controlgroup .ui-controlgroup-label span {\n\tfont-size: 80%;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item {\n\tborder-left: none;\n}\n.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item {\n\tborder-top: none;\n}\n.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content {\n\tborder-right: none;\n}\n.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content {\n\tborder-bottom: none;\n}\n\n/* Spinner specific style fixes */\n.ui-controlgroup-vertical .ui-spinner-input {\n\n\t/* Support: IE8 only, Android < 4.4 only */\n\twidth: 75%;\n\twidth: calc( 100% - 2.4em );\n}\n.ui-controlgroup-vertical .ui-spinner .ui-spinner-up {\n\tborder-top-style: solid;\n}\n\n.ui-checkboxradio-label .ui-icon-background {\n\tbox-shadow: inset 1px 1px 1px #ccc;\n\tborder-radius: .12em;\n\tborder: none;\n}\n.ui-checkboxradio-radio-label .ui-icon-background {\n\twidth: 16px;\n\theight: 16px;\n\tborder-radius: 1em;\n\toverflow: visible;\n\tborder: none;\n}\n.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,\n.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon {\n\tbackground-image: none;\n\twidth: 8px;\n\theight: 8px;\n\tborder-width: 4px;\n\tborder-style: solid;\n}\n.ui-checkboxradio-disabled {\n\tpointer-events: none;\n}\n.ui-datepicker {\n\twidth: 17em;\n\tpadding: .2em .2em 0;\n\tdisplay: none;\n}\n.ui-datepicker .ui-datepicker-header {\n\tposition: relative;\n\tpadding: .2em 0;\n}\n.ui-datepicker .ui-datepicker-prev,\n.ui-datepicker .ui-datepicker-next {\n\tposition: absolute;\n\ttop: 2px;\n\twidth: 1.8em;\n\theight: 1.8em;\n}\n.ui-datepicker .ui-datepicker-prev-hover,\n.ui-datepicker .ui-datepicker-next-hover {\n\ttop: 1px;\n}\n.ui-datepicker .ui-datepicker-prev {\n\tleft: 2px;\n}\n.ui-datepicker .ui-datepicker-next {\n\tright: 2px;\n}\n.ui-datepicker .ui-datepicker-prev-hover {\n\tleft: 1px;\n}\n.ui-datepicker .ui-datepicker-next-hover {\n\tright: 1px;\n}\n.ui-datepicker .ui-datepicker-prev span,\n.ui-datepicker .ui-datepicker-next span {\n\tdisplay: block;\n\tposition: absolute;\n\tleft: 50%;\n\tmargin-left: -8px;\n\ttop: 50%;\n\tmargin-top: -8px;\n}\n.ui-datepicker .ui-datepicker-title {\n\tmargin: 0 2.3em;\n\tline-height: 1.8em;\n\ttext-align: center;\n}\n.ui-datepicker .ui-datepicker-title select {\n\tfont-size: 1em;\n\tmargin: 1px 0;\n}\n.ui-datepicker select.ui-datepicker-month,\n.ui-datepicker select.ui-datepicker-year {\n\twidth: 45%;\n}\n.ui-datepicker table {\n\twidth: 100%;\n\tfont-size: .9em;\n\tborder-collapse: collapse;\n\tmargin: 0 0 .4em;\n}\n.ui-datepicker th {\n\tpadding: .7em .3em;\n\ttext-align: center;\n\tfont-weight: bold;\n\tborder: 0;\n}\n.ui-datepicker td {\n\tborder: 0;\n\tpadding: 1px;\n}\n.ui-datepicker td span,\n.ui-datepicker td a {\n\tdisplay: block;\n\tpadding: .2em;\n\ttext-align: right;\n\ttext-decoration: none;\n}\n.ui-datepicker .ui-datepicker-buttonpane {\n\tbackground-image: none;\n\tmargin: .7em 0 0 0;\n\tpadding: 0 .2em;\n\tborder-left: 0;\n\tborder-right: 0;\n\tborder-bottom: 0;\n}\n.ui-datepicker .ui-datepicker-buttonpane button {\n\tfloat: right;\n\tmargin: .5em .2em .4em;\n\tcursor: pointer;\n\tpadding: .2em .6em .3em .6em;\n\twidth: auto;\n\toverflow: visible;\n}\n.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {\n\tfloat: left;\n}\n\n/* with multiple calendars */\n.ui-datepicker.ui-datepicker-multi {\n\twidth: auto;\n}\n.ui-datepicker-multi .ui-datepicker-group {\n\tfloat: left;\n}\n.ui-datepicker-multi .ui-datepicker-group table {\n\twidth: 95%;\n\tmargin: 0 auto .4em;\n}\n.ui-datepicker-multi-2 .ui-datepicker-group {\n\twidth: 50%;\n}\n.ui-datepicker-multi-3 .ui-datepicker-group {\n\twidth: 33.3%;\n}\n.ui-datepicker-multi-4 .ui-datepicker-group {\n\twidth: 25%;\n}\n.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,\n.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {\n\tborder-left-width: 0;\n}\n.ui-datepicker-multi .ui-datepicker-buttonpane {\n\tclear: left;\n}\n.ui-datepicker-row-break {\n\tclear: both;\n\twidth: 100%;\n\tfont-size: 0;\n}\n\n/* RTL support */\n.ui-datepicker-rtl {\n\tdirection: rtl;\n}\n.ui-datepicker-rtl .ui-datepicker-prev {\n\tright: 2px;\n\tleft: auto;\n}\n.ui-datepicker-rtl .ui-datepicker-next {\n\tleft: 2px;\n\tright: auto;\n}\n.ui-datepicker-rtl .ui-datepicker-prev:hover {\n\tright: 1px;\n\tleft: auto;\n}\n.ui-datepicker-rtl .ui-datepicker-next:hover {\n\tleft: 1px;\n\tright: auto;\n}\n.ui-datepicker-rtl .ui-datepicker-buttonpane {\n\tclear: right;\n}\n.ui-datepicker-rtl .ui-datepicker-buttonpane button {\n\tfloat: left;\n}\n.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,\n.ui-datepicker-rtl .ui-datepicker-group {\n\tfloat: right;\n}\n.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,\n.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {\n\tborder-right-width: 0;\n\tborder-left-width: 1px;\n}\n\n/* Icons */\n.ui-datepicker .ui-icon {\n\tdisplay: block;\n\ttext-indent: -99999px;\n\toverflow: hidden;\n\tbackground-repeat: no-repeat;\n\tleft: .5em;\n\ttop: .3em;\n}\n.ui-dialog {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tpadding: .2em;\n\toutline: 0;\n}\n.ui-dialog .ui-dialog-titlebar {\n\tpadding: .4em 1em;\n\tposition: relative;\n}\n.ui-dialog .ui-dialog-title {\n\tfloat: left;\n\tmargin: .1em 0;\n\twhite-space: nowrap;\n\twidth: 90%;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n.ui-dialog .ui-dialog-titlebar-close {\n\tposition: absolute;\n\tright: .3em;\n\ttop: 50%;\n\twidth: 20px;\n\tmargin: -10px 0 0 0;\n\tpadding: 1px;\n\theight: 20px;\n}\n.ui-dialog .ui-dialog-content {\n\tposition: relative;\n\tborder: 0;\n\tpadding: .5em 1em;\n\tbackground: none;\n\toverflow: auto;\n}\n.ui-dialog .ui-dialog-buttonpane {\n\ttext-align: left;\n\tborder-width: 1px 0 0 0;\n\tbackground-image: none;\n\tmargin-top: .5em;\n\tpadding: .3em 1em .5em .4em;\n}\n.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {\n\tfloat: right;\n}\n.ui-dialog .ui-dialog-buttonpane button {\n\tmargin: .5em .4em .5em 0;\n\tcursor: pointer;\n}\n.ui-dialog .ui-resizable-n {\n\theight: 2px;\n\ttop: 0;\n}\n.ui-dialog .ui-resizable-e {\n\twidth: 2px;\n\tright: 0;\n}\n.ui-dialog .ui-resizable-s {\n\theight: 2px;\n\tbottom: 0;\n}\n.ui-dialog .ui-resizable-w {\n\twidth: 2px;\n\tleft: 0;\n}\n.ui-dialog .ui-resizable-se,\n.ui-dialog .ui-resizable-sw,\n.ui-dialog .ui-resizable-ne,\n.ui-dialog .ui-resizable-nw {\n\twidth: 7px;\n\theight: 7px;\n}\n.ui-dialog .ui-resizable-se {\n\tright: 0;\n\tbottom: 0;\n}\n.ui-dialog .ui-resizable-sw {\n\tleft: 0;\n\tbottom: 0;\n}\n.ui-dialog .ui-resizable-ne {\n\tright: 0;\n\ttop: 0;\n}\n.ui-dialog .ui-resizable-nw {\n\tleft: 0;\n\ttop: 0;\n}\n.ui-draggable .ui-dialog-titlebar {\n\tcursor: move;\n}\n.ui-progressbar {\n\theight: 2em;\n\ttext-align: left;\n\toverflow: hidden;\n}\n.ui-progressbar .ui-progressbar-value {\n\tmargin: -1px;\n\theight: 100%;\n}\n.ui-progressbar .ui-progressbar-overlay {\n\tbackground: url(\"data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==\");\n\theight: 100%;\n\tfilter: alpha(opacity=25); /* support: IE8 */\n\topacity: 0.25;\n}\n.ui-progressbar-indeterminate .ui-progressbar-value {\n\tbackground-image: none;\n}\n.ui-selectmenu-menu {\n\tpadding: 0;\n\tmargin: 0;\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tdisplay: none;\n}\n.ui-selectmenu-menu .ui-menu {\n\toverflow: auto;\n\toverflow-x: hidden;\n\tpadding-bottom: 1px;\n}\n.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {\n\tfont-size: 1em;\n\tfont-weight: bold;\n\tline-height: 1.5;\n\tpadding: 2px 0.4em;\n\tmargin: 0.5em 0 0 0;\n\theight: auto;\n\tborder: 0;\n}\n.ui-selectmenu-open {\n\tdisplay: block;\n}\n.ui-selectmenu-text {\n\tdisplay: block;\n\tmargin-right: 20px;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n.ui-selectmenu-button.ui-button {\n\ttext-align: left;\n\twhite-space: nowrap;\n\twidth: 14em;\n}\n.ui-selectmenu-icon.ui-icon {\n\tfloat: right;\n\tmargin-top: 0;\n}\n.ui-slider {\n\tposition: relative;\n\ttext-align: left;\n}\n.ui-slider .ui-slider-handle {\n\tposition: absolute;\n\tz-index: 2;\n\twidth: 1.2em;\n\theight: 1.2em;\n\tcursor: default;\n\t-ms-touch-action: none;\n\ttouch-action: none;\n}\n.ui-slider .ui-slider-range {\n\tposition: absolute;\n\tz-index: 1;\n\tfont-size: .7em;\n\tdisplay: block;\n\tborder: 0;\n\tbackground-position: 0 0;\n}\n\n/* support: IE8 - See #6727 */\n.ui-slider.ui-state-disabled .ui-slider-handle,\n.ui-slider.ui-state-disabled .ui-slider-range {\n\tfilter: inherit;\n}\n\n.ui-slider-horizontal {\n\theight: .8em;\n}\n.ui-slider-horizontal .ui-slider-handle {\n\ttop: -.3em;\n\tmargin-left: -.6em;\n}\n.ui-slider-horizontal .ui-slider-range {\n\ttop: 0;\n\theight: 100%;\n}\n.ui-slider-horizontal .ui-slider-range-min {\n\tleft: 0;\n}\n.ui-slider-horizontal .ui-slider-range-max {\n\tright: 0;\n}\n\n.ui-slider-vertical {\n\twidth: .8em;\n\theight: 100px;\n}\n.ui-slider-vertical .ui-slider-handle {\n\tleft: -.3em;\n\tmargin-left: 0;\n\tmargin-bottom: -.6em;\n}\n.ui-slider-vertical .ui-slider-range {\n\tleft: 0;\n\twidth: 100%;\n}\n.ui-slider-vertical .ui-slider-range-min {\n\tbottom: 0;\n}\n.ui-slider-vertical .ui-slider-range-max {\n\ttop: 0;\n}\n.ui-spinner {\n\tposition: relative;\n\tdisplay: inline-block;\n\toverflow: hidden;\n\tpadding: 0;\n\tvertical-align: middle;\n}\n.ui-spinner-input {\n\tborder: none;\n\tbackground: none;\n\tcolor: inherit;\n\tpadding: .222em 0;\n\tmargin: .2em 0;\n\tvertical-align: middle;\n\tmargin-left: .4em;\n\tmargin-right: 2em;\n}\n.ui-spinner-button {\n\twidth: 1.6em;\n\theight: 50%;\n\tfont-size: .5em;\n\tpadding: 0;\n\tmargin: 0;\n\ttext-align: center;\n\tposition: absolute;\n\tcursor: default;\n\tdisplay: block;\n\toverflow: hidden;\n\tright: 0;\n}\n/* more specificity required here to override default borders */\n.ui-spinner a.ui-spinner-button {\n\tborder-top-style: none;\n\tborder-bottom-style: none;\n\tborder-right-style: none;\n}\n.ui-spinner-up {\n\ttop: 0;\n}\n.ui-spinner-down {\n\tbottom: 0;\n}\n.ui-tabs {\n\tposition: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as \"fixed\") */\n\tpadding: .2em;\n}\n.ui-tabs .ui-tabs-nav {\n\tmargin: 0;\n\tpadding: .2em .2em 0;\n}\n.ui-tabs .ui-tabs-nav li {\n\tlist-style: none;\n\tfloat: left;\n\tposition: relative;\n\ttop: 0;\n\tmargin: 1px .2em 0 0;\n\tborder-bottom-width: 0;\n\tpadding: 0;\n\twhite-space: nowrap;\n}\n.ui-tabs .ui-tabs-nav .ui-tabs-anchor {\n\tfloat: left;\n\tpadding: .5em 1em;\n\ttext-decoration: none;\n}\n.ui-tabs .ui-tabs-nav li.ui-tabs-active {\n\tmargin-bottom: -1px;\n\tpadding-bottom: 1px;\n}\n.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,\n.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,\n.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {\n\tcursor: text;\n}\n.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {\n\tcursor: pointer;\n}\n.ui-tabs .ui-tabs-panel {\n\tdisplay: block;\n\tborder-width: 0;\n\tpadding: 1em 1.4em;\n\tbackground: none;\n}\n.ui-tooltip {\n\tpadding: 8px;\n\tposition: absolute;\n\tz-index: 9999;\n\tmax-width: 300px;\n}\nbody .ui-tooltip {\n\tborder-width: 2px;\n}\n"
  },
  {
    "path": "functional-samples/sample.bookmarks/third-party/jquery-ui.theme.css",
    "content": "/*!\n * jQuery UI CSS Framework 1.12.1\n * http://jqueryui.com\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n * http://api.jqueryui.com/category/theming/\n *\n * To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=base&cornerRadiusShadow=8px&offsetLeftShadow=0px&offsetTopShadow=0px&thicknessShadow=5px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=666666&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=aaaaaa&iconColorError=cc0000&fcError=5f3f3f&borderColorError=f1a899&bgTextureError=flat&bgColorError=fddfdf&iconColorHighlight=777620&fcHighlight=777620&borderColorHighlight=dad55e&bgTextureHighlight=flat&bgColorHighlight=fffa90&iconColorActive=ffffff&fcActive=ffffff&borderColorActive=003eff&bgTextureActive=flat&bgColorActive=007fff&iconColorHover=555555&fcHover=2b2b2b&borderColorHover=cccccc&bgTextureHover=flat&bgColorHover=ededed&iconColorDefault=777777&fcDefault=454545&borderColorDefault=c5c5c5&bgTextureDefault=flat&bgColorDefault=f6f6f6&iconColorContent=444444&fcContent=333333&borderColorContent=dddddd&bgTextureContent=flat&bgColorContent=ffffff&iconColorHeader=444444&fcHeader=333333&borderColorHeader=dddddd&bgTextureHeader=flat&bgColorHeader=e9e9e9&cornerRadius=3px&fwDefault=normal&fsDefault=1em&ffDefault=Arial%2CHelvetica%2Csans-serif\n */\n\n\n/* Component containers\n----------------------------------*/\n.ui-widget {\n\tfont-family: Arial,Helvetica,sans-serif;\n\tfont-size: 1em;\n}\n.ui-widget .ui-widget {\n\tfont-size: 1em;\n}\n.ui-widget input,\n.ui-widget select,\n.ui-widget textarea,\n.ui-widget button {\n\tfont-family: Arial,Helvetica,sans-serif;\n\tfont-size: 1em;\n}\n.ui-widget.ui-widget-content {\n\tborder: 1px solid #c5c5c5;\n}\n.ui-widget-content {\n\tborder: 1px solid #dddddd;\n\tbackground: #ffffff;\n\tcolor: #333333;\n}\n.ui-widget-content a {\n\tcolor: #333333;\n}\n.ui-widget-header {\n\tborder: 1px solid #dddddd;\n\tbackground: #e9e9e9;\n\tcolor: #333333;\n\tfont-weight: bold;\n}\n.ui-widget-header a {\n\tcolor: #333333;\n}\n\n/* Interaction states\n----------------------------------*/\n.ui-state-default,\n.ui-widget-content .ui-state-default,\n.ui-widget-header .ui-state-default,\n.ui-button,\n\n/* We use html here because we need a greater specificity to make sure disabled\nworks properly when clicked or hovered */\nhtml .ui-button.ui-state-disabled:hover,\nhtml .ui-button.ui-state-disabled:active {\n\tborder: 1px solid #c5c5c5;\n\tbackground: #f6f6f6;\n\tfont-weight: normal;\n\tcolor: #454545;\n}\n.ui-state-default a,\n.ui-state-default a:link,\n.ui-state-default a:visited,\na.ui-button,\na:link.ui-button,\na:visited.ui-button,\n.ui-button {\n\tcolor: #454545;\n\ttext-decoration: none;\n}\n.ui-state-hover,\n.ui-widget-content .ui-state-hover,\n.ui-widget-header .ui-state-hover,\n.ui-state-focus,\n.ui-widget-content .ui-state-focus,\n.ui-widget-header .ui-state-focus,\n.ui-button:hover,\n.ui-button:focus {\n\tborder: 1px solid #cccccc;\n\tbackground: #ededed;\n\tfont-weight: normal;\n\tcolor: #2b2b2b;\n}\n.ui-state-hover a,\n.ui-state-hover a:hover,\n.ui-state-hover a:link,\n.ui-state-hover a:visited,\n.ui-state-focus a,\n.ui-state-focus a:hover,\n.ui-state-focus a:link,\n.ui-state-focus a:visited,\na.ui-button:hover,\na.ui-button:focus {\n\tcolor: #2b2b2b;\n\ttext-decoration: none;\n}\n\n.ui-visual-focus {\n\tbox-shadow: 0 0 3px 1px rgb(94, 158, 214);\n}\n.ui-state-active,\n.ui-widget-content .ui-state-active,\n.ui-widget-header .ui-state-active,\na.ui-button:active,\n.ui-button:active,\n.ui-button.ui-state-active:hover {\n\tborder: 1px solid #003eff;\n\tbackground: #007fff;\n\tfont-weight: normal;\n\tcolor: #ffffff;\n}\n.ui-icon-background,\n.ui-state-active .ui-icon-background {\n\tborder: #003eff;\n\tbackground-color: #ffffff;\n}\n.ui-state-active a,\n.ui-state-active a:link,\n.ui-state-active a:visited {\n\tcolor: #ffffff;\n\ttext-decoration: none;\n}\n\n/* Interaction Cues\n----------------------------------*/\n.ui-state-highlight,\n.ui-widget-content .ui-state-highlight,\n.ui-widget-header .ui-state-highlight {\n\tborder: 1px solid #dad55e;\n\tbackground: #fffa90;\n\tcolor: #777620;\n}\n.ui-state-checked {\n\tborder: 1px solid #dad55e;\n\tbackground: #fffa90;\n}\n.ui-state-highlight a,\n.ui-widget-content .ui-state-highlight a,\n.ui-widget-header .ui-state-highlight a {\n\tcolor: #777620;\n}\n.ui-state-error,\n.ui-widget-content .ui-state-error,\n.ui-widget-header .ui-state-error {\n\tborder: 1px solid #f1a899;\n\tbackground: #fddfdf;\n\tcolor: #5f3f3f;\n}\n.ui-state-error a,\n.ui-widget-content .ui-state-error a,\n.ui-widget-header .ui-state-error a {\n\tcolor: #5f3f3f;\n}\n.ui-state-error-text,\n.ui-widget-content .ui-state-error-text,\n.ui-widget-header .ui-state-error-text {\n\tcolor: #5f3f3f;\n}\n.ui-priority-primary,\n.ui-widget-content .ui-priority-primary,\n.ui-widget-header .ui-priority-primary {\n\tfont-weight: bold;\n}\n.ui-priority-secondary,\n.ui-widget-content .ui-priority-secondary,\n.ui-widget-header .ui-priority-secondary {\n\topacity: .7;\n\tfilter:Alpha(Opacity=70); /* support: IE8 */\n\tfont-weight: normal;\n}\n.ui-state-disabled,\n.ui-widget-content .ui-state-disabled,\n.ui-widget-header .ui-state-disabled {\n\topacity: .35;\n\tfilter:Alpha(Opacity=35); /* support: IE8 */\n\tbackground-image: none;\n}\n.ui-state-disabled .ui-icon {\n\tfilter:Alpha(Opacity=35); /* support: IE8 - See #6059 */\n}\n\n/* Icons\n----------------------------------*/\n\n/* states and images */\n.ui-icon {\n\twidth: 16px;\n\theight: 16px;\n}\n.ui-icon,\n.ui-widget-content .ui-icon {\n\tbackground-image: url(\"images/ui-icons_444444_256x240.png\");\n}\n.ui-widget-header .ui-icon {\n\tbackground-image: url(\"images/ui-icons_444444_256x240.png\");\n}\n.ui-state-hover .ui-icon,\n.ui-state-focus .ui-icon,\n.ui-button:hover .ui-icon,\n.ui-button:focus .ui-icon {\n\tbackground-image: url(\"images/ui-icons_555555_256x240.png\");\n}\n.ui-state-active .ui-icon,\n.ui-button:active .ui-icon {\n\tbackground-image: url(\"images/ui-icons_ffffff_256x240.png\");\n}\n.ui-state-highlight .ui-icon,\n.ui-button .ui-state-highlight.ui-icon {\n\tbackground-image: url(\"images/ui-icons_777620_256x240.png\");\n}\n.ui-state-error .ui-icon,\n.ui-state-error-text .ui-icon {\n\tbackground-image: url(\"images/ui-icons_cc0000_256x240.png\");\n}\n.ui-button .ui-icon {\n\tbackground-image: url(\"images/ui-icons_777777_256x240.png\");\n}\n\n/* positioning */\n.ui-icon-blank { background-position: 16px 16px; }\n.ui-icon-caret-1-n { background-position: 0 0; }\n.ui-icon-caret-1-ne { background-position: -16px 0; }\n.ui-icon-caret-1-e { background-position: -32px 0; }\n.ui-icon-caret-1-se { background-position: -48px 0; }\n.ui-icon-caret-1-s { background-position: -65px 0; }\n.ui-icon-caret-1-sw { background-position: -80px 0; }\n.ui-icon-caret-1-w { background-position: -96px 0; }\n.ui-icon-caret-1-nw { background-position: -112px 0; }\n.ui-icon-caret-2-n-s { background-position: -128px 0; }\n.ui-icon-caret-2-e-w { background-position: -144px 0; }\n.ui-icon-triangle-1-n { background-position: 0 -16px; }\n.ui-icon-triangle-1-ne { background-position: -16px -16px; }\n.ui-icon-triangle-1-e { background-position: -32px -16px; }\n.ui-icon-triangle-1-se { background-position: -48px -16px; }\n.ui-icon-triangle-1-s { background-position: -65px -16px; }\n.ui-icon-triangle-1-sw { background-position: -80px -16px; }\n.ui-icon-triangle-1-w { background-position: -96px -16px; }\n.ui-icon-triangle-1-nw { background-position: -112px -16px; }\n.ui-icon-triangle-2-n-s { background-position: -128px -16px; }\n.ui-icon-triangle-2-e-w { background-position: -144px -16px; }\n.ui-icon-arrow-1-n { background-position: 0 -32px; }\n.ui-icon-arrow-1-ne { background-position: -16px -32px; }\n.ui-icon-arrow-1-e { background-position: -32px -32px; }\n.ui-icon-arrow-1-se { background-position: -48px -32px; }\n.ui-icon-arrow-1-s { background-position: -65px -32px; }\n.ui-icon-arrow-1-sw { background-position: -80px -32px; }\n.ui-icon-arrow-1-w { background-position: -96px -32px; }\n.ui-icon-arrow-1-nw { background-position: -112px -32px; }\n.ui-icon-arrow-2-n-s { background-position: -128px -32px; }\n.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }\n.ui-icon-arrow-2-e-w { background-position: -160px -32px; }\n.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }\n.ui-icon-arrowstop-1-n { background-position: -192px -32px; }\n.ui-icon-arrowstop-1-e { background-position: -208px -32px; }\n.ui-icon-arrowstop-1-s { background-position: -224px -32px; }\n.ui-icon-arrowstop-1-w { background-position: -240px -32px; }\n.ui-icon-arrowthick-1-n { background-position: 1px -48px; }\n.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }\n.ui-icon-arrowthick-1-e { background-position: -32px -48px; }\n.ui-icon-arrowthick-1-se { background-position: -48px -48px; }\n.ui-icon-arrowthick-1-s { background-position: -64px -48px; }\n.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }\n.ui-icon-arrowthick-1-w { background-position: -96px -48px; }\n.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }\n.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }\n.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }\n.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }\n.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }\n.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }\n.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }\n.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }\n.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }\n.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }\n.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }\n.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }\n.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }\n.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }\n.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }\n.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }\n.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }\n.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }\n.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }\n.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }\n.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }\n.ui-icon-arrow-4 { background-position: 0 -80px; }\n.ui-icon-arrow-4-diag { background-position: -16px -80px; }\n.ui-icon-extlink { background-position: -32px -80px; }\n.ui-icon-newwin { background-position: -48px -80px; }\n.ui-icon-refresh { background-position: -64px -80px; }\n.ui-icon-shuffle { background-position: -80px -80px; }\n.ui-icon-transfer-e-w { background-position: -96px -80px; }\n.ui-icon-transferthick-e-w { background-position: -112px -80px; }\n.ui-icon-folder-collapsed { background-position: 0 -96px; }\n.ui-icon-folder-open { background-position: -16px -96px; }\n.ui-icon-document { background-position: -32px -96px; }\n.ui-icon-document-b { background-position: -48px -96px; }\n.ui-icon-note { background-position: -64px -96px; }\n.ui-icon-mail-closed { background-position: -80px -96px; }\n.ui-icon-mail-open { background-position: -96px -96px; }\n.ui-icon-suitcase { background-position: -112px -96px; }\n.ui-icon-comment { background-position: -128px -96px; }\n.ui-icon-person { background-position: -144px -96px; }\n.ui-icon-print { background-position: -160px -96px; }\n.ui-icon-trash { background-position: -176px -96px; }\n.ui-icon-locked { background-position: -192px -96px; }\n.ui-icon-unlocked { background-position: -208px -96px; }\n.ui-icon-bookmark { background-position: -224px -96px; }\n.ui-icon-tag { background-position: -240px -96px; }\n.ui-icon-home { background-position: 0 -112px; }\n.ui-icon-flag { background-position: -16px -112px; }\n.ui-icon-calendar { background-position: -32px -112px; }\n.ui-icon-cart { background-position: -48px -112px; }\n.ui-icon-pencil { background-position: -64px -112px; }\n.ui-icon-clock { background-position: -80px -112px; }\n.ui-icon-disk { background-position: -96px -112px; }\n.ui-icon-calculator { background-position: -112px -112px; }\n.ui-icon-zoomin { background-position: -128px -112px; }\n.ui-icon-zoomout { background-position: -144px -112px; }\n.ui-icon-search { background-position: -160px -112px; }\n.ui-icon-wrench { background-position: -176px -112px; }\n.ui-icon-gear { background-position: -192px -112px; }\n.ui-icon-heart { background-position: -208px -112px; }\n.ui-icon-star { background-position: -224px -112px; }\n.ui-icon-link { background-position: -240px -112px; }\n.ui-icon-cancel { background-position: 0 -128px; }\n.ui-icon-plus { background-position: -16px -128px; }\n.ui-icon-plusthick { background-position: -32px -128px; }\n.ui-icon-minus { background-position: -48px -128px; }\n.ui-icon-minusthick { background-position: -64px -128px; }\n.ui-icon-close { background-position: -80px -128px; }\n.ui-icon-closethick { background-position: -96px -128px; }\n.ui-icon-key { background-position: -112px -128px; }\n.ui-icon-lightbulb { background-position: -128px -128px; }\n.ui-icon-scissors { background-position: -144px -128px; }\n.ui-icon-clipboard { background-position: -160px -128px; }\n.ui-icon-copy { background-position: -176px -128px; }\n.ui-icon-contact { background-position: -192px -128px; }\n.ui-icon-image { background-position: -208px -128px; }\n.ui-icon-video { background-position: -224px -128px; }\n.ui-icon-script { background-position: -240px -128px; }\n.ui-icon-alert { background-position: 0 -144px; }\n.ui-icon-info { background-position: -16px -144px; }\n.ui-icon-notice { background-position: -32px -144px; }\n.ui-icon-help { background-position: -48px -144px; }\n.ui-icon-check { background-position: -64px -144px; }\n.ui-icon-bullet { background-position: -80px -144px; }\n.ui-icon-radio-on { background-position: -96px -144px; }\n.ui-icon-radio-off { background-position: -112px -144px; }\n.ui-icon-pin-w { background-position: -128px -144px; }\n.ui-icon-pin-s { background-position: -144px -144px; }\n.ui-icon-play { background-position: 0 -160px; }\n.ui-icon-pause { background-position: -16px -160px; }\n.ui-icon-seek-next { background-position: -32px -160px; }\n.ui-icon-seek-prev { background-position: -48px -160px; }\n.ui-icon-seek-end { background-position: -64px -160px; }\n.ui-icon-seek-start { background-position: -80px -160px; }\n/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */\n.ui-icon-seek-first { background-position: -80px -160px; }\n.ui-icon-stop { background-position: -96px -160px; }\n.ui-icon-eject { background-position: -112px -160px; }\n.ui-icon-volume-off { background-position: -128px -160px; }\n.ui-icon-volume-on { background-position: -144px -160px; }\n.ui-icon-power { background-position: 0 -176px; }\n.ui-icon-signal-diag { background-position: -16px -176px; }\n.ui-icon-signal { background-position: -32px -176px; }\n.ui-icon-battery-0 { background-position: -48px -176px; }\n.ui-icon-battery-1 { background-position: -64px -176px; }\n.ui-icon-battery-2 { background-position: -80px -176px; }\n.ui-icon-battery-3 { background-position: -96px -176px; }\n.ui-icon-circle-plus { background-position: 0 -192px; }\n.ui-icon-circle-minus { background-position: -16px -192px; }\n.ui-icon-circle-close { background-position: -32px -192px; }\n.ui-icon-circle-triangle-e { background-position: -48px -192px; }\n.ui-icon-circle-triangle-s { background-position: -64px -192px; }\n.ui-icon-circle-triangle-w { background-position: -80px -192px; }\n.ui-icon-circle-triangle-n { background-position: -96px -192px; }\n.ui-icon-circle-arrow-e { background-position: -112px -192px; }\n.ui-icon-circle-arrow-s { background-position: -128px -192px; }\n.ui-icon-circle-arrow-w { background-position: -144px -192px; }\n.ui-icon-circle-arrow-n { background-position: -160px -192px; }\n.ui-icon-circle-zoomin { background-position: -176px -192px; }\n.ui-icon-circle-zoomout { background-position: -192px -192px; }\n.ui-icon-circle-check { background-position: -208px -192px; }\n.ui-icon-circlesmall-plus { background-position: 0 -208px; }\n.ui-icon-circlesmall-minus { background-position: -16px -208px; }\n.ui-icon-circlesmall-close { background-position: -32px -208px; }\n.ui-icon-squaresmall-plus { background-position: -48px -208px; }\n.ui-icon-squaresmall-minus { background-position: -64px -208px; }\n.ui-icon-squaresmall-close { background-position: -80px -208px; }\n.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }\n.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }\n.ui-icon-grip-solid-vertical { background-position: -32px -224px; }\n.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }\n.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }\n.ui-icon-grip-diagonal-se { background-position: -80px -224px; }\n\n\n/* Misc visuals\n----------------------------------*/\n\n/* Corner radius */\n.ui-corner-all,\n.ui-corner-top,\n.ui-corner-left,\n.ui-corner-tl {\n\tborder-top-left-radius: 3px;\n}\n.ui-corner-all,\n.ui-corner-top,\n.ui-corner-right,\n.ui-corner-tr {\n\tborder-top-right-radius: 3px;\n}\n.ui-corner-all,\n.ui-corner-bottom,\n.ui-corner-left,\n.ui-corner-bl {\n\tborder-bottom-left-radius: 3px;\n}\n.ui-corner-all,\n.ui-corner-bottom,\n.ui-corner-right,\n.ui-corner-br {\n\tborder-bottom-right-radius: 3px;\n}\n\n/* Overlays */\n.ui-widget-overlay {\n\tbackground: #aaaaaa;\n\topacity: .3;\n\tfilter: Alpha(Opacity=30); /* support: IE8 */\n}\n.ui-widget-shadow {\n\t-webkit-box-shadow: 0px 0px 5px #666666;\n\tbox-shadow: 0px 0px 5px #666666;\n}\n"
  },
  {
    "path": "functional-samples/sample.catifier/README.md",
    "content": "# Catifier\n\nWhen the extension is enabled, it replaces every image of extension jpg or jpeg, with [this](https://i.chzbgr.com/completestore/12/8/23/S__rxG9hIUK4sNuMdTIY9w2.jpg) image.\n\n## Testing the extension\n\n1. Follow the instructions to load an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n2. Navigate to any website, you should see every jpg or jpeg image being replaced by an image of a cat.\n"
  },
  {
    "path": "functional-samples/sample.catifier/manifest.json",
    "content": "{\n  \"name\": \"Catifier\",\n  \"version\": \"1.0\",\n  \"description\": \"Replace every image by a cat's image in a website you visit\",\n  \"permissions\": [\"declarativeNetRequest\"],\n  \"host_permissions\": [\"<all_urls>\"],\n  \"declarative_net_request\": {\n    \"rule_resources\": [\n      {\n        \"id\": \"ruleset_1\",\n        \"enabled\": true,\n        \"path\": \"rules.json\"\n      }\n    ]\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "functional-samples/sample.catifier/rules.json",
    "content": "[\n  {\n    \"id\": 1,\n    \"priority\": 100,\n    \"action\": {\n      \"type\": \"redirect\",\n      \"redirect\": {\n        \"url\": \"https://i.chzbgr.com/completestore/12/8/23/S__rxG9hIUK4sNuMdTIY9w2.jpg\"\n      }\n    },\n    \"condition\": { \"urlFilter\": \"*.jpeg\", \"resourceType\": [\"image\"] }\n  },\n  {\n    \"id\": 2,\n    \"priority\": 100,\n    \"action\": {\n      \"type\": \"redirect\",\n      \"redirect\": {\n        \"url\": \"https://i.chzbgr.com/completestore/12/8/23/S__rxG9hIUK4sNuMdTIY9w2.jpg\"\n      }\n    },\n    \"condition\": { \"urlFilter\": \"*.jpg\", \"resourceType\": [\"image\"] }\n  }\n]\n"
  },
  {
    "path": "functional-samples/sample.co2meter/README.md",
    "content": "# **Sample CO₂ Meter Chrome Extension**\n\nThe extension uses [WebHID](https://developer.chrome.com/en/articles/hid/) to access a device for measuring the CO₂ level and temperature in your surroundings.\n\n## **Testing the extension**\n\n1. Follow the instructions to load an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n2. Connect the CO₂ meter (currently it only supports the [CO2Mini Indoor Air Quality Monitor](https://www.co2meter.com/products/co2mini-co2-indoor-air-quality-monitor) from CO2Meter.com).\n3. Open the extension popup window and click “Settings” button to go to the settings page.\n4. Click the “Grant CO2 meter permission” button and grant the permission to the CO₂ meter.\n\nFollowing the above steps, the device connection session to the CO₂ meter will be created when the extension is running. The input reports from the device will be processed and are visble from the popup window or settings page.\n\n## **Design**\n\n- [co2_meter.js](modules/co2_meter.js): A CO2 meter device driver layer that uses WebHID to communicate with the device.\n- [co2-state-iframe.js](./co2-state-iframe.js): A module to be embedded in a regular page or popup window for showing the current CO2 meter status. It listens for events from the extension service worker, such as meter readings or availability, and renders the results.\n- [popup.js](./popup.js): For the extension popup window. It includes [co2-state-iframe.js](./co2-state-iframe.js) and a link to open [main-page.js](./main-page.js).\n- [main-page.js](./main-page.js): The settings page for opening a popup to grant permission to the device. It includes [co2-state-iframe.js](./co2-state-iframe.js) as well.\n- [background.js](./background.js): The script that runs on the extension service worker. This is the central piece of this extension, and it will:\n  - Initialize the CO2 meter for starting to generate reading input reports using [co2_meter.js](modules/co2_meter.js).\n  - Broadcast events (e.g., CO2 readings, CO2 availability) to registered clients (e.g., the popup window).\n\n## **WebHID limitations in extension service workers**\n\nWebHID will be officially available to extension service workers in Chrome 115. Before M115, it can be enabled through the flag chrome://flags#enable-web-hid-on-extension-service-worker. However, there are limitations to the support for WebHID in extension service workers:\n\n- Before M115 with flag enabled, if the service worker is idle for longer than [30 seconds](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/service_worker/service_worker.mojom;l=150;drc=ff468ef351dc107e9bb92635914e3908d763cf29) it may be terminated, closing the device connection session. This limitation will be resolved in M115.\n- Device connection events are not fired if the device is plugged or unplugged while the service worker is inactive. We have [crbug.com/1446487](http://crbug.com/1446487) to track the resolution of this limitation. If your extension encounters issues because of this limitation, please leave a comment in the bug about your use case and how the limitation affects your extension.\n"
  },
  {
    "path": "functional-samples/sample.co2meter/background.js",
    "content": "// Copyright 2023 Google LLC\n\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//     https://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n'use strict';\n\nimport icon from './modules/icon.js';\nimport CO2Meter from './modules/co2_meter.js';\nimport {\n  PERMISSION_GRANTED_MESSAGE,\n  CO2_METER_UNAVAILABLE,\n  CO2_METER_AVAILABLE,\n  NO_CO2_METER_FOR_READING,\n  NEW_CO2_READING,\n  NEW_TEMP_READING,\n  READING_UNKNOWN\n} from './modules/constant.js';\n\nlet clients = new Set();\n\nlet last_co2_reading = READING_UNKNOWN;\nlet last_temp_reading = READING_UNKNOWN;\n\nasync function co2MeterConnected() {\n  broadcastMessage(CO2_METER_AVAILABLE);\n  icon.setConnected();\n  startCO2Reading();\n}\n\nasync function co2MeterDisconnected() {\n  CO2Meter.stopReading();\n  broadcastMessage(CO2_METER_UNAVAILABLE);\n  icon.setDisconnected();\n  last_co2_reading = READING_UNKNOWN;\n  last_temp_reading = READING_UNKNOWN;\n  await broadcastMessage(NEW_CO2_READING, last_co2_reading);\n  await broadcastMessage(NEW_TEMP_READING, last_temp_reading);\n}\n\nasync function broadcastMessage(type, data) {\n  for (const client of clients.values()) {\n    client.postMessage({\n      type: type,\n      data: data\n    });\n  }\n}\n\nfunction onPermissionGranted() {\n  co2MeterConnected();\n}\n\nasync function startCO2Reading() {\n  try {\n    await CO2Meter.startReading();\n  } catch (e) {\n    console.log('Exception when startCO2Reading:', e);\n    if (e === NO_CO2_METER_FOR_READING) {\n      co2MeterDisconnected();\n    }\n  }\n}\n\nasync function OnCO2Reading(co2_reading) {\n  last_co2_reading = co2_reading;\n  await broadcastMessage(NEW_CO2_READING, co2_reading);\n}\n\nasync function OnTempReading(temp_reading) {\n  last_temp_reading = temp_reading;\n  await broadcastMessage(NEW_TEMP_READING, temp_reading);\n}\n\nasync function initialize() {\n  chrome.runtime.onMessage.addListener((message) => {\n    if (message === PERMISSION_GRANTED_MESSAGE) {\n      onPermissionGranted();\n      broadcastMessage(CO2_METER_AVAILABLE);\n    }\n  });\n\n  chrome.runtime.onConnect.addListener(async function (port) {\n    port.onDisconnect.addListener(function (port) {\n      clients.delete(port);\n    });\n    clients.add(port);\n    await broadcastMessage(NEW_CO2_READING, last_co2_reading);\n    await broadcastMessage(NEW_TEMP_READING, last_temp_reading);\n  });\n\n  await CO2Meter.init(\n    co2MeterConnected,\n    co2MeterDisconnected,\n    OnCO2Reading,\n    OnTempReading\n  );\n  startCO2Reading();\n}\n\nif (navigator.hid) {\n  initialize();\n} else {\n  console.error(\n    'WebHID is not available! Use chrome://flags#enable-web-hid-on-extension-service-worker'\n  );\n}\n"
  },
  {
    "path": "functional-samples/sample.co2meter/co2-state-iframe.html",
    "content": "<html>\n  <script type=\"module\" src=\"co2-state-iframe.js\"></script>\n  <body>\n    <dl>\n      <dt><b>CO2 meter</b></dt>\n      <dd id=\"co2_meter_connected_status\">unknown</dd>\n      <dt><b>CO2 reading (&#13273;)</b></dt>\n      <dd id=\"co2_reading\">unknown</dd>\n      <dt><b>Temperature reading (&#8457;)</b></dt>\n      <dd id=\"temp_reading\">unknown</dd>\n    </dl>\n  </body>\n</html>\n\n<dialog id=\"noDeviceDialog\">\n  <p>\n    Device is not detected, please make sure the CO2 meter is connected and the\n    permission is granted!\n  </p>\n  <p>Permission can be granted in the settings page.</p>\n  <button id=\"closeDialogButton\">Close</button>\n</dialog>\n"
  },
  {
    "path": "functional-samples/sample.co2meter/co2-state-iframe.js",
    "content": "// Copyright 2023 Google LLC\n\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//     https://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport {\n  CO2_METER_UNAVAILABLE,\n  CO2_METER_AVAILABLE,\n  NEW_CO2_READING,\n  NEW_TEMP_READING,\n  READING_UNKNOWN\n} from './modules/constant.js';\nimport CO2Meter from './modules/co2_meter.js';\n\nwindow.onload = async () => {\n  // Register for messages to update chart upon new data readings.\n  chrome.runtime.connect().onMessage.addListener((msg) => {\n    switch (msg.type) {\n      case NEW_CO2_READING:\n        updateCO2Reading(msg.data);\n        break;\n      case NEW_TEMP_READING:\n        updateTempReading(msg.data);\n        break;\n      case CO2_METER_AVAILABLE:\n        updateCO2MeterStatus(true);\n        break;\n      case CO2_METER_UNAVAILABLE:\n        updateCO2MeterStatus(false);\n        break;\n    }\n  });\n\n  // Dialog\n  document.getElementById('closeDialogButton').onclick = () => {\n    document.getElementById('noDeviceDialog').close();\n  };\n\n  await CO2Meter.init(CO2MeterConnected, CO2MeterDisconnected);\n  const deviceStatus = await CO2Meter.getDeviceStatus();\n  updateCO2MeterStatus(deviceStatus);\n};\n\nfunction updateCO2Reading(co2_reading) {\n  let co2_reading_element = document.getElementById('co2_reading');\n  if (co2_reading === READING_UNKNOWN) {\n    co2_reading_element.textContent = 'unknown';\n  } else {\n    co2_reading_element.textContent = `${co2_reading} \\u33d9`;\n  }\n}\n\nfunction updateTempReading(temp_reading) {\n  let temp_reading_element = document.getElementById('temp_reading');\n  if (temp_reading === READING_UNKNOWN) {\n    temp_reading_element.textContent = 'unknown';\n  } else {\n    const fahrenheit = CO2Meter.tempReadingToFahrenheit(temp_reading);\n    temp_reading_element.textContent = `${fahrenheit}\\u2109`;\n  }\n}\n\nfunction updateCO2MeterStatus(connected) {\n  let noDeviceDialog = document.getElementById('noDeviceDialog');\n  let co2_meter_connected_status = document.getElementById(\n    'co2_meter_connected_status'\n  );\n  if (connected) {\n    noDeviceDialog.close();\n    co2_meter_connected_status.textContent = 'connected';\n  } else {\n    if (!noDeviceDialog.open) {\n      noDeviceDialog.showModal();\n    }\n    co2_meter_connected_status.textContent = 'disconnected';\n  }\n}\n\nfunction CO2MeterConnected() {\n  updateCO2MeterStatus(true);\n}\n\nfunction CO2MeterDisconnected() {\n  updateCO2MeterStatus(false);\n}\n"
  },
  {
    "path": "functional-samples/sample.co2meter/main-page.html",
    "content": "<html>\n  <head>\n    <title>CO2 Meter</title>\n    <script type=\"module\" src=\"main-page.js\"></script>\n    <style>\n      iframe {\n        border: none;\n      }\n    </style>\n  </head>\n  <body>\n    <div>\n      <button type=\"button\" id=\"grantPermissionButton\">\n        Grant CO2 meter permission\n      </button>\n    </div>\n    <iframe src=\"co2-state-iframe.html\"></iframe>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/sample.co2meter/main-page.js",
    "content": "// Copyright 2023 Google LLC\n\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//     https://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport CO2Meter from './modules/co2_meter.js';\n\nwindow.onload = async () => {\n  // Permission\n  // Popup window can't open a permission prompt so we have to use a page instead.\n  // This issue is being tracked by crbug.com/1349183.\n  document.getElementById('grantPermissionButton').onclick = () => {\n    CO2Meter.requestPermission();\n  };\n};\n"
  },
  {
    "path": "functional-samples/sample.co2meter/manifest.json",
    "content": "{\n  \"name\": \"CO2 meter extension\",\n  \"description\": \"Demonstrates using WebHID to connect to a CO2 meter.\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"background.js\",\n    \"type\": \"module\"\n  },\n  \"action\": {\n    \"default_icon\": {\n      \"32\": \"images/icon32.png\"\n    },\n    \"default_title\": \"Show CO2 meter status\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"icons\": {\n    \"32\": \"images/icon32.png\",\n    \"128\": \"images/icon128.png\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/sample.co2meter/modules/co2_meter.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n/**\n * @filename co2_meter.js\n *\n * @description CO2Meter provides methods for accessing status and data of a\n * CO2 meter. When creating a CO2Meter, it has to await `init()` to finish\n * before quering device status.\n */\n\nimport { PERMISSION_GRANTED_MESSAGE } from './constant.js';\n\nconst key = new Uint8Array([0xc4, 0xc6, 0xc0, 0x92, 0x40, 0x23, 0xdc, 0x96]);\n\nfunction KelvinToFahrenheit(k) {\n  return Math.trunc(((k - 273.15) * 9) / 5 + 32);\n}\n\nclass CO2Meter {\n  constructor() {\n    this.device = null;\n    this.connectClientCB = null;\n    this.disconnectClientCB = null;\n    this.co2ReadingClientCB = null;\n    this.tempReadingClientCB = null;\n    this.connectHandler = this.connectHandler.bind(this);\n    this.disconnectHandler = this.disconnectHandler.bind(this);\n    this.onInputReport = this.onInputReport.bind(this);\n  }\n\n  /**\n   * @description This function initializes the CO2Meter object.\n   */\n  async init(\n    connectCallback = null,\n    disconnectCallback = null,\n    co2ReadingCallback = null,\n    tempReadingCallback = null\n  ) {\n    this.connectClientCB = connectCallback;\n    this.disconnectClientCB = disconnectCallback;\n    this.co2ReadingClientCB = co2ReadingCallback;\n    this.tempReadingClientCB = tempReadingCallback;\n    navigator.hid.addEventListener('connect', this.connectHandler);\n    navigator.hid.addEventListener('disconnect', this.disconnectHandler);\n    console.log('CO2Meter init() done');\n  }\n\n  async startReading() {\n    if (this.device) {\n      console.log('CO2 reading has already started!');\n      return;\n    }\n    const devices = await navigator.hid.getDevices();\n    if (devices.length == 0) {\n      throw 'No CO2 meter for reading!';\n    }\n    this.device = devices[0];\n\n    try {\n      await this.device.open();\n      await this.device.sendFeatureReport(0, key);\n    } catch (e) {\n      console.log('CO2 reading exception:', e);\n      await this.device.close();\n      this.device = null;\n      throw 'Fail to open CO2 meter for reading!';\n    }\n\n    this.device.addEventListener('inputreport', this.onInputReport);\n  }\n\n  async stopReading() {\n    if (this.device) {\n      this.device.removeEventListener('inputreport', this.onInputReport);\n      await this.device.close();\n      this.device = null;\n    }\n  }\n\n  onInputReport(report) {\n    let data = new Uint8Array(\n      report.data.buffer,\n      report.data.byteOffset,\n      report.data.byteLength\n    );\n\n    const op = data[0];\n    let val = (data[1] << 8) | data[2];\n\n    if (op == 0x50) {\n      console.log(`Current CO2 reading is ${val}`);\n      if (this.co2ReadingClientCB) {\n        this.co2ReadingClientCB(val);\n      }\n    } else if (op == 0x42) {\n      val = val / 16;\n      console.log(`Current Temp reading is ${val}`);\n      if (this.tempReadingClientCB) {\n        this.tempReadingClientCB(val);\n      }\n    }\n  }\n\n  /**\n   * @description Request user to grant permission for using CO2 meter.\n   * The extension currently only support this model:\n   * https://www.co2meter.com/products/co2mini-co2-indoor-air-quality-monitor\n   */\n  async requestPermission() {\n    const devices = await navigator.hid.requestDevice({\n      filters: [{ vendorId: 1241, productId: 41042 }]\n    });\n    console.log('CO2 meter permission granted!', devices[0]);\n    chrome.runtime.sendMessage(PERMISSION_GRANTED_MESSAGE);\n  }\n\n  connectHandler() {\n    if (this.connectClientCB && typeof this.connectClientCB === 'function') {\n      this.connectClientCB();\n    }\n  }\n\n  disconnectHandler() {\n    if (this.device) {\n      this.device.close();\n    }\n    this.device = null;\n    if (\n      this.disconnectClientCB &&\n      typeof this.disconnectClientCB === 'function'\n    ) {\n      this.disconnectClientCB();\n    }\n  }\n\n  /**\n   * @description Get Device connected status.\n   * @return {Boolean}\n   */\n  async getDeviceStatus() {\n    const devices = await navigator.hid.getDevices();\n    return devices.length > 0;\n  }\n\n  tempReadingToFahrenheit(temp_reading) {\n    return KelvinToFahrenheit(temp_reading);\n  }\n}\n\nexport default new CO2Meter();\n"
  },
  {
    "path": "functional-samples/sample.co2meter/modules/constant.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nexport const PERMISSION_GRANTED_MESSAGE = 'permission granted';\nexport const CO2_METER_UNAVAILABLE = 'co2 meter unavailable';\nexport const CO2_METER_AVAILABLE = 'co2 meter available';\nexport const NO_CO2_METER_FOR_READING = 'No CO2 meter for reading!';\nexport const NEW_CO2_READING = 'new co2 reading';\nexport const NEW_TEMP_READING = 'new temperature reading';\nexport const READING_UNKNOWN = 'reading unknown';\n"
  },
  {
    "path": "functional-samples/sample.co2meter/modules/icon.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nclass Icon {\n  constructor() {}\n\n  setConnected() {\n    chrome.action.setTitle({ title: 'Connected' });\n    chrome.action.setIcon({ path: { 32: 'images/icon32.png' } });\n  }\n\n  setDisconnected() {\n    chrome.action.setTitle({ title: 'Disconnected' });\n    chrome.action.setIcon({ path: { 32: 'images/icon32_disconnected.png' } });\n  }\n}\n\nexport default new Icon();\n"
  },
  {
    "path": "functional-samples/sample.co2meter/popup.html",
    "content": "<html>\n  <script type=\"module\" src=\"popup.js\"></script>\n  <style>\n    iframe {\n      border: none;\n    }\n  </style>\n  <body>\n    <div>\n      <button type=\"button\" id=\"mainPageButton\">Settings</button>\n    </div>\n    <iframe src=\"co2-state-iframe.html\"></iframe>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/sample.co2meter/popup.js",
    "content": "// Copyright 2023 Google LLC\n\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//     https://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n'use strict';\n\nwindow.onload = async () => {\n  document.getElementById('mainPageButton').onclick = () => {\n    window.open('main-page.html', '_blank');\n  };\n};\n"
  },
  {
    "path": "functional-samples/sample.dnr-rule-manager/README.md",
    "content": "# chrome.declarativeNetRequest - No Cookies Rule Manager\n\nThis sample demonstrates using the [`chrome.declarativeNetRequest`](https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/) API to remove the `Cookie` header from requests matching custom URL filters.\n\n## Overview\n\nThis extension has two default rules:\n\n- Any main frame or XHR requests ending with `?nocookies=1` will have their cookies removed (URL Filter).\n\n- Any main frame or XHR requests matching `.*\\.google\\.com` will have their cookies removed (Regex Filter).\n\nFor example, install this extension and try navigating to <https://github.com/GoogleChrome/chrome-extensions-samples?no-cookies=1> or <https://www.google.com> - you should appear signed out. The number of requests modified by this extension will be displayed on the extension's badge.\n\nYou can edit these rules in the manager page.\n\n## Implementation Notes\n\n[`chrome.declarativeNetRequest.setExtensionActionOptions()`](https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#method-setExtensionActionOptions) sets the extension's badge text to the number of requests modified by the extension.\n\n`\"declarativeNetRequestFeedback\"` permission is required to show the matching history.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension's action icon to open the popup.\n4. Click the \"Open Manager Tab\" button to open the manager page.\n"
  },
  {
    "path": "functional-samples/sample.dnr-rule-manager/manager.css",
    "content": "* {\n    box-sizing: border-box;\n}\n\n#rulesList {\n    margin-top: 20px;\n    display: flex;\n    flex-direction: column;\n    gap: 10px;\n}\n\n.rule-item {\n    padding: 5px;\n    border: 1px solid #ccc;\n    border-radius: 10px;\n    position: relative;\n}\n\n.rule-id {\n    width: 4em;\n}\n\n.condition-value {\n    width: 50em;\n    max-width: calc(100vw - 26px);\n}\n\n.actions {\n    position: absolute;\n    top: 5px;\n    right: 5px;\n}\n"
  },
  {
    "path": "functional-samples/sample.dnr-rule-manager/manager.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>no-cookies Rule Manager</title>\n    <link rel=\"stylesheet\" href=\"./manager.css\" />\n  </head>\n\n  <body>\n    <div class=\"toolbar\">\n      <button id=\"addRuleButton\">Add Rule</button>\n      <button id=\"viewRuleButton\">View Current Rule List</button>\n      <small>\n        Requests matching the following conditions will be prohibited from\n        carrying cookies.\n      </small>\n    </div>\n    <div id=\"rulesList\">\n      <!-- Rule Items will be added here -->\n    </div>\n\n    <template id=\"ruleItemTemplate\">\n      <div class=\"rule-item\">\n        <div>\n          <label>\n            Rule ID:\n            <input\n              class=\"rule-id\"\n              type=\"text\"\n              placeholder=\"Rule ID\"\n              disabled\n              value=\"NEW\"\n            />\n          </label>\n        </div>\n        <div class=\"condition\">\n          <div>\n            <label>\n              Condition Type:\n              <select class=\"condition-type\">\n                <option value=\"urlFilter\">URL Filter</option>\n                <option value=\"regexFilter\">Regex Filter</option>\n              </select>\n            </label>\n            <small>\n              <a\n                href=\"https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#property-RuleCondition-urlFilter\"\n                target=\"_blank\"\n                >URL Filter?</a\n              >\n              <span> | </span>\n              <a\n                href=\"https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#property-RuleCondition-regexFilter\"\n                target=\"_blank\"\n                >Regex Filter?</a\n              >\n            </small>\n          </div>\n          <div>\n            <label>\n              Case Sensitive: <input type=\"checkbox\" class=\"case-sensitive\" />\n            </label>\n            <small>\n              <a\n                href=\"https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#property-RuleCondition-isUrlFilterCaseSensitive\"\n                target=\"_blank\"\n                >?</a\n              >\n            </small>\n          </div>\n          <div>\n            <label>\n              Condition Value:\n              <input\n                class=\"condition-value\"\n                type=\"text\"\n                placeholder=\"Condition Value\"\n              />\n            </label>\n          </div>\n        </div>\n        <div class=\"actions\">\n          <button class=\"save-rule\">Save Rule</button>\n          <button class=\"remove-rule\">Remove Rule</button>\n        </div>\n      </div>\n    </template>\n    <script src=\"./manager.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/sample.dnr-rule-manager/manager.js",
    "content": "const ruleItemTemplate = document.getElementById('ruleItemTemplate');\nconst rulesList = document.getElementById('rulesList');\nconst addRuleButton = document.getElementById('addRuleButton');\nconst viewRuleButton = document.getElementById('viewRuleButton');\n\nasync function getNextRuleId() {\n  const rules = await chrome.declarativeNetRequest.getDynamicRules();\n  return Math.max(0, ...rules.map((rule) => rule.id)) + 1;\n}\n\nasync function refresh() {\n  const rules = await chrome.declarativeNetRequest.getDynamicRules();\n  renderRules(rules);\n}\n\nrefresh();\n\naddRuleButton.addEventListener('click', () => {\n  appendRuleItem(rulesList, {\n    id: 'NEW',\n    conditionType: 'urlFilter',\n    conditionValue: '',\n    caseSensitive: true\n  });\n});\n\nviewRuleButton.addEventListener('click', async () => {\n  const rules = await chrome.declarativeNetRequest.getDynamicRules();\n  const rulesString = JSON.stringify(rules, null, 2);\n  const newWindow = window.open();\n  const preElement = newWindow.document.createElement('pre');\n  preElement.style.fontSize = '1rem';\n  preElement.textContent = rulesString;\n  newWindow.document.body.appendChild(preElement);\n});\n\nfunction appendRuleItem(container, initialData) {\n  const { id, conditionType, conditionValue, caseSensitive } = initialData;\n  // Create a new rule item from the template\n  const ruleItem = ruleItemTemplate.content.cloneNode(true).children[0];\n  container.appendChild(ruleItem);\n\n  // Set the rule ID\n  ruleItem.querySelector('.rule-id').value = id;\n\n  // Set the conditionType select\n  ruleItem.querySelector('.condition-type').value = conditionType;\n\n  // set the caseSensitive input\n  ruleItem.querySelector('.case-sensitive').checked = caseSensitive;\n\n  // Set the conditionValue input\n  ruleItem.querySelector('.condition-value').value = conditionValue;\n\n  ruleItem.querySelector('.remove-rule').addEventListener('click', async () => {\n    const { id } = getCurrentRuleValues(ruleItem);\n    // For a new rule, just remove the item from the DOM\n    if (id !== 'NEW') {\n      await removeRule(id);\n    }\n    ruleItem.remove();\n  });\n\n  ruleItem.querySelector('.save-rule').addEventListener('click', async () => {\n    const { id, conditionValue, conditionType, caseSensitive } =\n      getCurrentRuleValues(ruleItem);\n    const realId = id === 'NEW' ? await getNextRuleId() : id;\n    await saveRule({\n      id: realId,\n      conditionType,\n      conditionValue,\n      caseSensitive\n    });\n    // Update the rule ID\n    ruleItem.querySelector('.rule-id').value = realId;\n    // Disable the save button\n    setSaveButtonEnabled(ruleItem, false);\n  });\n\n  // Disable the save button\n  setSaveButtonEnabled(ruleItem, false);\n\n  // Set input change handlers\n  ruleItem\n    .querySelector('.condition-type')\n    .addEventListener('change', verify.bind(null, ruleItem));\n  ruleItem\n    .querySelector('.case-sensitive')\n    .addEventListener('change', verify.bind(null, ruleItem));\n  ruleItem\n    .querySelector('.condition-value')\n    .addEventListener('change', verify.bind(null, ruleItem));\n}\n\nfunction setSaveButtonEnabled(ruleItem, enabled) {\n  ruleItem.querySelector('.save-rule').disabled = !enabled;\n}\n\nfunction getCurrentRuleValues(ruleItem) {\n  let id = ruleItem.querySelector('.rule-id').value;\n  if (id !== 'NEW') id = parseInt(id);\n  const conditionValue = ruleItem\n    .querySelector('.condition-value')\n    .value.trim();\n  const conditionType = ruleItem.querySelector('.condition-type').value;\n  const caseSensitive = ruleItem.querySelector('.case-sensitive').checked;\n  return {\n    id,\n    conditionValue,\n    conditionType,\n    caseSensitive\n  };\n}\n\nasync function verify(ruleItem) {\n  const { conditionValue, conditionType, caseSensitive } =\n    getCurrentRuleValues(ruleItem);\n\n  if (conditionValue.trim() === '') {\n    // If the condition value is empty, disable the save button\n    setSaveButtonEnabled(ruleItem, false);\n    return;\n  }\n  // For the regex filter, verify if the regex is supported\n  if (conditionType === 'regexFilter') {\n    const result = await chrome.declarativeNetRequest.isRegexSupported({\n      isCaseSensitive: caseSensitive,\n      regex: conditionValue\n    });\n    if (!result.isSupported) {\n      // If the regex is invalid, disable the save button\n      setSaveButtonEnabled(ruleItem, false);\n      alert(`Invalid regex: ${result.reason}`);\n      return;\n    }\n  }\n\n  setSaveButtonEnabled(ruleItem, true);\n}\n\nfunction renderRules(rules) {\n  rulesList.innerHTML = '';\n  for (const rule of rules) {\n    // The condition can only be either url-filter or regex-filter in this sample, so it can be determined in this way.\n    const conditionType = Object.keys(rule.condition).includes('urlFilter')\n      ? 'urlFilter'\n      : 'regexFilter';\n    const caseSensitive =\n      rule.condition.isUrlFilterCaseSensitive === undefined ||\n      rule.condition.isUrlFilterCaseSensitive;\n\n    appendRuleItem(rulesList, {\n      id: rule.id,\n      conditionType,\n      caseSensitive,\n      conditionValue: rule.condition[conditionType]\n    });\n  }\n}\n\nasync function saveRule({ id, conditionType, conditionValue, caseSensitive }) {\n  await chrome.declarativeNetRequest.updateDynamicRules({\n    removeRuleIds: [id],\n    addRules: [\n      {\n        id,\n        action: {\n          type: 'modifyHeaders',\n          requestHeaders: [\n            {\n              header: 'cookie',\n              operation: 'remove'\n            }\n          ]\n        },\n        condition: {\n          [conditionType]: conditionValue,\n          isUrlFilterCaseSensitive: caseSensitive,\n          resourceTypes: ['main_frame', 'xmlhttprequest']\n        }\n      }\n    ]\n  });\n}\n\nasync function removeRule(id) {\n  await chrome.declarativeNetRequest.updateDynamicRules({\n    removeRuleIds: [id]\n  });\n}\n"
  },
  {
    "path": "functional-samples/sample.dnr-rule-manager/manifest.json",
    "content": "{\n  \"name\": \"no-cookies Rule Manager\",\n  \"version\": \"0.1\",\n  \"manifest_version\": 3,\n  \"description\": \"Demonstrates the chrome.declarativeNetRequest API by providing a UI to manipulate declarativeNetRequest rules dynamically.\",\n  \"background\": {\n    \"service_worker\": \"service_worker.js\"\n  },\n  \"action\": {\n    \"default_title\": \"no-cookies Rule Manager\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"host_permissions\": [\"<all_urls>\"],\n  \"permissions\": [\"declarativeNetRequest\", \"declarativeNetRequestFeedback\"],\n  \"options_ui\": {\n    \"page\": \"manager.html\",\n    \"open_in_tab\": true\n  }\n}\n"
  },
  {
    "path": "functional-samples/sample.dnr-rule-manager/popup.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>popup</title>\n    <style>\n      html {\n        min-width: 300px;\n      }\n    </style>\n  </head>\n\n  <body>\n    <button id=\"openManagerTab\">Open Manager Tab</button>\n    <div class=\"tips\" style=\"display: none\">\n      No matched rules found for this tab.\n    </div>\n    <div class=\"matched-rules\" style=\"display: none\">\n      <h3>Matched Rules</h3>\n      <div id=\"matchedRulesList\">\n        <!-- Matched Rules will be added here -->\n      </div>\n    </div>\n    <script src=\"./popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/sample.dnr-rule-manager/popup.js",
    "content": "document.getElementById('openManagerTab').addEventListener('click', () => {\n  chrome.tabs.create({ url: 'manager.html' });\n});\n\nconst matchedRulesList = document.getElementById('matchedRulesList');\n\nasync function init() {\n  const tabId = (await chrome.tabs.query({ active: true }))[0].id;\n  const result = await chrome.declarativeNetRequest.getMatchedRules({ tabId });\n  if (result.rulesMatchedInfo.length === 0) {\n    document.querySelector('.tips').style.display = 'block';\n    return;\n  }\n  document.querySelector('.matched-rules').style.display = 'block';\n  for (const item of result.rulesMatchedInfo) {\n    let element = document.createElement('p');\n    element.innerText = `${new Date(\n      item.timeStamp\n    ).toLocaleString()} - RuleId: ${item.rule.ruleId}`;\n    matchedRulesList.appendChild(element);\n  }\n}\n\ninit();\n"
  },
  {
    "path": "functional-samples/sample.dnr-rule-manager/service_worker.js",
    "content": "chrome.runtime.onInstalled.addListener(async function () {\n  // restore the default rule if the extension is installed or updated\n  const existingRules = await chrome.declarativeNetRequest.getDynamicRules();\n  chrome.declarativeNetRequest.updateDynamicRules({\n    removeRuleIds: existingRules.map((rule) => rule.id),\n    addRules: [\n      {\n        id: 1,\n        action: {\n          type: 'modifyHeaders',\n          requestHeaders: [\n            {\n              header: 'cookie',\n              operation: 'remove'\n            }\n          ]\n        },\n        condition: {\n          urlFilter: '|*?no-cookies=1',\n          resourceTypes: ['main_frame', 'xmlhttprequest']\n        }\n      },\n      {\n        id: 2,\n        action: {\n          type: 'modifyHeaders',\n          requestHeaders: [\n            {\n              header: 'cookie',\n              operation: 'remove'\n            }\n          ]\n        },\n        condition: {\n          regexFilter: '.*\\\\.google\\\\.com',\n          resourceTypes: ['main_frame', 'xmlhttprequest']\n        }\n      }\n    ]\n  });\n});\n\nchrome.declarativeNetRequest.setExtensionActionOptions({\n  displayActionCountAsBadgeText: true\n});\n"
  },
  {
    "path": "functional-samples/sample.favicon-cs/README.md",
    "content": "## Fetching a favicon in a content script\n\nThis example fetches the favicon from www.google.com and inserts it at the top left of Google search pages.\n\nNote: This extension does not work on `chrome://extensions`.\n\nSee [Fetching favicons](https://developer.chrome.com/docs/extensions/mv3/favicon) to learn more.\n\n## Testing the extension\n\n1. Follow the instructions to load an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n2. Navigate to [www.google.com](https://www.google.com/).\n\nIt should look like this:\n\n<img src=\"../../.repo/images/content-script-favicon.png\" alt=\"Content script using the Favicon API\" width=\"400\"/>\n"
  },
  {
    "path": "functional-samples/sample.favicon-cs/content.js",
    "content": "function faviconURL(u) {\n  const url = new URL(chrome.runtime.getURL('/_favicon/'));\n  url.searchParams.set('pageUrl', u); // this encodes the URL as well\n  url.searchParams.set('size', '32');\n  return url.toString();\n}\n\nconst imageOverlay = document.createElement('img');\nimageOverlay.src = faviconURL('https://www.google.com');\nimageOverlay.alt = \"Google's favicon\";\nimageOverlay.classList.add('favicon-overlay');\ndocument.body.appendChild(imageOverlay);\n"
  },
  {
    "path": "functional-samples/sample.favicon-cs/manifest.json",
    "content": "{\n  \"name\": \"Favicon API in content scripts\",\n  \"version\": \"1.1\",\n  \"description\": \"Demonstrates fetching the favicon from www.google.com and inserting it at the top left of the specified pages.\",\n  \"manifest_version\": 3,\n  \"content_scripts\": [\n    {\n      \"matches\": [\"https://www.google.com/*\"],\n      \"js\": [\"content.js\"],\n      \"css\": [\"style.css\"]\n    }\n  ],\n  \"permissions\": [\"favicon\"],\n  \"web_accessible_resources\": [\n    {\n      \"resources\": [\"_favicon/*\"],\n      \"matches\": [\"https://www.google.com/*\"],\n      \"use_dynamic_url\": true\n    }\n  ]\n}\n"
  },
  {
    "path": "functional-samples/sample.favicon-cs/style.css",
    "content": ".favicon-overlay {\n  all: initial !important;\n  position: fixed !important;\n  top: 0 !important;\n  left: 0 !important;\n  z-index: 9999 !important;\n}\n"
  },
  {
    "path": "functional-samples/sample.milestones/README.md",
    "content": "Clicking this extension's action button while viewing a Chromium code review will open a small popup that shows what (if any) Chromium version the review was merged into. If the CR has not yet been merged or if the extension cannot find the version it was merged into, the action popup will automatically close itself.\n\n# Demo\n\n1. Install this extension\n2. Visit https://chromium-review.googlesource.com/c/chromium/src/+/3635900\n3. Click the extension's action icon\n\nOnce the extension retrieves the merged milestone information, it will appear in the extnesion's popup as shown below\n\n![The extension's popup shows that this change request was merged in milestone 104](./screenshot.png)\n"
  },
  {
    "path": "functional-samples/sample.milestones/manifest.json",
    "content": "{\n  \"name\": \"Chromium Milestones\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"action\": { \"default_popup\": \"popup.html\" },\n  \"description\": \"Shows the Chromium release milestone a given code review was merged into.\",\n  \"host_permissions\": [\"https://crrie.com/\"],\n  \"permissions\": [\"activeTab\"]\n}\n"
  },
  {
    "path": "functional-samples/sample.milestones/popup.html",
    "content": "<!doctype html>\n<!--\nCopyright 2022 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n<script src=\"popup.js\"></script>\n"
  },
  {
    "path": "functional-samples/sample.milestones/popup.js",
    "content": "// Copyright 2022 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.tabs.query({ active: true }).then((tabs) => getMilestone(tabs));\n\nfunction getMilestone(tabs) {\n  const div = document.createElement('div');\n  document.body.appendChild(div);\n  const url = tabs[0].url;\n  const origin = 'https://chromium-review.googlesource.com';\n  const search = `^${origin}/c/chromium/src/\\\\+/(\\\\d+)`;\n  const match = url.match(search);\n  if (match != undefined && match.length == 2) {\n    getMilestoneForRevId(match[1]).then((milestone) =>\n      milestone != '' ? (div.innerText = `m${milestone}`) : window.close()\n    );\n  } else {\n    window.close();\n  }\n}\n\nasync function getMilestoneForRevId(revId) {\n  const res = await fetch(`https://crrie.com/c/?r=${revId}`);\n  return await res.text();\n}\n"
  },
  {
    "path": "functional-samples/sample.optional_permissions/README.md",
    "content": "## Optional permissions in a new tab\n\nThis sample extension changes the **New Tab** page, prompting the user for permission to display their top sites. It demonstrates how extensions can provide users with the option to enable additional features.\n\nSee [optional permissions](https://developer.chrome.com/docs/extensions/reference/permissions/) to learn more.\n\n## Testing the extension\n\nFollow the instructions to load an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked), then open a new tab.\n\nIt should look like this:\n\n<img src=\"../../.repo/images/optional-permissions-new-tab.png\" alt=\"New tab with optional permission button\" width=\"500\"/>\n\nThen, click on `Allow Extension to Access to Top Sites`. You will see the following message:\n\n<img src=\"../../.repo/images/optional-permissions-dialog.png\" alt=\"Permissions dialog with Deny and Allow buttons respectively\" width=\"400\"/>\n\nSelecting `Allow` will display a list of the websites you visit most.\n\n<img src=\"../../.repo/images/optional-permissions-top-sites.png\" alt=\"New tab displaying top sites\" width=\"400\"/>\n"
  },
  {
    "path": "functional-samples/sample.optional_permissions/manifest.json",
    "content": "{\n  \"name\": \"Optional Permissions New Tab\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Demonstrates optional permissions in extensions\",\n  \"permissions\": [\"storage\", \"favicon\"],\n  \"optional_permissions\": [\"topSites\"],\n  \"icons\": {\n    \"16\": \"images/icon16.png\",\n    \"32\": \"images/icon32.png\",\n    \"48\": \"images/icon48.png\",\n    \"128\": \"images/icon128.png\"\n  },\n  \"chrome_url_overrides\": {\n    \"newtab\": \"newtab.html\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "functional-samples/sample.optional_permissions/newtab.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>New Tab - Optional Permissions</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />\n  </head>\n  <body>\n    <div id=\"todo_div\" class=\"center colorFun\">\n      <h1 id=\"display_todo\"></h1>\n    </div>\n    <div id=\"display_top\"></div>\n    <form class=\"center\">\n      <input id=\"todo_value\" placeholder=\"My focus today is...\" />\n      <input type=\"submit\" value=\"Submit\" />\n    </form>\n    <footer></footer>\n    <script src=\"newtab.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/sample.optional_permissions/newtab.js",
    "content": "// Copyright 2022 Google LLC\n\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n\n//     https://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n'use strict';\n\nconst newPerms = {\n  permissions: ['topSites']\n};\n\nconst sites_div = document.getElementById('display_top');\nconst todo = document.getElementById('display_todo');\nconst form = document.querySelector('form');\nconst footer = document.querySelector('footer');\n\nconst createTop = () => {\n  chrome.topSites.get((topSites) => {\n    topSites.forEach((site) => {\n      const div = document.createElement('div');\n      div.className = 'colorFun';\n      const tooltip = document.createElement('a');\n      tooltip.href = site.url;\n      tooltip.innerText = site.title;\n      tooltip.className = 'tooltip';\n      const url = document.createElement('a');\n      url.href = site.url;\n      const imageContainer = document.createElement('div');\n      imageContainer.className = 'imageContainer';\n      const imgUrl = new URL(chrome.runtime.getURL('/_favicon/'));\n      imgUrl.searchParams.set('pageUrl', site.url);\n      imgUrl.searchParams.set('size', '28');\n      const image = document.createElement('img');\n      image.title = site.title;\n      image.src = imgUrl.toString();\n      imageContainer.appendChild(image);\n      url.appendChild(imageContainer);\n      div.appendChild(url);\n      div.appendChild(tooltip);\n      sites_div.appendChild(div);\n    });\n  });\n};\n\nchrome.permissions.contains({ permissions: ['topSites'] }).then((result) => {\n  if (result) {\n    // The extension has the permissions.\n    createTop();\n  } else {\n    // The extension doesn't have the permissions.\n    const button = document.createElement('button');\n    button.innerText = 'Allow Extension to Access Top Sites';\n    button.addEventListener('click', () => {\n      chrome.permissions.request(newPerms).then((granted) => {\n        if (granted) {\n          console.log('granted');\n          sites_div.innerText = '';\n          createTop();\n        } else {\n          console.log('not granted');\n        }\n      });\n    });\n    footer.appendChild(button);\n  }\n});\n\nform.addEventListener('submit', () => {\n  const todo_value = document.getElementById('todo_value');\n  chrome.storage.sync.set({ todo: todo_value.value });\n});\n\nfunction setToDo() {\n  chrome.storage.sync.get(['todo']).then((value) => {\n    if (!value.todo) {\n      todo.innerText = '';\n    } else {\n      todo.innerText = value.todo;\n    }\n  });\n}\n\nsetToDo();\n"
  },
  {
    "path": "functional-samples/sample.optional_permissions/style.css",
    "content": "/* Copyright 2022 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License. */\n\nh1 {\n  font-family: Verdana, Geneva, Tahoma, sans-serif;\n}\n\n#display_top {\n  margin: auto;\n  margin-bottom: 40px;\n  width: 600px;\n}\n\n#todo_div {\n  margin-top: 0px;\n  height: 100px;\n  width: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n\n  animation-name: color-extravaganza;\n  animation-duration: 6s;\n  animation-iteration-count: infinite;\n  animation-direction: alternate;\n}\n\n.center {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n@keyframes color-extravaganza {\n  0% {\n    background-color: #4285f4;\n  }\n  10% {\n    background-color: #4285f4;\n  }\n  25% {\n    background-color: #ea4335;\n  }\n  50% {\n    background-color: #fbbc04;\n  }\n  100% {\n    background-color: #34a853;\n  }\n}\n\n.colorFun {\n  position: relative;\n  height: 70px;\n  width: 100px;\n  padding: 10px;\n  display: inline-block;\n  margin-top: 40px;\n}\n\n.colorFun .tooltip {\n  width: 100px;\n  text-align: center;\n  padding: 5px 0;\n  position: absolute;\n  z-index: 1;\n  bottom: 0%;\n  left: 50%;\n  transform: translateX(-50%);\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.imageContainer {\n  background-color: #cdcdcd;\n  width: 50px;\n  height: 50px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  border-radius: 50%;\n  justify-self: center;\n}\n\n.imageContainer img {\n  width: 28px;\n  height: 28px;\n}\n\nfooter {\n  position: absolute;\n  bottom: 20px;\n  left: 20px;\n}\n\ninput#todo_value {\n  width: 300px;\n  height: 40px;\n  font-size: 18px;\n  padding: 12px 20px;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n  box-sizing: border-box;\n  margin-right: 4px;\n}\n\ninput#todo_value ~ input[type=\"submit\"] {\n  background-color: #4285F4;\n  color: white;\n  padding: 12px 20px;\n  border: none;\n  border-radius: 4px;\n  cursor: pointer;\n}\n\ninput#todo_value ~ input[type=\"submit\"]:hover {\n  background-color: #45a049;\n}\n"
  },
  {
    "path": "functional-samples/sample.page-redder/README.md",
    "content": "# Page Redder\n\nThis sample demonstrates how to use the [chrome.action](https://developer.chrome.com/docs/extensions/reference/api/action) API to execute code when the extension icon is clicked.\n\n## Overview\n\nThis extension changes the background color of the active tab page (if its URL doesn't start with `chrome://`) to red when the extension icon is clicked.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Navigate to any page (make sure that the URL doesn't start with `chrome://`).\n4. Click the extension icon.\n"
  },
  {
    "path": "functional-samples/sample.page-redder/manifest.json",
    "content": "{\n  \"name\": \"Page Redder\",\n  \"action\": {},\n  \"manifest_version\": 3,\n  \"version\": \"0.1\",\n  \"description\": \"Turns the page red when you click the icon\",\n  \"permissions\": [\"activeTab\", \"scripting\"],\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/sample.page-redder/service-worker.js",
    "content": "function reddenPage() {\n  document.body.style.backgroundColor = 'red';\n}\n\nchrome.action.onClicked.addListener((tab) => {\n  if (!tab.url.includes('chrome://')) {\n    chrome.scripting.executeScript({\n      target: { tabId: tab.id },\n      function: reddenPage\n    });\n  }\n});\n"
  },
  {
    "path": "functional-samples/sample.sidepanel-dictionary/README.md",
    "content": "# Dictionary Side panel example\n\nThis example allows users to right-click on a word and see the definition on the side panel using the [Side Panel API](https://developer.chrome.com/docs/extensions/reference/sidePanel/).\n\nNOTE: This example only defines the word extensions and popup.\n\n## Implementation Notes\n\nWhen the user selects a word, we need to send it to the side panel, but that\nmay not be open yet. To handle this we store the word in\n`chrome.storage.session`, which results in the following:\n\n- If the side panel is already open, the `storage.session.onChanged` event\n  will fire in the side panel.\n- Otherwise, the value will be loaded from storage when the side panel opens.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Go to https://developer.chrome.com/docs/extensions/\n4. Right-click on the \"Extensions\" word.\n5. Choose the \"Define\" context menu\n\nYou should see the definition on the side panel\n\n<img src=\"../../.repo/images/side-panel-dictionary-context-menu.png\" alt=\"Dictionary extension context menu\">\n"
  },
  {
    "path": "functional-samples/sample.sidepanel-dictionary/manifest.json",
    "content": "{\n  \"name\": \"Dictionary side panel\",\n  \"version\": \"0.1\",\n  \"manifest_version\": 3,\n  \"description\": \"Provides definitions in the side panel.\",\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"icons\": {\n    \"128\": \"images/icon-128.png\",\n    \"16\": \"images/icon-16.png\"\n  },\n  \"side_panel\": {\n    \"default_path\": \"sidepanel.html\"\n  },\n  \"permissions\": [\"sidePanel\", \"contextMenus\", \"storage\"]\n}\n"
  },
  {
    "path": "functional-samples/sample.sidepanel-dictionary/service-worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nfunction setupContextMenu() {\n  chrome.contextMenus.create({\n    id: 'define-word',\n    title: 'Define',\n    contexts: ['selection']\n  });\n}\n\nchrome.runtime.onInstalled.addListener(() => {\n  setupContextMenu();\n});\n\nchrome.contextMenus.onClicked.addListener((data, tab) => {\n  // Store the last word in chrome.storage.session.\n  chrome.storage.session.set({ lastWord: data.selectionText });\n\n  // Make sure the side panel is open.\n  chrome.sidePanel.open({ tabId: tab.id });\n});\n"
  },
  {
    "path": "functional-samples/sample.sidepanel-dictionary/sidepanel.html",
    "content": "<html>\n  <head>\n    <title>Dictionary Side Panel</title>\n  </head>\n  <body>\n    <h1>Dictionary</h1>\n    <hr />\n    <p id=\"select-a-word\">Select a word to see the definition.</p>\n    <div>\n      <h2 id=\"definition-word\"></h2>\n      <p id=\"definition-text\"></p>\n    </div>\n    <script src=\"sidepanel.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/sample.sidepanel-dictionary/sidepanel.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst words = {\n  extensions:\n    'Extensions are software programs, built on web technologies (such as HTML, CSS, and JavaScript) that enable users to customize the Chrome browsing experience.',\n  popup:\n    \"A UI surface which appears when an extension's action icon is clicked.\"\n};\n\nchrome.storage.session.get('lastWord', ({ lastWord }) => {\n  updateDefinition(lastWord);\n});\n\nchrome.storage.session.onChanged.addListener((changes) => {\n  const lastWordChange = changes['lastWord'];\n\n  if (!lastWordChange) {\n    return;\n  }\n\n  updateDefinition(lastWordChange.newValue);\n});\n\nfunction updateDefinition(word) {\n  // If the side panel was opened manually, rather than using the context menu,\n  // we might not have a word to show the definition for.\n  if (!word) return;\n\n  // Hide instructions.\n  document.body.querySelector('#select-a-word').style.display = 'none';\n\n  // Show word and definition.\n  document.body.querySelector('#definition-word').innerText = word;\n  document.body.querySelector('#definition-text').innerText =\n    words[word.toLowerCase()] ??\n    `Unknown word! Supported words: ${Object.keys(words).join(', ')}`;\n}\n"
  },
  {
    "path": "functional-samples/sample.tabcapture-recorder/README.md",
    "content": "# chrome.tabCapture recorder\n\nThis sample demonstrates how to use the [`chrome.tabCapture`](https://developer.chrome.com/docs/extensions/reference/tabCapture/) API to record in the background, using a service worker and [offscreen document](https://developer.chrome.com/docs/extensions/reference/offscreen/).\n\n## Overview\n\nIn this sample, clicking the action button starts recording the current tab in an offscreen document. After 30 seconds, or once the action button is clicked again, the recording ends and is saved as a download.\n\n## Implementation Notes\n\nSee the [Audio recording and screen capture guide](https://developer.chrome.com/docs/extensions/mv3/screen_capture/#audio-and-video-offscreen-doc) for more implementation details.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extension from the extension menu.\n4. Click the extension's action icon to start recording.\n5. Click the extension's action again to stop recording.\n"
  },
  {
    "path": "functional-samples/sample.tabcapture-recorder/manifest.json",
    "content": "{\n  \"name\": \"Tab Capture - Recorder\",\n  \"description\": \"Records the current tab in an offscreen document.\",\n  \"version\": \"1\",\n  \"manifest_version\": 3,\n  \"minimum_chrome_version\": \"116\",\n  \"action\": {\n    \"default_icon\": \"icons/not-recording.png\"\n  },\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"permissions\": [\"tabCapture\", \"offscreen\"]\n}\n"
  },
  {
    "path": "functional-samples/sample.tabcapture-recorder/offscreen.html",
    "content": "<!--\n Copyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n  -->\n<!doctype html>\n<script src=\"offscreen.js\"></script>\n"
  },
  {
    "path": "functional-samples/sample.tabcapture-recorder/offscreen.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.runtime.onMessage.addListener(async (message) => {\n  if (message.target === 'offscreen') {\n    switch (message.type) {\n      case 'start-recording':\n        startRecording(message.data);\n        break;\n      case 'stop-recording':\n        stopRecording();\n        break;\n      default:\n        throw new Error('Unrecognized message:', message.type);\n    }\n  }\n});\n\nlet recorder;\nlet data = [];\n\nasync function startRecording(streamId) {\n  if (recorder?.state === 'recording') {\n    throw new Error('Called startRecording while recording is in progress.');\n  }\n\n  const media = await navigator.mediaDevices.getUserMedia({\n    audio: {\n      mandatory: {\n        chromeMediaSource: 'tab',\n        chromeMediaSourceId: streamId\n      }\n    },\n    video: {\n      mandatory: {\n        chromeMediaSource: 'tab',\n        chromeMediaSourceId: streamId\n      }\n    }\n  });\n\n  // Continue to play the captured audio to the user.\n  const output = new AudioContext();\n  const source = output.createMediaStreamSource(media);\n  source.connect(output.destination);\n\n  // Start recording.\n  recorder = new MediaRecorder(media, { mimeType: 'video/webm' });\n  recorder.ondataavailable = (event) => data.push(event.data);\n  recorder.onstop = () => {\n    const blob = new Blob(data, { type: 'video/webm' });\n    window.open(URL.createObjectURL(blob), '_blank');\n\n    // Clear state ready for next recording\n    recorder = undefined;\n    data = [];\n  };\n  recorder.start();\n\n  // Record the current state in the URL. This provides a very low-bandwidth\n  // way of communicating with the service worker (the service worker can check\n  // the URL of the document and see the current recording state). We can't\n  // store that directly in the service worker as it may be terminated while\n  // recording is in progress. We could write it to storage but that slightly\n  // increases the risk of things getting out of sync.\n  window.location.hash = 'recording';\n}\n\nasync function stopRecording() {\n  recorder.stop();\n\n  // Stopping the tracks makes sure the recording icon in the tab is removed.\n  recorder.stream.getTracks().forEach((t) => t.stop());\n\n  // Update current state in URL\n  window.location.hash = '';\n\n  // Note: In a real extension, you would want to write the recording to a more\n  // permanent location (e.g IndexedDB) and then close the offscreen document,\n  // to avoid keeping a document around unnecessarily. Here we avoid that to\n  // make sure the browser keeps the Object URL we create (see above) and to\n  // keep the sample fairly simple to follow.\n}\n"
  },
  {
    "path": "functional-samples/sample.tabcapture-recorder/service-worker.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.action.onClicked.addListener(async (tab) => {\n  const existingContexts = await chrome.runtime.getContexts({});\n  let recording = false;\n\n  const offscreenDocument = existingContexts.find(\n    (c) => c.contextType === 'OFFSCREEN_DOCUMENT'\n  );\n\n  // If an offscreen document is not already open, create one.\n  if (!offscreenDocument) {\n    // Create an offscreen document.\n    await chrome.offscreen.createDocument({\n      url: 'offscreen.html',\n      reasons: ['USER_MEDIA'],\n      justification: 'Recording from chrome.tabCapture API'\n    });\n  } else {\n    recording = offscreenDocument.documentUrl.endsWith('#recording');\n  }\n\n  if (recording) {\n    chrome.runtime.sendMessage({\n      type: 'stop-recording',\n      target: 'offscreen'\n    });\n    chrome.action.setIcon({ path: 'icons/not-recording.png' });\n    return;\n  }\n\n  // Get a MediaStream for the active tab.\n  const streamId = await chrome.tabCapture.getMediaStreamId({\n    targetTabId: tab.id\n  });\n\n  // Send the stream ID to the offscreen document to start recording.\n  chrome.runtime.sendMessage({\n    type: 'start-recording',\n    target: 'offscreen',\n    data: streamId\n  });\n\n  chrome.action.setIcon({ path: '/icons/recording.png' });\n});\n"
  },
  {
    "path": "functional-samples/sample.theme/README.md",
    "content": "# Sample Chrome Theme\n\nThis is a Chrome [theme](https://developer.chrome.com/docs/extensions/develop/ui/themes), that shows a number of color customization options.\n\n## Running this extension\n\n1. Clone this repository.\n1. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n1. Reset your theme on the Chrome Appearance settings panel - chrome://settings/appearance\n"
  },
  {
    "path": "functional-samples/sample.theme/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Simple Theme\",\n  \"version\": \"1.0\",\n  \"theme\": {\n    \"colors\": {\n      \"background_tab\": [255, 0, 0],\n      \"background_tab_inactive\": [0, 255, 0],\n      \"background_tab_incognito\": [0, 0, 255],\n      \"background_tab_incognito_inactive\": [255, 255, 0],\n      \"bookmark_text\": [255, 0, 255],\n      \"button_background\": [0, 255, 255],\n      \"frame\": [128, 128, 128],\n      \"frame_inactive\": [255, 128, 0],\n      \"frame_incognito\": [128, 255, 0],\n      \"frame_incognito_inactive\": [0, 128, 255],\n      \"ntp_background\": [255, 0, 128],\n      \"ntp_header\": [0, 255, 128],\n      \"ntp_link\": [128, 0, 255],\n      \"ntp_text\": [255, 255, 255],\n      \"omnibox_background\": [0, 128, 128],\n      \"omnibox_text\": [128, 128, 0],\n      \"tab_background_text\": [0, 0, 128],\n      \"tab_background_text_inactive\": [0, 128, 0],\n      \"tab_background_text_incognito\": [128, 0, 0],\n      \"tab_background_text_incognito_inactive\": [128, 128, 128],\n      \"tab_text\": [255, 255, 0],\n      \"toolbar\": [255, 0, 64],\n      \"toolbar_button_icon\": [0, 255, 64],\n      \"toolbar_text\": [64, 0, 255]\n    }\n  }\n}\n"
  },
  {
    "path": "functional-samples/sample.water_alarm_notification/README.md",
    "content": "# Drink Water Alarm\n\nThis example demonstrates how to use the [Alarms API](https://developer.chrome.com/docs/extensions/reference/api/alarms) and [Notifications API](https://developer.chrome.com/docs/extensions/reference/api/notifications) to remind users to drink water at set intervals.\n\n## Overview\n\nThe extension allows users to set a recurring reminder to stay hydrated. Users can choose from preset intervals (1, 15, or 30 minutes) through a popup interface. When the alarm fires, a notification appears prompting the user to drink water.\n\n## Implementation Notes\n\nThe extension uses several Chrome APIs together:\n\n- `chrome.alarms` - Creates and manages the reminder timer\n- `chrome.notifications` - Displays the hydration reminder when the alarm fires\n- `chrome.storage.sync` - Persists the user's selected interval across sessions\n- `chrome.action` - Shows an \"ON\" badge when an alarm is active\n\nWhen the notification appears, users can click \"Keep it Flowing\" to restart the timer with their previously selected interval.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension icon to open the popup.\n4. Select a time interval (Sample minute, 15 Minutes, or 30 Minutes).\n5. Wait for the notification to appear reminding you to drink water.\n"
  },
  {
    "path": "functional-samples/sample.water_alarm_notification/background.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n'use strict';\n\nchrome.alarms.onAlarm.addListener(() => {\n  chrome.action.setBadgeText({ text: '' });\n  chrome.notifications.create({\n    type: 'basic',\n    iconUrl: 'stay_hydrated.png',\n    title: 'Time to Hydrate',\n    message: \"Everyday I'm Guzzlin'!\",\n    buttons: [{ title: 'Keep it Flowing.' }],\n    priority: 0\n  });\n});\n\nchrome.notifications.onButtonClicked.addListener(async () => {\n  const item = await chrome.storage.sync.get(['minutes']);\n  chrome.action.setBadgeText({ text: 'ON' });\n  chrome.alarms.create({ delayInMinutes: item.minutes });\n});\n"
  },
  {
    "path": "functional-samples/sample.water_alarm_notification/manifest.json",
    "content": "{\n  \"name\": \"Drink Water Event Popup\",\n  \"description\": \"Demonstrates usage and features of the event page by reminding user to drink water\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"permissions\": [\"alarms\", \"notifications\", \"storage\"],\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"action\": {\n    \"default_title\": \"Drink Water Event\",\n    \"default_popup\": \"popup.html\"\n  },\n  \"icons\": {\n    \"16\": \"drink_water16.png\",\n    \"32\": \"drink_water32.png\",\n    \"48\": \"drink_water48.png\",\n    \"128\": \"drink_water128.png\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/sample.water_alarm_notification/popup.html",
    "content": "<!-- Copyright 2017 The Chromium Authors. All rights reserved.\nUse of this source code is governed by a BSD-style license that can be\nfound in the LICENSE file. -->\n<!doctype html>\n<html>\n  <head>\n    <title>Water Popup</title>\n    <style>\n      body {\n        text-align: center;\n      }\n\n      #hydrateImage {\n        width: 100px;\n        margin: 5px;\n      }\n\n      button {\n        margin: 5px;\n        outline: none;\n      }\n\n      button:hover {\n        outline: #80deea dotted thick;\n      }\n    </style>\n    <!--\n      - JavaScript and HTML must be in separate files\n     -->\n  </head>\n  <body>\n    <img src=\"./stay_hydrated.png\" id=\"hydrateImage\" />\n    <!-- An Alarm delay of less than the minimum 1 minute will fire\n      in approximately 1 minute increments if released -->\n    <button id=\"sampleMinute\" value=\"1\">Sample minute</button>\n    <button id=\"min15\" value=\"15\">15 Minutes</button>\n    <button id=\"min30\" value=\"30\">30 Minutes</button>\n    <button id=\"cancelAlarm\">Cancel Alarm</button>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/sample.water_alarm_notification/popup.js",
    "content": "// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n'use strict';\n\nfunction setAlarm(event) {\n  const minutes = parseFloat(event.target.value);\n  chrome.action.setBadgeText({ text: 'ON' });\n  chrome.alarms.create({ delayInMinutes: minutes });\n  chrome.storage.sync.set({ minutes: minutes });\n  window.close();\n}\n\nfunction clearAlarm() {\n  chrome.action.setBadgeText({ text: '' });\n  chrome.alarms.clearAll();\n  window.close();\n}\n\n// An Alarm delay of less than the minimum 1 minute will fire\n// in approximately 1 minute increments if released\ndocument.getElementById('sampleMinute').addEventListener('click', setAlarm);\ndocument.getElementById('min15').addEventListener('click', setAlarm);\ndocument.getElementById('min30').addEventListener('click', setAlarm);\ndocument.getElementById('cancelAlarm').addEventListener('click', clearAlarm);\n"
  },
  {
    "path": "functional-samples/sample.webgpu/README.md",
    "content": "# WebGPU extension sample\n\nThis sample demonstrates how to use the [WebGPU API](https://webgpu.dev/) to generate a red triangle using an extension service worker.\n\n> [!WARNING]  \n> Service worker support in WebGPU is enabled by default in Chrome 124.\n> If you are using Chrome 123, you can still enable this feature by running Chrome with the \"Experimental Web Platform Features\" flag.\n\n## Overview\n\nIn this sample, clicking the action button opens a red triangle image in a new tab.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extension from the extension menu.\n4. Click the extension's action icon to open the red triangle in a new tab.\n"
  },
  {
    "path": "functional-samples/sample.webgpu/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"WebGPU Extension\",\n  \"description\": \"Generate a red triangle with WebGPU in an extension service worker.\",\n  \"version\": \"1.0\",\n  \"action\": {\n    \"default_title\": \"Click to see a red triangle\"\n  },\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/sample.webgpu/service-worker.js",
    "content": "chrome.action.onClicked.addListener(async () => {\n  const adapter = await navigator.gpu.requestAdapter();\n  const device = await adapter.requestDevice();\n\n  const canvas = new OffscreenCanvas(256, 256);\n  const context = canvas.getContext('webgpu');\n  const format = navigator.gpu.getPreferredCanvasFormat();\n  context.configure({ device, format });\n\n  const code = `\n      @vertex fn vertexMain(@builtin(vertex_index) i : u32) ->\n      @builtin(position) vec4f {\n      const pos = array(vec2f(0, 1), vec2f(-1, -1), vec2f(1, -1));\n      return vec4f(pos[i], 0, 1);\n      }\n      @fragment fn fragmentMain() -> @location(0) vec4f {\n      return vec4f(1, 0, 0, 1);\n      }`;\n  const module = device.createShaderModule({ code });\n  const pipeline = await device.createRenderPipelineAsync({\n    layout: 'auto',\n    vertex: { module },\n    fragment: { module, targets: [{ format }] }\n  });\n  const commandEncoder = device.createCommandEncoder();\n  const colorAttachments = [\n    {\n      view: context.getCurrentTexture().createView(),\n      loadOp: 'clear',\n      storeOp: 'store'\n    }\n  ];\n  const passEncoder = commandEncoder.beginRenderPass({ colorAttachments });\n  passEncoder.setPipeline(pipeline);\n  passEncoder.draw(3);\n  passEncoder.end();\n  device.queue.submit([commandEncoder.finish()]);\n\n  // Open canvas as an image in a new tab.\n  const blob = await canvas.convertToBlob();\n  const reader = new FileReader();\n  reader.onload = () => chrome.tabs.create({ url: reader.result });\n  reader.readAsDataURL(blob);\n});\n"
  },
  {
    "path": "functional-samples/tutorial.broken-color/README.md",
    "content": "## Context\n\nThis is a simple sample extension used in the [Debugging extensions][1] tutorial. The purpose of this extension is to demonstrate how to debug different extension components. This extension changes the background color of active tab.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension][2].\n3. Go to https://developer.chrome.com/docs/extensions.\n4. Open the extension popup and click on the color.\n5. The background color will change.\n\n[1]: https://developer.chrome.com/docs/extensions/mv3/tut_debugging/\n[2]: https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked\n"
  },
  {
    "path": "functional-samples/tutorial.broken-color/manifest.json",
    "content": "{\n  \"name\": \"Broken Background Color\",\n  \"version\": \"1.0\",\n  \"description\": \"Fix an Extension!\",\n  \"permissions\": [\"activeTab\", \"scripting\", \"storage\"],\n  \"options_page\": \"options.html\",\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"action\": {\n    \"default_popup\": \"popup.html\",\n    \"default_icon\": {\n      \"16\": \"images/icon-16.png\",\n      \"128\": \"images/icon-128.png\"\n    }\n  },\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"128\": \"images/icon-128.png\"\n  },\n  \"manifest_version\": 3\n}\n"
  },
  {
    "path": "functional-samples/tutorial.broken-color/options.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <style>\n      button {\n        height: 30px;\n        width: 30px;\n        outline: none;\n        margin: 10px;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"buttonDiv\"></div>\n    <div>\n      <p>Choose a different background color!</p>\n    </div>\n    <script src=\"options.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/tutorial.broken-color/options.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst buttonDiv = document.getElementById('buttonDiv');\nconst buttonColors = ['#3aa757', '#e8453c', '#f9bb2d', '#4688f1'];\n\nconst createColorButtons = (buttonColors) => {\n  buttonColors.forEach((color) => {\n    const button = document.createElement('button');\n    button.style.backgroundColor = color;\n\n    button.addEventListener('click', () => {\n      chrome.storage.sync.set({ color }, () => {\n        console.log(`color is ${color}`);\n      });\n    });\n\n    buttonDiv.appendChild(button);\n  });\n};\n\ncreateColorButtons(buttonColors);\n"
  },
  {
    "path": "functional-samples/tutorial.broken-color/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <style>\n      button {\n        height: 30px;\n        width: 30px;\n        outline: none;\n        background-color: #3aa757;\n      }\n    </style>\n  </head>\n  <body>\n    <button id=\"changeColor\"></button>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/tutorial.broken-color/popup.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst changeColorButton = document.getElementById('changeColor');\n\n// Retrieve the color from storage and update the button's style and value\nchrome.storage.sync.get('color', ({ color }) => {\n  changeColorButton.style.backgroundColor = color;\n  changeColorButton.setAttribute('value', color);\n});\n\nchangeColorButton.addEventListener('click', (event) => {\n  const color = event.target.value;\n\n  // Query the active tab before injecting the content script\n  chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {\n    // Use the Scripting API to execute a script\n    chrome.scripting.executeScript({\n      target: { tabId: tabs[0].id },\n      args: [color],\n      func: setColor\n    });\n  });\n});\n\nfunction setColor(color) {\n  // There's a typo in the line below;\n  // ❌ colors should be ✅ color.\n  document.body.style.backgroundColor = color;\n}\n"
  },
  {
    "path": "functional-samples/tutorial.broken-color/service-worker.js",
    "content": "// Copyright 2018 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// There's a typo in the line below;\n// ❌ oninstalled should be ✅ onInstalled.\nchrome.runtime.onInstalled.addListener(() => {\n  chrome.storage.sync.set({ color: '#3aa757' }, () => {\n    console.log('The background color is green.');\n  });\n});\n"
  },
  {
    "path": "functional-samples/tutorial.custom-cursor/README.md",
    "content": "# Custom Cursor extension\n\nAdds a custom cursor to pages on https://developer.chrome.com. This sample is part of a [tutorial on YouTube](https://www.youtube.com/watch?v=QYgKhYbJFUU).\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Open https://developer.chrome.com.\n"
  },
  {
    "path": "functional-samples/tutorial.custom-cursor/counter.js",
    "content": "document.addEventListener('click', () => {\n  chrome.runtime.sendMessage('page-click');\n});\n"
  },
  {
    "path": "functional-samples/tutorial.custom-cursor/manifest.json",
    "content": "{\n  \"name\": \"Custom Cursor Extension\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"description\": \"Adds a custom cursor on developer.chrome.com.\",\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"content_scripts\": [\n    {\n      \"matches\": [\"https://developer.chrome.com/*\"],\n      \"css\": [\"style.css\"],\n      \"js\": [\"counter.js\"]\n    }\n  ],\n  \"web_accessible_resources\": [\n    {\n      \"resources\": [\"dino.png\", \"dino-pointer.png\"],\n      \"matches\": [\"https://developer.chrome.com/*\"],\n      \"use_dynamic_urls\": true\n    }\n  ],\n  \"permissions\": [\"storage\"],\n  \"action\": {\n    \"default_title\": \"Custom Cursor\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/tutorial.custom-cursor/service-worker.js",
    "content": "chrome.runtime.onMessage.addListener(async (msg) => {\n  if (msg === 'page-click') {\n    const data = await chrome.storage.local.get({ counter: 0 });\n    let counter = data['counter'];\n    counter++;\n    chrome.storage.local.set({ counter });\n    await chrome.action.setBadgeText({ text: counter.toString() });\n  }\n});\n"
  },
  {
    "path": "functional-samples/tutorial.custom-cursor/style.css",
    "content": "html {\n  cursor:\n    url('chrome-extension://__MSG_@@extension_id__/dino.png') 16 16,\n    auto;\n}\n\na {\n  cursor:\n    url('chrome-extension://__MSG_@@extension_id__/dino-pointer.png') 16 16,\n    auto;\n}\n"
  },
  {
    "path": "functional-samples/tutorial.focus-mode/README.md",
    "content": "# Focus Mode\n\nThis example demonstrates how to use the [Scripting API](https://developer.chrome.com/docs/extensions/reference/api/scripting) to inject and remove CSS on demand, enabling a distraction-free reading experience on Chrome's documentation pages.\n\n## Overview\n\nThe extension adds a focus mode toggle for Chrome's Extensions and Chrome Web Store documentation. When activated, it hides navigation elements and other distractions, centering the article content for easier reading.\n\n## Implementation Notes\n\nThe extension uses the following Chrome APIs:\n\n- `chrome.scripting.insertCSS()` - Injects the focus mode stylesheet when enabled\n- `chrome.scripting.removeCSS()` - Removes the stylesheet when disabled\n- `chrome.action` - Displays an \"ON\"/\"OFF\" badge indicating the current state\n- `activeTab` permission - Allows the extension to modify only the current tab\n\nThe focus mode can be toggled by:\n\n- Clicking the extension icon\n- Using the keyboard shortcut (Ctrl+B on Windows/Linux, Command+B on Mac)\n\nThe toggle state is maintained per-tab, allowing different tabs to have different focus mode states.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Navigate to https://developer.chrome.com/docs/extensions/ or https://developer.chrome.com/docs/webstore/.\n4. Click the extension icon or press Ctrl+B (Command+B on Mac) to toggle focus mode.\n"
  },
  {
    "path": "functional-samples/tutorial.focus-mode/background.js",
    "content": "// Copyright 2022 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.runtime.onInstalled.addListener(() => {\n  chrome.action.setBadgeText({\n    text: 'OFF'\n  });\n});\n\nconst extensions = 'https://developer.chrome.com/docs/extensions';\nconst webstore = 'https://developer.chrome.com/docs/webstore';\n\n// When the user clicks on the extension action\nchrome.action.onClicked.addListener(async (tab) => {\n  if (tab.url.startsWith(extensions) || tab.url.startsWith(webstore)) {\n    // We retrieve the action badge to check if the extension is 'ON' or 'OFF'\n    const prevState = await chrome.action.getBadgeText({ tabId: tab.id });\n    // Next state will always be the opposite\n    const nextState = prevState === 'ON' ? 'OFF' : 'ON';\n\n    // Set the action badge to the next state\n    await chrome.action.setBadgeText({\n      tabId: tab.id,\n      text: nextState\n    });\n\n    if (nextState === 'ON') {\n      // Insert the CSS file when the user turns the extension on\n      await chrome.scripting.insertCSS({\n        files: ['focus-mode.css'],\n        target: { tabId: tab.id }\n      });\n    } else if (nextState === 'OFF') {\n      // Remove the CSS file when the user turns the extension off\n      await chrome.scripting.removeCSS({\n        files: ['focus-mode.css'],\n        target: { tabId: tab.id }\n      });\n    }\n  }\n});\n"
  },
  {
    "path": "functional-samples/tutorial.focus-mode/focus-mode.css",
    "content": "/* \nCopyright 2022 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n* {\n  display: none !important;\n}\n\nhtml,\nbody,\n*:has(article),\narticle,\narticle * {\n  display: revert !important;\n}\n\n[role='navigation'] {\n  display: none !important;\n}\n\narticle {\n  margin: auto;\n  max-width: 700px;\n}\n"
  },
  {
    "path": "functional-samples/tutorial.focus-mode/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Focus Mode\",\n  \"description\": \"Enable focus mode on Chrome's official Extensions and Chrome Web Store documentation.\",\n  \"version\": \"1.0\",\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"32\": \"images/icon-32.png\",\n    \"48\": \"images/icon-48.png\",\n    \"128\": \"images/icon-128.png\"\n  },\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"action\": {\n    \"default_icon\": {\n      \"16\": \"images/icon-16.png\",\n      \"32\": \"images/icon-32.png\",\n      \"48\": \"images/icon-48.png\",\n      \"128\": \"images/icon-128.png\"\n    }\n  },\n  \"permissions\": [\"scripting\", \"activeTab\"],\n  \"commands\": {\n    \"_execute_action\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+B\",\n        \"mac\": \"Command+B\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "functional-samples/tutorial.focus-mode-debugging/README.md",
    "content": "# Oliver Focus Mode\n\nExtension used in the [Debugging Chrome extensions](https://www.youtube.com/watch?v=Ta-YTDhiBIQ) DevTools Tips video. This extension simplifies the styling of the extensions and Chrome Web Store documentation pages so that they are easier to read when the action icon is clicked.\n\nThis extension is based on the [Focus Mode](/functional-samples/tutorial.focus-mode/) extension.\n\n**Note:** `background.js` and `focus-mode.js` are intentionally broken. Try to fix them, and compare your fixes with the code in the `fixed` folder.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Visit a page in the Extensions or Chrome Web Store sections on developer.chrome.com, e.g https://developer.chrome.com/docs/extensions/mv3/getstarted/tut-focus-mode/.\n4. Click the extension icon to toggle focus mode.\n"
  },
  {
    "path": "functional-samples/tutorial.focus-mode-debugging/background.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.runtime.onInstalled.addListener(() => {\n  chrome.action.setBadgeText({\n    text: 'OFF'\n  });\n});\n\nconst extensions = 'https://developer.chrome.com/docs/extensions';\nconst webstore = 'https://developer.chrome.com/docs/webstore';\n\n// When the user clicks on the extension action\nchrome.action.onClicked.addListener(async (tab) => {\n  if (tab.url?.startsWith(extensions) || tab.url?.startsWith(webstore)) {\n    // We retrieve the action badge to check if the extension is 'ON' or 'OFF'\n    const prevState = await chrome.action.getBadgeText({ tabId: tab.id });\n    // Next state will always be the opposite\n    const nextState = prevState === 'ON' ? 'OFF' : 'ON';\n\n    // Set the action badge to the next state\n    await chrome.action.setBadgeText({\n      tabId: tab.id,\n      text: nextState\n    });\n\n    if (nextState === 'ON') {\n      chrome.tabs.sendMessage(tab.id, { data: 'focus-on' });\n    } else if (nextState === 'OFF') {\n      chrome.tabs.sendMessage(tab.id, { data: 'focus-off' });\n    }\n  }\n});\n"
  },
  {
    "path": "functional-samples/tutorial.focus-mode-debugging/fixed/background.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.runtime.onInstalled.addListener(() => {\n  chrome.action.setBadgeText({\n    text: 'OFF'\n  });\n});\n\nconst extensions = 'https://developer.chrome.com/docs/extensions';\nconst webstore = 'https://developer.chrome.com/docs/webstore';\n\n// When the user clicks on the extension action\nchrome.action.onClicked.addListener(async (tab) => {\n  if (tab.url?.startsWith(extensions) || tab.url?.startsWith(webstore)) {\n    // We retrieve the action badge to check if the extension is 'ON' or 'OFF'\n    const prevState = await chrome.action.getBadgeText({ tabId: tab.id });\n    // Next state will always be the opposite\n    const nextState = prevState === 'ON' ? 'OFF' : 'ON';\n\n    // Set the action badge to the next state\n    await chrome.action.setBadgeText({\n      tabId: tab.id,\n      text: nextState\n    });\n\n    if (nextState === 'ON') {\n      chrome.tabs.sendMessage(tab.id, { data: 'focus-on' });\n    } else if (nextState === 'OFF') {\n      chrome.tabs.sendMessage(tab.id, { data: 'focus-off' });\n    }\n  }\n});\n"
  },
  {
    "path": "functional-samples/tutorial.focus-mode-debugging/fixed/focus-mode.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.runtime.onMessage.addListener((msg) => {\n  switch (msg.data) {\n    case 'focus-on':\n      document.body.setAttribute('data-focus-mode', 'on');\n      break;\n    case 'focus-off':\n      document.body.removeAttribute('data-focus-mode');\n      break;\n  }\n});\n"
  },
  {
    "path": "functional-samples/tutorial.focus-mode-debugging/focus-mode.css",
    "content": "/* \nCopyright 2023 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n* {\n  display: none !important;\n}\n\nhtml,\nbody,\n*:has(article),\narticle,\narticle * {\n  display: revert !important;\n}\n\n[role='navigation'] {\n  display: none !important;\n}\n\narticle {\n  margin: auto;\n  max-width: 700px;\n}\n"
  },
  {
    "path": "functional-samples/tutorial.focus-mode-debugging/focus-mode.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nchrome.runtime.onMessage.addListener((msg) => {\n  switch (msg) {\n    case 'focus-on':\n      document.body.setAttribute('data-focus-mode', 'on');\n      break;\n    case 'focus-off':\n      document.body.removeAttribute('data-focus-mode');\n      break;\n  }\n});\n"
  },
  {
    "path": "functional-samples/tutorial.focus-mode-debugging/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Oliver Focus Mode\",\n  \"description\": \"Example extension from DevTools Tips video.\",\n  \"version\": \"1.0\",\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"32\": \"images/icon-32.png\",\n    \"48\": \"images/icon-48.png\",\n    \"128\": \"images/icon-128.png\"\n  },\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"action\": {\n    \"default_icon\": {\n      \"16\": \"images/icon-16.png\",\n      \"32\": \"images/icon-32.png\",\n      \"48\": \"images/icon-48.png\",\n      \"128\": \"images/icon-128.png\"\n    }\n  },\n  \"permissions\": [],\n  \"host_permissions\": [\"https://developer.chrome.com/*\"],\n  \"commands\": {\n    \"_execute_action\": {\n      \"suggested_key\": {\n        \"default\": \"Ctrl+B\",\n        \"mac\": \"Command+B\"\n      }\n    }\n  },\n  \"content_scripts\": [\n    {\n      \"js\": [\"focus-mode.js\"],\n      \"css\": [\"focus-mode.css\"],\n      \"matches\": [\"https://developer.chrome.com/*\"]\n    }\n  ]\n}\n"
  },
  {
    "path": "functional-samples/tutorial.getting-started/README.md",
    "content": "# Getting Started With Google Chrome Extensions\n\nThis is an extension used in the [Debug extensions][1] tutorial. It changes the HTML body background color of the active tab.\nThe purpose of this extension is to demonstrate how to create a simple Chrome Extension that uses the `default_popup`, `options_page` and `service_worker` manifest keys and `storage` and `tabs` APIs.\n\n ## Running This Extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension][2].\n3. Go to https://developer.chrome.com/docs/extensions/get-started/tutorial/debug or any web page.\n4. Click the extension icon in the Chrome toolbar, then click the three dots next to the \"Getting Started Example\" extension and select \"Options\".\n5. On the Options page, choose a color.\n6. Afterward, click the extension icon again, and the page's background color will change when you click the button in the extension popup.\n \n[1]: https://developer.chrome.com/docs/extensions/get-started/tutorial/debug\n[2]: https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked"
  },
  {
    "path": "functional-samples/tutorial.getting-started/background.js",
    "content": "const color = '#3aa757';\n\nchrome.runtime.onInstalled.addListener(() => {\n  chrome.storage.sync.set({ color });\n  console.log('Default background color set to %cgreen', `color: ${color}`);\n});\n"
  },
  {
    "path": "functional-samples/tutorial.getting-started/button.css",
    "content": "button {\n  height: 30px;\n  width: 30px;\n  outline: none;\n  margin: 10px;\n  border: none;\n  border-radius: 2px;\n}\n\nbutton.current {\n  box-shadow: 0 0 0 2px white, 0 0 0 4px black;\n}\n"
  },
  {
    "path": "functional-samples/tutorial.getting-started/manifest.json",
    "content": "{\n  \"name\": \"Getting Started Example\",\n  \"description\": \"Build an Extension!\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"background.js\"\n  },\n  \"permissions\": [\"storage\", \"activeTab\", \"scripting\"],\n  \"action\": {\n    \"default_popup\": \"popup.html\",\n    \"default_icon\": {\n      \"16\": \"/images/get_started16.png\",\n      \"32\": \"/images/get_started32.png\",\n      \"48\": \"/images/get_started48.png\",\n      \"128\": \"/images/get_started128.png\"\n    }\n  },\n  \"icons\": {\n    \"16\": \"/images/get_started16.png\",\n    \"32\": \"/images/get_started32.png\",\n    \"48\": \"/images/get_started48.png\",\n    \"128\": \"/images/get_started128.png\"\n  },\n  \"options_page\": \"options.html\"\n}\n"
  },
  {
    "path": "functional-samples/tutorial.getting-started/options.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <link rel=\"stylesheet\" href=\"button.css\" />\n  </head>\n  <body>\n    <div id=\"buttonDiv\"></div>\n    <div>\n      <p>Choose a different background color!</p>\n    </div>\n    <script src=\"options.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/tutorial.getting-started/options.js",
    "content": "const page = document.getElementById('buttonDiv');\nconst selectedClassName = 'current';\nconst presetButtonColors = ['#3aa757', '#e8453c', '#f9bb2d', '#4688f1'];\n\n// Reacts to a button click by marking the selected button and saving\n// the selection\nfunction handleButtonClick(event) {\n  // Remove styling from the previously selected color\n  const current = event.target.parentElement.querySelector(\n    `.${selectedClassName}`\n  );\n  if (current && current !== event.target) {\n    current.classList.remove(selectedClassName);\n  }\n\n  // Mark the button as selected\n  const color = event.target.dataset.color;\n  event.target.classList.add(selectedClassName);\n  chrome.storage.sync.set({ color });\n}\n\n// Add a button to the page for each supplied color\nfunction constructOptions(buttonColors) {\n  chrome.storage.sync.get('color', (data) => {\n    const currentColor = data.color;\n\n    // For each color we were provided…\n    for (const buttonColor of buttonColors) {\n      // …create a button with that color…\n      const button = document.createElement('button');\n      button.dataset.color = buttonColor;\n      button.style.backgroundColor = buttonColor;\n\n      // …mark the currently selected color…\n      if (buttonColor === currentColor) {\n        button.classList.add(selectedClassName);\n      }\n\n      // …and register a listener for when that button is clicked\n      button.addEventListener('click', handleButtonClick);\n      page.appendChild(button);\n    }\n  });\n}\n\n// Initialize the page by constructing the color options\nconstructOptions(presetButtonColors);\n"
  },
  {
    "path": "functional-samples/tutorial.getting-started/popup.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <link rel=\"stylesheet\" href=\"button.css\" />\n  </head>\n  <body>\n    <button id=\"changeColor\"></button>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/tutorial.getting-started/popup.js",
    "content": "// Initialize button with users' preferred color\nconst changeColor = document.getElementById('changeColor');\n\nchrome.storage.sync.get('color', ({ color }) => {\n  changeColor.style.backgroundColor = color;\n});\n\n// When the button is clicked, inject setPageBackgroundColor into current page\nchangeColor.addEventListener('click', async () => {\n  const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });\n\n  chrome.scripting.executeScript({\n    target: { tabId: tab.id },\n    func: setPageBackgroundColor\n  });\n});\n\n// The body of this function will be executed as a content script inside the\n// current page\nfunction setPageBackgroundColor() {\n  chrome.storage.sync.get('color', ({ color }) => {\n    document.body.style.backgroundColor = color;\n  });\n}\n"
  },
  {
    "path": "functional-samples/tutorial.google-analytics/README.md",
    "content": "# Google Analytics 4 example\n\nThis example demonstrates how to track extension events in Google Analytics 4 using the Measurement Protocol.\n\n## Running this extension\n\n1. Clone this repository.\n2. Get your `api_secret` and the `measurement_id` as described in the [Measurement Protocol documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4). Add these in [scripts/google-analytics.js](scripts/google-analytics.js):\n   ```\n   const MEASUREMENT_ID = '<measurement_id>';\n   const API_SECRET = '<api_secret>';\n   ```\n3. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n4. Click the extension icon to open the extension popup and click the button to generate a few analytics events.\n   <img src=\"https://github-production-user-asset-6210df.s3.amazonaws.com/380472/240995103-87cb61a3-d3f9-44d6-9dfa-0e3bf0c11a1e.png\" alt=\"Extension popup\" width=\"200\"/>\n5. Check out the [real-time report](https://support.google.com/analytics/answer/1638635) to see how the events surface in Google Analytics.\n\n<img src=\"../../.repo/images/google-analytics-events.png\" alt=\"Google Analytics real-time report\" width=400>\n"
  },
  {
    "path": "functional-samples/tutorial.google-analytics/manifest.json",
    "content": "{\n  \"name\": \"Google Analytics Demo\",\n  \"description\": \"How to use Google Analytics 4 in your extension.\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"action\": {\n    \"default_popup\": \"popup/popup.html\"\n  },\n  \"permissions\": [\"storage\"],\n  \"background\": {\n    \"service_worker\": \"service-worker.js\",\n    \"type\": \"module\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/tutorial.google-analytics/popup/popup.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Analytics Demo Popup</title>\n    <script src=\"./popup.js\" type=\"module\"></script>\n  </head>\n  <body>\n    <h1>Analytics Demo</h1>\n    <p><button id=\"myButton\">Click to fire event</button></p>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/tutorial.google-analytics/popup/popup.js",
    "content": "import Analytics from '../scripts/google-analytics.js';\n\n// Fire a page view event on load\nwindow.addEventListener('load', () => {\n  Analytics.firePageViewEvent(document.title, document.location.href);\n});\n\n// Listen globally for all button events\ndocument.addEventListener('click', (event) => {\n  if (event.target instanceof HTMLButtonElement) {\n    Analytics.fireEvent('click_button', { id: event.target.id });\n  }\n});\n"
  },
  {
    "path": "functional-samples/tutorial.google-analytics/scripts/google-analytics.js",
    "content": "const GA_ENDPOINT = 'https://www.google-analytics.com/mp/collect';\nconst GA_DEBUG_ENDPOINT = 'https://www.google-analytics.com/debug/mp/collect';\n\n// Get via https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#recommended_parameters_for_reports\nconst MEASUREMENT_ID = '<measurement_id>';\nconst API_SECRET = '<api_secret>';\nconst DEFAULT_ENGAGEMENT_TIME_MSEC = 100;\n\n// Duration of inactivity after which a new session is created\nconst SESSION_EXPIRATION_IN_MIN = 30;\n\nclass Analytics {\n  constructor(debug = false) {\n    this.debug = debug;\n  }\n\n  getRandomId() {\n    const digits = '123456789'.split('');\n    let result = '';\n\n    for (let i = 0; i < 10; i++) {\n      result += digits[Math.floor(Math.random() * 9)];\n    }\n\n    return result;\n  }\n\n  // Returns the client id, or creates a new one if one doesn't exist.\n  // Stores client id in local storage to keep the same client id as long as\n  // the extension is installed.\n  async getOrCreateClientId() {\n    let { clientId } = await chrome.storage.local.get('clientId');\n    if (!clientId) {\n      // Generate a unique client ID, the actual value is not relevant. We use\n      // the <number>.<number> format since this is typical for GA client IDs.\n      const unixTimestampSeconds = Math.floor(new Date().getTime() / 1000);\n      clientId = `${this.getRandomId()}.${unixTimestampSeconds}`;\n      await chrome.storage.local.set({ clientId });\n    }\n    return clientId;\n  }\n\n  // Returns the current session id, or creates a new one if one doesn't exist or\n  // the previous one has expired.\n  async getOrCreateSessionId() {\n    // Use storage.session because it is only in memory\n    let { sessionData } = await chrome.storage.session.get('sessionData');\n    const currentTimeInMs = Date.now();\n    // Check if session exists and is still valid\n    if (sessionData && sessionData.timestamp) {\n      // Calculate how long ago the session was last updated\n      const durationInMin = (currentTimeInMs - sessionData.timestamp) / 60000;\n      // Check if last update lays past the session expiration threshold\n      if (durationInMin > SESSION_EXPIRATION_IN_MIN) {\n        // Clear old session id to start a new session\n        sessionData = null;\n      } else {\n        // Update timestamp to keep session alive\n        sessionData.timestamp = currentTimeInMs;\n        await chrome.storage.session.set({ sessionData });\n      }\n    }\n    if (!sessionData) {\n      // Create and store a new session\n      sessionData = {\n        session_id: currentTimeInMs.toString(),\n        timestamp: currentTimeInMs.toString()\n      };\n      await chrome.storage.session.set({ sessionData });\n    }\n    return sessionData.session_id;\n  }\n\n  // Fires an event with optional params. Event names must only include letters and underscores.\n  async fireEvent(name, params = {}) {\n    // Configure session id and engagement time if not present, for more details see:\n    // https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#recommended_parameters_for_reports\n    if (!params.session_id) {\n      params.session_id = await this.getOrCreateSessionId();\n    }\n    if (!params.engagement_time_msec) {\n      params.engagement_time_msec = DEFAULT_ENGAGEMENT_TIME_MSEC;\n    }\n\n    try {\n      const response = await fetch(\n        `${\n          this.debug ? GA_DEBUG_ENDPOINT : GA_ENDPOINT\n        }?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`,\n        {\n          method: 'POST',\n          body: JSON.stringify({\n            client_id: await this.getOrCreateClientId(),\n            events: [\n              {\n                name,\n                params\n              }\n            ]\n          })\n        }\n      );\n      if (!this.debug) {\n        return;\n      }\n      console.log(await response.text());\n    } catch (e) {\n      console.error('Google Analytics request failed with an exception', e);\n    }\n  }\n\n  // Fire a page view event.\n  async firePageViewEvent(pageTitle, pageLocation, additionalParams = {}) {\n    return this.fireEvent('page_view', {\n      page_title: pageTitle,\n      page_location: pageLocation,\n      ...additionalParams\n    });\n  }\n\n  // Fire an error event.\n  async fireErrorEvent(error, additionalParams = {}) {\n    // Note: 'error' is a reserved event name and cannot be used\n    // see https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference?client_type=gtag#reserved_names\n    return this.fireEvent('extension_error', {\n      ...error,\n      ...additionalParams\n    });\n  }\n}\n\nexport default new Analytics();\n"
  },
  {
    "path": "functional-samples/tutorial.google-analytics/service-worker.js",
    "content": "import Analytics from './scripts/google-analytics.js';\n\naddEventListener('unhandledrejection', async (event) => {\n  Analytics.fireErrorEvent(event.reason);\n});\n\nchrome.runtime.onInstalled.addListener(() => {\n  Analytics.fireEvent('install');\n});\n\n// Throw an exception after a timeout to trigger an exception analytics event\nsetTimeout(throwAnException, 2000);\n\nasync function throwAnException() {\n  throw new Error(\"👋 I'm an error\");\n}\n"
  },
  {
    "path": "functional-samples/tutorial.hello-world/README.md",
    "content": "# Getting Started With Google Chrome Extensions (Hello World)\n\nThis example demonstrates how to create a simple \"Hello World\" Chrome Extension.\nFor more details, visit the [official tutorial](https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world).\n\n## Running This Extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Click the extension icon in the Chrome toolbar, then select the \"Hello Extensions\" extension. A popup will appear displaying the text \"Hello Extensions\"."
  },
  {
    "path": "functional-samples/tutorial.hello-world/hello.html",
    "content": "<html>\n  <body>\n    <h1>Hello Extensions</h1>\n    <script src=\"popup.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/tutorial.hello-world/manifest.json",
    "content": "{\n  \"name\": \"Hello Extensions\",\n  \"description\": \"Base Level Extension\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"action\": {\n    \"default_popup\": \"hello.html\",\n    \"default_icon\": \"hello_extensions.png\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/tutorial.hello-world/popup.js",
    "content": "console.log('This is a popup!');\n"
  },
  {
    "path": "functional-samples/tutorial.mole-game/README.md",
    "content": "# Mole Game\n\nThis mole game is based on a YouTube tutorial in our Chrome Extensions series. Watch it [here](https://goo.gle/Chrome-Ext).\n\n<img src=\"mole-game.png\" width=500>\n\n## Overview\n\nIn the sample, moles periodically appear from pipes in the browser toolbar. You score points by clicking the icon before the mole disappears.\n\nIf enabled, a browser tab is closed if you miss one of the moles.\n\n## Implementation Notes\n\nEach icon in the browser toolbar is a seperate extension. The extensions communicate using the `chrome.runtime.sendMessage` API and the `chrome.runtime.onMessageExternal` event.\n\nTo discover mole extensions, the controller extension uses the `chrome.management` API.\n\nBy default, the tab closing behavior is disabled. You can enable this by commenting out the line in `mole/service-worker.js`.\n\n## Running this extension\n\n1. Clone this repository.\n1. Make several copies of the `mole` directory.\n1. Load the `controller` directory and all mole directories in Chrome as [unpacked extensions](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n1. Click the puzzle icon in the browser toolbar, and pin each extension. This makes them visible even if the extensions menu is closed.\n1. Wait for a mole to appear!\n"
  },
  {
    "path": "functional-samples/tutorial.mole-game/controller/manifest.json",
    "content": "{\n  \"name\": \"mole controller\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"permissions\": [\"management\", \"alarms\"],\n  \"action\": {}\n}\n"
  },
  {
    "path": "functional-samples/tutorial.mole-game/controller/service-worker.js",
    "content": "chrome.runtime.onInstalled.addListener(() => {\n  // Register an alarm used to periodically wake up the extension to spawn a\n  // new mole.\n  chrome.alarms.create({ periodInMinutes: (1 / 60) * 3 });\n});\n\nchrome.alarms.onAlarm.addListener(async () => {\n  const extensions = await chrome.management.getAll();\n  const moles = extensions.filter((e) => e.name === 'mole');\n\n  const randomIndex = Math.floor(Math.random() * moles.length);\n\n  chrome.runtime.sendMessage(moles[randomIndex].id, { id: chrome.runtime.id });\n});\n\nlet counter = 0;\n\nchrome.runtime.onMessageExternal.addListener(() => {\n  counter++;\n  chrome.action.setBadgeText({ text: `${counter}` });\n});\n"
  },
  {
    "path": "functional-samples/tutorial.mole-game/mole/manifest.json",
    "content": "{\n  \"name\": \"mole\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"background\": {\n    \"service_worker\": \"service-worker.js\"\n  },\n  \"action\": {\n    \"default_icon\": \"icon-empty.png\"\n  },\n  \"permissions\": [\"management\", \"tabs\"]\n}\n"
  },
  {
    "path": "functional-samples/tutorial.mole-game/mole/service-worker.js",
    "content": "let failTimeout;\nlet moleShowing = false;\nlet controllerId;\n\nchrome.action.onClicked.addListener(() => {\n  if (!moleShowing) return;\n\n  chrome.runtime.sendMessage(controllerId, 'success');\n  hideMole();\n\n  failTimeout && clearTimeout(failTimeout);\n  failTimeout = undefined;\n});\n\nfunction showMole() {\n  chrome.action.setIcon({ path: 'icon-mole.png' });\n  moleShowing = true;\n}\n\nfunction hideMole() {\n  chrome.action.setIcon({ path: 'icon-empty.png' });\n  moleShowing = false;\n}\n\nchrome.runtime.onMessageExternal.addListener((msg) => {\n  controllerId = msg.id;\n  showMole();\n  failTimeout = setTimeout(async () => {\n    hideMole();\n    const tabs = await chrome.tabs.query({});\n\n    if (tabs.length > 0) {\n      // const tabToClose = Math.floor(Math.random() * tabs.length);\n      // chrome.tabs.remove(tabs[tabToClose].id);\n    }\n  }, 2000);\n});\n"
  },
  {
    "path": "functional-samples/tutorial.open-api-reference/README.md",
    "content": "# Open Extension API Reference\n\nThis example demonstrates how to use the [Omnibox API](https://developer.chrome.com/docs/extensions/reference/api/omnibox) to quickly navigate to Chrome extension API reference pages directly from the address bar.\n\n## Overview\n\nThe extension registers the keyword \"api\" in Chrome's omnibox. When users type \"api\" followed by a space, they can search for any Chrome extension API and navigate directly to its documentation page.\n\n## Implementation Notes\n\nThe extension uses several Chrome APIs:\n\n- `chrome.omnibox` - Registers the \"api\" keyword and handles input/selection events\n- `chrome.storage.local` - Stores recent search history to provide personalized suggestions\n- `chrome.alarms` - Used for periodic tip fetching from an external service\n- Content script - Runs on the API reference pages\n\nWhen the user types in the omnibox:\n\n1. `onInputChanged` provides API suggestions based on user input and search history\n2. `onInputEntered` opens the selected API's reference page in a new tab\n3. The most recent searches (up to 4) are saved for future suggestions\n\nThe service worker is organized into modules:\n\n- `sw-omnibox.js` - Handles omnibox events and navigation\n- `sw-suggestions.js` - Generates API suggestions\n- `sw-tips.js` - Fetches extension development tips\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Type \"api\" in the address bar and press Space or Tab.\n4. Start typing an API name (e.g., \"tabs\", \"storage\", \"scripting\").\n5. Select a suggestion or press Enter to open the API reference page.\n"
  },
  {
    "path": "functional-samples/tutorial.open-api-reference/api-list.js",
    "content": "export default [\n  {\n    content: 'commands',\n    description:\n      'Use the <match>Commands API</match> to add a keyboard shortcuts.'\n  },\n  {\n    content: 'contextmenus',\n    description:\n      \"Use the <match>ContextMenus API</match> to add a custom item to Chrome's context menu.\"\n  },\n  {\n    content: 'declarativeNetRequest',\n    description:\n      'Use the <match>DeclarativeNetRequest API</match> to block or modify network requests.'\n  },\n  {\n    content: 'downloads',\n    description:\n      'Use the <match>Downloads API</match> to programmatically manipulate downloads.'\n  },\n  {\n    content: 'i18n',\n    description: 'Use the <match>i18n API</match> to localize your extension'\n  },\n  {\n    content: 'identity',\n    description:\n      'Use the <match>Identity API</match> to get OAuth2 access tokens.'\n  },\n  {\n    content: 'notifications',\n    description:\n      'Use the <match>Notifications API</match> show notifications to users in the system tray.'\n  },\n  {\n    content: 'offscreen',\n    description:\n      'Use the <match>Offscreen API</match> to create and manage offscreen documents.'\n  },\n  {\n    content: 'omnibox',\n    description:\n      \"Use the <match>Omnibox API</match> to register a keyword with Chrome's address bar.\"\n  },\n  {\n    content: 'permissions',\n    description:\n      'Use the <match>Permissions API</match> to request optional permissions at run time.'\n  },\n  {\n    content: 'runtime',\n    description:\n      'Use the <match>Runtime API</match> pass messages, manage extension lifecycle, and access other helper utils.'\n  },\n  {\n    content: 'scripting',\n    description:\n      'Use the <match>Scripting API</match> to execute scripts in different contexts.'\n  },\n  {\n    content: 'storage',\n    description:\n      'Use the <match>Storage API</match> to store, retrieve, and track changes to user data.'\n  },\n  {\n    content: 'tabs',\n    description:\n      'Use the <match>Tabs API</match> to create, update and manipulate tabs.'\n  },\n  {\n    content: 'topSites',\n    description:\n      'Use the <match>TopSites API</match> to access the most visited sites that are displayed on the new tab page.'\n  },\n  {\n    content: 'webNavigation',\n    description:\n      'Use the <match>WebNavigation API</match> to receive notifications about the status of navigation requests in-flight.'\n  }\n];\n"
  },
  {
    "path": "functional-samples/tutorial.open-api-reference/content.js",
    "content": "// Popover API https://chromestatus.com/feature/5463833265045504\n\n(async () => {\n  const nav = document.querySelector('.navigation-rail__links');\n\n  const { tip } = await chrome.runtime.sendMessage({ greeting: 'tip' });\n\n  const tipWidget = createDomElement(`\n    <button class=\"navigation-rail__link\" popovertarget=\"tip-popover\" popovertargetaction=\"show\" style=\"padding: 0; border: none; background: none;>\n      <div class=\"navigation-rail__icon\">\n        <svg class=\"icon\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\"> \n        <path d='M15 16H9M14.5 9C14.5 7.61929 13.3807 6.5 12 6.5M6 9C6 11.2208 7.2066 13.1599 9 14.1973V18.5C9 19.8807 10.1193 21 11.5 21H12.5C13.8807 21 15 19.8807 15 18.5V14.1973C16.7934 13.1599 18 11.2208 18 9C18 5.68629 15.3137 3 12 3C8.68629 3 6 5.68629 6 9Z'\"></path>\n        </svg>\n      </div>\n      <span>Tip</span> \n    </button>\n  `);\n\n  const popover = createDomElement(\n    `<div id='tip-popover' popover>${tip}</div>`\n  );\n\n  document.body.append(popover);\n  nav.append(tipWidget);\n})();\n\nfunction createDomElement(html) {\n  const dom = new DOMParser().parseFromString(html, 'text/html');\n  return dom.body.firstElementChild;\n}\n"
  },
  {
    "path": "functional-samples/tutorial.open-api-reference/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Open extension API reference\",\n  \"version\": \"1.0.0\",\n  \"icons\": {\n    \"16\": \"icon-16.png\",\n    \"128\": \"icon-128.png\"\n  },\n  \"background\": {\n    \"service_worker\": \"service-worker.js\",\n    \"type\": \"module\"\n  },\n  \"minimum_chrome_version\": \"102\",\n  \"omnibox\": {\n    \"keyword\": \"api\"\n  },\n  \"permissions\": [\"alarms\", \"storage\"],\n  \"content_scripts\": [\n    {\n      \"matches\": [\"https://developer.chrome.com/docs/extensions/reference/*\"],\n      \"js\": [\"content.js\"]\n    }\n  ],\n  \"host_permissions\": [\"https://extension-tips.glitch.me/*\"]\n}\n"
  },
  {
    "path": "functional-samples/tutorial.open-api-reference/service-worker.js",
    "content": "import './sw-omnibox.js';\nimport './sw-tips.js';\n"
  },
  {
    "path": "functional-samples/tutorial.open-api-reference/sw-omnibox.js",
    "content": "import { getApiSuggestions } from './sw-suggestions.js';\n\nconsole.log('sw-omnibox.js');\n\n// Initialize default API suggestions\nchrome.runtime.onInstalled.addListener(({ reason }) => {\n  if (reason === 'install') {\n    chrome.storage.local.set({\n      apiSuggestions: ['tabs', 'storage', 'scripting']\n    });\n  }\n});\n\nconst URL_CHROME_EXTENSIONS_DOC =\n  'https://developer.chrome.com/docs/extensions/reference/';\nconst NUMBER_OF_PREVIOUS_SEARCHES = 4;\n\n// Displays the suggestions after user starts typing\nchrome.omnibox.onInputChanged.addListener(async (input, suggest) => {\n  const { description, suggestions } = await getApiSuggestions(input);\n  await chrome.omnibox.setDefaultSuggestion({ description });\n  suggest(suggestions);\n});\n\n// Opens the reference page of the chosen API\nchrome.omnibox.onInputEntered.addListener((input) => {\n  chrome.tabs.create({ url: URL_CHROME_EXTENSIONS_DOC + input });\n  // Saves the latest keyword\n  updateHistory(input);\n});\n\nasync function updateHistory(input) {\n  const { apiSuggestions } = await chrome.storage.local.get('apiSuggestions');\n  apiSuggestions.unshift(input);\n  apiSuggestions.splice(NUMBER_OF_PREVIOUS_SEARCHES);\n  await chrome.storage.local.set({ apiSuggestions });\n}\n"
  },
  {
    "path": "functional-samples/tutorial.open-api-reference/sw-suggestions.js",
    "content": "import apiList from './api-list.js';\n\n/**\n * Returns a list of suggestions and a description for the default suggestion\n */\nexport async function getApiSuggestions(input) {\n  const suggestions = apiList.filter((api) => api.content.startsWith(input));\n\n  // return suggestions if any exist\n  if (suggestions.length) {\n    return {\n      description: 'Matching Chrome APIs',\n      suggestions: suggestions\n    };\n  }\n\n  // return past searches if no match was found\n  const { apiSuggestions } = await chrome.storage.local.get('apiSuggestions');\n  return {\n    description: 'No matches found. Choose from past searches',\n    suggestions: apiList.filter((item) => apiSuggestions.includes(item.content))\n  };\n}\n"
  },
  {
    "path": "functional-samples/tutorial.open-api-reference/sw-tips.js",
    "content": "console.log('sw-tips.js');\n\n// Fetch tip & save in storage\nconst updateTip = async () => {\n  const response = await fetch('https://extension-tips.glitch.me/tips.json');\n  const tips = await response.json();\n  const randomIndex = Math.floor(Math.random() * tips.length);\n  await chrome.storage.local.set({ tip: tips[randomIndex] });\n};\n\n// Create a daily alarm and retrieves the first tip when extension is installed.\nchrome.runtime.onInstalled.addListener(({ reason }) => {\n  if (reason === 'install') {\n    chrome.alarms.create({ delayInMinutes: 1, periodInMinutes: 1440 });\n    updateTip();\n  }\n});\n\n// Retrieve tip of the day\nchrome.alarms.onAlarm.addListener(updateTip);\n\n// Send tip to content script via messaging\nchrome.runtime.onMessage.addListener((message, sender, sendResponse) => {\n  if (message.greeting === 'tip') {\n    chrome.storage.local.get('tip').then(sendResponse);\n    return true;\n  }\n});\n"
  },
  {
    "path": "functional-samples/tutorial.puppeteer/README.md",
    "content": "# Tutorial: Testing Chrome Extensions with Puppeteer\n\n## Overview\n\nThis is the sample code for the [Testing Chrome Extensions with Puppeteer](https://developer.chrome.com/docs/extensions/mv3/tut_puppeteer-testing/) tutorial.\n\n## Running the tests\n\n1. Install [Node.JS](https://nodejs.org/).\n2. Run `npm install`.\n3. Run `npm start`.\n"
  },
  {
    "path": "functional-samples/tutorial.puppeteer/index.test.js",
    "content": "// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// eslint-disable-next-line no-undef\nconst puppeteer = require('puppeteer');\n\nconst EXTENSION_PATH = '../../api-samples/history/showHistory';\n\nlet browser;\nlet worker;\n\nbeforeEach(async () => {\n  browser = await puppeteer.launch({\n    // Set to 'new' to hide Chrome if running as part of an automated build.\n    headless: false,\n    pipe: true,\n    enableExtensions: [EXTENSION_PATH]\n  });\n\n  const workerTarget = await browser.waitForTarget(\n    // Assumes that there is only one service worker created by the extension and its URL ends with service-worker.js.\n    (target) =>\n      target.type() === 'service_worker' &&\n      target.url().endsWith('service-worker.js')\n  );\n\n  worker = await workerTarget.worker();\n});\n\nafterEach(async () => {\n  await browser.close();\n  browser = undefined;\n});\n\ntest('one history item is visible', async () => {\n  // Open a page to add a history item.\n  const page = await browser.newPage();\n  await page.goto('https://example.com');\n\n  // Open the extension popup.\n  await worker.evaluate('chrome.action.openPopup();');\n\n  const popupTarget = await browser.waitForTarget(\n    // Assumes that there is only one page with the URL ending with popup.html\n    // and that is the popup created by the extension.\n    (target) => target.type() === 'page' && target.url().endsWith('popup.html')\n  );\n\n  const popup = await popupTarget.asPage();\n\n  const list = await popup.$('ul');\n  const children = await list.$$('li');\n\n  expect(children.length).toBe(1);\n});\n"
  },
  {
    "path": "functional-samples/tutorial.puppeteer/package.json",
    "content": "{\n  \"name\": \"puppeteer-demo\",\n  \"version\": \"1.0\",\n  \"dependencies\": {\n    \"jest\": \"29.7.0\",\n    \"puppeteer\": \"24.35.0\"\n  },\n  \"scripts\": {\n    \"start\": \"jest .\"\n  },\n  \"devDependencies\": {\n    \"@jest/globals\": \"29.7.0\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/tutorial.quick-api-reference/README.md",
    "content": "# Tutorial: Handling events\n\nThis sample demonstrates how to handle events with service workers.\n\n## Overview\n\nThe extension built allows users to quickly navigate to Chrome API reference pages using the omnibox.\n\nThe events from the following APIs have been handled: `chrome.runtime`, `chrome.omnibox` and `chrome.alarms`.\n\nThe complete tutorial is available [here](https://developer.chrome.com/docs/extensions/get-started/tutorial/service-worker-events).\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Type \"api\" in the omnibox followed by tab or space and select a suggestion.\n4. Click on \"Tip\" button in the navigation bar.\n"
  },
  {
    "path": "functional-samples/tutorial.quick-api-reference/content.js",
    "content": "// Popover API https://chromestatus.com/feature/5463833265045504\n\n(async () => {\n  const nav = document.querySelector('.upper-tabs > nav');\n\n  const { tip } = await chrome.runtime.sendMessage({ greeting: 'tip' });\n\n  const tipWidget = createDomElement(`\n    <button type=\"button\" popovertarget=\"tip-popover\" popovertargetaction=\"show\" style=\"padding: 0 12px; height: 36px;\">\n      <span style=\"display: block; font: var(--devsite-link-font,500 14px/20px var(--devsite-primary-font-family));\">Tip</span>\n    </button>\n  `);\n\n  const popover = createDomElement(\n    `<div id='tip-popover' popover style=\"margin: auto;\">${tip}</div>`\n  );\n\n  document.body.append(popover);\n  nav.append(tipWidget);\n})();\n\nfunction createDomElement(html) {\n  const dom = new DOMParser().parseFromString(html, 'text/html');\n  return dom.body.firstElementChild;\n}\n"
  },
  {
    "path": "functional-samples/tutorial.quick-api-reference/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Quick API Reference\",\n  \"description\": \"Quick API can speed up the building of Chrome extensions.\",\n  \"version\": \"1.0.0\",\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"128\": \"images/icon-128.png\"\n  },\n  \"background\": {\n    \"service_worker\": \"service-worker.js\",\n    \"type\": \"module\"\n  },\n  \"minimum_chrome_version\": \"102\",\n  \"omnibox\": {\n    \"keyword\": \"api\"\n  },\n  \"permissions\": [\"alarms\", \"storage\"],\n  \"content_scripts\": [\n    {\n      \"matches\": [\"https://developer.chrome.com/docs/extensions/reference/*\"],\n      \"js\": [\"content.js\"]\n    }\n  ]\n}\n"
  },
  {
    "path": "functional-samples/tutorial.quick-api-reference/service-worker.js",
    "content": "import './sw-omnibox.js';\nimport './sw-tips.js';\n"
  },
  {
    "path": "functional-samples/tutorial.quick-api-reference/sw-omnibox.js",
    "content": "console.log('sw-omnibox.js');\n\n// Initialize default API suggestions\nchrome.runtime.onInstalled.addListener(({ reason }) => {\n  if (reason === 'install') {\n    chrome.storage.local.set({\n      apiSuggestions: ['tabs', 'storage', 'scripting']\n    });\n  }\n});\n\nconst URL_CHROME_EXTENSIONS_DOC =\n  'https://developer.chrome.com/docs/extensions/reference/';\nconst NUMBER_OF_PREVIOUS_SEARCHES = 4;\n\n// Display the suggestions after user starts typing\nchrome.omnibox.onInputChanged.addListener(async (input, suggest) => {\n  await chrome.omnibox.setDefaultSuggestion({\n    description: 'Enter a Chrome API or choose from past searches'\n  });\n  const { apiSuggestions } = await chrome.storage.local.get('apiSuggestions');\n  const suggestions = apiSuggestions.map((api) => {\n    return { content: api, description: `Open chrome.${api} API` };\n  });\n  suggest(suggestions);\n});\n\n// Open the reference page of the chosen API\nchrome.omnibox.onInputEntered.addListener((input) => {\n  chrome.tabs.create({ url: URL_CHROME_EXTENSIONS_DOC + input });\n  // Save the latest keyword\n  updateHistory(input);\n});\n\nasync function updateHistory(input) {\n  const { apiSuggestions } = await chrome.storage.local.get('apiSuggestions');\n  apiSuggestions.unshift(input);\n  apiSuggestions.splice(NUMBER_OF_PREVIOUS_SEARCHES);\n  return chrome.storage.local.set({ apiSuggestions });\n}\n"
  },
  {
    "path": "functional-samples/tutorial.quick-api-reference/sw-tips.js",
    "content": "console.log('sw-tips.js');\n\n// Fetch tip & save in storage\nconst updateTip = async () => {\n  const response = await fetch('https://chrome.dev/f/extension_tips/');\n  const tips = await response.json();\n  const randomIndex = Math.floor(Math.random() * tips.length);\n  return chrome.storage.local.set({ tip: tips[randomIndex] });\n};\n\nconst ALARM_NAME = 'tip';\n\n// Check if alarm exists to avoid resetting the timer.\n// The alarm might be removed when the browser session restarts.\nasync function createAlarm() {\n  const alarm = await chrome.alarms.get(ALARM_NAME);\n  if (typeof alarm === 'undefined') {\n    chrome.alarms.create(ALARM_NAME, {\n      delayInMinutes: 1,\n      periodInMinutes: 1440\n    });\n    updateTip();\n  }\n}\n\ncreateAlarm();\n\n// Retrieve tip of the day\nchrome.alarms.onAlarm.addListener(updateTip);\n\n// Send tip to content script via messaging\nchrome.runtime.onMessage.addListener((message, sender, sendResponse) => {\n  if (message.greeting === 'tip') {\n    chrome.storage.local.get('tip').then(sendResponse);\n    return true;\n  }\n});\n"
  },
  {
    "path": "functional-samples/tutorial.reading-time/README.md",
    "content": "# Tutorial: Run scripts on every page\n\nThis sample demonstrates how to run scripts on any Chrome extension and Chrome Web Store documentation page using an extension called _Reading Time_.\n\n## Overview\n\nThis sample demonstrates how developers can use content scripts which employ Document Object Models to read and change the content of a page. In this instance, the extension checks to find an article element, counts all the words inside of it, and then creates a paragraph that estimates the total reading time for that article.\n\nAs https://developer.chrome.com/ is a SPA (Single Page Application) it also includes an example of how to use `MutationObserver` to watch for changes to article content. Using `MutationObserver` can have a performance cost, so use them sparingly and only observe the most relevant changes.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Navigate to a Chrome extension or Chrome Webstore documentation page with an article element. [Here](https://developer.chrome.com/docs/webstore/publish) is an example of a webpage with an article element.\n4. The extension will provide an estimated reading time for the text in that article element. Here is the [link](https://developer.chrome.com/docs/extensions/get-started/tutorial/scripts-on-every-tab) for the full instructions.\n"
  },
  {
    "path": "functional-samples/tutorial.reading-time/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Reading time\",\n  \"version\": \"1.0\",\n  \"description\": \"Add the reading time to Chrome Extension documentation articles\",\n\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"32\": \"images/icon-32.png\",\n    \"48\": \"images/icon-48.png\",\n    \"128\": \"images/icon-128.png\"\n  },\n  \"content_scripts\": [\n    {\n      \"js\": [\"scripts/content.js\"],\n      \"matches\": [\n        \"https://developer.chrome.com/docs/extensions/*\",\n        \"https://developer.chrome.com/docs/webstore/*\"\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "functional-samples/tutorial.reading-time/scripts/content.js",
    "content": "// Copyright 2022 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nfunction renderReadingTime(article) {\n  // If we weren't provided an article, we don't need to render anything.\n  if (!article) {\n    return;\n  }\n\n  const text = article.textContent;\n  /**\n   * Regular expression to find all \"words\" in a string.\n   *\n   * Here, a \"word\" is a sequence of one or more non-whitespace characters in a row. We don't use the\n   * regular expression character class \"\\w\" to match against \"word characters\" because it only\n   * matches against the Latin alphabet. Instead, we match against any sequence of characters that\n   * *are not* a whitespace characters. See the below link for more information.\n   *\n   * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n   */\n  const wordMatchRegExp = /[^\\s]+/g;\n  const words = text.matchAll(wordMatchRegExp);\n  // matchAll returns an iterator, convert to array to get word count\n  const wordCount = [...words].length;\n  const readingTime = Math.round(wordCount / 200);\n  const badge = document.createElement('p');\n  // Use the same styling as the publish information in an article's header\n  badge.classList.add('color-secondary-text', 'type--caption');\n  badge.textContent = `⏱️ ${readingTime} min read`;\n\n  // Support for API reference docs\n  const heading = article.querySelector('h1');\n  // Support for article docs with date\n  const date = article.querySelector('time')?.parentNode;\n\n  // https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement\n  (date ?? heading).insertAdjacentElement('afterend', badge);\n}\n\nrenderReadingTime(document.querySelector('article'));\n\nconst observer = new MutationObserver((mutations) => {\n  for (const mutation of mutations) {\n    // If a new article was added.\n    for (const node of mutation.addedNodes) {\n      if (node instanceof Element && node.tagName === 'ARTICLE') {\n        // Render the reading time for this particular article.\n        renderReadingTime(node);\n      }\n    }\n  }\n});\n\n// https://developer.chrome.com/ is a SPA (Single Page Application) so can\n// update the address bar and render new content without reloading. Our content\n// script won't be reinjected when this happens, so we need to watch for\n// changes to the content.\nobserver.observe(document.querySelector('devsite-content'), {\n  childList: true\n});\n"
  },
  {
    "path": "functional-samples/tutorial.tabs-manager/README.md",
    "content": "# Tab Manager For Chrome Dev Docs\n\nThis Chrome extension helps you manage and group your tabs related to Google Chrome Developer documentation. It organizes tabs into a group titled \"DOCS\" for easier navigation and enhanced productivity.\n\nPurpose of this extension is to demonstrate [chrome.tabGroups](https://developer.chrome.com/docs/extensions/reference/api/tabGroups) API to interact with the browser's tab grouping system.\n\n ## Running This Extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Open these two URLs in separate tabs:  \n   - [https://developer.chrome.com/docs/extensions](https://developer.chrome.com/docs/extensions)  \n   - [https://developer.chrome.com/docs/extensions/reference/api](https://developer.chrome.com/docs/extensions/reference/api)\n4. Click the extension icon in the Chrome toolbar, then select the \"Tab Manager for Chrome Dev Docs\" extension. A popup will appear having title \"Google Dev Docs\" and button named \"Group Tabs\". Click on the button to group the two tabs.\n"
  },
  {
    "path": "functional-samples/tutorial.tabs-manager/manifest.json",
    "content": "{\n  \"manifest_version\": 3,\n  \"name\": \"Tab Manager for Chrome Dev Docs\",\n  \"version\": \"1.0\",\n  \"icons\": {\n    \"16\": \"images/icon-16.png\",\n    \"32\": \"images/icon-32.png\",\n    \"48\": \"images/icon-48.png\",\n    \"128\": \"images/icon-128.png\"\n  },\n  \"action\": {\n    \"default_popup\": \"popup.html\"\n  },\n  \"host_permissions\": [\"https://developer.chrome.com/*\"],\n  \"permissions\": [\"tabGroups\"]\n}\n"
  },
  {
    "path": "functional-samples/tutorial.tabs-manager/popup.css",
    "content": "/* \nCopyright 2022 Google LLC\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    https://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nbody {\n  width: 20rem;\n}\n\nul {\n  list-style-type: none;\n  padding-inline-start: 0;\n  margin: 1rem 0;\n}\n\nli {\n  padding: 0.25rem;\n}\nli:nth-child(odd) {\n  background: #80808030;\n}\nli:nth-child(even) {\n  background: #ffffff;\n}\n\nh3,\np {\n  margin: 0;\n}\n"
  },
  {
    "path": "functional-samples/tutorial.tabs-manager/popup.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <link rel=\"stylesheet\" href=\"./popup.css\" />\n  </head>\n  <body>\n    <template id=\"li_template\">\n      <li>\n        <a>\n          <h3 class=\"title\">Tab Title</h3>\n          <p class=\"pathname\">Tab Pathname</p>\n        </a>\n      </li>\n    </template>\n\n    <h1>Google Dev Docs</h1>\n    <button>Group Tabs</button>\n    <ul></ul>\n\n    <script src=\"./popup.js\" type=\"module\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/tutorial.tabs-manager/popup.js",
    "content": "// Copyright 2022 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nconst tabs = await chrome.tabs.query({\n  url: [\n    'https://developer.chrome.com/docs/webstore/*',\n    'https://developer.chrome.com/docs/extensions/*'\n  ]\n});\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator\nconst collator = new Intl.Collator();\ntabs.sort((a, b) => collator.compare(a.title, b.title));\n\nconst template = document.getElementById('li_template');\nconst elements = new Set();\nfor (const tab of tabs) {\n  const element = template.content.firstElementChild.cloneNode(true);\n\n  const title = tab.title.split('|')[0].trim();\n  const pathname = new URL(tab.url).pathname.slice('/docs'.length);\n\n  element.querySelector('.title').textContent = title;\n  element.querySelector('.pathname').textContent = pathname;\n  element.querySelector('a').addEventListener('click', async () => {\n    // need to focus window as well as the active tab\n    await chrome.tabs.update(tab.id, { active: true });\n    await chrome.windows.update(tab.windowId, { focused: true });\n  });\n\n  elements.add(element);\n}\ndocument.querySelector('ul').append(...elements);\n\nconst button = document.querySelector('button');\nbutton.addEventListener('click', async () => {\n  const tabIds = tabs.map(({ id }) => id);\n  if (tabIds.length) {\n    const group = await chrome.tabs.group({ tabIds });\n    await chrome.tabGroups.update(group, { title: 'DOCS' });\n  }\n});\n"
  },
  {
    "path": "functional-samples/tutorial.terminate-sw/README.md",
    "content": "# Testing service worker termination\n\n## Overview\n\n**Note:** The test extension is intentionally broken as part of a tutorial in\nour documentation. See [Test service worker termination with Puppeteer](https://developer.chrome.com/docs/extensions/how-to/test/test-serviceworker-termination-with-puppeteer).\n\nSample code to show how to terminate a service worker in Puppeteer or Selenium.\n\n## Running the tests\n\n1. Install [Node.JS](https://nodejs.org/).\n2. Change to the `puppeteer` or `selenium` directory.\n3. Run `npm install`.\n4. Run `npm start`.\n"
  },
  {
    "path": "functional-samples/tutorial.terminate-sw/puppeteer/.eslintrc",
    "content": "{\n  \"extends\": [\"../../../.eslintrc\"],\n  \"plugins\": [\"jest\"],\n  \"env\": {\n    \"jest/globals\": true\n  }\n}\n"
  },
  {
    "path": "functional-samples/tutorial.terminate-sw/puppeteer/index.test.js",
    "content": "/* eslint-disable jest/expect-expect */\n// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// eslint-disable-next-line no-undef\nconst puppeteer = require('puppeteer');\n\nconst EXTENSION_PATH = '../test-extension';\nconst EXTENSION_ID = 'gjgkofgpcmpfpggbgjgdfaaifcmoklbl';\n\nlet browser;\n\nbeforeEach(async () => {\n  browser = await puppeteer.launch({\n    // Set to 'new' to hide Chrome if running as part of an automated build.\n    headless: false,\n    pipe: true,\n    enableExtensions: [EXTENSION_PATH]\n  });\n});\n\nafterEach(async () => {\n  await browser.close();\n  browser = undefined;\n});\n\n/**\n * Stops the service worker associated with a given extension ID. This is done\n * by creating a new Chrome DevTools Protocol session, finding the target ID\n * associated with the worker and running the Target.closeTarget command.\n *\n * @param {Page} browser Browser instance\n * @param {string} extensionId Extension ID of worker to terminate\n */\nasync function stopServiceWorker(browser, extensionId) {\n  const host = `chrome-extension://${extensionId}`;\n\n  const target = await browser.waitForTarget((t) => {\n    return t.type() === 'service_worker' && t.url().startsWith(host);\n  });\n\n  const worker = await target.worker();\n  await worker.close();\n}\n\ntest('can message service worker when terminated', async () => {\n  const page = await browser.newPage();\n  await page.goto(`chrome-extension://${EXTENSION_ID}/page.html`);\n\n  // Message without terminating service worker\n  await page.click('button');\n  await page.waitForSelector('#response-0');\n\n  // Terminate service worker\n  await stopServiceWorker(browser, EXTENSION_ID);\n\n  // Try to send another message\n  await page.click('button');\n  await page.waitForSelector('#response-1');\n});\n"
  },
  {
    "path": "functional-samples/tutorial.terminate-sw/puppeteer/package.json",
    "content": "{\n  \"name\": \"puppeteer-demo\",\n  \"version\": \"1.0\",\n  \"dependencies\": {\n    \"jest\": \"29.7.0\",\n    \"puppeteer\": \"24.8.1\"\n  },\n  \"scripts\": {\n    \"start\": \"jest .\"\n  },\n  \"devDependencies\": {\n    \"@jest/globals\": \"29.7.0\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/tutorial.terminate-sw/selenium/.eslintrc",
    "content": "{\n  \"extends\": [\"../../../.eslintrc\"],\n  \"plugins\": [\"jest\"],\n  \"env\": {\n    \"jest/globals\": true\n  }\n}\n"
  },
  {
    "path": "functional-samples/tutorial.terminate-sw/selenium/index.test.js",
    "content": "/* eslint-disable jest/expect-expect */\n// Copyright 2023 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     https://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n// eslint-disable-next-line no-undef\nconst { Builder, Browser, By, until } = require('selenium-webdriver');\n// eslint-disable-next-line no-undef\nconst { Options } = require('selenium-webdriver/chrome');\n\nconst EXTENSION_PATH = '../test-extension';\nconst EXTENSION_ID = 'gjgkofgpcmpfpggbgjgdfaaifcmoklbl';\n\nlet driver;\nlet cdpConnection;\n\nbeforeEach(async () => {\n  driver = await new Builder()\n    .forBrowser(Browser.CHROME)\n    .setChromeOptions(\n      new Options().addArguments([\n        `--disable-extensions-except=${EXTENSION_PATH}`,\n        `--load-extension=${EXTENSION_PATH}`\n      ])\n    )\n    .build();\n\n  // Create this here, since there is one connection per driver and we want to\n  // avoid repeatedly recreating it.\n  cdpConnection = await driver.createCDPConnection('page');\n});\n\nafterEach(async () => {\n  await driver.quit();\n  driver = undefined;\n});\n\n/**\n * Stops the service worker associated with a given extension ID. This is done\n * by creating a new Chrome DevTools Protocol session, finding the target ID\n * associated with the worker and running the Target.closeTarget command.\n *\n * @param {Driver} driver Driver that CDP session can be started from\n * @param {string} extensionId Extension ID of worker to terminate\n */\nasync function stopServiceWorker(driver, extensionId) {\n  const host = `chrome-extension://${extensionId}`;\n\n  // Find the extension service worker\n  const response = await cdpConnection.send('Target.getTargets', {});\n  const worker = response.result.targetInfos.find(\n    (t) => t.type === 'service_worker' && t.url.startsWith(host)\n  );\n\n  if (!worker) {\n    throw new Error(`No worker found for ${host}`);\n  }\n\n  // Terminate the service worker\n  await cdpConnection.send('Target.closeTarget', {\n    targetId: worker.targetId\n  });\n}\n\ntest('can message service worker when terminated', async () => {\n  await driver.get(`chrome-extension://${EXTENSION_ID}/page.html`);\n\n  // Message without terminating service worker\n  await driver.wait(until.elementLocated(By.css('button'))).click();\n  await driver.wait(until.elementLocated(By.css('#response-0')));\n\n  // Terminate service worker\n  await stopServiceWorker(driver, EXTENSION_ID);\n\n  // Try to send another message\n  await driver.wait(until.elementLocated(By.css('button'))).click();\n  await driver.wait(until.elementLocated(By.css('#response-1')));\n});\n"
  },
  {
    "path": "functional-samples/tutorial.terminate-sw/selenium/package.json",
    "content": "{\n  \"name\": \"puppeteer-demo\",\n  \"version\": \"1.0\",\n  \"dependencies\": {\n    \"jest\": \"29.7.0\",\n    \"selenium-webdriver\": \"4.17.0\"\n  },\n  \"scripts\": {\n    \"start\": \"jest .\"\n  },\n  \"devDependencies\": {\n    \"@jest/globals\": \"29.7.0\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/tutorial.terminate-sw/test-extension/manifest.json",
    "content": "{\n  \"name\": \"Hello World\",\n  \"version\": \"0.1\",\n  \"key\": \"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr1Cssen3kE1Kzw8x2vhc0neVV3Im5HhQ28cl2zptYPZVLMkT4RuVAbSu8/CnlqyfYMoHSSUKgo/kaEOW+g9aoGjPyKYfmy5FJmIZnWfbKP+qLRcnX8XrgX6NM8XxAalzrq/a8DeaFTCtLyVEX+Xw5uzjJapXfaiFdwPhAV6TR0GPgB6pSvkcRiPTTcctqQ64/FSbNQutcVRA0bH8d8tnIDQZ9nm/9/4A0njq1Xujf/NnhldWjlKilQPLZh/2bXrThlWDLal3LJbMsvWolFbQWpGIPw4ti13bhBFp9A7jFUt89wBnwEPhViMEjatOJzx72karMqkAFEOfPiXsytrNYQIDAQAB\",\n  \"manifest_version\": 3,\n  \"description\": \"Basic Hello World Extension\",\n  \"background\": {\n    \"service_worker\": \"service-worker-broken.js\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/tutorial.terminate-sw/test-extension/page.html",
    "content": "<html>\n  <head>\n    <title>Test Page</title>\n  </head>\n  <body>\n    <button id=\"get-response\" type=\"button\">Get Response</button>\n    <script src=\"page.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "functional-samples/tutorial.terminate-sw/test-extension/page.js",
    "content": "const GET_RESPONSE_BUTTON = document.getElementById('get-response');\nlet counter = 0;\n\nGET_RESPONSE_BUTTON.addEventListener('click', async () => {\n  const response = await chrome.runtime.sendMessage('ping');\n\n  if (response) {\n    const element = document.createElement('p');\n    element.id = `response-${counter}`;\n    element.innerText = `Response ${counter}: ${response}`;\n    document.body.appendChild(element);\n\n    counter++;\n  }\n});\n"
  },
  {
    "path": "functional-samples/tutorial.terminate-sw/test-extension/service-worker-broken.js",
    "content": "let data;\n\nchrome.runtime.onInstalled.addListener(() => {\n  data = { version: chrome.runtime.getManifest().version };\n});\n\nchrome.runtime.onMessage.addListener((message, sender, sendResponse) => {\n  sendResponse(data.version);\n});\n"
  },
  {
    "path": "functional-samples/tutorial.terminate-sw/test-extension/service-worker-fixed.js",
    "content": "chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {\n  sendResponse(chrome.runtime.getManifest().version);\n});\n"
  },
  {
    "path": "functional-samples/tutorial.websockets/README.md",
    "content": "# Chrome extension WebSocket example\n\nThis example demonstrates how to use WebSockets in a MV3 Chrome Extension. Starting with Chrome version M116, WebSocket\nactivity will extend the service worker lifetime. In previous Chrome versions, the service worker will become inactive\nwhile waiting for messages and disconnect the WebSocket.\n\n## Running this extension\n\n1. Clone this repository.\n2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked).\n3. Pin the extension from the extension menu.\n4. Click the extension's action icon to start a web socket connection.\n5. Click the extension's action again to stop the web socket connection.\n6. Check the [service worker status](https://developer.chrome.com/docs/extensions/mv3/tut_debugging/#sw-status) to see when the service worker is active/inactive.\n"
  },
  {
    "path": "functional-samples/tutorial.websockets/manifest.json",
    "content": "{\n  \"name\": \"WebSocket Demo\",\n  \"description\": \"How to use WebSockets in your Chrome Extension.\",\n  \"version\": \"1.0\",\n  \"manifest_version\": 3,\n  \"minimum_chrome_version\": \"116\",\n  \"action\": {\n    \"default_icon\": \"icons/socket-inactive.png\"\n  },\n  \"background\": {\n    \"service_worker\": \"service-worker.js\",\n    \"type\": \"module\"\n  }\n}\n"
  },
  {
    "path": "functional-samples/tutorial.websockets/service-worker.js",
    "content": "const TEN_SECONDS_MS = 10 * 1000;\nlet webSocket = null;\n\n// Make sure the Glitch demo server is running\nfetch('https://chrome-extension-websockets.glitch.me/', { mode: 'no-cors' });\n\n// Toggle WebSocket connection on action button click\n// Send a message every 10 seconds, the ServiceWorker will\n// be kept alive as long as messages are being sent.\nchrome.action.onClicked.addListener(async () => {\n  if (webSocket) {\n    disconnect();\n  } else {\n    connect();\n    keepAlive();\n  }\n});\n\nfunction connect() {\n  webSocket = new WebSocket('wss://chrome-extension-websockets.glitch.me/ws');\n\n  webSocket.onopen = () => {\n    chrome.action.setIcon({ path: 'icons/socket-active.png' });\n  };\n\n  webSocket.onmessage = (event) => {\n    console.log(event.data);\n  };\n\n  webSocket.onclose = () => {\n    chrome.action.setIcon({ path: 'icons/socket-inactive.png' });\n    console.log('websocket connection closed');\n    webSocket = null;\n  };\n}\n\nfunction disconnect() {\n  if (webSocket) {\n    webSocket.close();\n  }\n}\n\nfunction keepAlive() {\n  const keepAliveIntervalId = setInterval(\n    () => {\n      if (webSocket) {\n        console.log('ping');\n        webSocket.send('ping');\n      } else {\n        clearInterval(keepAliveIntervalId);\n      }\n    },\n    // It's important to pick an interval that's shorter than 30s, to\n    // avoid that the service worker becomes inactive.\n    TEN_SECONDS_MS\n  );\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"chrome-extensions-samples\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"description\": \"Official samples for Chrome Extensions and the Chrome Apps platform.\",\n  \"scripts\": {\n    \"prettier\": \"npx prettier **/*.{md,html,json} -w\",\n    \"lint\": \"eslint **/*.js\",\n    \"lint:fix\": \"npm run lint -- --fix\",\n    \"prepare\": \"husky install\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/GoogleChrome/chrome-extensions-samples.git\"\n  },\n  \"keywords\": [],\n  \"author\": \"The Chrome Team\",\n  \"license\": \"Apache 2.0\",\n  \"bugs\": {\n    \"url\": \"https://github.com/GoogleChrome/chrome-extensions-samples/issues\"\n  },\n  \"homepage\": \"https://github.com/GoogleChrome/chrome-extensions-samples#readme\",\n  \"devDependencies\": {\n    \"@eslint/js\": \"9.19.0\",\n    \"chrome-types\": \"0.1.335\",\n    \"eslint\": \"9.19.0\",\n    \"eslint-config-prettier\": \"9.1.0\",\n    \"eslint-plugin-jest\": \"28.11.0\",\n    \"eslint-plugin-prettier\": \"5.4.1\",\n    \"globals\": \"15.14.0\",\n    \"husky\": \"9.1.6\",\n    \"lint-staged\": \"15.2.10\",\n    \"prettier\": \"3.3.3\"\n  },\n  \"lint-staged\": {\n    \"**/*.js\": [\n      \"npx eslint --fix\"\n    ],\n    \"**/*.{md,html,json}\": [\n      \"npx prettier --write\"\n    ]\n  }\n}\n"
  }
]